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,265 @@
1
+ /**
2
+ * One-time migrations that run on startup.
3
+ */
4
+ import chalk from 'chalk';
5
+ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'fs';
6
+ import { dirname, join } from 'path';
7
+ import { CONFIG_DIR_NAME, getAgentDir, getBinDir } from './config.js';
8
+ const MIGRATION_GUIDE_URL = 'https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration';
9
+ const EXTENSIONS_DOC_URL = 'https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/extensions.md';
10
+ /**
11
+ * Migrate legacy oauth.json and settings.json apiKeys to auth.json.
12
+ *
13
+ * @returns Array of provider names that were migrated
14
+ */
15
+ function migrateAuthToAuthJson() {
16
+ const agentDir = getAgentDir();
17
+ const authPath = join(agentDir, 'auth.json');
18
+ const oauthPath = join(agentDir, 'oauth.json');
19
+ const settingsPath = join(agentDir, 'settings.json');
20
+ // Skip if auth.json already exists
21
+ if (existsSync(authPath))
22
+ return [];
23
+ const migrated = {};
24
+ const providers = [];
25
+ // Migrate oauth.json
26
+ if (existsSync(oauthPath)) {
27
+ try {
28
+ const oauth = JSON.parse(readFileSync(oauthPath, 'utf-8'));
29
+ for (const [provider, cred] of Object.entries(oauth)) {
30
+ migrated[provider] = { type: 'oauth', ...cred };
31
+ providers.push(provider);
32
+ }
33
+ renameSync(oauthPath, `${oauthPath}.migrated`);
34
+ }
35
+ catch {
36
+ // Skip on error
37
+ }
38
+ }
39
+ // Migrate settings.json apiKeys
40
+ if (existsSync(settingsPath)) {
41
+ try {
42
+ const content = readFileSync(settingsPath, 'utf-8');
43
+ const settings = JSON.parse(content);
44
+ if (settings.apiKeys && typeof settings.apiKeys === 'object') {
45
+ for (const [provider, key] of Object.entries(settings.apiKeys)) {
46
+ if (!migrated[provider] && typeof key === 'string') {
47
+ migrated[provider] = { type: 'api_key', key };
48
+ providers.push(provider);
49
+ }
50
+ }
51
+ delete settings.apiKeys;
52
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
53
+ }
54
+ }
55
+ catch {
56
+ // Skip on error
57
+ }
58
+ }
59
+ if (Object.keys(migrated).length > 0) {
60
+ mkdirSync(dirname(authPath), { recursive: true });
61
+ writeFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });
62
+ }
63
+ return providers;
64
+ }
65
+ /**
66
+ * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.
67
+ *
68
+ * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of
69
+ * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them
70
+ * to the correct location based on the cwd in their session header.
71
+ *
72
+ * See: https://github.com/badlogic/pi-mono/issues/320
73
+ */
74
+ function migrateSessionsFromAgentRoot() {
75
+ const agentDir = getAgentDir();
76
+ // Find all .jsonl files directly in agentDir (not in subdirectories)
77
+ let files;
78
+ try {
79
+ files = readdirSync(agentDir)
80
+ .filter((f) => f.endsWith('.jsonl'))
81
+ .map((f) => join(agentDir, f));
82
+ }
83
+ catch {
84
+ return;
85
+ }
86
+ if (files.length === 0)
87
+ return;
88
+ for (const file of files) {
89
+ try {
90
+ // Read first line to get session header
91
+ const content = readFileSync(file, 'utf8');
92
+ const firstLine = content.split('\n')[0];
93
+ if (!firstLine?.trim())
94
+ continue;
95
+ const header = JSON.parse(firstLine);
96
+ if (header.type !== 'session' || !header.cwd)
97
+ continue;
98
+ const cwd = header.cwd;
99
+ // Compute the correct session directory (same encoding as session-manager.ts)
100
+ const safePath = `--${cwd.replace(/^[/\\]/, '').replace(/[/\\:]/g, '-')}--`;
101
+ const correctDir = join(agentDir, 'sessions', safePath);
102
+ // Create directory if needed
103
+ if (!existsSync(correctDir)) {
104
+ mkdirSync(correctDir, { recursive: true });
105
+ }
106
+ // Move the file
107
+ const fileName = file.split('/').pop() || file.split('\\').pop();
108
+ const newPath = join(correctDir, fileName);
109
+ if (existsSync(newPath))
110
+ continue; // Skip if target exists
111
+ renameSync(file, newPath);
112
+ }
113
+ catch {
114
+ // Skip files that can't be migrated
115
+ }
116
+ }
117
+ }
118
+ /**
119
+ * Migrate commands/ to prompts/ if needed.
120
+ * Works for both regular directories and symlinks.
121
+ */
122
+ function migrateCommandsToPrompts(baseDir, label) {
123
+ const commandsDir = join(baseDir, 'commands');
124
+ const promptsDir = join(baseDir, 'prompts');
125
+ if (existsSync(commandsDir) && !existsSync(promptsDir)) {
126
+ try {
127
+ renameSync(commandsDir, promptsDir);
128
+ console.log(chalk.green(`Migrated ${label} commands/ → prompts/`));
129
+ return true;
130
+ }
131
+ catch (err) {
132
+ console.log(chalk.yellow(`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`));
133
+ }
134
+ }
135
+ return false;
136
+ }
137
+ /**
138
+ * Move fd/rg binaries from tools/ to bin/ if they exist.
139
+ */
140
+ function migrateToolsToBin() {
141
+ const agentDir = getAgentDir();
142
+ const toolsDir = join(agentDir, 'tools');
143
+ const binDir = getBinDir();
144
+ if (!existsSync(toolsDir))
145
+ return;
146
+ const binaries = ['fd', 'rg', 'fd.exe', 'rg.exe'];
147
+ let movedAny = false;
148
+ for (const bin of binaries) {
149
+ const oldPath = join(toolsDir, bin);
150
+ const newPath = join(binDir, bin);
151
+ if (existsSync(oldPath)) {
152
+ if (!existsSync(binDir)) {
153
+ mkdirSync(binDir, { recursive: true });
154
+ }
155
+ if (!existsSync(newPath)) {
156
+ try {
157
+ renameSync(oldPath, newPath);
158
+ movedAny = true;
159
+ }
160
+ catch {
161
+ // Ignore errors
162
+ }
163
+ }
164
+ else {
165
+ // Target exists, just delete the old one
166
+ try {
167
+ rmSync?.(oldPath, { force: true });
168
+ }
169
+ catch {
170
+ // Ignore
171
+ }
172
+ }
173
+ }
174
+ }
175
+ if (movedAny) {
176
+ console.log(chalk.green(`Migrated managed binaries tools/ → bin/`));
177
+ }
178
+ }
179
+ /**
180
+ * Check for deprecated hooks/ and tools/ directories.
181
+ * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.
182
+ */
183
+ function checkDeprecatedExtensionDirs(baseDir, label) {
184
+ const hooksDir = join(baseDir, 'hooks');
185
+ const toolsDir = join(baseDir, 'tools');
186
+ const warnings = [];
187
+ if (existsSync(hooksDir)) {
188
+ warnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);
189
+ }
190
+ if (existsSync(toolsDir)) {
191
+ // Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)
192
+ try {
193
+ const entries = readdirSync(toolsDir);
194
+ const customTools = entries.filter((e) => {
195
+ const lower = e.toLowerCase();
196
+ return (lower !== 'fd' &&
197
+ lower !== 'rg' &&
198
+ lower !== 'fd.exe' &&
199
+ lower !== 'rg.exe' &&
200
+ !e.startsWith('.') // Ignore .DS_Store and other hidden files
201
+ );
202
+ });
203
+ if (customTools.length > 0) {
204
+ warnings.push(`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`);
205
+ }
206
+ }
207
+ catch {
208
+ // Ignore read errors
209
+ }
210
+ }
211
+ return warnings;
212
+ }
213
+ /**
214
+ * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.
215
+ */
216
+ function migrateExtensionSystem(cwd) {
217
+ const agentDir = getAgentDir();
218
+ const projectDir = join(cwd, CONFIG_DIR_NAME);
219
+ // Migrate commands/ to prompts/
220
+ migrateCommandsToPrompts(agentDir, 'Global');
221
+ migrateCommandsToPrompts(projectDir, 'Project');
222
+ // Check for deprecated directories
223
+ const warnings = [
224
+ ...checkDeprecatedExtensionDirs(agentDir, 'Global'),
225
+ ...checkDeprecatedExtensionDirs(projectDir, 'Project')
226
+ ];
227
+ return warnings;
228
+ }
229
+ /**
230
+ * Print deprecation warnings and wait for keypress.
231
+ */
232
+ export async function showDeprecationWarnings(warnings) {
233
+ if (warnings.length === 0)
234
+ return;
235
+ for (const warning of warnings) {
236
+ console.log(chalk.yellow(`Warning: ${warning}`));
237
+ }
238
+ console.log(chalk.yellow(`\nMove your extensions to the extensions/ directory.`));
239
+ console.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));
240
+ console.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));
241
+ console.log(chalk.dim(`\nPress any key to continue...`));
242
+ await new Promise((resolve) => {
243
+ process.stdin.setRawMode?.(true);
244
+ process.stdin.resume();
245
+ process.stdin.once('data', () => {
246
+ process.stdin.setRawMode?.(false);
247
+ process.stdin.pause();
248
+ resolve();
249
+ });
250
+ });
251
+ console.log();
252
+ }
253
+ /**
254
+ * Run all migrations. Called once on startup.
255
+ *
256
+ * @returns Object with migration results and deprecation warnings
257
+ */
258
+ export function runMigrations(cwd = process.cwd()) {
259
+ const migratedAuthProviders = migrateAuthToAuthJson();
260
+ migrateSessionsFromAgentRoot();
261
+ migrateToolsToBin();
262
+ const deprecationWarnings = migrateExtensionSystem(cwd);
263
+ return { migratedAuthProviders, deprecationWarnings };
264
+ }
265
+ //# sourceMappingURL=migrations.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Run modes for the coding agent.
3
+ */
4
+ export { InteractiveMode } from './interactive/interactive-mode.js';
5
+ export { runPrintMode } from './print-mode.js';
6
+ export { RpcClient } from './rpc/rpc-client.js';
7
+ export { runRpcMode } from './rpc/rpc-mode.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,337 @@
1
+ /**
2
+ * Armin says hi! A fun easter egg with animated XBM art.
3
+ */
4
+ import { theme } from '../../../core/theme.js';
5
+ // XBM image: 31x36 pixels, LSB first, 1=background, 0=foreground
6
+ const WIDTH = 31;
7
+ const HEIGHT = 36;
8
+ const BITS = [
9
+ 0xff, 0xff, 0xff, 0x7f, 0xff, 0xf0, 0xff, 0x7f, 0xff, 0xed, 0xff, 0x7f, 0xff, 0xdb, 0xff, 0x7f,
10
+ 0xff, 0xb7, 0xff, 0x7f, 0xff, 0x77, 0xfe, 0x7f, 0x3f, 0xf8, 0xfe, 0x7f, 0xdf, 0xff, 0xfe, 0x7f,
11
+ 0xdf, 0x3f, 0xfc, 0x7f, 0x9f, 0xc3, 0xfb, 0x7f, 0x6f, 0xfc, 0xf4, 0x7f, 0xf7, 0x0f, 0xf7, 0x7f,
12
+ 0xf7, 0xff, 0xf7, 0x7f, 0xf7, 0xff, 0xe3, 0x7f, 0xf7, 0x07, 0xe8, 0x7f, 0xef, 0xf8, 0x67, 0x70,
13
+ 0x0f, 0xff, 0xbb, 0x6f, 0xf1, 0x00, 0xd0, 0x5b, 0xfd, 0x3f, 0xec, 0x53, 0xc1, 0xff, 0xef, 0x57,
14
+ 0x9f, 0xfd, 0xee, 0x5f, 0x9f, 0xfc, 0xae, 0x5f, 0x1f, 0x78, 0xac, 0x5f, 0x3f, 0x00, 0x50, 0x6c,
15
+ 0x7f, 0x00, 0xdc, 0x77, 0xff, 0xc0, 0x3f, 0x78, 0xff, 0x01, 0xf8, 0x7f, 0xff, 0x03, 0x9c, 0x78,
16
+ 0xff, 0x07, 0x8c, 0x7c, 0xff, 0x0f, 0xce, 0x78, 0xff, 0xff, 0xcf, 0x7f, 0xff, 0xff, 0xcf, 0x78,
17
+ 0xff, 0xff, 0xdf, 0x78, 0xff, 0xff, 0xdf, 0x7d, 0xff, 0xff, 0x3f, 0x7e, 0xff, 0xff, 0xff, 0x7f
18
+ ];
19
+ const BYTES_PER_ROW = Math.ceil(WIDTH / 8);
20
+ const DISPLAY_HEIGHT = Math.ceil(HEIGHT / 2); // Half-block rendering
21
+ const EFFECTS = ['typewriter', 'scanline', 'rain', 'fade', 'crt', 'glitch', 'dissolve'];
22
+ // Get pixel at (x, y): true = foreground, false = background
23
+ function getPixel(x, y) {
24
+ if (y >= HEIGHT)
25
+ return false;
26
+ const byteIndex = y * BYTES_PER_ROW + Math.floor(x / 8);
27
+ const bitIndex = x % 8;
28
+ return ((BITS[byteIndex] >> bitIndex) & 1) === 0;
29
+ }
30
+ // Get the character for a cell (2 vertical pixels packed)
31
+ function getChar(x, row) {
32
+ const upper = getPixel(x, row * 2);
33
+ const lower = getPixel(x, row * 2 + 1);
34
+ if (upper && lower)
35
+ return '█';
36
+ if (upper)
37
+ return '▀';
38
+ if (lower)
39
+ return '▄';
40
+ return ' ';
41
+ }
42
+ // Build the final image grid
43
+ function buildFinalGrid() {
44
+ const grid = [];
45
+ for (let row = 0; row < DISPLAY_HEIGHT; row++) {
46
+ const line = [];
47
+ for (let x = 0; x < WIDTH; x++) {
48
+ line.push(getChar(x, row));
49
+ }
50
+ grid.push(line);
51
+ }
52
+ return grid;
53
+ }
54
+ export class ArminComponent {
55
+ ui;
56
+ interval = null;
57
+ effect;
58
+ finalGrid;
59
+ currentGrid;
60
+ effectState = {};
61
+ cachedLines = [];
62
+ cachedWidth = 0;
63
+ gridVersion = 0;
64
+ cachedVersion = -1;
65
+ constructor(ui) {
66
+ this.ui = ui;
67
+ this.effect = EFFECTS[Math.floor(Math.random() * EFFECTS.length)];
68
+ this.finalGrid = buildFinalGrid();
69
+ this.currentGrid = this.createEmptyGrid();
70
+ this.initEffect();
71
+ this.startAnimation();
72
+ }
73
+ invalidate() {
74
+ this.cachedWidth = 0;
75
+ }
76
+ render(width) {
77
+ if (width === this.cachedWidth && this.cachedVersion === this.gridVersion) {
78
+ return this.cachedLines;
79
+ }
80
+ const padding = 1;
81
+ const availableWidth = width - padding;
82
+ this.cachedLines = this.currentGrid.map((row) => {
83
+ // Clip row to available width before applying color
84
+ const clipped = row.slice(0, availableWidth).join('');
85
+ const padRight = Math.max(0, width - padding - clipped.length);
86
+ return ` ${theme.fg('accent', clipped)}${' '.repeat(padRight)}`;
87
+ });
88
+ // Add "ARMIN SAYS HI" at the end
89
+ const message = 'ARMIN SAYS HI';
90
+ const msgPadRight = Math.max(0, width - padding - message.length);
91
+ this.cachedLines.push(` ${theme.fg('accent', message)}${' '.repeat(msgPadRight)}`);
92
+ this.cachedWidth = width;
93
+ this.cachedVersion = this.gridVersion;
94
+ return this.cachedLines;
95
+ }
96
+ createEmptyGrid() {
97
+ return Array.from({ length: DISPLAY_HEIGHT }, () => Array(WIDTH).fill(' '));
98
+ }
99
+ initEffect() {
100
+ switch (this.effect) {
101
+ case 'typewriter':
102
+ this.effectState = { pos: 0 };
103
+ break;
104
+ case 'scanline':
105
+ this.effectState = { row: 0 };
106
+ break;
107
+ case 'rain':
108
+ // Track falling position for each column
109
+ this.effectState = {
110
+ drops: Array.from({ length: WIDTH }, () => ({
111
+ y: -Math.floor(Math.random() * DISPLAY_HEIGHT * 2),
112
+ settled: 0
113
+ }))
114
+ };
115
+ break;
116
+ case 'fade': {
117
+ // Shuffle all pixel positions
118
+ const positions = [];
119
+ for (let row = 0; row < DISPLAY_HEIGHT; row++) {
120
+ for (let x = 0; x < WIDTH; x++) {
121
+ positions.push([row, x]);
122
+ }
123
+ }
124
+ // Fisher-Yates shuffle
125
+ for (let i = positions.length - 1; i > 0; i--) {
126
+ const j = Math.floor(Math.random() * (i + 1));
127
+ [positions[i], positions[j]] = [positions[j], positions[i]];
128
+ }
129
+ this.effectState = { positions, idx: 0 };
130
+ break;
131
+ }
132
+ case 'crt':
133
+ this.effectState = { expansion: 0 };
134
+ break;
135
+ case 'glitch':
136
+ this.effectState = { phase: 0, glitchFrames: 8 };
137
+ break;
138
+ case 'dissolve': {
139
+ // Start with random noise
140
+ this.currentGrid = Array.from({ length: DISPLAY_HEIGHT }, () => Array.from({ length: WIDTH }, () => {
141
+ const chars = [' ', '░', '▒', '▓', '█', '▀', '▄'];
142
+ return chars[Math.floor(Math.random() * chars.length)];
143
+ }));
144
+ // Shuffle positions for gradual resolve
145
+ const dissolvePositions = [];
146
+ for (let row = 0; row < DISPLAY_HEIGHT; row++) {
147
+ for (let x = 0; x < WIDTH; x++) {
148
+ dissolvePositions.push([row, x]);
149
+ }
150
+ }
151
+ for (let i = dissolvePositions.length - 1; i > 0; i--) {
152
+ const j = Math.floor(Math.random() * (i + 1));
153
+ [dissolvePositions[i], dissolvePositions[j]] = [
154
+ dissolvePositions[j],
155
+ dissolvePositions[i]
156
+ ];
157
+ }
158
+ this.effectState = { positions: dissolvePositions, idx: 0 };
159
+ break;
160
+ }
161
+ }
162
+ }
163
+ startAnimation() {
164
+ const fps = this.effect === 'glitch' ? 60 : 30;
165
+ this.interval = setInterval(() => {
166
+ const done = this.tickEffect();
167
+ this.updateDisplay();
168
+ this.ui.requestRender();
169
+ if (done) {
170
+ this.stopAnimation();
171
+ }
172
+ }, 1000 / fps);
173
+ }
174
+ stopAnimation() {
175
+ if (this.interval) {
176
+ clearInterval(this.interval);
177
+ this.interval = null;
178
+ }
179
+ }
180
+ tickEffect() {
181
+ switch (this.effect) {
182
+ case 'typewriter':
183
+ return this.tickTypewriter();
184
+ case 'scanline':
185
+ return this.tickScanline();
186
+ case 'rain':
187
+ return this.tickRain();
188
+ case 'fade':
189
+ return this.tickFade();
190
+ case 'crt':
191
+ return this.tickCrt();
192
+ case 'glitch':
193
+ return this.tickGlitch();
194
+ case 'dissolve':
195
+ return this.tickDissolve();
196
+ default:
197
+ return true;
198
+ }
199
+ }
200
+ tickTypewriter() {
201
+ const state = this.effectState;
202
+ const pixelsPerFrame = 3;
203
+ for (let i = 0; i < pixelsPerFrame; i++) {
204
+ const row = Math.floor(state.pos / WIDTH);
205
+ const x = state.pos % WIDTH;
206
+ if (row >= DISPLAY_HEIGHT)
207
+ return true;
208
+ this.currentGrid[row][x] = this.finalGrid[row][x];
209
+ state.pos++;
210
+ }
211
+ return false;
212
+ }
213
+ tickScanline() {
214
+ const state = this.effectState;
215
+ if (state.row >= DISPLAY_HEIGHT)
216
+ return true;
217
+ // Copy row
218
+ for (let x = 0; x < WIDTH; x++) {
219
+ this.currentGrid[state.row][x] = this.finalGrid[state.row][x];
220
+ }
221
+ state.row++;
222
+ return false;
223
+ }
224
+ tickRain() {
225
+ const state = this.effectState;
226
+ let allSettled = true;
227
+ this.currentGrid = this.createEmptyGrid();
228
+ for (let x = 0; x < WIDTH; x++) {
229
+ const drop = state.drops[x];
230
+ // Draw settled pixels
231
+ for (let row = DISPLAY_HEIGHT - 1; row >= DISPLAY_HEIGHT - drop.settled; row--) {
232
+ if (row >= 0) {
233
+ this.currentGrid[row][x] = this.finalGrid[row][x];
234
+ }
235
+ }
236
+ // Check if this column is done
237
+ if (drop.settled >= DISPLAY_HEIGHT)
238
+ continue;
239
+ allSettled = false;
240
+ // Find the target row for this column (lowest non-space pixel)
241
+ let targetRow = -1;
242
+ for (let row = DISPLAY_HEIGHT - 1 - drop.settled; row >= 0; row--) {
243
+ if (this.finalGrid[row][x] !== ' ') {
244
+ targetRow = row;
245
+ break;
246
+ }
247
+ }
248
+ // Move drop down
249
+ drop.y++;
250
+ // Draw falling drop
251
+ if (drop.y >= 0 && drop.y < DISPLAY_HEIGHT) {
252
+ if (targetRow >= 0 && drop.y >= targetRow) {
253
+ // Settle
254
+ drop.settled = DISPLAY_HEIGHT - targetRow;
255
+ drop.y = -Math.floor(Math.random() * 5) - 1;
256
+ }
257
+ else {
258
+ // Still falling
259
+ this.currentGrid[drop.y][x] = '▓';
260
+ }
261
+ }
262
+ }
263
+ return allSettled;
264
+ }
265
+ tickFade() {
266
+ const state = this.effectState;
267
+ const pixelsPerFrame = 15;
268
+ for (let i = 0; i < pixelsPerFrame; i++) {
269
+ if (state.idx >= state.positions.length)
270
+ return true;
271
+ const [row, x] = state.positions[state.idx];
272
+ this.currentGrid[row][x] = this.finalGrid[row][x];
273
+ state.idx++;
274
+ }
275
+ return false;
276
+ }
277
+ tickCrt() {
278
+ const state = this.effectState;
279
+ const midRow = Math.floor(DISPLAY_HEIGHT / 2);
280
+ this.currentGrid = this.createEmptyGrid();
281
+ // Draw from middle expanding outward
282
+ const top = midRow - state.expansion;
283
+ const bottom = midRow + state.expansion;
284
+ for (let row = Math.max(0, top); row <= Math.min(DISPLAY_HEIGHT - 1, bottom); row++) {
285
+ for (let x = 0; x < WIDTH; x++) {
286
+ this.currentGrid[row][x] = this.finalGrid[row][x];
287
+ }
288
+ }
289
+ state.expansion++;
290
+ return state.expansion > DISPLAY_HEIGHT;
291
+ }
292
+ tickGlitch() {
293
+ const state = this.effectState;
294
+ if (state.phase < state.glitchFrames) {
295
+ // Glitch phase: show corrupted version
296
+ this.currentGrid = this.finalGrid.map((row) => {
297
+ const offset = Math.floor(Math.random() * 7) - 3;
298
+ const glitchRow = [...row];
299
+ // Random horizontal offset
300
+ if (Math.random() < 0.3) {
301
+ const shifted = glitchRow.slice(offset).concat(glitchRow.slice(0, offset));
302
+ return shifted.slice(0, WIDTH);
303
+ }
304
+ // Random vertical swap
305
+ if (Math.random() < 0.2) {
306
+ const swapRow = Math.floor(Math.random() * DISPLAY_HEIGHT);
307
+ return [...this.finalGrid[swapRow]];
308
+ }
309
+ return glitchRow;
310
+ });
311
+ state.phase++;
312
+ return false;
313
+ }
314
+ // Final frame: show clean image
315
+ this.currentGrid = this.finalGrid.map((row) => [...row]);
316
+ return true;
317
+ }
318
+ tickDissolve() {
319
+ const state = this.effectState;
320
+ const pixelsPerFrame = 20;
321
+ for (let i = 0; i < pixelsPerFrame; i++) {
322
+ if (state.idx >= state.positions.length)
323
+ return true;
324
+ const [row, x] = state.positions[state.idx];
325
+ this.currentGrid[row][x] = this.finalGrid[row][x];
326
+ state.idx++;
327
+ }
328
+ return false;
329
+ }
330
+ updateDisplay() {
331
+ this.gridVersion++;
332
+ }
333
+ dispose() {
334
+ this.stopAnimation();
335
+ }
336
+ }
337
+ //# sourceMappingURL=armin.js.map