fix(tui): show shell working directory in prompt
This commit is contained in:
parent
c7871e14d4
commit
2ddc91a0e8
3 changed files with 61 additions and 5 deletions
|
|
@ -644,17 +644,17 @@ function snapQuestion(p: ToolProps): ToolSnapshot {
|
||||||
function scrollBashStart(p: ToolProps): string {
|
function scrollBashStart(p: ToolProps): string {
|
||||||
const cmd = p.input.command ?? ""
|
const cmd = p.input.command ?? ""
|
||||||
const wd = p.input.workdir ?? ""
|
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
|
const dir = formatted === "." ? "" : formatted
|
||||||
if (cmd && !dir) {
|
if (cmd && !dir) {
|
||||||
return `$ ${cmd}`
|
return `$ ${cmd}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!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 {
|
function scrollBashProgress(p: ToolProps): string {
|
||||||
|
|
@ -670,7 +670,7 @@ function scrollBashProgress(p: ToolProps): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
const wdRaw = (p.input.workdir ?? "").trim()
|
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 lines = out.split("\n")
|
||||||
const first = (lines[0] || "").trim()
|
const first = (lines[0] || "").trim()
|
||||||
const second = (lines[1] || "").trim()
|
const second = (lines[1] || "").trim()
|
||||||
|
|
|
||||||
|
|
@ -2562,6 +2562,7 @@ function Shell(props: ToolProps) {
|
||||||
const ctx = use()
|
const ctx = use()
|
||||||
const client = useClient()
|
const client = useClient()
|
||||||
const data = useData()
|
const data = useData()
|
||||||
|
const pathFormatter = usePathFormatter()
|
||||||
const permission = createMemo(() => {
|
const permission = createMemo(() => {
|
||||||
const request = data.session.permission.list(ctx.sessionID)?.[0]
|
const request = data.session.permission.list(ctx.sessionID)?.[0]
|
||||||
return request?.source?.type === "tool" && request.source.callID === props.part.id
|
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 isRunning = createMemo(() => props.part.state.status === "running" || backgroundRunning())
|
||||||
const command = createMemo(() => stringValue(props.input.command))
|
const command = createMemo(() => stringValue(props.input.command))
|
||||||
|
const workdir = createMemo(() => pathFormatter.format(stringValue(props.input.workdir)))
|
||||||
const [expanded, setExpanded] = createSignal(false)
|
const [expanded, setExpanded] = createSignal(false)
|
||||||
const [backgroundOutput, setBackgroundOutput] = createSignal("")
|
const [backgroundOutput, setBackgroundOutput] = createSignal("")
|
||||||
const [outputTruncated, setOutputTruncated] = createSignal(false)
|
const [outputTruncated, setOutputTruncated] = createSignal(false)
|
||||||
|
|
@ -2648,7 +2650,11 @@ function Shell(props: ToolProps) {
|
||||||
})
|
})
|
||||||
const maxLines = 10
|
const maxLines = 10
|
||||||
const maxChars = createMemo(() => maxLines * Math.max(20, ctx.width - 6))
|
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 content = createMemo(() => [input(), output()].filter(Boolean).join("\n\n"))
|
||||||
const collapsed = createMemo(() => collapseToolOutput(content(), maxLines, maxChars()))
|
const collapsed = createMemo(() => collapseToolOutput(content(), maxLines, maxChars()))
|
||||||
const limited = createMemo(() => {
|
const limited = createMemo(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import { describe, expect, test } from "bun:test"
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import os from "os"
|
||||||
|
import path from "path"
|
||||||
import type { SessionMessageAssistantTool } from "@opencode-ai/client/promise"
|
import type { SessionMessageAssistantTool } from "@opencode-ai/client/promise"
|
||||||
import { entryBody, entryCanStream, entryDone } from "../../src/mini/entry.body"
|
import { entryBody, entryCanStream, entryDone } from "../../src/mini/entry.body"
|
||||||
import type { StreamCommit, ToolSnapshot } from "../../src/mini/types"
|
import type { StreamCommit, ToolSnapshot } from "../../src/mini/types"
|
||||||
|
|
@ -11,6 +13,7 @@ function commit(input: Partial<StreamCommit> & Pick<StreamCommit, "kind" | "text
|
||||||
function toolCommit(input: {
|
function toolCommit(input: {
|
||||||
tool: string
|
tool: string
|
||||||
state: SessionMessageAssistantTool["state"]
|
state: SessionMessageAssistantTool["state"]
|
||||||
|
directory?: string
|
||||||
phase?: StreamCommit["phase"]
|
phase?: StreamCommit["phase"]
|
||||||
toolState?: StreamCommit["toolState"]
|
toolState?: StreamCommit["toolState"]
|
||||||
text?: string
|
text?: string
|
||||||
|
|
@ -23,6 +26,7 @@ function toolCommit(input: {
|
||||||
phase: input.phase ?? "final",
|
phase: input.phase ?? "final",
|
||||||
source: "tool",
|
source: "tool",
|
||||||
tool: input.tool,
|
tool: input.tool,
|
||||||
|
directory: input.directory,
|
||||||
toolState:
|
toolState:
|
||||||
input.toolState ??
|
input.toolState ??
|
||||||
(input.state.status === "error" ? "error" : input.state.status === "completed" ? "completed" : "running"),
|
(input.state.status === "error" ? "error" : input.state.status === "completed" ? "completed" : "running"),
|
||||||
|
|
@ -372,6 +376,52 @@ describe("run entry body", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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", () => {
|
test("renders direct shell commits without a synthetic shell header", () => {
|
||||||
expect(
|
expect(
|
||||||
entryBody(
|
entryBody(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue