@bastani/atomic 0.8.26-alpha.4 → 0.8.26-alpha.6
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 +12 -0
- package/dist/builtin/intercom/CHANGELOG.md +12 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +12 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +12 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +48 -10
- package/dist/builtin/subagents/src/runs/foreground/execution.ts +30 -9
- package/dist/builtin/subagents/src/runs/shared/final-drain.ts +34 -0
- package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +416 -7
- package/dist/builtin/web-access/CHANGELOG.md +12 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +12 -0
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +6 -6
- package/dist/builtin/workflows/builtin/goal.ts +10 -10
- package/dist/builtin/workflows/builtin/open-claude-design.ts +4 -4
- package/dist/builtin/workflows/builtin/ralph.ts +16 -16
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.ts +10 -2
- package/dist/builtin/workflows/src/extension/runtime.ts +35 -3
- package/dist/builtin/workflows/src/runs/background/status.ts +52 -6
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +441 -15
- package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +69 -8
- package/dist/builtin/workflows/src/runs/shared/model-fallback.ts +402 -8
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +182 -6
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +76 -6
- package/dist/builtin/workflows/src/shared/stage-prompt.ts +33 -2
- package/dist/builtin/workflows/src/shared/store-types.ts +31 -0
- package/dist/builtin/workflows/src/shared/store.ts +99 -11
- package/dist/builtin/workflows/src/shared/workflow-failures.ts +758 -132
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +74 -74
- package/dist/core/tools/ask-user-question/tool/format-answer.d.ts +5 -5
- package/dist/core/tools/ask-user-question/tool/format-answer.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/tool/format-answer.js +5 -5
- package/dist/core/tools/ask-user-question/tool/format-answer.js.map +1 -1
- package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts +16 -3
- package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/tool/response-envelope.js +21 -3
- package/dist/core/tools/ask-user-question/tool/response-envelope.js.map +1 -1
- package/package.json +1 -1
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
import { validateWorkflowModels } from "../runs/shared/model-fallback.js";
|
|
45
45
|
import { runDetached } from "../runs/background/runner.js";
|
|
46
46
|
import type { JobTracker } from "../runs/background/job-tracker.js";
|
|
47
|
+
import { appendRunEnd } from "../shared/persistence-session-entries.js";
|
|
47
48
|
import { classifyWorkflowFailure } from "../shared/workflow-failures.js";
|
|
48
49
|
|
|
49
50
|
// ---------------------------------------------------------------------------
|
|
@@ -389,13 +390,39 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
389
390
|
return { ok: true, stageId: failedStageId };
|
|
390
391
|
}
|
|
391
392
|
|
|
393
|
+
function finalizeResumedActiveBlockedSourceRun(source: RunSnapshot, continuationRunId: string): void {
|
|
394
|
+
const errorMessage = source.error ?? source.failureMessage ?? `workflow resumed in new run ${continuationRunId}`;
|
|
395
|
+
const metadata = {
|
|
396
|
+
...(source.failureKind !== undefined ? { failureKind: source.failureKind } : {}),
|
|
397
|
+
...(source.failureCode !== undefined ? { failureCode: source.failureCode } : {}),
|
|
398
|
+
failureRecoverability: "non_recoverable",
|
|
399
|
+
failureDisposition: "terminal_killed",
|
|
400
|
+
...(source.failureMessage !== undefined ? { failureMessage: source.failureMessage } : {}),
|
|
401
|
+
...(source.failedStageId !== undefined ? { failedStageId: source.failedStageId } : {}),
|
|
402
|
+
resumable: false,
|
|
403
|
+
...(source.retryAfterMs !== undefined ? { retryAfterMs: source.retryAfterMs } : {}),
|
|
404
|
+
} as const;
|
|
405
|
+
const recorded = activeStore.recordRunEnd(source.id, "killed", undefined, errorMessage, metadata);
|
|
406
|
+
if (recorded && persistence !== undefined) {
|
|
407
|
+
appendRunEnd(persistence, {
|
|
408
|
+
runId: source.id,
|
|
409
|
+
status: "killed",
|
|
410
|
+
error: errorMessage,
|
|
411
|
+
...metadata,
|
|
412
|
+
ts: Date.now(),
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
392
417
|
function resumeFailedRun(sourceRunId: string, stageId?: string, options?: RuntimeDispatchOptions): ResumeFailedRunResult {
|
|
393
418
|
const source = activeStore.runs().find((run) => run.id === sourceRunId);
|
|
394
419
|
if (source === undefined) {
|
|
395
420
|
return { ok: false, reason: "run_not_found", message: `run not found: ${sourceRunId}` };
|
|
396
421
|
}
|
|
397
|
-
|
|
398
|
-
|
|
422
|
+
const isTerminalFailedResumable = source.status === "failed" && source.endedAt !== undefined && source.resumable !== false;
|
|
423
|
+
const isActiveBlockedResumable = source.endedAt === undefined && source.resumable === true && source.failureRecoverability === "recoverable";
|
|
424
|
+
if (!isTerminalFailedResumable && !isActiveBlockedResumable) {
|
|
425
|
+
return { ok: false, reason: "not_resumable", message: `run ${sourceRunId} is not a resumable workflow run` };
|
|
399
426
|
}
|
|
400
427
|
const def = registry.get(source.name);
|
|
401
428
|
if (def === undefined) {
|
|
@@ -415,12 +442,17 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
415
442
|
...runOptions({ workflow: def.name, inputs: sourceInputs }, options?.policy),
|
|
416
443
|
continuation: { source, resumeFromStageId: resolvedStage.stageId },
|
|
417
444
|
});
|
|
445
|
+
if (isActiveBlockedResumable) {
|
|
446
|
+
finalizeResumedActiveBlockedSourceRun(source, accepted.runId);
|
|
447
|
+
}
|
|
418
448
|
return {
|
|
419
449
|
ok: true,
|
|
420
450
|
runId: accepted.runId,
|
|
421
451
|
sourceRunId: source.id,
|
|
422
452
|
resumeFromStageId: resolvedStage.stageId,
|
|
423
|
-
message:
|
|
453
|
+
message: isActiveBlockedResumable
|
|
454
|
+
? `Resuming blocked workflow "${def.name}" from run ${source.id.slice(0, 8)} at stage ${resolvedStage.stageId.slice(0, 8)} (new run ${accepted.runId}).`
|
|
455
|
+
: `Resuming failed workflow "${def.name}" from run ${source.id.slice(0, 8)} at stage ${resolvedStage.stageId.slice(0, 8)} (new run ${accepted.runId}).`,
|
|
424
456
|
};
|
|
425
457
|
}
|
|
426
458
|
|
|
@@ -82,6 +82,14 @@ export interface RunDetail {
|
|
|
82
82
|
readonly stages: readonly RunSnapshot["stages"][number][];
|
|
83
83
|
readonly result?: WorkflowOutputValues;
|
|
84
84
|
readonly error?: string;
|
|
85
|
+
readonly failureKind?: RunSnapshot["failureKind"];
|
|
86
|
+
readonly failureCode?: RunSnapshot["failureCode"];
|
|
87
|
+
readonly failureRecoverability?: RunSnapshot["failureRecoverability"];
|
|
88
|
+
readonly failureDisposition?: RunSnapshot["failureDisposition"];
|
|
89
|
+
readonly failedStageId?: string;
|
|
90
|
+
readonly resumable?: boolean;
|
|
91
|
+
readonly retryAfterMs?: number;
|
|
92
|
+
readonly blockedAt?: number;
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
export type InspectRunResult =
|
|
@@ -146,11 +154,26 @@ export function killRun(
|
|
|
146
154
|
const previousStatus = run.status;
|
|
147
155
|
|
|
148
156
|
// Abort active executor (no-op if not registered)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
157
|
+
const errorMessage = "workflow killed";
|
|
158
|
+
opts?.cancellation?.abort(runId, errorMessage);
|
|
159
|
+
|
|
160
|
+
const metadata = {
|
|
161
|
+
failureKind: "cancelled",
|
|
162
|
+
failureCode: "cancelled",
|
|
163
|
+
failureRecoverability: "non_recoverable",
|
|
164
|
+
failureDisposition: "terminal_killed",
|
|
165
|
+
failureMessage: errorMessage,
|
|
166
|
+
resumable: false,
|
|
167
|
+
} as const;
|
|
168
|
+
const recorded = activeStore.recordRunEnd(runId, "killed", undefined, errorMessage, metadata);
|
|
152
169
|
if (recorded && opts?.persistence) {
|
|
153
|
-
appendRunEnd(opts.persistence, {
|
|
170
|
+
appendRunEnd(opts.persistence, {
|
|
171
|
+
runId,
|
|
172
|
+
status: "killed",
|
|
173
|
+
error: errorMessage,
|
|
174
|
+
...metadata,
|
|
175
|
+
ts: Date.now(),
|
|
176
|
+
});
|
|
154
177
|
}
|
|
155
178
|
|
|
156
179
|
return { ok: true, runId, previousStatus };
|
|
@@ -247,14 +270,29 @@ export function resumeRun(
|
|
|
247
270
|
// Return a deep copy of the snapshot for safe consumption
|
|
248
271
|
const snapshot = structuredClone(run);
|
|
249
272
|
const resumedCopy = structuredClone(resumed);
|
|
250
|
-
if (run.status === "
|
|
273
|
+
if (run.status === "killed" || run.resumable === false) {
|
|
251
274
|
return {
|
|
252
275
|
ok: true,
|
|
253
276
|
runId,
|
|
254
277
|
snapshot,
|
|
255
278
|
resumed: resumedCopy,
|
|
256
279
|
mode: "not_resumable",
|
|
257
|
-
message: "This
|
|
280
|
+
message: "This workflow is not resumable; inspect the snapshot and start a new workflow run when ready.",
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
if (
|
|
284
|
+
run.endedAt === undefined &&
|
|
285
|
+
run.resumable === true &&
|
|
286
|
+
run.failureRecoverability === "recoverable" &&
|
|
287
|
+
run.failedStageId !== undefined
|
|
288
|
+
) {
|
|
289
|
+
return {
|
|
290
|
+
ok: true,
|
|
291
|
+
runId,
|
|
292
|
+
snapshot,
|
|
293
|
+
resumed: resumedCopy,
|
|
294
|
+
mode: resumedCopy.length > 0 ? "paused" : "snapshot",
|
|
295
|
+
message: `Workflow is blocked on a recoverable ${run.failureCode ?? run.failureKind ?? "workflow"} failure at stage ${run.failedStageId}; retry/resume after the issue clears.`,
|
|
258
296
|
};
|
|
259
297
|
}
|
|
260
298
|
return {
|
|
@@ -441,6 +479,14 @@ export function inspectRun(
|
|
|
441
479
|
stages: expandedStages.map((stage) => structuredClone(stage)),
|
|
442
480
|
result: copy.result,
|
|
443
481
|
error: copy.error,
|
|
482
|
+
failureKind: copy.failureKind,
|
|
483
|
+
failureCode: copy.failureCode,
|
|
484
|
+
failureRecoverability: copy.failureRecoverability,
|
|
485
|
+
failureDisposition: copy.failureDisposition,
|
|
486
|
+
failedStageId: copy.failedStageId,
|
|
487
|
+
resumable: copy.resumable,
|
|
488
|
+
retryAfterMs: copy.retryAfterMs,
|
|
489
|
+
blockedAt: copy.blockedAt,
|
|
444
490
|
};
|
|
445
491
|
|
|
446
492
|
return { ok: true, runId: copy.id, detail };
|