From 168737579fdd91b8c801400e66291d22ea5ec436 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 3 Mar 2026 00:47:08 +0100 Subject: [PATCH 1/8] fix(opencode): restore click-to-navigate on Task tool using BlockTool --- .../src/cli/cmd/tui/routes/session/index.tsx | 53 +++++++++++-------- 1 file changed, 30 insertions(+), 23 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 68f6796cdddb..f907c2812bda 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1974,33 +1974,40 @@ function Task(props: ToolProps) { }) return ( - navigate({ type: "session", sessionID: props.metadata.sessionId! }) : undefined + } part={props.part} + spinner={isRunning()} > - {props.input.description} - 0}> - {" "} - · {tools().length} toolcalls - - {(item) => { - const title = createMemo(() => (item().state as any).title) - return ( - <> - {"\n"}└ {Locale.titlecase(item().tool)} {title()} - - ) - }} + + 0}> + + {tools().length} toolcalls + + {(item) => { + const title = createMemo(() => (item().state as any).title) + return ( + <> + {"\n"}└ {Locale.titlecase(item().tool)} {title()} + + ) + }} + + + + + {tools().length} toolcalls · {Locale.duration(duration())} + + + + + {keybind.print("session_child_first")} view subagents - - {"\n "} - {tools().length} toolcalls · {Locale.duration(duration())} - - + ) } From 69a67d015777dd8cc6353f3d0df415139ee007d9 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 4 Mar 2026 00:23:25 +0100 Subject: [PATCH 2/8] feat(ui): add onClick prop to BasicTool for task click-to-navigate --- packages/ui/src/components/basic-tool.tsx | 13 ++++++++++++- packages/ui/src/components/message-part.tsx | 10 +++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/components/basic-tool.tsx b/packages/ui/src/components/basic-tool.tsx index fff6e92f17c3..07f6e075ca4f 100644 --- a/packages/ui/src/components/basic-tool.tsx +++ b/packages/ui/src/components/basic-tool.tsx @@ -31,6 +31,7 @@ export interface BasicToolProps { defer?: boolean locked?: boolean animated?: boolean + onClick?: (e: MouseEvent) => void onSubtitleClick?: () => void } @@ -118,7 +119,17 @@ export function BasicTool(props: BasicToolProps) { return ( -
+
{ + if (props.onClick) { + e.stopPropagation() + e.preventDefault() + props.onClick(e) + } + }} + style={{ cursor: props.onClick ? "pointer" : undefined }} + >
diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index a97b3867185d..5a3bd73f7dd1 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -1546,7 +1546,15 @@ ToolRegistry.register({
) - return + return ( + + ) }, }) From aab71187897bc650d222313402942d2ed07a0c87 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 4 Mar 2026 00:28:24 +0100 Subject: [PATCH 3/8] feat(tui): add onClick prop to InlineTool and use it for Task click-to-navigate Add native onClick support to InlineTool (matching BlockTool's onMouseUp pattern with text-selection guard), and revert Task from BlockTool back to InlineTool per maintainer preference while preserving upstream's content() memo pattern. --- .../src/cli/cmd/tui/routes/session/index.tsx | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 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 9d33dfb948a6..e24223eb8df0 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1625,9 +1625,11 @@ function InlineTool(props: { spinner?: boolean children: JSX.Element part: ToolPart + onClick?: () => void }) { const [margin, setMargin] = createSignal(0) const { theme } = useTheme() + const renderer = useRenderer() const ctx = use() const sync = useSync() @@ -1656,6 +1658,10 @@ function InlineTool(props: { { + if (renderer.getSelection()?.getSelectedText()) return + props.onClick?.() + }} renderBefore={function () { const el = this as BoxRenderable const parent = el.parent @@ -1941,10 +1947,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(() => { @@ -1991,23 +1994,18 @@ function Task(props: ToolProps) { }) return ( - navigate({ type: "session", sessionID: props.metadata.sessionId! }) : undefined } - part={props.part} - spinner={isRunning()} > - - - {content()} - - - {keybind.print("session_child_first")} view subagents - - - + {content()} + ) } From 4908dc53e55e2880c43e04596f9ec803d26583d2 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 4 Mar 2026 00:38:51 +0100 Subject: [PATCH 4/8] refactor: move click target to text element in InlineTool and revert BasicTool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Web UI: revert BasicTool onClick prop — the existing link on the subtitle text in Task's trigger JSX already handles click-to-navigate. TUI: move onMouseUp from the outer to the inner element so only the text content is clickable (not the entire tool block). Add onMouseOver/onMouseOut hover feedback matching header.tsx pattern. --- .../src/cli/cmd/tui/routes/session/index.tsx | 17 ++++++++++++----- packages/ui/src/components/basic-tool.tsx | 13 +------------ packages/ui/src/components/message-part.tsx | 10 +--------- 3 files changed, 14 insertions(+), 26 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 e24223eb8df0..9f7c91fadd4d 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1628,6 +1628,7 @@ function InlineTool(props: { onClick?: () => void }) { const [margin, setMargin] = createSignal(0) + const [hover, setHover] = createSignal(false) const { theme } = useTheme() const renderer = useRenderer() const ctx = use() @@ -1658,10 +1659,6 @@ function InlineTool(props: { { - if (renderer.getSelection()?.getSelectedText()) return - props.onClick?.() - }} renderBefore={function () { const el = this as BoxRenderable const parent = el.parent @@ -1690,7 +1687,17 @@ function InlineTool(props: { - + props.onClick && setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => { + if (renderer.getSelection()?.getSelectedText()) return + props.onClick?.() + }} + > ~ {props.pending}} when={props.complete}> {props.icon} {props.children} diff --git a/packages/ui/src/components/basic-tool.tsx b/packages/ui/src/components/basic-tool.tsx index 07f6e075ca4f..fff6e92f17c3 100644 --- a/packages/ui/src/components/basic-tool.tsx +++ b/packages/ui/src/components/basic-tool.tsx @@ -31,7 +31,6 @@ export interface BasicToolProps { defer?: boolean locked?: boolean animated?: boolean - onClick?: (e: MouseEvent) => void onSubtitleClick?: () => void } @@ -119,17 +118,7 @@ export function BasicTool(props: BasicToolProps) { return ( -
{ - if (props.onClick) { - e.stopPropagation() - e.preventDefault() - props.onClick(e) - } - }} - style={{ cursor: props.onClick ? "pointer" : undefined }} - > +
diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index 5a3bd73f7dd1..a97b3867185d 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -1546,15 +1546,7 @@ ToolRegistry.register({
) - return ( - - ) + return }, }) From 1de4a9ca9d70e8d7453993d5f67866698124e839 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 4 Mar 2026 00:46:12 +0100 Subject: [PATCH 5/8] fix: use backgroundColor hover pattern for InlineTool onClick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align InlineTool click hover with the rest of the TUI — wrap in a with onMouseOver/onMouseOut toggling backgroundColor, matching UserMessage, BlockTool, and header.tsx navigation buttons. --- .../src/cli/cmd/tui/routes/session/index.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 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 9f7c91fadd4d..812ce85f041b 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1687,21 +1687,21 @@ function InlineTool(props: { - props.onClick && setHover(true)} onMouseOut={() => setHover(false)} onMouseUp={() => { if (renderer.getSelection()?.getSelectedText()) return props.onClick?.() }} + backgroundColor={hover() ? theme.backgroundElement : undefined} > - ~ {props.pending}} when={props.complete}> - {props.icon} {props.children} - - + + ~ {props.pending}} when={props.complete}> + {props.icon} {props.children} + + + From a5ff0f9c0ab689a9b66ba669f8d80edc37d55bf4 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 4 Mar 2026 01:39:53 +0100 Subject: [PATCH 6/8] fix(tui): make 'view subagents' hint clickable instead of InlineTool --- .../src/cli/cmd/tui/routes/session/index.tsx | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 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 812ce85f041b..3c3e237e8d7d 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1312,6 +1312,8 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las const local = useLocal() const { theme } = useTheme() const sync = useSync() + const command = useCommandDialog() + const [hover, setHover] = createSignal(false) const messages = createMemo(() => sync.data.message[props.message.sessionID] ?? []) const final = createMemo(() => { @@ -1346,7 +1348,14 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las }} x.type === "tool" && x.tool === "task")}> - + setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => command.trigger("session.child.first")} + backgroundColor={hover() ? theme.backgroundElement : undefined} + > {keybind.print("session_child_first")} view subagents @@ -1625,12 +1634,9 @@ function InlineTool(props: { spinner?: boolean children: JSX.Element part: ToolPart - onClick?: () => void }) { const [margin, setMargin] = createSignal(0) - const [hover, setHover] = createSignal(false) const { theme } = useTheme() - const renderer = useRenderer() const ctx = use() const sync = useSync() @@ -1687,21 +1693,11 @@ function InlineTool(props: { - props.onClick && setHover(true)} - onMouseOut={() => setHover(false)} - onMouseUp={() => { - if (renderer.getSelection()?.getSelectedText()) return - props.onClick?.() - }} - backgroundColor={hover() ? theme.backgroundElement : undefined} - > - - ~ {props.pending}} when={props.complete}> - {props.icon} {props.children} - - - + + ~ {props.pending}} when={props.complete}> + {props.icon} {props.children} + + @@ -1954,7 +1950,6 @@ function WebSearch(props: ToolProps) { } function Task(props: ToolProps) { - const { navigate } = useRoute() const sync = useSync() onMount(() => { @@ -2007,9 +2002,6 @@ function Task(props: ToolProps) { complete={props.input.description} pending="Delegating..." part={props.part} - onClick={ - props.metadata.sessionId ? () => navigate({ type: "session", sessionID: props.metadata.sessionId! }) : undefined - } > {content()} From fa8444500c4862f452db4f6898e505eec9825b65 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 4 Mar 2026 02:05:12 +0100 Subject: [PATCH 7/8] fix(tui): separate layout box from clickable box for view subagents hint --- .../src/cli/cmd/tui/routes/session/index.tsx | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 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 3c3e237e8d7d..9b9a13c5d813 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1348,18 +1348,18 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las }} x.type === "tool" && x.tool === "task")}> - setHover(true)} - onMouseOut={() => setHover(false)} - onMouseUp={() => command.trigger("session.child.first")} - backgroundColor={hover() ? theme.backgroundElement : undefined} - > - - {keybind.print("session_child_first")} - view subagents - + + setHover(true)} + onMouseOut={() => setHover(false)} + onMouseUp={() => command.trigger("session.child.first")} + backgroundColor={hover() ? theme.backgroundElement : undefined} + > + + {keybind.print("session_child_first")} + view subagents + + From d273e35b3b4485205c14d7fa5730557f18e15ccf Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 4 Mar 2026 02:23:17 +0100 Subject: [PATCH 8/8] fix(tui): constrain hover highlight to text width with flexDirection row --- packages/opencode/src/cli/cmd/tui/routes/session/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9b9a13c5d813..cffd519fabd6 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -1348,7 +1348,7 @@ function AssistantMessage(props: { message: AssistantMessage; parts: Part[]; las }} x.type === "tool" && x.tool === "task")}> - + setHover(true)} onMouseOut={() => setHover(false)}