@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,146 @@
1
+ /**
2
+ * SSMAgent – high-level orchestration primitive.
3
+ *
4
+ * Combines SSMRuntime (inference + adaptation), MemoryStore (persistent facts),
5
+ * and a conversation history manager into a single agent interface.
6
+ *
7
+ * Prompt format matches MambaChatbot so the SSM model can follow the same
8
+ * token patterns it was trained on:
9
+ *
10
+ * System: <systemPrompt>
11
+ * [Fact (<key>): <content> ← injected by importance desc, filtered by tag/key]
12
+ * User: <message>
13
+ * Assistant: <message>
14
+ * ...
15
+ * User: <current input>
16
+ * Assistant:
17
+ */
18
+ import type { AdaptOptions, AdaptResult } from '../session/index.js';
19
+ import type { SSMRuntime, GenerateOptions } from '../runtime/SSMRuntime.js';
20
+ import type { MemoryStore } from '../memory/MemoryStore.js';
21
+ export type MessageRole = 'user' | 'assistant' | 'system';
22
+ export interface AgentMessage {
23
+ role: MessageRole;
24
+ content: string;
25
+ }
26
+ export interface SSMAgentOptions {
27
+ /** The runtime to use for inference and adaptation. */
28
+ runtime: SSMRuntime;
29
+ /** Optional memory store for persistent fact retrieval. */
30
+ memory?: MemoryStore;
31
+ /** Default system prompt. Default: 'You are a helpful assistant.' */
32
+ systemPrompt?: string;
33
+ /**
34
+ * Max user+assistant turn pairs to include in context.
35
+ * Oldest turns are dropped first.
36
+ * Default: 20
37
+ */
38
+ maxHistoryTurns?: number;
39
+ /**
40
+ * When true, the agent serialises its conversation history to memory
41
+ * under the `__history__` key on `destroy()`, and loads it back on
42
+ * construction if the key is present.
43
+ * Default: true
44
+ */
45
+ persistHistory?: boolean;
46
+ /**
47
+ * How facts are picked from the MemoryStore for injection each turn:
48
+ * - 'semantic' (default): top-`maxFacts` by SSM-embedding similarity to
49
+ * the input (`recallSimilar`) — injects the few *relevant* facts, which
50
+ * keeps the prompt small and is paraphrase-robust.
51
+ * - 'substring': legacy behaviour — only facts whose key literally appears
52
+ * in the input.
53
+ * `injectAllFacts` on a turn overrides this and injects everything.
54
+ */
55
+ factSelection?: 'semantic' | 'substring';
56
+ /** Max facts injected in 'semantic' mode. Default: 8. */
57
+ maxFacts?: number;
58
+ }
59
+ export interface ThinkOptions extends GenerateOptions {
60
+ /** Override the system prompt for this single turn only. */
61
+ systemPrompt?: string;
62
+ /**
63
+ * Inject all recalled facts into the context for this turn.
64
+ * Default: false — only facts whose keys appear in the input are injected.
65
+ */
66
+ injectAllFacts?: boolean;
67
+ }
68
+ export declare class SSMAgent {
69
+ private readonly _runtime;
70
+ private readonly _memory;
71
+ private readonly _systemPrompt;
72
+ private readonly _maxHistoryTurns;
73
+ private readonly _persistHistory;
74
+ private readonly _factSelection;
75
+ private readonly _maxFacts;
76
+ private _history;
77
+ constructor(opts: SSMAgentOptions);
78
+ /**
79
+ * Initialises the agent, loading persisted history from memory if available.
80
+ * Call this after construction when `persistHistory` is enabled and a memory
81
+ * store is present.
82
+ */
83
+ init(): Promise<void>;
84
+ /**
85
+ * Sends a user message and returns the full assistant response.
86
+ * Routes through InferenceRouter — may use SSM or transformer bridge.
87
+ * Appends both user and assistant turns to history.
88
+ */
89
+ think(input: string, opts?: ThinkOptions): Promise<string>;
90
+ /**
91
+ * Streaming variant of `think()`.
92
+ * Always uses the SSM path (consistent low-latency streaming).
93
+ * Appends history after the stream completes.
94
+ */
95
+ thinkStream(input: string, opts?: ThinkOptions): AsyncIterable<string>;
96
+ /**
97
+ * Fine-tunes the SSM on the provided text.
98
+ * Pass-through to runtime.adapt().
99
+ */
100
+ learn(data: string, opts?: AdaptOptions): Promise<AdaptResult>;
101
+ /**
102
+ * Stores a fact in the MemoryStore.
103
+ * Throws SSMError('MEMORY_UNAVAILABLE') if no MemoryStore was provided.
104
+ */
105
+ remember(key: string, fact: string): Promise<void>;
106
+ /**
107
+ * Retrieves a fact from the MemoryStore.
108
+ * Returns `undefined` if key not found or no MemoryStore was provided.
109
+ */
110
+ recall(key: string): Promise<string | undefined>;
111
+ /** Clears all conversation history. Does not affect MemoryStore. */
112
+ clearHistory(): void;
113
+ /** Number of complete user+assistant turn pairs. */
114
+ get turnCount(): number;
115
+ /** Read-only snapshot of the current conversation history. */
116
+ get history(): readonly AgentMessage[];
117
+ /**
118
+ * Persists conversation history to memory (if `persistHistory` is true and
119
+ * a MemoryStore is available) and destroys the underlying runtime.
120
+ */
121
+ destroy(): Promise<void>;
122
+ /**
123
+ * Selects which stored facts to inject for this turn:
124
+ * - injectAllFacts → every fact
125
+ * - 'semantic' → top-`maxFacts` by SSM-embedding similarity to the input
126
+ * (recallSimilar; falls back to lexical overlap when the
127
+ * runtime can't embed) — small, relevant, paraphrase-robust
128
+ * - 'substring' → legacy key-substring match
129
+ */
130
+ private _selectFacts;
131
+ /**
132
+ * Builds the prompt as two parts split at the cache boundary:
133
+ * - `system` : the System line + injected Facts — stable across a
134
+ * turn, so the transformer can cache it (see
135
+ * SSMRuntime.GenerateOptions.system).
136
+ * - `conversation` : trimmed history + the current User turn — volatile,
137
+ * regenerated every turn.
138
+ *
139
+ * Joining them with a newline (which SSMRuntime does on the SSM path)
140
+ * reproduces the original single-string MambaChatbot format exactly, so the
141
+ * SSM sees an unchanged prompt.
142
+ */
143
+ private _buildPrompt;
144
+ private _appendHistory;
145
+ }
146
+ //# sourceMappingURL=SSMAgent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SSMAgent.d.ts","sourceRoot":"","sources":["../../src/agent/SSMAgent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,0BAA0B,CAAC;AAKzE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE1D,MAAM,WAAW,YAAY;IACzB,IAAI,EAAK,WAAW,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC5B,uDAAuD;IACvD,OAAO,EAAY,UAAU,CAAC;IAC9B,2DAA2D;IAC3D,MAAM,CAAC,EAAY,WAAW,CAAC;IAC/B,qEAAqE;IACrE,YAAY,CAAC,EAAM,MAAM,CAAC;IAC1B;;;;OAIG;IACH,eAAe,CAAC,EAAG,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,cAAc,CAAC,EAAI,OAAO,CAAC;IAC3B;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAK,UAAU,GAAG,WAAW,CAAC;IAC5C,yDAAyD;IACzD,QAAQ,CAAC,EAAU,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,YAAa,SAAQ,eAAe;IACjD,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAOD,qBAAa,QAAQ;IACjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAa;IAC3C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAC3C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAY;IAC5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA8B;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAsB;gBAE1B,IAAI,EAAE,eAAe;IAUjC;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB3B;;;;OAIG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBpE;;;;OAIG;IACI,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiB,GAAG,aAAa,CAAC,MAAM,CAAC;IAuBjF;;;OAGG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAMpE;;;OAGG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxD;;;OAGG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAQtD,oEAAoE;IACpE,YAAY,IAAI,IAAI;IAIpB,oDAAoD;IACpD,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,8DAA8D;IAC9D,IAAI,OAAO,IAAI,SAAS,YAAY,EAAE,CAErC;IAID;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAa9B;;;;;;;OAOG;YACW,YAAY;IAS1B;;;;;;;;;;;OAWG;YACW,YAAY;IA6C1B,OAAO,CAAC,cAAc;CAIzB"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * SSMAgent – high-level orchestration primitive.
3
+ *
4
+ * Combines SSMRuntime (inference + adaptation), MemoryStore (persistent facts),
5
+ * and a conversation history manager into a single agent interface.
6
+ *
7
+ * Prompt format matches MambaChatbot so the SSM model can follow the same
8
+ * token patterns it was trained on:
9
+ *
10
+ * System: <systemPrompt>
11
+ * [Fact (<key>): <content> ← injected by importance desc, filtered by tag/key]
12
+ * User: <message>
13
+ * Assistant: <message>
14
+ * ...
15
+ * User: <current input>
16
+ * Assistant:
17
+ */
18
+ import { SSMError } from '../errors/SSMError.js';
19
+ /** Key used to persist conversation history in the MemoryStore. */
20
+ const HISTORY_KEY = '__history__';
21
+ // ── SSMAgent ──────────────────────────────────────────────────────────────────
22
+ export class SSMAgent {
23
+ _runtime;
24
+ _memory;
25
+ _systemPrompt;
26
+ _maxHistoryTurns;
27
+ _persistHistory;
28
+ _factSelection;
29
+ _maxFacts;
30
+ _history = [];
31
+ constructor(opts) {
32
+ this._runtime = opts.runtime;
33
+ this._memory = opts.memory;
34
+ this._systemPrompt = opts.systemPrompt ?? 'You are a helpful assistant.';
35
+ this._maxHistoryTurns = opts.maxHistoryTurns ?? 20;
36
+ this._persistHistory = opts.persistHistory ?? true;
37
+ this._factSelection = opts.factSelection ?? 'semantic';
38
+ this._maxFacts = opts.maxFacts ?? 8;
39
+ }
40
+ /**
41
+ * Initialises the agent, loading persisted history from memory if available.
42
+ * Call this after construction when `persistHistory` is enabled and a memory
43
+ * store is present.
44
+ */
45
+ async init() {
46
+ if (this._persistHistory && this._memory) {
47
+ try {
48
+ const entry = await this._memory.recall(HISTORY_KEY);
49
+ if (entry) {
50
+ const parsed = JSON.parse(entry.content);
51
+ if (Array.isArray(parsed)) {
52
+ this._history = parsed;
53
+ }
54
+ }
55
+ }
56
+ catch {
57
+ // Corrupted or missing history — start fresh
58
+ this._history = [];
59
+ }
60
+ }
61
+ }
62
+ // ── Inference ─────────────────────────────────────────────────────────────
63
+ /**
64
+ * Sends a user message and returns the full assistant response.
65
+ * Routes through InferenceRouter — may use SSM or transformer bridge.
66
+ * Appends both user and assistant turns to history.
67
+ */
68
+ async think(input, opts = {}) {
69
+ const { systemPrompt, injectAllFacts, ...generateOpts } = opts;
70
+ const { system, conversation } = await this._buildPrompt(input, systemPrompt, injectAllFacts);
71
+ const raw = await this._runtime.generate(conversation, {
72
+ maxNewTokens: 200,
73
+ temperature: 0.7,
74
+ topK: 50,
75
+ topP: 0.9,
76
+ system,
77
+ ...generateOpts,
78
+ });
79
+ // Trim any additional turns the model may have hallucinated
80
+ const response = raw.split('\nUser:')[0].trim();
81
+ this._appendHistory(input, response);
82
+ return response;
83
+ }
84
+ /**
85
+ * Streaming variant of `think()`.
86
+ * Always uses the SSM path (consistent low-latency streaming).
87
+ * Appends history after the stream completes.
88
+ */
89
+ async *thinkStream(input, opts = {}) {
90
+ const { systemPrompt, injectAllFacts, bridgeOpts: _b, ...completeOpts } = opts;
91
+ const { system, conversation } = await this._buildPrompt(input, systemPrompt, injectAllFacts);
92
+ let full = '';
93
+ for await (const token of this._runtime.stream(conversation, {
94
+ maxNewTokens: 200,
95
+ temperature: 0.7,
96
+ topK: 50,
97
+ topP: 0.9,
98
+ system,
99
+ ...completeOpts,
100
+ })) {
101
+ full += token;
102
+ yield token;
103
+ }
104
+ const response = full.split('\nUser:')[0].trim();
105
+ this._appendHistory(input, response);
106
+ }
107
+ // ── Adaptation ────────────────────────────────────────────────────────────
108
+ /**
109
+ * Fine-tunes the SSM on the provided text.
110
+ * Pass-through to runtime.adapt().
111
+ */
112
+ async learn(data, opts) {
113
+ return this._runtime.adapt(data, opts);
114
+ }
115
+ // ── Memory ────────────────────────────────────────────────────────────────
116
+ /**
117
+ * Stores a fact in the MemoryStore.
118
+ * Throws SSMError('MEMORY_UNAVAILABLE') if no MemoryStore was provided.
119
+ */
120
+ async remember(key, fact) {
121
+ if (!this._memory) {
122
+ throw new SSMError('MEMORY_UNAVAILABLE', 'SSMAgent was constructed without a MemoryStore. Pass `memory` in SSMAgentOptions.');
123
+ }
124
+ await this._memory.remember(key, fact);
125
+ }
126
+ /**
127
+ * Retrieves a fact from the MemoryStore.
128
+ * Returns `undefined` if key not found or no MemoryStore was provided.
129
+ */
130
+ async recall(key) {
131
+ if (!this._memory)
132
+ return undefined;
133
+ const entry = await this._memory.recall(key);
134
+ return entry?.content;
135
+ }
136
+ // ── History ───────────────────────────────────────────────────────────────
137
+ /** Clears all conversation history. Does not affect MemoryStore. */
138
+ clearHistory() {
139
+ this._history = [];
140
+ }
141
+ /** Number of complete user+assistant turn pairs. */
142
+ get turnCount() {
143
+ return Math.floor(this._history.length / 2);
144
+ }
145
+ /** Read-only snapshot of the current conversation history. */
146
+ get history() {
147
+ return this._history;
148
+ }
149
+ // ── Lifecycle ─────────────────────────────────────────────────────────────
150
+ /**
151
+ * Persists conversation history to memory (if `persistHistory` is true and
152
+ * a MemoryStore is available) and destroys the underlying runtime.
153
+ */
154
+ async destroy() {
155
+ if (this._persistHistory && this._memory && this._history.length > 0) {
156
+ try {
157
+ await this._memory.remember(HISTORY_KEY, JSON.stringify(this._history));
158
+ }
159
+ catch {
160
+ // Persistence failure is non-fatal
161
+ }
162
+ }
163
+ this._runtime.destroy();
164
+ }
165
+ // ── Private helpers ───────────────────────────────────────────────────────
166
+ /**
167
+ * Selects which stored facts to inject for this turn:
168
+ * - injectAllFacts → every fact
169
+ * - 'semantic' → top-`maxFacts` by SSM-embedding similarity to the input
170
+ * (recallSimilar; falls back to lexical overlap when the
171
+ * runtime can't embed) — small, relevant, paraphrase-robust
172
+ * - 'substring' → legacy key-substring match
173
+ */
174
+ async _selectFacts(input, injectAllFacts) {
175
+ const memory = this._memory;
176
+ if (injectAllFacts)
177
+ return memory.recallAll();
178
+ if (this._factSelection === 'semantic') {
179
+ return memory.recallSimilar(input, this._maxFacts, this._runtime);
180
+ }
181
+ return (await memory.recallAll()).filter(f => input.includes(f.key));
182
+ }
183
+ /**
184
+ * Builds the prompt as two parts split at the cache boundary:
185
+ * - `system` : the System line + injected Facts — stable across a
186
+ * turn, so the transformer can cache it (see
187
+ * SSMRuntime.GenerateOptions.system).
188
+ * - `conversation` : trimmed history + the current User turn — volatile,
189
+ * regenerated every turn.
190
+ *
191
+ * Joining them with a newline (which SSMRuntime does on the SSM path)
192
+ * reproduces the original single-string MambaChatbot format exactly, so the
193
+ * SSM sees an unchanged prompt.
194
+ */
195
+ async _buildPrompt(input, systemPromptOverride, injectAllFacts) {
196
+ const sys = systemPromptOverride ?? this._systemPrompt;
197
+ const systemLines = [`System: ${sys}`];
198
+ // Inject relevant facts from MemoryStore, sorted by importance descending
199
+ if (this._memory) {
200
+ const relevant = (await this._selectFacts(input, injectAllFacts))
201
+ // Never inject the serialised conversation-history blob as a fact.
202
+ .filter(f => f.key !== HISTORY_KEY);
203
+ // Sort by importance descending (missing importance defaults to 0.5)
204
+ const sorted = relevant.slice().sort((a, b) => (b.importance ?? 0.5) - (a.importance ?? 0.5));
205
+ for (const fact of sorted) {
206
+ systemLines.push(`Fact (${fact.key}): ${fact.content}`);
207
+ }
208
+ }
209
+ // Trim history to maxHistoryTurns pairs (oldest first)
210
+ const maxMessages = this._maxHistoryTurns * 2;
211
+ const trimmed = this._history.length > maxMessages
212
+ ? this._history.slice(this._history.length - maxMessages)
213
+ : this._history;
214
+ const convoLines = [];
215
+ for (const msg of trimmed) {
216
+ const speaker = msg.role === 'user' ? 'User' : 'Assistant';
217
+ convoLines.push(`${speaker}: ${msg.content}`);
218
+ }
219
+ convoLines.push(`User: ${input}`);
220
+ convoLines.push('Assistant:');
221
+ return {
222
+ system: systemLines.join('\n'),
223
+ conversation: convoLines.join('\n'),
224
+ };
225
+ }
226
+ _appendHistory(input, response) {
227
+ this._history.push({ role: 'user', content: input });
228
+ this._history.push({ role: 'assistant', content: response });
229
+ }
230
+ }
231
+ //# sourceMappingURL=SSMAgent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SSMAgent.js","sourceRoot":"","sources":["../../src/agent/SSMAgent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { SSMAgent } from './SSMAgent.js';
2
+ export type { SSMAgentOptions, ThinkOptions, AgentMessage, MessageRole } from './SSMAgent.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { SSMAgent } from './SSMAgent.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * AnthropicBridge – TransformerBridge implementation for the Anthropic Messages API.
3
+ *
4
+ * Uses the /v1/messages endpoint. System prompts are passed as the top-level
5
+ * `system` field (not a message role), per the Anthropic spec.
6
+ */
7
+ import type { TransformerBridge, BridgeGenerateOptions } from './TransformerBridge.js';
8
+ export interface AnthropicBridgeOptions {
9
+ /** Anthropic API key. */
10
+ apiKey: string;
11
+ /**
12
+ * Model to use. Default: 'claude-haiku-4-5' (cheapest current model:
13
+ * $1/1M input, $5/1M output). The previous default `claude-3-5-haiku-*`
14
+ * was retired on 2026-02-19 and now 404s.
15
+ */
16
+ model?: string;
17
+ /** Anthropic API version header. Default: '2023-06-01'. */
18
+ apiVersion?: string;
19
+ /** Default system prompt. Default: none. */
20
+ systemPrompt?: string;
21
+ /** Default max tokens — required by Anthropic. Default: 1024. */
22
+ maxTokens?: number;
23
+ /**
24
+ * When true (default), the system prompt is sent as a cacheable content
25
+ * block (`cache_control: {type: 'ephemeral'}`). Prompt caching bills cache
26
+ * reads at ~10% of the input price, so a stable system prefix reused across
27
+ * turns is up to ~90% cheaper on its input tokens. Caching only engages once
28
+ * the cached prefix exceeds the model minimum (~4096 tokens for Haiku 4.5);
29
+ * below that it is a silent no-op, never an error. Set false to opt out.
30
+ */
31
+ cacheSystem?: boolean;
32
+ }
33
+ export declare class AnthropicBridge implements TransformerBridge {
34
+ readonly supportsStreaming: true;
35
+ private readonly _apiKey;
36
+ private readonly _model;
37
+ private readonly _apiVersion;
38
+ private readonly _systemPrompt;
39
+ private readonly _maxTokens;
40
+ private readonly _cacheSystem;
41
+ constructor(opts: AnthropicBridgeOptions);
42
+ generate(prompt: string, opts?: BridgeGenerateOptions): Promise<string>;
43
+ stream(prompt: string, opts?: BridgeGenerateOptions): AsyncIterable<string>;
44
+ private _buildBody;
45
+ private _fetch;
46
+ }
47
+ //# sourceMappingURL=AnthropicBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnthropicBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/AnthropicBridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEvF,MAAM,WAAW,sBAAsB;IACnC,yBAAyB;IACzB,MAAM,EAAU,MAAM,CAAC;IACvB;;;;OAIG;IACH,KAAK,CAAC,EAAU,MAAM,CAAC;IACvB,2DAA2D;IAC3D,UAAU,CAAC,EAAK,MAAM,CAAC;IACvB,4CAA4C;IAC5C,YAAY,CAAC,EAAG,MAAM,CAAC;IACvB,iEAAiE;IACjE,SAAS,CAAC,EAAM,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAI,OAAO,CAAC;CAC3B;AAID,qBAAa,eAAgB,YAAW,iBAAiB;IACrD,QAAQ,CAAC,iBAAiB,EAAG,IAAI,CAAU;IAE3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAW;gBAE5B,IAAI,EAAE,sBAAsB;IASlC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC;IAoB1E,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,qBAA0B,GAAG,aAAa,CAAC,MAAM,CAAC;IAmBtF,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,MAAM;CAWjB"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * AnthropicBridge – TransformerBridge implementation for the Anthropic Messages API.
3
+ *
4
+ * Uses the /v1/messages endpoint. System prompts are passed as the top-level
5
+ * `system` field (not a message role), per the Anthropic spec.
6
+ */
7
+ import { SSMError } from '../errors/SSMError.js';
8
+ const API_URL = 'https://api.anthropic.com/v1/messages';
9
+ export class AnthropicBridge {
10
+ supportsStreaming = true;
11
+ _apiKey;
12
+ _model;
13
+ _apiVersion;
14
+ _systemPrompt;
15
+ _maxTokens;
16
+ _cacheSystem;
17
+ constructor(opts) {
18
+ this._apiKey = opts.apiKey;
19
+ this._model = opts.model ?? 'claude-haiku-4-5';
20
+ this._apiVersion = opts.apiVersion ?? '2023-06-01';
21
+ this._systemPrompt = opts.systemPrompt ?? '';
22
+ this._maxTokens = opts.maxTokens ?? 1024;
23
+ this._cacheSystem = opts.cacheSystem ?? true;
24
+ }
25
+ async generate(prompt, opts = {}) {
26
+ const body = this._buildBody(prompt, opts, false);
27
+ const res = await this._fetch(body);
28
+ if (!res.ok) {
29
+ const text = await res.text().catch(() => '');
30
+ throw new SSMError('BRIDGE_REQUEST_FAILED', `Anthropic API returned ${res.status}: ${text}`);
31
+ }
32
+ const json = await res.json();
33
+ const content = json.content?.[0]?.text;
34
+ if (typeof content !== 'string') {
35
+ throw new SSMError('BRIDGE_RESPONSE_INVALID', 'Unexpected Anthropic response shape.');
36
+ }
37
+ return content;
38
+ }
39
+ async *stream(prompt, opts = {}) {
40
+ const body = this._buildBody(prompt, opts, true);
41
+ const res = await this._fetch(body);
42
+ if (!res.ok) {
43
+ const text = await res.text().catch(() => '');
44
+ throw new SSMError('BRIDGE_REQUEST_FAILED', `Anthropic streaming API returned ${res.status}: ${text}`);
45
+ }
46
+ if (!res.body) {
47
+ throw new SSMError('BRIDGE_RESPONSE_INVALID', 'Anthropic streaming response has no body.');
48
+ }
49
+ yield* parseAnthropicStream(res.body);
50
+ }
51
+ _buildBody(prompt, opts, stream) {
52
+ const sys = opts.systemPrompt ?? this._systemPrompt;
53
+ const body = {
54
+ model: opts.model ?? this._model,
55
+ max_tokens: opts.maxTokens ?? this._maxTokens,
56
+ messages: [{ role: 'user', content: prompt }],
57
+ };
58
+ if (sys) {
59
+ // Caching is a prefix match: render the stable system prompt as a
60
+ // single cache-marked content block so reads on subsequent turns are
61
+ // billed at ~10% of input price. The volatile user message is sent
62
+ // unmarked after it, so it never enters the cached prefix.
63
+ body['system'] = this._cacheSystem
64
+ ? [{ type: 'text', text: sys, cache_control: { type: 'ephemeral' } }]
65
+ : sys;
66
+ }
67
+ if (stream)
68
+ body['stream'] = true;
69
+ return JSON.stringify(body);
70
+ }
71
+ _fetch(body) {
72
+ return fetch(API_URL, {
73
+ method: 'POST',
74
+ headers: {
75
+ 'Content-Type': 'application/json',
76
+ 'x-api-key': this._apiKey,
77
+ 'anthropic-version': this._apiVersion,
78
+ },
79
+ body,
80
+ });
81
+ }
82
+ }
83
+ // ── SSE parser (Anthropic event format) ──────────────────────────────────────
84
+ async function* parseAnthropicStream(body) {
85
+ const reader = body.getReader();
86
+ const decoder = new TextDecoder();
87
+ let buffer = '';
88
+ try {
89
+ while (true) {
90
+ const { done, value } = await reader.read();
91
+ if (done)
92
+ break;
93
+ buffer += decoder.decode(value, { stream: true });
94
+ const lines = buffer.split('\n');
95
+ buffer = lines.pop(); // split() always yields ≥1 element → never undefined
96
+ for (const line of lines) {
97
+ const trimmed = line.trim();
98
+ if (!trimmed.startsWith('data: '))
99
+ continue;
100
+ const data = trimmed.slice(6);
101
+ try {
102
+ const event = JSON.parse(data);
103
+ // content_block_delta events carry the streamed text
104
+ if (event['type'] === 'content_block_delta') {
105
+ const text = event.delta?.text;
106
+ if (typeof text === 'string' && text.length > 0)
107
+ yield text;
108
+ }
109
+ }
110
+ catch {
111
+ // Skip malformed SSE lines
112
+ }
113
+ }
114
+ }
115
+ }
116
+ finally {
117
+ reader.releaseLock();
118
+ }
119
+ }
120
+ //# sourceMappingURL=AnthropicBridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnthropicBridge.js","sourceRoot":"","sources":["../../src/bridges/AnthropicBridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * CachingBridge – a read-through caching decorator for any TransformerBridge.
3
+ *
4
+ * Wraps an inner bridge and memoises `generate()` keyed on the full request
5
+ * shape (model, system, prompt, sampling). Identical completions are served
6
+ * from memory instead of re-billing the provider — the single most effective
7
+ * lever for cutting LLM spend on repeated prompts (distillation passes, retries,
8
+ * fan-out over duplicate inputs).
9
+ *
10
+ * Composes with every bridge, so the caching policy lives in one place rather
11
+ * than being reimplemented per provider:
12
+ *
13
+ * const bridge = new CachingBridge(new AnthropicBridge({ apiKey }));
14
+ *
15
+ * Streaming is delegated straight through and never cached — a token stream is
16
+ * consumed once and caching it would defeat its purpose.
17
+ */
18
+ import type { TransformerBridge, BridgeGenerateOptions } from './TransformerBridge.js';
19
+ import { ResponseCache, type ResponseCacheOptions } from './ResponseCache.js';
20
+ export interface CachingBridgeOptions extends ResponseCacheOptions {
21
+ /**
22
+ * Provide a shared ResponseCache instance instead of letting the bridge
23
+ * create its own. Use this to share one cache across multiple bridges, or
24
+ * to inspect/clear the cache from outside.
25
+ */
26
+ cache?: ResponseCache;
27
+ }
28
+ export declare class CachingBridge implements TransformerBridge {
29
+ private readonly _inner;
30
+ private readonly _cache;
31
+ constructor(inner: TransformerBridge, opts?: CachingBridgeOptions);
32
+ /** Mirrors the wrapped bridge so callers can still gate on streaming support. */
33
+ get supportsStreaming(): boolean;
34
+ /** The underlying cache — exposed for stats inspection and manual eviction. */
35
+ get cache(): ResponseCache;
36
+ generate(prompt: string, opts?: BridgeGenerateOptions): Promise<string>;
37
+ /**
38
+ * Streaming is delegated to the inner bridge unchanged and is never cached.
39
+ * Present only when the inner bridge supports it, so `supportsStreaming`
40
+ * stays an accurate gate.
41
+ */
42
+ stream(prompt: string, opts?: BridgeGenerateOptions): AsyncIterable<string>;
43
+ }
44
+ //# sourceMappingURL=CachingBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CachingBridge.d.ts","sourceRoot":"","sources":["../../src/bridges/CachingBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EAAE,aAAa,EAAiB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE7F,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAC9D;;;;OAIG;IACH,KAAK,CAAC,EAAG,aAAa,CAAC;CAC1B;AAED,qBAAa,aAAc,YAAW,iBAAiB;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;gBAE5B,KAAK,EAAE,iBAAiB,EAAE,IAAI,GAAE,oBAAyB;IAKrE,iFAAiF;IACjF,IAAI,iBAAiB,IAAI,OAAO,CAE/B;IAED,+EAA+E;IAC/E,IAAI,KAAK,IAAI,aAAa,CAEzB;IAEK,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBjF;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAAC,MAAM,CAAC;CAM9E"}