summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax <[email protected]>2026-03-03 14:46:07 -0500
committerGitHub <[email protected]>2026-03-03 14:46:07 -0500
commite3a787a7a3c093935e7972ba606b3f0e3e7d2890 (patch)
tree0cc73f38a47e246fedaa07f3f667f3b1b0b0a72f
parent74ebb4147fd4385cc2d37b46799faddcddd8ba9c (diff)
downloadopencode-e3a787a7a3c093935e7972ba606b3f0e3e7d2890.tar.gz
opencode-e3a787a7a3c093935e7972ba606b3f0e3e7d2890.zip
tui: use arrow indicator for active tool execution (#15887)
-rw-r--r--packages/opencode/src/cli/cmd/tui/routes/session/index.tsx60
1 files changed, 31 insertions, 29 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 9d7098413..7a7f6ce9f 100644
--- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
+++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
@@ -241,7 +241,6 @@ export function Session() {
const logo = UI.logo(" ").split(/\r?\n/)
return exit.message.set(
[
- ``,
`${logo[0] ?? ""}`,
`${logo[1] ?? ""}`,
`${logo[2] ?? ""}`,
@@ -1897,10 +1896,8 @@ function Read(props: ToolProps<typeof ReadTool>) {
</InlineTool>
<For each={loaded()}>
{(filepath) => (
- <box paddingLeft={3}>
- <text paddingLeft={3} fg={theme.textMuted}>
- ↳ Loaded {normalizePath(filepath)}
- </text>
+ <box paddingLeft={5}>
+ <text fg={theme.textMuted}>⤷ Loaded {normalizePath(filepath)}</text>
</box>
)}
</For>
@@ -1994,33 +1991,32 @@ function Task(props: ToolProps<typeof TaskTool>) {
return assistant - first
})
+ const content = createMemo(() => {
+ if (!props.input.description) return ""
+ let content = [`Task ${props.input.description}`]
+
+ if (isRunning() && tools().length > 0) {
+ // content[0] += ` · ${tools().length} toolcalls`
+ if (current()) content.push(`└ ${Locale.titlecase(current()!.tool)} ${(current()!.state as any).title}`)
+ else content.push(`└ Running...`)
+ }
+
+ if (props.part.state.status === "completed") {
+ content.push(`└ ${tools().length} toolcalls · ${Locale.duration(duration())}`)
+ }
+
+ return content.join("\n")
+ })
+
return (
<InlineTool
- icon="≡"
+ icon="│"
spinner={isRunning()}
complete={props.input.description}
pending="Delegating..."
part={props.part}
>
- {props.input.description}
- <Show when={isRunning() && tools().length > 0}>
- {" "}
- · {tools().length} toolcalls
- <Show fallback={"\n└ Running..."} when={current()}>
- {(item) => {
- const title = createMemo(() => (item().state as any).title)
- return (
- <>
- {"\n"}└ {Locale.titlecase(item().tool)} {title()}
- </>
- )
- }}
- </Show>
- </Show>
- <Show when={duration() && props.part.state.status === "completed"}>
- {"\n "}
- {tools().length} toolcalls · {Locale.duration(duration())}
- </Show>
+ {content()}
</InlineTool>
)
}
@@ -2240,10 +2236,16 @@ function Diagnostics(props: { diagnostics?: Record<string, Record<string, any>[]
function normalizePath(input?: string) {
if (!input) return ""
- if (path.isAbsolute(input)) {
- return path.relative(process.cwd(), input) || "."
- }
- return input
+
+ const cwd = process.cwd()
+ const absolute = path.isAbsolute(input) ? input : path.resolve(cwd, input)
+ const relative = path.relative(cwd, absolute)
+
+ if (!relative) return "."
+ if (!relative.startsWith("..")) return relative
+
+ // outside cwd - use absolute
+ return absolute
}
function input(input: Record<string, any>, omit?: string[]): string {