What Is the Snapshot Transcript Cache and How Does Session Restoration Work in Prime-Agent?
The snapshot transcript cache is a hybrid memory/disk storage component that buffers streamed session transcripts so Prime-Agent's daemon mode can restore interrupted chat sessions for reconnecting clients.
The snapshot transcript cache enables reliable session restoration in Prime-Agent by storing a complete chat transcript while the daemon generates or delivers a session snapshot. This mechanism ensures clients can disconnect and reconnect without losing conversation context, picking up exactly where they left off. According to the Prime-Agent source code, the cache handles chunked streaming, automatic spill-to-disk, and reference-counted lifecycle management.
How the Snapshot Transcript Cache Works
Chunked Transcript Streaming
Rather than buffering entire transcripts in memory, Prime-Agent emits transcript data in configurable chunks (JSON-lines format). The createSnapshotTranscriptChunks generator in packages/coding-agent/src/modes/daemon/snapshot-transcript-cache.ts constructs each chunk while respecting the SNAPSHOT_TARGET_CHUNK_BYTES limit (lines 27-70). This chunked approach prevents memory exhaustion when serializing large sessions.
Hybrid Memory and File-Backed Storage
The cache dynamically selects storage based on total size:
- In-memory mode: While below
SNAPSHOT_MEMORY_CACHE_BYTES, chunks stay in abufferarray in RAM (lines 56-73) - Spill-to-disk mode: Once exceeded, the cache creates a private directory under
cacheRootand writes each chunk to separate*.jsonlfiles (lines 58-69)
This automatic switching ensures optimal performance for small snapshots while safely handling large transcripts.
Reading Chunks Synchronously or Asynchronously
The cache provides two access patterns (lines 17-33, 76-90):
| Method | Behavior | Use Case |
|---|---|---|
readChunk(index) |
Returns chunk immediately | Client already knows chunk exists |
waitForChunk(index) |
Returns Promise that resolves when chunk available |
Snapshot still being generated |
The waitForChunk method is essential for catch-up scenarios where a client connects while the daemon is still streaming the snapshot.
Reference-Counted Lifecycle Management
Consumers control cache lifetime through explicit reference counting (lines 93-107):
const release = cache.retain(); // increment reader count
// ... read chunks ...
release(); // decrement count, may trigger disposal
The cache only disposes when:
dispose()has been explicitly called, and- All readers have released their handles
Completion and Failure States
The cache exposes explicit state transitions (lines 44-62, 16-24):
markComplete()— signals finished snapshot, resolves pendingwaitForChunkcalls withundefinedmarkFailed(error)— aborts snapshot, rejects all pending waitersdispose()— removes temporary directory, clears memory structures, and deregisters from daemon'stranscriptCachesmap
How Session Restoration Works in Prime-Agent
Step 1: Snapshot Creation
When a client requests a session snapshot, the daemon streams the transcript using createSnapshotTranscriptChunks and feeds chunks into a fresh SnapshotTranscriptCache instance via appendEncodedChunk. The test file 4677-snapshot-catchup-replacement.test.ts demonstrates this complete flow, including chunk generation and cache population.
Step 2: Cache Registration
The daemon maintains a transcriptCaches map keyed by active session ID (lines 14-20). Each entry stores:
- The
snapshotId - Chunk data (memory or disk-backed)
- Completion status
This registry allows the daemon to locate snapshots for reconnecting clients.
Step 3: Client Attachment
A reconnecting client supplies its stored snapshotId. The daemon:
- Looks up the corresponding
SnapshotTranscriptCache - Calls
retain()to prevent premature disposal - Begins reading chunks via
readChunkorwaitForChunk
Step 4: Session Rehydration
As chunks arrive, the client deserializes each message:
const release = cache.retain();
for (let i = 0; i < cache.chunkCount; i++) {
const data = await cache.waitForChunk(i);
if (!data) break; // snapshot complete
const { messages } = JSON.parse(data.toString());
// Rebuild session message list...
}
release();
Once the cache reports complete (or the final session_snapshot_end event arrives), the client resumes normal interaction.
Step 5: Cleanup
After full restoration, the client releases its retain handle. The daemon calls dispose() on the cache; if no other readers remain, the temporary directory is removed and memory structures are cleared (lines 9-15, 20-28).
Complete Code Example
import { SnapshotTranscriptCache } from './snapshot-transcript-cache';
import { createSnapshotTranscriptChunks } from './create-snapshot';
// Daemon: Create and populate cache during snapshot generation
const cache = new SnapshotTranscriptCache({
activeSessionId: "session-123",
snapshotId: "snap-001",
cacheRoot: "/tmp/prime-agent-snapshots",
});
// Stream chunks as they become available
for (const chunk of createSnapshotTranscriptChunks({
activeSessionId: "session-123",
snapshotId: "snap-001",
messages: recentMessages,
})) {
cache.appendEncodedChunk(chunk);
}
cache.markComplete();
// Client: Restore session from cache
const restoreSession = async (cache: SnapshotTranscriptCache) => {
const release = cache.retain();
const restoredMessages: any[] = [];
try {
for (let i = 0; ; i++) {
const data = await cache.waitForChunk(i);
if (!data) break;
const { messages } = JSON.parse(data.toString());
restoredMessages.push(...messages);
}
return restoredMessages;
} finally {
release();
}
};
Key Source Files
packages/coding-agent/src/modes/daemon/snapshot-transcript-cache.ts— Core cache implementation with chunked storage, I/O handling, and lifecycle managementpackages/coding-agent/test/suite/regressions/4677-snapshot-catchup-replacement.test.ts— Regression test demonstrating snapshot generation and replacement logicpackages/coding-agent/src/modes/daemon/daemon-client.ts— Client attachment logic for session restorationpackages/coding-agent/src/modes/daemon/create-snapshot.ts— Entry point orchestratingcreateSnapshotTranscriptChunksand cache writes
Summary
- The snapshot transcript cache provides hybrid memory/disk storage for streamed session transcripts in Prime-Agent's daemon mode
- Chunked streaming via
createSnapshotTranscriptChunksprevents memory issues with large transcripts - Automatic spill-to-disk activates when
SNAPSHOT_MEMORY_CACHE_BYTESis exceeded - Reference counting ensures caches survive while any client is reading, then clean up automatically
- Session restoration works by: creating snapshot → registering cache → client attachment → chunk rehydration → cleanup
- The
waitForChunkmethod enables catch-up streaming where clients connect during active snapshot generation
Frequently Asked Questions
What triggers the cache to switch from memory to disk storage?
The cache monitors total buffered size against SNAPSHOT_MEMORY_CACHE_BYTES. Once appended chunks exceed this threshold, the cache creates a private directory under cacheRoot and begins writing each new chunk to individual *.jsonl files (lines 58-69). Existing memory chunks remain in RAM; only new data spills to disk.
How does the cache handle multiple clients reading the same snapshot?
Each client calls retain() to increment an internal reader counter before reading. The cache only disposes when dispose() was requested and the reader count reaches zero. This prevents premature cleanup while any client is still restoring the session, even if the original snapshot generation has completed.
What happens if snapshot generation fails midway?
Calling markFailed(error) immediately rejects all pending waitForChunk promises with the provided error. Clients receive the failure and can handle reconnection or error recovery. The cache remains accessible until all readers release it, allowing partial data retrieval if needed before disposal.
Can clients read chunks that were written to disk as fast as memory chunks?
Yes. The readChunk and waitForChunk methods abstract the storage location. Synchronous reads from disk incur filesystem latency, but the API presents uniform behavior regardless of whether the chunk resides in the buffer array or a *.jsonl file in the temporary directory.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →