import type { Readable } from "node:stream"; export declare const MAX_PERSISTED_TOOL_TEXT_CHARS = 40000; export declare const COLD_SESSION_AGE_DAYS = 7; export declare const SESSION_GZIP_VERSION = 1; export declare const SESSION_REDIRECT_VERSION = 1; export declare const SESSION_MEDIA_MARKER_VERSION = 1; export declare const SESSION_PLAIN_SUFFIX = ".jsonl"; export declare const SESSION_ARCHIVE_SUFFIX = ".jsonl.gz"; export declare const SESSION_ASSET_SUFFIX = ".jsonl.assets"; export declare const SESSION_TEMP_MARKER = ".gg-session-tmp-"; declare const REDIRECT_TYPE = "gg_session_redirect"; export interface SessionRedirect { type: typeof REDIRECT_TYPE; version: typeof SESSION_REDIRECT_VERSION; target: string; } export interface StorageNormalizationMetrics { truncatedToolTexts: number; externalizedMedia: number; omittedPathMedia: number; removedDisplayItems: number; } export interface ArchiveSessionResult extends StorageNormalizationMetrics { archived: boolean; sourceBytes: number; archiveBytes: number; bytesSaved: number; path: string; } export declare function emptyStorageNormalizationMetrics(): StorageNormalizationMetrics; export declare function isSessionPath(filePath: string): boolean; export declare function isSessionTempPath(filePath: string): boolean; export declare function plainSessionPath(filePath: string): string; export declare function archiveSessionPath(filePath: string): string; export declare function sessionAssetDir(filePath: string): string; export declare function sessionGroupPaths(filePath: string): { plainPath: string; archivePath: string; assetsPath: string; }; export declare function temporarySiblingPath(filePath: string): string; export declare function resolveSessionPath(filePath: string): Promise; export declare function isGzipSessionPath(filePath: string): Promise; /** * Open a session transcript for reading, transparently gunzipping archives. * * Returns `close()` alongside the stream because tearing down a gzip read is a * trap: `source.pipe(gunzip)` leaves the source unreachable, and `.pipe()` does * NOT propagate destroy() upstream. Destroying only the returned stream — the * intuitive cleanup — severs the pipe before the source can be torn down and * orphans its file descriptor forever. * * Measured on the shipped Node 22.12 runtime, 100 partial reads: * destroy(gunzip) only ....... 10 leaked fds * destroy(gunzip) + source ... 0 leaked fds * * A bare `break` out of `for await` is safe on its own (readline's iterator * return() tears down the whole chain), but any explicit teardown must go * through `close()` so both ends are destroyed together. Callers that stop * early should always call it; destroy() is idempotent, so calling it after a * natural end-of-stream is harmless. */ export declare function openSessionReadStream(filePath: string): Promise<{ path: string; stream: Readable; close: () => void; }>; export declare function thawSessionArchive(filePath: string): Promise; export declare function normalizeSessionEntryForStorage(entry: T, sessionPath: string, metrics?: StorageNormalizationMetrics): Promise; export declare function hydrateSessionEntry(entry: T, sessionPath: string): Promise; export declare function archiveColdSession(sessionPath: string): Promise; export declare function cleanupOldSessionTemps(directory: string, olderThanMs: number): Promise<{ deletedFiles: number; freedBytes: number; }>; export {}; //# sourceMappingURL=session-storage.d.ts.map