@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.
Files changed (264) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  3. package/dist/builtin/intercom/README.md +5 -12
  4. package/dist/builtin/intercom/broker/client.ts +11 -2
  5. package/dist/builtin/intercom/contact-supervisor-tool.ts +13 -3
  6. package/dist/builtin/intercom/index-heavy.ts +13 -3
  7. package/dist/builtin/intercom/index.ts +43 -19
  8. package/dist/builtin/intercom/intercom-utils.ts +15 -29
  9. package/dist/builtin/intercom/package.json +1 -1
  10. package/dist/builtin/intercom/source-ownership.ts +9 -12
  11. package/dist/builtin/mcp/CHANGELOG.md +6 -0
  12. package/dist/builtin/mcp/README.md +3 -1
  13. package/dist/builtin/mcp/index.ts +10 -16
  14. package/dist/builtin/mcp/package.json +1 -1
  15. package/dist/builtin/mcp/startup-warmup.ts +20 -8
  16. package/dist/builtin/subagents/CHANGELOG.md +30 -0
  17. package/dist/builtin/subagents/README.md +22 -30
  18. package/dist/builtin/subagents/package.json +1 -1
  19. package/dist/builtin/subagents/src/extension/doctor.ts +1 -1
  20. package/dist/builtin/subagents/src/extension/fanout-child.ts +76 -56
  21. package/dist/builtin/subagents/src/extension/index.ts +23 -32
  22. package/dist/builtin/subagents/src/extension/startup-maintenance.ts +25 -44
  23. package/dist/builtin/subagents/src/intercom/result-intercom.ts +7 -7
  24. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +166 -434
  25. package/dist/builtin/subagents/src/runs/background/notify.ts +29 -8
  26. package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +2 -2
  27. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +4 -4
  28. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +2 -2
  29. package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +2 -2
  30. package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +1 -281
  31. package/dist/builtin/subagents/src/runs/foreground/execution-structured-retries.ts +11 -75
  32. package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +457 -0
  33. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +119 -246
  34. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +1 -1
  35. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +18 -9
  36. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +1 -1
  37. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +4 -4
  38. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +1 -646
  39. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-runtime.ts +2 -7
  40. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +5 -5
  41. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +7 -8
  42. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +14 -5
  43. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +158 -93
  44. package/dist/builtin/subagents/src/runs/inprocess/background-single.ts +179 -0
  45. package/dist/builtin/subagents/src/runs/inprocess/background.ts +89 -0
  46. package/dist/builtin/subagents/src/runs/inprocess/child-policy.ts +27 -0
  47. package/dist/builtin/subagents/src/runs/inprocess/control-registry.ts +55 -0
  48. package/dist/builtin/subagents/src/runs/inprocess/control-status.ts +106 -0
  49. package/dist/builtin/subagents/src/runs/inprocess/index.ts +50 -0
  50. package/dist/builtin/subagents/src/runs/inprocess/nested-routing.ts +218 -0
  51. package/dist/builtin/subagents/src/runs/{shared/subagent-prompt-runtime.ts → inprocess/prompt-behavior.ts} +37 -75
  52. package/dist/builtin/subagents/src/runs/inprocess/runner.ts +1138 -0
  53. package/dist/builtin/subagents/src/runs/{shared/nested-events.ts → inprocess/runtime-support/nested-api.ts} +13 -7
  54. package/dist/builtin/subagents/src/runs/{shared/nested-events-control.ts → inprocess/runtime-support/nested-control.ts} +18 -17
  55. package/dist/builtin/subagents/src/runs/{shared/nested-events-core.ts → inprocess/runtime-support/nested-core.ts} +14 -61
  56. package/dist/builtin/subagents/src/runs/{shared/nested-events-projection.ts → inprocess/runtime-support/nested-projection.ts} +4 -10
  57. package/dist/builtin/subagents/src/runs/{shared/nested-events-registry.ts → inprocess/runtime-support/nested-registry.ts} +19 -4
  58. package/dist/builtin/subagents/src/runs/{shared/nested-render.ts → inprocess/runtime-support/nested-rendering.ts} +3 -3
  59. package/dist/builtin/subagents/src/runs/{shared/nested-events-sanitize.ts → inprocess/runtime-support/nested-sanitize.ts} +3 -3
  60. package/dist/builtin/subagents/src/runs/inprocess.ts +1 -0
  61. package/dist/builtin/subagents/src/runs/shared/dynamic-fanout.ts +10 -4
  62. package/dist/builtin/subagents/src/runs/shared/model-candidate-filter.ts +0 -1
  63. package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +15 -492
  64. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +13 -11
  65. package/dist/builtin/subagents/src/runs/shared/run-history.ts +3 -5
  66. package/dist/builtin/subagents/src/runs/shared/single-output.ts +4 -4
  67. package/dist/builtin/subagents/src/runs/shared/workflow-graph.ts +5 -5
  68. package/dist/builtin/subagents/src/shared/types-async.ts +0 -1
  69. package/dist/builtin/subagents/src/shared/types-config.ts +18 -0
  70. package/dist/builtin/subagents/src/shared/types-results.ts +9 -2
  71. package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +2 -3
  72. package/dist/builtin/subagents/src/slash/slash-live-state.ts +2 -2
  73. package/dist/builtin/subagents/src/tui/render-chain-graph.ts +10 -4
  74. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +12 -11
  75. package/dist/builtin/subagents/src/tui/render-result-compact.ts +49 -12
  76. package/dist/builtin/subagents/src/tui/render-result.ts +46 -17
  77. package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -1
  78. package/dist/builtin/subagents/src/tui/render-status-progress.ts +8 -5
  79. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +0 -8
  80. package/dist/builtin/subagents/src/tui/render-widget.ts +0 -24
  81. package/dist/builtin/web-access/package.json +1 -1
  82. package/dist/builtin/workflows/CHANGELOG.md +25 -0
  83. package/dist/builtin/workflows/README.md +13 -3
  84. package/dist/builtin/workflows/package.json +1 -1
  85. package/dist/builtin/workflows/src/durable/backend.ts +7 -0
  86. package/dist/builtin/workflows/src/durable/dbos-metadata.ts +11 -1
  87. package/dist/builtin/workflows/src/durable/resume-runtime.ts +1 -0
  88. package/dist/builtin/workflows/src/durable/tool-primitive.ts +4 -28
  89. package/dist/builtin/workflows/src/durable/types.ts +5 -0
  90. package/dist/builtin/workflows/src/engine/run.ts +17 -1
  91. package/dist/builtin/workflows/src/extension/atomic-stage-session.ts +12 -39
  92. package/dist/builtin/workflows/src/extension/config-file-loader.ts +10 -1
  93. package/dist/builtin/workflows/src/extension/config-loader.ts +1 -1
  94. package/dist/builtin/workflows/src/extension/dispatcher.ts +4 -0
  95. package/dist/builtin/workflows/src/extension/index.bundle.mjs +1151 -737
  96. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +303 -38
  97. package/dist/builtin/workflows/src/extension/render-result.ts +4 -0
  98. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +6 -3
  99. package/dist/builtin/workflows/src/extension/runtime.ts +7 -1
  100. package/dist/builtin/workflows/src/extension/wiring.ts +53 -11
  101. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +12 -3
  102. package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +5 -2
  103. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +9 -7
  104. package/dist/builtin/workflows/src/extension/workflow-status-summary.ts +11 -0
  105. package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +18 -1
  106. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +10 -8
  107. package/dist/builtin/workflows/src/extension/workflow-tool.ts +9 -4
  108. package/dist/builtin/workflows/src/runs/background/quit.ts +28 -4
  109. package/dist/builtin/workflows/src/runs/background/resume-acknowledgements.ts +2 -1
  110. package/dist/builtin/workflows/src/runs/background/status.ts +55 -8
  111. package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +4 -0
  112. package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +3 -1
  113. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +1 -1
  114. package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +1 -1
  115. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +688 -38
  116. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +3 -1
  117. package/dist/builtin/workflows/src/runs/shared/model-fallback-failures.ts +19 -514
  118. package/dist/builtin/workflows/src/runs/shared/retry.ts +44 -0
  119. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +5 -0
  120. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +6 -0
  121. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +5 -1
  122. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +5 -0
  123. package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +5 -0
  124. package/dist/builtin/workflows/src/shared/persistence-restore.ts +3 -0
  125. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
  126. package/dist/builtin/workflows/src/shared/run-indicator-status.ts +75 -0
  127. package/dist/builtin/workflows/src/shared/store-public-types.ts +43 -7
  128. package/dist/builtin/workflows/src/shared/store-run-methods.ts +42 -8
  129. package/dist/builtin/workflows/src/shared/store-stage-methods.ts +31 -8
  130. package/dist/builtin/workflows/src/shared/store-types.ts +34 -0
  131. package/dist/builtin/workflows/src/shared/timing.ts +10 -0
  132. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +22 -2
  133. package/dist/builtin/workflows/src/tui/session-list.ts +1 -1
  134. package/dist/builtin/workflows/src/tui/session-overlays.ts +14 -10
  135. package/dist/builtin/workflows/src/tui/session-picker.ts +20 -4
  136. package/dist/builtin/workflows/src/tui/status-list.ts +31 -47
  137. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +9 -1
  138. package/dist/builtin/workflows/src/tui/widget.ts +16 -46
  139. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  140. package/dist/core/agent-session-auto-compaction.js +54 -11
  141. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  142. package/dist/core/agent-session-events.d.ts.map +1 -1
  143. package/dist/core/agent-session-events.js +49 -14
  144. package/dist/core/agent-session-events.js.map +1 -1
  145. package/dist/core/agent-session-methods.d.ts +13 -0
  146. package/dist/core/agent-session-methods.d.ts.map +1 -1
  147. package/dist/core/agent-session-methods.js.map +1 -1
  148. package/dist/core/agent-session-models.d.ts.map +1 -1
  149. package/dist/core/agent-session-models.js +12 -1
  150. package/dist/core/agent-session-models.js.map +1 -1
  151. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  152. package/dist/core/agent-session-prompt.js +4 -0
  153. package/dist/core/agent-session-prompt.js.map +1 -1
  154. package/dist/core/agent-session-retry.d.ts +21 -4
  155. package/dist/core/agent-session-retry.d.ts.map +1 -1
  156. package/dist/core/agent-session-retry.js +232 -106
  157. package/dist/core/agent-session-retry.js.map +1 -1
  158. package/dist/core/agent-session-state.d.ts.map +1 -1
  159. package/dist/core/agent-session-state.js +2 -1
  160. package/dist/core/agent-session-state.js.map +1 -1
  161. package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
  162. package/dist/core/agent-session-tool-hooks.js +12 -0
  163. package/dist/core/agent-session-tool-hooks.js.map +1 -1
  164. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  165. package/dist/core/agent-session-tool-registry.js +1 -1
  166. package/dist/core/agent-session-tool-registry.js.map +1 -1
  167. package/dist/core/agent-session-types.d.ts +3 -1
  168. package/dist/core/agent-session-types.d.ts.map +1 -1
  169. package/dist/core/agent-session-types.js.map +1 -1
  170. package/dist/core/agent-session.d.ts +12 -1
  171. package/dist/core/agent-session.d.ts.map +1 -1
  172. package/dist/core/agent-session.js +7 -0
  173. package/dist/core/agent-session.js.map +1 -1
  174. package/dist/core/extensions/context-types.d.ts +25 -0
  175. package/dist/core/extensions/context-types.d.ts.map +1 -1
  176. package/dist/core/extensions/context-types.js.map +1 -1
  177. package/dist/core/extensions/index.d.ts +1 -1
  178. package/dist/core/extensions/index.d.ts.map +1 -1
  179. package/dist/core/extensions/index.js.map +1 -1
  180. package/dist/core/extensions/runner-context.d.ts +2 -1
  181. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  182. package/dist/core/extensions/runner-context.js +4 -0
  183. package/dist/core/extensions/runner-context.js.map +1 -1
  184. package/dist/core/extensions/runner.d.ts +3 -2
  185. package/dist/core/extensions/runner.d.ts.map +1 -1
  186. package/dist/core/extensions/runner.js +3 -1
  187. package/dist/core/extensions/runner.js.map +1 -1
  188. package/dist/core/model-fallback-failures.d.ts +30 -0
  189. package/dist/core/model-fallback-failures.d.ts.map +1 -0
  190. package/dist/core/model-fallback-failures.js +610 -0
  191. package/dist/core/model-fallback-failures.js.map +1 -0
  192. package/dist/core/retry-policy.d.ts +30 -0
  193. package/dist/core/retry-policy.d.ts.map +1 -0
  194. package/dist/core/retry-policy.js +25 -0
  195. package/dist/core/retry-policy.js.map +1 -0
  196. package/dist/core/sdk-types.d.ts +8 -2
  197. package/dist/core/sdk-types.d.ts.map +1 -1
  198. package/dist/core/sdk-types.js.map +1 -1
  199. package/dist/core/sdk.d.ts.map +1 -1
  200. package/dist/core/sdk.js +6 -1
  201. package/dist/core/sdk.js.map +1 -1
  202. package/dist/core/session-manager-core.d.ts +2 -0
  203. package/dist/core/session-manager-core.d.ts.map +1 -1
  204. package/dist/core/session-manager-core.js +7 -0
  205. package/dist/core/session-manager-core.js.map +1 -1
  206. package/dist/index-extensions.d.ts +1 -1
  207. package/dist/index-extensions.d.ts.map +1 -1
  208. package/dist/index-extensions.js.map +1 -1
  209. package/dist/index.d.ts +3 -0
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/index.js +2 -0
  212. package/dist/index.js.map +1 -1
  213. package/docs/intercom.md +5 -10
  214. package/docs/settings.md +7 -1
  215. package/docs/subagents.md +19 -19
  216. package/docs/workflows.md +21 -5
  217. package/examples/extensions/gondolin/package-lock.json +3 -3
  218. package/npm-shrinkwrap.json +29 -29
  219. package/package.json +2 -2
  220. package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +0 -112
  221. package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +0 -543
  222. package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +0 -140
  223. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +0 -279
  224. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +0 -99
  225. package/dist/builtin/subagents/src/runs/background/async-execution.ts +0 -17
  226. package/dist/builtin/subagents/src/runs/background/async-resume.ts +0 -402
  227. package/dist/builtin/subagents/src/runs/background/async-status.ts +0 -411
  228. package/dist/builtin/subagents/src/runs/background/completion-claims.ts +0 -196
  229. package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +0 -102
  230. package/dist/builtin/subagents/src/runs/background/parallel-groups.ts +0 -59
  231. package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +0 -300
  232. package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +0 -166
  233. package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +0 -77
  234. package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +0 -48
  235. package/dist/builtin/subagents/src/runs/background/result-status.ts +0 -87
  236. package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +0 -72
  237. package/dist/builtin/subagents/src/runs/background/result-watcher.ts +0 -320
  238. package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +0 -105
  239. package/dist/builtin/subagents/src/runs/background/run-status.ts +0 -358
  240. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +0 -457
  241. package/dist/builtin/subagents/src/runs/background/subagent-runner-dynamic.ts +0 -376
  242. package/dist/builtin/subagents/src/runs/background/subagent-runner-finalize.ts +0 -150
  243. package/dist/builtin/subagents/src/runs/background/subagent-runner-output.ts +0 -109
  244. package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel-helpers.ts +0 -128
  245. package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel.ts +0 -309
  246. package/dist/builtin/subagents/src/runs/background/subagent-runner-sequential.ts +0 -173
  247. package/dist/builtin/subagents/src/runs/background/subagent-runner-state.ts +0 -578
  248. package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +0 -330
  249. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +0 -330
  250. package/dist/builtin/subagents/src/runs/background/subagent-runner-types.ts +0 -210
  251. package/dist/builtin/subagents/src/runs/background/subagent-runner-utils.ts +0 -69
  252. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +0 -90
  253. package/dist/builtin/subagents/src/runs/background/top-level-async.ts +0 -12
  254. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-control.ts +0 -140
  255. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +0 -108
  256. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-types.ts +0 -17
  257. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +0 -558
  258. package/dist/builtin/subagents/src/runs/shared/attempt-watchdog.ts +0 -126
  259. package/dist/builtin/subagents/src/runs/shared/final-drain.ts +0 -39
  260. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +0 -339
  261. package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +0 -165
  262. package/dist/builtin/subagents/src/runs/shared/spawn-env.ts +0 -21
  263. package/dist/builtin/subagents/src/shared/post-exit-stdio-guard.ts +0 -86
  264. /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
+ }