@seanhogg/builderforce-memory 2026.6.18

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.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +582 -0
  3. package/dist/agent/SSMAgent.d.ts +146 -0
  4. package/dist/agent/SSMAgent.d.ts.map +1 -0
  5. package/dist/agent/SSMAgent.js +231 -0
  6. package/dist/agent/SSMAgent.js.map +1 -0
  7. package/dist/agent/index.d.ts +3 -0
  8. package/dist/agent/index.d.ts.map +1 -0
  9. package/dist/agent/index.js +2 -0
  10. package/dist/agent/index.js.map +1 -0
  11. package/dist/bridges/AnthropicBridge.d.ts +47 -0
  12. package/dist/bridges/AnthropicBridge.d.ts.map +1 -0
  13. package/dist/bridges/AnthropicBridge.js +120 -0
  14. package/dist/bridges/AnthropicBridge.js.map +1 -0
  15. package/dist/bridges/CachingBridge.d.ts +44 -0
  16. package/dist/bridges/CachingBridge.d.ts.map +1 -0
  17. package/dist/bridges/CachingBridge.js +62 -0
  18. package/dist/bridges/CachingBridge.js.map +1 -0
  19. package/dist/bridges/FetchBridge.d.ts +30 -0
  20. package/dist/bridges/FetchBridge.d.ts.map +1 -0
  21. package/dist/bridges/FetchBridge.js +24 -0
  22. package/dist/bridges/FetchBridge.js.map +1 -0
  23. package/dist/bridges/OpenAIBridge.d.ts +33 -0
  24. package/dist/bridges/OpenAIBridge.d.ts.map +1 -0
  25. package/dist/bridges/OpenAIBridge.js +110 -0
  26. package/dist/bridges/OpenAIBridge.js.map +1 -0
  27. package/dist/bridges/ResponseCache.d.ts +65 -0
  28. package/dist/bridges/ResponseCache.d.ts.map +1 -0
  29. package/dist/bridges/ResponseCache.js +97 -0
  30. package/dist/bridges/ResponseCache.js.map +1 -0
  31. package/dist/bridges/SemanticCachingBridge.d.ts +31 -0
  32. package/dist/bridges/SemanticCachingBridge.d.ts.map +1 -0
  33. package/dist/bridges/SemanticCachingBridge.js +44 -0
  34. package/dist/bridges/SemanticCachingBridge.js.map +1 -0
  35. package/dist/bridges/TransformerBridge.d.ts +35 -0
  36. package/dist/bridges/TransformerBridge.d.ts.map +1 -0
  37. package/dist/bridges/TransformerBridge.js +10 -0
  38. package/dist/bridges/TransformerBridge.js.map +1 -0
  39. package/dist/bridges/index.d.ts +14 -0
  40. package/dist/bridges/index.d.ts.map +1 -0
  41. package/dist/bridges/index.js +7 -0
  42. package/dist/bridges/index.js.map +1 -0
  43. package/dist/cache/FetchSemanticCacheBackend.d.ts +40 -0
  44. package/dist/cache/FetchSemanticCacheBackend.d.ts.map +1 -0
  45. package/dist/cache/FetchSemanticCacheBackend.js +61 -0
  46. package/dist/cache/FetchSemanticCacheBackend.js.map +1 -0
  47. package/dist/cache/SemanticCache.d.ts +105 -0
  48. package/dist/cache/SemanticCache.d.ts.map +1 -0
  49. package/dist/cache/SemanticCache.js +130 -0
  50. package/dist/cache/SemanticCache.js.map +1 -0
  51. package/dist/cache/index.d.ts +5 -0
  52. package/dist/cache/index.d.ts.map +1 -0
  53. package/dist/cache/index.js +3 -0
  54. package/dist/cache/index.js.map +1 -0
  55. package/dist/distillation/DistillationEngine.d.ts +107 -0
  56. package/dist/distillation/DistillationEngine.d.ts.map +1 -0
  57. package/dist/distillation/DistillationEngine.js +152 -0
  58. package/dist/distillation/DistillationEngine.js.map +1 -0
  59. package/dist/distillation/index.d.ts +3 -0
  60. package/dist/distillation/index.d.ts.map +1 -0
  61. package/dist/distillation/index.js +2 -0
  62. package/dist/distillation/index.js.map +1 -0
  63. package/dist/errors/SSMError.d.ts +14 -0
  64. package/dist/errors/SSMError.d.ts.map +1 -0
  65. package/dist/errors/SSMError.js +18 -0
  66. package/dist/errors/SSMError.js.map +1 -0
  67. package/dist/errors/index.d.ts +3 -0
  68. package/dist/errors/index.d.ts.map +1 -0
  69. package/dist/errors/index.js +2 -0
  70. package/dist/errors/index.js.map +1 -0
  71. package/dist/index.d.ts +65 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +59 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/memory/MemoryStore.d.ts +152 -0
  76. package/dist/memory/MemoryStore.d.ts.map +1 -0
  77. package/dist/memory/MemoryStore.js +290 -0
  78. package/dist/memory/MemoryStore.js.map +1 -0
  79. package/dist/memory/index.d.ts +3 -0
  80. package/dist/memory/index.d.ts.map +1 -0
  81. package/dist/memory/index.js +2 -0
  82. package/dist/memory/index.js.map +1 -0
  83. package/dist/router/InferenceRouter.d.ts +92 -0
  84. package/dist/router/InferenceRouter.d.ts.map +1 -0
  85. package/dist/router/InferenceRouter.js +113 -0
  86. package/dist/router/InferenceRouter.js.map +1 -0
  87. package/dist/router/index.d.ts +3 -0
  88. package/dist/router/index.d.ts.map +1 -0
  89. package/dist/router/index.js +2 -0
  90. package/dist/router/index.js.map +1 -0
  91. package/dist/runtime/SSMRuntime.d.ts +167 -0
  92. package/dist/runtime/SSMRuntime.d.ts.map +1 -0
  93. package/dist/runtime/SSMRuntime.js +199 -0
  94. package/dist/runtime/SSMRuntime.js.map +1 -0
  95. package/dist/runtime/index.d.ts +3 -0
  96. package/dist/runtime/index.d.ts.map +1 -0
  97. package/dist/runtime/index.js +2 -0
  98. package/dist/runtime/index.js.map +1 -0
  99. package/dist/session/errors.d.ts +10 -0
  100. package/dist/session/errors.d.ts.map +1 -0
  101. package/dist/session/errors.js +14 -0
  102. package/dist/session/errors.js.map +1 -0
  103. package/dist/session/index.d.ts +11 -0
  104. package/dist/session/index.d.ts.map +1 -0
  105. package/dist/session/index.js +7 -0
  106. package/dist/session/index.js.map +1 -0
  107. package/dist/session/persistence.d.ts +14 -0
  108. package/dist/session/persistence.d.ts.map +1 -0
  109. package/dist/session/persistence.js +100 -0
  110. package/dist/session/persistence.js.map +1 -0
  111. package/dist/session/presets.d.ts +31 -0
  112. package/dist/session/presets.d.ts.map +1 -0
  113. package/dist/session/presets.js +91 -0
  114. package/dist/session/presets.js.map +1 -0
  115. package/dist/session/session.d.ts +186 -0
  116. package/dist/session/session.d.ts.map +1 -0
  117. package/dist/session/session.js +358 -0
  118. package/dist/session/session.js.map +1 -0
  119. package/dist/session/streaming.d.ts +13 -0
  120. package/dist/session/streaming.d.ts.map +1 -0
  121. package/dist/session/streaming.js +74 -0
  122. package/dist/session/streaming.js.map +1 -0
  123. package/dist/session/tokenizer.d.ts +18 -0
  124. package/dist/session/tokenizer.d.ts.map +1 -0
  125. package/dist/session/tokenizer.js +11 -0
  126. package/dist/session/tokenizer.js.map +1 -0
  127. package/dist/similarity/index.d.ts +19 -0
  128. package/dist/similarity/index.d.ts.map +1 -0
  129. package/dist/similarity/index.js +42 -0
  130. package/dist/similarity/index.js.map +1 -0
  131. package/package.json +120 -0
  132. package/src/agent/SSMAgent.ts +327 -0
  133. package/src/agent/index.ts +2 -0
  134. package/src/bridges/AnthropicBridge.ts +166 -0
  135. package/src/bridges/CachingBridge.ts +79 -0
  136. package/src/bridges/FetchBridge.ts +41 -0
  137. package/src/bridges/OpenAIBridge.ts +143 -0
  138. package/src/bridges/ResponseCache.ts +131 -0
  139. package/src/bridges/SemanticCachingBridge.ts +60 -0
  140. package/src/bridges/TransformerBridge.ts +38 -0
  141. package/src/bridges/index.ts +13 -0
  142. package/src/cache/FetchSemanticCacheBackend.ts +79 -0
  143. package/src/cache/SemanticCache.ts +196 -0
  144. package/src/cache/index.ts +9 -0
  145. package/src/distillation/DistillationEngine.ts +248 -0
  146. package/src/distillation/index.ts +2 -0
  147. package/src/errors/SSMError.ts +26 -0
  148. package/src/errors/index.ts +2 -0
  149. package/src/index.ts +128 -0
  150. package/src/memory/MemoryStore.ts +408 -0
  151. package/src/memory/index.ts +2 -0
  152. package/src/router/InferenceRouter.ts +201 -0
  153. package/src/router/index.ts +2 -0
  154. package/src/runtime/SSMRuntime.ts +309 -0
  155. package/src/runtime/index.ts +2 -0
  156. package/src/session/errors.ts +24 -0
  157. package/src/session/index.ts +25 -0
  158. package/src/session/persistence.ts +142 -0
  159. package/src/session/presets.ts +122 -0
  160. package/src/session/session.ts +657 -0
  161. package/src/session/streaming.ts +97 -0
  162. package/src/session/tokenizer.ts +18 -0
  163. package/src/similarity/index.ts +42 -0
@@ -0,0 +1,290 @@
1
+ /**
2
+ * MemoryStore – persistent key-value fact store and weight checkpoint helper.
3
+ *
4
+ * Uses IndexedDB with a dedicated 'ssmjs' database containing two object stores:
5
+ * - 'facts' : MemoryEntry records keyed by the fact key string
6
+ * - 'weights' : a single ArrayBuffer keyed by `weightsKey`
7
+ *
8
+ * Weight save/load is delegated to the SSMRuntime passed to saveWeights/loadWeights.
9
+ */
10
+ import { SSMError } from '../errors/SSMError.js';
11
+ import { tokenize, jaccardSimilarity, cosineSimilarity } from '../similarity/index.js';
12
+ const FACTS_STORE = 'facts';
13
+ const WEIGHTS_STORE = 'weights';
14
+ const DB_VERSION = 1;
15
+ /**
16
+ * Process-wide monotonic counter stamped onto each remembered entry. Strictly
17
+ * increasing per write regardless of store instance, so it reliably breaks
18
+ * `timestamp` ties (same-millisecond writes) in newest-first ordering.
19
+ */
20
+ let _writeSeq = 0;
21
+ /** Max number of cached content→embedding vectors retained in memory. */
22
+ const EMBED_CACHE_MAX = 2000;
23
+ export class MemoryStore {
24
+ _dbName;
25
+ _weightsKey;
26
+ _idb;
27
+ _defaultTtl;
28
+ _db = null;
29
+ /** Content → L2-normalised embedding cache, used by recallSimilar. */
30
+ _embedCache = new Map();
31
+ constructor(opts = {}) {
32
+ this._dbName = opts.dbName ?? 'ssmjs';
33
+ this._weightsKey = opts.weightsKey ?? 'ssmjs-weights';
34
+ this._idb = opts.idbFactory;
35
+ this._defaultTtl = opts.defaultTtlMs;
36
+ }
37
+ // ── Internal DB open ──────────────────────────────────────────────────────
38
+ _open() {
39
+ if (this._db)
40
+ return Promise.resolve(this._db);
41
+ return new Promise((resolve, reject) => {
42
+ const factory = this._idb ?? (typeof indexedDB !== 'undefined' ? indexedDB : undefined);
43
+ if (!factory) {
44
+ reject(new SSMError('MEMORY_UNAVAILABLE', 'IndexedDB is not available in this environment. Pass an idbFactory option (e.g. from fake-indexeddb) for Node.js support.'));
45
+ return;
46
+ }
47
+ const req = factory.open(this._dbName, DB_VERSION);
48
+ req.onupgradeneeded = (e) => {
49
+ const db = e.target.result;
50
+ if (!db.objectStoreNames.contains(FACTS_STORE)) {
51
+ db.createObjectStore(FACTS_STORE, { keyPath: 'key' });
52
+ }
53
+ if (!db.objectStoreNames.contains(WEIGHTS_STORE)) {
54
+ db.createObjectStore(WEIGHTS_STORE);
55
+ }
56
+ };
57
+ req.onsuccess = () => {
58
+ this._db = req.result;
59
+ resolve(req.result);
60
+ };
61
+ /* istanbul ignore next -- IDB open onerror fires only on storage faults; not reproducible with fake-indexeddb */
62
+ req.onerror = () => reject(new SSMError('MEMORY_UNAVAILABLE', `Failed to open IndexedDB "${this._dbName}": ${req.error?.message ?? 'unknown'}`, req.error));
63
+ });
64
+ }
65
+ // ── TTL helpers ───────────────────────────────────────────────────────────
66
+ _isExpired(entry) {
67
+ if (entry.ttlMs == null)
68
+ return false;
69
+ return Date.now() > entry.timestamp + entry.ttlMs;
70
+ }
71
+ // ── Semantic facts ────────────────────────────────────────────────────────
72
+ /** Stores or overwrites a fact. */
73
+ async remember(key, content, opts) {
74
+ const db = await this._open();
75
+ const entry = {
76
+ key,
77
+ content,
78
+ timestamp: Date.now(),
79
+ seq: ++_writeSeq,
80
+ ttlMs: opts?.ttlMs ?? this._defaultTtl,
81
+ type: opts?.type,
82
+ tags: opts?.tags,
83
+ importance: opts?.importance,
84
+ };
85
+ const tx = db.transaction(FACTS_STORE, 'readwrite');
86
+ return requestToPromise(tx.objectStore(FACTS_STORE).put(entry), `Failed to store fact "${key}"`, () => undefined);
87
+ }
88
+ /**
89
+ * Retrieves a fact by key.
90
+ * Returns `undefined` if the key does not exist or the entry has expired.
91
+ */
92
+ async recall(key) {
93
+ const db = await this._open();
94
+ const tx = db.transaction(FACTS_STORE, 'readonly');
95
+ return requestToPromise(tx.objectStore(FACTS_STORE).get(key), `Failed to recall fact "${key}"`, (entry) => (entry && this._isExpired(entry) ? undefined : entry));
96
+ }
97
+ /** Returns all non-expired stored facts, newest first. */
98
+ async recallAll() {
99
+ const db = await this._open();
100
+ const tx = db.transaction(FACTS_STORE, 'readonly');
101
+ return requestToPromise(tx.objectStore(FACTS_STORE).getAll(), 'Failed to recall all facts', (entries) => entries
102
+ .filter(e => !this._isExpired(e))
103
+ // Newest first; break same-millisecond ties by write sequence so
104
+ // ordering is deterministic (IndexedDB getAll() returns key order,
105
+ // which would otherwise surface same-ms writes oldest-first).
106
+ .sort((a, b) => b.timestamp - a.timestamp || (b.seq ?? 0) - (a.seq ?? 0)));
107
+ }
108
+ /**
109
+ * Returns the N most recently updated non-expired facts.
110
+ * Equivalent to `recallAll()` truncated to `n` entries.
111
+ */
112
+ async recallRecent(n) {
113
+ const all = await this.recallAll();
114
+ return all.slice(0, n);
115
+ }
116
+ /**
117
+ * Returns all non-expired entries that contain the given tag.
118
+ */
119
+ async recallByTag(tag) {
120
+ const all = await this.recallAll();
121
+ return all.filter(e => e.tags?.includes(tag) ?? false);
122
+ }
123
+ /**
124
+ * Finds the top-K semantically similar entries to `query`.
125
+ *
126
+ * When `runtime` exposes an `embed()` method (the SSMRuntime does), similarity
127
+ * is computed as cosine distance between SSM hidden-state embeddings — i.e. the
128
+ * memory layer uses the very model it is attached to, and recall quality
129
+ * improves automatically as that model is adapted/distilled. Embeddings are
130
+ * cached per content string to avoid recomputing across calls.
131
+ *
132
+ * If no embedding-capable runtime is provided, or embedding fails for any
133
+ * reason, it transparently falls back to Jaccard word-overlap similarity.
134
+ */
135
+ async recallSimilar(query, topK, runtime) {
136
+ const all = await this.recallAll();
137
+ if (all.length === 0)
138
+ return [];
139
+ // ── Preferred path: SSM-embedding cosine similarity ───────────────────
140
+ if (runtime != null && typeof runtime.embed === 'function') {
141
+ const queryVec = await this._embedWithCache(runtime, query);
142
+ if (queryVec) {
143
+ const scored = [];
144
+ let embeddedAll = true;
145
+ for (const entry of all) {
146
+ const entryVec = await this._embedWithCache(runtime, entry.content);
147
+ if (!entryVec) {
148
+ embeddedAll = false;
149
+ break;
150
+ }
151
+ scored.push({ entry, score: cosineSimilarity(queryVec, entryVec) });
152
+ }
153
+ if (embeddedAll) {
154
+ scored.sort((a, b) => b.score - a.score);
155
+ return scored.slice(0, topK).map(s => s.entry);
156
+ }
157
+ }
158
+ // Any failure falls through to the Jaccard path below.
159
+ }
160
+ // ── Fallback: Jaccard word-overlap similarity ─────────────────────────
161
+ const queryTokens = new Set(tokenize(query));
162
+ const scored = all.map(entry => {
163
+ const entryTokens = new Set(tokenize(entry.content));
164
+ const score = jaccardSimilarity(queryTokens, entryTokens);
165
+ return { entry, score };
166
+ });
167
+ scored.sort((a, b) => b.score - a.score);
168
+ return scored.slice(0, topK).map(s => s.entry);
169
+ }
170
+ /**
171
+ * Returns a cached embedding for `text`, computing it via `runtime.embed()`
172
+ * on a cache miss. Returns `null` (never throws) when embedding is
173
+ * unavailable so callers can fall back to lexical similarity.
174
+ */
175
+ async _embedWithCache(runtime, text) {
176
+ const cached = this._embedCache.get(text);
177
+ if (cached)
178
+ return cached;
179
+ try {
180
+ const vec = await runtime.embed(text);
181
+ if (vec instanceof Float32Array && vec.length > 0) {
182
+ // Bound cache growth — simplest eviction is a full clear.
183
+ if (this._embedCache.size >= EMBED_CACHE_MAX)
184
+ this._embedCache.clear();
185
+ this._embedCache.set(text, vec);
186
+ return vec;
187
+ }
188
+ }
189
+ catch {
190
+ // Embedding unavailable (no GPU, destroyed runtime, etc.) — signal fallback.
191
+ }
192
+ return null;
193
+ }
194
+ /**
195
+ * Hard-deletes all entries whose TTL has expired.
196
+ * @returns The number of entries deleted.
197
+ */
198
+ async purgeExpired() {
199
+ const db = await this._open();
200
+ // Load all raw entries (including expired ones) to check each
201
+ const tx = db.transaction(FACTS_STORE, 'readonly');
202
+ const all = await requestToPromise(tx.objectStore(FACTS_STORE).getAll(), 'Failed to scan facts for purge', (r) => r);
203
+ const expired = all.filter(e => this._isExpired(e));
204
+ if (expired.length === 0)
205
+ return 0;
206
+ await Promise.all(expired.map(e => this.forget(e.key)));
207
+ return expired.length;
208
+ }
209
+ /** Deletes a single fact. No-op if key does not exist. */
210
+ async forget(key) {
211
+ const db = await this._open();
212
+ const tx = db.transaction(FACTS_STORE, 'readwrite');
213
+ return requestToPromise(tx.objectStore(FACTS_STORE).delete(key), `Failed to forget fact "${key}"`, () => undefined);
214
+ }
215
+ /** Deletes all facts. Does not affect saved weights. */
216
+ async clear() {
217
+ const db = await this._open();
218
+ const tx = db.transaction(FACTS_STORE, 'readwrite');
219
+ return requestToPromise(tx.objectStore(FACTS_STORE).clear(), 'Failed to clear facts', () => undefined);
220
+ }
221
+ // ── Cross-session memory merge ────────────────────────────────────────────
222
+ /**
223
+ * Returns all non-expired facts as a plain array for export.
224
+ * Suitable for serialisation and import into another MemoryStore instance.
225
+ */
226
+ async exportAll() {
227
+ return this.recallAll();
228
+ }
229
+ /**
230
+ * Imports entries from an external array.
231
+ *
232
+ * - `'merge'` : only writes an entry if no existing entry with the same
233
+ * key exists, or if the incoming entry has a newer timestamp.
234
+ * - `'overwrite'` : writes all entries unconditionally.
235
+ */
236
+ async importAll(entries, strategy) {
237
+ for (const entry of entries) {
238
+ if (strategy === 'overwrite') {
239
+ await this._putRaw(entry);
240
+ }
241
+ else {
242
+ const existing = await this.recall(entry.key);
243
+ if (existing == null || entry.timestamp > existing.timestamp) {
244
+ await this._putRaw(entry);
245
+ }
246
+ }
247
+ }
248
+ }
249
+ /** Writes a raw MemoryEntry directly (preserves original timestamp / metadata). */
250
+ async _putRaw(entry) {
251
+ const db = await this._open();
252
+ const tx = db.transaction(FACTS_STORE, 'readwrite');
253
+ return requestToPromise(tx.objectStore(FACTS_STORE).put(entry), `Failed to import fact "${entry.key}"`, () => undefined);
254
+ }
255
+ // ── Weight persistence ────────────────────────────────────────────────────
256
+ /**
257
+ * Saves SSM weights via `runtime.save()`.
258
+ * The weights are stored under `weightsKey` in this store's IndexedDB,
259
+ * separate from MambaSession's own key.
260
+ */
261
+ async saveWeights(runtime) {
262
+ await runtime.save({ storage: 'indexedDB', key: this._weightsKey });
263
+ }
264
+ /**
265
+ * Loads SSM weights via `runtime.load()`.
266
+ * Returns `false` when no saved weights exist under `weightsKey`.
267
+ */
268
+ async loadWeights(runtime) {
269
+ return runtime.load({ key: this._weightsKey });
270
+ }
271
+ }
272
+ // ── IndexedDB helper ──────────────────────────────────────────────────────────
273
+ /**
274
+ * Wires an IDBRequest to a promise: resolves with `map(result)` on success,
275
+ * rejects with a normalised MEMORY_UNAVAILABLE error on failure. Extracted so
276
+ * the success/error wiring lives in one place instead of being duplicated across
277
+ * every store method.
278
+ *
279
+ * The onerror branch fires only on IndexedDB storage faults (quota exceeded,
280
+ * disk failure, corruption), which the in-memory fake-indexeddb used in tests
281
+ * cannot reproduce — hence the istanbul ignore on that single line.
282
+ */
283
+ function requestToPromise(req, failMsg, map) {
284
+ return new Promise((resolve, reject) => {
285
+ req.onsuccess = () => resolve(map(req.result));
286
+ /* istanbul ignore next -- IDB storage-fault path; not reproducible with fake-indexeddb */
287
+ req.onerror = () => reject(new SSMError('MEMORY_UNAVAILABLE', `${failMsg}: ${req.error?.message ?? 'unknown'}`, req.error ?? undefined));
288
+ });
289
+ }
290
+ //# sourceMappingURL=MemoryStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryStore.js","sourceRoot":"","sources":["../../src/memory/MemoryStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { MemoryStore } from './MemoryStore.js';
2
+ export type { MemoryEntry, MemoryStoreOptions, RememberOptions, FactType } from './MemoryStore.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { MemoryStore } from './MemoryStore.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * InferenceRouter – decides whether a given input should be handled by the
3
+ * local SSM or routed to a transformer bridge.
4
+ *
5
+ * Three heuristics run in priority order (cheapest first):
6
+ * 1. Complexity patterns — regex against the input string (synchronous, zero cost)
7
+ * 2. Input length — char count proxy for token count (synchronous, zero cost)
8
+ * 3. Perplexity probe — async SSM evaluate(); only runs when 1 & 2 are inconclusive
9
+ *
10
+ * When no bridge is available the router always returns target='ssm'.
11
+ */
12
+ export type RoutingStrategy = 'auto' | 'ssm' | 'transformer';
13
+ /**
14
+ * The structured result of a routing decision.
15
+ */
16
+ export interface RoutingDecision {
17
+ /** Which model should handle this input. */
18
+ target: 'ssm' | 'transformer';
19
+ /** The primary heuristic that triggered this decision. */
20
+ reason: 'strategy' | 'complexity' | 'length' | 'perplexity' | 'no_bridge';
21
+ /** Confidence score in the range 0–1. */
22
+ confidence: number;
23
+ /** Optional human-readable explanation. */
24
+ details?: string;
25
+ }
26
+ export interface RouterContext {
27
+ /**
28
+ * Cached SSM perplexity for this input if already computed by the caller.
29
+ * Providing this skips the async perplexity probe in auto mode.
30
+ */
31
+ perplexity?: number;
32
+ }
33
+ export interface RoutingAuditEntry {
34
+ timestamp: number;
35
+ inputLength: number;
36
+ decision: RoutingDecision;
37
+ durationMs: number;
38
+ }
39
+ export interface InferenceRouterOptions {
40
+ /**
41
+ * Routing strategy.
42
+ * - 'auto' : heuristic routing (default)
43
+ * - 'ssm' : always route to SSM
44
+ * - 'transformer' : always route to transformer (no-op when bridge absent)
45
+ */
46
+ strategy?: RoutingStrategy;
47
+ /**
48
+ * Input character length above which auto-routing prefers the transformer.
49
+ * ~1200 chars ≈ 300 tokens — beyond this a large context model tends to
50
+ * outperform a small SSM for most tasks.
51
+ * Default: 1200
52
+ */
53
+ longInputThreshold?: number;
54
+ /**
55
+ * SSM perplexity above which auto-routing falls back to the transformer.
56
+ * High perplexity signals the model hasn't seen this topic.
57
+ * Default: 80
58
+ */
59
+ perplexityThreshold?: number;
60
+ /**
61
+ * Whether a transformer bridge is currently attached to the runtime.
62
+ * The router uses this to short-circuit to 'ssm' when no bridge is present.
63
+ * Set by SSMRuntime when constructing the router.
64
+ * Default: false
65
+ */
66
+ hasBridge?: boolean;
67
+ /**
68
+ * Callback for computing SSM perplexity, provided by SSMRuntime.
69
+ * Avoids a circular import between InferenceRouter and SSMRuntime.
70
+ * Only called in 'auto' mode as a last-resort heuristic.
71
+ */
72
+ perplexityProbe?: (text: string) => Promise<number>;
73
+ }
74
+ export declare class InferenceRouter {
75
+ private readonly _strategy;
76
+ private readonly _longInputThreshold;
77
+ private readonly _perplexityThreshold;
78
+ private readonly _hasBridge;
79
+ private readonly _perplexityProbe;
80
+ private readonly _auditLog;
81
+ constructor(opts?: InferenceRouterOptions);
82
+ /**
83
+ * Routes `input` to either SSM or transformer and returns a RoutingDecision.
84
+ *
85
+ * Always returns target='ssm' when no bridge is attached, regardless of strategy.
86
+ */
87
+ route(input: string, ctx?: RouterContext): Promise<RoutingDecision>;
88
+ /** Returns a copy of the in-memory routing audit log (most recent last). */
89
+ getAuditLog(): RoutingAuditEntry[];
90
+ private _decide;
91
+ }
92
+ //# sourceMappingURL=InferenceRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InferenceRouter.d.ts","sourceRoot":"","sources":["../../src/router/InferenceRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,KAAK,GAAG,aAAa,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,4CAA4C;IAC5C,MAAM,EAAO,KAAK,GAAG,aAAa,CAAC;IACnC,0DAA0D;IAC1D,MAAM,EAAO,UAAU,GAAG,YAAY,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,CAAC;IAC/E,yCAAyC;IACzC,UAAU,EAAG,MAAM,CAAC;IACpB,2CAA2C;IAC3C,OAAO,CAAC,EAAK,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC1B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAC9B,SAAS,EAAI,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAK,eAAe,CAAC;IAC7B,UAAU,EAAG,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,EAAc,eAAe,CAAC;IAEvC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAI,MAAM,CAAC;IAE9B;;;;OAIG;IACH,mBAAmB,CAAC,EAAG,MAAM,CAAC;IAE9B;;;;;OAKG;IACH,SAAS,CAAC,EAAa,OAAO,CAAC;IAE/B;;;;OAIG;IACH,eAAe,CAAC,EAAO,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC5D;AAoBD,qBAAa,eAAe;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;IACvD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAU;IAC9C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsD;IACvF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsC;gBAEpD,IAAI,GAAE,sBAA2B;IAQ7C;;;;OAIG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,aAAkB,GAAG,OAAO,CAAC,eAAe,CAAC;IAmB7E,4EAA4E;IAC5E,WAAW,IAAI,iBAAiB,EAAE;YAMpB,OAAO;CAoDxB"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * InferenceRouter – decides whether a given input should be handled by the
3
+ * local SSM or routed to a transformer bridge.
4
+ *
5
+ * Three heuristics run in priority order (cheapest first):
6
+ * 1. Complexity patterns — regex against the input string (synchronous, zero cost)
7
+ * 2. Input length — char count proxy for token count (synchronous, zero cost)
8
+ * 3. Perplexity probe — async SSM evaluate(); only runs when 1 & 2 are inconclusive
9
+ *
10
+ * When no bridge is available the router always returns target='ssm'.
11
+ */
12
+ // ── Complexity-signal regex patterns ─────────────────────────────────────────
13
+ // These match inputs that benefit from a larger transformer's broader knowledge.
14
+ const COMPLEXITY_PATTERNS = [
15
+ /step[\s-]by[\s-]step/i,
16
+ /\banalyze\b|\banalyse\b/i,
17
+ /\bexplain\s+(why|how|in\s+detail)/i,
18
+ /\bcompare\b.*\band\b/i,
19
+ /\bcontrast\b/i,
20
+ /\bpros?\s+and\s+cons?\b/i,
21
+ /\bsummariz/i,
22
+ /\bwrite\s+a\s+(detailed|comprehensive|complete|full)\b/i,
23
+ /\bwhat\s+are\s+the\s+(key|main|top)\s+(difference|reason|factor)/i,
24
+ ];
25
+ /** Maximum audit log entries to keep in memory. */
26
+ const MAX_AUDIT_LOG = 500;
27
+ export class InferenceRouter {
28
+ _strategy;
29
+ _longInputThreshold;
30
+ _perplexityThreshold;
31
+ _hasBridge;
32
+ _perplexityProbe;
33
+ _auditLog = [];
34
+ constructor(opts = {}) {
35
+ this._strategy = opts.strategy ?? 'auto';
36
+ this._longInputThreshold = opts.longInputThreshold ?? 1200;
37
+ this._perplexityThreshold = opts.perplexityThreshold ?? 80;
38
+ this._hasBridge = opts.hasBridge ?? false;
39
+ this._perplexityProbe = opts.perplexityProbe;
40
+ }
41
+ /**
42
+ * Routes `input` to either SSM or transformer and returns a RoutingDecision.
43
+ *
44
+ * Always returns target='ssm' when no bridge is attached, regardless of strategy.
45
+ */
46
+ async route(input, ctx = {}) {
47
+ const startMs = Date.now();
48
+ const decision = await this._decide(input, ctx);
49
+ const durationMs = Date.now() - startMs;
50
+ const auditEntry = {
51
+ timestamp: Date.now(),
52
+ inputLength: input.length,
53
+ decision,
54
+ durationMs,
55
+ };
56
+ this._auditLog.push(auditEntry);
57
+ if (this._auditLog.length > MAX_AUDIT_LOG) {
58
+ this._auditLog.shift();
59
+ }
60
+ return decision;
61
+ }
62
+ /** Returns a copy of the in-memory routing audit log (most recent last). */
63
+ getAuditLog() {
64
+ return this._auditLog.slice();
65
+ }
66
+ // ── Private routing logic ─────────────────────────────────────────────────
67
+ async _decide(input, ctx) {
68
+ // No bridge → always SSM
69
+ if (!this._hasBridge) {
70
+ return { target: 'ssm', reason: 'no_bridge', confidence: 1.0 };
71
+ }
72
+ // Fixed-strategy overrides
73
+ if (this._strategy === 'ssm') {
74
+ return { target: 'ssm', reason: 'strategy', confidence: 1.0 };
75
+ }
76
+ if (this._strategy === 'transformer') {
77
+ return { target: 'transformer', reason: 'strategy', confidence: 1.0 };
78
+ }
79
+ // Auto heuristics ────────────────────────────────────────────────────
80
+ // 1. Complexity patterns (synchronous)
81
+ const matchedPattern = COMPLEXITY_PATTERNS.find(p => p.test(input));
82
+ if (matchedPattern) {
83
+ return {
84
+ target: 'transformer',
85
+ reason: 'complexity',
86
+ confidence: 0.9,
87
+ details: `Matched pattern: ${matchedPattern.source}`,
88
+ };
89
+ }
90
+ // 2. Input length (synchronous)
91
+ if (input.length > this._longInputThreshold) {
92
+ return {
93
+ target: 'transformer',
94
+ reason: 'length',
95
+ confidence: 0.85,
96
+ details: `Input length ${input.length} exceeds threshold ${this._longInputThreshold}`,
97
+ };
98
+ }
99
+ // 3. Perplexity probe (async) — only if probe function provided
100
+ const perplexity = ctx.perplexity ??
101
+ (this._perplexityProbe ? await this._perplexityProbe(input) : undefined);
102
+ if (perplexity !== undefined && perplexity > this._perplexityThreshold) {
103
+ return {
104
+ target: 'transformer',
105
+ reason: 'perplexity',
106
+ confidence: Math.min(0.95, 0.5 + (perplexity - this._perplexityThreshold) / 200),
107
+ details: `SSM perplexity ${perplexity.toFixed(1)} exceeds threshold ${this._perplexityThreshold}`,
108
+ };
109
+ }
110
+ return { target: 'ssm', reason: 'complexity', confidence: 0.8 };
111
+ }
112
+ }
113
+ //# sourceMappingURL=InferenceRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InferenceRouter.js","sourceRoot":"","sources":["../../src/router/InferenceRouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { InferenceRouter } from './InferenceRouter.js';
2
+ export type { RoutingStrategy, RoutingDecision, RouterContext, InferenceRouterOptions, RoutingAuditEntry } from './InferenceRouter.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { InferenceRouter } from './InferenceRouter.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}