diff --git a/apps/desktop/src/components/assistant-ui/clarify-tool.tsx b/apps/desktop/src/components/assistant-ui/clarify-tool.tsx
index cad01efe6ee..e0784b06c5b 100644
--- a/apps/desktop/src/components/assistant-ui/clarify-tool.tsx
+++ b/apps/desktop/src/components/assistant-ui/clarify-tool.tsx
@@ -164,10 +164,10 @@ function ClarifyToolPending({ args }: ToolCallMessagePartProps) {
data-slot="clarify-inline"
>
-
+
diff --git a/apps/desktop/src/components/assistant-ui/tool-fallback-model.test.ts b/apps/desktop/src/components/assistant-ui/tool-fallback-model.test.ts
index 78d2c923a4c..55b7755973e 100644
--- a/apps/desktop/src/components/assistant-ui/tool-fallback-model.test.ts
+++ b/apps/desktop/src/components/assistant-ui/tool-fallback-model.test.ts
@@ -33,3 +33,34 @@ describe('buildToolView image handling', () => {
expect(buildToolView(part({ result: { url } }), '').imageUrl).toBe(url)
})
})
+
+describe('buildToolView terminal exit-code status', () => {
+ const terminal = (result: Record) =>
+ buildToolView(part({ result, toolName: 'terminal' }), '')
+
+ // A non-zero exit code with real output is not a failure (grep no-match,
+ // diff differences, piped commands surfacing the last stage's code, etc.) —
+ // it should render as success so the card isn't painted red.
+ it('treats non-zero exit with output as success', () => {
+ expect(terminal({ exit_code: 7, output: 'node ... 5174 (LISTEN)' }).status).toBe('success')
+ expect(terminal({ exit_code: 1, stdout: 'partial results' }).status).toBe('success')
+ })
+
+ // No output + non-zero exit is a genuine failure worth flagging.
+ it('treats non-zero exit with no output as error', () => {
+ expect(terminal({ exit_code: 127, output: '' }).status).toBe('error')
+ expect(terminal({ exit_code: 1 }).status).toBe('error')
+ })
+
+ it('treats zero exit as success', () => {
+ expect(terminal({ exit_code: 0, output: 'done' }).status).toBe('success')
+ })
+
+ // Explicit error signals still win regardless of output presence.
+ it('keeps explicit error signals red even with output', () => {
+ expect(terminal({ error: 'boom', exit_code: 0, output: 'partial' }).status).toBe('error')
+ expect(buildToolView(part({ isError: true, result: { output: 'x' }, toolName: 'terminal' }), '').status).toBe(
+ 'error'
+ )
+ })
+})
diff --git a/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts b/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts
index c5b4d7a789f..25fa75190a1 100644
--- a/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts
+++ b/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts
@@ -742,9 +742,20 @@ function toolErrorText(part: ToolPart, result: Record): string
return firstStringField(result, ['message', 'reason', 'detail']) || `Tool returned status "${result.status}".`
}
+ // A non-zero exit code alone is a weak failure signal: grep returns 1 on
+ // no-match, diff returns 1 on differences, piped commands surface the last
+ // stage's code, etc. — all routinely produce useful output and aren't
+ // failures. Only treat it as an error when the command produced no real
+ // output to show; otherwise render the output normally (not red).
const exit = numberValue(result.exit_code)
- return exit !== null && exit !== 0 ? `Command failed with exit code ${exit}.` : ''
+ if (exit !== null && exit !== 0) {
+ const hasOutput = Boolean(firstStringField(result, ['output', 'stdout', 'stderr'])?.trim())
+
+ return hasOutput ? '' : `Command failed with exit code ${exit}.`
+ }
+
+ return ''
}
function toolStatus(part: ToolPart, resultRecord: Record): ToolStatus {