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,309 @@
1
+ import { truncateToWidth, visibleWidth } from '../../../tui/index.js';
2
+ import { theme } from '../../../core/theme.js';
3
+ /**
4
+ * Sanitize text for display in a single-line status.
5
+ * Removes newlines, tabs, carriage returns, and other control characters.
6
+ */
7
+ function sanitizeStatusText(text) {
8
+ // Replace newlines, tabs, carriage returns with space, then collapse multiple spaces
9
+ return text
10
+ .replace(/[\r\n\t]/g, ' ')
11
+ .replace(/ +/g, ' ')
12
+ .trim();
13
+ }
14
+ /**
15
+ * Format token counts (similar to web-ui)
16
+ */
17
+ function formatTokens(count) {
18
+ if (count < 1000)
19
+ return count.toString();
20
+ if (count < 10000)
21
+ return `${(count / 1000).toFixed(1)}k`;
22
+ if (count < 1000000)
23
+ return `${Math.round(count / 1000)}k`;
24
+ if (count < 10000000)
25
+ return `${(count / 1000000).toFixed(1)}M`;
26
+ return `${Math.round(count / 1000000)}M`;
27
+ }
28
+ // ANSI escape helpers for credit tier styling
29
+ const ANSI = {
30
+ bold: '\x1b[1m',
31
+ brightWhite: '\x1b[97m',
32
+ cyan: '\x1b[36m',
33
+ brightCyan: '\x1b[96m',
34
+ reset: '\x1b[0m',
35
+ resetFg: '\x1b[39m',
36
+ resetBold: '\x1b[22m'
37
+ };
38
+ /**
39
+ * Style credit text based on usage tiers.
40
+ * Higher spend = more visually prominent = more "achievement" feel.
41
+ *
42
+ * 0 → dim (haven't started yet)
43
+ * 1-29 → normal (getting going)
44
+ * 30-99 → bold bright white (making progress)
45
+ * 100-299 → cyan (power user)
46
+ * 300+ → bright cyan + bold (legend)
47
+ */
48
+ function styleCreditText(text, creditsUsed) {
49
+ if (creditsUsed <= 0)
50
+ return theme.fg('dim', text);
51
+ if (creditsUsed < 30)
52
+ return text;
53
+ if (creditsUsed < 100)
54
+ return `${ANSI.bold}${ANSI.brightWhite}${text}${ANSI.resetBold}${ANSI.resetFg}`;
55
+ if (creditsUsed < 300)
56
+ return `${ANSI.cyan}${text}${ANSI.resetFg}`;
57
+ return `${ANSI.bold}${ANSI.brightCyan}${text}${ANSI.resetBold}${ANSI.resetFg}`;
58
+ }
59
+ /**
60
+ * Count user queries (user messages) in the session.
61
+ */
62
+ function countUserQueries(session) {
63
+ let count = 0;
64
+ for (const entry of session.sessionManager.getEntries()) {
65
+ if (entry.type === 'message' && entry.message.role === 'user') {
66
+ count++;
67
+ }
68
+ }
69
+ return count;
70
+ }
71
+ /**
72
+ * Footer component that shows pwd, token stats, and context usage.
73
+ * Computes token/context stats from session, gets git branch and extension statuses from provider.
74
+ *
75
+ * Shortcut credit users get a gamified footer:
76
+ * - Credits styled by spend tier (dim → normal → bold → cyan → bright cyan)
77
+ * - Context % colored by usage AND query count (orange at 50%/10q, red at 75%/15q)
78
+ * - Separator line on top
79
+ */
80
+ export class FooterComponent {
81
+ session;
82
+ footerData;
83
+ constructor(session, footerData) {
84
+ this.session = session;
85
+ this.footerData = footerData;
86
+ }
87
+ /**
88
+ * No-op: git branch caching now handled by provider.
89
+ * Kept for compatibility with existing call sites in interactive-mode.
90
+ */
91
+ invalidate() {
92
+ // No-op: git branch is cached/invalidated by provider
93
+ }
94
+ /**
95
+ * Clean up resources.
96
+ * Git watcher cleanup now handled by provider.
97
+ */
98
+ dispose() {
99
+ // Git watcher cleanup handled by provider
100
+ }
101
+ render(width) {
102
+ const state = this.session.state;
103
+ // Calculate cumulative usage from ALL session entries (not just post-compaction messages)
104
+ let totalInput = 0;
105
+ let totalOutput = 0;
106
+ let totalCacheRead = 0;
107
+ let totalCacheWrite = 0;
108
+ let totalCost = 0;
109
+ for (const entry of this.session.sessionManager.getEntries()) {
110
+ if (entry.type === 'message' && entry.message.role === 'assistant') {
111
+ totalInput += entry.message.usage.input;
112
+ totalOutput += entry.message.usage.output;
113
+ totalCacheRead += entry.message.usage.cacheRead;
114
+ totalCacheWrite += entry.message.usage.cacheWrite;
115
+ totalCost += entry.message.usage.cost.total;
116
+ }
117
+ }
118
+ // Calculate context usage from session (handles compaction correctly).
119
+ // After compaction, tokens are unknown until the next LLM response.
120
+ const contextUsage = this.session.getContextUsage();
121
+ const contextPercentValue = contextUsage?.percent ?? 0;
122
+ const contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : '?';
123
+ // Count user queries for context heat meter
124
+ const queryCount = countUserQueries(this.session);
125
+ // Build info line: session name only (no branch — user prefers minimal footer)
126
+ const sessionName = this.session.sessionManager.getSessionName();
127
+ const infoLine = sessionName || null;
128
+ // Build stats line
129
+ const statsParts = [];
130
+ // Track plain-text widths for each part (ANSI codes have zero visible width)
131
+ const isShortcutCredits = !!this.footerData.getCreditBalance();
132
+ // If a credit balance is available, show credits with tier styling.
133
+ // If the model uses credits but the balance fetch failed, show tokens only (no $cost).
134
+ // Otherwise show full token breakdown + cost.
135
+ const creditBalance = this.footerData.getCreditBalance();
136
+ if (creditBalance) {
137
+ const creditsUsed = this.footerData.getCreditsUsed();
138
+ if (creditBalance.isUnlimited) {
139
+ statsParts.push(theme.fg('dim', 'credits: ∞'));
140
+ }
141
+ else {
142
+ const creditsText = `credits used: ${creditsUsed}`;
143
+ statsParts.push(styleCreditText(creditsText, creditsUsed));
144
+ }
145
+ }
146
+ else if (this.footerData.usesCredits) {
147
+ // Credit-based model but balance unavailable — show tokens without $cost
148
+ if (totalInput)
149
+ statsParts.push(`↑${formatTokens(totalInput)}`);
150
+ if (totalOutput)
151
+ statsParts.push(`↓${formatTokens(totalOutput)}`);
152
+ if (totalCacheRead)
153
+ statsParts.push(`R${formatTokens(totalCacheRead)}`);
154
+ if (totalCacheWrite)
155
+ statsParts.push(`W${formatTokens(totalCacheWrite)}`);
156
+ }
157
+ else {
158
+ if (totalInput)
159
+ statsParts.push(`↑${formatTokens(totalInput)}`);
160
+ if (totalOutput)
161
+ statsParts.push(`↓${formatTokens(totalOutput)}`);
162
+ if (totalCacheRead)
163
+ statsParts.push(`R${formatTokens(totalCacheRead)}`);
164
+ if (totalCacheWrite)
165
+ statsParts.push(`W${formatTokens(totalCacheWrite)}`);
166
+ const usingSubscription = state.model
167
+ ? this.session.modelRegistry.isUsingOAuth(state.model)
168
+ : false;
169
+ if (totalCost || usingSubscription) {
170
+ const costStr = `$${totalCost.toFixed(3)}${usingSubscription ? ' (sub)' : ''}`;
171
+ statsParts.push(costStr);
172
+ }
173
+ }
174
+ // Colorize context percentage based on usage AND query count.
175
+ // For Shortcut credit users: more aggressive thresholds (50%/75%) + query-based triggers.
176
+ // For non-credit users: original thresholds (70%/90%).
177
+ let contextPercentStr;
178
+ const contextPercentDisplay = contextPercent === '?' ? '? context' : `${contextPercent}% context`;
179
+ if (isShortcutCredits) {
180
+ // Context colored only by context usage %
181
+ if (contextPercentValue >= 75) {
182
+ contextPercentStr = theme.fg('error', contextPercentDisplay);
183
+ }
184
+ else if (contextPercentValue >= 50) {
185
+ contextPercentStr = theme.fg('warning', contextPercentDisplay);
186
+ }
187
+ else {
188
+ contextPercentStr = contextPercentDisplay;
189
+ }
190
+ }
191
+ else {
192
+ // Non-credit users: original thresholds
193
+ const fullDisplay = `${contextPercentDisplay} (auto)`;
194
+ if (contextPercentValue > 90) {
195
+ contextPercentStr = theme.fg('error', fullDisplay);
196
+ }
197
+ else if (contextPercentValue > 70) {
198
+ contextPercentStr = theme.fg('warning', fullDisplay);
199
+ }
200
+ else {
201
+ contextPercentStr = fullDisplay;
202
+ }
203
+ }
204
+ statsParts.push(contextPercentStr);
205
+ // Add query count for Shortcut credit users
206
+ if (isShortcutCredits) {
207
+ const queriesText = `${queryCount} queries`;
208
+ // Queries colored only by query count
209
+ let styledQueries;
210
+ if (queryCount > 15) {
211
+ styledQueries = theme.fg('error', queriesText);
212
+ }
213
+ else if (queryCount > 10) {
214
+ styledQueries = theme.fg('warning', queriesText);
215
+ }
216
+ else {
217
+ styledQueries = queriesText;
218
+ }
219
+ statsParts.push(styledQueries);
220
+ }
221
+ let statsLeft = statsParts.join(' ');
222
+ // Add model name on the right side, plus thinking level if model supports it
223
+ const modelName = state.model?.id || 'no-model';
224
+ let statsLeftWidth = visibleWidth(statsLeft);
225
+ // If statsLeft is too wide, truncate it
226
+ if (statsLeftWidth > width) {
227
+ // Truncate statsLeft to fit width (no room for right side)
228
+ const plainStatsLeft = statsLeft.replace(/\x1b\[[0-9;]*m/g, '');
229
+ statsLeft = `${plainStatsLeft.substring(0, width - 3)}...`;
230
+ statsLeftWidth = visibleWidth(statsLeft);
231
+ }
232
+ // Calculate available space for padding (minimum 2 spaces between stats and model)
233
+ const minPadding = 2;
234
+ // Add thinking level indicator if model supports reasoning
235
+ let rightSideWithoutProvider = modelName;
236
+ if (state.model?.reasoning) {
237
+ const thinkingLevel = state.thinkingLevel || 'off';
238
+ rightSideWithoutProvider = `${modelName} • thinking: ${thinkingLevel}`;
239
+ }
240
+ // Prepend the provider in parentheses if there are multiple providers and there's enough room
241
+ let rightSide = rightSideWithoutProvider;
242
+ if (this.footerData.getAvailableProviderCount() > 1 && state.model) {
243
+ rightSide = `(${state.model.provider}) ${rightSideWithoutProvider}`;
244
+ if (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {
245
+ // Too wide, fall back
246
+ rightSide = rightSideWithoutProvider;
247
+ }
248
+ }
249
+ const rightSideWidth = visibleWidth(rightSide);
250
+ const totalNeeded = statsLeftWidth + minPadding + rightSideWidth;
251
+ let statsLine;
252
+ if (totalNeeded <= width) {
253
+ // Both fit - add padding to right-align model
254
+ const padding = ' '.repeat(width - statsLeftWidth - rightSideWidth);
255
+ statsLine = statsLeft + padding + rightSide;
256
+ }
257
+ else {
258
+ // Need to truncate right side
259
+ const availableForRight = width - statsLeftWidth - minPadding;
260
+ if (availableForRight > 3) {
261
+ // Truncate to fit (strip ANSI codes for length calculation, then truncate raw string)
262
+ const plainRightSide = rightSide.replace(/\x1b\[[0-9;]*m/g, '');
263
+ const truncatedPlain = plainRightSide.substring(0, availableForRight);
264
+ // For simplicity, just use plain truncated version (loses color, but fits)
265
+ const padding = ' '.repeat(width - statsLeftWidth - truncatedPlain.length);
266
+ statsLine = statsLeft + padding + truncatedPlain;
267
+ }
268
+ else {
269
+ // Not enough space for right side at all
270
+ statsLine = statsLeft;
271
+ }
272
+ }
273
+ // Apply dim to non-credit parts. For credit users, statsLeft already has its own
274
+ // styling (tier colors for credits, theme colors for context). Only dim the
275
+ // right side (model name + padding).
276
+ // For non-credit users, dim everything as before.
277
+ let styledStatsLeft;
278
+ let styledRemainder;
279
+ const remainder = statsLine.slice(statsLeft.length); // padding + rightSide
280
+ if (isShortcutCredits) {
281
+ // Credits line already has ANSI styling — pass through as-is
282
+ styledStatsLeft = statsLeft;
283
+ styledRemainder = theme.fg('dim', remainder);
284
+ }
285
+ else {
286
+ styledStatsLeft = theme.fg('dim', statsLeft);
287
+ styledRemainder = theme.fg('dim', remainder);
288
+ }
289
+ // Build lines: separator, optional info line, stats
290
+ const separator = theme.fg('dim', '─'.repeat(width));
291
+ const lines = [separator];
292
+ if (infoLine) {
293
+ lines.push(theme.fg('dim', infoLine));
294
+ }
295
+ lines.push(styledStatsLeft + styledRemainder);
296
+ // SHORTCUT PATCH: render each extension status on its own line (for dev trace paths)
297
+ const extensionStatuses = this.footerData.getExtensionStatuses();
298
+ if (extensionStatuses.size > 0) {
299
+ const sortedStatuses = Array.from(extensionStatuses.entries())
300
+ .sort(([a], [b]) => a.localeCompare(b))
301
+ .map(([, text]) => sanitizeStatusText(text));
302
+ for (const status of sortedStatuses) {
303
+ lines.push(truncateToWidth(theme.fg('dim', status), width, theme.fg('dim', '...')));
304
+ }
305
+ }
306
+ return lines;
307
+ }
308
+ }
309
+ //# sourceMappingURL=footer.js.map
@@ -0,0 +1,33 @@
1
+ // UI Components for extensions
2
+ export { ArminComponent } from './armin.js';
3
+ export { AssistantMessageComponent } from './assistant-message.js';
4
+ export { BashExecutionComponent } from './bash-execution.js';
5
+ export { BorderedLoader } from './bordered-loader.js';
6
+ export { BranchSummaryMessageComponent } from './branch-summary-message.js';
7
+ export { CompactionSummaryMessageComponent } from './compaction-summary-message.js';
8
+ export { CustomEditor } from './custom-editor.js';
9
+ export { CustomMessageComponent } from './custom-message.js';
10
+ export { DaxnutsComponent } from './daxnuts.js';
11
+ export { renderDiff } from './diff.js';
12
+ export { DynamicBorder } from './dynamic-border.js';
13
+ export { ExtensionEditorComponent } from './extension-editor.js';
14
+ export { ExtensionInputComponent } from './extension-input.js';
15
+ export { ExtensionSelectorComponent } from './extension-selector.js';
16
+ export { FooterComponent } from './footer.js';
17
+ export { appKey, appKeyHint, editorKey, keyHint, rawKeyHint } from './keybinding-hints.js';
18
+ export { LoginDialogComponent } from './login-dialog.js';
19
+ export { ModelSelectorComponent } from './model-selector.js';
20
+ export { OAuthSelectorComponent } from './oauth-selector.js';
21
+ // SHORTCUT PATCH: removed ScopedModelsSelectorComponent export — scoped models removed
22
+ export { SessionSelectorComponent } from './session-selector.js';
23
+ export { SettingsSelectorComponent } from './settings-selector.js';
24
+ export { ShowImagesSelectorComponent } from './show-images-selector.js';
25
+ export { SkillInvocationMessageComponent } from './skill-invocation-message.js';
26
+ export { ThemeSelectorComponent } from './theme-selector.js';
27
+ export { ThinkingSelectorComponent } from './thinking-selector.js';
28
+ export { ToolExecutionComponent } from './tool-execution.js';
29
+ export { TreeSelectorComponent } from './tree-selector.js';
30
+ export { UserMessageSelectorComponent } from './user-message-selector.js';
31
+ export { UserMessageComponent } from './user-message.js';
32
+ export { truncateToVisualLines } from './visual-truncate.js';
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Utilities for formatting keybinding hints in the UI.
3
+ */
4
+ import { getEditorKeybindings } from '../../../tui/index.js';
5
+ import { theme } from '../../../core/theme.js';
6
+ /**
7
+ * Format keys array as display string (e.g., ["ctrl+c", "escape"] -> "ctrl+c/escape").
8
+ */
9
+ function formatKeys(keys) {
10
+ if (keys.length === 0)
11
+ return '';
12
+ if (keys.length === 1)
13
+ return keys[0];
14
+ return keys.join('/');
15
+ }
16
+ /**
17
+ * Get display string for an editor action.
18
+ */
19
+ export function editorKey(action) {
20
+ return formatKeys(getEditorKeybindings().getKeys(action));
21
+ }
22
+ /**
23
+ * Get display string for an app action.
24
+ */
25
+ export function appKey(keybindings, action) {
26
+ return formatKeys(keybindings.getKeys(action));
27
+ }
28
+ /**
29
+ * Format a keybinding hint with consistent styling: dim key, muted description.
30
+ * Looks up the key from editor keybindings automatically.
31
+ *
32
+ * @param action - Editor action name (e.g., "selectConfirm", "expandTools")
33
+ * @param description - Description text (e.g., "to expand", "cancel")
34
+ * @returns Formatted string with dim key and muted description
35
+ */
36
+ export function keyHint(action, description) {
37
+ return theme.fg('dim', editorKey(action)) + theme.fg('muted', ` ${description}`);
38
+ }
39
+ /**
40
+ * Format a keybinding hint for app-level actions.
41
+ * Requires the KeybindingsManager instance.
42
+ *
43
+ * @param keybindings - KeybindingsManager instance
44
+ * @param action - App action name (e.g., "interrupt", "externalEditor")
45
+ * @param description - Description text
46
+ * @returns Formatted string with dim key and muted description
47
+ */
48
+ export function appKeyHint(keybindings, action, description) {
49
+ return theme.fg('dim', appKey(keybindings, action)) + theme.fg('muted', ` ${description}`);
50
+ }
51
+ /**
52
+ * Format a raw key string with description (for non-configurable keys like ↑↓).
53
+ *
54
+ * @param key - Raw key string
55
+ * @param description - Description text
56
+ * @returns Formatted string with dim key and muted description
57
+ */
58
+ export function rawKeyHint(key, description) {
59
+ return theme.fg('dim', key) + theme.fg('muted', ` ${description}`);
60
+ }
61
+ //# sourceMappingURL=keybinding-hints.js.map
@@ -0,0 +1,64 @@
1
+ import { Container } from '../../../tui/index.js';
2
+ import { theme } from '../../../core/theme.js';
3
+ /** Standard horizontal padding for content that uses its own background (e.g. custom messages). */
4
+ export const CONTENT_PAD_X = 1;
5
+ /** Standard vertical padding (0 = no extra blank lines above/below). */
6
+ export const CONTENT_PAD_Y = 0;
7
+ /** Visible character width of the message prefix (symbol + trailing space). */
8
+ export const PREFIX_WIDTH = 2;
9
+ // ── Prefix generators ────────────────────────────────────────────────
10
+ export function userPrefix() {
11
+ return `${theme.fg('accent', '❯')} `;
12
+ }
13
+ export function assistantPrefix() {
14
+ return `${theme.fg('text', '●')} `;
15
+ }
16
+ export function toolPrefix(isPending, isError, blinkOn) {
17
+ if (isPending) {
18
+ return blinkOn ? `${theme.fg('warning', '●')} ` : `${theme.fg('dim', '●')} `;
19
+ }
20
+ return isError ? `${theme.fg('error', '●')} ` : `${theme.fg('success', '●')} `;
21
+ }
22
+ // ── Layout utilities ─────────────────────────────────────────────────
23
+ /**
24
+ * Prefix the first visible line of rendered output with a symbol,
25
+ * and indent all subsequent lines to maintain alignment.
26
+ *
27
+ * Lines before the first visible content (e.g. spacer blanks) are left untouched.
28
+ */
29
+ export function prefixLines(lines, prefix) {
30
+ const indent = ' '.repeat(PREFIX_WIDTH);
31
+ let firstDone = false;
32
+ for (let i = 0; i < lines.length; i++) {
33
+ if (!firstDone) {
34
+ if (lines[i].trim()) {
35
+ lines[i] = prefix + lines[i];
36
+ firstDone = true;
37
+ }
38
+ }
39
+ else {
40
+ lines[i] = indent + lines[i];
41
+ }
42
+ }
43
+ return lines;
44
+ }
45
+ /**
46
+ * A Container that prefixes children's rendered output with a symbol.
47
+ *
48
+ * Use when only *part* of a component's output should be prefixed
49
+ * (e.g. UserMessage wraps the text portion but not the annotation above it).
50
+ */
51
+ export class PrefixedContainer extends Container {
52
+ prefix;
53
+ constructor(prefix) {
54
+ super();
55
+ this.prefix = prefix;
56
+ }
57
+ setPrefix(prefix) {
58
+ this.prefix = prefix;
59
+ }
60
+ render(width) {
61
+ return prefixLines(super.render(width - PREFIX_WIDTH), this.prefix);
62
+ }
63
+ }
64
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1,148 @@
1
+ import { getOAuthProviders } from '@mariozechner/pi-ai';
2
+ import { Container, getEditorKeybindings, Input, Spacer, Text } from '../../../tui/index.js';
3
+ import { exec } from 'child_process';
4
+ import { theme } from '../../../core/theme.js';
5
+ import { DynamicBorder } from './dynamic-border.js';
6
+ import { keyHint } from './keybinding-hints.js';
7
+ /**
8
+ * Login dialog component - replaces editor during OAuth login flow
9
+ */
10
+ export class LoginDialogComponent extends Container {
11
+ onComplete;
12
+ contentContainer;
13
+ input;
14
+ tui;
15
+ abortController = new AbortController();
16
+ inputResolver;
17
+ inputRejecter;
18
+ // Focusable implementation - propagate to input for IME cursor positioning
19
+ _focused = false;
20
+ get focused() {
21
+ return this._focused;
22
+ }
23
+ set focused(value) {
24
+ this._focused = value;
25
+ this.input.focused = value;
26
+ }
27
+ constructor(tui, providerId, onComplete) {
28
+ super();
29
+ this.onComplete = onComplete;
30
+ this.tui = tui;
31
+ const providerInfo = getOAuthProviders().find((p) => p.id === providerId);
32
+ const providerName = providerInfo?.name || providerId;
33
+ // Top border
34
+ this.addChild(new DynamicBorder());
35
+ // Title
36
+ this.addChild(new Text(theme.fg('warning', `Login to ${providerName}`), 1, 0));
37
+ // Dynamic content area
38
+ this.contentContainer = new Container();
39
+ this.addChild(this.contentContainer);
40
+ // Input (always present, used when needed)
41
+ this.input = new Input();
42
+ this.input.onSubmit = () => {
43
+ if (this.inputResolver) {
44
+ this.inputResolver(this.input.getValue());
45
+ this.inputResolver = undefined;
46
+ this.inputRejecter = undefined;
47
+ }
48
+ };
49
+ this.input.onEscape = () => {
50
+ this.cancel();
51
+ };
52
+ // Bottom border
53
+ this.addChild(new DynamicBorder());
54
+ }
55
+ get signal() {
56
+ return this.abortController.signal;
57
+ }
58
+ cancel() {
59
+ this.abortController.abort();
60
+ if (this.inputRejecter) {
61
+ this.inputRejecter(new Error('Login cancelled'));
62
+ this.inputResolver = undefined;
63
+ this.inputRejecter = undefined;
64
+ }
65
+ this.onComplete(false, 'Login cancelled');
66
+ }
67
+ /**
68
+ * Called by onAuth callback - show URL and optional instructions
69
+ */
70
+ showAuth(url, instructions) {
71
+ this.contentContainer.clear();
72
+ this.contentContainer.addChild(new Spacer(1));
73
+ this.contentContainer.addChild(new Text(theme.fg('accent', url), 1, 0));
74
+ const clickHint = process.platform === 'darwin' ? 'Cmd+click to open' : 'Ctrl+click to open';
75
+ const hyperlink = `\x1b]8;;${url}\x07${clickHint}\x1b]8;;\x07`;
76
+ this.contentContainer.addChild(new Text(theme.fg('dim', hyperlink), 1, 0));
77
+ if (instructions) {
78
+ this.contentContainer.addChild(new Spacer(1));
79
+ this.contentContainer.addChild(new Text(theme.fg('warning', instructions), 1, 0));
80
+ }
81
+ // Try to open browser
82
+ // On Windows, 'start' needs an empty title ("") before the URL, otherwise
83
+ // it interprets the URL as a window title and opens a blank cmd window.
84
+ const openCmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
85
+ const cmd = process.platform === 'win32' ? `${openCmd} "" "${url}"` : `${openCmd} "${url}"`;
86
+ exec(cmd);
87
+ this.tui.requestRender();
88
+ }
89
+ /**
90
+ * Show input for manual code/URL entry (for callback server providers)
91
+ */
92
+ showManualInput(prompt) {
93
+ this.contentContainer.addChild(new Spacer(1));
94
+ this.contentContainer.addChild(new Text(theme.fg('dim', prompt), 1, 0));
95
+ this.contentContainer.addChild(this.input);
96
+ this.contentContainer.addChild(new Text(`(${keyHint('selectCancel', 'to cancel')})`, 1, 0));
97
+ this.tui.requestRender();
98
+ return new Promise((resolve, reject) => {
99
+ this.inputResolver = resolve;
100
+ this.inputRejecter = reject;
101
+ });
102
+ }
103
+ /**
104
+ * Called by onPrompt callback - show prompt and wait for input
105
+ * Note: Does NOT clear content, appends to existing (preserves URL from showAuth)
106
+ */
107
+ showPrompt(message, placeholder) {
108
+ this.contentContainer.addChild(new Spacer(1));
109
+ this.contentContainer.addChild(new Text(theme.fg('text', message), 1, 0));
110
+ if (placeholder) {
111
+ this.contentContainer.addChild(new Text(theme.fg('dim', `e.g., ${placeholder}`), 1, 0));
112
+ }
113
+ this.contentContainer.addChild(this.input);
114
+ this.contentContainer.addChild(new Text(`(${keyHint('selectCancel', 'to cancel,')} ${keyHint('selectConfirm', 'to submit')})`, 1, 0));
115
+ this.input.setValue('');
116
+ this.tui.requestRender();
117
+ return new Promise((resolve, reject) => {
118
+ this.inputResolver = resolve;
119
+ this.inputRejecter = reject;
120
+ });
121
+ }
122
+ /**
123
+ * Show waiting message (for polling flows like GitHub Copilot)
124
+ */
125
+ showWaiting(message) {
126
+ this.contentContainer.addChild(new Spacer(1));
127
+ this.contentContainer.addChild(new Text(theme.fg('dim', message), 1, 0));
128
+ this.contentContainer.addChild(new Text(`(${keyHint('selectCancel', 'to cancel')})`, 1, 0));
129
+ this.tui.requestRender();
130
+ }
131
+ /**
132
+ * Called by onProgress callback
133
+ */
134
+ showProgress(message) {
135
+ this.contentContainer.addChild(new Text(theme.fg('dim', message), 1, 0));
136
+ this.tui.requestRender();
137
+ }
138
+ handleInput(data) {
139
+ const kb = getEditorKeybindings();
140
+ if (kb.matches(data, 'selectCancel')) {
141
+ this.cancel();
142
+ return;
143
+ }
144
+ // Pass to input
145
+ this.input.handleInput(data);
146
+ }
147
+ }
148
+ //# sourceMappingURL=login-dialog.js.map