import { VSBuffer } from "@codingame/monaco-vscode-api/vscode/vs/base/common/buffer"; /** IMPORTANT: `Key` comes first. Then we should sort in order of least->most expensive to diff */ declare enum TransformKind { Key = 0, Primitive = 1, Array = 2, Object = 3 } /** Schema entries sorted with key properties first */ export type SchemaEntries = [ string, Transform ][]; interface TransformBase { readonly kind: TransformKind; /** Extracts the serializable value from the source object */ extract(from: TFrom): TTo; } /** Transform for primitive values (keys and values) that can be compared for equality */ export interface TransformValue extends TransformBase { readonly kind: TransformKind.Key | TransformKind.Primitive; /** Compares two serialized values for equality */ equals(a: TTo, b: TTo): boolean; } /** Transform for arrays with an item schema */ export interface TransformArray extends TransformBase { readonly kind: TransformKind.Array; /** The schema for array items */ readonly itemSchema: TransformObject | TransformValue; } /** Transform for objects with child properties */ export interface TransformObject extends TransformBase { readonly kind: TransformKind.Object; /** Schema entries sorted with Key properties first */ readonly children: SchemaEntries; /** Checks if the object is sealed (won't change). */ sealed?(obj: TTo, wasSerialized: boolean): boolean; } export type Transform = TransformValue | TransformArray | TransformObject; export type Schema = { [K in keyof Required]: Transform; }; /** * A primitive that will be tracked and compared first. If this is changed, the entire * object is thrown out and re-stored. */ export declare function key(comparator?: (a: R, b: R) => boolean): TransformValue; /** A value that will be tracked and replaced if the comparator is not equal. */ export declare function value(): TransformValue; export declare function value(comparator: (a: R, b: R) => boolean): TransformValue; /** An array that will use the schema to compare items positionally. */ export declare function array(schema: TransformObject | TransformValue): TransformArray; export interface ObjectOptions { /** * Returns true if the object is sealed and will never change again. * When comparing two sealed objects, only key fields are compared * (to detect replacement), but other fields are not diffed. */ sealed?: (obj: R, wasSerialized: boolean) => boolean; } /** An object schema. */ export declare function object(schema: Schema, options?: ObjectOptions): TransformObject; /** * Defines a getter on the object to extract a value, compared with the given schema. * It should return the value that will get serialized in the resulting log file. */ export declare function t(getter: (obj: T) => O, schema: Transform): Transform; /** Shortcut for t(fn, value()) */ export declare function v(getter: (obj: T) => R): TransformValue; export declare function v(getter: (obj: T) => R, comparator: (a: R, b: R) => boolean): TransformValue; /** * Per-string cap (in UTF-16 code units, matching `string.length`) applied when * {@link stringifyEntryWithFallback} retries after `JSON.stringify` throws * `RangeError: Invalid string length` (V8's max string length is ~512 MiB on * 64-bit). Any single string longer than this is replaced with a marker on * retry. Generous so it triggers only on outliers. */ export declare const PERSIST_ENTRY_MAX_STRING_CHARS: number; /** * Total-size budget (sum of `string.length` for tracked strings, in UTF-16 * code units) for the retry of {@link stringifyEntryWithFallback}. Once the * cumulative tracked size during serialization exceeds this, remaining values * are replaced with a marker. * * This is an approximation: JSON escaping, property keys, and non-string * payload are not counted, so the actual output may be moderately larger. * The cap is sized well under V8's max string length to leave ample headroom * for that overhead. */ export declare const PERSIST_ENTRY_MAX_TOTAL_CHARS: number; /** * Wraps `JSON.stringify(entry)` with a safety net for the V8 max-string-length * limit. The common path is a single `JSON.stringify` with zero overhead. If * stringification throws `RangeError` (the resulting JSON would exceed V8's * ~512 MiB max string length — see microsoft/vscode#308843), retry with a * replacer that truncates oversized strings. Extensions sometimes put very * large content (browser dumps, command output, …) into chat result metadata; * losing the tail of one such value is dramatically better than losing the * entire chat session. */ export declare function stringifyEntryWithFallback(entry: unknown): string; /** * Deep-clones `value` through JSON with the same V8 max-string-length safety net * as {@link stringifyEntryWithFallback}. Exported for testing only. */ export declare function deepCloneWithFallback(value: T): T; /** * Exported for testing only. Builds the stateful `JSON.stringify` replacer * used by {@link stringifyEntryWithFallback} on its retry path. * * Sizes are tracked in UTF-16 code units (`string.length`); JSON escaping, * property keys, and non-string payload are not counted. */ export declare function makeTruncatingReplacer(maxStringChars: number, maxTotalChars: number): (key: string, value: unknown) => unknown; /** * An implementation of an append-based mutation logger. Given a `Transform` * definition of an object, it can recreate it from a file on disk. It is * then stateful, and given a `write` call it can update the log in a minimal * way. */ export declare class ObjectMutationLog { private readonly _transform; private readonly _compactAfterEntries; private _previous; private _entryCount; private _hasPendingWrite; private _pendingPrevious; private _pendingEntryCount; constructor(_transform: Transform, _compactAfterEntries?: number); /** * Creates an initial log file from the given object. */ createInitial(current: TFrom): VSBuffer; /** * Creates an initial log file from the serialized object. * * Unlike {@link write}, this commits state immediately without requiring * {@link confirmWrite}. This is safe because the returned buffer contains * a self-contained `Initial` entry — if it fails to persist, no * incremental entries can be appended to a non-existent file. */ createInitialFromSerialized(value: TTo): VSBuffer; /** * Reads and reconstructs the state from a log file. */ read(content: VSBuffer): TTo; /** * Writes updates to the log. Returns the operation type and data to write. * The caller **must** invoke {@link confirmWrite} after the data is * successfully persisted to commit the internal state. Without confirmation, * the next write is computed against the last confirmed state, and will only * produce a full initial entry when no confirmed state exists, preventing * corrupted log files when a write fails. */ write(current: TFrom): { op: "append" | "replace"; data: VSBuffer; }; /** * Commits the internal state after a successful write to disk. */ confirmWrite(): void; private _clearPending; private _applySet; private _applyPush; private _diff; private _diffObject; private _diffArray; private _hasKeyMismatch; } export {};