@particle-academy/fancy-flow 0.77.0 → 0.78.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.
Files changed (82) hide show
  1. package/dist/{FlowViewer-Ak8kbY0e.d.cts → FlowViewer-BqYQl2vS.d.cts} +1 -1
  2. package/dist/{FlowViewer-BAV29Zpi.d.ts → FlowViewer-_Fq8AX9V.d.ts} +1 -1
  3. package/dist/{HumanPrompt-xYPCL2jO.d.cts → HumanPrompt-Sl1wD9Bx.d.cts} +2 -2
  4. package/dist/{HumanPrompt-Ge_ccCgS.d.ts → HumanPrompt-_SKIdSpx.d.ts} +2 -2
  5. package/dist/{chunk-MMCHYY6B.js → chunk-3EDB6ELL.js} +3 -3
  6. package/dist/{chunk-MMCHYY6B.js.map → chunk-3EDB6ELL.js.map} +1 -1
  7. package/dist/{chunk-KFC3BURT.js → chunk-4GNDRRJ3.js} +3 -3
  8. package/dist/{chunk-KFC3BURT.js.map → chunk-4GNDRRJ3.js.map} +1 -1
  9. package/dist/{chunk-44VXYZ4M.js → chunk-BBFHGAEN.js} +4 -4
  10. package/dist/{chunk-44VXYZ4M.js.map → chunk-BBFHGAEN.js.map} +1 -1
  11. package/dist/{chunk-OOQ2MMBE.js → chunk-GPFIJR2K.js} +4 -4
  12. package/dist/{chunk-OOQ2MMBE.js.map → chunk-GPFIJR2K.js.map} +1 -1
  13. package/dist/{chunk-YNKOEQLI.js → chunk-J5YUYDMK.js} +106 -6
  14. package/dist/chunk-J5YUYDMK.js.map +1 -0
  15. package/dist/{chunk-X2UHP2S5.js → chunk-S4MOUOG4.js} +3 -3
  16. package/dist/{chunk-X2UHP2S5.js.map → chunk-S4MOUOG4.js.map} +1 -1
  17. package/dist/{chunk-66JAEWPP.js → chunk-XO4ODEY2.js} +3 -3
  18. package/dist/{chunk-66JAEWPP.js.map → chunk-XO4ODEY2.js.map} +1 -1
  19. package/dist/connectors.d.cts +2 -2
  20. package/dist/connectors.d.ts +2 -2
  21. package/dist/durable/index.d.cts +2 -2
  22. package/dist/durable/index.d.ts +2 -2
  23. package/dist/durable.cjs +104 -4
  24. package/dist/durable.cjs.map +1 -1
  25. package/dist/durable.js +1 -1
  26. package/dist/engine.cjs +104 -4
  27. package/dist/engine.cjs.map +1 -1
  28. package/dist/engine.d.cts +6 -6
  29. package/dist/engine.d.ts +6 -6
  30. package/dist/engine.js +4 -4
  31. package/dist/fields/react-fancy.d.cts +3 -3
  32. package/dist/fields/react-fancy.d.ts +3 -3
  33. package/dist/index.cjs +104 -4
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +10 -10
  36. package/dist/index.d.ts +10 -10
  37. package/dist/index.js +12 -12
  38. package/dist/layout/index.d.cts +1 -1
  39. package/dist/layout/index.d.ts +1 -1
  40. package/dist/llm/prism.d.cts +1 -1
  41. package/dist/llm/prism.d.ts +1 -1
  42. package/dist/llm/vercel-ai.d.cts +1 -1
  43. package/dist/llm/vercel-ai.d.ts +1 -1
  44. package/dist/registry/index.d.cts +5 -5
  45. package/dist/registry/index.d.ts +5 -5
  46. package/dist/{registry-JUcN_xWK.d.ts → registry-C4GcH583.d.ts} +1 -1
  47. package/dist/{registry-B6SiTaLZ.d.cts → registry-DWIY3bMP.d.cts} +1 -1
  48. package/dist/registry.cjs +104 -4
  49. package/dist/registry.cjs.map +1 -1
  50. package/dist/registry.js +2 -2
  51. package/dist/{run-cohort-rgT_FX3V.d.ts → run-cohort-DAfhZm-p.d.ts} +2 -2
  52. package/dist/{run-cohort-DNpPa0mq.d.cts → run-cohort-DRJvUWO9.d.cts} +2 -2
  53. package/dist/{run-flow-pW0PllaZ.d.cts → run-flow-Bdrn4lQV.d.cts} +1 -1
  54. package/dist/{run-flow-BLP9rXfO.d.ts → run-flow-D2iOjWsj.d.ts} +1 -1
  55. package/dist/runtime/index.d.cts +5 -5
  56. package/dist/runtime/index.d.ts +5 -5
  57. package/dist/runtime.cjs +104 -4
  58. package/dist/runtime.cjs.map +1 -1
  59. package/dist/runtime.js +3 -3
  60. package/dist/schema/index.d.cts +1 -1
  61. package/dist/schema/index.d.ts +1 -1
  62. package/dist/schema.cjs +104 -4
  63. package/dist/schema.cjs.map +1 -1
  64. package/dist/schema.js +3 -3
  65. package/dist/screens.cjs +104 -4
  66. package/dist/screens.cjs.map +1 -1
  67. package/dist/screens.d.cts +2 -2
  68. package/dist/screens.d.ts +2 -2
  69. package/dist/screens.js +4 -4
  70. package/dist/terminal/fancy-term-host.d.cts +1 -1
  71. package/dist/terminal/fancy-term-host.d.ts +1 -1
  72. package/dist/{types-BdkXxjFh.d.cts → types-B1jftRa9.d.cts} +1 -1
  73. package/dist/{types-CbekKMMO.d.ts → types-D5SBBpbe.d.ts} +1 -1
  74. package/dist/{types-B-Syk9-M.d.cts → types-E48Dpesq.d.cts} +20 -0
  75. package/dist/{types-B-Syk9-M.d.ts → types-E48Dpesq.d.ts} +20 -0
  76. package/dist/ux.cjs +104 -4
  77. package/dist/ux.cjs.map +1 -1
  78. package/dist/ux.d.cts +2 -2
  79. package/dist/ux.d.ts +2 -2
  80. package/dist/ux.js +1 -1
  81. package/package.json +2 -2
  82. package/dist/chunk-YNKOEQLI.js.map +0 -1
package/dist/schema.js CHANGED
@@ -1,6 +1,6 @@
1
- export { WORKFLOW_SCHEMA_URL, WORKFLOW_SCHEMA_VERSION, exportWorkflow, importWorkflow, migrateSchema, workflowToBlob } from './chunk-OOQ2MMBE.js';
2
- import './chunk-MMCHYY6B.js';
3
- import './chunk-YNKOEQLI.js';
1
+ export { WORKFLOW_SCHEMA_URL, WORKFLOW_SCHEMA_VERSION, exportWorkflow, importWorkflow, migrateSchema, workflowToBlob } from './chunk-GPFIJR2K.js';
2
+ import './chunk-3EDB6ELL.js';
3
+ import './chunk-J5YUYDMK.js';
4
4
  import './chunk-2QXKDLGT.js';
5
5
  //# sourceMappingURL=schema.js.map
6
6
  //# sourceMappingURL=schema.js.map
package/dist/screens.cjs CHANGED
@@ -9921,6 +9921,9 @@ async function runFlow(graph, executors, onEvent = () => {
9921
9921
  executors,
9922
9922
  depth,
9923
9923
  run,
9924
+ // Structural executors derive a nested lane from the graph they are
9925
+ // in; `for_each`'s `item` port cannot be implemented without it.
9926
+ graph,
9924
9927
  terminal: terminalAccessorFor(node)
9925
9928
  })
9926
9929
  );
@@ -10409,14 +10412,102 @@ var mergeExecutor = (ctx) => {
10409
10412
  }
10410
10413
  return merged;
10411
10414
  };
10412
- var forEachExecutor = (ctx) => {
10413
- const source = resolve(configOf(ctx.node).source, ctx.inputs);
10415
+ var FOR_EACH_DEFAULT_MAX_ITEMS = 1e3;
10416
+ var FOR_EACH_HARD_MAX_ITEMS = 1e4;
10417
+ function reachable(adjacency, starts) {
10418
+ const seen = /* @__PURE__ */ new Set();
10419
+ const queue = [...starts];
10420
+ for (let cursor = 0; cursor < queue.length; cursor += 1) {
10421
+ const id2 = queue[cursor];
10422
+ if (seen.has(id2)) continue;
10423
+ seen.add(id2);
10424
+ for (const target of adjacency.get(id2) ?? []) queue.push(target);
10425
+ }
10426
+ return seen;
10427
+ }
10428
+ function forEachLane(graph, nodeId) {
10429
+ const handleOf = (edge) => edge.sourceHandle ?? "out";
10430
+ const itemEdges = graph.edges.filter((e) => e.source === nodeId && handleOf(e) === "item");
10431
+ if (itemEdges.length === 0) return null;
10432
+ const adjacency = /* @__PURE__ */ new Map();
10433
+ for (const edge of graph.edges) {
10434
+ const list = adjacency.get(edge.source) ?? [];
10435
+ list.push(edge.target);
10436
+ adjacency.set(edge.source, list);
10437
+ }
10438
+ const done = reachable(
10439
+ adjacency,
10440
+ graph.edges.filter((e) => e.source === nodeId && handleOf(e) === "done").map((e) => e.target)
10441
+ );
10442
+ const body = new Set(
10443
+ [...reachable(adjacency, itemEdges.map((e) => e.target))].filter(
10444
+ (id2) => !done.has(id2) && id2 !== nodeId
10445
+ )
10446
+ );
10447
+ return {
10448
+ graph: {
10449
+ nodes: graph.nodes.filter((n) => body.has(n.id)),
10450
+ edges: graph.edges.filter((e) => body.has(e.source) && body.has(e.target)),
10451
+ ...graph.inputs === void 0 ? {} : { inputs: graph.inputs }
10452
+ },
10453
+ entries: itemEdges.filter((e) => body.has(e.target))
10454
+ };
10455
+ }
10456
+ var forEachExecutor = async (ctx) => {
10457
+ const config = configOf(ctx.node);
10458
+ const source = resolve(config.source, ctx.inputs);
10414
10459
  let items;
10415
10460
  if (Array.isArray(source)) items = source;
10416
10461
  else if (source === null || source === void 0) items = [];
10417
10462
  else if (typeof source === "object") items = Object.values(source);
10418
10463
  else items = [source];
10419
- return { items, count: items.length };
10464
+ const lane = ctx.graph ? forEachLane(ctx.graph, ctx.node.id) : null;
10465
+ if (lane === null || config.mode === "collect") {
10466
+ return { items, count: items.length };
10467
+ }
10468
+ if (lane.graph.nodes.length === 0) {
10469
+ ctx.abort(`for_each "${ctx.node.id}" has an item edge but its derived lane is empty`);
10470
+ }
10471
+ const maxItems = Number(config.maxItems ?? FOR_EACH_DEFAULT_MAX_ITEMS);
10472
+ if (!Number.isFinite(maxItems) || maxItems < 1 || maxItems > FOR_EACH_HARD_MAX_ITEMS) {
10473
+ ctx.abort(`for_each "${ctx.node.id}" maxItems must be between 1 and ${FOR_EACH_HARD_MAX_ITEMS}`);
10474
+ }
10475
+ if (items.length > maxItems) {
10476
+ ctx.abort(
10477
+ `for_each "${ctx.node.id}" resolved ${items.length} items exceeds its maxItems cap of ${maxItems}`
10478
+ );
10479
+ }
10480
+ const results = [];
10481
+ const failures = [];
10482
+ for (const [index2, item] of items.entries()) {
10483
+ const initialInputs = {};
10484
+ for (const edge of lane.entries) {
10485
+ initialInputs[edge.target] = {
10486
+ ...initialInputs[edge.target] ?? {},
10487
+ [edge.targetHandle ?? "in"]: item
10488
+ };
10489
+ }
10490
+ const nested = await runFlow(lane.graph, { ...ctx.executors ?? {} }, () => {
10491
+ }, {
10492
+ initialInputs,
10493
+ depth: (ctx.depth ?? 0) + 1,
10494
+ // The index rides on the identity, so a node in iteration 3 cannot share
10495
+ // an idempotency key with the same node in iteration 4.
10496
+ run: ctx.run?.descend(ctx.node.id, index2)
10497
+ });
10498
+ if (!nested.ok) {
10499
+ const reason = nested.error ?? "unknown error";
10500
+ if (decodePause(reason)) ctx.abort(reason);
10501
+ results.push(null);
10502
+ failures.push({ index: index2, item, error: reason });
10503
+ continue;
10504
+ }
10505
+ results.push(nested.outputs);
10506
+ }
10507
+ return {
10508
+ __port: "done",
10509
+ value: { items, results, failures, count: items.length }
10510
+ };
10420
10511
  };
10421
10512
  var manualTriggerExecutor = (ctx) => ctx.inputs;
10422
10513
  var outputExecutor = (ctx) => {
@@ -10973,6 +11064,15 @@ var KINDS = [
10973
11064
  name: "@particle-academy/for_each",
10974
11065
  outputShape: [
10975
11066
  { path: "items", type: "array" },
11067
+ // `results` and `failures` are the WIRED shape -- what a lane produces
11068
+ // when the `item` port is connected. Declared unconditionally because a
11069
+ // declaration describes the kind, not one graph's use of it, and because
11070
+ // the shared table requires them: fancy-conformance 0.30.0 added
11071
+ // `results` and 0.31.0 added `failures`, both BREAKING, both so that a
11072
+ // runtime which has not implemented iteration fails here rather than
11073
+ // reporting surface parity it does not have.
11074
+ { path: "results", type: "array" },
11075
+ { path: "failures", type: "array" },
10976
11076
  { path: "count", type: "number" }
10977
11077
  ],
10978
11078
  aliases: ["for_each", "@fancy/for_each"],
@@ -10981,7 +11081,7 @@ var KINDS = [
10981
11081
  executor: forEachExecutor,
10982
11082
  category: "logic",
10983
11083
  label: "For Each",
10984
- description: "Iterate over a list, emitting each item on `item`.",
11084
+ 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.",
10985
11085
  icon: "\u21BB",
10986
11086
  inputs: [{ id: "in" }],
10987
11087
  outputs: [{ id: "item", label: "item" }, { id: "done", label: "done" }],