@openeryc/pi-coding-agent 0.75.26 → 0.75.28

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 (313) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cli/config-selector.d.ts +1 -13
  3. package/dist/cli/config-selector.d.ts.map +1 -1
  4. package/dist/cli/config-selector.js +4 -29
  5. package/dist/cli/config-selector.js.map +1 -1
  6. package/dist/cli/list-models.d.ts.map +1 -1
  7. package/dist/cli/list-models.js +1 -1
  8. package/dist/cli/list-models.js.map +1 -1
  9. package/dist/core/agent-session.d.ts +0 -2
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +12 -20
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  14. package/dist/core/export-html/tool-renderer.js.map +1 -1
  15. package/dist/core/extensions/loader.d.ts.map +1 -1
  16. package/dist/core/extensions/loader.js +1 -1
  17. package/dist/core/extensions/loader.js.map +1 -1
  18. package/dist/core/extensions/runner.d.ts +1 -1
  19. package/dist/core/extensions/runner.d.ts.map +1 -1
  20. package/dist/core/extensions/runner.js +1 -1
  21. package/dist/core/extensions/runner.js.map +1 -1
  22. package/dist/core/extensions/types.d.ts +1 -1
  23. package/dist/core/extensions/types.d.ts.map +1 -1
  24. package/dist/core/extensions/types.js.map +1 -1
  25. package/dist/core/keybindings.d.ts +7 -135
  26. package/dist/core/keybindings.d.ts.map +1 -1
  27. package/dist/core/keybindings.js +1 -1
  28. package/dist/core/keybindings.js.map +1 -1
  29. package/dist/core/mcp/client.d.ts +30 -11
  30. package/dist/core/mcp/client.d.ts.map +1 -1
  31. package/dist/core/mcp/client.js +55 -110
  32. package/dist/core/mcp/client.js.map +1 -1
  33. package/dist/core/mcp/index.d.ts +1 -3
  34. package/dist/core/mcp/index.d.ts.map +1 -1
  35. package/dist/core/mcp/index.js.map +1 -1
  36. package/dist/core/mcp/manager.d.ts +3 -9
  37. package/dist/core/mcp/manager.d.ts.map +1 -1
  38. package/dist/core/mcp/manager.js +71 -105
  39. package/dist/core/mcp/manager.js.map +1 -1
  40. package/dist/core/tools/bash.d.ts.map +1 -1
  41. package/dist/core/tools/bash.js +1 -1
  42. package/dist/core/tools/bash.js.map +1 -1
  43. package/dist/core/tools/edit.d.ts +1 -1
  44. package/dist/core/tools/edit.d.ts.map +1 -1
  45. package/dist/core/tools/edit.js +1 -1
  46. package/dist/core/tools/edit.js.map +1 -1
  47. package/dist/core/tools/find.d.ts.map +1 -1
  48. package/dist/core/tools/find.js +1 -1
  49. package/dist/core/tools/find.js.map +1 -1
  50. package/dist/core/tools/grep.d.ts.map +1 -1
  51. package/dist/core/tools/grep.js +1 -1
  52. package/dist/core/tools/grep.js.map +1 -1
  53. package/dist/core/tools/index.d.ts +3 -1
  54. package/dist/core/tools/index.d.ts.map +1 -1
  55. package/dist/core/tools/index.js +27 -1
  56. package/dist/core/tools/index.js.map +1 -1
  57. package/dist/core/tools/ls.d.ts.map +1 -1
  58. package/dist/core/tools/ls.js +1 -1
  59. package/dist/core/tools/ls.js.map +1 -1
  60. package/dist/core/tools/read.d.ts.map +1 -1
  61. package/dist/core/tools/read.js +1 -1
  62. package/dist/core/tools/read.js.map +1 -1
  63. package/dist/core/tools/render-utils.d.ts.map +1 -1
  64. package/dist/core/tools/render-utils.js +1 -1
  65. package/dist/core/tools/render-utils.js.map +1 -1
  66. package/dist/core/tools/web-fetch.d.ts +15 -0
  67. package/dist/core/tools/web-fetch.d.ts.map +1 -0
  68. package/dist/core/tools/web-fetch.js +52 -0
  69. package/dist/core/tools/web-fetch.js.map +1 -0
  70. package/dist/core/tools/web-search.d.ts +18 -0
  71. package/dist/core/tools/web-search.d.ts.map +1 -0
  72. package/dist/core/tools/web-search.js +83 -0
  73. package/dist/core/tools/web-search.js.map +1 -0
  74. package/dist/core/tools/write.d.ts.map +1 -1
  75. package/dist/core/tools/write.js +1 -1
  76. package/dist/core/tools/write.js.map +1 -1
  77. package/dist/core/tui-stubs.d.ts +95 -0
  78. package/dist/core/tui-stubs.d.ts.map +1 -0
  79. package/dist/core/tui-stubs.js +90 -0
  80. package/dist/core/tui-stubs.js.map +1 -0
  81. package/dist/index.d.ts +5 -3
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +7 -5
  84. package/dist/index.js.map +1 -1
  85. package/dist/main.d.ts.map +1 -1
  86. package/dist/main.js +92 -106
  87. package/dist/main.js.map +1 -1
  88. package/dist/modes/index.d.ts +0 -4
  89. package/dist/modes/index.d.ts.map +1 -1
  90. package/dist/modes/index.js +0 -4
  91. package/dist/modes/index.js.map +1 -1
  92. package/dist/modes/interactive/components/diff.d.ts +1 -8
  93. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  94. package/dist/modes/interactive/components/diff.js +2 -131
  95. package/dist/modes/interactive/components/diff.js.map +1 -1
  96. package/dist/modes/interactive/components/keybinding-hints.d.ts +2 -12
  97. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  98. package/dist/modes/interactive/components/keybinding-hints.js +4 -33
  99. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  100. package/dist/modes/interactive/components/visual-truncate.d.ts +1 -19
  101. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  102. package/dist/modes/interactive/components/visual-truncate.js +4 -31
  103. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  104. package/dist/modes/interactive/theme/theme.d.ts +27 -89
  105. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  106. package/dist/modes/interactive/theme/theme.js +44 -992
  107. package/dist/modes/interactive/theme/theme.js.map +1 -1
  108. package/dist/package-manager-cli.d.ts.map +1 -1
  109. package/dist/package-manager-cli.js +1 -1
  110. package/dist/package-manager-cli.js.map +1 -1
  111. package/npm-shrinkwrap.json +240 -246
  112. package/package.json +6 -7
  113. package/dist/cli/session-picker.d.ts +0 -9
  114. package/dist/cli/session-picker.d.ts.map +0 -1
  115. package/dist/cli/session-picker.js +0 -35
  116. package/dist/cli/session-picker.js.map +0 -1
  117. package/dist/core/mcp/types.d.ts +0 -86
  118. package/dist/core/mcp/types.d.ts.map +0 -1
  119. package/dist/core/mcp/types.js +0 -8
  120. package/dist/core/mcp/types.js.map +0 -1
  121. package/dist/modes/interactive/assets/clankolas.png +0 -0
  122. package/dist/modes/interactive/components/armin.d.ts +0 -34
  123. package/dist/modes/interactive/components/armin.d.ts.map +0 -1
  124. package/dist/modes/interactive/components/armin.js +0 -333
  125. package/dist/modes/interactive/components/armin.js.map +0 -1
  126. package/dist/modes/interactive/components/assistant-message.d.ts +0 -20
  127. package/dist/modes/interactive/components/assistant-message.d.ts.map +0 -1
  128. package/dist/modes/interactive/components/assistant-message.js +0 -121
  129. package/dist/modes/interactive/components/assistant-message.js.map +0 -1
  130. package/dist/modes/interactive/components/bash-execution.d.ts +0 -34
  131. package/dist/modes/interactive/components/bash-execution.d.ts.map +0 -1
  132. package/dist/modes/interactive/components/bash-execution.js +0 -175
  133. package/dist/modes/interactive/components/bash-execution.js.map +0 -1
  134. package/dist/modes/interactive/components/bordered-loader.d.ts +0 -16
  135. package/dist/modes/interactive/components/bordered-loader.d.ts.map +0 -1
  136. package/dist/modes/interactive/components/bordered-loader.js +0 -54
  137. package/dist/modes/interactive/components/bordered-loader.js.map +0 -1
  138. package/dist/modes/interactive/components/branch-summary-message.d.ts +0 -16
  139. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +0 -1
  140. package/dist/modes/interactive/components/branch-summary-message.js +0 -44
  141. package/dist/modes/interactive/components/branch-summary-message.js.map +0 -1
  142. package/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
  143. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +0 -1
  144. package/dist/modes/interactive/components/compaction-summary-message.js +0 -45
  145. package/dist/modes/interactive/components/compaction-summary-message.js.map +0 -1
  146. package/dist/modes/interactive/components/config-selector.d.ts +0 -71
  147. package/dist/modes/interactive/components/config-selector.d.ts.map +0 -1
  148. package/dist/modes/interactive/components/config-selector.js +0 -506
  149. package/dist/modes/interactive/components/config-selector.js.map +0 -1
  150. package/dist/modes/interactive/components/countdown-timer.d.ts +0 -14
  151. package/dist/modes/interactive/components/countdown-timer.d.ts.map +0 -1
  152. package/dist/modes/interactive/components/countdown-timer.js +0 -33
  153. package/dist/modes/interactive/components/countdown-timer.js.map +0 -1
  154. package/dist/modes/interactive/components/custom-editor.d.ts +0 -21
  155. package/dist/modes/interactive/components/custom-editor.d.ts.map +0 -1
  156. package/dist/modes/interactive/components/custom-editor.js +0 -70
  157. package/dist/modes/interactive/components/custom-editor.js.map +0 -1
  158. package/dist/modes/interactive/components/custom-message.d.ts +0 -20
  159. package/dist/modes/interactive/components/custom-message.d.ts.map +0 -1
  160. package/dist/modes/interactive/components/custom-message.js +0 -79
  161. package/dist/modes/interactive/components/custom-message.js.map +0 -1
  162. package/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  163. package/dist/modes/interactive/components/daxnuts.d.ts.map +0 -1
  164. package/dist/modes/interactive/components/daxnuts.js +0 -140
  165. package/dist/modes/interactive/components/daxnuts.js.map +0 -1
  166. package/dist/modes/interactive/components/dynamic-border.d.ts +0 -15
  167. package/dist/modes/interactive/components/dynamic-border.d.ts.map +0 -1
  168. package/dist/modes/interactive/components/dynamic-border.js +0 -21
  169. package/dist/modes/interactive/components/dynamic-border.js.map +0 -1
  170. package/dist/modes/interactive/components/earendil-announcement.d.ts +0 -5
  171. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +0 -1
  172. package/dist/modes/interactive/components/earendil-announcement.js +0 -40
  173. package/dist/modes/interactive/components/earendil-announcement.js.map +0 -1
  174. package/dist/modes/interactive/components/extension-editor.d.ts +0 -20
  175. package/dist/modes/interactive/components/extension-editor.d.ts.map +0 -1
  176. package/dist/modes/interactive/components/extension-editor.js +0 -119
  177. package/dist/modes/interactive/components/extension-editor.js.map +0 -1
  178. package/dist/modes/interactive/components/extension-input.d.ts +0 -23
  179. package/dist/modes/interactive/components/extension-input.d.ts.map +0 -1
  180. package/dist/modes/interactive/components/extension-input.js +0 -61
  181. package/dist/modes/interactive/components/extension-input.js.map +0 -1
  182. package/dist/modes/interactive/components/extension-selector.d.ts +0 -26
  183. package/dist/modes/interactive/components/extension-selector.d.ts.map +0 -1
  184. package/dist/modes/interactive/components/extension-selector.js +0 -83
  185. package/dist/modes/interactive/components/extension-selector.js.map +0 -1
  186. package/dist/modes/interactive/components/footer.d.ts +0 -27
  187. package/dist/modes/interactive/components/footer.d.ts.map +0 -1
  188. package/dist/modes/interactive/components/footer.js +0 -201
  189. package/dist/modes/interactive/components/footer.js.map +0 -1
  190. package/dist/modes/interactive/components/index.d.ts +0 -32
  191. package/dist/modes/interactive/components/index.d.ts.map +0 -1
  192. package/dist/modes/interactive/components/index.js +0 -33
  193. package/dist/modes/interactive/components/index.js.map +0 -1
  194. package/dist/modes/interactive/components/login-dialog.d.ts +0 -46
  195. package/dist/modes/interactive/components/login-dialog.d.ts.map +0 -1
  196. package/dist/modes/interactive/components/login-dialog.js +0 -160
  197. package/dist/modes/interactive/components/login-dialog.js.map +0 -1
  198. package/dist/modes/interactive/components/model-selector.d.ts +0 -47
  199. package/dist/modes/interactive/components/model-selector.d.ts.map +0 -1
  200. package/dist/modes/interactive/components/model-selector.js +0 -278
  201. package/dist/modes/interactive/components/model-selector.js.map +0 -1
  202. package/dist/modes/interactive/components/oauth-selector.d.ts +0 -31
  203. package/dist/modes/interactive/components/oauth-selector.d.ts.map +0 -1
  204. package/dist/modes/interactive/components/oauth-selector.js +0 -165
  205. package/dist/modes/interactive/components/oauth-selector.js.map +0 -1
  206. package/dist/modes/interactive/components/scoped-models-selector.d.ts +0 -42
  207. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +0 -1
  208. package/dist/modes/interactive/components/scoped-models-selector.js +0 -290
  209. package/dist/modes/interactive/components/scoped-models-selector.js.map +0 -1
  210. package/dist/modes/interactive/components/session-selector-search.d.ts +0 -23
  211. package/dist/modes/interactive/components/session-selector-search.d.ts.map +0 -1
  212. package/dist/modes/interactive/components/session-selector-search.js +0 -155
  213. package/dist/modes/interactive/components/session-selector-search.js.map +0 -1
  214. package/dist/modes/interactive/components/session-selector.d.ts +0 -96
  215. package/dist/modes/interactive/components/session-selector.d.ts.map +0 -1
  216. package/dist/modes/interactive/components/session-selector.js +0 -861
  217. package/dist/modes/interactive/components/session-selector.js.map +0 -1
  218. package/dist/modes/interactive/components/settings-selector.d.ts +0 -69
  219. package/dist/modes/interactive/components/settings-selector.d.ts.map +0 -1
  220. package/dist/modes/interactive/components/settings-selector.js +0 -390
  221. package/dist/modes/interactive/components/settings-selector.js.map +0 -1
  222. package/dist/modes/interactive/components/show-images-selector.d.ts +0 -10
  223. package/dist/modes/interactive/components/show-images-selector.d.ts.map +0 -1
  224. package/dist/modes/interactive/components/show-images-selector.js +0 -39
  225. package/dist/modes/interactive/components/show-images-selector.js.map +0 -1
  226. package/dist/modes/interactive/components/skill-invocation-message.d.ts +0 -17
  227. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +0 -1
  228. package/dist/modes/interactive/components/skill-invocation-message.js +0 -47
  229. package/dist/modes/interactive/components/skill-invocation-message.js.map +0 -1
  230. package/dist/modes/interactive/components/theme-selector.d.ts +0 -11
  231. package/dist/modes/interactive/components/theme-selector.d.ts.map +0 -1
  232. package/dist/modes/interactive/components/theme-selector.js +0 -50
  233. package/dist/modes/interactive/components/theme-selector.js.map +0 -1
  234. package/dist/modes/interactive/components/thinking-selector.d.ts +0 -11
  235. package/dist/modes/interactive/components/thinking-selector.d.ts.map +0 -1
  236. package/dist/modes/interactive/components/thinking-selector.js +0 -51
  237. package/dist/modes/interactive/components/thinking-selector.js.map +0 -1
  238. package/dist/modes/interactive/components/tool-execution.d.ts +0 -63
  239. package/dist/modes/interactive/components/tool-execution.d.ts.map +0 -1
  240. package/dist/modes/interactive/components/tool-execution.js +0 -295
  241. package/dist/modes/interactive/components/tool-execution.js.map +0 -1
  242. package/dist/modes/interactive/components/tree-selector.d.ts +0 -89
  243. package/dist/modes/interactive/components/tree-selector.d.ts.map +0 -1
  244. package/dist/modes/interactive/components/tree-selector.js +0 -1093
  245. package/dist/modes/interactive/components/tree-selector.js.map +0 -1
  246. package/dist/modes/interactive/components/user-message-selector.d.ts +0 -30
  247. package/dist/modes/interactive/components/user-message-selector.d.ts.map +0 -1
  248. package/dist/modes/interactive/components/user-message-selector.js +0 -114
  249. package/dist/modes/interactive/components/user-message-selector.js.map +0 -1
  250. package/dist/modes/interactive/components/user-message.d.ts +0 -10
  251. package/dist/modes/interactive/components/user-message.d.ts.map +0 -1
  252. package/dist/modes/interactive/components/user-message.js +0 -29
  253. package/dist/modes/interactive/components/user-message.js.map +0 -1
  254. package/dist/modes/interactive/interactive-mode.d.ts +0 -375
  255. package/dist/modes/interactive/interactive-mode.d.ts.map +0 -1
  256. package/dist/modes/interactive/interactive-mode.js +0 -4799
  257. package/dist/modes/interactive/interactive-mode.js.map +0 -1
  258. package/dist/modes/interactive/theme/dark.json +0 -86
  259. package/dist/modes/interactive/theme/light.json +0 -85
  260. package/dist/modes/interactive/theme/theme-schema.json +0 -335
  261. package/examples/extensions/border-status-editor.ts +0 -150
  262. package/examples/extensions/built-in-tool-renderer.ts +0 -249
  263. package/examples/extensions/custom-footer.ts +0 -64
  264. package/examples/extensions/custom-header.ts +0 -73
  265. package/examples/extensions/custom-provider-anthropic/index.ts +0 -604
  266. package/examples/extensions/custom-provider-anthropic/package-lock.json +0 -24
  267. package/examples/extensions/custom-provider-anthropic/package.json +0 -19
  268. package/examples/extensions/custom-provider-gitlab-duo/index.ts +0 -349
  269. package/examples/extensions/custom-provider-gitlab-duo/package.json +0 -16
  270. package/examples/extensions/custom-provider-gitlab-duo/test.ts +0 -82
  271. package/examples/extensions/doom-overlay/README.md +0 -46
  272. package/examples/extensions/doom-overlay/doom/build/doom.js +0 -21
  273. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  274. package/examples/extensions/doom-overlay/doom/build.sh +0 -152
  275. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +0 -72
  276. package/examples/extensions/doom-overlay/doom-component.ts +0 -132
  277. package/examples/extensions/doom-overlay/doom-engine.ts +0 -173
  278. package/examples/extensions/doom-overlay/doom-keys.ts +0 -104
  279. package/examples/extensions/doom-overlay/index.ts +0 -74
  280. package/examples/extensions/doom-overlay/wad-finder.ts +0 -51
  281. package/examples/extensions/github-issue-autocomplete.ts +0 -185
  282. package/examples/extensions/handoff.ts +0 -191
  283. package/examples/extensions/interactive-shell.ts +0 -196
  284. package/examples/extensions/message-renderer.ts +0 -59
  285. package/examples/extensions/minimal-mode.ts +0 -426
  286. package/examples/extensions/modal-editor.ts +0 -85
  287. package/examples/extensions/overlay-qa-tests.ts +0 -1379
  288. package/examples/extensions/overlay-test.ts +0 -153
  289. package/examples/extensions/plan-mode/index.ts +0 -340
  290. package/examples/extensions/preset.ts +0 -430
  291. package/examples/extensions/qna.ts +0 -122
  292. package/examples/extensions/question.ts +0 -264
  293. package/examples/extensions/questionnaire.ts +0 -427
  294. package/examples/extensions/rainbow-editor.ts +0 -88
  295. package/examples/extensions/sandbox/index.ts +0 -321
  296. package/examples/extensions/sandbox/package-lock.json +0 -92
  297. package/examples/extensions/sandbox/package.json +0 -19
  298. package/examples/extensions/snake.ts +0 -343
  299. package/examples/extensions/space-invaders.ts +0 -560
  300. package/examples/extensions/ssh.ts +0 -220
  301. package/examples/extensions/status-line.ts +0 -32
  302. package/examples/extensions/structured-output.ts +0 -65
  303. package/examples/extensions/subagent/index.ts +0 -1009
  304. package/examples/extensions/summarize.ts +0 -206
  305. package/examples/extensions/tic-tac-toe.ts +0 -1008
  306. package/examples/extensions/todo.ts +0 -297
  307. package/examples/extensions/tools.ts +0 -141
  308. package/examples/extensions/truncated-tool.ts +0 -195
  309. package/examples/extensions/with-deps/index.ts +0 -32
  310. package/examples/extensions/with-deps/package-lock.json +0 -31
  311. package/examples/extensions/with-deps/package.json +0 -22
  312. package/examples/extensions/working-indicator.ts +0 -123
  313. package/examples/rpc-extension-ui.ts +0 -632
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openeryc/pi-coding-agent",
3
- "version": "0.75.26",
3
+ "version": "0.75.28",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -31,17 +31,16 @@
31
31
  "scripts": {
32
32
  "clean": "shx rm -rf dist",
33
33
  "build": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js && npm run copy-assets",
34
- "build:binary": "npm --prefix ../tui run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm run build && bun build --compile ./dist/bun/cli.js --outfile dist/pi && npm run copy-binary-assets",
35
- "copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/",
36
- "copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/assets && shx cp src/modes/interactive/assets/*.png dist/assets/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
34
+ "build:binary": "npm --prefix ../ai run build && npm --prefix ../agent run build && npm run build && bun build --compile ./dist/bun/cli.js --outfile dist/pi && npm run copy-binary-assets",
35
+ "copy-assets": "shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/",
36
+ "copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
37
37
  "test": "vitest --run",
38
38
  "shrinkwrap": "node ../../scripts/generate-coding-agent-shrinkwrap.mjs",
39
39
  "prepublishOnly": "npm run clean && npm run build && npm run shrinkwrap"
40
40
  },
41
41
  "dependencies": {
42
- "@openeryc/pi-agent-core": "^0.75.26",
43
- "@openeryc/pi-ai": "^0.75.26",
44
- "@openeryc/pi-tui": "^0.75.26",
42
+ "@openeryc/pi-agent-core": "^0.75.28",
43
+ "@openeryc/pi-ai": "^0.75.28",
45
44
  "@silvia-odwyer/photon-node": "0.3.4",
46
45
  "chalk": "5.6.2",
47
46
  "cross-spawn": "7.0.6",
@@ -1,9 +0,0 @@
1
- /**
2
- * TUI session selector for --resume flag
3
- */
4
- import type { SessionInfo, SessionListProgress } from "../core/session-manager.ts";
5
- type SessionsLoader = (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;
6
- /** Show TUI session selector and return selected session path or null if cancelled */
7
- export declare function selectSession(currentSessionsLoader: SessionsLoader, allSessionsLoader: SessionsLoader): Promise<string | null>;
8
- export {};
9
- //# sourceMappingURL=session-picker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-picker.d.ts","sourceRoot":"","sources":["../../src/cli/session-picker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGnF,KAAK,cAAc,GAAG,CAAC,UAAU,CAAC,EAAE,mBAAmB,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;AAEnF,sFAAsF;AACtF,wBAAsB,aAAa,CAClC,qBAAqB,EAAE,cAAc,EACrC,iBAAiB,EAAE,cAAc,GAC/B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoCxB","sourcesContent":["/**\n * TUI session selector for --resume flag\n */\n\nimport { ProcessTerminal, setKeybindings, TUI } from \"@openeryc/pi-tui\";\nimport { KeybindingsManager } from \"../core/keybindings.ts\";\nimport type { SessionInfo, SessionListProgress } from \"../core/session-manager.ts\";\nimport { SessionSelectorComponent } from \"../modes/interactive/components/session-selector.ts\";\n\ntype SessionsLoader = (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;\n\n/** Show TUI session selector and return selected session path or null if cancelled */\nexport async function selectSession(\n\tcurrentSessionsLoader: SessionsLoader,\n\tallSessionsLoader: SessionsLoader,\n): Promise<string | null> {\n\treturn new Promise((resolve) => {\n\t\tconst ui = new TUI(new ProcessTerminal());\n\t\tconst keybindings = KeybindingsManager.create();\n\t\tsetKeybindings(keybindings);\n\t\tlet resolved = false;\n\n\t\tconst selector = new SessionSelectorComponent(\n\t\t\tcurrentSessionsLoader,\n\t\t\tallSessionsLoader,\n\t\t\t(path: string) => {\n\t\t\t\tif (!resolved) {\n\t\t\t\t\tresolved = true;\n\t\t\t\t\tui.stop();\n\t\t\t\t\tresolve(path);\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tif (!resolved) {\n\t\t\t\t\tresolved = true;\n\t\t\t\t\tui.stop();\n\t\t\t\t\tresolve(null);\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tui.stop();\n\t\t\t\tprocess.exit(0);\n\t\t\t},\n\t\t\t() => ui.requestRender(),\n\t\t\t{ showRenameHint: false, keybindings },\n\t\t);\n\n\t\tui.addChild(selector);\n\t\tui.setFocus(selector.getSessionList());\n\t\tui.start();\n\t});\n}\n"]}
@@ -1,35 +0,0 @@
1
- /**
2
- * TUI session selector for --resume flag
3
- */
4
- import { ProcessTerminal, setKeybindings, TUI } from "@openeryc/pi-tui";
5
- import { KeybindingsManager } from "../core/keybindings.js";
6
- import { SessionSelectorComponent } from "../modes/interactive/components/session-selector.js";
7
- /** Show TUI session selector and return selected session path or null if cancelled */
8
- export async function selectSession(currentSessionsLoader, allSessionsLoader) {
9
- return new Promise((resolve) => {
10
- const ui = new TUI(new ProcessTerminal());
11
- const keybindings = KeybindingsManager.create();
12
- setKeybindings(keybindings);
13
- let resolved = false;
14
- const selector = new SessionSelectorComponent(currentSessionsLoader, allSessionsLoader, (path) => {
15
- if (!resolved) {
16
- resolved = true;
17
- ui.stop();
18
- resolve(path);
19
- }
20
- }, () => {
21
- if (!resolved) {
22
- resolved = true;
23
- ui.stop();
24
- resolve(null);
25
- }
26
- }, () => {
27
- ui.stop();
28
- process.exit(0);
29
- }, () => ui.requestRender(), { showRenameHint: false, keybindings });
30
- ui.addChild(selector);
31
- ui.setFocus(selector.getSessionList());
32
- ui.start();
33
- });
34
- }
35
- //# sourceMappingURL=session-picker.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"session-picker.js","sourceRoot":"","sources":["../../src/cli/session-picker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qDAAqD,CAAC;AAI/F,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,qBAAqC,EACrC,iBAAiC,EACR;IACzB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;QAC1C,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,EAAE,CAAC;QAChD,cAAc,CAAC,WAAW,CAAC,CAAC;QAC5B,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,MAAM,QAAQ,GAAG,IAAI,wBAAwB,CAC5C,qBAAqB,EACrB,iBAAiB,EACjB,CAAC,IAAY,EAAE,EAAE,CAAC;YACjB,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACf,QAAQ,GAAG,IAAI,CAAC;gBAChB,EAAE,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,CAAC,IAAI,CAAC,CAAC;YACf,CAAC;QAAA,CACD,EACD,GAAG,EAAE,CAAC;YACL,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACf,QAAQ,GAAG,IAAI,CAAC;gBAChB,EAAE,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,CAAC,IAAI,CAAC,CAAC;YACf,CAAC;QAAA,CACD,EACD,GAAG,EAAE,CAAC;YACL,EAAE,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAA,CAChB,EACD,GAAG,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EACxB,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,EAAE,CACtC,CAAC;QAEF,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACtB,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC;QACvC,EAAE,CAAC,KAAK,EAAE,CAAC;IAAA,CACX,CAAC,CAAC;AAAA,CACH","sourcesContent":["/**\n * TUI session selector for --resume flag\n */\n\nimport { ProcessTerminal, setKeybindings, TUI } from \"@openeryc/pi-tui\";\nimport { KeybindingsManager } from \"../core/keybindings.ts\";\nimport type { SessionInfo, SessionListProgress } from \"../core/session-manager.ts\";\nimport { SessionSelectorComponent } from \"../modes/interactive/components/session-selector.ts\";\n\ntype SessionsLoader = (onProgress?: SessionListProgress) => Promise<SessionInfo[]>;\n\n/** Show TUI session selector and return selected session path or null if cancelled */\nexport async function selectSession(\n\tcurrentSessionsLoader: SessionsLoader,\n\tallSessionsLoader: SessionsLoader,\n): Promise<string | null> {\n\treturn new Promise((resolve) => {\n\t\tconst ui = new TUI(new ProcessTerminal());\n\t\tconst keybindings = KeybindingsManager.create();\n\t\tsetKeybindings(keybindings);\n\t\tlet resolved = false;\n\n\t\tconst selector = new SessionSelectorComponent(\n\t\t\tcurrentSessionsLoader,\n\t\t\tallSessionsLoader,\n\t\t\t(path: string) => {\n\t\t\t\tif (!resolved) {\n\t\t\t\t\tresolved = true;\n\t\t\t\t\tui.stop();\n\t\t\t\t\tresolve(path);\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tif (!resolved) {\n\t\t\t\t\tresolved = true;\n\t\t\t\t\tui.stop();\n\t\t\t\t\tresolve(null);\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tui.stop();\n\t\t\t\tprocess.exit(0);\n\t\t\t},\n\t\t\t() => ui.requestRender(),\n\t\t\t{ showRenameHint: false, keybindings },\n\t\t);\n\n\t\tui.addChild(selector);\n\t\tui.setFocus(selector.getSessionList());\n\t\tui.start();\n\t});\n}\n"]}
@@ -1,86 +0,0 @@
1
- /**
2
- * MCP (Model Context Protocol) client types.
3
- *
4
- * Implements a minimal MCP client supporting stdio transport
5
- * and tool listing/calling (tools only, no resources/prompts).
6
- */
7
- export interface MCPServerConfig {
8
- command: string;
9
- args?: string[];
10
- env?: Record<string, string>;
11
- }
12
- export interface MCPJsonRpcRequest {
13
- jsonrpc: "2.0";
14
- id: number;
15
- method: string;
16
- params?: Record<string, unknown>;
17
- }
18
- export interface MCPJsonRpcResponse {
19
- jsonrpc: "2.0";
20
- id: number;
21
- result?: unknown;
22
- error?: MCPJsonRpcError;
23
- }
24
- export interface MCPJsonRpcError {
25
- code: number;
26
- message: string;
27
- data?: unknown;
28
- }
29
- export interface MCPInitializeResult {
30
- protocolVersion: string;
31
- capabilities: MCPCapabilities;
32
- serverInfo?: MCPInfo;
33
- }
34
- export interface MCPCapabilities {
35
- tools?: MCPToolsCapability;
36
- }
37
- export interface MCPToolsCapability {
38
- listChanged?: boolean;
39
- }
40
- export interface MCPInfo {
41
- name: string;
42
- version: string;
43
- }
44
- export interface MCPToolDefinition {
45
- name: string;
46
- description?: string;
47
- inputSchema: MCPJsonSchema;
48
- }
49
- export interface MCPJsonSchema {
50
- type: string;
51
- properties?: Record<string, MCPJsonSchemaProperty>;
52
- required?: string[];
53
- additionalProperties?: boolean;
54
- items?: MCPJsonSchema;
55
- description?: string;
56
- enum?: string[];
57
- }
58
- export interface MCPJsonSchemaProperty {
59
- type?: string;
60
- description?: string;
61
- enum?: string[];
62
- items?: MCPJsonSchema;
63
- default?: unknown;
64
- }
65
- export interface MCPListToolsResult {
66
- tools: MCPToolDefinition[];
67
- }
68
- export interface MCPCallToolRequest {
69
- name: string;
70
- arguments: Record<string, unknown>;
71
- }
72
- export interface MCPCallToolResult {
73
- content: MCPCallToolContent[];
74
- isError?: boolean;
75
- }
76
- export interface MCPCallToolTextContent {
77
- type: "text";
78
- text: string;
79
- }
80
- export interface MCPCallToolImageContent {
81
- type: "image";
82
- data: string;
83
- mimeType: string;
84
- }
85
- export type MCPCallToolContent = MCPCallToolTextContent | MCPCallToolImageContent;
86
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,eAAe,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,aAAa,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IACnD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,uBAAuB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,GAAG,uBAAuB,CAAC","sourcesContent":["/**\n * MCP (Model Context Protocol) client types.\n *\n * Implements a minimal MCP client supporting stdio transport\n * and tool listing/calling (tools only, no resources/prompts).\n */\n\nexport interface MCPServerConfig {\n\tcommand: string;\n\targs?: string[];\n\tenv?: Record<string, string>;\n}\n\nexport interface MCPJsonRpcRequest {\n\tjsonrpc: \"2.0\";\n\tid: number;\n\tmethod: string;\n\tparams?: Record<string, unknown>;\n}\n\nexport interface MCPJsonRpcResponse {\n\tjsonrpc: \"2.0\";\n\tid: number;\n\tresult?: unknown;\n\terror?: MCPJsonRpcError;\n}\n\nexport interface MCPJsonRpcError {\n\tcode: number;\n\tmessage: string;\n\tdata?: unknown;\n}\n\nexport interface MCPInitializeResult {\n\tprotocolVersion: string;\n\tcapabilities: MCPCapabilities;\n\tserverInfo?: MCPInfo;\n}\n\nexport interface MCPCapabilities {\n\ttools?: MCPToolsCapability;\n}\n\nexport interface MCPToolsCapability {\n\tlistChanged?: boolean;\n}\n\nexport interface MCPInfo {\n\tname: string;\n\tversion: string;\n}\n\nexport interface MCPToolDefinition {\n\tname: string;\n\tdescription?: string;\n\tinputSchema: MCPJsonSchema;\n}\n\nexport interface MCPJsonSchema {\n\ttype: string;\n\tproperties?: Record<string, MCPJsonSchemaProperty>;\n\trequired?: string[];\n\tadditionalProperties?: boolean;\n\titems?: MCPJsonSchema;\n\tdescription?: string;\n\tenum?: string[];\n}\n\nexport interface MCPJsonSchemaProperty {\n\ttype?: string;\n\tdescription?: string;\n\tenum?: string[];\n\titems?: MCPJsonSchema;\n\tdefault?: unknown;\n}\n\nexport interface MCPListToolsResult {\n\ttools: MCPToolDefinition[];\n}\n\nexport interface MCPCallToolRequest {\n\tname: string;\n\targuments: Record<string, unknown>;\n}\n\nexport interface MCPCallToolResult {\n\tcontent: MCPCallToolContent[];\n\tisError?: boolean;\n}\n\nexport interface MCPCallToolTextContent {\n\ttype: \"text\";\n\ttext: string;\n}\n\nexport interface MCPCallToolImageContent {\n\ttype: \"image\";\n\tdata: string;\n\tmimeType: string;\n}\n\nexport type MCPCallToolContent = MCPCallToolTextContent | MCPCallToolImageContent;\n"]}
@@ -1,8 +0,0 @@
1
- /**
2
- * MCP (Model Context Protocol) client types.
3
- *
4
- * Implements a minimal MCP client supporting stdio transport
5
- * and tool listing/calling (tools only, no resources/prompts).
6
- */
7
- export {};
8
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/mcp/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG","sourcesContent":["/**\n * MCP (Model Context Protocol) client types.\n *\n * Implements a minimal MCP client supporting stdio transport\n * and tool listing/calling (tools only, no resources/prompts).\n */\n\nexport interface MCPServerConfig {\n\tcommand: string;\n\targs?: string[];\n\tenv?: Record<string, string>;\n}\n\nexport interface MCPJsonRpcRequest {\n\tjsonrpc: \"2.0\";\n\tid: number;\n\tmethod: string;\n\tparams?: Record<string, unknown>;\n}\n\nexport interface MCPJsonRpcResponse {\n\tjsonrpc: \"2.0\";\n\tid: number;\n\tresult?: unknown;\n\terror?: MCPJsonRpcError;\n}\n\nexport interface MCPJsonRpcError {\n\tcode: number;\n\tmessage: string;\n\tdata?: unknown;\n}\n\nexport interface MCPInitializeResult {\n\tprotocolVersion: string;\n\tcapabilities: MCPCapabilities;\n\tserverInfo?: MCPInfo;\n}\n\nexport interface MCPCapabilities {\n\ttools?: MCPToolsCapability;\n}\n\nexport interface MCPToolsCapability {\n\tlistChanged?: boolean;\n}\n\nexport interface MCPInfo {\n\tname: string;\n\tversion: string;\n}\n\nexport interface MCPToolDefinition {\n\tname: string;\n\tdescription?: string;\n\tinputSchema: MCPJsonSchema;\n}\n\nexport interface MCPJsonSchema {\n\ttype: string;\n\tproperties?: Record<string, MCPJsonSchemaProperty>;\n\trequired?: string[];\n\tadditionalProperties?: boolean;\n\titems?: MCPJsonSchema;\n\tdescription?: string;\n\tenum?: string[];\n}\n\nexport interface MCPJsonSchemaProperty {\n\ttype?: string;\n\tdescription?: string;\n\tenum?: string[];\n\titems?: MCPJsonSchema;\n\tdefault?: unknown;\n}\n\nexport interface MCPListToolsResult {\n\ttools: MCPToolDefinition[];\n}\n\nexport interface MCPCallToolRequest {\n\tname: string;\n\targuments: Record<string, unknown>;\n}\n\nexport interface MCPCallToolResult {\n\tcontent: MCPCallToolContent[];\n\tisError?: boolean;\n}\n\nexport interface MCPCallToolTextContent {\n\ttype: \"text\";\n\ttext: string;\n}\n\nexport interface MCPCallToolImageContent {\n\ttype: \"image\";\n\tdata: string;\n\tmimeType: string;\n}\n\nexport type MCPCallToolContent = MCPCallToolTextContent | MCPCallToolImageContent;\n"]}
@@ -1,34 +0,0 @@
1
- /**
2
- * Armin says hi! A fun easter egg with animated XBM art.
3
- */
4
- import type { Component, TUI } from "@openeryc/pi-tui";
5
- export declare class ArminComponent implements Component {
6
- private ui;
7
- private interval;
8
- private effect;
9
- private finalGrid;
10
- private currentGrid;
11
- private effectState;
12
- private cachedLines;
13
- private cachedWidth;
14
- private gridVersion;
15
- private cachedVersion;
16
- constructor(ui: TUI);
17
- invalidate(): void;
18
- render(width: number): string[];
19
- private createEmptyGrid;
20
- private initEffect;
21
- private startAnimation;
22
- private stopAnimation;
23
- private tickEffect;
24
- private tickTypewriter;
25
- private tickScanline;
26
- private tickRain;
27
- private tickFade;
28
- private tickCrt;
29
- private tickGlitch;
30
- private tickDissolve;
31
- private updateDisplay;
32
- dispose(): void;
33
- }
34
- //# sourceMappingURL=armin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"armin.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/armin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAuDvD,qBAAa,cAAe,YAAW,SAAS;IAC/C,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,aAAa,CAAM;IAE3B,YAAY,EAAE,EAAE,GAAG,EAQlB;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAwB9B;IAED,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,UAAU;IAgElB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,UAAU;IAqBlB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,QAAQ;IAmDhB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,OAAO;IAoBf,OAAO,CAAC,UAAU;IAgClB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,aAAa;IAIrB,OAAO,IAAI,IAAI,CAEd;CACD","sourcesContent":["/**\n * Armin says hi! A fun easter egg with animated XBM art.\n */\n\nimport type { Component, TUI } from \"@openeryc/pi-tui\";\nimport { theme } from \"../theme/theme.ts\";\n\n// XBM image: 31x36 pixels, LSB first, 1=background, 0=foreground\nconst WIDTH = 31;\nconst HEIGHT = 36;\nconst BITS = [\n\t0xff, 0xff, 0xff, 0x7f, 0xff, 0xf0, 0xff, 0x7f, 0xff, 0xed, 0xff, 0x7f, 0xff, 0xdb, 0xff, 0x7f, 0xff, 0xb7, 0xff,\n\t0x7f, 0xff, 0x77, 0xfe, 0x7f, 0x3f, 0xf8, 0xfe, 0x7f, 0xdf, 0xff, 0xfe, 0x7f, 0xdf, 0x3f, 0xfc, 0x7f, 0x9f, 0xc3,\n\t0xfb, 0x7f, 0x6f, 0xfc, 0xf4, 0x7f, 0xf7, 0x0f, 0xf7, 0x7f, 0xf7, 0xff, 0xf7, 0x7f, 0xf7, 0xff, 0xe3, 0x7f, 0xf7,\n\t0x07, 0xe8, 0x7f, 0xef, 0xf8, 0x67, 0x70, 0x0f, 0xff, 0xbb, 0x6f, 0xf1, 0x00, 0xd0, 0x5b, 0xfd, 0x3f, 0xec, 0x53,\n\t0xc1, 0xff, 0xef, 0x57, 0x9f, 0xfd, 0xee, 0x5f, 0x9f, 0xfc, 0xae, 0x5f, 0x1f, 0x78, 0xac, 0x5f, 0x3f, 0x00, 0x50,\n\t0x6c, 0x7f, 0x00, 0xdc, 0x77, 0xff, 0xc0, 0x3f, 0x78, 0xff, 0x01, 0xf8, 0x7f, 0xff, 0x03, 0x9c, 0x78, 0xff, 0x07,\n\t0x8c, 0x7c, 0xff, 0x0f, 0xce, 0x78, 0xff, 0xff, 0xcf, 0x7f, 0xff, 0xff, 0xcf, 0x78, 0xff, 0xff, 0xdf, 0x78, 0xff,\n\t0xff, 0xdf, 0x7d, 0xff, 0xff, 0x3f, 0x7e, 0xff, 0xff, 0xff, 0x7f,\n];\n\nconst BYTES_PER_ROW = Math.ceil(WIDTH / 8);\nconst DISPLAY_HEIGHT = Math.ceil(HEIGHT / 2); // Half-block rendering\n\ntype Effect = \"typewriter\" | \"scanline\" | \"rain\" | \"fade\" | \"crt\" | \"glitch\" | \"dissolve\";\n\nconst EFFECTS: Effect[] = [\"typewriter\", \"scanline\", \"rain\", \"fade\", \"crt\", \"glitch\", \"dissolve\"];\n\n// Get pixel at (x, y): true = foreground, false = background\nfunction getPixel(x: number, y: number): boolean {\n\tif (y >= HEIGHT) return false;\n\tconst byteIndex = y * BYTES_PER_ROW + Math.floor(x / 8);\n\tconst bitIndex = x % 8;\n\treturn ((BITS[byteIndex] >> bitIndex) & 1) === 0;\n}\n\n// Get the character for a cell (2 vertical pixels packed)\nfunction getChar(x: number, row: number): string {\n\tconst upper = getPixel(x, row * 2);\n\tconst lower = getPixel(x, row * 2 + 1);\n\tif (upper && lower) return \"█\";\n\tif (upper) return \"▀\";\n\tif (lower) return \"▄\";\n\treturn \" \";\n}\n\n// Build the final image grid\nfunction buildFinalGrid(): string[][] {\n\tconst grid: string[][] = [];\n\tfor (let row = 0; row < DISPLAY_HEIGHT; row++) {\n\t\tconst line: string[] = [];\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tline.push(getChar(x, row));\n\t\t}\n\t\tgrid.push(line);\n\t}\n\treturn grid;\n}\n\nexport class ArminComponent implements Component {\n\tprivate ui: TUI;\n\tprivate interval: ReturnType<typeof setInterval> | null = null;\n\tprivate effect: Effect;\n\tprivate finalGrid: string[][];\n\tprivate currentGrid: string[][];\n\tprivate effectState: Record<string, unknown> = {};\n\tprivate cachedLines: string[] = [];\n\tprivate cachedWidth = 0;\n\tprivate gridVersion = 0;\n\tprivate cachedVersion = -1;\n\n\tconstructor(ui: TUI) {\n\t\tthis.ui = ui;\n\t\tthis.effect = EFFECTS[Math.floor(Math.random() * EFFECTS.length)];\n\t\tthis.finalGrid = buildFinalGrid();\n\t\tthis.currentGrid = this.createEmptyGrid();\n\n\t\tthis.initEffect();\n\t\tthis.startAnimation();\n\t}\n\n\tinvalidate(): void {\n\t\tthis.cachedWidth = 0;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width === this.cachedWidth && this.cachedVersion === this.gridVersion) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\tconst padding = 1;\n\t\tconst availableWidth = width - padding;\n\n\t\tthis.cachedLines = this.currentGrid.map((row) => {\n\t\t\t// Clip row to available width before applying color\n\t\t\tconst clipped = row.slice(0, availableWidth).join(\"\");\n\t\t\tconst padRight = Math.max(0, width - padding - clipped.length);\n\t\t\treturn ` ${theme.fg(\"accent\", clipped)}${\" \".repeat(padRight)}`;\n\t\t});\n\n\t\t// Add \"ARMIN SAYS HI\" at the end\n\t\tconst message = \"ARMIN SAYS HI\";\n\t\tconst msgPadRight = Math.max(0, width - padding - message.length);\n\t\tthis.cachedLines.push(` ${theme.fg(\"accent\", message)}${\" \".repeat(msgPadRight)}`);\n\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedVersion = this.gridVersion;\n\n\t\treturn this.cachedLines;\n\t}\n\n\tprivate createEmptyGrid(): string[][] {\n\t\treturn Array.from({ length: DISPLAY_HEIGHT }, () => Array(WIDTH).fill(\" \"));\n\t}\n\n\tprivate initEffect(): void {\n\t\tswitch (this.effect) {\n\t\t\tcase \"typewriter\":\n\t\t\t\tthis.effectState = { pos: 0 };\n\t\t\t\tbreak;\n\t\t\tcase \"scanline\":\n\t\t\t\tthis.effectState = { row: 0 };\n\t\t\t\tbreak;\n\t\t\tcase \"rain\":\n\t\t\t\t// Track falling position for each column\n\t\t\t\tthis.effectState = {\n\t\t\t\t\tdrops: Array.from({ length: WIDTH }, () => ({\n\t\t\t\t\t\ty: -Math.floor(Math.random() * DISPLAY_HEIGHT * 2),\n\t\t\t\t\t\tsettled: 0,\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\tcase \"fade\": {\n\t\t\t\t// Shuffle all pixel positions\n\t\t\t\tconst positions: [number, number][] = [];\n\t\t\t\tfor (let row = 0; row < DISPLAY_HEIGHT; row++) {\n\t\t\t\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\t\t\t\tpositions.push([row, x]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Fisher-Yates shuffle\n\t\t\t\tfor (let i = positions.length - 1; i > 0; i--) {\n\t\t\t\t\tconst j = Math.floor(Math.random() * (i + 1));\n\t\t\t\t\t[positions[i], positions[j]] = [positions[j], positions[i]];\n\t\t\t\t}\n\t\t\t\tthis.effectState = { positions, idx: 0 };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"crt\":\n\t\t\t\tthis.effectState = { expansion: 0 };\n\t\t\t\tbreak;\n\t\t\tcase \"glitch\":\n\t\t\t\tthis.effectState = { phase: 0, glitchFrames: 8 };\n\t\t\t\tbreak;\n\t\t\tcase \"dissolve\": {\n\t\t\t\t// Start with random noise\n\t\t\t\tthis.currentGrid = Array.from({ length: DISPLAY_HEIGHT }, () =>\n\t\t\t\t\tArray.from({ length: WIDTH }, () => {\n\t\t\t\t\t\tconst chars = [\" \", \"░\", \"▒\", \"▓\", \"█\", \"▀\", \"▄\"];\n\t\t\t\t\t\treturn chars[Math.floor(Math.random() * chars.length)];\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\t// Shuffle positions for gradual resolve\n\t\t\t\tconst dissolvePositions: [number, number][] = [];\n\t\t\t\tfor (let row = 0; row < DISPLAY_HEIGHT; row++) {\n\t\t\t\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\t\t\t\tdissolvePositions.push([row, x]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (let i = dissolvePositions.length - 1; i > 0; i--) {\n\t\t\t\t\tconst j = Math.floor(Math.random() * (i + 1));\n\t\t\t\t\t[dissolvePositions[i], dissolvePositions[j]] = [dissolvePositions[j], dissolvePositions[i]];\n\t\t\t\t}\n\t\t\t\tthis.effectState = { positions: dissolvePositions, idx: 0 };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate startAnimation(): void {\n\t\tconst fps = this.effect === \"glitch\" ? 60 : 30;\n\t\tthis.interval = setInterval(() => {\n\t\t\tconst done = this.tickEffect();\n\t\t\tthis.updateDisplay();\n\t\t\tthis.ui.requestRender();\n\t\t\tif (done) {\n\t\t\t\tthis.stopAnimation();\n\t\t\t}\n\t\t}, 1000 / fps);\n\t}\n\n\tprivate stopAnimation(): void {\n\t\tif (this.interval) {\n\t\t\tclearInterval(this.interval);\n\t\t\tthis.interval = null;\n\t\t}\n\t}\n\n\tprivate tickEffect(): boolean {\n\t\tswitch (this.effect) {\n\t\t\tcase \"typewriter\":\n\t\t\t\treturn this.tickTypewriter();\n\t\t\tcase \"scanline\":\n\t\t\t\treturn this.tickScanline();\n\t\t\tcase \"rain\":\n\t\t\t\treturn this.tickRain();\n\t\t\tcase \"fade\":\n\t\t\t\treturn this.tickFade();\n\t\t\tcase \"crt\":\n\t\t\t\treturn this.tickCrt();\n\t\t\tcase \"glitch\":\n\t\t\t\treturn this.tickGlitch();\n\t\t\tcase \"dissolve\":\n\t\t\t\treturn this.tickDissolve();\n\t\t\tdefault:\n\t\t\t\treturn true;\n\t\t}\n\t}\n\n\tprivate tickTypewriter(): boolean {\n\t\tconst state = this.effectState as { pos: number };\n\t\tconst pixelsPerFrame = 3;\n\n\t\tfor (let i = 0; i < pixelsPerFrame; i++) {\n\t\t\tconst row = Math.floor(state.pos / WIDTH);\n\t\t\tconst x = state.pos % WIDTH;\n\t\t\tif (row >= DISPLAY_HEIGHT) return true;\n\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\tstate.pos++;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate tickScanline(): boolean {\n\t\tconst state = this.effectState as { row: number };\n\t\tif (state.row >= DISPLAY_HEIGHT) return true;\n\n\t\t// Copy row\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tthis.currentGrid[state.row][x] = this.finalGrid[state.row][x];\n\t\t}\n\t\tstate.row++;\n\t\treturn false;\n\t}\n\n\tprivate tickRain(): boolean {\n\t\tconst state = this.effectState as {\n\t\t\tdrops: { y: number; settled: number }[];\n\t\t};\n\n\t\tlet allSettled = true;\n\t\tthis.currentGrid = this.createEmptyGrid();\n\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tconst drop = state.drops[x];\n\n\t\t\t// Draw settled pixels\n\t\t\tfor (let row = DISPLAY_HEIGHT - 1; row >= DISPLAY_HEIGHT - drop.settled; row--) {\n\t\t\t\tif (row >= 0) {\n\t\t\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if this column is done\n\t\t\tif (drop.settled >= DISPLAY_HEIGHT) continue;\n\n\t\t\tallSettled = false;\n\n\t\t\t// Find the target row for this column (lowest non-space pixel)\n\t\t\tlet targetRow = -1;\n\t\t\tfor (let row = DISPLAY_HEIGHT - 1 - drop.settled; row >= 0; row--) {\n\t\t\t\tif (this.finalGrid[row][x] !== \" \") {\n\t\t\t\t\ttargetRow = row;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Move drop down\n\t\t\tdrop.y++;\n\n\t\t\t// Draw falling drop\n\t\t\tif (drop.y >= 0 && drop.y < DISPLAY_HEIGHT) {\n\t\t\t\tif (targetRow >= 0 && drop.y >= targetRow) {\n\t\t\t\t\t// Settle\n\t\t\t\t\tdrop.settled = DISPLAY_HEIGHT - targetRow;\n\t\t\t\t\tdrop.y = -Math.floor(Math.random() * 5) - 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Still falling\n\t\t\t\t\tthis.currentGrid[drop.y][x] = \"▓\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn allSettled;\n\t}\n\n\tprivate tickFade(): boolean {\n\t\tconst state = this.effectState as { positions: [number, number][]; idx: number };\n\t\tconst pixelsPerFrame = 15;\n\n\t\tfor (let i = 0; i < pixelsPerFrame; i++) {\n\t\t\tif (state.idx >= state.positions.length) return true;\n\t\t\tconst [row, x] = state.positions[state.idx];\n\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\tstate.idx++;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate tickCrt(): boolean {\n\t\tconst state = this.effectState as { expansion: number };\n\t\tconst midRow = Math.floor(DISPLAY_HEIGHT / 2);\n\n\t\tthis.currentGrid = this.createEmptyGrid();\n\n\t\t// Draw from middle expanding outward\n\t\tconst top = midRow - state.expansion;\n\t\tconst bottom = midRow + state.expansion;\n\n\t\tfor (let row = Math.max(0, top); row <= Math.min(DISPLAY_HEIGHT - 1, bottom); row++) {\n\t\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\t}\n\t\t}\n\n\t\tstate.expansion++;\n\t\treturn state.expansion > DISPLAY_HEIGHT;\n\t}\n\n\tprivate tickGlitch(): boolean {\n\t\tconst state = this.effectState as { phase: number; glitchFrames: number };\n\n\t\tif (state.phase < state.glitchFrames) {\n\t\t\t// Glitch phase: show corrupted version\n\t\t\tthis.currentGrid = this.finalGrid.map((row) => {\n\t\t\t\tconst offset = Math.floor(Math.random() * 7) - 3;\n\t\t\t\tconst glitchRow = [...row];\n\n\t\t\t\t// Random horizontal offset\n\t\t\t\tif (Math.random() < 0.3) {\n\t\t\t\t\tconst shifted = glitchRow.slice(offset).concat(glitchRow.slice(0, offset));\n\t\t\t\t\treturn shifted.slice(0, WIDTH);\n\t\t\t\t}\n\n\t\t\t\t// Random vertical swap\n\t\t\t\tif (Math.random() < 0.2) {\n\t\t\t\t\tconst swapRow = Math.floor(Math.random() * DISPLAY_HEIGHT);\n\t\t\t\t\treturn [...this.finalGrid[swapRow]];\n\t\t\t\t}\n\n\t\t\t\treturn glitchRow;\n\t\t\t});\n\t\t\tstate.phase++;\n\t\t\treturn false;\n\t\t}\n\n\t\t// Final frame: show clean image\n\t\tthis.currentGrid = this.finalGrid.map((row) => [...row]);\n\t\treturn true;\n\t}\n\n\tprivate tickDissolve(): boolean {\n\t\tconst state = this.effectState as { positions: [number, number][]; idx: number };\n\t\tconst pixelsPerFrame = 20;\n\n\t\tfor (let i = 0; i < pixelsPerFrame; i++) {\n\t\t\tif (state.idx >= state.positions.length) return true;\n\t\t\tconst [row, x] = state.positions[state.idx];\n\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\tstate.idx++;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tthis.gridVersion++;\n\t}\n\n\tdispose(): void {\n\t\tthis.stopAnimation();\n\t}\n}\n"]}
@@ -1,333 +0,0 @@
1
- /**
2
- * Armin says hi! A fun easter egg with animated XBM art.
3
- */
4
- import { theme } from "../theme/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, 0xff, 0xb7, 0xff,
10
- 0x7f, 0xff, 0x77, 0xfe, 0x7f, 0x3f, 0xf8, 0xfe, 0x7f, 0xdf, 0xff, 0xfe, 0x7f, 0xdf, 0x3f, 0xfc, 0x7f, 0x9f, 0xc3,
11
- 0xfb, 0x7f, 0x6f, 0xfc, 0xf4, 0x7f, 0xf7, 0x0f, 0xf7, 0x7f, 0xf7, 0xff, 0xf7, 0x7f, 0xf7, 0xff, 0xe3, 0x7f, 0xf7,
12
- 0x07, 0xe8, 0x7f, 0xef, 0xf8, 0x67, 0x70, 0x0f, 0xff, 0xbb, 0x6f, 0xf1, 0x00, 0xd0, 0x5b, 0xfd, 0x3f, 0xec, 0x53,
13
- 0xc1, 0xff, 0xef, 0x57, 0x9f, 0xfd, 0xee, 0x5f, 0x9f, 0xfc, 0xae, 0x5f, 0x1f, 0x78, 0xac, 0x5f, 0x3f, 0x00, 0x50,
14
- 0x6c, 0x7f, 0x00, 0xdc, 0x77, 0xff, 0xc0, 0x3f, 0x78, 0xff, 0x01, 0xf8, 0x7f, 0xff, 0x03, 0x9c, 0x78, 0xff, 0x07,
15
- 0x8c, 0x7c, 0xff, 0x0f, 0xce, 0x78, 0xff, 0xff, 0xcf, 0x7f, 0xff, 0xff, 0xcf, 0x78, 0xff, 0xff, 0xdf, 0x78, 0xff,
16
- 0xff, 0xdf, 0x7d, 0xff, 0xff, 0x3f, 0x7e, 0xff, 0xff, 0xff, 0x7f,
17
- ];
18
- const BYTES_PER_ROW = Math.ceil(WIDTH / 8);
19
- const DISPLAY_HEIGHT = Math.ceil(HEIGHT / 2); // Half-block rendering
20
- const EFFECTS = ["typewriter", "scanline", "rain", "fade", "crt", "glitch", "dissolve"];
21
- // Get pixel at (x, y): true = foreground, false = background
22
- function getPixel(x, y) {
23
- if (y >= HEIGHT)
24
- return false;
25
- const byteIndex = y * BYTES_PER_ROW + Math.floor(x / 8);
26
- const bitIndex = x % 8;
27
- return ((BITS[byteIndex] >> bitIndex) & 1) === 0;
28
- }
29
- // Get the character for a cell (2 vertical pixels packed)
30
- function getChar(x, row) {
31
- const upper = getPixel(x, row * 2);
32
- const lower = getPixel(x, row * 2 + 1);
33
- if (upper && lower)
34
- return "█";
35
- if (upper)
36
- return "▀";
37
- if (lower)
38
- return "▄";
39
- return " ";
40
- }
41
- // Build the final image grid
42
- function buildFinalGrid() {
43
- const grid = [];
44
- for (let row = 0; row < DISPLAY_HEIGHT; row++) {
45
- const line = [];
46
- for (let x = 0; x < WIDTH; x++) {
47
- line.push(getChar(x, row));
48
- }
49
- grid.push(line);
50
- }
51
- return grid;
52
- }
53
- export class ArminComponent {
54
- ui;
55
- interval = null;
56
- effect;
57
- finalGrid;
58
- currentGrid;
59
- effectState = {};
60
- cachedLines = [];
61
- cachedWidth = 0;
62
- gridVersion = 0;
63
- cachedVersion = -1;
64
- constructor(ui) {
65
- this.ui = ui;
66
- this.effect = EFFECTS[Math.floor(Math.random() * EFFECTS.length)];
67
- this.finalGrid = buildFinalGrid();
68
- this.currentGrid = this.createEmptyGrid();
69
- this.initEffect();
70
- this.startAnimation();
71
- }
72
- invalidate() {
73
- this.cachedWidth = 0;
74
- }
75
- render(width) {
76
- if (width === this.cachedWidth && this.cachedVersion === this.gridVersion) {
77
- return this.cachedLines;
78
- }
79
- const padding = 1;
80
- const availableWidth = width - padding;
81
- this.cachedLines = this.currentGrid.map((row) => {
82
- // Clip row to available width before applying color
83
- const clipped = row.slice(0, availableWidth).join("");
84
- const padRight = Math.max(0, width - padding - clipped.length);
85
- return ` ${theme.fg("accent", clipped)}${" ".repeat(padRight)}`;
86
- });
87
- // Add "ARMIN SAYS HI" at the end
88
- const message = "ARMIN SAYS HI";
89
- const msgPadRight = Math.max(0, width - padding - message.length);
90
- this.cachedLines.push(` ${theme.fg("accent", message)}${" ".repeat(msgPadRight)}`);
91
- this.cachedWidth = width;
92
- this.cachedVersion = this.gridVersion;
93
- return this.cachedLines;
94
- }
95
- createEmptyGrid() {
96
- return Array.from({ length: DISPLAY_HEIGHT }, () => Array(WIDTH).fill(" "));
97
- }
98
- initEffect() {
99
- switch (this.effect) {
100
- case "typewriter":
101
- this.effectState = { pos: 0 };
102
- break;
103
- case "scanline":
104
- this.effectState = { row: 0 };
105
- break;
106
- case "rain":
107
- // Track falling position for each column
108
- this.effectState = {
109
- drops: Array.from({ length: WIDTH }, () => ({
110
- y: -Math.floor(Math.random() * DISPLAY_HEIGHT * 2),
111
- settled: 0,
112
- })),
113
- };
114
- break;
115
- case "fade": {
116
- // Shuffle all pixel positions
117
- const positions = [];
118
- for (let row = 0; row < DISPLAY_HEIGHT; row++) {
119
- for (let x = 0; x < WIDTH; x++) {
120
- positions.push([row, x]);
121
- }
122
- }
123
- // Fisher-Yates shuffle
124
- for (let i = positions.length - 1; i > 0; i--) {
125
- const j = Math.floor(Math.random() * (i + 1));
126
- [positions[i], positions[j]] = [positions[j], positions[i]];
127
- }
128
- this.effectState = { positions, idx: 0 };
129
- break;
130
- }
131
- case "crt":
132
- this.effectState = { expansion: 0 };
133
- break;
134
- case "glitch":
135
- this.effectState = { phase: 0, glitchFrames: 8 };
136
- break;
137
- case "dissolve": {
138
- // Start with random noise
139
- this.currentGrid = Array.from({ length: DISPLAY_HEIGHT }, () => Array.from({ length: WIDTH }, () => {
140
- const chars = [" ", "░", "▒", "▓", "█", "▀", "▄"];
141
- return chars[Math.floor(Math.random() * chars.length)];
142
- }));
143
- // Shuffle positions for gradual resolve
144
- const dissolvePositions = [];
145
- for (let row = 0; row < DISPLAY_HEIGHT; row++) {
146
- for (let x = 0; x < WIDTH; x++) {
147
- dissolvePositions.push([row, x]);
148
- }
149
- }
150
- for (let i = dissolvePositions.length - 1; i > 0; i--) {
151
- const j = Math.floor(Math.random() * (i + 1));
152
- [dissolvePositions[i], dissolvePositions[j]] = [dissolvePositions[j], dissolvePositions[i]];
153
- }
154
- this.effectState = { positions: dissolvePositions, idx: 0 };
155
- break;
156
- }
157
- }
158
- }
159
- startAnimation() {
160
- const fps = this.effect === "glitch" ? 60 : 30;
161
- this.interval = setInterval(() => {
162
- const done = this.tickEffect();
163
- this.updateDisplay();
164
- this.ui.requestRender();
165
- if (done) {
166
- this.stopAnimation();
167
- }
168
- }, 1000 / fps);
169
- }
170
- stopAnimation() {
171
- if (this.interval) {
172
- clearInterval(this.interval);
173
- this.interval = null;
174
- }
175
- }
176
- tickEffect() {
177
- switch (this.effect) {
178
- case "typewriter":
179
- return this.tickTypewriter();
180
- case "scanline":
181
- return this.tickScanline();
182
- case "rain":
183
- return this.tickRain();
184
- case "fade":
185
- return this.tickFade();
186
- case "crt":
187
- return this.tickCrt();
188
- case "glitch":
189
- return this.tickGlitch();
190
- case "dissolve":
191
- return this.tickDissolve();
192
- default:
193
- return true;
194
- }
195
- }
196
- tickTypewriter() {
197
- const state = this.effectState;
198
- const pixelsPerFrame = 3;
199
- for (let i = 0; i < pixelsPerFrame; i++) {
200
- const row = Math.floor(state.pos / WIDTH);
201
- const x = state.pos % WIDTH;
202
- if (row >= DISPLAY_HEIGHT)
203
- return true;
204
- this.currentGrid[row][x] = this.finalGrid[row][x];
205
- state.pos++;
206
- }
207
- return false;
208
- }
209
- tickScanline() {
210
- const state = this.effectState;
211
- if (state.row >= DISPLAY_HEIGHT)
212
- return true;
213
- // Copy row
214
- for (let x = 0; x < WIDTH; x++) {
215
- this.currentGrid[state.row][x] = this.finalGrid[state.row][x];
216
- }
217
- state.row++;
218
- return false;
219
- }
220
- tickRain() {
221
- const state = this.effectState;
222
- let allSettled = true;
223
- this.currentGrid = this.createEmptyGrid();
224
- for (let x = 0; x < WIDTH; x++) {
225
- const drop = state.drops[x];
226
- // Draw settled pixels
227
- for (let row = DISPLAY_HEIGHT - 1; row >= DISPLAY_HEIGHT - drop.settled; row--) {
228
- if (row >= 0) {
229
- this.currentGrid[row][x] = this.finalGrid[row][x];
230
- }
231
- }
232
- // Check if this column is done
233
- if (drop.settled >= DISPLAY_HEIGHT)
234
- continue;
235
- allSettled = false;
236
- // Find the target row for this column (lowest non-space pixel)
237
- let targetRow = -1;
238
- for (let row = DISPLAY_HEIGHT - 1 - drop.settled; row >= 0; row--) {
239
- if (this.finalGrid[row][x] !== " ") {
240
- targetRow = row;
241
- break;
242
- }
243
- }
244
- // Move drop down
245
- drop.y++;
246
- // Draw falling drop
247
- if (drop.y >= 0 && drop.y < DISPLAY_HEIGHT) {
248
- if (targetRow >= 0 && drop.y >= targetRow) {
249
- // Settle
250
- drop.settled = DISPLAY_HEIGHT - targetRow;
251
- drop.y = -Math.floor(Math.random() * 5) - 1;
252
- }
253
- else {
254
- // Still falling
255
- this.currentGrid[drop.y][x] = "▓";
256
- }
257
- }
258
- }
259
- return allSettled;
260
- }
261
- tickFade() {
262
- const state = this.effectState;
263
- const pixelsPerFrame = 15;
264
- for (let i = 0; i < pixelsPerFrame; i++) {
265
- if (state.idx >= state.positions.length)
266
- return true;
267
- const [row, x] = state.positions[state.idx];
268
- this.currentGrid[row][x] = this.finalGrid[row][x];
269
- state.idx++;
270
- }
271
- return false;
272
- }
273
- tickCrt() {
274
- const state = this.effectState;
275
- const midRow = Math.floor(DISPLAY_HEIGHT / 2);
276
- this.currentGrid = this.createEmptyGrid();
277
- // Draw from middle expanding outward
278
- const top = midRow - state.expansion;
279
- const bottom = midRow + state.expansion;
280
- for (let row = Math.max(0, top); row <= Math.min(DISPLAY_HEIGHT - 1, bottom); row++) {
281
- for (let x = 0; x < WIDTH; x++) {
282
- this.currentGrid[row][x] = this.finalGrid[row][x];
283
- }
284
- }
285
- state.expansion++;
286
- return state.expansion > DISPLAY_HEIGHT;
287
- }
288
- tickGlitch() {
289
- const state = this.effectState;
290
- if (state.phase < state.glitchFrames) {
291
- // Glitch phase: show corrupted version
292
- this.currentGrid = this.finalGrid.map((row) => {
293
- const offset = Math.floor(Math.random() * 7) - 3;
294
- const glitchRow = [...row];
295
- // Random horizontal offset
296
- if (Math.random() < 0.3) {
297
- const shifted = glitchRow.slice(offset).concat(glitchRow.slice(0, offset));
298
- return shifted.slice(0, WIDTH);
299
- }
300
- // Random vertical swap
301
- if (Math.random() < 0.2) {
302
- const swapRow = Math.floor(Math.random() * DISPLAY_HEIGHT);
303
- return [...this.finalGrid[swapRow]];
304
- }
305
- return glitchRow;
306
- });
307
- state.phase++;
308
- return false;
309
- }
310
- // Final frame: show clean image
311
- this.currentGrid = this.finalGrid.map((row) => [...row]);
312
- return true;
313
- }
314
- tickDissolve() {
315
- const state = this.effectState;
316
- const pixelsPerFrame = 20;
317
- for (let i = 0; i < pixelsPerFrame; i++) {
318
- if (state.idx >= state.positions.length)
319
- return true;
320
- const [row, x] = state.positions[state.idx];
321
- this.currentGrid[row][x] = this.finalGrid[row][x];
322
- state.idx++;
323
- }
324
- return false;
325
- }
326
- updateDisplay() {
327
- this.gridVersion++;
328
- }
329
- dispose() {
330
- this.stopAnimation();
331
- }
332
- }
333
- //# sourceMappingURL=armin.js.map