Skip to content

Commit 66e34d3

Browse files
committed
feat: update the Bash tool param to render on one line
1 parent 894b293 commit 66e34d3

2 files changed

Lines changed: 57 additions & 17 deletions

File tree

src/tests/message-view.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import assert from "node:assert/strict";
33
import { parseDiffPreview } from "../ui";
44
import {
55
buildThinkingSummary,
6+
formatBashStatusParams,
7+
formatToolStatusParams,
68
renderMessageToStdout,
79
getUpdatePlanPreviewLines,
810
parseToolPayload,
@@ -60,6 +62,26 @@ test("MessageView shows full reasoning content in Normal/Raw mode", () => {
6062
);
6163
});
6264

65+
test("formatBashStatusParams compacts multi-line commands and keeps the final description", () => {
66+
assert.equal(
67+
formatBashStatusParams('python3 -c "\nprint(1)\nprint(2)\n" # Run inline script'),
68+
'python3 -c " ... " # Run inline script'
69+
);
70+
});
71+
72+
test("formatToolStatusParams preserves compacted Bash params but truncates other tools", () => {
73+
assert.equal(
74+
formatToolStatusParams({
75+
name: "bash",
76+
params: "cat <<'EOF'\nhello\nEOF # Print heredoc",
77+
ok: true,
78+
metadata: null,
79+
}),
80+
"cat <<'EOF' ... EOF # Print heredoc"
81+
);
82+
assert.equal(formatToolStatusParams({ name: "read", params: "first\nsecond", ok: true, metadata: null }), "first");
83+
});
84+
6385
// --- renderMessageToStdout tests ---
6486

6587
function makeSessionMessage(overrides: Partial<SessionMessage> & Pick<SessionMessage, "role">): SessionMessage {
@@ -139,6 +161,18 @@ test("renderMessageToStdout renders tool messages with resultMd output", () => {
139161
assert.ok(output.includes("line 1"));
140162
});
141163

164+
test("renderMessageToStdout compacts multi-line Bash params", () => {
165+
const payload = JSON.stringify({ name: "bash", ok: true });
166+
const msg = makeSessionMessage({
167+
role: "tool",
168+
content: payload,
169+
meta: { paramsMd: 'python3 -c "\nprint(1)\nprint(2)\n" # Run inline script' },
170+
});
171+
const output = renderMessageToStdout(msg, RawMode.Raw);
172+
assert.ok(output.includes('python3 -c " ... " # Run inline script'));
173+
assert.ok(!output.includes("print(1)"));
174+
});
175+
142176
test("renderMessageToStdout renders UpdatePlan tool messages with Plan preview and resultMd", () => {
143177
const payload = JSON.stringify({
144178
name: "UpdatePlan",

src/ui/components/MessageView/utils.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,28 @@ export function buildThinkingSummary(content: string, messageParams: unknown | n
5454
return "";
5555
}
5656

57-
/** Formats a tool's parameters for status display, preserving full bash commands but truncating others. */
57+
/** Formats multi-line Bash params as first line, a placeholder, and the final line. */
58+
export function formatBashStatusParams(params: string): string {
59+
const value = params.trim();
60+
if (!value) {
61+
return "";
62+
}
63+
64+
const lines = value.split(/\r?\n/);
65+
if (lines.length <= 1) {
66+
return value;
67+
}
68+
69+
return `${lines[0]} ... ${lines[lines.length - 1].trimStart()}`;
70+
}
71+
72+
/** Formats a tool's parameters for status display, compacting multi-line Bash commands and truncating others. */
5873
export function formatToolStatusParams(summary: ToolSummary): string {
74+
if (summary.name.toLowerCase() === "bash") {
75+
return formatBashStatusParams(summary.params);
76+
}
5977
const params = firstNonEmptyLine(summary.params);
60-
return summary.name.toLowerCase() === "bash" ? params : truncate(params, 120);
78+
return truncate(params, 120);
6179
}
6280

6381
/** Builds a structured summary (name, params, ok, metadata) from a tool session message. */
@@ -226,25 +244,13 @@ export function renderMessageToStdout(message: SessionMessage, mode: RawMode): s
226244
}
227245

228246
if (message.role === "tool") {
229-
const payload = parseToolPayload(message.content);
230-
const metaFunctionName =
231-
message.meta?.function && typeof (message.meta.function as { name?: unknown }).name === "string"
232-
? (message.meta.function as { name: string }).name
233-
: null;
234-
const name = payload.name || metaFunctionName || "tool";
235-
const metaParams = typeof message.meta?.paramsMd === "string" ? message.meta.paramsMd.trim() : "";
236-
const params = name.toLowerCase() === "bash" ? metaParams : truncate(metaParams, 120);
237-
const statusLine = `${chalk("✧")} ${chalk(formatStatusName(name))}${params ? ` ${chalk(params)}` : ""}`;
247+
const summary = buildToolSummary(message);
248+
const params = formatToolStatusParams(summary);
249+
const statusLine = `${chalk("✧")} ${chalk(formatStatusName(summary.name))}${params ? ` ${chalk(params)}` : ""}`;
238250

239251
const metaResultMd = typeof message.meta?.resultMd === "string" ? message.meta.resultMd.trim() : "";
240252
const result = metaResultMd ? `\n${chalk.dim(" └ Result")}\n${metaResultMd}` : "";
241253

242-
const summary: ToolSummary = {
243-
name,
244-
params,
245-
ok: payload.ok !== false,
246-
metadata: payload.metadata,
247-
};
248254
const planLines = getUpdatePlanPreviewLines(summary);
249255
if (planLines.length > 0) {
250256
const planText = planLines.map((line) => ` ${line}`).join("\n");

0 commit comments

Comments
 (0)