@particle-academy/fancy-flow 0.45.0 → 0.46.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 (77) hide show
  1. package/dist/{ConfigFieldRenderer-Dzy4f6rG.d.cts → ConfigFieldRenderer-Cyir8-B8.d.cts} +2 -2
  2. package/dist/{ConfigFieldRenderer-WqJr-td_.d.ts → ConfigFieldRenderer-iMkZj0VK.d.ts} +2 -2
  3. package/dist/{FlowViewer-BbbUJe2b.d.cts → FlowViewer-CY3_vHSg.d.cts} +1 -1
  4. package/dist/{FlowViewer-csuaTL5t.d.ts → FlowViewer-DGW6t-80.d.ts} +1 -1
  5. package/dist/{capabilities-Brn74URS.d.ts → capabilities-DMUhnyZD.d.ts} +1 -1
  6. package/dist/{capabilities-CYCeIx6I.d.cts → capabilities-Dmd26aAs.d.cts} +1 -1
  7. package/dist/chunk-BHM5HGXH.js +79 -0
  8. package/dist/chunk-BHM5HGXH.js.map +1 -0
  9. package/dist/{chunk-DHUFUDEX.js → chunk-HFUBVT7W.js} +3 -3
  10. package/dist/{chunk-DHUFUDEX.js.map → chunk-HFUBVT7W.js.map} +1 -1
  11. package/dist/{chunk-VLATLVGH.js → chunk-L43CWD63.js} +129 -5
  12. package/dist/chunk-L43CWD63.js.map +1 -0
  13. package/dist/{chunk-A6RFLGWV.js → chunk-MH4ZW4DJ.js} +3 -3
  14. package/dist/{chunk-A6RFLGWV.js.map → chunk-MH4ZW4DJ.js.map} +1 -1
  15. package/dist/{chunk-QZTGV3ZL.js → chunk-P5SYH6M6.js} +3 -3
  16. package/dist/{chunk-QZTGV3ZL.js.map → chunk-P5SYH6M6.js.map} +1 -1
  17. package/dist/{chunk-WBXGZVLB.js → chunk-RMU6YCIQ.js} +11 -5
  18. package/dist/chunk-RMU6YCIQ.js.map +1 -0
  19. package/dist/durable/index.d.cts +490 -0
  20. package/dist/durable/index.d.ts +490 -0
  21. package/dist/durable.cjs +927 -0
  22. package/dist/durable.cjs.map +1 -0
  23. package/dist/durable.js +552 -0
  24. package/dist/durable.js.map +1 -0
  25. package/dist/engine.cjs +128 -2
  26. package/dist/engine.cjs.map +1 -1
  27. package/dist/engine.d.cts +9 -7
  28. package/dist/engine.d.ts +9 -7
  29. package/dist/engine.js +4 -4
  30. package/dist/fields/react-fancy.d.cts +4 -3
  31. package/dist/fields/react-fancy.d.ts +4 -3
  32. package/dist/index.cjs +133 -3
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +12 -10
  35. package/dist/index.d.ts +12 -10
  36. package/dist/index.js +13 -88
  37. package/dist/index.js.map +1 -1
  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 +2 -2
  41. package/dist/llm/prism.d.ts +2 -2
  42. package/dist/llm/vercel-ai.d.cts +2 -2
  43. package/dist/llm/vercel-ai.d.ts +2 -2
  44. package/dist/pause-9iT4tCEV.d.cts +96 -0
  45. package/dist/pause-9iT4tCEV.d.ts +96 -0
  46. package/dist/registry/index.d.cts +7 -6
  47. package/dist/registry/index.d.ts +7 -6
  48. package/dist/{registry-Budds73w.d.cts → registry-D_kyUZEf.d.cts} +1 -1
  49. package/dist/{registry-D0I20HJ3.d.ts → registry-LHB3MlR9.d.ts} +1 -1
  50. package/dist/registry.cjs +133 -3
  51. package/dist/registry.cjs.map +1 -1
  52. package/dist/registry.js +4 -4
  53. package/dist/{run-cohort-CV7EcwGG.d.ts → run-cohort-Cyeny2Uu.d.ts} +3 -34
  54. package/dist/{run-cohort-DitsaYgS.d.cts → run-cohort-DdPPowJ3.d.cts} +3 -34
  55. package/dist/run-flow-1KiXhy59.d.cts +55 -0
  56. package/dist/run-flow-CQvTDBYk.d.ts +55 -0
  57. package/dist/runtime/index.d.cts +5 -3
  58. package/dist/runtime/index.d.ts +5 -3
  59. package/dist/runtime.cjs +128 -2
  60. package/dist/runtime.cjs.map +1 -1
  61. package/dist/runtime.js +3 -3
  62. package/dist/schema/index.d.cts +1 -1
  63. package/dist/schema/index.d.ts +1 -1
  64. package/dist/screens.d.cts +2 -2
  65. package/dist/screens.d.ts +2 -2
  66. package/dist/screens.js +6 -6
  67. package/dist/{types-D6ZSKBly.d.ts → types--S2Kzx7w.d.cts} +3 -97
  68. package/dist/{types-nQOA8jpk.d.cts → types-ChkCRonF.d.ts} +3 -97
  69. package/dist/types-Jx1TwehV.d.cts +247 -0
  70. package/dist/types-Jx1TwehV.d.ts +247 -0
  71. package/dist/ux.d.cts +3 -2
  72. package/dist/ux.d.ts +3 -2
  73. package/package.json +12 -2
  74. package/dist/chunk-VLATLVGH.js.map +0 -1
  75. package/dist/chunk-WBXGZVLB.js.map +0 -1
  76. package/dist/types-CMSrWVYM.d.cts +0 -109
  77. package/dist/types-CMSrWVYM.d.ts +0 -109
package/dist/runtime.js CHANGED
@@ -1,7 +1,7 @@
1
- export { applyOutputsToNodes, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './chunk-A6RFLGWV.js';
2
- export { runCohort } from './chunk-QZTGV3ZL.js';
1
+ export { applyOutputsToNodes, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './chunk-MH4ZW4DJ.js';
2
+ export { runCohort } from './chunk-P5SYH6M6.js';
3
3
  import './chunk-OWENS2H5.js';
4
- export { runFlow } from './chunk-VLATLVGH.js';
4
+ export { RunIdentity, escapeSegment, runFlow } from './chunk-L43CWD63.js';
5
5
  import './chunk-TITD5W4Y.js';
6
6
  import './chunk-PVROYW7C.js';
7
7
  //# sourceMappingURL=runtime.js.map
@@ -1,4 +1,4 @@
1
- import { P as PortDescriptor, F as FlowGraph } from '../types-CMSrWVYM.cjs';
1
+ import { P as PortDescriptor, F as FlowGraph } from '../types-Jx1TwehV.cjs';
2
2
  import '@xyflow/react';
3
3
 
4
4
  /** Schema version. Bump on breaking shape changes; add migrations as needed. */
@@ -1,4 +1,4 @@
1
- import { P as PortDescriptor, F as FlowGraph } from '../types-CMSrWVYM.js';
1
+ import { P as PortDescriptor, F as FlowGraph } from '../types-Jx1TwehV.js';
2
2
  import '@xyflow/react';
3
3
 
4
4
  /** Schema version. Bump on breaking shape changes; add migrations as needed. */
@@ -1,6 +1,6 @@
1
- export { F as FlowNodeStatus, a as FlowViewer, b as FlowViewerClassNames, c as FlowViewerProps } from './FlowViewer-BbbUJe2b.cjs';
1
+ export { F as FlowNodeStatus, a as FlowViewer, b as FlowViewerClassNames, c as FlowViewerProps } from './FlowViewer-CY3_vHSg.cjs';
2
2
  import 'react';
3
- import './types-CMSrWVYM.cjs';
3
+ import './types-Jx1TwehV.cjs';
4
4
  import '@xyflow/react';
5
5
 
6
6
  /**
package/dist/screens.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { F as FlowNodeStatus, a as FlowViewer, b as FlowViewerClassNames, c as FlowViewerProps } from './FlowViewer-csuaTL5t.js';
1
+ export { F as FlowNodeStatus, a as FlowViewer, b as FlowViewerClassNames, c as FlowViewerProps } from './FlowViewer-DGW6t-80.js';
2
2
  import 'react';
3
- import './types-CMSrWVYM.js';
3
+ import './types-Jx1TwehV.js';
4
4
  import '@xyflow/react';
5
5
 
6
6
  /**
package/dist/screens.js CHANGED
@@ -1,13 +1,13 @@
1
- import { FlowViewer } from './chunk-DHUFUDEX.js';
2
- export { FlowViewer } from './chunk-DHUFUDEX.js';
3
- import './chunk-WBXGZVLB.js';
1
+ import { FlowViewer } from './chunk-HFUBVT7W.js';
2
+ export { FlowViewer } from './chunk-HFUBVT7W.js';
3
+ import './chunk-RMU6YCIQ.js';
4
+ import './chunk-F5RPRB7A.js';
4
5
  import './chunk-OWENS2H5.js';
5
- import './chunk-UEOE6B52.js';
6
6
  import './chunk-USL4FMFU.js';
7
- import './chunk-VLATLVGH.js';
7
+ import './chunk-UEOE6B52.js';
8
+ import './chunk-L43CWD63.js';
8
9
  import './chunk-TITD5W4Y.js';
9
10
  import './chunk-PVROYW7C.js';
10
- import './chunk-F5RPRB7A.js';
11
11
  import { registerSchemaComponents } from '@particle-academy/fancy-screens';
12
12
 
13
13
  function registerFlowSchema() {
@@ -1,6 +1,7 @@
1
1
  import { ReactNode, ComponentType } from 'react';
2
- import { F as FlowGraph, a as FlowNode, P as PortDescriptor, N as NodeExecutor } from './types-CMSrWVYM.js';
2
+ import { F as FlowGraph, a as FlowNode, P as PortDescriptor, N as NodeExecutor } from './types-Jx1TwehV.cjs';
3
3
  import { NodeProps } from '@xyflow/react';
4
+ import { P as PauseAwaiting } from './pause-9iT4tCEV.cjs';
4
5
 
5
6
  /**
6
7
  * What a node emits, described well enough for an author to reference it.
@@ -71,101 +72,6 @@ type ExpressionGrammarHelp = {
71
72
  */
72
73
  declare function describeExpressionGrammar(): ExpressionGrammarHelp;
73
74
 
74
- /**
75
- * The human-pause contract.
76
- *
77
- * A workflow that waits for a person is not an error, but it travels the same
78
- * channel as one: the executor aborts, the engine records a reason string, and
79
- * the durable runner decides whether that string meant "failed" or "waiting".
80
- *
81
- * That seam existed before this module, as two `str_starts_with` checks in the
82
- * Laravel run job against constants owned by two BUILTIN executors. It worked,
83
- * and it was invisible: a third-party human-input node had no way to announce
84
- * that it pauses, and nothing stopped a refactor from removing the mechanism
85
- * out from under published packages. Reported by the MOIC Suite consumer, who
86
- * needed exactly that and had to reach for a private constant to get it.
87
- *
88
- * So the encoding is now public, typed, and versioned by prefix rather than
89
- * implied. The wire format stays a plain string on purpose — it survives the
90
- * existing abort → `RunResult.error` path unchanged, crosses a queue boundary,
91
- * and decodes identically in PHP, none of which a thrown class would do.
92
- *
93
- * @see decodePause — the one function a durable runner needs.
94
- */
95
- /**
96
- * What the run is waiting for.
97
- *
98
- * `approval` and `input` are the shapes both runtimes ship. The type stays open
99
- * because the whole point is that a marketplace node can define its own —
100
- * a signature step, a payment confirmation, a review queue — and a runner that
101
- * does not recognise one should report it rather than guess.
102
- */
103
- type PauseAwaiting = "approval" | "input" | (string & {});
104
- /** A run halted, waiting for a person. */
105
- type PauseSignal = {
106
- /** The node that paused — where a submission gets injected on resume. */
107
- nodeId: string;
108
- awaiting: PauseAwaiting;
109
- /**
110
- * Kind-supplied context for whoever renders the wait — a form schema, the
111
- * question being asked, a diff to approve. Must be JSON-serializable: it
112
- * crosses a queue boundary and, for durable runs, a database column.
113
- */
114
- detail?: unknown;
115
- };
116
- /** Marks a reason string as a pause rather than a failure. */
117
- declare const PAUSE_PREFIX = "fancy-flow:pause:";
118
- /**
119
- * Reason prefixes shipped before this contract, kept decodable forever.
120
- *
121
- * These are what `DurableApprovalExecutor` and `DurableUserInputExecutor`
122
- * emitted, and they are written into the `error` column of every run that
123
- * paused under an older version. Dropping them would strand those runs
124
- * mid-flight — a resume path that only works for new runs is not a resume path.
125
- */
126
- declare const LEGACY_PAUSE_PREFIXES: ReadonlyArray<readonly [string, PauseAwaiting]>;
127
- /**
128
- * Encode a pause as the reason string an executor aborts with.
129
- *
130
- * The payload is JSON rather than delimited fields because a node id may
131
- * contain a colon, and a positional encoding that breaks on user data is the
132
- * kind of bug that only shows up in someone else's graph.
133
- */
134
- declare function encodePause(signal: PauseSignal): string;
135
- /**
136
- * Decode a run's error reason into a pause, or null if it was a real failure.
137
- *
138
- * This is the whole contract from a runner's side: call it on `result.error`,
139
- * and if it returns non-null, persist the run as waiting on `signal.nodeId`
140
- * instead of failing it. Accepts the legacy prefixes, so a runner written
141
- * against this handles runs that paused under an older version.
142
- */
143
- declare function decodePause(reason: string | null | undefined): PauseSignal | null;
144
- /** True when a run's error reason is actually a pause. */
145
- declare function isPause(reason: string | null | undefined): boolean;
146
- /**
147
- * Abort the current node as a pause.
148
- *
149
- * Called from inside an executor with its own context. Node authors should
150
- * reach for this rather than hand-encoding a reason, so the format stays ours
151
- * to change:
152
- *
153
- * ```ts
154
- * const values = ctx.inputs.values;
155
- * if (values === undefined) pauseForHuman(ctx, "input", { fields });
156
- * return values;
157
- * ```
158
- *
159
- * Note the `undefined` check — an empty submission (`{}`) is a real answer and
160
- * must resume. Truthiness here pauses forever on an empty form.
161
- */
162
- declare function pauseForHuman(ctx: {
163
- node: {
164
- id: string;
165
- };
166
- abort: (reason?: string) => never;
167
- }, awaiting: PauseAwaiting, detail?: unknown): never;
168
-
169
75
  /**
170
76
  * The node package manifest — what a marketplace node declares about itself.
171
77
  *
@@ -715,4 +621,4 @@ type NodeKindDefinition<TConfig = Record<string, unknown>, TIn = any, TOut = any
715
621
  reactive?: boolean;
716
622
  };
717
623
 
718
- export { type AvailableVariable as A, type ExpressionGrammarHelp as B, type ConfigField as C, type DocumentConfigField as D, type ExpressionConfigField as E, type OutputShape as F, availableVariables as G, baseVariables as H, describeExpressionGrammar as I, type JsonConfigField as J, type KeyValueConfigField as K, LEGACY_PAUSE_PREFIXES as L, type ManifestProblem as M, type NodeKindDefinition as N, type OutputField as O, type PauseAwaiting as P, outputFieldsFor as Q, type RenderBodyContext as R, type SideEffects as S, type TextConfigField as T, type NodeCategory as a, type CapabilityRequirement as b, type ManifestValidation as c, NODE_MANIFEST_SCHEMA_VERSION as d, type NodePackageManifest as e, type NodeRuntimeId as f, type NodeRuntimeSpec as g, PAUSE_PREFIX as h, type PauseSignal as i, type PortSpec as j, checkCapabilities as k, checkRuntimeSupport as l, decodePause as m, encodePause as n, isPause as o, pauseForHuman as p, type CredentialConfigField as q, type NumberConfigField as r, satisfiesRange as s, type RepeaterConfigField as t, type RepeaterRowField as u, validateNodeManifest as v, type SelectConfigField as w, type SwitchConfigField as x, type TextareaConfigField as y, type ExpressionForm as z };
624
+ export { type AvailableVariable as A, type ConfigField as C, type DocumentConfigField as D, type ExpressionConfigField as E, type JsonConfigField as J, type KeyValueConfigField as K, type ManifestProblem as M, type NodeKindDefinition as N, type OutputField as O, type PortSpec as P, type RenderBodyContext as R, type SideEffects as S, type TextConfigField as T, type NodeCategory as a, type CapabilityRequirement as b, type ManifestValidation as c, NODE_MANIFEST_SCHEMA_VERSION as d, type NodePackageManifest as e, type NodeRuntimeId as f, type NodeRuntimeSpec as g, checkCapabilities as h, checkRuntimeSupport as i, type CredentialConfigField as j, type NumberConfigField as k, type RepeaterConfigField as l, type RepeaterRowField as m, type SelectConfigField as n, type SwitchConfigField as o, type TextareaConfigField as p, type ExpressionForm as q, type ExpressionGrammarHelp as r, satisfiesRange as s, type OutputShape as t, availableVariables as u, validateNodeManifest as v, baseVariables as w, describeExpressionGrammar as x, outputFieldsFor as y };
@@ -1,6 +1,7 @@
1
1
  import { ReactNode, ComponentType } from 'react';
2
- import { F as FlowGraph, a as FlowNode, P as PortDescriptor, N as NodeExecutor } from './types-CMSrWVYM.cjs';
2
+ import { F as FlowGraph, a as FlowNode, P as PortDescriptor, N as NodeExecutor } from './types-Jx1TwehV.js';
3
3
  import { NodeProps } from '@xyflow/react';
4
+ import { P as PauseAwaiting } from './pause-9iT4tCEV.js';
4
5
 
5
6
  /**
6
7
  * What a node emits, described well enough for an author to reference it.
@@ -71,101 +72,6 @@ type ExpressionGrammarHelp = {
71
72
  */
72
73
  declare function describeExpressionGrammar(): ExpressionGrammarHelp;
73
74
 
74
- /**
75
- * The human-pause contract.
76
- *
77
- * A workflow that waits for a person is not an error, but it travels the same
78
- * channel as one: the executor aborts, the engine records a reason string, and
79
- * the durable runner decides whether that string meant "failed" or "waiting".
80
- *
81
- * That seam existed before this module, as two `str_starts_with` checks in the
82
- * Laravel run job against constants owned by two BUILTIN executors. It worked,
83
- * and it was invisible: a third-party human-input node had no way to announce
84
- * that it pauses, and nothing stopped a refactor from removing the mechanism
85
- * out from under published packages. Reported by the MOIC Suite consumer, who
86
- * needed exactly that and had to reach for a private constant to get it.
87
- *
88
- * So the encoding is now public, typed, and versioned by prefix rather than
89
- * implied. The wire format stays a plain string on purpose — it survives the
90
- * existing abort → `RunResult.error` path unchanged, crosses a queue boundary,
91
- * and decodes identically in PHP, none of which a thrown class would do.
92
- *
93
- * @see decodePause — the one function a durable runner needs.
94
- */
95
- /**
96
- * What the run is waiting for.
97
- *
98
- * `approval` and `input` are the shapes both runtimes ship. The type stays open
99
- * because the whole point is that a marketplace node can define its own —
100
- * a signature step, a payment confirmation, a review queue — and a runner that
101
- * does not recognise one should report it rather than guess.
102
- */
103
- type PauseAwaiting = "approval" | "input" | (string & {});
104
- /** A run halted, waiting for a person. */
105
- type PauseSignal = {
106
- /** The node that paused — where a submission gets injected on resume. */
107
- nodeId: string;
108
- awaiting: PauseAwaiting;
109
- /**
110
- * Kind-supplied context for whoever renders the wait — a form schema, the
111
- * question being asked, a diff to approve. Must be JSON-serializable: it
112
- * crosses a queue boundary and, for durable runs, a database column.
113
- */
114
- detail?: unknown;
115
- };
116
- /** Marks a reason string as a pause rather than a failure. */
117
- declare const PAUSE_PREFIX = "fancy-flow:pause:";
118
- /**
119
- * Reason prefixes shipped before this contract, kept decodable forever.
120
- *
121
- * These are what `DurableApprovalExecutor` and `DurableUserInputExecutor`
122
- * emitted, and they are written into the `error` column of every run that
123
- * paused under an older version. Dropping them would strand those runs
124
- * mid-flight — a resume path that only works for new runs is not a resume path.
125
- */
126
- declare const LEGACY_PAUSE_PREFIXES: ReadonlyArray<readonly [string, PauseAwaiting]>;
127
- /**
128
- * Encode a pause as the reason string an executor aborts with.
129
- *
130
- * The payload is JSON rather than delimited fields because a node id may
131
- * contain a colon, and a positional encoding that breaks on user data is the
132
- * kind of bug that only shows up in someone else's graph.
133
- */
134
- declare function encodePause(signal: PauseSignal): string;
135
- /**
136
- * Decode a run's error reason into a pause, or null if it was a real failure.
137
- *
138
- * This is the whole contract from a runner's side: call it on `result.error`,
139
- * and if it returns non-null, persist the run as waiting on `signal.nodeId`
140
- * instead of failing it. Accepts the legacy prefixes, so a runner written
141
- * against this handles runs that paused under an older version.
142
- */
143
- declare function decodePause(reason: string | null | undefined): PauseSignal | null;
144
- /** True when a run's error reason is actually a pause. */
145
- declare function isPause(reason: string | null | undefined): boolean;
146
- /**
147
- * Abort the current node as a pause.
148
- *
149
- * Called from inside an executor with its own context. Node authors should
150
- * reach for this rather than hand-encoding a reason, so the format stays ours
151
- * to change:
152
- *
153
- * ```ts
154
- * const values = ctx.inputs.values;
155
- * if (values === undefined) pauseForHuman(ctx, "input", { fields });
156
- * return values;
157
- * ```
158
- *
159
- * Note the `undefined` check — an empty submission (`{}`) is a real answer and
160
- * must resume. Truthiness here pauses forever on an empty form.
161
- */
162
- declare function pauseForHuman(ctx: {
163
- node: {
164
- id: string;
165
- };
166
- abort: (reason?: string) => never;
167
- }, awaiting: PauseAwaiting, detail?: unknown): never;
168
-
169
75
  /**
170
76
  * The node package manifest — what a marketplace node declares about itself.
171
77
  *
@@ -715,4 +621,4 @@ type NodeKindDefinition<TConfig = Record<string, unknown>, TIn = any, TOut = any
715
621
  reactive?: boolean;
716
622
  };
717
623
 
718
- export { type AvailableVariable as A, type ExpressionGrammarHelp as B, type ConfigField as C, type DocumentConfigField as D, type ExpressionConfigField as E, type OutputShape as F, availableVariables as G, baseVariables as H, describeExpressionGrammar as I, type JsonConfigField as J, type KeyValueConfigField as K, LEGACY_PAUSE_PREFIXES as L, type ManifestProblem as M, type NodeKindDefinition as N, type OutputField as O, type PauseAwaiting as P, outputFieldsFor as Q, type RenderBodyContext as R, type SideEffects as S, type TextConfigField as T, type NodeCategory as a, type CapabilityRequirement as b, type ManifestValidation as c, NODE_MANIFEST_SCHEMA_VERSION as d, type NodePackageManifest as e, type NodeRuntimeId as f, type NodeRuntimeSpec as g, PAUSE_PREFIX as h, type PauseSignal as i, type PortSpec as j, checkCapabilities as k, checkRuntimeSupport as l, decodePause as m, encodePause as n, isPause as o, pauseForHuman as p, type CredentialConfigField as q, type NumberConfigField as r, satisfiesRange as s, type RepeaterConfigField as t, type RepeaterRowField as u, validateNodeManifest as v, type SelectConfigField as w, type SwitchConfigField as x, type TextareaConfigField as y, type ExpressionForm as z };
624
+ export { type AvailableVariable as A, type ConfigField as C, type DocumentConfigField as D, type ExpressionConfigField as E, type JsonConfigField as J, type KeyValueConfigField as K, type ManifestProblem as M, type NodeKindDefinition as N, type OutputField as O, type PortSpec as P, type RenderBodyContext as R, type SideEffects as S, type TextConfigField as T, type NodeCategory as a, type CapabilityRequirement as b, type ManifestValidation as c, NODE_MANIFEST_SCHEMA_VERSION as d, type NodePackageManifest as e, type NodeRuntimeId as f, type NodeRuntimeSpec as g, checkCapabilities as h, checkRuntimeSupport as i, type CredentialConfigField as j, type NumberConfigField as k, type RepeaterConfigField as l, type RepeaterRowField as m, type SelectConfigField as n, type SwitchConfigField as o, type TextareaConfigField as p, type ExpressionForm as q, type ExpressionGrammarHelp as r, satisfiesRange as s, type OutputShape as t, availableVariables as u, validateNodeManifest as v, baseVariables as w, describeExpressionGrammar as x, outputFieldsFor as y };
@@ -0,0 +1,247 @@
1
+ import { Node, Edge } from '@xyflow/react';
2
+
3
+ /**
4
+ * Who is running, which step this is, and how many times it has been tried.
5
+ *
6
+ * ## Why an engine needs this at all
7
+ *
8
+ * A node that WRITES to somebody else's system — charge a card, send a message,
9
+ * open a pull request — can only survive a retry if the retry carries the same
10
+ * idempotency key the first attempt did. Otherwise the provider treats the
11
+ * second call as a new request and the customer is charged twice.
12
+ *
13
+ * Until this existed the executor context was `{ node, inputs, emit, abort }`,
14
+ * which is not enough to derive one. Both obvious fallbacks are worse than
15
+ * sending no key at all:
16
+ *
17
+ * - **the node id alone** is stable across retries, and also across RUNS — two
18
+ * legitimate payments share a key and the provider silently collapses the
19
+ * second into the first. A payment that never happened, reported as success;
20
+ * - **a fresh random value** is unique per run, and also per ATTEMPT — a retry
21
+ * creates a second charge, which is the thing being avoided.
22
+ *
23
+ * ## What actually identifies a step
24
+ *
25
+ * Not `(run, node)`. A node legitimately executes more than once inside one
26
+ * run: once per subflow invocation, once per iteration of a loop an executor
27
+ * drives itself. `(run, node)` would give every one of those the same key, and
28
+ * a provider would honour exactly one of them.
29
+ *
30
+ * So a step is identified by the **path of invocations that led to it**, plus
31
+ * an optional **occurrence** for repetition at the same level:
32
+ *
33
+ * ```text
34
+ * runKey ":" segment ("/" segment)* segment := escape(id) ["#" occurrence]
35
+ * ```
36
+ *
37
+ * And the part that is easy to get backwards: **`attempt` is NOT in the key.**
38
+ * It is carried here for logging and for {@link RunIdentity.isReplaySafe}, and
39
+ * putting it in the key would restore the exact bug the key exists to prevent.
40
+ *
41
+ * Pinned cross-runtime by `shared/flow-run-identity` in
42
+ * `@particle-academy/fancy-conformance`.
43
+ */
44
+ /** The wire shape — what a queue job payload carries. */
45
+ type RunIdentityJson = {
46
+ runKey: string;
47
+ path?: string[];
48
+ attempt?: number;
49
+ firstAttemptAt?: string;
50
+ };
51
+ /**
52
+ * Escape one segment so the composition is injective.
53
+ *
54
+ * `%` FIRST, or the escaping is not reversible: escaping `/` before `%` turns a
55
+ * literal `a%2Fb` into the same text as the escaped form of `a/b`, which is the
56
+ * collision this exists to prevent, reintroduced by its own fix.
57
+ */
58
+ declare function escapeSegment(value: string): string;
59
+ /**
60
+ * A run, a position inside it, and how many times this position has been tried.
61
+ *
62
+ * Immutable. {@link descend} returns a new identity rather than mutating, so an
63
+ * executor cannot change what its siblings see.
64
+ */
65
+ declare class RunIdentity {
66
+ /** Stable for the whole run: same across retries, resumes, workers and hosts. */
67
+ readonly runKey: string;
68
+ /**
69
+ * Enclosing invocation segments, outermost first, ALREADY RENDERED.
70
+ *
71
+ * Empty at the top level. A subflow pushes the invoking node's id; an
72
+ * executor that loops pushes `id#i`.
73
+ */
74
+ readonly path: readonly string[];
75
+ /**
76
+ * 1-based attempt of THIS logical step. Never part of the key.
77
+ *
78
+ * The durable driver sets it from the node's claim row, which is exact. A
79
+ * plain in-process `runFlow` gets whatever the host passed, which is
80
+ * run-scoped and therefore conservative — see `isReplaySafe`.
81
+ */
82
+ readonly attempt: number;
83
+ /** ISO-8601 UTC instant of attempt 1 of this step. */
84
+ readonly firstAttemptAt: string;
85
+ constructor(runKey: string, path?: readonly string[], attempt?: number, firstAttemptAt?: string);
86
+ /**
87
+ * The identity of one execution of one node — stable across retries of that
88
+ * execution, distinct from every other execution of the same node.
89
+ *
90
+ * Pass `occurrence` when an executor runs the same node more than once at the
91
+ * same level (a loop body, one item of a fan-out it drives itself).
92
+ */
93
+ stepKey(nodeId: string, occurrence?: number | null): string;
94
+ /**
95
+ * A child identity for work nested inside this step.
96
+ *
97
+ * `subflow` pushes the invoking node's id, so a node inside the child graph
98
+ * cannot collide with a same-named node in the parent. Attempt and
99
+ * `firstAttemptAt` are carried down unchanged: the nested work happens inside
100
+ * this step's attempt, and shares its clock.
101
+ */
102
+ descend(segment: string, occurrence?: number | null): RunIdentity;
103
+ /** A copy on a different attempt, first-attempt clock preserved. */
104
+ withAttempt(attempt: number, firstAttemptAt?: string): RunIdentity;
105
+ /**
106
+ * May this attempt reuse the step key and still be deduplicated?
107
+ *
108
+ * Providers forget idempotency keys — Stripe after 24 hours. Past that
109
+ * window, resending the key creates a second charge and sending a fresh one
110
+ * creates a second charge, so **the caller must refuse rather than pick
111
+ * between them**: a loud stuck run beats a silent double write.
112
+ *
113
+ * `true` on attempt 1 whatever the elapsed time — nothing was sent on an
114
+ * earlier attempt, so there is nothing for the provider to have forgotten.
115
+ * That is what lets a run park on a human gate for a week and then write.
116
+ *
117
+ * `windowSeconds: null` means the provider does not expire keys. `0` means
118
+ * it does not dedupe at all, so no retry may reuse a key — it is a real
119
+ * window, not an absent one, and the two must not be conflated: reading `0`
120
+ * as `null` turns "this provider does not dedupe" into "this provider
121
+ * dedupes forever", which is the more dangerous of the two by a distance.
122
+ */
123
+ isReplaySafe(windowSeconds: number | null | undefined, now?: Date | string): boolean;
124
+ toJSON(): Required<RunIdentityJson>;
125
+ /** Rebuild from a queue payload. */
126
+ static from(value: RunIdentity | RunIdentityJson | string): RunIdentity;
127
+ }
128
+
129
+ /**
130
+ * Public domain types for fancy-flow. Built-in nodes are layered on top of
131
+ * @xyflow/react's `Node` so consumers can mix custom xyflow nodes alongside
132
+ * the kit. Edges remain xyflow's standard `Edge`.
133
+ */
134
+
135
+ type FlowNodeKind = "trigger" | "action" | "decision" | "output" | "note" | "subgraph";
136
+ /** Status surfaced on the node while a run is in progress. */
137
+ type NodeRunStatus = "idle" | "queued" | "running" | "done" | "error";
138
+ /** Port description on a node. Ports are visual handles xyflow can connect. */
139
+ type PortDescriptor = {
140
+ id: string;
141
+ label?: string;
142
+ /** Optional logical type for hosts that want to validate connections. */
143
+ type?: string;
144
+ };
145
+ /** Common shape every kit node carries in its `data` slot. */
146
+ type BaseNodeData = {
147
+ label: string;
148
+ description?: string;
149
+ /** Free-form configuration the host owns (form values, code, parameters). */
150
+ config?: Record<string, unknown>;
151
+ /** Set by the runner; hosts shouldn't edit this directly. */
152
+ status?: NodeRunStatus;
153
+ /** Optional human-readable status detail (e.g. error message, current step). */
154
+ statusText?: string;
155
+ /** Per-node accent override, e.g. for theming a custom subclass. */
156
+ color?: string;
157
+ /** Input ports rendered on the node. Defaults vary by kind. */
158
+ inputs?: PortDescriptor[];
159
+ /** Output ports rendered on the node. Defaults vary by kind. */
160
+ outputs?: PortDescriptor[];
161
+ };
162
+ type TriggerNodeData = BaseNodeData & {
163
+ kind: "trigger";
164
+ };
165
+ type ActionNodeData = BaseNodeData & {
166
+ kind: "action";
167
+ };
168
+ type DecisionNodeData = BaseNodeData & {
169
+ kind: "decision";
170
+ };
171
+ type OutputNodeData = BaseNodeData & {
172
+ kind: "output";
173
+ };
174
+ type NoteNodeData = BaseNodeData & {
175
+ kind: "note";
176
+ body?: string;
177
+ };
178
+ type SubgraphNodeData = BaseNodeData & {
179
+ kind: "subgraph";
180
+ /** Ids of the nodes contained in this subgraph. */
181
+ childIds?: string[];
182
+ /** Whether the subgraph is shown collapsed (default true — children hidden). */
183
+ collapsed?: boolean;
184
+ };
185
+ type FlowNodeData = TriggerNodeData | ActionNodeData | DecisionNodeData | OutputNodeData | NoteNodeData | SubgraphNodeData;
186
+ type FlowNode = Node<FlowNodeData>;
187
+ type FlowEdge = Edge;
188
+ /** A serializable graph — what hosts persist, what agents read/write. */
189
+ type FlowGraph = {
190
+ nodes: FlowNode[];
191
+ edges: FlowEdge[];
192
+ };
193
+ /** Per-node executor signature. Inputs are keyed by input-port id. */
194
+ type NodeExecutor<TIn = Record<string, unknown>, TOut = unknown> = (ctx: {
195
+ node: FlowNode;
196
+ inputs: TIn;
197
+ /** Stops the run if called. */
198
+ abort: (reason?: string) => never;
199
+ /** Lets the executor stream status updates and partial outputs. */
200
+ emit: (event: RunEvent) => void;
201
+ /**
202
+ * How deep this run is nested. 0 for a top-level run; `subflow` passes
203
+ * depth + 1 to its child, so runaway recursion can be reported by name
204
+ * rather than as a stack overflow.
205
+ */
206
+ depth?: number;
207
+ /**
208
+ * Who is running, and which attempt of which step this is.
209
+ *
210
+ * `ctx.run.stepKey(ctx.node.id)` is the idempotency key for a node that
211
+ * writes to somebody else's system — stable across retries of this step,
212
+ * distinct for every other execution of the same node.
213
+ *
214
+ * `undefined` when the host supplied no identity, and that is a real
215
+ * answer: a write with no key must decline or accept one attempt, never
216
+ * invent a key. See `RunIdentity`.
217
+ */
218
+ run?: RunIdentity;
219
+ }) => Promise<TOut> | TOut;
220
+ type ExecutorRegistry = Partial<Record<FlowNodeKind | string, NodeExecutor>>;
221
+ type RunEvent = {
222
+ type: "node-status";
223
+ nodeId: string;
224
+ status: NodeRunStatus;
225
+ text?: string;
226
+ } | {
227
+ type: "node-output";
228
+ nodeId: string;
229
+ portId: string;
230
+ value: unknown;
231
+ } | {
232
+ type: "log";
233
+ nodeId?: string;
234
+ level: "info" | "warn" | "error";
235
+ message: string;
236
+ detail?: unknown;
237
+ } | {
238
+ type: "run-start";
239
+ } | {
240
+ type: "run-end";
241
+ ok: boolean;
242
+ } | {
243
+ type: "run-error";
244
+ error: string;
245
+ };
246
+
247
+ export { type ActionNodeData as A, type BaseNodeData as B, type DecisionNodeData as D, type ExecutorRegistry as E, type FlowGraph as F, type NodeExecutor as N, type OutputNodeData as O, type PortDescriptor as P, type RunEvent as R, type SubgraphNodeData as S, type TriggerNodeData as T, type FlowNode as a, RunIdentity as b, type RunIdentityJson as c, type FlowEdge as d, type FlowNodeData as e, type FlowNodeKind as f, type NodeRunStatus as g, type NoteNodeData as h, escapeSegment as i };