feat: align TaskOutput UX with Bash output (#1029)

This commit is contained in:
Charles Packer
2026-02-18 22:53:41 -08:00
committed by GitHub
parent 674e8c12c2
commit 47e81433ff
9 changed files with 266 additions and 44 deletions

View File

@@ -21,7 +21,7 @@ import {
isPatchTool,
isPlanTool,
isSearchTool,
isShellTool,
isShellOutputTool,
isTaskTool,
isTodoTool,
} from "../helpers/toolNameMapping.js";
@@ -192,7 +192,12 @@ export const ToolCallMessage = memo(
const truncatedDisplay = needsTruncation
? `${normalizedDisplay.slice(0, maxArgsChars - 1)}`
: normalizedDisplay;
args = `(${truncatedDisplay})`;
if (rawName.toLowerCase() === "taskoutput") {
const separator = truncatedDisplay.startsWith("(") ? "" : " ";
args = separator + truncatedDisplay;
} else {
args = `(${truncatedDisplay})`;
}
}
}
@@ -850,16 +855,21 @@ export const ToolCallMessage = memo(
</Box>
{/* Streaming output for shell tools during execution */}
{isShellTool(rawName) && line.phase === "running" && line.streaming && (
<StreamingOutputDisplay streaming={line.streaming} />
)}
{isShellOutputTool(rawName) &&
line.phase === "running" &&
line.streaming && (
<StreamingOutputDisplay streaming={line.streaming} />
)}
{/* Collapsed output for shell tools after completion */}
{isShellTool(rawName) &&
{isShellOutputTool(rawName) &&
line.phase === "finished" &&
line.resultText &&
line.resultOk !== false && (
<CollapsedOutputDisplay output={line.resultText} maxChars={300} />
<CollapsedOutputDisplay
output={extractMessageFromResult(line.resultText)}
maxChars={300}
/>
)}
{/* Tool result for non-shell tools or shell tool errors */}
@@ -869,7 +879,7 @@ export const ToolCallMessage = memo(
// - Shell tool with error (show error message)
// - Shell tool in streaming/ready phase (show default "Running..." etc)
const showDefaultResult =
!isShellTool(rawName) ||
!isShellOutputTool(rawName) ||
(line.phase === "finished" && line.resultOk === false) ||
(line.phase !== "running" && line.phase !== "finished");
return showDefaultResult ? getResultElement() : null;

View File

@@ -16,7 +16,7 @@ import { extractCompactionSummary } from "./backfill";
import type { ContextTracker } from "./contextTracker";
import { MAX_CONTEXT_HISTORY } from "./contextTracker";
import { findLastSafeSplitPoint } from "./markdownSplit";
import { isShellTool } from "./toolNameMapping";
import { isShellOutputTool } from "./toolNameMapping";
type CompactionSummaryMessageChunk = {
message_type: "summary_message";
@@ -1207,7 +1207,7 @@ export function setToolCallsRunning(b: Buffers, toolCallIds: string[]): void {
const line = b.byId.get(lineId);
if (line && line.kind === "tool_call") {
const shouldSeedStreaming =
line.name && isShellTool(line.name) && !line.streaming;
line.name && isShellOutputTool(line.name) && !line.streaming;
b.byId.set(lineId, {
...line,
phase: "running",

View File

@@ -272,6 +272,14 @@ export function formatArgsDisplay(
return { display, parsed };
}
// TaskOutput: show task id with optional non-blocking marker
if (toolName.toLowerCase() === "taskoutput" && parsed.task_id) {
const taskId = String(parsed.task_id);
const isNonBlocking = parsed.block === false;
display = isNonBlocking ? `(non-blocking) ${taskId}` : taskId;
return { display, parsed };
}
// Shell/Bash tools: show just the command
if (isShellTool(toolName) && parsed.command) {
// Handle both string and array command formats

View File

@@ -68,9 +68,8 @@ export function getDisplayToolName(rawName: string): string {
if (rawName === "Replace" || rawName === "replace") return "Update";
if (rawName === "WriteFile" || rawName === "write_file") return "Write";
if (rawName === "KillBash") return "Kill Bash";
if (rawName === "BashOutput" || rawName === "TaskOutput") {
return "Shell Output";
}
if (rawName === "BashOutput") return "Shell Output";
if (rawName === "TaskOutput") return "Task Output";
if (rawName === "MultiEdit") return "Update";
// No mapping found, return as-is
@@ -215,6 +214,15 @@ export function isShellTool(name: string): boolean {
);
}
/**
* Checks if a tool should use shell-style streaming output rendering.
* Includes shell command tools plus TaskOutput/BashOutput pollers.
*/
export function isShellOutputTool(name: string): boolean {
const n = name.toLowerCase();
return isShellTool(name) || n === "taskoutput" || n === "bashoutput";
}
/**
* Checks if a tool is a search/grep tool
*/