@bastani/atomic 0.8.26-alpha.1 → 0.8.26-alpha.11
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/CHANGELOG.md +79 -0
- package/README.md +5 -5
- package/dist/builtin/intercom/CHANGELOG.md +60 -0
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/mcp/CHANGELOG.md +60 -0
- package/dist/builtin/mcp/package.json +3 -3
- package/dist/builtin/subagents/CHANGELOG.md +61 -0
- package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
- package/dist/builtin/subagents/agents/codebase-locator.md +1 -1
- package/dist/builtin/subagents/agents/codebase-online-researcher.md +9 -9
- package/dist/builtin/subagents/agents/codebase-pattern-finder.md +1 -1
- package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
- package/dist/builtin/subagents/agents/codebase-research-locator.md +1 -1
- package/dist/builtin/subagents/agents/debugger.md +6 -6
- package/dist/builtin/subagents/package.json +4 -4
- package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +1 -1
- package/dist/builtin/subagents/skills/browser/EXAMPLES.md +151 -0
- package/dist/builtin/subagents/skills/browser/LICENSE.txt +21 -0
- package/dist/builtin/subagents/skills/browser/REFERENCE.md +451 -0
- package/dist/builtin/subagents/skills/browser/SKILL.md +170 -0
- package/dist/builtin/subagents/skills/subagent/SKILL.md +4 -4
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +55 -12
- package/dist/builtin/subagents/src/runs/foreground/execution.ts +71 -12
- package/dist/builtin/subagents/src/runs/shared/acceptance.ts +2 -1
- package/dist/builtin/subagents/src/runs/shared/final-drain.ts +34 -0
- package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +416 -7
- package/dist/builtin/subagents/src/runs/shared/worktree.ts +2 -2
- package/dist/builtin/web-access/CHANGELOG.md +60 -0
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +72 -0
- package/dist/builtin/workflows/README.md +10 -8
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +11 -8
- package/dist/builtin/workflows/builtin/goal.ts +137 -109
- package/dist/builtin/workflows/builtin/index.d.ts +2 -0
- package/dist/builtin/workflows/builtin/open-claude-design.ts +228 -151
- package/dist/builtin/workflows/builtin/ralph.d.ts +2 -0
- package/dist/builtin/workflows/builtin/ralph.ts +452 -279
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/skills/create-spec/SKILL.md +14 -0
- package/dist/builtin/workflows/skills/research-codebase/SKILL.md +29 -10
- package/dist/builtin/workflows/src/extension/index.ts +10 -2
- package/dist/builtin/workflows/src/extension/runtime.ts +35 -3
- package/dist/builtin/workflows/src/extension/wiring.ts +13 -1
- package/dist/builtin/workflows/src/runs/background/status.ts +52 -6
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +453 -21
- package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +77 -11
- package/dist/builtin/workflows/src/runs/shared/model-fallback.ts +402 -8
- package/dist/builtin/workflows/src/runs/shared/worktree.ts +2 -2
- package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +2 -2
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +182 -6
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +76 -6
- package/dist/builtin/workflows/src/shared/stage-prompt.ts +33 -2
- package/dist/builtin/workflows/src/shared/store-types.ts +31 -0
- package/dist/builtin/workflows/src/shared/store.ts +160 -18
- package/dist/builtin/workflows/src/shared/types.ts +3 -3
- package/dist/builtin/workflows/src/shared/workflow-failures.ts +758 -132
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +39 -3
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +74 -74
- package/dist/core/agent-session.d.ts +33 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +157 -182
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +11 -9
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +6 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +23 -10
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/context-compaction.d.ts +175 -0
- package/dist/core/compaction/context-compaction.d.ts.map +1 -0
- package/dist/core/compaction/context-compaction.js +1636 -0
- package/dist/core/compaction/context-compaction.js.map +1 -0
- package/dist/core/compaction/index.d.ts +1 -0
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +1 -0
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/extensions/types.d.ts +3 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +3 -0
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +14 -7
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/session-manager.d.ts +41 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +146 -7
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/ask-user-question/tool/format-answer.d.ts +5 -5
- package/dist/core/tools/ask-user-question/tool/format-answer.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/tool/format-answer.js +5 -5
- package/dist/core/tools/ask-user-question/tool/format-answer.js.map +1 -1
- package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts +16 -3
- package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/tool/response-envelope.js +21 -3
- package/dist/core/tools/ask-user-question/tool/response-envelope.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.js +17 -0
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
- package/dist/modes/interactive/components/context-compaction-summary-message.d.ts +17 -0
- package/dist/modes/interactive/components/context-compaction-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/context-compaction-summary-message.js +83 -0
- package/dist/modes/interactive/components/context-compaction-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +75 -10
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +13 -8
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +8 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +4 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +14 -3
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/git-env.d.ts +10 -0
- package/dist/utils/git-env.d.ts.map +1 -0
- package/dist/utils/git-env.js +33 -0
- package/dist/utils/git-env.js.map +1 -0
- package/docs/compaction.md +185 -50
- package/docs/custom-provider.md +11 -9
- package/docs/extensions.md +46 -42
- package/docs/index.md +13 -6
- package/docs/json.md +15 -12
- package/docs/packages.md +2 -0
- package/docs/providers.md +4 -1
- package/docs/quickstart.md +18 -11
- package/docs/rpc.md +38 -23
- package/docs/sdk.md +17 -8
- package/docs/session-format.md +26 -13
- package/docs/sessions.md +3 -3
- package/docs/settings.md +2 -2
- package/docs/skills.md +1 -15
- package/docs/termux.md +9 -10
- package/docs/themes.md +2 -2
- package/docs/tmux.md +3 -3
- package/docs/tui.md +19 -32
- package/docs/usage.md +2 -2
- package/docs/workflows.md +60 -16
- package/package.json +6 -12
- package/dist/builtin/subagents/skills/browser-use/SKILL.md +0 -234
- package/dist/builtin/subagents/skills/browser-use/references/cdp-python.md +0 -76
- package/dist/builtin/subagents/skills/browser-use/references/multi-session.md +0 -92
- package/node_modules/@earendil-works/pi-tui/README.md +0 -779
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.d.ts +0 -54
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.js +0 -632
- package/node_modules/@earendil-works/pi-tui/dist/autocomplete.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/box.d.ts +0 -22
- package/node_modules/@earendil-works/pi-tui/dist/components/box.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/box.js +0 -104
- package/node_modules/@earendil-works/pi-tui/dist/components/box.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/cancellable-loader.d.ts +0 -22
- package/node_modules/@earendil-works/pi-tui/dist/components/cancellable-loader.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/cancellable-loader.js +0 -35
- package/node_modules/@earendil-works/pi-tui/dist/components/cancellable-loader.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +0 -249
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +0 -1857
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/image.d.ts +0 -28
- package/node_modules/@earendil-works/pi-tui/dist/components/image.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/image.js +0 -89
- package/node_modules/@earendil-works/pi-tui/dist/components/image.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/input.d.ts +0 -37
- package/node_modules/@earendil-works/pi-tui/dist/components/input.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/input.js +0 -378
- package/node_modules/@earendil-works/pi-tui/dist/components/input.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/loader.d.ts +0 -31
- package/node_modules/@earendil-works/pi-tui/dist/components/loader.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/loader.js +0 -69
- package/node_modules/@earendil-works/pi-tui/dist/components/loader.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts +0 -96
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +0 -644
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/select-list.d.ts +0 -50
- package/node_modules/@earendil-works/pi-tui/dist/components/select-list.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/select-list.js +0 -159
- package/node_modules/@earendil-works/pi-tui/dist/components/select-list.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.d.ts +0 -50
- package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.js +0 -185
- package/node_modules/@earendil-works/pi-tui/dist/components/settings-list.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/spacer.d.ts +0 -12
- package/node_modules/@earendil-works/pi-tui/dist/components/spacer.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/spacer.js +0 -23
- package/node_modules/@earendil-works/pi-tui/dist/components/spacer.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/text.d.ts +0 -19
- package/node_modules/@earendil-works/pi-tui/dist/components/text.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/text.js +0 -89
- package/node_modules/@earendil-works/pi-tui/dist/components/text.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/truncated-text.d.ts +0 -13
- package/node_modules/@earendil-works/pi-tui/dist/components/truncated-text.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/truncated-text.js +0 -51
- package/node_modules/@earendil-works/pi-tui/dist/components/truncated-text.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/editor-component.d.ts +0 -39
- package/node_modules/@earendil-works/pi-tui/dist/editor-component.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/editor-component.js +0 -2
- package/node_modules/@earendil-works/pi-tui/dist/editor-component.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/fuzzy.d.ts +0 -16
- package/node_modules/@earendil-works/pi-tui/dist/fuzzy.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js +0 -110
- package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +0 -23
- package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/index.js +0 -32
- package/node_modules/@earendil-works/pi-tui/dist/index.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/keybindings.d.ts +0 -193
- package/node_modules/@earendil-works/pi-tui/dist/keybindings.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/keybindings.js +0 -174
- package/node_modules/@earendil-works/pi-tui/dist/keybindings.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/keys.d.ts +0 -184
- package/node_modules/@earendil-works/pi-tui/dist/keys.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/keys.js +0 -1173
- package/node_modules/@earendil-works/pi-tui/dist/keys.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/kill-ring.d.ts +0 -28
- package/node_modules/@earendil-works/pi-tui/dist/kill-ring.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/kill-ring.js +0 -44
- package/node_modules/@earendil-works/pi-tui/dist/kill-ring.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts +0 -3
- package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js +0 -53
- package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.d.ts +0 -50
- package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.js +0 -361
- package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts +0 -90
- package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js +0 -366
- package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +0 -113
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js +0 -472
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +0 -227
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +0 -1106
- package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/undo-stack.d.ts +0 -17
- package/node_modules/@earendil-works/pi-tui/dist/undo-stack.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/undo-stack.js +0 -25
- package/node_modules/@earendil-works/pi-tui/dist/undo-stack.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts +0 -84
- package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.js +0 -1029
- package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts +0 -25
- package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts.map +0 -1
- package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js +0 -96
- package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js.map +0 -1
- package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
- package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
- package/node_modules/@earendil-works/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
- package/node_modules/@earendil-works/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
- package/node_modules/@earendil-works/pi-tui/package.json +0 -47
- package/node_modules/get-east-asian-width/index.d.ts +0 -60
- package/node_modules/get-east-asian-width/index.js +0 -30
- package/node_modules/get-east-asian-width/license +0 -9
- package/node_modules/get-east-asian-width/lookup-data.js +0 -21
- package/node_modules/get-east-asian-width/lookup.js +0 -138
- package/node_modules/get-east-asian-width/package.json +0 -71
- package/node_modules/get-east-asian-width/readme.md +0 -65
- package/node_modules/get-east-asian-width/utilities.js +0 -24
- package/node_modules/marked/LICENSE.md +0 -44
- package/node_modules/marked/README.md +0 -106
- package/node_modules/marked/bin/main.js +0 -282
- package/node_modules/marked/bin/marked.js +0 -15
- package/node_modules/marked/lib/marked.cjs +0 -2211
- package/node_modules/marked/lib/marked.cjs.map +0 -7
- package/node_modules/marked/lib/marked.d.cts +0 -728
- package/node_modules/marked/lib/marked.d.ts +0 -728
- package/node_modules/marked/lib/marked.esm.js +0 -2189
- package/node_modules/marked/lib/marked.esm.js.map +0 -7
- package/node_modules/marked/lib/marked.umd.js +0 -2213
- package/node_modules/marked/lib/marked.umd.js.map +0 -7
- package/node_modules/marked/man/marked.1 +0 -111
- package/node_modules/marked/man/marked.1.md +0 -92
- package/node_modules/marked/marked.min.js +0 -69
- package/node_modules/marked/package.json +0 -111
|
@@ -7,11 +7,24 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Store } from "./store.js";
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
RunSnapshot,
|
|
12
|
+
StageSnapshot,
|
|
13
|
+
StageStatus,
|
|
14
|
+
WorkflowChildReplaySnapshot,
|
|
15
|
+
WorkflowFailureCode,
|
|
16
|
+
WorkflowFailureDisposition,
|
|
17
|
+
WorkflowFailureKind,
|
|
18
|
+
} from "./store-types.js";
|
|
11
19
|
import type { WorkflowInputValues, WorkflowOutputValues } from "./types.js";
|
|
12
20
|
import { workflowSerializableObjectSchema } from "./serializable.js";
|
|
13
21
|
import { Value } from "typebox/value";
|
|
14
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
isWorkflowFailureCode,
|
|
24
|
+
isWorkflowFailureDisposition,
|
|
25
|
+
isWorkflowFailureKind,
|
|
26
|
+
isWorkflowFailureRecoverability,
|
|
27
|
+
} from "./workflow-failures.js";
|
|
15
28
|
|
|
16
29
|
// ---------------------------------------------------------------------------
|
|
17
30
|
// Config option
|
|
@@ -49,6 +62,19 @@ export interface InFlightRun {
|
|
|
49
62
|
readonly stageIds: readonly string[];
|
|
50
63
|
}
|
|
51
64
|
|
|
65
|
+
interface RestoredRunBlockedMetadata {
|
|
66
|
+
readonly failedStageId: string;
|
|
67
|
+
readonly error: string;
|
|
68
|
+
readonly failureKind: WorkflowFailureKind;
|
|
69
|
+
readonly failureCode?: WorkflowFailureCode;
|
|
70
|
+
readonly failureRecoverability: "recoverable";
|
|
71
|
+
readonly failureDisposition?: WorkflowFailureDisposition;
|
|
72
|
+
readonly failureMessage?: string;
|
|
73
|
+
readonly retryAfterMs?: number;
|
|
74
|
+
readonly resumable: true;
|
|
75
|
+
readonly ts: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
52
78
|
// ---------------------------------------------------------------------------
|
|
53
79
|
// Scan logic
|
|
54
80
|
// ---------------------------------------------------------------------------
|
|
@@ -170,7 +196,37 @@ export function restoreOnSessionStart(
|
|
|
170
196
|
|
|
171
197
|
for (const run of inFlight) {
|
|
172
198
|
const runMeta = findRunStartMetadata(sessionEntries, run.runId);
|
|
173
|
-
const
|
|
199
|
+
const blockedMeta = findRunBlockedMetadata(sessionEntries, run.runId);
|
|
200
|
+
const stages = _buildStageSnapshots(sessionEntries, run.runId, blockedMeta);
|
|
201
|
+
|
|
202
|
+
if (blockedMeta !== undefined) {
|
|
203
|
+
const runSnapshot: RunSnapshot = {
|
|
204
|
+
id: run.runId,
|
|
205
|
+
name: run.name,
|
|
206
|
+
inputs: run.inputs,
|
|
207
|
+
status: "running",
|
|
208
|
+
stages,
|
|
209
|
+
startedAt: run.startTs,
|
|
210
|
+
...(runMeta.parentRunId !== undefined ? { parentRunId: runMeta.parentRunId } : {}),
|
|
211
|
+
...(runMeta.parentStageId !== undefined ? { parentStageId: runMeta.parentStageId } : {}),
|
|
212
|
+
...(runMeta.rootRunId !== undefined ? { rootRunId: runMeta.rootRunId } : {}),
|
|
213
|
+
...(runMeta.resumedFromRunId !== undefined ? { resumedFromRunId: runMeta.resumedFromRunId } : {}),
|
|
214
|
+
...(runMeta.resumeFromStageId !== undefined ? { resumeFromStageId: runMeta.resumeFromStageId } : {}),
|
|
215
|
+
};
|
|
216
|
+
store.recordRunStart(runSnapshot);
|
|
217
|
+
store.recordRunBlocked(run.runId, blockedMeta.error, {
|
|
218
|
+
failureKind: blockedMeta.failureKind,
|
|
219
|
+
...(blockedMeta.failureCode !== undefined ? { failureCode: blockedMeta.failureCode } : {}),
|
|
220
|
+
failureRecoverability: "recoverable",
|
|
221
|
+
...(blockedMeta.failureDisposition !== undefined ? { failureDisposition: blockedMeta.failureDisposition } : {}),
|
|
222
|
+
...(blockedMeta.failureMessage !== undefined ? { failureMessage: blockedMeta.failureMessage } : {}),
|
|
223
|
+
failedStageId: blockedMeta.failedStageId,
|
|
224
|
+
resumable: true,
|
|
225
|
+
...(blockedMeta.retryAfterMs !== undefined ? { retryAfterMs: blockedMeta.retryAfterMs } : {}),
|
|
226
|
+
blockedAt: blockedMeta.ts,
|
|
227
|
+
});
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
174
230
|
|
|
175
231
|
if (config.resumeInFlight === "auto") {
|
|
176
232
|
// Re-hydrate the run into the store as "running"
|
|
@@ -223,6 +279,7 @@ export function restoreOnSessionStart(
|
|
|
223
279
|
function _buildStageSnapshots(
|
|
224
280
|
entries: readonly SessionEntry[],
|
|
225
281
|
runId: string,
|
|
282
|
+
blockedMeta?: RestoredRunBlockedMetadata,
|
|
226
283
|
): StageSnapshot[] {
|
|
227
284
|
const stageMap = new Map<string, StageSnapshot>();
|
|
228
285
|
const endedStages = new Set<string>();
|
|
@@ -256,6 +313,10 @@ function _buildStageSnapshots(
|
|
|
256
313
|
const summary = entry.payload["summary"];
|
|
257
314
|
const error = entry.payload["error"];
|
|
258
315
|
const failureKind = entry.payload["failureKind"];
|
|
316
|
+
const failureCode = entry.payload["failureCode"];
|
|
317
|
+
const failureRecoverability = entry.payload["failureRecoverability"];
|
|
318
|
+
const failureDisposition = entry.payload["failureDisposition"];
|
|
319
|
+
const retryAfterMs = entry.payload["retryAfterMs"];
|
|
259
320
|
const failureMessage = entry.payload["failureMessage"];
|
|
260
321
|
const skippedReason = entry.payload["skippedReason"];
|
|
261
322
|
if (typeof stageId !== "string") continue;
|
|
@@ -267,6 +328,10 @@ function _buildStageSnapshots(
|
|
|
267
328
|
if (typeof summary === "string") snap.result = summary;
|
|
268
329
|
if (typeof error === "string") snap.error = error;
|
|
269
330
|
if (typeof failureKind === "string" && isWorkflowFailureKind(failureKind)) snap.failureKind = failureKind;
|
|
331
|
+
if (typeof failureCode === "string" && isWorkflowFailureCode(failureCode)) snap.failureCode = failureCode;
|
|
332
|
+
if (typeof failureRecoverability === "string" && isWorkflowFailureRecoverability(failureRecoverability)) snap.failureRecoverability = failureRecoverability;
|
|
333
|
+
if (typeof failureDisposition === "string" && isWorkflowFailureDisposition(failureDisposition)) snap.failureDisposition = failureDisposition;
|
|
334
|
+
if (typeof retryAfterMs === "number") snap.retryAfterMs = retryAfterMs;
|
|
270
335
|
if (typeof failureMessage === "string") snap.failureMessage = failureMessage;
|
|
271
336
|
if (typeof skippedReason === "string") snap.skippedReason = skippedReason;
|
|
272
337
|
Object.assign(snap, replayMetadata(entry.payload), workflowChildMetadata(entry.payload));
|
|
@@ -274,9 +339,12 @@ function _buildStageSnapshots(
|
|
|
274
339
|
}
|
|
275
340
|
}
|
|
276
341
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
342
|
+
if (blockedMeta !== undefined) {
|
|
343
|
+
restoreBlockedStageState(stageMap, endedStages, blockedMeta);
|
|
344
|
+
} else {
|
|
345
|
+
// Mark any stage that didn't get an end entry as crashed.
|
|
346
|
+
for (const [stageId, snap] of stageMap) {
|
|
347
|
+
if (endedStages.has(stageId)) continue;
|
|
280
348
|
snap.status = "failed";
|
|
281
349
|
snap.error = "Stage did not complete — process was interrupted.";
|
|
282
350
|
}
|
|
@@ -285,6 +353,57 @@ function _buildStageSnapshots(
|
|
|
285
353
|
return [...stageMap.values()];
|
|
286
354
|
}
|
|
287
355
|
|
|
356
|
+
function hasRestoredAncestor(
|
|
357
|
+
stageMap: ReadonlyMap<string, StageSnapshot>,
|
|
358
|
+
stage: StageSnapshot,
|
|
359
|
+
ancestorId: string,
|
|
360
|
+
): boolean {
|
|
361
|
+
const queue = [...stage.parentIds];
|
|
362
|
+
const seen = new Set<string>();
|
|
363
|
+
|
|
364
|
+
while (queue.length > 0) {
|
|
365
|
+
const next = queue.shift();
|
|
366
|
+
if (next === undefined || seen.has(next)) continue;
|
|
367
|
+
if (next === ancestorId) return true;
|
|
368
|
+
seen.add(next);
|
|
369
|
+
queue.push(...(stageMap.get(next)?.parentIds ?? []));
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function markRestoredBlockedFailureStage(
|
|
376
|
+
snap: StageSnapshot,
|
|
377
|
+
blockedMeta: RestoredRunBlockedMetadata,
|
|
378
|
+
): void {
|
|
379
|
+
snap.status = "failed";
|
|
380
|
+
snap.error = blockedMeta.error;
|
|
381
|
+
snap.failureKind = blockedMeta.failureKind;
|
|
382
|
+
snap.failureCode = blockedMeta.failureCode;
|
|
383
|
+
snap.failureRecoverability = blockedMeta.failureRecoverability;
|
|
384
|
+
snap.failureDisposition = blockedMeta.failureDisposition;
|
|
385
|
+
snap.failureMessage = blockedMeta.failureMessage;
|
|
386
|
+
snap.retryAfterMs = blockedMeta.retryAfterMs;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function restoreBlockedStageState(
|
|
390
|
+
stageMap: Map<string, StageSnapshot>,
|
|
391
|
+
endedStages: ReadonlySet<string>,
|
|
392
|
+
blockedMeta: RestoredRunBlockedMetadata,
|
|
393
|
+
): void {
|
|
394
|
+
for (const [stageId, snap] of stageMap) {
|
|
395
|
+
if (endedStages.has(stageId)) continue;
|
|
396
|
+
if (stageId === blockedMeta.failedStageId) {
|
|
397
|
+
markRestoredBlockedFailureStage(snap, blockedMeta);
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
if (hasRestoredAncestor(stageMap, snap, blockedMeta.failedStageId)) {
|
|
401
|
+
snap.status = "blocked";
|
|
402
|
+
snap.blockedByStageId = blockedMeta.failedStageId;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
288
407
|
function replayMetadata(payload: Record<string, unknown>): Pick<StageSnapshot, "replayKey" | "replayedFromStageId" | "replayed"> {
|
|
289
408
|
const replayKey = payload["replayKey"];
|
|
290
409
|
const replayedFromStageId = payload["replayedFromStageId"];
|
|
@@ -361,12 +480,61 @@ function restoreStageStatus(status: unknown): StageStatus {
|
|
|
361
480
|
case "completed":
|
|
362
481
|
case "failed":
|
|
363
482
|
case "skipped":
|
|
483
|
+
case "blocked":
|
|
364
484
|
return status;
|
|
365
485
|
default:
|
|
366
486
|
return "failed";
|
|
367
487
|
}
|
|
368
488
|
}
|
|
369
489
|
|
|
490
|
+
function numericRetryAfterMs(value: unknown): number | undefined {
|
|
491
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function findRunBlockedMetadata(
|
|
495
|
+
entries: readonly SessionEntry[],
|
|
496
|
+
runId: string,
|
|
497
|
+
): RestoredRunBlockedMetadata | undefined {
|
|
498
|
+
let latest: RestoredRunBlockedMetadata | undefined;
|
|
499
|
+
for (const entry of entries) {
|
|
500
|
+
if (entry.type !== "workflow.run.blocked" || entry.payload["runId"] !== runId) continue;
|
|
501
|
+
const failedStageId = entry.payload["failedStageId"];
|
|
502
|
+
const error = entry.payload["error"];
|
|
503
|
+
const failureKind = entry.payload["failureKind"];
|
|
504
|
+
const failureCode = entry.payload["failureCode"];
|
|
505
|
+
const failureRecoverability = entry.payload["failureRecoverability"];
|
|
506
|
+
const failureDisposition = entry.payload["failureDisposition"];
|
|
507
|
+
const failureMessage = entry.payload["failureMessage"];
|
|
508
|
+
const retryAfterMs = numericRetryAfterMs(entry.payload["retryAfterMs"]);
|
|
509
|
+
const resumable = entry.payload["resumable"];
|
|
510
|
+
const ts = entry.payload["ts"];
|
|
511
|
+
if (
|
|
512
|
+
typeof failedStageId !== "string" ||
|
|
513
|
+
typeof error !== "string" ||
|
|
514
|
+
typeof failureKind !== "string" ||
|
|
515
|
+
!isWorkflowFailureKind(failureKind) ||
|
|
516
|
+
failureRecoverability !== "recoverable" ||
|
|
517
|
+
resumable !== true ||
|
|
518
|
+
typeof ts !== "number"
|
|
519
|
+
) {
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
latest = {
|
|
523
|
+
failedStageId,
|
|
524
|
+
error,
|
|
525
|
+
failureKind,
|
|
526
|
+
...(typeof failureCode === "string" && isWorkflowFailureCode(failureCode) ? { failureCode } : {}),
|
|
527
|
+
failureRecoverability: "recoverable",
|
|
528
|
+
...(typeof failureDisposition === "string" && isWorkflowFailureDisposition(failureDisposition) ? { failureDisposition } : {}),
|
|
529
|
+
...(typeof failureMessage === "string" ? { failureMessage } : {}),
|
|
530
|
+
...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
|
|
531
|
+
resumable: true,
|
|
532
|
+
ts,
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
return latest;
|
|
536
|
+
}
|
|
537
|
+
|
|
370
538
|
function restoreTerminalRuns(entries: readonly SessionEntry[], store: Store): void {
|
|
371
539
|
const started = new Map<string, { readonly name: string; readonly inputs: Readonly<WorkflowInputValues>; readonly startTs: number }>();
|
|
372
540
|
const ended = new Map<string, Record<string, unknown>>();
|
|
@@ -416,6 +584,10 @@ function restoreTerminalRuns(entries: readonly SessionEntry[], store: Store): vo
|
|
|
416
584
|
|
|
417
585
|
const error = end["error"];
|
|
418
586
|
const failureKind = end["failureKind"];
|
|
587
|
+
const failureCode = end["failureCode"];
|
|
588
|
+
const failureRecoverability = end["failureRecoverability"];
|
|
589
|
+
const failureDisposition = end["failureDisposition"];
|
|
590
|
+
const retryAfterMs = numericRetryAfterMs(end["retryAfterMs"]);
|
|
419
591
|
const failureMessage = end["failureMessage"];
|
|
420
592
|
const failedStageId = end["failedStageId"];
|
|
421
593
|
const resumable = end["resumable"];
|
|
@@ -426,6 +598,10 @@ function restoreTerminalRuns(entries: readonly SessionEntry[], store: Store): vo
|
|
|
426
598
|
typeof error === "string" ? error : undefined,
|
|
427
599
|
{
|
|
428
600
|
...(typeof failureKind === "string" && isWorkflowFailureKind(failureKind) ? { failureKind } : {}),
|
|
601
|
+
...(typeof failureCode === "string" && isWorkflowFailureCode(failureCode) ? { failureCode } : {}),
|
|
602
|
+
...(typeof failureRecoverability === "string" && isWorkflowFailureRecoverability(failureRecoverability) ? { failureRecoverability } : {}),
|
|
603
|
+
...(typeof failureDisposition === "string" && isWorkflowFailureDisposition(failureDisposition) ? { failureDisposition } : {}),
|
|
604
|
+
...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
|
|
429
605
|
...(typeof failureMessage === "string" ? { failureMessage } : {}),
|
|
430
606
|
...(typeof failedStageId === "string" ? { failedStageId } : {}),
|
|
431
607
|
...(typeof resumable === "boolean" ? { resumable } : {}),
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { WorkflowInputValues, WorkflowOutputValues } from "./types.js";
|
|
10
|
+
import type {
|
|
11
|
+
WorkflowFailureCode,
|
|
12
|
+
WorkflowFailureDisposition,
|
|
13
|
+
WorkflowFailureKind,
|
|
14
|
+
} from "./store-types.js";
|
|
10
15
|
|
|
11
16
|
// ---------------------------------------------------------------------------
|
|
12
17
|
// Structural API type (subset of ExtensionAPI needed here)
|
|
@@ -76,7 +81,11 @@ export interface StageEndPayload {
|
|
|
76
81
|
readonly summary?: string;
|
|
77
82
|
readonly error?: string;
|
|
78
83
|
readonly failureKind?: string;
|
|
84
|
+
readonly failureCode?: string;
|
|
85
|
+
readonly failureRecoverability?: string;
|
|
86
|
+
readonly failureDisposition?: string;
|
|
79
87
|
readonly failureMessage?: string;
|
|
88
|
+
readonly retryAfterMs?: number;
|
|
80
89
|
readonly skippedReason?: string;
|
|
81
90
|
readonly replayKey?: string;
|
|
82
91
|
readonly replayedFromStageId?: string;
|
|
@@ -90,9 +99,27 @@ export interface RunEndPayload {
|
|
|
90
99
|
readonly result?: WorkflowOutputValues;
|
|
91
100
|
readonly error?: string;
|
|
92
101
|
readonly failureKind?: string;
|
|
102
|
+
readonly failureCode?: string;
|
|
103
|
+
readonly failureRecoverability?: string;
|
|
104
|
+
readonly failureDisposition?: string;
|
|
93
105
|
readonly failureMessage?: string;
|
|
94
106
|
readonly failedStageId?: string;
|
|
95
107
|
readonly resumable?: boolean;
|
|
108
|
+
readonly retryAfterMs?: number;
|
|
109
|
+
readonly ts: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface RunBlockedPayload {
|
|
113
|
+
readonly runId: string;
|
|
114
|
+
readonly failedStageId: string;
|
|
115
|
+
readonly error: string;
|
|
116
|
+
readonly failureKind: WorkflowFailureKind;
|
|
117
|
+
readonly failureCode?: WorkflowFailureCode;
|
|
118
|
+
readonly failureMessage?: string;
|
|
119
|
+
readonly failureRecoverability: "recoverable";
|
|
120
|
+
readonly failureDisposition?: WorkflowFailureDisposition;
|
|
121
|
+
readonly retryAfterMs?: number;
|
|
122
|
+
readonly resumable: true;
|
|
96
123
|
readonly ts: number;
|
|
97
124
|
}
|
|
98
125
|
|
|
@@ -165,7 +192,11 @@ export function appendStageEnd(
|
|
|
165
192
|
...(payload.summary !== undefined ? { summary: payload.summary } : {}),
|
|
166
193
|
...(payload.error !== undefined ? { error: payload.error } : {}),
|
|
167
194
|
...(payload.failureKind !== undefined ? { failureKind: payload.failureKind } : {}),
|
|
195
|
+
...(payload.failureCode !== undefined ? { failureCode: payload.failureCode } : {}),
|
|
196
|
+
...(payload.failureRecoverability !== undefined ? { failureRecoverability: payload.failureRecoverability } : {}),
|
|
197
|
+
...(payload.failureDisposition !== undefined ? { failureDisposition: payload.failureDisposition } : {}),
|
|
168
198
|
...(payload.failureMessage !== undefined ? { failureMessage: payload.failureMessage } : {}),
|
|
199
|
+
...(payload.retryAfterMs !== undefined ? { retryAfterMs: payload.retryAfterMs } : {}),
|
|
169
200
|
...(payload.skippedReason !== undefined ? { skippedReason: payload.skippedReason } : {}),
|
|
170
201
|
...(payload.replayKey !== undefined ? { replayKey: payload.replayKey } : {}),
|
|
171
202
|
...(payload.replayedFromStageId !== undefined ? { replayedFromStageId: payload.replayedFromStageId } : {}),
|
|
@@ -180,18 +211,57 @@ export function appendStageEnd(
|
|
|
180
211
|
}
|
|
181
212
|
}
|
|
182
213
|
|
|
214
|
+
function sanitizeTerminalRunEndPayload(payload: RunEndPayload): RunEndPayload {
|
|
215
|
+
if (payload.status === "killed") {
|
|
216
|
+
return {
|
|
217
|
+
...payload,
|
|
218
|
+
failureRecoverability: "non_recoverable",
|
|
219
|
+
failureDisposition: "terminal_killed",
|
|
220
|
+
resumable: false,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (payload.failureDisposition !== "active_blocked") return payload;
|
|
225
|
+
const sanitized = { ...payload };
|
|
226
|
+
delete (sanitized as { failureDisposition?: string }).failureDisposition;
|
|
227
|
+
return sanitized;
|
|
228
|
+
}
|
|
229
|
+
|
|
183
230
|
/** Appends a `workflow.run.end` entry. */
|
|
184
231
|
export function appendRunEnd(api: PersistenceAPI, payload: RunEndPayload): void {
|
|
185
232
|
if (typeof api.appendEntry !== "function") return;
|
|
233
|
+
const terminalPayload = sanitizeTerminalRunEndPayload(payload);
|
|
186
234
|
api.appendEntry("workflow.run.end", {
|
|
235
|
+
runId: terminalPayload.runId,
|
|
236
|
+
status: terminalPayload.status,
|
|
237
|
+
...(terminalPayload.result !== undefined ? { result: terminalPayload.result } : {}),
|
|
238
|
+
...(terminalPayload.error !== undefined ? { error: terminalPayload.error } : {}),
|
|
239
|
+
...(terminalPayload.failureKind !== undefined ? { failureKind: terminalPayload.failureKind } : {}),
|
|
240
|
+
...(terminalPayload.failureCode !== undefined ? { failureCode: terminalPayload.failureCode } : {}),
|
|
241
|
+
...(terminalPayload.failureRecoverability !== undefined ? { failureRecoverability: terminalPayload.failureRecoverability } : {}),
|
|
242
|
+
...(terminalPayload.failureDisposition !== undefined ? { failureDisposition: terminalPayload.failureDisposition } : {}),
|
|
243
|
+
...(terminalPayload.failureMessage !== undefined ? { failureMessage: terminalPayload.failureMessage } : {}),
|
|
244
|
+
...(terminalPayload.failedStageId !== undefined ? { failedStageId: terminalPayload.failedStageId } : {}),
|
|
245
|
+
...(terminalPayload.resumable !== undefined ? { resumable: terminalPayload.resumable } : {}),
|
|
246
|
+
...(terminalPayload.retryAfterMs !== undefined ? { retryAfterMs: terminalPayload.retryAfterMs } : {}),
|
|
247
|
+
ts: terminalPayload.ts,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Appends a `workflow.run.blocked` entry for active recoverable failures. */
|
|
252
|
+
export function appendRunBlocked(api: PersistenceAPI, payload: RunBlockedPayload): void {
|
|
253
|
+
if (typeof api.appendEntry !== "function") return;
|
|
254
|
+
api.appendEntry("workflow.run.blocked", {
|
|
187
255
|
runId: payload.runId,
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
...(payload.
|
|
256
|
+
failedStageId: payload.failedStageId,
|
|
257
|
+
error: payload.error,
|
|
258
|
+
failureKind: payload.failureKind,
|
|
259
|
+
...(payload.failureCode !== undefined ? { failureCode: payload.failureCode } : {}),
|
|
192
260
|
...(payload.failureMessage !== undefined ? { failureMessage: payload.failureMessage } : {}),
|
|
193
|
-
|
|
194
|
-
...(payload.
|
|
261
|
+
failureRecoverability: payload.failureRecoverability,
|
|
262
|
+
...(payload.failureDisposition !== undefined ? { failureDisposition: payload.failureDisposition } : {}),
|
|
263
|
+
...(payload.retryAfterMs !== undefined ? { retryAfterMs: payload.retryAfterMs } : {}),
|
|
264
|
+
resumable: payload.resumable,
|
|
195
265
|
ts: payload.ts,
|
|
196
266
|
});
|
|
197
267
|
}
|
|
@@ -239,13 +239,41 @@ export function parseAskUserQuestionArgs(
|
|
|
239
239
|
return questions.length > 0 ? questions : undefined;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
/**
|
|
243
|
+
* Sentinel label for the chat escape hatch. Matches the `ROW_INTENT_META.chat.label`
|
|
244
|
+
* in the coding-agent package. Duplicated here as a literal to avoid a cross-package
|
|
245
|
+
* import; the reserved-label guard in validate-questionnaire already prevents an
|
|
246
|
+
* authored option from using this label.
|
|
247
|
+
*/
|
|
248
|
+
const CHAT_ABOUT_THIS_LABEL = "Chat about this";
|
|
249
|
+
const CHAT_ABOUT_THIS_NORMALIZED = normalizeLabel(CHAT_ABOUT_THIS_LABEL);
|
|
250
|
+
|
|
251
|
+
function isChatSentinel(value: string): boolean {
|
|
252
|
+
return normalizeLabel(value) === CHAT_ABOUT_THIS_NORMALIZED;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function answerChat(question: StageInputQuestion): BuiltAnswer {
|
|
256
|
+
return {
|
|
257
|
+
questionIndex: 0,
|
|
258
|
+
question: question.question,
|
|
259
|
+
kind: "chat",
|
|
260
|
+
answer: CHAT_ABOUT_THIS_LABEL,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
242
264
|
/**
|
|
243
265
|
* Resolve a desired answer string against a single-select question's options.
|
|
244
|
-
*
|
|
245
|
-
*
|
|
266
|
+
* Checks the chat sentinel first (case/whitespace insensitive), then matches a
|
|
267
|
+
* case-insensitive option label, then a 1-based option index, then falls back to
|
|
268
|
+
* a typed ("custom") answer.
|
|
246
269
|
*/
|
|
247
270
|
function answerSingle(question: StageInputQuestion, desired: string): BuiltAnswer {
|
|
248
271
|
const normalized = normalizeLabel(desired);
|
|
272
|
+
// Chat sentinel takes priority over authored options — the label is reserved so
|
|
273
|
+
// no option can legitimately match it.
|
|
274
|
+
if (isChatSentinel(desired)) {
|
|
275
|
+
return answerChat(question);
|
|
276
|
+
}
|
|
249
277
|
const byLabel = question.options.find((option) => normalizeLabel(option.label) === normalized);
|
|
250
278
|
if (byLabel) {
|
|
251
279
|
return { questionIndex: 0, question: question.question, kind: "option", answer: byLabel.label };
|
|
@@ -295,6 +323,9 @@ function buildResult(
|
|
|
295
323
|
answer.optionLabels !== undefined
|
|
296
324
|
? answer.optionLabels
|
|
297
325
|
: (answer.text ?? "").split(",").map((part) => part.trim()).filter((part) => part.length > 0);
|
|
326
|
+
if (candidates.some(isChatSentinel)) {
|
|
327
|
+
return { answers: [answerChat(question)], cancelled: false } satisfies BuiltResult;
|
|
328
|
+
}
|
|
298
329
|
return { answers: [answerMulti(question, candidates)], cancelled: false } satisfies BuiltResult;
|
|
299
330
|
}
|
|
300
331
|
|
|
@@ -17,6 +17,19 @@ export type StageStatus =
|
|
|
17
17
|
| "skipped";
|
|
18
18
|
|
|
19
19
|
export type WorkflowFailureKind = "auth" | "rate_limit" | "provider" | "cancelled" | "unknown";
|
|
20
|
+
export type WorkflowFailureRecoverability = "recoverable" | "non_recoverable" | "unknown";
|
|
21
|
+
export type WorkflowFailureDisposition = "active_blocked" | "terminal_killed" | "terminal_failed";
|
|
22
|
+
export type WorkflowFailureCode =
|
|
23
|
+
| "login_required"
|
|
24
|
+
| "missing_api_key"
|
|
25
|
+
| "invalid_api_key"
|
|
26
|
+
| "forbidden_config"
|
|
27
|
+
| "unknown_model"
|
|
28
|
+
| "rate_limited"
|
|
29
|
+
| "quota_limited"
|
|
30
|
+
| "provider_unavailable"
|
|
31
|
+
| "cancelled"
|
|
32
|
+
| "unknown";
|
|
20
33
|
|
|
21
34
|
/**
|
|
22
35
|
* Human-in-the-loop prompt kind. Mirrors the four `WorkflowUIContext` methods.
|
|
@@ -127,6 +140,14 @@ export interface StageSnapshot {
|
|
|
127
140
|
error?: string;
|
|
128
141
|
/** Structured workflow failure category for failed stages. */
|
|
129
142
|
failureKind?: WorkflowFailureKind;
|
|
143
|
+
/** Specific additive workflow failure code within `failureKind`. */
|
|
144
|
+
failureCode?: WorkflowFailureCode;
|
|
145
|
+
/** Whether retry/resume can recover this failed stage without a workflow rerun. */
|
|
146
|
+
failureRecoverability?: WorkflowFailureRecoverability;
|
|
147
|
+
/** Executor lifecycle disposition chosen for the failed stage. */
|
|
148
|
+
failureDisposition?: WorkflowFailureDisposition;
|
|
149
|
+
/** Optional provider retry hint in milliseconds. Informational; blocked stages resume only via explicit user action. */
|
|
150
|
+
retryAfterMs?: number;
|
|
130
151
|
/** Original unsanitized error text when different from `error`. */
|
|
131
152
|
failureMessage?: string;
|
|
132
153
|
/** Reason for stages skipped by fail-fast/cascade handling. */
|
|
@@ -218,6 +239,16 @@ export interface RunSnapshot {
|
|
|
218
239
|
error?: string;
|
|
219
240
|
/** Structured workflow failure category for failed runs. */
|
|
220
241
|
failureKind?: WorkflowFailureKind;
|
|
242
|
+
/** Specific additive workflow failure code within `failureKind`. */
|
|
243
|
+
failureCode?: WorkflowFailureCode;
|
|
244
|
+
/** Whether retry/resume can recover this run without a workflow rerun. */
|
|
245
|
+
failureRecoverability?: WorkflowFailureRecoverability;
|
|
246
|
+
/** Executor lifecycle disposition chosen for this failure. */
|
|
247
|
+
failureDisposition?: WorkflowFailureDisposition;
|
|
248
|
+
/** Optional provider retry hint in milliseconds. Informational; blocked runs resume only via explicit user action. */
|
|
249
|
+
retryAfterMs?: number;
|
|
250
|
+
/** Timestamp when an active run was blocked by a recoverable workflow failure. */
|
|
251
|
+
blockedAt?: number;
|
|
221
252
|
/** Original unsanitized error text when different from `error`. */
|
|
222
253
|
failureMessage?: string;
|
|
223
254
|
failedStageId?: string;
|