import { useMemo, useState, type JSX } from "react"; import { translate } from "../../../../../i18n/index"; import { workspaceFilePathBasename } from "../../../../../actions/workspaceFilePathCandidate"; import { AgentPathTailLabel } from "../AgentPathTailLabel"; const MAX_VISIBLE_LINES = 120; export function AgentCodeBlock({ path, content, language, showHeader = true, collapsible = false, flat = false }: { path?: string | null; content: string; language?: string | null; showHeader?: boolean; collapsible?: boolean; flat?: boolean; }): JSX.Element { "use memo"; const [expanded, setExpanded] = useState(false); const normalized = content.trimEnd(); const isEmpty = !normalized; const emptyPlaceholder = translate( "agentHost.agentGui.codeBlockEmptyContent" ); const lines = useMemo( () => (isEmpty ? [] : normalized.split("\n")), [isEmpty, normalized] ); const lineCount = lines.length; const truncated = collapsible && !expanded && lineCount > MAX_VISIBLE_LINES; const visibleContent = truncated ? lines.slice(0, MAX_VISIBLE_LINES).join("\n") : isEmpty ? emptyPlaceholder : normalized; const visibleLines = useMemo( () => (truncated ? lines.slice(0, MAX_VISIBLE_LINES) : lines).map( (line, lineIndex) => ({ key: `${lineIndex + 1}:${line}`, line, lineNumber: lineIndex + 1 }) ), [lines, truncated] ); const addedCount = lineCount; const fileLabel = fileNameFromPath(path) ?? path ?? "Code"; const disclosureButton = collapsible && lineCount > MAX_VISIBLE_LINES ? ( ) : null; return (
{flat ? ( <> {showHeader ? (
{fileLabel} {addedCount > 0 ? ( +{addedCount} ) : null}
) : null}
{isEmpty ? (
                {emptyPlaceholder}
              
) : ( <> {visibleLines.map((line) => (
{line.lineNumber}
                      {line.line || " "}
                    
))} {disclosureButton} )}
) : ( <> {showHeader ? (
{language ? `${language} ยท ` : ""} {lineCount} lines
) : null}
            {visibleContent}
          
{disclosureButton} )}
); } function fileNameFromPath(path: string | null | undefined): string | null { if (!path) { return null; } const normalized = path.trim(); if (!normalized) { return null; } return workspaceFilePathBasename(normalized) || normalized; }