dexterm-cli 0.0.0-stage → 0.1.2

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 (377) hide show
  1. package/LICENSE +661 -0
  2. package/dist/packages/agents/src/audit.js +122 -0
  3. package/dist/packages/agents/src/bus.js +394 -0
  4. package/dist/packages/agents/src/executor.js +202 -0
  5. package/dist/packages/agents/src/gate.js +179 -0
  6. package/dist/packages/agents/src/identity.js +218 -0
  7. package/dist/packages/agents/src/index.js +15 -0
  8. package/dist/packages/agents/src/proposals.js +153 -0
  9. package/dist/packages/agents/src/schema.js +87 -0
  10. package/dist/packages/agents/src/sdk.js +140 -0
  11. package/dist/packages/agents/src/tiers.js +119 -0
  12. package/dist/packages/agents/src/tools.js +72 -0
  13. package/dist/packages/agents/src/ws.js +158 -0
  14. package/dist/packages/cli/assets/claude/analyst-system.md +76 -0
  15. package/dist/packages/cli/assets/claude/plugin/.claude-plugin/plugin.json +5 -0
  16. package/dist/packages/cli/assets/claude/plugin/skills/REGISTRY.json +16 -0
  17. package/dist/packages/cli/assets/claude/plugin/skills/larp-check/SKILL.md +75 -0
  18. package/dist/packages/cli/assets/claude/plugin/skills/rug-check/SKILL.md +74 -0
  19. package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +63 -0
  20. package/dist/packages/cli/assets/claude/plugin/skills/trench-scan/SKILL.md +44 -0
  21. package/dist/packages/cli/assets/claude/schemas/larp.schema.json +117 -0
  22. package/dist/packages/cli/assets/claude/schemas/trench-scan.schema.json +71 -0
  23. package/dist/packages/cli/assets/claude/schemas/verdict.schema.json +115 -0
  24. package/dist/packages/cli/bin/dexterm.mjs +11 -0
  25. package/dist/packages/cli/src/agent-cmd.js +336 -0
  26. package/dist/packages/cli/src/agent-roster.js +26 -0
  27. package/dist/packages/cli/src/alerts/adapters/desktop.js +40 -0
  28. package/dist/packages/cli/src/alerts/adapters/discord.js +36 -0
  29. package/dist/packages/cli/src/alerts/adapters/telegram.js +43 -0
  30. package/dist/packages/cli/src/alerts/adapters/toast.js +16 -0
  31. package/dist/packages/cli/src/alerts/creds.js +83 -0
  32. package/dist/packages/cli/src/alerts/format.js +41 -0
  33. package/dist/packages/cli/src/alerts/index.js +10 -0
  34. package/dist/packages/cli/src/alerts/notifier.js +53 -0
  35. package/dist/packages/cli/src/alerts/route.js +19 -0
  36. package/dist/packages/cli/src/alerts/types.js +1 -0
  37. package/dist/packages/cli/src/alerts-cmd.js +212 -0
  38. package/dist/packages/cli/src/analyst/backend.js +526 -0
  39. package/dist/packages/cli/src/analyst/results.js +38 -0
  40. package/dist/packages/cli/src/analyst/session.js +319 -0
  41. package/dist/packages/cli/src/audit.js +51 -0
  42. package/dist/packages/cli/src/backtest-cmd.js +208 -0
  43. package/dist/packages/cli/src/boot-state.js +62 -0
  44. package/dist/packages/cli/src/coin-target.js +2 -0
  45. package/dist/packages/cli/src/custom.js +261 -0
  46. package/dist/packages/cli/src/display.js +191 -0
  47. package/dist/packages/cli/src/doctor.js +375 -0
  48. package/dist/packages/cli/src/export.js +235 -0
  49. package/dist/packages/cli/src/feed.js +634 -0
  50. package/dist/packages/cli/src/fixtures.js +275 -0
  51. package/dist/packages/cli/src/follow-cmd.js +221 -0
  52. package/dist/packages/cli/src/images-config.js +59 -0
  53. package/dist/packages/cli/src/index.js +31 -0
  54. package/dist/packages/cli/src/kb-skill-cmd.js +240 -0
  55. package/dist/packages/cli/src/larp-record.js +21 -0
  56. package/dist/packages/cli/src/live/copy.js +80 -0
  57. package/dist/packages/cli/src/live/flow.js +233 -0
  58. package/dist/packages/cli/src/live/index.js +511 -0
  59. package/dist/packages/cli/src/live/intel.js +227 -0
  60. package/dist/packages/cli/src/live/newpairs.js +334 -0
  61. package/dist/packages/cli/src/live/screens/newpairs-live.js +219 -0
  62. package/dist/packages/cli/src/live/screens/token-live.js +459 -0
  63. package/dist/packages/cli/src/live/screens/watchlist-live.js +149 -0
  64. package/dist/packages/cli/src/live/token.js +585 -0
  65. package/dist/packages/cli/src/live/trade.js +929 -0
  66. package/dist/packages/cli/src/live/watchlist.js +178 -0
  67. package/dist/packages/cli/src/main.js +5785 -0
  68. package/dist/packages/cli/src/mcp-cmd.js +326 -0
  69. package/dist/packages/cli/src/narrative-cmd.js +76 -0
  70. package/dist/packages/cli/src/pack-cmd.js +323 -0
  71. package/dist/packages/cli/src/plan-cmd.js +278 -0
  72. package/dist/packages/cli/src/popup.js +810 -0
  73. package/dist/packages/cli/src/rules-cmd.js +131 -0
  74. package/dist/packages/cli/src/rules.js +358 -0
  75. package/dist/packages/cli/src/scan/command.js +57 -0
  76. package/dist/packages/cli/src/scan/engine.js +419 -0
  77. package/dist/packages/cli/src/scan/observe.js +64 -0
  78. package/dist/packages/cli/src/scan/ui.js +98 -0
  79. package/dist/packages/cli/src/screener/filter.js +241 -0
  80. package/dist/packages/cli/src/screener/presets.js +80 -0
  81. package/dist/packages/cli/src/screener/rows.js +146 -0
  82. package/dist/packages/cli/src/screener/rug.js +50 -0
  83. package/dist/packages/cli/src/screener/sort.js +52 -0
  84. package/dist/packages/cli/src/screener/view.js +183 -0
  85. package/dist/packages/cli/src/screens/analyst-session.js +343 -0
  86. package/dist/packages/cli/src/screens/analyst.js +326 -0
  87. package/dist/packages/cli/src/screens/boot.js +74 -0
  88. package/dist/packages/cli/src/screens/bubbles.js +255 -0
  89. package/dist/packages/cli/src/screens/coin.js +33 -0
  90. package/dist/packages/cli/src/screens/follows.js +201 -0
  91. package/dist/packages/cli/src/screens/kol.js +90 -0
  92. package/dist/packages/cli/src/screens/narrative.js +90 -0
  93. package/dist/packages/cli/src/screens/newpairs.js +150 -0
  94. package/dist/packages/cli/src/screens/overlay.js +257 -0
  95. package/dist/packages/cli/src/screens/plans.js +126 -0
  96. package/dist/packages/cli/src/screens/positions.js +176 -0
  97. package/dist/packages/cli/src/screens/rules.js +170 -0
  98. package/dist/packages/cli/src/screens/screener.js +459 -0
  99. package/dist/packages/cli/src/screens/social-panel.js +107 -0
  100. package/dist/packages/cli/src/screens/ticket.js +342 -0
  101. package/dist/packages/cli/src/screens/token.js +312 -0
  102. package/dist/packages/cli/src/screens/trending.js +181 -0
  103. package/dist/packages/cli/src/screens/watchlist.js +104 -0
  104. package/dist/packages/cli/src/skill-eval-build.js +109 -0
  105. package/dist/packages/cli/src/social/demo.js +96 -0
  106. package/dist/packages/cli/src/social/view.js +250 -0
  107. package/dist/packages/cli/src/state.js +463 -0
  108. package/dist/packages/cli/src/theme-cmd.js +126 -0
  109. package/dist/packages/cli/src/trade.js +319 -0
  110. package/dist/packages/cli/src/update.js +294 -0
  111. package/dist/packages/cli/src/version.js +3 -0
  112. package/dist/packages/cli/src/voice-cmd.js +119 -0
  113. package/dist/packages/cli/src/voice-hud.js +42 -0
  114. package/dist/packages/cli/src/wallet-cmd.js +440 -0
  115. package/dist/packages/cli/src/wallet-command.js +31 -0
  116. package/dist/packages/cli/src/watch-cmd.js +190 -0
  117. package/dist/packages/cli/src/widgets.js +208 -0
  118. package/dist/packages/cli/src/workspace-cmd.js +68 -0
  119. package/dist/packages/cli/src/x-cmd.js +154 -0
  120. package/dist/packages/custom/src/config.js +213 -0
  121. package/dist/packages/custom/src/index.js +10 -0
  122. package/dist/packages/custom/src/keymap.js +107 -0
  123. package/dist/packages/custom/src/layout.js +235 -0
  124. package/dist/packages/custom/src/packs.js +633 -0
  125. package/dist/packages/custom/src/rules.js +704 -0
  126. package/dist/packages/custom/src/schema.js +538 -0
  127. package/dist/packages/custom/src/themes.js +176 -0
  128. package/dist/packages/custom/src/widget-html.js +222 -0
  129. package/dist/packages/custom/src/workspace.js +141 -0
  130. package/dist/packages/data/src/analyst-actions.js +133 -0
  131. package/dist/packages/data/src/budget.js +88 -0
  132. package/dist/packages/data/src/cache.js +142 -0
  133. package/dist/packages/data/src/candles.js +168 -0
  134. package/dist/packages/data/src/clock.js +64 -0
  135. package/dist/packages/data/src/coin-target.js +82 -0
  136. package/dist/packages/data/src/credits.js +137 -0
  137. package/dist/packages/data/src/detail.js +97 -0
  138. package/dist/packages/data/src/fast-lane.js +321 -0
  139. package/dist/packages/data/src/fixtures.js +135 -0
  140. package/dist/packages/data/src/health.js +245 -0
  141. package/dist/packages/data/src/http.js +277 -0
  142. package/dist/packages/data/src/images/cache.js +141 -0
  143. package/dist/packages/data/src/images/decode-worker.js +28 -0
  144. package/dist/packages/data/src/images/decode.js +81 -0
  145. package/dist/packages/data/src/images/fetch.js +162 -0
  146. package/dist/packages/data/src/images/gif.js +214 -0
  147. package/dist/packages/data/src/images/index.js +10 -0
  148. package/dist/packages/data/src/images/jpeg.js +544 -0
  149. package/dist/packages/data/src/images/png.js +310 -0
  150. package/dist/packages/data/src/images/service.js +334 -0
  151. package/dist/packages/data/src/images/types.js +27 -0
  152. package/dist/packages/data/src/index.js +211 -0
  153. package/dist/packages/data/src/intel/helius-history.js +70 -0
  154. package/dist/packages/data/src/intel/holder-class.js +125 -0
  155. package/dist/packages/data/src/intel/rules.js +421 -0
  156. package/dist/packages/data/src/intel/scan.js +170 -0
  157. package/dist/packages/data/src/larp/evidence.js +288 -0
  158. package/dist/packages/data/src/larp/link-baseline.js +196 -0
  159. package/dist/packages/data/src/larp/links.js +137 -0
  160. package/dist/packages/data/src/larp/robots.js +90 -0
  161. package/dist/packages/data/src/larp/safe-fetch.js +389 -0
  162. package/dist/packages/data/src/limiter.js +341 -0
  163. package/dist/packages/data/src/model.js +12 -0
  164. package/dist/packages/data/src/paper.js +331 -0
  165. package/dist/packages/data/src/rpc-config.js +126 -0
  166. package/dist/packages/data/src/rpc-pool.js +166 -0
  167. package/dist/packages/data/src/social/chain.js +83 -0
  168. package/dist/packages/data/src/social/dedupe.js +205 -0
  169. package/dist/packages/data/src/social/feed.js +462 -0
  170. package/dist/packages/data/src/social/firewall.js +110 -0
  171. package/dist/packages/data/src/social/index.js +11 -0
  172. package/dist/packages/data/src/social/kol.js +269 -0
  173. package/dist/packages/data/src/social/model.js +11 -0
  174. package/dist/packages/data/src/social/rank.js +184 -0
  175. package/dist/packages/data/src/social/rss.js +113 -0
  176. package/dist/packages/data/src/social/summary.js +104 -0
  177. package/dist/packages/data/src/social/venues.js +186 -0
  178. package/dist/packages/data/src/sources/dexscreener.js +184 -0
  179. package/dist/packages/data/src/sources/geckoterminal.js +133 -0
  180. package/dist/packages/data/src/sources/goplus.js +161 -0
  181. package/dist/packages/data/src/sources/jupiter-swap.js +236 -0
  182. package/dist/packages/data/src/sources/jupiter.js +198 -0
  183. package/dist/packages/data/src/sources/pda.js +113 -0
  184. package/dist/packages/data/src/sources/pump-curve.js +58 -0
  185. package/dist/packages/data/src/sources/pumpportal.js +252 -0
  186. package/dist/packages/data/src/sources/rugcheck.js +71 -0
  187. package/dist/packages/data/src/sources/solana-rpc.js +299 -0
  188. package/dist/packages/data/src/sources/solana-ws.js +287 -0
  189. package/dist/packages/data/src/store.js +289 -0
  190. package/dist/packages/data/src/trade/bridge.js +464 -0
  191. package/dist/packages/data/src/trade/caps.js +323 -0
  192. package/dist/packages/data/src/trade/copy/auto.js +385 -0
  193. package/dist/packages/data/src/trade/copy/follows.js +103 -0
  194. package/dist/packages/data/src/trade/copy/index.js +9 -0
  195. package/dist/packages/data/src/trade/copy/mirror.js +91 -0
  196. package/dist/packages/data/src/trade/copy/stats.js +120 -0
  197. package/dist/packages/data/src/trade/copy/tracker.js +158 -0
  198. package/dist/packages/data/src/trade/copy/trades.js +87 -0
  199. package/dist/packages/data/src/trade/copy/types.js +6 -0
  200. package/dist/packages/data/src/trade/executor.js +933 -0
  201. package/dist/packages/data/src/trade/kill-switch.js +47 -0
  202. package/dist/packages/data/src/trade/link-store.js +52 -0
  203. package/dist/packages/data/src/trade/plans/confirm.js +157 -0
  204. package/dist/packages/data/src/trade/plans/engine.js +784 -0
  205. package/dist/packages/data/src/trade/plans/executor-live.js +220 -0
  206. package/dist/packages/data/src/trade/plans/executor-paper.js +44 -0
  207. package/dist/packages/data/src/trade/plans/executor.js +11 -0
  208. package/dist/packages/data/src/trade/plans/index.js +12 -0
  209. package/dist/packages/data/src/trade/plans/journal.js +77 -0
  210. package/dist/packages/data/src/trade/plans/mandate.js +129 -0
  211. package/dist/packages/data/src/trade/plans/plan.js +179 -0
  212. package/dist/packages/data/src/trade/plans/service.js +168 -0
  213. package/dist/packages/data/src/trade/plans/types.js +6 -0
  214. package/dist/packages/data/src/trade/rpc-exec.js +229 -0
  215. package/dist/packages/data/src/trade/signer/client.js +197 -0
  216. package/dist/packages/data/src/trade/signer/fast-wallet.js +154 -0
  217. package/dist/packages/data/src/trade/signer/host.js +97 -0
  218. package/dist/packages/data/src/trade/signer/main.js +121 -0
  219. package/dist/packages/data/src/trade/signer/probe-builder.js +85 -0
  220. package/dist/packages/data/src/trade/signer/protocol.js +92 -0
  221. package/dist/packages/data/src/trade/signer/service.js +400 -0
  222. package/dist/packages/data/src/trade/signer/sol-usd-feed.js +98 -0
  223. package/dist/packages/data/src/trade/sol-usd.js +86 -0
  224. package/dist/packages/data/src/trade/swap-build.js +108 -0
  225. package/dist/packages/data/src/trade/token-delta.js +201 -0
  226. package/dist/packages/data/src/trade/tx-decode.js +632 -0
  227. package/dist/packages/data/src/util.js +24 -0
  228. package/dist/packages/data/src/watchlist.js +176 -0
  229. package/dist/packages/data/src/x/api.js +256 -0
  230. package/dist/packages/data/src/x/budget.js +66 -0
  231. package/dist/packages/data/src/x/config.js +49 -0
  232. package/dist/packages/data/src/x/index.js +10 -0
  233. package/dist/packages/data/src/x/mock-server.js +217 -0
  234. package/dist/packages/data/src/x/oauth.js +242 -0
  235. package/dist/packages/data/src/x/pkce.js +21 -0
  236. package/dist/packages/data/src/x/source.js +285 -0
  237. package/dist/packages/data/src/x/token-store.js +134 -0
  238. package/dist/packages/data/src/x/transport.js +71 -0
  239. package/dist/packages/data/vendor/solana-web3/LICENSE +20 -0
  240. package/dist/packages/data/vendor/solana-web3/NOTICE.md +13 -0
  241. package/dist/packages/data/vendor/solana-web3/index.iife.min.js +20 -0
  242. package/dist/packages/mcp/assets/cases.json +1194 -0
  243. package/dist/packages/mcp/assets/kb/entries/cabal-and-coordinated-launches.md +28 -0
  244. package/dist/packages/mcp/assets/kb/entries/common-rug-patterns.md +40 -0
  245. package/dist/packages/mcp/assets/kb/entries/dbc-mechanics.md +30 -0
  246. package/dist/packages/mcp/assets/kb/entries/dev-wallet-behaviour.md +33 -0
  247. package/dist/packages/mcp/assets/kb/entries/glossary.md +35 -0
  248. package/dist/packages/mcp/assets/kb/entries/holder-concentration.md +30 -0
  249. package/dist/packages/mcp/assets/kb/entries/jito-bundles.md +29 -0
  250. package/dist/packages/mcp/assets/kb/entries/launchlab-curve.md +31 -0
  251. package/dist/packages/mcp/assets/kb/entries/lp-burn-vs-lock.md +31 -0
  252. package/dist/packages/mcp/assets/kb/entries/metadata-and-copycats.md +29 -0
  253. package/dist/packages/mcp/assets/kb/entries/mint-freeze-authority.md +31 -0
  254. package/dist/packages/mcp/assets/kb/entries/narrative-lifecycle.md +32 -0
  255. package/dist/packages/mcp/assets/kb/entries/pump-bonding-curve.md +33 -0
  256. package/dist/packages/mcp/assets/kb/entries/pumpswap-migration.md +29 -0
  257. package/dist/packages/mcp/assets/kb/entries/sniping-and-snipers.md +29 -0
  258. package/dist/packages/mcp/assets/kb/entries/token2022-extensions-risk.md +32 -0
  259. package/dist/packages/mcp/assets/kb/entries/wash-trading-fake-volume.md +33 -0
  260. package/dist/packages/mcp/assets/skills/rug-check.md +52 -0
  261. package/dist/packages/mcp/assets/skills/token-dossier.md +57 -0
  262. package/dist/packages/mcp/assets/skills/trench-scan.md +40 -0
  263. package/dist/packages/mcp/bin/dexterm-mcp.mjs +16 -0
  264. package/dist/packages/mcp/src/dossier.js +78 -0
  265. package/dist/packages/mcp/src/firewall.js +21 -0
  266. package/dist/packages/mcp/src/index.js +22 -0
  267. package/dist/packages/mcp/src/server.js +936 -0
  268. package/dist/packages/mcp/src/user-content.js +434 -0
  269. package/dist/packages/packs/src/backtest.js +183 -0
  270. package/dist/packages/packs/src/digest.js +95 -0
  271. package/dist/packages/packs/src/firewall.js +57 -0
  272. package/dist/packages/packs/src/index.js +20 -0
  273. package/dist/packages/packs/src/larp-eval.js +100 -0
  274. package/dist/packages/packs/src/narrative.js +309 -0
  275. package/dist/packages/packs/src/reason.js +135 -0
  276. package/dist/packages/packs/src/rug-model.js +137 -0
  277. package/dist/packages/packs/src/schema.js +54 -0
  278. package/dist/packages/packs/src/skill-backtest.js +300 -0
  279. package/dist/packages/packs/src/token-dossier.js +174 -0
  280. package/dist/packages/packs/src/verdicts.js +17 -0
  281. package/dist/packages/packs/src/wallet-dossier.js +105 -0
  282. package/dist/packages/popup/src/config.js +71 -0
  283. package/dist/packages/popup/src/dock.js +271 -0
  284. package/dist/packages/popup/src/host.js +210 -0
  285. package/dist/packages/popup/src/index.js +12 -0
  286. package/dist/packages/popup/src/loopback.js +53 -0
  287. package/dist/packages/popup/src/open.js +183 -0
  288. package/dist/packages/popup/src/pages/bubbles-lib.js +160 -0
  289. package/dist/packages/popup/src/pages/bubbles.css +23 -0
  290. package/dist/packages/popup/src/pages/bubbles.html +36 -0
  291. package/dist/packages/popup/src/pages/bubbles.js +214 -0
  292. package/dist/packages/popup/src/pages/chart-lib.js +262 -0
  293. package/dist/packages/popup/src/pages/chart.css +50 -0
  294. package/dist/packages/popup/src/pages/chart.html +56 -0
  295. package/dist/packages/popup/src/pages/chart.js +554 -0
  296. package/dist/packages/popup/src/pages/common.css +34 -0
  297. package/dist/packages/popup/src/pages/common.js +187 -0
  298. package/dist/packages/popup/src/pages/feeds.html +20 -0
  299. package/dist/packages/popup/src/pages/feeds.js +77 -0
  300. package/dist/packages/popup/src/pages/narrative.html +20 -0
  301. package/dist/packages/popup/src/pages/narrative.js +61 -0
  302. package/dist/packages/popup/src/pages/plans.css +30 -0
  303. package/dist/packages/popup/src/pages/plans.html +26 -0
  304. package/dist/packages/popup/src/pages/plans.js +82 -0
  305. package/dist/packages/popup/src/pages/roster.css +41 -0
  306. package/dist/packages/popup/src/pages/roster.html +25 -0
  307. package/dist/packages/popup/src/pages/roster.js +75 -0
  308. package/dist/packages/popup/src/pages/token.html +20 -0
  309. package/dist/packages/popup/src/pages/token.js +112 -0
  310. package/dist/packages/popup/src/pages/widget-sdk.js +224 -0
  311. package/dist/packages/popup/src/pages/widget.css +5 -0
  312. package/dist/packages/popup/src/pages/widget.html +21 -0
  313. package/dist/packages/popup/src/pages/widget.js +85 -0
  314. package/dist/packages/popup/src/protocol.js +31 -0
  315. package/dist/packages/popup/src/selftest.js +156 -0
  316. package/dist/packages/popup/src/server.js +582 -0
  317. package/dist/packages/popup/src/sinkproxy.js +167 -0
  318. package/dist/packages/popup/src/widget-html.js +231 -0
  319. package/dist/packages/popup/vendor/lightweight-charts/LICENSE +201 -0
  320. package/dist/packages/popup/vendor/lightweight-charts/NOTICE +2 -0
  321. package/dist/packages/popup/vendor/lightweight-charts/README.md +30 -0
  322. package/dist/packages/popup/vendor/lightweight-charts/VERSION +1 -0
  323. package/dist/packages/popup/vendor/lightweight-charts/lightweight-charts.standalone.production.js +7 -0
  324. package/dist/packages/recorder/bin/dexterm-recorder.mjs +11 -0
  325. package/dist/packages/recorder/src/cli.js +113 -0
  326. package/dist/packages/recorder/src/export.js +71 -0
  327. package/dist/packages/recorder/src/index.js +20 -0
  328. package/dist/packages/recorder/src/labels.js +151 -0
  329. package/dist/packages/recorder/src/open.js +29 -0
  330. package/dist/packages/recorder/src/recorder.js +553 -0
  331. package/dist/packages/recorder/src/schedule.js +43 -0
  332. package/dist/packages/recorder/src/schema.js +135 -0
  333. package/dist/packages/recorder/src/snapshot.js +191 -0
  334. package/dist/packages/recorder/src/sweep.js +52 -0
  335. package/dist/packages/recorder/src/verdicts.js +52 -0
  336. package/dist/packages/tui/src/bubbles.js +415 -0
  337. package/dist/packages/tui/src/canvas.js +370 -0
  338. package/dist/packages/tui/src/chrome.js +85 -0
  339. package/dist/packages/tui/src/color.js +133 -0
  340. package/dist/packages/tui/src/flush.js +62 -0
  341. package/dist/packages/tui/src/fmt.js +188 -0
  342. package/dist/packages/tui/src/fx-trade.js +278 -0
  343. package/dist/packages/tui/src/fx.js +527 -0
  344. package/dist/packages/tui/src/images/blocks.js +141 -0
  345. package/dist/packages/tui/src/images/coin.js +22 -0
  346. package/dist/packages/tui/src/images/detect.js +140 -0
  347. package/dist/packages/tui/src/images/index.js +7 -0
  348. package/dist/packages/tui/src/images/layer.js +146 -0
  349. package/dist/packages/tui/src/images/pixels.js +157 -0
  350. package/dist/packages/tui/src/images/protocols.js +87 -0
  351. package/dist/packages/tui/src/index.js +18 -0
  352. package/dist/packages/tui/src/keymap.js +357 -0
  353. package/dist/packages/tui/src/layout.js +11 -0
  354. package/dist/packages/tui/src/raster-font.js +195 -0
  355. package/dist/packages/tui/src/raster.js +213 -0
  356. package/dist/packages/tui/src/sound.js +177 -0
  357. package/dist/packages/tui/src/theme.js +182 -0
  358. package/dist/packages/tui/src/widgets.js +598 -0
  359. package/dist/packages/voice/src/controller.js +407 -0
  360. package/dist/packages/voice/src/doctor.js +131 -0
  361. package/dist/packages/voice/src/download.js +184 -0
  362. package/dist/packages/voice/src/engines.js +84 -0
  363. package/dist/packages/voice/src/index.js +20 -0
  364. package/dist/packages/voice/src/router.js +502 -0
  365. package/dist/packages/voice/src/stt/apple-helper.swift.js +103 -0
  366. package/dist/packages/voice/src/stt/apple.js +179 -0
  367. package/dist/packages/voice/src/stt/fake.js +34 -0
  368. package/dist/packages/voice/src/stt/whisper.js +112 -0
  369. package/dist/packages/voice/src/summary.js +44 -0
  370. package/dist/packages/voice/src/tts/espeak.js +131 -0
  371. package/dist/packages/voice/src/tts/fake.js +30 -0
  372. package/dist/packages/voice/src/tts/piper.js +206 -0
  373. package/dist/packages/voice/src/tts/say.js +132 -0
  374. package/dist/packages/voice/src/tts/voices.js +206 -0
  375. package/dist/packages/voice/src/types.js +3 -0
  376. package/package.json +38 -4
  377. package/README.md +0 -3
@@ -0,0 +1,357 @@
1
+ // @dexterm/tui — key decoding and keymap (SPEC §7.7: vim keys plus arrows, single-key verbs).
2
+ // parseKeys() turns a raw stdin chunk into named keys; Keymap maps named keys to actions,
3
+ // with per-screen overrides layered on a global table.
4
+ const CSI_FINAL = {
5
+ A: 'up', B: 'down', C: 'right', D: 'left', H: 'home', F: 'end',
6
+ '1~': 'home', '2~': 'delete', '3~': 'delete', '4~': 'end', '5~': 'pageup', '6~': 'pagedown', '7~': 'home', '8~': 'end',
7
+ '11~': 'f1', '12~': 'f2', '13~': 'f3', '14~': 'f4', '15~': 'f5', '17~': 'f6', '18~': 'f7', '19~': 'f8', '20~': 'f9', '21~': 'f10', '23~': 'f11', '24~': 'f12',
8
+ };
9
+ const SS3_FINAL = { A: 'up', B: 'down', C: 'right', D: 'left', H: 'home', F: 'end', P: 'f1', Q: 'f2', R: 'f3', S: 'f4' };
10
+ /** Decode one raw stdin chunk (utf8 string) into zero or more keys. */
11
+ export function parseKeys(data) {
12
+ const keys = [];
13
+ let i = 0;
14
+ while (i < data.length) {
15
+ const c = data[i];
16
+ if (c === '\x1b') {
17
+ const next = data[i + 1];
18
+ if (next === '[') {
19
+ // CSI: ESC [ params final
20
+ let j = i + 2;
21
+ let params = '';
22
+ while (j < data.length && /[0-9;]/.test(data[j]))
23
+ params += data[j++];
24
+ const fin = data[j];
25
+ if (fin === undefined) {
26
+ keys.push({ name: 'esc', raw: c });
27
+ i = data.length;
28
+ break;
29
+ }
30
+ // task-1388: bracketed-paste markers (ESC [ 200~ / 201~). dexterm never enables the mode, but a
31
+ // terminal/multiplexer that does would otherwise wrap a paste in them and the unknown-CSI branch
32
+ // below would surface each as `esc` — cancelling the go-to prompt before the pasted mint arrives.
33
+ // Swallow the markers so the printable paste flows through as plain chars.
34
+ if (fin === '~' && (params === '200' || params === '201')) {
35
+ i = j + 1;
36
+ continue;
37
+ }
38
+ const raw = data.slice(i, j + 1);
39
+ const parts = params.split(';');
40
+ const mod = parts.length > 1 ? Number(parts[1]) - 1 : 0;
41
+ const key = fin === '~' ? CSI_FINAL[`${parts[0]}~`] : CSI_FINAL[fin];
42
+ if (key) {
43
+ keys.push({ name: key, raw, shift: !!(mod & 1), alt: !!(mod & 2), ctrl: !!(mod & 4) });
44
+ }
45
+ else {
46
+ keys.push({ name: 'esc', raw }); // unknown CSI, surface as esc so the UI still reacts
47
+ }
48
+ i = j + 1;
49
+ continue;
50
+ }
51
+ if (next === 'O' && data[i + 2] && SS3_FINAL[data[i + 2]]) {
52
+ keys.push({ name: SS3_FINAL[data[i + 2]], raw: data.slice(i, i + 3) });
53
+ i += 3;
54
+ continue;
55
+ }
56
+ if (next !== undefined && next !== '\x1b') {
57
+ // alt+key
58
+ const inner = parseKeys(next);
59
+ for (const k of inner)
60
+ keys.push({ ...k, alt: true, raw: c + k.raw });
61
+ i += 2;
62
+ continue;
63
+ }
64
+ keys.push({ name: 'esc', raw: c });
65
+ i += 1;
66
+ continue;
67
+ }
68
+ if (c === '\r' || c === '\n') {
69
+ keys.push({ name: 'enter', raw: c });
70
+ i++;
71
+ continue;
72
+ }
73
+ if (c === '\t') {
74
+ keys.push({ name: 'tab', raw: c });
75
+ i++;
76
+ continue;
77
+ }
78
+ if (c === '\x7f' || c === '\b') {
79
+ keys.push({ name: 'backspace', raw: c });
80
+ i++;
81
+ continue;
82
+ }
83
+ if (c === ' ') {
84
+ keys.push({ name: 'space', ch: ' ', raw: c });
85
+ i++;
86
+ continue;
87
+ }
88
+ const code = c.charCodeAt(0);
89
+ if (code < 32) {
90
+ keys.push({ name: 'char', ch: String.fromCharCode(code + 96), ctrl: true, raw: c });
91
+ i++;
92
+ continue;
93
+ }
94
+ // printable (may be a surrogate pair)
95
+ const cp = data.codePointAt(i);
96
+ const s = String.fromCodePoint(cp);
97
+ keys.push({ name: 'char', ch: s, raw: s });
98
+ i += s.length;
99
+ }
100
+ return keys;
101
+ }
102
+ /**
103
+ * Canonical key id used in bindings: 'j', 'enter', 'up', 'ctrl+c', 'ctrl+l', 'alt+x', 'shift+tab'.
104
+ * Printable characters are case-sensitive ('G' and 'g' differ).
105
+ */
106
+ export function keyId(k) {
107
+ const base = k.name === 'char' ? (k.ch ?? '') : k.name;
108
+ let id = '';
109
+ if (k.ctrl)
110
+ id += 'ctrl+';
111
+ if (k.alt)
112
+ id += 'alt+';
113
+ if (k.shift && k.name !== 'char')
114
+ id += 'shift+';
115
+ return id + base;
116
+ }
117
+ export class Keymap {
118
+ global = new Map();
119
+ perScreen = new Map();
120
+ /** First keys of two-key chords ("ctrl+w s" → "ctrl+w"), task-1358. */
121
+ prefixes = new Set();
122
+ bindings = [];
123
+ constructor(bindings = []) {
124
+ for (const b of bindings)
125
+ this.bind(b);
126
+ }
127
+ bind(b) {
128
+ this.bindings.push(b);
129
+ const target = b.screen ? this.getScreen(b.screen) : this.global;
130
+ for (const k of b.keys) {
131
+ target.set(k, b);
132
+ const sp = k.indexOf(' ');
133
+ if (sp > 0)
134
+ this.prefixes.add(k.slice(0, sp));
135
+ }
136
+ return this;
137
+ }
138
+ /** Whether `id` starts a two-key chord (the loop then waits for the second key). */
139
+ isPrefix(id) { return this.prefixes.has(id); }
140
+ /** Resolve an already-formed key id (or chord id like "ctrl+w s"): screen bindings first, then global. */
141
+ resolveId(id, screen) {
142
+ if (screen) {
143
+ const hit = this.perScreen.get(screen)?.get(id);
144
+ if (hit)
145
+ return hit.action;
146
+ }
147
+ return this.global.get(id)?.action;
148
+ }
149
+ getScreen(screen) {
150
+ let m = this.perScreen.get(screen);
151
+ if (!m) {
152
+ m = new Map();
153
+ this.perScreen.set(screen, m);
154
+ }
155
+ return m;
156
+ }
157
+ /** Resolve a decoded key to an action: screen bindings first, then global. */
158
+ resolve(k, screen) {
159
+ const id = keyId(k);
160
+ if (screen) {
161
+ const hit = this.perScreen.get(screen)?.get(id);
162
+ if (hit)
163
+ return hit.action;
164
+ }
165
+ return this.global.get(id)?.action;
166
+ }
167
+ /** Resolve a raw stdin chunk; returns one action per decoded key that matched. */
168
+ resolveRaw(data, screen) {
169
+ const out = [];
170
+ for (const k of parseKeys(data)) {
171
+ const a = this.resolve(k, screen);
172
+ if (a !== undefined)
173
+ out.push(a);
174
+ }
175
+ return out;
176
+ }
177
+ /** Bindings visible on a screen (global + that screen), for footers and the `?` overlay. */
178
+ forScreen(screen) {
179
+ return this.bindings.filter((b) => !b.screen || b.screen === screen);
180
+ }
181
+ }
182
+ /** The prototype's key table (README of dexterm/prototype) plus the SPEC §4.1 screener keys. */
183
+ export const DEFAULT_KEYMAP = new Keymap([
184
+ { keys: ['q', 'ctrl+c'], action: 'quit', label: 'quit' },
185
+ { keys: ['1'], action: 'screen.screener', label: 'screener' },
186
+ { keys: ['2'], action: 'screen.newpairs', label: 'new pairs' },
187
+ { keys: ['3'], action: 'screen.watchlist', label: 'watchlist' },
188
+ { keys: ['4'], action: 'screen.analyst', label: 'analyst' },
189
+ { keys: ['tab'], action: 'screen.next', label: 'screens' },
190
+ { keys: ['j', 'down'], action: 'move.down', label: 'move' },
191
+ { keys: ['k', 'up'], action: 'move.up', label: 'move' },
192
+ { keys: ['g', 'home'], action: 'move.top', label: 'top' },
193
+ { keys: ['G', 'end'], action: 'move.bottom', label: 'bottom' },
194
+ // task-1388 GO-TO prompt: `g` on the list and token screens opens the "open any coin" input. Per-screen so it
195
+ // overrides the global `g` (move to top) only here; `home` still moves to top on these screens. Collision-free
196
+ // with every other verb on these screens (the token screen's `g` was only "scroll answer to top", kept on home).
197
+ { keys: ['g'], action: 'goto.open', label: 'go to coin', screen: 'screener' },
198
+ { keys: ['g'], action: 'goto.open', label: 'go to coin', screen: 'newpairs' },
199
+ { keys: ['g'], action: 'goto.open', label: 'go to coin', screen: 'watchlist' },
200
+ { keys: ['g'], action: 'goto.open', label: 'go to coin', screen: 'token' },
201
+ { keys: ['pagedown', 'ctrl+f'], action: 'move.pagedown', label: 'page' },
202
+ { keys: ['pageup', 'ctrl+b'], action: 'move.pageup', label: 'page' },
203
+ { keys: ['enter'], action: 'open', label: 'open' },
204
+ { keys: ['esc', 'backspace'], action: 'back', label: 'back' },
205
+ { keys: ['a'], action: 'analyst.toggle', label: 'ask claude' },
206
+ // task-1282 JARVIS voice: push-to-talk toggle (hold not possible in a terminal). Lowercase v is free
207
+ // on every screen; the loop auto-enables voice mode on first use and shows a live mic indicator.
208
+ { keys: ['v'], action: 'voice.talk', label: 'voice' },
209
+ // task-1311: `i` focuses the chat input on the token / analyst screens (QA B1–B3); the loop only
210
+ // captures keystrokes into the input while it is focused, so the number keys and `q` never type.
211
+ { keys: ['i'], action: 'input.focus', label: 'ask', screen: 'token' },
212
+ { keys: ['i'], action: 'input.focus', label: 'ask', screen: 'analyst' },
213
+ { keys: ['?'], action: 'help.toggle', label: 'help' },
214
+ { keys: ['t'], action: 'theme.next', label: 'theme' },
215
+ { keys: ['p'], action: 'pause.toggle', label: 'pause' },
216
+ // task-1366: `$` (unbound on every screen) toggles price ⇄ market cap on every screen + both charts; persisted.
217
+ { keys: ['$'], action: 'display.priceMode', label: 'price ⇄ mcap' },
218
+ // task-1401: `E` exports the current view (PNG + text report, local only). Free on every screen.
219
+ { keys: ['E'], action: 'export.view', label: 'export PNG + report' },
220
+ { keys: ['/'], action: 'filter.edit', label: 'filter', screen: 'screener' },
221
+ { keys: ['\\'], action: 'filter.clear', label: 'clear filter', screen: 'screener' },
222
+ { keys: ['s'], action: 'sort.menu', label: 'sort', screen: 'screener' },
223
+ { keys: [']', 'right', 'l'], action: 'preset.next', label: 'preset', screen: 'screener' },
224
+ { keys: ['[', 'left', 'h'], action: 'preset.prev', label: 'preset', screen: 'screener' },
225
+ { keys: ['r'], action: 'refresh', label: 'refresh', screen: 'screener' },
226
+ // task-1298 live screens: watchlist keys and the token screen's timeframe tabs (SPEC §4.3 footer `1-6`)
227
+ { keys: ['w'], action: 'watch.add', label: 'watch' },
228
+ { keys: ['d'], action: 'watch.remove', label: 'remove', screen: 'watchlist' },
229
+ { keys: ['b'], action: 'alert.propose', label: 'alert' },
230
+ { keys: ['y'], action: 'alert.confirm', label: 'confirm alert' },
231
+ { keys: ['x'], action: 'alert.dismiss', label: 'dismiss alert' },
232
+ { keys: ['1'], action: 'tf.1', label: '1m', screen: 'token' },
233
+ { keys: ['2'], action: 'tf.2', label: '5m', screen: 'token' },
234
+ { keys: ['3'], action: 'tf.3', label: '15m', screen: 'token' },
235
+ { keys: ['4'], action: 'tf.4', label: '1h', screen: 'token' },
236
+ { keys: ['5'], action: 'tf.5', label: '4h', screen: 'token' },
237
+ { keys: ['6'], action: 'tf.6', label: '1d', screen: 'token' },
238
+ // task-1311 (QA B5): copy the full contract address from the token screen. Overrides the global
239
+ // `y` (confirm alert) on this screen only.
240
+ { keys: ['y'], action: 'copy.ca', label: 'copy CA', screen: 'token' },
241
+ { keys: ['r'], action: 'refresh', label: 'refresh', screen: 'token' },
242
+ { keys: ['r'], action: 'refresh', label: 'refresh', screen: 'newpairs' },
243
+ { keys: ['r'], action: 'refresh', label: 'refresh', screen: 'watchlist' },
244
+ // task-1310 PAPER trading. Capital B/S on the token screen open the ticket (collision-free with the
245
+ // global `b` alert and screener `s` sort); `P` opens the positions screen from anywhere.
246
+ { keys: ['B'], action: 'trade.buy', label: 'paper buy', screen: 'token' },
247
+ { keys: ['S'], action: 'trade.sell', label: 'paper sell', screen: 'token' },
248
+ { keys: ['P'], action: 'screen.positions', label: 'positions' },
249
+ { keys: ['r'], action: 'refresh', label: 'refresh', screen: 'positions' },
250
+ // task-1315 LARP detector: open the coin's advertised links from the token screen. Capital letters
251
+ // stay collision-free with the lowercase verbs (t theme, w watch, x dismiss) and the B/S/P pattern.
252
+ { keys: ['W'], action: 'open.web', label: 'open site', screen: 'token' },
253
+ { keys: ['V'], action: 'analyst.larp', label: 'vet product (Claude)', screen: 'token' },
254
+ { keys: ['X'], action: 'open.x', label: 'open X', screen: 'token' },
255
+ { keys: ['T'], action: 'open.tg', label: 'open TG', screen: 'token' },
256
+ { keys: ['L'], action: 'open.links', label: 'links', screen: 'token' },
257
+ // task-1290 popup host: `C` on the token screen opens/toggles the frameless live-chart HUD window for
258
+ // the open coin. (`P` is already the global positions key, so chart uses `C`.) Collision-free with the
259
+ // token screen's other capitals (B/S trade, W/X/T/L links, V vet).
260
+ { keys: ['C'], action: 'popup.chart', label: 'chart popup', screen: 'token' },
261
+ // task-1359: `I` on the token screen opens/toggles the TOKEN-DETAIL HUD (identity, market, risk, snipers/bundled
262
+ // from the wallet-intel scan); `M` on the trending screen opens/toggles the FEEDS HUD (the keyless social feed +
263
+ // official news, newest first; ⏎ in the window opens that coin here). Both are read-only windows. `I` is unused
264
+ // on the token screen (lowercase `i` stays "ask"); `M` on trending matches the M = popup pattern of the
265
+ // narrative / bubbles / plans screens.
266
+ { keys: ['I'], action: 'popup.token', label: 'token popup', screen: 'token' },
267
+ { keys: ['M'], action: 'popup.feeds', label: 'feeds popup', screen: 'trending' },
268
+ // task-1323: `F` flips the token screen's lower-right panel between BUY/SELL FLOW (default) and the raw
269
+ // trade tape. `T` is already "open Telegram" on this screen, so the tape uses F (flow ⇄ tape).
270
+ { keys: ['F'], action: 'tape.toggle', label: 'flow ⇄ tape', screen: 'token' },
271
+ // task-1324 AI SCAN MODE: `Z` toggles the scan anywhere (unused elsewhere, collision-free with every
272
+ // lowercase verb and the token screen's capitals B/S/P/W/V/X/T/L/C/F); `R` resumes scanning after a
273
+ // lock (lowercase `r` stays refresh). Both are inert while the PAPER ticket or a text input has the keys.
274
+ { keys: ['Z'], action: 'scan.toggle', label: 'AI scan' },
275
+ { keys: ['R'], action: 'scan.resume', label: 'resume scan' },
276
+ // task-1330 keyless social layer. `T` opens TRENDING IN THE SPACE from every screen except the token screen
277
+ // (where `T` stays "open Telegram", task-1315; esc then T). `K` opens the KOL lists anywhere (unused before).
278
+ // On the token screen lowercase `s` (unbound there) toggles the SOCIAL panel in place of ON-CHAIN/HOLDERS.
279
+ // On the trending screen: f cycles the source filter, x shows/hides spam + squat rows, n cycles the narrative
280
+ // filter, s shows the sources/health panel, a asks the analyst for the board summary (one chat turn), r refreshes.
281
+ { keys: ['T'], action: 'screen.trending', label: 'trending' },
282
+ { keys: ['K'], action: 'social.kol', label: 'KOL lists' },
283
+ // task-1356 narrative board: global N opens it; on the board, w flips the 1h/24h window and M opens the HUD popup.
284
+ { keys: ['N'], action: 'screen.narrative', label: 'narrative board' },
285
+ { keys: ['w'], action: 'narrative.window', label: '1h/24h', screen: 'narrative' },
286
+ { keys: ['M'], action: 'narrative.popup', label: 'popup', screen: 'narrative' },
287
+ { keys: ['s'], action: 'social.toggle', label: 'social', screen: 'token' },
288
+ { keys: ['f'], action: 'social.filter', label: 'filter', screen: 'trending' },
289
+ { keys: ['x'], action: 'social.spam', label: 'hidden spam', screen: 'trending' },
290
+ { keys: ['n'], action: 'social.narrative', label: 'narrative', screen: 'trending' },
291
+ { keys: ['s'], action: 'social.sources', label: 'sources', screen: 'trending' },
292
+ { keys: ['a'], action: 'social.summary', label: 'summary (claude)', screen: 'trending' },
293
+ { keys: ['r'], action: 'refresh', label: 'refresh', screen: 'trending' },
294
+ { keys: ['f'], action: 'social.filter', label: 'filter', screen: 'token' },
295
+ // KOL screen: space toggles the selected list for the trending feed, m mutes/unmutes the selected handle,
296
+ // d removes the selected handle from a manual list, i types a new handle into the selected manual list.
297
+ { keys: ['space'], action: 'kol.toggle', label: 'enable/disable list', screen: 'kol' },
298
+ { keys: ['m'], action: 'kol.mute', label: 'mute/unmute', screen: 'kol' },
299
+ { keys: ['d'], action: 'kol.remove', label: 'remove handle', screen: 'kol' },
300
+ { keys: ['i'], action: 'kol.add', label: 'add handle', screen: 'kol' },
301
+ // task-1357 Login with X: X imports the user's OWN X lists (handles only, needs `dexterm x login`); o focuses the
302
+ // trending board + token panel on the selected handle (press again or f to clear).
303
+ { keys: ['X'], action: 'kol.importx', label: 'import X lists', screen: 'kol' },
304
+ { keys: ['o'], action: 'kol.focus', label: 'only this handle', screen: 'kol' },
305
+ // task-1340 wallet intel. `M` on the token screen opens the BUBBLE MAP (holder graph: clusters by funding
306
+ // source / same-slot buys / transfers, colour = rule) for the open coin; collision-free with the token screen's
307
+ // other capitals (B/S/P/W/V/X/T/L/C/F/Z/R/K). On the bubble screen `M` opens/closes the popup HUD window, `m`
308
+ // flips bubbles ⇄ treemap, `z` zooms the selected cluster, `D` forces a deep scan, `r` rescans, j/k select.
309
+ { keys: ['M'], action: 'intel.bubbles', label: 'bubble map', screen: 'token' },
310
+ { keys: ['M'], action: 'popup.bubbles', label: 'popup', screen: 'bubbles' },
311
+ { keys: ['m'], action: 'bubbles.view', label: 'treemap ⇄ bubbles', screen: 'bubbles' },
312
+ { keys: ['z'], action: 'bubbles.zoom', label: 'zoom cluster', screen: 'bubbles' },
313
+ { keys: ['D'], action: 'bubbles.deep', label: 'deep scan', screen: 'bubbles' },
314
+ { keys: ['r'], action: 'refresh', label: 'rescan', screen: 'bubbles' },
315
+ // task-1355 order plans & standing mandates. `O` opens the PLANS screen from anywhere (collision-free with
316
+ // every lowercase verb and the capitals B/S/P/W/V/X/T/L/C/F/Z/R/K/M/N/D). On the plans screen: tab flips
317
+ // plans ⇄ mandates, `a` arms the selected row (opens the hold-to-confirm modal — a captured physical keypress
318
+ // is the ONLY thing that arms; voice/agents can never reach this), `c` cancels the selected plan / `r` revokes
319
+ // the selected mandate, `!` panics (revokes all), `M` opens the read-only popup. j/k select, esc backs out.
320
+ { keys: ['O'], action: 'screen.plans', label: 'order plans' },
321
+ { keys: ['tab'], action: 'plans.tab', label: 'plans ⇄ mandates', screen: 'plans' },
322
+ { keys: ['a'], action: 'plans.arm', label: 'arm (hold)', screen: 'plans' },
323
+ { keys: ['c'], action: 'plans.cancel', label: 'cancel plan', screen: 'plans' },
324
+ { keys: ['r'], action: 'plans.revoke', label: 'revoke mandate', screen: 'plans' },
325
+ { keys: ['!'], action: 'plans.panic', label: 'PANIC', screen: 'plans' },
326
+ { keys: ['M'], action: 'plans.popup', label: 'popup', screen: 'plans' },
327
+ { keys: ['G'], action: 'plans.gate', label: 'hands-free gate', screen: 'plans' },
328
+ { keys: ['L'], action: 'plans.live', label: 'fire path paper/live', screen: 'plans' },
329
+ // task-1360 copy trading. `U` opens the FOLLOWED WALLETS screen from anywhere (free capital: not B/S/P/W/V/X/T/L/C/F/Z/R/
330
+ // K/M/N/D/O/G/I). On it: `i` types a wallet address (+ optional label) to follow, `d` unfollows the selected wallet,
331
+ // `r` (global refresh) polls now. Nothing on this screen trades: a buy/sell alert is information only.
332
+ { keys: ['U'], action: 'screen.follows', label: 'followed wallets' },
333
+ { keys: ['i'], action: 'follows.add', label: 'follow a wallet', screen: 'follows' },
334
+ { keys: ['d'], action: 'follows.remove', label: 'unfollow', screen: 'follows' },
335
+ { keys: ['r'], action: 'refresh', label: 'poll now', screen: 'follows' },
336
+ { keys: ['m'], action: 'follows.mirror', label: 'mirror ticket', screen: 'follows' },
337
+ { keys: ['A'], action: 'follows.auto', label: 'auto-mirror', screen: 'follows' },
338
+ // task-1358 workspaces (ctrl+w chord, global). `ctrl+w` itself is free everywhere except the chat input,
339
+ // which owns it (delete word) while focused — the keymap never sees it there.
340
+ { keys: ['ctrl+w w'], action: 'workspace.list', label: 'workspaces' },
341
+ { keys: ['ctrl+w n', 'ctrl+w tab'], action: 'workspace.next', label: 'next workspace' },
342
+ { keys: ['ctrl+w N'], action: 'workspace.prev', label: 'previous workspace' },
343
+ { keys: ['ctrl+w s'], action: 'workspace.save', label: 'save workspace' },
344
+ { keys: ['ctrl+w m'], action: 'workspace.morning', label: 'morning HUD' },
345
+ { keys: ['ctrl+w o'], action: 'workspace.popups', label: 'open workspace popups' },
346
+ { keys: ['ctrl+w d'], action: 'workspace.default', label: 'default workspace' },
347
+ // task-1358 Tier 3 rules (ctrl+r global; the screen's own verbs below). Nothing here arms or signs: a rule's
348
+ // ticket/ask is a PROPOSAL card; ⏎ on it opens the paper ticket editor / asks the analyst, where the user still confirms.
349
+ { keys: ['ctrl+r'], action: 'screen.rules', label: 'rules' },
350
+ { keys: ['i'], action: 'rules.new', label: 'new rule', screen: 'rules' },
351
+ { keys: ['enter'], action: 'rules.act', label: 'edit / act', screen: 'rules' },
352
+ { keys: ['e'], action: 'rules.edit', label: 'edit rule', screen: 'rules' },
353
+ { keys: ['space'], action: 'rules.toggle', label: 'enable/disable', screen: 'rules' },
354
+ { keys: ['d'], action: 'rules.remove', label: 'delete rule', screen: 'rules' },
355
+ { keys: ['tab'], action: 'rules.tab', label: 'rules ⇄ proposals', screen: 'rules' },
356
+ { keys: ['x'], action: 'rules.dismiss', label: 'dismiss proposal', screen: 'rules' },
357
+ ]);
@@ -0,0 +1,11 @@
1
+ // @dexterm/tui — breakpoints (SPEC §7.4): compact < 100 cols, standard 100..139, wide ≥ 140.
2
+ export const BREAKPOINTS = { compact: 0, standard: 100, wide: 140 };
3
+ export function breakpoint(w) {
4
+ if (w < BREAKPOINTS.standard)
5
+ return 'compact';
6
+ if (w < BREAKPOINTS.wide)
7
+ return 'standard';
8
+ return 'wide';
9
+ }
10
+ /** Minimum supported terminal (SPEC §7.4): screener only, 7 columns. */
11
+ export const MIN_SIZE = { w: 80, h: 24 };
@@ -0,0 +1,195 @@
1
+ // @dexterm/tui — a 5×9 bitmap font for the PNG exporter (task-1401). Drawn for dexterm (no third-party font data):
2
+ // rows 0–6 are the cap height, rows 7–8 the descenders. Box drawing, block elements and braille are not here:
3
+ // raster.ts draws those procedurally so they join up across cells exactly like a terminal does.
4
+ const G = {
5
+ ' ': [],
6
+ '!': ['..#..', '..#..', '..#..', '..#..', '..#..', '.....', '..#..'],
7
+ '"': ['.#.#.', '.#.#.', '.#.#.'],
8
+ '#': ['.#.#.', '.#.#.', '#####', '.#.#.', '#####', '.#.#.', '.#.#.'],
9
+ '$': ['..#..', '.####', '#.#..', '.###.', '..#.#', '####.', '..#..'],
10
+ '%': ['##...', '##..#', '...#.', '..#..', '.#...', '#..##', '...##'],
11
+ '&': ['.##..', '#..#.', '#.#..', '.#...', '#.#.#', '#..#.', '.##.#'],
12
+ "'": ['..#..', '..#..', '.#...'],
13
+ '(': ['...#.', '..#..', '.#...', '.#...', '.#...', '..#..', '...#.'],
14
+ ')': ['.#...', '..#..', '...#.', '...#.', '...#.', '..#..', '.#...'],
15
+ '*': ['.....', '..#..', '#.#.#', '.###.', '#.#.#', '..#..', '.....'],
16
+ '+': ['.....', '..#..', '..#..', '#####', '..#..', '..#..', '.....'],
17
+ ',': ['.....', '.....', '.....', '.....', '.....', '..#..', '..#..', '.#...'],
18
+ '-': ['.....', '.....', '.....', '#####', '.....', '.....', '.....'],
19
+ '.': ['.....', '.....', '.....', '.....', '.....', '.##..', '.##..'],
20
+ '/': ['.....', '....#', '...#.', '..#..', '.#...', '#....', '.....'],
21
+ '0': ['.###.', '#...#', '#..##', '#.#.#', '##..#', '#...#', '.###.'],
22
+ '1': ['..#..', '.##..', '..#..', '..#..', '..#..', '..#..', '.###.'],
23
+ '2': ['.###.', '#...#', '....#', '...#.', '..#..', '.#...', '#####'],
24
+ '3': ['#####', '...#.', '..#..', '...#.', '....#', '#...#', '.###.'],
25
+ '4': ['...#.', '..##.', '.#.#.', '#..#.', '#####', '...#.', '...#.'],
26
+ '5': ['#####', '#....', '####.', '....#', '....#', '#...#', '.###.'],
27
+ '6': ['..##.', '.#...', '#....', '####.', '#...#', '#...#', '.###.'],
28
+ '7': ['#####', '....#', '...#.', '..#..', '.#...', '.#...', '.#...'],
29
+ '8': ['.###.', '#...#', '#...#', '.###.', '#...#', '#...#', '.###.'],
30
+ '9': ['.###.', '#...#', '#...#', '.####', '....#', '...#.', '.##..'],
31
+ ':': ['.....', '.##..', '.##..', '.....', '.##..', '.##..', '.....'],
32
+ ';': ['.....', '.##..', '.##..', '.....', '.##..', '.##..', '.#...'],
33
+ '<': ['...#.', '..#..', '.#...', '#....', '.#...', '..#..', '...#.'],
34
+ '=': ['.....', '.....', '#####', '.....', '#####', '.....', '.....'],
35
+ '>': ['.#...', '..#..', '...#.', '....#', '...#.', '..#..', '.#...'],
36
+ '?': ['.###.', '#...#', '....#', '...#.', '..#..', '.....', '..#..'],
37
+ '@': ['.###.', '#...#', '....#', '.##.#', '#.#.#', '#.#.#', '.###.'],
38
+ 'A': ['.###.', '#...#', '#...#', '#####', '#...#', '#...#', '#...#'],
39
+ 'B': ['####.', '#...#', '#...#', '####.', '#...#', '#...#', '####.'],
40
+ 'C': ['.###.', '#...#', '#....', '#....', '#....', '#...#', '.###.'],
41
+ 'D': ['###..', '#..#.', '#...#', '#...#', '#...#', '#..#.', '###..'],
42
+ 'E': ['#####', '#....', '#....', '####.', '#....', '#....', '#####'],
43
+ 'F': ['#####', '#....', '#....', '####.', '#....', '#....', '#....'],
44
+ 'G': ['.###.', '#...#', '#....', '#.###', '#...#', '#...#', '.####'],
45
+ 'H': ['#...#', '#...#', '#...#', '#####', '#...#', '#...#', '#...#'],
46
+ 'I': ['.###.', '..#..', '..#..', '..#..', '..#..', '..#..', '.###.'],
47
+ 'J': ['..###', '...#.', '...#.', '...#.', '...#.', '#..#.', '.##..'],
48
+ 'K': ['#...#', '#..#.', '#.#..', '##...', '#.#..', '#..#.', '#...#'],
49
+ 'L': ['#....', '#....', '#....', '#....', '#....', '#....', '#####'],
50
+ 'M': ['#...#', '##.##', '#.#.#', '#.#.#', '#...#', '#...#', '#...#'],
51
+ 'N': ['#...#', '#...#', '##..#', '#.#.#', '#..##', '#...#', '#...#'],
52
+ 'O': ['.###.', '#...#', '#...#', '#...#', '#...#', '#...#', '.###.'],
53
+ 'P': ['####.', '#...#', '#...#', '####.', '#....', '#....', '#....'],
54
+ 'Q': ['.###.', '#...#', '#...#', '#...#', '#.#.#', '#..#.', '.##.#'],
55
+ 'R': ['####.', '#...#', '#...#', '####.', '#.#..', '#..#.', '#...#'],
56
+ 'S': ['.####', '#....', '#....', '.###.', '....#', '....#', '####.'],
57
+ 'T': ['#####', '..#..', '..#..', '..#..', '..#..', '..#..', '..#..'],
58
+ 'U': ['#...#', '#...#', '#...#', '#...#', '#...#', '#...#', '.###.'],
59
+ 'V': ['#...#', '#...#', '#...#', '#...#', '#...#', '.#.#.', '..#..'],
60
+ 'W': ['#...#', '#...#', '#...#', '#.#.#', '#.#.#', '#.#.#', '.#.#.'],
61
+ 'X': ['#...#', '#...#', '.#.#.', '..#..', '.#.#.', '#...#', '#...#'],
62
+ 'Y': ['#...#', '#...#', '.#.#.', '..#..', '..#..', '..#..', '..#..'],
63
+ 'Z': ['#####', '....#', '...#.', '..#..', '.#...', '#....', '#####'],
64
+ '[': ['.###.', '.#...', '.#...', '.#...', '.#...', '.#...', '.###.'],
65
+ '\\': ['.....', '#....', '.#...', '..#..', '...#.', '....#', '.....'],
66
+ ']': ['.###.', '...#.', '...#.', '...#.', '...#.', '...#.', '.###.'],
67
+ '^': ['..#..', '.#.#.', '#...#'],
68
+ '_': ['.....', '.....', '.....', '.....', '.....', '.....', '.....', '#####'],
69
+ '`': ['.#...', '..#..', '...#.'],
70
+ 'a': ['.....', '.....', '.###.', '....#', '.####', '#...#', '.####'],
71
+ 'b': ['#....', '#....', '#.##.', '##..#', '#...#', '#...#', '####.'],
72
+ 'c': ['.....', '.....', '.###.', '#....', '#....', '#...#', '.###.'],
73
+ 'd': ['....#', '....#', '.##.#', '#..##', '#...#', '#...#', '.####'],
74
+ 'e': ['.....', '.....', '.###.', '#...#', '#####', '#....', '.###.'],
75
+ 'f': ['..##.', '.#..#', '.#...', '###..', '.#...', '.#...', '.#...'],
76
+ 'g': ['.....', '.....', '.####', '#...#', '#...#', '.####', '....#', '....#', '.###.'],
77
+ 'h': ['#....', '#....', '#.##.', '##..#', '#...#', '#...#', '#...#'],
78
+ 'i': ['..#..', '.....', '.##..', '..#..', '..#..', '..#..', '.###.'],
79
+ 'j': ['...#.', '.....', '..##.', '...#.', '...#.', '...#.', '...#.', '#..#.', '.##..'],
80
+ 'k': ['#....', '#....', '#..#.', '#.#..', '##...', '#.#..', '#..#.'],
81
+ 'l': ['.##..', '..#..', '..#..', '..#..', '..#..', '..#..', '.###.'],
82
+ 'm': ['.....', '.....', '##.#.', '#.#.#', '#.#.#', '#...#', '#...#'],
83
+ 'n': ['.....', '.....', '#.##.', '##..#', '#...#', '#...#', '#...#'],
84
+ 'o': ['.....', '.....', '.###.', '#...#', '#...#', '#...#', '.###.'],
85
+ 'p': ['.....', '.....', '####.', '#...#', '#...#', '####.', '#....', '#....', '#....'],
86
+ 'q': ['.....', '.....', '.####', '#...#', '#...#', '.####', '....#', '....#', '....#'],
87
+ 'r': ['.....', '.....', '#.##.', '##..#', '#....', '#....', '#....'],
88
+ 's': ['.....', '.....', '.####', '#....', '.###.', '....#', '####.'],
89
+ 't': ['.#...', '.#...', '###..', '.#...', '.#...', '.#..#', '..##.'],
90
+ 'u': ['.....', '.....', '#...#', '#...#', '#...#', '#..##', '.##.#'],
91
+ 'v': ['.....', '.....', '#...#', '#...#', '#...#', '.#.#.', '..#..'],
92
+ 'w': ['.....', '.....', '#...#', '#...#', '#.#.#', '#.#.#', '.#.#.'],
93
+ 'x': ['.....', '.....', '#...#', '.#.#.', '..#..', '.#.#.', '#...#'],
94
+ 'y': ['.....', '.....', '#...#', '#...#', '#...#', '.####', '....#', '....#', '.###.'],
95
+ 'z': ['.....', '.....', '#####', '...#.', '..#..', '.#...', '#####'],
96
+ '{': ['...#.', '..#..', '..#..', '.#...', '..#..', '..#..', '...#.'],
97
+ '|': ['..#..', '..#..', '..#..', '..#..', '..#..', '..#..', '..#..'],
98
+ '}': ['.#...', '..#..', '..#..', '...#.', '..#..', '..#..', '.#...'],
99
+ '~': ['.....', '.....', '.#...', '#.#.#', '...#.', '.....', '.....'],
100
+ // symbols the screens use
101
+ '·': ['.....', '.....', '.....', '..#..', '.....', '.....', '.....'],
102
+ '•': ['.....', '.....', '.###.', '.###.', '.###.', '.....', '.....'],
103
+ '●': ['.....', '.###.', '#####', '#####', '#####', '.###.', '.....'],
104
+ '◉': ['.....', '.###.', '#...#', '#.#.#', '#...#', '.###.', '.....'],
105
+ '○': ['.....', '.###.', '#...#', '#...#', '#...#', '.###.', '.....'],
106
+ '◌': ['.....', '.#.#.', '#...#', '.....', '#...#', '.#.#.', '.....'],
107
+ '◐': ['.....', '.###.', '##..#', '##..#', '##..#', '.###.', '.....'],
108
+ '◈': ['..#..', '.#.#.', '#.#.#', '.#.#.', '..#..', '.....', '.....'],
109
+ '◆': ['..#..', '.###.', '#####', '.###.', '..#..', '.....', '.....'],
110
+ '◇': ['..#..', '.#.#.', '#...#', '.#.#.', '..#..', '.....', '.....'],
111
+ '■': ['.....', '#####', '#####', '#####', '#####', '#####', '.....'],
112
+ '□': ['.....', '#####', '#...#', '#...#', '#...#', '#####', '.....'],
113
+ '▪': ['.....', '.....', '.###.', '.###.', '.###.', '.....', '.....'],
114
+ '★': ['..#..', '..#..', '#####', '.###.', '.#.#.', '#...#', '.....'],
115
+ '☆': ['..#..', '..#..', '##.##', '.#.#.', '.#.#.', '#...#', '.....'],
116
+ '▲': ['.....', '..#..', '..#..', '.###.', '.###.', '#####', '.....'],
117
+ '▼': ['.....', '#####', '.###.', '.###.', '..#..', '..#..', '.....'],
118
+ '△': ['.....', '..#..', '..#..', '.#.#.', '.#.#.', '#####', '.....'],
119
+ '▽': ['.....', '#####', '.#.#.', '.#.#.', '..#..', '..#..', '.....'],
120
+ '▶': ['.#...', '.##..', '.###.', '.####', '.###.', '.##..', '.#...'],
121
+ '◀': ['...#.', '..##.', '.###.', '####.', '.###.', '..##.', '...#.'],
122
+ '▸': ['.....', '.#...', '.##..', '.###.', '.##..', '.#...', '.....'],
123
+ '◂': ['.....', '...#.', '..##.', '.###.', '..##.', '...#.', '.....'],
124
+ '✦': ['..#..', '..#..', '.###.', '#####', '.###.', '..#..', '..#..'],
125
+ '✧': ['..#..', '..#..', '.#.#.', '##.##', '.#.#.', '..#..', '..#..'],
126
+ '⚠': ['..#..', '.#.#.', '.#.#.', '#.#.#', '#...#', '#.#.#', '#####'],
127
+ '…': ['.....', '.....', '.....', '.....', '.....', '.....', '#.#.#'],
128
+ '→': ['.....', '..#..', '...#.', '#####', '...#.', '..#..', '.....'],
129
+ '←': ['.....', '..#..', '.#...', '#####', '.#...', '..#..', '.....'],
130
+ '↑': ['..#..', '.###.', '#.#.#', '..#..', '..#..', '..#..', '.....'],
131
+ '↓': ['.....', '..#..', '..#..', '..#..', '#.#.#', '.###.', '..#..'],
132
+ '↗': ['.....', '..###', '...##', '..#.#', '.#...', '#....', '.....'],
133
+ '↘': ['.....', '#....', '.#...', '..#.#', '...##', '..###', '.....'],
134
+ '↳': ['#....', '#....', '#..#.', '#...#', '#####', '....#', '...#.'],
135
+ '↪': ['.....', '.###.', '#...#', '#..#.', '#.###', '....#', '.....'],
136
+ '⎿': ['#....', '#....', '#....', '#....', '#####', '.....', '.....'],
137
+ '✔': ['.....', '....#', '...##', '#.##.', '###..', '.#...', '.....'],
138
+ '✖': ['.....', '##.##', '.###.', '..#..', '.###.', '##.##', '.....'],
139
+ '⚡': ['...##', '..##.', '.##..', '#####', '..##.', '.##..', '##...'],
140
+ '⇄': ['...#.', '#####', '...#.', '.#...', '#####', '.#...', '.....'],
141
+ '⏎': ['....#', '....#', '..#.#', '.####', '..#..', '.....', '.....'],
142
+ '✓': ['.....', '....#', '...#.', '#.#..', '.#...', '.....', '.....'],
143
+ '✗': ['.....', '#...#', '.#.#.', '..#..', '.#.#.', '#...#', '.....'],
144
+ '✕': ['.....', '#...#', '.#.#.', '..#..', '.#.#.', '#...#', '.....'],
145
+ '×': ['.....', '.....', '#...#', '.#.#.', '..#..', '.#.#.', '#...#'],
146
+ '—': ['.....', '.....', '.....', '#####', '.....', '.....', '.....'],
147
+ '–': ['.....', '.....', '.....', '.####', '.....', '.....', '.....'],
148
+ '≥': ['.#...', '..#..', '...#.', '..#..', '.#...', '.....', '#####'],
149
+ '≤': ['...#.', '..#..', '.#...', '..#..', '...#.', '.....', '#####'],
150
+ '≈': ['.....', '.#...', '#.#.#', '...#.', '.#...', '#.#.#', '...#.'],
151
+ '±': ['..#..', '..#..', '#####', '..#..', '..#..', '.....', '#####'],
152
+ '°': ['.##..', '#..#.', '.##..'],
153
+ '€': ['..###', '.#...', '####.', '.#...', '####.', '.#...', '..###'],
154
+ '£': ['..##.', '.#..#', '.#...', '###..', '.#...', '.#..#', '#.##.'],
155
+ 'ᵖ': ['###..', '#.#..', '###..', '#....'],
156
+ '‹': ['.....', '...#.', '..#..', '.#...', '..#..', '...#.', '.....'],
157
+ '›': ['.....', '.#...', '..#..', '...#.', '..#..', '.#...', '.....'],
158
+ '«': ['.....', '..#.#', '.#.#.', '#.#..', '.#.#.', '..#.#', '.....'],
159
+ '»': ['.....', '#.#..', '.#.#.', '..#.#', '.#.#.', '#.#..', '.....'],
160
+ '‘': ['..#..', '.#...', '.#...'],
161
+ '’': ['..#..', '..#..', '.#...'],
162
+ '“': ['.#.#.', '#.#..', '#.#..'],
163
+ '”': ['.#.#.', '.#.#.', '#.#..'],
164
+ };
165
+ /** Glyph width and height in font pixels. */
166
+ export const FONT_W = 5;
167
+ export const FONT_H = 9;
168
+ // Small 3×5 digits for subscripts (₀-₉: the price formatter's zero-count, e.g. $0.0₅3105) and superscripts (⁰-⁹).
169
+ // A subscript must never render as a full-size digit: that would turn 0.0₅31 into 0.0531.
170
+ const SMALL = [
171
+ ['###', '#.#', '#.#', '#.#', '###'], ['.#.', '##.', '.#.', '.#.', '###'], ['###', '..#', '###', '#..', '###'],
172
+ ['###', '..#', '.##', '..#', '###'], ['#.#', '#.#', '###', '..#', '..#'], ['###', '#..', '###', '..#', '###'],
173
+ ['###', '#..', '###', '#.#', '###'], ['###', '..#', '.#.', '.#.', '.#.'], ['###', '#.#', '###', '#.#', '###'],
174
+ ['###', '#.#', '###', '..#', '###'],
175
+ ];
176
+ const SUB = '₀₁₂₃₄₅₆₇₈₉', SUP = '⁰¹²³⁴⁵⁶⁷⁸⁹';
177
+ for (let d = 0; d < 10; d++) {
178
+ const rows = SMALL[d].map((r) => `.${r}.`);
179
+ G[SUB[d]] = ['.....', '.....', '.....', '.....', ...rows];
180
+ G[SUP[d]] = rows;
181
+ }
182
+ const BITS = new Map();
183
+ for (const [ch, rows] of Object.entries(G)) {
184
+ const b = new Uint8Array(FONT_W * FONT_H);
185
+ rows.forEach((r, y) => { for (let x = 0; x < FONT_W; x++)
186
+ if (r[x] === '#')
187
+ b[y * FONT_W + x] = 1; });
188
+ BITS.set(ch, b);
189
+ }
190
+ /** The 5×9 bitmap for a character (1 = ink), or null when the font has no glyph for it. */
191
+ export function glyphBits(ch) {
192
+ return BITS.get(ch) ?? null;
193
+ }
194
+ /** Every character with a bitmap glyph (tests check the printable ASCII range is complete). */
195
+ export function fontChars() { return [...BITS.keys()]; }