diff --git a/packages/web/src/features/chat/tool-call-card.tsx b/packages/web/src/features/chat/tool-call-card.tsx index 1206bfb..bfe544e 100644 --- a/packages/web/src/features/chat/tool-call-card.tsx +++ b/packages/web/src/features/chat/tool-call-card.tsx @@ -18,7 +18,6 @@ import { useMemo, useRef, useState } from "react"; import { S } from "../../lib/strings"; import { humanizeDuration } from "../../lib/format"; import { stripAnsi } from "../../lib/strip-ansi"; -import type { StopReason } from "@prismshadow/penguin-core/omnimessage"; import { approvalKey } from "../../lib/omni/stream-model"; import type { ToolCallItem } from "../../lib/omni/stream-model"; import { Chevron } from "../../components/ui/chevron"; @@ -42,18 +41,6 @@ const DESCRIBED_TOOLS = new Set([ /** The three file tools: previewed by their `file_path` argument. */ const FILE_TOOLS = new Set(["read_file", "edit_file", "write_file"]); -/** - * Colour for the row's `[stop reason]` marker: amber for a user interruption, red for a real - * failure. StatusIcon has a single failure tone, so the icon alone cannot carry this — without - * the marker an aborted call reads exactly like a failed one. Mirrors the warning-vs-error - * split `stopReasonTone` gives the Badge used elsewhere (Trace viewer, composer). - */ -function stopReasonToneClass(stopReason: string): string { - return stopReason === "aborted" - ? "text-amber-600 dark:text-amber-400" - : "text-red-600 dark:text-red-400"; -} - /** * Shortens a path for one-line display: at most one parent directory plus the filename * (`…/parent/file.ts`); paths already within that shape are shown as-is (same rule as the @@ -243,9 +230,9 @@ export function ToolCallCard({ item, ctx }: { item: ToolCallItem; ctx: StreamRen }` : null; // A user denial reports stop_reason "aborted" on the output it feeds back; that abort IS the - // decision, not an independent outcome — the icon reads "Denied", and no separate `[aborted]` - // marker repeats it. A user-abort of a RUNNING tool carries no deny decision, so the label - // falls through to its stop reason below. + // decision — the icon reads "Denied" rather than falling through to the raw stop reason. A + // user-abort of a RUNNING tool carries no deny decision, so the label falls through to its + // stop reason below. const deniedByUser = item.decision === "deny" && item.outputStopReason === "aborted"; const stateLabel = pending ? S.chat.approvalWaiting @@ -256,17 +243,6 @@ export function ToolCallCard({ item, ctx }: { item: ToolCallItem; ctx: StreamRen : deniedByUser ? (decisionText ?? undefined) : (item.outputStopReason ?? item.callStopReason); - // Stop reasons to spell out on the row. The two segments frequently carry the SAME value — - // a call that closed undispatched copies its own reason onto the output it will never - // produce (settleUndispatchedCall) — so equal values collapse to one marker instead of the - // `[malformed][malformed]` the two old pills rendered side by side. - const outcomes = [ - ...new Set( - [item.callStopReason, deniedByUser ? undefined : item.outputStopReason].filter( - (r): r is StopReason => r !== undefined && r !== "completed", - ), - ), - ]; return (