@bastani/atomic 0.9.19 → 0.9.20-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/index.bundle.mjs +15 -1
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +8 -0
- package/dist/builtin/workflows/builtin/{chunk-nkrafh9s.js → chunk-ewkkkbak.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-1jth021m.js → chunk-zqtm1d2c.js} +1 -1
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +3 -3
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +312 -67
- package/dist/builtin/workflows/src/index.js +231 -56
- package/docs/background-tasks.md +2 -0
- package/docs/workflows/operations.md +8 -0
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
- /package/dist/builtin/workflows/builtin/{chunk-ngkqkzej.js → chunk-m0xfsef8.js} +0 -0
|
@@ -67164,6 +67164,13 @@ function topLevelWorkflowRuns(runs) {
|
|
|
67164
67164
|
}
|
|
67165
67165
|
|
|
67166
67166
|
// dist/builtin/workflows/src/shared/timing.ts
|
|
67167
|
+
function stageTimingFields(stage = {}) {
|
|
67168
|
+
return {
|
|
67169
|
+
...stage.startedAt !== undefined ? { startedAt: stage.startedAt } : {},
|
|
67170
|
+
...stage.endedAt !== undefined ? { endedAt: stage.endedAt } : {},
|
|
67171
|
+
...stage.durationMs !== undefined ? { durationMs: stage.durationMs } : {}
|
|
67172
|
+
};
|
|
67173
|
+
}
|
|
67167
67174
|
function nonNegative(ms) {
|
|
67168
67175
|
return Math.max(0, ms);
|
|
67169
67176
|
}
|
|
@@ -67189,6 +67196,8 @@ function elapsedStageMs(stage, now = Date.now()) {
|
|
|
67189
67196
|
return nonNegative(stage.durationMs);
|
|
67190
67197
|
if (stage.startedAt === undefined)
|
|
67191
67198
|
return;
|
|
67199
|
+
if (stage.replayed && stage.endedAt === undefined)
|
|
67200
|
+
return;
|
|
67192
67201
|
const effectiveNow = stage.endedAt ?? now;
|
|
67193
67202
|
return elapsedFromStart(stage.startedAt, effectiveNow, stage.pausedDurationMs, stage.pausedAt);
|
|
67194
67203
|
}
|
|
@@ -68631,6 +68640,15 @@ function pendingWorkflowStageStatuses(run, resolveOwningRunStatus, resolveBounda
|
|
|
68631
68640
|
});
|
|
68632
68641
|
}
|
|
68633
68642
|
|
|
68643
|
+
// dist/builtin/workflows/src/shared/stage-startup.ts
|
|
68644
|
+
function formatStageStartup(startup, now = Date.now()) {
|
|
68645
|
+
const observedAt = startup.state === "dispatched" ? startup.phaseStartedAt : startup.settledAt ?? now;
|
|
68646
|
+
const age = Math.max(0, Math.floor((observedAt - startup.phaseStartedAt) / 1000));
|
|
68647
|
+
const total = Math.max(0, Math.floor((observedAt - startup.startedAt) / 1000));
|
|
68648
|
+
const recovery = startup.state === "cancelled" && startup.ownershipPending ? "; cleanup pending — do not retry in-process; stop the owning Atomic process before fresh execution" : "";
|
|
68649
|
+
return `startup ${startup.phase} (${total}s total, ${age}s on current step; ${startup.state})${recovery}`;
|
|
68650
|
+
}
|
|
68651
|
+
|
|
68634
68652
|
// dist/builtin/workflows/src/tui/status-helpers.ts
|
|
68635
68653
|
function statusColor(status, theme) {
|
|
68636
68654
|
switch (status) {
|
|
@@ -68886,9 +68904,15 @@ function pendingStageRows(runId, rootRunId, runStatus, stage, width, theme, reso
|
|
|
68886
68904
|
const text = hexToAnsi(theme.text);
|
|
68887
68905
|
return wrapped.map(({ prefix, chunk }, index) => index === 0 ? ` ${muted}${pad(label, 16)}${RESET}${text}${chunk}${RESET} ` : `${prefix}${text}${chunk}${RESET} `);
|
|
68888
68906
|
}
|
|
68907
|
+
function startupRows(stage, now, width, theme) {
|
|
68908
|
+
if (stage.startup === undefined)
|
|
68909
|
+
return [];
|
|
68910
|
+
return wrapIdentifierLines(formatStageStartup(stage.startup, now), Math.max(1, width - 2), " ", " ").map(({ prefix, chunk }) => theme === undefined ? `${prefix}${chunk}` : `${prefix}${hexToAnsi(theme.textMuted)}${chunk}${RESET}`);
|
|
68911
|
+
}
|
|
68889
68912
|
function renderStageRowsPlain(runId, rootRunId, runStatus, stage, now, width, resolveOwningRunStatus, resolveBoundarySegments) {
|
|
68890
68913
|
const rows = [
|
|
68891
68914
|
` ${stageLinePlain(stage, now, Math.max(1, width - 2))} `,
|
|
68915
|
+
...startupRows(stage, now, width),
|
|
68892
68916
|
...pendingStageRows(runId, rootRunId, runStatus, stage, width, undefined, resolveOwningRunStatus, resolveBoundarySegments)
|
|
68893
68917
|
];
|
|
68894
68918
|
if (stage.error) {
|
|
@@ -68900,6 +68924,7 @@ function renderStageRowsPlain(runId, rootRunId, runStatus, stage, now, width, re
|
|
|
68900
68924
|
function renderStageRowsThemed(runId, rootRunId, runStatus, stage, now, theme, width, resolveOwningRunStatus, resolveBoundarySegments) {
|
|
68901
68925
|
const rows = [
|
|
68902
68926
|
` ${stageLineThemed(stage, now, theme, Math.max(1, width - 2))} `,
|
|
68927
|
+
...startupRows(stage, now, width, theme),
|
|
68903
68928
|
...pendingStageRows(runId, rootRunId, runStatus, stage, width, theme, resolveOwningRunStatus, resolveBoundarySegments)
|
|
68904
68929
|
];
|
|
68905
68930
|
if (stage.error) {
|
|
@@ -87873,6 +87898,7 @@ function cachedStageId(runId, replayKey) {
|
|
|
87873
87898
|
function stageMetadataCheckpointId(replayKey, stage) {
|
|
87874
87899
|
return `${stableCheckpointId("stage-meta", replayKey)}:${durableHash({
|
|
87875
87900
|
stageId: stage.id,
|
|
87901
|
+
...stage.replayed === true ? { replayed: true } : {},
|
|
87876
87902
|
status: stage.status,
|
|
87877
87903
|
endedAt: stage.endedAt ?? 0,
|
|
87878
87904
|
durationMs: stage.durationMs ?? 0,
|
|
@@ -87880,11 +87906,9 @@ function stageMetadataCheckpointId(replayKey, stage) {
|
|
|
87880
87906
|
})}`;
|
|
87881
87907
|
}
|
|
87882
87908
|
function recordCachedStageIntoStore(store, runId, name, replayKey, output, completedStageReplayKeys, parentIds, checkpoint) {
|
|
87883
|
-
const now = Date.now();
|
|
87884
87909
|
const sourceStageId = checkpoint?.topology?.run?.runId === runId ? checkpoint.topology.stageId : undefined;
|
|
87885
87910
|
const stageId = sourceStageId ?? cachedStageId(runId, replayKey);
|
|
87886
87911
|
const result = checkpoint?.result ?? (typeof output === "string" ? output : JSON.stringify(output));
|
|
87887
|
-
const endedAt = checkpoint?.endedAt ?? checkpoint?.completedAt ?? now;
|
|
87888
87912
|
const hasCurrentIdentity = checkpoint?.topology?.sourceOrder !== undefined || checkpoint?.topology?.status !== undefined || checkpoint?.topology?.occurrenceKey !== undefined || checkpoint?.topology?.boundary !== undefined;
|
|
87889
87913
|
const childResult = parseWorkflowChildResult(output) ?? (hasCurrentIdentity ? undefined : parseLegacyWorkflowChildResult(output));
|
|
87890
87914
|
const workflowChild = childResult === undefined ? undefined : workflowChildSnapshotFromResult(childResult);
|
|
@@ -87894,9 +87918,7 @@ function recordCachedStageIntoStore(store, runId, name, replayKey, output, compl
|
|
|
87894
87918
|
name,
|
|
87895
87919
|
status: "completed",
|
|
87896
87920
|
parentIds: parentIds !== undefined ? Object.freeze([...parentIds]) : [],
|
|
87897
|
-
|
|
87898
|
-
endedAt,
|
|
87899
|
-
durationMs: checkpoint?.durationMs ?? 0,
|
|
87921
|
+
...stageTimingFields(checkpoint),
|
|
87900
87922
|
result,
|
|
87901
87923
|
replayKey,
|
|
87902
87924
|
replayed: true,
|
|
@@ -88260,7 +88282,7 @@ function appendStageStart(api, payload) {
|
|
|
88260
88282
|
...payload.replayKey !== undefined ? { replayKey: payload.replayKey } : {},
|
|
88261
88283
|
...payload.replayedFromStageId !== undefined ? { replayedFromStageId: payload.replayedFromStageId } : {},
|
|
88262
88284
|
...payload.replayed !== undefined ? { replayed: payload.replayed } : {},
|
|
88263
|
-
ts: payload.ts
|
|
88285
|
+
...payload.ts !== undefined ? { ts: payload.ts } : {}
|
|
88264
88286
|
});
|
|
88265
88287
|
}
|
|
88266
88288
|
function appendStageEnd(api, payload, opts) {
|
|
@@ -88271,6 +88293,7 @@ function appendStageEnd(api, payload, opts) {
|
|
|
88271
88293
|
stageId: payload.stageId,
|
|
88272
88294
|
status: payload.status,
|
|
88273
88295
|
...payload.durationMs !== undefined ? { durationMs: payload.durationMs } : {},
|
|
88296
|
+
...payload.endedAt !== undefined ? { endedAt: payload.endedAt } : {},
|
|
88274
88297
|
...payload.summary !== undefined ? { summary: payload.summary } : {},
|
|
88275
88298
|
...payload.error !== undefined ? { error: payload.error } : {},
|
|
88276
88299
|
...payload.failureKind !== undefined ? { failureKind: payload.failureKind } : {},
|
|
@@ -100921,6 +100944,26 @@ function createContinuationReplayIndex(continuation, sourceToContinuationNodeIds
|
|
|
100921
100944
|
}
|
|
100922
100945
|
|
|
100923
100946
|
// dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts
|
|
100947
|
+
function continuationPromptAnswer(store, sourceRun, sourceStage) {
|
|
100948
|
+
let run = sourceRun;
|
|
100949
|
+
let stage = sourceStage;
|
|
100950
|
+
const visited = new Set;
|
|
100951
|
+
while (!visited.has(stage.id)) {
|
|
100952
|
+
visited.add(stage.id);
|
|
100953
|
+
const answer = store.getStagePromptAnswer(run.id, stage.id);
|
|
100954
|
+
if (answer !== undefined)
|
|
100955
|
+
return answer;
|
|
100956
|
+
if (!stage.replayed || stage.replayedFromStageId === undefined || run.resumedFromRunId === undefined)
|
|
100957
|
+
break;
|
|
100958
|
+
const parentRun = store.runs().find((candidate) => candidate.id === run.resumedFromRunId);
|
|
100959
|
+
const parentStage = parentRun?.stages.find((candidate) => candidate.id === stage.replayedFromStageId);
|
|
100960
|
+
if (parentRun === undefined || parentStage === undefined)
|
|
100961
|
+
break;
|
|
100962
|
+
run = parentRun;
|
|
100963
|
+
stage = parentStage;
|
|
100964
|
+
}
|
|
100965
|
+
return;
|
|
100966
|
+
}
|
|
100924
100967
|
function buildPromptNodeUiAdapter(input) {
|
|
100925
100968
|
const ask = async (descriptor, durableReplay) => {
|
|
100926
100969
|
input.throwIfWorkflowExitSelected();
|
|
@@ -100935,6 +100978,9 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
100935
100978
|
const prompt = makePrompt(descriptor);
|
|
100936
100979
|
const replayKey = promptReplayKey(descriptor);
|
|
100937
100980
|
const durableTopology = input.durableTopologyForReplayKey?.(replayKey);
|
|
100981
|
+
if (durableTopology?.status === "completed" && durableReplay === undefined) {
|
|
100982
|
+
throw new Error(`insufficient_state: missing durable UI answer for completed prompt ${durableTopology.stageId}`);
|
|
100983
|
+
}
|
|
100938
100984
|
const stageId = durableTopology?.stageId ?? crypto.randomUUID();
|
|
100939
100985
|
const provisionalParentIds = input.tracker.onSpawn(stageId, descriptor.kind);
|
|
100940
100986
|
const replayDecision = input.replayIndex.decide({
|
|
@@ -100948,7 +100994,7 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
100948
100994
|
if (!sameStringSet(parentIds, provisionalParentIds))
|
|
100949
100995
|
input.tracker.replaceParents(stageId, parentIds);
|
|
100950
100996
|
const replaySource = replayDecision.source;
|
|
100951
|
-
const continuationAnswer = replayDecision.kind === "replay" ? input.activeStore
|
|
100997
|
+
const continuationAnswer = replayDecision.kind === "replay" ? continuationPromptAnswer(input.activeStore, input.opts.continuation.source, replayDecision.source) : undefined;
|
|
100952
100998
|
const replayAnswer = durableReplay === undefined ? continuationAnswer : { value: durableReplay.response };
|
|
100953
100999
|
const shouldReplay = replayAnswer !== undefined;
|
|
100954
101000
|
if (shouldReplay && durableReplay === undefined)
|
|
@@ -100961,13 +101007,11 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
100961
101007
|
replayKey,
|
|
100962
101008
|
status: shouldReplay ? "completed" : "running",
|
|
100963
101009
|
parentIds: Object.freeze(parentIds),
|
|
100964
|
-
startedAt: prompt.createdAt,
|
|
101010
|
+
...shouldReplay ? stageTimingFields(durableReplay === undefined ? replaySource : input.durableTimingForStageId?.(stageId)) : { startedAt: prompt.createdAt },
|
|
100965
101011
|
promptFootprint: { ...prompt },
|
|
100966
101012
|
toolEvents: [],
|
|
100967
101013
|
attachable: !shouldReplay,
|
|
100968
101014
|
...shouldReplay ? {
|
|
100969
|
-
endedAt: prompt.createdAt,
|
|
100970
|
-
durationMs: 0,
|
|
100971
101015
|
promptAnswerState: promptAnswerStatus,
|
|
100972
101016
|
replayedFromStageId: replaySourceId,
|
|
100973
101017
|
replayed: true
|
|
@@ -100997,8 +101041,10 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
100997
101041
|
pauseGate = undefined;
|
|
100998
101042
|
currentPauseGate?.resolve();
|
|
100999
101043
|
stageSnapshot.status = status;
|
|
101000
|
-
|
|
101001
|
-
|
|
101044
|
+
if (!shouldReplay) {
|
|
101045
|
+
stageSnapshot.endedAt = Date.now();
|
|
101046
|
+
stageSnapshot.durationMs = elapsedStageMs(stageSnapshot, stageSnapshot.endedAt);
|
|
101047
|
+
}
|
|
101002
101048
|
input.activeStore.recordStageAttachable(input.runId, stageId, false);
|
|
101003
101049
|
input.activeStore.recordStageEnd(input.runId, stageSnapshot);
|
|
101004
101050
|
await input.opts.onStageEnd?.(input.runId, stageSnapshot);
|
|
@@ -101008,6 +101054,7 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
101008
101054
|
stageId,
|
|
101009
101055
|
status: stageSnapshot.status,
|
|
101010
101056
|
durationMs: stageSnapshot.durationMs,
|
|
101057
|
+
endedAt: stageSnapshot.endedAt,
|
|
101011
101058
|
...stageSnapshot.error !== undefined ? { error: stageSnapshot.error } : {},
|
|
101012
101059
|
...stageSnapshot.failureKind !== undefined ? { failureKind: stageSnapshot.failureKind } : {},
|
|
101013
101060
|
...stageSnapshot.failureCode !== undefined ? { failureCode: stageSnapshot.failureCode } : {},
|
|
@@ -101074,7 +101121,7 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
101074
101121
|
name: stageSnapshot.name,
|
|
101075
101122
|
parentIds: stageSnapshot.parentIds,
|
|
101076
101123
|
...stageReplayFields(stageSnapshot),
|
|
101077
|
-
ts:
|
|
101124
|
+
ts: stageSnapshot.startedAt
|
|
101078
101125
|
});
|
|
101079
101126
|
}
|
|
101080
101127
|
if (shouldReplay) {
|
|
@@ -102345,7 +102392,7 @@ function wrapUiWithDurable(base, deps) {
|
|
|
102345
102392
|
// dist/builtin/workflows/src/engine/primitives/ui.ts
|
|
102346
102393
|
function buildExitGatedUiContext(input) {
|
|
102347
102394
|
const base = input.opts.usePromptNodesForUi === true ? input.baseFromPromptNodes() : input.opts.executionMode === "non_interactive" && input.opts.ui === undefined ? makeHeadlessUnavailableUIContext() : normalizeUIContext(input.opts.ui);
|
|
102348
|
-
const promptNodeReplay = input.opts.usePromptNodesForUi === true && input.opts.continuation !== undefined;
|
|
102395
|
+
const promptNodeReplay = input.opts.usePromptNodesForUi === true && input.opts.continuation !== undefined && input.opts.continuation.source.id !== input.durableUi?.workflowId;
|
|
102349
102396
|
const durableBase = input.durableUi !== undefined && !promptNodeReplay ? wrapUiWithDurable(base, input.durableUi) : base;
|
|
102350
102397
|
const invoke = (call) => {
|
|
102351
102398
|
input.throwIfWorkflowExitSelected();
|
|
@@ -102869,7 +102916,7 @@ function mergeStageDraft(existing, checkpoint, sequence) {
|
|
|
102869
102916
|
...valueOrExisting("thinkingLevel", checkpoint, existing),
|
|
102870
102917
|
...valueOrExisting("attemptedModels", checkpoint, existing),
|
|
102871
102918
|
...valueOrExisting("modelAttempts", checkpoint, existing),
|
|
102872
|
-
...checkpoint.topology !== undefined ? { topology: checkpoint.topology } : existing?.topology !== undefined ? { topology: existing.topology } : {}
|
|
102919
|
+
...existing?.topology?.run !== undefined && checkpoint.topology?.run === undefined ? { topology: existing.topology } : checkpoint.topology !== undefined ? { topology: checkpoint.topology } : existing?.topology !== undefined ? { topology: existing.topology } : {}
|
|
102873
102920
|
};
|
|
102874
102921
|
}
|
|
102875
102922
|
function valueOrExisting(key, checkpoint, existing) {
|
|
@@ -103090,7 +103137,7 @@ function resolveToolResumeFrontier(source, backend) {
|
|
|
103090
103137
|
if (source.failedToolNodeId === undefined && !checkpoints.some((checkpoint) => checkpoint.kind === "tool" && checkpoint.throwingFailureError === source.error && checkpoint.argsHash === frontier.argsHash && checkpoint.topology?.nodeId === frontier.id && checkpoint.topology.ordinal === frontier.ordinal))
|
|
103091
103138
|
return fail("missing typed tool failure checkpoint for legacy frontier");
|
|
103092
103139
|
for (const stage of source.stages) {
|
|
103093
|
-
if (stage.status !== "completed" || !checkpoints.some((checkpoint) => checkpoint.kind === "stage" && checkpoint.replayKey === stage.replayKey && checkpoint.output !== undefined))
|
|
103140
|
+
if (stage.status !== "completed" || !checkpoints.some((checkpoint) => checkpoint.kind === "stage" && checkpoint.replayKey === stage.replayKey && (checkpoint.output !== undefined || ["input", "confirm", "select", "editor", "custom"].includes(stage.name) && stage.replayKey?.startsWith(`prompt:${stage.name}:`) === true && checkpoint.name === stage.name && checkpoint.topology?.stageId === stage.id && checkpoint.topology.status === "completed" && checkpoint.topology.run?.runId === source.id)))
|
|
103094
103141
|
return fail(`unfinished or missing completed stage checkpoint ${stage.id}`);
|
|
103095
103142
|
}
|
|
103096
103143
|
for (const tool of tools) {
|
|
@@ -104510,13 +104557,11 @@ function createWorkflowBoundaryFactory(input) {
|
|
|
104510
104557
|
replayKey,
|
|
104511
104558
|
status: replayedChild !== undefined ? "completed" : "running",
|
|
104512
104559
|
parentIds: Object.freeze([...parentIds]),
|
|
104513
|
-
startedAt,
|
|
104560
|
+
...replayedChild === undefined ? { startedAt } : stageTimingFields(replaySource),
|
|
104514
104561
|
toolEvents: [],
|
|
104515
104562
|
attachable: false,
|
|
104516
104563
|
...replaySource !== undefined ? { replayedFromStageId: replaySource.id, replayed: replayedChild !== undefined } : {},
|
|
104517
104564
|
...replayedChild !== undefined && replayChildSnapshot !== undefined ? {
|
|
104518
|
-
endedAt: startedAt,
|
|
104519
|
-
durationMs: 0,
|
|
104520
104565
|
...replayDecision.kind === "replay" && replayDecision.source.result !== undefined ? { result: replayDecision.source.result } : {},
|
|
104521
104566
|
workflowChild: cloneWorkflowChildReplaySnapshot(replayChildSnapshot)
|
|
104522
104567
|
} : {}
|
|
@@ -104533,7 +104578,7 @@ function createWorkflowBoundaryFactory(input) {
|
|
|
104533
104578
|
name,
|
|
104534
104579
|
parentIds: stageSnapshot.parentIds,
|
|
104535
104580
|
...stageReplayFields(stageSnapshot),
|
|
104536
|
-
ts: startedAt
|
|
104581
|
+
ts: stageSnapshot.startedAt
|
|
104537
104582
|
});
|
|
104538
104583
|
};
|
|
104539
104584
|
const appendStageEndForSnapshot = () => {
|
|
@@ -104544,6 +104589,7 @@ function createWorkflowBoundaryFactory(input) {
|
|
|
104544
104589
|
stageId,
|
|
104545
104590
|
status: stageSnapshot.status,
|
|
104546
104591
|
durationMs: stageSnapshot.durationMs,
|
|
104592
|
+
endedAt: stageSnapshot.endedAt,
|
|
104547
104593
|
...stageSnapshot.error !== undefined ? { error: stageSnapshot.error } : {},
|
|
104548
104594
|
...stageSnapshot.failureKind !== undefined ? { failureKind: stageSnapshot.failureKind } : {},
|
|
104549
104595
|
...stageSnapshot.failureCode !== undefined ? { failureCode: stageSnapshot.failureCode } : {},
|
|
@@ -104580,8 +104626,10 @@ function createWorkflowBoundaryFactory(input) {
|
|
|
104580
104626
|
clearBoundaryChildMetadata();
|
|
104581
104627
|
applyFailureToStage(stageSnapshot, input.classifyExecutorFailure(failureError));
|
|
104582
104628
|
}
|
|
104583
|
-
|
|
104584
|
-
|
|
104629
|
+
if (replayedChild === undefined) {
|
|
104630
|
+
stageSnapshot.endedAt = Date.now();
|
|
104631
|
+
stageSnapshot.durationMs = elapsedStageMs(stageSnapshot, stageSnapshot.endedAt);
|
|
104632
|
+
}
|
|
104585
104633
|
input.activeStore.recordStageEnd(input.runId, stageSnapshot);
|
|
104586
104634
|
input.opts.onStageEnd?.(input.runId, stageSnapshot);
|
|
104587
104635
|
appendStageEndForSnapshot();
|
|
@@ -104649,6 +104697,34 @@ function createWorkflowBoundaryFactory(input) {
|
|
|
104649
104697
|
// dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts
|
|
104650
104698
|
import { runCallback as runCallback3, runSynchronousCallback } from "@bastani/atomic";
|
|
104651
104699
|
|
|
104700
|
+
// dist/builtin/workflows/src/shared/pending-stage-route-readiness.ts
|
|
104701
|
+
var owners = new WeakMap;
|
|
104702
|
+
function registerWorkflowPendingStageRouteReadiness(store, ready) {
|
|
104703
|
+
owners.get(store)?.retire();
|
|
104704
|
+
const controller = new AbortController;
|
|
104705
|
+
const owner = {
|
|
104706
|
+
ready(runId) {
|
|
104707
|
+
const completion = ready(runId);
|
|
104708
|
+
return completion === undefined ? undefined : {
|
|
104709
|
+
completion: raceAbort2(completion, controller.signal),
|
|
104710
|
+
assertCurrent: () => controller.signal.throwIfAborted()
|
|
104711
|
+
};
|
|
104712
|
+
},
|
|
104713
|
+
retire() {
|
|
104714
|
+
controller.abort(new Error("atomic-workflows: Intercom route authority owner retired before stage startup"));
|
|
104715
|
+
}
|
|
104716
|
+
};
|
|
104717
|
+
owners.set(store, owner);
|
|
104718
|
+
return () => {
|
|
104719
|
+
owner.retire();
|
|
104720
|
+
if (owners.get(store) === owner)
|
|
104721
|
+
owners.delete(store);
|
|
104722
|
+
};
|
|
104723
|
+
}
|
|
104724
|
+
function workflowPendingStageRouteReady(store, runId) {
|
|
104725
|
+
return owners.get(store)?.ready(runId);
|
|
104726
|
+
}
|
|
104727
|
+
|
|
104652
104728
|
// dist/builtin/workflows/src/runs/foreground/executor-queued-user-message.ts
|
|
104653
104729
|
function removedMessages(before, after) {
|
|
104654
104730
|
const remaining = [...after];
|
|
@@ -105503,7 +105579,7 @@ function createReplayStageContext(input) {
|
|
|
105503
105579
|
name,
|
|
105504
105580
|
parentIds: stageSnapshot.parentIds,
|
|
105505
105581
|
...stageReplayFields(stageSnapshot),
|
|
105506
|
-
ts: stageSnapshot.startedAt
|
|
105582
|
+
ts: stageSnapshot.startedAt
|
|
105507
105583
|
});
|
|
105508
105584
|
};
|
|
105509
105585
|
const appendReplayStageEnd = () => {
|
|
@@ -105513,7 +105589,8 @@ function createReplayStageContext(input) {
|
|
|
105513
105589
|
runId,
|
|
105514
105590
|
stageId,
|
|
105515
105591
|
status: stageSnapshot.status,
|
|
105516
|
-
durationMs: stageSnapshot.durationMs
|
|
105592
|
+
durationMs: stageSnapshot.durationMs,
|
|
105593
|
+
endedAt: stageSnapshot.endedAt,
|
|
105517
105594
|
...stageSnapshot.status === "completed" && stageSnapshot.result !== undefined ? { summary: stageSnapshot.result } : {},
|
|
105518
105595
|
...stageSnapshot.skippedReason !== undefined ? { skippedReason: stageSnapshot.skippedReason } : {},
|
|
105519
105596
|
...stageSnapshot.sessionId !== undefined ? { sessionId: stageSnapshot.sessionId } : {},
|
|
@@ -105531,8 +105608,6 @@ function createReplayStageContext(input) {
|
|
|
105531
105608
|
delete stageSnapshot.result;
|
|
105532
105609
|
stageSnapshot.skippedReason = input.workflowExitSkippedReason(reason);
|
|
105533
105610
|
}
|
|
105534
|
-
stageSnapshot.endedAt = Date.now();
|
|
105535
|
-
stageSnapshot.durationMs = elapsedStageMs(stageSnapshot, stageSnapshot.endedAt);
|
|
105536
105611
|
input.activeStore.recordStageEnd(runId, stageSnapshot);
|
|
105537
105612
|
input.opts.onStageEnd?.(runId, stageSnapshot);
|
|
105538
105613
|
appendReplayStageEnd();
|
|
@@ -107147,6 +107222,27 @@ function terminatingToolCallId(event) {
|
|
|
107147
107222
|
return typeof callId === "string" && callId.length > 0 ? callId : undefined;
|
|
107148
107223
|
}
|
|
107149
107224
|
|
|
107225
|
+
// dist/builtin/workflows/src/runs/foreground/stage-startup-wait.ts
|
|
107226
|
+
function waitForStageStartup(operation, signal) {
|
|
107227
|
+
return new Promise((resolve, reject) => {
|
|
107228
|
+
const onAbort = () => {
|
|
107229
|
+
signal.removeEventListener("abort", onAbort);
|
|
107230
|
+
reject(signal.reason ?? new DOMException("Stage startup cancelled", "AbortError"));
|
|
107231
|
+
};
|
|
107232
|
+
operation.then((value2) => {
|
|
107233
|
+
signal.removeEventListener("abort", onAbort);
|
|
107234
|
+
resolve(value2);
|
|
107235
|
+
}, (error) => {
|
|
107236
|
+
signal.removeEventListener("abort", onAbort);
|
|
107237
|
+
reject(error);
|
|
107238
|
+
});
|
|
107239
|
+
if (signal.aborted)
|
|
107240
|
+
onAbort();
|
|
107241
|
+
else
|
|
107242
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
107243
|
+
});
|
|
107244
|
+
}
|
|
107245
|
+
|
|
107150
107246
|
// dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts
|
|
107151
107247
|
function hasMeaningfulUsage(usage) {
|
|
107152
107248
|
if (usage === undefined)
|
|
@@ -107227,6 +107323,9 @@ class StageSessionController {
|
|
|
107227
107323
|
activeCreation;
|
|
107228
107324
|
ownedCreationPromise;
|
|
107229
107325
|
abortGeneration = 0;
|
|
107326
|
+
routeAuthorityWait;
|
|
107327
|
+
startupWait = new AbortController;
|
|
107328
|
+
startup;
|
|
107230
107329
|
abortReason;
|
|
107231
107330
|
abortReasonGeneration = 0;
|
|
107232
107331
|
sessionPromise;
|
|
@@ -107386,25 +107485,28 @@ class StageSessionController {
|
|
|
107386
107485
|
}
|
|
107387
107486
|
if (this.disposed)
|
|
107388
107487
|
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
107389
|
-
|
|
107488
|
+
this.opts.signal?.throwIfAborted();
|
|
107489
|
+
if (this.session !== undefined && this.activeCreation === undefined)
|
|
107390
107490
|
return this.session;
|
|
107391
107491
|
if (!this.sessionPromise) {
|
|
107492
|
+
this.beginStartup();
|
|
107392
107493
|
const pending = this.createInitialSession(consumer);
|
|
107393
107494
|
this.sessionPromise = pending;
|
|
107394
107495
|
this.ownedCreationPromise = pending;
|
|
107395
|
-
const release = () => {
|
|
107496
|
+
const release = (failed = false) => {
|
|
107396
107497
|
if (this.ownedCreationPromise === pending)
|
|
107397
107498
|
this.ownedCreationPromise = undefined;
|
|
107499
|
+
this.settleStartup(failed);
|
|
107398
107500
|
};
|
|
107399
|
-
pending.then(release, () => {
|
|
107400
|
-
release();
|
|
107501
|
+
pending.then(() => release(), () => {
|
|
107502
|
+
release(true);
|
|
107401
107503
|
if (this.sessionPromise === pending) {
|
|
107402
107504
|
this.sessionPromise = undefined;
|
|
107403
107505
|
this.activeCandidateIndex = undefined;
|
|
107404
107506
|
}
|
|
107405
107507
|
});
|
|
107406
107508
|
}
|
|
107407
|
-
return this.sessionPromise;
|
|
107509
|
+
return waitForStageStartup(this.sessionPromise, this.startupWait.signal);
|
|
107408
107510
|
}
|
|
107409
107511
|
async ensureSessionFromFile(sessionFile, consumer = "prompt") {
|
|
107410
107512
|
if (!this.sessionShutdownPromise && !this.sessionPromise && !this.session)
|
|
@@ -107452,6 +107554,10 @@ class StageSessionController {
|
|
|
107452
107554
|
this.artifactCapture.close();
|
|
107453
107555
|
}
|
|
107454
107556
|
async promptWithFallback(text, sdkOptions, consumer = "prompt") {
|
|
107557
|
+
if (this.session !== undefined && this.activeCreation === undefined && this.ownedCreationPromise === undefined && this.startupWait.signal.aborted) {
|
|
107558
|
+
this.opts.signal?.throwIfAborted();
|
|
107559
|
+
this.startupWait = new AbortController;
|
|
107560
|
+
}
|
|
107455
107561
|
if (!this.hasExplicitModelFallbackConfig) {
|
|
107456
107562
|
try {
|
|
107457
107563
|
const activeSession = await this.ensureSession(consumer);
|
|
@@ -107474,7 +107580,13 @@ class StageSessionController {
|
|
|
107474
107580
|
}
|
|
107475
107581
|
return;
|
|
107476
107582
|
}
|
|
107477
|
-
const
|
|
107583
|
+
const readinessOwner = this.ownedCreationPromise ?? this.activeCreation;
|
|
107584
|
+
if (readinessOwner !== undefined)
|
|
107585
|
+
await waitForStageStartup(readinessOwner, this.startupWait.signal);
|
|
107586
|
+
if (this.session === undefined)
|
|
107587
|
+
this.beginStartup();
|
|
107588
|
+
const startupSignal = this.startupWait.signal;
|
|
107589
|
+
const candidates = await waitForStageStartup(this.modelCandidates(), startupSignal);
|
|
107478
107590
|
if (candidates.length === 0) {
|
|
107479
107591
|
try {
|
|
107480
107592
|
const activeSession = await this.ensureSession(consumer);
|
|
@@ -107490,14 +107602,9 @@ class StageSessionController {
|
|
|
107490
107602
|
}
|
|
107491
107603
|
return;
|
|
107492
107604
|
}
|
|
107493
|
-
|
|
107494
|
-
|
|
107495
|
-
|
|
107496
|
-
} catch (error) {
|
|
107497
|
-
if (error instanceof StageSessionCreationCancelled)
|
|
107498
|
-
return;
|
|
107499
|
-
}
|
|
107500
|
-
}
|
|
107605
|
+
const creationOwner = this.ownedCreationPromise ?? this.activeCreation;
|
|
107606
|
+
if (creationOwner !== undefined)
|
|
107607
|
+
await waitForStageStartup(creationOwner, startupSignal);
|
|
107501
107608
|
const resumedText = this.pendingCreationResumeMessage;
|
|
107502
107609
|
this.pendingCreationResumeMessage = undefined;
|
|
107503
107610
|
let promptText = resumedText ?? text;
|
|
@@ -107505,9 +107612,9 @@ class StageSessionController {
|
|
|
107505
107612
|
return;
|
|
107506
107613
|
let index = this.activeCandidateIndex ?? 0;
|
|
107507
107614
|
while (index < candidates.length) {
|
|
107508
|
-
if (this.
|
|
107615
|
+
if (this.ownedCreationPromise !== undefined || this.activeCreation !== undefined) {
|
|
107509
107616
|
try {
|
|
107510
|
-
await this.ownedCreationPromise;
|
|
107617
|
+
await waitForStageStartup(this.ownedCreationPromise ?? this.activeCreation, startupSignal);
|
|
107511
107618
|
} catch (error) {
|
|
107512
107619
|
if (error instanceof StageSessionCreationCancelled)
|
|
107513
107620
|
return;
|
|
@@ -107519,7 +107626,7 @@ class StageSessionController {
|
|
|
107519
107626
|
}
|
|
107520
107627
|
const candidate = candidates[index];
|
|
107521
107628
|
try {
|
|
107522
|
-
const created = this.session && this.activeCandidateIndex === index ? this.session : await this.createSessionWithThrownErrorRetry(candidate, consumer);
|
|
107629
|
+
const created = this.session && this.activeCandidateIndex === index ? this.session : await waitForStageStartup(this.createSessionWithThrownErrorRetry(candidate, consumer), startupSignal);
|
|
107523
107630
|
if (isSessionCreationPauseResult(created)) {
|
|
107524
107631
|
if (created.resumeMessage === undefined)
|
|
107525
107632
|
return;
|
|
@@ -107546,8 +107653,10 @@ class StageSessionController {
|
|
|
107546
107653
|
const failure = await this.handleCandidateFailure(err, candidate, candidates, index);
|
|
107547
107654
|
if (failure === "handled")
|
|
107548
107655
|
return;
|
|
107549
|
-
if (failure === "throw")
|
|
107656
|
+
if (failure === "throw") {
|
|
107657
|
+
this.settleStartup(true);
|
|
107550
107658
|
throw err;
|
|
107659
|
+
}
|
|
107551
107660
|
index += 1;
|
|
107552
107661
|
}
|
|
107553
107662
|
}
|
|
@@ -107590,7 +107699,8 @@ class StageSessionController {
|
|
|
107590
107699
|
this.messageAdmission.dispose();
|
|
107591
107700
|
this.deliveryActivity.dispose();
|
|
107592
107701
|
await this.replacement.dispose();
|
|
107593
|
-
|
|
107702
|
+
if (this.activeCreation === undefined)
|
|
107703
|
+
await disposeStageSession(this.session);
|
|
107594
107704
|
}
|
|
107595
107705
|
async drainPendingDisposal() {
|
|
107596
107706
|
if (!this.pendingDisposal)
|
|
@@ -107664,6 +107774,12 @@ class StageSessionController {
|
|
|
107664
107774
|
this.abortGeneration += 1;
|
|
107665
107775
|
this.abortReason = reason;
|
|
107666
107776
|
this.abortReasonGeneration = this.abortGeneration;
|
|
107777
|
+
this.routeAuthorityWait?.abort(reason);
|
|
107778
|
+
this.startupWait.abort(reason);
|
|
107779
|
+
if (this.startup?.state === "active") {
|
|
107780
|
+
this.startup = { ...this.startup, state: "cancelled" };
|
|
107781
|
+
this.opts.onStartupChange?.(this.startup);
|
|
107782
|
+
}
|
|
107667
107783
|
this.abortThrownErrorRetries(reason);
|
|
107668
107784
|
}
|
|
107669
107785
|
pauseThrownErrorRetries(resume) {
|
|
@@ -107904,10 +108020,13 @@ class StageSessionController {
|
|
|
107904
108020
|
return this.candidatesPromise;
|
|
107905
108021
|
}
|
|
107906
108022
|
async createInitialSession(consumer) {
|
|
108023
|
+
const generation = this.abortGeneration;
|
|
107907
108024
|
if (!this.hasExplicitModelFallbackConfig) {
|
|
107908
108025
|
return this.createSessionObservingPause(undefined, consumer).catch((error) => this.createInitialSessionWithRetry(undefined, consumer, { error }));
|
|
107909
108026
|
}
|
|
107910
108027
|
const candidates = await this.modelCandidates();
|
|
108028
|
+
if (this.abortGeneration !== generation || this.opts.signal?.aborted || this.disposed)
|
|
108029
|
+
throw this.staleCreationReason(generation);
|
|
107911
108030
|
const initialIndex = this.activeCandidateIndex ?? 0;
|
|
107912
108031
|
const first = candidates[initialIndex];
|
|
107913
108032
|
if (first === undefined) {
|
|
@@ -108012,7 +108131,7 @@ class StageSessionController {
|
|
|
108012
108131
|
if (errorSettingsManager !== undefined)
|
|
108013
108132
|
this.sessionSettingsManager = errorSettingsManager;
|
|
108014
108133
|
const decision = isWorkflowPendingStageDeliveryFailure(error) ? undefined : nextRetryDecision(this.retrySettings(), retryAttempt, isRetryableSameModelFailure(error));
|
|
108015
|
-
if (decision === undefined || this.disposed || this.opts.signal?.aborted === true || this.capturedStructuredOutputForAttempt()) {
|
|
108134
|
+
if (decision === undefined || this.disposed || this.opts.signal?.aborted === true || this.startupWait.signal.aborted || this.capturedStructuredOutputForAttempt()) {
|
|
108016
108135
|
throw error;
|
|
108017
108136
|
}
|
|
108018
108137
|
retryAttempt = decision.attempt;
|
|
@@ -108055,16 +108174,72 @@ class StageSessionController {
|
|
|
108055
108174
|
return this.activeCreation;
|
|
108056
108175
|
if (this.session !== undefined)
|
|
108057
108176
|
return Promise.resolve(this.session);
|
|
108177
|
+
this.startupWait.signal.throwIfAborted();
|
|
108058
108178
|
const creation = this.createSessionAttempt(candidate, consumer, resumeOptions);
|
|
108059
108179
|
this.activeCreation = creation;
|
|
108060
108180
|
creation.finally(() => {
|
|
108061
108181
|
if (this.activeCreation === creation)
|
|
108062
108182
|
this.activeCreation = undefined;
|
|
108183
|
+
this.settleStartup();
|
|
108063
108184
|
}).catch(() => {});
|
|
108064
108185
|
return creation;
|
|
108065
108186
|
}
|
|
108187
|
+
settleStartup(failed = false) {
|
|
108188
|
+
if (this.activeCreation !== undefined || this.ownedCreationPromise !== undefined || this.startup === undefined)
|
|
108189
|
+
return;
|
|
108190
|
+
if (this.startup.state === "dispatched" || this.startup.phase === "ready")
|
|
108191
|
+
return;
|
|
108192
|
+
if (this.startup.state === "active" && !failed && this.bindingCleanupFailure === undefined)
|
|
108193
|
+
return;
|
|
108194
|
+
this.startup = {
|
|
108195
|
+
...this.startup,
|
|
108196
|
+
state: this.startup.state === "active" ? "failed" : this.startup.state,
|
|
108197
|
+
ownershipPending: this.bindingCleanupFailure !== undefined,
|
|
108198
|
+
...this.bindingCleanupFailure === undefined ? { settledAt: Date.now() } : {}
|
|
108199
|
+
};
|
|
108200
|
+
this.opts.onStartupChange?.(this.startup);
|
|
108201
|
+
}
|
|
108202
|
+
beginStartup() {
|
|
108203
|
+
if (this.activeCreation !== undefined || this.ownedCreationPromise !== undefined || this.sessionPromise !== undefined)
|
|
108204
|
+
return;
|
|
108205
|
+
this.opts.signal?.throwIfAborted();
|
|
108206
|
+
if (this.startupWait.signal.aborted)
|
|
108207
|
+
this.startupWait = new AbortController;
|
|
108208
|
+
this.reportStartupPhase("model-resolution", true);
|
|
108209
|
+
}
|
|
108210
|
+
reportStartupPhase(phase, reset = false) {
|
|
108211
|
+
if (!reset && this.startup !== undefined && this.startup.state !== "active")
|
|
108212
|
+
return;
|
|
108213
|
+
const now = Date.now();
|
|
108214
|
+
this.startup = {
|
|
108215
|
+
phase,
|
|
108216
|
+
startedAt: reset ? now : this.startup?.startedAt ?? now,
|
|
108217
|
+
phaseStartedAt: now,
|
|
108218
|
+
state: phase === "first-dispatch" ? "dispatched" : "active",
|
|
108219
|
+
ownershipPending: phase !== "first-dispatch" && phase !== "ready"
|
|
108220
|
+
};
|
|
108221
|
+
this.opts.onStartupChange?.(this.startup);
|
|
108222
|
+
}
|
|
108066
108223
|
async createSessionAttempt(candidate, consumer, resumeOptions) {
|
|
108067
108224
|
const startGeneration = this.abortGeneration;
|
|
108225
|
+
if (this.disposed || this.opts.signal?.aborted)
|
|
108226
|
+
throw this.staleCreationReason(startGeneration);
|
|
108227
|
+
this.reportStartupPhase("route-authority");
|
|
108228
|
+
const authority = this.opts.routeAuthorityReady?.();
|
|
108229
|
+
if (authority !== undefined) {
|
|
108230
|
+
const wait = new AbortController;
|
|
108231
|
+
this.routeAuthorityWait = wait;
|
|
108232
|
+
try {
|
|
108233
|
+
await raceAbort2(authority.completion, wait.signal);
|
|
108234
|
+
authority.assertCurrent();
|
|
108235
|
+
if (this.disposed || this.opts.signal?.aborted || this.abortGeneration !== startGeneration)
|
|
108236
|
+
throw this.staleCreationReason(startGeneration);
|
|
108237
|
+
} finally {
|
|
108238
|
+
if (this.routeAuthorityWait === wait)
|
|
108239
|
+
this.routeAuthorityWait = undefined;
|
|
108240
|
+
}
|
|
108241
|
+
}
|
|
108242
|
+
this.reportStartupPhase("resource-preparation");
|
|
108068
108243
|
this.applyCandidateThinking(candidate);
|
|
108069
108244
|
const stageOptions = buildStageSessionOptions({
|
|
108070
108245
|
effectiveStageOptions: this.effectiveStageOptions,
|
|
@@ -108077,6 +108252,11 @@ class StageSessionController {
|
|
|
108077
108252
|
try {
|
|
108078
108253
|
created = this.opts.adapters.agentSession ? await this.opts.adapters.agentSession.create(stripWorkflowOnlyOptions(stageOptions, this.opts.defaultSessionDir, this.meta, this.opts.pendingStageDelivery), {
|
|
108079
108254
|
...this.meta,
|
|
108255
|
+
startupSignal: this.startupWait.signal,
|
|
108256
|
+
onStartupPhase: (phase) => {
|
|
108257
|
+
if (this.abortGeneration === startGeneration)
|
|
108258
|
+
this.reportStartupPhase(phase);
|
|
108259
|
+
},
|
|
108080
108260
|
stageOptions,
|
|
108081
108261
|
...this.sharedOrchestrationContext !== undefined ? { orchestrationContext: this.sharedOrchestrationContext } : {}
|
|
108082
108262
|
}) : missingAdapter(consumer);
|
|
@@ -108095,20 +108275,28 @@ class StageSessionController {
|
|
|
108095
108275
|
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
108096
108276
|
throw this.staleCreationReason(startGeneration);
|
|
108097
108277
|
}
|
|
108278
|
+
this.reportStartupPhase("session-attachment");
|
|
108098
108279
|
const session = attachCreatedStageSession(created, this.disposed, this.opts.stageName, (result) => this.attachSession(result));
|
|
108099
108280
|
const attachedSession = session instanceof Promise ? await session : session;
|
|
108100
|
-
|
|
108101
|
-
|
|
108281
|
+
this.reportStartupPhase("delivery-readiness");
|
|
108282
|
+
try {
|
|
108283
|
+
await this.sharedOrchestrationContext?.pendingStageDelivery?.ready();
|
|
108284
|
+
await this.opts.onSessionReady?.();
|
|
108285
|
+
if (this.disposed || this.opts.signal?.aborted || this.abortGeneration !== startGeneration)
|
|
108286
|
+
throw this.staleCreationReason(startGeneration);
|
|
108287
|
+
} catch (reason) {
|
|
108288
|
+
if (this.session === attachedSession)
|
|
108289
|
+
this.session = undefined;
|
|
108102
108290
|
try {
|
|
108103
|
-
await
|
|
108291
|
+
await cleanupFailedStageSessionBinding(attachedSession, reason);
|
|
108104
108292
|
} catch (error) {
|
|
108105
|
-
if (
|
|
108106
|
-
this.
|
|
108107
|
-
await disposeStageSession(attachedSession).catch(() => {});
|
|
108293
|
+
if (error instanceof StageSessionBindingCleanupFailure)
|
|
108294
|
+
this.bindingCleanupFailure = error;
|
|
108108
108295
|
throw error;
|
|
108109
108296
|
}
|
|
108297
|
+
throw reason;
|
|
108110
108298
|
}
|
|
108111
|
-
|
|
108299
|
+
this.reportStartupPhase("ready");
|
|
108112
108300
|
return attachedSession;
|
|
108113
108301
|
}
|
|
108114
108302
|
attachSession(created) {
|
|
@@ -108194,6 +108382,7 @@ class StageSessionController {
|
|
|
108194
108382
|
this.lastPromptStartIndex = promptStartIndex;
|
|
108195
108383
|
this.unresolvedContextOverflowMessage = undefined;
|
|
108196
108384
|
try {
|
|
108385
|
+
this.reportStartupPhase("first-dispatch");
|
|
108197
108386
|
await activeSession.prompt(nextText, sdkOptions);
|
|
108198
108387
|
const pendingPauseAfterPrompt = this.pauseControl.currentResume();
|
|
108199
108388
|
if (pendingPauseAfterPrompt) {
|
|
@@ -108308,7 +108497,7 @@ class StageSessionController {
|
|
|
108308
108497
|
...usage === undefined ? {} : { usage },
|
|
108309
108498
|
error: message
|
|
108310
108499
|
});
|
|
108311
|
-
if (this.opts.signal?.aborted || terminalStageDelivery || !isRetryableModelFailure(err) || index === candidates.length - 1) {
|
|
108500
|
+
if (this.opts.signal?.aborted || this.startupWait.signal.aborted || terminalStageDelivery || !isRetryableModelFailure(err) || index === candidates.length - 1) {
|
|
108312
108501
|
this.modelWarnings.push(...this.pendingFallbackWarnings);
|
|
108313
108502
|
this.pendingFallbackWarnings.length = 0;
|
|
108314
108503
|
this.notifyModelFallbackMetaChange();
|
|
@@ -108957,9 +109146,7 @@ function createWorkflowStageFactory(input) {
|
|
|
108957
109146
|
toolEvents: [],
|
|
108958
109147
|
pendingStageDeliveryAvailable,
|
|
108959
109148
|
...shouldReplay ? {
|
|
108960
|
-
|
|
108961
|
-
endedAt: Date.now(),
|
|
108962
|
-
durationMs: 0,
|
|
109149
|
+
...stageTimingFields(replaySource),
|
|
108963
109150
|
...replaySource.result !== undefined ? { result: replaySource.result } : {},
|
|
108964
109151
|
...replaySource.sessionId !== undefined ? { sessionId: replaySource.sessionId } : {},
|
|
108965
109152
|
...replaySource.sessionFile !== undefined ? { sessionFile: replaySource.sessionFile } : {},
|
|
@@ -109022,11 +109209,19 @@ function createWorkflowStageFactory(input) {
|
|
|
109022
109209
|
signal: input.signal,
|
|
109023
109210
|
stageOptions: stageOptionsForContext,
|
|
109024
109211
|
...pendingStageDeliveryAvailable ? {
|
|
109212
|
+
routeAuthorityReady: () => workflowPendingStageRouteReady(input.activeStore, input.runId),
|
|
109025
109213
|
pendingStageDelivery: createWorkflowPendingStageDelivery(input.activeStore, input.runId, stageId, name)
|
|
109026
109214
|
} : {},
|
|
109027
109215
|
models: input.opts.models,
|
|
109028
109216
|
executionMode: input.opts.executionMode,
|
|
109029
109217
|
defaultSessionDir: input.opts.defaultSessionDir,
|
|
109218
|
+
onStartupChange(startup) {
|
|
109219
|
+
const current = input.activeStore.runs().find((run) => run.id === input.runId);
|
|
109220
|
+
if (!current?.stages.includes(stageSnapshot))
|
|
109221
|
+
return;
|
|
109222
|
+
stageSnapshot.startup = startup;
|
|
109223
|
+
input.activeStore.recordStageStart(input.runId, stageSnapshot);
|
|
109224
|
+
},
|
|
109030
109225
|
onModelFallbackMetaChange(meta) {
|
|
109031
109226
|
applyModelFallbackMeta(meta);
|
|
109032
109227
|
if (stageSnapshot.status === "running")
|
|
@@ -109189,6 +109384,7 @@ function createWorkflowStageFactory(input) {
|
|
|
109189
109384
|
stageId,
|
|
109190
109385
|
status: stageSnapshot.status,
|
|
109191
109386
|
durationMs: stageSnapshot.durationMs,
|
|
109387
|
+
endedAt: stageSnapshot.endedAt,
|
|
109192
109388
|
...stageSnapshot.error !== undefined ? { error: stageSnapshot.error } : {},
|
|
109193
109389
|
...stageSnapshot.failureKind !== undefined ? { failureKind: stageSnapshot.failureKind } : {},
|
|
109194
109390
|
...stageSnapshot.failureCode !== undefined ? { failureCode: stageSnapshot.failureCode } : {},
|
|
@@ -109794,6 +109990,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
109794
109990
|
};
|
|
109795
109991
|
};
|
|
109796
109992
|
const resolvePromptNodeTopology = createDurableStageTopologyResolver(durableBackend, runId);
|
|
109993
|
+
const priorPromptStageCheckpoints = durableBackend.listCheckpoints(runId).filter((checkpoint) => checkpoint.kind === "stage");
|
|
109797
109994
|
let promptNodeUi;
|
|
109798
109995
|
const getPromptNodeUi = () => {
|
|
109799
109996
|
promptNodeUi ??= buildPromptNodeUiAdapter({
|
|
@@ -109810,6 +110007,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
109810
110007
|
workflowExitSkippedReason: exit.workflowExitSkippedReason,
|
|
109811
110008
|
preserveWorkflowExitSkippedReason: exit.preserveWorkflowExitSkippedReason,
|
|
109812
110009
|
durableTopologyForReplayKey: resolvePromptNodeTopology,
|
|
110010
|
+
durableTimingForStageId: (stageId) => priorPromptStageCheckpoints.find((checkpoint) => checkpoint.topology?.stageId === stageId && checkpoint.topology.status === "completed" && (checkpoint.topology.run === undefined || checkpoint.topology.run.runId === runId)),
|
|
109813
110011
|
onPendingStage: async (pendingRunId, snapshot) => pendingRunId === runId ? void await recordDurableActiveStage(durableStageDeps, snapshot) : undefined
|
|
109814
110012
|
});
|
|
109815
110013
|
return promptNodeUi;
|
|
@@ -113063,6 +113261,8 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
113063
113261
|
return payload.handled && await payload.completion === true;
|
|
113064
113262
|
};
|
|
113065
113263
|
const announcedRoutes = new Map;
|
|
113264
|
+
const routeCompletions = new Map;
|
|
113265
|
+
const disposeReadiness = registerWorkflowPendingStageRouteReadiness(activeStore, (runId) => routeCompletions.get(runId));
|
|
113066
113266
|
const announceRoutes = () => {
|
|
113067
113267
|
if (disposed)
|
|
113068
113268
|
return;
|
|
@@ -113116,12 +113316,17 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
113116
113316
|
} catch (error) {
|
|
113117
113317
|
if (announcedRoutes.get(run.id) === entry)
|
|
113118
113318
|
announcedRoutes.delete(run.id);
|
|
113319
|
+
const failure = Promise.reject(error);
|
|
113320
|
+
failure.catch(() => {});
|
|
113321
|
+
routeCompletions.set(run.id, failure);
|
|
113119
113322
|
throw error;
|
|
113120
113323
|
}
|
|
113121
113324
|
const completion = announcement.completion;
|
|
113122
113325
|
if (completion === undefined) {
|
|
113123
113326
|
announcedRoutes.delete(run.id);
|
|
113327
|
+
routeCompletions.delete(run.id);
|
|
113124
113328
|
} else {
|
|
113329
|
+
routeCompletions.set(run.id, completion);
|
|
113125
113330
|
completion.catch(() => {
|
|
113126
113331
|
if (announcedRoutes.get(run.id) === entry)
|
|
113127
113332
|
announcedRoutes.delete(run.id);
|
|
@@ -113132,6 +113337,10 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
113132
113337
|
if (!ownedRunIds.has(runId))
|
|
113133
113338
|
announcedRoutes.delete(runId);
|
|
113134
113339
|
}
|
|
113340
|
+
for (const runId of routeCompletions.keys()) {
|
|
113341
|
+
if (!ownedRunIds.has(runId))
|
|
113342
|
+
routeCompletions.delete(runId);
|
|
113343
|
+
}
|
|
113135
113344
|
sweepPromise = sweepPromise.then(() => settleUndeliverablePendingStageMessages(activeStore, notifyUndeliverable)).then(() => {
|
|
113136
113345
|
return;
|
|
113137
113346
|
}).catch((error) => reportWarning(`atomic-workflows: pending stage delivery sweep failed: ${error.message}`));
|
|
@@ -113210,6 +113419,8 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
|
|
|
113210
113419
|
});
|
|
113211
113420
|
const dispose = () => {
|
|
113212
113421
|
disposed = true;
|
|
113422
|
+
disposeReadiness();
|
|
113423
|
+
routeCompletions.clear();
|
|
113213
113424
|
unsubscribeStore();
|
|
113214
113425
|
if (typeof subscription === "function")
|
|
113215
113426
|
subscription();
|
|
@@ -113696,6 +113907,8 @@ function resolveSessionCwd(options) {
|
|
|
113696
113907
|
return options?.cwd ?? options?.sessionManager?.getCwd() ?? process.cwd();
|
|
113697
113908
|
}
|
|
113698
113909
|
async function prepareAtomicStageSessionOptions(options, sdk, prepareOptions = {}) {
|
|
113910
|
+
prepareOptions.signal?.throwIfAborted();
|
|
113911
|
+
prepareOptions.onStartupPhase?.("resource-preparation");
|
|
113699
113912
|
const atomicOptions = options;
|
|
113700
113913
|
if (atomicOptions?.resourceLoader !== undefined)
|
|
113701
113914
|
return atomicOptions;
|
|
@@ -113714,7 +113927,8 @@ async function prepareAtomicStageSessionOptions(options, sdk, prepareOptions = {
|
|
|
113714
113927
|
resourceLoaderInheritanceSnapshot: inheritanceSnapshot,
|
|
113715
113928
|
builtinPackagePaths: stageBuiltinPackagePaths(builtinPackagePaths)
|
|
113716
113929
|
});
|
|
113717
|
-
await reloadWorkflowStageResources(resourceLoader);
|
|
113930
|
+
await reloadWorkflowStageResources(resourceLoader, prepareOptions);
|
|
113931
|
+
prepareOptions.signal?.throwIfAborted();
|
|
113718
113932
|
return {
|
|
113719
113933
|
...atomicOptions,
|
|
113720
113934
|
cwd,
|
|
@@ -113751,8 +113965,13 @@ function stageBuiltinPackagePaths(paths) {
|
|
|
113751
113965
|
});
|
|
113752
113966
|
}
|
|
113753
113967
|
var workflowStageResourceReloadQueue = Promise.resolve();
|
|
113754
|
-
async function reloadWorkflowStageResources(resourceLoader) {
|
|
113755
|
-
|
|
113968
|
+
async function reloadWorkflowStageResources(resourceLoader, options) {
|
|
113969
|
+
options.onStartupPhase?.("reload-queued");
|
|
113970
|
+
const queuedReload = workflowStageResourceReloadQueue.then(() => {
|
|
113971
|
+
options.signal?.throwIfAborted();
|
|
113972
|
+
options.onStartupPhase?.("reload-active");
|
|
113973
|
+
return resourceLoader.reload();
|
|
113974
|
+
});
|
|
113756
113975
|
workflowStageResourceReloadQueue = queuedReload.catch(() => {
|
|
113757
113976
|
return;
|
|
113758
113977
|
});
|
|
@@ -113787,8 +114006,8 @@ function attachSettingsManager(error, settingsManager) {
|
|
|
113787
114006
|
});
|
|
113788
114007
|
return wrapped;
|
|
113789
114008
|
}
|
|
113790
|
-
async function createPiSdkAgentSession(options, prepareOptions) {
|
|
113791
|
-
const sdk = await import("@bastani/atomic");
|
|
114009
|
+
async function createPiSdkAgentSession(options, prepareOptions, injectedSdk) {
|
|
114010
|
+
const sdk = injectedSdk ?? await import("@bastani/atomic");
|
|
113792
114011
|
let settingsManager;
|
|
113793
114012
|
try {
|
|
113794
114013
|
const sessionOptions = await prepareAtomicStageSessionOptions(options, sdk, {
|
|
@@ -113799,6 +114018,8 @@ async function createPiSdkAgentSession(options, prepareOptions) {
|
|
|
113799
114018
|
}
|
|
113800
114019
|
});
|
|
113801
114020
|
settingsManager = sessionOptions?.settingsManager ?? settingsManager;
|
|
114021
|
+
prepareOptions?.signal?.throwIfAborted();
|
|
114022
|
+
prepareOptions?.onStartupPhase?.("sdk-creation");
|
|
113802
114023
|
const result = await sdk.createAgentSession(sessionOptions);
|
|
113803
114024
|
const resultSettingsManager = result.session.settingsManager;
|
|
113804
114025
|
settingsManager = sessionOptions?.settingsManager ?? resultSettingsManager ?? settingsManager;
|
|
@@ -114058,20 +114279,25 @@ function makeStageExtensionUiContext(ui, meta, broker) {
|
|
|
114058
114279
|
};
|
|
114059
114280
|
}
|
|
114060
114281
|
function buildRuntimeAdapters(pi, options = {}) {
|
|
114061
|
-
const createSession = options.createAgentSession ?? pi.createAgentSession ?? (isTestContext() ? createTestAgentSession : (sessionOptions) => createPiSdkAgentSession(sessionOptions, {
|
|
114062
|
-
resourceLoaderInheritanceSnapshot: pi.getResourceLoaderInheritanceSnapshot?.()
|
|
114063
|
-
|
|
114282
|
+
const createSession = options.createAgentSession ?? pi.createAgentSession ?? (isTestContext() && options.sdk === undefined ? createTestAgentSession : (sessionOptions, prepareOptions) => createPiSdkAgentSession(sessionOptions, {
|
|
114283
|
+
resourceLoaderInheritanceSnapshot: pi.getResourceLoaderInheritanceSnapshot?.(),
|
|
114284
|
+
...prepareOptions
|
|
114285
|
+
}, options.sdk));
|
|
114064
114286
|
const broker = options.stageUiBroker ?? stageUiBroker;
|
|
114065
114287
|
const adapters = {
|
|
114066
114288
|
agentSession: {
|
|
114067
114289
|
async create(stageOptions, meta) {
|
|
114068
114290
|
const sessionOptions = withWorkflowStageSessionOptions(stripWorkflowOnlyOptions2(stageOptions) ?? {}, meta, pi);
|
|
114069
|
-
const
|
|
114291
|
+
const signal = meta?.startupSignal ?? meta?.signal;
|
|
114292
|
+
const result = await createSession(sessionOptions, { signal, onStartupPhase: meta?.onStartupPhase });
|
|
114070
114293
|
const bindable = result.session;
|
|
114071
114294
|
try {
|
|
114295
|
+
signal?.throwIfAborted();
|
|
114296
|
+
meta?.onStartupPhase?.("extension-binding");
|
|
114072
114297
|
if (typeof bindable.bindExtensions === "function") {
|
|
114073
114298
|
await bindable.bindExtensions(shouldBindStageUiContext(pi, meta) ? { uiContext: makeStageExtensionUiContext(pi.ui ?? {}, meta, broker) } : {});
|
|
114074
114299
|
}
|
|
114300
|
+
signal?.throwIfAborted();
|
|
114075
114301
|
} catch (error) {
|
|
114076
114302
|
await cleanupFailedStageSessionBinding(result.session, error);
|
|
114077
114303
|
throw error;
|
|
@@ -115639,7 +115865,21 @@ Picker requires an interactive UI surface. Pass a runId: /workflow attach <id> [
|
|
|
115639
115865
|
return true;
|
|
115640
115866
|
runId = picked.runId;
|
|
115641
115867
|
} else if (action === "resume") {
|
|
115642
|
-
|
|
115868
|
+
let backend;
|
|
115869
|
+
try {
|
|
115870
|
+
try {
|
|
115871
|
+
backend = getDurableBackend();
|
|
115872
|
+
} catch (error) {
|
|
115873
|
+
if (!(error instanceof DbosNotReadyError))
|
|
115874
|
+
throw error;
|
|
115875
|
+
await ensureWorkflowResourcesVisible();
|
|
115876
|
+
await deps.runtimeForContext(ctx).prepareDurableResumable(target);
|
|
115877
|
+
backend = getDurableBackend();
|
|
115878
|
+
}
|
|
115879
|
+
} catch (error) {
|
|
115880
|
+
fail(`Failed to resolve workflow resume target: ${error instanceof Error ? error.message : String(error)}`);
|
|
115881
|
+
return true;
|
|
115882
|
+
}
|
|
115643
115883
|
const localResolution = resolveRunId(target);
|
|
115644
115884
|
const localBeforePreparation = localResolution.kind === "exact" ? store.runs().find((run) => run.id === localResolution.runId) : undefined;
|
|
115645
115885
|
const exactBeforePreparation = localBeforePreparation?.id === target ? localBeforePreparation : undefined;
|
|
@@ -116493,6 +116733,8 @@ function renderStagesToolContent(result) {
|
|
|
116493
116733
|
lines.push("stages:");
|
|
116494
116734
|
result.stages.forEach((stage, index) => {
|
|
116495
116735
|
lines.push(`[${index + 1}] ${stage.name} (${stage.id}) ${stage.status}`);
|
|
116736
|
+
if (stage.startup)
|
|
116737
|
+
lines.push(formatStageStartup(stage.startup));
|
|
116496
116738
|
if (stage.sessionId)
|
|
116497
116739
|
lines.push(`sessionId: ${stage.sessionId}`);
|
|
116498
116740
|
if (stage.sessionFile)
|
|
@@ -116533,6 +116775,8 @@ function renderStageToolContent(result) {
|
|
|
116533
116775
|
`);
|
|
116534
116776
|
}
|
|
116535
116777
|
lines.push("stage:");
|
|
116778
|
+
if (result.stage.startup)
|
|
116779
|
+
lines.push(formatStageStartup(result.stage.startup));
|
|
116536
116780
|
lines.push(JSON.stringify(result.stage, null, 2));
|
|
116537
116781
|
if (result.stage.sessionFile) {
|
|
116538
116782
|
lines.push(`transcriptPath: ${result.stage.sessionFile}`);
|
|
@@ -117011,6 +117255,7 @@ function summarizeStage(stage) {
|
|
|
117011
117255
|
id: stage.id,
|
|
117012
117256
|
name: stage.name,
|
|
117013
117257
|
status: stage.status,
|
|
117258
|
+
...stage.startup === undefined ? {} : { startup: { ...stage.startup } },
|
|
117014
117259
|
sessionId: stage.sessionId,
|
|
117015
117260
|
sessionFile: stage.sessionFile,
|
|
117016
117261
|
transcriptPath: stage.sessionFile,
|