Controller Mode: auto-advance after approval + structured-input submit#284
Conversation
closes #277) Pin two or more sessions and enter Controller Mode. If a tool-approval card or a structured user-input prompt lands on the active session without a preceding send, the focus-advance countdown now fires once the user resolves the prompt — the same way it fires after a send. * handleToolApproval: on a successful submit, schedule the focus advance for any non-deny decision (allow_once / always_allow). Deny is the explicit 'stay and reconsider' signal and intentionally does not advance. * handleStructuredUserInputSubmit: on a successful submit, schedule the focus advance. The separate dismiss path is the explicit stay signal and is left untouched. * Both new call sites use the same focusAdvanceOnAttachRef deferral as the existing send path (issue #120), so a submission on a brand new session that hasn't attached yet still schedules the advance once the session id is known. * The de-duplication rule ('restart the clock on a new send') already lives in handleFocusAdvanceAfterSend; the new calls reuse it, so resolving a prompt during an in-flight countdown restarts the clock on the new origin session instead of stacking a second toast. * Toast copy updated to make it obvious the countdown can be triggered by sends OR prompt resolutions, and a regression test pins the new line. * Controller Mode docs updated to describe the new trigger sources.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 466001c8c1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (controllerMode && onFocusAdvanceAfterSend) { | ||
| if (targetSessionId) { | ||
| onFocusAdvanceAfterSend(targetSessionId); |
There was a problem hiding this comment.
Avoid advancing before a queued input resume can start
When a Claude structured-input answer is submitted while the original SSE is still closing, this schedules the 4s focus advance even though the resume is only staged in queuedStreamStart. If the countdown moves Controller Mode to another same-worktree session before that queued resume starts, the later startAgentStream(..., resumeSessionId) runs from the new view and its existing controller-mode scheduling uses the current sessionId instead of the resume target, causing an extra/wrong advance away from the new session. Please defer this schedule until the resume actually starts, or suppress the resume path's own focus-advance scheduling.
Useful? React with 👍 / 👎.
Closes #277.
Summary
Pin two or more sessions and enter Controller Mode. If a tool-approval card or a structured user-input prompt lands on the active session without a preceding send, the focus-advance countdown now fires once the user resolves the prompt — the same way it fires after a send. The user no longer has to hit the next-session chord manually to keep the loop moving.
Changes
client/src/pages/SessionView.tsxhandleToolApproval: on a successful submit, schedule the focus advance for any non-deny decision (allow_once/always_allow). Deny is the explicit "stay and reconsider" signal and intentionally does not advance.handleStructuredUserInputSubmit: on a successful submit, schedule the focus advance. The separate dismiss path is the explicit stay signal and is left untouched.focusAdvanceOnAttachRefdeferral as the existing send path (Focus mode: new sessions do not auto-advance after first send #120), so a submission on a brand-new session that hasn't attached yet still schedules the advance once the session id is known.handleFocusAdvanceAfterSend; the new calls reuse it, so resolving a prompt during an in-flight countdown restarts the clock on the new origin session instead of stacking a second toast.client/src/components/focus-advance-toast.tsx: copy now mentions that the countdown can be triggered by sends, approvals, or answered prompts.docs/content/docs/controller-mode.mdx: documents the new trigger sources and the deny-no-advance / dismiss-no-advance carve-outs.client/src/components/__tests__/focus-advance-toast.test.tsx: regression test pinning the new copy line.Validation
node --import tsx --test 'client/src/components/__tests__/**/*.test.tsx' 'client/src/lib/**/*.test.ts'→ 145/145 pass (includes the new regression test).npm test→ 548/549 pass; the one failure is the pre-existingserver/lib/__tests__/pty-manager.test.tsflake unrelated to this change.