summaryrefslogtreecommitdiffhomepage
path: root/src/features/conversation-cache/types.ts
blob: 345ab71468ae942019798e5af5a959d20beb91fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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[];
}