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,117 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "dexterm/claude-layer/larp",
4
+ "title": "LARP detector verdict (larp-check)",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["skill", "skill_version", "mint", "verdict", "confidence", "claims", "missing_data", "facts", "flags", "injection_detected", "sources_used", "summary"],
8
+ "properties": {
9
+ "skill": { "type": "string", "enum": ["larp-check"] },
10
+ "skill_version": { "type": "string" },
11
+ "mint": { "type": "string", "description": "The mint analysed, or empty string when AMBIGUOUS before resolution" },
12
+ "verdict": { "type": "string", "enum": ["REAL_PRODUCT", "EARLY_BUT_REAL", "LARP", "UNVERIFIABLE", "AMBIGUOUS"] },
13
+ "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
14
+ "summary": { "type": "string", "maxLength": 600, "description": "Two to four short lines for a 40-column panel: the verdict in plain words and the strongest evidence. Never a disclaimer line" },
15
+ "claims": {
16
+ "type": "array",
17
+ "description": "Each product claim the site/socials make, with the evidence for or against it.",
18
+ "minItems": 0,
19
+ "maxItems": 20,
20
+ "items": {
21
+ "type": "object",
22
+ "additionalProperties": false,
23
+ "required": ["claim", "status", "evidence"],
24
+ "properties": {
25
+ "claim": { "type": "string", "maxLength": 160, "description": "What the project claims exists (a live app, a demo, a GitHub, a team, docs…)" },
26
+ "status": { "type": "string", "enum": ["supported", "contradicted", "unverifiable"] },
27
+ "evidence": { "type": "string", "maxLength": 240, "description": "The tool result that supports/contradicts it (tool + field + value), or why it is unverifiable" }
28
+ }
29
+ }
30
+ },
31
+ "links_checked": {
32
+ "type": "array",
33
+ "maxItems": 24,
34
+ "items": {
35
+ "type": "object",
36
+ "additionalProperties": false,
37
+ "required": ["url", "kind", "reachable"],
38
+ "properties": {
39
+ "url": { "type": "string" },
40
+ "kind": { "type": "string" },
41
+ "reachable": { "type": "boolean" },
42
+ "status": { "type": ["number", "null"] }
43
+ }
44
+ }
45
+ },
46
+ "domain": {
47
+ "type": ["object", "null"],
48
+ "additionalProperties": false,
49
+ "properties": {
50
+ "domain": { "type": ["string", "null"] },
51
+ "age_days": { "type": ["number", "null"] },
52
+ "registrar": { "type": ["string", "null"] },
53
+ "privacy": { "type": ["boolean", "null"] }
54
+ }
55
+ },
56
+ "github": {
57
+ "type": ["object", "null"],
58
+ "additionalProperties": false,
59
+ "properties": {
60
+ "repo": { "type": ["string", "null"] },
61
+ "days_since_push": { "type": ["number", "null"] },
62
+ "stars": { "type": ["number", "null"] },
63
+ "archived": { "type": ["boolean", "null"] }
64
+ }
65
+ },
66
+ "missing_data": {
67
+ "type": "array",
68
+ "description": "What could not be fetched keyless (e.g. X is login-walled, site timed out). Be honest here.",
69
+ "items": { "type": "string", "maxLength": 160 },
70
+ "maxItems": 20
71
+ },
72
+ "facts": {
73
+ "type": "array",
74
+ "minItems": 0,
75
+ "maxItems": 24,
76
+ "items": {
77
+ "type": "object",
78
+ "additionalProperties": false,
79
+ "required": ["claim", "tool", "field", "value"],
80
+ "properties": {
81
+ "claim": { "type": "string", "maxLength": 160 },
82
+ "tool": { "type": "string" },
83
+ "field": { "type": "string" },
84
+ "value": { "type": ["number", "string", "boolean", "null"] },
85
+ "age_sec": { "type": ["number", "null"] }
86
+ }
87
+ }
88
+ },
89
+ "flags": { "type": "array", "items": { "type": "string" }, "maxItems": 20 },
90
+ "invalidation": { "type": "string", "maxLength": 240 },
91
+ "proposals": {
92
+ "type": "array",
93
+ "maxItems": 5,
94
+ "items": {
95
+ "type": "object",
96
+ "additionalProperties": false,
97
+ "required": ["type", "text"],
98
+ "properties": {
99
+ "type": { "type": "string", "enum": ["alert", "note", "watchlist"] },
100
+ "text": { "type": "string", "maxLength": 200 },
101
+ "condition": { "type": "string", "maxLength": 120 }
102
+ }
103
+ }
104
+ },
105
+ "injection_detected": { "type": "boolean" },
106
+ "candidates": {
107
+ "type": "array",
108
+ "description": "AMBIGUOUS only: the mints the symbol could mean",
109
+ "items": { "type": "object", "additionalProperties": false, "required": ["mint"], "properties": { "mint": { "type": "string" }, "launchpad": { "type": "string" }, "mcap": { "type": ["number", "null"] }, "ageSec": { "type": ["number", "null"] } } }
110
+ },
111
+ "sources_used": {
112
+ "type": "array",
113
+ "items": { "type": "object", "additionalProperties": false, "required": ["tool"], "properties": { "tool": { "type": "string" }, "source": { "type": "string" }, "age_sec": { "type": ["number", "null"] } } }
114
+ },
115
+ "kb_entries_cited": { "type": "array", "items": { "type": "string" } }
116
+ }
117
+ }
@@ -0,0 +1,71 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "dexterm/claude-layer/trench-scan",
4
+ "title": "Trench scan output",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["skill", "skill_version", "scanned", "candidates", "skipped", "injection_detected", "sources_used", "summary"],
8
+ "properties": {
9
+ "skill": { "type": "string", "enum": ["trench-scan"] },
10
+ "skill_version": { "type": "string" },
11
+ "scanned": { "type": "integer", "minimum": 0 },
12
+ "summary": { "type": "string", "maxLength": 400, "description": "One short line per candidate plus one skipped-count line. No intro, no disclaimer line" },
13
+ "candidates": {
14
+ "type": "array",
15
+ "maxItems": 10,
16
+ "items": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "required": ["mint", "verdict", "confidence", "reasons", "facts"],
20
+ "properties": {
21
+ "mint": { "type": "string" },
22
+ "symbol": { "type": "string" },
23
+ "verdict": { "type": "string", "enum": ["WATCH", "SPECULATIVE", "AVOID", "INSUFFICIENT_DATA"] },
24
+ "bias": { "type": "string", "enum": ["long", "short", "avoid", "wait"], "description": "Quick directional lean for this candidate" },
25
+ "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
26
+ "reasons": { "type": "array", "items": { "type": "string", "maxLength": 120 }, "maxItems": 5 },
27
+ "facts": {
28
+ "type": "array",
29
+ "maxItems": 8,
30
+ "items": { "type": "object", "additionalProperties": false, "required": ["claim", "tool", "field", "value"], "properties": { "claim": { "type": "string", "maxLength": 120 }, "tool": { "type": "string" }, "field": { "type": "string" }, "value": { "type": ["number", "string", "boolean", "null"] } } }
31
+ }
32
+ }
33
+ }
34
+ },
35
+ "skipped": {
36
+ "type": "array",
37
+ "items": { "type": "object", "additionalProperties": false, "required": ["mint", "reason"], "properties": { "mint": { "type": "string" }, "reason": { "type": "string", "maxLength": 120 } } }
38
+ },
39
+ "proposals": {
40
+ "type": "array",
41
+ "maxItems": 5,
42
+ "items": { "type": "object", "additionalProperties": false, "required": ["type", "text"], "properties": { "type": { "type": "string", "enum": ["alert", "note", "watchlist"] }, "text": { "type": "string", "maxLength": 200 }, "mint": { "type": "string" } } }
43
+ },
44
+ "injection_detected": { "type": "boolean" },
45
+ "results": {
46
+ "type": "array",
47
+ "maxItems": 20,
48
+ "description": "The scan's ranked coins as a list the app renders as a live table (prices/liq/vol from its data layer by mint, never your text). One entry per WATCH/SPECULATIVE candidate, best first; only mints the screener returned.",
49
+ "items": {
50
+ "type": "object",
51
+ "additionalProperties": false,
52
+ "required": ["mint", "reason"],
53
+ "properties": {
54
+ "mint": { "type": "string" },
55
+ "symbol": { "type": "string", "maxLength": 32 },
56
+ "reason": { "type": "string", "maxLength": 100 }
57
+ }
58
+ }
59
+ },
60
+ "filter_applied": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "required": ["query"],
64
+ "properties": {
65
+ "query": { "type": "string", "maxLength": 120 },
66
+ "notes": { "type": "string", "maxLength": 160 }
67
+ }
68
+ },
69
+ "sources_used": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["tool"], "properties": { "tool": { "type": "string" }, "source": { "type": "string" }, "age_sec": { "type": ["number", "null"] } } } }
70
+ }
71
+ }
@@ -0,0 +1,115 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "dexterm/claude-layer/verdict",
4
+ "title": "Analyst verdict (token-dossier, rug-check)",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["skill", "skill_version", "mint", "verdict", "confidence", "facts", "flags", "invalidation", "proposals", "injection_detected", "sources_used", "summary", "missing_data"],
8
+ "properties": {
9
+ "product_assessment": {
10
+ "type": "object", "additionalProperties": false,
11
+ "required": ["verdict", "confidence", "claims", "missing_data"],
12
+ "properties": {
13
+ "verdict": { "type": "string", "enum": ["REAL_PRODUCT", "EARLY_BUT_REAL", "LARP", "UNVERIFIABLE"] },
14
+ "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
15
+ "claims": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["claim", "evidence"], "properties": { "claim": { "type": "string" }, "evidence": { "type": "string" } } } },
16
+ "missing_data": { "type": "array", "items": { "type": "string" } }
17
+ }
18
+ },
19
+ "skill": { "type": "string", "enum": ["token-dossier", "rug-check"] },
20
+ "skill_version": { "type": "string" },
21
+ "mint": { "type": "string", "description": "The mint analysed, or empty string when AMBIGUOUS/INSUFFICIENT_DATA before resolution" },
22
+ "verdict": { "type": "string", "enum": ["WATCH", "SPECULATIVE", "AVOID", "INSUFFICIENT_DATA", "AMBIGUOUS"] },
23
+ "bias": { "type": "string", "enum": ["long", "short", "avoid", "wait"], "description": "The directional trading view; give one unless AMBIGUOUS/INSUFFICIENT_DATA" },
24
+ "setup_quality": { "type": "string", "enum": ["strong", "mixed", "weak"], "description": "How clean the setup is given liquidity, holders, tape and structure" },
25
+ "key_levels": {
26
+ "type": "array",
27
+ "maxItems": 8,
28
+ "description": "Concrete levels from the candles and liquidity (support, resistance, VWAP, range high/low, invalidation level)",
29
+ "items": {
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "required": ["label"],
33
+ "properties": {
34
+ "label": { "type": "string", "maxLength": 40 },
35
+ "value": { "type": ["number", "string", "null"] },
36
+ "note": { "type": "string", "maxLength": 80 }
37
+ }
38
+ }
39
+ },
40
+ "size_hint": { "type": "string", "maxLength": 160, "description": "Size framed as a fraction of risk capital with the stop (e.g. '0.5-1% risk, stop below the range low'); never a dollar amount or a token count" },
41
+ "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
42
+ "missing_data": { "type": "array", "items": { "type": "string", "maxLength": 160 }, "maxItems": 20, "description": "Sections or fields that were unavailable/null (copied from the dossier `availability.missing` and `knownUnavailable`). Empty array when everything was present. A non-empty list lowers confidence but — as long as price or liquidity exists — never forces INSUFFICIENT_DATA." },
43
+ "rug_probability": { "type": "number", "minimum": 0, "maximum": 1, "description": "rug-check only: model's probability that this token rugs within 72 h" },
44
+ "summary": { "type": "string", "maxLength": 600, "description": "Two to four short lines for a 40-column panel: the call in plain words and the deciding facts. Never repeats bias/levels/invalidation/size (rendered from their own fields), never a disclaimer line" },
45
+ "facts": {
46
+ "type": "array",
47
+ "minItems": 0,
48
+ "maxItems": 20,
49
+ "items": {
50
+ "type": "object",
51
+ "additionalProperties": false,
52
+ "required": ["claim", "tool", "field", "value"],
53
+ "properties": {
54
+ "claim": { "type": "string", "maxLength": 160 },
55
+ "tool": { "type": "string" },
56
+ "field": { "type": "string" },
57
+ "value": { "type": ["number", "string", "boolean", "null"] },
58
+ "age_sec": { "type": ["number", "null"] }
59
+ }
60
+ }
61
+ },
62
+ "flags": { "type": "array", "items": { "type": "string" }, "maxItems": 20 },
63
+ "invalidation": { "type": "string", "maxLength": 240 },
64
+ "proposals": {
65
+ "type": "array",
66
+ "maxItems": 5,
67
+ "items": {
68
+ "type": "object",
69
+ "additionalProperties": false,
70
+ "required": ["type", "text"],
71
+ "properties": {
72
+ "type": { "type": "string", "enum": ["alert", "note", "watchlist"] },
73
+ "text": { "type": "string", "maxLength": 200 },
74
+ "condition": { "type": "string", "maxLength": 120 }
75
+ }
76
+ }
77
+ },
78
+ "injection_detected": { "type": "boolean" },
79
+ "candidates": {
80
+ "type": "array",
81
+ "description": "AMBIGUOUS only: the mints the symbol could mean",
82
+ "items": { "type": "object", "additionalProperties": false, "required": ["mint"], "properties": { "mint": { "type": "string" }, "launchpad": { "type": "string" }, "mcap": { "type": ["number", "null"] }, "ageSec": { "type": ["number", "null"] } } }
83
+ },
84
+ "results": {
85
+ "type": "array",
86
+ "maxItems": 20,
87
+ "description": "When the answer is a LIST of coins (e.g. after a filter, or 'best setups right now'), put one entry per coin here by mint. The app renders a live table from these mints (prices/liq/vol come from its data layer, never your text); only mints already on screen or fetched via tools are shown. Give a one-line reason per row.",
88
+ "items": {
89
+ "type": "object",
90
+ "additionalProperties": false,
91
+ "required": ["mint", "reason"],
92
+ "properties": {
93
+ "mint": { "type": "string", "description": "base58 mint of a coin that is on screen or that a tool returned" },
94
+ "symbol": { "type": "string", "maxLength": 32 },
95
+ "reason": { "type": "string", "maxLength": 100, "description": "one short line on why this coin is in the list" }
96
+ }
97
+ }
98
+ },
99
+ "filter_applied": {
100
+ "type": "object",
101
+ "additionalProperties": false,
102
+ "description": "When you called show_in_screener for a plain-language request, echo the structured filter you applied here so the user sees (and can correct) the numbers you chose.",
103
+ "required": ["query"],
104
+ "properties": {
105
+ "query": { "type": "string", "maxLength": 120, "description": "the exact filter string you passed to show_in_screener, in dexterm grammar (e.g. 'mcap < 5M liq > 50K h24 > 0 flag:clean')" },
106
+ "notes": { "type": "string", "maxLength": 160, "description": "the numbers you chose for vague words, in words (e.g. 'low cap = mcap < 5M; liquid = liq > 50K; up on the day = h24 > 0; not a rug = flag:clean')" }
107
+ }
108
+ },
109
+ "sources_used": {
110
+ "type": "array",
111
+ "items": { "type": "object", "additionalProperties": false, "required": ["tool"], "properties": { "tool": { "type": "string" }, "source": { "type": "string" }, "age_sec": { "type": ["number", "null"] } } }
112
+ },
113
+ "kb_entries_cited": { "type": "array", "items": { "type": "string" } }
114
+ }
115
+ }
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ // dexterm bin shim. Runs the TypeScript sources directly via Node's built-in type stripping
3
+ // (Node >= 22.18 / 23.6+ / 24). This is the checkout/source-tarball entry; the npm package's bin is
4
+ // the compiled copy at dist/packages/cli/bin/dexterm.mjs, built by scripts/build-dist.mjs (task-1346).
5
+ const [major, minor] = process.versions.node.split('.').map(Number);
6
+ if (major < 22 || (major === 22 && minor < 18)) {
7
+ process.stderr.write(`dexterm needs Node 22.18 or newer (found ${process.versions.node})\n`);
8
+ process.exit(1);
9
+ }
10
+ const { main } = await import('../src/main.js');
11
+ process.exitCode = await main(process.argv.slice(2));
@@ -0,0 +1,303 @@
1
+ // `dexterm agent …` — bring-your-own-agent registry + loopback bus CLI (task-1345, tier 2).
2
+ //
3
+ // dexterm agent add <name> --tier observe|annotate|propose [--note T] [--reads N] [--proposals N] [--connections N]
4
+ // dexterm agent list
5
+ // dexterm agent rotate <name> # new one-time token; the old one stops working
6
+ // dexterm agent remove <name>
7
+ // dexterm agent tier <name> <tier>
8
+ // dexterm agent pause|resume <name>
9
+ // dexterm agent audit [--agent NAME] [--limit N]
10
+ // dexterm agent packs # the skills/KB an external agent gets over MCP (agent packs)
11
+ // dexterm agent serve [--fixtures|--live] [--port N] [--db PATH] # run a standalone loopback bus
12
+ // dexterm agent connect --name NAME [--port N] [--url ws://…] [--watch SECONDS] # token from $DEXTERM_AGENT_TOKEN
13
+ //
14
+ // A one-time token is printed to stdout by `add`/`rotate` so the user can paste it into THEIR agent's
15
+ // config; it is never stored in plaintext and never echoed again. The token for `serve`/`connect` auth is
16
+ // read ONLY from the $DEXTERM_AGENT_TOKEN environment variable — never a command-line flag — so it cannot
17
+ // leak through a process list. No agent path can arm, sign, send, raise a cap or touch a wallet/mandate.
18
+ import { AgentRegistry, SqliteAuditLog, MemoryProposalStore, SqliteProposalStore, AgentBus, FixtureExecutor, FixtureFeed, TIERS, isTier, } from '../../agents/src/index.js';
19
+ import { connectAgent } from '../../agents/src/sdk.js';
20
+ import { defaultDbPath } from '../../data/src/index.js';
21
+ function flag(rest, name) { const i = rest.indexOf(name); return i >= 0 ? rest[i + 1] : undefined; }
22
+ function has(rest, name) { return rest.includes(name); }
23
+ function intFlag(rest, name) { const v = flag(rest, name); const n = v === undefined ? undefined : Number(v); return typeof n === 'number' && Number.isFinite(n) ? n : undefined; }
24
+ const USAGE = `dexterm agent <command>
25
+ add <name> --tier observe|annotate|propose [--note T] [--reads N] [--proposals N] [--connections N]
26
+ list | rotate <name> | remove <name> | tier <name> <tier> | pause <name> | resume <name>
27
+ audit [--agent NAME] [--limit N]
28
+ proposals [--agent NAME] [--status pending|confirmed|dismissed] [--limit N] [--db PATH]
29
+ packs
30
+ serve [--fixtures|--live] [--roster] [--port N] [--db PATH]
31
+ connect --name NAME [--port N] [--url ws://127.0.0.1:PORT] [--watch SECONDS] (token via $DEXTERM_AGENT_TOKEN)`;
32
+ export async function runAgent(rest, io) {
33
+ const cmd = rest[0];
34
+ const out = (s) => io.stdout.write(s + '\n');
35
+ const errOut = (s) => io.stderr.write(s + '\n');
36
+ const registry = new AgentRegistry({ env: io.env });
37
+ switch (cmd) {
38
+ case 'add': {
39
+ const name = rest[1];
40
+ const tier = flag(rest, '--tier');
41
+ if (!name || !tier || !isTier(tier)) {
42
+ errOut(`usage: dexterm agent add <name> --tier ${TIERS.join('|')}`);
43
+ return 2;
44
+ }
45
+ const limits = { readsPerMin: intFlag(rest, '--reads'), proposalsPerHour: intFlag(rest, '--proposals'), connections: intFlag(rest, '--connections') };
46
+ try {
47
+ const { agent, token } = registry.add(name, tier, { note: flag(rest, '--note'), limits });
48
+ out(`registered "${agent.name}" (tier ${agent.tier}, id ${agent.id}).`);
49
+ out('');
50
+ out(' one-time token (shown once — paste it into your agent, do not commit it):');
51
+ out(` ${token}`);
52
+ out('');
53
+ out(` your agent authenticates with name="${agent.name}" + this token over the loopback bus or a bridged MCP child.`);
54
+ return 0;
55
+ }
56
+ catch (e) {
57
+ errOut(`dexterm agent add: ${e.message}`);
58
+ return 1;
59
+ }
60
+ }
61
+ case 'list': {
62
+ const list = registry.list();
63
+ if (!list.length) {
64
+ out('no agents registered. Add one: dexterm agent add <name> --tier observe');
65
+ return 0;
66
+ }
67
+ out('name tier paused created note');
68
+ for (const a of list)
69
+ out(`${a.name.padEnd(24)} ${a.tier.padEnd(9)} ${(a.paused ? 'yes' : 'no').padEnd(7)} ${new Date(a.createdAt).toISOString().slice(0, 19)} ${a.note ?? ''}`);
70
+ return 0;
71
+ }
72
+ case 'rotate': {
73
+ const name = rest[1];
74
+ if (!name) {
75
+ errOut('usage: dexterm agent rotate <name>');
76
+ return 2;
77
+ }
78
+ try {
79
+ const token = registry.rotate(name);
80
+ out(`rotated "${name}". the previous token no longer works.`);
81
+ out('');
82
+ out(' new one-time token (shown once):');
83
+ out(` ${token}`);
84
+ return 0;
85
+ }
86
+ catch (e) {
87
+ errOut(`dexterm agent rotate: ${e.message}`);
88
+ return 1;
89
+ }
90
+ }
91
+ case 'remove': {
92
+ const name = rest[1];
93
+ if (!name) {
94
+ errOut('usage: dexterm agent remove <name>');
95
+ return 2;
96
+ }
97
+ out(registry.remove(name) ? `removed "${name}" (its token is now invalid).` : `no agent "${name}".`);
98
+ return 0;
99
+ }
100
+ case 'tier': {
101
+ const name = rest[1];
102
+ const tier = rest[2];
103
+ if (!name || !tier || !isTier(tier)) {
104
+ errOut(`usage: dexterm agent tier <name> ${TIERS.join('|')}`);
105
+ return 2;
106
+ }
107
+ try {
108
+ registry.setTier(name, tier);
109
+ out(`"${name}" is now tier ${tier}.`);
110
+ return 0;
111
+ }
112
+ catch (e) {
113
+ errOut(`dexterm agent tier: ${e.message}`);
114
+ return 1;
115
+ }
116
+ }
117
+ case 'pause':
118
+ case 'resume': {
119
+ const name = rest[1];
120
+ if (!name) {
121
+ errOut(`usage: dexterm agent ${cmd} <name>`);
122
+ return 2;
123
+ }
124
+ try {
125
+ registry.setPaused(name, cmd === 'pause');
126
+ out(`"${name}" ${cmd === 'pause' ? 'paused' : 'resumed'} (persisted; a running dexterm applies it on the agent's next connection).`);
127
+ return 0;
128
+ }
129
+ catch (e) {
130
+ errOut(`dexterm agent ${cmd}: ${e.message}`);
131
+ return 1;
132
+ }
133
+ }
134
+ case 'audit': {
135
+ const dbPath = flag(rest, '--db') || defaultDbPath(io.env);
136
+ const log = new SqliteAuditLog(dbPath);
137
+ try {
138
+ const agentName = flag(rest, '--agent');
139
+ const rows = log.recent(intFlag(rest, '--limit') ?? 50, agentName ? { agentName } : {});
140
+ if (!rows.length) {
141
+ out('no audit rows yet.');
142
+ return 0;
143
+ }
144
+ out('time agent kind tool ok detail');
145
+ for (const r of rows.reverse())
146
+ out(`${new Date(r.t).toISOString().slice(0, 19)} ${r.agentName.padEnd(16)} ${r.kind.padEnd(10)} ${r.tool.slice(0, 16).padEnd(16)} ${r.ok ? ' y' : ' n'} ${r.detail}`);
147
+ return 0;
148
+ }
149
+ finally {
150
+ log.close();
151
+ }
152
+ }
153
+ case 'packs': {
154
+ const { selfTest } = await import('../../mcp/src/index.js');
155
+ const st = selfTest();
156
+ out('agent packs served over MCP (`dexterm mcp`): skills as prompts, KB + cases + skills as resources.');
157
+ out(` skills : ${st.skills.join(', ')}`);
158
+ out(` kb : ${st.kbEntries} entries`);
159
+ // task-1377: the user's overlay (~/.dexterm/kb/entries, ~/.dexterm/skills) is merged into what MCP serves.
160
+ const ov = st.overlay;
161
+ if (ov && (ov.kb.user || ov.skills.user))
162
+ out(` yours : kb +${ov.kb.user} (${ov.kb.overridden} override, ${ov.kb.added} new), skills +${ov.skills.user} (${ov.skills.overridden} override, ${ov.skills.added} new) — \`dexterm kb|skill list\``);
163
+ out(` cases : ${st.cases}`);
164
+ out(` resources: ${st.resources}`);
165
+ out('connect your agent: `claude mcp add dexterm -- dexterm mcp`, then run a skill, e.g. /dexterm:trench-scan 8');
166
+ return 0;
167
+ }
168
+ case 'proposals': {
169
+ const store = new SqliteProposalStore(flag(rest, '--db') || defaultDbPath(io.env));
170
+ try {
171
+ const status = flag(rest, '--status');
172
+ const rows = store.list({ agentId: undefined, status: status || undefined, limit: intFlag(rest, '--limit') ?? 50 });
173
+ const agent = flag(rest, '--agent');
174
+ const shown = agent ? rows.filter((p) => p.agentName === agent) : rows;
175
+ if (!shown.length) {
176
+ out('no proposals.');
177
+ return 0;
178
+ }
179
+ out('created agent kind status summary');
180
+ for (const p of shown)
181
+ out(`${new Date(p.createdAt).toISOString().slice(0, 19)} ${p.agentName.padEnd(16)} ${p.kind.padEnd(10)} ${p.status.padEnd(9)} ${p.summary}`);
182
+ out('');
183
+ out('proposals are DRAFTS. An agent can never confirm or arm one; the user confirms with a keypress.');
184
+ return 0;
185
+ }
186
+ finally {
187
+ store.close();
188
+ }
189
+ }
190
+ case 'serve': return serve(rest, io, registry);
191
+ case 'connect': return connect(rest, io);
192
+ default:
193
+ (cmd ? errOut(`unknown subcommand: ${cmd}`) : out(USAGE));
194
+ if (!cmd)
195
+ return 0;
196
+ errOut(USAGE);
197
+ return 2;
198
+ }
199
+ }
200
+ async function serve(rest, io, registry) {
201
+ const live = has(rest, '--live');
202
+ const port = intFlag(rest, '--port');
203
+ const dbPath = flag(rest, '--db');
204
+ const audit = new SqliteAuditLog(dbPath || ':memory:');
205
+ const proposals = dbPath ? new SqliteProposalStore(dbPath) : new MemoryProposalStore();
206
+ const feed = new FixtureFeed();
207
+ let executor;
208
+ let dataClose = null;
209
+ if (live) {
210
+ // Live reads over the real keyless data layer via the MCP tools; the gate still bounds every call.
211
+ const { McpTools } = await import('../../mcp/src/index.js');
212
+ const { createDataLayer, resolveRpcUrl, defaultDbPath: ddp } = await import('../../data/src/index.js');
213
+ const rpc = resolveRpcUrl({ env: io.env });
214
+ const data = createDataLayer({ dbPath: ddp(io.env), rpcUrl: rpc.url, rpcFallbackUrl: rpc.fallbackUrl });
215
+ dataClose = () => data.close();
216
+ const mcp = new McpTools(data, () => ({ screen: 'agent-bus', actions: { mints: [], feeds: [], sortKeys: [] } }));
217
+ executor = { async exec(_s, tool, args) { try {
218
+ return await mcp.call(tool, args);
219
+ }
220
+ catch (e) {
221
+ return { error: e.message };
222
+ } } };
223
+ }
224
+ else {
225
+ executor = new FixtureExecutor();
226
+ }
227
+ const bus = new AgentBus({ registry, audit, executor, proposals, feed, port, env: io.env });
228
+ const boundPort = await bus.start();
229
+ feed.start(1500);
230
+ io.stdout.write(`dexterm agent bus listening on ws://127.0.0.1:${boundPort} (${live ? 'live keyless reads' : 'fixtures'})\n`);
231
+ io.stdout.write(`discovery: ${process.env.DEXTERM_HOME ?? '~/.dexterm'}/agent-bus.json · ${registry.list().length} registered agent(s)\n`);
232
+ io.stdout.write('agents connect with their name + $DEXTERM_AGENT_TOKEN. Ctrl-C to stop.\n');
233
+ // --roster: open the agent roster popup and keep it live. The popup can only send pause/resume/kick.
234
+ let roster = null;
235
+ if (has(rest, '--roster')) {
236
+ try {
237
+ const { createPopupManager } = await import('../../popup/src/index.js');
238
+ const { buildRosterVM, applyRosterEvent } = await import("./agent-roster.js");
239
+ const { THEMES, DEFAULT_THEME } = await import('../../tui/src/index.js');
240
+ const { popupThemeFrom } = await import("./popup.js");
241
+ const mgr = createPopupManager({ theme: popupThemeFrom(THEMES[DEFAULT_THEME]), env: io.env, onWarn: (m) => io.stderr.write(`roster popup: ${m}\n`),
242
+ onEvent: (ev) => { if (ev.ev === 'popup.event' && ev.name.startsWith('roster.'))
243
+ io.stdout.write(`roster: ${applyRosterEvent(bus, ev.name, String(ev.payload.agent))}\n`); } });
244
+ const handle = await mgr.open({ kind: 'roster', title: 'agents', data: buildRosterVM(bus, audit) });
245
+ const timer = setInterval(() => { try {
246
+ mgr.setData(handle.id, buildRosterVM(bus, audit));
247
+ }
248
+ catch { /* popup closed */ } }, 1000);
249
+ timer.unref?.();
250
+ roster = { shutdown: () => mgr.shutdown(), timer };
251
+ io.stdout.write(`roster popup open (${mgr.native ? 'native window' : 'browser fallback'}).\n`);
252
+ }
253
+ catch (e) {
254
+ io.stderr.write(`roster popup unavailable: ${e.message}\n`);
255
+ }
256
+ }
257
+ await new Promise((resolve) => {
258
+ const stop = () => { if (roster) {
259
+ clearInterval(roster.timer);
260
+ void roster.shutdown();
261
+ } feed.stop(); audit.close(); proposals.close(); dataClose?.(); void bus.close().then(resolve); };
262
+ process.once('SIGINT', stop);
263
+ process.once('SIGTERM', stop);
264
+ });
265
+ return 0;
266
+ }
267
+ async function connect(rest, io) {
268
+ const name = flag(rest, '--name');
269
+ const token = io.env.DEXTERM_AGENT_TOKEN;
270
+ if (!name) {
271
+ io.stderr.write('usage: dexterm agent connect --name NAME [--port N] (token via $DEXTERM_AGENT_TOKEN)\n');
272
+ return 2;
273
+ }
274
+ if (!token) {
275
+ io.stderr.write('set $DEXTERM_AGENT_TOKEN to the token from `dexterm agent add` (never pass a token as a CLI flag).\n');
276
+ return 2;
277
+ }
278
+ const port = intFlag(rest, '--port');
279
+ const url = flag(rest, '--url');
280
+ try {
281
+ const agent = await connectAgent({ name, token, port, url, client: 'dexterm agent connect', home: io.env.DEXTERM_HOME });
282
+ io.stdout.write(`connected as "${agent.hello?.agent}" — tier ${agent.hello?.tier} (granted ${agent.hello?.grantedTier}).\n`);
283
+ const tools = await agent.listTools();
284
+ io.stdout.write(`tools (${tools.length}): ${tools.map((t) => t.name).join(', ')}\n`);
285
+ const who = await agent.whoami();
286
+ io.stdout.write(`whoami: ${JSON.stringify(who)}\n`);
287
+ const watch = intFlag(rest, '--watch');
288
+ if (watch && watch > 0) {
289
+ await agent.subscribe(['new_pairs', 'trades', 'alerts']);
290
+ agent.on('new_pairs', (ev) => io.stdout.write(`event new_pairs ${JSON.stringify(ev.data)}\n`));
291
+ agent.on('trades', (ev) => io.stdout.write(`event trades ${JSON.stringify(ev.data)}\n`));
292
+ agent.on('alerts', (ev) => io.stdout.write(`event alerts ${JSON.stringify(ev.data)}\n`));
293
+ io.stdout.write(`subscribed; watching for ${watch}s…\n`);
294
+ await new Promise((r) => setTimeout(r, watch * 1000));
295
+ }
296
+ agent.close();
297
+ return 0;
298
+ }
299
+ catch (e) {
300
+ io.stderr.write(`dexterm agent connect: ${e.message}\n`);
301
+ return 1;
302
+ }
303
+ }
@@ -0,0 +1,26 @@
1
+ // task-1345 tier 4: bridge the live agent bus to the roster popup VM, and drive the roster popup window.
2
+ // The popup only ever sends roster.pause / roster.resume / roster.kick (by agent name); this module maps
3
+ // those UI events onto the bus's user-side controls. Nothing here can arm, sign or change a cap.
4
+ /** Build the roster VM the popup renders from the live bus + the audit log. */
5
+ export function buildRosterVM(bus, audit, limit = 80) {
6
+ const agents = bus.roster().map((a) => ({
7
+ id: a.agentId, name: a.name, tier: a.tier, sessions: a.sessions, client: a.client, lastActivity: a.lastActivity,
8
+ topics: a.topics, reads: a.usage.readsPerMin, readsLimit: a.usage.limits.readsPerMin,
9
+ proposals: a.usage.proposalsPerHour, proposalsLimit: a.usage.limits.proposalsPerHour,
10
+ refused: a.counts.refused, paused: a.paused, floodPausedUntil: a.usage.floodPausedUntil,
11
+ }));
12
+ const log = audit.recent(limit).map((r) => ({ t: r.t, agent: r.agentName, kind: r.kind, tool: r.tool, ok: r.ok, detail: r.detail }));
13
+ return { now: Date.now(), busPort: bus.port, agents, audit: log };
14
+ }
15
+ /** Apply a validated popup roster event to the bus (user-side control). Returns a short log line. */
16
+ export function applyRosterEvent(bus, name, agent) {
17
+ if (name === 'roster.pause')
18
+ return bus.pauseAgent(agent) ? `paused ${agent}` : `no agent ${agent}`;
19
+ if (name === 'roster.resume')
20
+ return bus.resumeAgent(agent) ? `resumed ${agent}` : `no agent ${agent}`;
21
+ if (name === 'roster.kick') {
22
+ const n = bus.kickAgent(agent);
23
+ return `kicked ${agent} (${n} session${n === 1 ? '' : 's'})`;
24
+ }
25
+ return `ignored ${name}`;
26
+ }