diff --git a/packages/tui/src/mini/tool.ts b/packages/tui/src/mini/tool.ts index 010ab3b540d..f4fc0a3975d 100644 --- a/packages/tui/src/mini/tool.ts +++ b/packages/tui/src/mini/tool.ts @@ -644,17 +644,17 @@ function snapQuestion(p: ToolProps): ToolSnapshot { function scrollBashStart(p: ToolProps): string { const cmd = p.input.command ?? "" const wd = p.input.workdir ?? "" - const formatted = wd && wd !== "." ? displayPath(p, wd) : "" + const formatted = wd && wd !== "." ? displayPath(p, wd, { home: true }) : "" const dir = formatted === "." ? "" : formatted if (cmd && !dir) { return `$ ${cmd}` } if (!cmd) { - return dir ? `# Running in ${dir}` : "" + return dir ? `${dir}$` : "" } - return `# Running in ${dir}\n$ ${cmd}` + return `${dir}$ ${cmd}` } function scrollBashProgress(p: ToolProps): string { @@ -670,7 +670,7 @@ function scrollBashProgress(p: ToolProps): string { } const wdRaw = (p.input.workdir ?? "").trim() - const wd = wdRaw ? displayPath(p, wdRaw) : "" + const wd = wdRaw ? displayPath(p, wdRaw, { home: true }) : "" const lines = out.split("\n") const first = (lines[0] || "").trim() const second = (lines[1] || "").trim() diff --git a/packages/tui/src/routes/session/index.tsx b/packages/tui/src/routes/session/index.tsx index 46428a1a934..4b1717b4886 100644 --- a/packages/tui/src/routes/session/index.tsx +++ b/packages/tui/src/routes/session/index.tsx @@ -2562,6 +2562,7 @@ function Shell(props: ToolProps) { const ctx = use() const client = useClient() const data = useData() + const pathFormatter = usePathFormatter() const permission = createMemo(() => { const request = data.session.permission.list(ctx.sessionID)?.[0] return request?.source?.type === "tool" && request.source.callID === props.part.id @@ -2575,6 +2576,7 @@ function Shell(props: ToolProps) { }) const isRunning = createMemo(() => props.part.state.status === "running" || backgroundRunning()) const command = createMemo(() => stringValue(props.input.command)) + const workdir = createMemo(() => pathFormatter.format(stringValue(props.input.workdir))) const [expanded, setExpanded] = createSignal(false) const [backgroundOutput, setBackgroundOutput] = createSignal("") const [outputTruncated, setOutputTruncated] = createSignal(false) @@ -2648,7 +2650,11 @@ function Shell(props: ToolProps) { }) const maxLines = 10 const maxChars = createMemo(() => maxLines * Math.max(20, ctx.width - 6)) - const input = createMemo(() => (command() ? `${isRunning() ? "" : "$ "}${command()}` : "")) + const input = createMemo(() => { + if (!command()) return "" + const prompt = workdir() && workdir() !== "." ? `${workdir()}$ ` : isRunning() ? "" : "$ " + return `${prompt}${command()}` + }) const content = createMemo(() => [input(), output()].filter(Boolean).join("\n\n")) const collapsed = createMemo(() => collapseToolOutput(content(), maxLines, maxChars())) const limited = createMemo(() => { diff --git a/packages/tui/test/mini/entry.body.test.ts b/packages/tui/test/mini/entry.body.test.ts index 717466de3c6..6151b719fb6 100644 --- a/packages/tui/test/mini/entry.body.test.ts +++ b/packages/tui/test/mini/entry.body.test.ts @@ -1,4 +1,6 @@ import { describe, expect, test } from "bun:test" +import os from "os" +import path from "path" import type { SessionMessageAssistantTool } from "@opencode-ai/client/promise" import { entryBody, entryCanStream, entryDone } from "../../src/mini/entry.body" import type { StreamCommit, ToolSnapshot } from "../../src/mini/types" @@ -11,6 +13,7 @@ function commit(input: Partial & Pick { }) }) + test("renders a shell workdir before the prompt", () => { + expect( + entryBody( + toolCommit({ + tool: "shell", + directory: "/work/project", + phase: "start", + toolState: "running", + state: { + status: "running", + input: { + command: "ls", + workdir: "packages/foo", + }, + metadata: {}, + }, + }), + ), + ).toEqual({ + type: "text", + content: "packages/foo$ ls", + }) + + expect( + entryBody( + toolCommit({ + tool: "shell", + directory: path.join(os.homedir(), "project"), + phase: "start", + toolState: "running", + state: { + status: "running", + input: { + command: "pwd", + workdir: path.join(os.homedir(), "outside", "folder"), + }, + metadata: {}, + }, + }), + ), + ).toEqual({ + type: "text", + content: "~/outside/folder$ pwd", + }) + }) + test("renders direct shell commits without a synthetic shell header", () => { expect( entryBody(