@particle-academy/fancy-flow 0.45.0 → 0.47.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 (101) hide show
  1. package/README.md +29 -0
  2. package/dist/{ConfigFieldRenderer-Dzy4f6rG.d.cts → ConfigFieldRenderer-Cyir8-B8.d.cts} +2 -2
  3. package/dist/{ConfigFieldRenderer-WqJr-td_.d.ts → ConfigFieldRenderer-iMkZj0VK.d.ts} +2 -2
  4. package/dist/{FlowViewer-BbbUJe2b.d.cts → FlowViewer-CY3_vHSg.d.cts} +1 -1
  5. package/dist/{FlowViewer-csuaTL5t.d.ts → FlowViewer-DGW6t-80.d.ts} +1 -1
  6. package/dist/{capabilities-Brn74URS.d.ts → capabilities-DMUhnyZD.d.ts} +1 -1
  7. package/dist/{capabilities-CYCeIx6I.d.cts → capabilities-Dmd26aAs.d.cts} +1 -1
  8. package/dist/chunk-BHM5HGXH.js +79 -0
  9. package/dist/chunk-BHM5HGXH.js.map +1 -0
  10. package/dist/chunk-DR3GWVDG.js +196 -0
  11. package/dist/chunk-DR3GWVDG.js.map +1 -0
  12. package/dist/{chunk-3BKU4SQZ.js → chunk-ISXRQELT.js} +3 -4
  13. package/dist/chunk-ISXRQELT.js.map +1 -0
  14. package/dist/{chunk-OWENS2H5.js → chunk-NDEX655E.js} +1603 -36
  15. package/dist/chunk-NDEX655E.js.map +1 -0
  16. package/dist/{chunk-QZTGV3ZL.js → chunk-QVFVL5LQ.js} +3 -3
  17. package/dist/{chunk-QZTGV3ZL.js.map → chunk-QVFVL5LQ.js.map} +1 -1
  18. package/dist/{chunk-DHUFUDEX.js → chunk-Z2GRNYR2.js} +7 -6
  19. package/dist/chunk-Z2GRNYR2.js.map +1 -0
  20. package/dist/{chunk-A6RFLGWV.js → chunk-ZKJJWBDJ.js} +3 -5
  21. package/dist/chunk-ZKJJWBDJ.js.map +1 -0
  22. package/dist/durable/index.d.cts +490 -0
  23. package/dist/durable/index.d.ts +490 -0
  24. package/dist/durable.cjs +10991 -0
  25. package/dist/durable.cjs.map +1 -0
  26. package/dist/durable.js +552 -0
  27. package/dist/durable.js.map +1 -0
  28. package/dist/engine.cjs +10223 -47
  29. package/dist/engine.cjs.map +1 -1
  30. package/dist/engine.d.cts +9 -7
  31. package/dist/engine.d.ts +9 -7
  32. package/dist/engine.js +4 -6
  33. package/dist/engine.js.map +1 -1
  34. package/dist/fields/react-fancy.d.cts +4 -3
  35. package/dist/fields/react-fancy.d.ts +4 -3
  36. package/dist/index.cjs +336 -194
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +12 -10
  39. package/dist/index.d.ts +12 -10
  40. package/dist/index.js +15 -93
  41. package/dist/index.js.map +1 -1
  42. package/dist/layout/index.d.cts +1 -1
  43. package/dist/layout/index.d.ts +1 -1
  44. package/dist/llm/prism.d.cts +2 -2
  45. package/dist/llm/prism.d.ts +2 -2
  46. package/dist/llm/vercel-ai.d.cts +2 -2
  47. package/dist/llm/vercel-ai.d.ts +2 -2
  48. package/dist/pause-9iT4tCEV.d.cts +96 -0
  49. package/dist/pause-9iT4tCEV.d.ts +96 -0
  50. package/dist/registry/index.d.cts +7 -6
  51. package/dist/registry/index.d.ts +7 -6
  52. package/dist/{registry-Budds73w.d.cts → registry-Bt55f63_.d.ts} +21 -2
  53. package/dist/{registry-D0I20HJ3.d.ts → registry-CkcSwmfR.d.cts} +21 -2
  54. package/dist/registry.cjs +3961 -3821
  55. package/dist/registry.cjs.map +1 -1
  56. package/dist/registry.js +3 -6
  57. package/dist/{run-cohort-CV7EcwGG.d.ts → run-cohort-Cyeny2Uu.d.ts} +3 -34
  58. package/dist/{run-cohort-DitsaYgS.d.cts → run-cohort-DdPPowJ3.d.cts} +3 -34
  59. package/dist/run-flow-1KiXhy59.d.cts +55 -0
  60. package/dist/run-flow-CQvTDBYk.d.ts +55 -0
  61. package/dist/runtime/index.d.cts +5 -3
  62. package/dist/runtime/index.d.ts +5 -3
  63. package/dist/runtime.cjs +1712 -430
  64. package/dist/runtime.cjs.map +1 -1
  65. package/dist/runtime.js +5 -6
  66. package/dist/schema/index.d.cts +1 -1
  67. package/dist/schema/index.d.ts +1 -1
  68. package/dist/schema.cjs +10369 -24
  69. package/dist/schema.cjs.map +1 -1
  70. package/dist/schema.js +4 -3
  71. package/dist/screens.cjs +1366 -38
  72. package/dist/screens.cjs.map +1 -1
  73. package/dist/screens.d.cts +2 -2
  74. package/dist/screens.d.ts +2 -2
  75. package/dist/screens.js +5 -8
  76. package/dist/screens.js.map +1 -1
  77. package/dist/{types-D6ZSKBly.d.ts → types--S2Kzx7w.d.cts} +3 -97
  78. package/dist/{types-nQOA8jpk.d.cts → types-ChkCRonF.d.ts} +3 -97
  79. package/dist/types-Jx1TwehV.d.cts +247 -0
  80. package/dist/types-Jx1TwehV.d.ts +247 -0
  81. package/dist/ux.cjs +10363 -2
  82. package/dist/ux.cjs.map +1 -1
  83. package/dist/ux.d.cts +3 -2
  84. package/dist/ux.d.ts +3 -2
  85. package/dist/ux.js +3 -1
  86. package/dist/ux.js.map +1 -1
  87. package/package.json +17 -3
  88. package/dist/chunk-3BKU4SQZ.js.map +0 -1
  89. package/dist/chunk-A6RFLGWV.js.map +0 -1
  90. package/dist/chunk-DHUFUDEX.js.map +0 -1
  91. package/dist/chunk-OWENS2H5.js.map +0 -1
  92. package/dist/chunk-PVROYW7C.js +0 -187
  93. package/dist/chunk-PVROYW7C.js.map +0 -1
  94. package/dist/chunk-TITD5W4Y.js +0 -26
  95. package/dist/chunk-TITD5W4Y.js.map +0 -1
  96. package/dist/chunk-VLATLVGH.js +0 -158
  97. package/dist/chunk-VLATLVGH.js.map +0 -1
  98. package/dist/chunk-WBXGZVLB.js +0 -1268
  99. package/dist/chunk-WBXGZVLB.js.map +0 -1
  100. package/dist/types-CMSrWVYM.d.cts +0 -109
  101. package/dist/types-CMSrWVYM.d.ts +0 -109
@@ -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 };