import { isConnectedMachineOutcomeUnknownOutput, type GitFileDiff } from "@opengeni/sdk"; import { stringifyPayload, tryParseJson } from "../lib/format"; import { applyPatchOpsFromToolItem, controlCaret, execTruncated, isExecSessionLostBanner, looksBinary, parseExecBannerSessionId, parseToolArgs, retainedToolResultImages, sandboxCommandExitCode, stripExecBanner, tailPeek, unwrapMcpOutput, v4aToGitFileDiff, type ApplyPatchOperation, } from "./parsers"; import { invokedToolCall } from "./invoked-tool"; import { rawTypeOf } from "./registry"; import { mcpToolLeaf, toolDisplayName } from "./tool-display-name"; import { builtInToolStep, toolStepLabel, toolStepPhase, type ToolStepId, type ToolStepPhase, } from "./tool-steps"; import type { ToolCallItem } from "./types"; import { type OpenGeniText } from "../messages/runtime"; /* ---------------------------------------------------------------------------- Tool row presentation model (renderer-neutral) The collapsed-row decisions every tool renderer makes — icon, tint, title, preview, settle chip and what the expanded body holds — expressed as plain data so DOM and non-DOM renderers draw the same row from one source of truth. Web renderers consume these functions; a change here changes every surface. -------------------------------------------------------------------------- */ export type ToolIconKind = | "terminal" | "keyboard" | "file-diff" | "search" | "question" | "target" | "brain" | "sessions" | "server" | "server-cog" | "calendar" | "panels" | "share" | "message" | "git" | "box" | "key" | "file-search" | "package-search" | "plug" | "browser" | "screen" | "spreadsheet" | "wait" | "download" | "clipboard" | "image" | "video" | "record" | "document" | "file" | "attachment" | "archive" | "folder" | "site" | "guide" | "settings" | "bell" | "inbox" | "help" | "model" | "progress" | "helper" | "sign-in" | "code" | "accounting" | "rename" | "wrench"; export type ToolIconTone = "accent" | "failed" | "running" | "muted"; export type ToolChip = { tone: "ok" | "bad" | "muted" | "interrupted"; text: string; }; /** The collapsed-row secondary line. `running` previews carry the pulse locus. */ export type ToolPreview = | { kind: "text"; text: string; running?: boolean | undefined } | { kind: "path"; path: string; add?: number | undefined; del?: number | undefined; } | { kind: "files"; count: number; add: number; del: number } | { kind: "malformed"; name: string }; export type ToolPatchFile = { key: string; path: string; file: GitFileDiff | null; diff: string; }; export type WebSearchResult = { title: string; domain: string; snippet: string; }; /** What the expanded body holds; renderers draw these with their own primitives. */ export type ToolBody = | { kind: "term"; command: string | null; workdir: string | null; output: string; live?: boolean | undefined; failed?: boolean | undefined; note?: string | undefined; } | { kind: "note"; text: string; tone?: "error" | undefined } | { kind: "payloads"; /** A short explanation above the payloads. */ note?: string | undefined; blocks: Array<{ label: string; value: unknown; failed?: boolean }>; } | { kind: "patch"; files: ToolPatchFile[]; /** A single malformed op renders its raw patch without the path caption. */ bare?: boolean | undefined; } | { kind: "web-results"; results: WebSearchResult[] | null } | { /** A short labelled listing (disclosed tools, search hits) above payloads. */ kind: "listing"; note?: string | undefined; entries: ToolListingEntry[]; /** Entries beyond the visible list ("+N more"). */ more?: number | undefined; /** Shown instead of the list when it is known to be empty. */ empty?: string | undefined; blocks: Array<{ label: string; value: unknown; failed?: boolean }>; } /** Nothing to expand: the row says everything a person needs. */ | { kind: "none" }; export type ToolListingEntry = { key: string; title: string; /** Quiet leading label (the tool's server). */ eyebrow?: string | null | undefined; mono?: boolean | undefined; /** Secondary text under the title (a search snippet). */ snippet?: string | undefined; }; export type PresentedToolKind = | "exec" | "write_stdin" | "apply_patch" | "web_search" | "ask" | "run_on" | "tool_search" | "docs_search" | "session_title" | "machine" | "generic"; export type ToolRowPresentation = { tool: PresentedToolKind; icon: ToolIconKind; iconTone: ToolIconTone; title: string; titleMono?: boolean | undefined; running?: boolean | undefined; preview?: ToolPreview | undefined; chip?: ToolChip | undefined; failed?: boolean | undefined; cancelled?: boolean | undefined; /** * The preview quotes raw tool detail (command output, an error payload, tool * names), so plain rows leave it out. */ detailPreview?: boolean | undefined; body: ToolBody; }; /** * How much of a tool call a row shows. `full` (the default) shows commands, * arguments, output and diffs; `plain` shows only the plain step, its status * and human-readable results, never raw arguments, output or JSON. */ export type ToolDetails = "full" | "plain"; export type ToolPresentationContext = { /** Host-supplied active compute label ("on