import { memo } from "react"; import { ArrowRight, ArrowLeft, AlertCircle, Loader2, FileText, } from "lucide-react"; import type { ToolPart } from "../types/parts"; import { getToolDisplayMetadata } from "../utils/tool-display"; import { CommandPreview } from "../tool-previews/command-preview"; import { WriteFilePreview } from "../tool-previews/write-file-preview"; import { CodeBlock } from "../markdown/code-block"; import { GrepResultsPreview } from "../tool-previews/grep-results-preview"; import { GlobResultsPreview } from "../tool-previews/glob-results-preview"; import { WebSearchPreview } from "../tool-previews/web-search-preview"; import { QuestionPreview } from "../tool-previews/question-preview"; import { DiffPreview } from "../tool-previews/diff-preview"; import { cn } from "../lib/utils"; import { ExpandableContent } from "./expandable-content"; export interface ExpandedToolDetailProps { part: ToolPart; } const EXT_LANG: Record = { ts: "typescript", tsx: "tsx", js: "javascript", jsx: "jsx", rs: "rust", py: "python", go: "go", rb: "ruby", json: "json", yaml: "yaml", yml: "yaml", toml: "toml", md: "markdown", css: "css", scss: "scss", html: "html", sh: "bash", bash: "bash", zsh: "bash", sql: "sql", sol: "solidity", proto: "protobuf", }; function langFromPath(path?: string): string | undefined { if (!path) return undefined; const ext = path.split(".").pop()?.toLowerCase(); return ext ? EXT_LANG[ext] : undefined; } /** Format an unknown value as a displayable string. */ function formatOutput(value: unknown): string { if (value == null) return ""; if (typeof value === "string") return value; try { return JSON.stringify(value, null, 2); } catch { return String(value); } } /** * Renders full tool details when a tool item is expanded. * Dispatches to specialised previews (CommandPreview, WriteFilePreview) * or falls back to a generic input/output code view. */ export const ExpandedToolDetail = memo(({ part }: ExpandedToolDetailProps) => { const meta = getToolDisplayMetadata(part); const { status, input, output, error } = part.state; // Specialised previews if (meta.displayVariant === "command") { return ; } if (meta.displayVariant === "write-file") { return ; } if (meta.displayVariant === "grep") { return ; } if (meta.displayVariant === "glob") { return ; } if (meta.displayVariant === "web-search") { return ; } if (meta.displayVariant === "question") { return ; } if (meta.displayVariant === "diff") { return ; } if (meta.displayVariant === "read-file") { return (
Read file {meta.targetPath ? ( {meta.targetPath} ) : null}
{typeof output === "string" ? ( ) : (
No readable file content was returned.
)} {error ? (
{error}
) : null}
); } // Generic fallback — show input/output/error const inputStr = formatOutput(input); const outputStr = formatOutput(output); return (
{/* Input */} {inputStr && (
Input
)} {/* Output */} {status === "completed" && outputStr && (
Output
2000 ? outputStr.slice(0, 2000) + "\n...(truncated)" : outputStr } language="json" className="rounded-none border-0" />
)} {/* Error */} {error && (
Error
              {error}
            
)} {/* Running state */} {(status === "pending" || status === "running") && (
Running…
)}
); }); ExpandedToolDetail.displayName = "ExpandedToolDetail";