chore: v2.8.12 — clone queue and progress, session defaults, chat agents, drops as @ mentions

Whole tree from parallel sessions, plus the version bump:
- Clone: a queue with live progress (Add workspace and extra folders),
  clones run under nice/ionice so the machine stays responsive.
- Settings → AI tools → Session defaults: a new session's default
  permission mode / bypass per account.
- Chat lists the background subagents that have not reported back yet.
- A file pasted or dropped into a claude pane goes in as an @ mention.
- Changes panel: say why amend/undo is refused on a pushed commit.
- openapi.yaml regenerated (Artifacts, Host, resumeById).
This commit is contained in:
2026-10-19 17:19:41 +07:00
parent 1a6b550e89
commit 49f87c4da3
61 changed files with 2824 additions and 114 deletions
@@ -29,9 +29,9 @@ import { PetSettings } from "../settings/PetSettings";
import { Swatch, THEME_LABELS } from "../settings/AppearanceSettings";
import { markOnboarded, useOnboarding } from "../../lib/userPrefs";
import {
DEFAULT_MODES,
readDefaultMode,
readDefaultTool,
SAFE_MODES,
writeDefaultMode,
writeDefaultTool,
type DefaultMode,
@@ -310,7 +310,7 @@ function AgentStep() {
writeDefaultMode(m);
setMode(m);
}}
options={DEFAULT_MODES.map((m) => ({ value: m, label: t(`agent.modes.${m}`) }))}
options={SAFE_MODES.map((m) => ({ value: m, label: t(`agent.modes.${m}`) }))}
/>
</div>
<p className="text-xs text-fg-muted">{t("agent.permissionHint")}</p>
@@ -2,7 +2,7 @@
* @file Onboarding.test.tsx
* @description The first-run setup (docs/plans/onboarding): the account's
* preferences are loaded into localStorage on sign-in and every later change
* is sent back; the starting choices never hold bypass; the wizard shows only
* is sent back; the wizard never offers bypass (a Settings default may hold it); the wizard shows only
* for an account that is new to it, writes each pick like Settings does and
* ends in the tour; the tour follows the real UI step by step.
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
@@ -55,7 +55,7 @@ vi.mock("../../settings/PetSettings", () => ({
}));
import { __resetUserPrefs, hydrate, useOnboarding } from "../../../lib/userPrefs";
import { readDefaultMode, writeDefaultMode } from "../../../lib/sessionDefaults";
import { readDefaultMode, SAFE_MODES, writeDefaultMode } from "../../../lib/sessionDefaults";
import { OnboardingWizard } from "../OnboardingWizard";
import { OnboardingTour, startTour } from "../OnboardingTour";
import { __resetAiTools } from "../../../hooks/useAiTools";
@@ -98,10 +98,12 @@ describe("account preferences", () => {
}
});
it("never keeps bypass as the starting permission mode", () => {
it("keeps a bypass default from Settings, but the pet chat's safe read and the wizard never offer it", () => {
localStorage.setItem("agenthub.permissionMode", "bypassPermissions");
expect(readDefaultMode()).toBe("auto");
writeDefaultMode("bypassPermissions" as never);
expect(readDefaultMode()).toBe("bypassPermissions");
expect(readDefaultMode({ safe: true })).toBe("auto");
expect(SAFE_MODES).not.toContain("bypassPermissions");
writeDefaultMode("nonsense" as never);
expect(localStorage.getItem("agenthub.permissionMode")).toBe("bypassPermissions");
writeDefaultMode("plan");
expect(readDefaultMode()).toBe("plan");