From 6b3b4c8725d89dec3a3450b493251ec2e7156c9b Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 2 Feb 2026 23:25:29 -0500 Subject: [PATCH] cli: improve task tool display with locale formatting and status icons --- packages/opencode/src/cli/cmd/run.ts | 52 +++++++++++++++------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 24d88a0d4f..59d0e01a7c 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -24,6 +24,7 @@ import { TaskTool } from "../../tool/task" import { SkillTool } from "../../tool/skill" import { BashTool } from "../../tool/bash" import { TodoWriteTool } from "../../tool/todo" +import { Locale } from "../../util/locale" type ToolProps = { input: Tool.InferParameters @@ -165,12 +166,14 @@ function websearch(info: ToolProps) { } function task(info: ToolProps) { - const agent = info.input.subagent_type + const agent = Locale.titlecase(info.input.subagent_type) const desc = info.input.description + const started = info.part.state.status === "running" + const name = desc ?? `${agent} Task` inline({ - icon: "#", - title: `${agent} Task`, - ...(desc && { description: desc }), + icon: started ? "•" : "✓", + title: name, + description: desc ? `${agent} Agent` : undefined, }) } @@ -367,19 +370,6 @@ export const RunCommand = cmd({ } async function execute(sdk: OpencodeClient) { - const seen = new Set() - - function head(info: Message) { - if (args.format === "json") return - if (!process.stdout.isTTY) return - if (info.role !== "assistant") return - if (seen.has(info.id)) return - seen.add(info.id) - const model = info.modelID ? ` · ${info.modelID}` : "" - UI.empty() - UI.println(`$ ${info.agent}${model}`) - } - function tool(part: ToolPart) { if (part.tool === "bash") return bash(props(part)) if (part.tool === "glob") return glob(props(part)) @@ -409,16 +399,19 @@ export const RunCommand = cmd({ let error: string | undefined async function loop() { - UI.empty() - UI.println(`> ${args.message}`) - UI.empty() - let start = false + const toggles = new Map() + for await (const event of events.stream) { - if (event.type === "message.updated" && event.properties.info.role === "assistant" && !start) { - start = true + if ( + event.type === "message.updated" && + event.properties.info.role === "assistant" && + args.format !== "json" && + toggles.get("start") !== true + ) { UI.empty() - UI.println(`< ${event.properties.info.agent} · ${event.properties.info.modelID}`) + UI.println(`> ${event.properties.info.agent} · ${event.properties.info.modelID}`) UI.empty() + toggles.set("start", true) } if (event.type === "message.part.updated") { @@ -430,6 +423,17 @@ export const RunCommand = cmd({ tool(part) } + if ( + part.type === "tool" && + part.tool === "task" && + part.state.status === "running" && + args.format !== "json" + ) { + if (toggles.get(part.id) === true) continue + task(props(part)) + toggles.set(part.id, true) + } + if (part.type === "step-start") { if (emit("step_start", { part })) continue }