@graphrefly/graphrefly 0.7.0 → 0.9.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.
- package/dist/{chunk-L4J2K2RT.js → chunk-A2AJJOSJ.js} +3 -3
- package/dist/{chunk-ISGMZ2T3.js → chunk-E7OH6ZAZ.js} +3 -3
- package/dist/{chunk-47YJEZUJ.js → chunk-LR2CLSEF.js} +2 -2
- package/dist/{chunk-3EVXOI5C.js → chunk-QTZSBQGJ.js} +35 -21
- package/dist/chunk-QTZSBQGJ.js.map +1 -0
- package/dist/{chunk-ONLYF6GA.js → chunk-TZLX4KIT.js} +3 -3
- package/dist/{chunk-FGLZ5QID.js → chunk-UCW3VWMN.js} +4 -4
- package/dist/{chunk-BLCXEMAD.js → chunk-WYI7YW54.js} +16 -8
- package/dist/chunk-WYI7YW54.js.map +1 -0
- package/dist/{chunk-OSR3G3DP.js → chunk-XCZPGOVP.js} +3 -3
- package/dist/{chunk-PEBORXRA.js → chunk-YWTP2XRJ.js} +2 -2
- package/dist/compat/nestjs/index.cjs +47 -25
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +3 -3
- package/dist/compat/nestjs/index.d.ts +3 -3
- package/dist/compat/nestjs/index.js +7 -7
- package/dist/core/index.cjs +34 -20
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +3 -3
- package/dist/extra/index.cjs +34 -20
- package/dist/extra/index.cjs.map +1 -1
- package/dist/extra/index.d.cts +3 -3
- package/dist/extra/index.d.ts +3 -3
- package/dist/extra/index.js +3 -3
- package/dist/graph/index.cjs +47 -25
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +2 -2
- package/dist/graph/index.d.ts +2 -2
- package/dist/graph/index.js +4 -4
- package/dist/{graph-B3BoJjcb.d.cts → graph-DqTICAY2.d.cts} +11 -5
- package/dist/{graph-CmiUuhaN.d.ts → graph-X9uwnD_z.d.ts} +11 -5
- package/dist/{index-D0cx-Yht.d.cts → index-3U0WxdD-.d.cts} +1 -1
- package/dist/{index-D1hgSTzr.d.cts → index-BP1t_38S.d.cts} +2 -2
- package/dist/{index-CsUq2rrK.d.ts → index-BPCeYDS4.d.ts} +1 -1
- package/dist/{index-BrgtEG-C.d.ts → index-BVG5pjin.d.ts} +3 -1
- package/dist/{index-D8NIq6om.d.cts → index-BYEgosAX.d.cts} +3 -1
- package/dist/{index-BsuKSs4L.d.cts → index-BYa2YMat.d.cts} +2 -2
- package/dist/{index-DFFNKYig.d.ts → index-DLO8wnYU.d.ts} +2 -2
- package/dist/{index-Bf2X1YSI.d.ts → index-DMv1Etbi.d.ts} +1 -1
- package/dist/{index-Bl7hJcc3.d.cts → index-DbwgQ4Cw.d.cts} +1 -1
- package/dist/{index-Pm68AYPh.d.ts → index-a5gHmH5b.d.ts} +2 -2
- package/dist/index.cjs +322 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +200 -25
- package/dist/index.d.ts +200 -25
- package/dist/index.js +291 -18
- package/dist/index.js.map +1 -1
- package/dist/patterns/reactive-layout/index.cjs +47 -25
- package/dist/patterns/reactive-layout/index.cjs.map +1 -1
- package/dist/patterns/reactive-layout/index.d.cts +2 -2
- package/dist/patterns/reactive-layout/index.d.ts +2 -2
- package/dist/patterns/reactive-layout/index.js +4 -4
- package/dist/{reactive-log-CAXzJ7hw.d.cts → reactive-log-BfX6bOSZ.d.cts} +1 -1
- package/dist/{reactive-log-DwNhOe0g.d.ts → reactive-log-RhgIog2Z.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-3EVXOI5C.js.map +0 -1
- package/dist/chunk-BLCXEMAD.js.map +0 -1
- /package/dist/{chunk-L4J2K2RT.js.map → chunk-A2AJJOSJ.js.map} +0 -0
- /package/dist/{chunk-ISGMZ2T3.js.map → chunk-E7OH6ZAZ.js.map} +0 -0
- /package/dist/{chunk-47YJEZUJ.js.map → chunk-LR2CLSEF.js.map} +0 -0
- /package/dist/{chunk-ONLYF6GA.js.map → chunk-TZLX4KIT.js.map} +0 -0
- /package/dist/{chunk-FGLZ5QID.js.map → chunk-UCW3VWMN.js.map} +0 -0
- /package/dist/{chunk-OSR3G3DP.js.map → chunk-XCZPGOVP.js.map} +0 -0
- /package/dist/{chunk-PEBORXRA.js.map → chunk-YWTP2XRJ.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -237,6 +237,7 @@ __export(index_exports, {
|
|
|
237
237
|
reactiveLog: () => reactiveLog,
|
|
238
238
|
reactiveMap: () => reactiveMap,
|
|
239
239
|
reduce: () => reduce,
|
|
240
|
+
reduction: () => reduction_exports,
|
|
240
241
|
repeat: () => repeat,
|
|
241
242
|
replay: () => replay,
|
|
242
243
|
replayWAL: () => replayWAL,
|
|
@@ -726,6 +727,7 @@ function isV1(info) {
|
|
|
726
727
|
}
|
|
727
728
|
|
|
728
729
|
// src/core/node.ts
|
|
730
|
+
var NO_VALUE = /* @__PURE__ */ Symbol.for("graphrefly/NO_VALUE");
|
|
729
731
|
function createIntBitSet() {
|
|
730
732
|
let bits = 0;
|
|
731
733
|
return {
|
|
@@ -826,7 +828,6 @@ var NodeImpl = class {
|
|
|
826
828
|
_producerStarted = false;
|
|
827
829
|
_connecting = false;
|
|
828
830
|
_manualEmitUsed = false;
|
|
829
|
-
_hasEmittedData = false;
|
|
830
831
|
_sinkCount = 0;
|
|
831
832
|
_singleDepSinkCount = 0;
|
|
832
833
|
// --- Object/collection state ---
|
|
@@ -856,10 +857,10 @@ var NodeImpl = class {
|
|
|
856
857
|
this._hasDeps = deps.length > 0;
|
|
857
858
|
this._autoComplete = opts.completeWhenDepsComplete ?? true;
|
|
858
859
|
this._isSingleDep = deps.length === 1 && fn != null;
|
|
859
|
-
this._cached = opts.initial;
|
|
860
|
+
this._cached = "initial" in opts ? opts.initial : NO_VALUE;
|
|
860
861
|
this._status = this._hasDeps ? "disconnected" : "settled";
|
|
861
862
|
this._hashFn = opts.versioningHash ?? defaultHash;
|
|
862
|
-
this._versioning = opts.versioning != null ? createVersioning(opts.versioning, this._cached, {
|
|
863
|
+
this._versioning = opts.versioning != null ? createVersioning(opts.versioning, this._cached === NO_VALUE ? void 0 : this._cached, {
|
|
863
864
|
id: opts.versioningId,
|
|
864
865
|
hash: this._hashFn
|
|
865
866
|
}) : void 0;
|
|
@@ -943,10 +944,14 @@ var NodeImpl = class {
|
|
|
943
944
|
_applyVersioning(level, opts) {
|
|
944
945
|
if (this._versioning != null) return;
|
|
945
946
|
this._hashFn = opts?.hash ?? this._hashFn;
|
|
946
|
-
this._versioning = createVersioning(
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
947
|
+
this._versioning = createVersioning(
|
|
948
|
+
level,
|
|
949
|
+
this._cached === NO_VALUE ? void 0 : this._cached,
|
|
950
|
+
{
|
|
951
|
+
id: opts?.id,
|
|
952
|
+
hash: this._hashFn
|
|
953
|
+
}
|
|
954
|
+
);
|
|
950
955
|
}
|
|
951
956
|
hasGuard() {
|
|
952
957
|
return this._guard != null;
|
|
@@ -956,7 +961,7 @@ var NodeImpl = class {
|
|
|
956
961
|
return this._guard(normalizeActor(actor), "observe");
|
|
957
962
|
}
|
|
958
963
|
get() {
|
|
959
|
-
return this._cached;
|
|
964
|
+
return this._cached === NO_VALUE ? void 0 : this._cached;
|
|
960
965
|
}
|
|
961
966
|
down(messages, options) {
|
|
962
967
|
if (messages.length === 0) return;
|
|
@@ -1013,6 +1018,7 @@ var NodeImpl = class {
|
|
|
1013
1018
|
}
|
|
1014
1019
|
if (this._terminal && this._opts.resubscribable) {
|
|
1015
1020
|
this._terminal = false;
|
|
1021
|
+
this._cached = NO_VALUE;
|
|
1016
1022
|
this._status = this._hasDeps ? "disconnected" : "settled";
|
|
1017
1023
|
this._opts.onResubscribe?.();
|
|
1018
1024
|
}
|
|
@@ -1112,8 +1118,7 @@ var NodeImpl = class {
|
|
|
1112
1118
|
const cleanupFn = this._cleanup;
|
|
1113
1119
|
this._cleanup = void 0;
|
|
1114
1120
|
cleanupFn?.();
|
|
1115
|
-
this._cached =
|
|
1116
|
-
this._hasEmittedData = false;
|
|
1121
|
+
this._cached = NO_VALUE;
|
|
1117
1122
|
this._lastDepValues = void 0;
|
|
1118
1123
|
}
|
|
1119
1124
|
this._status = statusAfterMessage(this._status, m);
|
|
@@ -1122,8 +1127,7 @@ var NodeImpl = class {
|
|
|
1122
1127
|
}
|
|
1123
1128
|
if (t === TEARDOWN) {
|
|
1124
1129
|
if (this._opts.resetOnTeardown) {
|
|
1125
|
-
this._cached =
|
|
1126
|
-
this._hasEmittedData = false;
|
|
1130
|
+
this._cached = NO_VALUE;
|
|
1127
1131
|
}
|
|
1128
1132
|
const teardownCleanup = this._cleanup;
|
|
1129
1133
|
this._cleanup = void 0;
|
|
@@ -1156,14 +1160,13 @@ var NodeImpl = class {
|
|
|
1156
1160
|
const wasDirty = this._status === "dirty";
|
|
1157
1161
|
let unchanged;
|
|
1158
1162
|
try {
|
|
1159
|
-
unchanged = this.
|
|
1163
|
+
unchanged = this._cached !== NO_VALUE && this._equals(this._cached, value);
|
|
1160
1164
|
} catch (eqErr) {
|
|
1161
1165
|
const eqMsg = eqErr instanceof Error ? eqErr.message : String(eqErr);
|
|
1162
1166
|
const wrapped = new Error(`Node "${this.name}": equals threw: ${eqMsg}`, { cause: eqErr });
|
|
1163
1167
|
this._downInternal([[ERROR, wrapped]]);
|
|
1164
1168
|
return;
|
|
1165
1169
|
}
|
|
1166
|
-
this._hasEmittedData = true;
|
|
1167
1170
|
if (unchanged) {
|
|
1168
1171
|
this._downInternal(wasDirty ? [[RESOLVED]] : [[DIRTY], [RESOLVED]]);
|
|
1169
1172
|
return;
|
|
@@ -1387,7 +1390,7 @@ var DynamicNodeImpl = class {
|
|
|
1387
1390
|
_actions;
|
|
1388
1391
|
_boundEmitToSinks;
|
|
1389
1392
|
// Mutable state
|
|
1390
|
-
_cached;
|
|
1393
|
+
_cached = NO_VALUE;
|
|
1391
1394
|
_status = "disconnected";
|
|
1392
1395
|
_terminal = false;
|
|
1393
1396
|
_connected = false;
|
|
@@ -1481,7 +1484,7 @@ var DynamicNodeImpl = class {
|
|
|
1481
1484
|
return this._guard(normalizeActor(actor), "observe");
|
|
1482
1485
|
}
|
|
1483
1486
|
get() {
|
|
1484
|
-
return this._cached;
|
|
1487
|
+
return this._cached === NO_VALUE ? void 0 : this._cached;
|
|
1485
1488
|
}
|
|
1486
1489
|
down(messages, options) {
|
|
1487
1490
|
if (messages.length === 0) return;
|
|
@@ -1539,6 +1542,7 @@ var DynamicNodeImpl = class {
|
|
|
1539
1542
|
}
|
|
1540
1543
|
if (this._terminal && this._resubscribable) {
|
|
1541
1544
|
this._terminal = false;
|
|
1545
|
+
this._cached = NO_VALUE;
|
|
1542
1546
|
this._status = "disconnected";
|
|
1543
1547
|
this._onResubscribe?.();
|
|
1544
1548
|
}
|
|
@@ -1616,10 +1620,13 @@ var DynamicNodeImpl = class {
|
|
|
1616
1620
|
const t = m[0];
|
|
1617
1621
|
if (t === DATA) this._cached = m[1];
|
|
1618
1622
|
if (t === INVALIDATE) {
|
|
1619
|
-
this._cached =
|
|
1623
|
+
this._cached = NO_VALUE;
|
|
1624
|
+
this._status = "dirty";
|
|
1620
1625
|
}
|
|
1621
|
-
if (t === DATA
|
|
1626
|
+
if (t === DATA) {
|
|
1622
1627
|
this._status = "settled";
|
|
1628
|
+
} else if (t === RESOLVED) {
|
|
1629
|
+
this._status = "resolved";
|
|
1623
1630
|
} else if (t === DIRTY) {
|
|
1624
1631
|
this._status = "dirty";
|
|
1625
1632
|
} else if (t === COMPLETE) {
|
|
@@ -1630,7 +1637,7 @@ var DynamicNodeImpl = class {
|
|
|
1630
1637
|
this._terminal = true;
|
|
1631
1638
|
}
|
|
1632
1639
|
if (t === TEARDOWN) {
|
|
1633
|
-
if (this._resetOnTeardown) this._cached =
|
|
1640
|
+
if (this._resetOnTeardown) this._cached = NO_VALUE;
|
|
1634
1641
|
try {
|
|
1635
1642
|
this._propagateToMeta(t);
|
|
1636
1643
|
} finally {
|
|
@@ -1653,7 +1660,15 @@ var DynamicNodeImpl = class {
|
|
|
1653
1660
|
}
|
|
1654
1661
|
_emitAutoValue(value) {
|
|
1655
1662
|
const wasDirty = this._status === "dirty";
|
|
1656
|
-
|
|
1663
|
+
let unchanged;
|
|
1664
|
+
try {
|
|
1665
|
+
unchanged = this._cached !== NO_VALUE && this._equals(this._cached, value);
|
|
1666
|
+
} catch (eqErr) {
|
|
1667
|
+
const eqMsg = eqErr instanceof Error ? eqErr.message : String(eqErr);
|
|
1668
|
+
const wrapped = new Error(`Node "${this.name}": equals threw: ${eqMsg}`, { cause: eqErr });
|
|
1669
|
+
this._downInternal([[ERROR, wrapped]]);
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1657
1672
|
if (unchanged) {
|
|
1658
1673
|
this._downInternal(wasDirty ? [[RESOLVED]] : [[DIRTY], [RESOLVED]]);
|
|
1659
1674
|
return;
|
|
@@ -5174,20 +5189,28 @@ var Graph = class _Graph {
|
|
|
5174
5189
|
return g;
|
|
5175
5190
|
}
|
|
5176
5191
|
/**
|
|
5177
|
-
* Plain snapshot with **recursively sorted object keys** for deterministic serialization (§3.8).
|
|
5192
|
+
* Plain snapshot object with **recursively sorted object keys** for deterministic serialization (§3.8).
|
|
5178
5193
|
*
|
|
5179
5194
|
* @remarks
|
|
5180
|
-
* ECMAScript `JSON.stringify(graph)` invokes this method; it must return a plain object, not an
|
|
5181
|
-
* already-stringified JSON string (otherwise the graph would be double-encoded).
|
|
5182
5195
|
* For a single UTF-8 string with a trailing newline (convenient for git), use {@link Graph.toJSONString}.
|
|
5183
5196
|
*
|
|
5184
5197
|
* @returns Same object as {@link Graph.snapshot}.
|
|
5185
5198
|
*/
|
|
5186
|
-
|
|
5199
|
+
toObject() {
|
|
5187
5200
|
return this.snapshot();
|
|
5188
5201
|
}
|
|
5189
5202
|
/**
|
|
5190
|
-
*
|
|
5203
|
+
* ECMAScript `JSON.stringify` hook — delegates to {@link Graph.toObject}.
|
|
5204
|
+
*
|
|
5205
|
+
* @remarks
|
|
5206
|
+
* Must return a plain object (not a string) so `JSON.stringify(graph)` works correctly
|
|
5207
|
+
* without double-encoding.
|
|
5208
|
+
*/
|
|
5209
|
+
toJSON() {
|
|
5210
|
+
return this.toObject();
|
|
5211
|
+
}
|
|
5212
|
+
/**
|
|
5213
|
+
* Deterministic JSON **text**: `JSON.stringify` of {@link Graph.toObject} plus a trailing newline (§3.8).
|
|
5191
5214
|
*
|
|
5192
5215
|
* @returns Stable string suitable for diffs.
|
|
5193
5216
|
*/
|
|
@@ -12842,7 +12865,8 @@ __export(patterns_exports, {
|
|
|
12842
12865
|
layout: () => reactive_layout_exports,
|
|
12843
12866
|
memory: () => memory_exports,
|
|
12844
12867
|
messaging: () => messaging_exports,
|
|
12845
|
-
orchestration: () => orchestration_exports
|
|
12868
|
+
orchestration: () => orchestration_exports,
|
|
12869
|
+
reduction: () => reduction_exports
|
|
12846
12870
|
});
|
|
12847
12871
|
|
|
12848
12872
|
// src/patterns/ai.ts
|
|
@@ -16662,6 +16686,277 @@ function reactiveBlockLayout(opts) {
|
|
|
16662
16686
|
};
|
|
16663
16687
|
}
|
|
16664
16688
|
|
|
16689
|
+
// src/patterns/reduction.ts
|
|
16690
|
+
var reduction_exports = {};
|
|
16691
|
+
__export(reduction_exports, {
|
|
16692
|
+
budgetGate: () => budgetGate,
|
|
16693
|
+
feedback: () => feedback,
|
|
16694
|
+
funnel: () => funnel,
|
|
16695
|
+
scorer: () => scorer,
|
|
16696
|
+
stratify: () => stratify
|
|
16697
|
+
});
|
|
16698
|
+
function baseMeta2(kind, meta) {
|
|
16699
|
+
return {
|
|
16700
|
+
reduction: true,
|
|
16701
|
+
reduction_type: kind,
|
|
16702
|
+
...meta ?? {}
|
|
16703
|
+
};
|
|
16704
|
+
}
|
|
16705
|
+
function stratify(name, source, rules, opts) {
|
|
16706
|
+
const g = new Graph(name, opts);
|
|
16707
|
+
g.add("source", source);
|
|
16708
|
+
const rulesNode = state(rules, {
|
|
16709
|
+
meta: baseMeta2("stratify_rules")
|
|
16710
|
+
});
|
|
16711
|
+
g.add("rules", rulesNode);
|
|
16712
|
+
for (const rule of rules) {
|
|
16713
|
+
_addBranch(g, source, rulesNode, rule);
|
|
16714
|
+
}
|
|
16715
|
+
return g;
|
|
16716
|
+
}
|
|
16717
|
+
function _addBranch(graph, source, rulesNode, rule) {
|
|
16718
|
+
const branchName = `branch/${rule.name}`;
|
|
16719
|
+
let pendingDirty = false;
|
|
16720
|
+
const filterNode = node([source, rulesNode], () => void 0, {
|
|
16721
|
+
describeKind: "operator",
|
|
16722
|
+
meta: baseMeta2("stratify_branch", { branch: rule.name }),
|
|
16723
|
+
onMessage(msg, depIndex, actions) {
|
|
16724
|
+
if (depIndex !== 0) return false;
|
|
16725
|
+
const t = msg[0];
|
|
16726
|
+
if (t === DATA) {
|
|
16727
|
+
const value = msg[1];
|
|
16728
|
+
const currentRules = rulesNode.get();
|
|
16729
|
+
const currentRule = currentRules.find((r) => r.name === rule.name);
|
|
16730
|
+
if (currentRule && currentRule.classify(value)) {
|
|
16731
|
+
pendingDirty = false;
|
|
16732
|
+
actions.emit(value);
|
|
16733
|
+
} else {
|
|
16734
|
+
if (pendingDirty) {
|
|
16735
|
+
pendingDirty = false;
|
|
16736
|
+
actions.down([[DIRTY], [RESOLVED]]);
|
|
16737
|
+
}
|
|
16738
|
+
}
|
|
16739
|
+
return true;
|
|
16740
|
+
}
|
|
16741
|
+
if (t === DIRTY) {
|
|
16742
|
+
pendingDirty = true;
|
|
16743
|
+
return true;
|
|
16744
|
+
}
|
|
16745
|
+
if (t === RESOLVED) {
|
|
16746
|
+
if (pendingDirty) {
|
|
16747
|
+
pendingDirty = false;
|
|
16748
|
+
actions.down([[DIRTY], [RESOLVED]]);
|
|
16749
|
+
} else {
|
|
16750
|
+
actions.down([[RESOLVED]]);
|
|
16751
|
+
}
|
|
16752
|
+
return true;
|
|
16753
|
+
}
|
|
16754
|
+
if (t === COMPLETE || t === ERROR) {
|
|
16755
|
+
pendingDirty = false;
|
|
16756
|
+
actions.down([msg]);
|
|
16757
|
+
return true;
|
|
16758
|
+
}
|
|
16759
|
+
return false;
|
|
16760
|
+
}
|
|
16761
|
+
});
|
|
16762
|
+
graph.add(branchName, filterNode);
|
|
16763
|
+
graph.connect("source", branchName);
|
|
16764
|
+
if (rule.ops) {
|
|
16765
|
+
const transformed = rule.ops(filterNode);
|
|
16766
|
+
const transformedName = `branch/${rule.name}/out`;
|
|
16767
|
+
graph.add(transformedName, transformed);
|
|
16768
|
+
graph.connect(branchName, transformedName);
|
|
16769
|
+
}
|
|
16770
|
+
}
|
|
16771
|
+
function funnel(name, sources, stages, opts) {
|
|
16772
|
+
if (sources.length === 0) throw new RangeError("funnel requires at least one source");
|
|
16773
|
+
if (stages.length === 0) throw new RangeError("funnel requires at least one stage");
|
|
16774
|
+
const g = new Graph(name, opts);
|
|
16775
|
+
const merged = sources.length === 1 ? sources[0] : merge(...sources);
|
|
16776
|
+
g.add("merged", merged);
|
|
16777
|
+
let prevOutputPath = "merged";
|
|
16778
|
+
for (let i = 0; i < stages.length; i++) {
|
|
16779
|
+
const stage = stages[i];
|
|
16780
|
+
const sub = new Graph(stage.name);
|
|
16781
|
+
stage.build(sub);
|
|
16782
|
+
try {
|
|
16783
|
+
sub.resolve("input");
|
|
16784
|
+
} catch {
|
|
16785
|
+
throw new Error(`funnel stage "${stage.name}" must define an "input" node`);
|
|
16786
|
+
}
|
|
16787
|
+
try {
|
|
16788
|
+
sub.resolve("output");
|
|
16789
|
+
} catch {
|
|
16790
|
+
throw new Error(`funnel stage "${stage.name}" must define an "output" node`);
|
|
16791
|
+
}
|
|
16792
|
+
g.mount(stage.name, sub);
|
|
16793
|
+
const prevNode = g.resolve(prevOutputPath);
|
|
16794
|
+
const stageInputPath = `${stage.name}::input`;
|
|
16795
|
+
const stageInput = g.resolve(stageInputPath);
|
|
16796
|
+
prevNode.subscribe((msgs) => {
|
|
16797
|
+
for (const msg of msgs) {
|
|
16798
|
+
const t = msg[0];
|
|
16799
|
+
if (t === DATA) {
|
|
16800
|
+
stageInput.down([[DATA, msg[1]]]);
|
|
16801
|
+
} else if (t === DIRTY) {
|
|
16802
|
+
stageInput.down([[DIRTY]]);
|
|
16803
|
+
} else if (t === RESOLVED) {
|
|
16804
|
+
stageInput.down([[RESOLVED]]);
|
|
16805
|
+
} else if (t === COMPLETE || t === ERROR) {
|
|
16806
|
+
stageInput.down([msg]);
|
|
16807
|
+
}
|
|
16808
|
+
}
|
|
16809
|
+
});
|
|
16810
|
+
prevOutputPath = `${stage.name}::output`;
|
|
16811
|
+
}
|
|
16812
|
+
return g;
|
|
16813
|
+
}
|
|
16814
|
+
function feedback(graph, condition, reentry, opts) {
|
|
16815
|
+
const maxIter = opts?.maxIterations ?? 10;
|
|
16816
|
+
const counterName = `__feedback_${condition}`;
|
|
16817
|
+
const counter = state(0, {
|
|
16818
|
+
meta: baseMeta2("feedback_counter", { maxIterations: maxIter })
|
|
16819
|
+
});
|
|
16820
|
+
graph.add(counterName, counter);
|
|
16821
|
+
const condNode = graph.resolve(condition);
|
|
16822
|
+
const reentryNode = graph.resolve(reentry);
|
|
16823
|
+
condNode.subscribe((msgs) => {
|
|
16824
|
+
for (const msg of msgs) {
|
|
16825
|
+
if (msg[0] === DATA) {
|
|
16826
|
+
const currentCount = counter.get();
|
|
16827
|
+
if (currentCount >= maxIter) continue;
|
|
16828
|
+
const condValue = msg[1];
|
|
16829
|
+
if (condValue == null) continue;
|
|
16830
|
+
counter.down([[DATA, currentCount + 1]]);
|
|
16831
|
+
reentryNode.down([[DATA, condValue]]);
|
|
16832
|
+
}
|
|
16833
|
+
}
|
|
16834
|
+
});
|
|
16835
|
+
return graph;
|
|
16836
|
+
}
|
|
16837
|
+
function budgetGate(source, constraints, opts) {
|
|
16838
|
+
if (constraints.length === 0) throw new RangeError("budgetGate requires at least one constraint");
|
|
16839
|
+
const constraintNodes = constraints.map((c) => c.node);
|
|
16840
|
+
const allDeps = [source, ...constraintNodes];
|
|
16841
|
+
let buffer2 = [];
|
|
16842
|
+
let paused = false;
|
|
16843
|
+
const lockId = /* @__PURE__ */ Symbol("budget-gate");
|
|
16844
|
+
function checkBudget() {
|
|
16845
|
+
return constraints.every((c) => c.check(c.node.get()));
|
|
16846
|
+
}
|
|
16847
|
+
function flushBuffer(actions) {
|
|
16848
|
+
while (buffer2.length > 0 && checkBudget()) {
|
|
16849
|
+
const item = buffer2.shift();
|
|
16850
|
+
actions.emit(item);
|
|
16851
|
+
}
|
|
16852
|
+
}
|
|
16853
|
+
return node(allDeps, () => void 0, {
|
|
16854
|
+
...opts,
|
|
16855
|
+
describeKind: "operator",
|
|
16856
|
+
meta: baseMeta2("budget_gate", opts?.meta),
|
|
16857
|
+
onMessage(msg, depIndex, actions) {
|
|
16858
|
+
const t = msg[0];
|
|
16859
|
+
if (depIndex === 0) {
|
|
16860
|
+
if (t === DATA) {
|
|
16861
|
+
if (checkBudget() && buffer2.length === 0) {
|
|
16862
|
+
actions.emit(msg[1]);
|
|
16863
|
+
} else {
|
|
16864
|
+
buffer2.push(msg[1]);
|
|
16865
|
+
if (!paused) {
|
|
16866
|
+
paused = true;
|
|
16867
|
+
actions.up([[PAUSE, lockId]]);
|
|
16868
|
+
}
|
|
16869
|
+
}
|
|
16870
|
+
return true;
|
|
16871
|
+
}
|
|
16872
|
+
if (t === DIRTY) {
|
|
16873
|
+
actions.down([[DIRTY]]);
|
|
16874
|
+
return true;
|
|
16875
|
+
}
|
|
16876
|
+
if (t === RESOLVED) {
|
|
16877
|
+
if (buffer2.length === 0) {
|
|
16878
|
+
actions.down([[RESOLVED]]);
|
|
16879
|
+
}
|
|
16880
|
+
return true;
|
|
16881
|
+
}
|
|
16882
|
+
if (t === COMPLETE || t === ERROR) {
|
|
16883
|
+
for (const item of buffer2) {
|
|
16884
|
+
actions.emit(item);
|
|
16885
|
+
}
|
|
16886
|
+
buffer2 = [];
|
|
16887
|
+
if (paused) {
|
|
16888
|
+
paused = false;
|
|
16889
|
+
actions.up([[RESUME, lockId]]);
|
|
16890
|
+
}
|
|
16891
|
+
actions.down([msg]);
|
|
16892
|
+
return true;
|
|
16893
|
+
}
|
|
16894
|
+
return false;
|
|
16895
|
+
}
|
|
16896
|
+
if (t === DATA || t === RESOLVED) {
|
|
16897
|
+
if (checkBudget() && buffer2.length > 0) {
|
|
16898
|
+
flushBuffer(actions);
|
|
16899
|
+
if (buffer2.length === 0 && paused) {
|
|
16900
|
+
paused = false;
|
|
16901
|
+
actions.up([[RESUME, lockId]]);
|
|
16902
|
+
}
|
|
16903
|
+
} else if (!checkBudget() && !paused && buffer2.length > 0) {
|
|
16904
|
+
paused = true;
|
|
16905
|
+
actions.up([[PAUSE, lockId]]);
|
|
16906
|
+
}
|
|
16907
|
+
return true;
|
|
16908
|
+
}
|
|
16909
|
+
if (t === DIRTY) {
|
|
16910
|
+
return true;
|
|
16911
|
+
}
|
|
16912
|
+
if (t === ERROR) {
|
|
16913
|
+
actions.down([msg]);
|
|
16914
|
+
return true;
|
|
16915
|
+
}
|
|
16916
|
+
if (t === COMPLETE) {
|
|
16917
|
+
return true;
|
|
16918
|
+
}
|
|
16919
|
+
return false;
|
|
16920
|
+
}
|
|
16921
|
+
});
|
|
16922
|
+
}
|
|
16923
|
+
function scorer(sources, weights, opts) {
|
|
16924
|
+
if (sources.length === 0) throw new RangeError("scorer requires at least one source");
|
|
16925
|
+
if (sources.length !== weights.length) {
|
|
16926
|
+
throw new RangeError("scorer requires the same number of sources and weights");
|
|
16927
|
+
}
|
|
16928
|
+
const allDeps = [...sources, ...weights];
|
|
16929
|
+
const n = sources.length;
|
|
16930
|
+
const scoreFns = opts?.scoreFns;
|
|
16931
|
+
return derived(
|
|
16932
|
+
allDeps,
|
|
16933
|
+
(vals) => {
|
|
16934
|
+
const signals = vals.slice(0, n);
|
|
16935
|
+
const weightValues = vals.slice(n);
|
|
16936
|
+
const breakdown = [];
|
|
16937
|
+
let totalScore = 0;
|
|
16938
|
+
for (let i = 0; i < n; i++) {
|
|
16939
|
+
const sig = signals[i] ?? 0;
|
|
16940
|
+
const wt = weightValues[i] ?? 0;
|
|
16941
|
+
const rawScore = scoreFns?.[i] ? scoreFns[i](sig) : sig;
|
|
16942
|
+
const weighted = rawScore * wt;
|
|
16943
|
+
breakdown.push(weighted);
|
|
16944
|
+
totalScore += weighted;
|
|
16945
|
+
}
|
|
16946
|
+
return {
|
|
16947
|
+
value: signals,
|
|
16948
|
+
score: totalScore,
|
|
16949
|
+
breakdown
|
|
16950
|
+
};
|
|
16951
|
+
},
|
|
16952
|
+
{
|
|
16953
|
+
...opts,
|
|
16954
|
+
describeKind: "derived",
|
|
16955
|
+
meta: baseMeta2("scorer", opts?.meta)
|
|
16956
|
+
}
|
|
16957
|
+
);
|
|
16958
|
+
}
|
|
16959
|
+
|
|
16665
16960
|
// src/index.ts
|
|
16666
16961
|
var version = "0.0.0";
|
|
16667
16962
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -16838,6 +17133,7 @@ var version = "0.0.0";
|
|
|
16838
17133
|
reactiveLog,
|
|
16839
17134
|
reactiveMap,
|
|
16840
17135
|
reduce,
|
|
17136
|
+
reduction,
|
|
16841
17137
|
repeat,
|
|
16842
17138
|
replay,
|
|
16843
17139
|
replayWAL,
|