@astralyn/pi 0.87.6 → 0.99.0

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 (698) hide show
  1. package/CHANGELOG.md +30 -6
  2. package/README.md +3 -3
  3. package/dist/bun/runtime-setup.js +4 -1
  4. package/dist/bun/runtime-setup.js.map +1 -1
  5. package/dist/bundle/chunks/anthropic-messages-KIXY7EDT.js +6 -0
  6. package/dist/bundle/chunks/anthropic.js +2 -2
  7. package/dist/bundle/chunks/azure-openai-responses-RPBERDXD.js +2 -0
  8. package/dist/bundle/chunks/bedrock-converse-stream.js +8 -8
  9. package/dist/bundle/chunks/{chunk-LPQCB2VJ.js → chunk-A576H74Y.js} +2 -2
  10. package/dist/bundle/chunks/{chunk-NW5FIDD7.js → chunk-ABVRAYXT.js} +3 -3
  11. package/dist/bundle/chunks/{chunk-I5IVW2WS.js → chunk-CLLDCO64.js} +1 -1
  12. package/dist/bundle/chunks/chunk-DEWXBB6W.js +2 -0
  13. package/dist/bundle/chunks/chunk-G4RY3GN7.js +11 -0
  14. package/dist/bundle/chunks/chunk-GCKVOFWP.js +2 -0
  15. package/dist/bundle/chunks/chunk-MPDALHNJ.js +2 -0
  16. package/dist/bundle/chunks/chunk-OO6DJ3CL.js +31 -0
  17. package/dist/bundle/chunks/{chunk-4W4Q2H6W.js → chunk-VW2P3X6P.js} +905 -278
  18. package/dist/bundle/chunks/chunk-VWCWZD6E.js +2 -0
  19. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-ZYSAFXXL.js +2 -0
  20. package/dist/bundle/chunks/codemode-worker.js +295 -0
  21. package/dist/bundle/chunks/github-copilot.js +1 -1
  22. package/dist/bundle/chunks/google-generative-ai-SDNQVVXA.js +2 -0
  23. package/dist/bundle/chunks/google-vertex-LZXOLBIO.js +2 -0
  24. package/dist/bundle/chunks/llama-cpp-classify-7IYGGPND.js +22 -0
  25. package/dist/bundle/chunks/meta.js +2 -0
  26. package/dist/bundle/chunks/mistral-conversations-VYKPSSAM.js +5 -0
  27. package/dist/bundle/chunks/openai-chatgpt.js +75 -0
  28. package/dist/bundle/chunks/openai-codex-responses-HZ4VUDXD.js +10 -0
  29. package/dist/bundle/chunks/openai-codex.js +2 -2
  30. package/dist/bundle/chunks/openai-completions-SKDGF6OE.js +7 -0
  31. package/dist/bundle/chunks/openai-responses-FPML4SSG.js +3 -0
  32. package/dist/bundle/chunks/{openrouter-images-6XDE2CEW.js → openrouter-images-5524IQHX.js} +1 -1
  33. package/dist/bundle/chunks/openrouter.js +2 -2
  34. package/dist/bundle/chunks/{pi-messages-MQMPIPNC.js → pi-messages-HZZ7GEEW.js} +2 -2
  35. package/dist/bundle/chunks/radius.js +2 -2
  36. package/dist/bundle/chunks/typesafe-system-one-Z2CDLKEY.js +2 -0
  37. package/dist/bundle/chunks/virtual-modules-TQRORWJQ.js +2 -0
  38. package/dist/bundle/cli.js +1 -1
  39. package/dist/bundle/index.js +1 -1
  40. package/dist/bundle/rpc-entry.js +1 -1
  41. package/dist/cli/args.d.ts.map +1 -1
  42. package/dist/cli/args.js +4 -3
  43. package/dist/cli/args.js.map +1 -1
  44. package/dist/cli/startup-ui.d.ts.map +1 -1
  45. package/dist/cli/startup-ui.js +38 -30
  46. package/dist/cli/startup-ui.js.map +1 -1
  47. package/dist/config.d.ts +18 -4
  48. package/dist/config.d.ts.map +1 -1
  49. package/dist/config.js +30 -4
  50. package/dist/config.js.map +1 -1
  51. package/dist/core/agent-session-runtime.d.ts +1 -1
  52. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  53. package/dist/core/agent-session-runtime.js +13 -13
  54. package/dist/core/agent-session-runtime.js.map +1 -1
  55. package/dist/core/agent-session-services.d.ts +2 -2
  56. package/dist/core/agent-session-services.d.ts.map +1 -1
  57. package/dist/core/agent-session-services.js +14 -1
  58. package/dist/core/agent-session-services.js.map +1 -1
  59. package/dist/core/agent-session.d.ts +100 -35
  60. package/dist/core/agent-session.d.ts.map +1 -1
  61. package/dist/core/agent-session.js +456 -194
  62. package/dist/core/agent-session.js.map +1 -1
  63. package/dist/core/bug-report.js +1 -1
  64. package/dist/core/bug-report.js.map +1 -1
  65. package/dist/core/compaction/compaction.d.ts.map +1 -1
  66. package/dist/core/compaction/compaction.js +1 -22
  67. package/dist/core/compaction/compaction.js.map +1 -1
  68. package/dist/core/compaction/utils.d.ts +2 -1
  69. package/dist/core/compaction/utils.d.ts.map +1 -1
  70. package/dist/core/compaction/utils.js +25 -18
  71. package/dist/core/compaction/utils.js.map +1 -1
  72. package/dist/core/crash-log.d.ts.map +1 -1
  73. package/dist/core/crash-log.js +2 -1
  74. package/dist/core/crash-log.js.map +1 -1
  75. package/dist/core/export-html/template.css +10 -0
  76. package/dist/core/export-html/template.js +66 -17
  77. package/dist/core/extensions/distribution-api.d.ts +1 -1
  78. package/dist/core/extensions/distribution-api.d.ts.map +1 -1
  79. package/dist/core/extensions/distribution-api.js.map +1 -1
  80. package/dist/core/extensions/index.d.ts +2 -2
  81. package/dist/core/extensions/index.d.ts.map +1 -1
  82. package/dist/core/extensions/index.js.map +1 -1
  83. package/dist/core/extensions/loader.d.ts.map +1 -1
  84. package/dist/core/extensions/loader.js +55 -5
  85. package/dist/core/extensions/loader.js.map +1 -1
  86. package/dist/core/extensions/runner.d.ts +22 -3
  87. package/dist/core/extensions/runner.d.ts.map +1 -1
  88. package/dist/core/extensions/runner.js +124 -8
  89. package/dist/core/extensions/runner.js.map +1 -1
  90. package/dist/core/extensions/types.d.ts +305 -25
  91. package/dist/core/extensions/types.d.ts.map +1 -1
  92. package/dist/core/extensions/types.js.map +1 -1
  93. package/dist/core/extensions/wrapper.d.ts +2 -2
  94. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  95. package/dist/core/extensions/wrapper.js +3 -3
  96. package/dist/core/extensions/wrapper.js.map +1 -1
  97. package/dist/core/keybindings.d.ts +30 -5
  98. package/dist/core/keybindings.d.ts.map +1 -1
  99. package/dist/core/keybindings.js +7 -1
  100. package/dist/core/keybindings.js.map +1 -1
  101. package/dist/core/mcp-servers.d.ts +98 -0
  102. package/dist/core/mcp-servers.d.ts.map +1 -0
  103. package/dist/core/mcp-servers.js +158 -0
  104. package/dist/core/mcp-servers.js.map +1 -0
  105. package/dist/core/model-registry.d.ts +13 -1
  106. package/dist/core/model-registry.d.ts.map +1 -1
  107. package/dist/core/model-registry.js +25 -0
  108. package/dist/core/model-registry.js.map +1 -1
  109. package/dist/core/model-resolver.d.ts +2 -2
  110. package/dist/core/model-resolver.d.ts.map +1 -1
  111. package/dist/core/model-resolver.js +5 -5
  112. package/dist/core/model-resolver.js.map +1 -1
  113. package/dist/core/model-runtime.d.ts +41 -3
  114. package/dist/core/model-runtime.d.ts.map +1 -1
  115. package/dist/core/model-runtime.js +167 -17
  116. package/dist/core/model-runtime.js.map +1 -1
  117. package/dist/core/nested-tool-calls.d.ts +102 -0
  118. package/dist/core/nested-tool-calls.d.ts.map +1 -0
  119. package/dist/core/nested-tool-calls.js +177 -0
  120. package/dist/core/nested-tool-calls.js.map +1 -0
  121. package/dist/core/package-manager.d.ts +4 -0
  122. package/dist/core/package-manager.d.ts.map +1 -1
  123. package/dist/core/package-manager.js +58 -12
  124. package/dist/core/package-manager.js.map +1 -1
  125. package/dist/core/provider-composer.d.ts +40 -21
  126. package/dist/core/provider-composer.d.ts.map +1 -1
  127. package/dist/core/provider-composer.js +92 -40
  128. package/dist/core/provider-composer.js.map +1 -1
  129. package/dist/core/remote-catalog-provider.d.ts +8 -1
  130. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  131. package/dist/core/remote-catalog-provider.js +18 -3
  132. package/dist/core/remote-catalog-provider.js.map +1 -1
  133. package/dist/core/resource-loader.d.ts +7 -1
  134. package/dist/core/resource-loader.d.ts.map +1 -1
  135. package/dist/core/resource-loader.js +160 -35
  136. package/dist/core/resource-loader.js.map +1 -1
  137. package/dist/core/sdk.d.ts +3 -3
  138. package/dist/core/sdk.d.ts.map +1 -1
  139. package/dist/core/sdk.js +25 -7
  140. package/dist/core/sdk.js.map +1 -1
  141. package/dist/core/session-manager.d.ts +9 -0
  142. package/dist/core/session-manager.d.ts.map +1 -1
  143. package/dist/core/session-manager.js +22 -22
  144. package/dist/core/session-manager.js.map +1 -1
  145. package/dist/core/settings-manager.d.ts +36 -1
  146. package/dist/core/settings-manager.d.ts.map +1 -1
  147. package/dist/core/settings-manager.js +108 -2
  148. package/dist/core/settings-manager.js.map +1 -1
  149. package/dist/core/slash-commands.d.ts.map +1 -1
  150. package/dist/core/slash-commands.js +1 -0
  151. package/dist/core/slash-commands.js.map +1 -1
  152. package/dist/core/source-info.d.ts +8 -0
  153. package/dist/core/source-info.d.ts.map +1 -1
  154. package/dist/core/source-info.js +16 -0
  155. package/dist/core/source-info.js.map +1 -1
  156. package/dist/core/system-prompt.js +1 -1
  157. package/dist/core/system-prompt.js.map +1 -1
  158. package/dist/core/tasks/delivery.d.ts +40 -0
  159. package/dist/core/tasks/delivery.d.ts.map +1 -0
  160. package/dist/core/tasks/delivery.js +157 -0
  161. package/dist/core/tasks/delivery.js.map +1 -0
  162. package/dist/core/tasks/history.d.ts +4 -0
  163. package/dist/core/tasks/history.d.ts.map +1 -0
  164. package/dist/core/{background → tasks}/history.js +24 -48
  165. package/dist/core/tasks/history.js.map +1 -0
  166. package/dist/core/{background → tasks}/output.d.ts +4 -4
  167. package/dist/core/tasks/output.d.ts.map +1 -0
  168. package/dist/core/{background → tasks}/output.js +11 -11
  169. package/dist/core/tasks/output.js.map +1 -0
  170. package/dist/core/tasks/presentation.d.ts +9 -0
  171. package/dist/core/tasks/presentation.d.ts.map +1 -0
  172. package/dist/core/{background → tasks}/presentation.js +53 -51
  173. package/dist/core/tasks/presentation.js.map +1 -0
  174. package/dist/core/{background/service.d.ts → tasks/runtime.d.ts} +22 -23
  175. package/dist/core/tasks/runtime.d.ts.map +1 -0
  176. package/dist/core/{background/service.js → tasks/runtime.js} +154 -198
  177. package/dist/core/tasks/runtime.js.map +1 -0
  178. package/dist/core/tasks/session.d.ts +49 -0
  179. package/dist/core/tasks/session.d.ts.map +1 -0
  180. package/dist/core/tasks/session.js +129 -0
  181. package/dist/core/tasks/session.js.map +1 -0
  182. package/dist/core/tasks/store.d.ts +32 -0
  183. package/dist/core/tasks/store.d.ts.map +1 -0
  184. package/dist/core/tasks/store.js +135 -0
  185. package/dist/core/tasks/store.js.map +1 -0
  186. package/dist/core/{background → tasks}/types.d.ts +80 -62
  187. package/dist/core/tasks/types.d.ts.map +1 -0
  188. package/dist/core/{background → tasks}/types.js +9 -9
  189. package/dist/core/tasks/types.js.map +1 -0
  190. package/dist/core/tasks/view-data.d.ts +8 -0
  191. package/dist/core/tasks/view-data.d.ts.map +1 -0
  192. package/dist/core/tasks/view-data.js +61 -0
  193. package/dist/core/tasks/view-data.js.map +1 -0
  194. package/dist/core/tasks/view.d.ts +30 -0
  195. package/dist/core/tasks/view.d.ts.map +1 -0
  196. package/dist/core/tasks/view.js +50 -0
  197. package/dist/core/tasks/view.js.map +1 -0
  198. package/dist/core/tools/bash.d.ts +8 -93
  199. package/dist/core/tools/bash.d.ts.map +1 -1
  200. package/dist/core/tools/bash.js +8 -240
  201. package/dist/core/tools/bash.js.map +1 -1
  202. package/dist/core/tools/grep.d.ts +2 -0
  203. package/dist/core/tools/grep.d.ts.map +1 -1
  204. package/dist/core/tools/grep.js +2 -0
  205. package/dist/core/tools/grep.js.map +1 -1
  206. package/dist/core/tools/index.d.ts +2 -1
  207. package/dist/core/tools/index.d.ts.map +1 -1
  208. package/dist/core/tools/index.js +9 -0
  209. package/dist/core/tools/index.js.map +1 -1
  210. package/dist/core/tools/output-accumulator.d.ts +11 -0
  211. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  212. package/dist/core/tools/output-accumulator.js +36 -0
  213. package/dist/core/tools/output-accumulator.js.map +1 -1
  214. package/dist/core/tools/powershell.d.ts +6 -2
  215. package/dist/core/tools/powershell.d.ts.map +1 -1
  216. package/dist/core/tools/powershell.js +1 -1
  217. package/dist/core/tools/powershell.js.map +1 -1
  218. package/dist/core/tools/render-utils.d.ts +6 -0
  219. package/dist/core/tools/render-utils.d.ts.map +1 -1
  220. package/dist/core/tools/render-utils.js +26 -0
  221. package/dist/core/tools/render-utils.js.map +1 -1
  222. package/dist/core/tools/renderers/bash.d.ts +1 -1
  223. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  224. package/dist/core/tools/renderers/bash.js +9 -10
  225. package/dist/core/tools/renderers/bash.js.map +1 -1
  226. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  227. package/dist/core/tools/renderers/index.js +5 -7
  228. package/dist/core/tools/renderers/index.js.map +1 -1
  229. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  230. package/dist/core/tools/renderers/read.js +3 -2
  231. package/dist/core/tools/renderers/read.js.map +1 -1
  232. package/dist/core/tools/renderers/shell-task.d.ts +4 -0
  233. package/dist/core/tools/renderers/shell-task.d.ts.map +1 -0
  234. package/dist/core/tools/renderers/shell-task.js +35 -0
  235. package/dist/core/tools/renderers/shell-task.js.map +1 -0
  236. package/dist/core/tools/shell-execution.d.ts +4 -5
  237. package/dist/core/tools/shell-execution.d.ts.map +1 -1
  238. package/dist/core/tools/shell-execution.js +19 -3
  239. package/dist/core/tools/shell-execution.js.map +1 -1
  240. package/dist/core/tools/shell-tool.d.ts +93 -0
  241. package/dist/core/tools/shell-tool.d.ts.map +1 -0
  242. package/dist/core/tools/shell-tool.js +251 -0
  243. package/dist/core/tools/shell-tool.js.map +1 -0
  244. package/dist/core/tools/tasks/actions.d.ts +12 -0
  245. package/dist/core/tools/tasks/actions.d.ts.map +1 -0
  246. package/dist/{extensions/background → core/tools/tasks}/actions.js +20 -19
  247. package/dist/core/tools/tasks/actions.js.map +1 -0
  248. package/dist/{extensions/background → core/tools/tasks}/constants.d.ts +10 -10
  249. package/dist/core/tools/tasks/constants.d.ts.map +1 -0
  250. package/dist/{extensions/background → core/tools/tasks}/constants.js +10 -10
  251. package/dist/core/tools/tasks/constants.js.map +1 -0
  252. package/dist/{extensions/background → core/tools/tasks}/schema.d.ts +6 -6
  253. package/dist/core/tools/tasks/schema.d.ts.map +1 -0
  254. package/dist/{extensions/background → core/tools/tasks}/schema.js +17 -17
  255. package/dist/core/tools/tasks/schema.js.map +1 -0
  256. package/dist/{extensions/background → core/tools/tasks}/types.d.ts +15 -17
  257. package/dist/core/tools/tasks/types.d.ts.map +1 -0
  258. package/dist/core/tools/tasks/types.js.map +1 -0
  259. package/dist/core/tools/tasks.d.ts +14 -0
  260. package/dist/core/tools/tasks.d.ts.map +1 -0
  261. package/dist/core/tools/tasks.js +40 -0
  262. package/dist/core/tools/tasks.js.map +1 -0
  263. package/dist/core/tools/tool-definition-wrapper.d.ts +4 -3
  264. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  265. package/dist/core/tools/tool-definition-wrapper.js +4 -2
  266. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  267. package/dist/core/tools/truncate.d.ts +14 -0
  268. package/dist/core/tools/truncate.d.ts.map +1 -1
  269. package/dist/core/tools/truncate.js +29 -0
  270. package/dist/core/tools/truncate.js.map +1 -1
  271. package/dist/core/trust-manager.d.ts.map +1 -1
  272. package/dist/core/trust-manager.js +1 -0
  273. package/dist/core/trust-manager.js.map +1 -1
  274. package/dist/core/usage-totals.d.ts +5 -3
  275. package/dist/core/usage-totals.d.ts.map +1 -1
  276. package/dist/core/usage-totals.js +27 -4
  277. package/dist/core/usage-totals.js.map +1 -1
  278. package/dist/core/virtual-models.d.ts +115 -0
  279. package/dist/core/virtual-models.d.ts.map +1 -0
  280. package/dist/core/virtual-models.js +117 -0
  281. package/dist/core/virtual-models.js.map +1 -0
  282. package/dist/extensions/codemode/execute.d.ts +16 -0
  283. package/dist/extensions/codemode/execute.d.ts.map +1 -0
  284. package/dist/extensions/codemode/execute.js +390 -0
  285. package/dist/extensions/codemode/execute.js.map +1 -0
  286. package/dist/extensions/codemode/execute.lazy.d.ts +3 -0
  287. package/dist/extensions/codemode/execute.lazy.d.ts.map +1 -0
  288. package/dist/extensions/codemode/execute.lazy.js +3 -0
  289. package/dist/extensions/codemode/execute.lazy.js.map +1 -0
  290. package/dist/extensions/codemode/index.d.ts +21 -0
  291. package/dist/extensions/codemode/index.d.ts.map +1 -0
  292. package/dist/extensions/codemode/index.js +36 -0
  293. package/dist/extensions/codemode/index.js.map +1 -0
  294. package/dist/extensions/codemode/renderer.d.ts +12 -0
  295. package/dist/extensions/codemode/renderer.d.ts.map +1 -0
  296. package/dist/extensions/codemode/renderer.js +119 -0
  297. package/dist/extensions/codemode/renderer.js.map +1 -0
  298. package/dist/extensions/codemode/search.d.ts +33 -0
  299. package/dist/extensions/codemode/search.d.ts.map +1 -0
  300. package/dist/extensions/codemode/search.js +117 -0
  301. package/dist/extensions/codemode/search.js.map +1 -0
  302. package/dist/extensions/codemode/tool.d.ts +122 -0
  303. package/dist/extensions/codemode/tool.d.ts.map +1 -0
  304. package/dist/extensions/codemode/tool.js +324 -0
  305. package/dist/extensions/codemode/tool.js.map +1 -0
  306. package/dist/extensions/codemode/worker.d.ts +7 -0
  307. package/dist/extensions/codemode/worker.d.ts.map +1 -0
  308. package/dist/extensions/codemode/worker.js +7 -0
  309. package/dist/extensions/codemode/worker.js.map +1 -0
  310. package/dist/extensions/deepwiki/schema.d.ts +1 -1
  311. package/dist/extensions/index.d.ts.map +1 -1
  312. package/dist/extensions/index.js +14 -12
  313. package/dist/extensions/index.js.map +1 -1
  314. package/dist/extensions/llama/provider.d.ts +1 -1
  315. package/dist/extensions/llama/provider.d.ts.map +1 -1
  316. package/dist/extensions/llama/provider.js +65 -13
  317. package/dist/extensions/llama/provider.js.map +1 -1
  318. package/dist/extensions/mcp/cli.d.ts +21 -0
  319. package/dist/extensions/mcp/cli.d.ts.map +1 -0
  320. package/dist/extensions/mcp/cli.js +485 -0
  321. package/dist/extensions/mcp/cli.js.map +1 -0
  322. package/dist/extensions/mcp/cli.lazy.d.ts +3 -0
  323. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -0
  324. package/dist/extensions/mcp/cli.lazy.js +3 -0
  325. package/dist/extensions/mcp/cli.lazy.js.map +1 -0
  326. package/dist/extensions/mcp/config.d.ts +70 -0
  327. package/dist/extensions/mcp/config.d.ts.map +1 -0
  328. package/dist/extensions/mcp/config.js +146 -0
  329. package/dist/extensions/mcp/config.js.map +1 -0
  330. package/dist/extensions/mcp/index.d.ts +52 -0
  331. package/dist/extensions/mcp/index.d.ts.map +1 -0
  332. package/dist/extensions/mcp/index.js +904 -0
  333. package/dist/extensions/mcp/index.js.map +1 -0
  334. package/dist/extensions/mcp/log.d.ts +16 -0
  335. package/dist/extensions/mcp/log.d.ts.map +1 -0
  336. package/dist/extensions/mcp/log.js +64 -0
  337. package/dist/extensions/mcp/log.js.map +1 -0
  338. package/dist/extensions/mcp/oauth.d.ts +94 -0
  339. package/dist/extensions/mcp/oauth.d.ts.map +1 -0
  340. package/dist/extensions/mcp/oauth.js +330 -0
  341. package/dist/extensions/mcp/oauth.js.map +1 -0
  342. package/dist/extensions/mcp/resources.d.ts +43 -0
  343. package/dist/extensions/mcp/resources.d.ts.map +1 -0
  344. package/dist/extensions/mcp/resources.js +262 -0
  345. package/dist/extensions/mcp/resources.js.map +1 -0
  346. package/dist/extensions/mcp/runtime.d.ts +96 -0
  347. package/dist/extensions/mcp/runtime.d.ts.map +1 -0
  348. package/dist/extensions/mcp/runtime.js +372 -0
  349. package/dist/extensions/mcp/runtime.js.map +1 -0
  350. package/dist/extensions/mcp/runtime.lazy.d.ts +3 -0
  351. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -0
  352. package/dist/extensions/mcp/runtime.lazy.js +3 -0
  353. package/dist/extensions/mcp/runtime.lazy.js.map +1 -0
  354. package/dist/extensions/mcp/tools.d.ts +83 -0
  355. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  356. package/dist/extensions/mcp/tools.js +233 -0
  357. package/dist/extensions/mcp/tools.js.map +1 -0
  358. package/dist/extensions/mcp/ui.d.ts +60 -0
  359. package/dist/extensions/mcp/ui.d.ts.map +1 -0
  360. package/dist/extensions/mcp/ui.js +166 -0
  361. package/dist/extensions/mcp/ui.js.map +1 -0
  362. package/dist/extensions/statusline/index.js +2 -2
  363. package/dist/extensions/statusline/index.js.map +1 -1
  364. package/dist/extensions/tool-search/index.d.ts +12 -0
  365. package/dist/extensions/tool-search/index.d.ts.map +1 -0
  366. package/dist/extensions/tool-search/index.js +20 -0
  367. package/dist/extensions/tool-search/index.js.map +1 -0
  368. package/dist/extensions/tool-search/tool.d.ts +72 -0
  369. package/dist/extensions/tool-search/tool.d.ts.map +1 -0
  370. package/dist/extensions/tool-search/tool.js +208 -0
  371. package/dist/extensions/tool-search/tool.js.map +1 -0
  372. package/dist/index.d.ts +13 -4
  373. package/dist/index.d.ts.map +1 -1
  374. package/dist/index.js +7 -1
  375. package/dist/index.js.map +1 -1
  376. package/dist/main.d.ts.map +1 -1
  377. package/dist/main.js +10 -0
  378. package/dist/main.js.map +1 -1
  379. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  380. package/dist/modes/interactive/components/config-selector.js +13 -3
  381. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  382. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  383. package/dist/modes/interactive/components/custom-message.js +3 -1
  384. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  385. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  386. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  387. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  388. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  389. package/dist/modes/interactive/components/footer.d.ts +7 -0
  390. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  391. package/dist/modes/interactive/components/footer.js +42 -3
  392. package/dist/modes/interactive/components/footer.js.map +1 -1
  393. package/dist/modes/interactive/components/pi-logo.d.ts +12 -0
  394. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -0
  395. package/dist/modes/interactive/components/pi-logo.js +25 -0
  396. package/dist/modes/interactive/components/pi-logo.js.map +1 -0
  397. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  398. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  399. package/dist/modes/interactive/components/settings-selector.js +28 -6
  400. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  401. package/dist/modes/interactive/components/status-marker.d.ts +2 -2
  402. package/dist/modes/interactive/components/status-marker.js +2 -2
  403. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  404. package/dist/modes/interactive/components/themed-text.d.ts +17 -0
  405. package/dist/modes/interactive/components/themed-text.d.ts.map +1 -0
  406. package/dist/modes/interactive/components/themed-text.js +28 -0
  407. package/dist/modes/interactive/components/themed-text.js.map +1 -0
  408. package/dist/modes/interactive/interactive-mode.d.ts +2 -4
  409. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  410. package/dist/modes/interactive/interactive-mode.js +214 -163
  411. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  412. package/dist/modes/interactive/tasks/completion-render.d.ts +8 -0
  413. package/dist/modes/interactive/tasks/completion-render.d.ts.map +1 -0
  414. package/dist/{extensions/background → modes/interactive/tasks}/completion-render.js +31 -27
  415. package/dist/modes/interactive/tasks/completion-render.js.map +1 -0
  416. package/dist/modes/interactive/tasks/fallback-view.d.ts +4 -0
  417. package/dist/modes/interactive/tasks/fallback-view.d.ts.map +1 -0
  418. package/dist/modes/interactive/tasks/fallback-view.js +27 -0
  419. package/dist/modes/interactive/tasks/fallback-view.js.map +1 -0
  420. package/dist/modes/interactive/tasks/index.d.ts +12 -0
  421. package/dist/modes/interactive/tasks/index.d.ts.map +1 -0
  422. package/dist/modes/interactive/tasks/index.js +97 -0
  423. package/dist/modes/interactive/tasks/index.js.map +1 -0
  424. package/dist/modes/interactive/tasks/manager.d.ts +67 -0
  425. package/dist/modes/interactive/tasks/manager.d.ts.map +1 -0
  426. package/dist/modes/interactive/tasks/manager.js +380 -0
  427. package/dist/modes/interactive/tasks/manager.js.map +1 -0
  428. package/dist/{extensions/background → modes/interactive/tasks}/render.d.ts +13 -13
  429. package/dist/modes/interactive/tasks/render.d.ts.map +1 -0
  430. package/dist/{extensions/background → modes/interactive/tasks}/render.js +18 -18
  431. package/dist/modes/interactive/tasks/render.js.map +1 -0
  432. package/dist/{extensions/background → modes/interactive/tasks}/task-view.d.ts +7 -7
  433. package/dist/modes/interactive/tasks/task-view.d.ts.map +1 -0
  434. package/dist/{extensions/background → modes/interactive/tasks}/task-view.js +4 -4
  435. package/dist/modes/interactive/tasks/task-view.js.map +1 -0
  436. package/dist/{extensions/background → modes/interactive/tasks}/text.d.ts +1 -1
  437. package/dist/modes/interactive/tasks/text.d.ts.map +1 -0
  438. package/dist/{extensions/background → modes/interactive/tasks}/text.js +1 -1
  439. package/dist/modes/interactive/tasks/text.js.map +1 -0
  440. package/dist/modes/interactive/tasks/viewport.d.ts +15 -0
  441. package/dist/modes/interactive/tasks/viewport.d.ts.map +1 -0
  442. package/dist/modes/interactive/tasks/viewport.js +49 -0
  443. package/dist/modes/interactive/tasks/viewport.js.map +1 -0
  444. package/dist/modes/interactive/theme/dark.json +59 -72
  445. package/dist/modes/interactive/theme/light.json +57 -69
  446. package/dist/modes/interactive/theme/system-theme.d.ts +54 -0
  447. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
  448. package/dist/modes/interactive/theme/system-theme.js +535 -0
  449. package/dist/modes/interactive/theme/system-theme.js.map +1 -0
  450. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  451. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  452. package/dist/modes/interactive/theme/theme-controller.js +125 -47
  453. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  454. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  455. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -1
  456. package/dist/modes/interactive/theme/theme-json.js +3 -1
  457. package/dist/modes/interactive/theme/theme-json.js.map +1 -1
  458. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  459. package/dist/modes/interactive/theme/theme.d.ts +70 -39
  460. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  461. package/dist/modes/interactive/theme/theme.js +247 -313
  462. package/dist/modes/interactive/theme/theme.js.map +1 -1
  463. package/dist/modes/interactive/tool-view/fallback.d.ts +1 -1
  464. package/dist/modes/interactive/tool-view/fallback.d.ts.map +1 -1
  465. package/dist/modes/interactive/tool-view/fallback.js +4 -1
  466. package/dist/modes/interactive/tool-view/fallback.js.map +1 -1
  467. package/dist/modes/interactive/tool-view/tool-execution.js +2 -2
  468. package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -1
  469. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  470. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  471. package/dist/modes/interactive/tui-renderer.js +1 -0
  472. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  473. package/dist/modes/rpc/rpc-client.d.ts +6 -6
  474. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  475. package/dist/modes/rpc/rpc-client.js +12 -8
  476. package/dist/modes/rpc/rpc-client.js.map +1 -1
  477. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  478. package/dist/modes/rpc/rpc-mode.js +7 -9
  479. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  480. package/dist/modes/rpc/rpc-types.d.ts +10 -1
  481. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  482. package/dist/modes/rpc/rpc-types.js.map +1 -1
  483. package/dist/package-manager-cli.d.ts.map +1 -1
  484. package/dist/package-manager-cli.js +6 -2
  485. package/dist/package-manager-cli.js.map +1 -1
  486. package/dist/utils/clipboard-image.d.ts.map +1 -1
  487. package/dist/utils/clipboard-image.js +14 -17
  488. package/dist/utils/clipboard-image.js.map +1 -1
  489. package/dist/utils/clipboard.d.ts +2 -0
  490. package/dist/utils/clipboard.d.ts.map +1 -1
  491. package/dist/utils/clipboard.js +5 -0
  492. package/dist/utils/clipboard.js.map +1 -1
  493. package/dist/utils/paths.d.ts +3 -3
  494. package/dist/utils/paths.d.ts.map +1 -1
  495. package/dist/utils/paths.js +5 -4
  496. package/dist/utils/paths.js.map +1 -1
  497. package/dist/utils/shell.d.ts +1 -3
  498. package/dist/utils/shell.d.ts.map +1 -1
  499. package/dist/utils/shell.js +3 -30
  500. package/dist/utils/shell.js.map +1 -1
  501. package/docs/bundled/README.md +22 -8
  502. package/docs/bundled/extensions/statusline.md +2 -2
  503. package/docs/bundled/tasks.md +141 -0
  504. package/docs/bundled/tool-presentation.md +1 -1
  505. package/docs/custom-provider.md +44 -0
  506. package/docs/docs.json +10 -6
  507. package/docs/extensions.md +89 -86
  508. package/docs/index.md +2 -1
  509. package/docs/keybindings.md +8 -7
  510. package/docs/llama-cpp.md +12 -1
  511. package/docs/mcp.md +188 -0
  512. package/docs/models.md +35 -0
  513. package/docs/packages.md +4 -0
  514. package/docs/providers.md +6 -0
  515. package/docs/rpc.md +5 -3
  516. package/docs/sdk.md +26 -16
  517. package/docs/security.md +4 -0
  518. package/docs/session-format.md +18 -11
  519. package/docs/settings.md +26 -2
  520. package/docs/themes.md +27 -5
  521. package/docs/tui.md +20 -0
  522. package/docs/usage.md +61 -3
  523. package/docs/virtual-models.md +114 -0
  524. package/docs/windows.md +2 -0
  525. package/examples/README.md +1 -1
  526. package/examples/extensions/README.md +2 -0
  527. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  528. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  529. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  530. package/examples/extensions/custom-provider-gitlab-duo/test.ts +4 -4
  531. package/examples/extensions/debug-provider.ts +90 -0
  532. package/examples/extensions/gondolin/package-lock.json +2 -2
  533. package/examples/extensions/gondolin/package.json +1 -1
  534. package/examples/extensions/jev-router.ts +113 -0
  535. package/examples/extensions/sandbox/package-lock.json +2 -2
  536. package/examples/extensions/sandbox/package.json +1 -1
  537. package/examples/extensions/with-deps/package-lock.json +2 -2
  538. package/examples/extensions/with-deps/package.json +1 -1
  539. package/examples/rpc-client.ts +1 -1
  540. package/examples/rpc-extension-ui.ts +1 -1
  541. package/examples/sdk/14-codemode-mcp.ts +61 -0
  542. package/examples/sdk/README.md +1 -0
  543. package/npm-shrinkwrap.json +409 -423
  544. package/package.json +13 -10
  545. package/dist/bundle/chunks/anthropic-messages-XWFTZP2N.js +0 -6
  546. package/dist/bundle/chunks/azure-openai-responses-HS35BQV6.js +0 -2
  547. package/dist/bundle/chunks/chunk-2IO5GDBS.js +0 -11
  548. package/dist/bundle/chunks/chunk-EDBLK2JQ.js +0 -2
  549. package/dist/bundle/chunks/chunk-IORR2FW4.js +0 -2
  550. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
  551. package/dist/bundle/chunks/google-generative-ai-NOVAJBFC.js +0 -2
  552. package/dist/bundle/chunks/google-vertex-4VHCZJV5.js +0 -2
  553. package/dist/bundle/chunks/mistral-conversations-WC6A2WCJ.js +0 -5
  554. package/dist/bundle/chunks/openai-codex-responses-XCDG75W2.js +0 -10
  555. package/dist/bundle/chunks/openai-completions-SHS3CAEL.js +0 -7
  556. package/dist/bundle/chunks/openai-responses-UT6XFKC7.js +0 -2
  557. package/dist/bundle/chunks/virtual-modules-KUEIEAZN.js +0 -2
  558. package/dist/core/background/history.d.ts +0 -4
  559. package/dist/core/background/history.d.ts.map +0 -1
  560. package/dist/core/background/history.js.map +0 -1
  561. package/dist/core/background/output.d.ts.map +0 -1
  562. package/dist/core/background/output.js.map +0 -1
  563. package/dist/core/background/presentation.d.ts +0 -9
  564. package/dist/core/background/presentation.d.ts.map +0 -1
  565. package/dist/core/background/presentation.js.map +0 -1
  566. package/dist/core/background/service.d.ts.map +0 -1
  567. package/dist/core/background/service.js.map +0 -1
  568. package/dist/core/background/session.d.ts +0 -67
  569. package/dist/core/background/session.d.ts.map +0 -1
  570. package/dist/core/background/session.js +0 -248
  571. package/dist/core/background/session.js.map +0 -1
  572. package/dist/core/background/types.d.ts.map +0 -1
  573. package/dist/core/background/types.js.map +0 -1
  574. package/dist/extensions/background/actions.d.ts +0 -11
  575. package/dist/extensions/background/actions.d.ts.map +0 -1
  576. package/dist/extensions/background/actions.js.map +0 -1
  577. package/dist/extensions/background/completion-render.d.ts +0 -8
  578. package/dist/extensions/background/completion-render.d.ts.map +0 -1
  579. package/dist/extensions/background/completion-render.js.map +0 -1
  580. package/dist/extensions/background/constants.d.ts.map +0 -1
  581. package/dist/extensions/background/constants.js.map +0 -1
  582. package/dist/extensions/background/index.d.ts +0 -7
  583. package/dist/extensions/background/index.d.ts.map +0 -1
  584. package/dist/extensions/background/index.js +0 -135
  585. package/dist/extensions/background/index.js.map +0 -1
  586. package/dist/extensions/background/keybindings.d.ts +0 -10
  587. package/dist/extensions/background/keybindings.d.ts.map +0 -1
  588. package/dist/extensions/background/keybindings.js +0 -14
  589. package/dist/extensions/background/keybindings.js.map +0 -1
  590. package/dist/extensions/background/manager.d.ts +0 -80
  591. package/dist/extensions/background/manager.d.ts.map +0 -1
  592. package/dist/extensions/background/manager.js +0 -673
  593. package/dist/extensions/background/manager.js.map +0 -1
  594. package/dist/extensions/background/render.d.ts.map +0 -1
  595. package/dist/extensions/background/render.js.map +0 -1
  596. package/dist/extensions/background/schema.d.ts.map +0 -1
  597. package/dist/extensions/background/schema.js.map +0 -1
  598. package/dist/extensions/background/task-view.d.ts.map +0 -1
  599. package/dist/extensions/background/task-view.js.map +0 -1
  600. package/dist/extensions/background/text.d.ts.map +0 -1
  601. package/dist/extensions/background/text.js.map +0 -1
  602. package/dist/extensions/background/types.d.ts.map +0 -1
  603. package/dist/extensions/background/types.js.map +0 -1
  604. package/dist/extensions/subagent/activity.d.ts +0 -34
  605. package/dist/extensions/subagent/activity.d.ts.map +0 -1
  606. package/dist/extensions/subagent/activity.js +0 -192
  607. package/dist/extensions/subagent/activity.js.map +0 -1
  608. package/dist/extensions/subagent/agents-command.d.ts +0 -4
  609. package/dist/extensions/subagent/agents-command.d.ts.map +0 -1
  610. package/dist/extensions/subagent/agents-command.js +0 -230
  611. package/dist/extensions/subagent/agents-command.js.map +0 -1
  612. package/dist/extensions/subagent/agents.d.ts +0 -6
  613. package/dist/extensions/subagent/agents.d.ts.map +0 -1
  614. package/dist/extensions/subagent/agents.js +0 -53
  615. package/dist/extensions/subagent/agents.js.map +0 -1
  616. package/dist/extensions/subagent/budget.d.ts +0 -15
  617. package/dist/extensions/subagent/budget.d.ts.map +0 -1
  618. package/dist/extensions/subagent/budget.js +0 -123
  619. package/dist/extensions/subagent/budget.js.map +0 -1
  620. package/dist/extensions/subagent/cancellation.d.ts +0 -29
  621. package/dist/extensions/subagent/cancellation.d.ts.map +0 -1
  622. package/dist/extensions/subagent/cancellation.js +0 -91
  623. package/dist/extensions/subagent/cancellation.js.map +0 -1
  624. package/dist/extensions/subagent/constants.d.ts +0 -25
  625. package/dist/extensions/subagent/constants.d.ts.map +0 -1
  626. package/dist/extensions/subagent/constants.js +0 -50
  627. package/dist/extensions/subagent/constants.js.map +0 -1
  628. package/dist/extensions/subagent/index.d.ts +0 -3
  629. package/dist/extensions/subagent/index.d.ts.map +0 -1
  630. package/dist/extensions/subagent/index.js +0 -151
  631. package/dist/extensions/subagent/index.js.map +0 -1
  632. package/dist/extensions/subagent/model-selection.d.ts +0 -16
  633. package/dist/extensions/subagent/model-selection.d.ts.map +0 -1
  634. package/dist/extensions/subagent/model-selection.js +0 -51
  635. package/dist/extensions/subagent/model-selection.js.map +0 -1
  636. package/dist/extensions/subagent/render.d.ts +0 -24
  637. package/dist/extensions/subagent/render.d.ts.map +0 -1
  638. package/dist/extensions/subagent/render.js +0 -336
  639. package/dist/extensions/subagent/render.js.map +0 -1
  640. package/dist/extensions/subagent/resolve.d.ts +0 -31
  641. package/dist/extensions/subagent/resolve.d.ts.map +0 -1
  642. package/dist/extensions/subagent/resolve.js +0 -111
  643. package/dist/extensions/subagent/resolve.js.map +0 -1
  644. package/dist/extensions/subagent/runner.d.ts +0 -35
  645. package/dist/extensions/subagent/runner.d.ts.map +0 -1
  646. package/dist/extensions/subagent/runner.js +0 -255
  647. package/dist/extensions/subagent/runner.js.map +0 -1
  648. package/dist/extensions/subagent/schema.d.ts +0 -28
  649. package/dist/extensions/subagent/schema.d.ts.map +0 -1
  650. package/dist/extensions/subagent/schema.js +0 -58
  651. package/dist/extensions/subagent/schema.js.map +0 -1
  652. package/dist/extensions/subagent/sdk-runner.d.ts +0 -33
  653. package/dist/extensions/subagent/sdk-runner.d.ts.map +0 -1
  654. package/dist/extensions/subagent/sdk-runner.js +0 -331
  655. package/dist/extensions/subagent/sdk-runner.js.map +0 -1
  656. package/dist/extensions/subagent/settings.d.ts +0 -8
  657. package/dist/extensions/subagent/settings.d.ts.map +0 -1
  658. package/dist/extensions/subagent/settings.js +0 -206
  659. package/dist/extensions/subagent/settings.js.map +0 -1
  660. package/dist/extensions/subagent/state.d.ts +0 -102
  661. package/dist/extensions/subagent/state.d.ts.map +0 -1
  662. package/dist/extensions/subagent/state.js +0 -383
  663. package/dist/extensions/subagent/state.js.map +0 -1
  664. package/dist/extensions/subagent/text.d.ts +0 -6
  665. package/dist/extensions/subagent/text.d.ts.map +0 -1
  666. package/dist/extensions/subagent/text.js +0 -66
  667. package/dist/extensions/subagent/text.js.map +0 -1
  668. package/dist/extensions/subagent/types.d.ts +0 -91
  669. package/dist/extensions/subagent/types.d.ts.map +0 -1
  670. package/dist/extensions/subagent/types.js +0 -2
  671. package/dist/extensions/subagent/types.js.map +0 -1
  672. package/dist/extensions/subagent/ui/agents-dialog.d.ts +0 -4
  673. package/dist/extensions/subagent/ui/agents-dialog.d.ts.map +0 -1
  674. package/dist/extensions/subagent/ui/agents-dialog.js +0 -84
  675. package/dist/extensions/subagent/ui/agents-dialog.js.map +0 -1
  676. package/dist/extensions/subagent/ui/choice-menu.d.ts +0 -39
  677. package/dist/extensions/subagent/ui/choice-menu.d.ts.map +0 -1
  678. package/dist/extensions/subagent/ui/choice-menu.js +0 -93
  679. package/dist/extensions/subagent/ui/choice-menu.js.map +0 -1
  680. package/dist/extensions/subagent/ui/choices.d.ts +0 -36
  681. package/dist/extensions/subagent/ui/choices.d.ts.map +0 -1
  682. package/dist/extensions/subagent/ui/choices.js +0 -54
  683. package/dist/extensions/subagent/ui/choices.js.map +0 -1
  684. package/dist/extensions/subagent/ui/model-list.d.ts +0 -66
  685. package/dist/extensions/subagent/ui/model-list.d.ts.map +0 -1
  686. package/dist/extensions/subagent/ui/model-list.js +0 -235
  687. package/dist/extensions/subagent/ui/model-list.js.map +0 -1
  688. package/dist/extensions/subagent/ui/model-picker.d.ts +0 -47
  689. package/dist/extensions/subagent/ui/model-picker.d.ts.map +0 -1
  690. package/dist/extensions/subagent/ui/model-picker.js +0 -143
  691. package/dist/extensions/subagent/ui/model-picker.js.map +0 -1
  692. package/dist/extensions/subagent/ui/profile-settings-menu.d.ts +0 -41
  693. package/dist/extensions/subagent/ui/profile-settings-menu.d.ts.map +0 -1
  694. package/dist/extensions/subagent/ui/profile-settings-menu.js +0 -98
  695. package/dist/extensions/subagent/ui/profile-settings-menu.js.map +0 -1
  696. package/docs/bundled/extensions/background.md +0 -132
  697. package/docs/bundled/extensions/subagent.md +0 -148
  698. /package/dist/{extensions/background → core/tools/tasks}/types.js +0 -0
@@ -1,3 +1,4 @@
1
+ import { createTasksToolDefinition } from "./tools/tasks.js";
1
2
  /**
2
3
  * AgentSession - Core abstraction for agent lifecycle and session management.
3
4
  *
@@ -14,6 +15,7 @@
14
15
  */
15
16
  import { readFileSync } from "node:fs";
16
17
  import { basename, dirname } from "node:path";
18
+ import { runToolCall, } from "@earendil-works/pi-agent-core";
17
19
  import { contentText, getCurrentSystemMessage, getSystemMessageText, retryDelayMs } from "@earendil-works/pi-ai";
18
20
  import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, isRecoverableLength, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai/compat";
19
21
  import { getThemeByName, theme } from "../modes/interactive/theme/theme.js";
@@ -22,7 +24,6 @@ import { processImage } from "../utils/image-process.js";
22
24
  import { sleep } from "../utils/sleep.js";
23
25
  import { normalizeToolResultImages } from "../utils/tool-result-images.js";
24
26
  import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
25
- import { BackgroundSession } from "./background/session.js";
26
27
  import { executeBashWithOperations } from "./bash-executor.js";
27
28
  import { generateBugReportSummary } from "./bug-report.js";
28
29
  import { calculateContextTokens, collectEntriesForBranchSummary, compact, estimateContextTokens, estimateProjectedContextTokens, estimateTokens, generateBranchSummary, prepareCompaction, shouldCompact, } from "./compaction/index.js";
@@ -33,15 +34,18 @@ import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
33
34
  import { emitSessionShutdownEvent } from "./extensions/runner.js";
34
35
  import { convertToLlm } from "./messages.js";
35
36
  import { ModelRegistry } from "./model-registry.js";
37
+ import { NestedToolCallRunner } from "./nested-tool-calls.js";
36
38
  import { expandPromptTemplate } from "./prompt-templates.js";
37
39
  import { exportSessionToJsonl } from "./session-export.js";
38
40
  import { getLatestCompactionEntry, SessionManager, } from "./session-manager.js";
39
- import { createSyntheticSourceInfo } from "./source-info.js";
41
+ import { BUILTIN_PATH_PREFIX, createSyntheticSourceInfo, isSyntheticPath } from "./source-info.js";
40
42
  import { buildSystemPrompt, buildSystemPromptSections, diffSystemPromptSections, normalizeBuildSystemPromptOptions, } from "./system-prompt.js";
43
+ import { TaskSession } from "./tasks/session.js";
41
44
  import { createLocalBashOperations } from "./tools/bash.js";
42
45
  import { createAllToolDefinitions } from "./tools/index.js";
43
46
  import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
44
- import { addUsageToTotals, createUsageTotals, getAccountedUsages } from "./usage-totals.js";
47
+ import { addUsageToTotals, combineUsage, createUsageTotals, getAccountedUsages } from "./usage-totals.js";
48
+ import { findLatestResponse, getBranchSelection, getVirtualModelState, isVirtualModel, VIRTUAL_MODEL_STATE_ENTRY, } from "./virtual-models.js";
45
49
  /**
46
50
  * Parse a skill block from message text.
47
51
  * Returns null if the text doesn't contain a skill block.
@@ -113,13 +117,30 @@ export class AgentSession {
113
117
  this._extensionMode = "print";
114
118
  // Tool registry for extension getTools/setTools
115
119
  this._toolRegistry = new Map();
120
+ /** Declared tools whose declarations requests leave out, from `prepareLoadout` hooks. */
121
+ this._hiddenDeclarations = new Set();
116
122
  this._toolDefinitions = new Map();
117
123
  this._toolPromptSnippets = new Map();
118
124
  this._toolPromptGuidelines = new Map();
119
125
  /** Internal handler for agent events - shared by subscribe and reconnect */
120
126
  this._handleAgentEvent = async (event) => {
121
127
  if (event.type === "message_start")
122
- this._backgroundHost.messageStarted(event.message);
128
+ this._tasksHost.delivery.messageStarted(event.message);
129
+ // Record the calls a tool made through ctx.executeTool() and their usage on its result message.
130
+ if (this._nestedToolCalls) {
131
+ if (event.type === "message_start" && event.message.role === "toolResult") {
132
+ const message = event.message;
133
+ const summary = this._nestedToolCalls.takeRecord(message.toolCallId);
134
+ if (summary?.calls)
135
+ message.nestedCalls = summary.calls;
136
+ if (summary?.usage) {
137
+ message.usage = message.usage ? combineUsage(message.usage, summary.usage) : summary.usage;
138
+ }
139
+ }
140
+ else if (event.type === "agent_end") {
141
+ this._nestedToolCalls.clear();
142
+ }
143
+ }
123
144
  // When a user message starts, check if it's from either queue and remove it BEFORE emitting
124
145
  // This ensures the UI sees the updated queue state
125
146
  if (event.type === "message_start" && event.message.role === "user") {
@@ -193,14 +214,14 @@ export class AgentSession {
193
214
  this._flushPendingCustomMessages();
194
215
  }
195
216
  if (event.type === "agent_end")
196
- this._backgroundHost.agentEnded();
217
+ this._tasksHost.delivery.agentEnded();
197
218
  };
198
219
  this.agent = config.agent;
199
220
  this.sessionManager = config.sessionManager;
200
221
  this.settingsManager = config.settingsManager;
201
- this._backgroundHost = new BackgroundSession({
222
+ this._tasksHost = new TaskSession({
202
223
  manager: this.sessionManager,
203
- role: config.executionRole ?? "main",
224
+ backgroundAllowed: config.backgroundAllowed,
204
225
  canDeliver: () => {
205
226
  if (this.model === undefined || this.isCompacting)
206
227
  return false;
@@ -243,6 +264,7 @@ export class AgentSession {
243
264
  this._installAgentNextTurnRefresh();
244
265
  this._installAgentRequestProjection();
245
266
  this._installAgentBoundaryHooks();
267
+ this._installHiddenDeclarationsProjection();
246
268
  this._installAgentForcedPromptProjection();
247
269
  this._buildRuntime({
248
270
  activeToolNames: this._initialActiveToolNames,
@@ -251,26 +273,26 @@ export class AgentSession {
251
273
  if (this._initialActiveToolNames === undefined)
252
274
  this._restoreToolsFromTranscript();
253
275
  }
254
- get background() {
255
- return this._backgroundHost.service;
276
+ get tasks() {
277
+ return this._tasksHost.service;
256
278
  }
257
- get quarantinedBackgroundSettlements() {
258
- return this._backgroundHost.quarantinedSettlements;
279
+ get quarantinedTaskSettlements() {
280
+ return this._tasksHost.quarantinedSettlements;
259
281
  }
260
282
  /** Pause delivery across asynchronous lifecycle/preflight gaps. Nestable. */
261
- pauseBackgroundNotifications() {
262
- return this._backgroundHost.pause();
283
+ pauseTaskNotifications() {
284
+ return this._tasksHost.delivery.pause();
263
285
  }
264
286
  /** Explicit retry after a host delivery failure; never spins on a timer by itself. */
265
- retryBackgroundNotifications() {
266
- this._backgroundHost.retry();
287
+ retryTaskNotifications() {
288
+ this._tasksHost.delivery.retry();
267
289
  }
268
290
  /**
269
291
  * Run a lifecycle operation with delivery paused across its asynchronous gaps.
270
292
  * Lifecycle methods are thin shells over upstream bodies so those keep upstream's shape.
271
293
  */
272
- async _withBackgroundPaused(operation) {
273
- const resumeBackground = this.pauseBackgroundNotifications();
294
+ async _withTasksPaused(operation) {
295
+ const resumeBackground = this.pauseTaskNotifications();
274
296
  try {
275
297
  return await operation();
276
298
  }
@@ -354,28 +376,71 @@ export class AgentSession {
354
376
  }
355
377
  throw new Error(formatNoApiKeyFoundMessage(model.provider));
356
378
  }
357
- async _getSummarizationRequestAuth(model, signal) {
379
+ async _getSummarizationRequestAuth(selectedModel, signal) {
380
+ // Route a virtual model first: summaries size their input and output from the model they get.
381
+ const { model, thinkingLevel } = isVirtualModel(selectedModel)
382
+ ? await this._modelRuntime.resolveModel(selectedModel, convertToLlm(this.messages), {
383
+ reason: "direct",
384
+ thinkingLevel: this.thinkingLevel,
385
+ signal,
386
+ })
387
+ : { model: selectedModel, thinkingLevel: this.thinkingLevel };
358
388
  if (this.agent.streamFunction === streamSimple) {
359
- return this._getRequiredRequestAuth(model, signal);
389
+ return { ...(await this._getRequiredRequestAuth(model, signal)), thinkingLevel };
360
390
  }
361
391
  try {
362
392
  const result = await this._modelRuntime.getAuth(model, { signal });
363
393
  if (!result)
364
- return { model };
394
+ return { model, thinkingLevel };
365
395
  const requestModel = result.auth.baseUrl ? { ...model, baseUrl: result.auth.baseUrl } : model;
366
396
  return {
367
397
  model: requestModel,
368
398
  apiKey: result.auth.apiKey,
369
399
  headers: withoutDeletedHeaders(result.auth.headers),
370
400
  env: result.env,
401
+ thinkingLevel,
371
402
  };
372
403
  }
373
404
  catch (error) {
374
405
  if (signal?.aborted)
375
406
  throw error;
376
- return { model };
407
+ return { model, thinkingLevel };
377
408
  }
378
409
  }
410
+ /**
411
+ * The model whose limits apply to `message`, or undefined when the message came from another
412
+ * model. Under a virtual selection, that is the physical model that produced it.
413
+ */
414
+ _modelForMessage(message) {
415
+ const model = this.model;
416
+ if (model && isVirtualModel(model))
417
+ return this._modelRuntime.getPhysicalModel(message.provider, message.model);
418
+ return model?.provider === message.provider && model.id === message.model ? model : undefined;
419
+ }
420
+ /**
421
+ * Record the selection on the current branch when the branch implies another one, so a resume
422
+ * restores it. Tree navigation can leave the latest `model_change` on another branch; responses
423
+ * cannot record a virtual selection because they name physical models. Responses do record a
424
+ * physical selection unless the branch holds a virtual one; checking a physical selection against
425
+ * responses would record it on every prompt while `prepareRequest` redirects to another model.
426
+ */
427
+ _recordSelection() {
428
+ const model = this.model;
429
+ if (!model)
430
+ return;
431
+ const getModel = (provider, modelId) => this._modelRuntime.getModel(provider, modelId);
432
+ const recorded = getBranchSelection(this.sessionManager.getBranch(), getModel);
433
+ if (!recorded || (recorded.provider === model.provider && recorded.modelId === model.id))
434
+ return;
435
+ const recordedModel = getModel(recorded.provider, recorded.modelId);
436
+ if (!isVirtualModel(model) && !(recordedModel && isVirtualModel(recordedModel)))
437
+ return;
438
+ this.sessionManager.appendModelChange(model.provider, model.id);
439
+ }
440
+ /** The model whose limits apply to the conversation. */
441
+ _limitsModel() {
442
+ return this.routedModel?.model ?? this.model;
443
+ }
379
444
  /**
380
445
  * Install tool hooks once on the Agent instance.
381
446
  *
@@ -385,65 +450,112 @@ export class AgentSession {
385
450
  * happens here instead of in wrappers.
386
451
  */
387
452
  _installAgentToolHooks() {
388
- this.agent.beforeToolCall = async ({ toolCall, args }) => {
389
- const runner = this._extensionRunner;
390
- if (!runner.hasHandlers("tool_call")) {
391
- return undefined;
392
- }
393
- try {
394
- return await runner.emitToolCall({
395
- type: "tool_call",
396
- toolName: toolCall.name,
397
- toolCallId: toolCall.id,
398
- input: args,
399
- });
400
- }
401
- catch (err) {
402
- if (err instanceof Error) {
403
- throw err;
404
- }
405
- throw new Error(`Extension failed, blocking execution: ${String(err)}`);
406
- }
407
- };
408
- this.agent.afterToolCall = async ({ toolCall, args, result, isError }) => {
409
- const runner = this._extensionRunner;
410
- const hookResult = runner.hasHandlers("tool_result")
411
- ? await runner.emitToolResult({
412
- type: "tool_result",
413
- toolName: toolCall.name,
414
- toolCallId: toolCall.id,
415
- input: args,
416
- content: result.content,
417
- details: result.details,
418
- isError,
419
- usage: result.usage,
420
- })
421
- : undefined;
422
- const content = hookResult?.content ?? result.content ?? [];
423
- // Runs after the extension hook so images injected or replaced by extensions are normalized too.
424
- const resizeOptions = this.model?.inputLimits?.images?.resize;
425
- const normalizedContent = await normalizeToolResultImages(content, {
426
- autoResizeImages: this.settingsManager.getImageAutoResize(),
427
- ...(resizeOptions ? { resizeOptions } : {}),
453
+ this.agent.beforeToolCall = (context) => this._beforeToolCall(context);
454
+ this.agent.afterToolCall = (context) => this._afterToolCall(context);
455
+ }
456
+ /** `tool_call` handlers. `parentToolCallId` is set for calls another tool made. */
457
+ async _beforeToolCall({ toolCall, args }, parentToolCallId) {
458
+ const runner = this._extensionRunner;
459
+ if (!runner.hasHandlers("tool_call")) {
460
+ return undefined;
461
+ }
462
+ try {
463
+ return await runner.emitToolCall({
464
+ type: "tool_call",
465
+ toolName: toolCall.name,
466
+ toolCallId: toolCall.id,
467
+ ...(parentToolCallId ? { parentToolCallId } : {}),
468
+ input: args,
428
469
  });
429
- if (!hookResult && normalizedContent === content) {
430
- return undefined;
470
+ }
471
+ catch (err) {
472
+ if (err instanceof Error) {
473
+ throw err;
431
474
  }
432
- return {
433
- content: normalizedContent,
434
- details: hookResult?.details,
435
- isError: hookResult?.isError ?? isError,
436
- usage: hookResult?.usage,
437
- };
475
+ throw new Error(`Extension failed, blocking execution: ${String(err)}`);
476
+ }
477
+ }
478
+ /** `tool_result` handlers and image normalization. `parentToolCallId` is set for calls another tool made. */
479
+ async _afterToolCall({ toolCall, args, result, isError }, parentToolCallId) {
480
+ const runner = this._extensionRunner;
481
+ const hookResult = runner.hasHandlers("tool_result")
482
+ ? await runner.emitToolResult({
483
+ type: "tool_result",
484
+ toolName: toolCall.name,
485
+ toolCallId: toolCall.id,
486
+ ...(parentToolCallId ? { parentToolCallId } : {}),
487
+ input: args,
488
+ content: result.content,
489
+ details: result.details,
490
+ ...(result.structuredContent === undefined ? {} : { structuredContent: result.structuredContent }),
491
+ isError,
492
+ usage: result.usage,
493
+ })
494
+ : undefined;
495
+ const content = hookResult?.content ?? result.content ?? [];
496
+ // Runs after the extension hook so images injected or replaced by extensions are normalized too.
497
+ const resizeOptions = this._limitsModel()?.inputLimits?.images?.resize;
498
+ const normalizedContent = await normalizeToolResultImages(content, {
499
+ autoResizeImages: this.settingsManager.getImageAutoResize(),
500
+ ...(resizeOptions ? { resizeOptions } : {}),
501
+ });
502
+ if (!hookResult && normalizedContent === content) {
503
+ return undefined;
504
+ }
505
+ // The hook result already dropped structured content that replaced content no longer matches.
506
+ return {
507
+ content: normalizedContent,
508
+ details: hookResult?.details,
509
+ structuredContent: hookResult ? hookResult.structuredContent : result.structuredContent,
510
+ isError: hookResult?.isError ?? isError,
511
+ usage: hookResult?.usage,
438
512
  };
439
513
  }
514
+ /**
515
+ * Run a call that the tool call `parentToolCallId` made through `ctx.executeTool()`. It goes
516
+ * through the agent's tool pipeline with the session's hooks, against the callable tools.
517
+ */
518
+ async _executeNestedToolCall(parentToolCallId, name, args, options) {
519
+ this._nestedToolCalls ??= new NestedToolCallRunner({
520
+ getTools: () => this._getCallableTools(),
521
+ isSequential: () => this.agent.toolExecution === "sequential",
522
+ runToolCall: (toolCall, parentId, signal, onUpdate) => {
523
+ const assistantMessage = this._findLastAssistantMessage();
524
+ if (!assistantMessage) {
525
+ return Promise.resolve({
526
+ toolCall,
527
+ result: { content: [{ type: "text", text: "No assistant message issued this call" }], details: {} },
528
+ isError: true,
529
+ });
530
+ }
531
+ return runToolCall(toolCall, {
532
+ tools: this._getCallableTools(),
533
+ assistantMessage,
534
+ context: { messages: this.agent.state.messages, tools: this.agent.state.tools },
535
+ beforeToolCall: (context) => this._beforeToolCall(context, parentId),
536
+ afterToolCall: (context) => this._afterToolCall(context, parentId),
537
+ signal,
538
+ onUpdate,
539
+ });
540
+ },
541
+ emit: async (event) => {
542
+ await this._extensionRunner.emit(event);
543
+ this._emit(event);
544
+ },
545
+ });
546
+ return this._nestedToolCalls.execute(parentToolCallId, name, args, options);
547
+ }
548
+ /** Whether `projection`, the current session projection, exceeds the compaction threshold of `model`. */
549
+ _exceedsCompactionThreshold(model, projection) {
550
+ if (model.contextWindow <= 0)
551
+ return false;
552
+ return shouldCompact(estimateProjectedContextTokens(projection, this.sessionManager.getBranch()).tokens, model.contextWindow, this.settingsManager.getCompactionSettings(model));
553
+ }
440
554
  async _compactBeforeNextAssistantResponse(context) {
441
- const model = this.model;
442
- const settings = this.settingsManager.getCompactionSettings(model);
443
555
  const projection = this.sessionManager.buildSessionProjection();
444
- if (!model ||
445
- model.contextWindow <= 0 ||
446
- !shouldCompact(estimateProjectedContextTokens(projection, this.sessionManager.getBranch()).tokens, model.contextWindow, settings)) {
556
+ // A virtual selection is checked in prepareRequest, against the model the request is routed to.
557
+ const model = this.model;
558
+ if (!model || isVirtualModel(model) || !this._exceedsCompactionThreshold(model, projection)) {
447
559
  return { ...context, messages: projection.messages };
448
560
  }
449
561
  await this._runAutoCompaction("threshold", false);
@@ -452,24 +564,55 @@ export class AgentSession {
452
564
  _installAgentRequestProjection() {
453
565
  const previousPrepareRequest = this.agent.prepareRequest;
454
566
  this.agent.prepareRequest = async (request, signal) => {
455
- const canonicalContext = {
456
- ...request.context,
457
- messages: this.sessionManager.buildSessionProjection().messages,
458
- // Messages declare the provider-visible loadout; context.tools keeps executable implementations.
459
- tools: this.agent.state.tools.slice(),
460
- };
461
- const previous = await previousPrepareRequest?.({
462
- ...request,
463
- context: canonicalContext,
464
- model: this.agent.state.model,
465
- thinkingLevel: this.agent.state.thinkingLevel,
466
- }, signal);
467
- return {
468
- ...previous,
469
- context: previous?.context ?? canonicalContext,
470
- model: previous?.model ?? this.agent.state.model,
471
- thinkingLevel: previous?.thinkingLevel ?? this.agent.state.thinkingLevel,
567
+ const failed = this._failedResponse;
568
+ this._failedResponse = undefined;
569
+ const prepare = async () => {
570
+ const projection = this.sessionManager.buildSessionProjection();
571
+ const canonicalContext = {
572
+ ...request.context,
573
+ messages: projection.messages,
574
+ // Messages declare the provider-visible loadout; context.tools keeps executable implementations.
575
+ tools: this.agent.state.tools.slice(),
576
+ };
577
+ const previous = await previousPrepareRequest?.({
578
+ ...request,
579
+ context: canonicalContext,
580
+ model: this.agent.state.model,
581
+ thinkingLevel: this.agent.state.thinkingLevel,
582
+ }, signal);
583
+ return { previous, context: previous?.context ?? canonicalContext, projection };
472
584
  };
585
+ let { previous, context, projection } = await prepare();
586
+ const model = previous?.model ?? this.agent.state.model;
587
+ const thinkingLevel = previous?.thinkingLevel ?? this.agent.state.thinkingLevel;
588
+ if (!isVirtualModel(model))
589
+ return { ...previous, context, model, thinkingLevel };
590
+ // The selection stays in agent state; only this request uses the routed model. A routing
591
+ // failure rejects, which ends the run with an error response. Only messages the user wrote
592
+ // start a turn; extension messages can follow them, e.g. from before_agent_start.
593
+ const lastResponse = context.messages.findLastIndex((message) => message.role === "assistant");
594
+ const userTurn = context.messages.slice(lastResponse + 1).some((message) => message.role === "user");
595
+ const state = getVirtualModelState(this.sessionManager.getBranch(), model.provider, model.id);
596
+ const route = await this._modelRuntime.resolveModel(model, convertToLlm(context.messages), {
597
+ reason: failed ? "retry" : userTurn ? "user" : "continuation",
598
+ thinkingLevel,
599
+ signal,
600
+ failed,
601
+ state,
602
+ });
603
+ if (route.state !== undefined && route.state !== state) {
604
+ const data = { provider: model.provider, modelId: model.id, state: route.state };
605
+ const entry = this.sessionManager.getEntry(this.sessionManager.appendCustomEntry(VIRTUAL_MODEL_STATE_ENTRY, data));
606
+ if (entry)
607
+ this._emit({ type: "entry_appended", entry });
608
+ }
609
+ // The route stands: the router already decided this request. The state entry does not change
610
+ // the projection.
611
+ if (this._exceedsCompactionThreshold(route.model, projection)) {
612
+ await this._runAutoCompaction("threshold", false);
613
+ ({ previous, context } = await prepare());
614
+ }
615
+ return { ...previous, context, model: route.model, thinkingLevel: route.thinkingLevel };
473
616
  };
474
617
  }
475
618
  async _dispatchTurnEndBoundary(message, toolResults) {
@@ -525,10 +668,7 @@ export class AgentSession {
525
668
  ? async (_turn, signal) => await this.agent.prepareNextTurn?.(signal)
526
669
  : undefined);
527
670
  this.agent.prepareNextTurnWithContext = async (turn, signal) => {
528
- const context = await this._compactBeforeNextAssistantResponse({
529
- ...turn.context,
530
- messages: this.sessionManager.buildSessionProjection().messages,
531
- });
671
+ const context = await this._compactBeforeNextAssistantResponse(turn.context);
532
672
  const previousSnapshot = await previousPrepareNextTurnWithContext?.({ ...turn, context }, signal);
533
673
  const nextContext = previousSnapshot?.context ?? context;
534
674
  const runOptions = this._runSystemPromptOptions ?? this._baseSystemPromptOptions;
@@ -676,7 +816,7 @@ export class AgentSession {
676
816
  * so a deferred prompt never races a delivery for the same idle gap.
677
817
  */
678
818
  async _emitAgentSettled() {
679
- return this._withBackgroundPaused(() => this._emitAgentSettledBody());
819
+ return this._withTasksPaused(() => this._emitAgentSettledBody());
680
820
  }
681
821
  async _emitAgentSettledBody() {
682
822
  this._cacheWarmer?.onAgentSettled();
@@ -712,7 +852,7 @@ export class AgentSession {
712
852
  if (pendingIndex !== -1)
713
853
  this._pendingNextTurnMessages.splice(pendingIndex, 1);
714
854
  }
715
- this._backgroundHost.messagePersisted(message);
855
+ this._tasksHost.delivery.messagePersisted(message);
716
856
  }
717
857
  _willRetryAfterAgentEnd(event) {
718
858
  if (this._agentRunAbortRequested)
@@ -909,7 +1049,7 @@ export class AgentSession {
909
1049
  * Call this when completely done with the session.
910
1050
  */
911
1051
  dispose() {
912
- this._backgroundHost.dispose();
1052
+ this._tasksHost.dispose();
913
1053
  try {
914
1054
  this.abortRetry();
915
1055
  this.abortCompaction();
@@ -957,6 +1097,14 @@ export class AgentSession {
957
1097
  get thinkingLevel() {
958
1098
  return this.agent.state.thinkingLevel;
959
1099
  }
1100
+ /** Under a virtual selection, the physical model and thinking level of the latest successful response. */
1101
+ get routedModel() {
1102
+ if (!this.model || !isVirtualModel(this.model))
1103
+ return undefined;
1104
+ const latest = findLatestResponse(this.agent.state.messages);
1105
+ const model = latest && this._modelRuntime.getPhysicalModel(latest.provider, latest.model);
1106
+ return model && { model, thinkingLevel: latest?.thinkingLevel };
1107
+ }
960
1108
  /** Whether the session is currently processing an agent run or post-run continuation. */
961
1109
  get isStreaming() {
962
1110
  return this._isAgentRunActive;
@@ -974,12 +1122,16 @@ export class AgentSession {
974
1122
  return this._retryAttempt;
975
1123
  }
976
1124
  /**
977
- * Get the names of currently active tools.
978
- * Returns the names of tools currently set on the agent.
1125
+ * Get the names of currently active tools, which are the tools declared to the model.
1126
+ * Tools with `codemode` or `deferred` exposure are callable from other tools without being active.
979
1127
  */
980
1128
  getActiveToolNames() {
981
1129
  return this.agent.state.tools.map((t) => t.name);
982
1130
  }
1131
+ /** Get the names of the tools that tools can call through `ctx.executeTool()`. */
1132
+ getCallableToolNames() {
1133
+ return this._getCallableTools().map((t) => t.name);
1134
+ }
983
1135
  /**
984
1136
  * Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
985
1137
  */
@@ -989,6 +1141,9 @@ export class AgentSession {
989
1141
  description: definition.description,
990
1142
  parameters: definition.parameters,
991
1143
  promptGuidelines: definition.promptGuidelines,
1144
+ exposure: this._getToolExposure(definition.name),
1145
+ ...(definition.namespace ? { namespace: definition.namespace } : {}),
1146
+ ...(definition.annotations ? { annotations: { ...definition.annotations } } : {}),
992
1147
  sourceInfo,
993
1148
  }));
994
1149
  }
@@ -997,22 +1152,79 @@ export class AgentSession {
997
1152
  }
998
1153
  /**
999
1154
  * Set active tools by name.
1000
- * Only tools in the registry can be enabled. Unknown tool names are ignored.
1155
+ * Only tools in the registry can be enabled. Unknown and hidden tool names are ignored.
1001
1156
  * Also rebuilds the system prompt to reflect the new tool set.
1002
1157
  * Changes take effect on the next agent turn.
1003
1158
  */
1004
1159
  setActiveToolsByName(toolNames) {
1005
- const tools = [];
1006
- const validToolNames = [];
1007
- for (const name of toolNames) {
1160
+ const tools = this._applyToolLoadout(toolNames);
1161
+ this._rebuildSystemPrompt(tools.map((tool) => tool.name));
1162
+ }
1163
+ _getToolExposure(name) {
1164
+ return this._toolDefinitions.get(name)?.definition.exposure ?? "direct";
1165
+ }
1166
+ /**
1167
+ * Tools callable through `ctx.executeTool()`: the active `direct` tools and every registered
1168
+ * `codemode` or `deferred` tool.
1169
+ */
1170
+ _getCallableTools(active = new Set(this.getActiveToolNames())) {
1171
+ return [...this._toolRegistry.values()].filter((tool) => {
1172
+ const exposure = this._getToolExposure(tool.name);
1173
+ return exposure === "codemode" || exposure === "deferred" || (exposure === "direct" && active.has(tool.name));
1174
+ });
1175
+ }
1176
+ /**
1177
+ * Set the agent's tools for the given active tool names and return them. The active tools are
1178
+ * the registered, non-hidden ones; they are declared to the model. Active tools with a
1179
+ * `prepareLoadout` hook can change the declared descriptions and hide declarations from
1180
+ * requests (see {@link _installHiddenDeclarationsProjection}).
1181
+ */
1182
+ _applyToolLoadout(toolNames) {
1183
+ const tools = [...new Set(toolNames)].flatMap((name) => {
1008
1184
  const tool = this._toolRegistry.get(name);
1009
- if (tool) {
1010
- tools.push(tool);
1011
- validToolNames.push(name);
1185
+ return tool && this._getToolExposure(name) !== "hidden" ? [tool] : [];
1186
+ });
1187
+ const hooks = tools.flatMap((tool) => {
1188
+ const entry = this._toolDefinitions.get(tool.name);
1189
+ return entry?.definition.prepareLoadout ? [entry] : [];
1190
+ });
1191
+ const hidden = new Set();
1192
+ let declared = tools;
1193
+ if (hooks.length > 0) {
1194
+ const loadout = {
1195
+ declared: tools,
1196
+ callable: this._getCallableTools(new Set(tools.map((tool) => tool.name))),
1197
+ registered: [...this._toolRegistry.values()],
1198
+ getExposure: (name) => this._getToolExposure(name),
1199
+ getNamespace: (name) => this._toolDefinitions.get(name)?.definition.namespace,
1200
+ };
1201
+ const descriptions = new Map();
1202
+ for (const { definition, sourceInfo } of hooks) {
1203
+ try {
1204
+ const changes = definition.prepareLoadout?.(loadout);
1205
+ for (const [name, description] of Object.entries(changes?.descriptions ?? {})) {
1206
+ descriptions.set(name, description);
1207
+ }
1208
+ for (const name of changes?.hiddenDeclarations ?? [])
1209
+ hidden.add(name);
1210
+ }
1211
+ catch (error) {
1212
+ this._extensionRunner.emitError({
1213
+ extensionPath: sourceInfo.path,
1214
+ event: "prepare_loadout",
1215
+ error: error instanceof Error ? error.message : String(error),
1216
+ stack: error instanceof Error ? error.stack : undefined,
1217
+ });
1218
+ }
1012
1219
  }
1220
+ declared = tools.map((tool) => {
1221
+ const description = descriptions.get(tool.name);
1222
+ return description === undefined ? tool : { ...tool, description };
1223
+ });
1013
1224
  }
1014
- this.agent.state.tools = tools;
1015
- this._rebuildSystemPrompt(validToolNames);
1225
+ this._hiddenDeclarations = hidden;
1226
+ this.agent.state.tools = declared;
1227
+ return declared;
1016
1228
  }
1017
1229
  /** Whether compaction or branch summarization is currently running */
1018
1230
  get isCompacting() {
@@ -1113,11 +1325,7 @@ export class AgentSession {
1113
1325
  * {@link _installAgentForcedPromptProjection}.
1114
1326
  */
1115
1327
  _preparePromptAndToolLoadout(options, messages = this.agent.state.messages) {
1116
- options.selectedTools = [...new Set(options.selectedTools)].filter((name) => this._toolRegistry.has(name));
1117
- this.agent.state.tools = options.selectedTools.flatMap((name) => {
1118
- const tool = this._toolRegistry.get(name);
1119
- return tool ? [tool] : [];
1120
- });
1328
+ options.selectedTools = this._applyToolLoadout(options.selectedTools).map((tool) => tool.name);
1121
1329
  const sections = diffSystemPromptSections(getCurrentSystemMessage(messages)?.sections ?? {}, buildSystemPromptSections(options));
1122
1330
  return sections ? { role: "system", content: "", sections, timestamp: Date.now() } : undefined;
1123
1331
  }
@@ -1131,6 +1339,32 @@ export class AgentSession {
1131
1339
  * collapse into one head holding the forced text and the current tools. Runs after the
1132
1340
  * `context` extension handlers.
1133
1341
  */
1342
+ /**
1343
+ * Remove the declarations that `prepareLoadout` hooks hide from every request. The whole
1344
+ * transcript is filtered with the current set, so the projected declarations stay consistent
1345
+ * across requests and only change when the loadout does.
1346
+ */
1347
+ _installHiddenDeclarationsProjection() {
1348
+ const previousTransformContext = this.agent.transformContext;
1349
+ this.agent.transformContext = async (messages, signal) => {
1350
+ const transformed = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
1351
+ const hidden = this._hiddenDeclarations;
1352
+ if (hidden.size === 0)
1353
+ return transformed;
1354
+ return transformed.map((message) => {
1355
+ if (message.role !== "system" || (!message.toolsAdded && !message.toolsRemoved))
1356
+ return message;
1357
+ const { toolsAdded, toolsRemoved, ...rest } = message;
1358
+ const added = toolsAdded?.filter((tool) => !hidden.has(tool.name)) ?? [];
1359
+ const removed = toolsRemoved?.filter((tool) => !hidden.has(tool.name)) ?? [];
1360
+ return {
1361
+ ...rest,
1362
+ ...(added.length > 0 ? { toolsAdded: added } : {}),
1363
+ ...(removed.length > 0 ? { toolsRemoved: removed } : {}),
1364
+ };
1365
+ });
1366
+ };
1367
+ }
1134
1368
  _installAgentForcedPromptProjection() {
1135
1369
  const previousTransformContext = this.agent.transformContext;
1136
1370
  this.agent.transformContext = async (messages, signal) => {
@@ -1148,25 +1382,25 @@ export class AgentSession {
1148
1382
  return [head, ...transformed.filter((message) => message.role !== "system")];
1149
1383
  };
1150
1384
  }
1151
- /** Restore the active tool loadout declared by the session transcript, if it declares one. */
1385
+ /**
1386
+ * Restore the active tool loadout declared by the session transcript, if it declares one.
1387
+ * Tools reachable only from other tools are never declared, but they do not depend on the active
1388
+ * set, so the transcript's declarations are the whole loadout.
1389
+ */
1152
1390
  _restoreToolsFromTranscript() {
1153
1391
  const current = getCurrentSystemMessage(this.sessionManager.buildSessionContext().messages);
1154
1392
  if (!current)
1155
1393
  return;
1156
- const toolNames = (current.toolsAdded ?? [])
1157
- .map((tool) => tool.name)
1158
- .filter((name) => this._toolRegistry.has(name));
1159
- this.agent.state.tools = toolNames.flatMap((name) => {
1160
- const registered = this._toolRegistry.get(name);
1161
- return registered ? [registered] : [];
1162
- });
1163
- this._rebuildSystemPrompt(toolNames);
1394
+ this.setActiveToolsByName((current.toolsAdded ?? []).map((tool) => tool.name));
1164
1395
  }
1165
1396
  // =========================================================================
1166
1397
  // Prompting
1167
1398
  // =========================================================================
1168
1399
  async _runAgentPrompt(messages) {
1169
1400
  this._agentRunAbortRequested = false;
1401
+ // Compaction before the prompt may have scheduled a retry; the new prompt replaces it.
1402
+ this._failedResponse = undefined;
1403
+ this._recordSelection();
1170
1404
  this._isAgentRunActive = true;
1171
1405
  try {
1172
1406
  await this.agent.prompt(messages);
@@ -1187,6 +1421,7 @@ export class AgentSession {
1187
1421
  finally {
1188
1422
  if (this._agentRunAbortRequested)
1189
1423
  this._finishCancelledRetry();
1424
+ this._failedResponse = undefined;
1190
1425
  this._runSystemPromptOptions = undefined;
1191
1426
  this._flushPendingBashMessages();
1192
1427
  this._flushPendingCustomMessages();
@@ -1207,6 +1442,7 @@ export class AgentSession {
1207
1442
  if (this._isRetryableError(message) && (await this._prepareRetry(message))) {
1208
1443
  if (this._agentRunAbortRequested)
1209
1444
  this._finishCancelledRetry();
1445
+ this._failedResponse = message;
1210
1446
  return !this._agentRunAbortRequested;
1211
1447
  }
1212
1448
  if (this._agentRunAbortRequested) {
@@ -1274,7 +1510,7 @@ export class AgentSession {
1274
1510
  for (const image of images) {
1275
1511
  const processed = await processImage(Buffer.from(image.data, "base64"), image.mimeType, {
1276
1512
  autoResizeImages: this.settingsManager.getImageAutoResize(),
1277
- resizeOptions: this.model?.inputLimits?.images?.resize,
1513
+ resizeOptions: this._limitsModel()?.inputLimits?.images?.resize,
1278
1514
  });
1279
1515
  if (!processed.ok) {
1280
1516
  hints.push(processed.message);
@@ -1300,7 +1536,7 @@ export class AgentSession {
1300
1536
  return;
1301
1537
  }
1302
1538
  // A user-initiated prompt is the recovery point for failed completion deliveries.
1303
- this.retryBackgroundNotifications();
1539
+ this.retryTaskNotifications();
1304
1540
  const expandPromptTemplates = options?.expandPromptTemplates ?? true;
1305
1541
  const preflightResult = options?.preflightResult;
1306
1542
  let messages;
@@ -1312,20 +1548,20 @@ export class AgentSession {
1312
1548
  const handled = await this._tryExecuteExtensionCommand(text);
1313
1549
  if (handled) {
1314
1550
  // Extension command executed, no prompt to send
1315
- preflightResult?.(true);
1551
+ preflightResult?.("handled");
1316
1552
  return;
1317
1553
  }
1318
1554
  }
1319
1555
  // Observer commands above may stay open indefinitely; only real model input owns
1320
1556
  // the preflight pause, released once the user message is established.
1321
- resumeBackground = this.pauseBackgroundNotifications();
1557
+ resumeBackground = this.pauseTaskNotifications();
1322
1558
  if (this._compactionAbortController !== undefined) {
1323
1559
  throw new Error("Cannot submit a prompt while compaction is in progress. Wait for compaction to finish and retry.");
1324
1560
  }
1325
1561
  // Emit input event for extension interception (before skill/template expansion)
1326
1562
  const processedInput = await this._runInputHandlers(text, options?.images, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
1327
1563
  if (!processedInput) {
1328
- preflightResult?.(true);
1564
+ preflightResult?.("handled");
1329
1565
  return;
1330
1566
  }
1331
1567
  const { text: currentText, images: currentImages } = processedInput;
@@ -1346,7 +1582,7 @@ export class AgentSession {
1346
1582
  else {
1347
1583
  await this._queueSteer(expandedText, currentImages);
1348
1584
  }
1349
- preflightResult?.(true);
1585
+ preflightResult?.("queued");
1350
1586
  return;
1351
1587
  }
1352
1588
  // Flush any pending bash and custom messages before the new prompt
@@ -1396,7 +1632,6 @@ export class AgentSession {
1396
1632
  timestamp: Date.now(),
1397
1633
  });
1398
1634
  // Inject any pending "nextTurn" messages as context alongside the user message
1399
- // They stay queued until _messagePersisted() confirms the append.
1400
1635
  for (const msg of this._pendingNextTurnMessages) {
1401
1636
  messages.push(msg);
1402
1637
  }
@@ -1416,18 +1651,12 @@ export class AgentSession {
1416
1651
  if (updateMessage)
1417
1652
  messages.unshift(updateMessage);
1418
1653
  }
1419
- catch (error) {
1420
- preflightResult?.(false);
1421
- throw error;
1422
- }
1423
1654
  finally {
1424
- // Delivery is timer-scheduled, so a completion cannot start before the run below does.
1425
1655
  resumeBackground?.();
1426
1656
  }
1427
- if (!messages) {
1657
+ if (!messages)
1428
1658
  return;
1429
- }
1430
- preflightResult?.(true);
1659
+ preflightResult?.("started");
1431
1660
  await this._runAgentPrompt(messages);
1432
1661
  }
1433
1662
  /**
@@ -1493,7 +1722,7 @@ export class AgentSession {
1493
1722
  }
1494
1723
  const processedInput = await this._runInputHandlers(text, images, source, this.isStreaming ? behavior : undefined);
1495
1724
  if (!processedInput)
1496
- return;
1725
+ return "handled";
1497
1726
  let expandedText = this._expandSkillCommand(processedInput.text);
1498
1727
  expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
1499
1728
  if (behavior === "steer") {
@@ -1502,6 +1731,7 @@ export class AgentSession {
1502
1731
  else {
1503
1732
  await this._queueFollowUp(expandedText, processedInput.images);
1504
1733
  }
1734
+ return "queued";
1505
1735
  }
1506
1736
  /**
1507
1737
  * Queue a steering message while the agent is running.
@@ -1513,7 +1743,7 @@ export class AgentSession {
1513
1743
  * @throws Error if text is an extension command
1514
1744
  */
1515
1745
  async steer(text, images, options) {
1516
- await this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
1746
+ return this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
1517
1747
  }
1518
1748
  /**
1519
1749
  * Queue a follow-up message to be processed after the agent finishes.
@@ -1524,7 +1754,7 @@ export class AgentSession {
1524
1754
  * @throws Error if text is an extension command
1525
1755
  */
1526
1756
  async followUp(text, images, options) {
1527
- await this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
1757
+ return this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
1528
1758
  }
1529
1759
  /**
1530
1760
  * Internal: Queue a steering message (already expanded, no extension command check).
@@ -1685,7 +1915,7 @@ export class AgentSession {
1685
1915
  this._steeringMessages = [];
1686
1916
  this._followUpMessages = [];
1687
1917
  this.agent.clearAllQueues();
1688
- this._backgroundHost.queueCleared();
1918
+ this._tasksHost.delivery.queueCleared();
1689
1919
  this._emitQueueUpdate();
1690
1920
  return { steering, followUp };
1691
1921
  }
@@ -1942,8 +2172,10 @@ export class AgentSession {
1942
2172
  // Compaction
1943
2173
  // =========================================================================
1944
2174
  /** Generate Pi's built-in compaction summary for manual and automatic compaction. */
1945
- async _runDefaultCompaction(preparation, requestModel, apiKey, headers, customInstructions, signal, env, reason) {
1946
- return compact(preparation, requestModel, apiKey, headers, customInstructions, signal, this.thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }), undefined);
2175
+ async _runDefaultCompaction(preparation, model, customInstructions, signal, reason) {
2176
+ // Resolve the request only when Pi summarizes itself: routing may call models or fail.
2177
+ const request = await this._getSummarizationRequestAuth(model, signal);
2178
+ return compact(preparation, request.model, request.apiKey, request.headers, customInstructions, signal, request.thinkingLevel, this.agent.streamFunction, request.env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }), undefined);
1947
2179
  }
1948
2180
  _clearManualCompactionState() {
1949
2181
  this._compactionAbortController = undefined;
@@ -1965,7 +2197,7 @@ export class AgentSession {
1965
2197
  * @param customInstructions Optional instructions for the compaction summary
1966
2198
  */
1967
2199
  async compact(customInstructions) {
1968
- return this._withBackgroundPaused(() => this._compactBody(customInstructions));
2200
+ return this._withTasksPaused(() => this._compactBody(customInstructions));
1969
2201
  }
1970
2202
  async _compactBody(customInstructions) {
1971
2203
  await this.abort();
@@ -1978,8 +2210,7 @@ export class AgentSession {
1978
2210
  if (!model) {
1979
2211
  throw new Error(formatNoModelSelectedMessage());
1980
2212
  }
1981
- const settings = this.settingsManager.getCompactionSettings(model);
1982
- const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
2213
+ const settings = this.settingsManager.getCompactionSettings(this.routedModel?.model ?? model);
1983
2214
  const pathEntries = this.sessionManager.getBranch();
1984
2215
  const preparation = prepareCompaction(pathEntries, settings);
1985
2216
  if (!preparation) {
@@ -2025,7 +2256,7 @@ export class AgentSession {
2025
2256
  }
2026
2257
  else {
2027
2258
  // Shared default summary generator, also used by automatic compaction.
2028
- const result = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, customInstructions, this._compactionAbortController.signal, env, "manual");
2259
+ const result = await this._runDefaultCompaction(preparation, model, customInstructions, this._compactionAbortController.signal, "manual");
2029
2260
  summary = result.summary;
2030
2261
  firstKeptEntryId = result.firstKeptEntryId;
2031
2262
  tokensBefore = result.tokensBefore;
@@ -2130,18 +2361,20 @@ export class AgentSession {
2130
2361
  * @returns Whether the post-run loop should call `agent.continue()` for overflow recovery or queued messages
2131
2362
  */
2132
2363
  async _checkCompaction(assistantMessage, skipAbortedCheck = true, toolResults = []) {
2133
- const settings = this.settingsManager.getCompactionSettings(this.model);
2364
+ const settings = this.settingsManager.getCompactionSettings(this._modelForMessage(assistantMessage) ?? this.model);
2134
2365
  if (!settings.enabled)
2135
2366
  return false;
2136
2367
  // Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
2137
2368
  if (skipAbortedCheck && assistantMessage.stopReason === "aborted")
2138
2369
  return false;
2139
- const contextWindow = this.model?.contextWindow ?? 0;
2140
2370
  // Skip overflow check if the message came from a different model.
2141
2371
  // This handles the case where user switched from a smaller-context model (e.g. opus)
2142
2372
  // to a larger-context model (e.g. codex) - the overflow error from the old model
2143
- // shouldn't trigger compaction for the new model.
2144
- const sameModel = this.model && assistantMessage.provider === this.model.provider && assistantMessage.model === this.model.id;
2373
+ // shouldn't trigger compaction for the new model. Under a virtual selection, the
2374
+ // physical model that produced the message supplies the limits.
2375
+ const messageModel = this._modelForMessage(assistantMessage);
2376
+ const sameModel = messageModel !== undefined;
2377
+ const contextWindow = (messageModel ?? this.model)?.contextWindow ?? 0;
2145
2378
  // Skip compaction checks if this assistant message is older than the latest
2146
2379
  // compaction boundary. This prevents a stale pre-compaction usage/error
2147
2380
  // from retriggering compaction on the first prompt after compaction.
@@ -2173,7 +2406,7 @@ export class AgentSession {
2173
2406
  const contextOverflow = sameModel &&
2174
2407
  ((explicitOverflow && assistantRetainedForExplicitRecovery) ||
2175
2408
  (assistantUsageMatchesProjection && isContextOverflow(assistantMessage, contextWindow)));
2176
- const recoverableLength = sameModel && assistantIsProjected && isRecoverableLength(assistantMessage, this.model?.maxTokens ?? 0);
2409
+ const recoverableLength = sameModel && assistantIsProjected && isRecoverableLength(assistantMessage, messageModel.maxTokens);
2177
2410
  if (contextOverflow || recoverableLength) {
2178
2411
  const willRetry = assistantMessage.stopReason !== "stop";
2179
2412
  // Case 2: the response completed successfully. Compact, but do not retry because
@@ -2205,7 +2438,10 @@ export class AgentSession {
2205
2438
  // Persistently omit the selected final attempt before post-run recovery compaction.
2206
2439
  this._overflowRecoveryAttempted = true;
2207
2440
  this._omitRecoveryAttempt(assistantMessage, toolResults);
2208
- return await this._runAutoCompaction("overflow", willRetry);
2441
+ const retry = await this._runAutoCompaction("overflow", willRetry);
2442
+ if (retry)
2443
+ this._failedResponse = assistantMessage;
2444
+ return retry;
2209
2445
  }
2210
2446
  // Case 3: threshold compaction without retry.
2211
2447
  // For error messages or all-zero usage messages, estimate from the last valid response.
@@ -2255,11 +2491,11 @@ export class AgentSession {
2255
2491
  * @returns Whether the post-run loop should call `agent.continue()`
2256
2492
  */
2257
2493
  async _runAutoCompaction(reason, willRetry) {
2258
- return this._withBackgroundPaused(() => this._runAutoCompactionBody(reason, willRetry));
2494
+ return this._withTasksPaused(() => this._runAutoCompactionBody(reason, willRetry));
2259
2495
  }
2260
2496
  async _runAutoCompactionBody(reason, willRetry) {
2261
2497
  const model = this.model;
2262
- const settings = this.settingsManager.getCompactionSettings(model);
2498
+ const settings = this.settingsManager.getCompactionSettings(this.routedModel?.model ?? model);
2263
2499
  let abortController;
2264
2500
  let started = false;
2265
2501
  let fromExtension = false;
@@ -2278,8 +2514,6 @@ export class AgentSession {
2278
2514
  started = true;
2279
2515
  this._emit({ type: "compaction_start", reason });
2280
2516
  abortController.signal.throwIfAborted();
2281
- const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2282
- abortController.signal.throwIfAborted();
2283
2517
  let extensionCompaction;
2284
2518
  if (this._extensionRunner.hasHandlers("session_before_compact")) {
2285
2519
  const extensionResult = (await this._extensionRunner.emit({
@@ -2316,7 +2550,7 @@ export class AgentSession {
2316
2550
  }
2317
2551
  else {
2318
2552
  // Shared default summary generator, also used by manual compaction.
2319
- const compactResult = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, undefined, abortController.signal, env, reason);
2553
+ const compactResult = await this._runDefaultCompaction(preparation, model, undefined, abortController.signal, reason);
2320
2554
  summary = compactResult.summary;
2321
2555
  firstKeptEntryId = compactResult.firstKeptEntryId;
2322
2556
  tokensBefore = compactResult.tokensBefore;
@@ -2399,11 +2633,12 @@ export class AgentSession {
2399
2633
  return this.settingsManager.getCompactionEnabled();
2400
2634
  }
2401
2635
  async bindExtensions(bindings) {
2402
- return this._withBackgroundPaused(() => this._bindExtensionsBody(bindings));
2636
+ return this._withTasksPaused(() => this._bindExtensionsBody(bindings));
2403
2637
  }
2404
2638
  async _bindExtensionsBody(bindings) {
2405
- if (bindings.backgroundEnabled !== undefined) {
2406
- this._backgroundHost.setEnabled(bindings.backgroundEnabled);
2639
+ if (bindings.tasksEnabled !== undefined) {
2640
+ this._tasksHost.setEnabled(bindings.tasksEnabled);
2641
+ this._refreshToolRegistry();
2407
2642
  }
2408
2643
  if (bindings.uiContext !== undefined) {
2409
2644
  this._extensionUIContext = bindings.uiContext;
@@ -2425,6 +2660,7 @@ export class AgentSession {
2425
2660
  }
2426
2661
  this._applyExtensionBindings(this._extensionRunner);
2427
2662
  await this._extensionRunner.emit(this._sessionStartEvent);
2663
+ this._extensionRunner.reportUnhandledMcpServers();
2428
2664
  await this.extendResourcesFromExtensions(this._sessionStartEvent.reason === "reload" ? "reload" : "startup");
2429
2665
  }
2430
2666
  async extendResourcesFromExtensions(reason) {
@@ -2446,7 +2682,7 @@ export class AgentSession {
2446
2682
  buildExtensionResourcePaths(entries) {
2447
2683
  return entries.map((entry) => {
2448
2684
  const source = this.getExtensionSourceLabel(entry.extensionPath);
2449
- const baseDir = entry.extensionPath.startsWith("<") ? undefined : dirname(entry.extensionPath);
2685
+ const baseDir = isSyntheticPath(entry.extensionPath) ? undefined : dirname(entry.extensionPath);
2450
2686
  return {
2451
2687
  path: entry.path,
2452
2688
  metadata: {
@@ -2459,7 +2695,7 @@ export class AgentSession {
2459
2695
  });
2460
2696
  }
2461
2697
  getExtensionSourceLabel(extensionPath) {
2462
- if (extensionPath.startsWith("<")) {
2698
+ if (isSyntheticPath(extensionPath)) {
2463
2699
  return `extension:${extensionPath.replace(/[<>]/g, "")}`;
2464
2700
  }
2465
2701
  const base = basename(extensionPath);
@@ -2544,6 +2780,7 @@ export class AgentSession {
2544
2780
  },
2545
2781
  getActiveTools: () => this.getActiveToolNames(),
2546
2782
  getAllTools: () => this.getAllTools(),
2783
+ getSettings: () => this.settingsManager.getSettings(),
2547
2784
  setActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),
2548
2785
  refreshTools: () => this._refreshToolRegistry(),
2549
2786
  getCommands,
@@ -2556,7 +2793,9 @@ export class AgentSession {
2556
2793
  getThinkingLevel: () => this.thinkingLevel,
2557
2794
  setThinkingLevel: (level) => this.setThinkingLevel(level),
2558
2795
  }, {
2559
- getBackground: () => this.background,
2796
+ getTasks: () => this.tasks,
2797
+ getExtensionSettings: (namespace) => this.settingsManager.getExtensionSettings(namespace),
2798
+ setExtensionSettings: (namespace, value) => this.settingsManager.setExtensionSettings(namespace, value),
2560
2799
  getModel: () => this.model,
2561
2800
  getScopedModels: () => this._scopedModels,
2562
2801
  isIdle: () => this.isIdle,
@@ -2589,6 +2828,8 @@ export class AgentSession {
2589
2828
  },
2590
2829
  getSystemPrompt: () => this.systemPrompt,
2591
2830
  getSystemPromptOptions: () => this._baseSystemPromptOptions,
2831
+ executeTool: (callerId, name, args, options) => this._executeNestedToolCall(callerId, name, args, options),
2832
+ getCallableTools: () => this._getCallableTools(),
2592
2833
  }, {
2593
2834
  registerProvider: (name, config) => {
2594
2835
  this._modelRuntime.registerProvider(name, config);
@@ -2602,10 +2843,20 @@ export class AgentSession {
2602
2843
  this._modelRuntime.unregisterProvider(name);
2603
2844
  this._refreshCurrentModelFromRegistry();
2604
2845
  },
2846
+ registerVirtualModel: (definition) => {
2847
+ this._modelRuntime.registerVirtualModel(definition);
2848
+ this._refreshCurrentModelFromRegistry();
2849
+ },
2850
+ unregisterVirtualModel: (provider, id) => {
2851
+ this._modelRuntime.unregisterVirtualModel(provider, id);
2852
+ this._refreshCurrentModelFromRegistry();
2853
+ },
2605
2854
  });
2606
2855
  }
2607
2856
  _refreshToolRegistry(options) {
2608
- const previousRegistryNames = new Set(this._toolRegistry.keys());
2857
+ // Tools that were already activated on registration. A tool whose exposure changes to
2858
+ // `direct` or `model-only` (for example from `hidden`) is activated like a new tool.
2859
+ const previousActivatedOnRegistration = new Set([...this._toolRegistry.keys()].filter((name) => this._isActivatedOnRegistration(name)));
2609
2860
  const previousActiveToolNames = this.getActiveToolNames();
2610
2861
  const allowedToolNames = this._allowedToolNames;
2611
2862
  const excludedToolNames = this._excludedToolNames;
@@ -2624,7 +2875,7 @@ export class AgentSession {
2624
2875
  name,
2625
2876
  {
2626
2877
  definition,
2627
- sourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, { source: "builtin" }),
2878
+ sourceInfo: createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${name}`, { source: "builtin" }),
2628
2879
  },
2629
2880
  ]));
2630
2881
  for (const tool of allCustomTools) {
@@ -2652,7 +2903,9 @@ export class AgentSession {
2652
2903
  .filter((definition) => isAllowedTool(definition.name))
2653
2904
  .map((definition) => ({
2654
2905
  definition,
2655
- sourceInfo: createSyntheticSourceInfo(`<builtin:${definition.name}>`, { source: "builtin" }),
2906
+ sourceInfo: createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${definition.name}`, {
2907
+ source: "builtin",
2908
+ }),
2656
2909
  })), runner);
2657
2910
  const toolRegistry = new Map(wrappedBuiltInTools.map((tool) => [tool.name, tool]));
2658
2911
  for (const tool of wrappedExtensionTools) {
@@ -2662,25 +2915,41 @@ export class AgentSession {
2662
2915
  const nextActiveToolNames = (options?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]).filter((name) => isAllowedTool(name));
2663
2916
  if (allowedToolNames) {
2664
2917
  for (const toolName of this._toolRegistry.keys()) {
2665
- if (allowedToolNames.has(toolName)) {
2918
+ // Naming a tool activates it even when it is not active by default.
2919
+ if (allowedToolNames.has(toolName) && this._isDeclarable(toolName)) {
2666
2920
  nextActiveToolNames.push(toolName);
2667
2921
  }
2668
2922
  }
2669
2923
  }
2670
2924
  else if (options?.includeAllExtensionTools) {
2671
2925
  for (const tool of wrappedExtensionTools) {
2672
- nextActiveToolNames.push(tool.name);
2926
+ if (this._isActivatedOnRegistration(tool.name))
2927
+ nextActiveToolNames.push(tool.name);
2673
2928
  }
2674
2929
  }
2675
2930
  else if (!options?.activeToolNames) {
2676
2931
  for (const toolName of this._toolRegistry.keys()) {
2677
- if (!previousRegistryNames.has(toolName)) {
2932
+ if (!previousActivatedOnRegistration.has(toolName) && this._isActivatedOnRegistration(toolName)) {
2678
2933
  nextActiveToolNames.push(toolName);
2679
2934
  }
2680
2935
  }
2681
2936
  }
2937
+ if (this.tasks.enabled &&
2938
+ this._initialActiveToolNames?.length !== 0 &&
2939
+ this._toolRegistry.has("tasks") &&
2940
+ isAllowedTool("tasks"))
2941
+ nextActiveToolNames.push("tasks");
2682
2942
  this.setActiveToolsByName([...new Set(nextActiveToolNames)]);
2683
2943
  }
2944
+ /** Whether activating the tool declares it to the model. */
2945
+ _isDeclarable(name) {
2946
+ const exposure = this._getToolExposure(name);
2947
+ return exposure === "direct" || exposure === "model-only";
2948
+ }
2949
+ /** Whether registering the tool activates it, which declares it to the model. */
2950
+ _isActivatedOnRegistration(name) {
2951
+ return this._isDeclarable(name) && this._toolDefinitions.get(name)?.definition.defaultActive !== false;
2952
+ }
2684
2953
  _buildRuntime(options) {
2685
2954
  const autoResizeImages = this.settingsManager.getImageAutoResize();
2686
2955
  const shellCommandPrefix = this.settingsManager.getShellCommandPrefix();
@@ -2695,6 +2964,7 @@ export class AgentSession {
2695
2964
  bash: { commandPrefix: shellCommandPrefix, shellPath },
2696
2965
  });
2697
2966
  this._baseToolDefinitions = new Map(Object.entries(baseToolDefinitions).map(([name, tool]) => [name, tool]));
2967
+ this._baseToolDefinitions.set("tasks", createTasksToolDefinition((callId, taskId) => this._tasksHost.delivery.prepareWait(callId, taskId)));
2698
2968
  const extensionsResult = this._resourceLoader.getExtensions();
2699
2969
  if (options.flagValues) {
2700
2970
  for (const [name, value] of options.flagValues) {
@@ -2717,26 +2987,26 @@ export class AgentSession {
2717
2987
  });
2718
2988
  }
2719
2989
  async reload(options) {
2720
- return this._withBackgroundPaused(() => this._reloadBody(options));
2990
+ return this._withTasksPaused(() => this._reloadBody(options));
2721
2991
  }
2722
2992
  async _reloadBody(options) {
2723
2993
  const oldRunner = this._extensionRunner;
2724
2994
  const previousFlagValues = oldRunner.getFlagValues();
2725
- this.background.close();
2726
- await Promise.all([this.background.shutdown(), this.abort()]);
2995
+ this.tasks.close();
2996
+ await Promise.all([this.tasks.shutdown(), this.abort()]);
2727
2997
  await emitSessionShutdownEvent(oldRunner, { type: "session_shutdown", reason: "reload" });
2728
2998
  oldRunner.invalidate();
2729
2999
  await this.settingsManager.reload();
2730
3000
  this.syncQueueModesFromSettings();
2731
3001
  resetApiProviders();
2732
3002
  await this._resourceLoader.reload();
2733
- this._backgroundHost.replaceService();
3003
+ this._tasksHost.replaceService();
2734
3004
  this._buildRuntime({
2735
3005
  activeToolNames: this.getActiveToolNames(),
2736
3006
  flagValues: previousFlagValues,
2737
3007
  includeAllExtensionTools: true,
2738
3008
  });
2739
- const hasBindings = this.background.enabled ||
3009
+ const hasBindings = this.tasks.enabled ||
2740
3010
  this._extensionUIContext ||
2741
3011
  this._extensionCommandContextActions ||
2742
3012
  this._extensionShutdownHandler ||
@@ -2744,6 +3014,7 @@ export class AgentSession {
2744
3014
  if (hasBindings) {
2745
3015
  await options?.beforeSessionStart?.();
2746
3016
  await this._extensionRunner.emit({ type: "session_start", reason: "reload" });
3017
+ this._extensionRunner.reportUnhandledMcpServers();
2747
3018
  await this.extendResourcesFromExtensions("reload");
2748
3019
  }
2749
3020
  }
@@ -2756,7 +3027,7 @@ export class AgentSession {
2756
3027
  */
2757
3028
  _isRetryableError(message) {
2758
3029
  // Context overflow is handled by compaction, not retry.
2759
- if (isContextOverflow(message, this.model?.contextWindow ?? 0))
3030
+ if (isContextOverflow(message, (this._modelForMessage(message) ?? this.model)?.contextWindow ?? 0))
2760
3031
  return false;
2761
3032
  return isRetryableAssistantError(message);
2762
3033
  }
@@ -3011,7 +3282,7 @@ export class AgentSession {
3011
3282
  replaceInstructions,
3012
3283
  label,
3013
3284
  };
3014
- const resumeBackground = this.pauseBackgroundNotifications();
3285
+ const resumeBackground = this.pauseTaskNotifications();
3015
3286
  // Set up abort controller for summarization
3016
3287
  this._branchSummaryAbortController = new AbortController();
3017
3288
  try {
@@ -3047,15 +3318,11 @@ export class AgentSession {
3047
3318
  let summaryDetails;
3048
3319
  let summaryUsage;
3049
3320
  if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
3050
- const model = this.model;
3051
- const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
3321
+ const signal = this._branchSummaryAbortController.signal;
3052
3322
  const branchSummarySettings = this.settingsManager.getBranchSummarySettings();
3053
3323
  const result = await generateBranchSummary(entriesToSummarize, {
3054
- model: requestModel,
3055
- apiKey,
3056
- headers,
3057
- env,
3058
- signal: this._branchSummaryAbortController.signal,
3324
+ ...(await this._getSummarizationRequestAuth(this.model, signal)),
3325
+ signal,
3059
3326
  customInstructions,
3060
3327
  replaceInstructions,
3061
3328
  reserveTokens: branchSummarySettings.reserveTokens,
@@ -3098,7 +3365,7 @@ export class AgentSession {
3098
3365
  // Non-user message: leaf = selected node
3099
3366
  newLeafId = targetId;
3100
3367
  }
3101
- await this.background.cancelOutsideBranch(new Set(newLeafId === null ? [] : this.sessionManager.getBranch(newLeafId).map((entry) => entry.id)));
3368
+ await this.tasks.cancelOutsideBranch(new Set(newLeafId === null ? [] : this.sessionManager.getBranch(newLeafId).map((entry) => entry.id)));
3102
3369
  // Switch leaf (with or without summary)
3103
3370
  // Summary is attached at the navigation target position (newLeafId), not the old branch
3104
3371
  let summaryEntry;
@@ -3123,7 +3390,7 @@ export class AgentSession {
3123
3390
  if (label && !summaryText) {
3124
3391
  this.sessionManager.appendLabelChange(targetId, label);
3125
3392
  }
3126
- this._backgroundHost.restoreHistory();
3393
+ this._tasksHost.restoreHistory();
3127
3394
  // Update finalized context from the canonical session projection.
3128
3395
  this._refreshFinalizedContext();
3129
3396
  this._restoreToolsFromTranscript();
@@ -3216,7 +3483,7 @@ export class AgentSession {
3216
3483
  };
3217
3484
  }
3218
3485
  getContextUsage() {
3219
- const model = this.model;
3486
+ const model = this._limitsModel();
3220
3487
  if (!model)
3221
3488
  return undefined;
3222
3489
  const contextWindow = model.contextWindow ?? 0;
@@ -3288,16 +3555,11 @@ export class AgentSession {
3288
3555
  if (!model) {
3289
3556
  throw new Error("No model selected");
3290
3557
  }
3291
- const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
3292
3558
  return generateBugReportSummary({
3559
+ ...(await this._getSummarizationRequestAuth(model, options.signal)),
3293
3560
  messages: this.messages,
3294
3561
  hint: options.hint,
3295
- model: requestModel,
3296
- apiKey,
3297
- headers,
3298
- env,
3299
3562
  signal: options.signal,
3300
- thinkingLevel: this.thinkingLevel,
3301
3563
  streamFn: this.agent.streamFunction,
3302
3564
  retry: this.settingsManager.getRetrySettings(),
3303
3565
  sessionId: this.sessionId,