@bastani/atomic 0.9.0-alpha.1 → 0.9.0-alpha.2
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 +23 -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 +2 -2
- package/dist/builtin/mcp/CHANGELOG.md +6 -0
- package/dist/builtin/mcp/package.json +3 -3
- package/dist/builtin/subagents/CHANGELOG.md +6 -0
- package/dist/builtin/subagents/package.json +4 -4
- package/dist/builtin/web-access/CHANGELOG.md +6 -0
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +12 -0
- package/dist/builtin/workflows/README.md +189 -122
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +30 -27
- package/dist/builtin/workflows/builtin/goal-runner.ts +10 -17
- package/dist/builtin/workflows/builtin/goal.ts +39 -44
- package/dist/builtin/workflows/builtin/index.d.ts +1 -0
- package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +16 -17
- package/dist/builtin/workflows/builtin/open-claude-design.d.ts +1 -0
- package/dist/builtin/workflows/builtin/open-claude-design.ts +42 -50
- package/dist/builtin/workflows/builtin/ralph.ts +44 -41
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/authoring/typebox-defaults.d.ts +41 -0
- package/dist/builtin/workflows/src/authoring/typebox-defaults.ts +217 -0
- package/dist/builtin/workflows/src/authoring/workflow.ts +184 -0
- package/dist/builtin/workflows/src/authoring.d.ts +14 -66
- package/dist/builtin/workflows/src/engine/graph-inference.ts +100 -0
- package/dist/builtin/workflows/src/engine/options.ts +40 -0
- package/dist/builtin/workflows/src/engine/primitives/chain.ts +29 -0
- package/dist/builtin/workflows/src/engine/primitives/exit.ts +2 -0
- package/dist/builtin/workflows/src/engine/primitives/parallel.ts +47 -0
- package/dist/builtin/workflows/src/engine/primitives/task.ts +108 -0
- package/dist/builtin/workflows/src/engine/primitives/ui.ts +41 -0
- package/dist/builtin/workflows/src/engine/primitives/workflow.ts +159 -0
- package/dist/builtin/workflows/src/engine/replay.ts +8 -0
- package/dist/builtin/workflows/src/engine/run.ts +356 -0
- package/dist/builtin/workflows/src/engine/runtime.ts +160 -0
- package/dist/builtin/workflows/src/extension/workflow-module-loader.ts +9 -3
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +0 -18
- package/dist/builtin/workflows/src/index.ts +0 -2
- package/dist/builtin/workflows/src/runs/background/runner.ts +6 -3
- package/dist/builtin/workflows/src/runs/foreground/executor-child-boundary.ts +3 -3
- package/dist/builtin/workflows/src/runs/foreground/executor-child-helpers.ts +4 -4
- package/dist/builtin/workflows/src/runs/foreground/executor-child-workflow.ts +1 -158
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-outputs.ts +2 -2
- package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-run.ts +1 -359
- package/dist/builtin/workflows/src/runs/foreground/executor-scheduler.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +2 -5
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +12 -4
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-replay.ts +4 -3
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-types.ts +9 -2
- package/dist/builtin/workflows/src/runs/foreground/executor-task-context.ts +2 -132
- package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +2 -2
- package/dist/builtin/workflows/src/runs/shared/graph-inference.ts +2 -100
- package/dist/builtin/workflows/src/sdk-surface.ts +6 -9
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +9 -3
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +17 -3
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +3 -33
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +9 -81
- package/dist/builtin/workflows/src/shared/types.ts +25 -8
- package/dist/builtin/workflows/src/shared/workflow-authoring-types.d.ts +49 -0
- package/dist/builtin/workflows/src/shared/workflow-authoring-types.ts +84 -0
- package/dist/builtin/workflows/src/workflows/registry.ts +7 -3
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +6 -1
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-bash.d.ts.map +1 -1
- package/dist/core/agent-session-bash.js +0 -5
- package/dist/core/agent-session-bash.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +0 -2
- 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-services.d.ts +0 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +0 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +0 -2
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +0 -2
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +0 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +0 -1
- 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 +1 -1
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/extensions/loader-core.d.ts +1 -3
- package/dist/core/extensions/loader-core.d.ts.map +1 -1
- package/dist/core/extensions/loader-core.js +13 -6
- package/dist/core/extensions/loader-core.js.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts +7 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +34 -2
- package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +2 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +0 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/model-registry-builtins.d.ts.map +1 -1
- package/dist/core/model-registry-builtins.js +6 -0
- package/dist/core/model-registry-builtins.js.map +1 -1
- package/dist/core/model-registry-schemas.d.ts +65 -13
- package/dist/core/model-registry-schemas.d.ts.map +1 -1
- package/dist/core/model-registry-schemas.js +10 -0
- package/dist/core/model-registry-schemas.js.map +1 -1
- package/dist/core/resource-loader-core.d.ts +1 -0
- package/dist/core/resource-loader-core.d.ts.map +1 -1
- package/dist/core/resource-loader-core.js +2 -0
- package/dist/core/resource-loader-core.js.map +1 -1
- package/dist/core/resource-loader-extensions.d.ts.map +1 -1
- package/dist/core/resource-loader-extensions.js +3 -3
- package/dist/core/resource-loader-extensions.js.map +1 -1
- package/dist/core/resource-loader-internals.d.ts +1 -0
- package/dist/core/resource-loader-internals.d.ts.map +1 -1
- package/dist/core/resource-loader-internals.js.map +1 -1
- package/dist/core/resource-loader-reload.d.ts.map +1 -1
- package/dist/core/resource-loader-reload.js +6 -2
- package/dist/core/resource-loader-reload.js.map +1 -1
- package/dist/core/sdk-exports.d.ts +1 -1
- package/dist/core/sdk-exports.d.ts.map +1 -1
- package/dist/core/sdk-exports.js.map +1 -1
- package/dist/core/sdk-types.d.ts +0 -3
- package/dist/core/sdk-types.d.ts.map +1 -1
- package/dist/core/sdk-types.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +0 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager-history.d.ts.map +1 -1
- package/dist/core/session-manager-history.js +2 -1
- package/dist/core/session-manager-history.js.map +1 -1
- package/dist/core/tools/bash.d.ts +0 -5
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +10 -11
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff-preserve.d.ts +18 -0
- package/dist/core/tools/edit-diff-preserve.d.ts.map +1 -0
- package/dist/core/tools/edit-diff-preserve.js +85 -0
- package/dist/core/tools/edit-diff-preserve.js.map +1 -0
- package/dist/core/tools/edit-diff.d.ts +3 -2
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +15 -18
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/index.d.ts +0 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +0 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +2 -2
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/model-search.d.ts +5 -0
- package/dist/modes/interactive/model-search.d.ts.map +1 -1
- package/dist/modes/interactive/model-search.js +9 -0
- package/dist/modes/interactive/model-search.js.map +1 -1
- package/dist/utils/shell.d.ts +1 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +12 -5
- package/dist/utils/shell.js.map +1 -1
- package/docs/custom-provider.md +4 -3
- package/docs/models.md +3 -2
- package/docs/packages.md +2 -2
- package/docs/quickstart.md +1 -1
- package/docs/sdk.md +2 -40
- package/docs/security.md +1 -1
- package/docs/workflows.md +238 -173
- package/package.json +5 -5
- package/dist/builtin/workflows/src/workflows/define-workflow.ts +0 -277
- package/dist/core/tools/bash-policy-compile.d.ts +0 -5
- package/dist/core/tools/bash-policy-compile.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-compile.js +0 -241
- package/dist/core/tools/bash-policy-compile.js.map +0 -1
- package/dist/core/tools/bash-policy-evaluate.d.ts +0 -3
- package/dist/core/tools/bash-policy-evaluate.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-evaluate.js +0 -92
- package/dist/core/tools/bash-policy-evaluate.js.map +0 -1
- package/dist/core/tools/bash-policy-format.d.ts +0 -5
- package/dist/core/tools/bash-policy-format.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-format.js +0 -49
- package/dist/core/tools/bash-policy-format.js.map +0 -1
- package/dist/core/tools/bash-policy-parser.d.ts +0 -4
- package/dist/core/tools/bash-policy-parser.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-parser.js +0 -155
- package/dist/core/tools/bash-policy-parser.js.map +0 -1
- package/dist/core/tools/bash-policy-segment.d.ts +0 -3
- package/dist/core/tools/bash-policy-segment.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-segment.js +0 -275
- package/dist/core/tools/bash-policy-segment.js.map +0 -1
- package/dist/core/tools/bash-policy-shell.d.ts +0 -11
- package/dist/core/tools/bash-policy-shell.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-shell.js +0 -267
- package/dist/core/tools/bash-policy-shell.js.map +0 -1
- package/dist/core/tools/bash-policy-types.d.ts +0 -146
- package/dist/core/tools/bash-policy-types.d.ts.map +0 -1
- package/dist/core/tools/bash-policy-types.js +0 -2
- package/dist/core/tools/bash-policy-types.js.map +0 -1
- package/dist/core/tools/bash-policy.d.ts +0 -6
- package/dist/core/tools/bash-policy.d.ts.map +0 -1
- package/dist/core/tools/bash-policy.js +0 -5
- package/dist/core/tools/bash-policy.js.map +0 -1
|
@@ -1,158 +1 @@
|
|
|
1
|
-
|
|
2
|
-
WorkflowChildResult,
|
|
3
|
-
WorkflowDefinition,
|
|
4
|
-
WorkflowInputValues,
|
|
5
|
-
WorkflowOutputValues,
|
|
6
|
-
WorkflowRunChildOptions,
|
|
7
|
-
} from "../../shared/types.js";
|
|
8
|
-
import type { WorkflowChildRunRef } from "../../shared/store-types.js";
|
|
9
|
-
import type { RunOpts, RunResult } from "./executor-types.js";
|
|
10
|
-
import type { WorkflowExitManager } from "./executor-exit-manager.js";
|
|
11
|
-
import type { WorkflowBoundaryStage } from "./executor-child-boundary.js";
|
|
12
|
-
import { findWorkflowExitSignal, isWorkflowExitStatus, makeParentWorkflowExitAbortReason } from "./executor-abort.js";
|
|
13
|
-
import { selectWorkflowOutputs } from "./executor-outputs.js";
|
|
14
|
-
import { resolveAndValidateInputs } from "./executor-inputs.js";
|
|
15
|
-
import {
|
|
16
|
-
isWorkflowDefinition,
|
|
17
|
-
workflowChildReplaySnapshot,
|
|
18
|
-
workflowDefinitionRequirementMessage,
|
|
19
|
-
} from "./executor-child-helpers.js";
|
|
20
|
-
|
|
21
|
-
export function createChildWorkflowRunner(input: {
|
|
22
|
-
readonly runId: string;
|
|
23
|
-
readonly depth: number;
|
|
24
|
-
readonly opts: RunOpts;
|
|
25
|
-
readonly exit: WorkflowExitManager;
|
|
26
|
-
readonly ownController: AbortController;
|
|
27
|
-
readonly resolveWorkflowCwd: () => string;
|
|
28
|
-
readonly nextWorkflowBoundaryReplayKey: (name: string) => string;
|
|
29
|
-
readonly startWorkflowBoundaryStage: (name: string, replayKey: string) => WorkflowBoundaryStage;
|
|
30
|
-
readonly runWorkflow: <TInputs extends WorkflowInputValues>(
|
|
31
|
-
def: WorkflowDefinition<TInputs>,
|
|
32
|
-
inputs: Readonly<Record<string, unknown>>,
|
|
33
|
-
opts?: RunOpts,
|
|
34
|
-
) => Promise<RunResult>;
|
|
35
|
-
}): <TChildInputs extends WorkflowInputValues, TChildOutputs extends WorkflowOutputValues>(
|
|
36
|
-
child: WorkflowDefinition<TChildInputs, TChildOutputs>,
|
|
37
|
-
options?: WorkflowRunChildOptions<TChildInputs>,
|
|
38
|
-
) => Promise<WorkflowChildResult<TChildOutputs>> {
|
|
39
|
-
return async <TChildInputs extends WorkflowInputValues, TChildOutputs extends WorkflowOutputValues>(
|
|
40
|
-
child: WorkflowDefinition<TChildInputs, TChildOutputs>,
|
|
41
|
-
options: WorkflowRunChildOptions<TChildInputs> = {},
|
|
42
|
-
): Promise<WorkflowChildResult<TChildOutputs>> => {
|
|
43
|
-
input.exit.throwIfWorkflowExitSelected();
|
|
44
|
-
if (!isWorkflowDefinition(child)) throw new Error(workflowDefinitionRequirementMessage("ctx.workflow(definition)", child));
|
|
45
|
-
const childName = child.normalizedName;
|
|
46
|
-
const boundaryName = options.stageName ?? `workflow:${childName}`;
|
|
47
|
-
const boundaryReplayKey = input.nextWorkflowBoundaryReplayKey(boundaryName);
|
|
48
|
-
const boundary = input.startWorkflowBoundaryStage(boundaryName, boundaryReplayKey);
|
|
49
|
-
let childRunId: string | undefined;
|
|
50
|
-
let detachParentAbort: (() => void) | undefined;
|
|
51
|
-
try {
|
|
52
|
-
if (boundary.replayedChild !== undefined) {
|
|
53
|
-
await Promise.resolve();
|
|
54
|
-
input.exit.throwIfWorkflowExitSelected();
|
|
55
|
-
boundary.finalizeReplay();
|
|
56
|
-
return boundary.replayedChild as WorkflowChildResult<TChildOutputs>;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const childInputs = resolveAndValidateInputs(child.inputs, options.inputs ?? {}, `child workflow "${childName}" (${child.name})`);
|
|
60
|
-
input.exit.throwIfWorkflowExitSelected();
|
|
61
|
-
|
|
62
|
-
childRunId = crypto.randomUUID();
|
|
63
|
-
const childController = new AbortController();
|
|
64
|
-
const childRef: WorkflowChildRunRef = { alias: childName, workflow: child.normalizedName, runId: childRunId };
|
|
65
|
-
boundary.linkChildRun(childRef, childController);
|
|
66
|
-
|
|
67
|
-
const abortChildFromParent = (): void => {
|
|
68
|
-
const parentExit = findWorkflowExitSignal(input.ownController.signal.reason, input.exit.exitScope);
|
|
69
|
-
childController.abort(parentExit !== undefined ? makeParentWorkflowExitAbortReason(parentExit.reason) : input.ownController.signal.reason);
|
|
70
|
-
};
|
|
71
|
-
if (input.ownController.signal.aborted) abortChildFromParent();
|
|
72
|
-
else {
|
|
73
|
-
input.ownController.signal.addEventListener("abort", abortChildFromParent, { once: true });
|
|
74
|
-
detachParentAbort = () => input.ownController.signal.removeEventListener("abort", abortChildFromParent);
|
|
75
|
-
}
|
|
76
|
-
input.exit.throwIfWorkflowExitSelected();
|
|
77
|
-
input.opts.cancellation?.register(childRunId, childController);
|
|
78
|
-
input.exit.throwIfWorkflowExitSelected();
|
|
79
|
-
|
|
80
|
-
const {
|
|
81
|
-
runId: _parentRunId,
|
|
82
|
-
continuation: _parentContinuation,
|
|
83
|
-
deferWorkflowStart: _parentDeferWorkflowStart,
|
|
84
|
-
parentRun: _parentRun,
|
|
85
|
-
onRunStart: _parentOnRunStart,
|
|
86
|
-
onRunEnd: _parentOnRunEnd,
|
|
87
|
-
...childBaseOpts
|
|
88
|
-
} = input.opts;
|
|
89
|
-
const childRunPromise = input.runWorkflow(child, childInputs, {
|
|
90
|
-
...childBaseOpts,
|
|
91
|
-
runId: childRunId,
|
|
92
|
-
cwd: input.resolveWorkflowCwd(),
|
|
93
|
-
depth: input.depth + 1,
|
|
94
|
-
...(input.opts.registry !== undefined ? { registry: input.opts.registry } : {}),
|
|
95
|
-
parentRun: {
|
|
96
|
-
runId: input.runId,
|
|
97
|
-
stageId: boundary.id,
|
|
98
|
-
rootRunId: input.opts.parentRun?.rootRunId ?? input.runId,
|
|
99
|
-
},
|
|
100
|
-
signal: childController.signal,
|
|
101
|
-
deferWorkflowStart: false,
|
|
102
|
-
});
|
|
103
|
-
boundary.observeChildRun(childRunPromise);
|
|
104
|
-
const childRun = await childRunPromise;
|
|
105
|
-
input.exit.throwIfWorkflowExitSelected();
|
|
106
|
-
|
|
107
|
-
if (!isWorkflowExitStatus(childRun.status)) {
|
|
108
|
-
const failedChildStage = childRun.stages.find((stage) => stage.failureKind !== undefined);
|
|
109
|
-
throw new Error(
|
|
110
|
-
`atomic-workflows: child workflow "${childName}" (${child.name}) failed with status ${childRun.status}${childRun.error !== undefined ? `: ${childRun.error}` : ""}`,
|
|
111
|
-
{
|
|
112
|
-
cause: {
|
|
113
|
-
...(failedChildStage?.failureKind !== undefined ? { code: failedChildStage.failureKind } : {}),
|
|
114
|
-
...(failedChildStage?.failureMessage !== undefined ? { message: failedChildStage.failureMessage } : {}),
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const outputs = selectWorkflowOutputs(child, childRun.result);
|
|
121
|
-
const childExited = childRun.exited === true || childRun.status !== "completed";
|
|
122
|
-
const childResult: WorkflowChildResult<TChildOutputs> = childExited
|
|
123
|
-
? {
|
|
124
|
-
workflow: child.normalizedName,
|
|
125
|
-
runId: childRun.runId,
|
|
126
|
-
status: childRun.status,
|
|
127
|
-
exited: true,
|
|
128
|
-
outputs: outputs as Partial<TChildOutputs>,
|
|
129
|
-
...(childRun.exitReason !== undefined ? { exitReason: childRun.exitReason } : {}),
|
|
130
|
-
}
|
|
131
|
-
: {
|
|
132
|
-
workflow: child.normalizedName,
|
|
133
|
-
runId: childRun.runId,
|
|
134
|
-
status: "completed",
|
|
135
|
-
exited: false,
|
|
136
|
-
outputs: outputs as TChildOutputs,
|
|
137
|
-
};
|
|
138
|
-
const workflowChild = workflowChildReplaySnapshot(childName, childResult);
|
|
139
|
-
const outputKeys = Object.keys(outputs);
|
|
140
|
-
boundary.complete(
|
|
141
|
-
`Workflow "${child.name}" ${childRun.status} (runId: ${childRun.runId}; outputs: ${outputKeys.length > 0 ? outputKeys.join(", ") : "(none)"})`,
|
|
142
|
-
workflowChild,
|
|
143
|
-
);
|
|
144
|
-
return childResult;
|
|
145
|
-
} catch (err) {
|
|
146
|
-
const exit = findWorkflowExitSignal(err, input.exit.exitScope) ?? findWorkflowExitSignal(input.ownController.signal.reason, input.exit.exitScope);
|
|
147
|
-
if (exit !== undefined) {
|
|
148
|
-
await boundary.skipForWorkflowExit(exit.reason);
|
|
149
|
-
throw exit;
|
|
150
|
-
}
|
|
151
|
-
boundary.fail(err);
|
|
152
|
-
throw err;
|
|
153
|
-
} finally {
|
|
154
|
-
detachParentAbort?.();
|
|
155
|
-
if (childRunId !== undefined) input.opts.cancellation?.unregister(childRunId);
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
}
|
|
1
|
+
export { createChildWorkflowRunner } from "../../engine/primitives/workflow.js";
|
|
@@ -15,7 +15,7 @@ import type {
|
|
|
15
15
|
WorkflowTaskResult,
|
|
16
16
|
WorkflowTaskStep,
|
|
17
17
|
} from "../../shared/types.js";
|
|
18
|
-
import { stampWorkflowDefinition } from "../../
|
|
18
|
+
import { stampWorkflowDefinition } from "../../authoring/workflow.js";
|
|
19
19
|
import { classifyWorkflowFailure } from "../../shared/workflow-failures.js";
|
|
20
20
|
import { buildModelCandidatesFromCatalog, validateWorkflowModels, workflowModelId } from "../shared/model-fallback.js";
|
|
21
21
|
import {
|
|
@@ -31,7 +31,7 @@ function assertWorkflowOutputsExplicit(
|
|
|
31
31
|
for (const key of Object.keys(sourceOutput)) {
|
|
32
32
|
if (!hasOwnWorkflowOutput(declarations, key)) {
|
|
33
33
|
throw new Error(
|
|
34
|
-
`atomic-workflows: ${scope} returned undeclared output "${key}"; declare it
|
|
34
|
+
`atomic-workflows: ${scope} returned undeclared output "${key}"; declare it in outputs: { "${key}": Type.... } or remove it from the .run() return`,
|
|
35
35
|
);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -119,7 +119,7 @@ export function assertWorkflowExitOutputs(
|
|
|
119
119
|
for (const key of Object.keys(sourceOutput)) {
|
|
120
120
|
if (!hasOwnWorkflowOutput(declarations, key)) {
|
|
121
121
|
throw new Error(
|
|
122
|
-
`atomic-workflows: ${scope} provided undeclared output "${key}"; declare it
|
|
122
|
+
`atomic-workflows: ${scope} provided undeclared output "${key}"; declare it in outputs: { "${key}": Type.... } or remove it from ctx.exit({ outputs })`,
|
|
123
123
|
);
|
|
124
124
|
}
|
|
125
125
|
}
|
|
@@ -5,7 +5,7 @@ import { stageUiBroker } from "../../shared/stage-ui-broker.js";
|
|
|
5
5
|
import { appendStageEnd, appendStageStart } from "../../shared/persistence-session-entries.js";
|
|
6
6
|
import { elapsedStageMs } from "../../shared/timing.js";
|
|
7
7
|
import type { WorkflowFailure } from "../../shared/workflow-failures.js";
|
|
8
|
-
import type { GraphFrontierTracker } from "
|
|
8
|
+
import type { GraphFrontierTracker } from "../../engine/graph-inference.js";
|
|
9
9
|
import type { RunOpts, WorkflowExitCleanup } from "./executor-types.js";
|
|
10
10
|
import type { ContinuationReplayIndex } from "./executor-continuation.js";
|
|
11
11
|
import { getPromptAnswerState, sameStringSet } from "./executor-continuation.js";
|
|
@@ -1,359 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type {
|
|
3
|
-
WorkflowDefinition,
|
|
4
|
-
WorkflowInputValues,
|
|
5
|
-
WorkflowCustomUiFactory,
|
|
6
|
-
WorkflowCustomUiOptions,
|
|
7
|
-
WorkflowRunContext,
|
|
8
|
-
WorkflowUIContext,
|
|
9
|
-
} from "../../shared/types.js";
|
|
10
|
-
import type { WorkflowFailure } from "../../shared/workflow-failures.js";
|
|
11
|
-
import { classifyWorkflowFailure } from "../../shared/workflow-failures.js";
|
|
12
|
-
import { store as defaultStore } from "../../shared/store.js";
|
|
13
|
-
import { appendRunStart } from "../../shared/persistence-session-entries.js";
|
|
14
|
-
import { GraphFrontierTracker } from "../shared/graph-inference.js";
|
|
15
|
-
import { createRunLimiter } from "../shared/concurrency.js";
|
|
16
|
-
import { stageControlRegistry as defaultStageControlRegistry } from "./stage-control-registry.js";
|
|
17
|
-
import type { RunOpts, RunResult } from "./executor-types.js";
|
|
18
|
-
import { unknownErrorMessage, findWorkflowExitSignal, parentWorkflowExitAbortReason } from "./executor-abort.js";
|
|
19
|
-
import { createWorkflowExitManager } from "./executor-exit-manager.js";
|
|
20
|
-
import { resolveAndValidateInputs, resolveInputConcurrency, resolveInputRuntimeDefaults } from "./executor-inputs.js";
|
|
21
|
-
import { workflowCwdWithInputWorktree } from "./executor-direct-helpers.js";
|
|
22
|
-
import { createStageScheduler } from "./executor-scheduler.js";
|
|
23
|
-
import { createRunFinalizers } from "./executor-run-finalizers.js";
|
|
24
|
-
import { createWorkflowBoundaryFactory } from "./executor-child-boundary.js";
|
|
25
|
-
import { createWorkflowStageFactory } from "./executor-stage-factory.js";
|
|
26
|
-
import { createWorkflowTaskRunners } from "./executor-task-context.js";
|
|
27
|
-
import { createChildWorkflowRunner } from "./executor-child-workflow.js";
|
|
28
|
-
import { createContinuationReplayIndex } from "./executor-continuation.js";
|
|
29
|
-
import { buildPromptNodeUiAdapter } from "./executor-prompt-nodes.js";
|
|
30
|
-
import { makeHeadlessUnavailableUIContext, normalizeUIContext } from "./executor-hil.js";
|
|
31
|
-
import {
|
|
32
|
-
appendRunEndWhenRecorded,
|
|
33
|
-
assertWorkflowCreatedStage,
|
|
34
|
-
finalizeKilled,
|
|
35
|
-
finalizeKilledByFailure,
|
|
36
|
-
recordActiveBlockedFailure,
|
|
37
|
-
reconcileTerminalRunResult,
|
|
38
|
-
selectRunFailureDisposition,
|
|
39
|
-
} from "./executor-lifecycle.js";
|
|
40
|
-
import { assertWorkflowRunOutputs, normalizeWorkflowRunOutput } from "./executor-outputs.js";
|
|
41
|
-
import { isWorkflowDefinition, workflowDefinitionRequirementMessage } from "./executor-child-helpers.js";
|
|
42
|
-
|
|
43
|
-
function nextEventLoopTurn(): Promise<void> {
|
|
44
|
-
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function buildExitGatedUiContext(input: {
|
|
48
|
-
readonly opts: RunOpts;
|
|
49
|
-
readonly baseFromPromptNodes: () => WorkflowUIContext;
|
|
50
|
-
readonly throwIfWorkflowExitSelected: () => void;
|
|
51
|
-
}): WorkflowUIContext {
|
|
52
|
-
const base = input.opts.usePromptNodesForUi === true
|
|
53
|
-
? input.baseFromPromptNodes()
|
|
54
|
-
: input.opts.executionMode === "non_interactive" && input.opts.ui === undefined
|
|
55
|
-
? makeHeadlessUnavailableUIContext()
|
|
56
|
-
: normalizeUIContext(input.opts.ui);
|
|
57
|
-
return {
|
|
58
|
-
async input(promptText: string): Promise<string> {
|
|
59
|
-
input.throwIfWorkflowExitSelected();
|
|
60
|
-
return await base.input(promptText);
|
|
61
|
-
},
|
|
62
|
-
async confirm(message: string): Promise<boolean> {
|
|
63
|
-
input.throwIfWorkflowExitSelected();
|
|
64
|
-
return await base.confirm(message);
|
|
65
|
-
},
|
|
66
|
-
async select<T extends string>(message: string, options: readonly T[]): Promise<T> {
|
|
67
|
-
input.throwIfWorkflowExitSelected();
|
|
68
|
-
return await base.select(message, options);
|
|
69
|
-
},
|
|
70
|
-
async editor(initial?: string): Promise<string> {
|
|
71
|
-
input.throwIfWorkflowExitSelected();
|
|
72
|
-
return await base.editor(initial);
|
|
73
|
-
},
|
|
74
|
-
async custom<T>(factory: WorkflowCustomUiFactory<T>, options?: WorkflowCustomUiOptions): Promise<T> {
|
|
75
|
-
input.throwIfWorkflowExitSelected();
|
|
76
|
-
return await base.custom(factory, options);
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export async function run<TInputs extends WorkflowInputValues>(
|
|
82
|
-
def: WorkflowDefinition<TInputs>,
|
|
83
|
-
inputs: Readonly<Record<string, unknown>>,
|
|
84
|
-
opts: RunOpts = {},
|
|
85
|
-
): Promise<RunResult> {
|
|
86
|
-
if (!isWorkflowDefinition(def)) throw new Error(workflowDefinitionRequirementMessage("run(definition, inputs)", def));
|
|
87
|
-
|
|
88
|
-
const activeStore = opts.store ?? defaultStore;
|
|
89
|
-
const adapters = opts.adapters ?? {};
|
|
90
|
-
if (opts.usePromptNodesForUi === true && opts.ui !== undefined) {
|
|
91
|
-
console.warn("atomic-workflows: usePromptNodesForUi ignores the provided RunOpts.ui adapter");
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const depth = opts.depth ?? 0;
|
|
95
|
-
const maxDepth = opts.config?.maxDepth ?? 4;
|
|
96
|
-
if (depth >= maxDepth) {
|
|
97
|
-
return {
|
|
98
|
-
runId: opts.runId ?? crypto.randomUUID(),
|
|
99
|
-
status: "failed",
|
|
100
|
-
error: `atomic-workflows: maxDepth exceeded (max ${maxDepth})`,
|
|
101
|
-
stages: [],
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const resolvedInputs = resolveAndValidateInputs(def.inputs, inputs, `workflow "${def.name}"`);
|
|
106
|
-
const runId = opts.runId ?? crypto.randomUUID();
|
|
107
|
-
const exitScope = Symbol(`workflow-exit:${runId}`);
|
|
108
|
-
const ownController = new AbortController();
|
|
109
|
-
const callerSignal = opts.signal;
|
|
110
|
-
if (callerSignal) {
|
|
111
|
-
if (callerSignal.aborted) ownController.abort(callerSignal.reason);
|
|
112
|
-
else callerSignal.addEventListener("abort", () => { ownController.abort(callerSignal.reason); }, { once: true });
|
|
113
|
-
}
|
|
114
|
-
const exit = createWorkflowExitManager({ runId, exitScope, controller: ownController });
|
|
115
|
-
|
|
116
|
-
const runSnapshot: RunSnapshot = {
|
|
117
|
-
id: runId,
|
|
118
|
-
name: def.name,
|
|
119
|
-
inputs: Object.freeze(resolvedInputs),
|
|
120
|
-
status: "running" as const,
|
|
121
|
-
stages: [],
|
|
122
|
-
startedAt: Date.now(),
|
|
123
|
-
...(opts.parentRun !== undefined ? {
|
|
124
|
-
parentRunId: opts.parentRun.runId,
|
|
125
|
-
parentStageId: opts.parentRun.stageId,
|
|
126
|
-
rootRunId: opts.parentRun.rootRunId,
|
|
127
|
-
} : {}),
|
|
128
|
-
...(opts.continuation !== undefined ? {
|
|
129
|
-
resumedFromRunId: opts.continuation.source.id,
|
|
130
|
-
resumeFromStageId: opts.continuation.resumeFromStageId,
|
|
131
|
-
} : {}),
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const classifiedFailures = new Map<unknown, WorkflowFailure>();
|
|
135
|
-
const classifyExecutorFailure = (error: unknown): WorkflowFailure => {
|
|
136
|
-
const cached = classifiedFailures.get(error);
|
|
137
|
-
if (cached !== undefined) return cached;
|
|
138
|
-
let classified: WorkflowFailure;
|
|
139
|
-
try {
|
|
140
|
-
classified = classifyWorkflowFailure(error);
|
|
141
|
-
} catch {
|
|
142
|
-
classified = classifyWorkflowFailure(new Error(unknownErrorMessage(error)));
|
|
143
|
-
}
|
|
144
|
-
classifiedFailures.set(error, classified);
|
|
145
|
-
return classified;
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
activeStore.recordRunStart(runSnapshot);
|
|
149
|
-
if (!opts.signal) opts.cancellation?.register(runId, ownController);
|
|
150
|
-
opts.onRunStart?.(runSnapshot);
|
|
151
|
-
if (opts.persistence) {
|
|
152
|
-
appendRunStart(opts.persistence, {
|
|
153
|
-
runId,
|
|
154
|
-
name: def.name,
|
|
155
|
-
inputs: resolvedInputs,
|
|
156
|
-
...(runSnapshot.parentRunId !== undefined ? { parentRunId: runSnapshot.parentRunId } : {}),
|
|
157
|
-
...(runSnapshot.parentStageId !== undefined ? { parentStageId: runSnapshot.parentStageId } : {}),
|
|
158
|
-
...(runSnapshot.rootRunId !== undefined ? { rootRunId: runSnapshot.rootRunId } : {}),
|
|
159
|
-
...(runSnapshot.resumedFromRunId !== undefined ? { resumedFromRunId: runSnapshot.resumedFromRunId } : {}),
|
|
160
|
-
...(runSnapshot.resumeFromStageId !== undefined ? { resumeFromStageId: runSnapshot.resumeFromStageId } : {}),
|
|
161
|
-
ts: runSnapshot.startedAt,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const tracker = new GraphFrontierTracker();
|
|
166
|
-
const inputConcurrency = resolveInputConcurrency(def.inputs, resolvedInputs);
|
|
167
|
-
const inputRuntimeDefaults = resolveInputRuntimeDefaults(def, resolvedInputs);
|
|
168
|
-
const workflowInvocationCwd = opts.cwd ?? process.cwd();
|
|
169
|
-
let workflowCwd: string | undefined;
|
|
170
|
-
const resolveWorkflowCwd = (): string => {
|
|
171
|
-
workflowCwd ??= workflowCwdWithInputWorktree(inputRuntimeDefaults, workflowInvocationCwd);
|
|
172
|
-
return workflowCwd;
|
|
173
|
-
};
|
|
174
|
-
const limiter = createRunLimiter(inputConcurrency ?? opts.config?.defaultConcurrency);
|
|
175
|
-
const stageRegistry = opts.stageControlRegistry ?? defaultStageControlRegistry;
|
|
176
|
-
const replayIndex = createContinuationReplayIndex(opts.continuation);
|
|
177
|
-
const scheduler = createStageScheduler({
|
|
178
|
-
runId,
|
|
179
|
-
runSnapshot,
|
|
180
|
-
activeStore,
|
|
181
|
-
tracker,
|
|
182
|
-
stageRegistry: () => stageRegistry,
|
|
183
|
-
});
|
|
184
|
-
ownController.signal.addEventListener(
|
|
185
|
-
"abort",
|
|
186
|
-
() => scheduler.rejectReleaseBarriers(ownController.signal.reason ?? new Error("atomic-workflows: run aborted")),
|
|
187
|
-
{ once: true },
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
const finalizers = createRunFinalizers({
|
|
191
|
-
def,
|
|
192
|
-
runId,
|
|
193
|
-
runSnapshot,
|
|
194
|
-
activeStore,
|
|
195
|
-
opts,
|
|
196
|
-
classifyExecutorFailure,
|
|
197
|
-
drainWorkflowExitCleanups: exit.drainWorkflowExitCleanups,
|
|
198
|
-
});
|
|
199
|
-
const startWorkflowBoundaryStage = createWorkflowBoundaryFactory({
|
|
200
|
-
runId,
|
|
201
|
-
runSnapshot,
|
|
202
|
-
activeStore,
|
|
203
|
-
opts,
|
|
204
|
-
tracker,
|
|
205
|
-
replayIndex,
|
|
206
|
-
registerWorkflowExitCleanup: exit.registerWorkflowExitCleanup,
|
|
207
|
-
workflowExitSkippedReason: exit.workflowExitSkippedReason,
|
|
208
|
-
classifyExecutorFailure,
|
|
209
|
-
});
|
|
210
|
-
const workflowBoundaryReplayCounts = new Map<string, number>();
|
|
211
|
-
const nextWorkflowBoundaryReplayKey = (name: string): string => {
|
|
212
|
-
const next = (workflowBoundaryReplayCounts.get(name) ?? 0) + 1;
|
|
213
|
-
workflowBoundaryReplayCounts.set(name, next);
|
|
214
|
-
return `workflow:${name}:${next}`;
|
|
215
|
-
};
|
|
216
|
-
const stage = createWorkflowStageFactory({
|
|
217
|
-
runId,
|
|
218
|
-
activeStore,
|
|
219
|
-
opts,
|
|
220
|
-
adapters,
|
|
221
|
-
signal: ownController.signal,
|
|
222
|
-
tracker,
|
|
223
|
-
scheduler,
|
|
224
|
-
replayIndex,
|
|
225
|
-
limiter,
|
|
226
|
-
inputRuntimeDefaults,
|
|
227
|
-
workflowInvocationCwd,
|
|
228
|
-
stageRegistry,
|
|
229
|
-
exit,
|
|
230
|
-
classifyExecutorFailure,
|
|
231
|
-
});
|
|
232
|
-
const taskRunners = createWorkflowTaskRunners({
|
|
233
|
-
runId,
|
|
234
|
-
exit,
|
|
235
|
-
tracker,
|
|
236
|
-
inputRuntimeDefaults,
|
|
237
|
-
workflowInvocationCwd,
|
|
238
|
-
stage,
|
|
239
|
-
});
|
|
240
|
-
const workflow = createChildWorkflowRunner({
|
|
241
|
-
runId,
|
|
242
|
-
depth,
|
|
243
|
-
opts,
|
|
244
|
-
exit,
|
|
245
|
-
ownController,
|
|
246
|
-
resolveWorkflowCwd,
|
|
247
|
-
nextWorkflowBoundaryReplayKey,
|
|
248
|
-
startWorkflowBoundaryStage,
|
|
249
|
-
runWorkflow: run,
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
const ctx: WorkflowRunContext<TInputs> = {
|
|
253
|
-
inputs: resolvedInputs as TInputs,
|
|
254
|
-
get cwd() { return resolveWorkflowCwd(); },
|
|
255
|
-
exit: exit.exit,
|
|
256
|
-
ui: buildExitGatedUiContext({
|
|
257
|
-
opts,
|
|
258
|
-
throwIfWorkflowExitSelected: exit.throwIfWorkflowExitSelected,
|
|
259
|
-
baseFromPromptNodes: () => buildPromptNodeUiAdapter({
|
|
260
|
-
runId,
|
|
261
|
-
activeStore,
|
|
262
|
-
opts,
|
|
263
|
-
tracker,
|
|
264
|
-
replayIndex,
|
|
265
|
-
signal: ownController.signal,
|
|
266
|
-
throwIfWorkflowExitSelected: exit.throwIfWorkflowExitSelected,
|
|
267
|
-
registerWorkflowExitCleanup: exit.registerWorkflowExitCleanup,
|
|
268
|
-
workflowExitSkippedReason: exit.workflowExitSkippedReason,
|
|
269
|
-
preserveWorkflowExitSkippedReason: exit.preserveWorkflowExitSkippedReason,
|
|
270
|
-
classifyExecutorFailure,
|
|
271
|
-
}),
|
|
272
|
-
}),
|
|
273
|
-
stage,
|
|
274
|
-
task: taskRunners.task,
|
|
275
|
-
chain: taskRunners.chain,
|
|
276
|
-
parallel: taskRunners.parallel,
|
|
277
|
-
workflow,
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
try {
|
|
281
|
-
if (opts.deferWorkflowStart === true) {
|
|
282
|
-
await nextEventLoopTurn();
|
|
283
|
-
if (ownController.signal.aborted) {
|
|
284
|
-
const selectedExit = findWorkflowExitSignal(ownController.signal.reason, exitScope);
|
|
285
|
-
if (selectedExit !== undefined) return await finalizers.finalizeWorkflowExit(selectedExit);
|
|
286
|
-
const parentExit = parentWorkflowExitAbortReason(ownController.signal.reason);
|
|
287
|
-
if (parentExit !== undefined) return await finalizers.finalizeParentWorkflowExitCancellation(parentExit);
|
|
288
|
-
return finalizeKilled(runId, runSnapshot, activeStore, opts.persistence, opts.onRunEnd);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const rawResult = await def.run(ctx);
|
|
293
|
-
if (ownController.signal.aborted) {
|
|
294
|
-
const selectedExit = findWorkflowExitSignal(ownController.signal.reason, exitScope);
|
|
295
|
-
if (selectedExit !== undefined) return await finalizers.finalizeWorkflowExit(selectedExit);
|
|
296
|
-
const parentExit = parentWorkflowExitAbortReason(ownController.signal.reason);
|
|
297
|
-
if (parentExit !== undefined) return await finalizers.finalizeParentWorkflowExitCancellation(parentExit);
|
|
298
|
-
return finalizeKilled(runId, runSnapshot, activeStore, opts.persistence, opts.onRunEnd);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const result = normalizeWorkflowRunOutput(def.name, rawResult);
|
|
302
|
-
assertWorkflowRunOutputs(def.name, result, def.outputs);
|
|
303
|
-
assertWorkflowCreatedStage(runSnapshot);
|
|
304
|
-
const recorded = activeStore.recordRunEnd(runId, "completed", result);
|
|
305
|
-
appendRunEndWhenRecorded(opts.persistence, recorded, { runId, status: "completed", result, ts: Date.now() });
|
|
306
|
-
return reconcileTerminalRunResult(runId, runSnapshot, activeStore, { status: "completed", result }, opts.onRunEnd);
|
|
307
|
-
} catch (err) {
|
|
308
|
-
const selectedExit = findWorkflowExitSignal(err, exitScope) ?? findWorkflowExitSignal(ownController.signal.reason, exitScope);
|
|
309
|
-
if (selectedExit !== undefined) return await finalizers.finalizeWorkflowExit(selectedExit);
|
|
310
|
-
|
|
311
|
-
if (ownController.signal.aborted) {
|
|
312
|
-
const parentExit = parentWorkflowExitAbortReason(ownController.signal.reason);
|
|
313
|
-
if (parentExit !== undefined) return await finalizers.finalizeParentWorkflowExitCancellation(parentExit);
|
|
314
|
-
return finalizeKilled(runId, runSnapshot, activeStore, opts.persistence, opts.onRunEnd);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const failure = classifyExecutorFailure(err);
|
|
318
|
-
const metadata = selectRunFailureDisposition({
|
|
319
|
-
outerFailure: failure,
|
|
320
|
-
thrownError: err,
|
|
321
|
-
stages: runSnapshot.stages,
|
|
322
|
-
classifyFailure: classifyExecutorFailure,
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
if (metadata.failureDisposition === "terminal_killed") {
|
|
326
|
-
for (const failedStageId of metadata.failedStageIds) scheduler.blockKnownNonTerminalDescendants(failedStageId);
|
|
327
|
-
return finalizeKilledByFailure(runId, runSnapshot, activeStore, opts.persistence, opts.onRunEnd, { ...metadata, resumable: false });
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (metadata.failureDisposition === "active_blocked" && metadata.failedStageId !== undefined && metadata.failureRecoverability === "recoverable") {
|
|
331
|
-
for (const failedStageId of metadata.failedStageIds) scheduler.blockKnownNonTerminalDescendants(failedStageId);
|
|
332
|
-
return recordActiveBlockedFailure(runId, runSnapshot, activeStore, opts.persistence, {
|
|
333
|
-
...metadata,
|
|
334
|
-
failureRecoverability: "recoverable",
|
|
335
|
-
failedStageId: metadata.failedStageId,
|
|
336
|
-
resumable: true,
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const recorded = activeStore.recordRunEnd(runId, "failed", undefined, metadata.errorMessage, metadata);
|
|
341
|
-
appendRunEndWhenRecorded(opts.persistence, recorded, {
|
|
342
|
-
runId,
|
|
343
|
-
status: "failed",
|
|
344
|
-
error: metadata.errorMessage,
|
|
345
|
-
failureKind: metadata.failureKind,
|
|
346
|
-
...(metadata.failureCode !== undefined ? { failureCode: metadata.failureCode } : {}),
|
|
347
|
-
...(metadata.failureRecoverability !== undefined ? { failureRecoverability: metadata.failureRecoverability } : {}),
|
|
348
|
-
...(metadata.failureDisposition !== undefined ? { failureDisposition: metadata.failureDisposition } : {}),
|
|
349
|
-
failureMessage: metadata.failureMessage,
|
|
350
|
-
...(metadata.failedStageId !== undefined ? { failedStageId: metadata.failedStageId } : {}),
|
|
351
|
-
resumable: metadata.resumable,
|
|
352
|
-
...(metadata.retryAfterMs !== undefined ? { retryAfterMs: metadata.retryAfterMs } : {}),
|
|
353
|
-
ts: Date.now(),
|
|
354
|
-
});
|
|
355
|
-
return reconcileTerminalRunResult(runId, runSnapshot, activeStore, { status: "failed", error: metadata.errorMessage }, opts.onRunEnd);
|
|
356
|
-
} finally {
|
|
357
|
-
opts.cancellation?.unregister(runId);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
1
|
+
export { run } from "../../engine/run.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RunSnapshot, StageSnapshot } from "../../shared/store-types.js";
|
|
2
2
|
import type { Store } from "../../shared/store.js";
|
|
3
|
-
import type { GraphFrontierTracker } from "
|
|
3
|
+
import type { GraphFrontierTracker } from "../../engine/graph-inference.js";
|
|
4
4
|
import type { StageControlRegistry } from "./stage-control-registry.js";
|
|
5
5
|
|
|
6
6
|
interface ReleaseBarrier {
|
|
@@ -112,10 +112,7 @@ export function createTrackedStageCaller(input: {
|
|
|
112
112
|
runtime.activeStore.recordStageStart(runtime.runId, runtime.stageSnapshot);
|
|
113
113
|
runtime.appendStageStartOnce();
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
const mcpDeny = input.options?.mcp?.deny ?? null;
|
|
117
|
-
const hasMcpScope = mcpAllow !== null || mcpDeny !== null;
|
|
118
|
-
if (runtime.opts.mcp && hasMcpScope) runtime.opts.mcp.setScope(runtime.stageId, mcpAllow, mcpDeny);
|
|
115
|
+
runtime.mcpScope.apply();
|
|
119
116
|
|
|
120
117
|
try {
|
|
121
118
|
const abortSession = (): void => {
|
|
@@ -183,7 +180,7 @@ export function createTrackedStageCaller(input: {
|
|
|
183
180
|
}
|
|
184
181
|
throw err;
|
|
185
182
|
} finally {
|
|
186
|
-
|
|
183
|
+
runtime.mcpScope.clear();
|
|
187
184
|
runtime.captureStageSessionMeta();
|
|
188
185
|
runtime.finalizeStageSnapshot();
|
|
189
186
|
if (runtime.state.stageClosedByWorkflowExit || runtime.exit.currentWorkflowExitAbortReason() !== undefined) {
|
|
@@ -7,10 +7,11 @@ import { appendStageEnd, appendStageStart } from "../../shared/persistence-sessi
|
|
|
7
7
|
import { elapsedStageMs } from "../../shared/timing.js";
|
|
8
8
|
import type { WorkflowFailure } from "../../shared/workflow-failures.js";
|
|
9
9
|
import type { ConcurrencyLimiter } from "../shared/concurrency.js";
|
|
10
|
-
import type { GraphFrontierTracker } from "
|
|
10
|
+
import type { GraphFrontierTracker } from "../../engine/graph-inference.js";
|
|
11
|
+
import type { EngineStageRuntimeOptions } from "../../engine/options.js";
|
|
11
12
|
import { createStageContext as createInnerStageContext, type InternalStageContext, type StageAdapters } from "./stage-runner.js";
|
|
12
13
|
import type { StageControlRegistry } from "./stage-control-registry.js";
|
|
13
|
-
import type {
|
|
14
|
+
import type { ParallelFailFastScope } from "./executor-types.js";
|
|
14
15
|
import type { WorkflowExitManager } from "./executor-exit-manager.js";
|
|
15
16
|
import type { ContinuationReplayIndex } from "./executor-continuation.js";
|
|
16
17
|
import { sameStringSet } from "./executor-continuation.js";
|
|
@@ -19,7 +20,7 @@ import { isTerminalStage } from "./executor-scheduler.js";
|
|
|
19
20
|
import { stageReplayFields } from "./executor-lifecycle.js";
|
|
20
21
|
import { askUserQuestionToolEvent, toolResultHasChatAnswer } from "./executor-hil.js";
|
|
21
22
|
import { createReplayStageContext } from "./executor-stage-replay.js";
|
|
22
|
-
import type { LiveStageMutableState, LiveStageRuntime, StageContextWithMeta } from "./executor-stage-types.js";
|
|
23
|
+
import type { LiveStageMutableState, LiveStageRuntime, StageContextWithMeta, StageMcpScope } from "./executor-stage-types.js";
|
|
23
24
|
import { createStageControlHandle } from "./executor-stage-control.js";
|
|
24
25
|
import { createTrackedStageCaller } from "./executor-stage-call.js";
|
|
25
26
|
import { createStageContext } from "./executor-stage-context.js";
|
|
@@ -28,7 +29,7 @@ import { stageOptionsWithGitWorktree, stageOptionsWithInputDefaults } from "./ex
|
|
|
28
29
|
export function createWorkflowStageFactory(input: {
|
|
29
30
|
readonly runId: string;
|
|
30
31
|
readonly activeStore: Store;
|
|
31
|
-
readonly opts:
|
|
32
|
+
readonly opts: EngineStageRuntimeOptions;
|
|
32
33
|
readonly adapters: StageAdapters;
|
|
33
34
|
readonly signal: AbortSignal;
|
|
34
35
|
readonly tracker: GraphFrontierTracker;
|
|
@@ -40,6 +41,7 @@ export function createWorkflowStageFactory(input: {
|
|
|
40
41
|
readonly stageRegistry: StageControlRegistry;
|
|
41
42
|
readonly exit: WorkflowExitManager;
|
|
42
43
|
readonly classifyExecutorFailure: (error: unknown) => WorkflowFailure;
|
|
44
|
+
readonly createMcpScope: (stageId: string, options: StageOptions | undefined) => StageMcpScope;
|
|
43
45
|
}): (name: string, options?: StageOptions, stageFailFastScope?: ParallelFailFastScope) => StageContextWithMeta {
|
|
44
46
|
return (name: string, options?: StageOptions, stageFailFastScope?: ParallelFailFastScope): StageContextWithMeta => {
|
|
45
47
|
input.exit.throwIfWorkflowExitSelected();
|
|
@@ -287,6 +289,7 @@ export function createWorkflowStageFactory(input: {
|
|
|
287
289
|
signal: input.signal,
|
|
288
290
|
exit: input.exit,
|
|
289
291
|
classifyExecutorFailure: input.classifyExecutorFailure,
|
|
292
|
+
mcpScope: input.createMcpScope(stageId, options),
|
|
290
293
|
...(stageFailFastScope !== undefined ? { stageFailFastScope } : {}),
|
|
291
294
|
state,
|
|
292
295
|
unregisterStageHandle: () => {},
|
|
@@ -317,6 +320,11 @@ export function createWorkflowStageFactory(input: {
|
|
|
317
320
|
const blockedBy = input.scheduler.blockingAncestorFor(stageSnapshot);
|
|
318
321
|
if (blockedBy !== undefined) input.scheduler.blockStageUntilCascadeRelease(stageSnapshot, blockedBy);
|
|
319
322
|
|
|
323
|
+
// Parallel fail-fast and workflow-exit cleanup can both target a live stage.
|
|
324
|
+
// The first terminal path owns the snapshot: finalization unregisters
|
|
325
|
+
// workflow-exit cleanup and removes the stage from the fail-fast active set.
|
|
326
|
+
// Later paths must not overwrite the terminal skippedReason; they only abort
|
|
327
|
+
// and release idempotent live handles.
|
|
320
328
|
const skipForParallelFailFast = (): void => {
|
|
321
329
|
if (isTerminalStage(stageSnapshot)) return;
|
|
322
330
|
markSkippedForParallelFailFast();
|
|
@@ -2,9 +2,10 @@ import type { StageSnapshot } from "../../shared/store-types.js";
|
|
|
2
2
|
import type { Store } from "../../shared/store.js";
|
|
3
3
|
import { appendStageEnd, appendStageStart } from "../../shared/persistence-session-entries.js";
|
|
4
4
|
import { elapsedStageMs } from "../../shared/timing.js";
|
|
5
|
-
import type { GraphFrontierTracker } from "
|
|
5
|
+
import type { GraphFrontierTracker } from "../../engine/graph-inference.js";
|
|
6
|
+
import type { EngineStageRuntimeOptions } from "../../engine/options.js";
|
|
6
7
|
import type { InternalStageContext } from "./stage-runner.js";
|
|
7
|
-
import type {
|
|
8
|
+
import type { WorkflowExitCleanup } from "./executor-types.js";
|
|
8
9
|
import { stageReplayFields } from "./executor-lifecycle.js";
|
|
9
10
|
|
|
10
11
|
export function createReplayStageContext(input: {
|
|
@@ -14,7 +15,7 @@ export function createReplayStageContext(input: {
|
|
|
14
15
|
readonly stageSnapshot: StageSnapshot;
|
|
15
16
|
readonly replaySource: StageSnapshot;
|
|
16
17
|
readonly activeStore: Store;
|
|
17
|
-
readonly opts:
|
|
18
|
+
readonly opts: EngineStageRuntimeOptions;
|
|
18
19
|
readonly tracker: GraphFrontierTracker;
|
|
19
20
|
readonly registerWorkflowExitCleanup: (stageId: string, cleanup: WorkflowExitCleanup) => () => void;
|
|
20
21
|
readonly workflowExitSkippedReason: (reason?: string) => string;
|