export type RuntimeSessionEvictReason = "idle_timeout" | "stale" | "replaced" | "disposed"; /** Public upper bound for opaque canonical-history version tokens. */ export declare const CONVERSATION_HISTORY_VERSION_MAX_BYTES = 512; export declare function assertConversationHistoryVersion(value: unknown): asserts value is string; export interface RuntimeSessionRecord { modelKey?: string; /** Process-local budget and one-shot boundary; never serialized. */ recovery?: { failureUsed: boolean; nextOutcome?: "cancelled" | "failed"; }; readonly conversationId: string; readonly providerSessionId: string; providerSessionRevision?: number; /** Canonical host-history version this warm handle has consumed. */ historyVersion?: string; readonly createdAt: number; lastActivityAt: number; busy: boolean; } export interface RuntimeSessionSnapshot { readonly modelKey?: string; readonly conversationId: string; readonly providerSessionId: string; readonly providerSessionRevision?: number; readonly historyVersion?: string; readonly createdAt: number; readonly lastActivityAt: number; readonly busy: boolean; } export interface RuntimeSessionStoreOptions { readonly idleTimeoutMs: number; readonly onEvict?: (record: RuntimeSessionRecord, reason: RuntimeSessionEvictReason) => void | Promise; readonly now?: () => number; } export interface RuntimeSessionStore { /** * Returns the live record for a conversation and marks it busy, or * undefined when there is no session, another run already holds it, or it * idled out (lazy wall-clock check covers stalled timers). Busy records are * never evicted here — a session executing a turn must not be torn down. */ acquire(conversationId: string): RuntimeSessionRecord | undefined; /** No-op unless `record` is still the conversation's live record. */ release(conversationId: string, record: RuntimeSessionRecord): boolean | void; /** * Upsert. A differing stored id is evicted first with reason "replaced" — * unless that record is busy under another run (`owner` is the caller's * acquired record), in which case the save is skipped: the in-flight run's * session must not be disposed out from under it. */ save(conversationId: string, providerSessionId: string, owner?: RuntimeSessionRecord, providerSessionRevision?: number, historyVersion?: string, modelKey?: string, recovery?: RuntimeSessionRecord["recovery"]): void; /** * When `providerSessionId` is given, evicts only if it still matches the * stored record — a stale-resume eviction must not retire a session some * other run replaced it with. */ evict(conversationId: string, reason: RuntimeSessionEvictReason, providerSessionId?: string): Promise; /** Forget only this process's mapping after the runtime handle was refreshed explicitly. */ forget(conversationId: string, providerSessionId?: string): boolean; /** Read-only snapshot for detached status and diagnostics. */ list?(): readonly RuntimeSessionSnapshot[]; /** Evicts everything and latches the store shut: later save/acquire no-op. */ disposeAll(): Promise; } export interface RuntimeSessionStoreWithSnapshot extends RuntimeSessionStore { release(conversationId: string, record: RuntimeSessionRecord): boolean; list(): readonly RuntimeSessionSnapshot[]; } export declare function createRuntimeSessionStore(options: RuntimeSessionStoreOptions): RuntimeSessionStoreWithSnapshot; //# sourceMappingURL=sessions.d.ts.map