groundswell 0.0.1
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/.claude/settings.local.json +9 -0
- package/.claude/system_prompts/task-breakdown.md +100 -0
- package/PRPs/001-hierarchical-workflow-engine.md +2438 -0
- package/PRPs/PRDs/001-hierarchical-workflow-engine.md +543 -0
- package/PRPs/PRDs/002-agent-prompt.md +390 -0
- package/PRPs/PRDs/003-agent-prompt.md +943 -0
- package/PRPs/PRDs/004-agent-prompt.md +1136 -0
- package/PRPs/PRDs/tasks-001.json +492 -0
- package/PRPs/README.md +83 -0
- package/PRPs/templates/prp_base.md +222 -0
- package/README.md +218 -0
- package/docs/agent.md +422 -0
- package/docs/prompt.md +419 -0
- package/docs/workflow.md +600 -0
- package/examples/README.md +244 -0
- package/examples/examples/01-basic-workflow.ts +100 -0
- package/examples/examples/02-decorator-options.ts +217 -0
- package/examples/examples/03-parent-child.ts +241 -0
- package/examples/examples/04-observers-debugger.ts +340 -0
- package/examples/examples/05-error-handling.ts +387 -0
- package/examples/examples/06-concurrent-tasks.ts +352 -0
- package/examples/examples/07-agent-loops.ts +432 -0
- package/examples/examples/08-sdk-features.ts +667 -0
- package/examples/examples/09-reflection.ts +573 -0
- package/examples/examples/10-introspection.ts +550 -0
- package/examples/index.ts +143 -0
- package/examples/utils/helpers.ts +57 -0
- package/llms_full.txt +5890 -0
- package/package.json +63 -0
- package/plan/P1P2/PRP.md +527 -0
- package/plan/P1P2/research/LRU_CACHE_BEST_PRACTICES.md +1929 -0
- package/plan/P1P2/research/LRU_CACHE_CODE_PATTERNS.md +857 -0
- package/plan/P1P2/research/LRU_CACHE_INTEGRATION_GUIDE.md +738 -0
- package/plan/P1P2/research/LRU_CACHE_RESEARCH_INDEX.md +424 -0
- package/plan/P1P2/research/REFLECTION_INDEX.md +291 -0
- package/plan/P1P2/research/REFLECTION_RESEARCH_REPORT.md +1342 -0
- package/plan/P1P2/research/RESEARCH_SUMMARY.md +342 -0
- package/plan/P1P2/research/anthropic-sdk.md +174 -0
- package/plan/P1P2/research/async-local-storage.md +200 -0
- package/plan/P1P2/research/reflection-code-patterns.md +1205 -0
- package/plan/P1P2/research/reflection-decision-matrix.md +421 -0
- package/plan/P1P2/research/reflection-implementation-guide.md +1341 -0
- package/plan/P1P2/research/reflection-integration-guide.md +834 -0
- package/plan/P1P2/research/reflection-patterns.md +1468 -0
- package/plan/P1P2/research/reflection-quick-reference.md +558 -0
- package/plan/P1P2/research/zod-schema.md +152 -0
- package/plan/P3P4/PRP.md +1388 -0
- package/plan/P3P4/research/caching-lru.md +116 -0
- package/plan/P3P4/research/introspection-tools.md +177 -0
- package/plan/P3P4/research/reflection-patterns.md +117 -0
- package/plan/P4P5/PRP.md +1136 -0
- package/plan/P4P5/research/RESEARCH_SUMMARY.md +151 -0
- package/plan/architecture/external_deps.md +358 -0
- package/plan/architecture/system_context.md +242 -0
- package/plan/backlog.json +867 -0
- package/plan/research/INTROSPECTION_RESEARCH_SUMMARY.md +378 -0
- package/plan/research/README-INTROSPECTION.md +352 -0
- package/plan/research/agent-introspection-patterns.md +1085 -0
- package/plan/research/introspection-security-guide.md +928 -0
- package/plan/research/introspection-tool-examples.md +875 -0
- package/scripts/generate-llms-full.ts +206 -0
- package/src/__tests__/integration/agent-workflow.test.ts +256 -0
- package/src/__tests__/integration/tree-mirroring.test.ts +114 -0
- package/src/__tests__/unit/agent.test.ts +169 -0
- package/src/__tests__/unit/cache-key.test.ts +182 -0
- package/src/__tests__/unit/cache.test.ts +172 -0
- package/src/__tests__/unit/context.test.ts +138 -0
- package/src/__tests__/unit/decorators.test.ts +100 -0
- package/src/__tests__/unit/introspection-tools.test.ts +277 -0
- package/src/__tests__/unit/prompt.test.ts +135 -0
- package/src/__tests__/unit/reflection.test.ts +210 -0
- package/src/__tests__/unit/tree-debugger.test.ts +85 -0
- package/src/__tests__/unit/workflow.test.ts +81 -0
- package/src/cache/cache-key.ts +244 -0
- package/src/cache/cache.ts +236 -0
- package/src/cache/index.ts +8 -0
- package/src/core/agent.ts +573 -0
- package/src/core/context.ts +119 -0
- package/src/core/event-tree.ts +260 -0
- package/src/core/factory.ts +123 -0
- package/src/core/index.ts +17 -0
- package/src/core/logger.ts +87 -0
- package/src/core/mcp-handler.ts +184 -0
- package/src/core/prompt.ts +150 -0
- package/src/core/workflow-context.ts +349 -0
- package/src/core/workflow.ts +302 -0
- package/src/debugger/index.ts +1 -0
- package/src/debugger/tree-debugger.ts +210 -0
- package/src/decorators/index.ts +3 -0
- package/src/decorators/observed-state.ts +95 -0
- package/src/decorators/step.ts +139 -0
- package/src/decorators/task.ts +96 -0
- package/src/examples/index.ts +2 -0
- package/src/examples/tdd-orchestrator.ts +65 -0
- package/src/examples/test-cycle-workflow.ts +64 -0
- package/src/index.ts +140 -0
- package/src/reflection/index.ts +5 -0
- package/src/reflection/reflection.ts +407 -0
- package/src/tools/index.ts +36 -0
- package/src/tools/introspection.ts +464 -0
- package/src/types/agent.ts +90 -0
- package/src/types/decorators.ts +25 -0
- package/src/types/error-strategy.ts +13 -0
- package/src/types/error.ts +20 -0
- package/src/types/events.ts +74 -0
- package/src/types/index.ts +55 -0
- package/src/types/logging.ts +24 -0
- package/src/types/observer.ts +18 -0
- package/src/types/prompt.ts +40 -0
- package/src/types/reflection.ts +117 -0
- package/src/types/sdk-primitives.ts +128 -0
- package/src/types/snapshot.ts +14 -0
- package/src/types/workflow-context.ts +163 -0
- package/src/types/workflow.ts +37 -0
- package/src/utils/id.ts +11 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/observable.ts +77 -0
- package/tasks.json +0 -0
- package/tsconfig.json +22 -0
- package/vitest.config.ts +16 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example 5: Error Handling
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates:
|
|
5
|
+
* - How @Step decorator wraps errors in WorkflowError
|
|
6
|
+
* - Error context including state snapshots and logs
|
|
7
|
+
* - Error events emitted to observers
|
|
8
|
+
* - Error propagation in parent-child workflows
|
|
9
|
+
* - Recovery strategies in workflow orchestration
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
Workflow,
|
|
14
|
+
Step,
|
|
15
|
+
Task,
|
|
16
|
+
ObservedState,
|
|
17
|
+
getObservedState,
|
|
18
|
+
WorkflowTreeDebugger,
|
|
19
|
+
WorkflowObserver,
|
|
20
|
+
WorkflowEvent,
|
|
21
|
+
WorkflowError,
|
|
22
|
+
LogEntry,
|
|
23
|
+
WorkflowNode,
|
|
24
|
+
} from 'groundswell';
|
|
25
|
+
import { printHeader, printSection, sleep } from '../utils/helpers.js';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Workflow that demonstrates error wrapping
|
|
29
|
+
*/
|
|
30
|
+
class ErrorDemoWorkflow extends Workflow {
|
|
31
|
+
@ObservedState()
|
|
32
|
+
currentStep: string = 'init';
|
|
33
|
+
|
|
34
|
+
@ObservedState()
|
|
35
|
+
itemsProcessed: number = 0;
|
|
36
|
+
|
|
37
|
+
@ObservedState({ redact: true })
|
|
38
|
+
sensitiveContext: string = 'secret-data';
|
|
39
|
+
|
|
40
|
+
@Step({ snapshotState: true })
|
|
41
|
+
async step1(): Promise<void> {
|
|
42
|
+
this.currentStep = 'step1';
|
|
43
|
+
this.itemsProcessed = 5;
|
|
44
|
+
this.logger.info('Step 1 completed successfully');
|
|
45
|
+
await sleep(50);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Step({ snapshotState: true })
|
|
49
|
+
async step2(): Promise<void> {
|
|
50
|
+
this.currentStep = 'step2';
|
|
51
|
+
this.itemsProcessed = 10;
|
|
52
|
+
this.logger.info('Step 2 completed successfully');
|
|
53
|
+
await sleep(50);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@Step({ snapshotState: true })
|
|
57
|
+
async failingStep(): Promise<void> {
|
|
58
|
+
this.currentStep = 'failing';
|
|
59
|
+
this.logger.info('About to fail...');
|
|
60
|
+
await sleep(30);
|
|
61
|
+
|
|
62
|
+
// This error will be wrapped in WorkflowError
|
|
63
|
+
throw new Error('Something went wrong in failingStep!');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async run(): Promise<void> {
|
|
67
|
+
this.setStatus('running');
|
|
68
|
+
this.logger.info('Starting error demo workflow');
|
|
69
|
+
|
|
70
|
+
await this.step1();
|
|
71
|
+
await this.step2();
|
|
72
|
+
await this.failingStep(); // This will throw
|
|
73
|
+
|
|
74
|
+
// This line won't be reached
|
|
75
|
+
this.setStatus('completed');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Workflow with retry logic
|
|
81
|
+
*/
|
|
82
|
+
class RetryableWorkflow extends Workflow {
|
|
83
|
+
@ObservedState()
|
|
84
|
+
attempt: number = 0;
|
|
85
|
+
|
|
86
|
+
@ObservedState()
|
|
87
|
+
maxAttempts: number = 3;
|
|
88
|
+
|
|
89
|
+
@ObservedState()
|
|
90
|
+
success: boolean = false;
|
|
91
|
+
|
|
92
|
+
private failUntilAttempt: number;
|
|
93
|
+
|
|
94
|
+
constructor(name: string, failUntilAttempt: number = 2) {
|
|
95
|
+
super(name);
|
|
96
|
+
this.failUntilAttempt = failUntilAttempt;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@Step({ trackTiming: true, snapshotState: true })
|
|
100
|
+
async unreliableOperation(): Promise<void> {
|
|
101
|
+
this.attempt++;
|
|
102
|
+
this.logger.info(`Attempt ${this.attempt}/${this.maxAttempts}`);
|
|
103
|
+
await sleep(50);
|
|
104
|
+
|
|
105
|
+
if (this.attempt < this.failUntilAttempt) {
|
|
106
|
+
throw new Error(`Simulated failure on attempt ${this.attempt}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this.success = true;
|
|
110
|
+
this.logger.info('Operation succeeded!');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async run(): Promise<boolean> {
|
|
114
|
+
this.setStatus('running');
|
|
115
|
+
this.logger.info('Starting retryable workflow');
|
|
116
|
+
|
|
117
|
+
while (this.attempt < this.maxAttempts) {
|
|
118
|
+
try {
|
|
119
|
+
await this.unreliableOperation();
|
|
120
|
+
this.setStatus('completed');
|
|
121
|
+
return true;
|
|
122
|
+
} catch (error) {
|
|
123
|
+
const wfError = error as WorkflowError;
|
|
124
|
+
this.logger.warn(`Attempt failed: ${wfError.message}`);
|
|
125
|
+
|
|
126
|
+
if (this.attempt >= this.maxAttempts) {
|
|
127
|
+
this.setStatus('failed');
|
|
128
|
+
this.logger.error('All attempts exhausted');
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this.logger.info('Retrying...');
|
|
133
|
+
await sleep(100); // Backoff delay
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this.setStatus('failed');
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Child workflow that may fail
|
|
144
|
+
*/
|
|
145
|
+
class FailableChildWorkflow extends Workflow {
|
|
146
|
+
private shouldFail: boolean;
|
|
147
|
+
|
|
148
|
+
@ObservedState()
|
|
149
|
+
taskStatus: string = 'pending';
|
|
150
|
+
|
|
151
|
+
constructor(name: string, shouldFail: boolean, parent?: Workflow) {
|
|
152
|
+
super(name, parent);
|
|
153
|
+
this.shouldFail = shouldFail;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@Step({ snapshotState: true })
|
|
157
|
+
async execute(): Promise<void> {
|
|
158
|
+
this.taskStatus = 'executing';
|
|
159
|
+
this.logger.info('Executing child workflow');
|
|
160
|
+
await sleep(50);
|
|
161
|
+
|
|
162
|
+
if (this.shouldFail) {
|
|
163
|
+
throw new Error(`Child ${this.getNode().name} failed intentionally`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
this.taskStatus = 'success';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async run(): Promise<void> {
|
|
170
|
+
this.setStatus('running');
|
|
171
|
+
await this.execute();
|
|
172
|
+
this.setStatus('completed');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Parent workflow with error recovery
|
|
178
|
+
*/
|
|
179
|
+
class ResilientParentWorkflow extends Workflow {
|
|
180
|
+
@ObservedState()
|
|
181
|
+
totalChildren: number = 0;
|
|
182
|
+
|
|
183
|
+
@ObservedState()
|
|
184
|
+
successfulChildren: number = 0;
|
|
185
|
+
|
|
186
|
+
@ObservedState()
|
|
187
|
+
failedChildren: number = 0;
|
|
188
|
+
|
|
189
|
+
private childConfigs: { name: string; shouldFail: boolean }[];
|
|
190
|
+
|
|
191
|
+
constructor(name: string, childConfigs: { name: string; shouldFail: boolean }[]) {
|
|
192
|
+
super(name);
|
|
193
|
+
this.childConfigs = childConfigs;
|
|
194
|
+
this.totalChildren = childConfigs.length;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@Task()
|
|
198
|
+
async spawnChild(config: { name: string; shouldFail: boolean }): Promise<FailableChildWorkflow> {
|
|
199
|
+
return new FailableChildWorkflow(config.name, config.shouldFail, this);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async run(): Promise<{ success: number; failed: number }> {
|
|
203
|
+
this.setStatus('running');
|
|
204
|
+
this.logger.info(`Starting resilient parent with ${this.totalChildren} children`);
|
|
205
|
+
|
|
206
|
+
for (const config of this.childConfigs) {
|
|
207
|
+
const child = await this.spawnChild(config);
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
await child.run();
|
|
211
|
+
this.successfulChildren++;
|
|
212
|
+
this.logger.info(`Child ${config.name} succeeded`);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
this.failedChildren++;
|
|
215
|
+
const wfError = error as WorkflowError;
|
|
216
|
+
this.logger.warn(`Child ${config.name} failed: ${wfError.message}`);
|
|
217
|
+
// Continue with other children instead of failing entirely
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const allSucceeded = this.failedChildren === 0;
|
|
222
|
+
this.setStatus(allSucceeded ? 'completed' : 'completed'); // Still complete, but with partial success
|
|
223
|
+
this.logger.info(`Completed: ${this.successfulChildren} succeeded, ${this.failedChildren} failed`);
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
success: this.successfulChildren,
|
|
227
|
+
failed: this.failedChildren,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Run the error handling example
|
|
234
|
+
*/
|
|
235
|
+
export async function runErrorHandlingExample(): Promise<void> {
|
|
236
|
+
printHeader('Example 5: Error Handling');
|
|
237
|
+
|
|
238
|
+
// Part 1: Basic error wrapping
|
|
239
|
+
printSection('Part 1: WorkflowError Structure');
|
|
240
|
+
{
|
|
241
|
+
const workflow = new ErrorDemoWorkflow('ErrorDemo');
|
|
242
|
+
const debugger_ = new WorkflowTreeDebugger(workflow);
|
|
243
|
+
|
|
244
|
+
let capturedError: WorkflowError | null = null;
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
await workflow.run();
|
|
248
|
+
} catch (error) {
|
|
249
|
+
capturedError = error as WorkflowError;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
console.log('Error caught and wrapped in WorkflowError:');
|
|
253
|
+
console.log(` message: ${capturedError?.message}`);
|
|
254
|
+
console.log(` workflowId: ${capturedError?.workflowId}`);
|
|
255
|
+
console.log(` stack: ${capturedError?.stack?.split('\n')[0]}...`);
|
|
256
|
+
|
|
257
|
+
console.log('\nState snapshot at time of error:');
|
|
258
|
+
console.log(JSON.stringify(capturedError?.state, null, 2));
|
|
259
|
+
|
|
260
|
+
console.log('\nLogs at time of error:');
|
|
261
|
+
capturedError?.logs.forEach((log) => {
|
|
262
|
+
console.log(` [${log.level}] ${log.message}`);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
console.log('\nTree state after error:');
|
|
266
|
+
console.log(debugger_.toTreeString());
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Part 2: Error events
|
|
270
|
+
printSection('Part 2: Error Events');
|
|
271
|
+
{
|
|
272
|
+
const workflow = new ErrorDemoWorkflow('ErrorEvents');
|
|
273
|
+
const errors: WorkflowEvent[] = [];
|
|
274
|
+
|
|
275
|
+
const observer: WorkflowObserver = {
|
|
276
|
+
onLog: () => {},
|
|
277
|
+
onEvent: (event) => {
|
|
278
|
+
if (event.type === 'error') {
|
|
279
|
+
errors.push(event);
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
onStateUpdated: () => {},
|
|
283
|
+
onTreeChanged: () => {},
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
workflow.addObserver(observer);
|
|
287
|
+
|
|
288
|
+
try {
|
|
289
|
+
await workflow.run();
|
|
290
|
+
} catch {
|
|
291
|
+
// Expected
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
console.log(`Error events captured: ${errors.length}`);
|
|
295
|
+
errors.forEach((e) => {
|
|
296
|
+
if (e.type === 'error') {
|
|
297
|
+
console.log(` - Node: ${e.node.name}`);
|
|
298
|
+
console.log(` Message: ${e.error.message}`);
|
|
299
|
+
console.log(` State keys: ${Object.keys(e.error.state).join(', ')}`);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Part 3: Retry logic
|
|
305
|
+
printSection('Part 3: Retry Pattern');
|
|
306
|
+
{
|
|
307
|
+
console.log('Workflow that succeeds on 3rd attempt:');
|
|
308
|
+
const workflow1 = new RetryableWorkflow('RetrySuccess', 3);
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
const success = await workflow1.run();
|
|
312
|
+
console.log(` Result: ${success ? 'SUCCESS' : 'FAILED'}`);
|
|
313
|
+
console.log(` Attempts: ${workflow1.attempt}`);
|
|
314
|
+
} catch {
|
|
315
|
+
console.log(' Unexpected failure');
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
console.log('\nWorkflow that exhausts all retries:');
|
|
319
|
+
const workflow2 = new RetryableWorkflow('RetryFail', 10); // Will never succeed
|
|
320
|
+
|
|
321
|
+
try {
|
|
322
|
+
await workflow2.run();
|
|
323
|
+
} catch (error) {
|
|
324
|
+
const wfError = error as WorkflowError;
|
|
325
|
+
console.log(` Failed after ${workflow2.attempt} attempts`);
|
|
326
|
+
console.log(` Final error: ${wfError.message}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Part 4: Parent-child error isolation
|
|
331
|
+
printSection('Part 4: Error Isolation in Hierarchies');
|
|
332
|
+
{
|
|
333
|
+
const childConfigs = [
|
|
334
|
+
{ name: 'Child-A', shouldFail: false },
|
|
335
|
+
{ name: 'Child-B', shouldFail: true }, // This one will fail
|
|
336
|
+
{ name: 'Child-C', shouldFail: false },
|
|
337
|
+
{ name: 'Child-D', shouldFail: true }, // This one will fail
|
|
338
|
+
{ name: 'Child-E', shouldFail: false },
|
|
339
|
+
];
|
|
340
|
+
|
|
341
|
+
const workflow = new ResilientParentWorkflow('ResilientParent', childConfigs);
|
|
342
|
+
const debugger_ = new WorkflowTreeDebugger(workflow);
|
|
343
|
+
|
|
344
|
+
const result = await workflow.run();
|
|
345
|
+
|
|
346
|
+
console.log('Result:', result);
|
|
347
|
+
console.log('\nTree visualization:');
|
|
348
|
+
console.log(debugger_.toTreeString());
|
|
349
|
+
|
|
350
|
+
console.log('Child statuses:');
|
|
351
|
+
workflow.children.forEach((child) => {
|
|
352
|
+
const node = child.getNode();
|
|
353
|
+
const state = getObservedState(child);
|
|
354
|
+
console.log(` ${node.name}: ${node.status} (internal: ${state.taskStatus || 'N/A'})`);
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Part 5: Error context preservation
|
|
359
|
+
printSection('Part 5: Full Error Context');
|
|
360
|
+
{
|
|
361
|
+
const workflow = new ErrorDemoWorkflow('ContextDemo');
|
|
362
|
+
|
|
363
|
+
try {
|
|
364
|
+
await workflow.run();
|
|
365
|
+
} catch (error) {
|
|
366
|
+
const wfError = error as WorkflowError;
|
|
367
|
+
|
|
368
|
+
console.log('Complete WorkflowError object:');
|
|
369
|
+
console.log({
|
|
370
|
+
message: wfError.message,
|
|
371
|
+
workflowId: wfError.workflowId,
|
|
372
|
+
hasStack: !!wfError.stack,
|
|
373
|
+
stateFields: Object.keys(wfError.state),
|
|
374
|
+
logCount: wfError.logs.length,
|
|
375
|
+
originalError: wfError.original instanceof Error ? wfError.original.message : 'unknown',
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
console.log('\nNote: sensitiveContext is redacted in state snapshot');
|
|
379
|
+
console.log('State:', wfError.state);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Run if executed directly
|
|
385
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
386
|
+
runErrorHandlingExample().catch(console.error);
|
|
387
|
+
}
|