@particle-academy/fancy-flow 0.44.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.
- package/dist/{ConfigFieldRenderer-LotNHeG8.d.cts → ConfigFieldRenderer-Cyir8-B8.d.cts} +2 -2
- package/dist/{ConfigFieldRenderer-BHQDZer6.d.ts → ConfigFieldRenderer-iMkZj0VK.d.ts} +2 -2
- package/dist/{FlowViewer-nLqo7s2E.d.cts → FlowViewer-CY3_vHSg.d.cts} +1 -1
- package/dist/{FlowViewer-C4QAVgWv.d.ts → FlowViewer-DGW6t-80.d.ts} +1 -1
- package/dist/{capabilities-CkhKj_U_.d.ts → capabilities-DMUhnyZD.d.ts} +2 -2
- package/dist/{capabilities-BtJQTbnw.d.cts → capabilities-Dmd26aAs.d.cts} +2 -2
- package/dist/chunk-BHM5HGXH.js +79 -0
- package/dist/chunk-BHM5HGXH.js.map +1 -0
- package/dist/{chunk-DHUFUDEX.js → chunk-HFUBVT7W.js} +3 -3
- package/dist/{chunk-DHUFUDEX.js.map → chunk-HFUBVT7W.js.map} +1 -1
- package/dist/{chunk-VLATLVGH.js → chunk-L43CWD63.js} +129 -5
- package/dist/chunk-L43CWD63.js.map +1 -0
- package/dist/{chunk-A6RFLGWV.js → chunk-MH4ZW4DJ.js} +3 -3
- package/dist/{chunk-A6RFLGWV.js.map → chunk-MH4ZW4DJ.js.map} +1 -1
- package/dist/{chunk-QZTGV3ZL.js → chunk-P5SYH6M6.js} +3 -3
- package/dist/{chunk-QZTGV3ZL.js.map → chunk-P5SYH6M6.js.map} +1 -1
- package/dist/{chunk-WBXGZVLB.js → chunk-RMU6YCIQ.js} +11 -5
- package/dist/chunk-RMU6YCIQ.js.map +1 -0
- package/dist/durable/index.d.cts +490 -0
- package/dist/durable/index.d.ts +490 -0
- package/dist/durable.cjs +927 -0
- package/dist/durable.cjs.map +1 -0
- package/dist/durable.js +552 -0
- package/dist/durable.js.map +1 -0
- package/dist/engine.cjs +198 -12
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +44 -7
- package/dist/engine.d.ts +44 -7
- package/dist/engine.js +68 -12
- package/dist/engine.js.map +1 -1
- package/dist/fields/react-fancy.d.cts +4 -3
- package/dist/fields/react-fancy.d.ts +4 -3
- package/dist/index.cjs +133 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -10
- package/dist/index.d.ts +12 -10
- package/dist/index.js +13 -88
- package/dist/index.js.map +1 -1
- package/dist/layout/index.d.cts +1 -1
- package/dist/layout/index.d.ts +1 -1
- package/dist/llm/prism.d.cts +2 -2
- package/dist/llm/prism.d.ts +2 -2
- package/dist/llm/vercel-ai.d.cts +2 -2
- package/dist/llm/vercel-ai.d.ts +2 -2
- package/dist/pause-9iT4tCEV.d.cts +96 -0
- package/dist/pause-9iT4tCEV.d.ts +96 -0
- package/dist/registry/index.d.cts +7 -6
- package/dist/registry/index.d.ts +7 -6
- package/dist/{registry-C9KMVpn7.d.cts → registry-D_kyUZEf.d.cts} +1 -1
- package/dist/{registry-FGCBprcn.d.ts → registry-LHB3MlR9.d.ts} +1 -1
- package/dist/registry.cjs +133 -3
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +4 -4
- package/dist/{run-cohort-BnP6ErHi.d.ts → run-cohort-Cyeny2Uu.d.ts} +3 -34
- package/dist/{run-cohort-Bjv2ZU6g.d.cts → run-cohort-DdPPowJ3.d.cts} +3 -34
- package/dist/run-flow-1KiXhy59.d.cts +55 -0
- package/dist/run-flow-CQvTDBYk.d.ts +55 -0
- package/dist/runtime/index.d.cts +5 -3
- package/dist/runtime/index.d.ts +5 -3
- package/dist/runtime.cjs +128 -2
- 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/screens.d.cts +2 -2
- package/dist/screens.d.ts +2 -2
- package/dist/screens.js +6 -6
- package/dist/{types-JViq8reb.d.ts → types--S2Kzx7w.d.cts} +3 -97
- package/dist/{types-B78Rm69S.d.cts → types-ChkCRonF.d.ts} +3 -97
- package/dist/types-Jx1TwehV.d.cts +247 -0
- package/dist/types-Jx1TwehV.d.ts +247 -0
- package/dist/ux.d.cts +3 -2
- package/dist/ux.d.ts +3 -2
- package/package.json +12 -2
- package/dist/chunk-VLATLVGH.js.map +0 -1
- package/dist/chunk-WBXGZVLB.js.map +0 -1
- package/dist/types-sOmpCitB.d.cts +0 -109
- package/dist/types-sOmpCitB.d.ts +0 -109
package/dist/runtime.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { applyOutputsToNodes, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState } from './chunk-
|
|
2
|
-
export { runCohort } from './chunk-
|
|
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-
|
|
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
|
package/dist/schema/index.d.cts
CHANGED
package/dist/schema/index.d.ts
CHANGED
package/dist/screens.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { F as FlowNodeStatus, a as FlowViewer, b as FlowViewerClassNames, c as FlowViewerProps } from './FlowViewer-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
2
|
-
export { FlowViewer } from './chunk-
|
|
3
|
-
import './chunk-
|
|
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-
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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 };
|