@particle-academy/fancy-flow 0.71.0 → 0.72.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 (43) hide show
  1. package/dist/{chunk-3L47KJ6Q.js → chunk-57QTX3S3.js} +3 -3
  2. package/dist/{chunk-3L47KJ6Q.js.map → chunk-57QTX3S3.js.map} +1 -1
  3. package/dist/{chunk-KQCX6KN7.js → chunk-6TC44VCY.js} +3 -3
  4. package/dist/{chunk-KQCX6KN7.js.map → chunk-6TC44VCY.js.map} +1 -1
  5. package/dist/{chunk-EVGSL2EM.js → chunk-C5K2DSZB.js} +157 -148
  6. package/dist/chunk-C5K2DSZB.js.map +1 -0
  7. package/dist/{chunk-D2OBU3CE.js → chunk-E3U3MBKI.js} +3 -3
  8. package/dist/{chunk-D2OBU3CE.js.map → chunk-E3U3MBKI.js.map} +1 -1
  9. package/dist/{chunk-FPWJYSXX.js → chunk-R3GQ72WA.js} +4 -4
  10. package/dist/{chunk-FPWJYSXX.js.map → chunk-R3GQ72WA.js.map} +1 -1
  11. package/dist/{chunk-PNTDTSMR.js → chunk-RQP666FB.js} +4 -4
  12. package/dist/{chunk-PNTDTSMR.js.map → chunk-RQP666FB.js.map} +1 -1
  13. package/dist/{chunk-XI4AZD2S.js → chunk-ZEDBF2V6.js} +3 -3
  14. package/dist/{chunk-XI4AZD2S.js.map → chunk-ZEDBF2V6.js.map} +1 -1
  15. package/dist/durable/index.d.cts +45 -4
  16. package/dist/durable/index.d.ts +45 -4
  17. package/dist/durable.cjs +137 -72
  18. package/dist/durable.cjs.map +1 -1
  19. package/dist/durable.js +61 -5
  20. package/dist/durable.js.map +1 -1
  21. package/dist/engine.cjs +77 -68
  22. package/dist/engine.cjs.map +1 -1
  23. package/dist/engine.js +4 -4
  24. package/dist/index.cjs +123 -114
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.js +12 -12
  27. package/dist/registry.cjs +77 -68
  28. package/dist/registry.cjs.map +1 -1
  29. package/dist/registry.js +2 -2
  30. package/dist/runtime.cjs +77 -68
  31. package/dist/runtime.cjs.map +1 -1
  32. package/dist/runtime.js +3 -3
  33. package/dist/schema.cjs +77 -68
  34. package/dist/schema.cjs.map +1 -1
  35. package/dist/schema.js +3 -3
  36. package/dist/screens.cjs +77 -68
  37. package/dist/screens.cjs.map +1 -1
  38. package/dist/screens.js +4 -4
  39. package/dist/ux.cjs +77 -68
  40. package/dist/ux.cjs.map +1 -1
  41. package/dist/ux.js +1 -1
  42. package/package.json +1 -1
  43. package/dist/chunk-EVGSL2EM.js.map +0 -1
@@ -71,101 +71,6 @@ function resolveNodePorts(node, kind) {
71
71
  };
72
72
  }
73
73
 
74
- // src/components/FlowEditor/human-fields.ts
75
- var HUMAN_FIELD_TYPE_ALIASES = {
76
- text: "text",
77
- string: "text",
78
- str: "text",
79
- input: "text",
80
- textarea: "textarea",
81
- long_text: "textarea",
82
- longtext: "textarea",
83
- "long-text": "textarea",
84
- multiline: "textarea",
85
- paragraph: "textarea",
86
- markdown: "textarea",
87
- number: "number",
88
- numeric: "number",
89
- integer: "number",
90
- int: "number",
91
- float: "number",
92
- decimal: "number",
93
- select: "select",
94
- enum: "select",
95
- choice: "select",
96
- choices: "select",
97
- dropdown: "select",
98
- options: "select",
99
- radio: "select",
100
- switch: "switch",
101
- bool: "switch",
102
- boolean: "switch",
103
- checkbox: "switch",
104
- toggle: "switch",
105
- date: "date",
106
- datetime: "datetime",
107
- "datetime-local": "datetime",
108
- datetimelocal: "datetime",
109
- timestamp: "datetime",
110
- time: "time",
111
- email: "email",
112
- "e-mail": "email",
113
- url: "url",
114
- uri: "url",
115
- link: "url",
116
- tel: "tel",
117
- phone: "tel",
118
- telephone: "tel",
119
- password: "password",
120
- secret: "password"
121
- };
122
- function humanFieldType(raw) {
123
- if (typeof raw !== "string") return "text";
124
- return HUMAN_FIELD_TYPE_ALIASES[raw.trim().toLowerCase()] ?? "text";
125
- }
126
- function humanFieldOptions(raw) {
127
- const entries = [];
128
- if (Array.isArray(raw)) {
129
- for (const item of raw) {
130
- if (typeof item === "string" || typeof item === "number") {
131
- const value = String(item);
132
- if (value !== "") entries.push({ value, label: value });
133
- continue;
134
- }
135
- if (item && typeof item === "object") {
136
- const value = item.value;
137
- if (value === void 0 || value === null || value === "") continue;
138
- const label = item.label;
139
- entries.push({
140
- value: String(value),
141
- label: typeof label === "string" && label !== "" ? label : String(value)
142
- });
143
- }
144
- }
145
- } else if (raw && typeof raw === "object") {
146
- for (const [value, label] of Object.entries(raw)) {
147
- if (value === "") continue;
148
- entries.push({ value, label: typeof label === "string" && label !== "" ? label : value });
149
- }
150
- }
151
- return entries.length ? entries : void 0;
152
- }
153
- function humanInputFields(config) {
154
- const raw = Array.isArray(config?.fields) ? config.fields : [];
155
- const fields = raw.filter((f) => f && typeof f === "object" && typeof f.key === "string" && f.key).map((f) => ({
156
- key: f.key,
157
- label: typeof f.label === "string" && f.label ? f.label : f.key,
158
- type: humanFieldType(f.type),
159
- required: !!f.required,
160
- placeholder: typeof f.placeholder === "string" ? f.placeholder : void 0,
161
- options: humanFieldOptions(f.options ?? f.choices),
162
- default: f.default
163
- }));
164
- if (fields.length) return fields;
165
- const title = typeof config?.title === "string" && config.title ? config.title : "Your answer";
166
- return [{ key: "value", label: title, type: "textarea", required: true }];
167
- }
168
-
169
74
  // src/runtime/run-identity.ts
170
75
  function escapeSegment(value) {
171
76
  return value.replace(/%/g, "%25").replace(/\//g, "%2F").replace(/#/g, "%23");
@@ -276,6 +181,101 @@ var RunIdentity = class _RunIdentity {
276
181
  }
277
182
  };
278
183
 
184
+ // src/components/FlowEditor/human-fields.ts
185
+ var HUMAN_FIELD_TYPE_ALIASES = {
186
+ text: "text",
187
+ string: "text",
188
+ str: "text",
189
+ input: "text",
190
+ textarea: "textarea",
191
+ long_text: "textarea",
192
+ longtext: "textarea",
193
+ "long-text": "textarea",
194
+ multiline: "textarea",
195
+ paragraph: "textarea",
196
+ markdown: "textarea",
197
+ number: "number",
198
+ numeric: "number",
199
+ integer: "number",
200
+ int: "number",
201
+ float: "number",
202
+ decimal: "number",
203
+ select: "select",
204
+ enum: "select",
205
+ choice: "select",
206
+ choices: "select",
207
+ dropdown: "select",
208
+ options: "select",
209
+ radio: "select",
210
+ switch: "switch",
211
+ bool: "switch",
212
+ boolean: "switch",
213
+ checkbox: "switch",
214
+ toggle: "switch",
215
+ date: "date",
216
+ datetime: "datetime",
217
+ "datetime-local": "datetime",
218
+ datetimelocal: "datetime",
219
+ timestamp: "datetime",
220
+ time: "time",
221
+ email: "email",
222
+ "e-mail": "email",
223
+ url: "url",
224
+ uri: "url",
225
+ link: "url",
226
+ tel: "tel",
227
+ phone: "tel",
228
+ telephone: "tel",
229
+ password: "password",
230
+ secret: "password"
231
+ };
232
+ function humanFieldType(raw) {
233
+ if (typeof raw !== "string") return "text";
234
+ return HUMAN_FIELD_TYPE_ALIASES[raw.trim().toLowerCase()] ?? "text";
235
+ }
236
+ function humanFieldOptions(raw) {
237
+ const entries = [];
238
+ if (Array.isArray(raw)) {
239
+ for (const item of raw) {
240
+ if (typeof item === "string" || typeof item === "number") {
241
+ const value = String(item);
242
+ if (value !== "") entries.push({ value, label: value });
243
+ continue;
244
+ }
245
+ if (item && typeof item === "object") {
246
+ const value = item.value;
247
+ if (value === void 0 || value === null || value === "") continue;
248
+ const label = item.label;
249
+ entries.push({
250
+ value: String(value),
251
+ label: typeof label === "string" && label !== "" ? label : String(value)
252
+ });
253
+ }
254
+ }
255
+ } else if (raw && typeof raw === "object") {
256
+ for (const [value, label] of Object.entries(raw)) {
257
+ if (value === "") continue;
258
+ entries.push({ value, label: typeof label === "string" && label !== "" ? label : value });
259
+ }
260
+ }
261
+ return entries.length ? entries : void 0;
262
+ }
263
+ function humanInputFields(config) {
264
+ const raw = Array.isArray(config?.fields) ? config.fields : [];
265
+ const fields = raw.filter((f) => f && typeof f === "object" && typeof f.key === "string" && f.key).map((f) => ({
266
+ key: f.key,
267
+ label: typeof f.label === "string" && f.label ? f.label : f.key,
268
+ type: humanFieldType(f.type),
269
+ required: !!f.required,
270
+ placeholder: typeof f.placeholder === "string" ? f.placeholder : void 0,
271
+ options: humanFieldOptions(f.options ?? f.choices),
272
+ default: f.default
273
+ }));
274
+ if (fields.length) return fields;
275
+ const title = typeof config?.title === "string" && config.title ? config.title : "Your answer";
276
+ return [{ key: "value", label: title, type: "textarea", required: true }];
277
+ }
278
+
279
279
  // src/runtime/terminal-transcript.ts
280
280
  var ESC = String.fromCharCode(27);
281
281
  var CSI = String.fromCharCode(155);
@@ -519,6 +519,63 @@ function specForLane(lane) {
519
519
  };
520
520
  }
521
521
 
522
+ // src/runtime/undelivered-edges.ts
523
+ function undeliveredEdgeWarnings(target, incoming, portValues, completed, nodesById) {
524
+ const events = [];
525
+ for (const e of incoming) {
526
+ const handle = e.sourceHandle ?? "out";
527
+ if (portValues.has(`${e.source}:${handle}`) || !completed.has(e.source)) continue;
528
+ if (possiblePortIds(nodesById.get(e.source)).includes(handle)) continue;
529
+ events.push({
530
+ type: "log",
531
+ nodeId: target.id,
532
+ level: "warn",
533
+ message: undeliveredEdgeMessage(e, target, portValues, nodesById),
534
+ detail: { edge: e.id, source: e.source, sourceHandle: handle }
535
+ });
536
+ }
537
+ return events;
538
+ }
539
+ function possiblePortIds(node) {
540
+ if (!node) return ["out"];
541
+ const own = node.data?.outputs;
542
+ if (Array.isArray(own)) return own.map((p) => p.id);
543
+ const kind = getNodeKind(node.data?.kind ?? node.type ?? "");
544
+ if (!kind) return ["out"];
545
+ const config = nodeConfig(node);
546
+ const representative = typeof kind.outputs === "function" && !configDeclaresPorts(kind.name, config);
547
+ const ids = (resolvePortSpec(kind.outputs, representative ? defaultConfigFor(kind) : config) ?? []).map((p) => p.id);
548
+ return ids.length > 0 ? ids : ["out"];
549
+ }
550
+ function configDeclaresPorts(kindName, config) {
551
+ const bare = kindName.startsWith("@") ? kindName.slice(kindName.lastIndexOf("/") + 1) : kindName;
552
+ if (bare === "switch_case") {
553
+ const cases = config.cases;
554
+ return !!cases && typeof cases === "object" && Object.values(cases).some((port) => typeof port === "string" && port !== "");
555
+ }
556
+ if (bare === "llm_router") {
557
+ const routes = config.routes;
558
+ return Array.isArray(routes) && routes.some((route) => route?.port != null && route.port !== "");
559
+ }
560
+ return true;
561
+ }
562
+ function undeliveredEdgeMessage(edge, target, portValues, nodesById) {
563
+ const handle = edge.sourceHandle ?? "out";
564
+ const prefix = `${edge.source}:`;
565
+ const available = [];
566
+ for (const key of portValues.keys()) {
567
+ if (key.startsWith(prefix)) available.push(key.slice(prefix.length));
568
+ }
569
+ 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.`;
570
+ if (available.length > 0) message += ` Available: ${available.join(", ")}.`;
571
+ const source = nodesById.get(edge.source);
572
+ if (source && outputFieldsFor(source).some((field) => field?.path === handle)) {
573
+ 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.`;
574
+ }
575
+ if (edge.sourceHandle != null) message += " Leave sourceHandle off to read the node's output.";
576
+ return message;
577
+ }
578
+
522
579
  // src/runtime/workflow-props.ts
523
580
  function typeOf(value) {
524
581
  if (value === null) return "null";
@@ -640,17 +697,8 @@ async function runFlow(graph, executors, onEvent = () => {
640
697
  onEvent({ type: "node-status", nodeId: node.id, status: "idle", text: "skipped" });
641
698
  continue;
642
699
  }
643
- for (const e of incoming) {
644
- const handle = e.sourceHandle ?? "out";
645
- if (portValues.has(`${e.source}:${handle}`) || !completed.has(e.source)) continue;
646
- if (possiblePortIds(nodesById.get(e.source)).includes(handle)) continue;
647
- onEvent({
648
- type: "log",
649
- nodeId: node.id,
650
- level: "warn",
651
- message: undeliveredEdgeMessage(e, node, portValues, nodesById),
652
- detail: { edge: e.id, source: e.source, sourceHandle: handle }
653
- });
700
+ for (const warning of undeliveredEdgeWarnings(node, incoming, portValues, completed, nodesById)) {
701
+ onEvent(warning);
654
702
  }
655
703
  if (incoming.length > 0) {
656
704
  const anyActive = incoming.some((e) => portValues.has(`${e.source}:${e.sourceHandle ?? "out"}`));
@@ -814,45 +862,6 @@ function activatedPorts(node, result) {
814
862
  const declared = resolveNodePorts(node, kind).outputs?.map((p) => p.id);
815
863
  return { ports: declared?.length ? declared : ["out"], value: result };
816
864
  }
817
- function possiblePortIds(node) {
818
- if (!node) return ["out"];
819
- const own = node.data?.outputs;
820
- if (Array.isArray(own)) return own.map((p) => p.id);
821
- const kind = getNodeKind(node.data?.kind ?? node.type ?? "");
822
- if (!kind) return ["out"];
823
- const config = nodeConfig(node);
824
- const representative = typeof kind.outputs === "function" && !configDeclaresPorts(kind.name, config);
825
- const ids = (resolvePortSpec(kind.outputs, representative ? defaultConfigFor(kind) : config) ?? []).map((p) => p.id);
826
- return ids.length > 0 ? ids : ["out"];
827
- }
828
- function configDeclaresPorts(kindName, config) {
829
- const bare = kindName.startsWith("@") ? kindName.slice(kindName.lastIndexOf("/") + 1) : kindName;
830
- if (bare === "switch_case") {
831
- const cases = config.cases;
832
- return !!cases && typeof cases === "object" && Object.values(cases).some((port) => typeof port === "string" && port !== "");
833
- }
834
- if (bare === "llm_router") {
835
- const routes = config.routes;
836
- return Array.isArray(routes) && routes.some((route) => route?.port != null && route.port !== "");
837
- }
838
- return true;
839
- }
840
- function undeliveredEdgeMessage(edge, target, portValues, nodesById) {
841
- const handle = edge.sourceHandle ?? "out";
842
- const prefix = `${edge.source}:`;
843
- const available = [];
844
- for (const key of portValues.keys()) {
845
- if (key.startsWith(prefix)) available.push(key.slice(prefix.length));
846
- }
847
- 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.`;
848
- if (available.length > 0) message += ` Available: ${available.join(", ")}.`;
849
- const source = nodesById.get(edge.source);
850
- if (source && outputFieldsFor(source).some((field) => field?.path === handle)) {
851
- 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.`;
852
- }
853
- if (edge.sourceHandle != null) message += " Leave sourceHandle off to read the node's output.";
854
- return message;
855
- }
856
865
  function announce(onEvent, node, phase) {
857
866
  const data = node.data;
858
867
  const raw = phase === "start" ? data?.startingMsg : data?.stoppingMsg;
@@ -2829,6 +2838,6 @@ function describeExpressionGrammar() {
2829
2838
  };
2830
2839
  }
2831
2840
 
2832
- export { BUILTIN_KIND_DATA, DEFAULT_MAX_DEPTH, RunIdentity, UnresolvedPathError, applyKindSchemaOverlay, availableVariables, baseVariables, categoryAccent, clearKindSchemaOverlays, clearNodeKindOverrides, declaredRoutes, defaultConfigFor, describeExpressionGrammar, ensureBuiltinKinds, escapeSegment, evaluateConfig, evaluateExpression, getNodeKind, humanInputFields, kindIds, listNodeKinds, llmRouterExecutor, nodeConfig, onNodeKindsChanged, outputFieldsFor, overrideNodeKind, registerBuiltinKindInternal, registerNodeKind, resolveFallbackPort, resolveKindId, resolveNodePorts, resolvePath, resolvePortSpec, runFlow, subflowExecutor, subflowMode, subflowPorts, text, truthy, tryResolvePath, unregisterNodeKind, validateConfig };
2833
- //# sourceMappingURL=chunk-EVGSL2EM.js.map
2834
- //# sourceMappingURL=chunk-EVGSL2EM.js.map
2841
+ export { BUILTIN_KIND_DATA, DEFAULT_MAX_DEPTH, RunIdentity, UnresolvedPathError, applyKindSchemaOverlay, availableVariables, baseVariables, categoryAccent, clearKindSchemaOverlays, clearNodeKindOverrides, declaredRoutes, defaultConfigFor, describeExpressionGrammar, ensureBuiltinKinds, escapeSegment, evaluateConfig, evaluateExpression, getNodeKind, humanInputFields, kindIds, listNodeKinds, llmRouterExecutor, nodeConfig, onNodeKindsChanged, outputFieldsFor, overrideNodeKind, registerBuiltinKindInternal, registerNodeKind, resolveFallbackPort, resolveKindId, resolveNodePorts, resolvePath, resolvePortSpec, runFlow, subflowExecutor, subflowMode, subflowPorts, text, truthy, tryResolvePath, undeliveredEdgeWarnings, unregisterNodeKind, validateConfig };
2842
+ //# sourceMappingURL=chunk-C5K2DSZB.js.map
2843
+ //# sourceMappingURL=chunk-C5K2DSZB.js.map