cogmemory 0.0.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +139 -0
- package/dist/arbiter.cjs +22 -0
- package/dist/arbiter.cjs.map +1 -0
- package/dist/arbiter.d.ts +72 -0
- package/dist/arbiter.js +85 -0
- package/dist/arbiter.js.map +1 -0
- package/dist/cognitive-memory.cjs +15 -0
- package/dist/cognitive-memory.cjs.map +1 -0
- package/dist/cognitive-memory.js +1068 -0
- package/dist/cognitive-memory.js.map +1 -0
- package/dist/index.d.ts +1086 -0
- package/package.json +83 -0
- package/src/arbiter.ts +14 -0
- package/src/client.ts +105 -0
- package/src/cogmem.ts +74 -0
- package/src/cognitive/arbiter.ts +105 -0
- package/src/cognitive/fast-gate.ts +63 -0
- package/src/cognitive/index.ts +64 -0
- package/src/cognitive/memory.ts +878 -0
- package/src/cognitive/relevance.ts +199 -0
- package/src/cognitive/rules.ts +127 -0
- package/src/cognitive/types.ts +232 -0
- package/src/errors.ts +85 -0
- package/src/helpers/turn.ts +172 -0
- package/src/index.ts +134 -0
- package/src/resources/context.ts +17 -0
- package/src/resources/memories.ts +60 -0
- package/src/resources/recall.ts +17 -0
- package/src/resources/self-model.ts +21 -0
- package/src/resources/stats.ts +27 -0
- package/src/resources/tensions.ts +36 -0
- package/src/resources/turns.ts +16 -0
- package/src/types.ts +246 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1086 @@
|
|
|
1
|
+
import { $Fetch } from 'ofetch';
|
|
2
|
+
|
|
3
|
+
export declare interface AddTensionRequest {
|
|
4
|
+
claimA: string;
|
|
5
|
+
claimB: string;
|
|
6
|
+
impact?: Impact;
|
|
7
|
+
actionableQuestion: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export declare interface ArbiterEvaluationResult {
|
|
11
|
+
promotions: Array<{
|
|
12
|
+
memoryId: string;
|
|
13
|
+
targetTier: "L1";
|
|
14
|
+
signalType: "anticipatory" | "tension" | "proprioceptive" | "recency";
|
|
15
|
+
urgency: number;
|
|
16
|
+
}>;
|
|
17
|
+
demotions: Array<{
|
|
18
|
+
memoryId: string;
|
|
19
|
+
targetTier: "L2";
|
|
20
|
+
reason: string;
|
|
21
|
+
}>;
|
|
22
|
+
pins: Array<{
|
|
23
|
+
memoryId: string;
|
|
24
|
+
targetTier: "L0";
|
|
25
|
+
reason: string;
|
|
26
|
+
}>;
|
|
27
|
+
detectedTensions: Array<{
|
|
28
|
+
claimA: string;
|
|
29
|
+
claimB: string;
|
|
30
|
+
impact: TensionImpact;
|
|
31
|
+
actionableQuestion: string;
|
|
32
|
+
}>;
|
|
33
|
+
trajectoryPrediction?: TrajectoryPrediction;
|
|
34
|
+
selfModelUpdate?: {
|
|
35
|
+
domain: string;
|
|
36
|
+
success?: boolean;
|
|
37
|
+
failurePatternObserved?: string;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export declare type ArbiterFn = (params: {
|
|
42
|
+
turnText: string;
|
|
43
|
+
assistantReply: string;
|
|
44
|
+
l0Prompt: string;
|
|
45
|
+
l1Summaries: Array<{
|
|
46
|
+
id: string;
|
|
47
|
+
bookmark: string;
|
|
48
|
+
domains: string[];
|
|
49
|
+
}>;
|
|
50
|
+
candidates: Array<{
|
|
51
|
+
id: string;
|
|
52
|
+
bookmark: string;
|
|
53
|
+
domains: string[];
|
|
54
|
+
hasTension?: boolean;
|
|
55
|
+
}>;
|
|
56
|
+
}) => Promise<ArbiterEvaluationResult>;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Floor for *candidate* recall, not a similarity decision.
|
|
60
|
+
*
|
|
61
|
+
* Deliberately low. This only decides who gets adjudicated; a tight gate misses
|
|
62
|
+
* exactly the paraphrases worth merging.
|
|
63
|
+
*/
|
|
64
|
+
export declare const CANDIDATE_FLOOR = 0.3;
|
|
65
|
+
|
|
66
|
+
export declare interface Claim {
|
|
67
|
+
source: string;
|
|
68
|
+
statement: string;
|
|
69
|
+
timestamp: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The client.
|
|
74
|
+
*
|
|
75
|
+
* Named `Cogmem` rather than `CognitiveMemory` because that name belongs to the
|
|
76
|
+
* in-process engine, and has for as long as this layer existed. Two exports
|
|
77
|
+
* cannot share a name, and the engine's is the older public API: quietly
|
|
78
|
+
* redefining it to mean an HTTP client would break every consumer of it.
|
|
79
|
+
*
|
|
80
|
+
* Resource classes rather than a flat list of functions, because
|
|
81
|
+
* `memory.memories.` in an editor shows every operation on memories and nothing
|
|
82
|
+
* else. The methods stay one-to-one with endpoints, so the class never becomes a
|
|
83
|
+
* second, divergent copy of the service.
|
|
84
|
+
*
|
|
85
|
+
* `readonly` on the resources is not decoration: it stops a caller reassigning
|
|
86
|
+
* `memory.memories` and wondering why the other half of the client stopped
|
|
87
|
+
* seeing the change.
|
|
88
|
+
*/
|
|
89
|
+
export declare class Cogmem {
|
|
90
|
+
private readonly client;
|
|
91
|
+
readonly baseUrl: string;
|
|
92
|
+
readonly memories: MemoriesResource;
|
|
93
|
+
readonly context: ContextResource;
|
|
94
|
+
readonly recall: RecallResource;
|
|
95
|
+
readonly turns: TurnsResource;
|
|
96
|
+
readonly tensions: TensionsResource;
|
|
97
|
+
readonly selfModel: SelfModelResource;
|
|
98
|
+
readonly stats: StatsResource;
|
|
99
|
+
constructor(config: CognitiveMemoryConfig);
|
|
100
|
+
/**
|
|
101
|
+
* Liveness and limits, without spending a request on the configured key.
|
|
102
|
+
*
|
|
103
|
+
* Useful in a readiness probe: if `extractor` is `rules-only` the service is up
|
|
104
|
+
* but is not doing model-backed extraction, and `problems` is non-empty when a
|
|
105
|
+
* setting is present but unusable.
|
|
106
|
+
*/
|
|
107
|
+
health(): Promise<Health>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export declare class CognitiveMemory {
|
|
111
|
+
private activeTensions;
|
|
112
|
+
private selfModel;
|
|
113
|
+
private activeTaskTrace;
|
|
114
|
+
private l1HotCache;
|
|
115
|
+
private l2WarmStore;
|
|
116
|
+
private l3ColdArchive;
|
|
117
|
+
private maxL0Tokens;
|
|
118
|
+
private maxL1Tokens;
|
|
119
|
+
/** Ceiling on everything injected into one prompt, index and bodies together. */
|
|
120
|
+
private maxTotalTokens;
|
|
121
|
+
private arbiter;
|
|
122
|
+
private autoExtractMemories;
|
|
123
|
+
/** Model-backed turn extractor; the regex fallback runs when this is absent. */
|
|
124
|
+
private reconcile?;
|
|
125
|
+
private extract?;
|
|
126
|
+
private onPersist?;
|
|
127
|
+
private stats;
|
|
128
|
+
constructor(options?: CognitiveMemoryOptions);
|
|
129
|
+
/**
|
|
130
|
+
* Sub-1ms synchronous call to produce the prompt context block.
|
|
131
|
+
* Concatenates L0 (active tensions + self-model) and pre-staged L1.
|
|
132
|
+
* Adds zero latency to TTFT.
|
|
133
|
+
*/
|
|
134
|
+
/**
|
|
135
|
+
* Decide what goes into this turn's prompt, and record why.
|
|
136
|
+
*
|
|
137
|
+
* Follows the index/body split that Claude Code's `MEMORY.md` and Letta's
|
|
138
|
+
* progressive disclosure both converged on: a short index of every memory is
|
|
139
|
+
* always present, and a body is only spent where a deterministic signal earned
|
|
140
|
+
* it. Always injecting bodies costs an order of magnitude more tokens and, per
|
|
141
|
+
* Chroma's context-rot work, injects distractors by construction.
|
|
142
|
+
*
|
|
143
|
+
* @param forceFull memory ids whose body should be included regardless of tier.
|
|
144
|
+
*/
|
|
145
|
+
planInjection(options?: {
|
|
146
|
+
userMessage?: string;
|
|
147
|
+
forceFull?: Iterable<string>;
|
|
148
|
+
}): MemoryInjectionReport;
|
|
149
|
+
/** Prompt text only. Prefer `planInjection` when you want to log what went in. */
|
|
150
|
+
getPromptContext(currentUserMessage?: string): string;
|
|
151
|
+
/**
|
|
152
|
+
* Search every tier for memories relevant to `query`.
|
|
153
|
+
*
|
|
154
|
+
* This is the on-demand path, exposed to the agent as a tool. Pre-staging into
|
|
155
|
+
* the prompt is a best-effort optimisation; a model that does not read the
|
|
156
|
+
* block, or whose question shares no words with it, can still ask. Ranking is
|
|
157
|
+
* deterministic — no model involved — so recall does not depend on model
|
|
158
|
+
* quality.
|
|
159
|
+
*/
|
|
160
|
+
search(query: string, limit?: number): Array<{
|
|
161
|
+
item: MemoryItem;
|
|
162
|
+
score: number;
|
|
163
|
+
}>;
|
|
164
|
+
/**
|
|
165
|
+
* Post-turn asynchronous execution.
|
|
166
|
+
* Fired when the agent finishes streaming its response to the user.
|
|
167
|
+
* Evaluates turn, manages L1 cache, detects tensions, updates self-model.
|
|
168
|
+
*/
|
|
169
|
+
postTurnAsync(params: {
|
|
170
|
+
userMessage: string;
|
|
171
|
+
assistantResponse: string;
|
|
172
|
+
detectedDomains?: string[];
|
|
173
|
+
}): Promise<void>;
|
|
174
|
+
/**
|
|
175
|
+
* Fold extracted memories and tensions in, skipping anything already known.
|
|
176
|
+
*
|
|
177
|
+
* Extracted items land in L2 rather than L1: they are candidates, and the
|
|
178
|
+
* arbiter decides what is worth pre-staging. That is what gives the tiering
|
|
179
|
+
* something to actually do — previously nothing ever wrote to L2, so every
|
|
180
|
+
* arbiter run evaluated an empty candidate set.
|
|
181
|
+
*/
|
|
182
|
+
private applyExtraction;
|
|
183
|
+
/** Drop an entry by its exact content. */
|
|
184
|
+
private removeByContent;
|
|
185
|
+
/** Rewrite one entry's text in place, matched on its old value. */
|
|
186
|
+
private replaceByContent;
|
|
187
|
+
/** Replace an entry's content, keeping its identity and tags. */
|
|
188
|
+
private enrich;
|
|
189
|
+
/**
|
|
190
|
+
* Fold a duplicate into its survivor, refusing rewrites that drop anything.
|
|
191
|
+
*
|
|
192
|
+
* `merge` returns the model's idea of the fuller statement, and overwriting
|
|
193
|
+
* with it deletes whatever the model happened to leave out. The under-merge
|
|
194
|
+
* bias covers merging the *wrong* pair, but nothing covered a lossy rewrite
|
|
195
|
+
* of the right pair, so containment is checked first.
|
|
196
|
+
*
|
|
197
|
+
* @returns false when the rewrite would lose information, in which case the
|
|
198
|
+
* caller keeps both entries.
|
|
199
|
+
*/
|
|
200
|
+
private mergeInto;
|
|
201
|
+
/** Retire the entries a replacement supersedes, keeping them out of retrieval. */
|
|
202
|
+
private supersede;
|
|
203
|
+
/**
|
|
204
|
+
* Existing memories worth adjudicating a candidate against.
|
|
205
|
+
*
|
|
206
|
+
* Cheap and deliberately over-inclusive. An identical string short-circuits
|
|
207
|
+
* because it is never worth a model call; anything else above the recall floor
|
|
208
|
+
* is offered to the adjudicator, which decides.
|
|
209
|
+
*/
|
|
210
|
+
private recallSimilar;
|
|
211
|
+
/**
|
|
212
|
+
* Keep the pinned tiers within budget.
|
|
213
|
+
*
|
|
214
|
+
* `maxL0Tokens`/`maxL1Tokens` were stored but never read, so L1 grew for the
|
|
215
|
+
* lifetime of the process. Evict least-recently-accessed first, and demote to
|
|
216
|
+
* L2 rather than dropping, so nothing is lost.
|
|
217
|
+
*/
|
|
218
|
+
private enforceBudgets;
|
|
219
|
+
/**
|
|
220
|
+
* Add a known tension manually or from an external source.
|
|
221
|
+
*/
|
|
222
|
+
addTension(tension: KnowledgeTension): void;
|
|
223
|
+
/**
|
|
224
|
+
* Mark a tension resolved with an optional reusable pattern.
|
|
225
|
+
*/
|
|
226
|
+
resolveTension(id: string, resolution: {
|
|
227
|
+
resolvedBy: string;
|
|
228
|
+
pattern: string;
|
|
229
|
+
}): boolean;
|
|
230
|
+
/**
|
|
231
|
+
* Add a memory directly to L2 warm storage or promote to L1.
|
|
232
|
+
*/
|
|
233
|
+
addMemory(item: MemoryItem, targetTier?: CognitiveMemoryTier): void;
|
|
234
|
+
/**
|
|
235
|
+
* Drop one memory by id, from whichever tier holds it.
|
|
236
|
+
*
|
|
237
|
+
* The counterpart to `addMemory`, and the only way to retire a fact that has
|
|
238
|
+
* turned out to be wrong. One map is not enough to look in: a promotion or a
|
|
239
|
+
* demotion moves an id between them, so an id that is absent from the hot
|
|
240
|
+
* cache may still be in the warm store or the archive. Short-circuiting on the
|
|
241
|
+
* first hit is therefore safe — an id lives in exactly one of the three.
|
|
242
|
+
*/
|
|
243
|
+
removeMemory(id: string): boolean;
|
|
244
|
+
/**
|
|
245
|
+
* Update the proprioceptive capability record for a domain.
|
|
246
|
+
*/
|
|
247
|
+
recordDomainOutcome(domain: string, success: boolean, failurePattern?: string): void;
|
|
248
|
+
getSnapshot(): CognitiveMemoryStateSnapshot;
|
|
249
|
+
loadSnapshot(snapshot: CognitiveMemoryStateSnapshot): void;
|
|
250
|
+
private applyArbiterDecision;
|
|
251
|
+
/**
|
|
252
|
+
* Fast default heuristic arbiter when an LLM arbiter model is not supplied.
|
|
253
|
+
*/
|
|
254
|
+
private runHeuristicArbiter;
|
|
255
|
+
private autoExtractTurnMemory;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export declare interface CognitiveMemoryConfig {
|
|
259
|
+
apiKey: string;
|
|
260
|
+
/** Defaults to the current origin in a browser, or localhost otherwise. */
|
|
261
|
+
baseUrl?: string;
|
|
262
|
+
/** Per-request timeout in ms. */
|
|
263
|
+
timeout?: number;
|
|
264
|
+
/** Retries for transient failures. 0 disables. */
|
|
265
|
+
retry?: number;
|
|
266
|
+
/**
|
|
267
|
+
* Log every request and response.
|
|
268
|
+
*
|
|
269
|
+
* On by default for anyone who has been burned by a wrong base URL, which is
|
|
270
|
+
* everyone exactly once.
|
|
271
|
+
*/
|
|
272
|
+
debug?: boolean;
|
|
273
|
+
headers?: Record<string, string>;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* One error class for every failure the service can produce.
|
|
278
|
+
*
|
|
279
|
+
* The service already returns a structured envelope — a tag, a message, the
|
|
280
|
+
* scope that was missing, the fields that failed validation — so the SDK's job is
|
|
281
|
+
* to hand that over as a typed object instead of making callers dig through
|
|
282
|
+
* `error.response.data`.
|
|
283
|
+
*
|
|
284
|
+
* The predicate methods exist so callers ask semantic questions. `status === 403`
|
|
285
|
+
* scatters a magic number through every integration and means something slightly
|
|
286
|
+
* different at each one; `isScopeError()` means the same thing everywhere.
|
|
287
|
+
*/
|
|
288
|
+
export declare class CognitiveMemoryError extends Error {
|
|
289
|
+
/**
|
|
290
|
+
* Set as a real value, because a minifier renames the class and that silently
|
|
291
|
+
* changes what monitoring groups on. `error.name` is correct either way — the
|
|
292
|
+
* constructor assigns it — but `SomeError.name` and `error.constructor.name`
|
|
293
|
+
* are how a reporter identifies a class, and a minified `"h"` breaks that.
|
|
294
|
+
*/
|
|
295
|
+
static readonly name = "CognitiveMemoryError";
|
|
296
|
+
/** The service's own tag: `Unauthorized`, `Forbidden`, `InvalidRequest`, … */
|
|
297
|
+
readonly code: string;
|
|
298
|
+
readonly status: number;
|
|
299
|
+
/** Present on a 403: the scope the key would have needed. */
|
|
300
|
+
readonly requiredScope?: string;
|
|
301
|
+
/** Present on a 400: which field, and why. */
|
|
302
|
+
readonly issues?: string[];
|
|
303
|
+
readonly body?: CognitiveMemoryErrorBody;
|
|
304
|
+
constructor(message: string, init: {
|
|
305
|
+
status: number;
|
|
306
|
+
code: string;
|
|
307
|
+
body?: CognitiveMemoryErrorBody;
|
|
308
|
+
requiredScope?: string;
|
|
309
|
+
issues?: string[];
|
|
310
|
+
});
|
|
311
|
+
/** The key is missing, malformed, expired or revoked. */
|
|
312
|
+
isAuthError(): boolean;
|
|
313
|
+
/** The key is valid but lacks a scope. `requiredScope` says which. */
|
|
314
|
+
isScopeError(): boolean;
|
|
315
|
+
/** The request body did not match the schema. `issues` says where. */
|
|
316
|
+
isValidationError(): boolean;
|
|
317
|
+
/** Nothing exists at that id — or it belongs to another organisation. */
|
|
318
|
+
isNotFoundError(): boolean;
|
|
319
|
+
isRateLimitError(): boolean;
|
|
320
|
+
/** A dependency of ours failed, not the request. Safe to retry. */
|
|
321
|
+
isServerError(): boolean;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** The error envelope every non-2xx response carries. */
|
|
325
|
+
export declare interface CognitiveMemoryErrorBody {
|
|
326
|
+
error: string;
|
|
327
|
+
message: string;
|
|
328
|
+
requiredScope?: string;
|
|
329
|
+
resource?: string;
|
|
330
|
+
id?: string;
|
|
331
|
+
issues?: string[];
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export declare interface CognitiveMemoryOptions {
|
|
335
|
+
/** Maximum token budget for L0 (default: 2000) */
|
|
336
|
+
maxL0Tokens?: number;
|
|
337
|
+
/** Maximum token budget for L1 hot cache (default: 8000) */
|
|
338
|
+
maxL1Tokens?: number;
|
|
339
|
+
/** Ceiling on everything injected into a single prompt (index + bodies). Default 2000. */
|
|
340
|
+
maxTotalTokens?: number;
|
|
341
|
+
/** Custom Arbiter evaluator function (e.g. powered by Jev, Gemini Flash, or local model) */
|
|
342
|
+
arbiter?: ArbiterFn;
|
|
343
|
+
/** Initial self-model */
|
|
344
|
+
initialSelfModel?: Partial<ProprioceptiveSelfModel>;
|
|
345
|
+
/** Auto-extract candidate items from completed turns (default: true) */
|
|
346
|
+
autoExtractMemories?: boolean;
|
|
347
|
+
/**
|
|
348
|
+
* Adjudicate a candidate memory against ones that already exist.
|
|
349
|
+
*
|
|
350
|
+
* Lexical overlap cannot make this call: it peaks on identical strings and
|
|
351
|
+
* bottoms out on the paraphrases that actually add information. Every mature
|
|
352
|
+
* memory system therefore recalls candidates cheaply and then asks a model,
|
|
353
|
+
* explicitly allowing "no match". `remember` is the low-bar candidate
|
|
354
|
+
* recall; `decide` is the precision step.
|
|
355
|
+
*/
|
|
356
|
+
reconcile?: (input: {
|
|
357
|
+
/** Every candidate from this turn that resembles something we hold. */
|
|
358
|
+
items: Array<{
|
|
359
|
+
candidate: string;
|
|
360
|
+
remember: string[];
|
|
361
|
+
}>;
|
|
362
|
+
}) => Promise<MemoryReconciliation[]>;
|
|
363
|
+
/**
|
|
364
|
+
* Model-backed turn extractor. Preferred over the built-in regex, which only
|
|
365
|
+
* recognises "always/never/make sure to/remember to" and therefore never
|
|
366
|
+
* learned ordinary project facts. Return an empty array to learn nothing.
|
|
367
|
+
*/
|
|
368
|
+
extract?: (turn: {
|
|
369
|
+
userMessage: string;
|
|
370
|
+
assistantResponse: string;
|
|
371
|
+
}) => Promise<{
|
|
372
|
+
memories: Array<{
|
|
373
|
+
content: string;
|
|
374
|
+
domains?: string[];
|
|
375
|
+
}>;
|
|
376
|
+
tensions?: Array<{
|
|
377
|
+
claimA: string;
|
|
378
|
+
claimB: string;
|
|
379
|
+
impact: "low" | "medium" | "critical";
|
|
380
|
+
actionableQuestion: string;
|
|
381
|
+
}>;
|
|
382
|
+
}>;
|
|
383
|
+
/** Persistence callback to save L2/L3 state */
|
|
384
|
+
onPersist?: (state: CognitiveMemoryStateSnapshot) => Promise<void> | void;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export declare interface CognitiveMemoryStateSnapshot {
|
|
388
|
+
l0: {
|
|
389
|
+
tensions: KnowledgeTension[];
|
|
390
|
+
selfModel: ProprioceptiveSelfModel;
|
|
391
|
+
activeTaskTrace: string;
|
|
392
|
+
};
|
|
393
|
+
l1: MemoryItem[];
|
|
394
|
+
l2: MemoryItem[];
|
|
395
|
+
l3: MemoryItem[];
|
|
396
|
+
stats: {
|
|
397
|
+
totalTurnsProcessed: number;
|
|
398
|
+
predictionsHit: number;
|
|
399
|
+
predictionsTotal: number;
|
|
400
|
+
tensionsDetected: number;
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Cognitive Memory types and contracts for not-another-harness.
|
|
406
|
+
*/
|
|
407
|
+
export declare type CognitiveMemoryTier = "L0" | "L1" | "L2" | "L3";
|
|
408
|
+
|
|
409
|
+
/** Two results this similar are the same memory, restated. */
|
|
410
|
+
export declare const COLLAPSE_THRESHOLD = 0.8;
|
|
411
|
+
|
|
412
|
+
export declare interface ContextEntry {
|
|
413
|
+
id: string;
|
|
414
|
+
tier: MemoryTier;
|
|
415
|
+
reason: InclusionReason;
|
|
416
|
+
gist: string;
|
|
417
|
+
/** Absent for `index` entries: a line is all those cost. */
|
|
418
|
+
body?: string;
|
|
419
|
+
tokens: number;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export declare interface ContextReport {
|
|
423
|
+
/** Prepend this to the system prompt. Empty when there is nothing to say. */
|
|
424
|
+
text: string;
|
|
425
|
+
entries: ContextEntry[];
|
|
426
|
+
totalTokens: number;
|
|
427
|
+
/** True when the token budget forced something out. */
|
|
428
|
+
truncated: boolean;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export declare interface ContextRequest {
|
|
432
|
+
/** The message about to be answered. Drives the triggers. */
|
|
433
|
+
userMessage?: string;
|
|
434
|
+
/** Ids whose body to include regardless of tier. */
|
|
435
|
+
forceFull?: string[];
|
|
436
|
+
maxTokens?: number;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* The prompt block.
|
|
441
|
+
*
|
|
442
|
+
* One call per turn, and the reason the service exists: a one-line index of
|
|
443
|
+
* everything remembered, plus full bodies only where a named identifier, an
|
|
444
|
+
* unresolved contradiction, or a weak domain earned them.
|
|
445
|
+
*/
|
|
446
|
+
export declare class ContextResource {
|
|
447
|
+
private readonly client;
|
|
448
|
+
constructor(client: HttpClient);
|
|
449
|
+
build(request?: ContextRequest): Promise<ContextReport>;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Both construction styles, deliberately.
|
|
454
|
+
*
|
|
455
|
+
* Some people prefer `new Cogmem(...)` and some prefer `createClient(...)`; there
|
|
456
|
+
* is no reason to make anyone rename. The factory is also the easier one to mock
|
|
457
|
+
* in tests, which is the whole reason `createHttpClient` is a function.
|
|
458
|
+
*/
|
|
459
|
+
export declare function createClient(config: CognitiveMemoryConfig): Cogmem;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Configuration, as a factory rather than a constructor.
|
|
463
|
+
*
|
|
464
|
+
* A constructor with fifteen options is a dumping ground: configuration and
|
|
465
|
+
* instantiation get tangled, tests have to construct a whole class to check one
|
|
466
|
+
* header, and "the client with a different timeout" becomes a subclass. A factory
|
|
467
|
+
* is a plain function — no `new`, no `this`, composable, trivially mockable.
|
|
468
|
+
*
|
|
469
|
+
* The real work happens in the interceptors. Authentication, error translation
|
|
470
|
+
* and debug logging are configured once here instead of being repeated in each
|
|
471
|
+
* of the twenty-odd methods below, which is the difference between changing how
|
|
472
|
+
* auth works in one place and in twenty.
|
|
473
|
+
*/
|
|
474
|
+
export declare function createHttpClient(config: CognitiveMemoryConfig): $Fetch;
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Deterministic fact extraction.
|
|
478
|
+
*
|
|
479
|
+
* A model extractor is good at judgement but it is still a model: it can
|
|
480
|
+
* refuse, hedge, or return nothing, and a fact the user plainly stated then
|
|
481
|
+
* never gets learned. Everything stated unambiguously is captured here with
|
|
482
|
+
* plain pattern matching, and the model is layered on top for the subtler cases.
|
|
483
|
+
*
|
|
484
|
+
* Only high-confidence shapes are matched. Being wrong in this direction writes
|
|
485
|
+
* a useless memory; being silent loses a real one, which is the worse failure.
|
|
486
|
+
*/
|
|
487
|
+
export declare interface DeterministicMemory {
|
|
488
|
+
readonly content: string;
|
|
489
|
+
readonly domains: Array<string>;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Tokens that carry a fact's identity: identifiers, numbers, codes.
|
|
494
|
+
*
|
|
495
|
+
* Function words and generic nouns are dropped because they recur in every
|
|
496
|
+
* restatement and hide real differences.
|
|
497
|
+
*/
|
|
498
|
+
export declare const distinctiveTokens: (value: string) => Set<string>;
|
|
499
|
+
|
|
500
|
+
export declare interface DomainCapability {
|
|
501
|
+
reliabilityScore: number;
|
|
502
|
+
sampleCount: number;
|
|
503
|
+
knownFailurePatterns: string[];
|
|
504
|
+
recommendedStrategies: string[];
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
declare interface DomainCapability_2 {
|
|
508
|
+
reliabilityScore: number;
|
|
509
|
+
sampleCount: number;
|
|
510
|
+
knownFailurePatterns: string[];
|
|
511
|
+
recommendedStrategies: string[];
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export declare interface DomainOutcomeRequest {
|
|
515
|
+
domain: string;
|
|
516
|
+
success: boolean;
|
|
517
|
+
failurePattern?: string;
|
|
518
|
+
strategy?: string;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/** Approximate token cost of a string. */
|
|
522
|
+
export declare const estimateTokens: (value: string) => number;
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Extract statements the user made that are worth remembering, without a model.
|
|
526
|
+
*/
|
|
527
|
+
export declare const extractDeterministic: (userMessage: string) => Array<DeterministicMemory>;
|
|
528
|
+
|
|
529
|
+
export declare const extractDomains: (text: string) => string[];
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Identifiers worth matching a memory against: URLs, paths, hostnames,
|
|
533
|
+
* SCREAMING_SNAKE, camelCase, long kebab-case and hex-ish codes.
|
|
534
|
+
*
|
|
535
|
+
* The same idea as Aider's `mentioned_idents`: a user naming a concrete thing
|
|
536
|
+
* is a much stronger signal than the words around it. This is what turns a
|
|
537
|
+
* recall into a full-body injection without asking a model.
|
|
538
|
+
*/
|
|
539
|
+
export declare const extractIdentifiers: (text: string) => string[];
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Fast Heuristic Gate
|
|
543
|
+
*
|
|
544
|
+
* Synchronous, sub-5ms gate running on the critical path before model invocation.
|
|
545
|
+
* Detects explicit user corrections/contradictions and significant domain pivots
|
|
546
|
+
* without triggering an LLM call.
|
|
547
|
+
*/
|
|
548
|
+
export declare interface FastGateResult {
|
|
549
|
+
action: "proceed" | "inject_caution";
|
|
550
|
+
cautionNote?: string;
|
|
551
|
+
detectedDomains?: string[];
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Liveness, and this deployment's limits and extractor mode.
|
|
556
|
+
*
|
|
557
|
+
* Takes an explicit base URL because it is the one call that must work with no
|
|
558
|
+
* key at all — including from a health check that has no credentials.
|
|
559
|
+
*/
|
|
560
|
+
export declare const fetchHealth: (baseUrl: string) => Promise<Health>;
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* The index line: short, scannable, no body.
|
|
564
|
+
*
|
|
565
|
+
* Falling back to the first sentence keeps an index line readable when a memory
|
|
566
|
+
* arrives from the API without a gist.
|
|
567
|
+
*/
|
|
568
|
+
export declare const gistOf: (item: {
|
|
569
|
+
readonly content: string;
|
|
570
|
+
readonly gist?: string | undefined;
|
|
571
|
+
}) => string;
|
|
572
|
+
|
|
573
|
+
export declare interface Health {
|
|
574
|
+
ok: boolean;
|
|
575
|
+
service: string;
|
|
576
|
+
version: string;
|
|
577
|
+
/** `rules-only` means no model key is configured; learning is still on. */
|
|
578
|
+
extractor: "rules-only" | "rules+model";
|
|
579
|
+
limits: {
|
|
580
|
+
maxTotalTokens: number;
|
|
581
|
+
maxIndexItems: number;
|
|
582
|
+
defaultRecallLimit: number;
|
|
583
|
+
};
|
|
584
|
+
/** Non-empty only when a setting was present but unusable. */
|
|
585
|
+
problems: string[];
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
export declare type HttpClient = ReturnType<typeof createHttpClient>;
|
|
589
|
+
|
|
590
|
+
export declare type Impact = "low" | "medium" | "critical";
|
|
591
|
+
|
|
592
|
+
/** Why a memory body was included. Each reason costs differently. */
|
|
593
|
+
export declare type InclusionReason = "index" | "trigger" | "tension" | "guardrail";
|
|
594
|
+
|
|
595
|
+
export declare const isInteractionScoped: (content: string) => boolean;
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Whether rewriting `original` as `replacement` would drop information.
|
|
599
|
+
*
|
|
600
|
+
* Distinctive tokens carry a fact's identity, so a replacement missing one has
|
|
601
|
+
* deleted something — usually the qualifier that made the two statements differ
|
|
602
|
+
* at all ("never production", a build id, a port). Trailing plurals are folded
|
|
603
|
+
* so "deploys" merging into "deploy" is not read as a deletion.
|
|
604
|
+
*
|
|
605
|
+
* Biased towards reporting a loss: a false positive costs a duplicate entry,
|
|
606
|
+
* which is recoverable, while a false negative deletes a fact for good.
|
|
607
|
+
*/
|
|
608
|
+
export declare const isLossyRewrite: (original: string, replacement: string) => boolean;
|
|
609
|
+
|
|
610
|
+
export declare interface KnowledgeTension {
|
|
611
|
+
id: string;
|
|
612
|
+
status: TensionStatus_2;
|
|
613
|
+
claimA: {
|
|
614
|
+
source: string;
|
|
615
|
+
statement: string;
|
|
616
|
+
timestamp: number;
|
|
617
|
+
};
|
|
618
|
+
claimB: {
|
|
619
|
+
source: string;
|
|
620
|
+
statement: string;
|
|
621
|
+
timestamp: number;
|
|
622
|
+
};
|
|
623
|
+
impact: TensionImpact;
|
|
624
|
+
taskRelevance: number;
|
|
625
|
+
actionableQuestion: string;
|
|
626
|
+
resolution?: {
|
|
627
|
+
resolvedAt: number;
|
|
628
|
+
resolvedBy: string;
|
|
629
|
+
pattern: string;
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
export declare interface LearnResult {
|
|
634
|
+
/** Newly created. */
|
|
635
|
+
stored: Memory[];
|
|
636
|
+
/** Restatements folded into what was already held, and what survived. */
|
|
637
|
+
mergedInto: Memory[];
|
|
638
|
+
counts: {
|
|
639
|
+
stored: number;
|
|
640
|
+
merged: number;
|
|
641
|
+
rejected: number;
|
|
642
|
+
tensions: number;
|
|
643
|
+
promoted: number;
|
|
644
|
+
};
|
|
645
|
+
/** Never silent: a client that sent ten and got three needs the other seven. */
|
|
646
|
+
rejected: RejectedStatement[];
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
export declare interface ListMemoriesParams {
|
|
650
|
+
limit?: number;
|
|
651
|
+
tier?: MemoryTier;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/** How many existing memories to put in front of an adjudicator. */
|
|
655
|
+
export declare const MAX_CANDIDATES = 8;
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Reading and writing what is stored.
|
|
659
|
+
*
|
|
660
|
+
* Deliberately thin: one method, one endpoint, no cleverness. The class is a
|
|
661
|
+
* namespace, so `memory.memories.` offers the whole surface in an editor, but it
|
|
662
|
+
* is not a place for business logic. The workflow that composes these calls lives
|
|
663
|
+
* in `../helpers`.
|
|
664
|
+
*/
|
|
665
|
+
export declare class MemoriesResource {
|
|
666
|
+
private readonly client;
|
|
667
|
+
constructor(client: HttpClient);
|
|
668
|
+
/**
|
|
669
|
+
* The envelope is unwrapped here rather than passed on.
|
|
670
|
+
*
|
|
671
|
+
* The service replies with `{ memories, stats }` so a dashboard can get both in
|
|
672
|
+
* one call, but an SDK caller who asked for a list wants a list. Deciding that
|
|
673
|
+
* in one place here is better than making every integration know the shape.
|
|
674
|
+
*/
|
|
675
|
+
list(params?: ListMemoriesParams): Promise<Memory[]>;
|
|
676
|
+
get(id: string): Promise<Memory>;
|
|
677
|
+
/**
|
|
678
|
+
* State facts outright.
|
|
679
|
+
*
|
|
680
|
+
* Restatements of something already held are folded in rather than stored
|
|
681
|
+
* twice, and the result says which ones were folded and into what — a write
|
|
682
|
+
* that silently did nothing is indistinguishable from a bug.
|
|
683
|
+
*/
|
|
684
|
+
create(request: RememberRequest): Promise<LearnResult>;
|
|
685
|
+
/** Move a memory between tiers. L1 is pre-staged into every context build. */
|
|
686
|
+
promote(id: string, tier: MemoryTier): Promise<Memory>;
|
|
687
|
+
remove(id: string): Promise<{
|
|
688
|
+
deleted: boolean;
|
|
689
|
+
id: string;
|
|
690
|
+
}>;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
export declare interface Memory {
|
|
694
|
+
id: string;
|
|
695
|
+
content: string;
|
|
696
|
+
gist?: string;
|
|
697
|
+
tier: MemoryTier;
|
|
698
|
+
domains: string[];
|
|
699
|
+
accessCount: number;
|
|
700
|
+
source?: MemorySource;
|
|
701
|
+
sessionId?: string;
|
|
702
|
+
/** Epoch milliseconds. */
|
|
703
|
+
createdAt: number;
|
|
704
|
+
lastAccessedAt: number;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
export declare type MemoryInclusionReason =
|
|
708
|
+
/** Shown in the always-present index as a gist only. */
|
|
709
|
+
"index"
|
|
710
|
+
/** Unseen identifier in the user's message matched this memory: body included. */
|
|
711
|
+
| "trigger"
|
|
712
|
+
/** Active knowledge tension: body included. */
|
|
713
|
+
| "tension"
|
|
714
|
+
/** Proprioceptive guardrail: body included. */
|
|
715
|
+
| "guardrail";
|
|
716
|
+
|
|
717
|
+
export declare interface MemoryInjectionEntry {
|
|
718
|
+
id: string;
|
|
719
|
+
tier: CognitiveMemoryTier;
|
|
720
|
+
reason: MemoryInclusionReason;
|
|
721
|
+
/** Index line only. */
|
|
722
|
+
gist: string;
|
|
723
|
+
/** Present only when the body was worth the tokens. */
|
|
724
|
+
body?: string;
|
|
725
|
+
/** Rough token cost of what was included. */
|
|
726
|
+
tokens: number;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/** What was put in the prompt this turn, and why. */
|
|
730
|
+
export declare interface MemoryInjectionReport {
|
|
731
|
+
text: string;
|
|
732
|
+
entries: MemoryInjectionEntry[];
|
|
733
|
+
totalTokens: number;
|
|
734
|
+
/** True when the total budget forced something out. */
|
|
735
|
+
truncated: boolean;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
export declare interface MemoryItem {
|
|
739
|
+
id: string;
|
|
740
|
+
content: string;
|
|
741
|
+
/** Dense 1-2 sentence representation for fast arbiter scanning */
|
|
742
|
+
bookmark: string;
|
|
743
|
+
/**
|
|
744
|
+
* Short label shown in the pre-staged index (Claude Code's `MEMORY.md` pattern:
|
|
745
|
+
* the index is always in context, the body is fetched on demand). Falls back to
|
|
746
|
+
* a truncation of `content` when the extractor did not supply one.
|
|
747
|
+
*/
|
|
748
|
+
gist?: string;
|
|
749
|
+
/** Dense embedding vector (empty array if embedding disabled) */
|
|
750
|
+
embedding?: number[];
|
|
751
|
+
tier: CognitiveMemoryTier;
|
|
752
|
+
metadata: MemoryMetadata;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
export declare interface MemoryMetadata {
|
|
756
|
+
domains: string[];
|
|
757
|
+
isFailurePattern?: boolean;
|
|
758
|
+
isSuccessfulStrategy?: boolean;
|
|
759
|
+
isGuardrail?: boolean;
|
|
760
|
+
sourceSessionId?: string;
|
|
761
|
+
createdAt: number;
|
|
762
|
+
lastAccessedAt: number;
|
|
763
|
+
accessCount: number;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/** Why a memory ended up in the prompt — the thing you tune once you log it. */
|
|
767
|
+
/** What to do with a candidate memory once compared against what we hold. */
|
|
768
|
+
export declare type MemoryReconciliation = {
|
|
769
|
+
/**
|
|
770
|
+
* `add` keeps it as a new memory and is the safe default when unsure: an
|
|
771
|
+
* unmerged duplicate costs a row, while a wrong merge corrupts what we believe.
|
|
772
|
+
* `merge` collapses a restatement into the existing entry, keeping whichever
|
|
773
|
+
* carries more information. `replace` supersedes the existing entry. `reject`
|
|
774
|
+
* drops it as not worth storing.
|
|
775
|
+
*/
|
|
776
|
+
action: "add" | "merge" | "replace" | "reject";
|
|
777
|
+
/** Content to store when merging or replacing; defaults to the candidate. */
|
|
778
|
+
content?: string;
|
|
779
|
+
/** Why, so a bad merge is diagnosable rather than mysterious. */
|
|
780
|
+
reason?: string;
|
|
781
|
+
};
|
|
782
|
+
|
|
783
|
+
/** Where a statement came from. `rules` means no model was involved. */
|
|
784
|
+
export declare type MemorySource = "rules" | "model" | "api";
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* The wire contract, in one file, before any implementation.
|
|
788
|
+
*
|
|
789
|
+
* Two rules run through all of it:
|
|
790
|
+
*
|
|
791
|
+
* - **Literal unions, not `string`.** `tier: MemoryTier` means an editor offers
|
|
792
|
+
* exactly four values and a typo is a compile error. `tier: string` means a
|
|
793
|
+
* runtime surprise instead.
|
|
794
|
+
* - **Request and response types are separate.** A request has optional fields
|
|
795
|
+
* with defaults; a response has ids, timestamps and computed values. Deriving
|
|
796
|
+
* one from the other produces optional ids and a type that lies about both.
|
|
797
|
+
*
|
|
798
|
+
* Where a request value is constrained by a response value, it is written as a
|
|
799
|
+
* reference (`RememberRequest["items"][number]["tier"]`) so the two cannot drift
|
|
800
|
+
* apart when a new tier is added.
|
|
801
|
+
*/
|
|
802
|
+
export declare type MemoryTier = "L0" | "L1" | "L2" | "L3";
|
|
803
|
+
|
|
804
|
+
export declare const normalise: (value: string) => string;
|
|
805
|
+
|
|
806
|
+
/** Overlap of two token sets, normalised by the smaller side. */
|
|
807
|
+
export declare const overlapScore: (query: Set<string>, candidate: Set<string>) => number;
|
|
808
|
+
|
|
809
|
+
/** Above this, a memory is worth promoting into the pre-staged index. */
|
|
810
|
+
export declare const PROMOTE_THRESHOLD = 0.12;
|
|
811
|
+
|
|
812
|
+
export declare interface ProprioceptiveSelfModel {
|
|
813
|
+
/** Map of domain tag (e.g. "auth", "db-migration", "css") to capability stats */
|
|
814
|
+
domains: Record<string, DomainCapability_2>;
|
|
815
|
+
/** Overall calibration score (1.0 = well-calibrated, <0.7 = overconfident) */
|
|
816
|
+
calibrationFactor: number;
|
|
817
|
+
/** Active domains detected in current work */
|
|
818
|
+
activeDomains: string[];
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
export declare interface RecallHit {
|
|
822
|
+
memory: Memory;
|
|
823
|
+
score: number;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* Recall, phrased for injection into a prompt.
|
|
828
|
+
*
|
|
829
|
+
* Returns text rather than results because the caller's next step is almost
|
|
830
|
+
* always "put this in the prompt", and doing the formatting here means every
|
|
831
|
+
* integration handles the empty case the same way: by saying so, rather than
|
|
832
|
+
* letting a model fill the gap with a guess.
|
|
833
|
+
*/
|
|
834
|
+
export declare function recallOrExplain(memory: Cogmem, query: string, options?: RecallOrExplainOptions): Promise<string>;
|
|
835
|
+
|
|
836
|
+
export declare interface RecallOrExplainOptions {
|
|
837
|
+
limit?: number;
|
|
838
|
+
/** Overrides the default "you were not told this" wording. */
|
|
839
|
+
emptyMessage?: string;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
export declare interface RecallRequest {
|
|
843
|
+
query: string;
|
|
844
|
+
limit?: number;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* Deterministic ranked lookup.
|
|
849
|
+
*
|
|
850
|
+
* No model is involved, so recall quality does not change when a provider is
|
|
851
|
+
* down or a different model is configured. `empty: true` is the signal to admit
|
|
852
|
+
* ignorance rather than guess.
|
|
853
|
+
*/
|
|
854
|
+
export declare class RecallResource {
|
|
855
|
+
private readonly client;
|
|
856
|
+
constructor(client: HttpClient);
|
|
857
|
+
search(request: RecallRequest): Promise<RecallResponse>;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
export declare interface RecallResponse {
|
|
861
|
+
results: RecallHit[];
|
|
862
|
+
/** True when nothing matched, so the model can admit ignorance. */
|
|
863
|
+
empty: boolean;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
export declare interface RejectedStatement {
|
|
867
|
+
content: string;
|
|
868
|
+
reason: string;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
/** Content words worth matching a memory against. */
|
|
872
|
+
export declare const relevanceTokens: (value: string) => Set<string>;
|
|
873
|
+
|
|
874
|
+
export declare interface RememberRequest {
|
|
875
|
+
items: Array<{
|
|
876
|
+
content: string;
|
|
877
|
+
domains?: string[];
|
|
878
|
+
tier?: MemoryTier;
|
|
879
|
+
}>;
|
|
880
|
+
/** Groups memories from one conversation. */
|
|
881
|
+
sessionId?: string;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
export declare interface ResolveTensionRequest {
|
|
885
|
+
resolvedBy: string;
|
|
886
|
+
/** The reusable pattern the resolution revealed. */
|
|
887
|
+
pattern?: string;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
export declare const runFastGate: (userMessage: string) => FastGateResult;
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* One turn of an agent loop, with memory handled correctly.
|
|
894
|
+
*
|
|
895
|
+
* The order is the point:
|
|
896
|
+
*
|
|
897
|
+
* 1. build context *before* the model runs, keyed on the message being answered;
|
|
898
|
+
* 2. run the model;
|
|
899
|
+
* 3. learn from the finished exchange;
|
|
900
|
+
* 4. record how the domain went, so the self-model moves.
|
|
901
|
+
*
|
|
902
|
+
* Steps 3 and 4 never fail the turn. Memory is an enhancement; an outage in it
|
|
903
|
+
* must not take down the agent that was working fine without it, and the errors
|
|
904
|
+
* are surfaced through `onLearn` and the returned skip reason rather than
|
|
905
|
+
* swallowed.
|
|
906
|
+
*/
|
|
907
|
+
export declare function runTurn(memory: Cogmem, input: {
|
|
908
|
+
userMessage: string;
|
|
909
|
+
run: (context: string) => Promise<string>;
|
|
910
|
+
}, options?: TurnOptions): Promise<RunTurnResult>;
|
|
911
|
+
|
|
912
|
+
export declare interface RunTurnResult {
|
|
913
|
+
context: ContextReport;
|
|
914
|
+
learning: LearnResult | null;
|
|
915
|
+
/**
|
|
916
|
+
* Why learning did not happen, if it did not.
|
|
917
|
+
*
|
|
918
|
+
* Present because a silent skip looks identical to a working one until the
|
|
919
|
+
* thing you taught it never comes back.
|
|
920
|
+
*/
|
|
921
|
+
learningSkipped?: string;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
export declare type Scope = "memories:read" | "memories:write" | "stats:read" | "keys:manage";
|
|
925
|
+
|
|
926
|
+
/**
|
|
927
|
+
* Store a set of statements once, tolerating the ones already held.
|
|
928
|
+
*
|
|
929
|
+
* For a migration or a first run, where you have a list of facts and no way to
|
|
930
|
+
* know which the service already knows. Restatements come back under
|
|
931
|
+
* `mergedInto` rather than as errors, so re-running it is safe.
|
|
932
|
+
*/
|
|
933
|
+
export declare function seedMemories(memory: Cogmem, options: SeedOptions): Promise<{
|
|
934
|
+
stored: Memory[];
|
|
935
|
+
merged: Memory[];
|
|
936
|
+
rejected: LearnResult["rejected"];
|
|
937
|
+
}>;
|
|
938
|
+
|
|
939
|
+
export declare interface SeedOptions {
|
|
940
|
+
/** Statements worth keeping regardless of how they are phrased. */
|
|
941
|
+
facts: string[];
|
|
942
|
+
sessionId?: string;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
export declare interface SelfModel {
|
|
946
|
+
calibrationFactor: number;
|
|
947
|
+
activeDomains: string[];
|
|
948
|
+
domains: Record<string, DomainCapability>;
|
|
949
|
+
/** Below the 75% line, a guardrail is injected into every context build. */
|
|
950
|
+
weakDomains: string[];
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* The proprioceptive self-model: how reliably this agent has done in each domain.
|
|
955
|
+
*
|
|
956
|
+
* Nothing here is inferred. Without outcomes recorded through `record`, the
|
|
957
|
+
* model stays at its priors and no guardrail ever fires — which is the most
|
|
958
|
+
* common reason a self-model looks like it is not working.
|
|
959
|
+
*/
|
|
960
|
+
export declare class SelfModelResource {
|
|
961
|
+
private readonly client;
|
|
962
|
+
constructor(client: HttpClient);
|
|
963
|
+
get(): Promise<SelfModel>;
|
|
964
|
+
record(request: DomainOutcomeRequest): Promise<SelfModel>;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
/** Similarity of two statements by the tokens that carry identity. */
|
|
968
|
+
export declare const similarity: (a: string, b: string) => number;
|
|
969
|
+
|
|
970
|
+
export declare interface Stats {
|
|
971
|
+
memories: {
|
|
972
|
+
total: number;
|
|
973
|
+
byTier: Record<MemoryTier, number>;
|
|
974
|
+
sessions: number;
|
|
975
|
+
firstStoredAt: number;
|
|
976
|
+
lastAccessedAt: number;
|
|
977
|
+
};
|
|
978
|
+
tensions: {
|
|
979
|
+
active: number;
|
|
980
|
+
};
|
|
981
|
+
weakDomains: Array<{
|
|
982
|
+
domain: string;
|
|
983
|
+
reliabilityScore: number;
|
|
984
|
+
sampleCount: number;
|
|
985
|
+
}>;
|
|
986
|
+
recent: Memory[];
|
|
987
|
+
activeTensions: Tension[];
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
/** What the memory currently holds, and what the service can do. */
|
|
991
|
+
export declare class StatsResource {
|
|
992
|
+
private readonly client;
|
|
993
|
+
constructor(client: HttpClient);
|
|
994
|
+
/** Needs only `stats:read`, so monitoring can watch without reading memories. */
|
|
995
|
+
get(): Promise<Stats>;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
export declare interface Tension {
|
|
999
|
+
id: string;
|
|
1000
|
+
status: TensionStatus;
|
|
1001
|
+
claimA: Claim;
|
|
1002
|
+
claimB: Claim;
|
|
1003
|
+
impact: Impact;
|
|
1004
|
+
actionableQuestion: string;
|
|
1005
|
+
resolvedBy?: string;
|
|
1006
|
+
pattern?: string;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
export declare type TensionImpact = "low" | "medium" | "critical";
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Knowledge tensions: two claims that cannot both be true.
|
|
1013
|
+
*
|
|
1014
|
+
* A tension is worth more than either claim alone, so it is pinned into every
|
|
1015
|
+
* context build with an actionable question until it is resolved.
|
|
1016
|
+
*/
|
|
1017
|
+
export declare class TensionsResource {
|
|
1018
|
+
private readonly client;
|
|
1019
|
+
constructor(client: HttpClient);
|
|
1020
|
+
list(status?: TensionStatus): Promise<Tension[]>;
|
|
1021
|
+
create(request: AddTensionRequest): Promise<Tension>;
|
|
1022
|
+
resolve(id: string, request: ResolveTensionRequest): Promise<Tension>;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
export declare type TensionStatus = "active" | "latent" | "resolved";
|
|
1026
|
+
|
|
1027
|
+
declare type TensionStatus_2 = "active" | "latent" | "resolved";
|
|
1028
|
+
|
|
1029
|
+
export declare interface TrajectoryPrediction {
|
|
1030
|
+
predictedDomains: string[];
|
|
1031
|
+
predictedFiles: string[];
|
|
1032
|
+
prefetchMemoryIds: string[];
|
|
1033
|
+
confidence: number;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* Workflows.
|
|
1038
|
+
*
|
|
1039
|
+
* Resource methods are one call each. These compose them into the sequences
|
|
1040
|
+
* people actually get wrong when they write the loop themselves — and the
|
|
1041
|
+
* mistakes are mundane: forgetting to learn from a turn, learning from a question,
|
|
1042
|
+
* letting a memory failure take down the turn it was meant to help, or never
|
|
1043
|
+
* telling the service how a task went so the guardrails never fire.
|
|
1044
|
+
*
|
|
1045
|
+
* Each helper takes the client explicitly rather than closing over one, so it
|
|
1046
|
+
* works with a second client without a module-level singleton.
|
|
1047
|
+
*/
|
|
1048
|
+
export declare interface TurnOptions {
|
|
1049
|
+
/** Groups everything learned in one conversation. */
|
|
1050
|
+
sessionId?: string;
|
|
1051
|
+
/**
|
|
1052
|
+
* What the turn turned out to be about, e.g. `"database"`.
|
|
1053
|
+
*
|
|
1054
|
+
* Recorded against the self-model, which is what eventually produces a
|
|
1055
|
+
* guardrail for a domain the agent keeps failing in. Cheap to send and the
|
|
1056
|
+
* difference between a self-model that learns and one that sits at its priors.
|
|
1057
|
+
*/
|
|
1058
|
+
domain?: string;
|
|
1059
|
+
/** What went wrong, when the turn was a failure. */
|
|
1060
|
+
failurePattern?: string;
|
|
1061
|
+
/** What worked, when the turn was a success. */
|
|
1062
|
+
strategy?: string;
|
|
1063
|
+
/** Set false to skip learning — a retrieval-only turn, say. */
|
|
1064
|
+
learn?: boolean;
|
|
1065
|
+
onLearn?: (result: LearnResult) => void;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
export declare interface TurnRequest {
|
|
1069
|
+
userMessage: string;
|
|
1070
|
+
assistantResponse: string;
|
|
1071
|
+
sessionId?: string;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
/**
|
|
1075
|
+
* Learning from a completed turn.
|
|
1076
|
+
*
|
|
1077
|
+
* A turn whose user message contains a question is treated as a lookup rather
|
|
1078
|
+
* than a lesson, so this is called after work is done, not before.
|
|
1079
|
+
*/
|
|
1080
|
+
export declare class TurnsResource {
|
|
1081
|
+
private readonly client;
|
|
1082
|
+
constructor(client: HttpClient);
|
|
1083
|
+
learn(request: TurnRequest): Promise<LearnResult>;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
export { }
|