@astralyn/pi 0.87.6 → 1.0.0

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 (924) hide show
  1. package/CHANGELOG.md +69 -9
  2. package/README.md +3 -3
  3. package/dist/bun/runtime-setup.js +4 -1
  4. package/dist/bun/runtime-setup.js.map +1 -1
  5. package/dist/bundle/chunks/anthropic-messages-CG2BSDQS.js +6 -0
  6. package/dist/bundle/chunks/anthropic.js +2 -2
  7. package/dist/bundle/chunks/azure-openai-responses-PBA4QKCM.js +2 -0
  8. package/dist/bundle/chunks/bedrock-converse-stream.js +8 -8
  9. package/dist/bundle/chunks/{chunk-NW5FIDD7.js → chunk-6UFFVA7M.js} +3 -3
  10. package/dist/bundle/chunks/chunk-G4RY3GN7.js +11 -0
  11. package/dist/bundle/chunks/chunk-GCKVOFWP.js +2 -0
  12. package/dist/bundle/chunks/chunk-GIG5IHES.js +2 -0
  13. package/dist/bundle/chunks/{chunk-4W4Q2H6W.js → chunk-HESRDUKO.js} +1000 -625
  14. package/dist/bundle/chunks/chunk-MPDALHNJ.js +2 -0
  15. package/dist/bundle/chunks/chunk-OO6DJ3CL.js +31 -0
  16. package/dist/bundle/chunks/{chunk-LPQCB2VJ.js → chunk-PFZKRUMO.js} +2 -2
  17. package/dist/bundle/chunks/chunk-SGLYRVQL.js +2 -0
  18. package/dist/bundle/chunks/chunk-TRHTWM3C.js +2 -0
  19. package/dist/bundle/chunks/chunk-V66VGGOM.js +2 -0
  20. package/dist/bundle/chunks/chunk-Z2RKSI3O.js +2 -0
  21. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-YB7XPPP4.js +2 -0
  22. package/dist/bundle/chunks/codemode-worker.js +354 -0
  23. package/dist/bundle/chunks/github-copilot.js +1 -1
  24. package/dist/bundle/chunks/google-generative-ai-V5ZM5MCL.js +2 -0
  25. package/dist/bundle/chunks/google-vertex-22THOFP5.js +2 -0
  26. package/dist/bundle/chunks/llama-cpp-classify-R7DQLTQN.js +22 -0
  27. package/dist/bundle/chunks/meta.js +2 -0
  28. package/dist/bundle/chunks/mistral-conversations-WHSCJJWP.js +5 -0
  29. package/dist/bundle/chunks/openai-chatgpt.js +75 -0
  30. package/dist/bundle/chunks/openai-codex-responses-N7GDPBPP.js +10 -0
  31. package/dist/bundle/chunks/openai-codex.js +2 -2
  32. package/dist/bundle/chunks/openai-completions-RGGQK5UW.js +7 -0
  33. package/dist/bundle/chunks/openai-responses-3ZLD5JYI.js +3 -0
  34. package/dist/bundle/chunks/{openrouter-images-6XDE2CEW.js → openrouter-images-YP3YVB54.js} +1 -1
  35. package/dist/bundle/chunks/openrouter.js +2 -2
  36. package/dist/bundle/chunks/{pi-messages-MQMPIPNC.js → pi-messages-HZZ7GEEW.js} +2 -2
  37. package/dist/bundle/chunks/radius.js +2 -2
  38. package/dist/bundle/chunks/typesafe-system-one-RREJAKWB.js +2 -0
  39. package/dist/bundle/chunks/virtual-modules-4RQ2L6W4.js +2 -0
  40. package/dist/bundle/cli.js +1 -1
  41. package/dist/bundle/index.js +1 -1
  42. package/dist/bundle/rpc-entry.js +1 -1
  43. package/dist/cli/args.d.ts.map +1 -1
  44. package/dist/cli/args.js +5 -4
  45. package/dist/cli/args.js.map +1 -1
  46. package/dist/cli/startup-ui.d.ts.map +1 -1
  47. package/dist/cli/startup-ui.js +38 -30
  48. package/dist/cli/startup-ui.js.map +1 -1
  49. package/dist/config.d.ts +15 -4
  50. package/dist/config.d.ts.map +1 -1
  51. package/dist/config.js +33 -4
  52. package/dist/config.js.map +1 -1
  53. package/dist/core/agent-session-runtime.d.ts +1 -1
  54. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  55. package/dist/core/agent-session-runtime.js +13 -13
  56. package/dist/core/agent-session-runtime.js.map +1 -1
  57. package/dist/core/agent-session-services.d.ts +2 -2
  58. package/dist/core/agent-session-services.d.ts.map +1 -1
  59. package/dist/core/agent-session-services.js +14 -1
  60. package/dist/core/agent-session-services.js.map +1 -1
  61. package/dist/core/agent-session.d.ts +121 -36
  62. package/dist/core/agent-session.d.ts.map +1 -1
  63. package/dist/core/agent-session.js +518 -203
  64. package/dist/core/agent-session.js.map +1 -1
  65. package/dist/core/bug-report.js +1 -1
  66. package/dist/core/bug-report.js.map +1 -1
  67. package/dist/core/compaction/compaction.d.ts.map +1 -1
  68. package/dist/core/compaction/compaction.js +1 -22
  69. package/dist/core/compaction/compaction.js.map +1 -1
  70. package/dist/core/compaction/utils.d.ts +2 -1
  71. package/dist/core/compaction/utils.d.ts.map +1 -1
  72. package/dist/core/compaction/utils.js +25 -18
  73. package/dist/core/compaction/utils.js.map +1 -1
  74. package/dist/core/crash-log.d.ts.map +1 -1
  75. package/dist/core/crash-log.js +2 -1
  76. package/dist/core/crash-log.js.map +1 -1
  77. package/dist/core/export-html/template.css +10 -0
  78. package/dist/core/export-html/template.js +66 -17
  79. package/dist/core/extensions/distribution-api.d.ts +1 -1
  80. package/dist/core/extensions/distribution-api.d.ts.map +1 -1
  81. package/dist/core/extensions/distribution-api.js.map +1 -1
  82. package/dist/core/extensions/index.d.ts +2 -2
  83. package/dist/core/extensions/index.d.ts.map +1 -1
  84. package/dist/core/extensions/index.js.map +1 -1
  85. package/dist/core/extensions/loader.d.ts.map +1 -1
  86. package/dist/core/extensions/loader.js +67 -5
  87. package/dist/core/extensions/loader.js.map +1 -1
  88. package/dist/core/extensions/runner.d.ts +22 -3
  89. package/dist/core/extensions/runner.d.ts.map +1 -1
  90. package/dist/core/extensions/runner.js +124 -8
  91. package/dist/core/extensions/runner.js.map +1 -1
  92. package/dist/core/extensions/types.d.ts +310 -25
  93. package/dist/core/extensions/types.d.ts.map +1 -1
  94. package/dist/core/extensions/types.js.map +1 -1
  95. package/dist/core/extensions/wrapper.d.ts +2 -2
  96. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  97. package/dist/core/extensions/wrapper.js +3 -3
  98. package/dist/core/extensions/wrapper.js.map +1 -1
  99. package/dist/core/keybindings.d.ts +70 -5
  100. package/dist/core/keybindings.d.ts.map +1 -1
  101. package/dist/core/keybindings.js +15 -1
  102. package/dist/core/keybindings.js.map +1 -1
  103. package/dist/core/mcp-servers.d.ts +125 -0
  104. package/dist/core/mcp-servers.d.ts.map +1 -0
  105. package/dist/core/mcp-servers.js +199 -0
  106. package/dist/core/mcp-servers.js.map +1 -0
  107. package/dist/core/model-registry.d.ts +15 -1
  108. package/dist/core/model-registry.d.ts.map +1 -1
  109. package/dist/core/model-registry.js +29 -0
  110. package/dist/core/model-registry.js.map +1 -1
  111. package/dist/core/model-resolver.d.ts +2 -2
  112. package/dist/core/model-resolver.d.ts.map +1 -1
  113. package/dist/core/model-resolver.js +5 -5
  114. package/dist/core/model-resolver.js.map +1 -1
  115. package/dist/core/model-runtime.d.ts +47 -3
  116. package/dist/core/model-runtime.d.ts.map +1 -1
  117. package/dist/core/model-runtime.js +189 -35
  118. package/dist/core/model-runtime.js.map +1 -1
  119. package/dist/core/nested-tool-calls.d.ts +102 -0
  120. package/dist/core/nested-tool-calls.d.ts.map +1 -0
  121. package/dist/core/nested-tool-calls.js +177 -0
  122. package/dist/core/nested-tool-calls.js.map +1 -0
  123. package/dist/core/package-manager.d.ts +4 -0
  124. package/dist/core/package-manager.d.ts.map +1 -1
  125. package/dist/core/package-manager.js +58 -12
  126. package/dist/core/package-manager.js.map +1 -1
  127. package/dist/core/provider-composer.d.ts +40 -21
  128. package/dist/core/provider-composer.d.ts.map +1 -1
  129. package/dist/core/provider-composer.js +92 -40
  130. package/dist/core/provider-composer.js.map +1 -1
  131. package/dist/core/radius.d.ts +2 -0
  132. package/dist/core/radius.d.ts.map +1 -1
  133. package/dist/core/radius.js +2 -0
  134. package/dist/core/radius.js.map +1 -1
  135. package/dist/core/remote-catalog-provider.d.ts +8 -1
  136. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  137. package/dist/core/remote-catalog-provider.js +21 -11
  138. package/dist/core/remote-catalog-provider.js.map +1 -1
  139. package/dist/core/resource-loader.d.ts +7 -1
  140. package/dist/core/resource-loader.d.ts.map +1 -1
  141. package/dist/core/resource-loader.js +160 -35
  142. package/dist/core/resource-loader.js.map +1 -1
  143. package/dist/core/sdk.d.ts +3 -3
  144. package/dist/core/sdk.d.ts.map +1 -1
  145. package/dist/core/sdk.js +26 -7
  146. package/dist/core/sdk.js.map +1 -1
  147. package/dist/core/session-manager.d.ts +9 -0
  148. package/dist/core/session-manager.d.ts.map +1 -1
  149. package/dist/core/session-manager.js +22 -22
  150. package/dist/core/session-manager.js.map +1 -1
  151. package/dist/core/settings-manager.d.ts +41 -4
  152. package/dist/core/settings-manager.d.ts.map +1 -1
  153. package/dist/core/settings-manager.js +110 -3
  154. package/dist/core/settings-manager.js.map +1 -1
  155. package/dist/core/slash-commands.d.ts.map +1 -1
  156. package/dist/core/slash-commands.js +1 -0
  157. package/dist/core/slash-commands.js.map +1 -1
  158. package/dist/core/source-info.d.ts +8 -0
  159. package/dist/core/source-info.d.ts.map +1 -1
  160. package/dist/core/source-info.js +16 -0
  161. package/dist/core/source-info.js.map +1 -1
  162. package/dist/core/system-prompt.js +1 -1
  163. package/dist/core/system-prompt.js.map +1 -1
  164. package/dist/core/tasks/delivery.d.ts +40 -0
  165. package/dist/core/tasks/delivery.d.ts.map +1 -0
  166. package/dist/core/tasks/delivery.js +157 -0
  167. package/dist/core/tasks/delivery.js.map +1 -0
  168. package/dist/core/tasks/format.d.ts +7 -0
  169. package/dist/core/tasks/format.d.ts.map +1 -0
  170. package/dist/core/tasks/format.js +14 -0
  171. package/dist/core/tasks/format.js.map +1 -0
  172. package/dist/core/tasks/history.d.ts +4 -0
  173. package/dist/core/tasks/history.d.ts.map +1 -0
  174. package/dist/core/{background → tasks}/history.js +8 -51
  175. package/dist/core/tasks/history.js.map +1 -0
  176. package/dist/core/{background → tasks}/output.d.ts +12 -4
  177. package/dist/core/tasks/output.d.ts.map +1 -0
  178. package/dist/core/{background → tasks}/output.js +30 -11
  179. package/dist/core/tasks/output.js.map +1 -0
  180. package/dist/core/tasks/presentation.d.ts +7 -0
  181. package/dist/core/tasks/presentation.d.ts.map +1 -0
  182. package/dist/core/tasks/presentation.js +226 -0
  183. package/dist/core/tasks/presentation.js.map +1 -0
  184. package/dist/core/tasks/runtime.d.ts +74 -0
  185. package/dist/core/tasks/runtime.d.ts.map +1 -0
  186. package/dist/core/tasks/runtime.js +580 -0
  187. package/dist/core/tasks/runtime.js.map +1 -0
  188. package/dist/core/tasks/session.d.ts +49 -0
  189. package/dist/core/tasks/session.d.ts.map +1 -0
  190. package/dist/core/tasks/session.js +138 -0
  191. package/dist/core/tasks/session.js.map +1 -0
  192. package/dist/core/tasks/store.d.ts +46 -0
  193. package/dist/core/tasks/store.d.ts.map +1 -0
  194. package/dist/core/tasks/store.js +162 -0
  195. package/dist/core/tasks/store.js.map +1 -0
  196. package/dist/core/{background → tasks}/types.d.ts +64 -86
  197. package/dist/core/tasks/types.d.ts.map +1 -0
  198. package/dist/core/tasks/types.js +27 -0
  199. package/dist/core/tasks/types.js.map +1 -0
  200. package/dist/core/tools/bash.d.ts +8 -93
  201. package/dist/core/tools/bash.d.ts.map +1 -1
  202. package/dist/core/tools/bash.js +8 -240
  203. package/dist/core/tools/bash.js.map +1 -1
  204. package/dist/core/tools/grep.d.ts +2 -0
  205. package/dist/core/tools/grep.d.ts.map +1 -1
  206. package/dist/core/tools/grep.js +2 -0
  207. package/dist/core/tools/grep.js.map +1 -1
  208. package/dist/core/tools/index.d.ts +2 -1
  209. package/dist/core/tools/index.d.ts.map +1 -1
  210. package/dist/core/tools/index.js +9 -0
  211. package/dist/core/tools/index.js.map +1 -1
  212. package/dist/core/tools/output-accumulator.d.ts +11 -0
  213. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  214. package/dist/core/tools/output-accumulator.js +36 -0
  215. package/dist/core/tools/output-accumulator.js.map +1 -1
  216. package/dist/core/tools/powershell.d.ts +6 -2
  217. package/dist/core/tools/powershell.d.ts.map +1 -1
  218. package/dist/core/tools/powershell.js +1 -1
  219. package/dist/core/tools/powershell.js.map +1 -1
  220. package/dist/core/tools/render-utils.d.ts +6 -0
  221. package/dist/core/tools/render-utils.d.ts.map +1 -1
  222. package/dist/core/tools/render-utils.js +26 -0
  223. package/dist/core/tools/render-utils.js.map +1 -1
  224. package/dist/core/tools/renderers/bash.d.ts +1 -1
  225. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  226. package/dist/core/tools/renderers/bash.js +11 -35
  227. package/dist/core/tools/renderers/bash.js.map +1 -1
  228. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  229. package/dist/core/tools/renderers/index.js +5 -7
  230. package/dist/core/tools/renderers/index.js.map +1 -1
  231. package/dist/core/tools/renderers/read.d.ts.map +1 -1
  232. package/dist/core/tools/renderers/read.js +3 -2
  233. package/dist/core/tools/renderers/read.js.map +1 -1
  234. package/dist/core/tools/shell-execution.d.ts +4 -6
  235. package/dist/core/tools/shell-execution.d.ts.map +1 -1
  236. package/dist/core/tools/shell-execution.js +22 -13
  237. package/dist/core/tools/shell-execution.js.map +1 -1
  238. package/dist/core/tools/shell-tool.d.ts +93 -0
  239. package/dist/core/tools/shell-tool.d.ts.map +1 -0
  240. package/dist/core/tools/shell-tool.js +249 -0
  241. package/dist/core/tools/shell-tool.js.map +1 -0
  242. package/dist/core/tools/tasks/actions.d.ts +12 -0
  243. package/dist/core/tools/tasks/actions.d.ts.map +1 -0
  244. package/dist/{extensions/background → core/tools/tasks}/actions.js +44 -29
  245. package/dist/core/tools/tasks/actions.js.map +1 -0
  246. package/dist/core/tools/tasks/constants.d.ts +20 -0
  247. package/dist/core/tools/tasks/constants.d.ts.map +1 -0
  248. package/dist/core/tools/tasks/constants.js +20 -0
  249. package/dist/core/tools/tasks/constants.js.map +1 -0
  250. package/dist/{extensions/background → core/tools/tasks}/schema.d.ts +7 -7
  251. package/dist/core/tools/tasks/schema.d.ts.map +1 -0
  252. package/dist/{extensions/background → core/tools/tasks}/schema.js +21 -20
  253. package/dist/core/tools/tasks/schema.js.map +1 -0
  254. package/dist/core/tools/tasks/types.d.ts +53 -0
  255. package/dist/core/tools/tasks/types.d.ts.map +1 -0
  256. package/dist/core/tools/tasks/types.js +12 -0
  257. package/dist/core/tools/tasks/types.js.map +1 -0
  258. package/dist/core/tools/tasks.d.ts +14 -0
  259. package/dist/core/tools/tasks.d.ts.map +1 -0
  260. package/dist/core/tools/tasks.js +40 -0
  261. package/dist/core/tools/tasks.js.map +1 -0
  262. package/dist/core/tools/tool-definition-wrapper.d.ts +4 -3
  263. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  264. package/dist/core/tools/tool-definition-wrapper.js +4 -2
  265. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  266. package/dist/core/tools/truncate.d.ts +14 -0
  267. package/dist/core/tools/truncate.d.ts.map +1 -1
  268. package/dist/core/tools/truncate.js +29 -0
  269. package/dist/core/tools/truncate.js.map +1 -1
  270. package/dist/core/trust-manager.d.ts.map +1 -1
  271. package/dist/core/trust-manager.js +1 -0
  272. package/dist/core/trust-manager.js.map +1 -1
  273. package/dist/core/usage-totals.d.ts +5 -3
  274. package/dist/core/usage-totals.d.ts.map +1 -1
  275. package/dist/core/usage-totals.js +27 -4
  276. package/dist/core/usage-totals.js.map +1 -1
  277. package/dist/core/virtual-models.d.ts +117 -0
  278. package/dist/core/virtual-models.d.ts.map +1 -0
  279. package/dist/core/virtual-models.js +124 -0
  280. package/dist/core/virtual-models.js.map +1 -0
  281. package/dist/extensions/btw/agent.d.ts +17 -8
  282. package/dist/extensions/btw/agent.d.ts.map +1 -1
  283. package/dist/extensions/btw/agent.js +74 -76
  284. package/dist/extensions/btw/agent.js.map +1 -1
  285. package/dist/extensions/btw/controller.d.ts +0 -1
  286. package/dist/extensions/btw/controller.d.ts.map +1 -1
  287. package/dist/extensions/btw/controller.js +26 -33
  288. package/dist/extensions/btw/controller.js.map +1 -1
  289. package/dist/extensions/btw/panel.d.ts +13 -14
  290. package/dist/extensions/btw/panel.d.ts.map +1 -1
  291. package/dist/extensions/btw/panel.js +38 -29
  292. package/dist/extensions/btw/panel.js.map +1 -1
  293. package/dist/extensions/codemode/execute.d.ts +16 -0
  294. package/dist/extensions/codemode/execute.d.ts.map +1 -0
  295. package/dist/extensions/codemode/execute.js +536 -0
  296. package/dist/extensions/codemode/execute.js.map +1 -0
  297. package/dist/extensions/codemode/execute.lazy.d.ts +3 -0
  298. package/dist/extensions/codemode/execute.lazy.d.ts.map +1 -0
  299. package/dist/extensions/codemode/execute.lazy.js +3 -0
  300. package/dist/extensions/codemode/execute.lazy.js.map +1 -0
  301. package/dist/extensions/codemode/index.d.ts +21 -0
  302. package/dist/extensions/codemode/index.d.ts.map +1 -0
  303. package/dist/extensions/codemode/index.js +36 -0
  304. package/dist/extensions/codemode/index.js.map +1 -0
  305. package/dist/extensions/codemode/renderer.d.ts +12 -0
  306. package/dist/extensions/codemode/renderer.d.ts.map +1 -0
  307. package/dist/extensions/codemode/renderer.js +137 -0
  308. package/dist/extensions/codemode/renderer.js.map +1 -0
  309. package/dist/extensions/codemode/search.d.ts +33 -0
  310. package/dist/extensions/codemode/search.d.ts.map +1 -0
  311. package/dist/extensions/codemode/search.js +117 -0
  312. package/dist/extensions/codemode/search.js.map +1 -0
  313. package/dist/extensions/codemode/tool.d.ts +123 -0
  314. package/dist/extensions/codemode/tool.d.ts.map +1 -0
  315. package/dist/extensions/codemode/tool.js +268 -0
  316. package/dist/extensions/codemode/tool.js.map +1 -0
  317. package/dist/extensions/codemode/worker.d.ts +7 -0
  318. package/dist/extensions/codemode/worker.d.ts.map +1 -0
  319. package/dist/extensions/codemode/worker.js +7 -0
  320. package/dist/extensions/codemode/worker.js.map +1 -0
  321. package/dist/extensions/deepwiki/schema.d.ts +1 -1
  322. package/dist/extensions/index.js +13 -13
  323. package/dist/extensions/index.js.map +1 -1
  324. package/dist/extensions/llama/provider.d.ts +1 -1
  325. package/dist/extensions/llama/provider.d.ts.map +1 -1
  326. package/dist/extensions/llama/provider.js +65 -13
  327. package/dist/extensions/llama/provider.js.map +1 -1
  328. package/dist/extensions/mcp/cli.d.ts +21 -0
  329. package/dist/extensions/mcp/cli.d.ts.map +1 -0
  330. package/dist/extensions/mcp/cli.js +500 -0
  331. package/dist/extensions/mcp/cli.js.map +1 -0
  332. package/dist/extensions/mcp/cli.lazy.d.ts +3 -0
  333. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -0
  334. package/dist/extensions/mcp/cli.lazy.js +3 -0
  335. package/dist/extensions/mcp/cli.lazy.js.map +1 -0
  336. package/dist/extensions/mcp/config.d.ts +72 -0
  337. package/dist/extensions/mcp/config.d.ts.map +1 -0
  338. package/dist/extensions/mcp/config.js +158 -0
  339. package/dist/extensions/mcp/config.js.map +1 -0
  340. package/dist/extensions/mcp/index.d.ts +76 -0
  341. package/dist/extensions/mcp/index.d.ts.map +1 -0
  342. package/dist/extensions/mcp/index.js +1078 -0
  343. package/dist/extensions/mcp/index.js.map +1 -0
  344. package/dist/extensions/mcp/log.d.ts +16 -0
  345. package/dist/extensions/mcp/log.d.ts.map +1 -0
  346. package/dist/extensions/mcp/log.js +64 -0
  347. package/dist/extensions/mcp/log.js.map +1 -0
  348. package/dist/extensions/mcp/oauth.d.ts +97 -0
  349. package/dist/extensions/mcp/oauth.d.ts.map +1 -0
  350. package/dist/extensions/mcp/oauth.js +355 -0
  351. package/dist/extensions/mcp/oauth.js.map +1 -0
  352. package/dist/extensions/mcp/resources.d.ts +43 -0
  353. package/dist/extensions/mcp/resources.d.ts.map +1 -0
  354. package/dist/extensions/mcp/resources.js +262 -0
  355. package/dist/extensions/mcp/resources.js.map +1 -0
  356. package/dist/extensions/mcp/runtime.d.ts +98 -0
  357. package/dist/extensions/mcp/runtime.d.ts.map +1 -0
  358. package/dist/extensions/mcp/runtime.js +379 -0
  359. package/dist/extensions/mcp/runtime.js.map +1 -0
  360. package/dist/extensions/mcp/runtime.lazy.d.ts +3 -0
  361. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -0
  362. package/dist/extensions/mcp/runtime.lazy.js +3 -0
  363. package/dist/extensions/mcp/runtime.lazy.js.map +1 -0
  364. package/dist/extensions/mcp/tools.d.ts +84 -0
  365. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  366. package/dist/extensions/mcp/tools.js +251 -0
  367. package/dist/extensions/mcp/tools.js.map +1 -0
  368. package/dist/extensions/mcp/ui.d.ts +60 -0
  369. package/dist/extensions/mcp/ui.d.ts.map +1 -0
  370. package/dist/extensions/mcp/ui.js +168 -0
  371. package/dist/extensions/mcp/ui.js.map +1 -0
  372. package/dist/extensions/provider/catalog.d.ts +8 -1
  373. package/dist/extensions/provider/catalog.d.ts.map +1 -1
  374. package/dist/extensions/provider/catalog.js +31 -0
  375. package/dist/extensions/provider/catalog.js.map +1 -1
  376. package/dist/extensions/provider/connection.d.ts +4 -1
  377. package/dist/extensions/provider/connection.d.ts.map +1 -1
  378. package/dist/extensions/provider/connection.js +1 -5
  379. package/dist/extensions/provider/connection.js.map +1 -1
  380. package/dist/extensions/provider/editing.d.ts +36 -0
  381. package/dist/extensions/provider/editing.d.ts.map +1 -0
  382. package/dist/extensions/provider/editing.js +99 -0
  383. package/dist/extensions/provider/editing.js.map +1 -0
  384. package/dist/extensions/provider/json-fields.d.ts +5 -0
  385. package/dist/extensions/provider/json-fields.d.ts.map +1 -0
  386. package/dist/extensions/provider/json-fields.js +31 -0
  387. package/dist/extensions/provider/json-fields.js.map +1 -0
  388. package/dist/extensions/provider/store.d.ts +1 -4
  389. package/dist/extensions/provider/store.d.ts.map +1 -1
  390. package/dist/extensions/provider/store.js +2 -30
  391. package/dist/extensions/provider/store.js.map +1 -1
  392. package/dist/extensions/provider/ui/builtin-data.d.ts +0 -2
  393. package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
  394. package/dist/extensions/provider/ui/builtin-data.js +14 -79
  395. package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
  396. package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
  397. package/dist/extensions/provider/ui/compat.js +6 -9
  398. package/dist/extensions/provider/ui/compat.js.map +1 -1
  399. package/dist/extensions/provider/ui/controls.d.ts +48 -0
  400. package/dist/extensions/provider/ui/controls.d.ts.map +1 -0
  401. package/dist/extensions/provider/ui/controls.js +108 -0
  402. package/dist/extensions/provider/ui/controls.js.map +1 -0
  403. package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
  404. package/dist/extensions/provider/ui/dictionary.js +6 -9
  405. package/dist/extensions/provider/ui/dictionary.js.map +1 -1
  406. package/dist/extensions/provider/ui/editor.d.ts +3 -3
  407. package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
  408. package/dist/extensions/provider/ui/editor.js +35 -140
  409. package/dist/extensions/provider/ui/editor.js.map +1 -1
  410. package/dist/extensions/provider/ui/fetch-models.d.ts +0 -3
  411. package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
  412. package/dist/extensions/provider/ui/fetch-models.js +49 -44
  413. package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
  414. package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
  415. package/dist/extensions/provider/ui/model-fields.js +11 -14
  416. package/dist/extensions/provider/ui/model-fields.js.map +1 -1
  417. package/dist/extensions/provider/ui/model-options.d.ts +4 -34
  418. package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
  419. package/dist/extensions/provider/ui/model-options.js +90 -271
  420. package/dist/extensions/provider/ui/model-options.js.map +1 -1
  421. package/dist/extensions/provider/ui/pane.d.ts +4 -18
  422. package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
  423. package/dist/extensions/provider/ui/pane.js.map +1 -1
  424. package/dist/extensions/provider/ui/provider-fields.d.ts +2 -19
  425. package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
  426. package/dist/extensions/provider/ui/provider-fields.js +58 -171
  427. package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
  428. package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
  429. package/dist/extensions/provider/ui/thinking-map.js +6 -9
  430. package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
  431. package/dist/extensions/question/detail-pane.d.ts +7 -2
  432. package/dist/extensions/question/detail-pane.d.ts.map +1 -1
  433. package/dist/extensions/question/detail-pane.js +16 -5
  434. package/dist/extensions/question/detail-pane.js.map +1 -1
  435. package/dist/extensions/question/dialog-view.d.ts +41 -0
  436. package/dist/extensions/question/dialog-view.d.ts.map +1 -0
  437. package/dist/extensions/question/dialog-view.js +329 -0
  438. package/dist/extensions/question/dialog-view.js.map +1 -0
  439. package/dist/extensions/question/dialog.d.ts +3 -3
  440. package/dist/extensions/question/dialog.d.ts.map +1 -1
  441. package/dist/extensions/question/dialog.js +220 -634
  442. package/dist/extensions/question/dialog.js.map +1 -1
  443. package/dist/extensions/question/index.d.ts.map +1 -1
  444. package/dist/extensions/question/index.js +2 -3
  445. package/dist/extensions/question/index.js.map +1 -1
  446. package/dist/extensions/question/render.d.ts.map +1 -1
  447. package/dist/extensions/question/render.js +22 -32
  448. package/dist/extensions/question/render.js.map +1 -1
  449. package/dist/extensions/question/results.d.ts.map +1 -1
  450. package/dist/extensions/question/results.js +56 -12
  451. package/dist/extensions/question/results.js.map +1 -1
  452. package/dist/extensions/question/schema.d.ts +21 -6
  453. package/dist/extensions/question/schema.d.ts.map +1 -1
  454. package/dist/extensions/question/schema.js.map +1 -1
  455. package/dist/extensions/question/state.d.ts +9 -7
  456. package/dist/extensions/question/state.d.ts.map +1 -1
  457. package/dist/extensions/question/state.js +63 -54
  458. package/dist/extensions/question/state.js.map +1 -1
  459. package/dist/extensions/question/types.d.ts +41 -18
  460. package/dist/extensions/question/types.d.ts.map +1 -1
  461. package/dist/extensions/question/types.js.map +1 -1
  462. package/dist/extensions/statusline/index.d.ts +4 -0
  463. package/dist/extensions/statusline/index.d.ts.map +1 -1
  464. package/dist/extensions/statusline/index.js +18 -355
  465. package/dist/extensions/statusline/index.js.map +1 -1
  466. package/dist/extensions/statusline/render.d.ts +19 -0
  467. package/dist/extensions/statusline/render.d.ts.map +1 -0
  468. package/dist/extensions/statusline/render.js +163 -0
  469. package/dist/extensions/statusline/render.js.map +1 -0
  470. package/dist/extensions/statusline/usage.d.ts +12 -0
  471. package/dist/extensions/statusline/usage.d.ts.map +1 -0
  472. package/dist/extensions/statusline/usage.js +36 -0
  473. package/dist/extensions/statusline/usage.js.map +1 -0
  474. package/dist/extensions/tool-search/index.d.ts +12 -0
  475. package/dist/extensions/tool-search/index.d.ts.map +1 -0
  476. package/dist/extensions/tool-search/index.js +20 -0
  477. package/dist/extensions/tool-search/index.js.map +1 -0
  478. package/dist/extensions/tool-search/tool.d.ts +73 -0
  479. package/dist/extensions/tool-search/tool.d.ts.map +1 -0
  480. package/dist/extensions/tool-search/tool.js +187 -0
  481. package/dist/extensions/tool-search/tool.js.map +1 -0
  482. package/dist/extensions/web-search/execute.d.ts +1 -5
  483. package/dist/extensions/web-search/execute.d.ts.map +1 -1
  484. package/dist/extensions/web-search/execute.js +4 -9
  485. package/dist/extensions/web-search/execute.js.map +1 -1
  486. package/dist/extensions/web-search/format.d.ts +12 -3
  487. package/dist/extensions/web-search/format.d.ts.map +1 -1
  488. package/dist/extensions/web-search/format.js +33 -25
  489. package/dist/extensions/web-search/format.js.map +1 -1
  490. package/dist/extensions/web-search/index.d.ts.map +1 -1
  491. package/dist/extensions/web-search/index.js +6 -29
  492. package/dist/extensions/web-search/index.js.map +1 -1
  493. package/dist/extensions/web-search/providers/deepseek.d.ts.map +1 -1
  494. package/dist/extensions/web-search/providers/deepseek.js +0 -1
  495. package/dist/extensions/web-search/providers/deepseek.js.map +1 -1
  496. package/dist/extensions/web-search/providers/http.d.ts +1 -1
  497. package/dist/extensions/web-search/providers/http.d.ts.map +1 -1
  498. package/dist/extensions/web-search/providers/http.js.map +1 -1
  499. package/dist/extensions/web-search/providers/minimax.d.ts.map +1 -1
  500. package/dist/extensions/web-search/providers/minimax.js +0 -1
  501. package/dist/extensions/web-search/providers/minimax.js.map +1 -1
  502. package/dist/extensions/web-search/render.d.ts +7 -2
  503. package/dist/extensions/web-search/render.d.ts.map +1 -1
  504. package/dist/extensions/web-search/render.js +32 -4
  505. package/dist/extensions/web-search/render.js.map +1 -1
  506. package/dist/extensions/web-search/results.d.ts.map +1 -1
  507. package/dist/extensions/web-search/results.js +3 -8
  508. package/dist/extensions/web-search/results.js.map +1 -1
  509. package/dist/extensions/web-search/types.d.ts +4 -2
  510. package/dist/extensions/web-search/types.d.ts.map +1 -1
  511. package/dist/extensions/web-search/types.js.map +1 -1
  512. package/dist/index.d.ts +12 -5
  513. package/dist/index.d.ts.map +1 -1
  514. package/dist/index.js +6 -1
  515. package/dist/index.js.map +1 -1
  516. package/dist/main.d.ts.map +1 -1
  517. package/dist/main.js +16 -0
  518. package/dist/main.js.map +1 -1
  519. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  520. package/dist/modes/interactive/components/config-selector.js +13 -3
  521. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  522. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  523. package/dist/modes/interactive/components/custom-message.js +3 -1
  524. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  525. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  526. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  527. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  528. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  529. package/dist/modes/interactive/components/footer.d.ts +7 -0
  530. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  531. package/dist/modes/interactive/components/footer.js +42 -3
  532. package/dist/modes/interactive/components/footer.js.map +1 -1
  533. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  534. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  535. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  536. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  537. package/dist/modes/interactive/components/pi-logo-animation.d.ts +68 -0
  538. package/dist/modes/interactive/components/pi-logo-animation.d.ts.map +1 -0
  539. package/dist/modes/interactive/components/pi-logo-animation.js +1076 -0
  540. package/dist/modes/interactive/components/pi-logo-animation.js.map +1 -0
  541. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts +7 -0
  542. package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts.map +1 -0
  543. package/dist/modes/interactive/components/pi-logo-animation.lazy.js +12 -0
  544. package/dist/modes/interactive/components/pi-logo-animation.lazy.js.map +1 -0
  545. package/dist/modes/interactive/components/pi-logo.d.ts +19 -0
  546. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -0
  547. package/dist/modes/interactive/components/pi-logo.js +37 -0
  548. package/dist/modes/interactive/components/pi-logo.js.map +1 -0
  549. package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
  550. package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
  551. package/dist/modes/interactive/components/radius-login-selector.js +83 -0
  552. package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
  553. package/dist/modes/interactive/components/settings-selector.d.ts +6 -4
  554. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  555. package/dist/modes/interactive/components/settings-selector.js +33 -11
  556. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  557. package/dist/modes/interactive/components/status-marker.d.ts +2 -4
  558. package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
  559. package/dist/modes/interactive/components/status-marker.js +2 -6
  560. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  561. package/dist/modes/interactive/components/themed-text.d.ts +17 -0
  562. package/dist/modes/interactive/components/themed-text.d.ts.map +1 -0
  563. package/dist/modes/interactive/components/themed-text.js +28 -0
  564. package/dist/modes/interactive/components/themed-text.js.map +1 -0
  565. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  566. package/dist/modes/interactive/components/user-message.js +5 -4
  567. package/dist/modes/interactive/components/user-message.js.map +1 -1
  568. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  569. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  570. package/dist/modes/interactive/components/visual-truncate.js +36 -6
  571. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  572. package/dist/modes/interactive/interactive-mode.d.ts +12 -4
  573. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  574. package/dist/modes/interactive/interactive-mode.js +377 -199
  575. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  576. package/dist/modes/interactive/tasks/completion-render.d.ts +8 -0
  577. package/dist/modes/interactive/tasks/completion-render.d.ts.map +1 -0
  578. package/dist/{extensions/background → modes/interactive/tasks}/completion-render.js +41 -91
  579. package/dist/modes/interactive/tasks/completion-render.js.map +1 -0
  580. package/dist/modes/interactive/tasks/index.d.ts +12 -0
  581. package/dist/modes/interactive/tasks/index.d.ts.map +1 -0
  582. package/dist/modes/interactive/tasks/index.js +102 -0
  583. package/dist/modes/interactive/tasks/index.js.map +1 -0
  584. package/dist/modes/interactive/tasks/inspector.d.ts +35 -0
  585. package/dist/modes/interactive/tasks/inspector.d.ts.map +1 -0
  586. package/dist/modes/interactive/tasks/inspector.js +93 -0
  587. package/dist/modes/interactive/tasks/inspector.js.map +1 -0
  588. package/dist/modes/interactive/tasks/layout.d.ts +40 -0
  589. package/dist/modes/interactive/tasks/layout.d.ts.map +1 -0
  590. package/dist/modes/interactive/tasks/layout.js +212 -0
  591. package/dist/modes/interactive/tasks/layout.js.map +1 -0
  592. package/dist/modes/interactive/tasks/list.d.ts +21 -0
  593. package/dist/modes/interactive/tasks/list.d.ts.map +1 -0
  594. package/dist/modes/interactive/tasks/list.js +96 -0
  595. package/dist/modes/interactive/tasks/list.js.map +1 -0
  596. package/dist/modes/interactive/tasks/manager.d.ts +60 -0
  597. package/dist/modes/interactive/tasks/manager.d.ts.map +1 -0
  598. package/dist/modes/interactive/tasks/manager.js +380 -0
  599. package/dist/modes/interactive/tasks/manager.js.map +1 -0
  600. package/dist/modes/interactive/tasks/model.d.ts +21 -0
  601. package/dist/modes/interactive/tasks/model.d.ts.map +1 -0
  602. package/dist/modes/interactive/tasks/model.js +41 -0
  603. package/dist/modes/interactive/tasks/model.js.map +1 -0
  604. package/dist/modes/interactive/tasks/render.d.ts +28 -0
  605. package/dist/modes/interactive/tasks/render.d.ts.map +1 -0
  606. package/dist/modes/interactive/tasks/render.js +141 -0
  607. package/dist/modes/interactive/tasks/render.js.map +1 -0
  608. package/dist/modes/interactive/tasks/task-view.d.ts +13 -0
  609. package/dist/modes/interactive/tasks/task-view.d.ts.map +1 -0
  610. package/dist/modes/interactive/tasks/task-view.js +20 -0
  611. package/dist/modes/interactive/tasks/task-view.js.map +1 -0
  612. package/dist/modes/interactive/tasks/text.d.ts +6 -0
  613. package/dist/modes/interactive/tasks/text.d.ts.map +1 -0
  614. package/dist/modes/interactive/tasks/text.js +16 -0
  615. package/dist/modes/interactive/tasks/text.js.map +1 -0
  616. package/dist/modes/interactive/tasks/viewport.d.ts +17 -0
  617. package/dist/modes/interactive/tasks/viewport.d.ts.map +1 -0
  618. package/dist/modes/interactive/tasks/viewport.js +59 -0
  619. package/dist/modes/interactive/tasks/viewport.js.map +1 -0
  620. package/dist/modes/interactive/tasks/views.d.ts +9 -0
  621. package/dist/modes/interactive/tasks/views.d.ts.map +1 -0
  622. package/dist/modes/interactive/tasks/views.js +42 -0
  623. package/dist/modes/interactive/tasks/views.js.map +1 -0
  624. package/dist/modes/interactive/theme/dark.json +59 -72
  625. package/dist/modes/interactive/theme/light.json +57 -69
  626. package/dist/modes/interactive/theme/system-theme.d.ts +55 -0
  627. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
  628. package/dist/modes/interactive/theme/system-theme.js +546 -0
  629. package/dist/modes/interactive/theme/system-theme.js.map +1 -0
  630. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  631. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  632. package/dist/modes/interactive/theme/theme-controller.js +125 -47
  633. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  634. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  635. package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -1
  636. package/dist/modes/interactive/theme/theme-json.js +3 -1
  637. package/dist/modes/interactive/theme/theme-json.js.map +1 -1
  638. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  639. package/dist/modes/interactive/theme/theme.d.ts +70 -39
  640. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  641. package/dist/modes/interactive/theme/theme.js +247 -313
  642. package/dist/modes/interactive/theme/theme.js.map +1 -1
  643. package/dist/modes/interactive/tool-view/fallback.d.ts +1 -1
  644. package/dist/modes/interactive/tool-view/fallback.d.ts.map +1 -1
  645. package/dist/modes/interactive/tool-view/fallback.js +4 -1
  646. package/dist/modes/interactive/tool-view/fallback.js.map +1 -1
  647. package/dist/modes/interactive/tool-view/tool-execution.js +2 -2
  648. package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -1
  649. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  650. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  651. package/dist/modes/interactive/tui-renderer.js +1 -0
  652. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  653. package/dist/modes/rpc/rpc-client.d.ts +6 -6
  654. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  655. package/dist/modes/rpc/rpc-client.js +12 -8
  656. package/dist/modes/rpc/rpc-client.js.map +1 -1
  657. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  658. package/dist/modes/rpc/rpc-mode.js +7 -9
  659. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  660. package/dist/modes/rpc/rpc-types.d.ts +10 -1
  661. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  662. package/dist/modes/rpc/rpc-types.js.map +1 -1
  663. package/dist/package-manager-cli.d.ts.map +1 -1
  664. package/dist/package-manager-cli.js +6 -2
  665. package/dist/package-manager-cli.js.map +1 -1
  666. package/dist/utils/clipboard-image.d.ts.map +1 -1
  667. package/dist/utils/clipboard-image.js +14 -17
  668. package/dist/utils/clipboard-image.js.map +1 -1
  669. package/dist/utils/clipboard.d.ts +2 -0
  670. package/dist/utils/clipboard.d.ts.map +1 -1
  671. package/dist/utils/clipboard.js +5 -0
  672. package/dist/utils/clipboard.js.map +1 -1
  673. package/dist/utils/paths.d.ts +3 -3
  674. package/dist/utils/paths.d.ts.map +1 -1
  675. package/dist/utils/paths.js +5 -4
  676. package/dist/utils/paths.js.map +1 -1
  677. package/dist/utils/shell.d.ts +1 -3
  678. package/dist/utils/shell.d.ts.map +1 -1
  679. package/dist/utils/shell.js +3 -30
  680. package/dist/utils/shell.js.map +1 -1
  681. package/docs/bundled/README.md +22 -9
  682. package/docs/bundled/extensions/question.md +2 -2
  683. package/docs/bundled/extensions/statusline.md +26 -17
  684. package/docs/bundled/tasks.md +127 -0
  685. package/docs/bundled/tool-presentation.md +1 -1
  686. package/docs/codemode.md +207 -0
  687. package/docs/custom-provider.md +44 -0
  688. package/docs/docs.json +14 -10
  689. package/docs/environment-variables.md +1 -1
  690. package/docs/extensions.md +94 -93
  691. package/docs/index.md +2 -1
  692. package/docs/keybindings.md +17 -9
  693. package/docs/llama-cpp.md +12 -1
  694. package/docs/mcp.md +248 -0
  695. package/docs/models.md +56 -0
  696. package/docs/packages.md +4 -0
  697. package/docs/providers.md +14 -0
  698. package/docs/rpc.md +5 -3
  699. package/docs/sdk.md +26 -16
  700. package/docs/security.md +4 -0
  701. package/docs/session-format.md +20 -23
  702. package/docs/settings.md +29 -3
  703. package/docs/themes.md +27 -5
  704. package/docs/tui.md +21 -1
  705. package/docs/usage.md +52 -4
  706. package/docs/virtual-models.md +114 -0
  707. package/docs/windows.md +2 -0
  708. package/examples/README.md +2 -2
  709. package/examples/extensions/README.md +3 -2
  710. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  711. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  712. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  713. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  714. package/examples/extensions/custom-provider-gitlab-duo/test.ts +4 -4
  715. package/examples/extensions/debug-provider.ts +90 -0
  716. package/examples/extensions/gondolin/package-lock.json +2 -2
  717. package/examples/extensions/gondolin/package.json +1 -1
  718. package/examples/extensions/jev-router.ts +113 -0
  719. package/examples/extensions/minimal-mode.ts +24 -96
  720. package/examples/extensions/sandbox/package-lock.json +2 -2
  721. package/examples/extensions/sandbox/package.json +1 -1
  722. package/examples/extensions/with-deps/package-lock.json +2 -2
  723. package/examples/extensions/with-deps/package.json +1 -1
  724. package/examples/rpc-client.ts +1 -1
  725. package/examples/rpc-extension-ui.ts +1 -1
  726. package/examples/sdk/14-codemode-mcp.ts +61 -0
  727. package/examples/sdk/README.md +1 -0
  728. package/npm-shrinkwrap.json +420 -423
  729. package/package.json +14 -10
  730. package/dist/bundle/chunks/anthropic-messages-XWFTZP2N.js +0 -6
  731. package/dist/bundle/chunks/azure-openai-responses-HS35BQV6.js +0 -2
  732. package/dist/bundle/chunks/chunk-2IO5GDBS.js +0 -11
  733. package/dist/bundle/chunks/chunk-EDBLK2JQ.js +0 -2
  734. package/dist/bundle/chunks/chunk-I5IVW2WS.js +0 -2
  735. package/dist/bundle/chunks/chunk-IORR2FW4.js +0 -2
  736. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
  737. package/dist/bundle/chunks/chunk-UUSTLCVC.js +0 -2
  738. package/dist/bundle/chunks/google-generative-ai-NOVAJBFC.js +0 -2
  739. package/dist/bundle/chunks/google-vertex-4VHCZJV5.js +0 -2
  740. package/dist/bundle/chunks/mistral-conversations-WC6A2WCJ.js +0 -5
  741. package/dist/bundle/chunks/openai-codex-responses-XCDG75W2.js +0 -10
  742. package/dist/bundle/chunks/openai-completions-SHS3CAEL.js +0 -7
  743. package/dist/bundle/chunks/openai-responses-UT6XFKC7.js +0 -2
  744. package/dist/bundle/chunks/virtual-modules-KUEIEAZN.js +0 -2
  745. package/dist/core/background/history.d.ts +0 -4
  746. package/dist/core/background/history.d.ts.map +0 -1
  747. package/dist/core/background/history.js.map +0 -1
  748. package/dist/core/background/output.d.ts.map +0 -1
  749. package/dist/core/background/output.js.map +0 -1
  750. package/dist/core/background/presentation.d.ts +0 -9
  751. package/dist/core/background/presentation.d.ts.map +0 -1
  752. package/dist/core/background/presentation.js +0 -311
  753. package/dist/core/background/presentation.js.map +0 -1
  754. package/dist/core/background/service.d.ts +0 -68
  755. package/dist/core/background/service.d.ts.map +0 -1
  756. package/dist/core/background/service.js +0 -641
  757. package/dist/core/background/service.js.map +0 -1
  758. package/dist/core/background/session.d.ts +0 -67
  759. package/dist/core/background/session.d.ts.map +0 -1
  760. package/dist/core/background/session.js +0 -248
  761. package/dist/core/background/session.js.map +0 -1
  762. package/dist/core/background/types.d.ts.map +0 -1
  763. package/dist/core/background/types.js +0 -31
  764. package/dist/core/background/types.js.map +0 -1
  765. package/dist/extensions/background/actions.d.ts +0 -11
  766. package/dist/extensions/background/actions.d.ts.map +0 -1
  767. package/dist/extensions/background/actions.js.map +0 -1
  768. package/dist/extensions/background/completion-render.d.ts +0 -8
  769. package/dist/extensions/background/completion-render.d.ts.map +0 -1
  770. package/dist/extensions/background/completion-render.js.map +0 -1
  771. package/dist/extensions/background/constants.d.ts +0 -24
  772. package/dist/extensions/background/constants.d.ts.map +0 -1
  773. package/dist/extensions/background/constants.js +0 -24
  774. package/dist/extensions/background/constants.js.map +0 -1
  775. package/dist/extensions/background/index.d.ts +0 -7
  776. package/dist/extensions/background/index.d.ts.map +0 -1
  777. package/dist/extensions/background/index.js +0 -135
  778. package/dist/extensions/background/index.js.map +0 -1
  779. package/dist/extensions/background/keybindings.d.ts +0 -10
  780. package/dist/extensions/background/keybindings.d.ts.map +0 -1
  781. package/dist/extensions/background/keybindings.js +0 -14
  782. package/dist/extensions/background/keybindings.js.map +0 -1
  783. package/dist/extensions/background/manager.d.ts +0 -80
  784. package/dist/extensions/background/manager.d.ts.map +0 -1
  785. package/dist/extensions/background/manager.js +0 -673
  786. package/dist/extensions/background/manager.js.map +0 -1
  787. package/dist/extensions/background/render.d.ts +0 -42
  788. package/dist/extensions/background/render.d.ts.map +0 -1
  789. package/dist/extensions/background/render.js +0 -225
  790. package/dist/extensions/background/render.js.map +0 -1
  791. package/dist/extensions/background/schema.d.ts.map +0 -1
  792. package/dist/extensions/background/schema.js.map +0 -1
  793. package/dist/extensions/background/task-view.d.ts +0 -53
  794. package/dist/extensions/background/task-view.d.ts.map +0 -1
  795. package/dist/extensions/background/task-view.js +0 -60
  796. package/dist/extensions/background/task-view.js.map +0 -1
  797. package/dist/extensions/background/text.d.ts +0 -12
  798. package/dist/extensions/background/text.d.ts.map +0 -1
  799. package/dist/extensions/background/text.js +0 -39
  800. package/dist/extensions/background/text.js.map +0 -1
  801. package/dist/extensions/background/types.d.ts +0 -85
  802. package/dist/extensions/background/types.d.ts.map +0 -1
  803. package/dist/extensions/background/types.js +0 -17
  804. package/dist/extensions/background/types.js.map +0 -1
  805. package/dist/extensions/subagent/activity.d.ts +0 -34
  806. package/dist/extensions/subagent/activity.d.ts.map +0 -1
  807. package/dist/extensions/subagent/activity.js +0 -192
  808. package/dist/extensions/subagent/activity.js.map +0 -1
  809. package/dist/extensions/subagent/agents-command.d.ts +0 -4
  810. package/dist/extensions/subagent/agents-command.d.ts.map +0 -1
  811. package/dist/extensions/subagent/agents-command.js +0 -230
  812. package/dist/extensions/subagent/agents-command.js.map +0 -1
  813. package/dist/extensions/subagent/agents.d.ts +0 -6
  814. package/dist/extensions/subagent/agents.d.ts.map +0 -1
  815. package/dist/extensions/subagent/agents.js +0 -53
  816. package/dist/extensions/subagent/agents.js.map +0 -1
  817. package/dist/extensions/subagent/budget.d.ts +0 -15
  818. package/dist/extensions/subagent/budget.d.ts.map +0 -1
  819. package/dist/extensions/subagent/budget.js +0 -123
  820. package/dist/extensions/subagent/budget.js.map +0 -1
  821. package/dist/extensions/subagent/cancellation.d.ts +0 -29
  822. package/dist/extensions/subagent/cancellation.d.ts.map +0 -1
  823. package/dist/extensions/subagent/cancellation.js +0 -91
  824. package/dist/extensions/subagent/cancellation.js.map +0 -1
  825. package/dist/extensions/subagent/constants.d.ts +0 -25
  826. package/dist/extensions/subagent/constants.d.ts.map +0 -1
  827. package/dist/extensions/subagent/constants.js +0 -50
  828. package/dist/extensions/subagent/constants.js.map +0 -1
  829. package/dist/extensions/subagent/index.d.ts +0 -3
  830. package/dist/extensions/subagent/index.d.ts.map +0 -1
  831. package/dist/extensions/subagent/index.js +0 -151
  832. package/dist/extensions/subagent/index.js.map +0 -1
  833. package/dist/extensions/subagent/model-selection.d.ts +0 -16
  834. package/dist/extensions/subagent/model-selection.d.ts.map +0 -1
  835. package/dist/extensions/subagent/model-selection.js +0 -51
  836. package/dist/extensions/subagent/model-selection.js.map +0 -1
  837. package/dist/extensions/subagent/render.d.ts +0 -24
  838. package/dist/extensions/subagent/render.d.ts.map +0 -1
  839. package/dist/extensions/subagent/render.js +0 -336
  840. package/dist/extensions/subagent/render.js.map +0 -1
  841. package/dist/extensions/subagent/resolve.d.ts +0 -31
  842. package/dist/extensions/subagent/resolve.d.ts.map +0 -1
  843. package/dist/extensions/subagent/resolve.js +0 -111
  844. package/dist/extensions/subagent/resolve.js.map +0 -1
  845. package/dist/extensions/subagent/runner.d.ts +0 -35
  846. package/dist/extensions/subagent/runner.d.ts.map +0 -1
  847. package/dist/extensions/subagent/runner.js +0 -255
  848. package/dist/extensions/subagent/runner.js.map +0 -1
  849. package/dist/extensions/subagent/schema.d.ts +0 -28
  850. package/dist/extensions/subagent/schema.d.ts.map +0 -1
  851. package/dist/extensions/subagent/schema.js +0 -58
  852. package/dist/extensions/subagent/schema.js.map +0 -1
  853. package/dist/extensions/subagent/sdk-runner.d.ts +0 -33
  854. package/dist/extensions/subagent/sdk-runner.d.ts.map +0 -1
  855. package/dist/extensions/subagent/sdk-runner.js +0 -331
  856. package/dist/extensions/subagent/sdk-runner.js.map +0 -1
  857. package/dist/extensions/subagent/settings.d.ts +0 -8
  858. package/dist/extensions/subagent/settings.d.ts.map +0 -1
  859. package/dist/extensions/subagent/settings.js +0 -206
  860. package/dist/extensions/subagent/settings.js.map +0 -1
  861. package/dist/extensions/subagent/state.d.ts +0 -102
  862. package/dist/extensions/subagent/state.d.ts.map +0 -1
  863. package/dist/extensions/subagent/state.js +0 -383
  864. package/dist/extensions/subagent/state.js.map +0 -1
  865. package/dist/extensions/subagent/text.d.ts +0 -6
  866. package/dist/extensions/subagent/text.d.ts.map +0 -1
  867. package/dist/extensions/subagent/text.js +0 -66
  868. package/dist/extensions/subagent/text.js.map +0 -1
  869. package/dist/extensions/subagent/types.d.ts +0 -91
  870. package/dist/extensions/subagent/types.d.ts.map +0 -1
  871. package/dist/extensions/subagent/types.js +0 -2
  872. package/dist/extensions/subagent/types.js.map +0 -1
  873. package/dist/extensions/subagent/ui/agents-dialog.d.ts +0 -4
  874. package/dist/extensions/subagent/ui/agents-dialog.d.ts.map +0 -1
  875. package/dist/extensions/subagent/ui/agents-dialog.js +0 -84
  876. package/dist/extensions/subagent/ui/agents-dialog.js.map +0 -1
  877. package/dist/extensions/subagent/ui/choice-menu.d.ts +0 -39
  878. package/dist/extensions/subagent/ui/choice-menu.d.ts.map +0 -1
  879. package/dist/extensions/subagent/ui/choice-menu.js +0 -93
  880. package/dist/extensions/subagent/ui/choice-menu.js.map +0 -1
  881. package/dist/extensions/subagent/ui/choices.d.ts +0 -36
  882. package/dist/extensions/subagent/ui/choices.d.ts.map +0 -1
  883. package/dist/extensions/subagent/ui/choices.js +0 -54
  884. package/dist/extensions/subagent/ui/choices.js.map +0 -1
  885. package/dist/extensions/subagent/ui/model-list.d.ts +0 -66
  886. package/dist/extensions/subagent/ui/model-list.d.ts.map +0 -1
  887. package/dist/extensions/subagent/ui/model-list.js +0 -235
  888. package/dist/extensions/subagent/ui/model-list.js.map +0 -1
  889. package/dist/extensions/subagent/ui/model-picker.d.ts +0 -47
  890. package/dist/extensions/subagent/ui/model-picker.d.ts.map +0 -1
  891. package/dist/extensions/subagent/ui/model-picker.js +0 -143
  892. package/dist/extensions/subagent/ui/model-picker.js.map +0 -1
  893. package/dist/extensions/subagent/ui/profile-settings-menu.d.ts +0 -41
  894. package/dist/extensions/subagent/ui/profile-settings-menu.d.ts.map +0 -1
  895. package/dist/extensions/subagent/ui/profile-settings-menu.js +0 -98
  896. package/dist/extensions/subagent/ui/profile-settings-menu.js.map +0 -1
  897. package/dist/extensions/todo/constants.d.ts +0 -16
  898. package/dist/extensions/todo/constants.d.ts.map +0 -1
  899. package/dist/extensions/todo/constants.js +0 -30
  900. package/dist/extensions/todo/constants.js.map +0 -1
  901. package/dist/extensions/todo/index.d.ts +0 -3
  902. package/dist/extensions/todo/index.d.ts.map +0 -1
  903. package/dist/extensions/todo/index.js +0 -98
  904. package/dist/extensions/todo/index.js.map +0 -1
  905. package/dist/extensions/todo/schema.d.ts +0 -60
  906. package/dist/extensions/todo/schema.d.ts.map +0 -1
  907. package/dist/extensions/todo/schema.js +0 -56
  908. package/dist/extensions/todo/schema.js.map +0 -1
  909. package/dist/extensions/todo/state.d.ts +0 -34
  910. package/dist/extensions/todo/state.d.ts.map +0 -1
  911. package/dist/extensions/todo/state.js +0 -425
  912. package/dist/extensions/todo/state.js.map +0 -1
  913. package/dist/extensions/todo/view.d.ts +0 -36
  914. package/dist/extensions/todo/view.d.ts.map +0 -1
  915. package/dist/extensions/todo/view.js +0 -580
  916. package/dist/extensions/todo/view.js.map +0 -1
  917. package/dist/extensions/todo/widget.d.ts +0 -15
  918. package/dist/extensions/todo/widget.d.ts.map +0 -1
  919. package/dist/extensions/todo/widget.js +0 -50
  920. package/dist/extensions/todo/widget.js.map +0 -1
  921. package/docs/bundled/extensions/background.md +0 -132
  922. package/docs/bundled/extensions/subagent.md +0 -148
  923. package/docs/bundled/extensions/todo.md +0 -104
  924. package/examples/extensions/todo.ts +0 -297
@@ -1,3 +1,5 @@
1
+ import { bindTasksUI } from "./tasks/index.js";
2
+ import { cleanTaskText, firstCommandLine } from "./tasks/text.js";
1
3
  /**
2
4
  * Interactive mode for the coding agent.
3
5
  * Handles TUI rendering and user interaction, delegating business logic to AgentSession.
@@ -25,6 +27,7 @@ import { createCompactionSummaryMessage, createCustomMessage } from "../../core/
25
27
  import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScopeFromModels, } from "../../core/model-resolver.js";
26
28
  import { CredentialSynchronizationError } from "../../core/model-runtime.js";
27
29
  import { DefaultPackageManager } from "../../core/package-manager.js";
30
+ import { RADIUS_MCP_URL, RADIUS_PROVIDER_ID } from "../../core/radius.js";
28
31
  import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
29
32
  import { SessionManager, sessionEntryToContextMessages, } from "../../core/session-manager.js";
30
33
  import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
@@ -32,8 +35,9 @@ import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
32
35
  import { withBuiltInRenderers } from "../../core/tools/renderers/index.js";
33
36
  import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
34
37
  import { getUsageCostBreakdown } from "../../core/usage-totals.js";
38
+ import { addMcpServerConfig, loadMcpConfig } from "../../extensions/mcp/config.js";
35
39
  import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
36
- import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
40
+ import { copyToClipboard, readClipboardFilePaths, readClipboardText } from "../../utils/clipboard.js";
37
41
  import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
38
42
  import { parseGitUrl } from "../../utils/git.js";
39
43
  import { getCwdRelativePath } from "../../utils/paths.js";
@@ -63,12 +67,16 @@ import { formatKeyText, keyDisplayText, keyHint, keyText, rawKeyHint } from "./c
63
67
  import { LoginDialogComponent } from "./components/login-dialog.js";
64
68
  import { createMermaidMarkdownTransformer } from "./components/mermaid.js";
65
69
  import { ModelSelectorComponent } from "./components/model-selector.js";
66
- import { formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
70
+ import { formatAuthSelectorProviderStatus, formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
71
+ import { piLogoLines, piWordmark, supportsPiLogo } from "./components/pi-logo.js";
72
+ import { playPiLogoAnimation } from "./components/pi-logo-animation.lazy.js";
73
+ import { createLoginMenuSelector } from "./components/radius-login-selector.js";
67
74
  import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
68
75
  import { SessionSelectorComponent } from "./components/session-selector.js";
69
76
  import { SettingsSelectorComponent } from "./components/settings-selector.js";
70
77
  import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
71
78
  import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
79
+ import { ThemedText } from "./components/themed-text.js";
72
80
  import { ThinkingSelectorComponent } from "./components/thinking-selector.js";
73
81
  import { TreeSelectorComponent } from "./components/tree-selector.js";
74
82
  import { TrustSelectorComponent } from "./components/trust-selector.js";
@@ -79,7 +87,7 @@ import { editInExternalEditor } from "./external-editor.js";
79
87
  import { refreshModelCatalogs } from "./model-catalog-refresh.js";
80
88
  import { getModelSearchText } from "./model-search.js";
81
89
  import { shareSession } from "./session-share.js";
82
- import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
90
+ import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, SYSTEM_THEME_NAME, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
83
91
  import { InteractiveThemeController } from "./theme/theme-controller.js";
84
92
  import { disposeChatRows, PendingToolMap, ToolChatContainer } from "./tool-view/chat.js";
85
93
  import { ToolExecutionComponent } from "./tool-view/tool-execution.js";
@@ -94,14 +102,24 @@ function isWorkingStatusEditor(editor) {
94
102
  function isExpandable(obj) {
95
103
  return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
96
104
  }
97
- class ExpandableText extends Text {
105
+ class ExpandableText extends ThemedText {
98
106
  constructor(getCollapsedText, getExpandedText, expanded = false, paddingX = 0, paddingY = 0) {
99
- super(expanded ? getExpandedText() : getCollapsedText(), paddingX, paddingY);
100
- this.getCollapsedText = getCollapsedText;
101
- this.getExpandedText = getExpandedText;
107
+ const state = { expanded };
108
+ super(() => (state.expanded ? getExpandedText() : getCollapsedText()), paddingX, paddingY);
109
+ this.state = state;
102
110
  }
103
111
  setExpanded(expanded) {
104
- this.setText(expanded ? this.getExpandedText() : this.getCollapsedText());
112
+ this.state.expanded = expanded;
113
+ this.invalidate();
114
+ }
115
+ }
116
+ /** The built-in header. Clicking its logo (the first two lines, after one column of padding) plays an easter egg. */
117
+ class BuiltInHeader extends ExpandableText {
118
+ handleMouse(event) {
119
+ if (event.type !== "click" || event.y > 1 || event.x < 1 || event.x > 4 || !this.onLogoClick)
120
+ return undefined;
121
+ this.onLogoClick(event.screenX - event.x + 1, event.screenY - event.y);
122
+ return { handled: true };
105
123
  }
106
124
  }
107
125
  function isCustomSessionEntry(item) {
@@ -173,6 +191,7 @@ function llamaCppPostLoginGuidance(actionLabel, loadedModelCount) {
173
191
  ? `${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`
174
192
  : `${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`;
175
193
  }
194
+ const RADIUS_LOGIN_INTRO = "Radius is a service crafted for Pi by the builders of Pi, Earendil Works";
176
195
  const AUTH_TYPE_ORDER = { oauth: 0, api_key: 1 };
177
196
  function createFuzzyAutocompleteItems(items, prefix, getSearchText, toAutocompleteItem) {
178
197
  const filtered = fuzzyFilter(items, prefix, getSearchText);
@@ -195,18 +214,21 @@ function getLoginProviderCompletionOptions(providerOptions) {
195
214
  id: provider.id,
196
215
  name: provider.name,
197
216
  authTypes: [provider.authType],
217
+ subscription: provider.subscription,
198
218
  });
199
219
  }
200
220
  return Array.from(byId.values()).sort((a, b) => a.name.localeCompare(b.name));
201
221
  }
202
222
  function getLoginProviderSearchText(provider) {
203
223
  const authTypes = provider.authTypes
204
- .map((authType) => `${authType} ${formatAuthSelectorProviderType(authType)}`)
224
+ .map((authType) => `${authType} ${formatAuthSelectorProviderType(authType, provider.subscription)}`)
205
225
  .join(" ");
206
226
  return `${provider.id} ${provider.name} ${authTypes}`;
207
227
  }
208
228
  function formatLoginProviderCompletionDescription(provider) {
209
- const authTypes = provider.authTypes.map(formatAuthSelectorProviderType).join("/");
229
+ const authTypes = provider.authTypes
230
+ .map((authType) => formatAuthSelectorProviderType(authType, provider.subscription))
231
+ .join("/");
210
232
  return provider.name === provider.id ? authTypes : `${provider.name} · ${authTypes}`;
211
233
  }
212
234
  export class InteractiveMode {
@@ -244,6 +266,7 @@ export class InteractiveMode {
244
266
  // Status line tracking (for mutating immediately-sequential status updates)
245
267
  this.lastStatusSpacer = undefined;
246
268
  this.lastStatusText = undefined;
269
+ this.lastStatusMessage = "";
247
270
  this.managedToolStatusStarted = false;
248
271
  // Streaming message tracking
249
272
  this.streamingComponent = undefined;
@@ -316,11 +339,12 @@ export class InteractiveMode {
316
339
  this.options = { ...options, tuiMode };
317
340
  this.autoTrustOnReloadCwd = options.autoTrustOnReloadCwd;
318
341
  this.runtimeHost.setBeforeSessionInvalidate(() => {
342
+ this.tasksUI?.dispose();
319
343
  this.resetExtensionUI();
320
344
  });
321
345
  this.runtimeHost.setRebindSession(async () => {
322
346
  await this.rebindCurrentSession({ renderBeforeBind: true });
323
- await this.themeController.applyFromSettings();
347
+ this.themeController.applyFromSettings();
324
348
  });
325
349
  this.version = VERSION;
326
350
  this.renderer = createInteractiveTui({
@@ -330,6 +354,7 @@ export class InteractiveMode {
330
354
  terminal: options.terminal,
331
355
  onRightClickPaste: this.onRightClickPaste,
332
356
  fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
357
+ fullscreenWheelScrollLines: this.settingsManager.getFullscreenWheelScrollLines(),
333
358
  });
334
359
  this.ui = createInteractiveTuiReference(() => this.renderer);
335
360
  this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
@@ -374,7 +399,8 @@ export class InteractiveMode {
374
399
  });
375
400
  }
376
401
  getAutocompleteSourceTag(sourceInfo) {
377
- if (!sourceInfo) {
402
+ // Built-in extension commands are untagged, like built-in commands.
403
+ if (!sourceInfo || sourceInfo.source === "builtin") {
378
404
  return undefined;
379
405
  }
380
406
  const scopePrefix = sourceInfo.scope === "user" ? "u" : sourceInfo.scope === "project" ? "p" : "t";
@@ -527,7 +553,7 @@ export class InteractiveMode {
527
553
  this.chatContainer.addChild(new Text(condensedText, 1, 0));
528
554
  }
529
555
  else {
530
- this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
556
+ this.chatContainer.addChild(new ThemedText(() => theme.bold(theme.fg("accent", "What's New")), 1, 0));
531
557
  this.chatContainer.addChild(new Spacer(1));
532
558
  this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(), 1, 0, this.getMarkdownThemeWithSettings()));
533
559
  this.chatContainer.addChild(new Spacer(1));
@@ -579,6 +605,7 @@ export class InteractiveMode {
579
605
  terminal,
580
606
  onRightClickPaste: this.onRightClickPaste,
581
607
  fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
608
+ fullscreenWheelScrollLines: this.settingsManager.getFullscreenWheelScrollLines(),
582
609
  });
583
610
  nextUi.setClearOnShrink(clearOnShrink);
584
611
  nextUi.onDebug = onDebug;
@@ -608,7 +635,7 @@ export class InteractiveMode {
608
635
  this.registerSignalHandlers();
609
636
  // Load changelog (only show new entries, skip for resumed sessions)
610
637
  this.changelogMarkdown = this.getChangelogForDisplay();
611
- if (this.session.scopedModels.length > 0 && (this.options.verbose || !this.settingsManager.getQuietStartup())) {
638
+ if (this.session.scopedModels.length > 0 && this.shouldShowStartupDetails()) {
612
639
  const modelList = this.session.scopedModels
613
640
  .map((sm) => {
614
641
  const thinkingStr = sm.thinkingLevel ? `:${sm.thinkingLevel}` : "";
@@ -654,13 +681,26 @@ export class InteractiveMode {
654
681
  // Start the UI before initializing extensions so session_start handlers can use interactive dialogs
655
682
  this.ui.start();
656
683
  this.isInitialized = true;
657
- await this.themeController.applyFromSettings();
684
+ this.themeController.applyFromSettings();
685
+ // The header and startup notices bake theme colors into their text, so build them once the terminal
686
+ // reported its colors. This ends at the terminal's DA1 reply, or after 100 ms if it answers nothing.
687
+ await this.themeController.waitForTerminalColors();
658
688
  // Add header with keybindings from config (unless silenced)
659
- if (this.options.verbose || !this.settingsManager.getQuietStartup()) {
660
- const logo = theme.bold(theme.fg("accent", APP_NAME)) + theme.fg("dim", ` v${this.version}`);
689
+ if (this.shouldShowStartupHeader()) {
690
+ const showDetails = this.shouldShowStartupDetails();
691
+ // Built on demand so the header follows theme changes. The logo's first line carries the version,
692
+ // its second line the first line of key hints. Terminals that cannot render the logo get a
693
+ // "Pi vX" line instead, with the key hints below it.
694
+ const showLogo = supportsPiLogo();
695
+ const withLogo = (hints) => {
696
+ if (!showLogo)
697
+ return `${piWordmark()} ${theme.fg("dim", `v${this.version}`)}\n${hints}`;
698
+ const [top, bottom] = piLogoLines();
699
+ return `${top} ${theme.fg("dim", `v${this.version}`)}\n${bottom} ${hints}`;
700
+ };
661
701
  // Build startup instructions using keybinding hint helpers
662
702
  const hint = (keybinding, description) => keyHint(keybinding, description);
663
- const expandedInstructions = [
703
+ const expandedInstructions = () => [
664
704
  hint("app.interrupt", "to interrupt"),
665
705
  hint("app.clear", "to clear"),
666
706
  rawKeyHint(`${keyText("app.clear")} twice`, "to exit"),
@@ -678,19 +718,22 @@ export class InteractiveMode {
678
718
  rawKeyHint("!!", "to run bash (no context)"),
679
719
  hint("app.message.followUp", "to queue follow-up"),
680
720
  hint("app.message.dequeue", "to edit all queued messages"),
681
- hint("app.clipboard.pasteImage", "to paste image (with text fallback)"),
721
+ hint("app.clipboard.pasteImage", "to paste files on macOS, images, or text"),
682
722
  rawKeyHint("drop files", "to attach"),
683
723
  ].join("\n");
684
- const compactInstructions = [
724
+ const compactInstructions = () => [
685
725
  hint("app.interrupt", "interrupt"),
686
726
  rawKeyHint(`${keyText("app.clear")}/${keyText("app.exit")}`, "clear/exit"),
687
727
  rawKeyHint("/", "commands"),
688
728
  rawKeyHint("!", "bash"),
689
729
  hint("app.tools.expand", "more"),
690
730
  ].join(theme.fg("muted", " · "));
691
- const compactOnboarding = theme.fg("dim", `Press ${keyText("app.tools.expand")} to show full startup help and loaded resources.`);
692
- const onboarding = theme.fg("dim", `Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.`);
693
- this.builtInHeader = new ExpandableText(() => `${logo}\n${compactInstructions}\n${compactOnboarding}\n\n${onboarding}`, () => `${logo}\n${expandedInstructions}\n\n${onboarding}`, this.getStartupExpansionState(), 1, 0);
731
+ const compactOnboarding = () => theme.fg("dim", `Press ${keyText("app.tools.expand")} to show full startup help${showDetails ? " and loaded resources" : ""}.`);
732
+ const onboarding = () => theme.fg("dim", `Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.`);
733
+ const header = new BuiltInHeader(() => `${withLogo(compactInstructions())}\n${compactOnboarding()}\n\n${onboarding()}`, () => `${withLogo(expandedInstructions())}\n\n${onboarding()}`, this.getStartupExpansionState(), 1, 0);
734
+ if (showLogo)
735
+ header.onLogoClick = (column, row) => playPiLogoAnimation(this.renderer, column, row);
736
+ this.builtInHeader = header;
694
737
  // Setup UI layout
695
738
  this.headerContainer.addChild(new Spacer(1));
696
739
  this.headerContainer.addChild(this.builtInHeader);
@@ -991,6 +1034,14 @@ export class InteractiveMode {
991
1034
  getStartupExpansionState() {
992
1035
  return this.options.verbose || this.toolOutputExpanded;
993
1036
  }
1037
+ /** Startup header (logo, version, key hints). Hidden only by quietStartup: true. */
1038
+ shouldShowStartupHeader() {
1039
+ return this.options.verbose === true || this.settingsManager.getQuietStartup() !== true;
1040
+ }
1041
+ /** Startup details (model scope, loaded resources). Hidden by quietStartup: true or "header". */
1042
+ shouldShowStartupDetails() {
1043
+ return this.options.verbose === true || this.settingsManager.getQuietStartup() === false;
1044
+ }
994
1045
  /**
995
1046
  * Get a short path relative to the package root for display.
996
1047
  */
@@ -1252,7 +1303,7 @@ export class InteractiveMode {
1252
1303
  showLoadedResources(options) {
1253
1304
  // Resource rendering is idempotent; chat clears no longer clear this separate container.
1254
1305
  this.loadedResourcesContainer.clear();
1255
- const showListing = options?.force || this.options.verbose || !this.settingsManager.getQuietStartup();
1306
+ const showListing = options?.force || this.shouldShowStartupDetails();
1256
1307
  const showDiagnostics = showListing || options?.showDiagnosticsWhenQuiet === true;
1257
1308
  if (!showListing && !showDiagnostics) {
1258
1309
  return;
@@ -1265,8 +1316,9 @@ export class InteractiveMode {
1265
1316
  }
1266
1317
  return theme.fg("dim", ` ${labels.join(", ")}`);
1267
1318
  };
1319
+ // Bodies are built on demand so the listing follows theme changes.
1268
1320
  const addLoadedSection = (name, collapsedBody, expandedBody = collapsedBody, color = "mdHeading") => {
1269
- const section = new ExpandableText(() => `${sectionHeader(name, color)}\n${collapsedBody}`, () => `${sectionHeader(name, color)}\n${expandedBody}`, this.getStartupExpansionState(), 0, 0);
1321
+ const section = new ExpandableText(() => `${sectionHeader(name, color)}\n${collapsedBody()}`, () => `${sectionHeader(name, color)}\n${expandedBody()}`, this.getStartupExpansionState(), 0, 0);
1270
1322
  this.loadedResourcesContainer.addChild(section);
1271
1323
  this.loadedResourcesContainer.addChild(new Spacer(1));
1272
1324
  };
@@ -1311,27 +1363,25 @@ export class InteractiveMode {
1311
1363
  ];
1312
1364
  if (contextFiles.length > 0) {
1313
1365
  this.loadedResourcesContainer.addChild(new Spacer(1));
1314
- const contextList = contextFiles
1315
- .map((f) => theme.fg("dim", ` ${this.formatDisplayPath(f.path)}`))
1316
- .join("\n");
1317
- const contextCompactList = formatCompactList(contextFiles.map((contextFile) => this.formatContextPath(contextFile.path)), { sort: false });
1366
+ const contextList = () => contextFiles.map((f) => theme.fg("dim", ` ${this.formatDisplayPath(f.path)}`)).join("\n");
1367
+ const contextCompactList = () => formatCompactList(contextFiles.map((contextFile) => this.formatContextPath(contextFile.path)), { sort: false });
1318
1368
  addLoadedSection("Context", contextCompactList, contextList);
1319
1369
  }
1320
1370
  const skills = skillsResult.skills;
1321
1371
  if (skills.length > 0) {
1322
1372
  const groups = this.buildScopeGroups(skills.map((skill) => ({ path: skill.filePath, sourceInfo: skill.sourceInfo })));
1323
- const skillList = this.formatScopeGroups(groups, {
1373
+ const skillList = () => this.formatScopeGroups(groups, {
1324
1374
  formatPath: (item) => this.formatDisplayPath(item.path),
1325
1375
  formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
1326
1376
  });
1327
- const skillCompactList = formatCompactList(skills.map((skill) => skill.name));
1377
+ const skillCompactList = () => formatCompactList(skills.map((skill) => skill.name));
1328
1378
  addLoadedSection("Skills", skillCompactList, skillList);
1329
1379
  }
1330
1380
  const templates = this.session.promptTemplates;
1331
1381
  if (templates.length > 0) {
1332
1382
  const groups = this.buildScopeGroups(templates.map((template) => ({ path: template.filePath, sourceInfo: template.sourceInfo })));
1333
1383
  const templateByPath = new Map(templates.map((t) => [t.filePath, t]));
1334
- const templateList = this.formatScopeGroups(groups, {
1384
+ const templateList = () => this.formatScopeGroups(groups, {
1335
1385
  formatPath: (item) => {
1336
1386
  const template = templateByPath.get(item.path);
1337
1387
  return template ? `/${template.name}` : this.formatDisplayPath(item.path);
@@ -1341,53 +1391,40 @@ export class InteractiveMode {
1341
1391
  return template ? `/${template.name}` : this.formatDisplayPath(item.path);
1342
1392
  },
1343
1393
  });
1344
- const promptCompactList = formatCompactList(templates.map((template) => `/${template.name}`));
1394
+ const promptCompactList = () => formatCompactList(templates.map((template) => `/${template.name}`));
1345
1395
  addLoadedSection("Prompts", promptCompactList, templateList);
1346
1396
  }
1347
1397
  if (extensions.length > 0) {
1348
1398
  const groups = this.buildScopeGroups(extensions);
1349
- const extList = this.formatScopeGroups(groups, {
1399
+ const extList = () => this.formatScopeGroups(groups, {
1350
1400
  formatPath: (item) => this.formatExtensionDisplayPath(item.path),
1351
1401
  formatPackagePath: (item) => this.formatExtensionDisplayPath(this.getShortPath(item.path, item.sourceInfo)),
1352
1402
  });
1353
- const extensionCompactList = formatCompactList(this.getCompactExtensionLabels(extensions));
1403
+ const extensionLabels = this.getCompactExtensionLabels(extensions);
1404
+ const extensionCompactList = () => formatCompactList(extensionLabels);
1354
1405
  addLoadedSection("Extensions", extensionCompactList, extList, "mdHeading");
1355
1406
  }
1356
- // Show loaded themes (excluding built-in)
1357
- const loadedThemes = themesResult.themes;
1358
- const customThemes = loadedThemes.filter((t) => t.sourcePath);
1359
- if (customThemes.length > 0) {
1360
- const groups = this.buildScopeGroups(customThemes.map((loadedTheme) => ({
1361
- path: loadedTheme.sourcePath,
1362
- sourceInfo: loadedTheme.sourceInfo,
1363
- })));
1364
- const themeList = this.formatScopeGroups(groups, {
1365
- formatPath: (item) => this.formatDisplayPath(item.path),
1366
- formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
1367
- });
1368
- const themeCompactList = formatCompactList(customThemes.map((loadedTheme) => loadedTheme.name ?? this.getCompactPathLabel(loadedTheme.sourcePath, loadedTheme.sourceInfo)));
1369
- addLoadedSection("Themes", themeCompactList, themeList);
1370
- }
1371
1407
  }
1372
1408
  if (showDiagnostics) {
1373
1409
  const skillDiagnostics = skillsResult.diagnostics;
1374
1410
  if (skillDiagnostics.length > 0) {
1375
- const warningLines = this.formatDiagnostics(skillDiagnostics, sourceInfos);
1376
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Skill conflicts]")}\n${warningLines}`, 0, 0));
1411
+ const warningLines = () => this.formatDiagnostics(skillDiagnostics, sourceInfos);
1412
+ this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Skill conflicts]")}\n${warningLines()}`, 0, 0));
1377
1413
  this.loadedResourcesContainer.addChild(new Spacer(1));
1378
1414
  }
1379
1415
  const promptDiagnostics = promptsResult.diagnostics;
1380
1416
  if (promptDiagnostics.length > 0) {
1381
- const warningLines = this.formatDiagnostics(promptDiagnostics, sourceInfos);
1382
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Prompt conflicts]")}\n${warningLines}`, 0, 0));
1417
+ const warningLines = () => this.formatDiagnostics(promptDiagnostics, sourceInfos);
1418
+ this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Prompt conflicts]")}\n${warningLines()}`, 0, 0));
1383
1419
  this.loadedResourcesContainer.addChild(new Spacer(1));
1384
1420
  }
1385
1421
  const extensionDiagnostics = [];
1386
- const extensionErrors = this.session.resourceLoader.getExtensions().errors;
1387
- if (extensionErrors.length > 0) {
1388
- for (const error of extensionErrors) {
1389
- extensionDiagnostics.push({ type: "error", message: error.error, path: error.path });
1390
- }
1422
+ const extensionsResult = this.session.resourceLoader.getExtensions();
1423
+ for (const error of extensionsResult.errors) {
1424
+ extensionDiagnostics.push({ type: "error", message: error.error, path: error.path });
1425
+ }
1426
+ for (const warning of extensionsResult.warnings ?? []) {
1427
+ extensionDiagnostics.push({ type: "warning", message: warning.warning, path: warning.path });
1391
1428
  }
1392
1429
  const commandDiagnostics = this.session.extensionRunner.getCommandDiagnostics();
1393
1430
  extensionDiagnostics.push(...commandDiagnostics);
@@ -1395,14 +1432,14 @@ export class InteractiveMode {
1395
1432
  const shortcutDiagnostics = this.session.extensionRunner.getShortcutDiagnostics();
1396
1433
  extensionDiagnostics.push(...shortcutDiagnostics);
1397
1434
  if (extensionDiagnostics.length > 0) {
1398
- const warningLines = this.formatDiagnostics(extensionDiagnostics, sourceInfos);
1399
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Extension issues]")}\n${warningLines}`, 0, 0));
1435
+ const warningLines = () => this.formatDiagnostics(extensionDiagnostics, sourceInfos);
1436
+ this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Extension issues]")}\n${warningLines()}`, 0, 0));
1400
1437
  this.loadedResourcesContainer.addChild(new Spacer(1));
1401
1438
  }
1402
1439
  const themeDiagnostics = themesResult.diagnostics;
1403
1440
  if (themeDiagnostics.length > 0) {
1404
- const warningLines = this.formatDiagnostics(themeDiagnostics, sourceInfos);
1405
- this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning", "[Theme conflicts]")}\n${warningLines}`, 0, 0));
1441
+ const warningLines = () => this.formatDiagnostics(themeDiagnostics, sourceInfos);
1442
+ this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Theme conflicts]")}\n${warningLines()}`, 0, 0));
1406
1443
  this.loadedResourcesContainer.addChild(new Spacer(1));
1407
1444
  }
1408
1445
  }
@@ -1411,11 +1448,12 @@ export class InteractiveMode {
1411
1448
  * Initialize the extension system with TUI-based UI context.
1412
1449
  */
1413
1450
  async bindCurrentSessionExtensions() {
1451
+ this.tasksUI?.dispose();
1414
1452
  const uiContext = this.createExtensionUIContext();
1415
1453
  await this.session.bindExtensions({
1416
1454
  uiContext,
1417
1455
  mode: "tui",
1418
- backgroundEnabled: true,
1456
+ tasksEnabled: true,
1419
1457
  abortHandler: () => {
1420
1458
  this.restoreQueuedMessagesToEditor({ abort: true });
1421
1459
  },
@@ -1479,6 +1517,7 @@ export class InteractiveMode {
1479
1517
  this.showExtensionError(error.extensionPath, error.error, error.stack);
1480
1518
  },
1481
1519
  });
1520
+ this.tasksUI = bindTasksUI({ tasks: this.session.tasks, ui: uiContext });
1482
1521
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
1483
1522
  this.setupAutocompleteProvider();
1484
1523
  const extensionRunner = this.session.extensionRunner;
@@ -1495,6 +1534,7 @@ export class InteractiveMode {
1495
1534
  this.applyFullscreenScrollbarSetting();
1496
1535
  if (this.renderer instanceof TuiAltScreen) {
1497
1536
  this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
1537
+ this.renderer.setWheelScrollLines(this.settingsManager.getFullscreenWheelScrollLines());
1498
1538
  }
1499
1539
  this.footer.setSession(this.session);
1500
1540
  this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
@@ -1541,10 +1581,11 @@ export class InteractiveMode {
1541
1581
  this.showError(`${prefix}: ${message}`);
1542
1582
  const extensionHint = this.getCrashExtensionHint(error);
1543
1583
  if (extensionHint) {
1544
- this.chatContainer.addChild(new Text(theme.fg("warning", extensionHint), this.outputPad, 0));
1584
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", extensionHint), this.outputPad, 0));
1545
1585
  }
1546
1586
  if (this.recordCrash("fatal_error", error)) {
1547
- this.chatContainer.addChild(new Text(theme.fg("muted", this.crashReportInstructions()), this.outputPad, 0));
1587
+ const instructions = this.crashReportInstructions();
1588
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("muted", instructions), this.outputPad, 0));
1548
1589
  }
1549
1590
  stopThemeWatcher();
1550
1591
  this.stop("transcript");
@@ -1580,7 +1621,7 @@ export class InteractiveMode {
1580
1621
  if (this.bugReportHintShown)
1581
1622
  return;
1582
1623
  this.bugReportHintShown = true;
1583
- 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));
1624
+ 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));
1584
1625
  this.ui.requestRender();
1585
1626
  }
1586
1627
  maybeSuggestBugReport(message) {
@@ -1741,7 +1782,7 @@ export class InteractiveMode {
1741
1782
  container.addChild(new Text(line, 1, 0));
1742
1783
  }
1743
1784
  if (content.length > InteractiveMode.MAX_WIDGET_LINES) {
1744
- container.addChild(new Text(theme.fg("muted", "... (widget truncated)"), 1, 0));
1785
+ container.addChild(new ThemedText(() => theme.fg("muted", "... (widget truncated)"), 1, 0));
1745
1786
  }
1746
1787
  component = container;
1747
1788
  }
@@ -2263,17 +2304,14 @@ export class InteractiveMode {
2263
2304
  */
2264
2305
  showExtensionError(extensionPath, error, stack) {
2265
2306
  const errorMsg = `Extension "${extensionPath}" error: ${error}`;
2266
- const errorText = new Text(theme.fg("error", errorMsg), 1, 0);
2307
+ const errorText = new ThemedText(() => theme.fg("error", errorMsg), 1, 0);
2267
2308
  this.chatContainer.addChild(errorText);
2268
2309
  if (stack) {
2269
2310
  // Show stack trace in dim color, indented
2270
- const stackLines = stack
2271
- .split("\n")
2272
- .slice(1) // Skip first line (duplicates error message)
2273
- .map((line) => theme.fg("dim", ` ${line.trim()}`))
2274
- .join("\n");
2275
- if (stackLines) {
2276
- this.chatContainer.addChild(new Text(stackLines, 1, 0));
2311
+ const stackLines = stack.split("\n").slice(1); // Skip first line (duplicates error message)
2312
+ if (stackLines.length > 0) {
2313
+ const renderStack = () => stackLines.map((line) => theme.fg("dim", ` ${line.trim()}`)).join("\n");
2314
+ this.chatContainer.addChild(new ThemedText(renderStack, 1, 0));
2277
2315
  }
2278
2316
  }
2279
2317
  this.ui.requestRender();
@@ -2343,8 +2381,8 @@ export class InteractiveMode {
2343
2381
  this.updateEditorBorderColor();
2344
2382
  }
2345
2383
  };
2346
- // Handle clipboard paste (triggered on Ctrl+V). Images are attached by path;
2347
- // otherwise, paste plain text from the system clipboard.
2384
+ // Handle clipboard paste (triggered on Ctrl+V). Copied files use their original paths,
2385
+ // images are attached via temporary files, and plain text is the final fallback.
2348
2386
  this.defaultEditor.onPasteImage = () => {
2349
2387
  void this.handleClipboardPaste();
2350
2388
  };
@@ -2367,6 +2405,22 @@ export class InteractiveMode {
2367
2405
  }
2368
2406
  async handleClipboardPaste() {
2369
2407
  try {
2408
+ const filePaths = await readClipboardFilePaths();
2409
+ if (filePaths) {
2410
+ if (filePaths.some((filePath) => /\p{Cc}/u.test(filePath))) {
2411
+ throw new Error("Clipboard file path contains control characters");
2412
+ }
2413
+ const paths = this.isBashMode ? filePaths.map(quoteIfNeeded).join(" ") : filePaths.join("\n");
2414
+ const cursor = this.editor.getCursor?.();
2415
+ const currentLine = cursor ? (this.editor.getText().split("\n")[cursor.line] ?? "") : "";
2416
+ const characterBeforeCursor = cursor && cursor.col > 0 ? currentLine[cursor.col - 1] : "";
2417
+ const characterAfterCursor = cursor ? currentLine[cursor.col] : "";
2418
+ const leadingSpace = characterBeforeCursor && !/\s/.test(characterBeforeCursor) ? " " : "";
2419
+ const trailingSpace = characterAfterCursor && !/\s/.test(characterAfterCursor) ? " " : "";
2420
+ this.editor.insertTextAtCursor?.(`${leadingSpace}${paths}${trailingSpace}`);
2421
+ this.ui.requestRender();
2422
+ return;
2423
+ }
2370
2424
  const image = await readClipboardImage();
2371
2425
  if (image) {
2372
2426
  const tmpDir = os.tmpdir();
@@ -2384,8 +2438,8 @@ export class InteractiveMode {
2384
2438
  this.ui.requestRender();
2385
2439
  }
2386
2440
  }
2387
- catch {
2388
- // Silently ignore clipboard errors (may not have permission, etc.)
2441
+ catch (error) {
2442
+ this.showError(`Failed to paste from clipboard: ${error instanceof Error ? error.message : String(error)}`);
2389
2443
  }
2390
2444
  }
2391
2445
  handleStartupSubmit(text) {
@@ -2400,6 +2454,11 @@ export class InteractiveMode {
2400
2454
  if (this.editorHost.intercept(text, "steer"))
2401
2455
  return;
2402
2456
  // Handle commands
2457
+ if (text === "/tasks") {
2458
+ this.editor.setText("");
2459
+ await this.tasksUI?.open();
2460
+ return;
2461
+ }
2403
2462
  if (text === "/settings") {
2404
2463
  this.showSettingsSelector();
2405
2464
  this.editor.setText("");
@@ -2768,6 +2827,9 @@ export class InteractiveMode {
2768
2827
  // The bash execution callback handles TUI output rendering.
2769
2828
  break;
2770
2829
  case "tool_execution_start": {
2830
+ // Nested calls (from codemode scripts) are shown inside their parent's row.
2831
+ if (event.parentToolCallId)
2832
+ break;
2771
2833
  let component = this.pendingTools.get(event.toolCallId);
2772
2834
  if (!component) {
2773
2835
  component = new ToolExecutionComponent(event.toolName, event.toolCallId, event.args, {
@@ -2869,7 +2931,8 @@ export class InteractiveMode {
2869
2931
  }
2870
2932
  else {
2871
2933
  this.chatContainer.addChild(new Spacer(1));
2872
- this.chatContainer.addChild(new Text(theme.fg("error", event.errorMessage), 1, 0));
2934
+ const errorMessage = event.errorMessage;
2935
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("error", errorMessage), 1, 0));
2873
2936
  }
2874
2937
  }
2875
2938
  void this.flushCompactionQueue({ willRetry: event.willRetry });
@@ -2941,7 +3004,7 @@ export class InteractiveMode {
2941
3004
  }
2942
3005
  const message = status.type === "warning" ? `Warning: ${status.message}` : status.message;
2943
3006
  const color = status.type === "warning" ? "warning" : "dim";
2944
- this.chatContainer.addChild(new Text(theme.fg(color, message), 1, 0));
3007
+ this.chatContainer.addChild(new ThemedText(() => theme.fg(color, message), 1, 0));
2945
3008
  this.lastStatusSpacer = undefined;
2946
3009
  this.lastStatusText = undefined;
2947
3010
  this.ui.requestRender();
@@ -2957,12 +3020,14 @@ export class InteractiveMode {
2957
3020
  const last = children.length > 0 ? children[children.length - 1] : undefined;
2958
3021
  const secondLast = children.length > 1 ? children[children.length - 2] : undefined;
2959
3022
  if (last && secondLast && last === this.lastStatusText && secondLast === this.lastStatusSpacer) {
2960
- this.lastStatusText.setText(theme.fg("dim", message));
3023
+ this.lastStatusMessage = message;
3024
+ this.lastStatusText.invalidate();
2961
3025
  this.ui.requestRender();
2962
3026
  return;
2963
3027
  }
2964
3028
  const spacer = new Spacer(1);
2965
- const text = new Text(theme.fg("dim", message), 1, 0);
3029
+ this.lastStatusMessage = message;
3030
+ const text = new ThemedText(() => theme.fg("dim", this.lastStatusMessage), 1, 0);
2966
3031
  this.chatContainer.addChild(spacer);
2967
3032
  this.chatContainer.addChild(text);
2968
3033
  this.lastStatusSpacer = spacer;
@@ -3171,7 +3236,8 @@ export class InteractiveMode {
3171
3236
  if (!this.settingsManager.getShowCacheMissNotices())
3172
3237
  return;
3173
3238
  this.chatContainer.addChild(new Spacer(1));
3174
- this.chatContainer.addChild(new Text(theme.fg("dim", formatCacheWarmingUsage(entry)), 1, 0));
3239
+ const usage = formatCacheWarmingUsage(entry);
3240
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("dim", usage), 1, 0));
3175
3241
  }
3176
3242
  /**
3177
3243
  * Render billing usage for a compaction or branch summary. The notice is derived
@@ -3185,7 +3251,7 @@ export class InteractiveMode {
3185
3251
  const cost = usage.cost.total >= 0.01 ? ` (~$${usage.cost.total.toFixed(2)})` : "";
3186
3252
  const label = notice.kind === "compaction" ? "Compaction" : "Branch summary";
3187
3253
  this.chatContainer.addChild(new Spacer(1));
3188
- this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
3254
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
3189
3255
  }
3190
3256
  static countDroppedThinkingBlocks(message) {
3191
3257
  let count = 0;
@@ -3222,7 +3288,7 @@ export class InteractiveMode {
3222
3288
  return;
3223
3289
  const noun = droppedCount === 1 ? "thinking block" : "thinking blocks";
3224
3290
  this.chatContainer.addChild(new Spacer(1));
3225
- this.chatContainer.addChild(new Text(theme.fg("warning", `Anthropic dropped ${droppedCount} ${noun} (details in session)`), 1, 0));
3291
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `Anthropic dropped ${droppedCount} ${noun} (details in session)`), 1, 0));
3226
3292
  }
3227
3293
  /**
3228
3294
  * Show a transcript notice when a completed assistant message paid for a
@@ -3249,9 +3315,8 @@ export class InteractiveMode {
3249
3315
  else if (miss.idleMs >= CACHE_TTL_MS) {
3250
3316
  label = `Cache miss after ${Math.round(miss.idleMs / 60_000)}m idle`;
3251
3317
  }
3252
- const text = theme.fg("warning", `${label}: ${reBilled}`);
3253
3318
  this.chatContainer.addChild(new Spacer(1));
3254
- this.chatContainer.addChild(new Text(text, 1, 0));
3319
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `${label}: ${reBilled}`), 1, 0));
3255
3320
  }
3256
3321
  renderInitialMessages() {
3257
3322
  const entries = this.sessionManager.buildContextEntries();
@@ -3275,7 +3340,7 @@ export class InteractiveMode {
3275
3340
  if (this.chatContainer.children.length > 0) {
3276
3341
  this.chatContainer.addChild(new Spacer(1));
3277
3342
  }
3278
- 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));
3343
+ 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));
3279
3344
  }
3280
3345
  async getUserInput() {
3281
3346
  const queuedInput = this.pendingUserInputs.shift();
@@ -3314,7 +3379,8 @@ export class InteractiveMode {
3314
3379
  if (this.isShuttingDown)
3315
3380
  return;
3316
3381
  this.isShuttingDown = true;
3317
- this.session.background.close();
3382
+ this.tasksUI?.dispose();
3383
+ this.session.tasks.close();
3318
3384
  // Keep signal handlers registered until terminal cleanup has completed.
3319
3385
  // `signal-exit` checks the listener list during the same SIGTERM/SIGHUP
3320
3386
  // dispatch and re-sends the signal if only its own listeners remain.
@@ -3619,28 +3685,30 @@ export class InteractiveMode {
3619
3685
  }
3620
3686
  showError(errorMessage) {
3621
3687
  this.chatContainer.addChild(new Spacer(1));
3622
- this.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage}`), this.outputPad, 0));
3688
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("error", `Error: ${errorMessage}`), this.outputPad, 0));
3623
3689
  this.ui.requestRender();
3624
3690
  }
3625
3691
  showWarning(warningMessage) {
3626
3692
  this.chatContainer.addChild(new Spacer(1));
3627
- this.chatContainer.addChild(new Text(theme.fg("warning", `Warning: ${warningMessage}`), 1, 0));
3693
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `Warning: ${warningMessage}`), 1, 0));
3628
3694
  this.ui.requestRender();
3629
3695
  }
3630
3696
  showNewVersionNotification(release) {
3631
- const action = theme.fg("accent", `${APP_NAME} update`);
3632
- const updateInstruction = theme.fg("muted", `New version ${release.version} is available. Run `) + action;
3697
+ const updateInstruction = () => theme.fg("muted", `New version ${release.version} is available. Run `) +
3698
+ theme.fg("accent", `${APP_NAME} update`);
3633
3699
  const changelogUrl = "https://pi.dev/changelog";
3634
- const changelogLink = getCapabilities().hyperlinks
3635
- ? hyperlink(theme.fg("accent", changelogUrl), changelogUrl)
3636
- : theme.fg("accent", changelogUrl);
3637
- const changelogLine = UPDATE_CHANGELOG_HINT
3638
- ? theme.fg("muted", UPDATE_CHANGELOG_HINT)
3639
- : theme.fg("muted", "Changelog: ") + changelogLink;
3700
+ const changelogLine = () => {
3701
+ const changelogLink = getCapabilities().hyperlinks
3702
+ ? hyperlink(theme.fg("accent", changelogUrl), changelogUrl)
3703
+ : theme.fg("accent", changelogUrl);
3704
+ return UPDATE_CHANGELOG_HINT
3705
+ ? theme.fg("muted", UPDATE_CHANGELOG_HINT)
3706
+ : theme.fg("muted", "Changelog: ") + changelogLink;
3707
+ };
3640
3708
  const note = release.note?.trim();
3641
3709
  this.chatContainer.addChild(new Spacer(1));
3642
3710
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
3643
- this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Update Available"))}\n${updateInstruction}`, 1, 0));
3711
+ this.chatContainer.addChild(new ThemedText(() => `${theme.bold(theme.fg("warning", "Update Available"))}\n${updateInstruction()}`, 1, 0));
3644
3712
  if (note) {
3645
3713
  this.chatContainer.addChild(new Spacer(1));
3646
3714
  this.chatContainer.addChild(new Markdown(note, 1, 0, this.getMarkdownThemeWithSettings(), {
@@ -3648,17 +3716,17 @@ export class InteractiveMode {
3648
3716
  }));
3649
3717
  this.chatContainer.addChild(new Spacer(1));
3650
3718
  }
3651
- this.chatContainer.addChild(new Text(changelogLine, 1, 0));
3719
+ this.chatContainer.addChild(new ThemedText(changelogLine, 1, 0));
3652
3720
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
3653
3721
  this.ui.requestRender();
3654
3722
  }
3655
3723
  showPackageUpdateNotification(packages) {
3656
- const action = theme.fg("accent", `${APP_NAME} update --extensions`);
3657
- const updateInstruction = theme.fg("muted", "Package updates are available. Run ") + action;
3724
+ const updateInstruction = () => theme.fg("muted", "Package updates are available. Run ") +
3725
+ theme.fg("accent", `${APP_NAME} update --extensions`);
3658
3726
  const packageLines = packages.map((pkg) => `- ${pkg}`).join("\n");
3659
3727
  this.chatContainer.addChild(new Spacer(1));
3660
3728
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
3661
- this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Package Updates Available"))}\n${updateInstruction}\n${theme.fg("muted", "Packages:")}\n${packageLines}`, 1, 0));
3729
+ this.chatContainer.addChild(new ThemedText(() => `${theme.bold(theme.fg("warning", "Package Updates Available"))}\n${updateInstruction()}\n${theme.fg("muted", "Packages:")}\n${packageLines}`, 1, 0));
3662
3730
  this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
3663
3731
  this.ui.requestRender();
3664
3732
  }
@@ -3895,7 +3963,7 @@ export class InteractiveMode {
3895
3963
  thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
3896
3964
  availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
3897
3965
  modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
3898
- currentTheme: this.themeController.getThemeSelection() || "dark",
3966
+ currentTheme: this.themeController.getThemeSelection() || SYSTEM_THEME_NAME,
3899
3967
  terminalTheme: this.themeController.getTerminalTheme(),
3900
3968
  availableThemes: getAvailableThemes(),
3901
3969
  hideThinkingBlock: this.hideThinkingBlock,
@@ -3917,6 +3985,7 @@ export class InteractiveMode {
3917
3985
  fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
3918
3986
  fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
3919
3987
  fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
3988
+ fullscreenWheelScrollLines: this.settingsManager.getFullscreenWheelScrollLines(),
3920
3989
  warnings: this.settingsManager.getWarnings(),
3921
3990
  }, {
3922
3991
  onAutoCompactChange: (enabled) => {
@@ -3991,7 +4060,7 @@ export class InteractiveMode {
3991
4060
  },
3992
4061
  onThemeChange: (themeSetting) => {
3993
4062
  this.settingsManager.setTheme(themeSetting);
3994
- void this.themeController.setThemeSetting(themeSetting);
4063
+ this.themeController.setThemeSetting(themeSetting);
3995
4064
  },
3996
4065
  onThemePreview: (themeName) => this.themeController.preview(themeName),
3997
4066
  onHideThinkingBlockChange: (hidden) => {
@@ -4014,8 +4083,8 @@ export class InteractiveMode {
4014
4083
  onEnableInstallTelemetryChange: (enabled) => {
4015
4084
  this.settingsManager.setEnableInstallTelemetry(enabled);
4016
4085
  },
4017
- onQuietStartupChange: (enabled) => {
4018
- this.settingsManager.setQuietStartup(enabled);
4086
+ onQuietStartupChange: (quiet) => {
4087
+ this.settingsManager.setQuietStartup(quiet);
4019
4088
  },
4020
4089
  onDefaultProjectTrustChange: (defaultProjectTrust) => {
4021
4090
  this.settingsManager.setDefaultProjectTrust(defaultProjectTrust);
@@ -4096,6 +4165,11 @@ export class InteractiveMode {
4096
4165
  if (this.renderer instanceof TuiAltScreen)
4097
4166
  this.renderer.setCopyOnSelect(enabled);
4098
4167
  },
4168
+ onFullscreenWheelScrollLinesChange: (lines) => {
4169
+ this.settingsManager.setFullscreenWheelScrollLines(lines);
4170
+ if (this.renderer instanceof TuiAltScreen)
4171
+ this.renderer.setWheelScrollLines(lines);
4172
+ },
4099
4173
  onWarningsChange: (warnings) => {
4100
4174
  this.settingsManager.setWarnings(warnings);
4101
4175
  },
@@ -4486,6 +4560,20 @@ export class InteractiveMode {
4486
4560
  }
4487
4561
  // Ask about summarization
4488
4562
  done(); // Close selector first
4563
+ // Results are saved on their launch branch, so leaving it stops its running tasks.
4564
+ const stopped = this.session.tasksStoppedByTreeNavigation(entryId);
4565
+ if (stopped.length > 0) {
4566
+ const shown = stopped
4567
+ .slice(0, 5)
4568
+ .map((task) => ` ${cleanTaskText(firstCommandLine(task.command ?? task.title))}`);
4569
+ if (stopped.length > shown.length)
4570
+ shown.push(` …and ${stopped.length - shown.length} more`);
4571
+ const confirmed = await this.showExtensionConfirm(`Stop ${stopped.length} running task${stopped.length === 1 ? "" : "s"}?`, `They were started on the branch you are leaving and will be cancelled:\n${shown.join("\n")}`);
4572
+ if (!confirmed) {
4573
+ this.showTreeSelector(entryId);
4574
+ return;
4575
+ }
4576
+ }
4489
4577
  // Loop until user makes a complete choice or cancels to tree
4490
4578
  let wantsSummary = false;
4491
4579
  let customInstructions;
@@ -4662,6 +4750,7 @@ export class InteractiveMode {
4662
4750
  source: authStatus.label ?? authStatus.source,
4663
4751
  }
4664
4752
  : undefined;
4753
+ const subscription = provider.auth.oauth?.isSubscription === true;
4665
4754
  if ((!authType || authType === "oauth") && provider.auth.oauth) {
4666
4755
  options.push({
4667
4756
  id: provider.id,
@@ -4669,6 +4758,7 @@ export class InteractiveMode {
4669
4758
  authType: "oauth",
4670
4759
  method: provider.auth.oauth,
4671
4760
  status,
4761
+ subscription,
4672
4762
  });
4673
4763
  }
4674
4764
  if ((!authType || authType === "api_key") && provider.auth.apiKey) {
@@ -4678,6 +4768,7 @@ export class InteractiveMode {
4678
4768
  authType: "api_key",
4679
4769
  method: provider.auth.apiKey,
4680
4770
  status,
4771
+ subscription,
4681
4772
  });
4682
4773
  }
4683
4774
  }
@@ -4685,12 +4776,16 @@ export class InteractiveMode {
4685
4776
  }
4686
4777
  async getLogoutProviderOptions() {
4687
4778
  return (await this.session.modelRuntime.listCredentials({ signal: AbortSignal.timeout(15_000) }))
4688
- .map(({ providerId, type }) => ({
4689
- id: providerId,
4690
- name: this.session.modelRuntime.getProvider(providerId)?.name ?? providerId,
4691
- authType: type,
4692
- status: { type, source: "stored credential" },
4693
- }))
4779
+ .map(({ providerId, type }) => {
4780
+ const provider = this.session.modelRuntime.getProvider(providerId);
4781
+ return {
4782
+ id: providerId,
4783
+ name: provider?.name ?? providerId,
4784
+ authType: type,
4785
+ status: { type, source: "stored credential" },
4786
+ subscription: provider?.auth.oauth?.isSubscription === true,
4787
+ };
4788
+ })
4694
4789
  .sort((a, b) => a.name.localeCompare(b.name));
4695
4790
  }
4696
4791
  findLoginProviderOptions(providerRef) {
@@ -4720,18 +4815,25 @@ export class InteractiveMode {
4720
4815
  }
4721
4816
  this.showLoginProviderSelector(undefined, providerRef);
4722
4817
  }
4723
- async startProviderLogin(providerOption) {
4818
+ /** `onBack` reopens the selector the login was started from when the user cancels it. */
4819
+ async startProviderLogin(providerOption, onBack) {
4724
4820
  if (providerOption.authType === "oauth") {
4725
- await this.showLoginDialog(providerOption.id, providerOption.name);
4821
+ await this.showLoginDialog(providerOption.id, providerOption.name, onBack);
4726
4822
  }
4727
4823
  else if (providerOption.method?.login) {
4728
- await this.showApiKeyLoginDialog(providerOption.id, providerOption.name);
4824
+ await this.showApiKeyLoginDialog(providerOption.id, providerOption.name, onBack);
4729
4825
  }
4730
4826
  else {
4731
- this.showAmbientAuthDialog(providerOption);
4827
+ this.showAmbientAuthDialog(providerOption, onBack);
4732
4828
  }
4733
4829
  }
4734
4830
  showLoginAuthTypeSelector(providerOptions) {
4831
+ // The top-level selector offers Radius directly, as its last option.
4832
+ const radiusOption = providerOptions
4833
+ ? undefined
4834
+ : this.getLoginProviderOptions("oauth").find((provider) => provider.id === RADIUS_PROVIDER_ID);
4835
+ const radiusText = radiusOption ? `Sign in with ${radiusOption.name}` : undefined;
4836
+ const radiusLabel = radiusOption ? `${radiusText}${formatAuthSelectorProviderStatus(radiusOption)}` : undefined;
4735
4837
  const oauthProvider = providerOptions?.find((provider) => provider.authType === "oauth");
4736
4838
  const oauthLoginLabel = oauthProvider?.method && "loginLabel" in oauthProvider.method ? oauthProvider.method.loginLabel : undefined;
4737
4839
  const subscriptionLabel = oauthLoginLabel ?? "Sign in with an account";
@@ -4746,6 +4848,8 @@ export class InteractiveMode {
4746
4848
  if (availableAuthTypes.has("api_key")) {
4747
4849
  options.push(apiKeyLabel);
4748
4850
  }
4851
+ if (radiusLabel)
4852
+ options.push(radiusLabel);
4749
4853
  if (options.length === 0) {
4750
4854
  this.showStatus("No login methods available.");
4751
4855
  return;
@@ -4761,29 +4865,37 @@ export class InteractiveMode {
4761
4865
  ? `Select authentication method for ${providerOptions[0].name}:`
4762
4866
  : "Select authentication method:";
4763
4867
  this.showSelector((done) => {
4764
- const selector = new ExtensionSelectorComponent(title, options, (option) => {
4868
+ const onSelect = (option) => {
4765
4869
  done();
4870
+ if (radiusOption && option === radiusLabel) {
4871
+ void this.startProviderLogin(radiusOption, () => this.showLoginAuthTypeSelector());
4872
+ return;
4873
+ }
4766
4874
  const authType = option === subscriptionLabel ? "oauth" : "api_key";
4767
4875
  if (providerOptions) {
4768
4876
  const providerOption = providerOptions.find((provider) => provider.authType === authType);
4769
4877
  if (providerOption) {
4770
- void this.startProviderLogin(providerOption);
4878
+ void this.startProviderLogin(providerOption, () => this.showLoginAuthTypeSelector(providerOptions));
4771
4879
  }
4772
4880
  return;
4773
4881
  }
4774
4882
  this.showLoginProviderSelector(authType);
4775
- }, () => {
4883
+ };
4884
+ const onCancel = () => {
4776
4885
  done();
4777
4886
  this.ui.requestRender();
4778
- });
4779
- return { component: selector, focus: selector };
4887
+ };
4888
+ const selector = radiusLabel && radiusText
4889
+ ? createLoginMenuSelector(this.ui, title, options, { label: radiusLabel, text: radiusText }, onSelect, onCancel)
4890
+ : new ExtensionSelectorComponent(title, options, onSelect, onCancel);
4891
+ return { component: selector, focus: selector, dispose: () => selector.dispose() };
4780
4892
  });
4781
4893
  }
4782
4894
  showLoginProviderSelector(authType, initialSearchInput) {
4783
4895
  const providerOptions = this.getLoginProviderOptions(authType);
4784
4896
  if (providerOptions.length === 0) {
4785
4897
  const message = authType === "oauth"
4786
- ? "No subscription providers available."
4898
+ ? "No account providers available."
4787
4899
  : authType === "api_key"
4788
4900
  ? "No API key providers available."
4789
4901
  : "No login providers available.";
@@ -4797,7 +4909,7 @@ export class InteractiveMode {
4797
4909
  if (!providerOption) {
4798
4910
  return;
4799
4911
  }
4800
- await this.startProviderLogin(providerOption);
4912
+ await this.startProviderLogin(providerOption, () => this.showLoginProviderSelector(authType, initialSearchInput));
4801
4913
  }, () => {
4802
4914
  done();
4803
4915
  if (authType) {
@@ -4951,21 +5063,24 @@ export class InteractiveMode {
4951
5063
  })
4952
5064
  .finally(() => clearTimeout(timeout));
4953
5065
  }
4954
- showAmbientAuthDialog(providerOption) {
5066
+ showAmbientAuthDialog(providerOption, onBack) {
4955
5067
  const restoreEditor = () => {
4956
5068
  this.editorContainer.clear();
4957
5069
  this.editorContainer.addChild(this.editor);
4958
5070
  this.ui.setFocus(this.editor);
4959
5071
  this.ui.requestRender();
4960
5072
  };
4961
- const dialog = new LoginDialogComponent(this.ui, providerOption.id, () => restoreEditor(), providerOption.name, `${providerOption.name} setup`);
5073
+ const dialog = new LoginDialogComponent(this.ui, providerOption.id, () => {
5074
+ restoreEditor();
5075
+ onBack?.();
5076
+ }, providerOption.name, `${providerOption.name} setup`);
4962
5077
  dialog.showInfo(`${providerOption.method?.name ?? "Authentication"} is configured outside ${APP_NAME}.`, [], true);
4963
5078
  this.editorContainer.clear();
4964
5079
  this.editorContainer.addChild(dialog);
4965
5080
  this.ui.setFocus(dialog);
4966
5081
  this.ui.requestRender();
4967
5082
  }
4968
- async showApiKeyLoginDialog(providerId, providerName) {
5083
+ async showApiKeyLoginDialog(providerId, providerName, onBack) {
4969
5084
  const previousModel = this.session.model;
4970
5085
  const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => {
4971
5086
  // Completion handled below
@@ -4998,12 +5113,15 @@ export class InteractiveMode {
4998
5113
  if (error instanceof CredentialSynchronizationError) {
4999
5114
  this.showError(`Saved API key for ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
5000
5115
  }
5001
- else if (errorMsg !== "Login cancelled") {
5116
+ else if (errorMsg === "Login cancelled") {
5117
+ onBack?.();
5118
+ }
5119
+ else {
5002
5120
  this.showError(`Failed to save API key for ${providerName}: ${errorMsg}`);
5003
5121
  }
5004
5122
  }
5005
5123
  }
5006
- showAuthSelect(dialog, prompt) {
5124
+ showAuthSelect(dialog, prompt, providerId) {
5007
5125
  return new Promise((resolve, reject) => {
5008
5126
  const restoreDialog = () => {
5009
5127
  this.editorContainer.clear();
@@ -5022,17 +5140,17 @@ export class InteractiveMode {
5022
5140
  }, () => {
5023
5141
  restoreDialog();
5024
5142
  reject(new Error("Login cancelled"));
5025
- });
5143
+ }, { description: providerId === RADIUS_PROVIDER_ID ? RADIUS_LOGIN_INTRO : undefined });
5026
5144
  this.editorContainer.clear();
5027
5145
  this.editorContainer.addChild(selector);
5028
5146
  this.ui.setFocus(selector);
5029
5147
  this.ui.requestRender();
5030
5148
  });
5031
5149
  }
5032
- async showAuthPrompt(dialog, prompt) {
5150
+ async showAuthPrompt(dialog, prompt, providerId) {
5033
5151
  let response;
5034
5152
  if (prompt.type === "select") {
5035
- response = this.showAuthSelect(dialog, prompt);
5153
+ response = this.showAuthSelect(dialog, prompt, providerId);
5036
5154
  }
5037
5155
  else if (prompt.type === "manual_code") {
5038
5156
  response = dialog.showManualInput(prompt.message);
@@ -5076,11 +5194,11 @@ export class InteractiveMode {
5076
5194
  async loginProvider(dialog, providerId, method) {
5077
5195
  await this.session.modelRuntime.login(providerId, method, {
5078
5196
  signal: dialog.signal,
5079
- prompt: (prompt) => this.showAuthPrompt(dialog, prompt),
5197
+ prompt: (prompt) => this.showAuthPrompt(dialog, prompt, providerId),
5080
5198
  notify: (event) => this.notifyAuthDialog(dialog, event),
5081
- });
5199
+ }, { getDeviceId: () => this.settingsManager.getOrCreateDeviceId() });
5082
5200
  }
5083
- async showLoginDialog(providerId, providerName) {
5201
+ async showLoginDialog(providerId, providerName, onBack) {
5084
5202
  const previousModel = this.session.model;
5085
5203
  const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => { }, providerName);
5086
5204
  this.editorContainer.clear();
@@ -5097,6 +5215,8 @@ export class InteractiveMode {
5097
5215
  await this.loginProvider(dialog, providerId, "oauth");
5098
5216
  restoreEditor();
5099
5217
  await this.completeProviderAuthentication(providerId, providerName, "oauth", previousModel);
5218
+ if (providerId === RADIUS_PROVIDER_ID)
5219
+ this.offerRadiusMcpServer(providerId, providerName);
5100
5220
  }
5101
5221
  catch (error) {
5102
5222
  restoreEditor();
@@ -5104,11 +5224,58 @@ export class InteractiveMode {
5104
5224
  if (error instanceof CredentialSynchronizationError) {
5105
5225
  this.showError(`Logged in to ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
5106
5226
  }
5107
- else if (errorMsg !== "Login cancelled") {
5227
+ else if (errorMsg === "Login cancelled") {
5228
+ onBack?.();
5229
+ }
5230
+ else {
5108
5231
  this.showError(`Failed to login to ${providerName}: ${errorMsg}`);
5109
5232
  }
5110
5233
  }
5111
5234
  }
5235
+ /**
5236
+ * Offer to point the Radius MCP server in the global mcp.json at the Radius login, adding the server
5237
+ * when missing. Nothing is asked when a global server already uses this login.
5238
+ */
5239
+ offerRadiusMcpServer(providerId, providerName) {
5240
+ const mcpPath = path.join(getAgentDir(), "mcp.json");
5241
+ const normalizeUrl = (url) => url.replace(/\/+$/u, "");
5242
+ const { servers } = loadMcpConfig({
5243
+ agentDir: getAgentDir(),
5244
+ cwd: this.sessionManager.getCwd(),
5245
+ projectTrusted: false,
5246
+ });
5247
+ const existing = servers.find((server) => "url" in server.config && normalizeUrl(server.config.url) === normalizeUrl(RADIUS_MCP_URL));
5248
+ if (existing && "url" in existing.config && existing.config.auth?.provider === providerId)
5249
+ return;
5250
+ let name = existing?.name ?? "radius";
5251
+ if (!existing && servers.some((server) => server.name === name))
5252
+ name = "radius-mcp";
5253
+ const config = existing && "url" in existing.config
5254
+ ? { ...existing.config, auth: { provider: providerId } }
5255
+ : { url: RADIUS_MCP_URL, auth: { provider: providerId } };
5256
+ // `auth` replaces the MCP OAuth sign-in.
5257
+ delete config.oauth;
5258
+ this.showSelector((done) => {
5259
+ const selector = new ExtensionSelectorComponent(`Configure ${providerName} MCP in ${mcpPath}?`, ["Yes", "No"], (option) => {
5260
+ done();
5261
+ if (option !== "Yes")
5262
+ return;
5263
+ try {
5264
+ addMcpServerConfig(mcpPath, name, config);
5265
+ }
5266
+ catch (error) {
5267
+ this.showError(`Could not update ${mcpPath}: ${error instanceof Error ? error.message : String(error)}`);
5268
+ return;
5269
+ }
5270
+ // The MCP extension reads mcp.json when the session starts.
5271
+ void this.handleReloadCommand();
5272
+ }, () => {
5273
+ done();
5274
+ this.ui.requestRender();
5275
+ });
5276
+ return { component: selector, focus: selector };
5277
+ });
5278
+ }
5112
5279
  // =========================================================================
5113
5280
  // Command handlers
5114
5281
  // =========================================================================
@@ -5126,7 +5293,7 @@ export class InteractiveMode {
5126
5293
  const borderColor = (s) => theme.fg("border", s);
5127
5294
  reloadBox.addChild(new DynamicBorder(borderColor));
5128
5295
  reloadBox.addChild(new Spacer(1));
5129
- reloadBox.addChild(new Text(theme.fg("muted", "Reloading keybindings, extensions, skills, prompts, themes, and context files..."), 1, 0));
5296
+ reloadBox.addChild(new ThemedText(() => theme.fg("muted", "Reloading keybindings, extensions, skills, prompts, themes, and context files..."), 1, 0));
5130
5297
  reloadBox.addChild(new Spacer(1));
5131
5298
  reloadBox.addChild(new DynamicBorder(borderColor));
5132
5299
  const previousEditor = this.editor;
@@ -5153,7 +5320,9 @@ export class InteractiveMode {
5153
5320
  chatRestoredBeforeSessionStart = true;
5154
5321
  };
5155
5322
  try {
5323
+ this.tasksUI?.dispose();
5156
5324
  await this.session.reload({ beforeSessionStart: restoreChatBeforeSessionStart });
5325
+ this.tasksUI = bindTasksUI({ tasks: this.session.tasks, ui: this.createExtensionUIContext() });
5157
5326
  restoreChatBeforeSessionStart();
5158
5327
  this.keybindings.reload();
5159
5328
  const activeHeader = this.customHeader ?? this.builtInHeader;
@@ -5162,7 +5331,7 @@ export class InteractiveMode {
5162
5331
  }
5163
5332
  setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
5164
5333
  this.applyRuntimeSettings();
5165
- await this.themeController.applyFromSettings();
5334
+ this.themeController.applyFromSettings();
5166
5335
  this.setupAutocompleteProvider();
5167
5336
  const runner = this.session.extensionRunner;
5168
5337
  this.setupExtensionShortcuts(runner);
@@ -5326,7 +5495,7 @@ export class InteractiveMode {
5326
5495
  const currentName = this.sessionManager.getSessionName();
5327
5496
  if (currentName) {
5328
5497
  this.chatContainer.addChild(new Spacer(1));
5329
- this.chatContainer.addChild(new Text(theme.fg("dim", `Session name: ${currentName}`), 1, 0));
5498
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("dim", `Session name: ${currentName}`), 1, 0));
5330
5499
  }
5331
5500
  else {
5332
5501
  this.showWarning("Usage: /name <name>");
@@ -5340,7 +5509,8 @@ export class InteractiveMode {
5340
5509
  this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName)}`);
5341
5510
  }
5342
5511
  this.chatContainer.addChild(new Spacer(1));
5343
- this.chatContainer.addChild(new Text(theme.fg("dim", `Session name set: ${sessionName ?? name}`), 1, 0));
5512
+ const displayName = sessionName ?? name;
5513
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("dim", `Session name set: ${displayName}`), 1, 0));
5344
5514
  this.ui.requestRender();
5345
5515
  }
5346
5516
  handleSessionCommand() {
@@ -5352,61 +5522,69 @@ export class InteractiveMode {
5352
5522
  // resolves to a concrete responseModel). Usage without model attribution is
5353
5523
  // grouped separately so the breakdown reconciles with the session total.
5354
5524
  const usageBreakdown = getUsageCostBreakdown(entries);
5355
- let info = `${theme.bold("Session Info")}\n\n`;
5356
- if (sessionName) {
5357
- info += `${theme.fg("dim", "Name:")} ${sessionName}\n`;
5358
- }
5359
- info += `${theme.fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
5360
- info += `${theme.fg("dim", "ID:")} ${stats.sessionId}\n\n`;
5361
- info += `${theme.bold("Messages")}\n`;
5362
- info += `${theme.fg("dim", "Total:")} ${stats.totalMessages}\n`;
5363
- info += `${theme.fg("dim", "User:")} ${stats.userMessages}\n`;
5364
- info += `${theme.fg("dim", "Assistant:")} ${stats.assistantMessages}\n`;
5365
- info += `${theme.fg("dim", "Tools:")} ${stats.toolCalls} calls, ${stats.toolResults} results\n\n`;
5366
- info += `${theme.bold("Tokens")}\n`;
5367
- // "Input" is the full prompt volume. With cache activity, split it into
5368
- // cached (served from cache) vs uncached (everything else) - the only
5369
- // provider-independent split. Cache writes, where reported, are a detail
5370
- // of the uncached portion.
5371
- const { input, cacheRead, cacheWrite } = stats.tokens;
5372
- const promptTokens = input + cacheRead + cacheWrite;
5373
- info += `${theme.fg("dim", "Input:")} ${promptTokens.toLocaleString()}\n`;
5374
- if (promptTokens > 0 && (cacheRead > 0 || cacheWrite > 0)) {
5375
- const hitRate = theme.fg("dim", `(${((cacheRead / promptTokens) * 100).toFixed(1)}%)`);
5376
- info += ` ${theme.fg("dim", "Cached:")} ${cacheRead.toLocaleString()} ${hitRate}\n`;
5377
- const written = cacheWrite > 0 ? ` ${theme.fg("dim", `(${cacheWrite.toLocaleString()} written to cache)`)}` : "";
5378
- info += ` ${theme.fg("dim", "Uncached:")} ${(input + cacheWrite).toLocaleString()}${written}\n`;
5379
- }
5380
- info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
5381
- info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
5525
+ // Snapshot the stats; the text is built on demand so it follows theme changes.
5382
5526
  const cacheWarmingStatus = this.session.cacheWarmingStatus;
5383
- info += `\n${theme.bold("Cache Warming")}\n`;
5384
- info += `${theme.fg("dim", "Mode:")} ${this.settingsManager.getCacheWarmingMode()}\n`;
5385
- info += `${theme.fg("dim", "Status:")} ${cacheWarmingStatus ? formatCacheWarmingStatus(cacheWarmingStatus) : "Inactive (cache warming unavailable)"}\n`;
5386
- const decision = cacheWarmingStatus?.decision;
5387
- if (decision?.economicsAvailable) {
5388
- info += `${theme.fg("dim", "Cache miss penalty:")} $${decision.missCost.toFixed(3)}\n`;
5389
- info += `${theme.fg("dim", "Refresh cost:")} $${decision.warmCost.toFixed(3)}\n`;
5390
- }
5391
- if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
5392
- info += `\n${theme.bold("Cost")}\n`;
5393
- info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
5394
- if (usageBreakdown.length > 1) {
5395
- for (const entry of usageBreakdown) {
5396
- info += `\n ${theme.fg("dim", `${entry.key}:`)} $${entry.cost.toFixed(3)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
5527
+ const cacheWarmingMode = this.settingsManager.getCacheWarmingMode();
5528
+ const model = this.session.model;
5529
+ const selectedModelKey = `${model?.provider}/${model?.id}`;
5530
+ const renderInfo = () => {
5531
+ let info = `${theme.bold("Session Info")}\n\n`;
5532
+ if (sessionName) {
5533
+ info += `${theme.fg("dim", "Name:")} ${sessionName}\n`;
5534
+ }
5535
+ info += `${theme.fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
5536
+ info += `${theme.fg("dim", "ID:")} ${stats.sessionId}\n\n`;
5537
+ info += `${theme.bold("Messages")}\n`;
5538
+ info += `${theme.fg("dim", "Total:")} ${stats.totalMessages}\n`;
5539
+ info += `${theme.fg("dim", "User:")} ${stats.userMessages}\n`;
5540
+ info += `${theme.fg("dim", "Assistant:")} ${stats.assistantMessages}\n`;
5541
+ info += `${theme.fg("dim", "Tools:")} ${stats.toolCalls} calls, ${stats.toolResults} results\n\n`;
5542
+ info += `${theme.bold("Tokens")}\n`;
5543
+ // "Input" is the full prompt volume. With cache activity, split it into
5544
+ // cached (served from cache) vs uncached (everything else) - the only
5545
+ // provider-independent split. Cache writes, where reported, are a detail
5546
+ // of the uncached portion.
5547
+ const { input, cacheRead, cacheWrite } = stats.tokens;
5548
+ const promptTokens = input + cacheRead + cacheWrite;
5549
+ info += `${theme.fg("dim", "Input:")} ${promptTokens.toLocaleString()}\n`;
5550
+ if (promptTokens > 0 && (cacheRead > 0 || cacheWrite > 0)) {
5551
+ const hitRate = theme.fg("dim", `(${((cacheRead / promptTokens) * 100).toFixed(1)}%)`);
5552
+ info += ` ${theme.fg("dim", "Cached:")} ${cacheRead.toLocaleString()} ${hitRate}\n`;
5553
+ const written = cacheWrite > 0 ? ` ${theme.fg("dim", `(${cacheWrite.toLocaleString()} written to cache)`)}` : "";
5554
+ info += ` ${theme.fg("dim", "Uncached:")} ${(input + cacheWrite).toLocaleString()}${written}\n`;
5555
+ }
5556
+ info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
5557
+ info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
5558
+ info += `\n${theme.bold("Cache Warming")}\n`;
5559
+ info += `${theme.fg("dim", "Mode:")} ${cacheWarmingMode}\n`;
5560
+ info += `${theme.fg("dim", "Status:")} ${cacheWarmingStatus ? formatCacheWarmingStatus(cacheWarmingStatus) : "Inactive (cache warming unavailable)"}\n`;
5561
+ const decision = cacheWarmingStatus?.decision;
5562
+ if (decision?.economicsAvailable) {
5563
+ info += `${theme.fg("dim", "Cache miss penalty:")} $${decision.missCost.toFixed(3)}\n`;
5564
+ info += `${theme.fg("dim", "Refresh cost:")} $${decision.warmCost.toFixed(3)}\n`;
5565
+ }
5566
+ if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
5567
+ info += `\n${theme.bold("Cost")}\n`;
5568
+ info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
5569
+ // A single entry repeats the total, unless it names a model other than the selected one.
5570
+ if (usageBreakdown.length > 1 || usageBreakdown[0]?.key !== selectedModelKey) {
5571
+ for (const entry of usageBreakdown) {
5572
+ info += `\n ${theme.fg("dim", `${entry.key}:`)} $${entry.cost.toFixed(3)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
5573
+ }
5574
+ }
5575
+ if (cacheWaste.missedTokens > 0) {
5576
+ const missLabel = cacheWaste.missCount === 1 ? "1 miss" : `${cacheWaste.missCount} misses`;
5577
+ const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
5578
+ info +=
5579
+ cacheWaste.missedCost >= 0.0001
5580
+ ? `\n${theme.fg("dim", "Cache Re-billed:")} $${cacheWaste.missedCost.toFixed(3)} ${theme.fg("dim", `(${detail})`)}`
5581
+ : `\n${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
5397
5582
  }
5398
5583
  }
5399
- if (cacheWaste.missedTokens > 0) {
5400
- const missLabel = cacheWaste.missCount === 1 ? "1 miss" : `${cacheWaste.missCount} misses`;
5401
- const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
5402
- info +=
5403
- cacheWaste.missedCost >= 0.0001
5404
- ? `\n${theme.fg("dim", "Cache Re-billed:")} $${cacheWaste.missedCost.toFixed(3)} ${theme.fg("dim", `(${detail})`)}`
5405
- : `\n${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
5406
- }
5407
- }
5584
+ return info;
5585
+ };
5408
5586
  this.chatContainer.addChild(new Spacer(1));
5409
- this.chatContainer.addChild(new Text(info, 1, 0));
5587
+ this.chatContainer.addChild(new ThemedText(renderInfo, 1, 0));
5410
5588
  this.ui.requestRender();
5411
5589
  }
5412
5590
  handleChangelogCommand() {
@@ -5420,7 +5598,7 @@ export class InteractiveMode {
5420
5598
  : "No changelog entries found.";
5421
5599
  this.chatContainer.addChild(new Spacer(1));
5422
5600
  this.chatContainer.addChild(new DynamicBorder());
5423
- this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
5601
+ this.chatContainer.addChild(new ThemedText(() => theme.bold(theme.fg("accent", "What's New")), 1, 0));
5424
5602
  this.chatContainer.addChild(new Spacer(1));
5425
5603
  this.chatContainer.addChild(new Markdown(changelogMarkdown, 1, 1, this.getMarkdownThemeWithSettings()));
5426
5604
  this.chatContainer.addChild(new DynamicBorder());
@@ -5521,7 +5699,7 @@ export class InteractiveMode {
5521
5699
  | \`${copyMessage}\` | Copy selection or last assistant message |
5522
5700
  | \`${followUp}\` | Queue follow-up message |
5523
5701
  | \`${dequeue}\` | Restore queued messages |
5524
- | \`${pasteImage}\` | Paste image or text from clipboard |
5702
+ | \`${pasteImage}\` | Paste files on macOS, images, or text from clipboard |
5525
5703
  | \`/\` | Slash commands |
5526
5704
  | \`!\` | Run bash command |
5527
5705
  | \`!!\` | Run bash command (excluded from context) |
@@ -5543,7 +5721,7 @@ export class InteractiveMode {
5543
5721
  }
5544
5722
  this.chatContainer.addChild(new Spacer(1));
5545
5723
  this.chatContainer.addChild(new DynamicBorder());
5546
- this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "Keyboard Shortcuts")), 1, 0));
5724
+ this.chatContainer.addChild(new ThemedText(() => theme.bold(theme.fg("accent", "Keyboard Shortcuts")), 1, 0));
5547
5725
  this.chatContainer.addChild(new Spacer(1));
5548
5726
  this.chatContainer.addChild(new Markdown(hotkeys.trim(), 1, 1, this.getMarkdownThemeWithSettings()));
5549
5727
  this.chatContainer.addChild(new DynamicBorder());
@@ -5557,7 +5735,7 @@ export class InteractiveMode {
5557
5735
  return;
5558
5736
  }
5559
5737
  this.chatContainer.addChild(new Spacer(1));
5560
- this.chatContainer.addChild(new Text(`${theme.fg("accent", "✓ New session started")}`, 1, 1));
5738
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("accent", "✓ New session started"), 1, 1));
5561
5739
  this.ui.requestRender();
5562
5740
  }
5563
5741
  catch (error) {
@@ -5588,7 +5766,7 @@ export class InteractiveMode {
5588
5766
  fs.mkdirSync(path.dirname(debugLogPath), { recursive: true });
5589
5767
  fs.writeFileSync(debugLogPath, debugData);
5590
5768
  this.chatContainer.addChild(new Spacer(1));
5591
- this.chatContainer.addChild(new Text(`${theme.fg("accent", "✓ Debug log written")}\n${theme.fg("muted", debugLogPath)}`, 1, 1));
5769
+ this.chatContainer.addChild(new ThemedText(() => `${theme.fg("accent", "✓ Debug log written")}\n${theme.fg("muted", debugLogPath)}`, 1, 1));
5592
5770
  this.ui.requestRender();
5593
5771
  }
5594
5772
  handleArminSaysHi() {