shortcutxl 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (423) hide show
  1. package/README.md +59 -0
  2. package/agent-docs/README.md +397 -0
  3. package/agent-docs/docs/compaction.md +390 -0
  4. package/agent-docs/docs/custom-provider.md +580 -0
  5. package/agent-docs/docs/development.md +69 -0
  6. package/agent-docs/docs/extensions.md +1971 -0
  7. package/agent-docs/docs/json.md +79 -0
  8. package/agent-docs/docs/keybindings.md +174 -0
  9. package/agent-docs/docs/models.md +293 -0
  10. package/agent-docs/docs/packages.md +209 -0
  11. package/agent-docs/docs/prompt-templates.md +67 -0
  12. package/agent-docs/docs/providers.md +186 -0
  13. package/agent-docs/docs/rpc.md +1317 -0
  14. package/agent-docs/docs/sdk.md +962 -0
  15. package/agent-docs/docs/session.md +412 -0
  16. package/agent-docs/docs/settings.md +223 -0
  17. package/agent-docs/docs/shell-aliases.md +13 -0
  18. package/agent-docs/docs/skills.md +231 -0
  19. package/agent-docs/docs/terminal-setup.md +70 -0
  20. package/agent-docs/docs/termux.md +127 -0
  21. package/agent-docs/docs/themes.md +295 -0
  22. package/agent-docs/docs/tree.md +219 -0
  23. package/agent-docs/docs/tui.md +887 -0
  24. package/agent-docs/docs/windows.md +17 -0
  25. package/agent-docs/examples/README.md +25 -0
  26. package/agent-docs/examples/extensions/README.md +205 -0
  27. package/agent-docs/examples/extensions/antigravity-image-gen.ts +447 -0
  28. package/agent-docs/examples/extensions/auto-commit-on-exit.ts +49 -0
  29. package/agent-docs/examples/extensions/bash-spawn-hook.ts +30 -0
  30. package/agent-docs/examples/extensions/bookmark.ts +50 -0
  31. package/agent-docs/examples/extensions/built-in-tool-renderer.ts +256 -0
  32. package/agent-docs/examples/extensions/claude-rules.ts +86 -0
  33. package/agent-docs/examples/extensions/commands.ts +75 -0
  34. package/agent-docs/examples/extensions/confirm-destructive.ts +59 -0
  35. package/agent-docs/examples/extensions/custom-compaction.ts +126 -0
  36. package/agent-docs/examples/extensions/custom-footer.ts +63 -0
  37. package/agent-docs/examples/extensions/custom-header.ts +73 -0
  38. package/agent-docs/examples/extensions/custom-provider-anthropic/index.ts +660 -0
  39. package/agent-docs/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  40. package/agent-docs/examples/extensions/custom-provider-anthropic/package.json +19 -0
  41. package/agent-docs/examples/extensions/custom-provider-gitlab-duo/index.ts +362 -0
  42. package/agent-docs/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  43. package/agent-docs/examples/extensions/custom-provider-gitlab-duo/test.ts +88 -0
  44. package/agent-docs/examples/extensions/custom-provider-qwen-cli/index.ts +349 -0
  45. package/agent-docs/examples/extensions/custom-provider-qwen-cli/package.json +16 -0
  46. package/agent-docs/examples/extensions/dirty-repo-guard.ts +56 -0
  47. package/agent-docs/examples/extensions/doom-overlay/README.md +46 -0
  48. package/agent-docs/examples/extensions/doom-overlay/doom/build.sh +152 -0
  49. package/agent-docs/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  50. package/agent-docs/examples/extensions/doom-overlay/doom-component.ts +133 -0
  51. package/agent-docs/examples/extensions/doom-overlay/doom-engine.ts +186 -0
  52. package/agent-docs/examples/extensions/doom-overlay/doom-keys.ts +108 -0
  53. package/agent-docs/examples/extensions/doom-overlay/index.ts +74 -0
  54. package/agent-docs/examples/extensions/doom-overlay/wad-finder.ts +51 -0
  55. package/agent-docs/examples/extensions/dynamic-resources/SKILL.md +8 -0
  56. package/agent-docs/examples/extensions/dynamic-resources/dynamic.json +79 -0
  57. package/agent-docs/examples/extensions/dynamic-resources/dynamic.md +5 -0
  58. package/agent-docs/examples/extensions/dynamic-resources/index.ts +15 -0
  59. package/agent-docs/examples/extensions/dynamic-tools.ts +77 -0
  60. package/agent-docs/examples/extensions/event-bus.ts +43 -0
  61. package/agent-docs/examples/extensions/file-trigger.ts +41 -0
  62. package/agent-docs/examples/extensions/git-checkpoint.ts +53 -0
  63. package/agent-docs/examples/extensions/handoff.ts +155 -0
  64. package/agent-docs/examples/extensions/hello.ts +25 -0
  65. package/agent-docs/examples/extensions/inline-bash.ts +94 -0
  66. package/agent-docs/examples/extensions/input-transform.ts +43 -0
  67. package/agent-docs/examples/extensions/interactive-shell.ts +209 -0
  68. package/agent-docs/examples/extensions/mac-system-theme.ts +47 -0
  69. package/agent-docs/examples/extensions/message-renderer.ts +59 -0
  70. package/agent-docs/examples/extensions/minimal-mode.ts +430 -0
  71. package/agent-docs/examples/extensions/modal-editor.ts +90 -0
  72. package/agent-docs/examples/extensions/model-status.ts +31 -0
  73. package/agent-docs/examples/extensions/notify.ts +55 -0
  74. package/agent-docs/examples/extensions/overlay-qa-tests.ts +936 -0
  75. package/agent-docs/examples/extensions/overlay-test.ts +159 -0
  76. package/agent-docs/examples/extensions/permission-gate.ts +37 -0
  77. package/agent-docs/examples/extensions/pirate.ts +47 -0
  78. package/agent-docs/examples/extensions/plan-mode/README.md +65 -0
  79. package/agent-docs/examples/extensions/plan-mode/index.ts +363 -0
  80. package/agent-docs/examples/extensions/plan-mode/utils.ts +173 -0
  81. package/agent-docs/examples/extensions/preset.ts +418 -0
  82. package/agent-docs/examples/extensions/protected-paths.ts +30 -0
  83. package/agent-docs/examples/extensions/qna.ts +122 -0
  84. package/agent-docs/examples/extensions/question.ts +278 -0
  85. package/agent-docs/examples/extensions/questionnaire.ts +440 -0
  86. package/agent-docs/examples/extensions/rainbow-editor.ts +90 -0
  87. package/agent-docs/examples/extensions/reload-runtime.ts +37 -0
  88. package/agent-docs/examples/extensions/rpc-demo.ts +124 -0
  89. package/agent-docs/examples/extensions/sandbox/index.ts +324 -0
  90. package/agent-docs/examples/extensions/sandbox/package-lock.json +92 -0
  91. package/agent-docs/examples/extensions/sandbox/package.json +19 -0
  92. package/agent-docs/examples/extensions/send-user-message.ts +97 -0
  93. package/agent-docs/examples/extensions/session-name.ts +27 -0
  94. package/agent-docs/examples/extensions/shutdown-command.ts +69 -0
  95. package/agent-docs/examples/extensions/snake.ts +343 -0
  96. package/agent-docs/examples/extensions/space-invaders.ts +566 -0
  97. package/agent-docs/examples/extensions/ssh.ts +233 -0
  98. package/agent-docs/examples/extensions/status-line.ts +40 -0
  99. package/agent-docs/examples/extensions/subagent/README.md +172 -0
  100. package/agent-docs/examples/extensions/subagent/agents/planner.md +37 -0
  101. package/agent-docs/examples/extensions/subagent/agents/reviewer.md +35 -0
  102. package/agent-docs/examples/extensions/subagent/agents/scout.md +50 -0
  103. package/agent-docs/examples/extensions/subagent/agents/worker.md +24 -0
  104. package/agent-docs/examples/extensions/subagent/agents.ts +130 -0
  105. package/agent-docs/examples/extensions/subagent/index.ts +1068 -0
  106. package/agent-docs/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  107. package/agent-docs/examples/extensions/subagent/prompts/implement.md +10 -0
  108. package/agent-docs/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  109. package/agent-docs/examples/extensions/summarize.ts +206 -0
  110. package/agent-docs/examples/extensions/system-prompt-header.ts +17 -0
  111. package/agent-docs/examples/extensions/timed-confirm.ts +72 -0
  112. package/agent-docs/examples/extensions/titlebar-spinner.ts +58 -0
  113. package/agent-docs/examples/extensions/todo.ts +314 -0
  114. package/agent-docs/examples/extensions/tool-override.ts +146 -0
  115. package/agent-docs/examples/extensions/tools.ts +145 -0
  116. package/agent-docs/examples/extensions/trigger-compact.ts +40 -0
  117. package/agent-docs/examples/extensions/truncated-tool.ts +194 -0
  118. package/agent-docs/examples/extensions/widget-placement.ts +17 -0
  119. package/agent-docs/examples/extensions/with-deps/index.ts +37 -0
  120. package/agent-docs/examples/extensions/with-deps/package-lock.json +31 -0
  121. package/agent-docs/examples/extensions/with-deps/package.json +22 -0
  122. package/agent-docs/examples/rpc-extension-ui.ts +654 -0
  123. package/agent-docs/examples/sdk/01-minimal.ts +22 -0
  124. package/agent-docs/examples/sdk/02-custom-model.ts +48 -0
  125. package/agent-docs/examples/sdk/03-custom-prompt.ts +55 -0
  126. package/agent-docs/examples/sdk/04-skills.ts +53 -0
  127. package/agent-docs/examples/sdk/05-tools.ts +56 -0
  128. package/agent-docs/examples/sdk/06-extensions.ts +88 -0
  129. package/agent-docs/examples/sdk/07-context-files.ts +40 -0
  130. package/agent-docs/examples/sdk/08-prompt-templates.ts +47 -0
  131. package/agent-docs/examples/sdk/09-api-keys-and-oauth.ts +48 -0
  132. package/agent-docs/examples/sdk/10-settings.ts +54 -0
  133. package/agent-docs/examples/sdk/11-sessions.ts +48 -0
  134. package/agent-docs/examples/sdk/12-full-control.ts +82 -0
  135. package/agent-docs/examples/sdk/README.md +144 -0
  136. package/agent-docs/xll-skill.md +61 -0
  137. package/agent-docs/xll-spec.md +110 -0
  138. package/dist/cli/args.js +290 -0
  139. package/dist/cli/config-selector.js +31 -0
  140. package/dist/cli/file-processor.js +79 -0
  141. package/dist/cli/list-models.js +92 -0
  142. package/dist/cli/package-commands.js +210 -0
  143. package/dist/cli/report-settings-errors.js +11 -0
  144. package/dist/cli/session-picker.js +34 -0
  145. package/dist/cli.js +19 -0
  146. package/dist/config.js +288 -0
  147. package/dist/core/abort.js +15 -0
  148. package/dist/core/agent-loop.js +352 -0
  149. package/dist/core/agent-session.js +2019 -0
  150. package/dist/core/agent.js +410 -0
  151. package/dist/core/auth-storage.js +456 -0
  152. package/dist/core/bash-executor.js +222 -0
  153. package/dist/core/compaction/branch-summarization.js +242 -0
  154. package/dist/core/compaction/compaction.js +610 -0
  155. package/dist/core/compaction/index.js +7 -0
  156. package/dist/core/compaction/utils.js +139 -0
  157. package/dist/core/defaults.js +6 -0
  158. package/dist/core/diagnostics.js +2 -0
  159. package/dist/core/event-bus.js +25 -0
  160. package/dist/core/exec.js +71 -0
  161. package/dist/core/export-html/ansi-to-html.js +256 -0
  162. package/dist/core/export-html/index.js +238 -0
  163. package/dist/core/export-html/session-view-model.js +342 -0
  164. package/dist/core/export-html/template.css +1110 -0
  165. package/dist/core/export-html/template.html +76 -0
  166. package/dist/core/export-html/template.js +1990 -0
  167. package/dist/core/export-html/tool-renderer.js +63 -0
  168. package/dist/core/export-html/vendor/highlight.min.js +7725 -0
  169. package/dist/core/export-html/vendor/marked.min.js +1803 -0
  170. package/dist/core/extensions/index.js +9 -0
  171. package/dist/core/extensions/loader.js +422 -0
  172. package/dist/core/extensions/runner.js +651 -0
  173. package/dist/core/extensions/types.js +35 -0
  174. package/dist/core/extensions/wrapper.js +102 -0
  175. package/dist/core/footer-data-provider.js +162 -0
  176. package/dist/core/index.js +9 -0
  177. package/dist/core/keybindings.js +153 -0
  178. package/dist/core/messages.js +133 -0
  179. package/dist/core/model-registry.js +539 -0
  180. package/dist/core/model-resolver.js +370 -0
  181. package/dist/core/package-manager.js +1485 -0
  182. package/dist/core/prompt-templates.js +253 -0
  183. package/dist/core/resolve-config-value.js +59 -0
  184. package/dist/core/resource-loader.js +700 -0
  185. package/dist/core/sdk.js +197 -0
  186. package/dist/core/session-bash.js +99 -0
  187. package/dist/core/session-compaction.js +165 -0
  188. package/dist/core/session-manager.js +1153 -0
  189. package/dist/core/session-models.js +99 -0
  190. package/dist/core/session-retry.js +155 -0
  191. package/dist/core/settings-manager.js +572 -0
  192. package/dist/core/skills.js +382 -0
  193. package/dist/core/slash-commands.js +31 -0
  194. package/dist/core/system-prompt.js +161 -0
  195. package/dist/core/theme.js +770 -0
  196. package/dist/core/timings.js +26 -0
  197. package/dist/core/tools/bash.js +258 -0
  198. package/dist/core/tools/edit-diff.js +245 -0
  199. package/dist/core/tools/edit.js +148 -0
  200. package/dist/core/tools/find.js +208 -0
  201. package/dist/core/tools/grep.js +246 -0
  202. package/dist/core/tools/index.js +67 -0
  203. package/dist/core/tools/ls.js +123 -0
  204. package/dist/core/tools/path-utils.js +81 -0
  205. package/dist/core/tools/read.js +160 -0
  206. package/dist/core/tools/truncate.js +70 -0
  207. package/dist/core/tools/write.js +82 -0
  208. package/dist/custom/agents/action.js +13 -0
  209. package/dist/custom/agents/document-reader.js +70 -0
  210. package/dist/custom/agents/general.js +26 -0
  211. package/dist/custom/agents/index.js +49 -0
  212. package/dist/custom/agents/installation.js +13 -0
  213. package/dist/custom/agents/types.js +7 -0
  214. package/dist/custom/auth/refresh-timer.js +33 -0
  215. package/dist/custom/auth/shortcut-oauth.js +145 -0
  216. package/dist/custom/constants.js +21 -0
  217. package/dist/custom/context/workbook-summary.js +73 -0
  218. package/dist/custom/credits/shortcut-credits.js +29 -0
  219. package/dist/custom/cron/cron-daemon-entry.js +18 -0
  220. package/dist/custom/cron/daemon-ipc.js +131 -0
  221. package/dist/custom/cron/daemon.js +224 -0
  222. package/dist/custom/cron/jobs.js +226 -0
  223. package/dist/custom/cron/run-log.js +51 -0
  224. package/dist/custom/cron/schedule.js +72 -0
  225. package/dist/custom/cron/status-line.js +98 -0
  226. package/dist/custom/cron/store.js +87 -0
  227. package/dist/custom/cron/types.js +8 -0
  228. package/dist/custom/dev/index.js +59 -0
  229. package/dist/custom/dev/trace-export.js +58 -0
  230. package/dist/custom/ensure-excel.js +63 -0
  231. package/dist/custom/excel-config.js +36 -0
  232. package/dist/custom/preflight.js +422 -0
  233. package/dist/custom/prompts/action.js +100 -0
  234. package/dist/custom/prompts/api.js +66 -0
  235. package/dist/custom/prompts/installation.js +124 -0
  236. package/dist/custom/prompts/shared.js +138 -0
  237. package/dist/custom/providers/llm-usage.js +42 -0
  238. package/dist/custom/providers/message-converter.js +74 -0
  239. package/dist/custom/providers/provider-ids.js +9 -0
  240. package/dist/custom/providers/register-openai-codex-provider.js +27 -0
  241. package/dist/custom/providers/register-shortcut-provider.js +52 -0
  242. package/dist/custom/providers/shortcut-invoke.js +117 -0
  243. package/dist/custom/providers/shortcut-stream.js +252 -0
  244. package/dist/custom/providers/sse-protocol.js +38 -0
  245. package/dist/custom/sync-xll.js +130 -0
  246. package/dist/custom/tools/cron.js +413 -0
  247. package/dist/custom/tools/excel-exec.js +167 -0
  248. package/dist/custom/tools/excel-range.js +50 -0
  249. package/dist/custom/tools/llm-analysis.js +265 -0
  250. package/dist/custom/tools/render-helpers.js +38 -0
  251. package/dist/custom/tools/switch-mode.js +94 -0
  252. package/dist/custom/tools/task/agents.js +6 -0
  253. package/dist/custom/tools/task/index.js +8 -0
  254. package/dist/custom/tools/task/render.js +348 -0
  255. package/dist/custom/tools/task/subprocess.js +320 -0
  256. package/dist/custom/tools/task/task.js +205 -0
  257. package/dist/custom/tools/todo-list.js +195 -0
  258. package/dist/custom/tracing/session-upload.js +93 -0
  259. package/dist/index.js +45 -0
  260. package/dist/main.js +613 -0
  261. package/dist/migrations.js +265 -0
  262. package/dist/modes/index.js +8 -0
  263. package/dist/modes/interactive/components/armin.js +337 -0
  264. package/dist/modes/interactive/components/assistant-message.js +94 -0
  265. package/dist/modes/interactive/components/bash-execution.js +171 -0
  266. package/dist/modes/interactive/components/bordered-loader.js +51 -0
  267. package/dist/modes/interactive/components/branch-summary-message.js +45 -0
  268. package/dist/modes/interactive/components/compaction-summary-message.js +46 -0
  269. package/dist/modes/interactive/components/config-selector.js +488 -0
  270. package/dist/modes/interactive/components/countdown-timer.js +33 -0
  271. package/dist/modes/interactive/components/custom-editor.js +93 -0
  272. package/dist/modes/interactive/components/custom-message.js +81 -0
  273. package/dist/modes/interactive/components/daxnuts.js +140 -0
  274. package/dist/modes/interactive/components/diff.js +133 -0
  275. package/dist/modes/interactive/components/dynamic-border.js +21 -0
  276. package/dist/modes/interactive/components/extension-editor.js +105 -0
  277. package/dist/modes/interactive/components/extension-input.js +61 -0
  278. package/dist/modes/interactive/components/extension-selector.js +78 -0
  279. package/dist/modes/interactive/components/footer.js +309 -0
  280. package/dist/modes/interactive/components/index.js +33 -0
  281. package/dist/modes/interactive/components/keybinding-hints.js +61 -0
  282. package/dist/modes/interactive/components/layout.js +64 -0
  283. package/dist/modes/interactive/components/login-dialog.js +148 -0
  284. package/dist/modes/interactive/components/model-selector.js +237 -0
  285. package/dist/modes/interactive/components/oauth-selector.js +111 -0
  286. package/dist/modes/interactive/components/session-selector-search.js +157 -0
  287. package/dist/modes/interactive/components/session-selector.js +860 -0
  288. package/dist/modes/interactive/components/settings-selector.js +123 -0
  289. package/dist/modes/interactive/components/show-images-selector.js +35 -0
  290. package/dist/modes/interactive/components/skill-invocation-message.js +48 -0
  291. package/dist/modes/interactive/components/theme-selector.js +47 -0
  292. package/dist/modes/interactive/components/thinking-selector.js +47 -0
  293. package/dist/modes/interactive/components/tool-execution.js +789 -0
  294. package/dist/modes/interactive/components/tool-group.js +106 -0
  295. package/dist/modes/interactive/components/tree-selector.js +962 -0
  296. package/dist/modes/interactive/components/user-message-selector.js +115 -0
  297. package/dist/modes/interactive/components/user-message.js +48 -0
  298. package/dist/modes/interactive/components/visual-truncate.js +33 -0
  299. package/dist/modes/interactive/file-attachments.js +135 -0
  300. package/dist/modes/interactive/interactive-mode.js +3775 -0
  301. package/dist/modes/interactive/theme/dark.json +85 -0
  302. package/dist/modes/interactive/theme/light.json +85 -0
  303. package/dist/modes/interactive/theme/theme-schema.json +335 -0
  304. package/dist/modes/interactive/theme/theme.js +177 -0
  305. package/dist/modes/print-mode.js +101 -0
  306. package/dist/modes/rpc/rpc-client.js +387 -0
  307. package/dist/modes/rpc/rpc-mode.js +509 -0
  308. package/dist/modes/rpc/rpc-types.js +8 -0
  309. package/dist/subagent-entry.js +145 -0
  310. package/dist/tool-names.js +34 -0
  311. package/dist/tui/autocomplete.js +596 -0
  312. package/dist/tui/components/box.js +104 -0
  313. package/dist/tui/components/cancellable-loader.js +35 -0
  314. package/dist/tui/components/editor.js +1679 -0
  315. package/dist/tui/components/image.js +69 -0
  316. package/dist/tui/components/input.js +433 -0
  317. package/dist/tui/components/loader.js +49 -0
  318. package/dist/tui/components/markdown.js +629 -0
  319. package/dist/tui/components/select-list.js +152 -0
  320. package/dist/tui/components/settings-list.js +185 -0
  321. package/dist/tui/components/spacer.js +23 -0
  322. package/dist/tui/components/text.js +89 -0
  323. package/dist/tui/components/truncated-text.js +51 -0
  324. package/dist/tui/editor-component.js +2 -0
  325. package/dist/tui/fuzzy.js +107 -0
  326. package/dist/tui/get-east-asian-width/index.js +32 -0
  327. package/dist/tui/get-east-asian-width/lookup.js +404 -0
  328. package/dist/tui/index.js +32 -0
  329. package/dist/tui/keybindings.js +114 -0
  330. package/dist/tui/keys.js +959 -0
  331. package/dist/tui/kill-ring.js +44 -0
  332. package/dist/tui/stdin-buffer.js +317 -0
  333. package/dist/tui/terminal-image.js +288 -0
  334. package/dist/tui/terminal.js +249 -0
  335. package/dist/tui/tui/autocomplete.js +596 -0
  336. package/dist/tui/tui/components/box.js +106 -0
  337. package/dist/tui/tui/components/cancellable-loader.js +35 -0
  338. package/dist/tui/tui/components/editor.js +1679 -0
  339. package/dist/tui/tui/components/image.js +69 -0
  340. package/dist/tui/tui/components/input.js +433 -0
  341. package/dist/tui/tui/components/loader.js +49 -0
  342. package/dist/tui/tui/components/markdown.js +629 -0
  343. package/dist/tui/tui/components/select-list.js +152 -0
  344. package/dist/tui/tui/components/settings-list.js +185 -0
  345. package/dist/tui/tui/components/spacer.js +23 -0
  346. package/dist/tui/tui/components/text.js +91 -0
  347. package/dist/tui/tui/components/truncated-text.js +51 -0
  348. package/dist/tui/tui/editor-component.js +2 -0
  349. package/dist/tui/tui/fuzzy.js +107 -0
  350. package/dist/tui/tui/get-east-asian-width/index.js +32 -0
  351. package/dist/tui/tui/get-east-asian-width/lookup.js +404 -0
  352. package/dist/tui/tui/index.js +32 -0
  353. package/dist/tui/tui/keybindings.js +114 -0
  354. package/dist/tui/tui/keys.js +959 -0
  355. package/dist/tui/tui/kill-ring.js +44 -0
  356. package/dist/tui/tui/stdin-buffer.js +317 -0
  357. package/dist/tui/tui/terminal-image.js +288 -0
  358. package/dist/tui/tui/terminal.js +249 -0
  359. package/dist/tui/tui/tui.js +955 -0
  360. package/dist/tui/tui/undo-stack.js +25 -0
  361. package/dist/tui/tui/utils.js +800 -0
  362. package/dist/tui/tui.js +955 -0
  363. package/dist/tui/undo-stack.js +25 -0
  364. package/dist/tui/utils.js +800 -0
  365. package/dist/utils/changelog.js +87 -0
  366. package/dist/utils/clipboard-image.js +164 -0
  367. package/dist/utils/clipboard-native.js +14 -0
  368. package/dist/utils/clipboard.js +67 -0
  369. package/dist/utils/frontmatter.js +26 -0
  370. package/dist/utils/git.js +166 -0
  371. package/dist/utils/image-convert.js +35 -0
  372. package/dist/utils/image-resize.js +183 -0
  373. package/dist/utils/mime.js +26 -0
  374. package/dist/utils/photon.js +121 -0
  375. package/dist/utils/shell.js +217 -0
  376. package/dist/utils/sleep.js +17 -0
  377. package/dist/utils/tools-manager.js +259 -0
  378. package/package.json +78 -0
  379. package/skills/excel-com-api/SKILL.md +74 -0
  380. package/skills/excel-com-api/excel-type-library.py +27767 -0
  381. package/skills/excel-com-api/office-type-library.py +10867 -0
  382. package/skills/integrations/SKILL.md +138 -0
  383. package/skills/integrations/alphasense.md +457 -0
  384. package/skills/integrations/bloomberg.md +803 -0
  385. package/skills/integrations/calcbench.md +315 -0
  386. package/skills/integrations/capiq.md +848 -0
  387. package/skills/integrations/dynamics-365-finance.md +354 -0
  388. package/skills/integrations/earnings_transcripts.md +387 -0
  389. package/skills/integrations/factset.md +758 -0
  390. package/skills/integrations/ice-fixed-income.md +344 -0
  391. package/skills/integrations/moodys-analytics.md +313 -0
  392. package/skills/integrations/morningstar.md +433 -0
  393. package/skills/integrations/nasdaq-data-link.md +249 -0
  394. package/skills/integrations/pitchbook.md +413 -0
  395. package/skills/integrations/preqin.md +422 -0
  396. package/skills/integrations/quickbooks.md +289 -0
  397. package/skills/integrations/quickfs.md +314 -0
  398. package/skills/integrations/refinitiv.md +473 -0
  399. package/skills/integrations/sage-intacct.md +401 -0
  400. package/skills/integrations/visible-alpha.md +320 -0
  401. package/skills/integrations/xero.md +393 -0
  402. package/skills/integrations/ycharts.md +306 -0
  403. package/skills/pdf-creation/SKILL.md +93 -0
  404. package/skills/pdf-extraction/SKILL.md +32 -0
  405. package/skills/powerpoint-creation/SKILL.md +110 -0
  406. package/skills/sec-edgar/SKILL.md +127 -0
  407. package/skills/sec-edgar/sec_to_pdf.py +109 -0
  408. package/xll/ShortcutXL.xll +0 -0
  409. package/xll/modules/debug_render.py +272 -0
  410. package/xll/modules/gameboy.py +241 -0
  411. package/xll/modules/pong.py +188 -0
  412. package/xll/modules/shortcut_xl/__init__.py +18 -0
  413. package/xll/modules/shortcut_xl/_categorize.py +200 -0
  414. package/xll/modules/shortcut_xl/_com.py +108 -0
  415. package/xll/modules/shortcut_xl/_format.py +252 -0
  416. package/xll/modules/shortcut_xl/_log.py +12 -0
  417. package/xll/modules/shortcut_xl/_managed.py +116 -0
  418. package/xll/modules/shortcut_xl/_registry.py +44 -0
  419. package/xll/modules/shortcut_xl/_threading.py +161 -0
  420. package/xll/modules/shortcut_xl/_tracking.py +283 -0
  421. package/xll/modules/stocks.py +100 -0
  422. package/xll/python3.dll +0 -0
  423. package/xll/python312.dll +0 -0
@@ -0,0 +1,789 @@
1
+ import { Box, Container, getCapabilities, getImageDimensions, Image, imageFallback, Spacer, Text } from '../../../tui/index.js';
2
+ import * as os from 'node:os';
3
+ import stripAnsi from 'strip-ansi';
4
+ import { theme } from '../../../core/theme.js';
5
+ import { computeEditDiff } from '../../../core/tools/edit-diff.js';
6
+ import { allTools } from '../../../core/tools/index.js';
7
+ import { formatSize } from '../../../core/tools/truncate.js';
8
+ import { convertToPng } from '../../../utils/image-convert.js';
9
+ import { sanitizeBinaryOutput } from '../../../utils/shell.js';
10
+ import { getLanguageFromPath, highlightCode } from '../theme/theme.js';
11
+ import { renderDiff } from './diff.js';
12
+ import { PREFIX_WIDTH, prefixLines, toolPrefix } from './layout.js';
13
+ // During partial write tool-call streaming, re-highlight the first N lines fully
14
+ // to keep multiline tokenization mostly correct without re-highlighting the full file.
15
+ const WRITE_PARTIAL_FULL_HIGHLIGHT_LINES = 50;
16
+ /**
17
+ * Convert absolute path to tilde notation if it's in home directory
18
+ */
19
+ function shortenPath(path) {
20
+ if (typeof path !== 'string')
21
+ return '';
22
+ const home = os.homedir();
23
+ if (path.startsWith(home)) {
24
+ return `~${path.slice(home.length)}`;
25
+ }
26
+ return path;
27
+ }
28
+ /**
29
+ * Replace tabs with spaces for consistent rendering
30
+ */
31
+ function replaceTabs(text) {
32
+ return text.replace(/\t/g, ' ');
33
+ }
34
+ /** Safely coerce value to string for display. Returns null if invalid type. */
35
+ function str(value) {
36
+ if (typeof value === 'string')
37
+ return value;
38
+ if (value == null)
39
+ return '';
40
+ return null; // Invalid type
41
+ }
42
+ /**
43
+ * Component that renders a tool call with its result (updateable)
44
+ */
45
+ export class ToolExecutionComponent extends Container {
46
+ contentBox; // Used for custom tools and bash visual truncation
47
+ contentText; // For built-in tools (with its own padding/bg)
48
+ imageComponents = [];
49
+ imageSpacers = [];
50
+ toolName;
51
+ args;
52
+ expanded = false;
53
+ showImages;
54
+ isPartial = true;
55
+ toolDefinition;
56
+ ui;
57
+ cwd;
58
+ result;
59
+ // Cached edit diff preview (computed when args arrive, before tool executes)
60
+ editDiffPreview;
61
+ editDiffArgsKey; // Track which args the preview is for
62
+ // Cached converted images for Kitty protocol (which requires PNG), keyed by index
63
+ convertedImages = new Map();
64
+ // Incremental syntax highlighting cache for write tool call args
65
+ writeHighlightCache;
66
+ // When true, this component intentionally renders no lines
67
+ hideComponent = false;
68
+ // When true, this component is part of a ToolGroupComponent and renders 0 lines
69
+ grouped = false;
70
+ // Blink state for the status dot prefix
71
+ blinkOn = true;
72
+ blinkTimer;
73
+ /** Callback invoked when this component's state changes, so the group can re-render */
74
+ onGroupUpdate;
75
+ constructor(toolName, args, options = {}, toolDefinition, ui, cwd = process.cwd()) {
76
+ super();
77
+ this.toolName = toolName;
78
+ this.args = args;
79
+ this.showImages = options.showImages ?? true;
80
+ this.toolDefinition = toolDefinition;
81
+ this.ui = ui;
82
+ this.cwd = cwd;
83
+ this.addChild(new Spacer(1));
84
+ // Always create both - contentBox for custom tools/bash, contentText for other built-ins
85
+ this.contentBox = new Box(0, 0);
86
+ this.contentText = new Text('', 0, 0);
87
+ // Use contentBox for bash (visual truncation) or custom tools with custom renderers
88
+ // Use contentText for built-in tools (including overrides without custom renderers)
89
+ if (toolName === 'bash' || (toolDefinition && !this.shouldUseBuiltInRenderer())) {
90
+ this.addChild(this.contentBox);
91
+ }
92
+ else {
93
+ this.addChild(this.contentText);
94
+ }
95
+ this.blinkTimer = setInterval(() => {
96
+ this.blinkOn = !this.blinkOn;
97
+ ui.requestRender();
98
+ }, 500);
99
+ this.updateDisplay();
100
+ }
101
+ /**
102
+ * Check if we should use built-in rendering for this tool.
103
+ * Returns true if the tool name is a built-in AND either there's no toolDefinition
104
+ * or the toolDefinition doesn't provide custom renderers.
105
+ */
106
+ shouldUseBuiltInRenderer() {
107
+ const isBuiltInName = this.toolName in allTools;
108
+ const hasCustomRenderers = this.toolDefinition?.renderCall || this.toolDefinition?.renderResult;
109
+ return isBuiltInName && !hasCustomRenderers;
110
+ }
111
+ updateArgs(args) {
112
+ this.args = args;
113
+ if (this.toolName === 'write' && this.isPartial) {
114
+ this.updateWriteHighlightCacheIncremental();
115
+ }
116
+ this.updateDisplay();
117
+ this.onGroupUpdate?.();
118
+ }
119
+ highlightSingleLine(line, lang) {
120
+ const highlighted = highlightCode(line, lang);
121
+ return highlighted[0] ?? '';
122
+ }
123
+ refreshWriteHighlightPrefix(cache) {
124
+ const prefixCount = Math.min(WRITE_PARTIAL_FULL_HIGHLIGHT_LINES, cache.normalizedLines.length);
125
+ if (prefixCount === 0)
126
+ return;
127
+ const prefixSource = cache.normalizedLines.slice(0, prefixCount).join('\n');
128
+ const prefixHighlighted = highlightCode(prefixSource, cache.lang);
129
+ for (let i = 0; i < prefixCount; i++) {
130
+ cache.highlightedLines[i] =
131
+ prefixHighlighted[i] ??
132
+ this.highlightSingleLine(cache.normalizedLines[i] ?? '', cache.lang);
133
+ }
134
+ }
135
+ rebuildWriteHighlightCacheFull(rawPath, fileContent) {
136
+ const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
137
+ if (!lang) {
138
+ this.writeHighlightCache = undefined;
139
+ return;
140
+ }
141
+ const normalized = replaceTabs(fileContent);
142
+ this.writeHighlightCache = {
143
+ rawPath,
144
+ lang,
145
+ rawContent: fileContent,
146
+ normalizedLines: normalized.split('\n'),
147
+ highlightedLines: highlightCode(normalized, lang)
148
+ };
149
+ }
150
+ updateWriteHighlightCacheIncremental() {
151
+ const rawPath = str(this.args?.file_path ?? this.args?.path);
152
+ const fileContent = str(this.args?.content);
153
+ if (rawPath === null || fileContent === null) {
154
+ this.writeHighlightCache = undefined;
155
+ return;
156
+ }
157
+ const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
158
+ if (!lang) {
159
+ this.writeHighlightCache = undefined;
160
+ return;
161
+ }
162
+ if (!this.writeHighlightCache) {
163
+ this.rebuildWriteHighlightCacheFull(rawPath, fileContent);
164
+ return;
165
+ }
166
+ const cache = this.writeHighlightCache;
167
+ if (cache.lang !== lang || cache.rawPath !== rawPath) {
168
+ this.rebuildWriteHighlightCacheFull(rawPath, fileContent);
169
+ return;
170
+ }
171
+ if (!fileContent.startsWith(cache.rawContent)) {
172
+ this.rebuildWriteHighlightCacheFull(rawPath, fileContent);
173
+ return;
174
+ }
175
+ if (fileContent.length === cache.rawContent.length) {
176
+ return;
177
+ }
178
+ const deltaRaw = fileContent.slice(cache.rawContent.length);
179
+ const deltaNormalized = replaceTabs(deltaRaw);
180
+ cache.rawContent = fileContent;
181
+ if (cache.normalizedLines.length === 0) {
182
+ cache.normalizedLines.push('');
183
+ cache.highlightedLines.push('');
184
+ }
185
+ const segments = deltaNormalized.split('\n');
186
+ const lastIndex = cache.normalizedLines.length - 1;
187
+ cache.normalizedLines[lastIndex] += segments[0];
188
+ cache.highlightedLines[lastIndex] = this.highlightSingleLine(cache.normalizedLines[lastIndex], cache.lang);
189
+ for (let i = 1; i < segments.length; i++) {
190
+ cache.normalizedLines.push(segments[i]);
191
+ cache.highlightedLines.push(this.highlightSingleLine(segments[i], cache.lang));
192
+ }
193
+ this.refreshWriteHighlightPrefix(cache);
194
+ }
195
+ /**
196
+ * Signal that args are complete (tool is about to execute).
197
+ * This triggers diff computation for edit tool.
198
+ */
199
+ setArgsComplete() {
200
+ if (this.toolName === 'write') {
201
+ const rawPath = str(this.args?.file_path ?? this.args?.path);
202
+ const fileContent = str(this.args?.content);
203
+ if (rawPath !== null && fileContent !== null) {
204
+ this.rebuildWriteHighlightCacheFull(rawPath, fileContent);
205
+ }
206
+ }
207
+ this.maybeComputeEditDiff();
208
+ }
209
+ /**
210
+ * Compute edit diff preview when we have complete args.
211
+ * This runs async and updates display when done.
212
+ */
213
+ maybeComputeEditDiff() {
214
+ if (this.toolName !== 'edit')
215
+ return;
216
+ const path = this.args?.path;
217
+ const oldText = this.args?.oldText;
218
+ const newText = this.args?.newText;
219
+ // Need all three params to compute diff
220
+ if (!path || oldText === undefined || newText === undefined)
221
+ return;
222
+ // Create a key to track which args this computation is for
223
+ const argsKey = JSON.stringify({ path, oldText, newText });
224
+ // Skip if we already computed for these exact args
225
+ if (this.editDiffArgsKey === argsKey)
226
+ return;
227
+ this.editDiffArgsKey = argsKey;
228
+ // Compute diff async
229
+ computeEditDiff(path, oldText, newText, this.cwd).then((result) => {
230
+ // Only update if args haven't changed since we started
231
+ if (this.editDiffArgsKey === argsKey) {
232
+ this.editDiffPreview = result;
233
+ this.updateDisplay();
234
+ this.ui.requestRender();
235
+ }
236
+ });
237
+ }
238
+ updateResult(result, isPartial = false) {
239
+ this.result = result;
240
+ this.isPartial = isPartial;
241
+ if (!isPartial) {
242
+ this.stopBlink();
243
+ }
244
+ if (this.toolName === 'write' && !isPartial) {
245
+ const rawPath = str(this.args?.file_path ?? this.args?.path);
246
+ const fileContent = str(this.args?.content);
247
+ if (rawPath !== null && fileContent !== null) {
248
+ this.rebuildWriteHighlightCacheFull(rawPath, fileContent);
249
+ }
250
+ }
251
+ this.updateDisplay();
252
+ // Convert non-PNG images to PNG for Kitty protocol (async)
253
+ this.maybeConvertImagesForKitty();
254
+ this.onGroupUpdate?.();
255
+ }
256
+ /**
257
+ * Convert non-PNG images to PNG for Kitty graphics protocol.
258
+ * Kitty requires PNG format (f=100), so JPEG/GIF/WebP won't display.
259
+ */
260
+ maybeConvertImagesForKitty() {
261
+ const caps = getCapabilities();
262
+ // Only needed for Kitty protocol
263
+ if (caps.images !== 'kitty')
264
+ return;
265
+ if (!this.result)
266
+ return;
267
+ const imageBlocks = this.result.content?.filter((c) => c.type === 'image') || [];
268
+ for (let i = 0; i < imageBlocks.length; i++) {
269
+ const img = imageBlocks[i];
270
+ if (!img.data || !img.mimeType)
271
+ continue;
272
+ // Skip if already PNG or already converted
273
+ if (img.mimeType === 'image/png')
274
+ continue;
275
+ if (this.convertedImages.has(i))
276
+ continue;
277
+ // Convert async
278
+ const index = i;
279
+ convertToPng(img.data, img.mimeType).then((converted) => {
280
+ if (converted) {
281
+ this.convertedImages.set(index, converted);
282
+ this.updateDisplay();
283
+ this.ui.requestRender();
284
+ }
285
+ });
286
+ }
287
+ }
288
+ /** Mark this component as grouped — it will render 0 lines, deferring to the group. */
289
+ setGrouped(grouped) {
290
+ this.grouped = grouped;
291
+ }
292
+ /** Public read access to args (for group rendering) */
293
+ getArgs() {
294
+ return this.args;
295
+ }
296
+ /** Public read access to result (for group rendering) */
297
+ getResult() {
298
+ return this.result;
299
+ }
300
+ /** Public read access to partial state (for group rendering) */
301
+ getIsPartial() {
302
+ return this.isPartial;
303
+ }
304
+ setExpanded(expanded) {
305
+ this.expanded = expanded;
306
+ this.updateDisplay();
307
+ }
308
+ setShowImages(show) {
309
+ this.showImages = show;
310
+ this.updateDisplay();
311
+ }
312
+ invalidate() {
313
+ super.invalidate();
314
+ this.updateDisplay();
315
+ }
316
+ render(width) {
317
+ if (this.hideComponent || this.grouped) {
318
+ return [];
319
+ }
320
+ const prefix = toolPrefix(this.isPartial, !!this.result?.isError, this.blinkOn);
321
+ return prefixLines(super.render(width - PREFIX_WIDTH), prefix);
322
+ }
323
+ stopBlink() {
324
+ if (this.blinkTimer) {
325
+ clearInterval(this.blinkTimer);
326
+ this.blinkTimer = undefined;
327
+ this.blinkOn = true;
328
+ }
329
+ }
330
+ updateDisplay() {
331
+ const useBuiltInRenderer = this.shouldUseBuiltInRenderer();
332
+ let customRendererHasContent = false;
333
+ this.hideComponent = false;
334
+ // Use built-in rendering for built-in tools (or overrides without custom renderers)
335
+ if (useBuiltInRenderer) {
336
+ if (this.toolName === 'bash') {
337
+ // Bash uses Box with visual line truncation
338
+ this.contentBox.clear();
339
+ this.renderBashContent();
340
+ }
341
+ else {
342
+ // Other built-in tools: use Text directly with caching
343
+ this.contentText.setText(this.formatToolExecution());
344
+ }
345
+ }
346
+ else if (this.toolDefinition) {
347
+ // Custom tools use Box for flexible component rendering
348
+ this.contentBox.clear();
349
+ // Render call component
350
+ if (this.toolDefinition.renderCall) {
351
+ try {
352
+ const callComponent = this.toolDefinition.renderCall(this.args, { expanded: this.expanded, isPartial: this.isPartial }, theme);
353
+ if (callComponent !== undefined) {
354
+ this.contentBox.addChild(callComponent);
355
+ customRendererHasContent = true;
356
+ }
357
+ }
358
+ catch {
359
+ // Fall back to default on error
360
+ this.contentBox.addChild(new Text(theme.fg('toolTitle', theme.bold(this.toolName)), 0, 0));
361
+ customRendererHasContent = true;
362
+ }
363
+ }
364
+ else {
365
+ // No custom renderCall, show tool name
366
+ this.contentBox.addChild(new Text(theme.fg('toolTitle', theme.bold(this.toolName)), 0, 0));
367
+ customRendererHasContent = true;
368
+ }
369
+ // Render result component if we have a result
370
+ if (this.result && this.toolDefinition.renderResult) {
371
+ try {
372
+ const resultComponent = this.toolDefinition.renderResult({ content: this.result.content, details: this.result.details }, { expanded: this.expanded, isPartial: this.isPartial }, theme);
373
+ if (resultComponent !== undefined) {
374
+ this.contentBox.addChild(resultComponent);
375
+ customRendererHasContent = true;
376
+ }
377
+ }
378
+ catch {
379
+ // Fall back to showing raw output on error
380
+ const output = this.getTextOutput();
381
+ if (output) {
382
+ this.contentBox.addChild(new Text(theme.fg('toolOutput', output), 0, 0));
383
+ customRendererHasContent = true;
384
+ }
385
+ }
386
+ }
387
+ else if (this.result) {
388
+ // Has result but no custom renderResult
389
+ const output = this.getTextOutput();
390
+ if (output) {
391
+ this.contentBox.addChild(new Text(theme.fg('toolOutput', output), 0, 0));
392
+ customRendererHasContent = true;
393
+ }
394
+ }
395
+ }
396
+ else {
397
+ // Unknown tool with no registered definition - show generic fallback
398
+ this.contentText.setText(this.formatToolExecution());
399
+ }
400
+ // Handle images (same for both custom and built-in)
401
+ for (const img of this.imageComponents) {
402
+ this.removeChild(img);
403
+ }
404
+ this.imageComponents = [];
405
+ for (const spacer of this.imageSpacers) {
406
+ this.removeChild(spacer);
407
+ }
408
+ this.imageSpacers = [];
409
+ if (this.result) {
410
+ const imageBlocks = this.result.content?.filter((c) => c.type === 'image') || [];
411
+ const caps = getCapabilities();
412
+ for (let i = 0; i < imageBlocks.length; i++) {
413
+ const img = imageBlocks[i];
414
+ if (caps.images && this.showImages && img.data && img.mimeType) {
415
+ // Use converted PNG for Kitty protocol if available
416
+ const converted = this.convertedImages.get(i);
417
+ const imageData = converted?.data ?? img.data;
418
+ const imageMimeType = converted?.mimeType ?? img.mimeType;
419
+ // For Kitty, skip non-PNG images that haven't been converted yet
420
+ if (caps.images === 'kitty' && imageMimeType !== 'image/png') {
421
+ continue;
422
+ }
423
+ const spacer = new Spacer(1);
424
+ this.addChild(spacer);
425
+ this.imageSpacers.push(spacer);
426
+ const imageComponent = new Image(imageData, imageMimeType, { fallbackColor: (s) => theme.fg('toolOutput', s) }, { maxWidthCells: 60 });
427
+ this.imageComponents.push(imageComponent);
428
+ this.addChild(imageComponent);
429
+ }
430
+ }
431
+ }
432
+ if (!useBuiltInRenderer && this.toolDefinition) {
433
+ this.hideComponent = !customRendererHasContent && this.imageComponents.length === 0;
434
+ }
435
+ }
436
+ /**
437
+ * Render bash content using visual line truncation (like bash-execution.ts)
438
+ */
439
+ renderBashContent() {
440
+ const command = str(this.args?.command);
441
+ const description = str(this.args?.description);
442
+ const timeout = this.args?.timeout;
443
+ // Header: collapsed shows description, expanded shows command
444
+ const timeoutSuffix = timeout ? theme.fg('muted', ` (timeout ${timeout}s)`) : '';
445
+ if (this.expanded) {
446
+ const commandDisplay = command === null
447
+ ? theme.fg('error', '[invalid arg]')
448
+ : command
449
+ ? command
450
+ : theme.fg('toolOutput', '...');
451
+ this.contentBox.addChild(new Text(theme.fg('toolTitle', theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix, 0, 0));
452
+ }
453
+ else {
454
+ const headerText = description || command || '...';
455
+ this.contentBox.addChild(new Text(theme.fg('toolTitle', theme.bold(`$ ${headerText}`)) + timeoutSuffix, 0, 0));
456
+ }
457
+ if (this.result) {
458
+ const output = this.getTextOutput().trim();
459
+ if (output && this.expanded) {
460
+ // Style each line for the output
461
+ const styledOutput = output
462
+ .split('\n')
463
+ .map((line) => theme.fg('toolOutput', line))
464
+ .join('\n');
465
+ // Show all lines when expanded
466
+ this.contentBox.addChild(new Text(`\n${styledOutput}`, 0, 0));
467
+ }
468
+ // Truncation warnings
469
+ const truncation = this.result.details?.truncation;
470
+ const fullOutputPath = this.result.details?.fullOutputPath;
471
+ if (truncation?.truncated || fullOutputPath) {
472
+ const warnings = [];
473
+ if (fullOutputPath) {
474
+ warnings.push(`Full output: ${fullOutputPath}`);
475
+ }
476
+ if (truncation?.truncated) {
477
+ warnings.push(`Truncated: showing ${formatSize(truncation.outputChars)} of ${formatSize(truncation.totalChars)}`);
478
+ }
479
+ this.contentBox.addChild(new Text(`\n${theme.fg('warning', `[${warnings.join('. ')}]`)}`, 0, 0));
480
+ }
481
+ }
482
+ }
483
+ getTextOutput() {
484
+ if (!this.result)
485
+ return '';
486
+ const textBlocks = this.result.content?.filter((c) => c.type === 'text') || [];
487
+ const imageBlocks = this.result.content?.filter((c) => c.type === 'image') || [];
488
+ let output = textBlocks
489
+ .map((c) => {
490
+ // Use sanitizeBinaryOutput to handle binary data that crashes string-width
491
+ return sanitizeBinaryOutput(stripAnsi(c.text || '')).replace(/\r/g, '');
492
+ })
493
+ .join('\n');
494
+ const caps = getCapabilities();
495
+ if (imageBlocks.length > 0 && (!caps.images || !this.showImages)) {
496
+ const imageIndicators = imageBlocks
497
+ .map((img) => {
498
+ const dims = img.data
499
+ ? (getImageDimensions(img.data, img.mimeType) ?? undefined)
500
+ : undefined;
501
+ return imageFallback(img.mimeType, dims);
502
+ })
503
+ .join('\n');
504
+ output = output ? `${output}\n${imageIndicators}` : imageIndicators;
505
+ }
506
+ return output;
507
+ }
508
+ formatToolExecution() {
509
+ let text = '';
510
+ const invalidArg = theme.fg('error', '[invalid arg]');
511
+ if (this.toolName === 'read') {
512
+ const rawPath = str(this.args?.file_path ?? this.args?.path);
513
+ const path = rawPath !== null ? shortenPath(rawPath) : null;
514
+ const offset = this.args?.offset;
515
+ const limit = this.args?.limit;
516
+ let pathDisplay = path === null
517
+ ? invalidArg
518
+ : path
519
+ ? theme.fg('accent', path)
520
+ : theme.fg('toolOutput', '...');
521
+ if (offset !== undefined || limit !== undefined) {
522
+ const startLine = offset ?? 1;
523
+ const endLine = limit !== undefined ? startLine + limit - 1 : '';
524
+ pathDisplay += theme.fg('warning', `:${startLine}${endLine ? `-${endLine}` : ''}`);
525
+ }
526
+ text = `${theme.fg('toolTitle', theme.bold('read'))} ${pathDisplay}`;
527
+ if (this.result && this.expanded) {
528
+ const output = this.getTextOutput();
529
+ const rawPath = str(this.args?.file_path ?? this.args?.path);
530
+ const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
531
+ const lines = lang ? highlightCode(replaceTabs(output), lang) : output.split('\n');
532
+ if (lines.length > 0) {
533
+ text +=
534
+ '\n\n' +
535
+ lines
536
+ .map((line) => lang ? replaceTabs(line) : theme.fg('toolOutput', replaceTabs(line)))
537
+ .join('\n');
538
+ }
539
+ const truncation = this.result.details?.truncation;
540
+ if (truncation?.truncated) {
541
+ text +=
542
+ '\n' +
543
+ theme.fg('warning', `[Truncated: showing ${formatSize(truncation.outputChars)} of ${formatSize(truncation.totalChars)}]`);
544
+ }
545
+ }
546
+ }
547
+ else if (this.toolName === 'write') {
548
+ const rawPath = str(this.args?.file_path ?? this.args?.path);
549
+ const fileContent = str(this.args?.content);
550
+ const path = rawPath !== null ? shortenPath(rawPath) : null;
551
+ text =
552
+ theme.fg('toolTitle', theme.bold('write')) +
553
+ ' ' +
554
+ (path === null
555
+ ? invalidArg
556
+ : path
557
+ ? theme.fg('accent', path)
558
+ : theme.fg('toolOutput', '...'));
559
+ if (fileContent === null) {
560
+ text += `\n\n${theme.fg('error', '[invalid content arg - expected string]')}`;
561
+ }
562
+ else if (fileContent) {
563
+ const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
564
+ let lines;
565
+ if (lang) {
566
+ const cache = this.writeHighlightCache;
567
+ if (cache &&
568
+ cache.lang === lang &&
569
+ cache.rawPath === rawPath &&
570
+ cache.rawContent === fileContent) {
571
+ lines = cache.highlightedLines;
572
+ }
573
+ else {
574
+ const normalized = replaceTabs(fileContent);
575
+ lines = highlightCode(normalized, lang);
576
+ this.writeHighlightCache = {
577
+ rawPath,
578
+ lang,
579
+ rawContent: fileContent,
580
+ normalizedLines: normalized.split('\n'),
581
+ highlightedLines: lines
582
+ };
583
+ }
584
+ }
585
+ else {
586
+ lines = fileContent.split('\n');
587
+ this.writeHighlightCache = undefined;
588
+ }
589
+ const totalLines = lines.length;
590
+ const maxLines = this.expanded ? lines.length : 10;
591
+ const displayLines = lines.slice(0, maxLines);
592
+ const remaining = lines.length - maxLines;
593
+ text +=
594
+ '\n\n' +
595
+ displayLines
596
+ .map((line) => (lang ? line : theme.fg('toolOutput', replaceTabs(line))))
597
+ .join('\n');
598
+ if (remaining > 0) {
599
+ text += theme.fg('muted', `\n... (${remaining} more lines, ${totalLines} total)`);
600
+ }
601
+ }
602
+ // Show error if tool execution failed
603
+ if (this.result?.isError) {
604
+ const errorText = this.getTextOutput();
605
+ if (errorText) {
606
+ text += `\n\n${theme.fg('error', errorText)}`;
607
+ }
608
+ }
609
+ }
610
+ else if (this.toolName === 'edit') {
611
+ const rawPath = str(this.args?.file_path ?? this.args?.path);
612
+ const path = rawPath !== null ? shortenPath(rawPath) : null;
613
+ // Build path display, appending :line if we have diff info
614
+ let pathDisplay = path === null
615
+ ? invalidArg
616
+ : path
617
+ ? theme.fg('accent', path)
618
+ : theme.fg('toolOutput', '...');
619
+ const firstChangedLine = (this.editDiffPreview && 'firstChangedLine' in this.editDiffPreview
620
+ ? this.editDiffPreview.firstChangedLine
621
+ : undefined) ||
622
+ (this.result && !this.result.isError ? this.result.details?.firstChangedLine : undefined);
623
+ if (firstChangedLine) {
624
+ pathDisplay += theme.fg('warning', `:${firstChangedLine}`);
625
+ }
626
+ text = `${theme.fg('toolTitle', theme.bold('edit'))} ${pathDisplay}`;
627
+ if (this.result?.isError) {
628
+ // Show error from result
629
+ const errorText = this.getTextOutput();
630
+ if (errorText) {
631
+ text += `\n\n${theme.fg('error', errorText)}`;
632
+ }
633
+ }
634
+ else if (this.expanded) {
635
+ // Only show diff when expanded
636
+ if (this.result?.details?.diff) {
637
+ const diffText = renderDiff(this.result.details.diff, { filePath: rawPath ?? undefined });
638
+ text += `\n\n${diffText}`;
639
+ }
640
+ else if (this.editDiffPreview) {
641
+ if ('error' in this.editDiffPreview) {
642
+ text += `\n\n${theme.fg('error', this.editDiffPreview.error)}`;
643
+ }
644
+ else if (this.editDiffPreview.diff) {
645
+ const diffText = renderDiff(this.editDiffPreview.diff, {
646
+ filePath: rawPath ?? undefined
647
+ });
648
+ text += `\n\n${diffText}`;
649
+ }
650
+ }
651
+ }
652
+ }
653
+ else if (this.toolName === 'ls') {
654
+ const rawPath = str(this.args?.path);
655
+ const path = rawPath !== null ? shortenPath(rawPath || '.') : null;
656
+ const limit = this.args?.limit;
657
+ text = `${theme.fg('toolTitle', theme.bold('ls'))} ${path === null ? invalidArg : theme.fg('accent', path)}`;
658
+ if (limit !== undefined) {
659
+ text += theme.fg('toolOutput', ` (limit ${limit})`);
660
+ }
661
+ if (this.result) {
662
+ const output = this.getTextOutput().trim();
663
+ if (output) {
664
+ const lines = output.split('\n');
665
+ const maxLines = this.expanded ? lines.length : 20;
666
+ const displayLines = lines.slice(0, maxLines);
667
+ const remaining = lines.length - maxLines;
668
+ text += `\n\n${displayLines.map((line) => theme.fg('toolOutput', line)).join('\n')}`;
669
+ if (remaining > 0) {
670
+ text += theme.fg('muted', `\n... (${remaining} more lines)`);
671
+ }
672
+ }
673
+ const entryLimit = this.result.details?.entryLimitReached;
674
+ const truncation = this.result.details?.truncation;
675
+ if (entryLimit || truncation?.truncated) {
676
+ const warnings = [];
677
+ if (entryLimit) {
678
+ warnings.push(`${entryLimit} entries limit`);
679
+ }
680
+ if (truncation?.truncated) {
681
+ warnings.push(`${formatSize(truncation.maxChars)} char limit`);
682
+ }
683
+ text += `\n${theme.fg('warning', `[Truncated: ${warnings.join(', ')}]`)}`;
684
+ }
685
+ }
686
+ }
687
+ else if (this.toolName === 'find') {
688
+ const pattern = str(this.args?.pattern);
689
+ const rawPath = str(this.args?.path);
690
+ const path = rawPath !== null ? shortenPath(rawPath || '.') : null;
691
+ const limit = this.args?.limit;
692
+ text =
693
+ theme.fg('toolTitle', theme.bold('find')) +
694
+ ' ' +
695
+ (pattern === null ? invalidArg : theme.fg('accent', pattern || '')) +
696
+ theme.fg('toolOutput', ` in ${path === null ? invalidArg : path}`);
697
+ if (limit !== undefined) {
698
+ text += theme.fg('toolOutput', ` (limit ${limit})`);
699
+ }
700
+ if (this.result) {
701
+ const output = this.getTextOutput().trim();
702
+ if (output) {
703
+ const lines = output.split('\n');
704
+ const maxLines = this.expanded ? lines.length : 20;
705
+ const displayLines = lines.slice(0, maxLines);
706
+ const remaining = lines.length - maxLines;
707
+ text += `\n\n${displayLines.map((line) => theme.fg('toolOutput', line)).join('\n')}`;
708
+ if (remaining > 0) {
709
+ text += theme.fg('muted', `\n... (${remaining} more lines)`);
710
+ }
711
+ }
712
+ const resultLimit = this.result.details?.resultLimitReached;
713
+ const truncation = this.result.details?.truncation;
714
+ if (resultLimit || truncation?.truncated) {
715
+ const warnings = [];
716
+ if (resultLimit) {
717
+ warnings.push(`${resultLimit} results limit`);
718
+ }
719
+ if (truncation?.truncated) {
720
+ warnings.push(`${formatSize(truncation.maxChars)} char limit`);
721
+ }
722
+ text += `\n${theme.fg('warning', `[Truncated: ${warnings.join(', ')}]`)}`;
723
+ }
724
+ }
725
+ }
726
+ else if (this.toolName === 'grep') {
727
+ const pattern = str(this.args?.pattern);
728
+ const rawPath = str(this.args?.path);
729
+ const path = rawPath !== null ? shortenPath(rawPath || '.') : null;
730
+ const glob = str(this.args?.glob);
731
+ const limit = this.args?.limit;
732
+ text =
733
+ theme.fg('toolTitle', theme.bold('grep')) +
734
+ ' ' +
735
+ (pattern === null ? invalidArg : theme.fg('accent', `/${pattern || ''}/`)) +
736
+ theme.fg('toolOutput', ` in ${path === null ? invalidArg : path}`);
737
+ if (glob) {
738
+ text += theme.fg('toolOutput', ` (${glob})`);
739
+ }
740
+ if (limit !== undefined) {
741
+ text += theme.fg('toolOutput', ` limit ${limit}`);
742
+ }
743
+ if (this.result) {
744
+ const output = this.getTextOutput().trim();
745
+ if (output) {
746
+ const lines = output.split('\n');
747
+ const maxLines = this.expanded ? lines.length : 0;
748
+ const displayLines = lines.slice(0, maxLines);
749
+ const remaining = lines.length - maxLines;
750
+ if (displayLines.length > 0) {
751
+ text +=
752
+ '\n\n' + displayLines.map((line) => theme.fg('toolOutput', line)).join('\n');
753
+ }
754
+ if (remaining > 0) {
755
+ text += theme.fg('muted', `\n... (${remaining} more lines)`);
756
+ }
757
+ }
758
+ const matchLimit = this.result.details?.matchLimitReached;
759
+ const truncation = this.result.details?.truncation;
760
+ const linesTruncated = this.result.details?.linesTruncated;
761
+ if (matchLimit || truncation?.truncated || linesTruncated) {
762
+ const warnings = [];
763
+ if (matchLimit) {
764
+ warnings.push(`${matchLimit} matches limit`);
765
+ }
766
+ if (truncation?.truncated) {
767
+ warnings.push(`${formatSize(truncation.maxChars)} char limit`);
768
+ }
769
+ if (linesTruncated) {
770
+ warnings.push('some lines truncated');
771
+ }
772
+ text += `\n${theme.fg('warning', `[Truncated: ${warnings.join(', ')}]`)}`;
773
+ }
774
+ }
775
+ }
776
+ else {
777
+ // Generic tool (shouldn't reach here for custom tools)
778
+ text = theme.fg('toolTitle', theme.bold(this.toolName));
779
+ const content = JSON.stringify(this.args, null, 2);
780
+ text += `\n\n${content}`;
781
+ const output = this.getTextOutput();
782
+ if (output) {
783
+ text += `\n${output}`;
784
+ }
785
+ }
786
+ return text;
787
+ }
788
+ }
789
+ //# sourceMappingURL=tool-execution.js.map