@bastani/atomic 0.8.21 → 0.8.22-0
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 +40 -9
- package/dist/builtin/intercom/broker/broker.ts +3 -3
- package/dist/builtin/intercom/config.ts +3 -3
- package/dist/builtin/intercom/index.ts +1 -1
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/ui/compose.ts +2 -2
- package/dist/builtin/mcp/host-html-template.ts +0 -3
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +13 -4
- package/dist/builtin/subagents/agents/codebase-online-researcher.md +9 -9
- package/dist/builtin/subagents/agents/debugger.md +6 -6
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +1 -1
- package/dist/builtin/subagents/skills/browser-use/SKILL.md +234 -0
- package/dist/builtin/subagents/skills/browser-use/references/cdp-python.md +76 -0
- package/dist/builtin/subagents/skills/browser-use/references/multi-session.md +92 -0
- package/dist/builtin/subagents/skills/subagent/SKILL.md +4 -4
- package/dist/builtin/subagents/src/agents/skills.ts +19 -1
- package/dist/builtin/subagents/src/extension/index.ts +24 -22
- package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +7 -1
- package/dist/builtin/subagents/src/runs/background/async-execution.ts +23 -7
- package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +98 -3
- package/dist/builtin/subagents/src/runs/background/async-status.ts +3 -1
- package/dist/builtin/subagents/src/runs/background/run-status.ts +1 -1
- package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +3 -0
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +37 -12
- package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +15 -15
- package/dist/builtin/subagents/src/runs/foreground/execution.ts +26 -2
- package/dist/builtin/subagents/src/runs/shared/nested-render.ts +1 -1
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +7 -0
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +28 -1
- package/dist/builtin/subagents/src/shared/fast-mode.ts +80 -0
- package/dist/builtin/subagents/src/shared/formatters.ts +4 -2
- package/dist/builtin/subagents/src/shared/types.ts +4 -2
- package/dist/builtin/subagents/src/shared/utils.ts +3 -61
- package/dist/builtin/subagents/src/tui/render.ts +303 -157
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +95 -35
- package/dist/builtin/workflows/README.md +228 -41
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +535 -541
- package/dist/builtin/workflows/builtin/goal.ts +39 -25
- package/dist/builtin/workflows/builtin/open-claude-design.ts +66 -69
- package/dist/builtin/workflows/builtin/ralph.ts +21 -21
- package/dist/builtin/workflows/package.json +6 -5
- package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
- package/dist/builtin/workflows/src/extension/background-ui-adapter.ts +2 -2
- package/dist/builtin/workflows/src/extension/discovery.ts +25 -146
- package/dist/builtin/workflows/src/extension/dispatcher.ts +72 -24
- package/dist/builtin/workflows/src/extension/hil-answer-notifications.ts +363 -0
- package/dist/builtin/workflows/src/extension/index.ts +690 -352
- package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +99 -62
- package/dist/builtin/workflows/src/extension/render-call.ts +2 -1
- package/dist/builtin/workflows/src/extension/render-result.ts +9 -3
- package/dist/builtin/workflows/src/extension/renderers.ts +5 -3
- package/dist/builtin/workflows/src/extension/runtime.ts +68 -33
- package/dist/builtin/workflows/src/extension/status-writer.ts +1 -1
- package/dist/builtin/workflows/src/extension/wiring.ts +34 -13
- package/dist/builtin/workflows/src/extension/workflow-module-loader.ts +142 -0
- package/dist/builtin/workflows/src/extension/workflow-schema.ts +4 -4
- package/dist/builtin/workflows/src/index.ts +2 -0
- package/dist/builtin/workflows/src/intercom/result-intercom.ts +1 -1
- package/dist/builtin/workflows/src/runs/background/runner.ts +6 -4
- package/dist/builtin/workflows/src/runs/background/status.ts +45 -21
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +624 -52
- package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +80 -24
- package/dist/builtin/workflows/src/runs/shared/validate-inputs.ts +61 -24
- package/dist/builtin/workflows/src/runs/shared/workflow-runner.ts +32 -10
- package/dist/builtin/workflows/src/sdk-surface.ts +6 -0
- package/dist/builtin/workflows/src/shared/expanded-workflow-graph.ts +178 -0
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +92 -12
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +21 -3
- package/dist/builtin/workflows/src/shared/render-inputs-schema.ts +1 -2
- package/dist/builtin/workflows/src/shared/run-visibility.ts +9 -0
- package/dist/builtin/workflows/src/shared/schema-introspection.ts +121 -0
- package/dist/builtin/workflows/src/shared/serializable.ts +132 -0
- package/dist/builtin/workflows/src/shared/stage-ui-broker.ts +91 -9
- package/dist/builtin/workflows/src/shared/store-types.ts +31 -3
- package/dist/builtin/workflows/src/shared/store.ts +58 -14
- package/dist/builtin/workflows/src/shared/types.ts +105 -40
- package/dist/builtin/workflows/src/tui/chat-surface-message.ts +129 -13
- package/dist/builtin/workflows/src/tui/chat-surface.ts +6 -1
- package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +3 -2
- package/dist/builtin/workflows/src/tui/graph-canvas.ts +1 -1
- package/dist/builtin/workflows/src/tui/graph-view.ts +91 -65
- package/dist/builtin/workflows/src/tui/inline-form-card.ts +1 -1
- package/dist/builtin/workflows/src/tui/inline-form-overlay.ts +3 -2
- package/dist/builtin/workflows/src/tui/inputs-overlay.ts +3 -2
- package/dist/builtin/workflows/src/tui/inputs-picker.ts +8 -7
- package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +2 -0
- package/dist/builtin/workflows/src/tui/node-card.ts +34 -8
- package/dist/builtin/workflows/src/tui/overlay-adapter.ts +4 -11
- package/dist/builtin/workflows/src/tui/prompt-card.ts +98 -50
- package/dist/builtin/workflows/src/tui/session-list.ts +7 -2
- package/dist/builtin/workflows/src/tui/session-picker.ts +2 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view.ts +226 -55
- package/dist/builtin/workflows/src/tui/status-helpers.ts +2 -0
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +37 -158
- package/dist/builtin/workflows/src/tui/toast.ts +2 -2
- package/dist/builtin/workflows/src/tui/widget.ts +53 -12
- package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +270 -19
- package/dist/builtin/workflows/src/tui/workflow-notice-card.ts +184 -0
- package/dist/builtin/workflows/src/workflows/define-workflow.ts +138 -43
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +45 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +27 -9
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +196 -17
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +2 -2
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/codex-fast-mode.d.ts +36 -0
- package/dist/core/codex-fast-mode.d.ts.map +1 -0
- package/dist/core/codex-fast-mode.js +117 -0
- package/dist/core/codex-fast-mode.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +1 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +1 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/index.d.ts +4 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -0
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +7 -2
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +23 -8
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/reactive-widget.d.ts +58 -0
- package/dist/core/extensions/reactive-widget.d.ts.map +1 -0
- package/dist/core/extensions/reactive-widget.js +182 -0
- package/dist/core/extensions/reactive-widget.js.map +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +1 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +26 -12
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +8 -2
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts +4 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +11 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/resource-loader.d.ts +9 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +49 -21
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +22 -13
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +7 -5
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +5 -3
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +16 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +64 -5
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +7 -4
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/ask-user-question.js +2 -2
- package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +12 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/chat-input-actions.d.ts.map +1 -1
- package/dist/modes/interactive/chat-input-actions.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js +0 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/fast-mode-selector.d.ts +27 -0
- package/dist/modes/interactive/components/fast-mode-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/fast-mode-selector.js +105 -0
- package/dist/modes/interactive/components/fast-mode-selector.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +7 -12
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +132 -30
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +53 -6
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/docs/compaction.md +1 -1
- package/docs/custom-provider.md +2 -2
- package/docs/development.md +2 -2
- package/docs/docs.json +2 -2
- package/docs/extensions.md +18 -13
- package/docs/providers.md +5 -1
- package/docs/quickstart.md +5 -3
- package/docs/rpc.md +5 -5
- package/docs/sdk.md +12 -12
- package/docs/settings.md +18 -0
- package/docs/themes.md +6 -6
- package/docs/tui.md +20 -18
- package/docs/usage.md +2 -0
- package/docs/workflows.md +403 -39
- package/examples/extensions/qna.ts +2 -2
- package/package.json +4 -4
- package/dist/builtin/subagents/skills/playwright-cli/SKILL.md +0 -392
- package/dist/builtin/subagents/skills/playwright-cli/references/element-attributes.md +0 -23
- package/dist/builtin/subagents/skills/playwright-cli/references/playwright-tests.md +0 -39
- package/dist/builtin/subagents/skills/playwright-cli/references/request-mocking.md +0 -87
- package/dist/builtin/subagents/skills/playwright-cli/references/running-code.md +0 -241
- package/dist/builtin/subagents/skills/playwright-cli/references/session-management.md +0 -225
- package/dist/builtin/subagents/skills/playwright-cli/references/spec-driven-testing.md +0 -305
- package/dist/builtin/subagents/skills/playwright-cli/references/storage-state.md +0 -275
- package/dist/builtin/subagents/skills/playwright-cli/references/test-generation.md +0 -134
- package/dist/builtin/subagents/skills/playwright-cli/references/tracing.md +0 -139
- package/dist/builtin/subagents/skills/playwright-cli/references/video-recording.md +0 -143
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
ExtensionAPI,
|
|
3
3
|
PiMessageRenderComponent,
|
|
4
|
-
|
|
4
|
+
PiMessageRenderer,
|
|
5
5
|
} from "./index.js";
|
|
6
6
|
import type { Store } from "../shared/store.js";
|
|
7
7
|
import type {
|
|
@@ -9,11 +9,14 @@ import type {
|
|
|
9
9
|
PromptKind,
|
|
10
10
|
RunSnapshot,
|
|
11
11
|
RunStatus,
|
|
12
|
+
StageInputKind,
|
|
12
13
|
StageSnapshot,
|
|
13
14
|
StageStatus,
|
|
14
15
|
StoreSnapshot,
|
|
15
16
|
} from "../shared/store-types.js";
|
|
16
|
-
import {
|
|
17
|
+
import { isTopLevelWorkflowRun } from "../shared/run-visibility.js";
|
|
18
|
+
import { deriveGraphThemeFromPiTheme, type GraphTheme } from "../tui/graph-theme.js";
|
|
19
|
+
import { renderWorkflowNoticeCard, type WorkflowNoticeTone } from "../tui/workflow-notice-card.js";
|
|
17
20
|
|
|
18
21
|
export const LIFECYCLE_NOTICE_CUSTOM_TYPE = "workflows:lifecycle-notice";
|
|
19
22
|
export const LIFECYCLE_NOTICE_SNIPPET_LIMIT = 240;
|
|
@@ -40,7 +43,7 @@ export interface WorkflowLifecycleNoticeDetails {
|
|
|
40
43
|
readonly stageId?: string;
|
|
41
44
|
readonly stageName?: string;
|
|
42
45
|
readonly promptId?: string;
|
|
43
|
-
readonly promptKind?: PromptKind;
|
|
46
|
+
readonly promptKind?: PromptKind | StageInputKind;
|
|
44
47
|
readonly promptMessage?: string;
|
|
45
48
|
readonly error?: string;
|
|
46
49
|
readonly failedStageId?: string;
|
|
@@ -64,7 +67,7 @@ export interface WorkflowLifecycleNotificationOptions {
|
|
|
64
67
|
readonly seedExisting?: boolean;
|
|
65
68
|
}
|
|
66
69
|
|
|
67
|
-
type RawRenderer =
|
|
70
|
+
type RawRenderer = PiMessageRenderer;
|
|
68
71
|
|
|
69
72
|
// Process-lifetime registration dedupe: extension hosts are object identities
|
|
70
73
|
// and may be garbage-collected, but renderer registrations are not unregistered.
|
|
@@ -91,6 +94,7 @@ export function seedWorkflowLifecycleNotificationState(
|
|
|
91
94
|
snapshot: StoreSnapshot,
|
|
92
95
|
): void {
|
|
93
96
|
for (const run of snapshot.runs) {
|
|
97
|
+
if (!isTopLevelWorkflowRun(run)) continue;
|
|
94
98
|
if ((run.status === "completed" || run.status === "failed") && run.endedAt !== undefined) {
|
|
95
99
|
state.deliveredTerminalRuns.add(terminalRunKey(run.status, run.id));
|
|
96
100
|
}
|
|
@@ -124,6 +128,24 @@ export function withWorkflowLifecycleNotificationsSuppressed<T>(
|
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Async-safe companion to {@link withWorkflowLifecycleNotificationsSuppressed}.
|
|
133
|
+
* Keeps suppression active until the awaited operation settles, so terminal
|
|
134
|
+
* store updates produced by background jobs cannot race an awaited headless
|
|
135
|
+
* workflow dispatch and trigger an extra steer turn before the caller returns.
|
|
136
|
+
*/
|
|
137
|
+
export async function withWorkflowLifecycleNotificationsSuppressedAsync<T>(
|
|
138
|
+
state: WorkflowLifecycleNotificationState,
|
|
139
|
+
fn: () => Promise<T>,
|
|
140
|
+
): Promise<T> {
|
|
141
|
+
state.suppressionDepth += 1;
|
|
142
|
+
try {
|
|
143
|
+
return await fn();
|
|
144
|
+
} finally {
|
|
145
|
+
state.suppressionDepth -= 1;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
127
149
|
export function installWorkflowLifecycleNotifications(
|
|
128
150
|
options: WorkflowLifecycleNotificationOptions,
|
|
129
151
|
): () => void {
|
|
@@ -141,6 +163,7 @@ export function installWorkflowLifecycleNotifications(
|
|
|
141
163
|
|
|
142
164
|
const emit = (details: WorkflowLifecycleNoticeDetails): void => {
|
|
143
165
|
const content = formatWorkflowLifecycleNoticeText(details);
|
|
166
|
+
const deliveryOptions = { triggerTurn: true, deliverAs: "steer" as const };
|
|
144
167
|
try {
|
|
145
168
|
// Store subscribers are notified in a tight loop. A lifecycle notice
|
|
146
169
|
// failure must never abort sibling subscribers such as status writers.
|
|
@@ -152,7 +175,7 @@ export function installWorkflowLifecycleNotifications(
|
|
|
152
175
|
display: true,
|
|
153
176
|
details,
|
|
154
177
|
},
|
|
155
|
-
|
|
178
|
+
deliveryOptions,
|
|
156
179
|
),
|
|
157
180
|
).catch((error: unknown) => warnLifecycleSendFailure(error));
|
|
158
181
|
} catch (error) {
|
|
@@ -187,8 +210,9 @@ export function installWorkflowLifecycleNotifications(
|
|
|
187
210
|
if (state.deliveredInputPrompts.has(key)) return;
|
|
188
211
|
|
|
189
212
|
state.deliveredInputPrompts.add(key);
|
|
190
|
-
|
|
191
|
-
|
|
213
|
+
// Awaiting-input states are tracked for dedupe/restore, but must not enqueue
|
|
214
|
+
// a main-chat steer turn. Waking the active agent with an actionable prompt
|
|
215
|
+
// can let the model answer workflow HIL without a deliberate user action.
|
|
192
216
|
};
|
|
193
217
|
|
|
194
218
|
const emitRunAwaitingInputNoticeOnce = (run: RunSnapshot): void => {
|
|
@@ -198,12 +222,13 @@ export function installWorkflowLifecycleNotifications(
|
|
|
198
222
|
if (state.deliveredInputPrompts.has(key)) return;
|
|
199
223
|
|
|
200
224
|
state.deliveredInputPrompts.add(key);
|
|
201
|
-
|
|
202
|
-
|
|
225
|
+
// See stage-level awaiting-input handling above: prompt state remains visible
|
|
226
|
+
// through workflow status/connect surfaces instead of the main chat context.
|
|
203
227
|
};
|
|
204
228
|
|
|
205
229
|
const inspect = (snapshot: StoreSnapshot): void => {
|
|
206
230
|
for (const run of snapshot.runs) {
|
|
231
|
+
if (!isTopLevelWorkflowRun(run)) continue;
|
|
207
232
|
emitTerminalNoticeOnce(run, "completed");
|
|
208
233
|
emitTerminalNoticeOnce(run, "failed");
|
|
209
234
|
|
|
@@ -227,10 +252,10 @@ export function registerLifecycleNoticeRenderer(
|
|
|
227
252
|
const host = options.rendererHost ?? register;
|
|
228
253
|
if (rendererRegisteredHosts.has(host)) return;
|
|
229
254
|
|
|
230
|
-
const renderer: RawRenderer = (raw) => {
|
|
255
|
+
const renderer: RawRenderer = (raw, _options, piTheme) => {
|
|
231
256
|
const message = raw as { details?: WorkflowLifecycleNoticeDetails };
|
|
232
257
|
if (!message.details) return undefined;
|
|
233
|
-
return makeNoticeComponent(message.details);
|
|
258
|
+
return makeNoticeComponent(message.details, themeFromRenderer(piTheme));
|
|
234
259
|
};
|
|
235
260
|
|
|
236
261
|
register(LIFECYCLE_NOTICE_CUSTOM_TYPE, renderer);
|
|
@@ -240,23 +265,23 @@ export function registerLifecycleNoticeRenderer(
|
|
|
240
265
|
export function formatWorkflowLifecycleNoticeText(details: WorkflowLifecycleNoticeDetails): string {
|
|
241
266
|
const workflowName = escapeQuotedText(details.workflowName);
|
|
242
267
|
if (details.kind === "completed") {
|
|
243
|
-
return
|
|
268
|
+
return `✓ Workflow "${workflowName}" completed (run ${details.runId}). Inspect: /workflow status ${details.runId}`;
|
|
244
269
|
}
|
|
245
270
|
if (details.kind === "failed") {
|
|
246
271
|
const stage = details.stageName ?? details.failedStageId;
|
|
247
272
|
const stageText = stage ? `, stage ${stage}` : "";
|
|
248
273
|
const errorText = details.error ? `: ${details.error}` : "";
|
|
249
|
-
return
|
|
274
|
+
return `✗ Workflow "${workflowName}" failed (run ${details.runId}${stageText})${errorText}. Inspect: /workflow status ${details.runId}`;
|
|
250
275
|
}
|
|
251
276
|
const prompt = details.promptMessage ? ` Prompt: ${details.promptMessage}` : "";
|
|
252
277
|
if (details.scope === "run") {
|
|
253
|
-
return
|
|
278
|
+
return `? Workflow "${workflowName}" needs input (run ${details.runId}).${prompt} Respond: /workflow connect ${details.runId} to answer this run-level prompt.`;
|
|
254
279
|
}
|
|
255
280
|
const stage = details.stageName ?? details.stageId ?? "unknown";
|
|
256
281
|
const responseHint = details.stageId && details.promptId
|
|
257
282
|
? `/workflow connect ${details.runId} or workflow({ action: "send", runId: ${jsonString(details.runId)}, stageId: ${jsonString(details.stageId)}, promptId: ${jsonString(details.promptId)}, response: ... })`
|
|
258
283
|
: `/workflow connect ${details.runId}`;
|
|
259
|
-
return
|
|
284
|
+
return `? Workflow "${workflowName}" needs input (run ${details.runId}, stage ${stage}).${prompt} Respond: ${responseHint}.`;
|
|
260
285
|
}
|
|
261
286
|
|
|
262
287
|
function makeTerminalNotice(
|
|
@@ -281,34 +306,6 @@ function makeTerminalNotice(
|
|
|
281
306
|
};
|
|
282
307
|
}
|
|
283
308
|
|
|
284
|
-
function makeStageAwaitingInputNotice(run: RunSnapshot, stage: StageSnapshot): WorkflowLifecycleNoticeDetails {
|
|
285
|
-
const prompt = stage.pendingPrompt;
|
|
286
|
-
return {
|
|
287
|
-
kind: "awaiting_input",
|
|
288
|
-
scope: "stage",
|
|
289
|
-
runId: run.id,
|
|
290
|
-
workflowName: run.name,
|
|
291
|
-
status: stage.status,
|
|
292
|
-
stageId: stage.id,
|
|
293
|
-
stageName: stage.name,
|
|
294
|
-
...(prompt ? promptFields(prompt) : {}),
|
|
295
|
-
// Normal store paths stamp awaitingInputSince; Date.now() is defensive for malformed restored snapshots.
|
|
296
|
-
createdAt: prompt?.createdAt ?? stage.awaitingInputSince ?? Date.now(),
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function makeRunAwaitingInputNotice(run: RunSnapshot, prompt: PendingPrompt): WorkflowLifecycleNoticeDetails {
|
|
301
|
-
return {
|
|
302
|
-
kind: "awaiting_input",
|
|
303
|
-
scope: "run",
|
|
304
|
-
runId: run.id,
|
|
305
|
-
workflowName: run.name,
|
|
306
|
-
status: run.status,
|
|
307
|
-
...promptFields(prompt),
|
|
308
|
-
createdAt: prompt.createdAt,
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
|
|
312
309
|
function warnLifecycleSendFailure(error: unknown): void {
|
|
313
310
|
if (process.env.ATOMIC_WORKFLOW_DEBUG !== "1") return;
|
|
314
311
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -327,18 +324,8 @@ function terminalRunKey(kind: "completed" | "failed", runId: string): string {
|
|
|
327
324
|
return `${kind}:${runId}`;
|
|
328
325
|
}
|
|
329
326
|
|
|
330
|
-
function promptFields(
|
|
331
|
-
prompt: PendingPrompt,
|
|
332
|
-
): Pick<WorkflowLifecycleNoticeDetails, "promptId" | "promptKind" | "promptMessage"> {
|
|
333
|
-
return {
|
|
334
|
-
promptId: prompt.id,
|
|
335
|
-
promptKind: prompt.kind,
|
|
336
|
-
promptMessage: truncateSnippet(prompt.message),
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
|
|
340
327
|
function awaitingInputKey(runId: string, stage: StageSnapshot): string {
|
|
341
|
-
const promptId = stage.pendingPrompt?.id;
|
|
328
|
+
const promptId = stage.pendingPrompt?.id ?? stage.inputRequest?.id;
|
|
342
329
|
if (promptId) return `awaiting_input:${runId}:stage:${stage.id}:${promptId}`;
|
|
343
330
|
return `awaiting_input:${runId}:stage:${stage.id}:${stage.awaitingInputSince ?? "active"}`;
|
|
344
331
|
}
|
|
@@ -353,20 +340,70 @@ function truncateSnippet(value: string): string {
|
|
|
353
340
|
return `${normalized.slice(0, LIFECYCLE_NOTICE_SNIPPET_LIMIT - 1)}…`;
|
|
354
341
|
}
|
|
355
342
|
|
|
356
|
-
function makeNoticeComponent(
|
|
343
|
+
function makeNoticeComponent(
|
|
344
|
+
details: WorkflowLifecycleNoticeDetails,
|
|
345
|
+
theme: GraphTheme | undefined,
|
|
346
|
+
): PiMessageRenderComponent {
|
|
357
347
|
const text = formatWorkflowLifecycleNoticeText(details);
|
|
358
348
|
return {
|
|
359
349
|
render(width: number): string[] {
|
|
360
|
-
//
|
|
361
|
-
//
|
|
362
|
-
|
|
363
|
-
// crash the whole TUI on narrow terminals or after a resize (#1109).
|
|
364
|
-
// `wrapPlainText` hard-breaks long unbreakable tokens (e.g. UUIDs), so
|
|
365
|
-
// every returned line is guaranteed to fit within `width`.
|
|
366
|
-
return wrapPlainText(text, width);
|
|
350
|
+
// Width < 32 cannot carry rounded card chrome without exceeding the
|
|
351
|
+
// terminal, so the card helper falls back to wrapped plain text there.
|
|
352
|
+
return renderLifecycleNoticeCard(details, { width, theme, fallbackText: text });
|
|
367
353
|
},
|
|
368
354
|
invalidate() {
|
|
369
355
|
/* stored lifecycle notices are immutable */
|
|
370
356
|
},
|
|
371
357
|
};
|
|
372
358
|
}
|
|
359
|
+
|
|
360
|
+
function renderLifecycleNoticeCard(
|
|
361
|
+
details: WorkflowLifecycleNoticeDetails,
|
|
362
|
+
opts: { width: number; theme?: GraphTheme; fallbackText: string },
|
|
363
|
+
): string[] {
|
|
364
|
+
const tone: WorkflowNoticeTone = details.kind === "failed" ? "error" : details.kind === "awaiting_input" ? "warning" : "success";
|
|
365
|
+
const title = details.kind === "failed"
|
|
366
|
+
? "WORKFLOW FAILED"
|
|
367
|
+
: details.kind === "awaiting_input"
|
|
368
|
+
? "WORKFLOW INPUT"
|
|
369
|
+
: "WORKFLOW COMPLETE";
|
|
370
|
+
const glyph = details.kind === "failed" ? "✗" : details.kind === "awaiting_input" ? "?" : "✓";
|
|
371
|
+
const stage = details.stageName ?? details.failedStageId ?? details.stageId;
|
|
372
|
+
const headline = details.kind === "failed"
|
|
373
|
+
? `Workflow "${details.workflowName}" failed`
|
|
374
|
+
: details.kind === "awaiting_input"
|
|
375
|
+
? `Workflow "${details.workflowName}" needs input`
|
|
376
|
+
: `Workflow "${details.workflowName}" completed`;
|
|
377
|
+
return renderWorkflowNoticeCard({
|
|
378
|
+
title,
|
|
379
|
+
glyph,
|
|
380
|
+
headline,
|
|
381
|
+
tone,
|
|
382
|
+
fields: [
|
|
383
|
+
{ label: "workflow", value: details.workflowName },
|
|
384
|
+
{ label: "run", value: details.runId },
|
|
385
|
+
{ label: "stage", value: stage },
|
|
386
|
+
{ label: "prompt", value: details.promptMessage, tone: "muted" },
|
|
387
|
+
{ label: "error", value: details.error, tone: "error" },
|
|
388
|
+
{ label: "duration", value: formatDurationMs(details.durationMs), tone: "muted" },
|
|
389
|
+
],
|
|
390
|
+
hints: [details.kind === "awaiting_input" ? `/workflow connect ${details.runId}` : `/workflow status ${details.runId}`],
|
|
391
|
+
fallbackText: opts.fallbackText,
|
|
392
|
+
width: opts.width,
|
|
393
|
+
...(opts.theme ? { theme: opts.theme } : {}),
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function formatDurationMs(durationMs: number | undefined): string | undefined {
|
|
398
|
+
if (durationMs === undefined) return undefined;
|
|
399
|
+
if (durationMs < 1000) return `${durationMs}ms`;
|
|
400
|
+
const seconds = durationMs / 1000;
|
|
401
|
+
if (seconds < 60) return `${seconds.toFixed(seconds < 10 ? 1 : 0)}s`;
|
|
402
|
+
const minutes = Math.floor(seconds / 60);
|
|
403
|
+
const remainder = Math.round(seconds % 60);
|
|
404
|
+
return `${minutes}m ${remainder}s`;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function themeFromRenderer(piTheme: unknown): GraphTheme | undefined {
|
|
408
|
+
return piTheme === undefined ? undefined : deriveGraphThemeFromPiTheme(piTheme);
|
|
409
|
+
}
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { truncateToWidth } from "../tui/text-helpers.js";
|
|
7
|
+
import type { WorkflowInputValues } from "../shared/types.js";
|
|
7
8
|
|
|
8
9
|
/** Renderer-only subset of the canonical WorkflowToolArgs from index.ts. */
|
|
9
10
|
export interface WorkflowToolArgs {
|
|
10
11
|
workflow?: string;
|
|
11
|
-
inputs?:
|
|
12
|
+
inputs?: WorkflowInputValues;
|
|
12
13
|
action?:
|
|
13
14
|
| "run"
|
|
14
15
|
| "list"
|
|
@@ -20,6 +20,7 @@ import { renderRunDetail } from "../tui/run-detail.js";
|
|
|
20
20
|
import { renderWorkflowList } from "../tui/workflow-list.js";
|
|
21
21
|
import { deriveGraphTheme } from "../tui/graph-theme.js";
|
|
22
22
|
import { renderDispatchConfirm } from "../tui/dispatch-confirm.js";
|
|
23
|
+
import type { WorkflowInputValues, WorkflowOutputValues } from "../shared/types.js";
|
|
23
24
|
import { renderRoundedBox } from "../tui/chat-surface.js";
|
|
24
25
|
import { truncateToWidth } from "../tui/text-helpers.js";
|
|
25
26
|
|
|
@@ -87,7 +88,7 @@ type RunResult = {
|
|
|
87
88
|
name?: string;
|
|
88
89
|
runId: string;
|
|
89
90
|
status: string;
|
|
90
|
-
result?:
|
|
91
|
+
result?: WorkflowOutputValues;
|
|
91
92
|
details?: WorkflowDetails;
|
|
92
93
|
error?: string;
|
|
93
94
|
stages?: StageSnapshot[];
|
|
@@ -104,13 +105,15 @@ type StageListItem = {
|
|
|
104
105
|
status: StageStatus;
|
|
105
106
|
sessionId?: string;
|
|
106
107
|
sessionFile?: string;
|
|
108
|
+
transcriptPath?: string;
|
|
107
109
|
error?: string;
|
|
108
110
|
awaitingInputSince?: number;
|
|
109
111
|
pendingPrompt?: PendingPrompt;
|
|
110
112
|
inputRequest?: StageInputRequest;
|
|
111
113
|
};
|
|
112
114
|
type StageListResult = { action: "stages"; runId: string; filter: string; stages: StageListItem[]; error?: string };
|
|
113
|
-
type
|
|
115
|
+
type StageDetailItem = StageSnapshot & { transcriptPath?: string };
|
|
116
|
+
type StageDetailResult = { action: "stage"; runId: string; stage?: StageDetailItem; error?: string };
|
|
114
117
|
type TranscriptEntry = { role: string; text?: string; toolName?: string; output?: string; timestamp?: number };
|
|
115
118
|
type TranscriptResult = {
|
|
116
119
|
action: "transcript";
|
|
@@ -119,8 +122,11 @@ type TranscriptResult = {
|
|
|
119
122
|
source: "live" | "snapshot" | "error";
|
|
120
123
|
entries: TranscriptEntry[];
|
|
121
124
|
truncated: boolean;
|
|
125
|
+
entryCount?: number;
|
|
126
|
+
entryLimit?: number;
|
|
122
127
|
sessionId?: string;
|
|
123
128
|
sessionFile?: string;
|
|
129
|
+
transcriptPath?: string;
|
|
124
130
|
};
|
|
125
131
|
type SendResult = { action: "send"; runId: string; stageId: string; delivery: string; status: "ok" | "noop"; message: string };
|
|
126
132
|
type PauseResult = { action: "pause"; runId: string; status: string; message: string };
|
|
@@ -156,7 +162,7 @@ export interface RenderResultOpts {
|
|
|
156
162
|
width?: number;
|
|
157
163
|
/** Original workflow inputs from the tool call, used to render the same
|
|
158
164
|
* dispatch confirmation card as `/workflow <name> ...` for background runs. */
|
|
159
|
-
runInputs?: Readonly<
|
|
165
|
+
runInputs?: Readonly<WorkflowInputValues>;
|
|
160
166
|
/**
|
|
161
167
|
* Suppress ANSI colour output (CLI flag paths / non-TTY consumers).
|
|
162
168
|
* When false/undefined the canonical Catppuccin chrome is rendered.
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* cross-ref: spec §5.6 Persistence renderers (registration only)
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import type { WorkflowInputValues, WorkflowOutputValues } from "../shared/types.js";
|
|
12
|
+
|
|
11
13
|
// ---------------------------------------------------------------------------
|
|
12
14
|
// Entry payload shapes (matches pi.appendEntry call signatures from §5.6)
|
|
13
15
|
// ---------------------------------------------------------------------------
|
|
@@ -15,7 +17,7 @@
|
|
|
15
17
|
export interface RunStartPayload {
|
|
16
18
|
runId: string;
|
|
17
19
|
name: string;
|
|
18
|
-
inputs?:
|
|
20
|
+
inputs?: WorkflowInputValues;
|
|
19
21
|
ts?: number;
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -46,7 +48,7 @@ export interface StageEndPayload {
|
|
|
46
48
|
export interface RunEndPayload {
|
|
47
49
|
runId: string;
|
|
48
50
|
status: "ok" | "error" | "killed" | string;
|
|
49
|
-
result?:
|
|
51
|
+
result?: WorkflowOutputValues;
|
|
50
52
|
ts?: number;
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -82,6 +84,6 @@ export function renderStageResult(payload: StageEndPayload): string {
|
|
|
82
84
|
|
|
83
85
|
/** Render workflow.run.end entry. */
|
|
84
86
|
export function renderRunSummary(payload: RunEndPayload): string {
|
|
85
|
-
const icon = payload.status === "ok" ? "
|
|
87
|
+
const icon = payload.status === "ok" ? "✓" : "✗";
|
|
86
88
|
return `${icon} workflow [${payload.runId}] ${payload.status}`;
|
|
87
89
|
}
|
|
@@ -12,19 +12,21 @@
|
|
|
12
12
|
|
|
13
13
|
import { createRegistry } from "../workflows/registry.js";
|
|
14
14
|
import type { WorkflowRegistry } from "../workflows/registry.js";
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
import {
|
|
16
|
+
INTERACTIVE_WORKFLOW_POLICY,
|
|
17
|
+
type WorkflowDefinition,
|
|
18
|
+
type WorkflowPersistencePort,
|
|
19
|
+
type WorkflowMcpPort,
|
|
20
|
+
type WorkflowRuntimeConfig,
|
|
21
|
+
type WorkflowDetails,
|
|
22
|
+
type WorkflowDirectOptions,
|
|
23
|
+
type WorkflowDirectTaskItem,
|
|
24
|
+
type WorkflowChainStep,
|
|
25
|
+
type WorkflowModelCatalogPort,
|
|
26
|
+
type WorkflowExecutionPolicy,
|
|
25
27
|
} from "../shared/types.js";
|
|
26
28
|
import type { StageAdapters } from "../runs/foreground/stage-runner.js";
|
|
27
|
-
import {
|
|
29
|
+
import { resolveAndValidateInputs, runChain, runParallel, runTask, type RunOpts } from "../runs/foreground/executor.js";
|
|
28
30
|
import type { Store } from "../shared/store.js";
|
|
29
31
|
import type { RunSnapshot } from "../shared/store-types.js";
|
|
30
32
|
import type { CancellationRegistry } from "../runs/background/cancellation-registry.js";
|
|
@@ -41,6 +43,7 @@ import {
|
|
|
41
43
|
} from "../intercom/result-intercom.js";
|
|
42
44
|
import { validateWorkflowModels } from "../runs/shared/model-fallback.js";
|
|
43
45
|
import { runDetached } from "../runs/background/runner.js";
|
|
46
|
+
import type { JobTracker } from "../runs/background/job-tracker.js";
|
|
44
47
|
import { classifyWorkflowFailure } from "../shared/workflow-failures.js";
|
|
45
48
|
|
|
46
49
|
// ---------------------------------------------------------------------------
|
|
@@ -78,6 +81,10 @@ export interface ExtensionRuntimeOpts {
|
|
|
78
81
|
config?: WorkflowRuntimeConfig;
|
|
79
82
|
/** Optional model catalog forwarded to workflow runs for fallback resolution. */
|
|
80
83
|
models?: WorkflowModelCatalogPort;
|
|
84
|
+
/** Job tracker forwarded to named detached runs. */
|
|
85
|
+
jobs?: JobTracker;
|
|
86
|
+
/** Invocation cwd used for workflow execution. Defaults to process.cwd(). */
|
|
87
|
+
cwd?: string;
|
|
81
88
|
}
|
|
82
89
|
|
|
83
90
|
// ---------------------------------------------------------------------------
|
|
@@ -99,13 +106,17 @@ export interface ExtensionRuntime {
|
|
|
99
106
|
* Dispatch a `list`, `inputs`, or `run` action.
|
|
100
107
|
* For `status`, `kill`, and `resume` use the runs/background/status module directly.
|
|
101
108
|
*/
|
|
102
|
-
dispatch(args: WorkflowToolArgs): Promise<WorkflowToolResult>;
|
|
109
|
+
dispatch(args: WorkflowToolArgs, options?: RuntimeDispatchOptions): Promise<WorkflowToolResult>;
|
|
103
110
|
|
|
104
111
|
/** Execute direct single/parallel/chain workflow tool modes. */
|
|
105
|
-
runDirect(args: WorkflowToolArgs): Promise<WorkflowDetails>;
|
|
112
|
+
runDirect(args: WorkflowToolArgs, options?: RuntimeDispatchOptions): Promise<WorkflowDetails>;
|
|
106
113
|
|
|
107
114
|
/** Start a linked continuation for a failed resumable named workflow run. */
|
|
108
|
-
resumeFailedRun(sourceRunId: string, stageId?: string): ResumeFailedRunResult;
|
|
115
|
+
resumeFailedRun(sourceRunId: string, stageId?: string, options?: RuntimeDispatchOptions): ResumeFailedRunResult;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface RuntimeDispatchOptions {
|
|
119
|
+
readonly policy?: WorkflowExecutionPolicy;
|
|
109
120
|
}
|
|
110
121
|
|
|
111
122
|
// ---------------------------------------------------------------------------
|
|
@@ -135,8 +146,10 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
135
146
|
const config = opts.config;
|
|
136
147
|
const intercom = opts.intercom;
|
|
137
148
|
const models = opts.models;
|
|
149
|
+
const jobs = opts.jobs;
|
|
150
|
+
const runtimeCwd = opts.cwd ?? process.cwd();
|
|
138
151
|
|
|
139
|
-
function runOptions(args: WorkflowToolArgs): RunOpts {
|
|
152
|
+
function runOptions(args: WorkflowToolArgs, policy?: WorkflowExecutionPolicy): RunOpts {
|
|
140
153
|
const argConcurrency =
|
|
141
154
|
typeof args.concurrency === "number" && Number.isFinite(args.concurrency)
|
|
142
155
|
? Math.max(1, Math.floor(args.concurrency))
|
|
@@ -160,6 +173,9 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
160
173
|
mcp,
|
|
161
174
|
config: effectiveConfig,
|
|
162
175
|
models,
|
|
176
|
+
...(policy !== undefined ? { executionMode: policy.mode } : {}),
|
|
177
|
+
registry,
|
|
178
|
+
cwd: runtimeCwd,
|
|
163
179
|
};
|
|
164
180
|
}
|
|
165
181
|
|
|
@@ -309,19 +325,25 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
309
325
|
});
|
|
310
326
|
}
|
|
311
327
|
|
|
312
|
-
function runDirectForeground(
|
|
313
|
-
|
|
328
|
+
function runDirectForeground(
|
|
329
|
+
args: WorkflowToolArgs,
|
|
330
|
+
runId?: string,
|
|
331
|
+
policy?: WorkflowExecutionPolicy,
|
|
332
|
+
): Promise<WorkflowDetails> {
|
|
333
|
+
const directRunOptions = directOptions(args);
|
|
334
|
+
const baseRunOptions = runOptions(args, policy);
|
|
314
335
|
const effectiveRunOptions = runId === undefined
|
|
315
336
|
? baseRunOptions
|
|
316
337
|
: { ...baseRunOptions, runId };
|
|
338
|
+
|
|
317
339
|
if (Array.isArray(args.chain)) {
|
|
318
|
-
return runChain(args.chain,
|
|
340
|
+
return runChain(args.chain, directRunOptions, effectiveRunOptions);
|
|
319
341
|
}
|
|
320
342
|
if (Array.isArray(args.tasks)) {
|
|
321
|
-
return runParallel(args.tasks,
|
|
343
|
+
return runParallel(args.tasks, directRunOptions, effectiveRunOptions);
|
|
322
344
|
}
|
|
323
345
|
if (args.task !== undefined && typeof args.task === "object") {
|
|
324
|
-
return runTask(args.task,
|
|
346
|
+
return runTask(args.task, directRunOptions, effectiveRunOptions);
|
|
325
347
|
}
|
|
326
348
|
throw new Error("WorkflowRuntime.runDirect: no direct execution mode supplied");
|
|
327
349
|
}
|
|
@@ -367,7 +389,7 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
367
389
|
return { ok: true, stageId: failedStageId };
|
|
368
390
|
}
|
|
369
391
|
|
|
370
|
-
function resumeFailedRun(sourceRunId: string, stageId?: string): ResumeFailedRunResult {
|
|
392
|
+
function resumeFailedRun(sourceRunId: string, stageId?: string, options?: RuntimeDispatchOptions): ResumeFailedRunResult {
|
|
371
393
|
const source = activeStore.runs().find((run) => run.id === sourceRunId);
|
|
372
394
|
if (source === undefined) {
|
|
373
395
|
return { ok: false, reason: "run_not_found", message: `run not found: ${sourceRunId}` };
|
|
@@ -385,12 +407,12 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
385
407
|
}
|
|
386
408
|
const sourceInputs = { ...source.inputs };
|
|
387
409
|
try {
|
|
388
|
-
|
|
410
|
+
resolveAndValidateInputs(def.inputs, sourceInputs, `workflow "${def.name}"`);
|
|
389
411
|
} catch (err) {
|
|
390
412
|
return { ok: false, reason: "insufficient_state", message: `insufficient_state: ${err instanceof Error ? err.message : String(err)}` };
|
|
391
413
|
}
|
|
392
414
|
const accepted = runDetached(def, sourceInputs, {
|
|
393
|
-
...runOptions({ workflow: def.name, inputs: sourceInputs }),
|
|
415
|
+
...runOptions({ workflow: def.name, inputs: sourceInputs }, options?.policy),
|
|
394
416
|
continuation: { source, resumeFromStageId: resolvedStage.stageId },
|
|
395
417
|
});
|
|
396
418
|
return {
|
|
@@ -402,7 +424,7 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
402
424
|
};
|
|
403
425
|
}
|
|
404
426
|
|
|
405
|
-
async function runDirectAsync(args: WorkflowToolArgs): Promise<WorkflowDetails> {
|
|
427
|
+
async function runDirectAsync(args: WorkflowToolArgs, policy?: WorkflowExecutionPolicy): Promise<WorkflowDetails> {
|
|
406
428
|
const runId = crypto.randomUUID();
|
|
407
429
|
const mode = directMode(args);
|
|
408
430
|
const delivery = effectiveIntercomDelivery(args, mode);
|
|
@@ -411,7 +433,7 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
411
433
|
try {
|
|
412
434
|
warnings = await validateWorkflowModels({
|
|
413
435
|
requests: directModelRequests(args),
|
|
414
|
-
catalog:
|
|
436
|
+
catalog: models,
|
|
415
437
|
});
|
|
416
438
|
} catch (error: unknown) {
|
|
417
439
|
return withIntercomSummary({
|
|
@@ -423,10 +445,10 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
423
445
|
error: classifyWorkflowFailure(error).userMessage,
|
|
424
446
|
}, delivery, parentSession);
|
|
425
447
|
}
|
|
426
|
-
const background = runDirectForeground(args, runId);
|
|
448
|
+
const background = runDirectForeground(args, runId, policy);
|
|
427
449
|
void background.then(
|
|
428
450
|
(details) => {
|
|
429
|
-
emitDirectIntercom(
|
|
451
|
+
emitDirectIntercom(details, delivery, parentSession);
|
|
430
452
|
},
|
|
431
453
|
(error: unknown) => {
|
|
432
454
|
const details: WorkflowDetails = withIntercomSummary({
|
|
@@ -455,18 +477,31 @@ export function createExtensionRuntime(opts: ExtensionRuntimeOpts = {}): Extensi
|
|
|
455
477
|
return registry;
|
|
456
478
|
},
|
|
457
479
|
|
|
458
|
-
dispatch(args: WorkflowToolArgs): Promise<WorkflowToolResult> {
|
|
459
|
-
return dispatch(args, {
|
|
480
|
+
dispatch(args: WorkflowToolArgs, options?: RuntimeDispatchOptions): Promise<WorkflowToolResult> {
|
|
481
|
+
return dispatch(args, {
|
|
482
|
+
registry,
|
|
483
|
+
adapters,
|
|
484
|
+
store: activeStore,
|
|
485
|
+
cancellation,
|
|
486
|
+
jobs,
|
|
487
|
+
persistence,
|
|
488
|
+
mcp,
|
|
489
|
+
config,
|
|
490
|
+
models,
|
|
491
|
+
policy: options?.policy,
|
|
492
|
+
cwd: runtimeCwd,
|
|
493
|
+
});
|
|
460
494
|
},
|
|
461
495
|
|
|
462
|
-
runDirect(args: WorkflowToolArgs): Promise<WorkflowDetails> {
|
|
463
|
-
|
|
464
|
-
|
|
496
|
+
runDirect(args: WorkflowToolArgs, options?: RuntimeDispatchOptions): Promise<WorkflowDetails> {
|
|
497
|
+
const policy = options?.policy ?? INTERACTIVE_WORKFLOW_POLICY;
|
|
498
|
+
if (args.async === true && policy.awaitTerminalRun !== true) {
|
|
499
|
+
return runDirectAsync(args, policy);
|
|
465
500
|
}
|
|
466
501
|
const mode = directMode(args);
|
|
467
502
|
const delivery = effectiveIntercomDelivery(args, mode);
|
|
468
503
|
const parentSession = intercomParentSession(args);
|
|
469
|
-
return runDirectForeground(args).then((details) => {
|
|
504
|
+
return runDirectForeground(args, undefined, policy).then((details) => {
|
|
470
505
|
const summarized = withIntercomSummary(details, delivery, parentSession);
|
|
471
506
|
emitDirectIntercom(summarized, delivery, parentSession);
|
|
472
507
|
return summarized;
|
|
@@ -129,7 +129,7 @@ export function createStatusWriter(
|
|
|
129
129
|
store.recordNotice({
|
|
130
130
|
id: `status-writer-error-${Date.now()}`,
|
|
131
131
|
level: "warning",
|
|
132
|
-
message: `
|
|
132
|
+
message: `atomic-workflows: status file write failed (${filePath}): ${msg}`,
|
|
133
133
|
createdAt: Date.now(),
|
|
134
134
|
});
|
|
135
135
|
}
|