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.
@@ -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 { }