diff --git a/frontend/packages/agent/src/Root.tsx b/frontend/packages/agent/src/Root.tsx index cc3bb991..7aabfc37 100644 --- a/frontend/packages/agent/src/Root.tsx +++ b/frontend/packages/agent/src/Root.tsx @@ -25,6 +25,7 @@ import { fmtAge, fmtTokens } from './lib/format.js'; import { resolveDashboardBase } from './lib/dashboardBase.js'; import { submitPauseResume } from './lib/pauseAction.js'; import { postModel, postEffort } from './lib/modelEffort.js'; +import { postCancelTurn } from './lib/termActions.js'; import type { TokenUsage } from './types.js'; type OpenPanel = 'inbox' | 'todos' | null; @@ -153,6 +154,8 @@ export function Root() { onSelectEffort={() => {}} paused={false} onTogglePause={() => {}} + thinking={false} + onCancelTurn={() => Promise.resolve()} />
@@ -206,6 +209,13 @@ export function Root() { () => refresh(), ); }} + thinking={effectiveTurnState === 'thinking'} + onCancelTurn={() => + postCancelTurn().then((r) => { + if (!r.ok) liveStreamRef.current?.pushNote(`✗ /cancel failed${r.detail ? ': ' + r.detail : ''}`); + refresh(); + }) + } />
diff --git a/frontend/packages/agent/src/components/StatusChips.tsx b/frontend/packages/agent/src/components/StatusChips.tsx index 72ebe367..8c00f94e 100644 --- a/frontend/packages/agent/src/components/StatusChips.tsx +++ b/frontend/packages/agent/src/components/StatusChips.tsx @@ -31,6 +31,8 @@ export interface StatusChipsProps { paused: boolean; onTogglePause: () => void; lastTurnLabel?: string; + thinking: boolean; + onCancelTurn: () => Promise; } const MODEL_DESCRIPTIONS: Record = { @@ -100,7 +102,17 @@ export function StatusChips({ paused, onTogglePause, lastTurnLabel, + thinking, + onCancelTurn, }: StatusChipsProps) { + // `.finally()` on the caller's promise (not a `thinking`-flip effect): + // re-enables the button once the request actually settles, success or + // failure alike — ported from app.js's original + // `postCancelTurn().finally(() => { btn.disabled = false; })`. A + // `thinking`-only reset would leave the button stuck disabled on a + // failed request (argus, PR review): the turn is still in flight, so + // `thinking` never flips to trigger a reset. + const [cancelBusy, setCancelBusy] = useState(false); return (
@@ -141,6 +153,19 @@ export function StatusChips({ onClick={onTogglePause} /> {lastTurnLabel ? {lastTurnLabel} : null} + {thinking ? ( + + ) : null}
); }