summaryrefslogtreecommitdiffhomepage
path: root/src/features/conversation-cache/types.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-07 00:02:32 +0900
committerAdam Malczewski <[email protected]>2026-06-07 00:02:32 +0900
commit5d9ae1849337b64af1b0d47c23b8c4950a55f792 (patch)
treedd5fccaff7535bf1216457a986b8f95bd14fd61e /src/features/conversation-cache/types.ts
parentfac44794432928d0341728642fd70eef87837da4 (diff)
downloaddispatch-web-5d9ae1849337b64af1b0d47c23b8c4950a55f792.tar.gz
dispatch-web-5d9ae1849337b64af1b0d47c23b8c4950a55f792.zip
Slice 2 wave 1: transcript reducer, wire conformance, ws chat, cache core
- core/chunks: the one pure transcript reducer (foldEvent live deltas + applyHistory seq-keyed reconcile + selectChunks/selectMessages); 27 tests - core/wire: FE-side contract-conformance exhaustiveness guards + drift smoke tests over wire/transport-contract unions (ยง2.9 drift signal); 10 tests - adapters/ws: additively multiplex chat.send/chat.delta/chat.error on the existing surface socket (onChat + widened send); surface API unchanged - features/conversation-cache: pure reconcileCache/nextSinceSeq/selectEvictions + ConversationChunkStore port + injected createConversationCache; 26 tests Verified green: svelte-check 0/0, vitest 169, biome clean, build ok.
Diffstat (limited to 'src/features/conversation-cache/types.ts')
-rw-r--r--src/features/conversation-cache/types.ts42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/features/conversation-cache/types.ts b/src/features/conversation-cache/types.ts
new file mode 100644
index 0000000..2a349cc
--- /dev/null
+++ b/src/features/conversation-cache/types.ts
@@ -0,0 +1,42 @@
+import type { StoredChunk } from "@dispatch/wire";
+
+/** Metadata entry for a cached conversation, used by eviction logic. */
+export interface ConversationCacheIndexEntry {
+ readonly conversationId: string;
+ readonly chunkCount: number;
+ readonly maxSeq: number;
+ readonly lastAccess?: number;
+}
+
+/**
+ * Storage port for conversation chunk persistence.
+ *
+ * The IndexedDB implementation lives in `src/adapters/idb/` (separate unit);
+ * this interface is the contract the cache logic depends on.
+ *
+ * All methods MUST be idempotent on `seq`: re-appending an existing seq is a no-op.
+ */
+export interface ConversationChunkStore {
+ /** Load all cached chunks for a conversation, seq-ordered. Returns [] if absent. */
+ load(conversationId: string): Promise<readonly StoredChunk[]>;
+
+ /**
+ * Append committed chunks to a conversation's cache.
+ * MUST be idempotent on `seq`: re-appending an existing seq is a no-op.
+ */
+ append(conversationId: string, chunks: readonly StoredChunk[]): Promise<void>;
+
+ /** Delete all cached data for a conversation. */
+ delete(conversationId: string): Promise<void>;
+
+ /** Return metadata for all cached conversations (for eviction). */
+ index(): Promise<readonly ConversationCacheIndexEntry[]>;
+}
+
+/** Result of reconciling cached chunks with incoming authoritative chunks. */
+export interface ReconcileResult {
+ /** The merged, deduplicated, seq-ordered chunk list. */
+ readonly merged: readonly StoredChunk[];
+ /** The subset of incoming chunks that need to be appended (not already cached). */
+ readonly toAppend: readonly StoredChunk[];
+}