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,488 @@
1
+ /**
2
+ * TUI component for managing package resources (enable/disable)
3
+ */
4
+ import { Container, getEditorKeybindings, Input, matchesKey, Spacer, truncateToWidth, visibleWidth } from '../../../tui/index.js';
5
+ import { basename, dirname, join, relative } from 'node:path';
6
+ import { CONFIG_DIR_NAME } from '../../../config.js';
7
+ import { theme } from '../../../core/theme.js';
8
+ import { DynamicBorder } from './dynamic-border.js';
9
+ import { rawKeyHint } from './keybinding-hints.js';
10
+ const RESOURCE_TYPE_LABELS = {
11
+ extensions: 'Extensions',
12
+ skills: 'Skills',
13
+ prompts: 'Prompts',
14
+ themes: 'Themes'
15
+ };
16
+ function getGroupLabel(metadata) {
17
+ if (metadata.origin === 'package') {
18
+ return `${metadata.source} (${metadata.scope})`;
19
+ }
20
+ // Top-level resources
21
+ if (metadata.source === 'auto') {
22
+ return metadata.scope === 'user' ? 'User (~/.pi/agent/)' : 'Project (.pi/)';
23
+ }
24
+ return metadata.scope === 'user' ? 'User settings' : 'Project settings';
25
+ }
26
+ function buildGroups(resolved) {
27
+ const groupMap = new Map();
28
+ const addToGroup = (resources, resourceType) => {
29
+ for (const res of resources) {
30
+ const { path, enabled, metadata } = res;
31
+ const groupKey = `${metadata.origin}:${metadata.scope}:${metadata.source}`;
32
+ if (!groupMap.has(groupKey)) {
33
+ groupMap.set(groupKey, {
34
+ key: groupKey,
35
+ label: getGroupLabel(metadata),
36
+ scope: metadata.scope,
37
+ origin: metadata.origin,
38
+ source: metadata.source,
39
+ subgroups: []
40
+ });
41
+ }
42
+ const group = groupMap.get(groupKey);
43
+ const subgroupKey = `${groupKey}:${resourceType}`;
44
+ let subgroup = group.subgroups.find((sg) => sg.type === resourceType);
45
+ if (!subgroup) {
46
+ subgroup = {
47
+ type: resourceType,
48
+ label: RESOURCE_TYPE_LABELS[resourceType],
49
+ items: []
50
+ };
51
+ group.subgroups.push(subgroup);
52
+ }
53
+ const fileName = basename(path);
54
+ const parentFolder = basename(dirname(path));
55
+ let displayName;
56
+ if (resourceType === 'extensions' && parentFolder !== 'extensions') {
57
+ displayName = `${parentFolder}/${fileName}`;
58
+ }
59
+ else if (resourceType === 'skills' && fileName === 'SKILL.md') {
60
+ displayName = parentFolder;
61
+ }
62
+ else {
63
+ displayName = fileName;
64
+ }
65
+ subgroup.items.push({
66
+ path,
67
+ enabled,
68
+ metadata,
69
+ resourceType,
70
+ displayName,
71
+ groupKey,
72
+ subgroupKey
73
+ });
74
+ }
75
+ };
76
+ addToGroup(resolved.extensions, 'extensions');
77
+ addToGroup(resolved.skills, 'skills');
78
+ addToGroup(resolved.prompts, 'prompts');
79
+ addToGroup(resolved.themes, 'themes');
80
+ // Sort groups: packages first, then top-level; user before project
81
+ const groups = Array.from(groupMap.values());
82
+ groups.sort((a, b) => {
83
+ if (a.origin !== b.origin) {
84
+ return a.origin === 'package' ? -1 : 1;
85
+ }
86
+ if (a.scope !== b.scope) {
87
+ return a.scope === 'user' ? -1 : 1;
88
+ }
89
+ return a.source.localeCompare(b.source);
90
+ });
91
+ // Sort subgroups within each group by type order, and items by name
92
+ const typeOrder = {
93
+ extensions: 0,
94
+ skills: 1,
95
+ prompts: 2,
96
+ themes: 3
97
+ };
98
+ for (const group of groups) {
99
+ group.subgroups.sort((a, b) => typeOrder[a.type] - typeOrder[b.type]);
100
+ for (const subgroup of group.subgroups) {
101
+ subgroup.items.sort((a, b) => a.displayName.localeCompare(b.displayName));
102
+ }
103
+ }
104
+ return groups;
105
+ }
106
+ class ConfigSelectorHeader {
107
+ invalidate() { }
108
+ render(width) {
109
+ const title = theme.bold('Resource Configuration');
110
+ const sep = theme.fg('muted', ' · ');
111
+ const hint = rawKeyHint('space', 'toggle') + sep + rawKeyHint('esc', 'close');
112
+ const hintWidth = visibleWidth(hint);
113
+ const titleWidth = visibleWidth(title);
114
+ const spacing = Math.max(1, width - titleWidth - hintWidth);
115
+ return [
116
+ truncateToWidth(`${title}${' '.repeat(spacing)}${hint}`, width, ''),
117
+ theme.fg('muted', 'Type to filter resources')
118
+ ];
119
+ }
120
+ }
121
+ class ResourceList {
122
+ groups;
123
+ flatItems = [];
124
+ filteredItems = [];
125
+ selectedIndex = 0;
126
+ searchInput;
127
+ maxVisible = 15;
128
+ settingsManager;
129
+ cwd;
130
+ agentDir;
131
+ onCancel;
132
+ onExit;
133
+ onToggle;
134
+ _focused = false;
135
+ get focused() {
136
+ return this._focused;
137
+ }
138
+ set focused(value) {
139
+ this._focused = value;
140
+ this.searchInput.focused = value;
141
+ }
142
+ constructor(groups, settingsManager, cwd, agentDir) {
143
+ this.groups = groups;
144
+ this.settingsManager = settingsManager;
145
+ this.cwd = cwd;
146
+ this.agentDir = agentDir;
147
+ this.searchInput = new Input();
148
+ this.buildFlatList();
149
+ this.filteredItems = [...this.flatItems];
150
+ }
151
+ buildFlatList() {
152
+ this.flatItems = [];
153
+ for (const group of this.groups) {
154
+ this.flatItems.push({ type: 'group', group });
155
+ for (const subgroup of group.subgroups) {
156
+ this.flatItems.push({ type: 'subgroup', subgroup, group });
157
+ for (const item of subgroup.items) {
158
+ this.flatItems.push({ type: 'item', item });
159
+ }
160
+ }
161
+ }
162
+ // Start selection on first item (not header)
163
+ this.selectedIndex = this.flatItems.findIndex((e) => e.type === 'item');
164
+ if (this.selectedIndex < 0)
165
+ this.selectedIndex = 0;
166
+ }
167
+ findNextItem(fromIndex, direction) {
168
+ let idx = fromIndex + direction;
169
+ while (idx >= 0 && idx < this.filteredItems.length) {
170
+ if (this.filteredItems[idx].type === 'item') {
171
+ return idx;
172
+ }
173
+ idx += direction;
174
+ }
175
+ return fromIndex; // Stay at current if no item found
176
+ }
177
+ filterItems(query) {
178
+ if (!query.trim()) {
179
+ this.filteredItems = [...this.flatItems];
180
+ this.selectFirstItem();
181
+ return;
182
+ }
183
+ const lowerQuery = query.toLowerCase();
184
+ const matchingItems = new Set();
185
+ const matchingSubgroups = new Set();
186
+ const matchingGroups = new Set();
187
+ for (const entry of this.flatItems) {
188
+ if (entry.type === 'item') {
189
+ const item = entry.item;
190
+ if (item.displayName.toLowerCase().includes(lowerQuery) ||
191
+ item.resourceType.toLowerCase().includes(lowerQuery) ||
192
+ item.path.toLowerCase().includes(lowerQuery)) {
193
+ matchingItems.add(item);
194
+ }
195
+ }
196
+ }
197
+ // Find which subgroups and groups contain matching items
198
+ for (const group of this.groups) {
199
+ for (const subgroup of group.subgroups) {
200
+ for (const item of subgroup.items) {
201
+ if (matchingItems.has(item)) {
202
+ matchingSubgroups.add(subgroup);
203
+ matchingGroups.add(group);
204
+ }
205
+ }
206
+ }
207
+ }
208
+ this.filteredItems = [];
209
+ for (const entry of this.flatItems) {
210
+ if (entry.type === 'group' && matchingGroups.has(entry.group)) {
211
+ this.filteredItems.push(entry);
212
+ }
213
+ else if (entry.type === 'subgroup' && matchingSubgroups.has(entry.subgroup)) {
214
+ this.filteredItems.push(entry);
215
+ }
216
+ else if (entry.type === 'item' && matchingItems.has(entry.item)) {
217
+ this.filteredItems.push(entry);
218
+ }
219
+ }
220
+ this.selectFirstItem();
221
+ }
222
+ selectFirstItem() {
223
+ const firstItemIndex = this.filteredItems.findIndex((e) => e.type === 'item');
224
+ this.selectedIndex = firstItemIndex >= 0 ? firstItemIndex : 0;
225
+ }
226
+ updateItem(item, enabled) {
227
+ item.enabled = enabled;
228
+ // Update in groups too
229
+ for (const group of this.groups) {
230
+ for (const subgroup of group.subgroups) {
231
+ const found = subgroup.items.find((i) => i.path === item.path && i.resourceType === item.resourceType);
232
+ if (found) {
233
+ found.enabled = enabled;
234
+ return;
235
+ }
236
+ }
237
+ }
238
+ }
239
+ invalidate() { }
240
+ render(width) {
241
+ const lines = [];
242
+ // Search input
243
+ lines.push(...this.searchInput.render(width));
244
+ lines.push('');
245
+ if (this.filteredItems.length === 0) {
246
+ lines.push(theme.fg('muted', ' No resources found'));
247
+ return lines;
248
+ }
249
+ // Calculate visible range
250
+ const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible));
251
+ const endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);
252
+ for (let i = startIndex; i < endIndex; i++) {
253
+ const entry = this.filteredItems[i];
254
+ const isSelected = i === this.selectedIndex;
255
+ if (entry.type === 'group') {
256
+ // Main group header (no cursor)
257
+ const groupLine = theme.fg('accent', theme.bold(entry.group.label));
258
+ lines.push(truncateToWidth(` ${groupLine}`, width, ''));
259
+ }
260
+ else if (entry.type === 'subgroup') {
261
+ // Subgroup header (indented, no cursor)
262
+ const subgroupLine = theme.fg('muted', entry.subgroup.label);
263
+ lines.push(truncateToWidth(` ${subgroupLine}`, width, ''));
264
+ }
265
+ else {
266
+ // Resource item (cursor only on items)
267
+ const item = entry.item;
268
+ const cursor = isSelected ? '> ' : ' ';
269
+ const checkbox = item.enabled ? theme.fg('success', '[x]') : theme.fg('dim', '[ ]');
270
+ const name = isSelected ? theme.bold(item.displayName) : item.displayName;
271
+ lines.push(truncateToWidth(`${cursor} ${checkbox} ${name}`, width, '...'));
272
+ }
273
+ }
274
+ // Scroll indicator
275
+ if (startIndex > 0 || endIndex < this.filteredItems.length) {
276
+ lines.push(theme.fg('dim', ` (${this.selectedIndex + 1}/${this.filteredItems.length})`));
277
+ }
278
+ return lines;
279
+ }
280
+ handleInput(data) {
281
+ const kb = getEditorKeybindings();
282
+ if (kb.matches(data, 'selectUp')) {
283
+ this.selectedIndex = this.findNextItem(this.selectedIndex, -1);
284
+ return;
285
+ }
286
+ if (kb.matches(data, 'selectDown')) {
287
+ this.selectedIndex = this.findNextItem(this.selectedIndex, 1);
288
+ return;
289
+ }
290
+ if (kb.matches(data, 'selectPageUp')) {
291
+ // Jump up by maxVisible, then find nearest item
292
+ let target = Math.max(0, this.selectedIndex - this.maxVisible);
293
+ while (target < this.filteredItems.length && this.filteredItems[target].type !== 'item') {
294
+ target++;
295
+ }
296
+ if (target < this.filteredItems.length) {
297
+ this.selectedIndex = target;
298
+ }
299
+ return;
300
+ }
301
+ if (kb.matches(data, 'selectPageDown')) {
302
+ // Jump down by maxVisible, then find nearest item
303
+ let target = Math.min(this.filteredItems.length - 1, this.selectedIndex + this.maxVisible);
304
+ while (target >= 0 && this.filteredItems[target].type !== 'item') {
305
+ target--;
306
+ }
307
+ if (target >= 0) {
308
+ this.selectedIndex = target;
309
+ }
310
+ return;
311
+ }
312
+ if (kb.matches(data, 'selectCancel')) {
313
+ this.onCancel?.();
314
+ return;
315
+ }
316
+ if (matchesKey(data, 'ctrl+c')) {
317
+ this.onExit?.();
318
+ return;
319
+ }
320
+ if (data === ' ' || kb.matches(data, 'selectConfirm')) {
321
+ const entry = this.filteredItems[this.selectedIndex];
322
+ if (entry?.type === 'item') {
323
+ const newEnabled = !entry.item.enabled;
324
+ this.toggleResource(entry.item, newEnabled);
325
+ this.updateItem(entry.item, newEnabled);
326
+ this.onToggle?.(entry.item, newEnabled);
327
+ }
328
+ return;
329
+ }
330
+ // Pass to search input
331
+ this.searchInput.handleInput(data);
332
+ this.filterItems(this.searchInput.getValue());
333
+ }
334
+ toggleResource(item, enabled) {
335
+ if (item.metadata.origin === 'top-level') {
336
+ this.toggleTopLevelResource(item, enabled);
337
+ }
338
+ else {
339
+ this.togglePackageResource(item, enabled);
340
+ }
341
+ }
342
+ toggleTopLevelResource(item, enabled) {
343
+ const scope = item.metadata.scope;
344
+ const settings = scope === 'project'
345
+ ? this.settingsManager.getProjectSettings()
346
+ : this.settingsManager.getGlobalSettings();
347
+ const arrayKey = item.resourceType;
348
+ const current = (settings[arrayKey] ?? []);
349
+ // Generate pattern for this resource
350
+ const pattern = this.getResourcePattern(item);
351
+ const disablePattern = `-${pattern}`;
352
+ const enablePattern = `+${pattern}`;
353
+ // Filter out existing patterns for this resource
354
+ const updated = current.filter((p) => {
355
+ const stripped = p.startsWith('!') || p.startsWith('+') || p.startsWith('-') ? p.slice(1) : p;
356
+ return stripped !== pattern;
357
+ });
358
+ if (enabled) {
359
+ updated.push(enablePattern);
360
+ }
361
+ else {
362
+ updated.push(disablePattern);
363
+ }
364
+ if (scope === 'project') {
365
+ if (arrayKey === 'extensions') {
366
+ this.settingsManager.setProjectExtensionPaths(updated);
367
+ }
368
+ else if (arrayKey === 'skills') {
369
+ this.settingsManager.setProjectSkillPaths(updated);
370
+ }
371
+ else if (arrayKey === 'prompts') {
372
+ this.settingsManager.setProjectPromptTemplatePaths(updated);
373
+ }
374
+ else if (arrayKey === 'themes') {
375
+ this.settingsManager.setProjectThemePaths(updated);
376
+ }
377
+ }
378
+ else {
379
+ if (arrayKey === 'extensions') {
380
+ this.settingsManager.setExtensionPaths(updated);
381
+ }
382
+ else if (arrayKey === 'skills') {
383
+ this.settingsManager.setSkillPaths(updated);
384
+ }
385
+ else if (arrayKey === 'prompts') {
386
+ this.settingsManager.setPromptTemplatePaths(updated);
387
+ }
388
+ else if (arrayKey === 'themes') {
389
+ this.settingsManager.setThemePaths(updated);
390
+ }
391
+ }
392
+ }
393
+ togglePackageResource(item, enabled) {
394
+ const scope = item.metadata.scope;
395
+ const settings = scope === 'project'
396
+ ? this.settingsManager.getProjectSettings()
397
+ : this.settingsManager.getGlobalSettings();
398
+ const packages = [...(settings.packages ?? [])];
399
+ const pkgIndex = packages.findIndex((pkg) => {
400
+ const source = typeof pkg === 'string' ? pkg : pkg.source;
401
+ return source === item.metadata.source;
402
+ });
403
+ if (pkgIndex === -1)
404
+ return;
405
+ let pkg = packages[pkgIndex];
406
+ // Convert string to object form if needed
407
+ if (typeof pkg === 'string') {
408
+ pkg = { source: pkg };
409
+ packages[pkgIndex] = pkg;
410
+ }
411
+ // Get the resource array for this type
412
+ const arrayKey = item.resourceType;
413
+ const current = (pkg[arrayKey] ?? []);
414
+ // Generate pattern relative to package root
415
+ const pattern = this.getPackageResourcePattern(item);
416
+ const disablePattern = `-${pattern}`;
417
+ const enablePattern = `+${pattern}`;
418
+ // Filter out existing patterns for this resource
419
+ const updated = current.filter((p) => {
420
+ const stripped = p.startsWith('!') || p.startsWith('+') || p.startsWith('-') ? p.slice(1) : p;
421
+ return stripped !== pattern;
422
+ });
423
+ if (enabled) {
424
+ updated.push(enablePattern);
425
+ }
426
+ else {
427
+ updated.push(disablePattern);
428
+ }
429
+ pkg[arrayKey] = updated.length > 0 ? updated : undefined;
430
+ // Clean up empty filter object
431
+ const hasFilters = ['extensions', 'skills', 'prompts', 'themes'].some((k) => pkg[k] !== undefined);
432
+ if (!hasFilters) {
433
+ packages[pkgIndex] = pkg.source;
434
+ }
435
+ if (scope === 'project') {
436
+ this.settingsManager.setProjectPackages(packages);
437
+ }
438
+ else {
439
+ this.settingsManager.setPackages(packages);
440
+ }
441
+ }
442
+ getTopLevelBaseDir(scope) {
443
+ return scope === 'project' ? join(this.cwd, CONFIG_DIR_NAME) : this.agentDir;
444
+ }
445
+ getResourcePattern(item) {
446
+ const scope = item.metadata.scope;
447
+ const baseDir = this.getTopLevelBaseDir(scope);
448
+ return relative(baseDir, item.path);
449
+ }
450
+ getPackageResourcePattern(item) {
451
+ const baseDir = item.metadata.baseDir ?? dirname(item.path);
452
+ return relative(baseDir, item.path);
453
+ }
454
+ }
455
+ export class ConfigSelectorComponent extends Container {
456
+ resourceList;
457
+ _focused = false;
458
+ get focused() {
459
+ return this._focused;
460
+ }
461
+ set focused(value) {
462
+ this._focused = value;
463
+ this.resourceList.focused = value;
464
+ }
465
+ constructor(resolvedPaths, settingsManager, cwd, agentDir, onClose, onExit, requestRender) {
466
+ super();
467
+ const groups = buildGroups(resolvedPaths);
468
+ // Add header
469
+ this.addChild(new Spacer(1));
470
+ this.addChild(new DynamicBorder());
471
+ this.addChild(new Spacer(1));
472
+ this.addChild(new ConfigSelectorHeader());
473
+ this.addChild(new Spacer(1));
474
+ // Resource list
475
+ this.resourceList = new ResourceList(groups, settingsManager, cwd, agentDir);
476
+ this.resourceList.onCancel = onClose;
477
+ this.resourceList.onExit = onExit;
478
+ this.resourceList.onToggle = () => requestRender();
479
+ this.addChild(this.resourceList);
480
+ // Bottom border
481
+ this.addChild(new Spacer(1));
482
+ this.addChild(new DynamicBorder());
483
+ }
484
+ getResourceList() {
485
+ return this.resourceList;
486
+ }
487
+ }
488
+ //# sourceMappingURL=config-selector.js.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Reusable countdown timer for dialog components.
3
+ */
4
+ export class CountdownTimer {
5
+ tui;
6
+ onTick;
7
+ onExpire;
8
+ intervalId;
9
+ remainingSeconds;
10
+ constructor(timeoutMs, tui, onTick, onExpire) {
11
+ this.tui = tui;
12
+ this.onTick = onTick;
13
+ this.onExpire = onExpire;
14
+ this.remainingSeconds = Math.ceil(timeoutMs / 1000);
15
+ this.onTick(this.remainingSeconds);
16
+ this.intervalId = setInterval(() => {
17
+ this.remainingSeconds--;
18
+ this.onTick(this.remainingSeconds);
19
+ this.tui?.requestRender();
20
+ if (this.remainingSeconds <= 0) {
21
+ this.dispose();
22
+ this.onExpire();
23
+ }
24
+ }, 1000);
25
+ }
26
+ dispose() {
27
+ if (this.intervalId) {
28
+ clearInterval(this.intervalId);
29
+ this.intervalId = undefined;
30
+ }
31
+ }
32
+ }
33
+ //# sourceMappingURL=countdown-timer.js.map
@@ -0,0 +1,93 @@
1
+ import { Editor } from '../../../tui/index.js';
2
+ import { stripQuotes } from '../file-attachments.js';
3
+ const BRACKETED_PASTE_START = '\x1b[200~';
4
+ const BRACKETED_PASTE_END = '\x1b[201~';
5
+ /**
6
+ * Custom editor that handles app-level keybindings for coding-agent.
7
+ */
8
+ export class CustomEditor extends Editor {
9
+ keybindings;
10
+ actionHandlers = new Map();
11
+ // Special handlers that can be dynamically replaced
12
+ onEscape;
13
+ onCtrlD;
14
+ onPasteImage;
15
+ /** Handler for pasted file paths (drag-and-drop). Returns true if handled. */
16
+ onFilePaste;
17
+ /** Handler for extension-registered shortcuts. Returns true if handled. */
18
+ onExtensionShortcut;
19
+ constructor(tui, theme, keybindings, options) {
20
+ super(tui, theme, options);
21
+ this.keybindings = keybindings;
22
+ }
23
+ /**
24
+ * Register a handler for an app action.
25
+ */
26
+ onAction(action, handler) {
27
+ this.actionHandlers.set(action, handler);
28
+ }
29
+ handleInput(data) {
30
+ // Check extension-registered shortcuts first
31
+ if (this.onExtensionShortcut?.(data)) {
32
+ return;
33
+ }
34
+ // Check for paste image keybinding
35
+ if (this.keybindings.matches(data, 'pasteImage')) {
36
+ this.onPasteImage?.();
37
+ return;
38
+ }
39
+ // Check app keybindings first
40
+ // Escape/interrupt - only if autocomplete is NOT active
41
+ if (this.keybindings.matches(data, 'interrupt')) {
42
+ if (!this.isShowingAutocomplete()) {
43
+ // Use dynamic onEscape if set, otherwise registered handler
44
+ const handler = this.onEscape ?? this.actionHandlers.get('interrupt');
45
+ if (handler) {
46
+ handler();
47
+ return;
48
+ }
49
+ }
50
+ // Let parent handle escape for autocomplete cancellation
51
+ super.handleInput(data);
52
+ return;
53
+ }
54
+ // Exit (Ctrl+D) - only when editor is empty
55
+ if (this.keybindings.matches(data, 'exit')) {
56
+ if (this.getText().length === 0) {
57
+ const handler = this.onCtrlD ?? this.actionHandlers.get('exit');
58
+ if (handler)
59
+ handler();
60
+ return;
61
+ }
62
+ // Fall through to editor handling for delete-char-forward when not empty
63
+ }
64
+ // Check all other app actions
65
+ for (const [action, handler] of this.actionHandlers) {
66
+ if (action !== 'interrupt' && action !== 'exit' && this.keybindings.matches(data, action)) {
67
+ handler();
68
+ return;
69
+ }
70
+ }
71
+ // Intercept bracketed paste: if the pasted content is a file path,
72
+ // redirect to onFilePaste instead of inserting as text
73
+ if (this.onFilePaste && data.includes(BRACKETED_PASTE_START)) {
74
+ const startIdx = data.indexOf(BRACKETED_PASTE_START) + BRACKETED_PASTE_START.length;
75
+ const endIdx = data.indexOf(BRACKETED_PASTE_END);
76
+ if (endIdx !== -1) {
77
+ const pasteContent = stripQuotes(data.substring(startIdx, endIdx).trim());
78
+ // Check if the entire paste is a single absolute file path
79
+ if (pasteContent.startsWith('/') && !pasteContent.includes('\n') && this.onFilePaste(pasteContent)) {
80
+ // File paste handled — process any remaining data after the paste end marker
81
+ const remaining = data.substring(endIdx + BRACKETED_PASTE_END.length);
82
+ if (remaining.length > 0) {
83
+ this.handleInput(remaining);
84
+ }
85
+ return;
86
+ }
87
+ }
88
+ }
89
+ // Pass to parent for editor handling
90
+ super.handleInput(data);
91
+ }
92
+ }
93
+ //# sourceMappingURL=custom-editor.js.map
@@ -0,0 +1,81 @@
1
+ import { Box, Container, Markdown, Spacer, Text } from '../../../tui/index.js';
2
+ import { theme } from '../../../core/theme.js';
3
+ import { getMarkdownTheme } from '../theme/theme.js';
4
+ import { CONTENT_PAD_X, CONTENT_PAD_Y } from './layout.js';
5
+ /**
6
+ * Component that renders a custom message entry from extensions.
7
+ * Uses distinct styling to differentiate from user messages.
8
+ */
9
+ export class CustomMessageComponent extends Container {
10
+ message;
11
+ customRenderer;
12
+ box;
13
+ customComponent;
14
+ markdownTheme;
15
+ _expanded = false;
16
+ constructor(message, customRenderer, markdownTheme = getMarkdownTheme()) {
17
+ super();
18
+ this.message = message;
19
+ this.customRenderer = customRenderer;
20
+ this.markdownTheme = markdownTheme;
21
+ this.addChild(new Spacer(1));
22
+ // Create box with purple background (used for default rendering)
23
+ this.box = new Box(CONTENT_PAD_X, CONTENT_PAD_Y, (t) => theme.bg('customMessageBg', t));
24
+ this.rebuild();
25
+ }
26
+ setExpanded(expanded) {
27
+ if (this._expanded !== expanded) {
28
+ this._expanded = expanded;
29
+ this.rebuild();
30
+ }
31
+ }
32
+ invalidate() {
33
+ super.invalidate();
34
+ this.rebuild();
35
+ }
36
+ rebuild() {
37
+ // Remove previous content component
38
+ if (this.customComponent) {
39
+ this.removeChild(this.customComponent);
40
+ this.customComponent = undefined;
41
+ }
42
+ this.removeChild(this.box);
43
+ // Try custom renderer first - it handles its own styling
44
+ if (this.customRenderer) {
45
+ try {
46
+ const component = this.customRenderer(this.message, { expanded: this._expanded }, theme);
47
+ if (component) {
48
+ // Custom renderer provides its own styled component
49
+ this.customComponent = component;
50
+ this.addChild(component);
51
+ return;
52
+ }
53
+ }
54
+ catch {
55
+ // Fall through to default rendering
56
+ }
57
+ }
58
+ // Default rendering uses our box
59
+ this.addChild(this.box);
60
+ this.box.clear();
61
+ // Default rendering: label + content
62
+ const label = theme.fg('customMessageLabel', `\x1b[1m[${this.message.customType}]\x1b[22m`);
63
+ this.box.addChild(new Text(label, 0, 0));
64
+ this.box.addChild(new Spacer(1));
65
+ // Extract text content
66
+ let text;
67
+ if (typeof this.message.content === 'string') {
68
+ text = this.message.content;
69
+ }
70
+ else {
71
+ text = this.message.content
72
+ .filter((c) => c.type === 'text')
73
+ .map((c) => c.text)
74
+ .join('\n');
75
+ }
76
+ this.box.addChild(new Markdown(text, 0, 0, this.markdownTheme, {
77
+ color: (text) => theme.fg('customMessageText', text)
78
+ }));
79
+ }
80
+ }
81
+ //# sourceMappingURL=custom-message.js.map