@averyyy/pi-coding-agent 0.87.1-piclient.2 → 1.0.0-piclient.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (765) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/dist/bun/cli.d.ts.map +1 -1
  3. package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
  4. package/dist/bun/restore-sandbox-env.js.map +1 -1
  5. package/dist/bun/runtime-setup.d.ts.map +1 -1
  6. package/dist/bun/runtime-setup.js +4 -1
  7. package/dist/bun/runtime-setup.js.map +1 -1
  8. package/dist/bun/sandbox-env-setup.d.ts.map +1 -1
  9. package/dist/bundle/chunks/anthropic-messages-UID2PALB.js +6 -0
  10. package/dist/bundle/chunks/anthropic.js +2 -2
  11. package/dist/bundle/chunks/azure-openai-responses-WK37QQ3X.js +2 -0
  12. package/dist/bundle/chunks/bedrock-converse-stream.js +3 -3
  13. package/dist/bundle/chunks/chunk-2LGHNI5Y.js +1553 -0
  14. package/dist/bundle/chunks/chunk-6D7LHLKG.js +2 -0
  15. package/dist/bundle/chunks/chunk-7JGR3GZN.js +11 -0
  16. package/dist/bundle/chunks/{chunk-FUXEF6JQ.js → chunk-CWVWZD3J.js} +2 -2
  17. package/dist/bundle/chunks/chunk-GIUN2MS4.js +16 -0
  18. package/dist/bundle/chunks/chunk-H3QXYIF7.js +31 -0
  19. package/dist/bundle/chunks/chunk-KYK7L7MP.js +127 -0
  20. package/dist/bundle/chunks/chunk-LD2P6SFZ.js +2 -0
  21. package/dist/bundle/chunks/chunk-LDPPAHPJ.js +4 -0
  22. package/dist/bundle/chunks/chunk-NEUJZQL3.js +19 -0
  23. package/dist/bundle/chunks/chunk-OI6YFHHK.js +82 -0
  24. package/dist/bundle/chunks/chunk-OSKPX3Z5.js +2 -0
  25. package/dist/bundle/chunks/{chunk-XDUWOHPL.js → chunk-S3GGRYIO.js} +2 -2
  26. package/dist/bundle/chunks/chunk-SQXKOUF6.js +2 -0
  27. package/dist/bundle/chunks/chunk-UTB4DTYQ.js +2 -0
  28. package/dist/bundle/chunks/chunk-VIV3CWXG.js +2 -0
  29. package/dist/bundle/chunks/chunk-Y5O5BZGX.js +136 -0
  30. package/dist/bundle/chunks/{chunk-UZNGGY6N.js → chunk-Z772OFUN.js} +3 -3
  31. package/dist/bundle/chunks/cli-JE36AHMI.js +51 -0
  32. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-NPQN263E.js +2 -0
  33. package/dist/bundle/chunks/codemode-worker.js +354 -0
  34. package/dist/bundle/chunks/execute-UX73LR4F.js +367 -0
  35. package/dist/bundle/chunks/github-copilot.js +1 -1
  36. package/dist/bundle/chunks/google-generative-ai-OHRSHIE7.js +2 -0
  37. package/dist/bundle/chunks/google-vertex-KXEB3MVO.js +2 -0
  38. package/dist/bundle/chunks/{https-proxy-agent-2VXB7436.js → https-proxy-agent-UDEHOBGS.js} +1 -1
  39. package/dist/bundle/chunks/{lib-HGQMNYVT.js → lib-TEDK3E5I.js} +2 -2
  40. package/dist/bundle/chunks/llama-cpp-classify-XT44PI3C.js +22 -0
  41. package/dist/bundle/chunks/mistral-conversations-DKVFNQL6.js +5 -0
  42. package/dist/bundle/chunks/openai-chatgpt.js +75 -0
  43. package/dist/bundle/chunks/{openai-codex-responses-SG7PGUUZ.js → openai-codex-responses-WVERB76N.js} +2 -2
  44. package/dist/bundle/chunks/openai-codex.js +2 -2
  45. package/dist/bundle/chunks/{openai-completions-OBX42CLD.js → openai-completions-JXDDPZ23.js} +2 -2
  46. package/dist/bundle/chunks/openai-responses-WDT74L23.js +3 -0
  47. package/dist/bundle/chunks/{openrouter-images-N4XVVFSD.js → openrouter-images-ZVXWCSIM.js} +1 -1
  48. package/dist/bundle/chunks/openrouter.js +2 -2
  49. package/dist/bundle/chunks/pi-logo-animation-APS4JS6B.js +2 -0
  50. package/dist/bundle/chunks/{pi-messages-GFKBWJHZ.js → pi-messages-TM5SOOIW.js} +2 -2
  51. package/dist/bundle/chunks/radius.js +2 -2
  52. package/dist/bundle/chunks/runtime-MPXPM7VL.js +2 -0
  53. package/dist/bundle/chunks/typesafe-system-one-A4CZTQWZ.js +2 -0
  54. package/dist/bundle/chunks/virtual-modules-XLXFDFIX.js +2 -0
  55. package/dist/bundle/cli-runtime.js +1 -1
  56. package/dist/bundle/index.js +1 -1
  57. package/dist/bundle/rpc-entry.js +1 -1
  58. package/dist/cli/args.d.ts.map +1 -1
  59. package/dist/cli/args.js +6 -5
  60. package/dist/cli/args.js.map +1 -1
  61. package/dist/cli/auth-check.d.ts.map +1 -1
  62. package/dist/cli/auth-check.js.map +1 -1
  63. package/dist/cli/auth-command.d.ts.map +1 -1
  64. package/dist/cli/auth-command.js.map +1 -1
  65. package/dist/cli/config-selector.d.ts.map +1 -1
  66. package/dist/cli/config-selector.js.map +1 -1
  67. package/dist/cli/credential-print.d.ts.map +1 -1
  68. package/dist/cli/credential-print.js.map +1 -1
  69. package/dist/cli/file-processor.d.ts.map +1 -1
  70. package/dist/cli/file-processor.js.map +1 -1
  71. package/dist/cli/initial-message.d.ts +1 -1
  72. package/dist/cli/initial-message.d.ts.map +1 -1
  73. package/dist/cli/initial-message.js.map +1 -1
  74. package/dist/cli/list-models.d.ts.map +1 -1
  75. package/dist/cli/list-models.js.map +1 -1
  76. package/dist/cli/project-trust.d.ts.map +1 -1
  77. package/dist/cli/project-trust.js.map +1 -1
  78. package/dist/cli/session-picker.d.ts.map +1 -1
  79. package/dist/cli/session-picker.js.map +1 -1
  80. package/dist/cli/setup.d.ts.map +1 -1
  81. package/dist/cli/setup.js.map +1 -1
  82. package/dist/cli/startup-ui.d.ts.map +1 -1
  83. package/dist/cli/startup-ui.js +38 -30
  84. package/dist/cli/startup-ui.js.map +1 -1
  85. package/dist/cli.d.ts.map +1 -1
  86. package/dist/config.d.ts +15 -4
  87. package/dist/config.d.ts.map +1 -1
  88. package/dist/config.js +33 -4
  89. package/dist/config.js.map +1 -1
  90. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  91. package/dist/core/agent-session-runtime.js +1 -1
  92. package/dist/core/agent-session-runtime.js.map +1 -1
  93. package/dist/core/agent-session-services.d.ts.map +1 -1
  94. package/dist/core/agent-session-services.js +13 -0
  95. package/dist/core/agent-session-services.js.map +1 -1
  96. package/dist/core/agent-session.d.ts +133 -12
  97. package/dist/core/agent-session.d.ts.map +1 -1
  98. package/dist/core/agent-session.js +598 -297
  99. package/dist/core/agent-session.js.map +1 -1
  100. package/dist/core/auth-guidance.d.ts.map +1 -1
  101. package/dist/core/auth-guidance.js.map +1 -1
  102. package/dist/core/auth-storage.d.ts.map +1 -1
  103. package/dist/core/auth-storage.js.map +1 -1
  104. package/dist/core/bash-executor.d.ts.map +1 -1
  105. package/dist/core/bash-executor.js.map +1 -1
  106. package/dist/core/bug-report-upload.d.ts.map +1 -1
  107. package/dist/core/bug-report-upload.js.map +1 -1
  108. package/dist/core/bug-report.d.ts +1 -1
  109. package/dist/core/bug-report.d.ts.map +1 -1
  110. package/dist/core/bug-report.js +1 -1
  111. package/dist/core/bug-report.js.map +1 -1
  112. package/dist/core/cache-stats.d.ts.map +1 -1
  113. package/dist/core/cache-stats.js.map +1 -1
  114. package/dist/core/cache-warmer.d.ts.map +1 -1
  115. package/dist/core/cache-warmer.js.map +1 -1
  116. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  117. package/dist/core/compaction/branch-summarization.js.map +1 -1
  118. package/dist/core/compaction/compaction.d.ts.map +1 -1
  119. package/dist/core/compaction/compaction.js +1 -22
  120. package/dist/core/compaction/compaction.js.map +1 -1
  121. package/dist/core/compaction/index.d.ts.map +1 -1
  122. package/dist/core/compaction/utils.d.ts +2 -1
  123. package/dist/core/compaction/utils.d.ts.map +1 -1
  124. package/dist/core/compaction/utils.js +25 -18
  125. package/dist/core/compaction/utils.js.map +1 -1
  126. package/dist/core/crash-log.d.ts.map +1 -1
  127. package/dist/core/crash-log.js +2 -1
  128. package/dist/core/crash-log.js.map +1 -1
  129. package/dist/core/defaults.d.ts.map +1 -1
  130. package/dist/core/diagnostics.d.ts.map +1 -1
  131. package/dist/core/event-bus.d.ts.map +1 -1
  132. package/dist/core/event-bus.js.map +1 -1
  133. package/dist/core/exec.d.ts.map +1 -1
  134. package/dist/core/exec.js.map +1 -1
  135. package/dist/core/experimental.d.ts.map +1 -1
  136. package/dist/core/experimental.js.map +1 -1
  137. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  138. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  139. package/dist/core/export-html/index.d.ts.map +1 -1
  140. package/dist/core/export-html/index.js.map +1 -1
  141. package/dist/core/export-html/template.css +10 -0
  142. package/dist/core/export-html/template.js +66 -17
  143. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  144. package/dist/core/export-html/tool-renderer.js.map +1 -1
  145. package/dist/core/extensions/index.d.ts +1 -1
  146. package/dist/core/extensions/index.d.ts.map +1 -1
  147. package/dist/core/extensions/index.js.map +1 -1
  148. package/dist/core/extensions/jiti-loader.d.ts.map +1 -1
  149. package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -1
  150. package/dist/core/extensions/loader.d.ts.map +1 -1
  151. package/dist/core/extensions/loader.js +67 -5
  152. package/dist/core/extensions/loader.js.map +1 -1
  153. package/dist/core/extensions/runner.d.ts +18 -1
  154. package/dist/core/extensions/runner.d.ts.map +1 -1
  155. package/dist/core/extensions/runner.js +99 -0
  156. package/dist/core/extensions/runner.js.map +1 -1
  157. package/dist/core/extensions/types.d.ts +301 -22
  158. package/dist/core/extensions/types.d.ts.map +1 -1
  159. package/dist/core/extensions/types.js.map +1 -1
  160. package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
  161. package/dist/core/extensions/wrapper.d.ts +2 -2
  162. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  163. package/dist/core/extensions/wrapper.js +3 -3
  164. package/dist/core/extensions/wrapper.js.map +1 -1
  165. package/dist/core/footer-data-provider.d.ts.map +1 -1
  166. package/dist/core/footer-data-provider.js.map +1 -1
  167. package/dist/core/http-dispatcher.d.ts.map +1 -1
  168. package/dist/core/http-dispatcher.js.map +1 -1
  169. package/dist/core/index.d.ts.map +1 -1
  170. package/dist/core/keybindings.d.ts +1 -1
  171. package/dist/core/keybindings.d.ts.map +1 -1
  172. package/dist/core/keybindings.js +1 -1
  173. package/dist/core/keybindings.js.map +1 -1
  174. package/dist/core/mcp-servers.d.ts +125 -0
  175. package/dist/core/mcp-servers.d.ts.map +1 -0
  176. package/dist/core/mcp-servers.js +198 -0
  177. package/dist/core/mcp-servers.js.map +1 -0
  178. package/dist/core/messages.d.ts.map +1 -1
  179. package/dist/core/messages.js.map +1 -1
  180. package/dist/core/model-config.d.ts.map +1 -1
  181. package/dist/core/model-config.js.map +1 -1
  182. package/dist/core/model-registry.d.ts +15 -1
  183. package/dist/core/model-registry.d.ts.map +1 -1
  184. package/dist/core/model-registry.js +29 -0
  185. package/dist/core/model-registry.js.map +1 -1
  186. package/dist/core/model-resolver.d.ts +2 -2
  187. package/dist/core/model-resolver.d.ts.map +1 -1
  188. package/dist/core/model-resolver.js +5 -5
  189. package/dist/core/model-resolver.js.map +1 -1
  190. package/dist/core/model-runtime.d.ts +47 -3
  191. package/dist/core/model-runtime.d.ts.map +1 -1
  192. package/dist/core/model-runtime.js +189 -35
  193. package/dist/core/model-runtime.js.map +1 -1
  194. package/dist/core/models-store.d.ts.map +1 -1
  195. package/dist/core/models-store.js.map +1 -1
  196. package/dist/core/nested-tool-calls.d.ts +102 -0
  197. package/dist/core/nested-tool-calls.d.ts.map +1 -0
  198. package/dist/core/nested-tool-calls.js +178 -0
  199. package/dist/core/nested-tool-calls.js.map +1 -0
  200. package/dist/core/output-guard.d.ts.map +1 -1
  201. package/dist/core/output-guard.js.map +1 -1
  202. package/dist/core/package-manager.d.ts +4 -0
  203. package/dist/core/package-manager.d.ts.map +1 -1
  204. package/dist/core/package-manager.js +59 -12
  205. package/dist/core/package-manager.js.map +1 -1
  206. package/dist/core/pi-client-cli-adapter.d.ts.map +1 -1
  207. package/dist/core/pi-client-cli-adapter.js.map +1 -1
  208. package/dist/core/pi-client-runtime-update.d.ts.map +1 -1
  209. package/dist/core/pi-client-runtime-update.js.map +1 -1
  210. package/dist/core/pi-manifest.d.ts.map +1 -1
  211. package/dist/core/pi-manifest.js.map +1 -1
  212. package/dist/core/pi-server-client.d.ts.map +1 -1
  213. package/dist/core/pi-server-client.js.map +1 -1
  214. package/dist/core/pi-server-protocol.d.ts.map +1 -1
  215. package/dist/core/pi-server-protocol.js.map +1 -1
  216. package/dist/core/pi-server-request.d.ts.map +1 -1
  217. package/dist/core/pi-server-request.js.map +1 -1
  218. package/dist/core/project-trust.d.ts.map +1 -1
  219. package/dist/core/project-trust.js.map +1 -1
  220. package/dist/core/prompt-templates.d.ts.map +1 -1
  221. package/dist/core/prompt-templates.js.map +1 -1
  222. package/dist/core/provider-attribution.d.ts.map +1 -1
  223. package/dist/core/provider-attribution.js.map +1 -1
  224. package/dist/core/provider-composer.d.ts +40 -21
  225. package/dist/core/provider-composer.d.ts.map +1 -1
  226. package/dist/core/provider-composer.js +92 -40
  227. package/dist/core/provider-composer.js.map +1 -1
  228. package/dist/core/radius.d.ts +2 -0
  229. package/dist/core/radius.d.ts.map +1 -1
  230. package/dist/core/radius.js +2 -0
  231. package/dist/core/radius.js.map +1 -1
  232. package/dist/core/remote-catalog-provider.d.ts +8 -1
  233. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  234. package/dist/core/remote-catalog-provider.js +21 -11
  235. package/dist/core/remote-catalog-provider.js.map +1 -1
  236. package/dist/core/resolve-config-value.d.ts.map +1 -1
  237. package/dist/core/resolve-config-value.js.map +1 -1
  238. package/dist/core/resource-loader.d.ts +7 -1
  239. package/dist/core/resource-loader.d.ts.map +1 -1
  240. package/dist/core/resource-loader.js +161 -35
  241. package/dist/core/resource-loader.js.map +1 -1
  242. package/dist/core/runtime-credentials.d.ts.map +1 -1
  243. package/dist/core/runtime-credentials.js.map +1 -1
  244. package/dist/core/sdk.d.ts +1 -1
  245. package/dist/core/sdk.d.ts.map +1 -1
  246. package/dist/core/sdk.js +25 -6
  247. package/dist/core/sdk.js.map +1 -1
  248. package/dist/core/session-cwd.d.ts.map +1 -1
  249. package/dist/core/session-cwd.js.map +1 -1
  250. package/dist/core/session-export.d.ts.map +1 -1
  251. package/dist/core/session-export.js.map +1 -1
  252. package/dist/core/session-manager.d.ts +9 -0
  253. package/dist/core/session-manager.d.ts.map +1 -1
  254. package/dist/core/session-manager.js +22 -22
  255. package/dist/core/session-manager.js.map +1 -1
  256. package/dist/core/settings-diagnostics.d.ts.map +1 -1
  257. package/dist/core/settings-diagnostics.js.map +1 -1
  258. package/dist/core/settings-manager.d.ts +36 -4
  259. package/dist/core/settings-manager.d.ts.map +1 -1
  260. package/dist/core/settings-manager.js +75 -4
  261. package/dist/core/settings-manager.js.map +1 -1
  262. package/dist/core/skills.d.ts.map +1 -1
  263. package/dist/core/skills.js.map +1 -1
  264. package/dist/core/slash-commands.d.ts.map +1 -1
  265. package/dist/core/source-info.d.ts +8 -0
  266. package/dist/core/source-info.d.ts.map +1 -1
  267. package/dist/core/source-info.js +16 -0
  268. package/dist/core/source-info.js.map +1 -1
  269. package/dist/core/system-prompt.d.ts.map +1 -1
  270. package/dist/core/system-prompt.js +1 -1
  271. package/dist/core/system-prompt.js.map +1 -1
  272. package/dist/core/telemetry.d.ts.map +1 -1
  273. package/dist/core/telemetry.js.map +1 -1
  274. package/dist/core/timings.d.ts.map +1 -1
  275. package/dist/core/timings.js.map +1 -1
  276. package/dist/core/tools/bash.d.ts +12 -0
  277. package/dist/core/tools/bash.d.ts.map +1 -1
  278. package/dist/core/tools/bash.js +33 -2
  279. package/dist/core/tools/bash.js.map +1 -1
  280. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  281. package/dist/core/tools/edit-diff.js.map +1 -1
  282. package/dist/core/tools/edit.d.ts.map +1 -1
  283. package/dist/core/tools/edit.js.map +1 -1
  284. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  285. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  286. package/dist/core/tools/find.d.ts.map +1 -1
  287. package/dist/core/tools/find.js.map +1 -1
  288. package/dist/core/tools/grep.d.ts.map +1 -1
  289. package/dist/core/tools/grep.js.map +1 -1
  290. package/dist/core/tools/index.d.ts.map +1 -1
  291. package/dist/core/tools/index.js.map +1 -1
  292. package/dist/core/tools/ls.d.ts.map +1 -1
  293. package/dist/core/tools/ls.js.map +1 -1
  294. package/dist/core/tools/output-accumulator.d.ts +11 -0
  295. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  296. package/dist/core/tools/output-accumulator.js +36 -0
  297. package/dist/core/tools/output-accumulator.js.map +1 -1
  298. package/dist/core/tools/path-utils.d.ts.map +1 -1
  299. package/dist/core/tools/path-utils.js.map +1 -1
  300. package/dist/core/tools/powershell.d.ts.map +1 -1
  301. package/dist/core/tools/powershell.js.map +1 -1
  302. package/dist/core/tools/read.d.ts.map +1 -1
  303. package/dist/core/tools/read.js.map +1 -1
  304. package/dist/core/tools/render-utils.d.ts +6 -0
  305. package/dist/core/tools/render-utils.d.ts.map +1 -1
  306. package/dist/core/tools/render-utils.js +26 -0
  307. package/dist/core/tools/render-utils.js.map +1 -1
  308. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  309. package/dist/core/tools/renderers/bash.js +11 -32
  310. package/dist/core/tools/renderers/bash.js.map +1 -1
  311. package/dist/core/tools/renderers/edit.d.ts.map +1 -1
  312. package/dist/core/tools/renderers/edit.js.map +1 -1
  313. package/dist/core/tools/renderers/find.d.ts.map +1 -1
  314. package/dist/core/tools/renderers/find.js.map +1 -1
  315. package/dist/core/tools/renderers/grep.d.ts.map +1 -1
  316. package/dist/core/tools/renderers/grep.js.map +1 -1
  317. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  318. package/dist/core/tools/renderers/index.js.map +1 -1
  319. package/dist/core/tools/renderers/ls.d.ts.map +1 -1
  320. package/dist/core/tools/renderers/ls.js.map +1 -1
  321. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  322. package/dist/core/tools/renderers/read.js +3 -2
  323. package/dist/core/tools/renderers/read.js.map +1 -1
  324. package/dist/core/tools/renderers/write.d.ts.map +1 -1
  325. package/dist/core/tools/renderers/write.js.map +1 -1
  326. package/dist/core/tools/tool-definition-wrapper.d.ts +5 -3
  327. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  328. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  329. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  330. package/dist/core/tools/truncate.d.ts +14 -0
  331. package/dist/core/tools/truncate.d.ts.map +1 -1
  332. package/dist/core/tools/truncate.js +29 -0
  333. package/dist/core/tools/truncate.js.map +1 -1
  334. package/dist/core/tools/write.d.ts.map +1 -1
  335. package/dist/core/tools/write.js.map +1 -1
  336. package/dist/core/trust-manager.d.ts.map +1 -1
  337. package/dist/core/trust-manager.js +1 -0
  338. package/dist/core/trust-manager.js.map +1 -1
  339. package/dist/core/usage-totals.d.ts +2 -0
  340. package/dist/core/usage-totals.d.ts.map +1 -1
  341. package/dist/core/usage-totals.js +23 -0
  342. package/dist/core/usage-totals.js.map +1 -1
  343. package/dist/core/virtual-models.d.ts +117 -0
  344. package/dist/core/virtual-models.d.ts.map +1 -0
  345. package/dist/core/virtual-models.js +124 -0
  346. package/dist/core/virtual-models.js.map +1 -0
  347. package/dist/extensions/codemode/execute.d.ts +16 -0
  348. package/dist/extensions/codemode/execute.d.ts.map +1 -0
  349. package/dist/extensions/codemode/execute.js +536 -0
  350. package/dist/extensions/codemode/execute.js.map +1 -0
  351. package/dist/extensions/codemode/execute.lazy.d.ts +3 -0
  352. package/dist/extensions/codemode/execute.lazy.d.ts.map +1 -0
  353. package/dist/extensions/codemode/execute.lazy.js +3 -0
  354. package/dist/extensions/codemode/execute.lazy.js.map +1 -0
  355. package/dist/extensions/codemode/index.d.ts +21 -0
  356. package/dist/extensions/codemode/index.d.ts.map +1 -0
  357. package/dist/extensions/codemode/index.js +31 -0
  358. package/dist/extensions/codemode/index.js.map +1 -0
  359. package/dist/extensions/codemode/renderer.d.ts +12 -0
  360. package/dist/extensions/codemode/renderer.d.ts.map +1 -0
  361. package/dist/extensions/codemode/renderer.js +137 -0
  362. package/dist/extensions/codemode/renderer.js.map +1 -0
  363. package/dist/extensions/codemode/tool.d.ts +123 -0
  364. package/dist/extensions/codemode/tool.d.ts.map +1 -0
  365. package/dist/extensions/codemode/tool.js +268 -0
  366. package/dist/extensions/codemode/tool.js.map +1 -0
  367. package/dist/extensions/codemode/worker.d.ts +7 -0
  368. package/dist/extensions/codemode/worker.d.ts.map +1 -0
  369. package/dist/extensions/codemode/worker.js +7 -0
  370. package/dist/extensions/codemode/worker.js.map +1 -0
  371. package/dist/extensions/index.d.ts.map +1 -1
  372. package/dist/extensions/index.js +11 -1
  373. package/dist/extensions/index.js.map +1 -1
  374. package/dist/extensions/llama/client.d.ts.map +1 -1
  375. package/dist/extensions/llama/client.js.map +1 -1
  376. package/dist/extensions/llama/huggingface.d.ts.map +1 -1
  377. package/dist/extensions/llama/huggingface.js.map +1 -1
  378. package/dist/extensions/llama/index.d.ts.map +1 -1
  379. package/dist/extensions/llama/index.js.map +1 -1
  380. package/dist/extensions/llama/provider.d.ts +1 -1
  381. package/dist/extensions/llama/provider.d.ts.map +1 -1
  382. package/dist/extensions/llama/provider.js +65 -13
  383. package/dist/extensions/llama/provider.js.map +1 -1
  384. package/dist/extensions/llama/ui.d.ts.map +1 -1
  385. package/dist/extensions/llama/ui.js.map +1 -1
  386. package/dist/extensions/mcp/cli.d.ts +21 -0
  387. package/dist/extensions/mcp/cli.d.ts.map +1 -0
  388. package/dist/extensions/mcp/cli.js +500 -0
  389. package/dist/extensions/mcp/cli.js.map +1 -0
  390. package/dist/extensions/mcp/cli.lazy.d.ts +3 -0
  391. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -0
  392. package/dist/extensions/mcp/cli.lazy.js +3 -0
  393. package/dist/extensions/mcp/cli.lazy.js.map +1 -0
  394. package/dist/extensions/mcp/config.d.ts +72 -0
  395. package/dist/extensions/mcp/config.d.ts.map +1 -0
  396. package/dist/extensions/mcp/config.js +158 -0
  397. package/dist/extensions/mcp/config.js.map +1 -0
  398. package/dist/extensions/mcp/index.d.ts +76 -0
  399. package/dist/extensions/mcp/index.d.ts.map +1 -0
  400. package/dist/extensions/mcp/index.js +1066 -0
  401. package/dist/extensions/mcp/index.js.map +1 -0
  402. package/dist/extensions/mcp/log.d.ts +16 -0
  403. package/dist/extensions/mcp/log.d.ts.map +1 -0
  404. package/dist/extensions/mcp/log.js +66 -0
  405. package/dist/extensions/mcp/log.js.map +1 -0
  406. package/dist/extensions/mcp/oauth.d.ts +97 -0
  407. package/dist/extensions/mcp/oauth.d.ts.map +1 -0
  408. package/dist/extensions/mcp/oauth.js +358 -0
  409. package/dist/extensions/mcp/oauth.js.map +1 -0
  410. package/dist/extensions/mcp/resources.d.ts +43 -0
  411. package/dist/extensions/mcp/resources.d.ts.map +1 -0
  412. package/dist/extensions/mcp/resources.js +262 -0
  413. package/dist/extensions/mcp/resources.js.map +1 -0
  414. package/dist/extensions/mcp/runtime.d.ts +98 -0
  415. package/dist/extensions/mcp/runtime.d.ts.map +1 -0
  416. package/dist/extensions/mcp/runtime.js +395 -0
  417. package/dist/extensions/mcp/runtime.js.map +1 -0
  418. package/dist/extensions/mcp/runtime.lazy.d.ts +3 -0
  419. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -0
  420. package/dist/extensions/mcp/runtime.lazy.js +3 -0
  421. package/dist/extensions/mcp/runtime.lazy.js.map +1 -0
  422. package/dist/extensions/mcp/tools.d.ts +84 -0
  423. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  424. package/dist/extensions/mcp/tools.js +251 -0
  425. package/dist/extensions/mcp/tools.js.map +1 -0
  426. package/dist/extensions/mcp/ui.d.ts +60 -0
  427. package/dist/extensions/mcp/ui.d.ts.map +1 -0
  428. package/dist/extensions/mcp/ui.js +174 -0
  429. package/dist/extensions/mcp/ui.js.map +1 -0
  430. package/dist/extensions/tool-search/index.d.ts +12 -0
  431. package/dist/extensions/tool-search/index.d.ts.map +1 -0
  432. package/dist/extensions/tool-search/index.js +15 -0
  433. package/dist/extensions/tool-search/index.js.map +1 -0
  434. package/dist/extensions/tool-search/tool.d.ts +73 -0
  435. package/dist/extensions/tool-search/tool.d.ts.map +1 -0
  436. package/dist/extensions/tool-search/tool.js +189 -0
  437. package/dist/extensions/tool-search/tool.js.map +1 -0
  438. package/dist/index.d.ts +10 -3
  439. package/dist/index.d.ts.map +1 -1
  440. package/dist/index.js +5 -0
  441. package/dist/index.js.map +1 -1
  442. package/dist/main.d.ts.map +1 -1
  443. package/dist/main.js +16 -0
  444. package/dist/main.js.map +1 -1
  445. package/dist/migrations.d.ts.map +1 -1
  446. package/dist/migrations.js.map +1 -1
  447. package/dist/modes/index.d.ts.map +1 -1
  448. package/dist/modes/interactive/bug-report.d.ts.map +1 -1
  449. package/dist/modes/interactive/bug-report.js.map +1 -1
  450. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
  451. package/dist/modes/interactive/chat-viewport.js.map +1 -1
  452. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  453. package/dist/modes/interactive/components/armin.js.map +1 -1
  454. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  455. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  456. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  457. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  458. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  459. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  460. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  461. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  462. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  463. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  464. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  465. package/dist/modes/interactive/components/config-selector.js +13 -3
  466. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  467. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  468. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  469. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  470. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  471. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  472. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  473. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  474. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  475. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  476. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  477. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  478. package/dist/modes/interactive/components/diff.js.map +1 -1
  479. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  480. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  481. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  482. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  483. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  484. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  485. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  486. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  487. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  488. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  489. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  490. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  491. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  492. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  493. package/dist/modes/interactive/components/footer.d.ts +7 -0
  494. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  495. package/dist/modes/interactive/components/footer.js +43 -3
  496. package/dist/modes/interactive/components/footer.js.map +1 -1
  497. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  498. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  499. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  500. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  501. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  502. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  503. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  504. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  505. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  506. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  507. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  508. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  509. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  510. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  511. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  512. package/dist/modes/interactive/components/pi-logo-animation.d.ts +68 -0
  513. package/dist/modes/interactive/components/pi-logo-animation.d.ts.map +1 -0
  514. package/dist/modes/interactive/components/pi-logo-animation.js +1086 -0
  515. package/dist/modes/interactive/components/pi-logo-animation.js.map +1 -0
  516. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts +7 -0
  517. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts.map +1 -0
  518. package/dist/modes/interactive/components/pi-logo-animation.lazy.js +12 -0
  519. package/dist/modes/interactive/components/pi-logo-animation.lazy.js.map +1 -0
  520. package/dist/modes/interactive/components/pi-logo.d.ts +19 -0
  521. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -0
  522. package/dist/modes/interactive/components/pi-logo.js +37 -0
  523. package/dist/modes/interactive/components/pi-logo.js.map +1 -0
  524. package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
  525. package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
  526. package/dist/modes/interactive/components/radius-login-selector.js +85 -0
  527. package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
  528. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  529. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  530. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  531. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  532. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  533. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  534. package/dist/modes/interactive/components/settings-selector.d.ts +6 -4
  535. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  536. package/dist/modes/interactive/components/settings-selector.js +33 -11
  537. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  538. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  539. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  540. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  541. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  542. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  543. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  544. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  545. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  546. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  547. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  548. package/dist/modes/interactive/components/themed-text.d.ts +17 -0
  549. package/dist/modes/interactive/components/themed-text.d.ts.map +1 -0
  550. package/dist/modes/interactive/components/themed-text.js +29 -0
  551. package/dist/modes/interactive/components/themed-text.js.map +1 -0
  552. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  553. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  554. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  555. package/dist/modes/interactive/components/tool-execution.js +2 -2
  556. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  557. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  558. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  559. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  560. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  561. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  562. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  563. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  564. package/dist/modes/interactive/components/user-message.js +5 -4
  565. package/dist/modes/interactive/components/user-message.js.map +1 -1
  566. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  567. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  568. package/dist/modes/interactive/components/visual-truncate.js +39 -6
  569. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  570. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  571. package/dist/modes/interactive/external-editor.js.map +1 -1
  572. package/dist/modes/interactive/interactive-mode.d.ts +21 -0
  573. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  574. package/dist/modes/interactive/interactive-mode.js +348 -197
  575. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  576. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -1
  577. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -1
  578. package/dist/modes/interactive/model-search.d.ts.map +1 -1
  579. package/dist/modes/interactive/model-search.js.map +1 -1
  580. package/dist/modes/interactive/session-share.d.ts.map +1 -1
  581. package/dist/modes/interactive/session-share.js.map +1 -1
  582. package/dist/modes/interactive/theme/dark.json +59 -72
  583. package/dist/modes/interactive/theme/light.json +57 -69
  584. package/dist/modes/interactive/theme/system-theme.d.ts +55 -0
  585. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
  586. package/dist/modes/interactive/theme/system-theme.js +546 -0
  587. package/dist/modes/interactive/theme/system-theme.js.map +1 -0
  588. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  589. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  590. package/dist/modes/interactive/theme/theme-controller.js +127 -47
  591. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  592. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  593. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -1
  594. package/dist/modes/interactive/theme/theme-json.js +3 -1
  595. package/dist/modes/interactive/theme/theme-json.js.map +1 -1
  596. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  597. package/dist/modes/interactive/theme/theme.d.ts +66 -39
  598. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  599. package/dist/modes/interactive/theme/theme.js +238 -317
  600. package/dist/modes/interactive/theme/theme.js.map +1 -1
  601. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  602. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  603. package/dist/modes/interactive/tui-renderer.js +1 -0
  604. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  605. package/dist/modes/json-event.d.ts.map +1 -1
  606. package/dist/modes/json-event.js.map +1 -1
  607. package/dist/modes/print-mode.d.ts.map +1 -1
  608. package/dist/modes/print-mode.js.map +1 -1
  609. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  610. package/dist/modes/rpc/jsonl.js.map +1 -1
  611. package/dist/modes/rpc/rpc-client.d.ts +6 -6
  612. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  613. package/dist/modes/rpc/rpc-client.js +12 -8
  614. package/dist/modes/rpc/rpc-client.js.map +1 -1
  615. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  616. package/dist/modes/rpc/rpc-mode.js +7 -9
  617. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  618. package/dist/modes/rpc/rpc-types.d.ts +10 -1
  619. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  620. package/dist/modes/rpc/rpc-types.js.map +1 -1
  621. package/dist/package-manager-cli.d.ts.map +1 -1
  622. package/dist/package-manager-cli.js +6 -2
  623. package/dist/package-manager-cli.js.map +1 -1
  624. package/dist/pi-client-cli.d.ts.map +1 -1
  625. package/dist/pi-client-cli.js.map +1 -1
  626. package/dist/rpc-entry.d.ts.map +1 -1
  627. package/dist/rpc-entry.js.map +1 -1
  628. package/dist/utils/abort.d.ts.map +1 -1
  629. package/dist/utils/abort.js.map +1 -1
  630. package/dist/utils/ansi.d.ts.map +1 -1
  631. package/dist/utils/ansi.js.map +1 -1
  632. package/dist/utils/changelog.d.ts.map +1 -1
  633. package/dist/utils/changelog.js.map +1 -1
  634. package/dist/utils/child-process.d.ts.map +1 -1
  635. package/dist/utils/child-process.js.map +1 -1
  636. package/dist/utils/clipboard-command.d.ts.map +1 -1
  637. package/dist/utils/clipboard-command.js.map +1 -1
  638. package/dist/utils/clipboard-image.d.ts.map +1 -1
  639. package/dist/utils/clipboard-image.js +14 -17
  640. package/dist/utils/clipboard-image.js.map +1 -1
  641. package/dist/utils/clipboard.d.ts +2 -0
  642. package/dist/utils/clipboard.d.ts.map +1 -1
  643. package/dist/utils/clipboard.js +5 -0
  644. package/dist/utils/clipboard.js.map +1 -1
  645. package/dist/utils/deprecation.d.ts.map +1 -1
  646. package/dist/utils/deprecation.js.map +1 -1
  647. package/dist/utils/exif-orientation.d.ts.map +1 -1
  648. package/dist/utils/exif-orientation.js.map +1 -1
  649. package/dist/utils/frontmatter.d.ts.map +1 -1
  650. package/dist/utils/frontmatter.js.map +1 -1
  651. package/dist/utils/fs-watch.d.ts.map +1 -1
  652. package/dist/utils/fs-watch.js.map +1 -1
  653. package/dist/utils/git.d.ts.map +1 -1
  654. package/dist/utils/git.js.map +1 -1
  655. package/dist/utils/html.d.ts.map +1 -1
  656. package/dist/utils/html.js.map +1 -1
  657. package/dist/utils/image-convert.d.ts.map +1 -1
  658. package/dist/utils/image-convert.js.map +1 -1
  659. package/dist/utils/image-process.d.ts.map +1 -1
  660. package/dist/utils/image-process.js.map +1 -1
  661. package/dist/utils/image-resize-core.d.ts.map +1 -1
  662. package/dist/utils/image-resize-core.js.map +1 -1
  663. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  664. package/dist/utils/image-resize-worker.js.map +1 -1
  665. package/dist/utils/image-resize.d.ts.map +1 -1
  666. package/dist/utils/image-resize.js.map +1 -1
  667. package/dist/utils/json.d.ts.map +1 -1
  668. package/dist/utils/json.js.map +1 -1
  669. package/dist/utils/management-http.d.ts.map +1 -1
  670. package/dist/utils/management-http.js.map +1 -1
  671. package/dist/utils/mime.d.ts.map +1 -1
  672. package/dist/utils/mime.js.map +1 -1
  673. package/dist/utils/open-browser.d.ts.map +1 -1
  674. package/dist/utils/open-browser.js.map +1 -1
  675. package/dist/utils/paths.d.ts +3 -3
  676. package/dist/utils/paths.d.ts.map +1 -1
  677. package/dist/utils/paths.js +5 -4
  678. package/dist/utils/paths.js.map +1 -1
  679. package/dist/utils/photon.d.ts.map +1 -1
  680. package/dist/utils/photon.js.map +1 -1
  681. package/dist/utils/pi-user-agent.d.ts.map +1 -1
  682. package/dist/utils/pi-user-agent.js.map +1 -1
  683. package/dist/utils/shell.d.ts +1 -3
  684. package/dist/utils/shell.d.ts.map +1 -1
  685. package/dist/utils/shell.js +3 -30
  686. package/dist/utils/shell.js.map +1 -1
  687. package/dist/utils/sleep.d.ts.map +1 -1
  688. package/dist/utils/sleep.js.map +1 -1
  689. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  690. package/dist/utils/syntax-highlight.js +2 -0
  691. package/dist/utils/syntax-highlight.js.map +1 -1
  692. package/dist/utils/text.d.ts.map +1 -1
  693. package/dist/utils/text.js.map +1 -1
  694. package/dist/utils/tool-result-images.d.ts.map +1 -1
  695. package/dist/utils/tool-result-images.js.map +1 -1
  696. package/dist/utils/tools-manager.d.ts.map +1 -1
  697. package/dist/utils/tools-manager.js.map +1 -1
  698. package/dist/utils/version-check.d.ts.map +1 -1
  699. package/dist/utils/version-check.js.map +1 -1
  700. package/dist/utils/windows-self-update.d.ts.map +1 -1
  701. package/dist/utils/windows-self-update.js.map +1 -1
  702. package/dist/utils/wsl.d.ts.map +1 -1
  703. package/dist/utils/wsl.js.map +1 -1
  704. package/dist/utils/zip.d.ts.map +1 -1
  705. package/dist/utils/zip.js.map +1 -1
  706. package/docs/cli.md +58 -7
  707. package/docs/codemode.md +207 -0
  708. package/docs/configuration.md +2 -0
  709. package/docs/custom-provider.md +43 -4
  710. package/docs/docs.json +13 -1
  711. package/docs/environment-variables.md +2 -2
  712. package/docs/extensions.md +55 -0
  713. package/docs/index.md +1 -1
  714. package/docs/keybindings.md +1 -1
  715. package/docs/llama-cpp.md +13 -0
  716. package/docs/mcp.md +248 -0
  717. package/docs/models.md +57 -1
  718. package/docs/packages.md +4 -2
  719. package/docs/providers.md +19 -6
  720. package/docs/rpc-commands.md +9 -3
  721. package/docs/rpc.md +3 -1
  722. package/docs/sdk.md +8 -3
  723. package/docs/security.md +2 -0
  724. package/docs/session-format.md +5 -1
  725. package/docs/settings.md +24 -5
  726. package/docs/themes.md +33 -7
  727. package/docs/tui.md +18 -0
  728. package/docs/usage.md +1 -1
  729. package/docs/virtual-models.md +114 -0
  730. package/docs/windows.md +2 -0
  731. package/examples/README.md +1 -1
  732. package/examples/extensions/README.md +2 -0
  733. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  734. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  735. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  736. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  737. package/examples/extensions/custom-provider-gitlab-duo/test.ts +5 -5
  738. package/examples/extensions/debug-provider.ts +90 -0
  739. package/examples/extensions/gondolin/package-lock.json +2 -2
  740. package/examples/extensions/gondolin/package.json +1 -1
  741. package/examples/extensions/jev-router.ts +113 -0
  742. package/examples/extensions/minimal-mode.ts +24 -96
  743. package/examples/extensions/sandbox/package-lock.json +2 -2
  744. package/examples/extensions/sandbox/package.json +1 -1
  745. package/examples/extensions/with-deps/package-lock.json +2 -2
  746. package/examples/extensions/with-deps/package.json +1 -1
  747. package/examples/rpc-client.ts +1 -1
  748. package/examples/rpc-extension-ui.ts +1 -1
  749. package/examples/sdk/14-codemode-mcp.ts +61 -0
  750. package/examples/sdk/README.md +2 -1
  751. package/package.json +14 -12
  752. package/dist/bundle/chunks/anthropic-messages-J5WXPPPC.js +0 -6
  753. package/dist/bundle/chunks/azure-openai-responses-QJ7SPP5M.js +0 -2
  754. package/dist/bundle/chunks/chunk-6R7UI4IY.js +0 -2
  755. package/dist/bundle/chunks/chunk-BZKWNWMI.js +0 -2
  756. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
  757. package/dist/bundle/chunks/chunk-RCZIEVGO.js +0 -11
  758. package/dist/bundle/chunks/chunk-S7SZN6Z3.js +0 -2
  759. package/dist/bundle/chunks/chunk-X2F52Z34.js +0 -1685
  760. package/dist/bundle/chunks/chunk-XNGRGP62.js +0 -2
  761. package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +0 -2
  762. package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +0 -2
  763. package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +0 -5
  764. package/dist/bundle/chunks/openai-responses-AH7QTG23.js +0 -2
  765. package/dist/bundle/chunks/virtual-modules-WWGGM27U.js +0 -2
@@ -14,6 +14,7 @@
14
14
  */
15
15
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
16
16
  import { basename, dirname } from "node:path";
17
+ import { runToolCall, } from "@earendil-works/pi-agent-core";
17
18
  import { contentText, getCurrentSystemMessage, normalizeContext, retryDelayMs } from "@earendil-works/pi-ai";
18
19
  import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, isRecoverableLength, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai/compat";
19
20
  import { getThemeByName, theme } from "../modes/interactive/theme/theme.js";
@@ -33,16 +34,19 @@ 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 { cancelPiServerOperations, compactPiServer, hashStaticContext, } from "./pi-server-client.js";
37
39
  import { hashPiServerProviderMessages } from "./pi-server-protocol.js";
38
40
  import { expandPromptTemplate } from "./prompt-templates.js";
39
41
  import { CURRENT_SESSION_VERSION, getLatestCompactionEntry, SessionManager, } from "./session-manager.js";
40
- import { createSyntheticSourceInfo } from "./source-info.js";
42
+ import { DEFAULT_TOOL_NAMES } from "./settings-manager.js";
43
+ import { BUILTIN_PATH_PREFIX, createSyntheticSourceInfo, isSyntheticPath } from "./source-info.js";
41
44
  import { buildSystemPrompt, buildSystemPromptSections, diffSystemPromptSections, normalizeBuildSystemPromptOptions, } from "./system-prompt.js";
42
45
  import { createLocalBashOperations } from "./tools/bash.js";
43
46
  import { createAllToolDefinitions } from "./tools/index.js";
44
47
  import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
45
- import { addUsageToTotals, createUsageTotals } from "./usage-totals.js";
48
+ import { addUsageToTotals, combineUsage, createUsageTotals } from "./usage-totals.js";
49
+ import { findLatestResponse, getBranchSelection, getVirtualModelState, isVirtualModel, VIRTUAL_MODEL_STATE_ENTRY, } from "./virtual-models.js";
46
50
  /**
47
51
  * Parse a skill block from message text.
48
52
  * Returns null if the text doesn't contain a skill block.
@@ -203,6 +207,11 @@ export class AgentSession {
203
207
  // Retry state
204
208
  _retryAbortController = undefined;
205
209
  _retryAttempt = 0;
210
+ /**
211
+ * Failed response that the next request repeats, set by auto-retry and overflow recovery. The
212
+ * retry is routed with it as `failed`, since the context no longer contains it.
213
+ */
214
+ _failedResponse;
206
215
  // Post-turn session naming is a provider request too, so cancellation must reach it.
207
216
  _sessionNameAbortController = undefined;
208
217
  // Bash execution state
@@ -227,6 +236,13 @@ export class AgentSession {
227
236
  _cwd;
228
237
  _extensionRunnerRef;
229
238
  _initialActiveToolNames;
239
+ /**
240
+ * Tools of the restored or reloaded loadout that are not registered yet, such as tools of MCP
241
+ * servers that are still connecting. They are activated when they are registered, and dropped when
242
+ * `setActiveToolsByName()` deactivates a tool or the next agent run starts.
243
+ */
244
+ _pendingToolNames = new Set();
245
+ _usesDefaultTools;
230
246
  _allowedToolNames;
231
247
  _excludedToolNames;
232
248
  _baseToolsOverride;
@@ -244,6 +260,10 @@ export class AgentSession {
244
260
  _cacheWarmer;
245
261
  // Tool registry for extension getTools/setTools
246
262
  _toolRegistry = new Map();
263
+ /** Created on the first `ctx.executeTool()` call. */
264
+ _nestedToolCalls;
265
+ /** Declared tools whose declarations requests leave out, from `prepareLoadout` hooks. */
266
+ _hiddenDeclarations = new Set();
247
267
  _toolDefinitions = new Map();
248
268
  _toolPromptSnippets = new Map();
249
269
  _toolPromptGuidelines = new Map();
@@ -265,6 +285,7 @@ export class AgentSession {
265
285
  }
266
286
  this._extensionRunnerRef = config.extensionRunnerRef;
267
287
  this._initialActiveToolNames = config.initialActiveToolNames;
288
+ this._usesDefaultTools = config.usesDefaultTools ?? false;
268
289
  this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
269
290
  this._excludedToolNames = config.excludedToolNames ? new Set(config.excludedToolNames) : undefined;
270
291
  this._baseToolsOverride = config.baseToolsOverride;
@@ -280,6 +301,7 @@ export class AgentSession {
280
301
  this._installAgentNextTurnRefresh();
281
302
  this._installAgentRequestProjection();
282
303
  this._installAgentBoundaryHooks();
304
+ this._installHiddenDeclarationsProjection();
283
305
  this._installAgentForcedPromptProjection();
284
306
  this._buildRuntime({
285
307
  activeToolNames: this._initialActiveToolNames,
@@ -330,28 +352,71 @@ export class AgentSession {
330
352
  }
331
353
  throw new Error(formatNoApiKeyFoundMessage(model.provider));
332
354
  }
333
- async _getSummarizationRequestAuth(model, signal) {
355
+ async _getSummarizationRequestAuth(selectedModel, signal) {
356
+ // Route a virtual model first: summaries size their input and output from the model they get.
357
+ const { model, thinkingLevel } = isVirtualModel(selectedModel)
358
+ ? await this._modelRuntime.resolveModel(selectedModel, convertToLlm(this.messages), {
359
+ reason: "direct",
360
+ thinkingLevel: this.thinkingLevel,
361
+ signal,
362
+ })
363
+ : { model: selectedModel, thinkingLevel: this.thinkingLevel };
334
364
  if (this.agent.streamFunction === streamSimple) {
335
- return this._getRequiredRequestAuth(model, signal);
365
+ return { ...(await this._getRequiredRequestAuth(model, signal)), thinkingLevel };
336
366
  }
337
367
  try {
338
368
  const result = await this._modelRuntime.getAuth(model, { signal });
339
369
  if (!result)
340
- return { model };
370
+ return { model, thinkingLevel };
341
371
  const requestModel = result.auth.baseUrl ? { ...model, baseUrl: result.auth.baseUrl } : model;
342
372
  return {
343
373
  model: requestModel,
344
374
  apiKey: result.auth.apiKey,
345
375
  headers: withoutDeletedHeaders(result.auth.headers),
346
376
  env: result.env,
377
+ thinkingLevel,
347
378
  };
348
379
  }
349
380
  catch (error) {
350
381
  if (signal?.aborted)
351
382
  throw error;
352
- return { model };
383
+ return { model, thinkingLevel };
353
384
  }
354
385
  }
386
+ /**
387
+ * The model whose limits apply to `message`, or undefined when the message came from another
388
+ * model. Under a virtual selection, that is the physical model that produced it.
389
+ */
390
+ _modelForMessage(message) {
391
+ const model = this.model;
392
+ if (model && isVirtualModel(model))
393
+ return this._modelRuntime.getPhysicalModel(message.provider, message.model);
394
+ return model?.provider === message.provider && model.id === message.model ? model : undefined;
395
+ }
396
+ /**
397
+ * Record the selection on the current branch when the branch implies another one, so a resume
398
+ * restores it. Tree navigation can leave the latest `model_change` on another branch; responses
399
+ * cannot record a virtual selection because they name physical models. Responses do record a
400
+ * physical selection unless the branch holds a virtual one; checking a physical selection against
401
+ * responses would record it on every prompt while `prepareRequest` redirects to another model.
402
+ */
403
+ _recordSelection() {
404
+ const model = this.model;
405
+ if (!model)
406
+ return;
407
+ const getModel = (provider, modelId) => this._modelRuntime.getModel(provider, modelId);
408
+ const recorded = getBranchSelection(this.sessionManager.getBranch(), getModel);
409
+ if (!recorded || (recorded.provider === model.provider && recorded.modelId === model.id))
410
+ return;
411
+ const recordedModel = getModel(recorded.provider, recorded.modelId);
412
+ if (!isVirtualModel(model) && !(recordedModel && isVirtualModel(recordedModel)))
413
+ return;
414
+ this.sessionManager.appendModelChange(model.provider, model.id);
415
+ }
416
+ /** The model whose limits apply to the conversation. */
417
+ _limitsModel() {
418
+ return this.routedModel?.model ?? this.model;
419
+ }
355
420
  /**
356
421
  * Install tool hooks once on the Agent instance.
357
422
  *
@@ -361,67 +426,114 @@ export class AgentSession {
361
426
  * happens here instead of in wrappers.
362
427
  */
363
428
  _installAgentToolHooks() {
364
- this.agent.beforeToolCall = async ({ toolCall, args }) => {
365
- const runner = this._extensionRunner;
366
- if (!runner.hasHandlers("tool_call")) {
367
- return undefined;
368
- }
369
- try {
370
- return await runner.emitToolCall({
371
- type: "tool_call",
372
- toolName: toolCall.name,
373
- toolCallId: toolCall.id,
374
- input: args,
375
- });
376
- }
377
- catch (err) {
378
- if (err instanceof Error) {
379
- throw err;
380
- }
381
- throw new Error(`Extension failed, blocking execution: ${String(err)}`);
382
- }
383
- };
384
- this.agent.afterToolCall = async ({ toolCall, args, result, isError }) => {
385
- const runner = this._extensionRunner;
386
- const hookResult = runner.hasHandlers("tool_result")
387
- ? await runner.emitToolResult({
388
- type: "tool_result",
389
- toolName: toolCall.name,
390
- toolCallId: toolCall.id,
391
- input: args,
392
- content: result.content,
393
- details: result.details,
394
- isError,
395
- usage: result.usage,
396
- })
397
- : undefined;
398
- const content = hookResult?.content ?? result.content ?? [];
399
- // Runs after the extension hook so images injected or replaced by extensions are normalized too.
400
- const resizeOptions = this.model?.inputLimits?.images?.resize;
401
- const normalizedContent = await normalizeToolResultImages(content, {
402
- autoResizeImages: this.settingsManager.getImageAutoResize(),
403
- ...(resizeOptions ? { resizeOptions } : {}),
429
+ this.agent.beforeToolCall = (context) => this._beforeToolCall(context);
430
+ this.agent.afterToolCall = (context) => this._afterToolCall(context);
431
+ }
432
+ /** `tool_call` handlers. `parentToolCallId` is set for calls another tool made. */
433
+ async _beforeToolCall({ toolCall, args }, parentToolCallId) {
434
+ const runner = this._extensionRunner;
435
+ if (!runner.hasHandlers("tool_call")) {
436
+ return undefined;
437
+ }
438
+ try {
439
+ return await runner.emitToolCall({
440
+ type: "tool_call",
441
+ toolName: toolCall.name,
442
+ toolCallId: toolCall.id,
443
+ ...(parentToolCallId ? { parentToolCallId } : {}),
444
+ input: args,
404
445
  });
405
- if (!hookResult && normalizedContent === content) {
406
- return undefined;
446
+ }
447
+ catch (err) {
448
+ if (err instanceof Error) {
449
+ throw err;
407
450
  }
408
- return {
409
- content: normalizedContent,
410
- details: hookResult?.details,
411
- isError: hookResult?.isError ?? isError,
412
- usage: hookResult?.usage,
413
- };
451
+ throw new Error(`Extension failed, blocking execution: ${String(err)}`);
452
+ }
453
+ }
454
+ /** `tool_result` handlers and image normalization. `parentToolCallId` is set for calls another tool made. */
455
+ async _afterToolCall({ toolCall, args, result, isError }, parentToolCallId) {
456
+ const runner = this._extensionRunner;
457
+ const hookResult = runner.hasHandlers("tool_result")
458
+ ? await runner.emitToolResult({
459
+ type: "tool_result",
460
+ toolName: toolCall.name,
461
+ toolCallId: toolCall.id,
462
+ ...(parentToolCallId ? { parentToolCallId } : {}),
463
+ input: args,
464
+ content: result.content,
465
+ details: result.details,
466
+ ...(result.structuredContent === undefined ? {} : { structuredContent: result.structuredContent }),
467
+ isError,
468
+ usage: result.usage,
469
+ })
470
+ : undefined;
471
+ const content = hookResult?.content ?? result.content ?? [];
472
+ // Runs after the extension hook so images injected or replaced by extensions are normalized too.
473
+ const resizeOptions = this._limitsModel()?.inputLimits?.images?.resize;
474
+ const normalizedContent = await normalizeToolResultImages(content, {
475
+ autoResizeImages: this.settingsManager.getImageAutoResize(),
476
+ ...(resizeOptions ? { resizeOptions } : {}),
477
+ });
478
+ if (!hookResult && normalizedContent === content) {
479
+ return undefined;
480
+ }
481
+ // The hook result already dropped structured content that replaced content no longer matches.
482
+ return {
483
+ content: normalizedContent,
484
+ details: hookResult?.details,
485
+ structuredContent: hookResult ? hookResult.structuredContent : result.structuredContent,
486
+ isError: hookResult?.isError ?? isError,
487
+ usage: hookResult?.usage,
414
488
  };
415
489
  }
490
+ /**
491
+ * Run a call that the tool call `parentToolCallId` made through `ctx.executeTool()`. It goes
492
+ * through the agent's tool pipeline with the session's hooks, against the callable tools.
493
+ */
494
+ async _executeNestedToolCall(parentToolCallId, name, args, options) {
495
+ this._nestedToolCalls ??= new NestedToolCallRunner({
496
+ getTools: () => this._getCallableTools(),
497
+ isSequential: () => this.agent.toolExecution === "sequential",
498
+ runToolCall: (toolCall, parentId, signal, onUpdate) => {
499
+ const assistantMessage = this._findLastAssistantMessage();
500
+ if (!assistantMessage) {
501
+ return Promise.resolve({
502
+ toolCall,
503
+ result: { content: [{ type: "text", text: "No assistant message issued this call" }], details: {} },
504
+ isError: true,
505
+ });
506
+ }
507
+ return runToolCall(toolCall, {
508
+ tools: this._getCallableTools(),
509
+ assistantMessage,
510
+ context: { messages: this.agent.state.messages, tools: this.agent.state.tools },
511
+ beforeToolCall: (context) => this._beforeToolCall(context, parentId),
512
+ afterToolCall: (context) => this._afterToolCall(context, parentId),
513
+ signal,
514
+ onUpdate,
515
+ });
516
+ },
517
+ emit: async (event) => {
518
+ await this._extensionRunner.emit(event);
519
+ this._emit(event);
520
+ },
521
+ });
522
+ return this._nestedToolCalls.execute(parentToolCallId, name, args, options);
523
+ }
524
+ /** Whether `projection`, the current session projection, exceeds the compaction threshold of `model`. */
525
+ _exceedsCompactionThreshold(model, projection) {
526
+ if (model.contextWindow <= 0)
527
+ return false;
528
+ return shouldCompact(estimateProjectedContextTokens(projection, this.sessionManager.getBranch()).tokens, model.contextWindow, this.settingsManager.getCompactionSettings(this.model));
529
+ }
416
530
  async _compactBeforeNextAssistantResponse(context, signal) {
417
531
  if (signal?.aborted)
418
532
  return context;
419
- const model = this.model;
420
- const settings = this.settingsManager.getCompactionSettings(model);
421
533
  const projection = this.sessionManager.buildSessionProjection();
422
- if (!model ||
423
- model.contextWindow <= 0 ||
424
- !shouldCompact(estimateProjectedContextTokens(projection, this.sessionManager.getBranch()).tokens, model.contextWindow, settings)) {
534
+ // A virtual selection is checked in prepareRequest, against the model the request is routed to.
535
+ const model = this.model;
536
+ if (!model || isVirtualModel(model) || !this._exceedsCompactionThreshold(model, projection)) {
425
537
  return { ...context, messages: projection.messages };
426
538
  }
427
539
  await this._runAutoCompaction("threshold", false, undefined, undefined, signal);
@@ -432,24 +544,55 @@ export class AgentSession {
432
544
  if (previousPrepareRequest)
433
545
  this._cachePrefixUnavailableReason ??= "custom_prepare_request";
434
546
  this.agent.prepareRequest = async (request, signal) => {
435
- const canonicalContext = {
436
- ...request.context,
437
- messages: this.sessionManager.buildSessionProjection().messages,
438
- // Messages declare the provider-visible loadout; context.tools keeps executable implementations.
439
- tools: this.agent.state.tools.slice(),
440
- };
441
- const previous = await previousPrepareRequest?.({
442
- ...request,
443
- context: canonicalContext,
444
- model: this.agent.state.model,
445
- thinkingLevel: this.agent.state.thinkingLevel,
446
- }, signal);
447
- return {
448
- ...previous,
449
- context: previous?.context ?? canonicalContext,
450
- model: previous?.model ?? this.agent.state.model,
451
- thinkingLevel: previous?.thinkingLevel ?? this.agent.state.thinkingLevel,
547
+ const failed = this._failedResponse;
548
+ this._failedResponse = undefined;
549
+ const prepare = async () => {
550
+ const projection = this.sessionManager.buildSessionProjection();
551
+ const canonicalContext = {
552
+ ...request.context,
553
+ messages: projection.messages,
554
+ // Messages declare the provider-visible loadout; context.tools keeps executable implementations.
555
+ tools: this.agent.state.tools.slice(),
556
+ };
557
+ const previous = await previousPrepareRequest?.({
558
+ ...request,
559
+ context: canonicalContext,
560
+ model: this.agent.state.model,
561
+ thinkingLevel: this.agent.state.thinkingLevel,
562
+ }, signal);
563
+ return { previous, context: previous?.context ?? canonicalContext, projection };
452
564
  };
565
+ let { previous, context, projection } = await prepare();
566
+ const model = previous?.model ?? this.agent.state.model;
567
+ const thinkingLevel = previous?.thinkingLevel ?? this.agent.state.thinkingLevel;
568
+ if (!isVirtualModel(model))
569
+ return { ...previous, context, model, thinkingLevel };
570
+ // The selection stays in agent state; only this request uses the routed model. A routing
571
+ // failure rejects, which ends the run with an error response. Only messages the user wrote
572
+ // start a turn; extension messages can follow them, e.g. from before_agent_start.
573
+ const lastResponse = context.messages.findLastIndex((message) => message.role === "assistant");
574
+ const userTurn = context.messages.slice(lastResponse + 1).some((message) => message.role === "user");
575
+ const state = getVirtualModelState(this.sessionManager.getBranch(), model.provider, model.id);
576
+ const route = await this._modelRuntime.resolveModel(model, convertToLlm(context.messages), {
577
+ reason: failed ? "retry" : userTurn ? "user" : "continuation",
578
+ thinkingLevel,
579
+ signal,
580
+ failed,
581
+ state,
582
+ });
583
+ if (route.state !== undefined && route.state !== state) {
584
+ const data = { provider: model.provider, modelId: model.id, state: route.state };
585
+ const entry = this.sessionManager.getEntry(this.sessionManager.appendCustomEntry(VIRTUAL_MODEL_STATE_ENTRY, data));
586
+ if (entry)
587
+ this._emit({ type: "entry_appended", entry });
588
+ }
589
+ // The route stands: the router already decided this request. The state entry does not change
590
+ // the projection.
591
+ if (this._exceedsCompactionThreshold(route.model, projection)) {
592
+ await this._runAutoCompaction("threshold", false, undefined, undefined, signal);
593
+ ({ previous, context } = await prepare());
594
+ }
595
+ return { ...previous, context, model: route.model, thinkingLevel: route.thinkingLevel };
453
596
  };
454
597
  }
455
598
  async _dispatchTurnEndBoundary(message, toolResults) {
@@ -505,19 +648,17 @@ export class AgentSession {
505
648
  ? async (_turn, signal) => await this.agent.prepareNextTurn?.(signal)
506
649
  : undefined);
507
650
  this.agent.prepareNextTurnWithContext = async (turn, signal) => {
508
- const projectedTurn = {
509
- ...turn,
510
- context: {
511
- ...turn.context,
512
- messages: this.sessionManager.buildSessionProjection().messages,
513
- },
514
- };
515
- const compactedContext = await this._compactBeforeNextProviderRequest(projectedTurn, signal);
516
- const context = signal?.aborted
517
- ? projectedTurn.context
518
- : compactedContext === undefined
519
- ? await this._compactBeforeNextAssistantResponse(projectedTurn.context, signal)
520
- : (compactedContext ?? projectedTurn.context);
651
+ const compactedContext = await this._compactBeforeNextProviderRequest(turn, signal);
652
+ let context;
653
+ if (!signal?.aborted && compactedContext) {
654
+ context = compactedContext;
655
+ }
656
+ else if (!signal?.aborted && compactedContext === undefined) {
657
+ context = await this._compactBeforeNextAssistantResponse(turn.context, signal);
658
+ }
659
+ else {
660
+ context = { ...turn.context, messages: this.sessionManager.buildSessionProjection().messages };
661
+ }
521
662
  const nextTurn = { ...turn, context };
522
663
  const previousSnapshot = await previousPrepareNextTurnWithContext?.(nextTurn, signal);
523
664
  const nextContext = previousSnapshot?.context ?? context;
@@ -687,6 +828,21 @@ export class AgentSession {
687
828
  }
688
829
  /** Internal handler for agent events - shared by subscribe and reconnect */
689
830
  _handleAgentEvent = async (event, _signal) => {
831
+ // Record the calls a tool made through ctx.executeTool() and their usage on its result message.
832
+ if (this._nestedToolCalls) {
833
+ if (event.type === "message_start" && event.message.role === "toolResult") {
834
+ const message = event.message;
835
+ const summary = this._nestedToolCalls.takeRecord(message.toolCallId);
836
+ if (summary?.calls)
837
+ message.nestedCalls = summary.calls;
838
+ if (summary?.usage) {
839
+ message.usage = message.usage ? combineUsage(message.usage, summary.usage) : summary.usage;
840
+ }
841
+ }
842
+ else if (event.type === "agent_end") {
843
+ this._nestedToolCalls.clear();
844
+ }
845
+ }
690
846
  // When a user message starts, check if it's from either queue and remove it BEFORE emitting
691
847
  // This ensures the UI sees the updated queue state
692
848
  if (event.type === "message_start" && event.message.role === "user") {
@@ -1084,6 +1240,14 @@ export class AgentSession {
1084
1240
  get thinkingLevel() {
1085
1241
  return this.agent.state.thinkingLevel;
1086
1242
  }
1243
+ /** Under a virtual selection, the physical model and thinking level of the latest successful response. */
1244
+ get routedModel() {
1245
+ if (!this.model || !isVirtualModel(this.model))
1246
+ return undefined;
1247
+ const latest = findLatestResponse(this.agent.state.messages);
1248
+ const model = latest && this._modelRuntime.getPhysicalModel(latest.provider, latest.model);
1249
+ return model && { model, thinkingLevel: latest?.thinkingLevel };
1250
+ }
1087
1251
  /** Whether the session is currently processing an agent run or post-run continuation. */
1088
1252
  get isStreaming() {
1089
1253
  return this._isAgentRunActive;
@@ -1109,12 +1273,16 @@ export class AgentSession {
1109
1273
  return this._retryAttempt;
1110
1274
  }
1111
1275
  /**
1112
- * Get the names of currently active tools.
1113
- * Returns the names of tools currently set on the agent.
1276
+ * Get the names of currently active tools, which are the tools declared to the model.
1277
+ * Tools with `codemode` or `deferred` exposure are callable from other tools without being active.
1114
1278
  */
1115
1279
  getActiveToolNames() {
1116
1280
  return this.agent.state.tools.map((t) => t.name);
1117
1281
  }
1282
+ /** Get the names of the tools that tools can call through `ctx.executeTool()`. */
1283
+ getCallableToolNames() {
1284
+ return this._getCallableTools().map((t) => t.name);
1285
+ }
1118
1286
  /**
1119
1287
  * Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
1120
1288
  */
@@ -1124,6 +1292,9 @@ export class AgentSession {
1124
1292
  description: definition.description,
1125
1293
  parameters: definition.parameters,
1126
1294
  promptGuidelines: definition.promptGuidelines,
1295
+ exposure: this._getToolExposure(definition.name),
1296
+ ...(definition.namespace ? { namespace: definition.namespace } : {}),
1297
+ ...(definition.annotations ? { annotations: { ...definition.annotations } } : {}),
1127
1298
  sourceInfo,
1128
1299
  }));
1129
1300
  }
@@ -1132,22 +1303,93 @@ export class AgentSession {
1132
1303
  }
1133
1304
  /**
1134
1305
  * Set active tools by name.
1135
- * Only tools in the registry can be enabled. Unknown tool names are ignored.
1306
+ * Only tools in the registry can be enabled. Unknown and hidden tool names are ignored.
1136
1307
  * Also rebuilds the system prompt to reflect the new tool set.
1137
1308
  * Changes take effect on the next agent turn.
1138
1309
  */
1139
1310
  setActiveToolsByName(toolNames) {
1140
- const tools = [];
1141
- const validToolNames = [];
1142
- for (const name of toolNames) {
1311
+ const previous = this.getActiveToolNames();
1312
+ this._setActiveTools(toolNames);
1313
+ // A loadout that deactivates a tool replaces the restored one, whose pending tools are dropped.
1314
+ // One that only adds tools, like activating tool_search, keeps them.
1315
+ const active = new Set(this.getActiveToolNames());
1316
+ if (previous.some((name) => !active.has(name)))
1317
+ this._pendingToolNames.clear();
1318
+ }
1319
+ _setActiveTools(toolNames) {
1320
+ const tools = this._applyToolLoadout(toolNames);
1321
+ for (const tool of tools)
1322
+ this._pendingToolNames.delete(tool.name);
1323
+ this._rebuildSystemPrompt(tools.map((tool) => tool.name));
1324
+ }
1325
+ _isAllowedTool(name) {
1326
+ return (!this._allowedToolNames || this._allowedToolNames.has(name)) && !this._excludedToolNames?.has(name);
1327
+ }
1328
+ _getToolExposure(name) {
1329
+ return this._toolDefinitions.get(name)?.definition.exposure ?? "direct";
1330
+ }
1331
+ /**
1332
+ * Tools callable through `ctx.executeTool()`: the active `direct` tools and every registered
1333
+ * `codemode` or `deferred` tool.
1334
+ */
1335
+ _getCallableTools(active = new Set(this.getActiveToolNames())) {
1336
+ return [...this._toolRegistry.values()].filter((tool) => {
1337
+ const exposure = this._getToolExposure(tool.name);
1338
+ return exposure === "codemode" || exposure === "deferred" || (exposure === "direct" && active.has(tool.name));
1339
+ });
1340
+ }
1341
+ /**
1342
+ * Set the agent's tools for the given active tool names and return them. The active tools are
1343
+ * the registered, non-hidden ones; they are declared to the model. Active tools with a
1344
+ * `prepareLoadout` hook can change the declared descriptions and hide declarations from
1345
+ * requests (see {@link _installHiddenDeclarationsProjection}).
1346
+ */
1347
+ _applyToolLoadout(toolNames) {
1348
+ const tools = [...new Set(toolNames)].flatMap((name) => {
1143
1349
  const tool = this._toolRegistry.get(name);
1144
- if (tool) {
1145
- tools.push(tool);
1146
- validToolNames.push(name);
1350
+ return tool && this._getToolExposure(name) !== "hidden" ? [tool] : [];
1351
+ });
1352
+ const hooks = tools.flatMap((tool) => {
1353
+ const entry = this._toolDefinitions.get(tool.name);
1354
+ return entry?.definition.prepareLoadout ? [entry] : [];
1355
+ });
1356
+ const hidden = new Set();
1357
+ let declared = tools;
1358
+ if (hooks.length > 0) {
1359
+ const loadout = {
1360
+ declared: tools,
1361
+ callable: this._getCallableTools(new Set(tools.map((tool) => tool.name))),
1362
+ registered: [...this._toolRegistry.values()],
1363
+ getExposure: (name) => this._getToolExposure(name),
1364
+ getNamespace: (name) => this._toolDefinitions.get(name)?.definition.namespace,
1365
+ };
1366
+ const descriptions = new Map();
1367
+ for (const { definition, sourceInfo } of hooks) {
1368
+ try {
1369
+ const changes = definition.prepareLoadout?.(loadout);
1370
+ for (const [name, description] of Object.entries(changes?.descriptions ?? {})) {
1371
+ descriptions.set(name, description);
1372
+ }
1373
+ for (const name of changes?.hiddenDeclarations ?? [])
1374
+ hidden.add(name);
1375
+ }
1376
+ catch (error) {
1377
+ this._extensionRunner.emitError({
1378
+ extensionPath: sourceInfo.path,
1379
+ event: "prepare_loadout",
1380
+ error: error instanceof Error ? error.message : String(error),
1381
+ stack: error instanceof Error ? error.stack : undefined,
1382
+ });
1383
+ }
1147
1384
  }
1385
+ declared = tools.map((tool) => {
1386
+ const description = descriptions.get(tool.name);
1387
+ return description === undefined ? tool : { ...tool, description };
1388
+ });
1148
1389
  }
1149
- this.agent.state.tools = tools;
1150
- this._rebuildSystemPrompt(validToolNames);
1390
+ this._hiddenDeclarations = hidden;
1391
+ this.agent.state.tools = declared;
1392
+ return declared;
1151
1393
  }
1152
1394
  /** Whether compaction or branch summarization is currently running */
1153
1395
  get isCompacting() {
@@ -1218,7 +1460,8 @@ export class AgentSession {
1218
1460
  const toolSnippets = {};
1219
1461
  for (const name of this._toolRegistry.keys()) {
1220
1462
  const snippet = this._toolPromptSnippets.get(name);
1221
- if (snippet)
1463
+ // Tools without a snippet are not listed. Hidden tools are only callable through another tool.
1464
+ if (snippet && !this._hiddenDeclarations.has(name))
1222
1465
  toolSnippets[name] = snippet;
1223
1466
  }
1224
1467
  const loaderSystemPrompt = this._resourceLoader.getSystemPrompt();
@@ -1248,11 +1491,9 @@ export class AgentSession {
1248
1491
  * {@link _installAgentForcedPromptProjection}.
1249
1492
  */
1250
1493
  _preparePromptAndToolLoadout(options, messages = this.agent.state.messages) {
1251
- options.selectedTools = [...new Set(options.selectedTools)].filter((name) => this._toolRegistry.has(name));
1252
- this.agent.state.tools = options.selectedTools.flatMap((name) => {
1253
- const tool = this._toolRegistry.get(name);
1254
- return tool ? [tool] : [];
1255
- });
1494
+ options.selectedTools = this._applyToolLoadout(options.selectedTools).map((tool) => tool.name);
1495
+ // The tool list must match the declarations the request carries, so hidden tools are not listed.
1496
+ options.toolSnippets = Object.fromEntries(Object.entries(options.toolSnippets).filter(([name]) => !this._hiddenDeclarations.has(name)));
1256
1497
  const sections = diffSystemPromptSections(getCurrentSystemMessage(messages)?.sections ?? {}, buildSystemPromptSections(options));
1257
1498
  return sections ? { role: "system", content: "", sections, timestamp: Date.now() } : undefined;
1258
1499
  }
@@ -1266,6 +1507,32 @@ export class AgentSession {
1266
1507
  * collapse into one head holding the forced text and the current tools. Runs after the
1267
1508
  * `context` extension handlers.
1268
1509
  */
1510
+ /**
1511
+ * Remove the declarations that `prepareLoadout` hooks hide from every request. The whole
1512
+ * transcript is filtered with the current set, so the projected declarations stay consistent
1513
+ * across requests and only change when the loadout does.
1514
+ */
1515
+ _installHiddenDeclarationsProjection() {
1516
+ const previousTransformContext = this.agent.transformContext;
1517
+ this.agent.transformContext = async (messages, signal) => {
1518
+ const transformed = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
1519
+ const hidden = this._hiddenDeclarations;
1520
+ if (hidden.size === 0)
1521
+ return transformed;
1522
+ return transformed.map((message) => {
1523
+ if (message.role !== "system" || (!message.toolsAdded && !message.toolsRemoved))
1524
+ return message;
1525
+ const { toolsAdded, toolsRemoved, ...rest } = message;
1526
+ const added = toolsAdded?.filter((tool) => !hidden.has(tool.name)) ?? [];
1527
+ const removed = toolsRemoved?.filter((tool) => !hidden.has(tool.name)) ?? [];
1528
+ return {
1529
+ ...rest,
1530
+ ...(added.length > 0 ? { toolsAdded: added } : {}),
1531
+ ...(removed.length > 0 ? { toolsRemoved: removed } : {}),
1532
+ };
1533
+ });
1534
+ };
1535
+ }
1269
1536
  _installAgentForcedPromptProjection() {
1270
1537
  const previousTransformContext = this.agent.transformContext;
1271
1538
  if (previousTransformContext)
@@ -1285,25 +1552,31 @@ export class AgentSession {
1285
1552
  return [head, ...transformed.filter((message) => message.role !== "system")];
1286
1553
  };
1287
1554
  }
1288
- /** Restore the active tool loadout declared by the session transcript, if it declares one. */
1555
+ /**
1556
+ * Restore the active tool loadout declared by the session transcript, if it declares one.
1557
+ * Tools reachable only from other tools are never declared, but they do not depend on the active
1558
+ * set, so the transcript's declarations are the whole loadout.
1559
+ */
1289
1560
  _restoreToolsFromTranscript() {
1561
+ this._pendingToolNames.clear();
1290
1562
  const current = getCurrentSystemMessage(this.sessionManager.buildSessionContext().messages);
1291
1563
  if (!current)
1292
1564
  return;
1293
- const toolNames = (current.toolsAdded ?? [])
1294
- .map((tool) => tool.name)
1295
- .filter((name) => this._toolRegistry.has(name));
1296
- this.agent.state.tools = toolNames.flatMap((name) => {
1297
- const registered = this._toolRegistry.get(name);
1298
- return registered ? [registered] : [];
1299
- });
1300
- this._rebuildSystemPrompt(toolNames);
1565
+ const names = (current.toolsAdded ?? []).map((tool) => tool.name);
1566
+ this._pendingToolNames = new Set(names.filter((name) => this._isAllowedTool(name)));
1567
+ this._setActiveTools(names);
1301
1568
  }
1302
1569
  // =========================================================================
1303
1570
  // Prompting
1304
1571
  // =========================================================================
1305
1572
  async _runAgentOperation(start) {
1306
1573
  this._agentRunAbortRequested = false;
1574
+ // Compaction before the prompt may have scheduled a retry; the new prompt replaces it.
1575
+ this._failedResponse = undefined;
1576
+ this._recordSelection();
1577
+ // The run records the loadout in the transcript; restored tools that did not register by now
1578
+ // are dropped, so a tool that never registers does not stay pending.
1579
+ this._pendingToolNames.clear();
1307
1580
  this._isAgentRunActive = true;
1308
1581
  try {
1309
1582
  await start();
@@ -1339,6 +1612,7 @@ export class AgentSession {
1339
1612
  finally {
1340
1613
  if (this._agentRunAbortRequested)
1341
1614
  this._finishCancelledRetry();
1615
+ this._failedResponse = undefined;
1342
1616
  this._runSystemPromptOptions = undefined;
1343
1617
  this._flushPendingBashMessages();
1344
1618
  this._flushPendingCustomMessages();
@@ -1439,6 +1713,7 @@ export class AgentSession {
1439
1713
  if (this._isRetryableError(message) && (await this._prepareRetry(message))) {
1440
1714
  if (this._agentRunAbortRequested)
1441
1715
  this._finishCancelledRetry();
1716
+ this._failedResponse = message;
1442
1717
  return !this._agentRunAbortRequested;
1443
1718
  }
1444
1719
  if (this._agentRunAbortRequested) {
@@ -1512,7 +1787,7 @@ export class AgentSession {
1512
1787
  for (const image of images) {
1513
1788
  const processed = await processImage(Buffer.from(image.data, "base64"), image.mimeType, {
1514
1789
  autoResizeImages: this.settingsManager.getImageAutoResize(),
1515
- resizeOptions: this.model?.inputLimits?.images?.resize,
1790
+ resizeOptions: this._limitsModel()?.inputLimits?.images?.resize,
1516
1791
  });
1517
1792
  if (!processed.ok) {
1518
1793
  hints.push(processed.message);
@@ -1539,152 +1814,140 @@ export class AgentSession {
1539
1814
  }
1540
1815
  const expandPromptTemplates = options?.expandPromptTemplates ?? true;
1541
1816
  const preflightResult = options?.preflightResult;
1542
- let messages;
1543
- try {
1544
- // Handle extension commands first (execute immediately, even during streaming)
1545
- // Extension commands manage their own LLM interaction via pi.sendMessage()
1546
- if (expandPromptTemplates && text.startsWith("/")) {
1547
- const handled = await this._tryExecuteExtensionCommand(text);
1548
- if (handled) {
1549
- // Extension command executed, no prompt to send
1550
- preflightResult?.(true);
1551
- return;
1552
- }
1553
- }
1554
- if (this._compactionAbortController !== undefined && !this._isAborting) {
1555
- throw new Error("Cannot submit a prompt while compaction is in progress. Wait for compaction to finish and retry.");
1556
- }
1557
- // Emit input event for extension interception (before skill/template expansion)
1558
- const processedInput = await this._runInputHandlers(text, options?.images, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
1559
- if (!processedInput) {
1560
- preflightResult?.(true);
1817
+ // Handle extension commands first (execute immediately, even during streaming)
1818
+ // Extension commands manage their own LLM interaction via pi.sendMessage()
1819
+ if (expandPromptTemplates && text.startsWith("/")) {
1820
+ const handled = await this._tryExecuteExtensionCommand(text);
1821
+ if (handled) {
1822
+ // Extension command executed, no prompt to send
1823
+ preflightResult?.("handled");
1561
1824
  return;
1562
1825
  }
1563
- const { text: currentText, images: currentImages } = processedInput;
1564
- // Expand skill commands (/skill:name args) and prompt templates (/template args)
1565
- let expandedText = currentText;
1566
- if (expandPromptTemplates) {
1567
- expandedText = this._expandSkillCommand(expandedText);
1568
- expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
1569
- }
1570
- // If streaming, queue via steer() or followUp() based on option
1571
- if (this.isStreaming || this._isAborting) {
1572
- if (!options?.streamingBehavior) {
1573
- throw new Error("Agent is already processing. Specify streamingBehavior ('steer' or 'followUp') to queue the message.");
1574
- }
1575
- if (options.streamingBehavior === "followUp") {
1576
- await this._queueFollowUp(expandedText, currentImages);
1577
- }
1578
- else {
1579
- await this._queueSteer(expandedText, currentImages);
1580
- }
1581
- preflightResult?.(true);
1582
- return;
1826
+ }
1827
+ if (this._compactionAbortController !== undefined && !this._isAborting) {
1828
+ throw new Error("Cannot submit a prompt while compaction is in progress. Wait for compaction to finish and retry.");
1829
+ }
1830
+ // Emit input event for extension interception (before skill/template expansion)
1831
+ const processedInput = await this._runInputHandlers(text, options?.images, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
1832
+ if (!processedInput) {
1833
+ preflightResult?.("handled");
1834
+ return;
1835
+ }
1836
+ const { text: currentText, images: currentImages } = processedInput;
1837
+ // Expand skill commands (/skill:name args) and prompt templates (/template args)
1838
+ let expandedText = currentText;
1839
+ if (expandPromptTemplates) {
1840
+ expandedText = this._expandSkillCommand(expandedText);
1841
+ expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
1842
+ }
1843
+ // If streaming, queue via steer() or followUp() based on option
1844
+ if (this.isStreaming || this._isAborting) {
1845
+ if (!options?.streamingBehavior) {
1846
+ throw new Error("Agent is already processing. Specify streamingBehavior ('steer' or 'followUp') to queue the message.");
1583
1847
  }
1584
- // Flush any pending bash and custom messages before the new prompt
1585
- this._flushPendingBashMessages();
1586
- this._flushPendingCustomMessages();
1587
- // Validate model
1588
- if (!this.model) {
1589
- throw new Error(formatNoModelSelectedMessage());
1848
+ if (options.streamingBehavior === "followUp") {
1849
+ await this._queueFollowUp(expandedText, currentImages);
1590
1850
  }
1591
- const hasConfiguredAuth = this._modelRuntime.hasConfiguredAuth(this.model.provider) ||
1592
- (await this._modelRuntime.checkAuth(this.model.provider)) !== undefined;
1593
- if (!hasConfiguredAuth) {
1594
- const isOAuth = this._modelRuntime.isUsingOAuth(this.model.provider);
1595
- if (isOAuth) {
1596
- throw new Error(`Authentication failed for "${this.model.provider}". ` +
1597
- `Credentials may have expired or network is unavailable. ` +
1598
- `Run '/login ${this.model.provider}' to re-authenticate.`);
1599
- }
1600
- throw new Error(formatNoApiKeyFoundMessage(this.model.provider));
1851
+ else {
1852
+ await this._queueSteer(expandedText, currentImages);
1601
1853
  }
1602
- // Check if we need to compact before sending (catches aborted responses).
1603
- // The user's new prompt is sent below, so do not call agent.continue() here.
1604
- if (this._isAborting) {
1605
- preflightResult?.(false);
1606
- return;
1854
+ preflightResult?.("queued");
1855
+ return;
1856
+ }
1857
+ // Flush any pending bash and custom messages before the new prompt
1858
+ this._flushPendingBashMessages();
1859
+ this._flushPendingCustomMessages();
1860
+ // Validate model
1861
+ if (!this.model) {
1862
+ throw new Error(formatNoModelSelectedMessage());
1863
+ }
1864
+ const hasConfiguredAuth = this._modelRuntime.hasConfiguredAuth(this.model.provider) ||
1865
+ (await this._modelRuntime.checkAuth(this.model.provider)) !== undefined;
1866
+ if (!hasConfiguredAuth) {
1867
+ const isOAuth = this._modelRuntime.isUsingOAuth(this.model.provider);
1868
+ if (isOAuth) {
1869
+ throw new Error(`Authentication failed for "${this.model.provider}". ` +
1870
+ `Credentials may have expired or network is unavailable. ` +
1871
+ `Run '/login ${this.model.provider}' to re-authenticate.`);
1607
1872
  }
1608
- const lastAssistant = this._findLastAssistantMessage();
1609
- if (lastAssistant) {
1610
- const prePromptAbortController = new AbortController();
1611
- let resolvePrePromptCompletion;
1612
- const prePromptCompletion = new Promise((resolve) => {
1613
- resolvePrePromptCompletion = resolve;
1614
- });
1615
- this._prePromptAbortController = prePromptAbortController;
1616
- this._prePromptCompletionPromise = prePromptCompletion;
1617
- try {
1618
- await this._checkCompaction(lastAssistant, false, [], prePromptAbortController.signal);
1873
+ throw new Error(formatNoApiKeyFoundMessage(this.model.provider));
1874
+ }
1875
+ // Check if we need to compact before sending (catches aborted responses).
1876
+ // The user's new prompt is sent below, so do not call agent.continue() here.
1877
+ if (this._isAborting) {
1878
+ return;
1879
+ }
1880
+ const lastAssistant = this._findLastAssistantMessage();
1881
+ if (lastAssistant) {
1882
+ const prePromptAbortController = new AbortController();
1883
+ let resolvePrePromptCompletion;
1884
+ const prePromptCompletion = new Promise((resolve) => {
1885
+ resolvePrePromptCompletion = resolve;
1886
+ });
1887
+ this._prePromptAbortController = prePromptAbortController;
1888
+ this._prePromptCompletionPromise = prePromptCompletion;
1889
+ try {
1890
+ await this._checkCompaction(lastAssistant, false, [], prePromptAbortController.signal);
1891
+ }
1892
+ finally {
1893
+ if (this._prePromptAbortController === prePromptAbortController) {
1894
+ this._prePromptAbortController = undefined;
1619
1895
  }
1620
- finally {
1621
- if (this._prePromptAbortController === prePromptAbortController) {
1622
- this._prePromptAbortController = undefined;
1623
- }
1624
- if (this._prePromptCompletionPromise === prePromptCompletion) {
1625
- this._prePromptCompletionPromise = undefined;
1626
- }
1627
- resolvePrePromptCompletion?.();
1628
- }
1629
- if (prePromptAbortController.signal.aborted || this._isAborting) {
1630
- preflightResult?.(false);
1631
- return;
1896
+ if (this._prePromptCompletionPromise === prePromptCompletion) {
1897
+ this._prePromptCompletionPromise = undefined;
1632
1898
  }
1899
+ resolvePrePromptCompletion?.();
1633
1900
  }
1634
- if (isPiServerMode()) {
1635
- this._detachPiServerTerminalAssistantFailure();
1901
+ if (prePromptAbortController.signal.aborted || this._isAborting) {
1902
+ return;
1636
1903
  }
1637
- // Emit before_agent_start before normalizing images so extension-driven model
1638
- // selection determines the resize profile used for the request and history.
1639
- const selectedToolsBefore = this._baseSystemPromptOptions.selectedTools;
1640
- const result = await this._extensionRunner.emitBeforeAgentStart(expandedText, currentImages, this._baseSystemPromptOptions);
1641
- // Handlers may edit event.systemPromptOptions.selectedTools or call setActiveTools(),
1642
- // which updates the live loadout instead. An explicit edit wins; otherwise the live
1643
- // loadout is authoritative, so a setActiveTools() call is not undone here.
1644
- const handlerEditedTools = result.systemPromptOptions.selectedTools.length !== selectedToolsBefore.length ||
1645
- result.systemPromptOptions.selectedTools.some((name, index) => name !== selectedToolsBefore[index]);
1646
- if (!handlerEditedTools)
1647
- result.systemPromptOptions.selectedTools = this.getActiveToolNames();
1648
- const normalized = await this._normalizePromptImages(currentImages);
1649
- const userText = normalized.hints.length > 0 ? `${expandedText}\n\n${normalized.hints.join("\n")}` : expandedText;
1650
- // Build messages only after hooks and image normalization have completed.
1651
- messages = [];
1652
- const userContent = [{ type: "text", text: userText }];
1653
- userContent.push(...normalized.images);
1904
+ }
1905
+ if (isPiServerMode()) {
1906
+ this._detachPiServerTerminalAssistantFailure();
1907
+ }
1908
+ // Emit before_agent_start before normalizing images so extension-driven model
1909
+ // selection determines the resize profile used for the request and history.
1910
+ const selectedToolsBefore = this._baseSystemPromptOptions.selectedTools;
1911
+ const result = await this._extensionRunner.emitBeforeAgentStart(expandedText, currentImages, this._baseSystemPromptOptions);
1912
+ // Handlers may edit event.systemPromptOptions.selectedTools or call setActiveTools(),
1913
+ // which updates the live loadout instead. An explicit edit wins; otherwise the live
1914
+ // loadout is authoritative, so a setActiveTools() call is not undone here.
1915
+ const handlerEditedTools = result.systemPromptOptions.selectedTools.length !== selectedToolsBefore.length ||
1916
+ result.systemPromptOptions.selectedTools.some((name, index) => name !== selectedToolsBefore[index]);
1917
+ if (!handlerEditedTools)
1918
+ result.systemPromptOptions.selectedTools = this.getActiveToolNames();
1919
+ const normalized = await this._normalizePromptImages(currentImages);
1920
+ const userText = normalized.hints.length > 0 ? `${expandedText}\n\n${normalized.hints.join("\n")}` : expandedText;
1921
+ // Build messages only after hooks and image normalization have completed.
1922
+ const messages = [];
1923
+ const userContent = [{ type: "text", text: userText }];
1924
+ userContent.push(...normalized.images);
1925
+ messages.push({
1926
+ role: "user",
1927
+ content: userContent,
1928
+ timestamp: Date.now(),
1929
+ });
1930
+ // Inject any pending "nextTurn" messages as context alongside the user message
1931
+ for (const msg of this._pendingNextTurnMessages) {
1932
+ messages.push(msg);
1933
+ }
1934
+ this._pendingNextTurnMessages = [];
1935
+ for (const msg of result.messages) {
1654
1936
  messages.push({
1655
- role: "user",
1656
- content: userContent,
1937
+ role: "custom",
1938
+ customType: msg.customType,
1939
+ // Untyped extensions can pass null/missing content; normalize at ingestion.
1940
+ content: msg.content ?? [],
1941
+ display: msg.display,
1942
+ details: msg.details,
1657
1943
  timestamp: Date.now(),
1658
1944
  });
1659
- // Inject any pending "nextTurn" messages as context alongside the user message
1660
- for (const msg of this._pendingNextTurnMessages) {
1661
- messages.push(msg);
1662
- }
1663
- this._pendingNextTurnMessages = [];
1664
- for (const msg of result.messages) {
1665
- messages.push({
1666
- role: "custom",
1667
- customType: msg.customType,
1668
- // Untyped extensions can pass null/missing content; normalize at ingestion.
1669
- content: msg.content ?? [],
1670
- display: msg.display,
1671
- details: msg.details,
1672
- timestamp: Date.now(),
1673
- });
1674
- }
1675
- const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
1676
- this._runSystemPromptOptions = result.systemPromptOptions;
1677
- if (updateMessage)
1678
- messages.unshift(updateMessage);
1679
- }
1680
- catch (error) {
1681
- preflightResult?.(false);
1682
- throw error;
1683
1945
  }
1684
- if (!messages) {
1685
- return;
1686
- }
1687
- preflightResult?.(true);
1946
+ const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
1947
+ this._runSystemPromptOptions = result.systemPromptOptions;
1948
+ if (updateMessage)
1949
+ messages.unshift(updateMessage);
1950
+ preflightResult?.("started");
1688
1951
  await this._runAgentPrompt(messages);
1689
1952
  }
1690
1953
  /**
@@ -1750,7 +2013,7 @@ export class AgentSession {
1750
2013
  }
1751
2014
  const processedInput = await this._runInputHandlers(text, images, source, this.isStreaming ? behavior : undefined);
1752
2015
  if (!processedInput)
1753
- return;
2016
+ return "handled";
1754
2017
  let expandedText = this._expandSkillCommand(processedInput.text);
1755
2018
  expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
1756
2019
  if (behavior === "steer") {
@@ -1759,6 +2022,7 @@ export class AgentSession {
1759
2022
  else {
1760
2023
  await this._queueFollowUp(expandedText, processedInput.images);
1761
2024
  }
2025
+ return "queued";
1762
2026
  }
1763
2027
  /**
1764
2028
  * Queue a steering message while the agent is running.
@@ -1770,7 +2034,7 @@ export class AgentSession {
1770
2034
  * @throws Error if text is an extension command
1771
2035
  */
1772
2036
  async steer(text, images, options) {
1773
- await this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
2037
+ return this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
1774
2038
  }
1775
2039
  /**
1776
2040
  * Queue a follow-up message to be processed after the agent finishes.
@@ -1781,7 +2045,7 @@ export class AgentSession {
1781
2045
  * @throws Error if text is an extension command
1782
2046
  */
1783
2047
  async followUp(text, images, options) {
1784
- await this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
2048
+ return this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
1785
2049
  }
1786
2050
  /**
1787
2051
  * Internal: Queue a steering message (already expanded, no extension command check).
@@ -2393,8 +2657,8 @@ export class AgentSession {
2393
2657
  throw new Error(formatNoModelSelectedMessage());
2394
2658
  }
2395
2659
  const settings = this.settingsManager.getCompactionSettings(model);
2396
- const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
2397
2660
  if (isPiServerMode()) {
2661
+ const { model: requestModel, apiKey, headers, thinkingLevel, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
2398
2662
  this._detachPiServerTerminalAssistantFailure();
2399
2663
  const cacheInput = await this._buildCompactionCacheInput(requestModel);
2400
2664
  const piServerResult = await compactPiServer(requestModel, {
@@ -2413,7 +2677,7 @@ export class AgentSession {
2413
2677
  settings: this.settingsManager.getCompactionSettings(),
2414
2678
  sessionTree: buildPiServerSessionTree(this.sessionManager.getEntries(), this.sessionManager.getLeafId()),
2415
2679
  signal: this._compactionAbortController.signal,
2416
- reasoning: toProviderReasoning(this.thinkingLevel),
2680
+ reasoning: toProviderReasoning(thinkingLevel),
2417
2681
  onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
2418
2682
  });
2419
2683
  const result = await this._applyPiServerCompactionResult(piServerResult, "manual", false);
@@ -2471,9 +2735,10 @@ export class AgentSession {
2471
2735
  details = extensionCompaction.details;
2472
2736
  }
2473
2737
  else {
2474
- // Generate compaction result
2738
+ // Resolve the request only when Pi summarizes itself: routing may call models or fail.
2739
+ const { model: requestModel, apiKey, headers, env, thinkingLevel, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
2475
2740
  const cacheInput = await this._buildCompactionCacheInput(requestModel, preparation);
2476
- const result = await compact(preparation, requestModel, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason: "manual" }), undefined, cacheInput.cachePrefixContext, cacheInput.cacheOptions, cacheInput.reason);
2741
+ const result = await compact(preparation, requestModel, apiKey, headers, customInstructions, this._compactionAbortController.signal, thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason: "manual" }), undefined, cacheInput.cachePrefixContext, cacheInput.cacheOptions, cacheInput.reason);
2477
2742
  summary = result.summary;
2478
2743
  firstKeptEntryId = result.firstKeptEntryId;
2479
2744
  tokensBefore = result.tokensBefore;
@@ -2585,12 +2850,14 @@ export class AgentSession {
2585
2850
  // Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
2586
2851
  if (skipAbortedCheck && assistantMessage.stopReason === "aborted")
2587
2852
  return false;
2588
- const contextWindow = this.model?.contextWindow ?? 0;
2589
2853
  // Skip overflow check if the message came from a different model.
2590
2854
  // This handles the case where user switched from a smaller-context model (e.g. opus)
2591
2855
  // to a larger-context model (e.g. codex) - the overflow error from the old model
2592
- // shouldn't trigger compaction for the new model.
2593
- const sameModel = this.model && assistantMessage.provider === this.model.provider && assistantMessage.model === this.model.id;
2856
+ // shouldn't trigger compaction for the new model. Under a virtual selection, the
2857
+ // physical model that produced the message supplies the limits.
2858
+ const messageModel = this._modelForMessage(assistantMessage);
2859
+ const sameModel = messageModel !== undefined;
2860
+ const contextWindow = (messageModel ?? this.model)?.contextWindow ?? 0;
2594
2861
  // Skip compaction checks if this assistant message is older than the latest
2595
2862
  // compaction boundary. This prevents a stale pre-compaction usage/error
2596
2863
  // from retriggering compaction on the first prompt after compaction.
@@ -2624,7 +2891,7 @@ export class AgentSession {
2624
2891
  const contextOverflow = sameModel &&
2625
2892
  ((explicitOverflow && assistantRetainedForExplicitRecovery) ||
2626
2893
  (assistantUsageMatchesProjection && isContextOverflow(assistantMessage, contextWindow)));
2627
- const recoverableLength = sameModel && assistantIsProjected && isRecoverableLength(assistantMessage, this.model?.maxTokens ?? 0);
2894
+ const recoverableLength = sameModel && assistantIsProjected && isRecoverableLength(assistantMessage, messageModel.maxTokens);
2628
2895
  if (contextOverflow || recoverableLength) {
2629
2896
  const willRetry = assistantMessage.stopReason !== "stop";
2630
2897
  if (!willRetry) {
@@ -2649,7 +2916,10 @@ export class AgentSession {
2649
2916
  this._omitRecoveryAttempt(assistantMessage, toolResults);
2650
2917
  if (isPiServerMode())
2651
2918
  this._detachPiServerTerminalAssistantFailure();
2652
- return await this._runAutoCompaction("overflow", willRetry, undefined, undefined, externalSignal);
2919
+ const retry = await this._runAutoCompaction("overflow", willRetry, undefined, undefined, externalSignal);
2920
+ if (retry)
2921
+ this._failedResponse = assistantMessage;
2922
+ return retry;
2653
2923
  }
2654
2924
  // Case 2: Threshold - context is getting large
2655
2925
  // For error messages or all-zero usage messages, estimate from the last valid response.
@@ -2712,7 +2982,7 @@ export class AgentSession {
2712
2982
  started = true;
2713
2983
  this._emit({ type: "compaction_start", reason });
2714
2984
  abortController.signal.throwIfAborted();
2715
- const { model: requestModel, apiKey, headers, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2985
+ const { model: requestModel, apiKey, headers, thinkingLevel, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2716
2986
  abortController.signal.throwIfAborted();
2717
2987
  const cacheInput = await this._buildCompactionCacheInput(requestModel);
2718
2988
  const piServerResult = await compactPiServer(requestModel, {
@@ -2731,7 +3001,7 @@ export class AgentSession {
2731
3001
  preparation: preparationOptions,
2732
3002
  sessionTree: buildPiServerSessionTree(this.sessionManager.getEntries(), this.sessionManager.getLeafId()),
2733
3003
  signal: abortController.signal,
2734
- reasoning: toProviderReasoning(this.thinkingLevel),
3004
+ reasoning: toProviderReasoning(thinkingLevel),
2735
3005
  onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
2736
3006
  });
2737
3007
  if (externalSignal?.aborted || abortController.signal.aborted) {
@@ -2759,8 +3029,6 @@ export class AgentSession {
2759
3029
  started = true;
2760
3030
  this._emit({ type: "compaction_start", reason });
2761
3031
  abortController.signal.throwIfAborted();
2762
- const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2763
- abortController.signal.throwIfAborted();
2764
3032
  let extensionCompaction;
2765
3033
  if (this._extensionRunner.hasHandlers("session_before_compact")) {
2766
3034
  const extensionResult = (await this._extensionRunner.emit({
@@ -2795,8 +3063,10 @@ export class AgentSession {
2795
3063
  details = extensionCompaction.details;
2796
3064
  }
2797
3065
  else {
3066
+ const { model: requestModel, apiKey, headers, env, thinkingLevel, } = await this._getSummarizationRequestAuth(model, abortController.signal);
3067
+ abortController.signal.throwIfAborted();
2798
3068
  const cacheInput = await this._buildCompactionCacheInput(requestModel, preparation);
2799
- const compactResult = await compact(preparation, requestModel, apiKey, headers, undefined, abortController.signal, this.thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }), undefined, cacheInput.cachePrefixContext, cacheInput.cacheOptions, cacheInput.reason);
3069
+ const compactResult = await compact(preparation, requestModel, apiKey, headers, undefined, abortController.signal, thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }), undefined, cacheInput.cachePrefixContext, cacheInput.cacheOptions, cacheInput.reason);
2800
3070
  summary = compactResult.summary;
2801
3071
  firstKeptEntryId = compactResult.firstKeptEntryId;
2802
3072
  tokensBefore = compactResult.tokensBefore;
@@ -2893,10 +3163,13 @@ export class AgentSession {
2893
3163
  return this.settingsManager.getCompactionEnabled();
2894
3164
  }
2895
3165
  _shouldCompactBeforeNextProviderRequest(turn) {
3166
+ // A virtual selection is checked in prepareRequest, against the model the request is routed to.
3167
+ if (!this.model || isVirtualModel(this.model))
3168
+ return false;
2896
3169
  const settings = this.settingsManager.getCompactionSettings(this.model);
2897
3170
  if (!settings.enabled || turn.toolResults.length === 0)
2898
3171
  return false;
2899
- const contextWindow = this.model?.contextWindow ?? 0;
3172
+ const contextWindow = this.model.contextWindow;
2900
3173
  if (contextWindow <= 0)
2901
3174
  return false;
2902
3175
  const branch = this.sessionManager.getBranch();
@@ -2997,6 +3270,7 @@ export class AgentSession {
2997
3270
  }
2998
3271
  this._applyExtensionBindings(this._extensionRunner);
2999
3272
  await this._extensionRunner.emit(this._sessionStartEvent);
3273
+ this._extensionRunner.reportUnhandledMcpServers();
3000
3274
  await this.extendResourcesFromExtensions(this._sessionStartEvent.reason === "reload" ? "reload" : "startup");
3001
3275
  }
3002
3276
  async extendResourcesFromExtensions(reason) {
@@ -3018,7 +3292,7 @@ export class AgentSession {
3018
3292
  buildExtensionResourcePaths(entries) {
3019
3293
  return entries.map((entry) => {
3020
3294
  const source = this.getExtensionSourceLabel(entry.extensionPath);
3021
- const baseDir = entry.extensionPath.startsWith("<") ? undefined : dirname(entry.extensionPath);
3295
+ const baseDir = isSyntheticPath(entry.extensionPath) ? undefined : dirname(entry.extensionPath);
3022
3296
  return {
3023
3297
  path: entry.path,
3024
3298
  metadata: {
@@ -3031,7 +3305,7 @@ export class AgentSession {
3031
3305
  });
3032
3306
  }
3033
3307
  getExtensionSourceLabel(extensionPath) {
3034
- if (extensionPath.startsWith("<")) {
3308
+ if (isSyntheticPath(extensionPath)) {
3035
3309
  return `extension:${extensionPath.replace(/[<>]/g, "")}`;
3036
3310
  }
3037
3311
  const base = basename(extensionPath);
@@ -3116,6 +3390,7 @@ export class AgentSession {
3116
3390
  },
3117
3391
  getActiveTools: () => this.getActiveToolNames(),
3118
3392
  getAllTools: () => this.getAllTools(),
3393
+ getSettings: () => this.settingsManager.getSettings(),
3119
3394
  setActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),
3120
3395
  refreshTools: () => this._refreshToolRegistry(),
3121
3396
  getCommands,
@@ -3159,6 +3434,8 @@ export class AgentSession {
3159
3434
  },
3160
3435
  getSystemPrompt: () => this.systemPrompt,
3161
3436
  getSystemPromptOptions: () => this._baseSystemPromptOptions,
3437
+ executeTool: (callerId, name, args, options) => this._executeNestedToolCall(callerId, name, args, options),
3438
+ getCallableTools: () => this._getCallableTools(),
3162
3439
  }, {
3163
3440
  registerProvider: (name, config) => {
3164
3441
  this._modelRuntime.registerProvider(name, config);
@@ -3172,14 +3449,22 @@ export class AgentSession {
3172
3449
  this._modelRuntime.unregisterProvider(name);
3173
3450
  this._refreshCurrentModelFromRegistry();
3174
3451
  },
3452
+ registerVirtualModel: (definition) => {
3453
+ this._modelRuntime.registerVirtualModel(definition);
3454
+ this._refreshCurrentModelFromRegistry();
3455
+ },
3456
+ unregisterVirtualModel: (provider, id) => {
3457
+ this._modelRuntime.unregisterVirtualModel(provider, id);
3458
+ this._refreshCurrentModelFromRegistry();
3459
+ },
3175
3460
  });
3176
3461
  }
3177
3462
  _refreshToolRegistry(options) {
3178
- const previousRegistryNames = new Set(this._toolRegistry.keys());
3463
+ // Tools that were already activated on registration. A tool whose exposure changes to
3464
+ // `direct` or `model-only` (for example from `hidden`) is activated like a new tool.
3465
+ const previousActivatedOnRegistration = new Set([...this._toolRegistry.keys()].filter((name) => this._isActivatedOnRegistration(name)));
3179
3466
  const previousActiveToolNames = this.getActiveToolNames();
3180
3467
  const allowedToolNames = this._allowedToolNames;
3181
- const excludedToolNames = this._excludedToolNames;
3182
- const isAllowedTool = (name) => (!allowedToolNames || allowedToolNames.has(name)) && !excludedToolNames?.has(name);
3183
3468
  const registeredTools = this._extensionRunner.getAllRegisteredTools();
3184
3469
  const allCustomTools = [
3185
3470
  ...registeredTools,
@@ -3187,14 +3472,14 @@ export class AgentSession {
3187
3472
  definition,
3188
3473
  sourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, { source: "sdk" }),
3189
3474
  })),
3190
- ].filter((tool) => isAllowedTool(tool.definition.name));
3475
+ ].filter((tool) => this._isAllowedTool(tool.definition.name));
3191
3476
  const definitionRegistry = new Map(Array.from(this._baseToolDefinitions.entries())
3192
- .filter(([name]) => isAllowedTool(name))
3477
+ .filter(([name]) => this._isAllowedTool(name))
3193
3478
  .map(([name, definition]) => [
3194
3479
  name,
3195
3480
  {
3196
3481
  definition,
3197
- sourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, { source: "builtin" }),
3482
+ sourceInfo: createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${name}`, { source: "builtin" }),
3198
3483
  },
3199
3484
  ]));
3200
3485
  for (const tool of allCustomTools) {
@@ -3219,37 +3504,52 @@ export class AgentSession {
3219
3504
  const runner = this._extensionRunner;
3220
3505
  const wrappedExtensionTools = wrapRegisteredTools(allCustomTools, runner);
3221
3506
  const wrappedBuiltInTools = wrapRegisteredTools(Array.from(this._baseToolDefinitions.values())
3222
- .filter((definition) => isAllowedTool(definition.name))
3507
+ .filter((definition) => this._isAllowedTool(definition.name))
3223
3508
  .map((definition) => ({
3224
3509
  definition,
3225
- sourceInfo: createSyntheticSourceInfo(`<builtin:${definition.name}>`, { source: "builtin" }),
3510
+ sourceInfo: createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${definition.name}`, {
3511
+ source: "builtin",
3512
+ }),
3226
3513
  })), runner);
3227
3514
  const toolRegistry = new Map(wrappedBuiltInTools.map((tool) => [tool.name, tool]));
3228
3515
  for (const tool of wrappedExtensionTools) {
3229
3516
  toolRegistry.set(tool.name, tool);
3230
3517
  }
3231
3518
  this._toolRegistry = toolRegistry;
3232
- const nextActiveToolNames = (options?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]).filter((name) => isAllowedTool(name));
3519
+ const nextActiveToolNames = (options?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]).filter((name) => this._isAllowedTool(name));
3233
3520
  if (allowedToolNames) {
3234
3521
  for (const toolName of this._toolRegistry.keys()) {
3235
- if (allowedToolNames.has(toolName)) {
3522
+ // Naming a tool activates it even when it is not active by default.
3523
+ if (allowedToolNames.has(toolName) && this._isDeclarable(toolName)) {
3236
3524
  nextActiveToolNames.push(toolName);
3237
3525
  }
3238
3526
  }
3239
3527
  }
3240
3528
  else if (options?.includeAllExtensionTools) {
3241
3529
  for (const tool of wrappedExtensionTools) {
3242
- nextActiveToolNames.push(tool.name);
3530
+ if (this._isActivatedOnRegistration(tool.name))
3531
+ nextActiveToolNames.push(tool.name);
3243
3532
  }
3244
3533
  }
3245
3534
  else if (!options?.activeToolNames) {
3246
3535
  for (const toolName of this._toolRegistry.keys()) {
3247
- if (!previousRegistryNames.has(toolName)) {
3536
+ if (!previousActivatedOnRegistration.has(toolName) && this._isActivatedOnRegistration(toolName)) {
3248
3537
  nextActiveToolNames.push(toolName);
3249
3538
  }
3250
3539
  }
3251
3540
  }
3252
- this.setActiveToolsByName([...new Set(nextActiveToolNames)]);
3541
+ // Pending tools that are registered now become active.
3542
+ nextActiveToolNames.push(...this._pendingToolNames);
3543
+ this._setActiveTools([...new Set(nextActiveToolNames)]);
3544
+ }
3545
+ /** Whether activating the tool declares it to the model. */
3546
+ _isDeclarable(name) {
3547
+ const exposure = this._getToolExposure(name);
3548
+ return exposure === "direct" || exposure === "model-only";
3549
+ }
3550
+ /** Whether registering the tool activates it, which declares it to the model. */
3551
+ _isActivatedOnRegistration(name) {
3552
+ return this._isDeclarable(name) && this._toolDefinitions.get(name)?.definition.defaultActive !== false;
3253
3553
  }
3254
3554
  _buildRuntime(options) {
3255
3555
  const autoResizeImages = this.settingsManager.getImageAutoResize();
@@ -3291,12 +3591,21 @@ export class AgentSession {
3291
3591
  const previousFlagValues = oldRunner.getFlagValues();
3292
3592
  await emitSessionShutdownEvent(oldRunner, { type: "session_shutdown", reason: "reload" });
3293
3593
  oldRunner.invalidate();
3594
+ const previousDefaultTools = new Set(this._usesDefaultTools ? (this.settingsManager.getDefaultTools() ?? DEFAULT_TOOL_NAMES) : []);
3294
3595
  await this.settingsManager.reload();
3295
3596
  this.syncQueueModesFromSettings();
3296
3597
  resetApiProviders();
3297
3598
  await this._resourceLoader.reload();
3599
+ // Activate tools newly added to defaultTools. Removed ones stay active, and tools disabled
3600
+ // during the session stay disabled unless the setting newly adds them.
3601
+ const addedDefaultTools = this._usesDefaultTools
3602
+ ? (this.settingsManager.getDefaultTools() ?? DEFAULT_TOOL_NAMES).filter((name) => !previousDefaultTools.has(name))
3603
+ : [];
3604
+ // Tools the new extensions register later, such as MCP tools, are pending until then.
3605
+ for (const name of this.getActiveToolNames())
3606
+ this._pendingToolNames.add(name);
3298
3607
  this._buildRuntime({
3299
- activeToolNames: this.getActiveToolNames(),
3608
+ activeToolNames: [...this.getActiveToolNames(), ...addedDefaultTools],
3300
3609
  flagValues: previousFlagValues,
3301
3610
  includeAllExtensionTools: true,
3302
3611
  });
@@ -3307,6 +3616,7 @@ export class AgentSession {
3307
3616
  if (hasBindings) {
3308
3617
  await options?.beforeSessionStart?.();
3309
3618
  await this._extensionRunner.emit({ type: "session_start", reason: "reload" });
3619
+ this._extensionRunner.reportUnhandledMcpServers();
3310
3620
  await this.extendResourcesFromExtensions("reload");
3311
3621
  }
3312
3622
  }
@@ -3323,7 +3633,7 @@ export class AgentSession {
3323
3633
  */
3324
3634
  _isRetryableError(message) {
3325
3635
  // Context overflow is handled by compaction, not retry.
3326
- if (isContextOverflow(message, this.model?.contextWindow ?? 0))
3636
+ if (isContextOverflow(message, (this._modelForMessage(message) ?? this.model)?.contextWindow ?? 0))
3327
3637
  return false;
3328
3638
  if (this._isPostAssistantPiServerSyncFailure(message))
3329
3639
  return false;
@@ -3637,15 +3947,11 @@ export class AgentSession {
3637
3947
  let summaryDetails;
3638
3948
  let summaryUsage;
3639
3949
  if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
3640
- const model = this.model;
3641
- const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
3950
+ const signal = this._branchSummaryAbortController.signal;
3642
3951
  const branchSummarySettings = this.settingsManager.getBranchSummarySettings();
3643
3952
  const result = await generateBranchSummary(entriesToSummarize, {
3644
- model: requestModel,
3645
- apiKey,
3646
- headers,
3647
- env,
3648
- signal: this._branchSummaryAbortController.signal,
3953
+ ...(await this._getSummarizationRequestAuth(this.model, signal)),
3954
+ signal,
3649
3955
  customInstructions,
3650
3956
  replaceInstructions,
3651
3957
  reserveTokens: branchSummarySettings.reserveTokens,
@@ -3814,7 +4120,7 @@ export class AgentSession {
3814
4120
  };
3815
4121
  }
3816
4122
  getContextUsage() {
3817
- const model = this.model;
4123
+ const model = this._limitsModel();
3818
4124
  if (!model)
3819
4125
  return undefined;
3820
4126
  const contextWindow = model.contextWindow ?? 0;
@@ -3908,16 +4214,11 @@ export class AgentSession {
3908
4214
  if (!model) {
3909
4215
  throw new Error("No model selected");
3910
4216
  }
3911
- const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
3912
4217
  return generateBugReportSummary({
4218
+ ...(await this._getSummarizationRequestAuth(model, options.signal)),
3913
4219
  messages: this.messages,
3914
4220
  hint: options.hint,
3915
- model: requestModel,
3916
- apiKey,
3917
- headers,
3918
- env,
3919
4221
  signal: options.signal,
3920
- thinkingLevel: this.thinkingLevel,
3921
4222
  streamFn: this.agent.streamFunction,
3922
4223
  retry: this.settingsManager.getRetrySettings(),
3923
4224
  sessionId: this.sessionId,