@bastani/atomic 0.9.5-alpha.9 → 0.9.5

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 (377) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +2 -2
  3. package/dist/builtin/cursor/CHANGELOG.md +12 -0
  4. package/dist/builtin/cursor/package.json +3 -3
  5. package/dist/builtin/cursor/src/model-mapper.ts +6 -3
  6. package/dist/builtin/intercom/CHANGELOG.md +37 -0
  7. package/dist/builtin/intercom/README.md +4 -2
  8. package/dist/builtin/intercom/broker/broker.ts +6 -114
  9. package/dist/builtin/intercom/broker/client.ts +29 -54
  10. package/dist/builtin/intercom/broker/delivered-message-cache.ts +44 -0
  11. package/dist/builtin/intercom/broker/pending-send-registry.ts +142 -0
  12. package/dist/builtin/intercom/broker/send-handler.ts +106 -0
  13. package/dist/builtin/intercom/broker/send-signature.ts +37 -0
  14. package/dist/builtin/intercom/foreground-detach-handoff.ts +136 -0
  15. package/dist/builtin/intercom/index-heavy.ts +49 -53
  16. package/dist/builtin/intercom/index.ts +278 -262
  17. package/dist/builtin/intercom/lazy-heavy-proxy.ts +114 -0
  18. package/dist/builtin/intercom/lazy-subagent-ack.ts +20 -0
  19. package/dist/builtin/intercom/lazy-tool-execution.ts +39 -0
  20. package/dist/builtin/intercom/lifecycle-lease.ts +51 -0
  21. package/dist/builtin/intercom/lifecycle.ts +37 -20
  22. package/dist/builtin/intercom/package.json +3 -6
  23. package/dist/builtin/intercom/reply-routing.ts +17 -0
  24. package/dist/builtin/intercom/subagent-relay.ts +58 -12
  25. package/dist/builtin/intercom/types.ts +3 -3
  26. package/dist/builtin/mcp/CHANGELOG.md +27 -0
  27. package/dist/builtin/mcp/OAUTH.md +1 -0
  28. package/dist/builtin/mcp/README.md +4 -0
  29. package/dist/builtin/mcp/apps-cancellation.ts +32 -0
  30. package/dist/builtin/mcp/call-tool-result.ts +9 -0
  31. package/dist/builtin/mcp/caller-wait.ts +50 -0
  32. package/dist/builtin/mcp/command-registration.ts +82 -0
  33. package/dist/builtin/mcp/direct-tool-executor.ts +279 -0
  34. package/dist/builtin/mcp/direct-tools.ts +6 -239
  35. package/dist/builtin/mcp/host-html-template.ts +4 -2
  36. package/dist/builtin/mcp/index.ts +258 -250
  37. package/dist/builtin/mcp/init.ts +96 -87
  38. package/dist/builtin/mcp/mcp-auth-flow.ts +247 -237
  39. package/dist/builtin/mcp/mcp-callback-server.ts +89 -68
  40. package/dist/builtin/mcp/mcp-oauth-provider.ts +23 -1
  41. package/dist/builtin/mcp/metadata-hydration.ts +21 -6
  42. package/dist/builtin/mcp/package.json +3 -3
  43. package/dist/builtin/mcp/proxy-auth.ts +4 -4
  44. package/dist/builtin/mcp/proxy-call.ts +111 -40
  45. package/dist/builtin/mcp/proxy-connect.ts +35 -15
  46. package/dist/builtin/mcp/proxy-info-modes.ts +49 -19
  47. package/dist/builtin/mcp/proxy-modes.ts +3 -3
  48. package/dist/builtin/mcp/session-cleanup-barrier.ts +43 -0
  49. package/dist/builtin/mcp/state-lease.ts +12 -0
  50. package/dist/builtin/mcp/ui-server.ts +8 -8
  51. package/dist/builtin/mcp/ui-session.ts +9 -18
  52. package/dist/builtin/subagents/CHANGELOG.md +66 -0
  53. package/dist/builtin/subagents/README.md +30 -29
  54. package/dist/builtin/subagents/agents/code-simplifier.md +2 -2
  55. package/dist/builtin/subagents/agents/codebase-analyzer.md +2 -2
  56. package/dist/builtin/subagents/agents/codebase-locator.md +2 -2
  57. package/dist/builtin/subagents/agents/codebase-online-researcher.md +2 -2
  58. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +2 -2
  59. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +2 -2
  60. package/dist/builtin/subagents/agents/codebase-research-locator.md +2 -2
  61. package/dist/builtin/subagents/agents/debugger.md +2 -2
  62. package/dist/builtin/subagents/agents/worker.md +2 -2
  63. package/dist/builtin/subagents/package.json +5 -5
  64. package/dist/builtin/subagents/prompts/review-loop.md +1 -1
  65. package/dist/builtin/subagents/skills/subagent/SKILL.md +37 -36
  66. package/dist/builtin/subagents/src/extension/api-lifecycle.ts +64 -0
  67. package/dist/builtin/subagents/src/extension/fanout-child.ts +44 -51
  68. package/dist/builtin/subagents/src/extension/index.ts +287 -307
  69. package/dist/builtin/subagents/src/extension/prompt-guidance.ts +7 -10
  70. package/dist/builtin/subagents/src/extension/schemas.ts +22 -5
  71. package/dist/builtin/subagents/src/extension/tool-description.ts +29 -0
  72. package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +13 -2
  73. package/dist/builtin/subagents/src/intercom/result-intercom.ts +4 -4
  74. package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +106 -0
  75. package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +3 -2
  76. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +13 -2
  77. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +3 -0
  78. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +1 -1
  79. package/dist/builtin/subagents/src/runs/background/completion-claims.ts +189 -0
  80. package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +44 -7
  81. package/dist/builtin/subagents/src/runs/background/completion-notification.ts +34 -0
  82. package/dist/builtin/subagents/src/runs/background/notify.ts +72 -22
  83. package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +232 -0
  84. package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +151 -0
  85. package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +72 -0
  86. package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +48 -0
  87. package/dist/builtin/subagents/src/runs/background/result-status.ts +81 -0
  88. package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +59 -0
  89. package/dist/builtin/subagents/src/runs/background/result-watcher.ts +172 -238
  90. package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +3 -2
  91. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +73 -14
  92. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +17 -13
  93. package/dist/builtin/subagents/src/runs/background/top-level-async.ts +1 -2
  94. package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +1 -0
  95. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +1 -0
  96. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +1 -0
  97. package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +7 -9
  98. package/dist/builtin/subagents/src/runs/foreground/chain-execution-types.ts +3 -13
  99. package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +2 -15
  100. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +2 -2
  101. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +53 -44
  102. package/dist/builtin/subagents/src/runs/foreground/execution-detach-reservations.ts +48 -0
  103. package/dist/builtin/subagents/src/runs/foreground/execution-detach-route.ts +17 -0
  104. package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +39 -26
  105. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +3 -1
  106. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +3 -51
  107. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +6 -11
  108. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-input.ts +11 -2
  109. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +2 -0
  110. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +5 -112
  111. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +2 -0
  112. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +68 -118
  113. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +79 -7
  114. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +2 -2
  115. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +3 -0
  116. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +2 -2
  117. package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +27 -11
  118. package/dist/builtin/subagents/src/shared/artifacts.ts +22 -11
  119. package/dist/builtin/subagents/src/shared/event-jsonl-writer.ts +294 -0
  120. package/dist/builtin/subagents/src/shared/exclusive-file-publication.ts +44 -0
  121. package/dist/builtin/subagents/src/shared/jsonl-writer.ts +1 -0
  122. package/dist/builtin/subagents/src/shared/model-info.ts +2 -2
  123. package/dist/builtin/subagents/src/shared/settings.ts +20 -10
  124. package/dist/builtin/subagents/src/shared/types-async.ts +3 -1
  125. package/dist/builtin/subagents/src/shared/types-config.ts +2 -0
  126. package/dist/builtin/subagents/src/shared/types-runtime.ts +3 -2
  127. package/dist/builtin/subagents/src/slash/slash-commands.ts +9 -12
  128. package/dist/builtin/subagents/src/slash/slash-live-state.ts +63 -32
  129. package/dist/builtin/subagents/src/tui/render-result.ts +7 -0
  130. package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -0
  131. package/dist/builtin/subagents/src/tui/render-widget.ts +128 -89
  132. package/dist/builtin/web-access/CHANGELOG.md +28 -0
  133. package/dist/builtin/web-access/README.md +4 -0
  134. package/dist/builtin/web-access/content-tools.ts +8 -3
  135. package/dist/builtin/web-access/index-heavy.ts +1 -1
  136. package/dist/builtin/web-access/index.ts +190 -46
  137. package/dist/builtin/web-access/lifecycle-lease.ts +38 -0
  138. package/dist/builtin/web-access/package.json +2 -2
  139. package/dist/builtin/web-access/result-renderers.ts +1 -1
  140. package/dist/builtin/web-access/summary-review.ts +1 -1
  141. package/dist/builtin/web-access/web-search-activity.ts +1 -1
  142. package/dist/builtin/web-access/web-search-return.ts +7 -0
  143. package/dist/builtin/web-access/web-search-summary.ts +1 -1
  144. package/dist/builtin/web-access/web-search-tool.ts +4 -2
  145. package/dist/builtin/workflows/CHANGELOG.md +68 -0
  146. package/dist/builtin/workflows/README.md +4 -4
  147. package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +27 -4
  148. package/dist/builtin/workflows/builtin/goal-runner.ts +47 -26
  149. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +10 -0
  150. package/dist/builtin/workflows/builtin/ralph-core.ts +9 -9
  151. package/dist/builtin/workflows/builtin/ralph-models.ts +71 -36
  152. package/dist/builtin/workflows/builtin/ralph-runner.ts +20 -31
  153. package/dist/builtin/workflows/package.json +2 -2
  154. package/dist/builtin/workflows/src/durable/stage-primitive.ts +2 -1
  155. package/dist/builtin/workflows/src/engine/primitives/task.ts +2 -1
  156. package/dist/builtin/workflows/src/extension/workflow-prompts.ts +17 -22
  157. package/dist/builtin/workflows/src/extension/workflow-schema.ts +15 -2
  158. package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +1 -2
  159. package/dist/builtin/workflows/src/runs/shared/model-fallback-candidates.ts +1 -1
  160. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -2
  161. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +2 -2
  162. package/dist/builtin/workflows/src/shared/resume-continuation.ts +2 -0
  163. package/dist/builtin/workflows/src/tui/stage-chat-view-archive-history.ts +1 -23
  164. package/dist/builtin/workflows/src/tui/stage-chat-view-footer-status.ts +54 -9
  165. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +5 -2
  166. package/dist/cli/args.d.ts.map +1 -1
  167. package/dist/cli/args.js +2 -2
  168. package/dist/cli/args.js.map +1 -1
  169. package/dist/core/agent-session-events.d.ts.map +1 -1
  170. package/dist/core/agent-session-events.js +2 -1
  171. package/dist/core/agent-session-events.js.map +1 -1
  172. package/dist/core/agent-session-message-queue.d.ts.map +1 -1
  173. package/dist/core/agent-session-message-queue.js +1 -1
  174. package/dist/core/agent-session-message-queue.js.map +1 -1
  175. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  176. package/dist/core/agent-session-prompt.js +1 -1
  177. package/dist/core/agent-session-prompt.js.map +1 -1
  178. package/dist/core/agent-session-retry.d.ts.map +1 -1
  179. package/dist/core/agent-session-retry.js +1 -1
  180. package/dist/core/agent-session-retry.js.map +1 -1
  181. package/dist/core/agent-session-services.d.ts.map +1 -1
  182. package/dist/core/agent-session-services.js +3 -2
  183. package/dist/core/agent-session-services.js.map +1 -1
  184. package/dist/core/agent-session-types.d.ts.map +1 -1
  185. package/dist/core/agent-session-types.js +1 -1
  186. package/dist/core/agent-session-types.js.map +1 -1
  187. package/dist/core/anthropic-thinking-guard.d.ts +5 -5
  188. package/dist/core/anthropic-thinking-guard.d.ts.map +1 -1
  189. package/dist/core/anthropic-thinking-guard.js +42 -32
  190. package/dist/core/anthropic-thinking-guard.js.map +1 -1
  191. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  192. package/dist/core/atomic-guide-command.js +15 -15
  193. package/dist/core/atomic-guide-command.js.map +1 -1
  194. package/dist/core/auth-storage.d.ts.map +1 -1
  195. package/dist/core/auth-storage.js +14 -9
  196. package/dist/core/auth-storage.js.map +1 -1
  197. package/dist/core/compaction/compaction.d.ts +2 -0
  198. package/dist/core/compaction/compaction.d.ts.map +1 -1
  199. package/dist/core/compaction/compaction.js +79 -46
  200. package/dist/core/compaction/compaction.js.map +1 -1
  201. package/dist/core/compaction/context-assistant-turns.d.ts +42 -0
  202. package/dist/core/compaction/context-assistant-turns.d.ts.map +1 -0
  203. package/dist/core/compaction/context-assistant-turns.js +87 -0
  204. package/dist/core/compaction/context-assistant-turns.js.map +1 -0
  205. package/dist/core/compaction/context-compaction-critical.d.ts +1 -1
  206. package/dist/core/compaction/context-compaction-critical.d.ts.map +1 -1
  207. package/dist/core/compaction/context-compaction-critical.js +2 -2
  208. package/dist/core/compaction/context-compaction-critical.js.map +1 -1
  209. package/dist/core/compaction/context-compaction-eviction-alternates.d.ts +18 -0
  210. package/dist/core/compaction/context-compaction-eviction-alternates.d.ts.map +1 -0
  211. package/dist/core/compaction/context-compaction-eviction-alternates.js +186 -0
  212. package/dist/core/compaction/context-compaction-eviction-alternates.js.map +1 -0
  213. package/dist/core/compaction/context-compaction-eviction.d.ts +10 -2
  214. package/dist/core/compaction/context-compaction-eviction.d.ts.map +1 -1
  215. package/dist/core/compaction/context-compaction-eviction.js +196 -146
  216. package/dist/core/compaction/context-compaction-eviction.js.map +1 -1
  217. package/dist/core/compaction/context-compaction-prompt.d.ts.map +1 -1
  218. package/dist/core/compaction/context-compaction-prompt.js +1 -1
  219. package/dist/core/compaction/context-compaction-prompt.js.map +1 -1
  220. package/dist/core/compaction/context-compaction-types.d.ts +2 -0
  221. package/dist/core/compaction/context-compaction-types.d.ts.map +1 -1
  222. package/dist/core/compaction/context-compaction-types.js.map +1 -1
  223. package/dist/core/compaction/context-deletion-application.d.ts +5 -4
  224. package/dist/core/compaction/context-deletion-application.d.ts.map +1 -1
  225. package/dist/core/compaction/context-deletion-application.js +17 -15
  226. package/dist/core/compaction/context-deletion-application.js.map +1 -1
  227. package/dist/core/compaction/context-deletion-store.d.ts.map +1 -1
  228. package/dist/core/compaction/context-deletion-store.js +1 -1
  229. package/dist/core/compaction/context-deletion-store.js.map +1 -1
  230. package/dist/core/compaction/context-deletion-targets.d.ts +2 -1
  231. package/dist/core/compaction/context-deletion-targets.d.ts.map +1 -1
  232. package/dist/core/compaction/context-deletion-targets.js +36 -31
  233. package/dist/core/compaction/context-deletion-targets.js.map +1 -1
  234. package/dist/core/compaction/context-deletion-tool-helpers.d.ts.map +1 -1
  235. package/dist/core/compaction/context-deletion-tool-helpers.js +116 -43
  236. package/dist/core/compaction/context-deletion-tool-helpers.js.map +1 -1
  237. package/dist/core/compaction/context-transcript-analysis.d.ts +1 -2
  238. package/dist/core/compaction/context-transcript-analysis.d.ts.map +1 -1
  239. package/dist/core/compaction/context-transcript-analysis.js +33 -37
  240. package/dist/core/compaction/context-transcript-analysis.js.map +1 -1
  241. package/dist/core/copilot-model-synthesis.d.ts.map +1 -1
  242. package/dist/core/copilot-model-synthesis.js +3 -1
  243. package/dist/core/copilot-model-synthesis.js.map +1 -1
  244. package/dist/core/extensions/provider-types.d.ts +2 -7
  245. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  246. package/dist/core/extensions/provider-types.js.map +1 -1
  247. package/dist/core/messages.d.ts +9 -0
  248. package/dist/core/messages.d.ts.map +1 -1
  249. package/dist/core/messages.js +100 -18
  250. package/dist/core/messages.js.map +1 -1
  251. package/dist/core/model-registry-builtins.d.ts.map +1 -1
  252. package/dist/core/model-registry-builtins.js +5 -0
  253. package/dist/core/model-registry-builtins.js.map +1 -1
  254. package/dist/core/model-registry-custom-loader.d.ts.map +1 -1
  255. package/dist/core/model-registry-custom-loader.js +49 -8
  256. package/dist/core/model-registry-custom-loader.js.map +1 -1
  257. package/dist/core/model-registry-dynamic.d.ts.map +1 -1
  258. package/dist/core/model-registry-dynamic.js +11 -5
  259. package/dist/core/model-registry-dynamic.js.map +1 -1
  260. package/dist/core/model-registry-loader.d.ts.map +1 -1
  261. package/dist/core/model-registry-loader.js +8 -0
  262. package/dist/core/model-registry-loader.js.map +1 -1
  263. package/dist/core/model-registry-schemas.d.ts +93 -8
  264. package/dist/core/model-registry-schemas.d.ts.map +1 -1
  265. package/dist/core/model-registry-schemas.js +24 -12
  266. package/dist/core/model-registry-schemas.js.map +1 -1
  267. package/dist/core/model-registry-types.d.ts +7 -6
  268. package/dist/core/model-registry-types.d.ts.map +1 -1
  269. package/dist/core/model-registry-types.js.map +1 -1
  270. package/dist/core/model-registry.d.ts +5 -0
  271. package/dist/core/model-registry.d.ts.map +1 -1
  272. package/dist/core/model-registry.js +23 -0
  273. package/dist/core/model-registry.js.map +1 -1
  274. package/dist/core/model-resolver-cli.d.ts.map +1 -1
  275. package/dist/core/model-resolver-cli.js +33 -5
  276. package/dist/core/model-resolver-cli.js.map +1 -1
  277. package/dist/core/model-resolver-initial.d.ts +6 -1
  278. package/dist/core/model-resolver-initial.d.ts.map +1 -1
  279. package/dist/core/model-resolver-initial.js +12 -7
  280. package/dist/core/model-resolver-initial.js.map +1 -1
  281. package/dist/core/model-resolver.d.ts +1 -1
  282. package/dist/core/model-resolver.d.ts.map +1 -1
  283. package/dist/core/model-resolver.js +1 -1
  284. package/dist/core/model-resolver.js.map +1 -1
  285. package/dist/core/resource-loader-context-files.d.ts +1 -0
  286. package/dist/core/resource-loader-context-files.d.ts.map +1 -1
  287. package/dist/core/resource-loader-context-files.js +13 -10
  288. package/dist/core/resource-loader-context-files.js.map +1 -1
  289. package/dist/core/sdk.d.ts.map +1 -1
  290. package/dist/core/sdk.js +2 -2
  291. package/dist/core/sdk.js.map +1 -1
  292. package/dist/core/session-entry-normalization.d.ts +7 -0
  293. package/dist/core/session-entry-normalization.d.ts.map +1 -0
  294. package/dist/core/session-entry-normalization.js +14 -0
  295. package/dist/core/session-entry-normalization.js.map +1 -0
  296. package/dist/core/session-manager-core.d.ts.map +1 -1
  297. package/dist/core/session-manager-core.js +1 -0
  298. package/dist/core/session-manager-core.js.map +1 -1
  299. package/dist/core/session-manager-history.d.ts +2 -2
  300. package/dist/core/session-manager-history.d.ts.map +1 -1
  301. package/dist/core/session-manager-history.js +127 -108
  302. package/dist/core/session-manager-history.js.map +1 -1
  303. package/dist/core/settings-manager-basic-accessors.d.ts +2 -2
  304. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  305. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  306. package/dist/core/settings-types.d.ts +1 -1
  307. package/dist/core/settings-types.d.ts.map +1 -1
  308. package/dist/core/settings-types.js.map +1 -1
  309. package/dist/core/tools/bash.d.ts.map +1 -1
  310. package/dist/core/tools/bash.js +11 -8
  311. package/dist/core/tools/bash.js.map +1 -1
  312. package/dist/main-session.d.ts.map +1 -1
  313. package/dist/main-session.js +1 -0
  314. package/dist/main-session.js.map +1 -1
  315. package/dist/modes/interactive/components/settings-selector-options.d.ts.map +1 -1
  316. package/dist/modes/interactive/components/settings-selector-options.js +3 -1
  317. package/dist/modes/interactive/components/settings-selector-options.js.map +1 -1
  318. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  319. package/dist/modes/interactive/components/thinking-selector.js +2 -1
  320. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  321. package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
  322. package/dist/modes/interactive/interactive-agent-events.js +2 -1
  323. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  324. package/dist/modes/interactive/interactive-child-ordering.d.ts +7 -0
  325. package/dist/modes/interactive/interactive-child-ordering.d.ts.map +1 -0
  326. package/dist/modes/interactive/interactive-child-ordering.js +26 -0
  327. package/dist/modes/interactive/interactive-child-ordering.js.map +1 -0
  328. package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
  329. package/dist/modes/interactive/interactive-deferred-startup.js +2 -2
  330. package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
  331. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  332. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  333. package/dist/modes/interactive/interactive-mode-deps.js +1 -1
  334. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  335. package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
  336. package/dist/modes/interactive/interactive-model-routing.js +8 -3
  337. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  338. package/dist/modes/interactive/theme/theme-class.d.ts +1 -1
  339. package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
  340. package/dist/modes/interactive/theme/theme-class.js +2 -0
  341. package/dist/modes/interactive/theme/theme-class.js.map +1 -1
  342. package/dist/utils/clipboard-image.d.ts.map +1 -1
  343. package/dist/utils/clipboard-image.js +3 -0
  344. package/dist/utils/clipboard-image.js.map +1 -1
  345. package/docs/changelog.mdx +19 -0
  346. package/docs/compaction.md +55 -48
  347. package/docs/custom-provider.md +18 -5
  348. package/docs/extensions.md +7 -3
  349. package/docs/models.md +69 -10
  350. package/docs/providers.md +1 -1
  351. package/docs/quickstart.md +11 -7
  352. package/docs/rpc.md +2 -2
  353. package/docs/sdk.md +1 -1
  354. package/docs/settings.md +3 -3
  355. package/docs/subagents.md +36 -5
  356. package/docs/tools.md +1 -1
  357. package/docs/usage.md +4 -2
  358. package/docs/workflows.md +26 -43
  359. package/examples/extensions/preset.ts +2 -2
  360. package/examples/extensions/subagent/README.md +2 -2
  361. package/examples/extensions/subagent/index.ts +1 -2
  362. package/examples/extensions/subagent/schemas.ts +4 -1
  363. package/examples/sdk/12-full-control.ts +1 -1
  364. package/npm-shrinkwrap.json +48 -51
  365. package/package.json +7 -7
  366. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-behavior.ts +0 -75
  367. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-component.ts +0 -202
  368. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-edit.ts +0 -97
  369. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-editor.ts +0 -160
  370. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-frame.ts +0 -72
  371. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-render-modes.ts +0 -161
  372. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-render-selectors.ts +0 -203
  373. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-selectors.ts +0 -234
  374. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-state.ts +0 -103
  375. package/dist/builtin/subagents/src/runs/foreground/chain-clarify-types.ts +0 -29
  376. package/dist/builtin/subagents/src/runs/foreground/chain-clarify.ts +0 -9
  377. package/dist/builtin/subagents/src/runs/foreground/chain-execution-clarify.ts +0 -117
@@ -14,6 +14,12 @@ interface SlashSnapshot {
14
14
  version: number;
15
15
  }
16
16
 
17
+ export interface SlashSnapshotStore {
18
+ liveSnapshots: Map<string, SlashSnapshot>;
19
+ finalSnapshots: Map<string, SlashSnapshot>;
20
+ versionCounter: number;
21
+ }
22
+
17
23
  interface SequentialChainStepLike {
18
24
  agent: string;
19
25
  task?: string;
@@ -25,9 +31,26 @@ interface ParallelChainStepLike {
25
31
 
26
32
  type ChainStepLike = SequentialChainStepLike | ParallelChainStepLike;
27
33
 
28
- const liveSnapshots = new Map<string, SlashSnapshot>();
29
- const finalSnapshots = new Map<string, SlashSnapshot>();
30
- let versionCounter = 1;
34
+ const defaultStoreOwner = {};
35
+
36
+ function getStoreRegistry(): WeakMap<object, SlashSnapshotStore> {
37
+ const key = "__piSubagentSlashSnapshotStores";
38
+ const globalStore = globalThis as Record<string, unknown>;
39
+ const existing = globalStore[key];
40
+ if (existing instanceof WeakMap) return existing as WeakMap<object, SlashSnapshotStore>;
41
+ const registry = new WeakMap<object, SlashSnapshotStore>();
42
+ globalStore[key] = registry;
43
+ return registry;
44
+ }
45
+
46
+ export function getSlashSnapshotStore(owner: object = defaultStoreOwner): SlashSnapshotStore {
47
+ const registry = getStoreRegistry();
48
+ const existing = registry.get(owner);
49
+ if (existing) return existing;
50
+ const store = { liveSnapshots: new Map(), finalSnapshots: new Map(), versionCounter: 1 };
51
+ registry.set(owner, store);
52
+ return store;
53
+ }
31
54
 
32
55
  const EMPTY_MESSAGES: Message[] = [];
33
56
  const EMPTY_USAGE: Usage = {
@@ -39,8 +62,8 @@ const EMPTY_USAGE: Usage = {
39
62
  turns: 0,
40
63
  };
41
64
 
42
- function nextVersion(): number {
43
- return versionCounter++;
65
+ function nextVersion(store: SlashSnapshotStore): number {
66
+ return store.versionCounter++;
44
67
  }
45
68
 
46
69
  function cloneUsage(): Usage {
@@ -60,7 +83,7 @@ function createPlaceholderResult(
60
83
  messages: EMPTY_MESSAGES,
61
84
  usage: cloneUsage(),
62
85
  progress: {
63
- ...(index !== undefined ? { index } : {}),
86
+ index: index ?? 0,
64
87
  agent,
65
88
  status,
66
89
  task,
@@ -164,6 +187,7 @@ function buildSingleInitialResult(params: SubagentParamsLike): AgentToolResult<D
164
187
  ...(params.context ? { context: params.context } : {}),
165
188
  results: [createPlaceholderResult(agent, task, "running")],
166
189
  progress: [{
190
+ index: 0,
167
191
  agent,
168
192
  status: "running",
169
193
  task,
@@ -177,14 +201,15 @@ function buildSingleInitialResult(params: SubagentParamsLike): AgentToolResult<D
177
201
  };
178
202
  }
179
203
 
180
- export function buildSlashInitialResult(requestId: string, params: SubagentParamsLike): SlashMessageDetails {
204
+ export function buildSlashInitialResult(requestId: string, params: SubagentParamsLike, owner?: object): SlashMessageDetails {
205
+ const store = getSlashSnapshotStore(owner);
181
206
  const result = (params.tasks?.length ?? 0) > 0
182
207
  ? buildParallelInitialResult(params)
183
208
  : (params.chain?.length ?? 0) > 0
184
209
  ? buildChainInitialResult(params)
185
210
  : buildSingleInitialResult(params);
186
- liveSnapshots.set(requestId, { result, version: nextVersion() });
187
- finalSnapshots.delete(requestId);
211
+ store.liveSnapshots.set(requestId, { result, version: nextVersion(store) });
212
+ store.finalSnapshots.delete(requestId);
188
213
  return { requestId, result };
189
214
  }
190
215
 
@@ -200,8 +225,9 @@ function cloneResultsWithProgress(
200
225
  });
201
226
  }
202
227
 
203
- export function applySlashUpdate(requestId: string, update: SlashSubagentUpdate): void {
204
- const snapshot = liveSnapshots.get(requestId);
228
+ export function applySlashUpdate(requestId: string, update: SlashSubagentUpdate, owner?: object): void {
229
+ const store = getSlashSnapshotStore(owner);
230
+ const snapshot = store.liveSnapshots.get(requestId);
205
231
  if (!snapshot) return;
206
232
  const progress = update.progress;
207
233
  if (!progress || !snapshot.result.details) return;
@@ -212,30 +238,32 @@ export function applySlashUpdate(requestId: string, update: SlashSubagentUpdate)
212
238
  results: cloneResultsWithProgress(snapshot.result.details.results, progress),
213
239
  ...(snapshot.result.details.mode === "chain" && currentStepIndex >= 0 ? { currentStepIndex } : {}),
214
240
  };
215
- liveSnapshots.set(requestId, {
241
+ store.liveSnapshots.set(requestId, {
216
242
  result: {
217
243
  ...snapshot.result,
218
244
  details: nextDetails,
219
245
  },
220
- version: nextVersion(),
246
+ version: nextVersion(store),
221
247
  });
222
248
  }
223
249
 
224
- export function finalizeSlashResult(response: SlashSubagentResponse): SlashMessageDetails {
250
+ export function finalizeSlashResult(response: SlashSubagentResponse, owner?: object): SlashMessageDetails {
251
+ const store = getSlashSnapshotStore(owner);
225
252
  const snapshot = {
226
253
  result: response.result,
227
- version: nextVersion(),
254
+ version: nextVersion(store),
228
255
  };
229
- finalSnapshots.set(response.requestId, snapshot);
230
- liveSnapshots.delete(response.requestId);
256
+ store.finalSnapshots.set(response.requestId, snapshot);
257
+ store.liveSnapshots.delete(response.requestId);
231
258
  return {
232
259
  requestId: response.requestId,
233
260
  result: response.result,
234
261
  };
235
262
  }
236
263
 
237
- export function failSlashResult(requestId: string, params: SubagentParamsLike, message: string): SlashMessageDetails {
238
- const initial = buildSlashInitialResult(requestId, params).result;
264
+ export function failSlashResult(requestId: string, params: SubagentParamsLike, message: string, owner?: object): SlashMessageDetails {
265
+ const store = getSlashSnapshotStore(owner);
266
+ const initial = buildSlashInitialResult(requestId, params, owner).result;
239
267
  const failedResults = initial.details.results.map((result) => ({
240
268
  ...result,
241
269
  exitCode: 1,
@@ -250,9 +278,9 @@ export function failSlashResult(requestId: string, params: SubagentParamsLike, m
250
278
  progress: failedResults.map((entry) => entry.progress!).filter(Boolean),
251
279
  },
252
280
  };
253
- const snapshot = { result, version: nextVersion() };
254
- finalSnapshots.set(requestId, snapshot);
255
- liveSnapshots.delete(requestId);
281
+ const snapshot = { result, version: nextVersion(store) };
282
+ store.finalSnapshots.set(requestId, snapshot);
283
+ store.liveSnapshots.delete(requestId);
256
284
  return { requestId, result };
257
285
  }
258
286
 
@@ -268,25 +296,28 @@ export function resolveSlashMessageDetails(value: unknown): SlashMessageDetails
268
296
  return isSlashMessageDetails(value) ? value : undefined;
269
297
  }
270
298
 
271
- export function getSlashRenderableSnapshot(details: SlashMessageDetails): SlashSnapshot {
272
- return finalSnapshots.get(details.requestId)
273
- ?? liveSnapshots.get(details.requestId)
299
+ export function getSlashRenderableSnapshot(details: SlashMessageDetails, owner?: object): SlashSnapshot {
300
+ const store = getSlashSnapshotStore(owner);
301
+ return store.finalSnapshots.get(details.requestId)
302
+ ?? store.liveSnapshots.get(details.requestId)
274
303
  ?? { result: details.result, version: 0 };
275
304
  }
276
305
 
277
- export function restoreSlashFinalSnapshots(entries: unknown[]): void {
278
- liveSnapshots.clear();
279
- finalSnapshots.clear();
306
+ export function restoreSlashFinalSnapshots(entries: unknown[], owner?: object): void {
307
+ const store = getSlashSnapshotStore(owner);
308
+ store.liveSnapshots.clear();
309
+ store.finalSnapshots.clear();
280
310
  for (const entry of entries) {
281
311
  const e = entry as { type?: string; customType?: string; details?: unknown };
282
312
  if (e?.type !== "custom_message" || e.customType !== SLASH_RESULT_TYPE) continue;
283
313
  const details = resolveSlashMessageDetails(e.details);
284
314
  if (!details) continue;
285
- finalSnapshots.set(details.requestId, { result: details.result, version: nextVersion() });
315
+ store.finalSnapshots.set(details.requestId, { result: details.result, version: nextVersion(store) });
286
316
  }
287
317
  }
288
318
 
289
- export function clearSlashSnapshots(): void {
290
- liveSnapshots.clear();
291
- finalSnapshots.clear();
319
+ export function clearSlashSnapshots(owner?: object): void {
320
+ const store = getSlashSnapshotStore(owner);
321
+ store.liveSnapshots.clear();
322
+ store.finalSnapshots.clear();
292
323
  }
@@ -61,6 +61,13 @@ export function renderSubagentResult(
61
61
  theme: Theme,
62
62
  ): Component {
63
63
  const d = result.details;
64
+ if (d?.asyncId && d.results.length === 0) {
65
+ const contextPrefix = d.context === "fork" ? `${theme.fg("warning", "[fork]")} ` : "";
66
+ const container = new Container();
67
+ container.addChild(new Text(`${contextPrefix}${theme.fg("success", "launched")} · async run ${d.asyncId}`, 0, 0));
68
+ container.addChild(new Text(theme.fg("dim", "completion pending; the detached result will be delivered when it finishes"), 0, 0));
69
+ return container;
70
+ }
64
71
  if (!d || !d.results.length) {
65
72
  const t = result.content[0];
66
73
  const text = t?.type === "text" ? t.text : "(no output)";
@@ -76,6 +76,7 @@ export function subagentResultRenderKey(
76
76
  options.expanded ? "expanded" : "compact",
77
77
  details.mode,
78
78
  details.currentStepIndex ?? "",
79
+ details.asyncId ?? "",
79
80
  details.totalSteps ?? "",
80
81
  progressRenderKey(details.progressSummary),
81
82
  progressKeys.join("|"),
@@ -60,53 +60,81 @@ interface RenderRequestingContext {
60
60
  ui: ExtensionContext["ui"] & { requestRender?: () => void };
61
61
  }
62
62
 
63
- // There is only ever one async-agents widget per host process, so the mounted
64
- // component reads its driving context/jobs/pulse frame from module-level
65
- // singletons instead of remounting the widget for every visible update.
66
- let latestWidgetCtx: ExtensionContext | undefined;
67
- let latestWidgetJobs: AsyncJobState[] = [];
68
- let latestWidgetFrameNow = 0;
69
- let latestWidgetExpanded = false;
70
- let latestWidgetSnapshotKey: string | undefined;
71
- let latestWidgetPulseFrame: number | undefined;
72
- let mountedWidgetCtx: ExtensionContext | undefined;
73
- let mountedWidgetOwnerKey: string | undefined;
74
- let widgetMounted = false;
75
-
76
- function getLatestWidgetJobs(): AsyncJobState[] {
77
- return latestWidgetJobs;
63
+ interface WidgetAnimationState {
64
+ latestCtx?: ExtensionContext;
65
+ latestJobs: AsyncJobState[];
66
+ frameNow: number;
67
+ expanded: boolean;
68
+ snapshotKey?: string;
69
+ pulseFrame?: number;
70
+ mountedCtx?: ExtensionContext;
71
+ mountedOwnerKey?: string;
72
+ surfaceKey?: object;
73
+ mounted: boolean;
78
74
  }
79
75
 
80
- function getLatestWidgetFrameNow(): number {
81
- return latestWidgetFrameNow;
76
+ interface WidgetSurfaceState {
77
+ activeOwner?: object;
82
78
  }
83
79
 
84
- function getLatestWidgetPulseFrame(): number | undefined {
85
- return latestWidgetPulseFrame;
80
+ interface WidgetRegistry {
81
+ states: WeakMap<object, WidgetAnimationState>;
82
+ surfaces: WeakMap<object, WidgetSurfaceState>;
86
83
  }
87
84
 
88
- function getLatestWidgetExpanded(): boolean {
89
- // LiveWidgetComponent re-renders outside a specific renderWidget() call, so
90
- // remember the last expansion state observed from a live host UI. Workflow
91
- // stage-node detach can briefly repaint the mounted singleton with a stale or
92
- // no-UI context before the next subagent status update refreshes it; falling
93
- // back to the cached value avoids a transient collapse while jobs keep running.
94
- if (!latestWidgetCtx?.hasUI) return latestWidgetExpanded;
95
- const expanded = latestWidgetCtx.ui.getToolsExpanded?.();
96
- if (typeof expanded === "boolean") latestWidgetExpanded = expanded;
97
- return latestWidgetExpanded;
85
+ const defaultWidgetOwner = {};
86
+
87
+ function getWidgetRegistry(): WidgetRegistry {
88
+ const key = "__piSubagentWidgetRegistry";
89
+ const globalStore = globalThis as Record<string, unknown>;
90
+ const existing = globalStore[key] as WidgetRegistry | undefined;
91
+ if (existing?.states instanceof WeakMap && existing.surfaces instanceof WeakMap) return existing;
92
+ const registry: WidgetRegistry = { states: new WeakMap(), surfaces: new WeakMap() };
93
+ globalStore[key] = registry;
94
+ return registry;
95
+ }
96
+
97
+ function getWidgetState(owner: object): WidgetAnimationState {
98
+ const registry = getWidgetRegistry();
99
+ const existing = registry.states.get(owner);
100
+ if (existing) return existing;
101
+ const state: WidgetAnimationState = {
102
+ latestJobs: [],
103
+ frameNow: 0,
104
+ expanded: false,
105
+ mounted: false,
106
+ };
107
+ registry.states.set(owner, state);
108
+ return state;
109
+ }
110
+
111
+ function getSurfaceState(surfaceKey: object): WidgetSurfaceState {
112
+ const registry = getWidgetRegistry();
113
+ const existing = registry.surfaces.get(surfaceKey);
114
+ if (existing) return existing;
115
+ const surface = {};
116
+ registry.surfaces.set(surfaceKey, surface);
117
+ return surface;
118
+ }
119
+
120
+ function getExpanded(state: WidgetAnimationState): boolean {
121
+ if (!state.latestCtx?.hasUI) return state.expanded;
122
+ const expanded = state.latestCtx.ui.getToolsExpanded?.();
123
+ if (typeof expanded === "boolean") state.expanded = expanded;
124
+ return state.expanded;
98
125
  }
99
126
 
100
- function clearLatestWidgetState(): void {
101
- latestWidgetCtx = undefined;
102
- latestWidgetJobs = [];
103
- latestWidgetFrameNow = 0;
104
- latestWidgetExpanded = false;
105
- latestWidgetSnapshotKey = undefined;
106
- latestWidgetPulseFrame = undefined;
107
- mountedWidgetCtx = undefined;
108
- mountedWidgetOwnerKey = undefined;
109
- widgetMounted = false;
127
+ function clearWidgetState(state: WidgetAnimationState): void {
128
+ state.latestCtx = undefined;
129
+ state.latestJobs = [];
130
+ state.frameNow = 0;
131
+ state.expanded = false;
132
+ state.snapshotKey = undefined;
133
+ state.pulseFrame = undefined;
134
+ state.mountedCtx = undefined;
135
+ state.mountedOwnerKey = undefined;
136
+ state.surfaceKey = undefined;
137
+ state.mounted = false;
110
138
  }
111
139
 
112
140
  function getWidgetOwnerKey(ctx: ExtensionContext): string {
@@ -183,19 +211,33 @@ function widgetSnapshotKey(jobs: AsyncJobState[]): string {
183
211
  return jobs.map(widgetRenderKey).join("\n");
184
212
  }
185
213
 
186
- function refreshWidgetSnapshot(jobs: AsyncJobState[]): void {
214
+ function refreshWidgetSnapshot(state: WidgetAnimationState, jobs: AsyncJobState[]): void {
187
215
  const snapshotKey = widgetSnapshotKey(jobs);
188
- if (snapshotKey === latestWidgetSnapshotKey) return;
189
- latestWidgetSnapshotKey = snapshotKey;
190
- latestWidgetFrameNow = Date.now();
191
- latestWidgetPulseFrame = advanceResultPulseFrame(latestWidgetPulseFrame);
216
+ if (snapshotKey === state.snapshotKey) return;
217
+ state.snapshotKey = snapshotKey;
218
+ state.frameNow = Date.now();
219
+ state.pulseFrame = advanceResultPulseFrame(state.pulseFrame);
192
220
  }
193
221
 
194
- // Full teardown: clear the mounted widget if possible, and forget the driving
195
- // context/jobs entirely.
196
- export function stopWidgetAnimation(): void {
197
- if (widgetMounted) unmountWidgetBestEffort(mountedWidgetCtx);
198
- clearLatestWidgetState();
222
+ function releaseMountedWidget(state: WidgetAnimationState, owner: object): void {
223
+ if (state.mounted) unmountWidgetBestEffort(state.mountedCtx);
224
+ if (state.surfaceKey) {
225
+ const surface = getSurfaceState(state.surfaceKey);
226
+ if (surface.activeOwner === owner) surface.activeOwner = undefined;
227
+ }
228
+ clearWidgetState(state);
229
+ }
230
+
231
+ // Full teardown. Explicit API ownership is authoritative; logical context
232
+ // matching only protects context-driven teardown from stale session wrappers.
233
+ export function stopWidgetAnimation(ownerCtx?: ExtensionContext, owner: object = defaultWidgetOwner): void {
234
+ const state = getWidgetState(owner);
235
+ if (ownerCtx && state.mounted && state.mountedOwnerKey !== getWidgetOwnerKey(ownerCtx)) return;
236
+ if (state.surfaceKey && getSurfaceState(state.surfaceKey).activeOwner !== owner) {
237
+ clearWidgetState(state);
238
+ return;
239
+ }
240
+ releaseMountedWidget(state, owner);
199
241
  }
200
242
 
201
243
  export function buildWidgetLines(jobs: AsyncJobState[], theme: Theme, width = getTermWidth(), expanded = false, now: number = Date.now(), pulseFrame?: number): string[] {
@@ -268,57 +310,54 @@ export function buildWidgetLines(jobs: AsyncJobState[], theme: Theme, width = ge
268
310
  return lines;
269
311
  }
270
312
 
271
- /**
272
- * Render the async jobs widget
273
- */
274
- export function renderWidget(ctx: ExtensionContext, jobs: AsyncJobState[]): void {
313
+ /** Render the async jobs widget for one ExtensionAPI owner. */
314
+ export function renderWidget(ctx: ExtensionContext, jobs: AsyncJobState[], owner: object = defaultWidgetOwner): void {
315
+ const state = getWidgetState(owner);
275
316
  const ownerKey = getWidgetOwnerKey(ctx);
317
+ const requestedSurfaceKey = ctx.ui.setWidget;
318
+ const requestedSurface = getSurfaceState(requestedSurfaceKey);
276
319
  if (jobs.length === 0) {
277
- if (widgetMounted && mountedWidgetOwnerKey !== ownerKey) {
278
- // With no visible job frame, stale-owner empty updates and newly-active
279
- // empty owners are indistinguishable here. Preserve active-widget safety;
280
- // host session disposal owns cross-owner empty-session teardown.
281
- return;
282
- }
320
+ if (requestedSurface.activeOwner && requestedSurface.activeOwner !== owner) return;
321
+ if (state.surfaceKey && getSurfaceState(state.surfaceKey).activeOwner !== owner) return;
322
+ if (state.mounted && state.mountedOwnerKey !== ownerKey) return;
283
323
  if (ctx.hasUI) setWidgetStatus(ctx, []);
284
- stopWidgetAnimation();
324
+ stopWidgetAnimation(ctx, owner);
285
325
  return;
286
326
  }
287
327
  if (!ctx.hasUI) {
288
- stopWidgetAnimation();
328
+ stopWidgetAnimation(ctx, owner);
289
329
  return;
290
330
  }
291
- latestWidgetCtx = ctx;
292
- latestWidgetJobs = [...jobs];
293
- refreshWidgetSnapshot(jobs);
294
- if (widgetMounted && mountedWidgetOwnerKey !== ownerKey) {
295
- // Session rebinding can leave the previous host UI alive briefly; clear the
296
- // old mount before installing the singleton widget on the new owner/context.
297
- unmountWidgetBestEffort(mountedWidgetCtx);
298
- mountedWidgetCtx = undefined;
299
- mountedWidgetOwnerKey = undefined;
300
- widgetMounted = false;
331
+ // Workflow stages forward the host's setWidget function, which identifies the
332
+ // shared widget surface. A stage cannot replace a parent already active there.
333
+ if (!state.mounted && requestedSurface.activeOwner && requestedSurface.activeOwner !== owner) return;
334
+ state.latestCtx = ctx;
335
+ state.latestJobs = [...jobs];
336
+ refreshWidgetSnapshot(state, jobs);
337
+ if (state.mounted && state.mountedOwnerKey !== ownerKey) {
338
+ releaseMountedWidget(state, owner);
339
+ state.latestCtx = ctx;
340
+ state.latestJobs = [...jobs];
341
+ refreshWidgetSnapshot(state, jobs);
301
342
  }
302
343
  setWidgetStatus(ctx, jobs);
303
- if (!widgetMounted) {
304
- // belowEditor keeps the live async widget pinned to the bottom viewport,
305
- // matching the workflow companion widget's placement (#1109). The pulse frame
306
- // is advanced only by semantic async status updates, not by a cosmetic timer.
307
- ctx.ui.setWidget(WIDGET_KEY, buildWidgetComponent(getLatestWidgetJobs, getLatestWidgetExpanded, getLatestWidgetFrameNow, getLatestWidgetPulseFrame), {
308
- placement: "belowEditor",
309
- });
310
- mountedWidgetCtx = ctx;
311
- mountedWidgetOwnerKey = ownerKey;
312
- widgetMounted = true;
344
+ if (!state.mounted) {
345
+ const surface = getSurfaceState(requestedSurfaceKey);
346
+ if (surface.activeOwner && surface.activeOwner !== owner) return;
347
+ ctx.ui.setWidget(WIDGET_KEY, buildWidgetComponent(
348
+ () => state.latestJobs,
349
+ () => getExpanded(state),
350
+ () => state.frameNow,
351
+ () => state.pulseFrame,
352
+ ), { placement: "belowEditor" });
353
+ state.mountedCtx = ctx;
354
+ state.mountedOwnerKey = ownerKey;
355
+ state.surfaceKey = requestedSurfaceKey;
356
+ state.mounted = true;
357
+ surface.activeOwner = owner;
313
358
  } else {
314
- // The mounted widget reads latestWidgetJobs via getLatestWidgetJobs(), so a
315
- // visible->visible update only needs to ask the host to render in place. Keep
316
- // teardown pointed at the freshest same-owner wrapper because older wrappers
317
- // can go stale after host session/context rebinding.
318
- mountedWidgetCtx = ctx;
319
- mountedWidgetOwnerKey = ownerKey;
359
+ state.mountedCtx = ctx;
360
+ state.mountedOwnerKey = ownerKey;
320
361
  requestWidgetRender(ctx);
321
362
  }
322
- // The async pulse is update-driven like foreground subagent results, so no
323
- // periodic cosmetic ticker is needed.
324
363
  }
@@ -4,6 +4,34 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.5] - 2026-07-11
8
+
9
+ ### Changed
10
+
11
+ - Aligned the web-access extension peer dependency with upstream `pi-tui` `^0.80.6` as part of the consolidated Pi sync; no web-access source behavior changed ([#1703](https://github.com/bastani-inc/atomic/issues/1703)).
12
+
13
+ ### Fixed
14
+
15
+ - Retry failed lazy initialization and initial or later-generation lifecycle replays before a subsequent `web_search` or `fetch_content` executes, while concurrent cold/retry callers share one attempt ([#1704](https://github.com/bastani-inc/atomic/issues/1704)).
16
+ - Fixed native Bun loading of the heavy web-access graph by resolving pi-ai compatibility helpers from the installed `@earendil-works/pi-ai/compat` package, so `web_search`, `code_search`, `fetch_content`, and `get_search_content` initialize through their lazy wrappers ([#1728](https://github.com/bastani-inc/atomic/issues/1728)).
17
+ - Made lazy lifecycle replay generation-safe and session-leased: replay is committed only after successful dispatch, lifecycle changes during replay advance to the latest snapshot, shutdown does not report completion until retired replay/initializer cleanup settles, calls spanning teardown reject, and replacement wrappers cannot be mutated by late old cleanup.
18
+ - Recheck each invocation's abort signal after shared lazy initialization and provider/curator execution, preserving the exact host abort reason without cancelling initialization for other callers while keeping explicit curator user cancellation result-shaped.
19
+ - Classify non-empty all-failed search/fetch batches as host-visible tool errors with provider/fetch stage diagnostics while retaining per-item payloads and keeping partial successes successful.
20
+
21
+ ## [0.9.5-alpha.10] - 2026-07-11
22
+
23
+ ### Changed
24
+
25
+ - Aligned the web-access extension peer dependency with upstream `pi-tui` `^0.80.6` as part of the consolidated Pi sync; no web-access source behavior changed ([#1703](https://github.com/bastani-inc/atomic/issues/1703)).
26
+
27
+ ### Fixed
28
+
29
+ - Retry failed lazy initialization and initial or later-generation lifecycle replays before a subsequent `web_search` or `fetch_content` executes, while concurrent cold/retry callers share one attempt ([#1704](https://github.com/bastani-inc/atomic/issues/1704)).
30
+ - Fixed native Bun loading of the heavy web-access graph by resolving pi-ai compatibility helpers from the installed `@earendil-works/pi-ai/compat` package, so `web_search`, `code_search`, `fetch_content`, and `get_search_content` initialize through their lazy wrappers ([#1728](https://github.com/bastani-inc/atomic/issues/1728)).
31
+ - Made lazy lifecycle replay generation-safe and session-leased: replay is committed only after successful dispatch, lifecycle changes during replay advance to the latest snapshot, shutdown does not report completion until retired replay/initializer cleanup settles, calls spanning teardown reject, and replacement wrappers cannot be mutated by late old cleanup.
32
+ - Recheck each invocation's abort signal after shared lazy initialization and provider/curator execution, preserving the exact host abort reason without cancelling initialization for other callers while keeping explicit curator user cancellation result-shaped.
33
+ - Classify non-empty all-failed search/fetch batches as host-visible tool errors with provider/fetch stage diagnostics while retaining per-item payloads and keeping partial successes successful.
34
+
7
35
  ## [0.9.4] - 2026-07-03
8
36
 
9
37
  ### Changed
@@ -72,6 +72,10 @@ fetch_content({ url: "/path/to/recording.mp4", prompt: "What error appears on sc
72
72
 
73
73
  ## Tools
74
74
 
75
+ The public tools register immediately and share one lazy initialization attempt on first use. Calls wait for initialization and active-session replay before provider work begins; a rejected initializer or replay can be retried by a later call. Initialization and replay are leased to the active session: shutdown retires the lease and cleans its candidate, so calls spanning shutdown reject and a restarted session creates a fresh provider wrapper. An abort that arrives during the shared wait cancels only that invocation. Host cancellation after provider or curator work rejects with the exact host abort reason, while an explicit user action in the curator remains a successful `{ cancelled: true, cancelReason: "user" }` result. Resetting the application-owned attempt does not guarantee re-evaluation of an ESM module whose evaluation itself failed.
76
+
77
+ For batch search/fetch calls, partial success remains usable and retains item-level errors. A non-empty batch where every provider request or URL fetch fails is reported through Atomic's tool-error channel with aggregate stage metadata while the per-item diagnostics remain stored in the result.
78
+
75
79
  ### web_search
76
80
 
77
81
  Search the web via Exa, Perplexity AI, or Gemini. Returns a synthesized answer with source citations.
@@ -1,5 +1,5 @@
1
1
  import type { ExtensionAPI } from "@bastani/atomic";
2
- import { Text } from "@mariozechner/pi-tui";
2
+ import { Text } from "@earendil-works/pi-tui";
3
3
  import { Type } from "typebox";
4
4
  import {
5
5
  renderCodeSearchResult,
@@ -102,6 +102,7 @@ export function registerContentTools(pi: ExtensionAPI, deps: RegisterContentTool
102
102
  frames: params.frames,
103
103
  model: params.model,
104
104
  });
105
+ signal?.throwIfAborted();
105
106
  const successful = fetchResults.filter((r) => !r.error).length;
106
107
  const totalChars = fetchResults.reduce((sum, r) => sum + r.content.length, 0);
107
108
 
@@ -120,7 +121,7 @@ export function registerContentTools(pi: ExtensionAPI, deps: RegisterContentTool
120
121
  if (result.error) {
121
122
  return {
122
123
  content: [{ type: "text", text: `Error: ${result.error}` }],
123
- details: { urls: urlList, urlCount: 1, successful: 0, error: result.error, responseId, prompt: params.prompt, timestamp: params.timestamp, frames: params.frames },
124
+ details: { outcome: "all_failed", stage: "fetch", urls: urlList, urlCount: 1, successful: 0, error: result.error, responseId, prompt: params.prompt, timestamp: params.timestamp, frames: params.frames },
124
125
  };
125
126
  }
126
127
 
@@ -177,9 +178,13 @@ export function registerContentTools(pi: ExtensionAPI, deps: RegisterContentTool
177
178
  }
178
179
  output += `\n---\nUse get_search_content({ responseId: "${responseId}", urlIndex: 0 }) to retrieve full content.`;
179
180
 
181
+ const allFailed = successful === 0;
180
182
  return {
181
183
  content: [{ type: "text", text: output }],
182
- details: { urls: urlList, urlCount: urlList.length, successful, totalChars, responseId },
184
+ details: {
185
+ ...(allFailed ? { outcome: "all_failed", stage: "fetch", error: `All ${urlList.length} URL fetch(es) failed`, failedUrls: urlList.length } : {}),
186
+ urls: urlList, urlCount: urlList.length, successful, totalChars, responseId,
187
+ },
183
188
  };
184
189
  },
185
190
 
@@ -2,7 +2,7 @@ import type { ExtensionAPI } from "@bastani/atomic";
2
2
  import { CONFIG_DIR_NAME } from "@bastani/atomic";
3
3
  import { appendFileSync } from "node:fs";
4
4
  import { getActiveGoogleEmail, isGeminiWebAvailable } from "./gemini-web.js";
5
- import { isBrowserCookieAccessAllowed } from "./gemini-web-config.ts";
5
+ import { isBrowserCookieAccessAllowed } from "./gemini-web-config.js";
6
6
  import { deleteResult, getAllResults } from "./storage.js";
7
7
  import { loadConfigForExtensionInit, resolveWorkflow, saveConfig, type WebSearchWorkflow } from "./web-search-config.js";
8
8