From 002b81cd67a0e34b87bc03164eeb4bbb69159a87 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Wed, 4 Mar 2026 17:06:10 +0530 Subject: [PATCH 1/3] fix(tui): keep inline task navigation and fix nested child jump --- .../src/cli/cmd/tui/routes/session/index.tsx | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index e2747ad3b7a0..3a0560a3736b 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -128,6 +128,11 @@ export function Session() { .filter((x) => x.parentID === parentID || x.id === parentID) .toSorted((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)) }) + const subagents = createMemo(() => { + return sync.data.session + .filter((x) => x.parentID === route.sessionID) + .toSorted((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)) + }) const messages = createMemo(() => sync.data.message[route.sessionID] ?? []) const permissions = createMemo(() => { if (session()?.parentID) return [] @@ -316,20 +321,14 @@ export function Session() { const local = useLocal() function moveFirstChild() { - if (children().length === 1) return - const next = children().find((x) => !!x.parentID) - if (next) { - navigate({ - type: "session", - sessionID: next.id, - }) - } + const next = subagents()[0] + if (!next) return + navigate({ type: "session", sessionID: next.id }) } function moveChild(direction: number) { - if (children().length === 1) return - const sessions = children().filter((x) => !!x.parentID) + if (sessions.length === 0) return let next = sessions.findIndex((x) => x.id === session()?.id) + direction if (next >= sessions.length) next = 0 @@ -1623,6 +1622,7 @@ function InlineTool(props: { complete: any pending: string spinner?: boolean + onClick?: () => void children: JSX.Element part: ToolPart }) { @@ -1630,6 +1630,7 @@ function InlineTool(props: { const { theme } = useTheme() const ctx = use() const sync = useSync() + const renderer = useRenderer() const permission = createMemo(() => { const callID = sync.data.permission[ctx.sessionID]?.at(0)?.tool?.callID @@ -1678,6 +1679,10 @@ function InlineTool(props: { return } }} + onMouseUp={() => { + if (renderer.getSelection()?.getSelectedText()) return + props.onClick?.() + }} > @@ -1941,10 +1946,7 @@ function WebSearch(props: ToolProps) { } function Task(props: ToolProps) { - const { theme } = useTheme() - const keybind = useKeybind() const { navigate } = useRoute() - const local = useLocal() const sync = useSync() onMount(() => { @@ -1997,6 +1999,15 @@ function Task(props: ToolProps) { complete={props.input.description} pending="Delegating..." part={props.part} + onClick={ + props.metadata.sessionId + ? () => { + const id = props.metadata.sessionId + if (!id) return + navigate({ type: "session", sessionID: id }) + } + : undefined + } > {content()} From c4c3a020f92eba5a53894102332b5f6e6fc69204 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Wed, 4 Mar 2026 17:39:44 +0530 Subject: [PATCH 2/3] refactor(tui): use renderer.hasSelection guards --- packages/opencode/src/cli/cmd/tui/routes/session/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 3a0560a3736b..1f0e1f436f4c 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1123,7 +1123,7 @@ export function Session() { { - if (renderer.getSelection()?.getSelectedText()) return + if (renderer.hasSelection) return dialog.replace(() => ( { - if (renderer.getSelection()?.getSelectedText()) return + if (renderer.hasSelection) return props.onClick?.() }} > @@ -1728,7 +1728,7 @@ function BlockTool(props: { onMouseOver={() => props.onClick && setHover(true)} onMouseOut={() => setHover(false)} onMouseUp={() => { - if (renderer.getSelection()?.getSelectedText()) return + if (renderer.hasSelection) return props.onClick?.() }} > From d8c3d8d8843075666c599dba1559b73385026178 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Thu, 5 Mar 2026 19:07:49 +0530 Subject: [PATCH 3/3] highlight clickable inline tools --- .../opencode/src/cli/cmd/tui/routes/session/index.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index f9cd060552b5..849f831eecf3 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1631,6 +1631,7 @@ function InlineTool(props: { const ctx = use() const sync = useSync() const renderer = useRenderer() + const [hover, setHover] = createSignal(false) const permission = createMemo(() => { const callID = sync.data.permission[ctx.sessionID]?.at(0)?.tool?.callID @@ -1679,6 +1680,8 @@ function InlineTool(props: { return } }} + onMouseOver={() => props.onClick && setHover(true)} + onMouseOut={() => setHover(false)} onMouseUp={() => { if (renderer.hasSelection) return props.onClick?.() @@ -1686,10 +1689,14 @@ function InlineTool(props: { > - + - + ~ {props.pending}} when={props.complete}> {props.icon} {props.children}