fix(tui): clear completed background shell status (#35320)
This commit is contained in:
parent
9daa4d85a4
commit
610e618bc5
3 changed files with 22 additions and 9 deletions
|
|
@ -18,8 +18,9 @@ export const DEFAULT_TIMEOUT_MS = 2 * 60 * 1_000
|
||||||
export const MAX_TIMEOUT_MS = 10 * 60 * 1_000
|
export const MAX_TIMEOUT_MS = 10 * 60 * 1_000
|
||||||
export const MAX_CAPTURE_BYTES = 1024 * 1024
|
export const MAX_CAPTURE_BYTES = 1024 * 1024
|
||||||
|
|
||||||
const BACKGROUND_STARTED =
|
const BACKGROUND_STARTED = "The command was moved to the background."
|
||||||
"The command has not completed; it is now running in the background."
|
const BACKGROUND_INSTRUCTION =
|
||||||
|
"You will be notified automatically when the command finishes. DO NOT sleep, poll, or proactively check on its progress."
|
||||||
|
|
||||||
export const Input = Schema.Struct({
|
export const Input = Schema.Struct({
|
||||||
command: Schema.String.annotate({ description: "Shell command string to execute" }),
|
command: Schema.String.annotate({ description: "Shell command string to execute" }),
|
||||||
|
|
@ -54,10 +55,11 @@ const Output = Schema.Struct({
|
||||||
type Output = typeof Output.Type
|
type Output = typeof Output.Type
|
||||||
|
|
||||||
const modelOutput = (output: Output): string | undefined => {
|
const modelOutput = (output: Output): string | undefined => {
|
||||||
if (output.status === "running") return undefined
|
|
||||||
const warnings = output.warnings?.length
|
const warnings = output.warnings?.length
|
||||||
? `\n\nWarnings:\n${output.warnings.map((warning) => `- ${warning}`).join("\n")}`
|
? `\n\nWarnings:\n${output.warnings.map((warning) => `- ${warning}`).join("\n")}`
|
||||||
: ""
|
: ""
|
||||||
|
if (output.status === "running")
|
||||||
|
return `${warnings.trimStart()}${warnings ? "\n\n" : ""}${BACKGROUND_INSTRUCTION}`
|
||||||
if (output.timeout) return `${warnings.trimStart()}${warnings ? "\n\n" : ""}Command timed out before completion.`
|
if (output.timeout) return `${warnings.trimStart()}${warnings ? "\n\n" : ""}Command timed out before completion.`
|
||||||
return `${warnings.trimStart()}${warnings ? "\n\n" : ""}Command exited with code ${output.exit}.`
|
return `${warnings.trimStart()}${warnings ? "\n\n" : ""}Command exited with code ${output.exit}.`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -480,9 +480,13 @@ describe("ShellTool", () => {
|
||||||
const structured = settled.output?.structured as Record<string, unknown> | undefined
|
const structured = settled.output?.structured as Record<string, unknown> | undefined
|
||||||
const shellID = typeof structured?.shellID === "string" ? structured.shellID : undefined
|
const shellID = typeof structured?.shellID === "string" ? structured.shellID : undefined
|
||||||
expect(settled.output?.structured).toMatchObject({ truncated: false })
|
expect(settled.output?.structured).toMatchObject({ truncated: false })
|
||||||
expect(settled.output?.content[0]).toMatchObject({
|
expect(settled.output?.content[0]).toEqual({
|
||||||
type: "text",
|
type: "text",
|
||||||
text: expect.stringContaining("running in the background"),
|
text: "The command was moved to the background.",
|
||||||
|
})
|
||||||
|
expect(settled.output?.content[1]).toMatchObject({
|
||||||
|
type: "text",
|
||||||
|
text: expect.stringContaining("DO NOT sleep, poll"),
|
||||||
})
|
})
|
||||||
expect(shellID).toStartWith("sh_")
|
expect(shellID).toStartWith("sh_")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2080,14 +2080,16 @@ function Shell(props: ToolProps) {
|
||||||
return request?.source?.type === "tool" && request.source.callID === props.part.id
|
return request?.source?.type === "tool" && request.source.callID === props.part.id
|
||||||
})
|
})
|
||||||
const color = createMemo(() => (permission() ? theme.warning : theme.text))
|
const color = createMemo(() => (permission() ? theme.warning : theme.text))
|
||||||
const isRunning = createMemo(() => {
|
const shellID = createMemo(() => stringValue(props.metadata.shellID))
|
||||||
if (props.part.state.status === "running") return true
|
const backgroundRunning = createMemo(() => {
|
||||||
const shellID = stringValue(props.metadata.shellID)
|
const id = shellID()
|
||||||
return Boolean(shellID && data.shell.get(shellID))
|
return Boolean(id && data.shell.get(id))
|
||||||
})
|
})
|
||||||
|
const isRunning = createMemo(() => props.part.state.status === "running" || backgroundRunning())
|
||||||
const command = createMemo(() => stringValue(props.input.command))
|
const command = createMemo(() => stringValue(props.input.command))
|
||||||
const output = createMemo(() => {
|
const output = createMemo(() => {
|
||||||
if (props.part.state.status === "pending") return ""
|
if (props.part.state.status === "pending") return ""
|
||||||
|
if (shellID()) return ""
|
||||||
const content = props.part.state.content[0]
|
const content = props.part.state.content[0]
|
||||||
return stripAnsi(content?.type === "text" ? content.text.trim() : "")
|
return stripAnsi(content?.type === "text" ? content.text.trim() : "")
|
||||||
})
|
})
|
||||||
|
|
@ -2130,6 +2132,11 @@ function Shell(props: ToolProps) {
|
||||||
</Spinner>
|
</Spinner>
|
||||||
</Show>
|
</Show>
|
||||||
</Show>
|
</Show>
|
||||||
|
<Show when={shellID()}>
|
||||||
|
<text>
|
||||||
|
<span style={{ bg: theme.backgroundElement, fg: theme.textMuted }}> Backgrounded </span>
|
||||||
|
</text>
|
||||||
|
</Show>
|
||||||
<Show when={collapsed().overflow}>
|
<Show when={collapsed().overflow}>
|
||||||
<text fg={theme.textMuted}>{expanded() ? "Click to collapse" : "Click to expand"}</text>
|
<text fg={theme.textMuted}>{expanded() ? "Click to collapse" : "Click to expand"}</text>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue