@particle-academy/fancy-flow 0.77.1 → 0.79.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/{FlowViewer-Ak8kbY0e.d.cts → FlowViewer-BqYQl2vS.d.cts} +1 -1
- package/dist/{FlowViewer-BAV29Zpi.d.ts → FlowViewer-_Fq8AX9V.d.ts} +1 -1
- package/dist/{HumanPrompt-xYPCL2jO.d.cts → HumanPrompt-Sl1wD9Bx.d.cts} +2 -2
- package/dist/{HumanPrompt-Ge_ccCgS.d.ts → HumanPrompt-_SKIdSpx.d.ts} +2 -2
- package/dist/{chunk-T6WIIGSK.js → chunk-I5EPWHNM.js} +3 -3
- package/dist/{chunk-T6WIIGSK.js.map → chunk-I5EPWHNM.js.map} +1 -1
- package/dist/{chunk-EGXA4SYJ.js → chunk-J66LOLJR.js} +4 -4
- package/dist/{chunk-EGXA4SYJ.js.map → chunk-J66LOLJR.js.map} +1 -1
- package/dist/{chunk-G5RAGPVD.js → chunk-KMONOPAK.js} +3 -3
- package/dist/{chunk-G5RAGPVD.js.map → chunk-KMONOPAK.js.map} +1 -1
- package/dist/{chunk-ARSOSEJV.js → chunk-LBE4L3DS.js} +4 -4
- package/dist/{chunk-ARSOSEJV.js.map → chunk-LBE4L3DS.js.map} +1 -1
- package/dist/{chunk-EEIWAIXW.js → chunk-OZHBAXMA.js} +125 -8
- package/dist/chunk-OZHBAXMA.js.map +1 -0
- package/dist/{chunk-2VI24UPB.js → chunk-QMJVUT7C.js} +3 -3
- package/dist/{chunk-2VI24UPB.js.map → chunk-QMJVUT7C.js.map} +1 -1
- package/dist/{chunk-CQAMEPPI.js → chunk-R4G7SPLD.js} +3 -3
- package/dist/{chunk-CQAMEPPI.js.map → chunk-R4G7SPLD.js.map} +1 -1
- package/dist/connectors.d.cts +2 -2
- package/dist/connectors.d.ts +2 -2
- package/dist/durable/index.d.cts +2 -2
- package/dist/durable/index.d.ts +2 -2
- package/dist/durable.cjs +123 -6
- package/dist/durable.cjs.map +1 -1
- package/dist/durable.js +1 -1
- package/dist/engine.cjs +123 -6
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +6 -6
- package/dist/engine.d.ts +6 -6
- package/dist/engine.js +4 -4
- package/dist/fields/react-fancy.d.cts +3 -3
- package/dist/fields/react-fancy.d.ts +3 -3
- package/dist/index.cjs +123 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +12 -12
- package/dist/layout/index.d.cts +1 -1
- package/dist/layout/index.d.ts +1 -1
- package/dist/llm/prism.d.cts +1 -1
- package/dist/llm/prism.d.ts +1 -1
- package/dist/llm/vercel-ai.d.cts +1 -1
- package/dist/llm/vercel-ai.d.ts +1 -1
- package/dist/registry/index.d.cts +5 -5
- package/dist/registry/index.d.ts +5 -5
- package/dist/{registry-JUcN_xWK.d.ts → registry-C4GcH583.d.ts} +1 -1
- package/dist/{registry-B6SiTaLZ.d.cts → registry-DWIY3bMP.d.cts} +1 -1
- package/dist/registry.cjs +123 -6
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +2 -2
- package/dist/{run-cohort-rgT_FX3V.d.ts → run-cohort-DAfhZm-p.d.ts} +2 -2
- package/dist/{run-cohort-DNpPa0mq.d.cts → run-cohort-DRJvUWO9.d.cts} +2 -2
- package/dist/{run-flow-pW0PllaZ.d.cts → run-flow-Bdrn4lQV.d.cts} +1 -1
- package/dist/{run-flow-BLP9rXfO.d.ts → run-flow-D2iOjWsj.d.ts} +1 -1
- package/dist/runtime/index.d.cts +5 -5
- package/dist/runtime/index.d.ts +5 -5
- package/dist/runtime.cjs +123 -6
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +3 -3
- package/dist/schema/index.d.cts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema.cjs +123 -6
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +3 -3
- package/dist/screens.cjs +123 -6
- package/dist/screens.cjs.map +1 -1
- package/dist/screens.d.cts +2 -2
- package/dist/screens.d.ts +2 -2
- package/dist/screens.js +4 -4
- package/dist/terminal/fancy-term-host.d.cts +1 -1
- package/dist/terminal/fancy-term-host.d.ts +1 -1
- package/dist/{types-BdkXxjFh.d.cts → types-B1jftRa9.d.cts} +1 -1
- package/dist/{types-CbekKMMO.d.ts → types-D5SBBpbe.d.ts} +1 -1
- package/dist/{types-B-Syk9-M.d.ts → types-E48Dpesq.d.cts} +20 -0
- package/dist/{types-B-Syk9-M.d.cts → types-E48Dpesq.d.ts} +20 -0
- package/dist/ux.cjs +123 -6
- package/dist/ux.cjs.map +1 -1
- package/dist/ux.d.cts +2 -2
- package/dist/ux.d.ts +2 -2
- package/dist/ux.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-EEIWAIXW.js.map +0 -1
package/dist/registry.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { ANY_PORT_TYPE, BUILTIN_KINDS, RegistryNode, buildNodeTypes, createConnectionValidator, defaultPortCompatibility, registerBuiltinKinds } from './chunk-
|
|
1
|
+
export { ANY_PORT_TYPE, BUILTIN_KINDS, RegistryNode, buildNodeTypes, createConnectionValidator, defaultPortCompatibility, registerBuiltinKinds } from './chunk-I5EPWHNM.js';
|
|
2
2
|
export { RichInputPreview, getRichInputAdapter, isRichInputEnabled, onRichInputAdapterChanged, registerRichInputAdapter } from './chunk-F5RPRB7A.js';
|
|
3
3
|
import './chunk-OWENS2H5.js';
|
|
4
|
-
export { DEFAULT_MAX_DEPTH, LEGACY_PAUSE_PREFIXES, PAUSE_PREFIX, applyKindSchemaOverlay, categoryAccent, clearKindSchemaOverlays, clearNodeKindOverrides, declaredRoutes, decodePause, defaultConfigFor, encodePause, ensureBuiltinKinds, getNodeKind, isPause, kindIds, listNodeKinds, llmRouterExecutor as llmBranchExecutor, llmRouterExecutor, nodeConfig, onNodeKindsChanged, overrideNodeKind, pauseForHuman, registerNodeKind, resolveFallbackPort, resolveKindId, resolveNodePorts, resolvePortSpec, subflowExecutor, subflowMode, subflowPorts, unregisterNodeKind, validateConfig } from './chunk-
|
|
4
|
+
export { DEFAULT_MAX_DEPTH, LEGACY_PAUSE_PREFIXES, PAUSE_PREFIX, applyKindSchemaOverlay, categoryAccent, clearKindSchemaOverlays, clearNodeKindOverrides, declaredRoutes, decodePause, defaultConfigFor, encodePause, ensureBuiltinKinds, getNodeKind, isPause, kindIds, listNodeKinds, llmRouterExecutor as llmBranchExecutor, llmRouterExecutor, nodeConfig, onNodeKindsChanged, overrideNodeKind, pauseForHuman, registerNodeKind, resolveFallbackPort, resolveKindId, resolveNodePorts, resolvePortSpec, subflowExecutor, subflowMode, subflowPorts, unregisterNodeKind, validateConfig } from './chunk-OZHBAXMA.js';
|
|
5
5
|
export { capabilityStatus, getLlmClient, getTerminalHost, getWorkflowResolver, isResolutionFailure, registerLlmClient, registerTerminalHost, registerWorkflowResolver } from './chunk-2QXKDLGT.js';
|
|
6
6
|
//# sourceMappingURL=registry.js.map
|
|
7
7
|
//# sourceMappingURL=registry.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FlowGraph, E as ExecutorRegistry, R as RunEvent } from './types-
|
|
2
|
-
import { R as RunOptions, a as RunResult } from './run-flow-
|
|
1
|
+
import { F as FlowGraph, E as ExecutorRegistry, R as RunEvent } from './types-E48Dpesq.js';
|
|
2
|
+
import { R as RunOptions, a as RunResult } from './run-flow-D2iOjWsj.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* How the flows one trigger fired should treat each other.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FlowGraph, E as ExecutorRegistry, R as RunEvent } from './types-
|
|
2
|
-
import { R as RunOptions, a as RunResult } from './run-flow-
|
|
1
|
+
import { F as FlowGraph, E as ExecutorRegistry, R as RunEvent } from './types-E48Dpesq.cjs';
|
|
2
|
+
import { R as RunOptions, a as RunResult } from './run-flow-Bdrn4lQV.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* How the flows one trigger fired should treat each other.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as RunIdentity, d as RunIdentityJson, N as NodeExecutor, F as FlowGraph, E as ExecutorRegistry, R as RunEvent } from './types-
|
|
1
|
+
import { c as RunIdentity, d as RunIdentityJson, N as NodeExecutor, F as FlowGraph, E as ExecutorRegistry, R as RunEvent } from './types-E48Dpesq.cjs';
|
|
2
2
|
|
|
3
3
|
type RunOptions = {
|
|
4
4
|
/** Stop the run after this many ms. Default: no timeout. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as RunIdentity, d as RunIdentityJson, N as NodeExecutor, F as FlowGraph, E as ExecutorRegistry, R as RunEvent } from './types-
|
|
1
|
+
import { c as RunIdentity, d as RunIdentityJson, N as NodeExecutor, F as FlowGraph, E as ExecutorRegistry, R as RunEvent } from './types-E48Dpesq.js';
|
|
2
2
|
|
|
3
3
|
type RunOptions = {
|
|
4
4
|
/** Stop the run after this many ms. Default: no timeout. */
|
package/dist/runtime/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as RunResult, R as RunOptions } from '../run-flow-
|
|
2
|
-
export { r as runFlow } from '../run-flow-
|
|
3
|
-
import { h as NodeRunStatus, F as FlowGraph, E as ExecutorRegistry, a as FlowNode, e as FlowEdge } from '../types-
|
|
4
|
-
export { c as RunIdentity, d as RunIdentityJson, k as escapeSegment } from '../types-
|
|
5
|
-
export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from '../run-cohort-
|
|
1
|
+
import { a as RunResult, R as RunOptions } from '../run-flow-Bdrn4lQV.cjs';
|
|
2
|
+
export { r as runFlow } from '../run-flow-Bdrn4lQV.cjs';
|
|
3
|
+
import { h as NodeRunStatus, F as FlowGraph, E as ExecutorRegistry, a as FlowNode, e as FlowEdge } from '../types-E48Dpesq.cjs';
|
|
4
|
+
export { c as RunIdentity, d as RunIdentityJson, k as escapeSegment } from '../types-E48Dpesq.cjs';
|
|
5
|
+
export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from '../run-cohort-DRJvUWO9.cjs';
|
|
6
6
|
import { NodeChange, EdgeChange, Connection } from '@xyflow/react';
|
|
7
7
|
|
|
8
8
|
type FlowRunFeedEntry = {
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as RunResult, R as RunOptions } from '../run-flow-
|
|
2
|
-
export { r as runFlow } from '../run-flow-
|
|
3
|
-
import { h as NodeRunStatus, F as FlowGraph, E as ExecutorRegistry, a as FlowNode, e as FlowEdge } from '../types-
|
|
4
|
-
export { c as RunIdentity, d as RunIdentityJson, k as escapeSegment } from '../types-
|
|
5
|
-
export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from '../run-cohort-
|
|
1
|
+
import { a as RunResult, R as RunOptions } from '../run-flow-D2iOjWsj.js';
|
|
2
|
+
export { r as runFlow } from '../run-flow-D2iOjWsj.js';
|
|
3
|
+
import { h as NodeRunStatus, F as FlowGraph, E as ExecutorRegistry, a as FlowNode, e as FlowEdge } from '../types-E48Dpesq.js';
|
|
4
|
+
export { c as RunIdentity, d as RunIdentityJson, k as escapeSegment } from '../types-E48Dpesq.js';
|
|
5
|
+
export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from '../run-cohort-DAfhZm-p.js';
|
|
6
6
|
import { NodeChange, EdgeChange, Connection } from '@xyflow/react';
|
|
7
7
|
|
|
8
8
|
type FlowRunFeedEntry = {
|
package/dist/runtime.cjs
CHANGED
|
@@ -415,6 +415,7 @@ var branchExecutor = (ctx) => {
|
|
|
415
415
|
const inputs = ctx.inputs;
|
|
416
416
|
let taken;
|
|
417
417
|
const raw = config.condition;
|
|
418
|
+
validateRoutingExpression(ctx, raw, "branch", "condition");
|
|
418
419
|
if (typeof raw === "string" && raw.trim() !== "") {
|
|
419
420
|
taken = truthy(resolve(raw, inputs));
|
|
420
421
|
warnIfUnresolved(ctx, raw, taken ? "true" : "false");
|
|
@@ -469,14 +470,102 @@ var mergeExecutor = (ctx) => {
|
|
|
469
470
|
}
|
|
470
471
|
return merged;
|
|
471
472
|
};
|
|
472
|
-
var
|
|
473
|
-
|
|
473
|
+
var FOR_EACH_DEFAULT_MAX_ITEMS = 1e3;
|
|
474
|
+
var FOR_EACH_HARD_MAX_ITEMS = 1e4;
|
|
475
|
+
function reachable(adjacency, starts) {
|
|
476
|
+
const seen = /* @__PURE__ */ new Set();
|
|
477
|
+
const queue = [...starts];
|
|
478
|
+
for (let cursor = 0; cursor < queue.length; cursor += 1) {
|
|
479
|
+
const id2 = queue[cursor];
|
|
480
|
+
if (seen.has(id2)) continue;
|
|
481
|
+
seen.add(id2);
|
|
482
|
+
for (const target of adjacency.get(id2) ?? []) queue.push(target);
|
|
483
|
+
}
|
|
484
|
+
return seen;
|
|
485
|
+
}
|
|
486
|
+
function forEachLane(graph, nodeId) {
|
|
487
|
+
const handleOf = (edge) => edge.sourceHandle ?? "out";
|
|
488
|
+
const itemEdges = graph.edges.filter((e) => e.source === nodeId && handleOf(e) === "item");
|
|
489
|
+
if (itemEdges.length === 0) return null;
|
|
490
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
491
|
+
for (const edge of graph.edges) {
|
|
492
|
+
const list = adjacency.get(edge.source) ?? [];
|
|
493
|
+
list.push(edge.target);
|
|
494
|
+
adjacency.set(edge.source, list);
|
|
495
|
+
}
|
|
496
|
+
const done = reachable(
|
|
497
|
+
adjacency,
|
|
498
|
+
graph.edges.filter((e) => e.source === nodeId && handleOf(e) === "done").map((e) => e.target)
|
|
499
|
+
);
|
|
500
|
+
const body = new Set(
|
|
501
|
+
[...reachable(adjacency, itemEdges.map((e) => e.target))].filter(
|
|
502
|
+
(id2) => !done.has(id2) && id2 !== nodeId
|
|
503
|
+
)
|
|
504
|
+
);
|
|
505
|
+
return {
|
|
506
|
+
graph: {
|
|
507
|
+
nodes: graph.nodes.filter((n) => body.has(n.id)),
|
|
508
|
+
edges: graph.edges.filter((e) => body.has(e.source) && body.has(e.target)),
|
|
509
|
+
...graph.inputs === void 0 ? {} : { inputs: graph.inputs }
|
|
510
|
+
},
|
|
511
|
+
entries: itemEdges.filter((e) => body.has(e.target))
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
var forEachExecutor = async (ctx) => {
|
|
515
|
+
const config = configOf(ctx.node);
|
|
516
|
+
const source = resolve(config.source, ctx.inputs);
|
|
474
517
|
let items;
|
|
475
518
|
if (Array.isArray(source)) items = source;
|
|
476
519
|
else if (source === null || source === void 0) items = [];
|
|
477
520
|
else if (typeof source === "object") items = Object.values(source);
|
|
478
521
|
else items = [source];
|
|
479
|
-
|
|
522
|
+
const lane = ctx.graph ? forEachLane(ctx.graph, ctx.node.id) : null;
|
|
523
|
+
if (lane === null || config.mode === "collect") {
|
|
524
|
+
return { items, count: items.length };
|
|
525
|
+
}
|
|
526
|
+
if (lane.graph.nodes.length === 0) {
|
|
527
|
+
ctx.abort(`for_each "${ctx.node.id}" has an item edge but its derived lane is empty`);
|
|
528
|
+
}
|
|
529
|
+
const maxItems = Number(config.maxItems ?? FOR_EACH_DEFAULT_MAX_ITEMS);
|
|
530
|
+
if (!Number.isFinite(maxItems) || maxItems < 1 || maxItems > FOR_EACH_HARD_MAX_ITEMS) {
|
|
531
|
+
ctx.abort(`for_each "${ctx.node.id}" maxItems must be between 1 and ${FOR_EACH_HARD_MAX_ITEMS}`);
|
|
532
|
+
}
|
|
533
|
+
if (items.length > maxItems) {
|
|
534
|
+
ctx.abort(
|
|
535
|
+
`for_each "${ctx.node.id}" resolved ${items.length} items exceeds its maxItems cap of ${maxItems}`
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
const results = [];
|
|
539
|
+
const failures = [];
|
|
540
|
+
for (const [index2, item] of items.entries()) {
|
|
541
|
+
const initialInputs = {};
|
|
542
|
+
for (const edge of lane.entries) {
|
|
543
|
+
initialInputs[edge.target] = {
|
|
544
|
+
...initialInputs[edge.target] ?? {},
|
|
545
|
+
[edge.targetHandle ?? "in"]: item
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
const nested = await runFlow(lane.graph, { ...ctx.executors ?? {} }, () => {
|
|
549
|
+
}, {
|
|
550
|
+
initialInputs,
|
|
551
|
+
depth: (ctx.depth ?? 0) + 1,
|
|
552
|
+
// The index rides on the identity, so a node in iteration 3 cannot share
|
|
553
|
+
// an idempotency key with the same node in iteration 4.
|
|
554
|
+
run: ctx.run?.descend(ctx.node.id, index2)
|
|
555
|
+
});
|
|
556
|
+
if (!nested.ok) {
|
|
557
|
+
const reason = nested.error ?? "unknown error";
|
|
558
|
+
if (decodePause(reason)) ctx.abort(reason);
|
|
559
|
+
results.push(null);
|
|
560
|
+
failures.push({ index: index2, item, error: reason });
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
results.push(nested.outputs);
|
|
564
|
+
}
|
|
565
|
+
return {
|
|
566
|
+
__port: "done",
|
|
567
|
+
value: { items, results, failures, count: items.length }
|
|
568
|
+
};
|
|
480
569
|
};
|
|
481
570
|
var manualTriggerExecutor = (ctx) => ctx.inputs;
|
|
482
571
|
var outputExecutor = (ctx) => {
|
|
@@ -496,6 +585,7 @@ var switchCaseExecutor = (ctx) => {
|
|
|
496
585
|
const config = configOf(ctx.node);
|
|
497
586
|
const inputs = ctx.inputs;
|
|
498
587
|
const expression = config.value;
|
|
588
|
+
validateRoutingExpression(ctx, expression, "switch_case", "value");
|
|
499
589
|
const value = text(resolve(expression, inputs));
|
|
500
590
|
const cases = config.cases ?? {};
|
|
501
591
|
const matched = Object.prototype.hasOwnProperty.call(cases, value);
|
|
@@ -503,6 +593,21 @@ var switchCaseExecutor = (ctx) => {
|
|
|
503
593
|
warnIfUnresolved(ctx, expression, port, "value");
|
|
504
594
|
return { __port: port, value: inputs.in ?? inputs };
|
|
505
595
|
};
|
|
596
|
+
function validateRoutingExpression(ctx, value, kind, field) {
|
|
597
|
+
if (typeof value !== "string" || value.trim() === "") return;
|
|
598
|
+
const bare = value.trim();
|
|
599
|
+
const subject = `${kind} "${ctx.node.id}" ${field} "${bare}"`;
|
|
600
|
+
if (!value.includes("{{")) {
|
|
601
|
+
ctx.abort(`${subject} is not an expression -- wrap it: {{ ${bare} }}`);
|
|
602
|
+
}
|
|
603
|
+
let open = 0;
|
|
604
|
+
for (const [delimiter] of value.matchAll(/\{\{|\}\}/g)) {
|
|
605
|
+
open = delimiter === "{{" ? open + 1 : Math.max(0, open - 1);
|
|
606
|
+
}
|
|
607
|
+
if (open > 0) {
|
|
608
|
+
ctx.abort(`${subject} has an unclosed expression -- close every {{ with }}`);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
506
611
|
|
|
507
612
|
// src/registry/terminal-nodes.ts
|
|
508
613
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
@@ -994,7 +1099,7 @@ var KINDS = [
|
|
|
994
1099
|
key: "condition",
|
|
995
1100
|
label: "Raw expression (advanced)",
|
|
996
1101
|
example: "{{ $json.active && $json.score > 10 }}",
|
|
997
|
-
description: "Escape hatch for logic the builder can't express. Overrides the conditions above when set."
|
|
1102
|
+
description: "Escape hatch for logic the builder can't express. Overrides the conditions above when set. String values must be {{ }}-wrapped expressions; bare strings and unclosed templates abort the run."
|
|
998
1103
|
}
|
|
999
1104
|
]
|
|
1000
1105
|
},
|
|
@@ -1014,7 +1119,7 @@ var KINDS = [
|
|
|
1014
1119
|
// moves the ports on the canvas and the ports the runtime activates.
|
|
1015
1120
|
outputs: (config) => casePorts(config?.cases),
|
|
1016
1121
|
configSchema: [
|
|
1017
|
-
{ type: "expression", key: "value", label: "Switch on", example: "{{ $json.kind }}", required: true },
|
|
1122
|
+
{ type: "expression", key: "value", label: "Switch on", description: "String values must be {{ }}-wrapped expressions; bare strings and unclosed templates abort the run.", example: "{{ $json.kind }}", required: true },
|
|
1018
1123
|
{
|
|
1019
1124
|
type: "keyvalue",
|
|
1020
1125
|
key: "cases",
|
|
@@ -1033,6 +1138,15 @@ var KINDS = [
|
|
|
1033
1138
|
name: "@particle-academy/for_each",
|
|
1034
1139
|
outputShape: [
|
|
1035
1140
|
{ path: "items", type: "array" },
|
|
1141
|
+
// `results` and `failures` are the WIRED shape -- what a lane produces
|
|
1142
|
+
// when the `item` port is connected. Declared unconditionally because a
|
|
1143
|
+
// declaration describes the kind, not one graph's use of it, and because
|
|
1144
|
+
// the shared table requires them: fancy-conformance 0.30.0 added
|
|
1145
|
+
// `results` and 0.31.0 added `failures`, both BREAKING, both so that a
|
|
1146
|
+
// runtime which has not implemented iteration fails here rather than
|
|
1147
|
+
// reporting surface parity it does not have.
|
|
1148
|
+
{ path: "results", type: "array" },
|
|
1149
|
+
{ path: "failures", type: "array" },
|
|
1036
1150
|
{ path: "count", type: "number" }
|
|
1037
1151
|
],
|
|
1038
1152
|
aliases: ["for_each", "@fancy/for_each"],
|
|
@@ -1041,7 +1155,7 @@ var KINDS = [
|
|
|
1041
1155
|
executor: forEachExecutor,
|
|
1042
1156
|
category: "logic",
|
|
1043
1157
|
label: "For Each",
|
|
1044
|
-
description: "
|
|
1158
|
+
description: "Wire `item` to a lane and it runs once per item, aggregating `results` and `failures` on `done`. Leave `item` unwired (or set `mode: collect`) and it just publishes the list and its size -- one node, one checkpoint.",
|
|
1045
1159
|
icon: "\u21BB",
|
|
1046
1160
|
inputs: [{ id: "in" }],
|
|
1047
1161
|
outputs: [{ id: "item", label: "item" }, { id: "done", label: "done" }],
|
|
@@ -2444,6 +2558,9 @@ async function runFlow(graph, executors, onEvent = () => {
|
|
|
2444
2558
|
executors,
|
|
2445
2559
|
depth,
|
|
2446
2560
|
run,
|
|
2561
|
+
// Structural executors derive a nested lane from the graph they are
|
|
2562
|
+
// in; `for_each`'s `item` port cannot be implemented without it.
|
|
2563
|
+
graph,
|
|
2447
2564
|
terminal: terminalAccessorFor(node)
|
|
2448
2565
|
})
|
|
2449
2566
|
);
|