groundswell 0.0.2 → 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 +26 -9
- package/dist/cache/cache-key.d.ts +86 -0
- package/dist/cache/cache-key.d.ts.map +1 -0
- package/dist/cache/cache-key.js +204 -0
- package/dist/cache/cache-key.js.map +1 -0
- package/dist/cache/cache.d.ts +104 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +179 -0
- package/dist/cache/cache.js.map +1 -0
- package/{src/cache/index.ts → dist/cache/index.d.ts} +1 -1
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +6 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/core/agent.d.ts +203 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +833 -0
- package/dist/core/agent.js.map +1 -0
- package/{src/core/context.ts → dist/core/context.d.ts} +16 -67
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +80 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/event-tree.d.ts +72 -0
- package/dist/core/event-tree.d.ts.map +1 -0
- package/dist/core/event-tree.js +211 -0
- package/dist/core/event-tree.js.map +1 -0
- package/{src/core/factory.ts → dist/core/factory.d.ts} +6 -27
- package/dist/core/factory.d.ts.map +1 -0
- package/dist/core/factory.js +110 -0
- package/dist/core/factory.js.map +1 -0
- package/{src/core/index.ts → dist/core/index.d.ts} +2 -10
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +50 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +91 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/mcp-handler.d.ts +127 -0
- package/dist/core/mcp-handler.d.ts.map +1 -0
- package/dist/core/mcp-handler.js +323 -0
- package/dist/core/mcp-handler.js.map +1 -0
- package/dist/core/prompt.d.ts +80 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +120 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/workflow-context.d.ts +61 -0
- package/dist/core/workflow-context.d.ts.map +1 -0
- package/dist/core/workflow-context.js +358 -0
- package/dist/core/workflow-context.js.map +1 -0
- package/dist/core/workflow.d.ts +543 -0
- package/dist/core/workflow.d.ts.map +1 -0
- package/dist/core/workflow.js +986 -0
- package/dist/core/workflow.js.map +1 -0
- package/dist/debugger/event-replayer.d.ts +422 -0
- package/dist/debugger/event-replayer.d.ts.map +1 -0
- package/dist/debugger/event-replayer.js +639 -0
- package/dist/debugger/event-replayer.js.map +1 -0
- package/dist/debugger/index.d.ts +2 -0
- package/dist/debugger/index.d.ts.map +1 -0
- package/{src/debugger/index.ts → dist/debugger/index.js} +1 -0
- package/dist/debugger/index.js.map +1 -0
- package/dist/debugger/tree-debugger.d.ts +240 -0
- package/dist/debugger/tree-debugger.d.ts.map +1 -0
- package/dist/debugger/tree-debugger.js +620 -0
- package/dist/debugger/tree-debugger.js.map +1 -0
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/{src/decorators/index.ts → dist/decorators/index.js} +1 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/observed-state.d.ts +32 -0
- package/dist/decorators/observed-state.d.ts.map +1 -0
- package/dist/decorators/observed-state.js +79 -0
- package/dist/decorators/observed-state.js.map +1 -0
- package/dist/decorators/step.d.ts +15 -0
- package/dist/decorators/step.d.ts.map +1 -0
- package/dist/decorators/step.js +192 -0
- package/dist/decorators/step.js.map +1 -0
- package/dist/decorators/task.d.ts +50 -0
- package/dist/decorators/task.d.ts.map +1 -0
- package/dist/decorators/task.js +118 -0
- package/dist/decorators/task.js.map +1 -0
- package/dist/examples/index.d.ts +3 -0
- package/dist/examples/index.d.ts.map +1 -0
- package/{src/examples/index.ts → dist/examples/index.js} +1 -0
- package/dist/examples/index.js.map +1 -0
- package/dist/examples/tdd-orchestrator.d.ts +15 -0
- package/dist/examples/tdd-orchestrator.d.ts.map +1 -0
- package/dist/examples/tdd-orchestrator.js +121 -0
- package/dist/examples/tdd-orchestrator.js.map +1 -0
- package/dist/examples/test-cycle-workflow.d.ts +14 -0
- package/dist/examples/test-cycle-workflow.d.ts.map +1 -0
- package/dist/examples/test-cycle-workflow.js +116 -0
- package/dist/examples/test-cycle-workflow.js.map +1 -0
- package/dist/harnesses/claude-code-harness.d.ts +391 -0
- package/dist/harnesses/claude-code-harness.d.ts.map +1 -0
- package/dist/harnesses/claude-code-harness.js +1076 -0
- package/dist/harnesses/claude-code-harness.js.map +1 -0
- package/dist/harnesses/harness-registry.d.ts +440 -0
- package/dist/harnesses/harness-registry.d.ts.map +1 -0
- package/dist/harnesses/harness-registry.js +543 -0
- package/dist/harnesses/harness-registry.js.map +1 -0
- package/dist/harnesses/index.d.ts +12 -0
- package/dist/harnesses/index.d.ts.map +1 -0
- package/dist/harnesses/index.js +11 -0
- package/dist/harnesses/index.js.map +1 -0
- package/dist/harnesses/pi-harness.d.ts +219 -0
- package/dist/harnesses/pi-harness.d.ts.map +1 -0
- package/dist/harnesses/pi-harness.js +676 -0
- package/dist/harnesses/pi-harness.js.map +1 -0
- package/dist/harnesses/pi-schema-converter.d.ts +24 -0
- package/dist/harnesses/pi-schema-converter.d.ts.map +1 -0
- package/dist/harnesses/pi-schema-converter.js +81 -0
- package/dist/harnesses/pi-schema-converter.js.map +1 -0
- package/dist/harnesses/register-defaults.d.ts +24 -0
- package/dist/harnesses/register-defaults.d.ts.map +1 -0
- package/dist/harnesses/register-defaults.js +40 -0
- package/dist/harnesses/register-defaults.js.map +1 -0
- package/dist/harnesses/session-store.d.ts +201 -0
- package/dist/harnesses/session-store.d.ts.map +1 -0
- package/dist/harnesses/session-store.js +254 -0
- package/dist/harnesses/session-store.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/reflection/index.d.ts +5 -0
- package/dist/reflection/index.d.ts.map +1 -0
- package/{src/reflection/index.ts → dist/reflection/index.js} +1 -1
- package/dist/reflection/index.js.map +1 -0
- package/dist/reflection/reflection.d.ts +84 -0
- package/dist/reflection/reflection.d.ts.map +1 -0
- package/dist/reflection/reflection.js +344 -0
- package/dist/reflection/reflection.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +11 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/introspection.d.ts +165 -0
- package/dist/tools/introspection.d.ts.map +1 -0
- package/dist/tools/introspection.js +324 -0
- package/dist/tools/introspection.js.map +1 -0
- package/dist/types/agent.d.ts +1317 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +423 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/decorators.d.ts +40 -0
- package/dist/types/decorators.d.ts.map +1 -0
- package/dist/types/decorators.js +2 -0
- package/dist/types/decorators.js.map +1 -0
- package/dist/types/error-strategy.d.ts +13 -0
- package/dist/types/error-strategy.d.ts.map +1 -0
- package/dist/types/error-strategy.js +2 -0
- package/dist/types/error-strategy.js.map +1 -0
- package/dist/types/error.d.ts +20 -0
- package/dist/types/error.d.ts.map +1 -0
- package/dist/types/error.js +2 -0
- package/dist/types/error.js.map +1 -0
- package/dist/types/events.d.ts +113 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +2 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/harnesses.d.ts +474 -0
- package/dist/types/harnesses.d.ts.map +1 -0
- package/dist/types/harnesses.js +2 -0
- package/dist/types/harnesses.js.map +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/logging.d.ts +24 -0
- package/dist/types/logging.d.ts.map +1 -0
- package/dist/types/logging.js +2 -0
- package/dist/types/logging.js.map +1 -0
- package/dist/types/observer.d.ts +18 -0
- package/dist/types/observer.d.ts.map +1 -0
- package/dist/types/observer.js +2 -0
- package/dist/types/observer.js.map +1 -0
- package/dist/types/prompt.d.ts +31 -0
- package/dist/types/prompt.d.ts.map +1 -0
- package/dist/types/prompt.js +6 -0
- package/dist/types/prompt.js.map +1 -0
- package/dist/types/providers.d.ts +691 -0
- package/dist/types/providers.d.ts.map +1 -0
- package/dist/types/providers.js +14 -0
- package/dist/types/providers.js.map +1 -0
- package/dist/types/reflection.d.ts +96 -0
- package/dist/types/reflection.d.ts.map +1 -0
- package/dist/types/reflection.js +24 -0
- package/dist/types/reflection.js.map +1 -0
- package/dist/types/restart.d.ts +132 -0
- package/dist/types/restart.d.ts.map +1 -0
- package/dist/types/restart.js +2 -0
- package/dist/types/restart.js.map +1 -0
- package/dist/types/sdk-primitives.d.ts +118 -0
- package/dist/types/sdk-primitives.d.ts.map +1 -0
- package/dist/types/sdk-primitives.js +6 -0
- package/dist/types/sdk-primitives.js.map +1 -0
- package/{src/types/snapshot.ts → dist/types/snapshot.d.ts} +5 -5
- package/dist/types/snapshot.d.ts.map +1 -0
- package/dist/types/snapshot.js +2 -0
- package/dist/types/snapshot.js.map +1 -0
- package/dist/types/streaming.d.ts +194 -0
- package/dist/types/streaming.d.ts.map +1 -0
- package/dist/types/streaming.js +67 -0
- package/dist/types/streaming.js.map +1 -0
- package/dist/types/workflow-context.d.ts +275 -0
- package/dist/types/workflow-context.d.ts.map +1 -0
- package/dist/types/workflow-context.js +8 -0
- package/dist/types/workflow-context.js.map +1 -0
- package/dist/types/workflow.d.ts +30 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +2 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/utils/agent-validation.d.ts +88 -0
- package/dist/utils/agent-validation.d.ts.map +1 -0
- package/dist/utils/agent-validation.js +87 -0
- package/dist/utils/agent-validation.js.map +1 -0
- package/dist/utils/delay.d.ts +7 -0
- package/dist/utils/delay.d.ts.map +1 -0
- package/dist/utils/delay.js +9 -0
- package/dist/utils/delay.js.map +1 -0
- package/dist/utils/harness-config.d.ts +180 -0
- package/dist/utils/harness-config.d.ts.map +1 -0
- package/dist/utils/harness-config.js +311 -0
- package/dist/utils/harness-config.js.map +1 -0
- package/dist/utils/id.d.ts +6 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +12 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +11 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/model-spec.d.ts +110 -0
- package/dist/utils/model-spec.d.ts.map +1 -0
- package/dist/utils/model-spec.js +149 -0
- package/dist/utils/model-spec.js.map +1 -0
- package/dist/utils/observable.d.ts +54 -0
- package/dist/utils/observable.d.ts.map +1 -0
- package/dist/utils/observable.js +82 -0
- package/dist/utils/observable.js.map +1 -0
- package/dist/utils/provider-config.d.ts +10 -0
- package/dist/utils/provider-config.d.ts.map +1 -0
- package/dist/utils/provider-config.js +10 -0
- package/dist/utils/provider-config.js.map +1 -0
- package/dist/utils/restart-analysis.d.ts +202 -0
- package/dist/utils/restart-analysis.d.ts.map +1 -0
- package/dist/utils/restart-analysis.js +426 -0
- package/dist/utils/restart-analysis.js.map +1 -0
- package/dist/utils/session-serialization.d.ts +118 -0
- package/dist/utils/session-serialization.d.ts.map +1 -0
- package/dist/utils/session-serialization.js +217 -0
- package/dist/utils/session-serialization.js.map +1 -0
- package/dist/utils/workflow-error-utils.d.ts +22 -0
- package/dist/utils/workflow-error-utils.d.ts.map +1 -0
- package/dist/utils/workflow-error-utils.js +45 -0
- package/dist/utils/workflow-error-utils.js.map +1 -0
- package/package.json +34 -5
- package/.claude/commands/subtask-planning/prp-base-create.md +0 -120
- package/.claude/commands/subtask-planning/prp-base-execute.md +0 -65
- package/.claude/commands/task-breakdown.md +0 -94
- package/.claude/settings.local.json +0 -9
- package/.claude/system_prompts/task-breakdown.md +0 -101
- package/CHANGELOG.md +0 -188
- package/PRD.md +0 -543
- package/PRPs/001-hierarchical-workflow-engine.md +0 -2438
- package/PRPs/PRDs/002-agent-prompt.md +0 -390
- package/PRPs/PRDs/003-agent-prompt.md +0 -943
- package/PRPs/PRDs/004-agent-prompt.md +0 -1136
- package/PRPs/PRDs/tasks-001.json +0 -492
- package/PRPs/README.md +0 -83
- package/PRPs/templates/prp_base.md +0 -222
- package/docs/agent.md +0 -422
- package/docs/prompt.md +0 -419
- package/docs/workflow.md +0 -600
- package/examples/README.md +0 -258
- package/examples/examples/01-basic-workflow.ts +0 -100
- package/examples/examples/02-decorator-options.ts +0 -217
- package/examples/examples/03-parent-child.ts +0 -241
- package/examples/examples/04-observers-debugger.ts +0 -340
- package/examples/examples/05-error-handling.ts +0 -387
- package/examples/examples/06-concurrent-tasks.ts +0 -352
- package/examples/examples/07-agent-loops.ts +0 -432
- package/examples/examples/08-sdk-features.ts +0 -667
- package/examples/examples/09-reflection.ts +0 -573
- package/examples/examples/10-introspection.ts +0 -550
- package/examples/examples/11-reparenting-workflows.ts +0 -269
- package/examples/index.ts +0 -147
- package/examples/utils/helpers.ts +0 -57
- package/package-lock.json +0 -2398
- package/plan/001_d3bb02af4886/TEST_RESULTS.md +0 -259
- package/plan/001_d3bb02af4886/backlog.json +0 -867
- package/plan/001_d3bb02af4886/bug_fix_tasks.json +0 -484
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S1/PRP.md +0 -488
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S2/PRP.md +0 -581
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M1T1S3/PRP.md +0 -687
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S1/PRP.md +0 -492
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/PRP.md +0 -932
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/concurrent_error_testing_patterns.md +0 -1109
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/vitest_concurrent_testing.md +0 -802
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T1S3/research/workflow_engine_test_references.md +0 -603
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S1/PRP.md +0 -564
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S3/PRP.md +0 -518
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T2S4/PRP.md +0 -1252
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/PRP.md +0 -364
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/CODEBASE_INVENTORY.md +0 -114
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/DECORATOR_DOCUMENTATION_PATTERNS.md +0 -205
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/PRD_LOCATION_ANALYSIS.md +0 -199
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M2T3S1/research/ULTRATHINK_PRP_PLAN.md +0 -134
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/PRP.md +0 -495
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S1/research/console_error_inventory.md +0 -435
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S2/PRP.md +0 -506
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T1S3/PRP.md +0 -612
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/PRP.md +0 -558
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T2S2/research/external_research.md +0 -788
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S2/PRP.md +0 -460
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T3S3/PRP.md +0 -454
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/PRP.md +0 -520
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/RECOMMENDATION.md +0 -417
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/external_workflow_engines_research.md +0 -760
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S1/research/security_implications_analysis.md +0 -245
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M3T4S2/PRP.md +0 -792
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/PRP.md +0 -535
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S1/TEST_EXECUTION_REPORT.md +0 -190
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/PRP.md +0 -654
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/TEST_FIX_REPORT.md +0 -227
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/KEY_FINDINGS.md +0 -345
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/QUICK_REFERENCE.md +0 -193
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T1S2/research/test_maintenance_research.md +0 -1323
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/BREAKING_CHANGES_AUDIT.md +0 -1011
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S1/PRP.md +0 -927
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/P1M4T3S2/PRP.md +0 -505
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/architecture/logger_child_signature_analysis.md +0 -401
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/child_implementation_research.md +0 -142
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/test_patterns_research.md +0 -112
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S3/vitest_patterns_research.md +0 -159
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/PRP.md +0 -549
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/VERIFICATION_REPORT.md +0 -368
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/edge_case_analysis.md +0 -172
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M1T1S4/usage_inventory.md +0 -175
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S2/PRP.md +0 -696
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T1S4/PRP.md +0 -860
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/PRP.md +0 -1066
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01-testing-aggregated-errors.md +0 -1103
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/01_typescript_error_aggregation_patterns.md +0 -789
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02-error-merge-strategy-testing-guide.md +0 -1098
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/02_aggregate_error_patterns.md +0 -1037
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03-promise-allsettled-testing-patterns.md +0 -916
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/03_error_merging_strategies.md +0 -1045
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/04_github_stackoverflow_examples.md +0 -890
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/05_comprehensive_summary.md +0 -822
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/INDEX.md +0 -668
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/QUICK_REFERENCE.md +0 -706
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/README.md +0 -265
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S2/research/RESEARCH_REPORT.md +0 -655
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T2S4/research/vitest_testing_patterns.md +0 -1103
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M2T3S2/PRP.md +0 -426
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/PRP.md +0 -506
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/QUICK_REFERENCE.md +0 -114
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/RESEARCH_SUMMARY.md +0 -316
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S2/research/vitest_observer_error_logging_best_practices.md +0 -754
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T1S3/PRP.md +0 -612
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/PRP.md +0 -719
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/README.md +0 -215
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S1/analysis.md +0 -765
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T2S3/PRP.md +0 -718
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/DECISION.md +0 -149
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/PRP.md +0 -470
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/ULTRATHINK_PLAN.md +0 -332
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/codebase_workflow_name_analysis.md +0 -167
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/external_best_practices.md +0 -265
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T3S1/research/validation_patterns.md +0 -273
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S1/workflow_engine_ancestry_api_research.md +0 -760
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M3T4S3-PRP.md +0 -434
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S1/PRP.md +0 -717
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/PRP.md +0 -472
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/VALIDATION_REPORT.md +0 -125
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/P1M4T2S2/research/ULTRATHINK_PRP_PLAN.md +0 -301
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/error-logging-best-practices.md +0 -1170
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/research_typescript_partial_and_overloads.md +0 -940
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-quick-reference.md +0 -151
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/docs/vitest-research.md +0 -650
- package/plan/001_d3bb02af4886/bugfix/001_e8e04329daf3/prd_snapshot.md +0 -259
- package/plan/001_d3bb02af4886/bugfix/P1M1T1S1/PRP.md +0 -457
- package/plan/001_d3bb02af4886/bugfix/RESEARCH_SUMMARY.md +0 -346
- package/plan/001_d3bb02af4886/bugfix/architecture/codebase_structure.md +0 -311
- package/plan/001_d3bb02af4886/bugfix/architecture/concurrent_execution_best_practices.md +0 -1565
- package/plan/001_d3bb02af4886/bugfix/architecture/error_handling_patterns.md +0 -288
- package/plan/001_d3bb02af4886/bugfix/architecture/promise_all_analysis.md +0 -741
- package/plan/001_d3bb02af4886/docs/PRP/P1M1T1S4-functional-workflow-error-state-capture-test.md +0 -652
- package/plan/001_d3bb02af4886/docs/PRP/P1P2-PRP.md +0 -527
- package/plan/001_d3bb02af4886/docs/PRP/P3P4-PRP.md +0 -1388
- package/plan/001_d3bb02af4886/docs/PRP/P4P5-PRP.md +0 -1136
- package/plan/001_d3bb02af4886/docs/PRP/PRP.md +0 -527
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S1-PRP.md +0 -415
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S2-PRP.md +0 -378
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M1T2S4-PRP.md +0 -713
- package/plan/001_d3bb02af4886/docs/PRP/bugfix/P1M2T1S4-PRP.md +0 -370
- package/plan/001_d3bb02af4886/docs/PRP_P1M3T1S3.md +0 -499
- package/plan/001_d3bb02af4886/docs/TEST_RESULTS.md +0 -230
- package/plan/001_d3bb02af4886/docs/architecture/external_deps.md +0 -358
- package/plan/001_d3bb02af4886/docs/architecture/system_context.md +0 -242
- package/plan/001_d3bb02af4886/docs/bugfix/ANALYSIS_PRD_VS_IMPLEMENTATION.md +0 -1134
- package/plan/001_d3bb02af4886/docs/bugfix/GAP_ANALYSIS_SUMMARY.md +0 -179
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/PRP.md +0 -629
- package/plan/001_d3bb02af4886/docs/bugfix/P1M4T2S1/validation-report.md +0 -214
- package/plan/001_d3bb02af4886/docs/bugfix/PRP_P1M4T2S3.md +0 -629
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_PRP.md +0 -529
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_QUICK_REFERENCE.md +0 -142
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_README.md +0 -304
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_TEST_RESULTS.md +0 -558
- package/plan/001_d3bb02af4886/docs/bugfix/bugfix_VALIDATION_SUMMARY.md +0 -256
- package/plan/001_d3bb02af4886/docs/bugfix/system_context.md +0 -346
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/bug_analysis.md +0 -415
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/implementation_patterns.md +0 -489
- package/plan/001_d3bb02af4886/docs/bugfix-architecture/system_context.md +0 -218
- package/plan/001_d3bb02af4886/docs/bugfix_INITIATION_SUMMARY.md +0 -380
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_PATTERNS.md +0 -1923
- package/plan/001_d3bb02af4886/docs/research/CYCLE_DETECTION_QUICK_REF.md +0 -319
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/codebase-context.md +0 -115
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/cycle-detection-algorithms.md +0 -134
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/test-patterns.md +0 -153
- package/plan/001_d3bb02af4886/docs/research/P1M1T2S1/workflow-class.md +0 -132
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_BEST_PRACTICES.md +0 -716
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/DECORATOR_DOCUMENTATION_QUICK_REF.md +0 -186
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/GROUNDSWELL_DECORATOR_EXAMPLES.md +0 -604
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/INDEX.md +0 -213
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/codebase_structure.md +0 -30
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/existing_test_pattern.md +0 -56
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/getRootObservers_implementation.md +0 -53
- package/plan/001_d3bb02af4886/docs/research/P1M2T1S4/test_conventions.md +0 -49
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/PRP.md +0 -958
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/QUICK_REFERENCE.md +0 -339
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/README.md +0 -305
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/SUMMARY.md +0 -433
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/bidirectional-tree-consistency-testing.md +0 -1574
- package/plan/001_d3bb02af4886/docs/research/P1M3T1S4/test-pattern-examples.md +0 -1014
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_BEST_PRACTICES.md +0 -1929
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_CODE_PATTERNS.md +0 -857
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_INTEGRATION_GUIDE.md +0 -738
- package/plan/001_d3bb02af4886/docs/research/P1P2/LRU_CACHE_RESEARCH_INDEX.md +0 -424
- package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_INDEX.md +0 -291
- package/plan/001_d3bb02af4886/docs/research/P1P2/REFLECTION_RESEARCH_REPORT.md +0 -1342
- package/plan/001_d3bb02af4886/docs/research/P1P2/RESEARCH_SUMMARY.md +0 -342
- package/plan/001_d3bb02af4886/docs/research/P1P2/anthropic-sdk.md +0 -174
- package/plan/001_d3bb02af4886/docs/research/P1P2/async-local-storage.md +0 -200
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-code-patterns.md +0 -1205
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-decision-matrix.md +0 -421
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-implementation-guide.md +0 -1341
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-integration-guide.md +0 -834
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-patterns.md +0 -1468
- package/plan/001_d3bb02af4886/docs/research/P1P2/reflection-quick-reference.md +0 -558
- package/plan/001_d3bb02af4886/docs/research/P1P2/zod-schema.md +0 -152
- package/plan/001_d3bb02af4886/docs/research/P3P4/caching-lru.md +0 -116
- package/plan/001_d3bb02af4886/docs/research/P3P4/introspection-tools.md +0 -177
- package/plan/001_d3bb02af4886/docs/research/P3P4/reflection-patterns.md +0 -117
- package/plan/001_d3bb02af4886/docs/research/P4P5/RESEARCH_SUMMARY.md +0 -151
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_QUICK_REF.md +0 -376
- package/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_RESEARCH.md +0 -1507
- package/plan/001_d3bb02af4886/docs/research/bugfix_typescript_patterns.md +0 -949
- package/plan/001_d3bb02af4886/docs/research/error-testing-research.md +0 -619
- package/plan/001_d3bb02af4886/docs/research/error_handling_patterns.md +0 -723
- package/plan/001_d3bb02af4886/docs/research/general/INTROSPECTION_RESEARCH_SUMMARY.md +0 -378
- package/plan/001_d3bb02af4886/docs/research/general/README-INTROSPECTION.md +0 -352
- package/plan/001_d3bb02af4886/docs/research/general/agent-introspection-patterns.md +0 -1085
- package/plan/001_d3bb02af4886/docs/research/general/introspection-security-guide.md +0 -984
- package/plan/001_d3bb02af4886/docs/research/general/introspection-tool-examples.md +0 -875
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/PRP_TEMPLATE.md +0 -460
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/QUICK_REFERENCE.md +0 -324
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/README.md +0 -175
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/RESEARCH_REPORT.md +0 -499
- package/plan/001_d3bb02af4886/docs/research/incremental-tree-map-updates/SUMMARY.md +0 -163
- package/plan/001_d3bb02af4886/prd_snapshot.md +0 -543
- package/plan/bugfix/BUG_FIX_SUMMARY.md +0 -961
- package/scripts/generate-llms-full.ts +0 -206
- package/src/__tests__/adversarial/attachChild-performance.test.ts +0 -216
- package/src/__tests__/adversarial/circular-reference.test.ts +0 -101
- package/src/__tests__/adversarial/complex-circular-reference.test.ts +0 -139
- package/src/__tests__/adversarial/concurrent-task-failures.test.ts +0 -571
- package/src/__tests__/adversarial/deep-analysis.test.ts +0 -729
- package/src/__tests__/adversarial/deep-hierarchy-stress.test.ts +0 -213
- package/src/__tests__/adversarial/e2e-prd-validation.test.ts +0 -448
- package/src/__tests__/adversarial/edge-case.test.ts +0 -703
- package/src/__tests__/adversarial/error-merge-strategy.test.ts +0 -760
- package/src/__tests__/adversarial/incremental-performance.test.ts +0 -140
- package/src/__tests__/adversarial/node-map-update-benchmarks.test.ts +0 -457
- package/src/__tests__/adversarial/observer-propagation.test.ts +0 -487
- package/src/__tests__/adversarial/parent-validation.test.ts +0 -143
- package/src/__tests__/adversarial/prd-12-2-compliance.test.ts +0 -611
- package/src/__tests__/adversarial/prd-compliance.test.ts +0 -731
- package/src/__tests__/compatibility/backward-compatibility.test.ts +0 -1572
- package/src/__tests__/helpers/index.ts +0 -18
- package/src/__tests__/helpers/tree-verification.ts +0 -257
- package/src/__tests__/integration/agent-workflow.test.ts +0 -256
- package/src/__tests__/integration/bidirectional-consistency.test.ts +0 -847
- package/src/__tests__/integration/observer-logging.test.ts +0 -643
- package/src/__tests__/integration/tree-mirroring.test.ts +0 -151
- package/src/__tests__/integration/workflow-reparenting.test.ts +0 -303
- package/src/__tests__/unit/agent.test.ts +0 -169
- package/src/__tests__/unit/cache-key.test.ts +0 -182
- package/src/__tests__/unit/cache.test.ts +0 -172
- package/src/__tests__/unit/context.test.ts +0 -217
- package/src/__tests__/unit/decorators.test.ts +0 -100
- package/src/__tests__/unit/introspection-tools.test.ts +0 -277
- package/src/__tests__/unit/logger.test.ts +0 -293
- package/src/__tests__/unit/observable.test.ts +0 -321
- package/src/__tests__/unit/prompt.test.ts +0 -135
- package/src/__tests__/unit/reflection.test.ts +0 -210
- package/src/__tests__/unit/tree-debugger-incremental.test.ts +0 -170
- package/src/__tests__/unit/tree-debugger.test.ts +0 -85
- package/src/__tests__/unit/utils/workflow-error-utils.test.ts +0 -209
- package/src/__tests__/unit/workflow-detachChild.test.ts +0 -100
- package/src/__tests__/unit/workflow-emitEvent-childDetached.test.ts +0 -153
- package/src/__tests__/unit/workflow-isDescendantOf.test.ts +0 -180
- package/src/__tests__/unit/workflow.test.ts +0 -357
- package/src/cache/cache-key.ts +0 -244
- package/src/cache/cache.ts +0 -236
- package/src/core/agent.ts +0 -593
- package/src/core/event-tree.ts +0 -260
- package/src/core/logger.ts +0 -112
- package/src/core/mcp-handler.ts +0 -184
- package/src/core/prompt.ts +0 -150
- package/src/core/workflow-context.ts +0 -351
- package/src/core/workflow.ts +0 -540
- package/src/debugger/tree-debugger.ts +0 -255
- package/src/decorators/observed-state.ts +0 -95
- package/src/decorators/step.ts +0 -139
- package/src/decorators/task.ts +0 -159
- package/src/examples/tdd-orchestrator.ts +0 -65
- package/src/examples/test-cycle-workflow.ts +0 -64
- package/src/index.ts +0 -142
- package/src/reflection/reflection.ts +0 -407
- package/src/tools/index.ts +0 -36
- package/src/tools/introspection.ts +0 -464
- package/src/types/agent.ts +0 -90
- package/src/types/decorators.ts +0 -32
- package/src/types/error-strategy.ts +0 -13
- package/src/types/error.ts +0 -20
- package/src/types/events.ts +0 -75
- package/src/types/index.ts +0 -55
- package/src/types/logging.ts +0 -24
- package/src/types/observer.ts +0 -18
- package/src/types/prompt.ts +0 -40
- package/src/types/reflection.ts +0 -117
- package/src/types/sdk-primitives.ts +0 -128
- package/src/types/workflow-context.ts +0 -163
- package/src/types/workflow.ts +0 -37
- package/src/utils/id.ts +0 -11
- package/src/utils/index.ts +0 -4
- package/src/utils/observable.ts +0 -106
- package/src/utils/workflow-error-utils.ts +0 -56
- package/tsconfig.json +0 -22
- package/vitest.config.ts +0 -16
|
@@ -1,1037 +0,0 @@
|
|
|
1
|
-
# AggregateError Patterns and Implementations
|
|
2
|
-
|
|
3
|
-
**Research Date:** 2026-01-12
|
|
4
|
-
**Status:** Comprehensive Research Report
|
|
5
|
-
**Target:** P1M2T2S2 - Error Aggregation Implementation
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Executive Summary
|
|
10
|
-
|
|
11
|
-
This document provides comprehensive research on AggregateError patterns and implementations in JavaScript and TypeScript. It covers the native AggregateError API, custom implementations, polyfills, and production-grade patterns.
|
|
12
|
-
|
|
13
|
-
**Key Finding:** Native AggregateError is available in ES2021+ (Node.js 15.0+, modern browsers), but custom implementations are needed for enriched error context and hierarchical error aggregation in workflow engines.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Table of Contents
|
|
18
|
-
|
|
19
|
-
1. [Native AggregateError API](#1-native-aggregateerror-api)
|
|
20
|
-
2. [Custom AggregateError Implementations](#2-custom-aggregateerror-implementations)
|
|
21
|
-
3. [Polyfill Strategies](#3-polyfill-strategies)
|
|
22
|
-
4. [Production-Grade Patterns](#4-production-grade-patterns)
|
|
23
|
-
5. [TypeScript Integration](#5-typescript-integration)
|
|
24
|
-
6. [Common Pitfalls](#6-common-pitfalls)
|
|
25
|
-
7. [Code Examples](#7-code-examples)
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## 1. Native AggregateError API
|
|
30
|
-
|
|
31
|
-
### 1.1 Basic Usage
|
|
32
|
-
|
|
33
|
-
AggregateError is a built-in error type in ES2021+:
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
// Basic usage
|
|
37
|
-
const error1 = new Error('First error');
|
|
38
|
-
const error2 = new Error('Second error');
|
|
39
|
-
const error3 = new Error('Third error');
|
|
40
|
-
|
|
41
|
-
const aggregate = new AggregateError([error1, error2, error3], 'Multiple errors occurred');
|
|
42
|
-
|
|
43
|
-
console.log(aggregate.message); // 'Multiple errors occurred'
|
|
44
|
-
console.log(aggregate.name); // 'AggregateError'
|
|
45
|
-
console.log(aggregate.errors); // [error1, error2, error3]
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
**Key Characteristics:**
|
|
49
|
-
- `message`: The main error message
|
|
50
|
-
- `errors`: Array of original errors
|
|
51
|
-
- `name`: Always 'AggregateError'
|
|
52
|
-
- `stack`: Stack trace pointing to AggregateError creation
|
|
53
|
-
|
|
54
|
-
### 1.2 Throwing AggregateError
|
|
55
|
-
|
|
56
|
-
```typescript
|
|
57
|
-
async function executeAll(promises: Promise<unknown>[]) {
|
|
58
|
-
const results = await Promise.allSettled(promises);
|
|
59
|
-
|
|
60
|
-
const errors = results
|
|
61
|
-
.filter((r): r is PromiseRejectedResult => r.status === 'rejected')
|
|
62
|
-
.map(r => r.reason);
|
|
63
|
-
|
|
64
|
-
if (errors.length > 0) {
|
|
65
|
-
throw new AggregateError(errors, `${errors.length} operation(s) failed`);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return results;
|
|
69
|
-
}
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### 1.3 Catching AggregateError
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
try {
|
|
76
|
-
await executeAll(promises);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
if (error instanceof AggregateError) {
|
|
79
|
-
console.error(`AggregateError: ${error.message}`);
|
|
80
|
-
console.error(`Contains ${error.errors.length} errors:`);
|
|
81
|
-
|
|
82
|
-
for (const err of error.errors) {
|
|
83
|
-
console.error(` - ${err.message}`);
|
|
84
|
-
}
|
|
85
|
-
} else {
|
|
86
|
-
console.error(`Unexpected error: ${error}`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### 1.4 Browser and Node.js Support
|
|
92
|
-
|
|
93
|
-
**AggregateError Support:**
|
|
94
|
-
|
|
95
|
-
| Environment | Version | Notes |
|
|
96
|
-
|------------|---------|-------|
|
|
97
|
-
| Chrome | 76+ | Full support |
|
|
98
|
-
| Firefox | 71+ | Full support |
|
|
99
|
-
| Safari | 13+ | Full support |
|
|
100
|
-
| Edge | 79+ | Full support |
|
|
101
|
-
| Node.js | 15.0.0+ | Full support |
|
|
102
|
-
| Deno | 1.0+ | Full support |
|
|
103
|
-
| Bun | 0.1.0+ | Full support |
|
|
104
|
-
|
|
105
|
-
**Polyfill Required For:**
|
|
106
|
-
- Node.js < 15.0.0
|
|
107
|
-
- Internet Explorer (all versions)
|
|
108
|
-
- Older mobile browsers
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
## 2. Custom AggregateError Implementations
|
|
113
|
-
|
|
114
|
-
### 2.1 Basic Custom AggregateError
|
|
115
|
-
|
|
116
|
-
For environments without native AggregateError or when you need custom behavior:
|
|
117
|
-
|
|
118
|
-
```typescript
|
|
119
|
-
class CustomAggregateError extends Error {
|
|
120
|
-
readonly errors: Error[];
|
|
121
|
-
|
|
122
|
-
constructor(errors: Error[], message?: string) {
|
|
123
|
-
super(message || `Multiple errors occurred: ${errors.length} errors`);
|
|
124
|
-
this.name = 'AggregateError';
|
|
125
|
-
this.errors = errors;
|
|
126
|
-
|
|
127
|
-
// Maintains proper stack trace (V8 only)
|
|
128
|
-
if (Error.captureStackTrace) {
|
|
129
|
-
Error.captureStackTrace(this, CustomAggregateError);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
**Key Features:**
|
|
136
|
-
- Mimics native AggregateError interface
|
|
137
|
-
- Works in all JavaScript environments
|
|
138
|
-
- Optional custom message
|
|
139
|
-
- Preserves stack trace (V8/Node.js)
|
|
140
|
-
|
|
141
|
-
### 2.2 Enriched AggregateError with Context
|
|
142
|
-
|
|
143
|
-
Add metadata for better debugging:
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
interface ErrorContext {
|
|
147
|
-
operationId?: string;
|
|
148
|
-
operationName?: string;
|
|
149
|
-
timestamp?: number;
|
|
150
|
-
[key: string]: unknown;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
interface ContextualizedError {
|
|
154
|
-
error: Error;
|
|
155
|
-
context?: ErrorContext;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
class EnrichedAggregateError extends Error {
|
|
159
|
-
readonly errors: ContextualizedError[];
|
|
160
|
-
readonly context?: {
|
|
161
|
-
parentOperation?: string;
|
|
162
|
-
parentWorkflow?: string;
|
|
163
|
-
timestamp: number;
|
|
164
|
-
};
|
|
165
|
-
readonly stats: {
|
|
166
|
-
totalErrors: number;
|
|
167
|
-
errorsByType: Record<string, number>;
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
constructor(
|
|
171
|
-
errors: Array<Error | ContextualizedError>,
|
|
172
|
-
message?: string,
|
|
173
|
-
context?: EnrichedAggregateError['context']
|
|
174
|
-
) {
|
|
175
|
-
super(message || `${errors.length} error(s) occurred`);
|
|
176
|
-
this.name = 'EnrichedAggregateError';
|
|
177
|
-
|
|
178
|
-
// Normalize errors to ContextualizedError format
|
|
179
|
-
this.errors = errors.map(err =>
|
|
180
|
-
err instanceof Error
|
|
181
|
-
? { error: err }
|
|
182
|
-
: err
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
this.context = context;
|
|
186
|
-
|
|
187
|
-
// Calculate statistics
|
|
188
|
-
const errorsByType: Record<string, number> = {};
|
|
189
|
-
this.errors.forEach(({ error }) => {
|
|
190
|
-
const type = error.constructor.name;
|
|
191
|
-
errorsByType[type] = (errorsByType[type] || 0) + 1;
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
this.stats = {
|
|
195
|
-
totalErrors: this.errors.length,
|
|
196
|
-
errorsByType,
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
if (Error.captureStackTrace) {
|
|
200
|
-
Error.captureStackTrace(this, EnrichedAggregateError);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Pretty-print the aggregate error
|
|
205
|
-
toString(): string {
|
|
206
|
-
let output = `${this.name}: ${this.message}\n`;
|
|
207
|
-
output += `Total errors: ${this.stats.totalErrors}\n\n`;
|
|
208
|
-
|
|
209
|
-
for (const { error, context } of this.errors) {
|
|
210
|
-
output += ` - ${error.name}: ${error.message}`;
|
|
211
|
-
if (context?.operationName) {
|
|
212
|
-
output += ` (in ${context.operationName})`;
|
|
213
|
-
}
|
|
214
|
-
output += '\n';
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (Object.keys(this.stats.errorsByType).length > 1) {
|
|
218
|
-
output += '\nError types:\n';
|
|
219
|
-
for (const [type, count] of Object.entries(this.stats.errorsByType)) {
|
|
220
|
-
output += ` - ${type}: ${count}\n`;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return output;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### 2.3 Hierarchical AggregateError
|
|
230
|
-
|
|
231
|
-
Support nested aggregation for workflow hierarchies:
|
|
232
|
-
|
|
233
|
-
```typescript
|
|
234
|
-
class HierarchicalAggregateError extends Error {
|
|
235
|
-
readonly errors: Error[];
|
|
236
|
-
readonly parent?: HierarchicalAggregateError;
|
|
237
|
-
readonly depth: number;
|
|
238
|
-
readonly path: string[];
|
|
239
|
-
|
|
240
|
-
constructor(
|
|
241
|
-
errors: Error[],
|
|
242
|
-
message?: string,
|
|
243
|
-
parent?: HierarchicalAggregateError
|
|
244
|
-
) {
|
|
245
|
-
super(message || `${errors.length} error(s) occurred`);
|
|
246
|
-
this.name = 'HierarchicalAggregateError';
|
|
247
|
-
this.errors = errors;
|
|
248
|
-
this.parent = parent;
|
|
249
|
-
this.depth = parent ? parent.depth + 1 : 0;
|
|
250
|
-
this.path = parent ? [...parent.path, parent.message] : [];
|
|
251
|
-
|
|
252
|
-
if (Error.captureStackTrace) {
|
|
253
|
-
Error.captureStackTrace(this, HierarchicalAggregateError);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Get all errors from the entire hierarchy
|
|
258
|
-
getAllErrors(): Error[] {
|
|
259
|
-
let allErrors = [...this.errors];
|
|
260
|
-
|
|
261
|
-
if (this.parent) {
|
|
262
|
-
allErrors = allErrors.concat(this.parent.getAllErrors());
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
return allErrors;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// Get total error count including parent errors
|
|
269
|
-
getTotalErrorCount(): number {
|
|
270
|
-
return this.errors.length + (this.parent?.getTotalErrorCount() || 0);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Pretty-print with hierarchy
|
|
274
|
-
toString(): string {
|
|
275
|
-
let output = `${' '.repeat(this.depth)}${this.name}: ${this.message}\n`;
|
|
276
|
-
output += `${' '.repeat(this.depth)}Total at this level: ${this.errors.length}\n`;
|
|
277
|
-
output += `${' '.repeat(this.depth)}Total in hierarchy: ${this.getTotalErrorCount()}\n`;
|
|
278
|
-
|
|
279
|
-
if (this.parent) {
|
|
280
|
-
output += '\n' + this.parent.toString();
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
return output;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
---
|
|
289
|
-
|
|
290
|
-
## 3. Polyfill Strategies
|
|
291
|
-
|
|
292
|
-
### 3.1 Simple Polyfill
|
|
293
|
-
|
|
294
|
-
For basic AggregateError functionality:
|
|
295
|
-
|
|
296
|
-
```typescript
|
|
297
|
-
// Polyfill for environments without AggregateError
|
|
298
|
-
if (typeof AggregateError === 'undefined') {
|
|
299
|
-
(globalThis as any).AggregateError = class AggregateError extends Error {
|
|
300
|
-
readonly errors: unknown[];
|
|
301
|
-
|
|
302
|
-
constructor(errors: unknown[], message?: string) {
|
|
303
|
-
super(message || `Multiple errors occurred: ${errors.length} errors`);
|
|
304
|
-
this.name = 'AggregateError';
|
|
305
|
-
this.errors = errors;
|
|
306
|
-
|
|
307
|
-
if (Error.captureStackTrace) {
|
|
308
|
-
Error.captureStackTrace(this, (globalThis as any).AggregateError);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
### 3.2 Feature Detection
|
|
316
|
-
|
|
317
|
-
Check for AggregateError support:
|
|
318
|
-
|
|
319
|
-
```typescript
|
|
320
|
-
function hasAggregateErrorSupport(): boolean {
|
|
321
|
-
return typeof AggregateError !== 'undefined';
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Usage
|
|
325
|
-
if (!hasAggregateErrorSupport()) {
|
|
326
|
-
// Load polyfill or use custom implementation
|
|
327
|
-
console.warn('AggregateError not supported, using polyfill');
|
|
328
|
-
}
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
### 3.3 Conditional Usage
|
|
332
|
-
|
|
333
|
-
Use native AggregateError when available, fall back to custom:
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
function createAggregateError(
|
|
337
|
-
errors: Error[],
|
|
338
|
-
message?: string
|
|
339
|
-
): Error {
|
|
340
|
-
if (typeof AggregateError !== 'undefined') {
|
|
341
|
-
return new AggregateError(errors, message);
|
|
342
|
-
} else {
|
|
343
|
-
return new CustomAggregateError(errors, message);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
---
|
|
349
|
-
|
|
350
|
-
## 4. Production-Grade Patterns
|
|
351
|
-
|
|
352
|
-
### 4.1 Error Aggregation with Retry Logic
|
|
353
|
-
|
|
354
|
-
```typescript
|
|
355
|
-
interface RetryOptions {
|
|
356
|
-
maxRetries: number;
|
|
357
|
-
backoffMs: number;
|
|
358
|
-
retryableErrors: Array<string | RegExp>;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
class RetryableAggregateError extends Error {
|
|
362
|
-
readonly errors: Array<{
|
|
363
|
-
error: Error;
|
|
364
|
-
attempt: number;
|
|
365
|
-
retried: boolean;
|
|
366
|
-
}>;
|
|
367
|
-
readonly stats: {
|
|
368
|
-
totalErrors: number;
|
|
369
|
-
retryableErrors: number;
|
|
370
|
-
nonRetryableErrors: number;
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
constructor(
|
|
374
|
-
errors: Array<{ error: Error; attempt: number; retried: boolean }>,
|
|
375
|
-
message?: string
|
|
376
|
-
) {
|
|
377
|
-
super(message || `${errors.length} error(s) occurred after retries`);
|
|
378
|
-
this.name = 'RetryableAggregateError';
|
|
379
|
-
this.errors = errors;
|
|
380
|
-
|
|
381
|
-
const retryableErrors = errors.filter(e => e.retried).length;
|
|
382
|
-
const nonRetryableErrors = errors.length - retryableErrors;
|
|
383
|
-
|
|
384
|
-
this.stats = {
|
|
385
|
-
totalErrors: errors.length,
|
|
386
|
-
retryableErrors,
|
|
387
|
-
nonRetryableErrors,
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
async function executeWithRetry<T>(
|
|
393
|
-
promises: Promise<T>[],
|
|
394
|
-
options: RetryOptions
|
|
395
|
-
): Promise<T[]> {
|
|
396
|
-
const results = await Promise.allSettled(promises);
|
|
397
|
-
|
|
398
|
-
// Separate successes and failures
|
|
399
|
-
const successes = results
|
|
400
|
-
.filter((r): r is PromiseFulfilledResult<T> => r.status === 'fulfilled')
|
|
401
|
-
.map(r => r.value);
|
|
402
|
-
|
|
403
|
-
const failures = results
|
|
404
|
-
.filter((r): r is PromiseRejectedResult => r.status === 'rejected')
|
|
405
|
-
.map(r => r.reason as Error);
|
|
406
|
-
|
|
407
|
-
// Check if failures are retryable
|
|
408
|
-
const retryableFailures = failures.filter(error => {
|
|
409
|
-
return options.retryableErrors.some(pattern => {
|
|
410
|
-
if (typeof pattern === 'string') {
|
|
411
|
-
return error.message.includes(pattern);
|
|
412
|
-
} else {
|
|
413
|
-
return pattern.test(error.message);
|
|
414
|
-
}
|
|
415
|
-
});
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
if (retryableFailures.length > 0 && options.maxRetries > 0) {
|
|
419
|
-
// Wait for backoff period
|
|
420
|
-
await new Promise(resolve => setTimeout(resolve, options.backoffMs));
|
|
421
|
-
|
|
422
|
-
// Retry only retryable errors (simplified - in practice, you'd need to track which promises to retry)
|
|
423
|
-
// This is a conceptual example
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
if (failures.length > 0) {
|
|
427
|
-
const errors = failures.map(error => ({
|
|
428
|
-
error,
|
|
429
|
-
attempt: 1,
|
|
430
|
-
retried: false,
|
|
431
|
-
}));
|
|
432
|
-
|
|
433
|
-
throw new RetryableAggregateError(errors);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
return successes;
|
|
437
|
-
}
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
### 4.2 Error Aggregation with Deduplication
|
|
441
|
-
|
|
442
|
-
```typescript
|
|
443
|
-
class DeduplicatedAggregateError extends Error {
|
|
444
|
-
readonly uniqueErrors: Error[];
|
|
445
|
-
readonly duplicateCount: number;
|
|
446
|
-
readonly errorFrequency: Record<string, number>;
|
|
447
|
-
|
|
448
|
-
constructor(errors: Error[], message?: string) {
|
|
449
|
-
const errorMap = new Map<string, Error>();
|
|
450
|
-
|
|
451
|
-
// Deduplicate by error message
|
|
452
|
-
for (const error of errors) {
|
|
453
|
-
const key = `${error.name}:${error.message}`;
|
|
454
|
-
if (!errorMap.has(key)) {
|
|
455
|
-
errorMap.set(key, error);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
const uniqueErrors = Array.from(errorMap.values());
|
|
460
|
-
const duplicateCount = errors.length - uniqueErrors.length;
|
|
461
|
-
|
|
462
|
-
const errorFrequency: Record<string, number> = {};
|
|
463
|
-
for (const error of errors) {
|
|
464
|
-
const key = `${error.name}:${error.message}`;
|
|
465
|
-
errorFrequency[key] = (errorFrequency[key] || 0) + 1;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
super(
|
|
469
|
-
message ||
|
|
470
|
-
`${errors.length} error(s) occurred (${uniqueErrors.length} unique, ${duplicateCount} duplicates)`
|
|
471
|
-
);
|
|
472
|
-
this.name = 'DeduplicatedAggregateError';
|
|
473
|
-
this.uniqueErrors = uniqueErrors;
|
|
474
|
-
this.duplicateCount = duplicateCount;
|
|
475
|
-
this.errorFrequency = errorFrequency;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
### 4.3 Error Aggregation with Categorization
|
|
481
|
-
|
|
482
|
-
```typescript
|
|
483
|
-
enum ErrorCategory {
|
|
484
|
-
NETWORK = 'network',
|
|
485
|
-
VALIDATION = 'validation',
|
|
486
|
-
PERMISSION = 'permission',
|
|
487
|
-
SYSTEM = 'system',
|
|
488
|
-
UNKNOWN = 'unknown',
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
interface CategorizedError {
|
|
492
|
-
error: Error;
|
|
493
|
-
category: ErrorCategory;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
class CategorizedAggregateError extends Error {
|
|
497
|
-
readonly errors: CategorizedError[];
|
|
498
|
-
readonly errorsByCategory: Record<ErrorCategory, number>;
|
|
499
|
-
|
|
500
|
-
constructor(errors: Error[], message?: string) {
|
|
501
|
-
const categorizedErrors: CategorizedError[] = errors.map(error => ({
|
|
502
|
-
error,
|
|
503
|
-
category: categorizeError(error),
|
|
504
|
-
}));
|
|
505
|
-
|
|
506
|
-
const errorsByCategory: Record<ErrorCategory, number> = {
|
|
507
|
-
[ErrorCategory.NETWORK]: 0,
|
|
508
|
-
[ErrorCategory.VALIDATION]: 0,
|
|
509
|
-
[ErrorCategory.PERMISSION]: 0,
|
|
510
|
-
[ErrorCategory.SYSTEM]: 0,
|
|
511
|
-
[ErrorCategory.UNKNOWN]: 0,
|
|
512
|
-
};
|
|
513
|
-
|
|
514
|
-
for (const { category } of categorizedErrors) {
|
|
515
|
-
errorsByCategory[category]++;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
super(message || `${errors.length} error(s) occurred`);
|
|
519
|
-
this.name = 'CategorizedAggregateError';
|
|
520
|
-
this.errors = categorizedErrors;
|
|
521
|
-
this.errorsByCategory = errorsByCategory;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
getErrorsByCategory(category: ErrorCategory): Error[] {
|
|
525
|
-
return this.errors
|
|
526
|
-
.filter(e => e.category === category)
|
|
527
|
-
.map(e => e.error);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
function categorizeError(error: Error): ErrorCategory {
|
|
532
|
-
const message = error.message.toLowerCase();
|
|
533
|
-
|
|
534
|
-
if (message.includes('network') || message.includes('fetch') || message.includes('enet')) {
|
|
535
|
-
return ErrorCategory.NETWORK;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
if (message.includes('validation') || message.includes('invalid') || message.includes('schema')) {
|
|
539
|
-
return ErrorCategory.VALIDATION;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
if (message.includes('permission') || message.includes('unauthorized') || message.includes('forbidden')) {
|
|
543
|
-
return ErrorCategory.PERMISSION;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
if (message.includes('system') || message.includes('eacces') || message.includes('enoent')) {
|
|
547
|
-
return ErrorCategory.SYSTEM;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
return ErrorCategory.UNKNOWN;
|
|
551
|
-
}
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
---
|
|
555
|
-
|
|
556
|
-
## 5. TypeScript Integration
|
|
557
|
-
|
|
558
|
-
### 5.1 Type-Safe AggregateError
|
|
559
|
-
|
|
560
|
-
```typescript
|
|
561
|
-
interface AggregateErrorConstructor {
|
|
562
|
-
new(errors: Iterable<unknown>, message?: string): AggregateError;
|
|
563
|
-
(errors: Iterable<unknown>, message?: string): AggregateError;
|
|
564
|
-
readonly prototype: AggregateError;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
interface AggregateError extends Error {
|
|
568
|
-
readonly errors: unknown[];
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
declare var AggregateError: AggregateErrorConstructor;
|
|
572
|
-
```
|
|
573
|
-
|
|
574
|
-
### 5.2 Typed AggregateError
|
|
575
|
-
|
|
576
|
-
```typescript
|
|
577
|
-
class TypedAggregateError<T extends Error = Error> extends Error {
|
|
578
|
-
readonly errors: T[];
|
|
579
|
-
|
|
580
|
-
constructor(errors: T[], message?: string) {
|
|
581
|
-
super(message || `${errors.length} error(s) occurred`);
|
|
582
|
-
this.name = 'TypedAggregateError';
|
|
583
|
-
this.errors = errors;
|
|
584
|
-
|
|
585
|
-
if (Error.captureStackTrace) {
|
|
586
|
-
Error.captureStackTrace(this, TypedAggregateError);
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
// Filter errors by type
|
|
591
|
-
filterErrors<E extends Error>(errorType: new (...args: unknown[]) => E): E[] {
|
|
592
|
-
return this.errors.filter((e): e is E => e instanceof errorType);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// Get errors by type guard
|
|
596
|
-
getErrorsOfType<E extends Error>(
|
|
597
|
-
typeGuard: (error: Error) => error is E
|
|
598
|
-
): E[] {
|
|
599
|
-
return this.errors.filter(typeGuard);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
```
|
|
603
|
-
|
|
604
|
-
### 5.3 Workflow-Specific AggregateError
|
|
605
|
-
|
|
606
|
-
```typescript
|
|
607
|
-
// Based on Groundswell's WorkflowError interface
|
|
608
|
-
interface WorkflowError {
|
|
609
|
-
message: string;
|
|
610
|
-
original: unknown;
|
|
611
|
-
workflowId: string;
|
|
612
|
-
stack?: string;
|
|
613
|
-
state: unknown; // SerializedWorkflowState
|
|
614
|
-
logs: unknown[]; // LogEntry[]
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
interface WorkflowAggregateError extends Error {
|
|
618
|
-
name: 'WorkflowAggregateError';
|
|
619
|
-
message: string;
|
|
620
|
-
errors: Array<{
|
|
621
|
-
workflowId: string;
|
|
622
|
-
workflowName: string;
|
|
623
|
-
error: WorkflowError;
|
|
624
|
-
}>;
|
|
625
|
-
taskName: string;
|
|
626
|
-
workflowId: string;
|
|
627
|
-
totalChildren: number;
|
|
628
|
-
failedChildren: number;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
function isWorkflowAggregateError(error: unknown): error is WorkflowAggregateError {
|
|
632
|
-
return (
|
|
633
|
-
error instanceof Error &&
|
|
634
|
-
(error as any).name === 'WorkflowAggregateError' &&
|
|
635
|
-
'errors' in error &&
|
|
636
|
-
'totalChildren' in error &&
|
|
637
|
-
'failedChildren' in error
|
|
638
|
-
);
|
|
639
|
-
}
|
|
640
|
-
```
|
|
641
|
-
|
|
642
|
-
---
|
|
643
|
-
|
|
644
|
-
## 6. Common Pitfalls
|
|
645
|
-
|
|
646
|
-
### 6.1 Losing Original Stack Traces
|
|
647
|
-
|
|
648
|
-
**Problem:** Not preserving original stack traces makes debugging difficult.
|
|
649
|
-
|
|
650
|
-
```typescript
|
|
651
|
-
// ❌ WRONG - Loses original stack traces
|
|
652
|
-
const aggregate = new AggregateError([
|
|
653
|
-
new Error('Error 1'),
|
|
654
|
-
new Error('Error 2'),
|
|
655
|
-
]);
|
|
656
|
-
|
|
657
|
-
// ✅ CORRECT - Preserves stack traces
|
|
658
|
-
const errors = [
|
|
659
|
-
new Error('Error 1'),
|
|
660
|
-
new Error('Error 2'),
|
|
661
|
-
].map(err => {
|
|
662
|
-
// Ensure stack trace is captured
|
|
663
|
-
if (!err.stack) {
|
|
664
|
-
Error.captureStackTrace(err);
|
|
665
|
-
}
|
|
666
|
-
return err;
|
|
667
|
-
});
|
|
668
|
-
|
|
669
|
-
const aggregate = new AggregateError(errors);
|
|
670
|
-
```
|
|
671
|
-
|
|
672
|
-
### 6.2 Not Handling Non-Error Values
|
|
673
|
-
|
|
674
|
-
**Problem:** AggregateError can contain non-Error values.
|
|
675
|
-
|
|
676
|
-
```typescript
|
|
677
|
-
// ❌ WRONG - Assumes all values are Errors
|
|
678
|
-
const results = await Promise.allSettled(promises);
|
|
679
|
-
const errors = results
|
|
680
|
-
.filter((r): r is PromiseRejectedResult => r.status === 'rejected')
|
|
681
|
-
.map(r => r.reason);
|
|
682
|
-
|
|
683
|
-
throw new AggregateError(errors); // May contain strings, numbers, etc.
|
|
684
|
-
|
|
685
|
-
// ✅ CORRECT - Normalizes to Errors
|
|
686
|
-
const normalizedErrors = errors.map(err => {
|
|
687
|
-
if (err instanceof Error) {
|
|
688
|
-
return err;
|
|
689
|
-
}
|
|
690
|
-
return new Error(String(err ?? 'Unknown error'));
|
|
691
|
-
});
|
|
692
|
-
|
|
693
|
-
throw new AggregateError(normalizedErrors);
|
|
694
|
-
```
|
|
695
|
-
|
|
696
|
-
### 6.3 Circular References in Errors
|
|
697
|
-
|
|
698
|
-
**Problem:** Circular references can cause issues when stringifying errors.
|
|
699
|
-
|
|
700
|
-
```typescript
|
|
701
|
-
// ❌ PROBLEMATIC - Circular references
|
|
702
|
-
const error1 = new Error('Error 1');
|
|
703
|
-
const error2 = new Error('Error 2');
|
|
704
|
-
(error1 as any).cause = error2;
|
|
705
|
-
(error2 as any).cause = error1; // Circular reference
|
|
706
|
-
|
|
707
|
-
try {
|
|
708
|
-
throw new AggregateError([error1, error2]);
|
|
709
|
-
} catch (aggregate) {
|
|
710
|
-
console.log(aggregate.toString()); // May fail due to circular reference
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
// ✅ CORRECT - Handle circular references
|
|
714
|
-
import { safeStringify } from './utils';
|
|
715
|
-
|
|
716
|
-
const error1 = new Error('Error 1');
|
|
717
|
-
const error2 = new Error('Error 2');
|
|
718
|
-
(error1 as any).cause = error2;
|
|
719
|
-
(error2 as any).cause = error1;
|
|
720
|
-
|
|
721
|
-
class SafeAggregateError extends Error {
|
|
722
|
-
readonly errors: Error[];
|
|
723
|
-
|
|
724
|
-
constructor(errors: Error[], message?: string) {
|
|
725
|
-
super(message || `${errors.length} error(s) occurred`);
|
|
726
|
-
this.name = 'SafeAggregateError';
|
|
727
|
-
this.errors = errors;
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
toString(): string {
|
|
731
|
-
return safeStringify({
|
|
732
|
-
name: this.name,
|
|
733
|
-
message: this.message,
|
|
734
|
-
errors: this.errors.map(e => ({
|
|
735
|
-
name: e.name,
|
|
736
|
-
message: e.message,
|
|
737
|
-
stack: e.stack,
|
|
738
|
-
})),
|
|
739
|
-
});
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
```
|
|
743
|
-
|
|
744
|
-
### 6.4 Memory Leaks with Large Error Arrays
|
|
745
|
-
|
|
746
|
-
**Problem:** Storing too many errors can cause memory issues.
|
|
747
|
-
|
|
748
|
-
```typescript
|
|
749
|
-
// ❌ PROBLEMATIC - Stores all errors
|
|
750
|
-
const results = await Promise.allSettled(largeArrayOfPromises);
|
|
751
|
-
const errors = results
|
|
752
|
-
.filter((r): r is PromiseRejectedResult => r.status === 'rejected')
|
|
753
|
-
.map(r => r.reason);
|
|
754
|
-
|
|
755
|
-
throw new AggregateError(errors); // May be thousands of errors
|
|
756
|
-
|
|
757
|
-
// ✅ CORRECT - Limit error count
|
|
758
|
-
class BoundedAggregateError extends Error {
|
|
759
|
-
readonly errors: Error[];
|
|
760
|
-
readonly truncated: boolean;
|
|
761
|
-
|
|
762
|
-
constructor(errors: Error[], message?: string, maxErrors = 100) {
|
|
763
|
-
const truncated = errors.length > maxErrors;
|
|
764
|
-
const boundedErrors = truncated ? errors.slice(0, maxErrors) : errors;
|
|
765
|
-
|
|
766
|
-
super(
|
|
767
|
-
message ||
|
|
768
|
-
`${errors.length} error(s) occurred${truncated ? ` (showing first ${maxErrors})` : ''}`
|
|
769
|
-
);
|
|
770
|
-
this.name = 'BoundedAggregateError';
|
|
771
|
-
this.errors = boundedErrors;
|
|
772
|
-
this.truncated = truncated;
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
```
|
|
776
|
-
|
|
777
|
-
---
|
|
778
|
-
|
|
779
|
-
## 7. Code Examples
|
|
780
|
-
|
|
781
|
-
### 7.1 Complete Example: Promise.allSettled with AggregateError
|
|
782
|
-
|
|
783
|
-
```typescript
|
|
784
|
-
async function executeAll<T>(
|
|
785
|
-
promises: Promise<T>[],
|
|
786
|
-
options?: {
|
|
787
|
-
errorMessage?: string;
|
|
788
|
-
maxErrors?: number;
|
|
789
|
-
}
|
|
790
|
-
): Promise<T[]> {
|
|
791
|
-
const results = await Promise.allSettled(promises);
|
|
792
|
-
|
|
793
|
-
const errors = results
|
|
794
|
-
.filter((r): r is PromiseRejectedResult => r.status === 'rejected')
|
|
795
|
-
.map(r => {
|
|
796
|
-
const reason = r.reason;
|
|
797
|
-
return reason instanceof Error ? reason : new Error(String(reason));
|
|
798
|
-
});
|
|
799
|
-
|
|
800
|
-
if (errors.length > 0) {
|
|
801
|
-
// Limit error count if specified
|
|
802
|
-
const boundedErrors = options?.maxErrors
|
|
803
|
-
? errors.slice(0, options.maxErrors)
|
|
804
|
-
: errors;
|
|
805
|
-
|
|
806
|
-
throw new AggregateError(
|
|
807
|
-
boundedErrors,
|
|
808
|
-
options?.errorMessage || `${errors.length} operation(s) failed`
|
|
809
|
-
);
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
return results
|
|
813
|
-
.filter((r): r is PromiseFulfilledResult<T> => r.status === 'fulfilled')
|
|
814
|
-
.map(r => r.value);
|
|
815
|
-
}
|
|
816
|
-
```
|
|
817
|
-
|
|
818
|
-
### 7.2 Complete Example: Workflow Error Aggregation
|
|
819
|
-
|
|
820
|
-
```typescript
|
|
821
|
-
interface ChildWorkflowResult {
|
|
822
|
-
workflowId: string;
|
|
823
|
-
workflowName: string;
|
|
824
|
-
status: 'fulfilled' | 'rejected';
|
|
825
|
-
value?: unknown;
|
|
826
|
-
error?: Error;
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
async function executeChildWorkflows(
|
|
830
|
-
workflows: Array<{ id: string; name: string; run: () => Promise<unknown> }>,
|
|
831
|
-
parentWorkflowId: string
|
|
832
|
-
): Promise<ChildWorkflowResult[]> {
|
|
833
|
-
const results = await Promise.allSettled(
|
|
834
|
-
workflows.map(w => w.run())
|
|
835
|
-
);
|
|
836
|
-
|
|
837
|
-
return workflows.map((workflow, index) => {
|
|
838
|
-
const result = results[index];
|
|
839
|
-
|
|
840
|
-
if (result.status === 'fulfilled') {
|
|
841
|
-
return {
|
|
842
|
-
workflowId: workflow.id,
|
|
843
|
-
workflowName: workflow.name,
|
|
844
|
-
status: 'fulfilled',
|
|
845
|
-
value: result.value,
|
|
846
|
-
};
|
|
847
|
-
} else {
|
|
848
|
-
const reason = result.reason;
|
|
849
|
-
const error = reason instanceof Error ? reason : new Error(String(reason));
|
|
850
|
-
return {
|
|
851
|
-
workflowId: workflow.id,
|
|
852
|
-
workflowName: workflow.name,
|
|
853
|
-
status: 'rejected',
|
|
854
|
-
error,
|
|
855
|
-
};
|
|
856
|
-
}
|
|
857
|
-
});
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
async function executeChildWorkflowsWithAggregation(
|
|
861
|
-
workflows: Array<{ id: string; name: string; run: () => Promise<unknown> }>,
|
|
862
|
-
parentWorkflowId: string,
|
|
863
|
-
taskName: string
|
|
864
|
-
): Promise<void> {
|
|
865
|
-
const results = await executeChildWorkflows(workflows, parentWorkflowId);
|
|
866
|
-
|
|
867
|
-
const failures = results.filter((r): r is ChildWorkflowResult & { error: Error } => r.status === 'rejected');
|
|
868
|
-
|
|
869
|
-
if (failures.length > 0) {
|
|
870
|
-
const error = new Error(
|
|
871
|
-
`${failures.length} child workflow(s) failed in task '${taskName}'`
|
|
872
|
-
) as WorkflowAggregateError;
|
|
873
|
-
|
|
874
|
-
error.name = 'WorkflowAggregateError';
|
|
875
|
-
error.errors = failures.map(f => ({
|
|
876
|
-
workflowId: f.workflowId,
|
|
877
|
-
workflowName: f.workflowName,
|
|
878
|
-
error: f.error as WorkflowError,
|
|
879
|
-
}));
|
|
880
|
-
error.taskName = taskName;
|
|
881
|
-
error.workflowId = parentWorkflowId;
|
|
882
|
-
error.totalChildren = results.length;
|
|
883
|
-
error.failedChildren = failures.length;
|
|
884
|
-
|
|
885
|
-
throw error;
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
```
|
|
889
|
-
|
|
890
|
-
### 7.3 Complete Example: Enriched AggregateError Factory
|
|
891
|
-
|
|
892
|
-
```typescript
|
|
893
|
-
interface ErrorEnrichment {
|
|
894
|
-
operationId?: string;
|
|
895
|
-
operationName?: string;
|
|
896
|
-
timestamp?: number;
|
|
897
|
-
metadata?: Record<string, unknown>;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
interface EnrichedError {
|
|
901
|
-
originalError: Error;
|
|
902
|
-
enrichment: ErrorEnrichment;
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
class EnrichedAggregateError extends Error {
|
|
906
|
-
readonly errors: EnrichedError[];
|
|
907
|
-
readonly context: {
|
|
908
|
-
parentOperation?: string;
|
|
909
|
-
timestamp: number;
|
|
910
|
-
};
|
|
911
|
-
readonly stats: {
|
|
912
|
-
totalErrors: number;
|
|
913
|
-
errorsByType: Record<string, number>;
|
|
914
|
-
errorsByOperation: Record<string, number>;
|
|
915
|
-
};
|
|
916
|
-
|
|
917
|
-
constructor(
|
|
918
|
-
errors: Array<{ error: Error; enrichment?: ErrorEnrichment }>,
|
|
919
|
-
message?: string,
|
|
920
|
-
context?: { parentOperation?: string }
|
|
921
|
-
) {
|
|
922
|
-
super(message || `${errors.length} error(s) occurred`);
|
|
923
|
-
this.name = 'EnrichedAggregateError';
|
|
924
|
-
|
|
925
|
-
this.errors = errors.map(e => ({
|
|
926
|
-
originalError: e.error,
|
|
927
|
-
enrichment: {
|
|
928
|
-
timestamp: Date.now(),
|
|
929
|
-
...e.enrichment,
|
|
930
|
-
},
|
|
931
|
-
}));
|
|
932
|
-
|
|
933
|
-
this.context = {
|
|
934
|
-
parentOperation: context?.parentOperation,
|
|
935
|
-
timestamp: Date.now(),
|
|
936
|
-
};
|
|
937
|
-
|
|
938
|
-
// Calculate statistics
|
|
939
|
-
const errorsByType: Record<string, number> = {};
|
|
940
|
-
const errorsByOperation: Record<string, number> = {};
|
|
941
|
-
|
|
942
|
-
for (const { originalError, enrichment } of this.errors) {
|
|
943
|
-
const type = originalError.constructor.name;
|
|
944
|
-
errorsByType[type] = (errorsByType[type] || 0) + 1;
|
|
945
|
-
|
|
946
|
-
if (enrichment.operationName) {
|
|
947
|
-
errorsByOperation[enrichment.operationName] =
|
|
948
|
-
(errorsByOperation[enrichment.operationName] || 0) + 1;
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
this.stats = {
|
|
953
|
-
totalErrors: this.errors.length,
|
|
954
|
-
errorsByType,
|
|
955
|
-
errorsByOperation,
|
|
956
|
-
};
|
|
957
|
-
|
|
958
|
-
if (Error.captureStackTrace) {
|
|
959
|
-
Error.captureStackTrace(this, EnrichedAggregateError);
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
// Pretty-print for logging
|
|
964
|
-
toString(): string {
|
|
965
|
-
let output = `${this.name}: ${this.message}\n`;
|
|
966
|
-
output += `Timestamp: ${new Date(this.context.timestamp).toISOString()}\n`;
|
|
967
|
-
output += `Total errors: ${this.stats.totalErrors}\n\n`;
|
|
968
|
-
|
|
969
|
-
for (const { originalError, enrichment } of this.errors) {
|
|
970
|
-
output += ` [${enrichment.timestamp ? new Date(enrichment.timestamp).toISOString() : 'N/A'}] `;
|
|
971
|
-
output += `${originalError.name}: ${originalError.message}`;
|
|
972
|
-
|
|
973
|
-
if (enrichment.operationName) {
|
|
974
|
-
output += ` (in ${enrichment.operationName})`;
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
if (enrichment.operationId) {
|
|
978
|
-
output += ` [ID: ${enrichment.operationId}]`;
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
output += '\n';
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
if (Object.keys(this.stats.errorsByType).length > 0) {
|
|
985
|
-
output += '\nError types:\n';
|
|
986
|
-
for (const [type, count] of Object.entries(this.stats.errorsByType)) {
|
|
987
|
-
output += ` - ${type}: ${count}\n`;
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
if (Object.keys(this.stats.errorsByOperation).length > 0) {
|
|
992
|
-
output += '\nErrors by operation:\n';
|
|
993
|
-
for (const [operation, count] of Object.entries(this.stats.errorsByOperation)) {
|
|
994
|
-
output += ` - ${operation}: ${count}\n`;
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
return output;
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
// Factory function
|
|
1003
|
-
function createEnrichedAggregateError(
|
|
1004
|
-
errors: Array<{ error: Error; enrichment?: ErrorEnrichment }>,
|
|
1005
|
-
message?: string,
|
|
1006
|
-
context?: { parentOperation?: string }
|
|
1007
|
-
): EnrichedAggregateError {
|
|
1008
|
-
return new EnrichedAggregateError(errors, message, context);
|
|
1009
|
-
}
|
|
1010
|
-
```
|
|
1011
|
-
|
|
1012
|
-
---
|
|
1013
|
-
|
|
1014
|
-
## References
|
|
1015
|
-
|
|
1016
|
-
### Official Documentation
|
|
1017
|
-
1. MDN: AggregateError - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError
|
|
1018
|
-
2. TC39 Proposal: Promise.allSettled - https://github.com/tc39/proposal-promise-allSettled
|
|
1019
|
-
3. ECMAScript Specification: AggregateError - https://tc39.es/ecma262/#sec-aggregate-error-constructor
|
|
1020
|
-
|
|
1021
|
-
### Community Resources
|
|
1022
|
-
4. StackOverflow: When to use AggregateError - https://stackoverflow.com/questions/63285967
|
|
1023
|
-
5. StackOverflow: AggregateError polyfill - https://stackoverflow.com/questions/63454000
|
|
1024
|
-
6. GitHub: aggregate-error package - https://github.com/sindresorhus/aggregate-error
|
|
1025
|
-
|
|
1026
|
-
### Groundswell-Specific
|
|
1027
|
-
7. Current Implementation: /home/dustin/projects/groundswell/src/types/error-strategy.ts
|
|
1028
|
-
8. WorkflowError Interface: /home/dustin/projects/groundswell/src/types/error.ts
|
|
1029
|
-
9. Task Decorator: /home/dustin/projects/groundswell/src/decorators/task.ts
|
|
1030
|
-
10. Existing Research: /home/dustin/projects/groundswell/plan/001_d3bb02af4886/docs/research/PROMISE_ALLSETTLED_RESEARCH.md
|
|
1031
|
-
|
|
1032
|
-
---
|
|
1033
|
-
|
|
1034
|
-
**Document Version:** 1.0
|
|
1035
|
-
**Last Updated:** 2026-01-12
|
|
1036
|
-
**Status:** Complete
|
|
1037
|
-
**Next Review:** After P1M2T2S2 Implementation
|