@astralyn/pi 0.99.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (569) hide show
  1. package/CHANGELOG.md +58 -3
  2. package/dist/bundle/chunks/anthropic-messages-YET4T7BO.js +6 -0
  3. package/dist/bundle/chunks/anthropic.js +2 -2
  4. package/dist/bundle/chunks/azure-openai-responses-SBLL5YN3.js +2 -0
  5. package/dist/bundle/chunks/bedrock-converse-stream.js +3 -3
  6. package/dist/bundle/chunks/chunk-4TT2QGFL.js +2 -0
  7. package/dist/bundle/chunks/chunk-GIG5IHES.js +2 -0
  8. package/dist/bundle/chunks/{chunk-VW2P3X6P.js → chunk-H2N2THAO.js} +436 -668
  9. package/dist/bundle/chunks/{chunk-A576H74Y.js → chunk-IZ3S3GDX.js} +1 -1
  10. package/dist/bundle/chunks/{chunk-ABVRAYXT.js → chunk-NY3CWK44.js} +2 -2
  11. package/dist/bundle/chunks/chunk-SVJ7OGEB.js +2 -0
  12. package/dist/bundle/chunks/chunk-TRHTWM3C.js +2 -0
  13. package/dist/bundle/chunks/{chunk-DEWXBB6W.js → chunk-V66VGGOM.js} +1 -1
  14. package/dist/bundle/chunks/chunk-XDYM2567.js +20 -0
  15. package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-ZYSAFXXL.js → cloudflare-workers-ai-system-one-QI46LUZ6.js} +1 -1
  16. package/dist/bundle/chunks/codemode-worker.js +90 -10
  17. package/dist/bundle/chunks/github-copilot.js +1 -1
  18. package/dist/bundle/chunks/{google-generative-ai-SDNQVVXA.js → google-generative-ai-YTZCSHQN.js} +1 -1
  19. package/dist/bundle/chunks/{google-vertex-LZXOLBIO.js → google-vertex-OTFZJJXQ.js} +1 -1
  20. package/dist/bundle/chunks/{llama-cpp-classify-7IYGGPND.js → llama-cpp-classify-R7DQLTQN.js} +1 -1
  21. package/dist/bundle/chunks/{mistral-conversations-VYKPSSAM.js → mistral-conversations-ELH4V4TY.js} +1 -1
  22. package/dist/bundle/chunks/node-USQQ7C6M.js +16 -0
  23. package/dist/bundle/chunks/openai-chatgpt.js +2 -2
  24. package/dist/bundle/chunks/{openai-codex-responses-HZ4VUDXD.js → openai-codex-responses-OLVTU4UA.js} +1 -1
  25. package/dist/bundle/chunks/openai-codex.js +1 -1
  26. package/dist/bundle/chunks/openai-completions-53M2KJ67.js +7 -0
  27. package/dist/bundle/chunks/openai-responses-4ABDEL4Z.js +3 -0
  28. package/dist/bundle/chunks/{openrouter-images-5524IQHX.js → openrouter-images-YP3YVB54.js} +1 -1
  29. package/dist/bundle/chunks/openrouter.js +1 -1
  30. package/dist/bundle/chunks/radius.js +1 -1
  31. package/dist/bundle/chunks/{typesafe-system-one-Z2CDLKEY.js → typesafe-system-one-RREJAKWB.js} +1 -1
  32. package/dist/bundle/chunks/virtual-modules-YFKU7JZF.js +2 -0
  33. package/dist/bundle/cli.js +1 -1
  34. package/dist/bundle/index.js +1 -1
  35. package/dist/bundle/rpc-entry.js +1 -1
  36. package/dist/cli/args.d.ts.map +1 -1
  37. package/dist/cli/args.js +5 -2
  38. package/dist/cli/args.js.map +1 -1
  39. package/dist/config.d.ts +5 -8
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/config.js +19 -13
  42. package/dist/config.js.map +1 -1
  43. package/dist/core/agent-session.d.ts +21 -1
  44. package/dist/core/agent-session.d.ts.map +1 -1
  45. package/dist/core/agent-session.js +65 -12
  46. package/dist/core/agent-session.js.map +1 -1
  47. package/dist/core/export-html/tool-renderer.d.ts +3 -3
  48. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  49. package/dist/core/export-html/tool-renderer.js +3 -3
  50. package/dist/core/export-html/tool-renderer.js.map +1 -1
  51. package/dist/core/extensions/index.d.ts +2 -2
  52. package/dist/core/extensions/index.d.ts.map +1 -1
  53. package/dist/core/extensions/index.js.map +1 -1
  54. package/dist/core/extensions/loader.d.ts.map +1 -1
  55. package/dist/core/extensions/loader.js +18 -1
  56. package/dist/core/extensions/loader.js.map +1 -1
  57. package/dist/core/extensions/runner.d.ts +3 -1
  58. package/dist/core/extensions/runner.d.ts.map +1 -1
  59. package/dist/core/extensions/runner.js +6 -0
  60. package/dist/core/extensions/runner.js.map +1 -1
  61. package/dist/core/extensions/types.d.ts +15 -1
  62. package/dist/core/extensions/types.d.ts.map +1 -1
  63. package/dist/core/extensions/types.js.map +1 -1
  64. package/dist/core/keybindings.d.ts +51 -11
  65. package/dist/core/keybindings.d.ts.map +1 -1
  66. package/dist/core/keybindings.js +11 -3
  67. package/dist/core/keybindings.js.map +1 -1
  68. package/dist/core/mcp-servers.d.ts +40 -7
  69. package/dist/core/mcp-servers.d.ts.map +1 -1
  70. package/dist/core/mcp-servers.js +63 -11
  71. package/dist/core/mcp-servers.js.map +1 -1
  72. package/dist/core/model-config.d.ts +36 -0
  73. package/dist/core/model-config.d.ts.map +1 -1
  74. package/dist/core/model-config.js +14 -2
  75. package/dist/core/model-config.js.map +1 -1
  76. package/dist/core/model-registry.d.ts +3 -1
  77. package/dist/core/model-registry.d.ts.map +1 -1
  78. package/dist/core/model-registry.js +4 -0
  79. package/dist/core/model-registry.js.map +1 -1
  80. package/dist/core/model-resolver.js +1 -1
  81. package/dist/core/model-resolver.js.map +1 -1
  82. package/dist/core/model-runtime.d.ts +6 -0
  83. package/dist/core/model-runtime.d.ts.map +1 -1
  84. package/dist/core/model-runtime.js +22 -18
  85. package/dist/core/model-runtime.js.map +1 -1
  86. package/dist/core/provider-composer.d.ts +2 -1
  87. package/dist/core/provider-composer.d.ts.map +1 -1
  88. package/dist/core/provider-composer.js +13 -0
  89. package/dist/core/provider-composer.js.map +1 -1
  90. package/dist/core/radius.d.ts +2 -0
  91. package/dist/core/radius.d.ts.map +1 -1
  92. package/dist/core/radius.js +2 -0
  93. package/dist/core/radius.js.map +1 -1
  94. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  95. package/dist/core/remote-catalog-provider.js +4 -9
  96. package/dist/core/remote-catalog-provider.js.map +1 -1
  97. package/dist/core/sdk.d.ts.map +1 -1
  98. package/dist/core/sdk.js +1 -0
  99. package/dist/core/sdk.js.map +1 -1
  100. package/dist/core/settings-manager.d.ts +7 -5
  101. package/dist/core/settings-manager.d.ts.map +1 -1
  102. package/dist/core/settings-manager.js +2 -1
  103. package/dist/core/settings-manager.js.map +1 -1
  104. package/dist/core/system-prompt.js +1 -1
  105. package/dist/core/system-prompt.js.map +1 -1
  106. package/dist/core/tasks/format.d.ts +7 -0
  107. package/dist/core/tasks/format.d.ts.map +1 -0
  108. package/dist/core/tasks/format.js +14 -0
  109. package/dist/core/tasks/format.js.map +1 -0
  110. package/dist/core/tasks/history.d.ts.map +1 -1
  111. package/dist/core/tasks/history.js +0 -19
  112. package/dist/core/tasks/history.js.map +1 -1
  113. package/dist/core/tasks/output.d.ts +8 -0
  114. package/dist/core/tasks/output.d.ts.map +1 -1
  115. package/dist/core/tasks/output.js +19 -0
  116. package/dist/core/tasks/output.js.map +1 -1
  117. package/dist/core/tasks/presentation.d.ts +1 -3
  118. package/dist/core/tasks/presentation.d.ts.map +1 -1
  119. package/dist/core/tasks/presentation.js +79 -166
  120. package/dist/core/tasks/presentation.js.map +1 -1
  121. package/dist/core/tasks/runtime.d.ts +16 -9
  122. package/dist/core/tasks/runtime.d.ts.map +1 -1
  123. package/dist/core/tasks/runtime.js +89 -106
  124. package/dist/core/tasks/runtime.js.map +1 -1
  125. package/dist/core/tasks/session.d.ts.map +1 -1
  126. package/dist/core/tasks/session.js +13 -4
  127. package/dist/core/tasks/session.js.map +1 -1
  128. package/dist/core/tasks/store.d.ts +20 -6
  129. package/dist/core/tasks/store.d.ts.map +1 -1
  130. package/dist/core/tasks/store.js +45 -18
  131. package/dist/core/tasks/store.js.map +1 -1
  132. package/dist/core/tasks/types.d.ts +14 -54
  133. package/dist/core/tasks/types.d.ts.map +1 -1
  134. package/dist/core/tasks/types.js +1 -5
  135. package/dist/core/tasks/types.js.map +1 -1
  136. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  137. package/dist/core/tools/renderers/bash.js +11 -34
  138. package/dist/core/tools/renderers/bash.js.map +1 -1
  139. package/dist/core/tools/renderers/index.d.ts +2 -2
  140. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  141. package/dist/core/tools/renderers/index.js.map +1 -1
  142. package/dist/core/tools/shell-execution.d.ts +0 -1
  143. package/dist/core/tools/shell-execution.d.ts.map +1 -1
  144. package/dist/core/tools/shell-execution.js +3 -10
  145. package/dist/core/tools/shell-execution.js.map +1 -1
  146. package/dist/core/tools/shell-tool.d.ts.map +1 -1
  147. package/dist/core/tools/shell-tool.js +2 -4
  148. package/dist/core/tools/shell-tool.js.map +1 -1
  149. package/dist/core/tools/tasks/actions.d.ts +1 -1
  150. package/dist/core/tools/tasks/actions.d.ts.map +1 -1
  151. package/dist/core/tools/tasks/actions.js +26 -12
  152. package/dist/core/tools/tasks/actions.js.map +1 -1
  153. package/dist/core/tools/tasks/constants.d.ts +2 -6
  154. package/dist/core/tools/tasks/constants.d.ts.map +1 -1
  155. package/dist/core/tools/tasks/constants.js +2 -6
  156. package/dist/core/tools/tasks/constants.js.map +1 -1
  157. package/dist/core/tools/tasks/schema.d.ts +1 -1
  158. package/dist/core/tools/tasks/schema.d.ts.map +1 -1
  159. package/dist/core/tools/tasks/schema.js +8 -7
  160. package/dist/core/tools/tasks/schema.js.map +1 -1
  161. package/dist/core/tools/tasks/types.d.ts +8 -38
  162. package/dist/core/tools/tasks/types.d.ts.map +1 -1
  163. package/dist/core/tools/tasks/types.js +6 -11
  164. package/dist/core/tools/tasks/types.js.map +1 -1
  165. package/dist/core/virtual-models.d.ts +2 -0
  166. package/dist/core/virtual-models.d.ts.map +1 -1
  167. package/dist/core/virtual-models.js +19 -12
  168. package/dist/core/virtual-models.js.map +1 -1
  169. package/dist/extensions/btw/agent.d.ts +17 -8
  170. package/dist/extensions/btw/agent.d.ts.map +1 -1
  171. package/dist/extensions/btw/agent.js +74 -76
  172. package/dist/extensions/btw/agent.js.map +1 -1
  173. package/dist/extensions/btw/controller.d.ts +0 -1
  174. package/dist/extensions/btw/controller.d.ts.map +1 -1
  175. package/dist/extensions/btw/controller.js +26 -33
  176. package/dist/extensions/btw/controller.js.map +1 -1
  177. package/dist/extensions/btw/panel.d.ts +13 -14
  178. package/dist/extensions/btw/panel.d.ts.map +1 -1
  179. package/dist/extensions/btw/panel.js +38 -29
  180. package/dist/extensions/btw/panel.js.map +1 -1
  181. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  182. package/dist/extensions/codemode/execute.js +197 -51
  183. package/dist/extensions/codemode/execute.js.map +1 -1
  184. package/dist/extensions/codemode/renderer.d.ts.map +1 -1
  185. package/dist/extensions/codemode/renderer.js +43 -25
  186. package/dist/extensions/codemode/renderer.js.map +1 -1
  187. package/dist/extensions/codemode/tool.d.ts +12 -11
  188. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  189. package/dist/extensions/codemode/tool.js +73 -129
  190. package/dist/extensions/codemode/tool.js.map +1 -1
  191. package/dist/extensions/codemode/worker.d.ts +1 -1
  192. package/dist/extensions/codemode/worker.js +1 -1
  193. package/dist/extensions/codemode/worker.js.map +1 -1
  194. package/dist/extensions/deepwiki/schema.d.ts +1 -1
  195. package/dist/extensions/index.d.ts.map +1 -1
  196. package/dist/extensions/index.js +0 -2
  197. package/dist/extensions/index.js.map +1 -1
  198. package/dist/extensions/mcp/cli.d.ts.map +1 -1
  199. package/dist/extensions/mcp/cli.js +23 -5
  200. package/dist/extensions/mcp/cli.js.map +1 -1
  201. package/dist/extensions/mcp/config.d.ts +19 -5
  202. package/dist/extensions/mcp/config.d.ts.map +1 -1
  203. package/dist/extensions/mcp/config.js +60 -12
  204. package/dist/extensions/mcp/config.js.map +1 -1
  205. package/dist/extensions/mcp/index.d.ts +36 -9
  206. package/dist/extensions/mcp/index.d.ts.map +1 -1
  207. package/dist/extensions/mcp/index.js +309 -100
  208. package/dist/extensions/mcp/index.js.map +1 -1
  209. package/dist/extensions/mcp/oauth.d.ts +14 -8
  210. package/dist/extensions/mcp/oauth.d.ts.map +1 -1
  211. package/dist/extensions/mcp/oauth.js +105 -36
  212. package/dist/extensions/mcp/oauth.js.map +1 -1
  213. package/dist/extensions/mcp/runtime.d.ts +2 -0
  214. package/dist/extensions/mcp/runtime.d.ts.map +1 -1
  215. package/dist/extensions/mcp/runtime.js +17 -9
  216. package/dist/extensions/mcp/runtime.js.map +1 -1
  217. package/dist/extensions/mcp/tools.d.ts +8 -5
  218. package/dist/extensions/mcp/tools.d.ts.map +1 -1
  219. package/dist/extensions/mcp/tools.js +50 -26
  220. package/dist/extensions/mcp/tools.js.map +1 -1
  221. package/dist/extensions/mcp/ui.d.ts.map +1 -1
  222. package/dist/extensions/mcp/ui.js +7 -1
  223. package/dist/extensions/mcp/ui.js.map +1 -1
  224. package/dist/extensions/provider/catalog.d.ts +8 -1
  225. package/dist/extensions/provider/catalog.d.ts.map +1 -1
  226. package/dist/extensions/provider/catalog.js +31 -0
  227. package/dist/extensions/provider/catalog.js.map +1 -1
  228. package/dist/extensions/provider/connection.d.ts +4 -1
  229. package/dist/extensions/provider/connection.d.ts.map +1 -1
  230. package/dist/extensions/provider/connection.js +1 -5
  231. package/dist/extensions/provider/connection.js.map +1 -1
  232. package/dist/extensions/provider/editing.d.ts +36 -0
  233. package/dist/extensions/provider/editing.d.ts.map +1 -0
  234. package/dist/extensions/provider/editing.js +99 -0
  235. package/dist/extensions/provider/editing.js.map +1 -0
  236. package/dist/extensions/provider/json-fields.d.ts +5 -0
  237. package/dist/extensions/provider/json-fields.d.ts.map +1 -0
  238. package/dist/extensions/provider/json-fields.js +31 -0
  239. package/dist/extensions/provider/json-fields.js.map +1 -0
  240. package/dist/extensions/provider/store.d.ts +1 -4
  241. package/dist/extensions/provider/store.d.ts.map +1 -1
  242. package/dist/extensions/provider/store.js +2 -30
  243. package/dist/extensions/provider/store.js.map +1 -1
  244. package/dist/extensions/provider/ui/builtin-data.d.ts +0 -2
  245. package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
  246. package/dist/extensions/provider/ui/builtin-data.js +14 -79
  247. package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
  248. package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
  249. package/dist/extensions/provider/ui/compat.js +6 -9
  250. package/dist/extensions/provider/ui/compat.js.map +1 -1
  251. package/dist/extensions/provider/ui/controls.d.ts +48 -0
  252. package/dist/extensions/provider/ui/controls.d.ts.map +1 -0
  253. package/dist/extensions/provider/ui/controls.js +108 -0
  254. package/dist/extensions/provider/ui/controls.js.map +1 -0
  255. package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
  256. package/dist/extensions/provider/ui/dictionary.js +6 -9
  257. package/dist/extensions/provider/ui/dictionary.js.map +1 -1
  258. package/dist/extensions/provider/ui/editor.d.ts +3 -3
  259. package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
  260. package/dist/extensions/provider/ui/editor.js +35 -140
  261. package/dist/extensions/provider/ui/editor.js.map +1 -1
  262. package/dist/extensions/provider/ui/fetch-models.d.ts +0 -3
  263. package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
  264. package/dist/extensions/provider/ui/fetch-models.js +49 -44
  265. package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
  266. package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
  267. package/dist/extensions/provider/ui/model-fields.js +11 -14
  268. package/dist/extensions/provider/ui/model-fields.js.map +1 -1
  269. package/dist/extensions/provider/ui/model-options.d.ts +4 -34
  270. package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
  271. package/dist/extensions/provider/ui/model-options.js +90 -271
  272. package/dist/extensions/provider/ui/model-options.js.map +1 -1
  273. package/dist/extensions/provider/ui/pane.d.ts +4 -18
  274. package/dist/extensions/provider/ui/pane.d.ts.map +1 -1
  275. package/dist/extensions/provider/ui/pane.js.map +1 -1
  276. package/dist/extensions/provider/ui/provider-fields.d.ts +2 -19
  277. package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
  278. package/dist/extensions/provider/ui/provider-fields.js +58 -171
  279. package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
  280. package/dist/extensions/provider/ui/thinking-map.d.ts.map +1 -1
  281. package/dist/extensions/provider/ui/thinking-map.js +6 -9
  282. package/dist/extensions/provider/ui/thinking-map.js.map +1 -1
  283. package/dist/extensions/question/detail-pane.d.ts +7 -2
  284. package/dist/extensions/question/detail-pane.d.ts.map +1 -1
  285. package/dist/extensions/question/detail-pane.js +16 -5
  286. package/dist/extensions/question/detail-pane.js.map +1 -1
  287. package/dist/extensions/question/dialog-view.d.ts +41 -0
  288. package/dist/extensions/question/dialog-view.d.ts.map +1 -0
  289. package/dist/extensions/question/dialog-view.js +329 -0
  290. package/dist/extensions/question/dialog-view.js.map +1 -0
  291. package/dist/extensions/question/dialog.d.ts +3 -3
  292. package/dist/extensions/question/dialog.d.ts.map +1 -1
  293. package/dist/extensions/question/dialog.js +220 -634
  294. package/dist/extensions/question/dialog.js.map +1 -1
  295. package/dist/extensions/question/index.d.ts.map +1 -1
  296. package/dist/extensions/question/index.js +2 -3
  297. package/dist/extensions/question/index.js.map +1 -1
  298. package/dist/extensions/question/render.d.ts.map +1 -1
  299. package/dist/extensions/question/render.js +22 -32
  300. package/dist/extensions/question/render.js.map +1 -1
  301. package/dist/extensions/question/results.d.ts.map +1 -1
  302. package/dist/extensions/question/results.js +56 -12
  303. package/dist/extensions/question/results.js.map +1 -1
  304. package/dist/extensions/question/schema.d.ts +21 -6
  305. package/dist/extensions/question/schema.d.ts.map +1 -1
  306. package/dist/extensions/question/schema.js.map +1 -1
  307. package/dist/extensions/question/state.d.ts +9 -7
  308. package/dist/extensions/question/state.d.ts.map +1 -1
  309. package/dist/extensions/question/state.js +63 -54
  310. package/dist/extensions/question/state.js.map +1 -1
  311. package/dist/extensions/question/types.d.ts +41 -18
  312. package/dist/extensions/question/types.d.ts.map +1 -1
  313. package/dist/extensions/question/types.js.map +1 -1
  314. package/dist/extensions/statusline/index.d.ts +4 -0
  315. package/dist/extensions/statusline/index.d.ts.map +1 -1
  316. package/dist/extensions/statusline/index.js +18 -355
  317. package/dist/extensions/statusline/index.js.map +1 -1
  318. package/dist/extensions/statusline/render.d.ts +19 -0
  319. package/dist/extensions/statusline/render.d.ts.map +1 -0
  320. package/dist/extensions/statusline/render.js +163 -0
  321. package/dist/extensions/statusline/render.js.map +1 -0
  322. package/dist/extensions/statusline/usage.d.ts +12 -0
  323. package/dist/extensions/statusline/usage.d.ts.map +1 -0
  324. package/dist/extensions/statusline/usage.js +36 -0
  325. package/dist/extensions/statusline/usage.js.map +1 -0
  326. package/dist/extensions/tool-search/tool.d.ts +5 -4
  327. package/dist/extensions/tool-search/tool.d.ts.map +1 -1
  328. package/dist/extensions/tool-search/tool.js +7 -28
  329. package/dist/extensions/tool-search/tool.js.map +1 -1
  330. package/dist/extensions/web-search/execute.d.ts +1 -5
  331. package/dist/extensions/web-search/execute.d.ts.map +1 -1
  332. package/dist/extensions/web-search/execute.js +4 -9
  333. package/dist/extensions/web-search/execute.js.map +1 -1
  334. package/dist/extensions/web-search/format.d.ts +12 -3
  335. package/dist/extensions/web-search/format.d.ts.map +1 -1
  336. package/dist/extensions/web-search/format.js +33 -25
  337. package/dist/extensions/web-search/format.js.map +1 -1
  338. package/dist/extensions/web-search/index.d.ts.map +1 -1
  339. package/dist/extensions/web-search/index.js +6 -29
  340. package/dist/extensions/web-search/index.js.map +1 -1
  341. package/dist/extensions/web-search/providers/deepseek.d.ts.map +1 -1
  342. package/dist/extensions/web-search/providers/deepseek.js +0 -1
  343. package/dist/extensions/web-search/providers/deepseek.js.map +1 -1
  344. package/dist/extensions/web-search/providers/http.d.ts +1 -1
  345. package/dist/extensions/web-search/providers/http.d.ts.map +1 -1
  346. package/dist/extensions/web-search/providers/http.js.map +1 -1
  347. package/dist/extensions/web-search/providers/minimax.d.ts.map +1 -1
  348. package/dist/extensions/web-search/providers/minimax.js +0 -1
  349. package/dist/extensions/web-search/providers/minimax.js.map +1 -1
  350. package/dist/extensions/web-search/render.d.ts +7 -2
  351. package/dist/extensions/web-search/render.d.ts.map +1 -1
  352. package/dist/extensions/web-search/render.js +32 -4
  353. package/dist/extensions/web-search/render.js.map +1 -1
  354. package/dist/extensions/web-search/results.d.ts.map +1 -1
  355. package/dist/extensions/web-search/results.js +3 -8
  356. package/dist/extensions/web-search/results.js.map +1 -1
  357. package/dist/extensions/web-search/types.d.ts +4 -2
  358. package/dist/extensions/web-search/types.d.ts.map +1 -1
  359. package/dist/extensions/web-search/types.js.map +1 -1
  360. package/dist/index.d.ts +3 -5
  361. package/dist/index.d.ts.map +1 -1
  362. package/dist/index.js +0 -1
  363. package/dist/index.js.map +1 -1
  364. package/dist/main.d.ts.map +1 -1
  365. package/dist/main.js +6 -0
  366. package/dist/main.js.map +1 -1
  367. package/dist/modes/interactive/components/armin.d.ts +3 -0
  368. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  369. package/dist/modes/interactive/components/armin.js +7 -5
  370. package/dist/modes/interactive/components/armin.js.map +1 -1
  371. package/dist/modes/interactive/components/auth-url.d.ts +14 -0
  372. package/dist/modes/interactive/components/auth-url.d.ts.map +1 -0
  373. package/dist/modes/interactive/components/auth-url.js +34 -0
  374. package/dist/modes/interactive/components/auth-url.js.map +1 -0
  375. package/dist/modes/interactive/components/easter-egg-3d.d.ts +104 -0
  376. package/dist/modes/interactive/components/easter-egg-3d.d.ts.map +1 -0
  377. package/dist/modes/interactive/components/easter-egg-3d.js +1123 -0
  378. package/dist/modes/interactive/components/easter-egg-3d.js.map +1 -0
  379. package/dist/modes/interactive/components/easter-egg-3d.lazy.d.ts +6 -0
  380. package/dist/modes/interactive/components/easter-egg-3d.lazy.d.ts.map +1 -0
  381. package/dist/modes/interactive/components/easter-egg-3d.lazy.js +24 -0
  382. package/dist/modes/interactive/components/easter-egg-3d.lazy.js.map +1 -0
  383. package/dist/modes/interactive/components/index.d.ts +0 -1
  384. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  385. package/dist/modes/interactive/components/index.js +0 -1
  386. package/dist/modes/interactive/components/index.js.map +1 -1
  387. package/dist/modes/interactive/components/login-dialog.d.ts +2 -0
  388. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  389. package/dist/modes/interactive/components/login-dialog.js +9 -5
  390. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  391. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  392. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  393. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  394. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  395. package/dist/modes/interactive/components/pi-logo.d.ts +7 -0
  396. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -1
  397. package/dist/modes/interactive/components/pi-logo.js +13 -1
  398. package/dist/modes/interactive/components/pi-logo.js.map +1 -1
  399. package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
  400. package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
  401. package/dist/modes/interactive/components/radius-login-selector.js +83 -0
  402. package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
  403. package/dist/modes/interactive/components/settings-selector.d.ts +3 -3
  404. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  405. package/dist/modes/interactive/components/settings-selector.js +5 -5
  406. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  407. package/dist/modes/interactive/components/status-marker.d.ts +0 -2
  408. package/dist/modes/interactive/components/status-marker.d.ts.map +1 -1
  409. package/dist/modes/interactive/components/status-marker.js +0 -4
  410. package/dist/modes/interactive/components/status-marker.js.map +1 -1
  411. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  412. package/dist/modes/interactive/components/user-message.js +5 -4
  413. package/dist/modes/interactive/components/user-message.js.map +1 -1
  414. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  415. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  416. package/dist/modes/interactive/components/visual-truncate.js +36 -6
  417. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  418. package/dist/modes/interactive/interactive-mode.d.ts +12 -2
  419. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  420. package/dist/modes/interactive/interactive-mode.js +180 -55
  421. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  422. package/dist/modes/interactive/tasks/completion-render.d.ts +1 -1
  423. package/dist/modes/interactive/tasks/completion-render.d.ts.map +1 -1
  424. package/dist/modes/interactive/tasks/completion-render.js +28 -82
  425. package/dist/modes/interactive/tasks/completion-render.js.map +1 -1
  426. package/dist/modes/interactive/tasks/index.d.ts.map +1 -1
  427. package/dist/modes/interactive/tasks/index.js +18 -13
  428. package/dist/modes/interactive/tasks/index.js.map +1 -1
  429. package/dist/modes/interactive/tasks/inspector.d.ts +35 -0
  430. package/dist/modes/interactive/tasks/inspector.d.ts.map +1 -0
  431. package/dist/modes/interactive/tasks/inspector.js +93 -0
  432. package/dist/modes/interactive/tasks/inspector.js.map +1 -0
  433. package/dist/modes/interactive/tasks/layout.d.ts +40 -0
  434. package/dist/modes/interactive/tasks/layout.d.ts.map +1 -0
  435. package/dist/modes/interactive/tasks/layout.js +212 -0
  436. package/dist/modes/interactive/tasks/layout.js.map +1 -0
  437. package/dist/modes/interactive/tasks/list.d.ts +21 -0
  438. package/dist/modes/interactive/tasks/list.d.ts.map +1 -0
  439. package/dist/modes/interactive/tasks/list.js +96 -0
  440. package/dist/modes/interactive/tasks/list.js.map +1 -0
  441. package/dist/modes/interactive/tasks/manager.d.ts +29 -36
  442. package/dist/modes/interactive/tasks/manager.d.ts.map +1 -1
  443. package/dist/modes/interactive/tasks/manager.js +315 -315
  444. package/dist/modes/interactive/tasks/manager.js.map +1 -1
  445. package/dist/modes/interactive/tasks/model.d.ts +21 -0
  446. package/dist/modes/interactive/tasks/model.d.ts.map +1 -0
  447. package/dist/modes/interactive/tasks/model.js +41 -0
  448. package/dist/modes/interactive/tasks/model.js.map +1 -0
  449. package/dist/modes/interactive/tasks/render.d.ts +5 -19
  450. package/dist/modes/interactive/tasks/render.d.ts.map +1 -1
  451. package/dist/modes/interactive/tasks/render.js +18 -102
  452. package/dist/modes/interactive/tasks/render.js.map +1 -1
  453. package/dist/modes/interactive/tasks/task-view.d.ts +8 -48
  454. package/dist/modes/interactive/tasks/task-view.d.ts.map +1 -1
  455. package/dist/modes/interactive/tasks/task-view.js +11 -51
  456. package/dist/modes/interactive/tasks/task-view.js.map +1 -1
  457. package/dist/modes/interactive/tasks/text.d.ts +1 -7
  458. package/dist/modes/interactive/tasks/text.d.ts.map +1 -1
  459. package/dist/modes/interactive/tasks/text.js +6 -29
  460. package/dist/modes/interactive/tasks/text.js.map +1 -1
  461. package/dist/modes/interactive/tasks/viewport.d.ts +2 -0
  462. package/dist/modes/interactive/tasks/viewport.d.ts.map +1 -1
  463. package/dist/modes/interactive/tasks/viewport.js +17 -7
  464. package/dist/modes/interactive/tasks/viewport.js.map +1 -1
  465. package/dist/modes/interactive/tasks/views.d.ts +9 -0
  466. package/dist/modes/interactive/tasks/views.d.ts.map +1 -0
  467. package/dist/modes/interactive/tasks/views.js +42 -0
  468. package/dist/modes/interactive/tasks/views.js.map +1 -0
  469. package/dist/modes/interactive/theme/system-theme.d.ts +2 -1
  470. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -1
  471. package/dist/modes/interactive/theme/system-theme.js +16 -5
  472. package/dist/modes/interactive/theme/system-theme.js.map +1 -1
  473. package/dist/modes/interactive/tool-view/tool-execution.d.ts +4 -19
  474. package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -1
  475. package/dist/modes/interactive/tool-view/tool-execution.js +23 -67
  476. package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -1
  477. package/dist/utils/image-convert.d.ts +12 -0
  478. package/dist/utils/image-convert.d.ts.map +1 -1
  479. package/dist/utils/image-convert.js +45 -6
  480. package/dist/utils/image-convert.js.map +1 -1
  481. package/docs/bundled/README.md +0 -1
  482. package/docs/bundled/extensions/question.md +2 -2
  483. package/docs/bundled/extensions/statusline.md +24 -15
  484. package/docs/bundled/tasks.md +34 -48
  485. package/docs/codemode.md +207 -0
  486. package/docs/docs.json +4 -4
  487. package/docs/environment-variables.md +1 -1
  488. package/docs/extensions.md +11 -9
  489. package/docs/keybindings.md +14 -7
  490. package/docs/mcp.md +164 -82
  491. package/docs/models.md +51 -3
  492. package/docs/providers.md +8 -0
  493. package/docs/sdk.md +2 -2
  494. package/docs/session-format.md +12 -22
  495. package/docs/settings.md +4 -2
  496. package/docs/tui.md +1 -1
  497. package/docs/usage.md +6 -16
  498. package/examples/README.md +1 -1
  499. package/examples/extensions/README.md +1 -2
  500. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  501. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  502. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  503. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  504. package/examples/extensions/gondolin/package-lock.json +2 -2
  505. package/examples/extensions/gondolin/package.json +1 -1
  506. package/examples/extensions/minimal-mode.ts +24 -96
  507. package/examples/extensions/sandbox/package-lock.json +2 -2
  508. package/examples/extensions/sandbox/package.json +1 -1
  509. package/examples/extensions/with-deps/package-lock.json +2 -2
  510. package/examples/extensions/with-deps/package.json +1 -1
  511. package/examples/sdk/14-codemode-mcp.ts +2 -2
  512. package/npm-shrinkwrap.json +73 -62
  513. package/package.json +11 -10
  514. package/dist/bundle/chunks/anthropic-messages-KIXY7EDT.js +0 -6
  515. package/dist/bundle/chunks/azure-openai-responses-RPBERDXD.js +0 -2
  516. package/dist/bundle/chunks/chunk-CLLDCO64.js +0 -2
  517. package/dist/bundle/chunks/chunk-PJVFYVHE.js +0 -42
  518. package/dist/bundle/chunks/chunk-UUSTLCVC.js +0 -2
  519. package/dist/bundle/chunks/chunk-VWCWZD6E.js +0 -2
  520. package/dist/bundle/chunks/node-CXWYTK2I.js +0 -16
  521. package/dist/bundle/chunks/openai-completions-SKDGF6OE.js +0 -7
  522. package/dist/bundle/chunks/openai-responses-FPML4SSG.js +0 -3
  523. package/dist/bundle/chunks/virtual-modules-TQRORWJQ.js +0 -2
  524. package/dist/core/tasks/view-data.d.ts +0 -8
  525. package/dist/core/tasks/view-data.d.ts.map +0 -1
  526. package/dist/core/tasks/view-data.js +0 -61
  527. package/dist/core/tasks/view-data.js.map +0 -1
  528. package/dist/core/tasks/view.d.ts +0 -30
  529. package/dist/core/tasks/view.d.ts.map +0 -1
  530. package/dist/core/tasks/view.js +0 -50
  531. package/dist/core/tasks/view.js.map +0 -1
  532. package/dist/core/tools/renderers/shell-task.d.ts +0 -4
  533. package/dist/core/tools/renderers/shell-task.d.ts.map +0 -1
  534. package/dist/core/tools/renderers/shell-task.js +0 -35
  535. package/dist/core/tools/renderers/shell-task.js.map +0 -1
  536. package/dist/extensions/todo/constants.d.ts +0 -16
  537. package/dist/extensions/todo/constants.d.ts.map +0 -1
  538. package/dist/extensions/todo/constants.js +0 -30
  539. package/dist/extensions/todo/constants.js.map +0 -1
  540. package/dist/extensions/todo/index.d.ts +0 -3
  541. package/dist/extensions/todo/index.d.ts.map +0 -1
  542. package/dist/extensions/todo/index.js +0 -98
  543. package/dist/extensions/todo/index.js.map +0 -1
  544. package/dist/extensions/todo/schema.d.ts +0 -60
  545. package/dist/extensions/todo/schema.d.ts.map +0 -1
  546. package/dist/extensions/todo/schema.js +0 -56
  547. package/dist/extensions/todo/schema.js.map +0 -1
  548. package/dist/extensions/todo/state.d.ts +0 -34
  549. package/dist/extensions/todo/state.d.ts.map +0 -1
  550. package/dist/extensions/todo/state.js +0 -425
  551. package/dist/extensions/todo/state.js.map +0 -1
  552. package/dist/extensions/todo/view.d.ts +0 -36
  553. package/dist/extensions/todo/view.d.ts.map +0 -1
  554. package/dist/extensions/todo/view.js +0 -580
  555. package/dist/extensions/todo/view.js.map +0 -1
  556. package/dist/extensions/todo/widget.d.ts +0 -15
  557. package/dist/extensions/todo/widget.d.ts.map +0 -1
  558. package/dist/extensions/todo/widget.js +0 -50
  559. package/dist/extensions/todo/widget.js.map +0 -1
  560. package/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  561. package/dist/modes/interactive/components/daxnuts.d.ts.map +0 -1
  562. package/dist/modes/interactive/components/daxnuts.js +0 -138
  563. package/dist/modes/interactive/components/daxnuts.js.map +0 -1
  564. package/dist/modes/interactive/tasks/fallback-view.d.ts +0 -4
  565. package/dist/modes/interactive/tasks/fallback-view.d.ts.map +0 -1
  566. package/dist/modes/interactive/tasks/fallback-view.js +0 -27
  567. package/dist/modes/interactive/tasks/fallback-view.js.map +0 -1
  568. package/docs/bundled/extensions/todo.md +0 -104
  569. package/examples/extensions/todo.ts +0 -297
@@ -33,14 +33,16 @@ export class BtwPanel {
33
33
  if (this.disposed)
34
34
  return;
35
35
  this.tui.requestRender();
36
- if (this.getState().busy && !this.timer) {
36
+ const state = this.getState();
37
+ const busy = state.phase === "ready" && state.conversation.busy;
38
+ if (busy && !this.timer) {
37
39
  this.timer = setTimeout(() => {
38
40
  this.timer = undefined;
39
41
  this.changed();
40
42
  }, 150);
41
43
  this.timer.unref?.();
42
44
  }
43
- else if (!this.getState().busy && this.timer) {
45
+ else if (!busy && this.timer) {
44
46
  clearTimeout(this.timer);
45
47
  this.timer = undefined;
46
48
  }
@@ -68,12 +70,13 @@ export class BtwPanel {
68
70
  if (this.disposed || width < 1)
69
71
  return [];
70
72
  const state = this.getState();
73
+ const busy = state.phase === "ready" && state.conversation.busy;
71
74
  const theme = this.getTheme();
72
75
  const innerWidth = Math.max(1, width - 4);
73
76
  const lines = this.body(state, innerWidth, theme);
74
77
  const cap = Math.max(1, Math.floor(this.tui.terminal.rows / 3) - 2);
75
78
  const needed = Math.min(cap, Math.max(1, lines.length));
76
- this.heldHeight = state.busy ? Math.min(cap, Math.max(this.heldHeight, needed)) : needed;
79
+ this.heldHeight = busy ? Math.min(cap, Math.max(this.heldHeight, needed)) : needed;
77
80
  this.maxOffset = Math.max(0, lines.length - this.heldHeight);
78
81
  this.offset = this.follow ? this.maxOffset : Math.min(this.offset, this.maxOffset);
79
82
  const body = lines.slice(this.offset, this.offset + this.heldHeight);
@@ -84,7 +87,7 @@ export class BtwPanel {
84
87
  const title = [
85
88
  theme.fg("accent", theme.bold("BTW")),
86
89
  close && theme.fg("text", close) + theme.fg("muted", " close"),
87
- state.busy && cancel && theme.fg("text", cancel) + theme.fg("muted", " stop"),
90
+ busy && cancel && theme.fg("text", cancel) + theme.fg("muted", " stop"),
88
91
  ]
89
92
  .filter(Boolean)
90
93
  .join(theme.fg("muted", " · "));
@@ -103,29 +106,34 @@ export class BtwPanel {
103
106
  if (state.phase === "opening")
104
107
  return [theme.fg("muted", "Capturing context…")];
105
108
  if (state.phase === "error")
106
- return new Text(theme.fg("error", state.error ?? "Could not open BTW."), 0, 0).render(width);
107
- if (!state.turns.length) {
109
+ return new Text(theme.fg("error", state.error), 0, 0).render(width);
110
+ if (!state.conversation.turns.length) {
108
111
  return [
109
112
  ...new Text(theme.fg("text", "Ask a side question in the editor below."), 0, 0).render(width),
110
- ...new Text(theme.fg("muted", `Context at ${new Date(state.capturedAt ?? Date.now()).toTimeString().slice(0, 8)} · ${state.model ?? ""}`), 0, 0).render(width),
113
+ ...new Text(theme.fg("muted", `Context at ${new Date(state.capturedAt).toTimeString().slice(0, 8)} · ${state.model}`), 0, 0).render(width),
111
114
  ];
112
115
  }
113
116
  const lines = [];
114
- for (const [index, turn] of state.turns.entries()) {
117
+ for (const [index, turn] of state.conversation.turns.entries()) {
115
118
  if (index > 0)
116
119
  lines.push("");
117
120
  lines.push(...new Text(theme.fg("accent", theme.bold(`Q${index + 1}: `)) + theme.fg("text", turn.question), 0, 0).render(width));
118
121
  if (turn.answer) {
119
- let markdown = this.answers.get(turn);
120
- if (!markdown) {
121
- markdown = new Markdown(turn.answer, 0, 0, getMarkdownTheme(), {
122
- color: (text) => theme.fg("text", text),
123
- });
124
- this.answers.set(turn, markdown);
122
+ let answer = this.answers.get(turn);
123
+ if (!answer) {
124
+ answer = {
125
+ text: turn.answer,
126
+ markdown: new Markdown(turn.answer, 0, 0, getMarkdownTheme(), {
127
+ color: (text) => theme.fg("text", text),
128
+ }),
129
+ };
130
+ this.answers.set(turn, answer);
131
+ }
132
+ else if (answer.text !== turn.answer) {
133
+ answer.text = turn.answer;
134
+ answer.markdown.setText(turn.answer);
125
135
  }
126
- else
127
- markdown.setText(turn.answer);
128
- lines.push(...markdown.render(width));
136
+ lines.push(...answer.markdown.render(width));
129
137
  }
130
138
  else if (turn.thinking && (turn.status === "streaming" || turn.status === "cancelling")) {
131
139
  lines.push(...wrapTextWithAnsi(theme.fg("muted", turn.thinking.trimEnd()), width).slice(-2));
@@ -149,8 +157,9 @@ export class BtwPanel {
149
157
  label(" scroll ") +
150
158
  value(`${this.offset + 1}–${this.offset + this.heldHeight}/${this.maxOffset + this.heldHeight}`));
151
159
  }
152
- const usage = state.usage;
153
- if (usage) {
160
+ if (state.phase === "ready") {
161
+ const { conversation } = state;
162
+ const { usage } = conversation;
154
163
  const stats = [];
155
164
  if (usage.input > 0)
156
165
  stats.push(`↑${tokens(usage.input)}`);
@@ -160,20 +169,20 @@ export class BtwPanel {
160
169
  stats.push(`R${tokens(usage.cacheRead)}`);
161
170
  if (usage.cacheWrite > 0)
162
171
  stats.push(`W${tokens(usage.cacheWrite)}`);
163
- if (state.latestCacheHitPercent !== undefined)
164
- stats.push(`CH${state.latestCacheHitPercent.toFixed(1)}%`);
172
+ if (conversation.latestCacheHitPercent !== undefined)
173
+ stats.push(`CH${conversation.latestCacheHitPercent.toFixed(1)}%`);
165
174
  if (usage.cost.total > 0)
166
175
  stats.push(`$${usage.cost.total.toFixed(3)}${state.usesSubscription ? " (sub)" : ""}`);
167
176
  if (stats.length)
168
177
  parts.push(value(stats.join(" ")));
169
- }
170
- if (state.blockedTools)
171
- parts.push(value(String(state.blockedTools)) + label(" tools blocked"));
172
- const turn = state.turns.at(-1);
173
- if (turn && !state.busy) {
174
- parts.push(value(`${(turn.elapsedMs / 1000).toFixed(1)}s`));
175
- if (turn.firstAnswerMs !== undefined)
176
- parts.push(label("first ") + value(`${(turn.firstAnswerMs / 1000).toFixed(1)}s`));
178
+ if (conversation.blockedTools)
179
+ parts.push(value(String(conversation.blockedTools)) + label(" tools blocked"));
180
+ const turn = conversation.turns.at(-1);
181
+ if (turn && !conversation.busy) {
182
+ parts.push(value(`${(turn.elapsedMs / 1000).toFixed(1)}s`));
183
+ if (turn.firstAnswerMs !== undefined)
184
+ parts.push(label("first ") + value(`${(turn.firstAnswerMs / 1000).toFixed(1)}s`));
185
+ }
177
186
  }
178
187
  return parts.join(label(" · "));
179
188
  }
@@ -1 +1 @@
1
- {"version":3,"file":"panel.js","sourceRoot":"","sources":["../../../src/extensions/btw/panel.ts"],"names":[],"mappings":"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","sourcesContent":["import \"./keybindings.ts\";\nimport type { Usage } from \"@earendil-works/pi-ai\";\nimport {\n\ttype Component,\n\tMarkdown,\n\tText,\n\ttype TUI,\n\ttruncateToWidth,\n\tvisibleWidth,\n\twrapTextWithAnsi,\n} from \"@earendil-works/pi-tui\";\nimport { keyLabel } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { getMarkdownTheme, type Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { BtwTurn } from \"./agent.ts\";\n\nexport interface BtwPanelState {\n\tphase: \"opening\" | \"ready\" | \"error\";\n\terror?: string;\n\tcapturedAt?: number;\n\tmodel?: string;\n\tbusy: boolean;\n\tturns: readonly BtwTurn[];\n\tusage?: Usage;\n\tlatestCacheHitPercent?: number;\n\tusesSubscription?: boolean;\n\tblockedTools: number;\n}\n\nfunction tokens(value: number): string {\n\tif (value < 1000) return String(value);\n\tif (value < 10_000) return `${(value / 1000).toFixed(1)}k`;\n\tif (value < 1_000_000) return `${Math.round(value / 1000)}k`;\n\tif (value < 10_000_000) return `${(value / 1_000_000).toFixed(1)}M`;\n\treturn `${Math.round(value / 1_000_000)}M`;\n}\n\n/** A bounded, scrollable widget above the normal editor. It never takes keyboard focus. */\nexport class BtwPanel implements Component {\n\tprivate readonly tui: Pick<TUI, \"terminal\" | \"requestRender\">;\n\tprivate readonly getTheme: () => Theme;\n\tprivate readonly getState: () => BtwPanelState;\n\tprivate readonly answers = new Map<BtwTurn, Markdown>();\n\tprivate follow = true;\n\tprivate offset = 0;\n\tprivate maxOffset = 0;\n\tprivate heldHeight = 0;\n\tprivate timer?: ReturnType<typeof setTimeout>;\n\tprivate disposed = false;\n\n\tconstructor(tui: Pick<TUI, \"terminal\" | \"requestRender\">, getTheme: () => Theme, getState: () => BtwPanelState) {\n\t\tthis.tui = tui;\n\t\tthis.getTheme = getTheme;\n\t\tthis.getState = getState;\n\t}\n\n\tinvalidate(): void {\n\t\tthis.answers.clear();\n\t}\n\n\tchanged(): void {\n\t\tif (this.disposed) return;\n\t\tthis.tui.requestRender();\n\t\tif (this.getState().busy && !this.timer) {\n\t\t\tthis.timer = setTimeout(() => {\n\t\t\t\tthis.timer = undefined;\n\t\t\t\tthis.changed();\n\t\t\t}, 150);\n\t\t\tthis.timer.unref?.();\n\t\t} else if (!this.getState().busy && this.timer) {\n\t\t\tclearTimeout(this.timer);\n\t\t\tthis.timer = undefined;\n\t\t}\n\t}\n\n\tfollowTail(): void {\n\t\tthis.follow = true;\n\t\tthis.changed();\n\t}\n\n\tscroll(delta: number): boolean {\n\t\tif (this.maxOffset === 0) return false;\n\t\tthis.offset = Math.max(0, Math.min(this.maxOffset, this.offset + delta));\n\t\tthis.follow = this.offset === this.maxOffset;\n\t\tthis.tui.requestRender();\n\t\treturn true;\n\t}\n\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tif (this.timer) clearTimeout(this.timer);\n\t\tthis.timer = undefined;\n\t\tthis.answers.clear();\n\t}\n\n\trender(width: number): string[] {\n\t\tif (this.disposed || width < 1) return [];\n\t\tconst state = this.getState();\n\t\tconst theme = this.getTheme();\n\t\tconst innerWidth = Math.max(1, width - 4);\n\t\tconst lines = this.body(state, innerWidth, theme);\n\t\tconst cap = Math.max(1, Math.floor(this.tui.terminal.rows / 3) - 2);\n\t\tconst needed = Math.min(cap, Math.max(1, lines.length));\n\t\tthis.heldHeight = state.busy ? Math.min(cap, Math.max(this.heldHeight, needed)) : needed;\n\t\tthis.maxOffset = Math.max(0, lines.length - this.heldHeight);\n\t\tthis.offset = this.follow ? this.maxOffset : Math.min(this.offset, this.maxOffset);\n\t\tconst body = lines.slice(this.offset, this.offset + this.heldHeight);\n\t\twhile (body.length < this.heldHeight) body.push(\"\");\n\t\tconst close = keyLabel(\"app.btw.close\");\n\t\tconst cancel = keyLabel(\"app.btw.cancel\");\n\t\tconst title = [\n\t\t\ttheme.fg(\"accent\", theme.bold(\"BTW\")),\n\t\t\tclose && theme.fg(\"text\", close) + theme.fg(\"muted\", \" close\"),\n\t\t\tstate.busy && cancel && theme.fg(\"text\", cancel) + theme.fg(\"muted\", \" stop\"),\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.join(theme.fg(\"muted\", \" · \"));\n\t\tconst footer = this.footer(state, theme);\n\t\tif (width < 6) return body.map((line) => truncateToWidth(line, width));\n\t\treturn [\n\t\t\tthis.border(title, width, true, theme),\n\t\t\t...body.map(\n\t\t\t\t(line) =>\n\t\t\t\t\ttheme.fg(\"borderAccent\", \"│ \") +\n\t\t\t\t\ttruncateToWidth(line, innerWidth, \"…\", true) +\n\t\t\t\t\ttheme.fg(\"borderAccent\", \" │\"),\n\t\t\t),\n\t\t\tthis.border(footer, width, false, theme),\n\t\t];\n\t}\n\n\tprivate body(state: BtwPanelState, width: number, theme: Theme): string[] {\n\t\tif (state.phase === \"opening\") return [theme.fg(\"muted\", \"Capturing context…\")];\n\t\tif (state.phase === \"error\")\n\t\t\treturn new Text(theme.fg(\"error\", state.error ?? \"Could not open BTW.\"), 0, 0).render(width);\n\t\tif (!state.turns.length) {\n\t\t\treturn [\n\t\t\t\t...new Text(theme.fg(\"text\", \"Ask a side question in the editor below.\"), 0, 0).render(width),\n\t\t\t\t...new Text(\n\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\"muted\",\n\t\t\t\t\t\t`Context at ${new Date(state.capturedAt ?? Date.now()).toTimeString().slice(0, 8)} · ${state.model ?? \"\"}`,\n\t\t\t\t\t),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t).render(width),\n\t\t\t];\n\t\t}\n\t\tconst lines: string[] = [];\n\t\tfor (const [index, turn] of state.turns.entries()) {\n\t\t\tif (index > 0) lines.push(\"\");\n\t\t\tlines.push(\n\t\t\t\t...new Text(\n\t\t\t\t\ttheme.fg(\"accent\", theme.bold(`Q${index + 1}: `)) + theme.fg(\"text\", turn.question),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t).render(width),\n\t\t\t);\n\t\t\tif (turn.answer) {\n\t\t\t\tlet markdown = this.answers.get(turn);\n\t\t\t\tif (!markdown) {\n\t\t\t\t\tmarkdown = new Markdown(turn.answer, 0, 0, getMarkdownTheme(), {\n\t\t\t\t\t\tcolor: (text) => theme.fg(\"text\", text),\n\t\t\t\t\t});\n\t\t\t\t\tthis.answers.set(turn, markdown);\n\t\t\t\t} else markdown.setText(turn.answer);\n\t\t\t\tlines.push(...markdown.render(width));\n\t\t\t} else if (turn.thinking && (turn.status === \"streaming\" || turn.status === \"cancelling\")) {\n\t\t\t\tlines.push(...wrapTextWithAnsi(theme.fg(\"muted\", turn.thinking.trimEnd()), width).slice(-2));\n\t\t\t}\n\t\t\tif (turn.status === \"streaming\" || turn.status === \"cancelling\") {\n\t\t\t\tconst elapsed = ((Date.now() - turn.startedAt) / 1000).toFixed(1);\n\t\t\t\tlines.push(theme.fg(\"muted\", `${turn.status === \"cancelling\" ? \"Stopping\" : \"Answering\"}… ${elapsed}s`));\n\t\t\t}\n\t\t\tif (turn.notice)\n\t\t\t\tlines.push(\n\t\t\t\t\t...new Text(theme.fg(turn.status === \"error\" ? \"error\" : \"muted\", turn.notice), 0, 0).render(width),\n\t\t\t\t);\n\t\t}\n\t\treturn lines;\n\t}\n\n\tprivate footer(state: BtwPanelState, theme: Theme): string {\n\t\tconst parts: string[] = [];\n\t\tconst label = (text: string) => theme.fg(\"muted\", text);\n\t\tconst value = (text: string) => theme.fg(\"text\", text);\n\t\tif (this.maxOffset > 0) {\n\t\t\tconst keys = [keyLabel(\"app.btw.scrollUp\"), keyLabel(\"app.btw.scrollDown\")].filter(Boolean).join(\"/\");\n\t\t\tparts.push(\n\t\t\t\tvalue(keys) +\n\t\t\t\t\tlabel(\" scroll \") +\n\t\t\t\t\tvalue(`${this.offset + 1}–${this.offset + this.heldHeight}/${this.maxOffset + this.heldHeight}`),\n\t\t\t);\n\t\t}\n\t\tconst usage = state.usage;\n\t\tif (usage) {\n\t\t\tconst stats: string[] = [];\n\t\t\tif (usage.input > 0) stats.push(`↑${tokens(usage.input)}`);\n\t\t\tif (usage.output > 0) stats.push(`↓${tokens(usage.output)}`);\n\t\t\tif (usage.cacheRead > 0) stats.push(`R${tokens(usage.cacheRead)}`);\n\t\t\tif (usage.cacheWrite > 0) stats.push(`W${tokens(usage.cacheWrite)}`);\n\t\t\tif (state.latestCacheHitPercent !== undefined) stats.push(`CH${state.latestCacheHitPercent.toFixed(1)}%`);\n\t\t\tif (usage.cost.total > 0)\n\t\t\t\tstats.push(`$${usage.cost.total.toFixed(3)}${state.usesSubscription ? \" (sub)\" : \"\"}`);\n\t\t\tif (stats.length) parts.push(value(stats.join(\" \")));\n\t\t}\n\t\tif (state.blockedTools) parts.push(value(String(state.blockedTools)) + label(\" tools blocked\"));\n\t\tconst turn = state.turns.at(-1);\n\t\tif (turn && !state.busy) {\n\t\t\tparts.push(value(`${(turn.elapsedMs / 1000).toFixed(1)}s`));\n\t\t\tif (turn.firstAnswerMs !== undefined)\n\t\t\t\tparts.push(label(\"first \") + value(`${(turn.firstAnswerMs / 1000).toFixed(1)}s`));\n\t\t}\n\t\treturn parts.join(label(\" · \"));\n\t}\n\n\tprivate border(label: string, width: number, top: boolean, theme: Theme): string {\n\t\tconst text = label ? ` ${truncateToWidth(label, Math.max(0, width - 4))} ` : \"\";\n\t\treturn (\n\t\t\ttheme.fg(\"borderAccent\", top ? \"╭\" : \"╰\") +\n\t\t\ttext +\n\t\t\ttheme.fg(\"borderAccent\", `${\"─\".repeat(Math.max(0, width - visibleWidth(text) - 2))}${top ? \"╮\" : \"╯\"}`)\n\t\t);\n\t}\n}\n"]}
1
+ {"version":3,"file":"panel.js","sourceRoot":"","sources":["../../../src/extensions/btw/panel.ts"],"names":[],"mappings":"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","sourcesContent":["import \"./keybindings.ts\";\nimport {\n\ttype Component,\n\tMarkdown,\n\tText,\n\ttype TUI,\n\ttruncateToWidth,\n\tvisibleWidth,\n\twrapTextWithAnsi,\n} from \"@earendil-works/pi-tui\";\nimport { keyLabel } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { getMarkdownTheme, type Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport type { BtwConversationState, BtwTurn } from \"./agent.ts\";\n\nexport type BtwPanelState<Conversation extends BtwConversationState = Readonly<BtwConversationState>> =\n\t| { phase: \"opening\" }\n\t| { phase: \"error\"; error: string }\n\t| {\n\t\t\tphase: \"ready\";\n\t\t\tcapturedAt: number;\n\t\t\tmodel: string;\n\t\t\tusesSubscription: boolean;\n\t\t\tconversation: Conversation;\n\t };\n\nfunction tokens(value: number): string {\n\tif (value < 1000) return String(value);\n\tif (value < 10_000) return `${(value / 1000).toFixed(1)}k`;\n\tif (value < 1_000_000) return `${Math.round(value / 1000)}k`;\n\tif (value < 10_000_000) return `${(value / 1_000_000).toFixed(1)}M`;\n\treturn `${Math.round(value / 1_000_000)}M`;\n}\n\n/** A bounded, scrollable widget above the normal editor. It never takes keyboard focus. */\nexport class BtwPanel implements Component {\n\tprivate readonly tui: Pick<TUI, \"terminal\" | \"requestRender\">;\n\tprivate readonly getTheme: () => Theme;\n\tprivate readonly getState: () => BtwPanelState;\n\tprivate readonly answers = new Map<BtwTurn, { text: string; markdown: Markdown }>();\n\tprivate follow = true;\n\tprivate offset = 0;\n\tprivate maxOffset = 0;\n\tprivate heldHeight = 0;\n\tprivate timer?: ReturnType<typeof setTimeout>;\n\tprivate disposed = false;\n\n\tconstructor(tui: Pick<TUI, \"terminal\" | \"requestRender\">, getTheme: () => Theme, getState: () => BtwPanelState) {\n\t\tthis.tui = tui;\n\t\tthis.getTheme = getTheme;\n\t\tthis.getState = getState;\n\t}\n\n\tinvalidate(): void {\n\t\tthis.answers.clear();\n\t}\n\n\tchanged(): void {\n\t\tif (this.disposed) return;\n\t\tthis.tui.requestRender();\n\t\tconst state = this.getState();\n\t\tconst busy = state.phase === \"ready\" && state.conversation.busy;\n\t\tif (busy && !this.timer) {\n\t\t\tthis.timer = setTimeout(() => {\n\t\t\t\tthis.timer = undefined;\n\t\t\t\tthis.changed();\n\t\t\t}, 150);\n\t\t\tthis.timer.unref?.();\n\t\t} else if (!busy && this.timer) {\n\t\t\tclearTimeout(this.timer);\n\t\t\tthis.timer = undefined;\n\t\t}\n\t}\n\n\tfollowTail(): void {\n\t\tthis.follow = true;\n\t\tthis.changed();\n\t}\n\n\tscroll(delta: number): boolean {\n\t\tif (this.maxOffset === 0) return false;\n\t\tthis.offset = Math.max(0, Math.min(this.maxOffset, this.offset + delta));\n\t\tthis.follow = this.offset === this.maxOffset;\n\t\tthis.tui.requestRender();\n\t\treturn true;\n\t}\n\n\tdispose(): void {\n\t\tthis.disposed = true;\n\t\tif (this.timer) clearTimeout(this.timer);\n\t\tthis.timer = undefined;\n\t\tthis.answers.clear();\n\t}\n\n\trender(width: number): string[] {\n\t\tif (this.disposed || width < 1) return [];\n\t\tconst state = this.getState();\n\t\tconst busy = state.phase === \"ready\" && state.conversation.busy;\n\t\tconst theme = this.getTheme();\n\t\tconst innerWidth = Math.max(1, width - 4);\n\t\tconst lines = this.body(state, innerWidth, theme);\n\t\tconst cap = Math.max(1, Math.floor(this.tui.terminal.rows / 3) - 2);\n\t\tconst needed = Math.min(cap, Math.max(1, lines.length));\n\t\tthis.heldHeight = busy ? Math.min(cap, Math.max(this.heldHeight, needed)) : needed;\n\t\tthis.maxOffset = Math.max(0, lines.length - this.heldHeight);\n\t\tthis.offset = this.follow ? this.maxOffset : Math.min(this.offset, this.maxOffset);\n\t\tconst body = lines.slice(this.offset, this.offset + this.heldHeight);\n\t\twhile (body.length < this.heldHeight) body.push(\"\");\n\t\tconst close = keyLabel(\"app.btw.close\");\n\t\tconst cancel = keyLabel(\"app.btw.cancel\");\n\t\tconst title = [\n\t\t\ttheme.fg(\"accent\", theme.bold(\"BTW\")),\n\t\t\tclose && theme.fg(\"text\", close) + theme.fg(\"muted\", \" close\"),\n\t\t\tbusy && cancel && theme.fg(\"text\", cancel) + theme.fg(\"muted\", \" stop\"),\n\t\t]\n\t\t\t.filter(Boolean)\n\t\t\t.join(theme.fg(\"muted\", \" · \"));\n\t\tconst footer = this.footer(state, theme);\n\t\tif (width < 6) return body.map((line) => truncateToWidth(line, width));\n\t\treturn [\n\t\t\tthis.border(title, width, true, theme),\n\t\t\t...body.map(\n\t\t\t\t(line) =>\n\t\t\t\t\ttheme.fg(\"borderAccent\", \"│ \") +\n\t\t\t\t\ttruncateToWidth(line, innerWidth, \"…\", true) +\n\t\t\t\t\ttheme.fg(\"borderAccent\", \" │\"),\n\t\t\t),\n\t\t\tthis.border(footer, width, false, theme),\n\t\t];\n\t}\n\n\tprivate body(state: BtwPanelState, width: number, theme: Theme): string[] {\n\t\tif (state.phase === \"opening\") return [theme.fg(\"muted\", \"Capturing context…\")];\n\t\tif (state.phase === \"error\") return new Text(theme.fg(\"error\", state.error), 0, 0).render(width);\n\t\tif (!state.conversation.turns.length) {\n\t\t\treturn [\n\t\t\t\t...new Text(theme.fg(\"text\", \"Ask a side question in the editor below.\"), 0, 0).render(width),\n\t\t\t\t...new Text(\n\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\"muted\",\n\t\t\t\t\t\t`Context at ${new Date(state.capturedAt).toTimeString().slice(0, 8)} · ${state.model}`,\n\t\t\t\t\t),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t).render(width),\n\t\t\t];\n\t\t}\n\t\tconst lines: string[] = [];\n\t\tfor (const [index, turn] of state.conversation.turns.entries()) {\n\t\t\tif (index > 0) lines.push(\"\");\n\t\t\tlines.push(\n\t\t\t\t...new Text(\n\t\t\t\t\ttheme.fg(\"accent\", theme.bold(`Q${index + 1}: `)) + theme.fg(\"text\", turn.question),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t).render(width),\n\t\t\t);\n\t\t\tif (turn.answer) {\n\t\t\t\tlet answer = this.answers.get(turn);\n\t\t\t\tif (!answer) {\n\t\t\t\t\tanswer = {\n\t\t\t\t\t\ttext: turn.answer,\n\t\t\t\t\t\tmarkdown: new Markdown(turn.answer, 0, 0, getMarkdownTheme(), {\n\t\t\t\t\t\t\tcolor: (text) => theme.fg(\"text\", text),\n\t\t\t\t\t\t}),\n\t\t\t\t\t};\n\t\t\t\t\tthis.answers.set(turn, answer);\n\t\t\t\t} else if (answer.text !== turn.answer) {\n\t\t\t\t\tanswer.text = turn.answer;\n\t\t\t\t\tanswer.markdown.setText(turn.answer);\n\t\t\t\t}\n\t\t\t\tlines.push(...answer.markdown.render(width));\n\t\t\t} else if (turn.thinking && (turn.status === \"streaming\" || turn.status === \"cancelling\")) {\n\t\t\t\tlines.push(...wrapTextWithAnsi(theme.fg(\"muted\", turn.thinking.trimEnd()), width).slice(-2));\n\t\t\t}\n\t\t\tif (turn.status === \"streaming\" || turn.status === \"cancelling\") {\n\t\t\t\tconst elapsed = ((Date.now() - turn.startedAt) / 1000).toFixed(1);\n\t\t\t\tlines.push(theme.fg(\"muted\", `${turn.status === \"cancelling\" ? \"Stopping\" : \"Answering\"}… ${elapsed}s`));\n\t\t\t}\n\t\t\tif (turn.notice)\n\t\t\t\tlines.push(\n\t\t\t\t\t...new Text(theme.fg(turn.status === \"error\" ? \"error\" : \"muted\", turn.notice), 0, 0).render(width),\n\t\t\t\t);\n\t\t}\n\t\treturn lines;\n\t}\n\n\tprivate footer(state: BtwPanelState, theme: Theme): string {\n\t\tconst parts: string[] = [];\n\t\tconst label = (text: string) => theme.fg(\"muted\", text);\n\t\tconst value = (text: string) => theme.fg(\"text\", text);\n\t\tif (this.maxOffset > 0) {\n\t\t\tconst keys = [keyLabel(\"app.btw.scrollUp\"), keyLabel(\"app.btw.scrollDown\")].filter(Boolean).join(\"/\");\n\t\t\tparts.push(\n\t\t\t\tvalue(keys) +\n\t\t\t\t\tlabel(\" scroll \") +\n\t\t\t\t\tvalue(`${this.offset + 1}–${this.offset + this.heldHeight}/${this.maxOffset + this.heldHeight}`),\n\t\t\t);\n\t\t}\n\t\tif (state.phase === \"ready\") {\n\t\t\tconst { conversation } = state;\n\t\t\tconst { usage } = conversation;\n\t\t\tconst stats: string[] = [];\n\t\t\tif (usage.input > 0) stats.push(`↑${tokens(usage.input)}`);\n\t\t\tif (usage.output > 0) stats.push(`↓${tokens(usage.output)}`);\n\t\t\tif (usage.cacheRead > 0) stats.push(`R${tokens(usage.cacheRead)}`);\n\t\t\tif (usage.cacheWrite > 0) stats.push(`W${tokens(usage.cacheWrite)}`);\n\t\t\tif (conversation.latestCacheHitPercent !== undefined)\n\t\t\t\tstats.push(`CH${conversation.latestCacheHitPercent.toFixed(1)}%`);\n\t\t\tif (usage.cost.total > 0)\n\t\t\t\tstats.push(`$${usage.cost.total.toFixed(3)}${state.usesSubscription ? \" (sub)\" : \"\"}`);\n\t\t\tif (stats.length) parts.push(value(stats.join(\" \")));\n\t\t\tif (conversation.blockedTools) parts.push(value(String(conversation.blockedTools)) + label(\" tools blocked\"));\n\t\t\tconst turn = conversation.turns.at(-1);\n\t\t\tif (turn && !conversation.busy) {\n\t\t\t\tparts.push(value(`${(turn.elapsedMs / 1000).toFixed(1)}s`));\n\t\t\t\tif (turn.firstAnswerMs !== undefined)\n\t\t\t\t\tparts.push(label(\"first \") + value(`${(turn.firstAnswerMs / 1000).toFixed(1)}s`));\n\t\t\t}\n\t\t}\n\t\treturn parts.join(label(\" · \"));\n\t}\n\n\tprivate border(label: string, width: number, top: boolean, theme: Theme): string {\n\t\tconst text = label ? ` ${truncateToWidth(label, Math.max(0, width - 4))} ` : \"\";\n\t\treturn (\n\t\t\ttheme.fg(\"borderAccent\", top ? \"╭\" : \"╰\") +\n\t\t\ttext +\n\t\t\ttheme.fg(\"borderAccent\", `${\"─\".repeat(Math.max(0, width - visibleWidth(text) - 2))}${top ? \"╮\" : \"╯\"}`)\n\t\t);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/extensions/codemode/execute.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAmC,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAYtG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,EAKN,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAIxB,MAAM,WAAW,CAAC;AA+EnB,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAU1F;AAsFD;;;GAGG;AACH,wBAAsB,eAAe,CACpC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,EAC9E,GAAG,EAAE,oBAAoB,GAAG,SAAS,EACrC,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC,CAgG/C"}
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/extensions/codemode/execute.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAmC,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAqBtG,OAAO,KAAK,EAAE,oBAAoB,EAAiB,MAAM,gCAAgC,CAAC;AAC1F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,EAMN,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAGxB,MAAM,WAAW,CAAC;AA6KnB,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAU1F;AAsFD;;;GAGG;AACH,wBAAsB,eAAe,CACpC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,EAC9E,GAAG,EAAE,oBAAoB,GAAG,SAAS,EACrC,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC,CA2G/C"}
@@ -7,13 +7,13 @@ import { writeFile } from "node:fs/promises";
7
7
  import { tmpdir } from "node:os";
8
8
  import { join } from "node:path";
9
9
  import { CodemodeSandbox, loadQuickJSWasm, parseCodemodeSource, renderToolSample, toCodemodeIdentifier, } from "@earendil-works/pi-codemode";
10
- import { getCodemodeWorkerUrl, getQuickJSWasmPath } from "../../config.js";
10
+ import { getCodemodeWorkerSpecifier, getQuickJSWasmPath } from "../../config.js";
11
11
  import { combineUsage } from "../../core/usage-totals.js";
12
12
  import { Bm25Ranker, createToolSearchDocument, DEFAULT_TOOL_SEARCH_LIMIT } from "./search.js";
13
- import { CODEMODE_STORE_ENTRY_TYPE, getCodemodeCallableTools, MODEL_GLOBAL_DECLARATIONS, toCodemodeDeclaration, } from "./tool.js";
13
+ import { CODEMODE_DOCS_PATH, CODEMODE_STORE_ENTRY_TYPE, getCodemodeCallableTools, toCodemodeDeclaration, } from "./tool.js";
14
14
  const ARGS_PREVIEW_CHARS = 200;
15
15
  const ERROR_PREVIEW_CHARS = 500;
16
- /** Classifier calls one script may have in flight; `Promise.all` over many items queues the rest. */
16
+ /** `models.classify()` and `models.generateImages()` calls one script may have in flight; `Promise.all` over many items queues the rest. */
17
17
  const MAX_CONCURRENT_MODEL_CALLS = 4;
18
18
  /**
19
19
  * Heap limit for the QuickJS VM. The worker shares pi's process, so without a limit a runaway
@@ -59,6 +59,90 @@ function toModelInfo(model) {
59
59
  delete info.headers;
60
60
  return info;
61
61
  }
62
+ /** `an image`, `a classifier`. */
63
+ function withArticle(word) {
64
+ return `${/^[aeiou]/.test(word) ? "an" : "a"} ${word}`;
65
+ }
66
+ function isRecord(value) {
67
+ return typeof value === "object" && value !== null && !Array.isArray(value);
68
+ }
69
+ /** A script value in an error message: `undefined`, `a string`, `an array`, or its keys (`{ prompt }`). */
70
+ function describeValue(value) {
71
+ if (value === undefined || value === null)
72
+ return String(value);
73
+ if (Array.isArray(value))
74
+ return value.length === 0 ? "an empty array" : "an array";
75
+ if (typeof value === "object") {
76
+ const keys = Object.keys(value);
77
+ if (keys.length === 0)
78
+ return "{}";
79
+ return `{ ${keys.slice(0, 6).join(", ")}${keys.length > 6 ? ", ..." : ""} }`;
80
+ }
81
+ return typeof value === "string" ? "a string" : `a ${typeof value}`;
82
+ }
83
+ const CLASSIFIER_CONTEXT_SHAPE = '{ state: { ... }, questions: { <id>: { type: "choice", instructions, criteria: { <label>: <meaning> } } | { type: "score", instructions, criteria: [<lowest level>, ..., <highest level>] } | { type: "bool", instructions, criteria: { true: <meaning>, false: <meaning> } } } }';
84
+ /** Check a script's classifier context, so mistakes fail with the expected shape instead of a provider error. */
85
+ function checkClassifierContext(context) {
86
+ const fail = (problem) => new Error(`models.classify() ${problem}. Expected context: ${CLASSIFIER_CONTEXT_SHAPE}. See "Classify" in ${CODEMODE_DOCS_PATH}.`);
87
+ if (!isRecord(context))
88
+ throw fail(`expects a context object as its second argument, got ${describeValue(context)}`);
89
+ if (!isRecord(context.state))
90
+ throw fail(`context.state must be an object, got ${describeValue(context.state)}`);
91
+ const { questions } = context;
92
+ if (!isRecord(questions) || Object.keys(questions).length === 0) {
93
+ throw fail(`context.questions must map question IDs to questions, got ${describeValue(questions)}`);
94
+ }
95
+ const isStrings = (values) => values.length > 0 && values.every((value) => typeof value === "string");
96
+ for (const [id, question] of Object.entries(questions)) {
97
+ const at = `context.questions.${id}`;
98
+ if (!isRecord(question))
99
+ throw fail(`${at} must be a question object, got ${describeValue(question)}`);
100
+ if (typeof question.instructions !== "string")
101
+ throw fail(`${at}.instructions must be a string`);
102
+ const { criteria } = question;
103
+ if (question.type === "choice") {
104
+ if (!isRecord(criteria) || !isStrings(Object.values(criteria))) {
105
+ throw fail(`${at} is a "choice" question, so criteria must map each label to its meaning`);
106
+ }
107
+ }
108
+ else if (question.type === "score") {
109
+ if (!Array.isArray(criteria) || !isStrings(criteria)) {
110
+ throw fail(`${at} is a "score" question, so criteria must list the levels as strings, lowest first`);
111
+ }
112
+ }
113
+ else if (question.type === "bool") {
114
+ if (!isRecord(criteria) || typeof criteria.true !== "string" || typeof criteria.false !== "string") {
115
+ throw fail(`${at} is a "bool" question, so criteria must be { true: string, false: string }`);
116
+ }
117
+ }
118
+ else {
119
+ throw fail(`${at}.type must be "choice", "score", or "bool", got ${JSON.stringify(question.type)}`);
120
+ }
121
+ }
122
+ return context;
123
+ }
124
+ /** Check a script's image context, so mistakes such as `{ prompt }` fail with the expected shape. */
125
+ function checkImagesContext(context) {
126
+ const fail = (problem) => new Error(`models.generateImages() ${problem}. Expected context: { input: [{ type: "text", text: <prompt> }, ...optional { type: "image", data: <base64>, mimeType } references] }. See "Generate images" in ${CODEMODE_DOCS_PATH}.`);
127
+ if (!isRecord(context))
128
+ throw fail(`expects a context object as its second argument, got ${describeValue(context)}`);
129
+ const { input } = context;
130
+ if (!Array.isArray(input) || input.length === 0) {
131
+ throw fail(`context.input must be a non-empty array of blocks, got ${describeValue(input)}`);
132
+ }
133
+ input.forEach((block, index) => {
134
+ if (isRecord(block) && block.type === "text" && typeof block.text === "string")
135
+ return;
136
+ if (isRecord(block) &&
137
+ block.type === "image" &&
138
+ typeof block.data === "string" &&
139
+ typeof block.mimeType === "string") {
140
+ return;
141
+ }
142
+ throw fail(`context.input[${index}] must be a text or image block, got ${describeValue(block)}`);
143
+ });
144
+ return context;
145
+ }
62
146
  /** Runs at most `limit` calls at once, in call order. */
63
147
  function createLimiter(limit) {
64
148
  let active = 0;
@@ -188,6 +272,11 @@ export async function executeCodemode(toolCallId, input, signal, onUpdate, ctx,
188
272
  const calls = [];
189
273
  // Usage of the script's `models.*` calls. Nested tool calls report theirs through the session.
190
274
  let modelUsage;
275
+ // Images returned by `models.generateImages()`, to notice a script that never shows them.
276
+ let generatedImages = 0;
277
+ const addGeneratedImages = (count) => {
278
+ generatedImages += count;
279
+ };
191
280
  const addModelUsage = (usage) => {
192
281
  modelUsage = modelUsage ? combineUsage(modelUsage, usage) : usage;
193
282
  };
@@ -231,13 +320,13 @@ export async function executeCodemode(toolCallId, input, signal, onUpdate, ctx,
231
320
  globals: [
232
321
  ...createDiscoveryGlobals(callable, samples, options),
233
322
  ...(options.models && ctx
234
- ? createModelGlobals(ctx.modelRegistry, toolCallId, calls, publish, addModelUsage)
323
+ ? createModelGlobals(ctx.modelRegistry, toolCallId, calls, publish, addModelUsage, addGeneratedImages)
235
324
  : []),
236
325
  ],
237
326
  timeoutMs: sourceOptions.timeoutMs ?? Number.POSITIVE_INFINITY,
238
327
  memoryLimitBytes: CODEMODE_MEMORY_LIMIT_BYTES,
239
328
  wasm: loadQuickJSWasm(getQuickJSWasmPath()),
240
- workerUrl: getCodemodeWorkerUrl(),
329
+ workerUrl: getCodemodeWorkerSpecifier(),
241
330
  });
242
331
  let result;
243
332
  try {
@@ -265,6 +354,12 @@ export async function executeCodemode(toolCallId, input, signal, onUpdate, ctx,
265
354
  else {
266
355
  items.push({ type: "text", text: `Script error:\n${formatError(result, calls)}` });
267
356
  }
357
+ if (generatedImages > 0 && !items.some((item) => item.type === "image")) {
358
+ items.push({
359
+ type: "text",
360
+ text: `Note: models.generateImages() returned ${generatedImages} image${generatedImages === 1 ? "" : "s"} that the script did not show. Show each image block of result.output with image(block).`,
361
+ });
362
+ }
268
363
  const truncated = await truncateOutput(items, sourceOptions.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS);
269
364
  const wallTime = ((performance.now() - startedAt) / 1000).toFixed(1);
270
365
  const header = `${result.ok ? "Script completed" : "Script failed"}\nWall time ${wallTime} seconds\nOutput:\n`;
@@ -278,7 +373,20 @@ export async function executeCodemode(toolCallId, input, signal, onUpdate, ctx,
278
373
  ...(result.ok ? {} : { isError: true }),
279
374
  };
280
375
  }
281
- /** `searchTools()` and `describeTool()`: ranked search and lookup over the script's nested tools. */
376
+ /**
377
+ * Whether `query` names the namespace: its name, its script identifier (`mcp__dev-radius` is
378
+ * `mcp__dev_radius`), or the part after its last `__` in either form (`dev-radius`, `dev_radius`).
379
+ */
380
+ function isNamespaceName(namespace, query) {
381
+ const id = toCodemodeIdentifier(namespace);
382
+ const queryId = toCodemodeIdentifier(query);
383
+ const suffix = (name) => (name.includes("__") ? name.slice(name.lastIndexOf("__") + 2) : undefined);
384
+ return namespace === query || id === queryId || suffix(namespace) === query || suffix(id) === queryId;
385
+ }
386
+ /**
387
+ * `searchTools()`, `describeTool()`, and `describeNamespace()`: ranked search and lookup over the
388
+ * script's nested tools and their namespaces.
389
+ */
282
390
  function createDiscoveryGlobals(tools, samples, options) {
283
391
  const ranker = new Bm25Ranker();
284
392
  const entry = (name) => ({ name: toCodemodeIdentifier(name), description: samples.get(name) ?? "" });
@@ -300,7 +408,7 @@ function createDiscoveryGlobals(tools, samples, options) {
300
408
  }
301
409
  const documents = tools.flatMap((tool) => {
302
410
  const toolNamespace = options.getToolNamespace?.(tool.name);
303
- if (namespace && toolNamespace?.name !== namespace)
411
+ if (namespace && (!toolNamespace || !isNamespaceName(toolNamespace.name, namespace)))
304
412
  return [];
305
413
  return [createToolSearchDocument(tool, toolNamespace)];
306
414
  });
@@ -318,16 +426,86 @@ function createDiscoveryGlobals(tools, samples, options) {
318
426
  return tool ? samples.get(tool.name) : undefined;
319
427
  },
320
428
  },
429
+ {
430
+ name: "describeNamespace",
431
+ spread: true,
432
+ execute: (args) => {
433
+ const [name] = args;
434
+ if (typeof name !== "string")
435
+ throw new Error("describeNamespace() expects a namespace name");
436
+ let namespace;
437
+ const names = [];
438
+ for (const tool of tools) {
439
+ const toolNamespace = options.getToolNamespace?.(tool.name);
440
+ if (!toolNamespace || !isNamespaceName(toolNamespace.name, name))
441
+ continue;
442
+ namespace ??= toolNamespace;
443
+ names.push(toCodemodeIdentifier(tool.name));
444
+ }
445
+ if (!namespace)
446
+ return undefined;
447
+ return {
448
+ name: namespace.name,
449
+ ...(namespace.description ? { description: namespace.description } : {}),
450
+ ...(namespace.instructions ? { instructions: namespace.instructions } : {}),
451
+ tools: names,
452
+ };
453
+ },
454
+ },
321
455
  ];
322
456
  }
323
457
  /**
324
- * `models.*` for scripts: the model registry methods declared in {@link MODEL_GLOBAL_DECLARATIONS}.
325
- * Classifier calls appear as nested call rows so the renderer shows them, and their usage goes to
326
- * `addUsage`.
458
+ * `models.*` for scripts: the model registry methods documented in docs/codemode.md.
459
+ * Classifier and image calls appear as nested call rows so the renderer shows them, and their usage
460
+ * goes to `addUsage`. Rows show only the model, never prompts or image data.
327
461
  */
328
- function createModelGlobals(models, toolCallId, calls, publish, addUsage) {
462
+ function createModelGlobals(models, toolCallId, calls, publish, addUsage, addGeneratedImages) {
329
463
  const limit = createLimiter(MAX_CONCURRENT_MODEL_CALLS);
330
- let classifyCount = 0;
464
+ let callCount = 0;
465
+ /**
466
+ * Resolve the script's model by provider and id only, check the context, then run the call as a
467
+ * nested call row. A script-supplied baseUrl or headers must never receive the credentials.
468
+ */
469
+ const runModelCall = async (name, type, [model, context], checkContext, run) => {
470
+ const listHint = `List the ${type} models you can use with models.getAvailableOfType("${type}").`;
471
+ if (!isRecord(model) || typeof model.provider !== "string" || typeof model.id !== "string") {
472
+ // undefined arrives as null: spread arguments cross the sandbox as a JSON array.
473
+ const undefinedHint = model === undefined || model === null
474
+ ? " models.getModelOfType() returns undefined for an unknown provider or id."
475
+ : "";
476
+ throw new Error(`${name}() expects ${withArticle(type)} model as its first argument, got ${describeValue(model)}.${undefinedHint} ${listHint}`);
477
+ }
478
+ const { provider, id } = model;
479
+ const ref = `${provider}/${id}`;
480
+ const resolved = models.getModelOfType(type, provider, id);
481
+ if (!resolved) {
482
+ const actualType = [...MODEL_TYPES].find((other) => other !== type && models.getModelOfType(other, provider, id) !== undefined);
483
+ throw new Error(actualType
484
+ ? `"${ref}" is ${withArticle(actualType)} model, not ${withArticle(type)} model. ${listHint}`
485
+ : `Unknown ${type} model "${ref}". ${listHint}`);
486
+ }
487
+ const checked = checkContext(context);
488
+ const record = {
489
+ id: `${toolCallId}/${name}/${++callCount}`,
490
+ name,
491
+ args: `${resolved.provider}/${resolved.id}`,
492
+ status: "running",
493
+ };
494
+ calls.push(record);
495
+ publish();
496
+ const startedAt = performance.now();
497
+ const result = await limit(() => run(resolved, checked));
498
+ record.durationMs = performance.now() - startedAt;
499
+ record.status = result.stopReason === "stop" ? "ok" : result.stopReason === "aborted" ? "cancelled" : "error";
500
+ if (result.errorMessage)
501
+ record.error = truncateText(result.errorMessage, ERROR_PREVIEW_CHARS);
502
+ if (result.usage) {
503
+ record.cost = result.usage.cost.total;
504
+ addUsage(result.usage);
505
+ }
506
+ publish();
507
+ return result;
508
+ };
331
509
  const implementations = {
332
510
  "models.getModelsOfType": (args) => {
333
511
  const [type, provider] = args;
@@ -341,50 +519,18 @@ function createModelGlobals(models, toolCallId, calls, publish, addUsage) {
341
519
  "models.getModelOfType": (args) => {
342
520
  const [type, provider, id] = args;
343
521
  if (typeof provider !== "string" || typeof id !== "string") {
344
- throw new Error("models.getModelOfType() expects a type, a provider, and an id");
522
+ throw new Error(`models.getModelOfType(type, provider, id) expects three strings, got (${args.map(describeValue).join(", ")}). The provider and the id are separate arguments, for example models.getModelOfType("classifier", "typesafe", "jev-latest").`);
345
523
  }
346
524
  const model = models.getModelOfType(toModelType(type), provider, id);
347
525
  return model === undefined ? undefined : toModelInfo(model);
348
526
  },
349
- "models.classify": async (args, { signal }) => {
350
- const [model, context] = args;
351
- const ref = model;
352
- if (typeof ref !== "object" ||
353
- ref === null ||
354
- typeof ref.provider !== "string" ||
355
- typeof ref.id !== "string") {
356
- throw new Error("models.classify() expects a model from models.getModelOfType() or models.getAvailableOfType()");
357
- }
358
- // Only provider and id count. A script-supplied baseUrl or headers must never receive the credentials.
359
- const resolved = models.getModelOfType("classifier", ref.provider, ref.id);
360
- if (!resolved)
361
- throw new Error(`Unknown classifier model "${ref.provider}/${ref.id}"`);
362
- const record = {
363
- id: `${toolCallId}/models.classify/${++classifyCount}`,
364
- name: "models.classify",
365
- args: `${resolved.provider}/${resolved.id}`,
366
- status: "running",
367
- };
368
- calls.push(record);
369
- publish();
370
- const startedAt = performance.now();
371
- const result = await limit(() => models.classify(resolved, context, { signal }));
372
- record.durationMs = performance.now() - startedAt;
373
- record.status = result.stopReason === "stop" ? "ok" : result.stopReason === "aborted" ? "cancelled" : "error";
374
- if (result.errorMessage)
375
- record.error = truncateText(result.errorMessage, ERROR_PREVIEW_CHARS);
376
- if (result.usage) {
377
- record.cost = result.usage.cost.total;
378
- addUsage(result.usage);
379
- }
380
- publish();
527
+ "models.classify": (args, { signal }) => runModelCall("models.classify", "classifier", args, checkClassifierContext, (resolved, context) => models.classify(resolved, context, { signal })),
528
+ "models.generateImages": (args, { signal }) => runModelCall("models.generateImages", "image", args, checkImagesContext, async (resolved, context) => {
529
+ const result = await models.generateImages(resolved, context, { signal });
530
+ addGeneratedImages(result.output.filter((block) => block.type === "image").length);
381
531
  return result;
382
- },
532
+ }),
383
533
  };
384
- return MODEL_GLOBAL_DECLARATIONS.map((declaration) => ({
385
- name: declaration.name,
386
- spread: true,
387
- execute: implementations[declaration.name],
388
- }));
534
+ return Object.entries(implementations).map(([name, execute]) => ({ name, spread: true, execute }));
389
535
  }
390
536
  //# sourceMappingURL=execute.js.map