@graphrefly/graphrefly 0.10.0 → 0.11.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 (69) hide show
  1. package/dist/{chunk-WYI7YW54.js → chunk-2OTXEZQO.js} +3 -3
  2. package/dist/{chunk-TZLX4KIT.js → chunk-2VHNCFGG.js} +3 -3
  3. package/dist/{chunk-XCZPGOVP.js → chunk-3WACHRHV.js} +3 -3
  4. package/dist/{chunk-YWTP2XRJ.js → chunk-5WXTWOD7.js} +2 -2
  5. package/dist/{chunk-E7OH6ZAZ.js → chunk-FMVFRP7L.js} +62 -3
  6. package/dist/chunk-FMVFRP7L.js.map +1 -0
  7. package/dist/{chunk-LR2CLSEF.js → chunk-OHUECHWY.js} +2 -3
  8. package/dist/chunk-OHUECHWY.js.map +1 -0
  9. package/dist/{chunk-UCW3VWMN.js → chunk-PZCDQD2U.js} +4 -4
  10. package/dist/{chunk-A2AJJOSJ.js → chunk-U5HFZGAQ.js} +3 -3
  11. package/dist/{chunk-QTZSBQGJ.js → chunk-UG2QZMRN.js} +18 -1
  12. package/dist/chunk-UG2QZMRN.js.map +1 -0
  13. package/dist/compat/nestjs/index.cjs +10 -1
  14. package/dist/compat/nestjs/index.cjs.map +1 -1
  15. package/dist/compat/nestjs/index.d.cts +4 -4
  16. package/dist/compat/nestjs/index.d.ts +4 -4
  17. package/dist/compat/nestjs/index.js +7 -7
  18. package/dist/core/index.cjs +74 -1
  19. package/dist/core/index.cjs.map +1 -1
  20. package/dist/core/index.d.cts +2 -2
  21. package/dist/core/index.d.ts +2 -2
  22. package/dist/core/index.js +12 -3
  23. package/dist/extra/index.cjs +10 -0
  24. package/dist/extra/index.cjs.map +1 -1
  25. package/dist/extra/index.d.cts +4 -4
  26. package/dist/extra/index.d.ts +4 -4
  27. package/dist/extra/index.js +3 -3
  28. package/dist/graph/index.cjs +10 -1
  29. package/dist/graph/index.cjs.map +1 -1
  30. package/dist/graph/index.d.cts +3 -3
  31. package/dist/graph/index.d.ts +3 -3
  32. package/dist/graph/index.js +4 -4
  33. package/dist/{graph-DqTICAY2.d.cts → graph-BE10ujU9.d.cts} +1 -1
  34. package/dist/{graph-X9uwnD_z.d.ts → graph-DXT95WZ3.d.ts} +1 -1
  35. package/dist/{index-DLO8wnYU.d.ts → index-53cDGX7F.d.ts} +3 -3
  36. package/dist/{index-DMv1Etbi.d.ts → index-B10Q0sQB.d.ts} +2 -2
  37. package/dist/{index-a5gHmH5b.d.ts → index-Bbgvinsi.d.ts} +3 -3
  38. package/dist/{index-BPCeYDS4.d.ts → index-C0_7g9sj.d.ts} +1 -1
  39. package/dist/{index-3U0WxdD-.d.cts → index-CCvzN5GB.d.cts} +2 -2
  40. package/dist/{index-BP1t_38S.d.cts → index-DpZozxaJ.d.cts} +3 -3
  41. package/dist/{index-BVG5pjin.d.ts → index-Dzdm20sx.d.ts} +88 -3
  42. package/dist/{index-BYEgosAX.d.cts → index-QfbXNW1N.d.cts} +88 -3
  43. package/dist/{index-BYa2YMat.d.cts → index-aBZ2RoP0.d.cts} +3 -3
  44. package/dist/{index-DbwgQ4Cw.d.cts → index-nRulwTr-.d.cts} +1 -1
  45. package/dist/index.cjs +855 -101
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.cts +349 -19
  48. package/dist/index.d.ts +349 -19
  49. package/dist/index.js +800 -116
  50. package/dist/index.js.map +1 -1
  51. package/dist/{meta-BJEU8fYz.d.cts → meta-BcuDhtwu.d.cts} +33 -1
  52. package/dist/{meta-BJEU8fYz.d.ts → meta-BcuDhtwu.d.ts} +33 -1
  53. package/dist/patterns/reactive-layout/index.cjs +10 -1
  54. package/dist/patterns/reactive-layout/index.cjs.map +1 -1
  55. package/dist/patterns/reactive-layout/index.d.cts +3 -3
  56. package/dist/patterns/reactive-layout/index.d.ts +3 -3
  57. package/dist/patterns/reactive-layout/index.js +4 -4
  58. package/dist/{reactive-log-RhgIog2Z.d.ts → reactive-log-Cu0VdqkT.d.ts} +2 -2
  59. package/dist/{reactive-log-BfX6bOSZ.d.cts → reactive-log-OULQssZg.d.cts} +2 -2
  60. package/package.json +7 -2
  61. package/dist/chunk-E7OH6ZAZ.js.map +0 -1
  62. package/dist/chunk-LR2CLSEF.js.map +0 -1
  63. package/dist/chunk-QTZSBQGJ.js.map +0 -1
  64. /package/dist/{chunk-WYI7YW54.js.map → chunk-2OTXEZQO.js.map} +0 -0
  65. /package/dist/{chunk-TZLX4KIT.js.map → chunk-2VHNCFGG.js.map} +0 -0
  66. /package/dist/{chunk-XCZPGOVP.js.map → chunk-3WACHRHV.js.map} +0 -0
  67. /package/dist/{chunk-YWTP2XRJ.js.map → chunk-5WXTWOD7.js.map} +0 -0
  68. /package/dist/{chunk-UCW3VWMN.js.map → chunk-PZCDQD2U.js.map} +0 -0
  69. /package/dist/{chunk-A2AJJOSJ.js.map → chunk-U5HFZGAQ.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -65,10 +65,12 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
65
65
  // src/index.ts
66
66
  var index_exports = {};
67
67
  __export(index_exports, {
68
+ CLEANUP_RESULT: () => CLEANUP_RESULT,
68
69
  COMPLETE: () => COMPLETE,
69
70
  CircuitOpenError: () => CircuitOpenError,
70
71
  DATA: () => DATA,
71
72
  DEFAULT_ACTOR: () => DEFAULT_ACTOR,
73
+ DEFAULT_DOWN: () => DEFAULT_DOWN,
72
74
  DIRTY: () => DIRTY,
73
75
  DictCheckpointAdapter: () => DictCheckpointAdapter,
74
76
  DynamicNodeImpl: () => DynamicNodeImpl,
@@ -94,6 +96,7 @@ __export(index_exports, {
94
96
  ai: () => ai_exports,
95
97
  audit: () => audit,
96
98
  batch: () => batch,
99
+ bridge: () => bridge,
97
100
  buffer: () => buffer,
98
101
  bufferCount: () => bufferCount,
99
102
  bufferTime: () => bufferTime,
@@ -105,6 +108,7 @@ __export(index_exports, {
105
108
  checkpointToRedis: () => checkpointToRedis,
106
109
  checkpointToS3: () => checkpointToS3,
107
110
  circuitBreaker: () => circuitBreaker,
111
+ cleanupResult: () => cleanupResult,
108
112
  combine: () => combine,
109
113
  combineLatest: () => combineLatest,
110
114
  compat: () => compat_exports,
@@ -129,6 +133,7 @@ __export(index_exports, {
129
133
  deserializeError: () => deserializeError,
130
134
  distill: () => distill,
131
135
  distinctUntilChanged: () => distinctUntilChanged,
136
+ domainTemplates: () => domain_templates_exports,
132
137
  dynamicNode: () => dynamicNode,
133
138
  effect: () => effect,
134
139
  elementAt: () => elementAt,
@@ -729,6 +734,7 @@ function isV1(info) {
729
734
 
730
735
  // src/core/node.ts
731
736
  var NO_VALUE = /* @__PURE__ */ Symbol.for("graphrefly/NO_VALUE");
737
+ var CLEANUP_RESULT = /* @__PURE__ */ Symbol.for("graphrefly/CLEANUP_RESULT");
732
738
  function createIntBitSet() {
733
739
  let bits = 0;
734
740
  return {
@@ -791,6 +797,12 @@ function createBitSet(size) {
791
797
  }
792
798
  var isNodeArray = (value) => Array.isArray(value);
793
799
  var isNodeOptions = (value) => typeof value === "object" && value != null && !Array.isArray(value);
800
+ function cleanupResult(cleanup, ...args) {
801
+ const r = { [CLEANUP_RESULT]: true, cleanup };
802
+ if (args.length > 0) r.value = args[0];
803
+ return r;
804
+ }
805
+ var isCleanupResult = (value) => typeof value === "object" && value !== null && CLEANUP_RESULT in value;
794
806
  var isCleanupFn = (value) => typeof value === "function";
795
807
  var statusAfterMessage = (status, msg) => {
796
808
  const t = msg[0];
@@ -1206,6 +1218,14 @@ var NodeImpl = class {
1206
1218
  this._lastDepValues = depValues;
1207
1219
  this._inspectorHook?.({ kind: "run", depValues });
1208
1220
  const out = this._fn(depValues, this._actions);
1221
+ if (isCleanupResult(out)) {
1222
+ this._cleanup = out.cleanup;
1223
+ if (this._manualEmitUsed) return;
1224
+ if ("value" in out) {
1225
+ this._emitAutoValue(out.value);
1226
+ }
1227
+ return;
1228
+ }
1209
1229
  if (isCleanupFn(out)) {
1210
1230
  this._cleanup = out;
1211
1231
  return;
@@ -3544,7 +3564,6 @@ function resolveDescribeFields(detail, fields) {
3544
3564
  case "full":
3545
3565
  return null;
3546
3566
  // null = include everything
3547
- case "minimal":
3548
3567
  default:
3549
3568
  return /* @__PURE__ */ new Set(["type", "deps"]);
3550
3569
  }
@@ -5519,9 +5538,11 @@ __export(cqrs_exports, {
5519
5538
  // src/core/index.ts
5520
5539
  var core_exports = {};
5521
5540
  __export(core_exports, {
5541
+ CLEANUP_RESULT: () => CLEANUP_RESULT,
5522
5542
  COMPLETE: () => COMPLETE,
5523
5543
  DATA: () => DATA,
5524
5544
  DEFAULT_ACTOR: () => DEFAULT_ACTOR,
5545
+ DEFAULT_DOWN: () => DEFAULT_DOWN,
5525
5546
  DIRTY: () => DIRTY,
5526
5547
  DynamicNodeImpl: () => DynamicNodeImpl,
5527
5548
  ERROR: () => ERROR,
@@ -5535,6 +5556,8 @@ __export(core_exports, {
5535
5556
  accessHintForGuard: () => accessHintForGuard,
5536
5557
  advanceVersion: () => advanceVersion,
5537
5558
  batch: () => batch,
5559
+ bridge: () => bridge,
5560
+ cleanupResult: () => cleanupResult,
5538
5561
  createVersioning: () => createVersioning,
5539
5562
  defaultHash: () => defaultHash,
5540
5563
  derived: () => derived,
@@ -5564,6 +5587,57 @@ __export(core_exports, {
5564
5587
  wallClockNs: () => wallClockNs
5565
5588
  });
5566
5589
 
5590
+ // src/core/bridge.ts
5591
+ var DEFAULT_DOWN = [
5592
+ DATA,
5593
+ DIRTY,
5594
+ RESOLVED,
5595
+ COMPLETE,
5596
+ ERROR,
5597
+ TEARDOWN,
5598
+ PAUSE,
5599
+ RESUME,
5600
+ INVALIDATE
5601
+ ];
5602
+ var STANDARD_TYPES = /* @__PURE__ */ new Set([
5603
+ DATA,
5604
+ DIRTY,
5605
+ RESOLVED,
5606
+ COMPLETE,
5607
+ ERROR,
5608
+ TEARDOWN,
5609
+ PAUSE,
5610
+ RESUME,
5611
+ INVALIDATE
5612
+ ]);
5613
+ function bridge(from, to, opts) {
5614
+ const allowedDown = new Set(opts?.down ?? DEFAULT_DOWN);
5615
+ const onMessage = (msg, _depIndex, _actions) => {
5616
+ const type = msg[0];
5617
+ if (!STANDARD_TYPES.has(type)) {
5618
+ to.down([msg]);
5619
+ return true;
5620
+ }
5621
+ if (type === COMPLETE || type === ERROR) {
5622
+ if (allowedDown.has(type)) {
5623
+ to.down([msg]);
5624
+ }
5625
+ return false;
5626
+ }
5627
+ if (!allowedDown.has(type)) {
5628
+ return true;
5629
+ }
5630
+ to.down([msg]);
5631
+ return true;
5632
+ };
5633
+ return node([from], void 0, {
5634
+ name: opts?.name,
5635
+ describeKind: "effect",
5636
+ onMessage,
5637
+ meta: { _internal: true }
5638
+ });
5639
+ }
5640
+
5567
5641
  // src/core/timer.ts
5568
5642
  var ResettableTimer = class {
5569
5643
  _timer;
@@ -12863,6 +12937,7 @@ __export(patterns_exports, {
12863
12937
  ai: () => ai_exports,
12864
12938
  cqrs: () => cqrs_exports,
12865
12939
  demoShell: () => demo_shell_exports,
12940
+ domainTemplates: () => domain_templates_exports,
12866
12941
  graphspec: () => graphspec_exports,
12867
12942
  layout: () => reactive_layout_exports,
12868
12943
  memory: () => memory_exports,
@@ -14276,7 +14351,7 @@ function gaugesAsContext(graph, actor, options) {
14276
14351
  const ungrouped = [];
14277
14352
  for (const entry of entries) {
14278
14353
  const node2 = described.nodes[entry.path];
14279
- const tags = (node2.meta ?? {}).tags;
14354
+ const tags = node2.meta?.tags;
14280
14355
  if (tags && tags.length > 0) {
14281
14356
  const tag = tags[0];
14282
14357
  let group = tagGroups.get(tag);
@@ -15419,15 +15494,13 @@ function demoShell(opts) {
15419
15494
  };
15420
15495
  }
15421
15496
 
15422
- // src/patterns/graphspec.ts
15423
- var graphspec_exports = {};
15424
- __export(graphspec_exports, {
15425
- compileSpec: () => compileSpec,
15426
- decompileGraph: () => decompileGraph,
15427
- llmCompose: () => llmCompose,
15428
- llmRefine: () => llmRefine,
15429
- specDiff: () => specDiff,
15430
- validateSpec: () => validateSpec
15497
+ // src/patterns/domain-templates.ts
15498
+ var domain_templates_exports = {};
15499
+ __export(domain_templates_exports, {
15500
+ contentModerationGraph: () => contentModerationGraph,
15501
+ dataQualityGraph: () => dataQualityGraph,
15502
+ issueTrackerGraph: () => issueTrackerGraph,
15503
+ observabilityGraph: () => observabilityGraph
15431
15504
  });
15432
15505
 
15433
15506
  // src/patterns/reduction.ts
@@ -15446,6 +15519,10 @@ function baseMeta(kind, meta) {
15446
15519
  ...meta ?? {}
15447
15520
  };
15448
15521
  }
15522
+ function keepalive4(n) {
15523
+ return n.subscribe(() => {
15524
+ });
15525
+ }
15449
15526
  function stratify(name, source, rules, opts) {
15450
15527
  const g = new Graph(name, opts);
15451
15528
  g.add("source", source);
@@ -15460,18 +15537,27 @@ function stratify(name, source, rules, opts) {
15460
15537
  }
15461
15538
  function _addBranch(graph, source, rulesNode, rule) {
15462
15539
  const branchName = `branch/${rule.name}`;
15540
+ const _noValue = /* @__PURE__ */ Symbol("noValue");
15541
+ let sourceDirty = false;
15542
+ let rulesDirty = false;
15543
+ let sourcePhase2 = false;
15544
+ let sourceValue = _noValue;
15463
15545
  let pendingDirty = false;
15464
- const filterNode = node([source, rulesNode], () => void 0, {
15465
- describeKind: "operator",
15466
- meta: baseMeta("stratify_branch", { branch: rule.name }),
15467
- onMessage(msg, depIndex, actions) {
15468
- if (depIndex !== 0) return false;
15469
- const t = msg[0];
15470
- if (t === DATA) {
15471
- const value = msg[1];
15546
+ function resolve(actions) {
15547
+ if (sourcePhase2) {
15548
+ sourcePhase2 = false;
15549
+ const value = sourceValue;
15550
+ sourceValue = _noValue;
15551
+ if (value !== _noValue) {
15472
15552
  const currentRules = rulesNode.get();
15473
15553
  const currentRule = currentRules.find((r) => r.name === rule.name);
15474
- if (currentRule && currentRule.classify(value)) {
15554
+ let matches = false;
15555
+ try {
15556
+ matches = currentRule?.classify(value) ?? false;
15557
+ } catch {
15558
+ matches = false;
15559
+ }
15560
+ if (matches) {
15475
15561
  pendingDirty = false;
15476
15562
  actions.emit(value);
15477
15563
  } else {
@@ -15480,28 +15566,57 @@ function _addBranch(graph, source, rulesNode, rule) {
15480
15566
  actions.down([[DIRTY], [RESOLVED]]);
15481
15567
  }
15482
15568
  }
15483
- return true;
15484
- }
15485
- if (t === DIRTY) {
15486
- pendingDirty = true;
15487
- return true;
15488
- }
15489
- if (t === RESOLVED) {
15569
+ } else {
15490
15570
  if (pendingDirty) {
15491
15571
  pendingDirty = false;
15492
15572
  actions.down([[DIRTY], [RESOLVED]]);
15493
15573
  } else {
15494
15574
  actions.down([[RESOLVED]]);
15495
15575
  }
15576
+ }
15577
+ }
15578
+ }
15579
+ const filterNode = node([source, rulesNode], () => void 0, {
15580
+ describeKind: "operator",
15581
+ meta: baseMeta("stratify_branch", { branch: rule.name }),
15582
+ onMessage(msg, depIndex, actions) {
15583
+ const t = msg[0];
15584
+ if (t === DIRTY) {
15585
+ if (depIndex === 0) {
15586
+ sourceDirty = true;
15587
+ pendingDirty = true;
15588
+ } else {
15589
+ rulesDirty = true;
15590
+ }
15496
15591
  return true;
15497
15592
  }
15498
- if (t === COMPLETE || t === ERROR) {
15593
+ if (t === DATA || t === RESOLVED) {
15594
+ if (depIndex === 0) {
15595
+ sourceDirty = false;
15596
+ sourcePhase2 = true;
15597
+ sourceValue = t === DATA ? msg[1] : _noValue;
15598
+ } else {
15599
+ rulesDirty = false;
15600
+ }
15601
+ if (sourceDirty || rulesDirty) return true;
15602
+ resolve(actions);
15603
+ return true;
15604
+ }
15605
+ if (t === COMPLETE || t === ERROR || t === TEARDOWN) {
15606
+ sourceDirty = false;
15607
+ rulesDirty = false;
15608
+ sourcePhase2 = false;
15609
+ sourceValue = _noValue;
15499
15610
  pendingDirty = false;
15500
- actions.down([msg]);
15611
+ if (depIndex === 0) {
15612
+ actions.down([msg]);
15613
+ }
15501
15614
  return true;
15502
15615
  }
15616
+ if (depIndex === 1) return true;
15503
15617
  return false;
15504
- }
15618
+ },
15619
+ completeWhenDepsComplete: false
15505
15620
  });
15506
15621
  graph.add(branchName, filterNode);
15507
15622
  graph.connect("source", branchName);
@@ -15537,20 +15652,14 @@ function funnel(name, sources, stages, opts) {
15537
15652
  const prevNode = g.resolve(prevOutputPath);
15538
15653
  const stageInputPath = `${stage.name}::input`;
15539
15654
  const stageInput = g.resolve(stageInputPath);
15540
- prevNode.subscribe((msgs) => {
15541
- for (const msg of msgs) {
15542
- const t = msg[0];
15543
- if (t === DATA) {
15544
- stageInput.down([[DATA, msg[1]]]);
15545
- } else if (t === DIRTY) {
15546
- stageInput.down([[DIRTY]]);
15547
- } else if (t === RESOLVED) {
15548
- stageInput.down([[RESOLVED]]);
15549
- } else if (t === COMPLETE || t === ERROR) {
15550
- stageInput.down([msg]);
15551
- }
15552
- }
15655
+ const bridgeName = `__bridge_${prevOutputPath}\u2192${stage.name}_input`;
15656
+ const br = bridge(prevNode, stageInput, {
15657
+ name: bridgeName,
15658
+ down: DEFAULT_DOWN.filter((t) => t !== TEARDOWN)
15553
15659
  });
15660
+ g.add(bridgeName, br);
15661
+ g.connect(prevOutputPath, bridgeName);
15662
+ keepalive4(br);
15554
15663
  prevOutputPath = `${stage.name}::output`;
15555
15664
  }
15556
15665
  return g;
@@ -15568,38 +15677,41 @@ function feedback(graph, condition, reentry, opts) {
15568
15677
  graph.add(counterName, counter);
15569
15678
  const condNode = graph.resolve(condition);
15570
15679
  const reentryNode = graph.resolve(reentry);
15571
- let tornDown = false;
15572
- let unsubCounter = null;
15573
- const safeUnsub = () => {
15574
- if (tornDown) return;
15575
- tornDown = true;
15576
- unsub();
15577
- unsubCounter?.();
15578
- };
15579
- const unsub = condNode.subscribe((msgs) => {
15580
- for (const msg of msgs) {
15581
- if (msg[0] === DATA) {
15680
+ const feedbackEffectName = `__feedback_effect_${condition}`;
15681
+ const feedbackEffect = node([condNode], void 0, {
15682
+ name: feedbackEffectName,
15683
+ describeKind: "effect",
15684
+ meta: {
15685
+ ...baseMeta("feedback_effect", {
15686
+ feedbackFrom: condition,
15687
+ feedbackTo: reentry
15688
+ }),
15689
+ _internal: true
15690
+ },
15691
+ onMessage(msg, _depIndex, _actions) {
15692
+ const t = msg[0];
15693
+ if (t === DATA) {
15582
15694
  const currentCount = counter.get();
15583
- if (currentCount >= maxIter) continue;
15695
+ if (currentCount >= maxIter) return true;
15584
15696
  const condValue = msg[1];
15585
- if (condValue == null) continue;
15586
- counter.down([[DATA, currentCount + 1]]);
15587
- reentryNode.down([[DATA, condValue]]);
15588
- } else if (msg[0] === COMPLETE || msg[0] === ERROR) {
15589
- const terminal = msg[0] === ERROR && msg.length > 1 ? [ERROR, msg[1]] : [msg[0]];
15590
- counter.down([terminal]);
15591
- safeUnsub();
15697
+ if (condValue == null) return true;
15698
+ batch(() => {
15699
+ counter.down([[DATA, currentCount + 1]]);
15700
+ reentryNode.down([[DATA, condValue]]);
15701
+ });
15702
+ return true;
15592
15703
  }
15593
- }
15594
- });
15595
- unsubCounter = counter.subscribe((msgs) => {
15596
- for (const msg of msgs) {
15597
- if (msg[0] === COMPLETE || msg[0] === ERROR) {
15598
- safeUnsub();
15599
- return;
15704
+ if (t === COMPLETE || t === ERROR) {
15705
+ const terminal = t === ERROR && msg.length > 1 ? [ERROR, msg[1]] : [t];
15706
+ counter.down([terminal]);
15707
+ return true;
15600
15708
  }
15709
+ return false;
15601
15710
  }
15602
15711
  });
15712
+ graph.add(feedbackEffectName, feedbackEffect);
15713
+ graph.connect(condition, feedbackEffectName);
15714
+ keepalive4(feedbackEffect);
15603
15715
  return graph;
15604
15716
  }
15605
15717
  function budgetGate(source, constraints, opts) {
@@ -15615,7 +15727,8 @@ function budgetGate(source, constraints, opts) {
15615
15727
  }
15616
15728
  function flushBuffer(actions) {
15617
15729
  while (buffer2.length > 0 && checkBudget()) {
15618
- const item = buffer2.shift();
15730
+ const item = buffer2[0];
15731
+ buffer2 = buffer2.slice(1);
15619
15732
  actions.emit(item);
15620
15733
  }
15621
15734
  if (buffer2.length === 0 && pendingResolved) {
@@ -15733,7 +15846,600 @@ function scorer(sources, weights, opts) {
15733
15846
  );
15734
15847
  }
15735
15848
 
15849
+ // src/patterns/domain-templates.ts
15850
+ function keepalive5(n) {
15851
+ return n.subscribe(() => {
15852
+ });
15853
+ }
15854
+ function baseMeta2(kind, extra) {
15855
+ return { domain_template: true, template_type: kind, ...extra ?? {} };
15856
+ }
15857
+ function observabilityGraph(name, opts) {
15858
+ const g = new Graph(name, opts);
15859
+ g.add("source", opts.source);
15860
+ const defaultBranches = [
15861
+ { name: "errors", classify: (v) => isTagged(v, "error") },
15862
+ { name: "traces", classify: (v) => isTagged(v, "trace") },
15863
+ { name: "metrics", classify: (v) => isTagged(v, "metric") }
15864
+ ];
15865
+ const branches = opts.branches ?? defaultBranches;
15866
+ const rules = branches.map((b) => ({
15867
+ name: b.name,
15868
+ classify: b.classify
15869
+ }));
15870
+ const strat = stratify("stratify", opts.source, rules);
15871
+ g.mount("stratify", strat);
15872
+ const branchNodes = branches.map((b) => {
15873
+ try {
15874
+ return g.resolve(`stratify::branch/${b.name}`);
15875
+ } catch {
15876
+ return state(null);
15877
+ }
15878
+ });
15879
+ const correlateFn = opts.correlate ?? ((vals) => vals);
15880
+ const correlateNode = derived(
15881
+ branchNodes,
15882
+ (vals) => correlateFn(vals),
15883
+ {
15884
+ meta: baseMeta2("observability", { stage: "correlate" })
15885
+ }
15886
+ );
15887
+ g.add("correlate", correlateNode);
15888
+ for (const b of branches) {
15889
+ try {
15890
+ g.connect(`stratify::branch/${b.name}`, "correlate");
15891
+ } catch {
15892
+ }
15893
+ }
15894
+ const sloCheckFn = opts.sloCheck ?? (() => ({ pass: true }));
15895
+ const sloValue = derived([correlateNode], (vals) => vals[0], {
15896
+ meta: baseMeta2("observability", { stage: "slo_value" })
15897
+ });
15898
+ const sloVerified = derived([sloValue], (vals) => sloCheckFn(vals[0]), {
15899
+ meta: baseMeta2("observability", { stage: "slo_verified" })
15900
+ });
15901
+ g.add("slo_value", sloValue);
15902
+ g.add("slo_verified", sloVerified);
15903
+ g.connect("correlate", "slo_value");
15904
+ g.connect("slo_value", "slo_verified");
15905
+ const weightValues = opts.weights ?? branches.map(() => 1);
15906
+ const signalNodes = branchNodes.map(
15907
+ (bn) => derived([bn], (vals) => vals[0] != null ? 1 : 0)
15908
+ );
15909
+ const weightNodes = weightValues.map((w) => state(w));
15910
+ for (let i = 0; i < signalNodes.length; i++) {
15911
+ g.add(`__signal_${i}`, signalNodes[i]);
15912
+ g.add(`__weight_${i}`, weightNodes[i]);
15913
+ }
15914
+ const alerts = scorer(
15915
+ signalNodes,
15916
+ weightNodes
15917
+ );
15918
+ g.add("alerts", alerts);
15919
+ const output = derived(
15920
+ [alerts, sloVerified],
15921
+ (vals) => ({
15922
+ scored: vals[0],
15923
+ slo: vals[1]
15924
+ }),
15925
+ {
15926
+ meta: baseMeta2("observability", { stage: "output" })
15927
+ }
15928
+ );
15929
+ g.add("output", output);
15930
+ g.connect("alerts", "output");
15931
+ g.connect("slo_verified", "output");
15932
+ const fbReentry = state(null, {
15933
+ meta: baseMeta2("observability", { stage: "feedback_reentry" })
15934
+ });
15935
+ g.add("feedback_reentry", fbReentry);
15936
+ const fbCondition = derived(
15937
+ [sloVerified],
15938
+ (vals) => {
15939
+ const result = vals[0];
15940
+ if (result && result.pass === false) return result;
15941
+ return null;
15942
+ },
15943
+ {
15944
+ meta: baseMeta2("observability", { stage: "feedback_condition" })
15945
+ }
15946
+ );
15947
+ g.add("feedback_condition", fbCondition);
15948
+ g.connect("slo_verified", "feedback_condition");
15949
+ feedback(g, "feedback_condition", "feedback_reentry", {
15950
+ maxIterations: opts.maxFeedbackIterations ?? 5
15951
+ });
15952
+ return g;
15953
+ }
15954
+ function issueTrackerGraph(name, opts) {
15955
+ const g = new Graph(name, opts);
15956
+ g.add("source", opts.source);
15957
+ let _issueCounter = 0;
15958
+ const defaultExtract = (raw) => ({
15959
+ id: `issue-${++_issueCounter}`,
15960
+ title: String(raw),
15961
+ severity: 1,
15962
+ source: "unknown",
15963
+ raw
15964
+ });
15965
+ const extractFn = opts.extract ?? defaultExtract;
15966
+ const extractNode = derived([opts.source], (vals) => extractFn(vals[0]), {
15967
+ meta: baseMeta2("issue_tracker", { stage: "extract" })
15968
+ });
15969
+ g.add("extract", extractNode);
15970
+ g.connect("source", "extract");
15971
+ const verifyFn = opts.verify ?? (() => ({ valid: true }));
15972
+ const verifyNode = derived(
15973
+ [extractNode],
15974
+ (vals) => {
15975
+ const issue = vals[0];
15976
+ return { issue, verification: verifyFn(issue) };
15977
+ },
15978
+ {
15979
+ meta: baseMeta2("issue_tracker", { stage: "verify" })
15980
+ }
15981
+ );
15982
+ g.add("verify", verifyNode);
15983
+ g.connect("extract", "verify");
15984
+ const knownPatterns = state([], {
15985
+ meta: baseMeta2("issue_tracker", { stage: "known_patterns" })
15986
+ });
15987
+ g.add("known_patterns", knownPatterns);
15988
+ const detectFn = opts.detectRegression ?? (() => ({ regression: false }));
15989
+ const regressionNode = derived(
15990
+ [extractNode, knownPatterns],
15991
+ (vals) => {
15992
+ const issue = vals[0];
15993
+ const known = vals[1];
15994
+ return { issue, regression: detectFn(issue, known) };
15995
+ },
15996
+ { meta: baseMeta2("issue_tracker", { stage: "regression" }) }
15997
+ );
15998
+ g.add("regression", regressionNode);
15999
+ g.connect("extract", "regression");
16000
+ g.connect("known_patterns", "regression");
16001
+ const severitySignal = derived([extractNode], (vals) => {
16002
+ const issue = vals[0];
16003
+ return issue?.severity ?? 0;
16004
+ });
16005
+ const regressionSignal = derived([regressionNode], (vals) => {
16006
+ const r = vals[0];
16007
+ return r?.regression ? 2 : 0;
16008
+ });
16009
+ g.add("__severity_signal", severitySignal);
16010
+ g.add("__regression_signal", regressionSignal);
16011
+ const severityWeight = state(1);
16012
+ const regressionWeight = state(1.5);
16013
+ g.add("__severity_weight", severityWeight);
16014
+ g.add("__regression_weight", regressionWeight);
16015
+ const priority = scorer([severitySignal, regressionSignal], [severityWeight, regressionWeight]);
16016
+ g.add("priority", priority);
16017
+ const output = derived(
16018
+ [verifyNode, regressionNode, priority],
16019
+ (vals) => ({
16020
+ verified: vals[0],
16021
+ regression: vals[1],
16022
+ priority: vals[2]
16023
+ }),
16024
+ { meta: baseMeta2("issue_tracker", { stage: "output" }) }
16025
+ );
16026
+ g.add("output", output);
16027
+ g.connect("verify", "output");
16028
+ g.connect("regression", "output");
16029
+ g.connect("priority", "output");
16030
+ const fbReentry = state(null, {
16031
+ meta: baseMeta2("issue_tracker", { stage: "feedback_reentry" })
16032
+ });
16033
+ g.add("feedback_reentry", fbReentry);
16034
+ const fbCondition = derived(
16035
+ [verifyNode],
16036
+ (vals) => {
16037
+ const result = vals[0];
16038
+ if (result) {
16039
+ const v = result.verification;
16040
+ if (v && v.valid === false) return result;
16041
+ }
16042
+ return null;
16043
+ },
16044
+ {
16045
+ meta: baseMeta2("issue_tracker", { stage: "feedback_condition" })
16046
+ }
16047
+ );
16048
+ g.add("feedback_condition", fbCondition);
16049
+ g.connect("verify", "feedback_condition");
16050
+ feedback(g, "feedback_condition", "feedback_reentry", {
16051
+ maxIterations: opts.maxFeedbackIterations ?? 3
16052
+ });
16053
+ return g;
16054
+ }
16055
+ function contentModerationGraph(name, opts) {
16056
+ const g = new Graph(name, opts);
16057
+ g.add("source", opts.source);
16058
+ const defaultClassify = (content) => ({
16059
+ label: "review",
16060
+ confidence: 0.5,
16061
+ original: content
16062
+ });
16063
+ const classifyFn = opts.classify ?? defaultClassify;
16064
+ const classifyNode = derived([opts.source], (vals) => classifyFn(vals[0]), {
16065
+ meta: baseMeta2("content_moderation", { stage: "classify" })
16066
+ });
16067
+ g.add("classify", classifyNode);
16068
+ g.connect("source", "classify");
16069
+ const strat = stratify("stratify", classifyNode, [
16070
+ { name: "safe", classify: (v) => v.label === "safe" },
16071
+ { name: "review", classify: (v) => v.label === "review" },
16072
+ { name: "block", classify: (v) => v.label === "block" }
16073
+ ]);
16074
+ g.mount("stratify", strat);
16075
+ const reviewLog = reactiveLog([], {
16076
+ name: "review_queue",
16077
+ maxSize: opts.maxQueueSize
16078
+ });
16079
+ g.add("review_queue", reviewLog.entries);
16080
+ let reviewBranch;
16081
+ try {
16082
+ reviewBranch = g.resolve("stratify::branch/review");
16083
+ } catch {
16084
+ reviewBranch = state(null);
16085
+ g.add("__review_fallback", reviewBranch);
16086
+ }
16087
+ const reviewAccumulator = effect([reviewBranch], (vals) => {
16088
+ const item = vals[0];
16089
+ if (item) {
16090
+ reviewLog.append(item);
16091
+ }
16092
+ });
16093
+ g.add("__review_accumulator", reviewAccumulator);
16094
+ keepalive5(reviewAccumulator);
16095
+ try {
16096
+ g.connect("stratify::branch/review", "__review_accumulator");
16097
+ } catch {
16098
+ }
16099
+ const policy2 = state(
16100
+ {},
16101
+ {
16102
+ meta: baseMeta2("content_moderation", {
16103
+ stage: "policy",
16104
+ access: "both",
16105
+ description: "Moderation policy rules \u2014 updated via feedback"
16106
+ })
16107
+ }
16108
+ );
16109
+ g.add("policy", policy2);
16110
+ const weights = opts.weights ?? [0.1, 1, 2];
16111
+ const confidenceSignal = derived([classifyNode], (vals) => {
16112
+ const r = vals[0];
16113
+ return r?.confidence ?? 0;
16114
+ });
16115
+ const severitySignal = derived([classifyNode], (vals) => {
16116
+ const r = vals[0];
16117
+ if (!r) return 0;
16118
+ return r.label === "block" ? weights[2] : r.label === "review" ? weights[1] : weights[0];
16119
+ });
16120
+ g.add("__confidence_signal", confidenceSignal);
16121
+ g.add("__severity_signal", severitySignal);
16122
+ const wConfidence = state(1);
16123
+ const wSeverity = state(1);
16124
+ g.add("__w_confidence", wConfidence);
16125
+ g.add("__w_severity", wSeverity);
16126
+ const priority = scorer([confidenceSignal, severitySignal], [wConfidence, wSeverity]);
16127
+ g.add("priority", priority);
16128
+ const output = derived(
16129
+ [classifyNode, priority],
16130
+ (vals) => ({
16131
+ classification: vals[0],
16132
+ priority: vals[1]
16133
+ }),
16134
+ { meta: baseMeta2("content_moderation", { stage: "output" }) }
16135
+ );
16136
+ g.add("output", output);
16137
+ g.connect("classify", "output");
16138
+ g.connect("priority", "output");
16139
+ const fbCondition = derived(
16140
+ [reviewLog.entries, policy2],
16141
+ (vals) => {
16142
+ const snap = vals[0];
16143
+ const entries = snap?.value?.entries;
16144
+ if (entries && entries.length > 0) {
16145
+ const latest = entries[entries.length - 1];
16146
+ if (latest && latest.falsePositive) {
16147
+ return latest;
16148
+ }
16149
+ }
16150
+ return null;
16151
+ },
16152
+ {
16153
+ meta: baseMeta2("content_moderation", { stage: "feedback_condition" })
16154
+ }
16155
+ );
16156
+ g.add("feedback_condition", fbCondition);
16157
+ feedback(g, "feedback_condition", "policy", {
16158
+ maxIterations: opts.maxFeedbackIterations ?? 5
16159
+ });
16160
+ return g;
16161
+ }
16162
+ function dataQualityGraph(name, opts) {
16163
+ const g = new Graph(name, opts);
16164
+ g.add("source", opts.source);
16165
+ const validateFn = opts.validate ?? ((record) => ({
16166
+ valid: true,
16167
+ errors: [],
16168
+ record
16169
+ }));
16170
+ const validateNode = derived(
16171
+ [opts.source],
16172
+ (vals) => vals[0] != null ? validateFn(vals[0]) : void 0,
16173
+ { meta: baseMeta2("data_quality", { stage: "validate" }) }
16174
+ );
16175
+ g.add("validate", validateNode);
16176
+ g.connect("source", "validate");
16177
+ const detectAnomalyFn = opts.detectAnomaly ?? ((record) => ({
16178
+ anomaly: false,
16179
+ score: 0,
16180
+ record
16181
+ }));
16182
+ const anomalyNode = derived(
16183
+ [opts.source],
16184
+ (vals) => vals[0] != null ? detectAnomalyFn(vals[0]) : void 0,
16185
+ { meta: baseMeta2("data_quality", { stage: "anomaly" }) }
16186
+ );
16187
+ g.add("anomaly", anomalyNode);
16188
+ g.connect("source", "anomaly");
16189
+ const baseline = state(null, {
16190
+ meta: baseMeta2("data_quality", {
16191
+ stage: "baseline",
16192
+ description: "Rolling baseline for drift detection"
16193
+ })
16194
+ });
16195
+ g.add("baseline", baseline);
16196
+ const baselineUpdater = effect([validateNode], (vals) => {
16197
+ const result = vals[0];
16198
+ if (result?.valid) {
16199
+ batch(() => {
16200
+ baseline.down([[DATA, result.record]]);
16201
+ });
16202
+ }
16203
+ });
16204
+ g.add("__baseline_updater", baselineUpdater);
16205
+ g.connect("validate", "__baseline_updater");
16206
+ keepalive5(baselineUpdater);
16207
+ const detectDriftFn = opts.detectDrift ?? (() => ({ drift: false }));
16208
+ const driftNode = derived(
16209
+ [opts.source, baseline],
16210
+ (vals) => detectDriftFn(vals[0], vals[1]),
16211
+ { meta: baseMeta2("data_quality", { stage: "drift" }) }
16212
+ );
16213
+ g.add("drift", driftNode);
16214
+ g.connect("source", "drift");
16215
+ g.connect("baseline", "drift");
16216
+ const suggestFn = opts.suggest ?? (() => null);
16217
+ const remediateNode = derived(
16218
+ [validateNode, anomalyNode],
16219
+ (vals) => suggestFn({
16220
+ validation: vals[0],
16221
+ anomaly: vals[1]
16222
+ }),
16223
+ { meta: baseMeta2("data_quality", { stage: "remediate" }) }
16224
+ );
16225
+ g.add("remediate", remediateNode);
16226
+ g.connect("validate", "remediate");
16227
+ g.connect("anomaly", "remediate");
16228
+ const output = derived(
16229
+ [validateNode, anomalyNode, driftNode, remediateNode],
16230
+ (vals) => ({
16231
+ validation: vals[0],
16232
+ anomaly: vals[1],
16233
+ drift: vals[2],
16234
+ remediation: vals[3]
16235
+ }),
16236
+ { meta: baseMeta2("data_quality", { stage: "output" }) }
16237
+ );
16238
+ g.add("output", output);
16239
+ g.connect("validate", "output");
16240
+ g.connect("anomaly", "output");
16241
+ g.connect("drift", "output");
16242
+ g.connect("remediate", "output");
16243
+ const validationRules = state([], {
16244
+ meta: baseMeta2("data_quality", { stage: "validation_rules" })
16245
+ });
16246
+ g.add("validation_rules", validationRules);
16247
+ const fbCondition = derived(
16248
+ [anomalyNode],
16249
+ (vals) => {
16250
+ const a = vals[0];
16251
+ if (a?.anomaly) return a;
16252
+ return null;
16253
+ },
16254
+ {
16255
+ meta: baseMeta2("data_quality", { stage: "feedback_condition" })
16256
+ }
16257
+ );
16258
+ g.add("feedback_condition", fbCondition);
16259
+ g.connect("anomaly", "feedback_condition");
16260
+ feedback(g, "feedback_condition", "validation_rules", {
16261
+ maxIterations: opts.maxFeedbackIterations ?? 3
16262
+ });
16263
+ return g;
16264
+ }
16265
+ function isTagged(value, tag) {
16266
+ if (value == null || typeof value !== "object") return false;
16267
+ const v = value;
16268
+ return v.type === tag || v.kind === tag;
16269
+ }
16270
+
15736
16271
  // src/patterns/graphspec.ts
16272
+ var graphspec_exports = {};
16273
+ __export(graphspec_exports, {
16274
+ compileSpec: () => compileSpec,
16275
+ decompileGraph: () => decompileGraph,
16276
+ extractFnFactory: () => extractFnFactory,
16277
+ extractSourceFactory: () => extractSourceFactory,
16278
+ generateCatalogPrompt: () => generateCatalogPrompt,
16279
+ isRichFnEntry: () => isRichFnEntry,
16280
+ isRichSourceEntry: () => isRichSourceEntry,
16281
+ llmCompose: () => llmCompose,
16282
+ llmRefine: () => llmRefine,
16283
+ specDiff: () => specDiff,
16284
+ validateSpec: () => validateSpec,
16285
+ validateSpecAgainstCatalog: () => validateSpecAgainstCatalog
16286
+ });
16287
+ function isRichFnEntry(entry) {
16288
+ return typeof entry === "object" && entry !== null && "factory" in entry;
16289
+ }
16290
+ function isRichSourceEntry(entry) {
16291
+ return typeof entry === "object" && entry !== null && "factory" in entry;
16292
+ }
16293
+ function extractFnFactory(entry) {
16294
+ return isRichFnEntry(entry) ? entry.factory : entry;
16295
+ }
16296
+ function extractSourceFactory(entry) {
16297
+ return isRichSourceEntry(entry) ? entry.factory : entry;
16298
+ }
16299
+ function generateCatalogPrompt(catalog) {
16300
+ const sections = [];
16301
+ if (catalog.fns) {
16302
+ const groups = /* @__PURE__ */ new Map();
16303
+ for (const [name, entry] of Object.entries(catalog.fns)) {
16304
+ const tag = isRichFnEntry(entry) ? entry.tags?.[0] ?? "Other" : "Other";
16305
+ if (!groups.has(tag)) groups.set(tag, []);
16306
+ groups.get(tag).push(formatFnEntry(name, entry));
16307
+ }
16308
+ for (const [tag, lines] of groups) {
16309
+ sections.push(`${tag}:
16310
+ ${lines.join("\n")}`);
16311
+ }
16312
+ }
16313
+ if (catalog.sources) {
16314
+ const lines = [];
16315
+ for (const [name, entry] of Object.entries(catalog.sources)) {
16316
+ lines.push(formatSourceEntry(name, entry));
16317
+ }
16318
+ if (lines.length > 0) {
16319
+ sections.push(`Sources:
16320
+ ${lines.join("\n")}`);
16321
+ }
16322
+ }
16323
+ return sections.join("\n\n");
16324
+ }
16325
+ function formatFnEntry(name, entry) {
16326
+ if (!isRichFnEntry(entry)) return `- ${name}`;
16327
+ let line = `- ${name}: ${entry.description}`;
16328
+ if (entry.configSchema) {
16329
+ const fields = Object.entries(entry.configSchema).map(([k, v]) => {
16330
+ let desc = `${k}: ${v.type}`;
16331
+ if (v.enum) desc += ` (${v.enum.join("|")})`;
16332
+ if (v.required === false) desc += "?";
16333
+ return desc;
16334
+ });
16335
+ line += `. Config: { ${fields.join(", ")} }`;
16336
+ }
16337
+ return line;
16338
+ }
16339
+ function formatSourceEntry(name, entry) {
16340
+ if (!isRichSourceEntry(entry)) return `- ${name}`;
16341
+ let line = `- ${name}: ${entry.description}`;
16342
+ if (entry.configSchema) {
16343
+ const fields = Object.entries(entry.configSchema).map(([k, v]) => {
16344
+ let desc = `${k}: ${v.type}`;
16345
+ if (v.required === false) desc += "?";
16346
+ return desc;
16347
+ });
16348
+ line += `. Config: { ${fields.join(", ")} }`;
16349
+ }
16350
+ return line;
16351
+ }
16352
+ function validateSpecAgainstCatalog(spec, catalog) {
16353
+ const errors = [];
16354
+ const fnNames = new Set(Object.keys(catalog.fns ?? {}));
16355
+ const sourceNames = new Set(Object.keys(catalog.sources ?? {}));
16356
+ for (const [nodeName, nodeRaw] of Object.entries(spec.nodes)) {
16357
+ if (nodeRaw.type === "template") continue;
16358
+ const node2 = nodeRaw;
16359
+ if (node2.fn && fnNames.size > 0 && !fnNames.has(node2.fn)) {
16360
+ if (sourceNames.has(node2.fn)) {
16361
+ errors.push(
16362
+ `Node "${nodeName}": fn "${node2.fn}" is a source, not a function. Use it as a producer source instead, or use a function from: ${[...fnNames].join(", ")}`
16363
+ );
16364
+ } else {
16365
+ const suggestion = findClosest(node2.fn, fnNames);
16366
+ errors.push(
16367
+ `Node "${nodeName}": fn "${node2.fn}" not found in catalog` + (suggestion ? `. Did you mean "${suggestion}"?` : "")
16368
+ );
16369
+ }
16370
+ }
16371
+ if (node2.source && sourceNames.size > 0 && !sourceNames.has(node2.source)) {
16372
+ if (fnNames.has(node2.source)) {
16373
+ errors.push(
16374
+ `Node "${nodeName}": source "${node2.source}" is a function, not a source. Use it as fn instead, or use a source from: ${[...sourceNames].join(", ")}`
16375
+ );
16376
+ } else {
16377
+ const suggestion = findClosest(node2.source, sourceNames);
16378
+ errors.push(
16379
+ `Node "${nodeName}": source "${node2.source}" not found in catalog` + (suggestion ? `. Did you mean "${suggestion}"?` : "")
16380
+ );
16381
+ }
16382
+ }
16383
+ if (node2.fn && node2.config && catalog.fns?.[node2.fn]) {
16384
+ const entry = catalog.fns[node2.fn];
16385
+ if (isRichFnEntry(entry) && entry.configSchema) {
16386
+ for (const [field, schema] of Object.entries(entry.configSchema)) {
16387
+ if (schema.required !== false && !(field in node2.config)) {
16388
+ errors.push(`Node "${nodeName}": config missing required field "${field}"`);
16389
+ }
16390
+ if (field in node2.config && schema.enum) {
16391
+ const val = node2.config[field];
16392
+ if (!schema.enum.includes(val)) {
16393
+ errors.push(
16394
+ `Node "${nodeName}": config.${field} = ${JSON.stringify(val)}, expected one of: ${schema.enum.join(", ")}`
16395
+ );
16396
+ }
16397
+ }
16398
+ }
16399
+ }
16400
+ }
16401
+ }
16402
+ if (spec.templates) {
16403
+ for (const [tName, template] of Object.entries(spec.templates)) {
16404
+ for (const [nodeName, node2] of Object.entries(template.nodes)) {
16405
+ if (node2.fn && fnNames.size > 0 && !fnNames.has(node2.fn)) {
16406
+ const suggestion = findClosest(node2.fn, fnNames);
16407
+ errors.push(
16408
+ `Template "${tName}" node "${nodeName}": fn "${node2.fn}" not found in catalog` + (suggestion ? `. Did you mean "${suggestion}"?` : "")
16409
+ );
16410
+ }
16411
+ }
16412
+ }
16413
+ }
16414
+ return { valid: errors.length === 0, errors };
16415
+ }
16416
+ function findClosest(input, candidates) {
16417
+ let best = null;
16418
+ let bestDist = Infinity;
16419
+ const lower = input.toLowerCase();
16420
+ for (const c of candidates) {
16421
+ const dist = levenshtein(lower, c.toLowerCase());
16422
+ if (dist < bestDist && dist <= Math.max(3, Math.floor(input.length / 2))) {
16423
+ bestDist = dist;
16424
+ best = c;
16425
+ }
16426
+ }
16427
+ return best;
16428
+ }
16429
+ function levenshtein(a, b) {
16430
+ const m = a.length;
16431
+ const n = b.length;
16432
+ const dp = Array.from(
16433
+ { length: m + 1 },
16434
+ (_, i) => Array.from({ length: n + 1 }, (_2, j) => i === 0 ? j : j === 0 ? i : 0)
16435
+ );
16436
+ for (let i = 1; i <= m; i++) {
16437
+ for (let j = 1; j <= n; j++) {
16438
+ dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
16439
+ }
16440
+ }
16441
+ return dp[m][n];
16442
+ }
15737
16443
  var VALID_NODE_TYPES2 = /* @__PURE__ */ new Set([
15738
16444
  "state",
15739
16445
  "producer",
@@ -15910,6 +16616,21 @@ ${validation.errors.join("\n")}`);
15910
16616
  const catalog = opts?.catalog ?? {};
15911
16617
  const g = new Graph(spec.name);
15912
16618
  const templates = spec.templates ?? {};
16619
+ const catalogValidation = validateSpecAgainstCatalog(spec, catalog);
16620
+ if (!catalogValidation.valid) {
16621
+ throw new Error(
16622
+ `compileSpec: catalog validation errors:
16623
+ ${catalogValidation.errors.join("\n")}`
16624
+ );
16625
+ }
16626
+ const resolveFn = (fnName) => {
16627
+ const entry = catalog.fns?.[fnName];
16628
+ return entry ? extractFnFactory(entry) : void 0;
16629
+ };
16630
+ const resolveSource = (sourceName) => {
16631
+ const entry = catalog.sources?.[sourceName];
16632
+ return entry ? extractSourceFactory(entry) : void 0;
16633
+ };
15913
16634
  const created = /* @__PURE__ */ new Map();
15914
16635
  const deferred = [];
15915
16636
  for (const [name, raw] of Object.entries(spec.nodes)) {
@@ -15923,8 +16644,8 @@ ${validation.errors.join("\n")}`);
15923
16644
  g.add(name, nd);
15924
16645
  created.set(name, nd);
15925
16646
  } else if (n.type === "producer") {
15926
- const sourceFactory = n.source ? catalog.sources?.[n.source] : void 0;
15927
- const fnFactory = n.fn ? catalog.fns?.[n.fn] : void 0;
16647
+ const sourceFactory = n.source ? resolveSource(n.source) : void 0;
16648
+ const fnFactory = n.fn ? resolveFn(n.fn) : void 0;
15928
16649
  if (sourceFactory) {
15929
16650
  const nd = sourceFactory(n.config ?? {});
15930
16651
  g.add(name, nd);
@@ -15954,7 +16675,7 @@ ${validation.errors.join("\n")}`);
15954
16675
  const deps = n.deps ?? [];
15955
16676
  if (!deps.every((dep) => created.has(dep))) continue;
15956
16677
  const resolvedDeps = deps.map((dep) => created.get(dep));
15957
- const fnFactory = n.fn ? catalog.fns?.[n.fn] : void 0;
16678
+ const fnFactory = n.fn ? resolveFn(n.fn) : void 0;
15958
16679
  let nd;
15959
16680
  if (fnFactory) {
15960
16681
  nd = fnFactory(resolvedDeps, n.config ?? {});
@@ -15997,8 +16718,8 @@ ${validation.errors.join("\n")}`);
15997
16718
  sub.add(nName, nd);
15998
16719
  subCreated.set(nName, nd);
15999
16720
  } else if (nSpec.type === "producer") {
16000
- const sourceFactory = nSpec.source ? catalog.sources?.[nSpec.source] : void 0;
16001
- const fnFactory = nSpec.fn ? catalog.fns?.[nSpec.fn] : void 0;
16721
+ const sourceFactory = nSpec.source ? resolveSource(nSpec.source) : void 0;
16722
+ const fnFactory = nSpec.fn ? resolveFn(nSpec.fn) : void 0;
16002
16723
  if (sourceFactory) {
16003
16724
  const nd = sourceFactory(nSpec.config ?? {});
16004
16725
  sub.add(nName, nd);
@@ -16029,7 +16750,7 @@ ${validation.errors.join("\n")}`);
16029
16750
  const allReady = deps.every((dep) => subCreated.has(dep) || created.has(dep));
16030
16751
  if (!allReady) continue;
16031
16752
  const resolvedDeps = deps.map((dep) => subCreated.get(dep) ?? created.get(dep));
16032
- const fnFactory = nSpec.fn ? catalog.fns?.[nSpec.fn] : void 0;
16753
+ const fnFactory = nSpec.fn ? resolveFn(nSpec.fn) : void 0;
16033
16754
  let nd;
16034
16755
  if (fnFactory) {
16035
16756
  nd = fnFactory(resolvedDeps, nSpec.config ?? {});
@@ -16090,14 +16811,15 @@ var INTERNAL_META_KEYS = /* @__PURE__ */ new Set([
16090
16811
  "_templateName",
16091
16812
  "_templateBind",
16092
16813
  "feedbackFrom",
16093
- "feedbackTo"
16814
+ "feedbackTo",
16815
+ "_internal"
16094
16816
  ]);
16095
16817
  function decompileGraph(graph) {
16096
16818
  const desc = graph.describe({ detail: "standard" });
16097
16819
  const nodes = {};
16098
16820
  const feedbackEdges = [];
16099
16821
  const metaSegment = `::${GRAPH_META_SEGMENT}::`;
16100
- const feedbackCounterPattern = /^__feedback_(.+)$/;
16822
+ const feedbackCounterPattern = /^__feedback_(?!effect_)(.+)$/;
16101
16823
  const feedbackConditions = /* @__PURE__ */ new Set();
16102
16824
  for (const path of Object.keys(desc.nodes)) {
16103
16825
  if (path.includes(metaSegment)) continue;
@@ -16117,6 +16839,9 @@ function decompileGraph(graph) {
16117
16839
  for (const [path, nodeDesc] of Object.entries(desc.nodes)) {
16118
16840
  if (path.includes(metaSegment)) continue;
16119
16841
  if (feedbackCounterPattern.test(path)) continue;
16842
+ if (nodeDesc.meta?._internal) continue;
16843
+ if (path.startsWith("__feedback_effect_")) continue;
16844
+ if (path.startsWith("__bridge_")) continue;
16120
16845
  if (path.includes("::")) continue;
16121
16846
  const specNode = {
16122
16847
  type: nodeDesc.type
@@ -16449,11 +17174,12 @@ function stripFences2(text) {
16449
17174
  }
16450
17175
  async function llmCompose(problem, adapter, opts) {
16451
17176
  let systemPrompt = LLM_COMPOSE_SYSTEM_PROMPT;
16452
- if (opts?.catalogDescription) {
17177
+ const catalogPrompt = opts?.catalogDescription ?? (opts?.catalog ? generateCatalogPrompt(opts.catalog) : void 0);
17178
+ if (catalogPrompt) {
16453
17179
  systemPrompt += `
16454
17180
 
16455
- Available catalog:
16456
- ${opts.catalogDescription}`;
17181
+ Available catalog (use ONLY these names):
17182
+ ${catalogPrompt}`;
16457
17183
  }
16458
17184
  if (opts?.systemPromptExtra) {
16459
17185
  systemPrompt += `
@@ -16485,7 +17211,30 @@ ${opts.systemPromptExtra}`;
16485
17211
  throw new Error(`llmCompose: invalid GraphSpec:
16486
17212
  ${validation.errors.join("\n")}`);
16487
17213
  }
16488
- return parsed;
17214
+ let spec = parsed;
17215
+ if (opts?.catalog) {
17216
+ const maxRefine = opts.maxAutoRefine ?? 0;
17217
+ for (let attempt = 0; attempt <= maxRefine; attempt++) {
17218
+ const catalogValidation = validateSpecAgainstCatalog(spec, opts.catalog);
17219
+ if (catalogValidation.valid) break;
17220
+ if (attempt === maxRefine) {
17221
+ throw new Error(
17222
+ `llmCompose: catalog validation failed after ${maxRefine} refine attempts:
17223
+ ${catalogValidation.errors.join("\n")}`
17224
+ );
17225
+ }
17226
+ spec = await llmRefine(
17227
+ spec,
17228
+ `Fix these catalog errors:
17229
+ ${catalogValidation.errors.join("\n")}
17230
+
17231
+ Use ONLY functions and sources from the catalog.`,
17232
+ adapter,
17233
+ { ...opts, catalogDescription: catalogPrompt }
17234
+ );
17235
+ }
17236
+ }
17237
+ return spec;
16489
17238
  }
16490
17239
  async function llmRefine(currentSpec, feedback2, adapter, opts) {
16491
17240
  let systemPrompt = LLM_COMPOSE_SYSTEM_PROMPT;
@@ -16557,7 +17306,7 @@ function requireNonNegativeInt(value, label) {
16557
17306
  }
16558
17307
  return value;
16559
17308
  }
16560
- function keepalive4(n) {
17309
+ function keepalive6(n) {
16561
17310
  return n.subscribe(() => {
16562
17311
  });
16563
17312
  }
@@ -16593,7 +17342,7 @@ var TopicGraph = class extends Graph {
16593
17342
  );
16594
17343
  this.add("latest", this.latest);
16595
17344
  this.connect("events", "latest");
16596
- this._keepaliveDisposers.push(keepalive4(this.latest));
17345
+ this._keepaliveDisposers.push(keepalive6(this.latest));
16597
17346
  }
16598
17347
  destroy() {
16599
17348
  for (const dispose of this._keepaliveDisposers) dispose();
@@ -16649,8 +17398,8 @@ var SubscriptionGraph = class extends Graph {
16649
17398
  this.connect("topic::events", "source");
16650
17399
  this.connect("source", "available");
16651
17400
  this.connect("cursor", "available");
16652
- this._keepaliveDisposers.push(keepalive4(this.source));
16653
- this._keepaliveDisposers.push(keepalive4(this.available));
17401
+ this._keepaliveDisposers.push(keepalive6(this.source));
17402
+ this._keepaliveDisposers.push(keepalive6(this.available));
16654
17403
  }
16655
17404
  destroy() {
16656
17405
  for (const dispose of this._keepaliveDisposers) dispose();
@@ -16702,7 +17451,7 @@ var JobQueueGraph = class extends Graph {
16702
17451
  );
16703
17452
  this.add("depth", this.depth);
16704
17453
  this.connect("pending", "depth");
16705
- this._keepaliveDisposers.push(keepalive4(this.depth));
17454
+ this._keepaliveDisposers.push(keepalive6(this.depth));
16706
17455
  }
16707
17456
  destroy() {
16708
17457
  for (const dispose of this._keepaliveDisposers) dispose();
@@ -16802,7 +17551,7 @@ var JobFlowGraph = class extends Graph {
16802
17551
  );
16803
17552
  this.add("completedCount", this.completedCount);
16804
17553
  this.connect("completed", "completedCount");
16805
- this._keepaliveDisposers.push(keepalive4(this.completedCount));
17554
+ this._keepaliveDisposers.push(keepalive6(this.completedCount));
16806
17555
  const maxPerPump = Math.max(
16807
17556
  1,
16808
17557
  requireNonNegativeInt(opts.maxPerPump ?? DEFAULT_MAX_PER_PUMP, "job flow maxPerPump")
@@ -16842,7 +17591,7 @@ var JobFlowGraph = class extends Graph {
16842
17591
  );
16843
17592
  this.add(`pump_${stage}`, pump);
16844
17593
  this.connect(`${stage}::pending`, `pump_${stage}`);
16845
- this._keepaliveDisposers.push(keepalive4(pump));
17594
+ this._keepaliveDisposers.push(keepalive6(pump));
16846
17595
  }
16847
17596
  }
16848
17597
  destroy() {
@@ -16914,7 +17663,7 @@ var TopicBridgeGraph = class extends Graph {
16914
17663
  );
16915
17664
  this.add("pump", pump);
16916
17665
  this.connect("subscription::available", "pump");
16917
- this._keepaliveDisposers.push(keepalive4(pump));
17666
+ this._keepaliveDisposers.push(keepalive6(pump));
16918
17667
  }
16919
17668
  destroy() {
16920
17669
  for (const dispose of this._keepaliveDisposers) dispose();
@@ -16984,7 +17733,7 @@ function registerStep(graph, name, step, depPaths) {
16984
17733
  graph.connect(path, name);
16985
17734
  }
16986
17735
  }
16987
- function baseMeta2(kind, meta) {
17736
+ function baseMeta3(kind, meta) {
16988
17737
  return {
16989
17738
  orchestration: true,
16990
17739
  orchestration_type: kind,
@@ -17022,7 +17771,7 @@ function task(graph, name, run, opts) {
17022
17771
  ...nodeOpts,
17023
17772
  name,
17024
17773
  describeKind: "derived",
17025
- meta: baseMeta2("task", opts?.meta)
17774
+ meta: baseMeta3("task", opts?.meta)
17026
17775
  }
17027
17776
  );
17028
17777
  registerStep(
@@ -17045,7 +17794,7 @@ function branch(graph, name, source, predicate, opts) {
17045
17794
  ...opts,
17046
17795
  name,
17047
17796
  describeKind: "derived",
17048
- meta: baseMeta2("branch", opts?.meta)
17797
+ meta: baseMeta3("branch", opts?.meta)
17049
17798
  }
17050
17799
  );
17051
17800
  registerStep(graph, name, step, src.path ? [src.path] : []);
@@ -17068,7 +17817,7 @@ function gate2(graph, name, source, control, opts) {
17068
17817
  ...opts,
17069
17818
  name,
17070
17819
  describeKind: "operator",
17071
- meta: baseMeta2("gate", opts?.meta)
17820
+ meta: baseMeta3("gate", opts?.meta)
17072
17821
  }
17073
17822
  );
17074
17823
  registerStep(
@@ -17096,7 +17845,7 @@ function approval(graph, name, source, approver, opts) {
17096
17845
  ...opts,
17097
17846
  name,
17098
17847
  describeKind: "operator",
17099
- meta: baseMeta2("approval", opts?.meta)
17848
+ meta: baseMeta3("approval", opts?.meta)
17100
17849
  }
17101
17850
  );
17102
17851
  registerStep(
@@ -17115,7 +17864,7 @@ function forEach2(graph, name, source, run, opts) {
17115
17864
  name,
17116
17865
  describeKind: "effect",
17117
17866
  completeWhenDepsComplete: false,
17118
- meta: baseMeta2("forEach", opts?.meta),
17867
+ meta: baseMeta3("forEach", opts?.meta),
17119
17868
  onMessage(msg, depIndex, actions) {
17120
17869
  if (terminated) return true;
17121
17870
  if (depIndex !== 0) {
@@ -17150,7 +17899,7 @@ function join2(graph, name, deps, opts) {
17150
17899
  ...opts,
17151
17900
  name,
17152
17901
  describeKind: "derived",
17153
- meta: baseMeta2("join", opts?.meta)
17902
+ meta: baseMeta3("join", opts?.meta)
17154
17903
  }
17155
17904
  );
17156
17905
  registerStep(
@@ -17181,7 +17930,7 @@ function loop(graph, name, source, iterate, opts) {
17181
17930
  ...opts,
17182
17931
  name,
17183
17932
  describeKind: "derived",
17184
- meta: baseMeta2("loop", opts?.meta)
17933
+ meta: baseMeta3("loop", opts?.meta)
17185
17934
  }
17186
17935
  );
17187
17936
  registerStep(
@@ -17206,7 +17955,7 @@ function sensor(graph, name, initial, opts) {
17206
17955
  name,
17207
17956
  initial,
17208
17957
  describeKind: "producer",
17209
- meta: baseMeta2("sensor", opts?.meta)
17958
+ meta: baseMeta3("sensor", opts?.meta)
17210
17959
  });
17211
17960
  registerStep(graph, name, source, []);
17212
17961
  return {
@@ -17244,7 +17993,7 @@ function wait(graph, name, source, ms, opts) {
17244
17993
  initial: src.node.get(),
17245
17994
  describeKind: "operator",
17246
17995
  completeWhenDepsComplete: false,
17247
- meta: baseMeta2("wait", opts?.meta),
17996
+ meta: baseMeta3("wait", opts?.meta),
17248
17997
  onMessage(msg, depIndex, actions) {
17249
17998
  if (terminated) return true;
17250
17999
  if (depIndex !== 0) {
@@ -17294,7 +18043,7 @@ function onFailure(graph, name, source, recover, opts) {
17294
18043
  name,
17295
18044
  describeKind: "operator",
17296
18045
  completeWhenDepsComplete: false,
17297
- meta: baseMeta2("onFailure", opts?.meta),
18046
+ meta: baseMeta3("onFailure", opts?.meta),
17298
18047
  onMessage(msg, _depIndex, actions) {
17299
18048
  if (terminated) return true;
17300
18049
  if (msg[0] === ERROR) {
@@ -17809,10 +18558,12 @@ function reactiveBlockLayout(opts) {
17809
18558
  var version = "0.0.0";
17810
18559
  // Annotate the CommonJS export names for ESM import in node:
17811
18560
  0 && (module.exports = {
18561
+ CLEANUP_RESULT,
17812
18562
  COMPLETE,
17813
18563
  CircuitOpenError,
17814
18564
  DATA,
17815
18565
  DEFAULT_ACTOR,
18566
+ DEFAULT_DOWN,
17816
18567
  DIRTY,
17817
18568
  DictCheckpointAdapter,
17818
18569
  DynamicNodeImpl,
@@ -17838,6 +18589,7 @@ var version = "0.0.0";
17838
18589
  ai,
17839
18590
  audit,
17840
18591
  batch,
18592
+ bridge,
17841
18593
  buffer,
17842
18594
  bufferCount,
17843
18595
  bufferTime,
@@ -17849,6 +18601,7 @@ var version = "0.0.0";
17849
18601
  checkpointToRedis,
17850
18602
  checkpointToS3,
17851
18603
  circuitBreaker,
18604
+ cleanupResult,
17852
18605
  combine,
17853
18606
  combineLatest,
17854
18607
  compat,
@@ -17873,6 +18626,7 @@ var version = "0.0.0";
17873
18626
  deserializeError,
17874
18627
  distill,
17875
18628
  distinctUntilChanged,
18629
+ domainTemplates,
17876
18630
  dynamicNode,
17877
18631
  effect,
17878
18632
  elementAt,