import type { Telemetry } from '../utils/telemetry.ts'; import type { Snapshot } from './Snapshot.ts'; export interface CacheDependency { depKey: string; depVersion: string; } export interface CacheEntry { value: Value; deps: CacheDependency[]; fingerprint: string; persist: boolean; updatedAt: number; workspaceChangeToken?: string | null; } export interface CacheDependencyEvictionResult { deletedNodeKeys: string[]; usedDependencyIndex: boolean; hasMissingDependencyMetadata: boolean; missingDependencyNodeKeys?: string[]; invalidationSeq?: number; invalidationMode?: 'structured'; } export interface CacheStorePersistence { load(nodeKey: string, options?: { skipFingerprintCheck?: boolean; skipLastAccessedUpdate?: boolean; includeValue?: boolean; includeDeps?: boolean; }): Promise; save(nodeKey: string, entry: CacheEntry): Promise; saveWithRevision?(nodeKey: string, entry: CacheEntry): Promise; saveWithRevisionGuarded?(nodeKey: string, entry: CacheEntry, options: { expectedRevision: number | 'missing'; }): Promise<{ applied: boolean; revision: number; }>; delete(nodeKey: string): Promise; deleteMany?(nodeKeys: string[]): Promise; deleteByDependencyPath?(dependencyPathKey: string): Promise; deleteByDependencyPaths?(dependencyPathKeys: string[]): Promise; listNodeKeysByPrefix?(prefix: string): Promise; /** * Returns whether persistence is currently usable. This may flip to `false` * when an optional backend (for example SQLite) fails to initialize. */ isAvailable?(): boolean; } export interface CacheStoreGetOrComputeOptions { persist?: boolean; constDeps?: CacheStoreConstDependency[]; signal?: AbortSignal; staleWhileRevalidate?: boolean | CacheStoreStaleWhileRevalidateOptions; onBackgroundRefreshComplete?: (context: CacheStoreBackgroundRefreshCompleteContext) => void | Promise; } export interface CacheStorePutOptions { persist?: boolean; deps?: CacheDependency[]; } export interface CacheStoreStaleWhileRevalidateOptions { /** * Maximum age of stale entries that can be served while a background * refresh runs. Defaults to the store's stale retention TTL. */ maxStaleAgeMs?: number; } export interface CacheStoreBackgroundRefreshCompleteContext { nodeKey: string; } export interface CacheStoreComputeContext { readonly snapshot: Snapshot; readonly signal?: AbortSignal; recordDep(depKey: string, depVersion: string): void; recordConstDep(name: string, version: string): void; disablePersist(): void; recordFileDep(path: string): Promise; recordDirectoryDep(path: string): Promise; recordNodeDep(nodeKey: string): Promise; } export declare function isDisposedCacheStoreError(error: unknown, operation?: string): boolean; export interface CacheStoreFreshnessMismatch { depKey: string; expectedVersion: string; currentVersion: string | undefined; } export interface CacheStoreGetWithFreshnessOptions { includeStaleReason?: boolean; recordNodeDependency?: boolean; } export interface CacheStoreGetWithFreshnessResult { value: Value | undefined; fresh: boolean; staleReason?: CacheStoreFreshnessMismatch | 'graph-dirty'; } export interface CacheStoreConstDependency { name: string; version: string; } export interface CacheStoreOptions { snapshot: Snapshot; persistence?: CacheStorePersistence; inflight?: Map>; telemetry?: Telemetry; computeSlotTtlMs?: number; computeSlotPollMs?: number; staleRetentionTtlMs?: number; persistedVerificationAttempts?: number; debugPersistenceFailure?: boolean; } export interface CacheOptions { persistence?: CacheStorePersistence; telemetry?: Telemetry; /** Optional base directory for persisted cache files. */ outputDirectory?: string; /** Enable cache metric collection for directory snapshots. */ cacheMetricsEnabled?: boolean; /** Maximum number of hot paths tracked when logging cache metrics. */ cacheMetricsTopKeysLimit?: number; /** Soft cap for hot-key tracking set size before trimming. */ cacheMetricsTopKeysTrackingLimit?: number; /** Number of events before emitting hot-key metrics. */ cacheMetricsTopKeysLogInterval?: number; /** TTL for cached workspace change tokens in milliseconds. Set to 0 to disable caching. */ workspaceChangeTokenTtlMs?: number; /** TTL for cached changed-path lookups in milliseconds. Set to 0 to disable caching. */ workspaceChangedPathsTtlMs?: number; /** TTL for recently invalidated paths cache in milliseconds. */ invalidatedPathTtlMs?: number; /** TTL for persisted compute slots in milliseconds. */ computeSlotTtlMs?: number; /** Poll interval for waiting on persisted compute slots in milliseconds. */ computeSlotPollMs?: number; /** TTL for stale cache entries retained for stale-while-revalidate reads. */ staleRetentionTtlMs?: number; /** Number of persisted read-back attempts after a write. Set to 0 to skip verification. */ persistedVerificationAttempts?: number; /** * Override for targeted missing dependency invalidation fallback behavior. * When omitted, Session keeps targeted fallback enabled. */ targetedMissingDependencyFallback?: boolean; /** * Override strict hermetic cache mode. * When omitted, file-system logic defaults to strict mode in production and CI. */ strictHermetic?: boolean; /** * Maximum number of prefix keys tracked by the directory snapshot path index. * Larger values use more memory but reduce fallback scans. */ directorySnapshotPrefixIndexMaxKeys?: number; /** Log detailed cache persistence failures during debugging. */ debugCachePersistence?: boolean; /** Enable debug logging related to cache root/path resolution. */ debugSessionRoot?: boolean; } interface CacheStoreFactoryOptions { snapshot: Snapshot; persistence?: CacheStorePersistence; inflight?: Map>; telemetry?: Telemetry; computeSlotTtlMs?: number; computeSlotPollMs?: number; staleRetentionTtlMs?: number; persistedVerificationAttempts?: number; debugPersistenceFailure?: boolean; } export declare function createMemoryOnlyCacheStore(options?: { id?: string; staleRetentionTtlMs?: number; telemetry?: Telemetry; }): CacheStore; export declare class Cache { readonly outputDirectory?: string; readonly telemetry?: Telemetry; readonly cacheMetricsEnabled: boolean; readonly cacheMetricsTopKeysLimit: number; readonly cacheMetricsTopKeysTrackingLimit: number; readonly cacheMetricsTopKeysLogInterval: number; readonly workspaceChangeTokenTtlMs: number; readonly workspaceChangedPathsTtlMs: number; readonly invalidatedPathTtlMs: number; readonly computeSlotTtlMs: number; readonly computeSlotPollMs: number; readonly staleRetentionTtlMs: number; readonly persistedVerificationAttempts: number; readonly targetedMissingDependencyFallback?: boolean; readonly strictHermetic?: boolean; readonly directorySnapshotPrefixIndexMaxKeys?: number; readonly persistence?: CacheStorePersistence; readonly debugCachePersistence: boolean; readonly debugSessionRoot: boolean; constructor(options?: CacheOptions); get usesPersistentCache(): boolean; createStore(options: CacheStoreFactoryOptions): CacheStore; } export declare class CacheStore { #private; constructor(options: CacheStoreOptions); get usesPersistentCache(): boolean; dispose(options?: { skipClearMemory?: boolean; }): void; getOrCompute(nodeKey: string, options: CacheStoreGetOrComputeOptions, compute: (context: CacheStoreComputeContext) => Promise | Value): Promise; refresh(nodeKey: string, options: CacheStoreGetOrComputeOptions, compute: (context: CacheStoreComputeContext) => Promise | Value): Promise; getFingerprint(nodeKey: string): Promise; get(nodeKey: string): Promise; /** * Return the latest cached value without running freshness checks. * Useful for development stale-first paths that revalidate asynchronously. */ getPossiblyStale(nodeKey: string): Promise; getWithFreshness(nodeKey: string, options?: CacheStoreGetWithFreshnessOptions): Promise>; put(nodeKey: string, value: Value, options?: CacheStorePutOptions): Promise; delete(nodeKey: string): Promise; deleteMany(nodeKeys: Iterable): Promise; deleteByDependencyPath(dependencyPathKey: string): Promise; deleteByDependencyPaths(dependencyPathKeys: Iterable): Promise; invalidateDependencyPath(dependencyPathKey: string): void; invalidateDependencyPaths(dependencyPathKeys: Iterable): void; listNodeKeysByPrefix(prefix: string): Promise; withComputeSlot(nodeKey: string, options: { leader: () => Promise; follower?: () => Promise; ttlMs?: number; }): Promise<'leader' | 'follower'>; hasSync(nodeKey: string): boolean; hasInFlight(nodeKey: string): boolean; getSync(nodeKey: string): Value | undefined; setSync(nodeKey: string, value: Value): void; getOrComputeSync(nodeKey: string, compute: () => Value): Value; deleteSync(nodeKey: string): void; clearMemory(): void; } export { hashString, stableStringify } from '../utils/stable-serialization.ts'; export declare function createFingerprint(dependencies: CacheDependency[]): string;