Skip to content

fix(tui): isolate subagent prompt routing#20108

Open
diamondplated wants to merge 1 commit intoanomalyco:devfrom
diamondplated:copilot/opencode-issue-4422
Open

fix(tui): isolate subagent prompt routing#20108
diamondplated wants to merge 1 commit intoanomalyco:devfrom
diamondplated:copilot/opencode-issue-4422

Conversation

@diamondplated
Copy link
Copy Markdown

Issue for this PR

Closes #4422

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

This fixes nested subagent navigation and prompt routing in the TUI. It separates direct-child navigation from sibling cycling and only mounts the prompt when it should actually be active, so hidden prompts stop routing input to the wrong session.

How did you verify your code works?

  • Ran bun test test/cli/tui/session-navigation.test.ts
  • Ran bun run typecheck in packages/opencode

Screenshots / recordings

N/A

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 30, 2026 17:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes nested subagent navigation and prompt routing in the TUI by separating “direct child” navigation from sibling cycling and only rendering the prompt when it should be active (root session with no pending permissions/questions).

Changes:

  • Introduces session navigation helper utilities for direct-child and sibling session selection plus prompt render gating.
  • Updates the TUI session route to use the new navigation helpers and change prompt mounting behavior.
  • Adds unit tests for the new session navigation helpers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/opencode/test/cli/tui/session-navigation.test.ts Adds tests covering direct-child selection, sibling selection, and prompt render gating.
packages/opencode/src/cli/cmd/tui/routes/session/navigation.ts Adds helper functions to compute direct children, siblings, and whether the session prompt should render.
packages/opencode/src/cli/cmd/tui/routes/session/index.tsx Refactors navigation logic to use helpers and conditionally mounts/unmounts the prompt to prevent misrouted input.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +125 to +134
const directChildren = createMemo(() => getDirectChildSessions(sync.data.session, session()?.id))
const siblingSessions = createMemo(() => getSiblingSessions(sync.data.session, session()))
const messages = createMemo(() => sync.data.message[route.sessionID] ?? [])
const permissions = createMemo(() => {
if (session()?.parentID) return []
return children().flatMap((x) => sync.data.permission[x.id] ?? [])
return directChildren().flatMap((x) => sync.data.permission[x.id] ?? [])
})
const questions = createMemo(() => {
if (session()?.parentID) return []
return children().flatMap((x) => sync.data.question[x.id] ?? [])
return directChildren().flatMap((x) => sync.data.question[x.id] ?? [])
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

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

permissions/questions now aggregate only over directChildren(), which excludes the current root session. That means permission/question requests originating from the root session itself won’t be surfaced here, and shouldRenderSessionPrompt may incorrectly render the prompt while root-level requests exist. Include the current session in the aggregation (e.g., combine session()?.id with direct children) or otherwise ensure root session requests are counted and displayed.

Copilot uses AI. Check for mistakes.
Comment on lines +965 to +976
createEffect(() => {
if (
shouldRenderSessionPrompt({
session: session(),
permissionCount: permissions().length,
questionCount: questions().length,
})
) {
return
}
promptRef.set(undefined)
})
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

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

Prompt is now conditionally unmounted, but this effect only clears promptRef and leaves the local prompt variable intact. Many command handlers in this component call prompt.set(...) without guarding, which can now throw (or target a stale ref) when the prompt isn’t rendered (subagent view / permission prompt / question prompt). Consider making prompt optional and clearing it alongside promptRef, and update call sites to use promptRef.current (or optional chaining) so commands don’t crash when the prompt is not mounted.

Copilot uses AI. Check for mistakes.
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.

Primary agent responds in subagent view; delegated subagent views become inaccessible

2 participants