@bastani/atomic 0.9.8 → 0.9.9-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/builtin/cursor/CHANGELOG.md +6 -0
- package/dist/builtin/cursor/package.json +2 -2
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +6 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +6 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +2 -0
- package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +7 -1
- package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +2 -0
- package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +8 -2
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +2 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +2 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +2 -0
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +6 -0
- package/dist/builtin/subagents/src/shared/types-config.ts +4 -0
- package/dist/builtin/subagents/src/shared/types-depth.ts +29 -2
- package/dist/builtin/web-access/CHANGELOG.md +6 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +22 -0
- package/dist/builtin/workflows/README.md +17 -8
- package/dist/builtin/workflows/builtin/goal-prompts.ts +8 -2
- package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +26 -9
- package/dist/builtin/workflows/builtin/ralph-forked-prompts.ts +1 -1
- package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +8 -3
- package/dist/builtin/workflows/builtin/ralph-runner.ts +2 -0
- package/dist/builtin/workflows/builtin/shared-prompts.ts +24 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/durable/backend.ts +53 -15
- package/dist/builtin/workflows/src/durable/completed-catalog.ts +245 -0
- package/dist/builtin/workflows/src/durable/completed-inspection.ts +213 -0
- package/dist/builtin/workflows/src/durable/dbos-backend.ts +120 -170
- package/dist/builtin/workflows/src/durable/dbos-envelope.ts +84 -8
- package/dist/builtin/workflows/src/durable/dbos-metadata.ts +98 -0
- package/dist/builtin/workflows/src/durable/dbos-tombstone.ts +27 -0
- package/dist/builtin/workflows/src/durable/factory.ts +1 -1
- package/dist/builtin/workflows/src/durable/file-backend.ts +247 -241
- package/dist/builtin/workflows/src/durable/file-lock.ts +153 -0
- package/dist/builtin/workflows/src/durable/file-state.ts +104 -0
- package/dist/builtin/workflows/src/durable/format-version.ts +12 -0
- package/dist/builtin/workflows/src/durable/index.ts +12 -0
- package/dist/builtin/workflows/src/durable/resume-catalog.ts +16 -27
- package/dist/builtin/workflows/src/durable/resume-eligibility.ts +20 -0
- package/dist/builtin/workflows/src/durable/resume-runtime.ts +29 -29
- package/dist/builtin/workflows/src/durable/scoped-backend.ts +20 -3
- package/dist/builtin/workflows/src/durable/stage-primitive.ts +29 -8
- package/dist/builtin/workflows/src/durable/types.ts +3 -0
- package/dist/builtin/workflows/src/engine/primitives/task.ts +1 -0
- package/dist/builtin/workflows/src/engine/run.ts +14 -14
- package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +39 -9
- package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +10 -0
- package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +133 -0
- package/dist/builtin/workflows/src/extension/runtime.ts +15 -40
- package/dist/builtin/workflows/src/extension/wiring.ts +9 -6
- package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +226 -0
- package/dist/builtin/workflows/src/extension/workflow-prompts.ts +1 -0
- package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +66 -112
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +5 -5
- package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +16 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +50 -43
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-output.ts +91 -0
- package/dist/builtin/workflows/src/runs/foreground/executor-direct.ts +95 -46
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +3 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-task-prompts.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +3 -0
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-options.ts +36 -7
- package/dist/builtin/workflows/src/runs/shared/worktree-cache-lifecycle.ts +25 -0
- package/dist/builtin/workflows/src/runs/shared/worktree-cwd.ts +103 -0
- package/dist/builtin/workflows/src/runs/shared/worktree-generation.ts +57 -0
- package/dist/builtin/workflows/src/runs/shared/worktree-git.ts +134 -8
- package/dist/builtin/workflows/src/runs/shared/worktree.ts +2 -0
- package/dist/builtin/workflows/src/shared/resumable-workflow-notices.ts +43 -0
- package/dist/builtin/workflows/src/shared/timing.ts +4 -0
- package/dist/builtin/workflows/src/shared/types.ts +5 -3
- package/dist/builtin/workflows/src/tui/graph-view-constants.ts +1 -0
- package/dist/builtin/workflows/src/tui/graph-view-input.ts +24 -14
- package/dist/builtin/workflows/src/tui/workflow-resume-selector.ts +43 -13
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +5 -7
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-compaction.d.ts +6 -34
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +95 -233
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-message-queue.d.ts +0 -4
- package/dist/core/agent-session-message-queue.d.ts.map +1 -1
- package/dist/core/agent-session-message-queue.js +1 -5
- package/dist/core/agent-session-message-queue.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +5 -6
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +2 -12
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.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 +1 -2
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction-boundary.d.ts +9 -0
- package/dist/core/compaction/compaction-boundary.d.ts.map +1 -0
- package/dist/core/compaction/compaction-boundary.js +115 -0
- package/dist/core/compaction/compaction-boundary.js.map +1 -0
- package/dist/core/compaction/compaction-parameters.d.ts +5 -0
- package/dist/core/compaction/compaction-parameters.d.ts.map +1 -0
- package/dist/core/compaction/compaction-parameters.js +27 -0
- package/dist/core/compaction/compaction-parameters.js.map +1 -0
- package/dist/core/compaction/compaction-runner.d.ts +14 -0
- package/dist/core/compaction/compaction-runner.d.ts.map +1 -0
- package/dist/core/compaction/compaction-runner.js +29 -0
- package/dist/core/compaction/compaction-runner.js.map +1 -0
- package/dist/core/compaction/compaction-types.d.ts +79 -0
- package/dist/core/compaction/compaction-types.d.ts.map +1 -0
- package/dist/core/compaction/compaction-types.js +6 -0
- package/dist/core/compaction/compaction-types.js.map +1 -0
- package/dist/core/compaction/deleted-ranges.d.ts +6 -0
- package/dist/core/compaction/deleted-ranges.d.ts.map +1 -0
- package/dist/core/compaction/deleted-ranges.js +134 -0
- package/dist/core/compaction/deleted-ranges.js.map +1 -0
- package/dist/core/compaction/index.d.ts +7 -1
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +7 -1
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/compaction/range-planner.d.ts +21 -0
- package/dist/core/compaction/range-planner.d.ts.map +1 -0
- package/dist/core/compaction/range-planner.js +145 -0
- package/dist/core/compaction/range-planner.js.map +1 -0
- package/dist/core/compaction/transcript-serialization.d.ts +11 -0
- package/dist/core/compaction/transcript-serialization.d.ts.map +1 -0
- package/dist/core/compaction/transcript-serialization.js +104 -0
- package/dist/core/compaction/transcript-serialization.js.map +1 -0
- package/dist/core/extensions/context-types.d.ts +2 -2
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/event-results.d.ts +2 -2
- package/dist/core/extensions/event-results.d.ts.map +1 -1
- package/dist/core/extensions/event-results.js.map +1 -1
- package/dist/core/extensions/session-events.d.ts +7 -7
- package/dist/core/extensions/session-events.d.ts.map +1 -1
- package/dist/core/extensions/session-events.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/messages.d.ts +4 -0
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +11 -0
- package/dist/core/messages.js.map +1 -1
- package/dist/core/provider-context-usage.d.ts.map +1 -1
- package/dist/core/provider-context-usage.js +1 -2
- package/dist/core/provider-context-usage.js.map +1 -1
- package/dist/core/session-manager-archive.d.ts +2 -1
- package/dist/core/session-manager-archive.d.ts.map +1 -1
- package/dist/core/session-manager-archive.js +2 -2
- package/dist/core/session-manager-archive.js.map +1 -1
- package/dist/core/session-manager-classification.d.ts +9 -0
- package/dist/core/session-manager-classification.d.ts.map +1 -0
- package/dist/core/session-manager-classification.js +37 -0
- package/dist/core/session-manager-classification.js.map +1 -0
- package/dist/core/session-manager-core.d.ts +4 -4
- package/dist/core/session-manager-core.d.ts.map +1 -1
- package/dist/core/session-manager-core.js +13 -8
- package/dist/core/session-manager-core.js.map +1 -1
- package/dist/core/session-manager-entries.d.ts +4 -3
- package/dist/core/session-manager-entries.d.ts.map +1 -1
- package/dist/core/session-manager-entries.js +12 -10
- package/dist/core/session-manager-entries.js.map +1 -1
- package/dist/core/session-manager-history.d.ts +6 -23
- package/dist/core/session-manager-history.d.ts.map +1 -1
- package/dist/core/session-manager-history.js +23 -256
- package/dist/core/session-manager-history.js.map +1 -1
- package/dist/core/session-manager-list.d.ts.map +1 -1
- package/dist/core/session-manager-list.js +3 -3
- package/dist/core/session-manager-list.js.map +1 -1
- package/dist/core/session-manager-storage.d.ts +1 -1
- package/dist/core/session-manager-storage.d.ts.map +1 -1
- package/dist/core/session-manager-storage.js +3 -2
- package/dist/core/session-manager-storage.js.map +1 -1
- package/dist/core/session-manager-types.d.ts +14 -15
- package/dist/core/session-manager-types.d.ts.map +1 -1
- package/dist/core/session-manager-types.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +1 -1
- 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/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/main-session.d.ts +1 -0
- package/dist/main-session.d.ts.map +1 -1
- package/dist/main-session.js +7 -0
- package/dist/main-session.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -2
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +4 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js +12 -22
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.js +5 -11
- package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.js +3 -0
- package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-state.d.ts +1 -0
- package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-state.js +1 -0
- package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-utils.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-utils.js +1 -1
- package/dist/modes/interactive/components/chat-session-host-utils.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 +1 -0
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
- package/dist/modes/interactive/components/compaction-boundary-message.d.ts +20 -0
- package/dist/modes/interactive/components/compaction-boundary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/compaction-boundary-message.js +48 -0
- package/dist/modes/interactive/components/compaction-boundary-message.js.map +1 -0
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-list.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-list.js +3 -0
- package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.js +3 -47
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +2 -2
- package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +5 -3
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.js +21 -12
- package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +3 -5
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +1 -6
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.js +0 -4
- package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +2 -11
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/compaction.md +97 -772
- package/docs/extensions.md +25 -29
- package/docs/json.md +2 -2
- package/docs/rpc.md +32 -24
- package/docs/sdk.md +3 -3
- package/docs/session-format.md +49 -30
- package/docs/sessions.md +5 -3
- package/docs/settings.md +14 -4
- package/docs/usage.md +1 -1
- package/docs/workflows.md +30 -15
- package/examples/extensions/custom-compaction.ts +14 -58
- package/examples/extensions/handoff.ts +2 -3
- package/npm-shrinkwrap.json +23 -23
- package/package.json +2 -2
- package/dist/core/compaction/context-assistant-turns.d.ts +0 -42
- package/dist/core/compaction/context-assistant-turns.d.ts.map +0 -1
- package/dist/core/compaction/context-assistant-turns.js +0 -87
- package/dist/core/compaction/context-assistant-turns.js.map +0 -1
- package/dist/core/compaction/context-compaction-critical.d.ts +0 -15
- package/dist/core/compaction/context-compaction-critical.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-critical.js +0 -57
- package/dist/core/compaction/context-compaction-critical.js.map +0 -1
- package/dist/core/compaction/context-compaction-eviction-alternates.d.ts +0 -18
- package/dist/core/compaction/context-compaction-eviction-alternates.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-eviction-alternates.js +0 -186
- package/dist/core/compaction/context-compaction-eviction-alternates.js.map +0 -1
- package/dist/core/compaction/context-compaction-eviction.d.ts +0 -12
- package/dist/core/compaction/context-compaction-eviction.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-eviction.js +0 -222
- package/dist/core/compaction/context-compaction-eviction.js.map +0 -1
- package/dist/core/compaction/context-compaction-metrics.d.ts +0 -28
- package/dist/core/compaction/context-compaction-metrics.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-metrics.js +0 -107
- package/dist/core/compaction/context-compaction-metrics.js.map +0 -1
- package/dist/core/compaction/context-compaction-prompt.d.ts +0 -9
- package/dist/core/compaction/context-compaction-prompt.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-prompt.js +0 -163
- package/dist/core/compaction/context-compaction-prompt.js.map +0 -1
- package/dist/core/compaction/context-compaction-runner.d.ts +0 -11
- package/dist/core/compaction/context-compaction-runner.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-runner.js +0 -273
- package/dist/core/compaction/context-compaction-runner.js.map +0 -1
- package/dist/core/compaction/context-compaction-strategy.d.ts +0 -5
- package/dist/core/compaction/context-compaction-strategy.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-strategy.js +0 -27
- package/dist/core/compaction/context-compaction-strategy.js.map +0 -1
- package/dist/core/compaction/context-compaction-types.d.ts +0 -75
- package/dist/core/compaction/context-compaction-types.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction-types.js +0 -6
- package/dist/core/compaction/context-compaction-types.js.map +0 -1
- package/dist/core/compaction/context-compaction.d.ts +0 -10
- package/dist/core/compaction/context-compaction.d.ts.map +0 -1
- package/dist/core/compaction/context-compaction.js +0 -8
- package/dist/core/compaction/context-compaction.js.map +0 -1
- package/dist/core/compaction/context-deletion-application.d.ts +0 -14
- package/dist/core/compaction/context-deletion-application.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-application.js +0 -261
- package/dist/core/compaction/context-deletion-application.js.map +0 -1
- package/dist/core/compaction/context-deletion-store.d.ts +0 -78
- package/dist/core/compaction/context-deletion-store.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-store.js +0 -162
- package/dist/core/compaction/context-deletion-store.js.map +0 -1
- package/dist/core/compaction/context-deletion-targets.d.ts +0 -43
- package/dist/core/compaction/context-deletion-targets.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-targets.js +0 -292
- package/dist/core/compaction/context-deletion-targets.js.map +0 -1
- package/dist/core/compaction/context-deletion-tool-definitions.d.ts +0 -193
- package/dist/core/compaction/context-deletion-tool-definitions.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-tool-definitions.js +0 -98
- package/dist/core/compaction/context-deletion-tool-definitions.js.map +0 -1
- package/dist/core/compaction/context-deletion-tool-helpers.d.ts +0 -19
- package/dist/core/compaction/context-deletion-tool-helpers.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-tool-helpers.js +0 -210
- package/dist/core/compaction/context-deletion-tool-helpers.js.map +0 -1
- package/dist/core/compaction/context-deletion-tools.d.ts +0 -4
- package/dist/core/compaction/context-deletion-tools.d.ts.map +0 -1
- package/dist/core/compaction/context-deletion-tools.js +0 -403
- package/dist/core/compaction/context-deletion-tools.js.map +0 -1
- package/dist/core/compaction/context-transcript-analysis.d.ts +0 -11
- package/dist/core/compaction/context-transcript-analysis.d.ts.map +0 -1
- package/dist/core/compaction/context-transcript-analysis.js +0 -228
- package/dist/core/compaction/context-transcript-analysis.js.map +0 -1
- package/dist/core/session-manager-tool-dependencies.d.ts +0 -10
- package/dist/core/session-manager-tool-dependencies.d.ts.map +0 -1
- package/dist/core/session-manager-tool-dependencies.js +0 -133
- package/dist/core/session-manager-tool-dependencies.js.map +0 -1
- package/dist/modes/interactive/components/context-compaction-summary-message.d.ts +0 -17
- package/dist/modes/interactive/components/context-compaction-summary-message.d.ts.map +0 -1
- package/dist/modes/interactive/components/context-compaction-summary-message.js +0 -83
- package/dist/modes/interactive/components/context-compaction-summary-message.js.map +0 -1
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import { cancellationRegistry } from "../runs/background/cancellation-registry.js";
|
|
2
2
|
import { interruptAllRuns, interruptRun, killAllRuns, killRun, pauseRun, resumeRun } from "../runs/background/status.js";
|
|
3
|
-
import
|
|
3
|
+
import { getDurableBackend } from "../durable/factory.js";
|
|
4
4
|
import { store } from "../shared/store.js";
|
|
5
5
|
import { topLevelWorkflowRuns } from "../shared/run-visibility.js";
|
|
6
6
|
import { renderSessionList } from "../tui/session-list.js";
|
|
7
7
|
import { openKillConfirm, openSessionPicker } from "../tui/session-overlays.js";
|
|
8
|
-
import { openWorkflowResumeSelector } from "../tui/workflow-resume-selector.js";
|
|
9
8
|
import { deriveGraphTheme } from "../tui/graph-theme.js";
|
|
9
|
+
import { openWorkflowResumeSelector } from "../tui/workflow-resume-selector.js";
|
|
10
10
|
import { emitChatSurface } from "../tui/chat-surface-message.js";
|
|
11
|
-
import type {
|
|
12
|
-
import type { ExtensionRuntime } from "./runtime.js";
|
|
13
|
-
import type { ExtensionAPI, PiCommandContext } from "./public-types.js";
|
|
11
|
+
import type { PiCommandContext } from "./public-types.js";
|
|
14
12
|
import type { WorkflowCommandReporter } from "./workflow-command-utils.js";
|
|
15
13
|
import { stripYesFlag } from "./workflow-command-utils.js";
|
|
16
14
|
import { workflowPolicyFromContext } from "./workflow-policy.js";
|
|
17
|
-
import { formatResumableWorkflowList } from "../durable/resume-catalog.js";
|
|
18
15
|
import type { ResumableWorkflowEntry } from "../durable/types.js";
|
|
19
16
|
import {
|
|
20
17
|
formatAlreadyEndedRetainedMessage,
|
|
@@ -23,14 +20,14 @@ import {
|
|
|
23
20
|
resolveStageTarget,
|
|
24
21
|
} from "./workflow-targets.js";
|
|
25
22
|
import { formatWorkflowResourceLoadWarning } from "./workflow-command-surfaces.js";
|
|
23
|
+
import {
|
|
24
|
+
handleDurableResume,
|
|
25
|
+
prepareWorkflowResumeCatalog,
|
|
26
|
+
resolveWorkflowResumeTarget,
|
|
27
|
+
type WorkflowRunControlDeps,
|
|
28
|
+
} from "./workflow-durable-resume-command.js";
|
|
26
29
|
|
|
27
|
-
export
|
|
28
|
-
pi: ExtensionAPI;
|
|
29
|
-
overlay: GraphOverlayPort;
|
|
30
|
-
getPersistence: () => WorkflowPersistencePort | undefined;
|
|
31
|
-
runtimeForContext: (ctx?: PiCommandContext) => ExtensionRuntime;
|
|
32
|
-
ensureWorkflowResourcesLoaded: () => Promise<void> | void;
|
|
33
|
-
}
|
|
30
|
+
export type { WorkflowRunControlDeps } from "./workflow-durable-resume-command.js";
|
|
34
31
|
|
|
35
32
|
function resolveAttachStageId(runId: string, stageTarget: string | undefined): string | undefined | false {
|
|
36
33
|
if (!stageTarget) return undefined;
|
|
@@ -42,79 +39,6 @@ function resolveAttachStageId(runId: string, stageTarget: string | undefined): s
|
|
|
42
39
|
return byName?.id ?? false;
|
|
43
40
|
}
|
|
44
41
|
|
|
45
|
-
function filterSelectorDurableEntries(
|
|
46
|
-
runtime: ExtensionRuntime,
|
|
47
|
-
entries: readonly ResumableWorkflowEntry[],
|
|
48
|
-
): readonly ResumableWorkflowEntry[] {
|
|
49
|
-
const registry = runtime.registry as { has(name: string): boolean } | undefined;
|
|
50
|
-
if (registry === undefined) return entries;
|
|
51
|
-
return entries.filter((entry) => {
|
|
52
|
-
const requiresCurrentDefinition = entry.status === "running" || entry.status === "failed" || entry.status === "blocked";
|
|
53
|
-
return !requiresCurrentDefinition || registry.has(entry.name);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
async function handleDurableResume(
|
|
59
|
-
target: string | undefined,
|
|
60
|
-
ctx: PiCommandContext,
|
|
61
|
-
reporter: WorkflowCommandReporter,
|
|
62
|
-
deps: WorkflowRunControlDeps,
|
|
63
|
-
): Promise<boolean> {
|
|
64
|
-
const print = (msg: string): void => reporter.info(msg);
|
|
65
|
-
const fail = (msg: string): void => reporter.error(msg);
|
|
66
|
-
try {
|
|
67
|
-
await deps.ensureWorkflowResourcesLoaded();
|
|
68
|
-
} catch (error) {
|
|
69
|
-
ctx.ui?.notify(formatWorkflowResourceLoadWarning(error), "warning");
|
|
70
|
-
}
|
|
71
|
-
const runtime = deps.runtimeForContext(ctx);
|
|
72
|
-
const policy = workflowPolicyFromContext(ctx);
|
|
73
|
-
// Hydrate the durable backend from DBOS (if configured) before listing so a
|
|
74
|
-
// fresh process discovers workflows persisted by a prior session.
|
|
75
|
-
const prepared = await runtime.prepareDurableResumable(target);
|
|
76
|
-
const durable = filterSelectorDurableEntries(runtime, prepared);
|
|
77
|
-
if (target !== undefined) {
|
|
78
|
-
// Attempt resume by id/prefix against the durable catalog.
|
|
79
|
-
const result = runtime.resumeDurableWorkflow(target, { policy });
|
|
80
|
-
if (result.ok) {
|
|
81
|
-
print(result.message);
|
|
82
|
-
// Open/connect the overlay to the resumed run, analogous to live resume.
|
|
83
|
-
if (policy.allowInputPicker) deps.overlay.open(result.runId, overlaySurfaceFromContext(ctx));
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
// Not a durable workflow either — surface the catalog for discovery.
|
|
87
|
-
if (durable.length > 0) {
|
|
88
|
-
fail(`${result.message}\n\n${formatResumableWorkflowList(durable)}`);
|
|
89
|
-
} else {
|
|
90
|
-
fail(result.message);
|
|
91
|
-
}
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
// No target: show the durable selector when interactive, otherwise print.
|
|
95
|
-
if (durable.length === 0) {
|
|
96
|
-
fail("No resumable durable workflows found. Usage: /workflow resume <id> (or /resume for Atomic sessions).");
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
if (!policy.allowInputPicker) {
|
|
100
|
-
print(`${formatResumableWorkflowList(durable)}\n\nResume with: /workflow resume <id>`);
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
const picked = await openWorkflowResumeSelector(ctx.ui, [], durable);
|
|
104
|
-
if (picked.kind === "durable") {
|
|
105
|
-
const result = runtime.resumeDurableWorkflow(picked.workflowId, { policy });
|
|
106
|
-
if (result.ok) {
|
|
107
|
-
print(result.message);
|
|
108
|
-
if (policy.allowInputPicker) deps.overlay.open(result.runId, overlaySurfaceFromContext(ctx));
|
|
109
|
-
} else {
|
|
110
|
-
fail(result.message);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (picked.kind !== "durable") {
|
|
114
|
-
print(`${formatResumableWorkflowList(durable)}\n\nResume with: /workflow resume <id>`);
|
|
115
|
-
}
|
|
116
|
-
return true;
|
|
117
|
-
}
|
|
118
42
|
|
|
119
43
|
export async function handleRunControlCommand(
|
|
120
44
|
action: "connect" | "interrupt" | "kill" | "attach" | "pause" | "resume",
|
|
@@ -304,33 +228,35 @@ export async function handleRunControlCommand(
|
|
|
304
228
|
// Only inactive workflows belong in the resume selector. Live runs:
|
|
305
229
|
// show paused (quit) or recoverably-failed runs; actively-running live
|
|
306
230
|
// runs are hidden (resuming one that is executing would double-dispatch).
|
|
307
|
-
|
|
231
|
+
let liveRuns = topLevelWorkflowRuns(store.runs()).filter((run) =>
|
|
308
232
|
run.status === "paused" || (run.status === "failed" && run.resumable !== false),
|
|
309
233
|
);
|
|
234
|
+
const activeLiveIds = new Set(
|
|
235
|
+
topLevelWorkflowRuns(store.runs())
|
|
236
|
+
.filter((run) => run.endedAt === undefined && run.status === "running" && run.exitReason !== "quit")
|
|
237
|
+
.map((run) => run.id),
|
|
238
|
+
);
|
|
239
|
+
await ensureWorkflowResourcesVisible();
|
|
240
|
+
const runtime = deps.runtimeForContext(ctx);
|
|
310
241
|
let durableEntries: readonly ResumableWorkflowEntry[] = [];
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
)
|
|
320
|
-
|
|
321
|
-
const runtime = deps.runtimeForContext(ctx);
|
|
322
|
-
try {
|
|
323
|
-
const prepared = await runtime.prepareDurableResumable(undefined);
|
|
324
|
-
durableEntries = filterSelectorDurableEntries(runtime, prepared)
|
|
325
|
-
.filter((entry) => !activeLiveIds.has(entry.workflowId));
|
|
326
|
-
} catch (error) {
|
|
327
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
328
|
-
fail(`Failed to list resumable workflows: ${message}`);
|
|
242
|
+
let completedEntries: readonly ResumableWorkflowEntry[] = [];
|
|
243
|
+
try {
|
|
244
|
+
const catalog = await prepareWorkflowResumeCatalog(runtime, activeLiveIds);
|
|
245
|
+
durableEntries = catalog.resumable;
|
|
246
|
+
completedEntries = catalog.completed;
|
|
247
|
+
} catch (error) {
|
|
248
|
+
liveRuns = liveRuns.filter((run) => getDurableBackend().isWorkflowLoadable(run.id));
|
|
249
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
250
|
+
if (liveRuns.length === 0) {
|
|
251
|
+
fail(`Failed to list workflow resume targets: ${errorMessage}`);
|
|
329
252
|
return true;
|
|
330
253
|
}
|
|
331
254
|
}
|
|
332
|
-
|
|
333
|
-
|
|
255
|
+
liveRuns = liveRuns.filter((run) => getDurableBackend().isWorkflowLoadable(run.id));
|
|
256
|
+
const picked = await openWorkflowResumeSelector(ctx.ui, liveRuns, durableEntries, completedEntries);
|
|
257
|
+
if (picked.kind === "durable" || picked.kind === "completed") {
|
|
258
|
+
return await handleDurableResume(picked.workflowId, ctx, reporter, deps);
|
|
259
|
+
}
|
|
334
260
|
if (picked.kind === "live") {
|
|
335
261
|
const resolved = resolveRunIdPrefix(picked.runId);
|
|
336
262
|
if (resolved.kind !== "exact") {
|
|
@@ -359,14 +285,42 @@ export async function handleRunControlCommand(
|
|
|
359
285
|
if (action === "attach" && picked.kind === "kill") return handleRunControlCommand("kill", [picked.runId, "-y"], ctx, reporter, deps);
|
|
360
286
|
if (picked.kind !== (action === "attach" ? "connect" : action)) return true;
|
|
361
287
|
runId = picked.runId;
|
|
288
|
+
} else if (action === "resume") {
|
|
289
|
+
const backend = getDurableBackend();
|
|
290
|
+
const exactBeforePreparation = store.runs().find((run) => run.id === target);
|
|
291
|
+
let durable: readonly ResumableWorkflowEntry[] = [];
|
|
292
|
+
let preparationError: string | undefined;
|
|
293
|
+
const needsDurablePreparation = exactBeforePreparation === undefined
|
|
294
|
+
|| !backend.isWorkflowLoadable(exactBeforePreparation.id);
|
|
295
|
+
if (needsDurablePreparation) {
|
|
296
|
+
await ensureWorkflowResourcesVisible();
|
|
297
|
+
const runtime = deps.runtimeForContext(ctx);
|
|
298
|
+
try {
|
|
299
|
+
durable = await runtime.prepareDurableResumable(target);
|
|
300
|
+
} catch (error) {
|
|
301
|
+
preparationError = error instanceof Error ? error.message : String(error);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const loadableRuns = topLevelWorkflowRuns(store.runs()).filter((run) => backend.isWorkflowLoadable(run.id));
|
|
305
|
+
const combined = resolveWorkflowResumeTarget(target, loadableRuns, durable, backend.listCompletedWorkflows());
|
|
306
|
+
if (combined.kind === "ambiguous") {
|
|
307
|
+
fail(`Ambiguous workflow prefix "${target}" matches: ${combined.matches.map((match) => `${match.name} (${match.workflowId.slice(0, 8)})`).join(", ")}`);
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
if (combined.kind === "completed" || combined.kind === "durable") {
|
|
311
|
+
return await handleDurableResume(combined.workflowId, ctx, reporter, deps);
|
|
312
|
+
}
|
|
313
|
+
if (combined.kind === "live") runId = combined.workflowId;
|
|
314
|
+
else {
|
|
315
|
+
if (preparationError !== undefined) {
|
|
316
|
+
fail(`Failed to resolve workflow resume target: ${preparationError}`);
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
return await handleDurableResume(target, ctx, reporter, deps);
|
|
320
|
+
}
|
|
362
321
|
} else {
|
|
363
322
|
const resolved = resolveRunIdPrefix(target);
|
|
364
323
|
if (resolved.kind === "not_found") {
|
|
365
|
-
// Not a live run — fall back to the cross-session durable resume catalog.
|
|
366
|
-
// cross-ref: issue #1498 — /workflow resume by top-level workflow id.
|
|
367
|
-
if (action === "resume") {
|
|
368
|
-
return await handleDurableResume(target, ctx, reporter, deps);
|
|
369
|
-
}
|
|
370
324
|
fail(`Run not found: ${target}`);
|
|
371
325
|
return true;
|
|
372
326
|
}
|
|
@@ -45,7 +45,7 @@ const JsonSchemaObject = Type.Unsafe<Record<string, unknown>>({
|
|
|
45
45
|
|
|
46
46
|
const StageSessionOptionProperties = {
|
|
47
47
|
schema: Type.Optional(JsonSchemaObject),
|
|
48
|
-
cwd: Type.Optional(Type.String()),
|
|
48
|
+
cwd: Type.Optional(Type.String({ description: "Starting directory only; does not provide worktree isolation." })),
|
|
49
49
|
agentDir: Type.Optional(Type.String()),
|
|
50
50
|
authStorage: Type.Optional(SdkSessionOptionSchema("authStorage")),
|
|
51
51
|
modelRegistry: Type.Optional(SdkSessionOptionSchema("modelRegistry")),
|
|
@@ -88,8 +88,8 @@ const WorkflowTaskOptionProperties = {
|
|
|
88
88
|
output: Type.Optional(WorkflowOutputSchema),
|
|
89
89
|
outputMode: Type.Optional(Type.Union([Type.Literal("inline"), Type.Literal("file-only")])),
|
|
90
90
|
reads: Type.Optional(Type.Union([Type.Array(Type.String()), Type.Literal(false)])),
|
|
91
|
-
worktree: Type.Optional(Type.Boolean()),
|
|
92
|
-
gitWorktreeDir: Type.Optional(Type.String()),
|
|
91
|
+
worktree: Type.Optional(Type.Boolean({ description: "Runner-managed temporary per-task worktree isolation for direct runs." })),
|
|
92
|
+
gitWorktreeDir: Type.Optional(Type.String({ description: "Runner-managed reusable worktree; natural-language worktree instructions do not set this option." })),
|
|
93
93
|
baseBranch: Type.Optional(Type.String()),
|
|
94
94
|
maxOutput: Type.Optional(MaxOutputSchema),
|
|
95
95
|
artifacts: Type.Optional(Type.Boolean()),
|
|
@@ -107,8 +107,8 @@ const ParallelChainStepSchema = Type.Object({
|
|
|
107
107
|
parallel: Type.Array(DirectTaskSchema),
|
|
108
108
|
concurrency: Type.Optional(Type.Number()),
|
|
109
109
|
failFast: Type.Optional(Type.Boolean()),
|
|
110
|
-
worktree: Type.Optional(Type.Boolean()),
|
|
111
|
-
gitWorktreeDir: Type.Optional(Type.String()),
|
|
110
|
+
worktree: Type.Optional(Type.Boolean({ description: "Runner-managed temporary per-task worktree isolation for direct runs." })),
|
|
111
|
+
gitWorktreeDir: Type.Optional(Type.String({ description: "Runner-managed reusable worktree; natural-language worktree instructions do not set this option." })),
|
|
112
112
|
baseBranch: Type.Optional(Type.String()),
|
|
113
113
|
});
|
|
114
114
|
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from "../runs/background/status.js";
|
|
10
10
|
import { cancellationRegistry } from "../runs/background/cancellation-registry.js";
|
|
11
11
|
import { store } from "../shared/store.js";
|
|
12
|
+
import { getDurableBackend } from "../durable/factory.js";
|
|
12
13
|
import type { WorkflowExecutionPolicy, WorkflowPersistencePort } from "../shared/types.js";
|
|
13
14
|
import type { ExtensionRuntime } from "./runtime.js";
|
|
14
15
|
import type { WorkflowToolResult } from "./render-result.js";
|
|
@@ -176,6 +177,21 @@ export async function workflowResumeAction(
|
|
|
176
177
|
if (target.kind === "all") return { action: "resume", runId: "--all", status: "noop", message: "Resume does not support --all." };
|
|
177
178
|
if (target.kind === "ambiguous") return { action: "resume", runId: target.target, status: "noop", message: ambiguousRunMessage(target.target, target.matches) };
|
|
178
179
|
if (target.kind === "not_found") return { action: "resume", runId: target.target, status: "noop", message: target.message };
|
|
180
|
+
const backend = getDurableBackend();
|
|
181
|
+
if (!backend.isWorkflowLoadable(target.runId)) {
|
|
182
|
+
try {
|
|
183
|
+
await deps.ensureWorkflowResourcesLoaded();
|
|
184
|
+
await deps.getRuntime().prepareDurableResumable(target.runId);
|
|
185
|
+
} catch {
|
|
186
|
+
// Durable compatibility preparation failures fall through to the
|
|
187
|
+
// authoritative loadability check below; workflow resume remains best-effort.
|
|
188
|
+
}
|
|
189
|
+
if (!backend.isWorkflowLoadable(target.runId)) {
|
|
190
|
+
store.removeRun(target.runId);
|
|
191
|
+
return { action: "resume", runId: target.runId, status: "noop", message: `Run not found: ${target.runId}` };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
let warning: string | undefined;
|
|
179
195
|
const stage = resolveToolStageTarget(target.runId, args.stageId);
|
|
180
196
|
if (!stage.ok) return { action: "resume", runId: target.runId, status: "noop", message: stage.message };
|
|
181
197
|
const stageRunId = stage.runId ?? target.runId;
|
|
@@ -188,7 +204,6 @@ export async function workflowResumeAction(
|
|
|
188
204
|
(run.endedAt === undefined && run.resumable === true && run.failureRecoverability === "recoverable")
|
|
189
205
|
);
|
|
190
206
|
if (isResumableContinuation) {
|
|
191
|
-
let warning: string | undefined;
|
|
192
207
|
try {
|
|
193
208
|
await deps.ensureWorkflowResourcesLoaded();
|
|
194
209
|
} catch (error) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tmpdir } from "node:os";
|
|
2
2
|
import { basename, dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
3
|
-
import { CONFIG_DIR_NAME, isCodexFastModeCandidateModelId } from "@bastani/atomic";
|
|
3
|
+
import { APP_NAME, CONFIG_DIR_NAME, isCodexFastModeCandidateModelId } from "@bastani/atomic";
|
|
4
4
|
import { Type } from "typebox";
|
|
5
5
|
import type {
|
|
6
6
|
StageOptions,
|
|
@@ -10,7 +10,6 @@ import type {
|
|
|
10
10
|
WorkflowDetails,
|
|
11
11
|
WorkflowDirectOptions,
|
|
12
12
|
WorkflowDirectTaskItem,
|
|
13
|
-
WorkflowOutputMode,
|
|
14
13
|
WorkflowOutputSchema,
|
|
15
14
|
WorkflowTaskResult,
|
|
16
15
|
WorkflowTaskStep,
|
|
@@ -30,10 +29,11 @@ import {
|
|
|
30
29
|
type GitWorktreeSetupResult,
|
|
31
30
|
type WorktreeSetup,
|
|
32
31
|
} from "../shared/worktree.js";
|
|
32
|
+
import { resolveWorktreeStageCwd } from "../shared/worktree-cwd.js";
|
|
33
33
|
import type { RunOpts, RunResult } from "./executor-types.js";
|
|
34
34
|
import { isWorkflowExitStatus } from "./executor-abort.js";
|
|
35
|
-
import { directTaskWithDefaults,
|
|
36
|
-
export { createGitWorktreeSetupCache } from "../shared/worktree.js";
|
|
35
|
+
import { directTaskWithDefaults, withoutUndefinedProperties } from "./executor-task-prompts.js";
|
|
36
|
+
export { createGitWorktreeSetupCache, createGitWorktreeSetupCacheOwner } from "../shared/worktree.js";
|
|
37
37
|
export type { GitWorktreeSetupCache } from "../shared/worktree.js";
|
|
38
38
|
|
|
39
39
|
export function directModelRequestsFromChain(
|
|
@@ -190,11 +190,17 @@ function namespaceRepeatedOutput(output: WorkflowDirectTaskItem["output"], index
|
|
|
190
190
|
return join(dirname(output), `${base}-${index + 1}${ext}`);
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
+
export interface DirectOutputIsolation {
|
|
194
|
+
readonly baseDir: string;
|
|
195
|
+
readonly trustedRoot: string;
|
|
196
|
+
}
|
|
197
|
+
|
|
193
198
|
export interface PreparedDirectWorktrees {
|
|
194
199
|
readonly tasks: WorkflowDirectTaskItem[];
|
|
195
200
|
readonly setup?: WorktreeSetup;
|
|
196
201
|
readonly agents: string[];
|
|
197
202
|
readonly diffsDir?: string;
|
|
203
|
+
readonly outputIsolations?: readonly DirectOutputIsolation[];
|
|
198
204
|
}
|
|
199
205
|
|
|
200
206
|
export function directRunId(runOptions: RunOpts): string {
|
|
@@ -205,20 +211,18 @@ function hasDirectWorktreeIsolation(tasks: readonly WorkflowDirectTaskItem[], op
|
|
|
205
211
|
return options.worktree === true || tasks.some((task) => task.worktree === true);
|
|
206
212
|
}
|
|
207
213
|
|
|
208
|
-
function resolveSharedDirectWorktreeCwd(
|
|
214
|
+
function resolveSharedDirectWorktreeCwd(
|
|
215
|
+
tasks: readonly WorkflowDirectTaskItem[],
|
|
216
|
+
workflowInvocationCwd: string,
|
|
217
|
+
): string {
|
|
209
218
|
const explicitCwd = tasks.find((task) => typeof task.cwd === "string")?.cwd;
|
|
210
|
-
if (explicitCwd === undefined) return
|
|
211
|
-
return isAbsolute(explicitCwd) ? explicitCwd : resolve(
|
|
219
|
+
if (explicitCwd === undefined) return workflowInvocationCwd;
|
|
220
|
+
return isAbsolute(explicitCwd) ? explicitCwd : resolve(workflowInvocationCwd, explicitCwd);
|
|
212
221
|
}
|
|
213
222
|
|
|
214
|
-
function normalizeDirectTaskCwd(cwd: string | undefined): string | undefined {
|
|
223
|
+
function normalizeDirectTaskCwd(cwd: string | undefined, workflowInvocationCwd: string): string | undefined {
|
|
215
224
|
if (cwd === undefined) return undefined;
|
|
216
|
-
return isAbsolute(cwd) ? cwd : resolve(
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export function resolveWorktreeCwdOverride(cwd: string | undefined, worktreeCwd: string): string | undefined {
|
|
220
|
-
if (cwd === undefined || cwd.length === 0) return undefined;
|
|
221
|
-
return isAbsolute(cwd) ? cwd : resolve(worktreeCwd, cwd);
|
|
225
|
+
return isAbsolute(cwd) ? cwd : resolve(workflowInvocationCwd, cwd);
|
|
222
226
|
}
|
|
223
227
|
|
|
224
228
|
export function stageOptionsWithInputDefaults<T extends StageOptions>(options: T | undefined, inputDefaults: Partial<StageOptions>): T | undefined {
|
|
@@ -229,13 +233,16 @@ export function stageOptionsWithInputDefaults<T extends StageOptions>(options: T
|
|
|
229
233
|
|
|
230
234
|
export function stageOptionsWithGitWorktree<T extends StageOptions>(options: T | undefined, workflowInvocationCwd: string, cache?: GitWorktreeSetupCache): T | undefined {
|
|
231
235
|
if (options === undefined) return undefined;
|
|
232
|
-
if (typeof options.gitWorktreeDir !== "string"
|
|
236
|
+
if (typeof options.gitWorktreeDir !== "string") return options;
|
|
237
|
+
if (options.gitWorktreeDir.trim().length === 0) {
|
|
238
|
+
throw new Error("atomic-workflows: gitWorktreeDir cannot be empty; provide a reusable worktree path or omit gitWorktreeDir for a non-worktree run.");
|
|
239
|
+
}
|
|
233
240
|
const setup = setupGitWorktreeCached({
|
|
234
241
|
gitWorktreeDir: options.gitWorktreeDir,
|
|
235
242
|
baseBranch: options.baseBranch,
|
|
236
243
|
cwd: workflowInvocationCwd,
|
|
237
244
|
}, cache);
|
|
238
|
-
const explicitCwd =
|
|
245
|
+
const explicitCwd = resolveWorktreeStageCwd(options.cwd, setup);
|
|
239
246
|
return { ...options, gitWorktreeDir: undefined, baseBranch: undefined, cwd: explicitCwd ?? setup.cwd };
|
|
240
247
|
}
|
|
241
248
|
|
|
@@ -267,9 +274,24 @@ export function workflowInvocationMetadata(inputDefaults: Partial<StageOptions>,
|
|
|
267
274
|
};
|
|
268
275
|
}
|
|
269
276
|
|
|
277
|
+
function nonBlankChainDir(chainDir: string | undefined): string | undefined {
|
|
278
|
+
return typeof chainDir === "string" && chainDir.trim().length > 0 ? chainDir : undefined;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function directWorktreeArtifactBase(options: WorkflowDirectOptions, setup: WorktreeSetup): string {
|
|
282
|
+
return nonBlankChainDir(options.chainDir) ?? join(setup.cwd, CONFIG_DIR_NAME, "workflows");
|
|
283
|
+
}
|
|
284
|
+
|
|
270
285
|
function directWorktreeDiffsDir(options: WorkflowDirectOptions, setup: WorktreeSetup, runId: string, scope: string): string {
|
|
271
|
-
|
|
272
|
-
|
|
286
|
+
return join(directWorktreeArtifactBase(options, setup), "worktree-diffs", runId, scope);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function directWorktreeOutputsRoot(): string {
|
|
290
|
+
return join(tmpdir(), `${APP_NAME}-workflow-outputs`);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function directWorktreeOutputsDir(runId: string, scope: string, index: number): string {
|
|
294
|
+
return join(directWorktreeOutputsRoot(), runId, scope, String(index));
|
|
273
295
|
}
|
|
274
296
|
|
|
275
297
|
export function prepareDirectWorktrees(
|
|
@@ -277,6 +299,7 @@ export function prepareDirectWorktrees(
|
|
|
277
299
|
options: WorkflowDirectOptions,
|
|
278
300
|
runId: string,
|
|
279
301
|
scope: string,
|
|
302
|
+
workflowInvocationCwd: string = process.cwd(),
|
|
280
303
|
): PreparedDirectWorktrees {
|
|
281
304
|
if (!hasDirectWorktreeIsolation(tasks, options)) {
|
|
282
305
|
return {
|
|
@@ -289,9 +312,9 @@ export function prepareDirectWorktrees(
|
|
|
289
312
|
throw new Error("atomic-workflows: worktree and gitWorktreeDir are mutually exclusive; use gitWorktreeDir for a reusable worktree or worktree:true for temporary isolated worktrees.");
|
|
290
313
|
}
|
|
291
314
|
|
|
292
|
-
const sharedCwd = resolveSharedDirectWorktreeCwd(tasks);
|
|
315
|
+
const sharedCwd = resolveSharedDirectWorktreeCwd(tasks, workflowInvocationCwd);
|
|
293
316
|
const conflict = findWorktreeTaskCwdConflict(
|
|
294
|
-
tasks.map((task) => ({ agent: task.name, cwd: normalizeDirectTaskCwd(task.cwd) })),
|
|
317
|
+
tasks.map((task) => ({ agent: task.name, cwd: normalizeDirectTaskCwd(task.cwd, workflowInvocationCwd) })),
|
|
295
318
|
sharedCwd,
|
|
296
319
|
);
|
|
297
320
|
if (conflict !== undefined) throw new Error(formatWorktreeTaskCwdConflict(conflict, sharedCwd));
|
|
@@ -306,6 +329,10 @@ export function prepareDirectWorktrees(
|
|
|
306
329
|
setup,
|
|
307
330
|
agents,
|
|
308
331
|
diffsDir: directWorktreeDiffsDir(options, setup, runId, scope),
|
|
332
|
+
outputIsolations: tasks.map((_, index) => ({
|
|
333
|
+
baseDir: directWorktreeOutputsDir(runId, scope, index),
|
|
334
|
+
trustedRoot: directWorktreeOutputsRoot(),
|
|
335
|
+
})),
|
|
309
336
|
};
|
|
310
337
|
}
|
|
311
338
|
|
|
@@ -343,31 +370,11 @@ export function isRunOpts(value: WorkflowDirectOptions | RunOpts | undefined): v
|
|
|
343
370
|
"adapters" in value || "ui" in value || "store" in value || "persistence" in value ||
|
|
344
371
|
"mcp" in value || "cancellation" in value || "overlay" in value || "signal" in value ||
|
|
345
372
|
"config" in value || "depth" in value || "stageControlRegistry" in value || "runId" in value ||
|
|
346
|
-
"
|
|
347
|
-
"models" in value
|
|
373
|
+
"gitWorktreeSetupCache" in value || "onRunStart" in value || "onStageStart" in value ||
|
|
374
|
+
"onStageEnd" in value || "onRunEnd" in value || "models" in value
|
|
348
375
|
);
|
|
349
376
|
}
|
|
350
377
|
|
|
351
|
-
export async function writeDirectOutput(
|
|
352
|
-
item: { readonly chainDir?: string; readonly cwd?: string; readonly output?: string | false; readonly outputMode?: WorkflowOutputMode },
|
|
353
|
-
result: WorkflowTaskResult,
|
|
354
|
-
): Promise<{ result: WorkflowTaskResult; artifact?: WorkflowArtifact }> {
|
|
355
|
-
if (typeof item.output !== "string") return { result };
|
|
356
|
-
|
|
357
|
-
const outputPath = resolveWorkflowPath(item.output, taskBaseDir(item));
|
|
358
|
-
await mkdir(dirname(outputPath), { recursive: true });
|
|
359
|
-
await writeFile(outputPath, result.text, "utf8");
|
|
360
|
-
|
|
361
|
-
const visibleResult = item.outputMode === "file-only" ? { ...result, text: "" } : result;
|
|
362
|
-
return {
|
|
363
|
-
result: visibleResult,
|
|
364
|
-
artifact: {
|
|
365
|
-
kind: "output",
|
|
366
|
-
path: outputPath,
|
|
367
|
-
taskName: result.name,
|
|
368
|
-
},
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
378
|
|
|
372
379
|
function directFailureMessage(error: unknown): string {
|
|
373
380
|
return classifyWorkflowFailure(error).userMessage;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { lstat, mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, isAbsolute, relative } from "node:path";
|
|
3
|
+
import type {
|
|
4
|
+
WorkflowArtifact,
|
|
5
|
+
WorkflowDirectTaskItem,
|
|
6
|
+
WorkflowTaskResult,
|
|
7
|
+
} from "../../shared/types.js";
|
|
8
|
+
import { setupGitWorktreeCached, type GitWorktreeSetupCache } from "../shared/worktree.js";
|
|
9
|
+
import { resolveContainedRelativePath, resolveWorktreeStageCwd } from "../shared/worktree-cwd.js";
|
|
10
|
+
import type { DirectOutputIsolation } from "./executor-direct-helpers.js";
|
|
11
|
+
import { resolveWorkflowPath, taskBaseDir } from "./executor-task-prompts.js";
|
|
12
|
+
|
|
13
|
+
function nonBlankChainDir(chainDir: string | undefined): string | undefined {
|
|
14
|
+
return typeof chainDir === "string" && chainDir.trim().length > 0 ? chainDir : undefined;
|
|
15
|
+
}
|
|
16
|
+
async function ensureTrustedArtifactRoot(root: string): Promise<void> {
|
|
17
|
+
await mkdir(root, { recursive: true });
|
|
18
|
+
const entry = await lstat(root);
|
|
19
|
+
if (entry.isSymbolicLink() || !entry.isDirectory()) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`atomic-workflows: runner artifact root ${root} must be a real directory, not a symlink or junction.`,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function writeDirectOutput(
|
|
27
|
+
item: Pick<WorkflowDirectTaskItem, "cwd" | "output" | "outputMode" | "gitWorktreeDir" | "baseBranch"> & { readonly chainDir?: string },
|
|
28
|
+
result: WorkflowTaskResult,
|
|
29
|
+
workflowInvocationCwd: string = process.cwd(),
|
|
30
|
+
outputIsolation?: DirectOutputIsolation,
|
|
31
|
+
gitWorktreeSetupCache?: GitWorktreeSetupCache,
|
|
32
|
+
): Promise<{ result: WorkflowTaskResult; artifact?: WorkflowArtifact }> {
|
|
33
|
+
if (typeof item.output !== "string") return { result };
|
|
34
|
+
|
|
35
|
+
const explicitChainDir = nonBlankChainDir(item.chainDir);
|
|
36
|
+
let outputPath: string;
|
|
37
|
+
let trustedArtifactRoot: string | undefined;
|
|
38
|
+
let containment: { readonly root: string; readonly baseDir: string; readonly description: string } | undefined;
|
|
39
|
+
if (isAbsolute(item.output)) {
|
|
40
|
+
outputPath = item.output;
|
|
41
|
+
} else if (explicitChainDir !== undefined) {
|
|
42
|
+
outputPath = resolveWorkflowPath(item.output, resolveWorkflowPath(explicitChainDir, process.cwd()));
|
|
43
|
+
} else if (outputIsolation !== undefined) {
|
|
44
|
+
await ensureTrustedArtifactRoot(outputIsolation.trustedRoot);
|
|
45
|
+
trustedArtifactRoot = outputIsolation.trustedRoot;
|
|
46
|
+
const baseRelative = relative(outputIsolation.trustedRoot, outputIsolation.baseDir);
|
|
47
|
+
const baseDir = resolveContainedRelativePath(
|
|
48
|
+
outputIsolation.trustedRoot,
|
|
49
|
+
outputIsolation.trustedRoot,
|
|
50
|
+
baseRelative,
|
|
51
|
+
"runner artifact root",
|
|
52
|
+
);
|
|
53
|
+
await mkdir(baseDir, { recursive: true });
|
|
54
|
+
containment = { root: baseDir, baseDir, description: "runner output root" };
|
|
55
|
+
outputPath = resolveContainedRelativePath(baseDir, baseDir, item.output, containment.description);
|
|
56
|
+
} else if (typeof item.gitWorktreeDir === "string") {
|
|
57
|
+
const setup = setupGitWorktreeCached({
|
|
58
|
+
gitWorktreeDir: item.gitWorktreeDir,
|
|
59
|
+
baseBranch: item.baseBranch,
|
|
60
|
+
cwd: workflowInvocationCwd,
|
|
61
|
+
}, gitWorktreeSetupCache);
|
|
62
|
+
const baseDir = resolveWorktreeStageCwd(item.cwd, setup) ?? setup.cwd;
|
|
63
|
+
containment = { root: setup.worktreeRoot, baseDir, description: "gitWorktreeDir" };
|
|
64
|
+
outputPath = resolveContainedRelativePath(setup.worktreeRoot, baseDir, item.output, containment.description);
|
|
65
|
+
} else {
|
|
66
|
+
outputPath = resolveWorkflowPath(item.output, taskBaseDir(item));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
70
|
+
if (trustedArtifactRoot !== undefined) await ensureTrustedArtifactRoot(trustedArtifactRoot);
|
|
71
|
+
|
|
72
|
+
if (containment !== undefined) {
|
|
73
|
+
outputPath = resolveContainedRelativePath(
|
|
74
|
+
containment.root,
|
|
75
|
+
containment.baseDir,
|
|
76
|
+
item.output,
|
|
77
|
+
containment.description,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
await writeFile(outputPath, result.text, "utf8");
|
|
81
|
+
|
|
82
|
+
const visibleResult = item.outputMode === "file-only" ? { ...result, text: "" } : result;
|
|
83
|
+
return {
|
|
84
|
+
result: visibleResult,
|
|
85
|
+
artifact: {
|
|
86
|
+
kind: "output",
|
|
87
|
+
path: outputPath,
|
|
88
|
+
taskName: result.name,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|