omp-fabric 1.3.4 → 1.4.0

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 (73) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/agents/handoff.d.ts.map +1 -1
  3. package/dist/chunks/{chunk-WZAH7BO2.js → chunk-2J2GOB4A.js} +30 -11
  4. package/dist/chunks/chunk-2J2GOB4A.js.map +7 -0
  5. package/dist/chunks/{chunk-2WDZT27Q.js → chunk-3H5LZWAG.js} +253 -4
  6. package/dist/chunks/chunk-3H5LZWAG.js.map +7 -0
  7. package/dist/chunks/{chunk-PYXBHMSL.js → chunk-IMSGR6OW.js} +3 -3
  8. package/dist/chunks/chunk-IY3IQPRQ.js +308 -0
  9. package/dist/chunks/chunk-IY3IQPRQ.js.map +7 -0
  10. package/dist/chunks/{chunk-VSSC4IDU.js → chunk-RTDJFHGH.js} +2 -2
  11. package/dist/chunks/{chunk-45URY66G.js → chunk-S4I7RMR5.js} +3 -3
  12. package/dist/chunks/{chunk-ZP3S74LW.js → chunk-SG4GVSWX.js} +49 -26
  13. package/dist/chunks/chunk-SG4GVSWX.js.map +7 -0
  14. package/dist/chunks/{chunk-JOWMM3EX.js → chunk-WPU4PKXQ.js} +135 -24
  15. package/dist/chunks/chunk-WPU4PKXQ.js.map +7 -0
  16. package/dist/chunks/{chunk-Z5AP4M6K.js → chunk-YOAZ5SO7.js} +12 -2
  17. package/dist/chunks/{chunk-Z5AP4M6K.js.map → chunk-YOAZ5SO7.js.map} +2 -2
  18. package/dist/compaction/branch-summary.d.ts +1 -1
  19. package/dist/compaction/branch-summary.d.ts.map +1 -1
  20. package/dist/compaction/hook.d.ts +21 -1
  21. package/dist/compaction/hook.d.ts.map +1 -1
  22. package/dist/compaction/hook.js +1 -1
  23. package/dist/compaction/lcm-maintenance.d.ts +103 -0
  24. package/dist/compaction/lcm-maintenance.d.ts.map +1 -0
  25. package/dist/compaction/lcm-model.d.ts +41 -0
  26. package/dist/compaction/lcm-model.d.ts.map +1 -0
  27. package/dist/compaction/lcm-runtime.d.ts +106 -0
  28. package/dist/compaction/lcm-runtime.d.ts.map +1 -0
  29. package/dist/config-migrations.d.ts +1 -1
  30. package/dist/config-migrations.d.ts.map +1 -1
  31. package/dist/config.d.ts +7 -1
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/fabric-runtime-state.d.ts +2 -0
  34. package/dist/fabric-runtime-state.d.ts.map +1 -1
  35. package/dist/fabric-runtime-state.js +12 -7
  36. package/dist/fabric-runtime-state.js.map +2 -2
  37. package/dist/fabric-state.d.ts +2 -1
  38. package/dist/fabric-state.d.ts.map +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +1030 -108
  41. package/dist/index.js.map +4 -4
  42. package/dist/memory/lcm-adapter.d.ts +97 -0
  43. package/dist/memory/lcm-adapter.d.ts.map +1 -0
  44. package/dist/providers/memory-provider.d.ts +8 -0
  45. package/dist/providers/memory-provider.d.ts.map +1 -1
  46. package/dist/providers/memory-provider.js +2 -1
  47. package/dist/residency/host.js +6 -5
  48. package/dist/residency/omp-entry.js +6 -5
  49. package/dist/residency/omp-entry.js.map +1 -1
  50. package/dist/runtime/core-override-guest-types.js +1 -1
  51. package/dist/runtime/guest-types.d.ts +1 -1
  52. package/dist/runtime/guest-types.d.ts.map +1 -1
  53. package/dist/runtime/guest-types.js +1 -1
  54. package/dist/storage/lcm-ledger.d.ts +107 -0
  55. package/dist/storage/lcm-ledger.d.ts.map +1 -0
  56. package/dist/storage/lcm-migration.d.ts +67 -0
  57. package/dist/storage/lcm-migration.d.ts.map +1 -0
  58. package/dist/ui/settings.js +5 -5
  59. package/dist/ui/settings.js.map +2 -2
  60. package/docs/adr/0001-lcm-durable-context-ledger.md +6 -0
  61. package/docs/agents/domain.md +25 -0
  62. package/docs/agents/issue-tracker.md +25 -0
  63. package/docs/agents/triage-labels.md +11 -0
  64. package/docs/compaction.md +78 -312
  65. package/docs/configuration.md +3 -3
  66. package/package.json +1 -1
  67. package/dist/chunks/chunk-2WDZT27Q.js.map +0 -7
  68. package/dist/chunks/chunk-JOWMM3EX.js.map +0 -7
  69. package/dist/chunks/chunk-WZAH7BO2.js.map +0 -7
  70. package/dist/chunks/chunk-ZP3S74LW.js.map +0 -7
  71. /package/dist/chunks/{chunk-PYXBHMSL.js.map → chunk-IMSGR6OW.js.map} +0 -0
  72. /package/dist/chunks/{chunk-VSSC4IDU.js.map → chunk-RTDJFHGH.js.map} +0 -0
  73. /package/dist/chunks/{chunk-45URY66G.js.map → chunk-S4I7RMR5.js.map} +0 -0
@@ -27,6 +27,9 @@ import {
27
27
  expandSessionEntriesChecked,
28
28
  normalizeSession
29
29
  } from "./chunk-6QBPSZJ5.js";
30
+ import {
31
+ hashLcmPayload
32
+ } from "./chunk-IY3IQPRQ.js";
30
33
 
31
34
  // src/providers/memory-provider.ts
32
35
  import fs from "node:fs";
@@ -59,10 +62,10 @@ var snippetAnchor = (text, query, queryMode) => {
59
62
  return Math.max(0, normalized.indexOf(phrase));
60
63
  }
61
64
  if (queryMode === "literal") {
62
- const terms = [...new Set(tokenizeLexical(query))].sort(
65
+ const terms2 = [...new Set(tokenizeLexical(query))].sort(
63
66
  (left, right) => right.length - left.length || left.localeCompare(right)
64
67
  );
65
- for (const term of terms) {
68
+ for (const term of terms2) {
66
69
  const index = normalized.indexOf(term);
67
70
  if (index >= 0) return index;
68
71
  }
@@ -226,6 +229,235 @@ var presentRecall = (input) => {
226
229
  return response;
227
230
  };
228
231
 
232
+ // src/memory/lcm-adapter.ts
233
+ var terms = (text) => [
234
+ ...new Set(text.normalize("NFKC").toLowerCase().match(/[\p{L}\p{N}_]+/gu) ?? [])
235
+ ];
236
+ var score = (text, query) => {
237
+ if (!query?.trim()) return 0;
238
+ const available = new Set(terms(text));
239
+ return terms(query).reduce((total, term) => total + (available.has(term) ? 1 : 0), 0);
240
+ };
241
+ var excerpt = (text, max = 480) => ({
242
+ snippet: text.length <= max ? text : text.slice(0, max),
243
+ truncated: text.length > max
244
+ });
245
+ var sourceKey = (sessionId, entryId, revision) => `${sessionId}:${entryId}:${revision}`;
246
+ var activeBinding = (options, sessionId) => options.branchForSession?.(sessionId);
247
+ var activeSourceSet = (binding) => binding?.activeSourceKeys === void 0 ? void 0 : new Set(binding.activeSourceKeys);
248
+ var sessionScope = (args, currentSessionId) => {
249
+ const scope = typeof args.scope === "string" && args.scope.startsWith("session:") ? args.scope.slice("session:".length) : void 0;
250
+ return scope ?? currentSessionId;
251
+ };
252
+ var activeAllowed = (branches, binding, key) => {
253
+ if (branches === "all") return { allowed: true };
254
+ if (!binding) return { allowed: false, reason: "active_branch_unbound" };
255
+ if (!binding.ready) return { allowed: false, reason: "session_incomplete" };
256
+ if (binding.activeSourceKeys !== void 0 && !activeSourceSet(binding)?.has(key)) {
257
+ return { allowed: false, reason: "source_off_active_branch" };
258
+ }
259
+ return { allowed: true };
260
+ };
261
+ var LcmMemoryAdapter = class {
262
+ constructor(options) {
263
+ this.options = options;
264
+ this.projectKey = options.projectKey ?? options.ledger.projectKey;
265
+ this.maxRaw = Math.max(1, Math.min(options.maxRawEntries ?? 1e3, 1e4));
266
+ this.maxSummary = Math.max(1, Math.min(options.maxSummaryNodes ?? 1e3, 1e4));
267
+ }
268
+ projectKey;
269
+ maxRaw;
270
+ maxSummary;
271
+ recall(args) {
272
+ const query = typeof args.query === "string" ? args.query : void 0;
273
+ const branches = args.branches === "all" ? "all" : "active";
274
+ const offset = typeof args.offset === "number" && args.offset >= 0 ? Math.floor(args.offset) : 0;
275
+ const pageSize = typeof args.pageSize === "number" && args.pageSize >= 1 ? Math.min(50, Math.floor(args.pageSize)) : 10;
276
+ const selectedSession = sessionScope(args, this.options.currentSessionId);
277
+ const reasons = /* @__PURE__ */ new Set();
278
+ const raw = selectedSession === void 0 ? this.options.ledger.readRawPage(void 0, 0, this.maxRaw + 1) : this.options.ledger.readRawPage(selectedSession, 0, this.maxRaw + 1);
279
+ const rawBounded = raw.slice(0, this.maxRaw);
280
+ const summaryBranch = branches === "active" && selectedSession !== void 0 ? activeBinding(this.options, selectedSession)?.branch : void 0;
281
+ const summaries = selectedSession === void 0 ? this.options.summaries.listNodes({ limit: this.maxSummary + 1 }) : this.options.summaries.listNodes({ sessionId: selectedSession, limit: this.maxSummary + 1, ...summaryBranch === void 0 ? {} : { branch: summaryBranch } });
282
+ const summaryBounded = summaries.slice(0, this.maxSummary);
283
+ if (raw.length > this.maxRaw) reasons.add("raw_entry_limit");
284
+ if (summaries.length > this.maxSummary) reasons.add("summary_node_limit");
285
+ const hits = [];
286
+ for (const entry of rawBounded) {
287
+ const binding = activeBinding(this.options, entry.sessionId);
288
+ const allowed = activeAllowed(branches, binding, sourceKey(entry.sessionId, entry.entryId, entry.revision));
289
+ if (!allowed.allowed) {
290
+ if (allowed.reason) reasons.add(allowed.reason);
291
+ continue;
292
+ }
293
+ const value = score(entry.content, query);
294
+ if (query && value === 0) continue;
295
+ const preview = excerpt(entry.content);
296
+ hits.push({
297
+ kind: "lcm.raw",
298
+ sessionId: entry.sessionId,
299
+ score: value,
300
+ snippet: preview.snippet,
301
+ truncated: preview.truncated,
302
+ source: {
303
+ kind: "raw",
304
+ projectKey: entry.projectKey,
305
+ sessionId: entry.sessionId,
306
+ entryId: entry.entryId,
307
+ revision: entry.revision,
308
+ contentHash: entry.payloadHash,
309
+ sourceHash: entry.payloadHash
310
+ },
311
+ follow: {
312
+ ref: "memory.expand",
313
+ args: {
314
+ session: `lcm.raw:${entry.sessionId}:${entry.entryId}:${entry.revision}`,
315
+ branches,
316
+ expectedSourceHash: entry.payloadHash
317
+ }
318
+ }
319
+ });
320
+ }
321
+ for (const node of summaryBounded) {
322
+ if (node.state !== "ready") {
323
+ reasons.add(`summary_${node.state}`);
324
+ continue;
325
+ }
326
+ const binding = activeBinding(this.options, node.sessionId);
327
+ if (branches === "active") {
328
+ if (!binding) {
329
+ reasons.add("active_branch_unbound");
330
+ continue;
331
+ }
332
+ if (!binding.ready) {
333
+ reasons.add("session_incomplete");
334
+ continue;
335
+ }
336
+ const active = activeSourceSet(binding);
337
+ if (active && node.sources.some((source) => !active.has(sourceKey(node.sessionId, source.entryId, source.revision)))) {
338
+ reasons.add("summary_off_active_branch");
339
+ continue;
340
+ }
341
+ }
342
+ const value = score(node.text, query);
343
+ if (query && value === 0) continue;
344
+ const preview = excerpt(node.text);
345
+ hits.push({
346
+ kind: "lcm.summary",
347
+ sessionId: node.sessionId,
348
+ score: value,
349
+ snippet: preview.snippet,
350
+ truncated: preview.truncated,
351
+ source: {
352
+ kind: "summary",
353
+ projectKey: node.projectKey,
354
+ sessionId: node.sessionId,
355
+ nodeId: node.nodeId,
356
+ sourceHash: node.sourceHash
357
+ },
358
+ follow: {
359
+ ref: "memory.expand",
360
+ args: { session: `lcm.summary:${node.nodeId}`, branches, expectedSourceHash: node.sourceHash }
361
+ }
362
+ });
363
+ }
364
+ hits.sort((left, right) => right.score - left.score || left.sessionId.localeCompare(right.sessionId) || left.source.kind.localeCompare(right.source.kind) || String(left.source.entryId ?? left.source.nodeId).localeCompare(String(right.source.entryId ?? right.source.nodeId)));
365
+ const page = hits.slice(offset, offset + pageSize);
366
+ return {
367
+ total: hits.length,
368
+ hits: page,
369
+ next: offset + page.length < hits.length ? { ref: "memory.recall", args: { ...args, offset: offset + page.length } } : null,
370
+ coverage: {
371
+ complete: reasons.size === 0,
372
+ indexedSessions: new Set(hits.map((hit) => hit.sessionId)).size,
373
+ eligibleSessions: new Set(hits.map((hit) => hit.sessionId)).size,
374
+ staleSessions: 0,
375
+ incompleteSessions: reasons.size === 0 ? 0 : 1,
376
+ reasons: [...reasons].sort()
377
+ }
378
+ };
379
+ }
380
+ expand(args) {
381
+ const address = typeof args.session === "string" ? args.session : "";
382
+ const branches = args.branches === "all" ? "all" : "active";
383
+ if (address.startsWith("lcm.summary:")) {
384
+ const node = this.options.summaries.getNode(address.slice("lcm.summary:".length));
385
+ if (!node) return { entries: [], next: null, error: { code: "stale_pointer", message: "summary node is unavailable" } };
386
+ if (node.state !== "ready") return { entries: [], next: null, error: { code: "incomplete_coverage", message: `summary node is ${node.state}` } };
387
+ const binding2 = activeBinding(this.options, node.sessionId);
388
+ if (branches === "active") {
389
+ if (!binding2 || !binding2.ready) return { entries: [], next: null, error: { code: "incomplete_coverage", message: "summary lineage is not ready" } };
390
+ const active = activeSourceSet(binding2);
391
+ if (active && node.sources.some((source) => !active.has(sourceKey(node.sessionId, source.entryId, source.revision)))) {
392
+ return { entries: [], next: null, error: { code: "stale_pointer", message: "summary is outside the active branch" } };
393
+ }
394
+ }
395
+ const expected2 = typeof args.expectedSourceHash === "string" ? args.expectedSourceHash : void 0;
396
+ if (expected2 && expected2 !== node.sourceHash) return { entries: [], next: null, error: { code: "stale_pointer", message: "summary source hash changed", expectedSourceHash: expected2, actualSourceHash: node.sourceHash } };
397
+ return {
398
+ session: address,
399
+ sourceHash: node.sourceHash,
400
+ branches,
401
+ lineageFingerprint: node.lineageFingerprint ?? null,
402
+ entryCount: 1,
403
+ entries: [{
404
+ index: 0,
405
+ entryId: node.nodeId,
406
+ parentId: null,
407
+ type: "summary",
408
+ role: "compactionSummary",
409
+ timestamp: node.createdAt,
410
+ isError: false,
411
+ text: node.text,
412
+ textRange: { start: 0, end: node.text.length, total: node.text.length, complete: true },
413
+ anchor: true,
414
+ structuredContent: { nodeId: node.nodeId, sourceHash: node.sourceHash, children: node.children, sources: node.sources }
415
+ }],
416
+ next: null
417
+ };
418
+ }
419
+ const parts = address.split(":");
420
+ if (parts.length < 4 || parts[0] !== "lcm.raw") return { entries: [], next: null, error: { code: "invalid_address", message: "invalid LCM raw address" } };
421
+ const revision = Number(parts.at(-1));
422
+ const entryId = parts.slice(2, -1).join(":");
423
+ const sessionId = parts[1];
424
+ if (!sessionId || !entryId || !Number.isSafeInteger(revision) || revision < 1) return { entries: [], next: null, error: { code: "invalid_address", message: "invalid LCM raw address" } };
425
+ const entry = this.options.ledger.readRawEntry(sessionId, entryId, revision);
426
+ if (!entry) return { entries: [], next: null, error: { code: "stale_pointer", message: "raw source is unavailable" } };
427
+ const binding = activeBinding(this.options, sessionId);
428
+ const allowed = activeAllowed(branches, binding, sourceKey(sessionId, entryId, revision));
429
+ if (!allowed.allowed) return { entries: [], next: null, error: { code: allowed.reason === "source_off_active_branch" ? "stale_pointer" : "incomplete_coverage", message: allowed.reason ?? "raw lineage is unavailable" } };
430
+ const payload = JSON.parse(entry.payloadJson);
431
+ const sourceHash = hashLcmPayload(payload);
432
+ const expected = typeof args.expectedSourceHash === "string" ? args.expectedSourceHash : void 0;
433
+ if (expected && expected !== sourceHash) return { entries: [], next: null, error: { code: "stale_pointer", message: "raw source hash changed", expectedSourceHash: expected, actualSourceHash: sourceHash } };
434
+ const max = typeof args.maxChars === "number" ? Math.min(24e3, Math.max(256, Math.floor(args.maxChars))) : 2e4;
435
+ const start = typeof args.textOffset === "number" ? Math.max(0, Math.floor(args.textOffset)) : 0;
436
+ const text = entry.content.slice(start, start + max);
437
+ const complete = start + text.length >= entry.content.length;
438
+ return {
439
+ session: address,
440
+ sourceHash,
441
+ branches,
442
+ entryCount: 1,
443
+ entries: [{
444
+ index: 0,
445
+ entryId: entry.entryId,
446
+ parentId: entry.parentEntryId,
447
+ type: "raw",
448
+ role: entry.role,
449
+ timestamp: entry.createdAt,
450
+ isError: false,
451
+ text,
452
+ textRange: { start, end: start + text.length, total: entry.content.length, complete },
453
+ anchor: true,
454
+ structuredContent: payload
455
+ }],
456
+ next: complete ? null : { ref: "memory.expand", args: { ...args, textOffset: start + text.length } }
457
+ };
458
+ }
459
+ };
460
+
229
461
  // src/providers/arg-normalization.ts
230
462
  var normalizeForm = (key) => key.toLowerCase().replace(/[^a-z0-9]/g, "");
231
463
  var KEY_SYNONYM_CLASSES = [
@@ -627,6 +859,19 @@ var recallSessionOutputSchema = {
627
859
  "follow"
628
860
  ]
629
861
  };
862
+ var lcmRecallOutputSchema = {
863
+ type: "object",
864
+ properties: {
865
+ kind: { type: "string", enum: ["lcm.raw", "lcm.summary"] },
866
+ sessionId: { type: "string" },
867
+ score: { type: "number" },
868
+ snippet: { type: "string" },
869
+ truncated: { type: "boolean" },
870
+ source: { type: "object" },
871
+ follow: callOutputSchema("memory.expand")
872
+ },
873
+ required: ["kind", "sessionId", "score", "snippet", "truncated", "source", "follow"]
874
+ };
630
875
  var recallOutputSchema = {
631
876
  type: "object",
632
877
  description: "Bounded ranked memory hits with uniform follow and pagination calls.",
@@ -635,7 +880,7 @@ var recallOutputSchema = {
635
880
  hits: {
636
881
  type: "array",
637
882
  description: "Call tools.call(hit.follow) to expand an entry or resolve a cold session.",
638
- items: { oneOf: [recallEntryOutputSchema, recallSessionOutputSchema] }
883
+ items: { oneOf: [recallEntryOutputSchema, recallSessionOutputSchema, lcmRecallOutputSchema] }
639
884
  },
640
885
  next: {
641
886
  oneOf: [callOutputSchema("memory.recall"), { type: "null" }],
@@ -1137,6 +1382,10 @@ var MemoryProvider = class {
1137
1382
  }
1138
1383
  async invoke(actionName, args, invocationContext) {
1139
1384
  try {
1385
+ if (this.context.lcm && (actionName === "recall" || actionName === "expand")) {
1386
+ const adapter = new LcmMemoryAdapter(this.context.lcm);
1387
+ return actionName === "recall" ? adapter.recall(args) : adapter.expand(args);
1388
+ }
1140
1389
  switch (actionName) {
1141
1390
  case "recall":
1142
1391
  return await this.recall(args, invocationContext);
@@ -1883,4 +2132,4 @@ export {
1883
2132
  normalizeMemoryArgs,
1884
2133
  MemoryProvider
1885
2134
  };
1886
- //# sourceMappingURL=chunk-2WDZT27Q.js.map
2135
+ //# sourceMappingURL=chunk-3H5LZWAG.js.map