@graphrefly/graphrefly 0.14.0 → 0.16.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 (71) hide show
  1. package/dist/{chunk-2ZICUAUJ.js → chunk-26A4E7J7.js} +10 -12
  2. package/dist/chunk-26A4E7J7.js.map +1 -0
  3. package/dist/{chunk-CRACCCJY.js → chunk-3BLRREFM.js} +29 -5
  4. package/dist/chunk-3BLRREFM.js.map +1 -0
  5. package/dist/{chunk-XQ4UMAU7.js → chunk-ITDVOCFO.js} +2 -2
  6. package/dist/{chunk-YW6LFCFS.js → chunk-LKP7IWRV.js} +3 -3
  7. package/dist/{chunk-4APC3AFN.js → chunk-RLVFZDCE.js} +22 -49
  8. package/dist/chunk-RLVFZDCE.js.map +1 -0
  9. package/dist/{chunk-GKRKDYNT.js → chunk-RZSQ7P2C.js} +3 -3
  10. package/dist/{chunk-ZHTHUX5D.js → chunk-SHRJH2DN.js} +3 -3
  11. package/dist/{chunk-H243FWYP.js → chunk-VZY2B2LU.js} +1 -1
  12. package/dist/{chunk-H243FWYP.js.map → chunk-VZY2B2LU.js.map} +1 -1
  13. package/dist/{chunk-QVYZD65U.js → chunk-YX263TXI.js} +10 -38
  14. package/dist/chunk-YX263TXI.js.map +1 -0
  15. package/dist/compat/nestjs/index.cjs +38 -41
  16. package/dist/compat/nestjs/index.cjs.map +1 -1
  17. package/dist/compat/nestjs/index.d.cts +4 -4
  18. package/dist/compat/nestjs/index.d.ts +4 -4
  19. package/dist/compat/nestjs/index.js +7 -7
  20. package/dist/core/index.cjs.map +1 -1
  21. package/dist/core/index.d.cts +2 -2
  22. package/dist/core/index.d.ts +2 -2
  23. package/dist/core/index.js +3 -3
  24. package/dist/extra/index.cjs +27 -78
  25. package/dist/extra/index.cjs.map +1 -1
  26. package/dist/extra/index.d.cts +4 -4
  27. package/dist/extra/index.d.ts +4 -4
  28. package/dist/extra/index.js +3 -3
  29. package/dist/graph/index.cjs +26 -2
  30. package/dist/graph/index.cjs.map +1 -1
  31. package/dist/graph/index.d.cts +3 -3
  32. package/dist/graph/index.d.ts +3 -3
  33. package/dist/graph/index.js +4 -4
  34. package/dist/{graph-BXIK5Dq5.d.ts → graph-Dc-P9BVm.d.ts} +15 -3
  35. package/dist/{graph-BhADtuFU.d.cts → graph-fCsaaVIa.d.cts} +15 -3
  36. package/dist/{index-DSp5R3Xq.d.ts → index-BBVBYPxr.d.cts} +4 -4
  37. package/dist/{index-BkToATim.d.ts → index-BR19vQME.d.ts} +1 -1
  38. package/dist/{index-BNB0KjKe.d.ts → index-BmoUvOGN.d.ts} +1 -1
  39. package/dist/{index-DBhLjWSV.d.cts → index-ClaKZFPl.d.cts} +100 -31
  40. package/dist/{index-Dqemj9q0.d.cts → index-DWq0P9T6.d.ts} +4 -4
  41. package/dist/{index-Wa8jXne6.d.cts → index-Db27z6Ki.d.cts} +1 -1
  42. package/dist/{index-fYObbpUw.d.ts → index-DhXznWyH.d.ts} +2 -2
  43. package/dist/{index-DANO9Gg7.d.cts → index-DlGMf_Qe.d.cts} +2 -2
  44. package/dist/{index-CKyYg4IP.d.ts → index-N704txAA.d.ts} +100 -31
  45. package/dist/{index-DKIyo4Bq.d.cts → index-YlOH1Gw6.d.cts} +1 -1
  46. package/dist/index.cjs +185 -224
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.d.cts +35 -39
  49. package/dist/index.d.ts +35 -39
  50. package/dist/index.js +143 -153
  51. package/dist/index.js.map +1 -1
  52. package/dist/{meta-CrZUQAJ6.d.cts → meta-BV4pj9ML.d.cts} +6 -0
  53. package/dist/{meta-CrZUQAJ6.d.ts → meta-BV4pj9ML.d.ts} +6 -0
  54. package/dist/observable-Cz-AWhwR.d.cts +42 -0
  55. package/dist/observable-DCqlwGyl.d.ts +42 -0
  56. package/dist/patterns/reactive-layout/index.cjs +26 -2
  57. package/dist/patterns/reactive-layout/index.cjs.map +1 -1
  58. package/dist/patterns/reactive-layout/index.d.cts +3 -3
  59. package/dist/patterns/reactive-layout/index.d.ts +3 -3
  60. package/dist/patterns/reactive-layout/index.js +4 -4
  61. package/package.json +3 -2
  62. package/dist/chunk-2ZICUAUJ.js.map +0 -1
  63. package/dist/chunk-4APC3AFN.js.map +0 -1
  64. package/dist/chunk-CRACCCJY.js.map +0 -1
  65. package/dist/chunk-QVYZD65U.js.map +0 -1
  66. package/dist/reactive-log-ChbpUrY2.d.cts +0 -137
  67. package/dist/reactive-log-DV--7BWd.d.ts +0 -137
  68. /package/dist/{chunk-XQ4UMAU7.js.map → chunk-ITDVOCFO.js.map} +0 -0
  69. /package/dist/{chunk-YW6LFCFS.js.map → chunk-LKP7IWRV.js.map} +0 -0
  70. /package/dist/{chunk-GKRKDYNT.js.map → chunk-RZSQ7P2C.js.map} +0 -0
  71. /package/dist/{chunk-ZHTHUX5D.js.map → chunk-SHRJH2DN.js.map} +0 -0
package/dist/index.js CHANGED
@@ -137,11 +137,24 @@ import {
137
137
  workerBridge,
138
138
  workerSelf,
139
139
  zip
140
- } from "./chunk-4APC3AFN.js";
140
+ } from "./chunk-RLVFZDCE.js";
141
141
  import {
142
142
  cqrs_exports,
143
143
  nestjs_exports
144
- } from "./chunk-2ZICUAUJ.js";
144
+ } from "./chunk-26A4E7J7.js";
145
+ import {
146
+ DEFAULT_DOWN,
147
+ bridge,
148
+ core_exports
149
+ } from "./chunk-LKP7IWRV.js";
150
+ import {
151
+ JsonCodec,
152
+ createDagCborCodec,
153
+ createDagCborZstdCodec,
154
+ graph_exports,
155
+ negotiateCodec,
156
+ replayWAL
157
+ } from "./chunk-SHRJH2DN.js";
145
158
  import {
146
159
  cached,
147
160
  createWatermarkController,
@@ -174,20 +187,7 @@ import {
174
187
  toArray,
175
188
  toMessages$,
176
189
  toObservable
177
- } from "./chunk-QVYZD65U.js";
178
- import {
179
- JsonCodec,
180
- createDagCborCodec,
181
- createDagCborZstdCodec,
182
- graph_exports,
183
- negotiateCodec,
184
- replayWAL
185
- } from "./chunk-ZHTHUX5D.js";
186
- import {
187
- DEFAULT_DOWN,
188
- bridge,
189
- core_exports
190
- } from "./chunk-YW6LFCFS.js";
190
+ } from "./chunk-YX263TXI.js";
191
191
  import {
192
192
  ResettableTimer
193
193
  } from "./chunk-WZ2Z2CRV.js";
@@ -195,17 +195,17 @@ import {
195
195
  analyzeAndMeasure,
196
196
  computeLineBreaks,
197
197
  reactive_layout_exports
198
- } from "./chunk-GKRKDYNT.js";
198
+ } from "./chunk-RZSQ7P2C.js";
199
199
  import {
200
200
  GRAPH_META_SEGMENT,
201
201
  Graph,
202
202
  reachable
203
- } from "./chunk-CRACCCJY.js";
203
+ } from "./chunk-3BLRREFM.js";
204
204
  import {
205
205
  describeNode,
206
206
  metaSnapshot,
207
207
  resolveDescribeFields
208
- } from "./chunk-XQ4UMAU7.js";
208
+ } from "./chunk-ITDVOCFO.js";
209
209
  import {
210
210
  CLEANUP_RESULT,
211
211
  COMPLETE,
@@ -249,7 +249,7 @@ import {
249
249
  propagatesToMeta,
250
250
  state,
251
251
  wallClockNs
252
- } from "./chunk-H243FWYP.js";
252
+ } from "./chunk-VZY2B2LU.js";
253
253
 
254
254
  // src/compat/index.ts
255
255
  var compat_exports = {};
@@ -1607,7 +1607,9 @@ function promptNode(adapter, deps, prompt, opts) {
1607
1607
  const messagesNode = derived(
1608
1608
  deps,
1609
1609
  (values) => {
1610
+ if (values.some((v) => v == null)) return [];
1610
1611
  const text = typeof prompt === "string" ? prompt : prompt(...values);
1612
+ if (!text) return [];
1611
1613
  const msgs = [];
1612
1614
  if (opts?.systemPrompt) msgs.push({ role: "system", content: opts.systemPrompt });
1613
1615
  msgs.push({ role: "user", content: text });
@@ -1663,7 +1665,6 @@ function promptNode(adapter, deps, prompt, opts) {
1663
1665
  }
1664
1666
  var ChatStreamGraph = class extends Graph {
1665
1667
  _log;
1666
- _keepaliveSubs = [];
1667
1668
  messages;
1668
1669
  latest;
1669
1670
  messageCount;
@@ -1678,7 +1679,7 @@ var ChatStreamGraph = class extends Graph {
1678
1679
  this.latest = derived(
1679
1680
  [this.messages],
1680
1681
  ([snapshot]) => {
1681
- const entries = snapshot.value.entries;
1682
+ const entries = snapshot;
1682
1683
  return entries.length === 0 ? void 0 : entries[entries.length - 1];
1683
1684
  },
1684
1685
  {
@@ -1690,10 +1691,10 @@ var ChatStreamGraph = class extends Graph {
1690
1691
  );
1691
1692
  this.add("latest", this.latest);
1692
1693
  this.connect("messages", "latest");
1693
- this._keepaliveSubs.push(keepalive(this.latest));
1694
+ this.addDisposer(keepalive(this.latest));
1694
1695
  this.messageCount = derived(
1695
1696
  [this.messages],
1696
- ([snapshot]) => snapshot.value.entries.length,
1697
+ ([snapshot]) => snapshot.length,
1697
1698
  {
1698
1699
  name: "messageCount",
1699
1700
  describeKind: "derived",
@@ -1703,7 +1704,7 @@ var ChatStreamGraph = class extends Graph {
1703
1704
  );
1704
1705
  this.add("messageCount", this.messageCount);
1705
1706
  this.connect("messages", "messageCount");
1706
- this._keepaliveSubs.push(keepalive(this.messageCount));
1707
+ this.addDisposer(keepalive(this.messageCount));
1707
1708
  }
1708
1709
  append(role, content, extra) {
1709
1710
  this._log.append({ role, content, ...extra });
@@ -1715,12 +1716,7 @@ var ChatStreamGraph = class extends Graph {
1715
1716
  this._log.clear();
1716
1717
  }
1717
1718
  allMessages() {
1718
- return this.messages.get().value.entries;
1719
- }
1720
- destroy() {
1721
- for (const unsub of this._keepaliveSubs) unsub();
1722
- this._keepaliveSubs.length = 0;
1723
- super.destroy();
1719
+ return this.messages.get();
1724
1720
  }
1725
1721
  };
1726
1722
  function chatStream(name, opts) {
@@ -1729,7 +1725,6 @@ function chatStream(name, opts) {
1729
1725
  var ToolRegistryGraph = class extends Graph {
1730
1726
  definitions;
1731
1727
  schemas;
1732
- _keepaliveSubs = [];
1733
1728
  constructor(name, opts = {}) {
1734
1729
  super(name, opts.graph);
1735
1730
  this.definitions = state(/* @__PURE__ */ new Map(), {
@@ -1750,7 +1745,7 @@ var ToolRegistryGraph = class extends Graph {
1750
1745
  );
1751
1746
  this.add("schemas", this.schemas);
1752
1747
  this.connect("definitions", "schemas");
1753
- this._keepaliveSubs.push(keepalive(this.schemas));
1748
+ this.addDisposer(keepalive(this.schemas));
1754
1749
  }
1755
1750
  register(tool) {
1756
1751
  const current = this.definitions.get();
@@ -1775,11 +1770,6 @@ var ToolRegistryGraph = class extends Graph {
1775
1770
  getDefinition(name) {
1776
1771
  return this.definitions.get().get(name);
1777
1772
  }
1778
- destroy() {
1779
- for (const unsub of this._keepaliveSubs) unsub();
1780
- this._keepaliveSubs.length = 0;
1781
- super.destroy();
1782
- }
1783
1773
  };
1784
1774
  function toolRegistry(name, opts) {
1785
1775
  return new ToolRegistryGraph(name, opts);
@@ -1924,9 +1914,7 @@ function admissionFilter3D(opts = {}) {
1924
1914
  }
1925
1915
  var DEFAULT_DECAY_RATE = Math.LN2 / (7 * 86400);
1926
1916
  function extractStoreMap(snapshot) {
1927
- if (snapshot && typeof snapshot === "object" && "value" in snapshot && typeof snapshot.value === "object" && snapshot.value !== null && "map" in snapshot.value) {
1928
- return snapshot.value.map ?? /* @__PURE__ */ new Map();
1929
- }
1917
+ if (snapshot instanceof Map) return snapshot;
1930
1918
  return /* @__PURE__ */ new Map();
1931
1919
  }
1932
1920
  function agentMemory(name, source, opts) {
@@ -1977,7 +1965,7 @@ function agentMemory(name, source, opts) {
1977
1965
  consolidateTrigger
1978
1966
  };
1979
1967
  const distillBundle = distill(filteredSource, extractFn, distillOpts);
1980
- graph.add("store", distillBundle.store.node);
1968
+ graph.add("store", distillBundle.store.entries);
1981
1969
  graph.add("compact", distillBundle.compact);
1982
1970
  graph.add("size", distillBundle.size);
1983
1971
  graph.connect("store", "compact");
@@ -2004,7 +1992,7 @@ function agentMemory(name, source, opts) {
2004
1992
  const permanentKeys = /* @__PURE__ */ new Set();
2005
1993
  const tierOf = (key) => {
2006
1994
  if (permanentKeys.has(key)) return "permanent";
2007
- const storeMap = extractStoreMap(distillBundle.store.node.get());
1995
+ const storeMap = extractStoreMap(distillBundle.store.entries.get());
2008
1996
  if (storeMap.has(key)) return "active";
2009
1997
  return "archived";
2010
1998
  };
@@ -2013,7 +2001,7 @@ function agentMemory(name, source, opts) {
2013
2001
  permanent.upsert(key, value);
2014
2002
  };
2015
2003
  const entryCreatedAtNs = /* @__PURE__ */ new Map();
2016
- const storeNode = distillBundle.store.node;
2004
+ const storeNode = distillBundle.store.entries;
2017
2005
  const contextNode = opts.context ? fromAny(opts.context) : state(null);
2018
2006
  const tierClassifier = effect([storeNode, contextNode], ([snapshot, ctx]) => {
2019
2007
  const storeMap = extractStoreMap(snapshot);
@@ -2080,7 +2068,7 @@ function agentMemory(name, source, opts) {
2080
2068
  if (vectors || kg) {
2081
2069
  const embedFn = opts.embedFn;
2082
2070
  const entityFn = opts.entityFn;
2083
- const storeNode = distillBundle.store.node;
2071
+ const storeNode = distillBundle.store.entries;
2084
2072
  const indexer = effect([storeNode], ([snapshot]) => {
2085
2073
  const storeMap = extractStoreMap(snapshot);
2086
2074
  for (const [key, mem] of storeMap) {
@@ -2125,7 +2113,7 @@ function agentMemory(name, source, opts) {
2125
2113
  });
2126
2114
  graph.add("retrievalTrace", traceState);
2127
2115
  retrievalTraceNode = traceState;
2128
- const storeNode = distillBundle.store.node;
2116
+ const storeNode = distillBundle.store.entries;
2129
2117
  let lastTrace = null;
2130
2118
  const retrievalDerived = derived(
2131
2119
  [queryInput, storeNode, contextNode],
@@ -2218,12 +2206,10 @@ function agentMemory(name, source, opts) {
2218
2206
  return result;
2219
2207
  };
2220
2208
  }
2221
- const origDestroy = graph.destroy.bind(graph);
2222
- graph.destroy = () => {
2209
+ graph.addDisposer(() => {
2223
2210
  for (const unsub of keepaliveSubs) unsub();
2224
2211
  keepaliveSubs.length = 0;
2225
- origDestroy();
2226
- };
2212
+ });
2227
2213
  return Object.assign(graph, {
2228
2214
  distillBundle,
2229
2215
  compact: distillBundle.compact,
@@ -3266,7 +3252,7 @@ function funnel(name, sources, stages, opts) {
3266
3252
  });
3267
3253
  g.add(bridgeName, br);
3268
3254
  g.connect(prevOutputPath, bridgeName);
3269
- keepalive2(br);
3255
+ g.addDisposer(keepalive2(br));
3270
3256
  prevOutputPath = `${stage.name}::output`;
3271
3257
  }
3272
3258
  return g;
@@ -3318,7 +3304,7 @@ function feedback(graph, condition, reentry, opts) {
3318
3304
  });
3319
3305
  graph.add(feedbackEffectName, feedbackEffect);
3320
3306
  graph.connect(condition, feedbackEffectName);
3321
- keepalive2(feedbackEffect);
3307
+ graph.addDisposer(keepalive2(feedbackEffect));
3322
3308
  return graph;
3323
3309
  }
3324
3310
  function budgetGate(source, constraints, opts) {
@@ -3698,7 +3684,7 @@ function contentModerationGraph(name, opts) {
3698
3684
  }
3699
3685
  });
3700
3686
  g.add("__review_accumulator", reviewAccumulator);
3701
- keepalive3(reviewAccumulator);
3687
+ g.addDisposer(keepalive3(reviewAccumulator));
3702
3688
  try {
3703
3689
  g.connect("stratify::branch/review", "__review_accumulator");
3704
3690
  } catch {
@@ -3746,8 +3732,7 @@ function contentModerationGraph(name, opts) {
3746
3732
  const fbCondition = derived(
3747
3733
  [reviewLog.entries, policy2],
3748
3734
  (vals) => {
3749
- const snap = vals[0];
3750
- const entries = snap?.value?.entries;
3735
+ const entries = vals[0];
3751
3736
  if (entries && entries.length > 0) {
3752
3737
  const latest = entries[entries.length - 1];
3753
3738
  if (latest && latest.falsePositive) {
@@ -4979,7 +4964,6 @@ function messagingMeta(kind, extra) {
4979
4964
  }
4980
4965
  var TopicGraph = class extends Graph {
4981
4966
  _log;
4982
- _keepaliveDisposers = [];
4983
4967
  events;
4984
4968
  latest;
4985
4969
  constructor(name, opts = {}) {
@@ -4990,7 +4974,7 @@ var TopicGraph = class extends Graph {
4990
4974
  this.latest = derived(
4991
4975
  [this.events],
4992
4976
  ([snapshot]) => {
4993
- const entries = snapshot.value.entries;
4977
+ const entries = snapshot;
4994
4978
  return entries.length === 0 ? void 0 : entries[entries.length - 1];
4995
4979
  },
4996
4980
  {
@@ -5002,23 +4986,16 @@ var TopicGraph = class extends Graph {
5002
4986
  );
5003
4987
  this.add("latest", this.latest);
5004
4988
  this.connect("events", "latest");
5005
- this._keepaliveDisposers.push(keepalive4(this.latest));
5006
- }
5007
- destroy() {
5008
- for (const dispose of this._keepaliveDisposers) dispose();
5009
- this._keepaliveDisposers.length = 0;
5010
- super.destroy();
4989
+ this.addDisposer(keepalive4(this.latest));
5011
4990
  }
5012
4991
  publish(value) {
5013
4992
  this._log.append(value);
5014
4993
  }
5015
4994
  retained() {
5016
- const snapshot = this.events.get();
5017
- return snapshot.value.entries;
4995
+ return this.events.get();
5018
4996
  }
5019
4997
  };
5020
4998
  var SubscriptionGraph = class extends Graph {
5021
- _keepaliveDisposers = [];
5022
4999
  source;
5023
5000
  cursor;
5024
5001
  available;
@@ -5043,7 +5020,7 @@ var SubscriptionGraph = class extends Graph {
5043
5020
  this.available = derived(
5044
5021
  [this.source, this.cursor],
5045
5022
  ([sourceSnapshot, cursor]) => {
5046
- const entries = sourceSnapshot.value.entries;
5023
+ const entries = sourceSnapshot;
5047
5024
  const start = Math.max(0, Math.trunc(cursor ?? 0));
5048
5025
  return entries.slice(start);
5049
5026
  },
@@ -5058,13 +5035,8 @@ var SubscriptionGraph = class extends Graph {
5058
5035
  this.connect("topic::events", "source");
5059
5036
  this.connect("source", "available");
5060
5037
  this.connect("cursor", "available");
5061
- this._keepaliveDisposers.push(keepalive4(this.source));
5062
- this._keepaliveDisposers.push(keepalive4(this.available));
5063
- }
5064
- destroy() {
5065
- for (const dispose of this._keepaliveDisposers) dispose();
5066
- this._keepaliveDisposers.length = 0;
5067
- super.destroy();
5038
+ this.addDisposer(keepalive4(this.source));
5039
+ this.addDisposer(keepalive4(this.available));
5068
5040
  }
5069
5041
  ack(count) {
5070
5042
  const available = this.available.get();
@@ -5086,7 +5058,6 @@ var SubscriptionGraph = class extends Graph {
5086
5058
  var JobQueueGraph = class extends Graph {
5087
5059
  _pending;
5088
5060
  _jobs;
5089
- _keepaliveDisposers = [];
5090
5061
  _seq = 0;
5091
5062
  pending;
5092
5063
  jobs;
@@ -5096,27 +5067,18 @@ var JobQueueGraph = class extends Graph {
5096
5067
  this._pending = reactiveList([], { name: "pending" });
5097
5068
  this._jobs = reactiveMap({ name: "jobs" });
5098
5069
  this.pending = this._pending.items;
5099
- this.jobs = this._jobs.node;
5070
+ this.jobs = this._jobs.entries;
5100
5071
  this.add("pending", this.pending);
5101
5072
  this.add("jobs", this.jobs);
5102
- this.depth = derived(
5103
- [this.pending],
5104
- ([snapshot]) => snapshot.value.items.length,
5105
- {
5106
- name: "depth",
5107
- describeKind: "derived",
5108
- meta: messagingMeta("queue_depth"),
5109
- initial: 0
5110
- }
5111
- );
5073
+ this.depth = derived([this.pending], ([snapshot]) => snapshot.length, {
5074
+ name: "depth",
5075
+ describeKind: "derived",
5076
+ meta: messagingMeta("queue_depth"),
5077
+ initial: 0
5078
+ });
5112
5079
  this.add("depth", this.depth);
5113
5080
  this.connect("pending", "depth");
5114
- this._keepaliveDisposers.push(keepalive4(this.depth));
5115
- }
5116
- destroy() {
5117
- for (const dispose of this._keepaliveDisposers) dispose();
5118
- this._keepaliveDisposers.length = 0;
5119
- super.destroy();
5081
+ this.addDisposer(keepalive4(this.depth));
5120
5082
  }
5121
5083
  enqueue(payload, opts = {}) {
5122
5084
  const id = opts.id ?? `${this.name}-${++this._seq}`;
@@ -5139,8 +5101,7 @@ var JobQueueGraph = class extends Graph {
5139
5101
  if (max === 0) return [];
5140
5102
  const out = [];
5141
5103
  while (out.length < max) {
5142
- const snapshot = this.pending.get();
5143
- const ids = snapshot.value.items;
5104
+ const ids = this.pending.get();
5144
5105
  if (ids.length === 0) break;
5145
5106
  const id = this._pending.pop(0);
5146
5107
  const job = this._jobs.get(id);
@@ -5176,7 +5137,6 @@ var JobQueueGraph = class extends Graph {
5176
5137
  var JobFlowGraph = class extends Graph {
5177
5138
  _stageNames;
5178
5139
  _queues = /* @__PURE__ */ new Map();
5179
- _keepaliveDisposers = [];
5180
5140
  _completed;
5181
5141
  completed;
5182
5142
  completedCount;
@@ -5201,7 +5161,7 @@ var JobFlowGraph = class extends Graph {
5201
5161
  this.add("completed", this.completed);
5202
5162
  this.completedCount = derived(
5203
5163
  [this.completed],
5204
- ([snapshot]) => snapshot.value.entries.length,
5164
+ ([snapshot]) => snapshot.length,
5205
5165
  {
5206
5166
  name: "completedCount",
5207
5167
  describeKind: "derived",
@@ -5211,7 +5171,7 @@ var JobFlowGraph = class extends Graph {
5211
5171
  );
5212
5172
  this.add("completedCount", this.completedCount);
5213
5173
  this.connect("completed", "completedCount");
5214
- this._keepaliveDisposers.push(keepalive4(this.completedCount));
5174
+ this.addDisposer(keepalive4(this.completedCount));
5215
5175
  const maxPerPump = Math.max(
5216
5176
  1,
5217
5177
  requireNonNegativeInt(opts.maxPerPump ?? DEFAULT_MAX_PER_PUMP, "job flow maxPerPump")
@@ -5251,14 +5211,9 @@ var JobFlowGraph = class extends Graph {
5251
5211
  );
5252
5212
  this.add(`pump_${stage}`, pump);
5253
5213
  this.connect(`${stage}::pending`, `pump_${stage}`);
5254
- this._keepaliveDisposers.push(keepalive4(pump));
5214
+ this.addDisposer(keepalive4(pump));
5255
5215
  }
5256
5216
  }
5257
- destroy() {
5258
- for (const dispose of this._keepaliveDisposers) dispose();
5259
- this._keepaliveDisposers.length = 0;
5260
- super.destroy();
5261
- }
5262
5217
  stages() {
5263
5218
  return this._stageNames;
5264
5219
  }
@@ -5271,14 +5226,12 @@ var JobFlowGraph = class extends Graph {
5271
5226
  return this.queue(this._stageNames[0]).enqueue(payload, opts);
5272
5227
  }
5273
5228
  retainedCompleted() {
5274
- const snapshot = this.completed.get();
5275
- return snapshot.value.entries;
5229
+ return this.completed.get();
5276
5230
  }
5277
5231
  };
5278
5232
  var TopicBridgeGraph = class extends Graph {
5279
5233
  _sourceSub;
5280
5234
  _target;
5281
- _keepaliveDisposers = [];
5282
5235
  bridgedCount;
5283
5236
  constructor(name, sourceTopic, targetTopic, opts = {}) {
5284
5237
  super(name, opts.graph);
@@ -5323,12 +5276,7 @@ var TopicBridgeGraph = class extends Graph {
5323
5276
  );
5324
5277
  this.add("pump", pump);
5325
5278
  this.connect("subscription::available", "pump");
5326
- this._keepaliveDisposers.push(keepalive4(pump));
5327
- }
5328
- destroy() {
5329
- for (const dispose of this._keepaliveDisposers) dispose();
5330
- this._keepaliveDisposers.length = 0;
5331
- super.destroy();
5279
+ this.addDisposer(keepalive4(pump));
5332
5280
  }
5333
5281
  };
5334
5282
  function topic(name, opts) {
@@ -5620,7 +5568,7 @@ function gate(graph, name, source, opts) {
5620
5568
  isOpenNode.down([[DATA, false]]);
5621
5569
  }
5622
5570
  };
5623
- countNode.subscribe(() => void 0);
5571
+ graph.addDisposer(countNode.subscribe(() => void 0));
5624
5572
  registerStep(graph, name, output, src.path ? [src.path] : []);
5625
5573
  const internal = new Graph(`${name}_state`);
5626
5574
  internal.add("pending", pendingNode);
@@ -5867,9 +5815,9 @@ var DEFAULT_QUEUE_CONFIGS = {
5867
5815
  function strategyModel() {
5868
5816
  const _map = reactiveMap({ name: "strategy-entries" });
5869
5817
  const snapshot = derived(
5870
- [_map.node],
5818
+ [_map.entries],
5871
5819
  ([mapSnap]) => {
5872
- const raw = mapSnap.value.map;
5820
+ const raw = mapSnap;
5873
5821
  return new Map(raw);
5874
5822
  },
5875
5823
  {
@@ -5904,7 +5852,10 @@ function strategyModel() {
5904
5852
  }
5905
5853
  const _unsub = snapshot.subscribe(() => {
5906
5854
  });
5907
- return { node: snapshot, record, lookup };
5855
+ function dispose() {
5856
+ _unsub();
5857
+ }
5858
+ return { node: snapshot, record, lookup, dispose };
5908
5859
  }
5909
5860
  function priorityScore(item, strategy, lastInteractionNs, urgency, signals) {
5910
5861
  const severityWeights = { ...DEFAULT_SEVERITY_WEIGHTS, ...signals?.severityWeights };
@@ -5936,6 +5887,9 @@ function priorityScore(item, strategy, lastInteractionNs, urgency, signals) {
5936
5887
  }
5937
5888
 
5938
5889
  // src/patterns/harness/loop.ts
5890
+ function baseSummary(summary) {
5891
+ return summary.replace(/^\[RETRY \d+\/\d+\]\s*/, "");
5892
+ }
5939
5893
  var DEFAULT_TRIAGE_PROMPT = `You are a triage classifier for a reactive collaboration harness.
5940
5894
 
5941
5895
  Given an intake item, classify it and output JSON:
@@ -5997,13 +5951,19 @@ var HarnessGraph = class extends Graph {
5997
5951
  strategy;
5998
5952
  /** Verify results topic — subscribe to see verification outcomes. */
5999
5953
  verifyResults;
6000
- constructor(name, intake, queues, gates, strategy, verifyResults) {
5954
+ /** Per-item fast-retry counts (keyed by base summary). */
5955
+ retryTracker;
5956
+ /** Per-item reingestion counts (keyed by base summary). */
5957
+ reingestionTracker;
5958
+ constructor(name, intake, queues, gates, strategy, verifyResults, retryTracker, reingestionTracker) {
6001
5959
  super(name);
6002
5960
  this.intake = intake;
6003
5961
  this.queues = queues;
6004
5962
  this.gates = gates;
6005
5963
  this.strategy = strategy;
6006
5964
  this.verifyResults = verifyResults;
5965
+ this.retryTracker = retryTracker;
5966
+ this.reingestionTracker = reingestionTracker;
6007
5967
  }
6008
5968
  };
6009
5969
  function harnessLoop(name, opts) {
@@ -6020,14 +5980,20 @@ function harnessLoop(name, opts) {
6020
5980
  }
6021
5981
  const intake = new TopicGraph("intake", { retainedLimit });
6022
5982
  const strategy = strategyModel();
5983
+ const triageInput = withLatestFrom(
5984
+ intake.latest,
5985
+ strategy.node
5986
+ );
6023
5987
  const triageNode = promptNode(
6024
5988
  adapter,
6025
- [intake.latest, strategy.node],
6026
- opts.triagePrompt ?? ((item, strat) => {
6027
- return DEFAULT_TRIAGE_PROMPT.replace("{{strategy}}", JSON.stringify(strat)).replace(
6028
- "{{item}}",
6029
- JSON.stringify(item)
6030
- );
5989
+ [triageInput],
5990
+ opts.triagePrompt ?? ((pair) => {
5991
+ const [item, strat] = pair;
5992
+ if (!item) return "";
5993
+ return DEFAULT_TRIAGE_PROMPT.replace(
5994
+ "{{strategy}}",
5995
+ JSON.stringify(Array.from(strat.entries()))
5996
+ ).replace("{{item}}", JSON.stringify(item));
6031
5997
  }),
6032
5998
  {
6033
5999
  name: "triage",
@@ -6039,12 +6005,14 @@ function harnessLoop(name, opts) {
6039
6005
  for (const route of QUEUE_NAMES) {
6040
6006
  queueTopics.set(route, new TopicGraph(`queue/${route}`, { retainedLimit }));
6041
6007
  }
6042
- const _router = effect([triageNode], ([triaged]) => {
6008
+ const router = effect([triageNode], ([triaged]) => {
6043
6009
  const item = triaged;
6044
6010
  if (!item || !item.route) return;
6045
6011
  const topic2 = queueTopics.get(item.route);
6046
6012
  if (topic2) topic2.publish(item);
6047
6013
  });
6014
+ const routerUnsub = router.subscribe(() => {
6015
+ });
6048
6016
  const gateGraph = new Graph("gates");
6049
6017
  const gateControllers = /* @__PURE__ */ new Map();
6050
6018
  for (const route of QUEUE_NAMES) {
@@ -6074,9 +6042,7 @@ function harnessLoop(name, opts) {
6074
6042
  const executeNode = promptNode(
6075
6043
  adapter,
6076
6044
  [executeInput],
6077
- opts.executePrompt ?? ((item) => {
6078
- return DEFAULT_EXECUTE_PROMPT.replace("{{item}}", JSON.stringify(item));
6079
- }),
6045
+ opts.executePrompt ?? ((item) => DEFAULT_EXECUTE_PROMPT.replace("{{item}}", JSON.stringify(item))),
6080
6046
  {
6081
6047
  name: "execute",
6082
6048
  format: "json",
@@ -6087,67 +6053,91 @@ function harnessLoop(name, opts) {
6087
6053
  const verifyNode = promptNode(
6088
6054
  adapter,
6089
6055
  [executeNode, executeInput],
6090
- opts.verifyPrompt ?? ((execution, item) => {
6091
- return DEFAULT_VERIFY_PROMPT.replace("{{execution}}", JSON.stringify(execution)).replace(
6092
- "{{item}}",
6093
- JSON.stringify(item)
6094
- );
6095
- }),
6056
+ opts.verifyPrompt ?? ((execution, item) => DEFAULT_VERIFY_PROMPT.replace("{{execution}}", JSON.stringify(execution)).replace(
6057
+ "{{item}}",
6058
+ JSON.stringify(item)
6059
+ )),
6096
6060
  {
6097
6061
  name: "verify",
6098
6062
  format: "json",
6099
6063
  retries: 1
6100
6064
  }
6101
6065
  );
6066
+ const verifyWithExec = withLatestFrom(verifyNode, executeNode);
6067
+ const verifyContext = withLatestFrom(
6068
+ verifyWithExec,
6069
+ executeInput
6070
+ );
6102
6071
  const maxReingestions = opts.maxReingestions ?? 1;
6103
- let reingestionCount = 0;
6104
- const _fastRetry = effect([verifyNode], ([result]) => {
6105
- const vr = result;
6106
- if (!vr) return;
6072
+ const retryTracker = /* @__PURE__ */ new Map();
6073
+ const reingestionTracker = /* @__PURE__ */ new Map();
6074
+ const fastRetry = effect([verifyContext], ([ctx]) => {
6075
+ const [[vo, execRaw], item] = ctx;
6076
+ if (!vo || !item) return;
6077
+ const exec = {
6078
+ item,
6079
+ outcome: execRaw?.outcome ?? "failure",
6080
+ detail: execRaw?.detail ?? "unknown"
6081
+ };
6082
+ const vr = {
6083
+ item,
6084
+ execution: exec,
6085
+ verified: vo.verified,
6086
+ findings: vo.findings ?? [],
6087
+ errorClass: vo.errorClass
6088
+ };
6107
6089
  if (vr.verified) {
6108
- strategy.record(vr.item.rootCause, vr.item.intervention, true);
6090
+ strategy.record(item.rootCause, item.intervention, true);
6109
6091
  verifyResults.publish(vr);
6110
6092
  return;
6111
6093
  }
6112
6094
  const errClass = vr.errorClass ?? errorClassifier({
6113
- item: vr.item,
6095
+ item,
6114
6096
  outcome: "failure",
6115
- detail: vr.findings.join("; "),
6116
- retryCount: 0
6097
+ detail: vr.findings.join("; ")
6117
6098
  });
6118
- const exec = vr.execution;
6119
- const retryCount = exec?.retryCount ?? 0;
6099
+ const key = baseSummary(item.summary);
6100
+ const retryCount = retryTracker.get(key) ?? 0;
6120
6101
  if (errClass === "self-correctable" && retryCount < maxRetries) {
6102
+ retryTracker.set(key, retryCount + 1);
6121
6103
  const retryItem = {
6122
- ...vr.item,
6123
- summary: `[RETRY ${retryCount + 1}/${maxRetries}] ${vr.item.summary} \u2014 Previous attempt failed: ${vr.findings.join("; ")}`
6104
+ ...item,
6105
+ summary: `[RETRY ${retryCount + 1}/${maxRetries}] ${baseSummary(item.summary)} \u2014 Previous attempt failed: ${vr.findings.join("; ")}`
6124
6106
  };
6125
6107
  retryTopic.publish(retryItem);
6126
6108
  } else {
6127
- strategy.record(vr.item.rootCause, vr.item.intervention, false);
6109
+ strategy.record(item.rootCause, item.intervention, false);
6128
6110
  verifyResults.publish(vr);
6129
- if (reingestionCount < maxReingestions) {
6130
- reingestionCount++;
6111
+ const itemReingestions = reingestionTracker.get(key) ?? 0;
6112
+ if (itemReingestions < maxReingestions) {
6113
+ reingestionTracker.set(key, itemReingestions + 1);
6131
6114
  intake.publish({
6132
6115
  source: "eval",
6133
- summary: `Verification failed for: ${vr.item.summary}`,
6116
+ summary: `Verification failed for: ${baseSummary(item.summary)}`,
6134
6117
  evidence: vr.findings.join("\n"),
6135
- affectsAreas: vr.item.affectsAreas,
6136
- affectsEvalTasks: vr.item.affectsEvalTasks,
6118
+ affectsAreas: item.affectsAreas,
6119
+ affectsEvalTasks: item.affectsEvalTasks,
6137
6120
  severity: "high",
6138
- relatedTo: [vr.item.summary]
6121
+ relatedTo: [baseSummary(item.summary)]
6139
6122
  });
6140
6123
  }
6141
6124
  }
6142
6125
  });
6126
+ const fastRetryUnsub = fastRetry.subscribe(() => {
6127
+ });
6143
6128
  const harness = new HarnessGraph(
6144
6129
  name,
6145
6130
  intake,
6146
6131
  queueTopics,
6147
6132
  gateControllers,
6148
6133
  strategy,
6149
- verifyResults
6134
+ verifyResults,
6135
+ retryTracker,
6136
+ reingestionTracker
6150
6137
  );
6138
+ harness.addDisposer(routerUnsub);
6139
+ harness.addDisposer(fastRetryUnsub);
6140
+ harness.addDisposer(strategy.dispose);
6151
6141
  harness.mount("intake", intake);
6152
6142
  for (const [route, topic2] of queueTopics) {
6153
6143
  harness.mount(`queue/${route}`, topic2);