@graphrefly/graphrefly 0.21.0 → 0.22.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 (97) hide show
  1. package/README.md +7 -5
  2. package/dist/chunk-44HD4BTA.js +47 -0
  3. package/dist/chunk-44HD4BTA.js.map +1 -0
  4. package/dist/chunk-7TAQJHQV.js +103 -0
  5. package/dist/chunk-7TAQJHQV.js.map +1 -0
  6. package/dist/chunk-BLD3IFYF.js +6827 -0
  7. package/dist/chunk-BLD3IFYF.js.map +1 -0
  8. package/dist/{chunk-ZTCDY5NQ.js → chunk-EQUZ5NLD.js} +34 -45
  9. package/dist/chunk-EQUZ5NLD.js.map +1 -0
  10. package/dist/{chunk-VOQFK7YN.js → chunk-IR3KMOLX.js} +358 -128
  11. package/dist/chunk-IR3KMOLX.js.map +1 -0
  12. package/dist/{chunk-XWBVAO2R.js → chunk-MQBQOFDS.js} +20 -11
  13. package/dist/chunk-MQBQOFDS.js.map +1 -0
  14. package/dist/chunk-NXC35KC5.js +2417 -0
  15. package/dist/chunk-NXC35KC5.js.map +1 -0
  16. package/dist/chunk-QA3RP5NH.js +2234 -0
  17. package/dist/chunk-QA3RP5NH.js.map +1 -0
  18. package/dist/chunk-RHI3GHZW.js +115 -0
  19. package/dist/chunk-RHI3GHZW.js.map +1 -0
  20. package/dist/{chunk-7IGHIFTT.js → chunk-TH6COGOP.js} +15 -26
  21. package/dist/chunk-TH6COGOP.js.map +1 -0
  22. package/dist/compat/nestjs/index.cjs +3366 -2259
  23. package/dist/compat/nestjs/index.cjs.map +1 -1
  24. package/dist/compat/nestjs/index.d.cts +6 -4
  25. package/dist/compat/nestjs/index.d.ts +6 -4
  26. package/dist/compat/nestjs/index.js +8 -8
  27. package/dist/core/index.cjs +1611 -1218
  28. package/dist/core/index.cjs.map +1 -1
  29. package/dist/core/index.d.cts +3 -2
  30. package/dist/core/index.d.ts +3 -2
  31. package/dist/core/index.js +37 -34
  32. package/dist/extra/index.cjs +7387 -6089
  33. package/dist/extra/index.cjs.map +1 -1
  34. package/dist/extra/index.d.cts +4 -4
  35. package/dist/extra/index.d.ts +4 -4
  36. package/dist/extra/index.js +57 -30
  37. package/dist/graph/index.cjs +3107 -2216
  38. package/dist/graph/index.cjs.map +1 -1
  39. package/dist/graph/index.d.cts +5 -3
  40. package/dist/graph/index.d.ts +5 -3
  41. package/dist/graph/index.js +24 -11
  42. package/dist/graph-DFr0diXB.d.ts +1128 -0
  43. package/dist/graph-ab1yPwIB.d.cts +1128 -0
  44. package/dist/{index-8a605sg9.d.ts → index-BHm3Ba5q.d.ts} +2 -2
  45. package/dist/{index-DuN3bhtm.d.ts → index-BbYZma8G.d.ts} +1697 -586
  46. package/dist/{index-SFzE_KTa.d.cts → index-BvWfZCTt.d.cts} +1697 -586
  47. package/dist/index-C9z6rU9P.d.cts +388 -0
  48. package/dist/{index-BjtlNirP.d.cts → index-D36MAQ3f.d.ts} +4 -4
  49. package/dist/{index-VHA43cGP.d.cts → index-DLE1Sp-L.d.cts} +2 -2
  50. package/dist/{index-CgSiUouz.d.ts → index-DrJq9B1T.d.cts} +4 -4
  51. package/dist/index-DsGxLfwL.d.ts +315 -0
  52. package/dist/index-Dy04P4W3.d.cts +315 -0
  53. package/dist/index-HdJx_BjO.d.ts +388 -0
  54. package/dist/index.cjs +9781 -7878
  55. package/dist/index.cjs.map +1 -1
  56. package/dist/index.d.cts +214 -37
  57. package/dist/index.d.ts +214 -37
  58. package/dist/index.js +905 -638
  59. package/dist/index.js.map +1 -1
  60. package/dist/meta--fr9sxRM.d.cts +41 -0
  61. package/dist/meta-n3FoVWML.d.ts +41 -0
  62. package/dist/node-C5UD5MGq.d.cts +1146 -0
  63. package/dist/node-C5UD5MGq.d.ts +1146 -0
  64. package/dist/{observable-DcBwQY7t.d.ts → observable-CQRBtEbq.d.ts} +1 -1
  65. package/dist/{observable-C8Kx_O6k.d.cts → observable-DWydVy5b.d.cts} +1 -1
  66. package/dist/patterns/reactive-layout/index.cjs +3102 -2132
  67. package/dist/patterns/reactive-layout/index.cjs.map +1 -1
  68. package/dist/patterns/reactive-layout/index.d.cts +5 -3
  69. package/dist/patterns/reactive-layout/index.d.ts +5 -3
  70. package/dist/patterns/reactive-layout/index.js +5 -4
  71. package/dist/storage-Bew05Xy6.d.cts +182 -0
  72. package/dist/storage-C9fZfMfM.d.ts +182 -0
  73. package/package.json +1 -1
  74. package/dist/chunk-2UDLYZHT.js +0 -2117
  75. package/dist/chunk-2UDLYZHT.js.map +0 -1
  76. package/dist/chunk-4MQ2J6IG.js +0 -1631
  77. package/dist/chunk-4MQ2J6IG.js.map +0 -1
  78. package/dist/chunk-7IGHIFTT.js.map +0 -1
  79. package/dist/chunk-DOSLSFKL.js +0 -162
  80. package/dist/chunk-DOSLSFKL.js.map +0 -1
  81. package/dist/chunk-ECN37NVS.js +0 -6227
  82. package/dist/chunk-ECN37NVS.js.map +0 -1
  83. package/dist/chunk-G66H6ZRK.js +0 -111
  84. package/dist/chunk-G66H6ZRK.js.map +0 -1
  85. package/dist/chunk-VOQFK7YN.js.map +0 -1
  86. package/dist/chunk-WZ2Z2CRV.js +0 -32
  87. package/dist/chunk-WZ2Z2CRV.js.map +0 -1
  88. package/dist/chunk-XWBVAO2R.js.map +0 -1
  89. package/dist/chunk-ZTCDY5NQ.js.map +0 -1
  90. package/dist/graph-KsTe57nI.d.cts +0 -750
  91. package/dist/graph-mILUUqW8.d.ts +0 -750
  92. package/dist/index-B2SvPEbc.d.ts +0 -257
  93. package/dist/index-BHfg_Ez3.d.ts +0 -629
  94. package/dist/index-Bc_diYYJ.d.cts +0 -629
  95. package/dist/index-UudxGnzc.d.cts +0 -257
  96. package/dist/meta-BnG7XAaE.d.cts +0 -778
  97. package/dist/meta-BnG7XAaE.d.ts +0 -778
package/dist/index.js CHANGED
@@ -1,20 +1,19 @@
1
1
  import {
2
2
  CircuitOpenError,
3
- DictCheckpointAdapter,
4
- FileCheckpointAdapter,
5
- MemoryCheckpointAdapter,
6
3
  NS_PER_MS,
7
4
  NS_PER_SEC,
8
- SqliteCheckpointAdapter,
5
+ NativeIndexBackend,
6
+ NativeListBackend,
7
+ NativeMapBackend,
8
+ NativePubSubBackend,
9
+ RateLimiterOverflowError,
9
10
  TimeoutError,
10
11
  audit,
11
12
  buffer,
12
13
  bufferCount,
13
14
  bufferTime,
14
- cache,
15
15
  cascadingCache,
16
16
  catchError,
17
- checkpointNodeValue,
18
17
  checkpointToRedis,
19
18
  checkpointToS3,
20
19
  circuitBreaker,
@@ -24,19 +23,24 @@ import {
24
23
  concatMap,
25
24
  constant,
26
25
  createTransport,
26
+ csvRows,
27
27
  debounce,
28
28
  debounceTime,
29
29
  decorrelatedJitter,
30
30
  delay,
31
31
  deserializeError,
32
+ dictStorage,
32
33
  distill,
33
34
  distinctUntilChanged,
34
35
  elementAt,
35
36
  exhaustMap,
36
37
  exponential,
38
+ externalBundle,
39
+ externalProducer,
37
40
  extra_exports,
38
41
  fallback,
39
42
  fibonacci,
43
+ fileStorage,
40
44
  filter,
41
45
  find,
42
46
  first,
@@ -46,6 +50,8 @@ import {
46
50
  fromDrizzle,
47
51
  fromGitHook,
48
52
  fromHTTP,
53
+ fromHTTPPoll,
54
+ fromHTTPStream,
49
55
  fromIDBRequest,
50
56
  fromIDBTransaction,
51
57
  fromKafka,
@@ -59,19 +65,25 @@ import {
59
65
  fromPulsar,
60
66
  fromRabbitMQ,
61
67
  fromRedisStream,
68
+ fromSSE,
62
69
  fromSqlite,
70
+ fromSqliteCursor,
63
71
  fromStatsD,
64
72
  fromSyslog,
65
73
  fromWebSocket,
74
+ fromWebSocketReconnect,
66
75
  fromWebhook,
76
+ indexedDbStorage,
67
77
  interval,
68
78
  last,
69
79
  linear,
70
80
  lru,
71
81
  map,
82
+ memoryStorage,
72
83
  merge,
73
84
  mergeMap,
74
85
  nameToSignal,
86
+ ndjsonRows,
75
87
  pairwise,
76
88
  parsePrometheusText,
77
89
  parseStatsD,
@@ -83,20 +95,19 @@ import {
83
95
  reactiveIndex,
84
96
  reactiveList,
85
97
  reactiveMap,
98
+ reactiveSink,
86
99
  reduce,
87
100
  repeat,
88
101
  rescue,
89
102
  resolveBackoffPreset,
90
- restoreGraphCheckpoint,
91
- restoreGraphCheckpointIndexedDb,
92
103
  retry,
104
+ retrySource,
93
105
  sample,
94
- saveGraphCheckpoint,
95
- saveGraphCheckpointIndexedDb,
96
106
  scan,
97
107
  serializeError,
98
108
  signalToName,
99
109
  skip,
110
+ sqliteStorage,
100
111
  switchMap,
101
112
  take,
102
113
  takeUntil,
@@ -104,11 +115,11 @@ import {
104
115
  tap,
105
116
  throttle,
106
117
  throttleTime,
107
- tieredStorage,
108
118
  timeout,
109
119
  toCSV,
110
120
  toClickHouse,
111
121
  toFile,
122
+ toHTTP,
112
123
  toKafka,
113
124
  toLoki,
114
125
  toMongo,
@@ -116,14 +127,15 @@ import {
116
127
  toPostgres,
117
128
  toPulsar,
118
129
  toRabbitMQ,
130
+ toReadableStream,
119
131
  toRedisStream,
120
132
  toS3,
121
133
  toSSE,
134
+ toSSEBytes,
122
135
  toSqlite,
123
136
  toTempo,
124
137
  toWebSocket,
125
138
  tokenBucket,
126
- tokenTracker,
127
139
  valve,
128
140
  verifiable,
129
141
  window,
@@ -136,27 +148,22 @@ import {
136
148
  workerBridge,
137
149
  workerSelf,
138
150
  zip
139
- } from "./chunk-ECN37NVS.js";
151
+ } from "./chunk-BLD3IFYF.js";
140
152
  import {
141
153
  cqrs_exports,
142
154
  domainMeta,
143
155
  nestjs_exports,
144
- trackingKey
145
- } from "./chunk-XWBVAO2R.js";
156
+ trackingKey,
157
+ tryIncrementBounded
158
+ } from "./chunk-MQBQOFDS.js";
146
159
  import {
147
- JsonCodec,
148
- createDagCborCodec,
149
- createDagCborZstdCodec,
150
- graph_exports,
151
- negotiateCodec,
152
- replayWAL
153
- } from "./chunk-G66H6ZRK.js";
154
- import {
155
- DEFAULT_DOWN,
156
- bridge,
157
160
  core_exports
158
- } from "./chunk-DOSLSFKL.js";
161
+ } from "./chunk-RHI3GHZW.js";
162
+ import {
163
+ graph_exports
164
+ } from "./chunk-44HD4BTA.js";
159
165
  import {
166
+ NativeLogBackend,
160
167
  cached,
161
168
  createWatermarkController,
162
169
  empty,
@@ -174,7 +181,6 @@ import {
174
181
  fromTimer,
175
182
  globToRegExp,
176
183
  keepalive,
177
- logSlice,
178
184
  matchesAnyPattern,
179
185
  matchesCron,
180
186
  never,
@@ -188,72 +194,89 @@ import {
188
194
  throwError,
189
195
  toArray,
190
196
  toObservable
191
- } from "./chunk-VOQFK7YN.js";
192
- import {
193
- ResettableTimer
194
- } from "./chunk-WZ2Z2CRV.js";
197
+ } from "./chunk-IR3KMOLX.js";
195
198
  import {
196
199
  analyzeAndMeasure,
197
200
  computeLineBreaks,
198
201
  reactive_layout_exports
199
- } from "./chunk-ZTCDY5NQ.js";
202
+ } from "./chunk-EQUZ5NLD.js";
200
203
  import {
201
204
  GRAPH_META_SEGMENT,
202
205
  Graph,
206
+ OVERHEAD,
207
+ SIZEOF_SYMBOL,
208
+ diffForWAL,
203
209
  graphProfile,
204
210
  reachable,
205
211
  sizeof
206
- } from "./chunk-2UDLYZHT.js";
212
+ } from "./chunk-NXC35KC5.js";
207
213
  import {
208
214
  describeNode,
209
215
  resolveDescribeFields
210
- } from "./chunk-7IGHIFTT.js";
216
+ } from "./chunk-TH6COGOP.js";
217
+ import {
218
+ ResettableTimer
219
+ } from "./chunk-7TAQJHQV.js";
211
220
  import {
212
- CLEANUP_RESULT,
213
221
  COMPLETE,
222
+ COMPLETE_MSG,
223
+ COMPLETE_ONLY_BATCH,
214
224
  DATA,
215
225
  DEFAULT_ACTOR,
216
226
  DIRTY,
217
- DynamicNodeImpl,
227
+ DIRTY_MSG,
228
+ DIRTY_ONLY_BATCH,
229
+ ENVELOPE_VERSION,
218
230
  ERROR,
231
+ GraphReFlyConfig,
219
232
  GuardDenied,
220
233
  INVALIDATE,
234
+ INVALIDATE_MSG,
235
+ INVALIDATE_ONLY_BATCH,
236
+ JsonCodec,
237
+ NodeImpl,
221
238
  PAUSE,
222
239
  RESOLVED,
240
+ RESOLVED_MSG,
241
+ RESOLVED_ONLY_BATCH,
223
242
  RESUME,
224
243
  START,
244
+ START_MSG,
225
245
  TEARDOWN,
246
+ TEARDOWN_MSG,
247
+ TEARDOWN_ONLY_BATCH,
226
248
  __export,
227
249
  accessHintForGuard,
228
250
  advanceVersion,
251
+ autoTrackNode,
229
252
  batch,
230
- cleanupResult,
253
+ configure,
254
+ createDagCborCodec,
255
+ createDagCborZstdCodec,
231
256
  createVersioning,
257
+ decodeEnvelope,
258
+ defaultConfig,
232
259
  defaultHash,
233
260
  derived,
234
261
  downWithBatch,
235
262
  dynamicNode,
236
263
  effect,
264
+ encodeEnvelope,
237
265
  isBatching,
238
- isKnownMessageType,
239
- isLocalOnly,
240
- isPhase2Message,
241
- isTerminalMessage,
242
266
  isV1,
243
- knownMessageTypes,
244
- messageTier,
245
267
  monotonicNs,
246
268
  node,
247
269
  normalizeActor,
248
- partitionForBatch,
249
270
  pipe,
250
271
  policy,
251
272
  policyFromRules,
252
273
  producer,
253
- propagatesToMeta,
274
+ registerBuiltinCodecs,
275
+ registerBuiltins,
276
+ replayWAL,
254
277
  state,
255
278
  wallClockNs
256
- } from "./chunk-4MQ2J6IG.js";
279
+ } from "./chunk-QA3RP5NH.js";
257
280
 
258
281
  // src/compat/index.ts
259
282
  var compat_exports = {};
@@ -285,7 +308,7 @@ function atom(initialOrRead, writeOrOptions, options) {
285
308
  return createPrimitiveAtom(initialOrRead, writeOrOptions);
286
309
  }
287
310
  function pull(n) {
288
- let val = n.get();
311
+ let val = n.cache;
289
312
  let err;
290
313
  const unsub = n.subscribe((msgs) => {
291
314
  for (const [t, v] of msgs) {
@@ -305,15 +328,19 @@ function createPrimitiveAtom(initial, options) {
305
328
  });
306
329
  return {
307
330
  get: () => {
308
- if (n.status === "disconnected") {
331
+ if (n.status === "sentinel") {
309
332
  return pull(n);
310
333
  }
311
- return n.get();
334
+ return n.cache;
312
335
  },
313
- set: (value) => n.down([[DATA, value]]),
336
+ // Use `n.emit` (not raw `n.down`) so writes go through the framed
337
+ // emit pipeline: bundle() auto-prefixes DIRTY (diamond-safe wave
338
+ // coordination) and the equals check folds same-value writes to
339
+ // RESOLVED (no spurious subscriber fires).
340
+ set: (value) => n.emit(value),
314
341
  update: (fn) => {
315
- const current = n.status === "disconnected" ? pull(n) : n.get();
316
- n.down([[DATA, fn(current)]]);
342
+ const current = n.status === "sentinel" ? pull(n) : n.cache;
343
+ n.emit(fn(current));
317
344
  },
318
345
  subscribe: (cb) => {
319
346
  let initial2 = true;
@@ -334,13 +361,13 @@ function createPrimitiveAtom(initial, options) {
334
361
  };
335
362
  }
336
363
  function createDerivedAtom(read, write, options) {
337
- const n = dynamicNode(
338
- (get) => read((a) => {
364
+ const n = autoTrackNode(
365
+ (track) => read((a) => {
339
366
  const dn = a._node;
340
- if (dn.status === "disconnected") {
367
+ if (dn.status === "sentinel") {
341
368
  pull(dn);
342
369
  }
343
- return get(dn);
370
+ return track(dn);
344
371
  }),
345
372
  {
346
373
  ...options,
@@ -350,10 +377,10 @@ function createDerivedAtom(read, write, options) {
350
377
  );
351
378
  const result = {
352
379
  get: () => {
353
- if (n.status === "disconnected") {
380
+ if (n.status === "sentinel") {
354
381
  return pull(n);
355
382
  }
356
- return n.get();
383
+ return n.cache;
357
384
  },
358
385
  subscribe: (cb) => {
359
386
  let initial = true;
@@ -378,7 +405,7 @@ function createDerivedAtom(read, write, options) {
378
405
  const writable = result;
379
406
  writable.set = (value) => write(getFn, setFn, value);
380
407
  writable.update = (fn) => {
381
- const current = n.status === "disconnected" ? pull(n) : n.get();
408
+ const current = n.status === "sentinel" ? pull(n) : n.cache;
382
409
  return write(getFn, setFn, fn(current));
383
410
  };
384
411
  return writable;
@@ -451,7 +478,7 @@ function createStore(node2, extra = {}) {
451
478
  return store;
452
479
  }
453
480
  function pull2(n) {
454
- let val = n.get();
481
+ let val = n.cache;
455
482
  let err;
456
483
  const unsub = n.subscribe((msgs) => {
457
484
  for (const [t, v] of msgs) {
@@ -464,10 +491,10 @@ function pull2(n) {
464
491
  return val;
465
492
  }
466
493
  function getVal(n) {
467
- if (n.status === "disconnected") {
494
+ if (n.status === "sentinel") {
468
495
  return pull2(n);
469
496
  }
470
- return n.get();
497
+ return n.cache;
471
498
  }
472
499
  function atom2(initial) {
473
500
  const n = state(initial, {
@@ -475,19 +502,26 @@ function atom2(initial) {
475
502
  resetOnTeardown: true
476
503
  });
477
504
  return createStore(n, {
478
- set: (value) => n.down([[DATA, value]])
505
+ // `n.emit` routes through the framed pipeline: `bundle()` auto-
506
+ // prefixes `[DIRTY]` (diamond-safe wave coordination) and the
507
+ // node's `equals` (default `Object.is`) folds same-value writes
508
+ // into `RESOLVED`. Matches nanostores' documented Object.is
509
+ // dedup semantics without any custom check.
510
+ set: (value) => n.emit(value)
479
511
  });
480
512
  }
481
513
  function computed(stores, fn) {
482
514
  const storeArray = Array.isArray(stores) ? stores : [stores];
515
+ const depNodes = storeArray.map((s) => s._node);
483
516
  const n = dynamicNode(
484
- (get) => {
517
+ depNodes,
518
+ (track) => {
485
519
  const vals = storeArray.map((s) => {
486
520
  const node2 = s._node;
487
- if (node2.status === "disconnected") {
521
+ if (node2.status === "sentinel") {
488
522
  pull2(node2);
489
523
  }
490
- return get(node2);
524
+ return track(node2);
491
525
  });
492
526
  return fn(...vals);
493
527
  },
@@ -506,10 +540,14 @@ function map2(initial) {
506
540
  equals: () => false
507
541
  });
508
542
  return createStore(n, {
509
- set: (value) => n.down([[DATA, value]]),
543
+ // `map`'s state node is configured with `equals: () => false`
544
+ // above, so every `emit` produces DATA (even for same-key same-
545
+ // value sets). The `emit` path is still required for diamond
546
+ // coordination (`[DIRTY]` auto-prefix via `bundle()`).
547
+ set: (value) => n.emit(value),
510
548
  setKey: (key, value) => {
511
549
  const current = getVal(n);
512
- n.down([[DATA, { ...current, [key]: value }]]);
550
+ n.emit({ ...current, [key]: value });
513
551
  }
514
552
  });
515
553
  }
@@ -570,8 +608,8 @@ function useSubscribe(node2) {
570
608
  unsub();
571
609
  };
572
610
  },
573
- () => node2.get(),
574
- () => node2.get()
611
+ () => node2.cache,
612
+ () => node2.cache
575
613
  // Server snapshot
576
614
  );
577
615
  }
@@ -591,12 +629,12 @@ function useSubscribeRecord(keysNode, factory) {
591
629
  const store = useMemo(() => {
592
630
  const computeSnap = () => {
593
631
  const snap = {};
594
- const keys = keysNode.get() ?? [];
632
+ const keys = keysNode.cache ?? [];
595
633
  for (const key of keys) {
596
634
  const nodes = factoryRef.current(key);
597
635
  const values = {};
598
636
  for (const field of Object.keys(nodes)) {
599
- values[field] = nodes[field].get();
637
+ values[field] = nodes[field].cache;
600
638
  }
601
639
  snap[key] = values;
602
640
  }
@@ -627,10 +665,10 @@ function useSubscribeRecord(keysNode, factory) {
627
665
  if (!disposed) onStoreChange();
628
666
  };
629
667
  const keysUnsub = keysNode.subscribe((msgs) => {
630
- const hasSettled = msgs.some((m) => messageTier(m[0]) >= 3);
631
- if (!disposed && hasSettled) sync(keysNode.get() ?? []);
668
+ const hasSettled = msgs.some((m) => m[0] === DATA || m[0] === RESOLVED);
669
+ if (!disposed && hasSettled) sync(keysNode.cache ?? []);
632
670
  });
633
- sync(keysNode.get() ?? []);
671
+ sync(keysNode.cache ?? []);
634
672
  return () => {
635
673
  disposed = true;
636
674
  keysUnsub();
@@ -650,7 +688,7 @@ __export(signals_exports, {
650
688
  });
651
689
  var trackingStack = [];
652
690
  function pull3(n) {
653
- let val = n.get();
691
+ let val = n.cache;
654
692
  const unsub = n.subscribe((msgs) => {
655
693
  for (const [t, v] of msgs) {
656
694
  if (t === DATA) val = v;
@@ -674,15 +712,15 @@ var SignalState = class {
674
712
  get() {
675
713
  const tracker = trackingStack[trackingStack.length - 1];
676
714
  if (tracker) {
677
- if (this._node.status === "disconnected") {
715
+ if (this._node.status === "sentinel") {
678
716
  pull3(this._node);
679
717
  }
680
718
  return tracker(this._node);
681
719
  }
682
- if (this._node.status === "disconnected") {
720
+ if (this._node.status === "sentinel") {
683
721
  return pull3(this._node);
684
722
  }
685
- return this._node.get();
723
+ return this._node.cache;
686
724
  }
687
725
  set(value) {
688
726
  if (this._equals(this.get(), value)) return;
@@ -695,9 +733,9 @@ var SignalComputed = class {
695
733
  /** @internal */
696
734
  _node;
697
735
  constructor(computation, opts) {
698
- this._node = dynamicNode(
699
- (get) => {
700
- trackingStack.push(get);
736
+ this._node = autoTrackNode(
737
+ (track) => {
738
+ trackingStack.push(track);
701
739
  try {
702
740
  return computation();
703
741
  } finally {
@@ -715,15 +753,15 @@ var SignalComputed = class {
715
753
  get() {
716
754
  const tracker = trackingStack[trackingStack.length - 1];
717
755
  if (tracker) {
718
- if (this._node.status === "disconnected") {
756
+ if (this._node.status === "sentinel") {
719
757
  pull3(this._node);
720
758
  }
721
759
  return tracker(this._node);
722
760
  }
723
- if (this._node.status === "disconnected") {
761
+ if (this._node.status === "sentinel") {
724
762
  return pull3(this._node);
725
763
  }
726
- return this._node.get();
764
+ return this._node.cache;
727
765
  }
728
766
  };
729
767
  var Signal = {
@@ -767,9 +805,9 @@ __export(solid_exports, {
767
805
  });
768
806
  import { createSignal, getOwner, onCleanup } from "solid-js";
769
807
  function useSubscribe2(node2) {
770
- const [value, setValue] = createSignal(node2.get(), { equals: false });
808
+ const [value, setValue] = createSignal(node2.cache, { equals: false });
771
809
  const unsub = node2.subscribe(() => {
772
- setValue(() => node2.get());
810
+ setValue(() => node2.cache);
773
811
  });
774
812
  if (getOwner()) {
775
813
  onCleanup(() => unsub());
@@ -796,11 +834,11 @@ function useSubscribeRecord2(keysNode, factory) {
796
834
  };
797
835
  const buildSnapshot = () => {
798
836
  const snap = {};
799
- for (const key of keysNode.get() ?? []) {
837
+ for (const key of keysNode.cache ?? []) {
800
838
  const nodes = factory(key);
801
839
  const values = {};
802
840
  for (const field of Object.keys(nodes)) {
803
- values[field] = nodes[field].get();
841
+ values[field] = nodes[field].cache;
804
842
  }
805
843
  snap[key] = values;
806
844
  }
@@ -820,11 +858,11 @@ function useSubscribeRecord2(keysNode, factory) {
820
858
  setValue(() => buildSnapshot());
821
859
  };
822
860
  const keysUnsub = keysNode.subscribe((msgs) => {
823
- if (msgs.some((m) => messageTier(m[0]) >= 3)) {
824
- sync(keysNode.get() ?? []);
861
+ if (msgs.some((m) => m[0] === DATA || m[0] === RESOLVED)) {
862
+ sync(keysNode.cache ?? []);
825
863
  }
826
864
  });
827
- sync(keysNode.get() ?? []);
865
+ sync(keysNode.cache ?? []);
828
866
  if (getOwner()) {
829
867
  onCleanup(() => {
830
868
  keysUnsub();
@@ -849,9 +887,9 @@ function useSubscribe3(node2) {
849
887
  return {
850
888
  subscribe(run) {
851
889
  const unsub = node2.subscribe(() => {
852
- run(node2.get());
890
+ run(node2.cache);
853
891
  });
854
- run(node2.get());
892
+ run(node2.cache);
855
893
  return unsub;
856
894
  }
857
895
  };
@@ -860,16 +898,16 @@ function useStore3(node2) {
860
898
  return {
861
899
  subscribe(run) {
862
900
  const unsub = node2.subscribe(() => {
863
- run(node2.get());
901
+ run(node2.cache);
864
902
  });
865
- run(node2.get());
903
+ run(node2.cache);
866
904
  return unsub;
867
905
  },
868
906
  set(value) {
869
907
  node2.down([[DIRTY], [DATA, value]]);
870
908
  },
871
909
  update(updater) {
872
- const next = updater(node2.get());
910
+ const next = updater(node2.cache);
873
911
  node2.down([[DIRTY], [DATA, next]]);
874
912
  }
875
913
  };
@@ -884,11 +922,11 @@ function useSubscribeRecord3(keysNode, factory) {
884
922
  };
885
923
  const buildSnapshot = () => {
886
924
  const snap = {};
887
- for (const key of keysNode.get() ?? []) {
925
+ for (const key of keysNode.cache ?? []) {
888
926
  const nodes = factory(key);
889
927
  const values = {};
890
928
  for (const field of Object.keys(nodes)) {
891
- values[field] = nodes[field].get();
929
+ values[field] = nodes[field].cache;
892
930
  }
893
931
  snap[key] = values;
894
932
  }
@@ -908,11 +946,11 @@ function useSubscribeRecord3(keysNode, factory) {
908
946
  run(buildSnapshot());
909
947
  };
910
948
  const keysUnsub = keysNode.subscribe((msgs) => {
911
- if (msgs.some((m) => messageTier(m[0]) >= 3)) {
912
- sync(keysNode.get() ?? []);
949
+ if (msgs.some((m) => m[0] === DATA || m[0] === RESOLVED)) {
950
+ sync(keysNode.cache ?? []);
913
951
  }
914
952
  });
915
- sync(keysNode.get() ?? []);
953
+ sync(keysNode.cache ?? []);
916
954
  return () => {
917
955
  keysUnsub();
918
956
  cleanupEntries();
@@ -938,9 +976,9 @@ import {
938
976
  watch
939
977
  } from "vue";
940
978
  function useSubscribe4(node2) {
941
- const ref = shallowRef(node2.get());
979
+ const ref = shallowRef(node2.cache);
942
980
  const unsub = node2.subscribe(() => {
943
- ref.value = node2.get();
981
+ ref.value = node2.cache;
944
982
  });
945
983
  if (getCurrentScope()) {
946
984
  onScopeDispose(() => unsub());
@@ -952,9 +990,9 @@ function useSubscribe4(node2) {
952
990
  return readonly(ref);
953
991
  }
954
992
  function useStore4(node2) {
955
- const inner = shallowRef(node2.get());
993
+ const inner = shallowRef(node2.cache);
956
994
  const unsub = node2.subscribe(() => {
957
- inner.value = node2.get();
995
+ inner.value = node2.cache;
958
996
  });
959
997
  if (getCurrentScope()) {
960
998
  onScopeDispose(() => unsub());
@@ -1000,9 +1038,9 @@ function useSubscribeRecord4(keys, factory) {
1000
1038
  const subs = [];
1001
1039
  for (const field of fields) {
1002
1040
  const node2 = nodes[field];
1003
- values[field] = node2.get();
1041
+ values[field] = node2.cache;
1004
1042
  const unsub = node2.subscribe(() => {
1005
- values[field] = node2.get();
1043
+ values[field] = node2.cache;
1006
1044
  scheduleBatch();
1007
1045
  });
1008
1046
  subs.push(unsub);
@@ -1041,16 +1079,20 @@ var zustand_exports = {};
1041
1079
  __export(zustand_exports, {
1042
1080
  create: () => create
1043
1081
  });
1082
+ var alwaysDiffer = () => false;
1044
1083
  function create(initializer) {
1045
1084
  const g = new Graph("zustand");
1046
- const s = state(void 0, { name: "state" });
1085
+ const s = state(void 0, {
1086
+ name: "state",
1087
+ equals: alwaysDiffer
1088
+ });
1047
1089
  g.add("state", s);
1048
- const getState = () => s.get();
1090
+ const getState = () => s.cache;
1049
1091
  const setState = (partial, replace) => {
1050
1092
  const prev = getState();
1051
1093
  const next = typeof partial === "function" ? partial(prev) : partial;
1052
1094
  const nextState = replace ? next : { ...prev, ...next };
1053
- s.down([[DATA, nextState]]);
1095
+ s.emit(nextState);
1054
1096
  };
1055
1097
  const api = {
1056
1098
  getState,
@@ -1075,7 +1117,7 @@ function create(initializer) {
1075
1117
  destroy: g.destroy.bind(g)
1076
1118
  };
1077
1119
  const initialValue = initializer(setState, getState, api);
1078
- s.down([[DATA, initialValue]]);
1120
+ s.emit(initialValue);
1079
1121
  return Object.assign(g, api);
1080
1122
  }
1081
1123
 
@@ -1151,10 +1193,10 @@ function copyMap(m) {
1151
1193
  return new Map(m);
1152
1194
  }
1153
1195
  function readMap(node2) {
1154
- return node2.get() ?? /* @__PURE__ */ new Map();
1196
+ return node2.cache ?? /* @__PURE__ */ new Map();
1155
1197
  }
1156
1198
  function readArray(node2) {
1157
- return node2.get() ?? [];
1199
+ return node2.cache ?? [];
1158
1200
  }
1159
1201
  function cosineSimilarity(a, b) {
1160
1202
  const n = Math.max(a.length, b.length);
@@ -1284,8 +1326,6 @@ function collection(name, opts = {}) {
1284
1326
  graph.add("items", items);
1285
1327
  graph.add("ranked", ranked);
1286
1328
  graph.add("size", size);
1287
- graph.connect("items", "ranked");
1288
- graph.connect("items", "size");
1289
1329
  function effective(entry, now) {
1290
1330
  const ageSeconds = (now - entry.lastAccessNs) / 1e9;
1291
1331
  return decay(entry.baseScore, ageSeconds, decayRate, minScore);
@@ -1443,7 +1483,6 @@ function knowledgeGraph(name) {
1443
1483
  graph.add("entities", entities);
1444
1484
  graph.add("edges", edges);
1445
1485
  graph.add("adjacency", adjacency);
1446
- graph.connect("edges", "adjacency");
1447
1486
  function commitEntities(next) {
1448
1487
  entities.down([[DATA, next]]);
1449
1488
  }
@@ -1507,11 +1546,13 @@ var messaging_exports = {};
1507
1546
  __export(messaging_exports, {
1508
1547
  JobFlowGraph: () => JobFlowGraph,
1509
1548
  JobQueueGraph: () => JobQueueGraph,
1549
+ MessagingHubGraph: () => MessagingHubGraph,
1510
1550
  SubscriptionGraph: () => SubscriptionGraph,
1511
1551
  TopicBridgeGraph: () => TopicBridgeGraph,
1512
1552
  TopicGraph: () => TopicGraph,
1513
1553
  jobFlow: () => jobFlow,
1514
1554
  jobQueue: () => jobQueue,
1555
+ messagingHub: () => messagingHub,
1515
1556
  subscription: () => subscription,
1516
1557
  topic: () => topic,
1517
1558
  topicBridge: () => topicBridge
@@ -1529,7 +1570,24 @@ function messagingMeta(kind, extra) {
1529
1570
  var TopicGraph = class extends Graph {
1530
1571
  _log;
1531
1572
  events;
1573
+ /**
1574
+ * Most recently published value, or `null` when the topic has no entries
1575
+ * yet. Spec §5.12 reserves `undefined` as the protocol-internal "never
1576
+ * sent DATA" sentinel — `null` is the idiomatic "empty / no value" signal
1577
+ * for domain nodes. F7.
1578
+ *
1579
+ * **Caveat when `T` itself includes `null`** (e.g., `topic<number | null>`):
1580
+ * `latest === null` is ambiguous — it could mean "no publish yet" OR "a
1581
+ * `null` value was published". Use {@link hasLatest} to disambiguate, or
1582
+ * observe {@link events} directly and track length yourself.
1583
+ */
1532
1584
  latest;
1585
+ /**
1586
+ * Reactive `true` once the topic has at least one published entry.
1587
+ * Disambiguates "`null` never published" from "`null` was published" when
1588
+ * `T` includes `null`.
1589
+ */
1590
+ hasLatest;
1533
1591
  constructor(name, opts = {}) {
1534
1592
  super(name, opts.graph);
1535
1593
  this._log = reactiveLog([], { name: "events", maxSize: opts.retainedLimit });
@@ -1539,40 +1597,62 @@ var TopicGraph = class extends Graph {
1539
1597
  [this.events],
1540
1598
  ([snapshot]) => {
1541
1599
  const entries = snapshot;
1542
- return entries.length === 0 ? void 0 : entries[entries.length - 1];
1600
+ return entries.length === 0 ? null : entries[entries.length - 1];
1543
1601
  },
1544
1602
  {
1545
1603
  name: "latest",
1546
1604
  describeKind: "derived",
1547
- meta: messagingMeta("topic_latest"),
1548
- initial: void 0
1605
+ meta: messagingMeta("topic_latest")
1549
1606
  }
1550
1607
  );
1551
1608
  this.add("latest", this.latest);
1552
- this.connect("events", "latest");
1553
1609
  this.addDisposer(keepalive(this.latest));
1610
+ this.hasLatest = derived(
1611
+ [this.events],
1612
+ ([snapshot]) => snapshot.length > 0,
1613
+ {
1614
+ name: "hasLatest",
1615
+ describeKind: "derived",
1616
+ meta: messagingMeta("topic_has_latest")
1617
+ }
1618
+ );
1619
+ this.add("hasLatest", this.hasLatest);
1620
+ this.addDisposer(keepalive(this.hasLatest));
1621
+ this.addDisposer(() => {
1622
+ this.events.down([[COMPLETE]]);
1623
+ });
1624
+ this.addDisposer(() => this._log.disposeAllViews());
1554
1625
  }
1555
1626
  publish(value) {
1556
1627
  this._log.append(value);
1557
1628
  }
1558
1629
  retained() {
1559
- return this.events.get();
1630
+ return this.events.cache;
1560
1631
  }
1561
1632
  };
1562
1633
  var SubscriptionGraph = class extends Graph {
1563
1634
  source;
1564
1635
  cursor;
1565
1636
  available;
1637
+ /**
1638
+ * Reference to the upstream topic graph. Intentionally NOT mounted
1639
+ * under this subscription: a subscription is a VIEW over an
1640
+ * externally-owned topic. Double-mounting (e.g. hub-owned topic +
1641
+ * sub-mount here) would make either-side teardown leave the other
1642
+ * holding a dead reference. Node-level `derived([topicEvents], …)`
1643
+ * still wires the data dependency across graph boundaries. D1(e).
1644
+ */
1645
+ topic;
1566
1646
  constructor(name, topicGraph, opts = {}) {
1567
1647
  super(name, opts.graph);
1568
1648
  const initialCursor = requireNonNegativeInt(opts.cursor ?? 0, "subscription cursor");
1569
- this.mount("topic", topicGraph);
1649
+ this.topic = topicGraph;
1570
1650
  const topicEvents = topicGraph.events;
1571
1651
  this.source = derived([topicEvents], ([snapshot]) => snapshot, {
1572
1652
  name: "source",
1573
1653
  describeKind: "derived",
1574
1654
  meta: messagingMeta("subscription_source"),
1575
- initial: topicEvents.get()
1655
+ initial: topicEvents.cache
1576
1656
  });
1577
1657
  this.add("source", this.source);
1578
1658
  this.cursor = state(initialCursor, {
@@ -1596,23 +1676,20 @@ var SubscriptionGraph = class extends Graph {
1596
1676
  }
1597
1677
  );
1598
1678
  this.add("available", this.available);
1599
- this.connect("topic::events", "source");
1600
- this.connect("source", "available");
1601
- this.connect("cursor", "available");
1602
1679
  this.addDisposer(keepalive(this.source));
1603
1680
  this.addDisposer(keepalive(this.available));
1604
1681
  }
1605
1682
  ack(count) {
1606
- const available = this.available.get();
1683
+ const available = this.available.cache;
1607
1684
  const requested = count === void 0 ? available.length : requireNonNegativeInt(count, "subscription ack count");
1608
1685
  const step = Math.min(requested, available.length);
1609
- if (step <= 0) return this.cursor.get();
1610
- const next = this.cursor.get() + step;
1611
- this.cursor.down([[DATA, next]]);
1686
+ if (step <= 0) return this.cursor.cache;
1687
+ const next = this.cursor.cache + step;
1688
+ this.cursor.emit(next);
1612
1689
  return next;
1613
1690
  }
1614
1691
  pull(limit, opts = {}) {
1615
- const available = this.available.get();
1692
+ const available = this.available.cache;
1616
1693
  const max = limit === void 0 ? available.length : requireNonNegativeInt(limit, "subscription pull limit");
1617
1694
  const out = available.slice(0, max);
1618
1695
  if (opts.ack && out.length > 0) this.ack(out.length);
@@ -1641,7 +1718,6 @@ var JobQueueGraph = class extends Graph {
1641
1718
  initial: 0
1642
1719
  });
1643
1720
  this.add("depth", this.depth);
1644
- this.connect("pending", "depth");
1645
1721
  this.addDisposer(keepalive(this.depth));
1646
1722
  }
1647
1723
  enqueue(payload, opts = {}) {
@@ -1665,7 +1741,7 @@ var JobQueueGraph = class extends Graph {
1665
1741
  if (max === 0) return [];
1666
1742
  const out = [];
1667
1743
  while (out.length < max) {
1668
- const ids = this.pending.get();
1744
+ const ids = this.pending.cache;
1669
1745
  if (ids.length === 0) break;
1670
1746
  const id = this._pending.pop(0);
1671
1747
  const job = this._jobs.get(id);
@@ -1734,7 +1810,6 @@ var JobFlowGraph = class extends Graph {
1734
1810
  }
1735
1811
  );
1736
1812
  this.add("completedCount", this.completedCount);
1737
- this.connect("completed", "completedCount");
1738
1813
  this.addDisposer(keepalive(this.completedCount));
1739
1814
  const maxPerPump = Math.max(
1740
1815
  1,
@@ -1774,7 +1849,6 @@ var JobFlowGraph = class extends Graph {
1774
1849
  }
1775
1850
  );
1776
1851
  this.add(`pump_${stage}`, pump);
1777
- this.connect(`${stage}::pending`, `pump_${stage}`);
1778
1852
  this.addDisposer(keepalive(pump));
1779
1853
  }
1780
1854
  }
@@ -1790,7 +1864,7 @@ var JobFlowGraph = class extends Graph {
1790
1864
  return this.queue(this._stageNames[0]).enqueue(payload, opts);
1791
1865
  }
1792
1866
  retainedCompleted() {
1793
- return this.completed.get();
1867
+ return this.completed.cache;
1794
1868
  }
1795
1869
  };
1796
1870
  var TopicBridgeGraph = class extends Graph {
@@ -1828,7 +1902,7 @@ var TopicBridgeGraph = class extends Graph {
1828
1902
  bridged += 1;
1829
1903
  }
1830
1904
  if (bridged > 0) {
1831
- const current = this.bridgedCount.get();
1905
+ const current = this.bridgedCount.cache;
1832
1906
  this.bridgedCount.down([[DATA, current + bridged]]);
1833
1907
  }
1834
1908
  },
@@ -1839,13 +1913,112 @@ var TopicBridgeGraph = class extends Graph {
1839
1913
  }
1840
1914
  );
1841
1915
  this.add("pump", pump);
1842
- this.connect("subscription::available", "pump");
1843
1916
  this.addDisposer(keepalive(pump));
1844
1917
  }
1845
1918
  };
1919
+ var MessagingHubGraph = class extends Graph {
1920
+ _topics = /* @__PURE__ */ new Map();
1921
+ _version = 0;
1922
+ _defaultTopicOptions;
1923
+ constructor(name, opts = {}) {
1924
+ super(name, opts.graph);
1925
+ this._defaultTopicOptions = { ...opts.defaultTopicOptions ?? {} };
1926
+ }
1927
+ /** Monotonic counter advancing on topic create/remove. */
1928
+ get version() {
1929
+ return this._version;
1930
+ }
1931
+ /** Number of topics currently in the hub. */
1932
+ get size() {
1933
+ return this._topics.size;
1934
+ }
1935
+ /** Checks topic existence without creating. */
1936
+ has(name) {
1937
+ return this._topics.has(name);
1938
+ }
1939
+ /** Iterator over topic names. */
1940
+ topicNames() {
1941
+ return this._topics.keys();
1942
+ }
1943
+ /**
1944
+ * Returns the {@link TopicGraph} for `name`, creating lazily on first call.
1945
+ * Subsequent calls with the same name return the same instance (options on
1946
+ * repeat calls are ignored — the topic is already configured).
1947
+ */
1948
+ topic(name, opts) {
1949
+ let t = this._topics.get(name);
1950
+ if (t === void 0) {
1951
+ const effective = { ...this._defaultTopicOptions, ...opts ?? {} };
1952
+ t = new TopicGraph(name, effective);
1953
+ this._topics.set(name, t);
1954
+ this.mount(name, t);
1955
+ this._version += 1;
1956
+ }
1957
+ return t;
1958
+ }
1959
+ /**
1960
+ * Publishes a value to the topic, lazily creating it on first publish.
1961
+ *
1962
+ * **Late-subscriber caveat:** the topic is created lazily, so subscribers
1963
+ * that attach AFTER a publish only see the retained window (governed by
1964
+ * `retainedLimit` on `TopicOptions` / `defaultTopicOptions`). If
1965
+ * `retainedLimit === 0` is set explicitly, early publishes are
1966
+ * effectively dropped — prefer an unset `retainedLimit` (unbounded
1967
+ * retention) or subscribe before publishing when late-subscribers matter.
1968
+ */
1969
+ publish(name, value) {
1970
+ this.topic(name).publish(value);
1971
+ }
1972
+ /**
1973
+ * Bulk publish — issues all publishes inside one outer batch. New topics
1974
+ * are created on demand. No-op if `entries` yields nothing.
1975
+ *
1976
+ * **Iterable consumption (F6):** `entries` is consumed once (single-pass)
1977
+ * INSIDE the batch frame. If the iterator throws mid-way, the batch is
1978
+ * discarded and NO publishes are visible to subscribers (all-or-nothing).
1979
+ * Pass an array or `Set` for multi-shot callers.
1980
+ */
1981
+ publishMany(entries) {
1982
+ batch(() => {
1983
+ for (const [name, value] of entries) {
1984
+ this.topic(name).publish(value);
1985
+ }
1986
+ });
1987
+ }
1988
+ /**
1989
+ * Creates a {@link SubscriptionGraph} over a named topic. The topic is
1990
+ * lazily created if missing. Subscription lifecycle is owned by the caller —
1991
+ * the hub does NOT mount the subscription.
1992
+ *
1993
+ * @param subName - Local name for the subscription graph.
1994
+ * @param topicName - Hub topic to subscribe to.
1995
+ * @param opts - `SubscriptionOptions` (initial cursor, etc.).
1996
+ */
1997
+ subscribe(subName, topicName, opts) {
1998
+ const t = this.topic(topicName);
1999
+ return new SubscriptionGraph(subName, t, opts);
2000
+ }
2001
+ /**
2002
+ * Unmounts and tears down the topic's graph. Returns `true` if the topic
2003
+ * existed. Subscribers receive `TEARDOWN` via {@link Graph.remove}.
2004
+ */
2005
+ removeTopic(name) {
2006
+ if (!this._topics.has(name)) return false;
2007
+ try {
2008
+ this.remove(name);
2009
+ } finally {
2010
+ this._topics.delete(name);
2011
+ this._version += 1;
2012
+ }
2013
+ return true;
2014
+ }
2015
+ };
1846
2016
  function topic(name, opts) {
1847
2017
  return new TopicGraph(name, opts);
1848
2018
  }
2019
+ function messagingHub(name, opts) {
2020
+ return new MessagingHubGraph(name, opts);
2021
+ }
1849
2022
  function subscription(name, topicGraph, opts) {
1850
2023
  return new SubscriptionGraph(name, topicGraph, opts);
1851
2024
  }
@@ -1902,9 +2075,7 @@ function findRegisteredNodePath(graph, target) {
1902
2075
  }
1903
2076
  function registerStep(graph, name, step, depPaths) {
1904
2077
  graph.add(name, step);
1905
- for (const path of depPaths) {
1906
- graph.connect(path, name);
1907
- }
2078
+ void depPaths;
1908
2079
  }
1909
2080
  function baseMeta(kind, meta) {
1910
2081
  return domainMeta("orchestration", kind, meta);
@@ -1933,9 +2104,16 @@ function task(graph, name, run, opts) {
1933
2104
  const depRefs = opts?.deps ?? [];
1934
2105
  const deps = depRefs.map((dep) => resolveDep(graph, dep));
1935
2106
  const { deps: _deps, ...nodeOpts } = opts ?? {};
2107
+ const wrapped = (batchData, actions, ctx) => {
2108
+ const data = batchData.map(
2109
+ (batch2, i) => batch2 != null && batch2.length > 0 ? batch2.at(-1) : ctx.prevData[i]
2110
+ );
2111
+ actions.emit(run(data, ctx));
2112
+ return void 0;
2113
+ };
1936
2114
  const step = node(
1937
2115
  deps.map((d) => d.node),
1938
- run,
2116
+ wrapped,
1939
2117
  {
1940
2118
  ...nodeOpts,
1941
2119
  name,
@@ -1953,7 +2131,7 @@ function task(graph, name, run, opts) {
1953
2131
  }
1954
2132
  function branch(graph, name, source, predicate, opts) {
1955
2133
  const src = resolveDep(graph, source);
1956
- const step = node(
2134
+ const step = derived(
1957
2135
  [src.node],
1958
2136
  ([value]) => ({
1959
2137
  branch: predicate(value) ? "then" : "else",
@@ -1962,7 +2140,6 @@ function branch(graph, name, source, predicate, opts) {
1962
2140
  {
1963
2141
  ...opts,
1964
2142
  name,
1965
- describeKind: "derived",
1966
2143
  meta: baseMeta("branch", opts?.meta)
1967
2144
  }
1968
2145
  );
@@ -1974,18 +2151,28 @@ function valve2(graph, name, source, control, opts) {
1974
2151
  const ctrl = resolveDep(graph, control);
1975
2152
  const step = node(
1976
2153
  [src.node, ctrl.node],
1977
- (_deps, actions) => {
1978
- const opened = ctrl.node.get();
1979
- if (!opened) {
2154
+ (batchData, actions, ctx) => {
2155
+ const batch0 = batchData[0];
2156
+ const batch1 = batchData[1];
2157
+ const ctrlVal = batch1 != null && batch1.length > 0 ? batch1.at(-1) : ctx.prevData[1];
2158
+ if (batch0 == null || batch0.length === 0) {
2159
+ if (batch1 != null && batch1.length > 0 && ctrlVal && ctx.prevData[0] !== void 0) {
2160
+ actions.emit(ctx.prevData[0]);
2161
+ } else {
2162
+ actions.down([[RESOLVED]]);
2163
+ }
2164
+ return;
2165
+ }
2166
+ if (!ctrlVal) {
1980
2167
  actions.down([[RESOLVED]]);
1981
- return void 0;
2168
+ return;
1982
2169
  }
1983
- return src.node.get();
2170
+ for (const v of batch0) actions.emit(v);
1984
2171
  },
1985
2172
  {
1986
2173
  ...opts,
1987
2174
  name,
1988
- describeKind: "operator",
2175
+ describeKind: "derived",
1989
2176
  meta: baseMeta("valve", opts?.meta)
1990
2177
  }
1991
2178
  );
@@ -2003,17 +2190,28 @@ function approval(graph, name, source, approver, opts) {
2003
2190
  const isApproved = opts?.isApproved ?? ((value) => Boolean(value));
2004
2191
  const step = node(
2005
2192
  [src.node, ctrl.node],
2006
- (_deps, actions) => {
2007
- if (!isApproved(ctrl.node.get())) {
2193
+ (batchData, actions, ctx) => {
2194
+ const batch0 = batchData[0];
2195
+ const batch1 = batchData[1];
2196
+ const ctrlVal = batch1 != null && batch1.length > 0 ? batch1.at(-1) : ctx.prevData[1];
2197
+ if (ctrlVal === void 0 || !isApproved(ctrlVal)) {
2008
2198
  actions.down([[RESOLVED]]);
2009
- return void 0;
2199
+ return;
2200
+ }
2201
+ if (batch0 == null || batch0.length === 0) {
2202
+ if (batch1 != null && batch1.length > 0 && ctx.prevData[0] !== void 0) {
2203
+ actions.emit(ctx.prevData[0]);
2204
+ } else {
2205
+ actions.down([[RESOLVED]]);
2206
+ }
2207
+ return;
2010
2208
  }
2011
- return src.node.get();
2209
+ for (const v of batch0) actions.emit(v);
2012
2210
  },
2013
2211
  {
2014
2212
  ...opts,
2015
2213
  name,
2016
- describeKind: "operator",
2214
+ describeKind: "derived",
2017
2215
  meta: baseMeta("approval", opts?.meta)
2018
2216
  }
2019
2217
  );
@@ -2034,12 +2232,17 @@ function gate(graph, name, source, opts) {
2034
2232
  const src = resolveDep(graph, source);
2035
2233
  const pendingNode = state([], { name: "pending", equals: () => false });
2036
2234
  const isOpenNode = state(startOpen, { name: "isOpen" });
2037
- const countNode = node([pendingNode], ([arr]) => arr.length, {
2038
- name: "count",
2039
- describeKind: "derived"
2235
+ const countNode = derived([pendingNode], ([arr]) => arr.length, {
2236
+ name: "count"
2040
2237
  });
2041
2238
  let queue = [];
2042
2239
  let torn = false;
2240
+ let latestIsOpen = startOpen;
2241
+ const isOpenUnsub = isOpenNode.subscribe((msgs) => {
2242
+ for (const m of msgs) {
2243
+ if (m[0] === DATA) latestIsOpen = m[1];
2244
+ }
2245
+ });
2043
2246
  function syncPending() {
2044
2247
  pendingNode.down([[DATA, [...queue]]]);
2045
2248
  }
@@ -2056,38 +2259,37 @@ function gate(graph, name, source, opts) {
2056
2259
  function guardTorn(method) {
2057
2260
  if (torn) throw new Error(`gate: ${method}() called after gate was torn down`);
2058
2261
  }
2059
- const output = node([src.node], () => void 0, {
2060
- name,
2061
- describeKind: "operator",
2062
- meta: baseMeta("gate", opts?.meta),
2063
- onMessage(msg, _depIndex, actions) {
2064
- if (msg[0] === DATA) {
2065
- if (isOpenNode.get()) {
2066
- actions.emit(msg[1]);
2067
- } else {
2068
- enqueue(msg[1]);
2069
- actions.down([[RESOLVED]]);
2070
- }
2071
- return true;
2072
- }
2073
- if (msg[0] === TEARDOWN) {
2262
+ const output = node(
2263
+ [src.node],
2264
+ (batchData, actions, ctx) => {
2265
+ const terminal = ctx.terminalDeps[0];
2266
+ if (terminal !== void 0) {
2074
2267
  torn = true;
2075
2268
  queue = [];
2076
2269
  syncPending();
2077
- actions.down([msg]);
2078
- return true;
2270
+ actions.down(terminal === true ? [[COMPLETE]] : [[ERROR, terminal]]);
2271
+ return;
2079
2272
  }
2080
- if (msg[0] === COMPLETE || msg[0] === ERROR) {
2081
- torn = true;
2082
- queue = [];
2083
- syncPending();
2084
- actions.down([msg]);
2085
- return true;
2273
+ const batch0 = batchData[0];
2274
+ if (batch0 == null || batch0.length === 0) {
2275
+ actions.down([[RESOLVED]]);
2276
+ return;
2086
2277
  }
2087
- actions.down([msg]);
2088
- return true;
2278
+ for (const v of batch0) {
2279
+ if (latestIsOpen) {
2280
+ actions.emit(v);
2281
+ } else {
2282
+ enqueue(v);
2283
+ actions.down([[RESOLVED]]);
2284
+ }
2285
+ }
2286
+ },
2287
+ {
2288
+ name,
2289
+ describeKind: "derived",
2290
+ meta: baseMeta("gate", opts?.meta)
2089
2291
  }
2090
- });
2292
+ );
2091
2293
  const controller = {
2092
2294
  node: output,
2093
2295
  pending: pendingNode,
@@ -2116,12 +2318,14 @@ function gate(graph, name, source, opts) {
2116
2318
  },
2117
2319
  open() {
2118
2320
  guardTorn("open");
2119
- isOpenNode.down([[DATA, true]]);
2120
- const items = dequeue(queue.length);
2121
- for (const item of items) {
2122
- if (torn) break;
2123
- output.down([[DATA, item]]);
2124
- }
2321
+ batch(() => {
2322
+ isOpenNode.down([[DATA, true]]);
2323
+ const items = dequeue(queue.length);
2324
+ for (const item of items) {
2325
+ if (torn) break;
2326
+ output.down([[DATA, item]]);
2327
+ }
2328
+ });
2125
2329
  },
2126
2330
  close() {
2127
2331
  guardTorn("close");
@@ -2129,58 +2333,65 @@ function gate(graph, name, source, opts) {
2129
2333
  }
2130
2334
  };
2131
2335
  graph.addDisposer(countNode.subscribe(() => void 0));
2336
+ graph.addDisposer(isOpenUnsub);
2132
2337
  registerStep(graph, name, output, src.path ? [src.path] : []);
2133
2338
  const internal = new Graph(`${name}_state`);
2134
2339
  internal.add("pending", pendingNode);
2135
2340
  internal.add("isOpen", isOpenNode);
2136
2341
  internal.add("count", countNode);
2137
- internal.connect("pending", "count");
2138
2342
  graph.mount(`${name}_state`, internal);
2139
2343
  return controller;
2140
2344
  }
2141
2345
  function forEach2(graph, name, source, run, opts) {
2142
2346
  const src = resolveDep(graph, source);
2143
2347
  let terminated = false;
2144
- const step = node([src.node], () => void 0, {
2145
- ...opts,
2146
- name,
2147
- describeKind: "effect",
2148
- completeWhenDepsComplete: false,
2149
- meta: baseMeta("forEach", opts?.meta),
2150
- onMessage(msg, depIndex, actions) {
2151
- if (terminated) return true;
2152
- if (depIndex !== 0) {
2153
- actions.down([msg]);
2154
- if (msg[0] === COMPLETE || msg[0] === ERROR) terminated = true;
2155
- return true;
2348
+ const step = node(
2349
+ [src.node],
2350
+ (batchData, actions, ctx) => {
2351
+ if (terminated) {
2352
+ actions.down([[RESOLVED]]);
2353
+ return;
2354
+ }
2355
+ const terminal = ctx.terminalDeps[0];
2356
+ if (terminal !== void 0) {
2357
+ terminated = true;
2358
+ actions.down(terminal === true ? [[COMPLETE]] : [[ERROR, terminal]]);
2359
+ return;
2360
+ }
2361
+ const batch0 = batchData[0];
2362
+ if (batch0 == null || batch0.length === 0) {
2363
+ actions.down([[RESOLVED]]);
2364
+ return;
2156
2365
  }
2157
- if (msg[0] === DATA) {
2366
+ for (const v of batch0) {
2158
2367
  try {
2159
- run(msg[1], actions);
2160
- actions.down([msg]);
2368
+ run(v, actions);
2161
2369
  } catch (err) {
2162
2370
  terminated = true;
2163
2371
  actions.down([[ERROR, err]]);
2372
+ return;
2164
2373
  }
2165
- return true;
2166
2374
  }
2167
- actions.down([msg]);
2168
- if (msg[0] === COMPLETE || msg[0] === ERROR) terminated = true;
2169
- return true;
2375
+ },
2376
+ {
2377
+ ...opts,
2378
+ name,
2379
+ describeKind: "effect",
2380
+ completeWhenDepsComplete: false,
2381
+ meta: baseMeta("forEach", opts?.meta)
2170
2382
  }
2171
- });
2383
+ );
2172
2384
  registerStep(graph, name, step, src.path ? [src.path] : []);
2173
2385
  return step;
2174
2386
  }
2175
2387
  function join(graph, name, deps, opts) {
2176
2388
  const resolved = deps.map((dep) => resolveDep(graph, dep));
2177
- const step = node(
2389
+ const step = derived(
2178
2390
  resolved.map((d) => d.node),
2179
2391
  (values) => values,
2180
2392
  {
2181
2393
  ...opts,
2182
2394
  name,
2183
- describeKind: "derived",
2184
2395
  meta: baseMeta("join", opts?.meta)
2185
2396
  }
2186
2397
  );
@@ -2199,14 +2410,16 @@ function loop(graph, name, source, iterate, opts) {
2199
2410
  const staticIterations = typeof iterRef === "number" ? iterRef : void 0;
2200
2411
  const step = node(
2201
2412
  iterDep ? [src.node, iterDep.node] : [src.node],
2202
- (_deps, actions) => {
2203
- let current = src.node.get();
2204
- const rawCount = staticIterations ?? iterDep?.node.get() ?? 1;
2413
+ (depValues, actions, ctx) => {
2414
+ const batch0 = depValues[0];
2415
+ let current = batch0 != null && batch0.length > 0 ? batch0.at(-1) : ctx.prevData[0];
2416
+ const batch1 = iterDep ? depValues[1] : void 0;
2417
+ const rawCount = staticIterations ?? (iterDep ? batch1 != null && batch1.length > 0 ? batch1.at(-1) : ctx.prevData[1] : 1);
2205
2418
  const count = coerceLoopIterations(rawCount);
2206
2419
  for (let i = 0; i < count; i += 1) {
2207
2420
  current = iterate(current, i, actions);
2208
2421
  }
2209
- return current;
2422
+ actions.emit(current);
2210
2423
  },
2211
2424
  {
2212
2425
  ...opts,
@@ -2262,7 +2475,7 @@ function wait(graph, name, source, ms, opts) {
2262
2475
  for (const id of timers) clearTimeout(id);
2263
2476
  timers.clear();
2264
2477
  }
2265
- const srcVal = src.node.get();
2478
+ const srcVal = src.node.cache;
2266
2479
  const initialOpt = srcVal !== void 0 ? { initial: srcVal } : {};
2267
2480
  const step = node(
2268
2481
  [],
@@ -2307,46 +2520,50 @@ function wait(graph, name, source, ms, opts) {
2307
2520
  ...opts,
2308
2521
  name,
2309
2522
  ...initialOpt,
2310
- describeKind: "operator",
2523
+ describeKind: "derived",
2311
2524
  completeWhenDepsComplete: false,
2312
2525
  meta: baseMeta("wait", opts?.meta)
2313
2526
  }
2314
2527
  );
2315
2528
  graph.add(name, step);
2316
- if (src.path) {
2317
- try {
2318
- graph.connect(src.path, name);
2319
- } catch (e) {
2320
- if (!(e instanceof Error && /dep|edge|connect/i.test(e.message))) throw e;
2321
- }
2322
- }
2323
2529
  return step;
2324
2530
  }
2325
2531
  function onFailure(graph, name, source, recover, opts) {
2326
2532
  const src = resolveDep(graph, source);
2327
2533
  let terminated = false;
2328
- const step = node([src.node], () => void 0, {
2329
- ...opts,
2330
- name,
2331
- describeKind: "operator",
2332
- completeWhenDepsComplete: false,
2333
- meta: baseMeta("onFailure", opts?.meta),
2334
- onMessage(msg, _depIndex, actions) {
2335
- if (terminated) return true;
2336
- if (msg[0] === ERROR) {
2337
- try {
2338
- actions.emit(recover(msg[1], actions));
2339
- } catch (err) {
2340
- terminated = true;
2341
- actions.down([[ERROR, err]]);
2534
+ const step = node(
2535
+ [],
2536
+ (_data, actions) => {
2537
+ const unsub = src.node.subscribe((msgs) => {
2538
+ for (const msg of msgs) {
2539
+ if (terminated) return;
2540
+ if (msg[0] === ERROR) {
2541
+ try {
2542
+ actions.emit(recover(msg[1], actions));
2543
+ } catch (err) {
2544
+ terminated = true;
2545
+ actions.down([[ERROR, err]]);
2546
+ }
2547
+ } else {
2548
+ actions.down([msg]);
2549
+ if (msg[0] === COMPLETE) terminated = true;
2550
+ }
2342
2551
  }
2343
- return true;
2344
- }
2345
- actions.down([msg]);
2346
- if (msg[0] === COMPLETE) terminated = true;
2347
- return true;
2552
+ });
2553
+ return () => unsub();
2554
+ },
2555
+ {
2556
+ ...opts,
2557
+ name,
2558
+ describeKind: "derived",
2559
+ completeWhenDepsComplete: false,
2560
+ // onFailure handles errors via manual subscription (recover callback).
2561
+ // Disable auto-propagation so dep-channel ERROR doesn't terminate this
2562
+ // node before the recover callback has a chance to emit a replacement value.
2563
+ errorWhenDepsError: false,
2564
+ meta: baseMeta("onFailure", opts?.meta)
2348
2565
  }
2349
- });
2566
+ );
2350
2567
  registerStep(graph, name, step, src.path ? [src.path] : []);
2351
2568
  return step;
2352
2569
  }
@@ -2359,7 +2576,7 @@ function isPromiseLike(x) {
2359
2576
  return x != null && typeof x.then === "function";
2360
2577
  }
2361
2578
  function isNodeLike(x) {
2362
- return typeof x === "object" && x !== null && "subscribe" in x && typeof x.subscribe === "function" && "get" in x && typeof x.get === "function";
2579
+ return typeof x === "object" && x !== null && "subscribe" in x && typeof x.subscribe === "function" && "cache" in x;
2363
2580
  }
2364
2581
  function isAsyncIterableLike(x) {
2365
2582
  return x != null && typeof x === "object" && Symbol.asyncIterator in x && typeof x[Symbol.asyncIterator] === "function";
@@ -2367,7 +2584,7 @@ function isAsyncIterableLike(x) {
2367
2584
  var DEFAULT_TIMEOUT_MS = 3e4;
2368
2585
  function firstDataFromNode(resolved, opts) {
2369
2586
  if (resolved.status === "settled") {
2370
- const immediate = resolved.get();
2587
+ const immediate = resolved.cache;
2371
2588
  if (immediate !== void 0) {
2372
2589
  return Promise.resolve(immediate);
2373
2590
  }
@@ -2507,43 +2724,94 @@ function streamExtractor(streamTopic, extractFn, opts) {
2507
2724
  {
2508
2725
  name: opts?.name ?? "extractor",
2509
2726
  describeKind: "derived",
2510
- initial: null
2727
+ initial: null,
2728
+ meta: aiMeta("stream_extractor"),
2729
+ ...opts?.equals ? { equals: opts.equals } : {}
2511
2730
  }
2512
2731
  );
2513
2732
  }
2733
+ var keywordFlagsEqual = (a, b) => {
2734
+ if (a === b) return true;
2735
+ if (a == null || b == null) return a === b;
2736
+ if (a.length !== b.length) return false;
2737
+ for (let i = 0; i < a.length; i++) {
2738
+ const x = a[i];
2739
+ const y = b[i];
2740
+ if (x.label !== y.label || x.pattern !== y.pattern || x.match !== y.match || x.position !== y.position) {
2741
+ return false;
2742
+ }
2743
+ }
2744
+ return true;
2745
+ };
2514
2746
  function keywordFlagExtractor(streamTopic, opts) {
2747
+ const maxPatternLength = opts.maxPatternLength ?? 128;
2515
2748
  return derived(
2516
2749
  [streamTopic.latest],
2517
- ([chunk]) => {
2750
+ ([chunk], ctx) => {
2518
2751
  if (chunk == null) return [];
2519
2752
  const accumulated = chunk.accumulated;
2520
- const flags = [];
2753
+ if (!("flags" in ctx.store)) {
2754
+ ctx.store.flags = [];
2755
+ ctx.store.scannedTo = 0;
2756
+ }
2757
+ const flags = ctx.store.flags;
2758
+ const scannedTo = ctx.store.scannedTo;
2759
+ const startOffset = Math.max(0, scannedTo - maxPatternLength);
2760
+ const region = accumulated.slice(startOffset);
2761
+ let added = false;
2521
2762
  for (const { pattern, label } of opts.patterns) {
2522
2763
  const re = new RegExp(pattern.source, `${pattern.flags.replace("g", "")}g`);
2523
- for (const m of accumulated.matchAll(re)) {
2524
- flags.push({ label, pattern, match: m[0], position: m.index });
2764
+ for (const m of region.matchAll(re)) {
2765
+ const pos = startOffset + m.index;
2766
+ if (pos + m[0].length <= scannedTo) continue;
2767
+ flags.push({ label, pattern, match: m[0], position: pos });
2768
+ added = true;
2525
2769
  }
2526
2770
  }
2527
- return flags;
2771
+ ctx.store.scannedTo = accumulated.length;
2772
+ return added ? [...flags] : flags.slice();
2528
2773
  },
2529
2774
  {
2530
2775
  name: opts.name ?? "keyword-flag-extractor",
2531
2776
  describeKind: "derived",
2532
- initial: []
2777
+ initial: [],
2778
+ meta: aiMeta("keyword_flag_extractor"),
2779
+ equals: keywordFlagsEqual
2533
2780
  }
2534
2781
  );
2535
2782
  }
2783
+ var toolCallsEqual = (a, b) => {
2784
+ if (a === b) return true;
2785
+ if (a == null || b == null) return a === b;
2786
+ if (a.length !== b.length) return false;
2787
+ for (let i = 0; i < a.length; i++) {
2788
+ const x = a[i];
2789
+ const y = b[i];
2790
+ if (x.startIndex !== y.startIndex || x.name !== y.name || x.raw !== y.raw) {
2791
+ return false;
2792
+ }
2793
+ }
2794
+ return true;
2795
+ };
2536
2796
  function toolCallExtractor(streamTopic, opts) {
2537
2797
  return derived(
2538
2798
  [streamTopic.latest],
2539
- ([chunk]) => {
2799
+ ([chunk], ctx) => {
2540
2800
  if (chunk == null) return [];
2541
2801
  const accumulated = chunk.accumulated;
2542
- const calls = [];
2543
- let i = 0;
2802
+ if (!("calls" in ctx.store)) {
2803
+ ctx.store.calls = [];
2804
+ ctx.store.scanFrom = 0;
2805
+ }
2806
+ const calls = ctx.store.calls;
2807
+ let i = ctx.store.scanFrom;
2808
+ let added = false;
2544
2809
  while (i < accumulated.length) {
2545
2810
  const start = accumulated.indexOf("{", i);
2546
- if (start === -1) break;
2811
+ if (start === -1) {
2812
+ ctx.store.scanFrom = accumulated.length;
2813
+ break;
2814
+ }
2547
2815
  let depth = 0;
2548
2816
  let end = -1;
2549
2817
  let inString = false;
@@ -2567,7 +2835,10 @@ function toolCallExtractor(streamTopic, opts) {
2567
2835
  }
2568
2836
  }
2569
2837
  }
2570
- if (end === -1) break;
2838
+ if (end === -1) {
2839
+ ctx.store.scanFrom = start;
2840
+ break;
2841
+ }
2571
2842
  const raw = accumulated.slice(start, end + 1);
2572
2843
  try {
2573
2844
  const parsed = JSON.parse(raw);
@@ -2578,20 +2849,28 @@ function toolCallExtractor(streamTopic, opts) {
2578
2849
  raw,
2579
2850
  startIndex: start
2580
2851
  });
2852
+ added = true;
2581
2853
  }
2582
2854
  } catch {
2583
2855
  }
2584
2856
  i = end + 1;
2857
+ ctx.store.scanFrom = i;
2585
2858
  }
2586
- return calls;
2859
+ return added ? [...calls] : calls.slice();
2587
2860
  },
2588
2861
  {
2589
2862
  name: opts?.name ?? "tool-call-extractor",
2590
2863
  describeKind: "derived",
2591
- initial: []
2864
+ initial: [],
2865
+ meta: aiMeta("tool_call_extractor"),
2866
+ equals: toolCallsEqual
2592
2867
  }
2593
2868
  );
2594
2869
  }
2870
+ var costMeterEqual = (a, b) => {
2871
+ if (a === b) return true;
2872
+ return a.chunkCount === b.chunkCount && a.charCount === b.charCount && a.estimatedTokens === b.estimatedTokens;
2873
+ };
2595
2874
  function costMeterExtractor(streamTopic, opts) {
2596
2875
  const charsPerToken = opts?.charsPerToken ?? 4;
2597
2876
  return derived(
@@ -2609,7 +2888,9 @@ function costMeterExtractor(streamTopic, opts) {
2609
2888
  {
2610
2889
  name: opts?.name ?? "cost-meter",
2611
2890
  describeKind: "derived",
2612
- initial: { chunkCount: 0, charCount: 0, estimatedTokens: 0 }
2891
+ initial: { chunkCount: 0, charCount: 0, estimatedTokens: 0 },
2892
+ meta: aiMeta("cost_meter_extractor"),
2893
+ equals: costMeterEqual
2613
2894
  }
2614
2895
  );
2615
2896
  }
@@ -2761,7 +3042,7 @@ function promptNode(adapter, deps, prompt, opts) {
2761
3042
  const format = opts?.format ?? "text";
2762
3043
  const retries = opts?.retries ?? 0;
2763
3044
  const useCache = opts?.cache ?? false;
2764
- const cache2 = useCache ? /* @__PURE__ */ new Map() : null;
3045
+ const cache = useCache ? /* @__PURE__ */ new Map() : null;
2765
3046
  const messagesNode = derived(
2766
3047
  deps,
2767
3048
  (values) => {
@@ -2784,8 +3065,8 @@ function promptNode(adapter, deps, prompt, opts) {
2784
3065
  return state(null);
2785
3066
  }
2786
3067
  const cacheKey = useCache ? JSON.stringify(msgs.map((m) => [m.role, m.content])) : "";
2787
- if (cache2?.has(cacheKey)) {
2788
- return state(cache2.get(cacheKey));
3068
+ if (cache?.has(cacheKey)) {
3069
+ return state(cache.get(cacheKey));
2789
3070
  }
2790
3071
  async function attempt(remaining) {
2791
3072
  try {
@@ -2798,8 +3079,8 @@ function promptNode(adapter, deps, prompt, opts) {
2798
3079
  });
2799
3080
  if (input && typeof input.then === "function") {
2800
3081
  input.then(resolve, reject);
2801
- } else if (input && typeof input.get === "function") {
2802
- resolve(input.get());
3082
+ } else if (input && typeof input.subscribe === "function") {
3083
+ resolve(input.cache);
2803
3084
  } else {
2804
3085
  resolve(input);
2805
3086
  }
@@ -2811,7 +3092,7 @@ function promptNode(adapter, deps, prompt, opts) {
2811
3092
  } else {
2812
3093
  parsed = content;
2813
3094
  }
2814
- cache2?.set(cacheKey, parsed);
3095
+ cache?.set(cacheKey, parsed);
2815
3096
  return parsed;
2816
3097
  } catch (err) {
2817
3098
  if (remaining > 0) return attempt(remaining - 1);
@@ -2839,17 +3120,15 @@ var ChatStreamGraph = class extends Graph {
2839
3120
  [this.messages],
2840
3121
  ([snapshot]) => {
2841
3122
  const entries = snapshot;
2842
- return entries.length === 0 ? void 0 : entries[entries.length - 1];
3123
+ return entries.length === 0 ? null : entries[entries.length - 1];
2843
3124
  },
2844
3125
  {
2845
3126
  name: "latest",
2846
3127
  describeKind: "derived",
2847
- meta: aiMeta("chat_latest"),
2848
- initial: void 0
3128
+ meta: aiMeta("chat_latest")
2849
3129
  }
2850
3130
  );
2851
3131
  this.add("latest", this.latest);
2852
- this.connect("messages", "latest");
2853
3132
  this.addDisposer(keepalive(this.latest));
2854
3133
  this.messageCount = derived(
2855
3134
  [this.messages],
@@ -2862,7 +3141,6 @@ var ChatStreamGraph = class extends Graph {
2862
3141
  }
2863
3142
  );
2864
3143
  this.add("messageCount", this.messageCount);
2865
- this.connect("messages", "messageCount");
2866
3144
  this.addDisposer(keepalive(this.messageCount));
2867
3145
  }
2868
3146
  append(role, content, extra) {
@@ -2875,7 +3153,7 @@ var ChatStreamGraph = class extends Graph {
2875
3153
  this._log.clear();
2876
3154
  }
2877
3155
  allMessages() {
2878
- return this.messages.get();
3156
+ return this.messages.cache;
2879
3157
  }
2880
3158
  };
2881
3159
  function chatStream(name, opts) {
@@ -2903,31 +3181,30 @@ var ToolRegistryGraph = class extends Graph {
2903
3181
  }
2904
3182
  );
2905
3183
  this.add("schemas", this.schemas);
2906
- this.connect("definitions", "schemas");
2907
3184
  this.addDisposer(keepalive(this.schemas));
2908
3185
  }
2909
3186
  register(tool) {
2910
- const current = this.definitions.get();
3187
+ const current = this.definitions.cache;
2911
3188
  const next = new Map(current);
2912
3189
  next.set(tool.name, tool);
2913
3190
  this.definitions.down([[DATA, next]]);
2914
3191
  }
2915
3192
  unregister(name) {
2916
- const current = this.definitions.get();
3193
+ const current = this.definitions.cache;
2917
3194
  if (!current.has(name)) return;
2918
3195
  const next = new Map(current);
2919
3196
  next.delete(name);
2920
3197
  this.definitions.down([[DATA, next]]);
2921
3198
  }
2922
3199
  async execute(name, args) {
2923
- const defs = this.definitions.get();
3200
+ const defs = this.definitions.cache;
2924
3201
  const tool = defs.get(name);
2925
3202
  if (!tool) throw new Error(`toolRegistry: unknown tool "${name}"`);
2926
3203
  const raw = tool.handler(args);
2927
3204
  return resolveToolHandlerResult(raw);
2928
3205
  }
2929
3206
  getDefinition(name) {
2930
- return this.definitions.get().get(name);
3207
+ return this.definitions.cache?.get(name);
2931
3208
  }
2932
3209
  };
2933
3210
  function toolRegistry(name, opts) {
@@ -2962,7 +3239,7 @@ function llmExtractor(systemPrompt, opts) {
2962
3239
  })
2963
3240
  }
2964
3241
  ];
2965
- return producer((_deps, actions) => {
3242
+ return producer((actions) => {
2966
3243
  let active = true;
2967
3244
  const result = opts.adapter.invoke(messages, {
2968
3245
  model: opts.model,
@@ -3012,7 +3289,7 @@ function llmConsolidator(systemPrompt, opts) {
3012
3289
  { role: "system", content: systemPrompt },
3013
3290
  { role: "user", content: JSON.stringify({ memories: entriesArray }) }
3014
3291
  ];
3015
- return producer((_deps, actions) => {
3292
+ return producer((actions) => {
3016
3293
  let active = true;
3017
3294
  const result = opts.adapter.invoke(messages, {
3018
3295
  model: opts.model,
@@ -3127,8 +3404,6 @@ function agentMemory(name, source, opts) {
3127
3404
  graph.add("store", distillBundle.store.entries);
3128
3405
  graph.add("compact", distillBundle.compact);
3129
3406
  graph.add("size", distillBundle.size);
3130
- graph.connect("store", "compact");
3131
- graph.connect("store", "size");
3132
3407
  let vectors = null;
3133
3408
  if (opts.vectorDimensions && opts.vectorDimensions > 0 && opts.embedFn) {
3134
3409
  vectors = vectorIndex({ dimension: opts.vectorDimensions });
@@ -3151,7 +3426,7 @@ function agentMemory(name, source, opts) {
3151
3426
  const permanentKeys = /* @__PURE__ */ new Set();
3152
3427
  const tierOf = (key) => {
3153
3428
  if (permanentKeys.has(key)) return "permanent";
3154
- const storeMap = extractStoreMap(distillBundle.store.entries.get());
3429
+ const storeMap = extractStoreMap(distillBundle.store.entries.cache);
3155
3430
  if (storeMap.has(key)) return "active";
3156
3431
  return "archived";
3157
3432
  };
@@ -3210,10 +3485,10 @@ function agentMemory(name, source, opts) {
3210
3485
  });
3211
3486
  keepaliveSubs.push(tierClassifier.subscribe(() => void 0));
3212
3487
  let archiveHandle = null;
3213
- if (tiersOpts.archiveAdapter) {
3214
- archiveHandle = graph.autoCheckpoint(
3215
- tiersOpts.archiveAdapter,
3216
- tiersOpts.archiveCheckpointOptions
3488
+ if (tiersOpts.archiveTier) {
3489
+ archiveHandle = graph.attachStorage(
3490
+ [tiersOpts.archiveTier],
3491
+ tiersOpts.archiveStorageOptions ?? {}
3217
3492
  );
3218
3493
  }
3219
3494
  memoryTiersBundle = {
@@ -3259,12 +3534,14 @@ function agentMemory(name, source, opts) {
3259
3534
  const budget = opts.budget ?? 2e3;
3260
3535
  const costFn = opts.cost;
3261
3536
  const scoreFn = opts.score;
3262
- const queryInput = state(null, {
3263
- name: "retrievalQuery",
3264
- describeKind: "state"
3265
- });
3266
- graph.add("retrievalQuery", queryInput);
3267
3537
  const contextNode = opts.context ? fromAny(opts.context) : state(null);
3538
+ const retrievalOutput = state([], {
3539
+ name: "retrieval",
3540
+ describeKind: "state",
3541
+ meta: aiMeta("retrieval_pipeline")
3542
+ });
3543
+ graph.add("retrieval", retrievalOutput);
3544
+ retrievalNode = retrievalOutput;
3268
3545
  const traceState = state(null, {
3269
3546
  name: "retrievalTrace",
3270
3547
  describeKind: "state",
@@ -3272,97 +3549,81 @@ function agentMemory(name, source, opts) {
3272
3549
  });
3273
3550
  graph.add("retrievalTrace", traceState);
3274
3551
  retrievalTraceNode = traceState;
3275
- const storeNode = distillBundle.store.entries;
3276
- let lastTrace = null;
3277
- const retrievalDerived = derived(
3278
- [queryInput, storeNode, contextNode],
3279
- ([query, snapshot, ctx]) => {
3280
- if (!query) return [];
3281
- const q = query;
3282
- const storeMap = extractStoreMap(snapshot);
3283
- const candidateMap = /* @__PURE__ */ new Map();
3284
- let vectorCandidates = [];
3285
- if (vectors && q.vector) {
3286
- vectorCandidates = vectors.search(q.vector, topK);
3287
- for (const vc of vectorCandidates) {
3288
- const mem = storeMap.get(vc.id);
3289
- if (mem) {
3290
- candidateMap.set(vc.id, { value: mem, sources: /* @__PURE__ */ new Set(["vector"]) });
3291
- }
3552
+ retrieveFn = (query) => {
3553
+ const storeMap = extractStoreMap(distillBundle.store.entries.cache);
3554
+ const ctx = contextNode.cache;
3555
+ const candidateMap = /* @__PURE__ */ new Map();
3556
+ let vectorCandidates = [];
3557
+ if (vectors && query.vector) {
3558
+ vectorCandidates = vectors.search(query.vector, topK);
3559
+ for (const vc of vectorCandidates) {
3560
+ const mem = storeMap.get(vc.id);
3561
+ if (mem) {
3562
+ candidateMap.set(vc.id, { value: mem, sources: /* @__PURE__ */ new Set(["vector"]) });
3292
3563
  }
3293
3564
  }
3294
- const graphExpanded = [];
3295
- if (kg) {
3296
- const seedIds = [...q.entityIds ?? [], ...[...candidateMap.keys()]];
3297
- const visited = /* @__PURE__ */ new Set();
3298
- let frontier = seedIds;
3299
- for (let depth = 0; depth < graphDepth; depth++) {
3300
- const nextFrontier = [];
3301
- for (const id of frontier) {
3302
- if (visited.has(id)) continue;
3303
- visited.add(id);
3304
- const related = kg.related(id);
3305
- for (const edge of related) {
3306
- const targetId = edge.to;
3307
- if (!visited.has(targetId)) {
3308
- nextFrontier.push(targetId);
3309
- const mem = storeMap.get(targetId);
3310
- if (mem) {
3311
- const existing = candidateMap.get(targetId);
3312
- if (existing) {
3313
- existing.sources.add("graph");
3314
- } else {
3315
- candidateMap.set(targetId, { value: mem, sources: /* @__PURE__ */ new Set(["graph"]) });
3316
- }
3317
- graphExpanded.push(targetId);
3565
+ }
3566
+ const graphExpanded = [];
3567
+ if (kg) {
3568
+ const seedIds = [...query.entityIds ?? [], ...[...candidateMap.keys()]];
3569
+ const visited = /* @__PURE__ */ new Set();
3570
+ let frontier = seedIds;
3571
+ for (let depth = 0; depth < graphDepth; depth++) {
3572
+ const nextFrontier = [];
3573
+ for (const id of frontier) {
3574
+ if (visited.has(id)) continue;
3575
+ visited.add(id);
3576
+ const related = kg.related(id);
3577
+ for (const edge of related) {
3578
+ const targetId = edge.to;
3579
+ if (!visited.has(targetId)) {
3580
+ nextFrontier.push(targetId);
3581
+ const mem = storeMap.get(targetId);
3582
+ if (mem) {
3583
+ const existing = candidateMap.get(targetId);
3584
+ if (existing) {
3585
+ existing.sources.add("graph");
3586
+ } else {
3587
+ candidateMap.set(targetId, { value: mem, sources: /* @__PURE__ */ new Set(["graph"]) });
3318
3588
  }
3589
+ graphExpanded.push(targetId);
3319
3590
  }
3320
3591
  }
3321
3592
  }
3322
- frontier = nextFrontier;
3323
3593
  }
3594
+ frontier = nextFrontier;
3324
3595
  }
3325
- for (const [key, mem] of storeMap) {
3326
- if (!candidateMap.has(key)) {
3327
- candidateMap.set(key, { value: mem, sources: /* @__PURE__ */ new Set(["store"]) });
3328
- }
3329
- }
3330
- const ranked = [];
3331
- for (const [key, { value, sources }] of candidateMap) {
3332
- const score = scoreFn(value, ctx);
3333
- ranked.push({ key, value, score, sources: [...sources] });
3334
- }
3335
- ranked.sort((a, b) => b.score - a.score);
3336
- const packed = [];
3337
- let usedBudget = 0;
3338
- for (const entry of ranked) {
3339
- const c = costFn(entry.value);
3340
- if (usedBudget + c > budget && packed.length > 0) break;
3341
- packed.push(entry);
3342
- usedBudget += c;
3596
+ }
3597
+ for (const [key, mem] of storeMap) {
3598
+ if (!candidateMap.has(key)) {
3599
+ candidateMap.set(key, { value: mem, sources: /* @__PURE__ */ new Set(["store"]) });
3343
3600
  }
3344
- lastTrace = { vectorCandidates, graphExpanded, ranked, packed };
3345
- return packed;
3346
- },
3347
- {
3348
- name: "retrieval",
3349
- describeKind: "derived",
3350
- meta: aiMeta("retrieval_pipeline"),
3351
- initial: []
3352
3601
  }
3353
- );
3354
- graph.add("retrieval", retrievalDerived);
3355
- graph.connect("retrievalQuery", "retrieval");
3356
- graph.connect("store", "retrieval");
3357
- keepaliveSubs.push(retrievalDerived.subscribe(() => void 0));
3358
- retrievalNode = retrievalDerived;
3359
- retrieveFn = (query) => {
3360
- queryInput.down([[DATA, query]]);
3361
- const result = retrievalDerived.get();
3362
- if (lastTrace) {
3363
- traceState.down([[DATA, lastTrace]]);
3602
+ const ranked = [];
3603
+ for (const [key, { value, sources }] of candidateMap) {
3604
+ const score = scoreFn(value, ctx);
3605
+ ranked.push({ key, value, score, sources: [...sources] });
3364
3606
  }
3365
- return result;
3607
+ ranked.sort((a, b) => b.score - a.score);
3608
+ const packed = [];
3609
+ let usedBudget = 0;
3610
+ for (const entry of ranked) {
3611
+ const c = costFn(entry.value);
3612
+ if (usedBudget + c > budget && packed.length > 0) break;
3613
+ packed.push(entry);
3614
+ usedBudget += c;
3615
+ }
3616
+ const trace = {
3617
+ vectorCandidates,
3618
+ graphExpanded,
3619
+ ranked,
3620
+ packed
3621
+ };
3622
+ batch(() => {
3623
+ retrievalOutput.down([[DATA, packed]]);
3624
+ traceState.down([[DATA, trace]]);
3625
+ });
3626
+ return packed;
3366
3627
  };
3367
3628
  }
3368
3629
  graph.addDisposer(() => {
@@ -3466,7 +3727,7 @@ var AgentLoopGraph = class extends Graph {
3466
3727
  this._statusState.down([[DATA, "thinking"]]);
3467
3728
  });
3468
3729
  const msgs = this.chat.allMessages();
3469
- const toolSchemas = this.tools.schemas.get() ?? [];
3730
+ const toolSchemas = this.tools.schemas.cache ?? [];
3470
3731
  const response = await this._invokeLLM(msgs, toolSchemas, signal);
3471
3732
  if (signal.aborted) throw new Error("agentLoop: aborted");
3472
3733
  this.lastResponse.down([[DATA, response]]);
@@ -3501,7 +3762,7 @@ var AgentLoopGraph = class extends Graph {
3501
3762
  this._statusState.down([[DATA, "done"]]);
3502
3763
  this._running = false;
3503
3764
  this._abortController = null;
3504
- return this.lastResponse.get();
3765
+ return this.lastResponse.cache;
3505
3766
  } catch (err) {
3506
3767
  this._statusState.down([[DATA, "error"]]);
3507
3768
  this._running = false;
@@ -3997,7 +4258,7 @@ function demoShell(opts) {
3997
4258
  ([ref, _tick]) => {
3998
4259
  const demo = ref;
3999
4260
  if (!demo) return "";
4000
- return demo.toMermaid();
4261
+ return demo.describe({ format: "mermaid" });
4001
4262
  },
4002
4263
  { name: "graph/mermaid" }
4003
4264
  );
@@ -4053,7 +4314,6 @@ function demoShell(opts) {
4053
4314
  cb(line);
4054
4315
  });
4055
4316
  g.add("highlight/apply-code-scroll", applyCodeScroll);
4056
- g.connect("highlight/code-scroll", "highlight/apply-code-scroll");
4057
4317
  }
4058
4318
  if (onHighlight?.visual) {
4059
4319
  const cb = onHighlight.visual;
@@ -4061,7 +4321,6 @@ function demoShell(opts) {
4061
4321
  cb(selector);
4062
4322
  });
4063
4323
  g.add("highlight/apply-visual", applyVisual);
4064
- g.connect("highlight/visual", "highlight/apply-visual");
4065
4324
  }
4066
4325
  if (onHighlight?.graph) {
4067
4326
  const cb = onHighlight.graph;
@@ -4069,7 +4328,6 @@ function demoShell(opts) {
4069
4328
  cb(nodeId);
4070
4329
  });
4071
4330
  g.add("highlight/apply-graph", applyGraph);
4072
- g.connect("highlight/graph", "highlight/apply-graph");
4073
4331
  }
4074
4332
  const inspectSelected = state(null, {
4075
4333
  name: "inspect/selected-node"
@@ -4085,7 +4343,7 @@ function demoShell(opts) {
4085
4343
  try {
4086
4344
  const nd = demo.resolve(p);
4087
4345
  const nodeDesc = describeNode(nd, standardFields);
4088
- return { path: p, ...nodeDesc, value: nd.get() };
4346
+ return { path: p, ...nodeDesc, value: nd.cache };
4089
4347
  } catch {
4090
4348
  return null;
4091
4349
  }
@@ -4109,7 +4367,7 @@ function demoShell(opts) {
4109
4367
  [metaDebug, demoGraphTick],
4110
4368
  ([debug, _tick]) => {
4111
4369
  if (!debug) return "";
4112
- return g.toMermaid();
4370
+ return g.describe({ format: "mermaid" });
4113
4371
  },
4114
4372
  { name: "meta/shell-mermaid" }
4115
4373
  );
@@ -4175,35 +4433,7 @@ function demoShell(opts) {
4175
4433
  g.add("layout/graph-labels", graphLabels);
4176
4434
  g.add("layout/code-lines", codeLines);
4177
4435
  g.add("layout/side-width-hint", sideWidthHint);
4178
- g.connect("graph/describe", "layout/graph-labels");
4179
- g.connect("layout/code-text", "layout/code-lines");
4180
- g.connect("pane/side-width", "layout/code-lines");
4181
- g.connect("layout/graph-labels", "layout/side-width-hint");
4182
- }
4183
- g.connect("pane/main-ratio", "pane/main-width");
4184
- g.connect("viewport/width", "pane/main-width");
4185
- g.connect("pane/fullscreen", "pane/main-width");
4186
- g.connect("pane/main-width", "pane/side-width");
4187
- g.connect("viewport/width", "pane/side-width");
4188
- g.connect("pane/fullscreen", "pane/side-width");
4189
- g.connect("pane/side-split", "pane/graph-height-ratio");
4190
- g.connect("pane/fullscreen", "pane/graph-height-ratio");
4191
- g.connect("pane/graph-height-ratio", "pane/code-height-ratio");
4192
- g.connect("pane/fullscreen", "pane/code-height-ratio");
4193
- g.connect("demo/graph-ref", "graph/mermaid");
4194
- g.connect("demo/graph-tick", "graph/mermaid");
4195
- g.connect("demo/graph-ref", "graph/describe");
4196
- g.connect("demo/graph-tick", "graph/describe");
4197
- g.connect("hover/target", "highlight/code-scroll");
4198
- g.connect("hover/target", "highlight/visual");
4199
- g.connect("hover/target", "highlight/graph");
4200
- g.connect("inspect/selected-node", "inspect/node-detail");
4201
- g.connect("demo/graph-ref", "inspect/node-detail");
4202
- g.connect("demo/graph-tick", "inspect/node-detail");
4203
- g.connect("demo/graph-ref", "inspect/trace-log");
4204
- g.connect("demo/graph-tick", "inspect/trace-log");
4205
- g.connect("meta/debug", "meta/shell-mermaid");
4206
- g.connect("demo/graph-tick", "meta/shell-mermaid");
4436
+ }
4207
4437
  let tickCounter = 0;
4208
4438
  return {
4209
4439
  graph: g,
@@ -4288,14 +4518,14 @@ function _addBranch(graph, source, rulesNode, rule) {
4288
4518
  let sourcePhase2 = false;
4289
4519
  let sourceValue = _noValue;
4290
4520
  let pendingDirty = false;
4521
+ let latestRules = rulesNode.cache ?? [];
4291
4522
  function resolve(actions) {
4292
4523
  if (sourcePhase2) {
4293
4524
  sourcePhase2 = false;
4294
4525
  const value = sourceValue;
4295
4526
  sourceValue = _noValue;
4296
4527
  if (value !== _noValue) {
4297
- const currentRules = rulesNode.get();
4298
- const currentRule = currentRules.find((r) => r.name === rule.name);
4528
+ const currentRule = latestRules.find((r) => r.name === rule.name);
4299
4529
  let matches = false;
4300
4530
  try {
4301
4531
  matches = currentRule?.classify(value) ?? false;
@@ -4321,55 +4551,75 @@ function _addBranch(graph, source, rulesNode, rule) {
4321
4551
  }
4322
4552
  }
4323
4553
  }
4324
- const filterNode = node([source, rulesNode], () => void 0, {
4325
- describeKind: "operator",
4326
- meta: baseMeta2("stratify_branch", { branch: rule.name }),
4327
- onMessage(msg, depIndex, actions) {
4328
- const t = msg[0];
4329
- if (t === DIRTY) {
4330
- if (depIndex === 0) {
4331
- sourceDirty = true;
4332
- pendingDirty = true;
4333
- } else {
4334
- rulesDirty = true;
4554
+ const filterNode = node(
4555
+ [],
4556
+ (_data, filterActions) => {
4557
+ const srcUnsub = source.subscribe((msgs) => {
4558
+ for (const msg of msgs) {
4559
+ _handleStratifyMessage(msg, 0, filterActions);
4335
4560
  }
4336
- return true;
4337
- }
4338
- if (t === DATA || t === RESOLVED) {
4339
- if (depIndex === 0) {
4340
- sourceDirty = false;
4341
- sourcePhase2 = true;
4342
- sourceValue = t === DATA ? msg[1] : _noValue;
4343
- } else {
4344
- rulesDirty = false;
4561
+ });
4562
+ const rulesUnsub = rulesNode.subscribe((msgs) => {
4563
+ for (const msg of msgs) {
4564
+ _handleStratifyMessage(msg, 1, filterActions);
4345
4565
  }
4346
- if (sourceDirty || rulesDirty) return true;
4347
- resolve(actions);
4348
- return true;
4566
+ });
4567
+ return () => {
4568
+ srcUnsub();
4569
+ rulesUnsub();
4570
+ };
4571
+ },
4572
+ {
4573
+ describeKind: "derived",
4574
+ meta: baseMeta2("stratify_branch", { branch: rule.name }),
4575
+ completeWhenDepsComplete: false
4576
+ }
4577
+ );
4578
+ function _handleStratifyMessage(msg, depIndex, actions) {
4579
+ const t = msg[0];
4580
+ if (t === DIRTY) {
4581
+ if (depIndex === 0) {
4582
+ sourceDirty = true;
4583
+ pendingDirty = true;
4584
+ } else {
4585
+ rulesDirty = true;
4349
4586
  }
4350
- if (t === COMPLETE || t === ERROR || t === TEARDOWN) {
4587
+ return true;
4588
+ }
4589
+ if (t === DATA || t === RESOLVED) {
4590
+ if (depIndex === 0) {
4351
4591
  sourceDirty = false;
4352
- rulesDirty = false;
4353
- sourcePhase2 = false;
4354
- sourceValue = _noValue;
4355
- pendingDirty = false;
4356
- if (depIndex === 0) {
4357
- actions.down([msg]);
4592
+ sourcePhase2 = true;
4593
+ sourceValue = t === DATA ? msg[1] : _noValue;
4594
+ } else {
4595
+ if (t === DATA) {
4596
+ latestRules = msg[1];
4358
4597
  }
4359
- return true;
4598
+ rulesDirty = false;
4360
4599
  }
4361
- if (depIndex === 1) return true;
4362
- return false;
4363
- },
4364
- completeWhenDepsComplete: false
4365
- });
4600
+ if (sourceDirty || rulesDirty) return true;
4601
+ resolve(actions);
4602
+ return true;
4603
+ }
4604
+ if (t === COMPLETE || t === ERROR || t === TEARDOWN) {
4605
+ sourceDirty = false;
4606
+ rulesDirty = false;
4607
+ sourcePhase2 = false;
4608
+ sourceValue = _noValue;
4609
+ pendingDirty = false;
4610
+ if (depIndex === 0) {
4611
+ actions.down([msg]);
4612
+ }
4613
+ return true;
4614
+ }
4615
+ if (depIndex === 1) return true;
4616
+ return false;
4617
+ }
4366
4618
  graph.add(branchName, filterNode);
4367
- graph.connect("source", branchName);
4368
4619
  if (rule.ops) {
4369
4620
  const transformed = rule.ops(filterNode);
4370
4621
  const transformedName = `branch/${rule.name}/out`;
4371
4622
  graph.add(transformedName, transformed);
4372
- graph.connect(branchName, transformedName);
4373
4623
  }
4374
4624
  }
4375
4625
  function funnel(name, sources, stages, opts) {
@@ -4398,12 +4648,14 @@ function funnel(name, sources, stages, opts) {
4398
4648
  const stageInputPath = `${stage.name}::input`;
4399
4649
  const stageInput = g.resolve(stageInputPath);
4400
4650
  const bridgeName = `__bridge_${prevOutputPath}\u2192${stage.name}_input`;
4401
- const br = bridge(prevNode, stageInput, {
4402
- name: bridgeName,
4403
- down: DEFAULT_DOWN.filter((t) => t !== TEARDOWN)
4404
- });
4651
+ const br = effect(
4652
+ [prevNode],
4653
+ ([data]) => {
4654
+ stageInput.down([[DATA, data]]);
4655
+ },
4656
+ { name: bridgeName }
4657
+ );
4405
4658
  g.add(bridgeName, br);
4406
- g.connect(prevOutputPath, bridgeName);
4407
4659
  g.addDisposer(keepalive(br));
4408
4660
  prevOutputPath = `${stage.name}::output`;
4409
4661
  }
@@ -4423,39 +4675,41 @@ function feedback(graph, condition, reentry, opts) {
4423
4675
  const condNode = graph.resolve(condition);
4424
4676
  const reentryNode = graph.resolve(reentry);
4425
4677
  const feedbackEffectName = `__feedback_effect_${condition}`;
4426
- const feedbackEffect = node([condNode], void 0, {
4427
- name: feedbackEffectName,
4428
- describeKind: "effect",
4429
- meta: {
4430
- ...baseMeta2("feedback_effect", {
4431
- feedbackFrom: condition,
4432
- feedbackTo: reentry
4433
- }),
4434
- _internal: true
4678
+ const feedbackEffect = node(
4679
+ [],
4680
+ (_data, _feedbackActions) => {
4681
+ const unsub = condNode.subscribe((msgs) => {
4682
+ for (const msg of msgs) {
4683
+ const t = msg[0];
4684
+ if (t === DATA) {
4685
+ const condValue = msg[1];
4686
+ if (condValue == null) return;
4687
+ batch(() => {
4688
+ if (tryIncrementBounded(counter, maxIter)) {
4689
+ reentryNode.down([[DATA, condValue]]);
4690
+ }
4691
+ });
4692
+ } else if (t === COMPLETE || t === ERROR) {
4693
+ const terminal = t === ERROR && msg.length > 1 ? [ERROR, msg[1]] : [t];
4694
+ counter.down([terminal]);
4695
+ }
4696
+ }
4697
+ });
4698
+ return () => unsub();
4435
4699
  },
4436
- onMessage(msg, _depIndex, _actions) {
4437
- const t = msg[0];
4438
- if (t === DATA) {
4439
- const currentCount = counter.get();
4440
- if (currentCount >= maxIter) return true;
4441
- const condValue = msg[1];
4442
- if (condValue == null) return true;
4443
- batch(() => {
4444
- counter.down([[DATA, currentCount + 1]]);
4445
- reentryNode.down([[DATA, condValue]]);
4446
- });
4447
- return true;
4448
- }
4449
- if (t === COMPLETE || t === ERROR) {
4450
- const terminal = t === ERROR && msg.length > 1 ? [ERROR, msg[1]] : [t];
4451
- counter.down([terminal]);
4452
- return true;
4700
+ {
4701
+ name: feedbackEffectName,
4702
+ describeKind: "effect",
4703
+ meta: {
4704
+ ...baseMeta2("feedback_effect", {
4705
+ feedbackFrom: condition,
4706
+ feedbackTo: reentry
4707
+ }),
4708
+ _internal: true
4453
4709
  }
4454
- return false;
4455
4710
  }
4456
- });
4711
+ );
4457
4712
  graph.add(feedbackEffectName, feedbackEffect);
4458
- graph.connect(condition, feedbackEffectName);
4459
4713
  graph.addDisposer(keepalive(feedbackEffect));
4460
4714
  return graph;
4461
4715
  }
@@ -4467,8 +4721,9 @@ function budgetGate(source, constraints, opts) {
4467
4721
  let paused = false;
4468
4722
  let pendingResolved = false;
4469
4723
  const lockId = /* @__PURE__ */ Symbol("budget-gate");
4724
+ const latestValues = new Array(constraints.length);
4470
4725
  function checkBudget() {
4471
- return constraints.every((c) => c.check(c.node.get()));
4726
+ return constraints.every((c, i) => c.check(latestValues[i]));
4472
4727
  }
4473
4728
  function flushBuffer(actions) {
4474
4729
  while (buffer2.length > 0 && checkBudget()) {
@@ -4481,78 +4736,103 @@ function budgetGate(source, constraints, opts) {
4481
4736
  actions.down([[RESOLVED]]);
4482
4737
  }
4483
4738
  }
4484
- return node(allDeps, () => void 0, {
4485
- ...opts,
4486
- describeKind: "operator",
4487
- meta: baseMeta2("budget_gate", opts?.meta),
4488
- onMessage(msg, depIndex, actions) {
4489
- const t = msg[0];
4490
- if (depIndex === 0) {
4491
- if (t === DATA) {
4492
- if (checkBudget() && buffer2.length === 0) {
4493
- actions.emit(msg[1]);
4494
- } else {
4495
- buffer2.push(msg[1]);
4496
- if (!paused) {
4497
- paused = true;
4498
- actions.up([[PAUSE, lockId]]);
4739
+ return node(
4740
+ [],
4741
+ (_data, gateActions) => {
4742
+ for (let i = 0; i < constraints.length; i++) {
4743
+ latestValues[i] = constraints[i].node.cache;
4744
+ }
4745
+ const unsubs = [];
4746
+ for (let depIdx = 0; depIdx < allDeps.length; depIdx++) {
4747
+ const dep = allDeps[depIdx];
4748
+ unsubs.push(
4749
+ dep.subscribe((msgs) => {
4750
+ for (const msg of msgs) {
4751
+ _handleBudgetMessage(msg, depIdx, gateActions);
4499
4752
  }
4500
- }
4501
- return true;
4502
- }
4503
- if (t === DIRTY) {
4504
- actions.down([[DIRTY]]);
4505
- return true;
4506
- }
4507
- if (t === RESOLVED) {
4508
- if (buffer2.length === 0) {
4509
- actions.down([[RESOLVED]]);
4510
- } else {
4511
- pendingResolved = true;
4512
- }
4513
- return true;
4514
- }
4515
- if (t === COMPLETE || t === ERROR) {
4516
- for (const item of buffer2) {
4517
- actions.emit(item);
4518
- }
4519
- buffer2 = [];
4520
- pendingResolved = false;
4521
- if (paused) {
4522
- paused = false;
4523
- actions.up([[RESUME, lockId]]);
4524
- }
4525
- actions.down([msg]);
4526
- return true;
4527
- }
4528
- return false;
4753
+ })
4754
+ );
4529
4755
  }
4530
- if (t === DATA || t === RESOLVED) {
4531
- if (checkBudget() && buffer2.length > 0) {
4532
- flushBuffer(actions);
4533
- if (buffer2.length === 0 && paused) {
4534
- paused = false;
4535
- actions.up([[RESUME, lockId]]);
4756
+ return () => {
4757
+ for (const u of unsubs) u();
4758
+ };
4759
+ },
4760
+ {
4761
+ ...opts,
4762
+ describeKind: "derived",
4763
+ meta: baseMeta2("budget_gate", opts?.meta)
4764
+ }
4765
+ );
4766
+ function _handleBudgetMessage(msg, depIndex, actions) {
4767
+ const t = msg[0];
4768
+ if (depIndex === 0) {
4769
+ if (t === DATA) {
4770
+ if (checkBudget() && buffer2.length === 0) {
4771
+ actions.emit(msg[1]);
4772
+ } else {
4773
+ buffer2.push(msg[1]);
4774
+ if (!paused) {
4775
+ paused = true;
4776
+ actions.up([[PAUSE, lockId]]);
4536
4777
  }
4537
- } else if (!checkBudget() && !paused && buffer2.length > 0) {
4538
- paused = true;
4539
- actions.up([[PAUSE, lockId]]);
4540
4778
  }
4541
4779
  return true;
4542
4780
  }
4543
4781
  if (t === DIRTY) {
4782
+ actions.down([[DIRTY]]);
4544
4783
  return true;
4545
4784
  }
4546
- if (t === ERROR) {
4547
- actions.down([msg]);
4785
+ if (t === RESOLVED) {
4786
+ if (buffer2.length === 0) {
4787
+ actions.down([[RESOLVED]]);
4788
+ } else {
4789
+ pendingResolved = true;
4790
+ }
4548
4791
  return true;
4549
4792
  }
4550
- if (t === COMPLETE) {
4793
+ if (t === COMPLETE || t === ERROR) {
4794
+ for (const item of buffer2) {
4795
+ actions.emit(item);
4796
+ }
4797
+ buffer2 = [];
4798
+ pendingResolved = false;
4799
+ if (paused) {
4800
+ paused = false;
4801
+ actions.up([[RESUME, lockId]]);
4802
+ }
4803
+ actions.down([msg]);
4551
4804
  return true;
4552
4805
  }
4553
4806
  return false;
4554
4807
  }
4555
- });
4808
+ if (t === DATA) {
4809
+ latestValues[depIndex - 1] = msg[1];
4810
+ }
4811
+ if (t === DATA || t === RESOLVED) {
4812
+ if (checkBudget() && buffer2.length > 0) {
4813
+ flushBuffer(actions);
4814
+ if (buffer2.length === 0 && paused) {
4815
+ paused = false;
4816
+ actions.up([[RESUME, lockId]]);
4817
+ }
4818
+ } else if (!checkBudget() && !paused && buffer2.length > 0) {
4819
+ paused = true;
4820
+ actions.up([[PAUSE, lockId]]);
4821
+ }
4822
+ return true;
4823
+ }
4824
+ if (t === DIRTY) {
4825
+ return true;
4826
+ }
4827
+ if (t === ERROR) {
4828
+ actions.down([msg]);
4829
+ return true;
4830
+ }
4831
+ if (t === COMPLETE) {
4832
+ return true;
4833
+ }
4834
+ return false;
4835
+ }
4556
4836
  }
4557
4837
  function scorer(sources, weights, opts) {
4558
4838
  if (sources.length === 0) throw new RangeError("scorer requires at least one source");
@@ -4584,7 +4864,11 @@ function scorer(sources, weights, opts) {
4584
4864
  };
4585
4865
  },
4586
4866
  {
4587
- ...opts,
4867
+ ...opts ? {
4868
+ equals: opts.equals,
4869
+ resubscribable: opts.resubscribable,
4870
+ resetOnTeardown: opts.resetOnTeardown
4871
+ } : {},
4588
4872
  describeKind: "derived",
4589
4873
  meta: baseMeta2("scorer", opts?.meta)
4590
4874
  }
@@ -4672,12 +4956,6 @@ function observabilityGraph(name, opts) {
4672
4956
  }
4673
4957
  );
4674
4958
  g.add("correlate", correlateNode);
4675
- for (const b of branches) {
4676
- try {
4677
- g.connect(`stratify::branch/${b.name}`, "correlate");
4678
- } catch {
4679
- }
4680
- }
4681
4959
  const sloCheckFn = opts.sloCheck ?? (() => ({ pass: true }));
4682
4960
  const sloValue = derived([correlateNode], (vals) => vals[0], {
4683
4961
  meta: baseMeta3("observability", { stage: "slo_value" })
@@ -4687,8 +4965,6 @@ function observabilityGraph(name, opts) {
4687
4965
  });
4688
4966
  g.add("slo_value", sloValue);
4689
4967
  g.add("slo_verified", sloVerified);
4690
- g.connect("correlate", "slo_value");
4691
- g.connect("slo_value", "slo_verified");
4692
4968
  const weightValues = opts.weights ?? branches.map(() => 1);
4693
4969
  const signalNodes = branchNodes.map(
4694
4970
  (bn) => derived([bn], (vals) => vals[0] != null ? 1 : 0)
@@ -4714,8 +4990,6 @@ function observabilityGraph(name, opts) {
4714
4990
  }
4715
4991
  );
4716
4992
  g.add("output", output);
4717
- g.connect("alerts", "output");
4718
- g.connect("slo_verified", "output");
4719
4993
  const fbReentry = state(null, {
4720
4994
  meta: baseMeta3("observability", { stage: "feedback_reentry" })
4721
4995
  });
@@ -4732,7 +5006,6 @@ function observabilityGraph(name, opts) {
4732
5006
  }
4733
5007
  );
4734
5008
  g.add("feedback_condition", fbCondition);
4735
- g.connect("slo_verified", "feedback_condition");
4736
5009
  feedback(g, "feedback_condition", "feedback_reentry", {
4737
5010
  maxIterations: opts.maxFeedbackIterations ?? 5
4738
5011
  });
@@ -4754,7 +5027,6 @@ function issueTrackerGraph(name, opts) {
4754
5027
  meta: baseMeta3("issue_tracker", { stage: "extract" })
4755
5028
  });
4756
5029
  g.add("extract", extractNode);
4757
- g.connect("source", "extract");
4758
5030
  const verifyFn = opts.verify ?? (() => ({ valid: true }));
4759
5031
  const verifyNode = derived(
4760
5032
  [extractNode],
@@ -4767,7 +5039,6 @@ function issueTrackerGraph(name, opts) {
4767
5039
  }
4768
5040
  );
4769
5041
  g.add("verify", verifyNode);
4770
- g.connect("extract", "verify");
4771
5042
  const knownPatterns = state([], {
4772
5043
  meta: baseMeta3("issue_tracker", { stage: "known_patterns" })
4773
5044
  });
@@ -4783,8 +5054,6 @@ function issueTrackerGraph(name, opts) {
4783
5054
  { meta: baseMeta3("issue_tracker", { stage: "regression" }) }
4784
5055
  );
4785
5056
  g.add("regression", regressionNode);
4786
- g.connect("extract", "regression");
4787
- g.connect("known_patterns", "regression");
4788
5057
  const severitySignal = derived([extractNode], (vals) => {
4789
5058
  const issue = vals[0];
4790
5059
  return issue?.severity ?? 0;
@@ -4811,9 +5080,6 @@ function issueTrackerGraph(name, opts) {
4811
5080
  { meta: baseMeta3("issue_tracker", { stage: "output" }) }
4812
5081
  );
4813
5082
  g.add("output", output);
4814
- g.connect("verify", "output");
4815
- g.connect("regression", "output");
4816
- g.connect("priority", "output");
4817
5083
  const fbReentry = state(null, {
4818
5084
  meta: baseMeta3("issue_tracker", { stage: "feedback_reentry" })
4819
5085
  });
@@ -4833,7 +5099,6 @@ function issueTrackerGraph(name, opts) {
4833
5099
  }
4834
5100
  );
4835
5101
  g.add("feedback_condition", fbCondition);
4836
- g.connect("verify", "feedback_condition");
4837
5102
  feedback(g, "feedback_condition", "feedback_reentry", {
4838
5103
  maxIterations: opts.maxFeedbackIterations ?? 3
4839
5104
  });
@@ -4852,7 +5117,6 @@ function contentModerationGraph(name, opts) {
4852
5117
  meta: baseMeta3("content_moderation", { stage: "classify" })
4853
5118
  });
4854
5119
  g.add("classify", classifyNode);
4855
- g.connect("source", "classify");
4856
5120
  const strat = stratify("stratify", classifyNode, [
4857
5121
  { name: "safe", classify: (v) => v.label === "safe" },
4858
5122
  { name: "review", classify: (v) => v.label === "review" },
@@ -4880,7 +5144,6 @@ function contentModerationGraph(name, opts) {
4880
5144
  g.add("__review_accumulator", reviewAccumulator);
4881
5145
  g.addDisposer(keepalive(reviewAccumulator));
4882
5146
  try {
4883
- g.connect("stratify::branch/review", "__review_accumulator");
4884
5147
  } catch {
4885
5148
  }
4886
5149
  const policy2 = state(
@@ -4921,8 +5184,6 @@ function contentModerationGraph(name, opts) {
4921
5184
  { meta: baseMeta3("content_moderation", { stage: "output" }) }
4922
5185
  );
4923
5186
  g.add("output", output);
4924
- g.connect("classify", "output");
4925
- g.connect("priority", "output");
4926
5187
  const fbCondition = derived(
4927
5188
  [reviewLog.entries, policy2],
4928
5189
  (vals) => {
@@ -4959,7 +5220,6 @@ function dataQualityGraph(name, opts) {
4959
5220
  { meta: baseMeta3("data_quality", { stage: "validate" }) }
4960
5221
  );
4961
5222
  g.add("validate", validateNode);
4962
- g.connect("source", "validate");
4963
5223
  const detectAnomalyFn = opts.detectAnomaly ?? ((record) => ({
4964
5224
  anomaly: false,
4965
5225
  score: 0,
@@ -4971,7 +5231,6 @@ function dataQualityGraph(name, opts) {
4971
5231
  { meta: baseMeta3("data_quality", { stage: "anomaly" }) }
4972
5232
  );
4973
5233
  g.add("anomaly", anomalyNode);
4974
- g.connect("source", "anomaly");
4975
5234
  const baseline = state(null, {
4976
5235
  meta: baseMeta3("data_quality", {
4977
5236
  stage: "baseline",
@@ -4988,7 +5247,6 @@ function dataQualityGraph(name, opts) {
4988
5247
  }
4989
5248
  });
4990
5249
  g.add("__baseline_updater", baselineUpdater);
4991
- g.connect("validate", "__baseline_updater");
4992
5250
  keepalive(baselineUpdater);
4993
5251
  const detectDriftFn = opts.detectDrift ?? (() => ({ drift: false }));
4994
5252
  const driftNode = derived(
@@ -4997,8 +5255,6 @@ function dataQualityGraph(name, opts) {
4997
5255
  { meta: baseMeta3("data_quality", { stage: "drift" }) }
4998
5256
  );
4999
5257
  g.add("drift", driftNode);
5000
- g.connect("source", "drift");
5001
- g.connect("baseline", "drift");
5002
5258
  const suggestFn = opts.suggest ?? (() => null);
5003
5259
  const remediateNode = derived(
5004
5260
  [validateNode, anomalyNode],
@@ -5009,8 +5265,6 @@ function dataQualityGraph(name, opts) {
5009
5265
  { meta: baseMeta3("data_quality", { stage: "remediate" }) }
5010
5266
  );
5011
5267
  g.add("remediate", remediateNode);
5012
- g.connect("validate", "remediate");
5013
- g.connect("anomaly", "remediate");
5014
5268
  const output = derived(
5015
5269
  [validateNode, anomalyNode, driftNode, remediateNode],
5016
5270
  (vals) => ({
@@ -5022,10 +5276,6 @@ function dataQualityGraph(name, opts) {
5022
5276
  { meta: baseMeta3("data_quality", { stage: "output" }) }
5023
5277
  );
5024
5278
  g.add("output", output);
5025
- g.connect("validate", "output");
5026
- g.connect("anomaly", "output");
5027
- g.connect("drift", "output");
5028
- g.connect("remediate", "output");
5029
5279
  const validationRules = state([], {
5030
5280
  meta: baseMeta3("data_quality", { stage: "validation_rules" })
5031
5281
  });
@@ -5042,7 +5292,6 @@ function dataQualityGraph(name, opts) {
5042
5292
  }
5043
5293
  );
5044
5294
  g.add("feedback_condition", fbCondition);
5045
- g.connect("anomaly", "feedback_condition");
5046
5295
  feedback(g, "feedback_condition", "validation_rules", {
5047
5296
  maxIterations: opts.maxFeedbackIterations ?? 3
5048
5297
  });
@@ -5568,20 +5817,6 @@ ${catalogValidation.errors.join("\n")}`
5568
5817
  } catch {
5569
5818
  }
5570
5819
  }
5571
- for (const [name, raw] of Object.entries(spec.nodes)) {
5572
- if (raw.type === "template") continue;
5573
- const n = raw;
5574
- for (const dep of n.deps ?? []) {
5575
- try {
5576
- g.connect(dep, name);
5577
- } catch (err) {
5578
- const msg = err instanceof Error ? err.message : "";
5579
- if (!msg.includes("constructor deps") && !msg.includes("already")) {
5580
- throw err;
5581
- }
5582
- }
5583
- }
5584
- }
5585
5820
  for (const fb of spec.feedback ?? []) {
5586
5821
  feedback(g, fb.from, fb.to, {
5587
5822
  maxIterations: fb.maxIterations
@@ -6472,6 +6707,7 @@ function harnessLoop(name, opts) {
6472
6707
  }
6473
6708
  const routerInput = withLatestFrom(triageNode, triageInput);
6474
6709
  const router = effect([routerInput], ([pair]) => {
6710
+ if (pair == null) return;
6475
6711
  const [classification, triagePair] = pair;
6476
6712
  if (!classification || !classification.route) return;
6477
6713
  const intakeItem = triagePair?.[0];
@@ -6517,32 +6753,43 @@ function harnessLoop(name, opts) {
6517
6753
  retries: 1
6518
6754
  }
6519
6755
  );
6756
+ const executeContextNode = withLatestFrom(
6757
+ executeNode,
6758
+ executeInput
6759
+ );
6520
6760
  const verifyResults = new TopicGraph("verify-results", { retainedLimit });
6521
6761
  const verifyNode = promptNode(
6522
6762
  adapter,
6523
- [executeNode, executeInput],
6524
- opts.verifyPrompt ?? ((execution, item) => DEFAULT_VERIFY_PROMPT.replace("{{execution}}", JSON.stringify(execution)).replace(
6525
- "{{item}}",
6526
- JSON.stringify(item)
6527
- )),
6763
+ [executeContextNode],
6764
+ opts.verifyPrompt ?? ((ctxPair) => {
6765
+ const [execution, item] = ctxPair;
6766
+ return DEFAULT_VERIFY_PROMPT.replace("{{execution}}", JSON.stringify(execution)).replace(
6767
+ "{{item}}",
6768
+ JSON.stringify(item)
6769
+ );
6770
+ }),
6528
6771
  {
6529
6772
  name: "verify",
6530
6773
  format: "json",
6531
6774
  retries: 1
6532
6775
  }
6533
6776
  );
6534
- const verifyWithExec = withLatestFrom(verifyNode, executeNode);
6535
6777
  const verifyContext = withLatestFrom(
6536
- verifyWithExec,
6537
- executeInput
6778
+ verifyNode,
6779
+ executeContextNode
6538
6780
  );
6539
6781
  const maxReingestions = opts.maxReingestions ?? 1;
6540
6782
  const maxTotalRetries = Math.min(opts.maxTotalRetries ?? maxRetries * 10, 100);
6541
6783
  const maxTotalReingestions = Math.min(opts.maxTotalReingestions ?? maxReingestions * 10, 100);
6542
6784
  const totalRetries = state(0);
6543
6785
  const totalReingestions = state(0);
6544
- const fastRetry = effect([verifyContext], ([ctx]) => {
6545
- const [[vo, execRaw], item] = ctx;
6786
+ const fastRetry = node([verifyContext], (batchData, _actions) => {
6787
+ const batch2 = batchData[0];
6788
+ if (batch2 == null || batch2.length === 0) return;
6789
+ const ctxVal = batch2[batch2.length - 1];
6790
+ if (ctxVal == null) return;
6791
+ const [vo, execCtx] = ctxVal;
6792
+ const [execRaw, item] = execCtx ?? [null, null];
6546
6793
  if (!vo || !item) return;
6547
6794
  const exec = {
6548
6795
  item,
@@ -6567,8 +6814,7 @@ function harnessLoop(name, opts) {
6567
6814
  detail: vr.findings.join("; ")
6568
6815
  });
6569
6816
  const itemRetries = item._retries ?? 0;
6570
- if (errClass === "self-correctable" && itemRetries < maxRetries && (totalRetries.get() ?? 0) < maxTotalRetries) {
6571
- totalRetries.down([[DIRTY], [DATA, (totalRetries.get() ?? 0) + 1]]);
6817
+ if (errClass === "self-correctable" && itemRetries < maxRetries && tryIncrementBounded(totalRetries, maxTotalRetries)) {
6572
6818
  const key = trackingKey(item);
6573
6819
  const retryItem = {
6574
6820
  ...item,
@@ -6582,8 +6828,7 @@ function harnessLoop(name, opts) {
6582
6828
  verifyResults.publish(vr);
6583
6829
  const key = trackingKey(item);
6584
6830
  const itemReingestions = item._reingestions ?? 0;
6585
- if (itemReingestions < maxReingestions && (totalReingestions.get() ?? 0) < maxTotalReingestions) {
6586
- totalReingestions.down([[DIRTY], [DATA, (totalReingestions.get() ?? 0) + 1]]);
6831
+ if (itemReingestions < maxReingestions && tryIncrementBounded(totalReingestions, maxTotalReingestions)) {
6587
6832
  intake.publish({
6588
6833
  source: "eval",
6589
6834
  summary: `Verification failed for: ${key}`,
@@ -6636,9 +6881,9 @@ function harnessProfile(harness, opts) {
6636
6881
  return {
6637
6882
  ...base,
6638
6883
  queueDepths,
6639
- strategyEntries: harness.strategy.node.get()?.size ?? 0,
6640
- totalRetries: harness.totalRetries.get() ?? 0,
6641
- totalReingestions: harness.totalReingestions.get() ?? 0
6884
+ strategyEntries: harness.strategy.node.cache?.size ?? 0,
6885
+ totalRetries: harness.totalRetries.cache ?? 0,
6886
+ totalReingestions: harness.totalReingestions.cache ?? 0
6642
6887
  };
6643
6888
  }
6644
6889
 
@@ -6745,56 +6990,69 @@ function truncate(s, max) {
6745
6990
  // src/index.ts
6746
6991
  var version = "0.0.0";
6747
6992
  export {
6748
- CLEANUP_RESULT,
6749
6993
  COMPLETE,
6994
+ COMPLETE_MSG,
6995
+ COMPLETE_ONLY_BATCH,
6750
6996
  CircuitOpenError,
6751
6997
  DATA,
6752
6998
  DEFAULT_ACTOR,
6753
- DEFAULT_DOWN,
6754
6999
  DIRTY,
6755
- DictCheckpointAdapter,
6756
- DynamicNodeImpl,
7000
+ DIRTY_MSG,
7001
+ DIRTY_ONLY_BATCH,
7002
+ ENVELOPE_VERSION,
6757
7003
  ERROR,
6758
- FileCheckpointAdapter,
6759
7004
  GRAPH_META_SEGMENT,
6760
7005
  Graph,
7006
+ GraphReFlyConfig,
6761
7007
  GuardDenied,
6762
7008
  INVALIDATE,
7009
+ INVALIDATE_MSG,
7010
+ INVALIDATE_ONLY_BATCH,
6763
7011
  JsonCodec,
6764
- MemoryCheckpointAdapter,
6765
7012
  NS_PER_MS,
6766
7013
  NS_PER_SEC,
7014
+ NativeIndexBackend,
7015
+ NativeListBackend,
7016
+ NativeLogBackend,
7017
+ NativeMapBackend,
7018
+ NativePubSubBackend,
7019
+ NodeImpl,
6767
7020
  PAUSE,
6768
7021
  RESOLVED,
7022
+ RESOLVED_MSG,
7023
+ RESOLVED_ONLY_BATCH,
6769
7024
  RESUME,
7025
+ RateLimiterOverflowError,
6770
7026
  ResettableTimer,
7027
+ OVERHEAD as SIZEOF_OVERHEAD,
7028
+ SIZEOF_SYMBOL,
6771
7029
  START,
6772
- SqliteCheckpointAdapter,
7030
+ START_MSG,
6773
7031
  TEARDOWN,
7032
+ TEARDOWN_MSG,
7033
+ TEARDOWN_ONLY_BATCH,
6774
7034
  TimeoutError,
6775
7035
  accessHintForGuard,
6776
7036
  advanceVersion,
6777
7037
  ai_exports as ai,
6778
7038
  audit,
7039
+ autoTrackNode,
6779
7040
  batch,
6780
- bridge,
6781
7041
  buffer,
6782
7042
  bufferCount,
6783
7043
  bufferTime,
6784
- cache,
6785
7044
  cached,
6786
7045
  cascadingCache,
6787
7046
  catchError,
6788
- checkpointNodeValue,
6789
7047
  checkpointToRedis,
6790
7048
  checkpointToS3,
6791
7049
  circuitBreaker,
6792
- cleanupResult,
6793
7050
  combine,
6794
7051
  combineLatest,
6795
7052
  compat_exports as compat,
6796
7053
  concat,
6797
7054
  concatMap,
7055
+ configure,
6798
7056
  constant,
6799
7057
  core_exports as core,
6800
7058
  cqrs_exports as cqrs,
@@ -6803,14 +7061,19 @@ export {
6803
7061
  createTransport,
6804
7062
  createVersioning,
6805
7063
  createWatermarkController,
7064
+ csvRows,
6806
7065
  debounce,
6807
7066
  debounceTime,
7067
+ decodeEnvelope,
6808
7068
  decorrelatedJitter,
7069
+ defaultConfig,
6809
7070
  defaultHash,
6810
7071
  delay,
6811
7072
  demo_shell_exports as demoShell,
6812
7073
  derived,
6813
7074
  deserializeError,
7075
+ dictStorage,
7076
+ diffForWAL,
6814
7077
  distill,
6815
7078
  distinctUntilChanged,
6816
7079
  domain_templates_exports as domainTemplates,
@@ -6819,12 +7082,16 @@ export {
6819
7082
  effect,
6820
7083
  elementAt,
6821
7084
  empty,
7085
+ encodeEnvelope,
6822
7086
  escapeRegexChar,
6823
7087
  exhaustMap,
6824
7088
  exponential,
7089
+ externalBundle,
7090
+ externalProducer,
6825
7091
  extra_exports as extra,
6826
7092
  fallback,
6827
7093
  fibonacci,
7094
+ fileStorage,
6828
7095
  filter,
6829
7096
  find,
6830
7097
  first,
@@ -6842,6 +7109,8 @@ export {
6842
7109
  fromFSWatch,
6843
7110
  fromGitHook,
6844
7111
  fromHTTP,
7112
+ fromHTTPPoll,
7113
+ fromHTTPStream,
6845
7114
  fromIDBRequest,
6846
7115
  fromIDBTransaction,
6847
7116
  fromIter,
@@ -6857,44 +7126,42 @@ export {
6857
7126
  fromPulsar,
6858
7127
  fromRabbitMQ,
6859
7128
  fromRedisStream,
7129
+ fromSSE,
6860
7130
  fromSqlite,
7131
+ fromSqliteCursor,
6861
7132
  fromStatsD,
6862
7133
  fromSyslog,
6863
7134
  fromTimer,
6864
7135
  fromWebSocket,
7136
+ fromWebSocketReconnect,
6865
7137
  fromWebhook,
6866
7138
  globToRegExp,
6867
7139
  graph_exports as graph,
6868
7140
  graphProfile,
6869
7141
  graphspec_exports as graphspec,
6870
7142
  harness_exports as harness,
7143
+ indexedDbStorage,
6871
7144
  interval,
6872
7145
  isBatching,
6873
- isKnownMessageType,
6874
- isLocalOnly,
6875
- isPhase2Message,
6876
- isTerminalMessage,
6877
7146
  isV1,
6878
7147
  jotai_exports as jotai,
6879
7148
  keepalive,
6880
- knownMessageTypes,
6881
7149
  last,
6882
7150
  reactive_layout_exports as layout,
6883
7151
  linear,
6884
- logSlice,
6885
7152
  lru,
6886
7153
  map,
6887
7154
  matchesAnyPattern,
6888
7155
  matchesCron,
6889
7156
  memory_exports as memory,
7157
+ memoryStorage,
6890
7158
  merge,
6891
7159
  mergeMap,
6892
- messageTier,
6893
7160
  messaging_exports as messaging,
6894
7161
  monotonicNs,
6895
7162
  nameToSignal,
6896
7163
  nanostores_exports as nanostores,
6897
- negotiateCodec,
7164
+ ndjsonRows,
6898
7165
  nestjs_exports as nestjs,
6899
7166
  never,
6900
7167
  node,
@@ -6906,14 +7173,12 @@ export {
6906
7173
  parsePrometheusText,
6907
7174
  parseStatsD,
6908
7175
  parseSyslog,
6909
- partitionForBatch,
6910
7176
  patterns_exports as patterns,
6911
7177
  pausable,
6912
7178
  pipe,
6913
7179
  policy,
6914
7180
  policyFromRules,
6915
7181
  producer,
6916
- propagatesToMeta,
6917
7182
  pubsub,
6918
7183
  race,
6919
7184
  rateLimiter,
@@ -6924,20 +7189,20 @@ export {
6924
7189
  reactiveList,
6925
7190
  reactiveLog,
6926
7191
  reactiveMap,
7192
+ reactiveSink,
6927
7193
  reduce,
6928
7194
  reduction_exports as reduction,
7195
+ registerBuiltinCodecs,
7196
+ registerBuiltins,
6929
7197
  repeat,
6930
7198
  replay,
6931
7199
  replayWAL,
6932
7200
  rescue,
6933
7201
  resolveBackoffPreset,
6934
7202
  resolveDescribeFields,
6935
- restoreGraphCheckpoint,
6936
- restoreGraphCheckpointIndexedDb,
6937
7203
  retry,
7204
+ retrySource,
6938
7205
  sample,
6939
- saveGraphCheckpoint,
6940
- saveGraphCheckpointIndexedDb,
6941
7206
  scan,
6942
7207
  serializeError,
6943
7208
  share,
@@ -6947,6 +7212,7 @@ export {
6947
7212
  sizeof,
6948
7213
  skip,
6949
7214
  solid_exports as solid,
7215
+ sqliteStorage,
6950
7216
  state,
6951
7217
  svelte_exports as svelte,
6952
7218
  switchMap,
@@ -6957,12 +7223,12 @@ export {
6957
7223
  throttle,
6958
7224
  throttleTime,
6959
7225
  throwError,
6960
- tieredStorage,
6961
7226
  timeout,
6962
7227
  toArray,
6963
7228
  toCSV,
6964
7229
  toClickHouse,
6965
7230
  toFile,
7231
+ toHTTP,
6966
7232
  toKafka,
6967
7233
  toLoki,
6968
7234
  toMongo,
@@ -6971,14 +7237,15 @@ export {
6971
7237
  toPostgres,
6972
7238
  toPulsar,
6973
7239
  toRabbitMQ,
7240
+ toReadableStream,
6974
7241
  toRedisStream,
6975
7242
  toS3,
6976
7243
  toSSE,
7244
+ toSSEBytes,
6977
7245
  toSqlite,
6978
7246
  toTempo,
6979
7247
  toWebSocket,
6980
7248
  tokenBucket,
6981
- tokenTracker,
6982
7249
  valve,
6983
7250
  verifiable,
6984
7251
  version,