footprintjs 9.26.0 → 9.28.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/AGENTS.md +3 -0
- package/CLAUDE.md +5 -4
- package/README.md +4 -0
- package/dist/advanced.js +3 -2
- package/dist/esm/advanced.d.ts +2 -2
- package/dist/esm/advanced.js +2 -2
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/lib/builder/FlowChartBuilder.d.ts +10 -0
- package/dist/esm/lib/builder/FlowChartBuilder.js +27 -13
- package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +45 -12
- package/dist/esm/lib/engine/handlers/ResumeEntry.d.ts +195 -0
- package/dist/esm/lib/engine/handlers/ResumeEntry.js +471 -0
- package/dist/esm/lib/engine/handlers/SubflowExecutor.d.ts +6 -0
- package/dist/esm/lib/engine/handlers/SubflowExecutor.js +43 -10
- package/dist/esm/lib/engine/handlers/index.d.ts +2 -0
- package/dist/esm/lib/engine/handlers/index.js +2 -1
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +1 -1
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.d.ts +49 -4
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +64 -13
- package/dist/esm/lib/engine/types.d.ts +30 -11
- package/dist/esm/lib/engine/types.js +1 -1
- package/dist/esm/lib/pause/index.d.ts +1 -1
- package/dist/esm/lib/pause/index.js +1 -1
- package/dist/esm/lib/pause/types.d.ts +93 -5
- package/dist/esm/lib/pause/types.js +57 -3
- package/dist/esm/lib/runner/FlowChartExecutor.d.ts +8 -10
- package/dist/esm/lib/runner/FlowChartExecutor.js +153 -181
- package/dist/esm/lib/time-travel/bundles.js +11 -1
- package/dist/index.js +1 -1
- package/dist/lib/builder/FlowChartBuilder.js +27 -13
- package/dist/lib/engine/handlers/ChildrenExecutor.js +45 -12
- package/dist/lib/engine/handlers/ResumeEntry.js +478 -0
- package/dist/lib/engine/handlers/SubflowExecutor.js +43 -10
- package/dist/lib/engine/handlers/index.js +4 -2
- package/dist/lib/engine/traversal/FlowchartTraverser.js +64 -13
- package/dist/lib/engine/types.js +1 -1
- package/dist/lib/pause/index.js +1 -1
- package/dist/lib/pause/types.js +57 -3
- package/dist/lib/runner/FlowChartExecutor.js +153 -181
- package/dist/lib/time-travel/bundles.js +11 -1
- package/dist/types/advanced.d.ts +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/lib/builder/FlowChartBuilder.d.ts +10 -0
- package/dist/types/lib/engine/handlers/ResumeEntry.d.ts +195 -0
- package/dist/types/lib/engine/handlers/SubflowExecutor.d.ts +6 -0
- package/dist/types/lib/engine/handlers/index.d.ts +2 -0
- package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +1 -1
- package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +49 -4
- package/dist/types/lib/engine/types.d.ts +30 -11
- package/dist/types/lib/pause/index.d.ts +1 -1
- package/dist/types/lib/pause/types.d.ts +93 -5
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +8 -10
- package/package.json +1 -1
|
@@ -14,7 +14,16 @@
|
|
|
14
14
|
* Resume rebuilds the flowchart, restores scope, navigates to the paused stage,
|
|
15
15
|
* injects resumeInput, and continues traversal.
|
|
16
16
|
*
|
|
17
|
-
* Supported topologies: linear, subflow
|
|
17
|
+
* Supported topologies: linear, subflow (at any depth — mounted linearly, as a
|
|
18
|
+
* decider or selector branch, or as a fork child), loop, nested subflow in
|
|
19
|
+
* loop, and several parallel siblings pausing in one fan-out (each asks in
|
|
20
|
+
* turn — `FlowchartCheckpoint.pendingPauses`).
|
|
21
|
+
*
|
|
22
|
+
* NOT resumable yet: a pause inside a LAZY subflow (`addLazySubFlowChart*`) or
|
|
23
|
+
* inside an `addParallelForEach` branch. Their graphs are resolved at run time
|
|
24
|
+
* and are not in the chart a resume walks, so `resume()` refuses the
|
|
25
|
+
* checkpoint ("not found") instead of guessing. Pinned in
|
|
26
|
+
* test/lib/pause/resume-known-limitations.test.ts.
|
|
18
27
|
*/
|
|
19
28
|
/**
|
|
20
29
|
* Thrown by `scope.$pause()` to signal that execution should stop
|
|
@@ -65,10 +74,35 @@ export declare class PauseSignal extends Error {
|
|
|
65
74
|
* crash with "X is not iterable" / undefined.
|
|
66
75
|
*/
|
|
67
76
|
private _subflowStates;
|
|
77
|
+
/**
|
|
78
|
+
* Pauses that PARALLEL SIBLINGS raised in the same fan-out as this one,
|
|
79
|
+
* waiting their turn (9.28.0). Recorded by `ChildrenExecutor` when more
|
|
80
|
+
* than one child of a fork (or more than one selected branch) pauses: the
|
|
81
|
+
* first pause is the one that is asked, the others ride here instead of
|
|
82
|
+
* being dropped. Each path is relative to where the signal currently is
|
|
83
|
+
* and grows with it — `prependSubflow` prepends to every entry too.
|
|
84
|
+
*/
|
|
85
|
+
private _pendingPauses;
|
|
68
86
|
constructor(data: unknown, stageId: string, pausedBy?: 'interrupt');
|
|
69
87
|
get subflowPath(): readonly string[];
|
|
70
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Prepend a subflow ID to the path (called during bubble-up). The pending
|
|
90
|
+
* sibling pauses ride the same boundary, so their paths grow with it.
|
|
91
|
+
*/
|
|
71
92
|
prependSubflow(subflowId: string): void;
|
|
93
|
+
/**
|
|
94
|
+
* Queue a parallel sibling's pause behind this one (its path relative to
|
|
95
|
+
* this signal's current level). Copied in: the entry is owned by the
|
|
96
|
+
* signal from here on.
|
|
97
|
+
*/
|
|
98
|
+
addPendingPause(pause: PendingPause): void;
|
|
99
|
+
/** Parallel siblings' pauses waiting behind this one, in the order they will be asked. */
|
|
100
|
+
get pendingPauses(): readonly PendingPause[];
|
|
101
|
+
/**
|
|
102
|
+
* This pause as a {@link PendingPause} — what `ChildrenExecutor` queues
|
|
103
|
+
* behind a sibling's pause when both paused in one fan-out.
|
|
104
|
+
*/
|
|
105
|
+
toPendingPause(): PendingPause;
|
|
72
106
|
/** The stage that invoked the paused child (decider, selector, fork). */
|
|
73
107
|
get invokerStageId(): string | undefined;
|
|
74
108
|
/** Where execution should continue after resume (invoker's next node). */
|
|
@@ -93,6 +127,42 @@ export declare class PauseSignal extends Error {
|
|
|
93
127
|
/** Captured subflow scopes (read-only view). */
|
|
94
128
|
get subflowStates(): Readonly<Record<string, Record<string, unknown>>>;
|
|
95
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* A pause a PARALLEL SIBLING of the paused stage raised in the same fan-out —
|
|
132
|
+
* two children of one fork (or two selected branches of one selector) that
|
|
133
|
+
* both paused (9.28.0). Only one pause is asked at a time: the checkpoint's
|
|
134
|
+
* own (`pausedStageId`), then each of these in turn, with the fan-out's join
|
|
135
|
+
* running only once every child is done.
|
|
136
|
+
*
|
|
137
|
+
* Everything needed to raise the sibling's pause again later WITHOUT re-running
|
|
138
|
+
* the sibling: its stage, its path, its captured subflow state, its question.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```typescript
|
|
142
|
+
* // A fork whose two children both ask: the first checkpoint asks c1 and
|
|
143
|
+
* // carries c2's pause; resuming it finishes c1, then pauses with c2's
|
|
144
|
+
* // question; resuming THAT finishes c2 and runs the join.
|
|
145
|
+
* const cp = executor.getCheckpoint()!;
|
|
146
|
+
* cp.pausedStageId; // 'c1/ask'
|
|
147
|
+
* cp.pendingPauses?.[0].pausedStageId; // 'c2/ask'
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export interface PendingPause {
|
|
151
|
+
/** The sibling's paused stage (path-prefixed id, as `pausedStageId`). */
|
|
152
|
+
readonly pausedStageId: string;
|
|
153
|
+
/** Path through subflows to the sibling's paused stage (as `subflowPath`). */
|
|
154
|
+
readonly subflowPath: readonly string[];
|
|
155
|
+
/**
|
|
156
|
+
* The sibling's own subflow captures — the subflows on ITS path below the
|
|
157
|
+
* fan-out. The subflows above the fan-out are shared with the checkpoint's
|
|
158
|
+
* own pause and are captured again when this pause is raised.
|
|
159
|
+
*/
|
|
160
|
+
readonly subflowStates: Record<string, Record<string, unknown>>;
|
|
161
|
+
/** The sibling's question (as `pauseData`). */
|
|
162
|
+
readonly pauseData?: unknown;
|
|
163
|
+
/** How the sibling paused (as `pausedBy`). */
|
|
164
|
+
readonly pausedBy?: 'interrupt';
|
|
165
|
+
}
|
|
96
166
|
/**
|
|
97
167
|
* Returned by a pausable stage's execute/resume function to signal pause.
|
|
98
168
|
*
|
|
@@ -183,8 +253,10 @@ export interface FlowchartCheckpoint {
|
|
|
183
253
|
*
|
|
184
254
|
* Always present (empty `{}` for root-level pauses where no subflows
|
|
185
255
|
* were entered). On resume, `SubflowExecutor` seeds each nested runtime
|
|
186
|
-
* from this map
|
|
187
|
-
*
|
|
256
|
+
* on the path from this map — ONCE, on its first entry, in place of the
|
|
257
|
+
* inputMapper's values (the mapper still runs, for the stages' read-only
|
|
258
|
+
* args) — so resume handlers see pre-pause scope across same-executor AND
|
|
259
|
+
* cross-executor restarts. Only the subflows ON `subflowPath` read it.
|
|
188
260
|
*/
|
|
189
261
|
readonly subflowStates: Record<string, Record<string, unknown>>;
|
|
190
262
|
/**
|
|
@@ -209,8 +281,24 @@ export interface FlowchartCheckpoint {
|
|
|
209
281
|
readonly visitCounts?: Readonly<Record<string, number>>;
|
|
210
282
|
/** Stage that invoked the paused child (decider, selector, fork). Absent for linear pauses. */
|
|
211
283
|
readonly invokerStageId?: string;
|
|
212
|
-
/**
|
|
284
|
+
/**
|
|
285
|
+
* The invoker's next node ID. Absent for linear pauses.
|
|
286
|
+
*
|
|
287
|
+
* A RECORD, not an instruction: since 9.28.0 `resume()` derives what runs
|
|
288
|
+
* after the paused stage from the chart itself (the stage's own `next`, else
|
|
289
|
+
* the continuation of the dispatcher that ran it — at every level of the
|
|
290
|
+
* pause path), so an edited value cannot redirect a resumed run.
|
|
291
|
+
*/
|
|
213
292
|
readonly continuationStageId?: string;
|
|
293
|
+
/**
|
|
294
|
+
* Pauses raised by PARALLEL SIBLINGS of the paused stage in the same
|
|
295
|
+
* fan-out, waiting their turn (9.28.0) — see {@link PendingPause}. Absent
|
|
296
|
+
* when only one child paused (every checkpoint before 9.28.0 omits it, and
|
|
297
|
+
* resumes exactly as before). Resuming this checkpoint finishes the paused
|
|
298
|
+
* stage's child, then pauses again with the first of these; the fan-out's
|
|
299
|
+
* join runs once every child is done.
|
|
300
|
+
*/
|
|
301
|
+
readonly pendingPauses?: readonly PendingPause[];
|
|
214
302
|
/** Timestamp of when the pause occurred. */
|
|
215
303
|
readonly pausedAt: number;
|
|
216
304
|
}
|
|
@@ -320,7 +320,14 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
320
320
|
* Resume a paused flowchart from a checkpoint.
|
|
321
321
|
*
|
|
322
322
|
* Restores the scope state, calls the paused stage's `resumeFn` with the
|
|
323
|
-
* provided input,
|
|
323
|
+
* provided input (or, for an `interrupt()` pause, re-runs the stage with the
|
|
324
|
+
* answer), then continues with whatever ran after that stage on the run —
|
|
325
|
+
* its own `next`, or the continuation of the decider, selector or fork that
|
|
326
|
+
* dispatched it, at every level of the pause path — and from there walks the
|
|
327
|
+
* chart as built. When parallel siblings paused in the same fan-out
|
|
328
|
+
* (`checkpoint.pendingPauses`), the run pauses again with the next sibling's
|
|
329
|
+
* question once this one's branch is done; the fan-out's join runs after the
|
|
330
|
+
* last answer. See `ResumeEntry` (`footprintjs/advanced`).
|
|
324
331
|
*
|
|
325
332
|
* The checkpoint can come from `getCheckpoint()` on a previous run, or from
|
|
326
333
|
* a serialized checkpoint stored in Redis/Postgres/localStorage.
|
|
@@ -392,15 +399,6 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
392
399
|
* Handles subflow paths by drilling into registered subflows.
|
|
393
400
|
*/
|
|
394
401
|
private findNodeInGraph;
|
|
395
|
-
/**
|
|
396
|
-
* Find the mount node (the node that mounts a subflow boundary)
|
|
397
|
-
* for a given subflowId, by DFS from `start`. Used by `resume()` to
|
|
398
|
-
* locate the OUTER node we have to enter through so the subflow's
|
|
399
|
-
* outputMapper and parent continuation execute.
|
|
400
|
-
*
|
|
401
|
-
* Cycle-safe via visited set. Returns the first match (DFS order).
|
|
402
|
-
*/
|
|
403
|
-
private findMountInGraph;
|
|
404
402
|
/** DFS search for a node by ID in the StageNode graph. Cycle-safe via visited set. */
|
|
405
403
|
private dfsFind;
|
|
406
404
|
/**
|
package/package.json
CHANGED