dexterm-cli 0.0.0-stage → 0.1.1

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 (349) 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 +379 -0
  4. package/dist/packages/agents/src/executor.js +177 -0
  5. package/dist/packages/agents/src/gate.js +176 -0
  6. package/dist/packages/agents/src/identity.js +179 -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 +114 -0
  12. package/dist/packages/agents/src/tools.js +69 -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 +67 -0
  18. package/dist/packages/cli/assets/claude/plugin/skills/rug-check/SKILL.md +64 -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 +303 -0
  26. package/dist/packages/cli/src/agent-roster.js +26 -0
  27. package/dist/packages/cli/src/analyst/backend.js +526 -0
  28. package/dist/packages/cli/src/analyst/results.js +38 -0
  29. package/dist/packages/cli/src/analyst/session.js +319 -0
  30. package/dist/packages/cli/src/audit.js +51 -0
  31. package/dist/packages/cli/src/backtest-cmd.js +149 -0
  32. package/dist/packages/cli/src/boot-state.js +62 -0
  33. package/dist/packages/cli/src/custom.js +261 -0
  34. package/dist/packages/cli/src/display.js +191 -0
  35. package/dist/packages/cli/src/doctor.js +361 -0
  36. package/dist/packages/cli/src/feed.js +634 -0
  37. package/dist/packages/cli/src/fixtures.js +275 -0
  38. package/dist/packages/cli/src/follow-cmd.js +221 -0
  39. package/dist/packages/cli/src/images-config.js +59 -0
  40. package/dist/packages/cli/src/index.js +31 -0
  41. package/dist/packages/cli/src/kb-skill-cmd.js +240 -0
  42. package/dist/packages/cli/src/larp-record.js +21 -0
  43. package/dist/packages/cli/src/live/copy.js +80 -0
  44. package/dist/packages/cli/src/live/flow.js +233 -0
  45. package/dist/packages/cli/src/live/index.js +509 -0
  46. package/dist/packages/cli/src/live/intel.js +227 -0
  47. package/dist/packages/cli/src/live/newpairs.js +334 -0
  48. package/dist/packages/cli/src/live/screens/newpairs-live.js +219 -0
  49. package/dist/packages/cli/src/live/screens/token-live.js +459 -0
  50. package/dist/packages/cli/src/live/screens/watchlist-live.js +149 -0
  51. package/dist/packages/cli/src/live/token.js +585 -0
  52. package/dist/packages/cli/src/live/trade.js +929 -0
  53. package/dist/packages/cli/src/live/watchlist.js +178 -0
  54. package/dist/packages/cli/src/main.js +5583 -0
  55. package/dist/packages/cli/src/narrative-cmd.js +76 -0
  56. package/dist/packages/cli/src/pack-cmd.js +323 -0
  57. package/dist/packages/cli/src/plan-cmd.js +278 -0
  58. package/dist/packages/cli/src/popup.js +810 -0
  59. package/dist/packages/cli/src/rules-cmd.js +131 -0
  60. package/dist/packages/cli/src/rules.js +339 -0
  61. package/dist/packages/cli/src/scan/command.js +57 -0
  62. package/dist/packages/cli/src/scan/engine.js +419 -0
  63. package/dist/packages/cli/src/scan/observe.js +64 -0
  64. package/dist/packages/cli/src/scan/ui.js +98 -0
  65. package/dist/packages/cli/src/screener/filter.js +241 -0
  66. package/dist/packages/cli/src/screener/presets.js +80 -0
  67. package/dist/packages/cli/src/screener/rows.js +146 -0
  68. package/dist/packages/cli/src/screener/rug.js +50 -0
  69. package/dist/packages/cli/src/screener/sort.js +52 -0
  70. package/dist/packages/cli/src/screener/view.js +183 -0
  71. package/dist/packages/cli/src/screens/analyst-session.js +343 -0
  72. package/dist/packages/cli/src/screens/analyst.js +326 -0
  73. package/dist/packages/cli/src/screens/boot.js +74 -0
  74. package/dist/packages/cli/src/screens/bubbles.js +255 -0
  75. package/dist/packages/cli/src/screens/coin.js +33 -0
  76. package/dist/packages/cli/src/screens/follows.js +201 -0
  77. package/dist/packages/cli/src/screens/kol.js +90 -0
  78. package/dist/packages/cli/src/screens/narrative.js +90 -0
  79. package/dist/packages/cli/src/screens/newpairs.js +150 -0
  80. package/dist/packages/cli/src/screens/overlay.js +257 -0
  81. package/dist/packages/cli/src/screens/plans.js +126 -0
  82. package/dist/packages/cli/src/screens/positions.js +176 -0
  83. package/dist/packages/cli/src/screens/rules.js +170 -0
  84. package/dist/packages/cli/src/screens/screener.js +459 -0
  85. package/dist/packages/cli/src/screens/social-panel.js +107 -0
  86. package/dist/packages/cli/src/screens/ticket.js +342 -0
  87. package/dist/packages/cli/src/screens/token.js +312 -0
  88. package/dist/packages/cli/src/screens/trending.js +181 -0
  89. package/dist/packages/cli/src/screens/watchlist.js +104 -0
  90. package/dist/packages/cli/src/social/demo.js +96 -0
  91. package/dist/packages/cli/src/social/view.js +250 -0
  92. package/dist/packages/cli/src/state.js +463 -0
  93. package/dist/packages/cli/src/theme-cmd.js +126 -0
  94. package/dist/packages/cli/src/trade.js +319 -0
  95. package/dist/packages/cli/src/voice-hud.js +42 -0
  96. package/dist/packages/cli/src/wallet-cmd.js +440 -0
  97. package/dist/packages/cli/src/wallet-command.js +31 -0
  98. package/dist/packages/cli/src/widgets.js +208 -0
  99. package/dist/packages/cli/src/workspace-cmd.js +68 -0
  100. package/dist/packages/cli/src/x-cmd.js +154 -0
  101. package/dist/packages/custom/src/config.js +213 -0
  102. package/dist/packages/custom/src/index.js +10 -0
  103. package/dist/packages/custom/src/keymap.js +107 -0
  104. package/dist/packages/custom/src/layout.js +235 -0
  105. package/dist/packages/custom/src/packs.js +633 -0
  106. package/dist/packages/custom/src/rules.js +704 -0
  107. package/dist/packages/custom/src/schema.js +515 -0
  108. package/dist/packages/custom/src/themes.js +176 -0
  109. package/dist/packages/custom/src/widget-html.js +222 -0
  110. package/dist/packages/custom/src/workspace.js +141 -0
  111. package/dist/packages/data/src/analyst-actions.js +133 -0
  112. package/dist/packages/data/src/budget.js +88 -0
  113. package/dist/packages/data/src/cache.js +142 -0
  114. package/dist/packages/data/src/candles.js +168 -0
  115. package/dist/packages/data/src/clock.js +64 -0
  116. package/dist/packages/data/src/credits.js +137 -0
  117. package/dist/packages/data/src/detail.js +97 -0
  118. package/dist/packages/data/src/fast-lane.js +321 -0
  119. package/dist/packages/data/src/fixtures.js +135 -0
  120. package/dist/packages/data/src/health.js +245 -0
  121. package/dist/packages/data/src/http.js +277 -0
  122. package/dist/packages/data/src/images/cache.js +141 -0
  123. package/dist/packages/data/src/images/decode-worker.js +28 -0
  124. package/dist/packages/data/src/images/decode.js +81 -0
  125. package/dist/packages/data/src/images/fetch.js +162 -0
  126. package/dist/packages/data/src/images/gif.js +214 -0
  127. package/dist/packages/data/src/images/index.js +10 -0
  128. package/dist/packages/data/src/images/jpeg.js +544 -0
  129. package/dist/packages/data/src/images/png.js +310 -0
  130. package/dist/packages/data/src/images/service.js +334 -0
  131. package/dist/packages/data/src/images/types.js +27 -0
  132. package/dist/packages/data/src/index.js +208 -0
  133. package/dist/packages/data/src/intel/helius-history.js +59 -0
  134. package/dist/packages/data/src/intel/holder-class.js +125 -0
  135. package/dist/packages/data/src/intel/rules.js +421 -0
  136. package/dist/packages/data/src/intel/scan.js +170 -0
  137. package/dist/packages/data/src/larp/evidence.js +288 -0
  138. package/dist/packages/data/src/larp/links.js +137 -0
  139. package/dist/packages/data/src/larp/robots.js +90 -0
  140. package/dist/packages/data/src/larp/safe-fetch.js +389 -0
  141. package/dist/packages/data/src/limiter.js +341 -0
  142. package/dist/packages/data/src/model.js +12 -0
  143. package/dist/packages/data/src/paper.js +331 -0
  144. package/dist/packages/data/src/rpc-config.js +126 -0
  145. package/dist/packages/data/src/rpc-pool.js +166 -0
  146. package/dist/packages/data/src/social/chain.js +83 -0
  147. package/dist/packages/data/src/social/dedupe.js +205 -0
  148. package/dist/packages/data/src/social/feed.js +462 -0
  149. package/dist/packages/data/src/social/firewall.js +110 -0
  150. package/dist/packages/data/src/social/index.js +11 -0
  151. package/dist/packages/data/src/social/kol.js +269 -0
  152. package/dist/packages/data/src/social/model.js +11 -0
  153. package/dist/packages/data/src/social/rank.js +184 -0
  154. package/dist/packages/data/src/social/rss.js +113 -0
  155. package/dist/packages/data/src/social/summary.js +104 -0
  156. package/dist/packages/data/src/social/venues.js +186 -0
  157. package/dist/packages/data/src/sources/dexscreener.js +170 -0
  158. package/dist/packages/data/src/sources/geckoterminal.js +133 -0
  159. package/dist/packages/data/src/sources/goplus.js +161 -0
  160. package/dist/packages/data/src/sources/jupiter-swap.js +236 -0
  161. package/dist/packages/data/src/sources/jupiter.js +198 -0
  162. package/dist/packages/data/src/sources/pda.js +113 -0
  163. package/dist/packages/data/src/sources/pump-curve.js +58 -0
  164. package/dist/packages/data/src/sources/pumpportal.js +247 -0
  165. package/dist/packages/data/src/sources/rugcheck.js +71 -0
  166. package/dist/packages/data/src/sources/solana-rpc.js +299 -0
  167. package/dist/packages/data/src/sources/solana-ws.js +287 -0
  168. package/dist/packages/data/src/store.js +289 -0
  169. package/dist/packages/data/src/trade/bridge.js +464 -0
  170. package/dist/packages/data/src/trade/caps.js +323 -0
  171. package/dist/packages/data/src/trade/copy/auto.js +385 -0
  172. package/dist/packages/data/src/trade/copy/follows.js +103 -0
  173. package/dist/packages/data/src/trade/copy/index.js +9 -0
  174. package/dist/packages/data/src/trade/copy/mirror.js +91 -0
  175. package/dist/packages/data/src/trade/copy/stats.js +120 -0
  176. package/dist/packages/data/src/trade/copy/tracker.js +158 -0
  177. package/dist/packages/data/src/trade/copy/trades.js +87 -0
  178. package/dist/packages/data/src/trade/copy/types.js +6 -0
  179. package/dist/packages/data/src/trade/executor.js +933 -0
  180. package/dist/packages/data/src/trade/kill-switch.js +47 -0
  181. package/dist/packages/data/src/trade/link-store.js +52 -0
  182. package/dist/packages/data/src/trade/plans/confirm.js +157 -0
  183. package/dist/packages/data/src/trade/plans/engine.js +784 -0
  184. package/dist/packages/data/src/trade/plans/executor-live.js +220 -0
  185. package/dist/packages/data/src/trade/plans/executor-paper.js +44 -0
  186. package/dist/packages/data/src/trade/plans/executor.js +11 -0
  187. package/dist/packages/data/src/trade/plans/index.js +12 -0
  188. package/dist/packages/data/src/trade/plans/journal.js +77 -0
  189. package/dist/packages/data/src/trade/plans/mandate.js +129 -0
  190. package/dist/packages/data/src/trade/plans/plan.js +179 -0
  191. package/dist/packages/data/src/trade/plans/service.js +168 -0
  192. package/dist/packages/data/src/trade/plans/types.js +6 -0
  193. package/dist/packages/data/src/trade/rpc-exec.js +229 -0
  194. package/dist/packages/data/src/trade/signer/client.js +197 -0
  195. package/dist/packages/data/src/trade/signer/fast-wallet.js +154 -0
  196. package/dist/packages/data/src/trade/signer/host.js +97 -0
  197. package/dist/packages/data/src/trade/signer/main.js +121 -0
  198. package/dist/packages/data/src/trade/signer/probe-builder.js +85 -0
  199. package/dist/packages/data/src/trade/signer/protocol.js +92 -0
  200. package/dist/packages/data/src/trade/signer/service.js +400 -0
  201. package/dist/packages/data/src/trade/signer/sol-usd-feed.js +98 -0
  202. package/dist/packages/data/src/trade/sol-usd.js +86 -0
  203. package/dist/packages/data/src/trade/swap-build.js +108 -0
  204. package/dist/packages/data/src/trade/token-delta.js +201 -0
  205. package/dist/packages/data/src/trade/tx-decode.js +632 -0
  206. package/dist/packages/data/src/util.js +24 -0
  207. package/dist/packages/data/src/watchlist.js +176 -0
  208. package/dist/packages/data/src/x/api.js +256 -0
  209. package/dist/packages/data/src/x/budget.js +66 -0
  210. package/dist/packages/data/src/x/config.js +49 -0
  211. package/dist/packages/data/src/x/index.js +10 -0
  212. package/dist/packages/data/src/x/mock-server.js +217 -0
  213. package/dist/packages/data/src/x/oauth.js +242 -0
  214. package/dist/packages/data/src/x/pkce.js +21 -0
  215. package/dist/packages/data/src/x/source.js +285 -0
  216. package/dist/packages/data/src/x/token-store.js +134 -0
  217. package/dist/packages/data/src/x/transport.js +71 -0
  218. package/dist/packages/data/vendor/solana-web3/LICENSE +20 -0
  219. package/dist/packages/data/vendor/solana-web3/NOTICE.md +13 -0
  220. package/dist/packages/data/vendor/solana-web3/index.iife.min.js +20 -0
  221. package/dist/packages/mcp/assets/cases.json +1194 -0
  222. package/dist/packages/mcp/assets/kb/entries/cabal-and-coordinated-launches.md +28 -0
  223. package/dist/packages/mcp/assets/kb/entries/common-rug-patterns.md +40 -0
  224. package/dist/packages/mcp/assets/kb/entries/dbc-mechanics.md +30 -0
  225. package/dist/packages/mcp/assets/kb/entries/dev-wallet-behaviour.md +33 -0
  226. package/dist/packages/mcp/assets/kb/entries/glossary.md +35 -0
  227. package/dist/packages/mcp/assets/kb/entries/holder-concentration.md +30 -0
  228. package/dist/packages/mcp/assets/kb/entries/jito-bundles.md +29 -0
  229. package/dist/packages/mcp/assets/kb/entries/launchlab-curve.md +31 -0
  230. package/dist/packages/mcp/assets/kb/entries/lp-burn-vs-lock.md +31 -0
  231. package/dist/packages/mcp/assets/kb/entries/metadata-and-copycats.md +29 -0
  232. package/dist/packages/mcp/assets/kb/entries/mint-freeze-authority.md +31 -0
  233. package/dist/packages/mcp/assets/kb/entries/narrative-lifecycle.md +32 -0
  234. package/dist/packages/mcp/assets/kb/entries/pump-bonding-curve.md +33 -0
  235. package/dist/packages/mcp/assets/kb/entries/pumpswap-migration.md +29 -0
  236. package/dist/packages/mcp/assets/kb/entries/sniping-and-snipers.md +29 -0
  237. package/dist/packages/mcp/assets/kb/entries/token2022-extensions-risk.md +32 -0
  238. package/dist/packages/mcp/assets/kb/entries/wash-trading-fake-volume.md +33 -0
  239. package/dist/packages/mcp/assets/skills/rug-check.md +52 -0
  240. package/dist/packages/mcp/assets/skills/token-dossier.md +57 -0
  241. package/dist/packages/mcp/assets/skills/trench-scan.md +40 -0
  242. package/dist/packages/mcp/bin/dexterm-mcp.mjs +16 -0
  243. package/dist/packages/mcp/src/dossier.js +78 -0
  244. package/dist/packages/mcp/src/firewall.js +21 -0
  245. package/dist/packages/mcp/src/index.js +22 -0
  246. package/dist/packages/mcp/src/server.js +849 -0
  247. package/dist/packages/mcp/src/user-content.js +434 -0
  248. package/dist/packages/packs/src/backtest.js +183 -0
  249. package/dist/packages/packs/src/digest.js +95 -0
  250. package/dist/packages/packs/src/firewall.js +57 -0
  251. package/dist/packages/packs/src/index.js +19 -0
  252. package/dist/packages/packs/src/larp-eval.js +100 -0
  253. package/dist/packages/packs/src/narrative.js +309 -0
  254. package/dist/packages/packs/src/reason.js +135 -0
  255. package/dist/packages/packs/src/rug-model.js +137 -0
  256. package/dist/packages/packs/src/schema.js +54 -0
  257. package/dist/packages/packs/src/token-dossier.js +174 -0
  258. package/dist/packages/packs/src/verdicts.js +17 -0
  259. package/dist/packages/packs/src/wallet-dossier.js +105 -0
  260. package/dist/packages/popup/src/config.js +71 -0
  261. package/dist/packages/popup/src/dock.js +271 -0
  262. package/dist/packages/popup/src/host.js +210 -0
  263. package/dist/packages/popup/src/index.js +12 -0
  264. package/dist/packages/popup/src/loopback.js +53 -0
  265. package/dist/packages/popup/src/open.js +183 -0
  266. package/dist/packages/popup/src/pages/bubbles-lib.js +160 -0
  267. package/dist/packages/popup/src/pages/bubbles.css +23 -0
  268. package/dist/packages/popup/src/pages/bubbles.html +36 -0
  269. package/dist/packages/popup/src/pages/bubbles.js +214 -0
  270. package/dist/packages/popup/src/pages/chart-lib.js +262 -0
  271. package/dist/packages/popup/src/pages/chart.css +50 -0
  272. package/dist/packages/popup/src/pages/chart.html +56 -0
  273. package/dist/packages/popup/src/pages/chart.js +554 -0
  274. package/dist/packages/popup/src/pages/common.css +34 -0
  275. package/dist/packages/popup/src/pages/common.js +187 -0
  276. package/dist/packages/popup/src/pages/feeds.html +20 -0
  277. package/dist/packages/popup/src/pages/feeds.js +77 -0
  278. package/dist/packages/popup/src/pages/narrative.html +20 -0
  279. package/dist/packages/popup/src/pages/narrative.js +61 -0
  280. package/dist/packages/popup/src/pages/plans.css +30 -0
  281. package/dist/packages/popup/src/pages/plans.html +26 -0
  282. package/dist/packages/popup/src/pages/plans.js +82 -0
  283. package/dist/packages/popup/src/pages/roster.css +41 -0
  284. package/dist/packages/popup/src/pages/roster.html +25 -0
  285. package/dist/packages/popup/src/pages/roster.js +75 -0
  286. package/dist/packages/popup/src/pages/token.html +20 -0
  287. package/dist/packages/popup/src/pages/token.js +112 -0
  288. package/dist/packages/popup/src/pages/widget-sdk.js +224 -0
  289. package/dist/packages/popup/src/pages/widget.css +5 -0
  290. package/dist/packages/popup/src/pages/widget.html +21 -0
  291. package/dist/packages/popup/src/pages/widget.js +85 -0
  292. package/dist/packages/popup/src/protocol.js +31 -0
  293. package/dist/packages/popup/src/selftest.js +156 -0
  294. package/dist/packages/popup/src/server.js +582 -0
  295. package/dist/packages/popup/src/sinkproxy.js +167 -0
  296. package/dist/packages/popup/src/widget-html.js +231 -0
  297. package/dist/packages/popup/vendor/lightweight-charts/LICENSE +201 -0
  298. package/dist/packages/popup/vendor/lightweight-charts/NOTICE +2 -0
  299. package/dist/packages/popup/vendor/lightweight-charts/README.md +30 -0
  300. package/dist/packages/popup/vendor/lightweight-charts/VERSION +1 -0
  301. package/dist/packages/popup/vendor/lightweight-charts/lightweight-charts.standalone.production.js +7 -0
  302. package/dist/packages/recorder/bin/dexterm-recorder.mjs +11 -0
  303. package/dist/packages/recorder/src/cli.js +113 -0
  304. package/dist/packages/recorder/src/export.js +71 -0
  305. package/dist/packages/recorder/src/index.js +20 -0
  306. package/dist/packages/recorder/src/labels.js +151 -0
  307. package/dist/packages/recorder/src/open.js +29 -0
  308. package/dist/packages/recorder/src/recorder.js +553 -0
  309. package/dist/packages/recorder/src/schedule.js +43 -0
  310. package/dist/packages/recorder/src/schema.js +135 -0
  311. package/dist/packages/recorder/src/snapshot.js +191 -0
  312. package/dist/packages/recorder/src/sweep.js +52 -0
  313. package/dist/packages/recorder/src/verdicts.js +52 -0
  314. package/dist/packages/tui/src/bubbles.js +415 -0
  315. package/dist/packages/tui/src/canvas.js +370 -0
  316. package/dist/packages/tui/src/chrome.js +85 -0
  317. package/dist/packages/tui/src/color.js +133 -0
  318. package/dist/packages/tui/src/flush.js +62 -0
  319. package/dist/packages/tui/src/fmt.js +188 -0
  320. package/dist/packages/tui/src/fx-trade.js +278 -0
  321. package/dist/packages/tui/src/fx.js +527 -0
  322. package/dist/packages/tui/src/images/blocks.js +141 -0
  323. package/dist/packages/tui/src/images/coin.js +22 -0
  324. package/dist/packages/tui/src/images/detect.js +140 -0
  325. package/dist/packages/tui/src/images/index.js +7 -0
  326. package/dist/packages/tui/src/images/layer.js +146 -0
  327. package/dist/packages/tui/src/images/pixels.js +157 -0
  328. package/dist/packages/tui/src/images/protocols.js +87 -0
  329. package/dist/packages/tui/src/index.js +15 -0
  330. package/dist/packages/tui/src/keymap.js +355 -0
  331. package/dist/packages/tui/src/layout.js +11 -0
  332. package/dist/packages/tui/src/sound.js +177 -0
  333. package/dist/packages/tui/src/theme.js +182 -0
  334. package/dist/packages/tui/src/widgets.js +598 -0
  335. package/dist/packages/voice/src/controller.js +395 -0
  336. package/dist/packages/voice/src/doctor.js +63 -0
  337. package/dist/packages/voice/src/engines.js +44 -0
  338. package/dist/packages/voice/src/index.js +16 -0
  339. package/dist/packages/voice/src/router.js +502 -0
  340. package/dist/packages/voice/src/stt/apple-helper.swift.js +103 -0
  341. package/dist/packages/voice/src/stt/apple.js +179 -0
  342. package/dist/packages/voice/src/stt/fake.js +34 -0
  343. package/dist/packages/voice/src/stt/whisper.js +102 -0
  344. package/dist/packages/voice/src/summary.js +44 -0
  345. package/dist/packages/voice/src/tts/fake.js +30 -0
  346. package/dist/packages/voice/src/tts/say.js +96 -0
  347. package/dist/packages/voice/src/types.js +3 -0
  348. package/package.json +42 -4
  349. package/README.md +0 -3
@@ -0,0 +1,361 @@
1
+ // dexterm doctor (task-1305): a pre-flight the user runs before anything else. It answers one
2
+ // question — "will dexterm work on this machine, and if not, exactly what do I fix?" — as a plain
3
+ // pass/warn/fail list with a copy-pasteable fix on every line that is not a pass.
4
+ //
5
+ // Everything that touches the outside world (the claude binary, the network) is injected so the
6
+ // checks stay deterministic in tests and never hang: each probe carries its own timeout and any
7
+ // failure is turned into a `fail`/`warn` line, never an exception. The doctor NEVER prints the
8
+ // Helius key or any URL that could carry it — it reports the provider name only.
9
+ import { homedir } from 'node:os';
10
+ import { join, dirname } from 'node:path';
11
+ import { mkdtempSync, writeFileSync, rmSync, mkdirSync, existsSync } from 'node:fs';
12
+ import { spawnSync } from 'node:child_process';
13
+ import { shellBinaryPath } from '../../popup/src/index.js';
14
+ import { detectColorDepth, protocolFromEnv } from '../../tui/src/index.js';
15
+ import { resolveRpcUrl, defaultDbPath } from '../../data/src/index.js';
16
+ import { XTokenStore } from '../../data/src/index.js';
17
+ import { SayTts, voiceDoctor, WHISPER_MODEL } from '../../voice/src/index.js';
18
+ import { kbStore, skillStore } from "./kb-skill-cmd.js";
19
+ /** The minimum Node that runs dexterm (type-stripping of the .ts entry needs 22.18). */
20
+ export const MIN_NODE = [22, 18, 0];
21
+ /** Cheap PATH lookup (no spawn) for the voice probe. */
22
+ function onPath(bin) {
23
+ for (const p of (process.env.PATH ?? '').split(':'))
24
+ if (p && existsSync(join(p, bin)))
25
+ return true;
26
+ return false;
27
+ }
28
+ /**
29
+ * Default voice probe. Deliberately cheap and non-blocking: it never compiles the Swift helper (that
30
+ * is left to the first real `v` press), so resolvedStt is inferred from swiftc / whisper presence.
31
+ */
32
+ export async function defaultVoiceProbe(platform = process.platform) {
33
+ const say = new SayTts();
34
+ const sayAvailable = platform === 'darwin' ? await say.available() : false;
35
+ const voices = sayAvailable ? await say.listVoices() : [];
36
+ const swiftcPresent = platform === 'darwin' && onPath('swiftc');
37
+ const whisperBinPresent = onPath('whisper-cli');
38
+ const whisperModelPresent = existsSync(WHISPER_MODEL);
39
+ const micToolPresent = onPath('sox') || onPath('rec') || onPath('ffmpeg');
40
+ const resolvedStt = swiftcPresent ? 'apple' : (whisperBinPresent && whisperModelPresent && micToolPresent) ? 'whisper' : null;
41
+ return { platform, sayAvailable, voiceCount: voices.length, swiftcPresent, whisperBinPresent, whisperModelPresent, micToolPresent, resolvedStt };
42
+ }
43
+ /** The keyless data sources the live app depends on, with a cheap reachability URL for each. */
44
+ export const DATA_SOURCES = [
45
+ { name: 'DexScreener', url: 'https://api.dexscreener.com/latest/dex/search?q=SOL' },
46
+ { name: 'Jupiter', url: 'https://lite-api.jup.ag/price/v3?ids=So11111111111111111111111111111111111111112' },
47
+ { name: 'GeckoTerminal', url: 'https://api.geckoterminal.com/api/v2/networks' },
48
+ { name: 'RugCheck', url: 'https://api.rugcheck.xyz/v1/stats/new_tokens' },
49
+ { name: 'GoPlus', url: 'https://api.gopluslabs.io/api/v1/supported_chains' },
50
+ { name: 'Solana RPC', url: 'https://api.mainnet-beta.solana.com' },
51
+ // PumpPortal is a websocket; a plain GET to the host proves the network path (new pairs is a soft dep).
52
+ { name: 'PumpPortal', url: 'https://pumpportal.fun/', soft: true },
53
+ ];
54
+ function parseVersion(v) {
55
+ const m = /(\d+)\.(\d+)\.(\d+)/.exec(v);
56
+ if (!m)
57
+ return [0, 0, 0];
58
+ return [Number(m[1]), Number(m[2]), Number(m[3])];
59
+ }
60
+ /** Compare two semver triples: -1 / 0 / 1. */
61
+ export function cmpVersion(a, b) {
62
+ for (let i = 0; i < 3; i++) {
63
+ const d = (a[i] ?? 0) - (b[i] ?? 0);
64
+ if (d)
65
+ return d < 0 ? -1 : 1;
66
+ }
67
+ return 0;
68
+ }
69
+ /** Default live probe: a GET with a hard timeout. Any HTTP answer = reachable; only transport errors fail. */
70
+ export async function livingProbe(url, timeoutMs = 4000) {
71
+ const ctl = new AbortController();
72
+ const timer = setTimeout(() => ctl.abort(), timeoutMs);
73
+ const t0 = Date.now();
74
+ try {
75
+ const res = await fetch(url, { method: 'GET', signal: ctl.signal, headers: { 'user-agent': 'dexterm-doctor' } });
76
+ // Drain a little so sockets close cleanly; we do not care about the body.
77
+ try {
78
+ await res.arrayBuffer();
79
+ }
80
+ catch { /* ignore */ }
81
+ return { reachable: true, status: res.status, ms: Date.now() - t0 };
82
+ }
83
+ catch (e) {
84
+ const err = e.name === 'AbortError' ? `timeout after ${timeoutMs}ms` : e.message;
85
+ return { reachable: false, error: err, ms: Date.now() - t0 };
86
+ }
87
+ finally {
88
+ clearTimeout(timer);
89
+ }
90
+ }
91
+ /** Default claude probe: spawn `claude --version` with a timeout. Presence only (login is not asserted here). */
92
+ export async function claudeProbe(timeoutMs = 4000) {
93
+ const { execFile } = await import('node:child_process');
94
+ return new Promise((resolve) => {
95
+ let done = false;
96
+ const finish = (r) => { if (!done) {
97
+ done = true;
98
+ resolve(r);
99
+ } };
100
+ try {
101
+ const child = execFile('claude', ['--version'], { timeout: timeoutMs }, (err) => {
102
+ if (err && err.code === 'ENOENT')
103
+ finish('missing');
104
+ else if (err)
105
+ finish('present'); // on PATH but the probe errored/timed out: do not block on it
106
+ else
107
+ finish('present');
108
+ });
109
+ child.on('error', () => finish('missing'));
110
+ }
111
+ catch {
112
+ finish('missing');
113
+ }
114
+ });
115
+ }
116
+ /** Default writable check: create the directory, write and remove a temp file. Returns an error message or null. */
117
+ export function writableProbe(dir) {
118
+ try {
119
+ mkdirSync(dir, { recursive: true });
120
+ const tmp = mkdtempSync(join(dir, '.dexterm-doctor-'));
121
+ const f = join(tmp, 'probe');
122
+ writeFileSync(f, 'ok');
123
+ rmSync(tmp, { recursive: true, force: true });
124
+ return null;
125
+ }
126
+ catch (e) {
127
+ return e.message;
128
+ }
129
+ }
130
+ export function defaultDeps(env = process.env, isTTY = process.stdout.isTTY === true) {
131
+ return {
132
+ env,
133
+ isTTY,
134
+ nodeVersion: process.versions.node,
135
+ platform: process.platform,
136
+ claude: () => claudeProbe(),
137
+ probe: (url) => livingProbe(url),
138
+ checkWritable: writableProbe,
139
+ offline: env.DEXTERM_OFFLINE === '1' || env.DEXTERM_OFFLINE === 'true',
140
+ popupShell: () => {
141
+ const path = shellBinaryPath(env);
142
+ const cargo = spawnSync('cargo', ['--version'], { stdio: 'ignore', timeout: 3000 }).status === 0;
143
+ return { path, built: existsSync(path), cargo };
144
+ },
145
+ voiceProbe: () => defaultVoiceProbe(process.platform),
146
+ content: () => ({ kb: kbStore(env).get(), skills: skillStore(env).get() }),
147
+ };
148
+ }
149
+ /** Run every check. Never throws; network and claude probes are the injected ones. */
150
+ export async function runDoctor(deps) {
151
+ const checks = [];
152
+ // 1. Node version
153
+ const node = parseVersion(deps.nodeVersion);
154
+ if (cmpVersion(node, MIN_NODE) >= 0) {
155
+ checks.push({ name: 'Node', status: 'pass', detail: `v${deps.nodeVersion} (need ${MIN_NODE.join('.')}+)` });
156
+ }
157
+ else {
158
+ checks.push({
159
+ name: 'Node', status: 'fail',
160
+ detail: `v${deps.nodeVersion} is too old (need ${MIN_NODE.join('.')}+ for the TypeScript entry)`,
161
+ fix: 'Install Node 22.18+ : `nvm install 22` (nvm) or `brew install node` (Homebrew), then re-run.',
162
+ });
163
+ }
164
+ // 2. Terminal colour
165
+ const depth = detectColorDepth(deps.env, deps.isTTY);
166
+ const term = deps.env.TERM_PROGRAM || deps.env.TERM || 'unknown';
167
+ if (!deps.isTTY) {
168
+ checks.push({
169
+ name: 'Terminal', status: 'warn',
170
+ detail: 'not a TTY (output is being piped); the interactive UI needs a real terminal',
171
+ fix: 'Run dexterm directly in a terminal window, not through a pipe or a non-interactive shell.',
172
+ });
173
+ }
174
+ else if (depth === 'truecolor') {
175
+ checks.push({ name: 'Terminal colour', status: 'pass', detail: `24-bit truecolor (${term})` });
176
+ }
177
+ else if (depth === '256') {
178
+ checks.push({
179
+ name: 'Terminal colour', status: 'warn',
180
+ detail: `256-colour only (${term}); dexterm runs but the neon look is flattened`,
181
+ fix: 'Use a truecolor terminal (iTerm2, WezTerm, Ghostty, Kitty, Alacritty, Windows Terminal) or set COLORTERM=truecolor.',
182
+ });
183
+ }
184
+ else {
185
+ checks.push({
186
+ name: 'Terminal colour', status: 'warn',
187
+ detail: `no colour (${term}${deps.env.NO_COLOR ? ', NO_COLOR set' : ''}); dexterm falls back to monochrome`,
188
+ fix: 'Unset NO_COLOR and use a colour terminal for the full look; dexterm still works without it.',
189
+ });
190
+ }
191
+ // 2b. Coin images (task-1326): the protocol this terminal gets, judged from the environment alone (the
192
+ // interactive run also asks the tty). Apple Terminal.app is the one known no-images terminal → warn + fix.
193
+ {
194
+ const p = protocolFromEnv(deps.env);
195
+ const label = p.protocol === 'kitty' ? 'real pixels (kitty graphics)' : p.protocol === 'iterm' ? 'real pixels (iTerm2 inline images)' : p.protocol === 'sixel' ? 'real pixels (sixel)' : 'half-block art';
196
+ if (p.protocol === 'blocks' && /apple terminal/i.test(p.reason)) {
197
+ checks.push({ name: 'Coin images', status: 'warn', detail: `${label}: ${p.reason}`, fix: 'For real coin pictures use Ghostty (`brew install --cask ghostty`) or iTerm2 (`brew install --cask iterm2`); the block-art fallback still shows every coin here.' });
198
+ }
199
+ else {
200
+ checks.push({ name: 'Coin images', status: 'pass', detail: `${label} (${p.reason})${p.protocol === 'blocks' ? '; --no-images turns them off' : ''}` });
201
+ }
202
+ }
203
+ // 3. Claude CLI (the analyst). Not required to browse; required for the `a` analyst.
204
+ const claude = await deps.claude();
205
+ if (claude === 'missing') {
206
+ checks.push({
207
+ name: 'Claude CLI', status: 'warn',
208
+ detail: 'not found on PATH; the analyst (a) is disabled, the rest of dexterm works',
209
+ fix: 'Install Claude Code (https://claude.com/claude-code) and run `claude` once to log in.',
210
+ });
211
+ }
212
+ else {
213
+ checks.push({
214
+ name: 'Claude CLI', status: 'pass',
215
+ detail: 'found on PATH (the analyst runs your local `claude`; log in once with `claude` if the analyst errors)',
216
+ });
217
+ }
218
+ // 4b. Login with X (optional, task-1357): the user's own X app + login unlock X posts in the SOCIAL panel / TRENDING.
219
+ {
220
+ const xs = new XTokenStore({ env: deps.env });
221
+ const meta = xs.meta();
222
+ const modes = xs.modes();
223
+ const clientId = xs.clientId(deps.env);
224
+ if (meta.loggedIn) {
225
+ const loose = (modes.tokens !== null && modes.tokens !== 0o600) || (modes.dir !== null && modes.dir !== 0o700);
226
+ checks.push({ name: 'Login with X', status: loose ? 'warn' : 'pass', detail: `logged in${meta.user ? ` as @${meta.user.username}` : ''} · scopes ${meta.scopes.join(' ') || '?'} · refresh ${meta.hasRefresh ? 'yes' : 'no'}${loose ? ' · token file permissions are looser than 0600' : ''}`, ...(loose ? { fix: `chmod 700 ${xs.dir} && chmod 600 ${xs.tokensPath}` } : {}) });
227
+ }
228
+ else if (clientId) {
229
+ checks.push({ name: 'Login with X', status: 'warn', detail: 'client id stored, not logged in — X posts stay off (keyless venues, news and on-chain rows still work)', fix: 'dexterm x login' });
230
+ }
231
+ else {
232
+ checks.push({ name: 'Login with X', status: 'pass', detail: 'not set up (optional) — X posts need your own X app: free Native App + `dexterm x set-client-id` + `dexterm x login`; see docs › Login with X' });
233
+ }
234
+ }
235
+ // 4. Helius key (optional; the app is live and keyless without it, just with fewer holders/safety fields).
236
+ const rpc = resolveRpcUrl({ env: deps.env, home: deps.env.HOME || undefined });
237
+ if (rpc.provider === 'helius') {
238
+ checks.push({ name: 'Helius RPC', status: 'pass', detail: `key configured (${rpc.basis}) — holders & safety enriched` });
239
+ }
240
+ else if (rpc.provider === 'custom') {
241
+ checks.push({ name: 'RPC', status: 'pass', detail: 'custom endpoint via DEXTERM_RPC_URL' });
242
+ }
243
+ else {
244
+ checks.push({
245
+ name: 'Helius RPC', status: 'warn',
246
+ detail: 'no key — dexterm uses the public RPC (holders & some safety fields will show as "needs key")',
247
+ fix: 'Free tier: make a key at https://dashboard.helius.dev, then `mkdir -p ~/.dexterm && printf %s "YOUR_KEY" > ~/.dexterm/helius.key && chmod 600 ~/.dexterm/helius.key`',
248
+ });
249
+ }
250
+ // 5. Network + each data source
251
+ if (deps.offline) {
252
+ checks.push({
253
+ name: 'Network', status: 'warn',
254
+ detail: 'DEXTERM_OFFLINE is set; skipped the live source probes (use --fixtures / --replay for offline data)',
255
+ });
256
+ }
257
+ else {
258
+ const results = await Promise.all(DATA_SOURCES.map(async (s) => ({ s, r: await deps.probe(s.url) })));
259
+ const down = results.filter((x) => !x.r.reachable);
260
+ const hardDown = down.filter((x) => !x.s.soft);
261
+ if (down.length === 0) {
262
+ const slow = results.filter((x) => (x.r.ms ?? 0) > 2500).map((x) => x.s.name);
263
+ checks.push({
264
+ name: 'Data sources', status: 'pass',
265
+ detail: `all ${results.length} reachable${slow.length ? ` (slow: ${slow.join(', ')})` : ''}`,
266
+ });
267
+ }
268
+ else {
269
+ checks.push({
270
+ name: 'Data sources', status: hardDown.length ? 'fail' : 'warn',
271
+ detail: `unreachable: ${down.map((x) => `${x.s.name} (${x.r.error ?? 'error'})`).join(', ')}`,
272
+ fix: hardDown.length
273
+ ? 'Check your internet connection / VPN / firewall. If only some hosts fail, they may be regionally blocked — try again or use a different network.'
274
+ : 'New pairs (PumpPortal) is unreachable; the rest of dexterm works. Check back later or your network may block its host.',
275
+ });
276
+ }
277
+ }
278
+ // 5b. task-1325: the native chart window (docked beside the terminal) vs the browser fallback
279
+ if (deps.popupShell) {
280
+ const sh = deps.popupShell();
281
+ if (sh.built)
282
+ checks.push({ name: 'Chart window', status: 'pass', detail: `native window ready (${sh.path}); C on a token opens it docked beside this terminal` });
283
+ else
284
+ checks.push({
285
+ name: 'Chart window', status: 'warn',
286
+ detail: `native window not built — C opens the chart in your browser instead`,
287
+ fix: sh.cargo ? 'Run `npm run build:shell` in packages/popup (about a minute the first time).' : 'Install Rust (https://rustup.rs), then run `npm run build:shell` in packages/popup.',
288
+ });
289
+ }
290
+ // 6. Writable DB path
291
+ const dbPath = defaultDbPath(deps.env);
292
+ const dbDir = dirname(dbPath);
293
+ const werr = deps.checkWritable(dbDir);
294
+ if (!werr) {
295
+ checks.push({ name: 'Data directory', status: 'pass', detail: `${dbDir} is writable (cache, watchlist, credit meter)` });
296
+ }
297
+ else {
298
+ checks.push({
299
+ name: 'Data directory', status: 'fail',
300
+ detail: `cannot write ${dbDir}: ${werr}`,
301
+ fix: `Fix the permissions (\`mkdir -p ${dbDir} && chmod u+rwx ${dbDir}\`) or run with \`--db :memory:\` for a throwaway session.`,
302
+ });
303
+ }
304
+ // 6b. task-1377: the user's KB / skill overlay. Warn-only: a bad user file is skipped and the bundled one stays in effect.
305
+ if (deps.content) {
306
+ try {
307
+ const { kb, skills } = deps.content();
308
+ const part = (label, m) => `${label} ${m.bundled} bundled · ${m.user} user (${m.overridden} overridden, ${m.added} new)${m.skipped.length ? ` · ${m.skipped.length} skipped` : ''}`;
309
+ const detail = `${part('KB', kb)} · ${part('skills', skills)}`;
310
+ const skipped = [...kb.skipped.map((s) => `kb ${s.id}: ${s.reason}`), ...skills.skipped.map((s) => `skill ${s.id}: ${s.reason}`)];
311
+ if (skipped.length) {
312
+ checks.push({ name: 'KB + skills', status: 'warn', detail: `${detail}; skipped ${skipped.slice(0, 3).join('; ')}`, fix: `Run \`dexterm kb check\` / \`dexterm skill check\` and fix the file, or \`dexterm kb|skill reset <id>\` to go back to the bundled one.` });
313
+ }
314
+ else {
315
+ checks.push({ name: 'KB + skills', status: 'pass', detail: `${detail} (yours: ${kb.dir}, ${skills.dir}; \`dexterm kb|skill list\`)` });
316
+ }
317
+ }
318
+ catch { /* an overlay problem must not break the doctor */ }
319
+ }
320
+ // 7. Voice mode (task-1282). Warn-only — voice always degrades to text, so it never fails the doctor.
321
+ if (deps.voiceProbe) {
322
+ try {
323
+ const vc = voiceDoctor(await deps.voiceProbe());
324
+ for (const c of vc)
325
+ checks.push(c);
326
+ }
327
+ catch { /* a voice probe failure must not break the doctor */ }
328
+ }
329
+ const ok = !checks.some((c) => c.status === 'fail');
330
+ return { checks, ok };
331
+ }
332
+ const GLYPH = { pass: '✓', warn: '!', fail: '✗' };
333
+ const ANSI = { pass: '\x1b[32m', warn: '\x1b[33m', fail: '\x1b[31m' };
334
+ const RESET = '\x1b[0m';
335
+ const DIM = '\x1b[2m';
336
+ const BOLD = '\x1b[1m';
337
+ /** Render the result as a plain pass/fail list. `color` adds ANSI; off for pipes / NO_COLOR. */
338
+ export function renderDoctor(result, opts = {}) {
339
+ const color = opts.color ?? false;
340
+ const paint = (s, code) => (color ? code + s + RESET : s);
341
+ const lines = [];
342
+ lines.push(paint('dexterm doctor', color ? BOLD : ''));
343
+ lines.push('');
344
+ const nameW = Math.max(...result.checks.map((c) => c.name.length));
345
+ for (const c of result.checks) {
346
+ const g = paint(GLYPH[c.status], color ? ANSI[c.status] : '');
347
+ lines.push(` ${g} ${c.name.padEnd(nameW)} ${c.detail}`);
348
+ if (c.fix)
349
+ lines.push(` ${' '.repeat(nameW)} ${paint('→ ' + c.fix, color ? DIM : '')}`);
350
+ }
351
+ lines.push('');
352
+ const fails = result.checks.filter((c) => c.status === 'fail').length;
353
+ const warns = result.checks.filter((c) => c.status === 'warn').length;
354
+ if (result.ok && warns === 0)
355
+ lines.push(paint('All checks passed — run `dexterm` to start.', color ? ANSI.pass : ''));
356
+ else if (result.ok)
357
+ lines.push(paint(`Ready to run (${warns} warning${warns === 1 ? '' : 's'} above are optional).`, color ? ANSI.warn : ''));
358
+ else
359
+ lines.push(paint(`${fails} check${fails === 1 ? '' : 's'} failed — fix the ✗ lines above, then re-run \`dexterm doctor\`.`, color ? ANSI.fail : ''));
360
+ return lines.join('\n');
361
+ }