@bastani/atomic 0.9.13-alpha.2 → 0.9.13-alpha.3

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 (255) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +1 -1
  3. package/dist/builtin/i-have-adhd/package.json +1 -1
  4. package/dist/builtin/intercom/CHANGELOG.md +14 -0
  5. package/dist/builtin/intercom/README.md +12 -12
  6. package/dist/builtin/intercom/incoming-message-delivery.ts +1 -1
  7. package/dist/builtin/intercom/index.ts +1 -1
  8. package/dist/builtin/intercom/intercom-tool.ts +1 -1
  9. package/dist/builtin/intercom/intercom-utils.ts +3 -6
  10. package/dist/builtin/intercom/package.json +1 -1
  11. package/dist/builtin/intercom/result-renderers.ts +1 -1
  12. package/dist/builtin/intercom/session-target.ts +1 -15
  13. package/dist/builtin/intercom/skills/intercom/SKILL.md +6 -6
  14. package/dist/builtin/intercom/terminal-ordering-barrier.ts +2 -2
  15. package/dist/builtin/intercom/ui/inline-message.ts +7 -5
  16. package/dist/builtin/intercom/ui/session-list.ts +23 -10
  17. package/dist/builtin/mcp/package.json +1 -1
  18. package/dist/builtin/subagents/CHANGELOG.md +19 -0
  19. package/dist/builtin/subagents/README.md +29 -73
  20. package/dist/builtin/subagents/package.json +2 -2
  21. package/dist/builtin/subagents/prompts/parallel-cleanup.md +1 -1
  22. package/dist/builtin/subagents/prompts/parallel-review.md +1 -1
  23. package/dist/builtin/subagents/prompts/review-loop.md +2 -2
  24. package/dist/builtin/subagents/skills/subagent/SKILL.md +23 -59
  25. package/dist/builtin/subagents/skills/tmux/SKILL.md +1 -1
  26. package/dist/builtin/subagents/src/extension/control-notices.ts +2 -3
  27. package/dist/builtin/subagents/src/extension/doctor.ts +2 -14
  28. package/dist/builtin/subagents/src/extension/fanout-child.ts +1 -17
  29. package/dist/builtin/subagents/src/extension/index.ts +9 -70
  30. package/dist/builtin/subagents/src/extension/notification-content.ts +1 -1
  31. package/dist/builtin/subagents/src/extension/prompt-guidance.ts +2 -2
  32. package/dist/builtin/subagents/src/extension/schemas.ts +2 -8
  33. package/dist/builtin/subagents/src/extension/tool-description.ts +2 -3
  34. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +1 -1
  35. package/dist/builtin/subagents/src/intercom/result-intercom.ts +5 -46
  36. package/dist/builtin/subagents/src/runs/{background → foreground}/completion-notification.ts +2 -2
  37. package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +25 -88
  38. package/dist/builtin/subagents/src/runs/{background → foreground}/notify.ts +5 -5
  39. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +11 -28
  40. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +3 -0
  41. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +2 -0
  42. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-runtime.ts +0 -5
  43. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +30 -20
  44. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +4 -4
  45. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +0 -13
  46. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +104 -48
  47. package/dist/builtin/subagents/src/runs/inprocess/index.ts +1 -1
  48. package/dist/builtin/subagents/src/runs/inprocess/runner.ts +5 -5
  49. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-api.ts +0 -7
  50. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-core.ts +0 -10
  51. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-projection.ts +3 -108
  52. package/dist/builtin/subagents/src/runs/inprocess/runtime-support/nested-sanitize.ts +0 -4
  53. package/dist/builtin/subagents/src/runs/shared/subagent-control.ts +1 -1
  54. package/dist/builtin/subagents/src/shared/formatters.ts +3 -5
  55. package/dist/builtin/subagents/src/shared/model-resolution.ts +78 -0
  56. package/dist/builtin/subagents/src/shared/status-format.ts +4 -11
  57. package/dist/builtin/subagents/src/shared/types-config.ts +10 -9
  58. package/dist/builtin/subagents/src/shared/types-nested.ts +127 -0
  59. package/dist/builtin/subagents/src/shared/types-results.ts +2 -8
  60. package/dist/builtin/subagents/src/shared/types-runtime.ts +0 -9
  61. package/dist/builtin/subagents/src/shared/types.ts +1 -1
  62. package/dist/builtin/subagents/src/shared/utils.ts +1 -109
  63. package/dist/builtin/subagents/src/slash/slash-commands.ts +7 -17
  64. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +2 -252
  65. package/dist/builtin/subagents/src/tui/render-layout.ts +4 -4
  66. package/dist/builtin/subagents/src/tui/render-result.ts +0 -9
  67. package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -34
  68. package/dist/builtin/subagents/src/tui/render.ts +0 -2
  69. package/dist/builtin/web-access/package.json +1 -1
  70. package/dist/builtin/workflows/CHANGELOG.md +12 -0
  71. package/dist/builtin/workflows/README.md +3 -3
  72. package/dist/builtin/workflows/package.json +1 -1
  73. package/dist/builtin/workflows/src/durable/backend.ts +11 -0
  74. package/dist/builtin/workflows/src/durable/completed-catalog-stage-groups.ts +63 -25
  75. package/dist/builtin/workflows/src/durable/completed-catalog.ts +166 -25
  76. package/dist/builtin/workflows/src/durable/dbos-backend.ts +42 -24
  77. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +2 -1
  78. package/dist/builtin/workflows/src/durable/run-timing.ts +28 -7
  79. package/dist/builtin/workflows/src/durable/scoped-backend.ts +4 -0
  80. package/dist/builtin/workflows/src/durable/targeted-inspection.ts +110 -0
  81. package/dist/builtin/workflows/src/engine/run-durable-stage-session.ts +2 -2
  82. package/dist/builtin/workflows/src/engine/runtime.ts +19 -2
  83. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +3 -0
  84. package/dist/builtin/workflows/src/extension/index.bundle.mjs +680 -152
  85. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +6 -0
  86. package/dist/builtin/workflows/src/extension/ui-surface.ts +2 -0
  87. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +6 -1
  88. package/dist/builtin/workflows/src/extension/workflow-targets.ts +18 -10
  89. package/dist/builtin/workflows/src/extension/workflow-tool-inspection.ts +31 -16
  90. package/dist/builtin/workflows/src/extension/workflow-tool-send.ts +75 -3
  91. package/dist/builtin/workflows/src/extension/workflow-tool.ts +53 -6
  92. package/dist/builtin/workflows/src/runs/background/run-inspect.ts +5 -1
  93. package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +94 -60
  94. package/dist/builtin/workflows/src/runs/foreground/executor-stage-context.ts +1 -1
  95. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +7 -7
  96. package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +25 -4
  97. package/dist/builtin/workflows/src/runs/foreground/executor-stage-types.ts +4 -1
  98. package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +2 -0
  99. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +142 -4
  100. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +2 -0
  101. package/dist/builtin/workflows/src/runs/foreground/stage-session-heartbeat.ts +88 -0
  102. package/dist/builtin/workflows/src/tui/run-detail.ts +25 -12
  103. package/dist/builtin/workflows/src/tui/workflow-resume-selector.ts +1 -0
  104. package/dist/core/agent-session-events.d.ts.map +1 -1
  105. package/dist/core/agent-session-events.js +16 -5
  106. package/dist/core/agent-session-events.js.map +1 -1
  107. package/dist/core/agent-session-export.d.ts.map +1 -1
  108. package/dist/core/agent-session-export.js +2 -1
  109. package/dist/core/agent-session-export.js.map +1 -1
  110. package/dist/core/agent-session-methods.d.ts +8 -4
  111. package/dist/core/agent-session-methods.d.ts.map +1 -1
  112. package/dist/core/agent-session-methods.js.map +1 -1
  113. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  114. package/dist/core/agent-session-prompt.js +5 -0
  115. package/dist/core/agent-session-prompt.js.map +1 -1
  116. package/dist/core/agent-session-summary.d.ts +21 -0
  117. package/dist/core/agent-session-summary.d.ts.map +1 -0
  118. package/dist/core/agent-session-summary.js +156 -0
  119. package/dist/core/agent-session-summary.js.map +1 -0
  120. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  121. package/dist/core/agent-session-tool-registry.js +0 -4
  122. package/dist/core/agent-session-tool-registry.js.map +1 -1
  123. package/dist/core/agent-session-transfer.d.ts.map +1 -1
  124. package/dist/core/agent-session-transfer.js +0 -2
  125. package/dist/core/agent-session-transfer.js.map +1 -1
  126. package/dist/core/agent-session-tree.d.ts.map +1 -1
  127. package/dist/core/agent-session-tree.js +6 -0
  128. package/dist/core/agent-session-tree.js.map +1 -1
  129. package/dist/core/agent-session.d.ts +7 -3
  130. package/dist/core/agent-session.d.ts.map +1 -1
  131. package/dist/core/agent-session.js +8 -5
  132. package/dist/core/agent-session.js.map +1 -1
  133. package/dist/core/atomic-guide-command.js +2 -2
  134. package/dist/core/atomic-guide-command.js.map +1 -1
  135. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  136. package/dist/core/compaction/branch-summarization.js +1 -0
  137. package/dist/core/compaction/branch-summarization.js.map +1 -1
  138. package/dist/core/compaction/index.d.ts +1 -0
  139. package/dist/core/compaction/index.d.ts.map +1 -1
  140. package/dist/core/compaction/index.js +1 -0
  141. package/dist/core/compaction/index.js.map +1 -1
  142. package/dist/core/compaction/session-summarization.d.ts +41 -0
  143. package/dist/core/compaction/session-summarization.d.ts.map +1 -0
  144. package/dist/core/compaction/session-summarization.js +97 -0
  145. package/dist/core/compaction/session-summarization.js.map +1 -0
  146. package/dist/core/extensions/ui-types.d.ts +2 -0
  147. package/dist/core/extensions/ui-types.d.ts.map +1 -1
  148. package/dist/core/extensions/ui-types.js.map +1 -1
  149. package/dist/core/session-manager-core.d.ts +3 -1
  150. package/dist/core/session-manager-core.d.ts.map +1 -1
  151. package/dist/core/session-manager-core.js +9 -1
  152. package/dist/core/session-manager-core.js.map +1 -1
  153. package/dist/core/session-manager-entries.d.ts +24 -1
  154. package/dist/core/session-manager-entries.d.ts.map +1 -1
  155. package/dist/core/session-manager-entries.js +48 -0
  156. package/dist/core/session-manager-entries.js.map +1 -1
  157. package/dist/core/session-manager-list.d.ts.map +1 -1
  158. package/dist/core/session-manager-list.js +10 -0
  159. package/dist/core/session-manager-list.js.map +1 -1
  160. package/dist/core/session-manager-types.d.ts +10 -1
  161. package/dist/core/session-manager-types.d.ts.map +1 -1
  162. package/dist/core/session-manager-types.js.map +1 -1
  163. package/dist/core/settings-manager-basic-accessors.d.ts +3 -0
  164. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  165. package/dist/core/settings-manager-basic-accessors.js +5 -0
  166. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  167. package/dist/core/settings-manager.d.ts +1 -1
  168. package/dist/core/settings-manager.d.ts.map +1 -1
  169. package/dist/core/settings-manager.js.map +1 -1
  170. package/dist/core/settings-types.d.ts +4 -0
  171. package/dist/core/settings-types.d.ts.map +1 -1
  172. package/dist/core/settings-types.js.map +1 -1
  173. package/dist/core/slash-commands.js +2 -2
  174. package/dist/core/slash-commands.js.map +1 -1
  175. package/dist/core/tools/bash.d.ts +0 -15
  176. package/dist/core/tools/bash.d.ts.map +1 -1
  177. package/dist/core/tools/bash.js +3 -81
  178. package/dist/core/tools/bash.js.map +1 -1
  179. package/dist/core/tools/fetch-url.d.ts +12 -0
  180. package/dist/core/tools/fetch-url.d.ts.map +1 -1
  181. package/dist/core/tools/fetch-url.js +76 -10
  182. package/dist/core/tools/fetch-url.js.map +1 -1
  183. package/dist/core/tools/index.js +4 -4
  184. package/dist/core/tools/index.js.map +1 -1
  185. package/dist/core/tools/session-temp-dir.d.ts +2 -2
  186. package/dist/core/tools/session-temp-dir.d.ts.map +1 -1
  187. package/dist/core/tools/session-temp-dir.js +6 -7
  188. package/dist/core/tools/session-temp-dir.js.map +1 -1
  189. package/dist/core/usage-totals.js +1 -1
  190. package/dist/core/usage-totals.js.map +1 -1
  191. package/dist/modes/interactive/components/footer.js +1 -1
  192. package/dist/modes/interactive/components/footer.js.map +1 -1
  193. package/dist/modes/interactive/components/host-session-picker.d.ts.map +1 -1
  194. package/dist/modes/interactive/components/host-session-picker.js +1 -0
  195. package/dist/modes/interactive/components/host-session-picker.js.map +1 -1
  196. package/dist/modes/interactive/components/session-selector-list.d.ts.map +1 -1
  197. package/dist/modes/interactive/components/session-selector-list.js +29 -4
  198. package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
  199. package/dist/modes/interactive/components/session-selector-search.js +1 -1
  200. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  201. package/dist/modes/interactive/components/tree-selector-content.d.ts.map +1 -1
  202. package/dist/modes/interactive/components/tree-selector-content.js +6 -0
  203. package/dist/modes/interactive/components/tree-selector-content.js.map +1 -1
  204. package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
  205. package/dist/modes/interactive-engine/protocol.js +4 -1
  206. package/dist/modes/interactive-engine/protocol.js.map +1 -1
  207. package/docs/environment-variables.md +1 -1
  208. package/docs/intercom.md +20 -21
  209. package/docs/quickstart.md +5 -1
  210. package/docs/sdk.md +1 -1
  211. package/docs/session-format.md +15 -0
  212. package/docs/sessions.md +8 -0
  213. package/docs/settings.md +6 -0
  214. package/docs/subagents.md +19 -31
  215. package/docs/tools.md +3 -5
  216. package/docs/usage.md +1 -1
  217. package/docs/windows.md +1 -1
  218. package/docs/workflows.md +60 -32
  219. package/npm-shrinkwrap.json +29 -29
  220. package/package.json +2 -2
  221. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +0 -331
  222. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +0 -161
  223. package/dist/builtin/subagents/src/runs/inprocess/background-single.ts +0 -195
  224. package/dist/builtin/subagents/src/runs/inprocess/background.ts +0 -90
  225. package/dist/builtin/subagents/src/shared/types-async.ts +0 -247
  226. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +0 -217
  227. package/dist/builtin/subagents/src/tui/render-widget.ts +0 -366
  228. package/dist/core/async/format.d.ts +0 -3
  229. package/dist/core/async/format.d.ts.map +0 -1
  230. package/dist/core/async/format.js +0 -52
  231. package/dist/core/async/format.js.map +0 -1
  232. package/dist/core/async/job-manager.d.ts +0 -40
  233. package/dist/core/async/job-manager.d.ts.map +0 -1
  234. package/dist/core/async/job-manager.js +0 -293
  235. package/dist/core/async/job-manager.js.map +0 -1
  236. package/dist/core/async/session-manager.d.ts +0 -16
  237. package/dist/core/async/session-manager.d.ts.map +0 -1
  238. package/dist/core/async/session-manager.js +0 -34
  239. package/dist/core/async/session-manager.js.map +0 -1
  240. package/dist/core/async/types.d.ts +0 -23
  241. package/dist/core/async/types.d.ts.map +0 -1
  242. package/dist/core/async/types.js +0 -2
  243. package/dist/core/async/types.js.map +0 -1
  244. package/dist/core/tools/bash-async-execution.d.ts +0 -27
  245. package/dist/core/tools/bash-async-execution.d.ts.map +0 -1
  246. package/dist/core/tools/bash-async-execution.js +0 -81
  247. package/dist/core/tools/bash-async-execution.js.map +0 -1
  248. package/dist/core/tools/bash-async-jobs.d.ts +0 -30
  249. package/dist/core/tools/bash-async-jobs.d.ts.map +0 -1
  250. package/dist/core/tools/bash-async-jobs.js +0 -87
  251. package/dist/core/tools/bash-async-jobs.js.map +0 -1
  252. package/dist/core/tools/bash-async-output.d.ts +0 -13
  253. package/dist/core/tools/bash-async-output.d.ts.map +0 -1
  254. package/dist/core/tools/bash-async-output.js +0 -122
  255. package/dist/core/tools/bash-async-output.js.map +0 -1
@@ -199,6 +199,11 @@ export async function runSingleInProcess(
199
199
  return noSpawnableCandidatesResult(agent, task, filteredCandidates.skippedAttempts);
200
200
  const candidate = filteredCandidates.candidates[0];
201
201
  const fallbackCandidates = filteredCandidates.candidates.slice(1);
202
+ // The candidate is only a string. `createAgentSession` selects a model from a
203
+ // `Model<Api>` object and otherwise restores the model persisted in the
204
+ // session file — which, for a fork-context child, is the parent's model.
205
+ // Resolving the candidate here is what makes the agent's configured model win.
206
+ const resolvedCandidate = candidate ? options.resolveCandidateModel?.(candidate) : undefined;
202
207
  const fastModeSettings = getSubagentCodexFastModeSettings(cwd);
203
208
  const orchestrationContext = workflowOrchestrationContext(options);
204
209
  const fastModeScope = resolveSubagentCodexFastModeScope(
@@ -248,8 +253,8 @@ export async function runSingleInProcess(
248
253
  tools: agent.tools,
249
254
  mcpDirectTools: agent.mcpDirectTools,
250
255
  skills: options.skills ?? agent.skills,
251
- model: undefined,
252
- thinkingLevel: agent.thinking as ChildSpec["thinkingLevel"],
256
+ model: resolvedCandidate?.model,
257
+ thinkingLevel: (resolvedCandidate?.thinkingLevel ?? agent.thinking) as ChildSpec["thinkingLevel"],
253
258
  parent,
254
259
  intercom: options.orchestratorIntercomTarget
255
260
  ? {
@@ -305,14 +310,14 @@ export async function runSingleInProcess(
305
310
  const neverAbort = new AbortController().signal;
306
311
  const running = control.startAttempt(
307
312
  admission.admitted,
308
- { modelId: candidate, thinkingLevel: spec.thinkingLevel },
313
+ { model: resolvedCandidate?.model, modelId: candidate, thinkingLevel: spec.thinkingLevel },
309
314
  {
310
315
  abort: options.signal ?? neverAbort,
311
316
  interrupt: options.interruptSignal ?? neverAbort,
312
317
  },
313
318
  { fastModeForModel },
314
319
  );
315
- if (options.onUpdate && !options.backgroundContinuation) {
320
+ if (options.onUpdate) {
316
321
  const launchModel = running.currentModel ?? candidate;
317
322
  spec.onProgress?.({
318
323
  index: options.index ?? 0,
@@ -330,79 +335,11 @@ export async function runSingleInProcess(
330
335
  lastActivityAt: Date.now(),
331
336
  });
332
337
  }
333
- control.registerNestedAttempt(options.runId, running, { modelId: candidate, thinkingLevel: spec.thinkingLevel });
334
- if (options.backgroundContinuation) {
335
- control.continueInBackground(running, "async-requested");
336
- void running.promise.then(
337
- async (backgroundOutcome) => {
338
- const recovered = resultFromOutcome(agent, task, backgroundOutcome, startedAt, artifactPaths, {
339
- cwd,
340
- settings: fastModeSettings,
341
- scope: fastModeScope,
342
- });
343
- await control.deliverChildResult(
344
- {
345
- path: backgroundOutcome.path,
346
- status: backgroundOutcome.status,
347
- ...(backgroundOutcome.status === "error" ? { cause: backgroundOutcome.cause } : {}),
348
- stats: backgroundOutcome.stats,
349
- envelope: backgroundOutcome.envelope,
350
- ...(recovered.model === undefined ? {} : { model: recovered.model }),
351
- ...(recovered.thinking === undefined ? {} : { thinking: recovered.thinking }),
352
- ...(recovered.fastMode ? { fastMode: true } : {}),
353
- sessionFile: backgroundOutcome.sessionFile,
354
- timestamp: Date.now(),
355
- artifactsDir: options.artifactsDir,
356
- },
357
- { artifactsDir: options.artifactsDir, artifactPaths, artifactsDisabled, maxOutput: options.maxOutput },
358
- );
359
- const delivered = control.getDeliveredResult(backgroundOutcome.path);
360
- if (delivered) {
361
- recovered.envelope = delivered.envelope;
362
- recovered.finalOutput = delivered.envelope;
363
- }
364
- options.onDetachedExit?.(recovered);
365
- },
366
- () => undefined,
367
- );
368
- const continuedModel = running.currentModel ?? candidate;
369
- const continuedFastMode = fastModeForModel(continuedModel);
370
- const continuedThinking = running.currentThinking;
371
- const continuedResult: SingleResult = {
372
- agent: agent.name,
373
- task,
374
- status: "continued",
375
- path: admission.admitted.identity.path,
376
- envelope: "Child continued in background.",
377
- detached: true,
378
- detachedReason: "async-requested",
379
- messages: [],
380
- usage: emptyUsage(),
381
- ...(continuedModel === undefined ? {} : { model: continuedModel }),
382
- ...(continuedThinking === undefined ? {} : { thinking: continuedThinking }),
383
- ...(continuedFastMode ? { fastMode: true } : {}),
384
- progress: {
385
- index: options.index ?? 0,
386
- agent: agent.name,
387
- status: "running",
388
- task,
389
- ...(continuedModel === undefined ? {} : { model: continuedModel }),
390
- ...(continuedThinking === undefined ? {} : { thinking: continuedThinking }),
391
- ...(continuedFastMode ? { fastMode: true } : {}),
392
- recentTools: [],
393
- recentOutput: [],
394
- toolCount: 0,
395
- tokens: 0,
396
- durationMs: Math.max(0, Date.now() - startedAt),
397
- lastActivityAt: Date.now(),
398
- },
399
- };
400
- options.onUpdate?.({
401
- content: [{ type: "text", text: continuedResult.envelope ?? "" }],
402
- details: { mode: "single", runId: options.runId, results: [continuedResult] } satisfies Details,
403
- });
404
- return continuedResult;
405
- }
338
+ control.registerNestedAttempt(options.runId, running, {
339
+ model: resolvedCandidate?.model,
340
+ modelId: candidate,
341
+ thinkingLevel: spec.thinkingLevel,
342
+ });
406
343
  let detached = false;
407
344
  let resolveContinuation!: () => void;
408
345
  const continuation = new Promise<void>((resolve) => {
@@ -414,7 +351,7 @@ export async function runSingleInProcess(
414
351
  detach: () => {
415
352
  if (detached) return;
416
353
  detached = true;
417
- control.continueInBackground(running, "intercom-coordination");
354
+ control.continueDetached(running, "intercom-coordination");
418
355
  resolveContinuation();
419
356
  },
420
357
  });
@@ -422,29 +359,29 @@ export async function runSingleInProcess(
422
359
  const winner = await Promise.race([terminal, continuation.then(() => ({ kind: "continued" as const }))]);
423
360
  if (winner.kind === "continued") {
424
361
  detachCleanup();
425
- void running.promise.then(async (backgroundOutcome) => {
426
- const recovered = resultFromOutcome(agent, task, backgroundOutcome, startedAt, artifactPaths, {
362
+ void running.promise.then(async (continuedOutcome) => {
363
+ const recovered = resultFromOutcome(agent, task, continuedOutcome, startedAt, artifactPaths, {
427
364
  cwd,
428
365
  settings: fastModeSettings,
429
366
  scope: fastModeScope,
430
367
  });
431
368
  await control.deliverChildResult(
432
369
  {
433
- path: backgroundOutcome.path,
434
- status: backgroundOutcome.status,
435
- ...(backgroundOutcome.status === "error" ? { cause: backgroundOutcome.cause } : {}),
436
- stats: backgroundOutcome.stats,
437
- envelope: backgroundOutcome.envelope,
370
+ path: continuedOutcome.path,
371
+ status: continuedOutcome.status,
372
+ ...(continuedOutcome.status === "error" ? { cause: continuedOutcome.cause } : {}),
373
+ stats: continuedOutcome.stats,
374
+ envelope: continuedOutcome.envelope,
438
375
  ...(recovered.model === undefined ? {} : { model: recovered.model }),
439
376
  ...(recovered.thinking === undefined ? {} : { thinking: recovered.thinking }),
440
377
  ...(recovered.fastMode ? { fastMode: true } : {}),
441
- sessionFile: backgroundOutcome.sessionFile,
378
+ sessionFile: continuedOutcome.sessionFile,
442
379
  timestamp: Date.now(),
443
380
  artifactsDir: options.artifactsDir,
444
381
  },
445
382
  { artifactsDir: options.artifactsDir, artifactPaths, artifactsDisabled, maxOutput: options.maxOutput },
446
383
  );
447
- const delivered = control.getDeliveredResult(backgroundOutcome.path);
384
+ const delivered = control.getDeliveredResult(continuedOutcome.path);
448
385
  if (delivered) {
449
386
  recovered.envelope = delivered.envelope;
450
387
  recovered.finalOutput = delivered.envelope;
@@ -459,7 +396,7 @@ export async function runSingleInProcess(
459
396
  task,
460
397
  status: "continued",
461
398
  path: admission.admitted.identity.path,
462
- envelope: "Child continued in background.",
399
+ envelope: "Child detached for intercom coordination.",
463
400
  detached: true,
464
401
  detachedReason: "intercom-coordination",
465
402
  messages: [],
@@ -5,7 +5,7 @@
5
5
  import { type ExtensionAPI, isStaleExtensionContextError } from "@bastani/atomic";
6
6
  import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts";
7
7
  import {
8
- SUBAGENT_ASYNC_COMPLETE_EVENT,
8
+ SUBAGENT_COMPLETE_EVENT,
9
9
  SUBAGENT_TERMINAL_ORDERING_BARRIER_EVENT,
10
10
  type SubagentAttemptStatus,
11
11
  } from "../../shared/types.ts";
@@ -170,7 +170,7 @@ export default function registerSubagentNotify(pi: ExtensionAPI): () => void {
170
170
  runId,
171
171
  ...(terminalId ? { terminalId } : {}),
172
172
  terminalAt: Number.isFinite(result.timestamp) ? result.timestamp : Date.now(),
173
- source: "background-notify" as const,
173
+ source: "detached-notify" as const,
174
174
  sourceSessionTargets,
175
175
  ...(barrierDispatch ? { dispatch: barrierDispatch } : {}),
176
176
  };
@@ -238,7 +238,7 @@ export default function registerSubagentNotify(pi: ExtensionAPI): () => void {
238
238
  const noticeLabel =
239
239
  typeof result.noticeLabel === "string" && result.noticeLabel.trim()
240
240
  ? result.noticeLabel.trim()
241
- : "Background task";
241
+ : "Subagent task";
242
242
  let sessionLabel: string | undefined;
243
243
  let sessionValue: string | undefined;
244
244
  if (sessionLine) {
@@ -281,7 +281,7 @@ export default function registerSubagentNotify(pi: ExtensionAPI): () => void {
281
281
  inFlight.delete(key);
282
282
  ownership.reject(error);
283
283
  result.acknowledge?.(false);
284
- console.error("Failed to deliver async subagent completion notification:", error);
284
+ console.error("Failed to deliver subagent completion notification:", error);
285
285
  };
286
286
  const observe = (delivery: PromiseLike<void>): void => {
287
287
  result.defer?.();
@@ -314,7 +314,7 @@ export default function registerSubagentNotify(pi: ExtensionAPI): () => void {
314
314
  };
315
315
  let unsubscribe: () => void;
316
316
  try {
317
- unsubscribe = pi.events.on(SUBAGENT_ASYNC_COMPLETE_EVENT, handleComplete);
317
+ unsubscribe = pi.events.on(SUBAGENT_COMPLETE_EVENT, handleComplete);
318
318
  } catch (error) {
319
319
  if (!isStaleExtensionContextError(error)) throw error;
320
320
  // A stale API cannot accept a new subscription; keep the prior one usable.
@@ -22,10 +22,6 @@ import {
22
22
  subagentDepthBlockedMessage,
23
23
  } from "../../shared/types.ts";
24
24
 
25
- function applyForceTopLevelAsyncOverride<T extends { async?: boolean }>(params: T, depth: number, force: boolean): T {
26
- return depth === 0 && force ? { ...params, async: true } : params;
27
- }
28
-
29
25
  import {
30
26
  createNestedRoute,
31
27
  resolveInheritedNestedRouteFromEnv,
@@ -81,11 +77,7 @@ export function prepareExecutionContext(input: {
81
77
  if (normalized.error) return { error: normalized.error };
82
78
  const normalizedParams = normalized.params!;
83
79
 
84
- let effectiveParams = applyForceTopLevelAsyncOverride(
85
- normalizedParams,
86
- depth,
87
- deps.config.forceTopLevelAsync === true,
88
- );
80
+ let effectiveParams = normalizedParams;
89
81
 
90
82
  const scope = resolveExecutionAgentScope(effectiveParams.agentScope);
91
83
  const effectiveCwd = effectiveParams.cwd ?? ctx.cwd;
@@ -124,7 +116,6 @@ export function prepareExecutionContext(input: {
124
116
  } catch (error) {
125
117
  return { error: toExecutionErrorResult(effectiveParams, error) };
126
118
  }
127
- const effectiveAsync = effectiveParams.async ?? deps.asyncByDefault;
128
119
  const controlConfig = resolveControlConfig(deps.config.control, effectiveParams.control);
129
120
 
130
121
  const artifactConfig: ArtifactConfig = {
@@ -176,30 +167,22 @@ export function prepareExecutionContext(input: {
176
167
  artifactConfig,
177
168
  artifactsDir,
178
169
  parentDepth: depth,
179
- effectiveAsync,
180
170
  controlConfig,
181
171
  intercomBridge,
182
172
  nestedRoute,
183
173
  };
184
174
 
185
175
  const foregroundMode: "single" | "parallel" = hasTasks ? "parallel" : "single";
186
- const foregroundControl = effectiveAsync
187
- ? undefined
188
- : {
189
- runId,
190
- mode: foregroundMode,
191
- startedAt: Date.now(),
192
- updatedAt: Date.now(),
193
- currentAgent: undefined,
194
- currentIndex: undefined,
195
- currentActivityState: undefined,
196
- nestedRoute,
197
- interrupt: undefined,
198
- };
199
- if (foregroundControl) {
200
- deps.state.foregroundControls.set(runId, foregroundControl);
201
- deps.state.lastForegroundControlId = runId;
202
- }
176
+ const foregroundControl = {
177
+ runId,
178
+ mode: foregroundMode,
179
+ startedAt: Date.now(),
180
+ updatedAt: Date.now(),
181
+ nestedRoute,
182
+ interrupt: undefined,
183
+ };
184
+ deps.state.foregroundControls.set(runId, foregroundControl);
185
+ deps.state.lastForegroundControlId = runId;
203
186
 
204
187
  const writeNestedForegroundEvent = (
205
188
  type: "subagent.nested.started" | "subagent.nested.completed",
@@ -2,6 +2,7 @@ import type { ExtensionContext } from "@bastani/atomic";
2
2
  import type { AgentConfig } from "../../agents/agents.ts";
3
3
  import { INTERCOM_BRIDGE_MARKER } from "../../intercom/intercom-bridge.ts";
4
4
  import type { ModelInfo } from "../../shared/model-info.ts";
5
+ import type { CandidateModelResolver } from "../../shared/model-resolution.ts";
5
6
  import { buildTaskInstructions, type ResolvedStepBehavior } from "../../shared/settings.ts";
6
7
  import type {
7
8
  AgentProgress,
@@ -42,6 +43,7 @@ interface ForegroundParallelRunInput {
42
43
  workflowStageSubagentGuard?: boolean;
43
44
  availableModels: ModelInfo[];
44
45
  knownModelProviders: string[];
46
+ resolveCandidateModel: CandidateModelResolver;
45
47
  modelOverrides: (string | undefined)[];
46
48
  behaviors: ResolvedStepBehavior[];
47
49
  firstProgressIndex: number;
@@ -144,6 +146,7 @@ export async function runForegroundParallelTasks(input: ForegroundParallelRunInp
144
146
  modelOverride: input.modelOverrides[index],
145
147
  availableModels: input.availableModels,
146
148
  knownModelProviders: input.knownModelProviders,
149
+ resolveCandidateModel: input.resolveCandidateModel,
147
150
  preferredModelProvider: input.ctx.model?.provider,
148
151
  currentModel: currentModelFullId(input.ctx.model),
149
152
  skills: effectiveSkills === false ? [] : effectiveSkills,
@@ -2,6 +2,7 @@ import type { AgentConfig } from "../../agents/agents.ts";
2
2
  import { normalizeSkillInput } from "../../agents/skills.ts";
3
3
  import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts";
4
4
  import { collectKnownModelProviders, type ModelInfo, toModelInfo } from "../../shared/model-info.ts";
5
+ import { createCandidateModelResolver } from "../../shared/model-resolution.ts";
5
6
  import {
6
7
  resolveStepBehavior,
7
8
  type StepOverrides,
@@ -212,6 +213,7 @@ export async function runParallelPath(
212
213
  workflowStageSubagentGuard,
213
214
  availableModels,
214
215
  knownModelProviders,
216
+ resolveCandidateModel: createCandidateModelResolver(ctx.modelRegistry, currentProvider),
215
217
  modelOverrides,
216
218
  behaviors,
217
219
  firstProgressIndex: parallelProgressPrecreated ? -1 : firstProgressIndex,
@@ -1,13 +1,8 @@
1
- import { formatAsyncStartedMessage, isAsyncAvailable } from "../inprocess/background.ts";
2
- import { executeAsyncSingle } from "../inprocess/background-single.ts";
3
1
  import { runSync } from "./execution.ts";
4
2
  import type { SubagentExecutorRuntimeDeps } from "./subagent-executor-types.ts";
5
3
 
6
4
  const defaultSubagentExecutorRuntimeDeps: SubagentExecutorRuntimeDeps = {
7
5
  runSync,
8
- executeAsyncSingle,
9
- isAsyncAvailable,
10
- formatAsyncStartedMessage,
11
6
  };
12
7
 
13
8
  export function resolveSubagentExecutorRuntimeDeps(
@@ -3,6 +3,7 @@ import * as path from "node:path";
3
3
  import { normalizeSkillInput } from "../../agents/skills.ts";
4
4
  import { INTERCOM_BRIDGE_MARKER, resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts";
5
5
  import { collectKnownModelProviders, type ModelInfo, toModelInfo } from "../../shared/model-info.ts";
6
+ import { createCandidateModelResolver } from "../../shared/model-resolution.ts";
6
7
  import {
7
8
  injectSingleProgressInstruction,
8
9
  resolveSingleProgress,
@@ -37,7 +38,7 @@ import {
37
38
  rememberForegroundRun,
38
39
  replaceForegroundRunChild,
39
40
  } from "./subagent-executor-status.ts";
40
- import type { ExecutionContextData, ResolvedExecutorDeps } from "./subagent-executor-types.ts";
41
+ import type { ExecutionContextData, ForegroundControl, ResolvedExecutorDeps } from "./subagent-executor-types.ts";
41
42
 
42
43
  function formatFailedSingleRunOutput(result: SingleResult, displayOutput: string): string {
43
44
  const error = result.error || "Failed";
@@ -61,6 +62,32 @@ function cleanupTransientProgress(progressDir: string | undefined, artifactsEnab
61
62
  }
62
63
  }
63
64
 
65
+ export function createForwardSingleUpdate(
66
+ onUpdate: ((r: SubagentToolResult) => void) | undefined,
67
+ foregroundControl: ForegroundControl | undefined,
68
+ agent: string,
69
+ index: number,
70
+ ): ((r: SubagentToolResult) => void) | undefined {
71
+ if (!onUpdate) return undefined;
72
+ return (update: SubagentToolResult) => {
73
+ if (foregroundControl) {
74
+ const firstProgress = update.details?.progress?.[0];
75
+ foregroundControl.currentAgent = agent;
76
+ foregroundControl.currentIndex = firstProgress?.index ?? index;
77
+ foregroundControl.currentActivityState = firstProgress?.activityState;
78
+ foregroundControl.lastActivityAt = firstProgress?.lastActivityAt;
79
+ foregroundControl.currentTool = firstProgress?.currentTool;
80
+ foregroundControl.currentToolStartedAt = firstProgress?.currentToolStartedAt;
81
+ foregroundControl.currentPath = firstProgress?.currentPath;
82
+ foregroundControl.turnCount = firstProgress?.turnCount;
83
+ foregroundControl.tokens = firstProgress?.tokens;
84
+ foregroundControl.toolCount = firstProgress?.toolCount;
85
+ foregroundControl.updatedAt = Date.now();
86
+ }
87
+ onUpdate(update);
88
+ };
89
+ }
90
+
64
91
  export async function runSinglePath(
65
92
  data: ExecutionContextData,
66
93
  deps: ResolvedExecutorDeps,
@@ -158,25 +185,7 @@ export async function runSinglePath(
158
185
  };
159
186
  }
160
187
 
161
- const forwardSingleUpdate = onUpdate
162
- ? (update: SubagentToolResult) => {
163
- if (foregroundControl) {
164
- const firstProgress = update.details?.progress?.[0];
165
- foregroundControl.currentAgent = params.agent;
166
- foregroundControl.currentIndex = firstProgress?.index ?? 0;
167
- foregroundControl.currentActivityState = firstProgress?.activityState;
168
- foregroundControl.lastActivityAt = firstProgress?.lastActivityAt;
169
- foregroundControl.currentTool = firstProgress?.currentTool;
170
- foregroundControl.currentToolStartedAt = firstProgress?.currentToolStartedAt;
171
- foregroundControl.currentPath = firstProgress?.currentPath;
172
- foregroundControl.turnCount = firstProgress?.turnCount;
173
- foregroundControl.tokens = firstProgress?.tokens;
174
- foregroundControl.toolCount = firstProgress?.toolCount;
175
- foregroundControl.updatedAt = Date.now();
176
- }
177
- onUpdate(update);
178
- }
179
- : undefined;
188
+ const forwardSingleUpdate = createForwardSingleUpdate(onUpdate, foregroundControl, params.agent!, 0);
180
189
 
181
190
  let r: SingleResult;
182
191
  try {
@@ -217,6 +226,7 @@ export async function runSinglePath(
217
226
  modelOverride,
218
227
  availableModels,
219
228
  knownModelProviders,
229
+ resolveCandidateModel: createCandidateModelResolver(ctx.modelRegistry, currentProvider),
220
230
  preferredModelProvider: currentProvider,
221
231
  currentModel: currentModelFullId(ctx.model),
222
232
  skills: effectiveSkills,
@@ -20,7 +20,6 @@ import {
20
20
  type SubagentToolResult,
21
21
  } from "../../shared/types.ts";
22
22
  import { compactForegroundDetails, compactForegroundResult, getSingleResultOutput } from "../../shared/utils.ts";
23
- import { deliverLocalCompletionNotification } from "../background/completion-notification.ts";
24
23
  import { updateForegroundNestedProjection } from "../inprocess/runtime-support/nested-api.ts";
25
24
  import { formatNestedRunStatusLines } from "../inprocess/runtime-support/nested-rendering.ts";
26
25
  import {
@@ -28,6 +27,7 @@ import {
28
27
  formatControlNoticeMessage,
29
28
  shouldNotifyControlEvent,
30
29
  } from "../shared/subagent-control.ts";
30
+ import { deliverLocalCompletionNotification } from "./completion-notification.ts";
31
31
  import type { ExecutionContextData, ExecutorDeps, ForegroundControl } from "./subagent-executor-types.ts";
32
32
 
33
33
  export function getForegroundControl(state: SubagentState, runId: string | undefined): ForegroundControl | undefined {
@@ -171,6 +171,7 @@ export function replaceForegroundRunChild(
171
171
  runId: string,
172
172
  index: number,
173
173
  result: SingleResult,
174
+ options: { onlyWhenDetached?: boolean } = {},
174
175
  ): void {
175
176
  const retainedResult = compactForegroundResult(result);
176
177
  const run = state.foregroundRuns?.get(runId);
@@ -199,7 +200,7 @@ export function replaceForegroundRunChild(
199
200
  return;
200
201
  }
201
202
  const child = run.children.find((entry) => entry.index === index);
202
- if (child?.status !== "detached") return;
203
+ if (!child || (options.onlyWhenDetached !== false && child.status !== "detached")) return;
203
204
  child.status = resolveSubagentResultStatus({
204
205
  status: retainedResult.status,
205
206
  interrupted: retainedResult.interrupted,
@@ -280,7 +281,7 @@ function resultSummaryForIntercom(result: SingleResult): string {
280
281
  * normally return their results inline in the tool result, but a detached
281
282
  * child outlives that tool call, so without this the parent never learns the
282
283
  * child finished (see run history: detached parallel runs completed silently).
283
- * Reuses the async completion pipeline (dedupe, ordering barrier, triggerTurn).
284
+ * Reuses the detached completion pipeline (dedupe, ordering barrier, triggerTurn).
284
285
  */
285
286
  export function notifyDetachedForegroundChildExit(input: {
286
287
  pi: ExtensionAPI;
@@ -349,7 +350,6 @@ async function emitForegroundResultIntercom(input: {
349
350
  to: input.intercomBridge.orchestratorTarget,
350
351
  runId: input.runId,
351
352
  mode: input.mode,
352
- source: "foreground",
353
353
  children: attachNestedChildrenToResultChildren(input.runId, children, input.nestedChildren),
354
354
  });
355
355
  const delivered = await deliverSubagentResultIntercomEvent(input.pi.events, payload);
@@ -12,12 +12,6 @@ import type {
12
12
  SubagentState,
13
13
  SubagentToolResult,
14
14
  } from "../../shared/types.ts";
15
- import type {
16
- AsyncExecutionResult,
17
- AsyncSingleParams,
18
- formatAsyncStartedMessage,
19
- isAsyncAvailable,
20
- } from "../inprocess/background.ts";
21
15
  import type { ChildModePolicy } from "../inprocess/child-policy.ts";
22
16
  import type { runSync } from "./execution.ts";
23
17
 
@@ -39,7 +33,6 @@ export interface SubagentParamsLike {
39
33
  action?: (typeof SUBAGENT_ACTIONS)[number];
40
34
  id?: string;
41
35
  runId?: string;
42
- dir?: string;
43
36
  index?: number;
44
37
  agent?: string;
45
38
  task?: string;
@@ -49,7 +42,6 @@ export interface SubagentParamsLike {
49
42
  concurrency?: number;
50
43
  worktree?: boolean;
51
44
  context?: "fresh" | "fork";
52
- async?: boolean;
53
45
  share?: boolean;
54
46
  control?: ControlConfig;
55
47
  sessionDir?: string;
@@ -69,16 +61,12 @@ export interface SubagentParamsLike {
69
61
 
70
62
  export interface SubagentExecutorRuntimeDeps {
71
63
  runSync: typeof runSync;
72
- executeAsyncSingle: (id: string, params: AsyncSingleParams) => AsyncExecutionResult | Promise<AsyncExecutionResult>;
73
- isAsyncAvailable: typeof isAsyncAvailable;
74
- formatAsyncStartedMessage: typeof formatAsyncStartedMessage;
75
64
  }
76
65
 
77
66
  export interface ExecutorDeps {
78
67
  pi: ExtensionAPI;
79
68
  state: SubagentState;
80
69
  config: import("../../shared/types.ts").ExtensionConfig;
81
- asyncByDefault: boolean;
82
70
  tempArtifactsDir: string;
83
71
  getSubagentSessionRoot: (parentSessionFile: string | null) => string;
84
72
  expandTilde: (p: string) => string;
@@ -115,7 +103,6 @@ export interface ExecutionContextData {
115
103
  artifactConfig: ArtifactConfig;
116
104
  artifactsDir: string;
117
105
  parentDepth?: number;
118
- effectiveAsync: boolean;
119
106
  controlConfig: ResolvedControlConfig;
120
107
  intercomBridge: IntercomBridgeState;
121
108
  nestedRoute?: NestedRouteInfo;