@earendil-works/pi-coding-agent 0.84.1 → 0.84.3

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 (328) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +9 -4
  3. package/dist/bundle/chunks/anthropic-messages-JWX2WP65.js +45 -0
  4. package/dist/bundle/chunks/anthropic.js +75 -0
  5. package/dist/bundle/chunks/azure-openai-responses-5ENVCQ7U.js +2 -0
  6. package/dist/bundle/chunks/bedrock-converse-stream.js +74 -0
  7. package/dist/bundle/chunks/chunk-4L3WN2XY.js +2 -0
  8. package/dist/bundle/chunks/chunk-6CYCI3EJ.js +12 -0
  9. package/dist/bundle/chunks/chunk-6R7UI4IY.js +2 -0
  10. package/dist/bundle/chunks/chunk-AXIIZGTV.js +2 -0
  11. package/dist/bundle/chunks/chunk-DRQDKNXA.js +2 -0
  12. package/dist/bundle/chunks/chunk-E5KXRMZK.js +1547 -0
  13. package/dist/bundle/chunks/chunk-GMWCTUPB.js +2 -0
  14. package/dist/bundle/chunks/chunk-GPPBJGBU.js +50 -0
  15. package/dist/bundle/chunks/chunk-JUUC5AZY.js +2 -0
  16. package/dist/bundle/chunks/chunk-L2ZPNLYD.js +2 -0
  17. package/dist/bundle/chunks/chunk-MNAIPA3J.js +2 -0
  18. package/dist/bundle/chunks/chunk-NBBFIJUL.js +11 -0
  19. package/dist/bundle/chunks/chunk-NUHFSC37.js +25 -0
  20. package/dist/bundle/chunks/chunk-PGXDEOVV.js +2 -0
  21. package/dist/bundle/chunks/chunk-PJACZCIR.js +2 -0
  22. package/dist/bundle/chunks/chunk-PRRNXB7S.js +2 -0
  23. package/dist/bundle/chunks/chunk-TEPMHNKQ.js +2 -0
  24. package/dist/bundle/chunks/chunk-TRDNDS6A.js +4 -0
  25. package/dist/bundle/chunks/chunk-UAQELI3K.js +2 -0
  26. package/dist/bundle/chunks/chunk-XDUWOHPL.js +6 -0
  27. package/dist/bundle/chunks/chunk-XNGRGP62.js +2 -0
  28. package/dist/bundle/chunks/dist-RDWOYWHR.js +13 -0
  29. package/dist/bundle/chunks/github-copilot.js +2 -0
  30. package/dist/bundle/chunks/google-generative-ai-XDKMGBCJ.js +2 -0
  31. package/dist/bundle/chunks/google-vertex-D5FGEO3Y.js +2 -0
  32. package/dist/bundle/chunks/image-resize-worker.js +2 -0
  33. package/dist/bundle/chunks/kimi-coding.js +2 -0
  34. package/dist/bundle/chunks/lib-HGQMNYVT.js +9 -0
  35. package/dist/bundle/chunks/mistral-conversations-YK73UAOZ.js +5 -0
  36. package/dist/bundle/chunks/multipart-parser-SQ6GDJL7.js +3 -0
  37. package/dist/bundle/chunks/openai-codex-responses-GJVBJXLB.js +8 -0
  38. package/dist/bundle/chunks/openai-codex.js +75 -0
  39. package/dist/bundle/chunks/openai-completions-JD4WAC3R.js +7 -0
  40. package/dist/bundle/chunks/openai-responses-BSOJMSEV.js +2 -0
  41. package/dist/bundle/chunks/openrouter-images-N4XVVFSD.js +2 -0
  42. package/dist/bundle/chunks/openrouter.js +75 -0
  43. package/dist/bundle/chunks/pi-messages-TPFH44NP.js +8 -0
  44. package/dist/bundle/chunks/radius.js +75 -0
  45. package/dist/bundle/chunks/src-UK77SYZE.js +4 -0
  46. package/dist/bundle/chunks/xai.js +2 -0
  47. package/dist/bundle/cli.js +3 -0
  48. package/dist/bundle/client.js +2 -0
  49. package/dist/bundle/index.js +2 -0
  50. package/dist/bundle/rpc-entry.js +3 -0
  51. package/dist/cli/args.d.ts +2 -0
  52. package/dist/cli/args.d.ts.map +1 -1
  53. package/dist/cli/args.js +40 -9
  54. package/dist/cli/args.js.map +1 -1
  55. package/dist/cli/auth-command.d.ts.map +1 -1
  56. package/dist/cli/auth-command.js +5 -4
  57. package/dist/cli/auth-command.js.map +1 -1
  58. package/dist/cli/file-processor.d.ts.map +1 -1
  59. package/dist/cli/file-processor.js +2 -1
  60. package/dist/cli/file-processor.js.map +1 -1
  61. package/dist/config.d.ts +4 -3
  62. package/dist/config.d.ts.map +1 -1
  63. package/dist/config.js +22 -14
  64. package/dist/config.js.map +1 -1
  65. package/dist/core/agent-session.d.ts +33 -9
  66. package/dist/core/agent-session.d.ts.map +1 -1
  67. package/dist/core/agent-session.js +169 -101
  68. package/dist/core/agent-session.js.map +1 -1
  69. package/dist/core/auth-storage.d.ts.map +1 -1
  70. package/dist/core/auth-storage.js +6 -7
  71. package/dist/core/auth-storage.js.map +1 -1
  72. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  73. package/dist/core/compaction/branch-summarization.js +3 -0
  74. package/dist/core/compaction/branch-summarization.js.map +1 -1
  75. package/dist/core/compaction/compaction.d.ts +4 -3
  76. package/dist/core/compaction/compaction.d.ts.map +1 -1
  77. package/dist/core/compaction/compaction.js +41 -32
  78. package/dist/core/compaction/compaction.js.map +1 -1
  79. package/dist/core/defaults.d.ts +1 -0
  80. package/dist/core/defaults.d.ts.map +1 -1
  81. package/dist/core/defaults.js +9 -0
  82. package/dist/core/defaults.js.map +1 -1
  83. package/dist/core/experimental.d.ts +4 -0
  84. package/dist/core/experimental.d.ts.map +1 -1
  85. package/dist/core/experimental.js +4 -0
  86. package/dist/core/experimental.js.map +1 -1
  87. package/dist/core/extensions/index.d.ts +2 -2
  88. package/dist/core/extensions/index.d.ts.map +1 -1
  89. package/dist/core/extensions/index.js +1 -1
  90. package/dist/core/extensions/index.js.map +1 -1
  91. package/dist/core/extensions/loader.d.ts.map +1 -1
  92. package/dist/core/extensions/loader.js +115 -48
  93. package/dist/core/extensions/loader.js.map +1 -1
  94. package/dist/core/extensions/types.d.ts +42 -9
  95. package/dist/core/extensions/types.d.ts.map +1 -1
  96. package/dist/core/extensions/types.js +3 -0
  97. package/dist/core/extensions/types.js.map +1 -1
  98. package/dist/core/footer-data-provider.d.ts +1 -1
  99. package/dist/core/footer-data-provider.d.ts.map +1 -1
  100. package/dist/core/footer-data-provider.js +1 -1
  101. package/dist/core/footer-data-provider.js.map +1 -1
  102. package/dist/core/keybindings.d.ts +38 -13
  103. package/dist/core/keybindings.d.ts.map +1 -1
  104. package/dist/core/keybindings.js +26 -5
  105. package/dist/core/keybindings.js.map +1 -1
  106. package/dist/core/model-config.d.ts +10 -0
  107. package/dist/core/model-config.d.ts.map +1 -1
  108. package/dist/core/model-config.js +4 -1
  109. package/dist/core/model-config.js.map +1 -1
  110. package/dist/core/model-resolver.d.ts +1 -0
  111. package/dist/core/model-resolver.d.ts.map +1 -1
  112. package/dist/core/model-resolver.js +14 -8
  113. package/dist/core/model-resolver.js.map +1 -1
  114. package/dist/core/models-store.d.ts.map +1 -1
  115. package/dist/core/models-store.js +2 -1
  116. package/dist/core/models-store.js.map +1 -1
  117. package/dist/core/package-manager.d.ts.map +1 -1
  118. package/dist/core/package-manager.js +22 -14
  119. package/dist/core/package-manager.js.map +1 -1
  120. package/dist/core/pi-manifest.d.ts.map +1 -1
  121. package/dist/core/pi-manifest.js +2 -1
  122. package/dist/core/pi-manifest.js.map +1 -1
  123. package/dist/core/project-trust.d.ts.map +1 -1
  124. package/dist/core/project-trust.js +2 -2
  125. package/dist/core/project-trust.js.map +1 -1
  126. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  127. package/dist/core/remote-catalog-provider.js +2 -1
  128. package/dist/core/remote-catalog-provider.js.map +1 -1
  129. package/dist/core/resource-loader.d.ts.map +1 -1
  130. package/dist/core/resource-loader.js +3 -2
  131. package/dist/core/resource-loader.js.map +1 -1
  132. package/dist/core/sdk.d.ts +7 -5
  133. package/dist/core/sdk.d.ts.map +1 -1
  134. package/dist/core/sdk.js +12 -4
  135. package/dist/core/sdk.js.map +1 -1
  136. package/dist/core/session-export.d.ts +4 -0
  137. package/dist/core/session-export.d.ts.map +1 -0
  138. package/dist/core/session-export.js +32 -0
  139. package/dist/core/session-export.js.map +1 -0
  140. package/dist/core/session-manager.d.ts.map +1 -1
  141. package/dist/core/session-manager.js +4 -3
  142. package/dist/core/session-manager.js.map +1 -1
  143. package/dist/core/settings-diagnostics.d.ts +9 -0
  144. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  145. package/dist/core/settings-diagnostics.js +21 -0
  146. package/dist/core/settings-diagnostics.js.map +1 -0
  147. package/dist/core/settings-manager.d.ts +15 -0
  148. package/dist/core/settings-manager.d.ts.map +1 -1
  149. package/dist/core/settings-manager.js +64 -10
  150. package/dist/core/settings-manager.js.map +1 -1
  151. package/dist/core/skills.d.ts.map +1 -1
  152. package/dist/core/skills.js +51 -33
  153. package/dist/core/skills.js.map +1 -1
  154. package/dist/core/slash-commands.d.ts.map +1 -1
  155. package/dist/core/slash-commands.js +2 -1
  156. package/dist/core/slash-commands.js.map +1 -1
  157. package/dist/core/system-prompt.d.ts.map +1 -1
  158. package/dist/core/system-prompt.js +12 -3
  159. package/dist/core/system-prompt.js.map +1 -1
  160. package/dist/core/tools/bash.d.ts +14 -1
  161. package/dist/core/tools/bash.d.ts.map +1 -1
  162. package/dist/core/tools/bash.js +38 -20
  163. package/dist/core/tools/bash.js.map +1 -1
  164. package/dist/core/tools/edit-diff.d.ts +0 -5
  165. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  166. package/dist/core/tools/edit-diff.js +2 -5
  167. package/dist/core/tools/edit-diff.js.map +1 -1
  168. package/dist/core/tools/edit.d.ts.map +1 -1
  169. package/dist/core/tools/edit.js +22 -4
  170. package/dist/core/tools/edit.js.map +1 -1
  171. package/dist/core/tools/find.d.ts.map +1 -1
  172. package/dist/core/tools/find.js +1 -1
  173. package/dist/core/tools/find.js.map +1 -1
  174. package/dist/core/tools/grep.d.ts.map +1 -1
  175. package/dist/core/tools/grep.js +1 -1
  176. package/dist/core/tools/grep.js.map +1 -1
  177. package/dist/core/tools/index.d.ts +4 -1
  178. package/dist/core/tools/index.d.ts.map +1 -1
  179. package/dist/core/tools/index.js +18 -1
  180. package/dist/core/tools/index.js.map +1 -1
  181. package/dist/core/tools/powershell.d.ts +16 -0
  182. package/dist/core/tools/powershell.d.ts.map +1 -0
  183. package/dist/core/tools/powershell.js +39 -0
  184. package/dist/core/tools/powershell.js.map +1 -0
  185. package/dist/core/tools/read.d.ts.map +1 -1
  186. package/dist/core/tools/read.js +2 -0
  187. package/dist/core/tools/read.js.map +1 -1
  188. package/dist/core/tools/write.d.ts.map +1 -1
  189. package/dist/core/tools/write.js +2 -0
  190. package/dist/core/tools/write.js.map +1 -1
  191. package/dist/core/trust-manager.d.ts.map +1 -1
  192. package/dist/core/trust-manager.js +2 -1
  193. package/dist/core/trust-manager.js.map +1 -1
  194. package/dist/extensions/llama/index.d.ts.map +1 -1
  195. package/dist/extensions/llama/index.js +2 -0
  196. package/dist/extensions/llama/index.js.map +1 -1
  197. package/dist/extensions/llama/provider.d.ts.map +1 -1
  198. package/dist/extensions/llama/provider.js +6 -2
  199. package/dist/extensions/llama/provider.js.map +1 -1
  200. package/dist/index.d.ts +6 -6
  201. package/dist/index.d.ts.map +1 -1
  202. package/dist/index.js +4 -4
  203. package/dist/index.js.map +1 -1
  204. package/dist/main.d.ts +4 -0
  205. package/dist/main.d.ts.map +1 -1
  206. package/dist/main.js +23 -16
  207. package/dist/main.js.map +1 -1
  208. package/dist/migrations.d.ts.map +1 -1
  209. package/dist/migrations.js +4 -3
  210. package/dist/migrations.js.map +1 -1
  211. package/dist/modes/interactive/components/model-selector.d.ts +9 -3
  212. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  213. package/dist/modes/interactive/components/model-selector.js +58 -13
  214. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  215. package/dist/modes/interactive/components/settings-selector.d.ts +10 -3
  216. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  217. package/dist/modes/interactive/components/settings-selector.js +128 -56
  218. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  219. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  220. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  221. package/dist/modes/interactive/components/settings-submenu.js +165 -0
  222. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  223. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  224. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  225. package/dist/modes/interactive/components/thinking-selector.js +74 -17
  226. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  227. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  228. package/dist/modes/interactive/components/tool-execution.js +10 -1
  229. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  230. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  231. package/dist/modes/interactive/external-editor.js +2 -1
  232. package/dist/modes/interactive/external-editor.js.map +1 -1
  233. package/dist/modes/interactive/interactive-mode.d.ts +19 -2
  234. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  235. package/dist/modes/interactive/interactive-mode.js +250 -129
  236. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  237. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  238. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  239. package/dist/modes/interactive/model-catalog-refresh.js +34 -0
  240. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  241. package/dist/modes/interactive/session-share.d.ts +16 -0
  242. package/dist/modes/interactive/session-share.d.ts.map +1 -0
  243. package/dist/modes/interactive/session-share.js +188 -0
  244. package/dist/modes/interactive/session-share.js.map +1 -0
  245. package/dist/modes/interactive/theme/dark.json +2 -0
  246. package/dist/modes/interactive/theme/light.json +2 -0
  247. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  248. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  249. package/dist/modes/interactive/theme/theme-controller.js +25 -11
  250. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  251. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  252. package/dist/modes/interactive/theme/theme.d.ts +5 -3
  253. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  254. package/dist/modes/interactive/theme/theme.js +16 -5
  255. package/dist/modes/interactive/theme/theme.js.map +1 -1
  256. package/dist/modes/json-event.d.ts +18 -12
  257. package/dist/modes/json-event.d.ts.map +1 -1
  258. package/dist/modes/json-event.js +22 -5
  259. package/dist/modes/json-event.js.map +1 -1
  260. package/dist/package-manager-cli.d.ts +1 -0
  261. package/dist/package-manager-cli.d.ts.map +1 -1
  262. package/dist/package-manager-cli.js +187 -3
  263. package/dist/package-manager-cli.js.map +1 -1
  264. package/dist/server/create-harness.d.ts.map +1 -1
  265. package/dist/server/create-harness.js +2 -0
  266. package/dist/server/create-harness.js.map +1 -1
  267. package/dist/utils/frontmatter.d.ts.map +1 -1
  268. package/dist/utils/frontmatter.js +2 -1
  269. package/dist/utils/frontmatter.js.map +1 -1
  270. package/dist/utils/management-http.d.ts +5 -3
  271. package/dist/utils/management-http.d.ts.map +1 -1
  272. package/dist/utils/management-http.js +14 -10
  273. package/dist/utils/management-http.js.map +1 -1
  274. package/dist/utils/shell.d.ts +3 -0
  275. package/dist/utils/shell.d.ts.map +1 -1
  276. package/dist/utils/shell.js +17 -5
  277. package/dist/utils/shell.js.map +1 -1
  278. package/dist/utils/syntax-highlight.d.ts +1 -0
  279. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  280. package/dist/utils/syntax-highlight.js +60 -1
  281. package/dist/utils/syntax-highlight.js.map +1 -1
  282. package/dist/utils/text.d.ts +8 -0
  283. package/dist/utils/text.d.ts.map +1 -0
  284. package/dist/utils/text.js +9 -0
  285. package/dist/utils/text.js.map +1 -0
  286. package/dist/utils/tools-manager.d.ts +10 -1
  287. package/dist/utils/tools-manager.d.ts.map +1 -1
  288. package/dist/utils/tools-manager.js +14 -19
  289. package/dist/utils/tools-manager.js.map +1 -1
  290. package/docs/compaction.md +21 -6
  291. package/docs/custom-provider.md +6 -3
  292. package/docs/environment-variables.md +16 -10
  293. package/docs/extensions.md +21 -7
  294. package/docs/json.md +12 -5
  295. package/docs/keybindings.md +15 -9
  296. package/docs/llama-cpp.md +2 -0
  297. package/docs/models.md +8 -2
  298. package/docs/packages.md +2 -2
  299. package/docs/rpc.md +24 -7
  300. package/docs/sdk.md +16 -2
  301. package/docs/settings.md +41 -2
  302. package/docs/skills.md +4 -3
  303. package/docs/terminal-setup.md +34 -11
  304. package/docs/themes.md +24 -3
  305. package/docs/tui.md +2 -2
  306. package/docs/usage.md +9 -4
  307. package/docs/windows.md +24 -2
  308. package/examples/extensions/border-status-editor.ts +1 -1
  309. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  310. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  311. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  312. package/examples/extensions/git-checkpoint.ts +2 -2
  313. package/examples/extensions/gondolin/package-lock.json +2 -2
  314. package/examples/extensions/gondolin/package.json +1 -1
  315. package/examples/extensions/notify.ts +3 -1
  316. package/examples/extensions/sandbox/package-lock.json +2 -2
  317. package/examples/extensions/sandbox/package.json +1 -1
  318. package/examples/extensions/subagent/README.md +3 -1
  319. package/examples/extensions/subagent/agents.ts +40 -9
  320. package/examples/extensions/subagent/index.ts +27 -4
  321. package/examples/extensions/titlebar-spinner.ts +1 -1
  322. package/examples/extensions/with-deps/package-lock.json +2 -2
  323. package/examples/extensions/with-deps/package.json +1 -1
  324. package/examples/rpc-extension-ui.ts +1 -1
  325. package/examples/sdk/06-extensions.ts +1 -1
  326. package/examples/sdk/README.md +1 -1
  327. package/npm-shrinkwrap.json +28 -132
  328. package/package.json +12 -14
@@ -1 +1 @@
1
- {"version":3,"file":"thinking-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/thinking-selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,SAAS,EAAmB,UAAU,EAAgC,MAAM,wBAAwB,CAAC;AAmB9G;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,UAAU,CAAa;IAE/B,YACC,YAAY,EAAE,aAAa,EAC3B,eAAe,EAAE,aAAa,EAAE,EAChC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,EACxC,QAAQ,EAAE,MAAM,IAAI,EAuCpB;IAED,aAAa,IAAI,UAAU,CAE1B;CACD","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { Container, type SelectItem, SelectList, type SelectListLayoutOptions } from \"@earendil-works/pi-tui\";\nimport { getSelectListTheme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\nconst THINKING_SELECT_LIST_LAYOUT: SelectListLayoutOptions = {\n\tminPrimaryColumnWidth: 12,\n\tmaxPrimaryColumnWidth: 32,\n};\n\nconst LEVEL_DESCRIPTIONS: Record<ThinkingLevel, string> = {\n\toff: \"No reasoning\",\n\tminimal: \"Very brief reasoning (~1k tokens)\",\n\tlow: \"Light reasoning (~2k tokens)\",\n\tmedium: \"Moderate reasoning (~8k tokens)\",\n\thigh: \"Deep reasoning (~16k tokens)\",\n\txhigh: \"Extra-high reasoning (~32k tokens)\",\n\tmax: \"Maximum reasoning\",\n};\n\n/**\n * Component that renders a thinking level selector with borders\n */\nexport class ThinkingSelectorComponent extends Container {\n\tprivate selectList: SelectList;\n\n\tconstructor(\n\t\tcurrentLevel: ThinkingLevel,\n\t\tavailableLevels: ThinkingLevel[],\n\t\tonSelect: (level: ThinkingLevel) => void,\n\t\tonCancel: () => void,\n\t) {\n\t\tsuper();\n\n\t\tconst thinkingLevels: SelectItem[] = availableLevels.map((level) => ({\n\t\t\tvalue: level,\n\t\t\tlabel: level,\n\t\t\tdescription: LEVEL_DESCRIPTIONS[level],\n\t\t}));\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Create selector\n\t\tthis.selectList = new SelectList(\n\t\t\tthinkingLevels,\n\t\t\tthinkingLevels.length,\n\t\t\tgetSelectListTheme(),\n\t\t\tTHINKING_SELECT_LIST_LAYOUT,\n\t\t);\n\n\t\t// Preselect current level\n\t\tconst currentIndex = thinkingLevels.findIndex((item) => item.value === currentLevel);\n\t\tif (currentIndex !== -1) {\n\t\t\tthis.selectList.setSelectedIndex(currentIndex);\n\t\t}\n\n\t\tthis.selectList.onSelect = (item) => {\n\t\t\tonSelect(item.value as ThinkingLevel);\n\t\t};\n\n\t\tthis.selectList.onCancel = () => {\n\t\t\tonCancel();\n\t\t};\n\n\t\tthis.addChild(this.selectList);\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\tgetSelectList(): SelectList {\n\t\treturn this.selectList;\n\t}\n}\n"]}
1
+ {"version":3,"file":"thinking-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/thinking-selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EACN,SAAS,EACT,KAAK,SAAS,EAMd,UAAU,EAIV,MAAM,wBAAwB,CAAC;AAoBhC;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAU,YAAW,SAAS;IAC5E,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,iBAAiB,CAAC,CAAiC;IAC3D,OAAO,CAAC,QAAQ,CAAS;IAEzB,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAED,YACC,YAAY,EAAE,aAAa,EAC3B,eAAe,EAAE,aAAa,EAAE,EAChC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,EACxC,QAAQ,EAAE,MAAM,IAAI,EACpB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,EAClD,oBAAoB,CAAC,EAAE,aAAa,EAoCpC;IAED,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,WAAW;IAUnB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAoBjC;IAED,aAAa,IAAI,UAAU,CAE1B;CACD","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tInput,\n\tmatchesKey,\n\ttype SelectItem,\n\tSelectList,\n\ttype SelectListLayoutOptions,\n\tSpacer,\n\tText,\n} from \"@earendil-works/pi-tui\";\nimport { getSelectListTheme, theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyDisplayText } from \"./keybinding-hints.ts\";\n\nconst THINKING_SELECT_LIST_LAYOUT: SelectListLayoutOptions = {\n\tminPrimaryColumnWidth: 12,\n\tmaxPrimaryColumnWidth: 32,\n};\n\nconst LEVEL_DESCRIPTIONS: Record<ThinkingLevel, string> = {\n\toff: \"No reasoning\",\n\tminimal: \"Very brief reasoning (~1k tokens)\",\n\tlow: \"Light reasoning (~2k tokens)\",\n\tmedium: \"Moderate reasoning (~8k tokens)\",\n\thigh: \"Deep reasoning (~16k tokens)\",\n\txhigh: \"Extra-high reasoning (~32k tokens)\",\n\tmax: \"Maximum reasoning\",\n};\n\n/**\n * Component that renders a thinking level selector with borders\n */\nexport class ThinkingSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\tprivate selectList: SelectList;\n\tprivate selectListChildIndex: number;\n\tprivate allItems: SelectItem[];\n\tprivate onSelect: (level: ThinkingLevel) => void;\n\tprivate onCancel: () => void;\n\tprivate onSelectAsDefault?: (level: ThinkingLevel) => void;\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tconstructor(\n\t\tcurrentLevel: ThinkingLevel,\n\t\tavailableLevels: ThinkingLevel[],\n\t\tonSelect: (level: ThinkingLevel) => void,\n\t\tonCancel: () => void,\n\t\tonSelectAsDefault?: (level: ThinkingLevel) => void,\n\t\tdefaultThinkingLevel?: ThinkingLevel,\n\t) {\n\t\tsuper();\n\t\tthis.onSelect = onSelect;\n\t\tthis.onCancel = onCancel;\n\t\tthis.onSelectAsDefault = onSelectAsDefault;\n\n\t\tthis.allItems = availableLevels.map((level) => ({\n\t\t\tvalue: level,\n\t\t\tlabel: level,\n\t\t\tdescription:\n\t\t\t\tlevel === defaultThinkingLevel ? `${LEVEL_DESCRIPTIONS[level]} · default` : LEVEL_DESCRIPTIONS[level],\n\t\t}));\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(\"Thinking Level\", 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(`${keyDisplayText(\"app.thinking.cycle\")} cycles thinking levels in-session`, 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.searchInput = new Input();\n\t\tthis.searchInput.onSubmit = () => this.selectList.handleInput(\"\\r\");\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create selector\n\t\tthis.selectList = this.buildSelectList(this.allItems, currentLevel);\n\t\tthis.selectListChildIndex = this.children.length;\n\t\tthis.addChild(this.selectList);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.fg(\"dim\", \" Enter to select · Ctrl+S to set as default · Esc to cancel\"), 0, 0));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\tprivate buildSelectList(items: SelectItem[], preselect?: ThinkingLevel): SelectList {\n\t\tconst list = new SelectList(items, Math.max(1, items.length), getSelectListTheme(), THINKING_SELECT_LIST_LAYOUT);\n\t\tconst currentIndex = items.findIndex((item) => item.value === preselect);\n\t\tif (currentIndex !== -1) {\n\t\t\tlist.setSelectedIndex(currentIndex);\n\t\t}\n\t\tlist.onSelect = (item) => this.onSelect(item.value as ThinkingLevel);\n\t\tlist.onCancel = () => this.onCancel();\n\t\treturn list;\n\t}\n\n\tprivate applyFilter(query: string): void {\n\t\tconst filtered = query\n\t\t\t? fuzzyFilter(this.allItems, query, (item) => `${item.label} ${item.description ?? \"\"}`)\n\t\t\t: this.allItems;\n\t\tconst selectedValue = this.selectList.getSelectedItem()?.value as ThinkingLevel | undefined;\n\t\tconst newList = this.buildSelectList(filtered, selectedValue);\n\t\tthis.children[this.selectListChildIndex] = newList;\n\t\tthis.selectList = newList;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tif (matchesKey(keyData, \"ctrl+s\") && this.onSelectAsDefault) {\n\t\t\tconst item = this.selectList.getSelectedItem();\n\t\t\tif (item) this.onSelectAsDefault(item.value as ThinkingLevel);\n\t\t\treturn;\n\t\t}\n\n\t\tconst kb = getKeybindings();\n\t\tconst isNav =\n\t\t\tkb.matches(keyData, \"tui.select.up\") ||\n\t\t\tkb.matches(keyData, \"tui.select.down\") ||\n\t\t\tkb.matches(keyData, \"tui.select.confirm\") ||\n\t\t\tkb.matches(keyData, \"tui.select.cancel\");\n\t\tif (isNav) {\n\t\t\tthis.selectList.handleInput(keyData);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.searchInput.handleInput(keyData);\n\t\tthis.applyFilter(this.searchInput.getValue());\n\t}\n\n\tgetSelectList(): SelectList {\n\t\treturn this.selectList;\n\t}\n}\n"]}
@@ -1,6 +1,7 @@
1
- import { Container, SelectList } from "@earendil-works/pi-tui";
2
- import { getSelectListTheme } from "../theme/theme.js";
1
+ import { Container, fuzzyFilter, getKeybindings, Input, matchesKey, SelectList, Spacer, Text, } from "@earendil-works/pi-tui";
2
+ import { getSelectListTheme, theme } from "../theme/theme.js";
3
3
  import { DynamicBorder } from "./dynamic-border.js";
4
+ import { keyDisplayText } from "./keybinding-hints.js";
4
5
  const THINKING_SELECT_LIST_LAYOUT = {
5
6
  minPrimaryColumnWidth: 12,
6
7
  maxPrimaryColumnWidth: 32,
@@ -18,33 +19,89 @@ const LEVEL_DESCRIPTIONS = {
18
19
  * Component that renders a thinking level selector with borders
19
20
  */
20
21
  export class ThinkingSelectorComponent extends Container {
22
+ searchInput;
21
23
  selectList;
22
- constructor(currentLevel, availableLevels, onSelect, onCancel) {
24
+ selectListChildIndex;
25
+ allItems;
26
+ onSelect;
27
+ onCancel;
28
+ onSelectAsDefault;
29
+ _focused = false;
30
+ get focused() {
31
+ return this._focused;
32
+ }
33
+ set focused(value) {
34
+ this._focused = value;
35
+ this.searchInput.focused = value;
36
+ }
37
+ constructor(currentLevel, availableLevels, onSelect, onCancel, onSelectAsDefault, defaultThinkingLevel) {
23
38
  super();
24
- const thinkingLevels = availableLevels.map((level) => ({
39
+ this.onSelect = onSelect;
40
+ this.onCancel = onCancel;
41
+ this.onSelectAsDefault = onSelectAsDefault;
42
+ this.allItems = availableLevels.map((level) => ({
25
43
  value: level,
26
44
  label: level,
27
- description: LEVEL_DESCRIPTIONS[level],
45
+ description: level === defaultThinkingLevel ? `${LEVEL_DESCRIPTIONS[level]} · default` : LEVEL_DESCRIPTIONS[level],
28
46
  }));
29
47
  // Add top border
30
48
  this.addChild(new DynamicBorder());
49
+ this.addChild(new Spacer(1));
50
+ this.addChild(new Text("Thinking Level", 0, 0));
51
+ this.addChild(new Spacer(1));
52
+ this.addChild(new Text(`${keyDisplayText("app.thinking.cycle")} cycles thinking levels in-session`, 0, 0));
53
+ this.addChild(new Spacer(1));
54
+ this.searchInput = new Input();
55
+ this.searchInput.onSubmit = () => this.selectList.handleInput("\r");
56
+ this.addChild(this.searchInput);
57
+ this.addChild(new Spacer(1));
31
58
  // Create selector
32
- this.selectList = new SelectList(thinkingLevels, thinkingLevels.length, getSelectListTheme(), THINKING_SELECT_LIST_LAYOUT);
33
- // Preselect current level
34
- const currentIndex = thinkingLevels.findIndex((item) => item.value === currentLevel);
35
- if (currentIndex !== -1) {
36
- this.selectList.setSelectedIndex(currentIndex);
37
- }
38
- this.selectList.onSelect = (item) => {
39
- onSelect(item.value);
40
- };
41
- this.selectList.onCancel = () => {
42
- onCancel();
43
- };
59
+ this.selectList = this.buildSelectList(this.allItems, currentLevel);
60
+ this.selectListChildIndex = this.children.length;
44
61
  this.addChild(this.selectList);
62
+ this.addChild(new Spacer(1));
63
+ this.addChild(new Text(theme.fg("dim", " Enter to select · Ctrl+S to set as default · Esc to cancel"), 0, 0));
45
64
  // Add bottom border
46
65
  this.addChild(new DynamicBorder());
47
66
  }
67
+ buildSelectList(items, preselect) {
68
+ const list = new SelectList(items, Math.max(1, items.length), getSelectListTheme(), THINKING_SELECT_LIST_LAYOUT);
69
+ const currentIndex = items.findIndex((item) => item.value === preselect);
70
+ if (currentIndex !== -1) {
71
+ list.setSelectedIndex(currentIndex);
72
+ }
73
+ list.onSelect = (item) => this.onSelect(item.value);
74
+ list.onCancel = () => this.onCancel();
75
+ return list;
76
+ }
77
+ applyFilter(query) {
78
+ const filtered = query
79
+ ? fuzzyFilter(this.allItems, query, (item) => `${item.label} ${item.description ?? ""}`)
80
+ : this.allItems;
81
+ const selectedValue = this.selectList.getSelectedItem()?.value;
82
+ const newList = this.buildSelectList(filtered, selectedValue);
83
+ this.children[this.selectListChildIndex] = newList;
84
+ this.selectList = newList;
85
+ }
86
+ handleInput(keyData) {
87
+ if (matchesKey(keyData, "ctrl+s") && this.onSelectAsDefault) {
88
+ const item = this.selectList.getSelectedItem();
89
+ if (item)
90
+ this.onSelectAsDefault(item.value);
91
+ return;
92
+ }
93
+ const kb = getKeybindings();
94
+ const isNav = kb.matches(keyData, "tui.select.up") ||
95
+ kb.matches(keyData, "tui.select.down") ||
96
+ kb.matches(keyData, "tui.select.confirm") ||
97
+ kb.matches(keyData, "tui.select.cancel");
98
+ if (isNav) {
99
+ this.selectList.handleInput(keyData);
100
+ return;
101
+ }
102
+ this.searchInput.handleInput(keyData);
103
+ this.applyFilter(this.searchInput.getValue());
104
+ }
48
105
  getSelectList() {
49
106
  return this.selectList;
50
107
  }
@@ -1 +1 @@
1
- {"version":3,"file":"thinking-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/thinking-selector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAmB,UAAU,EAAgC,MAAM,wBAAwB,CAAC;AAC9G,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,2BAA2B,GAA4B;IAC5D,qBAAqB,EAAE,EAAE;IACzB,qBAAqB,EAAE,EAAE;CACzB,CAAC;AAEF,MAAM,kBAAkB,GAAkC;IACzD,GAAG,EAAE,cAAc;IACnB,OAAO,EAAE,mCAAmC;IAC5C,GAAG,EAAE,8BAA8B;IACnC,MAAM,EAAE,iCAAiC;IACzC,IAAI,EAAE,8BAA8B;IACpC,KAAK,EAAE,oCAAoC;IAC3C,GAAG,EAAE,mBAAmB;CACxB,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,yBAA0B,SAAQ,SAAS;IAC/C,UAAU,CAAa;IAE/B,YACC,YAA2B,EAC3B,eAAgC,EAChC,QAAwC,EACxC,QAAoB,EACnB;QACD,KAAK,EAAE,CAAC;QAER,MAAM,cAAc,GAAiB,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACpE,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,KAAK;YACZ,WAAW,EAAE,kBAAkB,CAAC,KAAK,CAAC;SACtC,CAAC,CAAC,CAAC;QAEJ,iBAAiB;QACjB,IAAI,CAAC,QAAQ,CAAC,IAAI,aAAa,EAAE,CAAC,CAAC;QAEnC,kBAAkB;QAClB,IAAI,CAAC,UAAU,GAAG,IAAI,UAAU,CAC/B,cAAc,EACd,cAAc,CAAC,MAAM,EACrB,kBAAkB,EAAE,EACpB,2BAA2B,CAC3B,CAAC;QAEF,0BAA0B;QAC1B,MAAM,YAAY,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC;QACrF,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAChD,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,QAAQ,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YACpC,QAAQ,CAAC,IAAI,CAAC,KAAsB,CAAC,CAAC;QAAA,CACtC,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,EAAE,CAAC;YAChC,QAAQ,EAAE,CAAC;QAAA,CACX,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAE/B,oBAAoB;QACpB,IAAI,CAAC,QAAQ,CAAC,IAAI,aAAa,EAAE,CAAC,CAAC;IAAA,CACnC;IAED,aAAa,GAAe;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAC;IAAA,CACvB;CACD","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { Container, type SelectItem, SelectList, type SelectListLayoutOptions } from \"@earendil-works/pi-tui\";\nimport { getSelectListTheme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\nconst THINKING_SELECT_LIST_LAYOUT: SelectListLayoutOptions = {\n\tminPrimaryColumnWidth: 12,\n\tmaxPrimaryColumnWidth: 32,\n};\n\nconst LEVEL_DESCRIPTIONS: Record<ThinkingLevel, string> = {\n\toff: \"No reasoning\",\n\tminimal: \"Very brief reasoning (~1k tokens)\",\n\tlow: \"Light reasoning (~2k tokens)\",\n\tmedium: \"Moderate reasoning (~8k tokens)\",\n\thigh: \"Deep reasoning (~16k tokens)\",\n\txhigh: \"Extra-high reasoning (~32k tokens)\",\n\tmax: \"Maximum reasoning\",\n};\n\n/**\n * Component that renders a thinking level selector with borders\n */\nexport class ThinkingSelectorComponent extends Container {\n\tprivate selectList: SelectList;\n\n\tconstructor(\n\t\tcurrentLevel: ThinkingLevel,\n\t\tavailableLevels: ThinkingLevel[],\n\t\tonSelect: (level: ThinkingLevel) => void,\n\t\tonCancel: () => void,\n\t) {\n\t\tsuper();\n\n\t\tconst thinkingLevels: SelectItem[] = availableLevels.map((level) => ({\n\t\t\tvalue: level,\n\t\t\tlabel: level,\n\t\t\tdescription: LEVEL_DESCRIPTIONS[level],\n\t\t}));\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Create selector\n\t\tthis.selectList = new SelectList(\n\t\t\tthinkingLevels,\n\t\t\tthinkingLevels.length,\n\t\t\tgetSelectListTheme(),\n\t\t\tTHINKING_SELECT_LIST_LAYOUT,\n\t\t);\n\n\t\t// Preselect current level\n\t\tconst currentIndex = thinkingLevels.findIndex((item) => item.value === currentLevel);\n\t\tif (currentIndex !== -1) {\n\t\t\tthis.selectList.setSelectedIndex(currentIndex);\n\t\t}\n\n\t\tthis.selectList.onSelect = (item) => {\n\t\t\tonSelect(item.value as ThinkingLevel);\n\t\t};\n\n\t\tthis.selectList.onCancel = () => {\n\t\t\tonCancel();\n\t\t};\n\n\t\tthis.addChild(this.selectList);\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\tgetSelectList(): SelectList {\n\t\treturn this.selectList;\n\t}\n}\n"]}
1
+ {"version":3,"file":"thinking-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/thinking-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tInput,\n\tmatchesKey,\n\ttype SelectItem,\n\tSelectList,\n\ttype SelectListLayoutOptions,\n\tSpacer,\n\tText,\n} from \"@earendil-works/pi-tui\";\nimport { getSelectListTheme, theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyDisplayText } from \"./keybinding-hints.ts\";\n\nconst THINKING_SELECT_LIST_LAYOUT: SelectListLayoutOptions = {\n\tminPrimaryColumnWidth: 12,\n\tmaxPrimaryColumnWidth: 32,\n};\n\nconst LEVEL_DESCRIPTIONS: Record<ThinkingLevel, string> = {\n\toff: \"No reasoning\",\n\tminimal: \"Very brief reasoning (~1k tokens)\",\n\tlow: \"Light reasoning (~2k tokens)\",\n\tmedium: \"Moderate reasoning (~8k tokens)\",\n\thigh: \"Deep reasoning (~16k tokens)\",\n\txhigh: \"Extra-high reasoning (~32k tokens)\",\n\tmax: \"Maximum reasoning\",\n};\n\n/**\n * Component that renders a thinking level selector with borders\n */\nexport class ThinkingSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\tprivate selectList: SelectList;\n\tprivate selectListChildIndex: number;\n\tprivate allItems: SelectItem[];\n\tprivate onSelect: (level: ThinkingLevel) => void;\n\tprivate onCancel: () => void;\n\tprivate onSelectAsDefault?: (level: ThinkingLevel) => void;\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tconstructor(\n\t\tcurrentLevel: ThinkingLevel,\n\t\tavailableLevels: ThinkingLevel[],\n\t\tonSelect: (level: ThinkingLevel) => void,\n\t\tonCancel: () => void,\n\t\tonSelectAsDefault?: (level: ThinkingLevel) => void,\n\t\tdefaultThinkingLevel?: ThinkingLevel,\n\t) {\n\t\tsuper();\n\t\tthis.onSelect = onSelect;\n\t\tthis.onCancel = onCancel;\n\t\tthis.onSelectAsDefault = onSelectAsDefault;\n\n\t\tthis.allItems = availableLevels.map((level) => ({\n\t\t\tvalue: level,\n\t\t\tlabel: level,\n\t\t\tdescription:\n\t\t\t\tlevel === defaultThinkingLevel ? `${LEVEL_DESCRIPTIONS[level]} · default` : LEVEL_DESCRIPTIONS[level],\n\t\t}));\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(\"Thinking Level\", 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(`${keyDisplayText(\"app.thinking.cycle\")} cycles thinking levels in-session`, 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.searchInput = new Input();\n\t\tthis.searchInput.onSubmit = () => this.selectList.handleInput(\"\\r\");\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create selector\n\t\tthis.selectList = this.buildSelectList(this.allItems, currentLevel);\n\t\tthis.selectListChildIndex = this.children.length;\n\t\tthis.addChild(this.selectList);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.fg(\"dim\", \" Enter to select · Ctrl+S to set as default · Esc to cancel\"), 0, 0));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\t}\n\n\tprivate buildSelectList(items: SelectItem[], preselect?: ThinkingLevel): SelectList {\n\t\tconst list = new SelectList(items, Math.max(1, items.length), getSelectListTheme(), THINKING_SELECT_LIST_LAYOUT);\n\t\tconst currentIndex = items.findIndex((item) => item.value === preselect);\n\t\tif (currentIndex !== -1) {\n\t\t\tlist.setSelectedIndex(currentIndex);\n\t\t}\n\t\tlist.onSelect = (item) => this.onSelect(item.value as ThinkingLevel);\n\t\tlist.onCancel = () => this.onCancel();\n\t\treturn list;\n\t}\n\n\tprivate applyFilter(query: string): void {\n\t\tconst filtered = query\n\t\t\t? fuzzyFilter(this.allItems, query, (item) => `${item.label} ${item.description ?? \"\"}`)\n\t\t\t: this.allItems;\n\t\tconst selectedValue = this.selectList.getSelectedItem()?.value as ThinkingLevel | undefined;\n\t\tconst newList = this.buildSelectList(filtered, selectedValue);\n\t\tthis.children[this.selectListChildIndex] = newList;\n\t\tthis.selectList = newList;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tif (matchesKey(keyData, \"ctrl+s\") && this.onSelectAsDefault) {\n\t\t\tconst item = this.selectList.getSelectedItem();\n\t\t\tif (item) this.onSelectAsDefault(item.value as ThinkingLevel);\n\t\t\treturn;\n\t\t}\n\n\t\tconst kb = getKeybindings();\n\t\tconst isNav =\n\t\t\tkb.matches(keyData, \"tui.select.up\") ||\n\t\t\tkb.matches(keyData, \"tui.select.down\") ||\n\t\t\tkb.matches(keyData, \"tui.select.confirm\") ||\n\t\t\tkb.matches(keyData, \"tui.select.cancel\");\n\t\tif (isNav) {\n\t\t\tthis.selectList.handleInput(keyData);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.searchInput.handleInput(keyData);\n\t\tthis.applyFilter(this.searchInput.getValue());\n\t}\n\n\tgetSelectList(): SelectList {\n\t\treturn this.selectList;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,SAAS,EAAwC,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AACxH,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,mCAAmC,CAAC;AAM3F,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,WAAW,CAAO;IAC1B,OAAO,CAAC,mBAAmB,CAAY;IACvC,OAAO,CAAC,qBAAqB,CAAC,CAAY;IAC1C,OAAO,CAAC,uBAAuB,CAAC,CAAY;IAC5C,OAAO,CAAC,aAAa,CAAW;IAChC,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,cAAc,CAAC,CAA2B;IAClD,OAAO,CAAC,qBAAqB,CAAC,CAA2B;IACzD,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAC,CAIb;IACF,OAAO,CAAC,eAAe,CAA8D;IACrF,OAAO,CAAC,aAAa,CAAS;IAE9B,YACC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,GAAG,EACT,OAAO,kCAA2B,EAClC,cAAc,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,SAAS,EACpD,EAAE,EAAE,GAAG,EACP,GAAG,EAAE,MAAM,EA6BX;IAED,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,oBAAoB;IAQ5B,UAAU,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,CAG1B;IAED,oBAAoB,IAAI,IAAI,CAI3B;IAED,eAAe,IAAI,IAAI,CAItB;IAED,YAAY,CACX,MAAM,EAAE;QACP,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAClF,OAAO,CAAC,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;KACjB,EACD,SAAS,UAAQ,GACf,IAAI,CAKN;IAED,OAAO,CAAC,0BAA0B;IAuBlC,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAGnC;IAED,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAGjC;IAED,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGtC;IAEQ,UAAU,IAAI,IAAI,CAG1B;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BvC;IAED,OAAO,CAAC,aAAa;IA4GrB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,mBAAmB;CAY3B","sourcesContent":["import { Box, type Component, Container, getCapabilities, Image, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.ts\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.ts\";\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.ts\";\nimport { convertToPng } from \"../../../utils/image-convert.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\tthis.contentBox = new Box(1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.contentText = new Text(\"\", 1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox);\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(this.toolName)), 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn new Text(theme.fg(\"toolOutput\", output), 0, 0);\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && this.getRenderShell() === \"self\") {\n\t\t\tconst contentLines = this.selfRenderContainer.render(width);\n\t\t\tif (contentLines.length === 0 && this.imageComponents.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst lines: string[] = [];\n\t\t\tif (contentLines.length > 0) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(...contentLines);\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) {\n\t\t\t\t\tlines.push(...spacer.render(width));\n\t\t\t\t}\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) {\n\t\t\t\t\tlines.push(...imageComponent.render(width));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tconst bgFn = this.isPartial\n\t\t\t? (text: string) => theme.bg(\"toolPendingBg\", text)\n\t\t\t: this.result?.isError\n\t\t\t\t? (text: string) => theme.bg(\"toolErrorBg\", text)\n\t\t\t\t: (text: string) => theme.bg(\"toolSuccessBg\", text);\n\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tconst renderContainer = this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(bgFn);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\tif (!callRenderer) {\n\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\thasContent = true;\n\t\t\t\t} catch {\n\t\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\t\thasContent = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.contentText.setCustomBgFn(bgFn);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tlet text = theme.fg(\"toolTitle\", theme.bold(this.toolName));\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.getTextOutput();\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
1
+ {"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,SAAS,EAAwC,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AACxH,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,mCAAmC,CAAC;AAS3F,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,sBAAuB,SAAQ,SAAS;IACpD,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,WAAW,CAAO;IAC1B,OAAO,CAAC,mBAAmB,CAAY;IACvC,OAAO,CAAC,qBAAqB,CAAC,CAAY;IAC1C,OAAO,CAAC,uBAAuB,CAAC,CAAY;IAC5C,OAAO,CAAC,aAAa,CAAW;IAChC,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,cAAc,CAAC,CAA2B;IAClD,OAAO,CAAC,qBAAqB,CAAC,CAA2B;IACzD,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAC,CAIb;IACF,OAAO,CAAC,eAAe,CAA8D;IACrF,OAAO,CAAC,aAAa,CAAS;IAE9B,YACC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,GAAG,EACT,OAAO,kCAA2B,EAClC,cAAc,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,SAAS,EACpD,EAAE,EAAE,GAAG,EACP,GAAG,EAAE,MAAM,EA6BX;IAED,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,oBAAoB;IAgB5B,UAAU,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,CAG1B;IAED,oBAAoB,IAAI,IAAI,CAI3B;IAED,eAAe,IAAI,IAAI,CAItB;IAED,YAAY,CACX,MAAM,EAAE;QACP,OAAO,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAClF,OAAO,CAAC,EAAE,GAAG,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;KACjB,EACD,SAAS,UAAQ,GACf,IAAI,CAKN;IAED,OAAO,CAAC,0BAA0B;IAuBlC,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAGnC;IAED,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAGjC;IAED,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGtC;IAEQ,UAAU,IAAI,IAAI,CAG1B;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BvC;IAED,OAAO,CAAC,aAAa;IA4GrB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,mBAAmB;CAY3B","sourcesContent":["import { Box, type Component, Container, getCapabilities, Image, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.ts\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.ts\";\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.ts\";\nimport { convertToPng } from \"../../../utils/image-convert.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\n\nconst FALLBACK_PREVIEW_LINES = 10;\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\tthis.contentBox = new Box(1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.contentText = new Text(\"\", 1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox);\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(this.toolName)), 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst lines = output.split(\"\\n\");\n\t\tconst displayLines = this.expanded ? lines : lines.slice(0, FALLBACK_PREVIEW_LINES);\n\t\tconst remaining = lines.length - displayLines.length;\n\t\tlet text = displayLines.map((line) => theme.fg(\"toolOutput\", line)).join(\"\\n\");\n\t\tif (remaining > 0) {\n\t\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"to expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t}\n\t\treturn new Text(text, 0, 0);\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && this.getRenderShell() === \"self\") {\n\t\t\tconst contentLines = this.selfRenderContainer.render(width);\n\t\t\tif (contentLines.length === 0 && this.imageComponents.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst lines: string[] = [];\n\t\t\tif (contentLines.length > 0) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(...contentLines);\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) {\n\t\t\t\t\tlines.push(...spacer.render(width));\n\t\t\t\t}\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) {\n\t\t\t\t\tlines.push(...imageComponent.render(width));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tconst bgFn = this.isPartial\n\t\t\t? (text: string) => theme.bg(\"toolPendingBg\", text)\n\t\t\t: this.result?.isError\n\t\t\t\t? (text: string) => theme.bg(\"toolErrorBg\", text)\n\t\t\t\t: (text: string) => theme.bg(\"toolSuccessBg\", text);\n\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tconst renderContainer = this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(bgFn);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\tif (!callRenderer) {\n\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\thasContent = true;\n\t\t\t\t} catch {\n\t\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\t\thasContent = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.contentText.setCustomBgFn(bgFn);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tlet text = theme.fg(\"toolTitle\", theme.bold(this.toolName));\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.getTextOutput();\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
@@ -3,6 +3,8 @@ import { createAllToolDefinitions } from "../../../core/tools/index.js";
3
3
  import { getTextOutput as getRenderedTextOutput } from "../../../core/tools/render-utils.js";
4
4
  import { convertToPng } from "../../../utils/image-convert.js";
5
5
  import { theme } from "../theme/theme.js";
6
+ import { keyHint } from "./keybinding-hints.js";
7
+ const FALLBACK_PREVIEW_LINES = 10;
6
8
  export class ToolExecutionComponent extends Container {
7
9
  contentBox;
8
10
  contentText;
@@ -111,7 +113,14 @@ export class ToolExecutionComponent extends Container {
111
113
  if (!output) {
112
114
  return undefined;
113
115
  }
114
- return new Text(theme.fg("toolOutput", output), 0, 0);
116
+ const lines = output.split("\n");
117
+ const displayLines = this.expanded ? lines : lines.slice(0, FALLBACK_PREVIEW_LINES);
118
+ const remaining = lines.length - displayLines.length;
119
+ let text = displayLines.map((line) => theme.fg("toolOutput", line)).join("\n");
120
+ if (remaining > 0) {
121
+ text += `${theme.fg("muted", `\n... (${remaining} more lines,`)} ${keyHint("app.tools.expand", "to expand")}${theme.fg("muted", ")")}`;
122
+ }
123
+ return new Text(text, 0, 0);
115
124
  }
116
125
  updateArgs(args) {
117
126
  this.args = args;
@@ -1 +1 @@
1
- {"version":3,"file":"tool-execution.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import { Box, type Component, Container, getCapabilities, Image, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.ts\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.ts\";\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.ts\";\nimport { convertToPng } from \"../../../utils/image-convert.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\tthis.contentBox = new Box(1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.contentText = new Text(\"\", 1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox);\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(this.toolName)), 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn new Text(theme.fg(\"toolOutput\", output), 0, 0);\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && this.getRenderShell() === \"self\") {\n\t\t\tconst contentLines = this.selfRenderContainer.render(width);\n\t\t\tif (contentLines.length === 0 && this.imageComponents.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst lines: string[] = [];\n\t\t\tif (contentLines.length > 0) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(...contentLines);\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) {\n\t\t\t\t\tlines.push(...spacer.render(width));\n\t\t\t\t}\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) {\n\t\t\t\t\tlines.push(...imageComponent.render(width));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tconst bgFn = this.isPartial\n\t\t\t? (text: string) => theme.bg(\"toolPendingBg\", text)\n\t\t\t: this.result?.isError\n\t\t\t\t? (text: string) => theme.bg(\"toolErrorBg\", text)\n\t\t\t\t: (text: string) => theme.bg(\"toolSuccessBg\", text);\n\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tconst renderContainer = this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(bgFn);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\tif (!callRenderer) {\n\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\thasContent = true;\n\t\t\t\t} catch {\n\t\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\t\thasContent = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.contentText.setCustomBgFn(bgFn);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tlet text = theme.fg(\"toolTitle\", theme.bold(this.toolName));\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.getTextOutput();\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
1
+ {"version":3,"file":"tool-execution.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import { Box, type Component, Container, getCapabilities, Image, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.ts\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.ts\";\nimport { getTextOutput as getRenderedTextOutput } from \"../../../core/tools/render-utils.ts\";\nimport { convertToPng } from \"../../../utils/image-convert.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { keyHint } from \"./keybinding-hints.ts\";\n\nconst FALLBACK_PREVIEW_LINES = 10;\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\tthis.contentBox = new Box(1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.contentText = new Text(\"\", 1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox);\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(theme.fg(\"toolTitle\", theme.bold(this.toolName)), 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst lines = output.split(\"\\n\");\n\t\tconst displayLines = this.expanded ? lines : lines.slice(0, FALLBACK_PREVIEW_LINES);\n\t\tconst remaining = lines.length - displayLines.length;\n\t\tlet text = displayLines.map((line) => theme.fg(\"toolOutput\", line)).join(\"\\n\");\n\t\tif (remaining > 0) {\n\t\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"to expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t}\n\t\treturn new Text(text, 0, 0);\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && this.getRenderShell() === \"self\") {\n\t\t\tconst contentLines = this.selfRenderContainer.render(width);\n\t\t\tif (contentLines.length === 0 && this.imageComponents.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst lines: string[] = [];\n\t\t\tif (contentLines.length > 0) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(...contentLines);\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) {\n\t\t\t\t\tlines.push(...spacer.render(width));\n\t\t\t\t}\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) {\n\t\t\t\t\tlines.push(...imageComponent.render(width));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tconst bgFn = this.isPartial\n\t\t\t? (text: string) => theme.bg(\"toolPendingBg\", text)\n\t\t\t: this.result?.isError\n\t\t\t\t? (text: string) => theme.bg(\"toolErrorBg\", text)\n\t\t\t\t: (text: string) => theme.bg(\"toolSuccessBg\", text);\n\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tconst renderContainer = this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(bgFn);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\tif (!callRenderer) {\n\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\thasContent = true;\n\t\t\t\t} catch {\n\t\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\t\thasContent = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.contentText.setCustomBgFn(bgFn);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tlet text = theme.fg(\"toolTitle\", theme.bold(this.toolName));\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.getTextOutput();\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"external-editor.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/external-editor.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,oBAAoB,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAElG,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgCxG","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface ExternalEditorOptions {\n\tcommand: string;\n\tcontent: string;\n}\n\nexport type ExternalEditorResult = { status: \"complete\"; content: string } | { status: \"failed\" };\n\nexport async function editInExternalEditor(options: ExternalEditorOptions): Promise<ExternalEditorResult> {\n\tconst directory = mkdtempSync(join(tmpdir(), \"pi-editor-\"));\n\tconst filePath = join(directory, \"prompt.md\");\n\ttry {\n\t\twriteFileSync(filePath, options.content, \"utf-8\");\n\t\tconst [editor, ...editorArgs] = options.command.split(\" \");\n\t\tprocess.stdout.write(`Launching external editor: ${options.command}\\nPi will resume when the editor exits.\\n`);\n\n\t\t// Do not use spawnSync here. On Windows, synchronous child_process calls can keep\n\t\t// Node/libuv's console input read active after the parent pauses stdin, racing\n\t\t// vim/nvim for the console input buffer until Ctrl+C cancels the pending read.\n\t\tconst exitCode = await new Promise<number | null>((resolve) => {\n\t\t\tconst child = spawn(editor, [...editorArgs, filePath], {\n\t\t\t\tstdio: \"inherit\",\n\t\t\t\tshell: process.platform === \"win32\",\n\t\t\t});\n\t\t\tchild.on(\"error\", () => resolve(null));\n\t\t\tchild.on(\"close\", (code) => resolve(code));\n\t\t});\n\n\t\tif (exitCode !== 0) {\n\t\t\treturn { status: \"failed\" };\n\t\t}\n\n\t\treturn { status: \"complete\", content: readFileSync(filePath, \"utf-8\").replace(/\\n$/, \"\") };\n\t} finally {\n\t\ttry {\n\t\t\trmSync(directory, { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Cleanup is best effort.\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"external-editor.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/external-editor.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,oBAAoB,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAElG,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgCxG","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { stripBom } from \"../../utils/text.ts\";\n\nexport interface ExternalEditorOptions {\n\tcommand: string;\n\tcontent: string;\n}\n\nexport type ExternalEditorResult = { status: \"complete\"; content: string } | { status: \"failed\" };\n\nexport async function editInExternalEditor(options: ExternalEditorOptions): Promise<ExternalEditorResult> {\n\tconst directory = mkdtempSync(join(tmpdir(), \"pi-editor-\"));\n\tconst filePath = join(directory, \"prompt.md\");\n\ttry {\n\t\twriteFileSync(filePath, options.content, \"utf-8\");\n\t\tconst [editor, ...editorArgs] = options.command.split(\" \");\n\t\tprocess.stdout.write(`Launching external editor: ${options.command}\\nPi will resume when the editor exits.\\n`);\n\n\t\t// Do not use spawnSync here. On Windows, synchronous child_process calls can keep\n\t\t// Node/libuv's console input read active after the parent pauses stdin, racing\n\t\t// vim/nvim for the console input buffer until Ctrl+C cancels the pending read.\n\t\tconst exitCode = await new Promise<number | null>((resolve) => {\n\t\t\tconst child = spawn(editor, [...editorArgs, filePath], {\n\t\t\t\tstdio: \"inherit\",\n\t\t\t\tshell: process.platform === \"win32\",\n\t\t\t});\n\t\t\tchild.on(\"error\", () => resolve(null));\n\t\t\tchild.on(\"close\", (code) => resolve(code));\n\t\t});\n\n\t\tif (exitCode !== 0) {\n\t\t\treturn { status: \"failed\" };\n\t\t}\n\n\t\treturn { status: \"complete\", content: stripBom(readFileSync(filePath, \"utf-8\")).replace(/\\n$/, \"\") };\n\t} finally {\n\t\ttry {\n\t\t\trmSync(directory, { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Cleanup is best effort.\n\t\t}\n\t}\n}\n"]}
@@ -2,6 +2,7 @@ import { spawn } from "node:child_process";
2
2
  import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
+ import { stripBom } from "../../utils/text.js";
5
6
  export async function editInExternalEditor(options) {
6
7
  const directory = mkdtempSync(join(tmpdir(), "pi-editor-"));
7
8
  const filePath = join(directory, "prompt.md");
@@ -23,7 +24,7 @@ export async function editInExternalEditor(options) {
23
24
  if (exitCode !== 0) {
24
25
  return { status: "failed" };
25
26
  }
26
- return { status: "complete", content: readFileSync(filePath, "utf-8").replace(/\n$/, "") };
27
+ return { status: "complete", content: stripBom(readFileSync(filePath, "utf-8")).replace(/\n$/, "") };
27
28
  }
28
29
  finally {
29
30
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"external-editor.js","sourceRoot":"","sources":["../../../src/modes/interactive/external-editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AASjC,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAA8B,EAAiC;IACzG,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC;QACJ,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,OAAO,CAAC,OAAO,2CAA2C,CAAC,CAAC;QAE/G,kFAAkF;QAClF,+EAA+E;QAC/E,+EAA+E;QAC/E,MAAM,QAAQ,GAAG,MAAM,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,EAAE,CAAC;YAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,UAAU,EAAE,QAAQ,CAAC,EAAE;gBACtD,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;aACnC,CAAC,CAAC;YACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACvC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAAA,CAC3C,CAAC,CAAC;QAEH,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC7B,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;IAC5F,CAAC;YAAS,CAAC;QACV,IAAI,CAAC;YACJ,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACR,0BAA0B;QAC3B,CAAC;IACF,CAAC;AAAA,CACD","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface ExternalEditorOptions {\n\tcommand: string;\n\tcontent: string;\n}\n\nexport type ExternalEditorResult = { status: \"complete\"; content: string } | { status: \"failed\" };\n\nexport async function editInExternalEditor(options: ExternalEditorOptions): Promise<ExternalEditorResult> {\n\tconst directory = mkdtempSync(join(tmpdir(), \"pi-editor-\"));\n\tconst filePath = join(directory, \"prompt.md\");\n\ttry {\n\t\twriteFileSync(filePath, options.content, \"utf-8\");\n\t\tconst [editor, ...editorArgs] = options.command.split(\" \");\n\t\tprocess.stdout.write(`Launching external editor: ${options.command}\\nPi will resume when the editor exits.\\n`);\n\n\t\t// Do not use spawnSync here. On Windows, synchronous child_process calls can keep\n\t\t// Node/libuv's console input read active after the parent pauses stdin, racing\n\t\t// vim/nvim for the console input buffer until Ctrl+C cancels the pending read.\n\t\tconst exitCode = await new Promise<number | null>((resolve) => {\n\t\t\tconst child = spawn(editor, [...editorArgs, filePath], {\n\t\t\t\tstdio: \"inherit\",\n\t\t\t\tshell: process.platform === \"win32\",\n\t\t\t});\n\t\t\tchild.on(\"error\", () => resolve(null));\n\t\t\tchild.on(\"close\", (code) => resolve(code));\n\t\t});\n\n\t\tif (exitCode !== 0) {\n\t\t\treturn { status: \"failed\" };\n\t\t}\n\n\t\treturn { status: \"complete\", content: readFileSync(filePath, \"utf-8\").replace(/\\n$/, \"\") };\n\t} finally {\n\t\ttry {\n\t\t\trmSync(directory, { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Cleanup is best effort.\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"external-editor.js","sourceRoot":"","sources":["../../../src/modes/interactive/external-editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAS/C,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAA8B,EAAiC;IACzG,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC;QACJ,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,OAAO,CAAC,OAAO,2CAA2C,CAAC,CAAC;QAE/G,kFAAkF;QAClF,+EAA+E;QAC/E,+EAA+E;QAC/E,MAAM,QAAQ,GAAG,MAAM,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,EAAE,CAAC;YAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,UAAU,EAAE,QAAQ,CAAC,EAAE;gBACtD,KAAK,EAAE,SAAS;gBAChB,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;aACnC,CAAC,CAAC;YACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACvC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAAA,CAC3C,CAAC,CAAC;QAEH,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC7B,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;IACtG,CAAC;YAAS,CAAC;QACV,IAAI,CAAC;YACJ,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACR,0BAA0B;QAC3B,CAAC;IACF,CAAC;AAAA,CACD","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { stripBom } from \"../../utils/text.ts\";\n\nexport interface ExternalEditorOptions {\n\tcommand: string;\n\tcontent: string;\n}\n\nexport type ExternalEditorResult = { status: \"complete\"; content: string } | { status: \"failed\" };\n\nexport async function editInExternalEditor(options: ExternalEditorOptions): Promise<ExternalEditorResult> {\n\tconst directory = mkdtempSync(join(tmpdir(), \"pi-editor-\"));\n\tconst filePath = join(directory, \"prompt.md\");\n\ttry {\n\t\twriteFileSync(filePath, options.content, \"utf-8\");\n\t\tconst [editor, ...editorArgs] = options.command.split(\" \");\n\t\tprocess.stdout.write(`Launching external editor: ${options.command}\\nPi will resume when the editor exits.\\n`);\n\n\t\t// Do not use spawnSync here. On Windows, synchronous child_process calls can keep\n\t\t// Node/libuv's console input read active after the parent pauses stdin, racing\n\t\t// vim/nvim for the console input buffer until Ctrl+C cancels the pending read.\n\t\tconst exitCode = await new Promise<number | null>((resolve) => {\n\t\t\tconst child = spawn(editor, [...editorArgs, filePath], {\n\t\t\t\tstdio: \"inherit\",\n\t\t\t\tshell: process.platform === \"win32\",\n\t\t\t});\n\t\t\tchild.on(\"error\", () => resolve(null));\n\t\t\tchild.on(\"close\", (code) => resolve(code));\n\t\t});\n\n\t\tif (exitCode !== 0) {\n\t\t\treturn { status: \"failed\" };\n\t\t}\n\n\t\treturn { status: \"complete\", content: stripBom(readFileSync(filePath, \"utf-8\")).replace(/\\n$/, \"\") };\n\t} finally {\n\t\ttry {\n\t\t\trmSync(directory, { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Cleanup is best effort.\n\t\t}\n\t}\n}\n"]}
@@ -6,8 +6,9 @@ import type { ImageContent } from "@earendil-works/pi-ai/compat";
6
6
  import type { Terminal } from "@earendil-works/pi-tui";
7
7
  import { type TUI, TuiAltScreen, TuiMainScreen } from "@earendil-works/pi-tui";
8
8
  import { type AgentSessionRuntime } from "../../core/agent-session-runtime.ts";
9
+ import type { AgentSessionRuntimeDiagnostic } from "../../core/agent-session-services.ts";
9
10
  import { SessionManager } from "../../core/session-manager.ts";
10
- import type { TuiMode } from "../../core/settings-manager.ts";
11
+ import type { FullscreenExitOutput, TuiMode } from "../../core/settings-manager.ts";
11
12
  import { type LatestPiRelease } from "../../utils/version-check.ts";
12
13
  export declare function formatResumeCommand(sessionManager: SessionManager): string | undefined;
13
14
  /**
@@ -16,6 +17,8 @@ export declare function formatResumeCommand(sessionManager: SessionManager): str
16
17
  export interface InteractiveModeOptions {
17
18
  /** Providers that were migrated to auth.json (shows warning) */
18
19
  migratedProviders?: string[];
20
+ /** Diagnostics collected before the interactive TUI was initialized. */
21
+ startupDiagnostics?: AgentSessionRuntimeDiagnostic[];
19
22
  /** Warning message if session model couldn't be restored */
20
23
  modelFallbackMessage?: string;
21
24
  /** Cwd to trust after reload if it gained a .pi directory during this implicitly trusted session. */
@@ -30,6 +33,8 @@ export interface InteractiveModeOptions {
30
33
  verbose?: boolean;
31
34
  /** TUI layout mode. */
32
35
  tuiMode?: TuiMode;
36
+ /** Initial interactive theme setting for this invocation. */
37
+ initialThemeSetting?: string;
33
38
  }
34
39
  interface InteractiveTuiOptions {
35
40
  tuiMode: TuiMode;
@@ -86,6 +91,7 @@ export declare class InteractiveMode {
86
91
  private anthropicSubscriptionWarningShown;
87
92
  private lastStatusSpacer;
88
93
  private lastStatusText;
94
+ private managedToolStatusStarted;
89
95
  private streamingComponent;
90
96
  private streamingMessage;
91
97
  private pendingTools;
@@ -270,11 +276,14 @@ export declare class InteractiveMode {
270
276
  private setupKeyHandlers;
271
277
  private handleRightClickPaste;
272
278
  private handleClipboardPaste;
279
+ private handleStartupSubmit;
273
280
  private setupEditorSubmitHandler;
274
281
  private subscribeToAgent;
275
282
  private handleEvent;
276
283
  /** Extract text content from a user message */
277
284
  private getUserMessageText;
285
+ /** Show a managed-tool status update in the chat. */
286
+ private showManagedToolStatus;
278
287
  /**
279
288
  * Show a status message in the chat.
280
289
  *
@@ -292,6 +301,11 @@ export declare class InteractiveMode {
292
301
  * @param options.populateHistory Add user messages to editor history
293
302
  */
294
303
  private renderSessionEntries;
304
+ /**
305
+ * Render billing usage for a compaction or branch summary. The notice is derived
306
+ * from persisted summary usage and is not stored as a separate session entry.
307
+ */
308
+ private addCompactionCostNotice;
295
309
  /**
296
310
  * Show a transcript notice when a completed assistant message paid for a
297
311
  * significant cache miss. Only states observable facts: the miss itself,
@@ -367,6 +381,9 @@ export declare class InteractiveMode {
367
381
  */
368
382
  private showSelector;
369
383
  private showSettingsSelector;
384
+ private handleThinkingCommand;
385
+ private selectThinkingLevel;
386
+ private showThinkingSelector;
370
387
  private handleModelCommand;
371
388
  private findExactModelMatch;
372
389
  /** Update the footer's available provider count from the current snapshot without refreshing catalogs. */
@@ -423,7 +440,7 @@ export declare class InteractiveMode {
423
440
  private checkDaxnutsEasterEgg;
424
441
  private handleBashCommand;
425
442
  private handleCompactCommand;
426
- stop(): void;
443
+ stop(fullscreenExitOutput?: FullscreenExitOutput): void;
427
444
  }
428
445
  export {};
429
446
  //# sourceMappingURL=interactive-mode.d.ts.map