@averyyy/pi-coding-agent 0.87.1-piclient.2 → 0.99.1-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 (733) hide show
  1. package/CHANGELOG.md +97 -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-A6EXUBG6.js +6 -0
  10. package/dist/bundle/chunks/anthropic.js +2 -2
  11. package/dist/bundle/chunks/azure-openai-responses-YZ3Q2WVP.js +2 -0
  12. package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
  13. package/dist/bundle/chunks/chunk-3YXHSP6S.js +21 -0
  14. package/dist/bundle/chunks/chunk-7BINYQ2V.js +1548 -0
  15. package/dist/bundle/chunks/chunk-7JGR3GZN.js +11 -0
  16. package/dist/bundle/chunks/chunk-F6ORSP6L.js +187 -0
  17. package/dist/bundle/chunks/chunk-FJTXMIZI.js +150 -0
  18. package/dist/bundle/chunks/chunk-H3QXYIF7.js +31 -0
  19. package/dist/bundle/chunks/{chunk-S7SZN6Z3.js → chunk-HSPCVFST.js} +1 -1
  20. package/dist/bundle/chunks/chunk-J4CWPC4N.js +2 -0
  21. package/dist/bundle/chunks/chunk-KYJKN5BJ.js +2 -0
  22. package/dist/bundle/chunks/chunk-RO6I2QFQ.js +4 -0
  23. package/dist/bundle/chunks/{chunk-XDUWOHPL.js → chunk-S3GGRYIO.js} +2 -2
  24. package/dist/bundle/chunks/chunk-UTB4DTYQ.js +2 -0
  25. package/dist/bundle/chunks/{chunk-UZNGGY6N.js → chunk-V7V43FNB.js} +3 -3
  26. package/dist/bundle/chunks/{chunk-FUXEF6JQ.js → chunk-W2DOMZSC.js} +1 -1
  27. package/dist/bundle/chunks/chunk-WVKBMRQX.js +82 -0
  28. package/dist/bundle/chunks/cli-WF6HDHBO.js +49 -0
  29. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-XJQQYGGU.js +2 -0
  30. package/dist/bundle/chunks/codemode-worker.js +295 -0
  31. package/dist/bundle/chunks/execute-AVGAUHMT.js +308 -0
  32. package/dist/bundle/chunks/github-copilot.js +1 -1
  33. package/dist/bundle/chunks/google-generative-ai-CQAKKJTA.js +2 -0
  34. package/dist/bundle/chunks/google-vertex-AE36YXJU.js +2 -0
  35. package/dist/bundle/chunks/{lib-HGQMNYVT.js → lib-TEDK3E5I.js} +2 -2
  36. package/dist/bundle/chunks/llama-cpp-classify-PJJYKPLD.js +22 -0
  37. package/dist/bundle/chunks/mistral-conversations-KEYTXJM7.js +5 -0
  38. package/dist/bundle/chunks/openai-chatgpt.js +75 -0
  39. package/dist/bundle/chunks/{openai-codex-responses-SG7PGUUZ.js → openai-codex-responses-FUE7WESF.js} +2 -2
  40. package/dist/bundle/chunks/openai-codex.js +2 -2
  41. package/dist/bundle/chunks/{openai-completions-OBX42CLD.js → openai-completions-XW2Q5HVC.js} +2 -2
  42. package/dist/bundle/chunks/openai-responses-ZUXFVYPI.js +3 -0
  43. package/dist/bundle/chunks/{openrouter-images-N4XVVFSD.js → openrouter-images-TPQ4V6OR.js} +1 -1
  44. package/dist/bundle/chunks/openrouter.js +2 -2
  45. package/dist/bundle/chunks/{pi-messages-GFKBWJHZ.js → pi-messages-TM5SOOIW.js} +2 -2
  46. package/dist/bundle/chunks/radius.js +2 -2
  47. package/dist/bundle/chunks/runtime-6ZC4MGWD.js +2 -0
  48. package/dist/bundle/chunks/typesafe-system-one-E7A4HNJI.js +2 -0
  49. package/dist/bundle/chunks/virtual-modules-H7OCXN6W.js +2 -0
  50. package/dist/bundle/cli-runtime.js +1 -1
  51. package/dist/bundle/index.js +1 -1
  52. package/dist/bundle/rpc-entry.js +1 -1
  53. package/dist/cli/args.d.ts.map +1 -1
  54. package/dist/cli/args.js +4 -3
  55. package/dist/cli/args.js.map +1 -1
  56. package/dist/cli/auth-check.d.ts.map +1 -1
  57. package/dist/cli/auth-check.js.map +1 -1
  58. package/dist/cli/auth-command.d.ts.map +1 -1
  59. package/dist/cli/auth-command.js.map +1 -1
  60. package/dist/cli/config-selector.d.ts.map +1 -1
  61. package/dist/cli/config-selector.js.map +1 -1
  62. package/dist/cli/credential-print.d.ts.map +1 -1
  63. package/dist/cli/credential-print.js.map +1 -1
  64. package/dist/cli/file-processor.d.ts.map +1 -1
  65. package/dist/cli/file-processor.js.map +1 -1
  66. package/dist/cli/initial-message.d.ts +1 -1
  67. package/dist/cli/initial-message.d.ts.map +1 -1
  68. package/dist/cli/initial-message.js.map +1 -1
  69. package/dist/cli/list-models.d.ts.map +1 -1
  70. package/dist/cli/list-models.js.map +1 -1
  71. package/dist/cli/project-trust.d.ts.map +1 -1
  72. package/dist/cli/project-trust.js.map +1 -1
  73. package/dist/cli/session-picker.d.ts.map +1 -1
  74. package/dist/cli/session-picker.js.map +1 -1
  75. package/dist/cli/setup.d.ts.map +1 -1
  76. package/dist/cli/setup.js.map +1 -1
  77. package/dist/cli/startup-ui.d.ts.map +1 -1
  78. package/dist/cli/startup-ui.js +38 -30
  79. package/dist/cli/startup-ui.js.map +1 -1
  80. package/dist/cli.d.ts.map +1 -1
  81. package/dist/config.d.ts +18 -4
  82. package/dist/config.d.ts.map +1 -1
  83. package/dist/config.js +30 -4
  84. package/dist/config.js.map +1 -1
  85. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  86. package/dist/core/agent-session-runtime.js +1 -1
  87. package/dist/core/agent-session-runtime.js.map +1 -1
  88. package/dist/core/agent-session-services.d.ts.map +1 -1
  89. package/dist/core/agent-session-services.js +13 -0
  90. package/dist/core/agent-session-services.js.map +1 -1
  91. package/dist/core/agent-session.d.ts +118 -11
  92. package/dist/core/agent-session.d.ts.map +1 -1
  93. package/dist/core/agent-session.js +548 -288
  94. package/dist/core/agent-session.js.map +1 -1
  95. package/dist/core/auth-guidance.d.ts.map +1 -1
  96. package/dist/core/auth-guidance.js.map +1 -1
  97. package/dist/core/auth-storage.d.ts.map +1 -1
  98. package/dist/core/auth-storage.js.map +1 -1
  99. package/dist/core/bash-executor.d.ts.map +1 -1
  100. package/dist/core/bash-executor.js.map +1 -1
  101. package/dist/core/bug-report-upload.d.ts.map +1 -1
  102. package/dist/core/bug-report-upload.js.map +1 -1
  103. package/dist/core/bug-report.d.ts +1 -1
  104. package/dist/core/bug-report.d.ts.map +1 -1
  105. package/dist/core/bug-report.js +1 -1
  106. package/dist/core/bug-report.js.map +1 -1
  107. package/dist/core/cache-stats.d.ts.map +1 -1
  108. package/dist/core/cache-stats.js.map +1 -1
  109. package/dist/core/cache-warmer.d.ts.map +1 -1
  110. package/dist/core/cache-warmer.js.map +1 -1
  111. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  112. package/dist/core/compaction/branch-summarization.js.map +1 -1
  113. package/dist/core/compaction/compaction.d.ts.map +1 -1
  114. package/dist/core/compaction/compaction.js +1 -22
  115. package/dist/core/compaction/compaction.js.map +1 -1
  116. package/dist/core/compaction/index.d.ts.map +1 -1
  117. package/dist/core/compaction/utils.d.ts +2 -1
  118. package/dist/core/compaction/utils.d.ts.map +1 -1
  119. package/dist/core/compaction/utils.js +25 -18
  120. package/dist/core/compaction/utils.js.map +1 -1
  121. package/dist/core/crash-log.d.ts.map +1 -1
  122. package/dist/core/crash-log.js +2 -1
  123. package/dist/core/crash-log.js.map +1 -1
  124. package/dist/core/defaults.d.ts.map +1 -1
  125. package/dist/core/diagnostics.d.ts.map +1 -1
  126. package/dist/core/event-bus.d.ts.map +1 -1
  127. package/dist/core/event-bus.js.map +1 -1
  128. package/dist/core/exec.d.ts.map +1 -1
  129. package/dist/core/exec.js.map +1 -1
  130. package/dist/core/experimental.d.ts.map +1 -1
  131. package/dist/core/experimental.js.map +1 -1
  132. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  133. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  134. package/dist/core/export-html/index.d.ts.map +1 -1
  135. package/dist/core/export-html/index.js.map +1 -1
  136. package/dist/core/export-html/template.css +10 -0
  137. package/dist/core/export-html/template.js +66 -17
  138. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  139. package/dist/core/export-html/tool-renderer.js.map +1 -1
  140. package/dist/core/extensions/index.d.ts +1 -1
  141. package/dist/core/extensions/index.d.ts.map +1 -1
  142. package/dist/core/extensions/index.js.map +1 -1
  143. package/dist/core/extensions/jiti-loader.d.ts.map +1 -1
  144. package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -1
  145. package/dist/core/extensions/loader.d.ts.map +1 -1
  146. package/dist/core/extensions/loader.js +55 -5
  147. package/dist/core/extensions/loader.js.map +1 -1
  148. package/dist/core/extensions/runner.d.ts +18 -1
  149. package/dist/core/extensions/runner.d.ts.map +1 -1
  150. package/dist/core/extensions/runner.js +99 -0
  151. package/dist/core/extensions/runner.js.map +1 -1
  152. package/dist/core/extensions/types.d.ts +296 -22
  153. package/dist/core/extensions/types.d.ts.map +1 -1
  154. package/dist/core/extensions/types.js.map +1 -1
  155. package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
  156. package/dist/core/extensions/wrapper.d.ts +2 -2
  157. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  158. package/dist/core/extensions/wrapper.js +3 -3
  159. package/dist/core/extensions/wrapper.js.map +1 -1
  160. package/dist/core/footer-data-provider.d.ts.map +1 -1
  161. package/dist/core/footer-data-provider.js.map +1 -1
  162. package/dist/core/http-dispatcher.d.ts.map +1 -1
  163. package/dist/core/http-dispatcher.js.map +1 -1
  164. package/dist/core/index.d.ts.map +1 -1
  165. package/dist/core/keybindings.d.ts +1 -1
  166. package/dist/core/keybindings.d.ts.map +1 -1
  167. package/dist/core/keybindings.js +1 -1
  168. package/dist/core/keybindings.js.map +1 -1
  169. package/dist/core/mcp-servers.d.ts +98 -0
  170. package/dist/core/mcp-servers.d.ts.map +1 -0
  171. package/dist/core/mcp-servers.js +157 -0
  172. package/dist/core/mcp-servers.js.map +1 -0
  173. package/dist/core/messages.d.ts.map +1 -1
  174. package/dist/core/messages.js.map +1 -1
  175. package/dist/core/model-config.d.ts.map +1 -1
  176. package/dist/core/model-config.js.map +1 -1
  177. package/dist/core/model-registry.d.ts +13 -1
  178. package/dist/core/model-registry.d.ts.map +1 -1
  179. package/dist/core/model-registry.js +25 -0
  180. package/dist/core/model-registry.js.map +1 -1
  181. package/dist/core/model-resolver.d.ts +2 -2
  182. package/dist/core/model-resolver.d.ts.map +1 -1
  183. package/dist/core/model-resolver.js +5 -5
  184. package/dist/core/model-resolver.js.map +1 -1
  185. package/dist/core/model-runtime.d.ts +41 -3
  186. package/dist/core/model-runtime.d.ts.map +1 -1
  187. package/dist/core/model-runtime.js +167 -17
  188. package/dist/core/model-runtime.js.map +1 -1
  189. package/dist/core/models-store.d.ts.map +1 -1
  190. package/dist/core/models-store.js.map +1 -1
  191. package/dist/core/nested-tool-calls.d.ts +102 -0
  192. package/dist/core/nested-tool-calls.d.ts.map +1 -0
  193. package/dist/core/nested-tool-calls.js +178 -0
  194. package/dist/core/nested-tool-calls.js.map +1 -0
  195. package/dist/core/output-guard.d.ts.map +1 -1
  196. package/dist/core/output-guard.js.map +1 -1
  197. package/dist/core/package-manager.d.ts +4 -0
  198. package/dist/core/package-manager.d.ts.map +1 -1
  199. package/dist/core/package-manager.js +59 -12
  200. package/dist/core/package-manager.js.map +1 -1
  201. package/dist/core/pi-client-cli-adapter.d.ts.map +1 -1
  202. package/dist/core/pi-client-cli-adapter.js.map +1 -1
  203. package/dist/core/pi-client-runtime-update.d.ts.map +1 -1
  204. package/dist/core/pi-client-runtime-update.js.map +1 -1
  205. package/dist/core/pi-manifest.d.ts.map +1 -1
  206. package/dist/core/pi-manifest.js.map +1 -1
  207. package/dist/core/pi-server-client.d.ts.map +1 -1
  208. package/dist/core/pi-server-client.js.map +1 -1
  209. package/dist/core/pi-server-protocol.d.ts.map +1 -1
  210. package/dist/core/pi-server-protocol.js.map +1 -1
  211. package/dist/core/pi-server-request.d.ts.map +1 -1
  212. package/dist/core/pi-server-request.js.map +1 -1
  213. package/dist/core/project-trust.d.ts.map +1 -1
  214. package/dist/core/project-trust.js.map +1 -1
  215. package/dist/core/prompt-templates.d.ts.map +1 -1
  216. package/dist/core/prompt-templates.js.map +1 -1
  217. package/dist/core/provider-attribution.d.ts.map +1 -1
  218. package/dist/core/provider-attribution.js.map +1 -1
  219. package/dist/core/provider-composer.d.ts +40 -21
  220. package/dist/core/provider-composer.d.ts.map +1 -1
  221. package/dist/core/provider-composer.js +92 -40
  222. package/dist/core/provider-composer.js.map +1 -1
  223. package/dist/core/radius.d.ts.map +1 -1
  224. package/dist/core/radius.js.map +1 -1
  225. package/dist/core/remote-catalog-provider.d.ts +8 -1
  226. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  227. package/dist/core/remote-catalog-provider.js +18 -3
  228. package/dist/core/remote-catalog-provider.js.map +1 -1
  229. package/dist/core/resolve-config-value.d.ts.map +1 -1
  230. package/dist/core/resolve-config-value.js.map +1 -1
  231. package/dist/core/resource-loader.d.ts +7 -1
  232. package/dist/core/resource-loader.d.ts.map +1 -1
  233. package/dist/core/resource-loader.js +161 -35
  234. package/dist/core/resource-loader.js.map +1 -1
  235. package/dist/core/runtime-credentials.d.ts.map +1 -1
  236. package/dist/core/runtime-credentials.js.map +1 -1
  237. package/dist/core/sdk.d.ts +1 -1
  238. package/dist/core/sdk.d.ts.map +1 -1
  239. package/dist/core/sdk.js +24 -6
  240. package/dist/core/sdk.js.map +1 -1
  241. package/dist/core/session-cwd.d.ts.map +1 -1
  242. package/dist/core/session-cwd.js.map +1 -1
  243. package/dist/core/session-export.d.ts.map +1 -1
  244. package/dist/core/session-export.js.map +1 -1
  245. package/dist/core/session-manager.d.ts +9 -0
  246. package/dist/core/session-manager.d.ts.map +1 -1
  247. package/dist/core/session-manager.js +22 -22
  248. package/dist/core/session-manager.js.map +1 -1
  249. package/dist/core/settings-diagnostics.d.ts.map +1 -1
  250. package/dist/core/settings-diagnostics.js.map +1 -1
  251. package/dist/core/settings-manager.d.ts +31 -1
  252. package/dist/core/settings-manager.d.ts.map +1 -1
  253. package/dist/core/settings-manager.js +72 -2
  254. package/dist/core/settings-manager.js.map +1 -1
  255. package/dist/core/skills.d.ts.map +1 -1
  256. package/dist/core/skills.js.map +1 -1
  257. package/dist/core/slash-commands.d.ts.map +1 -1
  258. package/dist/core/source-info.d.ts +8 -0
  259. package/dist/core/source-info.d.ts.map +1 -1
  260. package/dist/core/source-info.js +16 -0
  261. package/dist/core/source-info.js.map +1 -1
  262. package/dist/core/system-prompt.d.ts.map +1 -1
  263. package/dist/core/system-prompt.js +1 -1
  264. package/dist/core/system-prompt.js.map +1 -1
  265. package/dist/core/telemetry.d.ts.map +1 -1
  266. package/dist/core/telemetry.js.map +1 -1
  267. package/dist/core/timings.d.ts.map +1 -1
  268. package/dist/core/timings.js.map +1 -1
  269. package/dist/core/tools/bash.d.ts +12 -0
  270. package/dist/core/tools/bash.d.ts.map +1 -1
  271. package/dist/core/tools/bash.js +35 -2
  272. package/dist/core/tools/bash.js.map +1 -1
  273. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  274. package/dist/core/tools/edit-diff.js.map +1 -1
  275. package/dist/core/tools/edit.d.ts.map +1 -1
  276. package/dist/core/tools/edit.js.map +1 -1
  277. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  278. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  279. package/dist/core/tools/find.d.ts.map +1 -1
  280. package/dist/core/tools/find.js.map +1 -1
  281. package/dist/core/tools/grep.d.ts.map +1 -1
  282. package/dist/core/tools/grep.js.map +1 -1
  283. package/dist/core/tools/index.d.ts.map +1 -1
  284. package/dist/core/tools/index.js.map +1 -1
  285. package/dist/core/tools/ls.d.ts.map +1 -1
  286. package/dist/core/tools/ls.js.map +1 -1
  287. package/dist/core/tools/output-accumulator.d.ts +11 -0
  288. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  289. package/dist/core/tools/output-accumulator.js +36 -0
  290. package/dist/core/tools/output-accumulator.js.map +1 -1
  291. package/dist/core/tools/path-utils.d.ts.map +1 -1
  292. package/dist/core/tools/path-utils.js.map +1 -1
  293. package/dist/core/tools/powershell.d.ts.map +1 -1
  294. package/dist/core/tools/powershell.js.map +1 -1
  295. package/dist/core/tools/read.d.ts.map +1 -1
  296. package/dist/core/tools/read.js.map +1 -1
  297. package/dist/core/tools/render-utils.d.ts +6 -0
  298. package/dist/core/tools/render-utils.d.ts.map +1 -1
  299. package/dist/core/tools/render-utils.js +26 -0
  300. package/dist/core/tools/render-utils.js.map +1 -1
  301. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  302. package/dist/core/tools/renderers/bash.js +9 -10
  303. package/dist/core/tools/renderers/bash.js.map +1 -1
  304. package/dist/core/tools/renderers/edit.d.ts.map +1 -1
  305. package/dist/core/tools/renderers/edit.js.map +1 -1
  306. package/dist/core/tools/renderers/find.d.ts.map +1 -1
  307. package/dist/core/tools/renderers/find.js.map +1 -1
  308. package/dist/core/tools/renderers/grep.d.ts.map +1 -1
  309. package/dist/core/tools/renderers/grep.js.map +1 -1
  310. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  311. package/dist/core/tools/renderers/index.js.map +1 -1
  312. package/dist/core/tools/renderers/ls.d.ts.map +1 -1
  313. package/dist/core/tools/renderers/ls.js.map +1 -1
  314. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  315. package/dist/core/tools/renderers/read.js +3 -2
  316. package/dist/core/tools/renderers/read.js.map +1 -1
  317. package/dist/core/tools/renderers/write.d.ts.map +1 -1
  318. package/dist/core/tools/renderers/write.js.map +1 -1
  319. package/dist/core/tools/tool-definition-wrapper.d.ts +5 -3
  320. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  321. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  322. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  323. package/dist/core/tools/truncate.d.ts +14 -0
  324. package/dist/core/tools/truncate.d.ts.map +1 -1
  325. package/dist/core/tools/truncate.js +29 -0
  326. package/dist/core/tools/truncate.js.map +1 -1
  327. package/dist/core/tools/write.d.ts.map +1 -1
  328. package/dist/core/tools/write.js.map +1 -1
  329. package/dist/core/trust-manager.d.ts.map +1 -1
  330. package/dist/core/trust-manager.js +1 -0
  331. package/dist/core/trust-manager.js.map +1 -1
  332. package/dist/core/usage-totals.d.ts +2 -0
  333. package/dist/core/usage-totals.d.ts.map +1 -1
  334. package/dist/core/usage-totals.js +23 -0
  335. package/dist/core/usage-totals.js.map +1 -1
  336. package/dist/core/virtual-models.d.ts +115 -0
  337. package/dist/core/virtual-models.d.ts.map +1 -0
  338. package/dist/core/virtual-models.js +117 -0
  339. package/dist/core/virtual-models.js.map +1 -0
  340. package/dist/extensions/codemode/execute.d.ts +16 -0
  341. package/dist/extensions/codemode/execute.d.ts.map +1 -0
  342. package/dist/extensions/codemode/execute.js +390 -0
  343. package/dist/extensions/codemode/execute.js.map +1 -0
  344. package/dist/extensions/codemode/execute.lazy.d.ts +3 -0
  345. package/dist/extensions/codemode/execute.lazy.d.ts.map +1 -0
  346. package/dist/extensions/codemode/execute.lazy.js +3 -0
  347. package/dist/extensions/codemode/execute.lazy.js.map +1 -0
  348. package/dist/extensions/codemode/index.d.ts +21 -0
  349. package/dist/extensions/codemode/index.d.ts.map +1 -0
  350. package/dist/extensions/codemode/index.js +31 -0
  351. package/dist/extensions/codemode/index.js.map +1 -0
  352. package/dist/extensions/codemode/renderer.d.ts +12 -0
  353. package/dist/extensions/codemode/renderer.d.ts.map +1 -0
  354. package/dist/extensions/codemode/renderer.js +119 -0
  355. package/dist/extensions/codemode/renderer.js.map +1 -0
  356. package/dist/extensions/codemode/tool.d.ts +122 -0
  357. package/dist/extensions/codemode/tool.d.ts.map +1 -0
  358. package/dist/extensions/codemode/tool.js +324 -0
  359. package/dist/extensions/codemode/tool.js.map +1 -0
  360. package/dist/extensions/codemode/worker.d.ts +7 -0
  361. package/dist/extensions/codemode/worker.d.ts.map +1 -0
  362. package/dist/extensions/codemode/worker.js +7 -0
  363. package/dist/extensions/codemode/worker.js.map +1 -0
  364. package/dist/extensions/index.d.ts.map +1 -1
  365. package/dist/extensions/index.js +11 -1
  366. package/dist/extensions/index.js.map +1 -1
  367. package/dist/extensions/llama/client.d.ts.map +1 -1
  368. package/dist/extensions/llama/client.js.map +1 -1
  369. package/dist/extensions/llama/huggingface.d.ts.map +1 -1
  370. package/dist/extensions/llama/huggingface.js.map +1 -1
  371. package/dist/extensions/llama/index.d.ts.map +1 -1
  372. package/dist/extensions/llama/index.js.map +1 -1
  373. package/dist/extensions/llama/provider.d.ts +1 -1
  374. package/dist/extensions/llama/provider.d.ts.map +1 -1
  375. package/dist/extensions/llama/provider.js +65 -13
  376. package/dist/extensions/llama/provider.js.map +1 -1
  377. package/dist/extensions/llama/ui.d.ts.map +1 -1
  378. package/dist/extensions/llama/ui.js.map +1 -1
  379. package/dist/extensions/mcp/cli.d.ts +21 -0
  380. package/dist/extensions/mcp/cli.d.ts.map +1 -0
  381. package/dist/extensions/mcp/cli.js +485 -0
  382. package/dist/extensions/mcp/cli.js.map +1 -0
  383. package/dist/extensions/mcp/cli.lazy.d.ts +3 -0
  384. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -0
  385. package/dist/extensions/mcp/cli.lazy.js +3 -0
  386. package/dist/extensions/mcp/cli.lazy.js.map +1 -0
  387. package/dist/extensions/mcp/config.d.ts +70 -0
  388. package/dist/extensions/mcp/config.d.ts.map +1 -0
  389. package/dist/extensions/mcp/config.js +146 -0
  390. package/dist/extensions/mcp/config.js.map +1 -0
  391. package/dist/extensions/mcp/index.d.ts +52 -0
  392. package/dist/extensions/mcp/index.d.ts.map +1 -0
  393. package/dist/extensions/mcp/index.js +902 -0
  394. package/dist/extensions/mcp/index.js.map +1 -0
  395. package/dist/extensions/mcp/log.d.ts +16 -0
  396. package/dist/extensions/mcp/log.d.ts.map +1 -0
  397. package/dist/extensions/mcp/log.js +66 -0
  398. package/dist/extensions/mcp/log.js.map +1 -0
  399. package/dist/extensions/mcp/oauth.d.ts +94 -0
  400. package/dist/extensions/mcp/oauth.d.ts.map +1 -0
  401. package/dist/extensions/mcp/oauth.js +333 -0
  402. package/dist/extensions/mcp/oauth.js.map +1 -0
  403. package/dist/extensions/mcp/resources.d.ts +43 -0
  404. package/dist/extensions/mcp/resources.d.ts.map +1 -0
  405. package/dist/extensions/mcp/resources.js +262 -0
  406. package/dist/extensions/mcp/resources.js.map +1 -0
  407. package/dist/extensions/mcp/runtime.d.ts +96 -0
  408. package/dist/extensions/mcp/runtime.d.ts.map +1 -0
  409. package/dist/extensions/mcp/runtime.js +388 -0
  410. package/dist/extensions/mcp/runtime.js.map +1 -0
  411. package/dist/extensions/mcp/runtime.lazy.d.ts +3 -0
  412. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -0
  413. package/dist/extensions/mcp/runtime.lazy.js +3 -0
  414. package/dist/extensions/mcp/runtime.lazy.js.map +1 -0
  415. package/dist/extensions/mcp/tools.d.ts +83 -0
  416. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  417. package/dist/extensions/mcp/tools.js +233 -0
  418. package/dist/extensions/mcp/tools.js.map +1 -0
  419. package/dist/extensions/mcp/ui.d.ts +60 -0
  420. package/dist/extensions/mcp/ui.d.ts.map +1 -0
  421. package/dist/extensions/mcp/ui.js +172 -0
  422. package/dist/extensions/mcp/ui.js.map +1 -0
  423. package/dist/extensions/tool-search/index.d.ts +12 -0
  424. package/dist/extensions/tool-search/index.d.ts.map +1 -0
  425. package/dist/extensions/tool-search/index.js +15 -0
  426. package/dist/extensions/tool-search/index.js.map +1 -0
  427. package/dist/extensions/tool-search/tool.d.ts +72 -0
  428. package/dist/extensions/tool-search/tool.d.ts.map +1 -0
  429. package/dist/extensions/tool-search/tool.js +210 -0
  430. package/dist/extensions/tool-search/tool.js.map +1 -0
  431. package/dist/index.d.ts +9 -2
  432. package/dist/index.d.ts.map +1 -1
  433. package/dist/index.js +5 -0
  434. package/dist/index.js.map +1 -1
  435. package/dist/main.d.ts.map +1 -1
  436. package/dist/main.js +10 -0
  437. package/dist/main.js.map +1 -1
  438. package/dist/migrations.d.ts.map +1 -1
  439. package/dist/migrations.js.map +1 -1
  440. package/dist/modes/index.d.ts.map +1 -1
  441. package/dist/modes/interactive/bug-report.d.ts.map +1 -1
  442. package/dist/modes/interactive/bug-report.js.map +1 -1
  443. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
  444. package/dist/modes/interactive/chat-viewport.js.map +1 -1
  445. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  446. package/dist/modes/interactive/components/armin.js.map +1 -1
  447. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  448. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  449. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  450. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  451. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  452. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  453. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  454. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  455. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  456. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  457. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  458. package/dist/modes/interactive/components/config-selector.js +13 -3
  459. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  460. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  461. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  462. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  463. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  464. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  465. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  466. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  467. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  468. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  469. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  470. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  471. package/dist/modes/interactive/components/diff.js.map +1 -1
  472. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  473. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  474. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  475. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  476. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  477. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  478. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  479. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  480. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  481. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  482. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  483. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  484. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  485. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  486. package/dist/modes/interactive/components/footer.d.ts +7 -0
  487. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  488. package/dist/modes/interactive/components/footer.js +43 -3
  489. package/dist/modes/interactive/components/footer.js.map +1 -1
  490. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  491. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  492. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  493. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  494. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  495. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  496. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  497. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  498. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  499. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  500. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  501. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  502. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  503. package/dist/modes/interactive/components/pi-logo.d.ts +12 -0
  504. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -0
  505. package/dist/modes/interactive/components/pi-logo.js +25 -0
  506. package/dist/modes/interactive/components/pi-logo.js.map +1 -0
  507. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  508. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  509. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  510. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  511. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  512. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  513. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  514. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  515. package/dist/modes/interactive/components/settings-selector.js +28 -6
  516. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  517. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  518. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  519. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  520. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  521. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  522. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  523. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  524. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  525. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  526. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  527. package/dist/modes/interactive/components/themed-text.d.ts +17 -0
  528. package/dist/modes/interactive/components/themed-text.d.ts.map +1 -0
  529. package/dist/modes/interactive/components/themed-text.js +29 -0
  530. package/dist/modes/interactive/components/themed-text.js.map +1 -0
  531. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  532. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  533. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  534. package/dist/modes/interactive/components/tool-execution.js +2 -2
  535. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  536. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  537. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  538. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  539. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  540. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  541. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  542. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  543. package/dist/modes/interactive/components/user-message.js.map +1 -1
  544. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  545. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  546. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  547. package/dist/modes/interactive/external-editor.js.map +1 -1
  548. package/dist/modes/interactive/interactive-mode.d.ts +11 -0
  549. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  550. package/dist/modes/interactive/interactive-mode.js +199 -161
  551. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  552. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -1
  553. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -1
  554. package/dist/modes/interactive/model-search.d.ts.map +1 -1
  555. package/dist/modes/interactive/model-search.js.map +1 -1
  556. package/dist/modes/interactive/session-share.d.ts.map +1 -1
  557. package/dist/modes/interactive/session-share.js.map +1 -1
  558. package/dist/modes/interactive/theme/dark.json +59 -72
  559. package/dist/modes/interactive/theme/light.json +57 -69
  560. package/dist/modes/interactive/theme/system-theme.d.ts +54 -0
  561. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
  562. package/dist/modes/interactive/theme/system-theme.js +535 -0
  563. package/dist/modes/interactive/theme/system-theme.js.map +1 -0
  564. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  565. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  566. package/dist/modes/interactive/theme/theme-controller.js +127 -47
  567. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  568. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  569. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -1
  570. package/dist/modes/interactive/theme/theme-json.js +3 -1
  571. package/dist/modes/interactive/theme/theme-json.js.map +1 -1
  572. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  573. package/dist/modes/interactive/theme/theme.d.ts +66 -39
  574. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  575. package/dist/modes/interactive/theme/theme.js +238 -317
  576. package/dist/modes/interactive/theme/theme.js.map +1 -1
  577. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  578. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  579. package/dist/modes/interactive/tui-renderer.js +1 -0
  580. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  581. package/dist/modes/json-event.d.ts.map +1 -1
  582. package/dist/modes/json-event.js.map +1 -1
  583. package/dist/modes/print-mode.d.ts.map +1 -1
  584. package/dist/modes/print-mode.js.map +1 -1
  585. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  586. package/dist/modes/rpc/jsonl.js.map +1 -1
  587. package/dist/modes/rpc/rpc-client.d.ts +6 -6
  588. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  589. package/dist/modes/rpc/rpc-client.js +12 -8
  590. package/dist/modes/rpc/rpc-client.js.map +1 -1
  591. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  592. package/dist/modes/rpc/rpc-mode.js +7 -9
  593. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  594. package/dist/modes/rpc/rpc-types.d.ts +10 -1
  595. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  596. package/dist/modes/rpc/rpc-types.js.map +1 -1
  597. package/dist/package-manager-cli.d.ts.map +1 -1
  598. package/dist/package-manager-cli.js +6 -2
  599. package/dist/package-manager-cli.js.map +1 -1
  600. package/dist/pi-client-cli.d.ts.map +1 -1
  601. package/dist/pi-client-cli.js.map +1 -1
  602. package/dist/rpc-entry.d.ts.map +1 -1
  603. package/dist/rpc-entry.js.map +1 -1
  604. package/dist/utils/abort.d.ts.map +1 -1
  605. package/dist/utils/abort.js.map +1 -1
  606. package/dist/utils/ansi.d.ts.map +1 -1
  607. package/dist/utils/ansi.js.map +1 -1
  608. package/dist/utils/changelog.d.ts.map +1 -1
  609. package/dist/utils/changelog.js.map +1 -1
  610. package/dist/utils/child-process.d.ts.map +1 -1
  611. package/dist/utils/child-process.js.map +1 -1
  612. package/dist/utils/clipboard-command.d.ts.map +1 -1
  613. package/dist/utils/clipboard-command.js.map +1 -1
  614. package/dist/utils/clipboard-image.d.ts.map +1 -1
  615. package/dist/utils/clipboard-image.js +14 -17
  616. package/dist/utils/clipboard-image.js.map +1 -1
  617. package/dist/utils/clipboard.d.ts +2 -0
  618. package/dist/utils/clipboard.d.ts.map +1 -1
  619. package/dist/utils/clipboard.js +5 -0
  620. package/dist/utils/clipboard.js.map +1 -1
  621. package/dist/utils/deprecation.d.ts.map +1 -1
  622. package/dist/utils/deprecation.js.map +1 -1
  623. package/dist/utils/exif-orientation.d.ts.map +1 -1
  624. package/dist/utils/exif-orientation.js.map +1 -1
  625. package/dist/utils/frontmatter.d.ts.map +1 -1
  626. package/dist/utils/frontmatter.js.map +1 -1
  627. package/dist/utils/fs-watch.d.ts.map +1 -1
  628. package/dist/utils/fs-watch.js.map +1 -1
  629. package/dist/utils/git.d.ts.map +1 -1
  630. package/dist/utils/git.js.map +1 -1
  631. package/dist/utils/html.d.ts.map +1 -1
  632. package/dist/utils/html.js.map +1 -1
  633. package/dist/utils/image-convert.d.ts.map +1 -1
  634. package/dist/utils/image-convert.js.map +1 -1
  635. package/dist/utils/image-process.d.ts.map +1 -1
  636. package/dist/utils/image-process.js.map +1 -1
  637. package/dist/utils/image-resize-core.d.ts.map +1 -1
  638. package/dist/utils/image-resize-core.js.map +1 -1
  639. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  640. package/dist/utils/image-resize-worker.js.map +1 -1
  641. package/dist/utils/image-resize.d.ts.map +1 -1
  642. package/dist/utils/image-resize.js.map +1 -1
  643. package/dist/utils/json.d.ts.map +1 -1
  644. package/dist/utils/json.js.map +1 -1
  645. package/dist/utils/management-http.d.ts.map +1 -1
  646. package/dist/utils/management-http.js.map +1 -1
  647. package/dist/utils/mime.d.ts.map +1 -1
  648. package/dist/utils/mime.js.map +1 -1
  649. package/dist/utils/open-browser.d.ts.map +1 -1
  650. package/dist/utils/open-browser.js.map +1 -1
  651. package/dist/utils/paths.d.ts +3 -3
  652. package/dist/utils/paths.d.ts.map +1 -1
  653. package/dist/utils/paths.js +5 -4
  654. package/dist/utils/paths.js.map +1 -1
  655. package/dist/utils/photon.d.ts.map +1 -1
  656. package/dist/utils/photon.js.map +1 -1
  657. package/dist/utils/pi-user-agent.d.ts.map +1 -1
  658. package/dist/utils/pi-user-agent.js.map +1 -1
  659. package/dist/utils/shell.d.ts +1 -3
  660. package/dist/utils/shell.d.ts.map +1 -1
  661. package/dist/utils/shell.js +3 -30
  662. package/dist/utils/shell.js.map +1 -1
  663. package/dist/utils/sleep.d.ts.map +1 -1
  664. package/dist/utils/sleep.js.map +1 -1
  665. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  666. package/dist/utils/syntax-highlight.js +2 -0
  667. package/dist/utils/syntax-highlight.js.map +1 -1
  668. package/dist/utils/text.d.ts.map +1 -1
  669. package/dist/utils/text.js.map +1 -1
  670. package/dist/utils/tool-result-images.d.ts.map +1 -1
  671. package/dist/utils/tool-result-images.js.map +1 -1
  672. package/dist/utils/tools-manager.d.ts.map +1 -1
  673. package/dist/utils/tools-manager.js.map +1 -1
  674. package/dist/utils/version-check.d.ts.map +1 -1
  675. package/dist/utils/version-check.js.map +1 -1
  676. package/dist/utils/windows-self-update.d.ts.map +1 -1
  677. package/dist/utils/windows-self-update.js.map +1 -1
  678. package/dist/utils/wsl.d.ts.map +1 -1
  679. package/dist/utils/wsl.js.map +1 -1
  680. package/dist/utils/zip.d.ts.map +1 -1
  681. package/dist/utils/zip.js.map +1 -1
  682. package/docs/cli.md +64 -3
  683. package/docs/configuration.md +2 -0
  684. package/docs/custom-provider.md +43 -4
  685. package/docs/docs.json +8 -0
  686. package/docs/extensions.md +55 -0
  687. package/docs/keybindings.md +1 -1
  688. package/docs/llama-cpp.md +13 -0
  689. package/docs/mcp.md +188 -0
  690. package/docs/models.md +35 -0
  691. package/docs/packages.md +4 -2
  692. package/docs/providers.md +1 -0
  693. package/docs/rpc-commands.md +9 -3
  694. package/docs/rpc.md +3 -1
  695. package/docs/sdk.md +7 -2
  696. package/docs/security.md +2 -0
  697. package/docs/session-format.md +5 -1
  698. package/docs/settings.md +20 -3
  699. package/docs/themes.md +33 -7
  700. package/docs/tui.md +18 -0
  701. package/docs/virtual-models.md +114 -0
  702. package/docs/windows.md +2 -0
  703. package/examples/README.md +1 -1
  704. package/examples/extensions/README.md +2 -0
  705. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  706. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  707. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  708. package/examples/extensions/custom-provider-gitlab-duo/test.ts +5 -5
  709. package/examples/extensions/debug-provider.ts +90 -0
  710. package/examples/extensions/gondolin/package-lock.json +2 -2
  711. package/examples/extensions/gondolin/package.json +1 -1
  712. package/examples/extensions/jev-router.ts +113 -0
  713. package/examples/extensions/sandbox/package-lock.json +2 -2
  714. package/examples/extensions/sandbox/package.json +1 -1
  715. package/examples/extensions/with-deps/package-lock.json +2 -2
  716. package/examples/extensions/with-deps/package.json +1 -1
  717. package/examples/rpc-client.ts +1 -1
  718. package/examples/rpc-extension-ui.ts +1 -1
  719. package/examples/sdk/14-codemode-mcp.ts +61 -0
  720. package/examples/sdk/README.md +2 -1
  721. package/package.json +14 -12
  722. package/dist/bundle/chunks/anthropic-messages-J5WXPPPC.js +0 -6
  723. package/dist/bundle/chunks/azure-openai-responses-QJ7SPP5M.js +0 -2
  724. package/dist/bundle/chunks/chunk-6R7UI4IY.js +0 -2
  725. package/dist/bundle/chunks/chunk-BZKWNWMI.js +0 -2
  726. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
  727. package/dist/bundle/chunks/chunk-RCZIEVGO.js +0 -11
  728. package/dist/bundle/chunks/chunk-X2F52Z34.js +0 -1685
  729. package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +0 -2
  730. package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +0 -2
  731. package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +0 -5
  732. package/dist/bundle/chunks/openai-responses-AH7QTG23.js +0 -2
  733. 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,18 @@ import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
33
34
  import { emitSessionShutdownEvent } from "./extensions/runner.js";
34
35
  import { convertToLlm } from "./messages.js";
35
36
  import { ModelRegistry } from "./model-registry.js";
37
+ import { NestedToolCallRunner } from "./nested-tool-calls.js";
36
38
  import { 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 { BUILTIN_PATH_PREFIX, createSyntheticSourceInfo, isSyntheticPath } from "./source-info.js";
41
43
  import { buildSystemPrompt, buildSystemPromptSections, diffSystemPromptSections, normalizeBuildSystemPromptOptions, } from "./system-prompt.js";
42
44
  import { createLocalBashOperations } from "./tools/bash.js";
43
45
  import { createAllToolDefinitions } from "./tools/index.js";
44
46
  import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
45
- import { addUsageToTotals, createUsageTotals } from "./usage-totals.js";
47
+ import { addUsageToTotals, combineUsage, createUsageTotals } from "./usage-totals.js";
48
+ import { findLatestResponse, getBranchSelection, getVirtualModelState, isVirtualModel, VIRTUAL_MODEL_STATE_ENTRY, } from "./virtual-models.js";
46
49
  /**
47
50
  * Parse a skill block from message text.
48
51
  * Returns null if the text doesn't contain a skill block.
@@ -203,6 +206,11 @@ export class AgentSession {
203
206
  // Retry state
204
207
  _retryAbortController = undefined;
205
208
  _retryAttempt = 0;
209
+ /**
210
+ * Failed response that the next request repeats, set by auto-retry and overflow recovery. The
211
+ * retry is routed with it as `failed`, since the context no longer contains it.
212
+ */
213
+ _failedResponse;
206
214
  // Post-turn session naming is a provider request too, so cancellation must reach it.
207
215
  _sessionNameAbortController = undefined;
208
216
  // Bash execution state
@@ -244,6 +252,10 @@ export class AgentSession {
244
252
  _cacheWarmer;
245
253
  // Tool registry for extension getTools/setTools
246
254
  _toolRegistry = new Map();
255
+ /** Created on the first `ctx.executeTool()` call. */
256
+ _nestedToolCalls;
257
+ /** Declared tools whose declarations requests leave out, from `prepareLoadout` hooks. */
258
+ _hiddenDeclarations = new Set();
247
259
  _toolDefinitions = new Map();
248
260
  _toolPromptSnippets = new Map();
249
261
  _toolPromptGuidelines = new Map();
@@ -280,6 +292,7 @@ export class AgentSession {
280
292
  this._installAgentNextTurnRefresh();
281
293
  this._installAgentRequestProjection();
282
294
  this._installAgentBoundaryHooks();
295
+ this._installHiddenDeclarationsProjection();
283
296
  this._installAgentForcedPromptProjection();
284
297
  this._buildRuntime({
285
298
  activeToolNames: this._initialActiveToolNames,
@@ -330,28 +343,71 @@ export class AgentSession {
330
343
  }
331
344
  throw new Error(formatNoApiKeyFoundMessage(model.provider));
332
345
  }
333
- async _getSummarizationRequestAuth(model, signal) {
346
+ async _getSummarizationRequestAuth(selectedModel, signal) {
347
+ // Route a virtual model first: summaries size their input and output from the model they get.
348
+ const { model, thinkingLevel } = isVirtualModel(selectedModel)
349
+ ? await this._modelRuntime.resolveModel(selectedModel, convertToLlm(this.messages), {
350
+ reason: "direct",
351
+ thinkingLevel: this.thinkingLevel,
352
+ signal,
353
+ })
354
+ : { model: selectedModel, thinkingLevel: this.thinkingLevel };
334
355
  if (this.agent.streamFunction === streamSimple) {
335
- return this._getRequiredRequestAuth(model, signal);
356
+ return { ...(await this._getRequiredRequestAuth(model, signal)), thinkingLevel };
336
357
  }
337
358
  try {
338
359
  const result = await this._modelRuntime.getAuth(model, { signal });
339
360
  if (!result)
340
- return { model };
361
+ return { model, thinkingLevel };
341
362
  const requestModel = result.auth.baseUrl ? { ...model, baseUrl: result.auth.baseUrl } : model;
342
363
  return {
343
364
  model: requestModel,
344
365
  apiKey: result.auth.apiKey,
345
366
  headers: withoutDeletedHeaders(result.auth.headers),
346
367
  env: result.env,
368
+ thinkingLevel,
347
369
  };
348
370
  }
349
371
  catch (error) {
350
372
  if (signal?.aborted)
351
373
  throw error;
352
- return { model };
374
+ return { model, thinkingLevel };
353
375
  }
354
376
  }
377
+ /**
378
+ * The model whose limits apply to `message`, or undefined when the message came from another
379
+ * model. Under a virtual selection, that is the physical model that produced it.
380
+ */
381
+ _modelForMessage(message) {
382
+ const model = this.model;
383
+ if (model && isVirtualModel(model))
384
+ return this._modelRuntime.getPhysicalModel(message.provider, message.model);
385
+ return model?.provider === message.provider && model.id === message.model ? model : undefined;
386
+ }
387
+ /**
388
+ * Record the selection on the current branch when the branch implies another one, so a resume
389
+ * restores it. Tree navigation can leave the latest `model_change` on another branch; responses
390
+ * cannot record a virtual selection because they name physical models. Responses do record a
391
+ * physical selection unless the branch holds a virtual one; checking a physical selection against
392
+ * responses would record it on every prompt while `prepareRequest` redirects to another model.
393
+ */
394
+ _recordSelection() {
395
+ const model = this.model;
396
+ if (!model)
397
+ return;
398
+ const getModel = (provider, modelId) => this._modelRuntime.getModel(provider, modelId);
399
+ const recorded = getBranchSelection(this.sessionManager.getBranch(), getModel);
400
+ if (!recorded || (recorded.provider === model.provider && recorded.modelId === model.id))
401
+ return;
402
+ const recordedModel = getModel(recorded.provider, recorded.modelId);
403
+ if (!isVirtualModel(model) && !(recordedModel && isVirtualModel(recordedModel)))
404
+ return;
405
+ this.sessionManager.appendModelChange(model.provider, model.id);
406
+ }
407
+ /** The model whose limits apply to the conversation. */
408
+ _limitsModel() {
409
+ return this.routedModel?.model ?? this.model;
410
+ }
355
411
  /**
356
412
  * Install tool hooks once on the Agent instance.
357
413
  *
@@ -361,67 +417,114 @@ export class AgentSession {
361
417
  * happens here instead of in wrappers.
362
418
  */
363
419
  _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 } : {}),
420
+ this.agent.beforeToolCall = (context) => this._beforeToolCall(context);
421
+ this.agent.afterToolCall = (context) => this._afterToolCall(context);
422
+ }
423
+ /** `tool_call` handlers. `parentToolCallId` is set for calls another tool made. */
424
+ async _beforeToolCall({ toolCall, args }, parentToolCallId) {
425
+ const runner = this._extensionRunner;
426
+ if (!runner.hasHandlers("tool_call")) {
427
+ return undefined;
428
+ }
429
+ try {
430
+ return await runner.emitToolCall({
431
+ type: "tool_call",
432
+ toolName: toolCall.name,
433
+ toolCallId: toolCall.id,
434
+ ...(parentToolCallId ? { parentToolCallId } : {}),
435
+ input: args,
404
436
  });
405
- if (!hookResult && normalizedContent === content) {
406
- return undefined;
437
+ }
438
+ catch (err) {
439
+ if (err instanceof Error) {
440
+ throw err;
407
441
  }
408
- return {
409
- content: normalizedContent,
410
- details: hookResult?.details,
411
- isError: hookResult?.isError ?? isError,
412
- usage: hookResult?.usage,
413
- };
442
+ throw new Error(`Extension failed, blocking execution: ${String(err)}`);
443
+ }
444
+ }
445
+ /** `tool_result` handlers and image normalization. `parentToolCallId` is set for calls another tool made. */
446
+ async _afterToolCall({ toolCall, args, result, isError }, parentToolCallId) {
447
+ const runner = this._extensionRunner;
448
+ const hookResult = runner.hasHandlers("tool_result")
449
+ ? await runner.emitToolResult({
450
+ type: "tool_result",
451
+ toolName: toolCall.name,
452
+ toolCallId: toolCall.id,
453
+ ...(parentToolCallId ? { parentToolCallId } : {}),
454
+ input: args,
455
+ content: result.content,
456
+ details: result.details,
457
+ ...(result.structuredContent === undefined ? {} : { structuredContent: result.structuredContent }),
458
+ isError,
459
+ usage: result.usage,
460
+ })
461
+ : undefined;
462
+ const content = hookResult?.content ?? result.content ?? [];
463
+ // Runs after the extension hook so images injected or replaced by extensions are normalized too.
464
+ const resizeOptions = this._limitsModel()?.inputLimits?.images?.resize;
465
+ const normalizedContent = await normalizeToolResultImages(content, {
466
+ autoResizeImages: this.settingsManager.getImageAutoResize(),
467
+ ...(resizeOptions ? { resizeOptions } : {}),
468
+ });
469
+ if (!hookResult && normalizedContent === content) {
470
+ return undefined;
471
+ }
472
+ // The hook result already dropped structured content that replaced content no longer matches.
473
+ return {
474
+ content: normalizedContent,
475
+ details: hookResult?.details,
476
+ structuredContent: hookResult ? hookResult.structuredContent : result.structuredContent,
477
+ isError: hookResult?.isError ?? isError,
478
+ usage: hookResult?.usage,
414
479
  };
415
480
  }
481
+ /**
482
+ * Run a call that the tool call `parentToolCallId` made through `ctx.executeTool()`. It goes
483
+ * through the agent's tool pipeline with the session's hooks, against the callable tools.
484
+ */
485
+ async _executeNestedToolCall(parentToolCallId, name, args, options) {
486
+ this._nestedToolCalls ??= new NestedToolCallRunner({
487
+ getTools: () => this._getCallableTools(),
488
+ isSequential: () => this.agent.toolExecution === "sequential",
489
+ runToolCall: (toolCall, parentId, signal, onUpdate) => {
490
+ const assistantMessage = this._findLastAssistantMessage();
491
+ if (!assistantMessage) {
492
+ return Promise.resolve({
493
+ toolCall,
494
+ result: { content: [{ type: "text", text: "No assistant message issued this call" }], details: {} },
495
+ isError: true,
496
+ });
497
+ }
498
+ return runToolCall(toolCall, {
499
+ tools: this._getCallableTools(),
500
+ assistantMessage,
501
+ context: { messages: this.agent.state.messages, tools: this.agent.state.tools },
502
+ beforeToolCall: (context) => this._beforeToolCall(context, parentId),
503
+ afterToolCall: (context) => this._afterToolCall(context, parentId),
504
+ signal,
505
+ onUpdate,
506
+ });
507
+ },
508
+ emit: async (event) => {
509
+ await this._extensionRunner.emit(event);
510
+ this._emit(event);
511
+ },
512
+ });
513
+ return this._nestedToolCalls.execute(parentToolCallId, name, args, options);
514
+ }
515
+ /** Whether `projection`, the current session projection, exceeds the compaction threshold of `model`. */
516
+ _exceedsCompactionThreshold(model, projection) {
517
+ if (model.contextWindow <= 0)
518
+ return false;
519
+ return shouldCompact(estimateProjectedContextTokens(projection, this.sessionManager.getBranch()).tokens, model.contextWindow, this.settingsManager.getCompactionSettings(this.model));
520
+ }
416
521
  async _compactBeforeNextAssistantResponse(context, signal) {
417
522
  if (signal?.aborted)
418
523
  return context;
419
- const model = this.model;
420
- const settings = this.settingsManager.getCompactionSettings(model);
421
524
  const projection = this.sessionManager.buildSessionProjection();
422
- if (!model ||
423
- model.contextWindow <= 0 ||
424
- !shouldCompact(estimateProjectedContextTokens(projection, this.sessionManager.getBranch()).tokens, model.contextWindow, settings)) {
525
+ // A virtual selection is checked in prepareRequest, against the model the request is routed to.
526
+ const model = this.model;
527
+ if (!model || isVirtualModel(model) || !this._exceedsCompactionThreshold(model, projection)) {
425
528
  return { ...context, messages: projection.messages };
426
529
  }
427
530
  await this._runAutoCompaction("threshold", false, undefined, undefined, signal);
@@ -432,24 +535,55 @@ export class AgentSession {
432
535
  if (previousPrepareRequest)
433
536
  this._cachePrefixUnavailableReason ??= "custom_prepare_request";
434
537
  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,
538
+ const failed = this._failedResponse;
539
+ this._failedResponse = undefined;
540
+ const prepare = async () => {
541
+ const projection = this.sessionManager.buildSessionProjection();
542
+ const canonicalContext = {
543
+ ...request.context,
544
+ messages: projection.messages,
545
+ // Messages declare the provider-visible loadout; context.tools keeps executable implementations.
546
+ tools: this.agent.state.tools.slice(),
547
+ };
548
+ const previous = await previousPrepareRequest?.({
549
+ ...request,
550
+ context: canonicalContext,
551
+ model: this.agent.state.model,
552
+ thinkingLevel: this.agent.state.thinkingLevel,
553
+ }, signal);
554
+ return { previous, context: previous?.context ?? canonicalContext, projection };
452
555
  };
556
+ let { previous, context, projection } = await prepare();
557
+ const model = previous?.model ?? this.agent.state.model;
558
+ const thinkingLevel = previous?.thinkingLevel ?? this.agent.state.thinkingLevel;
559
+ if (!isVirtualModel(model))
560
+ return { ...previous, context, model, thinkingLevel };
561
+ // The selection stays in agent state; only this request uses the routed model. A routing
562
+ // failure rejects, which ends the run with an error response. Only messages the user wrote
563
+ // start a turn; extension messages can follow them, e.g. from before_agent_start.
564
+ const lastResponse = context.messages.findLastIndex((message) => message.role === "assistant");
565
+ const userTurn = context.messages.slice(lastResponse + 1).some((message) => message.role === "user");
566
+ const state = getVirtualModelState(this.sessionManager.getBranch(), model.provider, model.id);
567
+ const route = await this._modelRuntime.resolveModel(model, convertToLlm(context.messages), {
568
+ reason: failed ? "retry" : userTurn ? "user" : "continuation",
569
+ thinkingLevel,
570
+ signal,
571
+ failed,
572
+ state,
573
+ });
574
+ if (route.state !== undefined && route.state !== state) {
575
+ const data = { provider: model.provider, modelId: model.id, state: route.state };
576
+ const entry = this.sessionManager.getEntry(this.sessionManager.appendCustomEntry(VIRTUAL_MODEL_STATE_ENTRY, data));
577
+ if (entry)
578
+ this._emit({ type: "entry_appended", entry });
579
+ }
580
+ // The route stands: the router already decided this request. The state entry does not change
581
+ // the projection.
582
+ if (this._exceedsCompactionThreshold(route.model, projection)) {
583
+ await this._runAutoCompaction("threshold", false, undefined, undefined, signal);
584
+ ({ previous, context } = await prepare());
585
+ }
586
+ return { ...previous, context, model: route.model, thinkingLevel: route.thinkingLevel };
453
587
  };
454
588
  }
455
589
  async _dispatchTurnEndBoundary(message, toolResults) {
@@ -505,19 +639,17 @@ export class AgentSession {
505
639
  ? async (_turn, signal) => await this.agent.prepareNextTurn?.(signal)
506
640
  : undefined);
507
641
  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);
642
+ const compactedContext = await this._compactBeforeNextProviderRequest(turn, signal);
643
+ let context;
644
+ if (!signal?.aborted && compactedContext) {
645
+ context = compactedContext;
646
+ }
647
+ else if (!signal?.aborted && compactedContext === undefined) {
648
+ context = await this._compactBeforeNextAssistantResponse(turn.context, signal);
649
+ }
650
+ else {
651
+ context = { ...turn.context, messages: this.sessionManager.buildSessionProjection().messages };
652
+ }
521
653
  const nextTurn = { ...turn, context };
522
654
  const previousSnapshot = await previousPrepareNextTurnWithContext?.(nextTurn, signal);
523
655
  const nextContext = previousSnapshot?.context ?? context;
@@ -687,6 +819,21 @@ export class AgentSession {
687
819
  }
688
820
  /** Internal handler for agent events - shared by subscribe and reconnect */
689
821
  _handleAgentEvent = async (event, _signal) => {
822
+ // Record the calls a tool made through ctx.executeTool() and their usage on its result message.
823
+ if (this._nestedToolCalls) {
824
+ if (event.type === "message_start" && event.message.role === "toolResult") {
825
+ const message = event.message;
826
+ const summary = this._nestedToolCalls.takeRecord(message.toolCallId);
827
+ if (summary?.calls)
828
+ message.nestedCalls = summary.calls;
829
+ if (summary?.usage) {
830
+ message.usage = message.usage ? combineUsage(message.usage, summary.usage) : summary.usage;
831
+ }
832
+ }
833
+ else if (event.type === "agent_end") {
834
+ this._nestedToolCalls.clear();
835
+ }
836
+ }
690
837
  // When a user message starts, check if it's from either queue and remove it BEFORE emitting
691
838
  // This ensures the UI sees the updated queue state
692
839
  if (event.type === "message_start" && event.message.role === "user") {
@@ -1084,6 +1231,14 @@ export class AgentSession {
1084
1231
  get thinkingLevel() {
1085
1232
  return this.agent.state.thinkingLevel;
1086
1233
  }
1234
+ /** Under a virtual selection, the physical model and thinking level of the latest successful response. */
1235
+ get routedModel() {
1236
+ if (!this.model || !isVirtualModel(this.model))
1237
+ return undefined;
1238
+ const latest = findLatestResponse(this.agent.state.messages);
1239
+ const model = latest && this._modelRuntime.getPhysicalModel(latest.provider, latest.model);
1240
+ return model && { model, thinkingLevel: latest?.thinkingLevel };
1241
+ }
1087
1242
  /** Whether the session is currently processing an agent run or post-run continuation. */
1088
1243
  get isStreaming() {
1089
1244
  return this._isAgentRunActive;
@@ -1109,12 +1264,16 @@ export class AgentSession {
1109
1264
  return this._retryAttempt;
1110
1265
  }
1111
1266
  /**
1112
- * Get the names of currently active tools.
1113
- * Returns the names of tools currently set on the agent.
1267
+ * Get the names of currently active tools, which are the tools declared to the model.
1268
+ * Tools with `codemode` or `deferred` exposure are callable from other tools without being active.
1114
1269
  */
1115
1270
  getActiveToolNames() {
1116
1271
  return this.agent.state.tools.map((t) => t.name);
1117
1272
  }
1273
+ /** Get the names of the tools that tools can call through `ctx.executeTool()`. */
1274
+ getCallableToolNames() {
1275
+ return this._getCallableTools().map((t) => t.name);
1276
+ }
1118
1277
  /**
1119
1278
  * Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
1120
1279
  */
@@ -1124,6 +1283,9 @@ export class AgentSession {
1124
1283
  description: definition.description,
1125
1284
  parameters: definition.parameters,
1126
1285
  promptGuidelines: definition.promptGuidelines,
1286
+ exposure: this._getToolExposure(definition.name),
1287
+ ...(definition.namespace ? { namespace: definition.namespace } : {}),
1288
+ ...(definition.annotations ? { annotations: { ...definition.annotations } } : {}),
1127
1289
  sourceInfo,
1128
1290
  }));
1129
1291
  }
@@ -1132,22 +1294,79 @@ export class AgentSession {
1132
1294
  }
1133
1295
  /**
1134
1296
  * Set active tools by name.
1135
- * Only tools in the registry can be enabled. Unknown tool names are ignored.
1297
+ * Only tools in the registry can be enabled. Unknown and hidden tool names are ignored.
1136
1298
  * Also rebuilds the system prompt to reflect the new tool set.
1137
1299
  * Changes take effect on the next agent turn.
1138
1300
  */
1139
1301
  setActiveToolsByName(toolNames) {
1140
- const tools = [];
1141
- const validToolNames = [];
1142
- for (const name of toolNames) {
1302
+ const tools = this._applyToolLoadout(toolNames);
1303
+ this._rebuildSystemPrompt(tools.map((tool) => tool.name));
1304
+ }
1305
+ _getToolExposure(name) {
1306
+ return this._toolDefinitions.get(name)?.definition.exposure ?? "direct";
1307
+ }
1308
+ /**
1309
+ * Tools callable through `ctx.executeTool()`: the active `direct` tools and every registered
1310
+ * `codemode` or `deferred` tool.
1311
+ */
1312
+ _getCallableTools(active = new Set(this.getActiveToolNames())) {
1313
+ return [...this._toolRegistry.values()].filter((tool) => {
1314
+ const exposure = this._getToolExposure(tool.name);
1315
+ return exposure === "codemode" || exposure === "deferred" || (exposure === "direct" && active.has(tool.name));
1316
+ });
1317
+ }
1318
+ /**
1319
+ * Set the agent's tools for the given active tool names and return them. The active tools are
1320
+ * the registered, non-hidden ones; they are declared to the model. Active tools with a
1321
+ * `prepareLoadout` hook can change the declared descriptions and hide declarations from
1322
+ * requests (see {@link _installHiddenDeclarationsProjection}).
1323
+ */
1324
+ _applyToolLoadout(toolNames) {
1325
+ const tools = [...new Set(toolNames)].flatMap((name) => {
1143
1326
  const tool = this._toolRegistry.get(name);
1144
- if (tool) {
1145
- tools.push(tool);
1146
- validToolNames.push(name);
1327
+ return tool && this._getToolExposure(name) !== "hidden" ? [tool] : [];
1328
+ });
1329
+ const hooks = tools.flatMap((tool) => {
1330
+ const entry = this._toolDefinitions.get(tool.name);
1331
+ return entry?.definition.prepareLoadout ? [entry] : [];
1332
+ });
1333
+ const hidden = new Set();
1334
+ let declared = tools;
1335
+ if (hooks.length > 0) {
1336
+ const loadout = {
1337
+ declared: tools,
1338
+ callable: this._getCallableTools(new Set(tools.map((tool) => tool.name))),
1339
+ registered: [...this._toolRegistry.values()],
1340
+ getExposure: (name) => this._getToolExposure(name),
1341
+ getNamespace: (name) => this._toolDefinitions.get(name)?.definition.namespace,
1342
+ };
1343
+ const descriptions = new Map();
1344
+ for (const { definition, sourceInfo } of hooks) {
1345
+ try {
1346
+ const changes = definition.prepareLoadout?.(loadout);
1347
+ for (const [name, description] of Object.entries(changes?.descriptions ?? {})) {
1348
+ descriptions.set(name, description);
1349
+ }
1350
+ for (const name of changes?.hiddenDeclarations ?? [])
1351
+ hidden.add(name);
1352
+ }
1353
+ catch (error) {
1354
+ this._extensionRunner.emitError({
1355
+ extensionPath: sourceInfo.path,
1356
+ event: "prepare_loadout",
1357
+ error: error instanceof Error ? error.message : String(error),
1358
+ stack: error instanceof Error ? error.stack : undefined,
1359
+ });
1360
+ }
1147
1361
  }
1362
+ declared = tools.map((tool) => {
1363
+ const description = descriptions.get(tool.name);
1364
+ return description === undefined ? tool : { ...tool, description };
1365
+ });
1148
1366
  }
1149
- this.agent.state.tools = tools;
1150
- this._rebuildSystemPrompt(validToolNames);
1367
+ this._hiddenDeclarations = hidden;
1368
+ this.agent.state.tools = declared;
1369
+ return declared;
1151
1370
  }
1152
1371
  /** Whether compaction or branch summarization is currently running */
1153
1372
  get isCompacting() {
@@ -1248,11 +1467,7 @@ export class AgentSession {
1248
1467
  * {@link _installAgentForcedPromptProjection}.
1249
1468
  */
1250
1469
  _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
- });
1470
+ options.selectedTools = this._applyToolLoadout(options.selectedTools).map((tool) => tool.name);
1256
1471
  const sections = diffSystemPromptSections(getCurrentSystemMessage(messages)?.sections ?? {}, buildSystemPromptSections(options));
1257
1472
  return sections ? { role: "system", content: "", sections, timestamp: Date.now() } : undefined;
1258
1473
  }
@@ -1266,6 +1481,32 @@ export class AgentSession {
1266
1481
  * collapse into one head holding the forced text and the current tools. Runs after the
1267
1482
  * `context` extension handlers.
1268
1483
  */
1484
+ /**
1485
+ * Remove the declarations that `prepareLoadout` hooks hide from every request. The whole
1486
+ * transcript is filtered with the current set, so the projected declarations stay consistent
1487
+ * across requests and only change when the loadout does.
1488
+ */
1489
+ _installHiddenDeclarationsProjection() {
1490
+ const previousTransformContext = this.agent.transformContext;
1491
+ this.agent.transformContext = async (messages, signal) => {
1492
+ const transformed = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
1493
+ const hidden = this._hiddenDeclarations;
1494
+ if (hidden.size === 0)
1495
+ return transformed;
1496
+ return transformed.map((message) => {
1497
+ if (message.role !== "system" || (!message.toolsAdded && !message.toolsRemoved))
1498
+ return message;
1499
+ const { toolsAdded, toolsRemoved, ...rest } = message;
1500
+ const added = toolsAdded?.filter((tool) => !hidden.has(tool.name)) ?? [];
1501
+ const removed = toolsRemoved?.filter((tool) => !hidden.has(tool.name)) ?? [];
1502
+ return {
1503
+ ...rest,
1504
+ ...(added.length > 0 ? { toolsAdded: added } : {}),
1505
+ ...(removed.length > 0 ? { toolsRemoved: removed } : {}),
1506
+ };
1507
+ });
1508
+ };
1509
+ }
1269
1510
  _installAgentForcedPromptProjection() {
1270
1511
  const previousTransformContext = this.agent.transformContext;
1271
1512
  if (previousTransformContext)
@@ -1285,25 +1526,25 @@ export class AgentSession {
1285
1526
  return [head, ...transformed.filter((message) => message.role !== "system")];
1286
1527
  };
1287
1528
  }
1288
- /** Restore the active tool loadout declared by the session transcript, if it declares one. */
1529
+ /**
1530
+ * Restore the active tool loadout declared by the session transcript, if it declares one.
1531
+ * Tools reachable only from other tools are never declared, but they do not depend on the active
1532
+ * set, so the transcript's declarations are the whole loadout.
1533
+ */
1289
1534
  _restoreToolsFromTranscript() {
1290
1535
  const current = getCurrentSystemMessage(this.sessionManager.buildSessionContext().messages);
1291
1536
  if (!current)
1292
1537
  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);
1538
+ this.setActiveToolsByName((current.toolsAdded ?? []).map((tool) => tool.name));
1301
1539
  }
1302
1540
  // =========================================================================
1303
1541
  // Prompting
1304
1542
  // =========================================================================
1305
1543
  async _runAgentOperation(start) {
1306
1544
  this._agentRunAbortRequested = false;
1545
+ // Compaction before the prompt may have scheduled a retry; the new prompt replaces it.
1546
+ this._failedResponse = undefined;
1547
+ this._recordSelection();
1307
1548
  this._isAgentRunActive = true;
1308
1549
  try {
1309
1550
  await start();
@@ -1339,6 +1580,7 @@ export class AgentSession {
1339
1580
  finally {
1340
1581
  if (this._agentRunAbortRequested)
1341
1582
  this._finishCancelledRetry();
1583
+ this._failedResponse = undefined;
1342
1584
  this._runSystemPromptOptions = undefined;
1343
1585
  this._flushPendingBashMessages();
1344
1586
  this._flushPendingCustomMessages();
@@ -1439,6 +1681,7 @@ export class AgentSession {
1439
1681
  if (this._isRetryableError(message) && (await this._prepareRetry(message))) {
1440
1682
  if (this._agentRunAbortRequested)
1441
1683
  this._finishCancelledRetry();
1684
+ this._failedResponse = message;
1442
1685
  return !this._agentRunAbortRequested;
1443
1686
  }
1444
1687
  if (this._agentRunAbortRequested) {
@@ -1512,7 +1755,7 @@ export class AgentSession {
1512
1755
  for (const image of images) {
1513
1756
  const processed = await processImage(Buffer.from(image.data, "base64"), image.mimeType, {
1514
1757
  autoResizeImages: this.settingsManager.getImageAutoResize(),
1515
- resizeOptions: this.model?.inputLimits?.images?.resize,
1758
+ resizeOptions: this._limitsModel()?.inputLimits?.images?.resize,
1516
1759
  });
1517
1760
  if (!processed.ok) {
1518
1761
  hints.push(processed.message);
@@ -1539,152 +1782,140 @@ export class AgentSession {
1539
1782
  }
1540
1783
  const expandPromptTemplates = options?.expandPromptTemplates ?? true;
1541
1784
  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);
1785
+ // Handle extension commands first (execute immediately, even during streaming)
1786
+ // Extension commands manage their own LLM interaction via pi.sendMessage()
1787
+ if (expandPromptTemplates && text.startsWith("/")) {
1788
+ const handled = await this._tryExecuteExtensionCommand(text);
1789
+ if (handled) {
1790
+ // Extension command executed, no prompt to send
1791
+ preflightResult?.("handled");
1561
1792
  return;
1562
1793
  }
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;
1794
+ }
1795
+ if (this._compactionAbortController !== undefined && !this._isAborting) {
1796
+ throw new Error("Cannot submit a prompt while compaction is in progress. Wait for compaction to finish and retry.");
1797
+ }
1798
+ // Emit input event for extension interception (before skill/template expansion)
1799
+ const processedInput = await this._runInputHandlers(text, options?.images, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
1800
+ if (!processedInput) {
1801
+ preflightResult?.("handled");
1802
+ return;
1803
+ }
1804
+ const { text: currentText, images: currentImages } = processedInput;
1805
+ // Expand skill commands (/skill:name args) and prompt templates (/template args)
1806
+ let expandedText = currentText;
1807
+ if (expandPromptTemplates) {
1808
+ expandedText = this._expandSkillCommand(expandedText);
1809
+ expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
1810
+ }
1811
+ // If streaming, queue via steer() or followUp() based on option
1812
+ if (this.isStreaming || this._isAborting) {
1813
+ if (!options?.streamingBehavior) {
1814
+ throw new Error("Agent is already processing. Specify streamingBehavior ('steer' or 'followUp') to queue the message.");
1583
1815
  }
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());
1816
+ if (options.streamingBehavior === "followUp") {
1817
+ await this._queueFollowUp(expandedText, currentImages);
1590
1818
  }
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));
1819
+ else {
1820
+ await this._queueSteer(expandedText, currentImages);
1601
1821
  }
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;
1822
+ preflightResult?.("queued");
1823
+ return;
1824
+ }
1825
+ // Flush any pending bash and custom messages before the new prompt
1826
+ this._flushPendingBashMessages();
1827
+ this._flushPendingCustomMessages();
1828
+ // Validate model
1829
+ if (!this.model) {
1830
+ throw new Error(formatNoModelSelectedMessage());
1831
+ }
1832
+ const hasConfiguredAuth = this._modelRuntime.hasConfiguredAuth(this.model.provider) ||
1833
+ (await this._modelRuntime.checkAuth(this.model.provider)) !== undefined;
1834
+ if (!hasConfiguredAuth) {
1835
+ const isOAuth = this._modelRuntime.isUsingOAuth(this.model.provider);
1836
+ if (isOAuth) {
1837
+ throw new Error(`Authentication failed for "${this.model.provider}". ` +
1838
+ `Credentials may have expired or network is unavailable. ` +
1839
+ `Run '/login ${this.model.provider}' to re-authenticate.`);
1607
1840
  }
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);
1841
+ throw new Error(formatNoApiKeyFoundMessage(this.model.provider));
1842
+ }
1843
+ // Check if we need to compact before sending (catches aborted responses).
1844
+ // The user's new prompt is sent below, so do not call agent.continue() here.
1845
+ if (this._isAborting) {
1846
+ return;
1847
+ }
1848
+ const lastAssistant = this._findLastAssistantMessage();
1849
+ if (lastAssistant) {
1850
+ const prePromptAbortController = new AbortController();
1851
+ let resolvePrePromptCompletion;
1852
+ const prePromptCompletion = new Promise((resolve) => {
1853
+ resolvePrePromptCompletion = resolve;
1854
+ });
1855
+ this._prePromptAbortController = prePromptAbortController;
1856
+ this._prePromptCompletionPromise = prePromptCompletion;
1857
+ try {
1858
+ await this._checkCompaction(lastAssistant, false, [], prePromptAbortController.signal);
1859
+ }
1860
+ finally {
1861
+ if (this._prePromptAbortController === prePromptAbortController) {
1862
+ this._prePromptAbortController = undefined;
1619
1863
  }
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;
1864
+ if (this._prePromptCompletionPromise === prePromptCompletion) {
1865
+ this._prePromptCompletionPromise = undefined;
1632
1866
  }
1867
+ resolvePrePromptCompletion?.();
1633
1868
  }
1634
- if (isPiServerMode()) {
1635
- this._detachPiServerTerminalAssistantFailure();
1869
+ if (prePromptAbortController.signal.aborted || this._isAborting) {
1870
+ return;
1636
1871
  }
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);
1872
+ }
1873
+ if (isPiServerMode()) {
1874
+ this._detachPiServerTerminalAssistantFailure();
1875
+ }
1876
+ // Emit before_agent_start before normalizing images so extension-driven model
1877
+ // selection determines the resize profile used for the request and history.
1878
+ const selectedToolsBefore = this._baseSystemPromptOptions.selectedTools;
1879
+ const result = await this._extensionRunner.emitBeforeAgentStart(expandedText, currentImages, this._baseSystemPromptOptions);
1880
+ // Handlers may edit event.systemPromptOptions.selectedTools or call setActiveTools(),
1881
+ // which updates the live loadout instead. An explicit edit wins; otherwise the live
1882
+ // loadout is authoritative, so a setActiveTools() call is not undone here.
1883
+ const handlerEditedTools = result.systemPromptOptions.selectedTools.length !== selectedToolsBefore.length ||
1884
+ result.systemPromptOptions.selectedTools.some((name, index) => name !== selectedToolsBefore[index]);
1885
+ if (!handlerEditedTools)
1886
+ result.systemPromptOptions.selectedTools = this.getActiveToolNames();
1887
+ const normalized = await this._normalizePromptImages(currentImages);
1888
+ const userText = normalized.hints.length > 0 ? `${expandedText}\n\n${normalized.hints.join("\n")}` : expandedText;
1889
+ // Build messages only after hooks and image normalization have completed.
1890
+ const messages = [];
1891
+ const userContent = [{ type: "text", text: userText }];
1892
+ userContent.push(...normalized.images);
1893
+ messages.push({
1894
+ role: "user",
1895
+ content: userContent,
1896
+ timestamp: Date.now(),
1897
+ });
1898
+ // Inject any pending "nextTurn" messages as context alongside the user message
1899
+ for (const msg of this._pendingNextTurnMessages) {
1900
+ messages.push(msg);
1901
+ }
1902
+ this._pendingNextTurnMessages = [];
1903
+ for (const msg of result.messages) {
1654
1904
  messages.push({
1655
- role: "user",
1656
- content: userContent,
1905
+ role: "custom",
1906
+ customType: msg.customType,
1907
+ // Untyped extensions can pass null/missing content; normalize at ingestion.
1908
+ content: msg.content ?? [],
1909
+ display: msg.display,
1910
+ details: msg.details,
1657
1911
  timestamp: Date.now(),
1658
1912
  });
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
1913
  }
1684
- if (!messages) {
1685
- return;
1686
- }
1687
- preflightResult?.(true);
1914
+ const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
1915
+ this._runSystemPromptOptions = result.systemPromptOptions;
1916
+ if (updateMessage)
1917
+ messages.unshift(updateMessage);
1918
+ preflightResult?.("started");
1688
1919
  await this._runAgentPrompt(messages);
1689
1920
  }
1690
1921
  /**
@@ -1750,7 +1981,7 @@ export class AgentSession {
1750
1981
  }
1751
1982
  const processedInput = await this._runInputHandlers(text, images, source, this.isStreaming ? behavior : undefined);
1752
1983
  if (!processedInput)
1753
- return;
1984
+ return "handled";
1754
1985
  let expandedText = this._expandSkillCommand(processedInput.text);
1755
1986
  expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
1756
1987
  if (behavior === "steer") {
@@ -1759,6 +1990,7 @@ export class AgentSession {
1759
1990
  else {
1760
1991
  await this._queueFollowUp(expandedText, processedInput.images);
1761
1992
  }
1993
+ return "queued";
1762
1994
  }
1763
1995
  /**
1764
1996
  * Queue a steering message while the agent is running.
@@ -1770,7 +2002,7 @@ export class AgentSession {
1770
2002
  * @throws Error if text is an extension command
1771
2003
  */
1772
2004
  async steer(text, images, options) {
1773
- await this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
2005
+ return this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
1774
2006
  }
1775
2007
  /**
1776
2008
  * Queue a follow-up message to be processed after the agent finishes.
@@ -1781,7 +2013,7 @@ export class AgentSession {
1781
2013
  * @throws Error if text is an extension command
1782
2014
  */
1783
2015
  async followUp(text, images, options) {
1784
- await this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
2016
+ return this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
1785
2017
  }
1786
2018
  /**
1787
2019
  * Internal: Queue a steering message (already expanded, no extension command check).
@@ -2393,8 +2625,8 @@ export class AgentSession {
2393
2625
  throw new Error(formatNoModelSelectedMessage());
2394
2626
  }
2395
2627
  const settings = this.settingsManager.getCompactionSettings(model);
2396
- const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
2397
2628
  if (isPiServerMode()) {
2629
+ const { model: requestModel, apiKey, headers, thinkingLevel, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
2398
2630
  this._detachPiServerTerminalAssistantFailure();
2399
2631
  const cacheInput = await this._buildCompactionCacheInput(requestModel);
2400
2632
  const piServerResult = await compactPiServer(requestModel, {
@@ -2413,7 +2645,7 @@ export class AgentSession {
2413
2645
  settings: this.settingsManager.getCompactionSettings(),
2414
2646
  sessionTree: buildPiServerSessionTree(this.sessionManager.getEntries(), this.sessionManager.getLeafId()),
2415
2647
  signal: this._compactionAbortController.signal,
2416
- reasoning: toProviderReasoning(this.thinkingLevel),
2648
+ reasoning: toProviderReasoning(thinkingLevel),
2417
2649
  onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
2418
2650
  });
2419
2651
  const result = await this._applyPiServerCompactionResult(piServerResult, "manual", false);
@@ -2471,9 +2703,10 @@ export class AgentSession {
2471
2703
  details = extensionCompaction.details;
2472
2704
  }
2473
2705
  else {
2474
- // Generate compaction result
2706
+ // Resolve the request only when Pi summarizes itself: routing may call models or fail.
2707
+ const { model: requestModel, apiKey, headers, env, thinkingLevel, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
2475
2708
  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);
2709
+ 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
2710
  summary = result.summary;
2478
2711
  firstKeptEntryId = result.firstKeptEntryId;
2479
2712
  tokensBefore = result.tokensBefore;
@@ -2585,12 +2818,14 @@ export class AgentSession {
2585
2818
  // Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
2586
2819
  if (skipAbortedCheck && assistantMessage.stopReason === "aborted")
2587
2820
  return false;
2588
- const contextWindow = this.model?.contextWindow ?? 0;
2589
2821
  // Skip overflow check if the message came from a different model.
2590
2822
  // This handles the case where user switched from a smaller-context model (e.g. opus)
2591
2823
  // 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;
2824
+ // shouldn't trigger compaction for the new model. Under a virtual selection, the
2825
+ // physical model that produced the message supplies the limits.
2826
+ const messageModel = this._modelForMessage(assistantMessage);
2827
+ const sameModel = messageModel !== undefined;
2828
+ const contextWindow = (messageModel ?? this.model)?.contextWindow ?? 0;
2594
2829
  // Skip compaction checks if this assistant message is older than the latest
2595
2830
  // compaction boundary. This prevents a stale pre-compaction usage/error
2596
2831
  // from retriggering compaction on the first prompt after compaction.
@@ -2624,7 +2859,7 @@ export class AgentSession {
2624
2859
  const contextOverflow = sameModel &&
2625
2860
  ((explicitOverflow && assistantRetainedForExplicitRecovery) ||
2626
2861
  (assistantUsageMatchesProjection && isContextOverflow(assistantMessage, contextWindow)));
2627
- const recoverableLength = sameModel && assistantIsProjected && isRecoverableLength(assistantMessage, this.model?.maxTokens ?? 0);
2862
+ const recoverableLength = sameModel && assistantIsProjected && isRecoverableLength(assistantMessage, messageModel.maxTokens);
2628
2863
  if (contextOverflow || recoverableLength) {
2629
2864
  const willRetry = assistantMessage.stopReason !== "stop";
2630
2865
  if (!willRetry) {
@@ -2649,7 +2884,10 @@ export class AgentSession {
2649
2884
  this._omitRecoveryAttempt(assistantMessage, toolResults);
2650
2885
  if (isPiServerMode())
2651
2886
  this._detachPiServerTerminalAssistantFailure();
2652
- return await this._runAutoCompaction("overflow", willRetry, undefined, undefined, externalSignal);
2887
+ const retry = await this._runAutoCompaction("overflow", willRetry, undefined, undefined, externalSignal);
2888
+ if (retry)
2889
+ this._failedResponse = assistantMessage;
2890
+ return retry;
2653
2891
  }
2654
2892
  // Case 2: Threshold - context is getting large
2655
2893
  // For error messages or all-zero usage messages, estimate from the last valid response.
@@ -2712,7 +2950,7 @@ export class AgentSession {
2712
2950
  started = true;
2713
2951
  this._emit({ type: "compaction_start", reason });
2714
2952
  abortController.signal.throwIfAborted();
2715
- const { model: requestModel, apiKey, headers, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2953
+ const { model: requestModel, apiKey, headers, thinkingLevel, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2716
2954
  abortController.signal.throwIfAborted();
2717
2955
  const cacheInput = await this._buildCompactionCacheInput(requestModel);
2718
2956
  const piServerResult = await compactPiServer(requestModel, {
@@ -2731,7 +2969,7 @@ export class AgentSession {
2731
2969
  preparation: preparationOptions,
2732
2970
  sessionTree: buildPiServerSessionTree(this.sessionManager.getEntries(), this.sessionManager.getLeafId()),
2733
2971
  signal: abortController.signal,
2734
- reasoning: toProviderReasoning(this.thinkingLevel),
2972
+ reasoning: toProviderReasoning(thinkingLevel),
2735
2973
  onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
2736
2974
  });
2737
2975
  if (externalSignal?.aborted || abortController.signal.aborted) {
@@ -2759,8 +2997,6 @@ export class AgentSession {
2759
2997
  started = true;
2760
2998
  this._emit({ type: "compaction_start", reason });
2761
2999
  abortController.signal.throwIfAborted();
2762
- const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2763
- abortController.signal.throwIfAborted();
2764
3000
  let extensionCompaction;
2765
3001
  if (this._extensionRunner.hasHandlers("session_before_compact")) {
2766
3002
  const extensionResult = (await this._extensionRunner.emit({
@@ -2795,8 +3031,10 @@ export class AgentSession {
2795
3031
  details = extensionCompaction.details;
2796
3032
  }
2797
3033
  else {
3034
+ const { model: requestModel, apiKey, headers, env, thinkingLevel, } = await this._getSummarizationRequestAuth(model, abortController.signal);
3035
+ abortController.signal.throwIfAborted();
2798
3036
  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);
3037
+ 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
3038
  summary = compactResult.summary;
2801
3039
  firstKeptEntryId = compactResult.firstKeptEntryId;
2802
3040
  tokensBefore = compactResult.tokensBefore;
@@ -2893,10 +3131,13 @@ export class AgentSession {
2893
3131
  return this.settingsManager.getCompactionEnabled();
2894
3132
  }
2895
3133
  _shouldCompactBeforeNextProviderRequest(turn) {
3134
+ // A virtual selection is checked in prepareRequest, against the model the request is routed to.
3135
+ if (!this.model || isVirtualModel(this.model))
3136
+ return false;
2896
3137
  const settings = this.settingsManager.getCompactionSettings(this.model);
2897
3138
  if (!settings.enabled || turn.toolResults.length === 0)
2898
3139
  return false;
2899
- const contextWindow = this.model?.contextWindow ?? 0;
3140
+ const contextWindow = this.model.contextWindow;
2900
3141
  if (contextWindow <= 0)
2901
3142
  return false;
2902
3143
  const branch = this.sessionManager.getBranch();
@@ -2997,6 +3238,7 @@ export class AgentSession {
2997
3238
  }
2998
3239
  this._applyExtensionBindings(this._extensionRunner);
2999
3240
  await this._extensionRunner.emit(this._sessionStartEvent);
3241
+ this._extensionRunner.reportUnhandledMcpServers();
3000
3242
  await this.extendResourcesFromExtensions(this._sessionStartEvent.reason === "reload" ? "reload" : "startup");
3001
3243
  }
3002
3244
  async extendResourcesFromExtensions(reason) {
@@ -3018,7 +3260,7 @@ export class AgentSession {
3018
3260
  buildExtensionResourcePaths(entries) {
3019
3261
  return entries.map((entry) => {
3020
3262
  const source = this.getExtensionSourceLabel(entry.extensionPath);
3021
- const baseDir = entry.extensionPath.startsWith("<") ? undefined : dirname(entry.extensionPath);
3263
+ const baseDir = isSyntheticPath(entry.extensionPath) ? undefined : dirname(entry.extensionPath);
3022
3264
  return {
3023
3265
  path: entry.path,
3024
3266
  metadata: {
@@ -3031,7 +3273,7 @@ export class AgentSession {
3031
3273
  });
3032
3274
  }
3033
3275
  getExtensionSourceLabel(extensionPath) {
3034
- if (extensionPath.startsWith("<")) {
3276
+ if (isSyntheticPath(extensionPath)) {
3035
3277
  return `extension:${extensionPath.replace(/[<>]/g, "")}`;
3036
3278
  }
3037
3279
  const base = basename(extensionPath);
@@ -3116,6 +3358,7 @@ export class AgentSession {
3116
3358
  },
3117
3359
  getActiveTools: () => this.getActiveToolNames(),
3118
3360
  getAllTools: () => this.getAllTools(),
3361
+ getSettings: () => this.settingsManager.getSettings(),
3119
3362
  setActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),
3120
3363
  refreshTools: () => this._refreshToolRegistry(),
3121
3364
  getCommands,
@@ -3159,6 +3402,8 @@ export class AgentSession {
3159
3402
  },
3160
3403
  getSystemPrompt: () => this.systemPrompt,
3161
3404
  getSystemPromptOptions: () => this._baseSystemPromptOptions,
3405
+ executeTool: (callerId, name, args, options) => this._executeNestedToolCall(callerId, name, args, options),
3406
+ getCallableTools: () => this._getCallableTools(),
3162
3407
  }, {
3163
3408
  registerProvider: (name, config) => {
3164
3409
  this._modelRuntime.registerProvider(name, config);
@@ -3172,10 +3417,20 @@ export class AgentSession {
3172
3417
  this._modelRuntime.unregisterProvider(name);
3173
3418
  this._refreshCurrentModelFromRegistry();
3174
3419
  },
3420
+ registerVirtualModel: (definition) => {
3421
+ this._modelRuntime.registerVirtualModel(definition);
3422
+ this._refreshCurrentModelFromRegistry();
3423
+ },
3424
+ unregisterVirtualModel: (provider, id) => {
3425
+ this._modelRuntime.unregisterVirtualModel(provider, id);
3426
+ this._refreshCurrentModelFromRegistry();
3427
+ },
3175
3428
  });
3176
3429
  }
3177
3430
  _refreshToolRegistry(options) {
3178
- const previousRegistryNames = new Set(this._toolRegistry.keys());
3431
+ // Tools that were already activated on registration. A tool whose exposure changes to
3432
+ // `direct` or `model-only` (for example from `hidden`) is activated like a new tool.
3433
+ const previousActivatedOnRegistration = new Set([...this._toolRegistry.keys()].filter((name) => this._isActivatedOnRegistration(name)));
3179
3434
  const previousActiveToolNames = this.getActiveToolNames();
3180
3435
  const allowedToolNames = this._allowedToolNames;
3181
3436
  const excludedToolNames = this._excludedToolNames;
@@ -3194,7 +3449,7 @@ export class AgentSession {
3194
3449
  name,
3195
3450
  {
3196
3451
  definition,
3197
- sourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, { source: "builtin" }),
3452
+ sourceInfo: createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${name}`, { source: "builtin" }),
3198
3453
  },
3199
3454
  ]));
3200
3455
  for (const tool of allCustomTools) {
@@ -3222,7 +3477,9 @@ export class AgentSession {
3222
3477
  .filter((definition) => isAllowedTool(definition.name))
3223
3478
  .map((definition) => ({
3224
3479
  definition,
3225
- sourceInfo: createSyntheticSourceInfo(`<builtin:${definition.name}>`, { source: "builtin" }),
3480
+ sourceInfo: createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${definition.name}`, {
3481
+ source: "builtin",
3482
+ }),
3226
3483
  })), runner);
3227
3484
  const toolRegistry = new Map(wrappedBuiltInTools.map((tool) => [tool.name, tool]));
3228
3485
  for (const tool of wrappedExtensionTools) {
@@ -3232,25 +3489,36 @@ export class AgentSession {
3232
3489
  const nextActiveToolNames = (options?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]).filter((name) => isAllowedTool(name));
3233
3490
  if (allowedToolNames) {
3234
3491
  for (const toolName of this._toolRegistry.keys()) {
3235
- if (allowedToolNames.has(toolName)) {
3492
+ // Naming a tool activates it even when it is not active by default.
3493
+ if (allowedToolNames.has(toolName) && this._isDeclarable(toolName)) {
3236
3494
  nextActiveToolNames.push(toolName);
3237
3495
  }
3238
3496
  }
3239
3497
  }
3240
3498
  else if (options?.includeAllExtensionTools) {
3241
3499
  for (const tool of wrappedExtensionTools) {
3242
- nextActiveToolNames.push(tool.name);
3500
+ if (this._isActivatedOnRegistration(tool.name))
3501
+ nextActiveToolNames.push(tool.name);
3243
3502
  }
3244
3503
  }
3245
3504
  else if (!options?.activeToolNames) {
3246
3505
  for (const toolName of this._toolRegistry.keys()) {
3247
- if (!previousRegistryNames.has(toolName)) {
3506
+ if (!previousActivatedOnRegistration.has(toolName) && this._isActivatedOnRegistration(toolName)) {
3248
3507
  nextActiveToolNames.push(toolName);
3249
3508
  }
3250
3509
  }
3251
3510
  }
3252
3511
  this.setActiveToolsByName([...new Set(nextActiveToolNames)]);
3253
3512
  }
3513
+ /** Whether activating the tool declares it to the model. */
3514
+ _isDeclarable(name) {
3515
+ const exposure = this._getToolExposure(name);
3516
+ return exposure === "direct" || exposure === "model-only";
3517
+ }
3518
+ /** Whether registering the tool activates it, which declares it to the model. */
3519
+ _isActivatedOnRegistration(name) {
3520
+ return this._isDeclarable(name) && this._toolDefinitions.get(name)?.definition.defaultActive !== false;
3521
+ }
3254
3522
  _buildRuntime(options) {
3255
3523
  const autoResizeImages = this.settingsManager.getImageAutoResize();
3256
3524
  const shellCommandPrefix = this.settingsManager.getShellCommandPrefix();
@@ -3307,6 +3575,7 @@ export class AgentSession {
3307
3575
  if (hasBindings) {
3308
3576
  await options?.beforeSessionStart?.();
3309
3577
  await this._extensionRunner.emit({ type: "session_start", reason: "reload" });
3578
+ this._extensionRunner.reportUnhandledMcpServers();
3310
3579
  await this.extendResourcesFromExtensions("reload");
3311
3580
  }
3312
3581
  }
@@ -3323,7 +3592,7 @@ export class AgentSession {
3323
3592
  */
3324
3593
  _isRetryableError(message) {
3325
3594
  // Context overflow is handled by compaction, not retry.
3326
- if (isContextOverflow(message, this.model?.contextWindow ?? 0))
3595
+ if (isContextOverflow(message, (this._modelForMessage(message) ?? this.model)?.contextWindow ?? 0))
3327
3596
  return false;
3328
3597
  if (this._isPostAssistantPiServerSyncFailure(message))
3329
3598
  return false;
@@ -3637,15 +3906,11 @@ export class AgentSession {
3637
3906
  let summaryDetails;
3638
3907
  let summaryUsage;
3639
3908
  if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
3640
- const model = this.model;
3641
- const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
3909
+ const signal = this._branchSummaryAbortController.signal;
3642
3910
  const branchSummarySettings = this.settingsManager.getBranchSummarySettings();
3643
3911
  const result = await generateBranchSummary(entriesToSummarize, {
3644
- model: requestModel,
3645
- apiKey,
3646
- headers,
3647
- env,
3648
- signal: this._branchSummaryAbortController.signal,
3912
+ ...(await this._getSummarizationRequestAuth(this.model, signal)),
3913
+ signal,
3649
3914
  customInstructions,
3650
3915
  replaceInstructions,
3651
3916
  reserveTokens: branchSummarySettings.reserveTokens,
@@ -3814,7 +4079,7 @@ export class AgentSession {
3814
4079
  };
3815
4080
  }
3816
4081
  getContextUsage() {
3817
- const model = this.model;
4082
+ const model = this._limitsModel();
3818
4083
  if (!model)
3819
4084
  return undefined;
3820
4085
  const contextWindow = model.contextWindow ?? 0;
@@ -3908,16 +4173,11 @@ export class AgentSession {
3908
4173
  if (!model) {
3909
4174
  throw new Error("No model selected");
3910
4175
  }
3911
- const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
3912
4176
  return generateBugReportSummary({
4177
+ ...(await this._getSummarizationRequestAuth(model, options.signal)),
3913
4178
  messages: this.messages,
3914
4179
  hint: options.hint,
3915
- model: requestModel,
3916
- apiKey,
3917
- headers,
3918
- env,
3919
4180
  signal: options.signal,
3920
- thinkingLevel: this.thinkingLevel,
3921
4181
  streamFn: this.agent.streamFunction,
3922
4182
  retry: this.settingsManager.getRetrySettings(),
3923
4183
  sessionId: this.sessionId,