hippo-memory 1.13.0 → 1.13.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.
Files changed (55) hide show
  1. package/dist/api.d.ts +69 -6
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +64 -1
  4. package/dist/api.js.map +1 -1
  5. package/dist/audit.d.ts +1 -1
  6. package/dist/audit.d.ts.map +1 -1
  7. package/dist/audit.js.map +1 -1
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +133 -1
  11. package/dist/cli.js.map +1 -1
  12. package/dist/client.d.ts.map +1 -1
  13. package/dist/client.js +12 -0
  14. package/dist/client.js.map +1 -1
  15. package/dist/forward-claim-detector.d.ts +38 -0
  16. package/dist/forward-claim-detector.d.ts.map +1 -0
  17. package/dist/forward-claim-detector.js +117 -0
  18. package/dist/forward-claim-detector.js.map +1 -0
  19. package/dist/mcp/server.d.ts +2 -0
  20. package/dist/mcp/server.d.ts.map +1 -1
  21. package/dist/mcp/server.js +121 -2
  22. package/dist/mcp/server.js.map +1 -1
  23. package/dist/predictions.d.ts +73 -1
  24. package/dist/predictions.d.ts.map +1 -1
  25. package/dist/predictions.js +210 -16
  26. package/dist/predictions.js.map +1 -1
  27. package/dist/recall-history.d.ts +127 -0
  28. package/dist/recall-history.d.ts.map +1 -0
  29. package/dist/recall-history.js +235 -0
  30. package/dist/recall-history.js.map +1 -0
  31. package/dist/server.d.ts +2 -0
  32. package/dist/server.d.ts.map +1 -1
  33. package/dist/server.js +81 -0
  34. package/dist/server.js.map +1 -1
  35. package/dist/src/api.js +64 -1
  36. package/dist/src/api.js.map +1 -1
  37. package/dist/src/audit.js.map +1 -1
  38. package/dist/src/cli.js +133 -1
  39. package/dist/src/cli.js.map +1 -1
  40. package/dist/src/client.js +12 -0
  41. package/dist/src/client.js.map +1 -1
  42. package/dist/src/forward-claim-detector.js +117 -0
  43. package/dist/src/forward-claim-detector.js.map +1 -0
  44. package/dist/src/mcp/server.js +121 -2
  45. package/dist/src/mcp/server.js.map +1 -1
  46. package/dist/src/predictions.js +210 -16
  47. package/dist/src/predictions.js.map +1 -1
  48. package/dist/src/recall-history.js +235 -0
  49. package/dist/src/recall-history.js.map +1 -0
  50. package/dist/src/server.js +81 -0
  51. package/dist/src/server.js.map +1 -1
  52. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  53. package/extensions/openclaw-plugin/package.json +1 -1
  54. package/openclaw.plugin.json +1 -1
  55. package/package.json +1 -1
@@ -28,6 +28,7 @@ import { openHippoDb, closeHippoDb } from './db.js';
28
28
  import { writeEntry, assertTenantId } from './store.js';
29
29
  import { createMemory, Layer } from './memory.js';
30
30
  import { appendAuditEvent } from './audit.js';
31
+ import { detectForwardClaim } from './forward-claim-detector.js';
31
32
  export const VALID_CLOSURE_STATES = new Set([
32
33
  'open',
33
34
  'closed',
@@ -269,7 +270,17 @@ export function loadPredictionsByClass(hippoRoot, tenantId, classTag, opts = {})
269
270
  * drift risk). Plan-eng-critic round 1 HIGH recommendation: emit inside
270
271
  * helper, not at 3 call sites.
271
272
  */
272
- export function computePredictionBaserate(hippoRoot, tenantId, classTag, actor = 'cli') {
273
+ export function computePredictionBaserate(hippoRoot, tenantId, classTag, actor = 'cli',
274
+ /** v0.32 / J3.2 — when false, skip the predict_baserate audit emit. The
275
+ * J3.2 orchestrator (computePlanningFallacyHint, below) calls this with
276
+ * emitAudit=false and emits its own `recall_autodebias_hint` audit row
277
+ * instead, so the predict_baserate channel stays scoped to deliberate
278
+ * CLI / HTTP / MCP predict-baserate calls and does NOT pollute on every
279
+ * recall containing a forward-claim phrase. Default true preserves the
280
+ * v1.13.0 J3 audit semantics for the 3 direct callers (cmdPredict
281
+ * baserate, /v1/predictions/stats route, hippo_predict_baserate MCP
282
+ * handler) — none of them pass this argument. */
283
+ emitAudit = true) {
273
284
  assertTenantId('computePredictionBaserate', tenantId);
274
285
  if (!classTag)
275
286
  throw new Error('computePredictionBaserate: classTag is required');
@@ -287,14 +298,18 @@ export function computePredictionBaserate(hippoRoot, tenantId, classTag, actor =
287
298
  const nClosed = rows.length;
288
299
  if (nClosed === 0) {
289
300
  // Audit zero-result reads too — agents probing empty classes is
290
- // a signal worth recording.
291
- appendAuditEvent(db, {
292
- tenantId,
293
- actor,
294
- op: 'predict_baserate',
295
- targetId: classTag,
296
- metadata: { class_tag: classTag, n_closed: 0 },
297
- });
301
+ // a signal worth recording. Skipped when emitAudit=false (J3.2
302
+ // orchestrator path; its own recall_autodebias_hint audit fires
303
+ // only when nClosed > 0 anyway, so no signal is lost).
304
+ if (emitAudit) {
305
+ appendAuditEvent(db, {
306
+ tenantId,
307
+ actor,
308
+ op: 'predict_baserate',
309
+ targetId: classTag,
310
+ metadata: { class_tag: classTag, n_closed: 0 },
311
+ });
312
+ }
298
313
  return {
299
314
  classTag,
300
315
  nClosed: 0,
@@ -326,13 +341,15 @@ export function computePredictionBaserate(hippoRoot, tenantId, classTag, actor =
326
341
  ? `averaged ${meanRatio.toFixed(2)}x actual`
327
342
  : 'no ratio-eligible rows (all estimates were 0)';
328
343
  const summary = `Last ${nClosed} estimate${nClosed === 1 ? '' : 's'} in class ${classTag} ${ratioPart} (MAE ${mae.toFixed(2)}).`;
329
- appendAuditEvent(db, {
330
- tenantId,
331
- actor,
332
- op: 'predict_baserate',
333
- targetId: classTag,
334
- metadata: { class_tag: classTag, n_closed: nClosed },
335
- });
344
+ if (emitAudit) {
345
+ appendAuditEvent(db, {
346
+ tenantId,
347
+ actor,
348
+ op: 'predict_baserate',
349
+ targetId: classTag,
350
+ metadata: { class_tag: classTag, n_closed: nClosed },
351
+ });
352
+ }
336
353
  return {
337
354
  classTag,
338
355
  nClosed,
@@ -383,4 +400,181 @@ export function loadOpenPredictions(hippoRoot, tenantId, opts = {}) {
383
400
  closeHippoDb(db);
384
401
  }
385
402
  }
403
+ /**
404
+ * Resolve a query-token set to a unique best-matching class_tag for the
405
+ * tenant. Scores by lower-cased token overlap; requires best score ≥ 1
406
+ * AND strictly greater than the 2nd-best score.
407
+ *
408
+ * Indexed via idx_predictions_tenant_class (db.ts:1015) → O(log n) seek
409
+ * plus a small DISTINCT scan over the per-tenant class-tag set.
410
+ *
411
+ * Scope behaviour (v1 design choice, independent-review-critic round 1
412
+ * MED): class_tag selection is TENANT-GLOBAL, NOT scope-filtered against
413
+ * the recall's opts.scope. The class_tag is an aggregator label across
414
+ * historical predictions in the class, not a per-memory scope-bound
415
+ * property. A no-scope recall CAN surface a class_tag from a privately-
416
+ * scoped prediction's class in PlanningFallacyHint.classTag — by design,
417
+ * because base-rate reasoning needs the full historical sample.
418
+ * Implications:
419
+ * - The hint payload itself carries no memory content (only the aggregate
420
+ * summary string + numeric stats), so memory bodies do not leak.
421
+ * - The class_tag NAME is the side-channel. If sensitive labels are a
422
+ * concern, callers should either use opaque class names (e.g. hashes
423
+ * or numeric tokens) or set HIPPO_AUTODEBIAS=off.
424
+ * - tests/api-recall-autodebias.test.ts locks this with an explicit
425
+ * test asserting that scope-set predictions surface via no-scope
426
+ * recalls (so future "fix" attempts that scope-filter trip CI).
427
+ */
428
+ function resolveClassFromTokens(hippoRoot, tenantId, queryTokens) {
429
+ if (queryTokens.length === 0)
430
+ return { classTag: null, tiebreak: false };
431
+ const db = openHippoDb(hippoRoot);
432
+ try {
433
+ const rows = db.prepare(`SELECT DISTINCT class_tag FROM predictions WHERE tenant_id = ?`).all(tenantId);
434
+ const querySet = new Set(queryTokens);
435
+ let bestScore = 0;
436
+ let bestClass = null;
437
+ let secondBest = 0;
438
+ for (const { class_tag } of rows) {
439
+ const classTokens = class_tag
440
+ .toLowerCase()
441
+ .split(/[-_\s]+/)
442
+ .filter((t) => t.length >= 3);
443
+ let score = 0;
444
+ for (const t of classTokens)
445
+ if (querySet.has(t))
446
+ score++;
447
+ if (score > bestScore) {
448
+ secondBest = bestScore;
449
+ bestScore = score;
450
+ bestClass = class_tag;
451
+ }
452
+ else if (score === bestScore && score > 0) {
453
+ // Tie at current best — bump secondBest. Do NOT update bestClass
454
+ // (alphabetical tiebreak would pick wrong class on ambiguous query
455
+ // like "migration will take 3 days" between migration-effort vs
456
+ // migration-risk; silent on tie instead).
457
+ secondBest = score;
458
+ }
459
+ else if (score > secondBest) {
460
+ secondBest = score;
461
+ }
462
+ }
463
+ if (bestScore < 1)
464
+ return { classTag: null, tiebreak: false };
465
+ if (bestScore === secondBest)
466
+ return { classTag: null, tiebreak: true };
467
+ return { classTag: bestClass, tiebreak: false };
468
+ }
469
+ finally {
470
+ closeHippoDb(db);
471
+ }
472
+ }
473
+ /**
474
+ * J3.2 orchestrator. Composes the forward-claim detector + class resolver +
475
+ * baserate compute, with telemetry-grade audit emission at every decision
476
+ * point (success, no-class-match, tiebreak).
477
+ *
478
+ * Returns null on any of:
479
+ * - mode === 'off' (env-disabled; pays only the env read, skips regex)
480
+ * - empty queryText
481
+ * - no forward-claim regex match
482
+ * - resolver returns no class (no overlap ≥ 1; emits no_class_match audit)
483
+ * - resolver returns tiebreak (≥2 classes tied at best; emits tiebreak audit)
484
+ * - resolved class has nClosed=0 (no historical data yet; silent)
485
+ *
486
+ * On success: calls computePredictionBaserate(..., emitAudit=false) so the
487
+ * predict_baserate audit channel stays scoped to deliberate predict-
488
+ * baserate calls (the orchestrator's own recall_autodebias_hint audit
489
+ * carries n_closed + mean_ratio in metadata so no telemetry is lost), then
490
+ * emits recall_autodebias_hint audit + returns the hint.
491
+ *
492
+ * Latency budget (plan §Latency): ~50us regex-only on miss; ~750-850us
493
+ * on full match+resolve+baserate path. Well under 50ms target.
494
+ */
495
+ export function computePlanningFallacyHint(hippoRoot, tenantId, queryText, opts = {}) {
496
+ // Env read FIRST so AUTODEBIAS=off pays zero regex cost. Per-call read
497
+ // (rather than module-load cache) is deliberate: tests env-toggle this
498
+ // via process.env mutation without module reload.
499
+ const mode = opts.mode ?? (process.env.HIPPO_AUTODEBIAS === 'off' ? 'off' : 'regex');
500
+ if (mode === 'off')
501
+ return null;
502
+ if (!queryText)
503
+ return null;
504
+ const match = detectForwardClaim(queryText);
505
+ if (!match)
506
+ return null;
507
+ const actor = opts.actor ?? 'recall';
508
+ const resolution = resolveClassFromTokens(hippoRoot, tenantId, match.classQueryTokens);
509
+ if (resolution.tiebreak) {
510
+ // Telemetry: forward-claim detected, ≥2 classes tied at best overlap.
511
+ // Silent to caller; surfaces in audit only.
512
+ const db = openHippoDb(hippoRoot);
513
+ try {
514
+ appendAuditEvent(db, {
515
+ tenantId,
516
+ actor,
517
+ op: 'recall_autodebias_hint_tiebreak',
518
+ targetId: match.phrase.slice(0, 100),
519
+ metadata: { detected_phrase: match.phrase, token_count: match.classQueryTokens.length },
520
+ });
521
+ }
522
+ finally {
523
+ closeHippoDb(db);
524
+ }
525
+ return null;
526
+ }
527
+ if (!resolution.classTag) {
528
+ // Telemetry: forward-claim detected, no class scored ≥ 1.
529
+ // This is the channel that drives the embedding-fallback decision
530
+ // for J3.3 — high volume here = regex+token-overlap is missing
531
+ // legitimate forward-claims that have NO obvious class signal.
532
+ const db = openHippoDb(hippoRoot);
533
+ try {
534
+ appendAuditEvent(db, {
535
+ tenantId,
536
+ actor,
537
+ op: 'recall_autodebias_hint_no_class_match',
538
+ targetId: match.phrase.slice(0, 100),
539
+ metadata: { detected_phrase: match.phrase, token_count: match.classQueryTokens.length },
540
+ });
541
+ }
542
+ finally {
543
+ closeHippoDb(db);
544
+ }
545
+ return null;
546
+ }
547
+ // emitAudit=false: avoid double-write to predict_baserate channel.
548
+ // The recall_autodebias_hint audit below carries n_closed + mean_ratio.
549
+ const baserate = computePredictionBaserate(hippoRoot, tenantId, resolution.classTag, actor,
550
+ /*emitAudit=*/ false);
551
+ if (baserate.nClosed === 0)
552
+ return null; // Silent — wait for closed data.
553
+ const db = openHippoDb(hippoRoot);
554
+ try {
555
+ appendAuditEvent(db, {
556
+ tenantId,
557
+ actor,
558
+ op: 'recall_autodebias_hint',
559
+ targetId: resolution.classTag,
560
+ metadata: {
561
+ class_tag: resolution.classTag,
562
+ detected_phrase: match.phrase,
563
+ n_closed: baserate.nClosed,
564
+ mean_ratio: baserate.meanRatio,
565
+ },
566
+ });
567
+ }
568
+ finally {
569
+ closeHippoDb(db);
570
+ }
571
+ return {
572
+ classTag: resolution.classTag,
573
+ baserateSummary: baserate.summary,
574
+ source: 'j3.2-auto',
575
+ detectedPhrase: match.phrase,
576
+ nClosed: baserate.nClosed,
577
+ meanRatio: baserate.meanRatio,
578
+ };
579
+ }
386
580
  //# sourceMappingURL=predictions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"predictions.js","sourceRoot":"","sources":["../../src/predictions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"predictions.js","sourceRoot":"","sources":["../../src/predictions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * J1 anchoring detector (recall-recurrence) — pure module.
3
+ *
4
+ * Implements two detection rules from ROADMAP-RESEARCH.md L546:
5
+ * R1 query_repeat: same queryHash within recentRepeatWindow returned
6
+ * same topMemoryId (caller is re-asking the same question).
7
+ * R2 memory_dominance: same topMemoryId across >= minDominance distinct
8
+ * queryHashes (memory acts as a fixed-point anchor regardless of what
9
+ * the agent asks).
10
+ *
11
+ * Per the plan v3 architectural decision: each pipeline (api.recall via
12
+ * HTTP, cmdRecall, MCP hippo_recall) owns its OWN ring buffer Map keyed
13
+ * by (tenant, session). No cross-pipeline sharing (the typical multi-
14
+ * process deployment makes IPC ring-sharing impractical; per-pipeline
15
+ * is correct because each pipeline has its own top-1 ranking anyway).
16
+ *
17
+ * Plan: docs/plans/2026-05-26-j1-anchoring-detector.md.
18
+ * Composes with J3.2: AnchoringHint + PlanningFallacyHint are independent
19
+ * signals; both can fire on the same recall.
20
+ */
21
+ const DEFAULT_MIN_DOMINANCE = 3;
22
+ const DEFAULT_RECENT_REPEAT_WINDOW = 5;
23
+ const DEFAULT_COOLDOWN = 3;
24
+ // ---------------------------------------------------------------------------
25
+ // Query text normalization + hashing
26
+ // ---------------------------------------------------------------------------
27
+ /**
28
+ * Normalize + hash a query text into a 32-bit integer.
29
+ * Lowercase → strip non-alphanumeric → split → drop empty + short tokens →
30
+ * sort tokens → join → FNV-1a 32-bit.
31
+ *
32
+ * Token sort + dedup means semantically-equivalent queries with reordered
33
+ * words collide intentionally (the roadmap's "semantically-distinct" v1
34
+ * uses textual normalization; embedding-based distinctness is J1-v2).
35
+ *
36
+ * Deterministic across processes; stable across Node + V8 versions.
37
+ */
38
+ export function hashQueryText(query) {
39
+ if (!query)
40
+ return 0;
41
+ // Token dedup before join: the R2 contract says "distinct queries"
42
+ // means semantically distinct, so `foo bar` and `foo foo bar` should
43
+ // collapse to the same hash. Without dedup, simple phrasing
44
+ // variations (typos, doubled tokens, intensifiers) would inflate
45
+ // distinct-query counts and trip R2 on essentially the same question.
46
+ // Codex round-1 catch.
47
+ // Unicode-aware tokenization (codex round-3 P2 catch): the prior
48
+ // ASCII-only [^a-z0-9\s] pattern stripped every non-Latin letter, so
49
+ // Japanese, Arabic, Cyrillic, accented-Latin etc. queries collapsed
50
+ // to empty token set -> hash 0 -> false R1 collisions across distinct
51
+ // non-English queries. \p{L} = any Unicode letter, \p{N} = any Unicode
52
+ // number, \p{M} = combining marks (preserve composed accented chars).
53
+ // Requires the /u flag and Node >= 12.
54
+ const normalized = query
55
+ .toLowerCase()
56
+ .replace(/[^\p{L}\p{N}\p{M}\s]/gu, ' ')
57
+ .split(/\s+/)
58
+ .filter((t) => t.length > 0);
59
+ // Drop tokens shorter than 3 chars to match the normalizer contract
60
+ // (filler / stop words). Without this, `a login bug` vs `login bug`
61
+ // hash differently and inflate R2 distinct-query counts, firing
62
+ // memory_dominance on repeated phrasings of the same question.
63
+ // Codex round-4 P2 catch. Matches the same >=3 filter in
64
+ // src/forward-claim-detector.ts for class-resolver tokens.
65
+ const filtered = normalized.filter((t) => t.length >= 3);
66
+ // Fallback when the >=3 filter would collapse the entire query to
67
+ // empty: CJK queries like `测试` / `环境` are 2-char tokens; English
68
+ // acronyms like `AI` / `UI` are 2 chars. Without this fallback they
69
+ // all hash to fnv1a32(''), producing false R1 collisions across
70
+ // distinct short-token queries. Codex round-5 P2 catch.
71
+ const tokens = filtered.length > 0 ? filtered : normalized;
72
+ const deduped = Array.from(new Set(tokens)).sort();
73
+ return fnv1a32(deduped.join(' '));
74
+ }
75
+ function fnv1a32(text) {
76
+ // FNV-1a 32-bit. Offset basis 2166136261, prime 16777619.
77
+ let hash = 2166136261;
78
+ for (let i = 0; i < text.length; i++) {
79
+ hash ^= text.charCodeAt(i);
80
+ // 32-bit multiply via Math.imul — handles overflow correctly.
81
+ hash = Math.imul(hash, 16777619);
82
+ }
83
+ // Coerce to unsigned 32-bit for stable comparison.
84
+ return hash >>> 0;
85
+ }
86
+ // ---------------------------------------------------------------------------
87
+ // Anchoring detection
88
+ // ---------------------------------------------------------------------------
89
+ /**
90
+ * Detect anchoring patterns in the recall history against the current
91
+ * recall's (queryHash, topMemoryId).
92
+ *
93
+ * Rule precedence: R2 (memory_dominance) wins on tie. When both R1 and R2
94
+ * fire on the same recall, return only the R2 hint — R2's signal is the
95
+ * cognitively stronger one (a memory dominating multiple DIFFERENT queries
96
+ * is a fixed-point anchor; R1 alone is just a literal re-ask).
97
+ *
98
+ * Cooldown: if the immediately-prior recall fired a hint on the SAME
99
+ * topMemoryId within `cooldown=3` history entries, suppress. Prevents
100
+ * spam when the agent repeatedly recalls within the dominance window.
101
+ * Cooldown is per-memory, not per-rule: if R2 fired on M (cooldown
102
+ * engaged for M), and the next recall has top=N + repeated query →
103
+ * R1 fires on N (different memory, not in cooldown).
104
+ *
105
+ * @returns AnchoringHint when a pattern fires; null otherwise.
106
+ */
107
+ export function detectAnchoring(history, currentQueryHash, currentTopMemoryId, opts = {}) {
108
+ if (currentTopMemoryId === null)
109
+ return null;
110
+ const minDominance = opts.minDominance ?? DEFAULT_MIN_DOMINANCE;
111
+ const recentRepeatWindow = opts.recentRepeatWindow ?? DEFAULT_RECENT_REPEAT_WINDOW;
112
+ const cooldown = opts.cooldown ?? DEFAULT_COOLDOWN;
113
+ // Cooldown gate: was the most-recent hint (across the last `cooldown`
114
+ // entries) for THIS memory? If yes, suppress regardless of rule.
115
+ const cooldownSlice = history.slice(-cooldown);
116
+ for (const entry of cooldownSlice) {
117
+ if (entry.anchoredOn === currentTopMemoryId) {
118
+ return null;
119
+ }
120
+ }
121
+ // R2 check FIRST (wins on tie). Count distinct queryHashes in history
122
+ // where topMemoryId === currentTopMemoryId (excluding null tops).
123
+ const matchingQueryHashes = new Set();
124
+ for (const entry of history) {
125
+ if (entry.topMemoryId === currentTopMemoryId) {
126
+ matchingQueryHashes.add(entry.queryHash);
127
+ }
128
+ }
129
+ // Include current query in the count.
130
+ matchingQueryHashes.add(currentQueryHash);
131
+ const queryCount = matchingQueryHashes.size;
132
+ if (queryCount >= minDominance) {
133
+ return {
134
+ reason: 'memory_dominance',
135
+ memoryId: currentTopMemoryId,
136
+ queryCount,
137
+ summary: `Memory ${currentTopMemoryId} has been the top result for ${queryCount} distinct queries in this session and may be anchoring your reasoning.`,
138
+ source: 'j1-recurrence',
139
+ };
140
+ }
141
+ // R1 check: is currentQueryHash present in the last `recentRepeatWindow`
142
+ // entries AND was that entry's topMemoryId === currentTopMemoryId?
143
+ const r1Slice = history.slice(-recentRepeatWindow);
144
+ for (const entry of r1Slice) {
145
+ if (entry.queryHash === currentQueryHash && entry.topMemoryId === currentTopMemoryId) {
146
+ return {
147
+ reason: 'query_repeat',
148
+ memoryId: currentTopMemoryId,
149
+ summary: `Same query phrasing as a recent recall returned the same top result (${currentTopMemoryId}); you may be re-asking the same question.`,
150
+ source: 'j1-recurrence',
151
+ };
152
+ }
153
+ }
154
+ return null;
155
+ }
156
+ // ---------------------------------------------------------------------------
157
+ // RingBuffer + caller-side state helpers
158
+ // ---------------------------------------------------------------------------
159
+ const MAX_HISTORY = 10;
160
+ const DEFAULT_MAX_SESSIONS = 1000;
161
+ /**
162
+ * Bounded FIFO ring of RecallHistoryEntry. Newest entries pushed via
163
+ * append; oldest evicted when the ring is full. The class is intentionally
164
+ * a thin wrapper around an array so snapshotRing returns a readonly view
165
+ * without copying on the hot path.
166
+ */
167
+ export class RingBuffer {
168
+ entries = [];
169
+ append(entry) {
170
+ this.entries.push(entry);
171
+ if (this.entries.length > MAX_HISTORY) {
172
+ this.entries.shift();
173
+ }
174
+ }
175
+ snapshot() {
176
+ return this.entries;
177
+ }
178
+ size() {
179
+ return this.entries.length;
180
+ }
181
+ }
182
+ /**
183
+ * Build the (tenant, session) key for a per-session ring Map. Uses a NUL
184
+ * (`\x00`) byte as delimiter because tenant ids and session ids are
185
+ * validated elsewhere to reject NUL chars — guarantees collision-free
186
+ * concatenation regardless of what `:` or other delimiters might appear
187
+ * inside either field (notably API-key-derived subjects can contain `:`).
188
+ */
189
+ export function buildSessionKey(tenantId, sessionId) {
190
+ return `${tenantId}\x00${sessionId}`;
191
+ }
192
+ /**
193
+ * Get-or-create a RingBuffer for a session key. Caps total tracked keys
194
+ * at `maxSessions` (default 1000) with LRU eviction — when the cap is
195
+ * hit, deletes the oldest-inserted key before inserting the new one.
196
+ * Map iteration order preserves insertion order per ECMA-262 spec, so
197
+ * "oldest" = first key returned by Map.prototype.keys().
198
+ */
199
+ export function getOrCreateRing(map, key, maxSessions = DEFAULT_MAX_SESSIONS) {
200
+ const existing = map.get(key);
201
+ if (existing) {
202
+ // LRU touch: delete + re-insert to move to back of iteration order.
203
+ map.delete(key);
204
+ map.set(key, existing);
205
+ return existing;
206
+ }
207
+ if (map.size >= maxSessions) {
208
+ const oldest = map.keys().next().value;
209
+ if (oldest !== undefined)
210
+ map.delete(oldest);
211
+ }
212
+ const ring = new RingBuffer();
213
+ map.set(key, ring);
214
+ return ring;
215
+ }
216
+ /**
217
+ * Append a recall to a ring. The `anchoredOn` argument carries the
218
+ * memoryId of the AnchoringHint that fired on THIS recall (or undefined
219
+ * if no hint). detectAnchoring reads it next time for cooldown gating.
220
+ */
221
+ export function appendRecall(ring, queryHash, topMemoryId, anchoredOn) {
222
+ const entry = {
223
+ queryHash,
224
+ topMemoryId,
225
+ ts: new Date().toISOString(),
226
+ };
227
+ if (anchoredOn !== undefined)
228
+ entry.anchoredOn = anchoredOn;
229
+ ring.append(entry);
230
+ }
231
+ /** Snapshot a ring as a readonly RecallHistorySnapshot. */
232
+ export function snapshotRing(ring) {
233
+ return ring.snapshot();
234
+ }
235
+ //# sourceMappingURL=recall-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall-history.js","sourceRoot":"","sources":["../../src/recall-history.ts"],"names":[],"mappings":"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"}