Skip to content

fix(vscode): persist Agent Manager focus per session - #12801

Merged
marius-kilocode merged 4 commits into
mainfrom
persist-terminal-focus-state
Aug 3, 2026
Merged

fix(vscode): persist Agent Manager focus per session#12801
marius-kilocode merged 4 commits into
mainfrom
persist-terminal-focus-state

Conversation

@marius-kilocode

Copy link
Copy Markdown
Collaborator

The Agent Manager webview steals the prompt cursor whenever a session or worktree switch happens while the right-side embedded terminal is open. This was caused by three independent focus paths that all unconditionally dispatched focusPrompt: the draft-key effect in PromptInput, the onWindowFocus handler in AgentManagerApp, and the side-terminal activation transition in TerminalTab. None of them knew whether the target session last used the prompt or the terminal.

What changed

  • Per-session focus owner. AgentManagerApp now keeps a focusMemory map keyed by (context, session) that records whether the last focused surface in that session was the prompt or a specific side-terminal id. The key is derived from terms.sideKey() + session.currentSessionID() so it tracks the actual chat session, not just the worktree.
  • Explicit terminal focus. Side-terminal creation is now opt-in: requestSide() and addSide() pass focus=true; ensureSide() and background context switches pass focus=false. The new focus flag travels through beginSideSideRequestonSideCreated so the handler only calls requestFocus when the user explicitly opened the terminal.
  • Side terminals opt out of auto-focus on activation. A new focusOnActivate prop on TerminalTab prevents the active prop transition from stealing the cursor when a context switch makes a remembered terminal visible without an explicit focus request.
  • Prompt draft effect respects the saved owner. PromptInput accepts a focusOnDraftChange accessor; Agent Manager passes focusPromptForSession which returns false when the target session's remembered owner is the terminal.
  • Window-focus restore follows the saved owner. The unconditional onWindowFocus prompt dispatch is replaced with restoreFocus(), which either re-focuses the remembered terminal (when the side panel is still open) or falls through to the prompt.

Validation

  • bun run compile, bun run check-types, bun run lint all pass.
  • Targeted unit tests in agent-manager-terminal-state.test.ts now distinguish explicit vs background side creates and assert the focus flag on the resulting onSideCreated callback.
  • Manual scenario in isolated VS Code: focus the prompt in session A → open the embedded terminal → switch to session B → switch back to A. The prompt regains focus; the terminal does not steal it on the way back.

Remember whether each session last focused the prompt or its right-side
embedded terminal, and restore that focus owner when switching back.

- Add a focus-owner map keyed by (context, session) in AgentManagerApp
  that records the last focused surface per session.
- Make side-terminal creation explicit: / focus
  the new terminal, while  and context switches do not.
- Suppress the PromptInput draft-change focus dispatch when the target
  session's remembered owner is the terminal.
- Side terminals opt out of auto-focus on activation via a new
   prop so context switches don't steal the cursor.
- Replace the unconditional  prompt dispatch with a
  restore-focus path that follows the saved owner.
- Add regression tests distinguishing explicit vs background side
  creates, and a changeset.
@marius-kilocode
marius-kilocode enabled auto-merge (squash) August 3, 2026 10:17
Comment thread packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx Outdated
Comment thread packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx
Comment thread packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx Outdated
Comment thread packages/kilo-vscode/webview-ui/src/components/chat/ChatView.tsx Outdated
@kilo-code-bot

kilo-code-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx 411 terminalVisible() ? false : true should be !terminalVisible(); the new terminalVisible() helper also isn't reused at the two remaining inline copies of the same condition (~1327, ~2068)
Resolved since last review
  • focusOnDraftChange now checks terminal visibility (sidePanel() === "terminal" && !history() && !reviewActive()), not just existence, so a hidden remembered terminal no longer suppresses prompt auto-focus
  • Redundant IIFE inside focusOnDraftChange removed
Files Reviewed (1 file changed since last review)
  • packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx - 1 issue

Fix these issues in Kilo Cloud

Previous Review Summaries (3 snapshots, latest commit ab296d4)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit ab296d4)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 2
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx 407 Existence-only guard: a remembered terminal that is hidden (panel closed, review/history open) still suppresses prompt auto-focus, unlike restoreFocus which also checks visibility
packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx 402 Redundant IIFE inside the arrow function; a plain block body is equivalent
Resolved since last review
  • Stale terminal owners now self-heal: focusOnDraftChange and restoreFocus drop the focusMemory entry when the remembered terminal no longer exists, so the local closeSide() path can no longer permanently suppress prompt auto-focus
  • Redundant forgetSessionFocus(msg.sessionId) in the agentManager.sessionClosed handler removed (handleCloseTab already does it)
Files Reviewed (1 file changed since last review)
  • packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx - 2 issues

Fix these issues in Kilo Cloud

Previous review (commit b0e60e9)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx 1321 onSideClosed never fires for the local closeSide() path (state removed before the terminal.closed echo), so a dead terminal owner can persist in focusMemory and permanently suppress prompt auto-focus for that session

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx 1295 Redundant forgetSessionFocus(msg.sessionId)handleCloseTab already calls it
Resolved since last review
  • Duplicated createEffect(on(focusKey, ...)) block removed
  • focusOnActivate={false} now respected on the first effect run (serial > 0 guard)
  • focusMemory eviction added for session close, worktree delete, and side-terminal close
  • Prop naming unified on focusOnDraftChange / onFocusChange across ChatView and PromptInput
Files Reviewed (4 files changed since last review)
  • packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx - 2 issues
  • packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/terminal/state.ts
  • packages/kilo-vscode/webview-ui/src/components/chat/ChatView.tsx

Fix these issues in Kilo Cloud

Previous review (commit 66427c4)

Status: 4 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 2
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx 427 Duplicated createEffect(on(focusKey, ...)) block — identical to the one on lines 418-426, so restoreFocus runs twice per session switch
packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx 389 focusOnActivate={false} is bypassed on the first effect run (focusSerial starts at -1 vs 0), so a side terminal created via the new focus: false path still focuses on mount

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx 382 focusMemory map is never evicted — grows for the webview lifetime and keeps stale terminal owners after close/delete
packages/kilo-vscode/webview-ui/src/components/chat/ChatView.tsx 43 Same value renamed at each hop (focusPromptForSessionfocusOnSessionChangefocusOnDraftChange)
Files Reviewed (8 files)
  • .changeset/quiet-terminals-focus.md
  • packages/kilo-vscode/tests/unit/agent-manager-terminal-state.test.ts
  • packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx - 2 issues
  • packages/kilo-vscode/webview-ui/agent-manager/terminal/TerminalTab.tsx - 1 issue
  • packages/kilo-vscode/webview-ui/agent-manager/terminal/render.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/terminal/state.ts
  • packages/kilo-vscode/webview-ui/src/components/chat/ChatView.tsx - 1 issue
  • packages/kilo-vscode/webview-ui/src/components/chat/PromptInput.tsx

Fix these issues in Kilo Cloud


Reviewed by claude-opus-5 · Input: 44 · Output: 8.2K · Cached: 1.4M

Review guidance: REVIEW.md from base branch main

Comment thread packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx
Comment thread packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx Outdated
Comment thread packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx Outdated
Comment thread packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx Outdated
focusMemory.delete(key)
return true
}
return terminalVisible() ? false : true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: x ? false : true is just !x

Minor readability nit on the new guard. While here, the freshly extracted terminalVisible() isn't reused at the two other spots that still spell the condition out inline (if (focus && sidePanel() === "terminal" && !history() && !reviewActive() && ...) around line 1327, and visible: () => sidePanel() === "terminal" && !history() && !reviewActive() around line 2068). Routing those through the helper keeps the four call sites from drifting apart later.

Suggested change
return terminalVisible() ? false : true
return !terminalVisible()

Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@marius-kilocode
marius-kilocode merged commit 4810766 into main Aug 3, 2026
24 checks passed
@marius-kilocode
marius-kilocode deleted the persist-terminal-focus-state branch August 3, 2026 14:34
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
* fix(vscode): persist Agent Manager focus per session

Remember whether each session last focused the prompt or its right-side
embedded terminal, and restore that focus owner when switching back.

- Add a focus-owner map keyed by (context, session) in AgentManagerApp
  that records the last focused surface per session.
- Make side-terminal creation explicit: / focus
  the new terminal, while  and context switches do not.
- Suppress the PromptInput draft-change focus dispatch when the target
  session's remembered owner is the terminal.
- Side terminals opt out of auto-focus on activation via a new
   prop so context switches don't steal the cursor.
- Replace the unconditional  prompt dispatch with a
  restore-focus path that follows the saved owner.
- Add regression tests distinguishing explicit vs background side
  creates, and a changeset.

* fix(vscode): address Agent Manager focus review

* fix(vscode): self-heal stale Agent Manager focus

* fix(vscode): align Agent Manager focus visibility
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants