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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (765) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/dist/bun/cli.d.ts.map +1 -1
  3. package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
  4. package/dist/bun/restore-sandbox-env.js.map +1 -1
  5. package/dist/bun/runtime-setup.d.ts.map +1 -1
  6. package/dist/bun/runtime-setup.js +4 -1
  7. package/dist/bun/runtime-setup.js.map +1 -1
  8. package/dist/bun/sandbox-env-setup.d.ts.map +1 -1
  9. package/dist/bundle/chunks/anthropic-messages-UID2PALB.js +6 -0
  10. package/dist/bundle/chunks/anthropic.js +2 -2
  11. package/dist/bundle/chunks/azure-openai-responses-WK37QQ3X.js +2 -0
  12. package/dist/bundle/chunks/bedrock-converse-stream.js +3 -3
  13. package/dist/bundle/chunks/chunk-2LGHNI5Y.js +1553 -0
  14. package/dist/bundle/chunks/chunk-6D7LHLKG.js +2 -0
  15. package/dist/bundle/chunks/chunk-7JGR3GZN.js +11 -0
  16. package/dist/bundle/chunks/{chunk-FUXEF6JQ.js → chunk-CWVWZD3J.js} +2 -2
  17. package/dist/bundle/chunks/chunk-GIUN2MS4.js +16 -0
  18. package/dist/bundle/chunks/chunk-H3QXYIF7.js +31 -0
  19. package/dist/bundle/chunks/chunk-KYK7L7MP.js +127 -0
  20. package/dist/bundle/chunks/chunk-LD2P6SFZ.js +2 -0
  21. package/dist/bundle/chunks/chunk-LDPPAHPJ.js +4 -0
  22. package/dist/bundle/chunks/chunk-NEUJZQL3.js +19 -0
  23. package/dist/bundle/chunks/chunk-OI6YFHHK.js +82 -0
  24. package/dist/bundle/chunks/chunk-OSKPX3Z5.js +2 -0
  25. package/dist/bundle/chunks/{chunk-XDUWOHPL.js → chunk-S3GGRYIO.js} +2 -2
  26. package/dist/bundle/chunks/chunk-SQXKOUF6.js +2 -0
  27. package/dist/bundle/chunks/chunk-UTB4DTYQ.js +2 -0
  28. package/dist/bundle/chunks/chunk-VIV3CWXG.js +2 -0
  29. package/dist/bundle/chunks/chunk-Y5O5BZGX.js +136 -0
  30. package/dist/bundle/chunks/{chunk-UZNGGY6N.js → chunk-Z772OFUN.js} +3 -3
  31. package/dist/bundle/chunks/cli-JE36AHMI.js +51 -0
  32. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-NPQN263E.js +2 -0
  33. package/dist/bundle/chunks/codemode-worker.js +354 -0
  34. package/dist/bundle/chunks/execute-UX73LR4F.js +367 -0
  35. package/dist/bundle/chunks/github-copilot.js +1 -1
  36. package/dist/bundle/chunks/google-generative-ai-OHRSHIE7.js +2 -0
  37. package/dist/bundle/chunks/google-vertex-KXEB3MVO.js +2 -0
  38. package/dist/bundle/chunks/{https-proxy-agent-2VXB7436.js → https-proxy-agent-UDEHOBGS.js} +1 -1
  39. package/dist/bundle/chunks/{lib-HGQMNYVT.js → lib-TEDK3E5I.js} +2 -2
  40. package/dist/bundle/chunks/llama-cpp-classify-XT44PI3C.js +22 -0
  41. package/dist/bundle/chunks/mistral-conversations-DKVFNQL6.js +5 -0
  42. package/dist/bundle/chunks/openai-chatgpt.js +75 -0
  43. package/dist/bundle/chunks/{openai-codex-responses-SG7PGUUZ.js → openai-codex-responses-WVERB76N.js} +2 -2
  44. package/dist/bundle/chunks/openai-codex.js +2 -2
  45. package/dist/bundle/chunks/{openai-completions-OBX42CLD.js → openai-completions-JXDDPZ23.js} +2 -2
  46. package/dist/bundle/chunks/openai-responses-WDT74L23.js +3 -0
  47. package/dist/bundle/chunks/{openrouter-images-N4XVVFSD.js → openrouter-images-ZVXWCSIM.js} +1 -1
  48. package/dist/bundle/chunks/openrouter.js +2 -2
  49. package/dist/bundle/chunks/pi-logo-animation-APS4JS6B.js +2 -0
  50. package/dist/bundle/chunks/{pi-messages-GFKBWJHZ.js → pi-messages-TM5SOOIW.js} +2 -2
  51. package/dist/bundle/chunks/radius.js +2 -2
  52. package/dist/bundle/chunks/runtime-MPXPM7VL.js +2 -0
  53. package/dist/bundle/chunks/typesafe-system-one-A4CZTQWZ.js +2 -0
  54. package/dist/bundle/chunks/virtual-modules-XLXFDFIX.js +2 -0
  55. package/dist/bundle/cli-runtime.js +1 -1
  56. package/dist/bundle/index.js +1 -1
  57. package/dist/bundle/rpc-entry.js +1 -1
  58. package/dist/cli/args.d.ts.map +1 -1
  59. package/dist/cli/args.js +6 -5
  60. package/dist/cli/args.js.map +1 -1
  61. package/dist/cli/auth-check.d.ts.map +1 -1
  62. package/dist/cli/auth-check.js.map +1 -1
  63. package/dist/cli/auth-command.d.ts.map +1 -1
  64. package/dist/cli/auth-command.js.map +1 -1
  65. package/dist/cli/config-selector.d.ts.map +1 -1
  66. package/dist/cli/config-selector.js.map +1 -1
  67. package/dist/cli/credential-print.d.ts.map +1 -1
  68. package/dist/cli/credential-print.js.map +1 -1
  69. package/dist/cli/file-processor.d.ts.map +1 -1
  70. package/dist/cli/file-processor.js.map +1 -1
  71. package/dist/cli/initial-message.d.ts +1 -1
  72. package/dist/cli/initial-message.d.ts.map +1 -1
  73. package/dist/cli/initial-message.js.map +1 -1
  74. package/dist/cli/list-models.d.ts.map +1 -1
  75. package/dist/cli/list-models.js.map +1 -1
  76. package/dist/cli/project-trust.d.ts.map +1 -1
  77. package/dist/cli/project-trust.js.map +1 -1
  78. package/dist/cli/session-picker.d.ts.map +1 -1
  79. package/dist/cli/session-picker.js.map +1 -1
  80. package/dist/cli/setup.d.ts.map +1 -1
  81. package/dist/cli/setup.js.map +1 -1
  82. package/dist/cli/startup-ui.d.ts.map +1 -1
  83. package/dist/cli/startup-ui.js +38 -30
  84. package/dist/cli/startup-ui.js.map +1 -1
  85. package/dist/cli.d.ts.map +1 -1
  86. package/dist/config.d.ts +15 -4
  87. package/dist/config.d.ts.map +1 -1
  88. package/dist/config.js +33 -4
  89. package/dist/config.js.map +1 -1
  90. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  91. package/dist/core/agent-session-runtime.js +1 -1
  92. package/dist/core/agent-session-runtime.js.map +1 -1
  93. package/dist/core/agent-session-services.d.ts.map +1 -1
  94. package/dist/core/agent-session-services.js +13 -0
  95. package/dist/core/agent-session-services.js.map +1 -1
  96. package/dist/core/agent-session.d.ts +133 -12
  97. package/dist/core/agent-session.d.ts.map +1 -1
  98. package/dist/core/agent-session.js +598 -297
  99. package/dist/core/agent-session.js.map +1 -1
  100. package/dist/core/auth-guidance.d.ts.map +1 -1
  101. package/dist/core/auth-guidance.js.map +1 -1
  102. package/dist/core/auth-storage.d.ts.map +1 -1
  103. package/dist/core/auth-storage.js.map +1 -1
  104. package/dist/core/bash-executor.d.ts.map +1 -1
  105. package/dist/core/bash-executor.js.map +1 -1
  106. package/dist/core/bug-report-upload.d.ts.map +1 -1
  107. package/dist/core/bug-report-upload.js.map +1 -1
  108. package/dist/core/bug-report.d.ts +1 -1
  109. package/dist/core/bug-report.d.ts.map +1 -1
  110. package/dist/core/bug-report.js +1 -1
  111. package/dist/core/bug-report.js.map +1 -1
  112. package/dist/core/cache-stats.d.ts.map +1 -1
  113. package/dist/core/cache-stats.js.map +1 -1
  114. package/dist/core/cache-warmer.d.ts.map +1 -1
  115. package/dist/core/cache-warmer.js.map +1 -1
  116. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  117. package/dist/core/compaction/branch-summarization.js.map +1 -1
  118. package/dist/core/compaction/compaction.d.ts.map +1 -1
  119. package/dist/core/compaction/compaction.js +1 -22
  120. package/dist/core/compaction/compaction.js.map +1 -1
  121. package/dist/core/compaction/index.d.ts.map +1 -1
  122. package/dist/core/compaction/utils.d.ts +2 -1
  123. package/dist/core/compaction/utils.d.ts.map +1 -1
  124. package/dist/core/compaction/utils.js +25 -18
  125. package/dist/core/compaction/utils.js.map +1 -1
  126. package/dist/core/crash-log.d.ts.map +1 -1
  127. package/dist/core/crash-log.js +2 -1
  128. package/dist/core/crash-log.js.map +1 -1
  129. package/dist/core/defaults.d.ts.map +1 -1
  130. package/dist/core/diagnostics.d.ts.map +1 -1
  131. package/dist/core/event-bus.d.ts.map +1 -1
  132. package/dist/core/event-bus.js.map +1 -1
  133. package/dist/core/exec.d.ts.map +1 -1
  134. package/dist/core/exec.js.map +1 -1
  135. package/dist/core/experimental.d.ts.map +1 -1
  136. package/dist/core/experimental.js.map +1 -1
  137. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  138. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  139. package/dist/core/export-html/index.d.ts.map +1 -1
  140. package/dist/core/export-html/index.js.map +1 -1
  141. package/dist/core/export-html/template.css +10 -0
  142. package/dist/core/export-html/template.js +66 -17
  143. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  144. package/dist/core/export-html/tool-renderer.js.map +1 -1
  145. package/dist/core/extensions/index.d.ts +1 -1
  146. package/dist/core/extensions/index.d.ts.map +1 -1
  147. package/dist/core/extensions/index.js.map +1 -1
  148. package/dist/core/extensions/jiti-loader.d.ts.map +1 -1
  149. package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -1
  150. package/dist/core/extensions/loader.d.ts.map +1 -1
  151. package/dist/core/extensions/loader.js +67 -5
  152. package/dist/core/extensions/loader.js.map +1 -1
  153. package/dist/core/extensions/runner.d.ts +18 -1
  154. package/dist/core/extensions/runner.d.ts.map +1 -1
  155. package/dist/core/extensions/runner.js +99 -0
  156. package/dist/core/extensions/runner.js.map +1 -1
  157. package/dist/core/extensions/types.d.ts +301 -22
  158. package/dist/core/extensions/types.d.ts.map +1 -1
  159. package/dist/core/extensions/types.js.map +1 -1
  160. package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
  161. package/dist/core/extensions/wrapper.d.ts +2 -2
  162. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  163. package/dist/core/extensions/wrapper.js +3 -3
  164. package/dist/core/extensions/wrapper.js.map +1 -1
  165. package/dist/core/footer-data-provider.d.ts.map +1 -1
  166. package/dist/core/footer-data-provider.js.map +1 -1
  167. package/dist/core/http-dispatcher.d.ts.map +1 -1
  168. package/dist/core/http-dispatcher.js.map +1 -1
  169. package/dist/core/index.d.ts.map +1 -1
  170. package/dist/core/keybindings.d.ts +1 -1
  171. package/dist/core/keybindings.d.ts.map +1 -1
  172. package/dist/core/keybindings.js +1 -1
  173. package/dist/core/keybindings.js.map +1 -1
  174. package/dist/core/mcp-servers.d.ts +125 -0
  175. package/dist/core/mcp-servers.d.ts.map +1 -0
  176. package/dist/core/mcp-servers.js +198 -0
  177. package/dist/core/mcp-servers.js.map +1 -0
  178. package/dist/core/messages.d.ts.map +1 -1
  179. package/dist/core/messages.js.map +1 -1
  180. package/dist/core/model-config.d.ts.map +1 -1
  181. package/dist/core/model-config.js.map +1 -1
  182. package/dist/core/model-registry.d.ts +15 -1
  183. package/dist/core/model-registry.d.ts.map +1 -1
  184. package/dist/core/model-registry.js +29 -0
  185. package/dist/core/model-registry.js.map +1 -1
  186. package/dist/core/model-resolver.d.ts +2 -2
  187. package/dist/core/model-resolver.d.ts.map +1 -1
  188. package/dist/core/model-resolver.js +5 -5
  189. package/dist/core/model-resolver.js.map +1 -1
  190. package/dist/core/model-runtime.d.ts +47 -3
  191. package/dist/core/model-runtime.d.ts.map +1 -1
  192. package/dist/core/model-runtime.js +189 -35
  193. package/dist/core/model-runtime.js.map +1 -1
  194. package/dist/core/models-store.d.ts.map +1 -1
  195. package/dist/core/models-store.js.map +1 -1
  196. package/dist/core/nested-tool-calls.d.ts +102 -0
  197. package/dist/core/nested-tool-calls.d.ts.map +1 -0
  198. package/dist/core/nested-tool-calls.js +178 -0
  199. package/dist/core/nested-tool-calls.js.map +1 -0
  200. package/dist/core/output-guard.d.ts.map +1 -1
  201. package/dist/core/output-guard.js.map +1 -1
  202. package/dist/core/package-manager.d.ts +4 -0
  203. package/dist/core/package-manager.d.ts.map +1 -1
  204. package/dist/core/package-manager.js +59 -12
  205. package/dist/core/package-manager.js.map +1 -1
  206. package/dist/core/pi-client-cli-adapter.d.ts.map +1 -1
  207. package/dist/core/pi-client-cli-adapter.js.map +1 -1
  208. package/dist/core/pi-client-runtime-update.d.ts.map +1 -1
  209. package/dist/core/pi-client-runtime-update.js.map +1 -1
  210. package/dist/core/pi-manifest.d.ts.map +1 -1
  211. package/dist/core/pi-manifest.js.map +1 -1
  212. package/dist/core/pi-server-client.d.ts.map +1 -1
  213. package/dist/core/pi-server-client.js.map +1 -1
  214. package/dist/core/pi-server-protocol.d.ts.map +1 -1
  215. package/dist/core/pi-server-protocol.js.map +1 -1
  216. package/dist/core/pi-server-request.d.ts.map +1 -1
  217. package/dist/core/pi-server-request.js.map +1 -1
  218. package/dist/core/project-trust.d.ts.map +1 -1
  219. package/dist/core/project-trust.js.map +1 -1
  220. package/dist/core/prompt-templates.d.ts.map +1 -1
  221. package/dist/core/prompt-templates.js.map +1 -1
  222. package/dist/core/provider-attribution.d.ts.map +1 -1
  223. package/dist/core/provider-attribution.js.map +1 -1
  224. package/dist/core/provider-composer.d.ts +40 -21
  225. package/dist/core/provider-composer.d.ts.map +1 -1
  226. package/dist/core/provider-composer.js +92 -40
  227. package/dist/core/provider-composer.js.map +1 -1
  228. package/dist/core/radius.d.ts +2 -0
  229. package/dist/core/radius.d.ts.map +1 -1
  230. package/dist/core/radius.js +2 -0
  231. package/dist/core/radius.js.map +1 -1
  232. package/dist/core/remote-catalog-provider.d.ts +8 -1
  233. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  234. package/dist/core/remote-catalog-provider.js +21 -11
  235. package/dist/core/remote-catalog-provider.js.map +1 -1
  236. package/dist/core/resolve-config-value.d.ts.map +1 -1
  237. package/dist/core/resolve-config-value.js.map +1 -1
  238. package/dist/core/resource-loader.d.ts +7 -1
  239. package/dist/core/resource-loader.d.ts.map +1 -1
  240. package/dist/core/resource-loader.js +161 -35
  241. package/dist/core/resource-loader.js.map +1 -1
  242. package/dist/core/runtime-credentials.d.ts.map +1 -1
  243. package/dist/core/runtime-credentials.js.map +1 -1
  244. package/dist/core/sdk.d.ts +1 -1
  245. package/dist/core/sdk.d.ts.map +1 -1
  246. package/dist/core/sdk.js +25 -6
  247. package/dist/core/sdk.js.map +1 -1
  248. package/dist/core/session-cwd.d.ts.map +1 -1
  249. package/dist/core/session-cwd.js.map +1 -1
  250. package/dist/core/session-export.d.ts.map +1 -1
  251. package/dist/core/session-export.js.map +1 -1
  252. package/dist/core/session-manager.d.ts +9 -0
  253. package/dist/core/session-manager.d.ts.map +1 -1
  254. package/dist/core/session-manager.js +22 -22
  255. package/dist/core/session-manager.js.map +1 -1
  256. package/dist/core/settings-diagnostics.d.ts.map +1 -1
  257. package/dist/core/settings-diagnostics.js.map +1 -1
  258. package/dist/core/settings-manager.d.ts +36 -4
  259. package/dist/core/settings-manager.d.ts.map +1 -1
  260. package/dist/core/settings-manager.js +75 -4
  261. package/dist/core/settings-manager.js.map +1 -1
  262. package/dist/core/skills.d.ts.map +1 -1
  263. package/dist/core/skills.js.map +1 -1
  264. package/dist/core/slash-commands.d.ts.map +1 -1
  265. package/dist/core/source-info.d.ts +8 -0
  266. package/dist/core/source-info.d.ts.map +1 -1
  267. package/dist/core/source-info.js +16 -0
  268. package/dist/core/source-info.js.map +1 -1
  269. package/dist/core/system-prompt.d.ts.map +1 -1
  270. package/dist/core/system-prompt.js +1 -1
  271. package/dist/core/system-prompt.js.map +1 -1
  272. package/dist/core/telemetry.d.ts.map +1 -1
  273. package/dist/core/telemetry.js.map +1 -1
  274. package/dist/core/timings.d.ts.map +1 -1
  275. package/dist/core/timings.js.map +1 -1
  276. package/dist/core/tools/bash.d.ts +12 -0
  277. package/dist/core/tools/bash.d.ts.map +1 -1
  278. package/dist/core/tools/bash.js +33 -2
  279. package/dist/core/tools/bash.js.map +1 -1
  280. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  281. package/dist/core/tools/edit-diff.js.map +1 -1
  282. package/dist/core/tools/edit.d.ts.map +1 -1
  283. package/dist/core/tools/edit.js.map +1 -1
  284. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  285. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  286. package/dist/core/tools/find.d.ts.map +1 -1
  287. package/dist/core/tools/find.js.map +1 -1
  288. package/dist/core/tools/grep.d.ts.map +1 -1
  289. package/dist/core/tools/grep.js.map +1 -1
  290. package/dist/core/tools/index.d.ts.map +1 -1
  291. package/dist/core/tools/index.js.map +1 -1
  292. package/dist/core/tools/ls.d.ts.map +1 -1
  293. package/dist/core/tools/ls.js.map +1 -1
  294. package/dist/core/tools/output-accumulator.d.ts +11 -0
  295. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  296. package/dist/core/tools/output-accumulator.js +36 -0
  297. package/dist/core/tools/output-accumulator.js.map +1 -1
  298. package/dist/core/tools/path-utils.d.ts.map +1 -1
  299. package/dist/core/tools/path-utils.js.map +1 -1
  300. package/dist/core/tools/powershell.d.ts.map +1 -1
  301. package/dist/core/tools/powershell.js.map +1 -1
  302. package/dist/core/tools/read.d.ts.map +1 -1
  303. package/dist/core/tools/read.js.map +1 -1
  304. package/dist/core/tools/render-utils.d.ts +6 -0
  305. package/dist/core/tools/render-utils.d.ts.map +1 -1
  306. package/dist/core/tools/render-utils.js +26 -0
  307. package/dist/core/tools/render-utils.js.map +1 -1
  308. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  309. package/dist/core/tools/renderers/bash.js +11 -32
  310. package/dist/core/tools/renderers/bash.js.map +1 -1
  311. package/dist/core/tools/renderers/edit.d.ts.map +1 -1
  312. package/dist/core/tools/renderers/edit.js.map +1 -1
  313. package/dist/core/tools/renderers/find.d.ts.map +1 -1
  314. package/dist/core/tools/renderers/find.js.map +1 -1
  315. package/dist/core/tools/renderers/grep.d.ts.map +1 -1
  316. package/dist/core/tools/renderers/grep.js.map +1 -1
  317. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  318. package/dist/core/tools/renderers/index.js.map +1 -1
  319. package/dist/core/tools/renderers/ls.d.ts.map +1 -1
  320. package/dist/core/tools/renderers/ls.js.map +1 -1
  321. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  322. package/dist/core/tools/renderers/read.js +3 -2
  323. package/dist/core/tools/renderers/read.js.map +1 -1
  324. package/dist/core/tools/renderers/write.d.ts.map +1 -1
  325. package/dist/core/tools/renderers/write.js.map +1 -1
  326. package/dist/core/tools/tool-definition-wrapper.d.ts +5 -3
  327. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  328. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  329. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  330. package/dist/core/tools/truncate.d.ts +14 -0
  331. package/dist/core/tools/truncate.d.ts.map +1 -1
  332. package/dist/core/tools/truncate.js +29 -0
  333. package/dist/core/tools/truncate.js.map +1 -1
  334. package/dist/core/tools/write.d.ts.map +1 -1
  335. package/dist/core/tools/write.js.map +1 -1
  336. package/dist/core/trust-manager.d.ts.map +1 -1
  337. package/dist/core/trust-manager.js +1 -0
  338. package/dist/core/trust-manager.js.map +1 -1
  339. package/dist/core/usage-totals.d.ts +2 -0
  340. package/dist/core/usage-totals.d.ts.map +1 -1
  341. package/dist/core/usage-totals.js +23 -0
  342. package/dist/core/usage-totals.js.map +1 -1
  343. package/dist/core/virtual-models.d.ts +117 -0
  344. package/dist/core/virtual-models.d.ts.map +1 -0
  345. package/dist/core/virtual-models.js +124 -0
  346. package/dist/core/virtual-models.js.map +1 -0
  347. package/dist/extensions/codemode/execute.d.ts +16 -0
  348. package/dist/extensions/codemode/execute.d.ts.map +1 -0
  349. package/dist/extensions/codemode/execute.js +536 -0
  350. package/dist/extensions/codemode/execute.js.map +1 -0
  351. package/dist/extensions/codemode/execute.lazy.d.ts +3 -0
  352. package/dist/extensions/codemode/execute.lazy.d.ts.map +1 -0
  353. package/dist/extensions/codemode/execute.lazy.js +3 -0
  354. package/dist/extensions/codemode/execute.lazy.js.map +1 -0
  355. package/dist/extensions/codemode/index.d.ts +21 -0
  356. package/dist/extensions/codemode/index.d.ts.map +1 -0
  357. package/dist/extensions/codemode/index.js +31 -0
  358. package/dist/extensions/codemode/index.js.map +1 -0
  359. package/dist/extensions/codemode/renderer.d.ts +12 -0
  360. package/dist/extensions/codemode/renderer.d.ts.map +1 -0
  361. package/dist/extensions/codemode/renderer.js +137 -0
  362. package/dist/extensions/codemode/renderer.js.map +1 -0
  363. package/dist/extensions/codemode/tool.d.ts +123 -0
  364. package/dist/extensions/codemode/tool.d.ts.map +1 -0
  365. package/dist/extensions/codemode/tool.js +268 -0
  366. package/dist/extensions/codemode/tool.js.map +1 -0
  367. package/dist/extensions/codemode/worker.d.ts +7 -0
  368. package/dist/extensions/codemode/worker.d.ts.map +1 -0
  369. package/dist/extensions/codemode/worker.js +7 -0
  370. package/dist/extensions/codemode/worker.js.map +1 -0
  371. package/dist/extensions/index.d.ts.map +1 -1
  372. package/dist/extensions/index.js +11 -1
  373. package/dist/extensions/index.js.map +1 -1
  374. package/dist/extensions/llama/client.d.ts.map +1 -1
  375. package/dist/extensions/llama/client.js.map +1 -1
  376. package/dist/extensions/llama/huggingface.d.ts.map +1 -1
  377. package/dist/extensions/llama/huggingface.js.map +1 -1
  378. package/dist/extensions/llama/index.d.ts.map +1 -1
  379. package/dist/extensions/llama/index.js.map +1 -1
  380. package/dist/extensions/llama/provider.d.ts +1 -1
  381. package/dist/extensions/llama/provider.d.ts.map +1 -1
  382. package/dist/extensions/llama/provider.js +65 -13
  383. package/dist/extensions/llama/provider.js.map +1 -1
  384. package/dist/extensions/llama/ui.d.ts.map +1 -1
  385. package/dist/extensions/llama/ui.js.map +1 -1
  386. package/dist/extensions/mcp/cli.d.ts +21 -0
  387. package/dist/extensions/mcp/cli.d.ts.map +1 -0
  388. package/dist/extensions/mcp/cli.js +500 -0
  389. package/dist/extensions/mcp/cli.js.map +1 -0
  390. package/dist/extensions/mcp/cli.lazy.d.ts +3 -0
  391. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -0
  392. package/dist/extensions/mcp/cli.lazy.js +3 -0
  393. package/dist/extensions/mcp/cli.lazy.js.map +1 -0
  394. package/dist/extensions/mcp/config.d.ts +72 -0
  395. package/dist/extensions/mcp/config.d.ts.map +1 -0
  396. package/dist/extensions/mcp/config.js +158 -0
  397. package/dist/extensions/mcp/config.js.map +1 -0
  398. package/dist/extensions/mcp/index.d.ts +76 -0
  399. package/dist/extensions/mcp/index.d.ts.map +1 -0
  400. package/dist/extensions/mcp/index.js +1066 -0
  401. package/dist/extensions/mcp/index.js.map +1 -0
  402. package/dist/extensions/mcp/log.d.ts +16 -0
  403. package/dist/extensions/mcp/log.d.ts.map +1 -0
  404. package/dist/extensions/mcp/log.js +66 -0
  405. package/dist/extensions/mcp/log.js.map +1 -0
  406. package/dist/extensions/mcp/oauth.d.ts +97 -0
  407. package/dist/extensions/mcp/oauth.d.ts.map +1 -0
  408. package/dist/extensions/mcp/oauth.js +358 -0
  409. package/dist/extensions/mcp/oauth.js.map +1 -0
  410. package/dist/extensions/mcp/resources.d.ts +43 -0
  411. package/dist/extensions/mcp/resources.d.ts.map +1 -0
  412. package/dist/extensions/mcp/resources.js +262 -0
  413. package/dist/extensions/mcp/resources.js.map +1 -0
  414. package/dist/extensions/mcp/runtime.d.ts +98 -0
  415. package/dist/extensions/mcp/runtime.d.ts.map +1 -0
  416. package/dist/extensions/mcp/runtime.js +395 -0
  417. package/dist/extensions/mcp/runtime.js.map +1 -0
  418. package/dist/extensions/mcp/runtime.lazy.d.ts +3 -0
  419. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -0
  420. package/dist/extensions/mcp/runtime.lazy.js +3 -0
  421. package/dist/extensions/mcp/runtime.lazy.js.map +1 -0
  422. package/dist/extensions/mcp/tools.d.ts +84 -0
  423. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  424. package/dist/extensions/mcp/tools.js +251 -0
  425. package/dist/extensions/mcp/tools.js.map +1 -0
  426. package/dist/extensions/mcp/ui.d.ts +60 -0
  427. package/dist/extensions/mcp/ui.d.ts.map +1 -0
  428. package/dist/extensions/mcp/ui.js +174 -0
  429. package/dist/extensions/mcp/ui.js.map +1 -0
  430. package/dist/extensions/tool-search/index.d.ts +12 -0
  431. package/dist/extensions/tool-search/index.d.ts.map +1 -0
  432. package/dist/extensions/tool-search/index.js +15 -0
  433. package/dist/extensions/tool-search/index.js.map +1 -0
  434. package/dist/extensions/tool-search/tool.d.ts +73 -0
  435. package/dist/extensions/tool-search/tool.d.ts.map +1 -0
  436. package/dist/extensions/tool-search/tool.js +189 -0
  437. package/dist/extensions/tool-search/tool.js.map +1 -0
  438. package/dist/index.d.ts +10 -3
  439. package/dist/index.d.ts.map +1 -1
  440. package/dist/index.js +5 -0
  441. package/dist/index.js.map +1 -1
  442. package/dist/main.d.ts.map +1 -1
  443. package/dist/main.js +16 -0
  444. package/dist/main.js.map +1 -1
  445. package/dist/migrations.d.ts.map +1 -1
  446. package/dist/migrations.js.map +1 -1
  447. package/dist/modes/index.d.ts.map +1 -1
  448. package/dist/modes/interactive/bug-report.d.ts.map +1 -1
  449. package/dist/modes/interactive/bug-report.js.map +1 -1
  450. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
  451. package/dist/modes/interactive/chat-viewport.js.map +1 -1
  452. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  453. package/dist/modes/interactive/components/armin.js.map +1 -1
  454. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  455. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  456. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  457. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  458. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  459. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  460. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  461. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  462. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  463. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  464. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  465. package/dist/modes/interactive/components/config-selector.js +13 -3
  466. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  467. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  468. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  469. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  470. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  471. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  472. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  473. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  474. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  475. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  476. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  477. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  478. package/dist/modes/interactive/components/diff.js.map +1 -1
  479. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  480. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  481. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
  482. package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
  483. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  484. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  485. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  486. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  487. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  488. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  489. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  490. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  491. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  492. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  493. package/dist/modes/interactive/components/footer.d.ts +7 -0
  494. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  495. package/dist/modes/interactive/components/footer.js +43 -3
  496. package/dist/modes/interactive/components/footer.js.map +1 -1
  497. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  498. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  499. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  500. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  501. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  502. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  503. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  504. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  505. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  506. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  507. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  508. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  509. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  510. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  511. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  512. package/dist/modes/interactive/components/pi-logo-animation.d.ts +68 -0
  513. package/dist/modes/interactive/components/pi-logo-animation.d.ts.map +1 -0
  514. package/dist/modes/interactive/components/pi-logo-animation.js +1086 -0
  515. package/dist/modes/interactive/components/pi-logo-animation.js.map +1 -0
  516. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts +7 -0
  517. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts.map +1 -0
  518. package/dist/modes/interactive/components/pi-logo-animation.lazy.js +12 -0
  519. package/dist/modes/interactive/components/pi-logo-animation.lazy.js.map +1 -0
  520. package/dist/modes/interactive/components/pi-logo.d.ts +19 -0
  521. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -0
  522. package/dist/modes/interactive/components/pi-logo.js +37 -0
  523. package/dist/modes/interactive/components/pi-logo.js.map +1 -0
  524. package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
  525. package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
  526. package/dist/modes/interactive/components/radius-login-selector.js +85 -0
  527. package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
  528. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  529. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  530. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  531. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  532. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  533. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  534. package/dist/modes/interactive/components/settings-selector.d.ts +6 -4
  535. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  536. package/dist/modes/interactive/components/settings-selector.js +33 -11
  537. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  538. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  539. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  540. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  541. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  542. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  543. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  544. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  545. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  546. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  547. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  548. package/dist/modes/interactive/components/themed-text.d.ts +17 -0
  549. package/dist/modes/interactive/components/themed-text.d.ts.map +1 -0
  550. package/dist/modes/interactive/components/themed-text.js +29 -0
  551. package/dist/modes/interactive/components/themed-text.js.map +1 -0
  552. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  553. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  554. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  555. package/dist/modes/interactive/components/tool-execution.js +2 -2
  556. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  557. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  558. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  559. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
  560. package/dist/modes/interactive/components/trust-selector.js.map +1 -1
  561. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  562. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  563. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  564. package/dist/modes/interactive/components/user-message.js +5 -4
  565. package/dist/modes/interactive/components/user-message.js.map +1 -1
  566. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  567. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  568. package/dist/modes/interactive/components/visual-truncate.js +39 -6
  569. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  570. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  571. package/dist/modes/interactive/external-editor.js.map +1 -1
  572. package/dist/modes/interactive/interactive-mode.d.ts +21 -0
  573. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  574. package/dist/modes/interactive/interactive-mode.js +348 -197
  575. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  576. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -1
  577. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -1
  578. package/dist/modes/interactive/model-search.d.ts.map +1 -1
  579. package/dist/modes/interactive/model-search.js.map +1 -1
  580. package/dist/modes/interactive/session-share.d.ts.map +1 -1
  581. package/dist/modes/interactive/session-share.js.map +1 -1
  582. package/dist/modes/interactive/theme/dark.json +59 -72
  583. package/dist/modes/interactive/theme/light.json +57 -69
  584. package/dist/modes/interactive/theme/system-theme.d.ts +55 -0
  585. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
  586. package/dist/modes/interactive/theme/system-theme.js +546 -0
  587. package/dist/modes/interactive/theme/system-theme.js.map +1 -0
  588. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  589. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  590. package/dist/modes/interactive/theme/theme-controller.js +127 -47
  591. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  592. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  593. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -1
  594. package/dist/modes/interactive/theme/theme-json.js +3 -1
  595. package/dist/modes/interactive/theme/theme-json.js.map +1 -1
  596. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  597. package/dist/modes/interactive/theme/theme.d.ts +66 -39
  598. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  599. package/dist/modes/interactive/theme/theme.js +238 -317
  600. package/dist/modes/interactive/theme/theme.js.map +1 -1
  601. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  602. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  603. package/dist/modes/interactive/tui-renderer.js +1 -0
  604. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  605. package/dist/modes/json-event.d.ts.map +1 -1
  606. package/dist/modes/json-event.js.map +1 -1
  607. package/dist/modes/print-mode.d.ts.map +1 -1
  608. package/dist/modes/print-mode.js.map +1 -1
  609. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  610. package/dist/modes/rpc/jsonl.js.map +1 -1
  611. package/dist/modes/rpc/rpc-client.d.ts +6 -6
  612. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  613. package/dist/modes/rpc/rpc-client.js +12 -8
  614. package/dist/modes/rpc/rpc-client.js.map +1 -1
  615. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  616. package/dist/modes/rpc/rpc-mode.js +7 -9
  617. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  618. package/dist/modes/rpc/rpc-types.d.ts +10 -1
  619. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  620. package/dist/modes/rpc/rpc-types.js.map +1 -1
  621. package/dist/package-manager-cli.d.ts.map +1 -1
  622. package/dist/package-manager-cli.js +6 -2
  623. package/dist/package-manager-cli.js.map +1 -1
  624. package/dist/pi-client-cli.d.ts.map +1 -1
  625. package/dist/pi-client-cli.js.map +1 -1
  626. package/dist/rpc-entry.d.ts.map +1 -1
  627. package/dist/rpc-entry.js.map +1 -1
  628. package/dist/utils/abort.d.ts.map +1 -1
  629. package/dist/utils/abort.js.map +1 -1
  630. package/dist/utils/ansi.d.ts.map +1 -1
  631. package/dist/utils/ansi.js.map +1 -1
  632. package/dist/utils/changelog.d.ts.map +1 -1
  633. package/dist/utils/changelog.js.map +1 -1
  634. package/dist/utils/child-process.d.ts.map +1 -1
  635. package/dist/utils/child-process.js.map +1 -1
  636. package/dist/utils/clipboard-command.d.ts.map +1 -1
  637. package/dist/utils/clipboard-command.js.map +1 -1
  638. package/dist/utils/clipboard-image.d.ts.map +1 -1
  639. package/dist/utils/clipboard-image.js +14 -17
  640. package/dist/utils/clipboard-image.js.map +1 -1
  641. package/dist/utils/clipboard.d.ts +2 -0
  642. package/dist/utils/clipboard.d.ts.map +1 -1
  643. package/dist/utils/clipboard.js +5 -0
  644. package/dist/utils/clipboard.js.map +1 -1
  645. package/dist/utils/deprecation.d.ts.map +1 -1
  646. package/dist/utils/deprecation.js.map +1 -1
  647. package/dist/utils/exif-orientation.d.ts.map +1 -1
  648. package/dist/utils/exif-orientation.js.map +1 -1
  649. package/dist/utils/frontmatter.d.ts.map +1 -1
  650. package/dist/utils/frontmatter.js.map +1 -1
  651. package/dist/utils/fs-watch.d.ts.map +1 -1
  652. package/dist/utils/fs-watch.js.map +1 -1
  653. package/dist/utils/git.d.ts.map +1 -1
  654. package/dist/utils/git.js.map +1 -1
  655. package/dist/utils/html.d.ts.map +1 -1
  656. package/dist/utils/html.js.map +1 -1
  657. package/dist/utils/image-convert.d.ts.map +1 -1
  658. package/dist/utils/image-convert.js.map +1 -1
  659. package/dist/utils/image-process.d.ts.map +1 -1
  660. package/dist/utils/image-process.js.map +1 -1
  661. package/dist/utils/image-resize-core.d.ts.map +1 -1
  662. package/dist/utils/image-resize-core.js.map +1 -1
  663. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  664. package/dist/utils/image-resize-worker.js.map +1 -1
  665. package/dist/utils/image-resize.d.ts.map +1 -1
  666. package/dist/utils/image-resize.js.map +1 -1
  667. package/dist/utils/json.d.ts.map +1 -1
  668. package/dist/utils/json.js.map +1 -1
  669. package/dist/utils/management-http.d.ts.map +1 -1
  670. package/dist/utils/management-http.js.map +1 -1
  671. package/dist/utils/mime.d.ts.map +1 -1
  672. package/dist/utils/mime.js.map +1 -1
  673. package/dist/utils/open-browser.d.ts.map +1 -1
  674. package/dist/utils/open-browser.js.map +1 -1
  675. package/dist/utils/paths.d.ts +3 -3
  676. package/dist/utils/paths.d.ts.map +1 -1
  677. package/dist/utils/paths.js +5 -4
  678. package/dist/utils/paths.js.map +1 -1
  679. package/dist/utils/photon.d.ts.map +1 -1
  680. package/dist/utils/photon.js.map +1 -1
  681. package/dist/utils/pi-user-agent.d.ts.map +1 -1
  682. package/dist/utils/pi-user-agent.js.map +1 -1
  683. package/dist/utils/shell.d.ts +1 -3
  684. package/dist/utils/shell.d.ts.map +1 -1
  685. package/dist/utils/shell.js +3 -30
  686. package/dist/utils/shell.js.map +1 -1
  687. package/dist/utils/sleep.d.ts.map +1 -1
  688. package/dist/utils/sleep.js.map +1 -1
  689. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  690. package/dist/utils/syntax-highlight.js +2 -0
  691. package/dist/utils/syntax-highlight.js.map +1 -1
  692. package/dist/utils/text.d.ts.map +1 -1
  693. package/dist/utils/text.js.map +1 -1
  694. package/dist/utils/tool-result-images.d.ts.map +1 -1
  695. package/dist/utils/tool-result-images.js.map +1 -1
  696. package/dist/utils/tools-manager.d.ts.map +1 -1
  697. package/dist/utils/tools-manager.js.map +1 -1
  698. package/dist/utils/version-check.d.ts.map +1 -1
  699. package/dist/utils/version-check.js.map +1 -1
  700. package/dist/utils/windows-self-update.d.ts.map +1 -1
  701. package/dist/utils/windows-self-update.js.map +1 -1
  702. package/dist/utils/wsl.d.ts.map +1 -1
  703. package/dist/utils/wsl.js.map +1 -1
  704. package/dist/utils/zip.d.ts.map +1 -1
  705. package/dist/utils/zip.js.map +1 -1
  706. package/docs/cli.md +58 -7
  707. package/docs/codemode.md +207 -0
  708. package/docs/configuration.md +2 -0
  709. package/docs/custom-provider.md +43 -4
  710. package/docs/docs.json +13 -1
  711. package/docs/environment-variables.md +2 -2
  712. package/docs/extensions.md +55 -0
  713. package/docs/index.md +1 -1
  714. package/docs/keybindings.md +1 -1
  715. package/docs/llama-cpp.md +13 -0
  716. package/docs/mcp.md +248 -0
  717. package/docs/models.md +57 -1
  718. package/docs/packages.md +4 -2
  719. package/docs/providers.md +19 -6
  720. package/docs/rpc-commands.md +9 -3
  721. package/docs/rpc.md +3 -1
  722. package/docs/sdk.md +8 -3
  723. package/docs/security.md +2 -0
  724. package/docs/session-format.md +5 -1
  725. package/docs/settings.md +24 -5
  726. package/docs/themes.md +33 -7
  727. package/docs/tui.md +18 -0
  728. package/docs/usage.md +1 -1
  729. package/docs/virtual-models.md +114 -0
  730. package/docs/windows.md +2 -0
  731. package/examples/README.md +1 -1
  732. package/examples/extensions/README.md +2 -0
  733. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  734. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  735. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  736. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  737. package/examples/extensions/custom-provider-gitlab-duo/test.ts +5 -5
  738. package/examples/extensions/debug-provider.ts +90 -0
  739. package/examples/extensions/gondolin/package-lock.json +2 -2
  740. package/examples/extensions/gondolin/package.json +1 -1
  741. package/examples/extensions/jev-router.ts +113 -0
  742. package/examples/extensions/minimal-mode.ts +24 -96
  743. package/examples/extensions/sandbox/package-lock.json +2 -2
  744. package/examples/extensions/sandbox/package.json +1 -1
  745. package/examples/extensions/with-deps/package-lock.json +2 -2
  746. package/examples/extensions/with-deps/package.json +1 -1
  747. package/examples/rpc-client.ts +1 -1
  748. package/examples/rpc-extension-ui.ts +1 -1
  749. package/examples/sdk/14-codemode-mcp.ts +61 -0
  750. package/examples/sdk/README.md +2 -1
  751. package/package.json +14 -12
  752. package/dist/bundle/chunks/anthropic-messages-J5WXPPPC.js +0 -6
  753. package/dist/bundle/chunks/azure-openai-responses-QJ7SPP5M.js +0 -2
  754. package/dist/bundle/chunks/chunk-6R7UI4IY.js +0 -2
  755. package/dist/bundle/chunks/chunk-BZKWNWMI.js +0 -2
  756. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
  757. package/dist/bundle/chunks/chunk-RCZIEVGO.js +0 -11
  758. package/dist/bundle/chunks/chunk-S7SZN6Z3.js +0 -2
  759. package/dist/bundle/chunks/chunk-X2F52Z34.js +0 -1685
  760. package/dist/bundle/chunks/chunk-XNGRGP62.js +0 -2
  761. package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +0 -2
  762. package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +0 -2
  763. package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +0 -5
  764. package/dist/bundle/chunks/openai-responses-AH7QTG23.js +0 -2
  765. package/dist/bundle/chunks/virtual-modules-WWGGM27U.js +0 -2
@@ -26,6 +26,7 @@ import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScop
26
26
  import { CredentialSynchronizationError } from "../../core/model-runtime.js";
27
27
  import { DefaultPackageManager } from "../../core/package-manager.js";
28
28
  import { getCliBinName } from "../../core/pi-client-cli-adapter.js";
29
+ import { RADIUS_MCP_URL, RADIUS_PROVIDER_ID } from "../../core/radius.js";
29
30
  import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
30
31
  import { SessionManager, sessionEntryToContextMessages, } from "../../core/session-manager.js";
31
32
  import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
@@ -33,8 +34,9 @@ import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
33
34
  import { withBuiltInRenderers } from "../../core/tools/renderers/index.js";
34
35
  import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
35
36
  import { getUsageCostBreakdown } from "../../core/usage-totals.js";
37
+ import { addMcpServerConfig, loadMcpConfig } from "../../extensions/mcp/config.js";
36
38
  import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
37
- import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
39
+ import { copyToClipboard, readClipboardFilePaths, readClipboardText } from "../../utils/clipboard.js";
38
40
  import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
39
41
  import { parseGitUrl } from "../../utils/git.js";
40
42
  import { getCwdRelativePath } from "../../utils/paths.js";
@@ -64,12 +66,16 @@ import { formatKeyText, keyDisplayText, keyHint, keyText, rawKeyHint } from "./c
64
66
  import { LoginDialogComponent } from "./components/login-dialog.js";
65
67
  import { createMermaidMarkdownTransformer } from "./components/mermaid.js";
66
68
  import { ModelSelectorComponent } from "./components/model-selector.js";
67
- import { formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
69
+ import { formatAuthSelectorProviderStatus, formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
70
+ import { piLogoLines, piWordmark, supportsPiLogo } from "./components/pi-logo.js";
71
+ import { playPiLogoAnimation } from "./components/pi-logo-animation.lazy.js";
72
+ import { createLoginMenuSelector } from "./components/radius-login-selector.js";
68
73
  import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
69
74
  import { SessionSelectorComponent } from "./components/session-selector.js";
70
75
  import { SettingsSelectorComponent } from "./components/settings-selector.js";
71
76
  import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
72
77
  import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
78
+ import { ThemedText } from "./components/themed-text.js";
73
79
  import { ThinkingSelectorComponent } from "./components/thinking-selector.js";
74
80
  import { ToolExecutionComponent } from "./components/tool-execution.js";
75
81
  import { TreeSelectorComponent } from "./components/tree-selector.js";
@@ -80,7 +86,7 @@ import { editInExternalEditor } from "./external-editor.js";
80
86
  import { refreshModelCatalogs } from "./model-catalog-refresh.js";
81
87
  import { getModelSearchText } from "./model-search.js";
82
88
  import { shareSession } from "./session-share.js";
83
- import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
89
+ import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, SYSTEM_THEME_NAME, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
84
90
  import { InteractiveThemeController } from "./theme/theme-controller.js";
85
91
  import { createInteractiveTui, createInteractiveTuiReference } from "./tui-renderer.js";
86
92
  export { createInteractiveTui, createInteractiveTuiReference } from "./tui-renderer.js";
@@ -93,16 +99,26 @@ function isWorkingStatusEditor(editor) {
93
99
  function isExpandable(obj) {
94
100
  return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
95
101
  }
96
- class ExpandableText extends Text {
97
- getCollapsedText;
98
- getExpandedText;
102
+ class ExpandableText extends ThemedText {
103
+ state;
99
104
  constructor(getCollapsedText, getExpandedText, expanded = false, paddingX = 0, paddingY = 0) {
100
- super(expanded ? getExpandedText() : getCollapsedText(), paddingX, paddingY);
101
- this.getCollapsedText = getCollapsedText;
102
- this.getExpandedText = getExpandedText;
105
+ const state = { expanded };
106
+ super(() => (state.expanded ? getExpandedText() : getCollapsedText()), paddingX, paddingY);
107
+ this.state = state;
103
108
  }
104
109
  setExpanded(expanded) {
105
- this.setText(expanded ? this.getExpandedText() : this.getCollapsedText());
110
+ this.state.expanded = expanded;
111
+ this.invalidate();
112
+ }
113
+ }
114
+ /** The built-in header. Clicking its logo (the first two lines, after one column of padding) plays an easter egg. */
115
+ class BuiltInHeader extends ExpandableText {
116
+ onLogoClick;
117
+ handleMouse(event) {
118
+ if (event.type !== "click" || event.y > 1 || event.x < 1 || event.x > 4 || !this.onLogoClick)
119
+ return undefined;
120
+ this.onLogoClick(event.screenX - event.x + 1, event.screenY - event.y);
121
+ return { handled: true };
106
122
  }
107
123
  }
108
124
  function isCustomSessionEntry(item) {
@@ -174,6 +190,7 @@ function llamaCppPostLoginGuidance(actionLabel, loadedModelCount) {
174
190
  ? `${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`
175
191
  : `${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`;
176
192
  }
193
+ const RADIUS_LOGIN_INTRO = "Radius is a service crafted for Pi by the builders of Pi, Earendil Works";
177
194
  const AUTH_TYPE_ORDER = { oauth: 0, api_key: 1 };
178
195
  function createFuzzyAutocompleteItems(items, prefix, getSearchText, toAutocompleteItem) {
179
196
  const filtered = fuzzyFilter(items, prefix, getSearchText);
@@ -196,18 +213,21 @@ function getLoginProviderCompletionOptions(providerOptions) {
196
213
  id: provider.id,
197
214
  name: provider.name,
198
215
  authTypes: [provider.authType],
216
+ subscription: provider.subscription,
199
217
  });
200
218
  }
201
219
  return Array.from(byId.values()).sort((a, b) => a.name.localeCompare(b.name));
202
220
  }
203
221
  function getLoginProviderSearchText(provider) {
204
222
  const authTypes = provider.authTypes
205
- .map((authType) => `${authType} ${formatAuthSelectorProviderType(authType)}`)
223
+ .map((authType) => `${authType} ${formatAuthSelectorProviderType(authType, provider.subscription)}`)
206
224
  .join(" ");
207
225
  return `${provider.id} ${provider.name} ${authTypes}`;
208
226
  }
209
227
  function formatLoginProviderCompletionDescription(provider) {
210
- const authTypes = provider.authTypes.map(formatAuthSelectorProviderType).join("/");
228
+ const authTypes = provider.authTypes
229
+ .map((authType) => formatAuthSelectorProviderType(authType, provider.subscription))
230
+ .join("/");
211
231
  return provider.name === provider.id ? authTypes : `${provider.name} · ${authTypes}`;
212
232
  }
213
233
  export class InteractiveMode {
@@ -257,6 +277,7 @@ export class InteractiveMode {
257
277
  // Status line tracking (for mutating immediately-sequential status updates)
258
278
  lastStatusSpacer = undefined;
259
279
  lastStatusText = undefined;
280
+ lastStatusMessage = "";
260
281
  managedToolStatusStarted = false;
261
282
  // Streaming message tracking
262
283
  streamingComponent = undefined;
@@ -347,7 +368,7 @@ export class InteractiveMode {
347
368
  });
348
369
  this.runtimeHost.setRebindSession(async () => {
349
370
  await this.rebindCurrentSession({ renderBeforeBind: true });
350
- await this.themeController.applyFromSettings();
371
+ this.themeController.applyFromSettings();
351
372
  });
352
373
  this.version = VERSION;
353
374
  this.renderer = createInteractiveTui({
@@ -357,6 +378,7 @@ export class InteractiveMode {
357
378
  terminal: options.terminal,
358
379
  onRightClickPaste: this.onRightClickPaste,
359
380
  fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
381
+ fullscreenWheelScrollLines: this.settingsManager.getFullscreenWheelScrollLines(),
360
382
  });
361
383
  this.ui = createInteractiveTuiReference(() => this.renderer);
362
384
  this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
@@ -401,7 +423,8 @@ export class InteractiveMode {
401
423
  });
402
424
  }
403
425
  getAutocompleteSourceTag(sourceInfo) {
404
- if (!sourceInfo) {
426
+ // Built-in extension commands are untagged, like built-in commands.
427
+ if (!sourceInfo || sourceInfo.source === "builtin") {
405
428
  return undefined;
406
429
  }
407
430
  const scopePrefix = sourceInfo.scope === "user" ? "u" : sourceInfo.scope === "project" ? "p" : "t";
@@ -554,7 +577,7 @@ export class InteractiveMode {
554
577
  this.chatContainer.addChild(new Text(condensedText, 1, 0));
555
578
  }
556
579
  else {
557
- this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
580
+ this.chatContainer.addChild(new ThemedText(() => theme.bold(theme.fg("accent", "What's New")), 1, 0));
558
581
  this.chatContainer.addChild(new Spacer(1));
559
582
  this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(), 1, 0, this.getMarkdownThemeWithSettings()));
560
583
  this.chatContainer.addChild(new Spacer(1));
@@ -606,6 +629,7 @@ export class InteractiveMode {
606
629
  terminal,
607
630
  onRightClickPaste: this.onRightClickPaste,
608
631
  fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
632
+ fullscreenWheelScrollLines: this.settingsManager.getFullscreenWheelScrollLines(),
609
633
  });
610
634
  nextUi.setClearOnShrink(clearOnShrink);
611
635
  nextUi.onDebug = onDebug;
@@ -636,7 +660,7 @@ export class InteractiveMode {
636
660
  this.registerSignalHandlers();
637
661
  // Load changelog (only show new entries, skip for resumed sessions)
638
662
  this.changelogMarkdown = this.getChangelogForDisplay();
639
- if (this.session.scopedModels.length > 0 && (this.options.verbose || !this.settingsManager.getQuietStartup())) {
663
+ if (this.session.scopedModels.length > 0 && this.shouldShowStartupDetails()) {
640
664
  const modelList = this.session.scopedModels
641
665
  .map((sm) => {
642
666
  const thinkingStr = sm.thinkingLevel ? `:${sm.thinkingLevel}` : "";
@@ -683,13 +707,26 @@ export class InteractiveMode {
683
707
  this.ui.start();
684
708
  this.bindAbortInputListener();
685
709
  this.isInitialized = true;
686
- await this.themeController.applyFromSettings();
710
+ this.themeController.applyFromSettings();
711
+ // The header and startup notices bake theme colors into their text, so build them once the terminal
712
+ // reported its colors. This ends at the terminal's DA1 reply, or after 100 ms if it answers nothing.
713
+ await this.themeController.waitForTerminalColors();
687
714
  // Add header with keybindings from config (unless silenced)
688
- if (this.options.verbose || !this.settingsManager.getQuietStartup()) {
689
- const logo = theme.bold(theme.fg("accent", APP_NAME)) + theme.fg("dim", ` v${this.version}`);
715
+ if (this.shouldShowStartupHeader()) {
716
+ const showDetails = this.shouldShowStartupDetails();
717
+ // Built on demand so the header follows theme changes. The logo's first line carries the version,
718
+ // its second line the first line of key hints. Terminals that cannot render the logo get a
719
+ // "Pi vX" line instead, with the key hints below it.
720
+ const showLogo = supportsPiLogo();
721
+ const withLogo = (hints) => {
722
+ if (!showLogo)
723
+ return `${piWordmark()} ${theme.fg("dim", `v${this.version}`)}\n${hints}`;
724
+ const [top, bottom] = piLogoLines();
725
+ return `${top} ${theme.fg("dim", `v${this.version}`)}\n${bottom} ${hints}`;
726
+ };
690
727
  // Build startup instructions using keybinding hint helpers
691
728
  const hint = (keybinding, description) => keyHint(keybinding, description);
692
- const expandedInstructions = [
729
+ const expandedInstructions = () => [
693
730
  hint("app.interrupt", "to interrupt"),
694
731
  hint("app.clear", "to clear"),
695
732
  rawKeyHint(`${keyText("app.clear")} twice`, "to exit"),
@@ -707,19 +744,22 @@ export class InteractiveMode {
707
744
  rawKeyHint("!!", "to run bash (no context)"),
708
745
  hint("app.message.followUp", "to queue follow-up"),
709
746
  hint("app.message.dequeue", "to edit all queued messages"),
710
- hint("app.clipboard.pasteImage", "to paste image (with text fallback)"),
747
+ hint("app.clipboard.pasteImage", "to paste files on macOS, images, or text"),
711
748
  rawKeyHint("drop files", "to attach"),
712
749
  ].join("\n");
713
- const compactInstructions = [
750
+ const compactInstructions = () => [
714
751
  hint("app.interrupt", "interrupt"),
715
752
  rawKeyHint(`${keyText("app.clear")}/${keyText("app.exit")}`, "clear/exit"),
716
753
  rawKeyHint("/", "commands"),
717
754
  rawKeyHint("!", "bash"),
718
755
  hint("app.tools.expand", "more"),
719
756
  ].join(theme.fg("muted", " · "));
720
- const compactOnboarding = theme.fg("dim", `Press ${keyText("app.tools.expand")} to show full startup help and loaded resources.`);
721
- const onboarding = theme.fg("dim", `Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.`);
722
- this.builtInHeader = new ExpandableText(() => `${logo}\n${compactInstructions}\n${compactOnboarding}\n\n${onboarding}`, () => `${logo}\n${expandedInstructions}\n\n${onboarding}`, this.getStartupExpansionState(), 1, 0);
757
+ const compactOnboarding = () => theme.fg("dim", `Press ${keyText("app.tools.expand")} to show full startup help${showDetails ? " and loaded resources" : ""}.`);
758
+ const onboarding = () => theme.fg("dim", `Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.`);
759
+ const header = new BuiltInHeader(() => `${withLogo(compactInstructions())}\n${compactOnboarding()}\n\n${onboarding()}`, () => `${withLogo(expandedInstructions())}\n\n${onboarding()}`, this.getStartupExpansionState(), 1, 0);
760
+ if (showLogo)
761
+ header.onLogoClick = (column, row) => playPiLogoAnimation(this.renderer, column, row);
762
+ this.builtInHeader = header;
723
763
  // Setup UI layout
724
764
  this.headerContainer.addChild(new Spacer(1));
725
765
  this.headerContainer.addChild(this.builtInHeader);
@@ -1032,6 +1072,14 @@ export class InteractiveMode {
1032
1072
  getStartupExpansionState() {
1033
1073
  return this.options.verbose || this.toolOutputExpanded;
1034
1074
  }
1075
+ /** Startup header (logo, version, key hints). Hidden only by quietStartup: true. */
1076
+ shouldShowStartupHeader() {
1077
+ return this.options.verbose === true || this.settingsManager.getQuietStartup() !== true;
1078
+ }
1079
+ /** Startup details (model scope, loaded resources). Hidden by quietStartup: true or "header". */
1080
+ shouldShowStartupDetails() {
1081
+ return this.options.verbose === true || this.settingsManager.getQuietStartup() === false;
1082
+ }
1035
1083
  /**
1036
1084
  * Get a short path relative to the package root for display.
1037
1085
  */
@@ -1293,7 +1341,7 @@ export class InteractiveMode {
1293
1341
  showLoadedResources(options) {
1294
1342
  // Resource rendering is idempotent; chat clears no longer clear this separate container.
1295
1343
  this.loadedResourcesContainer.clear();
1296
- const showListing = options?.force || this.options.verbose || !this.settingsManager.getQuietStartup();
1344
+ const showListing = options?.force || this.shouldShowStartupDetails();
1297
1345
  const showDiagnostics = showListing || options?.showDiagnosticsWhenQuiet === true;
1298
1346
  if (!showListing && !showDiagnostics) {
1299
1347
  return;
@@ -1306,8 +1354,9 @@ export class InteractiveMode {
1306
1354
  }
1307
1355
  return theme.fg("dim", ` ${labels.join(", ")}`);
1308
1356
  };
1357
+ // Bodies are built on demand so the listing follows theme changes.
1309
1358
  const addLoadedSection = (name, collapsedBody, expandedBody = collapsedBody, color = "mdHeading") => {
1310
- const section = new ExpandableText(() => `${sectionHeader(name, color)}\n${collapsedBody}`, () => `${sectionHeader(name, color)}\n${expandedBody}`, this.getStartupExpansionState(), 0, 0);
1359
+ const section = new ExpandableText(() => `${sectionHeader(name, color)}\n${collapsedBody()}`, () => `${sectionHeader(name, color)}\n${expandedBody()}`, this.getStartupExpansionState(), 0, 0);
1311
1360
  this.loadedResourcesContainer.addChild(section);
1312
1361
  this.loadedResourcesContainer.addChild(new Spacer(1));
1313
1362
  };
@@ -1352,27 +1401,25 @@ export class InteractiveMode {
1352
1401
  ];
1353
1402
  if (contextFiles.length > 0) {
1354
1403
  this.loadedResourcesContainer.addChild(new Spacer(1));
1355
- const contextList = contextFiles
1356
- .map((f) => theme.fg("dim", ` ${this.formatDisplayPath(f.path)}`))
1357
- .join("\n");
1358
- const contextCompactList = formatCompactList(contextFiles.map((contextFile) => this.formatContextPath(contextFile.path)), { sort: false });
1404
+ const contextList = () => contextFiles.map((f) => theme.fg("dim", ` ${this.formatDisplayPath(f.path)}`)).join("\n");
1405
+ const contextCompactList = () => formatCompactList(contextFiles.map((contextFile) => this.formatContextPath(contextFile.path)), { sort: false });
1359
1406
  addLoadedSection("Context", contextCompactList, contextList);
1360
1407
  }
1361
1408
  const skills = skillsResult.skills;
1362
1409
  if (skills.length > 0) {
1363
1410
  const groups = this.buildScopeGroups(skills.map((skill) => ({ path: skill.filePath, sourceInfo: skill.sourceInfo })));
1364
- const skillList = this.formatScopeGroups(groups, {
1411
+ const skillList = () => this.formatScopeGroups(groups, {
1365
1412
  formatPath: (item) => this.formatDisplayPath(item.path),
1366
1413
  formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
1367
1414
  });
1368
- const skillCompactList = formatCompactList(skills.map((skill) => skill.name));
1415
+ const skillCompactList = () => formatCompactList(skills.map((skill) => skill.name));
1369
1416
  addLoadedSection("Skills", skillCompactList, skillList);
1370
1417
  }
1371
1418
  const templates = this.session.promptTemplates;
1372
1419
  if (templates.length > 0) {
1373
1420
  const groups = this.buildScopeGroups(templates.map((template) => ({ path: template.filePath, sourceInfo: template.sourceInfo })));
1374
1421
  const templateByPath = new Map(templates.map((t) => [t.filePath, t]));
1375
- const templateList = this.formatScopeGroups(groups, {
1422
+ const templateList = () => this.formatScopeGroups(groups, {
1376
1423
  formatPath: (item) => {
1377
1424
  const template = templateByPath.get(item.path);
1378
1425
  return template ? `/${template.name}` : this.formatDisplayPath(item.path);
@@ -1382,53 +1429,40 @@ export class InteractiveMode {
1382
1429
  return template ? `/${template.name}` : this.formatDisplayPath(item.path);
1383
1430
  },
1384
1431
  });
1385
- const promptCompactList = formatCompactList(templates.map((template) => `/${template.name}`));
1432
+ const promptCompactList = () => formatCompactList(templates.map((template) => `/${template.name}`));
1386
1433
  addLoadedSection("Prompts", promptCompactList, templateList);
1387
1434
  }
1388
1435
  if (extensions.length > 0) {
1389
1436
  const groups = this.buildScopeGroups(extensions);
1390
- const extList = this.formatScopeGroups(groups, {
1437
+ const extList = () => this.formatScopeGroups(groups, {
1391
1438
  formatPath: (item) => this.formatExtensionDisplayPath(item.path),
1392
1439
  formatPackagePath: (item) => this.formatExtensionDisplayPath(this.getShortPath(item.path, item.sourceInfo)),
1393
1440
  });
1394
- const extensionCompactList = formatCompactList(this.getCompactExtensionLabels(extensions));
1441
+ const extensionLabels = this.getCompactExtensionLabels(extensions);
1442
+ const extensionCompactList = () => formatCompactList(extensionLabels);
1395
1443
  addLoadedSection("Extensions", extensionCompactList, extList, "mdHeading");
1396
1444
  }
1397
- // Show loaded themes (excluding built-in)
1398
- const loadedThemes = themesResult.themes;
1399
- const customThemes = loadedThemes.filter((t) => t.sourcePath);
1400
- if (customThemes.length > 0) {
1401
- const groups = this.buildScopeGroups(customThemes.map((loadedTheme) => ({
1402
- path: loadedTheme.sourcePath,
1403
- sourceInfo: loadedTheme.sourceInfo,
1404
- })));
1405
- const themeList = this.formatScopeGroups(groups, {
1406
- formatPath: (item) => this.formatDisplayPath(item.path),
1407
- formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
1408
- });
1409
- const themeCompactList = formatCompactList(customThemes.map((loadedTheme) => loadedTheme.name ?? this.getCompactPathLabel(loadedTheme.sourcePath, loadedTheme.sourceInfo)));
1410
- addLoadedSection("Themes", themeCompactList, themeList);
1411
- }
1412
1445
  }
1413
1446
  if (showDiagnostics) {
1414
1447
  const skillDiagnostics = skillsResult.diagnostics;
1415
1448
  if (skillDiagnostics.length > 0) {
1416
- const warningLines = this.formatDiagnostics(skillDiagnostics, sourceInfos);
1417
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Skill conflicts]")}\n${warningLines}`, 0, 0));
1449
+ const warningLines = () => this.formatDiagnostics(skillDiagnostics, sourceInfos);
1450
+ this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Skill conflicts]")}\n${warningLines()}`, 0, 0));
1418
1451
  this.loadedResourcesContainer.addChild(new Spacer(1));
1419
1452
  }
1420
1453
  const promptDiagnostics = promptsResult.diagnostics;
1421
1454
  if (promptDiagnostics.length > 0) {
1422
- const warningLines = this.formatDiagnostics(promptDiagnostics, sourceInfos);
1423
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Prompt conflicts]")}\n${warningLines}`, 0, 0));
1455
+ const warningLines = () => this.formatDiagnostics(promptDiagnostics, sourceInfos);
1456
+ this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Prompt conflicts]")}\n${warningLines()}`, 0, 0));
1424
1457
  this.loadedResourcesContainer.addChild(new Spacer(1));
1425
1458
  }
1426
1459
  const extensionDiagnostics = [];
1427
- const extensionErrors = this.session.resourceLoader.getExtensions().errors;
1428
- if (extensionErrors.length > 0) {
1429
- for (const error of extensionErrors) {
1430
- extensionDiagnostics.push({ type: "error", message: error.error, path: error.path });
1431
- }
1460
+ const extensionsResult = this.session.resourceLoader.getExtensions();
1461
+ for (const error of extensionsResult.errors) {
1462
+ extensionDiagnostics.push({ type: "error", message: error.error, path: error.path });
1463
+ }
1464
+ for (const warning of extensionsResult.warnings ?? []) {
1465
+ extensionDiagnostics.push({ type: "warning", message: warning.warning, path: warning.path });
1432
1466
  }
1433
1467
  const commandDiagnostics = this.session.extensionRunner.getCommandDiagnostics();
1434
1468
  extensionDiagnostics.push(...commandDiagnostics);
@@ -1436,14 +1470,14 @@ export class InteractiveMode {
1436
1470
  const shortcutDiagnostics = this.session.extensionRunner.getShortcutDiagnostics();
1437
1471
  extensionDiagnostics.push(...shortcutDiagnostics);
1438
1472
  if (extensionDiagnostics.length > 0) {
1439
- const warningLines = this.formatDiagnostics(extensionDiagnostics, sourceInfos);
1440
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Extension issues]")}\n${warningLines}`, 0, 0));
1473
+ const warningLines = () => this.formatDiagnostics(extensionDiagnostics, sourceInfos);
1474
+ this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Extension issues]")}\n${warningLines()}`, 0, 0));
1441
1475
  this.loadedResourcesContainer.addChild(new Spacer(1));
1442
1476
  }
1443
1477
  const themeDiagnostics = themesResult.diagnostics;
1444
1478
  if (themeDiagnostics.length > 0) {
1445
- const warningLines = this.formatDiagnostics(themeDiagnostics, sourceInfos);
1446
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Theme conflicts]")}\n${warningLines}`, 0, 0));
1479
+ const warningLines = () => this.formatDiagnostics(themeDiagnostics, sourceInfos);
1480
+ this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Theme conflicts]")}\n${warningLines()}`, 0, 0));
1447
1481
  this.loadedResourcesContainer.addChild(new Spacer(1));
1448
1482
  }
1449
1483
  }
@@ -1535,6 +1569,7 @@ export class InteractiveMode {
1535
1569
  this.applyFullscreenScrollbarSetting();
1536
1570
  if (this.renderer instanceof TuiAltScreen) {
1537
1571
  this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
1572
+ this.renderer.setWheelScrollLines(this.settingsManager.getFullscreenWheelScrollLines());
1538
1573
  }
1539
1574
  this.footer.setSession(this.session);
1540
1575
  this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
@@ -1581,10 +1616,11 @@ export class InteractiveMode {
1581
1616
  this.showError(`${prefix}: ${message}`);
1582
1617
  const extensionHint = this.getCrashExtensionHint(error);
1583
1618
  if (extensionHint) {
1584
- this.chatContainer.addChild(new Text(theme.fg("warning", extensionHint), this.outputPad, 0));
1619
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", extensionHint), this.outputPad, 0));
1585
1620
  }
1586
1621
  if (this.recordCrash("fatal_error", error)) {
1587
- this.chatContainer.addChild(new Text(theme.fg("muted", this.crashReportInstructions()), this.outputPad, 0));
1622
+ const instructions = this.crashReportInstructions();
1623
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("muted", instructions), this.outputPad, 0));
1588
1624
  }
1589
1625
  stopThemeWatcher();
1590
1626
  this.stop("transcript");
@@ -1620,7 +1656,7 @@ export class InteractiveMode {
1620
1656
  if (this.bugReportHintShown)
1621
1657
  return;
1622
1658
  this.bugReportHintShown = true;
1623
- this.chatContainer.addChild(new Text(theme.fg("muted", `If this looks like a ${APP_NAME} bug, /bug sends a report to the developers.`), this.outputPad, 0));
1659
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("muted", `If this looks like a ${APP_NAME} bug, /bug sends a report to the developers.`), this.outputPad, 0));
1624
1660
  this.ui.requestRender();
1625
1661
  }
1626
1662
  maybeSuggestBugReport(message) {
@@ -1874,7 +1910,7 @@ export class InteractiveMode {
1874
1910
  container.addChild(new Text(line, 1, 0));
1875
1911
  }
1876
1912
  if (content.length > InteractiveMode.MAX_WIDGET_LINES) {
1877
- container.addChild(new Text(theme.fg("muted", "... (widget truncated)"), 1, 0));
1913
+ container.addChild(new ThemedText(() => theme.fg("muted", "... (widget truncated)"), 1, 0));
1878
1914
  }
1879
1915
  component = container;
1880
1916
  }
@@ -2404,17 +2440,14 @@ export class InteractiveMode {
2404
2440
  */
2405
2441
  showExtensionError(extensionPath, error, stack) {
2406
2442
  const errorMsg = `Extension "${extensionPath}" error: ${error}`;
2407
- const errorText = new Text(theme.fg("error", errorMsg), 1, 0);
2443
+ const errorText = new ThemedText(() => theme.fg("error", errorMsg), 1, 0);
2408
2444
  this.chatContainer.addChild(errorText);
2409
2445
  if (stack) {
2410
2446
  // Show stack trace in dim color, indented
2411
- const stackLines = stack
2412
- .split("\n")
2413
- .slice(1) // Skip first line (duplicates error message)
2414
- .map((line) => theme.fg("dim", ` ${line.trim()}`))
2415
- .join("\n");
2416
- if (stackLines) {
2417
- this.chatContainer.addChild(new Text(stackLines, 1, 0));
2447
+ const stackLines = stack.split("\n").slice(1); // Skip first line (duplicates error message)
2448
+ if (stackLines.length > 0) {
2449
+ const renderStack = () => stackLines.map((line) => theme.fg("dim", ` ${line.trim()}`)).join("\n");
2450
+ this.chatContainer.addChild(new ThemedText(renderStack, 1, 0));
2418
2451
  }
2419
2452
  }
2420
2453
  this.ui.requestRender();
@@ -2517,8 +2550,8 @@ export class InteractiveMode {
2517
2550
  this.updateEditorBorderColor();
2518
2551
  }
2519
2552
  };
2520
- // Handle clipboard paste (triggered on Ctrl+V). Images are attached by path;
2521
- // otherwise, paste plain text from the system clipboard.
2553
+ // Handle clipboard paste (triggered on Ctrl+V). Copied files use their original paths,
2554
+ // images are attached via temporary files, and plain text is the final fallback.
2522
2555
  this.defaultEditor.onPasteImage = () => {
2523
2556
  void this.handleClipboardPaste();
2524
2557
  };
@@ -2541,6 +2574,22 @@ export class InteractiveMode {
2541
2574
  }
2542
2575
  async handleClipboardPaste() {
2543
2576
  try {
2577
+ const filePaths = await readClipboardFilePaths();
2578
+ if (filePaths) {
2579
+ if (filePaths.some((filePath) => /\p{Cc}/u.test(filePath))) {
2580
+ throw new Error("Clipboard file path contains control characters");
2581
+ }
2582
+ const paths = this.isBashMode ? filePaths.map(quoteIfNeeded).join(" ") : filePaths.join("\n");
2583
+ const cursor = this.editor.getCursor?.();
2584
+ const currentLine = cursor ? (this.editor.getText().split("\n")[cursor.line] ?? "") : "";
2585
+ const characterBeforeCursor = cursor && cursor.col > 0 ? currentLine[cursor.col - 1] : "";
2586
+ const characterAfterCursor = cursor ? currentLine[cursor.col] : "";
2587
+ const leadingSpace = characterBeforeCursor && !/\s/.test(characterBeforeCursor) ? " " : "";
2588
+ const trailingSpace = characterAfterCursor && !/\s/.test(characterAfterCursor) ? " " : "";
2589
+ this.editor.insertTextAtCursor?.(`${leadingSpace}${paths}${trailingSpace}`);
2590
+ this.ui.requestRender();
2591
+ return;
2592
+ }
2544
2593
  const image = await readClipboardImage();
2545
2594
  if (image) {
2546
2595
  const tmpDir = os.tmpdir();
@@ -2558,8 +2607,8 @@ export class InteractiveMode {
2558
2607
  this.ui.requestRender();
2559
2608
  }
2560
2609
  }
2561
- catch {
2562
- // Silently ignore clipboard errors (may not have permission, etc.)
2610
+ catch (error) {
2611
+ this.showError(`Failed to paste from clipboard: ${error instanceof Error ? error.message : String(error)}`);
2563
2612
  }
2564
2613
  }
2565
2614
  handleStartupSubmit(text) {
@@ -2988,6 +3037,9 @@ export class InteractiveMode {
2988
3037
  // The bash execution callback handles TUI output rendering.
2989
3038
  break;
2990
3039
  case "tool_execution_start": {
3040
+ // Nested calls (from codemode scripts) are shown inside their parent's row.
3041
+ if (event.parentToolCallId)
3042
+ break;
2991
3043
  let component = this.pendingTools.get(event.toolCallId);
2992
3044
  if (!component) {
2993
3045
  component = new ToolExecutionComponent(event.toolName, event.toolCallId, event.args, {
@@ -3097,7 +3149,8 @@ export class InteractiveMode {
3097
3149
  }
3098
3150
  else {
3099
3151
  this.chatContainer.addChild(new Spacer(1));
3100
- this.chatContainer.addChild(new Text(theme.fg("error", event.errorMessage), 1, 0));
3152
+ const errorMessage = event.errorMessage;
3153
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("error", errorMessage), 1, 0));
3101
3154
  }
3102
3155
  }
3103
3156
  if (this.session.isAborting) {
@@ -3186,7 +3239,7 @@ export class InteractiveMode {
3186
3239
  }
3187
3240
  const message = status.type === "warning" ? `Warning: ${status.message}` : status.message;
3188
3241
  const color = status.type === "warning" ? "warning" : "dim";
3189
- this.chatContainer.addChild(new Text(theme.fg(color, message), 1, 0));
3242
+ this.chatContainer.addChild(new ThemedText(() => theme.fg(color, message), 1, 0));
3190
3243
  this.lastStatusSpacer = undefined;
3191
3244
  this.lastStatusText = undefined;
3192
3245
  this.ui.requestRender();
@@ -3202,12 +3255,14 @@ export class InteractiveMode {
3202
3255
  const last = children.length > 0 ? children[children.length - 1] : undefined;
3203
3256
  const secondLast = children.length > 1 ? children[children.length - 2] : undefined;
3204
3257
  if (last && secondLast && last === this.lastStatusText && secondLast === this.lastStatusSpacer) {
3205
- this.lastStatusText.setText(theme.fg("dim", message));
3258
+ this.lastStatusMessage = message;
3259
+ this.lastStatusText.invalidate();
3206
3260
  this.ui.requestRender();
3207
3261
  return;
3208
3262
  }
3209
3263
  const spacer = new Spacer(1);
3210
- const text = new Text(theme.fg("dim", message), 1, 0);
3264
+ this.lastStatusMessage = message;
3265
+ const text = new ThemedText(() => theme.fg("dim", this.lastStatusMessage), 1, 0);
3211
3266
  this.chatContainer.addChild(spacer);
3212
3267
  this.chatContainer.addChild(text);
3213
3268
  this.lastStatusSpacer = spacer;
@@ -3416,7 +3471,8 @@ export class InteractiveMode {
3416
3471
  if (!this.settingsManager.getShowCacheMissNotices())
3417
3472
  return;
3418
3473
  this.chatContainer.addChild(new Spacer(1));
3419
- this.chatContainer.addChild(new Text(theme.fg("dim", formatCacheWarmingUsage(entry)), 1, 0));
3474
+ const usage = formatCacheWarmingUsage(entry);
3475
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("dim", usage), 1, 0));
3420
3476
  }
3421
3477
  /**
3422
3478
  * Render billing usage for a compaction or branch summary. The notice is derived
@@ -3430,7 +3486,7 @@ export class InteractiveMode {
3430
3486
  const cost = usage.cost.total >= 0.01 ? ` (~$${usage.cost.total.toFixed(2)})` : "";
3431
3487
  const label = notice.kind === "compaction" ? "Compaction" : "Branch summary";
3432
3488
  this.chatContainer.addChild(new Spacer(1));
3433
- this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
3489
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
3434
3490
  }
3435
3491
  static countDroppedThinkingBlocks(message) {
3436
3492
  let count = 0;
@@ -3467,7 +3523,7 @@ export class InteractiveMode {
3467
3523
  return;
3468
3524
  const noun = droppedCount === 1 ? "thinking block" : "thinking blocks";
3469
3525
  this.chatContainer.addChild(new Spacer(1));
3470
- this.chatContainer.addChild(new Text(theme.fg("warning", `Anthropic dropped ${droppedCount} ${noun} (details in session)`), 1, 0));
3526
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `Anthropic dropped ${droppedCount} ${noun} (details in session)`), 1, 0));
3471
3527
  }
3472
3528
  /**
3473
3529
  * Show a transcript notice when a completed assistant message paid for a
@@ -3494,9 +3550,8 @@ export class InteractiveMode {
3494
3550
  else if (miss.idleMs >= CACHE_TTL_MS) {
3495
3551
  label = `Cache miss after ${Math.round(miss.idleMs / 60_000)}m idle`;
3496
3552
  }
3497
- const text = theme.fg("warning", `${label}: ${reBilled}`);
3498
3553
  this.chatContainer.addChild(new Spacer(1));
3499
- this.chatContainer.addChild(new Text(text, 1, 0));
3554
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `${label}: ${reBilled}`), 1, 0));
3500
3555
  }
3501
3556
  renderInitialMessages() {
3502
3557
  const entries = this.sessionManager.buildContextEntries();
@@ -3520,7 +3575,7 @@ export class InteractiveMode {
3520
3575
  if (this.chatContainer.children.length > 0) {
3521
3576
  this.chatContainer.addChild(new Spacer(1));
3522
3577
  }
3523
- this.chatContainer.addChild(new Text(theme.fg("warning", `This project is not trusted. Project ${CONFIG_DIR_NAME} resources and packages are ignored. Use /trust to save a trust decision, then restart pi.`), 1, 0));
3578
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `This project is not trusted. Project ${CONFIG_DIR_NAME} resources and packages are ignored. Use /trust to save a trust decision, then restart pi.`), 1, 0));
3524
3579
  }
3525
3580
  async getUserInput() {
3526
3581
  const queuedInput = this.pendingUserInputs.shift();
@@ -3871,26 +3926,28 @@ export class InteractiveMode {
3871
3926
  }
3872
3927
  showError(errorMessage) {
3873
3928
  this.chatContainer.addChild(new Spacer(1));
3874
- this.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage}`), this.outputPad, 0));
3929
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("error", `Error: ${errorMessage}`), this.outputPad, 0));
3875
3930
  this.ui.requestRender();
3876
3931
  }
3877
3932
  showWarning(warningMessage) {
3878
3933
  this.chatContainer.addChild(new Spacer(1));
3879
- this.chatContainer.addChild(new Text(theme.fg("warning", `Warning: ${warningMessage}`), 1, 0));
3934
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `Warning: ${warningMessage}`), 1, 0));
3880
3935
  this.ui.requestRender();
3881
3936
  }
3882
3937
  showNewVersionNotification(release) {
3883
- const action = theme.fg("accent", `${APP_NAME} update`);
3884
- const updateInstruction = theme.fg("muted", `New version ${release.version} is available. Run `) + action;
3938
+ const updateInstruction = () => theme.fg("muted", `New version ${release.version} is available. Run `) +
3939
+ theme.fg("accent", `${APP_NAME} update`);
3885
3940
  const changelogUrl = "https://pi.dev/changelog";
3886
- const changelogLink = getCapabilities().hyperlinks
3887
- ? hyperlink(theme.fg("accent", changelogUrl), changelogUrl)
3888
- : theme.fg("accent", changelogUrl);
3889
- const changelogLine = theme.fg("muted", "Changelog: ") + changelogLink;
3941
+ const changelogLine = () => {
3942
+ const changelogLink = getCapabilities().hyperlinks
3943
+ ? hyperlink(theme.fg("accent", changelogUrl), changelogUrl)
3944
+ : theme.fg("accent", changelogUrl);
3945
+ return theme.fg("muted", "Changelog: ") + changelogLink;
3946
+ };
3890
3947
  const note = release.note?.trim();
3891
3948
  this.chatContainer.addChild(new Spacer(1));
3892
3949
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
3893
- this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Update Available"))}\n${updateInstruction}`, 1, 0));
3950
+ this.chatContainer.addChild(new ThemedText(() => `${theme.bold(theme.fg("warning", "Update Available"))}\n${updateInstruction()}`, 1, 0));
3894
3951
  if (note) {
3895
3952
  this.chatContainer.addChild(new Spacer(1));
3896
3953
  this.chatContainer.addChild(new Markdown(note, 1, 0, this.getMarkdownThemeWithSettings(), {
@@ -3898,17 +3955,17 @@ export class InteractiveMode {
3898
3955
  }));
3899
3956
  this.chatContainer.addChild(new Spacer(1));
3900
3957
  }
3901
- this.chatContainer.addChild(new Text(changelogLine, 1, 0));
3958
+ this.chatContainer.addChild(new ThemedText(changelogLine, 1, 0));
3902
3959
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
3903
3960
  this.ui.requestRender();
3904
3961
  }
3905
3962
  showPackageUpdateNotification(packages) {
3906
- const action = theme.fg("accent", `${APP_NAME} update --extensions`);
3907
- const updateInstruction = theme.fg("muted", "Package updates are available. Run ") + action;
3963
+ const updateInstruction = () => theme.fg("muted", "Package updates are available. Run ") +
3964
+ theme.fg("accent", `${APP_NAME} update --extensions`);
3908
3965
  const packageLines = packages.map((pkg) => `- ${pkg}`).join("\n");
3909
3966
  this.chatContainer.addChild(new Spacer(1));
3910
3967
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
3911
- this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Package Updates Available"))}\n${updateInstruction}\n${theme.fg("muted", "Packages:")}\n${packageLines}`, 1, 0));
3968
+ this.chatContainer.addChild(new ThemedText(() => `${theme.bold(theme.fg("warning", "Package Updates Available"))}\n${updateInstruction()}\n${theme.fg("muted", "Packages:")}\n${packageLines}`, 1, 0));
3912
3969
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
3913
3970
  this.ui.requestRender();
3914
3971
  }
@@ -4156,7 +4213,7 @@ export class InteractiveMode {
4156
4213
  thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
4157
4214
  availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
4158
4215
  modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
4159
- currentTheme: this.themeController.getThemeSelection() || "dark",
4216
+ currentTheme: this.themeController.getThemeSelection() || SYSTEM_THEME_NAME,
4160
4217
  terminalTheme: this.themeController.getTerminalTheme(),
4161
4218
  availableThemes: getAvailableThemes(),
4162
4219
  hideThinkingBlock: this.hideThinkingBlock,
@@ -4178,6 +4235,7 @@ export class InteractiveMode {
4178
4235
  fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
4179
4236
  fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
4180
4237
  fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
4238
+ fullscreenWheelScrollLines: this.settingsManager.getFullscreenWheelScrollLines(),
4181
4239
  warnings: this.settingsManager.getWarnings(),
4182
4240
  }, {
4183
4241
  onAutoCompactChange: (enabled) => {
@@ -4252,7 +4310,7 @@ export class InteractiveMode {
4252
4310
  },
4253
4311
  onThemeChange: (themeSetting) => {
4254
4312
  this.settingsManager.setTheme(themeSetting);
4255
- void this.themeController.setThemeSetting(themeSetting);
4313
+ this.themeController.setThemeSetting(themeSetting);
4256
4314
  },
4257
4315
  onThemePreview: (themeName) => this.themeController.preview(themeName),
4258
4316
  onHideThinkingBlockChange: (hidden) => {
@@ -4275,8 +4333,8 @@ export class InteractiveMode {
4275
4333
  onEnableInstallTelemetryChange: (enabled) => {
4276
4334
  this.settingsManager.setEnableInstallTelemetry(enabled);
4277
4335
  },
4278
- onQuietStartupChange: (enabled) => {
4279
- this.settingsManager.setQuietStartup(enabled);
4336
+ onQuietStartupChange: (quiet) => {
4337
+ this.settingsManager.setQuietStartup(quiet);
4280
4338
  },
4281
4339
  onDefaultProjectTrustChange: (defaultProjectTrust) => {
4282
4340
  this.settingsManager.setDefaultProjectTrust(defaultProjectTrust);
@@ -4357,6 +4415,11 @@ export class InteractiveMode {
4357
4415
  if (this.renderer instanceof TuiAltScreen)
4358
4416
  this.renderer.setCopyOnSelect(enabled);
4359
4417
  },
4418
+ onFullscreenWheelScrollLinesChange: (lines) => {
4419
+ this.settingsManager.setFullscreenWheelScrollLines(lines);
4420
+ if (this.renderer instanceof TuiAltScreen)
4421
+ this.renderer.setWheelScrollLines(lines);
4422
+ },
4360
4423
  onWarningsChange: (warnings) => {
4361
4424
  this.settingsManager.setWarnings(warnings);
4362
4425
  },
@@ -4923,6 +4986,7 @@ export class InteractiveMode {
4923
4986
  source: authStatus.label ?? authStatus.source,
4924
4987
  }
4925
4988
  : undefined;
4989
+ const subscription = provider.auth.oauth?.isSubscription === true;
4926
4990
  if ((!authType || authType === "oauth") && provider.auth.oauth) {
4927
4991
  options.push({
4928
4992
  id: provider.id,
@@ -4930,6 +4994,7 @@ export class InteractiveMode {
4930
4994
  authType: "oauth",
4931
4995
  method: provider.auth.oauth,
4932
4996
  status,
4997
+ subscription,
4933
4998
  });
4934
4999
  }
4935
5000
  if ((!authType || authType === "api_key") && provider.auth.apiKey) {
@@ -4939,6 +5004,7 @@ export class InteractiveMode {
4939
5004
  authType: "api_key",
4940
5005
  method: provider.auth.apiKey,
4941
5006
  status,
5007
+ subscription,
4942
5008
  });
4943
5009
  }
4944
5010
  }
@@ -4946,12 +5012,16 @@ export class InteractiveMode {
4946
5012
  }
4947
5013
  async getLogoutProviderOptions() {
4948
5014
  return (await this.session.modelRuntime.listCredentials({ signal: AbortSignal.timeout(15_000) }))
4949
- .map(({ providerId, type }) => ({
4950
- id: providerId,
4951
- name: this.session.modelRuntime.getProvider(providerId)?.name ?? providerId,
4952
- authType: type,
4953
- status: { type, source: "stored credential" },
4954
- }))
5015
+ .map(({ providerId, type }) => {
5016
+ const provider = this.session.modelRuntime.getProvider(providerId);
5017
+ return {
5018
+ id: providerId,
5019
+ name: provider?.name ?? providerId,
5020
+ authType: type,
5021
+ status: { type, source: "stored credential" },
5022
+ subscription: provider?.auth.oauth?.isSubscription === true,
5023
+ };
5024
+ })
4955
5025
  .sort((a, b) => a.name.localeCompare(b.name));
4956
5026
  }
4957
5027
  findLoginProviderOptions(providerRef) {
@@ -4981,18 +5051,25 @@ export class InteractiveMode {
4981
5051
  }
4982
5052
  this.showLoginProviderSelector(undefined, providerRef);
4983
5053
  }
4984
- async startProviderLogin(providerOption) {
5054
+ /** `onBack` reopens the selector the login was started from when the user cancels it. */
5055
+ async startProviderLogin(providerOption, onBack) {
4985
5056
  if (providerOption.authType === "oauth") {
4986
- await this.showLoginDialog(providerOption.id, providerOption.name);
5057
+ await this.showLoginDialog(providerOption.id, providerOption.name, onBack);
4987
5058
  }
4988
5059
  else if (providerOption.method?.login) {
4989
- await this.showApiKeyLoginDialog(providerOption.id, providerOption.name);
5060
+ await this.showApiKeyLoginDialog(providerOption.id, providerOption.name, onBack);
4990
5061
  }
4991
5062
  else {
4992
- this.showAmbientAuthDialog(providerOption);
5063
+ this.showAmbientAuthDialog(providerOption, onBack);
4993
5064
  }
4994
5065
  }
4995
5066
  showLoginAuthTypeSelector(providerOptions) {
5067
+ // The top-level selector offers Radius directly, as its last option.
5068
+ const radiusOption = providerOptions
5069
+ ? undefined
5070
+ : this.getLoginProviderOptions("oauth").find((provider) => provider.id === RADIUS_PROVIDER_ID);
5071
+ const radiusText = radiusOption ? `Sign in with ${radiusOption.name}` : undefined;
5072
+ const radiusLabel = radiusOption ? `${radiusText}${formatAuthSelectorProviderStatus(radiusOption)}` : undefined;
4996
5073
  const oauthProvider = providerOptions?.find((provider) => provider.authType === "oauth");
4997
5074
  const oauthLoginLabel = oauthProvider?.method && "loginLabel" in oauthProvider.method ? oauthProvider.method.loginLabel : undefined;
4998
5075
  const subscriptionLabel = oauthLoginLabel ?? "Sign in with an account";
@@ -5007,6 +5084,8 @@ export class InteractiveMode {
5007
5084
  if (availableAuthTypes.has("api_key")) {
5008
5085
  options.push(apiKeyLabel);
5009
5086
  }
5087
+ if (radiusLabel)
5088
+ options.push(radiusLabel);
5010
5089
  if (options.length === 0) {
5011
5090
  this.showStatus("No login methods available.");
5012
5091
  return;
@@ -5022,29 +5101,37 @@ export class InteractiveMode {
5022
5101
  ? `Select authentication method for ${providerOptions[0].name}:`
5023
5102
  : "Select authentication method:";
5024
5103
  this.showSelector((done) => {
5025
- const selector = new ExtensionSelectorComponent(title, options, (option) => {
5104
+ const onSelect = (option) => {
5026
5105
  done();
5106
+ if (radiusOption && option === radiusLabel) {
5107
+ void this.startProviderLogin(radiusOption, () => this.showLoginAuthTypeSelector());
5108
+ return;
5109
+ }
5027
5110
  const authType = option === subscriptionLabel ? "oauth" : "api_key";
5028
5111
  if (providerOptions) {
5029
5112
  const providerOption = providerOptions.find((provider) => provider.authType === authType);
5030
5113
  if (providerOption) {
5031
- void this.startProviderLogin(providerOption);
5114
+ void this.startProviderLogin(providerOption, () => this.showLoginAuthTypeSelector(providerOptions));
5032
5115
  }
5033
5116
  return;
5034
5117
  }
5035
5118
  this.showLoginProviderSelector(authType);
5036
- }, () => {
5119
+ };
5120
+ const onCancel = () => {
5037
5121
  done();
5038
5122
  this.ui.requestRender();
5039
- });
5040
- return { component: selector, focus: selector };
5123
+ };
5124
+ const selector = radiusLabel && radiusText
5125
+ ? createLoginMenuSelector(this.ui, title, options, { label: radiusLabel, text: radiusText }, onSelect, onCancel)
5126
+ : new ExtensionSelectorComponent(title, options, onSelect, onCancel);
5127
+ return { component: selector, focus: selector, dispose: () => selector.dispose() };
5041
5128
  });
5042
5129
  }
5043
5130
  showLoginProviderSelector(authType, initialSearchInput) {
5044
5131
  const providerOptions = this.getLoginProviderOptions(authType);
5045
5132
  if (providerOptions.length === 0) {
5046
5133
  const message = authType === "oauth"
5047
- ? "No subscription providers available."
5134
+ ? "No account providers available."
5048
5135
  : authType === "api_key"
5049
5136
  ? "No API key providers available."
5050
5137
  : "No login providers available.";
@@ -5058,7 +5145,7 @@ export class InteractiveMode {
5058
5145
  if (!providerOption) {
5059
5146
  return;
5060
5147
  }
5061
- await this.startProviderLogin(providerOption);
5148
+ await this.startProviderLogin(providerOption, () => this.showLoginProviderSelector(authType, initialSearchInput));
5062
5149
  }, () => {
5063
5150
  done();
5064
5151
  if (authType) {
@@ -5212,21 +5299,24 @@ export class InteractiveMode {
5212
5299
  })
5213
5300
  .finally(() => clearTimeout(timeout));
5214
5301
  }
5215
- showAmbientAuthDialog(providerOption) {
5302
+ showAmbientAuthDialog(providerOption, onBack) {
5216
5303
  const restoreEditor = () => {
5217
5304
  this.editorContainer.clear();
5218
5305
  this.editorContainer.addChild(this.editor);
5219
5306
  this.ui.setFocus(this.editor);
5220
5307
  this.ui.requestRender();
5221
5308
  };
5222
- const dialog = new LoginDialogComponent(this.ui, providerOption.id, () => restoreEditor(), providerOption.name, `${providerOption.name} setup`);
5309
+ const dialog = new LoginDialogComponent(this.ui, providerOption.id, () => {
5310
+ restoreEditor();
5311
+ onBack?.();
5312
+ }, providerOption.name, `${providerOption.name} setup`);
5223
5313
  dialog.showInfo(`${providerOption.method?.name ?? "Authentication"} is configured outside ${APP_NAME}.`, [], true);
5224
5314
  this.editorContainer.clear();
5225
5315
  this.editorContainer.addChild(dialog);
5226
5316
  this.ui.setFocus(dialog);
5227
5317
  this.ui.requestRender();
5228
5318
  }
5229
- async showApiKeyLoginDialog(providerId, providerName) {
5319
+ async showApiKeyLoginDialog(providerId, providerName, onBack) {
5230
5320
  const previousModel = this.session.model;
5231
5321
  const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => {
5232
5322
  // Completion handled below
@@ -5259,12 +5349,15 @@ export class InteractiveMode {
5259
5349
  if (error instanceof CredentialSynchronizationError) {
5260
5350
  this.showError(`Saved API key for ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
5261
5351
  }
5262
- else if (errorMsg !== "Login cancelled") {
5352
+ else if (errorMsg === "Login cancelled") {
5353
+ onBack?.();
5354
+ }
5355
+ else {
5263
5356
  this.showError(`Failed to save API key for ${providerName}: ${errorMsg}`);
5264
5357
  }
5265
5358
  }
5266
5359
  }
5267
- showAuthSelect(dialog, prompt) {
5360
+ showAuthSelect(dialog, prompt, providerId) {
5268
5361
  return new Promise((resolve, reject) => {
5269
5362
  const restoreDialog = () => {
5270
5363
  this.editorContainer.clear();
@@ -5283,17 +5376,17 @@ export class InteractiveMode {
5283
5376
  }, () => {
5284
5377
  restoreDialog();
5285
5378
  reject(new Error("Login cancelled"));
5286
- });
5379
+ }, { description: providerId === RADIUS_PROVIDER_ID ? RADIUS_LOGIN_INTRO : undefined });
5287
5380
  this.editorContainer.clear();
5288
5381
  this.editorContainer.addChild(selector);
5289
5382
  this.ui.setFocus(selector);
5290
5383
  this.ui.requestRender();
5291
5384
  });
5292
5385
  }
5293
- async showAuthPrompt(dialog, prompt) {
5386
+ async showAuthPrompt(dialog, prompt, providerId) {
5294
5387
  let response;
5295
5388
  if (prompt.type === "select") {
5296
- response = this.showAuthSelect(dialog, prompt);
5389
+ response = this.showAuthSelect(dialog, prompt, providerId);
5297
5390
  }
5298
5391
  else if (prompt.type === "manual_code") {
5299
5392
  response = dialog.showManualInput(prompt.message);
@@ -5337,11 +5430,11 @@ export class InteractiveMode {
5337
5430
  async loginProvider(dialog, providerId, method) {
5338
5431
  await this.session.modelRuntime.login(providerId, method, {
5339
5432
  signal: dialog.signal,
5340
- prompt: (prompt) => this.showAuthPrompt(dialog, prompt),
5433
+ prompt: (prompt) => this.showAuthPrompt(dialog, prompt, providerId),
5341
5434
  notify: (event) => this.notifyAuthDialog(dialog, event),
5342
- });
5435
+ }, { getDeviceId: () => this.settingsManager.getOrCreateDeviceId() });
5343
5436
  }
5344
- async showLoginDialog(providerId, providerName) {
5437
+ async showLoginDialog(providerId, providerName, onBack) {
5345
5438
  const previousModel = this.session.model;
5346
5439
  const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => { }, providerName);
5347
5440
  this.editorContainer.clear();
@@ -5358,6 +5451,8 @@ export class InteractiveMode {
5358
5451
  await this.loginProvider(dialog, providerId, "oauth");
5359
5452
  restoreEditor();
5360
5453
  await this.completeProviderAuthentication(providerId, providerName, "oauth", previousModel);
5454
+ if (providerId === RADIUS_PROVIDER_ID)
5455
+ this.offerRadiusMcpServer(providerId, providerName);
5361
5456
  }
5362
5457
  catch (error) {
5363
5458
  restoreEditor();
@@ -5365,11 +5460,58 @@ export class InteractiveMode {
5365
5460
  if (error instanceof CredentialSynchronizationError) {
5366
5461
  this.showError(`Logged in to ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
5367
5462
  }
5368
- else if (errorMsg !== "Login cancelled") {
5463
+ else if (errorMsg === "Login cancelled") {
5464
+ onBack?.();
5465
+ }
5466
+ else {
5369
5467
  this.showError(`Failed to login to ${providerName}: ${errorMsg}`);
5370
5468
  }
5371
5469
  }
5372
5470
  }
5471
+ /**
5472
+ * Offer to point the Radius MCP server in the global mcp.json at the Radius login, adding the server
5473
+ * when missing. Nothing is asked when a global server already uses this login.
5474
+ */
5475
+ offerRadiusMcpServer(providerId, providerName) {
5476
+ const mcpPath = path.join(getAgentDir(), "mcp.json");
5477
+ const normalizeUrl = (url) => url.replace(/\/+$/u, "");
5478
+ const { servers } = loadMcpConfig({
5479
+ agentDir: getAgentDir(),
5480
+ cwd: this.sessionManager.getCwd(),
5481
+ projectTrusted: false,
5482
+ });
5483
+ const existing = servers.find((server) => "url" in server.config && normalizeUrl(server.config.url) === normalizeUrl(RADIUS_MCP_URL));
5484
+ if (existing && "url" in existing.config && existing.config.auth?.provider === providerId)
5485
+ return;
5486
+ let name = existing?.name ?? "radius";
5487
+ if (!existing && servers.some((server) => server.name === name))
5488
+ name = "radius-mcp";
5489
+ const config = existing && "url" in existing.config
5490
+ ? { ...existing.config, auth: { provider: providerId } }
5491
+ : { url: RADIUS_MCP_URL, auth: { provider: providerId } };
5492
+ // `auth` replaces the MCP OAuth sign-in.
5493
+ delete config.oauth;
5494
+ this.showSelector((done) => {
5495
+ const selector = new ExtensionSelectorComponent(`Configure ${providerName} MCP in ${mcpPath}?`, ["Yes", "No"], (option) => {
5496
+ done();
5497
+ if (option !== "Yes")
5498
+ return;
5499
+ try {
5500
+ addMcpServerConfig(mcpPath, name, config);
5501
+ }
5502
+ catch (error) {
5503
+ this.showError(`Could not update ${mcpPath}: ${error instanceof Error ? error.message : String(error)}`);
5504
+ return;
5505
+ }
5506
+ // The MCP extension reads mcp.json when the session starts.
5507
+ void this.handleReloadCommand();
5508
+ }, () => {
5509
+ done();
5510
+ this.ui.requestRender();
5511
+ });
5512
+ return { component: selector, focus: selector };
5513
+ });
5514
+ }
5373
5515
  // =========================================================================
5374
5516
  // Command handlers
5375
5517
  // =========================================================================
@@ -5387,7 +5529,7 @@ export class InteractiveMode {
5387
5529
  const borderColor = (s) => theme.fg("border", s);
5388
5530
  reloadBox.addChild(new DynamicBorder(borderColor));
5389
5531
  reloadBox.addChild(new Spacer(1));
5390
- reloadBox.addChild(new Text(theme.fg("muted", "Reloading keybindings, extensions, skills, prompts, themes, and context files..."), 1, 0));
5532
+ reloadBox.addChild(new ThemedText(() => theme.fg("muted", "Reloading keybindings, extensions, skills, prompts, themes, and context files..."), 1, 0));
5391
5533
  reloadBox.addChild(new Spacer(1));
5392
5534
  reloadBox.addChild(new DynamicBorder(borderColor));
5393
5535
  const previousEditor = this.editor;
@@ -5423,7 +5565,7 @@ export class InteractiveMode {
5423
5565
  }
5424
5566
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
5425
5567
  this.applyRuntimeSettings();
5426
- await this.themeController.applyFromSettings();
5568
+ this.themeController.applyFromSettings();
5427
5569
  this.setupAutocompleteProvider();
5428
5570
  const runner = this.session.extensionRunner;
5429
5571
  this.setupExtensionShortcuts(runner);
@@ -5587,7 +5729,7 @@ export class InteractiveMode {
5587
5729
  const currentName = this.sessionManager.getSessionName();
5588
5730
  if (currentName) {
5589
5731
  this.chatContainer.addChild(new Spacer(1));
5590
- this.chatContainer.addChild(new Text(theme.fg("dim", `Session name: ${currentName}`), 1, 0));
5732
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("dim", `Session name: ${currentName}`), 1, 0));
5591
5733
  }
5592
5734
  else {
5593
5735
  this.showWarning("Usage: /name <name>");
@@ -5601,7 +5743,8 @@ export class InteractiveMode {
5601
5743
  this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName)}`);
5602
5744
  }
5603
5745
  this.chatContainer.addChild(new Spacer(1));
5604
- this.chatContainer.addChild(new Text(theme.fg("dim", `Session name set: ${sessionName ?? name}`), 1, 0));
5746
+ const displayName = sessionName ?? name;
5747
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("dim", `Session name set: ${displayName}`), 1, 0));
5605
5748
  this.ui.requestRender();
5606
5749
  }
5607
5750
  handleSessionCommand() {
@@ -5613,61 +5756,69 @@ export class InteractiveMode {
5613
5756
  // resolves to a concrete responseModel). Usage without model attribution is
5614
5757
  // grouped separately so the breakdown reconciles with the session total.
5615
5758
  const usageBreakdown = getUsageCostBreakdown(entries);
5616
- let info = `${theme.bold("Session Info")}\n\n`;
5617
- if (sessionName) {
5618
- info += `${theme.fg("dim", "Name:")} ${sessionName}\n`;
5619
- }
5620
- info += `${theme.fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
5621
- info += `${theme.fg("dim", "ID:")} ${stats.sessionId}\n\n`;
5622
- info += `${theme.bold("Messages")}\n`;
5623
- info += `${theme.fg("dim", "Total:")} ${stats.totalMessages}\n`;
5624
- info += `${theme.fg("dim", "User:")} ${stats.userMessages}\n`;
5625
- info += `${theme.fg("dim", "Assistant:")} ${stats.assistantMessages}\n`;
5626
- info += `${theme.fg("dim", "Tools:")} ${stats.toolCalls} calls, ${stats.toolResults} results\n\n`;
5627
- info += `${theme.bold("Tokens")}\n`;
5628
- // "Input" is the full prompt volume. With cache activity, split it into
5629
- // cached (served from cache) vs uncached (everything else) - the only
5630
- // provider-independent split. Cache writes, where reported, are a detail
5631
- // of the uncached portion.
5632
- const { input, cacheRead, cacheWrite } = stats.tokens;
5633
- const promptTokens = input + cacheRead + cacheWrite;
5634
- info += `${theme.fg("dim", "Input:")} ${promptTokens.toLocaleString()}\n`;
5635
- if (promptTokens > 0 && (cacheRead > 0 || cacheWrite > 0)) {
5636
- const hitRate = theme.fg("dim", `(${((cacheRead / promptTokens) * 100).toFixed(1)}%)`);
5637
- info += ` ${theme.fg("dim", "Cached:")} ${cacheRead.toLocaleString()} ${hitRate}\n`;
5638
- const written = cacheWrite > 0 ? ` ${theme.fg("dim", `(${cacheWrite.toLocaleString()} written to cache)`)}` : "";
5639
- info += ` ${theme.fg("dim", "Uncached:")} ${(input + cacheWrite).toLocaleString()}${written}\n`;
5640
- }
5641
- info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
5642
- info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
5759
+ // Snapshot the stats; the text is built on demand so it follows theme changes.
5643
5760
  const cacheWarmingStatus = this.session.cacheWarmingStatus;
5644
- info += `\n${theme.bold("Cache Warming")}\n`;
5645
- info += `${theme.fg("dim", "Mode:")} ${this.settingsManager.getCacheWarmingMode()}\n`;
5646
- info += `${theme.fg("dim", "Status:")} ${cacheWarmingStatus ? formatCacheWarmingStatus(cacheWarmingStatus) : "Inactive (cache warming unavailable)"}\n`;
5647
- const decision = cacheWarmingStatus?.decision;
5648
- if (decision?.economicsAvailable) {
5649
- info += `${theme.fg("dim", "Cache miss penalty:")} $${decision.missCost.toFixed(3)}\n`;
5650
- info += `${theme.fg("dim", "Refresh cost:")} $${decision.warmCost.toFixed(3)}\n`;
5651
- }
5652
- if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
5653
- info += `\n${theme.bold("Cost")}\n`;
5654
- info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
5655
- if (usageBreakdown.length > 1) {
5656
- for (const entry of usageBreakdown) {
5657
- info += `\n ${theme.fg("dim", `${entry.key}:`)} $${entry.cost.toFixed(3)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
5761
+ const cacheWarmingMode = this.settingsManager.getCacheWarmingMode();
5762
+ const model = this.session.model;
5763
+ const selectedModelKey = `${model?.provider}/${model?.id}`;
5764
+ const renderInfo = () => {
5765
+ let info = `${theme.bold("Session Info")}\n\n`;
5766
+ if (sessionName) {
5767
+ info += `${theme.fg("dim", "Name:")} ${sessionName}\n`;
5768
+ }
5769
+ info += `${theme.fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
5770
+ info += `${theme.fg("dim", "ID:")} ${stats.sessionId}\n\n`;
5771
+ info += `${theme.bold("Messages")}\n`;
5772
+ info += `${theme.fg("dim", "Total:")} ${stats.totalMessages}\n`;
5773
+ info += `${theme.fg("dim", "User:")} ${stats.userMessages}\n`;
5774
+ info += `${theme.fg("dim", "Assistant:")} ${stats.assistantMessages}\n`;
5775
+ info += `${theme.fg("dim", "Tools:")} ${stats.toolCalls} calls, ${stats.toolResults} results\n\n`;
5776
+ info += `${theme.bold("Tokens")}\n`;
5777
+ // "Input" is the full prompt volume. With cache activity, split it into
5778
+ // cached (served from cache) vs uncached (everything else) - the only
5779
+ // provider-independent split. Cache writes, where reported, are a detail
5780
+ // of the uncached portion.
5781
+ const { input, cacheRead, cacheWrite } = stats.tokens;
5782
+ const promptTokens = input + cacheRead + cacheWrite;
5783
+ info += `${theme.fg("dim", "Input:")} ${promptTokens.toLocaleString()}\n`;
5784
+ if (promptTokens > 0 && (cacheRead > 0 || cacheWrite > 0)) {
5785
+ const hitRate = theme.fg("dim", `(${((cacheRead / promptTokens) * 100).toFixed(1)}%)`);
5786
+ info += ` ${theme.fg("dim", "Cached:")} ${cacheRead.toLocaleString()} ${hitRate}\n`;
5787
+ const written = cacheWrite > 0 ? ` ${theme.fg("dim", `(${cacheWrite.toLocaleString()} written to cache)`)}` : "";
5788
+ info += ` ${theme.fg("dim", "Uncached:")} ${(input + cacheWrite).toLocaleString()}${written}\n`;
5789
+ }
5790
+ info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
5791
+ info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
5792
+ info += `\n${theme.bold("Cache Warming")}\n`;
5793
+ info += `${theme.fg("dim", "Mode:")} ${cacheWarmingMode}\n`;
5794
+ info += `${theme.fg("dim", "Status:")} ${cacheWarmingStatus ? formatCacheWarmingStatus(cacheWarmingStatus) : "Inactive (cache warming unavailable)"}\n`;
5795
+ const decision = cacheWarmingStatus?.decision;
5796
+ if (decision?.economicsAvailable) {
5797
+ info += `${theme.fg("dim", "Cache miss penalty:")} $${decision.missCost.toFixed(3)}\n`;
5798
+ info += `${theme.fg("dim", "Refresh cost:")} $${decision.warmCost.toFixed(3)}\n`;
5799
+ }
5800
+ if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
5801
+ info += `\n${theme.bold("Cost")}\n`;
5802
+ info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
5803
+ // A single entry repeats the total, unless it names a model other than the selected one.
5804
+ if (usageBreakdown.length > 1 || usageBreakdown[0]?.key !== selectedModelKey) {
5805
+ for (const entry of usageBreakdown) {
5806
+ info += `\n ${theme.fg("dim", `${entry.key}:`)} $${entry.cost.toFixed(3)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
5807
+ }
5808
+ }
5809
+ if (cacheWaste.missedTokens > 0) {
5810
+ const missLabel = cacheWaste.missCount === 1 ? "1 miss" : `${cacheWaste.missCount} misses`;
5811
+ const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
5812
+ info +=
5813
+ cacheWaste.missedCost >= 0.0001
5814
+ ? `\n${theme.fg("dim", "Cache Re-billed:")} $${cacheWaste.missedCost.toFixed(3)} ${theme.fg("dim", `(${detail})`)}`
5815
+ : `\n${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
5658
5816
  }
5659
5817
  }
5660
- if (cacheWaste.missedTokens > 0) {
5661
- const missLabel = cacheWaste.missCount === 1 ? "1 miss" : `${cacheWaste.missCount} misses`;
5662
- const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
5663
- info +=
5664
- cacheWaste.missedCost >= 0.0001
5665
- ? `\n${theme.fg("dim", "Cache Re-billed:")} $${cacheWaste.missedCost.toFixed(3)} ${theme.fg("dim", `(${detail})`)}`
5666
- : `\n${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
5667
- }
5668
- }
5818
+ return info;
5819
+ };
5669
5820
  this.chatContainer.addChild(new Spacer(1));
5670
- this.chatContainer.addChild(new Text(info, 1, 0));
5821
+ this.chatContainer.addChild(new ThemedText(renderInfo, 1, 0));
5671
5822
  this.ui.requestRender();
5672
5823
  }
5673
5824
  handleChangelogCommand() {
@@ -5681,7 +5832,7 @@ export class InteractiveMode {
5681
5832
  : "No changelog entries found.";
5682
5833
  this.chatContainer.addChild(new Spacer(1));
5683
5834
  this.chatContainer.addChild(new DynamicBorder());
5684
- this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
5835
+ this.chatContainer.addChild(new ThemedText(() => theme.bold(theme.fg("accent", "What's New")), 1, 0));
5685
5836
  this.chatContainer.addChild(new Spacer(1));
5686
5837
  this.chatContainer.addChild(new Markdown(changelogMarkdown, 1, 1, this.getMarkdownThemeWithSettings()));
5687
5838
  this.chatContainer.addChild(new DynamicBorder());
@@ -5782,7 +5933,7 @@ export class InteractiveMode {
5782
5933
  | \`${copyMessage}\` | Copy selection or last assistant message |
5783
5934
  | \`${followUp}\` | Queue follow-up message |
5784
5935
  | \`${dequeue}\` | Restore queued messages |
5785
- | \`${pasteImage}\` | Paste image or text from clipboard |
5936
+ | \`${pasteImage}\` | Paste files on macOS, images, or text from clipboard |
5786
5937
  | \`/\` | Slash commands |
5787
5938
  | \`!\` | Run bash command |
5788
5939
  | \`!!\` | Run bash command (excluded from context) |
@@ -5804,7 +5955,7 @@ export class InteractiveMode {
5804
5955
  }
5805
5956
  this.chatContainer.addChild(new Spacer(1));
5806
5957
  this.chatContainer.addChild(new DynamicBorder());
5807
- this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "Keyboard Shortcuts")), 1, 0));
5958
+ this.chatContainer.addChild(new ThemedText(() => theme.bold(theme.fg("accent", "Keyboard Shortcuts")), 1, 0));
5808
5959
  this.chatContainer.addChild(new Spacer(1));
5809
5960
  this.chatContainer.addChild(new Markdown(hotkeys.trim(), 1, 1, this.getMarkdownThemeWithSettings()));
5810
5961
  this.chatContainer.addChild(new DynamicBorder());
@@ -5818,7 +5969,7 @@ export class InteractiveMode {
5818
5969
  return;
5819
5970
  }
5820
5971
  this.chatContainer.addChild(new Spacer(1));
5821
- this.chatContainer.addChild(new Text(`${theme.fg("accent", "✓ New session started")}`, 1, 1));
5972
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("accent", "✓ New session started"), 1, 1));
5822
5973
  this.ui.requestRender();
5823
5974
  }
5824
5975
  catch (error) {
@@ -5849,7 +6000,7 @@ export class InteractiveMode {
5849
6000
  fs.mkdirSync(path.dirname(debugLogPath), { recursive: true });
5850
6001
  fs.writeFileSync(debugLogPath, debugData);
5851
6002
  this.chatContainer.addChild(new Spacer(1));
5852
- this.chatContainer.addChild(new Text(`${theme.fg("accent", "✓ Debug log written")}\n${theme.fg("muted", debugLogPath)}`, 1, 1));
6003
+ this.chatContainer.addChild(new ThemedText(() => `${theme.fg("accent", "✓ Debug log written")}\n${theme.fg("muted", debugLogPath)}`, 1, 1));
5853
6004
  this.ui.requestRender();
5854
6005
  }
5855
6006
  handleArminSaysHi() {