@graphrefly/graphrefly 0.8.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/compat/nestjs/index.js +1 -1
- package/dist/index.cjs +275 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +190 -15
- package/dist/index.d.ts +190 -15
- package/dist/index.js +277 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -32,7 +32,6 @@ import {
|
|
|
32
32
|
observeSSE,
|
|
33
33
|
observeSubscription
|
|
34
34
|
} from "../../chunk-UCW3VWMN.js";
|
|
35
|
-
import "../../chunk-E7OH6ZAZ.js";
|
|
36
35
|
import "../../chunk-A2AJJOSJ.js";
|
|
37
36
|
import {
|
|
38
37
|
observeGraph$,
|
|
@@ -40,6 +39,7 @@ import {
|
|
|
40
39
|
toMessages$,
|
|
41
40
|
toObservable
|
|
42
41
|
} from "../../chunk-YWTP2XRJ.js";
|
|
42
|
+
import "../../chunk-E7OH6ZAZ.js";
|
|
43
43
|
import "../../chunk-WZ2Z2CRV.js";
|
|
44
44
|
import "../../chunk-WYI7YW54.js";
|
|
45
45
|
import "../../chunk-LR2CLSEF.js";
|
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,
|
|
@@ -12864,7 +12865,8 @@ __export(patterns_exports, {
|
|
|
12864
12865
|
layout: () => reactive_layout_exports,
|
|
12865
12866
|
memory: () => memory_exports,
|
|
12866
12867
|
messaging: () => messaging_exports,
|
|
12867
|
-
orchestration: () => orchestration_exports
|
|
12868
|
+
orchestration: () => orchestration_exports,
|
|
12869
|
+
reduction: () => reduction_exports
|
|
12868
12870
|
});
|
|
12869
12871
|
|
|
12870
12872
|
// src/patterns/ai.ts
|
|
@@ -16684,6 +16686,277 @@ function reactiveBlockLayout(opts) {
|
|
|
16684
16686
|
};
|
|
16685
16687
|
}
|
|
16686
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
|
+
|
|
16687
16960
|
// src/index.ts
|
|
16688
16961
|
var version = "0.0.0";
|
|
16689
16962
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -16860,6 +17133,7 @@ var version = "0.0.0";
|
|
|
16860
17133
|
reactiveLog,
|
|
16861
17134
|
reactiveMap,
|
|
16862
17135
|
reduce,
|
|
17136
|
+
reduction,
|
|
16863
17137
|
repeat,
|
|
16864
17138
|
replay,
|
|
16865
17139
|
replayWAL,
|