awaitly 1.0.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/LICENSE +21 -0
- package/README.md +1278 -0
- package/dist/batch.cjs +2 -0
- package/dist/batch.cjs.map +1 -0
- package/dist/batch.d.cts +197 -0
- package/dist/batch.d.ts +197 -0
- package/dist/batch.js +2 -0
- package/dist/batch.js.map +1 -0
- package/dist/circuit-breaker.cjs +2 -0
- package/dist/circuit-breaker.cjs.map +1 -0
- package/dist/circuit-breaker.d.cts +208 -0
- package/dist/circuit-breaker.d.ts +208 -0
- package/dist/circuit-breaker.js +2 -0
- package/dist/circuit-breaker.js.map +1 -0
- package/dist/conditional.cjs +2 -0
- package/dist/conditional.cjs.map +1 -0
- package/dist/conditional.d.cts +249 -0
- package/dist/conditional.d.ts +249 -0
- package/dist/conditional.js +2 -0
- package/dist/conditional.js.map +1 -0
- package/dist/core-BuTBsR0x.d.cts +2325 -0
- package/dist/core-BuTBsR0x.d.ts +2325 -0
- package/dist/core.cjs +2 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +3 -0
- package/dist/core.d.ts +3 -0
- package/dist/core.js +2 -0
- package/dist/core.js.map +1 -0
- package/dist/devtools.cjs +11 -0
- package/dist/devtools.cjs.map +1 -0
- package/dist/devtools.d.cts +176 -0
- package/dist/devtools.d.ts +176 -0
- package/dist/devtools.js +11 -0
- package/dist/devtools.js.map +1 -0
- package/dist/duration.cjs +2 -0
- package/dist/duration.cjs.map +1 -0
- package/dist/duration.d.cts +246 -0
- package/dist/duration.d.ts +246 -0
- package/dist/duration.js +2 -0
- package/dist/duration.js.map +1 -0
- package/dist/hitl.cjs +2 -0
- package/dist/hitl.cjs.map +1 -0
- package/dist/hitl.d.cts +337 -0
- package/dist/hitl.d.ts +337 -0
- package/dist/hitl.js +2 -0
- package/dist/hitl.js.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/match.cjs +2 -0
- package/dist/match.cjs.map +1 -0
- package/dist/match.d.cts +209 -0
- package/dist/match.d.ts +209 -0
- package/dist/match.js +2 -0
- package/dist/match.js.map +1 -0
- package/dist/otel.cjs +2 -0
- package/dist/otel.cjs.map +1 -0
- package/dist/otel.d.cts +185 -0
- package/dist/otel.d.ts +185 -0
- package/dist/otel.js +2 -0
- package/dist/otel.js.map +1 -0
- package/dist/persistence.cjs +2 -0
- package/dist/persistence.cjs.map +1 -0
- package/dist/persistence.d.cts +572 -0
- package/dist/persistence.d.ts +572 -0
- package/dist/persistence.js +2 -0
- package/dist/persistence.js.map +1 -0
- package/dist/policies.cjs +2 -0
- package/dist/policies.cjs.map +1 -0
- package/dist/policies.d.cts +378 -0
- package/dist/policies.d.ts +378 -0
- package/dist/policies.js +2 -0
- package/dist/policies.js.map +1 -0
- package/dist/ratelimit.cjs +2 -0
- package/dist/ratelimit.cjs.map +1 -0
- package/dist/ratelimit.d.cts +279 -0
- package/dist/ratelimit.d.ts +279 -0
- package/dist/ratelimit.js +2 -0
- package/dist/ratelimit.js.map +1 -0
- package/dist/reliability.cjs +2 -0
- package/dist/reliability.cjs.map +1 -0
- package/dist/reliability.d.cts +5 -0
- package/dist/reliability.d.ts +5 -0
- package/dist/reliability.js +2 -0
- package/dist/reliability.js.map +1 -0
- package/dist/resource.cjs +2 -0
- package/dist/resource.cjs.map +1 -0
- package/dist/resource.d.cts +171 -0
- package/dist/resource.d.ts +171 -0
- package/dist/resource.js +2 -0
- package/dist/resource.js.map +1 -0
- package/dist/retry.cjs +2 -0
- package/dist/retry.cjs.map +1 -0
- package/dist/retry.d.cts +2 -0
- package/dist/retry.d.ts +2 -0
- package/dist/retry.js +2 -0
- package/dist/retry.js.map +1 -0
- package/dist/saga.cjs +2 -0
- package/dist/saga.cjs.map +1 -0
- package/dist/saga.d.cts +231 -0
- package/dist/saga.d.ts +231 -0
- package/dist/saga.js +2 -0
- package/dist/saga.js.map +1 -0
- package/dist/schedule.cjs +2 -0
- package/dist/schedule.cjs.map +1 -0
- package/dist/schedule.d.cts +387 -0
- package/dist/schedule.d.ts +387 -0
- package/dist/schedule.js +2 -0
- package/dist/schedule.js.map +1 -0
- package/dist/tagged-error.cjs +2 -0
- package/dist/tagged-error.cjs.map +1 -0
- package/dist/tagged-error.d.cts +252 -0
- package/dist/tagged-error.d.ts +252 -0
- package/dist/tagged-error.js +2 -0
- package/dist/tagged-error.js.map +1 -0
- package/dist/testing.cjs +2 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +228 -0
- package/dist/testing.d.ts +228 -0
- package/dist/testing.js +2 -0
- package/dist/testing.js.map +1 -0
- package/dist/visualize.cjs +1573 -0
- package/dist/visualize.cjs.map +1 -0
- package/dist/visualize.d.cts +1415 -0
- package/dist/visualize.d.ts +1415 -0
- package/dist/visualize.js +1573 -0
- package/dist/visualize.js.map +1 -0
- package/dist/webhook.cjs +2 -0
- package/dist/webhook.cjs.map +1 -0
- package/dist/webhook.d.cts +469 -0
- package/dist/webhook.d.ts +469 -0
- package/dist/webhook.js +2 -0
- package/dist/webhook.js.map +1 -0
- package/dist/workflow-entry-C6nH8ByN.d.ts +858 -0
- package/dist/workflow-entry-RRTlSg_4.d.cts +858 -0
- package/dist/workflow.cjs +2 -0
- package/dist/workflow.cjs.map +1 -0
- package/dist/workflow.d.cts +2 -0
- package/dist/workflow.d.ts +2 -0
- package/dist/workflow.js +2 -0
- package/dist/workflow.js.map +1 -0
- package/docs/advanced.md +1548 -0
- package/docs/api.md +513 -0
- package/docs/coming-from-neverthrow.md +1013 -0
- package/docs/match.md +417 -0
- package/docs/pino-logging-example.md +396 -0
- package/docs/policies.md +508 -0
- package/docs/resource-management.md +509 -0
- package/docs/schedule.md +467 -0
- package/docs/tagged-error.md +785 -0
- package/docs/visualization.md +430 -0
- package/docs/visualize-examples.md +330 -0
- package/package.json +227 -0
|
@@ -0,0 +1,1415 @@
|
|
|
1
|
+
import { k as ScopeType, W as WorkflowEvent } from './core-BuTBsR0x.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Workflow Visualization - Intermediate Representation Types
|
|
5
|
+
*
|
|
6
|
+
* The IR (Intermediate Representation) is a DSL that represents workflow
|
|
7
|
+
* execution structure. Events are converted to IR, which can then be
|
|
8
|
+
* rendered to various output formats (ASCII, Mermaid, JSON, etc.).
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Execution state of a step with semantic meaning for visualization.
|
|
12
|
+
*
|
|
13
|
+
* Color mapping:
|
|
14
|
+
* - pending → white/clear (not started)
|
|
15
|
+
* - running → yellow (currently executing)
|
|
16
|
+
* - success → green (completed successfully)
|
|
17
|
+
* - error → red (failed with error)
|
|
18
|
+
* - aborted → gray (cancelled, e.g., in race)
|
|
19
|
+
* - cached → blue (served from cache)
|
|
20
|
+
* - skipped → dim gray (not executed due to conditional logic)
|
|
21
|
+
*/
|
|
22
|
+
type StepState = "pending" | "running" | "success" | "error" | "aborted" | "cached" | "skipped";
|
|
23
|
+
/**
|
|
24
|
+
* Base properties shared by all IR nodes.
|
|
25
|
+
*/
|
|
26
|
+
interface BaseNode {
|
|
27
|
+
/** Unique identifier for this node */
|
|
28
|
+
id: string;
|
|
29
|
+
/** Human-readable name (from step options or inferred) */
|
|
30
|
+
name?: string;
|
|
31
|
+
/** Cache key if this is a keyed step */
|
|
32
|
+
key?: string;
|
|
33
|
+
/** Current execution state */
|
|
34
|
+
state: StepState;
|
|
35
|
+
/** Timestamp when execution started */
|
|
36
|
+
startTs?: number;
|
|
37
|
+
/** Timestamp when execution ended */
|
|
38
|
+
endTs?: number;
|
|
39
|
+
/** Duration in milliseconds */
|
|
40
|
+
durationMs?: number;
|
|
41
|
+
/** Error value if state is 'error' */
|
|
42
|
+
error?: unknown;
|
|
43
|
+
/** Input value that triggered this step (for decision understanding) */
|
|
44
|
+
input?: unknown;
|
|
45
|
+
/** Output value from this step (for decision understanding) */
|
|
46
|
+
output?: unknown;
|
|
47
|
+
/** Number of retry attempts made (0 = no retries, 1 = one retry, etc.) */
|
|
48
|
+
retryCount?: number;
|
|
49
|
+
/** Whether this step experienced a timeout (may have retried after) */
|
|
50
|
+
timedOut?: boolean;
|
|
51
|
+
/** Timeout duration in ms (if timed out) */
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A single step execution node.
|
|
56
|
+
*/
|
|
57
|
+
interface StepNode extends BaseNode {
|
|
58
|
+
type: "step";
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Sequential execution - steps run one after another.
|
|
62
|
+
* This is the implicit structure when steps are awaited in sequence.
|
|
63
|
+
*/
|
|
64
|
+
interface SequenceNode extends BaseNode {
|
|
65
|
+
type: "sequence";
|
|
66
|
+
children: FlowNode[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Parallel execution - all branches run simultaneously.
|
|
70
|
+
* Created by allAsync() or allSettledAsync().
|
|
71
|
+
*/
|
|
72
|
+
interface ParallelNode extends BaseNode {
|
|
73
|
+
type: "parallel";
|
|
74
|
+
children: FlowNode[];
|
|
75
|
+
/**
|
|
76
|
+
* Execution mode:
|
|
77
|
+
* - 'all': Fails on first error (allAsync)
|
|
78
|
+
* - 'allSettled': Collects all results (allSettledAsync)
|
|
79
|
+
*/
|
|
80
|
+
mode: "all" | "allSettled";
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Race execution - first to complete wins.
|
|
84
|
+
* Created by anyAsync().
|
|
85
|
+
*/
|
|
86
|
+
interface RaceNode extends BaseNode {
|
|
87
|
+
type: "race";
|
|
88
|
+
children: FlowNode[];
|
|
89
|
+
/** ID of the winning branch (first to succeed) */
|
|
90
|
+
winnerId?: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Decision point - conditional branch (if/switch).
|
|
94
|
+
* Shows which branch was taken and why.
|
|
95
|
+
*/
|
|
96
|
+
interface DecisionNode extends BaseNode {
|
|
97
|
+
type: "decision";
|
|
98
|
+
/** Condition that was evaluated (e.g., "user.role === 'admin'") */
|
|
99
|
+
condition?: string;
|
|
100
|
+
/** Value that was evaluated (the input to the decision) */
|
|
101
|
+
decisionValue?: unknown;
|
|
102
|
+
/** Which branch was taken (true/false, or the matched case) */
|
|
103
|
+
branchTaken?: string | boolean;
|
|
104
|
+
/** All possible branches (including skipped ones) */
|
|
105
|
+
branches: DecisionBranch[];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* A branch in a decision node.
|
|
109
|
+
*/
|
|
110
|
+
interface DecisionBranch {
|
|
111
|
+
/** Label for this branch (e.g., "if", "else", "case 'admin'") */
|
|
112
|
+
label: string;
|
|
113
|
+
/** Condition that would trigger this branch */
|
|
114
|
+
condition?: string;
|
|
115
|
+
/** Whether this branch was taken */
|
|
116
|
+
taken: boolean;
|
|
117
|
+
/** Steps in this branch */
|
|
118
|
+
children: FlowNode[];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Union of all flow node types.
|
|
122
|
+
*/
|
|
123
|
+
type FlowNode = StepNode | SequenceNode | ParallelNode | RaceNode | DecisionNode;
|
|
124
|
+
/**
|
|
125
|
+
* Root node representing the entire workflow.
|
|
126
|
+
*/
|
|
127
|
+
interface WorkflowNode extends BaseNode {
|
|
128
|
+
type: "workflow";
|
|
129
|
+
/** Correlation ID from the workflow execution */
|
|
130
|
+
workflowId: string;
|
|
131
|
+
/** Child nodes (steps, parallel blocks, etc.) */
|
|
132
|
+
children: FlowNode[];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Complete workflow intermediate representation.
|
|
136
|
+
* This is the main data structure produced by the IR builder.
|
|
137
|
+
*/
|
|
138
|
+
interface WorkflowIR {
|
|
139
|
+
/** Root workflow node */
|
|
140
|
+
root: WorkflowNode;
|
|
141
|
+
/** Metadata about the IR */
|
|
142
|
+
metadata: {
|
|
143
|
+
/** When the IR was first created */
|
|
144
|
+
createdAt: number;
|
|
145
|
+
/** When the IR was last updated */
|
|
146
|
+
lastUpdatedAt: number;
|
|
147
|
+
};
|
|
148
|
+
/** Hook executions (if any hooks are configured) */
|
|
149
|
+
hooks?: WorkflowHooks;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Event emitted when entering a parallel/race scope.
|
|
154
|
+
* This matches the scope_start event in WorkflowEvent.
|
|
155
|
+
*/
|
|
156
|
+
interface ScopeStartEvent {
|
|
157
|
+
type: "scope_start";
|
|
158
|
+
workflowId: string;
|
|
159
|
+
scopeId: string;
|
|
160
|
+
scopeType: ScopeType;
|
|
161
|
+
name?: string;
|
|
162
|
+
ts: number;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Event emitted when exiting a parallel/race scope.
|
|
166
|
+
*/
|
|
167
|
+
interface ScopeEndEvent {
|
|
168
|
+
type: "scope_end";
|
|
169
|
+
workflowId: string;
|
|
170
|
+
scopeId: string;
|
|
171
|
+
ts: number;
|
|
172
|
+
durationMs: number;
|
|
173
|
+
/** For race scopes, the ID of the winning branch */
|
|
174
|
+
winnerId?: string;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Event emitted when a decision point is encountered.
|
|
178
|
+
* Use this to track conditional logic (if/switch).
|
|
179
|
+
*/
|
|
180
|
+
interface DecisionStartEvent {
|
|
181
|
+
type: "decision_start";
|
|
182
|
+
workflowId: string;
|
|
183
|
+
decisionId: string;
|
|
184
|
+
/** Condition being evaluated (e.g., "user.role === 'admin'") */
|
|
185
|
+
condition?: string;
|
|
186
|
+
/** Value being evaluated */
|
|
187
|
+
decisionValue?: unknown;
|
|
188
|
+
/** Name/label for this decision point */
|
|
189
|
+
name?: string;
|
|
190
|
+
ts: number;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Event emitted when a decision branch is taken.
|
|
194
|
+
*/
|
|
195
|
+
interface DecisionBranchEvent {
|
|
196
|
+
type: "decision_branch";
|
|
197
|
+
workflowId: string;
|
|
198
|
+
decisionId: string;
|
|
199
|
+
/** Label for this branch (e.g., "if", "else", "case 'admin'") */
|
|
200
|
+
branchLabel: string;
|
|
201
|
+
/** Condition for this branch */
|
|
202
|
+
condition?: string;
|
|
203
|
+
/** Whether this branch was taken */
|
|
204
|
+
taken: boolean;
|
|
205
|
+
ts: number;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Event emitted when a decision point completes.
|
|
209
|
+
*/
|
|
210
|
+
interface DecisionEndEvent {
|
|
211
|
+
type: "decision_end";
|
|
212
|
+
workflowId: string;
|
|
213
|
+
decisionId: string;
|
|
214
|
+
/** Which branch was taken */
|
|
215
|
+
branchTaken?: string | boolean;
|
|
216
|
+
ts: number;
|
|
217
|
+
durationMs: number;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Event emitted when a step is skipped due to conditional logic.
|
|
221
|
+
*/
|
|
222
|
+
interface StepSkippedEvent {
|
|
223
|
+
type: "step_skipped";
|
|
224
|
+
workflowId: string;
|
|
225
|
+
stepKey?: string;
|
|
226
|
+
name?: string;
|
|
227
|
+
/** Reason why this step was skipped (e.g., "condition was false") */
|
|
228
|
+
reason?: string;
|
|
229
|
+
/** The decision that caused this skip */
|
|
230
|
+
decisionId?: string;
|
|
231
|
+
ts: number;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Union of scope-related events.
|
|
235
|
+
*/
|
|
236
|
+
type ScopeEvent = ScopeStartEvent | ScopeEndEvent;
|
|
237
|
+
/**
|
|
238
|
+
* Union of decision-related events.
|
|
239
|
+
*/
|
|
240
|
+
type DecisionEvent = DecisionStartEvent | DecisionBranchEvent | DecisionEndEvent;
|
|
241
|
+
/**
|
|
242
|
+
* Color scheme for rendering step states.
|
|
243
|
+
*/
|
|
244
|
+
interface ColorScheme {
|
|
245
|
+
pending: string;
|
|
246
|
+
running: string;
|
|
247
|
+
success: string;
|
|
248
|
+
error: string;
|
|
249
|
+
aborted: string;
|
|
250
|
+
cached: string;
|
|
251
|
+
skipped: string;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Options passed to renderers.
|
|
255
|
+
*/
|
|
256
|
+
interface RenderOptions {
|
|
257
|
+
/** Show timing information (duration) */
|
|
258
|
+
showTimings: boolean;
|
|
259
|
+
/** Show step cache keys */
|
|
260
|
+
showKeys: boolean;
|
|
261
|
+
/** Terminal width for ASCII renderer */
|
|
262
|
+
terminalWidth?: number;
|
|
263
|
+
/** Color scheme */
|
|
264
|
+
colors: ColorScheme;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Extended options for Mermaid renderer.
|
|
268
|
+
* Controls how edges are displayed for retries, errors, and timeouts.
|
|
269
|
+
*/
|
|
270
|
+
interface MermaidRenderOptions extends RenderOptions {
|
|
271
|
+
/** Show retry as self-loop edge (default: true) */
|
|
272
|
+
showRetryEdges?: boolean;
|
|
273
|
+
/** Show error flow to error node (default: true) */
|
|
274
|
+
showErrorEdges?: boolean;
|
|
275
|
+
/** Show timeout as alternative path (default: true) */
|
|
276
|
+
showTimeoutEdges?: boolean;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Renderer interface - transforms IR to output format.
|
|
280
|
+
*/
|
|
281
|
+
interface Renderer {
|
|
282
|
+
/** Unique identifier for this renderer */
|
|
283
|
+
readonly name: string;
|
|
284
|
+
/** Render IR to string output */
|
|
285
|
+
render(ir: WorkflowIR, options: RenderOptions): string;
|
|
286
|
+
/** Whether this renderer supports live (incremental) updates */
|
|
287
|
+
supportsLive?: boolean;
|
|
288
|
+
/** Render incremental update (optional) */
|
|
289
|
+
renderUpdate?(ir: WorkflowIR, changedNodes: FlowNode[], options: RenderOptions): string;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Output format for rendering.
|
|
293
|
+
*/
|
|
294
|
+
type OutputFormat = "ascii" | "mermaid" | "json" | "logger" | "flowchart";
|
|
295
|
+
/**
|
|
296
|
+
* Options for creating a visualizer.
|
|
297
|
+
*/
|
|
298
|
+
interface VisualizerOptions {
|
|
299
|
+
/** Name for the workflow in visualizations */
|
|
300
|
+
workflowName?: string;
|
|
301
|
+
/** Enable parallel detection heuristics (default: true) */
|
|
302
|
+
detectParallel?: boolean;
|
|
303
|
+
/** Show timing information (default: true) */
|
|
304
|
+
showTimings?: boolean;
|
|
305
|
+
/** Show step keys (default: false) */
|
|
306
|
+
showKeys?: boolean;
|
|
307
|
+
/** Custom color scheme */
|
|
308
|
+
colors?: Partial<ColorScheme>;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Options for live visualization.
|
|
312
|
+
*/
|
|
313
|
+
interface LiveVisualizerOptions extends VisualizerOptions {
|
|
314
|
+
/** Output stream (default: process.stdout) */
|
|
315
|
+
stream?: NodeJS.WriteStream;
|
|
316
|
+
/** Update interval in ms (default: 100) */
|
|
317
|
+
updateInterval?: number;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Check if a node is a StepNode.
|
|
321
|
+
*/
|
|
322
|
+
declare function isStepNode(node: FlowNode): node is StepNode;
|
|
323
|
+
/**
|
|
324
|
+
* Check if a node is a SequenceNode.
|
|
325
|
+
*/
|
|
326
|
+
declare function isSequenceNode(node: FlowNode): node is SequenceNode;
|
|
327
|
+
/**
|
|
328
|
+
* Check if a node is a ParallelNode.
|
|
329
|
+
*/
|
|
330
|
+
declare function isParallelNode(node: FlowNode): node is ParallelNode;
|
|
331
|
+
/**
|
|
332
|
+
* Check if a node is a RaceNode.
|
|
333
|
+
*/
|
|
334
|
+
declare function isRaceNode(node: FlowNode): node is RaceNode;
|
|
335
|
+
/**
|
|
336
|
+
* Check if a node is a DecisionNode.
|
|
337
|
+
*/
|
|
338
|
+
declare function isDecisionNode(node: FlowNode): node is DecisionNode;
|
|
339
|
+
/**
|
|
340
|
+
* Check if a node has children.
|
|
341
|
+
*/
|
|
342
|
+
declare function hasChildren(node: FlowNode): node is SequenceNode | ParallelNode | RaceNode | DecisionNode;
|
|
343
|
+
/**
|
|
344
|
+
* Snapshot of an active step's state at a point in time.
|
|
345
|
+
*/
|
|
346
|
+
interface ActiveStepSnapshot {
|
|
347
|
+
id: string;
|
|
348
|
+
name?: string;
|
|
349
|
+
key?: string;
|
|
350
|
+
startTs: number;
|
|
351
|
+
retryCount: number;
|
|
352
|
+
timedOut: boolean;
|
|
353
|
+
timeoutMs?: number;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* A snapshot of the complete IR state at a specific point in time.
|
|
357
|
+
* Used for time-travel debugging - each event creates a snapshot.
|
|
358
|
+
*/
|
|
359
|
+
interface IRSnapshot {
|
|
360
|
+
/** Unique identifier for this snapshot */
|
|
361
|
+
id: string;
|
|
362
|
+
/** Index in the event sequence (0-based) */
|
|
363
|
+
eventIndex: number;
|
|
364
|
+
/** The event that triggered this snapshot */
|
|
365
|
+
event: unknown;
|
|
366
|
+
/** Complete IR state at this moment */
|
|
367
|
+
ir: WorkflowIR;
|
|
368
|
+
/** Timestamp when snapshot was taken */
|
|
369
|
+
timestamp: number;
|
|
370
|
+
/** Active step states at this moment (for debugging) */
|
|
371
|
+
activeSteps: Map<string, ActiveStepSnapshot>;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* State of the time-travel controller.
|
|
375
|
+
*/
|
|
376
|
+
interface TimeTravelState {
|
|
377
|
+
/** All recorded snapshots */
|
|
378
|
+
snapshots: IRSnapshot[];
|
|
379
|
+
/** Current snapshot index (for playback position) */
|
|
380
|
+
currentIndex: number;
|
|
381
|
+
/** Whether playback is active */
|
|
382
|
+
isPlaying: boolean;
|
|
383
|
+
/** Playback speed multiplier (1.0 = realtime, 2.0 = 2x speed) */
|
|
384
|
+
playbackSpeed: number;
|
|
385
|
+
/** Whether recording is active */
|
|
386
|
+
isRecording: boolean;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Performance metrics for a single node across multiple runs.
|
|
390
|
+
*/
|
|
391
|
+
interface NodePerformance {
|
|
392
|
+
/** Node identifier (name or step ID) */
|
|
393
|
+
nodeId: string;
|
|
394
|
+
/** Average duration across all samples */
|
|
395
|
+
avgDurationMs: number;
|
|
396
|
+
/** Minimum duration observed */
|
|
397
|
+
minDurationMs: number;
|
|
398
|
+
/** Maximum duration observed */
|
|
399
|
+
maxDurationMs: number;
|
|
400
|
+
/** Standard deviation of durations */
|
|
401
|
+
stdDevMs: number;
|
|
402
|
+
/** Number of timing samples collected */
|
|
403
|
+
samples: number;
|
|
404
|
+
/** Retry frequency (0-1, where 1 = always retries) */
|
|
405
|
+
retryRate: number;
|
|
406
|
+
/** Timeout frequency (0-1) */
|
|
407
|
+
timeoutRate: number;
|
|
408
|
+
/** Error rate (0-1) */
|
|
409
|
+
errorRate: number;
|
|
410
|
+
/** Percentile data for distribution analysis */
|
|
411
|
+
percentiles: {
|
|
412
|
+
p50: number;
|
|
413
|
+
p90: number;
|
|
414
|
+
p95: number;
|
|
415
|
+
p99: number;
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Heatmap data for visualizing performance across nodes.
|
|
420
|
+
*/
|
|
421
|
+
interface HeatmapData {
|
|
422
|
+
/** Map of node ID to heat level (0-1, where 1 is hottest/slowest) */
|
|
423
|
+
heat: Map<string, number>;
|
|
424
|
+
/** The metric used for heat calculation */
|
|
425
|
+
metric: "duration" | "retryRate" | "errorRate";
|
|
426
|
+
/** Statistics used to compute heat values */
|
|
427
|
+
stats: {
|
|
428
|
+
/** Minimum value in the dataset */
|
|
429
|
+
min: number;
|
|
430
|
+
/** Maximum value in the dataset */
|
|
431
|
+
max: number;
|
|
432
|
+
/** Mean value */
|
|
433
|
+
mean: number;
|
|
434
|
+
/** Threshold above which a node is considered "hot" */
|
|
435
|
+
threshold: number;
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Heat level for visual styling.
|
|
440
|
+
*/
|
|
441
|
+
type HeatLevel = "cold" | "cool" | "neutral" | "warm" | "hot" | "critical";
|
|
442
|
+
/**
|
|
443
|
+
* Theme for the HTML visualizer.
|
|
444
|
+
*/
|
|
445
|
+
type HTMLTheme = "light" | "dark" | "auto";
|
|
446
|
+
/**
|
|
447
|
+
* Layout direction for the workflow diagram.
|
|
448
|
+
*/
|
|
449
|
+
type LayoutDirection = "TB" | "LR" | "BT" | "RL";
|
|
450
|
+
/**
|
|
451
|
+
* Options for the HTML renderer.
|
|
452
|
+
*/
|
|
453
|
+
interface HTMLRenderOptions extends RenderOptions {
|
|
454
|
+
/** Enable interactive features (click to inspect, zoom/pan) */
|
|
455
|
+
interactive: boolean;
|
|
456
|
+
/** Include time-travel controls */
|
|
457
|
+
timeTravel: boolean;
|
|
458
|
+
/** Include performance heatmap overlay */
|
|
459
|
+
heatmap: boolean;
|
|
460
|
+
/** Animation duration for transitions (ms) */
|
|
461
|
+
animationDuration: number;
|
|
462
|
+
/** Color theme */
|
|
463
|
+
theme: HTMLTheme;
|
|
464
|
+
/** Diagram layout direction */
|
|
465
|
+
layout: LayoutDirection;
|
|
466
|
+
/** Heatmap data (if heatmap is enabled) */
|
|
467
|
+
heatmapData?: HeatmapData;
|
|
468
|
+
/** WebSocket URL for live updates (if streaming) */
|
|
469
|
+
wsUrl?: string;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Message sent from the web visualizer to the dev server.
|
|
473
|
+
*/
|
|
474
|
+
interface WebVisualizerMessage {
|
|
475
|
+
type: "time_travel_seek" | "time_travel_play" | "time_travel_pause" | "time_travel_step_forward" | "time_travel_step_backward" | "request_snapshots" | "toggle_heatmap" | "set_heatmap_metric";
|
|
476
|
+
payload?: unknown;
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Message sent from the dev server to the web visualizer.
|
|
480
|
+
*/
|
|
481
|
+
interface ServerMessage {
|
|
482
|
+
type: "ir_update" | "snapshot" | "snapshots_list" | "performance_data" | "workflow_complete" | "time_travel_state";
|
|
483
|
+
payload: unknown;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Extended render options for the enhanced ASCII renderer.
|
|
487
|
+
*/
|
|
488
|
+
interface EnhancedRenderOptions extends RenderOptions {
|
|
489
|
+
/** Show performance heatmap coloring */
|
|
490
|
+
showHeatmap?: boolean;
|
|
491
|
+
/** Heatmap data for coloring nodes */
|
|
492
|
+
heatmapData?: HeatmapData;
|
|
493
|
+
/** Show timing sparklines (requires historical data) */
|
|
494
|
+
showSparklines?: boolean;
|
|
495
|
+
/** Historical timing data for sparklines: nodeId → array of durations */
|
|
496
|
+
timingHistory?: Map<string, number[]>;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Options for the flowchart ASCII renderer.
|
|
500
|
+
* Renders workflow as a proper flowchart with boxes and arrows.
|
|
501
|
+
*/
|
|
502
|
+
interface FlowchartRenderOptions extends EnhancedRenderOptions {
|
|
503
|
+
/** Show start and end nodes (default: true) */
|
|
504
|
+
showStartEnd?: boolean;
|
|
505
|
+
/** Reduce vertical spacing between nodes (default: false) */
|
|
506
|
+
compact?: boolean;
|
|
507
|
+
/** Box border style (default: 'single') */
|
|
508
|
+
boxStyle?: "single" | "double" | "rounded";
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* State of a hook execution.
|
|
512
|
+
*/
|
|
513
|
+
type HookState = "pending" | "running" | "success" | "error";
|
|
514
|
+
/**
|
|
515
|
+
* Execution record for a workflow hook.
|
|
516
|
+
*/
|
|
517
|
+
interface HookExecution {
|
|
518
|
+
/** Hook type identifier */
|
|
519
|
+
type: "shouldRun" | "onBeforeStart" | "onAfterStep";
|
|
520
|
+
/** Execution state */
|
|
521
|
+
state: HookState;
|
|
522
|
+
/** Timestamp when hook started */
|
|
523
|
+
ts: number;
|
|
524
|
+
/** Duration in milliseconds */
|
|
525
|
+
durationMs?: number;
|
|
526
|
+
/** Error if hook failed */
|
|
527
|
+
error?: unknown;
|
|
528
|
+
/** Additional context (e.g., stepKey for onAfterStep) */
|
|
529
|
+
context?: {
|
|
530
|
+
/** Step key for onAfterStep hooks */
|
|
531
|
+
stepKey?: string;
|
|
532
|
+
/** Result of shouldRun hook */
|
|
533
|
+
result?: boolean;
|
|
534
|
+
/** Whether workflow was skipped due to shouldRun returning false */
|
|
535
|
+
skipped?: boolean;
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Hook execution summary for the workflow.
|
|
540
|
+
*/
|
|
541
|
+
interface WorkflowHooks {
|
|
542
|
+
/** shouldRun hook execution (if configured) */
|
|
543
|
+
shouldRun?: HookExecution;
|
|
544
|
+
/** onBeforeStart hook execution (if configured) */
|
|
545
|
+
onBeforeStart?: HookExecution;
|
|
546
|
+
/** onAfterStep hook executions (keyed by stepKey) */
|
|
547
|
+
onAfterStep: Map<string, HookExecution>;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Parallel Detection - Heuristic detection of parallel execution from timing.
|
|
552
|
+
*
|
|
553
|
+
* When steps overlap in time (one starts before another ends), they are
|
|
554
|
+
* likely running in parallel. This module detects such patterns and
|
|
555
|
+
* groups overlapping steps into ParallelNode structures.
|
|
556
|
+
*/
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Options for parallel detection.
|
|
560
|
+
*/
|
|
561
|
+
interface ParallelDetectorOptions {
|
|
562
|
+
/**
|
|
563
|
+
* Minimum overlap in milliseconds to consider steps parallel.
|
|
564
|
+
* Default: 0 (any overlap counts)
|
|
565
|
+
*/
|
|
566
|
+
minOverlapMs?: number;
|
|
567
|
+
/**
|
|
568
|
+
* Maximum gap in milliseconds to still consider steps as part of same parallel group.
|
|
569
|
+
* Default: 5 (steps starting within 5ms are grouped)
|
|
570
|
+
*/
|
|
571
|
+
maxGapMs?: number;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Group overlapping steps into parallel nodes.
|
|
575
|
+
*
|
|
576
|
+
* Algorithm:
|
|
577
|
+
* 1. Sort steps by start time
|
|
578
|
+
* 2. For each step, check if it overlaps with existing parallel groups
|
|
579
|
+
* 3. If it overlaps, add to group; otherwise start new sequence
|
|
580
|
+
* 4. Merge overlapping groups when step bridges them
|
|
581
|
+
*
|
|
582
|
+
* Note: If real scope nodes (from scope_start/scope_end) are present,
|
|
583
|
+
* heuristic detection is skipped to avoid conflicts.
|
|
584
|
+
*/
|
|
585
|
+
declare function detectParallelGroups(nodes: FlowNode[], options?: ParallelDetectorOptions): FlowNode[];
|
|
586
|
+
/**
|
|
587
|
+
* Create a parallel detector that processes nodes.
|
|
588
|
+
*/
|
|
589
|
+
declare function createParallelDetector(options?: ParallelDetectorOptions): {
|
|
590
|
+
/**
|
|
591
|
+
* Process nodes and group overlapping ones into parallel nodes.
|
|
592
|
+
*/
|
|
593
|
+
detect: (nodes: FlowNode[]) => FlowNode[];
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* IR Builder - Converts workflow events to Intermediate Representation.
|
|
598
|
+
*
|
|
599
|
+
* The builder maintains state as events arrive, constructing a tree
|
|
600
|
+
* representation of the workflow execution that can be rendered.
|
|
601
|
+
*/
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Options for the IR builder.
|
|
605
|
+
*/
|
|
606
|
+
interface IRBuilderOptions {
|
|
607
|
+
/**
|
|
608
|
+
* Enable heuristic parallel detection based on timing.
|
|
609
|
+
* When true, overlapping steps are grouped into ParallelNodes.
|
|
610
|
+
* Default: true
|
|
611
|
+
*/
|
|
612
|
+
detectParallel?: boolean;
|
|
613
|
+
/**
|
|
614
|
+
* Options for parallel detection.
|
|
615
|
+
*/
|
|
616
|
+
parallelDetection?: ParallelDetectorOptions;
|
|
617
|
+
/**
|
|
618
|
+
* Enable snapshot recording for time-travel debugging.
|
|
619
|
+
* When true, the builder captures IR state after each event.
|
|
620
|
+
* Default: false
|
|
621
|
+
*/
|
|
622
|
+
enableSnapshots?: boolean;
|
|
623
|
+
/**
|
|
624
|
+
* Maximum number of snapshots to keep (ring buffer behavior).
|
|
625
|
+
* When exceeded, oldest snapshots are discarded.
|
|
626
|
+
* Default: 1000
|
|
627
|
+
*/
|
|
628
|
+
maxSnapshots?: number;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Creates an IR builder that processes workflow events.
|
|
632
|
+
*/
|
|
633
|
+
declare function createIRBuilder(options?: IRBuilderOptions): {
|
|
634
|
+
handleEvent: (event: WorkflowEvent<unknown>) => void;
|
|
635
|
+
handleScopeEvent: (event: ScopeStartEvent | ScopeEndEvent) => void;
|
|
636
|
+
handleDecisionEvent: (event: DecisionStartEvent | DecisionBranchEvent | DecisionEndEvent) => void;
|
|
637
|
+
getIR: () => WorkflowIR;
|
|
638
|
+
reset: () => void;
|
|
639
|
+
getSnapshots: () => IRSnapshot[];
|
|
640
|
+
getSnapshotAt: (index: number) => IRSnapshot | undefined;
|
|
641
|
+
getIRAt: (index: number) => WorkflowIR | undefined;
|
|
642
|
+
clearSnapshots: () => void;
|
|
643
|
+
/** Check if there are active (running) steps */
|
|
644
|
+
readonly hasActiveSteps: boolean;
|
|
645
|
+
/** Get the current workflow state */
|
|
646
|
+
readonly state: StepState;
|
|
647
|
+
/** Get the number of recorded snapshots */
|
|
648
|
+
readonly snapshotCount: number;
|
|
649
|
+
/** Check if snapshot recording is enabled */
|
|
650
|
+
readonly snapshotsEnabled: boolean;
|
|
651
|
+
};
|
|
652
|
+
/**
|
|
653
|
+
* Type for the IR builder instance.
|
|
654
|
+
*/
|
|
655
|
+
type IRBuilder = ReturnType<typeof createIRBuilder>;
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* ANSI color utilities for terminal output.
|
|
659
|
+
*/
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Default ANSI color scheme for step states.
|
|
663
|
+
*/
|
|
664
|
+
declare const defaultColorScheme: ColorScheme;
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* ASCII Terminal Renderer
|
|
668
|
+
*
|
|
669
|
+
* Renders the workflow IR as ASCII art with box-drawing characters
|
|
670
|
+
* and ANSI colors for terminal display.
|
|
671
|
+
*/
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Create the ASCII terminal renderer.
|
|
675
|
+
*/
|
|
676
|
+
declare function asciiRenderer(): Renderer;
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Mermaid Diagram Renderer
|
|
680
|
+
*
|
|
681
|
+
* Renders the workflow IR as a Mermaid flowchart diagram.
|
|
682
|
+
* Supports sequential flows, parallel (subgraph), and race patterns.
|
|
683
|
+
*/
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* Create the Mermaid diagram renderer.
|
|
687
|
+
*/
|
|
688
|
+
declare function mermaidRenderer(): Renderer;
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Logger Renderer - Outputs structured JSON optimized for logging systems.
|
|
692
|
+
*
|
|
693
|
+
* Works with any structured logger (Pino, Winston, Bunyan, console).
|
|
694
|
+
* Includes workflow summary, step details, and optional ASCII diagram.
|
|
695
|
+
*
|
|
696
|
+
* @example
|
|
697
|
+
* ```typescript
|
|
698
|
+
* const logData = JSON.parse(viz.renderAs('logger'));
|
|
699
|
+
* logger.info(logData, 'Workflow completed');
|
|
700
|
+
* ```
|
|
701
|
+
*/
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Step log entry with execution details.
|
|
705
|
+
*/
|
|
706
|
+
interface StepLog {
|
|
707
|
+
id: string;
|
|
708
|
+
name: string;
|
|
709
|
+
key?: string;
|
|
710
|
+
state: string;
|
|
711
|
+
durationMs?: number;
|
|
712
|
+
startTs?: number;
|
|
713
|
+
endTs?: number;
|
|
714
|
+
retryCount?: number;
|
|
715
|
+
timedOut?: boolean;
|
|
716
|
+
timeoutMs?: number;
|
|
717
|
+
error?: string;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Hook execution log entry.
|
|
721
|
+
*/
|
|
722
|
+
interface HookLog {
|
|
723
|
+
shouldRun?: {
|
|
724
|
+
result?: boolean;
|
|
725
|
+
durationMs?: number;
|
|
726
|
+
error?: string;
|
|
727
|
+
};
|
|
728
|
+
onBeforeStart?: {
|
|
729
|
+
durationMs?: number;
|
|
730
|
+
error?: string;
|
|
731
|
+
};
|
|
732
|
+
onAfterStep?: Array<{
|
|
733
|
+
stepKey: string;
|
|
734
|
+
durationMs?: number;
|
|
735
|
+
error?: string;
|
|
736
|
+
}>;
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Summary statistics for the workflow.
|
|
740
|
+
*/
|
|
741
|
+
interface WorkflowSummary {
|
|
742
|
+
totalSteps: number;
|
|
743
|
+
successCount: number;
|
|
744
|
+
errorCount: number;
|
|
745
|
+
cacheHits: number;
|
|
746
|
+
skippedCount: number;
|
|
747
|
+
totalRetries: number;
|
|
748
|
+
slowestStep?: {
|
|
749
|
+
name: string;
|
|
750
|
+
durationMs: number;
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Complete logger output structure.
|
|
755
|
+
*/
|
|
756
|
+
interface LoggerOutput {
|
|
757
|
+
workflow: {
|
|
758
|
+
id: string;
|
|
759
|
+
name?: string;
|
|
760
|
+
state: string;
|
|
761
|
+
durationMs?: number;
|
|
762
|
+
startedAt?: number;
|
|
763
|
+
completedAt?: number;
|
|
764
|
+
};
|
|
765
|
+
steps: StepLog[];
|
|
766
|
+
summary: WorkflowSummary;
|
|
767
|
+
hooks?: HookLog;
|
|
768
|
+
diagram?: string;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Extended render options for logger renderer.
|
|
772
|
+
*/
|
|
773
|
+
interface LoggerRenderOptions extends RenderOptions {
|
|
774
|
+
/** Include ASCII diagram in output (default: true) */
|
|
775
|
+
includeDiagram?: boolean;
|
|
776
|
+
/** Strip ANSI color codes from diagram (default: true) */
|
|
777
|
+
stripAnsiColors?: boolean;
|
|
778
|
+
/** Diagram format: 'ascii' (tree-style) or 'flowchart' (boxes/arrows) (default: 'ascii') */
|
|
779
|
+
diagramFormat?: "ascii" | "flowchart";
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Create a logger renderer that outputs structured JSON.
|
|
783
|
+
*
|
|
784
|
+
* @example
|
|
785
|
+
* ```typescript
|
|
786
|
+
* const viz = createVisualizer({ workflowName: 'checkout' });
|
|
787
|
+
* // ... run workflow ...
|
|
788
|
+
*
|
|
789
|
+
* const logData = JSON.parse(viz.renderAs('logger'));
|
|
790
|
+
* logger.info(logData, 'Workflow completed');
|
|
791
|
+
* ```
|
|
792
|
+
*/
|
|
793
|
+
declare function loggerRenderer(): Renderer;
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Flowchart ASCII Renderer
|
|
797
|
+
*
|
|
798
|
+
* Renders workflow IR as a proper flowchart with boxes and arrows.
|
|
799
|
+
* Uses a 2D canvas approach for spatial layout with proper fork/join patterns.
|
|
800
|
+
*/
|
|
801
|
+
|
|
802
|
+
declare function flowchartRenderer(): Renderer;
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* HTML Renderer
|
|
806
|
+
*
|
|
807
|
+
* Renders the workflow IR as an interactive HTML page with:
|
|
808
|
+
* - SVG-based workflow diagram
|
|
809
|
+
* - Zoom and pan
|
|
810
|
+
* - Node inspection
|
|
811
|
+
* - Time-travel controls
|
|
812
|
+
* - Performance heatmap overlay
|
|
813
|
+
*/
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Create the HTML renderer.
|
|
817
|
+
*/
|
|
818
|
+
declare function htmlRenderer(): Renderer;
|
|
819
|
+
/**
|
|
820
|
+
* Render workflow IR to HTML with custom options.
|
|
821
|
+
*/
|
|
822
|
+
declare function renderToHTML(ir: WorkflowIR, options?: Partial<HTMLRenderOptions>): string;
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Live Visualizer - Real-time terminal updates during workflow execution.
|
|
826
|
+
*
|
|
827
|
+
* Uses ANSI escape codes to update the terminal in-place, showing
|
|
828
|
+
* workflow progress as it happens.
|
|
829
|
+
*/
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Live visualizer with real-time terminal updates.
|
|
833
|
+
*/
|
|
834
|
+
interface LiveVisualizer {
|
|
835
|
+
/** Process a workflow event */
|
|
836
|
+
handleEvent: (event: WorkflowEvent<unknown>) => void;
|
|
837
|
+
/** Process a scope event */
|
|
838
|
+
handleScopeEvent: (event: ScopeStartEvent | ScopeEndEvent) => void;
|
|
839
|
+
/** Process a decision event */
|
|
840
|
+
handleDecisionEvent: (event: DecisionStartEvent | DecisionBranchEvent | DecisionEndEvent) => void;
|
|
841
|
+
/** Get current IR state */
|
|
842
|
+
getIR: () => WorkflowIR;
|
|
843
|
+
/** Render current state to string (without terminal output) */
|
|
844
|
+
render: () => string;
|
|
845
|
+
/** Start live rendering to terminal */
|
|
846
|
+
start: () => void;
|
|
847
|
+
/** Stop live rendering */
|
|
848
|
+
stop: () => void;
|
|
849
|
+
/** Force an immediate redraw */
|
|
850
|
+
refresh: () => void;
|
|
851
|
+
/** Reset state for a new workflow */
|
|
852
|
+
reset: () => void;
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Create a live visualizer for real-time terminal updates.
|
|
856
|
+
*
|
|
857
|
+
* @example
|
|
858
|
+
* ```typescript
|
|
859
|
+
* const live = createLiveVisualizer({ workflowName: 'my-workflow' });
|
|
860
|
+
* const workflow = createWorkflow(deps, { onEvent: live.handleEvent });
|
|
861
|
+
*
|
|
862
|
+
* live.start();
|
|
863
|
+
* await workflow(async (step) => { ... });
|
|
864
|
+
* live.stop();
|
|
865
|
+
* ```
|
|
866
|
+
*/
|
|
867
|
+
declare function createLiveVisualizer(options?: LiveVisualizerOptions): LiveVisualizer;
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Decision Tracker - Helper for tracking conditional logic in workflows.
|
|
871
|
+
*
|
|
872
|
+
* This module provides utilities to track decision points (if/switch statements)
|
|
873
|
+
* so they can be visualized in workflow diagrams.
|
|
874
|
+
*
|
|
875
|
+
* @example
|
|
876
|
+
* ```typescript
|
|
877
|
+
* import { trackDecision } from 'awaitly/visualize';
|
|
878
|
+
*
|
|
879
|
+
* const workflow = createWorkflow(deps, {
|
|
880
|
+
* onEvent: (event) => {
|
|
881
|
+
* // Pass events to visualizer
|
|
882
|
+
* viz.handleEvent(event);
|
|
883
|
+
* }
|
|
884
|
+
* });
|
|
885
|
+
*
|
|
886
|
+
* await workflow(async (step) => {
|
|
887
|
+
* const user = await step(fetchUser(id));
|
|
888
|
+
*
|
|
889
|
+
* // Track a decision point
|
|
890
|
+
* const decision = trackDecision('user-role-check', {
|
|
891
|
+
* condition: 'user.role === "admin"',
|
|
892
|
+
* value: user.role
|
|
893
|
+
* });
|
|
894
|
+
*
|
|
895
|
+
* if (user.role === 'admin') {
|
|
896
|
+
* decision.takeBranch('admin', true);
|
|
897
|
+
* await step(processAdminAction(user));
|
|
898
|
+
* } else {
|
|
899
|
+
* decision.takeBranch('user', false);
|
|
900
|
+
* await step(processUserAction(user));
|
|
901
|
+
* }
|
|
902
|
+
*
|
|
903
|
+
* decision.end();
|
|
904
|
+
* });
|
|
905
|
+
* ```
|
|
906
|
+
*/
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* Options for creating a decision tracker.
|
|
910
|
+
*/
|
|
911
|
+
interface DecisionTrackerOptions {
|
|
912
|
+
/** Condition being evaluated (e.g., "user.role === 'admin'") */
|
|
913
|
+
condition?: string;
|
|
914
|
+
/** Value being evaluated */
|
|
915
|
+
value?: unknown;
|
|
916
|
+
/** Name/label for this decision point */
|
|
917
|
+
name?: string;
|
|
918
|
+
/** Workflow ID (auto-generated if not provided) */
|
|
919
|
+
workflowId?: string;
|
|
920
|
+
/** Event emitter function */
|
|
921
|
+
emit?: (event: DecisionStartEvent | DecisionBranchEvent | DecisionEndEvent) => void;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Track a decision point in your workflow.
|
|
925
|
+
*
|
|
926
|
+
* Use this to annotate conditional logic (if/switch) so it appears
|
|
927
|
+
* in workflow visualizations.
|
|
928
|
+
*
|
|
929
|
+
* @param decisionId - Unique identifier for this decision
|
|
930
|
+
* @param options - Decision tracking options
|
|
931
|
+
* @returns A tracker object with methods to track branches
|
|
932
|
+
*
|
|
933
|
+
* @example
|
|
934
|
+
* ```typescript
|
|
935
|
+
* const decision = trackDecision('check-role', {
|
|
936
|
+
* condition: 'user.role === "admin"',
|
|
937
|
+
* value: user.role,
|
|
938
|
+
* emit: (event) => viz.handleDecisionEvent(event)
|
|
939
|
+
* });
|
|
940
|
+
*
|
|
941
|
+
* if (user.role === 'admin') {
|
|
942
|
+
* decision.takeBranch('admin', true);
|
|
943
|
+
* // ... admin logic
|
|
944
|
+
* } else {
|
|
945
|
+
* decision.takeBranch('user', false);
|
|
946
|
+
* // ... user logic
|
|
947
|
+
* }
|
|
948
|
+
*
|
|
949
|
+
* decision.end();
|
|
950
|
+
* ```
|
|
951
|
+
*/
|
|
952
|
+
declare function trackDecision(decisionId: string, options?: DecisionTrackerOptions): DecisionTracker;
|
|
953
|
+
/**
|
|
954
|
+
* Decision tracker instance.
|
|
955
|
+
*/
|
|
956
|
+
interface DecisionTracker {
|
|
957
|
+
/**
|
|
958
|
+
* Mark that a branch was taken or skipped.
|
|
959
|
+
* @param label - Label for this branch (e.g., "if", "else", "case 'admin'")
|
|
960
|
+
* @param taken - Whether this branch was executed
|
|
961
|
+
* @param branchCondition - Optional condition for this specific branch
|
|
962
|
+
*/
|
|
963
|
+
takeBranch(label: string, taken: boolean, branchCondition?: string): void;
|
|
964
|
+
/**
|
|
965
|
+
* End the decision tracking.
|
|
966
|
+
* Call this after all branches have been evaluated.
|
|
967
|
+
*/
|
|
968
|
+
end(): void;
|
|
969
|
+
/**
|
|
970
|
+
* Get which branch was taken.
|
|
971
|
+
*/
|
|
972
|
+
getBranchTaken(): string | boolean | undefined;
|
|
973
|
+
/**
|
|
974
|
+
* Get all branches (taken and skipped).
|
|
975
|
+
*/
|
|
976
|
+
getBranches(): Array<{
|
|
977
|
+
label: string;
|
|
978
|
+
condition?: string;
|
|
979
|
+
taken: boolean;
|
|
980
|
+
}>;
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* Track a simple if/else decision.
|
|
984
|
+
*
|
|
985
|
+
* @example
|
|
986
|
+
* ```typescript
|
|
987
|
+
* const decision = trackIf('check-admin', user.role === 'admin', {
|
|
988
|
+
* condition: 'user.role === "admin"',
|
|
989
|
+
* value: user.role,
|
|
990
|
+
* emit: (e) => viz.handleDecisionEvent(e)
|
|
991
|
+
* });
|
|
992
|
+
*
|
|
993
|
+
* if (decision.condition) {
|
|
994
|
+
* decision.then();
|
|
995
|
+
* // admin logic
|
|
996
|
+
* } else {
|
|
997
|
+
* decision.else();
|
|
998
|
+
* // user logic
|
|
999
|
+
* }
|
|
1000
|
+
*
|
|
1001
|
+
* decision.end();
|
|
1002
|
+
* ```
|
|
1003
|
+
*/
|
|
1004
|
+
declare function trackIf(decisionId: string, condition: boolean, options?: Omit<DecisionTrackerOptions, "value"> & {
|
|
1005
|
+
value?: unknown;
|
|
1006
|
+
}): IfTracker;
|
|
1007
|
+
/**
|
|
1008
|
+
* If tracker with convenience methods.
|
|
1009
|
+
*/
|
|
1010
|
+
interface IfTracker extends DecisionTracker {
|
|
1011
|
+
/** The condition value */
|
|
1012
|
+
condition: boolean;
|
|
1013
|
+
/** Mark the "if" branch as taken */
|
|
1014
|
+
then(): void;
|
|
1015
|
+
/** Mark the "else" branch as taken */
|
|
1016
|
+
else(): void;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Track a switch statement decision.
|
|
1020
|
+
*
|
|
1021
|
+
* @example
|
|
1022
|
+
* ```typescript
|
|
1023
|
+
* const decision = trackSwitch('process-type', user.type, {
|
|
1024
|
+
* emit: (e) => viz.handleDecisionEvent(e)
|
|
1025
|
+
* });
|
|
1026
|
+
*
|
|
1027
|
+
* switch (user.type) {
|
|
1028
|
+
* case 'admin':
|
|
1029
|
+
* decision.case('admin', true);
|
|
1030
|
+
* // admin logic
|
|
1031
|
+
* break;
|
|
1032
|
+
* case 'user':
|
|
1033
|
+
* decision.case('user', true);
|
|
1034
|
+
* // user logic
|
|
1035
|
+
* break;
|
|
1036
|
+
* default:
|
|
1037
|
+
* decision.default(true);
|
|
1038
|
+
* // default logic
|
|
1039
|
+
* }
|
|
1040
|
+
*
|
|
1041
|
+
* decision.end();
|
|
1042
|
+
* ```
|
|
1043
|
+
*/
|
|
1044
|
+
declare function trackSwitch(decisionId: string, value: unknown, options?: Omit<DecisionTrackerOptions, "value">): SwitchTracker;
|
|
1045
|
+
/**
|
|
1046
|
+
* Switch tracker with convenience methods.
|
|
1047
|
+
*/
|
|
1048
|
+
interface SwitchTracker extends DecisionTracker {
|
|
1049
|
+
/** The value being switched on */
|
|
1050
|
+
value: unknown;
|
|
1051
|
+
/** Mark a case branch */
|
|
1052
|
+
case(caseValue: string | number, taken: boolean): void;
|
|
1053
|
+
/** Mark the default branch */
|
|
1054
|
+
default(taken: boolean): void;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* Time Travel Debugger
|
|
1059
|
+
*
|
|
1060
|
+
* Records IR snapshots at each event, enabling:
|
|
1061
|
+
* - Step-by-step forward/backward navigation
|
|
1062
|
+
* - Seeking to any point in execution
|
|
1063
|
+
* - Playback at various speeds
|
|
1064
|
+
* - State inspection at any moment
|
|
1065
|
+
*/
|
|
1066
|
+
|
|
1067
|
+
/**
|
|
1068
|
+
* Options for the time-travel controller.
|
|
1069
|
+
*/
|
|
1070
|
+
interface TimeTravelOptions {
|
|
1071
|
+
/** Maximum snapshots to store (ring buffer) */
|
|
1072
|
+
maxSnapshots?: number;
|
|
1073
|
+
/** Automatically record snapshots on each event */
|
|
1074
|
+
autoRecord?: boolean;
|
|
1075
|
+
/** IR builder options (passed through) */
|
|
1076
|
+
builderOptions?: Omit<IRBuilderOptions, "enableSnapshots" | "maxSnapshots">;
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Time-travel controller interface.
|
|
1080
|
+
*/
|
|
1081
|
+
interface TimeTravelController {
|
|
1082
|
+
/** Handle a workflow event (records snapshot if recording) */
|
|
1083
|
+
handleEvent: (event: WorkflowEvent<unknown>) => void;
|
|
1084
|
+
/** Navigate to specific snapshot index */
|
|
1085
|
+
seek: (index: number) => WorkflowIR | undefined;
|
|
1086
|
+
/** Move one step forward */
|
|
1087
|
+
stepForward: () => WorkflowIR | undefined;
|
|
1088
|
+
/** Move one step backward */
|
|
1089
|
+
stepBackward: () => WorkflowIR | undefined;
|
|
1090
|
+
/** Start playback at given speed (1.0 = realtime) */
|
|
1091
|
+
play: (speed?: number) => void;
|
|
1092
|
+
/** Pause playback */
|
|
1093
|
+
pause: () => void;
|
|
1094
|
+
/** Get current IR state */
|
|
1095
|
+
getCurrentIR: () => WorkflowIR;
|
|
1096
|
+
/** Get IR at specific snapshot index */
|
|
1097
|
+
getIRAt: (index: number) => WorkflowIR | undefined;
|
|
1098
|
+
/** Get all snapshots */
|
|
1099
|
+
getSnapshots: () => IRSnapshot[];
|
|
1100
|
+
/** Get snapshot at specific index */
|
|
1101
|
+
getSnapshotAt: (index: number) => IRSnapshot | undefined;
|
|
1102
|
+
/** Get current time-travel state */
|
|
1103
|
+
getState: () => TimeTravelState;
|
|
1104
|
+
/** Subscribe to state changes */
|
|
1105
|
+
onStateChange: (callback: (state: TimeTravelState) => void) => () => void;
|
|
1106
|
+
/** Start/resume recording */
|
|
1107
|
+
startRecording: () => void;
|
|
1108
|
+
/** Stop recording */
|
|
1109
|
+
stopRecording: () => void;
|
|
1110
|
+
/** Reset to initial state */
|
|
1111
|
+
reset: () => void;
|
|
1112
|
+
/** Get the underlying IR builder */
|
|
1113
|
+
getBuilder: () => IRBuilder;
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Create a time-travel controller for workflow debugging.
|
|
1117
|
+
*
|
|
1118
|
+
* @example
|
|
1119
|
+
* ```typescript
|
|
1120
|
+
* const controller = createTimeTravelController();
|
|
1121
|
+
*
|
|
1122
|
+
* // Feed events from workflow execution
|
|
1123
|
+
* workflow.onEvent(event => controller.handleEvent(event));
|
|
1124
|
+
*
|
|
1125
|
+
* // After execution, explore the timeline
|
|
1126
|
+
* controller.seek(0); // Go to start
|
|
1127
|
+
* controller.stepForward(); // Step through
|
|
1128
|
+
* controller.play(2); // Playback at 2x speed
|
|
1129
|
+
* ```
|
|
1130
|
+
*/
|
|
1131
|
+
declare function createTimeTravelController(options?: TimeTravelOptions): TimeTravelController;
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* Performance Analyzer
|
|
1135
|
+
*
|
|
1136
|
+
* Analyzes workflow execution data to identify:
|
|
1137
|
+
* - Slow steps (bottlenecks)
|
|
1138
|
+
* - Retry patterns
|
|
1139
|
+
* - Error-prone steps
|
|
1140
|
+
* - Timing anomalies
|
|
1141
|
+
*
|
|
1142
|
+
* Aggregates metrics across multiple workflow runs to provide
|
|
1143
|
+
* statistical insights and heatmap visualization data.
|
|
1144
|
+
*/
|
|
1145
|
+
|
|
1146
|
+
/**
|
|
1147
|
+
* A recorded workflow run for analysis.
|
|
1148
|
+
*/
|
|
1149
|
+
interface WorkflowRun {
|
|
1150
|
+
/** Unique identifier for this run */
|
|
1151
|
+
id: string;
|
|
1152
|
+
/** Workflow start timestamp */
|
|
1153
|
+
startTime: number;
|
|
1154
|
+
/** All events from the workflow execution */
|
|
1155
|
+
events: WorkflowEvent<unknown>[];
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Performance analyzer interface.
|
|
1159
|
+
*/
|
|
1160
|
+
interface PerformanceAnalyzer {
|
|
1161
|
+
/** Add a completed workflow run for analysis */
|
|
1162
|
+
addRun: (run: WorkflowRun) => void;
|
|
1163
|
+
/** Add events incrementally (alternative to addRun) */
|
|
1164
|
+
addEvent: (event: WorkflowEvent<unknown>) => void;
|
|
1165
|
+
/** Finalize current run (when using addEvent) */
|
|
1166
|
+
finalizeRun: (runId: string) => void;
|
|
1167
|
+
/** Get performance stats for a specific node */
|
|
1168
|
+
getNodePerformance: (nodeId: string) => NodePerformance | undefined;
|
|
1169
|
+
/** Get heatmap data for an IR */
|
|
1170
|
+
getHeatmap: (ir: WorkflowIR, metric?: "duration" | "retryRate" | "errorRate") => HeatmapData;
|
|
1171
|
+
/** Get slowest nodes */
|
|
1172
|
+
getSlowestNodes: (limit?: number) => NodePerformance[];
|
|
1173
|
+
/** Get error-prone nodes */
|
|
1174
|
+
getErrorProneNodes: (limit?: number) => NodePerformance[];
|
|
1175
|
+
/** Get retry-prone nodes */
|
|
1176
|
+
getRetryProneNodes: (limit?: number) => NodePerformance[];
|
|
1177
|
+
/** Get all performance data */
|
|
1178
|
+
getAllPerformance: () => Map<string, NodePerformance>;
|
|
1179
|
+
/** Export performance data as JSON */
|
|
1180
|
+
exportData: () => string;
|
|
1181
|
+
/** Import performance data from JSON */
|
|
1182
|
+
importData: (json: string) => void;
|
|
1183
|
+
/** Clear all collected data */
|
|
1184
|
+
clear: () => void;
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Get heat level from normalized value (0-1).
|
|
1188
|
+
*/
|
|
1189
|
+
declare function getHeatLevel(heat: number): HeatLevel;
|
|
1190
|
+
/**
|
|
1191
|
+
* Create a performance analyzer for workflow metrics.
|
|
1192
|
+
*
|
|
1193
|
+
* @example
|
|
1194
|
+
* ```typescript
|
|
1195
|
+
* const analyzer = createPerformanceAnalyzer();
|
|
1196
|
+
*
|
|
1197
|
+
* // Add completed runs
|
|
1198
|
+
* analyzer.addRun({ id: 'run-1', startTime: Date.now(), events });
|
|
1199
|
+
*
|
|
1200
|
+
* // Get insights
|
|
1201
|
+
* const slowest = analyzer.getSlowestNodes(5);
|
|
1202
|
+
* const heatmap = analyzer.getHeatmap(ir, 'duration');
|
|
1203
|
+
* ```
|
|
1204
|
+
*/
|
|
1205
|
+
declare function createPerformanceAnalyzer(): PerformanceAnalyzer;
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* Development Server
|
|
1209
|
+
*
|
|
1210
|
+
* Provides a local HTTP server with WebSocket support for:
|
|
1211
|
+
* - Serving the HTML visualizer
|
|
1212
|
+
* - Live streaming workflow events
|
|
1213
|
+
* - Time-travel control from the browser
|
|
1214
|
+
* - Performance data broadcasting
|
|
1215
|
+
*
|
|
1216
|
+
* The `ws` package is an optional peer dependency.
|
|
1217
|
+
* Install it with: npm install ws
|
|
1218
|
+
*/
|
|
1219
|
+
|
|
1220
|
+
/**
|
|
1221
|
+
* Options for the dev server.
|
|
1222
|
+
*/
|
|
1223
|
+
interface DevServerOptions {
|
|
1224
|
+
/** Port to listen on (default: 3377) */
|
|
1225
|
+
port?: number;
|
|
1226
|
+
/** Hostname to bind to (default: localhost) */
|
|
1227
|
+
host?: string;
|
|
1228
|
+
/** Auto-open browser when starting (default: true) */
|
|
1229
|
+
autoOpen?: boolean;
|
|
1230
|
+
/** Workflow name for the visualizer title */
|
|
1231
|
+
workflowName?: string;
|
|
1232
|
+
/** Enable time-travel debugging (default: true) */
|
|
1233
|
+
timeTravel?: boolean;
|
|
1234
|
+
/** Enable performance heatmap (default: true) */
|
|
1235
|
+
heatmap?: boolean;
|
|
1236
|
+
/** Max snapshots for time-travel (default: 1000) */
|
|
1237
|
+
maxSnapshots?: number;
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Dev server interface.
|
|
1241
|
+
*/
|
|
1242
|
+
interface DevServer {
|
|
1243
|
+
/** Start the server */
|
|
1244
|
+
start(): Promise<{
|
|
1245
|
+
port: number;
|
|
1246
|
+
url: string;
|
|
1247
|
+
}>;
|
|
1248
|
+
/** Stop the server */
|
|
1249
|
+
stop(): Promise<void>;
|
|
1250
|
+
/** Handle a workflow event (forwards to time-travel and broadcasts) */
|
|
1251
|
+
handleEvent(event: WorkflowEvent<unknown>): void;
|
|
1252
|
+
/** Push an IR update to all clients */
|
|
1253
|
+
pushUpdate(ir: WorkflowIR): void;
|
|
1254
|
+
/** Push heatmap data to all clients */
|
|
1255
|
+
pushHeatmap(data: HeatmapData): void;
|
|
1256
|
+
/** Mark workflow as complete */
|
|
1257
|
+
complete(): void;
|
|
1258
|
+
/** Get the time-travel controller */
|
|
1259
|
+
getTimeTravel(): TimeTravelController;
|
|
1260
|
+
/** Get the performance analyzer */
|
|
1261
|
+
getAnalyzer(): PerformanceAnalyzer;
|
|
1262
|
+
/** Get current IR */
|
|
1263
|
+
getCurrentIR(): WorkflowIR;
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* Create a development server for the workflow visualizer.
|
|
1267
|
+
*
|
|
1268
|
+
* @example
|
|
1269
|
+
* ```typescript
|
|
1270
|
+
* const server = createDevServer({ port: 3377 });
|
|
1271
|
+
* await server.start();
|
|
1272
|
+
*
|
|
1273
|
+
* // Forward events from workflow execution
|
|
1274
|
+
* workflow.onEvent(event => server.handleEvent(event));
|
|
1275
|
+
*
|
|
1276
|
+
* // When done
|
|
1277
|
+
* server.complete();
|
|
1278
|
+
* await server.stop();
|
|
1279
|
+
* ```
|
|
1280
|
+
*/
|
|
1281
|
+
declare function createDevServer(options?: DevServerOptions): Promise<DevServer>;
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* Workflow Visualization Module
|
|
1285
|
+
*
|
|
1286
|
+
* Provides tools for visualizing workflow execution with color-coded
|
|
1287
|
+
* step states and support for parallel/race operations.
|
|
1288
|
+
*
|
|
1289
|
+
* @example
|
|
1290
|
+
* ```typescript
|
|
1291
|
+
* import { createVisualizer } from 'awaitly/visualize';
|
|
1292
|
+
*
|
|
1293
|
+
* const viz = createVisualizer({ workflowName: 'checkout' });
|
|
1294
|
+
* const workflow = createWorkflow(deps, { onEvent: viz.handleEvent });
|
|
1295
|
+
*
|
|
1296
|
+
* await workflow(async (step) => {
|
|
1297
|
+
* await step(() => validateCart(cart), 'Validate cart');
|
|
1298
|
+
* await step(() => processPayment(payment), 'Process payment');
|
|
1299
|
+
* });
|
|
1300
|
+
*
|
|
1301
|
+
* console.log(viz.render());
|
|
1302
|
+
* ```
|
|
1303
|
+
*/
|
|
1304
|
+
|
|
1305
|
+
/**
|
|
1306
|
+
* Workflow visualizer that processes events and renders output.
|
|
1307
|
+
*/
|
|
1308
|
+
interface WorkflowVisualizer {
|
|
1309
|
+
/** Process a workflow event */
|
|
1310
|
+
handleEvent: (event: WorkflowEvent<unknown>) => void;
|
|
1311
|
+
/** Process a scope event (parallel/race) */
|
|
1312
|
+
handleScopeEvent: (event: ScopeStartEvent | ScopeEndEvent) => void;
|
|
1313
|
+
/** Process a decision event (conditional branches) */
|
|
1314
|
+
handleDecisionEvent: (event: DecisionStartEvent | DecisionBranchEvent | DecisionEndEvent) => void;
|
|
1315
|
+
/** Get current IR state */
|
|
1316
|
+
getIR: () => WorkflowIR;
|
|
1317
|
+
/** Render current state using the default renderer */
|
|
1318
|
+
render: () => string;
|
|
1319
|
+
/** Render to a specific format */
|
|
1320
|
+
renderAs: (format: OutputFormat) => string;
|
|
1321
|
+
/** Reset state for a new workflow */
|
|
1322
|
+
reset: () => void;
|
|
1323
|
+
/** Subscribe to IR updates (for live visualization) */
|
|
1324
|
+
onUpdate: (callback: (ir: WorkflowIR) => void) => () => void;
|
|
1325
|
+
}
|
|
1326
|
+
/**
|
|
1327
|
+
* Create a workflow visualizer.
|
|
1328
|
+
*
|
|
1329
|
+
* @example
|
|
1330
|
+
* ```typescript
|
|
1331
|
+
* const viz = createVisualizer({ workflowName: 'my-workflow' });
|
|
1332
|
+
*
|
|
1333
|
+
* const workflow = createWorkflow(deps, {
|
|
1334
|
+
* onEvent: viz.handleEvent,
|
|
1335
|
+
* });
|
|
1336
|
+
*
|
|
1337
|
+
* await workflow(async (step) => { ... });
|
|
1338
|
+
*
|
|
1339
|
+
* console.log(viz.render());
|
|
1340
|
+
* ```
|
|
1341
|
+
*/
|
|
1342
|
+
declare function createVisualizer(options?: VisualizerOptions): WorkflowVisualizer;
|
|
1343
|
+
/**
|
|
1344
|
+
* Union type for all collectable/visualizable events (workflow + decision).
|
|
1345
|
+
*/
|
|
1346
|
+
type CollectableEvent = WorkflowEvent<unknown> | DecisionStartEvent | DecisionBranchEvent | DecisionEndEvent;
|
|
1347
|
+
/**
|
|
1348
|
+
* Visualize collected events (post-execution).
|
|
1349
|
+
*
|
|
1350
|
+
* Supports both workflow events (from onEvent) and decision events
|
|
1351
|
+
* (from trackDecision/trackIf/trackSwitch).
|
|
1352
|
+
*
|
|
1353
|
+
* @example
|
|
1354
|
+
* ```typescript
|
|
1355
|
+
* const events: CollectableEvent[] = [];
|
|
1356
|
+
* const workflow = createWorkflow(deps, {
|
|
1357
|
+
* onEvent: (e) => events.push(e),
|
|
1358
|
+
* });
|
|
1359
|
+
*
|
|
1360
|
+
* await workflow(async (step) => {
|
|
1361
|
+
* const decision = trackIf('check', condition, {
|
|
1362
|
+
* emit: (e) => events.push(e),
|
|
1363
|
+
* });
|
|
1364
|
+
* // ...
|
|
1365
|
+
* });
|
|
1366
|
+
*
|
|
1367
|
+
* console.log(visualizeEvents(events));
|
|
1368
|
+
* ```
|
|
1369
|
+
*/
|
|
1370
|
+
declare function visualizeEvents(events: CollectableEvent[], options?: VisualizerOptions): string;
|
|
1371
|
+
/**
|
|
1372
|
+
* Create an event collector for later visualization.
|
|
1373
|
+
*
|
|
1374
|
+
* Supports both workflow events (from onEvent) and decision events
|
|
1375
|
+
* (from trackDecision/trackIf/trackSwitch).
|
|
1376
|
+
*
|
|
1377
|
+
* @example
|
|
1378
|
+
* ```typescript
|
|
1379
|
+
* const collector = createEventCollector();
|
|
1380
|
+
*
|
|
1381
|
+
* const workflow = createWorkflow(deps, {
|
|
1382
|
+
* onEvent: collector.handleEvent,
|
|
1383
|
+
* });
|
|
1384
|
+
*
|
|
1385
|
+
* await workflow(async (step) => {
|
|
1386
|
+
* // Decision events can also be collected
|
|
1387
|
+
* const decision = trackIf('check', condition, {
|
|
1388
|
+
* emit: collector.handleDecisionEvent,
|
|
1389
|
+
* });
|
|
1390
|
+
* // ...
|
|
1391
|
+
* });
|
|
1392
|
+
*
|
|
1393
|
+
* console.log(collector.visualize());
|
|
1394
|
+
* ```
|
|
1395
|
+
*/
|
|
1396
|
+
declare function createEventCollector(options?: VisualizerOptions): {
|
|
1397
|
+
/** Handle a workflow event */
|
|
1398
|
+
handleEvent: (event: WorkflowEvent<unknown>) => void;
|
|
1399
|
+
/** Handle a decision event */
|
|
1400
|
+
handleDecisionEvent: (event: DecisionStartEvent | DecisionBranchEvent | DecisionEndEvent) => void;
|
|
1401
|
+
/** Get all collected events */
|
|
1402
|
+
getEvents: () => CollectableEvent[];
|
|
1403
|
+
/** Get workflow events only */
|
|
1404
|
+
getWorkflowEvents: () => WorkflowEvent<unknown>[];
|
|
1405
|
+
/** Get decision events only */
|
|
1406
|
+
getDecisionEvents: () => (DecisionStartEvent | DecisionBranchEvent | DecisionEndEvent)[];
|
|
1407
|
+
/** Clear collected events */
|
|
1408
|
+
clear: () => void;
|
|
1409
|
+
/** Visualize collected events */
|
|
1410
|
+
visualize: () => string;
|
|
1411
|
+
/** Visualize in a specific format */
|
|
1412
|
+
visualizeAs: (format: OutputFormat) => string;
|
|
1413
|
+
};
|
|
1414
|
+
|
|
1415
|
+
export { type ActiveStepSnapshot, type BaseNode, type CollectableEvent, type ColorScheme, type DecisionBranch, type DecisionBranchEvent, type DecisionEndEvent, type DecisionEvent, type DecisionNode, type DecisionStartEvent, type DecisionTracker, type DevServer, type DevServerOptions, type EnhancedRenderOptions, type FlowNode, type FlowchartRenderOptions, type HTMLRenderOptions, type HTMLTheme, type HeatLevel, type HeatmapData, type HookExecution, type HookLog, type HookState, type IRBuilderOptions, type IRSnapshot, type IfTracker, type LayoutDirection, type LiveVisualizer, type LiveVisualizerOptions, type LoggerOutput, type LoggerRenderOptions, type MermaidRenderOptions, type NodePerformance, type OutputFormat, type ParallelDetectorOptions, type ParallelNode, type PerformanceAnalyzer, type RaceNode, type RenderOptions, type Renderer, type ScopeEndEvent, type ScopeEvent, type ScopeStartEvent, ScopeType, type SequenceNode, type ServerMessage, type StepLog, type StepNode, type StepSkippedEvent, type StepState, type SwitchTracker, type TimeTravelController, type TimeTravelOptions, type TimeTravelState, type VisualizerOptions, type WebVisualizerMessage, type WorkflowHooks, type WorkflowIR, type WorkflowNode, type WorkflowRun, type WorkflowSummary, type WorkflowVisualizer, asciiRenderer, createDevServer, createEventCollector, createIRBuilder, createLiveVisualizer, createParallelDetector, createPerformanceAnalyzer, createTimeTravelController, createVisualizer, defaultColorScheme, detectParallelGroups, flowchartRenderer, getHeatLevel, hasChildren, htmlRenderer, isDecisionNode, isParallelNode, isRaceNode, isSequenceNode, isStepNode, loggerRenderer, mermaidRenderer, renderToHTML, trackDecision, trackIf, trackSwitch, visualizeEvents };
|