/** * Edit tool renderer and LSP batching helpers. */ import type { Component } from "@gajae-code/tui"; import type { RenderResultOptions } from "../extensibility/custom-tools/types"; import type { FileDiagnosticsResult } from "../lsp"; import { type Theme } from "../modes/theme/theme"; import type { OutputMeta } from "../tools/output-meta"; import { getLspBatchRequest, type LspBatchRequest } from "../tools/render-utils"; import { type VimRenderArgs } from "../tools/vim"; import type { EditMode } from "../utils/edit-mode"; import type { DiffError, DiffResult } from "./diff"; import type { Operation } from "./modes/patch"; import { type PerFileDiffPreview } from "./streaming"; export { getLspBatchRequest, type LspBatchRequest }; export interface EditToolPerFileResult { path: string; diff: string; firstChangedLine?: number; diagnostics?: FileDiagnosticsResult; op?: Operation; move?: string; isError?: boolean; errorText?: string; /** TUI-friendly error text. When present, rendered to the user instead of `errorText`. * Set when the underlying error carries a `displayMessage` (e.g. {@link HashlineMismatchError}). */ displayErrorText?: string; meta?: OutputMeta; /** Source-of-truth content before the edit; `undefined` for create operations. */ oldText?: string; /** Source-of-truth content after the edit; `undefined` for delete operations. */ newText?: string; } export interface EditToolDetails { /** Unified diff of the changes made */ diff: string; /** Line number of the first change in the new file (for editor navigation) */ firstChangedLine?: number; /** Diagnostic result (if available) */ diagnostics?: FileDiagnosticsResult; /** Operation type (patch mode only) */ op?: Operation; /** New path after move/rename (patch mode only) */ move?: string; /** Structured output metadata */ meta?: OutputMeta; /** Per-file results (multi-file edits) */ perFileResults?: EditToolPerFileResult[]; /** Absolute file path for single-file edit results. Required by ACP diff metadata consumers. */ path?: string; /** Source-of-truth content before the edit; `undefined` for create operations. */ oldText?: string; /** Source-of-truth content after the edit; `undefined` for delete operations. */ newText?: string; } /** * Bounded durable identity of one edit snapshot (#4566). * * Live edit results carry full `oldText`/`newText` file bodies so in-process * consumers (ACP `diff` ToolCallContent, editors) keep working. Every persisted * transcript entry replaces those bodies with this fixed-size receipt: byte * length plus SHA-256 content digest, enough to detect source drift and to * account for the edit durably without re-writing the whole file per edit. */ export interface EditSnapshotReceipt { /** UTF-8 byte length of the snapshot (`0` for create/delete-absent sides). */ bytes: number; /** SHA-256 hex digest of the exact snapshot text (empty string for length 0). */ sha256: string; } /** Per-edit-mode cap on any single persisted edit-result string field (#4566). */ export declare const EDIT_PERSIST_FIELD_MAX_CHARS: number; /** Fixed marker used when a snapshot receipt replaces a full body. */ export declare const EDIT_SNAPSHOT_EXTERNALIZED_NOTICE = "[edit snapshot externalized: see oldTextDigest/newTextDigest; full body omitted from transcript]"; /** Build the bounded durable receipt for one snapshot body. */ export declare function editSnapshotReceipt(text: string | undefined): EditSnapshotReceipt | undefined; /** True when a snapshot body is small enough to persist inline without amplification. */ export declare function editSnapshotPersistableInline(text: string | undefined): boolean; export interface EditRenderArgs { path?: string; file_path?: string; oldText?: string; newText?: string; patch?: string; input?: string; all?: boolean; op?: Operation; rename?: string; diff?: string; /** * Computed preview diff (used when tool args don't include a diff, e.g. hashline mode). */ previewDiff?: string; __partialJson?: string; edits?: EditRenderEntry[]; } type EditRenderEntry = { path?: string; rename?: string; move?: string; op?: Operation; firstChangedLine?: number; }; /** Extended context for edit tool rendering */ export interface EditRenderContext { /** Edit mode resolved by the caller; lets the renderer dispatch without shape-sniffing */ editMode?: EditMode; /** Pre-computed diff preview (computed before tool executes) */ editDiffPreview?: DiffResult | DiffError; /** Multi-file streaming diff preview (edits spanning several files) */ perFileDiffPreview?: PerFileDiffPreview[]; /** Raw in-flight edit text shown while a computed diff preview is unavailable */ editStreamingFallback?: string; /** Function to render diff text with syntax highlighting */ renderDiff?: (diffText: string, options?: { filePath?: string; }) => string; } export declare const editToolRenderer: { mergeCallAndResult: boolean; renderCall(args: EditRenderArgs | VimRenderArgs, options: RenderResultOptions & { renderContext?: EditRenderContext; }, uiTheme: Theme): Component; renderResult(result: { content: Array<{ type: string; text?: string; }>; details?: EditToolDetails; isError?: boolean; }, options: RenderResultOptions & { renderContext?: EditRenderContext; }, uiTheme: Theme, args?: EditRenderArgs): Component; }; export declare function getPerFileEditRenderArgs(args: EditRenderArgs | undefined, path: string, editMode: EditMode | undefined): EditRenderArgs | undefined; export declare function getPerFileEditRenderContext(renderContext: EditRenderContext | undefined, path: string): EditRenderContext | undefined;