@bastani/atomic 0.9.41-alpha.1 → 0.9.41-alpha.3
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 +39 -0
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +3 -3
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +8 -0
- package/dist/builtin/workflows/builtin/adversarial-verification.js +2 -2
- package/dist/builtin/workflows/builtin/{chunk-qjqn389g.js → chunk-2jfst7e4.js} +72 -10
- package/dist/builtin/workflows/builtin/{chunk-4bwtzyjq.js → chunk-49kkbdpr.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-qdd897wm.js → chunk-apagcs4r.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-454hz1qt.js → chunk-dcxscfnb.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-bjva9j5k.js → chunk-hx8v4p97.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-85mx6wcf.js → chunk-k5q3t7je.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-8kkv04hz.js → chunk-n2gkzkty.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-y45tkftg.js → chunk-txbc93t6.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-x0vvjyzg.js → chunk-w4xp1w1f.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-5eh0brtd.js → chunk-z3pajrfs.js} +1 -1
- package/dist/builtin/workflows/builtin/classify-and-act.js +2 -2
- package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +2 -2
- package/dist/builtin/workflows/builtin/generate-and-filter.js +2 -2
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +10 -10
- package/dist/builtin/workflows/builtin/loop-until-done.js +2 -2
- package/dist/builtin/workflows/builtin/open-claude-design.js +2 -2
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/builtin/tournament.js +2 -2
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +511 -28
- package/dist/builtin/workflows/src/index.js +582 -99
- package/dist/core/compaction/compaction-runner.d.ts.map +1 -1
- package/dist/core/compaction/compaction-runner.js +1 -0
- package/dist/core/compaction/compaction-runner.js.map +1 -1
- package/dist/core/model-config.d.ts +28 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/provider-composer-internal.d.ts +2 -1
- package/dist/core/provider-composer-internal.d.ts.map +1 -1
- package/dist/core/provider-composer-internal.js +8 -6
- package/dist/core/provider-composer-internal.js.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js +2 -0
- package/dist/core/usage-totals.js.map +1 -1
- package/docs/getting-started/installation.md +19 -1
- package/docs/models-configuration.md +9 -0
- package/docs/models.md +3 -1
- package/docs/providers.md +1 -1
- package/docs/quickstart.md +1 -1
- package/docs/windows.md +1 -1
- package/docs/workflows/authoring.md +1 -1
- package/npm-shrinkwrap.json +67 -54
- package/package.json +6 -6
- package/schemas/models.schema.json +21 -0
|
@@ -11,7 +11,7 @@ ${KEEP_CONTEXT_CLOSE_TAG}`;
|
|
|
11
11
|
}
|
|
12
12
|
// dist/builtin/workflows/src/authoring/workflow.ts
|
|
13
13
|
import { basename } from "node:path";
|
|
14
|
-
import { fileURLToPath } from "node:url";
|
|
14
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
15
15
|
|
|
16
16
|
// dist/builtin/workflows/src/shared/budget.ts
|
|
17
17
|
function enforceDurationBudget(reading, budget, options = {}) {
|
|
@@ -87,6 +87,89 @@ function resolve_budget(layers) {
|
|
|
87
87
|
var DEFAULT_WORKFLOW_HEARTBEAT_INTERVAL_MINUTES = 15;
|
|
88
88
|
var WORKFLOW_HEARTBEAT_CUSTOM_TYPE = "workflows:workflow-heartbeat";
|
|
89
89
|
|
|
90
|
+
// dist/builtin/workflows/src/runs/shared/prompt-callsite.ts
|
|
91
|
+
import { fileURLToPath } from "node:url";
|
|
92
|
+
var PACKAGED_WORKFLOW_RUNTIME_ROOTS = ["/dist/builtin/workflows/src/"];
|
|
93
|
+
function normalizeSlashes(path) {
|
|
94
|
+
return path.replace(/\\/g, "/");
|
|
95
|
+
}
|
|
96
|
+
function normalizeStackPath(framePath) {
|
|
97
|
+
let normalized = framePath;
|
|
98
|
+
if (normalized.startsWith("file://")) {
|
|
99
|
+
try {
|
|
100
|
+
normalized = fileURLToPath(normalized);
|
|
101
|
+
} catch {
|
|
102
|
+
try {
|
|
103
|
+
normalized = decodeURIComponent(new URL(normalized).pathname);
|
|
104
|
+
} catch {}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
normalized = normalizeSlashes(normalized).replace(/^\/([A-Za-z]:\/)/, "$1");
|
|
108
|
+
return normalized;
|
|
109
|
+
}
|
|
110
|
+
function currentModuleRuntimeRoot() {
|
|
111
|
+
const modulePath = normalizeStackPath(fileURLToPath(import.meta.url));
|
|
112
|
+
const markers = ["packages/workflows/src/", ...PACKAGED_WORKFLOW_RUNTIME_ROOTS.map((root) => root.slice(1))];
|
|
113
|
+
for (const marker of markers) {
|
|
114
|
+
const index = modulePath.indexOf(marker);
|
|
115
|
+
if (index >= 0)
|
|
116
|
+
return modulePath.slice(0, index + marker.length);
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
var CURRENT_WORKFLOW_RUNTIME_ROOT = currentModuleRuntimeRoot();
|
|
121
|
+
function isWorkflowRuntimeFrame(normalizedPath) {
|
|
122
|
+
const path = normalizeSlashes(normalizedPath);
|
|
123
|
+
if (path.startsWith("packages/workflows/src/"))
|
|
124
|
+
return true;
|
|
125
|
+
if (CURRENT_WORKFLOW_RUNTIME_ROOT !== undefined && path.startsWith(CURRENT_WORKFLOW_RUNTIME_ROOT)) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
const comparable = path.startsWith("/") ? path : `/${path}`;
|
|
129
|
+
return PACKAGED_WORKFLOW_RUNTIME_ROOTS.some((runtimeRoot) => comparable.includes(runtimeRoot));
|
|
130
|
+
}
|
|
131
|
+
function parsePromptStackFrame(stackLine) {
|
|
132
|
+
const line = stackLine.trim();
|
|
133
|
+
if (line.length === 0)
|
|
134
|
+
return;
|
|
135
|
+
if (line.includes("node:internal") || line.includes("bun:") || line.includes("(native:"))
|
|
136
|
+
return;
|
|
137
|
+
const match = line.match(/(\S+):(\d+):(\d+)\)?$/);
|
|
138
|
+
if (!match)
|
|
139
|
+
return;
|
|
140
|
+
const [, rawFramePath, lineNumber, columnNumber] = match;
|
|
141
|
+
if (rawFramePath === undefined || lineNumber === undefined || columnNumber === undefined)
|
|
142
|
+
return;
|
|
143
|
+
const normalizedPath = normalizeStackPath(rawFramePath.replace(/^\(/, ""));
|
|
144
|
+
return { normalizedPath, lineNumber, columnNumber };
|
|
145
|
+
}
|
|
146
|
+
function normalizedPromptCallsiteFrame(stackLine) {
|
|
147
|
+
const frame = parsePromptStackFrame(stackLine);
|
|
148
|
+
if (frame === undefined)
|
|
149
|
+
return;
|
|
150
|
+
if (isWorkflowRuntimeFrame(frame.normalizedPath))
|
|
151
|
+
return;
|
|
152
|
+
return `${frame.normalizedPath}:${frame.lineNumber}:${frame.columnNumber}`;
|
|
153
|
+
}
|
|
154
|
+
function selectPromptCallsiteFrame(stack) {
|
|
155
|
+
return stack.split(`
|
|
156
|
+
`).slice(1).map(normalizedPromptCallsiteFrame).find((candidate) => candidate !== undefined);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// dist/builtin/workflows/src/shared/workflow-source.ts
|
|
160
|
+
var WORKFLOW_SOURCES = new WeakMap;
|
|
161
|
+
var OWN_MODULE_PATH = normalizeStackPath(import.meta.url);
|
|
162
|
+
function isWorkflowRuntimeModule(path) {
|
|
163
|
+
const normalized = normalizeStackPath(path);
|
|
164
|
+
return normalized === OWN_MODULE_PATH || isWorkflowRuntimeFrame(normalized);
|
|
165
|
+
}
|
|
166
|
+
function recordWorkflowSource(definition, path) {
|
|
167
|
+
WORKFLOW_SOURCES.set(definition, path);
|
|
168
|
+
}
|
|
169
|
+
function workflowSource(definition) {
|
|
170
|
+
return WORKFLOW_SOURCES.get(definition);
|
|
171
|
+
}
|
|
172
|
+
|
|
90
173
|
// dist/builtin/workflows/src/workflows/identity.ts
|
|
91
174
|
function normalizeWorkflowName(name) {
|
|
92
175
|
if (!name || typeof name !== "string") {
|
|
@@ -123,7 +206,7 @@ function stackFilePath(line) {
|
|
|
123
206
|
if (!rawPath.startsWith("file://"))
|
|
124
207
|
return rawPath;
|
|
125
208
|
try {
|
|
126
|
-
return
|
|
209
|
+
return fileURLToPath2(rawPath);
|
|
127
210
|
} catch {
|
|
128
211
|
return;
|
|
129
212
|
}
|
|
@@ -134,8 +217,10 @@ function isWorkflowAuthoringImplementationFrame(filePath) {
|
|
|
134
217
|
return false;
|
|
135
218
|
return normalized.includes("/packages/workflows/") || normalized.includes("/dist/builtin/workflows/") || normalized.includes("/.atomic/agent/extensions/workflows/");
|
|
136
219
|
}
|
|
137
|
-
function
|
|
138
|
-
const
|
|
220
|
+
function callerSourcePath(entry) {
|
|
221
|
+
const capture = new Error;
|
|
222
|
+
Error.captureStackTrace(capture, entry);
|
|
223
|
+
const stack = capture.stack;
|
|
139
224
|
if (stack === undefined)
|
|
140
225
|
return;
|
|
141
226
|
for (const line of stack.split(`
|
|
@@ -145,14 +230,18 @@ function workflowNameFromCaller() {
|
|
|
145
230
|
continue;
|
|
146
231
|
if (isWorkflowAuthoringImplementationFrame(filePath))
|
|
147
232
|
continue;
|
|
148
|
-
|
|
149
|
-
if (base.length > 0)
|
|
150
|
-
return base;
|
|
233
|
+
return isWorkflowRuntimeModule(filePath) ? undefined : filePath;
|
|
151
234
|
}
|
|
152
235
|
return;
|
|
153
236
|
}
|
|
154
|
-
function
|
|
155
|
-
|
|
237
|
+
function workflowNameFromSourcePath(filePath) {
|
|
238
|
+
if (filePath === undefined)
|
|
239
|
+
return;
|
|
240
|
+
const base = basename(filePath.replace(/\\/g, "/")).replace(/\.[cm]?[jt]sx?$/, "");
|
|
241
|
+
return base.length > 0 ? base : undefined;
|
|
242
|
+
}
|
|
243
|
+
function resolveWorkflowName(name, sourcePath) {
|
|
244
|
+
const resolved = name ?? workflowNameFromSourcePath(sourcePath);
|
|
156
245
|
if (resolved === undefined) {
|
|
157
246
|
throw new TypeError("workflow: name must be provided when caller filename cannot be inferred");
|
|
158
247
|
}
|
|
@@ -188,7 +277,8 @@ function workflow(spec) {
|
|
|
188
277
|
throw new TypeError("workflow: heartbeatIntervalMinutes must be a non-negative finite number");
|
|
189
278
|
}
|
|
190
279
|
assertWorkflowBudget(spec.budget, "workflow: budget");
|
|
191
|
-
const
|
|
280
|
+
const source = callerSourcePath(workflow);
|
|
281
|
+
const name = resolveWorkflowName(spec.name, source);
|
|
192
282
|
const normalizedName = normalizeWorkflowName(name);
|
|
193
283
|
requireNonEmptyString(normalizedName, "normalized name");
|
|
194
284
|
const frozenInputs = freezeSchemaMap(spec.inputs ?? {});
|
|
@@ -210,6 +300,8 @@ function workflow(spec) {
|
|
|
210
300
|
run
|
|
211
301
|
};
|
|
212
302
|
const branded = stampWorkflowDefinition(definition);
|
|
303
|
+
if (source !== undefined)
|
|
304
|
+
recordWorkflowSource(branded, source);
|
|
213
305
|
return Object.freeze(branded);
|
|
214
306
|
}
|
|
215
307
|
// dist/builtin/workflows/src/durable/journal/conformance.ts
|
|
@@ -5956,75 +6048,6 @@ function buildStagePromptAdapter(id, kind, args, createdAt) {
|
|
|
5956
6048
|
};
|
|
5957
6049
|
}
|
|
5958
6050
|
|
|
5959
|
-
// dist/builtin/workflows/src/runs/shared/prompt-callsite.ts
|
|
5960
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
5961
|
-
var PACKAGED_WORKFLOW_RUNTIME_ROOTS = ["/dist/builtin/workflows/src/"];
|
|
5962
|
-
function normalizeSlashes(path) {
|
|
5963
|
-
return path.replace(/\\/g, "/");
|
|
5964
|
-
}
|
|
5965
|
-
function normalizeStackPath(framePath) {
|
|
5966
|
-
let normalized = framePath;
|
|
5967
|
-
if (normalized.startsWith("file://")) {
|
|
5968
|
-
try {
|
|
5969
|
-
normalized = fileURLToPath2(normalized);
|
|
5970
|
-
} catch {
|
|
5971
|
-
try {
|
|
5972
|
-
normalized = decodeURIComponent(new URL(normalized).pathname);
|
|
5973
|
-
} catch {}
|
|
5974
|
-
}
|
|
5975
|
-
}
|
|
5976
|
-
normalized = normalizeSlashes(normalized).replace(/^\/([A-Za-z]:\/)/, "$1");
|
|
5977
|
-
return normalized;
|
|
5978
|
-
}
|
|
5979
|
-
function currentModuleRuntimeRoot() {
|
|
5980
|
-
const modulePath = normalizeStackPath(fileURLToPath2(import.meta.url));
|
|
5981
|
-
const markers = ["packages/workflows/src/", ...PACKAGED_WORKFLOW_RUNTIME_ROOTS.map((root) => root.slice(1))];
|
|
5982
|
-
for (const marker of markers) {
|
|
5983
|
-
const index = modulePath.indexOf(marker);
|
|
5984
|
-
if (index >= 0)
|
|
5985
|
-
return modulePath.slice(0, index + marker.length);
|
|
5986
|
-
}
|
|
5987
|
-
return;
|
|
5988
|
-
}
|
|
5989
|
-
var CURRENT_WORKFLOW_RUNTIME_ROOT = currentModuleRuntimeRoot();
|
|
5990
|
-
function isWorkflowRuntimeFrame(normalizedPath) {
|
|
5991
|
-
const path = normalizeSlashes(normalizedPath);
|
|
5992
|
-
if (path.startsWith("packages/workflows/src/"))
|
|
5993
|
-
return true;
|
|
5994
|
-
if (CURRENT_WORKFLOW_RUNTIME_ROOT !== undefined && path.startsWith(CURRENT_WORKFLOW_RUNTIME_ROOT)) {
|
|
5995
|
-
return true;
|
|
5996
|
-
}
|
|
5997
|
-
const comparable = path.startsWith("/") ? path : `/${path}`;
|
|
5998
|
-
return PACKAGED_WORKFLOW_RUNTIME_ROOTS.some((runtimeRoot) => comparable.includes(runtimeRoot));
|
|
5999
|
-
}
|
|
6000
|
-
function parsePromptStackFrame(stackLine) {
|
|
6001
|
-
const line = stackLine.trim();
|
|
6002
|
-
if (line.length === 0)
|
|
6003
|
-
return;
|
|
6004
|
-
if (line.includes("node:internal") || line.includes("bun:") || line.includes("(native:"))
|
|
6005
|
-
return;
|
|
6006
|
-
const match = line.match(/(\S+):(\d+):(\d+)\)?$/);
|
|
6007
|
-
if (!match)
|
|
6008
|
-
return;
|
|
6009
|
-
const [, rawFramePath, lineNumber, columnNumber] = match;
|
|
6010
|
-
if (rawFramePath === undefined || lineNumber === undefined || columnNumber === undefined)
|
|
6011
|
-
return;
|
|
6012
|
-
const normalizedPath = normalizeStackPath(rawFramePath.replace(/^\(/, ""));
|
|
6013
|
-
return { normalizedPath, lineNumber, columnNumber };
|
|
6014
|
-
}
|
|
6015
|
-
function normalizedPromptCallsiteFrame(stackLine) {
|
|
6016
|
-
const frame = parsePromptStackFrame(stackLine);
|
|
6017
|
-
if (frame === undefined)
|
|
6018
|
-
return;
|
|
6019
|
-
if (isWorkflowRuntimeFrame(frame.normalizedPath))
|
|
6020
|
-
return;
|
|
6021
|
-
return `${frame.normalizedPath}:${frame.lineNumber}:${frame.columnNumber}`;
|
|
6022
|
-
}
|
|
6023
|
-
function selectPromptCallsiteFrame(stack) {
|
|
6024
|
-
return stack.split(`
|
|
6025
|
-
`).slice(1).map(normalizedPromptCallsiteFrame).find((candidate) => candidate !== undefined);
|
|
6026
|
-
}
|
|
6027
|
-
|
|
6028
6051
|
// dist/builtin/workflows/src/shared/resume-continuation.ts
|
|
6029
6052
|
var RESUME_CONTINUATION_PROMPT = "Continue where you left off. If you believe you are finished with your original task (or a redefined task if the user told you), stop.";
|
|
6030
6053
|
|
|
@@ -14693,6 +14716,7 @@ function createWorkflowExitManager(input) {
|
|
|
14693
14716
|
...outputSnapshot !== undefined ? { outputSnapshot } : {},
|
|
14694
14717
|
...validationError !== undefined ? { validationError } : {}
|
|
14695
14718
|
}));
|
|
14719
|
+
input.onExitSelected?.(selectedExit);
|
|
14696
14720
|
input.controller.abort(selectedExit);
|
|
14697
14721
|
runWorkflowExitCleanups(reason);
|
|
14698
14722
|
throw selectedExit;
|
|
@@ -15914,7 +15938,7 @@ function compareDraftSourceOrder(left, right) {
|
|
|
15914
15938
|
function runTopologyFor(drafts, tools) {
|
|
15915
15939
|
return drafts.find((draft) => draft.topology?.run !== undefined)?.topology?.run ?? tools.find((checkpoint) => checkpoint.topology?.run !== undefined)?.topology?.run;
|
|
15916
15940
|
}
|
|
15917
|
-
function validateRunGroups(grouped, rootRunId, tools, checkpoints) {
|
|
15941
|
+
function validateRunGroups(grouped, rootRunId, tools, checkpoints, allowPendingChildren = false) {
|
|
15918
15942
|
const toolsFor = (runId) => tools.filter((checkpoint) => (checkpoint.topology?.run?.runId ?? rootRunId) === runId);
|
|
15919
15943
|
const owners = new Map;
|
|
15920
15944
|
const syntheticChildIds = new Set;
|
|
@@ -15926,6 +15950,11 @@ function validateRunGroups(grouped, rootRunId, tools, checkpoints) {
|
|
|
15926
15950
|
if (childRunId === parentRunId || owners.has(childRunId))
|
|
15927
15951
|
return false;
|
|
15928
15952
|
if (!grouped.has(childRunId)) {
|
|
15953
|
+
if (allowPendingChildren && isPendingChildBoundary(draft, parentRunId, childRunId, rootRunId) && !childScopedEvidenceExists(checkpoints, draft.replayKey, childRunId)) {
|
|
15954
|
+
syntheticChildIds.add(childRunId);
|
|
15955
|
+
owners.set(childRunId, draft);
|
|
15956
|
+
continue;
|
|
15957
|
+
}
|
|
15929
15958
|
if (!isSyntheticExitedChild(draft, parentRunId, childRunId, rootRunId) || childScopedEvidenceExists(checkpoints, draft.replayKey, childRunId))
|
|
15930
15959
|
return false;
|
|
15931
15960
|
syntheticChildIds.add(childRunId);
|
|
@@ -15958,6 +15987,10 @@ function validateRunGroups(grouped, rootRunId, tools, checkpoints) {
|
|
|
15958
15987
|
}
|
|
15959
15988
|
return true;
|
|
15960
15989
|
}
|
|
15990
|
+
function isPendingChildBoundary(draft, parentRunId, childRunId, rootRunId) {
|
|
15991
|
+
const boundary = draft.topology?.boundary;
|
|
15992
|
+
return workflowChildFromDraft(draft) === undefined && boundary?.event === "start" && boundary.status === "running" && boundary.child.runId === childRunId && boundary.child.parentRunId === parentRunId && boundary.child.parentStageId === draft.topology?.stageId && boundary.child.rootRunId === rootRunId;
|
|
15993
|
+
}
|
|
15961
15994
|
function isSyntheticExitedChild(draft, parentRunId, childRunId, rootRunId) {
|
|
15962
15995
|
const child = workflowChildFromDraft(draft);
|
|
15963
15996
|
const boundary = draft.topology?.boundary;
|
|
@@ -16373,11 +16406,17 @@ function runSnapshotsFromCheckpoints(checkpoints, rootRunId, rootRunName, fallba
|
|
|
16373
16406
|
retainReachableRunGroups(grouped, rootRunId);
|
|
16374
16407
|
if (policy.failOnUnreachable && grouped.size !== groupedCount)
|
|
16375
16408
|
return [];
|
|
16376
|
-
if (!validateRunGroups(grouped, rootRunId, toolCheckpoints, checkpoints))
|
|
16409
|
+
if (!validateRunGroups(grouped, rootRunId, toolCheckpoints, checkpoints, policy.retainActive))
|
|
16377
16410
|
return [];
|
|
16378
16411
|
const syntheticChildren = [];
|
|
16412
|
+
const pendingChildren = [];
|
|
16379
16413
|
for (const [parentRunId, runDrafts] of grouped) {
|
|
16380
16414
|
for (const draft of runDrafts) {
|
|
16415
|
+
const pendingChildRunId = childRunIdFromDraft(draft);
|
|
16416
|
+
if (policy.retainActive && pendingChildRunId !== undefined && !grouped.has(pendingChildRunId) && isPendingChildBoundary(draft, parentRunId, pendingChildRunId, rootRunId)) {
|
|
16417
|
+
pendingChildren.push({ parentRunId, owner: draft });
|
|
16418
|
+
continue;
|
|
16419
|
+
}
|
|
16381
16420
|
const child = workflowChildFromDraft(draft);
|
|
16382
16421
|
if (child?.exited !== true || grouped.has(child.runId))
|
|
16383
16422
|
continue;
|
|
@@ -16486,6 +16525,28 @@ function runSnapshotsFromCheckpoints(checkpoints, rootRunId, rootRunName, fallba
|
|
|
16486
16525
|
resumable: false
|
|
16487
16526
|
});
|
|
16488
16527
|
}
|
|
16528
|
+
for (const { parentRunId, owner } of pendingChildren) {
|
|
16529
|
+
if (!emittedRunIds.has(parentRunId))
|
|
16530
|
+
return [];
|
|
16531
|
+
const topology = owner.topology;
|
|
16532
|
+
const boundary = topology.boundary;
|
|
16533
|
+
const parentStageId = idMaps.get(parentRunId)?.get(topology.stageId);
|
|
16534
|
+
if (parentStageId === undefined)
|
|
16535
|
+
return [];
|
|
16536
|
+
runs.push({
|
|
16537
|
+
id: boundary.child.runId,
|
|
16538
|
+
name: boundary.child.runName,
|
|
16539
|
+
inputs: {},
|
|
16540
|
+
status: "running",
|
|
16541
|
+
stages: [],
|
|
16542
|
+
toolNodes: [],
|
|
16543
|
+
startedAt: owner.startedAt ?? owner.firstCompletedAt,
|
|
16544
|
+
parentRunId,
|
|
16545
|
+
parentStageId,
|
|
16546
|
+
rootRunId: boundary.child.rootRunId,
|
|
16547
|
+
resumable: false
|
|
16548
|
+
});
|
|
16549
|
+
}
|
|
16489
16550
|
return runs;
|
|
16490
16551
|
}
|
|
16491
16552
|
function stageSnapshotFromDraft(draft, id, parentIds) {
|
|
@@ -16801,6 +16862,402 @@ function deferStageUntilRunRelease(input) {
|
|
|
16801
16862
|
};
|
|
16802
16863
|
}
|
|
16803
16864
|
|
|
16865
|
+
// dist/builtin/workflows/src/engine/run-rejection-boundary.ts
|
|
16866
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
|
|
16867
|
+
import { inspect } from "node:util";
|
|
16868
|
+
var EVENT = "unhandledRejection";
|
|
16869
|
+
var BOUNDARY_KEY = Symbol.for("atomic-workflows/run-rejection-boundary@5");
|
|
16870
|
+
var FLAG = "--unhandled-rejections";
|
|
16871
|
+
var MAX_CAUSE_DEPTH2 = 8;
|
|
16872
|
+
var MAX_PRIMITIVES_PER_RUN = 64;
|
|
16873
|
+
var MAX_STOP_STRINGS = 64;
|
|
16874
|
+
var ENDED_RUN_GRACE_MS = 30000;
|
|
16875
|
+
var NATIVE_REPORTING_MODES = new Set(["throw", "warn-with-error-code"]);
|
|
16876
|
+
function boundaryBag() {
|
|
16877
|
+
return globalThis;
|
|
16878
|
+
}
|
|
16879
|
+
function sharedBoundary() {
|
|
16880
|
+
const bag = boundaryBag();
|
|
16881
|
+
const existing = bag[BOUNDARY_KEY];
|
|
16882
|
+
if (existing !== undefined && existing.version === 5)
|
|
16883
|
+
return existing;
|
|
16884
|
+
const created = {
|
|
16885
|
+
version: 5,
|
|
16886
|
+
store: new AsyncLocalStorage3,
|
|
16887
|
+
owners: new WeakMap,
|
|
16888
|
+
promises: new WeakMap,
|
|
16889
|
+
scopes: new Set,
|
|
16890
|
+
runs: new Map,
|
|
16891
|
+
ended: new Map,
|
|
16892
|
+
stops: new Set,
|
|
16893
|
+
listener: undefined
|
|
16894
|
+
};
|
|
16895
|
+
bag[BOUNDARY_KEY] = created;
|
|
16896
|
+
return created;
|
|
16897
|
+
}
|
|
16898
|
+
function isObject(value) {
|
|
16899
|
+
return typeof value === "object" && value !== null || typeof value === "function";
|
|
16900
|
+
}
|
|
16901
|
+
function isPrimitive(value) {
|
|
16902
|
+
return !isObject(value);
|
|
16903
|
+
}
|
|
16904
|
+
function safeField3(value, key) {
|
|
16905
|
+
try {
|
|
16906
|
+
return value[key];
|
|
16907
|
+
} catch {
|
|
16908
|
+
return;
|
|
16909
|
+
}
|
|
16910
|
+
}
|
|
16911
|
+
function strongerEffect(left, right) {
|
|
16912
|
+
return left === "fail-run" || right === "fail-run" ? "fail-run" : "ignore";
|
|
16913
|
+
}
|
|
16914
|
+
function addAttribution(into, scope, effect) {
|
|
16915
|
+
into.set(scope, strongerEffect(into.get(scope), effect));
|
|
16916
|
+
}
|
|
16917
|
+
function recordedOwners(boundary, reason) {
|
|
16918
|
+
const owners = new Map;
|
|
16919
|
+
let stopped = false;
|
|
16920
|
+
const seen = new Set;
|
|
16921
|
+
const pending = [{ value: reason, depth: 0 }];
|
|
16922
|
+
while (pending.length > 0) {
|
|
16923
|
+
const { value, depth } = pending.pop();
|
|
16924
|
+
if (depth > MAX_CAUSE_DEPTH2)
|
|
16925
|
+
continue;
|
|
16926
|
+
if (isPrimitive(value)) {
|
|
16927
|
+
if (depth === 0 || value !== undefined && value !== null) {
|
|
16928
|
+
for (const scope of boundary.scopes) {
|
|
16929
|
+
const entry = scope.primitives.get(value);
|
|
16930
|
+
if (entry !== undefined)
|
|
16931
|
+
addAttribution(owners, scope, entry.effect);
|
|
16932
|
+
}
|
|
16933
|
+
if (typeof value === "string" && boundary.stops.has(value))
|
|
16934
|
+
stopped = true;
|
|
16935
|
+
}
|
|
16936
|
+
continue;
|
|
16937
|
+
}
|
|
16938
|
+
if (seen.has(value))
|
|
16939
|
+
continue;
|
|
16940
|
+
seen.add(value);
|
|
16941
|
+
for (const [scope, effect] of boundary.owners.get(value) ?? [])
|
|
16942
|
+
addAttribution(owners, scope, effect);
|
|
16943
|
+
pending.push({ value: safeField3(value, "cause"), depth: depth + 1 });
|
|
16944
|
+
const errors = safeField3(value, "errors");
|
|
16945
|
+
if (Array.isArray(errors))
|
|
16946
|
+
for (const entry of errors)
|
|
16947
|
+
pending.push({ value: entry, depth: depth + 1 });
|
|
16948
|
+
}
|
|
16949
|
+
return { owners, stopped };
|
|
16950
|
+
}
|
|
16951
|
+
function pruneEndedSources(boundary) {
|
|
16952
|
+
const now = Date.now();
|
|
16953
|
+
for (const [source, trees] of boundary.ended) {
|
|
16954
|
+
for (const [rootRunId, endedAt] of trees)
|
|
16955
|
+
if (now - endedAt > ENDED_RUN_GRACE_MS)
|
|
16956
|
+
trees.delete(rootRunId);
|
|
16957
|
+
if (trees.size === 0)
|
|
16958
|
+
boundary.ended.delete(source);
|
|
16959
|
+
}
|
|
16960
|
+
}
|
|
16961
|
+
function recordEndedRun(boundary, scope) {
|
|
16962
|
+
if (scope.source === undefined)
|
|
16963
|
+
return;
|
|
16964
|
+
const trees = boundary.ended.get(scope.source) ?? new Map;
|
|
16965
|
+
trees.set(scope.rootRunId, Date.now());
|
|
16966
|
+
boundary.ended.set(scope.source, trees);
|
|
16967
|
+
}
|
|
16968
|
+
function endedInAnotherRunTree(boundary, source, live) {
|
|
16969
|
+
for (const endedRoot of boundary.ended.get(source)?.keys() ?? [])
|
|
16970
|
+
if (endedRoot !== live.rootRunId)
|
|
16971
|
+
return true;
|
|
16972
|
+
return false;
|
|
16973
|
+
}
|
|
16974
|
+
function recognizedSources(boundary) {
|
|
16975
|
+
pruneEndedSources(boundary);
|
|
16976
|
+
const sources = new Set(boundary.ended.keys());
|
|
16977
|
+
for (const scope of boundary.scopes)
|
|
16978
|
+
if (scope.live && scope.source !== undefined)
|
|
16979
|
+
sources.add(scope.source);
|
|
16980
|
+
return sources;
|
|
16981
|
+
}
|
|
16982
|
+
function authoringSource(reason, sources) {
|
|
16983
|
+
if (sources.size === 0 || !isObject(reason))
|
|
16984
|
+
return;
|
|
16985
|
+
const stack = safeField3(reason, "stack");
|
|
16986
|
+
if (typeof stack !== "string")
|
|
16987
|
+
return;
|
|
16988
|
+
for (const line of stack.split(`
|
|
16989
|
+
`)) {
|
|
16990
|
+
if (!line.trimStart().startsWith("at "))
|
|
16991
|
+
continue;
|
|
16992
|
+
const path = parsePromptStackFrame(line)?.normalizedPath;
|
|
16993
|
+
if (path === undefined)
|
|
16994
|
+
continue;
|
|
16995
|
+
if (isWorkflowRuntimeModule(path))
|
|
16996
|
+
return;
|
|
16997
|
+
if (/\/node_modules\//.test(path))
|
|
16998
|
+
continue;
|
|
16999
|
+
if (sources.has(path))
|
|
17000
|
+
return path;
|
|
17001
|
+
}
|
|
17002
|
+
return;
|
|
17003
|
+
}
|
|
17004
|
+
function hasAncestorIn(scope, candidates) {
|
|
17005
|
+
for (let ancestor = scope.parent;ancestor !== undefined; ancestor = ancestor.parent) {
|
|
17006
|
+
if (candidates.has(ancestor))
|
|
17007
|
+
return true;
|
|
17008
|
+
}
|
|
17009
|
+
return false;
|
|
17010
|
+
}
|
|
17011
|
+
function outermostLiveRuns(boundary, source) {
|
|
17012
|
+
const matching = new Set;
|
|
17013
|
+
for (const scope of boundary.scopes)
|
|
17014
|
+
if (scope.live && scope.source === source)
|
|
17015
|
+
matching.add(scope);
|
|
17016
|
+
const outermost = new Set;
|
|
17017
|
+
for (const scope of matching)
|
|
17018
|
+
if (!hasAncestorIn(scope, matching))
|
|
17019
|
+
outermost.add(scope);
|
|
17020
|
+
return outermost;
|
|
17021
|
+
}
|
|
17022
|
+
function runOfSource(boundary, source) {
|
|
17023
|
+
const [only, ...others] = outermostLiveRuns(boundary, source);
|
|
17024
|
+
if (only === undefined)
|
|
17025
|
+
return new Map;
|
|
17026
|
+
if (others.length > 0 || only.sharedSource)
|
|
17027
|
+
return;
|
|
17028
|
+
if (endedInAnotherRunTree(boundary, source, only))
|
|
17029
|
+
return;
|
|
17030
|
+
return new Map([[only, "fail-run"]]);
|
|
17031
|
+
}
|
|
17032
|
+
function markSharedSource(boundary, source) {
|
|
17033
|
+
const runs = outermostLiveRuns(boundary, source);
|
|
17034
|
+
if (runs.size > 1)
|
|
17035
|
+
for (const run of runs)
|
|
17036
|
+
run.sharedSource = true;
|
|
17037
|
+
}
|
|
17038
|
+
function rejectingRun(boundary, recorded, promise, scoped) {
|
|
17039
|
+
const tracked = promise === undefined ? undefined : boundary.promises.get(promise);
|
|
17040
|
+
if (tracked !== undefined && recorded.has(tracked))
|
|
17041
|
+
return tracked;
|
|
17042
|
+
if (scoped !== undefined && recorded.has(scoped))
|
|
17043
|
+
return scoped;
|
|
17044
|
+
return;
|
|
17045
|
+
}
|
|
17046
|
+
function attribute(boundary, reason, promise) {
|
|
17047
|
+
const { owners: recorded, stopped } = recordedOwners(boundary, reason);
|
|
17048
|
+
const scoped = boundary.store.getStore();
|
|
17049
|
+
if (recorded.size > 1) {
|
|
17050
|
+
const rejecting = rejectingRun(boundary, recorded, promise, scoped);
|
|
17051
|
+
if (rejecting !== undefined)
|
|
17052
|
+
return new Map([[rejecting, recorded.get(rejecting) ?? "fail-run"]]);
|
|
17053
|
+
}
|
|
17054
|
+
if (recorded.size > 0)
|
|
17055
|
+
return recorded;
|
|
17056
|
+
if (stopped)
|
|
17057
|
+
return new Map;
|
|
17058
|
+
if (scoped !== undefined && boundary.scopes.has(scoped))
|
|
17059
|
+
return new Map([[scoped, "fail-run"]]);
|
|
17060
|
+
const origin = authoringSource(reason, recognizedSources(boundary));
|
|
17061
|
+
if (origin === undefined)
|
|
17062
|
+
return;
|
|
17063
|
+
if (scoped !== undefined)
|
|
17064
|
+
return new Map([[scoped, "ignore"]]);
|
|
17065
|
+
return runOfSource(boundary, origin);
|
|
17066
|
+
}
|
|
17067
|
+
function unhandledRejectionError(reason) {
|
|
17068
|
+
return Object.assign(new Error("This error originated either by throwing inside of an async function without a catch block, " + `or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "${inspect(reason)}".`), { code: "ERR_UNHANDLED_REJECTION" });
|
|
17069
|
+
}
|
|
17070
|
+
function unhandledRejectionsMode() {
|
|
17071
|
+
const args = [...(process.env.NODE_OPTIONS ?? "").split(/\s+/), ...process.execArgv];
|
|
17072
|
+
let mode = "throw";
|
|
17073
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
17074
|
+
const arg = args[index] ?? "";
|
|
17075
|
+
if (arg.startsWith(`${FLAG}=`))
|
|
17076
|
+
mode = arg.slice(FLAG.length + 1);
|
|
17077
|
+
else if (arg === FLAG && args[index + 1] !== undefined)
|
|
17078
|
+
mode = args[index + 1] ?? mode;
|
|
17079
|
+
}
|
|
17080
|
+
return mode;
|
|
17081
|
+
}
|
|
17082
|
+
function surfaceNatively(boundary, reason) {
|
|
17083
|
+
const listener = boundary.listener;
|
|
17084
|
+
if (listener === undefined || process.listenerCount(EVENT) > 1)
|
|
17085
|
+
return;
|
|
17086
|
+
if (!NATIVE_REPORTING_MODES.has(unhandledRejectionsMode()))
|
|
17087
|
+
return;
|
|
17088
|
+
process.nextTick(() => {
|
|
17089
|
+
process.removeListener(EVENT, listener);
|
|
17090
|
+
Promise.reject(reason);
|
|
17091
|
+
setImmediate(() => {
|
|
17092
|
+
if (!process.listeners(EVENT).includes(listener))
|
|
17093
|
+
process.on(EVENT, listener);
|
|
17094
|
+
});
|
|
17095
|
+
});
|
|
17096
|
+
}
|
|
17097
|
+
function onUnhandledRejection(reason, promise) {
|
|
17098
|
+
const boundary = sharedBoundary();
|
|
17099
|
+
const owners = attribute(boundary, reason, promise);
|
|
17100
|
+
if (owners === undefined) {
|
|
17101
|
+
surfaceNatively(boundary, reason);
|
|
17102
|
+
return;
|
|
17103
|
+
}
|
|
17104
|
+
const error = isObject(reason) ? reason : unhandledRejectionError(reason);
|
|
17105
|
+
for (const [scope, effect] of owners) {
|
|
17106
|
+
if (effect !== "fail-run" || !scope.live)
|
|
17107
|
+
continue;
|
|
17108
|
+
try {
|
|
17109
|
+
scope.fail(error);
|
|
17110
|
+
} catch {}
|
|
17111
|
+
}
|
|
17112
|
+
}
|
|
17113
|
+
function ensureInstalled(boundary) {
|
|
17114
|
+
if (boundary.listener !== undefined)
|
|
17115
|
+
return;
|
|
17116
|
+
boundary.listener = onUnhandledRejection;
|
|
17117
|
+
process.on(EVENT, onUnhandledRejection);
|
|
17118
|
+
}
|
|
17119
|
+
function record(boundary, scope, reason, effect) {
|
|
17120
|
+
if (isPrimitive(reason)) {
|
|
17121
|
+
recordPrimitive(scope, reason, effect);
|
|
17122
|
+
return;
|
|
17123
|
+
}
|
|
17124
|
+
const owners = boundary.owners.get(reason);
|
|
17125
|
+
if (owners === undefined)
|
|
17126
|
+
boundary.owners.set(reason, new Map([[scope, effect]]));
|
|
17127
|
+
else
|
|
17128
|
+
addAttribution(owners, scope, effect);
|
|
17129
|
+
}
|
|
17130
|
+
function recordStop(boundary, reason) {
|
|
17131
|
+
boundary.stops.delete(reason);
|
|
17132
|
+
boundary.stops.add(reason);
|
|
17133
|
+
if (boundary.stops.size <= MAX_STOP_STRINGS)
|
|
17134
|
+
return;
|
|
17135
|
+
const oldest = boundary.stops.values().next();
|
|
17136
|
+
if (!oldest.done)
|
|
17137
|
+
boundary.stops.delete(oldest.value);
|
|
17138
|
+
}
|
|
17139
|
+
function recordPrimitive(scope, reason, effect) {
|
|
17140
|
+
if (!scope.live)
|
|
17141
|
+
return;
|
|
17142
|
+
if (scope.primitives.size >= MAX_PRIMITIVES_PER_RUN && !scope.primitives.has(reason)) {
|
|
17143
|
+
const oldest = scope.primitives.keys().next();
|
|
17144
|
+
if (!oldest.done)
|
|
17145
|
+
scope.primitives.delete(oldest.value);
|
|
17146
|
+
}
|
|
17147
|
+
scope.generation += 1;
|
|
17148
|
+
const generation = scope.generation;
|
|
17149
|
+
scope.primitives.set(reason, { effect: strongerEffect(scope.primitives.get(reason)?.effect, effect), generation });
|
|
17150
|
+
afterPendingRejectionReports().then(() => {
|
|
17151
|
+
if (scope.primitives.get(reason)?.generation === generation)
|
|
17152
|
+
scope.primitives.delete(reason);
|
|
17153
|
+
});
|
|
17154
|
+
}
|
|
17155
|
+
function discardFailure() {}
|
|
17156
|
+
function afterPendingRejectionReports() {
|
|
17157
|
+
return new Promise((resolve) => {
|
|
17158
|
+
const { port1, port2 } = new MessageChannel;
|
|
17159
|
+
port1.onmessage = () => {
|
|
17160
|
+
port1.close();
|
|
17161
|
+
port2.close();
|
|
17162
|
+
resolve();
|
|
17163
|
+
};
|
|
17164
|
+
port2.postMessage(undefined);
|
|
17165
|
+
});
|
|
17166
|
+
}
|
|
17167
|
+
function openRunRejectionScope(options) {
|
|
17168
|
+
const boundary = sharedBoundary();
|
|
17169
|
+
ensureInstalled(boundary);
|
|
17170
|
+
pruneEndedSources(boundary);
|
|
17171
|
+
const parent = options.parentRunId === undefined ? undefined : boundary.runs.get(options.parentRunId);
|
|
17172
|
+
const scope = {
|
|
17173
|
+
runId: options.runId,
|
|
17174
|
+
rootRunId: parent?.rootRunId ?? options.runId,
|
|
17175
|
+
source: options.source === undefined ? undefined : normalizeStackPath(options.source),
|
|
17176
|
+
parent,
|
|
17177
|
+
fail: options.fail,
|
|
17178
|
+
primitives: new Map,
|
|
17179
|
+
generation: 0,
|
|
17180
|
+
live: true,
|
|
17181
|
+
sharedSource: false
|
|
17182
|
+
};
|
|
17183
|
+
boundary.scopes.add(scope);
|
|
17184
|
+
boundary.runs.set(scope.runId, scope);
|
|
17185
|
+
if (scope.source !== undefined)
|
|
17186
|
+
markSharedSource(boundary, scope.source);
|
|
17187
|
+
return {
|
|
17188
|
+
run: (callback) => boundary.store.run(scope, callback),
|
|
17189
|
+
contain: (promise, effect = "fail-run") => {
|
|
17190
|
+
boundary.promises.set(promise, scope);
|
|
17191
|
+
promise.then(undefined, (reason) => record(boundary, scope, reason, effect));
|
|
17192
|
+
return promise;
|
|
17193
|
+
},
|
|
17194
|
+
watch: (promise) => {
|
|
17195
|
+
const watched = promise.then(undefined, (reason) => {
|
|
17196
|
+
record(boundary, scope, reason, "fail-run");
|
|
17197
|
+
throw reason;
|
|
17198
|
+
});
|
|
17199
|
+
boundary.promises.set(watched, scope);
|
|
17200
|
+
return watched;
|
|
17201
|
+
},
|
|
17202
|
+
ignore: (reason) => {
|
|
17203
|
+
if (typeof reason === "string")
|
|
17204
|
+
recordStop(boundary, reason);
|
|
17205
|
+
else
|
|
17206
|
+
record(boundary, scope, reason, "ignore");
|
|
17207
|
+
},
|
|
17208
|
+
settle: afterPendingRejectionReports,
|
|
17209
|
+
close: () => {
|
|
17210
|
+
scope.live = false;
|
|
17211
|
+
scope.fail = discardFailure;
|
|
17212
|
+
recordEndedRun(boundary, scope);
|
|
17213
|
+
afterPendingRejectionReports().then(() => {
|
|
17214
|
+
scope.primitives.clear();
|
|
17215
|
+
scope.parent = undefined;
|
|
17216
|
+
boundary.scopes.delete(scope);
|
|
17217
|
+
if (boundary.runs.get(scope.runId) === scope)
|
|
17218
|
+
boundary.runs.delete(scope.runId);
|
|
17219
|
+
});
|
|
17220
|
+
}
|
|
17221
|
+
};
|
|
17222
|
+
}
|
|
17223
|
+
var WATCHED_STAGE_METHODS = [
|
|
17224
|
+
"prompt",
|
|
17225
|
+
"complete",
|
|
17226
|
+
"sendUserMessage",
|
|
17227
|
+
"steer",
|
|
17228
|
+
"followUp",
|
|
17229
|
+
"setModel",
|
|
17230
|
+
"setThinkingLevel",
|
|
17231
|
+
"cycleModel",
|
|
17232
|
+
"cycleThinkingLevel",
|
|
17233
|
+
"navigateTree",
|
|
17234
|
+
"compact",
|
|
17235
|
+
"abort"
|
|
17236
|
+
];
|
|
17237
|
+
function containStageRejections(stage, scope) {
|
|
17238
|
+
const contained = Object.create(stage);
|
|
17239
|
+
const descriptors = {};
|
|
17240
|
+
for (const name of WATCHED_STAGE_METHODS) {
|
|
17241
|
+
descriptors[name] = {
|
|
17242
|
+
value: (...args) => {
|
|
17243
|
+
const result = Reflect.apply(stage[name], stage, args);
|
|
17244
|
+
return result instanceof Promise ? scope.watch(result) : result;
|
|
17245
|
+
}
|
|
17246
|
+
};
|
|
17247
|
+
}
|
|
17248
|
+
Object.defineProperties(contained, descriptors);
|
|
17249
|
+
return contained;
|
|
17250
|
+
}
|
|
17251
|
+
function containUiRejections(ui, scope) {
|
|
17252
|
+
return {
|
|
17253
|
+
input: (prompt) => scope.watch(ui.input(prompt)),
|
|
17254
|
+
confirm: (message) => scope.watch(ui.confirm(message)),
|
|
17255
|
+
select: (message, options) => scope.watch(ui.select(message, options)),
|
|
17256
|
+
editor: (initial) => scope.watch(ui.editor(initial)),
|
|
17257
|
+
custom: (factory, options) => scope.watch(ui.custom(factory, options))
|
|
17258
|
+
};
|
|
17259
|
+
}
|
|
17260
|
+
|
|
16804
17261
|
// dist/builtin/workflows/src/engine/run-returned-status.ts
|
|
16805
17262
|
function classifyReturnedRunStatus(result, runSnapshot) {
|
|
16806
17263
|
const structuredFailure = runSnapshot !== undefined ? structuredRecoverableWorkflowFailure(runSnapshot) : undefined;
|
|
@@ -22800,13 +23257,13 @@ class EngineRuntime {
|
|
|
22800
23257
|
|
|
22801
23258
|
// dist/builtin/workflows/src/engine/session-closed-error.ts
|
|
22802
23259
|
import { isStaleExtensionContextError as isStaleExtensionContextError2 } from "@bastani/atomic";
|
|
22803
|
-
var
|
|
23260
|
+
var MAX_CAUSE_DEPTH3 = 8;
|
|
22804
23261
|
function reportsClosedSession(error) {
|
|
22805
23262
|
return "code" in error && error.code === "SessionClosed" || isStaleExtensionContextError2(error);
|
|
22806
23263
|
}
|
|
22807
23264
|
function isSessionClosedError(error) {
|
|
22808
23265
|
let current = error;
|
|
22809
|
-
for (let depth = 0;depth <
|
|
23266
|
+
for (let depth = 0;depth < MAX_CAUSE_DEPTH3 && current !== undefined; depth++) {
|
|
22810
23267
|
try {
|
|
22811
23268
|
if (reportsClosedSession(current))
|
|
22812
23269
|
return true;
|
|
@@ -22878,7 +23335,12 @@ async function executeRun(def, resolvedInputs, opts) {
|
|
|
22878
23335
|
workflowObservationRuntime(activeStore).control(runId, "kill");
|
|
22879
23336
|
ownController.abort(callerSignal?.reason);
|
|
22880
23337
|
};
|
|
22881
|
-
const exit = createWorkflowExitManager({
|
|
23338
|
+
const exit = createWorkflowExitManager({
|
|
23339
|
+
runId,
|
|
23340
|
+
exitScope,
|
|
23341
|
+
controller: ownController,
|
|
23342
|
+
onExitSelected: (signal) => rejectionScope.ignore(signal)
|
|
23343
|
+
});
|
|
22882
23344
|
const sourceBackend = opts.durableBackend;
|
|
22883
23345
|
const backendView = sourceBackend;
|
|
22884
23346
|
const rootBackend = opts.durableRootBackend ?? backendView;
|
|
@@ -23392,6 +23854,22 @@ async function executeRun(def, resolvedInputs, opts) {
|
|
|
23392
23854
|
baseFromPromptNodes: getPromptNodeUi
|
|
23393
23855
|
});
|
|
23394
23856
|
let pausedExit;
|
|
23857
|
+
const authoredIn = workflowSource(def);
|
|
23858
|
+
const rejectionScope = openRunRejectionScope({
|
|
23859
|
+
runId,
|
|
23860
|
+
...opts.parentRun !== undefined ? { parentRunId: opts.parentRun.runId } : {},
|
|
23861
|
+
...authoredIn !== undefined ? { source: authoredIn } : {},
|
|
23862
|
+
fail: (error) => {
|
|
23863
|
+
if (findWorkflowGracefulQuit(error) !== undefined)
|
|
23864
|
+
return;
|
|
23865
|
+
const selected = terminalEvents.selectFailure(error);
|
|
23866
|
+
if (selected.kind === "failure" && !ownController.signal.aborted)
|
|
23867
|
+
ownController.abort(selected.error);
|
|
23868
|
+
}
|
|
23869
|
+
});
|
|
23870
|
+
ownController.signal.addEventListener("abort", () => rejectionScope.ignore(ownController.signal.reason), {
|
|
23871
|
+
once: true
|
|
23872
|
+
});
|
|
23395
23873
|
const ctx = {
|
|
23396
23874
|
inputs: resolvedInputs,
|
|
23397
23875
|
runId,
|
|
@@ -23402,28 +23880,30 @@ async function executeRun(def, resolvedInputs, opts) {
|
|
|
23402
23880
|
if (scheduler.isRunPaused()) {
|
|
23403
23881
|
pausedExit ??= whenRunning(async () => exit.exit(options));
|
|
23404
23882
|
pausedExit.catch(() => {});
|
|
23405
|
-
|
|
23883
|
+
const waiting = new Error("Workflow exit is waiting for explicit resume");
|
|
23884
|
+
rejectionScope.ignore(waiting);
|
|
23885
|
+
throw waiting;
|
|
23406
23886
|
}
|
|
23407
23887
|
return exit.exit(options);
|
|
23408
23888
|
},
|
|
23409
|
-
ui,
|
|
23889
|
+
ui: containUiRejections(ui, rejectionScope),
|
|
23410
23890
|
stage: (name, options) => {
|
|
23411
23891
|
ownController.signal.throwIfAborted();
|
|
23412
23892
|
if (!scheduler.isRunPaused())
|
|
23413
|
-
return durableStage(name, options);
|
|
23893
|
+
return containStageRejections(durableStage(name, options), rejectionScope);
|
|
23414
23894
|
const replayKey = stageReplayKeyGenerator(name);
|
|
23415
|
-
return deferStageUntilRunRelease({
|
|
23895
|
+
return containStageRejections(deferStageUntilRunRelease({
|
|
23416
23896
|
name,
|
|
23417
23897
|
create: () => durableStage(name, options, replayKey),
|
|
23418
23898
|
isPaused: scheduler.isRunPaused,
|
|
23419
23899
|
waitForRelease: waitForRunRelease,
|
|
23420
23900
|
signal: ownController.signal
|
|
23421
|
-
});
|
|
23901
|
+
}), rejectionScope);
|
|
23422
23902
|
},
|
|
23423
|
-
task: gatedTask,
|
|
23424
|
-
chain: (...args) => whenRunning(() => chain(...args)),
|
|
23425
|
-
parallel: (...args) => whenRunning(() => parallel(...args)),
|
|
23426
|
-
workflow: (...args) => whenRunning(() => {
|
|
23903
|
+
task: (...args) => rejectionScope.watch(gatedTask(...args)),
|
|
23904
|
+
chain: (...args) => rejectionScope.watch(whenRunning(() => chain(...args))),
|
|
23905
|
+
parallel: (...args) => rejectionScope.watch(whenRunning(() => parallel(...args))),
|
|
23906
|
+
workflow: (...args) => rejectionScope.watch(whenRunning(() => {
|
|
23427
23907
|
const pending = durableWorkflow(...args);
|
|
23428
23908
|
pendingChildWorkflows.add(pending);
|
|
23429
23909
|
const settled = () => {
|
|
@@ -23431,13 +23911,11 @@ async function executeRun(def, resolvedInputs, opts) {
|
|
|
23431
23911
|
};
|
|
23432
23912
|
pending.then(settled, settled);
|
|
23433
23913
|
return pending;
|
|
23434
|
-
}),
|
|
23914
|
+
})),
|
|
23435
23915
|
tool: (...args) => {
|
|
23436
23916
|
if (admittedTools.closed)
|
|
23437
|
-
return tool(...args);
|
|
23438
|
-
|
|
23439
|
-
pending.catch(() => {});
|
|
23440
|
-
return pending;
|
|
23917
|
+
return rejectionScope.contain(tool(...args), "ignore");
|
|
23918
|
+
return rejectionScope.contain(whenRunning(() => tool(...args)));
|
|
23441
23919
|
},
|
|
23442
23920
|
...opts.models !== undefined ? { models: opts.models } : {}
|
|
23443
23921
|
};
|
|
@@ -23589,7 +24067,7 @@ async function executeRun(def, resolvedInputs, opts) {
|
|
|
23589
24067
|
while (scheduler.isRunPaused())
|
|
23590
24068
|
await waitForRunRelease();
|
|
23591
24069
|
ownController.signal.throwIfAborted();
|
|
23592
|
-
const rawResult = await raceAbort2(runWorkflowDefinitionCallback(def.name, runId, () => def.run(ctx)), ownController.signal);
|
|
24070
|
+
const rawResult = await raceAbort2(runWorkflowDefinitionCallback(def.name, runId, () => rejectionScope.run(() => def.run(ctx))), ownController.signal);
|
|
23593
24071
|
await drainCachedStagePersistence();
|
|
23594
24072
|
while (scheduler.isRunPaused())
|
|
23595
24073
|
await waitForRunRelease();
|
|
@@ -23599,6 +24077,7 @@ async function executeRun(def, resolvedInputs, opts) {
|
|
|
23599
24077
|
if (pausedExit !== undefined)
|
|
23600
24078
|
await pausedExit;
|
|
23601
24079
|
budget.rethrowIfSystemOwnedStop(runSnapshot.stages.at(-1)?.name ?? startupFrontierStage);
|
|
24080
|
+
await rejectionScope.settle();
|
|
23602
24081
|
const normalTerminalEvent = terminalEvents.winner();
|
|
23603
24082
|
if (normalTerminalEvent?.kind === "cancellation") {
|
|
23604
24083
|
const gracefulQuit = findWorkflowGracefulQuit(normalTerminalEvent.reason);
|
|
@@ -23668,6 +24147,9 @@ async function executeRun(def, resolvedInputs, opts) {
|
|
|
23668
24147
|
}
|
|
23669
24148
|
if (ownerClosing && err instanceof Error && isSessionClosedError(err))
|
|
23670
24149
|
return await suspendForClosedSession(err);
|
|
24150
|
+
if (selectedTerminalEvent.kind === "failure" && pendingChildWorkflows.size > 0 && !ownController.signal.aborted) {
|
|
24151
|
+
ownController.abort(err);
|
|
24152
|
+
}
|
|
23671
24153
|
await admittedTools.closeAndDrain();
|
|
23672
24154
|
if (ownController.signal.aborted)
|
|
23673
24155
|
await Promise.allSettled([...pendingChildWorkflows]);
|
|
@@ -23742,6 +24224,7 @@ async function executeRun(def, resolvedInputs, opts) {
|
|
|
23742
24224
|
});
|
|
23743
24225
|
return failed;
|
|
23744
24226
|
} finally {
|
|
24227
|
+
rejectionScope.close();
|
|
23745
24228
|
callerSignal?.removeEventListener("abort", onCallerAbort);
|
|
23746
24229
|
workflowObservationRuntime(activeStore).finishRun(runId);
|
|
23747
24230
|
runtimeSettled.resolve();
|