omp-fabric 1.23.0 → 1.24.1

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 (100) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/capture/wrapper.d.ts.map +1 -1
  3. package/dist/chunks/{chunk-52JBWP2C.js → chunk-3LMPHRDQ.js} +2 -2
  4. package/dist/chunks/{chunk-R4EFMCIY.js → chunk-4XJHCLTX.js} +2 -2
  5. package/dist/chunks/{chunk-P4GPBAQS.js → chunk-66PGUYJJ.js} +3 -3
  6. package/dist/chunks/{chunk-MQSRZC2O.js → chunk-AEZ7VF5S.js} +2 -2
  7. package/dist/chunks/{chunk-SDZXNTBF.js → chunk-B7HOWHPZ.js} +2 -2
  8. package/dist/chunks/{chunk-DTG3DYVC.js → chunk-BQLRDSNL.js} +3 -3
  9. package/dist/chunks/{chunk-RA2IB2QT.js → chunk-DRIWQ6PD.js} +5 -5
  10. package/dist/chunks/chunk-G5FBLYOY.js +895 -0
  11. package/dist/chunks/chunk-G5FBLYOY.js.map +7 -0
  12. package/dist/chunks/{chunk-BPMSLBX4.js → chunk-GE53G4VR.js} +2 -2
  13. package/dist/chunks/{chunk-LNP6JVCZ.js → chunk-ICADZLLJ.js} +5 -4
  14. package/dist/chunks/chunk-ICADZLLJ.js.map +7 -0
  15. package/dist/chunks/{chunk-3GMSYFLT.js → chunk-IE5HUDWQ.js} +3 -3
  16. package/dist/chunks/{chunk-YBNCEX5E.js → chunk-JXNXHUIJ.js} +2 -2
  17. package/dist/chunks/{chunk-E4HNDTLM.js → chunk-MZUWSNZX.js} +2 -69
  18. package/dist/chunks/{chunk-E4HNDTLM.js.map → chunk-MZUWSNZX.js.map} +3 -3
  19. package/dist/chunks/chunk-NIWOSO22.js +74 -0
  20. package/dist/chunks/chunk-NIWOSO22.js.map +7 -0
  21. package/dist/chunks/{chunk-ZFMSJLQE.js → chunk-OHPTGVDK.js} +7 -2
  22. package/dist/chunks/chunk-OHPTGVDK.js.map +7 -0
  23. package/dist/chunks/{chunk-GUJNTA7Z.js → chunk-ON7LE7QA.js} +8 -3
  24. package/dist/chunks/chunk-ON7LE7QA.js.map +7 -0
  25. package/dist/chunks/{chunk-ZQ72MAHY.js → chunk-QP3SVWUV.js} +7 -4
  26. package/dist/chunks/chunk-QP3SVWUV.js.map +7 -0
  27. package/dist/chunks/chunk-QW5LEEFV.js +130 -0
  28. package/dist/chunks/chunk-QW5LEEFV.js.map +7 -0
  29. package/dist/chunks/{chunk-4J65SMNI.js → chunk-SWHJQ6XH.js} +173 -71
  30. package/dist/chunks/chunk-SWHJQ6XH.js.map +7 -0
  31. package/dist/compaction/hook.d.ts +1 -0
  32. package/dist/compaction/hook.d.ts.map +1 -1
  33. package/dist/compaction/hook.js +6 -5
  34. package/dist/compaction/lcm-addresses.d.ts.map +1 -1
  35. package/dist/compaction/lcm-maintenance.d.ts +4 -0
  36. package/dist/compaction/lcm-maintenance.d.ts.map +1 -1
  37. package/dist/compaction/lcm-model.d.ts +1 -0
  38. package/dist/compaction/lcm-model.d.ts.map +1 -1
  39. package/dist/compaction/lcm-recovery.d.ts +7 -0
  40. package/dist/compaction/lcm-recovery.d.ts.map +1 -0
  41. package/dist/compaction/lcm-runtime.d.ts +8 -3
  42. package/dist/compaction/lcm-runtime.d.ts.map +1 -1
  43. package/dist/compaction/lcm-runtime.js +272 -670
  44. package/dist/compaction/lcm-runtime.js.map +4 -4
  45. package/dist/config.d.ts +1 -0
  46. package/dist/config.d.ts.map +1 -1
  47. package/dist/core/action-registry.js +3 -3
  48. package/dist/core/omp-tools.d.ts +3 -0
  49. package/dist/core/omp-tools.d.ts.map +1 -1
  50. package/dist/core/system-guidance.d.ts.map +1 -1
  51. package/dist/entropy/index.js +6 -6
  52. package/dist/fabric-exec-tool.d.ts.map +1 -1
  53. package/dist/fabric-runtime-state.js +17 -16
  54. package/dist/fabric-runtime-state.js.map +1 -1
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +40 -19
  57. package/dist/index.js.map +3 -3
  58. package/dist/memory/discovery.js +5 -5
  59. package/dist/memory/lcm-adapter.d.ts +7 -2
  60. package/dist/memory/lcm-adapter.d.ts.map +1 -1
  61. package/dist/memory/normalize.js +4 -4
  62. package/dist/memory/search.js +5 -5
  63. package/dist/providers/memory-provider.d.ts +2 -1
  64. package/dist/providers/memory-provider.d.ts.map +1 -1
  65. package/dist/providers/memory-provider.js +8 -8
  66. package/dist/residency/host.js +12 -11
  67. package/dist/residency/omp-entry.js +12 -11
  68. package/dist/residency/omp-entry.js.map +1 -1
  69. package/dist/runtime/core-override-guest-types.js +1 -1
  70. package/dist/runtime/node-process-runtime.js +1 -1
  71. package/dist/storage/lcm-identity.d.ts +4 -0
  72. package/dist/storage/lcm-identity.d.ts.map +1 -1
  73. package/dist/storage/lcm-ledger.d.ts +11 -2
  74. package/dist/storage/lcm-ledger.d.ts.map +1 -1
  75. package/dist/storage/lcm-migration.d.ts.map +1 -1
  76. package/dist/ui/settings.d.ts.map +1 -1
  77. package/dist/ui/settings.js +26 -2
  78. package/dist/ui/settings.js.map +2 -2
  79. package/docs/compaction.md +18 -4
  80. package/docs/configuration.md +1 -1
  81. package/package.json +1 -1
  82. package/dist/chunks/chunk-4J65SMNI.js.map +0 -7
  83. package/dist/chunks/chunk-GUJNTA7Z.js.map +0 -7
  84. package/dist/chunks/chunk-LNP6JVCZ.js.map +0 -7
  85. package/dist/chunks/chunk-NX2G7BRO.js +0 -87
  86. package/dist/chunks/chunk-NX2G7BRO.js.map +0 -7
  87. package/dist/chunks/chunk-WCV26AOT.js +0 -183
  88. package/dist/chunks/chunk-WCV26AOT.js.map +0 -7
  89. package/dist/chunks/chunk-ZFMSJLQE.js.map +0 -7
  90. package/dist/chunks/chunk-ZQ72MAHY.js.map +0 -7
  91. /package/dist/chunks/{chunk-52JBWP2C.js.map → chunk-3LMPHRDQ.js.map} +0 -0
  92. /package/dist/chunks/{chunk-R4EFMCIY.js.map → chunk-4XJHCLTX.js.map} +0 -0
  93. /package/dist/chunks/{chunk-P4GPBAQS.js.map → chunk-66PGUYJJ.js.map} +0 -0
  94. /package/dist/chunks/{chunk-MQSRZC2O.js.map → chunk-AEZ7VF5S.js.map} +0 -0
  95. /package/dist/chunks/{chunk-SDZXNTBF.js.map → chunk-B7HOWHPZ.js.map} +0 -0
  96. /package/dist/chunks/{chunk-DTG3DYVC.js.map → chunk-BQLRDSNL.js.map} +0 -0
  97. /package/dist/chunks/{chunk-RA2IB2QT.js.map → chunk-DRIWQ6PD.js.map} +0 -0
  98. /package/dist/chunks/{chunk-BPMSLBX4.js.map → chunk-GE53G4VR.js.map} +0 -0
  99. /package/dist/chunks/{chunk-3GMSYFLT.js.map → chunk-IE5HUDWQ.js.map} +0 -0
  100. /package/dist/chunks/{chunk-YBNCEX5E.js.map → chunk-JXNXHUIJ.js.map} +0 -0
@@ -8,7 +8,7 @@ import {
8
8
  loadTieredIndex,
9
9
  reconstructSessionLineage,
10
10
  searchMemoryIndex
11
- } from "./chunk-SDZXNTBF.js";
11
+ } from "./chunk-B7HOWHPZ.js";
12
12
  import {
13
13
  compareLexical,
14
14
  normalizeMemoryPhrase,
@@ -23,17 +23,17 @@ import {
23
23
  overrideSessionDir,
24
24
  resolveScope,
25
25
  resolveSessionTarget
26
- } from "./chunk-MQSRZC2O.js";
26
+ } from "./chunk-AEZ7VF5S.js";
27
27
  import {
28
28
  expandSessionEntriesChecked,
29
29
  normalizeSession
30
- } from "./chunk-BPMSLBX4.js";
30
+ } from "./chunk-GE53G4VR.js";
31
31
  import {
32
32
  hash,
33
33
  hashLcmPayload,
34
34
  lcmRawAddress,
35
35
  lcmSummaryAddress
36
- } from "./chunk-NX2G7BRO.js";
36
+ } from "./chunk-QW5LEEFV.js";
37
37
 
38
38
  // src/providers/memory-provider.ts
39
39
  import fs from "node:fs";
@@ -278,6 +278,33 @@ var isLowSurrogate = (code) => code >= 56320 && code <= 57343;
278
278
  var sourceKey = (entryId, contentHash) => `${entryId}:${contentHash}`;
279
279
  var activeBinding = (options, sessionId) => options.branchForSession?.(sessionId);
280
280
  var activeSourceSet = (binding) => binding?.activeSourceKeys === void 0 ? void 0 : new Set(binding.activeSourceKeys);
281
+ var parseLcmRawAddress = (address) => {
282
+ const parts = address.split(":");
283
+ if (parts.length < 4 || parts[0] !== "lcm.raw") return void 0;
284
+ const revision = Number(parts.at(-1));
285
+ const entryId = parts.slice(2, -1).join(":");
286
+ const sessionId = parts[1];
287
+ if (!sessionId || !entryId || !Number.isSafeInteger(revision) || revision < 1) return void 0;
288
+ return { sessionId, entryId, revision };
289
+ };
290
+ var readTime = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
291
+ var rawFilter = (args, query, mode) => {
292
+ const role = typeof args.role === "string" && args.role.length > 0 ? args.role : void 0;
293
+ const since = readTime(args.since);
294
+ const until = readTime(args.until);
295
+ const ranked = (query?.trim().length ?? 0) > 0 && mode !== "regex";
296
+ return {
297
+ search: {
298
+ ...role === void 0 ? { excludeRoles: ["custom"] } : { roles: [role] },
299
+ ...since === void 0 ? {} : { since },
300
+ ...until === void 0 ? {} : { until },
301
+ order: ranked ? "relevance" : "recent"
302
+ },
303
+ includeSummaries: role === void 0 || role === "compactionSummary",
304
+ ...since === void 0 ? {} : { since },
305
+ ...until === void 0 ? {} : { until }
306
+ };
307
+ };
281
308
  var sessionScope = (args, currentSessionId) => {
282
309
  const scope = typeof args.scope === "string" && args.scope.startsWith("session:") ? args.scope.slice("session:".length) : void 0;
283
310
  return scope ?? currentSessionId;
@@ -384,29 +411,32 @@ var LcmMemoryAdapter = class {
384
411
  const branches = args.branches === "all" ? "all" : "active";
385
412
  const offset = typeof args.offset === "number" && args.offset >= 0 ? Math.floor(args.offset) : 0;
386
413
  const pageSize = typeof args.pageSize === "number" && args.pageSize >= 1 ? Math.min(50, Math.floor(args.pageSize)) : 10;
387
- const selectedSession = sessionScope(args, this.options.currentSessionId);
414
+ const selectedSession = sessionScope(args, this.options.getCurrentSessionId?.());
415
+ const filter = rawFilter(args, query, mode);
388
416
  const reasons = /* @__PURE__ */ new Set();
389
417
  if (predicate.failure) reasons.add(predicate.failure);
390
- const summaryHits = this.summaryHits(selectedSession, branches, predicate, reasons);
391
- const raw = this.rawPage(selectedSession, branches, query, mode, match, predicate, offset, pageSize, reasons);
392
- const hits = raw.hits;
393
- const consumedPositions = offset + raw.consumed;
394
- let summaryTaken = 0;
395
- if (consumedPositions >= raw.total) {
396
- const start = Math.max(0, consumedPositions - raw.total);
397
- for (const hit of summaryHits.slice(start)) {
398
- if (hits.length >= pageSize) break;
399
- hits.push(hit);
400
- summaryTaken += 1;
401
- }
402
- }
403
- const total = raw.total + summaryHits.length;
404
- const consumed = raw.consumed + summaryTaken;
405
- const sessions = new Set(hits.map((hit) => hit.sessionId)).size;
418
+ const summaryHits = filter.includeSummaries ? this.summaryHits(selectedSession, branches, predicate, filter, reasons) : [];
419
+ const page = this.mergedPage({
420
+ search: {
421
+ ...selectedSession === void 0 ? {} : { sessionId: selectedSession },
422
+ ...query === void 0 ? {} : { query },
423
+ mode,
424
+ match,
425
+ ...filter.search
426
+ },
427
+ branches,
428
+ predicate,
429
+ summaryHits,
430
+ offset,
431
+ pageSize,
432
+ reasons
433
+ });
434
+ const total = page.rawTotal + summaryHits.length;
435
+ const sessions = new Set(page.hits.map((hit) => hit.sessionId)).size;
406
436
  return {
407
437
  total,
408
- hits,
409
- next: offset + consumed < total ? { ref: "memory.recall", args: { ...args, offset: offset + consumed } } : null,
438
+ hits: page.hits,
439
+ next: !page.exhausted && page.position < total ? { ref: "memory.recall", args: { ...args, offset: page.position } } : null,
410
440
  coverage: {
411
441
  complete: reasons.size === 0,
412
442
  indexedSessions: sessions,
@@ -417,48 +447,73 @@ var LcmMemoryAdapter = class {
417
447
  }
418
448
  };
419
449
  }
420
- rawPage(selectedSession, branches, query, mode, match, predicate, offset, pageSize, reasons) {
421
- const hits = [];
422
- let consumed = 0;
423
- let total = 0;
424
- while (hits.length < pageSize && consumed < this.maxRaw) {
425
- const limit = Math.min(Math.max(pageSize, 32), this.maxRaw - consumed);
426
- const page = this.options.ledger.searchRaw({
427
- ...selectedSession === void 0 ? {} : { sessionId: selectedSession },
428
- ...query === void 0 ? {} : { query },
429
- mode,
430
- match,
431
- offset: offset + consumed,
432
- limit,
433
- scanLimit: this.maxRaw
434
- });
435
- total = page.total;
450
+ mergedPage(input) {
451
+ const { search, branches, predicate, summaryHits, offset, pageSize, reasons } = input;
452
+ let batch = [];
453
+ let batchStart = 0;
454
+ let rawEnd = Number.POSITIVE_INFINITY;
455
+ let rawTotal = 0;
456
+ const rawAt = (position2) => {
457
+ if (position2 >= batchStart && position2 < batchStart + batch.length) return batch[position2 - batchStart];
458
+ if (position2 >= rawEnd) return void 0;
459
+ const limit = Math.max(pageSize, 32);
460
+ const page = this.options.ledger.searchRaw({ ...search, offset: position2, limit, scanLimit: this.maxRaw });
461
+ rawTotal = page.total;
436
462
  if (!page.complete) reasons.add("raw_search_incomplete");
437
- if (page.rows.length === 0) break;
438
- for (const entry of page.rows) {
439
- consumed += 1;
440
- const allowed = activeAllowed(branches, activeBinding(this.options, entry.sessionId), sourceKey(entry.entryId, entry.contentHash));
441
- if (!allowed.allowed) {
442
- if (allowed.reason) reasons.add(allowed.reason);
443
- continue;
444
- }
445
- hits.push(this.rawHit(entry, predicate, branches));
446
- if (hits.length >= pageSize) break;
463
+ batch = page.rows;
464
+ batchStart = position2;
465
+ if (page.rows.length < limit) rawEnd = position2 + page.rows.length;
466
+ return batch[0];
467
+ };
468
+ const hits = [];
469
+ let rawPosition = summaryHits.length === 0 ? offset : 0;
470
+ let summaryPosition = 0;
471
+ let position = rawPosition;
472
+ let emittedRaw = 0;
473
+ let headPosition = -1;
474
+ let headScore = 0;
475
+ let exhausted = false;
476
+ while (hits.length < pageSize) {
477
+ if (position >= offset && emittedRaw >= this.maxRaw) {
478
+ if (rawAt(rawPosition) !== void 0) reasons.add("raw_scan_limit");
479
+ break;
447
480
  }
448
- if (page.rows.length < limit) break;
449
- }
450
- if (hits.length < pageSize && consumed >= this.maxRaw && offset + consumed < total) {
451
- reasons.add("raw_scan_limit");
481
+ const entry = rawAt(rawPosition);
482
+ const summary = summaryHits[summaryPosition];
483
+ if (entry === void 0 && summary === void 0) {
484
+ exhausted = true;
485
+ break;
486
+ }
487
+ if (entry !== void 0 && headPosition !== rawPosition) {
488
+ headScore = predicate.scoreOf(entry.content);
489
+ headPosition = rawPosition;
490
+ }
491
+ const emit = position >= offset;
492
+ position += 1;
493
+ if (summary !== void 0 && (entry === void 0 || summary.score > headScore)) {
494
+ summaryPosition += 1;
495
+ if (emit) hits.push(summary);
496
+ continue;
497
+ }
498
+ rawPosition += 1;
499
+ if (!emit) continue;
500
+ emittedRaw += 1;
501
+ const allowed = activeAllowed(branches, activeBinding(this.options, entry.sessionId), sourceKey(entry.entryId, entry.contentHash));
502
+ if (!allowed.allowed) {
503
+ if (allowed.reason) reasons.add(allowed.reason);
504
+ continue;
505
+ }
506
+ hits.push(this.rawHit(entry, headScore, branches));
452
507
  }
453
- return { hits, consumed, total };
508
+ return { hits, position, rawTotal, exhausted };
454
509
  }
455
- rawHit(entry, predicate, branches) {
510
+ rawHit(entry, score, branches) {
456
511
  const preview = excerpt(entry.content);
457
512
  const address = lcmRawAddress(entry);
458
513
  return {
459
514
  kind: "lcm.raw",
460
515
  sessionId: entry.sessionId,
461
- score: predicate.scoreOf(entry.content),
516
+ score,
462
517
  snippet: preview.snippet,
463
518
  truncated: preview.truncated,
464
519
  source: {
@@ -476,7 +531,7 @@ var LcmMemoryAdapter = class {
476
531
  }
477
532
  };
478
533
  }
479
- summaryHits(selectedSession, branches, predicate, reasons) {
534
+ summaryHits(selectedSession, branches, predicate, filter, reasons) {
480
535
  const nodes = selectedSession === void 0 ? this.options.summaries.listNodes({ limit: this.maxSummary + 1 }) : this.options.summaries.listNodes({ sessionId: selectedSession, limit: this.maxSummary + 1 });
481
536
  if (nodes.length > this.maxSummary) reasons.add("summary_node_limit");
482
537
  const hits = [];
@@ -501,6 +556,8 @@ var LcmMemoryAdapter = class {
501
556
  continue;
502
557
  }
503
558
  }
559
+ if (filter.since !== void 0 && node.createdAt < filter.since) continue;
560
+ if (filter.until !== void 0 && node.createdAt > filter.until) continue;
504
561
  if (!predicate.matches(node.text)) continue;
505
562
  const preview = excerpt(node.text);
506
563
  hits.push({
@@ -731,12 +788,9 @@ var LcmMemoryAdapter = class {
731
788
  return { items, unavailable };
732
789
  }
733
790
  expandRaw(address, args, branches) {
734
- const parts = address.split(":");
735
- if (parts.length < 4 || parts[0] !== "lcm.raw") return { entries: [], next: null, error: { code: "invalid_address", message: "invalid LCM raw address" } };
736
- const revision = Number(parts.at(-1));
737
- const entryId = parts.slice(2, -1).join(":");
738
- const sessionId = parts[1];
739
- if (!sessionId || !entryId || !Number.isSafeInteger(revision) || revision < 1) return { entries: [], next: null, error: { code: "invalid_address", message: "invalid LCM raw address" } };
791
+ const parsed = parseLcmRawAddress(address);
792
+ if (!parsed) return { entries: [], next: null, error: { code: "invalid_address", message: "invalid LCM raw address" } };
793
+ const { sessionId, entryId, revision } = parsed;
740
794
  const entry = this.options.ledger.readRawEntry(sessionId, entryId, revision);
741
795
  if (!entry) return { entries: [], next: null, error: { code: "stale_pointer", message: "raw source is unavailable" } };
742
796
  const binding = activeBinding(this.options, sessionId);
@@ -1316,7 +1370,7 @@ var sessionsOutputSchema = {
1316
1370
  var descriptors = [
1317
1371
  {
1318
1372
  name: "recall",
1319
- description: "Search session memory as bounded ranked snippets. Literal queries rank any matching term by default; queryMatch all narrows to co-located terms. Call tools.call(hit.follow) for either an exact entry or a cold-session candidate, and tools.call(next) to continue.",
1373
+ description: "Search session memory as bounded snippets. An empty query browses entries newest first; a literal or phrase query ranks by relevance, then recency. Literal queries accept any matching term by default; queryMatch all narrows to co-located terms. role:'user' finds the user's requests; since/until bound entry time in epoch ms. When the LCM ledger is active, recall reads it together with its summaries and skips tool bookkeeping entries (role custom) unless role:'custom' is given; entryRange, ref, provider, action, outcome, or tool switch recall to the session-file engine. Call tools.call(hit.follow) for either an exact entry or a cold-session candidate, and tools.call(next) to continue.",
1320
1374
  inputSchema: {
1321
1375
  type: "object",
1322
1376
  properties: {
@@ -1424,11 +1478,11 @@ var descriptors = [
1424
1478
  },
1425
1479
  {
1426
1480
  name: "expand",
1427
- description: "Read exact normalized session entries and nearby context as bounded lossless chunks. An lcm.summary: address returns the entries that summary was built from, each addressed for further expansion. Call tools.call(next) to continue, or use guest-side memory.walk(args, visitor) to traverse complete reassembled entries.",
1481
+ description: "Read exact normalized session entries and nearby context as bounded lossless chunks. An lcm.raw: address reads that ledger entry; before/after add its neighbouring entries from the session file. An lcm.summary: address returns the entries that summary was built from, each addressed for further expansion. A bare session id or file path with indices, entryIds, entryRange, or operationAddresses reads absolute entry indices. Call tools.call(next) to continue, or use guest-side memory.walk(args, visitor) to traverse complete reassembled entries.",
1428
1482
  inputSchema: {
1429
1483
  type: "object",
1430
1484
  properties: {
1431
- session: { type: "string", description: "Exact session file path or unambiguous id." },
1485
+ session: { type: "string", description: "Exact session file path, unambiguous session id, or an lcm.raw:/lcm.summary: address." },
1432
1486
  expectedSourceHash: {
1433
1487
  type: "string",
1434
1488
  description: "SHA-256 from a prior pointer; stale sources are refused."
@@ -1549,6 +1603,8 @@ var normalizeMemoryArgs = actionArgNormalizer(
1549
1603
  () => descriptors,
1550
1604
  MEMORY_ARG_NORMALIZATION
1551
1605
  );
1606
+ var SESSION_ENGINE_RECALL_KEYS = ["entryRange", "ref", "provider", "action", "outcome", "tool"];
1607
+ var isLcmAddress = (session) => typeof session === "string" && (session.startsWith("lcm.raw:") || session.startsWith("lcm.summary:"));
1552
1608
  var parseBranches = (value, action) => {
1553
1609
  if (value === void 0) return "active";
1554
1610
  if (value === "active" || value === "all") return value;
@@ -1725,12 +1781,14 @@ var MemoryProvider = class {
1725
1781
  }
1726
1782
  async invoke(actionName, args, invocationContext) {
1727
1783
  try {
1728
- if (this.context.lcm && (actionName === "recall" || actionName === "expand")) {
1729
- const adapter = this.lcmMemoryAdapter(this.context.lcm);
1730
- if (actionName === "expand") return adapter.expand(args);
1784
+ const lcm = this.context.lcm;
1785
+ if (lcm && actionName === "expand" && isLcmAddress(args.session)) {
1786
+ return await this.expandLcm(this.lcmMemoryAdapter(lcm), args);
1787
+ }
1788
+ if (lcm && actionName === "recall" && !SESSION_ENGINE_RECALL_KEYS.some((key) => args[key] !== void 0)) {
1731
1789
  const queryMode = parseQueryMode(args.queryMode, "memory.recall");
1732
1790
  const queryMatch = parseQueryMatch(args.queryMatch, queryMode, "memory.recall");
1733
- return adapter.recall({ ...args, queryMode, queryMatch });
1791
+ return this.lcmMemoryAdapter(lcm).recall({ ...args, queryMode, queryMatch });
1734
1792
  }
1735
1793
  switch (actionName) {
1736
1794
  case "recall":
@@ -1763,6 +1821,50 @@ var MemoryProvider = class {
1763
1821
  throw error;
1764
1822
  }
1765
1823
  }
1824
+ async expandLcm(adapter, args) {
1825
+ const single = adapter.expand(args);
1826
+ const raw = parseLcmRawAddress(String(args.session));
1827
+ const context = (value) => typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? Math.min(value, EXPAND_MAX_CONTEXT) : 0;
1828
+ const before = context(args.before);
1829
+ const after = context(args.after);
1830
+ if (!raw || before === 0 && after === 0 || single.error !== void 0) return single;
1831
+ const unavailable = (message) => ({
1832
+ ...single,
1833
+ error: { code: "context_unavailable", message }
1834
+ });
1835
+ let ref;
1836
+ try {
1837
+ ref = resolveSessionTarget(this.context.agentDir, raw.sessionId, overrideSessionDir(this.context.sessionFile));
1838
+ } catch (error) {
1839
+ return unavailable(`Session ${raw.sessionId} did not resolve: ${error instanceof Error ? error.message : String(error)}`);
1840
+ }
1841
+ if (!ref) {
1842
+ return unavailable(`Session file for ${raw.sessionId} is unavailable; returned the single ledger entry.`);
1843
+ }
1844
+ const {
1845
+ session: _session,
1846
+ expectedSourceHash: _expectedSourceHash,
1847
+ expectedLineageFingerprint: _expectedLineageFingerprint,
1848
+ indices: _indices,
1849
+ entryIds: _entryIds,
1850
+ operationAddresses: _operationAddresses,
1851
+ entryRange: _entryRange,
1852
+ entryOffset: _entryOffset,
1853
+ textOffset: _textOffset,
1854
+ ...rest
1855
+ } = args;
1856
+ let widened;
1857
+ try {
1858
+ widened = await this.expand({ ...rest, session: ref.file, entryIds: [raw.entryId], before, after });
1859
+ } catch (error) {
1860
+ return unavailable(`Context read failed: ${error instanceof Error ? error.message : String(error)}`);
1861
+ }
1862
+ if (widened.error !== void 0) {
1863
+ const detail = widened.error;
1864
+ return unavailable(`Entry ${raw.entryId} has no context in ${ref.file}: ${String(detail.message ?? "unreadable")}`);
1865
+ }
1866
+ return widened;
1867
+ }
1766
1868
  async recall(args, invocationContext) {
1767
1869
  const query = typeof args.query === "string" ? args.query : void 0;
1768
1870
  const queryMode = parseQueryMode(args.queryMode, "memory.recall");
@@ -2467,4 +2569,4 @@ export {
2467
2569
  normalizeMemoryArgs,
2468
2570
  MemoryProvider
2469
2571
  };
2470
- //# sourceMappingURL=chunk-4J65SMNI.js.map
2572
+ //# sourceMappingURL=chunk-SWHJQ6XH.js.map