@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
package/dist/index.js
CHANGED
|
@@ -142,9 +142,6 @@ import {
|
|
|
142
142
|
cqrs_exports,
|
|
143
143
|
nestjs_exports
|
|
144
144
|
} from "./chunk-UCW3VWMN.js";
|
|
145
|
-
import {
|
|
146
|
-
core_exports
|
|
147
|
-
} from "./chunk-E7OH6ZAZ.js";
|
|
148
145
|
import {
|
|
149
146
|
JsonCodec,
|
|
150
147
|
createDagCborCodec,
|
|
@@ -186,6 +183,9 @@ import {
|
|
|
186
183
|
toMessages$,
|
|
187
184
|
toObservable
|
|
188
185
|
} from "./chunk-YWTP2XRJ.js";
|
|
186
|
+
import {
|
|
187
|
+
core_exports
|
|
188
|
+
} from "./chunk-E7OH6ZAZ.js";
|
|
189
189
|
import {
|
|
190
190
|
ResettableTimer
|
|
191
191
|
} from "./chunk-WZ2Z2CRV.js";
|
|
@@ -1048,7 +1048,8 @@ __export(patterns_exports, {
|
|
|
1048
1048
|
layout: () => reactive_layout_exports,
|
|
1049
1049
|
memory: () => memory_exports,
|
|
1050
1050
|
messaging: () => messaging_exports,
|
|
1051
|
-
orchestration: () => orchestration_exports
|
|
1051
|
+
orchestration: () => orchestration_exports,
|
|
1052
|
+
reduction: () => reduction_exports
|
|
1052
1053
|
});
|
|
1053
1054
|
|
|
1054
1055
|
// src/patterns/ai.ts
|
|
@@ -3802,6 +3803,277 @@ function onFailure(graph, name, source, recover, opts) {
|
|
|
3802
3803
|
return step;
|
|
3803
3804
|
}
|
|
3804
3805
|
|
|
3806
|
+
// src/patterns/reduction.ts
|
|
3807
|
+
var reduction_exports = {};
|
|
3808
|
+
__export(reduction_exports, {
|
|
3809
|
+
budgetGate: () => budgetGate,
|
|
3810
|
+
feedback: () => feedback,
|
|
3811
|
+
funnel: () => funnel,
|
|
3812
|
+
scorer: () => scorer,
|
|
3813
|
+
stratify: () => stratify
|
|
3814
|
+
});
|
|
3815
|
+
function baseMeta2(kind, meta) {
|
|
3816
|
+
return {
|
|
3817
|
+
reduction: true,
|
|
3818
|
+
reduction_type: kind,
|
|
3819
|
+
...meta ?? {}
|
|
3820
|
+
};
|
|
3821
|
+
}
|
|
3822
|
+
function stratify(name, source, rules, opts) {
|
|
3823
|
+
const g = new Graph(name, opts);
|
|
3824
|
+
g.add("source", source);
|
|
3825
|
+
const rulesNode = state(rules, {
|
|
3826
|
+
meta: baseMeta2("stratify_rules")
|
|
3827
|
+
});
|
|
3828
|
+
g.add("rules", rulesNode);
|
|
3829
|
+
for (const rule of rules) {
|
|
3830
|
+
_addBranch(g, source, rulesNode, rule);
|
|
3831
|
+
}
|
|
3832
|
+
return g;
|
|
3833
|
+
}
|
|
3834
|
+
function _addBranch(graph, source, rulesNode, rule) {
|
|
3835
|
+
const branchName = `branch/${rule.name}`;
|
|
3836
|
+
let pendingDirty = false;
|
|
3837
|
+
const filterNode = node([source, rulesNode], () => void 0, {
|
|
3838
|
+
describeKind: "operator",
|
|
3839
|
+
meta: baseMeta2("stratify_branch", { branch: rule.name }),
|
|
3840
|
+
onMessage(msg, depIndex, actions) {
|
|
3841
|
+
if (depIndex !== 0) return false;
|
|
3842
|
+
const t = msg[0];
|
|
3843
|
+
if (t === DATA) {
|
|
3844
|
+
const value = msg[1];
|
|
3845
|
+
const currentRules = rulesNode.get();
|
|
3846
|
+
const currentRule = currentRules.find((r) => r.name === rule.name);
|
|
3847
|
+
if (currentRule && currentRule.classify(value)) {
|
|
3848
|
+
pendingDirty = false;
|
|
3849
|
+
actions.emit(value);
|
|
3850
|
+
} else {
|
|
3851
|
+
if (pendingDirty) {
|
|
3852
|
+
pendingDirty = false;
|
|
3853
|
+
actions.down([[DIRTY], [RESOLVED]]);
|
|
3854
|
+
}
|
|
3855
|
+
}
|
|
3856
|
+
return true;
|
|
3857
|
+
}
|
|
3858
|
+
if (t === DIRTY) {
|
|
3859
|
+
pendingDirty = true;
|
|
3860
|
+
return true;
|
|
3861
|
+
}
|
|
3862
|
+
if (t === RESOLVED) {
|
|
3863
|
+
if (pendingDirty) {
|
|
3864
|
+
pendingDirty = false;
|
|
3865
|
+
actions.down([[DIRTY], [RESOLVED]]);
|
|
3866
|
+
} else {
|
|
3867
|
+
actions.down([[RESOLVED]]);
|
|
3868
|
+
}
|
|
3869
|
+
return true;
|
|
3870
|
+
}
|
|
3871
|
+
if (t === COMPLETE || t === ERROR) {
|
|
3872
|
+
pendingDirty = false;
|
|
3873
|
+
actions.down([msg]);
|
|
3874
|
+
return true;
|
|
3875
|
+
}
|
|
3876
|
+
return false;
|
|
3877
|
+
}
|
|
3878
|
+
});
|
|
3879
|
+
graph.add(branchName, filterNode);
|
|
3880
|
+
graph.connect("source", branchName);
|
|
3881
|
+
if (rule.ops) {
|
|
3882
|
+
const transformed = rule.ops(filterNode);
|
|
3883
|
+
const transformedName = `branch/${rule.name}/out`;
|
|
3884
|
+
graph.add(transformedName, transformed);
|
|
3885
|
+
graph.connect(branchName, transformedName);
|
|
3886
|
+
}
|
|
3887
|
+
}
|
|
3888
|
+
function funnel(name, sources, stages, opts) {
|
|
3889
|
+
if (sources.length === 0) throw new RangeError("funnel requires at least one source");
|
|
3890
|
+
if (stages.length === 0) throw new RangeError("funnel requires at least one stage");
|
|
3891
|
+
const g = new Graph(name, opts);
|
|
3892
|
+
const merged = sources.length === 1 ? sources[0] : merge(...sources);
|
|
3893
|
+
g.add("merged", merged);
|
|
3894
|
+
let prevOutputPath = "merged";
|
|
3895
|
+
for (let i = 0; i < stages.length; i++) {
|
|
3896
|
+
const stage = stages[i];
|
|
3897
|
+
const sub = new Graph(stage.name);
|
|
3898
|
+
stage.build(sub);
|
|
3899
|
+
try {
|
|
3900
|
+
sub.resolve("input");
|
|
3901
|
+
} catch {
|
|
3902
|
+
throw new Error(`funnel stage "${stage.name}" must define an "input" node`);
|
|
3903
|
+
}
|
|
3904
|
+
try {
|
|
3905
|
+
sub.resolve("output");
|
|
3906
|
+
} catch {
|
|
3907
|
+
throw new Error(`funnel stage "${stage.name}" must define an "output" node`);
|
|
3908
|
+
}
|
|
3909
|
+
g.mount(stage.name, sub);
|
|
3910
|
+
const prevNode = g.resolve(prevOutputPath);
|
|
3911
|
+
const stageInputPath = `${stage.name}::input`;
|
|
3912
|
+
const stageInput = g.resolve(stageInputPath);
|
|
3913
|
+
prevNode.subscribe((msgs) => {
|
|
3914
|
+
for (const msg of msgs) {
|
|
3915
|
+
const t = msg[0];
|
|
3916
|
+
if (t === DATA) {
|
|
3917
|
+
stageInput.down([[DATA, msg[1]]]);
|
|
3918
|
+
} else if (t === DIRTY) {
|
|
3919
|
+
stageInput.down([[DIRTY]]);
|
|
3920
|
+
} else if (t === RESOLVED) {
|
|
3921
|
+
stageInput.down([[RESOLVED]]);
|
|
3922
|
+
} else if (t === COMPLETE || t === ERROR) {
|
|
3923
|
+
stageInput.down([msg]);
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
});
|
|
3927
|
+
prevOutputPath = `${stage.name}::output`;
|
|
3928
|
+
}
|
|
3929
|
+
return g;
|
|
3930
|
+
}
|
|
3931
|
+
function feedback(graph, condition, reentry, opts) {
|
|
3932
|
+
const maxIter = opts?.maxIterations ?? 10;
|
|
3933
|
+
const counterName = `__feedback_${condition}`;
|
|
3934
|
+
const counter = state(0, {
|
|
3935
|
+
meta: baseMeta2("feedback_counter", { maxIterations: maxIter })
|
|
3936
|
+
});
|
|
3937
|
+
graph.add(counterName, counter);
|
|
3938
|
+
const condNode = graph.resolve(condition);
|
|
3939
|
+
const reentryNode = graph.resolve(reentry);
|
|
3940
|
+
condNode.subscribe((msgs) => {
|
|
3941
|
+
for (const msg of msgs) {
|
|
3942
|
+
if (msg[0] === DATA) {
|
|
3943
|
+
const currentCount = counter.get();
|
|
3944
|
+
if (currentCount >= maxIter) continue;
|
|
3945
|
+
const condValue = msg[1];
|
|
3946
|
+
if (condValue == null) continue;
|
|
3947
|
+
counter.down([[DATA, currentCount + 1]]);
|
|
3948
|
+
reentryNode.down([[DATA, condValue]]);
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
});
|
|
3952
|
+
return graph;
|
|
3953
|
+
}
|
|
3954
|
+
function budgetGate(source, constraints, opts) {
|
|
3955
|
+
if (constraints.length === 0) throw new RangeError("budgetGate requires at least one constraint");
|
|
3956
|
+
const constraintNodes = constraints.map((c) => c.node);
|
|
3957
|
+
const allDeps = [source, ...constraintNodes];
|
|
3958
|
+
let buffer2 = [];
|
|
3959
|
+
let paused = false;
|
|
3960
|
+
const lockId = /* @__PURE__ */ Symbol("budget-gate");
|
|
3961
|
+
function checkBudget() {
|
|
3962
|
+
return constraints.every((c) => c.check(c.node.get()));
|
|
3963
|
+
}
|
|
3964
|
+
function flushBuffer(actions) {
|
|
3965
|
+
while (buffer2.length > 0 && checkBudget()) {
|
|
3966
|
+
const item = buffer2.shift();
|
|
3967
|
+
actions.emit(item);
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
return node(allDeps, () => void 0, {
|
|
3971
|
+
...opts,
|
|
3972
|
+
describeKind: "operator",
|
|
3973
|
+
meta: baseMeta2("budget_gate", opts?.meta),
|
|
3974
|
+
onMessage(msg, depIndex, actions) {
|
|
3975
|
+
const t = msg[0];
|
|
3976
|
+
if (depIndex === 0) {
|
|
3977
|
+
if (t === DATA) {
|
|
3978
|
+
if (checkBudget() && buffer2.length === 0) {
|
|
3979
|
+
actions.emit(msg[1]);
|
|
3980
|
+
} else {
|
|
3981
|
+
buffer2.push(msg[1]);
|
|
3982
|
+
if (!paused) {
|
|
3983
|
+
paused = true;
|
|
3984
|
+
actions.up([[PAUSE, lockId]]);
|
|
3985
|
+
}
|
|
3986
|
+
}
|
|
3987
|
+
return true;
|
|
3988
|
+
}
|
|
3989
|
+
if (t === DIRTY) {
|
|
3990
|
+
actions.down([[DIRTY]]);
|
|
3991
|
+
return true;
|
|
3992
|
+
}
|
|
3993
|
+
if (t === RESOLVED) {
|
|
3994
|
+
if (buffer2.length === 0) {
|
|
3995
|
+
actions.down([[RESOLVED]]);
|
|
3996
|
+
}
|
|
3997
|
+
return true;
|
|
3998
|
+
}
|
|
3999
|
+
if (t === COMPLETE || t === ERROR) {
|
|
4000
|
+
for (const item of buffer2) {
|
|
4001
|
+
actions.emit(item);
|
|
4002
|
+
}
|
|
4003
|
+
buffer2 = [];
|
|
4004
|
+
if (paused) {
|
|
4005
|
+
paused = false;
|
|
4006
|
+
actions.up([[RESUME, lockId]]);
|
|
4007
|
+
}
|
|
4008
|
+
actions.down([msg]);
|
|
4009
|
+
return true;
|
|
4010
|
+
}
|
|
4011
|
+
return false;
|
|
4012
|
+
}
|
|
4013
|
+
if (t === DATA || t === RESOLVED) {
|
|
4014
|
+
if (checkBudget() && buffer2.length > 0) {
|
|
4015
|
+
flushBuffer(actions);
|
|
4016
|
+
if (buffer2.length === 0 && paused) {
|
|
4017
|
+
paused = false;
|
|
4018
|
+
actions.up([[RESUME, lockId]]);
|
|
4019
|
+
}
|
|
4020
|
+
} else if (!checkBudget() && !paused && buffer2.length > 0) {
|
|
4021
|
+
paused = true;
|
|
4022
|
+
actions.up([[PAUSE, lockId]]);
|
|
4023
|
+
}
|
|
4024
|
+
return true;
|
|
4025
|
+
}
|
|
4026
|
+
if (t === DIRTY) {
|
|
4027
|
+
return true;
|
|
4028
|
+
}
|
|
4029
|
+
if (t === ERROR) {
|
|
4030
|
+
actions.down([msg]);
|
|
4031
|
+
return true;
|
|
4032
|
+
}
|
|
4033
|
+
if (t === COMPLETE) {
|
|
4034
|
+
return true;
|
|
4035
|
+
}
|
|
4036
|
+
return false;
|
|
4037
|
+
}
|
|
4038
|
+
});
|
|
4039
|
+
}
|
|
4040
|
+
function scorer(sources, weights, opts) {
|
|
4041
|
+
if (sources.length === 0) throw new RangeError("scorer requires at least one source");
|
|
4042
|
+
if (sources.length !== weights.length) {
|
|
4043
|
+
throw new RangeError("scorer requires the same number of sources and weights");
|
|
4044
|
+
}
|
|
4045
|
+
const allDeps = [...sources, ...weights];
|
|
4046
|
+
const n = sources.length;
|
|
4047
|
+
const scoreFns = opts?.scoreFns;
|
|
4048
|
+
return derived(
|
|
4049
|
+
allDeps,
|
|
4050
|
+
(vals) => {
|
|
4051
|
+
const signals = vals.slice(0, n);
|
|
4052
|
+
const weightValues = vals.slice(n);
|
|
4053
|
+
const breakdown = [];
|
|
4054
|
+
let totalScore = 0;
|
|
4055
|
+
for (let i = 0; i < n; i++) {
|
|
4056
|
+
const sig = signals[i] ?? 0;
|
|
4057
|
+
const wt = weightValues[i] ?? 0;
|
|
4058
|
+
const rawScore = scoreFns?.[i] ? scoreFns[i](sig) : sig;
|
|
4059
|
+
const weighted = rawScore * wt;
|
|
4060
|
+
breakdown.push(weighted);
|
|
4061
|
+
totalScore += weighted;
|
|
4062
|
+
}
|
|
4063
|
+
return {
|
|
4064
|
+
value: signals,
|
|
4065
|
+
score: totalScore,
|
|
4066
|
+
breakdown
|
|
4067
|
+
};
|
|
4068
|
+
},
|
|
4069
|
+
{
|
|
4070
|
+
...opts,
|
|
4071
|
+
describeKind: "derived",
|
|
4072
|
+
meta: baseMeta2("scorer", opts?.meta)
|
|
4073
|
+
}
|
|
4074
|
+
);
|
|
4075
|
+
}
|
|
4076
|
+
|
|
3805
4077
|
// src/index.ts
|
|
3806
4078
|
var version = "0.0.0";
|
|
3807
4079
|
export {
|
|
@@ -3977,6 +4249,7 @@ export {
|
|
|
3977
4249
|
reactiveLog,
|
|
3978
4250
|
reactiveMap,
|
|
3979
4251
|
reduce,
|
|
4252
|
+
reduction_exports as reduction,
|
|
3980
4253
|
repeat,
|
|
3981
4254
|
replay,
|
|
3982
4255
|
replayWAL,
|