@graphrefly/graphrefly 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +234 -0
  3. package/dist/chunk-5X3LAO3B.js +1571 -0
  4. package/dist/chunk-5X3LAO3B.js.map +1 -0
  5. package/dist/chunk-6W5SGIGB.js +1793 -0
  6. package/dist/chunk-6W5SGIGB.js.map +1 -0
  7. package/dist/chunk-CP6MNKAA.js +97 -0
  8. package/dist/chunk-CP6MNKAA.js.map +1 -0
  9. package/dist/chunk-HP7OKEOE.js +107 -0
  10. package/dist/chunk-HP7OKEOE.js.map +1 -0
  11. package/dist/chunk-KWXPDASV.js +781 -0
  12. package/dist/chunk-KWXPDASV.js.map +1 -0
  13. package/dist/chunk-O3PI7W45.js +68 -0
  14. package/dist/chunk-O3PI7W45.js.map +1 -0
  15. package/dist/chunk-QW7H3ICI.js +1372 -0
  16. package/dist/chunk-QW7H3ICI.js.map +1 -0
  17. package/dist/chunk-VPS7L64N.js +4785 -0
  18. package/dist/chunk-VPS7L64N.js.map +1 -0
  19. package/dist/chunk-Z4Y4FMQN.js +1097 -0
  20. package/dist/chunk-Z4Y4FMQN.js.map +1 -0
  21. package/dist/compat/nestjs/index.cjs +4883 -0
  22. package/dist/compat/nestjs/index.cjs.map +1 -0
  23. package/dist/compat/nestjs/index.d.cts +7 -0
  24. package/dist/compat/nestjs/index.d.ts +7 -0
  25. package/dist/compat/nestjs/index.js +84 -0
  26. package/dist/compat/nestjs/index.js.map +1 -0
  27. package/dist/core/index.cjs +1632 -0
  28. package/dist/core/index.cjs.map +1 -0
  29. package/dist/core/index.d.cts +2 -0
  30. package/dist/core/index.d.ts +2 -0
  31. package/dist/core/index.js +90 -0
  32. package/dist/core/index.js.map +1 -0
  33. package/dist/extra/index.cjs +6885 -0
  34. package/dist/extra/index.cjs.map +1 -0
  35. package/dist/extra/index.d.cts +5 -0
  36. package/dist/extra/index.d.ts +5 -0
  37. package/dist/extra/index.js +290 -0
  38. package/dist/extra/index.js.map +1 -0
  39. package/dist/graph/index.cjs +3225 -0
  40. package/dist/graph/index.cjs.map +1 -0
  41. package/dist/graph/index.d.cts +3 -0
  42. package/dist/graph/index.d.ts +3 -0
  43. package/dist/graph/index.js +25 -0
  44. package/dist/graph/index.js.map +1 -0
  45. package/dist/graph-CL_ZDAj9.d.cts +605 -0
  46. package/dist/graph-D18qmsNm.d.ts +605 -0
  47. package/dist/index-B6SsZs2h.d.cts +3463 -0
  48. package/dist/index-B7eOdgEx.d.ts +449 -0
  49. package/dist/index-BHUvlQ3v.d.ts +3463 -0
  50. package/dist/index-BtK55IE2.d.ts +231 -0
  51. package/dist/index-BvhgZRHK.d.cts +231 -0
  52. package/dist/index-Bvy_6CaN.d.ts +452 -0
  53. package/dist/index-C3BMRmmp.d.cts +449 -0
  54. package/dist/index-C5mqLhMX.d.cts +452 -0
  55. package/dist/index-CP_QvbWu.d.ts +940 -0
  56. package/dist/index-D_geH2Bm.d.cts +940 -0
  57. package/dist/index.cjs +14843 -0
  58. package/dist/index.cjs.map +1 -0
  59. package/dist/index.d.cts +1517 -0
  60. package/dist/index.d.ts +1517 -0
  61. package/dist/index.js +3649 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/meta-BsF6Sag9.d.cts +607 -0
  64. package/dist/meta-BsF6Sag9.d.ts +607 -0
  65. package/dist/patterns/reactive-layout/index.cjs +4143 -0
  66. package/dist/patterns/reactive-layout/index.cjs.map +1 -0
  67. package/dist/patterns/reactive-layout/index.d.cts +3 -0
  68. package/dist/patterns/reactive-layout/index.d.ts +3 -0
  69. package/dist/patterns/reactive-layout/index.js +38 -0
  70. package/dist/patterns/reactive-layout/index.js.map +1 -0
  71. package/dist/reactive-log-BfvfNWQh.d.cts +137 -0
  72. package/dist/reactive-log-ohLmTXoZ.d.ts +137 -0
  73. package/package.json +256 -0
package/dist/index.js ADDED
@@ -0,0 +1,3649 @@
1
+ import {
2
+ CircuitOpenError,
3
+ DictCheckpointAdapter,
4
+ FileCheckpointAdapter,
5
+ MemoryCheckpointAdapter,
6
+ NS_PER_MS,
7
+ NS_PER_SEC,
8
+ SqliteCheckpointAdapter,
9
+ audit,
10
+ buffer,
11
+ bufferCount,
12
+ bufferTime,
13
+ catchError,
14
+ checkpointNodeValue,
15
+ circuitBreaker,
16
+ combine,
17
+ combineLatest,
18
+ concat,
19
+ concatMap,
20
+ constant,
21
+ createTransport,
22
+ debounce,
23
+ debounceTime,
24
+ decorrelatedJitter,
25
+ delay,
26
+ deserializeError,
27
+ distill,
28
+ distinctUntilChanged,
29
+ elementAt,
30
+ exhaustMap,
31
+ exponential,
32
+ extra_exports,
33
+ fibonacci,
34
+ filter,
35
+ find,
36
+ first,
37
+ flatMap,
38
+ fromCSV,
39
+ fromClickHouseWatch,
40
+ fromGitHook,
41
+ fromHTTP,
42
+ fromIDBRequest,
43
+ fromIDBTransaction,
44
+ fromKafka,
45
+ fromMCP,
46
+ fromNDJSON,
47
+ fromOTel,
48
+ fromPrometheus,
49
+ fromRedisStream,
50
+ fromStatsD,
51
+ fromSyslog,
52
+ fromWebSocket,
53
+ fromWebhook,
54
+ gate,
55
+ interval,
56
+ last,
57
+ linear,
58
+ map,
59
+ merge,
60
+ mergeMap,
61
+ nameToSignal,
62
+ pairwise,
63
+ parsePrometheusText,
64
+ parseStatsD,
65
+ parseSyslog,
66
+ pausable,
67
+ pubsub,
68
+ race,
69
+ rateLimiter,
70
+ reactiveIndex,
71
+ reactiveList,
72
+ reactiveMap,
73
+ reduce,
74
+ repeat,
75
+ rescue,
76
+ resolveBackoffPreset,
77
+ restoreGraphCheckpoint,
78
+ restoreGraphCheckpointIndexedDb,
79
+ retry,
80
+ sample,
81
+ saveGraphCheckpoint,
82
+ saveGraphCheckpointIndexedDb,
83
+ scan,
84
+ serializeError,
85
+ signalToName,
86
+ skip,
87
+ startWith,
88
+ switchMap,
89
+ take,
90
+ takeUntil,
91
+ takeWhile,
92
+ tap,
93
+ throttle,
94
+ throttleTime,
95
+ timeout,
96
+ toKafka,
97
+ toRedisStream,
98
+ toSSE,
99
+ toWebSocket,
100
+ tokenBucket,
101
+ tokenTracker,
102
+ verifiable,
103
+ window,
104
+ windowCount,
105
+ windowTime,
106
+ withBreaker,
107
+ withLatestFrom,
108
+ withMaxAttempts,
109
+ withStatus,
110
+ workerBridge,
111
+ workerSelf,
112
+ zip
113
+ } from "./chunk-VPS7L64N.js";
114
+ import {
115
+ cqrs_exports,
116
+ nestjs_exports
117
+ } from "./chunk-QW7H3ICI.js";
118
+ import {
119
+ JsonCodec,
120
+ createDagCborCodec,
121
+ createDagCborZstdCodec,
122
+ graph_exports,
123
+ negotiateCodec,
124
+ replayWAL
125
+ } from "./chunk-HP7OKEOE.js";
126
+ import {
127
+ core_exports
128
+ } from "./chunk-CP6MNKAA.js";
129
+ import {
130
+ cached,
131
+ createWatermarkController,
132
+ empty,
133
+ escapeRegexChar,
134
+ firstValueFrom,
135
+ forEach,
136
+ fromAny,
137
+ fromAsyncIter,
138
+ fromCron,
139
+ fromEvent,
140
+ fromFSWatch,
141
+ fromIter,
142
+ fromPromise,
143
+ fromTimer,
144
+ globToRegExp,
145
+ logSlice,
146
+ matchesAnyPattern,
147
+ matchesCron,
148
+ never,
149
+ observeGraph$,
150
+ observeNode$,
151
+ of,
152
+ parseCron,
153
+ reactiveLog,
154
+ replay,
155
+ share,
156
+ shareReplay,
157
+ throwError,
158
+ toArray,
159
+ toMessages$,
160
+ toObservable
161
+ } from "./chunk-KWXPDASV.js";
162
+ import {
163
+ reactive_layout_exports
164
+ } from "./chunk-Z4Y4FMQN.js";
165
+ import {
166
+ GRAPH_META_SEGMENT,
167
+ Graph,
168
+ reachable
169
+ } from "./chunk-6W5SGIGB.js";
170
+ import {
171
+ describeNode,
172
+ metaSnapshot
173
+ } from "./chunk-O3PI7W45.js";
174
+ import {
175
+ COMPLETE,
176
+ DATA,
177
+ DEFAULT_ACTOR,
178
+ DIRTY,
179
+ DynamicNodeImpl,
180
+ ERROR,
181
+ GuardDenied,
182
+ INVALIDATE,
183
+ PAUSE,
184
+ RESOLVED,
185
+ RESUME,
186
+ TEARDOWN,
187
+ __export,
188
+ accessHintForGuard,
189
+ advanceVersion,
190
+ batch,
191
+ createVersioning,
192
+ defaultHash,
193
+ derived,
194
+ dynamicNode,
195
+ effect,
196
+ emitWithBatch,
197
+ isBatching,
198
+ isKnownMessageType,
199
+ isPhase2Message,
200
+ isTerminalMessage,
201
+ isV1,
202
+ knownMessageTypes,
203
+ messageTier,
204
+ monotonicNs,
205
+ node,
206
+ normalizeActor,
207
+ partitionForBatch,
208
+ pipe,
209
+ policy,
210
+ policyFromRules,
211
+ producer,
212
+ propagatesToMeta,
213
+ state,
214
+ wallClockNs
215
+ } from "./chunk-5X3LAO3B.js";
216
+
217
+ // src/compat/index.ts
218
+ var compat_exports = {};
219
+ __export(compat_exports, {
220
+ jotai: () => jotai_exports,
221
+ nanostores: () => nanostores_exports,
222
+ nestjs: () => nestjs_exports,
223
+ react: () => react_exports,
224
+ signals: () => signals_exports,
225
+ solid: () => solid_exports,
226
+ svelte: () => svelte_exports,
227
+ vue: () => vue_exports,
228
+ zustand: () => zustand_exports
229
+ });
230
+
231
+ // src/compat/jotai/index.ts
232
+ var jotai_exports = {};
233
+ __export(jotai_exports, {
234
+ atom: () => atom
235
+ });
236
+ function atom(initialOrRead, writeOrOptions, options) {
237
+ if (typeof initialOrRead === "function") {
238
+ const read = initialOrRead;
239
+ if (typeof writeOrOptions === "function") {
240
+ return createDerivedAtom(read, writeOrOptions, options);
241
+ }
242
+ return createDerivedAtom(read, void 0, writeOrOptions);
243
+ }
244
+ return createPrimitiveAtom(initialOrRead, writeOrOptions);
245
+ }
246
+ function pull(n) {
247
+ let val = n.get();
248
+ let err;
249
+ const unsub = n.subscribe((msgs) => {
250
+ for (const [t, v] of msgs) {
251
+ if (t === DATA) val = v;
252
+ if (t === ERROR) err = v;
253
+ }
254
+ });
255
+ unsub();
256
+ if (err) throw err;
257
+ return val;
258
+ }
259
+ function createPrimitiveAtom(initial, options) {
260
+ const n = state(initial, {
261
+ ...options,
262
+ resubscribable: true,
263
+ resetOnTeardown: true
264
+ });
265
+ return {
266
+ get: () => {
267
+ if (n.status === "disconnected") {
268
+ return pull(n);
269
+ }
270
+ return n.get();
271
+ },
272
+ set: (value) => n.down([[DATA, value]]),
273
+ update: (fn) => {
274
+ const current = n.status === "disconnected" ? pull(n) : n.get();
275
+ n.down([[DATA, fn(current)]]);
276
+ },
277
+ subscribe: (cb) => {
278
+ return n.subscribe((msgs) => {
279
+ for (const [t, v] of msgs) {
280
+ if (t === DATA) cb(v);
281
+ }
282
+ });
283
+ },
284
+ meta: n.meta,
285
+ _node: n
286
+ };
287
+ }
288
+ function createDerivedAtom(read, write, options) {
289
+ const n = dynamicNode(
290
+ (get) => read((a) => {
291
+ const dn = a._node;
292
+ if (dn.status === "disconnected") {
293
+ pull(dn);
294
+ }
295
+ return get(dn);
296
+ }),
297
+ {
298
+ ...options,
299
+ resubscribable: true,
300
+ resetOnTeardown: true
301
+ }
302
+ );
303
+ const result = {
304
+ get: () => {
305
+ if (n.status === "disconnected") {
306
+ return pull(n);
307
+ }
308
+ return n.get();
309
+ },
310
+ subscribe: (cb) => {
311
+ return n.subscribe((msgs) => {
312
+ for (const [t, v] of msgs) {
313
+ if (t === DATA) cb(v);
314
+ }
315
+ });
316
+ },
317
+ meta: n.meta,
318
+ _node: n
319
+ };
320
+ if (write) {
321
+ const getFn = (a) => a.get();
322
+ const setFn = (a, value) => a.set(value);
323
+ const writable = result;
324
+ writable.set = (value) => write(getFn, setFn, value);
325
+ writable.update = (fn) => {
326
+ const current = n.status === "disconnected" ? pull(n) : n.get();
327
+ return write(getFn, setFn, fn(current));
328
+ };
329
+ return writable;
330
+ }
331
+ return result;
332
+ }
333
+
334
+ // src/compat/nanostores/index.ts
335
+ var nanostores_exports = {};
336
+ __export(nanostores_exports, {
337
+ action: () => action,
338
+ atom: () => atom2,
339
+ computed: () => computed,
340
+ getValue: () => getValue,
341
+ map: () => map2,
342
+ onMount: () => onMount,
343
+ onStart: () => onStart,
344
+ onStop: () => onStop
345
+ });
346
+ var START_LISTENERS = /* @__PURE__ */ new WeakMap();
347
+ var STOP_LISTENERS = /* @__PURE__ */ new WeakMap();
348
+ function trigger(node2, map3) {
349
+ const callbacks = map3.get(node2);
350
+ if (callbacks) {
351
+ for (const cb of callbacks) cb();
352
+ }
353
+ }
354
+ function createStore(node2, extra = {}) {
355
+ let listeners = 0;
356
+ const store = {
357
+ ...extra,
358
+ get: () => getVal(node2),
359
+ subscribe: (cb) => {
360
+ if (listeners === 0) trigger(node2, START_LISTENERS);
361
+ listeners++;
362
+ const sub = node2.subscribe((msgs) => {
363
+ for (const [t, v] of msgs) {
364
+ if (t === DATA) cb(v);
365
+ }
366
+ });
367
+ cb(getVal(node2));
368
+ return () => {
369
+ sub();
370
+ listeners--;
371
+ if (listeners === 0) trigger(node2, STOP_LISTENERS);
372
+ };
373
+ },
374
+ listen: (cb) => {
375
+ if (listeners === 0) trigger(node2, START_LISTENERS);
376
+ listeners++;
377
+ const sub = node2.subscribe((msgs) => {
378
+ for (const [t, v] of msgs) {
379
+ if (t === DATA) cb(v);
380
+ }
381
+ });
382
+ return () => {
383
+ sub();
384
+ listeners--;
385
+ if (listeners === 0) trigger(node2, STOP_LISTENERS);
386
+ };
387
+ },
388
+ _node: node2
389
+ };
390
+ return store;
391
+ }
392
+ function pull2(n) {
393
+ let val = n.get();
394
+ let err;
395
+ const unsub = n.subscribe((msgs) => {
396
+ for (const [t, v] of msgs) {
397
+ if (t === DATA) val = v;
398
+ if (t === ERROR) err = v;
399
+ }
400
+ });
401
+ unsub();
402
+ if (err) throw err;
403
+ return val;
404
+ }
405
+ function getVal(n) {
406
+ if (n.status === "disconnected") {
407
+ return pull2(n);
408
+ }
409
+ return n.get();
410
+ }
411
+ function atom2(initial) {
412
+ const n = state(initial, {
413
+ resubscribable: true,
414
+ resetOnTeardown: true
415
+ });
416
+ return createStore(n, {
417
+ set: (value) => n.down([[DATA, value]])
418
+ });
419
+ }
420
+ function computed(stores, fn) {
421
+ const storeArray = Array.isArray(stores) ? stores : [stores];
422
+ const n = dynamicNode(
423
+ (get) => {
424
+ const vals = storeArray.map((s) => {
425
+ const node2 = s._node;
426
+ if (node2.status === "disconnected") {
427
+ pull2(node2);
428
+ }
429
+ return get(node2);
430
+ });
431
+ return fn(...vals);
432
+ },
433
+ {
434
+ resubscribable: true,
435
+ resetOnTeardown: true,
436
+ equals: Object.is
437
+ }
438
+ );
439
+ return createStore(n);
440
+ }
441
+ function map2(initial) {
442
+ const n = state(initial, {
443
+ resubscribable: true,
444
+ resetOnTeardown: true,
445
+ equals: () => false
446
+ });
447
+ return createStore(n, {
448
+ set: (value) => n.down([[DATA, value]]),
449
+ setKey: (key, value) => {
450
+ const current = getVal(n);
451
+ n.down([[DATA, { ...current, [key]: value }]]);
452
+ }
453
+ });
454
+ }
455
+ function getValue(store) {
456
+ return store.get();
457
+ }
458
+ function onStart(store, cb) {
459
+ const node2 = store._node;
460
+ let callbacks = START_LISTENERS.get(node2);
461
+ if (!callbacks) {
462
+ callbacks = /* @__PURE__ */ new Set();
463
+ START_LISTENERS.set(node2, callbacks);
464
+ }
465
+ callbacks.add(cb);
466
+ }
467
+ function onStop(store, cb) {
468
+ const node2 = store._node;
469
+ let callbacks = STOP_LISTENERS.get(node2);
470
+ if (!callbacks) {
471
+ callbacks = /* @__PURE__ */ new Set();
472
+ STOP_LISTENERS.set(node2, callbacks);
473
+ }
474
+ callbacks.add(cb);
475
+ }
476
+ function onMount(store, cb) {
477
+ onStart(store, () => {
478
+ const stop = cb();
479
+ if (typeof stop === "function") onStop(store, stop);
480
+ });
481
+ }
482
+ function action(_store, _name, fn) {
483
+ return (...args) => {
484
+ let result;
485
+ batch(() => {
486
+ result = fn(...args);
487
+ });
488
+ return result;
489
+ };
490
+ }
491
+
492
+ // src/compat/react/index.ts
493
+ var react_exports = {};
494
+ __export(react_exports, {
495
+ useStore: () => useStore,
496
+ useSubscribe: () => useSubscribe,
497
+ useSubscribeRecord: () => useSubscribeRecord
498
+ });
499
+ import { useCallback, useMemo, useRef, useSyncExternalStore } from "react";
500
+ function useSubscribe(node2) {
501
+ return useSyncExternalStore(
502
+ (onStoreChange) => {
503
+ let disposed = false;
504
+ const unsub = node2.subscribe(() => {
505
+ if (!disposed) onStoreChange();
506
+ });
507
+ return () => {
508
+ disposed = true;
509
+ unsub();
510
+ };
511
+ },
512
+ () => node2.get(),
513
+ () => node2.get()
514
+ // Server snapshot
515
+ );
516
+ }
517
+ function useStore(node2) {
518
+ const value = useSubscribe(node2);
519
+ const setter = useCallback(
520
+ (v) => {
521
+ node2.down([[DIRTY], [DATA, v]]);
522
+ },
523
+ [node2]
524
+ );
525
+ return [value, setter];
526
+ }
527
+ function useSubscribeRecord(keysNode, factory) {
528
+ const factoryRef = useRef(factory);
529
+ factoryRef.current = factory;
530
+ const store = useMemo(() => {
531
+ const computeSnap = () => {
532
+ const snap = {};
533
+ const keys = keysNode.get() ?? [];
534
+ for (const key of keys) {
535
+ const nodes = factoryRef.current(key);
536
+ const values = {};
537
+ for (const field of Object.keys(nodes)) {
538
+ values[field] = nodes[field].get();
539
+ }
540
+ snap[key] = values;
541
+ }
542
+ return snap;
543
+ };
544
+ let currentSnapshot = computeSnap();
545
+ return {
546
+ subscribe: (onStoreChange) => {
547
+ let disposed = false;
548
+ let entrySubs = [];
549
+ const cleanupEntries = () => {
550
+ for (const unsub of entrySubs) unsub();
551
+ entrySubs = [];
552
+ };
553
+ const sync = (nextKeys) => {
554
+ cleanupEntries();
555
+ for (const key of nextKeys) {
556
+ const nodes = factoryRef.current(key);
557
+ for (const field of Object.keys(nodes)) {
558
+ const unsub = nodes[field].subscribe(() => {
559
+ currentSnapshot = computeSnap();
560
+ if (!disposed) onStoreChange();
561
+ });
562
+ entrySubs.push(unsub);
563
+ }
564
+ }
565
+ currentSnapshot = computeSnap();
566
+ if (!disposed) onStoreChange();
567
+ };
568
+ const keysUnsub = keysNode.subscribe((msgs) => {
569
+ const hasSettled = msgs.some((m) => messageTier(m[0]) >= 2);
570
+ if (!disposed && hasSettled) sync(keysNode.get() ?? []);
571
+ });
572
+ sync(keysNode.get() ?? []);
573
+ return () => {
574
+ disposed = true;
575
+ keysUnsub();
576
+ cleanupEntries();
577
+ };
578
+ },
579
+ getSnapshot: () => currentSnapshot
580
+ };
581
+ }, [keysNode]);
582
+ return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
583
+ }
584
+
585
+ // src/compat/signals/index.ts
586
+ var signals_exports = {};
587
+ __export(signals_exports, {
588
+ Signal: () => Signal
589
+ });
590
+ var trackingStack = [];
591
+ function pull3(n) {
592
+ let val = n.get();
593
+ const unsub = n.subscribe((msgs) => {
594
+ for (const [t, v] of msgs) {
595
+ if (t === DATA) val = v;
596
+ }
597
+ });
598
+ unsub();
599
+ return val;
600
+ }
601
+ var SignalState = class {
602
+ /** @internal */
603
+ _node;
604
+ _equals;
605
+ constructor(initial, opts) {
606
+ this._equals = opts?.equals ?? Object.is;
607
+ this._node = state(initial, {
608
+ ...opts,
609
+ resubscribable: true,
610
+ resetOnTeardown: true
611
+ });
612
+ }
613
+ get() {
614
+ const tracker = trackingStack[trackingStack.length - 1];
615
+ if (tracker) {
616
+ if (this._node.status === "disconnected") {
617
+ pull3(this._node);
618
+ }
619
+ return tracker(this._node);
620
+ }
621
+ if (this._node.status === "disconnected") {
622
+ return pull3(this._node);
623
+ }
624
+ return this._node.get();
625
+ }
626
+ set(value) {
627
+ if (this._equals(this.get(), value)) return;
628
+ batch(() => {
629
+ this._node.down([[DIRTY], [DATA, value]]);
630
+ });
631
+ }
632
+ };
633
+ var SignalComputed = class {
634
+ /** @internal */
635
+ _node;
636
+ constructor(computation, opts) {
637
+ this._node = dynamicNode(
638
+ (get) => {
639
+ trackingStack.push(get);
640
+ try {
641
+ return computation();
642
+ } finally {
643
+ trackingStack.pop();
644
+ }
645
+ },
646
+ {
647
+ ...opts,
648
+ describeKind: "derived",
649
+ resubscribable: true,
650
+ resetOnTeardown: true
651
+ }
652
+ );
653
+ }
654
+ get() {
655
+ const tracker = trackingStack[trackingStack.length - 1];
656
+ if (tracker) {
657
+ if (this._node.status === "disconnected") {
658
+ pull3(this._node);
659
+ }
660
+ return tracker(this._node);
661
+ }
662
+ if (this._node.status === "disconnected") {
663
+ return pull3(this._node);
664
+ }
665
+ return this._node.get();
666
+ }
667
+ };
668
+ var Signal = {
669
+ State: SignalState,
670
+ Computed: SignalComputed,
671
+ /**
672
+ * Subscribes to changes on a signal.
673
+ * Returns an unsubscribe callback.
674
+ *
675
+ * @example
676
+ * ```ts
677
+ * const count = new Signal.State(0);
678
+ * const unsub = Signal.sub(count, v => console.log(v));
679
+ * ```
680
+ */
681
+ sub: (signal, callback) => {
682
+ const handlers = typeof callback === "function" ? { data: callback, error: void 0, complete: void 0 } : callback;
683
+ return signal._node.subscribe((msgs) => {
684
+ for (const [t, v] of msgs) {
685
+ if (t === DATA) handlers.data?.(v);
686
+ if (t === ERROR) handlers.error?.(v);
687
+ if (t === COMPLETE) handlers.complete?.();
688
+ }
689
+ });
690
+ }
691
+ };
692
+
693
+ // src/compat/solid/index.ts
694
+ var solid_exports = {};
695
+ __export(solid_exports, {
696
+ useStore: () => useStore2,
697
+ useSubscribe: () => useSubscribe2,
698
+ useSubscribeRecord: () => useSubscribeRecord2
699
+ });
700
+ import { createSignal, getOwner, onCleanup } from "solid-js";
701
+ function useSubscribe2(node2) {
702
+ const [value, setValue] = createSignal(node2.get(), { equals: false });
703
+ const unsub = node2.subscribe(() => {
704
+ setValue(() => node2.get());
705
+ });
706
+ if (getOwner()) {
707
+ onCleanup(() => unsub());
708
+ } else if (typeof console !== "undefined") {
709
+ console.warn(
710
+ "[graphrefly-ts] useSubscribe called outside a Solid reactive owner \u2014 subscription will not be auto-disposed."
711
+ );
712
+ }
713
+ return value;
714
+ }
715
+ function useStore2(node2) {
716
+ const value = useSubscribe2(node2);
717
+ const setter = (v) => {
718
+ node2.down([[DIRTY], [DATA, v]]);
719
+ };
720
+ return [value, setter];
721
+ }
722
+ function useSubscribeRecord2(keysNode, factory) {
723
+ const [value, setValue] = createSignal({}, { equals: false });
724
+ let entrySubs = [];
725
+ const cleanupEntries = () => {
726
+ for (const unsub of entrySubs) unsub();
727
+ entrySubs = [];
728
+ };
729
+ const buildSnapshot = () => {
730
+ const snap = {};
731
+ for (const key of keysNode.get() ?? []) {
732
+ const nodes = factory(key);
733
+ const values = {};
734
+ for (const field of Object.keys(nodes)) {
735
+ values[field] = nodes[field].get();
736
+ }
737
+ snap[key] = values;
738
+ }
739
+ return snap;
740
+ };
741
+ const sync = (nextKeys) => {
742
+ cleanupEntries();
743
+ for (const key of nextKeys) {
744
+ const nodes = factory(key);
745
+ for (const field of Object.keys(nodes)) {
746
+ const unsub = nodes[field].subscribe(() => {
747
+ setValue(() => buildSnapshot());
748
+ });
749
+ entrySubs.push(unsub);
750
+ }
751
+ }
752
+ setValue(() => buildSnapshot());
753
+ };
754
+ const keysUnsub = keysNode.subscribe((msgs) => {
755
+ if (msgs.some((m) => messageTier(m[0]) >= 2)) {
756
+ sync(keysNode.get() ?? []);
757
+ }
758
+ });
759
+ sync(keysNode.get() ?? []);
760
+ if (getOwner()) {
761
+ onCleanup(() => {
762
+ keysUnsub();
763
+ cleanupEntries();
764
+ });
765
+ } else if (typeof console !== "undefined") {
766
+ console.warn(
767
+ "[graphrefly-ts] useSubscribeRecord called outside a Solid reactive owner \u2014 subscription will not be auto-disposed."
768
+ );
769
+ }
770
+ return value;
771
+ }
772
+
773
+ // src/compat/svelte/index.ts
774
+ var svelte_exports = {};
775
+ __export(svelte_exports, {
776
+ useStore: () => useStore3,
777
+ useSubscribe: () => useSubscribe3,
778
+ useSubscribeRecord: () => useSubscribeRecord3
779
+ });
780
+ function useSubscribe3(node2) {
781
+ return {
782
+ subscribe(run) {
783
+ const unsub = node2.subscribe(() => {
784
+ run(node2.get());
785
+ });
786
+ run(node2.get());
787
+ return unsub;
788
+ }
789
+ };
790
+ }
791
+ function useStore3(node2) {
792
+ return {
793
+ subscribe(run) {
794
+ const unsub = node2.subscribe(() => {
795
+ run(node2.get());
796
+ });
797
+ run(node2.get());
798
+ return unsub;
799
+ },
800
+ set(value) {
801
+ node2.down([[DIRTY], [DATA, value]]);
802
+ },
803
+ update(updater) {
804
+ const next = updater(node2.get());
805
+ node2.down([[DIRTY], [DATA, next]]);
806
+ }
807
+ };
808
+ }
809
+ function useSubscribeRecord3(keysNode, factory) {
810
+ return {
811
+ subscribe(run) {
812
+ let entrySubs = [];
813
+ const cleanupEntries = () => {
814
+ for (const unsub of entrySubs) unsub();
815
+ entrySubs = [];
816
+ };
817
+ const buildSnapshot = () => {
818
+ const snap = {};
819
+ for (const key of keysNode.get() ?? []) {
820
+ const nodes = factory(key);
821
+ const values = {};
822
+ for (const field of Object.keys(nodes)) {
823
+ values[field] = nodes[field].get();
824
+ }
825
+ snap[key] = values;
826
+ }
827
+ return snap;
828
+ };
829
+ const sync = (nextKeys) => {
830
+ cleanupEntries();
831
+ for (const key of nextKeys) {
832
+ const nodes = factory(key);
833
+ for (const field of Object.keys(nodes)) {
834
+ const unsub = nodes[field].subscribe(() => {
835
+ run(buildSnapshot());
836
+ });
837
+ entrySubs.push(unsub);
838
+ }
839
+ }
840
+ run(buildSnapshot());
841
+ };
842
+ const keysUnsub = keysNode.subscribe((msgs) => {
843
+ if (msgs.some((m) => messageTier(m[0]) >= 2)) {
844
+ sync(keysNode.get() ?? []);
845
+ }
846
+ });
847
+ sync(keysNode.get() ?? []);
848
+ return () => {
849
+ keysUnsub();
850
+ cleanupEntries();
851
+ };
852
+ }
853
+ };
854
+ }
855
+
856
+ // src/compat/vue/index.ts
857
+ var vue_exports = {};
858
+ __export(vue_exports, {
859
+ useStore: () => useStore4,
860
+ useSubscribe: () => useSubscribe4,
861
+ useSubscribeRecord: () => useSubscribeRecord4
862
+ });
863
+ import {
864
+ computed as computed2,
865
+ getCurrentScope,
866
+ isRef,
867
+ onScopeDispose,
868
+ readonly,
869
+ shallowRef,
870
+ watch
871
+ } from "vue";
872
+ function useSubscribe4(node2) {
873
+ const ref = shallowRef(node2.get());
874
+ const unsub = node2.subscribe(() => {
875
+ ref.value = node2.get();
876
+ });
877
+ if (getCurrentScope()) {
878
+ onScopeDispose(() => unsub());
879
+ } else if (typeof console !== "undefined") {
880
+ console.warn(
881
+ "[graphrefly-ts] useSubscribe called outside a Vue scope \u2014 subscription will not be auto-disposed."
882
+ );
883
+ }
884
+ return readonly(ref);
885
+ }
886
+ function useStore4(node2) {
887
+ const inner = shallowRef(node2.get());
888
+ const unsub = node2.subscribe(() => {
889
+ inner.value = node2.get();
890
+ });
891
+ if (getCurrentScope()) {
892
+ onScopeDispose(() => unsub());
893
+ } else if (typeof console !== "undefined") {
894
+ console.warn(
895
+ "[graphrefly-ts] useStore called outside a Vue scope \u2014 subscription will not be auto-disposed."
896
+ );
897
+ }
898
+ return computed2({
899
+ get: () => inner.value,
900
+ set: (v) => {
901
+ node2.down([[DIRTY], [DATA, v]]);
902
+ }
903
+ });
904
+ }
905
+ function useSubscribeRecord4(keys, factory) {
906
+ const result = shallowRef({});
907
+ const activeSubs = /* @__PURE__ */ new Map();
908
+ let disposed = false;
909
+ let batchPending = false;
910
+ function scheduleBatch() {
911
+ if (batchPending) return;
912
+ batchPending = true;
913
+ queueMicrotask(() => {
914
+ if (disposed) return;
915
+ batchPending = false;
916
+ const snap = {};
917
+ for (const [key, entry] of activeSubs) {
918
+ snap[key] = { ...entry.values };
919
+ }
920
+ result.value = snap;
921
+ });
922
+ }
923
+ function sync(newKeys) {
924
+ for (const entry of activeSubs.values()) {
925
+ for (const unsub of entry.subs) unsub();
926
+ }
927
+ activeSubs.clear();
928
+ for (const key of newKeys) {
929
+ const nodes = factory(key);
930
+ const fields = Object.keys(nodes);
931
+ const values = {};
932
+ const subs = [];
933
+ for (const field of fields) {
934
+ const node2 = nodes[field];
935
+ values[field] = node2.get();
936
+ const unsub = node2.subscribe(() => {
937
+ values[field] = node2.get();
938
+ scheduleBatch();
939
+ });
940
+ subs.push(unsub);
941
+ }
942
+ activeSubs.set(key, { subs, values });
943
+ }
944
+ const snap = {};
945
+ for (const [key, entry] of activeSubs) {
946
+ snap[key] = { ...entry.values };
947
+ }
948
+ result.value = snap;
949
+ }
950
+ const readKeys = () => {
951
+ const current = typeof keys === "function" ? keys() : isRef(keys) ? keys.value : keys;
952
+ return [...current ?? []];
953
+ };
954
+ watch(readKeys, (newKeys) => sync(newKeys ?? []), { immediate: true });
955
+ if (getCurrentScope()) {
956
+ onScopeDispose(() => {
957
+ disposed = true;
958
+ for (const entry of activeSubs.values()) {
959
+ for (const unsub of entry.subs) unsub();
960
+ }
961
+ activeSubs.clear();
962
+ });
963
+ } else if (typeof console !== "undefined") {
964
+ console.warn(
965
+ "[graphrefly-ts] useSubscribeRecord called outside a Vue scope \u2014 subscription will not be auto-disposed."
966
+ );
967
+ }
968
+ return readonly(result);
969
+ }
970
+
971
+ // src/compat/zustand/index.ts
972
+ var zustand_exports = {};
973
+ __export(zustand_exports, {
974
+ create: () => create
975
+ });
976
+ function create(initializer) {
977
+ const g = new Graph("zustand");
978
+ const s = state(void 0, { name: "state" });
979
+ g.add("state", s);
980
+ const getState = () => s.get();
981
+ const setState = (partial, replace) => {
982
+ const prev = getState();
983
+ const next = typeof partial === "function" ? partial(prev) : partial;
984
+ const nextState = replace ? next : { ...prev, ...next };
985
+ s.down([[DATA, nextState]]);
986
+ };
987
+ const api = {
988
+ getState,
989
+ setState,
990
+ getInitialState: () => initialValue,
991
+ subscribe: (listener) => {
992
+ let prev = getState();
993
+ return s.subscribe((msgs) => {
994
+ for (const [t, v] of msgs) {
995
+ if (t === DATA) {
996
+ listener(v, prev);
997
+ prev = v;
998
+ }
999
+ }
1000
+ });
1001
+ },
1002
+ destroy: g.destroy.bind(g)
1003
+ };
1004
+ const initialValue = initializer(setState, getState, api);
1005
+ s.down([[DATA, initialValue]]);
1006
+ return Object.assign(g, api);
1007
+ }
1008
+
1009
+ // src/patterns/index.ts
1010
+ var patterns_exports = {};
1011
+ __export(patterns_exports, {
1012
+ ai: () => ai_exports,
1013
+ cqrs: () => cqrs_exports,
1014
+ layout: () => reactive_layout_exports,
1015
+ memory: () => memory_exports,
1016
+ messaging: () => messaging_exports,
1017
+ orchestration: () => orchestration_exports
1018
+ });
1019
+
1020
+ // src/patterns/ai.ts
1021
+ var ai_exports = {};
1022
+ __export(ai_exports, {
1023
+ AgentLoopGraph: () => AgentLoopGraph,
1024
+ ChatStreamGraph: () => ChatStreamGraph,
1025
+ ToolRegistryGraph: () => ToolRegistryGraph,
1026
+ admissionFilter3D: () => admissionFilter3D,
1027
+ agentLoop: () => agentLoop,
1028
+ agentMemory: () => agentMemory,
1029
+ chatStream: () => chatStream,
1030
+ fromLLM: () => fromLLM,
1031
+ fromLLMStream: () => fromLLMStream,
1032
+ gaugesAsContext: () => gaugesAsContext,
1033
+ graphFromSpec: () => graphFromSpec,
1034
+ knobsAsTools: () => knobsAsTools,
1035
+ llmConsolidator: () => llmConsolidator,
1036
+ llmExtractor: () => llmExtractor,
1037
+ suggestStrategy: () => suggestStrategy,
1038
+ systemPromptBuilder: () => systemPromptBuilder,
1039
+ toolRegistry: () => toolRegistry,
1040
+ validateGraphDef: () => validateGraphDef
1041
+ });
1042
+
1043
+ // src/patterns/memory.ts
1044
+ var memory_exports = {};
1045
+ __export(memory_exports, {
1046
+ collection: () => collection,
1047
+ decay: () => decay,
1048
+ knowledgeGraph: () => knowledgeGraph,
1049
+ lightCollection: () => lightCollection,
1050
+ vectorIndex: () => vectorIndex
1051
+ });
1052
+ function decay(baseScore, ageSeconds, ratePerSecond, minScore = 0) {
1053
+ if (!Number.isFinite(baseScore)) return minScore;
1054
+ if (!Number.isFinite(ageSeconds) || ageSeconds <= 0) return Math.max(minScore, baseScore);
1055
+ if (!Number.isFinite(ratePerSecond) || ratePerSecond <= 0) return Math.max(minScore, baseScore);
1056
+ const decayed = baseScore * Math.exp(-ratePerSecond * ageSeconds);
1057
+ return Math.max(minScore, decayed);
1058
+ }
1059
+ function assertMaxSize(maxSize) {
1060
+ if (maxSize !== void 0 && maxSize < 1) {
1061
+ throw new RangeError("maxSize must be >= 1");
1062
+ }
1063
+ }
1064
+ function copyMap(m) {
1065
+ return new Map(m);
1066
+ }
1067
+ function readMap(node2) {
1068
+ return node2.get() ?? /* @__PURE__ */ new Map();
1069
+ }
1070
+ function readArray(node2) {
1071
+ return node2.get() ?? [];
1072
+ }
1073
+ function cosineSimilarity(a, b) {
1074
+ const n = Math.max(a.length, b.length);
1075
+ let dot = 0;
1076
+ let na = 0;
1077
+ let nb = 0;
1078
+ for (let i = 0; i < n; i += 1) {
1079
+ const av = a[i] ?? 0;
1080
+ const bv = b[i] ?? 0;
1081
+ dot += av * bv;
1082
+ na += av * av;
1083
+ nb += bv * bv;
1084
+ }
1085
+ if (na === 0 || nb === 0) return 0;
1086
+ return dot / Math.sqrt(na * nb);
1087
+ }
1088
+ function lightCollection(opts = {}) {
1089
+ const maxSize = opts.maxSize;
1090
+ const policy2 = opts.policy ?? "fifo";
1091
+ assertMaxSize(maxSize);
1092
+ const entries = state(/* @__PURE__ */ new Map(), {
1093
+ name: opts.name,
1094
+ describeKind: "state"
1095
+ });
1096
+ function evictIfNeeded(next) {
1097
+ if (maxSize === void 0) return;
1098
+ while (next.size > maxSize) {
1099
+ let victim;
1100
+ for (const entry of next.values()) {
1101
+ if (!victim) {
1102
+ victim = entry;
1103
+ continue;
1104
+ }
1105
+ const lhs = policy2 === "lru" ? entry.lastAccessNs : entry.createdAtNs;
1106
+ const rhs = policy2 === "lru" ? victim.lastAccessNs : victim.createdAtNs;
1107
+ if (lhs < rhs) victim = entry;
1108
+ }
1109
+ if (!victim) break;
1110
+ next.delete(victim.id);
1111
+ }
1112
+ }
1113
+ function commit(next) {
1114
+ entries.down([[DATA, next]]);
1115
+ }
1116
+ return {
1117
+ entries,
1118
+ upsert(id, value) {
1119
+ const now = monotonicNs();
1120
+ const current = readMap(entries);
1121
+ const prev = current.get(id);
1122
+ const next = copyMap(current);
1123
+ next.set(id, {
1124
+ id,
1125
+ value,
1126
+ createdAtNs: prev?.createdAtNs ?? now,
1127
+ lastAccessNs: now
1128
+ });
1129
+ evictIfNeeded(next);
1130
+ commit(next);
1131
+ },
1132
+ remove(id) {
1133
+ const next = copyMap(readMap(entries));
1134
+ if (!next.delete(id)) return;
1135
+ commit(next);
1136
+ },
1137
+ clear() {
1138
+ if (readMap(entries).size === 0) return;
1139
+ commit(/* @__PURE__ */ new Map());
1140
+ },
1141
+ get(id) {
1142
+ const current = readMap(entries);
1143
+ const found = current.get(id);
1144
+ if (!found) return void 0;
1145
+ if (policy2 === "lru") {
1146
+ const now = monotonicNs();
1147
+ const next = copyMap(current);
1148
+ next.set(id, { ...found, lastAccessNs: now });
1149
+ commit(next);
1150
+ }
1151
+ return found.value;
1152
+ },
1153
+ has(id) {
1154
+ return readMap(entries).has(id);
1155
+ }
1156
+ };
1157
+ }
1158
+ function collection(name, opts = {}) {
1159
+ const maxSize = opts.maxSize;
1160
+ const policy2 = opts.policy ?? "lru";
1161
+ const decayRate = opts.decayRate ?? 0;
1162
+ const minScore = opts.minScore ?? 0;
1163
+ const scoreFn = opts.score ?? (() => 1);
1164
+ assertMaxSize(maxSize);
1165
+ const graph = new Graph(name);
1166
+ const items = state(/* @__PURE__ */ new Map(), {
1167
+ name: "items",
1168
+ describeKind: "state"
1169
+ });
1170
+ const ranked = derived(
1171
+ [items],
1172
+ ([snapshot]) => {
1173
+ const typed = snapshot ?? /* @__PURE__ */ new Map();
1174
+ const now = monotonicNs();
1175
+ const out2 = [...typed.values()].map((entry) => {
1176
+ const ageSeconds = (now - entry.lastAccessNs) / 1e9;
1177
+ return {
1178
+ ...entry,
1179
+ score: decay(entry.baseScore, ageSeconds, decayRate, minScore)
1180
+ };
1181
+ });
1182
+ out2.sort((a, b) => b.score - a.score || b.lastAccessNs - a.lastAccessNs);
1183
+ return out2;
1184
+ },
1185
+ { name: "ranked", describeKind: "derived" }
1186
+ );
1187
+ const size = derived(
1188
+ [items],
1189
+ ([snapshot]) => (snapshot ?? /* @__PURE__ */ new Map()).size,
1190
+ {
1191
+ name: "size",
1192
+ describeKind: "derived",
1193
+ initial: 0
1194
+ }
1195
+ );
1196
+ void ranked.subscribe(() => void 0);
1197
+ void size.subscribe(() => void 0);
1198
+ graph.add("items", items);
1199
+ graph.add("ranked", ranked);
1200
+ graph.add("size", size);
1201
+ graph.connect("items", "ranked");
1202
+ graph.connect("items", "size");
1203
+ function effective(entry, now) {
1204
+ const ageSeconds = (now - entry.lastAccessNs) / 1e9;
1205
+ return decay(entry.baseScore, ageSeconds, decayRate, minScore);
1206
+ }
1207
+ function evictIfNeeded(next) {
1208
+ if (maxSize === void 0) return;
1209
+ while (next.size > maxSize) {
1210
+ const now = monotonicNs();
1211
+ let victim;
1212
+ let victimScore = Number.POSITIVE_INFINITY;
1213
+ for (const entry of next.values()) {
1214
+ const score = effective(entry, now);
1215
+ if (score < victimScore) {
1216
+ victim = entry;
1217
+ victimScore = score;
1218
+ continue;
1219
+ }
1220
+ if (score === victimScore && victim) {
1221
+ const lhs = policy2 === "lru" ? entry.lastAccessNs : entry.createdAtNs;
1222
+ const rhs = policy2 === "lru" ? victim.lastAccessNs : victim.createdAtNs;
1223
+ if (lhs < rhs) victim = entry;
1224
+ }
1225
+ }
1226
+ if (!victim) break;
1227
+ next.delete(victim.id);
1228
+ }
1229
+ }
1230
+ function commit(next) {
1231
+ items.down([[DATA, next]]);
1232
+ }
1233
+ const out = Object.assign(graph, {
1234
+ upsert(id, value, upsertOpts) {
1235
+ const now = monotonicNs();
1236
+ const current = readMap(items);
1237
+ const prev = current.get(id);
1238
+ const baseScore = upsertOpts?.score ?? scoreFn(value);
1239
+ const next = copyMap(current);
1240
+ next.set(id, {
1241
+ id,
1242
+ value,
1243
+ baseScore,
1244
+ createdAtNs: prev?.createdAtNs ?? now,
1245
+ lastAccessNs: now
1246
+ });
1247
+ evictIfNeeded(next);
1248
+ commit(next);
1249
+ },
1250
+ remove(id) {
1251
+ const next = copyMap(readMap(items));
1252
+ if (!next.delete(id)) return;
1253
+ commit(next);
1254
+ },
1255
+ clear() {
1256
+ if (readMap(items).size === 0) return;
1257
+ commit(/* @__PURE__ */ new Map());
1258
+ },
1259
+ getItem(id) {
1260
+ const current = readMap(items);
1261
+ const found = current.get(id);
1262
+ if (!found) return void 0;
1263
+ if (policy2 === "lru") {
1264
+ const next = copyMap(current);
1265
+ next.set(id, { ...found, lastAccessNs: monotonicNs() });
1266
+ commit(next);
1267
+ }
1268
+ return found;
1269
+ }
1270
+ });
1271
+ return out;
1272
+ }
1273
+ function vectorIndex(opts = {}) {
1274
+ const backend = opts.backend ?? "flat";
1275
+ const dimension = opts.dimension;
1276
+ let hnsw;
1277
+ if (backend === "hnsw") {
1278
+ hnsw = opts.hnswFactory?.();
1279
+ if (!hnsw) {
1280
+ throw new Error(
1281
+ 'vectorIndex backend "hnsw" requires an optional dependency adapter; install your HNSW package and provide `hnswFactory`.'
1282
+ );
1283
+ }
1284
+ }
1285
+ const entries = state(/* @__PURE__ */ new Map(), {
1286
+ describeKind: "state",
1287
+ name: "vector-index"
1288
+ });
1289
+ function assertDimension(vector) {
1290
+ if (dimension !== void 0 && vector.length !== dimension) {
1291
+ throw new RangeError(
1292
+ `vector dimension mismatch: expected ${dimension}, got ${vector.length}`
1293
+ );
1294
+ }
1295
+ }
1296
+ function commit(next) {
1297
+ entries.down([[DATA, next]]);
1298
+ }
1299
+ return {
1300
+ backend,
1301
+ entries,
1302
+ upsert(id, vector, meta) {
1303
+ assertDimension(vector);
1304
+ const next = copyMap(readMap(entries));
1305
+ next.set(id, { id, vector: [...vector], meta });
1306
+ if (backend === "hnsw") hnsw.upsert(id, vector, meta);
1307
+ commit(next);
1308
+ },
1309
+ remove(id) {
1310
+ const next = copyMap(readMap(entries));
1311
+ if (!next.delete(id)) return;
1312
+ if (backend === "hnsw") hnsw.remove(id);
1313
+ commit(next);
1314
+ },
1315
+ clear() {
1316
+ if (readMap(entries).size === 0) return;
1317
+ if (backend === "hnsw") hnsw.clear();
1318
+ commit(/* @__PURE__ */ new Map());
1319
+ },
1320
+ search(query, k = 5) {
1321
+ assertDimension(query);
1322
+ if (k <= 0) return [];
1323
+ if (backend === "hnsw") return hnsw.search(query, k);
1324
+ const ranked = [...readMap(entries).values()].map((row) => ({
1325
+ id: row.id,
1326
+ score: cosineSimilarity(query, row.vector),
1327
+ meta: row.meta
1328
+ })).sort((a, b) => b.score - a.score).slice(0, k);
1329
+ return ranked;
1330
+ }
1331
+ };
1332
+ }
1333
+ function knowledgeGraph(name) {
1334
+ const graph = new Graph(name);
1335
+ const entities = state(/* @__PURE__ */ new Map(), {
1336
+ name: "entities",
1337
+ describeKind: "state"
1338
+ });
1339
+ const edges = state([], {
1340
+ name: "edges",
1341
+ describeKind: "state"
1342
+ });
1343
+ const adjacency = derived(
1344
+ [edges],
1345
+ ([rows]) => {
1346
+ const typed = rows ?? [];
1347
+ const out2 = /* @__PURE__ */ new Map();
1348
+ for (const edge of typed) {
1349
+ const prev = out2.get(edge.from) ?? [];
1350
+ out2.set(edge.from, Object.freeze([...prev, edge]));
1351
+ }
1352
+ return out2;
1353
+ },
1354
+ { name: "adjacency", describeKind: "derived", initial: /* @__PURE__ */ new Map() }
1355
+ );
1356
+ void adjacency.subscribe(() => void 0);
1357
+ graph.add("entities", entities);
1358
+ graph.add("edges", edges);
1359
+ graph.add("adjacency", adjacency);
1360
+ graph.connect("edges", "adjacency");
1361
+ function commitEntities(next) {
1362
+ entities.down([[DATA, next]]);
1363
+ }
1364
+ function commitEdges(next) {
1365
+ edges.down([[DATA, next]]);
1366
+ }
1367
+ const out = Object.assign(graph, {
1368
+ upsertEntity(id, value) {
1369
+ const next = copyMap(readMap(entities));
1370
+ next.set(id, value);
1371
+ commitEntities(next);
1372
+ },
1373
+ removeEntity(id) {
1374
+ const nextEntities = copyMap(readMap(entities));
1375
+ const existed = nextEntities.delete(id);
1376
+ const currentEdges = readArray(edges);
1377
+ const nextEdges = currentEdges.filter((edge) => edge.from !== id && edge.to !== id);
1378
+ if (!existed && nextEdges.length === currentEdges.length) return;
1379
+ commitEntities(nextEntities);
1380
+ commitEdges(nextEdges);
1381
+ },
1382
+ link(from, to, relation, weight = 1) {
1383
+ const key = `${from}\0${to}\0${relation}`;
1384
+ const currentEdges = readArray(edges);
1385
+ const existing = new Set(
1386
+ currentEdges.map((edge) => `${edge.from}\0${edge.to}\0${edge.relation}`)
1387
+ );
1388
+ const next = [...currentEdges];
1389
+ if (existing.has(key)) {
1390
+ for (let i = 0; i < next.length; i += 1) {
1391
+ const edge = next[i];
1392
+ if (edge.from === from && edge.to === to && edge.relation === relation) {
1393
+ next[i] = { ...edge, weight };
1394
+ break;
1395
+ }
1396
+ }
1397
+ } else {
1398
+ next.push({ from, to, relation, weight });
1399
+ }
1400
+ commitEdges(next);
1401
+ },
1402
+ unlink(from, to, relation) {
1403
+ const currentEdges = readArray(edges);
1404
+ const next = currentEdges.filter(
1405
+ (edge) => relation === void 0 ? !(edge.from === from && edge.to === to) : !(edge.from === from && edge.to === to && edge.relation === relation)
1406
+ );
1407
+ if (next.length === currentEdges.length) return;
1408
+ commitEdges(next);
1409
+ },
1410
+ related(id, relation) {
1411
+ return readArray(edges).filter(
1412
+ (edge) => (edge.from === id || edge.to === id) && (relation === void 0 || edge.relation === relation)
1413
+ );
1414
+ }
1415
+ });
1416
+ return out;
1417
+ }
1418
+
1419
+ // src/patterns/ai.ts
1420
+ function aiMeta(kind, extra) {
1421
+ return {
1422
+ ai: true,
1423
+ ai_type: kind,
1424
+ ...extra ?? {}
1425
+ };
1426
+ }
1427
+ function keepalive(n) {
1428
+ return n.subscribe(() => void 0);
1429
+ }
1430
+ function isPromiseLike(x) {
1431
+ return x != null && typeof x.then === "function";
1432
+ }
1433
+ function isNodeLike(x) {
1434
+ return typeof x === "object" && x !== null && "subscribe" in x && typeof x.subscribe === "function" && "get" in x && typeof x.get === "function";
1435
+ }
1436
+ function isAsyncIterableLike(x) {
1437
+ return x != null && typeof x === "object" && Symbol.asyncIterator in x && typeof x[Symbol.asyncIterator] === "function";
1438
+ }
1439
+ var DEFAULT_TIMEOUT_MS = 3e4;
1440
+ function firstDataFromNode(resolved, opts) {
1441
+ if (resolved.status === "settled") {
1442
+ const immediate = resolved.get();
1443
+ if (immediate !== void 0) {
1444
+ return Promise.resolve(immediate);
1445
+ }
1446
+ }
1447
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1448
+ return new Promise((resolve, reject) => {
1449
+ let timer;
1450
+ const cleanup = () => {
1451
+ if (timer !== void 0) clearTimeout(timer);
1452
+ };
1453
+ const unsub = resolved.subscribe((messages) => {
1454
+ for (const msg of messages) {
1455
+ if (msg[0] === DATA) {
1456
+ cleanup();
1457
+ unsub();
1458
+ resolve(msg[1]);
1459
+ return;
1460
+ }
1461
+ if (msg[0] === ERROR) {
1462
+ cleanup();
1463
+ unsub();
1464
+ reject(msg[1]);
1465
+ return;
1466
+ }
1467
+ if (msg[0] === COMPLETE) {
1468
+ cleanup();
1469
+ unsub();
1470
+ reject(new Error("firstDataFromNode: completed without producing a value"));
1471
+ return;
1472
+ }
1473
+ }
1474
+ });
1475
+ timer = setTimeout(() => {
1476
+ unsub();
1477
+ reject(new Error(`firstDataFromNode: timed out after ${timeoutMs}ms`));
1478
+ }, timeoutMs);
1479
+ });
1480
+ }
1481
+ async function resolveToolHandlerResult(value) {
1482
+ if (isPromiseLike(value)) {
1483
+ return resolveToolHandlerResult(await value);
1484
+ }
1485
+ if (isNodeLike(value)) {
1486
+ return firstDataFromNode(value);
1487
+ }
1488
+ if (isAsyncIterableLike(value)) {
1489
+ return firstDataFromNode(fromAny(value));
1490
+ }
1491
+ return value;
1492
+ }
1493
+ function fromLLM(adapter, messages, opts) {
1494
+ const msgsNode = fromAny(messages);
1495
+ const result = switchMap(msgsNode, (msgs) => {
1496
+ if (!msgs || msgs.length === 0) {
1497
+ return state(null);
1498
+ }
1499
+ const tools = opts?.tools;
1500
+ return adapter.invoke(msgs, {
1501
+ model: opts?.model,
1502
+ temperature: opts?.temperature,
1503
+ maxTokens: opts?.maxTokens,
1504
+ tools,
1505
+ systemPrompt: opts?.systemPrompt
1506
+ });
1507
+ });
1508
+ return result;
1509
+ }
1510
+ function fromLLMStream(adapter, messages, opts) {
1511
+ const msgsNode = fromAny(messages);
1512
+ let controller;
1513
+ const log = reactiveLog([], { name: opts?.name ?? "llmStream" });
1514
+ const eff = effect([msgsNode], ([msgs]) => {
1515
+ controller?.abort();
1516
+ log.clear();
1517
+ const chatMsgs = msgs;
1518
+ if (!chatMsgs || chatMsgs.length === 0) return;
1519
+ controller = new AbortController();
1520
+ const iter = adapter.stream(chatMsgs, {
1521
+ model: opts?.model,
1522
+ temperature: opts?.temperature,
1523
+ maxTokens: opts?.maxTokens,
1524
+ tools: opts?.tools,
1525
+ systemPrompt: opts?.systemPrompt,
1526
+ signal: controller.signal
1527
+ });
1528
+ const ctrl = controller;
1529
+ (async () => {
1530
+ try {
1531
+ for await (const chunk of iter) {
1532
+ if (ctrl.signal.aborted) break;
1533
+ log.append(chunk);
1534
+ }
1535
+ } catch (_err) {
1536
+ }
1537
+ })();
1538
+ return () => {
1539
+ ctrl.abort();
1540
+ };
1541
+ });
1542
+ const unsub = keepalive(eff);
1543
+ return {
1544
+ node: log.entries,
1545
+ dispose() {
1546
+ controller?.abort();
1547
+ unsub();
1548
+ eff.down([[TEARDOWN]]);
1549
+ }
1550
+ };
1551
+ }
1552
+ var ChatStreamGraph = class extends Graph {
1553
+ _log;
1554
+ _keepaliveSubs = [];
1555
+ messages;
1556
+ latest;
1557
+ messageCount;
1558
+ constructor(name, opts = {}) {
1559
+ super(name, opts.graph);
1560
+ this._log = reactiveLog([], {
1561
+ name: "messages",
1562
+ maxSize: opts.maxMessages
1563
+ });
1564
+ this.messages = this._log.entries;
1565
+ this.add("messages", this.messages);
1566
+ this.latest = derived(
1567
+ [this.messages],
1568
+ ([snapshot]) => {
1569
+ const entries = snapshot.value.entries;
1570
+ return entries.length === 0 ? void 0 : entries[entries.length - 1];
1571
+ },
1572
+ {
1573
+ name: "latest",
1574
+ describeKind: "derived",
1575
+ meta: aiMeta("chat_latest"),
1576
+ initial: void 0
1577
+ }
1578
+ );
1579
+ this.add("latest", this.latest);
1580
+ this.connect("messages", "latest");
1581
+ this._keepaliveSubs.push(keepalive(this.latest));
1582
+ this.messageCount = derived(
1583
+ [this.messages],
1584
+ ([snapshot]) => snapshot.value.entries.length,
1585
+ {
1586
+ name: "messageCount",
1587
+ describeKind: "derived",
1588
+ meta: aiMeta("chat_message_count"),
1589
+ initial: 0
1590
+ }
1591
+ );
1592
+ this.add("messageCount", this.messageCount);
1593
+ this.connect("messages", "messageCount");
1594
+ this._keepaliveSubs.push(keepalive(this.messageCount));
1595
+ }
1596
+ append(role, content, extra) {
1597
+ this._log.append({ role, content, ...extra });
1598
+ }
1599
+ appendToolResult(callId, content) {
1600
+ this._log.append({ role: "tool", content, toolCallId: callId });
1601
+ }
1602
+ clear() {
1603
+ this._log.clear();
1604
+ }
1605
+ allMessages() {
1606
+ return this.messages.get().value.entries;
1607
+ }
1608
+ destroy() {
1609
+ for (const unsub of this._keepaliveSubs) unsub();
1610
+ this._keepaliveSubs.length = 0;
1611
+ super.destroy();
1612
+ }
1613
+ };
1614
+ function chatStream(name, opts) {
1615
+ return new ChatStreamGraph(name, opts);
1616
+ }
1617
+ var ToolRegistryGraph = class extends Graph {
1618
+ definitions;
1619
+ schemas;
1620
+ _keepaliveSubs = [];
1621
+ constructor(name, opts = {}) {
1622
+ super(name, opts.graph);
1623
+ this.definitions = state(/* @__PURE__ */ new Map(), {
1624
+ name: "definitions",
1625
+ describeKind: "state",
1626
+ meta: aiMeta("tool_definitions")
1627
+ });
1628
+ this.add("definitions", this.definitions);
1629
+ this.schemas = derived(
1630
+ [this.definitions],
1631
+ ([defs]) => [...(defs ?? /* @__PURE__ */ new Map()).values()],
1632
+ {
1633
+ name: "schemas",
1634
+ describeKind: "derived",
1635
+ meta: aiMeta("tool_schemas"),
1636
+ initial: []
1637
+ }
1638
+ );
1639
+ this.add("schemas", this.schemas);
1640
+ this.connect("definitions", "schemas");
1641
+ this._keepaliveSubs.push(keepalive(this.schemas));
1642
+ }
1643
+ register(tool) {
1644
+ const current = this.definitions.get();
1645
+ const next = new Map(current);
1646
+ next.set(tool.name, tool);
1647
+ this.definitions.down([[DATA, next]]);
1648
+ }
1649
+ unregister(name) {
1650
+ const current = this.definitions.get();
1651
+ if (!current.has(name)) return;
1652
+ const next = new Map(current);
1653
+ next.delete(name);
1654
+ this.definitions.down([[DATA, next]]);
1655
+ }
1656
+ async execute(name, args) {
1657
+ const defs = this.definitions.get();
1658
+ const tool = defs.get(name);
1659
+ if (!tool) throw new Error(`toolRegistry: unknown tool "${name}"`);
1660
+ const raw = tool.handler(args);
1661
+ return resolveToolHandlerResult(raw);
1662
+ }
1663
+ getDefinition(name) {
1664
+ return this.definitions.get().get(name);
1665
+ }
1666
+ destroy() {
1667
+ for (const unsub of this._keepaliveSubs) unsub();
1668
+ this._keepaliveSubs.length = 0;
1669
+ super.destroy();
1670
+ }
1671
+ };
1672
+ function toolRegistry(name, opts) {
1673
+ return new ToolRegistryGraph(name, opts);
1674
+ }
1675
+ function systemPromptBuilder(sections, opts) {
1676
+ const separator = opts?.separator ?? "\n\n";
1677
+ const sectionNodes = sections.map((s) => typeof s === "string" ? state(s) : fromAny(s));
1678
+ const prompt = derived(
1679
+ sectionNodes,
1680
+ (values) => values.filter((v) => v != null && v !== "").join(separator),
1681
+ {
1682
+ name: opts?.name ?? "systemPrompt",
1683
+ describeKind: "derived",
1684
+ meta: aiMeta("system_prompt"),
1685
+ initial: ""
1686
+ }
1687
+ );
1688
+ const unsub = keepalive(prompt);
1689
+ return Object.assign(prompt, { dispose: unsub });
1690
+ }
1691
+ function llmExtractor(systemPrompt, opts) {
1692
+ return (raw, existing) => {
1693
+ const existingKeys = [...existing.keys()].slice(0, 100);
1694
+ const messages = [
1695
+ { role: "system", content: systemPrompt },
1696
+ {
1697
+ role: "user",
1698
+ content: JSON.stringify({
1699
+ input: raw,
1700
+ existingKeys
1701
+ })
1702
+ }
1703
+ ];
1704
+ return producer((_deps, actions) => {
1705
+ let active = true;
1706
+ const result = opts.adapter.invoke(messages, {
1707
+ model: opts.model,
1708
+ temperature: opts.temperature ?? 0,
1709
+ maxTokens: opts.maxTokens
1710
+ });
1711
+ const resolved = fromAny(result);
1712
+ const unsub = resolved.subscribe((msgs) => {
1713
+ if (!active) return;
1714
+ let done = false;
1715
+ for (const msg of msgs) {
1716
+ if (done) break;
1717
+ if (msg[0] === DATA) {
1718
+ const response = msg[1];
1719
+ try {
1720
+ const parsed = JSON.parse(response.content);
1721
+ actions.emit(parsed);
1722
+ actions.down([[COMPLETE]]);
1723
+ } catch {
1724
+ actions.down([
1725
+ [ERROR, new Error("llmExtractor: failed to parse LLM response as JSON")]
1726
+ ]);
1727
+ }
1728
+ done = true;
1729
+ } else if (msg[0] === ERROR) {
1730
+ actions.down([[ERROR, msg[1]]]);
1731
+ done = true;
1732
+ } else if (msg[0] === COMPLETE) {
1733
+ actions.down([[COMPLETE]]);
1734
+ done = true;
1735
+ } else {
1736
+ actions.down([[msg[0], msg[1]]]);
1737
+ }
1738
+ }
1739
+ });
1740
+ return () => {
1741
+ unsub();
1742
+ active = false;
1743
+ };
1744
+ });
1745
+ };
1746
+ }
1747
+ function llmConsolidator(systemPrompt, opts) {
1748
+ return (entries) => {
1749
+ const entriesArray = [...entries.entries()].map(([key, value]) => ({ key, value }));
1750
+ const messages = [
1751
+ { role: "system", content: systemPrompt },
1752
+ { role: "user", content: JSON.stringify({ memories: entriesArray }) }
1753
+ ];
1754
+ return producer((_deps, actions) => {
1755
+ let active = true;
1756
+ const result = opts.adapter.invoke(messages, {
1757
+ model: opts.model,
1758
+ temperature: opts.temperature ?? 0,
1759
+ maxTokens: opts.maxTokens
1760
+ });
1761
+ const resolved = fromAny(result);
1762
+ const unsub = resolved.subscribe((msgs) => {
1763
+ if (!active) return;
1764
+ let done = false;
1765
+ for (const msg of msgs) {
1766
+ if (done) break;
1767
+ if (msg[0] === DATA) {
1768
+ const response = msg[1];
1769
+ try {
1770
+ const parsed = JSON.parse(response.content);
1771
+ actions.emit(parsed);
1772
+ actions.down([[COMPLETE]]);
1773
+ } catch {
1774
+ actions.down([
1775
+ [ERROR, new Error("llmConsolidator: failed to parse LLM response as JSON")]
1776
+ ]);
1777
+ }
1778
+ done = true;
1779
+ } else if (msg[0] === ERROR) {
1780
+ actions.down([[ERROR, msg[1]]]);
1781
+ done = true;
1782
+ } else if (msg[0] === COMPLETE) {
1783
+ actions.down([[COMPLETE]]);
1784
+ done = true;
1785
+ } else {
1786
+ actions.down([[msg[0], msg[1]]]);
1787
+ }
1788
+ }
1789
+ });
1790
+ return () => {
1791
+ unsub();
1792
+ active = false;
1793
+ };
1794
+ });
1795
+ };
1796
+ }
1797
+ function defaultAdmissionScorer(_raw) {
1798
+ return { persistence: 0.5, structure: 0.5, personalValue: 0.5 };
1799
+ }
1800
+ function admissionFilter3D(opts = {}) {
1801
+ const scoreFn = opts.scoreFn ?? defaultAdmissionScorer;
1802
+ const pThresh = opts.persistenceThreshold ?? 0.3;
1803
+ const pvThresh = opts.personalValueThreshold ?? 0.3;
1804
+ const reqStructured = opts.requireStructured ?? false;
1805
+ return (raw) => {
1806
+ const scores = scoreFn(raw);
1807
+ if (scores.persistence < pThresh) return false;
1808
+ if (scores.personalValue < pvThresh) return false;
1809
+ if (reqStructured && scores.structure <= 0) return false;
1810
+ return true;
1811
+ };
1812
+ }
1813
+ var DEFAULT_DECAY_RATE = Math.LN2 / (7 * 86400);
1814
+ function extractStoreMap(snapshot) {
1815
+ if (snapshot && typeof snapshot === "object" && "value" in snapshot && typeof snapshot.value === "object" && snapshot.value !== null && "map" in snapshot.value) {
1816
+ return snapshot.value.map ?? /* @__PURE__ */ new Map();
1817
+ }
1818
+ return /* @__PURE__ */ new Map();
1819
+ }
1820
+ function agentMemory(name, source, opts) {
1821
+ const graph = new Graph(name, opts.graph);
1822
+ const keepaliveSubs = [];
1823
+ let rawExtractFn;
1824
+ if (opts.extractFn) {
1825
+ rawExtractFn = opts.extractFn;
1826
+ } else if (opts.adapter && opts.extractPrompt) {
1827
+ rawExtractFn = llmExtractor(opts.extractPrompt, { adapter: opts.adapter });
1828
+ } else {
1829
+ throw new Error("agentMemory: provide either extractFn or adapter + extractPrompt");
1830
+ }
1831
+ const extractFn = (raw, existing) => {
1832
+ if (raw == null) return { upsert: [] };
1833
+ return rawExtractFn(raw, existing);
1834
+ };
1835
+ let filteredSource = source;
1836
+ if (opts.admissionFilter) {
1837
+ const srcNode = fromAny(source);
1838
+ const filter2 = opts.admissionFilter;
1839
+ filteredSource = derived(
1840
+ [srcNode],
1841
+ ([raw]) => {
1842
+ if (filter2(raw)) return raw;
1843
+ return void 0;
1844
+ },
1845
+ { name: "admissionFilter", describeKind: "derived" }
1846
+ );
1847
+ }
1848
+ let consolidateFn;
1849
+ if (opts.consolidateFn) {
1850
+ consolidateFn = opts.consolidateFn;
1851
+ } else if (opts.adapter && opts.consolidatePrompt) {
1852
+ consolidateFn = llmConsolidator(opts.consolidatePrompt, { adapter: opts.adapter });
1853
+ }
1854
+ let consolidateTrigger = opts.consolidateTrigger;
1855
+ if (!consolidateTrigger && consolidateFn && opts.reflection?.enabled !== false) {
1856
+ const interval2 = opts.reflection?.interval ?? 3e5;
1857
+ consolidateTrigger = fromTimer(interval2, { period: interval2 });
1858
+ }
1859
+ const distillOpts = {
1860
+ score: opts.score,
1861
+ cost: opts.cost,
1862
+ budget: opts.budget ?? 2e3,
1863
+ context: opts.context,
1864
+ consolidate: consolidateFn,
1865
+ consolidateTrigger
1866
+ };
1867
+ const distillBundle = distill(filteredSource, extractFn, distillOpts);
1868
+ graph.add("store", distillBundle.store.node);
1869
+ graph.add("compact", distillBundle.compact);
1870
+ graph.add("size", distillBundle.size);
1871
+ graph.connect("store", "compact");
1872
+ graph.connect("store", "size");
1873
+ let vectors = null;
1874
+ if (opts.vectorDimensions && opts.vectorDimensions > 0 && opts.embedFn) {
1875
+ vectors = vectorIndex({ dimension: opts.vectorDimensions });
1876
+ graph.add("vectorIndex", vectors.entries);
1877
+ }
1878
+ let kg = null;
1879
+ if (opts.enableKnowledgeGraph) {
1880
+ kg = knowledgeGraph(`${name}-kg`);
1881
+ graph.mount("kg", kg);
1882
+ }
1883
+ let memoryTiersBundle = null;
1884
+ if (opts.tiers) {
1885
+ const tiersOpts = opts.tiers;
1886
+ const decayRate = tiersOpts.decayRate ?? DEFAULT_DECAY_RATE;
1887
+ const maxActive = tiersOpts.maxActive ?? 1e3;
1888
+ const archiveThreshold = tiersOpts.archiveThreshold ?? 0.1;
1889
+ const permanentFilter = tiersOpts.permanentFilter ?? (() => false);
1890
+ const permanent = lightCollection({ name: "permanent" });
1891
+ graph.add("permanent", permanent.entries);
1892
+ const permanentKeys = /* @__PURE__ */ new Set();
1893
+ const tierOf = (key) => {
1894
+ if (permanentKeys.has(key)) return "permanent";
1895
+ const storeMap = extractStoreMap(distillBundle.store.node.get());
1896
+ if (storeMap.has(key)) return "active";
1897
+ return "archived";
1898
+ };
1899
+ const markPermanent = (key, value) => {
1900
+ permanentKeys.add(key);
1901
+ permanent.upsert(key, value);
1902
+ };
1903
+ const entryCreatedAtNs = /* @__PURE__ */ new Map();
1904
+ const storeNode = distillBundle.store.node;
1905
+ const contextNode = opts.context ? fromAny(opts.context) : state(null);
1906
+ const tierClassifier = effect([storeNode, contextNode], ([snapshot, ctx]) => {
1907
+ const storeMap = extractStoreMap(snapshot);
1908
+ const nowNs = monotonicNs();
1909
+ const toArchive = [];
1910
+ const toPermanent = [];
1911
+ for (const [key, mem] of storeMap) {
1912
+ if (!entryCreatedAtNs.has(key)) {
1913
+ entryCreatedAtNs.set(key, nowNs);
1914
+ }
1915
+ if (permanentFilter(key, mem)) {
1916
+ toPermanent.push({ key, value: mem });
1917
+ continue;
1918
+ }
1919
+ const baseScore = opts.score(mem, ctx);
1920
+ const createdNs = entryCreatedAtNs.get(key) ?? nowNs;
1921
+ const ageSeconds = Number(nowNs - createdNs) / 1e9;
1922
+ const decayed = decay(baseScore, ageSeconds, decayRate);
1923
+ if (decayed < archiveThreshold) {
1924
+ toArchive.push(key);
1925
+ }
1926
+ }
1927
+ for (const key of entryCreatedAtNs.keys()) {
1928
+ if (!storeMap.has(key)) entryCreatedAtNs.delete(key);
1929
+ }
1930
+ for (const { key, value } of toPermanent) {
1931
+ if (!permanentKeys.has(key)) {
1932
+ markPermanent(key, value);
1933
+ }
1934
+ }
1935
+ const activeCount = storeMap.size - permanentKeys.size;
1936
+ if (activeCount > maxActive) {
1937
+ const scored = [...storeMap.entries()].filter(([k]) => !permanentKeys.has(k)).map(([k, m]) => ({ key: k, score: opts.score(m, ctx) })).sort((a, b) => a.score - b.score);
1938
+ const excess = activeCount - maxActive;
1939
+ for (let i = 0; i < excess && i < scored.length; i++) {
1940
+ const sk = scored[i].key;
1941
+ if (!toArchive.includes(sk)) toArchive.push(sk);
1942
+ }
1943
+ }
1944
+ if (toArchive.length > 0) {
1945
+ batch(() => {
1946
+ for (const key of toArchive) {
1947
+ distillBundle.store.delete(key);
1948
+ }
1949
+ });
1950
+ }
1951
+ });
1952
+ keepaliveSubs.push(tierClassifier.subscribe(() => void 0));
1953
+ let archiveHandle = null;
1954
+ if (tiersOpts.archiveAdapter) {
1955
+ archiveHandle = graph.autoCheckpoint(
1956
+ tiersOpts.archiveAdapter,
1957
+ tiersOpts.archiveCheckpointOptions
1958
+ );
1959
+ }
1960
+ memoryTiersBundle = {
1961
+ permanent,
1962
+ activeEntries: storeNode,
1963
+ archiveHandle,
1964
+ tierOf,
1965
+ markPermanent
1966
+ };
1967
+ }
1968
+ if (vectors || kg) {
1969
+ const embedFn = opts.embedFn;
1970
+ const entityFn = opts.entityFn;
1971
+ const storeNode = distillBundle.store.node;
1972
+ const indexer = effect([storeNode], ([snapshot]) => {
1973
+ const storeMap = extractStoreMap(snapshot);
1974
+ for (const [key, mem] of storeMap) {
1975
+ if (vectors && embedFn) {
1976
+ const vec = embedFn(mem);
1977
+ if (vec) vectors.upsert(key, vec, mem);
1978
+ }
1979
+ if (kg && entityFn) {
1980
+ const extracted = entityFn(key, mem);
1981
+ if (extracted) {
1982
+ for (const ent of extracted.entities ?? []) {
1983
+ kg.upsertEntity(ent.id, ent.value);
1984
+ }
1985
+ for (const rel of extracted.relations ?? []) {
1986
+ kg.link(rel.from, rel.to, rel.relation, rel.weight);
1987
+ }
1988
+ }
1989
+ }
1990
+ }
1991
+ });
1992
+ keepaliveSubs.push(indexer.subscribe(() => void 0));
1993
+ }
1994
+ let retrievalNode = null;
1995
+ let retrievalTraceNode = null;
1996
+ let retrieveFn = null;
1997
+ if (vectors || kg) {
1998
+ const topK = opts.retrieval?.topK ?? 20;
1999
+ const graphDepth = opts.retrieval?.graphDepth ?? 1;
2000
+ const budget = opts.budget ?? 2e3;
2001
+ const costFn = opts.cost;
2002
+ const scoreFn = opts.score;
2003
+ const queryInput = state(null, {
2004
+ name: "retrievalQuery",
2005
+ describeKind: "state"
2006
+ });
2007
+ graph.add("retrievalQuery", queryInput);
2008
+ const contextNode = opts.context ? fromAny(opts.context) : state(null);
2009
+ const traceState = state(null, {
2010
+ name: "retrievalTrace",
2011
+ describeKind: "state",
2012
+ meta: aiMeta("retrieval_trace")
2013
+ });
2014
+ graph.add("retrievalTrace", traceState);
2015
+ retrievalTraceNode = traceState;
2016
+ const storeNode = distillBundle.store.node;
2017
+ let lastTrace = null;
2018
+ const retrievalDerived = derived(
2019
+ [queryInput, storeNode, contextNode],
2020
+ ([query, snapshot, ctx]) => {
2021
+ if (!query) return [];
2022
+ const q = query;
2023
+ const storeMap = extractStoreMap(snapshot);
2024
+ const candidateMap = /* @__PURE__ */ new Map();
2025
+ let vectorCandidates = [];
2026
+ if (vectors && q.vector) {
2027
+ vectorCandidates = vectors.search(q.vector, topK);
2028
+ for (const vc of vectorCandidates) {
2029
+ const mem = storeMap.get(vc.id);
2030
+ if (mem) {
2031
+ candidateMap.set(vc.id, { value: mem, sources: /* @__PURE__ */ new Set(["vector"]) });
2032
+ }
2033
+ }
2034
+ }
2035
+ const graphExpanded = [];
2036
+ if (kg) {
2037
+ const seedIds = [...q.entityIds ?? [], ...[...candidateMap.keys()]];
2038
+ const visited = /* @__PURE__ */ new Set();
2039
+ let frontier = seedIds;
2040
+ for (let depth = 0; depth < graphDepth; depth++) {
2041
+ const nextFrontier = [];
2042
+ for (const id of frontier) {
2043
+ if (visited.has(id)) continue;
2044
+ visited.add(id);
2045
+ const related = kg.related(id);
2046
+ for (const edge of related) {
2047
+ const targetId = edge.to;
2048
+ if (!visited.has(targetId)) {
2049
+ nextFrontier.push(targetId);
2050
+ const mem = storeMap.get(targetId);
2051
+ if (mem) {
2052
+ const existing = candidateMap.get(targetId);
2053
+ if (existing) {
2054
+ existing.sources.add("graph");
2055
+ } else {
2056
+ candidateMap.set(targetId, { value: mem, sources: /* @__PURE__ */ new Set(["graph"]) });
2057
+ }
2058
+ graphExpanded.push(targetId);
2059
+ }
2060
+ }
2061
+ }
2062
+ }
2063
+ frontier = nextFrontier;
2064
+ }
2065
+ }
2066
+ for (const [key, mem] of storeMap) {
2067
+ if (!candidateMap.has(key)) {
2068
+ candidateMap.set(key, { value: mem, sources: /* @__PURE__ */ new Set(["store"]) });
2069
+ }
2070
+ }
2071
+ const ranked = [];
2072
+ for (const [key, { value, sources }] of candidateMap) {
2073
+ const score = scoreFn(value, ctx);
2074
+ ranked.push({ key, value, score, sources: [...sources] });
2075
+ }
2076
+ ranked.sort((a, b) => b.score - a.score);
2077
+ const packed = [];
2078
+ let usedBudget = 0;
2079
+ for (const entry of ranked) {
2080
+ const c = costFn(entry.value);
2081
+ if (usedBudget + c > budget && packed.length > 0) break;
2082
+ packed.push(entry);
2083
+ usedBudget += c;
2084
+ }
2085
+ lastTrace = { vectorCandidates, graphExpanded, ranked, packed };
2086
+ return packed;
2087
+ },
2088
+ {
2089
+ name: "retrieval",
2090
+ describeKind: "derived",
2091
+ meta: aiMeta("retrieval_pipeline"),
2092
+ initial: []
2093
+ }
2094
+ );
2095
+ graph.add("retrieval", retrievalDerived);
2096
+ graph.connect("retrievalQuery", "retrieval");
2097
+ graph.connect("store", "retrieval");
2098
+ keepaliveSubs.push(retrievalDerived.subscribe(() => void 0));
2099
+ retrievalNode = retrievalDerived;
2100
+ retrieveFn = (query) => {
2101
+ queryInput.down([[DATA, query]]);
2102
+ const result = retrievalDerived.get();
2103
+ if (lastTrace) {
2104
+ traceState.down([[DATA, lastTrace]]);
2105
+ }
2106
+ return result;
2107
+ };
2108
+ }
2109
+ const origDestroy = graph.destroy.bind(graph);
2110
+ graph.destroy = () => {
2111
+ for (const unsub of keepaliveSubs) unsub();
2112
+ keepaliveSubs.length = 0;
2113
+ origDestroy();
2114
+ };
2115
+ return Object.assign(graph, {
2116
+ distillBundle,
2117
+ compact: distillBundle.compact,
2118
+ size: distillBundle.size,
2119
+ vectors,
2120
+ kg,
2121
+ memoryTiers: memoryTiersBundle,
2122
+ retrieval: retrievalNode,
2123
+ retrievalTrace: retrievalTraceNode,
2124
+ retrieve: retrieveFn
2125
+ });
2126
+ }
2127
+ var AgentLoopGraph = class extends Graph {
2128
+ chat;
2129
+ tools;
2130
+ status;
2131
+ turnCount;
2132
+ lastResponse;
2133
+ _statusState;
2134
+ _turnCountState;
2135
+ _adapter;
2136
+ _maxTurns;
2137
+ _stopWhen;
2138
+ _onToolCall;
2139
+ _systemPrompt;
2140
+ _model;
2141
+ _temperature;
2142
+ _maxTokens;
2143
+ _running = false;
2144
+ _abortController = null;
2145
+ constructor(name, opts) {
2146
+ super(name, opts.graph);
2147
+ this._adapter = opts.adapter;
2148
+ this._maxTurns = opts.maxTurns ?? 10;
2149
+ this._stopWhen = opts.stopWhen;
2150
+ this._onToolCall = opts.onToolCall;
2151
+ this._systemPrompt = opts.systemPrompt;
2152
+ this._model = opts.model;
2153
+ this._temperature = opts.temperature;
2154
+ this._maxTokens = opts.maxTokens;
2155
+ this.chat = chatStream(`${name}-chat`, { maxMessages: opts.maxMessages });
2156
+ this.mount("chat", this.chat);
2157
+ this.tools = toolRegistry(`${name}-tools`);
2158
+ this.mount("tools", this.tools);
2159
+ if (opts.tools) {
2160
+ for (const tool of opts.tools) {
2161
+ this.tools.register(tool);
2162
+ }
2163
+ }
2164
+ this._statusState = state("idle", {
2165
+ name: "status",
2166
+ describeKind: "state",
2167
+ meta: aiMeta("agent_status")
2168
+ });
2169
+ this.status = this._statusState;
2170
+ this.add("status", this.status);
2171
+ this._turnCountState = state(0, {
2172
+ name: "turnCount",
2173
+ describeKind: "state",
2174
+ meta: aiMeta("agent_turn_count")
2175
+ });
2176
+ this.turnCount = this._turnCountState;
2177
+ this.add("turnCount", this.turnCount);
2178
+ this.lastResponse = state(null, {
2179
+ name: "lastResponse",
2180
+ describeKind: "state",
2181
+ meta: aiMeta("agent_last_response")
2182
+ });
2183
+ this.add("lastResponse", this.lastResponse);
2184
+ }
2185
+ /**
2186
+ * Start the agent loop with a user message. The loop runs reactively:
2187
+ * think (LLM call) → act (tool execution) → repeat until done.
2188
+ *
2189
+ * Messages accumulate across calls. Call `chat.clear()` before `run()`
2190
+ * to reset conversation history.
2191
+ */
2192
+ async run(userMessage) {
2193
+ if (this._running) throw new Error("agentLoop: already running");
2194
+ this._running = true;
2195
+ this._abortController = new AbortController();
2196
+ const { signal } = this._abortController;
2197
+ batch(() => {
2198
+ this._statusState.down([[DATA, "idle"]]);
2199
+ this._turnCountState.down([[DATA, 0]]);
2200
+ });
2201
+ this.chat.append("user", userMessage);
2202
+ try {
2203
+ let turns = 0;
2204
+ while (turns < this._maxTurns) {
2205
+ if (signal.aborted) throw new Error("agentLoop: aborted");
2206
+ turns++;
2207
+ batch(() => {
2208
+ this._turnCountState.down([[DATA, turns]]);
2209
+ this._statusState.down([[DATA, "thinking"]]);
2210
+ });
2211
+ const msgs = this.chat.allMessages();
2212
+ const toolSchemas = this.tools.schemas.get() ?? [];
2213
+ const response = await this._invokeLLM(msgs, toolSchemas, signal);
2214
+ if (signal.aborted) throw new Error("agentLoop: aborted");
2215
+ this.lastResponse.down([[DATA, response]]);
2216
+ this.chat.append("assistant", response.content, {
2217
+ toolCalls: response.toolCalls
2218
+ });
2219
+ if (this._shouldStop(response)) {
2220
+ this._statusState.down([[DATA, "done"]]);
2221
+ this._running = false;
2222
+ this._abortController = null;
2223
+ return response;
2224
+ }
2225
+ if (response.toolCalls && response.toolCalls.length > 0) {
2226
+ this._statusState.down([[DATA, "acting"]]);
2227
+ for (const call of response.toolCalls) {
2228
+ if (signal.aborted) throw new Error("agentLoop: aborted");
2229
+ this._onToolCall?.(call);
2230
+ try {
2231
+ const result = await this.tools.execute(call.name, call.arguments);
2232
+ this.chat.appendToolResult(call.id, JSON.stringify(result));
2233
+ } catch (err) {
2234
+ this.chat.appendToolResult(call.id, JSON.stringify({ error: String(err) }));
2235
+ }
2236
+ }
2237
+ } else {
2238
+ this._statusState.down([[DATA, "done"]]);
2239
+ this._running = false;
2240
+ this._abortController = null;
2241
+ return response;
2242
+ }
2243
+ }
2244
+ this._statusState.down([[DATA, "done"]]);
2245
+ this._running = false;
2246
+ this._abortController = null;
2247
+ return this.lastResponse.get();
2248
+ } catch (err) {
2249
+ this._statusState.down([[DATA, "error"]]);
2250
+ this._running = false;
2251
+ this._abortController = null;
2252
+ throw err;
2253
+ }
2254
+ }
2255
+ async _invokeLLM(msgs, tools, signal) {
2256
+ const result = this._adapter.invoke(msgs, {
2257
+ tools: tools.length > 0 ? tools : void 0,
2258
+ systemPrompt: this._systemPrompt,
2259
+ model: this._model,
2260
+ temperature: this._temperature,
2261
+ maxTokens: this._maxTokens,
2262
+ signal
2263
+ });
2264
+ if (result == null) {
2265
+ throw new Error("_invokeLLM: adapter.invoke() returned null or undefined");
2266
+ }
2267
+ if (typeof result === "string") {
2268
+ throw new Error("_invokeLLM: adapter.invoke() returned a string, expected LLMResponse");
2269
+ }
2270
+ if (typeof result === "object" && "content" in result && !("subscribe" in result) && !("then" in result)) {
2271
+ return result;
2272
+ }
2273
+ if (isPromiseLike(result)) {
2274
+ const awaited = await result;
2275
+ if (typeof awaited === "object" && awaited !== null && "content" in awaited && !("subscribe" in awaited)) {
2276
+ return awaited;
2277
+ }
2278
+ return firstDataFromNode(fromAny(awaited));
2279
+ }
2280
+ return firstDataFromNode(fromAny(result));
2281
+ }
2282
+ _shouldStop(response) {
2283
+ if (response.finishReason === "end_turn" && (!response.toolCalls || response.toolCalls.length === 0))
2284
+ return true;
2285
+ if (this._stopWhen?.(response)) return true;
2286
+ return false;
2287
+ }
2288
+ destroy() {
2289
+ if (this._abortController) {
2290
+ this._abortController.abort();
2291
+ this._abortController = null;
2292
+ }
2293
+ this._running = false;
2294
+ super.destroy();
2295
+ }
2296
+ };
2297
+ function agentLoop(name, opts) {
2298
+ return new AgentLoopGraph(name, opts);
2299
+ }
2300
+ function metaToJsonSchema(meta) {
2301
+ const schema = {};
2302
+ const metaType = meta.type;
2303
+ if (metaType === "enum" && Array.isArray(meta.values)) {
2304
+ schema.type = "string";
2305
+ schema.enum = meta.values;
2306
+ } else if (metaType === "integer") {
2307
+ schema.type = "integer";
2308
+ } else if (metaType === "number") {
2309
+ schema.type = "number";
2310
+ } else if (metaType === "boolean") {
2311
+ schema.type = "boolean";
2312
+ } else if (metaType === "string") {
2313
+ schema.type = "string";
2314
+ } else {
2315
+ schema.type = ["string", "number", "boolean"];
2316
+ }
2317
+ if (Array.isArray(meta.range) && meta.range.length === 2) {
2318
+ schema.minimum = meta.range[0];
2319
+ schema.maximum = meta.range[1];
2320
+ }
2321
+ if (typeof meta.format === "string") {
2322
+ schema.description = `Format: ${meta.format}`;
2323
+ }
2324
+ if (typeof meta.unit === "string") {
2325
+ if (schema.description) {
2326
+ schema.description += ` (${meta.unit})`;
2327
+ } else {
2328
+ schema.description = `Unit: ${meta.unit}`;
2329
+ }
2330
+ }
2331
+ return schema;
2332
+ }
2333
+ function knobsAsTools(graph, actor) {
2334
+ const described = graph.describe({ actor });
2335
+ const openai = [];
2336
+ const mcp = [];
2337
+ const definitions = [];
2338
+ for (const [path, node2] of Object.entries(described.nodes)) {
2339
+ if (node2.type !== "state") continue;
2340
+ if (path.includes("::__meta__::")) continue;
2341
+ if (node2.status === "completed" || node2.status === "errored") continue;
2342
+ const access = node2.meta.access;
2343
+ if (access === "human" || access === "system") continue;
2344
+ const description = node2.meta.description ?? `Set the value of ${path}`;
2345
+ const valueSchema = metaToJsonSchema(node2.meta);
2346
+ const parameterSchema = {
2347
+ type: "object",
2348
+ required: ["value"],
2349
+ properties: {
2350
+ value: valueSchema
2351
+ },
2352
+ additionalProperties: false
2353
+ };
2354
+ const sanitizedName = path.replace(/::/g, "__");
2355
+ openai.push({
2356
+ type: "function",
2357
+ function: {
2358
+ name: sanitizedName,
2359
+ description,
2360
+ parameters: parameterSchema
2361
+ }
2362
+ });
2363
+ mcp.push({
2364
+ name: path,
2365
+ description,
2366
+ inputSchema: parameterSchema
2367
+ });
2368
+ const graphRef = graph;
2369
+ const actorRef = actor;
2370
+ const nv = node2.v;
2371
+ definitions.push({
2372
+ name: path,
2373
+ description,
2374
+ parameters: parameterSchema,
2375
+ handler(args) {
2376
+ graphRef.set(path, args.value, actorRef ? { actor: actorRef } : void 0);
2377
+ return args.value;
2378
+ },
2379
+ ...nv != null ? { version: { id: nv.id, version: nv.version } } : {}
2380
+ });
2381
+ }
2382
+ return { openai, mcp, definitions };
2383
+ }
2384
+ function gaugesAsContext(graph, actor, options) {
2385
+ const described = graph.describe({ actor });
2386
+ const groupByTags = options?.groupByTags ?? true;
2387
+ const separator = options?.separator ?? "\n";
2388
+ const entries = [];
2389
+ const sinceVersion = options?.sinceVersion;
2390
+ for (const [path, node2] of Object.entries(described.nodes)) {
2391
+ const desc = node2.meta.description;
2392
+ const format = node2.meta.format;
2393
+ if (!desc && !format) continue;
2394
+ if (sinceVersion != null && node2.v != null) {
2395
+ const lastSeen = sinceVersion.get(path);
2396
+ if (lastSeen != null && lastSeen.id === node2.v.id && node2.v.version <= lastSeen.version)
2397
+ continue;
2398
+ }
2399
+ const label = desc ?? path;
2400
+ const value = node2.value;
2401
+ const unit = node2.meta.unit;
2402
+ let formatted;
2403
+ if (format === "currency" && typeof value === "number") {
2404
+ formatted = `$${value.toFixed(2)}`;
2405
+ } else if (format === "percentage" && typeof value === "number") {
2406
+ formatted = `${(value * 100).toFixed(1)}%`;
2407
+ } else if (value === void 0 || value === null) {
2408
+ formatted = "(no value)";
2409
+ } else {
2410
+ formatted = String(value);
2411
+ }
2412
+ if (unit && format !== "currency" && format !== "percentage") {
2413
+ formatted = `${formatted} ${unit}`;
2414
+ }
2415
+ entries.push({ path, description: label, formatted });
2416
+ }
2417
+ if (entries.length === 0) return "";
2418
+ if (groupByTags) {
2419
+ const tagGroups = /* @__PURE__ */ new Map();
2420
+ const ungrouped = [];
2421
+ for (const entry of entries) {
2422
+ const node2 = described.nodes[entry.path];
2423
+ const tags = node2.meta.tags;
2424
+ if (tags && tags.length > 0) {
2425
+ const tag = tags[0];
2426
+ let group = tagGroups.get(tag);
2427
+ if (!group) {
2428
+ group = [];
2429
+ tagGroups.set(tag, group);
2430
+ }
2431
+ group.push(entry);
2432
+ } else {
2433
+ ungrouped.push(entry);
2434
+ }
2435
+ }
2436
+ if (tagGroups.size === 0) {
2437
+ return entries.map((e) => `- ${e.description}: ${e.formatted}`).join(separator);
2438
+ }
2439
+ const sections = [];
2440
+ for (const [tag, group] of [...tagGroups.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
2441
+ sections.push(
2442
+ `[${tag}]${separator}${group.map((e) => `- ${e.description}: ${e.formatted}`).join(separator)}`
2443
+ );
2444
+ }
2445
+ if (ungrouped.length > 0) {
2446
+ sections.push(ungrouped.map((e) => `- ${e.description}: ${e.formatted}`).join(separator));
2447
+ }
2448
+ return sections.join(separator + separator);
2449
+ }
2450
+ return entries.map((e) => `- ${e.description}: ${e.formatted}`).join(separator);
2451
+ }
2452
+ var VALID_NODE_TYPES = /* @__PURE__ */ new Set(["state", "derived", "producer", "operator", "effect"]);
2453
+ function validateGraphDef(def) {
2454
+ const errors = [];
2455
+ if (def == null || typeof def !== "object") {
2456
+ return { valid: false, errors: ["Definition must be a non-null object"] };
2457
+ }
2458
+ const d = def;
2459
+ if (typeof d.name !== "string" || d.name.length === 0) {
2460
+ errors.push("Missing or empty 'name' field");
2461
+ }
2462
+ if (d.nodes == null || typeof d.nodes !== "object" || Array.isArray(d.nodes)) {
2463
+ errors.push("Missing or invalid 'nodes' field (must be an object)");
2464
+ return { valid: false, errors };
2465
+ }
2466
+ const nodeNames = new Set(Object.keys(d.nodes));
2467
+ for (const [name, raw] of Object.entries(d.nodes)) {
2468
+ if (raw == null || typeof raw !== "object") {
2469
+ errors.push(`Node "${name}": must be an object`);
2470
+ continue;
2471
+ }
2472
+ const node2 = raw;
2473
+ if (typeof node2.type !== "string" || !VALID_NODE_TYPES.has(node2.type)) {
2474
+ errors.push(
2475
+ `Node "${name}": invalid type "${String(node2.type)}" (expected: ${[...VALID_NODE_TYPES].join(", ")})`
2476
+ );
2477
+ }
2478
+ if (Array.isArray(node2.deps)) {
2479
+ for (const dep of node2.deps) {
2480
+ if (typeof dep === "string" && !nodeNames.has(dep)) {
2481
+ errors.push(`Node "${name}": dep "${dep}" does not reference an existing node`);
2482
+ }
2483
+ }
2484
+ }
2485
+ }
2486
+ if (!Array.isArray(d.edges)) {
2487
+ if (d.edges !== void 0) {
2488
+ errors.push("'edges' must be an array");
2489
+ }
2490
+ } else {
2491
+ const seen = /* @__PURE__ */ new Set();
2492
+ for (let i = 0; i < d.edges.length; i++) {
2493
+ const edge = d.edges[i];
2494
+ if (edge == null || typeof edge !== "object") {
2495
+ errors.push(`Edge [${i}]: must be an object`);
2496
+ continue;
2497
+ }
2498
+ const e = edge;
2499
+ if (typeof e.from !== "string" || !nodeNames.has(e.from)) {
2500
+ errors.push(`Edge [${i}]: 'from' "${String(e.from)}" does not reference an existing node`);
2501
+ }
2502
+ if (typeof e.to !== "string" || !nodeNames.has(e.to)) {
2503
+ errors.push(`Edge [${i}]: 'to' "${String(e.to)}" does not reference an existing node`);
2504
+ }
2505
+ const key = `${e.from}->${e.to}`;
2506
+ if (seen.has(key)) {
2507
+ errors.push(`Edge [${i}]: duplicate edge ${key}`);
2508
+ }
2509
+ seen.add(key);
2510
+ }
2511
+ }
2512
+ return { valid: errors.length === 0, errors };
2513
+ }
2514
+ function stripFences(text) {
2515
+ const match = text.match(/^```(?:json)?\s*([\s\S]*?)\s*```[\s\S]*$/);
2516
+ return match ? match[1] : text;
2517
+ }
2518
+ var GRAPH_FROM_SPEC_SYSTEM_PROMPT = `You are a graph architect for GraphReFly, a reactive graph protocol.
2519
+
2520
+ Given a natural-language description, produce a JSON graph definition with this structure:
2521
+
2522
+ {
2523
+ "name": "<graph_name>",
2524
+ "nodes": {
2525
+ "<node_name>": {
2526
+ "type": "state" | "derived" | "producer" | "operator" | "effect",
2527
+ "value": <initial_value_or_null>,
2528
+ "deps": ["<dep_node_name>", ...],
2529
+ "meta": {
2530
+ "description": "<human-readable purpose>",
2531
+ "type": "string" | "number" | "boolean" | "integer" | "enum",
2532
+ "range": [min, max],
2533
+ "values": ["a", "b"],
2534
+ "format": "currency" | "percentage" | "status",
2535
+ "access": "human" | "llm" | "both" | "system",
2536
+ "unit": "<unit>",
2537
+ "tags": ["<tag>"]
2538
+ }
2539
+ }
2540
+ },
2541
+ "edges": [
2542
+ { "from": "<source_node>", "to": "<target_node>" }
2543
+ ]
2544
+ }
2545
+
2546
+ Rules:
2547
+ - "state" nodes have no deps and hold user/LLM-writable values (knobs).
2548
+ - "derived" nodes have deps and compute from them.
2549
+ - "effect" nodes have deps but produce side effects (no return value).
2550
+ - "producer" nodes have no deps but generate values asynchronously.
2551
+ - Edges wire output of one node as input to another. They must match deps.
2552
+ - meta.description is required for every node.
2553
+ - Return ONLY valid JSON, no markdown fences or commentary.`;
2554
+ async function graphFromSpec(naturalLanguage, adapter, opts) {
2555
+ const systemPrompt = opts?.systemPromptExtra ? `${GRAPH_FROM_SPEC_SYSTEM_PROMPT}
2556
+
2557
+ ${opts.systemPromptExtra}` : GRAPH_FROM_SPEC_SYSTEM_PROMPT;
2558
+ const messages = [
2559
+ { role: "system", content: systemPrompt },
2560
+ { role: "user", content: naturalLanguage }
2561
+ ];
2562
+ const rawResult = adapter.invoke(messages, {
2563
+ model: opts?.model,
2564
+ temperature: opts?.temperature ?? 0,
2565
+ maxTokens: opts?.maxTokens
2566
+ });
2567
+ const response = await resolveToolHandlerResult(rawResult);
2568
+ let content = response.content.trim();
2569
+ if (content.startsWith("```")) {
2570
+ content = stripFences(content);
2571
+ }
2572
+ let parsed;
2573
+ try {
2574
+ parsed = JSON.parse(content);
2575
+ } catch {
2576
+ throw new Error(`graphFromSpec: LLM response is not valid JSON: ${content.slice(0, 200)}`);
2577
+ }
2578
+ const validation = validateGraphDef(parsed);
2579
+ if (!validation.valid) {
2580
+ throw new Error(`graphFromSpec: invalid graph definition:
2581
+ ${validation.errors.join("\n")}`);
2582
+ }
2583
+ const def = parsed;
2584
+ if (def.version === void 0) def.version = 1;
2585
+ if (!Array.isArray(def.subgraphs)) def.subgraphs = [];
2586
+ return Graph.fromSnapshot(def, opts?.build);
2587
+ }
2588
+ var SUGGEST_STRATEGY_SYSTEM_PROMPT = `You are a reactive graph optimizer for GraphReFly.
2589
+
2590
+ Given a graph's current structure (from describe()) and a problem statement, suggest topology and parameter changes to solve the problem.
2591
+
2592
+ Return ONLY valid JSON with this structure:
2593
+ {
2594
+ "summary": "<one-line summary of the strategy>",
2595
+ "reasoning": "<explanation of why these changes help>",
2596
+ "operations": [
2597
+ { "type": "add_node", "name": "<name>", "nodeType": "state|derived|effect|producer|operator", "meta": {...}, "initial": <value> },
2598
+ { "type": "remove_node", "name": "<name>" },
2599
+ { "type": "connect", "from": "<source>", "to": "<target>" },
2600
+ { "type": "disconnect", "from": "<source>", "to": "<target>" },
2601
+ { "type": "set_value", "name": "<name>", "value": <new_value> },
2602
+ { "type": "update_meta", "name": "<name>", "key": "<meta_key>", "value": <new_value> }
2603
+ ]
2604
+ }
2605
+
2606
+ Rules:
2607
+ - Only suggest operations that reference existing nodes (for remove/disconnect/set_value/update_meta) or new nodes you define (for add_node).
2608
+ - Keep changes minimal \u2014 prefer the smallest set of operations that solves the problem.
2609
+ - Return ONLY valid JSON, no markdown fences or commentary.`;
2610
+ async function suggestStrategy(graph, problem, adapter, opts) {
2611
+ const described = graph.describe({ actor: opts?.actor });
2612
+ const messages = [
2613
+ { role: "system", content: SUGGEST_STRATEGY_SYSTEM_PROMPT },
2614
+ {
2615
+ role: "user",
2616
+ content: JSON.stringify({
2617
+ graph: described,
2618
+ problem
2619
+ })
2620
+ }
2621
+ ];
2622
+ const rawResult = adapter.invoke(messages, {
2623
+ model: opts?.model,
2624
+ temperature: opts?.temperature ?? 0,
2625
+ maxTokens: opts?.maxTokens
2626
+ });
2627
+ const response = await resolveToolHandlerResult(rawResult);
2628
+ let content = response.content.trim();
2629
+ if (content.startsWith("```")) {
2630
+ content = content.replace(/^```(?:json)?\s*/, "").replace(/\s*```$/, "");
2631
+ }
2632
+ let parsed;
2633
+ try {
2634
+ parsed = JSON.parse(content);
2635
+ } catch {
2636
+ throw new Error(`suggestStrategy: LLM response is not valid JSON: ${content.slice(0, 200)}`);
2637
+ }
2638
+ const plan = parsed;
2639
+ if (typeof plan.summary !== "string") {
2640
+ throw new Error("suggestStrategy: missing 'summary' in response");
2641
+ }
2642
+ if (typeof plan.reasoning !== "string") {
2643
+ throw new Error("suggestStrategy: missing 'reasoning' in response");
2644
+ }
2645
+ if (!Array.isArray(plan.operations)) {
2646
+ throw new Error("suggestStrategy: missing 'operations' array in response");
2647
+ }
2648
+ return {
2649
+ summary: plan.summary,
2650
+ reasoning: plan.reasoning,
2651
+ operations: plan.operations
2652
+ };
2653
+ }
2654
+
2655
+ // src/patterns/messaging.ts
2656
+ var messaging_exports = {};
2657
+ __export(messaging_exports, {
2658
+ JobFlowGraph: () => JobFlowGraph,
2659
+ JobQueueGraph: () => JobQueueGraph,
2660
+ SubscriptionGraph: () => SubscriptionGraph,
2661
+ TopicBridgeGraph: () => TopicBridgeGraph,
2662
+ TopicGraph: () => TopicGraph,
2663
+ jobFlow: () => jobFlow,
2664
+ jobQueue: () => jobQueue,
2665
+ subscription: () => subscription,
2666
+ topic: () => topic,
2667
+ topicBridge: () => topicBridge
2668
+ });
2669
+ var DEFAULT_MAX_PER_PUMP = 2147483647;
2670
+ function requireNonNegativeInt(value, label) {
2671
+ if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
2672
+ throw new Error(`${label} must be a non-negative integer`);
2673
+ }
2674
+ return value;
2675
+ }
2676
+ function keepalive2(n) {
2677
+ return n.subscribe(() => {
2678
+ });
2679
+ }
2680
+ function messagingMeta(kind, extra) {
2681
+ return {
2682
+ messaging: true,
2683
+ messaging_type: kind,
2684
+ ...extra ?? {}
2685
+ };
2686
+ }
2687
+ var TopicGraph = class extends Graph {
2688
+ _log;
2689
+ _keepaliveDisposers = [];
2690
+ events;
2691
+ latest;
2692
+ constructor(name, opts = {}) {
2693
+ super(name, opts.graph);
2694
+ this._log = reactiveLog([], { name: "events", maxSize: opts.retainedLimit });
2695
+ this.events = this._log.entries;
2696
+ this.add("events", this.events);
2697
+ this.latest = derived(
2698
+ [this.events],
2699
+ ([snapshot]) => {
2700
+ const entries = snapshot.value.entries;
2701
+ return entries.length === 0 ? void 0 : entries[entries.length - 1];
2702
+ },
2703
+ {
2704
+ name: "latest",
2705
+ describeKind: "derived",
2706
+ meta: messagingMeta("topic_latest"),
2707
+ initial: void 0
2708
+ }
2709
+ );
2710
+ this.add("latest", this.latest);
2711
+ this.connect("events", "latest");
2712
+ this._keepaliveDisposers.push(keepalive2(this.latest));
2713
+ }
2714
+ destroy() {
2715
+ for (const dispose of this._keepaliveDisposers) dispose();
2716
+ this._keepaliveDisposers.length = 0;
2717
+ super.destroy();
2718
+ }
2719
+ publish(value) {
2720
+ this._log.append(value);
2721
+ }
2722
+ retained() {
2723
+ const snapshot = this.events.get();
2724
+ return snapshot.value.entries;
2725
+ }
2726
+ };
2727
+ var SubscriptionGraph = class extends Graph {
2728
+ _keepaliveDisposers = [];
2729
+ source;
2730
+ cursor;
2731
+ available;
2732
+ constructor(name, topicGraph, opts = {}) {
2733
+ super(name, opts.graph);
2734
+ const initialCursor = requireNonNegativeInt(opts.cursor ?? 0, "subscription cursor");
2735
+ this.mount("topic", topicGraph);
2736
+ const topicEvents = topicGraph.events;
2737
+ this.source = derived([topicEvents], ([snapshot]) => snapshot, {
2738
+ name: "source",
2739
+ describeKind: "derived",
2740
+ meta: messagingMeta("subscription_source"),
2741
+ initial: topicEvents.get()
2742
+ });
2743
+ this.add("source", this.source);
2744
+ this.cursor = state(initialCursor, {
2745
+ name: "cursor",
2746
+ describeKind: "state",
2747
+ meta: messagingMeta("subscription_cursor")
2748
+ });
2749
+ this.add("cursor", this.cursor);
2750
+ this.available = derived(
2751
+ [this.source, this.cursor],
2752
+ ([sourceSnapshot, cursor]) => {
2753
+ const entries = sourceSnapshot.value.entries;
2754
+ const start = Math.max(0, Math.trunc(cursor ?? 0));
2755
+ return entries.slice(start);
2756
+ },
2757
+ {
2758
+ name: "available",
2759
+ describeKind: "derived",
2760
+ meta: messagingMeta("subscription_available"),
2761
+ initial: []
2762
+ }
2763
+ );
2764
+ this.add("available", this.available);
2765
+ this.connect("topic::events", "source");
2766
+ this.connect("source", "available");
2767
+ this.connect("cursor", "available");
2768
+ this._keepaliveDisposers.push(keepalive2(this.source));
2769
+ this._keepaliveDisposers.push(keepalive2(this.available));
2770
+ }
2771
+ destroy() {
2772
+ for (const dispose of this._keepaliveDisposers) dispose();
2773
+ this._keepaliveDisposers.length = 0;
2774
+ super.destroy();
2775
+ }
2776
+ ack(count) {
2777
+ const available = this.available.get();
2778
+ const requested = count === void 0 ? available.length : requireNonNegativeInt(count, "subscription ack count");
2779
+ const step = Math.min(requested, available.length);
2780
+ if (step <= 0) return this.cursor.get();
2781
+ const next = this.cursor.get() + step;
2782
+ this.cursor.down([[DATA, next]]);
2783
+ return next;
2784
+ }
2785
+ pull(limit, opts = {}) {
2786
+ const available = this.available.get();
2787
+ const max = limit === void 0 ? available.length : requireNonNegativeInt(limit, "subscription pull limit");
2788
+ const out = available.slice(0, max);
2789
+ if (opts.ack && out.length > 0) this.ack(out.length);
2790
+ return out;
2791
+ }
2792
+ };
2793
+ var JobQueueGraph = class extends Graph {
2794
+ _pending;
2795
+ _jobs;
2796
+ _keepaliveDisposers = [];
2797
+ _seq = 0;
2798
+ pending;
2799
+ jobs;
2800
+ depth;
2801
+ constructor(name, opts = {}) {
2802
+ super(name, opts.graph);
2803
+ this._pending = reactiveList([], { name: "pending" });
2804
+ this._jobs = reactiveMap({ name: "jobs" });
2805
+ this.pending = this._pending.items;
2806
+ this.jobs = this._jobs.node;
2807
+ this.add("pending", this.pending);
2808
+ this.add("jobs", this.jobs);
2809
+ this.depth = derived(
2810
+ [this.pending],
2811
+ ([snapshot]) => snapshot.value.items.length,
2812
+ {
2813
+ name: "depth",
2814
+ describeKind: "derived",
2815
+ meta: messagingMeta("queue_depth"),
2816
+ initial: 0
2817
+ }
2818
+ );
2819
+ this.add("depth", this.depth);
2820
+ this.connect("pending", "depth");
2821
+ this._keepaliveDisposers.push(keepalive2(this.depth));
2822
+ }
2823
+ destroy() {
2824
+ for (const dispose of this._keepaliveDisposers) dispose();
2825
+ this._keepaliveDisposers.length = 0;
2826
+ super.destroy();
2827
+ }
2828
+ enqueue(payload, opts = {}) {
2829
+ const id = opts.id ?? `${this.name}-${++this._seq}`;
2830
+ if (this._jobs.get(id) !== void 0) {
2831
+ throw new Error(`jobQueue("${this.name}"): duplicate job id "${id}"`);
2832
+ }
2833
+ const job = {
2834
+ id,
2835
+ payload,
2836
+ attempts: 0,
2837
+ metadata: Object.freeze({ ...opts.metadata ?? {} }),
2838
+ state: "queued"
2839
+ };
2840
+ this._jobs.set(id, job);
2841
+ this._pending.append(id);
2842
+ return id;
2843
+ }
2844
+ claim(limit = 1) {
2845
+ const max = requireNonNegativeInt(limit, "job queue claim limit");
2846
+ if (max === 0) return [];
2847
+ const out = [];
2848
+ while (out.length < max) {
2849
+ const snapshot = this.pending.get();
2850
+ const ids = snapshot.value.items;
2851
+ if (ids.length === 0) break;
2852
+ const id = this._pending.pop(0);
2853
+ const job = this._jobs.get(id);
2854
+ if (!job || job.state !== "queued") continue;
2855
+ const inflight = {
2856
+ ...job,
2857
+ state: "inflight",
2858
+ attempts: job.attempts + 1
2859
+ };
2860
+ this._jobs.set(id, inflight);
2861
+ out.push(inflight);
2862
+ }
2863
+ return out;
2864
+ }
2865
+ ack(id) {
2866
+ const job = this._jobs.get(id);
2867
+ if (!job || job.state !== "inflight") return false;
2868
+ this._jobs.delete(id);
2869
+ return true;
2870
+ }
2871
+ nack(id, opts = {}) {
2872
+ const job = this._jobs.get(id);
2873
+ if (!job || job.state !== "inflight") return false;
2874
+ if (opts.requeue ?? true) {
2875
+ this._jobs.set(id, { ...job, state: "queued" });
2876
+ this._pending.append(id);
2877
+ return true;
2878
+ }
2879
+ this._jobs.delete(id);
2880
+ return true;
2881
+ }
2882
+ };
2883
+ var JobFlowGraph = class extends Graph {
2884
+ _stageNames;
2885
+ _queues = /* @__PURE__ */ new Map();
2886
+ _keepaliveDisposers = [];
2887
+ _completed;
2888
+ completed;
2889
+ completedCount;
2890
+ constructor(name, opts = {}) {
2891
+ super(name, opts.graph);
2892
+ const stages = (opts.stages ?? ["incoming", "processing", "done"]).map((v) => v.trim());
2893
+ if (stages.length < 2) {
2894
+ throw new Error(`jobFlow("${name}"): requires at least 2 stages`);
2895
+ }
2896
+ const unique = new Set(stages);
2897
+ if (unique.size !== stages.length) {
2898
+ throw new Error(`jobFlow("${name}"): stage names must be unique`);
2899
+ }
2900
+ this._stageNames = Object.freeze([...stages]);
2901
+ for (const stage of this._stageNames) {
2902
+ const q = jobQueue(`${name}-${stage}`);
2903
+ this._queues.set(stage, q);
2904
+ this.mount(stage, q);
2905
+ }
2906
+ this._completed = reactiveLog([], { name: "completed" });
2907
+ this.completed = this._completed.entries;
2908
+ this.add("completed", this.completed);
2909
+ this.completedCount = derived(
2910
+ [this.completed],
2911
+ ([snapshot]) => snapshot.value.entries.length,
2912
+ {
2913
+ name: "completedCount",
2914
+ describeKind: "derived",
2915
+ meta: messagingMeta("job_flow_completed_count"),
2916
+ initial: 0
2917
+ }
2918
+ );
2919
+ this.add("completedCount", this.completedCount);
2920
+ this.connect("completed", "completedCount");
2921
+ this._keepaliveDisposers.push(keepalive2(this.completedCount));
2922
+ const maxPerPump = Math.max(
2923
+ 1,
2924
+ requireNonNegativeInt(opts.maxPerPump ?? DEFAULT_MAX_PER_PUMP, "job flow maxPerPump")
2925
+ );
2926
+ for (let i = 0; i < this._stageNames.length; i += 1) {
2927
+ const stage = this._stageNames[i];
2928
+ const current = this.queue(stage);
2929
+ const next = i + 1 < this._stageNames.length ? this.queue(this._stageNames[i + 1]) : null;
2930
+ const pump = node(
2931
+ [current.pending],
2932
+ () => {
2933
+ let moved = 0;
2934
+ while (moved < maxPerPump) {
2935
+ const claim = current.claim(1);
2936
+ if (claim.length === 0) break;
2937
+ const job = claim[0];
2938
+ if (!job) break;
2939
+ if (next) {
2940
+ next.enqueue(job.payload, {
2941
+ metadata: {
2942
+ ...job.metadata,
2943
+ job_flow_from: stage
2944
+ }
2945
+ });
2946
+ } else {
2947
+ this._completed.append(job);
2948
+ }
2949
+ current.ack(job.id);
2950
+ moved += 1;
2951
+ }
2952
+ },
2953
+ {
2954
+ name: `pump_${stage}`,
2955
+ describeKind: "effect",
2956
+ meta: messagingMeta("job_flow_pump")
2957
+ }
2958
+ );
2959
+ this.add(`pump_${stage}`, pump);
2960
+ this.connect(`${stage}::pending`, `pump_${stage}`);
2961
+ this._keepaliveDisposers.push(keepalive2(pump));
2962
+ }
2963
+ }
2964
+ destroy() {
2965
+ for (const dispose of this._keepaliveDisposers) dispose();
2966
+ this._keepaliveDisposers.length = 0;
2967
+ super.destroy();
2968
+ }
2969
+ stages() {
2970
+ return this._stageNames;
2971
+ }
2972
+ queue(stage) {
2973
+ const q = this._queues.get(stage);
2974
+ if (!q) throw new Error(`jobFlow("${this.name}"): unknown stage "${stage}"`);
2975
+ return q;
2976
+ }
2977
+ enqueue(payload, opts = {}) {
2978
+ return this.queue(this._stageNames[0]).enqueue(payload, opts);
2979
+ }
2980
+ retainedCompleted() {
2981
+ const snapshot = this.completed.get();
2982
+ return snapshot.value.entries;
2983
+ }
2984
+ };
2985
+ var TopicBridgeGraph = class extends Graph {
2986
+ _sourceSub;
2987
+ _target;
2988
+ _keepaliveDisposers = [];
2989
+ bridgedCount;
2990
+ constructor(name, sourceTopic, targetTopic, opts = {}) {
2991
+ super(name, opts.graph);
2992
+ this._sourceSub = subscription(`${name}-subscription`, sourceTopic, {
2993
+ cursor: opts.cursor
2994
+ });
2995
+ this._target = targetTopic;
2996
+ this.mount("subscription", this._sourceSub);
2997
+ this.bridgedCount = state(0, {
2998
+ name: "bridgedCount",
2999
+ describeKind: "state",
3000
+ meta: messagingMeta("topic_bridge_count")
3001
+ });
3002
+ this.add("bridgedCount", this.bridgedCount);
3003
+ const maxPerPump = Math.max(
3004
+ 1,
3005
+ requireNonNegativeInt(opts.maxPerPump ?? DEFAULT_MAX_PER_PUMP, "topic bridge maxPerPump")
3006
+ );
3007
+ const mapValue = opts.map ?? ((value) => value);
3008
+ const pump = node(
3009
+ [this._sourceSub.available],
3010
+ () => {
3011
+ const available = this._sourceSub.pull(maxPerPump, { ack: true });
3012
+ if (available.length === 0) return;
3013
+ let bridged = 0;
3014
+ for (const value of available) {
3015
+ const mapped = mapValue(value);
3016
+ if (mapped === void 0) continue;
3017
+ this._target.publish(mapped);
3018
+ bridged += 1;
3019
+ }
3020
+ if (bridged > 0) {
3021
+ const current = this.bridgedCount.get();
3022
+ this.bridgedCount.down([[DATA, current + bridged]]);
3023
+ }
3024
+ },
3025
+ {
3026
+ name: "pump",
3027
+ describeKind: "effect",
3028
+ meta: messagingMeta("topic_bridge_pump")
3029
+ }
3030
+ );
3031
+ this.add("pump", pump);
3032
+ this.connect("subscription::available", "pump");
3033
+ this._keepaliveDisposers.push(keepalive2(pump));
3034
+ }
3035
+ destroy() {
3036
+ for (const dispose of this._keepaliveDisposers) dispose();
3037
+ this._keepaliveDisposers.length = 0;
3038
+ super.destroy();
3039
+ }
3040
+ };
3041
+ function topic(name, opts) {
3042
+ return new TopicGraph(name, opts);
3043
+ }
3044
+ function subscription(name, topicGraph, opts) {
3045
+ return new SubscriptionGraph(name, topicGraph, opts);
3046
+ }
3047
+ function jobQueue(name, opts) {
3048
+ return new JobQueueGraph(name, opts);
3049
+ }
3050
+ function jobFlow(name, opts) {
3051
+ return new JobFlowGraph(name, opts);
3052
+ }
3053
+ function topicBridge(name, sourceTopic, targetTopic, opts) {
3054
+ return new TopicBridgeGraph(name, sourceTopic, targetTopic, opts);
3055
+ }
3056
+
3057
+ // src/patterns/orchestration.ts
3058
+ var orchestration_exports = {};
3059
+ __export(orchestration_exports, {
3060
+ approval: () => approval,
3061
+ branch: () => branch,
3062
+ forEach: () => forEach2,
3063
+ gate: () => gate2,
3064
+ join: () => join,
3065
+ loop: () => loop,
3066
+ onFailure: () => onFailure,
3067
+ pipeline: () => pipeline,
3068
+ sensor: () => sensor,
3069
+ subPipeline: () => subPipeline,
3070
+ task: () => task,
3071
+ wait: () => wait
3072
+ });
3073
+ function resolveDep(graph, dep) {
3074
+ if (typeof dep === "string") {
3075
+ return { node: graph.resolve(dep), path: dep };
3076
+ }
3077
+ const path = findRegisteredNodePath(graph, dep);
3078
+ if (!path) {
3079
+ throw new Error(
3080
+ "orchestration dep node must already be registered in the graph so explicit edges can be recorded; pass a string path or register the node first"
3081
+ );
3082
+ }
3083
+ return { node: dep, path };
3084
+ }
3085
+ function findRegisteredNodePath(graph, target) {
3086
+ const described = graph.describe();
3087
+ const metaSegment = `::${GRAPH_META_SEGMENT}::`;
3088
+ for (const path of Object.keys(described.nodes).sort()) {
3089
+ if (path.includes(metaSegment)) continue;
3090
+ try {
3091
+ if (graph.resolve(path) === target) return path;
3092
+ } catch {
3093
+ }
3094
+ }
3095
+ return void 0;
3096
+ }
3097
+ function registerStep(graph, name, step, depPaths) {
3098
+ graph.add(name, step);
3099
+ for (const path of depPaths) {
3100
+ graph.connect(path, name);
3101
+ }
3102
+ }
3103
+ function baseMeta(kind, meta) {
3104
+ return {
3105
+ orchestration: true,
3106
+ orchestration_type: kind,
3107
+ ...meta ?? {}
3108
+ };
3109
+ }
3110
+ function coerceLoopIterations(raw) {
3111
+ const parseString = (value) => {
3112
+ const trimmed = value.trim();
3113
+ if (trimmed.length === 0) return 0;
3114
+ return Number(trimmed);
3115
+ };
3116
+ let parsed;
3117
+ if (typeof raw === "string") {
3118
+ parsed = parseString(raw);
3119
+ } else if (raw === null) {
3120
+ parsed = 0;
3121
+ } else {
3122
+ parsed = Number(raw);
3123
+ }
3124
+ if (!Number.isFinite(parsed)) return 1;
3125
+ return Math.max(0, Math.trunc(parsed));
3126
+ }
3127
+ function pipeline(name, opts) {
3128
+ return new Graph(name, opts);
3129
+ }
3130
+ function task(graph, name, run, opts) {
3131
+ const depRefs = opts?.deps ?? [];
3132
+ const deps = depRefs.map((dep) => resolveDep(graph, dep));
3133
+ const { deps: _deps, ...nodeOpts } = opts ?? {};
3134
+ const step = node(
3135
+ deps.map((d) => d.node),
3136
+ run,
3137
+ {
3138
+ ...nodeOpts,
3139
+ name,
3140
+ describeKind: "derived",
3141
+ meta: baseMeta("task", opts?.meta)
3142
+ }
3143
+ );
3144
+ registerStep(
3145
+ graph,
3146
+ name,
3147
+ step,
3148
+ deps.flatMap((d) => d.path ? [d.path] : [])
3149
+ );
3150
+ return step;
3151
+ }
3152
+ function branch(graph, name, source, predicate, opts) {
3153
+ const src = resolveDep(graph, source);
3154
+ const step = node(
3155
+ [src.node],
3156
+ ([value]) => ({
3157
+ branch: predicate(value) ? "then" : "else",
3158
+ value
3159
+ }),
3160
+ {
3161
+ ...opts,
3162
+ name,
3163
+ describeKind: "derived",
3164
+ meta: baseMeta("branch", opts?.meta)
3165
+ }
3166
+ );
3167
+ registerStep(graph, name, step, src.path ? [src.path] : []);
3168
+ return step;
3169
+ }
3170
+ function gate2(graph, name, source, control, opts) {
3171
+ const src = resolveDep(graph, source);
3172
+ const ctrl = resolveDep(graph, control);
3173
+ const step = node(
3174
+ [src.node, ctrl.node],
3175
+ (_deps, actions) => {
3176
+ const opened = ctrl.node.get();
3177
+ if (!opened) {
3178
+ actions.down([[RESOLVED]]);
3179
+ return void 0;
3180
+ }
3181
+ return src.node.get();
3182
+ },
3183
+ {
3184
+ ...opts,
3185
+ name,
3186
+ describeKind: "operator",
3187
+ meta: baseMeta("gate", opts?.meta)
3188
+ }
3189
+ );
3190
+ registerStep(
3191
+ graph,
3192
+ name,
3193
+ step,
3194
+ [src.path, ctrl.path].filter((v) => typeof v === "string")
3195
+ );
3196
+ return step;
3197
+ }
3198
+ function approval(graph, name, source, approver, opts) {
3199
+ const src = resolveDep(graph, source);
3200
+ const ctrl = resolveDep(graph, approver);
3201
+ const isApproved = opts?.isApproved ?? ((value) => Boolean(value));
3202
+ const step = node(
3203
+ [src.node, ctrl.node],
3204
+ (_deps, actions) => {
3205
+ if (!isApproved(ctrl.node.get())) {
3206
+ actions.down([[RESOLVED]]);
3207
+ return void 0;
3208
+ }
3209
+ return src.node.get();
3210
+ },
3211
+ {
3212
+ ...opts,
3213
+ name,
3214
+ describeKind: "operator",
3215
+ meta: baseMeta("approval", opts?.meta)
3216
+ }
3217
+ );
3218
+ registerStep(
3219
+ graph,
3220
+ name,
3221
+ step,
3222
+ [src.path, ctrl.path].filter((v) => typeof v === "string")
3223
+ );
3224
+ return step;
3225
+ }
3226
+ function forEach2(graph, name, source, run, opts) {
3227
+ const src = resolveDep(graph, source);
3228
+ let terminated = false;
3229
+ const step = node([src.node], () => void 0, {
3230
+ ...opts,
3231
+ name,
3232
+ describeKind: "effect",
3233
+ completeWhenDepsComplete: false,
3234
+ meta: baseMeta("forEach", opts?.meta),
3235
+ onMessage(msg, depIndex, actions) {
3236
+ if (terminated) return true;
3237
+ if (depIndex !== 0) {
3238
+ actions.down([msg]);
3239
+ if (msg[0] === COMPLETE || msg[0] === ERROR) terminated = true;
3240
+ return true;
3241
+ }
3242
+ if (msg[0] === DATA) {
3243
+ try {
3244
+ run(msg[1], actions);
3245
+ actions.down([msg]);
3246
+ } catch (err) {
3247
+ terminated = true;
3248
+ actions.down([[ERROR, err]]);
3249
+ }
3250
+ return true;
3251
+ }
3252
+ actions.down([msg]);
3253
+ if (msg[0] === COMPLETE || msg[0] === ERROR) terminated = true;
3254
+ return true;
3255
+ }
3256
+ });
3257
+ registerStep(graph, name, step, src.path ? [src.path] : []);
3258
+ return step;
3259
+ }
3260
+ function join(graph, name, deps, opts) {
3261
+ const resolved = deps.map((dep) => resolveDep(graph, dep));
3262
+ const step = node(
3263
+ resolved.map((d) => d.node),
3264
+ (values) => values,
3265
+ {
3266
+ ...opts,
3267
+ name,
3268
+ describeKind: "derived",
3269
+ meta: baseMeta("join", opts?.meta)
3270
+ }
3271
+ );
3272
+ registerStep(
3273
+ graph,
3274
+ name,
3275
+ step,
3276
+ resolved.flatMap((d) => d.path ? [d.path] : [])
3277
+ );
3278
+ return step;
3279
+ }
3280
+ function loop(graph, name, source, iterate, opts) {
3281
+ const src = resolveDep(graph, source);
3282
+ const iterRef = opts?.iterations;
3283
+ const iterDep = typeof iterRef === "number" || iterRef === void 0 ? void 0 : resolveDep(graph, iterRef);
3284
+ const staticIterations = typeof iterRef === "number" ? iterRef : void 0;
3285
+ const step = node(
3286
+ iterDep ? [src.node, iterDep.node] : [src.node],
3287
+ (_deps, actions) => {
3288
+ let current = src.node.get();
3289
+ const rawCount = staticIterations ?? iterDep?.node.get() ?? 1;
3290
+ const count = coerceLoopIterations(rawCount);
3291
+ for (let i = 0; i < count; i += 1) {
3292
+ current = iterate(current, i, actions);
3293
+ }
3294
+ return current;
3295
+ },
3296
+ {
3297
+ ...opts,
3298
+ name,
3299
+ describeKind: "derived",
3300
+ meta: baseMeta("loop", opts?.meta)
3301
+ }
3302
+ );
3303
+ registerStep(
3304
+ graph,
3305
+ name,
3306
+ step,
3307
+ [src.path, iterDep?.path].filter((v) => typeof v === "string")
3308
+ );
3309
+ return step;
3310
+ }
3311
+ function subPipeline(graph, name, childOrBuild, opts) {
3312
+ const child = childOrBuild instanceof Graph ? childOrBuild : pipeline(name, opts);
3313
+ if (typeof childOrBuild === "function") {
3314
+ childOrBuild(child);
3315
+ }
3316
+ graph.mount(name, child);
3317
+ return child;
3318
+ }
3319
+ function sensor(graph, name, initial, opts) {
3320
+ const source = node([], () => void 0, {
3321
+ ...opts,
3322
+ name,
3323
+ initial,
3324
+ describeKind: "producer",
3325
+ meta: baseMeta("sensor", opts?.meta)
3326
+ });
3327
+ registerStep(graph, name, source, []);
3328
+ return {
3329
+ node: source,
3330
+ push(value) {
3331
+ source.down([[DATA, value]]);
3332
+ },
3333
+ error(err) {
3334
+ source.down([[ERROR, err]]);
3335
+ },
3336
+ complete() {
3337
+ source.down([[COMPLETE]]);
3338
+ }
3339
+ };
3340
+ }
3341
+ function wait(graph, name, source, ms, opts) {
3342
+ const src = resolveDep(graph, source);
3343
+ const timers = /* @__PURE__ */ new Set();
3344
+ let terminated = false;
3345
+ let completed = false;
3346
+ const step = node(
3347
+ [src.node],
3348
+ () => {
3349
+ for (const id of timers) clearTimeout(id);
3350
+ timers.clear();
3351
+ return () => {
3352
+ for (const id of timers) clearTimeout(id);
3353
+ timers.clear();
3354
+ terminated = true;
3355
+ };
3356
+ },
3357
+ {
3358
+ ...opts,
3359
+ name,
3360
+ initial: src.node.get(),
3361
+ describeKind: "operator",
3362
+ completeWhenDepsComplete: false,
3363
+ meta: baseMeta("wait", opts?.meta),
3364
+ onMessage(msg, depIndex, actions) {
3365
+ if (terminated) return true;
3366
+ if (depIndex !== 0) {
3367
+ actions.down([msg]);
3368
+ if (msg[0] === COMPLETE || msg[0] === ERROR) terminated = true;
3369
+ return true;
3370
+ }
3371
+ if (msg[0] === DATA) {
3372
+ const id = setTimeout(() => {
3373
+ timers.delete(id);
3374
+ actions.down([msg]);
3375
+ if (completed && timers.size === 0) {
3376
+ actions.down([[COMPLETE]]);
3377
+ }
3378
+ }, ms);
3379
+ timers.add(id);
3380
+ return true;
3381
+ }
3382
+ if (msg[0] === COMPLETE) {
3383
+ terminated = true;
3384
+ completed = true;
3385
+ if (timers.size === 0) {
3386
+ actions.down([[COMPLETE]]);
3387
+ }
3388
+ return true;
3389
+ }
3390
+ if (msg[0] === ERROR) {
3391
+ terminated = true;
3392
+ for (const id of timers) clearTimeout(id);
3393
+ timers.clear();
3394
+ actions.down([msg]);
3395
+ return true;
3396
+ }
3397
+ actions.down([msg]);
3398
+ return true;
3399
+ }
3400
+ }
3401
+ );
3402
+ registerStep(graph, name, step, src.path ? [src.path] : []);
3403
+ return step;
3404
+ }
3405
+ function onFailure(graph, name, source, recover, opts) {
3406
+ const src = resolveDep(graph, source);
3407
+ let terminated = false;
3408
+ const step = node([src.node], () => void 0, {
3409
+ ...opts,
3410
+ name,
3411
+ describeKind: "operator",
3412
+ completeWhenDepsComplete: false,
3413
+ meta: baseMeta("onFailure", opts?.meta),
3414
+ onMessage(msg, _depIndex, actions) {
3415
+ if (terminated) return true;
3416
+ if (msg[0] === ERROR) {
3417
+ try {
3418
+ actions.emit(recover(msg[1], actions));
3419
+ } catch (err) {
3420
+ terminated = true;
3421
+ actions.down([[ERROR, err]]);
3422
+ }
3423
+ return true;
3424
+ }
3425
+ actions.down([msg]);
3426
+ if (msg[0] === COMPLETE) terminated = true;
3427
+ return true;
3428
+ }
3429
+ });
3430
+ registerStep(graph, name, step, src.path ? [src.path] : []);
3431
+ return step;
3432
+ }
3433
+
3434
+ // src/index.ts
3435
+ var version = "0.0.0";
3436
+ export {
3437
+ COMPLETE,
3438
+ CircuitOpenError,
3439
+ DATA,
3440
+ DEFAULT_ACTOR,
3441
+ DIRTY,
3442
+ DictCheckpointAdapter,
3443
+ DynamicNodeImpl,
3444
+ ERROR,
3445
+ FileCheckpointAdapter,
3446
+ GRAPH_META_SEGMENT,
3447
+ Graph,
3448
+ GuardDenied,
3449
+ INVALIDATE,
3450
+ JsonCodec,
3451
+ MemoryCheckpointAdapter,
3452
+ NS_PER_MS,
3453
+ NS_PER_SEC,
3454
+ PAUSE,
3455
+ RESOLVED,
3456
+ RESUME,
3457
+ SqliteCheckpointAdapter,
3458
+ TEARDOWN,
3459
+ accessHintForGuard,
3460
+ advanceVersion,
3461
+ ai_exports as ai,
3462
+ audit,
3463
+ batch,
3464
+ buffer,
3465
+ bufferCount,
3466
+ bufferTime,
3467
+ cached,
3468
+ catchError,
3469
+ checkpointNodeValue,
3470
+ circuitBreaker,
3471
+ combine,
3472
+ combineLatest,
3473
+ compat_exports as compat,
3474
+ concat,
3475
+ concatMap,
3476
+ constant,
3477
+ core_exports as core,
3478
+ cqrs_exports as cqrs,
3479
+ createDagCborCodec,
3480
+ createDagCborZstdCodec,
3481
+ createTransport,
3482
+ createVersioning,
3483
+ createWatermarkController,
3484
+ debounce,
3485
+ debounceTime,
3486
+ decorrelatedJitter,
3487
+ defaultHash,
3488
+ delay,
3489
+ derived,
3490
+ describeNode,
3491
+ deserializeError,
3492
+ distill,
3493
+ distinctUntilChanged,
3494
+ dynamicNode,
3495
+ effect,
3496
+ elementAt,
3497
+ emitWithBatch,
3498
+ empty,
3499
+ escapeRegexChar,
3500
+ exhaustMap,
3501
+ exponential,
3502
+ extra_exports as extra,
3503
+ fibonacci,
3504
+ filter,
3505
+ find,
3506
+ first,
3507
+ firstValueFrom,
3508
+ flatMap,
3509
+ forEach,
3510
+ fromAny,
3511
+ fromAsyncIter,
3512
+ fromCSV,
3513
+ fromClickHouseWatch,
3514
+ fromCron,
3515
+ fromEvent,
3516
+ fromFSWatch,
3517
+ fromGitHook,
3518
+ fromHTTP,
3519
+ fromIDBRequest,
3520
+ fromIDBTransaction,
3521
+ fromIter,
3522
+ fromKafka,
3523
+ fromMCP,
3524
+ fromNDJSON,
3525
+ fromOTel,
3526
+ fromPrometheus,
3527
+ fromPromise,
3528
+ fromRedisStream,
3529
+ fromStatsD,
3530
+ fromSyslog,
3531
+ fromTimer,
3532
+ fromWebSocket,
3533
+ fromWebhook,
3534
+ gate,
3535
+ globToRegExp,
3536
+ graph_exports as graph,
3537
+ interval,
3538
+ isBatching,
3539
+ isKnownMessageType,
3540
+ isPhase2Message,
3541
+ isTerminalMessage,
3542
+ isV1,
3543
+ jotai_exports as jotai,
3544
+ knownMessageTypes,
3545
+ last,
3546
+ reactive_layout_exports as layout,
3547
+ linear,
3548
+ logSlice,
3549
+ map,
3550
+ matchesAnyPattern,
3551
+ matchesCron,
3552
+ memory_exports as memory,
3553
+ merge,
3554
+ mergeMap,
3555
+ messageTier,
3556
+ messaging_exports as messaging,
3557
+ metaSnapshot,
3558
+ monotonicNs,
3559
+ nameToSignal,
3560
+ nanostores_exports as nanostores,
3561
+ negotiateCodec,
3562
+ nestjs_exports as nestjs,
3563
+ never,
3564
+ node,
3565
+ normalizeActor,
3566
+ observeGraph$,
3567
+ observeNode$,
3568
+ of,
3569
+ orchestration_exports as orchestration,
3570
+ pairwise,
3571
+ parseCron,
3572
+ parsePrometheusText,
3573
+ parseStatsD,
3574
+ parseSyslog,
3575
+ partitionForBatch,
3576
+ patterns_exports as patterns,
3577
+ pausable,
3578
+ pipe,
3579
+ policy,
3580
+ policyFromRules,
3581
+ producer,
3582
+ propagatesToMeta,
3583
+ pubsub,
3584
+ race,
3585
+ rateLimiter,
3586
+ reachable,
3587
+ react_exports as react,
3588
+ reactiveIndex,
3589
+ reactiveList,
3590
+ reactiveLog,
3591
+ reactiveMap,
3592
+ reduce,
3593
+ repeat,
3594
+ replay,
3595
+ replayWAL,
3596
+ rescue,
3597
+ resolveBackoffPreset,
3598
+ restoreGraphCheckpoint,
3599
+ restoreGraphCheckpointIndexedDb,
3600
+ retry,
3601
+ sample,
3602
+ saveGraphCheckpoint,
3603
+ saveGraphCheckpointIndexedDb,
3604
+ scan,
3605
+ serializeError,
3606
+ share,
3607
+ shareReplay,
3608
+ signalToName,
3609
+ signals_exports as signals,
3610
+ skip,
3611
+ solid_exports as solid,
3612
+ startWith,
3613
+ state,
3614
+ svelte_exports as svelte,
3615
+ switchMap,
3616
+ take,
3617
+ takeUntil,
3618
+ takeWhile,
3619
+ tap,
3620
+ throttle,
3621
+ throttleTime,
3622
+ throwError,
3623
+ timeout,
3624
+ toArray,
3625
+ toKafka,
3626
+ toMessages$,
3627
+ toObservable,
3628
+ toRedisStream,
3629
+ toSSE,
3630
+ toWebSocket,
3631
+ tokenBucket,
3632
+ tokenTracker,
3633
+ verifiable,
3634
+ version,
3635
+ vue_exports as vue,
3636
+ wallClockNs,
3637
+ window,
3638
+ windowCount,
3639
+ windowTime,
3640
+ withBreaker,
3641
+ withLatestFrom,
3642
+ withMaxAttempts,
3643
+ withStatus,
3644
+ workerBridge,
3645
+ workerSelf,
3646
+ zip,
3647
+ zustand_exports as zustand
3648
+ };
3649
+ //# sourceMappingURL=index.js.map