pi-namespace-patch 0.87.1-namespace.1 → 1.0.0-namespace.2

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 (754) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/README.md +100 -25
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
  5. package/dist/bun/restore-sandbox-env.js.map +1 -1
  6. package/dist/bun/runtime-setup.d.ts.map +1 -1
  7. package/dist/bun/runtime-setup.js +4 -1
  8. package/dist/bun/runtime-setup.js.map +1 -1
  9. package/dist/bun/sandbox-env-setup.d.ts.map +1 -1
  10. package/dist/bundle/chunks/anthropic-messages-UID2PALB.js +6 -0
  11. package/dist/bundle/chunks/anthropic.js +2 -2
  12. package/dist/bundle/chunks/azure-openai-responses-AFMVM6NP.js +2 -0
  13. package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
  14. package/dist/bundle/chunks/chunk-2KTBZM5G.js +132 -0
  15. package/dist/bundle/chunks/{chunk-WIUZI2CJ.js → chunk-2VNGUWBO.js} +3 -3
  16. package/dist/bundle/chunks/{chunk-FUXEF6JQ.js → chunk-3LH3ZQKY.js} +1 -1
  17. package/dist/bundle/chunks/chunk-4N5K4RKC.js +1204 -0
  18. package/dist/bundle/chunks/chunk-6D7LHLKG.js +2 -0
  19. package/dist/bundle/chunks/chunk-7FH3BDRG.js +82 -0
  20. package/dist/bundle/chunks/chunk-7JGR3GZN.js +11 -0
  21. package/dist/bundle/chunks/chunk-H3QXYIF7.js +31 -0
  22. package/dist/bundle/chunks/chunk-IBCPYVFK.js +19 -0
  23. package/dist/bundle/chunks/chunk-KDN6RCEQ.js +4 -0
  24. package/dist/bundle/chunks/chunk-LD2P6SFZ.js +2 -0
  25. package/dist/bundle/chunks/chunk-LTXEMVMA.js +127 -0
  26. package/dist/bundle/chunks/chunk-MJOHEBV7.js +2 -0
  27. package/dist/bundle/chunks/chunk-OSKPX3Z5.js +2 -0
  28. package/dist/bundle/chunks/chunk-PRD6WYBT.js +16 -0
  29. package/dist/bundle/chunks/{chunk-XDUWOHPL.js → chunk-S3GGRYIO.js} +2 -2
  30. package/dist/bundle/chunks/chunk-UTB4DTYQ.js +2 -0
  31. package/dist/bundle/chunks/chunk-VIV3CWXG.js +2 -0
  32. package/dist/bundle/chunks/cli-QOMC26IJ.js +51 -0
  33. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-NPQN263E.js +2 -0
  34. package/dist/bundle/chunks/codemode-worker.js +354 -0
  35. package/dist/bundle/chunks/execute-GVRSEGHL.js +367 -0
  36. package/dist/bundle/chunks/github-copilot.js +1 -1
  37. package/dist/bundle/chunks/google-generative-ai-APTPZOQL.js +2 -0
  38. package/dist/bundle/chunks/google-vertex-MXCOSOY3.js +2 -0
  39. package/dist/bundle/chunks/{lib-HGQMNYVT.js → lib-TEDK3E5I.js} +2 -2
  40. package/dist/bundle/chunks/llama-cpp-classify-XT44PI3C.js +22 -0
  41. package/dist/bundle/chunks/mistral-conversations-DKVFNQL6.js +5 -0
  42. package/dist/bundle/chunks/openai-chatgpt.js +75 -0
  43. package/dist/bundle/chunks/{openai-codex-responses-QDSOTBBO.js → openai-codex-responses-GK67DQQJ.js} +2 -2
  44. package/dist/bundle/chunks/openai-codex.js +2 -2
  45. package/dist/bundle/chunks/{openai-completions-OBX42CLD.js → openai-completions-JXDDPZ23.js} +2 -2
  46. package/dist/bundle/chunks/openai-responses-CQDDLDQF.js +3 -0
  47. package/dist/bundle/chunks/{openrouter-images-N4XVVFSD.js → openrouter-images-ZVXWCSIM.js} +1 -1
  48. package/dist/bundle/chunks/openrouter.js +2 -2
  49. package/dist/bundle/chunks/pi-logo-animation-MPKZE4EK.js +2 -0
  50. package/dist/bundle/chunks/{pi-messages-GFKBWJHZ.js → pi-messages-TM5SOOIW.js} +2 -2
  51. package/dist/bundle/chunks/radius.js +2 -2
  52. package/dist/bundle/chunks/runtime-2SO2JDWM.js +2 -0
  53. package/dist/bundle/chunks/typesafe-system-one-A4CZTQWZ.js +2 -0
  54. package/dist/bundle/chunks/virtual-modules-3THEGRQQ.js +2 -0
  55. package/dist/bundle/cli-runtime.js +1 -1
  56. package/dist/bundle/index.js +1 -1
  57. package/dist/bundle/rpc-entry.js +1 -1
  58. package/dist/cli/args.d.ts.map +1 -1
  59. package/dist/cli/args.js +6 -5
  60. package/dist/cli/args.js.map +1 -1
  61. package/dist/cli/auth-check.d.ts.map +1 -1
  62. package/dist/cli/auth-check.js.map +1 -1
  63. package/dist/cli/auth-command.d.ts.map +1 -1
  64. package/dist/cli/auth-command.js.map +1 -1
  65. package/dist/cli/config-selector.d.ts.map +1 -1
  66. package/dist/cli/config-selector.js.map +1 -1
  67. package/dist/cli/credential-print.d.ts.map +1 -1
  68. package/dist/cli/credential-print.js.map +1 -1
  69. package/dist/cli/file-processor.d.ts.map +1 -1
  70. package/dist/cli/file-processor.js.map +1 -1
  71. package/dist/cli/initial-message.d.ts +1 -1
  72. package/dist/cli/initial-message.d.ts.map +1 -1
  73. package/dist/cli/initial-message.js.map +1 -1
  74. package/dist/cli/list-models.d.ts.map +1 -1
  75. package/dist/cli/list-models.js.map +1 -1
  76. package/dist/cli/project-trust.d.ts.map +1 -1
  77. package/dist/cli/project-trust.js.map +1 -1
  78. package/dist/cli/session-picker.d.ts.map +1 -1
  79. package/dist/cli/session-picker.js.map +1 -1
  80. package/dist/cli/setup.d.ts.map +1 -1
  81. package/dist/cli/setup.js.map +1 -1
  82. package/dist/cli/startup-ui.d.ts.map +1 -1
  83. package/dist/cli/startup-ui.js +38 -30
  84. package/dist/cli/startup-ui.js.map +1 -1
  85. package/dist/cli.d.ts.map +1 -1
  86. package/dist/config.d.ts +15 -4
  87. package/dist/config.d.ts.map +1 -1
  88. package/dist/config.js +33 -4
  89. package/dist/config.js.map +1 -1
  90. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  91. package/dist/core/agent-session-runtime.js +1 -1
  92. package/dist/core/agent-session-runtime.js.map +1 -1
  93. package/dist/core/agent-session-services.d.ts.map +1 -1
  94. package/dist/core/agent-session-services.js +13 -0
  95. package/dist/core/agent-session-services.js.map +1 -1
  96. package/dist/core/agent-session.d.ts +150 -12
  97. package/dist/core/agent-session.d.ts.map +1 -1
  98. package/dist/core/agent-session.js +560 -263
  99. package/dist/core/agent-session.js.map +1 -1
  100. package/dist/core/auth-guidance.d.ts.map +1 -1
  101. package/dist/core/auth-guidance.js.map +1 -1
  102. package/dist/core/auth-storage.d.ts.map +1 -1
  103. package/dist/core/auth-storage.js.map +1 -1
  104. package/dist/core/bash-executor.d.ts.map +1 -1
  105. package/dist/core/bash-executor.js.map +1 -1
  106. package/dist/core/bug-report-upload.d.ts.map +1 -1
  107. package/dist/core/bug-report-upload.js.map +1 -1
  108. package/dist/core/bug-report.d.ts +1 -1
  109. package/dist/core/bug-report.d.ts.map +1 -1
  110. package/dist/core/bug-report.js +1 -1
  111. package/dist/core/bug-report.js.map +1 -1
  112. package/dist/core/cache-stats.d.ts.map +1 -1
  113. package/dist/core/cache-stats.js.map +1 -1
  114. package/dist/core/cache-warmer.d.ts.map +1 -1
  115. package/dist/core/cache-warmer.js.map +1 -1
  116. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  117. package/dist/core/compaction/branch-summarization.js.map +1 -1
  118. package/dist/core/compaction/compaction.d.ts.map +1 -1
  119. package/dist/core/compaction/compaction.js +1 -22
  120. package/dist/core/compaction/compaction.js.map +1 -1
  121. package/dist/core/compaction/index.d.ts.map +1 -1
  122. package/dist/core/compaction/utils.d.ts +2 -1
  123. package/dist/core/compaction/utils.d.ts.map +1 -1
  124. package/dist/core/compaction/utils.js +25 -18
  125. package/dist/core/compaction/utils.js.map +1 -1
  126. package/dist/core/crash-log.d.ts.map +1 -1
  127. package/dist/core/crash-log.js +2 -1
  128. package/dist/core/crash-log.js.map +1 -1
  129. package/dist/core/defaults.d.ts.map +1 -1
  130. package/dist/core/diagnostics.d.ts.map +1 -1
  131. package/dist/core/event-bus.d.ts.map +1 -1
  132. package/dist/core/event-bus.js.map +1 -1
  133. package/dist/core/exec.d.ts.map +1 -1
  134. package/dist/core/exec.js.map +1 -1
  135. package/dist/core/experimental.d.ts.map +1 -1
  136. package/dist/core/experimental.js.map +1 -1
  137. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  138. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  139. package/dist/core/export-html/index.d.ts.map +1 -1
  140. package/dist/core/export-html/index.js.map +1 -1
  141. package/dist/core/export-html/template.css +10 -0
  142. package/dist/core/export-html/template.js +66 -17
  143. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  144. package/dist/core/export-html/tool-renderer.js.map +1 -1
  145. package/dist/core/extensions/index.d.ts +1 -1
  146. package/dist/core/extensions/index.d.ts.map +1 -1
  147. package/dist/core/extensions/index.js.map +1 -1
  148. package/dist/core/extensions/jiti-loader.d.ts.map +1 -1
  149. package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -1
  150. package/dist/core/extensions/loader.d.ts.map +1 -1
  151. package/dist/core/extensions/loader.js +67 -5
  152. package/dist/core/extensions/loader.js.map +1 -1
  153. package/dist/core/extensions/runner.d.ts +18 -1
  154. package/dist/core/extensions/runner.d.ts.map +1 -1
  155. package/dist/core/extensions/runner.js +99 -0
  156. package/dist/core/extensions/runner.js.map +1 -1
  157. package/dist/core/extensions/types.d.ts +301 -22
  158. package/dist/core/extensions/types.d.ts.map +1 -1
  159. package/dist/core/extensions/types.js.map +1 -1
  160. package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
  161. package/dist/core/extensions/wrapper.d.ts +2 -2
  162. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  163. package/dist/core/extensions/wrapper.js +3 -3
  164. package/dist/core/extensions/wrapper.js.map +1 -1
  165. package/dist/core/footer-data-provider.d.ts.map +1 -1
  166. package/dist/core/footer-data-provider.js.map +1 -1
  167. package/dist/core/http-dispatcher.d.ts.map +1 -1
  168. package/dist/core/http-dispatcher.js.map +1 -1
  169. package/dist/core/index.d.ts.map +1 -1
  170. package/dist/core/keybindings.d.ts +1 -1
  171. package/dist/core/keybindings.d.ts.map +1 -1
  172. package/dist/core/keybindings.js +1 -1
  173. package/dist/core/keybindings.js.map +1 -1
  174. package/dist/core/mcp-servers.d.ts +125 -0
  175. package/dist/core/mcp-servers.d.ts.map +1 -0
  176. package/dist/core/mcp-servers.js +198 -0
  177. package/dist/core/mcp-servers.js.map +1 -0
  178. package/dist/core/messages.d.ts.map +1 -1
  179. package/dist/core/messages.js.map +1 -1
  180. package/dist/core/model-config.d.ts.map +1 -1
  181. package/dist/core/model-config.js.map +1 -1
  182. package/dist/core/model-registry.d.ts +15 -1
  183. package/dist/core/model-registry.d.ts.map +1 -1
  184. package/dist/core/model-registry.js +29 -0
  185. package/dist/core/model-registry.js.map +1 -1
  186. package/dist/core/model-resolver.d.ts +2 -2
  187. package/dist/core/model-resolver.d.ts.map +1 -1
  188. package/dist/core/model-resolver.js +5 -5
  189. package/dist/core/model-resolver.js.map +1 -1
  190. package/dist/core/model-runtime.d.ts +47 -3
  191. package/dist/core/model-runtime.d.ts.map +1 -1
  192. package/dist/core/model-runtime.js +189 -35
  193. package/dist/core/model-runtime.js.map +1 -1
  194. package/dist/core/models-store.d.ts.map +1 -1
  195. package/dist/core/models-store.js.map +1 -1
  196. package/dist/core/nested-tool-calls.d.ts +102 -0
  197. package/dist/core/nested-tool-calls.d.ts.map +1 -0
  198. package/dist/core/nested-tool-calls.js +178 -0
  199. package/dist/core/nested-tool-calls.js.map +1 -0
  200. package/dist/core/output-guard.d.ts.map +1 -1
  201. package/dist/core/output-guard.js.map +1 -1
  202. package/dist/core/package-manager.d.ts +4 -0
  203. package/dist/core/package-manager.d.ts.map +1 -1
  204. package/dist/core/package-manager.js +59 -12
  205. package/dist/core/package-manager.js.map +1 -1
  206. package/dist/core/pi-manifest.d.ts.map +1 -1
  207. package/dist/core/pi-manifest.js.map +1 -1
  208. package/dist/core/project-trust.d.ts.map +1 -1
  209. package/dist/core/project-trust.js.map +1 -1
  210. package/dist/core/prompt-templates.d.ts.map +1 -1
  211. package/dist/core/prompt-templates.js.map +1 -1
  212. package/dist/core/provider-attribution.d.ts.map +1 -1
  213. package/dist/core/provider-attribution.js.map +1 -1
  214. package/dist/core/provider-composer.d.ts +40 -21
  215. package/dist/core/provider-composer.d.ts.map +1 -1
  216. package/dist/core/provider-composer.js +92 -40
  217. package/dist/core/provider-composer.js.map +1 -1
  218. package/dist/core/radius.d.ts +2 -0
  219. package/dist/core/radius.d.ts.map +1 -1
  220. package/dist/core/radius.js +2 -0
  221. package/dist/core/radius.js.map +1 -1
  222. package/dist/core/remote-catalog-provider.d.ts +8 -1
  223. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  224. package/dist/core/remote-catalog-provider.js +21 -11
  225. package/dist/core/remote-catalog-provider.js.map +1 -1
  226. package/dist/core/resolve-config-value.d.ts.map +1 -1
  227. package/dist/core/resolve-config-value.js.map +1 -1
  228. package/dist/core/resource-loader.d.ts +7 -1
  229. package/dist/core/resource-loader.d.ts.map +1 -1
  230. package/dist/core/resource-loader.js +161 -35
  231. package/dist/core/resource-loader.js.map +1 -1
  232. package/dist/core/runtime-credentials.d.ts.map +1 -1
  233. package/dist/core/runtime-credentials.js.map +1 -1
  234. package/dist/core/sdk.d.ts +1 -1
  235. package/dist/core/sdk.d.ts.map +1 -1
  236. package/dist/core/sdk.js +25 -6
  237. package/dist/core/sdk.js.map +1 -1
  238. package/dist/core/session-cwd.d.ts.map +1 -1
  239. package/dist/core/session-cwd.js.map +1 -1
  240. package/dist/core/session-export.d.ts.map +1 -1
  241. package/dist/core/session-export.js.map +1 -1
  242. package/dist/core/session-manager.d.ts +9 -0
  243. package/dist/core/session-manager.d.ts.map +1 -1
  244. package/dist/core/session-manager.js +22 -22
  245. package/dist/core/session-manager.js.map +1 -1
  246. package/dist/core/settings-diagnostics.d.ts.map +1 -1
  247. package/dist/core/settings-diagnostics.js.map +1 -1
  248. package/dist/core/settings-manager.d.ts +36 -4
  249. package/dist/core/settings-manager.d.ts.map +1 -1
  250. package/dist/core/settings-manager.js +75 -4
  251. package/dist/core/settings-manager.js.map +1 -1
  252. package/dist/core/skills.d.ts.map +1 -1
  253. package/dist/core/skills.js.map +1 -1
  254. package/dist/core/slash-commands.d.ts.map +1 -1
  255. package/dist/core/source-info.d.ts +8 -0
  256. package/dist/core/source-info.d.ts.map +1 -1
  257. package/dist/core/source-info.js +16 -0
  258. package/dist/core/source-info.js.map +1 -1
  259. package/dist/core/system-prompt.d.ts.map +1 -1
  260. package/dist/core/system-prompt.js +1 -1
  261. package/dist/core/system-prompt.js.map +1 -1
  262. package/dist/core/telemetry.d.ts.map +1 -1
  263. package/dist/core/telemetry.js.map +1 -1
  264. package/dist/core/timings.d.ts.map +1 -1
  265. package/dist/core/timings.js.map +1 -1
  266. package/dist/core/tools/bash.d.ts +12 -0
  267. package/dist/core/tools/bash.d.ts.map +1 -1
  268. package/dist/core/tools/bash.js +33 -2
  269. package/dist/core/tools/bash.js.map +1 -1
  270. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  271. package/dist/core/tools/edit-diff.js.map +1 -1
  272. package/dist/core/tools/edit.d.ts.map +1 -1
  273. package/dist/core/tools/edit.js.map +1 -1
  274. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  275. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  276. package/dist/core/tools/find.d.ts.map +1 -1
  277. package/dist/core/tools/find.js.map +1 -1
  278. package/dist/core/tools/grep.d.ts.map +1 -1
  279. package/dist/core/tools/grep.js.map +1 -1
  280. package/dist/core/tools/index.d.ts.map +1 -1
  281. package/dist/core/tools/index.js.map +1 -1
  282. package/dist/core/tools/ls.d.ts.map +1 -1
  283. package/dist/core/tools/ls.js.map +1 -1
  284. package/dist/core/tools/output-accumulator.d.ts +11 -0
  285. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  286. package/dist/core/tools/output-accumulator.js +36 -0
  287. package/dist/core/tools/output-accumulator.js.map +1 -1
  288. package/dist/core/tools/path-utils.d.ts.map +1 -1
  289. package/dist/core/tools/path-utils.js.map +1 -1
  290. package/dist/core/tools/powershell.d.ts.map +1 -1
  291. package/dist/core/tools/powershell.js.map +1 -1
  292. package/dist/core/tools/read.d.ts.map +1 -1
  293. package/dist/core/tools/read.js.map +1 -1
  294. package/dist/core/tools/render-utils.d.ts +6 -0
  295. package/dist/core/tools/render-utils.d.ts.map +1 -1
  296. package/dist/core/tools/render-utils.js +26 -0
  297. package/dist/core/tools/render-utils.js.map +1 -1
  298. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  299. package/dist/core/tools/renderers/bash.js +11 -32
  300. package/dist/core/tools/renderers/bash.js.map +1 -1
  301. package/dist/core/tools/renderers/edit.d.ts.map +1 -1
  302. package/dist/core/tools/renderers/edit.js.map +1 -1
  303. package/dist/core/tools/renderers/find.d.ts.map +1 -1
  304. package/dist/core/tools/renderers/find.js.map +1 -1
  305. package/dist/core/tools/renderers/grep.d.ts.map +1 -1
  306. package/dist/core/tools/renderers/grep.js.map +1 -1
  307. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  308. package/dist/core/tools/renderers/index.js.map +1 -1
  309. package/dist/core/tools/renderers/ls.d.ts.map +1 -1
  310. package/dist/core/tools/renderers/ls.js.map +1 -1
  311. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  312. package/dist/core/tools/renderers/read.js +3 -2
  313. package/dist/core/tools/renderers/read.js.map +1 -1
  314. package/dist/core/tools/renderers/write.d.ts.map +1 -1
  315. package/dist/core/tools/renderers/write.js.map +1 -1
  316. package/dist/core/tools/tool-definition-wrapper.d.ts +5 -3
  317. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  318. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  319. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  320. package/dist/core/tools/truncate.d.ts +14 -0
  321. package/dist/core/tools/truncate.d.ts.map +1 -1
  322. package/dist/core/tools/truncate.js +29 -0
  323. package/dist/core/tools/truncate.js.map +1 -1
  324. package/dist/core/tools/write.d.ts.map +1 -1
  325. package/dist/core/tools/write.js.map +1 -1
  326. package/dist/core/trust-manager.d.ts.map +1 -1
  327. package/dist/core/trust-manager.js +1 -0
  328. package/dist/core/trust-manager.js.map +1 -1
  329. package/dist/core/usage-totals.d.ts +2 -0
  330. package/dist/core/usage-totals.d.ts.map +1 -1
  331. package/dist/core/usage-totals.js +23 -0
  332. package/dist/core/usage-totals.js.map +1 -1
  333. package/dist/core/virtual-models.d.ts +117 -0
  334. package/dist/core/virtual-models.d.ts.map +1 -0
  335. package/dist/core/virtual-models.js +124 -0
  336. package/dist/core/virtual-models.js.map +1 -0
  337. package/dist/extensions/codemode/execute.d.ts +16 -0
  338. package/dist/extensions/codemode/execute.d.ts.map +1 -0
  339. package/dist/extensions/codemode/execute.js +536 -0
  340. package/dist/extensions/codemode/execute.js.map +1 -0
  341. package/dist/extensions/codemode/execute.lazy.d.ts +3 -0
  342. package/dist/extensions/codemode/execute.lazy.d.ts.map +1 -0
  343. package/dist/extensions/codemode/execute.lazy.js +3 -0
  344. package/dist/extensions/codemode/execute.lazy.js.map +1 -0
  345. package/dist/extensions/codemode/index.d.ts +21 -0
  346. package/dist/extensions/codemode/index.d.ts.map +1 -0
  347. package/dist/extensions/codemode/index.js +31 -0
  348. package/dist/extensions/codemode/index.js.map +1 -0
  349. package/dist/extensions/codemode/renderer.d.ts +12 -0
  350. package/dist/extensions/codemode/renderer.d.ts.map +1 -0
  351. package/dist/extensions/codemode/renderer.js +137 -0
  352. package/dist/extensions/codemode/renderer.js.map +1 -0
  353. package/dist/extensions/codemode/tool.d.ts +123 -0
  354. package/dist/extensions/codemode/tool.d.ts.map +1 -0
  355. package/dist/extensions/codemode/tool.js +268 -0
  356. package/dist/extensions/codemode/tool.js.map +1 -0
  357. package/dist/extensions/codemode/worker.d.ts +7 -0
  358. package/dist/extensions/codemode/worker.d.ts.map +1 -0
  359. package/dist/extensions/codemode/worker.js +7 -0
  360. package/dist/extensions/codemode/worker.js.map +1 -0
  361. package/dist/extensions/index.d.ts.map +1 -1
  362. package/dist/extensions/index.js +11 -1
  363. package/dist/extensions/index.js.map +1 -1
  364. package/dist/extensions/llama/client.d.ts.map +1 -1
  365. package/dist/extensions/llama/client.js.map +1 -1
  366. package/dist/extensions/llama/huggingface.d.ts.map +1 -1
  367. package/dist/extensions/llama/huggingface.js.map +1 -1
  368. package/dist/extensions/llama/index.d.ts.map +1 -1
  369. package/dist/extensions/llama/index.js.map +1 -1
  370. package/dist/extensions/llama/provider.d.ts +1 -1
  371. package/dist/extensions/llama/provider.d.ts.map +1 -1
  372. package/dist/extensions/llama/provider.js +65 -13
  373. package/dist/extensions/llama/provider.js.map +1 -1
  374. package/dist/extensions/llama/ui.d.ts.map +1 -1
  375. package/dist/extensions/llama/ui.js.map +1 -1
  376. package/dist/extensions/mcp/cli.d.ts +21 -0
  377. package/dist/extensions/mcp/cli.d.ts.map +1 -0
  378. package/dist/extensions/mcp/cli.js +500 -0
  379. package/dist/extensions/mcp/cli.js.map +1 -0
  380. package/dist/extensions/mcp/cli.lazy.d.ts +3 -0
  381. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -0
  382. package/dist/extensions/mcp/cli.lazy.js +3 -0
  383. package/dist/extensions/mcp/cli.lazy.js.map +1 -0
  384. package/dist/extensions/mcp/config.d.ts +72 -0
  385. package/dist/extensions/mcp/config.d.ts.map +1 -0
  386. package/dist/extensions/mcp/config.js +158 -0
  387. package/dist/extensions/mcp/config.js.map +1 -0
  388. package/dist/extensions/mcp/index.d.ts +76 -0
  389. package/dist/extensions/mcp/index.d.ts.map +1 -0
  390. package/dist/extensions/mcp/index.js +1066 -0
  391. package/dist/extensions/mcp/index.js.map +1 -0
  392. package/dist/extensions/mcp/log.d.ts +16 -0
  393. package/dist/extensions/mcp/log.d.ts.map +1 -0
  394. package/dist/extensions/mcp/log.js +66 -0
  395. package/dist/extensions/mcp/log.js.map +1 -0
  396. package/dist/extensions/mcp/oauth.d.ts +97 -0
  397. package/dist/extensions/mcp/oauth.d.ts.map +1 -0
  398. package/dist/extensions/mcp/oauth.js +358 -0
  399. package/dist/extensions/mcp/oauth.js.map +1 -0
  400. package/dist/extensions/mcp/resources.d.ts +43 -0
  401. package/dist/extensions/mcp/resources.d.ts.map +1 -0
  402. package/dist/extensions/mcp/resources.js +262 -0
  403. package/dist/extensions/mcp/resources.js.map +1 -0
  404. package/dist/extensions/mcp/runtime.d.ts +98 -0
  405. package/dist/extensions/mcp/runtime.d.ts.map +1 -0
  406. package/dist/extensions/mcp/runtime.js +395 -0
  407. package/dist/extensions/mcp/runtime.js.map +1 -0
  408. package/dist/extensions/mcp/runtime.lazy.d.ts +3 -0
  409. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -0
  410. package/dist/extensions/mcp/runtime.lazy.js +3 -0
  411. package/dist/extensions/mcp/runtime.lazy.js.map +1 -0
  412. package/dist/extensions/mcp/tools.d.ts +84 -0
  413. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  414. package/dist/extensions/mcp/tools.js +251 -0
  415. package/dist/extensions/mcp/tools.js.map +1 -0
  416. package/dist/extensions/mcp/ui.d.ts +60 -0
  417. package/dist/extensions/mcp/ui.d.ts.map +1 -0
  418. package/dist/extensions/mcp/ui.js +174 -0
  419. package/dist/extensions/mcp/ui.js.map +1 -0
  420. package/dist/extensions/tool-search/index.d.ts +12 -0
  421. package/dist/extensions/tool-search/index.d.ts.map +1 -0
  422. package/dist/extensions/tool-search/index.js +15 -0
  423. package/dist/extensions/tool-search/index.js.map +1 -0
  424. package/dist/extensions/tool-search/tool.d.ts +73 -0
  425. package/dist/extensions/tool-search/tool.d.ts.map +1 -0
  426. package/dist/extensions/tool-search/tool.js +189 -0
  427. package/dist/extensions/tool-search/tool.js.map +1 -0
  428. package/dist/index.d.ts +10 -3
  429. package/dist/index.d.ts.map +1 -1
  430. package/dist/index.js +5 -0
  431. package/dist/index.js.map +1 -1
  432. package/dist/main.d.ts.map +1 -1
  433. package/dist/main.js +16 -0
  434. package/dist/main.js.map +1 -1
  435. package/dist/migrations.d.ts.map +1 -1
  436. package/dist/migrations.js.map +1 -1
  437. package/dist/modes/index.d.ts.map +1 -1
  438. package/dist/modes/interactive/bug-report.d.ts.map +1 -1
  439. package/dist/modes/interactive/bug-report.js.map +1 -1
  440. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
  441. package/dist/modes/interactive/chat-viewport.js.map +1 -1
  442. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  443. package/dist/modes/interactive/components/armin.js.map +1 -1
  444. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  445. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  446. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  447. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  448. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  449. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  450. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  451. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  452. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  453. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  454. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  455. package/dist/modes/interactive/components/config-selector.js +13 -3
  456. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  457. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  458. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  459. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  460. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  461. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  462. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  463. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  464. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  465. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  466. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  467. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  468. package/dist/modes/interactive/components/diff.js.map +1 -1
  469. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  470. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  471. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  472. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  473. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  474. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  475. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  476. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  477. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  478. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  479. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  480. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  481. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  482. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  483. package/dist/modes/interactive/components/footer.d.ts +7 -0
  484. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  485. package/dist/modes/interactive/components/footer.js +43 -3
  486. package/dist/modes/interactive/components/footer.js.map +1 -1
  487. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  488. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  489. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  490. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  491. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  492. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  493. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  494. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  495. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  496. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  497. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  498. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  499. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  500. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  501. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  502. package/dist/modes/interactive/components/pi-logo-animation.d.ts +68 -0
  503. package/dist/modes/interactive/components/pi-logo-animation.d.ts.map +1 -0
  504. package/dist/modes/interactive/components/pi-logo-animation.js +1086 -0
  505. package/dist/modes/interactive/components/pi-logo-animation.js.map +1 -0
  506. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts +7 -0
  507. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts.map +1 -0
  508. package/dist/modes/interactive/components/pi-logo-animation.lazy.js +12 -0
  509. package/dist/modes/interactive/components/pi-logo-animation.lazy.js.map +1 -0
  510. package/dist/modes/interactive/components/pi-logo.d.ts +19 -0
  511. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -0
  512. package/dist/modes/interactive/components/pi-logo.js +37 -0
  513. package/dist/modes/interactive/components/pi-logo.js.map +1 -0
  514. package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
  515. package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
  516. package/dist/modes/interactive/components/radius-login-selector.js +85 -0
  517. package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
  518. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  519. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  520. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  521. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  522. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  523. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  524. package/dist/modes/interactive/components/settings-selector.d.ts +6 -4
  525. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  526. package/dist/modes/interactive/components/settings-selector.js +33 -11
  527. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  528. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  529. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  530. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  531. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  532. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  533. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  534. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  535. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  536. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  537. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  538. package/dist/modes/interactive/components/themed-text.d.ts +17 -0
  539. package/dist/modes/interactive/components/themed-text.d.ts.map +1 -0
  540. package/dist/modes/interactive/components/themed-text.js +29 -0
  541. package/dist/modes/interactive/components/themed-text.js.map +1 -0
  542. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  543. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  544. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  545. package/dist/modes/interactive/components/tool-execution.js +2 -2
  546. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  547. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  548. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  549. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  550. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  551. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  552. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  553. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  554. package/dist/modes/interactive/components/user-message.js +5 -4
  555. package/dist/modes/interactive/components/user-message.js.map +1 -1
  556. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  557. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  558. package/dist/modes/interactive/components/visual-truncate.js +39 -6
  559. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  560. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  561. package/dist/modes/interactive/external-editor.js.map +1 -1
  562. package/dist/modes/interactive/interactive-mode.d.ts +21 -0
  563. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  564. package/dist/modes/interactive/interactive-mode.js +348 -197
  565. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  566. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -1
  567. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -1
  568. package/dist/modes/interactive/model-search.d.ts.map +1 -1
  569. package/dist/modes/interactive/model-search.js.map +1 -1
  570. package/dist/modes/interactive/session-share.d.ts.map +1 -1
  571. package/dist/modes/interactive/session-share.js.map +1 -1
  572. package/dist/modes/interactive/theme/dark.json +59 -72
  573. package/dist/modes/interactive/theme/light.json +57 -69
  574. package/dist/modes/interactive/theme/system-theme.d.ts +55 -0
  575. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
  576. package/dist/modes/interactive/theme/system-theme.js +546 -0
  577. package/dist/modes/interactive/theme/system-theme.js.map +1 -0
  578. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  579. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  580. package/dist/modes/interactive/theme/theme-controller.js +127 -47
  581. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  582. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  583. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -1
  584. package/dist/modes/interactive/theme/theme-json.js +3 -1
  585. package/dist/modes/interactive/theme/theme-json.js.map +1 -1
  586. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  587. package/dist/modes/interactive/theme/theme.d.ts +66 -39
  588. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  589. package/dist/modes/interactive/theme/theme.js +238 -317
  590. package/dist/modes/interactive/theme/theme.js.map +1 -1
  591. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  592. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  593. package/dist/modes/interactive/tui-renderer.js +1 -0
  594. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  595. package/dist/modes/json-event.d.ts.map +1 -1
  596. package/dist/modes/json-event.js.map +1 -1
  597. package/dist/modes/print-mode.d.ts.map +1 -1
  598. package/dist/modes/print-mode.js.map +1 -1
  599. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  600. package/dist/modes/rpc/jsonl.js.map +1 -1
  601. package/dist/modes/rpc/rpc-client.d.ts +6 -6
  602. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  603. package/dist/modes/rpc/rpc-client.js +12 -8
  604. package/dist/modes/rpc/rpc-client.js.map +1 -1
  605. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  606. package/dist/modes/rpc/rpc-mode.js +7 -9
  607. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  608. package/dist/modes/rpc/rpc-types.d.ts +10 -1
  609. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  610. package/dist/modes/rpc/rpc-types.js.map +1 -1
  611. package/dist/package-manager-cli.d.ts.map +1 -1
  612. package/dist/package-manager-cli.js +6 -2
  613. package/dist/package-manager-cli.js.map +1 -1
  614. package/dist/rpc-entry.d.ts.map +1 -1
  615. package/dist/rpc-entry.js.map +1 -1
  616. package/dist/utils/abort.d.ts.map +1 -1
  617. package/dist/utils/abort.js.map +1 -1
  618. package/dist/utils/ansi.d.ts.map +1 -1
  619. package/dist/utils/ansi.js.map +1 -1
  620. package/dist/utils/changelog.d.ts.map +1 -1
  621. package/dist/utils/changelog.js.map +1 -1
  622. package/dist/utils/child-process.d.ts.map +1 -1
  623. package/dist/utils/child-process.js.map +1 -1
  624. package/dist/utils/clipboard-command.d.ts.map +1 -1
  625. package/dist/utils/clipboard-command.js.map +1 -1
  626. package/dist/utils/clipboard-image.d.ts.map +1 -1
  627. package/dist/utils/clipboard-image.js +14 -17
  628. package/dist/utils/clipboard-image.js.map +1 -1
  629. package/dist/utils/clipboard.d.ts +2 -0
  630. package/dist/utils/clipboard.d.ts.map +1 -1
  631. package/dist/utils/clipboard.js +5 -0
  632. package/dist/utils/clipboard.js.map +1 -1
  633. package/dist/utils/deprecation.d.ts.map +1 -1
  634. package/dist/utils/deprecation.js.map +1 -1
  635. package/dist/utils/exif-orientation.d.ts.map +1 -1
  636. package/dist/utils/exif-orientation.js.map +1 -1
  637. package/dist/utils/frontmatter.d.ts.map +1 -1
  638. package/dist/utils/frontmatter.js.map +1 -1
  639. package/dist/utils/fs-watch.d.ts.map +1 -1
  640. package/dist/utils/fs-watch.js.map +1 -1
  641. package/dist/utils/git.d.ts.map +1 -1
  642. package/dist/utils/git.js.map +1 -1
  643. package/dist/utils/html.d.ts.map +1 -1
  644. package/dist/utils/html.js.map +1 -1
  645. package/dist/utils/image-convert.d.ts.map +1 -1
  646. package/dist/utils/image-convert.js.map +1 -1
  647. package/dist/utils/image-process.d.ts.map +1 -1
  648. package/dist/utils/image-process.js.map +1 -1
  649. package/dist/utils/image-resize-core.d.ts.map +1 -1
  650. package/dist/utils/image-resize-core.js.map +1 -1
  651. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  652. package/dist/utils/image-resize-worker.js.map +1 -1
  653. package/dist/utils/image-resize.d.ts.map +1 -1
  654. package/dist/utils/image-resize.js.map +1 -1
  655. package/dist/utils/json.d.ts.map +1 -1
  656. package/dist/utils/json.js.map +1 -1
  657. package/dist/utils/management-http.d.ts.map +1 -1
  658. package/dist/utils/management-http.js.map +1 -1
  659. package/dist/utils/mime.d.ts.map +1 -1
  660. package/dist/utils/mime.js.map +1 -1
  661. package/dist/utils/open-browser.d.ts.map +1 -1
  662. package/dist/utils/open-browser.js.map +1 -1
  663. package/dist/utils/paths.d.ts +3 -3
  664. package/dist/utils/paths.d.ts.map +1 -1
  665. package/dist/utils/paths.js +5 -4
  666. package/dist/utils/paths.js.map +1 -1
  667. package/dist/utils/photon.d.ts.map +1 -1
  668. package/dist/utils/photon.js.map +1 -1
  669. package/dist/utils/pi-user-agent.d.ts.map +1 -1
  670. package/dist/utils/pi-user-agent.js.map +1 -1
  671. package/dist/utils/shell.d.ts +1 -3
  672. package/dist/utils/shell.d.ts.map +1 -1
  673. package/dist/utils/shell.js +3 -30
  674. package/dist/utils/shell.js.map +1 -1
  675. package/dist/utils/sleep.d.ts.map +1 -1
  676. package/dist/utils/sleep.js.map +1 -1
  677. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  678. package/dist/utils/syntax-highlight.js +2 -0
  679. package/dist/utils/syntax-highlight.js.map +1 -1
  680. package/dist/utils/text.d.ts.map +1 -1
  681. package/dist/utils/text.js.map +1 -1
  682. package/dist/utils/tool-result-images.d.ts.map +1 -1
  683. package/dist/utils/tool-result-images.js.map +1 -1
  684. package/dist/utils/tools-manager.d.ts.map +1 -1
  685. package/dist/utils/tools-manager.js.map +1 -1
  686. package/dist/utils/version-check.d.ts.map +1 -1
  687. package/dist/utils/version-check.js.map +1 -1
  688. package/dist/utils/windows-self-update.d.ts.map +1 -1
  689. package/dist/utils/windows-self-update.js.map +1 -1
  690. package/dist/utils/wsl.d.ts.map +1 -1
  691. package/dist/utils/wsl.js.map +1 -1
  692. package/dist/utils/zip.d.ts.map +1 -1
  693. package/dist/utils/zip.js.map +1 -1
  694. package/docs/cli.md +58 -7
  695. package/docs/codemode.md +207 -0
  696. package/docs/configuration.md +2 -0
  697. package/docs/custom-provider.md +43 -4
  698. package/docs/docs.json +13 -1
  699. package/docs/environment-variables.md +2 -2
  700. package/docs/extensions.md +55 -0
  701. package/docs/index.md +1 -1
  702. package/docs/keybindings.md +1 -1
  703. package/docs/llama-cpp.md +13 -0
  704. package/docs/mcp.md +248 -0
  705. package/docs/models.md +57 -1
  706. package/docs/packages.md +4 -2
  707. package/docs/providers.md +19 -6
  708. package/docs/rpc-commands.md +9 -3
  709. package/docs/rpc.md +3 -1
  710. package/docs/sdk.md +8 -3
  711. package/docs/security.md +2 -0
  712. package/docs/session-format.md +5 -1
  713. package/docs/settings.md +24 -5
  714. package/docs/themes.md +33 -7
  715. package/docs/tui.md +18 -0
  716. package/docs/usage.md +1 -1
  717. package/docs/virtual-models.md +114 -0
  718. package/docs/windows.md +2 -0
  719. package/examples/README.md +1 -1
  720. package/examples/extensions/README.md +2 -0
  721. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  722. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  723. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  724. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  725. package/examples/extensions/custom-provider-gitlab-duo/test.ts +5 -5
  726. package/examples/extensions/debug-provider.ts +90 -0
  727. package/examples/extensions/gondolin/package-lock.json +2 -2
  728. package/examples/extensions/gondolin/package.json +1 -1
  729. package/examples/extensions/jev-router.ts +113 -0
  730. package/examples/extensions/minimal-mode.ts +24 -96
  731. package/examples/extensions/sandbox/package-lock.json +2 -2
  732. package/examples/extensions/sandbox/package.json +1 -1
  733. package/examples/extensions/with-deps/package-lock.json +2 -2
  734. package/examples/extensions/with-deps/package.json +1 -1
  735. package/examples/rpc-client.ts +1 -1
  736. package/examples/rpc-extension-ui.ts +1 -1
  737. package/examples/sdk/14-codemode-mcp.ts +61 -0
  738. package/examples/sdk/README.md +2 -1
  739. package/npm-shrinkwrap.json +88 -43
  740. package/package.json +14 -12
  741. package/dist/bundle/chunks/anthropic-messages-J5WXPPPC.js +0 -6
  742. package/dist/bundle/chunks/azure-openai-responses-HUSQ3GP2.js +0 -2
  743. package/dist/bundle/chunks/chunk-6R7UI4IY.js +0 -2
  744. package/dist/bundle/chunks/chunk-FN7P5NHX.js +0 -1568
  745. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
  746. package/dist/bundle/chunks/chunk-RCZIEVGO.js +0 -11
  747. package/dist/bundle/chunks/chunk-S7SZN6Z3.js +0 -2
  748. package/dist/bundle/chunks/chunk-UXY3GQU2.js +0 -2
  749. package/dist/bundle/chunks/chunk-XNGRGP62.js +0 -2
  750. package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +0 -2
  751. package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +0 -2
  752. package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +0 -5
  753. package/dist/bundle/chunks/openai-responses-HWEUZ6WZ.js +0 -2
  754. package/dist/bundle/chunks/virtual-modules-WS3GCBF2.js +0 -2
@@ -14,6 +14,7 @@
14
14
  */
15
15
  import { readFileSync } 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, 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";
@@ -32,16 +33,19 @@ import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
32
33
  import { emitSessionShutdownEvent } from "./extensions/runner.js";
33
34
  import { convertToLlm } from "./messages.js";
34
35
  import { ModelRegistry } from "./model-registry.js";
36
+ import { NestedToolCallRunner } from "./nested-tool-calls.js";
35
37
  import { expandPromptTemplate } from "./prompt-templates.js";
36
38
  import { exportSessionToJsonl } from "./session-export.js";
37
39
  import { getLatestCompactionEntry, SessionManager, } from "./session-manager.js";
40
+ import { DEFAULT_TOOL_NAMES } from "./settings-manager.js";
38
41
  import { findSkillByInvocationName, resolveBareNamespaceSkill } from "./skills.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.
@@ -104,6 +108,11 @@ export class AgentSession {
104
108
  // Retry state
105
109
  _retryAbortController = undefined;
106
110
  _retryAttempt = 0;
111
+ /**
112
+ * Failed response that the next request repeats, set by auto-retry and overflow recovery. The
113
+ * retry is routed with it as `failed`, since the context no longer contains it.
114
+ */
115
+ _failedResponse;
107
116
  // Bash execution state
108
117
  _bashAbortControllers = new Set();
109
118
  _pendingBashMessages = [];
@@ -125,6 +134,13 @@ export class AgentSession {
125
134
  _cwd;
126
135
  _extensionRunnerRef;
127
136
  _initialActiveToolNames;
137
+ /**
138
+ * Tools of the restored or reloaded loadout that are not registered yet, such as tools of MCP
139
+ * servers that are still connecting. They are activated when they are registered, and dropped when
140
+ * `setActiveToolsByName()` deactivates a tool or the next agent run starts.
141
+ */
142
+ _pendingToolNames = new Set();
143
+ _usesDefaultTools;
128
144
  _allowedToolNames;
129
145
  _excludedToolNames;
130
146
  _baseToolsOverride;
@@ -140,6 +156,10 @@ export class AgentSession {
140
156
  _cacheWarmer;
141
157
  // Tool registry for extension getTools/setTools
142
158
  _toolRegistry = new Map();
159
+ /** Created on the first `ctx.executeTool()` call. */
160
+ _nestedToolCalls;
161
+ /** Declared tools whose declarations requests leave out, from `prepareLoadout` hooks. */
162
+ _hiddenDeclarations = new Set();
143
163
  _toolDefinitions = new Map();
144
164
  _toolPromptSnippets = new Map();
145
165
  _toolPromptGuidelines = new Map();
@@ -161,6 +181,7 @@ export class AgentSession {
161
181
  }
162
182
  this._extensionRunnerRef = config.extensionRunnerRef;
163
183
  this._initialActiveToolNames = config.initialActiveToolNames;
184
+ this._usesDefaultTools = config.usesDefaultTools ?? false;
164
185
  this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
165
186
  this._excludedToolNames = config.excludedToolNames ? new Set(config.excludedToolNames) : undefined;
166
187
  this._baseToolsOverride = config.baseToolsOverride;
@@ -172,6 +193,7 @@ export class AgentSession {
172
193
  this._installAgentNextTurnRefresh();
173
194
  this._installAgentRequestProjection();
174
195
  this._installAgentBoundaryHooks();
196
+ this._installHiddenDeclarationsProjection();
175
197
  this._installAgentForcedPromptProjection();
176
198
  this._buildRuntime({
177
199
  activeToolNames: this._initialActiveToolNames,
@@ -212,28 +234,71 @@ export class AgentSession {
212
234
  }
213
235
  throw new Error(formatNoApiKeyFoundMessage(model.provider));
214
236
  }
215
- async _getSummarizationRequestAuth(model, signal) {
237
+ async _getSummarizationRequestAuth(selectedModel, signal) {
238
+ // Route a virtual model first: summaries size their input and output from the model they get.
239
+ const { model, thinkingLevel } = isVirtualModel(selectedModel)
240
+ ? await this._modelRuntime.resolveModel(selectedModel, convertToLlm(this.messages), {
241
+ reason: "direct",
242
+ thinkingLevel: this.thinkingLevel,
243
+ signal,
244
+ })
245
+ : { model: selectedModel, thinkingLevel: this.thinkingLevel };
216
246
  if (this.agent.streamFunction === streamSimple) {
217
- return this._getRequiredRequestAuth(model, signal);
247
+ return { ...(await this._getRequiredRequestAuth(model, signal)), thinkingLevel };
218
248
  }
219
249
  try {
220
250
  const result = await this._modelRuntime.getAuth(model, { signal });
221
251
  if (!result)
222
- return { model };
252
+ return { model, thinkingLevel };
223
253
  const requestModel = result.auth.baseUrl ? { ...model, baseUrl: result.auth.baseUrl } : model;
224
254
  return {
225
255
  model: requestModel,
226
256
  apiKey: result.auth.apiKey,
227
257
  headers: withoutDeletedHeaders(result.auth.headers),
228
258
  env: result.env,
259
+ thinkingLevel,
229
260
  };
230
261
  }
231
262
  catch (error) {
232
263
  if (signal?.aborted)
233
264
  throw error;
234
- return { model };
265
+ return { model, thinkingLevel };
235
266
  }
236
267
  }
268
+ /**
269
+ * The model whose limits apply to `message`, or undefined when the message came from another
270
+ * model. Under a virtual selection, that is the physical model that produced it.
271
+ */
272
+ _modelForMessage(message) {
273
+ const model = this.model;
274
+ if (model && isVirtualModel(model))
275
+ return this._modelRuntime.getPhysicalModel(message.provider, message.model);
276
+ return model?.provider === message.provider && model.id === message.model ? model : undefined;
277
+ }
278
+ /**
279
+ * Record the selection on the current branch when the branch implies another one, so a resume
280
+ * restores it. Tree navigation can leave the latest `model_change` on another branch; responses
281
+ * cannot record a virtual selection because they name physical models. Responses do record a
282
+ * physical selection unless the branch holds a virtual one; checking a physical selection against
283
+ * responses would record it on every prompt while `prepareRequest` redirects to another model.
284
+ */
285
+ _recordSelection() {
286
+ const model = this.model;
287
+ if (!model)
288
+ return;
289
+ const getModel = (provider, modelId) => this._modelRuntime.getModel(provider, modelId);
290
+ const recorded = getBranchSelection(this.sessionManager.getBranch(), getModel);
291
+ if (!recorded || (recorded.provider === model.provider && recorded.modelId === model.id))
292
+ return;
293
+ const recordedModel = getModel(recorded.provider, recorded.modelId);
294
+ if (!isVirtualModel(model) && !(recordedModel && isVirtualModel(recordedModel)))
295
+ return;
296
+ this.sessionManager.appendModelChange(model.provider, model.id);
297
+ }
298
+ /** The model whose limits apply to the conversation. */
299
+ _limitsModel() {
300
+ return this.routedModel?.model ?? this.model;
301
+ }
237
302
  /**
238
303
  * Install tool hooks once on the Agent instance.
239
304
  *
@@ -243,65 +308,112 @@ export class AgentSession {
243
308
  * happens here instead of in wrappers.
244
309
  */
245
310
  _installAgentToolHooks() {
246
- this.agent.beforeToolCall = async ({ toolCall, args }) => {
247
- const runner = this._extensionRunner;
248
- if (!runner.hasHandlers("tool_call")) {
249
- return undefined;
250
- }
251
- try {
252
- return await runner.emitToolCall({
253
- type: "tool_call",
254
- toolName: toolCall.name,
255
- toolCallId: toolCall.id,
256
- input: args,
257
- });
258
- }
259
- catch (err) {
260
- if (err instanceof Error) {
261
- throw err;
262
- }
263
- throw new Error(`Extension failed, blocking execution: ${String(err)}`);
264
- }
265
- };
266
- this.agent.afterToolCall = async ({ toolCall, args, result, isError }) => {
267
- const runner = this._extensionRunner;
268
- const hookResult = runner.hasHandlers("tool_result")
269
- ? await runner.emitToolResult({
270
- type: "tool_result",
271
- toolName: toolCall.name,
272
- toolCallId: toolCall.id,
273
- input: args,
274
- content: result.content,
275
- details: result.details,
276
- isError,
277
- usage: result.usage,
278
- })
279
- : undefined;
280
- const content = hookResult?.content ?? result.content ?? [];
281
- // Runs after the extension hook so images injected or replaced by extensions are normalized too.
282
- const resizeOptions = this.model?.inputLimits?.images?.resize;
283
- const normalizedContent = await normalizeToolResultImages(content, {
284
- autoResizeImages: this.settingsManager.getImageAutoResize(),
285
- ...(resizeOptions ? { resizeOptions } : {}),
311
+ this.agent.beforeToolCall = (context) => this._beforeToolCall(context);
312
+ this.agent.afterToolCall = (context) => this._afterToolCall(context);
313
+ }
314
+ /** `tool_call` handlers. `parentToolCallId` is set for calls another tool made. */
315
+ async _beforeToolCall({ toolCall, args }, parentToolCallId) {
316
+ const runner = this._extensionRunner;
317
+ if (!runner.hasHandlers("tool_call")) {
318
+ return undefined;
319
+ }
320
+ try {
321
+ return await runner.emitToolCall({
322
+ type: "tool_call",
323
+ toolName: toolCall.name,
324
+ toolCallId: toolCall.id,
325
+ ...(parentToolCallId ? { parentToolCallId } : {}),
326
+ input: args,
286
327
  });
287
- if (!hookResult && normalizedContent === content) {
288
- return undefined;
328
+ }
329
+ catch (err) {
330
+ if (err instanceof Error) {
331
+ throw err;
289
332
  }
290
- return {
291
- content: normalizedContent,
292
- details: hookResult?.details,
293
- isError: hookResult?.isError ?? isError,
294
- usage: hookResult?.usage,
295
- };
333
+ throw new Error(`Extension failed, blocking execution: ${String(err)}`);
334
+ }
335
+ }
336
+ /** `tool_result` handlers and image normalization. `parentToolCallId` is set for calls another tool made. */
337
+ async _afterToolCall({ toolCall, args, result, isError }, parentToolCallId) {
338
+ const runner = this._extensionRunner;
339
+ const hookResult = runner.hasHandlers("tool_result")
340
+ ? await runner.emitToolResult({
341
+ type: "tool_result",
342
+ toolName: toolCall.name,
343
+ toolCallId: toolCall.id,
344
+ ...(parentToolCallId ? { parentToolCallId } : {}),
345
+ input: args,
346
+ content: result.content,
347
+ details: result.details,
348
+ ...(result.structuredContent === undefined ? {} : { structuredContent: result.structuredContent }),
349
+ isError,
350
+ usage: result.usage,
351
+ })
352
+ : undefined;
353
+ const content = hookResult?.content ?? result.content ?? [];
354
+ // Runs after the extension hook so images injected or replaced by extensions are normalized too.
355
+ const resizeOptions = this._limitsModel()?.inputLimits?.images?.resize;
356
+ const normalizedContent = await normalizeToolResultImages(content, {
357
+ autoResizeImages: this.settingsManager.getImageAutoResize(),
358
+ ...(resizeOptions ? { resizeOptions } : {}),
359
+ });
360
+ if (!hookResult && normalizedContent === content) {
361
+ return undefined;
362
+ }
363
+ // The hook result already dropped structured content that replaced content no longer matches.
364
+ return {
365
+ content: normalizedContent,
366
+ details: hookResult?.details,
367
+ structuredContent: hookResult ? hookResult.structuredContent : result.structuredContent,
368
+ isError: hookResult?.isError ?? isError,
369
+ usage: hookResult?.usage,
296
370
  };
297
371
  }
372
+ /**
373
+ * Run a call that the tool call `parentToolCallId` made through `ctx.executeTool()`. It goes
374
+ * through the agent's tool pipeline with the session's hooks, against the callable tools.
375
+ */
376
+ async _executeNestedToolCall(parentToolCallId, name, args, options) {
377
+ this._nestedToolCalls ??= new NestedToolCallRunner({
378
+ getTools: () => this._getCallableTools(),
379
+ isSequential: () => this.agent.toolExecution === "sequential",
380
+ runToolCall: (toolCall, parentId, signal, onUpdate) => {
381
+ const assistantMessage = this._findLastAssistantMessage();
382
+ if (!assistantMessage) {
383
+ return Promise.resolve({
384
+ toolCall,
385
+ result: { content: [{ type: "text", text: "No assistant message issued this call" }], details: {} },
386
+ isError: true,
387
+ });
388
+ }
389
+ return runToolCall(toolCall, {
390
+ tools: this._getCallableTools(),
391
+ assistantMessage,
392
+ context: { messages: this.agent.state.messages, tools: this.agent.state.tools },
393
+ beforeToolCall: (context) => this._beforeToolCall(context, parentId),
394
+ afterToolCall: (context) => this._afterToolCall(context, parentId),
395
+ signal,
396
+ onUpdate,
397
+ });
398
+ },
399
+ emit: async (event) => {
400
+ await this._extensionRunner.emit(event);
401
+ this._emit(event);
402
+ },
403
+ });
404
+ return this._nestedToolCalls.execute(parentToolCallId, name, args, options);
405
+ }
406
+ /** Whether `projection`, the current session projection, exceeds the compaction threshold of `model`. */
407
+ _exceedsCompactionThreshold(model, projection) {
408
+ if (model.contextWindow <= 0)
409
+ return false;
410
+ return shouldCompact(estimateProjectedContextTokens(projection, this.sessionManager.getBranch()).tokens, model.contextWindow, this.settingsManager.getCompactionSettings(this.model));
411
+ }
298
412
  async _compactBeforeNextAssistantResponse(context) {
299
- const model = this.model;
300
- const settings = this.settingsManager.getCompactionSettings(model);
301
413
  const projection = this.sessionManager.buildSessionProjection();
302
- if (!model ||
303
- model.contextWindow <= 0 ||
304
- !shouldCompact(estimateProjectedContextTokens(projection, this.sessionManager.getBranch()).tokens, model.contextWindow, settings)) {
414
+ // A virtual selection is checked in prepareRequest, against the model the request is routed to.
415
+ const model = this.model;
416
+ if (!model || isVirtualModel(model) || !this._exceedsCompactionThreshold(model, projection)) {
305
417
  return { ...context, messages: projection.messages };
306
418
  }
307
419
  await this._runAutoCompaction("threshold", false);
@@ -310,24 +422,55 @@ export class AgentSession {
310
422
  _installAgentRequestProjection() {
311
423
  const previousPrepareRequest = this.agent.prepareRequest;
312
424
  this.agent.prepareRequest = async (request, signal) => {
313
- const canonicalContext = {
314
- ...request.context,
315
- messages: this.sessionManager.buildSessionProjection().messages,
316
- // Messages declare the provider-visible loadout; context.tools keeps executable implementations.
317
- tools: this.agent.state.tools.slice(),
318
- };
319
- const previous = await previousPrepareRequest?.({
320
- ...request,
321
- context: canonicalContext,
322
- model: this.agent.state.model,
323
- thinkingLevel: this.agent.state.thinkingLevel,
324
- }, signal);
325
- return {
326
- ...previous,
327
- context: previous?.context ?? canonicalContext,
328
- model: previous?.model ?? this.agent.state.model,
329
- thinkingLevel: previous?.thinkingLevel ?? this.agent.state.thinkingLevel,
425
+ const failed = this._failedResponse;
426
+ this._failedResponse = undefined;
427
+ const prepare = async () => {
428
+ const projection = this.sessionManager.buildSessionProjection();
429
+ const canonicalContext = {
430
+ ...request.context,
431
+ messages: projection.messages,
432
+ // Messages declare the provider-visible loadout; context.tools keeps executable implementations.
433
+ tools: this.agent.state.tools.slice(),
434
+ };
435
+ const previous = await previousPrepareRequest?.({
436
+ ...request,
437
+ context: canonicalContext,
438
+ model: this.agent.state.model,
439
+ thinkingLevel: this.agent.state.thinkingLevel,
440
+ }, signal);
441
+ return { previous, context: previous?.context ?? canonicalContext, projection };
330
442
  };
443
+ let { previous, context, projection } = await prepare();
444
+ const model = previous?.model ?? this.agent.state.model;
445
+ const thinkingLevel = previous?.thinkingLevel ?? this.agent.state.thinkingLevel;
446
+ if (!isVirtualModel(model))
447
+ return { ...previous, context, model, thinkingLevel };
448
+ // The selection stays in agent state; only this request uses the routed model. A routing
449
+ // failure rejects, which ends the run with an error response. Only messages the user wrote
450
+ // start a turn; extension messages can follow them, e.g. from before_agent_start.
451
+ const lastResponse = context.messages.findLastIndex((message) => message.role === "assistant");
452
+ const userTurn = context.messages.slice(lastResponse + 1).some((message) => message.role === "user");
453
+ const state = getVirtualModelState(this.sessionManager.getBranch(), model.provider, model.id);
454
+ const route = await this._modelRuntime.resolveModel(model, convertToLlm(context.messages), {
455
+ reason: failed ? "retry" : userTurn ? "user" : "continuation",
456
+ thinkingLevel,
457
+ signal,
458
+ failed,
459
+ state,
460
+ });
461
+ if (route.state !== undefined && route.state !== state) {
462
+ const data = { provider: model.provider, modelId: model.id, state: route.state };
463
+ const entry = this.sessionManager.getEntry(this.sessionManager.appendCustomEntry(VIRTUAL_MODEL_STATE_ENTRY, data));
464
+ if (entry)
465
+ this._emit({ type: "entry_appended", entry });
466
+ }
467
+ // The route stands: the router already decided this request. The state entry does not change
468
+ // the projection.
469
+ if (this._exceedsCompactionThreshold(route.model, projection)) {
470
+ await this._runAutoCompaction("threshold", false);
471
+ ({ previous, context } = await prepare());
472
+ }
473
+ return { ...previous, context, model: route.model, thinkingLevel: route.thinkingLevel };
331
474
  };
332
475
  }
333
476
  async _dispatchTurnEndBoundary(message, toolResults) {
@@ -383,10 +526,7 @@ export class AgentSession {
383
526
  ? async (_turn, signal) => await this.agent.prepareNextTurn?.(signal)
384
527
  : undefined);
385
528
  this.agent.prepareNextTurnWithContext = async (turn, signal) => {
386
- const context = await this._compactBeforeNextAssistantResponse({
387
- ...turn.context,
388
- messages: this.sessionManager.buildSessionProjection().messages,
389
- });
529
+ const context = await this._compactBeforeNextAssistantResponse(turn.context);
390
530
  const previousSnapshot = await previousPrepareNextTurnWithContext?.({ ...turn, context }, signal);
391
531
  const nextContext = previousSnapshot?.context ?? context;
392
532
  const runOptions = this._runSystemPromptOptions ?? this._baseSystemPromptOptions;
@@ -555,6 +695,21 @@ export class AgentSession {
555
695
  }
556
696
  /** Internal handler for agent events - shared by subscribe and reconnect */
557
697
  _handleAgentEvent = async (event) => {
698
+ // Record the calls a tool made through ctx.executeTool() and their usage on its result message.
699
+ if (this._nestedToolCalls) {
700
+ if (event.type === "message_start" && event.message.role === "toolResult") {
701
+ const message = event.message;
702
+ const summary = this._nestedToolCalls.takeRecord(message.toolCallId);
703
+ if (summary?.calls)
704
+ message.nestedCalls = summary.calls;
705
+ if (summary?.usage) {
706
+ message.usage = message.usage ? combineUsage(message.usage, summary.usage) : summary.usage;
707
+ }
708
+ }
709
+ else if (event.type === "agent_end") {
710
+ this._nestedToolCalls.clear();
711
+ }
712
+ }
558
713
  // When a user message starts, check if it's from either queue and remove it BEFORE emitting
559
714
  // This ensures the UI sees the updated queue state
560
715
  if (event.type === "message_start" && event.message.role === "user") {
@@ -868,6 +1023,14 @@ export class AgentSession {
868
1023
  get thinkingLevel() {
869
1024
  return this.agent.state.thinkingLevel;
870
1025
  }
1026
+ /** Under a virtual selection, the physical model and thinking level of the latest successful response. */
1027
+ get routedModel() {
1028
+ if (!this.model || !isVirtualModel(this.model))
1029
+ return undefined;
1030
+ const latest = findLatestResponse(this.agent.state.messages);
1031
+ const model = latest && this._modelRuntime.getPhysicalModel(latest.provider, latest.model);
1032
+ return model && { model, thinkingLevel: latest?.thinkingLevel };
1033
+ }
871
1034
  /** Whether the session is currently processing an agent run or post-run continuation. */
872
1035
  get isStreaming() {
873
1036
  return this._isAgentRunActive;
@@ -885,12 +1048,16 @@ export class AgentSession {
885
1048
  return this._retryAttempt;
886
1049
  }
887
1050
  /**
888
- * Get the names of currently active tools.
889
- * Returns the names of tools currently set on the agent.
1051
+ * Get the names of currently active tools, which are the tools declared to the model.
1052
+ * Tools with `codemode` or `deferred` exposure are callable from other tools without being active.
890
1053
  */
891
1054
  getActiveToolNames() {
892
1055
  return this.agent.state.tools.map((t) => t.name);
893
1056
  }
1057
+ /** Get the names of the tools that tools can call through `ctx.executeTool()`. */
1058
+ getCallableToolNames() {
1059
+ return this._getCallableTools().map((t) => t.name);
1060
+ }
894
1061
  /**
895
1062
  * Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
896
1063
  */
@@ -900,6 +1067,9 @@ export class AgentSession {
900
1067
  description: definition.description,
901
1068
  parameters: definition.parameters,
902
1069
  promptGuidelines: definition.promptGuidelines,
1070
+ exposure: this._getToolExposure(definition.name),
1071
+ ...(definition.namespace ? { namespace: definition.namespace } : {}),
1072
+ ...(definition.annotations ? { annotations: { ...definition.annotations } } : {}),
903
1073
  sourceInfo,
904
1074
  }));
905
1075
  }
@@ -908,22 +1078,93 @@ export class AgentSession {
908
1078
  }
909
1079
  /**
910
1080
  * Set active tools by name.
911
- * Only tools in the registry can be enabled. Unknown tool names are ignored.
1081
+ * Only tools in the registry can be enabled. Unknown and hidden tool names are ignored.
912
1082
  * Also rebuilds the system prompt to reflect the new tool set.
913
1083
  * Changes take effect on the next agent turn.
914
1084
  */
915
1085
  setActiveToolsByName(toolNames) {
916
- const tools = [];
917
- const validToolNames = [];
918
- for (const name of toolNames) {
1086
+ const previous = this.getActiveToolNames();
1087
+ this._setActiveTools(toolNames);
1088
+ // A loadout that deactivates a tool replaces the restored one, whose pending tools are dropped.
1089
+ // One that only adds tools, like activating tool_search, keeps them.
1090
+ const active = new Set(this.getActiveToolNames());
1091
+ if (previous.some((name) => !active.has(name)))
1092
+ this._pendingToolNames.clear();
1093
+ }
1094
+ _setActiveTools(toolNames) {
1095
+ const tools = this._applyToolLoadout(toolNames);
1096
+ for (const tool of tools)
1097
+ this._pendingToolNames.delete(tool.name);
1098
+ this._rebuildSystemPrompt(tools.map((tool) => tool.name));
1099
+ }
1100
+ _isAllowedTool(name) {
1101
+ return (!this._allowedToolNames || this._allowedToolNames.has(name)) && !this._excludedToolNames?.has(name);
1102
+ }
1103
+ _getToolExposure(name) {
1104
+ return this._toolDefinitions.get(name)?.definition.exposure ?? "direct";
1105
+ }
1106
+ /**
1107
+ * Tools callable through `ctx.executeTool()`: the active `direct` tools and every registered
1108
+ * `codemode` or `deferred` tool.
1109
+ */
1110
+ _getCallableTools(active = new Set(this.getActiveToolNames())) {
1111
+ return [...this._toolRegistry.values()].filter((tool) => {
1112
+ const exposure = this._getToolExposure(tool.name);
1113
+ return exposure === "codemode" || exposure === "deferred" || (exposure === "direct" && active.has(tool.name));
1114
+ });
1115
+ }
1116
+ /**
1117
+ * Set the agent's tools for the given active tool names and return them. The active tools are
1118
+ * the registered, non-hidden ones; they are declared to the model. Active tools with a
1119
+ * `prepareLoadout` hook can change the declared descriptions and hide declarations from
1120
+ * requests (see {@link _installHiddenDeclarationsProjection}).
1121
+ */
1122
+ _applyToolLoadout(toolNames) {
1123
+ const tools = [...new Set(toolNames)].flatMap((name) => {
919
1124
  const tool = this._toolRegistry.get(name);
920
- if (tool) {
921
- tools.push(tool);
922
- validToolNames.push(name);
1125
+ return tool && this._getToolExposure(name) !== "hidden" ? [tool] : [];
1126
+ });
1127
+ const hooks = tools.flatMap((tool) => {
1128
+ const entry = this._toolDefinitions.get(tool.name);
1129
+ return entry?.definition.prepareLoadout ? [entry] : [];
1130
+ });
1131
+ const hidden = new Set();
1132
+ let declared = tools;
1133
+ if (hooks.length > 0) {
1134
+ const loadout = {
1135
+ declared: tools,
1136
+ callable: this._getCallableTools(new Set(tools.map((tool) => tool.name))),
1137
+ registered: [...this._toolRegistry.values()],
1138
+ getExposure: (name) => this._getToolExposure(name),
1139
+ getNamespace: (name) => this._toolDefinitions.get(name)?.definition.namespace,
1140
+ };
1141
+ const descriptions = new Map();
1142
+ for (const { definition, sourceInfo } of hooks) {
1143
+ try {
1144
+ const changes = definition.prepareLoadout?.(loadout);
1145
+ for (const [name, description] of Object.entries(changes?.descriptions ?? {})) {
1146
+ descriptions.set(name, description);
1147
+ }
1148
+ for (const name of changes?.hiddenDeclarations ?? [])
1149
+ hidden.add(name);
1150
+ }
1151
+ catch (error) {
1152
+ this._extensionRunner.emitError({
1153
+ extensionPath: sourceInfo.path,
1154
+ event: "prepare_loadout",
1155
+ error: error instanceof Error ? error.message : String(error),
1156
+ stack: error instanceof Error ? error.stack : undefined,
1157
+ });
1158
+ }
923
1159
  }
1160
+ declared = tools.map((tool) => {
1161
+ const description = descriptions.get(tool.name);
1162
+ return description === undefined ? tool : { ...tool, description };
1163
+ });
924
1164
  }
925
- this.agent.state.tools = tools;
926
- this._rebuildSystemPrompt(validToolNames);
1165
+ this._hiddenDeclarations = hidden;
1166
+ this.agent.state.tools = declared;
1167
+ return declared;
927
1168
  }
928
1169
  /** Whether compaction or branch summarization is currently running */
929
1170
  get isCompacting() {
@@ -994,7 +1235,8 @@ export class AgentSession {
994
1235
  const toolSnippets = {};
995
1236
  for (const name of this._toolRegistry.keys()) {
996
1237
  const snippet = this._toolPromptSnippets.get(name);
997
- if (snippet)
1238
+ // Tools without a snippet are not listed. Hidden tools are only callable through another tool.
1239
+ if (snippet && !this._hiddenDeclarations.has(name))
998
1240
  toolSnippets[name] = snippet;
999
1241
  }
1000
1242
  const loaderSystemPrompt = this._resourceLoader.getSystemPrompt();
@@ -1024,11 +1266,9 @@ export class AgentSession {
1024
1266
  * {@link _installAgentForcedPromptProjection}.
1025
1267
  */
1026
1268
  _preparePromptAndToolLoadout(options, messages = this.agent.state.messages) {
1027
- options.selectedTools = [...new Set(options.selectedTools)].filter((name) => this._toolRegistry.has(name));
1028
- this.agent.state.tools = options.selectedTools.flatMap((name) => {
1029
- const tool = this._toolRegistry.get(name);
1030
- return tool ? [tool] : [];
1031
- });
1269
+ options.selectedTools = this._applyToolLoadout(options.selectedTools).map((tool) => tool.name);
1270
+ // The tool list must match the declarations the request carries, so hidden tools are not listed.
1271
+ options.toolSnippets = Object.fromEntries(Object.entries(options.toolSnippets).filter(([name]) => !this._hiddenDeclarations.has(name)));
1032
1272
  const sections = diffSystemPromptSections(getCurrentSystemMessage(messages)?.sections ?? {}, buildSystemPromptSections(options));
1033
1273
  return sections ? { role: "system", content: "", sections, timestamp: Date.now() } : undefined;
1034
1274
  }
@@ -1042,6 +1282,32 @@ export class AgentSession {
1042
1282
  * collapse into one head holding the forced text and the current tools. Runs after the
1043
1283
  * `context` extension handlers.
1044
1284
  */
1285
+ /**
1286
+ * Remove the declarations that `prepareLoadout` hooks hide from every request. The whole
1287
+ * transcript is filtered with the current set, so the projected declarations stay consistent
1288
+ * across requests and only change when the loadout does.
1289
+ */
1290
+ _installHiddenDeclarationsProjection() {
1291
+ const previousTransformContext = this.agent.transformContext;
1292
+ this.agent.transformContext = async (messages, signal) => {
1293
+ const transformed = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
1294
+ const hidden = this._hiddenDeclarations;
1295
+ if (hidden.size === 0)
1296
+ return transformed;
1297
+ return transformed.map((message) => {
1298
+ if (message.role !== "system" || (!message.toolsAdded && !message.toolsRemoved))
1299
+ return message;
1300
+ const { toolsAdded, toolsRemoved, ...rest } = message;
1301
+ const added = toolsAdded?.filter((tool) => !hidden.has(tool.name)) ?? [];
1302
+ const removed = toolsRemoved?.filter((tool) => !hidden.has(tool.name)) ?? [];
1303
+ return {
1304
+ ...rest,
1305
+ ...(added.length > 0 ? { toolsAdded: added } : {}),
1306
+ ...(removed.length > 0 ? { toolsRemoved: removed } : {}),
1307
+ };
1308
+ });
1309
+ };
1310
+ }
1045
1311
  _installAgentForcedPromptProjection() {
1046
1312
  const previousTransformContext = this.agent.transformContext;
1047
1313
  this.agent.transformContext = async (messages, signal) => {
@@ -1059,25 +1325,31 @@ export class AgentSession {
1059
1325
  return [head, ...transformed.filter((message) => message.role !== "system")];
1060
1326
  };
1061
1327
  }
1062
- /** Restore the active tool loadout declared by the session transcript, if it declares one. */
1328
+ /**
1329
+ * Restore the active tool loadout declared by the session transcript, if it declares one.
1330
+ * Tools reachable only from other tools are never declared, but they do not depend on the active
1331
+ * set, so the transcript's declarations are the whole loadout.
1332
+ */
1063
1333
  _restoreToolsFromTranscript() {
1334
+ this._pendingToolNames.clear();
1064
1335
  const current = getCurrentSystemMessage(this.sessionManager.buildSessionContext().messages);
1065
1336
  if (!current)
1066
1337
  return;
1067
- const toolNames = (current.toolsAdded ?? [])
1068
- .map((tool) => tool.name)
1069
- .filter((name) => this._toolRegistry.has(name));
1070
- this.agent.state.tools = toolNames.flatMap((name) => {
1071
- const registered = this._toolRegistry.get(name);
1072
- return registered ? [registered] : [];
1073
- });
1074
- this._rebuildSystemPrompt(toolNames);
1338
+ const names = (current.toolsAdded ?? []).map((tool) => tool.name);
1339
+ this._pendingToolNames = new Set(names.filter((name) => this._isAllowedTool(name)));
1340
+ this._setActiveTools(names);
1075
1341
  }
1076
1342
  // =========================================================================
1077
1343
  // Prompting
1078
1344
  // =========================================================================
1079
1345
  async _runAgentPrompt(messages) {
1080
1346
  this._agentRunAbortRequested = false;
1347
+ // Compaction before the prompt may have scheduled a retry; the new prompt replaces it.
1348
+ this._failedResponse = undefined;
1349
+ this._recordSelection();
1350
+ // The run records the loadout in the transcript; restored tools that did not register by now
1351
+ // are dropped, so a tool that never registers does not stay pending.
1352
+ this._pendingToolNames.clear();
1081
1353
  this._isAgentRunActive = true;
1082
1354
  try {
1083
1355
  await this.agent.prompt(messages);
@@ -1098,6 +1370,7 @@ export class AgentSession {
1098
1370
  finally {
1099
1371
  if (this._agentRunAbortRequested)
1100
1372
  this._finishCancelledRetry();
1373
+ this._failedResponse = undefined;
1101
1374
  this._runSystemPromptOptions = undefined;
1102
1375
  this._flushPendingBashMessages();
1103
1376
  this._flushPendingCustomMessages();
@@ -1118,6 +1391,7 @@ export class AgentSession {
1118
1391
  if (this._isRetryableError(message) && (await this._prepareRetry(message))) {
1119
1392
  if (this._agentRunAbortRequested)
1120
1393
  this._finishCancelledRetry();
1394
+ this._failedResponse = message;
1121
1395
  return !this._agentRunAbortRequested;
1122
1396
  }
1123
1397
  if (this._agentRunAbortRequested) {
@@ -1185,7 +1459,7 @@ export class AgentSession {
1185
1459
  for (const image of images) {
1186
1460
  const processed = await processImage(Buffer.from(image.data, "base64"), image.mimeType, {
1187
1461
  autoResizeImages: this.settingsManager.getImageAutoResize(),
1188
- resizeOptions: this.model?.inputLimits?.images?.resize,
1462
+ resizeOptions: this._limitsModel()?.inputLimits?.images?.resize,
1189
1463
  });
1190
1464
  if (!processed.ok) {
1191
1465
  hints.push(processed.message);
@@ -1212,124 +1486,114 @@ export class AgentSession {
1212
1486
  }
1213
1487
  const expandPromptTemplates = options?.expandPromptTemplates ?? true;
1214
1488
  const preflightResult = options?.preflightResult;
1215
- let messages;
1216
- try {
1217
- // Handle extension commands first (execute immediately, even during streaming)
1218
- // Extension commands manage their own LLM interaction via pi.sendMessage()
1219
- if (expandPromptTemplates && text.startsWith("/")) {
1220
- const handled = await this._tryExecuteExtensionCommand(text);
1221
- if (handled) {
1222
- // Extension command executed, no prompt to send
1223
- preflightResult?.(true);
1224
- return;
1225
- }
1226
- }
1227
- if (this._compactionAbortController !== undefined) {
1228
- throw new Error("Cannot submit a prompt while compaction is in progress. Wait for compaction to finish and retry.");
1229
- }
1230
- // Emit input event for extension interception (before skill/template expansion)
1231
- const processedInput = await this._runInputHandlers(text, options?.images, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
1232
- if (!processedInput) {
1233
- preflightResult?.(true);
1489
+ // Handle extension commands first (execute immediately, even during streaming)
1490
+ // Extension commands manage their own LLM interaction via pi.sendMessage()
1491
+ if (expandPromptTemplates && text.startsWith("/")) {
1492
+ const handled = await this._tryExecuteExtensionCommand(text);
1493
+ if (handled) {
1494
+ // Extension command executed, no prompt to send
1495
+ preflightResult?.("handled");
1234
1496
  return;
1235
1497
  }
1236
- const { text: currentText, images: currentImages } = processedInput;
1237
- // Expand skill commands (/skill:name args) and prompt templates (/template args)
1238
- let expandedText = currentText;
1239
- if (expandPromptTemplates) {
1240
- expandedText = this._expandSkillCommand(expandedText);
1241
- expandedText = this._expandBareNamespaceSkillCommand(expandedText);
1242
- expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
1243
- }
1244
- // If streaming, queue via steer() or followUp() based on option
1245
- if (this.isStreaming) {
1246
- if (!options?.streamingBehavior) {
1247
- throw new Error("Agent is already processing. Specify streamingBehavior ('steer' or 'followUp') to queue the message.");
1248
- }
1249
- if (options.streamingBehavior === "followUp") {
1250
- await this._queueFollowUp(expandedText, currentImages);
1251
- }
1252
- else {
1253
- await this._queueSteer(expandedText, currentImages);
1254
- }
1255
- preflightResult?.(true);
1256
- return;
1498
+ }
1499
+ if (this._compactionAbortController !== undefined) {
1500
+ throw new Error("Cannot submit a prompt while compaction is in progress. Wait for compaction to finish and retry.");
1501
+ }
1502
+ // Emit input event for extension interception (before skill/template expansion)
1503
+ const processedInput = await this._runInputHandlers(text, options?.images, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
1504
+ if (!processedInput) {
1505
+ preflightResult?.("handled");
1506
+ return;
1507
+ }
1508
+ const { text: currentText, images: currentImages } = processedInput;
1509
+ // Expand skill commands (/skill:name args) and prompt templates (/template args)
1510
+ let expandedText = currentText;
1511
+ if (expandPromptTemplates) {
1512
+ expandedText = this._expandSkillCommand(expandedText);
1513
+ expandedText = this._expandBareNamespaceSkillCommand(expandedText);
1514
+ expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
1515
+ }
1516
+ // If streaming, queue via steer() or followUp() based on option
1517
+ if (this.isStreaming) {
1518
+ if (!options?.streamingBehavior) {
1519
+ throw new Error("Agent is already processing. Specify streamingBehavior ('steer' or 'followUp') to queue the message.");
1257
1520
  }
1258
- // Flush any pending bash and custom messages before the new prompt
1259
- this._flushPendingBashMessages();
1260
- this._flushPendingCustomMessages();
1261
- // Validate model
1262
- if (!this.model) {
1263
- throw new Error(formatNoModelSelectedMessage());
1521
+ if (options.streamingBehavior === "followUp") {
1522
+ await this._queueFollowUp(expandedText, currentImages);
1264
1523
  }
1265
- const hasConfiguredAuth = this._modelRuntime.hasConfiguredAuth(this.model.provider) ||
1266
- (await this._modelRuntime.checkAuth(this.model.provider)) !== undefined;
1267
- if (!hasConfiguredAuth) {
1268
- const isOAuth = this._modelRuntime.isUsingOAuth(this.model.provider);
1269
- if (isOAuth) {
1270
- throw new Error(`Authentication failed for "${this.model.provider}". ` +
1271
- `Credentials may have expired or network is unavailable. ` +
1272
- `Run '/login ${this.model.provider}' to re-authenticate.`);
1273
- }
1274
- throw new Error(formatNoApiKeyFoundMessage(this.model.provider));
1275
- }
1276
- // Check if we need to compact before sending (catches aborted responses).
1277
- // The user's new prompt is sent below, so do not call agent.continue() here.
1278
- const lastAssistant = this._findLastAssistantMessage();
1279
- if (lastAssistant) {
1280
- await this._checkCompaction(lastAssistant, false);
1281
- }
1282
- // Emit before_agent_start before normalizing images so extension-driven model
1283
- // selection determines the resize profile used for the request and history.
1284
- const selectedToolsBefore = this._baseSystemPromptOptions.selectedTools;
1285
- const result = await this._extensionRunner.emitBeforeAgentStart(expandedText, currentImages, this._baseSystemPromptOptions);
1286
- // Handlers may edit event.systemPromptOptions.selectedTools or call setActiveTools(),
1287
- // which updates the live loadout instead. An explicit edit wins; otherwise the live
1288
- // loadout is authoritative, so a setActiveTools() call is not undone here.
1289
- const handlerEditedTools = result.systemPromptOptions.selectedTools.length !== selectedToolsBefore.length ||
1290
- result.systemPromptOptions.selectedTools.some((name, index) => name !== selectedToolsBefore[index]);
1291
- if (!handlerEditedTools)
1292
- result.systemPromptOptions.selectedTools = this.getActiveToolNames();
1293
- const normalized = await this._normalizePromptImages(currentImages);
1294
- const userText = normalized.hints.length > 0 ? `${expandedText}\n\n${normalized.hints.join("\n")}` : expandedText;
1295
- // Build messages only after hooks and image normalization have completed.
1296
- messages = [];
1297
- const userContent = [{ type: "text", text: userText }];
1298
- userContent.push(...normalized.images);
1299
- messages.push({
1300
- role: "user",
1301
- content: userContent,
1302
- timestamp: Date.now(),
1303
- });
1304
- // Inject any pending "nextTurn" messages as context alongside the user message
1305
- for (const msg of this._pendingNextTurnMessages) {
1306
- messages.push(msg);
1307
- }
1308
- this._pendingNextTurnMessages = [];
1309
- for (const msg of result.messages) {
1310
- messages.push({
1311
- role: "custom",
1312
- customType: msg.customType,
1313
- // Untyped extensions can pass null/missing content; normalize at ingestion.
1314
- content: msg.content ?? [],
1315
- display: msg.display,
1316
- details: msg.details,
1317
- timestamp: Date.now(),
1318
- });
1524
+ else {
1525
+ await this._queueSteer(expandedText, currentImages);
1319
1526
  }
1320
- const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
1321
- this._runSystemPromptOptions = result.systemPromptOptions;
1322
- if (updateMessage)
1323
- messages.unshift(updateMessage);
1527
+ preflightResult?.("queued");
1528
+ return;
1324
1529
  }
1325
- catch (error) {
1326
- preflightResult?.(false);
1327
- throw error;
1530
+ // Flush any pending bash and custom messages before the new prompt
1531
+ this._flushPendingBashMessages();
1532
+ this._flushPendingCustomMessages();
1533
+ // Validate model
1534
+ if (!this.model) {
1535
+ throw new Error(formatNoModelSelectedMessage());
1536
+ }
1537
+ const hasConfiguredAuth = this._modelRuntime.hasConfiguredAuth(this.model.provider) ||
1538
+ (await this._modelRuntime.checkAuth(this.model.provider)) !== undefined;
1539
+ if (!hasConfiguredAuth) {
1540
+ const isOAuth = this._modelRuntime.isUsingOAuth(this.model.provider);
1541
+ if (isOAuth) {
1542
+ throw new Error(`Authentication failed for "${this.model.provider}". ` +
1543
+ `Credentials may have expired or network is unavailable. ` +
1544
+ `Run '/login ${this.model.provider}' to re-authenticate.`);
1545
+ }
1546
+ throw new Error(formatNoApiKeyFoundMessage(this.model.provider));
1547
+ }
1548
+ // Check if we need to compact before sending (catches aborted responses).
1549
+ // The user's new prompt is sent below, so do not call agent.continue() here.
1550
+ const lastAssistant = this._findLastAssistantMessage();
1551
+ if (lastAssistant) {
1552
+ await this._checkCompaction(lastAssistant, false);
1553
+ }
1554
+ // Emit before_agent_start before normalizing images so extension-driven model
1555
+ // selection determines the resize profile used for the request and history.
1556
+ const selectedToolsBefore = this._baseSystemPromptOptions.selectedTools;
1557
+ const result = await this._extensionRunner.emitBeforeAgentStart(expandedText, currentImages, this._baseSystemPromptOptions);
1558
+ // Handlers may edit event.systemPromptOptions.selectedTools or call setActiveTools(),
1559
+ // which updates the live loadout instead. An explicit edit wins; otherwise the live
1560
+ // loadout is authoritative, so a setActiveTools() call is not undone here.
1561
+ const handlerEditedTools = result.systemPromptOptions.selectedTools.length !== selectedToolsBefore.length ||
1562
+ result.systemPromptOptions.selectedTools.some((name, index) => name !== selectedToolsBefore[index]);
1563
+ if (!handlerEditedTools)
1564
+ result.systemPromptOptions.selectedTools = this.getActiveToolNames();
1565
+ const normalized = await this._normalizePromptImages(currentImages);
1566
+ const userText = normalized.hints.length > 0 ? `${expandedText}\n\n${normalized.hints.join("\n")}` : expandedText;
1567
+ // Build messages only after hooks and image normalization have completed.
1568
+ const messages = [];
1569
+ const userContent = [{ type: "text", text: userText }];
1570
+ userContent.push(...normalized.images);
1571
+ messages.push({
1572
+ role: "user",
1573
+ content: userContent,
1574
+ timestamp: Date.now(),
1575
+ });
1576
+ // Inject any pending "nextTurn" messages as context alongside the user message
1577
+ for (const msg of this._pendingNextTurnMessages) {
1578
+ messages.push(msg);
1328
1579
  }
1329
- if (!messages) {
1330
- return;
1580
+ this._pendingNextTurnMessages = [];
1581
+ for (const msg of result.messages) {
1582
+ messages.push({
1583
+ role: "custom",
1584
+ customType: msg.customType,
1585
+ // Untyped extensions can pass null/missing content; normalize at ingestion.
1586
+ content: msg.content ?? [],
1587
+ display: msg.display,
1588
+ details: msg.details,
1589
+ timestamp: Date.now(),
1590
+ });
1331
1591
  }
1332
- preflightResult?.(true);
1592
+ const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
1593
+ this._runSystemPromptOptions = result.systemPromptOptions;
1594
+ if (updateMessage)
1595
+ messages.unshift(updateMessage);
1596
+ preflightResult?.("started");
1333
1597
  await this._runAgentPrompt(messages);
1334
1598
  }
1335
1599
  /**
@@ -1415,7 +1679,7 @@ export class AgentSession {
1415
1679
  }
1416
1680
  const processedInput = await this._runInputHandlers(text, images, source, this.isStreaming ? behavior : undefined);
1417
1681
  if (!processedInput)
1418
- return;
1682
+ return "handled";
1419
1683
  let expandedText = this._expandSkillCommand(processedInput.text);
1420
1684
  expandedText = this._expandBareNamespaceSkillCommand(expandedText);
1421
1685
  expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
@@ -1425,6 +1689,7 @@ export class AgentSession {
1425
1689
  else {
1426
1690
  await this._queueFollowUp(expandedText, processedInput.images);
1427
1691
  }
1692
+ return "queued";
1428
1693
  }
1429
1694
  /**
1430
1695
  * Queue a steering message while the agent is running.
@@ -1436,7 +1701,7 @@ export class AgentSession {
1436
1701
  * @throws Error if text is an extension command
1437
1702
  */
1438
1703
  async steer(text, images, options) {
1439
- await this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
1704
+ return this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
1440
1705
  }
1441
1706
  /**
1442
1707
  * Queue a follow-up message to be processed after the agent finishes.
@@ -1447,7 +1712,7 @@ export class AgentSession {
1447
1712
  * @throws Error if text is an extension command
1448
1713
  */
1449
1714
  async followUp(text, images, options) {
1450
- await this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
1715
+ return this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
1451
1716
  }
1452
1717
  /**
1453
1718
  * Internal: Queue a steering message (already expanded, no extension command check).
@@ -1863,8 +2128,10 @@ export class AgentSession {
1863
2128
  // Compaction
1864
2129
  // =========================================================================
1865
2130
  /** Generate Pi's built-in compaction summary for manual and automatic compaction. */
1866
- async _runDefaultCompaction(preparation, requestModel, apiKey, headers, customInstructions, signal, env, reason) {
1867
- return compact(preparation, requestModel, apiKey, headers, customInstructions, signal, this.thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }), undefined);
2131
+ async _runDefaultCompaction(preparation, model, customInstructions, signal, reason) {
2132
+ // Resolve the request only when Pi summarizes itself: routing may call models or fail.
2133
+ const request = await this._getSummarizationRequestAuth(model, signal);
2134
+ return compact(preparation, request.model, request.apiKey, request.headers, customInstructions, signal, request.thinkingLevel, this.agent.streamFunction, request.env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }), undefined);
1868
2135
  }
1869
2136
  _clearManualCompactionState() {
1870
2137
  this._compactionAbortController = undefined;
@@ -1897,7 +2164,6 @@ export class AgentSession {
1897
2164
  throw new Error(formatNoModelSelectedMessage());
1898
2165
  }
1899
2166
  const settings = this.settingsManager.getCompactionSettings(model);
1900
- const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
1901
2167
  const pathEntries = this.sessionManager.getBranch();
1902
2168
  const preparation = prepareCompaction(pathEntries, settings);
1903
2169
  if (!preparation) {
@@ -1943,7 +2209,7 @@ export class AgentSession {
1943
2209
  }
1944
2210
  else {
1945
2211
  // Shared default summary generator, also used by automatic compaction.
1946
- const result = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, customInstructions, this._compactionAbortController.signal, env, "manual");
2212
+ const result = await this._runDefaultCompaction(preparation, model, customInstructions, this._compactionAbortController.signal, "manual");
1947
2213
  summary = result.summary;
1948
2214
  firstKeptEntryId = result.firstKeptEntryId;
1949
2215
  tokensBefore = result.tokensBefore;
@@ -2054,12 +2320,14 @@ export class AgentSession {
2054
2320
  // Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
2055
2321
  if (skipAbortedCheck && assistantMessage.stopReason === "aborted")
2056
2322
  return false;
2057
- const contextWindow = this.model?.contextWindow ?? 0;
2058
2323
  // Skip overflow check if the message came from a different model.
2059
2324
  // This handles the case where user switched from a smaller-context model (e.g. opus)
2060
2325
  // to a larger-context model (e.g. codex) - the overflow error from the old model
2061
- // shouldn't trigger compaction for the new model.
2062
- const sameModel = this.model && assistantMessage.provider === this.model.provider && assistantMessage.model === this.model.id;
2326
+ // shouldn't trigger compaction for the new model. Under a virtual selection, the
2327
+ // physical model that produced the message supplies the limits.
2328
+ const messageModel = this._modelForMessage(assistantMessage);
2329
+ const sameModel = messageModel !== undefined;
2330
+ const contextWindow = (messageModel ?? this.model)?.contextWindow ?? 0;
2063
2331
  // Skip compaction checks if this assistant message is older than the latest
2064
2332
  // compaction boundary. This prevents a stale pre-compaction usage/error
2065
2333
  // from retriggering compaction on the first prompt after compaction.
@@ -2091,7 +2359,7 @@ export class AgentSession {
2091
2359
  const contextOverflow = sameModel &&
2092
2360
  ((explicitOverflow && assistantRetainedForExplicitRecovery) ||
2093
2361
  (assistantUsageMatchesProjection && isContextOverflow(assistantMessage, contextWindow)));
2094
- const recoverableLength = sameModel && assistantIsProjected && isRecoverableLength(assistantMessage, this.model?.maxTokens ?? 0);
2362
+ const recoverableLength = sameModel && assistantIsProjected && isRecoverableLength(assistantMessage, messageModel.maxTokens);
2095
2363
  if (contextOverflow || recoverableLength) {
2096
2364
  const willRetry = assistantMessage.stopReason !== "stop";
2097
2365
  // Case 2: the response completed successfully. Compact, but do not retry because
@@ -2123,7 +2391,10 @@ export class AgentSession {
2123
2391
  // Persistently omit the selected final attempt before post-run recovery compaction.
2124
2392
  this._overflowRecoveryAttempted = true;
2125
2393
  this._omitRecoveryAttempt(assistantMessage, toolResults);
2126
- return await this._runAutoCompaction("overflow", willRetry);
2394
+ const retry = await this._runAutoCompaction("overflow", willRetry);
2395
+ if (retry)
2396
+ this._failedResponse = assistantMessage;
2397
+ return retry;
2127
2398
  }
2128
2399
  // Case 3: threshold compaction without retry.
2129
2400
  // For error messages or all-zero usage messages, estimate from the last valid response.
@@ -2193,8 +2464,6 @@ export class AgentSession {
2193
2464
  started = true;
2194
2465
  this._emit({ type: "compaction_start", reason });
2195
2466
  abortController.signal.throwIfAborted();
2196
- const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, abortController.signal);
2197
- abortController.signal.throwIfAborted();
2198
2467
  let extensionCompaction;
2199
2468
  if (this._extensionRunner.hasHandlers("session_before_compact")) {
2200
2469
  const extensionResult = (await this._extensionRunner.emit({
@@ -2231,7 +2500,7 @@ export class AgentSession {
2231
2500
  }
2232
2501
  else {
2233
2502
  // Shared default summary generator, also used by manual compaction.
2234
- const compactResult = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, undefined, abortController.signal, env, reason);
2503
+ const compactResult = await this._runDefaultCompaction(preparation, model, undefined, abortController.signal, reason);
2235
2504
  summary = compactResult.summary;
2236
2505
  firstKeptEntryId = compactResult.firstKeptEntryId;
2237
2506
  tokensBefore = compactResult.tokensBefore;
@@ -2334,6 +2603,7 @@ export class AgentSession {
2334
2603
  }
2335
2604
  this._applyExtensionBindings(this._extensionRunner);
2336
2605
  await this._extensionRunner.emit(this._sessionStartEvent);
2606
+ this._extensionRunner.reportUnhandledMcpServers();
2337
2607
  await this.extendResourcesFromExtensions(this._sessionStartEvent.reason === "reload" ? "reload" : "startup");
2338
2608
  }
2339
2609
  async extendResourcesFromExtensions(reason) {
@@ -2355,7 +2625,7 @@ export class AgentSession {
2355
2625
  buildExtensionResourcePaths(entries) {
2356
2626
  return entries.map((entry) => {
2357
2627
  const source = this.getExtensionSourceLabel(entry.extensionPath);
2358
- const baseDir = entry.extensionPath.startsWith("<") ? undefined : dirname(entry.extensionPath);
2628
+ const baseDir = isSyntheticPath(entry.extensionPath) ? undefined : dirname(entry.extensionPath);
2359
2629
  return {
2360
2630
  path: entry.path,
2361
2631
  metadata: {
@@ -2368,7 +2638,7 @@ export class AgentSession {
2368
2638
  });
2369
2639
  }
2370
2640
  getExtensionSourceLabel(extensionPath) {
2371
- if (extensionPath.startsWith("<")) {
2641
+ if (isSyntheticPath(extensionPath)) {
2372
2642
  return `extension:${extensionPath.replace(/[<>]/g, "")}`;
2373
2643
  }
2374
2644
  const base = basename(extensionPath);
@@ -2453,6 +2723,7 @@ export class AgentSession {
2453
2723
  },
2454
2724
  getActiveTools: () => this.getActiveToolNames(),
2455
2725
  getAllTools: () => this.getAllTools(),
2726
+ getSettings: () => this.settingsManager.getSettings(),
2456
2727
  setActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),
2457
2728
  refreshTools: () => this._refreshToolRegistry(),
2458
2729
  getCommands,
@@ -2496,6 +2767,8 @@ export class AgentSession {
2496
2767
  },
2497
2768
  getSystemPrompt: () => this.systemPrompt,
2498
2769
  getSystemPromptOptions: () => this._baseSystemPromptOptions,
2770
+ executeTool: (callerId, name, args, options) => this._executeNestedToolCall(callerId, name, args, options),
2771
+ getCallableTools: () => this._getCallableTools(),
2499
2772
  }, {
2500
2773
  registerProvider: (name, config) => {
2501
2774
  this._modelRuntime.registerProvider(name, config);
@@ -2509,14 +2782,22 @@ export class AgentSession {
2509
2782
  this._modelRuntime.unregisterProvider(name);
2510
2783
  this._refreshCurrentModelFromRegistry();
2511
2784
  },
2785
+ registerVirtualModel: (definition) => {
2786
+ this._modelRuntime.registerVirtualModel(definition);
2787
+ this._refreshCurrentModelFromRegistry();
2788
+ },
2789
+ unregisterVirtualModel: (provider, id) => {
2790
+ this._modelRuntime.unregisterVirtualModel(provider, id);
2791
+ this._refreshCurrentModelFromRegistry();
2792
+ },
2512
2793
  });
2513
2794
  }
2514
2795
  _refreshToolRegistry(options) {
2515
- const previousRegistryNames = new Set(this._toolRegistry.keys());
2796
+ // Tools that were already activated on registration. A tool whose exposure changes to
2797
+ // `direct` or `model-only` (for example from `hidden`) is activated like a new tool.
2798
+ const previousActivatedOnRegistration = new Set([...this._toolRegistry.keys()].filter((name) => this._isActivatedOnRegistration(name)));
2516
2799
  const previousActiveToolNames = this.getActiveToolNames();
2517
2800
  const allowedToolNames = this._allowedToolNames;
2518
- const excludedToolNames = this._excludedToolNames;
2519
- const isAllowedTool = (name) => (!allowedToolNames || allowedToolNames.has(name)) && !excludedToolNames?.has(name);
2520
2801
  const registeredTools = this._extensionRunner.getAllRegisteredTools();
2521
2802
  const allCustomTools = [
2522
2803
  ...registeredTools,
@@ -2524,14 +2805,14 @@ export class AgentSession {
2524
2805
  definition,
2525
2806
  sourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, { source: "sdk" }),
2526
2807
  })),
2527
- ].filter((tool) => isAllowedTool(tool.definition.name));
2808
+ ].filter((tool) => this._isAllowedTool(tool.definition.name));
2528
2809
  const definitionRegistry = new Map(Array.from(this._baseToolDefinitions.entries())
2529
- .filter(([name]) => isAllowedTool(name))
2810
+ .filter(([name]) => this._isAllowedTool(name))
2530
2811
  .map(([name, definition]) => [
2531
2812
  name,
2532
2813
  {
2533
2814
  definition,
2534
- sourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, { source: "builtin" }),
2815
+ sourceInfo: createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${name}`, { source: "builtin" }),
2535
2816
  },
2536
2817
  ]));
2537
2818
  for (const tool of allCustomTools) {
@@ -2556,37 +2837,52 @@ export class AgentSession {
2556
2837
  const runner = this._extensionRunner;
2557
2838
  const wrappedExtensionTools = wrapRegisteredTools(allCustomTools, runner);
2558
2839
  const wrappedBuiltInTools = wrapRegisteredTools(Array.from(this._baseToolDefinitions.values())
2559
- .filter((definition) => isAllowedTool(definition.name))
2840
+ .filter((definition) => this._isAllowedTool(definition.name))
2560
2841
  .map((definition) => ({
2561
2842
  definition,
2562
- sourceInfo: createSyntheticSourceInfo(`<builtin:${definition.name}>`, { source: "builtin" }),
2843
+ sourceInfo: createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${definition.name}`, {
2844
+ source: "builtin",
2845
+ }),
2563
2846
  })), runner);
2564
2847
  const toolRegistry = new Map(wrappedBuiltInTools.map((tool) => [tool.name, tool]));
2565
2848
  for (const tool of wrappedExtensionTools) {
2566
2849
  toolRegistry.set(tool.name, tool);
2567
2850
  }
2568
2851
  this._toolRegistry = toolRegistry;
2569
- const nextActiveToolNames = (options?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]).filter((name) => isAllowedTool(name));
2852
+ const nextActiveToolNames = (options?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]).filter((name) => this._isAllowedTool(name));
2570
2853
  if (allowedToolNames) {
2571
2854
  for (const toolName of this._toolRegistry.keys()) {
2572
- if (allowedToolNames.has(toolName)) {
2855
+ // Naming a tool activates it even when it is not active by default.
2856
+ if (allowedToolNames.has(toolName) && this._isDeclarable(toolName)) {
2573
2857
  nextActiveToolNames.push(toolName);
2574
2858
  }
2575
2859
  }
2576
2860
  }
2577
2861
  else if (options?.includeAllExtensionTools) {
2578
2862
  for (const tool of wrappedExtensionTools) {
2579
- nextActiveToolNames.push(tool.name);
2863
+ if (this._isActivatedOnRegistration(tool.name))
2864
+ nextActiveToolNames.push(tool.name);
2580
2865
  }
2581
2866
  }
2582
2867
  else if (!options?.activeToolNames) {
2583
2868
  for (const toolName of this._toolRegistry.keys()) {
2584
- if (!previousRegistryNames.has(toolName)) {
2869
+ if (!previousActivatedOnRegistration.has(toolName) && this._isActivatedOnRegistration(toolName)) {
2585
2870
  nextActiveToolNames.push(toolName);
2586
2871
  }
2587
2872
  }
2588
2873
  }
2589
- this.setActiveToolsByName([...new Set(nextActiveToolNames)]);
2874
+ // Pending tools that are registered now become active.
2875
+ nextActiveToolNames.push(...this._pendingToolNames);
2876
+ this._setActiveTools([...new Set(nextActiveToolNames)]);
2877
+ }
2878
+ /** Whether activating the tool declares it to the model. */
2879
+ _isDeclarable(name) {
2880
+ const exposure = this._getToolExposure(name);
2881
+ return exposure === "direct" || exposure === "model-only";
2882
+ }
2883
+ /** Whether registering the tool activates it, which declares it to the model. */
2884
+ _isActivatedOnRegistration(name) {
2885
+ return this._isDeclarable(name) && this._toolDefinitions.get(name)?.definition.defaultActive !== false;
2590
2886
  }
2591
2887
  _buildRuntime(options) {
2592
2888
  const autoResizeImages = this.settingsManager.getImageAutoResize();
@@ -2628,12 +2924,21 @@ export class AgentSession {
2628
2924
  const previousFlagValues = oldRunner.getFlagValues();
2629
2925
  await emitSessionShutdownEvent(oldRunner, { type: "session_shutdown", reason: "reload" });
2630
2926
  oldRunner.invalidate();
2927
+ const previousDefaultTools = new Set(this._usesDefaultTools ? (this.settingsManager.getDefaultTools() ?? DEFAULT_TOOL_NAMES) : []);
2631
2928
  await this.settingsManager.reload();
2632
2929
  this.syncQueueModesFromSettings();
2633
2930
  resetApiProviders();
2634
2931
  await this._resourceLoader.reload();
2932
+ // Activate tools newly added to defaultTools. Removed ones stay active, and tools disabled
2933
+ // during the session stay disabled unless the setting newly adds them.
2934
+ const addedDefaultTools = this._usesDefaultTools
2935
+ ? (this.settingsManager.getDefaultTools() ?? DEFAULT_TOOL_NAMES).filter((name) => !previousDefaultTools.has(name))
2936
+ : [];
2937
+ // Tools the new extensions register later, such as MCP tools, are pending until then.
2938
+ for (const name of this.getActiveToolNames())
2939
+ this._pendingToolNames.add(name);
2635
2940
  this._buildRuntime({
2636
- activeToolNames: this.getActiveToolNames(),
2941
+ activeToolNames: [...this.getActiveToolNames(), ...addedDefaultTools],
2637
2942
  flagValues: previousFlagValues,
2638
2943
  includeAllExtensionTools: true,
2639
2944
  });
@@ -2644,6 +2949,7 @@ export class AgentSession {
2644
2949
  if (hasBindings) {
2645
2950
  await options?.beforeSessionStart?.();
2646
2951
  await this._extensionRunner.emit({ type: "session_start", reason: "reload" });
2952
+ this._extensionRunner.reportUnhandledMcpServers();
2647
2953
  await this.extendResourcesFromExtensions("reload");
2648
2954
  }
2649
2955
  }
@@ -2656,7 +2962,7 @@ export class AgentSession {
2656
2962
  */
2657
2963
  _isRetryableError(message) {
2658
2964
  // Context overflow is handled by compaction, not retry.
2659
- if (isContextOverflow(message, this.model?.contextWindow ?? 0))
2965
+ if (isContextOverflow(message, (this._modelForMessage(message) ?? this.model)?.contextWindow ?? 0))
2660
2966
  return false;
2661
2967
  return isRetryableAssistantError(message);
2662
2968
  }
@@ -2946,15 +3252,11 @@ export class AgentSession {
2946
3252
  let summaryDetails;
2947
3253
  let summaryUsage;
2948
3254
  if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
2949
- const model = this.model;
2950
- const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
3255
+ const signal = this._branchSummaryAbortController.signal;
2951
3256
  const branchSummarySettings = this.settingsManager.getBranchSummarySettings();
2952
3257
  const result = await generateBranchSummary(entriesToSummarize, {
2953
- model: requestModel,
2954
- apiKey,
2955
- headers,
2956
- env,
2957
- signal: this._branchSummaryAbortController.signal,
3258
+ ...(await this._getSummarizationRequestAuth(this.model, signal)),
3259
+ signal,
2958
3260
  customInstructions,
2959
3261
  replaceInstructions,
2960
3262
  reserveTokens: branchSummarySettings.reserveTokens,
@@ -3119,7 +3421,7 @@ export class AgentSession {
3119
3421
  };
3120
3422
  }
3121
3423
  getContextUsage() {
3122
- const model = this.model;
3424
+ const model = this._limitsModel();
3123
3425
  if (!model)
3124
3426
  return undefined;
3125
3427
  const contextWindow = model.contextWindow ?? 0;
@@ -3191,16 +3493,11 @@ export class AgentSession {
3191
3493
  if (!model) {
3192
3494
  throw new Error("No model selected");
3193
3495
  }
3194
- const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
3195
3496
  return generateBugReportSummary({
3497
+ ...(await this._getSummarizationRequestAuth(model, options.signal)),
3196
3498
  messages: this.messages,
3197
3499
  hint: options.hint,
3198
- model: requestModel,
3199
- apiKey,
3200
- headers,
3201
- env,
3202
3500
  signal: options.signal,
3203
- thinkingLevel: this.thinkingLevel,
3204
3501
  streamFn: this.agent.streamFunction,
3205
3502
  retry: this.settingsManager.getRetrySettings(),
3206
3503
  sessionId: this.sessionId,