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:
@@ -11,7 +11,7 @@
|
||||
* shell tab at once, like the tab bar's New terminal) and one Model chip (`ModelMenu`: the tool's own list or the
|
||||
* proxy's models, plus Effort); under it the quieter choices — AI Proxy
|
||||
* (Native or a profile), Permission (Claude's mode, Codex's sandbox/approval,
|
||||
* a catalog tool's bypass) and Local / New worktree — the workspace's Recents — the sessions it
|
||||
* a catalog tool's bypass — a YOLO chip for Codex) and Local / New worktree — the workspace's Recents — the sessions it
|
||||
* owns and has not archived (`?lane=&archived=0`, with each one's state dot,
|
||||
* **Show more** past the first page, and the sidebar row's Rename/Archive in
|
||||
* its right-click menu), then the archived ones folded with Unarchive; a live session opens its pane,
|
||||
@@ -20,7 +20,6 @@
|
||||
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
||||
*/
|
||||
|
||||
import { Checkbox } from "../Checkbox";
|
||||
import { isSubmitEnter } from "../../lib/keys";
|
||||
import { confirmDialog } from "../../lib/confirm";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
@@ -34,6 +33,7 @@ import {
|
||||
MoreHorizontal,
|
||||
ArrowUp,
|
||||
SquareTerminal,
|
||||
Zap,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
api,
|
||||
@@ -76,7 +76,7 @@ export {
|
||||
} from "./startSession";
|
||||
import { startInFreeTab } from "./startSession";
|
||||
import { WorkspaceContext } from "./WorkspaceContext";
|
||||
import { readDefaultMode } from "../../lib/sessionDefaults";
|
||||
import { readCodexDefaults, readDefaultMode } from "../../lib/sessionDefaults";
|
||||
|
||||
/** Recents' page size; Show more adds another. */
|
||||
const RECENT_PAGE = 30;
|
||||
@@ -165,12 +165,14 @@ function HomeBody({
|
||||
// Claude and Codex always take a model and an effort; a catalog tool a
|
||||
// model only when its file names the flag, an effort never.
|
||||
const hasModel = claude || codex || !!entry?.modelFlag;
|
||||
// The account's own default (first-run setup) — never bypass.
|
||||
// The account's own defaults (first-run setup, Settings → AI tools →
|
||||
// Session defaults); a pick here is for this session only.
|
||||
const [mode, setMode] = useState<PermissionMode>(readDefaultMode);
|
||||
const [sandbox, setSandbox] = useState<CodexSandbox>("workspace-write");
|
||||
const [approval, setApproval] = useState<CodexApproval>("on-request");
|
||||
// Per session, never remembered.
|
||||
const [sandbox, setSandbox] = useState<CodexSandbox>(() => readCodexDefaults().sandbox);
|
||||
const [approval, setApproval] = useState<CodexApproval>(() => readCodexDefaults().approval);
|
||||
// Off for every tool but Codex, which starts from the account's default.
|
||||
const [bypass, setBypass] = useState(false);
|
||||
useEffect(() => setBypass(codex && readCodexDefaults().bypass), [codex]);
|
||||
const canBypass = !claude && !!entry?.bypass;
|
||||
const [effort, setEffort] = useState<EffortLevel>("");
|
||||
const hasEffort = claude || codex;
|
||||
@@ -254,7 +256,7 @@ function HomeBody({
|
||||
}
|
||||
};
|
||||
|
||||
const text = promptWithImages(prompt, images);
|
||||
const text = promptWithImages(prompt, images, claude);
|
||||
const start = async () => {
|
||||
// Enter reaches here past the disabled button: the same guards again.
|
||||
// A ref, not only the state: two Enters in one tick both read `starting` false.
|
||||
@@ -607,15 +609,25 @@ function HomeBody({
|
||||
</div>
|
||||
)}
|
||||
{canBypass && (
|
||||
<span className="px-2">
|
||||
<Checkbox
|
||||
tone="danger"
|
||||
checked={bypass}
|
||||
onChange={setBypass}
|
||||
label={t("run:fields.bypass")}
|
||||
labelClassName="text-xs text-status-danger"
|
||||
// A chip like the selects beside it: quiet when off, red when on.
|
||||
<button
|
||||
type="button"
|
||||
aria-pressed={bypass}
|
||||
data-testid="workspace-home-bypass"
|
||||
title={t(codex ? "run:fields.yoloHint" : "run:fields.bypass")}
|
||||
onClick={() => setBypass(!bypass)}
|
||||
className={`flex items-center gap-1.5 rounded-md px-2 py-1 text-xs transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-status-danger/60 ${
|
||||
bypass
|
||||
? "bg-status-danger/10 font-medium text-status-danger ring-1 ring-inset ring-status-danger/30 hover:bg-status-danger/20"
|
||||
: "text-fg-secondary hover:bg-surface-3 hover:text-fg-primary"
|
||||
}`}
|
||||
>
|
||||
<Zap
|
||||
className={`h-3.5 w-3.5 ${bypass ? "fill-current" : "text-fg-muted"}`}
|
||||
aria-hidden
|
||||
/>
|
||||
</span>
|
||||
{t(codex ? "run:fields.yolo" : "run:fields.bypassShort")}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{danger && (
|
||||
|
||||
Reference in New Issue
Block a user