@particle-academy/fancy-flow 0.48.1 → 0.49.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 (83) hide show
  1. package/dist/{ConfigFieldRenderer-NuDjtun1.d.cts → ConfigFieldRenderer-CrXFq6Eb.d.cts} +2 -2
  2. package/dist/{ConfigFieldRenderer-DrD2-Qml.d.ts → ConfigFieldRenderer-u3nYHovX.d.ts} +2 -2
  3. package/dist/{FlowViewer-CY3_vHSg.d.cts → FlowViewer-CFSMlCqi.d.cts} +1 -1
  4. package/dist/{FlowViewer-DGW6t-80.d.ts → FlowViewer-DRgjeWJ7.d.ts} +1 -1
  5. package/dist/{capabilities-DMUhnyZD.d.ts → capabilities-B00VXLUp.d.ts} +1 -1
  6. package/dist/{capabilities-Dmd26aAs.d.cts → capabilities-VzgDApur.d.cts} +1 -1
  7. package/dist/{chunk-M7H3ASBI.js → chunk-6FP3F5YR.js} +17 -3
  8. package/dist/chunk-6FP3F5YR.js.map +1 -0
  9. package/dist/{chunk-HHGU7JXJ.js → chunk-6XKR65XM.js} +3 -3
  10. package/dist/{chunk-HHGU7JXJ.js.map → chunk-6XKR65XM.js.map} +1 -1
  11. package/dist/{chunk-FCCGV52I.js → chunk-AVRGZFXG.js} +4 -4
  12. package/dist/{chunk-FCCGV52I.js.map → chunk-AVRGZFXG.js.map} +1 -1
  13. package/dist/{chunk-6HGXAU5L.js → chunk-UL3DGSSG.js} +9 -4
  14. package/dist/chunk-UL3DGSSG.js.map +1 -0
  15. package/dist/{chunk-54SN6LML.js → chunk-VUL7CUFW.js} +3 -3
  16. package/dist/{chunk-54SN6LML.js.map → chunk-VUL7CUFW.js.map} +1 -1
  17. package/dist/{chunk-ACGCHWCM.js → chunk-YOK3WKWC.js} +7 -3
  18. package/dist/chunk-YOK3WKWC.js.map +1 -0
  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 +15 -1
  24. package/dist/durable.cjs.map +1 -1
  25. package/dist/durable.js +1 -1
  26. package/dist/engine.cjs +15 -1
  27. package/dist/engine.cjs.map +1 -1
  28. package/dist/engine.d.cts +7 -7
  29. package/dist/engine.d.ts +7 -7
  30. package/dist/engine.js +3 -3
  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 +56 -2
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +11 -11
  36. package/dist/index.d.ts +11 -11
  37. package/dist/index.js +42 -11
  38. package/dist/index.js.map +1 -1
  39. package/dist/layout/index.d.cts +1 -1
  40. package/dist/layout/index.d.ts +1 -1
  41. package/dist/llm/prism.d.cts +2 -2
  42. package/dist/llm/prism.d.ts +2 -2
  43. package/dist/llm/vercel-ai.d.cts +2 -2
  44. package/dist/llm/vercel-ai.d.ts +2 -2
  45. package/dist/registry/index.d.cts +6 -6
  46. package/dist/registry/index.d.ts +6 -6
  47. package/dist/{registry-DpARG95T.d.ts → registry-6cB5wCv6.d.ts} +1 -1
  48. package/dist/{registry-BnnifM-t.d.cts → registry-DQh7ZmnM.d.cts} +1 -1
  49. package/dist/registry.cjs +15 -1
  50. package/dist/registry.cjs.map +1 -1
  51. package/dist/registry.js +2 -2
  52. package/dist/{run-cohort-DdPPowJ3.d.cts → run-cohort-DYCL8Qv6.d.cts} +2 -2
  53. package/dist/{run-cohort-Cyeny2Uu.d.ts → run-cohort-VX4JG21l.d.ts} +2 -2
  54. package/dist/{run-flow-1KiXhy59.d.cts → run-flow-B24QUO1H.d.cts} +1 -1
  55. package/dist/{run-flow-CQvTDBYk.d.ts → run-flow-DPUPAWk6.d.ts} +1 -1
  56. package/dist/runtime/index.d.cts +18 -6
  57. package/dist/runtime/index.d.ts +18 -6
  58. package/dist/runtime.cjs +21 -2
  59. package/dist/runtime.cjs.map +1 -1
  60. package/dist/runtime.js +3 -3
  61. package/dist/schema/index.d.cts +9 -1
  62. package/dist/schema/index.d.ts +9 -1
  63. package/dist/schema.cjs +19 -1
  64. package/dist/schema.cjs.map +1 -1
  65. package/dist/schema.js +2 -2
  66. package/dist/screens.cjs +15 -1
  67. package/dist/screens.cjs.map +1 -1
  68. package/dist/screens.d.cts +2 -2
  69. package/dist/screens.d.ts +2 -2
  70. package/dist/screens.js +4 -4
  71. package/dist/{types-Jx1TwehV.d.cts → types-7cXcSQlx.d.cts} +50 -0
  72. package/dist/{types-Jx1TwehV.d.ts → types-7cXcSQlx.d.ts} +50 -0
  73. package/dist/{types-BO8TgI2M.d.cts → types-BtMOnb9I.d.cts} +1 -1
  74. package/dist/{types-DJAmfiJC.d.ts → types-CDgIIj4c.d.ts} +1 -1
  75. package/dist/ux.cjs +15 -1
  76. package/dist/ux.cjs.map +1 -1
  77. package/dist/ux.d.cts +2 -2
  78. package/dist/ux.d.ts +2 -2
  79. package/dist/ux.js +1 -1
  80. package/package.json +1 -1
  81. package/dist/chunk-6HGXAU5L.js.map +0 -1
  82. package/dist/chunk-ACGCHWCM.js.map +0 -1
  83. package/dist/chunk-M7H3ASBI.js.map +0 -1
package/dist/engine.d.cts CHANGED
@@ -1,12 +1,12 @@
1
- export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-1KiXhy59.cjs';
2
- import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-Jx1TwehV.cjs';
3
- export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, d as FlowEdge, a as FlowNode, e as FlowNodeData, f as FlowNodeKind, g as NodeRunStatus, h as NoteNodeData, O as OutputNodeData, P as PortDescriptor, b as RunIdentity, c as RunIdentityJson, S as SubgraphNodeData, T as TriggerNodeData, i as escapeSegment } from './types-Jx1TwehV.cjs';
4
- export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from './run-cohort-DdPPowJ3.cjs';
5
- export { d as defaultConfigFor, g as getNodeKind, k as kindIds, l as listNodeKinds, r as registerNodeKind, a as resolveKindId, v as validateConfig } from './registry-BnnifM-t.cjs';
6
- export { b as CapabilityRequirement, C as ConfigField, M as ManifestProblem, c as ManifestValidation, d as NODE_MANIFEST_SCHEMA_VERSION, a as NodeCategory, N as NodeKindDefinition, e as NodePackageManifest, f as NodeRuntimeId, g as NodeRuntimeSpec, O as OutputField, h as OutputShape, P as PortSpec, S as SideEffects, i as checkCapabilities, j as checkRuntimeSupport, s as satisfiesRange, v as validateNodeManifest } from './types-BO8TgI2M.cjs';
1
+ export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-B24QUO1H.cjs';
2
+ import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-7cXcSQlx.cjs';
3
+ export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, d as FlowEdge, a as FlowNode, e as FlowNodeData, f as FlowNodeKind, g as NodeRunStatus, h as NoteNodeData, O as OutputNodeData, P as PortDescriptor, b as RunIdentity, c as RunIdentityJson, S as SubgraphNodeData, T as TriggerNodeData, i as escapeSegment } from './types-7cXcSQlx.cjs';
4
+ export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from './run-cohort-DYCL8Qv6.cjs';
5
+ export { d as defaultConfigFor, g as getNodeKind, k as kindIds, l as listNodeKinds, r as registerNodeKind, a as resolveKindId, v as validateConfig } from './registry-DQh7ZmnM.cjs';
6
+ export { b as CapabilityRequirement, C as ConfigField, M as ManifestProblem, c as ManifestValidation, d as NODE_MANIFEST_SCHEMA_VERSION, a as NodeCategory, N as NodeKindDefinition, e as NodePackageManifest, f as NodeRuntimeId, g as NodeRuntimeSpec, O as OutputField, h as OutputShape, P as PortSpec, S as SideEffects, i as checkCapabilities, j as checkRuntimeSupport, s as satisfiesRange, v as validateNodeManifest } from './types-BtMOnb9I.cjs';
7
7
  import { P as PauseAwaiting } from './pause-9iT4tCEV.cjs';
8
8
  export { L as LEGACY_PAUSE_PREFIXES, a as PAUSE_PREFIX, b as PauseSignal, d as decodePause, e as encodePause, i as isPause, p as pauseForHuman } from './pause-9iT4tCEV.cjs';
9
- import { W as WorkflowResolver } from './capabilities-Dmd26aAs.cjs';
9
+ import { W as WorkflowResolver } from './capabilities-VzgDApur.cjs';
10
10
  import '@xyflow/react';
11
11
  import 'react';
12
12
 
package/dist/engine.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-CQvTDBYk.js';
2
- import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-Jx1TwehV.js';
3
- export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, d as FlowEdge, a as FlowNode, e as FlowNodeData, f as FlowNodeKind, g as NodeRunStatus, h as NoteNodeData, O as OutputNodeData, P as PortDescriptor, b as RunIdentity, c as RunIdentityJson, S as SubgraphNodeData, T as TriggerNodeData, i as escapeSegment } from './types-Jx1TwehV.js';
4
- export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from './run-cohort-Cyeny2Uu.js';
5
- export { d as defaultConfigFor, g as getNodeKind, k as kindIds, l as listNodeKinds, r as registerNodeKind, a as resolveKindId, v as validateConfig } from './registry-DpARG95T.js';
6
- export { b as CapabilityRequirement, C as ConfigField, M as ManifestProblem, c as ManifestValidation, d as NODE_MANIFEST_SCHEMA_VERSION, a as NodeCategory, N as NodeKindDefinition, e as NodePackageManifest, f as NodeRuntimeId, g as NodeRuntimeSpec, O as OutputField, h as OutputShape, P as PortSpec, S as SideEffects, i as checkCapabilities, j as checkRuntimeSupport, s as satisfiesRange, v as validateNodeManifest } from './types-DJAmfiJC.js';
1
+ export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-DPUPAWk6.js';
2
+ import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-7cXcSQlx.js';
3
+ export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, d as FlowEdge, a as FlowNode, e as FlowNodeData, f as FlowNodeKind, g as NodeRunStatus, h as NoteNodeData, O as OutputNodeData, P as PortDescriptor, b as RunIdentity, c as RunIdentityJson, S as SubgraphNodeData, T as TriggerNodeData, i as escapeSegment } from './types-7cXcSQlx.js';
4
+ export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from './run-cohort-VX4JG21l.js';
5
+ export { d as defaultConfigFor, g as getNodeKind, k as kindIds, l as listNodeKinds, r as registerNodeKind, a as resolveKindId, v as validateConfig } from './registry-6cB5wCv6.js';
6
+ export { b as CapabilityRequirement, C as ConfigField, M as ManifestProblem, c as ManifestValidation, d as NODE_MANIFEST_SCHEMA_VERSION, a as NodeCategory, N as NodeKindDefinition, e as NodePackageManifest, f as NodeRuntimeId, g as NodeRuntimeSpec, O as OutputField, h as OutputShape, P as PortSpec, S as SideEffects, i as checkCapabilities, j as checkRuntimeSupport, s as satisfiesRange, v as validateNodeManifest } from './types-CDgIIj4c.js';
7
7
  import { P as PauseAwaiting } from './pause-9iT4tCEV.js';
8
8
  export { L as LEGACY_PAUSE_PREFIXES, a as PAUSE_PREFIX, b as PauseSignal, d as decodePause, e as encodePause, i as isPause, p as pauseForHuman } from './pause-9iT4tCEV.js';
9
- import { W as WorkflowResolver } from './capabilities-DMUhnyZD.js';
9
+ import { W as WorkflowResolver } from './capabilities-B00VXLUp.js';
10
10
  import '@xyflow/react';
11
11
  import 'react';
12
12
 
package/dist/engine.js CHANGED
@@ -1,8 +1,8 @@
1
- export { runCohort } from './chunk-54SN6LML.js';
1
+ export { runCohort } from './chunk-VUL7CUFW.js';
2
2
  import { decodePause } from './chunk-UEOE6B52.js';
3
3
  export { LEGACY_PAUSE_PREFIXES, PAUSE_PREFIX, decodePause, encodePause, isPause, pauseForHuman } from './chunk-UEOE6B52.js';
4
- import { runFlow, getNodeKind, resolveNodePorts } from './chunk-M7H3ASBI.js';
5
- export { RunIdentity, defaultConfigFor, escapeSegment, getNodeKind, kindIds, listNodeKinds, registerNodeKind, resolveKindId, runFlow, validateConfig } from './chunk-M7H3ASBI.js';
4
+ import { runFlow, getNodeKind, resolveNodePorts } from './chunk-6FP3F5YR.js';
5
+ export { RunIdentity, defaultConfigFor, escapeSegment, getNodeKind, kindIds, listNodeKinds, registerNodeKind, resolveKindId, runFlow, validateConfig } from './chunk-6FP3F5YR.js';
6
6
  import './chunk-F5RPRB7A.js';
7
7
  import { isResolutionFailure, registerLlmClient, registerWorkflowResolver } from './chunk-USL4FMFU.js';
8
8
 
@@ -1,8 +1,8 @@
1
- import { C as ConfigFieldRenderFn } from '../ConfigFieldRenderer-NuDjtun1.cjs';
1
+ import { C as ConfigFieldRenderFn } from '../ConfigFieldRenderer-CrXFq6Eb.cjs';
2
2
  import 'react';
3
- import '../types-Jx1TwehV.cjs';
3
+ import '../types-7cXcSQlx.cjs';
4
4
  import '@xyflow/react';
5
- import '../types-BO8TgI2M.cjs';
5
+ import '../types-BtMOnb9I.cjs';
6
6
  import '../pause-9iT4tCEV.cjs';
7
7
 
8
8
  /**
@@ -1,8 +1,8 @@
1
- import { C as ConfigFieldRenderFn } from '../ConfigFieldRenderer-DrD2-Qml.js';
1
+ import { C as ConfigFieldRenderFn } from '../ConfigFieldRenderer-u3nYHovX.js';
2
2
  import 'react';
3
- import '../types-Jx1TwehV.js';
3
+ import '../types-7cXcSQlx.js';
4
4
  import '@xyflow/react';
5
- import '../types-DJAmfiJC.js';
5
+ import '../types-CDgIIj4c.js';
6
6
  import '../pause-9iT4tCEV.js';
7
7
 
8
8
  /**
package/dist/index.cjs CHANGED
@@ -11153,6 +11153,7 @@ async function runFlow(graph, executors, onEvent = () => {
11153
11153
  continue;
11154
11154
  }
11155
11155
  onEvent({ type: "node-status", nodeId: node.id, status: "running" });
11156
+ announce(onEvent, node, "start");
11156
11157
  const inputs = collectInputs(node, incoming, portValues, initialInputs);
11157
11158
  const exec = pickExecutor(executors, node);
11158
11159
  if (!exec) {
@@ -11171,6 +11172,7 @@ async function runFlow(graph, executors, onEvent = () => {
11171
11172
  throw new Error(reason ?? "aborted");
11172
11173
  },
11173
11174
  emit: onEvent,
11175
+ executors,
11174
11176
  depth,
11175
11177
  run
11176
11178
  })
@@ -11183,6 +11185,7 @@ async function runFlow(graph, executors, onEvent = () => {
11183
11185
  }
11184
11186
  completed.add(node.id);
11185
11187
  onEvent({ type: "node-status", nodeId: node.id, status: "done" });
11188
+ announce(onEvent, node, "end");
11186
11189
  } catch (e) {
11187
11190
  const msg = e instanceof Error ? e.message : String(e);
11188
11191
  errors.push(msg);
@@ -11266,6 +11269,14 @@ function activatedPorts(node, result) {
11266
11269
  const declared = resolveNodePorts(node, kind).outputs?.map((p2) => p2.id);
11267
11270
  return { ports: declared?.length ? declared : ["out"], value: result };
11268
11271
  }
11272
+ function announce(onEvent, node, phase) {
11273
+ const data = node.data;
11274
+ const raw = phase === "start" ? data?.startingMsg : data?.stoppingMsg;
11275
+ if (typeof raw !== "string") return;
11276
+ const message = raw.trim();
11277
+ if (message === "") return;
11278
+ onEvent({ type: "node-message", nodeId: node.id, phase, message });
11279
+ }
11269
11280
 
11270
11281
  // src/registry/subflow.ts
11271
11282
  var DEFAULT_MAX_DEPTH = 8;
@@ -11319,7 +11330,10 @@ var subflowExecutor = async (ctx) => {
11319
11330
  };
11320
11331
  const result = await runFlow(
11321
11332
  child,
11322
- config.executors ?? {},
11333
+ // Inherit the parent's registry, then let the graph layer its own on top.
11334
+ // The inherited half is the fix; the layered half keeps a graph that
11335
+ // deliberately hands its child extra or different executors working.
11336
+ { ...ctx.executors ?? {}, ...config.executors ?? {} },
11323
11337
  forward,
11324
11338
  {
11325
11339
  initialInputs: config.inputs ?? {
@@ -13704,6 +13718,7 @@ function NodeConfigPanel({
13704
13718
  }
13705
13719
  const setLabel = (label) => onChange({ ...node, data: { ...node.data, label } });
13706
13720
  const setDescription = (description) => onChange({ ...node, data: { ...node.data, description } });
13721
+ const setStatusMsg = (key, value) => onChange({ ...node, data: { ...node.data, [key]: value } });
13707
13722
  const setConfigValue = (key, value) => onChange({ ...node, data: { ...node.data, config: { ...config, [key]: value } } });
13708
13723
  const issues = validateConfig(kind, config);
13709
13724
  const adapter2 = getRichInputAdapter();
@@ -13746,6 +13761,36 @@ function NodeConfigPanel({
13746
13761
  }
13747
13762
  )
13748
13763
  ] }),
13764
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-panel__field", children: [
13765
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "ff-panel__label", htmlFor: fieldId("startingMsg"), children: "Message when it starts" }),
13766
+ /* @__PURE__ */ jsxRuntime.jsx(
13767
+ "input",
13768
+ {
13769
+ id: fieldId("startingMsg"),
13770
+ "data-ff-field": "startingMsg",
13771
+ className: "ff-panel__input",
13772
+ value: node.data.startingMsg ?? "",
13773
+ onChange: (e) => setStatusMsg("startingMsg", e.target.value),
13774
+ placeholder: "e.g. Starting the deep analysis"
13775
+ }
13776
+ ),
13777
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ff-panel__hint", children: "Announced just before this node runs. Leave blank to say nothing." })
13778
+ ] }),
13779
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ff-panel__field", children: [
13780
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "ff-panel__label", htmlFor: fieldId("stoppingMsg"), children: "Message when it finishes" }),
13781
+ /* @__PURE__ */ jsxRuntime.jsx(
13782
+ "input",
13783
+ {
13784
+ id: fieldId("stoppingMsg"),
13785
+ "data-ff-field": "stoppingMsg",
13786
+ className: "ff-panel__input",
13787
+ value: node.data.stoppingMsg ?? "",
13788
+ onChange: (e) => setStatusMsg("stoppingMsg", e.target.value),
13789
+ placeholder: "e.g. Analysis complete"
13790
+ }
13791
+ ),
13792
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ff-panel__hint", children: "Announced only if the node succeeds \u2014 never after a failure." })
13793
+ ] }),
13749
13794
  kind.renderPanel ? kind.renderPanel({
13750
13795
  config,
13751
13796
  onChange: (next) => onChange({ ...node, data: { ...node.data, config: next } }),
@@ -13955,6 +14000,7 @@ function useFlowHistory(flow) {
13955
14000
  function useFlowRun({ maxFeed = 200 } = {}) {
13956
14001
  const [statuses, setStatuses] = ReactExports.useState({});
13957
14002
  const [statusText, setStatusText] = ReactExports.useState({});
14003
+ const [nodeMessages, setNodeMessages] = ReactExports.useState({});
13958
14004
  const [outputs, setOutputs] = ReactExports.useState({});
13959
14005
  const [feed, setFeed] = ReactExports.useState([]);
13960
14006
  const [running, setRunning] = ReactExports.useState(false);
@@ -13968,6 +14014,10 @@ function useFlowRun({ maxFeed = 200 } = {}) {
13968
14014
  setStatusText((t) => ({ ...t, [e.nodeId]: e.text }));
13969
14015
  appendFeed({ level: "status", text: `${e.nodeId} \u2192 ${e.status}${e.text ? ` (${e.text})` : ""}`, nodeId: e.nodeId });
13970
14016
  break;
14017
+ case "node-message":
14018
+ setNodeMessages((m) => ({ ...m, [e.nodeId]: e.message }));
14019
+ appendFeed({ level: "message", text: e.message, nodeId: e.nodeId });
14020
+ break;
13971
14021
  case "node-output":
13972
14022
  setOutputs((o) => ({ ...o, [e.nodeId]: e.value }));
13973
14023
  appendFeed({ level: "info", text: `${e.nodeId}.${e.portId} = ${preview(e.value)}`, nodeId: e.nodeId, detail: e.value });
@@ -14027,7 +14077,7 @@ function useFlowRun({ maxFeed = 200 } = {}) {
14027
14077
  setFeed([]);
14028
14078
  setLastResult(null);
14029
14079
  }, []);
14030
- return { statuses, statusText, outputs, feed, running, lastResult, run, cancel, reset };
14080
+ return { statuses, statusText, nodeMessages, outputs, feed, running, lastResult, run, cancel, reset };
14031
14081
  }
14032
14082
  function applyOutputsToNodes(nodes, outputs) {
14033
14083
  return nodes.map((n) => {
@@ -14081,6 +14131,8 @@ function toSchemaNode(n) {
14081
14131
  position: { x: n.position.x, y: n.position.y },
14082
14132
  label: data.label,
14083
14133
  description: data.description,
14134
+ ...typeof data.startingMsg === "string" && data.startingMsg !== "" ? { startingMsg: data.startingMsg } : {},
14135
+ ...typeof data.stoppingMsg === "string" && data.stoppingMsg !== "" ? { stoppingMsg: data.stoppingMsg } : {},
14084
14136
  config: data.config,
14085
14137
  inputs: ports.inputs,
14086
14138
  outputs: ports.outputs,
@@ -14153,6 +14205,8 @@ function importWorkflow(schema, options = {}) {
14153
14205
  kind: kindId,
14154
14206
  label: n.label ?? kind?.label ?? n.kind,
14155
14207
  description: n.description,
14208
+ ...n.startingMsg ? { startingMsg: n.startingMsg } : {},
14209
+ ...n.stoppingMsg ? { stoppingMsg: n.stoppingMsg } : {},
14156
14210
  config,
14157
14211
  // Carry serialized ports back onto the node so a round-trip is stable
14158
14212
  // and an unknown kind still routes the way the document described.