/** * Session lineage verification. * * Pure functions for hashing messages and classifying mutations * (continuation, compaction, undo, diverged). */ /** Token usage counters from the SDK (subset of Anthropic usage object). */ export interface TokenUsageIteration { input_tokens?: number; output_tokens?: number; cache_read_input_tokens?: number; cache_creation_input_tokens?: number; type?: string; } /** Token usage counters from the SDK, including optional iteration breakdowns. */ export interface TokenUsage extends TokenUsageIteration { iterations?: TokenUsageIteration[]; } /** Return the effective current-context usage snapshot. * When `iterations` is present and non-empty, returns the last entry; * otherwise returns the original top-level usage object. */ export declare function normalizeContextUsage(usage: TokenUsage): TokenUsageIteration; /** Minimum suffix overlap (stored messages found at the end of incoming) * required to classify a mutation as compaction rather than a branch. */ export declare const MIN_SUFFIX_FOR_COMPACTION = 2; export interface SessionState { claudeSessionId: string; lastAccess: number; messageCount: number; /** Hash of messages[0..messageCount-1] for fast-path lineage verification. * When the full prefix matches, the conversation is a strict continuation * and we skip the per-message diff entirely. */ lineageHash: string; /** Per-message content hashes from the last stored request. * Used for precise diff-based mutation classification when the aggregate * lineageHash mismatches. */ messageHashes?: string[]; /** SDK assistant message UUIDs indexed by message position. * Only assistant messages have UUIDs (user messages are null). * Used to find the rollback point for undo. */ sdkMessageUuids?: Array; /** Last observed token usage for this session (from SDK message_start / message_delta events) */ contextUsage?: TokenUsage; } /** * Result of lineage verification — classifies the mutation and provides * the information needed to take the correct SDK action. */ export type LineageResult = { type: "continuation"; session: SessionState; } | { type: "compaction"; session: SessionState; } | { type: "undo"; session: SessionState; prefixOverlap: number; rollbackUuid: string | undefined; } | { type: "diverged"; }; /** * Compute a lineage hash of an ordered message array. * Used as a fast-path check: if the aggregate hash matches, the messages * are an exact prefix-extension and we skip the per-message diff. */ export declare function computeLineageHash(messages: Array<{ role: string; content: any; }>): string; /** * Compute a content hash for a single message (role + normalised content). * Used to build per-message hash arrays for precise diff-based verification. */ export declare function hashMessage(message: { role: string; content: any; }): string; /** * Compute per-message hashes for an entire message array. */ export declare function computeMessageHashes(messages: Array<{ role: string; content: any; }>): string[]; /** * Measure how many stored hashes match from the START of the stored array * against the incoming hashes (positional comparison). * * Prefix overlap means the beginning of the conversation is intact (undo * changes the end but preserves the beginning). * * NOTE: Compares stored[i] === incoming[i] positionally. An earlier * implementation used a Set for O(1) lookups, but that allowed a stored * hash at position i to match an incoming hash at a completely different * position, inflating the overlap count when duplicate messages exist * in the conversation history. */ export declare function measurePrefixOverlap(storedHashes: string[], incomingHashes: string[]): number; /** * Measure how many consecutive messages at the END of the stored array * appear as a contiguous run in the incoming array. * * Suffix overlap means the recent conversation is intact (compaction * changes the beginning but preserves the end). * * Algorithm: find the last stored hash in the incoming array, then walk * backward through both arrays verifying contiguous matches. This handles * the real-world compaction pattern where new messages are appended AFTER * the preserved suffix. * * NOTE: An earlier implementation used a Set for O(1) lookups, but that * allowed a stored suffix hash to match an incoming hash at a completely * different position — producing false compaction when duplicate messages * exist in the conversation. The current approach verifies positional * contiguity. */ export declare function measureSuffixOverlap(storedHashes: string[], incomingHashes: string[]): number; /** Cache-like interface for verifyLineage — only needs get/set/delete */ export interface SessionCacheLike { delete(key: string): boolean; } /** * Verify that incoming messages are a valid continuation of a cached session. * Uses per-message hash comparison to deterministically classify mutations. * * Decision matrix: * Full prefix match (fast-path) → continuation (resume normally) * Suffix overlap >= MIN_SUFFIX → compaction (resume normally) * Prefix overlap > 0, no suffix → undo (fork at rollback point) * No overlap → diverged (start fresh) */ export declare function verifyLineage(cached: SessionState, messages: Array<{ role: string; content: any; }>, cacheKey: string, cache: SessionCacheLike): LineageResult; //# sourceMappingURL=lineage.d.ts.map