@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sean Hogg
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,582 @@
1
+ # SSM.js
2
+
3
+ > **JavaScript-native AI runtime** — SSM execution + Transformer orchestration + online distillation + persistent agent memory.
4
+
5
+ [![npm](https://img.shields.io/npm/v/@seanhogg/ssmjs)](https://www.npmjs.com/package/@seanhogg/ssmjs)
6
+ [![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
7
+
8
+ SSM.js is a complete, self-contained AI runtime built directly on top of [MambaCode.js](https://www.npmjs.com/package/@seanhogg/mambacode.js). It includes the full session layer (previously `@seanhogg/mambakit`) as an internal layer, so you only need one package.
9
+
10
+ ---
11
+
12
+ ## Overview
13
+
14
+ SSM.js is a JavaScript-native AI runtime that combines local SSM (State Space Model) inference with optional transformer bridge escalation, persistent semantic memory, and online distillation — all without leaving the browser or Node.js process.
15
+
16
+ The layered stack:
17
+
18
+ ```
19
+ MambaCode.js → WebGPU kernels (WGSL, Mamba-1/2/3 SSM math)
20
+ SSM.js → Session layer + Runtime orchestration (this package)
21
+ ├── src/session/ MambaSession, tokenizer, persistence
22
+ ├── src/runtime/ SSMRuntime, routing
23
+ ├── src/memory/ MemoryStore
24
+ ├── src/agent/ SSMAgent
25
+ └── src/distillation/ DistillationEngine
26
+ ```
27
+
28
+ | Capability | SSM.js |
29
+ |------------------------------|--------|
30
+ | Simple session API | ✅ |
31
+ | WebGPU execution | ✅ |
32
+ | SSM variants (1/2/3/hybrid) | ✅ |
33
+ | Transformer bridge | ✅ |
34
+ | Intelligent routing | ✅ |
35
+ | Online distillation | ✅ |
36
+ | Persistent semantic memory | ✅ |
37
+ | Agent workflows | ✅ |
38
+
39
+ ---
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ npm install @seanhogg/ssmjs
45
+ # or
46
+ pnpm add @seanhogg/ssmjs
47
+ ```
48
+
49
+ `@seanhogg/ssmjs` includes the full session layer (previously `@seanhogg/mambakit`).
50
+ `@seanhogg/mambacode.js` is a peer dependency — install it alongside:
51
+
52
+ ```bash
53
+ npm install @seanhogg/ssmjs @seanhogg/mambacode.js
54
+ ```
55
+
56
+ ### Node.js requirements
57
+
58
+ Node.js 18+ is required. Two additional shims are needed for Node.js:
59
+
60
+ ```bash
61
+ npm install @webgpu/node fake-indexeddb
62
+ ```
63
+
64
+ - `@webgpu/node` — Dawn-based WebGPU for Node.js; drives all WGSL compute kernels
65
+ - `fake-indexeddb` — in-memory IndexedDB compatible with the IDB spec; used by `MemoryStore`
66
+
67
+ ---
68
+
69
+ ## Quick Start
70
+
71
+ ### Browser
72
+
73
+ ```ts
74
+ import { SSM, AnthropicBridge, SSMAgent, MemoryStore } from '@seanhogg/ssmjs';
75
+
76
+ const runtime = await SSM.create({
77
+ session: { modelSize: 'small', mambaVersion: 'mamba2' },
78
+ bridge : new AnthropicBridge({ apiKey: 'sk-ant-...' }),
79
+ });
80
+
81
+ // Generate — routes to SSM or transformer automatically
82
+ const answer = await runtime.generate('What is a state space model?');
83
+
84
+ // Streaming — always SSM for low-latency output
85
+ for await (const token of runtime.stream('function fibonacci(')) {
86
+ process.stdout.write(token);
87
+ }
88
+
89
+ // Fine-tune on your content
90
+ await runtime.adapt(myCodebase);
91
+ runtime.destroy();
92
+ ```
93
+
94
+ ### Node.js
95
+
96
+ ```ts
97
+ import { create as createGPU } from '@webgpu/node';
98
+ import { IDBFactory } from 'fake-indexeddb';
99
+ import { SSM, MemoryStore, SSMAgent } from '@seanhogg/ssmjs';
100
+
101
+ const gpuAdapter = await createGPU().requestAdapter({ powerPreference: 'high-performance' });
102
+ const idbFactory = new IDBFactory();
103
+
104
+ const runtime = await SSM.create({
105
+ session: {
106
+ gpuAdapter,
107
+ idbFactory,
108
+ modelSize: 'small',
109
+ },
110
+ });
111
+
112
+ const memory = new MemoryStore({ idbFactory });
113
+ const agent = new SSMAgent({ runtime, memory });
114
+ await agent.init(); // loads persisted history if present
115
+
116
+ const reply = await agent.think('Explain this codebase');
117
+ console.log(reply);
118
+
119
+ await agent.destroy(); // persists history, releases GPU
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Custom Tokenizers
125
+
126
+ By default, `MambaSession` uses the built-in Qwen2.5-Coder BPE tokenizer. You can override this by passing any object that satisfies the `Tokenizer` interface:
127
+
128
+ ```ts
129
+ import type { Tokenizer } from '@seanhogg/ssmjs';
130
+
131
+ const myTokenizer: Tokenizer = {
132
+ encode(text: string): number[] { /* your encode implementation */ return []; },
133
+ decode(tokens: number[]): string { /* your decode implementation */ return ''; },
134
+ get vocabSize(): number { return 32000; },
135
+ };
136
+
137
+ const runtime = await SSM.create({
138
+ session: {
139
+ tokenizer: myTokenizer, // replaces BPETokenizer entirely
140
+ modelSize: 'small',
141
+ },
142
+ });
143
+ ```
144
+
145
+ Use cases:
146
+ - **HuggingFace Transformers.js** tokenizer — wrap its `encode`/`decode` in the interface
147
+ - **Unit testing** — a stub tokenizer that maps words to sequential IDs, no network needed
148
+ - **Domain-specific vocabularies** — medical, legal, multilingual tokenizers
149
+
150
+ ---
151
+
152
+ ## Memory System
153
+
154
+ `MemoryStore` is a persistent, TTL-aware, tagged key-value fact store backed by IndexedDB.
155
+
156
+ ### Basic usage
157
+
158
+ ```ts
159
+ import { MemoryStore } from '@seanhogg/ssmjs';
160
+
161
+ const memory = new MemoryStore({
162
+ dbName : 'my-app',
163
+ defaultTtlMs: 7 * 24 * 60 * 60 * 1000, // 7-day default TTL
164
+ idbFactory, // Node.js only
165
+ });
166
+
167
+ // Store facts
168
+ await memory.remember('author', 'Sean Hogg');
169
+ await memory.remember('stack', 'React + TypeScript', {
170
+ tags : ['tech', 'project'],
171
+ importance: 0.8,
172
+ ttlMs : 30 * 24 * 60 * 60 * 1000, // 30 days
173
+ });
174
+
175
+ // Retrieve
176
+ const entry = await memory.recall('author');
177
+
178
+ // All non-expired facts, newest first
179
+ const all = await memory.recallAll();
180
+
181
+ // N most recent non-expired facts
182
+ const recent = await memory.recallRecent(10);
183
+
184
+ // Filter by tag
185
+ const techFacts = await memory.recallByTag('tech');
186
+
187
+ // Semantic similarity search (Jaccard word-overlap; SSM embeddings in future)
188
+ const similar = await memory.recallSimilar('who built this?', 5, runtime);
189
+
190
+ // Purge expired entries from storage
191
+ const deletedCount = await memory.purgeExpired();
192
+ ```
193
+
194
+ ### Cross-session memory merge
195
+
196
+ ```ts
197
+ // Export all non-expired facts from sessionA
198
+ const exported = await memoryA.exportAll();
199
+
200
+ // Import into sessionB
201
+ await memoryB.importAll(exported, 'merge');
202
+ // 'merge' — only overwrites if incoming entry is newer
203
+ // 'overwrite' — writes all entries unconditionally
204
+ ```
205
+
206
+ ### Weight persistence
207
+
208
+ ```ts
209
+ await memory.saveWeights(runtime); // saves model weights to IndexedDB
210
+ const loaded = await memory.loadWeights(runtime); // false if no checkpoint found
211
+ ```
212
+
213
+ ### MemoryEntry schema
214
+
215
+ ```ts
216
+ interface MemoryEntry {
217
+ key : string;
218
+ content : string;
219
+ timestamp : number;
220
+ ttlMs? : number; // optional TTL; entry filtered after timestamp + ttlMs
221
+ type? : FactType; // 'text' | 'json' | 'number' | 'boolean'
222
+ tags? : string[]; // for grouping/filtering
223
+ importance?: number; // 0–1, default 0.5; higher facts appear first in prompts
224
+ }
225
+ ```
226
+
227
+ ---
228
+
229
+ ## Inference Routing
230
+
231
+ `InferenceRouter` decides whether each request goes to the local SSM or the transformer bridge. It is built into `SSMRuntime` — you don't need to instantiate it directly.
232
+
233
+ ### Routing strategies
234
+
235
+ ```ts
236
+ const runtime = await SSM.create({
237
+ session: { modelSize: 'nano' },
238
+ bridge : claude,
239
+ routingStrategy : 'auto', // 'auto' | 'ssm' | 'transformer'
240
+ longInputThreshold: 1200, // chars before preferring transformer (default: 1200)
241
+ perplexityThreshold: 80, // SSM perplexity cutoff (default: 80)
242
+ });
243
+ ```
244
+
245
+ **Auto-routing heuristics (cheapest first):**
246
+ 1. **Complexity patterns** — "step by step", "analyze", "compare and contrast" → transformer
247
+ 2. **Input length** — over threshold → transformer
248
+ 3. **SSM perplexity** — async probe; high perplexity = novel topic → transformer
249
+
250
+ ### RoutingDecision type
251
+
252
+ `route()` now returns a structured `RoutingDecision` object:
253
+
254
+ ```ts
255
+ interface RoutingDecision {
256
+ target : 'ssm' | 'transformer';
257
+ reason : 'strategy' | 'complexity' | 'length' | 'perplexity' | 'no_bridge';
258
+ confidence: number; // 0–1
259
+ details? : string; // human-readable explanation
260
+ }
261
+ ```
262
+
263
+ ### Routing audit log
264
+
265
+ Every routing decision is appended to an in-memory audit log (last 500 entries):
266
+
267
+ ```ts
268
+ const log = runtime.getRoutingAuditLog();
269
+ // log: RoutingAuditEntry[]
270
+ // { timestamp, inputLength, decision: RoutingDecision, durationMs }
271
+ ```
272
+
273
+ ---
274
+
275
+ ## Distillation
276
+
277
+ Teach the local SSM using a transformer teacher — runs entirely in the browser or Node.js.
278
+
279
+ ```ts
280
+ import { DistillationEngine } from '@seanhogg/ssmjs';
281
+
282
+ const distiller = new DistillationEngine(runtime, claude);
283
+
284
+ // Single pass: claude generates → SSM adapts on output
285
+ const result = await distiller.distill('Explain WebGPU compute shaders', {
286
+ adapt : { wsla: true, epochs: 3 },
287
+ qualityGate: {
288
+ minLength : 50, // skip if teacher output < 50 chars
289
+ maxPerplexity: 15, // skip if SSM perplexity already < 15 (already learned)
290
+ },
291
+ });
292
+
293
+ console.log('skipped:', result.skipped, result.skipReason);
294
+ console.log('loss:', result.adaptResult.losses.at(-1));
295
+
296
+ // Batch distillation
297
+ const batch = await distiller.distillBatch([
298
+ 'What is a Mamba block?',
299
+ 'Explain WSLA adaptation.',
300
+ ], { adapt: { wsla: true, epochs: 5 } });
301
+
302
+ console.log(`${batch.totalEpochs} epochs in ${batch.totalMs}ms`);
303
+ ```
304
+
305
+ ### Quality gates
306
+
307
+ | Gate option | Description |
308
+ |------------------|-------------|
309
+ | `minLength` | Skip if teacher output is shorter than N characters (low-quality response) |
310
+ | `maxPerplexity` | Skip if SSM perplexity on teacher output is already below threshold (already learned) |
311
+
312
+ ### Distillation log
313
+
314
+ ```ts
315
+ const log = distiller.getLog();
316
+ // log: DistillationLog[]
317
+ // { timestamp, input, teacherOutputLength, skipped, skipReason?, finalLoss?, epochs }
318
+ ```
319
+
320
+ The log is bounded to the last 200 entries.
321
+
322
+ ---
323
+
324
+ ## SSMAgent
325
+
326
+ High-level orchestration: conversation history, routing, memory injection, and lifecycle.
327
+
328
+ ```ts
329
+ import { SSMAgent, MemoryStore } from '@seanhogg/ssmjs';
330
+
331
+ const memory = new MemoryStore();
332
+ const agent = new SSMAgent({
333
+ runtime : runtime,
334
+ memory,
335
+ systemPrompt : 'You are a senior TypeScript engineer.',
336
+ maxHistoryTurns: 20,
337
+ persistHistory : true, // saves/loads history via memory on destroy/init
338
+ });
339
+
340
+ // Load persisted history from a prior session
341
+ await agent.init();
342
+
343
+ // Store project context
344
+ await agent.remember('stack', 'React 18, TypeScript 5, Vite');
345
+
346
+ // Multi-turn conversation — facts with highest importance appear first in context
347
+ const reply1 = await agent.think('What stack should I use?');
348
+ const reply2 = await agent.think('How do I handle concurrent edits?');
349
+
350
+ // Streaming
351
+ for await (const token of agent.thinkStream('Show me a WebSocket hook')) {
352
+ process.stdout.write(token);
353
+ }
354
+
355
+ // Teach the agent from content
356
+ await agent.learn(myCodebase, { wsla: true, epochs: 3 });
357
+
358
+ console.log(agent.turnCount); // 2
359
+
360
+ // Persists history to memory, then destroys runtime
361
+ await agent.destroy();
362
+ ```
363
+
364
+ ### History persistence
365
+
366
+ When `persistHistory: true` (default):
367
+ - On `agent.init()`: loads `__history__` from the `MemoryStore` and restores conversation turns.
368
+ - On `agent.destroy()`: serialises `_history` to JSON and writes it under `__history__`.
369
+
370
+ This enables multi-session continuity without external state management.
371
+
372
+ ### Fact injection order
373
+
374
+ Facts retrieved from `MemoryStore` are sorted by `importance` descending before being injected into the prompt. Higher-importance facts appear first, giving the model the most relevant context regardless of insertion order.
375
+
376
+ ---
377
+
378
+ ## Migration from MambaKit
379
+
380
+ `@seanhogg/mambakit` has been consolidated into this package. `MambaSession` and all related types are now exported directly from `@seanhogg/ssmjs`.
381
+
382
+ **Before:**
383
+
384
+ ```bash
385
+ npm install @seanhogg/mambakit @seanhogg/ssmjs
386
+ ```
387
+
388
+ ```ts
389
+ import { MambaSession } from '@seanhogg/mambakit';
390
+ import type { MambaSessionOptions, Tokenizer } from '@seanhogg/mambakit';
391
+ ```
392
+
393
+ **After:**
394
+
395
+ ```bash
396
+ npm install @seanhogg/ssmjs
397
+ ```
398
+
399
+ ```ts
400
+ import { MambaSession, SessionError } from '@seanhogg/ssmjs';
401
+ import type { MambaSessionOptions, Tokenizer } from '@seanhogg/ssmjs';
402
+ ```
403
+
404
+ All types are re-exported unchanged — `MambaSessionOptions`, `CompleteOptions`, `AdaptOptions`,
405
+ `AdaptResult`, `SaveOptions`, `LoadOptions`, `StorageTarget`, `CreateCallbacks`,
406
+ `LayerSchedulePreset`, `MODEL_PRESETS`, `GpuMode`, and `Tokenizer`.
407
+ No logic changes are required, only the import path.
408
+
409
+ ---
410
+
411
+ ## BuilderForce Agents Integration
412
+
413
+ SSM.js serves as the **hippocampus** layer of [BuilderForce Agents](https://builderforce.ai)'s gateway — a persistent semantic memory and local inference engine running alongside the frontier LLM (Claude/GPT) cortex.
414
+
415
+ The `SsmMemoryService` class in BuilderForce Agents's `src/infra/ssm-memory-service.ts` wraps an `SSMRuntime` + `SSMAgent` + `MemoryStore` triplet:
416
+
417
+ ```
418
+ BuilderForce Agents gateway
419
+ ├── server-startup.ts ← initSsmMemoryService() on boot
420
+ ├── infra/knowledge-loop.ts ← remember() + learn() on every agent run
421
+ ├── infra/ssm-memory-service.ts ← SsmMemoryService wrapper
422
+ └── builderforce/orchestrator.ts ← recallSimilar() injected into task prompts
423
+ ```
424
+
425
+ **Data flow:**
426
+ 1. Agent run completes → `KnowledgeLoopService` derives activity summary
427
+ 2. Summary is stored in `.builderforce/memory/YYYY-MM-DD.md` (markdown log)
428
+ 3. Summary is also passed to `ssmSvc.remember()` (tagged + importance-weighted)
429
+ 4. Summary is passed to `ssmSvc.learn()` → WSLA fine-tuning adapts the SSM
430
+ 5. On next workflow task, `recallSimilar(taskDescription, 5)` injects relevant memories into the prompt as a `[Memory Context]` block
431
+
432
+ GPU init is optional: if `@webgpu/node` is unavailable, the service starts in memory-only mode (`gpuAvailable: false`) and SSM inference is skipped. The gateway never crashes due to a missing GPU.
433
+
434
+ ---
435
+
436
+ ## Phase Roadmap
437
+
438
+ ### Phase 1 — Foundations
439
+ - Session layer: `Tokenizer` interface + pluggable injection via `MambaSessionOptions.tokenizer`
440
+ - `MemoryStore`: TTL (`ttlMs`), `defaultTtlMs`, `purgeExpired()`, `recallRecent(n)`
441
+ - `MemoryStore`: `FactType`, `tags`, `importance` fields on `MemoryEntry`
442
+ - `MemoryStore`: updated `remember()` accepting `RememberOptions`
443
+ - `InferenceRouter`: `route()` now returns `RoutingDecision` object with `target`, `reason`, `confidence`, `details`
444
+ - `SSMAgent`: `persistHistory` option; `init()` loads `__history__`; `destroy()` saves it
445
+ - `SSMAgent`: fact injection sorted by `importance` descending
446
+
447
+ ### Phase 2 — Semantic Memory
448
+ - `MemoryStore.recallSimilar(query, topK, runtime)` — Jaccard similarity; SSM embedding-based search in future
449
+ - `MemoryStore.recallByTag(tag)` — tag-based filtering
450
+ - `MemoryStore.exportAll()` / `importAll(entries, strategy)` — cross-session merge
451
+
452
+ ### Phase 3 — BuilderForce Agents Integration
453
+ - `SsmMemoryService` in `src/infra/ssm-memory-service.ts` — singleton gateway service
454
+ - `server-startup.ts`: `initSsmMemoryService()` on boot; non-fatal GPU fallback
455
+ - `KnowledgeLoopService`: `remember()` + `learn()` on every agent run completion
456
+ - `AgentOrchestrator`: `recallSimilar()` injected as `[Memory Context]` before task dispatch
457
+
458
+ ### Phase 4 — Feedback Loop
459
+ - `DistillationEngine`: `qualityGate` option (`minLength`, `maxPerplexity`)
460
+ - `DistillResult`: `skipped` + `skipReason` fields
461
+ - `DistillationEngine.getLog()` — bounded in-memory `DistillationLog[]`
462
+ - `InferenceRouter`: `RoutingAuditEntry` + `getAuditLog()` — bounded in-memory log
463
+ - `SSMRuntime.getRoutingAuditLog()` — delegates to router
464
+ - `SSMRuntime.getDistillationLog()` — stub; returns empty array (inline engine future work)
465
+
466
+ ---
467
+
468
+ ## API Reference
469
+
470
+ ### `SSM.create(opts)` / `SSMRuntime.create(opts)`
471
+
472
+ | Option | Type | Default | Description |
473
+ |---|---|---|---|
474
+ | `session` | `MambaSessionOptions` | required | Forwarded to `MambaSession.create()` |
475
+ | `bridge` | `TransformerBridge` | — | Transformer backend for routing/distillation |
476
+ | `routingStrategy` | `'auto'\|'ssm'\|'transformer'` | `'auto'` | Routing strategy |
477
+ | `longInputThreshold` | `number` | `1200` | Chars before auto-routing prefers transformer |
478
+ | `perplexityThreshold` | `number` | `80` | SSM perplexity cutoff |
479
+ | `callbacks` | `CreateCallbacks` | — | Progress callbacks |
480
+
481
+ ### `runtime.generate(input, opts?)`
482
+ Generates a full response. Routes to SSM or transformer per strategy. Returns `Promise<string>`.
483
+
484
+ ### `runtime.stream(input, opts?)`
485
+ `AsyncIterable<string>` — always uses SSM path for consistent latency.
486
+
487
+ ### `runtime.streamHybrid(input, opts?)`
488
+ `AsyncIterable<string>` — routes like `generate()`, streams via bridge if available.
489
+
490
+ ### `runtime.adapt(data, opts?)`
491
+ Pass-through to `session.adapt()`. Returns `AdaptResult`.
492
+
493
+ ### `runtime.evaluate(text)`
494
+ Returns SSM perplexity. Used internally by auto-routing.
495
+
496
+ ### `runtime.getRoutingAuditLog()`
497
+ Returns `RoutingAuditEntry[]` — last 500 routing decisions with timing.
498
+
499
+ ### `runtime.getDistillationLog()`
500
+ Returns `DistillationLog[]` — last 200 distillation runs (stub; use `distiller.getLog()` directly).
501
+
502
+ ### `runtime.save(opts?)` / `runtime.load(opts?)`
503
+ Weight persistence pass-throughs to `MambaSession`.
504
+
505
+ ### `runtime.destroy()`
506
+ Releases GPU device and all buffers.
507
+
508
+ ---
509
+
510
+ ## Error Handling
511
+
512
+ ```ts
513
+ import { SSMError, SessionError } from '@seanhogg/ssmjs';
514
+
515
+ try {
516
+ const runtime = await SSM.create({ session: { modelSize: 'nano' } });
517
+ await runtime.generate('hello');
518
+ } catch (err) {
519
+ if (err instanceof SSMError) {
520
+ // Runtime-level error (bridge, distillation, memory)
521
+ console.error(err.code); // 'BRIDGE_REQUEST_FAILED' | 'RUNTIME_DESTROYED' | ...
522
+ }
523
+ if (err instanceof SessionError) {
524
+ // Session-level error (GPU init, tokenizer, checkpoint)
525
+ console.error(err.code); // 'GPU_UNAVAILABLE' | 'TOKENIZER_LOAD_FAILED' | ...
526
+ }
527
+ }
528
+ ```
529
+
530
+ ---
531
+
532
+ ## File Structure
533
+
534
+ ```
535
+ src/
536
+ ├── index.ts ← package entry + SSM namespace
537
+ ├── session/ ← session layer (absorbed from @seanhogg/mambakit)
538
+ │ ├── session.ts ← MambaSession.create() — GPU, tokenizer, model, persistence
539
+ │ ├── tokenizer.ts ← Tokenizer interface (pluggable)
540
+ │ ├── presets.ts ← MODEL_PRESETS + layer schedule resolution
541
+ │ ├── persistence.ts ← IndexedDB / download / File System API helpers
542
+ │ ├── streaming.ts ← AsyncIterable token streaming
543
+ │ ├── errors.ts ← SessionError typed error class
544
+ │ └── index.ts ← barrel export
545
+ ├── runtime/
546
+ │ └── SSMRuntime.ts ← core runtime, owns MambaSession
547
+ ├── bridges/
548
+ │ ├── TransformerBridge.ts ← interface
549
+ │ ├── OpenAIBridge.ts ← OpenAI chat completions
550
+ │ ├── AnthropicBridge.ts ← Anthropic Messages API
551
+ │ └── FetchBridge.ts ← generic OpenAI-compatible endpoint
552
+ ├── router/
553
+ │ └── InferenceRouter.ts ← SSM ↔ transformer routing + audit log
554
+ ├── memory/
555
+ │ └── MemoryStore.ts ← IndexedDB fact store: TTL, tags, importance, export/import
556
+ ├── distillation/
557
+ │ └── DistillationEngine.ts ← online teacher→student distillation + quality gates
558
+ ├── agent/
559
+ │ └── SSMAgent.ts ← orchestration: history persistence + fact injection
560
+ └── errors/
561
+ └── SSMError.ts ← typed error class
562
+ ```
563
+
564
+ ---
565
+
566
+ ## Professional Platform
567
+
568
+ **SSM.js patterns are the architectural foundation of [Builderforce.ai](https://builderforce.ai)'s Agent Runtime.**
569
+
570
+ | SSM.js concept | Builderforce.ai equivalent |
571
+ |---|---|
572
+ | `SSMRuntime` | `AgentRuntime` (browser-native, ties to IDE project) |
573
+ | `DistillationEngine` | LLM-assisted dataset generation → in-browser LoRA training |
574
+ | `MemoryStore` | IndexedDB `MambaAgentState` + `AgentPackage` embedding |
575
+ | `SSMAgent` | Published workforce agent (Workforce Registry) |
576
+ | `TransformerBridge` | Cloudflare Workers AI / OpenRouter fallback |
577
+
578
+ ---
579
+
580
+ ## License
581
+
582
+ MIT