@averyyy/pi-coding-agent 0.87.1-piclient.1 → 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 (738) hide show
  1. package/CHANGELOG.md +98 -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 +120 -11
  92. package/dist/core/agent-session.d.ts.map +1 -1
  93. package/dist/core/agent-session.js +619 -289
  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 +10 -3
  114. package/dist/core/compaction/compaction.d.ts.map +1 -1
  115. package/dist/core/compaction/compaction.js +71 -33
  116. package/dist/core/compaction/compaction.js.map +1 -1
  117. package/dist/core/compaction/index.d.ts.map +1 -1
  118. package/dist/core/compaction/utils.d.ts +2 -1
  119. package/dist/core/compaction/utils.d.ts.map +1 -1
  120. package/dist/core/compaction/utils.js +25 -18
  121. package/dist/core/compaction/utils.js.map +1 -1
  122. package/dist/core/crash-log.d.ts.map +1 -1
  123. package/dist/core/crash-log.js +2 -1
  124. package/dist/core/crash-log.js.map +1 -1
  125. package/dist/core/defaults.d.ts.map +1 -1
  126. package/dist/core/diagnostics.d.ts.map +1 -1
  127. package/dist/core/event-bus.d.ts.map +1 -1
  128. package/dist/core/event-bus.js.map +1 -1
  129. package/dist/core/exec.d.ts.map +1 -1
  130. package/dist/core/exec.js.map +1 -1
  131. package/dist/core/experimental.d.ts.map +1 -1
  132. package/dist/core/experimental.js.map +1 -1
  133. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  134. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  135. package/dist/core/export-html/index.d.ts.map +1 -1
  136. package/dist/core/export-html/index.js.map +1 -1
  137. package/dist/core/export-html/template.css +10 -0
  138. package/dist/core/export-html/template.js +66 -17
  139. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  140. package/dist/core/export-html/tool-renderer.js.map +1 -1
  141. package/dist/core/extensions/index.d.ts +1 -1
  142. package/dist/core/extensions/index.d.ts.map +1 -1
  143. package/dist/core/extensions/index.js.map +1 -1
  144. package/dist/core/extensions/jiti-loader.d.ts.map +1 -1
  145. package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -1
  146. package/dist/core/extensions/loader.d.ts.map +1 -1
  147. package/dist/core/extensions/loader.js +55 -5
  148. package/dist/core/extensions/loader.js.map +1 -1
  149. package/dist/core/extensions/runner.d.ts +18 -1
  150. package/dist/core/extensions/runner.d.ts.map +1 -1
  151. package/dist/core/extensions/runner.js +99 -0
  152. package/dist/core/extensions/runner.js.map +1 -1
  153. package/dist/core/extensions/types.d.ts +296 -22
  154. package/dist/core/extensions/types.d.ts.map +1 -1
  155. package/dist/core/extensions/types.js.map +1 -1
  156. package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
  157. package/dist/core/extensions/wrapper.d.ts +2 -2
  158. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  159. package/dist/core/extensions/wrapper.js +3 -3
  160. package/dist/core/extensions/wrapper.js.map +1 -1
  161. package/dist/core/footer-data-provider.d.ts.map +1 -1
  162. package/dist/core/footer-data-provider.js.map +1 -1
  163. package/dist/core/http-dispatcher.d.ts.map +1 -1
  164. package/dist/core/http-dispatcher.js.map +1 -1
  165. package/dist/core/index.d.ts.map +1 -1
  166. package/dist/core/keybindings.d.ts +1 -1
  167. package/dist/core/keybindings.d.ts.map +1 -1
  168. package/dist/core/keybindings.js +1 -1
  169. package/dist/core/keybindings.js.map +1 -1
  170. package/dist/core/mcp-servers.d.ts +98 -0
  171. package/dist/core/mcp-servers.d.ts.map +1 -0
  172. package/dist/core/mcp-servers.js +157 -0
  173. package/dist/core/mcp-servers.js.map +1 -0
  174. package/dist/core/messages.d.ts.map +1 -1
  175. package/dist/core/messages.js.map +1 -1
  176. package/dist/core/model-config.d.ts.map +1 -1
  177. package/dist/core/model-config.js.map +1 -1
  178. package/dist/core/model-registry.d.ts +13 -1
  179. package/dist/core/model-registry.d.ts.map +1 -1
  180. package/dist/core/model-registry.js +25 -0
  181. package/dist/core/model-registry.js.map +1 -1
  182. package/dist/core/model-resolver.d.ts +2 -2
  183. package/dist/core/model-resolver.d.ts.map +1 -1
  184. package/dist/core/model-resolver.js +5 -5
  185. package/dist/core/model-resolver.js.map +1 -1
  186. package/dist/core/model-runtime.d.ts +41 -3
  187. package/dist/core/model-runtime.d.ts.map +1 -1
  188. package/dist/core/model-runtime.js +167 -17
  189. package/dist/core/model-runtime.js.map +1 -1
  190. package/dist/core/models-store.d.ts.map +1 -1
  191. package/dist/core/models-store.js.map +1 -1
  192. package/dist/core/nested-tool-calls.d.ts +102 -0
  193. package/dist/core/nested-tool-calls.d.ts.map +1 -0
  194. package/dist/core/nested-tool-calls.js +178 -0
  195. package/dist/core/nested-tool-calls.js.map +1 -0
  196. package/dist/core/output-guard.d.ts.map +1 -1
  197. package/dist/core/output-guard.js.map +1 -1
  198. package/dist/core/package-manager.d.ts +4 -0
  199. package/dist/core/package-manager.d.ts.map +1 -1
  200. package/dist/core/package-manager.js +59 -12
  201. package/dist/core/package-manager.js.map +1 -1
  202. package/dist/core/pi-client-cli-adapter.d.ts.map +1 -1
  203. package/dist/core/pi-client-cli-adapter.js.map +1 -1
  204. package/dist/core/pi-client-runtime-update.d.ts.map +1 -1
  205. package/dist/core/pi-client-runtime-update.js.map +1 -1
  206. package/dist/core/pi-manifest.d.ts.map +1 -1
  207. package/dist/core/pi-manifest.js.map +1 -1
  208. package/dist/core/pi-server-client.d.ts +5 -0
  209. package/dist/core/pi-server-client.d.ts.map +1 -1
  210. package/dist/core/pi-server-client.js +3 -0
  211. package/dist/core/pi-server-client.js.map +1 -1
  212. package/dist/core/pi-server-protocol.d.ts +2 -1
  213. package/dist/core/pi-server-protocol.d.ts.map +1 -1
  214. package/dist/core/pi-server-protocol.js +16 -0
  215. package/dist/core/pi-server-protocol.js.map +1 -1
  216. package/dist/core/pi-server-request.d.ts.map +1 -1
  217. package/dist/core/pi-server-request.js.map +1 -1
  218. package/dist/core/project-trust.d.ts.map +1 -1
  219. package/dist/core/project-trust.js.map +1 -1
  220. package/dist/core/prompt-templates.d.ts.map +1 -1
  221. package/dist/core/prompt-templates.js.map +1 -1
  222. package/dist/core/provider-attribution.d.ts.map +1 -1
  223. package/dist/core/provider-attribution.js.map +1 -1
  224. package/dist/core/provider-composer.d.ts +40 -21
  225. package/dist/core/provider-composer.d.ts.map +1 -1
  226. package/dist/core/provider-composer.js +92 -40
  227. package/dist/core/provider-composer.js.map +1 -1
  228. package/dist/core/radius.d.ts.map +1 -1
  229. package/dist/core/radius.js.map +1 -1
  230. package/dist/core/remote-catalog-provider.d.ts +8 -1
  231. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  232. package/dist/core/remote-catalog-provider.js +18 -3
  233. package/dist/core/remote-catalog-provider.js.map +1 -1
  234. package/dist/core/resolve-config-value.d.ts.map +1 -1
  235. package/dist/core/resolve-config-value.js.map +1 -1
  236. package/dist/core/resource-loader.d.ts +7 -1
  237. package/dist/core/resource-loader.d.ts.map +1 -1
  238. package/dist/core/resource-loader.js +161 -35
  239. package/dist/core/resource-loader.js.map +1 -1
  240. package/dist/core/runtime-credentials.d.ts.map +1 -1
  241. package/dist/core/runtime-credentials.js.map +1 -1
  242. package/dist/core/sdk.d.ts +1 -1
  243. package/dist/core/sdk.d.ts.map +1 -1
  244. package/dist/core/sdk.js +24 -6
  245. package/dist/core/sdk.js.map +1 -1
  246. package/dist/core/session-cwd.d.ts.map +1 -1
  247. package/dist/core/session-cwd.js.map +1 -1
  248. package/dist/core/session-export.d.ts.map +1 -1
  249. package/dist/core/session-export.js.map +1 -1
  250. package/dist/core/session-manager.d.ts +9 -0
  251. package/dist/core/session-manager.d.ts.map +1 -1
  252. package/dist/core/session-manager.js +22 -22
  253. package/dist/core/session-manager.js.map +1 -1
  254. package/dist/core/settings-diagnostics.d.ts.map +1 -1
  255. package/dist/core/settings-diagnostics.js.map +1 -1
  256. package/dist/core/settings-manager.d.ts +31 -1
  257. package/dist/core/settings-manager.d.ts.map +1 -1
  258. package/dist/core/settings-manager.js +72 -2
  259. package/dist/core/settings-manager.js.map +1 -1
  260. package/dist/core/skills.d.ts.map +1 -1
  261. package/dist/core/skills.js.map +1 -1
  262. package/dist/core/slash-commands.d.ts.map +1 -1
  263. package/dist/core/source-info.d.ts +8 -0
  264. package/dist/core/source-info.d.ts.map +1 -1
  265. package/dist/core/source-info.js +16 -0
  266. package/dist/core/source-info.js.map +1 -1
  267. package/dist/core/system-prompt.d.ts.map +1 -1
  268. package/dist/core/system-prompt.js +1 -1
  269. package/dist/core/system-prompt.js.map +1 -1
  270. package/dist/core/telemetry.d.ts.map +1 -1
  271. package/dist/core/telemetry.js.map +1 -1
  272. package/dist/core/timings.d.ts.map +1 -1
  273. package/dist/core/timings.js.map +1 -1
  274. package/dist/core/tools/bash.d.ts +12 -0
  275. package/dist/core/tools/bash.d.ts.map +1 -1
  276. package/dist/core/tools/bash.js +35 -2
  277. package/dist/core/tools/bash.js.map +1 -1
  278. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  279. package/dist/core/tools/edit-diff.js.map +1 -1
  280. package/dist/core/tools/edit.d.ts.map +1 -1
  281. package/dist/core/tools/edit.js.map +1 -1
  282. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  283. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  284. package/dist/core/tools/find.d.ts.map +1 -1
  285. package/dist/core/tools/find.js.map +1 -1
  286. package/dist/core/tools/grep.d.ts.map +1 -1
  287. package/dist/core/tools/grep.js.map +1 -1
  288. package/dist/core/tools/index.d.ts.map +1 -1
  289. package/dist/core/tools/index.js.map +1 -1
  290. package/dist/core/tools/ls.d.ts.map +1 -1
  291. package/dist/core/tools/ls.js.map +1 -1
  292. package/dist/core/tools/output-accumulator.d.ts +11 -0
  293. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  294. package/dist/core/tools/output-accumulator.js +36 -0
  295. package/dist/core/tools/output-accumulator.js.map +1 -1
  296. package/dist/core/tools/path-utils.d.ts.map +1 -1
  297. package/dist/core/tools/path-utils.js.map +1 -1
  298. package/dist/core/tools/powershell.d.ts.map +1 -1
  299. package/dist/core/tools/powershell.js.map +1 -1
  300. package/dist/core/tools/read.d.ts.map +1 -1
  301. package/dist/core/tools/read.js.map +1 -1
  302. package/dist/core/tools/render-utils.d.ts +6 -0
  303. package/dist/core/tools/render-utils.d.ts.map +1 -1
  304. package/dist/core/tools/render-utils.js +26 -0
  305. package/dist/core/tools/render-utils.js.map +1 -1
  306. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  307. package/dist/core/tools/renderers/bash.js +9 -10
  308. package/dist/core/tools/renderers/bash.js.map +1 -1
  309. package/dist/core/tools/renderers/edit.d.ts.map +1 -1
  310. package/dist/core/tools/renderers/edit.js.map +1 -1
  311. package/dist/core/tools/renderers/find.d.ts.map +1 -1
  312. package/dist/core/tools/renderers/find.js.map +1 -1
  313. package/dist/core/tools/renderers/grep.d.ts.map +1 -1
  314. package/dist/core/tools/renderers/grep.js.map +1 -1
  315. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  316. package/dist/core/tools/renderers/index.js.map +1 -1
  317. package/dist/core/tools/renderers/ls.d.ts.map +1 -1
  318. package/dist/core/tools/renderers/ls.js.map +1 -1
  319. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  320. package/dist/core/tools/renderers/read.js +3 -2
  321. package/dist/core/tools/renderers/read.js.map +1 -1
  322. package/dist/core/tools/renderers/write.d.ts.map +1 -1
  323. package/dist/core/tools/renderers/write.js.map +1 -1
  324. package/dist/core/tools/tool-definition-wrapper.d.ts +5 -3
  325. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  326. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  327. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  328. package/dist/core/tools/truncate.d.ts +14 -0
  329. package/dist/core/tools/truncate.d.ts.map +1 -1
  330. package/dist/core/tools/truncate.js +29 -0
  331. package/dist/core/tools/truncate.js.map +1 -1
  332. package/dist/core/tools/write.d.ts.map +1 -1
  333. package/dist/core/tools/write.js.map +1 -1
  334. package/dist/core/trust-manager.d.ts.map +1 -1
  335. package/dist/core/trust-manager.js +1 -0
  336. package/dist/core/trust-manager.js.map +1 -1
  337. package/dist/core/usage-totals.d.ts +2 -0
  338. package/dist/core/usage-totals.d.ts.map +1 -1
  339. package/dist/core/usage-totals.js +23 -0
  340. package/dist/core/usage-totals.js.map +1 -1
  341. package/dist/core/virtual-models.d.ts +115 -0
  342. package/dist/core/virtual-models.d.ts.map +1 -0
  343. package/dist/core/virtual-models.js +117 -0
  344. package/dist/core/virtual-models.js.map +1 -0
  345. package/dist/extensions/codemode/execute.d.ts +16 -0
  346. package/dist/extensions/codemode/execute.d.ts.map +1 -0
  347. package/dist/extensions/codemode/execute.js +390 -0
  348. package/dist/extensions/codemode/execute.js.map +1 -0
  349. package/dist/extensions/codemode/execute.lazy.d.ts +3 -0
  350. package/dist/extensions/codemode/execute.lazy.d.ts.map +1 -0
  351. package/dist/extensions/codemode/execute.lazy.js +3 -0
  352. package/dist/extensions/codemode/execute.lazy.js.map +1 -0
  353. package/dist/extensions/codemode/index.d.ts +21 -0
  354. package/dist/extensions/codemode/index.d.ts.map +1 -0
  355. package/dist/extensions/codemode/index.js +31 -0
  356. package/dist/extensions/codemode/index.js.map +1 -0
  357. package/dist/extensions/codemode/renderer.d.ts +12 -0
  358. package/dist/extensions/codemode/renderer.d.ts.map +1 -0
  359. package/dist/extensions/codemode/renderer.js +119 -0
  360. package/dist/extensions/codemode/renderer.js.map +1 -0
  361. package/dist/extensions/codemode/tool.d.ts +122 -0
  362. package/dist/extensions/codemode/tool.d.ts.map +1 -0
  363. package/dist/extensions/codemode/tool.js +324 -0
  364. package/dist/extensions/codemode/tool.js.map +1 -0
  365. package/dist/extensions/codemode/worker.d.ts +7 -0
  366. package/dist/extensions/codemode/worker.d.ts.map +1 -0
  367. package/dist/extensions/codemode/worker.js +7 -0
  368. package/dist/extensions/codemode/worker.js.map +1 -0
  369. package/dist/extensions/index.d.ts.map +1 -1
  370. package/dist/extensions/index.js +11 -1
  371. package/dist/extensions/index.js.map +1 -1
  372. package/dist/extensions/llama/client.d.ts.map +1 -1
  373. package/dist/extensions/llama/client.js.map +1 -1
  374. package/dist/extensions/llama/huggingface.d.ts.map +1 -1
  375. package/dist/extensions/llama/huggingface.js.map +1 -1
  376. package/dist/extensions/llama/index.d.ts.map +1 -1
  377. package/dist/extensions/llama/index.js.map +1 -1
  378. package/dist/extensions/llama/provider.d.ts +1 -1
  379. package/dist/extensions/llama/provider.d.ts.map +1 -1
  380. package/dist/extensions/llama/provider.js +65 -13
  381. package/dist/extensions/llama/provider.js.map +1 -1
  382. package/dist/extensions/llama/ui.d.ts.map +1 -1
  383. package/dist/extensions/llama/ui.js.map +1 -1
  384. package/dist/extensions/mcp/cli.d.ts +21 -0
  385. package/dist/extensions/mcp/cli.d.ts.map +1 -0
  386. package/dist/extensions/mcp/cli.js +485 -0
  387. package/dist/extensions/mcp/cli.js.map +1 -0
  388. package/dist/extensions/mcp/cli.lazy.d.ts +3 -0
  389. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -0
  390. package/dist/extensions/mcp/cli.lazy.js +3 -0
  391. package/dist/extensions/mcp/cli.lazy.js.map +1 -0
  392. package/dist/extensions/mcp/config.d.ts +70 -0
  393. package/dist/extensions/mcp/config.d.ts.map +1 -0
  394. package/dist/extensions/mcp/config.js +146 -0
  395. package/dist/extensions/mcp/config.js.map +1 -0
  396. package/dist/extensions/mcp/index.d.ts +52 -0
  397. package/dist/extensions/mcp/index.d.ts.map +1 -0
  398. package/dist/extensions/mcp/index.js +902 -0
  399. package/dist/extensions/mcp/index.js.map +1 -0
  400. package/dist/extensions/mcp/log.d.ts +16 -0
  401. package/dist/extensions/mcp/log.d.ts.map +1 -0
  402. package/dist/extensions/mcp/log.js +66 -0
  403. package/dist/extensions/mcp/log.js.map +1 -0
  404. package/dist/extensions/mcp/oauth.d.ts +94 -0
  405. package/dist/extensions/mcp/oauth.d.ts.map +1 -0
  406. package/dist/extensions/mcp/oauth.js +333 -0
  407. package/dist/extensions/mcp/oauth.js.map +1 -0
  408. package/dist/extensions/mcp/resources.d.ts +43 -0
  409. package/dist/extensions/mcp/resources.d.ts.map +1 -0
  410. package/dist/extensions/mcp/resources.js +262 -0
  411. package/dist/extensions/mcp/resources.js.map +1 -0
  412. package/dist/extensions/mcp/runtime.d.ts +96 -0
  413. package/dist/extensions/mcp/runtime.d.ts.map +1 -0
  414. package/dist/extensions/mcp/runtime.js +388 -0
  415. package/dist/extensions/mcp/runtime.js.map +1 -0
  416. package/dist/extensions/mcp/runtime.lazy.d.ts +3 -0
  417. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -0
  418. package/dist/extensions/mcp/runtime.lazy.js +3 -0
  419. package/dist/extensions/mcp/runtime.lazy.js.map +1 -0
  420. package/dist/extensions/mcp/tools.d.ts +83 -0
  421. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  422. package/dist/extensions/mcp/tools.js +233 -0
  423. package/dist/extensions/mcp/tools.js.map +1 -0
  424. package/dist/extensions/mcp/ui.d.ts +60 -0
  425. package/dist/extensions/mcp/ui.d.ts.map +1 -0
  426. package/dist/extensions/mcp/ui.js +172 -0
  427. package/dist/extensions/mcp/ui.js.map +1 -0
  428. package/dist/extensions/tool-search/index.d.ts +12 -0
  429. package/dist/extensions/tool-search/index.d.ts.map +1 -0
  430. package/dist/extensions/tool-search/index.js +15 -0
  431. package/dist/extensions/tool-search/index.js.map +1 -0
  432. package/dist/extensions/tool-search/tool.d.ts +72 -0
  433. package/dist/extensions/tool-search/tool.d.ts.map +1 -0
  434. package/dist/extensions/tool-search/tool.js +210 -0
  435. package/dist/extensions/tool-search/tool.js.map +1 -0
  436. package/dist/index.d.ts +9 -2
  437. package/dist/index.d.ts.map +1 -1
  438. package/dist/index.js +5 -0
  439. package/dist/index.js.map +1 -1
  440. package/dist/main.d.ts.map +1 -1
  441. package/dist/main.js +10 -0
  442. package/dist/main.js.map +1 -1
  443. package/dist/migrations.d.ts.map +1 -1
  444. package/dist/migrations.js.map +1 -1
  445. package/dist/modes/index.d.ts.map +1 -1
  446. package/dist/modes/interactive/bug-report.d.ts.map +1 -1
  447. package/dist/modes/interactive/bug-report.js.map +1 -1
  448. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
  449. package/dist/modes/interactive/chat-viewport.js.map +1 -1
  450. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  451. package/dist/modes/interactive/components/armin.js.map +1 -1
  452. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  453. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  454. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  455. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  456. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  457. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  458. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  459. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  460. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  461. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  462. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  463. package/dist/modes/interactive/components/config-selector.js +13 -3
  464. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  465. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  466. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  467. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  468. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  469. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  470. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  471. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  472. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  473. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  474. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  475. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  476. package/dist/modes/interactive/components/diff.js.map +1 -1
  477. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  478. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  479. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  480. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  481. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  482. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  483. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  484. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  485. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  486. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  487. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  488. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  489. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  490. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  491. package/dist/modes/interactive/components/footer.d.ts +7 -0
  492. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  493. package/dist/modes/interactive/components/footer.js +43 -3
  494. package/dist/modes/interactive/components/footer.js.map +1 -1
  495. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  496. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  497. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  498. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  499. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  500. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  501. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  502. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  503. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  504. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  505. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  506. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  507. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  508. package/dist/modes/interactive/components/pi-logo.d.ts +12 -0
  509. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -0
  510. package/dist/modes/interactive/components/pi-logo.js +25 -0
  511. package/dist/modes/interactive/components/pi-logo.js.map +1 -0
  512. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  513. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  514. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  515. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  516. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  517. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  518. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  519. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  520. package/dist/modes/interactive/components/settings-selector.js +28 -6
  521. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  522. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  523. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  524. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  525. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  526. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  527. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  528. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  529. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  530. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  531. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  532. package/dist/modes/interactive/components/themed-text.d.ts +17 -0
  533. package/dist/modes/interactive/components/themed-text.d.ts.map +1 -0
  534. package/dist/modes/interactive/components/themed-text.js +29 -0
  535. package/dist/modes/interactive/components/themed-text.js.map +1 -0
  536. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  537. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  538. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  539. package/dist/modes/interactive/components/tool-execution.js +2 -2
  540. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  541. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  542. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  543. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  544. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  545. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  546. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  547. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  548. package/dist/modes/interactive/components/user-message.js.map +1 -1
  549. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  550. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  551. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  552. package/dist/modes/interactive/external-editor.js.map +1 -1
  553. package/dist/modes/interactive/interactive-mode.d.ts +11 -0
  554. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  555. package/dist/modes/interactive/interactive-mode.js +199 -161
  556. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  557. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -1
  558. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -1
  559. package/dist/modes/interactive/model-search.d.ts.map +1 -1
  560. package/dist/modes/interactive/model-search.js.map +1 -1
  561. package/dist/modes/interactive/session-share.d.ts.map +1 -1
  562. package/dist/modes/interactive/session-share.js.map +1 -1
  563. package/dist/modes/interactive/theme/dark.json +59 -72
  564. package/dist/modes/interactive/theme/light.json +57 -69
  565. package/dist/modes/interactive/theme/system-theme.d.ts +54 -0
  566. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
  567. package/dist/modes/interactive/theme/system-theme.js +535 -0
  568. package/dist/modes/interactive/theme/system-theme.js.map +1 -0
  569. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  570. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  571. package/dist/modes/interactive/theme/theme-controller.js +127 -47
  572. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  573. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  574. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -1
  575. package/dist/modes/interactive/theme/theme-json.js +3 -1
  576. package/dist/modes/interactive/theme/theme-json.js.map +1 -1
  577. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  578. package/dist/modes/interactive/theme/theme.d.ts +66 -39
  579. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  580. package/dist/modes/interactive/theme/theme.js +238 -317
  581. package/dist/modes/interactive/theme/theme.js.map +1 -1
  582. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  583. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  584. package/dist/modes/interactive/tui-renderer.js +1 -0
  585. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  586. package/dist/modes/json-event.d.ts.map +1 -1
  587. package/dist/modes/json-event.js.map +1 -1
  588. package/dist/modes/print-mode.d.ts.map +1 -1
  589. package/dist/modes/print-mode.js.map +1 -1
  590. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  591. package/dist/modes/rpc/jsonl.js.map +1 -1
  592. package/dist/modes/rpc/rpc-client.d.ts +6 -6
  593. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  594. package/dist/modes/rpc/rpc-client.js +12 -8
  595. package/dist/modes/rpc/rpc-client.js.map +1 -1
  596. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  597. package/dist/modes/rpc/rpc-mode.js +7 -9
  598. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  599. package/dist/modes/rpc/rpc-types.d.ts +10 -1
  600. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  601. package/dist/modes/rpc/rpc-types.js.map +1 -1
  602. package/dist/package-manager-cli.d.ts.map +1 -1
  603. package/dist/package-manager-cli.js +6 -2
  604. package/dist/package-manager-cli.js.map +1 -1
  605. package/dist/pi-client-cli.d.ts.map +1 -1
  606. package/dist/pi-client-cli.js.map +1 -1
  607. package/dist/rpc-entry.d.ts.map +1 -1
  608. package/dist/rpc-entry.js.map +1 -1
  609. package/dist/utils/abort.d.ts.map +1 -1
  610. package/dist/utils/abort.js.map +1 -1
  611. package/dist/utils/ansi.d.ts.map +1 -1
  612. package/dist/utils/ansi.js.map +1 -1
  613. package/dist/utils/changelog.d.ts.map +1 -1
  614. package/dist/utils/changelog.js.map +1 -1
  615. package/dist/utils/child-process.d.ts.map +1 -1
  616. package/dist/utils/child-process.js.map +1 -1
  617. package/dist/utils/clipboard-command.d.ts.map +1 -1
  618. package/dist/utils/clipboard-command.js.map +1 -1
  619. package/dist/utils/clipboard-image.d.ts.map +1 -1
  620. package/dist/utils/clipboard-image.js +14 -17
  621. package/dist/utils/clipboard-image.js.map +1 -1
  622. package/dist/utils/clipboard.d.ts +2 -0
  623. package/dist/utils/clipboard.d.ts.map +1 -1
  624. package/dist/utils/clipboard.js +5 -0
  625. package/dist/utils/clipboard.js.map +1 -1
  626. package/dist/utils/deprecation.d.ts.map +1 -1
  627. package/dist/utils/deprecation.js.map +1 -1
  628. package/dist/utils/exif-orientation.d.ts.map +1 -1
  629. package/dist/utils/exif-orientation.js.map +1 -1
  630. package/dist/utils/frontmatter.d.ts.map +1 -1
  631. package/dist/utils/frontmatter.js.map +1 -1
  632. package/dist/utils/fs-watch.d.ts.map +1 -1
  633. package/dist/utils/fs-watch.js.map +1 -1
  634. package/dist/utils/git.d.ts.map +1 -1
  635. package/dist/utils/git.js.map +1 -1
  636. package/dist/utils/html.d.ts.map +1 -1
  637. package/dist/utils/html.js.map +1 -1
  638. package/dist/utils/image-convert.d.ts.map +1 -1
  639. package/dist/utils/image-convert.js.map +1 -1
  640. package/dist/utils/image-process.d.ts.map +1 -1
  641. package/dist/utils/image-process.js.map +1 -1
  642. package/dist/utils/image-resize-core.d.ts.map +1 -1
  643. package/dist/utils/image-resize-core.js.map +1 -1
  644. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  645. package/dist/utils/image-resize-worker.js.map +1 -1
  646. package/dist/utils/image-resize.d.ts.map +1 -1
  647. package/dist/utils/image-resize.js.map +1 -1
  648. package/dist/utils/json.d.ts.map +1 -1
  649. package/dist/utils/json.js.map +1 -1
  650. package/dist/utils/management-http.d.ts.map +1 -1
  651. package/dist/utils/management-http.js.map +1 -1
  652. package/dist/utils/mime.d.ts.map +1 -1
  653. package/dist/utils/mime.js.map +1 -1
  654. package/dist/utils/open-browser.d.ts.map +1 -1
  655. package/dist/utils/open-browser.js.map +1 -1
  656. package/dist/utils/paths.d.ts +3 -3
  657. package/dist/utils/paths.d.ts.map +1 -1
  658. package/dist/utils/paths.js +5 -4
  659. package/dist/utils/paths.js.map +1 -1
  660. package/dist/utils/photon.d.ts.map +1 -1
  661. package/dist/utils/photon.js.map +1 -1
  662. package/dist/utils/pi-user-agent.d.ts.map +1 -1
  663. package/dist/utils/pi-user-agent.js.map +1 -1
  664. package/dist/utils/shell.d.ts +1 -3
  665. package/dist/utils/shell.d.ts.map +1 -1
  666. package/dist/utils/shell.js +3 -30
  667. package/dist/utils/shell.js.map +1 -1
  668. package/dist/utils/sleep.d.ts.map +1 -1
  669. package/dist/utils/sleep.js.map +1 -1
  670. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  671. package/dist/utils/syntax-highlight.js +2 -0
  672. package/dist/utils/syntax-highlight.js.map +1 -1
  673. package/dist/utils/text.d.ts.map +1 -1
  674. package/dist/utils/text.js.map +1 -1
  675. package/dist/utils/tool-result-images.d.ts.map +1 -1
  676. package/dist/utils/tool-result-images.js.map +1 -1
  677. package/dist/utils/tools-manager.d.ts.map +1 -1
  678. package/dist/utils/tools-manager.js.map +1 -1
  679. package/dist/utils/version-check.d.ts.map +1 -1
  680. package/dist/utils/version-check.js.map +1 -1
  681. package/dist/utils/windows-self-update.d.ts.map +1 -1
  682. package/dist/utils/windows-self-update.js.map +1 -1
  683. package/dist/utils/wsl.d.ts.map +1 -1
  684. package/dist/utils/wsl.js.map +1 -1
  685. package/dist/utils/zip.d.ts.map +1 -1
  686. package/dist/utils/zip.js.map +1 -1
  687. package/docs/cli.md +64 -3
  688. package/docs/configuration.md +2 -0
  689. package/docs/custom-provider.md +43 -4
  690. package/docs/docs.json +8 -0
  691. package/docs/extensions.md +55 -0
  692. package/docs/keybindings.md +1 -1
  693. package/docs/llama-cpp.md +13 -0
  694. package/docs/mcp.md +188 -0
  695. package/docs/models.md +35 -0
  696. package/docs/packages.md +4 -2
  697. package/docs/providers.md +1 -0
  698. package/docs/rpc-commands.md +9 -3
  699. package/docs/rpc.md +3 -1
  700. package/docs/sdk.md +7 -2
  701. package/docs/security.md +2 -0
  702. package/docs/session-format.md +5 -1
  703. package/docs/settings.md +20 -3
  704. package/docs/themes.md +33 -7
  705. package/docs/tui.md +18 -0
  706. package/docs/virtual-models.md +114 -0
  707. package/docs/windows.md +2 -0
  708. package/examples/README.md +1 -1
  709. package/examples/extensions/README.md +2 -0
  710. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  711. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  712. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  713. package/examples/extensions/custom-provider-gitlab-duo/test.ts +5 -5
  714. package/examples/extensions/debug-provider.ts +90 -0
  715. package/examples/extensions/gondolin/package-lock.json +2 -2
  716. package/examples/extensions/gondolin/package.json +1 -1
  717. package/examples/extensions/jev-router.ts +113 -0
  718. package/examples/extensions/sandbox/package-lock.json +2 -2
  719. package/examples/extensions/sandbox/package.json +1 -1
  720. package/examples/extensions/with-deps/package-lock.json +2 -2
  721. package/examples/extensions/with-deps/package.json +1 -1
  722. package/examples/rpc-client.ts +1 -1
  723. package/examples/rpc-extension-ui.ts +1 -1
  724. package/examples/sdk/14-codemode-mcp.ts +61 -0
  725. package/examples/sdk/README.md +2 -1
  726. package/package.json +14 -12
  727. package/dist/bundle/chunks/anthropic-messages-J5WXPPPC.js +0 -6
  728. package/dist/bundle/chunks/azure-openai-responses-QJ7SPP5M.js +0 -2
  729. package/dist/bundle/chunks/chunk-6R7UI4IY.js +0 -2
  730. package/dist/bundle/chunks/chunk-CGLIERPR.js +0 -2
  731. package/dist/bundle/chunks/chunk-G4PLSCJV.js +0 -1669
  732. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
  733. package/dist/bundle/chunks/chunk-RCZIEVGO.js +0 -11
  734. package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +0 -2
  735. package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +0 -2
  736. package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +0 -5
  737. package/dist/bundle/chunks/openai-responses-AH7QTG23.js +0 -2
  738. package/dist/bundle/chunks/virtual-modules-LRIRMGSI.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,15 +34,18 @@ import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
33
34
  import { emitSessionShutdownEvent } from "./extensions/runner.js";
34
35
  import { convertToLlm } from "./messages.js";
35
36
  import { ModelRegistry } from "./model-registry.js";
36
- import { cancelPiServerOperations, compactPiServer, } from "./pi-server-client.js";
37
+ import { NestedToolCallRunner } from "./nested-tool-calls.js";
38
+ import { cancelPiServerOperations, compactPiServer, hashStaticContext, } from "./pi-server-client.js";
39
+ import { hashPiServerProviderMessages } from "./pi-server-protocol.js";
37
40
  import { expandPromptTemplate } from "./prompt-templates.js";
38
41
  import { CURRENT_SESSION_VERSION, getLatestCompactionEntry, SessionManager, } from "./session-manager.js";
39
- import { createSyntheticSourceInfo } from "./source-info.js";
42
+ import { BUILTIN_PATH_PREFIX, createSyntheticSourceInfo, isSyntheticPath } from "./source-info.js";
40
43
  import { buildSystemPrompt, buildSystemPromptSections, diffSystemPromptSections, normalizeBuildSystemPromptOptions, } from "./system-prompt.js";
41
44
  import { createLocalBashOperations } from "./tools/bash.js";
42
45
  import { createAllToolDefinitions } from "./tools/index.js";
43
46
  import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
44
- import { addUsageToTotals, createUsageTotals } 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";
45
49
  /**
46
50
  * Parse a skill block from message text.
47
51
  * Returns null if the text doesn't contain a skill block.
@@ -195,12 +199,18 @@ export class AgentSession {
195
199
  _prePromptCompletionPromise = undefined;
196
200
  _overflowRecoveryAttempted = false;
197
201
  _lastServerCompactionTimestamp = undefined;
202
+ _cachePrefixUnavailableReason;
198
203
  // Branch summarization state
199
204
  _branchSummaryAbortController = undefined;
200
205
  _branchSummaryCompletionPromise = undefined;
201
206
  // Retry state
202
207
  _retryAbortController = undefined;
203
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;
204
214
  // Post-turn session naming is a provider request too, so cancellation must reach it.
205
215
  _sessionNameAbortController = undefined;
206
216
  // Bash execution state
@@ -242,6 +252,10 @@ export class AgentSession {
242
252
  _cacheWarmer;
243
253
  // Tool registry for extension getTools/setTools
244
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();
245
259
  _toolDefinitions = new Map();
246
260
  _toolPromptSnippets = new Map();
247
261
  _toolPromptGuidelines = new Map();
@@ -278,6 +292,7 @@ export class AgentSession {
278
292
  this._installAgentNextTurnRefresh();
279
293
  this._installAgentRequestProjection();
280
294
  this._installAgentBoundaryHooks();
295
+ this._installHiddenDeclarationsProjection();
281
296
  this._installAgentForcedPromptProjection();
282
297
  this._buildRuntime({
283
298
  activeToolNames: this._initialActiveToolNames,
@@ -328,28 +343,71 @@ export class AgentSession {
328
343
  }
329
344
  throw new Error(formatNoApiKeyFoundMessage(model.provider));
330
345
  }
331
- 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 };
332
355
  if (this.agent.streamFunction === streamSimple) {
333
- return this._getRequiredRequestAuth(model, signal);
356
+ return { ...(await this._getRequiredRequestAuth(model, signal)), thinkingLevel };
334
357
  }
335
358
  try {
336
359
  const result = await this._modelRuntime.getAuth(model, { signal });
337
360
  if (!result)
338
- return { model };
361
+ return { model, thinkingLevel };
339
362
  const requestModel = result.auth.baseUrl ? { ...model, baseUrl: result.auth.baseUrl } : model;
340
363
  return {
341
364
  model: requestModel,
342
365
  apiKey: result.auth.apiKey,
343
366
  headers: withoutDeletedHeaders(result.auth.headers),
344
367
  env: result.env,
368
+ thinkingLevel,
345
369
  };
346
370
  }
347
371
  catch (error) {
348
372
  if (signal?.aborted)
349
373
  throw error;
350
- return { model };
374
+ return { model, thinkingLevel };
351
375
  }
352
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
+ }
353
411
  /**
354
412
  * Install tool hooks once on the Agent instance.
355
413
  *
@@ -359,67 +417,114 @@ export class AgentSession {
359
417
  * happens here instead of in wrappers.
360
418
  */
361
419
  _installAgentToolHooks() {
362
- this.agent.beforeToolCall = async ({ toolCall, args }) => {
363
- const runner = this._extensionRunner;
364
- if (!runner.hasHandlers("tool_call")) {
365
- return undefined;
366
- }
367
- try {
368
- return await runner.emitToolCall({
369
- type: "tool_call",
370
- toolName: toolCall.name,
371
- toolCallId: toolCall.id,
372
- input: args,
373
- });
374
- }
375
- catch (err) {
376
- if (err instanceof Error) {
377
- throw err;
378
- }
379
- throw new Error(`Extension failed, blocking execution: ${String(err)}`);
380
- }
381
- };
382
- this.agent.afterToolCall = async ({ toolCall, args, result, isError }) => {
383
- const runner = this._extensionRunner;
384
- const hookResult = runner.hasHandlers("tool_result")
385
- ? await runner.emitToolResult({
386
- type: "tool_result",
387
- toolName: toolCall.name,
388
- toolCallId: toolCall.id,
389
- input: args,
390
- content: result.content,
391
- details: result.details,
392
- isError,
393
- usage: result.usage,
394
- })
395
- : undefined;
396
- const content = hookResult?.content ?? result.content ?? [];
397
- // Runs after the extension hook so images injected or replaced by extensions are normalized too.
398
- const resizeOptions = this.model?.inputLimits?.images?.resize;
399
- const normalizedContent = await normalizeToolResultImages(content, {
400
- autoResizeImages: this.settingsManager.getImageAutoResize(),
401
- ...(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,
402
436
  });
403
- if (!hookResult && normalizedContent === content) {
404
- return undefined;
437
+ }
438
+ catch (err) {
439
+ if (err instanceof Error) {
440
+ throw err;
405
441
  }
406
- return {
407
- content: normalizedContent,
408
- details: hookResult?.details,
409
- isError: hookResult?.isError ?? isError,
410
- usage: hookResult?.usage,
411
- };
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,
412
479
  };
413
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
+ }
414
521
  async _compactBeforeNextAssistantResponse(context, signal) {
415
522
  if (signal?.aborted)
416
523
  return context;
417
- const model = this.model;
418
- const settings = this.settingsManager.getCompactionSettings(model);
419
524
  const projection = this.sessionManager.buildSessionProjection();
420
- if (!model ||
421
- model.contextWindow <= 0 ||
422
- !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)) {
423
528
  return { ...context, messages: projection.messages };
424
529
  }
425
530
  await this._runAutoCompaction("threshold", false, undefined, undefined, signal);
@@ -427,25 +532,58 @@ export class AgentSession {
427
532
  }
428
533
  _installAgentRequestProjection() {
429
534
  const previousPrepareRequest = this.agent.prepareRequest;
535
+ if (previousPrepareRequest)
536
+ this._cachePrefixUnavailableReason ??= "custom_prepare_request";
430
537
  this.agent.prepareRequest = async (request, signal) => {
431
- const canonicalContext = {
432
- ...request.context,
433
- messages: this.sessionManager.buildSessionProjection().messages,
434
- // Messages declare the provider-visible loadout; context.tools keeps executable implementations.
435
- tools: this.agent.state.tools.slice(),
436
- };
437
- const previous = await previousPrepareRequest?.({
438
- ...request,
439
- context: canonicalContext,
440
- model: this.agent.state.model,
441
- thinkingLevel: this.agent.state.thinkingLevel,
442
- }, signal);
443
- return {
444
- ...previous,
445
- context: previous?.context ?? canonicalContext,
446
- model: previous?.model ?? this.agent.state.model,
447
- 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 };
448
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 };
449
587
  };
450
588
  }
451
589
  async _dispatchTurnEndBoundary(message, toolResults) {
@@ -501,19 +639,17 @@ export class AgentSession {
501
639
  ? async (_turn, signal) => await this.agent.prepareNextTurn?.(signal)
502
640
  : undefined);
503
641
  this.agent.prepareNextTurnWithContext = async (turn, signal) => {
504
- const projectedTurn = {
505
- ...turn,
506
- context: {
507
- ...turn.context,
508
- messages: this.sessionManager.buildSessionProjection().messages,
509
- },
510
- };
511
- const compactedContext = await this._compactBeforeNextProviderRequest(projectedTurn, signal);
512
- const context = signal?.aborted
513
- ? projectedTurn.context
514
- : compactedContext === undefined
515
- ? await this._compactBeforeNextAssistantResponse(projectedTurn.context, signal)
516
- : (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
+ }
517
653
  const nextTurn = { ...turn, context };
518
654
  const previousSnapshot = await previousPrepareNextTurnWithContext?.(nextTurn, signal);
519
655
  const nextContext = previousSnapshot?.context ?? context;
@@ -683,6 +819,21 @@ export class AgentSession {
683
819
  }
684
820
  /** Internal handler for agent events - shared by subscribe and reconnect */
685
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
+ }
686
837
  // When a user message starts, check if it's from either queue and remove it BEFORE emitting
687
838
  // This ensures the UI sees the updated queue state
688
839
  if (event.type === "message_start" && event.message.role === "user") {
@@ -1080,6 +1231,14 @@ export class AgentSession {
1080
1231
  get thinkingLevel() {
1081
1232
  return this.agent.state.thinkingLevel;
1082
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
+ }
1083
1242
  /** Whether the session is currently processing an agent run or post-run continuation. */
1084
1243
  get isStreaming() {
1085
1244
  return this._isAgentRunActive;
@@ -1105,12 +1264,16 @@ export class AgentSession {
1105
1264
  return this._retryAttempt;
1106
1265
  }
1107
1266
  /**
1108
- * Get the names of currently active tools.
1109
- * 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.
1110
1269
  */
1111
1270
  getActiveToolNames() {
1112
1271
  return this.agent.state.tools.map((t) => t.name);
1113
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
+ }
1114
1277
  /**
1115
1278
  * Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
1116
1279
  */
@@ -1120,6 +1283,9 @@ export class AgentSession {
1120
1283
  description: definition.description,
1121
1284
  parameters: definition.parameters,
1122
1285
  promptGuidelines: definition.promptGuidelines,
1286
+ exposure: this._getToolExposure(definition.name),
1287
+ ...(definition.namespace ? { namespace: definition.namespace } : {}),
1288
+ ...(definition.annotations ? { annotations: { ...definition.annotations } } : {}),
1123
1289
  sourceInfo,
1124
1290
  }));
1125
1291
  }
@@ -1128,22 +1294,79 @@ export class AgentSession {
1128
1294
  }
1129
1295
  /**
1130
1296
  * Set active tools by name.
1131
- * 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.
1132
1298
  * Also rebuilds the system prompt to reflect the new tool set.
1133
1299
  * Changes take effect on the next agent turn.
1134
1300
  */
1135
1301
  setActiveToolsByName(toolNames) {
1136
- const tools = [];
1137
- const validToolNames = [];
1138
- 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) => {
1139
1326
  const tool = this._toolRegistry.get(name);
1140
- if (tool) {
1141
- tools.push(tool);
1142
- 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
+ }
1143
1361
  }
1362
+ declared = tools.map((tool) => {
1363
+ const description = descriptions.get(tool.name);
1364
+ return description === undefined ? tool : { ...tool, description };
1365
+ });
1144
1366
  }
1145
- this.agent.state.tools = tools;
1146
- this._rebuildSystemPrompt(validToolNames);
1367
+ this._hiddenDeclarations = hidden;
1368
+ this.agent.state.tools = declared;
1369
+ return declared;
1147
1370
  }
1148
1371
  /** Whether compaction or branch summarization is currently running */
1149
1372
  get isCompacting() {
@@ -1244,11 +1467,7 @@ export class AgentSession {
1244
1467
  * {@link _installAgentForcedPromptProjection}.
1245
1468
  */
1246
1469
  _preparePromptAndToolLoadout(options, messages = this.agent.state.messages) {
1247
- options.selectedTools = [...new Set(options.selectedTools)].filter((name) => this._toolRegistry.has(name));
1248
- this.agent.state.tools = options.selectedTools.flatMap((name) => {
1249
- const tool = this._toolRegistry.get(name);
1250
- return tool ? [tool] : [];
1251
- });
1470
+ options.selectedTools = this._applyToolLoadout(options.selectedTools).map((tool) => tool.name);
1252
1471
  const sections = diffSystemPromptSections(getCurrentSystemMessage(messages)?.sections ?? {}, buildSystemPromptSections(options));
1253
1472
  return sections ? { role: "system", content: "", sections, timestamp: Date.now() } : undefined;
1254
1473
  }
@@ -1262,8 +1481,36 @@ export class AgentSession {
1262
1481
  * collapse into one head holding the forced text and the current tools. Runs after the
1263
1482
  * `context` extension handlers.
1264
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
+ }
1265
1510
  _installAgentForcedPromptProjection() {
1266
1511
  const previousTransformContext = this.agent.transformContext;
1512
+ if (previousTransformContext)
1513
+ this._cachePrefixUnavailableReason ??= "custom_context_transform";
1267
1514
  this.agent.transformContext = async (messages, signal) => {
1268
1515
  const transformed = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
1269
1516
  const forced = this._runSystemPromptOptions?.forceSystemPrompt;
@@ -1279,25 +1526,25 @@ export class AgentSession {
1279
1526
  return [head, ...transformed.filter((message) => message.role !== "system")];
1280
1527
  };
1281
1528
  }
1282
- /** 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
+ */
1283
1534
  _restoreToolsFromTranscript() {
1284
1535
  const current = getCurrentSystemMessage(this.sessionManager.buildSessionContext().messages);
1285
1536
  if (!current)
1286
1537
  return;
1287
- const toolNames = (current.toolsAdded ?? [])
1288
- .map((tool) => tool.name)
1289
- .filter((name) => this._toolRegistry.has(name));
1290
- this.agent.state.tools = toolNames.flatMap((name) => {
1291
- const registered = this._toolRegistry.get(name);
1292
- return registered ? [registered] : [];
1293
- });
1294
- this._rebuildSystemPrompt(toolNames);
1538
+ this.setActiveToolsByName((current.toolsAdded ?? []).map((tool) => tool.name));
1295
1539
  }
1296
1540
  // =========================================================================
1297
1541
  // Prompting
1298
1542
  // =========================================================================
1299
1543
  async _runAgentOperation(start) {
1300
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();
1301
1548
  this._isAgentRunActive = true;
1302
1549
  try {
1303
1550
  await start();
@@ -1333,6 +1580,7 @@ export class AgentSession {
1333
1580
  finally {
1334
1581
  if (this._agentRunAbortRequested)
1335
1582
  this._finishCancelledRetry();
1583
+ this._failedResponse = undefined;
1336
1584
  this._runSystemPromptOptions = undefined;
1337
1585
  this._flushPendingBashMessages();
1338
1586
  this._flushPendingCustomMessages();
@@ -1433,6 +1681,7 @@ export class AgentSession {
1433
1681
  if (this._isRetryableError(message) && (await this._prepareRetry(message))) {
1434
1682
  if (this._agentRunAbortRequested)
1435
1683
  this._finishCancelledRetry();
1684
+ this._failedResponse = message;
1436
1685
  return !this._agentRunAbortRequested;
1437
1686
  }
1438
1687
  if (this._agentRunAbortRequested) {
@@ -1506,7 +1755,7 @@ export class AgentSession {
1506
1755
  for (const image of images) {
1507
1756
  const processed = await processImage(Buffer.from(image.data, "base64"), image.mimeType, {
1508
1757
  autoResizeImages: this.settingsManager.getImageAutoResize(),
1509
- resizeOptions: this.model?.inputLimits?.images?.resize,
1758
+ resizeOptions: this._limitsModel()?.inputLimits?.images?.resize,
1510
1759
  });
1511
1760
  if (!processed.ok) {
1512
1761
  hints.push(processed.message);
@@ -1533,152 +1782,140 @@ export class AgentSession {
1533
1782
  }
1534
1783
  const expandPromptTemplates = options?.expandPromptTemplates ?? true;
1535
1784
  const preflightResult = options?.preflightResult;
1536
- let messages;
1537
- try {
1538
- // Handle extension commands first (execute immediately, even during streaming)
1539
- // Extension commands manage their own LLM interaction via pi.sendMessage()
1540
- if (expandPromptTemplates && text.startsWith("/")) {
1541
- const handled = await this._tryExecuteExtensionCommand(text);
1542
- if (handled) {
1543
- // Extension command executed, no prompt to send
1544
- preflightResult?.(true);
1545
- return;
1546
- }
1547
- }
1548
- if (this._compactionAbortController !== undefined && !this._isAborting) {
1549
- throw new Error("Cannot submit a prompt while compaction is in progress. Wait for compaction to finish and retry.");
1550
- }
1551
- // Emit input event for extension interception (before skill/template expansion)
1552
- const processedInput = await this._runInputHandlers(text, options?.images, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
1553
- if (!processedInput) {
1554
- 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");
1555
1792
  return;
1556
1793
  }
1557
- const { text: currentText, images: currentImages } = processedInput;
1558
- // Expand skill commands (/skill:name args) and prompt templates (/template args)
1559
- let expandedText = currentText;
1560
- if (expandPromptTemplates) {
1561
- expandedText = this._expandSkillCommand(expandedText);
1562
- expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
1563
- }
1564
- // If streaming, queue via steer() or followUp() based on option
1565
- if (this.isStreaming || this._isAborting) {
1566
- if (!options?.streamingBehavior) {
1567
- throw new Error("Agent is already processing. Specify streamingBehavior ('steer' or 'followUp') to queue the message.");
1568
- }
1569
- if (options.streamingBehavior === "followUp") {
1570
- await this._queueFollowUp(expandedText, currentImages);
1571
- }
1572
- else {
1573
- await this._queueSteer(expandedText, currentImages);
1574
- }
1575
- preflightResult?.(true);
1576
- 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.");
1577
1815
  }
1578
- // Flush any pending bash and custom messages before the new prompt
1579
- this._flushPendingBashMessages();
1580
- this._flushPendingCustomMessages();
1581
- // Validate model
1582
- if (!this.model) {
1583
- throw new Error(formatNoModelSelectedMessage());
1816
+ if (options.streamingBehavior === "followUp") {
1817
+ await this._queueFollowUp(expandedText, currentImages);
1584
1818
  }
1585
- const hasConfiguredAuth = this._modelRuntime.hasConfiguredAuth(this.model.provider) ||
1586
- (await this._modelRuntime.checkAuth(this.model.provider)) !== undefined;
1587
- if (!hasConfiguredAuth) {
1588
- const isOAuth = this._modelRuntime.isUsingOAuth(this.model.provider);
1589
- if (isOAuth) {
1590
- throw new Error(`Authentication failed for "${this.model.provider}". ` +
1591
- `Credentials may have expired or network is unavailable. ` +
1592
- `Run '/login ${this.model.provider}' to re-authenticate.`);
1593
- }
1594
- throw new Error(formatNoApiKeyFoundMessage(this.model.provider));
1819
+ else {
1820
+ await this._queueSteer(expandedText, currentImages);
1595
1821
  }
1596
- // Check if we need to compact before sending (catches aborted responses).
1597
- // The user's new prompt is sent below, so do not call agent.continue() here.
1598
- if (this._isAborting) {
1599
- preflightResult?.(false);
1600
- 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.`);
1601
1840
  }
1602
- const lastAssistant = this._findLastAssistantMessage();
1603
- if (lastAssistant) {
1604
- const prePromptAbortController = new AbortController();
1605
- let resolvePrePromptCompletion;
1606
- const prePromptCompletion = new Promise((resolve) => {
1607
- resolvePrePromptCompletion = resolve;
1608
- });
1609
- this._prePromptAbortController = prePromptAbortController;
1610
- this._prePromptCompletionPromise = prePromptCompletion;
1611
- try {
1612
- await this._checkCompaction(lastAssistant, false, [], prePromptAbortController.signal);
1613
- }
1614
- finally {
1615
- if (this._prePromptAbortController === prePromptAbortController) {
1616
- this._prePromptAbortController = undefined;
1617
- }
1618
- if (this._prePromptCompletionPromise === prePromptCompletion) {
1619
- this._prePromptCompletionPromise = undefined;
1620
- }
1621
- resolvePrePromptCompletion?.();
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;
1622
1863
  }
1623
- if (prePromptAbortController.signal.aborted || this._isAborting) {
1624
- preflightResult?.(false);
1625
- return;
1864
+ if (this._prePromptCompletionPromise === prePromptCompletion) {
1865
+ this._prePromptCompletionPromise = undefined;
1626
1866
  }
1867
+ resolvePrePromptCompletion?.();
1627
1868
  }
1628
- if (isPiServerMode()) {
1629
- this._detachPiServerTerminalAssistantFailure();
1869
+ if (prePromptAbortController.signal.aborted || this._isAborting) {
1870
+ return;
1630
1871
  }
1631
- // Emit before_agent_start before normalizing images so extension-driven model
1632
- // selection determines the resize profile used for the request and history.
1633
- const selectedToolsBefore = this._baseSystemPromptOptions.selectedTools;
1634
- const result = await this._extensionRunner.emitBeforeAgentStart(expandedText, currentImages, this._baseSystemPromptOptions);
1635
- // Handlers may edit event.systemPromptOptions.selectedTools or call setActiveTools(),
1636
- // which updates the live loadout instead. An explicit edit wins; otherwise the live
1637
- // loadout is authoritative, so a setActiveTools() call is not undone here.
1638
- const handlerEditedTools = result.systemPromptOptions.selectedTools.length !== selectedToolsBefore.length ||
1639
- result.systemPromptOptions.selectedTools.some((name, index) => name !== selectedToolsBefore[index]);
1640
- if (!handlerEditedTools)
1641
- result.systemPromptOptions.selectedTools = this.getActiveToolNames();
1642
- const normalized = await this._normalizePromptImages(currentImages);
1643
- const userText = normalized.hints.length > 0 ? `${expandedText}\n\n${normalized.hints.join("\n")}` : expandedText;
1644
- // Build messages only after hooks and image normalization have completed.
1645
- messages = [];
1646
- const userContent = [{ type: "text", text: userText }];
1647
- 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) {
1648
1904
  messages.push({
1649
- role: "user",
1650
- 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,
1651
1911
  timestamp: Date.now(),
1652
1912
  });
1653
- // Inject any pending "nextTurn" messages as context alongside the user message
1654
- for (const msg of this._pendingNextTurnMessages) {
1655
- messages.push(msg);
1656
- }
1657
- this._pendingNextTurnMessages = [];
1658
- for (const msg of result.messages) {
1659
- messages.push({
1660
- role: "custom",
1661
- customType: msg.customType,
1662
- // Untyped extensions can pass null/missing content; normalize at ingestion.
1663
- content: msg.content ?? [],
1664
- display: msg.display,
1665
- details: msg.details,
1666
- timestamp: Date.now(),
1667
- });
1668
- }
1669
- const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
1670
- this._runSystemPromptOptions = result.systemPromptOptions;
1671
- if (updateMessage)
1672
- messages.unshift(updateMessage);
1673
1913
  }
1674
- catch (error) {
1675
- preflightResult?.(false);
1676
- throw error;
1677
- }
1678
- if (!messages) {
1679
- return;
1680
- }
1681
- preflightResult?.(true);
1914
+ const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
1915
+ this._runSystemPromptOptions = result.systemPromptOptions;
1916
+ if (updateMessage)
1917
+ messages.unshift(updateMessage);
1918
+ preflightResult?.("started");
1682
1919
  await this._runAgentPrompt(messages);
1683
1920
  }
1684
1921
  /**
@@ -1744,7 +1981,7 @@ export class AgentSession {
1744
1981
  }
1745
1982
  const processedInput = await this._runInputHandlers(text, images, source, this.isStreaming ? behavior : undefined);
1746
1983
  if (!processedInput)
1747
- return;
1984
+ return "handled";
1748
1985
  let expandedText = this._expandSkillCommand(processedInput.text);
1749
1986
  expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
1750
1987
  if (behavior === "steer") {
@@ -1753,6 +1990,7 @@ export class AgentSession {
1753
1990
  else {
1754
1991
  await this._queueFollowUp(expandedText, processedInput.images);
1755
1992
  }
1993
+ return "queued";
1756
1994
  }
1757
1995
  /**
1758
1996
  * Queue a steering message while the agent is running.
@@ -1764,7 +2002,7 @@ export class AgentSession {
1764
2002
  * @throws Error if text is an extension command
1765
2003
  */
1766
2004
  async steer(text, images, options) {
1767
- await this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
2005
+ return this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
1768
2006
  }
1769
2007
  /**
1770
2008
  * Queue a follow-up message to be processed after the agent finishes.
@@ -1775,7 +2013,7 @@ export class AgentSession {
1775
2013
  * @throws Error if text is an extension command
1776
2014
  */
1777
2015
  async followUp(text, images, options) {
1778
- await this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
2016
+ return this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
1779
2017
  }
1780
2018
  /**
1781
2019
  * Internal: Queue a steering message (already expanded, no extension command check).
@@ -2280,6 +2518,58 @@ export class AgentSession {
2280
2518
  // =========================================================================
2281
2519
  // Compaction
2282
2520
  // =========================================================================
2521
+ async _buildCompactionCacheInput(model, preparation) {
2522
+ if (this._cachePrefixUnavailableReason)
2523
+ return { reason: this._cachePrefixUnavailableReason };
2524
+ if (this.agent.onPayload)
2525
+ return { reason: "request_payload_hook_active" };
2526
+ if (this._runSystemPromptOptions?.forceSystemPrompt !== undefined) {
2527
+ return { reason: "forced_system_prompt_active" };
2528
+ }
2529
+ const activeModel = this.agent.state.model;
2530
+ if (!modelsAreEqual(model, activeModel) ||
2531
+ model.api !== activeModel.api ||
2532
+ model.baseUrl !== activeModel.baseUrl) {
2533
+ return { reason: "summary_model_mismatch" };
2534
+ }
2535
+ if (!this.agent.sessionId)
2536
+ return { reason: "session_id_unavailable" };
2537
+ const projectedMessages = this.sessionManager.buildSessionProjection().messages;
2538
+ if (JSON.stringify(projectedMessages) !== JSON.stringify(this.agent.state.messages)) {
2539
+ return { reason: "request_context_mismatch" };
2540
+ }
2541
+ const fullMessages = await this.agent.convertToLlm(projectedMessages);
2542
+ const fullContext = normalizeContext({ messages: fullMessages });
2543
+ const cacheOptions = {
2544
+ sessionId: this.agent.sessionId,
2545
+ transport: this.agent.transport,
2546
+ thinkingBudgets: this.agent.thinkingBudgets,
2547
+ maxRetryDelayMs: this.agent.maxRetryDelayMs,
2548
+ };
2549
+ if (!preparation) {
2550
+ return {
2551
+ cacheContextHash: hashPiServerProviderMessages(fullMessages),
2552
+ cacheStaticContextHash: hashStaticContext({
2553
+ systemPrompt: this.systemPrompt,
2554
+ tools: this.agent.state.tools,
2555
+ messages: [],
2556
+ }),
2557
+ cacheOptions,
2558
+ reason: "exact_prefix_unavailable",
2559
+ };
2560
+ }
2561
+ const prefixMessages = await this.agent.convertToLlm(preparation.cachePrefixMessages);
2562
+ const cachePrefixContext = normalizeContext({ messages: prefixMessages });
2563
+ if (cachePrefixContext.messages.length > fullContext.messages.length ||
2564
+ cachePrefixContext.messages.some((message, index) => JSON.stringify(message) !== JSON.stringify(fullContext.messages[index]))) {
2565
+ return { reason: "projected_prefix_mismatch" };
2566
+ }
2567
+ return {
2568
+ cachePrefixContext,
2569
+ cacheOptions,
2570
+ reason: "exact_prefix_unavailable",
2571
+ };
2572
+ }
2283
2573
  async _applyPiServerCompactionResult(result, reason, willRetry) {
2284
2574
  this.sessionManager.replaceTree(result.entries, result.leafId);
2285
2575
  const sessionContext = this.sessionManager.buildSessionContext();
@@ -2335,22 +2625,27 @@ export class AgentSession {
2335
2625
  throw new Error(formatNoModelSelectedMessage());
2336
2626
  }
2337
2627
  const settings = this.settingsManager.getCompactionSettings(model);
2338
- const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
2339
2628
  if (isPiServerMode()) {
2629
+ const { model: requestModel, apiKey, headers, thinkingLevel, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
2340
2630
  this._detachPiServerTerminalAssistantFailure();
2631
+ const cacheInput = await this._buildCompactionCacheInput(requestModel);
2341
2632
  const piServerResult = await compactPiServer(requestModel, {
2342
2633
  systemPrompt: this.systemPrompt,
2343
2634
  messages: this.agent.state.messages,
2344
2635
  tools: this.agent.state.tools,
2345
2636
  }, {
2637
+ ...cacheInput.cacheOptions,
2346
2638
  sessionId: this.sessionId,
2347
2639
  apiKey,
2348
2640
  headers,
2349
2641
  customInstructions,
2642
+ cacheContextHash: cacheInput.cacheContextHash,
2643
+ cacheStaticContextHash: cacheInput.cacheStaticContextHash,
2644
+ cacheFallbackReason: cacheInput.reason,
2350
2645
  settings: this.settingsManager.getCompactionSettings(),
2351
2646
  sessionTree: buildPiServerSessionTree(this.sessionManager.getEntries(), this.sessionManager.getLeafId()),
2352
2647
  signal: this._compactionAbortController.signal,
2353
- reasoning: toProviderReasoning(this.thinkingLevel),
2648
+ reasoning: toProviderReasoning(thinkingLevel),
2354
2649
  onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
2355
2650
  });
2356
2651
  const result = await this._applyPiServerCompactionResult(piServerResult, "manual", false);
@@ -2408,8 +2703,10 @@ export class AgentSession {
2408
2703
  details = extensionCompaction.details;
2409
2704
  }
2410
2705
  else {
2411
- // Generate compaction result
2412
- 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" }));
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);
2708
+ const cacheInput = await this._buildCompactionCacheInput(requestModel, preparation);
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);
2413
2710
  summary = result.summary;
2414
2711
  firstKeptEntryId = result.firstKeptEntryId;
2415
2712
  tokensBefore = result.tokensBefore;
@@ -2521,12 +2818,14 @@ export class AgentSession {
2521
2818
  // Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
2522
2819
  if (skipAbortedCheck && assistantMessage.stopReason === "aborted")
2523
2820
  return false;
2524
- const contextWindow = this.model?.contextWindow ?? 0;
2525
2821
  // Skip overflow check if the message came from a different model.
2526
2822
  // This handles the case where user switched from a smaller-context model (e.g. opus)
2527
2823
  // to a larger-context model (e.g. codex) - the overflow error from the old model
2528
- // shouldn't trigger compaction for the new model.
2529
- 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;
2530
2829
  // Skip compaction checks if this assistant message is older than the latest
2531
2830
  // compaction boundary. This prevents a stale pre-compaction usage/error
2532
2831
  // from retriggering compaction on the first prompt after compaction.
@@ -2560,7 +2859,7 @@ export class AgentSession {
2560
2859
  const contextOverflow = sameModel &&
2561
2860
  ((explicitOverflow && assistantRetainedForExplicitRecovery) ||
2562
2861
  (assistantUsageMatchesProjection && isContextOverflow(assistantMessage, contextWindow)));
2563
- const recoverableLength = sameModel && assistantIsProjected && isRecoverableLength(assistantMessage, this.model?.maxTokens ?? 0);
2862
+ const recoverableLength = sameModel && assistantIsProjected && isRecoverableLength(assistantMessage, messageModel.maxTokens);
2564
2863
  if (contextOverflow || recoverableLength) {
2565
2864
  const willRetry = assistantMessage.stopReason !== "stop";
2566
2865
  if (!willRetry) {
@@ -2585,7 +2884,10 @@ export class AgentSession {
2585
2884
  this._omitRecoveryAttempt(assistantMessage, toolResults);
2586
2885
  if (isPiServerMode())
2587
2886
  this._detachPiServerTerminalAssistantFailure();
2588
- 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;
2589
2891
  }
2590
2892
  // Case 2: Threshold - context is getting large
2591
2893
  // For error messages or all-zero usage messages, estimate from the last valid response.
@@ -2648,21 +2950,26 @@ export class AgentSession {
2648
2950
  started = true;
2649
2951
  this._emit({ type: "compaction_start", reason });
2650
2952
  abortController.signal.throwIfAborted();
2651
- const { model: requestModel, apiKey, headers, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2953
+ const { model: requestModel, apiKey, headers, thinkingLevel, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2652
2954
  abortController.signal.throwIfAborted();
2955
+ const cacheInput = await this._buildCompactionCacheInput(requestModel);
2653
2956
  const piServerResult = await compactPiServer(requestModel, {
2654
2957
  systemPrompt: this.systemPrompt,
2655
2958
  messages: this.agent.state.messages,
2656
2959
  tools: this.agent.state.tools,
2657
2960
  }, {
2961
+ ...cacheInput.cacheOptions,
2658
2962
  sessionId: this.sessionId,
2659
2963
  apiKey,
2660
2964
  headers,
2965
+ cacheContextHash: cacheInput.cacheContextHash,
2966
+ cacheStaticContextHash: cacheInput.cacheStaticContextHash,
2967
+ cacheFallbackReason: cacheInput.reason,
2661
2968
  settings,
2662
2969
  preparation: preparationOptions,
2663
2970
  sessionTree: buildPiServerSessionTree(this.sessionManager.getEntries(), this.sessionManager.getLeafId()),
2664
2971
  signal: abortController.signal,
2665
- reasoning: toProviderReasoning(this.thinkingLevel),
2972
+ reasoning: toProviderReasoning(thinkingLevel),
2666
2973
  onHistoryReconciled: (snapshot) => this.reconcilePiServerHistory(snapshot),
2667
2974
  });
2668
2975
  if (externalSignal?.aborted || abortController.signal.aborted) {
@@ -2690,8 +2997,6 @@ export class AgentSession {
2690
2997
  started = true;
2691
2998
  this._emit({ type: "compaction_start", reason });
2692
2999
  abortController.signal.throwIfAborted();
2693
- const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2694
- abortController.signal.throwIfAborted();
2695
3000
  let extensionCompaction;
2696
3001
  if (this._extensionRunner.hasHandlers("session_before_compact")) {
2697
3002
  const extensionResult = (await this._extensionRunner.emit({
@@ -2726,7 +3031,10 @@ export class AgentSession {
2726
3031
  details = extensionCompaction.details;
2727
3032
  }
2728
3033
  else {
2729
- 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 }));
3034
+ const { model: requestModel, apiKey, headers, env, thinkingLevel, } = await this._getSummarizationRequestAuth(model, abortController.signal);
3035
+ abortController.signal.throwIfAborted();
3036
+ const cacheInput = await this._buildCompactionCacheInput(requestModel, preparation);
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);
2730
3038
  summary = compactResult.summary;
2731
3039
  firstKeptEntryId = compactResult.firstKeptEntryId;
2732
3040
  tokensBefore = compactResult.tokensBefore;
@@ -2823,10 +3131,13 @@ export class AgentSession {
2823
3131
  return this.settingsManager.getCompactionEnabled();
2824
3132
  }
2825
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;
2826
3137
  const settings = this.settingsManager.getCompactionSettings(this.model);
2827
3138
  if (!settings.enabled || turn.toolResults.length === 0)
2828
3139
  return false;
2829
- const contextWindow = this.model?.contextWindow ?? 0;
3140
+ const contextWindow = this.model.contextWindow;
2830
3141
  if (contextWindow <= 0)
2831
3142
  return false;
2832
3143
  const branch = this.sessionManager.getBranch();
@@ -2927,6 +3238,7 @@ export class AgentSession {
2927
3238
  }
2928
3239
  this._applyExtensionBindings(this._extensionRunner);
2929
3240
  await this._extensionRunner.emit(this._sessionStartEvent);
3241
+ this._extensionRunner.reportUnhandledMcpServers();
2930
3242
  await this.extendResourcesFromExtensions(this._sessionStartEvent.reason === "reload" ? "reload" : "startup");
2931
3243
  }
2932
3244
  async extendResourcesFromExtensions(reason) {
@@ -2948,7 +3260,7 @@ export class AgentSession {
2948
3260
  buildExtensionResourcePaths(entries) {
2949
3261
  return entries.map((entry) => {
2950
3262
  const source = this.getExtensionSourceLabel(entry.extensionPath);
2951
- const baseDir = entry.extensionPath.startsWith("<") ? undefined : dirname(entry.extensionPath);
3263
+ const baseDir = isSyntheticPath(entry.extensionPath) ? undefined : dirname(entry.extensionPath);
2952
3264
  return {
2953
3265
  path: entry.path,
2954
3266
  metadata: {
@@ -2961,7 +3273,7 @@ export class AgentSession {
2961
3273
  });
2962
3274
  }
2963
3275
  getExtensionSourceLabel(extensionPath) {
2964
- if (extensionPath.startsWith("<")) {
3276
+ if (isSyntheticPath(extensionPath)) {
2965
3277
  return `extension:${extensionPath.replace(/[<>]/g, "")}`;
2966
3278
  }
2967
3279
  const base = basename(extensionPath);
@@ -3046,6 +3358,7 @@ export class AgentSession {
3046
3358
  },
3047
3359
  getActiveTools: () => this.getActiveToolNames(),
3048
3360
  getAllTools: () => this.getAllTools(),
3361
+ getSettings: () => this.settingsManager.getSettings(),
3049
3362
  setActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),
3050
3363
  refreshTools: () => this._refreshToolRegistry(),
3051
3364
  getCommands,
@@ -3089,6 +3402,8 @@ export class AgentSession {
3089
3402
  },
3090
3403
  getSystemPrompt: () => this.systemPrompt,
3091
3404
  getSystemPromptOptions: () => this._baseSystemPromptOptions,
3405
+ executeTool: (callerId, name, args, options) => this._executeNestedToolCall(callerId, name, args, options),
3406
+ getCallableTools: () => this._getCallableTools(),
3092
3407
  }, {
3093
3408
  registerProvider: (name, config) => {
3094
3409
  this._modelRuntime.registerProvider(name, config);
@@ -3102,10 +3417,20 @@ export class AgentSession {
3102
3417
  this._modelRuntime.unregisterProvider(name);
3103
3418
  this._refreshCurrentModelFromRegistry();
3104
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
+ },
3105
3428
  });
3106
3429
  }
3107
3430
  _refreshToolRegistry(options) {
3108
- 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)));
3109
3434
  const previousActiveToolNames = this.getActiveToolNames();
3110
3435
  const allowedToolNames = this._allowedToolNames;
3111
3436
  const excludedToolNames = this._excludedToolNames;
@@ -3124,7 +3449,7 @@ export class AgentSession {
3124
3449
  name,
3125
3450
  {
3126
3451
  definition,
3127
- sourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, { source: "builtin" }),
3452
+ sourceInfo: createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${name}`, { source: "builtin" }),
3128
3453
  },
3129
3454
  ]));
3130
3455
  for (const tool of allCustomTools) {
@@ -3152,7 +3477,9 @@ export class AgentSession {
3152
3477
  .filter((definition) => isAllowedTool(definition.name))
3153
3478
  .map((definition) => ({
3154
3479
  definition,
3155
- sourceInfo: createSyntheticSourceInfo(`<builtin:${definition.name}>`, { source: "builtin" }),
3480
+ sourceInfo: createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${definition.name}`, {
3481
+ source: "builtin",
3482
+ }),
3156
3483
  })), runner);
3157
3484
  const toolRegistry = new Map(wrappedBuiltInTools.map((tool) => [tool.name, tool]));
3158
3485
  for (const tool of wrappedExtensionTools) {
@@ -3162,25 +3489,36 @@ export class AgentSession {
3162
3489
  const nextActiveToolNames = (options?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]).filter((name) => isAllowedTool(name));
3163
3490
  if (allowedToolNames) {
3164
3491
  for (const toolName of this._toolRegistry.keys()) {
3165
- 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)) {
3166
3494
  nextActiveToolNames.push(toolName);
3167
3495
  }
3168
3496
  }
3169
3497
  }
3170
3498
  else if (options?.includeAllExtensionTools) {
3171
3499
  for (const tool of wrappedExtensionTools) {
3172
- nextActiveToolNames.push(tool.name);
3500
+ if (this._isActivatedOnRegistration(tool.name))
3501
+ nextActiveToolNames.push(tool.name);
3173
3502
  }
3174
3503
  }
3175
3504
  else if (!options?.activeToolNames) {
3176
3505
  for (const toolName of this._toolRegistry.keys()) {
3177
- if (!previousRegistryNames.has(toolName)) {
3506
+ if (!previousActivatedOnRegistration.has(toolName) && this._isActivatedOnRegistration(toolName)) {
3178
3507
  nextActiveToolNames.push(toolName);
3179
3508
  }
3180
3509
  }
3181
3510
  }
3182
3511
  this.setActiveToolsByName([...new Set(nextActiveToolNames)]);
3183
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
+ }
3184
3522
  _buildRuntime(options) {
3185
3523
  const autoResizeImages = this.settingsManager.getImageAutoResize();
3186
3524
  const shellCommandPrefix = this.settingsManager.getShellCommandPrefix();
@@ -3237,6 +3575,7 @@ export class AgentSession {
3237
3575
  if (hasBindings) {
3238
3576
  await options?.beforeSessionStart?.();
3239
3577
  await this._extensionRunner.emit({ type: "session_start", reason: "reload" });
3578
+ this._extensionRunner.reportUnhandledMcpServers();
3240
3579
  await this.extendResourcesFromExtensions("reload");
3241
3580
  }
3242
3581
  }
@@ -3253,7 +3592,7 @@ export class AgentSession {
3253
3592
  */
3254
3593
  _isRetryableError(message) {
3255
3594
  // Context overflow is handled by compaction, not retry.
3256
- if (isContextOverflow(message, this.model?.contextWindow ?? 0))
3595
+ if (isContextOverflow(message, (this._modelForMessage(message) ?? this.model)?.contextWindow ?? 0))
3257
3596
  return false;
3258
3597
  if (this._isPostAssistantPiServerSyncFailure(message))
3259
3598
  return false;
@@ -3567,15 +3906,11 @@ export class AgentSession {
3567
3906
  let summaryDetails;
3568
3907
  let summaryUsage;
3569
3908
  if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
3570
- const model = this.model;
3571
- const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
3909
+ const signal = this._branchSummaryAbortController.signal;
3572
3910
  const branchSummarySettings = this.settingsManager.getBranchSummarySettings();
3573
3911
  const result = await generateBranchSummary(entriesToSummarize, {
3574
- model: requestModel,
3575
- apiKey,
3576
- headers,
3577
- env,
3578
- signal: this._branchSummaryAbortController.signal,
3912
+ ...(await this._getSummarizationRequestAuth(this.model, signal)),
3913
+ signal,
3579
3914
  customInstructions,
3580
3915
  replaceInstructions,
3581
3916
  reserveTokens: branchSummarySettings.reserveTokens,
@@ -3744,7 +4079,7 @@ export class AgentSession {
3744
4079
  };
3745
4080
  }
3746
4081
  getContextUsage() {
3747
- const model = this.model;
4082
+ const model = this._limitsModel();
3748
4083
  if (!model)
3749
4084
  return undefined;
3750
4085
  const contextWindow = model.contextWindow ?? 0;
@@ -3838,16 +4173,11 @@ export class AgentSession {
3838
4173
  if (!model) {
3839
4174
  throw new Error("No model selected");
3840
4175
  }
3841
- const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
3842
4176
  return generateBugReportSummary({
4177
+ ...(await this._getSummarizationRequestAuth(model, options.signal)),
3843
4178
  messages: this.messages,
3844
4179
  hint: options.hint,
3845
- model: requestModel,
3846
- apiKey,
3847
- headers,
3848
- env,
3849
4180
  signal: options.signal,
3850
- thinkingLevel: this.thinkingLevel,
3851
4181
  streamFn: this.agent.streamFunction,
3852
4182
  retry: this.settingsManager.getRetrySettings(),
3853
4183
  sessionId: this.sessionId,