@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
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ExtensionAPI, SessionWorkflowMetadata } from "@bastani/atomic";
|
|
2
|
+
import type { AgentConfig } from "../../agents/agents.ts";
|
|
3
|
+
import type { SupervisorAuthorization } from "../../intercom/supervisor-authorization.ts";
|
|
4
|
+
import type { ModelInfo } from "../../shared/model-info.ts";
|
|
5
|
+
import type { RunSyncOptions } from "../../shared/types.ts";
|
|
6
|
+
|
|
7
|
+
export interface AsyncExecutionContext {
|
|
8
|
+
pi: ExtensionAPI;
|
|
9
|
+
cwd: string;
|
|
10
|
+
currentSessionId: string;
|
|
11
|
+
currentModelProvider?: string;
|
|
12
|
+
currentModel?: string;
|
|
13
|
+
intercomGroup?: string;
|
|
14
|
+
workflowSessionMetadata?: SessionWorkflowMetadata;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface AsyncSingleParams {
|
|
18
|
+
agent: string;
|
|
19
|
+
task?: string;
|
|
20
|
+
group?: string | true;
|
|
21
|
+
agentConfig: AgentConfig;
|
|
22
|
+
ctx: AsyncExecutionContext;
|
|
23
|
+
cwd?: string;
|
|
24
|
+
maxOutput?: { bytes?: number; lines?: number };
|
|
25
|
+
artifactsDir?: string;
|
|
26
|
+
artifactConfig: {
|
|
27
|
+
enabled: boolean;
|
|
28
|
+
includeInput: boolean;
|
|
29
|
+
includeOutput: boolean;
|
|
30
|
+
includeJsonl: boolean;
|
|
31
|
+
includeMetadata: boolean;
|
|
32
|
+
cleanupDays: number;
|
|
33
|
+
};
|
|
34
|
+
shareEnabled: boolean;
|
|
35
|
+
sessionRoot?: string;
|
|
36
|
+
sessionFile?: string;
|
|
37
|
+
skills?: string[];
|
|
38
|
+
output?: string | boolean;
|
|
39
|
+
outputMode?: "inline" | "file-only";
|
|
40
|
+
progress?: boolean;
|
|
41
|
+
modelOverride?: string;
|
|
42
|
+
availableModels?: ModelInfo[];
|
|
43
|
+
knownModelProviders?: string[];
|
|
44
|
+
maxSubagentDepth: number;
|
|
45
|
+
workflowStageSubagentGuard?: boolean;
|
|
46
|
+
worktreeSetupHook?: string;
|
|
47
|
+
worktreeSetupHookTimeoutMs?: number;
|
|
48
|
+
controlConfig?: import("../../shared/types.ts").ResolvedControlConfig;
|
|
49
|
+
controlIntercomTarget?: string;
|
|
50
|
+
childIntercomTarget?: (agent: string, index: number) => string | undefined;
|
|
51
|
+
supervisorAuthorization?: SupervisorAuthorization;
|
|
52
|
+
nestedRoute?: import("../../shared/types.ts").NestedRouteInfo;
|
|
53
|
+
/** Internal seam used by focused runtime tests. */
|
|
54
|
+
testSession?: RunSyncOptions["testSession"];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface AsyncExecutionResult {
|
|
58
|
+
content: Array<{ type: "text"; text: string }>;
|
|
59
|
+
details: import("../../shared/types.ts").Details;
|
|
60
|
+
isError?: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function formatAsyncStartedMessage(headline: string): string {
|
|
64
|
+
return [
|
|
65
|
+
`Launched: ${headline}`,
|
|
66
|
+
"Completion pending; Atomic will deliver the result when the in-process child finishes.",
|
|
67
|
+
"",
|
|
68
|
+
"The async child is tied to the current parent process and does not survive parent exit.",
|
|
69
|
+
'Use subagent({ action: "status", id: "..." }) when you need the current status/result.',
|
|
70
|
+
].join("\n");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Async execution is always available because it no longer depends on a jiti child process. */
|
|
74
|
+
export function isAsyncAvailable(): boolean {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function formatAsyncStartError(mode: "single" | "parallel" | "chain", message: string): AsyncExecutionResult {
|
|
79
|
+
return {
|
|
80
|
+
content: [{ type: "text", text: message }],
|
|
81
|
+
isError: true,
|
|
82
|
+
details: { mode, results: [] },
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const UNAVAILABLE_SUBAGENT_SKILL_ERROR = "Skills not found: subagent";
|
|
87
|
+
|
|
88
|
+
export class UnavailableSubagentSkillError extends Error {}
|
|
89
|
+
export class AsyncStartValidationError extends Error {}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SubagentChildPolicy } from "@bastani/atomic";
|
|
2
|
+
|
|
3
|
+
export type ChildModePolicy = SubagentChildPolicy;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the child-mode capabilities at the in-process admission door.
|
|
7
|
+
*
|
|
8
|
+
* Every admitted child is management-restricted. Fanout is granted only when
|
|
9
|
+
* the admitted tool allowlist explicitly includes the subagent tool; an
|
|
10
|
+
* omitted allowlist cannot widen a descendant's capabilities.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveChildModePolicy(spec: {
|
|
13
|
+
readonly tools?: readonly string[];
|
|
14
|
+
readonly agent: {
|
|
15
|
+
readonly tools?: readonly string[];
|
|
16
|
+
readonly inheritProjectContext: boolean;
|
|
17
|
+
readonly inheritSkills: boolean;
|
|
18
|
+
};
|
|
19
|
+
}): ChildModePolicy {
|
|
20
|
+
const tools = spec.tools ?? spec.agent.tools;
|
|
21
|
+
return {
|
|
22
|
+
managementActions: "restricted",
|
|
23
|
+
fanoutAuthorized: tools?.includes("subagent") === true,
|
|
24
|
+
inheritProjectContext: spec.agent.inheritProjectContext,
|
|
25
|
+
inheritSkills: spec.agent.inheritSkills,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ChildIdentity } from "@bastani/atomic-natives";
|
|
2
|
+
import { createSubagentControl, type ParentContext, type SubagentControlRuntime } from "./runner.ts";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Host-local registry for the Rust control planes owned by the current Atomic
|
|
6
|
+
* session. The native registry remains authoritative for child identity and
|
|
7
|
+
* status; this map only lets management actions find the corresponding
|
|
8
|
+
* in-process runtime without a file-backed run directory.
|
|
9
|
+
*/
|
|
10
|
+
const controls = new Map<string, SubagentControlRuntime>();
|
|
11
|
+
|
|
12
|
+
export function registerSubagentControl(control: SubagentControlRuntime): void {
|
|
13
|
+
controls.set(control.parent.path, control);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getOrCreateSubagentControl(parent: ParentContext, sessionRoot: string): SubagentControlRuntime {
|
|
17
|
+
const existing = controls.get(parent.path);
|
|
18
|
+
// The control plane is parent-scoped. Parallel callers pass their per-child
|
|
19
|
+
// session directories here, but those storage paths must not split identity
|
|
20
|
+
// allocation across fresh native registries.
|
|
21
|
+
if (existing) return existing;
|
|
22
|
+
const control = createSubagentControl(parent, sessionRoot);
|
|
23
|
+
controls.set(parent.path, control);
|
|
24
|
+
return control;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function unregisterSubagentControl(control: SubagentControlRuntime): void {
|
|
28
|
+
if (controls.get(control.parent.path) === control) controls.delete(control.parent.path);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function findSubagentControl(id: string): SubagentControlRuntime | undefined {
|
|
32
|
+
const direct = controls.get(id);
|
|
33
|
+
if (direct) return direct;
|
|
34
|
+
for (const control of controls.values()) {
|
|
35
|
+
if (control.native.listChildren().some((child) => child.path === id)) return control;
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function listSubagentControls(): readonly SubagentControlRuntime[] {
|
|
41
|
+
return [...controls.values()];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function findChildIdentity(
|
|
45
|
+
id: string,
|
|
46
|
+
): { control: SubagentControlRuntime; identity: ChildIdentity } | undefined {
|
|
47
|
+
const control = findSubagentControl(id);
|
|
48
|
+
if (!control) return undefined;
|
|
49
|
+
const identity = control.native.listChildren().find((child) => child.path === id);
|
|
50
|
+
return identity ? { control, identity } : undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function clearSubagentControls(): void {
|
|
54
|
+
controls.clear();
|
|
55
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { SubagentToolResult } from "../../shared/types.ts";
|
|
2
|
+
import { findSubagentControl, listSubagentControls } from "./control-registry.ts";
|
|
3
|
+
import type { ModelCandidate } from "./runner.ts";
|
|
4
|
+
|
|
5
|
+
function canonicalChildren(control: NonNullable<ReturnType<typeof findSubagentControl>>) {
|
|
6
|
+
return [...control.listChildren()].sort((left, right) => left.path.localeCompare(right.path));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function resumeTarget(control: NonNullable<ReturnType<typeof findSubagentControl>>, id: string) {
|
|
10
|
+
if (id !== control.parent.path) return control.findChild(id);
|
|
11
|
+
const children = canonicalChildren(control);
|
|
12
|
+
return children.find((child) => child.status === "interrupted") ?? children[0];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function childLines(control: ReturnType<typeof findSubagentControl>, id?: string): string[] {
|
|
16
|
+
if (!control) return [];
|
|
17
|
+
if (id) {
|
|
18
|
+
const child = control.findChild(id);
|
|
19
|
+
if (!child) return [];
|
|
20
|
+
const delivered = control.getDeliveredResult(id);
|
|
21
|
+
return [
|
|
22
|
+
`Child: ${child.path}`,
|
|
23
|
+
`Parent: ${child.parentPath}`,
|
|
24
|
+
`Task: ${child.taskName}`,
|
|
25
|
+
`Depth: ${child.depth}`,
|
|
26
|
+
`Status: ${child.status}`,
|
|
27
|
+
`Residency: ${child.loaded ? "loaded" : "cold"}`,
|
|
28
|
+
...(delivered?.sessionFile ? [`Session: ${delivered.sessionFile}`] : []),
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
return control
|
|
32
|
+
.listChildren()
|
|
33
|
+
.map((child) => `${child.path} — ${child.status} (${child.loaded ? "loaded" : "cold"})`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function inspectInProcessChildStatus(id?: string): SubagentToolResult | undefined {
|
|
37
|
+
if (id) {
|
|
38
|
+
const control = findSubagentControl(id);
|
|
39
|
+
if (!control) return undefined;
|
|
40
|
+
const text =
|
|
41
|
+
id === control.parent.path
|
|
42
|
+
? [`Parent: ${control.parent.path}`, ...childLines(control)].join("\n")
|
|
43
|
+
: childLines(control, id).join("\n");
|
|
44
|
+
if (!text) return undefined;
|
|
45
|
+
return {
|
|
46
|
+
content: [{ type: "text", text }],
|
|
47
|
+
details: { mode: "management", results: [] },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const lines = listSubagentControls().flatMap((control) => [
|
|
51
|
+
`Parent: ${control.parent.path}`,
|
|
52
|
+
...childLines(control),
|
|
53
|
+
]);
|
|
54
|
+
if (lines.length === 0) return undefined;
|
|
55
|
+
return {
|
|
56
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
57
|
+
details: { mode: "management", results: [] },
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function interruptInProcessChild(id: string): Promise<SubagentToolResult | undefined> {
|
|
62
|
+
const control = findSubagentControl(id);
|
|
63
|
+
if (!control) return undefined;
|
|
64
|
+
const identities = canonicalChildren(control);
|
|
65
|
+
const candidates = id === control.parent.path ? identities : identities.filter((child) => child.path === id);
|
|
66
|
+
for (const child of candidates) {
|
|
67
|
+
if (await control.interruptChild(child.path)) {
|
|
68
|
+
return {
|
|
69
|
+
content: [{ type: "text", text: `Interrupt requested for in-process child ${child.path}.` }],
|
|
70
|
+
details: { mode: "management", results: [] },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
content: [{ type: "text", text: `No running in-process child found for '${id}'.` }],
|
|
76
|
+
isError: true,
|
|
77
|
+
details: { mode: "management", results: [] },
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function resumeInProcessChild(
|
|
82
|
+
id: string,
|
|
83
|
+
message: string,
|
|
84
|
+
candidate: ModelCandidate,
|
|
85
|
+
): Promise<SubagentToolResult | undefined> {
|
|
86
|
+
const control = findSubagentControl(id);
|
|
87
|
+
if (!control) return undefined;
|
|
88
|
+
const target = resumeTarget(control, id);
|
|
89
|
+
if (!target) {
|
|
90
|
+
return {
|
|
91
|
+
content: [{ type: "text", text: `No in-process child found for '${id}'.` }],
|
|
92
|
+
isError: true,
|
|
93
|
+
details: { mode: "management", results: [] },
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const outcome = await control.resumeChild(target.path, message, candidate);
|
|
97
|
+
const selection =
|
|
98
|
+
id === control.parent.path && control.listChildren().length > 1
|
|
99
|
+
? `Bare run id resolved to ${target.path}; interrupted children are preferred, then canonical path order.\n\n`
|
|
100
|
+
: "";
|
|
101
|
+
return {
|
|
102
|
+
content: [{ type: "text", text: `${selection}${outcome.envelope}` }],
|
|
103
|
+
isError: outcome.status === "error" || outcome.status === "interrupted" ? true : undefined,
|
|
104
|
+
details: { mode: "management", results: [] },
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export {
|
|
2
|
+
appendInProcessControlRequest,
|
|
3
|
+
appendInProcessControlResult,
|
|
4
|
+
appendInProcessNestedEvent,
|
|
5
|
+
clearInProcessNestedRouting,
|
|
6
|
+
hasInProcessNestedRoute,
|
|
7
|
+
interruptInProcessNestedAttempt,
|
|
8
|
+
readInProcessControlRequests,
|
|
9
|
+
readInProcessControlResults,
|
|
10
|
+
readInProcessNestedEvents,
|
|
11
|
+
registerInProcessNestedAttempt,
|
|
12
|
+
registerInProcessNestedRoute,
|
|
13
|
+
removeInProcessControlRequest,
|
|
14
|
+
resumeInProcessNestedAttempt,
|
|
15
|
+
subscribeInProcessControlRequests,
|
|
16
|
+
unregisterInProcessNestedRoute,
|
|
17
|
+
} from "./nested-routing.ts";
|
|
18
|
+
export type {
|
|
19
|
+
AdmissionRefusal,
|
|
20
|
+
AdmittedResult,
|
|
21
|
+
AttemptOutcome,
|
|
22
|
+
AttemptSignals,
|
|
23
|
+
AttemptStats,
|
|
24
|
+
ChildPolicy,
|
|
25
|
+
ChildSpec,
|
|
26
|
+
ChildStatus,
|
|
27
|
+
ContinuationReason,
|
|
28
|
+
InProcessControlRequest,
|
|
29
|
+
InProcessControlResult,
|
|
30
|
+
InProcessNestedAttemptHandle,
|
|
31
|
+
InProcessNestedResumeOutcome,
|
|
32
|
+
InProcessNestedRouteKey,
|
|
33
|
+
ModelCandidate,
|
|
34
|
+
ParentContext,
|
|
35
|
+
ResultEnvelope,
|
|
36
|
+
RunningAttempt,
|
|
37
|
+
TerminalStatus,
|
|
38
|
+
TerminationCauseName,
|
|
39
|
+
} from "./runner.ts";
|
|
40
|
+
export {
|
|
41
|
+
AdmittedChild,
|
|
42
|
+
admit_child_session,
|
|
43
|
+
continue_in_background,
|
|
44
|
+
createSubagentControl,
|
|
45
|
+
deliver_child_result,
|
|
46
|
+
reload_cold_child,
|
|
47
|
+
run_child_attempt,
|
|
48
|
+
SubagentControlRuntime,
|
|
49
|
+
terminate_child_attempt,
|
|
50
|
+
} from "./runner.ts";
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process nested routing and control registry.
|
|
3
|
+
*
|
|
4
|
+
* Routes still expose the file-backed shape for compatibility with cold starts and
|
|
5
|
+
* older sessions, but a live host registers the same route here. Live children are
|
|
6
|
+
* addressed by their run id or canonical task path, so control never needs a
|
|
7
|
+
* request file, an inherited capability-token environment variable, or a poller.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export interface InProcessNestedRouteKey {
|
|
11
|
+
readonly rootRunId: string;
|
|
12
|
+
readonly capabilityToken: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface InProcessControlRequest {
|
|
16
|
+
readonly type: "subagent.nested.control-request";
|
|
17
|
+
readonly rootRunId: string;
|
|
18
|
+
readonly capabilityToken: string;
|
|
19
|
+
readonly ts: number;
|
|
20
|
+
readonly requestId: string;
|
|
21
|
+
readonly targetRunId: string;
|
|
22
|
+
readonly action: "interrupt" | "resume";
|
|
23
|
+
readonly message?: string;
|
|
24
|
+
readonly filePath: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface InProcessControlResult {
|
|
28
|
+
readonly ts: number;
|
|
29
|
+
readonly requestId: string;
|
|
30
|
+
readonly targetRunId: string;
|
|
31
|
+
readonly ok: boolean;
|
|
32
|
+
readonly message: string;
|
|
33
|
+
readonly filePath?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface InProcessNestedResumeOutcome {
|
|
37
|
+
readonly status: "ok" | "error" | "interrupted" | "continued";
|
|
38
|
+
readonly path: string;
|
|
39
|
+
readonly sessionFile?: string;
|
|
40
|
+
readonly envelope?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface InProcessNestedAttemptHandle {
|
|
44
|
+
readonly runId: string;
|
|
45
|
+
readonly path: string;
|
|
46
|
+
readonly status: () => string;
|
|
47
|
+
readonly interrupt: () => Promise<void>;
|
|
48
|
+
readonly resume: (message: string) => Promise<InProcessNestedResumeOutcome>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface RouteState {
|
|
52
|
+
readonly key: InProcessNestedRouteKey;
|
|
53
|
+
readonly events: object[];
|
|
54
|
+
readonly controlRequests: Map<string, InProcessControlRequest>;
|
|
55
|
+
readonly controlResults: Map<string, InProcessControlResult>;
|
|
56
|
+
readonly listeners: Set<(request: InProcessControlRequest) => void | Promise<void>>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const routeStates = new Map<string, RouteState>();
|
|
60
|
+
const attemptHandles = new Map<string, Map<string, InProcessNestedAttemptHandle>>();
|
|
61
|
+
|
|
62
|
+
function routeKey(route: InProcessNestedRouteKey): string {
|
|
63
|
+
return `${route.rootRunId}\u0000${route.capabilityToken}`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function attemptKey(id: string): string {
|
|
67
|
+
return id.trim();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function stateFor(route: InProcessNestedRouteKey): RouteState | undefined {
|
|
71
|
+
return routeStates.get(routeKey(route));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function registerInProcessNestedRoute(route: InProcessNestedRouteKey): void {
|
|
75
|
+
const key = routeKey(route);
|
|
76
|
+
if (!routeStates.has(key)) {
|
|
77
|
+
routeStates.set(key, {
|
|
78
|
+
key: { rootRunId: route.rootRunId, capabilityToken: route.capabilityToken },
|
|
79
|
+
events: [],
|
|
80
|
+
controlRequests: new Map(),
|
|
81
|
+
controlResults: new Map(),
|
|
82
|
+
listeners: new Set(),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function unregisterInProcessNestedRoute(route: InProcessNestedRouteKey): void {
|
|
88
|
+
routeStates.delete(routeKey(route));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function hasInProcessNestedRoute(route: InProcessNestedRouteKey): boolean {
|
|
92
|
+
return stateFor(route) !== undefined;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function appendInProcessNestedEvent(route: InProcessNestedRouteKey, event: object): void {
|
|
96
|
+
const state = stateFor(route);
|
|
97
|
+
if (!state) return;
|
|
98
|
+
state.events.push(event);
|
|
99
|
+
if (state.events.length > 20_000) state.events.splice(0, state.events.length - 20_000);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function readInProcessNestedEvents(route: InProcessNestedRouteKey): readonly object[] {
|
|
103
|
+
return stateFor(route)?.events ?? [];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function appendInProcessControlRequest(route: InProcessNestedRouteKey, request: InProcessControlRequest): void {
|
|
107
|
+
const state = stateFor(route);
|
|
108
|
+
if (!state) return;
|
|
109
|
+
state.controlRequests.set(request.requestId, request);
|
|
110
|
+
for (const listener of state.listeners) queueMicrotask(() => void listener(request));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function readInProcessControlRequests(route: InProcessNestedRouteKey): readonly InProcessControlRequest[] {
|
|
114
|
+
return stateFor(route) ? [...stateFor(route)!.controlRequests.values()] : [];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function removeInProcessControlRequest(route: InProcessNestedRouteKey, requestId: string): void {
|
|
118
|
+
stateFor(route)?.controlRequests.delete(requestId);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function appendInProcessControlResult(route: InProcessNestedRouteKey, result: InProcessControlResult): void {
|
|
122
|
+
const state = stateFor(route);
|
|
123
|
+
if (!state) return;
|
|
124
|
+
state.controlResults.set(result.requestId, result);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function readInProcessControlResults(route: InProcessNestedRouteKey): readonly InProcessControlResult[] {
|
|
128
|
+
return stateFor(route) ? [...stateFor(route)!.controlResults.values()] : [];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function subscribeInProcessControlRequests(
|
|
132
|
+
route: InProcessNestedRouteKey,
|
|
133
|
+
listener: (request: InProcessControlRequest) => void | Promise<void>,
|
|
134
|
+
): (() => void) | undefined {
|
|
135
|
+
const state = stateFor(route);
|
|
136
|
+
if (!state) return undefined;
|
|
137
|
+
state.listeners.add(listener);
|
|
138
|
+
for (const request of state.controlRequests.values()) queueMicrotask(() => void listener(request));
|
|
139
|
+
return () => state.listeners.delete(listener);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function registerInProcessNestedAttempt(handle: InProcessNestedAttemptHandle): () => void {
|
|
143
|
+
const key = attemptKey(handle.runId);
|
|
144
|
+
let handles = attemptHandles.get(key);
|
|
145
|
+
if (!handles) {
|
|
146
|
+
handles = new Map();
|
|
147
|
+
attemptHandles.set(key, handles);
|
|
148
|
+
}
|
|
149
|
+
handles.set(handle.path, handle);
|
|
150
|
+
const pathKey = attemptKey(handle.path);
|
|
151
|
+
if (pathKey !== key) {
|
|
152
|
+
let byPath = attemptHandles.get(pathKey);
|
|
153
|
+
if (!byPath) {
|
|
154
|
+
byPath = new Map();
|
|
155
|
+
attemptHandles.set(pathKey, byPath);
|
|
156
|
+
}
|
|
157
|
+
byPath.set(handle.path, handle);
|
|
158
|
+
}
|
|
159
|
+
return () => {
|
|
160
|
+
for (const lookupKey of [key, pathKey]) {
|
|
161
|
+
const current = attemptHandles.get(lookupKey);
|
|
162
|
+
if (!current || current.get(handle.path) !== handle) continue;
|
|
163
|
+
current.delete(handle.path);
|
|
164
|
+
if (current.size === 0) attemptHandles.delete(lookupKey);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function handlesFor(id: string): InProcessNestedAttemptHandle[] {
|
|
170
|
+
return [...(attemptHandles.get(attemptKey(id))?.values() ?? [])];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface InProcessNestedControlResult {
|
|
174
|
+
readonly ok: boolean;
|
|
175
|
+
readonly message: string;
|
|
176
|
+
readonly outcome?: InProcessNestedResumeOutcome;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export async function interruptInProcessNestedAttempt(
|
|
180
|
+
targetId: string,
|
|
181
|
+
): Promise<InProcessNestedControlResult | undefined> {
|
|
182
|
+
const handles = handlesFor(targetId);
|
|
183
|
+
if (handles.length === 0) return undefined;
|
|
184
|
+
const active = handles.filter((handle) => handle.status() === "running" || handle.status() === "continued");
|
|
185
|
+
if (active.length === 0) {
|
|
186
|
+
return { ok: false, message: `Nested run ${targetId} has no active child attempt to interrupt.` };
|
|
187
|
+
}
|
|
188
|
+
await Promise.all(active.map((handle) => handle.interrupt()));
|
|
189
|
+
return { ok: true, message: `Interrupt requested for nested run ${targetId}.` };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export async function resumeInProcessNestedAttempt(
|
|
193
|
+
targetId: string,
|
|
194
|
+
message: string,
|
|
195
|
+
): Promise<InProcessNestedControlResult | undefined> {
|
|
196
|
+
const handles = handlesFor(targetId);
|
|
197
|
+
if (handles.length === 0) return undefined;
|
|
198
|
+
const handle =
|
|
199
|
+
handles.find((candidate) => candidate.status() === "interrupted" || candidate.status() === "error") ?? handles[0];
|
|
200
|
+
if (!handle) return undefined;
|
|
201
|
+
if (handle.status() === "running" || handle.status() === "continued") {
|
|
202
|
+
return { ok: false, message: `Nested run ${targetId} is still running; resume is not required.` };
|
|
203
|
+
}
|
|
204
|
+
const outcome = await handle.resume(message);
|
|
205
|
+
return {
|
|
206
|
+
ok: outcome.status === "ok" || outcome.status === "continued",
|
|
207
|
+
message:
|
|
208
|
+
outcome.status === "ok"
|
|
209
|
+
? `Reloaded nested run ${targetId} through the in-process control plane.`
|
|
210
|
+
: `Nested run ${targetId} resume ended with status '${outcome.status}'.`,
|
|
211
|
+
outcome,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function clearInProcessNestedRouting(): void {
|
|
216
|
+
routeStates.clear();
|
|
217
|
+
attemptHandles.clear();
|
|
218
|
+
}
|