@bastani/atomic 0.8.21 → 0.8.22
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 +66 -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 +20 -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 +113 -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
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import { basename } from "node:path";
|
|
25
25
|
import type { ChatMessageRenderOptions, CreateAgentSessionOptions } from "@bastani/atomic";
|
|
26
|
-
import type { StageAdapters, StageSessionRuntime } from "../runs/foreground/stage-runner.js";
|
|
26
|
+
import type { StageAdapters, StageSessionCreateResult, StageSessionRuntime } from "../runs/foreground/stage-runner.js";
|
|
27
27
|
import type { StageExecutionMeta, StageOptions } from "../shared/types.js";
|
|
28
28
|
import { stageUiBroker, type StageUiBroker } from "../shared/stage-ui-broker.js";
|
|
29
29
|
|
|
@@ -56,12 +56,12 @@ export interface RuntimeWiringSurface {
|
|
|
56
56
|
exec?: (command: string, args: string[], opts?: PiExecOpts) => Promise<PiExecResult>;
|
|
57
57
|
ui?: PiUISurface;
|
|
58
58
|
/** Test seam: inject a stub session factory instead of importing the SDK. */
|
|
59
|
-
createAgentSession?: (options?: CreateAgentSessionOptions) => Promise<
|
|
59
|
+
createAgentSession?: (options?: CreateAgentSessionOptions) => Promise<StageSessionCreateResult>;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
export interface RuntimeAdapterBuildOptions {
|
|
63
63
|
/** Test seam for SDK session creation. */
|
|
64
|
-
createAgentSession?: (options?: CreateAgentSessionOptions) => Promise<
|
|
64
|
+
createAgentSession?: (options?: CreateAgentSessionOptions) => Promise<StageSessionCreateResult>;
|
|
65
65
|
/** Broker that routes stage-local custom UI into attached workflow nodes. */
|
|
66
66
|
stageUiBroker?: StageUiBroker;
|
|
67
67
|
}
|
|
@@ -90,7 +90,9 @@ function isTestContext(): boolean {
|
|
|
90
90
|
* cross-ref: node_modules/@bastani/atomic/docs/sdk.md
|
|
91
91
|
* node_modules/@bastani/atomic/dist/core/sdk.d.ts
|
|
92
92
|
*/
|
|
93
|
-
export interface PiSdkSettingsManager {
|
|
93
|
+
export interface PiSdkSettingsManager {
|
|
94
|
+
getCodexFastModeSettings(): { readonly chat: boolean; readonly workflow: boolean };
|
|
95
|
+
}
|
|
94
96
|
export interface PiSdkResourceLoader {
|
|
95
97
|
reload(): Promise<void>;
|
|
96
98
|
}
|
|
@@ -176,17 +178,24 @@ function stageBuiltinPackagePaths(paths: readonly string[]): string[] {
|
|
|
176
178
|
|
|
177
179
|
async function createPiSdkAgentSession(
|
|
178
180
|
options?: CreateAgentSessionOptions,
|
|
179
|
-
): Promise<
|
|
181
|
+
): Promise<StageSessionCreateResult> {
|
|
180
182
|
const sdk = await import("@bastani/atomic") as PiCodingAgentSdk;
|
|
181
183
|
const sessionOptions = await prepareAtomicStageSessionOptions(options, sdk);
|
|
182
184
|
const result = await sdk.createAgentSession(sessionOptions);
|
|
183
185
|
// `CreateAgentSessionResult` is `{ session, extensionsResult, modelFallbackMessage? }`;
|
|
184
186
|
// workflow stages only consume `.session` (structurally an `AgentSession`,
|
|
185
187
|
// which is a superset of our `StageSessionRuntime` projection).
|
|
186
|
-
|
|
188
|
+
const resultSettingsManager = result.session.settingsManager;
|
|
189
|
+
const settingsManager = sessionOptions?.settingsManager ?? resultSettingsManager;
|
|
190
|
+
return {
|
|
191
|
+
session: result.session,
|
|
192
|
+
...(settingsManager?.getCodexFastModeSettings !== undefined
|
|
193
|
+
? { settingsManager }
|
|
194
|
+
: {}),
|
|
195
|
+
};
|
|
187
196
|
}
|
|
188
197
|
|
|
189
|
-
async function createTestAgentSession(_options?: CreateAgentSessionOptions): Promise<
|
|
198
|
+
async function createTestAgentSession(_options?: CreateAgentSessionOptions): Promise<StageSessionCreateResult> {
|
|
190
199
|
let lastAssistantText: string | undefined;
|
|
191
200
|
const session: StageSessionRuntime = {
|
|
192
201
|
async prompt(text: string): Promise<string> {
|
|
@@ -255,7 +264,14 @@ function withWorkflowStageSessionOptions(
|
|
|
255
264
|
): CreateAgentSessionOptions {
|
|
256
265
|
// Workflow stage sessions should never see the workflow tool, even when older
|
|
257
266
|
// meta-less callers cannot receive the richer runtime orchestration context.
|
|
258
|
-
|
|
267
|
+
// Non-interactive workflow runs also remove ask_user_question so child agents
|
|
268
|
+
// cannot block unattended automation on a prompt that no user can answer.
|
|
269
|
+
const policyExcludedTools = meta?.executionMode === "non_interactive"
|
|
270
|
+
? ["workflow", "ask_user_question"]
|
|
271
|
+
: ["workflow"];
|
|
272
|
+
const excludedTools = Array.from(
|
|
273
|
+
new Set([...(options.excludedTools ?? []), ...policyExcludedTools]),
|
|
274
|
+
);
|
|
259
275
|
return {
|
|
260
276
|
...options,
|
|
261
277
|
excludedTools,
|
|
@@ -263,6 +279,11 @@ function withWorkflowStageSessionOptions(
|
|
|
263
279
|
};
|
|
264
280
|
}
|
|
265
281
|
|
|
282
|
+
function shouldBindStageUiContext(pi: RuntimeWiringSurface, meta: StageExecutionMeta | undefined): boolean {
|
|
283
|
+
if (meta?.executionMode === "non_interactive") return false;
|
|
284
|
+
return pi.ui !== undefined || meta !== undefined;
|
|
285
|
+
}
|
|
286
|
+
|
|
266
287
|
function makeStageExtensionUiContext(
|
|
267
288
|
ui: PiUISurface,
|
|
268
289
|
meta: StageExecutionMeta | undefined,
|
|
@@ -297,7 +318,7 @@ function makeStageExtensionUiContext(
|
|
|
297
318
|
const result = await ui.custom(factory as PiCustomOverlayFactory, options ?? { overlay: true });
|
|
298
319
|
return result as T;
|
|
299
320
|
}
|
|
300
|
-
throw new Error("
|
|
321
|
+
throw new Error("atomic-workflows: ask_user_question UI is unavailable");
|
|
301
322
|
},
|
|
302
323
|
pasteToEditor: ui.pasteToEditor ?? (() => undefined),
|
|
303
324
|
setEditorText: ui.setEditorText ?? (() => undefined),
|
|
@@ -309,7 +330,7 @@ function makeStageExtensionUiContext(
|
|
|
309
330
|
theme: ui.theme,
|
|
310
331
|
getAllThemes: ui.getAllThemes ?? (() => []),
|
|
311
332
|
getTheme: ui.getTheme ?? (() => undefined),
|
|
312
|
-
setTheme: ui.setTheme ?? (() => ({ success: false, error: "
|
|
333
|
+
setTheme: ui.setTheme ?? (() => ({ success: false, error: "atomic-workflows: theme UI is unavailable" })),
|
|
313
334
|
getToolsExpanded: ui.getToolsExpanded ?? (() => false),
|
|
314
335
|
setToolsExpanded: ui.setToolsExpanded ?? (() => undefined),
|
|
315
336
|
getChatRenderSettings: ui.getChatRenderSettings ?? (() => undefined),
|
|
@@ -343,7 +364,7 @@ export function buildRuntimeAdapters(
|
|
|
343
364
|
const broker = options.stageUiBroker ?? stageUiBroker;
|
|
344
365
|
const adapters: StageAdapters = {
|
|
345
366
|
agentSession: {
|
|
346
|
-
async create(stageOptions: CreateAgentSessionOptions & Pick<StageOptions, "mcp" | "fallbackModels">, meta?: StageExecutionMeta): Promise<StageSessionRuntime> {
|
|
367
|
+
async create(stageOptions: CreateAgentSessionOptions & Pick<StageOptions, "mcp" | "fallbackModels">, meta?: StageExecutionMeta): Promise<StageSessionRuntime | StageSessionCreateResult> {
|
|
347
368
|
// Atomic's SDK handles extension / skills / prompt-template /
|
|
348
369
|
// slash-command discovery via the SettingsManager / ResourceLoader.
|
|
349
370
|
// The production default deliberately uses normal DefaultResourceLoader
|
|
@@ -357,12 +378,12 @@ export function buildRuntimeAdapters(
|
|
|
357
378
|
);
|
|
358
379
|
const result = await createSession(sessionOptions);
|
|
359
380
|
const bindable = result.session as BindableStageSession;
|
|
360
|
-
if ((pi
|
|
381
|
+
if (shouldBindStageUiContext(pi, meta) && typeof bindable.bindExtensions === "function") {
|
|
361
382
|
await bindable.bindExtensions({
|
|
362
383
|
uiContext: makeStageExtensionUiContext(pi.ui ?? {}, meta, broker),
|
|
363
384
|
});
|
|
364
385
|
}
|
|
365
|
-
return result
|
|
386
|
+
return result;
|
|
366
387
|
},
|
|
367
388
|
},
|
|
368
389
|
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared workflow module loading helpers.
|
|
3
|
+
*
|
|
4
|
+
* Discovery loads user-authored workflow files through this jiti instance so
|
|
5
|
+
* TypeScript/ESM/CJS semantics and the @bastani/workflows virtual SDK alias
|
|
6
|
+
* stay consistent.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createJiti } from "jiti/static";
|
|
10
|
+
import * as workflowsSdkSurface from "../sdk-surface.js";
|
|
11
|
+
import deepResearchCodebase from "../../builtin/deep-research-codebase.js";
|
|
12
|
+
import goal from "../../builtin/goal.js";
|
|
13
|
+
import openClaudeDesign from "../../builtin/open-claude-design.js";
|
|
14
|
+
import ralph from "../../builtin/ralph.js";
|
|
15
|
+
|
|
16
|
+
type RunWorkflowFunction = typeof import("../runs/shared/workflow-runner.js").runWorkflow;
|
|
17
|
+
|
|
18
|
+
const runWorkflow: RunWorkflowFunction = async (...args) => {
|
|
19
|
+
const { runWorkflow: actualRunWorkflow } = await import("../runs/shared/workflow-runner.js");
|
|
20
|
+
return actualRunWorkflow(...args);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const WORKFLOWS_MODULE_SPECIFIER = "@bastani/workflows";
|
|
24
|
+
const WORKFLOWS_BUILTIN_MODULE_SPECIFIER = `${WORKFLOWS_MODULE_SPECIFIER}/builtin`;
|
|
25
|
+
// Keep this in sync with index.ts through sdk-surface.ts. runWorkflow stays as
|
|
26
|
+
// a lazy wrapper because the public re-export comes from workflow-runner.ts,
|
|
27
|
+
// which imports discovery.ts and would otherwise reintroduce a cycle.
|
|
28
|
+
const WORKFLOWS_SDK_MODULE: Record<string, unknown> = {
|
|
29
|
+
...workflowsSdkSurface,
|
|
30
|
+
runWorkflow,
|
|
31
|
+
};
|
|
32
|
+
const WORKFLOWS_BUILTIN_MODULE: Record<string, unknown> = {
|
|
33
|
+
deepResearchCodebase,
|
|
34
|
+
goal,
|
|
35
|
+
openClaudeDesign,
|
|
36
|
+
ralph,
|
|
37
|
+
};
|
|
38
|
+
const WORKFLOWS_VIRTUAL_MODULES: Record<string, unknown> = {
|
|
39
|
+
[WORKFLOWS_MODULE_SPECIFIER]: WORKFLOWS_SDK_MODULE,
|
|
40
|
+
[WORKFLOWS_BUILTIN_MODULE_SPECIFIER]: WORKFLOWS_BUILTIN_MODULE,
|
|
41
|
+
[`${WORKFLOWS_BUILTIN_MODULE_SPECIFIER}/deep-research-codebase`]: { default: deepResearchCodebase },
|
|
42
|
+
[`${WORKFLOWS_BUILTIN_MODULE_SPECIFIER}/goal`]: { default: goal },
|
|
43
|
+
[`${WORKFLOWS_BUILTIN_MODULE_SPECIFIER}/open-claude-design`]: { default: openClaudeDesign },
|
|
44
|
+
[`${WORKFLOWS_BUILTIN_MODULE_SPECIFIER}/ralph`]: { default: ralph },
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const workflowModuleLoader = createJiti(import.meta.url, {
|
|
48
|
+
moduleCache: false,
|
|
49
|
+
// Keep workflow-file import semantics deterministic: jiti owns .ts/.js/.mjs/.cjs
|
|
50
|
+
// resolution instead of handing some imports back to native import().
|
|
51
|
+
tryNative: false,
|
|
52
|
+
// Resolve the @bastani/workflows SDK (and its builtin submodules) to in-memory
|
|
53
|
+
// surfaces in every runtime. This mirrors the compiled bun binary path and
|
|
54
|
+
// keeps discovery fast: aliasing the SDK to its on-disk package re-evaluated
|
|
55
|
+
// the entire SDK module graph once per workflow file (moduleCache stays false),
|
|
56
|
+
// which scaled discovery to multiple seconds on projects with many workflow
|
|
57
|
+
// files. Workflow files themselves are still evaluated fresh from disk, so
|
|
58
|
+
// `/workflow reload` continues to observe edits.
|
|
59
|
+
virtualModules: WORKFLOWS_VIRTUAL_MODULES,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
function materializeModuleObject(mod: object): Record<string, unknown> {
|
|
63
|
+
const materialized: Record<string, unknown> = {};
|
|
64
|
+
|
|
65
|
+
// jiti's callable API can return an interop namespace proxy. Its own property
|
|
66
|
+
// descriptors contain the authored export values, but property access may apply
|
|
67
|
+
// default-export conveniences (and even expose a throwing inherited `then`
|
|
68
|
+
// getter for `export default null`). Copy own descriptors into a plain object
|
|
69
|
+
// so candidate collection sees the exact authored exports.
|
|
70
|
+
for (const key of Object.getOwnPropertyNames(mod)) {
|
|
71
|
+
const descriptor = Object.getOwnPropertyDescriptor(mod, key);
|
|
72
|
+
if (descriptor === undefined) continue;
|
|
73
|
+
|
|
74
|
+
const value = "value" in descriptor ? descriptor.value : descriptor.get?.call(mod);
|
|
75
|
+
Object.defineProperty(materialized, key, {
|
|
76
|
+
value,
|
|
77
|
+
enumerable: descriptor.enumerable,
|
|
78
|
+
configurable: true,
|
|
79
|
+
writable: true,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return materialized;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function normalizeWorkflowModule(mod: unknown): Record<string, unknown> {
|
|
87
|
+
if (mod !== null && typeof mod === "object") {
|
|
88
|
+
return materializeModuleObject(mod);
|
|
89
|
+
}
|
|
90
|
+
// CJS/default interop can return the exported value directly; wrap it so the
|
|
91
|
+
// candidate collector can handle it the same way as an ESM default export.
|
|
92
|
+
return { default: mod };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface WorkflowModuleCandidate {
|
|
96
|
+
readonly value: unknown;
|
|
97
|
+
readonly exportKey: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function validateWorkflowDefinitionShape(value: unknown): string | null {
|
|
101
|
+
if (value === null || typeof value !== "object") {
|
|
102
|
+
return "export is not an object";
|
|
103
|
+
}
|
|
104
|
+
const d = value as Record<string, unknown>;
|
|
105
|
+
|
|
106
|
+
if (d["__piWorkflow"] !== true) {
|
|
107
|
+
return "missing or incorrect __piWorkflow sentinel (expected true)";
|
|
108
|
+
}
|
|
109
|
+
if (typeof d["name"] !== "string" || (d["name"] as string).trim().length === 0) {
|
|
110
|
+
return "name must be a non-empty string";
|
|
111
|
+
}
|
|
112
|
+
if (typeof d["normalizedName"] !== "string" || (d["normalizedName"] as string).trim().length === 0) {
|
|
113
|
+
return "normalizedName must be a non-empty string";
|
|
114
|
+
}
|
|
115
|
+
if (typeof d["run"] !== "function") {
|
|
116
|
+
return "run must be a function";
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function loadWorkflowModule(filePath: string): Record<string, unknown> {
|
|
122
|
+
return normalizeWorkflowModule(workflowModuleLoader(filePath));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function collectWorkflowModuleCandidates(mod: Record<string, unknown>): WorkflowModuleCandidate[] {
|
|
126
|
+
const candidates: WorkflowModuleCandidate[] = [];
|
|
127
|
+
|
|
128
|
+
// Default export first (RFC §5.12: check mod.default before named exports)
|
|
129
|
+
if ("default" in mod && mod["default"] !== undefined) {
|
|
130
|
+
candidates.push({ value: mod["default"], exportKey: "default" });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Then all named exports (a file may export multiple workflow definitions)
|
|
134
|
+
for (const [key, val] of Object.entries(mod)) {
|
|
135
|
+
if (key === "default") continue;
|
|
136
|
+
if (val !== undefined) {
|
|
137
|
+
candidates.push({ value: val, exportKey: key });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return candidates;
|
|
142
|
+
}
|
|
@@ -113,7 +113,7 @@ export const WorkflowParametersSchema = Type.Object({
|
|
|
113
113
|
Type.Literal("resume"),
|
|
114
114
|
Type.Literal("reload"),
|
|
115
115
|
], {
|
|
116
|
-
description: "Workflow action: run/list/get/inputs/status, inspect
|
|
116
|
+
description: "Workflow action: run/list/get/inputs/status, inspect stage metadata, send messages or prompt answers, pause/resume/interrupt/kill runs, or reload workflow resources. For transcript inspection, prefer status/stages/stage first to get sessionFile/transcriptPath, quote the exact path without rewriting separators (Windows backslashes are valid), then search it with rg/grep and read small ranges; transcript defaults to at most 5 recent entries and explicit tail/limit overrides that preview.",
|
|
117
117
|
})),
|
|
118
118
|
runId: Type.Optional(Type.String({
|
|
119
119
|
description: "Run identifier or unique prefix for status/stages/stage/transcript/send/pause/resume/interrupt/kill. Use '--all' or all:true for supported bulk run-control actions.",
|
|
@@ -145,14 +145,14 @@ export const WorkflowParametersSchema = Type.Object({
|
|
|
145
145
|
})),
|
|
146
146
|
limit: Type.Optional(Type.Integer({
|
|
147
147
|
minimum: 0,
|
|
148
|
-
description: "Transcript-only:
|
|
148
|
+
description: "Transcript-only: explicitly inline at most this many recent entries. Omit both limit and tail to use the default 5-entry preview plus metadata/path; prefer rg/grep on the exact quoted sessionFile/transcriptPath for targeted lookup without rewriting platform path separators.",
|
|
149
149
|
})),
|
|
150
150
|
tail: Type.Optional(Type.Integer({
|
|
151
151
|
minimum: 0,
|
|
152
|
-
description: "Transcript-only:
|
|
152
|
+
description: "Transcript-only: explicitly inline the last N entries; overrides limit. Use for quick recent-context checks after status/stages/stage expose the transcript path.",
|
|
153
153
|
})),
|
|
154
154
|
includeToolOutput: Type.Optional(Type.Boolean({
|
|
155
|
-
description: "Transcript-only: include captured tool output entries when building results from stage snapshots;
|
|
155
|
+
description: "Transcript-only: include captured tool output entries when building transcript results from stage snapshots; prefer rg/grep on the exact quoted sessionFile/transcriptPath for large outputs. Live session transcripts may not expose tool output.",
|
|
156
156
|
})),
|
|
157
157
|
text: Type.Optional(Type.String({
|
|
158
158
|
description: "Text to send to a stage for prompt answers, steering, follow-ups, or resume messages.",
|
|
@@ -11,3 +11,5 @@ export * from "./sdk-surface.js";
|
|
|
11
11
|
// discovery provides a lazy wrapper instead of importing this entry eagerly.
|
|
12
12
|
export { runWorkflow } from "./runs/shared/workflow-runner.js";
|
|
13
13
|
export type { WorkflowOptions, WorkflowRunOptions } from "./runs/shared/workflow-runner.js";
|
|
14
|
+
|
|
15
|
+
// Note: `Type` / `Static` / `TSchema` are re-exported via ./sdk-surface.js.
|
|
@@ -225,7 +225,7 @@ export function subscribeIntercomControl(
|
|
|
225
225
|
// Surface errors without breaking the event loop.
|
|
226
226
|
Promise.reject(
|
|
227
227
|
new Error(
|
|
228
|
-
`
|
|
228
|
+
`atomic-workflows: intercom callback error (type=${payload.type}): ${err instanceof Error ? err.message : String(err)}`,
|
|
229
229
|
),
|
|
230
230
|
);
|
|
231
231
|
});
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* cross-ref: spec detached-runner
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import type { WorkflowDefinition } from "../../shared/types.js";
|
|
17
|
+
import type { WorkflowDefinition, WorkflowExecutionMode, WorkflowInputValues } from "../../shared/types.js";
|
|
18
18
|
import type { RunOpts, RunResult } from "../foreground/executor.js";
|
|
19
19
|
import type { CancellationRegistry } from "./cancellation-registry.js";
|
|
20
20
|
import type { JobTracker } from "./job-tracker.js";
|
|
@@ -52,6 +52,8 @@ export interface DetachedRunOpts
|
|
|
52
52
|
* Override JobTracker (default: singleton jobTracker).
|
|
53
53
|
*/
|
|
54
54
|
jobs?: JobTracker;
|
|
55
|
+
/** Runtime execution mode for UI/prompt policy. Defaults to interactive. */
|
|
56
|
+
executionMode?: WorkflowExecutionMode;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
// ---------------------------------------------------------------------------
|
|
@@ -83,9 +85,9 @@ export function buildDetachedAccepted(
|
|
|
83
85
|
* the store remains source of truth for run status. Cancellation is wired
|
|
84
86
|
* through the provided (or default) CancellationRegistry.
|
|
85
87
|
*/
|
|
86
|
-
export function runDetached<TInputs extends
|
|
88
|
+
export function runDetached<TInputs extends WorkflowInputValues>(
|
|
87
89
|
def: WorkflowDefinition<TInputs>,
|
|
88
|
-
inputs: Record<string, unknown
|
|
90
|
+
inputs: Readonly<Record<string, unknown>>,
|
|
89
91
|
opts: DetachedRunOpts = {},
|
|
90
92
|
): DetachedAccepted {
|
|
91
93
|
const registry = opts.cancellation ?? defaultCancellationRegistry;
|
|
@@ -122,7 +124,7 @@ export function runDetached<TInputs extends Record<string, unknown>>(
|
|
|
122
124
|
signal: controller.signal,
|
|
123
125
|
cancellation: registry,
|
|
124
126
|
store,
|
|
125
|
-
usePromptNodesForUi:
|
|
127
|
+
usePromptNodesForUi: opts.executionMode !== "non_interactive",
|
|
126
128
|
deferWorkflowStart: true,
|
|
127
129
|
};
|
|
128
130
|
|
|
@@ -10,12 +10,14 @@
|
|
|
10
10
|
|
|
11
11
|
import type { Store } from "../../shared/store.js";
|
|
12
12
|
import type { RunSnapshot, RunStatus, StageSnapshot } from "../../shared/store-types.js";
|
|
13
|
-
import type { WorkflowPersistencePort } from "../../shared/types.js";
|
|
13
|
+
import type { WorkflowInputValues, WorkflowOutputValues, WorkflowPersistencePort } from "../../shared/types.js";
|
|
14
14
|
import type { CancellationRegistry } from "./cancellation-registry.js";
|
|
15
15
|
import type { StageControlRegistry } from "../foreground/stage-control-registry.js";
|
|
16
16
|
import { store as defaultStore } from "../../shared/store.js";
|
|
17
17
|
import { stageControlRegistry as defaultStageControlRegistry } from "../foreground/stage-control-registry.js";
|
|
18
18
|
import { appendRunEnd } from "../../shared/persistence-session-entries.js";
|
|
19
|
+
import { expandWorkflowGraph } from "../../shared/expanded-workflow-graph.js";
|
|
20
|
+
import { topLevelWorkflowRuns } from "../../shared/run-visibility.js";
|
|
19
21
|
|
|
20
22
|
// ---------------------------------------------------------------------------
|
|
21
23
|
// Types
|
|
@@ -76,9 +78,9 @@ export interface RunDetail {
|
|
|
76
78
|
readonly pausedDurationMs?: number;
|
|
77
79
|
readonly pausedAt?: number;
|
|
78
80
|
readonly resumedAt?: number;
|
|
79
|
-
readonly inputs: Readonly<
|
|
81
|
+
readonly inputs: Readonly<WorkflowInputValues>;
|
|
80
82
|
readonly stages: readonly RunSnapshot["stages"][number][];
|
|
81
|
-
readonly result?:
|
|
83
|
+
readonly result?: WorkflowOutputValues;
|
|
82
84
|
readonly error?: string;
|
|
83
85
|
}
|
|
84
86
|
|
|
@@ -99,13 +101,14 @@ export type InspectRunResult =
|
|
|
99
101
|
export function statusRuns(opts?: { all?: boolean; store?: Store }): RunStatusEntry[] {
|
|
100
102
|
const activeStore = opts?.store ?? defaultStore;
|
|
101
103
|
|
|
102
|
-
|
|
104
|
+
const snapshot = activeStore.snapshot();
|
|
105
|
+
return topLevelWorkflowRuns(snapshot.runs).map((run) => ({
|
|
103
106
|
runId: run.id,
|
|
104
107
|
name: run.name,
|
|
105
108
|
status: run.status,
|
|
106
109
|
startedAt: run.startedAt,
|
|
107
110
|
durationMs: run.durationMs,
|
|
108
|
-
stageCount: run.stages.length,
|
|
111
|
+
stageCount: expandWorkflowGraph(snapshot, run.id).stages.length,
|
|
109
112
|
}));
|
|
110
113
|
}
|
|
111
114
|
|
|
@@ -164,7 +167,7 @@ export function killAllRuns(opts?: {
|
|
|
164
167
|
persistence?: WorkflowPersistencePort;
|
|
165
168
|
}): KillResult[] {
|
|
166
169
|
const activeStore = opts?.store ?? defaultStore;
|
|
167
|
-
const inFlight = activeStore.runs().filter((r) => r.endedAt === undefined);
|
|
170
|
+
const inFlight = topLevelWorkflowRuns(activeStore.runs()).filter((r) => r.endedAt === undefined);
|
|
168
171
|
return inFlight.map((r) =>
|
|
169
172
|
killRun(r.id, { store: activeStore, cancellation: opts?.cancellation, persistence: opts?.persistence }),
|
|
170
173
|
);
|
|
@@ -211,24 +214,32 @@ export function resumeRun(
|
|
|
211
214
|
}
|
|
212
215
|
|
|
213
216
|
const resumed: StageSnapshot[] = [];
|
|
214
|
-
|
|
215
|
-
|
|
217
|
+
const controlRunIds = opts?.stageId ? [runId] : expandedControlRunIds(activeStore, runId);
|
|
218
|
+
const hasPausedState = controlRunIds.some((controlRunId) => {
|
|
219
|
+
const controlRun = runs.find((candidate) => candidate.id === controlRunId);
|
|
220
|
+
return controlRun?.status === "paused" || (controlRun?.stages.some((s) => s.status === "paused") ?? false);
|
|
221
|
+
});
|
|
222
|
+
if (hasPausedState) {
|
|
216
223
|
const handles = opts?.stageId
|
|
217
224
|
? [registry.get(runId, opts.stageId)].filter(
|
|
218
225
|
(h): h is NonNullable<typeof h> => h !== undefined,
|
|
219
|
-
)
|
|
220
|
-
:
|
|
226
|
+
).map((handle) => ({ controlRunId: runId, handle }))
|
|
227
|
+
: controlRunIds.flatMap((controlRunId) =>
|
|
228
|
+
registry.run(controlRunId).pausedStages().map((handle) => ({ controlRunId, handle })),
|
|
229
|
+
);
|
|
221
230
|
// Fire-and-forget the resume promise — the executor will mark each
|
|
222
231
|
// stage running once `__resume()` settles. The snapshot returned
|
|
223
232
|
// below reflects the *current* paused state; subscribers see the
|
|
224
233
|
// transition through the usual store notify path.
|
|
225
|
-
for (const handle of handles) {
|
|
234
|
+
for (const { controlRunId, handle } of handles) {
|
|
226
235
|
if (handle.status !== "paused") continue;
|
|
227
236
|
void handle.resume(opts?.message);
|
|
228
|
-
const
|
|
237
|
+
const controlRun = runs.find((candidate) => candidate.id === controlRunId);
|
|
238
|
+
const stageSnap = controlRun?.stages.find((s) => s.id === handle.stageId);
|
|
229
239
|
if (stageSnap) resumed.push(stageSnap);
|
|
240
|
+
activeStore.recordRunResumed(controlRunId);
|
|
230
241
|
}
|
|
231
|
-
if (
|
|
242
|
+
if (!opts?.stageId || resumed.length > 0) {
|
|
232
243
|
activeStore.recordRunResumed(runId);
|
|
233
244
|
}
|
|
234
245
|
}
|
|
@@ -275,6 +286,13 @@ export function resumeRun(
|
|
|
275
286
|
* stage-scoped pause when no matching handle exists with
|
|
276
287
|
* `reason: "stage_not_found"`.
|
|
277
288
|
*/
|
|
289
|
+
function expandedControlRunIds(activeStore: Store, runId: string): string[] {
|
|
290
|
+
const graph = expandWorkflowGraph(activeStore.snapshot(), runId);
|
|
291
|
+
const ids = new Set<string>([runId]);
|
|
292
|
+
for (const stage of graph.stages) ids.add(stage.workflowGraphTarget.runId);
|
|
293
|
+
return [...ids];
|
|
294
|
+
}
|
|
295
|
+
|
|
278
296
|
export function pauseRun(
|
|
279
297
|
runId: string,
|
|
280
298
|
opts?: {
|
|
@@ -315,17 +333,22 @@ export function pauseRun(
|
|
|
315
333
|
return { ok: true, runId, paused };
|
|
316
334
|
}
|
|
317
335
|
|
|
318
|
-
const
|
|
319
|
-
|
|
336
|
+
const controlRunIds = expandedControlRunIds(activeStore, runId);
|
|
337
|
+
const handles = controlRunIds.flatMap((controlRunId) =>
|
|
338
|
+
registry.run(controlRunId).stages().filter(
|
|
339
|
+
(h) => h.status === "running" || h.status === "pending",
|
|
340
|
+
).map((handle) => ({ controlRunId, handle })),
|
|
320
341
|
);
|
|
321
342
|
if (handles.length === 0) {
|
|
322
343
|
return { ok: false, runId, reason: "no_active_stages" };
|
|
323
344
|
}
|
|
324
345
|
const pausedSnaps: StageSnapshot[] = [];
|
|
325
|
-
for (const handle of handles) {
|
|
346
|
+
for (const { controlRunId, handle } of handles) {
|
|
326
347
|
void handle.pause();
|
|
327
|
-
const
|
|
348
|
+
const controlRun = activeStore.runs().find((candidate) => candidate.id === controlRunId);
|
|
349
|
+
const stageSnap = controlRun?.stages.find((s) => s.id === handle.stageId);
|
|
328
350
|
if (stageSnap) pausedSnaps.push(structuredClone(stageSnap));
|
|
351
|
+
activeStore.recordRunPaused(controlRunId);
|
|
329
352
|
}
|
|
330
353
|
activeStore.recordRunPaused(runId);
|
|
331
354
|
return { ok: true, runId, paused: pausedSnaps };
|
|
@@ -336,7 +359,7 @@ export function pauseAllRuns(opts?: {
|
|
|
336
359
|
stageControlRegistry?: StageControlRegistry;
|
|
337
360
|
}): PauseResult[] {
|
|
338
361
|
const activeStore = opts?.store ?? defaultStore;
|
|
339
|
-
const inFlight = activeStore.runs().filter((r) => r.endedAt === undefined);
|
|
362
|
+
const inFlight = topLevelWorkflowRuns(activeStore.runs()).filter((r) => r.endedAt === undefined);
|
|
340
363
|
return inFlight.map((r) =>
|
|
341
364
|
pauseRun(r.id, { store: activeStore, stageControlRegistry: opts?.stageControlRegistry }),
|
|
342
365
|
);
|
|
@@ -368,7 +391,7 @@ export function interruptAllRuns(opts?: {
|
|
|
368
391
|
stageControlRegistry?: StageControlRegistry;
|
|
369
392
|
}): InterruptRunResult[] {
|
|
370
393
|
const activeStore = opts?.store ?? defaultStore;
|
|
371
|
-
const inFlight = activeStore.runs().filter((r) => r.endedAt === undefined);
|
|
394
|
+
const inFlight = topLevelWorkflowRuns(activeStore.runs()).filter((r) => r.endedAt === undefined);
|
|
372
395
|
return inFlight.map((r) =>
|
|
373
396
|
interruptRun(r.id, { store: activeStore, stageControlRegistry: opts?.stageControlRegistry }),
|
|
374
397
|
);
|
|
@@ -401,12 +424,13 @@ export function inspectRun(
|
|
|
401
424
|
|
|
402
425
|
// Deep copy so callers cannot mutate the store via the snapshot.
|
|
403
426
|
const copy = structuredClone(candidate);
|
|
427
|
+
const expandedStages = expandWorkflowGraph(activeStore.snapshot(), copy.id).stages;
|
|
404
428
|
|
|
405
429
|
const detail: RunDetail = {
|
|
406
430
|
runId: copy.id,
|
|
407
431
|
name: copy.name,
|
|
408
432
|
status: copy.status,
|
|
409
|
-
mode:
|
|
433
|
+
mode: expandedStages.length > 1 ? "chain" : "single",
|
|
410
434
|
startedAt: copy.startedAt,
|
|
411
435
|
endedAt: copy.endedAt,
|
|
412
436
|
durationMs: copy.durationMs,
|
|
@@ -414,7 +438,7 @@ export function inspectRun(
|
|
|
414
438
|
pausedAt: copy.pausedAt,
|
|
415
439
|
resumedAt: copy.resumedAt,
|
|
416
440
|
inputs: copy.inputs,
|
|
417
|
-
stages:
|
|
441
|
+
stages: expandedStages.map((stage) => structuredClone(stage)),
|
|
418
442
|
result: copy.result,
|
|
419
443
|
error: copy.error,
|
|
420
444
|
};
|