@bastani/atomic 0.9.12 → 0.9.13-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 +20 -0
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/README.md +5 -12
- package/dist/builtin/intercom/broker/client.ts +11 -2
- package/dist/builtin/intercom/contact-supervisor-tool.ts +13 -3
- package/dist/builtin/intercom/index-heavy.ts +13 -3
- package/dist/builtin/intercom/index.ts +43 -19
- package/dist/builtin/intercom/intercom-utils.ts +15 -29
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/source-ownership.ts +9 -12
- package/dist/builtin/mcp/CHANGELOG.md +6 -0
- package/dist/builtin/mcp/README.md +3 -1
- package/dist/builtin/mcp/index.ts +10 -16
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/mcp/startup-warmup.ts +20 -8
- package/dist/builtin/subagents/CHANGELOG.md +30 -0
- package/dist/builtin/subagents/README.md +22 -30
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/extension/doctor.ts +1 -1
- package/dist/builtin/subagents/src/extension/fanout-child.ts +76 -56
- package/dist/builtin/subagents/src/extension/index.ts +23 -32
- package/dist/builtin/subagents/src/extension/startup-maintenance.ts +25 -44
- package/dist/builtin/subagents/src/intercom/result-intercom.ts +7 -7
- package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +166 -434
- package/dist/builtin/subagents/src/runs/background/notify.ts +29 -8
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +4 -4
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +1 -281
- package/dist/builtin/subagents/src/runs/foreground/execution-structured-retries.ts +11 -75
- package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +457 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +119 -246
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +1 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +18 -9
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +1 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +4 -4
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +1 -646
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-runtime.ts +2 -7
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +5 -5
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +7 -8
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +14 -5
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +158 -93
- package/dist/builtin/subagents/src/runs/inprocess/background-single.ts +179 -0
- package/dist/builtin/subagents/src/runs/inprocess/background.ts +89 -0
- package/dist/builtin/subagents/src/runs/inprocess/child-policy.ts +27 -0
- package/dist/builtin/subagents/src/runs/inprocess/control-registry.ts +55 -0
- package/dist/builtin/subagents/src/runs/inprocess/control-status.ts +106 -0
- package/dist/builtin/subagents/src/runs/inprocess/index.ts +50 -0
- package/dist/builtin/subagents/src/runs/inprocess/nested-routing.ts +218 -0
- package/dist/builtin/subagents/src/runs/{shared/subagent-prompt-runtime.ts → inprocess/prompt-behavior.ts} +37 -75
- package/dist/builtin/subagents/src/runs/inprocess/runner.ts +1138 -0
- package/dist/builtin/subagents/src/runs/{shared/nested-events.ts → inprocess/runtime-support/nested-api.ts} +13 -7
- package/dist/builtin/subagents/src/runs/{shared/nested-events-control.ts → inprocess/runtime-support/nested-control.ts} +18 -17
- package/dist/builtin/subagents/src/runs/{shared/nested-events-core.ts → inprocess/runtime-support/nested-core.ts} +14 -61
- package/dist/builtin/subagents/src/runs/{shared/nested-events-projection.ts → inprocess/runtime-support/nested-projection.ts} +4 -10
- package/dist/builtin/subagents/src/runs/{shared/nested-events-registry.ts → inprocess/runtime-support/nested-registry.ts} +19 -4
- package/dist/builtin/subagents/src/runs/{shared/nested-render.ts → inprocess/runtime-support/nested-rendering.ts} +3 -3
- package/dist/builtin/subagents/src/runs/{shared/nested-events-sanitize.ts → inprocess/runtime-support/nested-sanitize.ts} +3 -3
- package/dist/builtin/subagents/src/runs/inprocess.ts +1 -0
- package/dist/builtin/subagents/src/runs/shared/dynamic-fanout.ts +10 -4
- package/dist/builtin/subagents/src/runs/shared/model-candidate-filter.ts +0 -1
- package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +15 -492
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +13 -11
- package/dist/builtin/subagents/src/runs/shared/run-history.ts +3 -5
- package/dist/builtin/subagents/src/runs/shared/single-output.ts +4 -4
- package/dist/builtin/subagents/src/runs/shared/workflow-graph.ts +5 -5
- package/dist/builtin/subagents/src/shared/types-async.ts +0 -1
- package/dist/builtin/subagents/src/shared/types-config.ts +18 -0
- package/dist/builtin/subagents/src/shared/types-results.ts +9 -2
- package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +2 -3
- package/dist/builtin/subagents/src/slash/slash-live-state.ts +2 -2
- package/dist/builtin/subagents/src/tui/render-chain-graph.ts +10 -4
- package/dist/builtin/subagents/src/tui/render-event-formatting.ts +12 -11
- package/dist/builtin/subagents/src/tui/render-result-compact.ts +49 -12
- package/dist/builtin/subagents/src/tui/render-result.ts +46 -17
- package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -1
- package/dist/builtin/subagents/src/tui/render-status-progress.ts +8 -5
- package/dist/builtin/subagents/src/tui/render-widget-graph.ts +0 -8
- package/dist/builtin/subagents/src/tui/render-widget.ts +0 -24
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +25 -0
- package/dist/builtin/workflows/README.md +13 -3
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/durable/backend.ts +7 -0
- package/dist/builtin/workflows/src/durable/dbos-metadata.ts +11 -1
- package/dist/builtin/workflows/src/durable/resume-runtime.ts +1 -0
- package/dist/builtin/workflows/src/durable/tool-primitive.ts +4 -28
- package/dist/builtin/workflows/src/durable/types.ts +5 -0
- package/dist/builtin/workflows/src/engine/run.ts +17 -1
- package/dist/builtin/workflows/src/extension/atomic-stage-session.ts +12 -39
- package/dist/builtin/workflows/src/extension/config-file-loader.ts +10 -1
- package/dist/builtin/workflows/src/extension/config-loader.ts +1 -1
- package/dist/builtin/workflows/src/extension/dispatcher.ts +4 -0
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +1151 -737
- package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +303 -38
- package/dist/builtin/workflows/src/extension/render-result.ts +4 -0
- package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +6 -3
- package/dist/builtin/workflows/src/extension/runtime.ts +7 -1
- package/dist/builtin/workflows/src/extension/wiring.ts +53 -11
- package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +12 -3
- package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +5 -2
- package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +9 -7
- package/dist/builtin/workflows/src/extension/workflow-status-summary.ts +11 -0
- package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +18 -1
- package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +10 -8
- package/dist/builtin/workflows/src/extension/workflow-tool.ts +9 -4
- package/dist/builtin/workflows/src/runs/background/quit.ts +28 -4
- package/dist/builtin/workflows/src/runs/background/resume-acknowledgements.ts +2 -1
- package/dist/builtin/workflows/src/runs/background/status.ts +55 -8
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +4 -0
- package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +3 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +688 -38
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +3 -1
- package/dist/builtin/workflows/src/runs/shared/model-fallback-failures.ts +19 -514
- package/dist/builtin/workflows/src/runs/shared/retry.ts +44 -0
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +5 -0
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +6 -0
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +5 -1
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +5 -0
- package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +5 -0
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +3 -0
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
- package/dist/builtin/workflows/src/shared/run-indicator-status.ts +75 -0
- package/dist/builtin/workflows/src/shared/store-public-types.ts +43 -7
- package/dist/builtin/workflows/src/shared/store-run-methods.ts +42 -8
- package/dist/builtin/workflows/src/shared/store-stage-methods.ts +31 -8
- package/dist/builtin/workflows/src/shared/store-types.ts +34 -0
- package/dist/builtin/workflows/src/shared/timing.ts +10 -0
- package/dist/builtin/workflows/src/tui/chat-surface-message.ts +22 -2
- package/dist/builtin/workflows/src/tui/session-list.ts +1 -1
- package/dist/builtin/workflows/src/tui/session-overlays.ts +14 -10
- package/dist/builtin/workflows/src/tui/session-picker.ts +20 -4
- package/dist/builtin/workflows/src/tui/status-list.ts +31 -47
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +9 -1
- package/dist/builtin/workflows/src/tui/widget.ts +16 -46
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +54 -11
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +49 -14
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +13 -0
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-models.d.ts.map +1 -1
- package/dist/core/agent-session-models.js +12 -1
- package/dist/core/agent-session-models.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +4 -0
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts +21 -4
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +232 -106
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-state.d.ts.map +1 -1
- package/dist/core/agent-session-state.js +2 -1
- package/dist/core/agent-session-state.js.map +1 -1
- package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
- package/dist/core/agent-session-tool-hooks.js +12 -0
- package/dist/core/agent-session-tool-hooks.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +1 -1
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +3 -1
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +7 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +25 -0
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner-context.d.ts +2 -1
- package/dist/core/extensions/runner-context.d.ts.map +1 -1
- package/dist/core/extensions/runner-context.js +4 -0
- package/dist/core/extensions/runner-context.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -2
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/model-fallback-failures.d.ts +30 -0
- package/dist/core/model-fallback-failures.d.ts.map +1 -0
- package/dist/core/model-fallback-failures.js +610 -0
- package/dist/core/model-fallback-failures.js.map +1 -0
- package/dist/core/retry-policy.d.ts +30 -0
- package/dist/core/retry-policy.d.ts.map +1 -0
- package/dist/core/retry-policy.js +25 -0
- package/dist/core/retry-policy.js.map +1 -0
- package/dist/core/sdk-types.d.ts +8 -2
- package/dist/core/sdk-types.d.ts.map +1 -1
- package/dist/core/sdk-types.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +6 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager-core.d.ts +2 -0
- package/dist/core/session-manager-core.d.ts.map +1 -1
- package/dist/core/session-manager-core.js +7 -0
- package/dist/core/session-manager-core.js.map +1 -1
- package/dist/index-extensions.d.ts +1 -1
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/docs/intercom.md +5 -10
- package/docs/settings.md +7 -1
- package/docs/subagents.md +19 -19
- package/docs/workflows.md +21 -5
- package/examples/extensions/gondolin/package-lock.json +3 -3
- package/npm-shrinkwrap.json +29 -29
- package/package.json +2 -2
- package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +0 -112
- package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +0 -543
- package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +0 -140
- package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +0 -279
- package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +0 -99
- package/dist/builtin/subagents/src/runs/background/async-execution.ts +0 -17
- package/dist/builtin/subagents/src/runs/background/async-resume.ts +0 -402
- package/dist/builtin/subagents/src/runs/background/async-status.ts +0 -411
- package/dist/builtin/subagents/src/runs/background/completion-claims.ts +0 -196
- package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +0 -102
- package/dist/builtin/subagents/src/runs/background/parallel-groups.ts +0 -59
- package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +0 -300
- package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +0 -166
- package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +0 -77
- package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +0 -48
- package/dist/builtin/subagents/src/runs/background/result-status.ts +0 -87
- package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +0 -72
- package/dist/builtin/subagents/src/runs/background/result-watcher.ts +0 -320
- package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +0 -105
- package/dist/builtin/subagents/src/runs/background/run-status.ts +0 -358
- package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +0 -457
- package/dist/builtin/subagents/src/runs/background/subagent-runner-dynamic.ts +0 -376
- package/dist/builtin/subagents/src/runs/background/subagent-runner-finalize.ts +0 -150
- package/dist/builtin/subagents/src/runs/background/subagent-runner-output.ts +0 -109
- package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel-helpers.ts +0 -128
- package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel.ts +0 -309
- package/dist/builtin/subagents/src/runs/background/subagent-runner-sequential.ts +0 -173
- package/dist/builtin/subagents/src/runs/background/subagent-runner-state.ts +0 -578
- package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +0 -330
- package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +0 -330
- package/dist/builtin/subagents/src/runs/background/subagent-runner-types.ts +0 -210
- package/dist/builtin/subagents/src/runs/background/subagent-runner-utils.ts +0 -69
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +0 -90
- package/dist/builtin/subagents/src/runs/background/top-level-async.ts +0 -12
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt-control.ts +0 -140
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +0 -108
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt-types.ts +0 -17
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +0 -558
- package/dist/builtin/subagents/src/runs/shared/attempt-watchdog.ts +0 -126
- package/dist/builtin/subagents/src/runs/shared/final-drain.ts +0 -39
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +0 -339
- package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +0 -165
- package/dist/builtin/subagents/src/runs/shared/spawn-env.ts +0 -21
- package/dist/builtin/subagents/src/shared/post-exit-stdio-guard.ts +0 -86
- /package/dist/builtin/subagents/src/runs/{shared/nested-path.ts → inprocess/runtime-support/nested-paths.ts} +0 -0
|
@@ -36157,6 +36157,10 @@ function topLevelWorkflowRuns(runs) {
|
|
|
36157
36157
|
function nonNegative(ms) {
|
|
36158
36158
|
return Math.max(0, ms);
|
|
36159
36159
|
}
|
|
36160
|
+
function nextControlTimestamp(requestedAt, previousAt) {
|
|
36161
|
+
const candidate = requestedAt ?? Date.now();
|
|
36162
|
+
return previousAt === undefined || candidate > previousAt ? candidate : previousAt + 1;
|
|
36163
|
+
}
|
|
36160
36164
|
function rebasedStageStartedAt(accumulatedDurationMs, resumedAt) {
|
|
36161
36165
|
return resumedAt - nonNegative(accumulatedDurationMs ?? 0);
|
|
36162
36166
|
}
|
|
@@ -36333,38 +36337,65 @@ function createRunStoreMethods(context) {
|
|
|
36333
36337
|
if (TERMINAL_STATUSES.has(run.status))
|
|
36334
36338
|
return false;
|
|
36335
36339
|
const wasPaused = run.status === "paused";
|
|
36336
|
-
const enteringQuit = metadata?.exitReason === "quit" && run.exitReason !== "quit";
|
|
36337
36340
|
if (!wasPaused) {
|
|
36338
36341
|
run.status = "paused";
|
|
36339
|
-
run.pausedAt = pausedAt
|
|
36342
|
+
run.pausedAt = nextControlTimestamp(pausedAt, run.resumedAt);
|
|
36340
36343
|
run.resumedAt = undefined;
|
|
36344
|
+
delete run.pauseActor;
|
|
36345
|
+
delete run.resumeActor;
|
|
36346
|
+
delete run.resumeSource;
|
|
36341
36347
|
}
|
|
36342
36348
|
if (metadata?.resumable !== undefined)
|
|
36343
36349
|
run.resumable = metadata.resumable;
|
|
36344
36350
|
if (metadata?.exitReason !== undefined)
|
|
36345
36351
|
run.exitReason = metadata.exitReason;
|
|
36346
|
-
if (
|
|
36347
|
-
run.quitAt =
|
|
36352
|
+
if (metadata?.exitReason === "quit" && run.quitAt === undefined)
|
|
36353
|
+
run.quitAt = nextControlTimestamp(undefined, run.pausedAt);
|
|
36354
|
+
if (metadata?.actor !== undefined)
|
|
36355
|
+
run.pauseActor = metadata.actor;
|
|
36348
36356
|
if (wasPaused && metadata === undefined)
|
|
36349
36357
|
return false;
|
|
36350
36358
|
context.bumpAndNotify();
|
|
36351
36359
|
return true;
|
|
36352
36360
|
},
|
|
36353
|
-
recordRunResumed(runId, resumedAt) {
|
|
36361
|
+
recordRunResumed(runId, resumedAt, metadata) {
|
|
36354
36362
|
const run = context.findRun(runId);
|
|
36355
36363
|
if (!run)
|
|
36356
36364
|
return false;
|
|
36357
36365
|
if (TERMINAL_STATUSES.has(run.status))
|
|
36358
36366
|
return false;
|
|
36359
|
-
|
|
36367
|
+
const claimsRunControl = metadata?.source === "run_control";
|
|
36368
|
+
if (run.status !== "paused") {
|
|
36369
|
+
if (!claimsRunControl || run.status !== "running" || run.resumedAt === undefined)
|
|
36370
|
+
return false;
|
|
36371
|
+
if (run.resumeSource === "run_control" && run.resumeActor === metadata?.actor)
|
|
36372
|
+
return false;
|
|
36373
|
+
run.resumeSource = "run_control";
|
|
36374
|
+
if (metadata?.actor === undefined)
|
|
36375
|
+
delete run.resumeActor;
|
|
36376
|
+
else
|
|
36377
|
+
run.resumeActor = metadata.actor;
|
|
36378
|
+
context.bumpAndNotify();
|
|
36360
36379
|
return false;
|
|
36361
|
-
|
|
36380
|
+
}
|
|
36381
|
+
const resumedTs = nextControlTimestamp(resumedAt, run.pausedAt);
|
|
36362
36382
|
run.status = "running";
|
|
36363
36383
|
run.pausedDurationMs = accumulatePausedDurationMs(run.pausedDurationMs, run.pausedAt, resumedTs);
|
|
36364
36384
|
run.resumedAt = resumedTs;
|
|
36365
36385
|
run.pausedAt = undefined;
|
|
36366
36386
|
delete run.quitAt;
|
|
36367
36387
|
delete run.exitReason;
|
|
36388
|
+
delete run.pauseActor;
|
|
36389
|
+
if (metadata === undefined) {
|
|
36390
|
+
delete run.resumeActor;
|
|
36391
|
+
delete run.resumeSource;
|
|
36392
|
+
} else {
|
|
36393
|
+
run.resumeSource = metadata.source;
|
|
36394
|
+
if (metadata.actor === undefined)
|
|
36395
|
+
delete run.resumeActor;
|
|
36396
|
+
else
|
|
36397
|
+
run.resumeActor = metadata.actor;
|
|
36398
|
+
}
|
|
36368
36399
|
context.bumpAndNotify();
|
|
36369
36400
|
return true;
|
|
36370
36401
|
},
|
|
@@ -36717,7 +36748,7 @@ function createStageStoreMethods(context) {
|
|
|
36717
36748
|
context.bumpAndNotify();
|
|
36718
36749
|
return true;
|
|
36719
36750
|
},
|
|
36720
|
-
recordStagePaused(runId, stageId, pausedAt) {
|
|
36751
|
+
recordStagePaused(runId, stageId, pausedAt, metadata) {
|
|
36721
36752
|
const run = context.findRun(runId);
|
|
36722
36753
|
if (!run)
|
|
36723
36754
|
return false;
|
|
@@ -36726,16 +36757,28 @@ function createStageStoreMethods(context) {
|
|
|
36726
36757
|
const stage = context.findStage(run, stageId);
|
|
36727
36758
|
if (!stage)
|
|
36728
36759
|
return false;
|
|
36729
|
-
if (cannotPause(stage.status))
|
|
36760
|
+
if (cannotPause(stage.status)) {
|
|
36761
|
+
if (stage.status !== "paused" || metadata?.actor === undefined)
|
|
36762
|
+
return false;
|
|
36763
|
+
if (stage.pauseActor === metadata.actor)
|
|
36764
|
+
return false;
|
|
36765
|
+
stage.pauseActor = metadata.actor;
|
|
36766
|
+
context.bumpAndNotify();
|
|
36730
36767
|
return false;
|
|
36768
|
+
}
|
|
36731
36769
|
stage.status = "paused";
|
|
36732
|
-
stage.pausedAt = pausedAt
|
|
36770
|
+
stage.pausedAt = nextControlTimestamp(pausedAt, stage.resumedAt);
|
|
36733
36771
|
stage.resumedAt = undefined;
|
|
36734
36772
|
delete stage.awaitingInputSince;
|
|
36773
|
+
delete stage.resumeActor;
|
|
36774
|
+
if (metadata?.actor === undefined)
|
|
36775
|
+
delete stage.pauseActor;
|
|
36776
|
+
else
|
|
36777
|
+
stage.pauseActor = metadata.actor;
|
|
36735
36778
|
context.bumpAndNotify();
|
|
36736
36779
|
return true;
|
|
36737
36780
|
},
|
|
36738
|
-
recordStageResumed(runId, stageId, resumedAt) {
|
|
36781
|
+
recordStageResumed(runId, stageId, resumedAt, metadata) {
|
|
36739
36782
|
const run = context.findRun(runId);
|
|
36740
36783
|
if (!run)
|
|
36741
36784
|
return false;
|
|
@@ -36744,9 +36787,17 @@ function createStageStoreMethods(context) {
|
|
|
36744
36787
|
const stage = context.findStage(run, stageId);
|
|
36745
36788
|
if (!stage)
|
|
36746
36789
|
return false;
|
|
36747
|
-
if (stage.status !== "paused" && stage.status !== "blocked")
|
|
36790
|
+
if (stage.status !== "paused" && stage.status !== "blocked") {
|
|
36791
|
+
if (stage.status !== "running" || stage.resumedAt === undefined || metadata?.actor === undefined) {
|
|
36792
|
+
return false;
|
|
36793
|
+
}
|
|
36794
|
+
if (stage.resumeActor === metadata.actor)
|
|
36795
|
+
return false;
|
|
36796
|
+
stage.resumeActor = metadata.actor;
|
|
36797
|
+
context.bumpAndNotify();
|
|
36748
36798
|
return false;
|
|
36749
|
-
|
|
36799
|
+
}
|
|
36800
|
+
const resumedTs = nextControlTimestamp(resumedAt, stage.pausedAt);
|
|
36750
36801
|
stage.status = "running";
|
|
36751
36802
|
if (stage.startedAt !== undefined) {
|
|
36752
36803
|
stage.pausedDurationMs = accumulatePausedDurationMs(stage.pausedDurationMs, stage.pausedAt, resumedTs);
|
|
@@ -36755,6 +36806,11 @@ function createStageStoreMethods(context) {
|
|
|
36755
36806
|
stage.pausedAt = undefined;
|
|
36756
36807
|
delete stage.blockedByStageId;
|
|
36757
36808
|
delete stage.awaitingInputSince;
|
|
36809
|
+
delete stage.pauseActor;
|
|
36810
|
+
if (metadata?.actor === undefined)
|
|
36811
|
+
delete stage.resumeActor;
|
|
36812
|
+
else
|
|
36813
|
+
stage.resumeActor = metadata.actor;
|
|
36758
36814
|
context.bumpAndNotify();
|
|
36759
36815
|
return true;
|
|
36760
36816
|
}
|
|
@@ -37724,6 +37780,51 @@ function stringResultField(result, key) {
|
|
|
37724
37780
|
return typeof value2 === "string" && value2.trim().length > 0 ? value2.trim() : undefined;
|
|
37725
37781
|
}
|
|
37726
37782
|
|
|
37783
|
+
// dist/builtin/workflows/src/shared/run-indicator-status.ts
|
|
37784
|
+
var TERMINAL_OR_BLOCKED = new Set(["completed", "failed", "killed", "cancelled", "skipped", "blocked"]);
|
|
37785
|
+
function runIndicatorStatus(run, allRuns = [run]) {
|
|
37786
|
+
const status = effectiveRunStatus(run);
|
|
37787
|
+
if (TERMINAL_OR_BLOCKED.has(status))
|
|
37788
|
+
return status;
|
|
37789
|
+
if (runHasPendingInput(run))
|
|
37790
|
+
return "awaiting_input";
|
|
37791
|
+
const runsById = new Map(allRuns.map((candidate) => [candidate.id, candidate]));
|
|
37792
|
+
for (const candidate of allRuns) {
|
|
37793
|
+
if (candidate.id === run.id || !runBelongsTo(candidate, run, runsById))
|
|
37794
|
+
continue;
|
|
37795
|
+
const candidateStatus = effectiveRunStatus(candidate);
|
|
37796
|
+
if (!TERMINAL_OR_BLOCKED.has(candidateStatus) && runHasPendingInput(candidate))
|
|
37797
|
+
return "awaiting_input";
|
|
37798
|
+
}
|
|
37799
|
+
return status;
|
|
37800
|
+
}
|
|
37801
|
+
function resolveRunIndicatorStatuses(runs, allRuns) {
|
|
37802
|
+
const statuses = {};
|
|
37803
|
+
for (const run of runs)
|
|
37804
|
+
statuses[run.id] = runIndicatorStatus(run, allRuns);
|
|
37805
|
+
return statuses;
|
|
37806
|
+
}
|
|
37807
|
+
function runHasPendingInput(run) {
|
|
37808
|
+
if (run.pendingPrompt !== undefined)
|
|
37809
|
+
return true;
|
|
37810
|
+
return run.stages.some((stage) => stage.status === "awaiting_input" || stage.awaitingInputSince !== undefined || stage.pendingPrompt !== undefined || stage.inputRequest !== undefined);
|
|
37811
|
+
}
|
|
37812
|
+
function runBelongsTo(candidate, ancestor, runsById) {
|
|
37813
|
+
if (candidate.rootRunId === ancestor.id)
|
|
37814
|
+
return true;
|
|
37815
|
+
const visited = new Set;
|
|
37816
|
+
let current = candidate;
|
|
37817
|
+
while (current !== undefined && current.parentRunId !== undefined) {
|
|
37818
|
+
if (current.parentRunId === ancestor.id)
|
|
37819
|
+
return true;
|
|
37820
|
+
if (visited.has(current.id))
|
|
37821
|
+
return false;
|
|
37822
|
+
visited.add(current.id);
|
|
37823
|
+
current = runsById.get(current.parentRunId);
|
|
37824
|
+
}
|
|
37825
|
+
return false;
|
|
37826
|
+
}
|
|
37827
|
+
|
|
37727
37828
|
// dist/builtin/workflows/src/tui/status-list.ts
|
|
37728
37829
|
var STAGE_LABEL_BUDGET = 24;
|
|
37729
37830
|
function isQuitRun(run) {
|
|
@@ -37744,7 +37845,7 @@ function renderStatusList(runs, opts = {}) {
|
|
|
37744
37845
|
for (let i = 0;i < sorted.length; i++) {
|
|
37745
37846
|
if (i > 0)
|
|
37746
37847
|
body.push("");
|
|
37747
|
-
body.push(...renderRunEntry(sorted[i], now, cardWidth, opts.theme));
|
|
37848
|
+
body.push(...renderRunEntry(sorted[i], now, cardWidth, opts.theme, opts.allRuns ?? runs, opts.indicatorStatuses));
|
|
37748
37849
|
}
|
|
37749
37850
|
}
|
|
37750
37851
|
if (opts.showDetailHint !== false && sorted.length > 0) {
|
|
@@ -37759,11 +37860,12 @@ function renderStatusList(runs, opts = {}) {
|
|
|
37759
37860
|
width
|
|
37760
37861
|
});
|
|
37761
37862
|
}
|
|
37762
|
-
function renderRunEntry(run, now, width, theme) {
|
|
37863
|
+
function renderRunEntry(run, now, width, theme, allRuns, indicatorStatuses) {
|
|
37763
37864
|
const bodyWidth = effectiveWidth2(width);
|
|
37764
37865
|
const interior = Math.max(8, bodyWidth - 4);
|
|
37765
|
-
const
|
|
37766
|
-
const
|
|
37866
|
+
const indicatorStatus = indicatorStatuses?.[run.id] ?? runIndicatorStatus(run, allRuns);
|
|
37867
|
+
const glyph = statusIconForRun(run, indicatorStatus);
|
|
37868
|
+
const glyphFg = theme ? hexToAnsi(runAccent(run, theme, indicatorStatus)) : "";
|
|
37767
37869
|
const accent = theme ? hexToAnsi(theme.accent) : "";
|
|
37768
37870
|
const text = theme ? hexToAnsi(theme.text) : "";
|
|
37769
37871
|
const muted = theme ? hexToAnsi(theme.textMuted) : "";
|
|
@@ -37799,31 +37901,12 @@ function renderRunEntry(run, now, width, theme) {
|
|
|
37799
37901
|
const metaLine = ` ${modeSeg} ${strip}${" ".repeat(gap)}${metaSeg} `;
|
|
37800
37902
|
return [...identityRows, identity, metaLine];
|
|
37801
37903
|
}
|
|
37802
|
-
function runAccent(run, theme) {
|
|
37904
|
+
function runAccent(run, theme, indicatorStatus) {
|
|
37803
37905
|
if (!theme)
|
|
37804
37906
|
return "#000000";
|
|
37805
37907
|
if (isQuitRun(run))
|
|
37806
37908
|
return theme.warning;
|
|
37807
|
-
|
|
37808
|
-
case "completed":
|
|
37809
|
-
return theme.success;
|
|
37810
|
-
case "running":
|
|
37811
|
-
return theme.warning;
|
|
37812
|
-
case "paused":
|
|
37813
|
-
return theme.warning;
|
|
37814
|
-
case "skipped":
|
|
37815
|
-
return theme.dim;
|
|
37816
|
-
case "cancelled":
|
|
37817
|
-
return theme.dim;
|
|
37818
|
-
case "blocked":
|
|
37819
|
-
return theme.dim;
|
|
37820
|
-
case "failed":
|
|
37821
|
-
return theme.error;
|
|
37822
|
-
case "killed":
|
|
37823
|
-
return theme.error;
|
|
37824
|
-
default:
|
|
37825
|
-
return theme.dim;
|
|
37826
|
-
}
|
|
37909
|
+
return statusColor(indicatorStatus, theme);
|
|
37827
37910
|
}
|
|
37828
37911
|
function runTrailing(run, theme) {
|
|
37829
37912
|
if (isQuitRun(run))
|
|
@@ -38074,28 +38157,10 @@ function emptyStateLine(theme) {
|
|
|
38074
38157
|
return " no workflow runs in current session";
|
|
38075
38158
|
return ` ${hexToAnsi(theme.dim)}no workflow runs in current session${RESET}`;
|
|
38076
38159
|
}
|
|
38077
|
-
function statusIconForRun(run) {
|
|
38160
|
+
function statusIconForRun(run, indicatorStatus) {
|
|
38078
38161
|
if (isQuitRun(run))
|
|
38079
|
-
return "
|
|
38080
|
-
|
|
38081
|
-
case "completed":
|
|
38082
|
-
return "✓";
|
|
38083
|
-
case "skipped":
|
|
38084
|
-
case "cancelled":
|
|
38085
|
-
return "⊘";
|
|
38086
|
-
case "blocked":
|
|
38087
|
-
return "↑";
|
|
38088
|
-
case "running":
|
|
38089
|
-
return "●";
|
|
38090
|
-
case "paused":
|
|
38091
|
-
return "❚❚";
|
|
38092
|
-
case "failed":
|
|
38093
|
-
return "✗";
|
|
38094
|
-
case "killed":
|
|
38095
|
-
return "⊘";
|
|
38096
|
-
default:
|
|
38097
|
-
return "○";
|
|
38098
|
-
}
|
|
38162
|
+
return statusIcon("pending");
|
|
38163
|
+
return statusIcon(indicatorStatus);
|
|
38099
38164
|
}
|
|
38100
38165
|
|
|
38101
38166
|
// dist/builtin/workflows/src/tui/workflow-list.ts
|
|
@@ -38235,7 +38300,12 @@ function renderChatSurfacePlainText(payload, options = {}) {
|
|
|
38235
38300
|
`);
|
|
38236
38301
|
}
|
|
38237
38302
|
case "status": {
|
|
38238
|
-
const rendered = renderStatusList(payload.runs, {
|
|
38303
|
+
const rendered = renderStatusList(payload.runs, {
|
|
38304
|
+
width,
|
|
38305
|
+
now,
|
|
38306
|
+
...themed,
|
|
38307
|
+
indicatorStatuses: payload.indicatorStatuses
|
|
38308
|
+
});
|
|
38239
38309
|
if (payload.runs.length === 0)
|
|
38240
38310
|
return rendered;
|
|
38241
38311
|
return [
|
|
@@ -38325,7 +38395,12 @@ function renderPayload(payload, theme, width, now) {
|
|
|
38325
38395
|
width
|
|
38326
38396
|
});
|
|
38327
38397
|
case "status":
|
|
38328
|
-
return renderStatusList(payload.runs, {
|
|
38398
|
+
return renderStatusList(payload.runs, {
|
|
38399
|
+
theme,
|
|
38400
|
+
width,
|
|
38401
|
+
now,
|
|
38402
|
+
indicatorStatuses: payload.indicatorStatuses
|
|
38403
|
+
});
|
|
38329
38404
|
case "list":
|
|
38330
38405
|
return renderWorkflowList(payload.entries, { theme, width });
|
|
38331
38406
|
case "detail":
|
|
@@ -46389,13 +46464,8 @@ function quitExpiryTimestamp(run) {
|
|
|
46389
46464
|
function recentlyQuit(run, now) {
|
|
46390
46465
|
return isQuitRun2(run) && now - quitExpiryTimestamp(run) <= RECENT_ENDED_WINDOW_MS;
|
|
46391
46466
|
}
|
|
46392
|
-
function runAwaitsInput(run) {
|
|
46393
|
-
return run.endedAt === undefined && (run.pendingPrompt !== undefined || run.stages.some((s) => s.status === "awaiting_input"));
|
|
46394
|
-
}
|
|
46395
46467
|
function subtreeAwaitsInput(root, allRuns) {
|
|
46396
|
-
|
|
46397
|
-
return true;
|
|
46398
|
-
return allRuns.some((run) => run.rootRunId === root.id && runAwaitsInput(run));
|
|
46468
|
+
return runIndicatorStatus(root, allRuns) === "awaiting_input";
|
|
46399
46469
|
}
|
|
46400
46470
|
function countRuns(runs, allRuns = runs) {
|
|
46401
46471
|
const counts = { active: 0, paused: 0, quit: 0, done: 0, blocked: 0, failed: 0, awaiting: 0 };
|
|
@@ -46413,7 +46483,7 @@ function countRuns(runs, allRuns = runs) {
|
|
|
46413
46483
|
counts.done++;
|
|
46414
46484
|
else if (status === "failed" || status === "killed")
|
|
46415
46485
|
counts.failed++;
|
|
46416
|
-
if (r.endedAt === undefined && subtreeAwaitsInput(r, allRuns))
|
|
46486
|
+
if (r.endedAt === undefined && !isQuitRun2(r) && subtreeAwaitsInput(r, allRuns))
|
|
46417
46487
|
counts.awaiting++;
|
|
46418
46488
|
}
|
|
46419
46489
|
return counts;
|
|
@@ -46445,32 +46515,17 @@ function selectDisplayRuns(snap, now) {
|
|
|
46445
46515
|
const sort = (xs) => [...xs].sort((a, b) => (b.startedAt ?? 0) - (a.startedAt ?? 0));
|
|
46446
46516
|
return [...sort(active), ...sort(recent)];
|
|
46447
46517
|
}
|
|
46448
|
-
function statusGlyph(run) {
|
|
46518
|
+
function statusGlyph(run, allRuns) {
|
|
46449
46519
|
if (isQuitRun2(run))
|
|
46450
|
-
return "
|
|
46451
|
-
|
|
46452
|
-
case "running":
|
|
46453
|
-
return "●";
|
|
46454
|
-
case "paused":
|
|
46455
|
-
return "❚❚";
|
|
46456
|
-
case "completed":
|
|
46457
|
-
return "✓";
|
|
46458
|
-
case "skipped":
|
|
46459
|
-
case "cancelled":
|
|
46460
|
-
return "⊘";
|
|
46461
|
-
case "blocked":
|
|
46462
|
-
return "↑";
|
|
46463
|
-
case "failed":
|
|
46464
|
-
return "✗";
|
|
46465
|
-
case "killed":
|
|
46466
|
-
return "⊘";
|
|
46467
|
-
default:
|
|
46468
|
-
return "○";
|
|
46469
|
-
}
|
|
46520
|
+
return statusIcon("pending");
|
|
46521
|
+
return statusIcon(runIndicatorStatus(run, allRuns));
|
|
46470
46522
|
}
|
|
46471
|
-
function statusFg(run, theme) {
|
|
46523
|
+
function statusFg(run, theme, allRuns) {
|
|
46472
46524
|
if (isQuitRun2(run))
|
|
46473
46525
|
return theme.warning;
|
|
46526
|
+
const indicatorStatus = runIndicatorStatus(run, allRuns);
|
|
46527
|
+
if (indicatorStatus === "awaiting_input")
|
|
46528
|
+
return statusColor(indicatorStatus, theme);
|
|
46474
46529
|
switch (effectiveRunStatus(run)) {
|
|
46475
46530
|
case "running":
|
|
46476
46531
|
case "paused":
|
|
@@ -46568,25 +46623,25 @@ function formatTitleBadges(badges, theme, themed) {
|
|
|
46568
46623
|
const fallbackFg = hexToAnsi(theme.border);
|
|
46569
46624
|
return badges.map((b) => `${b.fg ? hexToAnsi(b.fg) : fallbackFg}${b.text}${RESET}${fallbackFg}`).join(" ");
|
|
46570
46625
|
}
|
|
46571
|
-
function themedRunLines(run, now, theme) {
|
|
46626
|
+
function themedRunLines(run, now, theme, allRuns) {
|
|
46572
46627
|
const meta = metaLine(run, now);
|
|
46573
46628
|
const metaColor = effectiveRunStatus(run) === "running" ? theme.textMuted : theme.dim;
|
|
46574
46629
|
return renderRunIdentityRows({
|
|
46575
46630
|
runId: run.id,
|
|
46576
46631
|
name: run.name,
|
|
46577
46632
|
meta,
|
|
46578
|
-
glyph: statusGlyph(run),
|
|
46579
|
-
glyphColor: statusFg(run, theme),
|
|
46633
|
+
glyph: statusGlyph(run, allRuns),
|
|
46634
|
+
glyphColor: statusFg(run, theme, allRuns),
|
|
46580
46635
|
metaColor,
|
|
46581
46636
|
theme
|
|
46582
46637
|
});
|
|
46583
46638
|
}
|
|
46584
|
-
function plainRunLines(run, now) {
|
|
46639
|
+
function plainRunLines(run, now, allRuns) {
|
|
46585
46640
|
return renderRunIdentityRows({
|
|
46586
46641
|
runId: run.id,
|
|
46587
46642
|
name: run.name,
|
|
46588
46643
|
meta: metaLine(run, now),
|
|
46589
|
-
glyph: statusGlyph(run)
|
|
46644
|
+
glyph: statusGlyph(run, allRuns)
|
|
46590
46645
|
});
|
|
46591
46646
|
}
|
|
46592
46647
|
function themedCollapsed(counts, theme) {
|
|
@@ -46635,7 +46690,7 @@ function buildThemedWidgetLines(snap, piTheme, width = 120, now = Date.now()) {
|
|
|
46635
46690
|
const body = [];
|
|
46636
46691
|
for (let i = 0;i < display.length; i++) {
|
|
46637
46692
|
const run = display[i];
|
|
46638
|
-
const runLines = themed ? themedRunLines(run, now, graphTheme) : plainRunLines(run, now);
|
|
46693
|
+
const runLines = themed ? themedRunLines(run, now, graphTheme, snap.runs) : plainRunLines(run, now, snap.runs);
|
|
46639
46694
|
body.push(...runLines);
|
|
46640
46695
|
if (i < display.length - 1)
|
|
46641
46696
|
body.push("");
|
|
@@ -46659,6 +46714,13 @@ var STALE_CONTEXT = "This extension ctx is stale";
|
|
|
46659
46714
|
function isStale(err) {
|
|
46660
46715
|
return err instanceof Error && err.message.includes(STALE_CONTEXT);
|
|
46661
46716
|
}
|
|
46717
|
+
function liveWidgetSnapshot(storeInstance) {
|
|
46718
|
+
return {
|
|
46719
|
+
runs: storeInstance.runs(),
|
|
46720
|
+
notices: storeInstance.notices(),
|
|
46721
|
+
version: 0
|
|
46722
|
+
};
|
|
46723
|
+
}
|
|
46662
46724
|
function installStoreWidget(pi, storeInstance, timers = defaultTimerApi) {
|
|
46663
46725
|
const ui = pi.ui;
|
|
46664
46726
|
if (!ui?.setWidget)
|
|
@@ -46672,7 +46734,7 @@ function installStoreWidget(pi, storeInstance, timers = defaultTimerApi) {
|
|
|
46672
46734
|
key: WIDGET_KEY,
|
|
46673
46735
|
placement: "belowEditor",
|
|
46674
46736
|
timers,
|
|
46675
|
-
getSnapshot: () =>
|
|
46737
|
+
getSnapshot: () => liveWidgetSnapshot(storeInstance),
|
|
46676
46738
|
subscribe: (listener) => subscribeStoreInvalidation(storeInstance, listener),
|
|
46677
46739
|
getPreviewLines: (snap, now) => buildThemedWidgetLines(snap, undefined, 120, now),
|
|
46678
46740
|
render: (snap, { theme, width, now }) => buildThemedWidgetLines(snap, theme, width, now),
|
|
@@ -47745,6 +47807,7 @@ class InMemoryDurableBackend {
|
|
|
47745
47807
|
createdAt: handle.createdAt,
|
|
47746
47808
|
status: handle.status,
|
|
47747
47809
|
...handle.invocationCwd !== undefined ? { invocationCwd: handle.invocationCwd } : existing?.handle.invocationCwd !== undefined ? { invocationCwd: existing.handle.invocationCwd } : {},
|
|
47810
|
+
...handle.origin !== undefined ? { origin: handle.origin } : existing?.handle.origin !== undefined ? { origin: existing.handle.origin } : {},
|
|
47748
47811
|
...handle.workflowCwd !== undefined ? { workflowCwd: handle.workflowCwd } : existing?.handle.workflowCwd !== undefined ? { workflowCwd: existing.handle.workflowCwd } : {},
|
|
47749
47812
|
...handle.repositoryRoot !== undefined ? { repositoryRoot: handle.repositoryRoot } : existing?.handle.repositoryRoot !== undefined ? { repositoryRoot: existing.handle.repositoryRoot } : {},
|
|
47750
47813
|
...handle.gitWorktreeRoot !== undefined ? { gitWorktreeRoot: handle.gitWorktreeRoot } : existing?.handle.gitWorktreeRoot !== undefined ? { gitWorktreeRoot: existing.handle.gitWorktreeRoot } : {},
|
|
@@ -47959,6 +48022,7 @@ class InMemoryDurableBackend {
|
|
|
47959
48022
|
...h.resumable !== undefined ? { resumable: h.resumable } : {},
|
|
47960
48023
|
...workflowFailureFields(h),
|
|
47961
48024
|
...h.invocationCwd !== undefined ? { invocationCwd: h.invocationCwd } : {},
|
|
48025
|
+
...h.origin !== undefined ? { origin: h.origin } : {},
|
|
47962
48026
|
...h.workflowCwd !== undefined ? { workflowCwd: h.workflowCwd } : {},
|
|
47963
48027
|
...h.repositoryRoot !== undefined ? { repositoryRoot: h.repositoryRoot } : {},
|
|
47964
48028
|
...h.gitWorktreeRoot !== undefined ? { gitWorktreeRoot: h.gitWorktreeRoot } : {},
|
|
@@ -48026,6 +48090,7 @@ function toResumableEntry(handle) {
|
|
|
48026
48090
|
...handle.resumable !== undefined ? { resumable: handle.resumable } : {},
|
|
48027
48091
|
...workflowFailureFields(handle),
|
|
48028
48092
|
...handle.invocationCwd !== undefined ? { invocationCwd: handle.invocationCwd } : {},
|
|
48093
|
+
...handle.origin !== undefined ? { origin: handle.origin } : {},
|
|
48029
48094
|
...handle.workflowCwd !== undefined ? { workflowCwd: handle.workflowCwd } : {},
|
|
48030
48095
|
...handle.repositoryRoot !== undefined ? { repositoryRoot: handle.repositoryRoot } : {},
|
|
48031
48096
|
...handle.gitWorktreeRoot !== undefined ? { gitWorktreeRoot: handle.gitWorktreeRoot } : {},
|
|
@@ -49235,6 +49300,7 @@ function encodeMetadata(metadata) {
|
|
|
49235
49300
|
...metadata.failureRecoverability !== undefined ? { failureRecoverability: metadata.failureRecoverability } : {},
|
|
49236
49301
|
...metadata.failureDisposition !== undefined ? { failureDisposition: metadata.failureDisposition } : {},
|
|
49237
49302
|
...metadata.failedToolNodeId !== undefined ? { failedToolNodeId: metadata.failedToolNodeId } : {},
|
|
49303
|
+
...metadata.origin !== undefined ? { origin: metadata.origin } : {},
|
|
49238
49304
|
...metadata.invocationCwd !== undefined ? { invocationCwd: metadata.invocationCwd } : {},
|
|
49239
49305
|
...metadata.workflowCwd !== undefined ? { workflowCwd: metadata.workflowCwd } : {},
|
|
49240
49306
|
...metadata.repositoryRoot !== undefined ? { repositoryRoot: metadata.repositoryRoot } : {},
|
|
@@ -49280,7 +49346,14 @@ function parseDurableWorkflowMetadata(value2, workflowId) {
|
|
|
49280
49346
|
const metadata = value2;
|
|
49281
49347
|
if (metadata.workflowId !== workflowId || typeof metadata.workflowId !== "string" || typeof metadata.name !== "string" || typeof metadata.inputs !== "object" || metadata.inputs === null || Array.isArray(metadata.inputs) || typeof metadata.status !== "string" || !isDurableWorkflowStatus(metadata.status) || typeof metadata.completedCheckpoints !== "number" || typeof metadata.createdAt !== "number" || typeof metadata.pendingPrompts !== "number" || typeof metadata.promptReservationEpoch !== "string" || typeof metadata.updatedAt !== "number" || metadata.ownerExecutorId !== undefined && typeof metadata.ownerExecutorId !== "string" || metadata.transitionClaimId !== undefined && typeof metadata.transitionClaimId !== "string" || metadata.sessionFile !== undefined && typeof metadata.sessionFile !== "string" || metadata.label !== undefined && typeof metadata.label !== "string" || metadata.rootWorkflowId !== undefined && typeof metadata.rootWorkflowId !== "string" || metadata.resumable !== undefined && typeof metadata.resumable !== "boolean" || metadata.error !== undefined && typeof metadata.error !== "string" || metadata.failureKind !== undefined && !isWorkflowFailureKind(metadata.failureKind) || metadata.failureCode !== undefined && !isWorkflowFailureCode(metadata.failureCode) || metadata.failureRecoverability !== undefined && !isWorkflowFailureRecoverability(metadata.failureRecoverability) || metadata.failureDisposition !== undefined && !isWorkflowFailureDisposition(metadata.failureDisposition) || metadata.failedToolNodeId !== undefined && typeof metadata.failedToolNodeId !== "string" || metadata.invocationCwd !== undefined && typeof metadata.invocationCwd !== "string" || metadata.workflowCwd !== undefined && typeof metadata.workflowCwd !== "string" || metadata.repositoryRoot !== undefined && typeof metadata.repositoryRoot !== "string" || metadata.gitWorktreeRoot !== undefined && typeof metadata.gitWorktreeRoot !== "string")
|
|
49282
49348
|
return;
|
|
49283
|
-
|
|
49349
|
+
const { origin, ...metadataWithoutOrigin } = metadata;
|
|
49350
|
+
return {
|
|
49351
|
+
...metadataWithoutOrigin,
|
|
49352
|
+
...isWorkflowActor(origin) ? { origin } : {}
|
|
49353
|
+
};
|
|
49354
|
+
}
|
|
49355
|
+
function isWorkflowActor(value2) {
|
|
49356
|
+
return value2 === "user" || value2 === "agent";
|
|
49284
49357
|
}
|
|
49285
49358
|
function isDurableWorkflowStatus(value2) {
|
|
49286
49359
|
return value2 === "running" || value2 === "paused" || value2 === "completed" || value2 === "failed" || value2 === "cancelled" || value2 === "blocked";
|
|
@@ -51041,7 +51114,7 @@ async function quitRun(runId, opts) {
|
|
|
51041
51114
|
return { ok: false, runId, reason: "already_ended" };
|
|
51042
51115
|
const suspendedByAbort = toolHandles.length > 0;
|
|
51043
51116
|
const publish = (resumable) => {
|
|
51044
|
-
publishLocalQuit(activeStore, runId, pausedRunIds, resumable);
|
|
51117
|
+
publishLocalQuit(activeStore, runId, pausedRunIds, resumable, opts?.actor);
|
|
51045
51118
|
if (abandonedTools.length > 0)
|
|
51046
51119
|
jobs.detach(runId, jobs.get(runId));
|
|
51047
51120
|
};
|
|
@@ -51062,10 +51135,17 @@ async function quitRun(runId, opts) {
|
|
|
51062
51135
|
publish(true);
|
|
51063
51136
|
return { ok: true, runId, paused, cancelledTools, abandonedTools };
|
|
51064
51137
|
}
|
|
51065
|
-
function publishLocalQuit(activeStore, runId, pausedRunIds, resumable) {
|
|
51066
|
-
for (const pausedRunId of pausedRunIds)
|
|
51138
|
+
function publishLocalQuit(activeStore, runId, pausedRunIds, resumable, actor) {
|
|
51139
|
+
for (const pausedRunId of pausedRunIds) {
|
|
51140
|
+
if (pausedRunId === runId)
|
|
51141
|
+
continue;
|
|
51067
51142
|
activeStore.recordRunPaused(pausedRunId);
|
|
51068
|
-
|
|
51143
|
+
}
|
|
51144
|
+
activeStore.recordRunPaused(runId, undefined, {
|
|
51145
|
+
exitReason: "quit",
|
|
51146
|
+
resumable,
|
|
51147
|
+
...actor === undefined ? {} : { actor }
|
|
51148
|
+
});
|
|
51069
51149
|
}
|
|
51070
51150
|
function unrecordedDurableQuitMessage(error) {
|
|
51071
51151
|
const detail = error instanceof Error ? error.message : String(error);
|
|
@@ -51148,7 +51228,8 @@ async function quitAllRuns(opts) {
|
|
|
51148
51228
|
store: activeStore,
|
|
51149
51229
|
stageControlRegistry: opts?.stageControlRegistry,
|
|
51150
51230
|
toolControlRegistry: opts?.toolControlRegistry,
|
|
51151
|
-
jobs: opts?.jobs
|
|
51231
|
+
jobs: opts?.jobs,
|
|
51232
|
+
...opts?.actor === undefined ? {} : { actor: opts.actor }
|
|
51152
51233
|
}));
|
|
51153
51234
|
const settled = await Promise.allSettled(attempts);
|
|
51154
51235
|
return settled.map((result, index) => {
|
|
@@ -51202,6 +51283,7 @@ function appendRunStart(api, payload) {
|
|
|
51202
51283
|
...payload.parentStageId !== undefined ? { parentStageId: payload.parentStageId } : {},
|
|
51203
51284
|
...payload.rootRunId !== undefined ? { rootRunId: payload.rootRunId } : {},
|
|
51204
51285
|
...payload.resumedFromRunId !== undefined ? { resumedFromRunId: payload.resumedFromRunId } : {},
|
|
51286
|
+
...payload.origin !== undefined ? { origin: payload.origin } : {},
|
|
51205
51287
|
...payload.resumeFromStageId !== undefined ? { resumeFromStageId: payload.resumeFromStageId } : {},
|
|
51206
51288
|
...payload.accumulatedDurationMs !== undefined ? { accumulatedDurationMs: payload.accumulatedDurationMs } : {},
|
|
51207
51289
|
ts: payload.ts
|
|
@@ -51405,7 +51487,7 @@ async function settleResumeAcknowledgements(store2, targets, message) {
|
|
|
51405
51487
|
failures.push(qualified);
|
|
51406
51488
|
});
|
|
51407
51489
|
for (const controlRunId of resumedRunIds)
|
|
51408
|
-
store2.recordRunResumed(controlRunId);
|
|
51490
|
+
store2.recordRunResumed(controlRunId, undefined, { source: "acknowledgement" });
|
|
51409
51491
|
return { resumed, acknowledged, failures, lateFailures };
|
|
51410
51492
|
}
|
|
51411
51493
|
async function waitForResumeReconciliation(acknowledged) {
|
|
@@ -51526,9 +51608,17 @@ async function resumeRun(runId, opts) {
|
|
|
51526
51608
|
const currentRun2 = activeStore.runs().find((candidate) => candidate.id === runId);
|
|
51527
51609
|
const hasPausedDescendant = workflowHasPausedStages(activeStore, runId);
|
|
51528
51610
|
if (acknowledgements.acknowledged > 0 || handles.length === 0 && acknowledgements.failures.length === 0 && !hasPausedDescendant && currentRun2?.status === "paused") {
|
|
51529
|
-
|
|
51530
|
-
|
|
51531
|
-
|
|
51611
|
+
const attributeStage = opts?.stageId !== undefined && (hasPausedDescendant || currentRun2?.resumedAt === undefined);
|
|
51612
|
+
activeStore.recordRunResumed(runId, undefined, {
|
|
51613
|
+
source: "run_control",
|
|
51614
|
+
...opts?.actor === undefined || attributeStage ? {} : { actor: opts.actor }
|
|
51615
|
+
});
|
|
51616
|
+
if (aggregateRootRunId !== runId) {
|
|
51617
|
+
activeStore.recordRunResumed(aggregateRootRunId, undefined, { source: "run_control" });
|
|
51618
|
+
}
|
|
51619
|
+
if (attributeStage && opts?.actor !== undefined && opts.stageId !== undefined) {
|
|
51620
|
+
activeStore.recordStageResumed(runId, opts.stageId, undefined, { actor: opts.actor });
|
|
51621
|
+
}
|
|
51532
51622
|
}
|
|
51533
51623
|
const reconciledRoot = activeStore.runs().find((candidate) => candidate.id === runId);
|
|
51534
51624
|
if (acknowledgements.failures.length > 0) {
|
|
@@ -51603,6 +51693,7 @@ async function pauseRun(runId, opts) {
|
|
|
51603
51693
|
const activeStore = opts?.store ?? store;
|
|
51604
51694
|
const registry = opts?.stageControlRegistry ?? stageControlRegistry;
|
|
51605
51695
|
const run = activeStore.runs().find((candidate) => candidate.id === runId);
|
|
51696
|
+
const actorMetadata = opts?.actor === undefined ? undefined : { actor: opts.actor };
|
|
51606
51697
|
if (!run)
|
|
51607
51698
|
return { ok: false, runId, reason: "not_found" };
|
|
51608
51699
|
if (run.endedAt !== undefined)
|
|
@@ -51621,7 +51712,9 @@ async function pauseRun(runId, opts) {
|
|
|
51621
51712
|
const paused2 = stage === undefined ? [] : [structuredClone(stage)];
|
|
51622
51713
|
const stillActive = currentRun2?.stages.some((candidate) => candidate.id !== opts.stageId && (candidate.status === "running" || candidate.status === "pending")) ?? false;
|
|
51623
51714
|
if (!stillActive)
|
|
51624
|
-
activeStore.recordRunPaused(runId);
|
|
51715
|
+
activeStore.recordRunPaused(runId, undefined, actorMetadata);
|
|
51716
|
+
else if (actorMetadata !== undefined)
|
|
51717
|
+
activeStore.recordStagePaused(runId, opts.stageId, undefined, actorMetadata);
|
|
51625
51718
|
return { ok: true, runId, paused: paused2 };
|
|
51626
51719
|
}
|
|
51627
51720
|
const controlRunIds = expandedControlRunIds(activeStore, runId);
|
|
@@ -51639,15 +51732,22 @@ async function pauseRun(runId, opts) {
|
|
|
51639
51732
|
if (stage !== undefined)
|
|
51640
51733
|
paused.push(structuredClone(stage));
|
|
51641
51734
|
}
|
|
51642
|
-
for (const pausedRunId of pausedRunIds)
|
|
51735
|
+
for (const pausedRunId of pausedRunIds) {
|
|
51736
|
+
if (pausedRunId === runId)
|
|
51737
|
+
continue;
|
|
51643
51738
|
activeStore.recordRunPaused(pausedRunId);
|
|
51644
|
-
|
|
51739
|
+
}
|
|
51740
|
+
activeStore.recordRunPaused(runId, undefined, actorMetadata);
|
|
51645
51741
|
return { ok: true, runId, paused };
|
|
51646
51742
|
}
|
|
51647
51743
|
async function pauseAllRuns(opts) {
|
|
51648
51744
|
const activeStore = opts?.store ?? store;
|
|
51649
51745
|
const inFlight = topLevelWorkflowRuns(activeStore.runs()).filter((run) => run.endedAt === undefined);
|
|
51650
|
-
return Promise.all(inFlight.map((run) => pauseRun(run.id, {
|
|
51746
|
+
return Promise.all(inFlight.map((run) => pauseRun(run.id, {
|
|
51747
|
+
store: activeStore,
|
|
51748
|
+
stageControlRegistry: opts?.stageControlRegistry,
|
|
51749
|
+
...opts?.actor === undefined ? {} : { actor: opts.actor }
|
|
51750
|
+
})));
|
|
51651
51751
|
}
|
|
51652
51752
|
async function interruptRun(runId, opts) {
|
|
51653
51753
|
return pauseRun(runId, opts);
|
|
@@ -51995,10 +52095,14 @@ function createLifecycleNoticeDelivery(options) {
|
|
|
51995
52095
|
var LIFECYCLE_NOTICE_CUSTOM_TYPE = "workflows:lifecycle-notice";
|
|
51996
52096
|
var LIFECYCLE_NOTICE_SNIPPET_LIMIT = 240;
|
|
51997
52097
|
var WORKFLOW_LIFECYCLE_NOTICE_KINDS = [
|
|
52098
|
+
"started",
|
|
51998
52099
|
"completed",
|
|
51999
52100
|
"failed",
|
|
52000
52101
|
"blocked",
|
|
52001
|
-
"awaiting_input"
|
|
52102
|
+
"awaiting_input",
|
|
52103
|
+
"paused",
|
|
52104
|
+
"quit",
|
|
52105
|
+
"resumed"
|
|
52002
52106
|
];
|
|
52003
52107
|
var rendererRegisteredHosts4 = new WeakSet;
|
|
52004
52108
|
function createWorkflowLifecycleNotificationState() {
|
|
@@ -52032,6 +52136,12 @@ function seedWorkflowLifecycleNotificationState(state2, snapshot) {
|
|
|
52032
52136
|
state2.deliveredTerminalRuns.add(key2);
|
|
52033
52137
|
}
|
|
52034
52138
|
}
|
|
52139
|
+
for (const occurrence of controlOccurrences(run)) {
|
|
52140
|
+
const controlKey = controlOccurrenceKey(run, occurrence);
|
|
52141
|
+
if (!state2.pendingTerminalRuns.has(controlKey) && !state2.retryableTerminalRuns.has(controlKey)) {
|
|
52142
|
+
state2.deliveredTerminalRuns.add(controlKey);
|
|
52143
|
+
}
|
|
52144
|
+
}
|
|
52035
52145
|
if (run.pendingPrompt !== undefined) {
|
|
52036
52146
|
state2.deliveredInputPrompts.add(runAwaitingInputKey(run.id, run.pendingPrompt));
|
|
52037
52147
|
}
|
|
@@ -52102,6 +52212,22 @@ function installWorkflowLifecycleNotifications(options) {
|
|
|
52102
52212
|
}
|
|
52103
52213
|
delivery.deliver(key2, makeTerminalNotice(run, kind));
|
|
52104
52214
|
};
|
|
52215
|
+
const emitControlNoticesOnce = (run) => {
|
|
52216
|
+
for (const occurrence of controlOccurrences(run)) {
|
|
52217
|
+
if (!notifyOn.has(occurrence.kind))
|
|
52218
|
+
continue;
|
|
52219
|
+
const key2 = controlOccurrenceKey(run, occurrence);
|
|
52220
|
+
if (state2.deliveredTerminalRuns.has(key2) || state2.pendingTerminalRuns.has(key2) || state2.retryableTerminalRuns.has(key2))
|
|
52221
|
+
continue;
|
|
52222
|
+
if (state2.suppressionDepth > 0) {
|
|
52223
|
+
state2.deliveredTerminalRuns.add(key2);
|
|
52224
|
+
state2.retryableTerminalRuns.delete(key2);
|
|
52225
|
+
state2.retryableTerminalNotices.delete(key2);
|
|
52226
|
+
continue;
|
|
52227
|
+
}
|
|
52228
|
+
delivery.deliver(key2, makeControlNotice(run, occurrence));
|
|
52229
|
+
}
|
|
52230
|
+
};
|
|
52105
52231
|
const emitStageAwaitingInputNoticeOnce = (run, stage) => {
|
|
52106
52232
|
if (stage.status !== "awaiting_input")
|
|
52107
52233
|
return;
|
|
@@ -52125,6 +52251,7 @@ function installWorkflowLifecycleNotifications(options) {
|
|
|
52125
52251
|
emitTerminalNoticeOnce(run, "completed");
|
|
52126
52252
|
emitTerminalNoticeOnce(run, "failed");
|
|
52127
52253
|
emitTerminalNoticeOnce(run, "blocked");
|
|
52254
|
+
emitControlNoticesOnce(run);
|
|
52128
52255
|
if (!notifyOn.has("awaiting_input"))
|
|
52129
52256
|
continue;
|
|
52130
52257
|
emitRunAwaitingInputNoticeOnce(run);
|
|
@@ -52163,20 +52290,41 @@ function registerLifecycleNoticeRenderer(options) {
|
|
|
52163
52290
|
}
|
|
52164
52291
|
function formatWorkflowLifecycleNoticeText(details) {
|
|
52165
52292
|
const workflowName = escapeQuotedText2(details.workflowName);
|
|
52293
|
+
const origin = details.origin === undefined ? "" : details.origin === "agent" ? ", which you started" : ", which the user started";
|
|
52294
|
+
const actor = details.actor === "agent" ? "You" : "The user";
|
|
52295
|
+
if (details.kind === "started") {
|
|
52296
|
+
return `▶ ${actor} started workflow "${workflowName}" (run ${details.runId}). It is running in the background; you will be notified when it completes.`;
|
|
52297
|
+
}
|
|
52166
52298
|
if (details.kind === "completed") {
|
|
52167
|
-
return `✓ Workflow "${workflowName}" completed (run ${details.runId}). Inspect: /workflow status ${details.runId}`;
|
|
52299
|
+
return `✓ Workflow "${workflowName}" completed (run ${details.runId})${origin}. Inspect: /workflow status ${details.runId}`;
|
|
52168
52300
|
}
|
|
52169
52301
|
if (details.kind === "failed") {
|
|
52170
52302
|
const stage2 = details.stageName ?? details.failedStageId ?? details.stageId;
|
|
52171
52303
|
const tool = lifecycleToolOrigin(details);
|
|
52172
|
-
const
|
|
52304
|
+
const failureSite = stage2 ? `, stage ${stage2}` : tool !== undefined ? `, tool ${tool}` : "";
|
|
52173
52305
|
const errorText = details.error ? `: ${details.error}` : "";
|
|
52174
|
-
return `✗ Workflow "${workflowName}" failed (run ${details.runId}${
|
|
52306
|
+
return `✗ Workflow "${workflowName}" failed (run ${details.runId}${failureSite})${origin}${errorText}. Inspect: /workflow status ${details.runId}`;
|
|
52175
52307
|
}
|
|
52176
52308
|
if (details.kind === "blocked") {
|
|
52177
52309
|
const errorText = details.error ? `: ${details.error}` : "";
|
|
52178
52310
|
const stateText = details.active === true ? "is blocked" : "ended blocked";
|
|
52179
|
-
return `! Workflow "${workflowName}" ${stateText} (run ${details.runId})${errorText}. Inspect: /workflow status ${details.runId}`;
|
|
52311
|
+
return `! Workflow "${workflowName}" ${stateText} (run ${details.runId})${origin}${errorText}. Inspect: /workflow status ${details.runId}`;
|
|
52312
|
+
}
|
|
52313
|
+
if (details.kind === "paused" || details.kind === "quit") {
|
|
52314
|
+
const stopStage = details.stageName ?? details.stageId;
|
|
52315
|
+
const stageText = stopStage ? `${origin === "" ? "" : ","} at stage ${stopStage}` : "";
|
|
52316
|
+
const scopeText = details.scope === "stage" ? "stage of workflow" : "workflow";
|
|
52317
|
+
const verb = details.kind === "paused" ? "paused" : "quit";
|
|
52318
|
+
const noun = details.kind === "paused" ? "pause" : "stop";
|
|
52319
|
+
const glyph = details.kind === "paused" ? "⏸" : "⏹";
|
|
52320
|
+
return `${glyph} ${actor} ${verb} the ${scopeText} "${workflowName}" (run ${details.runId})${origin}${stageText}. This ${noun} was deliberate and user-requested; do not resume it or take over the work unless asked. Resume: /workflow resume ${details.runId}`;
|
|
52321
|
+
}
|
|
52322
|
+
if (details.kind === "resumed") {
|
|
52323
|
+
const resumedStage = details.stageName ?? details.stageId;
|
|
52324
|
+
const stageText = resumedStage ? `${origin === "" ? "" : ","} at stage ${resumedStage}` : "";
|
|
52325
|
+
const scopeText = details.scope === "stage" ? "stage of workflow" : "workflow";
|
|
52326
|
+
const continues = details.continuedFromRunId === undefined ? "" : `, continuing run ${details.continuedFromRunId}`;
|
|
52327
|
+
return `▶ ${actor} resumed the ${scopeText} "${workflowName}" (run ${details.runId}${continues})${origin}${stageText}. It is running again in the background.`;
|
|
52180
52328
|
}
|
|
52181
52329
|
const prompt = details.promptMessage ? ` Prompt: ${details.promptMessage}` : "";
|
|
52182
52330
|
if (details.scope === "run") {
|
|
@@ -52205,9 +52353,31 @@ function makeTerminalNotice(run, kind) {
|
|
|
52205
52353
|
...failedToolNodeId !== undefined ? { toolNodeId: failedToolNodeId } : {},
|
|
52206
52354
|
...failedTool !== undefined ? { toolName: failedTool.name } : {},
|
|
52207
52355
|
...run.durationMs !== undefined ? { durationMs: run.durationMs } : {},
|
|
52356
|
+
...run.origin !== undefined ? { origin: run.origin } : {},
|
|
52208
52357
|
createdAt: lifecycleOccurrenceAt(run, kind) ?? Date.now()
|
|
52209
52358
|
};
|
|
52210
52359
|
}
|
|
52360
|
+
function makeControlNotice(run, occurrence) {
|
|
52361
|
+
const stage = occurrence.stage ?? restingStage(run);
|
|
52362
|
+
const elapsedMs = run.durationMs ?? (occurrence.at >= run.startedAt ? occurrence.at - run.startedAt : undefined);
|
|
52363
|
+
return {
|
|
52364
|
+
kind: occurrence.kind,
|
|
52365
|
+
scope: occurrence.scope,
|
|
52366
|
+
runId: run.id,
|
|
52367
|
+
workflowName: run.name,
|
|
52368
|
+
status: occurrence.stage !== undefined ? occurrence.stage.status : run.status,
|
|
52369
|
+
...stage !== undefined ? { stageId: stage.id, stageName: stage.name } : {},
|
|
52370
|
+
...elapsedMs !== undefined ? { durationMs: elapsedMs } : {},
|
|
52371
|
+
...occurrence.kind === "quit" && run.resumable !== undefined ? { resumable: run.resumable } : {},
|
|
52372
|
+
...occurrence.actor !== undefined ? { actor: occurrence.actor } : {},
|
|
52373
|
+
...occurrence.kind !== "started" && run.origin !== undefined ? { origin: run.origin } : {},
|
|
52374
|
+
...occurrence.kind === "resumed" && run.resumedFromRunId !== undefined ? { continuedFromRunId: run.resumedFromRunId } : {},
|
|
52375
|
+
createdAt: occurrence.at
|
|
52376
|
+
};
|
|
52377
|
+
}
|
|
52378
|
+
function restingStage(run) {
|
|
52379
|
+
return run.stages.find((stage) => stage.status === "paused") ?? run.stages.find((stage) => stage.status === "running");
|
|
52380
|
+
}
|
|
52211
52381
|
function warnLifecycleSendFailure(error) {
|
|
52212
52382
|
if (process.env.ATOMIC_WORKFLOW_DEBUG !== "1")
|
|
52213
52383
|
return;
|
|
@@ -52255,6 +52425,54 @@ function terminalRunKey(kind, run) {
|
|
|
52255
52425
|
const occurrence = kind === "blocked" ? run.blockedAt ?? lifecycleOccurrenceAt(run, kind) : "";
|
|
52256
52426
|
return occurrence === undefined ? `${kind}:${run.id}` : `${kind}:${run.id}:${occurrence}`;
|
|
52257
52427
|
}
|
|
52428
|
+
function controlOccurrences(run) {
|
|
52429
|
+
const occurrences = [];
|
|
52430
|
+
const resumedRun = run.resumeSource === "run_control" || run.resumedFromRunId !== undefined;
|
|
52431
|
+
const userResumed = run.resumeSource === "run_control" && run.resumeActor === "user";
|
|
52432
|
+
const continuation = userResumed && run.resumedAt === undefined;
|
|
52433
|
+
if (run.origin === "user" && !resumedRun) {
|
|
52434
|
+
occurrences.push({ kind: "started", scope: "run", at: run.startedAt, actor: "user" });
|
|
52435
|
+
}
|
|
52436
|
+
if (userResumed && run.status === "running") {
|
|
52437
|
+
occurrences.push({
|
|
52438
|
+
kind: "resumed",
|
|
52439
|
+
scope: "run",
|
|
52440
|
+
at: continuation ? run.startedAt : run.resumedAt ?? run.startedAt,
|
|
52441
|
+
actor: "user"
|
|
52442
|
+
});
|
|
52443
|
+
}
|
|
52444
|
+
if (run.endedAt === undefined && run.status === "paused" && run.pauseActor === "user") {
|
|
52445
|
+
if (run.exitReason === "quit") {
|
|
52446
|
+
const quitAt = run.quitAt ?? run.pausedAt;
|
|
52447
|
+
if (quitAt !== undefined)
|
|
52448
|
+
occurrences.push({ kind: "quit", scope: "run", at: quitAt, actor: "user" });
|
|
52449
|
+
} else if (run.pausedAt !== undefined) {
|
|
52450
|
+
occurrences.push({ kind: "paused", scope: "run", at: run.pausedAt, actor: "user" });
|
|
52451
|
+
}
|
|
52452
|
+
}
|
|
52453
|
+
const runScoped = new Set(occurrences.map((occurrence) => occurrence.kind));
|
|
52454
|
+
if (run.endedAt !== undefined)
|
|
52455
|
+
return occurrences;
|
|
52456
|
+
for (const stage of run.stages) {
|
|
52457
|
+
if (stage.status === "paused" && stage.pauseActor === "user" && stage.pausedAt !== undefined) {
|
|
52458
|
+
if (!runScoped.has("paused") && !runScoped.has("quit")) {
|
|
52459
|
+
occurrences.push({ kind: "paused", scope: "stage", at: stage.pausedAt, actor: "user", stage });
|
|
52460
|
+
}
|
|
52461
|
+
}
|
|
52462
|
+
if (stage.status === "running" && stage.resumeActor === "user" && stage.resumedAt !== undefined) {
|
|
52463
|
+
if (!runScoped.has("resumed")) {
|
|
52464
|
+
occurrences.push({ kind: "resumed", scope: "stage", at: stage.resumedAt, actor: "user", stage });
|
|
52465
|
+
}
|
|
52466
|
+
}
|
|
52467
|
+
}
|
|
52468
|
+
return occurrences;
|
|
52469
|
+
}
|
|
52470
|
+
function controlOccurrenceKey(run, occurrence) {
|
|
52471
|
+
if (occurrence.scope === "stage" && occurrence.stage !== undefined) {
|
|
52472
|
+
return `${occurrence.kind}:${run.id}:stage:${occurrence.stage.id}:${occurrence.at}`;
|
|
52473
|
+
}
|
|
52474
|
+
return `${occurrence.kind}:${run.id}:${occurrence.at}`;
|
|
52475
|
+
}
|
|
52258
52476
|
function awaitingInputKey(runId, stage) {
|
|
52259
52477
|
const promptId = stage.pendingPrompt?.id ?? stage.inputRequest?.id;
|
|
52260
52478
|
if (promptId)
|
|
@@ -52283,12 +52501,12 @@ function makeNoticeComponent2(details, theme) {
|
|
|
52283
52501
|
};
|
|
52284
52502
|
}
|
|
52285
52503
|
function renderLifecycleNoticeCard(details, opts) {
|
|
52286
|
-
const tone = details.kind
|
|
52287
|
-
const title = details.kind
|
|
52288
|
-
const glyph = details.kind
|
|
52504
|
+
const tone = lifecycleNoticeTone(details.kind);
|
|
52505
|
+
const title = lifecycleNoticeTitle(details.kind);
|
|
52506
|
+
const glyph = lifecycleNoticeGlyph(details.kind);
|
|
52289
52507
|
const stage = details.stageName ?? details.failedStageId ?? details.stageId;
|
|
52290
52508
|
const tool = stage === undefined ? lifecycleToolOrigin(details) : undefined;
|
|
52291
|
-
const headline = details
|
|
52509
|
+
const headline = lifecycleNoticeHeadline(details);
|
|
52292
52510
|
return renderWorkflowNoticeCard({
|
|
52293
52511
|
title,
|
|
52294
52512
|
glyph,
|
|
@@ -52297,20 +52515,108 @@ function renderLifecycleNoticeCard(details, opts) {
|
|
|
52297
52515
|
fields: [
|
|
52298
52516
|
{ label: "workflow", value: details.workflowName },
|
|
52299
52517
|
{ label: "run", value: details.runId },
|
|
52518
|
+
{ label: "continues", value: details.continuedFromRunId },
|
|
52300
52519
|
{ label: "stage", value: stage },
|
|
52301
52520
|
{ label: "tool", value: tool },
|
|
52521
|
+
{ label: "actor", value: details.actor, tone: "muted" },
|
|
52522
|
+
{ label: "launched", value: details.origin, tone: "muted" },
|
|
52302
52523
|
{ label: "prompt", value: details.promptMessage, tone: "muted" },
|
|
52303
52524
|
{ label: "error", value: details.error, tone: "error" },
|
|
52525
|
+
{ label: "resumable", value: resumableFieldValue(details), tone: "muted" },
|
|
52304
52526
|
{ label: "duration", value: formatDurationMs(details.durationMs), tone: "muted" }
|
|
52305
52527
|
],
|
|
52306
|
-
hints: [
|
|
52307
|
-
details.kind === "awaiting_input" ? `/workflow connect ${details.runId}` : `/workflow status ${details.runId}`
|
|
52308
|
-
],
|
|
52528
|
+
hints: [lifecycleNoticeHint(details)],
|
|
52309
52529
|
fallbackText: opts.fallbackText,
|
|
52310
52530
|
width: opts.width,
|
|
52311
52531
|
...opts.theme ? { theme: opts.theme } : {}
|
|
52312
52532
|
});
|
|
52313
52533
|
}
|
|
52534
|
+
function lifecycleNoticeTone(kind) {
|
|
52535
|
+
switch (kind) {
|
|
52536
|
+
case "failed":
|
|
52537
|
+
return "error";
|
|
52538
|
+
case "blocked":
|
|
52539
|
+
case "awaiting_input":
|
|
52540
|
+
case "paused":
|
|
52541
|
+
case "quit":
|
|
52542
|
+
return "warning";
|
|
52543
|
+
default:
|
|
52544
|
+
return "success";
|
|
52545
|
+
}
|
|
52546
|
+
}
|
|
52547
|
+
function lifecycleNoticeTitle(kind) {
|
|
52548
|
+
switch (kind) {
|
|
52549
|
+
case "started":
|
|
52550
|
+
return "WORKFLOW STARTED";
|
|
52551
|
+
case "failed":
|
|
52552
|
+
return "WORKFLOW FAILED";
|
|
52553
|
+
case "awaiting_input":
|
|
52554
|
+
return "WORKFLOW INPUT";
|
|
52555
|
+
case "blocked":
|
|
52556
|
+
return "WORKFLOW BLOCKED";
|
|
52557
|
+
case "paused":
|
|
52558
|
+
return "WORKFLOW PAUSED";
|
|
52559
|
+
case "quit":
|
|
52560
|
+
return "WORKFLOW QUIT";
|
|
52561
|
+
case "resumed":
|
|
52562
|
+
return "WORKFLOW RESUMED";
|
|
52563
|
+
default:
|
|
52564
|
+
return "WORKFLOW COMPLETE";
|
|
52565
|
+
}
|
|
52566
|
+
}
|
|
52567
|
+
function lifecycleNoticeGlyph(kind) {
|
|
52568
|
+
switch (kind) {
|
|
52569
|
+
case "failed":
|
|
52570
|
+
return "✗";
|
|
52571
|
+
case "awaiting_input":
|
|
52572
|
+
return "?";
|
|
52573
|
+
case "blocked":
|
|
52574
|
+
return "!";
|
|
52575
|
+
case "paused":
|
|
52576
|
+
return "⏸";
|
|
52577
|
+
case "quit":
|
|
52578
|
+
return "⏹";
|
|
52579
|
+
case "started":
|
|
52580
|
+
case "resumed":
|
|
52581
|
+
return "▶";
|
|
52582
|
+
default:
|
|
52583
|
+
return "✓";
|
|
52584
|
+
}
|
|
52585
|
+
}
|
|
52586
|
+
function lifecycleNoticeHeadline(details) {
|
|
52587
|
+
const name = details.workflowName;
|
|
52588
|
+
const scope = details.scope === "stage" ? "Stage of workflow" : "Workflow";
|
|
52589
|
+
switch (details.kind) {
|
|
52590
|
+
case "started":
|
|
52591
|
+
return `Workflow "${name}" started`;
|
|
52592
|
+
case "failed":
|
|
52593
|
+
return `Workflow "${name}" failed`;
|
|
52594
|
+
case "awaiting_input":
|
|
52595
|
+
return `Workflow "${name}" needs input`;
|
|
52596
|
+
case "blocked":
|
|
52597
|
+
return `Workflow "${name}" ${details.active === true ? "is blocked" : "ended blocked"}`;
|
|
52598
|
+
case "paused":
|
|
52599
|
+
return `${scope} "${name}" paused`;
|
|
52600
|
+
case "quit":
|
|
52601
|
+
return `Workflow "${name}" quit`;
|
|
52602
|
+
case "resumed":
|
|
52603
|
+
return `${scope} "${name}" resumed`;
|
|
52604
|
+
default:
|
|
52605
|
+
return `Workflow "${name}" completed`;
|
|
52606
|
+
}
|
|
52607
|
+
}
|
|
52608
|
+
function lifecycleNoticeHint(details) {
|
|
52609
|
+
if (details.kind === "awaiting_input")
|
|
52610
|
+
return `/workflow connect ${details.runId}`;
|
|
52611
|
+
if (details.kind === "paused" || details.kind === "quit")
|
|
52612
|
+
return `/workflow resume ${details.runId}`;
|
|
52613
|
+
return `/workflow status ${details.runId}`;
|
|
52614
|
+
}
|
|
52615
|
+
function resumableFieldValue(details) {
|
|
52616
|
+
if (details.resumable === undefined)
|
|
52617
|
+
return;
|
|
52618
|
+
return details.resumable ? "yes" : "no";
|
|
52619
|
+
}
|
|
52314
52620
|
function formatDurationMs(durationMs) {
|
|
52315
52621
|
if (durationMs === undefined)
|
|
52316
52622
|
return;
|
|
@@ -52686,6 +52992,11 @@ import { CONFIG_DIR_NAME, CONFIG_DIR_NAMES, getAgentDir, getAgentDirs, getProjec
|
|
|
52686
52992
|
|
|
52687
52993
|
// dist/builtin/workflows/src/extension/config-file-loader.ts
|
|
52688
52994
|
var WORKFLOW_LIFECYCLE_NOTICE_KIND_SET = new Set(WORKFLOW_LIFECYCLE_NOTICE_KINDS);
|
|
52995
|
+
var WORKFLOW_LIFECYCLE_NOTICE_KIND_LIST = (() => {
|
|
52996
|
+
const quoted = WORKFLOW_LIFECYCLE_NOTICE_KINDS.map((kind) => JSON.stringify(kind));
|
|
52997
|
+
const last = quoted[quoted.length - 1] ?? "";
|
|
52998
|
+
return quoted.length <= 1 ? last : `${quoted.slice(0, -1).join(", ")}, or ${last}`;
|
|
52999
|
+
})();
|
|
52689
53000
|
async function tryReadFile(filePath) {
|
|
52690
53001
|
const { readFile } = await import("node:fs/promises");
|
|
52691
53002
|
try {
|
|
@@ -52741,7 +53052,7 @@ function validateConfig(value2) {
|
|
|
52741
53052
|
}
|
|
52742
53053
|
for (const item of notifyOn) {
|
|
52743
53054
|
if (!isWorkflowLifecycleNoticeKind(item)) {
|
|
52744
|
-
return `"workflowNotifications.notifyOn" entries must be
|
|
53055
|
+
return `"workflowNotifications.notifyOn" entries must be ${WORKFLOW_LIFECYCLE_NOTICE_KIND_LIST}, got ${JSON.stringify(item)}`;
|
|
52745
53056
|
}
|
|
52746
53057
|
}
|
|
52747
53058
|
}
|
|
@@ -52852,7 +53163,7 @@ var WORKFLOW_CONFIG_DEFAULTS = {
|
|
|
52852
53163
|
resumeInFlight: "ask",
|
|
52853
53164
|
workflowNotifications: {
|
|
52854
53165
|
enabled: true,
|
|
52855
|
-
notifyOn: ["completed", "failed", "blocked", "awaiting_input"]
|
|
53166
|
+
notifyOn: ["started", "completed", "failed", "blocked", "awaiting_input", "paused", "quit", "resumed"]
|
|
52856
53167
|
},
|
|
52857
53168
|
worktree: {
|
|
52858
53169
|
symlinkDirectories: ["node_modules"]
|
|
@@ -59478,6 +59789,40 @@ function durableStageCheckpointMetadata(stage, run, sourceOrder) {
|
|
|
59478
59789
|
// dist/builtin/workflows/src/durable/tool-primitive.ts
|
|
59479
59790
|
import { runCallback } from "@bastani/atomic";
|
|
59480
59791
|
|
|
59792
|
+
// dist/builtin/workflows/src/runs/shared/retry.ts
|
|
59793
|
+
import { nextRetryDecision } from "@bastani/atomic";
|
|
59794
|
+
function abortReason(signal) {
|
|
59795
|
+
const reason = signal?.reason;
|
|
59796
|
+
if (reason instanceof Error || reason instanceof DOMException || typeof reason === "string")
|
|
59797
|
+
return reason;
|
|
59798
|
+
return new Error("atomic-workflows: workflow cancelled");
|
|
59799
|
+
}
|
|
59800
|
+
function sleepOrAbort(ms, signal) {
|
|
59801
|
+
if (signal?.aborted)
|
|
59802
|
+
return Promise.reject(abortReason(signal));
|
|
59803
|
+
return new Promise((resolve4, reject) => {
|
|
59804
|
+
let settled = false;
|
|
59805
|
+
const cleanup = () => signal?.removeEventListener("abort", onAbort);
|
|
59806
|
+
const finish = () => {
|
|
59807
|
+
if (settled)
|
|
59808
|
+
return;
|
|
59809
|
+
settled = true;
|
|
59810
|
+
cleanup();
|
|
59811
|
+
resolve4();
|
|
59812
|
+
};
|
|
59813
|
+
const fail = (error) => {
|
|
59814
|
+
if (settled)
|
|
59815
|
+
return;
|
|
59816
|
+
settled = true;
|
|
59817
|
+
clearTimeout(timer);
|
|
59818
|
+
cleanup();
|
|
59819
|
+
reject(error);
|
|
59820
|
+
};
|
|
59821
|
+
const timer = setTimeout(finish, Math.max(0, ms));
|
|
59822
|
+
const onAbort = () => fail(abortReason(signal));
|
|
59823
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
59824
|
+
});
|
|
59825
|
+
}
|
|
59481
59826
|
// dist/builtin/workflows/src/durable/tool-failure-checkpoint.ts
|
|
59482
59827
|
async function recordThrowingToolFailure(input, node, identity, error, attempts) {
|
|
59483
59828
|
const message = workflowToolFailure(error, attempts, false).error.message;
|
|
@@ -59905,32 +60250,6 @@ async function executeWithRetries(fn, options, throwIfCancelled, signal) {
|
|
|
59905
60250
|
}
|
|
59906
60251
|
throw lastError ?? new Error("ctx.tool: retries exhausted");
|
|
59907
60252
|
}
|
|
59908
|
-
function sleepOrAbort(ms, signal) {
|
|
59909
|
-
if (signal?.aborted)
|
|
59910
|
-
return Promise.reject(signal.reason instanceof Error ? signal.reason : new Error("atomic-workflows: workflow cancelled"));
|
|
59911
|
-
return new Promise((resolve4, reject) => {
|
|
59912
|
-
let settled = false;
|
|
59913
|
-
const cleanup = () => signal?.removeEventListener("abort", onAbort);
|
|
59914
|
-
const finish = () => {
|
|
59915
|
-
if (settled)
|
|
59916
|
-
return;
|
|
59917
|
-
settled = true;
|
|
59918
|
-
cleanup();
|
|
59919
|
-
resolve4();
|
|
59920
|
-
};
|
|
59921
|
-
const fail = (err) => {
|
|
59922
|
-
if (settled)
|
|
59923
|
-
return;
|
|
59924
|
-
settled = true;
|
|
59925
|
-
clearTimeout(timer);
|
|
59926
|
-
cleanup();
|
|
59927
|
-
reject(err);
|
|
59928
|
-
};
|
|
59929
|
-
const timer = setTimeout(finish, ms);
|
|
59930
|
-
const onAbort = () => fail(signal?.reason instanceof Error ? signal.reason : new Error("atomic-workflows: workflow cancelled"));
|
|
59931
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
59932
|
-
});
|
|
59933
|
-
}
|
|
59934
60253
|
function createCheckpointIdGenerator() {
|
|
59935
60254
|
let counter = 0;
|
|
59936
60255
|
return () => `cp-${++counter}`;
|
|
@@ -60753,455 +61072,13 @@ async function buildModelCandidatesFromCatalog(input) {
|
|
|
60753
61072
|
}
|
|
60754
61073
|
}
|
|
60755
61074
|
// dist/builtin/workflows/src/runs/shared/model-fallback-failures.ts
|
|
60756
|
-
|
|
60757
|
-
|
|
60758
|
-
|
|
60759
|
-
|
|
60760
|
-
|
|
60761
|
-
|
|
60762
|
-
|
|
60763
|
-
/credit/i,
|
|
60764
|
-
/auth(?:entication|orization)?/i,
|
|
60765
|
-
/unauthori[sz]ed/i,
|
|
60766
|
-
/\b40[13]\b/,
|
|
60767
|
-
/api\s*key/i,
|
|
60768
|
-
/token\s*expired/i,
|
|
60769
|
-
/forbidden/i,
|
|
60770
|
-
/invalid\s*key/i,
|
|
60771
|
-
/model.*(?:unavailable|disabled|not\s*found|unknown)/i,
|
|
60772
|
-
/(?:unavailable|disabled|not\s*found|unknown).*model/i,
|
|
60773
|
-
/overloaded/i,
|
|
60774
|
-
/temporarily\s*unavailable/i,
|
|
60775
|
-
/service\s*unavailable/i,
|
|
60776
|
-
/network/i,
|
|
60777
|
-
/fetch/i,
|
|
60778
|
-
/socket/i,
|
|
60779
|
-
/connection\s*refused/i,
|
|
60780
|
-
/upstream/i,
|
|
60781
|
-
/timeout/i,
|
|
60782
|
-
/timed\s*out/i,
|
|
60783
|
-
/\b50[0-4]\b/
|
|
60784
|
-
];
|
|
60785
|
-
var NON_RETRYABLE_FAILURE_PATTERNS = [
|
|
60786
|
-
/command failed/i,
|
|
60787
|
-
/tests? failed/i,
|
|
60788
|
-
/shell/i,
|
|
60789
|
-
/missing file/i,
|
|
60790
|
-
/no such file/i,
|
|
60791
|
-
/cancel/i,
|
|
60792
|
-
/abort/i,
|
|
60793
|
-
/interrupted/i
|
|
60794
|
-
];
|
|
60795
|
-
var CANCELLED_FAILURE_PATTERNS = [/cancel/i, /abort/i, /interrupted/i];
|
|
60796
|
-
var FALLBACKABLE_FAILURE_KINDS = new Set([
|
|
60797
|
-
"auth_on_candidate_provider",
|
|
60798
|
-
"rate_limit",
|
|
60799
|
-
"provider_unavailable",
|
|
60800
|
-
"network_timeout",
|
|
60801
|
-
"transport_error",
|
|
60802
|
-
"model_unavailable",
|
|
60803
|
-
"request_incompatible"
|
|
60804
|
-
]);
|
|
60805
|
-
function asRecord2(value2) {
|
|
60806
|
-
return value2 !== null && typeof value2 === "object" ? value2 : undefined;
|
|
60807
|
-
}
|
|
60808
|
-
function field2(value2, key2) {
|
|
60809
|
-
return asRecord2(value2)?.[key2];
|
|
60810
|
-
}
|
|
60811
|
-
function stringField3(value2, key2) {
|
|
60812
|
-
const raw = field2(value2, key2);
|
|
60813
|
-
return typeof raw === "string" && raw.trim().length > 0 ? raw : undefined;
|
|
60814
|
-
}
|
|
60815
|
-
function errorName2(value2) {
|
|
60816
|
-
return value2 instanceof Error ? value2.name : stringField3(value2, "name");
|
|
60817
|
-
}
|
|
60818
|
-
function directMessageFrom(value2) {
|
|
60819
|
-
return stringField3(value2, "errorMessage") ?? stringField3(value2, "message") ?? stringField3(value2, "statusText");
|
|
60820
|
-
}
|
|
60821
|
-
function integerFrom2(value2) {
|
|
60822
|
-
if (typeof value2 === "number" && Number.isInteger(value2))
|
|
60823
|
-
return value2;
|
|
60824
|
-
if (typeof value2 !== "string" || value2.trim().length === 0)
|
|
60825
|
-
return;
|
|
60826
|
-
const parsed = Number(value2.trim());
|
|
60827
|
-
return Number.isInteger(parsed) ? parsed : undefined;
|
|
60828
|
-
}
|
|
60829
|
-
function statusFrom(value2) {
|
|
60830
|
-
return integerFrom2(field2(value2, "status")) ?? integerFrom2(field2(value2, "statusCode")) ?? integerFrom2(field2(value2, "httpStatus"));
|
|
60831
|
-
}
|
|
60832
|
-
function codeFrom(value2) {
|
|
60833
|
-
const rawCode = field2(value2, "code");
|
|
60834
|
-
return typeof rawCode === "string" || typeof rawCode === "number" ? rawCode : undefined;
|
|
60835
|
-
}
|
|
60836
|
-
function stopReasonFrom(value2) {
|
|
60837
|
-
return stringField3(value2, "stopReason");
|
|
60838
|
-
}
|
|
60839
|
-
function finishReasonFrom(value2) {
|
|
60840
|
-
return stringField3(value2, "finish_reason") ?? stringField3(value2, "finishReason");
|
|
60841
|
-
}
|
|
60842
|
-
function causeOf2(value2) {
|
|
60843
|
-
return value2 instanceof Error ? value2.cause : field2(value2, "cause");
|
|
60844
|
-
}
|
|
60845
|
-
function diagnosticErrors2(value2) {
|
|
60846
|
-
const diagnostics = field2(value2, "diagnostics");
|
|
60847
|
-
if (!Array.isArray(diagnostics))
|
|
60848
|
-
return [];
|
|
60849
|
-
const errors = [];
|
|
60850
|
-
for (const diagnostic of diagnostics) {
|
|
60851
|
-
const diagnosticError = field2(diagnostic, "error");
|
|
60852
|
-
errors.push(diagnosticError ?? diagnostic);
|
|
60853
|
-
}
|
|
60854
|
-
return errors;
|
|
60855
|
-
}
|
|
60856
|
-
function normalizeCode2(value2) {
|
|
60857
|
-
if (value2 === undefined)
|
|
60858
|
-
return;
|
|
60859
|
-
const normalized = String(value2).trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
60860
|
-
return normalized.length > 0 ? normalized : undefined;
|
|
60861
|
-
}
|
|
60862
|
-
function kindFromStatus(status) {
|
|
60863
|
-
switch (status) {
|
|
60864
|
-
case 400:
|
|
60865
|
-
case 413:
|
|
60866
|
-
case 422:
|
|
60867
|
-
return "request_incompatible";
|
|
60868
|
-
case 401:
|
|
60869
|
-
case 403:
|
|
60870
|
-
return "auth_on_candidate_provider";
|
|
60871
|
-
case 408:
|
|
60872
|
-
return "network_timeout";
|
|
60873
|
-
case 404:
|
|
60874
|
-
return "model_unavailable";
|
|
60875
|
-
case 429:
|
|
60876
|
-
return "rate_limit";
|
|
60877
|
-
default:
|
|
60878
|
-
if (status !== undefined && status >= 500 && status <= 599)
|
|
60879
|
-
return "provider_unavailable";
|
|
60880
|
-
return;
|
|
60881
|
-
}
|
|
60882
|
-
}
|
|
60883
|
-
function refusalKindFromCode(code) {
|
|
60884
|
-
const normalizedCode = normalizeCode2(code);
|
|
60885
|
-
if (normalizedCode === undefined)
|
|
60886
|
-
return;
|
|
60887
|
-
if (normalizedCode.includes("content_filter") || normalizedCode.includes("contentfilter"))
|
|
60888
|
-
return "task_failure";
|
|
60889
|
-
if (normalizedCode.includes("safety") || normalizedCode.includes("policy"))
|
|
60890
|
-
return "task_failure";
|
|
60891
|
-
switch (normalizedCode) {
|
|
60892
|
-
case "blocked":
|
|
60893
|
-
case "blocked_by_provider":
|
|
60894
|
-
case "blocked_by_safety":
|
|
60895
|
-
case "blocked_by_policy":
|
|
60896
|
-
case "provider_refusal":
|
|
60897
|
-
case "refusal":
|
|
60898
|
-
case "tool_refusal":
|
|
60899
|
-
case "tool_call_refusal":
|
|
60900
|
-
case "tool_use_refusal":
|
|
60901
|
-
return "task_failure";
|
|
60902
|
-
default:
|
|
60903
|
-
return;
|
|
60904
|
-
}
|
|
60905
|
-
}
|
|
60906
|
-
var REQUEST_INCOMPATIBLE_CODES = new Set([
|
|
60907
|
-
"invalid_request",
|
|
60908
|
-
"invalid_request_error",
|
|
60909
|
-
"bad_request",
|
|
60910
|
-
"context_length_exceeded",
|
|
60911
|
-
"request_too_large",
|
|
60912
|
-
"too_large",
|
|
60913
|
-
"request_entity_too_large",
|
|
60914
|
-
"max_tokens",
|
|
60915
|
-
"max_context_length",
|
|
60916
|
-
"context_window_exceeded"
|
|
60917
|
-
]);
|
|
60918
|
-
function requestIncompatibleKindFromCode(code) {
|
|
60919
|
-
const normalizedCode = normalizeCode2(code);
|
|
60920
|
-
return normalizedCode !== undefined && REQUEST_INCOMPATIBLE_CODES.has(normalizedCode) ? "request_incompatible" : undefined;
|
|
60921
|
-
}
|
|
60922
|
-
function kindFromCode(code) {
|
|
60923
|
-
const normalizedCode = normalizeCode2(code);
|
|
60924
|
-
if (normalizedCode === undefined)
|
|
60925
|
-
return;
|
|
60926
|
-
const refusalKind = refusalKindFromCode(code);
|
|
60927
|
-
if (refusalKind !== undefined)
|
|
60928
|
-
return refusalKind;
|
|
60929
|
-
const httpStatusKind = kindFromStatus(integerFrom2(code));
|
|
60930
|
-
if (httpStatusKind !== undefined)
|
|
60931
|
-
return httpStatusKind;
|
|
60932
|
-
const requestIncompatibleKind = requestIncompatibleKindFromCode(code);
|
|
60933
|
-
if (requestIncompatibleKind !== undefined)
|
|
60934
|
-
return requestIncompatibleKind;
|
|
60935
|
-
switch (normalizedCode) {
|
|
60936
|
-
case "auth":
|
|
60937
|
-
case "auth_required":
|
|
60938
|
-
case "authentication_required":
|
|
60939
|
-
case "unauthorized":
|
|
60940
|
-
case "forbidden":
|
|
60941
|
-
case "invalid_api_key":
|
|
60942
|
-
case "missing_api_key":
|
|
60943
|
-
case "invalid_key":
|
|
60944
|
-
return "auth_on_candidate_provider";
|
|
60945
|
-
case "etimedout":
|
|
60946
|
-
case "econnreset":
|
|
60947
|
-
case "econnrefused":
|
|
60948
|
-
case "enotfound":
|
|
60949
|
-
case "eai_again":
|
|
60950
|
-
case "fetch_failed":
|
|
60951
|
-
case "network_error":
|
|
60952
|
-
case "timeout":
|
|
60953
|
-
case "timeout_error":
|
|
60954
|
-
case "und_err_connect_timeout":
|
|
60955
|
-
return "network_timeout";
|
|
60956
|
-
case "rate_limit":
|
|
60957
|
-
case "rate_limit_exceeded":
|
|
60958
|
-
case "too_many_requests":
|
|
60959
|
-
case "quota_exceeded":
|
|
60960
|
-
case "insufficient_quota":
|
|
60961
|
-
case "usage_limit":
|
|
60962
|
-
case "usage_limit_reached":
|
|
60963
|
-
case "usage_limit_exceeded":
|
|
60964
|
-
return "rate_limit";
|
|
60965
|
-
case "aborterror":
|
|
60966
|
-
case "aborted":
|
|
60967
|
-
case "cancelled":
|
|
60968
|
-
case "canceled":
|
|
60969
|
-
return "cancelled";
|
|
60970
|
-
case "model_not_found":
|
|
60971
|
-
case "model_unavailable":
|
|
60972
|
-
case "model_disabled":
|
|
60973
|
-
case "unknown_model":
|
|
60974
|
-
return "model_unavailable";
|
|
60975
|
-
case "provider_error":
|
|
60976
|
-
case "api_error":
|
|
60977
|
-
case "service_unavailable":
|
|
60978
|
-
case "temporarily_unavailable":
|
|
60979
|
-
case "overloaded":
|
|
60980
|
-
return "provider_unavailable";
|
|
60981
|
-
default:
|
|
60982
|
-
return;
|
|
60983
|
-
}
|
|
60984
|
-
}
|
|
60985
|
-
var REQUEST_INCOMPATIBLE_FAILURE_PATTERNS = [
|
|
60986
|
-
/\bcontext[_\s-]?length(?:[_\s-]?exceeded)?\b/i,
|
|
60987
|
-
/\bcontext[_\s-]?window(?:[_\s-]?exceeded)?\b/i,
|
|
60988
|
-
/\bmax[_\s-]?context\b/i,
|
|
60989
|
-
/\bmax[_\s-]?tokens?\b/i,
|
|
60990
|
-
/\brequest(?:[_\s-]?entity)?[_\s-]?too[_\s-]?large\b/i,
|
|
60991
|
-
/\btoo[_\s-]?large\b/i,
|
|
60992
|
-
/\b(?:unsupported|unknown|invalid)\s+(?:tool|parameter|function)\b/i,
|
|
60993
|
-
/\b(?:tool|parameter|function)\s+(?:not\s+(?:supported|found|allowed)|unknown|invalid)\b/i,
|
|
60994
|
-
/\binvalid[_\s-]?request(?:[_\s-]?error)?\b/i,
|
|
60995
|
-
/\bbad[_\s-]?request\b/i
|
|
60996
|
-
];
|
|
60997
|
-
var PROVIDER_REFUSAL_FAILURE_PATTERNS = [
|
|
60998
|
-
/\bfinish[_\s-]?reason\b[^\n]*\bcontent[_\s-]?filter\b/i,
|
|
60999
|
-
/\bcontent[_\s-]?filter(?:ed|ing)?\b/i,
|
|
61000
|
-
/\b(?:safety|policy)\b[^\n]*\b(?:refus(?:e|al|ed|es|ing)?|block(?:ed|ing)?|filter(?:ed|ing)?|violat(?:e|ion|ed|ing)?|disallow(?:ed|ing)?|reject(?:ed|ion|ing)?)\b/i,
|
|
61001
|
-
/\b(?:refus(?:e|al|ed|es|ing)?|block(?:ed|ing)?|filter(?:ed|ing)?|violat(?:e|ion|ed|ing)?|disallow(?:ed|ing)?|reject(?:ed|ion|ing)?)\b[^\n]*\b(?:safety|policy)\b/i,
|
|
61002
|
-
/\btool[_\s-]?(?:call|use)?[_\s-]?refus(?:e|al|ed|es|ing)?\b/i,
|
|
61003
|
-
/\btool(?:\s+call|\s+use)?\b[^\n]*\brefus(?:e|al|ed|es|ing)?\b/i,
|
|
61004
|
-
/\brefus(?:e|al|ed|es|ing)?\b[^\n]*\btool(?:\s+call|\s+use)?\b/i,
|
|
61005
|
-
/\bprovider[_\s-]?refus(?:e|al|ed|es|ing)?\b/i,
|
|
61006
|
-
/\bprovider\b[^\n]*\brefus(?:e|al|ed|es|ing)?\b[^\n]*\b(?:prompt|request|content|policy|safety)\b/i
|
|
61007
|
-
];
|
|
61008
|
-
var TRANSPORT_OUTAGE_FAILURE_PATTERNS = [/^connection\s+error\.?$/i, /^fetch\s+failed\.?$/i];
|
|
61009
|
-
function transportOutageKindFromMessage(message) {
|
|
61010
|
-
return TRANSPORT_OUTAGE_FAILURE_PATTERNS.some((pattern) => pattern.test(message.trim())) ? "transport_error" : undefined;
|
|
61011
|
-
}
|
|
61012
|
-
function refusalKindFromMessage(message) {
|
|
61013
|
-
if (CANCELLED_FAILURE_PATTERNS.some((pattern) => pattern.test(message)))
|
|
61014
|
-
return "cancelled";
|
|
61015
|
-
if (NON_RETRYABLE_FAILURE_PATTERNS.some((pattern) => pattern.test(message)))
|
|
61016
|
-
return "task_failure";
|
|
61017
|
-
if (PROVIDER_REFUSAL_FAILURE_PATTERNS.some((pattern) => pattern.test(message)))
|
|
61018
|
-
return "task_failure";
|
|
61019
|
-
return;
|
|
61020
|
-
}
|
|
61021
|
-
function fallbackKindFromMessage(message, name) {
|
|
61022
|
-
const refusalKind = refusalKindFromMessage(message);
|
|
61023
|
-
if (refusalKind !== undefined)
|
|
61024
|
-
return refusalKind;
|
|
61025
|
-
const transportOutageKind = transportOutageKindFromMessage(message);
|
|
61026
|
-
if (transportOutageKind !== undefined)
|
|
61027
|
-
return transportOutageKind;
|
|
61028
|
-
if (REQUEST_INCOMPATIBLE_FAILURE_PATTERNS.some((pattern) => pattern.test(message)))
|
|
61029
|
-
return "request_incompatible";
|
|
61030
|
-
const nameKind = kindFromCode(name);
|
|
61031
|
-
if (nameKind !== undefined)
|
|
61032
|
-
return nameKind;
|
|
61033
|
-
if (!RETRYABLE_MODEL_FAILURE_PATTERNS.some((pattern) => pattern.test(message)))
|
|
61034
|
-
return;
|
|
61035
|
-
if (/rate\s*limit|too\s*many\s*requests|\b429\b|quota|usage[\s_-]*limit|billing|credit/i.test(message))
|
|
61036
|
-
return "rate_limit";
|
|
61037
|
-
if (/auth|unauthori[sz]ed|\b40[13]\b|api\s*key|token\s*expired|forbidden|invalid\s*key/i.test(message))
|
|
61038
|
-
return "auth_on_candidate_provider";
|
|
61039
|
-
if (/model.*(?:unavailable|disabled|not\s*found|unknown)|(?:unavailable|disabled|not\s*found|unknown).*model/i.test(message))
|
|
61040
|
-
return "model_unavailable";
|
|
61041
|
-
if (/network|fetch|socket|connection\s*refused|timeout|timed\s*out/i.test(message))
|
|
61042
|
-
return "network_timeout";
|
|
61043
|
-
return "provider_unavailable";
|
|
61044
|
-
}
|
|
61045
|
-
function signalSource(value2, fallback) {
|
|
61046
|
-
if (fallback !== undefined)
|
|
61047
|
-
return fallback;
|
|
61048
|
-
if (stopReasonFrom(value2) !== undefined || diagnosticErrors2(value2).length > 0)
|
|
61049
|
-
return "assistant_message";
|
|
61050
|
-
if (value2 instanceof Error)
|
|
61051
|
-
return "throw";
|
|
61052
|
-
return "structured";
|
|
61053
|
-
}
|
|
61054
|
-
function makeSignal(kind, value2, source) {
|
|
61055
|
-
const status = statusFrom(value2);
|
|
61056
|
-
const code = codeFrom(value2);
|
|
61057
|
-
const name = errorName2(value2);
|
|
61058
|
-
const stopReason = stopReasonFrom(value2);
|
|
61059
|
-
return {
|
|
61060
|
-
kind,
|
|
61061
|
-
message: errorMessage3(value2),
|
|
61062
|
-
source: signalSource(value2, source),
|
|
61063
|
-
...stopReason !== undefined ? { stopReason } : {},
|
|
61064
|
-
...status !== undefined ? { status } : {},
|
|
61065
|
-
...code !== undefined ? { code } : {},
|
|
61066
|
-
...name !== undefined ? { name } : {}
|
|
61067
|
-
};
|
|
61068
|
-
}
|
|
61069
|
-
function fallbackSignalFromDirectMessage(value2, source) {
|
|
61070
|
-
const message = directMessageFrom(value2);
|
|
61071
|
-
if (message === undefined)
|
|
61072
|
-
return;
|
|
61073
|
-
const kind = fallbackKindFromMessage(message, errorName2(value2));
|
|
61074
|
-
return kind === undefined ? undefined : makeSignal(kind, value2, source);
|
|
61075
|
-
}
|
|
61076
|
-
function fallbackSignalFromMessage(value2, source) {
|
|
61077
|
-
const message = errorMessage3(value2);
|
|
61078
|
-
if (!message.trim())
|
|
61079
|
-
return;
|
|
61080
|
-
const kind = fallbackKindFromMessage(message, errorName2(value2));
|
|
61081
|
-
return kind === undefined ? undefined : makeSignal(kind, value2, source);
|
|
61082
|
-
}
|
|
61083
|
-
function classifyAssistantRefusalSignal(value2, source) {
|
|
61084
|
-
const codeRefusalKind = refusalKindFromCode(codeFrom(value2)) ?? refusalKindFromCode(errorName2(value2)) ?? refusalKindFromCode(finishReasonFrom(value2));
|
|
61085
|
-
if (codeRefusalKind !== undefined)
|
|
61086
|
-
return makeSignal(codeRefusalKind, value2, source);
|
|
61087
|
-
const messageRefusalKind = refusalKindFromMessage(directMessageFrom(value2) ?? "");
|
|
61088
|
-
return messageRefusalKind === undefined ? undefined : makeSignal(messageRefusalKind, value2, source);
|
|
61089
|
-
}
|
|
61090
|
-
function isRefusalSignal(signal) {
|
|
61091
|
-
return signal.kind === "cancelled" || signal.kind === "task_failure";
|
|
61092
|
-
}
|
|
61093
|
-
function structuredSignal2(value2, seen, source) {
|
|
61094
|
-
if (value2 === undefined || value2 === null || seen.has(value2))
|
|
61095
|
-
return;
|
|
61096
|
-
if (typeof value2 === "object")
|
|
61097
|
-
seen.add(value2);
|
|
61098
|
-
const stopReason = stopReasonFrom(value2)?.toLowerCase();
|
|
61099
|
-
if (stopReason === "aborted")
|
|
61100
|
-
return makeSignal("cancelled", value2, source);
|
|
61101
|
-
const directRefusalSignal = classifyAssistantRefusalSignal(value2, source);
|
|
61102
|
-
if (directRefusalSignal !== undefined)
|
|
61103
|
-
return directRefusalSignal;
|
|
61104
|
-
const codeKind = kindFromCode(codeFrom(value2));
|
|
61105
|
-
const nameKind = kindFromCode(errorName2(value2));
|
|
61106
|
-
if (codeKind === "cancelled" || nameKind === "cancelled")
|
|
61107
|
-
return makeSignal("cancelled", value2, source);
|
|
61108
|
-
let firstNestedFallbackSignal;
|
|
61109
|
-
const nestedSeen = new Set(seen);
|
|
61110
|
-
for (const diagnosticError of diagnosticErrors2(value2)) {
|
|
61111
|
-
const diagnosticSignal = structuredSignal2(diagnosticError, nestedSeen, "diagnostic") ?? fallbackSignalFromMessage(diagnosticError, "diagnostic");
|
|
61112
|
-
if (diagnosticSignal === undefined)
|
|
61113
|
-
continue;
|
|
61114
|
-
if (isRefusalSignal(diagnosticSignal))
|
|
61115
|
-
return diagnosticSignal;
|
|
61116
|
-
firstNestedFallbackSignal ??= diagnosticSignal;
|
|
61117
|
-
}
|
|
61118
|
-
const cause = causeOf2(value2);
|
|
61119
|
-
const causeSignal = structuredSignal2(cause, nestedSeen, source) ?? fallbackSignalFromMessage(cause, source);
|
|
61120
|
-
if (causeSignal !== undefined) {
|
|
61121
|
-
if (isRefusalSignal(causeSignal))
|
|
61122
|
-
return causeSignal;
|
|
61123
|
-
firstNestedFallbackSignal ??= causeSignal;
|
|
61124
|
-
}
|
|
61125
|
-
const directMessageSignal = fallbackSignalFromDirectMessage(value2, source);
|
|
61126
|
-
if (directMessageSignal !== undefined)
|
|
61127
|
-
return directMessageSignal;
|
|
61128
|
-
const statusKind = kindFromStatus(statusFrom(value2));
|
|
61129
|
-
if (statusKind !== undefined)
|
|
61130
|
-
return makeSignal(statusKind, value2, source);
|
|
61131
|
-
if (codeKind !== undefined)
|
|
61132
|
-
return makeSignal(codeKind, value2, source);
|
|
61133
|
-
if (nameKind !== undefined)
|
|
61134
|
-
return makeSignal(nameKind, value2, source);
|
|
61135
|
-
if (firstNestedFallbackSignal !== undefined)
|
|
61136
|
-
return firstNestedFallbackSignal;
|
|
61137
|
-
if (stopReason === "error")
|
|
61138
|
-
return makeSignal("provider_unavailable", value2, source);
|
|
61139
|
-
return;
|
|
61140
|
-
}
|
|
61141
|
-
function messageFromUnknown(value2, seen) {
|
|
61142
|
-
if (value2 === undefined || value2 === null || seen.has(value2))
|
|
61143
|
-
return;
|
|
61144
|
-
if (typeof value2 === "string")
|
|
61145
|
-
return value2.trim().length > 0 ? value2 : undefined;
|
|
61146
|
-
if (typeof value2 === "number" || typeof value2 === "boolean" || typeof value2 === "bigint")
|
|
61147
|
-
return String(value2);
|
|
61148
|
-
if (typeof value2 === "symbol" || typeof value2 === "function")
|
|
61149
|
-
return;
|
|
61150
|
-
seen.add(value2);
|
|
61151
|
-
if (value2 instanceof Error && value2.message.trim().length > 0)
|
|
61152
|
-
return value2.message;
|
|
61153
|
-
const directMessage = directMessageFrom(value2);
|
|
61154
|
-
if (directMessage !== undefined)
|
|
61155
|
-
return directMessage;
|
|
61156
|
-
for (const diagnosticError of diagnosticErrors2(value2)) {
|
|
61157
|
-
const diagnosticMessage = messageFromUnknown(diagnosticError, seen);
|
|
61158
|
-
if (diagnosticMessage !== undefined)
|
|
61159
|
-
return diagnosticMessage;
|
|
61160
|
-
}
|
|
61161
|
-
const causeMessage = messageFromUnknown(causeOf2(value2), seen);
|
|
61162
|
-
if (causeMessage !== undefined)
|
|
61163
|
-
return causeMessage;
|
|
61164
|
-
const stopReason = stopReasonFrom(value2);
|
|
61165
|
-
if (stopReason !== undefined)
|
|
61166
|
-
return `Assistant message ended with stopReason:${stopReason}`;
|
|
61167
|
-
const finishReason = finishReasonFrom(value2);
|
|
61168
|
-
if (finishReason !== undefined)
|
|
61169
|
-
return `Model request finished with finish_reason:${finishReason}`;
|
|
61170
|
-
const status = statusFrom(value2);
|
|
61171
|
-
if (status !== undefined)
|
|
61172
|
-
return `Model request failed with status ${status}`;
|
|
61173
|
-
const code = codeFrom(value2);
|
|
61174
|
-
if (code !== undefined)
|
|
61175
|
-
return `Model request failed with code ${String(code)}`;
|
|
61176
|
-
return;
|
|
61177
|
-
}
|
|
61178
|
-
function errorMessage3(error) {
|
|
61179
|
-
const structuredMessage = messageFromUnknown(error, new Set);
|
|
61180
|
-
if (structuredMessage !== undefined)
|
|
61181
|
-
return structuredMessage;
|
|
61182
|
-
const rendered = String(error);
|
|
61183
|
-
return rendered === "[object Object]" ? "Model request failed" : rendered;
|
|
61184
|
-
}
|
|
61185
|
-
function normalizeModelFailureSignal(error) {
|
|
61186
|
-
const structured2 = structuredSignal2(error, new Set);
|
|
61187
|
-
if (structured2 !== undefined)
|
|
61188
|
-
return structured2;
|
|
61189
|
-
const message = errorMessage3(error);
|
|
61190
|
-
const name = errorName2(error);
|
|
61191
|
-
const fallbackKind = message.trim().length > 0 ? fallbackKindFromMessage(message, name) : undefined;
|
|
61192
|
-
return {
|
|
61193
|
-
kind: fallbackKind ?? "unknown",
|
|
61194
|
-
message,
|
|
61195
|
-
source: "string_fallback",
|
|
61196
|
-
...name !== undefined ? { name } : {}
|
|
61197
|
-
};
|
|
61198
|
-
}
|
|
61199
|
-
function isRetryableModelFailure(error) {
|
|
61200
|
-
if (error === undefined)
|
|
61201
|
-
return false;
|
|
61202
|
-
const signal = normalizeModelFailureSignal(error);
|
|
61203
|
-
return FALLBACKABLE_FAILURE_KINDS.has(signal.kind);
|
|
61204
|
-
}
|
|
61075
|
+
import {
|
|
61076
|
+
errorMessage as errorMessage3,
|
|
61077
|
+
isRetryableModelFailure,
|
|
61078
|
+
isRetryableSameModelFailure,
|
|
61079
|
+
modelFailureMessage,
|
|
61080
|
+
normalizeModelFailureSignal
|
|
61081
|
+
} from "@bastani/atomic";
|
|
61205
61082
|
// dist/builtin/workflows/src/runs/shared/worktree-git.ts
|
|
61206
61083
|
import * as fs3 from "node:fs";
|
|
61207
61084
|
import * as path3 from "node:path";
|
|
@@ -62541,7 +62418,7 @@ function truncateTaskOutput(text, maxOutput) {
|
|
|
62541
62418
|
[workflow output truncated; limits: ${limits.bytes} bytes, ${limits.lines} lines]`;
|
|
62542
62419
|
}
|
|
62543
62420
|
function withoutUndefinedProperties(value2) {
|
|
62544
|
-
return Object.fromEntries(Object.entries(value2).filter(([,
|
|
62421
|
+
return Object.fromEntries(Object.entries(value2).filter(([, field2]) => field2 !== undefined));
|
|
62545
62422
|
}
|
|
62546
62423
|
function sharedTaskDefaultsFromOptions(options) {
|
|
62547
62424
|
const {
|
|
@@ -62680,11 +62557,12 @@ function setupWorkflowInputGitWorktree(inputDefaults, workflowInvocationCwd, cac
|
|
|
62680
62557
|
function workflowCwdWithInputWorktree(inputDefaults, workflowInvocationCwd, cache) {
|
|
62681
62558
|
return setupWorkflowInputGitWorktree(inputDefaults, workflowInvocationCwd, cache)?.cwd ?? workflowInvocationCwd;
|
|
62682
62559
|
}
|
|
62683
|
-
function workflowInvocationMetadata(inputDefaults, workflowInvocationCwd, cache) {
|
|
62560
|
+
function workflowInvocationMetadata(inputDefaults, workflowInvocationCwd, cache, origin) {
|
|
62684
62561
|
const setup = setupWorkflowInputGitWorktree(inputDefaults, workflowInvocationCwd, cache);
|
|
62685
62562
|
return {
|
|
62686
62563
|
invocationCwd: workflowInvocationCwd,
|
|
62687
|
-
...setup !== undefined ? { workflowCwd: setup.cwd, repositoryRoot: setup.repositoryRoot, gitWorktreeRoot: setup.worktreeRoot } : {}
|
|
62564
|
+
...setup !== undefined ? { workflowCwd: setup.cwd, repositoryRoot: setup.repositoryRoot, gitWorktreeRoot: setup.worktreeRoot } : {},
|
|
62565
|
+
...origin !== undefined ? { origin } : {}
|
|
62688
62566
|
};
|
|
62689
62567
|
}
|
|
62690
62568
|
function resolvedTaskCwd(cwd, workflowInvocationCwd) {
|
|
@@ -63409,7 +63287,7 @@ function buildPromptNodeUiAdapter(input) {
|
|
|
63409
63287
|
},
|
|
63410
63288
|
async resume() {
|
|
63411
63289
|
input.activeStore.recordStageResumed(input.runId, stageId);
|
|
63412
|
-
input.activeStore.recordRunResumed(input.runId);
|
|
63290
|
+
input.activeStore.recordRunResumed(input.runId, undefined, { source: "prompt_answer" });
|
|
63413
63291
|
const currentPauseGate = pauseGate;
|
|
63414
63292
|
pauseGate = undefined;
|
|
63415
63293
|
currentPauseGate?.resolve();
|
|
@@ -63643,8 +63521,8 @@ function createRunFinalizers(input) {
|
|
|
63643
63521
|
...signal.reason !== undefined ? { exitReason: signal.reason } : {}
|
|
63644
63522
|
}, input.opts.onRunEnd);
|
|
63645
63523
|
};
|
|
63646
|
-
const finalizeParentWorkflowExitCancellation = async (
|
|
63647
|
-
const parentReason =
|
|
63524
|
+
const finalizeParentWorkflowExitCancellation = async (abortReason2) => {
|
|
63525
|
+
const parentReason = abortReason2.workflowExitReason;
|
|
63648
63526
|
await input.drainWorkflowExitCleanups(parentReason);
|
|
63649
63527
|
const exitReason = parentWorkflowExitRunReason(parentReason);
|
|
63650
63528
|
const metadata = { resumable: false, exited: true, exitReason };
|
|
@@ -65043,6 +64921,7 @@ async function resumeDurableWorkflow(workflowId, deps, catalog) {
|
|
|
65043
64921
|
const resumeRunOpts = {
|
|
65044
64922
|
...deps.baseRunOpts,
|
|
65045
64923
|
...handle.invocationCwd !== undefined ? { cwd: handle.invocationCwd } : {},
|
|
64924
|
+
...handle.origin !== undefined ? { origin: handle.origin } : {},
|
|
65046
64925
|
runId: resolved.workflowId,
|
|
65047
64926
|
durableBackend: backend
|
|
65048
64927
|
};
|
|
@@ -66858,7 +66737,7 @@ function createStageControlHandle(runtime) {
|
|
|
66858
66737
|
if (changed) {
|
|
66859
66738
|
runtime.scheduler.releaseStageBarrier(runtime.stageId);
|
|
66860
66739
|
await runtime.scheduler.cascadeResumeFrom(runtime.stageId);
|
|
66861
|
-
runtime.activeStore.recordRunResumed(runtime.runId);
|
|
66740
|
+
runtime.activeStore.recordRunResumed(runtime.runId, undefined, { source: "stage_control" });
|
|
66862
66741
|
}
|
|
66863
66742
|
if (wakeReleasedIdleStageChat)
|
|
66864
66743
|
runtime.state.wakeWaitingForStageChatTurn?.();
|
|
@@ -67028,6 +66907,7 @@ import { createStructuredOutputCapture, runCallback as runCallback2 } from "@bas
|
|
|
67028
66907
|
|
|
67029
66908
|
// dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts
|
|
67030
66909
|
import {
|
|
66910
|
+
convertToLlm,
|
|
67031
66911
|
shouldApplyCodexFastModeForScope
|
|
67032
66912
|
} from "@bastani/atomic";
|
|
67033
66913
|
|
|
@@ -67915,6 +67795,54 @@ function terminatingToolCallId(event) {
|
|
|
67915
67795
|
}
|
|
67916
67796
|
|
|
67917
67797
|
// dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts
|
|
67798
|
+
function isSessionCreationPauseResult(value2) {
|
|
67799
|
+
return "kind" in value2 && value2.kind === "paused";
|
|
67800
|
+
}
|
|
67801
|
+
|
|
67802
|
+
class StageSessionCreationCancelled extends Error {
|
|
67803
|
+
constructor() {
|
|
67804
|
+
super("atomic-workflows: stage session creation was cancelled while paused");
|
|
67805
|
+
this.name = "StageSessionCreationCancelled";
|
|
67806
|
+
}
|
|
67807
|
+
}
|
|
67808
|
+
function stageUserMessageText(message) {
|
|
67809
|
+
if (message.role !== "user")
|
|
67810
|
+
return;
|
|
67811
|
+
if (typeof message.content === "string")
|
|
67812
|
+
return message.content;
|
|
67813
|
+
return message.content.filter((part) => part.type === "text").map((part) => part.text).join("");
|
|
67814
|
+
}
|
|
67815
|
+
function retrySettingsManagerFromError(error) {
|
|
67816
|
+
if (error === null || typeof error !== "object")
|
|
67817
|
+
return;
|
|
67818
|
+
const manager = error.settingsManager;
|
|
67819
|
+
if (manager === null || typeof manager !== "object")
|
|
67820
|
+
return;
|
|
67821
|
+
const candidate = manager;
|
|
67822
|
+
return typeof candidate.getCodexFastModeSettings === "function" ? candidate : undefined;
|
|
67823
|
+
}
|
|
67824
|
+
function retryableAgentSession(activeSession) {
|
|
67825
|
+
const session = asAgentSession(activeSession);
|
|
67826
|
+
if (session === undefined)
|
|
67827
|
+
return;
|
|
67828
|
+
const candidate = session;
|
|
67829
|
+
return typeof candidate._runAgentContinue === "function" ? session : undefined;
|
|
67830
|
+
}
|
|
67831
|
+
function canContinueFromTranscript(activeSession) {
|
|
67832
|
+
const converted = convertToLlm([...activeSession.messages]);
|
|
67833
|
+
const last = converted[converted.length - 1];
|
|
67834
|
+
return last !== undefined && (last.role === "user" || last.role === "toolResult");
|
|
67835
|
+
}
|
|
67836
|
+
|
|
67837
|
+
class ThrownErrorRetryPaused extends Error {
|
|
67838
|
+
resume;
|
|
67839
|
+
constructor(resume) {
|
|
67840
|
+
super("atomic-workflows: thrown-error retry paused");
|
|
67841
|
+
this.resume = resume;
|
|
67842
|
+
this.name = "ThrownErrorRetryPaused";
|
|
67843
|
+
}
|
|
67844
|
+
}
|
|
67845
|
+
|
|
67918
67846
|
class StageSessionController {
|
|
67919
67847
|
opts;
|
|
67920
67848
|
meta;
|
|
@@ -67922,6 +67850,10 @@ class StageSessionController {
|
|
|
67922
67850
|
structuredOutputCapture;
|
|
67923
67851
|
session;
|
|
67924
67852
|
activeCreation;
|
|
67853
|
+
ownedCreationPromise;
|
|
67854
|
+
abortGeneration = 0;
|
|
67855
|
+
abortReason;
|
|
67856
|
+
abortReasonGeneration = 0;
|
|
67925
67857
|
sessionPromise;
|
|
67926
67858
|
reattachSessionFile;
|
|
67927
67859
|
lastPromptStartIndex;
|
|
@@ -67947,7 +67879,10 @@ class StageSessionController {
|
|
|
67947
67879
|
pendingFallbackWarnings = [];
|
|
67948
67880
|
modelCatalog;
|
|
67949
67881
|
sessionSettingsManager;
|
|
67882
|
+
thrownErrorRetryStates = new Set;
|
|
67883
|
+
creationPauseObservers = new Set;
|
|
67950
67884
|
replacement = new StageSessionReplacement;
|
|
67885
|
+
pendingCreationResumeMessage;
|
|
67951
67886
|
messageAdmission = new StageMessageAdmission;
|
|
67952
67887
|
deliveryActivity = new StageDeliveryActivity;
|
|
67953
67888
|
constructor(opts, meta2, effectiveStageOptions, structuredOutputCapture) {
|
|
@@ -68005,8 +67940,20 @@ class StageSessionController {
|
|
|
68005
67940
|
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
68006
67941
|
if (this.session !== undefined)
|
|
68007
67942
|
return this.session;
|
|
68008
|
-
if (!this.sessionPromise)
|
|
68009
|
-
|
|
67943
|
+
if (!this.sessionPromise) {
|
|
67944
|
+
const pending = this.createInitialSession(consumer);
|
|
67945
|
+
this.sessionPromise = pending;
|
|
67946
|
+
this.ownedCreationPromise = pending;
|
|
67947
|
+
const release = () => {
|
|
67948
|
+
if (this.ownedCreationPromise === pending)
|
|
67949
|
+
this.ownedCreationPromise = undefined;
|
|
67950
|
+
};
|
|
67951
|
+
pending.then(release, () => {
|
|
67952
|
+
release();
|
|
67953
|
+
if (this.sessionPromise === pending)
|
|
67954
|
+
this.sessionPromise = undefined;
|
|
67955
|
+
});
|
|
67956
|
+
}
|
|
68010
67957
|
return this.sessionPromise;
|
|
68011
67958
|
}
|
|
68012
67959
|
async ensureSessionFromFile(sessionFile, consumer = "prompt") {
|
|
@@ -68025,7 +67972,15 @@ class StageSessionController {
|
|
|
68025
67972
|
}
|
|
68026
67973
|
preparation?.beforePreparation?.();
|
|
68027
67974
|
const sessionFile = preparation?.sessionFile;
|
|
68028
|
-
const deliver = async (activity) =>
|
|
67975
|
+
const deliver = async (activity) => {
|
|
67976
|
+
const activeSession = sessionFile === undefined ? await this.ensureSession("prompt") : await this.ensureSessionFromFile(sessionFile, "prompt");
|
|
67977
|
+
const pausedDelivery2 = this.pauseControl.deferRunnerOwnedDelivery(() => sendStageUserMessage(activeSession, content, options, beforeDelivery, release, this.messageAdmission, activity));
|
|
67978
|
+
if (pausedDelivery2 !== undefined) {
|
|
67979
|
+
release();
|
|
67980
|
+
return pausedDelivery2;
|
|
67981
|
+
}
|
|
67982
|
+
return sendStageUserMessage(activeSession, content, options, beforeDelivery, release, this.messageAdmission, activity);
|
|
67983
|
+
};
|
|
68029
67984
|
if (this.session === undefined || sessionFile !== undefined)
|
|
68030
67985
|
return this.deliveryActivity.runWithLease(() => deliver());
|
|
68031
67986
|
return deliver(this.deliveryActivity);
|
|
@@ -68047,25 +68002,61 @@ class StageSessionController {
|
|
|
68047
68002
|
}
|
|
68048
68003
|
async promptWithFallback(text, sdkOptions, consumer = "prompt") {
|
|
68049
68004
|
if (!this.hasExplicitModelFallbackConfig) {
|
|
68050
|
-
|
|
68005
|
+
try {
|
|
68006
|
+
const activeSession = await this.ensureSession(consumer);
|
|
68007
|
+
const resumedText2 = this.pendingCreationResumeMessage;
|
|
68008
|
+
this.pendingCreationResumeMessage = undefined;
|
|
68009
|
+
await this.promptWithThrownErrorRetry(activeSession, resumedText2 ?? text, sdkOptions);
|
|
68010
|
+
} catch (error) {
|
|
68011
|
+
if (error instanceof StageSessionCreationCancelled)
|
|
68012
|
+
return;
|
|
68013
|
+
throw error;
|
|
68014
|
+
}
|
|
68051
68015
|
return;
|
|
68052
68016
|
}
|
|
68053
68017
|
const candidates = await this.modelCandidates();
|
|
68054
68018
|
if (candidates.length === 0) {
|
|
68055
|
-
|
|
68019
|
+
try {
|
|
68020
|
+
const activeSession = await this.ensureSession(consumer);
|
|
68021
|
+
const resumedText2 = this.pendingCreationResumeMessage;
|
|
68022
|
+
this.pendingCreationResumeMessage = undefined;
|
|
68023
|
+
await this.promptWithThrownErrorRetry(activeSession, resumedText2 ?? text, sdkOptions);
|
|
68024
|
+
} catch (error) {
|
|
68025
|
+
if (error instanceof StageSessionCreationCancelled)
|
|
68026
|
+
return;
|
|
68027
|
+
throw error;
|
|
68028
|
+
}
|
|
68056
68029
|
return;
|
|
68057
68030
|
}
|
|
68058
|
-
if (
|
|
68031
|
+
if (this.session === undefined && this.sessionPromise !== undefined) {
|
|
68032
|
+
try {
|
|
68033
|
+
await this.sessionPromise;
|
|
68034
|
+
} catch (error) {
|
|
68035
|
+
if (error instanceof StageSessionCreationCancelled)
|
|
68036
|
+
return;
|
|
68037
|
+
}
|
|
68038
|
+
}
|
|
68039
|
+
const resumedText = this.pendingCreationResumeMessage;
|
|
68040
|
+
this.pendingCreationResumeMessage = undefined;
|
|
68041
|
+
let promptText = resumedText ?? text;
|
|
68042
|
+
if (await this.tryResumeCurrentSession(promptText, sdkOptions, candidates))
|
|
68059
68043
|
return;
|
|
68060
68044
|
let index = this.activeCandidateIndex ?? 0;
|
|
68061
68045
|
while (index < candidates.length) {
|
|
68062
68046
|
const candidate = candidates[index];
|
|
68063
|
-
const activeSession = this.session && this.activeCandidateIndex === index ? this.session : await this.createSession(candidate, consumer);
|
|
68064
|
-
this.activeCandidateIndex = index;
|
|
68065
|
-
this.selectedModel = candidate.id;
|
|
68066
|
-
this.notifyModelFallbackMetaChange();
|
|
68067
68047
|
try {
|
|
68068
|
-
const
|
|
68048
|
+
const created = this.session && this.activeCandidateIndex === index ? this.session : await this.createSessionWithThrownErrorRetry(candidate, consumer);
|
|
68049
|
+
if (isSessionCreationPauseResult(created)) {
|
|
68050
|
+
if (created.resumeMessage === undefined)
|
|
68051
|
+
return;
|
|
68052
|
+
promptText = created.resumeMessage;
|
|
68053
|
+
continue;
|
|
68054
|
+
}
|
|
68055
|
+
const activeSession = created;
|
|
68056
|
+
this.activeCandidateIndex = index;
|
|
68057
|
+
this.selectedModel = candidate.id;
|
|
68058
|
+
this.notifyModelFallbackMetaChange();
|
|
68059
|
+
const { terminalScanStartIndex } = await this.promptWithThrownErrorRetry(activeSession, promptText, sdkOptions);
|
|
68069
68060
|
const terminalFailure = latestTerminalAssistantFailureSince(activeSession.messages, terminalScanStartIndex);
|
|
68070
68061
|
if (terminalFailure !== undefined) {
|
|
68071
68062
|
if (this.capturedStructuredOutputForAttempt()) {
|
|
@@ -68100,6 +68091,9 @@ class StageSessionController {
|
|
|
68100
68091
|
}
|
|
68101
68092
|
async disposeAll() {
|
|
68102
68093
|
this.disposed = true;
|
|
68094
|
+
const reason = new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
68095
|
+
this.markAbort(reason);
|
|
68096
|
+
this.pauseControl.reject(reason);
|
|
68103
68097
|
for (const unsubscribe of this.listenerUnsubscribes.values())
|
|
68104
68098
|
unsubscribe();
|
|
68105
68099
|
this.listenerUnsubscribes.clear();
|
|
@@ -68112,8 +68106,25 @@ class StageSessionController {
|
|
|
68112
68106
|
await this.replacement.dispose();
|
|
68113
68107
|
await disposeStageSession(this.session);
|
|
68114
68108
|
}
|
|
68109
|
+
async abort() {
|
|
68110
|
+
const reason = new DOMException("stage aborted", "AbortError");
|
|
68111
|
+
this.markAbort(reason);
|
|
68112
|
+
this.pauseControl.reject(reason);
|
|
68113
|
+
await this.session?.abort();
|
|
68114
|
+
}
|
|
68115
68115
|
requestPause() {
|
|
68116
|
-
|
|
68116
|
+
const pause = this.pauseControl.requestPause();
|
|
68117
|
+
const resume = this.pauseControl.currentResume();
|
|
68118
|
+
if (resume !== undefined) {
|
|
68119
|
+
this.pauseThrownErrorRetries(resume);
|
|
68120
|
+
for (const observer of this.creationPauseObservers) {
|
|
68121
|
+
if (observer.pauseResume !== undefined)
|
|
68122
|
+
continue;
|
|
68123
|
+
observer.pauseResume = resume;
|
|
68124
|
+
this.latchCreationResume(resume);
|
|
68125
|
+
}
|
|
68126
|
+
}
|
|
68127
|
+
return pause;
|
|
68117
68128
|
}
|
|
68118
68129
|
resume(message, beforeResolve, beforeRelease) {
|
|
68119
68130
|
return this.pauseControl.resume(message, beforeResolve, beforeRelease);
|
|
@@ -68134,21 +68145,224 @@ class StageSessionController {
|
|
|
68134
68145
|
const { signal } = this.opts;
|
|
68135
68146
|
if (!signal)
|
|
68136
68147
|
return;
|
|
68137
|
-
const
|
|
68148
|
+
const abortReason2 = () => {
|
|
68138
68149
|
const reason = signal.reason;
|
|
68139
68150
|
if (reason instanceof Error || reason instanceof DOMException || typeof reason === "string")
|
|
68140
68151
|
return reason;
|
|
68141
68152
|
return new DOMException("workflow killed", "AbortError");
|
|
68142
68153
|
};
|
|
68143
68154
|
const onAbort = () => {
|
|
68155
|
+
const reason = abortReason2();
|
|
68156
|
+
this.markAbort(reason);
|
|
68144
68157
|
this.session?.abort().catch(() => {});
|
|
68145
|
-
this.pauseControl.reject(
|
|
68158
|
+
this.pauseControl.reject(reason);
|
|
68146
68159
|
};
|
|
68147
68160
|
if (signal.aborted)
|
|
68148
68161
|
onAbort();
|
|
68149
68162
|
else
|
|
68150
68163
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
68151
68164
|
}
|
|
68165
|
+
markAbort(reason) {
|
|
68166
|
+
this.abortGeneration += 1;
|
|
68167
|
+
this.abortReason = reason;
|
|
68168
|
+
this.abortReasonGeneration = this.abortGeneration;
|
|
68169
|
+
this.abortThrownErrorRetries(reason);
|
|
68170
|
+
}
|
|
68171
|
+
pauseThrownErrorRetries(resume) {
|
|
68172
|
+
for (const state2 of this.thrownErrorRetryStates) {
|
|
68173
|
+
if (state2.pauseResume !== undefined)
|
|
68174
|
+
continue;
|
|
68175
|
+
state2.pauseResume = resume;
|
|
68176
|
+
state2.controller.abort(new ThrownErrorRetryPaused(resume));
|
|
68177
|
+
}
|
|
68178
|
+
}
|
|
68179
|
+
abortThrownErrorRetries(reason) {
|
|
68180
|
+
for (const state2 of this.thrownErrorRetryStates)
|
|
68181
|
+
state2.controller.abort(reason);
|
|
68182
|
+
this.thrownErrorRetryStates.clear();
|
|
68183
|
+
}
|
|
68184
|
+
retrySettings() {
|
|
68185
|
+
const managers = [
|
|
68186
|
+
this.sessionSettingsManager,
|
|
68187
|
+
this.session?.settingsManager,
|
|
68188
|
+
this.effectiveStageOptions?.settingsManager
|
|
68189
|
+
];
|
|
68190
|
+
for (const manager of managers) {
|
|
68191
|
+
if (manager === undefined || typeof manager.getRetrySettings !== "function")
|
|
68192
|
+
continue;
|
|
68193
|
+
return manager.getRetrySettings();
|
|
68194
|
+
}
|
|
68195
|
+
return;
|
|
68196
|
+
}
|
|
68197
|
+
restoreSessionMessages(session, snapshot, promptText, keepPrompt) {
|
|
68198
|
+
const snapshotMessages = new Set(snapshot);
|
|
68199
|
+
const admitted = session.messages.filter((message) => !snapshotMessages.has(message));
|
|
68200
|
+
const failedAssistantIndex = admitted.findLastIndex((message) => message.role === "assistant" && message.stopReason === "error");
|
|
68201
|
+
const promptUser = admitted.slice(0, failedAssistantIndex < 0 ? admitted.length : failedAssistantIndex).findLast((message) => message.role === "user" && stageUserMessageText(message) === promptText);
|
|
68202
|
+
const retainedMessages = admitted.filter((message) => {
|
|
68203
|
+
if (message === promptUser)
|
|
68204
|
+
return keepPrompt;
|
|
68205
|
+
if (message.role === "assistant")
|
|
68206
|
+
return message.stopReason !== "error";
|
|
68207
|
+
return ["user", "toolResult", "custom", "bashExecution", "branchSummary"].includes(message.role);
|
|
68208
|
+
});
|
|
68209
|
+
session.messages.splice(0, session.messages.length, ...snapshot, ...retainedMessages);
|
|
68210
|
+
return keepPrompt ? promptUser : undefined;
|
|
68211
|
+
}
|
|
68212
|
+
dropRetainedPrompt(session, retained) {
|
|
68213
|
+
if (retained === undefined)
|
|
68214
|
+
return;
|
|
68215
|
+
const index = session.messages.indexOf(retained);
|
|
68216
|
+
if (index >= 0)
|
|
68217
|
+
session.messages.splice(index, 1);
|
|
68218
|
+
}
|
|
68219
|
+
async sleepForThrownErrorRetry(delayMs, state2) {
|
|
68220
|
+
this.thrownErrorRetryStates.add(state2);
|
|
68221
|
+
const currentResume = this.pauseControl.currentResume();
|
|
68222
|
+
if (currentResume !== undefined) {
|
|
68223
|
+
state2.pauseResume = currentResume;
|
|
68224
|
+
state2.controller.abort(new ThrownErrorRetryPaused(currentResume));
|
|
68225
|
+
}
|
|
68226
|
+
try {
|
|
68227
|
+
await sleepOrAbort(delayMs, state2.controller.signal);
|
|
68228
|
+
} finally {
|
|
68229
|
+
this.thrownErrorRetryStates.delete(state2);
|
|
68230
|
+
}
|
|
68231
|
+
}
|
|
68232
|
+
async continueWithPauseResume(continuationSession) {
|
|
68233
|
+
const settlePause = async (resume) => {
|
|
68234
|
+
const resumed = await resume;
|
|
68235
|
+
await resumed.runnerOwnedDeliverySettlement;
|
|
68236
|
+
return { kind: "paused", ...resumed.message === undefined ? {} : { message: resumed.message } };
|
|
68237
|
+
};
|
|
68238
|
+
const pauseBeforeContinue = this.pauseControl.currentResume();
|
|
68239
|
+
if (pauseBeforeContinue !== undefined)
|
|
68240
|
+
return settlePause(pauseBeforeContinue);
|
|
68241
|
+
const state2 = { controller: new AbortController };
|
|
68242
|
+
this.thrownErrorRetryStates.add(state2);
|
|
68243
|
+
try {
|
|
68244
|
+
await continuationSession._runAgentContinue();
|
|
68245
|
+
} catch (error) {
|
|
68246
|
+
const resume = state2.pauseResume ?? this.pauseControl.currentResume();
|
|
68247
|
+
if (resume === undefined)
|
|
68248
|
+
throw error;
|
|
68249
|
+
return settlePause(resume);
|
|
68250
|
+
} finally {
|
|
68251
|
+
this.thrownErrorRetryStates.delete(state2);
|
|
68252
|
+
}
|
|
68253
|
+
const pauseAfterContinue = state2.pauseResume ?? this.pauseControl.currentResume();
|
|
68254
|
+
if (pauseAfterContinue !== undefined)
|
|
68255
|
+
return settlePause(pauseAfterContinue);
|
|
68256
|
+
return { kind: "continued" };
|
|
68257
|
+
}
|
|
68258
|
+
async promptWithThrownErrorRetry(activeSession, text, sdkOptions) {
|
|
68259
|
+
let retryAttempt = 0;
|
|
68260
|
+
let nextText = text;
|
|
68261
|
+
let retryAdmittedPrompt = false;
|
|
68262
|
+
let retainedPrompt;
|
|
68263
|
+
let terminalScanStartIndex;
|
|
68264
|
+
while (true) {
|
|
68265
|
+
const messagesBeforeAttempt = [...activeSession.messages];
|
|
68266
|
+
try {
|
|
68267
|
+
if (retryAdmittedPrompt) {
|
|
68268
|
+
const continuationSession = retryableAgentSession(activeSession);
|
|
68269
|
+
if (continuationSession !== undefined) {
|
|
68270
|
+
const outcome = await this.continueWithPauseResume(continuationSession);
|
|
68271
|
+
if (outcome.kind === "continued") {
|
|
68272
|
+
return {
|
|
68273
|
+
terminalScanStartIndex: terminalScanStartIndex ?? this.lastPromptStartIndex ?? messagesBeforeAttempt.length
|
|
68274
|
+
};
|
|
68275
|
+
}
|
|
68276
|
+
this.dropRetainedPrompt(activeSession, retainedPrompt);
|
|
68277
|
+
retainedPrompt = undefined;
|
|
68278
|
+
retryAdmittedPrompt = false;
|
|
68279
|
+
retryAttempt = 0;
|
|
68280
|
+
terminalScanStartIndex = undefined;
|
|
68281
|
+
if (outcome.message === undefined) {
|
|
68282
|
+
return { terminalScanStartIndex: activeSession.messages.length };
|
|
68283
|
+
}
|
|
68284
|
+
nextText = outcome.message;
|
|
68285
|
+
continue;
|
|
68286
|
+
}
|
|
68287
|
+
this.dropRetainedPrompt(activeSession, retainedPrompt);
|
|
68288
|
+
retainedPrompt = undefined;
|
|
68289
|
+
retryAdmittedPrompt = false;
|
|
68290
|
+
}
|
|
68291
|
+
const result = await this.promptWithPauseResume(activeSession, nextText, sdkOptions);
|
|
68292
|
+
return {
|
|
68293
|
+
terminalScanStartIndex: terminalScanStartIndex ?? result.terminalScanStartIndex
|
|
68294
|
+
};
|
|
68295
|
+
} catch (error) {
|
|
68296
|
+
const errorSettingsManager = retrySettingsManagerFromError(error);
|
|
68297
|
+
if (errorSettingsManager !== undefined)
|
|
68298
|
+
this.sessionSettingsManager = errorSettingsManager;
|
|
68299
|
+
const retryableFailure = isRetryableModelFailure(error);
|
|
68300
|
+
const sameCandidateRetryable = isRetryableSameModelFailure(error) && !isUnresolvedContextOverflowFailure(error);
|
|
68301
|
+
const decision = nextRetryDecision(this.retrySettings(), retryAttempt, sameCandidateRetryable);
|
|
68302
|
+
const continuationSession = retryableAgentSession(activeSession);
|
|
68303
|
+
const admittedMessages = activeSession.messages.length > messagesBeforeAttempt.length;
|
|
68304
|
+
const willRetry = decision !== undefined && !this.disposed && this.opts.signal?.aborted !== true && !this.capturedStructuredOutputForAttempt();
|
|
68305
|
+
const willContinue = continuationSession !== undefined && admittedMessages;
|
|
68306
|
+
if (retryableFailure && willRetry) {
|
|
68307
|
+
retainedPrompt = this.restoreSessionMessages(activeSession, messagesBeforeAttempt, nextText, willContinue) ?? retainedPrompt;
|
|
68308
|
+
}
|
|
68309
|
+
if (!willRetry)
|
|
68310
|
+
throw error;
|
|
68311
|
+
terminalScanStartIndex ??= this.lastPromptStartIndex ?? messagesBeforeAttempt.length;
|
|
68312
|
+
retryAttempt = decision.attempt;
|
|
68313
|
+
const state2 = { controller: new AbortController };
|
|
68314
|
+
let pauseResume;
|
|
68315
|
+
try {
|
|
68316
|
+
await this.sleepForThrownErrorRetry(decision.delayMs, state2);
|
|
68317
|
+
} catch (sleepError) {
|
|
68318
|
+
if (sleepError instanceof ThrownErrorRetryPaused)
|
|
68319
|
+
pauseResume = sleepError.resume;
|
|
68320
|
+
else {
|
|
68321
|
+
if (this.opts.signal?.aborted)
|
|
68322
|
+
throw this.workflowAbortReason();
|
|
68323
|
+
if (this.disposed)
|
|
68324
|
+
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
68325
|
+
throw sleepError;
|
|
68326
|
+
}
|
|
68327
|
+
}
|
|
68328
|
+
if (pauseResume !== undefined) {
|
|
68329
|
+
const resumed = await pauseResume;
|
|
68330
|
+
retryAttempt = 0;
|
|
68331
|
+
retryAdmittedPrompt = false;
|
|
68332
|
+
terminalScanStartIndex = undefined;
|
|
68333
|
+
this.dropRetainedPrompt(activeSession, retainedPrompt);
|
|
68334
|
+
retainedPrompt = undefined;
|
|
68335
|
+
if (resumed.message === undefined) {
|
|
68336
|
+
return { terminalScanStartIndex: activeSession.messages.length };
|
|
68337
|
+
}
|
|
68338
|
+
nextText = resumed.message;
|
|
68339
|
+
continue;
|
|
68340
|
+
}
|
|
68341
|
+
if (this.disposed)
|
|
68342
|
+
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
68343
|
+
if (this.opts.signal?.aborted)
|
|
68344
|
+
throw this.workflowAbortReason();
|
|
68345
|
+
retryAdmittedPrompt = willContinue && canContinueFromTranscript(activeSession);
|
|
68346
|
+
if (!retryAdmittedPrompt) {
|
|
68347
|
+
this.dropRetainedPrompt(activeSession, retainedPrompt);
|
|
68348
|
+
retainedPrompt = undefined;
|
|
68349
|
+
}
|
|
68350
|
+
}
|
|
68351
|
+
}
|
|
68352
|
+
}
|
|
68353
|
+
workflowAbortReason() {
|
|
68354
|
+
const reason = this.opts.signal?.reason;
|
|
68355
|
+
if (reason instanceof Error || reason instanceof DOMException || typeof reason === "string")
|
|
68356
|
+
return reason;
|
|
68357
|
+
return new DOMException("workflow killed", "AbortError");
|
|
68358
|
+
}
|
|
68359
|
+
staleCreationReason(startGeneration) {
|
|
68360
|
+
if (this.opts.signal?.aborted)
|
|
68361
|
+
return this.workflowAbortReason();
|
|
68362
|
+
if (this.abortReasonGeneration > startGeneration && this.abortReason !== undefined)
|
|
68363
|
+
return this.abortReason;
|
|
68364
|
+
return new DOMException("stage aborted", "AbortError");
|
|
68365
|
+
}
|
|
68152
68366
|
modelCandidates() {
|
|
68153
68367
|
if (!this.candidatesPromise) {
|
|
68154
68368
|
this.candidatesPromise = buildModelCandidatesFromCatalog({
|
|
@@ -68161,12 +68375,14 @@ class StageSessionController {
|
|
|
68161
68375
|
return this.candidatesPromise;
|
|
68162
68376
|
}
|
|
68163
68377
|
async createInitialSession(consumer) {
|
|
68164
|
-
if (!this.hasExplicitModelFallbackConfig)
|
|
68165
|
-
return this.
|
|
68378
|
+
if (!this.hasExplicitModelFallbackConfig) {
|
|
68379
|
+
return this.createSessionObservingPause(undefined, consumer).catch((error) => this.createInitialSessionWithRetry(undefined, consumer, { error }));
|
|
68380
|
+
}
|
|
68166
68381
|
const candidates = await this.modelCandidates();
|
|
68167
68382
|
const first = candidates[0];
|
|
68168
|
-
if (first === undefined)
|
|
68169
|
-
return this.
|
|
68383
|
+
if (first === undefined) {
|
|
68384
|
+
return this.createSessionObservingPause(undefined, consumer).catch((error) => this.createInitialSessionWithRetry(undefined, consumer, { error }));
|
|
68385
|
+
}
|
|
68170
68386
|
if (this.reattachSessionFile !== undefined) {
|
|
68171
68387
|
const resumed = await this.createSession(undefined, consumer, { restoreSavedModel: true });
|
|
68172
68388
|
const restoredId = workflowModelId(resumed.model);
|
|
@@ -68178,7 +68394,119 @@ class StageSessionController {
|
|
|
68178
68394
|
}
|
|
68179
68395
|
this.activeCandidateIndex = 0;
|
|
68180
68396
|
this.selectedModel = first.id;
|
|
68181
|
-
return this.
|
|
68397
|
+
return this.createSessionObservingPause(first, consumer).catch((error) => this.createInitialSessionCandidateWalk(candidates, consumer, 0, { error }));
|
|
68398
|
+
}
|
|
68399
|
+
async createInitialSessionCandidateWalk(candidates, consumer, startIndex, initialFailure) {
|
|
68400
|
+
let index = startIndex;
|
|
68401
|
+
let pendingFailure = initialFailure;
|
|
68402
|
+
let lastError = initialFailure?.error;
|
|
68403
|
+
while (index < candidates.length) {
|
|
68404
|
+
const candidate = candidates[index];
|
|
68405
|
+
this.activeCandidateIndex = index;
|
|
68406
|
+
this.selectedModel = candidate.id;
|
|
68407
|
+
try {
|
|
68408
|
+
const created = await this.createSessionWithThrownErrorRetry(candidate, consumer, pendingFailure);
|
|
68409
|
+
pendingFailure = undefined;
|
|
68410
|
+
if (!isSessionCreationPauseResult(created)) {
|
|
68411
|
+
this.notifyModelFallbackMetaChange();
|
|
68412
|
+
return created;
|
|
68413
|
+
}
|
|
68414
|
+
if (created.resumeMessage === undefined) {
|
|
68415
|
+
this.pendingCreationResumeMessage = undefined;
|
|
68416
|
+
this.sessionPromise = undefined;
|
|
68417
|
+
throw new StageSessionCreationCancelled;
|
|
68418
|
+
}
|
|
68419
|
+
this.pendingCreationResumeMessage = created.resumeMessage;
|
|
68420
|
+
} catch (error) {
|
|
68421
|
+
if (error instanceof StageSessionCreationCancelled)
|
|
68422
|
+
throw error;
|
|
68423
|
+
pendingFailure = undefined;
|
|
68424
|
+
lastError = error;
|
|
68425
|
+
if (await this.handleCandidateFailure(error, candidate, candidates, index) !== "retry")
|
|
68426
|
+
throw error;
|
|
68427
|
+
index += 1;
|
|
68428
|
+
}
|
|
68429
|
+
}
|
|
68430
|
+
throw lastError ?? new Error(`atomic-workflows: stage "${this.opts.stageName}" has no usable model candidate`);
|
|
68431
|
+
}
|
|
68432
|
+
async createInitialSessionWithRetry(candidate, consumer, initialFailure) {
|
|
68433
|
+
let pendingFailure = initialFailure;
|
|
68434
|
+
while (true) {
|
|
68435
|
+
const created = await this.createSessionWithThrownErrorRetry(candidate, consumer, pendingFailure);
|
|
68436
|
+
pendingFailure = undefined;
|
|
68437
|
+
if (!isSessionCreationPauseResult(created))
|
|
68438
|
+
return created;
|
|
68439
|
+
if (created.resumeMessage === undefined) {
|
|
68440
|
+
this.pendingCreationResumeMessage = undefined;
|
|
68441
|
+
this.sessionPromise = undefined;
|
|
68442
|
+
throw new StageSessionCreationCancelled;
|
|
68443
|
+
}
|
|
68444
|
+
this.pendingCreationResumeMessage = created.resumeMessage;
|
|
68445
|
+
}
|
|
68446
|
+
}
|
|
68447
|
+
latchCreationResume(resume) {
|
|
68448
|
+
resume.then(async (resolved) => {
|
|
68449
|
+
await resolved.runnerOwnedDeliverySettlement;
|
|
68450
|
+
if (resolved.message !== undefined)
|
|
68451
|
+
this.pendingCreationResumeMessage = resolved.message;
|
|
68452
|
+
}).catch(() => {});
|
|
68453
|
+
}
|
|
68454
|
+
createSessionObservingPause(candidate, consumer) {
|
|
68455
|
+
const activePause = this.pauseControl.currentResume();
|
|
68456
|
+
const observer = { pauseResume: activePause };
|
|
68457
|
+
if (activePause !== undefined)
|
|
68458
|
+
this.latchCreationResume(activePause);
|
|
68459
|
+
this.creationPauseObservers.add(observer);
|
|
68460
|
+
const creation = this.createSession(candidate, consumer);
|
|
68461
|
+
const settle = () => {
|
|
68462
|
+
this.creationPauseObservers.delete(observer);
|
|
68463
|
+
};
|
|
68464
|
+
creation.then(settle, settle);
|
|
68465
|
+
return creation;
|
|
68466
|
+
}
|
|
68467
|
+
async createSessionWithThrownErrorRetry(candidate, consumer, initialFailure) {
|
|
68468
|
+
let retryAttempt = 0;
|
|
68469
|
+
let pendingFailure = initialFailure;
|
|
68470
|
+
while (true) {
|
|
68471
|
+
try {
|
|
68472
|
+
if (pendingFailure !== undefined) {
|
|
68473
|
+
const failure3 = pendingFailure;
|
|
68474
|
+
pendingFailure = undefined;
|
|
68475
|
+
throw failure3.error;
|
|
68476
|
+
}
|
|
68477
|
+
return await this.createSessionObservingPause(candidate, consumer);
|
|
68478
|
+
} catch (error) {
|
|
68479
|
+
const errorSettingsManager = retrySettingsManagerFromError(error);
|
|
68480
|
+
if (errorSettingsManager !== undefined)
|
|
68481
|
+
this.sessionSettingsManager = errorSettingsManager;
|
|
68482
|
+
const decision = nextRetryDecision(this.retrySettings(), retryAttempt, isRetryableSameModelFailure(error));
|
|
68483
|
+
if (decision === undefined || this.disposed || this.opts.signal?.aborted === true || this.capturedStructuredOutputForAttempt()) {
|
|
68484
|
+
throw error;
|
|
68485
|
+
}
|
|
68486
|
+
retryAttempt = decision.attempt;
|
|
68487
|
+
const state2 = { controller: new AbortController };
|
|
68488
|
+
try {
|
|
68489
|
+
await this.sleepForThrownErrorRetry(decision.delayMs, state2);
|
|
68490
|
+
} catch (sleepError) {
|
|
68491
|
+
if (sleepError instanceof ThrownErrorRetryPaused) {
|
|
68492
|
+
const resumed = await sleepError.resume;
|
|
68493
|
+
return {
|
|
68494
|
+
kind: "paused",
|
|
68495
|
+
...resumed.message === undefined ? {} : { resumeMessage: resumed.message }
|
|
68496
|
+
};
|
|
68497
|
+
}
|
|
68498
|
+
if (this.opts.signal?.aborted)
|
|
68499
|
+
throw this.workflowAbortReason();
|
|
68500
|
+
if (this.disposed)
|
|
68501
|
+
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
68502
|
+
throw sleepError;
|
|
68503
|
+
}
|
|
68504
|
+
if (this.disposed)
|
|
68505
|
+
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
68506
|
+
if (this.opts.signal?.aborted)
|
|
68507
|
+
throw this.workflowAbortReason();
|
|
68508
|
+
}
|
|
68509
|
+
}
|
|
68182
68510
|
}
|
|
68183
68511
|
createSession(candidate, consumer, resumeOptions) {
|
|
68184
68512
|
const creation = this.createSessionAttempt(candidate, consumer, resumeOptions);
|
|
@@ -68190,6 +68518,7 @@ class StageSessionController {
|
|
|
68190
68518
|
return creation;
|
|
68191
68519
|
}
|
|
68192
68520
|
async createSessionAttempt(candidate, consumer, resumeOptions) {
|
|
68521
|
+
const startGeneration = this.abortGeneration;
|
|
68193
68522
|
this.applyCandidateThinking(candidate);
|
|
68194
68523
|
const stageOptions = buildStageSessionOptions({
|
|
68195
68524
|
effectiveStageOptions: this.effectiveStageOptions,
|
|
@@ -68198,11 +68527,24 @@ class StageSessionController {
|
|
|
68198
68527
|
reattachSessionFile: this.reattachSessionFile,
|
|
68199
68528
|
sharedModelRuntime: this.sharedModelRuntime
|
|
68200
68529
|
});
|
|
68201
|
-
|
|
68202
|
-
|
|
68203
|
-
stageOptions,
|
|
68204
|
-
|
|
68205
|
-
|
|
68530
|
+
let created;
|
|
68531
|
+
try {
|
|
68532
|
+
created = this.opts.adapters.agentSession ? await this.opts.adapters.agentSession.create(stripWorkflowOnlyOptions(stageOptions, this.opts.defaultSessionDir, this.meta), {
|
|
68533
|
+
...this.meta,
|
|
68534
|
+
stageOptions,
|
|
68535
|
+
...this.sharedOrchestrationContext !== undefined ? { orchestrationContext: this.sharedOrchestrationContext } : {}
|
|
68536
|
+
}) : missingAdapter(consumer);
|
|
68537
|
+
} catch (error) {
|
|
68538
|
+
if (this.disposed || this.opts.signal?.aborted === true || this.abortGeneration !== startGeneration)
|
|
68539
|
+
throw this.disposed ? new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`) : this.staleCreationReason(startGeneration);
|
|
68540
|
+
throw error;
|
|
68541
|
+
}
|
|
68542
|
+
if (this.disposed || this.opts.signal?.aborted === true || this.abortGeneration !== startGeneration) {
|
|
68543
|
+
await disposeStageSession(normalizeSessionCreateResult(created).session).catch(() => {});
|
|
68544
|
+
if (this.disposed)
|
|
68545
|
+
throw new Error(`atomic-workflows: stage "${this.opts.stageName}" session has been disposed`);
|
|
68546
|
+
throw this.staleCreationReason(startGeneration);
|
|
68547
|
+
}
|
|
68206
68548
|
return attachCreatedStageSession(created, this.disposed, this.opts.stageName, (result) => this.attachSession(result));
|
|
68207
68549
|
}
|
|
68208
68550
|
attachSession(created) {
|
|
@@ -68242,11 +68584,13 @@ class StageSessionController {
|
|
|
68242
68584
|
return result.session;
|
|
68243
68585
|
}
|
|
68244
68586
|
async disposeCurrentSession() {
|
|
68587
|
+
this.abortThrownErrorRetries(new Error(`atomic-workflows: stage "${this.opts.stageName}" session was replaced`));
|
|
68245
68588
|
const current = this.session;
|
|
68246
68589
|
this.messageAdmission.reset();
|
|
68247
68590
|
this.replacement.retire(current);
|
|
68248
68591
|
this.session = undefined;
|
|
68249
|
-
this.sessionPromise
|
|
68592
|
+
if (this.sessionPromise !== this.ownedCreationPromise)
|
|
68593
|
+
this.sessionPromise = undefined;
|
|
68250
68594
|
this.sessionSettingsManager = undefined;
|
|
68251
68595
|
this.resumeCurrentSession = false;
|
|
68252
68596
|
for (const unsubscribe of this.listenerUnsubscribes.values())
|
|
@@ -68310,7 +68654,7 @@ class StageSessionController {
|
|
|
68310
68654
|
const resumedLabel = this.selectedModel ?? workflowModelId(resumedSession.model) ?? candidates[0].id;
|
|
68311
68655
|
this.notifyModelFallbackMetaChange();
|
|
68312
68656
|
try {
|
|
68313
|
-
const { terminalScanStartIndex } = await this.
|
|
68657
|
+
const { terminalScanStartIndex } = await this.promptWithThrownErrorRetry(resumedSession, text, sdkOptions);
|
|
68314
68658
|
const terminalFailure = latestTerminalAssistantFailureSince(resumedSession.messages, terminalScanStartIndex);
|
|
68315
68659
|
if (terminalFailure === undefined || this.capturedStructuredOutputForAttempt()) {
|
|
68316
68660
|
this.modelAttempts.push({ model: resumedLabel, success: true });
|
|
@@ -68765,7 +69109,7 @@ function createStageContext2(opts) {
|
|
|
68765
69109
|
controller.currentSession?.abortCompaction();
|
|
68766
69110
|
},
|
|
68767
69111
|
async abort() {
|
|
68768
|
-
await controller.
|
|
69112
|
+
await controller.abort();
|
|
68769
69113
|
},
|
|
68770
69114
|
async __dispose() {
|
|
68771
69115
|
await controller.disposeAll();
|
|
@@ -69314,6 +69658,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
69314
69658
|
const rootBackend = opts.durableRootBackend ?? backendView;
|
|
69315
69659
|
const durableBackend = opts.durableScope !== undefined ? new ScopedDurableBackend(backendView, opts.durableScope) : backendView;
|
|
69316
69660
|
const inheritedElapsedMs = opts.parentRun === undefined ? inheritedRunElapsedMs({ backend: durableBackend, runId, continuationSource: opts.continuation?.source }) : undefined;
|
|
69661
|
+
const continuationOrigin = opts.continuation !== undefined ? opts.continuation.source.origin : opts.origin;
|
|
69317
69662
|
const runSnapshot = {
|
|
69318
69663
|
id: runId,
|
|
69319
69664
|
name: def.name,
|
|
@@ -69331,6 +69676,8 @@ async function run(def, inputs, opts = {}) {
|
|
|
69331
69676
|
resumedFromRunId: opts.continuation.source.id,
|
|
69332
69677
|
resumeFromStageId: opts.continuation.resumeFromStageId
|
|
69333
69678
|
} : {},
|
|
69679
|
+
...continuationOrigin !== undefined ? { origin: continuationOrigin } : {},
|
|
69680
|
+
...opts.resumeActor !== undefined ? { resumeActor: opts.resumeActor, resumeSource: "run_control" } : {},
|
|
69334
69681
|
...inheritedElapsedMs !== undefined ? { accumulatedDurationMs: inheritedElapsedMs } : {}
|
|
69335
69682
|
};
|
|
69336
69683
|
const classifiedFailures = new Map;
|
|
@@ -69361,6 +69708,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
69361
69708
|
...runSnapshot.parentStageId !== undefined ? { parentStageId: runSnapshot.parentStageId } : {},
|
|
69362
69709
|
...runSnapshot.rootRunId !== undefined ? { rootRunId: runSnapshot.rootRunId } : {},
|
|
69363
69710
|
...runSnapshot.resumedFromRunId !== undefined ? { resumedFromRunId: runSnapshot.resumedFromRunId } : {},
|
|
69711
|
+
...runSnapshot.origin !== undefined ? { origin: runSnapshot.origin } : {},
|
|
69364
69712
|
...runSnapshot.resumeFromStageId !== undefined ? { resumeFromStageId: runSnapshot.resumeFromStageId } : {},
|
|
69365
69713
|
...runSnapshot.accumulatedDurationMs !== undefined ? { accumulatedDurationMs: runSnapshot.accumulatedDurationMs } : {},
|
|
69366
69714
|
ts: runSnapshot.startedAt
|
|
@@ -69664,7 +70012,7 @@ async function run(def, inputs, opts = {}) {
|
|
|
69664
70012
|
isChildRun: opts.parentRun !== undefined,
|
|
69665
70013
|
registration: durableRootRegistration === undefined ? undefined : {
|
|
69666
70014
|
...durableRootRegistration,
|
|
69667
|
-
...workflowInvocationMetadata(inputRuntimeDefaults, workflowInvocationCwd, gitWorktreeSetupCache)
|
|
70015
|
+
...workflowInvocationMetadata(inputRuntimeDefaults, workflowInvocationCwd, gitWorktreeSetupCache, runSnapshot.origin)
|
|
69668
70016
|
}
|
|
69669
70017
|
});
|
|
69670
70018
|
if (opts.deferWorkflowStart === true)
|
|
@@ -69989,21 +70337,21 @@ function validateConfig2(config) {
|
|
|
69989
70337
|
return "config must be an object";
|
|
69990
70338
|
}
|
|
69991
70339
|
const c = config;
|
|
69992
|
-
for (const
|
|
69993
|
-
const val = c[
|
|
70340
|
+
for (const field2 of ["projectWorkflows", "globalWorkflows"]) {
|
|
70341
|
+
const val = c[field2];
|
|
69994
70342
|
if (val !== undefined) {
|
|
69995
70343
|
if (Array.isArray(val)) {
|
|
69996
70344
|
for (const entry of val) {
|
|
69997
70345
|
if (typeof entry !== "string")
|
|
69998
|
-
return `config.${
|
|
70346
|
+
return `config.${field2} entries must be strings`;
|
|
69999
70347
|
}
|
|
70000
70348
|
} else if (typeof val === "object" && val !== null) {
|
|
70001
70349
|
for (const [key2, entry] of Object.entries(val)) {
|
|
70002
70350
|
if (typeof entry !== "string")
|
|
70003
|
-
return `config.${
|
|
70351
|
+
return `config.${field2}["${key2}"] must be a string path`;
|
|
70004
70352
|
}
|
|
70005
70353
|
} else {
|
|
70006
|
-
return `config.${
|
|
70354
|
+
return `config.${field2} must be a string array or a Record<string, string> map`;
|
|
70007
70355
|
}
|
|
70008
70356
|
}
|
|
70009
70357
|
}
|
|
@@ -70261,6 +70609,7 @@ async function dispatch(args, opts) {
|
|
|
70261
70609
|
executionMode: policy.mode,
|
|
70262
70610
|
cwd: opts.cwd,
|
|
70263
70611
|
defaultSessionDir: opts.defaultSessionDir,
|
|
70612
|
+
...opts.origin === undefined ? {} : { origin: opts.origin },
|
|
70264
70613
|
runId
|
|
70265
70614
|
});
|
|
70266
70615
|
} catch (error) {
|
|
@@ -70606,7 +70955,10 @@ function createDurableResumeRuntime(deps) {
|
|
|
70606
70955
|
await backend.hydrateWorkflow(resolved.workflowId);
|
|
70607
70956
|
const adapterDeps = {
|
|
70608
70957
|
registry: deps.registry,
|
|
70609
|
-
baseRunOpts:
|
|
70958
|
+
baseRunOpts: {
|
|
70959
|
+
...deps.baseRunOpts(options?.policy),
|
|
70960
|
+
...options?.actor === undefined ? {} : { resumeActor: options.actor }
|
|
70961
|
+
},
|
|
70610
70962
|
durableBackend: backend,
|
|
70611
70963
|
resolveDefinition: async (name, cwd) => (await discoverWorkflows({ cwd: cwd ?? deps.runtimeCwd })).registry.get(name),
|
|
70612
70964
|
...deps.jobs !== undefined ? { jobs: deps.jobs } : {}
|
|
@@ -70791,6 +71143,7 @@ function createExtensionRuntime(opts = {}) {
|
|
|
70791
71143
|
const launchContinuation = () => launchDetachedUntilStartup(def, sourceInputs, {
|
|
70792
71144
|
...runOptions(options?.policy),
|
|
70793
71145
|
continuation: { source, resumeFromStageId: resolvedStage.stageId },
|
|
71146
|
+
...options?.actor === undefined ? {} : { resumeActor: options.actor },
|
|
70794
71147
|
...jobs !== undefined ? { jobs } : {}
|
|
70795
71148
|
});
|
|
70796
71149
|
if (isActiveBlockedResumable) {
|
|
@@ -70907,6 +71260,7 @@ function createExtensionRuntime(opts = {}) {
|
|
|
70907
71260
|
config,
|
|
70908
71261
|
models,
|
|
70909
71262
|
policy: options?.policy,
|
|
71263
|
+
...options?.origin === undefined ? {} : { origin: options.origin },
|
|
70910
71264
|
cwd: runtimeCwd,
|
|
70911
71265
|
...defaultSessionDir !== undefined ? { defaultSessionDir } : {}
|
|
70912
71266
|
});
|
|
@@ -71567,6 +71921,12 @@ function renderRunSummary(payload) {
|
|
|
71567
71921
|
|
|
71568
71922
|
// dist/builtin/workflows/src/extension/atomic-stage-session.ts
|
|
71569
71923
|
import { basename as basename5 } from "node:path";
|
|
71924
|
+
var WORKFLOW_STAGE_SUBAGENT_POLICY = {
|
|
71925
|
+
managementActions: "full",
|
|
71926
|
+
fanoutAuthorized: false,
|
|
71927
|
+
inheritProjectContext: true,
|
|
71928
|
+
inheritSkills: true
|
|
71929
|
+
};
|
|
71570
71930
|
function resolveSessionCwd(options) {
|
|
71571
71931
|
return options?.cwd ?? options?.sessionManager?.getCwd() ?? process.cwd();
|
|
71572
71932
|
}
|
|
@@ -71579,6 +71939,7 @@ async function prepareAtomicStageSessionOptions(options, sdk, prepareOptions = {
|
|
|
71579
71939
|
const hasAgentDirOverride = atomicOptions?.agentDir !== undefined;
|
|
71580
71940
|
const agentDir = atomicOptions?.agentDir ?? sdk.getAgentDir();
|
|
71581
71941
|
const settingsManager = atomicOptions?.settingsManager ?? sdk.SettingsManager.create(cwd, agentDir, inheritanceSnapshot?.projectTrusted === undefined ? undefined : { projectTrusted: inheritanceSnapshot.projectTrusted });
|
|
71942
|
+
prepareOptions.onSettingsManager?.(settingsManager);
|
|
71582
71943
|
const inheritedBuiltinPackagePaths = inheritanceSnapshot?.builtinPackagePaths;
|
|
71583
71944
|
const builtinPackagePaths = inheritedBuiltinPackagePaths === undefined ? sdk.getBuiltinPackagePaths?.() ?? [] : [...inheritedBuiltinPackagePaths];
|
|
71584
71945
|
const resourceLoader = new sdk.DefaultResourceLoader({
|
|
@@ -71594,7 +71955,8 @@ async function prepareAtomicStageSessionOptions(options, sdk, prepareOptions = {
|
|
|
71594
71955
|
cwd,
|
|
71595
71956
|
...hasAgentDirOverride ? { agentDir } : {},
|
|
71596
71957
|
settingsManager,
|
|
71597
|
-
resourceLoader
|
|
71958
|
+
resourceLoader,
|
|
71959
|
+
subagentPolicy: WORKFLOW_STAGE_SUBAGENT_POLICY
|
|
71598
71960
|
};
|
|
71599
71961
|
}
|
|
71600
71962
|
function clonePackageSource(source) {
|
|
@@ -71623,54 +71985,67 @@ function stageBuiltinPackagePaths(paths) {
|
|
|
71623
71985
|
return basename5(packageSourcePath(cloned)) === "workflows" ? disablePackageExtensions(cloned) : cloned;
|
|
71624
71986
|
});
|
|
71625
71987
|
}
|
|
71626
|
-
var SUBAGENT_CHILD_EXTENSION_ENV_KEYS = [
|
|
71627
|
-
"ATOMIC_SUBAGENT_CHILD",
|
|
71628
|
-
"ATOMIC_SUBAGENT_FANOUT_CHILD",
|
|
71629
|
-
"PI_SUBAGENT_CHILD",
|
|
71630
|
-
"PI_SUBAGENT_FANOUT_CHILD"
|
|
71631
|
-
];
|
|
71632
71988
|
var workflowStageResourceReloadQueue = Promise.resolve();
|
|
71633
71989
|
async function reloadWorkflowStageResources(resourceLoader) {
|
|
71634
|
-
const queuedReload = workflowStageResourceReloadQueue.then(() =>
|
|
71990
|
+
const queuedReload = workflowStageResourceReloadQueue.then(() => resourceLoader.reload());
|
|
71635
71991
|
workflowStageResourceReloadQueue = queuedReload.catch(() => {
|
|
71636
71992
|
return;
|
|
71637
71993
|
});
|
|
71638
71994
|
return queuedReload;
|
|
71639
71995
|
}
|
|
71640
|
-
async function reloadWorkflowStageResourcesWithEnvIsolation(resourceLoader) {
|
|
71641
|
-
const previousValues = new Map;
|
|
71642
|
-
for (const key2 of SUBAGENT_CHILD_EXTENSION_ENV_KEYS) {
|
|
71643
|
-
previousValues.set(key2, process.env[key2]);
|
|
71644
|
-
delete process.env[key2];
|
|
71645
|
-
}
|
|
71646
|
-
try {
|
|
71647
|
-
await resourceLoader.reload();
|
|
71648
|
-
} finally {
|
|
71649
|
-
for (const key2 of SUBAGENT_CHILD_EXTENSION_ENV_KEYS) {
|
|
71650
|
-
const previousValue = previousValues.get(key2);
|
|
71651
|
-
if (previousValue === undefined)
|
|
71652
|
-
delete process.env[key2];
|
|
71653
|
-
else
|
|
71654
|
-
process.env[key2] = previousValue;
|
|
71655
|
-
}
|
|
71656
|
-
}
|
|
71657
|
-
}
|
|
71658
71996
|
|
|
71659
71997
|
// dist/builtin/workflows/src/extension/wiring.ts
|
|
71660
71998
|
var LATE_STAGE_MESSAGE_EVENT2 = "atomic:workflow-stage-late-message";
|
|
71661
71999
|
function isTestContext() {
|
|
71662
72000
|
return process.env.NODE_TEST_CONTEXT !== undefined || false;
|
|
71663
72001
|
}
|
|
72002
|
+
function attachSettingsManager(error, settingsManager) {
|
|
72003
|
+
if (error !== null && (typeof error === "object" || typeof error === "function")) {
|
|
72004
|
+
try {
|
|
72005
|
+
if (Object.isExtensible(error)) {
|
|
72006
|
+
Object.defineProperty(error, "settingsManager", {
|
|
72007
|
+
configurable: true,
|
|
72008
|
+
enumerable: false,
|
|
72009
|
+
value: settingsManager,
|
|
72010
|
+
writable: false
|
|
72011
|
+
});
|
|
72012
|
+
return error;
|
|
72013
|
+
}
|
|
72014
|
+
} catch {}
|
|
72015
|
+
}
|
|
72016
|
+
const wrapped = new Error(error instanceof Error ? error.message : String(error), { cause: error });
|
|
72017
|
+
Object.defineProperty(wrapped, "settingsManager", {
|
|
72018
|
+
configurable: true,
|
|
72019
|
+
enumerable: false,
|
|
72020
|
+
value: settingsManager,
|
|
72021
|
+
writable: false
|
|
72022
|
+
});
|
|
72023
|
+
return wrapped;
|
|
72024
|
+
}
|
|
71664
72025
|
async function createPiSdkAgentSession(options, prepareOptions) {
|
|
71665
72026
|
const sdk = await import("@bastani/atomic");
|
|
71666
|
-
|
|
71667
|
-
|
|
71668
|
-
|
|
71669
|
-
|
|
71670
|
-
|
|
71671
|
-
|
|
71672
|
-
|
|
71673
|
-
|
|
72027
|
+
let settingsManager;
|
|
72028
|
+
try {
|
|
72029
|
+
const sessionOptions = await prepareAtomicStageSessionOptions(options, sdk, {
|
|
72030
|
+
...prepareOptions,
|
|
72031
|
+
onSettingsManager: (manager) => {
|
|
72032
|
+
settingsManager = manager;
|
|
72033
|
+
prepareOptions?.onSettingsManager?.(manager);
|
|
72034
|
+
}
|
|
72035
|
+
});
|
|
72036
|
+
settingsManager = sessionOptions?.settingsManager ?? settingsManager;
|
|
72037
|
+
const result = await sdk.createAgentSession(sessionOptions);
|
|
72038
|
+
const resultSettingsManager = result.session.settingsManager;
|
|
72039
|
+
settingsManager = sessionOptions?.settingsManager ?? resultSettingsManager ?? settingsManager;
|
|
72040
|
+
return {
|
|
72041
|
+
session: result.session,
|
|
72042
|
+
...settingsManager?.getCodexFastModeSettings !== undefined ? { settingsManager } : {}
|
|
72043
|
+
};
|
|
72044
|
+
} catch (error) {
|
|
72045
|
+
if (settingsManager !== undefined)
|
|
72046
|
+
throw attachSettingsManager(error, settingsManager);
|
|
72047
|
+
throw error;
|
|
72048
|
+
}
|
|
71674
72049
|
}
|
|
71675
72050
|
async function createTestAgentSession(_options) {
|
|
71676
72051
|
let lastAssistantText;
|
|
@@ -71965,23 +72340,23 @@ function renderPretty(name, inputs, theme, width) {
|
|
|
71965
72340
|
width: boxWidth
|
|
71966
72341
|
});
|
|
71967
72342
|
}
|
|
71968
|
-
function renderInputRows(
|
|
71969
|
-
const tagLabel =
|
|
71970
|
-
const heading = theme ? ` ${paint(
|
|
72343
|
+
function renderInputRows(field2, theme) {
|
|
72344
|
+
const tagLabel = field2.required ? "required" : "optional";
|
|
72345
|
+
const heading = theme ? ` ${paint(field2.name, theme.text, { bold: true })} ${paint(field2.type, theme.dim)} · ${paint(tagLabel, field2.required ? theme.warning : theme.dim)} ` : ` ${field2.name} ${field2.type} · ${tagLabel} `;
|
|
71971
72346
|
const lines = [heading];
|
|
71972
|
-
if (
|
|
71973
|
-
lines.push(` ${theme ? paint(
|
|
72347
|
+
if (field2.description) {
|
|
72348
|
+
lines.push(` ${theme ? paint(field2.description, theme.textMuted) : field2.description} `);
|
|
71974
72349
|
}
|
|
71975
|
-
if (
|
|
71976
|
-
const values =
|
|
72350
|
+
if (field2.choices && field2.choices.length > 0) {
|
|
72351
|
+
const values = field2.choices.join(" · ");
|
|
71977
72352
|
lines.push(` ${theme ? paint("values: ", theme.dim) + paint(values, theme.text) : `values: ${values}`} `);
|
|
71978
72353
|
}
|
|
71979
|
-
if (
|
|
71980
|
-
const value2 = JSON.stringify(
|
|
72354
|
+
if (field2.default !== undefined) {
|
|
72355
|
+
const value2 = JSON.stringify(field2.default);
|
|
71981
72356
|
lines.push(` ${theme ? paint("default: ", theme.dim) + paint(value2, theme.text) : `default: ${value2}`} `);
|
|
71982
72357
|
}
|
|
71983
|
-
if (
|
|
71984
|
-
lines.push(` ${theme ? paint("placeholder: ", theme.dim) + paint(
|
|
72358
|
+
if (field2.placeholder) {
|
|
72359
|
+
lines.push(` ${theme ? paint("placeholder: ", theme.dim) + paint(field2.placeholder, theme.textMuted) : `placeholder: ${field2.placeholder}`} `);
|
|
71985
72360
|
}
|
|
71986
72361
|
return lines;
|
|
71987
72362
|
}
|
|
@@ -72006,14 +72381,14 @@ function supportedType(type) {
|
|
|
72006
72381
|
return "string";
|
|
72007
72382
|
}
|
|
72008
72383
|
}
|
|
72009
|
-
function initialValue(
|
|
72010
|
-
if (prefilled[
|
|
72011
|
-
return String(prefilled[
|
|
72012
|
-
if (
|
|
72013
|
-
return String(
|
|
72014
|
-
if (
|
|
72015
|
-
return
|
|
72016
|
-
if (
|
|
72384
|
+
function initialValue(field2, prefilled) {
|
|
72385
|
+
if (prefilled[field2.name] !== undefined)
|
|
72386
|
+
return String(prefilled[field2.name]);
|
|
72387
|
+
if (field2.default !== undefined)
|
|
72388
|
+
return String(field2.default);
|
|
72389
|
+
if (field2.type === "select" && field2.choices && field2.choices.length > 0)
|
|
72390
|
+
return field2.choices[0];
|
|
72391
|
+
if (field2.type === "boolean")
|
|
72017
72392
|
return "false";
|
|
72018
72393
|
return "";
|
|
72019
72394
|
}
|
|
@@ -72022,14 +72397,14 @@ async function openHostInputsForm(ui, options) {
|
|
|
72022
72397
|
if (typeof open !== "function")
|
|
72023
72398
|
return { kind: "unsupported" };
|
|
72024
72399
|
const prefilled = options.prefilled ?? {};
|
|
72025
|
-
const fields = options.fields.map((
|
|
72026
|
-
name:
|
|
72027
|
-
type: supportedType(
|
|
72028
|
-
initialValue: initialValue(
|
|
72029
|
-
...
|
|
72030
|
-
...
|
|
72031
|
-
...
|
|
72032
|
-
...
|
|
72400
|
+
const fields = options.fields.map((field2) => ({
|
|
72401
|
+
name: field2.name,
|
|
72402
|
+
type: supportedType(field2.type),
|
|
72403
|
+
initialValue: initialValue(field2, prefilled),
|
|
72404
|
+
...field2.description !== undefined ? { description: field2.description } : {},
|
|
72405
|
+
...field2.required !== undefined ? { required: field2.required } : {},
|
|
72406
|
+
...field2.choices !== undefined ? { choices: [...field2.choices] } : {},
|
|
72407
|
+
...field2.placeholder !== undefined ? { placeholder: field2.placeholder } : {}
|
|
72033
72408
|
}));
|
|
72034
72409
|
try {
|
|
72035
72410
|
const raw = await open.call(ui, {
|
|
@@ -72140,6 +72515,9 @@ function openInputsPicker(ui, opts) {
|
|
|
72140
72515
|
// dist/builtin/workflows/src/tui/session-picker.ts
|
|
72141
72516
|
import { keyText as keyText2 } from "@bastani/atomic";
|
|
72142
72517
|
var ESCAPE_CODE = 27;
|
|
72518
|
+
function isQuitRun3(run2) {
|
|
72519
|
+
return run2.endedAt === undefined && run2.status === "paused" && run2.exitReason === "quit";
|
|
72520
|
+
}
|
|
72143
72521
|
var DOUBLE_ESCAPE_SEQUENCE = String.fromCharCode(ESCAPE_CODE, ESCAPE_CODE);
|
|
72144
72522
|
function createSessionPickerState() {
|
|
72145
72523
|
return { query: "", selectedIndex: 0, includeAll: true, filterFocused: false };
|
|
@@ -72280,12 +72658,13 @@ function stageProgress(run2) {
|
|
|
72280
72658
|
const done = run2.stages.filter((s) => s.status === "completed" || s.status === "failed").length;
|
|
72281
72659
|
return `${done}/${total} stages`;
|
|
72282
72660
|
}
|
|
72283
|
-
function renderRunRow(row, isSelected, inner, theme, now) {
|
|
72661
|
+
function renderRunRow(row, isSelected, inner, theme, now, allRuns) {
|
|
72284
72662
|
const border = hexToAnsi(theme.border);
|
|
72285
72663
|
const panelBg = hexBg(theme.bg);
|
|
72286
72664
|
const run2 = row.run;
|
|
72287
|
-
const
|
|
72288
|
-
const
|
|
72665
|
+
const indicatorStatus = isQuitRun3(run2) ? run2.status : runIndicatorStatus(run2, allRuns);
|
|
72666
|
+
const icon = statusIcon(indicatorStatus);
|
|
72667
|
+
const iconColor = hexToAnsi(statusColor(indicatorStatus, theme));
|
|
72289
72668
|
const dim = hexToAnsi(theme.dim);
|
|
72290
72669
|
const text = hexToAnsi(theme.text);
|
|
72291
72670
|
const muted = hexToAnsi(theme.textMuted);
|
|
@@ -72339,6 +72718,7 @@ function renderSessionPicker(opts) {
|
|
|
72339
72718
|
const start = Math.max(0, Math.min(sel - Math.floor(VIEWPORT / 2), rows.length - VIEWPORT));
|
|
72340
72719
|
const visible = rows.slice(Math.max(0, start), Math.max(0, start) + VIEWPORT);
|
|
72341
72720
|
let prevBucket = null;
|
|
72721
|
+
const allRuns = opts.allRuns ?? rows.map(({ run: run2 }) => run2);
|
|
72342
72722
|
for (let i = 0;i < visible.length; i++) {
|
|
72343
72723
|
const row = visible[i];
|
|
72344
72724
|
if (row.bucket !== prevBucket) {
|
|
@@ -72346,7 +72726,7 @@ function renderSessionPicker(opts) {
|
|
|
72346
72726
|
prevBucket = row.bucket;
|
|
72347
72727
|
}
|
|
72348
72728
|
const absIndex = Math.max(0, start) + i;
|
|
72349
|
-
lines.push(...renderRunRow(row, absIndex === sel, inner, theme, now));
|
|
72729
|
+
lines.push(...renderRunRow(row, absIndex === sel, inner, theme, now, allRuns));
|
|
72350
72730
|
}
|
|
72351
72731
|
lines.push(renderBlankRow(inner, theme));
|
|
72352
72732
|
lines.push(renderBottomBorder(width, theme));
|
|
@@ -72686,7 +73066,7 @@ function renderSessionList(runs, opts) {
|
|
|
72686
73066
|
toolNodes: graph.tools.map((tool) => structuredClone(tool))
|
|
72687
73067
|
};
|
|
72688
73068
|
});
|
|
72689
|
-
return renderStatusList(filtered, { theme: opts.theme, now });
|
|
73069
|
+
return renderStatusList(filtered, { theme: opts.theme, now, allRuns: runs });
|
|
72690
73070
|
}
|
|
72691
73071
|
|
|
72692
73072
|
// dist/builtin/workflows/src/tui/session-overlays.ts
|
|
@@ -72707,6 +73087,7 @@ function openSessionPicker(ui, store2, theme, intent = "connect") {
|
|
|
72707
73087
|
const state2 = createSessionPickerState();
|
|
72708
73088
|
let settled = false;
|
|
72709
73089
|
let unsubscribe = null;
|
|
73090
|
+
let pickerRevision = 0;
|
|
72710
73091
|
const resumeCandidateCache = createSessionPickerResumeCandidateCache();
|
|
72711
73092
|
const factory = (tui, _theme, _keys, done) => {
|
|
72712
73093
|
const finish = (result) => {
|
|
@@ -72719,15 +73100,18 @@ function openSessionPicker(ui, store2, theme, intent = "connect") {
|
|
|
72719
73100
|
resolve14(result);
|
|
72720
73101
|
};
|
|
72721
73102
|
const selectRows = () => {
|
|
72722
|
-
const
|
|
72723
|
-
const resumeCandidateLookup = intent === "resume" ? resumeCandidateCache({
|
|
72724
|
-
return selectRunsForPicker(
|
|
73103
|
+
const liveRuns = store2.runs();
|
|
73104
|
+
const resumeCandidateLookup = intent === "resume" ? resumeCandidateCache({ runs: liveRuns, notices: store2.notices(), version: pickerRevision }) : undefined;
|
|
73105
|
+
return selectRunsForPicker(liveRuns, state2.query, state2.includeAll, Date.now(), intent, resumeCandidateLookup);
|
|
72725
73106
|
};
|
|
72726
|
-
unsubscribe = subscribeStoreInvalidation(store2, () =>
|
|
73107
|
+
unsubscribe = subscribeStoreInvalidation(store2, () => {
|
|
73108
|
+
pickerRevision++;
|
|
73109
|
+
tui.requestRender?.();
|
|
73110
|
+
});
|
|
72727
73111
|
return {
|
|
72728
73112
|
render: (width) => {
|
|
72729
73113
|
const rows = selectRows();
|
|
72730
|
-
return renderSessionPicker({ width, theme, rows, state: state2 });
|
|
73114
|
+
return renderSessionPicker({ width, theme, rows, state: state2, allRuns: store2.runs() });
|
|
72731
73115
|
},
|
|
72732
73116
|
handleInput: (data) => {
|
|
72733
73117
|
const rows = selectRows();
|
|
@@ -73056,7 +73440,7 @@ async function handleDurableResume(target, ctx, reporter, deps, preparedCatalog)
|
|
|
73056
73440
|
fail(completedAttempt.message);
|
|
73057
73441
|
return true;
|
|
73058
73442
|
}
|
|
73059
|
-
const result = await runtime.resumeDurableWorkflow(target, { policy });
|
|
73443
|
+
const result = await runtime.resumeDurableWorkflow(target, { policy, actor: "user" });
|
|
73060
73444
|
fail(allOpenable.length === 0 ? result.message : `${result.message}
|
|
73061
73445
|
|
|
73062
73446
|
${formatResumableWorkflowList(allOpenable)}`);
|
|
@@ -73125,7 +73509,10 @@ function isExplicitResumeCandidate(run2) {
|
|
|
73125
73509
|
return isWorkflowRunResumable(workflowRunResumeCandidate(run2)) || run2.endedAt === undefined && run2.status === "running";
|
|
73126
73510
|
}
|
|
73127
73511
|
async function resumeDurableTarget(workflowId, ctx, reporter, deps, runtime) {
|
|
73128
|
-
const result = await runtime.resumeDurableWorkflow(workflowId, {
|
|
73512
|
+
const result = await runtime.resumeDurableWorkflow(workflowId, {
|
|
73513
|
+
policy: workflowPolicyFromContext(ctx),
|
|
73514
|
+
actor: "user"
|
|
73515
|
+
});
|
|
73129
73516
|
if (!result.ok)
|
|
73130
73517
|
reporter.error(result.message);
|
|
73131
73518
|
else {
|
|
@@ -73300,7 +73687,7 @@ ${renderSessionList(store.runs(), { theme, includeAll: true })}`);
|
|
|
73300
73687
|
return true;
|
|
73301
73688
|
}
|
|
73302
73689
|
}
|
|
73303
|
-
const results = action === "quit" ? await quitAllRuns() : await interruptAllRuns();
|
|
73690
|
+
const results = action === "quit" ? await quitAllRuns({ actor: "user" }) : await interruptAllRuns();
|
|
73304
73691
|
const successes = results.filter((result) => result.ok);
|
|
73305
73692
|
const changed = successes.length;
|
|
73306
73693
|
const failures = results.filter((result) => !result.ok);
|
|
@@ -73334,7 +73721,7 @@ ${renderSessionList(store.runs(), { theme, includeAll: true })}`);
|
|
|
73334
73721
|
return true;
|
|
73335
73722
|
}
|
|
73336
73723
|
try {
|
|
73337
|
-
const result = await quitRun(resolved.runId);
|
|
73724
|
+
const result = await quitRun(resolved.runId, { actor: "user" });
|
|
73338
73725
|
if (result.ok)
|
|
73339
73726
|
print(`Run ${result.runId} quit and can be resumed with /workflow resume.`);
|
|
73340
73727
|
else if (result.reason === "already_ended")
|
|
@@ -73427,11 +73814,11 @@ Picker requires an interactive UI surface. Pass a runId: /workflow attach <id> [
|
|
|
73427
73814
|
const isResumableContinuation2 = run3 !== undefined && !isPaused3 && run3.exitReason !== "quit" && isWorkflowRunResumable(workflowRunResumeCandidate(run3));
|
|
73428
73815
|
if (isResumableContinuation2) {
|
|
73429
73816
|
await ensureWorkflowResourcesVisible();
|
|
73430
|
-
const continuation = await deps.runtimeForContext(ctx).resumeFailedRun(resolved.runId, undefined, { policy });
|
|
73817
|
+
const continuation = await deps.runtimeForContext(ctx).resumeFailedRun(resolved.runId, undefined, { policy, actor: "user" });
|
|
73431
73818
|
continuation.ok ? print(continuation.message) : fail(continuation.message);
|
|
73432
73819
|
} else {
|
|
73433
73820
|
try {
|
|
73434
|
-
const result2 = await resumeRun(resolved.runId, {});
|
|
73821
|
+
const result2 = await resumeRun(resolved.runId, { actor: "user" });
|
|
73435
73822
|
if (result2.ok && !isPaused3 && result2.mode === "snapshot" && run3?.exitReason === "quit") {
|
|
73436
73823
|
return await handleDurableResume(resolved.runId, ctx, reporter, deps);
|
|
73437
73824
|
}
|
|
@@ -73541,7 +73928,7 @@ Picker requires an interactive UI surface. Pass a runId: /workflow attach <id> [
|
|
|
73541
73928
|
const stageRunId = resolvedStage.runId ?? runId;
|
|
73542
73929
|
if (action === "pause") {
|
|
73543
73930
|
try {
|
|
73544
|
-
const result2 = await pauseRun(stageRunId, { stageId });
|
|
73931
|
+
const result2 = await pauseRun(stageRunId, { stageId, actor: "user" });
|
|
73545
73932
|
if (!result2.ok) {
|
|
73546
73933
|
fail(result2.reason === "not_found" ? `Run not found: ${stageRunId}` : result2.reason === "already_ended" ? `Run ${stageRunId} already ended.` : result2.reason === "no_active_stages" ? `No pausable stages on run ${stageRunId}.` : `Stage not found: ${stageTarget ?? "(unknown)"}`);
|
|
73547
73934
|
return true;
|
|
@@ -73566,7 +73953,7 @@ Picker requires an interactive UI surface. Pass a runId: /workflow attach <id> [
|
|
|
73566
73953
|
}
|
|
73567
73954
|
if (isResumableContinuation) {
|
|
73568
73955
|
await ensureWorkflowResourcesVisible();
|
|
73569
|
-
const continuation = await deps.runtimeForContext(ctx).resumeFailedRun(stageRunId, stageId, { policy });
|
|
73956
|
+
const continuation = await deps.runtimeForContext(ctx).resumeFailedRun(stageRunId, stageId, { policy, actor: "user" });
|
|
73570
73957
|
continuation.ok ? print(continuation.message) : fail(continuation.message);
|
|
73571
73958
|
return true;
|
|
73572
73959
|
}
|
|
@@ -73575,7 +73962,7 @@ Picker requires an interactive UI surface. Pass a runId: /workflow attach <id> [
|
|
|
73575
73962
|
}
|
|
73576
73963
|
let result;
|
|
73577
73964
|
try {
|
|
73578
|
-
result = await resumeRun(stageRunId, { stageId, message });
|
|
73965
|
+
result = await resumeRun(stageRunId, { stageId, message, actor: "user" });
|
|
73579
73966
|
} catch (error) {
|
|
73580
73967
|
fail(`Failed to resume run ${stageRunId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
73581
73968
|
return true;
|
|
@@ -73699,8 +74086,14 @@ Available: ${formatAvailableWorkflowNames(deps.runtimeProxy.registry.names())}`)
|
|
|
73699
74086
|
emitChatSurface(pi, { kind: "detail", detail: inspected.detail });
|
|
73700
74087
|
return;
|
|
73701
74088
|
}
|
|
73702
|
-
const
|
|
73703
|
-
|
|
74089
|
+
const capturedRuns = store.graphSnapshot().runs;
|
|
74090
|
+
const rows = selectRunsForPicker(capturedRuns, "", true, Date.now());
|
|
74091
|
+
const visibleRuns = rows.map((r) => r.run);
|
|
74092
|
+
emitChatSurface(pi, {
|
|
74093
|
+
kind: "status",
|
|
74094
|
+
runs: visibleRuns,
|
|
74095
|
+
indicatorStatuses: resolveRunIndicatorStatuses(visibleRuns, capturedRuns)
|
|
74096
|
+
});
|
|
73704
74097
|
return;
|
|
73705
74098
|
}
|
|
73706
74099
|
if (subcommand === "reload") {
|
|
@@ -73775,7 +74168,7 @@ Available: ${formatAvailableWorkflowNames(deps.runtimeProxy.registry.names())}`)
|
|
|
73775
74168
|
}
|
|
73776
74169
|
}
|
|
73777
74170
|
await ensureWorkflowResourcesVisible();
|
|
73778
|
-
const result = await deps.runWithLifecycleSuppressedForPolicy(policy, () => deps.runtimeForContext(ctx).dispatch({ workflow: workflowName, inputs: mergedInputs, action: "run" }, { policy }));
|
|
74171
|
+
const result = await deps.runWithLifecycleSuppressedForPolicy(policy, () => deps.runtimeForContext(ctx).dispatch({ workflow: workflowName, inputs: mergedInputs, action: "run" }, { policy, origin: "user" }));
|
|
73779
74172
|
if (result.action !== "run" || !("runId" in result))
|
|
73780
74173
|
return;
|
|
73781
74174
|
const runResult = result;
|
|
@@ -73806,6 +74199,13 @@ Available: ${formatAvailableWorkflowNames(deps.runtimeProxy.registry.names())}`)
|
|
|
73806
74199
|
import { getSupportedThinkingLevels } from "@earendil-works/pi-ai/compat";
|
|
73807
74200
|
|
|
73808
74201
|
// dist/builtin/workflows/src/extension/workflow-status-summary.ts
|
|
74202
|
+
var workflowStatusRenderRuns = new WeakMap;
|
|
74203
|
+
function setWorkflowStatusRenderRuns(result, runs) {
|
|
74204
|
+
workflowStatusRenderRuns.set(result, runs);
|
|
74205
|
+
}
|
|
74206
|
+
function getWorkflowStatusRenderRuns(result) {
|
|
74207
|
+
return workflowStatusRenderRuns.get(result);
|
|
74208
|
+
}
|
|
73809
74209
|
function stageIsActive(stage) {
|
|
73810
74210
|
return stage.status === "running" || stage.status === "awaiting_input";
|
|
73811
74211
|
}
|
|
@@ -73949,7 +74349,17 @@ function statusAwaitingInputLine(entry) {
|
|
|
73949
74349
|
const message = entry.message !== undefined ? ` — "${truncateStatusText(entry.message)}"` : "";
|
|
73950
74350
|
return ` awaiting input: ${target}${prompt}${message}`;
|
|
73951
74351
|
}
|
|
74352
|
+
function statusRunIcon(run2, snapshot, allRuns) {
|
|
74353
|
+
if (snapshot === undefined)
|
|
74354
|
+
return statusIcon(run2.status);
|
|
74355
|
+
const indicatorStatus = runIndicatorStatus(snapshot, allRuns);
|
|
74356
|
+
if (snapshot.endedAt === undefined && snapshot.status === "paused" && snapshot.exitReason === "quit") {
|
|
74357
|
+
return statusIcon("pending");
|
|
74358
|
+
}
|
|
74359
|
+
return statusIcon(indicatorStatus);
|
|
74360
|
+
}
|
|
73952
74361
|
function renderStatusToolContent(result) {
|
|
74362
|
+
const allRuns = getWorkflowStatusRenderRuns(result) ?? result.snapshots;
|
|
73953
74363
|
const lines = ["action: status", `filter: ${result.filter}`];
|
|
73954
74364
|
if (result.runs.length === 0) {
|
|
73955
74365
|
lines.push(result.filter === "all" ? "runs: none" : `runs: none (statusFilter: ${result.filter})`);
|
|
@@ -73962,6 +74372,7 @@ function renderStatusToolContent(result) {
|
|
|
73962
74372
|
const hint = statusRunHint(run2);
|
|
73963
74373
|
const summaryLine = [
|
|
73964
74374
|
`[${index + 1}]`,
|
|
74375
|
+
statusRunIcon(run2, result.snapshots[index], allRuns),
|
|
73965
74376
|
run2.runId,
|
|
73966
74377
|
run2.name,
|
|
73967
74378
|
run2.status,
|
|
@@ -74196,7 +74607,7 @@ async function workflowPauseAction(args) {
|
|
|
74196
74607
|
return { action, runId: "--all", status: "noop", message: allStageConflictMessage("pause") };
|
|
74197
74608
|
}
|
|
74198
74609
|
try {
|
|
74199
|
-
const results = await pauseAllRuns();
|
|
74610
|
+
const results = await pauseAllRuns({ actor: "agent" });
|
|
74200
74611
|
const paused = results.filter((result) => result.ok).length;
|
|
74201
74612
|
return {
|
|
74202
74613
|
action,
|
|
@@ -74226,7 +74637,7 @@ async function workflowPauseAction(args) {
|
|
|
74226
74637
|
return { action, runId: target.runId, status: "noop", message: stage.message };
|
|
74227
74638
|
const stageRunId = stage.runId ?? target.runId;
|
|
74228
74639
|
try {
|
|
74229
|
-
const result = await pauseRun(stageRunId, { stageId: stage.stageId });
|
|
74640
|
+
const result = await pauseRun(stageRunId, { stageId: stage.stageId, actor: "agent" });
|
|
74230
74641
|
return result.ok ? {
|
|
74231
74642
|
action,
|
|
74232
74643
|
runId: result.runId,
|
|
@@ -74315,7 +74726,7 @@ async function workflowQuitAction(args) {
|
|
|
74315
74726
|
if (args.stageId !== undefined && args.stageId.length > 0) {
|
|
74316
74727
|
return { action, runId: "--all", status: "noop", message: allStageConflictMessage("quit") };
|
|
74317
74728
|
}
|
|
74318
|
-
const results = await quitAllRuns();
|
|
74729
|
+
const results = await quitAllRuns({ actor: "agent" });
|
|
74319
74730
|
const successes = results.filter((result) => result.ok);
|
|
74320
74731
|
const quitCount = successes.length;
|
|
74321
74732
|
const failures = results.filter((result) => !result.ok);
|
|
@@ -74335,7 +74746,7 @@ async function workflowQuitAction(args) {
|
|
|
74335
74746
|
if (controlNode.kind === "tool")
|
|
74336
74747
|
return quitToolNodeAction(controlNode.runId, controlNode.nodeId, action);
|
|
74337
74748
|
try {
|
|
74338
|
-
const result = await quitRun(target.runId);
|
|
74749
|
+
const result = await quitRun(target.runId, { actor: "agent" });
|
|
74339
74750
|
if (result.ok) {
|
|
74340
74751
|
return {
|
|
74341
74752
|
action,
|
|
@@ -74417,7 +74828,7 @@ async function resumeDurableShadow(runId, deps) {
|
|
|
74417
74828
|
} catch (error) {
|
|
74418
74829
|
warning = formatWorkflowResourceLoadWarning(error);
|
|
74419
74830
|
}
|
|
74420
|
-
const resumed = await runtime.resumeDurableWorkflow(runId, { policy: deps.policy });
|
|
74831
|
+
const resumed = await runtime.resumeDurableWorkflow(runId, { policy: deps.policy, actor: "agent" });
|
|
74421
74832
|
const message = warning === undefined ? resumed.message : `${warning}
|
|
74422
74833
|
|
|
74423
74834
|
${resumed.message}`;
|
|
@@ -74430,7 +74841,7 @@ ${resumed.message}`;
|
|
|
74430
74841
|
}
|
|
74431
74842
|
async function resumePreparedDurableTarget(runId, deps) {
|
|
74432
74843
|
try {
|
|
74433
|
-
const resumed = await deps.getRuntime().resumeDurableWorkflow(runId, { policy: deps.policy });
|
|
74844
|
+
const resumed = await deps.getRuntime().resumeDurableWorkflow(runId, { policy: deps.policy, actor: "agent" });
|
|
74434
74845
|
return {
|
|
74435
74846
|
action: "resume",
|
|
74436
74847
|
runId: resumed.ok ? resumed.runId : runId,
|
|
@@ -74538,7 +74949,7 @@ async function workflowResumeAction(args, deps) {
|
|
|
74538
74949
|
} catch (error) {
|
|
74539
74950
|
warning = formatWorkflowResourceLoadWarning(error);
|
|
74540
74951
|
}
|
|
74541
|
-
const continuation = await deps.getRuntime().resumeFailedRun(stageRunId, stage.stageId, { policy: deps.policy });
|
|
74952
|
+
const continuation = await deps.getRuntime().resumeFailedRun(stageRunId, stage.stageId, { policy: deps.policy, actor: "agent" });
|
|
74542
74953
|
const message = warning === undefined ? continuation.message : `${warning}
|
|
74543
74954
|
|
|
74544
74955
|
${continuation.message}`;
|
|
@@ -74550,7 +74961,7 @@ ${continuation.message}`;
|
|
|
74550
74961
|
};
|
|
74551
74962
|
}
|
|
74552
74963
|
try {
|
|
74553
|
-
const result = await resumeRun(stageRunId, { stageId: stage.stageId, message: args.message });
|
|
74964
|
+
const result = await resumeRun(stageRunId, { stageId: stage.stageId, message: args.message, actor: "agent" });
|
|
74554
74965
|
if (result.ok) {
|
|
74555
74966
|
const runLevelResumed = hadPausedRunState && !hadPausedStageState && stage.stageId === undefined && result.snapshot.status === "running";
|
|
74556
74967
|
const noPausedProgress = isPaused2 && result.resumed.length === 0 && result.message === undefined && !runLevelResumed;
|
|
@@ -75131,7 +75542,7 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
|
|
|
75131
75542
|
}
|
|
75132
75543
|
case "run": {
|
|
75133
75544
|
await ensureWorkflowResourcesVisible();
|
|
75134
|
-
return getRuntime().dispatch(args, { policy });
|
|
75545
|
+
return getRuntime().dispatch(args, { policy, origin: "agent" });
|
|
75135
75546
|
}
|
|
75136
75547
|
case "status": {
|
|
75137
75548
|
const target = args.runId;
|
|
@@ -75143,16 +75554,18 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
|
|
|
75143
75554
|
if (resolved.kind === "not_found") {
|
|
75144
75555
|
return { action: "statusDetail", runId: target, error: `run not found: ${target}` };
|
|
75145
75556
|
}
|
|
75146
|
-
const
|
|
75147
|
-
return
|
|
75557
|
+
const result2 = inspectRun(resolved.runId);
|
|
75558
|
+
return result2.ok ? { action: "statusDetail", runId: result2.runId, detail: result2.detail } : { action: "statusDetail", runId: target, error: `run not found: ${target}` };
|
|
75148
75559
|
}
|
|
75149
75560
|
const listing = buildWorkflowStatusListing(topLevelExpandedSnapshots(), args.statusFilter ?? "all");
|
|
75150
|
-
|
|
75561
|
+
const result = {
|
|
75151
75562
|
action: "status",
|
|
75152
75563
|
filter: listing.filter,
|
|
75153
75564
|
runs: listing.runs,
|
|
75154
75565
|
snapshots: listing.snapshots
|
|
75155
75566
|
};
|
|
75567
|
+
setWorkflowStatusRenderRuns(result, store.graphSnapshot().runs);
|
|
75568
|
+
return result;
|
|
75156
75569
|
}
|
|
75157
75570
|
case "stages":
|
|
75158
75571
|
return workflowStagesResult(args);
|
|
@@ -75319,7 +75732,8 @@ function renderResult(result, opts) {
|
|
|
75319
75732
|
return renderStatusList(r.snapshots, {
|
|
75320
75733
|
theme: themed ? deriveGraphTheme({}) : undefined,
|
|
75321
75734
|
width: opts?.width,
|
|
75322
|
-
now: opts?.now
|
|
75735
|
+
now: opts?.now,
|
|
75736
|
+
allRuns: opts?.allRuns ?? getWorkflowStatusRenderRuns(r) ?? r.snapshots
|
|
75323
75737
|
});
|
|
75324
75738
|
}
|
|
75325
75739
|
case "statusDetail": {
|