diff --git a/examples/tui-agent/tests/snapshots/multi-turn-conversation/terminal.expected.txt b/examples/tui-agent/tests/snapshots/multi-turn-conversation/terminal.expected.txt index e4fa63468a..09f3cb1fb4 100644 --- a/examples/tui-agent/tests/snapshots/multi-turn-conversation/terminal.expected.txt +++ b/examples/tui-agent/tests/snapshots/multi-turn-conversation/terminal.expected.txt @@ -15,8 +15,8 @@ buffer style 0-2 fg=bright-blue bold underline 5| "Reply with exactly the word: ONE. No tools. " 6| -7| "Entering plan mode (applies from the next step). Use /plan off to leave. " - style 0-71 fg=bright-black +7| "Plan mode on. Use /plan off to leave. " + style 0-36 fg=bright-black 8| 9| "Assistant " style 0-8 fg=bright-magenta bold underline @@ -28,17 +28,17 @@ buffer 13| "Model wait 0.0s · Completed 2026-07-21 12:00:00 " style 0-46 dim 14| -15| "Leaving plan mode (applies from the next step). " - style 0-46 fg=bright-black -16| -17| "You " - style 0-2 fg=bright-blue bold underline -18| "Reply with exactly the word: TWO. No tools. " -19| -20| "Context · plan-mode " +15| "Context · plan-mode " style 0-18 dim -21| "The user switched this session back to the default mode. " +16| "The user switched this session back to the default mode. " style 0-55 fg=bright-black +17| +18| "Plan mode off. " + style 0-13 fg=bright-black +19| +20| "You " + style 0-2 fg=bright-blue bold underline +21| "Reply with exactly the word: TWO. No tools. " 22| 23| "Assistant " style 0-8 fg=bright-magenta bold underline diff --git a/packages/client/ui-plan/src/client/PlanModeControl.tsx b/packages/client/ui-plan/src/client/PlanModeControl.tsx index 711d17e675..b7945789a0 100644 --- a/packages/client/ui-plan/src/client/PlanModeControl.tsx +++ b/packages/client/ui-plan/src/client/PlanModeControl.tsx @@ -37,7 +37,7 @@ export function PlanChip({ useProjection, locked, exitPlanMode }: PlanChipProps) if (!target) return null const off = (): void => { - if (leaving || locked) return + // No leaving/locked guard: both disable the button, so no click arrives. setLeaving(true) setError(null) void exitPlanMode().then((failure) => { diff --git a/packages/plan/plan-mode/tests/plan-mode.spec.ts b/packages/plan/plan-mode/tests/plan-mode.spec.ts index 73dce25dbb..edfd9bd660 100644 --- a/packages/plan/plan-mode/tests/plan-mode.spec.ts +++ b/packages/plan/plan-mode/tests/plan-mode.spec.ts @@ -607,6 +607,20 @@ describe('/plan', () => { expect(ctx.planMode.get(active)).toEqual({ active: false }) }) + it('idle sessions get the immediate-commit copy on both /plan and /plan off', async () => { + const ctx = await setup() + await ctx.plugin(CommandService) + await new Promise(resolve => setImmediate(resolve)) + const signal = new AbortController().signal + const agent = await agentWithSession(ctx, 'idle-plan-command', { status: 'idle' }) + expect((await ctx.commands.execute(agent, '/plan', signal))?.result) + .toEqual({ kind: 'success', text: 'Plan mode on. Use /plan off to leave.' }) + expect(foldPlanMode(agent.session.events)).toBe(true) + expect((await ctx.commands.execute(agent, '/plan off', signal))?.result) + .toEqual({ kind: 'success', text: 'Plan mode off.' }) + expect(foldPlanMode(agent.session.events)).toBe(false) + }) + it('removes the contributed command when the plan-mode plugin is disposed', async () => { const ctx = new Context() await ctx.plugin(SystemPrompt)