@theokit/sdk-cache 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +10 -0
- package/dist/index.cjs +38 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +38 -7
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 08539f0: Fix a cross-model semantic-cache false hit and add session revert (#67). (1) **Model-scoped cache:** the semantic-search path filtered eligible entries by embedder + namespace + dim + expiry but NOT `modelId`, so two models sharing an embedder could return each other's cached response; `semanticSearch` / `isEligibleForSearch` now require `modelId` equality (the composite KV key already included it). (2) **Session revert:** `ConversationStorageAdapter.truncateConversation(id, keepCount)` reverts a transcript back to its first `keepCount` messages ("undo the last turn(s)"), rewriting the JSONL atomically under the same cross-process lock as append/compaction; the FS + in-memory adapters implement it. `keepCount <= 0` empties, `keepCount >= length` is a no-op.
|
|
8
|
+
|
|
9
|
+
## 0.2.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- ac3f77d: @theokit/sdk: resolveModelCapabilities catalog gains cheap OpenRouter slugs (qwen3-coder, deepseek v4-flash/v3.2, glm-4.7-flash, gemini-2.5-flash-lite/pro) so they resolve real context windows instead of the 4096 default. @theokit/sdk-tools: new createGenericHttpSearchAdapter (env-keyed generic HTTP WebSearchCallback alongside Brave); buildEnvContext gains git-branch detection + an injectable clock. @theokit/sdk-cache: ships createLexicalEmbedder (zero-dependency token-hash lexical embedder built-in).
|
|
14
|
+
|
|
3
15
|
All notable changes to `@theokit/sdk-cache` are documented in this file.
|
|
4
16
|
|
|
5
17
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
package/README.md
CHANGED
|
@@ -48,6 +48,16 @@ Constructs a semantic cache instance with vector similarity + FTS hybrid lookup.
|
|
|
48
48
|
| `modelId` | `string` | (required) | LLM model identifier (used in cache key composition). |
|
|
49
49
|
| `store` | `"memory" \| { backend: "json", dir }` | `"memory"` | Persistence backend. |
|
|
50
50
|
|
|
51
|
+
### `createLexicalEmbedder(dimension = 256): CacheEmbedderRuntime`
|
|
52
|
+
|
|
53
|
+
A built-in, zero-dependency embedder so you can use `Cache.semantic` without wiring an LLM embedding API. It produces a deterministic token-hash frequency vector, L2-normalized (id `theokit-lexical-v1-d{dimension}`, model `theokit-lexical-hash`). Identical text yields identical vectors (exact-repeat hits) and lexically similar text yields nearby vectors (cosine-similar hits). It carries no semantic understanding — for that, supply an LLM-backed `CacheEmbedderRuntime`. Empty/whitespace text maps to the zero vector.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { Cache, createLexicalEmbedder } from "@theokit/sdk-cache";
|
|
57
|
+
|
|
58
|
+
const cache = Cache.semantic({ embedder: createLexicalEmbedder() });
|
|
59
|
+
```
|
|
60
|
+
|
|
51
61
|
### `cache.asPlugin(): Plugin`
|
|
52
62
|
|
|
53
63
|
Returns a `Plugin` compatible with `Agent.create({ plugins })`. The plugin hooks `preUserSend` (cache lookup) and `postAssistantReply` (cache store).
|
package/dist/index.cjs
CHANGED
|
@@ -110,7 +110,14 @@ async function performLookup(p) {
|
|
|
110
110
|
}
|
|
111
111
|
const vec = await embedOrDegrade(p.embedder, p.prompt, p.store, span, "lookup");
|
|
112
112
|
if (vec === void 0) return { cached: false };
|
|
113
|
-
const match = p.store.semanticSearch(
|
|
113
|
+
const match = p.store.semanticSearch(
|
|
114
|
+
vec,
|
|
115
|
+
p.threshold,
|
|
116
|
+
p.embedder.id,
|
|
117
|
+
p.namespace,
|
|
118
|
+
now,
|
|
119
|
+
p.modelId
|
|
120
|
+
);
|
|
114
121
|
if (match !== void 0) {
|
|
115
122
|
p.store.incrementSemanticHits();
|
|
116
123
|
span.setAttribute("cache.hit", "semantic");
|
|
@@ -177,17 +184,19 @@ var InMemoryCacheStore = class {
|
|
|
177
184
|
this.map.set(key, { ...e, accessedAt: now, accessCount: e.accessCount + 1 });
|
|
178
185
|
return this.map.get(key);
|
|
179
186
|
}
|
|
180
|
-
isEligibleForSearch(e, embedderId, namespace, dim, now) {
|
|
187
|
+
isEligibleForSearch(e, embedderId, namespace, dim, now, modelId) {
|
|
181
188
|
if (e.embedderId !== embedderId) return false;
|
|
189
|
+
if (e.modelId !== modelId) return false;
|
|
182
190
|
if (e.namespace !== namespace) return false;
|
|
183
191
|
if (e.vector.length !== dim) return false;
|
|
184
192
|
if (e.expiresAt <= now) return false;
|
|
185
193
|
return true;
|
|
186
194
|
}
|
|
187
|
-
semanticSearch(vector, threshold, embedderId, namespace, now) {
|
|
195
|
+
semanticSearch(vector, threshold, embedderId, namespace, now, modelId) {
|
|
188
196
|
let best;
|
|
189
197
|
for (const e of this.map.values()) {
|
|
190
|
-
if (!this.isEligibleForSearch(e, embedderId, namespace, vector.length, now))
|
|
198
|
+
if (!this.isEligibleForSearch(e, embedderId, namespace, vector.length, now, modelId))
|
|
199
|
+
continue;
|
|
191
200
|
const d = cosineDistance(e.vector, vector);
|
|
192
201
|
if (d <= threshold && (best === void 0 || d < best.distance)) {
|
|
193
202
|
best = { entry: e, distance: d };
|
|
@@ -414,8 +423,8 @@ var JsonFileCacheStore = class {
|
|
|
414
423
|
kvGet(key, now) {
|
|
415
424
|
return this.inner.kvGet(key, now);
|
|
416
425
|
}
|
|
417
|
-
semanticSearch(vector, threshold, embedderId, namespace, now) {
|
|
418
|
-
return this.inner.semanticSearch(vector, threshold, embedderId, namespace, now);
|
|
426
|
+
semanticSearch(vector, threshold, embedderId, namespace, now, modelId) {
|
|
427
|
+
return this.inner.semanticSearch(vector, threshold, embedderId, namespace, now, modelId);
|
|
419
428
|
}
|
|
420
429
|
set(entry) {
|
|
421
430
|
this.inner.set(entry);
|
|
@@ -656,8 +665,31 @@ function createStore(namespace, maxEntries, persistence) {
|
|
|
656
665
|
return new InMemoryCacheStore(maxEntries);
|
|
657
666
|
}
|
|
658
667
|
|
|
668
|
+
// src/lexical-embedder.ts
|
|
669
|
+
function createLexicalEmbedder(dimension = 256) {
|
|
670
|
+
return {
|
|
671
|
+
id: `theokit-lexical-v1-d${dimension}`,
|
|
672
|
+
model: "theokit-lexical-hash",
|
|
673
|
+
dimension,
|
|
674
|
+
async embed(texts) {
|
|
675
|
+
return texts.map((text) => {
|
|
676
|
+
const vec = new Array(dimension).fill(0);
|
|
677
|
+
for (const tok of text.toLowerCase().split(/\s+/).filter(Boolean)) {
|
|
678
|
+
let h = 0;
|
|
679
|
+
for (let i = 0; i < tok.length; i += 1) h = h * 31 + tok.charCodeAt(i) | 0;
|
|
680
|
+
const idx = Math.abs(h) % dimension;
|
|
681
|
+
vec[idx] = (vec[idx] ?? 0) + 1;
|
|
682
|
+
}
|
|
683
|
+
const magnitude = Math.sqrt(vec.reduce((s, x) => s + x * x, 0)) || 1;
|
|
684
|
+
return vec.map((x) => x / magnitude);
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
|
|
659
690
|
exports.Cache = Cache;
|
|
660
691
|
exports.CacheEmbedderError = CacheEmbedderError;
|
|
661
692
|
exports.CacheInvalidTtlError = CacheInvalidTtlError;
|
|
693
|
+
exports.createLexicalEmbedder = createLexicalEmbedder;
|
|
662
694
|
//# sourceMappingURL=index.cjs.map
|
|
663
695
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/embed-helper.ts","../src/internal/key.ts","../src/internal/telemetry.ts","../src/internal/lookup.ts","../src/internal/cosine.ts","../src/internal/store.ts","../src/types/cache.ts","../src/internal/ttl.ts","../src/internal/store-handler.ts","../src/internal/store-json.ts","../src/cache.ts"],"names":["createHash","createRequire","readFile","join","mkdir","atomicWriteText","z","PersistenceSchema","definePlugin"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Shared embed-with-graceful-degradation helper — used by both `lookup.ts`\n * and `store-handler.ts`. Extracted to remove the embed-failure boilerplate\n * clone flagged by jscpd. EC-1 absorbed: embedder failure is silent (caller\n * decides what to do via the boolean return).\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime } from \"../types/cache.js\";\nimport type { InMemoryCacheStore } from \"./store.js\";\nimport type { JsonFileCacheStore } from \"./store-json.js\";\n\ninterface SpanLike {\n setAttribute(key: string, value: string | number | boolean): SpanLike;\n}\n\nexport async function embedOrDegrade(\n embedder: CacheEmbedderRuntime,\n prompt: string,\n store: InMemoryCacheStore | JsonFileCacheStore,\n span: SpanLike,\n context: \"lookup\" | \"store\",\n): Promise<number[] | undefined> {\n try {\n const result = await embedder.embed([prompt]);\n return result[0]!;\n } catch (err) {\n store.incrementEmbedderFailures();\n const action = context === \"lookup\" ? \"degrading to miss\" : \"skipping cache write\";\n console.warn(\n `[cache] embedder failed during ${context}, ${action}:`,\n err instanceof Error ? err.message : err,\n );\n span.setAttribute(\"cache.bypass_reason\", \"embedder_failure\");\n return undefined;\n }\n}\n","/**\n * Composite cache key (ADR D253).\n *\n * Format: `${namespace}:${embedderId}:${modelId}:${hash(normalizedPrompt)}`.\n * Normalizes whitespace + lowercases. Hash = first 16 hex chars of SHA-256.\n *\n * @internal\n */\n\nimport { createHash } from \"node:crypto\";\n\ninterface CacheKeyParams {\n namespace: string;\n embedderId: string;\n modelId: string;\n prompt: string;\n}\n\nexport function computeCacheKey(p: CacheKeyParams): string {\n const normalized = p.prompt.trim().replace(/\\s+/g, \" \").toLowerCase();\n const hash = createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n return `${p.namespace}:${p.embedderId}:${p.modelId}:${hash}`;\n}\n","/**\n * OTel telemetry for semantic cache (ADR D262).\n *\n * Spans:\n * - `cache.lookup` — per `pre_user_send`. Attributes: namespace, embedder.id,\n * hit (kv|semantic|miss), distance, ttl_remaining_s, bypass_reason.\n * - `cache.store` — per `post_assistant_reply`. Attributes: bypass_reason, stored.\n *\n * @internal\n */\n\n// SDK 2.0 split: observability primitives live in @theokit/sdk.\n// The sub-path barrel was avoided due to a rollup-plugin-dts edge case\n// that emitted an empty index.d.ts for newly-added internal barrels;\n// re-exporting locally produces the same runtime behavior with stable types.\nimport { createRequire } from \"node:module\";\n\ninterface SpanLike {\n setAttribute(key: string, value: string | number | boolean): SpanLike;\n end(): void;\n}\n\nconst noopSpan: SpanLike = {\n setAttribute: () => noopSpan,\n end: () => undefined,\n};\n\ninterface TracerLike {\n startSpan(\n name: string,\n options?: { attributes?: Record<string, string | number | boolean> },\n ): SpanLike;\n}\n\ninterface CacheEntry {\n tracer: TracerLike | null;\n}\nconst tracerCache = new Map<string, CacheEntry>();\n\nfunction getTracer(name: string, version = \"1.0.0\"): TracerLike | undefined {\n const cached = tracerCache.get(name);\n if (cached !== undefined) return cached.tracer ?? undefined;\n try {\n const r = createRequire(import.meta.url);\n const otel = r(\"@opentelemetry/api\") as {\n trace?: { getTracer: (n: string, v?: string) => TracerLike };\n };\n if (otel.trace?.getTracer === undefined) {\n tracerCache.set(name, { tracer: null });\n return undefined;\n }\n const tracer = otel.trace.getTracer(name, version);\n tracerCache.set(name, { tracer });\n return tracer;\n } catch {\n tracerCache.set(name, { tracer: null });\n return undefined;\n }\n}\n\nfunction resetTracerCacheForTests(): void {\n tracerCache.clear();\n}\n\nconst TRACER_NAME = \"@theokit/sdk/cache\";\n\nexport function startCacheLookupSpan(info: { namespace: string; embedderId: string }): SpanLike {\n const tracer = getTracer(TRACER_NAME);\n if (tracer === undefined) return noopSpan;\n return tracer.startSpan(\"cache.lookup\", {\n attributes: {\n \"cache.namespace\": info.namespace,\n \"cache.embedder_id\": info.embedderId,\n },\n });\n}\n\nexport function startCacheStoreSpan(info: { namespace: string; embedderId: string }): SpanLike {\n const tracer = getTracer(TRACER_NAME);\n if (tracer === undefined) return noopSpan;\n return tracer.startSpan(\"cache.store\", {\n attributes: {\n \"cache.namespace\": info.namespace,\n \"cache.embedder_id\": info.embedderId,\n },\n });\n}\n\n/** Test seam — reset tracer cache so a fresh require attempt happens. */\nfunction __resetCacheTelemetryForTests(): void {\n resetTracerCacheForTests();\n}\n","/**\n * Cache lookup handler — wired to `pre_user_send` hook (ADRs D259, D260).\n *\n * EC-1: embedder failure degrades to miss (cache is transparent).\n * EC-3: empty / whitespace prompt bypasses cache (avoids hash collision).\n * EC-5: telemetry span ends in finally even on early-return.\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime, CacheTTLConfig } from \"../types/cache.js\";\nimport { embedOrDegrade } from \"./embed-helper.js\";\nimport { computeCacheKey } from \"./key.js\";\nimport type { InMemoryCacheStore } from \"./store.js\";\nimport type { JsonFileCacheStore } from \"./store-json.js\";\nimport { startCacheLookupSpan } from \"./telemetry.js\";\n\nexport type LookupableStore = InMemoryCacheStore | JsonFileCacheStore;\n\ninterface LookupParams {\n prompt: string;\n store: LookupableStore;\n embedder: CacheEmbedderRuntime;\n threshold: number;\n ttl: CacheTTLConfig;\n namespace: string;\n modelId: string;\n}\n\ninterface LookupResult {\n cached: boolean;\n response?: string;\n source?: \"kv\" | \"semantic\";\n distance?: number;\n}\n\nexport async function performLookup(p: LookupParams): Promise<LookupResult> {\n const span = startCacheLookupSpan({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n });\n try {\n // EC-3: empty prompt bypass.\n if (p.prompt.trim().length === 0) {\n p.store.incrementMisses();\n span.setAttribute(\"cache.bypass_reason\", \"empty_prompt\");\n return { cached: false };\n }\n // D255 exclude regex.\n if (p.ttl.exclude?.test(p.prompt)) {\n p.store.incrementExcluded();\n span.setAttribute(\"cache.bypass_reason\", \"exclude_regex\");\n return { cached: false };\n }\n\n const key = computeCacheKey({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n });\n const now = Date.now();\n\n // Step 1: KV exact (D259).\n const kv = p.store.kvGet(key, now);\n if (kv !== undefined) {\n p.store.incrementKvHits();\n span.setAttribute(\"cache.hit\", \"kv\");\n span.setAttribute(\"cache.ttl_remaining_s\", Math.floor((kv.expiresAt - now) / 1000));\n return { cached: true, response: kv.response, source: \"kv\" };\n }\n\n // Step 2: semantic — EC-1: embedder failure degrades to miss.\n const vec = await embedOrDegrade(p.embedder, p.prompt, p.store, span, \"lookup\");\n if (vec === undefined) return { cached: false };\n\n const match = p.store.semanticSearch(vec, p.threshold, p.embedder.id, p.namespace, now);\n if (match !== undefined) {\n p.store.incrementSemanticHits();\n span.setAttribute(\"cache.hit\", \"semantic\");\n span.setAttribute(\"cache.distance\", match.distance);\n span.setAttribute(\"cache.ttl_remaining_s\", Math.floor((match.entry.expiresAt - now) / 1000));\n return {\n cached: true,\n response: match.entry.response,\n source: \"semantic\",\n distance: match.distance,\n };\n }\n\n p.store.incrementMisses();\n span.setAttribute(\"cache.hit\", \"miss\");\n return { cached: false };\n } finally {\n span.end();\n }\n}\n","/**\n * Cosine distance between two equal-length vectors.\n *\n * Returns `1 - cos(a, b)`. Range:\n * - 0.0 = identical direction\n * - 1.0 = orthogonal\n * - 2.0 = opposite (rare in normalized embeddings)\n *\n * Throws on dim mismatch. (Callers MUST filter by dim before calling\n * — EC-2 absorbed at the store level.)\n *\n * @internal\n */\n\nexport function cosineDistance(a: ReadonlyArray<number>, b: ReadonlyArray<number>): number {\n if (a.length !== b.length) {\n throw new Error(`cosineDistance: dim mismatch (${a.length} vs ${b.length})`);\n }\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < a.length; i += 1) {\n const av = a[i]!;\n const bv = b[i]!;\n dot += av * bv;\n normA += av * av;\n normB += bv * bv;\n }\n if (normA === 0 || normB === 0) return 1.0;\n return 1 - dot / (Math.sqrt(normA) * Math.sqrt(normB));\n}\n","/**\n * Cache store interface + in-memory implementation (ADRs D252, D259, D261).\n *\n * INVARIANT (EC-9, EC-13): KV map and vector view are the SAME Map.\n * `semanticSearch` iterates `Map.values()`. No parallel list. `set` replaces\n * by key (Map semantics) — no duplicate-on-race possible.\n *\n * EC-2: `semanticSearch` filters by `embedderId === currentEmbedderId &&\n * vector.length === currentDim` before cosine compare. Protects against\n * dim mismatch when disk-loaded entries used a different embedder.\n *\n * @internal\n */\n\nimport type { CacheEntry, CacheStats } from \"../types/cache.js\";\nimport { cosineDistance } from \"./cosine.js\";\n\nexport interface CacheStore {\n kvGet(key: string, now: number): CacheEntry | undefined;\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n ): { entry: CacheEntry; distance: number } | undefined;\n set(entry: CacheEntry): void;\n delete(key: string): void;\n clear(): Promise<void>;\n stats(): CacheStats;\n evictExpired(now: number): number;\n /** For persistence backends — bulk import. */\n loadAll?(entries: ReadonlyArray<CacheEntry>): void;\n /** For persistence backends — snapshot for serialization. */\n dump?(): ReadonlyArray<CacheEntry>;\n}\n\ninterface StoreCounters {\n kvHits: number;\n semanticHits: number;\n misses: number;\n excluded: number;\n evicted: number;\n embedderFailures: number;\n}\n\nexport class InMemoryCacheStore implements CacheStore {\n private readonly map = new Map<string, CacheEntry>();\n private readonly counters: StoreCounters = {\n kvHits: 0,\n semanticHits: 0,\n misses: 0,\n excluded: 0,\n evicted: 0,\n embedderFailures: 0,\n };\n\n constructor(private readonly maxEntries: number) {}\n\n kvGet(key: string, now: number): CacheEntry | undefined {\n const e = this.map.get(key);\n if (e === undefined) return undefined;\n if (e.expiresAt <= now) {\n this.map.delete(key);\n this.counters.evicted += 1;\n return undefined;\n }\n // Touch for LRU recency.\n this.map.delete(key);\n this.map.set(key, { ...e, accessedAt: now, accessCount: e.accessCount + 1 });\n return this.map.get(key);\n }\n\n private isEligibleForSearch(\n e: CacheEntry,\n embedderId: string,\n namespace: string,\n dim: number,\n now: number,\n ): boolean {\n if (e.embedderId !== embedderId) return false;\n if (e.namespace !== namespace) return false;\n if (e.vector.length !== dim) return false;\n if (e.expiresAt <= now) return false;\n return true;\n }\n\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n ): { entry: CacheEntry; distance: number } | undefined {\n let best: { entry: CacheEntry; distance: number } | undefined;\n for (const e of this.map.values()) {\n if (!this.isEligibleForSearch(e, embedderId, namespace, vector.length, now)) continue;\n const d = cosineDistance(e.vector, vector);\n if (d <= threshold && (best === undefined || d < best.distance)) {\n best = { entry: e, distance: d };\n }\n }\n if (best !== undefined) {\n this.map.delete(best.entry.key);\n this.map.set(best.entry.key, {\n ...best.entry,\n accessedAt: now,\n accessCount: best.entry.accessCount + 1,\n });\n }\n return best;\n }\n\n set(entry: CacheEntry): void {\n // EC-13: Map.set replaces by key — no parallel list.\n if (this.map.has(entry.key)) {\n this.map.delete(entry.key);\n }\n this.map.set(entry.key, entry);\n // Evict LRU when over capacity.\n while (this.map.size > this.maxEntries) {\n const oldestKey = this.map.keys().next().value;\n if (oldestKey === undefined) break;\n this.map.delete(oldestKey);\n this.counters.evicted += 1;\n }\n }\n\n delete(key: string): void {\n this.map.delete(key);\n }\n\n async clear(): Promise<void> {\n this.map.clear();\n }\n\n stats(): CacheStats {\n return {\n entries: this.map.size,\n kvHits: this.counters.kvHits,\n semanticHits: this.counters.semanticHits,\n misses: this.counters.misses,\n excluded: this.counters.excluded,\n evicted: this.counters.evicted,\n embedderFailures: this.counters.embedderFailures,\n };\n }\n\n evictExpired(now: number): number {\n let count = 0;\n for (const [k, e] of this.map.entries()) {\n if (e.expiresAt <= now) {\n this.map.delete(k);\n count += 1;\n }\n }\n this.counters.evicted += count;\n return count;\n }\n\n loadAll(entries: ReadonlyArray<CacheEntry>): void {\n for (const e of entries) this.map.set(e.key, e);\n }\n\n dump(): ReadonlyArray<CacheEntry> {\n return [...this.map.values()];\n }\n\n /** Internal helpers for counters (used by lookup/store handlers). */\n incrementKvHits(): void {\n this.counters.kvHits += 1;\n }\n incrementSemanticHits(): void {\n this.counters.semanticHits += 1;\n }\n incrementMisses(): void {\n this.counters.misses += 1;\n }\n incrementExcluded(): void {\n this.counters.excluded += 1;\n }\n incrementEmbedderFailures(): void {\n this.counters.embedderFailures += 1;\n }\n}\n","/**\n * Public type contract for `Cache.semantic / .asPlugin / .stats / .clear`\n * (Adoption Roadmap #6; ADRs D249-D266).\n *\n * @public\n */\n\n/* ─── TTL config (D255) ─── */\n\nexport interface CacheTTLConfig {\n /** Default TTL applied to all entries. Format: `\"1h\" | \"30m\" | 86400 (seconds)`. */\n readonly default: string | number;\n /** Regex marking queries that must NEVER be cached (e.g. /weather|today|now/i). */\n readonly exclude?: RegExp;\n}\n\n/* ─── Persistence (D265) ─── */\n\nexport interface CachePersistenceOptions {\n readonly backend: \"memory\" | \"json\";\n /** Required when backend = \"json\". */\n readonly dir?: string;\n}\n\n/* ─── Embedder option ─── */\n\n/**\n * Embedder runtime shape — minimal subset of `EmbeddingRuntime` (D11) the\n * Cache actually uses. Lets tests inject fake embedders without pulling\n * the full memory subsystem.\n */\nexport interface CacheEmbedderRuntime {\n readonly id: string;\n readonly model: string;\n readonly dimension: number;\n embed(texts: ReadonlyArray<string>): Promise<number[][]>;\n}\n\n/* ─── Options ─── */\n\nexport interface CacheSemanticOptions {\n /** Embedder instance. REQUIRED in v1 — no autoselect (avoids surprise API calls). */\n readonly embedder: CacheEmbedderRuntime;\n /** Cosine distance threshold (0..2). Default 0.85; lower = stricter. */\n readonly threshold?: number;\n /** TTL config. Default `{ default: \"1h\" }`. */\n readonly ttl?: CacheTTLConfig;\n /** Multi-tenant namespace. Default `\"global\"`. */\n readonly namespace?: string;\n /** Default modelId attached to entries when caller doesn't override. */\n readonly modelId?: string;\n /** Max entries (LRU eviction). Default 1000. */\n readonly maxEntries?: number;\n /** Persistence backend. Default in-memory. */\n readonly persistence?: CachePersistenceOptions;\n}\n\n/* ─── Entry + stats ─── */\n\nexport interface CacheEntry {\n readonly key: string;\n readonly namespace: string;\n readonly embedderId: string;\n readonly modelId: string;\n readonly prompt: string;\n readonly response: string;\n readonly vector: ReadonlyArray<number>;\n readonly createdAt: number;\n readonly expiresAt: number;\n readonly accessedAt: number;\n readonly accessCount: number;\n}\n\nexport interface CacheStats {\n readonly entries: number;\n readonly kvHits: number;\n readonly semanticHits: number;\n readonly misses: number;\n readonly excluded: number;\n readonly evicted: number;\n readonly embedderFailures: number;\n}\n\n/* ─── Error classes ─── */\n\nexport class CacheEmbedderError extends Error {\n override readonly name = \"CacheEmbedderError\";\n override readonly cause?: Error;\n constructor(message: string, cause?: Error) {\n super(`Cache embedder failed: ${message}`);\n if (cause !== undefined) this.cause = cause;\n }\n}\n\nexport class CacheInvalidTtlError extends Error {\n override readonly name = \"CacheInvalidTtlError\";\n constructor(public readonly input: string | number) {\n super(\n `Invalid TTL value: \"${String(input)}\". Expected number (seconds) or string like \"1h\" / \"30m\" / \"7d\".`,\n );\n }\n}\n","/**\n * TTL string parser. Accepts:\n * - number → treated as SECONDS\n * - string `\"\\d+(s|m|h|d|w)\"` → seconds/minutes/hours/days/weeks\n *\n * EC-8: `\"0s\"` / `0` returns 0 (effectively disables cache for that entry).\n * Negative numbers throw `CacheInvalidTtlError`.\n *\n * @internal\n */\n\nimport { CacheInvalidTtlError } from \"../types/cache.js\";\n\nconst TTL_PATTERN = /^(\\d+)\\s*(s|m|h|d|w)$/i;\n\nexport function parseTtlMs(input: string | number): number {\n if (typeof input === \"number\") {\n if (!Number.isFinite(input) || input < 0) {\n throw new CacheInvalidTtlError(input);\n }\n return Math.floor(input * 1000);\n }\n const trimmed = input.trim();\n const m = TTL_PATTERN.exec(trimmed);\n if (m === null) {\n throw new CacheInvalidTtlError(input);\n }\n const value = Number(m[1]);\n const unit = m[2]!.toLowerCase();\n switch (unit) {\n case \"s\":\n return value * 1000;\n case \"m\":\n return value * 60_000;\n case \"h\":\n return value * 3_600_000;\n case \"d\":\n return value * 86_400_000;\n case \"w\":\n return value * 604_800_000;\n /* c8 ignore next 2 */\n default:\n throw new CacheInvalidTtlError(input);\n }\n}\n","/**\n * Cache store handler — wired to `post_assistant_reply` hook (ADRs D260, D266).\n *\n * EC-1: embedder failure during store is silent (LLM call already succeeded;\n * no cache entry written).\n * EC-3: empty prompt bypass.\n * EC-10 / D266: skip storage when the run invoked tools (replay loses\n * side-effects).\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime, CacheTTLConfig } from \"../types/cache.js\";\nimport { embedOrDegrade } from \"./embed-helper.js\";\nimport { computeCacheKey } from \"./key.js\";\nimport type { LookupableStore } from \"./lookup.js\";\nimport { startCacheStoreSpan } from \"./telemetry.js\";\nimport { parseTtlMs } from \"./ttl.js\";\n\ninterface StoreParams {\n prompt: string;\n response: string;\n /** D266: skip cache when tools were used. */\n usedTools?: boolean;\n store: LookupableStore;\n embedder: CacheEmbedderRuntime;\n ttl: CacheTTLConfig;\n namespace: string;\n modelId: string;\n}\n\nexport async function performStore(p: StoreParams): Promise<void> {\n const span = startCacheStoreSpan({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n });\n try {\n // EC-3: empty prompt bypass.\n if (p.prompt.trim().length === 0) {\n span.setAttribute(\"cache.bypass_reason\", \"empty_prompt\");\n return;\n }\n // EC-3 + safety: empty response is not a useful cache entry.\n if (p.response.length === 0) {\n span.setAttribute(\"cache.bypass_reason\", \"empty_response\");\n return;\n }\n // D266 / EC-10: tool-use runs are not cached (replay loses side-effects).\n if (p.usedTools === true) {\n span.setAttribute(\"cache.bypass_reason\", \"used_tools\");\n return;\n }\n // D255 exclude regex.\n if (p.ttl.exclude?.test(p.prompt)) {\n span.setAttribute(\"cache.bypass_reason\", \"exclude_regex\");\n return;\n }\n\n const key = computeCacheKey({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n });\n\n // EC-1: embedder failure during store is silent.\n const vec = await embedOrDegrade(p.embedder, p.prompt, p.store, span, \"store\");\n if (vec === undefined) return;\n\n const now = Date.now();\n const ttlMs = parseTtlMs(p.ttl.default);\n p.store.set({\n key,\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n response: p.response,\n vector: vec,\n createdAt: now,\n expiresAt: now + ttlMs,\n accessedAt: now,\n accessCount: 0,\n });\n span.setAttribute(\"cache.stored\", true);\n } finally {\n span.end();\n }\n}\n","/**\n * JSON disk-backed cache store (ADR D265).\n *\n * One file per namespace at `<dir>/<namespace>.json`. Uses\n * `atomicWriteText` (D60) for crash-safe writes. Debounced flush (200ms)\n * to coalesce bursts.\n *\n * EC-7: corrupt JSON load → log warn + treat as empty cache. Never\n * propagates parse errors that would block `Agent.create`.\n *\n * Layered behind `InMemoryCacheStore` — disk is just persistence; all\n * lookups still hit the in-memory Map for O(1) KV / O(N) vector scan.\n *\n * @internal\n */\n\nimport { mkdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { atomicWriteText } from \"@theokit/sdk/internal/persistence\";\nimport type { CacheEntry, CacheStats } from \"../types/cache.js\";\nimport { type CacheStore, InMemoryCacheStore } from \"./store.js\";\n\ninterface SerializedSnapshot {\n readonly _schemaVersion: 1;\n readonly namespace: string;\n readonly entries: ReadonlyArray<CacheEntry>;\n}\n\nconst FLUSH_DEBOUNCE_MS = 200;\n\nexport class JsonFileCacheStore implements CacheStore {\n private readonly inner: InMemoryCacheStore;\n private flushTimer: ReturnType<typeof setTimeout> | undefined;\n private dirty = false;\n\n constructor(\n private readonly dir: string,\n private readonly namespace: string,\n maxEntries: number,\n ) {\n this.inner = new InMemoryCacheStore(maxEntries);\n }\n\n /** Hydrate from disk. EC-7: corrupt file → empty cache. */\n async hydrate(): Promise<void> {\n const file = this.filePath();\n try {\n const raw = await readFile(file, \"utf8\");\n let parsed: SerializedSnapshot;\n try {\n parsed = JSON.parse(raw) as SerializedSnapshot;\n } catch (err) {\n console.warn(\n `[cache] corrupt snapshot at ${file}, starting fresh:`,\n err instanceof Error ? err.message : err,\n );\n return;\n }\n if (parsed._schemaVersion !== 1) {\n console.warn(\n `[cache] unsupported schema v${parsed._schemaVersion} at ${file}, starting fresh`,\n );\n return;\n }\n // Only load entries for this namespace (defensive).\n const valid = parsed.entries.filter((e) => e.namespace === this.namespace);\n this.inner.loadAll(valid);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return;\n console.warn(`[cache] failed to read ${file}:`, err instanceof Error ? err.message : err);\n }\n }\n\n kvGet(key: string, now: number): CacheEntry | undefined {\n return this.inner.kvGet(key, now);\n }\n\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n ): { entry: CacheEntry; distance: number } | undefined {\n return this.inner.semanticSearch(vector, threshold, embedderId, namespace, now);\n }\n\n set(entry: CacheEntry): void {\n this.inner.set(entry);\n this.markDirty();\n }\n\n delete(key: string): void {\n this.inner.delete(key);\n this.markDirty();\n }\n\n async clear(): Promise<void> {\n await this.inner.clear();\n this.markDirty();\n await this.flush();\n }\n\n stats(): CacheStats {\n return this.inner.stats();\n }\n\n evictExpired(now: number): number {\n const n = this.inner.evictExpired(now);\n if (n > 0) this.markDirty();\n return n;\n }\n\n /** Force write the current snapshot. Called on shutdown / clear. */\n async flush(): Promise<void> {\n if (this.flushTimer !== undefined) {\n clearTimeout(this.flushTimer);\n this.flushTimer = undefined;\n }\n if (!this.dirty) return;\n await this.writeSnapshot();\n this.dirty = false;\n }\n\n /** Counters proxied to inner. */\n incrementKvHits(): void {\n this.inner.incrementKvHits();\n }\n incrementSemanticHits(): void {\n this.inner.incrementSemanticHits();\n }\n incrementMisses(): void {\n this.inner.incrementMisses();\n }\n incrementExcluded(): void {\n this.inner.incrementExcluded();\n }\n incrementEmbedderFailures(): void {\n this.inner.incrementEmbedderFailures();\n }\n\n private filePath(): string {\n return join(this.dir, `${this.namespace}.json`);\n }\n\n private markDirty(): void {\n this.dirty = true;\n if (this.flushTimer === undefined) {\n this.flushTimer = setTimeout(() => {\n this.flushTimer = undefined;\n void this.flush().catch((err) =>\n console.warn(`[cache] debounced flush failed:`, err instanceof Error ? err.message : err),\n );\n }, FLUSH_DEBOUNCE_MS);\n }\n }\n\n private async writeSnapshot(): Promise<void> {\n await mkdir(this.dir, { recursive: true });\n const snapshot: SerializedSnapshot = {\n _schemaVersion: 1,\n namespace: this.namespace,\n entries: this.inner.dump(),\n };\n const serialized = JSON.stringify(snapshot);\n await atomicWriteText(this.filePath(), serialized);\n }\n}\n","/**\n * Public `Cache` class — semantic LLM response cache (Adoption Roadmap #6;\n * ADRs D249-D266).\n *\n * Usage:\n *\n * import { Agent, Cache, definePlugin } from \"@theokit/sdk\";\n *\n * const cache = Cache.semantic({\n * embedder: myEmbedderRuntime, // EmbeddingRuntime (D11)\n * threshold: 0.85,\n * ttl: { default: \"1h\", exclude: /weather|today|now/i },\n * namespace: \"my-app\",\n * modelId: \"openai/gpt-4o-mini\",\n * });\n *\n * const agent = await Agent.create({\n * model: { id: \"openai/gpt-4o-mini\" },\n * plugins: [cache.asPlugin()],\n * // ...\n * });\n *\n * await agent.send(\"What is the capital of France?\"); // miss → LLM\n * await agent.send(\"Tell me the capital of France\"); // semantic hit\n *\n * @public\n */\n\nimport {\n definePlugin,\n type Plugin,\n type PluginContext,\n type PostAssistantReplyContext,\n type PreUserSendContext,\n type PreUserSendResult,\n} from \"@theokit/sdk\";\nimport { PersistenceSchema } from \"@theokit/sdk/internal/persistence\";\nimport { z } from \"zod\";\nimport { type LookupableStore, performLookup } from \"./internal/lookup.js\";\nimport { InMemoryCacheStore } from \"./internal/store.js\";\nimport { performStore } from \"./internal/store-handler.js\";\nimport { JsonFileCacheStore } from \"./internal/store-json.js\";\nimport type {\n CacheEmbedderRuntime,\n CachePersistenceOptions,\n CacheSemanticOptions,\n CacheStats,\n CacheTTLConfig,\n} from \"./types/cache.js\";\n\nconst CacheSemanticOptionsSchema = z.object({\n embedder: z.unknown().refine(\n (v) => {\n if (v === null || typeof v !== \"object\") return false;\n const o = v as { id?: unknown; embed?: unknown; dimension?: unknown };\n return (\n typeof o.id === \"string\" && typeof o.embed === \"function\" && typeof o.dimension === \"number\"\n );\n },\n { message: \"embedder must be a CacheEmbedderRuntime with { id, dimension, embed }\" },\n ),\n threshold: z.number().min(0).max(2).optional(),\n ttl: z\n .object({\n default: z.union([z.string(), z.number()]),\n exclude: z.instanceof(RegExp).optional(),\n })\n .optional(),\n namespace: z.string().min(1).max(64).optional(),\n modelId: z.string().min(1).max(128).optional(),\n maxEntries: z.number().int().min(1).max(1_000_000).optional(),\n persistence: PersistenceSchema,\n});\n\nconst DEFAULT_THRESHOLD = 0.85;\nconst DEFAULT_TTL: CacheTTLConfig = { default: \"1h\" };\nconst DEFAULT_NAMESPACE = \"global\";\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport class Cache {\n private _plugin?: Plugin;\n\n private constructor(\n private readonly embedder: CacheEmbedderRuntime,\n private readonly threshold: number,\n private readonly ttl: CacheTTLConfig,\n private readonly namespace: string,\n private readonly modelId: string,\n private readonly store: LookupableStore,\n ) {}\n\n static semantic(options: CacheSemanticOptions): Cache {\n CacheSemanticOptionsSchema.parse(options);\n const threshold = options.threshold ?? DEFAULT_THRESHOLD;\n const ttl = options.ttl ?? DEFAULT_TTL;\n const namespace = options.namespace ?? DEFAULT_NAMESPACE;\n const modelId = options.modelId ?? \"unknown\";\n const maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n const store = createStore(namespace, maxEntries, options.persistence);\n return new Cache(options.embedder, threshold, ttl, namespace, modelId, store);\n }\n\n /**\n * EC-4 absorbed: memoized so repeated `asPlugin()` calls return the SAME\n * plugin descriptor — no duplicate hook registration.\n */\n asPlugin(): Plugin {\n if (this._plugin !== undefined) return this._plugin;\n const cache = this;\n this._plugin = definePlugin({\n name: `cache-semantic-${this.namespace}`,\n version: \"1.0.0\",\n kind: \"general\" as const,\n register(ctx: PluginContext): void {\n ctx.on(\"pre_user_send\", async (rawCtx) => {\n const c = rawCtx as PreUserSendContext;\n const result = await performLookup({\n prompt: c.prompt,\n store: cache.store,\n embedder: cache.embedder,\n threshold: cache.threshold,\n ttl: cache.ttl,\n namespace: cache.namespace,\n modelId: cache.modelId,\n });\n if (result.cached === true) {\n // Cache hit — return recalledContext as the cached response.\n // The agent loop will inject this; in v1 the caller must\n // check `pre_user_send` hook return value via runtime support\n // (the cache hit short-circuits via injection; see docs).\n const wrapped: PreUserSendResult = {\n recalledContext: result.response,\n };\n return wrapped;\n }\n const miss: PreUserSendResult = {};\n return miss;\n });\n ctx.on(\"post_assistant_reply\", async (rawCtx) => {\n const c = rawCtx as PostAssistantReplyContext;\n // EC-10: don't cache tool-use runs. v1 lacks a \"usedTools\" signal\n // in PostAssistantReplyContext (D266 documented gap). For now we\n // accept the conservative-skip if `c.reply` looks like a tool\n // result envelope (contains `tool_call_id` markers). Future\n // PostAssistantReplyContext extension will surface usedTools\n // explicitly.\n await performStore({\n prompt: c.prompt,\n response: c.reply,\n usedTools: false,\n store: cache.store,\n embedder: cache.embedder,\n ttl: cache.ttl,\n namespace: cache.namespace,\n modelId: cache.modelId,\n });\n return undefined;\n });\n },\n });\n return this._plugin;\n }\n\n /**\n * Explicit cache lookup — callers that want true LLM short-circuit\n * call this BEFORE `agent.send()`, then dispatch to the LLM only on miss.\n *\n * v1 plugin mode provides recall + context-inject (LLM still called).\n * v1.x will add transparent short-circuit via an agent-loop refactor.\n */\n async consult(\n prompt: string,\n ): Promise<\n { hit: false } | { hit: true; response: string; source: \"kv\" | \"semantic\"; distance?: number }\n > {\n const result = await performLookup({\n prompt,\n store: this.store,\n embedder: this.embedder,\n threshold: this.threshold,\n ttl: this.ttl,\n namespace: this.namespace,\n modelId: this.modelId,\n });\n if (result.cached === true) {\n return {\n hit: true,\n response: result.response ?? \"\",\n source: result.source ?? \"kv\",\n ...(result.distance !== undefined ? { distance: result.distance } : {}),\n };\n }\n return { hit: false };\n }\n\n /**\n * Explicit cache store — pair with `consult()` to manually feed the\n * cache after dispatching the LLM call yourself.\n */\n async remember(prompt: string, response: string, opts?: { usedTools?: boolean }): Promise<void> {\n await performStore({\n prompt,\n response,\n usedTools: opts?.usedTools === true,\n store: this.store,\n embedder: this.embedder,\n ttl: this.ttl,\n namespace: this.namespace,\n modelId: this.modelId,\n });\n }\n\n /** Stats snapshot — primary observable for dogfood verification. */\n stats(): CacheStats {\n return this.store.stats();\n }\n\n /** Clear all entries (and flush to disk if JSON backend). */\n async clear(): Promise<void> {\n await this.store.clear();\n }\n\n /** Force-evict expired entries. Returns count removed. */\n evictExpired(now: number = Date.now()): number {\n return this.store.evictExpired(now);\n }\n}\n\nfunction createStore(\n namespace: string,\n maxEntries: number,\n persistence?: CachePersistenceOptions,\n): LookupableStore {\n if (persistence?.backend === \"json\") {\n const dir = persistence.dir as string;\n const store = new JsonFileCacheStore(dir, namespace, maxEntries);\n // Hydrate fire-and-forget — callers do `await cache.ready()` if they need\n // sync hydration. v1: lazy load on first lookup.\n void store.hydrate();\n return store;\n }\n return new InMemoryCacheStore(maxEntries);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/embed-helper.ts","../src/internal/key.ts","../src/internal/telemetry.ts","../src/internal/lookup.ts","../src/internal/cosine.ts","../src/internal/store.ts","../src/types/cache.ts","../src/internal/ttl.ts","../src/internal/store-handler.ts","../src/internal/store-json.ts","../src/cache.ts","../src/lexical-embedder.ts"],"names":["createHash","createRequire","readFile","join","mkdir","atomicWriteText","z","PersistenceSchema","definePlugin"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Shared embed-with-graceful-degradation helper — used by both `lookup.ts`\n * and `store-handler.ts`. Extracted to remove the embed-failure boilerplate\n * clone flagged by jscpd. EC-1 absorbed: embedder failure is silent (caller\n * decides what to do via the boolean return).\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime } from \"../types/cache.js\";\nimport type { InMemoryCacheStore } from \"./store.js\";\nimport type { JsonFileCacheStore } from \"./store-json.js\";\n\ninterface SpanLike {\n setAttribute(key: string, value: string | number | boolean): SpanLike;\n}\n\nexport async function embedOrDegrade(\n embedder: CacheEmbedderRuntime,\n prompt: string,\n store: InMemoryCacheStore | JsonFileCacheStore,\n span: SpanLike,\n context: \"lookup\" | \"store\",\n): Promise<number[] | undefined> {\n try {\n const result = await embedder.embed([prompt]);\n return result[0]!;\n } catch (err) {\n store.incrementEmbedderFailures();\n const action = context === \"lookup\" ? \"degrading to miss\" : \"skipping cache write\";\n console.warn(\n `[cache] embedder failed during ${context}, ${action}:`,\n err instanceof Error ? err.message : err,\n );\n span.setAttribute(\"cache.bypass_reason\", \"embedder_failure\");\n return undefined;\n }\n}\n","/**\n * Composite cache key (ADR D253).\n *\n * Format: `${namespace}:${embedderId}:${modelId}:${hash(normalizedPrompt)}`.\n * Normalizes whitespace + lowercases. Hash = first 16 hex chars of SHA-256.\n *\n * @internal\n */\n\nimport { createHash } from \"node:crypto\";\n\ninterface CacheKeyParams {\n namespace: string;\n embedderId: string;\n modelId: string;\n prompt: string;\n}\n\nexport function computeCacheKey(p: CacheKeyParams): string {\n const normalized = p.prompt.trim().replace(/\\s+/g, \" \").toLowerCase();\n const hash = createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n return `${p.namespace}:${p.embedderId}:${p.modelId}:${hash}`;\n}\n","/**\n * OTel telemetry for semantic cache (ADR D262).\n *\n * Spans:\n * - `cache.lookup` — per `pre_user_send`. Attributes: namespace, embedder.id,\n * hit (kv|semantic|miss), distance, ttl_remaining_s, bypass_reason.\n * - `cache.store` — per `post_assistant_reply`. Attributes: bypass_reason, stored.\n *\n * @internal\n */\n\n// SDK 2.0 split: observability primitives live in @theokit/sdk.\n// The sub-path barrel was avoided due to a rollup-plugin-dts edge case\n// that emitted an empty index.d.ts for newly-added internal barrels;\n// re-exporting locally produces the same runtime behavior with stable types.\nimport { createRequire } from \"node:module\";\n\ninterface SpanLike {\n setAttribute(key: string, value: string | number | boolean): SpanLike;\n end(): void;\n}\n\nconst noopSpan: SpanLike = {\n setAttribute: () => noopSpan,\n end: () => undefined,\n};\n\ninterface TracerLike {\n startSpan(\n name: string,\n options?: { attributes?: Record<string, string | number | boolean> },\n ): SpanLike;\n}\n\ninterface CacheEntry {\n tracer: TracerLike | null;\n}\nconst tracerCache = new Map<string, CacheEntry>();\n\nfunction getTracer(name: string, version = \"1.0.0\"): TracerLike | undefined {\n const cached = tracerCache.get(name);\n if (cached !== undefined) return cached.tracer ?? undefined;\n try {\n const r = createRequire(import.meta.url);\n const otel = r(\"@opentelemetry/api\") as {\n trace?: { getTracer: (n: string, v?: string) => TracerLike };\n };\n if (otel.trace?.getTracer === undefined) {\n tracerCache.set(name, { tracer: null });\n return undefined;\n }\n const tracer = otel.trace.getTracer(name, version);\n tracerCache.set(name, { tracer });\n return tracer;\n } catch {\n tracerCache.set(name, { tracer: null });\n return undefined;\n }\n}\n\nfunction resetTracerCacheForTests(): void {\n tracerCache.clear();\n}\n\nconst TRACER_NAME = \"@theokit/sdk/cache\";\n\nexport function startCacheLookupSpan(info: { namespace: string; embedderId: string }): SpanLike {\n const tracer = getTracer(TRACER_NAME);\n if (tracer === undefined) return noopSpan;\n return tracer.startSpan(\"cache.lookup\", {\n attributes: {\n \"cache.namespace\": info.namespace,\n \"cache.embedder_id\": info.embedderId,\n },\n });\n}\n\nexport function startCacheStoreSpan(info: { namespace: string; embedderId: string }): SpanLike {\n const tracer = getTracer(TRACER_NAME);\n if (tracer === undefined) return noopSpan;\n return tracer.startSpan(\"cache.store\", {\n attributes: {\n \"cache.namespace\": info.namespace,\n \"cache.embedder_id\": info.embedderId,\n },\n });\n}\n\n/** Test seam — reset tracer cache so a fresh require attempt happens. */\nfunction __resetCacheTelemetryForTests(): void {\n resetTracerCacheForTests();\n}\n","/**\n * Cache lookup handler — wired to `pre_user_send` hook (ADRs D259, D260).\n *\n * EC-1: embedder failure degrades to miss (cache is transparent).\n * EC-3: empty / whitespace prompt bypasses cache (avoids hash collision).\n * EC-5: telemetry span ends in finally even on early-return.\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime, CacheTTLConfig } from \"../types/cache.js\";\nimport { embedOrDegrade } from \"./embed-helper.js\";\nimport { computeCacheKey } from \"./key.js\";\nimport type { InMemoryCacheStore } from \"./store.js\";\nimport type { JsonFileCacheStore } from \"./store-json.js\";\nimport { startCacheLookupSpan } from \"./telemetry.js\";\n\nexport type LookupableStore = InMemoryCacheStore | JsonFileCacheStore;\n\ninterface LookupParams {\n prompt: string;\n store: LookupableStore;\n embedder: CacheEmbedderRuntime;\n threshold: number;\n ttl: CacheTTLConfig;\n namespace: string;\n modelId: string;\n}\n\ninterface LookupResult {\n cached: boolean;\n response?: string;\n source?: \"kv\" | \"semantic\";\n distance?: number;\n}\n\nexport async function performLookup(p: LookupParams): Promise<LookupResult> {\n const span = startCacheLookupSpan({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n });\n try {\n // EC-3: empty prompt bypass.\n if (p.prompt.trim().length === 0) {\n p.store.incrementMisses();\n span.setAttribute(\"cache.bypass_reason\", \"empty_prompt\");\n return { cached: false };\n }\n // D255 exclude regex.\n if (p.ttl.exclude?.test(p.prompt)) {\n p.store.incrementExcluded();\n span.setAttribute(\"cache.bypass_reason\", \"exclude_regex\");\n return { cached: false };\n }\n\n const key = computeCacheKey({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n });\n const now = Date.now();\n\n // Step 1: KV exact (D259).\n const kv = p.store.kvGet(key, now);\n if (kv !== undefined) {\n p.store.incrementKvHits();\n span.setAttribute(\"cache.hit\", \"kv\");\n span.setAttribute(\"cache.ttl_remaining_s\", Math.floor((kv.expiresAt - now) / 1000));\n return { cached: true, response: kv.response, source: \"kv\" };\n }\n\n // Step 2: semantic — EC-1: embedder failure degrades to miss.\n const vec = await embedOrDegrade(p.embedder, p.prompt, p.store, span, \"lookup\");\n if (vec === undefined) return { cached: false };\n\n const match = p.store.semanticSearch(\n vec,\n p.threshold,\n p.embedder.id,\n p.namespace,\n now,\n p.modelId,\n );\n if (match !== undefined) {\n p.store.incrementSemanticHits();\n span.setAttribute(\"cache.hit\", \"semantic\");\n span.setAttribute(\"cache.distance\", match.distance);\n span.setAttribute(\"cache.ttl_remaining_s\", Math.floor((match.entry.expiresAt - now) / 1000));\n return {\n cached: true,\n response: match.entry.response,\n source: \"semantic\",\n distance: match.distance,\n };\n }\n\n p.store.incrementMisses();\n span.setAttribute(\"cache.hit\", \"miss\");\n return { cached: false };\n } finally {\n span.end();\n }\n}\n","/**\n * Cosine distance between two equal-length vectors.\n *\n * Returns `1 - cos(a, b)`. Range:\n * - 0.0 = identical direction\n * - 1.0 = orthogonal\n * - 2.0 = opposite (rare in normalized embeddings)\n *\n * Throws on dim mismatch. (Callers MUST filter by dim before calling\n * — EC-2 absorbed at the store level.)\n *\n * @internal\n */\n\nexport function cosineDistance(a: ReadonlyArray<number>, b: ReadonlyArray<number>): number {\n if (a.length !== b.length) {\n throw new Error(`cosineDistance: dim mismatch (${a.length} vs ${b.length})`);\n }\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < a.length; i += 1) {\n const av = a[i]!;\n const bv = b[i]!;\n dot += av * bv;\n normA += av * av;\n normB += bv * bv;\n }\n if (normA === 0 || normB === 0) return 1.0;\n return 1 - dot / (Math.sqrt(normA) * Math.sqrt(normB));\n}\n","/**\n * Cache store interface + in-memory implementation (ADRs D252, D259, D261).\n *\n * INVARIANT (EC-9, EC-13): KV map and vector view are the SAME Map.\n * `semanticSearch` iterates `Map.values()`. No parallel list. `set` replaces\n * by key (Map semantics) — no duplicate-on-race possible.\n *\n * EC-2: `semanticSearch` filters by `embedderId === currentEmbedderId &&\n * vector.length === currentDim` before cosine compare. Protects against\n * dim mismatch when disk-loaded entries used a different embedder.\n *\n * @internal\n */\n\nimport type { CacheEntry, CacheStats } from \"../types/cache.js\";\nimport { cosineDistance } from \"./cosine.js\";\n\nexport interface CacheStore {\n kvGet(key: string, now: number): CacheEntry | undefined;\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n modelId: string,\n ): { entry: CacheEntry; distance: number } | undefined;\n set(entry: CacheEntry): void;\n delete(key: string): void;\n clear(): Promise<void>;\n stats(): CacheStats;\n evictExpired(now: number): number;\n /** For persistence backends — bulk import. */\n loadAll?(entries: ReadonlyArray<CacheEntry>): void;\n /** For persistence backends — snapshot for serialization. */\n dump?(): ReadonlyArray<CacheEntry>;\n}\n\ninterface StoreCounters {\n kvHits: number;\n semanticHits: number;\n misses: number;\n excluded: number;\n evicted: number;\n embedderFailures: number;\n}\n\nexport class InMemoryCacheStore implements CacheStore {\n private readonly map = new Map<string, CacheEntry>();\n private readonly counters: StoreCounters = {\n kvHits: 0,\n semanticHits: 0,\n misses: 0,\n excluded: 0,\n evicted: 0,\n embedderFailures: 0,\n };\n\n constructor(private readonly maxEntries: number) {}\n\n kvGet(key: string, now: number): CacheEntry | undefined {\n const e = this.map.get(key);\n if (e === undefined) return undefined;\n if (e.expiresAt <= now) {\n this.map.delete(key);\n this.counters.evicted += 1;\n return undefined;\n }\n // Touch for LRU recency.\n this.map.delete(key);\n this.map.set(key, { ...e, accessedAt: now, accessCount: e.accessCount + 1 });\n return this.map.get(key);\n }\n\n private isEligibleForSearch(\n e: CacheEntry,\n embedderId: string,\n namespace: string,\n dim: number,\n now: number,\n modelId: string,\n ): boolean {\n if (e.embedderId !== embedderId) return false;\n // M3 #67 — a stored entry only matches a query for the SAME model.\n if (e.modelId !== modelId) return false;\n if (e.namespace !== namespace) return false;\n if (e.vector.length !== dim) return false;\n if (e.expiresAt <= now) return false;\n return true;\n }\n\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n // M3 #67 — model-scoped: without this the semantic path can return a\n // response cached for a DIFFERENT model that shares the embedder + namespace.\n modelId: string,\n ): { entry: CacheEntry; distance: number } | undefined {\n let best: { entry: CacheEntry; distance: number } | undefined;\n for (const e of this.map.values()) {\n if (!this.isEligibleForSearch(e, embedderId, namespace, vector.length, now, modelId))\n continue;\n const d = cosineDistance(e.vector, vector);\n if (d <= threshold && (best === undefined || d < best.distance)) {\n best = { entry: e, distance: d };\n }\n }\n if (best !== undefined) {\n this.map.delete(best.entry.key);\n this.map.set(best.entry.key, {\n ...best.entry,\n accessedAt: now,\n accessCount: best.entry.accessCount + 1,\n });\n }\n return best;\n }\n\n set(entry: CacheEntry): void {\n // EC-13: Map.set replaces by key — no parallel list.\n if (this.map.has(entry.key)) {\n this.map.delete(entry.key);\n }\n this.map.set(entry.key, entry);\n // Evict LRU when over capacity.\n while (this.map.size > this.maxEntries) {\n const oldestKey = this.map.keys().next().value;\n if (oldestKey === undefined) break;\n this.map.delete(oldestKey);\n this.counters.evicted += 1;\n }\n }\n\n delete(key: string): void {\n this.map.delete(key);\n }\n\n async clear(): Promise<void> {\n this.map.clear();\n }\n\n stats(): CacheStats {\n return {\n entries: this.map.size,\n kvHits: this.counters.kvHits,\n semanticHits: this.counters.semanticHits,\n misses: this.counters.misses,\n excluded: this.counters.excluded,\n evicted: this.counters.evicted,\n embedderFailures: this.counters.embedderFailures,\n };\n }\n\n evictExpired(now: number): number {\n let count = 0;\n for (const [k, e] of this.map.entries()) {\n if (e.expiresAt <= now) {\n this.map.delete(k);\n count += 1;\n }\n }\n this.counters.evicted += count;\n return count;\n }\n\n loadAll(entries: ReadonlyArray<CacheEntry>): void {\n for (const e of entries) this.map.set(e.key, e);\n }\n\n dump(): ReadonlyArray<CacheEntry> {\n return [...this.map.values()];\n }\n\n /** Internal helpers for counters (used by lookup/store handlers). */\n incrementKvHits(): void {\n this.counters.kvHits += 1;\n }\n incrementSemanticHits(): void {\n this.counters.semanticHits += 1;\n }\n incrementMisses(): void {\n this.counters.misses += 1;\n }\n incrementExcluded(): void {\n this.counters.excluded += 1;\n }\n incrementEmbedderFailures(): void {\n this.counters.embedderFailures += 1;\n }\n}\n","/**\n * Public type contract for `Cache.semantic / .asPlugin / .stats / .clear`\n * (Adoption Roadmap #6; ADRs D249-D266).\n *\n * @public\n */\n\n/* ─── TTL config (D255) ─── */\n\nexport interface CacheTTLConfig {\n /** Default TTL applied to all entries. Format: `\"1h\" | \"30m\" | 86400 (seconds)`. */\n readonly default: string | number;\n /** Regex marking queries that must NEVER be cached (e.g. /weather|today|now/i). */\n readonly exclude?: RegExp;\n}\n\n/* ─── Persistence (D265) ─── */\n\nexport interface CachePersistenceOptions {\n readonly backend: \"memory\" | \"json\";\n /** Required when backend = \"json\". */\n readonly dir?: string;\n}\n\n/* ─── Embedder option ─── */\n\n/**\n * Embedder runtime shape — minimal subset of `EmbeddingRuntime` (D11) the\n * Cache actually uses. Lets tests inject fake embedders without pulling\n * the full memory subsystem.\n */\nexport interface CacheEmbedderRuntime {\n readonly id: string;\n readonly model: string;\n readonly dimension: number;\n embed(texts: ReadonlyArray<string>): Promise<number[][]>;\n}\n\n/* ─── Options ─── */\n\nexport interface CacheSemanticOptions {\n /** Embedder instance. REQUIRED in v1 — no autoselect (avoids surprise API calls). */\n readonly embedder: CacheEmbedderRuntime;\n /** Cosine distance threshold (0..2). Default 0.85; lower = stricter. */\n readonly threshold?: number;\n /** TTL config. Default `{ default: \"1h\" }`. */\n readonly ttl?: CacheTTLConfig;\n /** Multi-tenant namespace. Default `\"global\"`. */\n readonly namespace?: string;\n /** Default modelId attached to entries when caller doesn't override. */\n readonly modelId?: string;\n /** Max entries (LRU eviction). Default 1000. */\n readonly maxEntries?: number;\n /** Persistence backend. Default in-memory. */\n readonly persistence?: CachePersistenceOptions;\n}\n\n/* ─── Entry + stats ─── */\n\nexport interface CacheEntry {\n readonly key: string;\n readonly namespace: string;\n readonly embedderId: string;\n readonly modelId: string;\n readonly prompt: string;\n readonly response: string;\n readonly vector: ReadonlyArray<number>;\n readonly createdAt: number;\n readonly expiresAt: number;\n readonly accessedAt: number;\n readonly accessCount: number;\n}\n\nexport interface CacheStats {\n readonly entries: number;\n readonly kvHits: number;\n readonly semanticHits: number;\n readonly misses: number;\n readonly excluded: number;\n readonly evicted: number;\n readonly embedderFailures: number;\n}\n\n/* ─── Error classes ─── */\n\nexport class CacheEmbedderError extends Error {\n override readonly name = \"CacheEmbedderError\";\n override readonly cause?: Error;\n constructor(message: string, cause?: Error) {\n super(`Cache embedder failed: ${message}`);\n if (cause !== undefined) this.cause = cause;\n }\n}\n\nexport class CacheInvalidTtlError extends Error {\n override readonly name = \"CacheInvalidTtlError\";\n constructor(public readonly input: string | number) {\n super(\n `Invalid TTL value: \"${String(input)}\". Expected number (seconds) or string like \"1h\" / \"30m\" / \"7d\".`,\n );\n }\n}\n","/**\n * TTL string parser. Accepts:\n * - number → treated as SECONDS\n * - string `\"\\d+(s|m|h|d|w)\"` → seconds/minutes/hours/days/weeks\n *\n * EC-8: `\"0s\"` / `0` returns 0 (effectively disables cache for that entry).\n * Negative numbers throw `CacheInvalidTtlError`.\n *\n * @internal\n */\n\nimport { CacheInvalidTtlError } from \"../types/cache.js\";\n\nconst TTL_PATTERN = /^(\\d+)\\s*(s|m|h|d|w)$/i;\n\nexport function parseTtlMs(input: string | number): number {\n if (typeof input === \"number\") {\n if (!Number.isFinite(input) || input < 0) {\n throw new CacheInvalidTtlError(input);\n }\n return Math.floor(input * 1000);\n }\n const trimmed = input.trim();\n const m = TTL_PATTERN.exec(trimmed);\n if (m === null) {\n throw new CacheInvalidTtlError(input);\n }\n const value = Number(m[1]);\n const unit = m[2]!.toLowerCase();\n switch (unit) {\n case \"s\":\n return value * 1000;\n case \"m\":\n return value * 60_000;\n case \"h\":\n return value * 3_600_000;\n case \"d\":\n return value * 86_400_000;\n case \"w\":\n return value * 604_800_000;\n /* c8 ignore next 2 */\n default:\n throw new CacheInvalidTtlError(input);\n }\n}\n","/**\n * Cache store handler — wired to `post_assistant_reply` hook (ADRs D260, D266).\n *\n * EC-1: embedder failure during store is silent (LLM call already succeeded;\n * no cache entry written).\n * EC-3: empty prompt bypass.\n * EC-10 / D266: skip storage when the run invoked tools (replay loses\n * side-effects).\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime, CacheTTLConfig } from \"../types/cache.js\";\nimport { embedOrDegrade } from \"./embed-helper.js\";\nimport { computeCacheKey } from \"./key.js\";\nimport type { LookupableStore } from \"./lookup.js\";\nimport { startCacheStoreSpan } from \"./telemetry.js\";\nimport { parseTtlMs } from \"./ttl.js\";\n\ninterface StoreParams {\n prompt: string;\n response: string;\n /** D266: skip cache when tools were used. */\n usedTools?: boolean;\n store: LookupableStore;\n embedder: CacheEmbedderRuntime;\n ttl: CacheTTLConfig;\n namespace: string;\n modelId: string;\n}\n\nexport async function performStore(p: StoreParams): Promise<void> {\n const span = startCacheStoreSpan({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n });\n try {\n // EC-3: empty prompt bypass.\n if (p.prompt.trim().length === 0) {\n span.setAttribute(\"cache.bypass_reason\", \"empty_prompt\");\n return;\n }\n // EC-3 + safety: empty response is not a useful cache entry.\n if (p.response.length === 0) {\n span.setAttribute(\"cache.bypass_reason\", \"empty_response\");\n return;\n }\n // D266 / EC-10: tool-use runs are not cached (replay loses side-effects).\n if (p.usedTools === true) {\n span.setAttribute(\"cache.bypass_reason\", \"used_tools\");\n return;\n }\n // D255 exclude regex.\n if (p.ttl.exclude?.test(p.prompt)) {\n span.setAttribute(\"cache.bypass_reason\", \"exclude_regex\");\n return;\n }\n\n const key = computeCacheKey({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n });\n\n // EC-1: embedder failure during store is silent.\n const vec = await embedOrDegrade(p.embedder, p.prompt, p.store, span, \"store\");\n if (vec === undefined) return;\n\n const now = Date.now();\n const ttlMs = parseTtlMs(p.ttl.default);\n p.store.set({\n key,\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n response: p.response,\n vector: vec,\n createdAt: now,\n expiresAt: now + ttlMs,\n accessedAt: now,\n accessCount: 0,\n });\n span.setAttribute(\"cache.stored\", true);\n } finally {\n span.end();\n }\n}\n","/**\n * JSON disk-backed cache store (ADR D265).\n *\n * One file per namespace at `<dir>/<namespace>.json`. Uses\n * `atomicWriteText` (D60) for crash-safe writes. Debounced flush (200ms)\n * to coalesce bursts.\n *\n * EC-7: corrupt JSON load → log warn + treat as empty cache. Never\n * propagates parse errors that would block `Agent.create`.\n *\n * Layered behind `InMemoryCacheStore` — disk is just persistence; all\n * lookups still hit the in-memory Map for O(1) KV / O(N) vector scan.\n *\n * @internal\n */\n\nimport { mkdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { atomicWriteText } from \"@theokit/sdk/internal/persistence\";\nimport type { CacheEntry, CacheStats } from \"../types/cache.js\";\nimport { type CacheStore, InMemoryCacheStore } from \"./store.js\";\n\ninterface SerializedSnapshot {\n readonly _schemaVersion: 1;\n readonly namespace: string;\n readonly entries: ReadonlyArray<CacheEntry>;\n}\n\nconst FLUSH_DEBOUNCE_MS = 200;\n\nexport class JsonFileCacheStore implements CacheStore {\n private readonly inner: InMemoryCacheStore;\n private flushTimer: ReturnType<typeof setTimeout> | undefined;\n private dirty = false;\n\n constructor(\n private readonly dir: string,\n private readonly namespace: string,\n maxEntries: number,\n ) {\n this.inner = new InMemoryCacheStore(maxEntries);\n }\n\n /** Hydrate from disk. EC-7: corrupt file → empty cache. */\n async hydrate(): Promise<void> {\n const file = this.filePath();\n try {\n const raw = await readFile(file, \"utf8\");\n let parsed: SerializedSnapshot;\n try {\n parsed = JSON.parse(raw) as SerializedSnapshot;\n } catch (err) {\n console.warn(\n `[cache] corrupt snapshot at ${file}, starting fresh:`,\n err instanceof Error ? err.message : err,\n );\n return;\n }\n if (parsed._schemaVersion !== 1) {\n console.warn(\n `[cache] unsupported schema v${parsed._schemaVersion} at ${file}, starting fresh`,\n );\n return;\n }\n // Only load entries for this namespace (defensive).\n const valid = parsed.entries.filter((e) => e.namespace === this.namespace);\n this.inner.loadAll(valid);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return;\n console.warn(`[cache] failed to read ${file}:`, err instanceof Error ? err.message : err);\n }\n }\n\n kvGet(key: string, now: number): CacheEntry | undefined {\n return this.inner.kvGet(key, now);\n }\n\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n modelId: string,\n ): { entry: CacheEntry; distance: number } | undefined {\n return this.inner.semanticSearch(vector, threshold, embedderId, namespace, now, modelId);\n }\n\n set(entry: CacheEntry): void {\n this.inner.set(entry);\n this.markDirty();\n }\n\n delete(key: string): void {\n this.inner.delete(key);\n this.markDirty();\n }\n\n async clear(): Promise<void> {\n await this.inner.clear();\n this.markDirty();\n await this.flush();\n }\n\n stats(): CacheStats {\n return this.inner.stats();\n }\n\n evictExpired(now: number): number {\n const n = this.inner.evictExpired(now);\n if (n > 0) this.markDirty();\n return n;\n }\n\n /** Force write the current snapshot. Called on shutdown / clear. */\n async flush(): Promise<void> {\n if (this.flushTimer !== undefined) {\n clearTimeout(this.flushTimer);\n this.flushTimer = undefined;\n }\n if (!this.dirty) return;\n await this.writeSnapshot();\n this.dirty = false;\n }\n\n /** Counters proxied to inner. */\n incrementKvHits(): void {\n this.inner.incrementKvHits();\n }\n incrementSemanticHits(): void {\n this.inner.incrementSemanticHits();\n }\n incrementMisses(): void {\n this.inner.incrementMisses();\n }\n incrementExcluded(): void {\n this.inner.incrementExcluded();\n }\n incrementEmbedderFailures(): void {\n this.inner.incrementEmbedderFailures();\n }\n\n private filePath(): string {\n return join(this.dir, `${this.namespace}.json`);\n }\n\n private markDirty(): void {\n this.dirty = true;\n if (this.flushTimer === undefined) {\n this.flushTimer = setTimeout(() => {\n this.flushTimer = undefined;\n void this.flush().catch((err) =>\n console.warn(`[cache] debounced flush failed:`, err instanceof Error ? err.message : err),\n );\n }, FLUSH_DEBOUNCE_MS);\n }\n }\n\n private async writeSnapshot(): Promise<void> {\n await mkdir(this.dir, { recursive: true });\n const snapshot: SerializedSnapshot = {\n _schemaVersion: 1,\n namespace: this.namespace,\n entries: this.inner.dump(),\n };\n const serialized = JSON.stringify(snapshot);\n await atomicWriteText(this.filePath(), serialized);\n }\n}\n","/**\n * Public `Cache` class — semantic LLM response cache (Adoption Roadmap #6;\n * ADRs D249-D266).\n *\n * Usage:\n *\n * import { Agent, Cache, definePlugin } from \"@theokit/sdk\";\n *\n * const cache = Cache.semantic({\n * embedder: myEmbedderRuntime, // EmbeddingRuntime (D11)\n * threshold: 0.85,\n * ttl: { default: \"1h\", exclude: /weather|today|now/i },\n * namespace: \"my-app\",\n * modelId: \"openai/gpt-4o-mini\",\n * });\n *\n * const agent = await Agent.create({\n * model: { id: \"openai/gpt-4o-mini\" },\n * plugins: [cache.asPlugin()],\n * // ...\n * });\n *\n * await agent.send(\"What is the capital of France?\"); // miss → LLM\n * await agent.send(\"Tell me the capital of France\"); // semantic hit\n *\n * @public\n */\n\nimport {\n definePlugin,\n type Plugin,\n type PluginContext,\n type PostAssistantReplyContext,\n type PreUserSendContext,\n type PreUserSendResult,\n} from \"@theokit/sdk\";\nimport { PersistenceSchema } from \"@theokit/sdk/internal/persistence\";\nimport { z } from \"zod\";\nimport { type LookupableStore, performLookup } from \"./internal/lookup.js\";\nimport { InMemoryCacheStore } from \"./internal/store.js\";\nimport { performStore } from \"./internal/store-handler.js\";\nimport { JsonFileCacheStore } from \"./internal/store-json.js\";\nimport type {\n CacheEmbedderRuntime,\n CachePersistenceOptions,\n CacheSemanticOptions,\n CacheStats,\n CacheTTLConfig,\n} from \"./types/cache.js\";\n\nconst CacheSemanticOptionsSchema = z.object({\n embedder: z.unknown().refine(\n (v) => {\n if (v === null || typeof v !== \"object\") return false;\n const o = v as { id?: unknown; embed?: unknown; dimension?: unknown };\n return (\n typeof o.id === \"string\" && typeof o.embed === \"function\" && typeof o.dimension === \"number\"\n );\n },\n { message: \"embedder must be a CacheEmbedderRuntime with { id, dimension, embed }\" },\n ),\n threshold: z.number().min(0).max(2).optional(),\n ttl: z\n .object({\n default: z.union([z.string(), z.number()]),\n exclude: z.instanceof(RegExp).optional(),\n })\n .optional(),\n namespace: z.string().min(1).max(64).optional(),\n modelId: z.string().min(1).max(128).optional(),\n maxEntries: z.number().int().min(1).max(1_000_000).optional(),\n persistence: PersistenceSchema,\n});\n\nconst DEFAULT_THRESHOLD = 0.85;\nconst DEFAULT_TTL: CacheTTLConfig = { default: \"1h\" };\nconst DEFAULT_NAMESPACE = \"global\";\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport class Cache {\n private _plugin?: Plugin;\n\n private constructor(\n private readonly embedder: CacheEmbedderRuntime,\n private readonly threshold: number,\n private readonly ttl: CacheTTLConfig,\n private readonly namespace: string,\n private readonly modelId: string,\n private readonly store: LookupableStore,\n ) {}\n\n static semantic(options: CacheSemanticOptions): Cache {\n CacheSemanticOptionsSchema.parse(options);\n const threshold = options.threshold ?? DEFAULT_THRESHOLD;\n const ttl = options.ttl ?? DEFAULT_TTL;\n const namespace = options.namespace ?? DEFAULT_NAMESPACE;\n const modelId = options.modelId ?? \"unknown\";\n const maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n const store = createStore(namespace, maxEntries, options.persistence);\n return new Cache(options.embedder, threshold, ttl, namespace, modelId, store);\n }\n\n /**\n * EC-4 absorbed: memoized so repeated `asPlugin()` calls return the SAME\n * plugin descriptor — no duplicate hook registration.\n */\n asPlugin(): Plugin {\n if (this._plugin !== undefined) return this._plugin;\n const cache = this;\n this._plugin = definePlugin({\n name: `cache-semantic-${this.namespace}`,\n version: \"1.0.0\",\n kind: \"general\" as const,\n register(ctx: PluginContext): void {\n ctx.on(\"pre_user_send\", async (rawCtx) => {\n const c = rawCtx as PreUserSendContext;\n const result = await performLookup({\n prompt: c.prompt,\n store: cache.store,\n embedder: cache.embedder,\n threshold: cache.threshold,\n ttl: cache.ttl,\n namespace: cache.namespace,\n modelId: cache.modelId,\n });\n if (result.cached === true) {\n // Cache hit — return recalledContext as the cached response.\n // The agent loop will inject this; in v1 the caller must\n // check `pre_user_send` hook return value via runtime support\n // (the cache hit short-circuits via injection; see docs).\n const wrapped: PreUserSendResult = {\n recalledContext: result.response,\n };\n return wrapped;\n }\n const miss: PreUserSendResult = {};\n return miss;\n });\n ctx.on(\"post_assistant_reply\", async (rawCtx) => {\n const c = rawCtx as PostAssistantReplyContext;\n // EC-10: don't cache tool-use runs. v1 lacks a \"usedTools\" signal\n // in PostAssistantReplyContext (D266 documented gap). For now we\n // accept the conservative-skip if `c.reply` looks like a tool\n // result envelope (contains `tool_call_id` markers). Future\n // PostAssistantReplyContext extension will surface usedTools\n // explicitly.\n await performStore({\n prompt: c.prompt,\n response: c.reply,\n usedTools: false,\n store: cache.store,\n embedder: cache.embedder,\n ttl: cache.ttl,\n namespace: cache.namespace,\n modelId: cache.modelId,\n });\n return undefined;\n });\n },\n });\n return this._plugin;\n }\n\n /**\n * Explicit cache lookup — callers that want true LLM short-circuit\n * call this BEFORE `agent.send()`, then dispatch to the LLM only on miss.\n *\n * v1 plugin mode provides recall + context-inject (LLM still called).\n * v1.x will add transparent short-circuit via an agent-loop refactor.\n */\n async consult(\n prompt: string,\n ): Promise<\n { hit: false } | { hit: true; response: string; source: \"kv\" | \"semantic\"; distance?: number }\n > {\n const result = await performLookup({\n prompt,\n store: this.store,\n embedder: this.embedder,\n threshold: this.threshold,\n ttl: this.ttl,\n namespace: this.namespace,\n modelId: this.modelId,\n });\n if (result.cached === true) {\n return {\n hit: true,\n response: result.response ?? \"\",\n source: result.source ?? \"kv\",\n ...(result.distance !== undefined ? { distance: result.distance } : {}),\n };\n }\n return { hit: false };\n }\n\n /**\n * Explicit cache store — pair with `consult()` to manually feed the\n * cache after dispatching the LLM call yourself.\n */\n async remember(prompt: string, response: string, opts?: { usedTools?: boolean }): Promise<void> {\n await performStore({\n prompt,\n response,\n usedTools: opts?.usedTools === true,\n store: this.store,\n embedder: this.embedder,\n ttl: this.ttl,\n namespace: this.namespace,\n modelId: this.modelId,\n });\n }\n\n /** Stats snapshot — primary observable for dogfood verification. */\n stats(): CacheStats {\n return this.store.stats();\n }\n\n /** Clear all entries (and flush to disk if JSON backend). */\n async clear(): Promise<void> {\n await this.store.clear();\n }\n\n /** Force-evict expired entries. Returns count removed. */\n evictExpired(now: number = Date.now()): number {\n return this.store.evictExpired(now);\n }\n}\n\nfunction createStore(\n namespace: string,\n maxEntries: number,\n persistence?: CachePersistenceOptions,\n): LookupableStore {\n if (persistence?.backend === \"json\") {\n const dir = persistence.dir as string;\n const store = new JsonFileCacheStore(dir, namespace, maxEntries);\n // Hydrate fire-and-forget — callers do `await cache.ready()` if they need\n // sync hydration. v1: lazy load on first lookup.\n void store.hydrate();\n return store;\n }\n return new InMemoryCacheStore(maxEntries);\n}\n","/**\n * Built-in deterministic lexical embedder for `@theokit/sdk-cache` (RADAR #92.e).\n *\n * `Cache.semantic` requires a `CacheEmbedderRuntime` (no autoselect — it avoids\n * surprise LLM-embedding API calls). This supplies a REAL, deterministic,\n * zero-dependency embedding: a token-hash frequency vector, L2-normalized. It is\n * NOT a stub/fake — identical text yields identical vectors (exact cache hits)\n * and lexically similar text yields nearby vectors (cosine-similar hits). It\n * carries no semantic understanding (that needs an LLM embedder), which is the\n * honest trade-off: the cache's value here is exact-repeat + lexical dedup, with\n * no API cost.\n *\n * Promoted from theocode's `server/lib/cache-embedder.ts`.\n *\n * @public\n */\n\nimport type { CacheEmbedderRuntime } from \"./types/cache.js\";\n\nexport function createLexicalEmbedder(dimension = 256): CacheEmbedderRuntime {\n return {\n id: `theokit-lexical-v1-d${dimension}`,\n model: \"theokit-lexical-hash\",\n dimension,\n async embed(texts: ReadonlyArray<string>): Promise<number[][]> {\n return texts.map((text) => {\n const vec = new Array<number>(dimension).fill(0);\n for (const tok of text.toLowerCase().split(/\\s+/).filter(Boolean)) {\n // FNV-ish rolling hash → bucket; deterministic across runs/processes.\n let h = 0;\n for (let i = 0; i < tok.length; i += 1) h = (h * 31 + tok.charCodeAt(i)) | 0;\n const idx = Math.abs(h) % dimension;\n vec[idx] = (vec[idx] ?? 0) + 1;\n }\n // L2-normalize so cosine distance is well-defined; an empty/whitespace\n // text stays the zero vector (the cache treats it as a non-match).\n const magnitude = Math.sqrt(vec.reduce((s, x) => s + x * x, 0)) || 1;\n return vec.map((x) => x / magnitude);\n });\n },\n };\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -150,4 +150,23 @@ declare class Cache {
|
|
|
150
150
|
evictExpired(now?: number): number;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Built-in deterministic lexical embedder for `@theokit/sdk-cache` (RADAR #92.e).
|
|
155
|
+
*
|
|
156
|
+
* `Cache.semantic` requires a `CacheEmbedderRuntime` (no autoselect — it avoids
|
|
157
|
+
* surprise LLM-embedding API calls). This supplies a REAL, deterministic,
|
|
158
|
+
* zero-dependency embedding: a token-hash frequency vector, L2-normalized. It is
|
|
159
|
+
* NOT a stub/fake — identical text yields identical vectors (exact cache hits)
|
|
160
|
+
* and lexically similar text yields nearby vectors (cosine-similar hits). It
|
|
161
|
+
* carries no semantic understanding (that needs an LLM embedder), which is the
|
|
162
|
+
* honest trade-off: the cache's value here is exact-repeat + lexical dedup, with
|
|
163
|
+
* no API cost.
|
|
164
|
+
*
|
|
165
|
+
* Promoted from theocode's `server/lib/cache-embedder.ts`.
|
|
166
|
+
*
|
|
167
|
+
* @public
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
declare function createLexicalEmbedder(dimension?: number): CacheEmbedderRuntime;
|
|
171
|
+
|
|
172
|
+
export { Cache, CacheEmbedderError, type CacheEmbedderRuntime, type CacheEntry, CacheInvalidTtlError, type CachePersistenceOptions, type CacheSemanticOptions, type CacheStats, type CacheTTLConfig, createLexicalEmbedder };
|
package/dist/index.d.ts
CHANGED
|
@@ -150,4 +150,23 @@ declare class Cache {
|
|
|
150
150
|
evictExpired(now?: number): number;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Built-in deterministic lexical embedder for `@theokit/sdk-cache` (RADAR #92.e).
|
|
155
|
+
*
|
|
156
|
+
* `Cache.semantic` requires a `CacheEmbedderRuntime` (no autoselect — it avoids
|
|
157
|
+
* surprise LLM-embedding API calls). This supplies a REAL, deterministic,
|
|
158
|
+
* zero-dependency embedding: a token-hash frequency vector, L2-normalized. It is
|
|
159
|
+
* NOT a stub/fake — identical text yields identical vectors (exact cache hits)
|
|
160
|
+
* and lexically similar text yields nearby vectors (cosine-similar hits). It
|
|
161
|
+
* carries no semantic understanding (that needs an LLM embedder), which is the
|
|
162
|
+
* honest trade-off: the cache's value here is exact-repeat + lexical dedup, with
|
|
163
|
+
* no API cost.
|
|
164
|
+
*
|
|
165
|
+
* Promoted from theocode's `server/lib/cache-embedder.ts`.
|
|
166
|
+
*
|
|
167
|
+
* @public
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
declare function createLexicalEmbedder(dimension?: number): CacheEmbedderRuntime;
|
|
171
|
+
|
|
172
|
+
export { Cache, CacheEmbedderError, type CacheEmbedderRuntime, type CacheEntry, CacheInvalidTtlError, type CachePersistenceOptions, type CacheSemanticOptions, type CacheStats, type CacheTTLConfig, createLexicalEmbedder };
|
package/dist/index.js
CHANGED
|
@@ -107,7 +107,14 @@ async function performLookup(p) {
|
|
|
107
107
|
}
|
|
108
108
|
const vec = await embedOrDegrade(p.embedder, p.prompt, p.store, span, "lookup");
|
|
109
109
|
if (vec === void 0) return { cached: false };
|
|
110
|
-
const match = p.store.semanticSearch(
|
|
110
|
+
const match = p.store.semanticSearch(
|
|
111
|
+
vec,
|
|
112
|
+
p.threshold,
|
|
113
|
+
p.embedder.id,
|
|
114
|
+
p.namespace,
|
|
115
|
+
now,
|
|
116
|
+
p.modelId
|
|
117
|
+
);
|
|
111
118
|
if (match !== void 0) {
|
|
112
119
|
p.store.incrementSemanticHits();
|
|
113
120
|
span.setAttribute("cache.hit", "semantic");
|
|
@@ -174,17 +181,19 @@ var InMemoryCacheStore = class {
|
|
|
174
181
|
this.map.set(key, { ...e, accessedAt: now, accessCount: e.accessCount + 1 });
|
|
175
182
|
return this.map.get(key);
|
|
176
183
|
}
|
|
177
|
-
isEligibleForSearch(e, embedderId, namespace, dim, now) {
|
|
184
|
+
isEligibleForSearch(e, embedderId, namespace, dim, now, modelId) {
|
|
178
185
|
if (e.embedderId !== embedderId) return false;
|
|
186
|
+
if (e.modelId !== modelId) return false;
|
|
179
187
|
if (e.namespace !== namespace) return false;
|
|
180
188
|
if (e.vector.length !== dim) return false;
|
|
181
189
|
if (e.expiresAt <= now) return false;
|
|
182
190
|
return true;
|
|
183
191
|
}
|
|
184
|
-
semanticSearch(vector, threshold, embedderId, namespace, now) {
|
|
192
|
+
semanticSearch(vector, threshold, embedderId, namespace, now, modelId) {
|
|
185
193
|
let best;
|
|
186
194
|
for (const e of this.map.values()) {
|
|
187
|
-
if (!this.isEligibleForSearch(e, embedderId, namespace, vector.length, now))
|
|
195
|
+
if (!this.isEligibleForSearch(e, embedderId, namespace, vector.length, now, modelId))
|
|
196
|
+
continue;
|
|
188
197
|
const d = cosineDistance(e.vector, vector);
|
|
189
198
|
if (d <= threshold && (best === void 0 || d < best.distance)) {
|
|
190
199
|
best = { entry: e, distance: d };
|
|
@@ -411,8 +420,8 @@ var JsonFileCacheStore = class {
|
|
|
411
420
|
kvGet(key, now) {
|
|
412
421
|
return this.inner.kvGet(key, now);
|
|
413
422
|
}
|
|
414
|
-
semanticSearch(vector, threshold, embedderId, namespace, now) {
|
|
415
|
-
return this.inner.semanticSearch(vector, threshold, embedderId, namespace, now);
|
|
423
|
+
semanticSearch(vector, threshold, embedderId, namespace, now, modelId) {
|
|
424
|
+
return this.inner.semanticSearch(vector, threshold, embedderId, namespace, now, modelId);
|
|
416
425
|
}
|
|
417
426
|
set(entry) {
|
|
418
427
|
this.inner.set(entry);
|
|
@@ -653,6 +662,28 @@ function createStore(namespace, maxEntries, persistence) {
|
|
|
653
662
|
return new InMemoryCacheStore(maxEntries);
|
|
654
663
|
}
|
|
655
664
|
|
|
656
|
-
|
|
665
|
+
// src/lexical-embedder.ts
|
|
666
|
+
function createLexicalEmbedder(dimension = 256) {
|
|
667
|
+
return {
|
|
668
|
+
id: `theokit-lexical-v1-d${dimension}`,
|
|
669
|
+
model: "theokit-lexical-hash",
|
|
670
|
+
dimension,
|
|
671
|
+
async embed(texts) {
|
|
672
|
+
return texts.map((text) => {
|
|
673
|
+
const vec = new Array(dimension).fill(0);
|
|
674
|
+
for (const tok of text.toLowerCase().split(/\s+/).filter(Boolean)) {
|
|
675
|
+
let h = 0;
|
|
676
|
+
for (let i = 0; i < tok.length; i += 1) h = h * 31 + tok.charCodeAt(i) | 0;
|
|
677
|
+
const idx = Math.abs(h) % dimension;
|
|
678
|
+
vec[idx] = (vec[idx] ?? 0) + 1;
|
|
679
|
+
}
|
|
680
|
+
const magnitude = Math.sqrt(vec.reduce((s, x) => s + x * x, 0)) || 1;
|
|
681
|
+
return vec.map((x) => x / magnitude);
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
export { Cache, CacheEmbedderError, CacheInvalidTtlError, createLexicalEmbedder };
|
|
657
688
|
//# sourceMappingURL=index.js.map
|
|
658
689
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/embed-helper.ts","../src/internal/key.ts","../src/internal/telemetry.ts","../src/internal/lookup.ts","../src/internal/cosine.ts","../src/internal/store.ts","../src/types/cache.ts","../src/internal/ttl.ts","../src/internal/store-handler.ts","../src/internal/store-json.ts","../src/cache.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Shared embed-with-graceful-degradation helper — used by both `lookup.ts`\n * and `store-handler.ts`. Extracted to remove the embed-failure boilerplate\n * clone flagged by jscpd. EC-1 absorbed: embedder failure is silent (caller\n * decides what to do via the boolean return).\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime } from \"../types/cache.js\";\nimport type { InMemoryCacheStore } from \"./store.js\";\nimport type { JsonFileCacheStore } from \"./store-json.js\";\n\ninterface SpanLike {\n setAttribute(key: string, value: string | number | boolean): SpanLike;\n}\n\nexport async function embedOrDegrade(\n embedder: CacheEmbedderRuntime,\n prompt: string,\n store: InMemoryCacheStore | JsonFileCacheStore,\n span: SpanLike,\n context: \"lookup\" | \"store\",\n): Promise<number[] | undefined> {\n try {\n const result = await embedder.embed([prompt]);\n return result[0]!;\n } catch (err) {\n store.incrementEmbedderFailures();\n const action = context === \"lookup\" ? \"degrading to miss\" : \"skipping cache write\";\n console.warn(\n `[cache] embedder failed during ${context}, ${action}:`,\n err instanceof Error ? err.message : err,\n );\n span.setAttribute(\"cache.bypass_reason\", \"embedder_failure\");\n return undefined;\n }\n}\n","/**\n * Composite cache key (ADR D253).\n *\n * Format: `${namespace}:${embedderId}:${modelId}:${hash(normalizedPrompt)}`.\n * Normalizes whitespace + lowercases. Hash = first 16 hex chars of SHA-256.\n *\n * @internal\n */\n\nimport { createHash } from \"node:crypto\";\n\ninterface CacheKeyParams {\n namespace: string;\n embedderId: string;\n modelId: string;\n prompt: string;\n}\n\nexport function computeCacheKey(p: CacheKeyParams): string {\n const normalized = p.prompt.trim().replace(/\\s+/g, \" \").toLowerCase();\n const hash = createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n return `${p.namespace}:${p.embedderId}:${p.modelId}:${hash}`;\n}\n","/**\n * OTel telemetry for semantic cache (ADR D262).\n *\n * Spans:\n * - `cache.lookup` — per `pre_user_send`. Attributes: namespace, embedder.id,\n * hit (kv|semantic|miss), distance, ttl_remaining_s, bypass_reason.\n * - `cache.store` — per `post_assistant_reply`. Attributes: bypass_reason, stored.\n *\n * @internal\n */\n\n// SDK 2.0 split: observability primitives live in @theokit/sdk.\n// The sub-path barrel was avoided due to a rollup-plugin-dts edge case\n// that emitted an empty index.d.ts for newly-added internal barrels;\n// re-exporting locally produces the same runtime behavior with stable types.\nimport { createRequire } from \"node:module\";\n\ninterface SpanLike {\n setAttribute(key: string, value: string | number | boolean): SpanLike;\n end(): void;\n}\n\nconst noopSpan: SpanLike = {\n setAttribute: () => noopSpan,\n end: () => undefined,\n};\n\ninterface TracerLike {\n startSpan(\n name: string,\n options?: { attributes?: Record<string, string | number | boolean> },\n ): SpanLike;\n}\n\ninterface CacheEntry {\n tracer: TracerLike | null;\n}\nconst tracerCache = new Map<string, CacheEntry>();\n\nfunction getTracer(name: string, version = \"1.0.0\"): TracerLike | undefined {\n const cached = tracerCache.get(name);\n if (cached !== undefined) return cached.tracer ?? undefined;\n try {\n const r = createRequire(import.meta.url);\n const otel = r(\"@opentelemetry/api\") as {\n trace?: { getTracer: (n: string, v?: string) => TracerLike };\n };\n if (otel.trace?.getTracer === undefined) {\n tracerCache.set(name, { tracer: null });\n return undefined;\n }\n const tracer = otel.trace.getTracer(name, version);\n tracerCache.set(name, { tracer });\n return tracer;\n } catch {\n tracerCache.set(name, { tracer: null });\n return undefined;\n }\n}\n\nfunction resetTracerCacheForTests(): void {\n tracerCache.clear();\n}\n\nconst TRACER_NAME = \"@theokit/sdk/cache\";\n\nexport function startCacheLookupSpan(info: { namespace: string; embedderId: string }): SpanLike {\n const tracer = getTracer(TRACER_NAME);\n if (tracer === undefined) return noopSpan;\n return tracer.startSpan(\"cache.lookup\", {\n attributes: {\n \"cache.namespace\": info.namespace,\n \"cache.embedder_id\": info.embedderId,\n },\n });\n}\n\nexport function startCacheStoreSpan(info: { namespace: string; embedderId: string }): SpanLike {\n const tracer = getTracer(TRACER_NAME);\n if (tracer === undefined) return noopSpan;\n return tracer.startSpan(\"cache.store\", {\n attributes: {\n \"cache.namespace\": info.namespace,\n \"cache.embedder_id\": info.embedderId,\n },\n });\n}\n\n/** Test seam — reset tracer cache so a fresh require attempt happens. */\nfunction __resetCacheTelemetryForTests(): void {\n resetTracerCacheForTests();\n}\n","/**\n * Cache lookup handler — wired to `pre_user_send` hook (ADRs D259, D260).\n *\n * EC-1: embedder failure degrades to miss (cache is transparent).\n * EC-3: empty / whitespace prompt bypasses cache (avoids hash collision).\n * EC-5: telemetry span ends in finally even on early-return.\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime, CacheTTLConfig } from \"../types/cache.js\";\nimport { embedOrDegrade } from \"./embed-helper.js\";\nimport { computeCacheKey } from \"./key.js\";\nimport type { InMemoryCacheStore } from \"./store.js\";\nimport type { JsonFileCacheStore } from \"./store-json.js\";\nimport { startCacheLookupSpan } from \"./telemetry.js\";\n\nexport type LookupableStore = InMemoryCacheStore | JsonFileCacheStore;\n\ninterface LookupParams {\n prompt: string;\n store: LookupableStore;\n embedder: CacheEmbedderRuntime;\n threshold: number;\n ttl: CacheTTLConfig;\n namespace: string;\n modelId: string;\n}\n\ninterface LookupResult {\n cached: boolean;\n response?: string;\n source?: \"kv\" | \"semantic\";\n distance?: number;\n}\n\nexport async function performLookup(p: LookupParams): Promise<LookupResult> {\n const span = startCacheLookupSpan({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n });\n try {\n // EC-3: empty prompt bypass.\n if (p.prompt.trim().length === 0) {\n p.store.incrementMisses();\n span.setAttribute(\"cache.bypass_reason\", \"empty_prompt\");\n return { cached: false };\n }\n // D255 exclude regex.\n if (p.ttl.exclude?.test(p.prompt)) {\n p.store.incrementExcluded();\n span.setAttribute(\"cache.bypass_reason\", \"exclude_regex\");\n return { cached: false };\n }\n\n const key = computeCacheKey({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n });\n const now = Date.now();\n\n // Step 1: KV exact (D259).\n const kv = p.store.kvGet(key, now);\n if (kv !== undefined) {\n p.store.incrementKvHits();\n span.setAttribute(\"cache.hit\", \"kv\");\n span.setAttribute(\"cache.ttl_remaining_s\", Math.floor((kv.expiresAt - now) / 1000));\n return { cached: true, response: kv.response, source: \"kv\" };\n }\n\n // Step 2: semantic — EC-1: embedder failure degrades to miss.\n const vec = await embedOrDegrade(p.embedder, p.prompt, p.store, span, \"lookup\");\n if (vec === undefined) return { cached: false };\n\n const match = p.store.semanticSearch(vec, p.threshold, p.embedder.id, p.namespace, now);\n if (match !== undefined) {\n p.store.incrementSemanticHits();\n span.setAttribute(\"cache.hit\", \"semantic\");\n span.setAttribute(\"cache.distance\", match.distance);\n span.setAttribute(\"cache.ttl_remaining_s\", Math.floor((match.entry.expiresAt - now) / 1000));\n return {\n cached: true,\n response: match.entry.response,\n source: \"semantic\",\n distance: match.distance,\n };\n }\n\n p.store.incrementMisses();\n span.setAttribute(\"cache.hit\", \"miss\");\n return { cached: false };\n } finally {\n span.end();\n }\n}\n","/**\n * Cosine distance between two equal-length vectors.\n *\n * Returns `1 - cos(a, b)`. Range:\n * - 0.0 = identical direction\n * - 1.0 = orthogonal\n * - 2.0 = opposite (rare in normalized embeddings)\n *\n * Throws on dim mismatch. (Callers MUST filter by dim before calling\n * — EC-2 absorbed at the store level.)\n *\n * @internal\n */\n\nexport function cosineDistance(a: ReadonlyArray<number>, b: ReadonlyArray<number>): number {\n if (a.length !== b.length) {\n throw new Error(`cosineDistance: dim mismatch (${a.length} vs ${b.length})`);\n }\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < a.length; i += 1) {\n const av = a[i]!;\n const bv = b[i]!;\n dot += av * bv;\n normA += av * av;\n normB += bv * bv;\n }\n if (normA === 0 || normB === 0) return 1.0;\n return 1 - dot / (Math.sqrt(normA) * Math.sqrt(normB));\n}\n","/**\n * Cache store interface + in-memory implementation (ADRs D252, D259, D261).\n *\n * INVARIANT (EC-9, EC-13): KV map and vector view are the SAME Map.\n * `semanticSearch` iterates `Map.values()`. No parallel list. `set` replaces\n * by key (Map semantics) — no duplicate-on-race possible.\n *\n * EC-2: `semanticSearch` filters by `embedderId === currentEmbedderId &&\n * vector.length === currentDim` before cosine compare. Protects against\n * dim mismatch when disk-loaded entries used a different embedder.\n *\n * @internal\n */\n\nimport type { CacheEntry, CacheStats } from \"../types/cache.js\";\nimport { cosineDistance } from \"./cosine.js\";\n\nexport interface CacheStore {\n kvGet(key: string, now: number): CacheEntry | undefined;\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n ): { entry: CacheEntry; distance: number } | undefined;\n set(entry: CacheEntry): void;\n delete(key: string): void;\n clear(): Promise<void>;\n stats(): CacheStats;\n evictExpired(now: number): number;\n /** For persistence backends — bulk import. */\n loadAll?(entries: ReadonlyArray<CacheEntry>): void;\n /** For persistence backends — snapshot for serialization. */\n dump?(): ReadonlyArray<CacheEntry>;\n}\n\ninterface StoreCounters {\n kvHits: number;\n semanticHits: number;\n misses: number;\n excluded: number;\n evicted: number;\n embedderFailures: number;\n}\n\nexport class InMemoryCacheStore implements CacheStore {\n private readonly map = new Map<string, CacheEntry>();\n private readonly counters: StoreCounters = {\n kvHits: 0,\n semanticHits: 0,\n misses: 0,\n excluded: 0,\n evicted: 0,\n embedderFailures: 0,\n };\n\n constructor(private readonly maxEntries: number) {}\n\n kvGet(key: string, now: number): CacheEntry | undefined {\n const e = this.map.get(key);\n if (e === undefined) return undefined;\n if (e.expiresAt <= now) {\n this.map.delete(key);\n this.counters.evicted += 1;\n return undefined;\n }\n // Touch for LRU recency.\n this.map.delete(key);\n this.map.set(key, { ...e, accessedAt: now, accessCount: e.accessCount + 1 });\n return this.map.get(key);\n }\n\n private isEligibleForSearch(\n e: CacheEntry,\n embedderId: string,\n namespace: string,\n dim: number,\n now: number,\n ): boolean {\n if (e.embedderId !== embedderId) return false;\n if (e.namespace !== namespace) return false;\n if (e.vector.length !== dim) return false;\n if (e.expiresAt <= now) return false;\n return true;\n }\n\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n ): { entry: CacheEntry; distance: number } | undefined {\n let best: { entry: CacheEntry; distance: number } | undefined;\n for (const e of this.map.values()) {\n if (!this.isEligibleForSearch(e, embedderId, namespace, vector.length, now)) continue;\n const d = cosineDistance(e.vector, vector);\n if (d <= threshold && (best === undefined || d < best.distance)) {\n best = { entry: e, distance: d };\n }\n }\n if (best !== undefined) {\n this.map.delete(best.entry.key);\n this.map.set(best.entry.key, {\n ...best.entry,\n accessedAt: now,\n accessCount: best.entry.accessCount + 1,\n });\n }\n return best;\n }\n\n set(entry: CacheEntry): void {\n // EC-13: Map.set replaces by key — no parallel list.\n if (this.map.has(entry.key)) {\n this.map.delete(entry.key);\n }\n this.map.set(entry.key, entry);\n // Evict LRU when over capacity.\n while (this.map.size > this.maxEntries) {\n const oldestKey = this.map.keys().next().value;\n if (oldestKey === undefined) break;\n this.map.delete(oldestKey);\n this.counters.evicted += 1;\n }\n }\n\n delete(key: string): void {\n this.map.delete(key);\n }\n\n async clear(): Promise<void> {\n this.map.clear();\n }\n\n stats(): CacheStats {\n return {\n entries: this.map.size,\n kvHits: this.counters.kvHits,\n semanticHits: this.counters.semanticHits,\n misses: this.counters.misses,\n excluded: this.counters.excluded,\n evicted: this.counters.evicted,\n embedderFailures: this.counters.embedderFailures,\n };\n }\n\n evictExpired(now: number): number {\n let count = 0;\n for (const [k, e] of this.map.entries()) {\n if (e.expiresAt <= now) {\n this.map.delete(k);\n count += 1;\n }\n }\n this.counters.evicted += count;\n return count;\n }\n\n loadAll(entries: ReadonlyArray<CacheEntry>): void {\n for (const e of entries) this.map.set(e.key, e);\n }\n\n dump(): ReadonlyArray<CacheEntry> {\n return [...this.map.values()];\n }\n\n /** Internal helpers for counters (used by lookup/store handlers). */\n incrementKvHits(): void {\n this.counters.kvHits += 1;\n }\n incrementSemanticHits(): void {\n this.counters.semanticHits += 1;\n }\n incrementMisses(): void {\n this.counters.misses += 1;\n }\n incrementExcluded(): void {\n this.counters.excluded += 1;\n }\n incrementEmbedderFailures(): void {\n this.counters.embedderFailures += 1;\n }\n}\n","/**\n * Public type contract for `Cache.semantic / .asPlugin / .stats / .clear`\n * (Adoption Roadmap #6; ADRs D249-D266).\n *\n * @public\n */\n\n/* ─── TTL config (D255) ─── */\n\nexport interface CacheTTLConfig {\n /** Default TTL applied to all entries. Format: `\"1h\" | \"30m\" | 86400 (seconds)`. */\n readonly default: string | number;\n /** Regex marking queries that must NEVER be cached (e.g. /weather|today|now/i). */\n readonly exclude?: RegExp;\n}\n\n/* ─── Persistence (D265) ─── */\n\nexport interface CachePersistenceOptions {\n readonly backend: \"memory\" | \"json\";\n /** Required when backend = \"json\". */\n readonly dir?: string;\n}\n\n/* ─── Embedder option ─── */\n\n/**\n * Embedder runtime shape — minimal subset of `EmbeddingRuntime` (D11) the\n * Cache actually uses. Lets tests inject fake embedders without pulling\n * the full memory subsystem.\n */\nexport interface CacheEmbedderRuntime {\n readonly id: string;\n readonly model: string;\n readonly dimension: number;\n embed(texts: ReadonlyArray<string>): Promise<number[][]>;\n}\n\n/* ─── Options ─── */\n\nexport interface CacheSemanticOptions {\n /** Embedder instance. REQUIRED in v1 — no autoselect (avoids surprise API calls). */\n readonly embedder: CacheEmbedderRuntime;\n /** Cosine distance threshold (0..2). Default 0.85; lower = stricter. */\n readonly threshold?: number;\n /** TTL config. Default `{ default: \"1h\" }`. */\n readonly ttl?: CacheTTLConfig;\n /** Multi-tenant namespace. Default `\"global\"`. */\n readonly namespace?: string;\n /** Default modelId attached to entries when caller doesn't override. */\n readonly modelId?: string;\n /** Max entries (LRU eviction). Default 1000. */\n readonly maxEntries?: number;\n /** Persistence backend. Default in-memory. */\n readonly persistence?: CachePersistenceOptions;\n}\n\n/* ─── Entry + stats ─── */\n\nexport interface CacheEntry {\n readonly key: string;\n readonly namespace: string;\n readonly embedderId: string;\n readonly modelId: string;\n readonly prompt: string;\n readonly response: string;\n readonly vector: ReadonlyArray<number>;\n readonly createdAt: number;\n readonly expiresAt: number;\n readonly accessedAt: number;\n readonly accessCount: number;\n}\n\nexport interface CacheStats {\n readonly entries: number;\n readonly kvHits: number;\n readonly semanticHits: number;\n readonly misses: number;\n readonly excluded: number;\n readonly evicted: number;\n readonly embedderFailures: number;\n}\n\n/* ─── Error classes ─── */\n\nexport class CacheEmbedderError extends Error {\n override readonly name = \"CacheEmbedderError\";\n override readonly cause?: Error;\n constructor(message: string, cause?: Error) {\n super(`Cache embedder failed: ${message}`);\n if (cause !== undefined) this.cause = cause;\n }\n}\n\nexport class CacheInvalidTtlError extends Error {\n override readonly name = \"CacheInvalidTtlError\";\n constructor(public readonly input: string | number) {\n super(\n `Invalid TTL value: \"${String(input)}\". Expected number (seconds) or string like \"1h\" / \"30m\" / \"7d\".`,\n );\n }\n}\n","/**\n * TTL string parser. Accepts:\n * - number → treated as SECONDS\n * - string `\"\\d+(s|m|h|d|w)\"` → seconds/minutes/hours/days/weeks\n *\n * EC-8: `\"0s\"` / `0` returns 0 (effectively disables cache for that entry).\n * Negative numbers throw `CacheInvalidTtlError`.\n *\n * @internal\n */\n\nimport { CacheInvalidTtlError } from \"../types/cache.js\";\n\nconst TTL_PATTERN = /^(\\d+)\\s*(s|m|h|d|w)$/i;\n\nexport function parseTtlMs(input: string | number): number {\n if (typeof input === \"number\") {\n if (!Number.isFinite(input) || input < 0) {\n throw new CacheInvalidTtlError(input);\n }\n return Math.floor(input * 1000);\n }\n const trimmed = input.trim();\n const m = TTL_PATTERN.exec(trimmed);\n if (m === null) {\n throw new CacheInvalidTtlError(input);\n }\n const value = Number(m[1]);\n const unit = m[2]!.toLowerCase();\n switch (unit) {\n case \"s\":\n return value * 1000;\n case \"m\":\n return value * 60_000;\n case \"h\":\n return value * 3_600_000;\n case \"d\":\n return value * 86_400_000;\n case \"w\":\n return value * 604_800_000;\n /* c8 ignore next 2 */\n default:\n throw new CacheInvalidTtlError(input);\n }\n}\n","/**\n * Cache store handler — wired to `post_assistant_reply` hook (ADRs D260, D266).\n *\n * EC-1: embedder failure during store is silent (LLM call already succeeded;\n * no cache entry written).\n * EC-3: empty prompt bypass.\n * EC-10 / D266: skip storage when the run invoked tools (replay loses\n * side-effects).\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime, CacheTTLConfig } from \"../types/cache.js\";\nimport { embedOrDegrade } from \"./embed-helper.js\";\nimport { computeCacheKey } from \"./key.js\";\nimport type { LookupableStore } from \"./lookup.js\";\nimport { startCacheStoreSpan } from \"./telemetry.js\";\nimport { parseTtlMs } from \"./ttl.js\";\n\ninterface StoreParams {\n prompt: string;\n response: string;\n /** D266: skip cache when tools were used. */\n usedTools?: boolean;\n store: LookupableStore;\n embedder: CacheEmbedderRuntime;\n ttl: CacheTTLConfig;\n namespace: string;\n modelId: string;\n}\n\nexport async function performStore(p: StoreParams): Promise<void> {\n const span = startCacheStoreSpan({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n });\n try {\n // EC-3: empty prompt bypass.\n if (p.prompt.trim().length === 0) {\n span.setAttribute(\"cache.bypass_reason\", \"empty_prompt\");\n return;\n }\n // EC-3 + safety: empty response is not a useful cache entry.\n if (p.response.length === 0) {\n span.setAttribute(\"cache.bypass_reason\", \"empty_response\");\n return;\n }\n // D266 / EC-10: tool-use runs are not cached (replay loses side-effects).\n if (p.usedTools === true) {\n span.setAttribute(\"cache.bypass_reason\", \"used_tools\");\n return;\n }\n // D255 exclude regex.\n if (p.ttl.exclude?.test(p.prompt)) {\n span.setAttribute(\"cache.bypass_reason\", \"exclude_regex\");\n return;\n }\n\n const key = computeCacheKey({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n });\n\n // EC-1: embedder failure during store is silent.\n const vec = await embedOrDegrade(p.embedder, p.prompt, p.store, span, \"store\");\n if (vec === undefined) return;\n\n const now = Date.now();\n const ttlMs = parseTtlMs(p.ttl.default);\n p.store.set({\n key,\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n response: p.response,\n vector: vec,\n createdAt: now,\n expiresAt: now + ttlMs,\n accessedAt: now,\n accessCount: 0,\n });\n span.setAttribute(\"cache.stored\", true);\n } finally {\n span.end();\n }\n}\n","/**\n * JSON disk-backed cache store (ADR D265).\n *\n * One file per namespace at `<dir>/<namespace>.json`. Uses\n * `atomicWriteText` (D60) for crash-safe writes. Debounced flush (200ms)\n * to coalesce bursts.\n *\n * EC-7: corrupt JSON load → log warn + treat as empty cache. Never\n * propagates parse errors that would block `Agent.create`.\n *\n * Layered behind `InMemoryCacheStore` — disk is just persistence; all\n * lookups still hit the in-memory Map for O(1) KV / O(N) vector scan.\n *\n * @internal\n */\n\nimport { mkdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { atomicWriteText } from \"@theokit/sdk/internal/persistence\";\nimport type { CacheEntry, CacheStats } from \"../types/cache.js\";\nimport { type CacheStore, InMemoryCacheStore } from \"./store.js\";\n\ninterface SerializedSnapshot {\n readonly _schemaVersion: 1;\n readonly namespace: string;\n readonly entries: ReadonlyArray<CacheEntry>;\n}\n\nconst FLUSH_DEBOUNCE_MS = 200;\n\nexport class JsonFileCacheStore implements CacheStore {\n private readonly inner: InMemoryCacheStore;\n private flushTimer: ReturnType<typeof setTimeout> | undefined;\n private dirty = false;\n\n constructor(\n private readonly dir: string,\n private readonly namespace: string,\n maxEntries: number,\n ) {\n this.inner = new InMemoryCacheStore(maxEntries);\n }\n\n /** Hydrate from disk. EC-7: corrupt file → empty cache. */\n async hydrate(): Promise<void> {\n const file = this.filePath();\n try {\n const raw = await readFile(file, \"utf8\");\n let parsed: SerializedSnapshot;\n try {\n parsed = JSON.parse(raw) as SerializedSnapshot;\n } catch (err) {\n console.warn(\n `[cache] corrupt snapshot at ${file}, starting fresh:`,\n err instanceof Error ? err.message : err,\n );\n return;\n }\n if (parsed._schemaVersion !== 1) {\n console.warn(\n `[cache] unsupported schema v${parsed._schemaVersion} at ${file}, starting fresh`,\n );\n return;\n }\n // Only load entries for this namespace (defensive).\n const valid = parsed.entries.filter((e) => e.namespace === this.namespace);\n this.inner.loadAll(valid);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return;\n console.warn(`[cache] failed to read ${file}:`, err instanceof Error ? err.message : err);\n }\n }\n\n kvGet(key: string, now: number): CacheEntry | undefined {\n return this.inner.kvGet(key, now);\n }\n\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n ): { entry: CacheEntry; distance: number } | undefined {\n return this.inner.semanticSearch(vector, threshold, embedderId, namespace, now);\n }\n\n set(entry: CacheEntry): void {\n this.inner.set(entry);\n this.markDirty();\n }\n\n delete(key: string): void {\n this.inner.delete(key);\n this.markDirty();\n }\n\n async clear(): Promise<void> {\n await this.inner.clear();\n this.markDirty();\n await this.flush();\n }\n\n stats(): CacheStats {\n return this.inner.stats();\n }\n\n evictExpired(now: number): number {\n const n = this.inner.evictExpired(now);\n if (n > 0) this.markDirty();\n return n;\n }\n\n /** Force write the current snapshot. Called on shutdown / clear. */\n async flush(): Promise<void> {\n if (this.flushTimer !== undefined) {\n clearTimeout(this.flushTimer);\n this.flushTimer = undefined;\n }\n if (!this.dirty) return;\n await this.writeSnapshot();\n this.dirty = false;\n }\n\n /** Counters proxied to inner. */\n incrementKvHits(): void {\n this.inner.incrementKvHits();\n }\n incrementSemanticHits(): void {\n this.inner.incrementSemanticHits();\n }\n incrementMisses(): void {\n this.inner.incrementMisses();\n }\n incrementExcluded(): void {\n this.inner.incrementExcluded();\n }\n incrementEmbedderFailures(): void {\n this.inner.incrementEmbedderFailures();\n }\n\n private filePath(): string {\n return join(this.dir, `${this.namespace}.json`);\n }\n\n private markDirty(): void {\n this.dirty = true;\n if (this.flushTimer === undefined) {\n this.flushTimer = setTimeout(() => {\n this.flushTimer = undefined;\n void this.flush().catch((err) =>\n console.warn(`[cache] debounced flush failed:`, err instanceof Error ? err.message : err),\n );\n }, FLUSH_DEBOUNCE_MS);\n }\n }\n\n private async writeSnapshot(): Promise<void> {\n await mkdir(this.dir, { recursive: true });\n const snapshot: SerializedSnapshot = {\n _schemaVersion: 1,\n namespace: this.namespace,\n entries: this.inner.dump(),\n };\n const serialized = JSON.stringify(snapshot);\n await atomicWriteText(this.filePath(), serialized);\n }\n}\n","/**\n * Public `Cache` class — semantic LLM response cache (Adoption Roadmap #6;\n * ADRs D249-D266).\n *\n * Usage:\n *\n * import { Agent, Cache, definePlugin } from \"@theokit/sdk\";\n *\n * const cache = Cache.semantic({\n * embedder: myEmbedderRuntime, // EmbeddingRuntime (D11)\n * threshold: 0.85,\n * ttl: { default: \"1h\", exclude: /weather|today|now/i },\n * namespace: \"my-app\",\n * modelId: \"openai/gpt-4o-mini\",\n * });\n *\n * const agent = await Agent.create({\n * model: { id: \"openai/gpt-4o-mini\" },\n * plugins: [cache.asPlugin()],\n * // ...\n * });\n *\n * await agent.send(\"What is the capital of France?\"); // miss → LLM\n * await agent.send(\"Tell me the capital of France\"); // semantic hit\n *\n * @public\n */\n\nimport {\n definePlugin,\n type Plugin,\n type PluginContext,\n type PostAssistantReplyContext,\n type PreUserSendContext,\n type PreUserSendResult,\n} from \"@theokit/sdk\";\nimport { PersistenceSchema } from \"@theokit/sdk/internal/persistence\";\nimport { z } from \"zod\";\nimport { type LookupableStore, performLookup } from \"./internal/lookup.js\";\nimport { InMemoryCacheStore } from \"./internal/store.js\";\nimport { performStore } from \"./internal/store-handler.js\";\nimport { JsonFileCacheStore } from \"./internal/store-json.js\";\nimport type {\n CacheEmbedderRuntime,\n CachePersistenceOptions,\n CacheSemanticOptions,\n CacheStats,\n CacheTTLConfig,\n} from \"./types/cache.js\";\n\nconst CacheSemanticOptionsSchema = z.object({\n embedder: z.unknown().refine(\n (v) => {\n if (v === null || typeof v !== \"object\") return false;\n const o = v as { id?: unknown; embed?: unknown; dimension?: unknown };\n return (\n typeof o.id === \"string\" && typeof o.embed === \"function\" && typeof o.dimension === \"number\"\n );\n },\n { message: \"embedder must be a CacheEmbedderRuntime with { id, dimension, embed }\" },\n ),\n threshold: z.number().min(0).max(2).optional(),\n ttl: z\n .object({\n default: z.union([z.string(), z.number()]),\n exclude: z.instanceof(RegExp).optional(),\n })\n .optional(),\n namespace: z.string().min(1).max(64).optional(),\n modelId: z.string().min(1).max(128).optional(),\n maxEntries: z.number().int().min(1).max(1_000_000).optional(),\n persistence: PersistenceSchema,\n});\n\nconst DEFAULT_THRESHOLD = 0.85;\nconst DEFAULT_TTL: CacheTTLConfig = { default: \"1h\" };\nconst DEFAULT_NAMESPACE = \"global\";\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport class Cache {\n private _plugin?: Plugin;\n\n private constructor(\n private readonly embedder: CacheEmbedderRuntime,\n private readonly threshold: number,\n private readonly ttl: CacheTTLConfig,\n private readonly namespace: string,\n private readonly modelId: string,\n private readonly store: LookupableStore,\n ) {}\n\n static semantic(options: CacheSemanticOptions): Cache {\n CacheSemanticOptionsSchema.parse(options);\n const threshold = options.threshold ?? DEFAULT_THRESHOLD;\n const ttl = options.ttl ?? DEFAULT_TTL;\n const namespace = options.namespace ?? DEFAULT_NAMESPACE;\n const modelId = options.modelId ?? \"unknown\";\n const maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n const store = createStore(namespace, maxEntries, options.persistence);\n return new Cache(options.embedder, threshold, ttl, namespace, modelId, store);\n }\n\n /**\n * EC-4 absorbed: memoized so repeated `asPlugin()` calls return the SAME\n * plugin descriptor — no duplicate hook registration.\n */\n asPlugin(): Plugin {\n if (this._plugin !== undefined) return this._plugin;\n const cache = this;\n this._plugin = definePlugin({\n name: `cache-semantic-${this.namespace}`,\n version: \"1.0.0\",\n kind: \"general\" as const,\n register(ctx: PluginContext): void {\n ctx.on(\"pre_user_send\", async (rawCtx) => {\n const c = rawCtx as PreUserSendContext;\n const result = await performLookup({\n prompt: c.prompt,\n store: cache.store,\n embedder: cache.embedder,\n threshold: cache.threshold,\n ttl: cache.ttl,\n namespace: cache.namespace,\n modelId: cache.modelId,\n });\n if (result.cached === true) {\n // Cache hit — return recalledContext as the cached response.\n // The agent loop will inject this; in v1 the caller must\n // check `pre_user_send` hook return value via runtime support\n // (the cache hit short-circuits via injection; see docs).\n const wrapped: PreUserSendResult = {\n recalledContext: result.response,\n };\n return wrapped;\n }\n const miss: PreUserSendResult = {};\n return miss;\n });\n ctx.on(\"post_assistant_reply\", async (rawCtx) => {\n const c = rawCtx as PostAssistantReplyContext;\n // EC-10: don't cache tool-use runs. v1 lacks a \"usedTools\" signal\n // in PostAssistantReplyContext (D266 documented gap). For now we\n // accept the conservative-skip if `c.reply` looks like a tool\n // result envelope (contains `tool_call_id` markers). Future\n // PostAssistantReplyContext extension will surface usedTools\n // explicitly.\n await performStore({\n prompt: c.prompt,\n response: c.reply,\n usedTools: false,\n store: cache.store,\n embedder: cache.embedder,\n ttl: cache.ttl,\n namespace: cache.namespace,\n modelId: cache.modelId,\n });\n return undefined;\n });\n },\n });\n return this._plugin;\n }\n\n /**\n * Explicit cache lookup — callers that want true LLM short-circuit\n * call this BEFORE `agent.send()`, then dispatch to the LLM only on miss.\n *\n * v1 plugin mode provides recall + context-inject (LLM still called).\n * v1.x will add transparent short-circuit via an agent-loop refactor.\n */\n async consult(\n prompt: string,\n ): Promise<\n { hit: false } | { hit: true; response: string; source: \"kv\" | \"semantic\"; distance?: number }\n > {\n const result = await performLookup({\n prompt,\n store: this.store,\n embedder: this.embedder,\n threshold: this.threshold,\n ttl: this.ttl,\n namespace: this.namespace,\n modelId: this.modelId,\n });\n if (result.cached === true) {\n return {\n hit: true,\n response: result.response ?? \"\",\n source: result.source ?? \"kv\",\n ...(result.distance !== undefined ? { distance: result.distance } : {}),\n };\n }\n return { hit: false };\n }\n\n /**\n * Explicit cache store — pair with `consult()` to manually feed the\n * cache after dispatching the LLM call yourself.\n */\n async remember(prompt: string, response: string, opts?: { usedTools?: boolean }): Promise<void> {\n await performStore({\n prompt,\n response,\n usedTools: opts?.usedTools === true,\n store: this.store,\n embedder: this.embedder,\n ttl: this.ttl,\n namespace: this.namespace,\n modelId: this.modelId,\n });\n }\n\n /** Stats snapshot — primary observable for dogfood verification. */\n stats(): CacheStats {\n return this.store.stats();\n }\n\n /** Clear all entries (and flush to disk if JSON backend). */\n async clear(): Promise<void> {\n await this.store.clear();\n }\n\n /** Force-evict expired entries. Returns count removed. */\n evictExpired(now: number = Date.now()): number {\n return this.store.evictExpired(now);\n }\n}\n\nfunction createStore(\n namespace: string,\n maxEntries: number,\n persistence?: CachePersistenceOptions,\n): LookupableStore {\n if (persistence?.backend === \"json\") {\n const dir = persistence.dir as string;\n const store = new JsonFileCacheStore(dir, namespace, maxEntries);\n // Hydrate fire-and-forget — callers do `await cache.ready()` if they need\n // sync hydration. v1: lazy load on first lookup.\n void store.hydrate();\n return store;\n }\n return new InMemoryCacheStore(maxEntries);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/embed-helper.ts","../src/internal/key.ts","../src/internal/telemetry.ts","../src/internal/lookup.ts","../src/internal/cosine.ts","../src/internal/store.ts","../src/types/cache.ts","../src/internal/ttl.ts","../src/internal/store-handler.ts","../src/internal/store-json.ts","../src/cache.ts","../src/lexical-embedder.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Shared embed-with-graceful-degradation helper — used by both `lookup.ts`\n * and `store-handler.ts`. Extracted to remove the embed-failure boilerplate\n * clone flagged by jscpd. EC-1 absorbed: embedder failure is silent (caller\n * decides what to do via the boolean return).\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime } from \"../types/cache.js\";\nimport type { InMemoryCacheStore } from \"./store.js\";\nimport type { JsonFileCacheStore } from \"./store-json.js\";\n\ninterface SpanLike {\n setAttribute(key: string, value: string | number | boolean): SpanLike;\n}\n\nexport async function embedOrDegrade(\n embedder: CacheEmbedderRuntime,\n prompt: string,\n store: InMemoryCacheStore | JsonFileCacheStore,\n span: SpanLike,\n context: \"lookup\" | \"store\",\n): Promise<number[] | undefined> {\n try {\n const result = await embedder.embed([prompt]);\n return result[0]!;\n } catch (err) {\n store.incrementEmbedderFailures();\n const action = context === \"lookup\" ? \"degrading to miss\" : \"skipping cache write\";\n console.warn(\n `[cache] embedder failed during ${context}, ${action}:`,\n err instanceof Error ? err.message : err,\n );\n span.setAttribute(\"cache.bypass_reason\", \"embedder_failure\");\n return undefined;\n }\n}\n","/**\n * Composite cache key (ADR D253).\n *\n * Format: `${namespace}:${embedderId}:${modelId}:${hash(normalizedPrompt)}`.\n * Normalizes whitespace + lowercases. Hash = first 16 hex chars of SHA-256.\n *\n * @internal\n */\n\nimport { createHash } from \"node:crypto\";\n\ninterface CacheKeyParams {\n namespace: string;\n embedderId: string;\n modelId: string;\n prompt: string;\n}\n\nexport function computeCacheKey(p: CacheKeyParams): string {\n const normalized = p.prompt.trim().replace(/\\s+/g, \" \").toLowerCase();\n const hash = createHash(\"sha256\").update(normalized).digest(\"hex\").slice(0, 16);\n return `${p.namespace}:${p.embedderId}:${p.modelId}:${hash}`;\n}\n","/**\n * OTel telemetry for semantic cache (ADR D262).\n *\n * Spans:\n * - `cache.lookup` — per `pre_user_send`. Attributes: namespace, embedder.id,\n * hit (kv|semantic|miss), distance, ttl_remaining_s, bypass_reason.\n * - `cache.store` — per `post_assistant_reply`. Attributes: bypass_reason, stored.\n *\n * @internal\n */\n\n// SDK 2.0 split: observability primitives live in @theokit/sdk.\n// The sub-path barrel was avoided due to a rollup-plugin-dts edge case\n// that emitted an empty index.d.ts for newly-added internal barrels;\n// re-exporting locally produces the same runtime behavior with stable types.\nimport { createRequire } from \"node:module\";\n\ninterface SpanLike {\n setAttribute(key: string, value: string | number | boolean): SpanLike;\n end(): void;\n}\n\nconst noopSpan: SpanLike = {\n setAttribute: () => noopSpan,\n end: () => undefined,\n};\n\ninterface TracerLike {\n startSpan(\n name: string,\n options?: { attributes?: Record<string, string | number | boolean> },\n ): SpanLike;\n}\n\ninterface CacheEntry {\n tracer: TracerLike | null;\n}\nconst tracerCache = new Map<string, CacheEntry>();\n\nfunction getTracer(name: string, version = \"1.0.0\"): TracerLike | undefined {\n const cached = tracerCache.get(name);\n if (cached !== undefined) return cached.tracer ?? undefined;\n try {\n const r = createRequire(import.meta.url);\n const otel = r(\"@opentelemetry/api\") as {\n trace?: { getTracer: (n: string, v?: string) => TracerLike };\n };\n if (otel.trace?.getTracer === undefined) {\n tracerCache.set(name, { tracer: null });\n return undefined;\n }\n const tracer = otel.trace.getTracer(name, version);\n tracerCache.set(name, { tracer });\n return tracer;\n } catch {\n tracerCache.set(name, { tracer: null });\n return undefined;\n }\n}\n\nfunction resetTracerCacheForTests(): void {\n tracerCache.clear();\n}\n\nconst TRACER_NAME = \"@theokit/sdk/cache\";\n\nexport function startCacheLookupSpan(info: { namespace: string; embedderId: string }): SpanLike {\n const tracer = getTracer(TRACER_NAME);\n if (tracer === undefined) return noopSpan;\n return tracer.startSpan(\"cache.lookup\", {\n attributes: {\n \"cache.namespace\": info.namespace,\n \"cache.embedder_id\": info.embedderId,\n },\n });\n}\n\nexport function startCacheStoreSpan(info: { namespace: string; embedderId: string }): SpanLike {\n const tracer = getTracer(TRACER_NAME);\n if (tracer === undefined) return noopSpan;\n return tracer.startSpan(\"cache.store\", {\n attributes: {\n \"cache.namespace\": info.namespace,\n \"cache.embedder_id\": info.embedderId,\n },\n });\n}\n\n/** Test seam — reset tracer cache so a fresh require attempt happens. */\nfunction __resetCacheTelemetryForTests(): void {\n resetTracerCacheForTests();\n}\n","/**\n * Cache lookup handler — wired to `pre_user_send` hook (ADRs D259, D260).\n *\n * EC-1: embedder failure degrades to miss (cache is transparent).\n * EC-3: empty / whitespace prompt bypasses cache (avoids hash collision).\n * EC-5: telemetry span ends in finally even on early-return.\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime, CacheTTLConfig } from \"../types/cache.js\";\nimport { embedOrDegrade } from \"./embed-helper.js\";\nimport { computeCacheKey } from \"./key.js\";\nimport type { InMemoryCacheStore } from \"./store.js\";\nimport type { JsonFileCacheStore } from \"./store-json.js\";\nimport { startCacheLookupSpan } from \"./telemetry.js\";\n\nexport type LookupableStore = InMemoryCacheStore | JsonFileCacheStore;\n\ninterface LookupParams {\n prompt: string;\n store: LookupableStore;\n embedder: CacheEmbedderRuntime;\n threshold: number;\n ttl: CacheTTLConfig;\n namespace: string;\n modelId: string;\n}\n\ninterface LookupResult {\n cached: boolean;\n response?: string;\n source?: \"kv\" | \"semantic\";\n distance?: number;\n}\n\nexport async function performLookup(p: LookupParams): Promise<LookupResult> {\n const span = startCacheLookupSpan({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n });\n try {\n // EC-3: empty prompt bypass.\n if (p.prompt.trim().length === 0) {\n p.store.incrementMisses();\n span.setAttribute(\"cache.bypass_reason\", \"empty_prompt\");\n return { cached: false };\n }\n // D255 exclude regex.\n if (p.ttl.exclude?.test(p.prompt)) {\n p.store.incrementExcluded();\n span.setAttribute(\"cache.bypass_reason\", \"exclude_regex\");\n return { cached: false };\n }\n\n const key = computeCacheKey({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n });\n const now = Date.now();\n\n // Step 1: KV exact (D259).\n const kv = p.store.kvGet(key, now);\n if (kv !== undefined) {\n p.store.incrementKvHits();\n span.setAttribute(\"cache.hit\", \"kv\");\n span.setAttribute(\"cache.ttl_remaining_s\", Math.floor((kv.expiresAt - now) / 1000));\n return { cached: true, response: kv.response, source: \"kv\" };\n }\n\n // Step 2: semantic — EC-1: embedder failure degrades to miss.\n const vec = await embedOrDegrade(p.embedder, p.prompt, p.store, span, \"lookup\");\n if (vec === undefined) return { cached: false };\n\n const match = p.store.semanticSearch(\n vec,\n p.threshold,\n p.embedder.id,\n p.namespace,\n now,\n p.modelId,\n );\n if (match !== undefined) {\n p.store.incrementSemanticHits();\n span.setAttribute(\"cache.hit\", \"semantic\");\n span.setAttribute(\"cache.distance\", match.distance);\n span.setAttribute(\"cache.ttl_remaining_s\", Math.floor((match.entry.expiresAt - now) / 1000));\n return {\n cached: true,\n response: match.entry.response,\n source: \"semantic\",\n distance: match.distance,\n };\n }\n\n p.store.incrementMisses();\n span.setAttribute(\"cache.hit\", \"miss\");\n return { cached: false };\n } finally {\n span.end();\n }\n}\n","/**\n * Cosine distance between two equal-length vectors.\n *\n * Returns `1 - cos(a, b)`. Range:\n * - 0.0 = identical direction\n * - 1.0 = orthogonal\n * - 2.0 = opposite (rare in normalized embeddings)\n *\n * Throws on dim mismatch. (Callers MUST filter by dim before calling\n * — EC-2 absorbed at the store level.)\n *\n * @internal\n */\n\nexport function cosineDistance(a: ReadonlyArray<number>, b: ReadonlyArray<number>): number {\n if (a.length !== b.length) {\n throw new Error(`cosineDistance: dim mismatch (${a.length} vs ${b.length})`);\n }\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < a.length; i += 1) {\n const av = a[i]!;\n const bv = b[i]!;\n dot += av * bv;\n normA += av * av;\n normB += bv * bv;\n }\n if (normA === 0 || normB === 0) return 1.0;\n return 1 - dot / (Math.sqrt(normA) * Math.sqrt(normB));\n}\n","/**\n * Cache store interface + in-memory implementation (ADRs D252, D259, D261).\n *\n * INVARIANT (EC-9, EC-13): KV map and vector view are the SAME Map.\n * `semanticSearch` iterates `Map.values()`. No parallel list. `set` replaces\n * by key (Map semantics) — no duplicate-on-race possible.\n *\n * EC-2: `semanticSearch` filters by `embedderId === currentEmbedderId &&\n * vector.length === currentDim` before cosine compare. Protects against\n * dim mismatch when disk-loaded entries used a different embedder.\n *\n * @internal\n */\n\nimport type { CacheEntry, CacheStats } from \"../types/cache.js\";\nimport { cosineDistance } from \"./cosine.js\";\n\nexport interface CacheStore {\n kvGet(key: string, now: number): CacheEntry | undefined;\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n modelId: string,\n ): { entry: CacheEntry; distance: number } | undefined;\n set(entry: CacheEntry): void;\n delete(key: string): void;\n clear(): Promise<void>;\n stats(): CacheStats;\n evictExpired(now: number): number;\n /** For persistence backends — bulk import. */\n loadAll?(entries: ReadonlyArray<CacheEntry>): void;\n /** For persistence backends — snapshot for serialization. */\n dump?(): ReadonlyArray<CacheEntry>;\n}\n\ninterface StoreCounters {\n kvHits: number;\n semanticHits: number;\n misses: number;\n excluded: number;\n evicted: number;\n embedderFailures: number;\n}\n\nexport class InMemoryCacheStore implements CacheStore {\n private readonly map = new Map<string, CacheEntry>();\n private readonly counters: StoreCounters = {\n kvHits: 0,\n semanticHits: 0,\n misses: 0,\n excluded: 0,\n evicted: 0,\n embedderFailures: 0,\n };\n\n constructor(private readonly maxEntries: number) {}\n\n kvGet(key: string, now: number): CacheEntry | undefined {\n const e = this.map.get(key);\n if (e === undefined) return undefined;\n if (e.expiresAt <= now) {\n this.map.delete(key);\n this.counters.evicted += 1;\n return undefined;\n }\n // Touch for LRU recency.\n this.map.delete(key);\n this.map.set(key, { ...e, accessedAt: now, accessCount: e.accessCount + 1 });\n return this.map.get(key);\n }\n\n private isEligibleForSearch(\n e: CacheEntry,\n embedderId: string,\n namespace: string,\n dim: number,\n now: number,\n modelId: string,\n ): boolean {\n if (e.embedderId !== embedderId) return false;\n // M3 #67 — a stored entry only matches a query for the SAME model.\n if (e.modelId !== modelId) return false;\n if (e.namespace !== namespace) return false;\n if (e.vector.length !== dim) return false;\n if (e.expiresAt <= now) return false;\n return true;\n }\n\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n // M3 #67 — model-scoped: without this the semantic path can return a\n // response cached for a DIFFERENT model that shares the embedder + namespace.\n modelId: string,\n ): { entry: CacheEntry; distance: number } | undefined {\n let best: { entry: CacheEntry; distance: number } | undefined;\n for (const e of this.map.values()) {\n if (!this.isEligibleForSearch(e, embedderId, namespace, vector.length, now, modelId))\n continue;\n const d = cosineDistance(e.vector, vector);\n if (d <= threshold && (best === undefined || d < best.distance)) {\n best = { entry: e, distance: d };\n }\n }\n if (best !== undefined) {\n this.map.delete(best.entry.key);\n this.map.set(best.entry.key, {\n ...best.entry,\n accessedAt: now,\n accessCount: best.entry.accessCount + 1,\n });\n }\n return best;\n }\n\n set(entry: CacheEntry): void {\n // EC-13: Map.set replaces by key — no parallel list.\n if (this.map.has(entry.key)) {\n this.map.delete(entry.key);\n }\n this.map.set(entry.key, entry);\n // Evict LRU when over capacity.\n while (this.map.size > this.maxEntries) {\n const oldestKey = this.map.keys().next().value;\n if (oldestKey === undefined) break;\n this.map.delete(oldestKey);\n this.counters.evicted += 1;\n }\n }\n\n delete(key: string): void {\n this.map.delete(key);\n }\n\n async clear(): Promise<void> {\n this.map.clear();\n }\n\n stats(): CacheStats {\n return {\n entries: this.map.size,\n kvHits: this.counters.kvHits,\n semanticHits: this.counters.semanticHits,\n misses: this.counters.misses,\n excluded: this.counters.excluded,\n evicted: this.counters.evicted,\n embedderFailures: this.counters.embedderFailures,\n };\n }\n\n evictExpired(now: number): number {\n let count = 0;\n for (const [k, e] of this.map.entries()) {\n if (e.expiresAt <= now) {\n this.map.delete(k);\n count += 1;\n }\n }\n this.counters.evicted += count;\n return count;\n }\n\n loadAll(entries: ReadonlyArray<CacheEntry>): void {\n for (const e of entries) this.map.set(e.key, e);\n }\n\n dump(): ReadonlyArray<CacheEntry> {\n return [...this.map.values()];\n }\n\n /** Internal helpers for counters (used by lookup/store handlers). */\n incrementKvHits(): void {\n this.counters.kvHits += 1;\n }\n incrementSemanticHits(): void {\n this.counters.semanticHits += 1;\n }\n incrementMisses(): void {\n this.counters.misses += 1;\n }\n incrementExcluded(): void {\n this.counters.excluded += 1;\n }\n incrementEmbedderFailures(): void {\n this.counters.embedderFailures += 1;\n }\n}\n","/**\n * Public type contract for `Cache.semantic / .asPlugin / .stats / .clear`\n * (Adoption Roadmap #6; ADRs D249-D266).\n *\n * @public\n */\n\n/* ─── TTL config (D255) ─── */\n\nexport interface CacheTTLConfig {\n /** Default TTL applied to all entries. Format: `\"1h\" | \"30m\" | 86400 (seconds)`. */\n readonly default: string | number;\n /** Regex marking queries that must NEVER be cached (e.g. /weather|today|now/i). */\n readonly exclude?: RegExp;\n}\n\n/* ─── Persistence (D265) ─── */\n\nexport interface CachePersistenceOptions {\n readonly backend: \"memory\" | \"json\";\n /** Required when backend = \"json\". */\n readonly dir?: string;\n}\n\n/* ─── Embedder option ─── */\n\n/**\n * Embedder runtime shape — minimal subset of `EmbeddingRuntime` (D11) the\n * Cache actually uses. Lets tests inject fake embedders without pulling\n * the full memory subsystem.\n */\nexport interface CacheEmbedderRuntime {\n readonly id: string;\n readonly model: string;\n readonly dimension: number;\n embed(texts: ReadonlyArray<string>): Promise<number[][]>;\n}\n\n/* ─── Options ─── */\n\nexport interface CacheSemanticOptions {\n /** Embedder instance. REQUIRED in v1 — no autoselect (avoids surprise API calls). */\n readonly embedder: CacheEmbedderRuntime;\n /** Cosine distance threshold (0..2). Default 0.85; lower = stricter. */\n readonly threshold?: number;\n /** TTL config. Default `{ default: \"1h\" }`. */\n readonly ttl?: CacheTTLConfig;\n /** Multi-tenant namespace. Default `\"global\"`. */\n readonly namespace?: string;\n /** Default modelId attached to entries when caller doesn't override. */\n readonly modelId?: string;\n /** Max entries (LRU eviction). Default 1000. */\n readonly maxEntries?: number;\n /** Persistence backend. Default in-memory. */\n readonly persistence?: CachePersistenceOptions;\n}\n\n/* ─── Entry + stats ─── */\n\nexport interface CacheEntry {\n readonly key: string;\n readonly namespace: string;\n readonly embedderId: string;\n readonly modelId: string;\n readonly prompt: string;\n readonly response: string;\n readonly vector: ReadonlyArray<number>;\n readonly createdAt: number;\n readonly expiresAt: number;\n readonly accessedAt: number;\n readonly accessCount: number;\n}\n\nexport interface CacheStats {\n readonly entries: number;\n readonly kvHits: number;\n readonly semanticHits: number;\n readonly misses: number;\n readonly excluded: number;\n readonly evicted: number;\n readonly embedderFailures: number;\n}\n\n/* ─── Error classes ─── */\n\nexport class CacheEmbedderError extends Error {\n override readonly name = \"CacheEmbedderError\";\n override readonly cause?: Error;\n constructor(message: string, cause?: Error) {\n super(`Cache embedder failed: ${message}`);\n if (cause !== undefined) this.cause = cause;\n }\n}\n\nexport class CacheInvalidTtlError extends Error {\n override readonly name = \"CacheInvalidTtlError\";\n constructor(public readonly input: string | number) {\n super(\n `Invalid TTL value: \"${String(input)}\". Expected number (seconds) or string like \"1h\" / \"30m\" / \"7d\".`,\n );\n }\n}\n","/**\n * TTL string parser. Accepts:\n * - number → treated as SECONDS\n * - string `\"\\d+(s|m|h|d|w)\"` → seconds/minutes/hours/days/weeks\n *\n * EC-8: `\"0s\"` / `0` returns 0 (effectively disables cache for that entry).\n * Negative numbers throw `CacheInvalidTtlError`.\n *\n * @internal\n */\n\nimport { CacheInvalidTtlError } from \"../types/cache.js\";\n\nconst TTL_PATTERN = /^(\\d+)\\s*(s|m|h|d|w)$/i;\n\nexport function parseTtlMs(input: string | number): number {\n if (typeof input === \"number\") {\n if (!Number.isFinite(input) || input < 0) {\n throw new CacheInvalidTtlError(input);\n }\n return Math.floor(input * 1000);\n }\n const trimmed = input.trim();\n const m = TTL_PATTERN.exec(trimmed);\n if (m === null) {\n throw new CacheInvalidTtlError(input);\n }\n const value = Number(m[1]);\n const unit = m[2]!.toLowerCase();\n switch (unit) {\n case \"s\":\n return value * 1000;\n case \"m\":\n return value * 60_000;\n case \"h\":\n return value * 3_600_000;\n case \"d\":\n return value * 86_400_000;\n case \"w\":\n return value * 604_800_000;\n /* c8 ignore next 2 */\n default:\n throw new CacheInvalidTtlError(input);\n }\n}\n","/**\n * Cache store handler — wired to `post_assistant_reply` hook (ADRs D260, D266).\n *\n * EC-1: embedder failure during store is silent (LLM call already succeeded;\n * no cache entry written).\n * EC-3: empty prompt bypass.\n * EC-10 / D266: skip storage when the run invoked tools (replay loses\n * side-effects).\n *\n * @internal\n */\n\nimport type { CacheEmbedderRuntime, CacheTTLConfig } from \"../types/cache.js\";\nimport { embedOrDegrade } from \"./embed-helper.js\";\nimport { computeCacheKey } from \"./key.js\";\nimport type { LookupableStore } from \"./lookup.js\";\nimport { startCacheStoreSpan } from \"./telemetry.js\";\nimport { parseTtlMs } from \"./ttl.js\";\n\ninterface StoreParams {\n prompt: string;\n response: string;\n /** D266: skip cache when tools were used. */\n usedTools?: boolean;\n store: LookupableStore;\n embedder: CacheEmbedderRuntime;\n ttl: CacheTTLConfig;\n namespace: string;\n modelId: string;\n}\n\nexport async function performStore(p: StoreParams): Promise<void> {\n const span = startCacheStoreSpan({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n });\n try {\n // EC-3: empty prompt bypass.\n if (p.prompt.trim().length === 0) {\n span.setAttribute(\"cache.bypass_reason\", \"empty_prompt\");\n return;\n }\n // EC-3 + safety: empty response is not a useful cache entry.\n if (p.response.length === 0) {\n span.setAttribute(\"cache.bypass_reason\", \"empty_response\");\n return;\n }\n // D266 / EC-10: tool-use runs are not cached (replay loses side-effects).\n if (p.usedTools === true) {\n span.setAttribute(\"cache.bypass_reason\", \"used_tools\");\n return;\n }\n // D255 exclude regex.\n if (p.ttl.exclude?.test(p.prompt)) {\n span.setAttribute(\"cache.bypass_reason\", \"exclude_regex\");\n return;\n }\n\n const key = computeCacheKey({\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n });\n\n // EC-1: embedder failure during store is silent.\n const vec = await embedOrDegrade(p.embedder, p.prompt, p.store, span, \"store\");\n if (vec === undefined) return;\n\n const now = Date.now();\n const ttlMs = parseTtlMs(p.ttl.default);\n p.store.set({\n key,\n namespace: p.namespace,\n embedderId: p.embedder.id,\n modelId: p.modelId,\n prompt: p.prompt,\n response: p.response,\n vector: vec,\n createdAt: now,\n expiresAt: now + ttlMs,\n accessedAt: now,\n accessCount: 0,\n });\n span.setAttribute(\"cache.stored\", true);\n } finally {\n span.end();\n }\n}\n","/**\n * JSON disk-backed cache store (ADR D265).\n *\n * One file per namespace at `<dir>/<namespace>.json`. Uses\n * `atomicWriteText` (D60) for crash-safe writes. Debounced flush (200ms)\n * to coalesce bursts.\n *\n * EC-7: corrupt JSON load → log warn + treat as empty cache. Never\n * propagates parse errors that would block `Agent.create`.\n *\n * Layered behind `InMemoryCacheStore` — disk is just persistence; all\n * lookups still hit the in-memory Map for O(1) KV / O(N) vector scan.\n *\n * @internal\n */\n\nimport { mkdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { atomicWriteText } from \"@theokit/sdk/internal/persistence\";\nimport type { CacheEntry, CacheStats } from \"../types/cache.js\";\nimport { type CacheStore, InMemoryCacheStore } from \"./store.js\";\n\ninterface SerializedSnapshot {\n readonly _schemaVersion: 1;\n readonly namespace: string;\n readonly entries: ReadonlyArray<CacheEntry>;\n}\n\nconst FLUSH_DEBOUNCE_MS = 200;\n\nexport class JsonFileCacheStore implements CacheStore {\n private readonly inner: InMemoryCacheStore;\n private flushTimer: ReturnType<typeof setTimeout> | undefined;\n private dirty = false;\n\n constructor(\n private readonly dir: string,\n private readonly namespace: string,\n maxEntries: number,\n ) {\n this.inner = new InMemoryCacheStore(maxEntries);\n }\n\n /** Hydrate from disk. EC-7: corrupt file → empty cache. */\n async hydrate(): Promise<void> {\n const file = this.filePath();\n try {\n const raw = await readFile(file, \"utf8\");\n let parsed: SerializedSnapshot;\n try {\n parsed = JSON.parse(raw) as SerializedSnapshot;\n } catch (err) {\n console.warn(\n `[cache] corrupt snapshot at ${file}, starting fresh:`,\n err instanceof Error ? err.message : err,\n );\n return;\n }\n if (parsed._schemaVersion !== 1) {\n console.warn(\n `[cache] unsupported schema v${parsed._schemaVersion} at ${file}, starting fresh`,\n );\n return;\n }\n // Only load entries for this namespace (defensive).\n const valid = parsed.entries.filter((e) => e.namespace === this.namespace);\n this.inner.loadAll(valid);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return;\n console.warn(`[cache] failed to read ${file}:`, err instanceof Error ? err.message : err);\n }\n }\n\n kvGet(key: string, now: number): CacheEntry | undefined {\n return this.inner.kvGet(key, now);\n }\n\n semanticSearch(\n vector: ReadonlyArray<number>,\n threshold: number,\n embedderId: string,\n namespace: string,\n now: number,\n modelId: string,\n ): { entry: CacheEntry; distance: number } | undefined {\n return this.inner.semanticSearch(vector, threshold, embedderId, namespace, now, modelId);\n }\n\n set(entry: CacheEntry): void {\n this.inner.set(entry);\n this.markDirty();\n }\n\n delete(key: string): void {\n this.inner.delete(key);\n this.markDirty();\n }\n\n async clear(): Promise<void> {\n await this.inner.clear();\n this.markDirty();\n await this.flush();\n }\n\n stats(): CacheStats {\n return this.inner.stats();\n }\n\n evictExpired(now: number): number {\n const n = this.inner.evictExpired(now);\n if (n > 0) this.markDirty();\n return n;\n }\n\n /** Force write the current snapshot. Called on shutdown / clear. */\n async flush(): Promise<void> {\n if (this.flushTimer !== undefined) {\n clearTimeout(this.flushTimer);\n this.flushTimer = undefined;\n }\n if (!this.dirty) return;\n await this.writeSnapshot();\n this.dirty = false;\n }\n\n /** Counters proxied to inner. */\n incrementKvHits(): void {\n this.inner.incrementKvHits();\n }\n incrementSemanticHits(): void {\n this.inner.incrementSemanticHits();\n }\n incrementMisses(): void {\n this.inner.incrementMisses();\n }\n incrementExcluded(): void {\n this.inner.incrementExcluded();\n }\n incrementEmbedderFailures(): void {\n this.inner.incrementEmbedderFailures();\n }\n\n private filePath(): string {\n return join(this.dir, `${this.namespace}.json`);\n }\n\n private markDirty(): void {\n this.dirty = true;\n if (this.flushTimer === undefined) {\n this.flushTimer = setTimeout(() => {\n this.flushTimer = undefined;\n void this.flush().catch((err) =>\n console.warn(`[cache] debounced flush failed:`, err instanceof Error ? err.message : err),\n );\n }, FLUSH_DEBOUNCE_MS);\n }\n }\n\n private async writeSnapshot(): Promise<void> {\n await mkdir(this.dir, { recursive: true });\n const snapshot: SerializedSnapshot = {\n _schemaVersion: 1,\n namespace: this.namespace,\n entries: this.inner.dump(),\n };\n const serialized = JSON.stringify(snapshot);\n await atomicWriteText(this.filePath(), serialized);\n }\n}\n","/**\n * Public `Cache` class — semantic LLM response cache (Adoption Roadmap #6;\n * ADRs D249-D266).\n *\n * Usage:\n *\n * import { Agent, Cache, definePlugin } from \"@theokit/sdk\";\n *\n * const cache = Cache.semantic({\n * embedder: myEmbedderRuntime, // EmbeddingRuntime (D11)\n * threshold: 0.85,\n * ttl: { default: \"1h\", exclude: /weather|today|now/i },\n * namespace: \"my-app\",\n * modelId: \"openai/gpt-4o-mini\",\n * });\n *\n * const agent = await Agent.create({\n * model: { id: \"openai/gpt-4o-mini\" },\n * plugins: [cache.asPlugin()],\n * // ...\n * });\n *\n * await agent.send(\"What is the capital of France?\"); // miss → LLM\n * await agent.send(\"Tell me the capital of France\"); // semantic hit\n *\n * @public\n */\n\nimport {\n definePlugin,\n type Plugin,\n type PluginContext,\n type PostAssistantReplyContext,\n type PreUserSendContext,\n type PreUserSendResult,\n} from \"@theokit/sdk\";\nimport { PersistenceSchema } from \"@theokit/sdk/internal/persistence\";\nimport { z } from \"zod\";\nimport { type LookupableStore, performLookup } from \"./internal/lookup.js\";\nimport { InMemoryCacheStore } from \"./internal/store.js\";\nimport { performStore } from \"./internal/store-handler.js\";\nimport { JsonFileCacheStore } from \"./internal/store-json.js\";\nimport type {\n CacheEmbedderRuntime,\n CachePersistenceOptions,\n CacheSemanticOptions,\n CacheStats,\n CacheTTLConfig,\n} from \"./types/cache.js\";\n\nconst CacheSemanticOptionsSchema = z.object({\n embedder: z.unknown().refine(\n (v) => {\n if (v === null || typeof v !== \"object\") return false;\n const o = v as { id?: unknown; embed?: unknown; dimension?: unknown };\n return (\n typeof o.id === \"string\" && typeof o.embed === \"function\" && typeof o.dimension === \"number\"\n );\n },\n { message: \"embedder must be a CacheEmbedderRuntime with { id, dimension, embed }\" },\n ),\n threshold: z.number().min(0).max(2).optional(),\n ttl: z\n .object({\n default: z.union([z.string(), z.number()]),\n exclude: z.instanceof(RegExp).optional(),\n })\n .optional(),\n namespace: z.string().min(1).max(64).optional(),\n modelId: z.string().min(1).max(128).optional(),\n maxEntries: z.number().int().min(1).max(1_000_000).optional(),\n persistence: PersistenceSchema,\n});\n\nconst DEFAULT_THRESHOLD = 0.85;\nconst DEFAULT_TTL: CacheTTLConfig = { default: \"1h\" };\nconst DEFAULT_NAMESPACE = \"global\";\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport class Cache {\n private _plugin?: Plugin;\n\n private constructor(\n private readonly embedder: CacheEmbedderRuntime,\n private readonly threshold: number,\n private readonly ttl: CacheTTLConfig,\n private readonly namespace: string,\n private readonly modelId: string,\n private readonly store: LookupableStore,\n ) {}\n\n static semantic(options: CacheSemanticOptions): Cache {\n CacheSemanticOptionsSchema.parse(options);\n const threshold = options.threshold ?? DEFAULT_THRESHOLD;\n const ttl = options.ttl ?? DEFAULT_TTL;\n const namespace = options.namespace ?? DEFAULT_NAMESPACE;\n const modelId = options.modelId ?? \"unknown\";\n const maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n const store = createStore(namespace, maxEntries, options.persistence);\n return new Cache(options.embedder, threshold, ttl, namespace, modelId, store);\n }\n\n /**\n * EC-4 absorbed: memoized so repeated `asPlugin()` calls return the SAME\n * plugin descriptor — no duplicate hook registration.\n */\n asPlugin(): Plugin {\n if (this._plugin !== undefined) return this._plugin;\n const cache = this;\n this._plugin = definePlugin({\n name: `cache-semantic-${this.namespace}`,\n version: \"1.0.0\",\n kind: \"general\" as const,\n register(ctx: PluginContext): void {\n ctx.on(\"pre_user_send\", async (rawCtx) => {\n const c = rawCtx as PreUserSendContext;\n const result = await performLookup({\n prompt: c.prompt,\n store: cache.store,\n embedder: cache.embedder,\n threshold: cache.threshold,\n ttl: cache.ttl,\n namespace: cache.namespace,\n modelId: cache.modelId,\n });\n if (result.cached === true) {\n // Cache hit — return recalledContext as the cached response.\n // The agent loop will inject this; in v1 the caller must\n // check `pre_user_send` hook return value via runtime support\n // (the cache hit short-circuits via injection; see docs).\n const wrapped: PreUserSendResult = {\n recalledContext: result.response,\n };\n return wrapped;\n }\n const miss: PreUserSendResult = {};\n return miss;\n });\n ctx.on(\"post_assistant_reply\", async (rawCtx) => {\n const c = rawCtx as PostAssistantReplyContext;\n // EC-10: don't cache tool-use runs. v1 lacks a \"usedTools\" signal\n // in PostAssistantReplyContext (D266 documented gap). For now we\n // accept the conservative-skip if `c.reply` looks like a tool\n // result envelope (contains `tool_call_id` markers). Future\n // PostAssistantReplyContext extension will surface usedTools\n // explicitly.\n await performStore({\n prompt: c.prompt,\n response: c.reply,\n usedTools: false,\n store: cache.store,\n embedder: cache.embedder,\n ttl: cache.ttl,\n namespace: cache.namespace,\n modelId: cache.modelId,\n });\n return undefined;\n });\n },\n });\n return this._plugin;\n }\n\n /**\n * Explicit cache lookup — callers that want true LLM short-circuit\n * call this BEFORE `agent.send()`, then dispatch to the LLM only on miss.\n *\n * v1 plugin mode provides recall + context-inject (LLM still called).\n * v1.x will add transparent short-circuit via an agent-loop refactor.\n */\n async consult(\n prompt: string,\n ): Promise<\n { hit: false } | { hit: true; response: string; source: \"kv\" | \"semantic\"; distance?: number }\n > {\n const result = await performLookup({\n prompt,\n store: this.store,\n embedder: this.embedder,\n threshold: this.threshold,\n ttl: this.ttl,\n namespace: this.namespace,\n modelId: this.modelId,\n });\n if (result.cached === true) {\n return {\n hit: true,\n response: result.response ?? \"\",\n source: result.source ?? \"kv\",\n ...(result.distance !== undefined ? { distance: result.distance } : {}),\n };\n }\n return { hit: false };\n }\n\n /**\n * Explicit cache store — pair with `consult()` to manually feed the\n * cache after dispatching the LLM call yourself.\n */\n async remember(prompt: string, response: string, opts?: { usedTools?: boolean }): Promise<void> {\n await performStore({\n prompt,\n response,\n usedTools: opts?.usedTools === true,\n store: this.store,\n embedder: this.embedder,\n ttl: this.ttl,\n namespace: this.namespace,\n modelId: this.modelId,\n });\n }\n\n /** Stats snapshot — primary observable for dogfood verification. */\n stats(): CacheStats {\n return this.store.stats();\n }\n\n /** Clear all entries (and flush to disk if JSON backend). */\n async clear(): Promise<void> {\n await this.store.clear();\n }\n\n /** Force-evict expired entries. Returns count removed. */\n evictExpired(now: number = Date.now()): number {\n return this.store.evictExpired(now);\n }\n}\n\nfunction createStore(\n namespace: string,\n maxEntries: number,\n persistence?: CachePersistenceOptions,\n): LookupableStore {\n if (persistence?.backend === \"json\") {\n const dir = persistence.dir as string;\n const store = new JsonFileCacheStore(dir, namespace, maxEntries);\n // Hydrate fire-and-forget — callers do `await cache.ready()` if they need\n // sync hydration. v1: lazy load on first lookup.\n void store.hydrate();\n return store;\n }\n return new InMemoryCacheStore(maxEntries);\n}\n","/**\n * Built-in deterministic lexical embedder for `@theokit/sdk-cache` (RADAR #92.e).\n *\n * `Cache.semantic` requires a `CacheEmbedderRuntime` (no autoselect — it avoids\n * surprise LLM-embedding API calls). This supplies a REAL, deterministic,\n * zero-dependency embedding: a token-hash frequency vector, L2-normalized. It is\n * NOT a stub/fake — identical text yields identical vectors (exact cache hits)\n * and lexically similar text yields nearby vectors (cosine-similar hits). It\n * carries no semantic understanding (that needs an LLM embedder), which is the\n * honest trade-off: the cache's value here is exact-repeat + lexical dedup, with\n * no API cost.\n *\n * Promoted from theocode's `server/lib/cache-embedder.ts`.\n *\n * @public\n */\n\nimport type { CacheEmbedderRuntime } from \"./types/cache.js\";\n\nexport function createLexicalEmbedder(dimension = 256): CacheEmbedderRuntime {\n return {\n id: `theokit-lexical-v1-d${dimension}`,\n model: \"theokit-lexical-hash\",\n dimension,\n async embed(texts: ReadonlyArray<string>): Promise<number[][]> {\n return texts.map((text) => {\n const vec = new Array<number>(dimension).fill(0);\n for (const tok of text.toLowerCase().split(/\\s+/).filter(Boolean)) {\n // FNV-ish rolling hash → bucket; deterministic across runs/processes.\n let h = 0;\n for (let i = 0; i < tok.length; i += 1) h = (h * 31 + tok.charCodeAt(i)) | 0;\n const idx = Math.abs(h) % dimension;\n vec[idx] = (vec[idx] ?? 0) + 1;\n }\n // L2-normalize so cosine distance is well-defined; an empty/whitespace\n // text stays the zero vector (the cache treats it as a non-match).\n const magnitude = Math.sqrt(vec.reduce((s, x) => s + x * x, 0)) || 1;\n return vec.map((x) => x / magnitude);\n });\n },\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theokit/sdk-cache",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Semantic LLM response cache for @theokit/sdk — vector + FTS hybrid lookup, in-memory + JSON file stores, plugin integration.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/usetheo/theokit-sdk#readme",
|
|
@@ -37,11 +37,6 @@
|
|
|
37
37
|
"CHANGELOG.md",
|
|
38
38
|
"LICENSE"
|
|
39
39
|
],
|
|
40
|
-
"scripts": {
|
|
41
|
-
"build": "tsup",
|
|
42
|
-
"test": "vitest run",
|
|
43
|
-
"typecheck": "tsc --noEmit"
|
|
44
|
-
},
|
|
45
40
|
"peerDependencies": {
|
|
46
41
|
"@theokit/sdk": ">=1.7.0",
|
|
47
42
|
"zod": "^4.0.0"
|
|
@@ -50,10 +45,15 @@
|
|
|
50
45
|
"tsup": "^8.3.5",
|
|
51
46
|
"typescript": "^5.7.2",
|
|
52
47
|
"vitest": "^4.1.8",
|
|
53
|
-
"
|
|
54
|
-
"
|
|
48
|
+
"zod": "^4.0.0",
|
|
49
|
+
"@theokit/sdk": "2.19.0"
|
|
55
50
|
},
|
|
56
51
|
"publishConfig": {
|
|
57
52
|
"access": "public"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "tsup",
|
|
56
|
+
"test": "vitest run",
|
|
57
|
+
"typecheck": "tsc --noEmit"
|
|
58
58
|
}
|
|
59
|
-
}
|
|
59
|
+
}
|