import { For, Show, createMemo } from "solid-js" import type { ToolRenderer } from "../types" import { getRelativePath, getToolName, isToolStateCompleted, readToolStatePayload } from "../utils" import { buildDiagnosticEntries, type DiagnosticEntry, type DiagnosticsMap } from "../diagnostics" type ApplyPatchFile = { filePath?: string relativePath?: string type?: string diff?: string patch?: string } function DiagnosticsInline(props: { entries: DiagnosticEntry[]; label: string; t: (key: string, params?: Record) => string }) { return ( 0}>
{(entry) => (
{entry.icon} {entry.label} {entry.displayPath} :L{entry.line || "-"}:C{entry.column || "-"} {entry.message}
)}
) } export const applyPatchRenderer: ToolRenderer = { tools: ["apply_patch"], getAction: ({ t }) => t("toolCall.applyPatch.action.preparing"), getTitle({ toolState, t }) { const state = toolState() if (!state) return undefined if (state.status === "pending") return getToolName("apply_patch") const { metadata } = readToolStatePayload(state) const files = Array.isArray((metadata as any).files) ? ((metadata as any).files as ApplyPatchFile[]) : [] if (files.length > 0) { const tool = getToolName("apply_patch") return files.length === 1 ? t("toolCall.applyPatch.title.withFileCount.one", { tool, count: files.length }) : t("toolCall.applyPatch.title.withFileCount.other", { tool, count: files.length }) } return getToolName("apply_patch") }, renderBody({ toolState, renderDiff, renderMarkdown, t }) { const state = toolState() if (!state || state.status === "pending") return null const payload = readToolStatePayload(state) const files = createMemo(() => { const list = (payload.metadata as any).files return Array.isArray(list) ? (list as ApplyPatchFile[]) : [] }) const diagnosticsMap = createMemo(() => { const value = (payload.metadata as any).diagnostics return value && typeof value === "object" ? (value as DiagnosticsMap) : {} }) if (files().length === 0) { const fallback = isToolStateCompleted(state) && typeof state.output === "string" ? state.output : null if (!fallback) return null return renderMarkdown({ content: fallback, size: "large", disableHighlight: state.status === "running" }) } return (
{(file, index) => { const labelBase = file.relativePath || file.filePath || t("toolCall.applyPatch.fileFallback", { number: index() + 1 }) const diffText = typeof file.diff === "string" ? file.diff : typeof file.patch === "string" ? file.patch : "" const filePath = typeof file.filePath === "string" ? file.filePath : file.relativePath const entries = createMemo(() => buildDiagnosticEntries(diagnosticsMap(), [file.filePath, file.relativePath])) return (
0}> {renderDiff( { diffText, filePath }, { label: t("toolCall.diff.label.withPath", { path: getRelativePath(labelBase) }), cacheKey: `apply_patch:${labelBase}:${index()}`, }, )}
) }}
) }, }