@particle-academy/fancy-flow 0.71.0 → 0.72.1
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-3L47KJ6Q.js → chunk-3RXQGYGH.js} +3 -3
- package/dist/{chunk-3L47KJ6Q.js.map → chunk-3RXQGYGH.js.map} +1 -1
- package/dist/{chunk-PNTDTSMR.js → chunk-7DJ56PUA.js} +4 -4
- package/dist/{chunk-PNTDTSMR.js.map → chunk-7DJ56PUA.js.map} +1 -1
- package/dist/{chunk-EVGSL2EM.js → chunk-EX34GCKK.js} +162 -151
- package/dist/chunk-EX34GCKK.js.map +1 -0
- package/dist/{chunk-XI4AZD2S.js → chunk-GQ5LEA7Q.js} +3 -3
- package/dist/{chunk-XI4AZD2S.js.map → chunk-GQ5LEA7Q.js.map} +1 -1
- package/dist/{chunk-D2OBU3CE.js → chunk-K7KO3UJ3.js} +3 -3
- package/dist/{chunk-D2OBU3CE.js.map → chunk-K7KO3UJ3.js.map} +1 -1
- package/dist/{chunk-FPWJYSXX.js → chunk-LYYQO7EY.js} +4 -4
- package/dist/{chunk-FPWJYSXX.js.map → chunk-LYYQO7EY.js.map} +1 -1
- package/dist/{chunk-KQCX6KN7.js → chunk-VAF2SWTC.js} +3 -3
- package/dist/{chunk-KQCX6KN7.js.map → chunk-VAF2SWTC.js.map} +1 -1
- package/dist/durable/index.d.cts +90 -16
- package/dist/durable/index.d.ts +90 -16
- package/dist/durable.cjs +160 -83
- package/dist/durable.cjs.map +1 -1
- package/dist/durable.js +79 -14
- package/dist/durable.js.map +1 -1
- package/dist/engine.cjs +82 -71
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +2 -2
- package/dist/engine.d.ts +2 -2
- package/dist/engine.js +4 -4
- package/dist/index.cjs +128 -117
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +12 -12
- package/dist/registry.cjs +82 -71
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +2 -2
- package/dist/{run-cohort-DL9JzzPU.d.cts → run-cohort-DNpPa0mq.d.cts} +1 -1
- package/dist/{run-cohort-CjUBWg6X.d.ts → run-cohort-rgT_FX3V.d.ts} +1 -1
- package/dist/{run-flow-B_8hgO5_.d.cts → run-flow-BLP9rXfO.d.ts} +22 -1
- package/dist/{run-flow-CxEGBOxd.d.ts → run-flow-pW0PllaZ.d.cts} +22 -1
- package/dist/runtime/index.d.cts +3 -3
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime.cjs +82 -71
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +3 -3
- package/dist/schema.cjs +82 -71
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +3 -3
- package/dist/screens.cjs +82 -71
- package/dist/screens.cjs.map +1 -1
- package/dist/screens.js +4 -4
- package/dist/ux.cjs +82 -71
- package/dist/ux.cjs.map +1 -1
- package/dist/ux.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-EVGSL2EM.js.map +0 -1
package/dist/engine.cjs
CHANGED
|
@@ -2004,24 +2004,6 @@ function resolveNodePorts(node, kind) {
|
|
|
2004
2004
|
};
|
|
2005
2005
|
}
|
|
2006
2006
|
|
|
2007
|
-
// src/expressions/variables.ts
|
|
2008
|
-
function outputFieldsFor(node) {
|
|
2009
|
-
const kindName2 = node.data?.kind ?? node.type;
|
|
2010
|
-
if (!kindName2) return [];
|
|
2011
|
-
const kind = getNodeKind(kindName2);
|
|
2012
|
-
const shape = kind?.outputShape;
|
|
2013
|
-
if (!shape) return [];
|
|
2014
|
-
if (typeof shape === "function") {
|
|
2015
|
-
try {
|
|
2016
|
-
const config = node.data?.config ?? {};
|
|
2017
|
-
return shape(config) ?? [];
|
|
2018
|
-
} catch {
|
|
2019
|
-
return [];
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
|
-
return shape;
|
|
2023
|
-
}
|
|
2024
|
-
|
|
2025
2007
|
// src/runtime/run-identity.ts
|
|
2026
2008
|
function escapeSegment(value) {
|
|
2027
2009
|
return value.replace(/%/g, "%25").replace(/\//g, "%2F").replace(/#/g, "%23");
|
|
@@ -2365,6 +2347,81 @@ function specForLane(lane) {
|
|
|
2365
2347
|
};
|
|
2366
2348
|
}
|
|
2367
2349
|
|
|
2350
|
+
// src/expressions/variables.ts
|
|
2351
|
+
function outputFieldsFor(node) {
|
|
2352
|
+
const kindName2 = node.data?.kind ?? node.type;
|
|
2353
|
+
if (!kindName2) return [];
|
|
2354
|
+
const kind = getNodeKind(kindName2);
|
|
2355
|
+
const shape = kind?.outputShape;
|
|
2356
|
+
if (!shape) return [];
|
|
2357
|
+
if (typeof shape === "function") {
|
|
2358
|
+
try {
|
|
2359
|
+
const config = node.data?.config ?? {};
|
|
2360
|
+
return shape(config) ?? [];
|
|
2361
|
+
} catch {
|
|
2362
|
+
return [];
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
return shape;
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
// src/runtime/undelivered-edges.ts
|
|
2369
|
+
function undeliveredEdgeWarnings(target, incoming, portValues, completed, nodesById) {
|
|
2370
|
+
const events = [];
|
|
2371
|
+
for (const e of incoming) {
|
|
2372
|
+
const handle = e.sourceHandle ?? "out";
|
|
2373
|
+
if (portValues.has(`${e.source}:${handle}`) || !completed.has(e.source)) continue;
|
|
2374
|
+
if (possiblePortIds(nodesById.get(e.source)).includes(handle)) continue;
|
|
2375
|
+
events.push({
|
|
2376
|
+
type: "log",
|
|
2377
|
+
nodeId: target.id,
|
|
2378
|
+
level: "warn",
|
|
2379
|
+
message: undeliveredEdgeMessage(e, target, portValues, nodesById),
|
|
2380
|
+
detail: { edge: e.id, source: e.source, sourceHandle: handle }
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
return events;
|
|
2384
|
+
}
|
|
2385
|
+
function possiblePortIds(node) {
|
|
2386
|
+
if (!node) return ["out"];
|
|
2387
|
+
const own = node.data?.outputs;
|
|
2388
|
+
if (Array.isArray(own)) return own.map((p) => p.id);
|
|
2389
|
+
const kind = getNodeKind(node.data?.kind ?? node.type ?? "");
|
|
2390
|
+
if (!kind) return ["out"];
|
|
2391
|
+
const config = nodeConfig(node);
|
|
2392
|
+
const representative = typeof kind.outputs === "function" && !configDeclaresPorts(kind.name, config);
|
|
2393
|
+
const ids = (resolvePortSpec(kind.outputs, representative ? defaultConfigFor(kind) : config) ?? []).map((p) => p.id);
|
|
2394
|
+
return ids.length > 0 ? ids : ["out"];
|
|
2395
|
+
}
|
|
2396
|
+
function configDeclaresPorts(kindName2, config) {
|
|
2397
|
+
const bare = kindName2.startsWith("@") ? kindName2.slice(kindName2.lastIndexOf("/") + 1) : kindName2;
|
|
2398
|
+
if (bare === "switch_case") {
|
|
2399
|
+
const cases = config.cases;
|
|
2400
|
+
return !!cases && typeof cases === "object" && Object.values(cases).some((port) => typeof port === "string" && port !== "");
|
|
2401
|
+
}
|
|
2402
|
+
if (bare === "llm_router") {
|
|
2403
|
+
const routes = config.routes;
|
|
2404
|
+
return Array.isArray(routes) && routes.some((route) => route?.port != null && route.port !== "");
|
|
2405
|
+
}
|
|
2406
|
+
return true;
|
|
2407
|
+
}
|
|
2408
|
+
function undeliveredEdgeMessage(edge, target, portValues, nodesById) {
|
|
2409
|
+
const handle = edge.sourceHandle ?? "out";
|
|
2410
|
+
const prefix = `${edge.source}:`;
|
|
2411
|
+
const available = [];
|
|
2412
|
+
for (const key2 of portValues.keys()) {
|
|
2413
|
+
if (key2.startsWith(prefix)) available.push(key2.slice(prefix.length));
|
|
2414
|
+
}
|
|
2415
|
+
let message = `Edge ${edge.id} reads port "${handle}" from node ${edge.source}, which never publishes it \u2014 nothing would reach ${target.id} at run time.`;
|
|
2416
|
+
if (available.length > 0) message += ` Available: ${available.join(", ")}.`;
|
|
2417
|
+
const source = nodesById.get(edge.source);
|
|
2418
|
+
if (source && outputFieldsFor(source).some((field) => field?.path === handle)) {
|
|
2419
|
+
message += ` Note: "${handle}" is a FIELD this node emits, not a port \u2014 read it downstream as {{ in.${handle} }} rather than naming it as a source handle.`;
|
|
2420
|
+
}
|
|
2421
|
+
if (edge.sourceHandle != null) message += " Leave sourceHandle off to read the node's output.";
|
|
2422
|
+
return message;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2368
2425
|
// src/runtime/workflow-props.ts
|
|
2369
2426
|
function typeOf(value) {
|
|
2370
2427
|
if (value === null) return "null";
|
|
@@ -2423,7 +2480,7 @@ function resolveWorkflowProps(declared, passed) {
|
|
|
2423
2480
|
// src/runtime/run-flow.ts
|
|
2424
2481
|
async function runFlow(graph, executors, onEvent = () => {
|
|
2425
2482
|
}, options = {}) {
|
|
2426
|
-
const { signal, initialInputs = {}, timeoutMs, depth = 0, resumeOutputs = {}, entryNodes } = options;
|
|
2483
|
+
const { signal, initialInputs = {}, timeoutMs, depth = 0, resumeOutputs = {}, entryNodes, nodeExecutors } = options;
|
|
2427
2484
|
const run = options.run === void 0 ? void 0 : RunIdentity.from(options.run);
|
|
2428
2485
|
const outputs = {};
|
|
2429
2486
|
const portValues = /* @__PURE__ */ new Map();
|
|
@@ -2486,17 +2543,8 @@ async function runFlow(graph, executors, onEvent = () => {
|
|
|
2486
2543
|
onEvent({ type: "node-status", nodeId: node.id, status: "idle", text: "skipped" });
|
|
2487
2544
|
continue;
|
|
2488
2545
|
}
|
|
2489
|
-
for (const
|
|
2490
|
-
|
|
2491
|
-
if (portValues.has(`${e.source}:${handle}`) || !completed.has(e.source)) continue;
|
|
2492
|
-
if (possiblePortIds(nodesById.get(e.source)).includes(handle)) continue;
|
|
2493
|
-
onEvent({
|
|
2494
|
-
type: "log",
|
|
2495
|
-
nodeId: node.id,
|
|
2496
|
-
level: "warn",
|
|
2497
|
-
message: undeliveredEdgeMessage(e, node, portValues, nodesById),
|
|
2498
|
-
detail: { edge: e.id, source: e.source, sourceHandle: handle }
|
|
2499
|
-
});
|
|
2546
|
+
for (const warning of undeliveredEdgeWarnings(node, incoming, portValues, completed, nodesById)) {
|
|
2547
|
+
onEvent(warning);
|
|
2500
2548
|
}
|
|
2501
2549
|
if (incoming.length > 0) {
|
|
2502
2550
|
const anyActive = incoming.some((e) => portValues.has(`${e.source}:${e.sourceHandle ?? "out"}`));
|
|
@@ -2520,7 +2568,7 @@ async function runFlow(graph, executors, onEvent = () => {
|
|
|
2520
2568
|
onEvent({ type: "node-status", nodeId: node.id, status: "running" });
|
|
2521
2569
|
announce(onEvent, node, "start");
|
|
2522
2570
|
const inputs = collectInputs(node, incoming, portValues, initialInputs, props, declaresProps);
|
|
2523
|
-
const exec = pickExecutor(executors, node);
|
|
2571
|
+
const exec = pickExecutor(executors, node, nodeExecutors);
|
|
2524
2572
|
if (!exec) {
|
|
2525
2573
|
const tried = executorLookupIds(node);
|
|
2526
2574
|
const msg = `No executor registered for kind=${node.type} \u2014 tried ${tried.map((id) => `"${id}"`).join(", ")}. Key your registry by one of those.`;
|
|
@@ -2640,7 +2688,9 @@ function executorLookupIds(node) {
|
|
|
2640
2688
|
ids.push("*");
|
|
2641
2689
|
return [...new Set(ids)];
|
|
2642
2690
|
}
|
|
2643
|
-
function pickExecutor(executors, node) {
|
|
2691
|
+
function pickExecutor(executors, node, nodeExecutors) {
|
|
2692
|
+
const pinned = nodeExecutors && Object.prototype.hasOwnProperty.call(nodeExecutors, node.id) ? nodeExecutors[node.id] : void 0;
|
|
2693
|
+
if (pinned) return pinned;
|
|
2644
2694
|
for (const id of executorLookupIds(node)) {
|
|
2645
2695
|
if (executors[id]) return executors[id];
|
|
2646
2696
|
}
|
|
@@ -2660,45 +2710,6 @@ function activatedPorts(node, result) {
|
|
|
2660
2710
|
const declared = resolveNodePorts(node, kind).outputs?.map((p) => p.id);
|
|
2661
2711
|
return { ports: declared?.length ? declared : ["out"], value: result };
|
|
2662
2712
|
}
|
|
2663
|
-
function possiblePortIds(node) {
|
|
2664
|
-
if (!node) return ["out"];
|
|
2665
|
-
const own = node.data?.outputs;
|
|
2666
|
-
if (Array.isArray(own)) return own.map((p) => p.id);
|
|
2667
|
-
const kind = getNodeKind(node.data?.kind ?? node.type ?? "");
|
|
2668
|
-
if (!kind) return ["out"];
|
|
2669
|
-
const config = nodeConfig(node);
|
|
2670
|
-
const representative = typeof kind.outputs === "function" && !configDeclaresPorts(kind.name, config);
|
|
2671
|
-
const ids = (resolvePortSpec(kind.outputs, representative ? defaultConfigFor(kind) : config) ?? []).map((p) => p.id);
|
|
2672
|
-
return ids.length > 0 ? ids : ["out"];
|
|
2673
|
-
}
|
|
2674
|
-
function configDeclaresPorts(kindName2, config) {
|
|
2675
|
-
const bare = kindName2.startsWith("@") ? kindName2.slice(kindName2.lastIndexOf("/") + 1) : kindName2;
|
|
2676
|
-
if (bare === "switch_case") {
|
|
2677
|
-
const cases = config.cases;
|
|
2678
|
-
return !!cases && typeof cases === "object" && Object.values(cases).some((port) => typeof port === "string" && port !== "");
|
|
2679
|
-
}
|
|
2680
|
-
if (bare === "llm_router") {
|
|
2681
|
-
const routes = config.routes;
|
|
2682
|
-
return Array.isArray(routes) && routes.some((route) => route?.port != null && route.port !== "");
|
|
2683
|
-
}
|
|
2684
|
-
return true;
|
|
2685
|
-
}
|
|
2686
|
-
function undeliveredEdgeMessage(edge, target, portValues, nodesById) {
|
|
2687
|
-
const handle = edge.sourceHandle ?? "out";
|
|
2688
|
-
const prefix = `${edge.source}:`;
|
|
2689
|
-
const available = [];
|
|
2690
|
-
for (const key2 of portValues.keys()) {
|
|
2691
|
-
if (key2.startsWith(prefix)) available.push(key2.slice(prefix.length));
|
|
2692
|
-
}
|
|
2693
|
-
let message = `Edge ${edge.id} reads port "${handle}" from node ${edge.source}, which never publishes it \u2014 nothing would reach ${target.id} at run time.`;
|
|
2694
|
-
if (available.length > 0) message += ` Available: ${available.join(", ")}.`;
|
|
2695
|
-
const source = nodesById.get(edge.source);
|
|
2696
|
-
if (source && outputFieldsFor(source).some((field) => field?.path === handle)) {
|
|
2697
|
-
message += ` Note: "${handle}" is a FIELD this node emits, not a port \u2014 read it downstream as {{ in.${handle} }} rather than naming it as a source handle.`;
|
|
2698
|
-
}
|
|
2699
|
-
if (edge.sourceHandle != null) message += " Leave sourceHandle off to read the node's output.";
|
|
2700
|
-
return message;
|
|
2701
|
-
}
|
|
2702
2713
|
function announce(onEvent, node, phase) {
|
|
2703
2714
|
const data = node.data;
|
|
2704
2715
|
const raw = phase === "start" ? data?.startingMsg : data?.stoppingMsg;
|