dexterm-cli 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/dist/packages/agents/src/schema.js +22 -1
  2. package/dist/packages/agents/src/spectator.js +3 -1
  3. package/dist/packages/agents/src/story.js +11 -2
  4. package/dist/packages/agents/src/tiers.js +36 -2
  5. package/dist/packages/agents/src/tools.js +35 -2
  6. package/dist/packages/autotrade/assets/exit-profile.schema.json +492 -0
  7. package/dist/packages/autotrade/assets/limits.schema.json +569 -0
  8. package/dist/packages/autotrade/assets/profiles/moonbag.json +46 -0
  9. package/dist/packages/autotrade/assets/profiles/runner.json +88 -0
  10. package/dist/packages/autotrade/assets/profiles/scalp.json +88 -0
  11. package/dist/packages/autotrade/assets/profiles/swing.json +88 -0
  12. package/dist/packages/autotrade/assets/strategies/moonbag.json +101 -0
  13. package/dist/packages/autotrade/assets/strategies/runner.json +101 -0
  14. package/dist/packages/autotrade/assets/strategies/sample-dip-ladder.json +188 -0
  15. package/dist/packages/autotrade/assets/strategies/scalp.json +98 -0
  16. package/dist/packages/autotrade/assets/strategies/swing.json +97 -0
  17. package/dist/packages/autotrade/assets/strategies/yolo.json +157 -0
  18. package/dist/packages/autotrade/assets/tapes/yolo-rehearsal.json +1 -0
  19. package/dist/packages/autotrade/examples/executor/README.md +70 -0
  20. package/dist/packages/autotrade/examples/executor/jsonl-tail-executor.mjs +57 -0
  21. package/dist/packages/autotrade/examples/executor/kit.mjs +144 -0
  22. package/dist/packages/autotrade/examples/executor/signal-cmd-executor.mjs +25 -0
  23. package/dist/packages/autotrade/examples/executor/telegram-bot-recipe.md +47 -0
  24. package/dist/packages/autotrade/examples/executor/webhook-executor.mjs +47 -0
  25. package/dist/packages/autotrade/src/account.js +74 -0
  26. package/dist/packages/autotrade/src/backtest.js +358 -0
  27. package/dist/packages/autotrade/src/basis-text.js +32 -0
  28. package/dist/packages/autotrade/src/chat/approvals.js +484 -0
  29. package/dist/packages/autotrade/src/chat/audit.js +140 -0
  30. package/dist/packages/autotrade/src/chat/config.js +95 -0
  31. package/dist/packages/autotrade/src/chat/connector.js +24 -0
  32. package/dist/packages/autotrade/src/chat/control.js +104 -0
  33. package/dist/packages/autotrade/src/chat/fake.js +100 -0
  34. package/dist/packages/autotrade/src/chat/format.js +71 -0
  35. package/dist/packages/autotrade/src/chat/hub.js +187 -0
  36. package/dist/packages/autotrade/src/chat/index.js +18 -0
  37. package/dist/packages/autotrade/src/chat/notify.js +302 -0
  38. package/dist/packages/autotrade/src/chat/pairing.js +46 -0
  39. package/dist/packages/autotrade/src/chat/redact.js +48 -0
  40. package/dist/packages/autotrade/src/chat/secrets.js +106 -0
  41. package/dist/packages/autotrade/src/chat/service.js +251 -0
  42. package/dist/packages/autotrade/src/chat/telegram.js +290 -0
  43. package/dist/packages/autotrade/src/desk-executor.js +188 -0
  44. package/dist/packages/autotrade/src/engine.js +401 -0
  45. package/dist/packages/autotrade/src/execution-port.js +97 -0
  46. package/dist/packages/autotrade/src/executor-health.js +217 -0
  47. package/dist/packages/autotrade/src/fleet-config.js +169 -0
  48. package/dist/packages/autotrade/src/fleet-control.js +276 -0
  49. package/dist/packages/autotrade/src/fleet.js +642 -0
  50. package/dist/packages/autotrade/src/forward.js +355 -0
  51. package/dist/packages/autotrade/src/index.js +72 -0
  52. package/dist/packages/autotrade/src/journey.js +477 -0
  53. package/dist/packages/autotrade/src/ledger.js +108 -0
  54. package/dist/packages/autotrade/src/limits.js +682 -0
  55. package/dist/packages/autotrade/src/live-source.js +182 -0
  56. package/dist/packages/autotrade/src/monitor-daemon.js +715 -0
  57. package/dist/packages/autotrade/src/monitor.js +190 -0
  58. package/dist/packages/autotrade/src/ollama-sessions.js +137 -0
  59. package/dist/packages/autotrade/src/outbox.js +394 -0
  60. package/dist/packages/autotrade/src/paper-accounts.js +72 -0
  61. package/dist/packages/autotrade/src/paper-limits.js +87 -0
  62. package/dist/packages/autotrade/src/real-mode.js +688 -0
  63. package/dist/packages/autotrade/src/receipts.js +330 -0
  64. package/dist/packages/autotrade/src/replay.js +198 -0
  65. package/dist/packages/autotrade/src/report.js +168 -0
  66. package/dist/packages/autotrade/src/runner-config.js +99 -0
  67. package/dist/packages/autotrade/src/runner.js +923 -0
  68. package/dist/packages/autotrade/src/safety.js +243 -0
  69. package/dist/packages/autotrade/src/service-guard.js +125 -0
  70. package/dist/packages/autotrade/src/service-install.js +213 -0
  71. package/dist/packages/autotrade/src/service-recover.js +232 -0
  72. package/dist/packages/autotrade/src/service.js +289 -0
  73. package/dist/packages/autotrade/src/session.js +269 -0
  74. package/dist/packages/autotrade/src/sessions.js +503 -0
  75. package/dist/packages/autotrade/src/signal-channels.js +312 -0
  76. package/dist/packages/autotrade/src/signal.js +196 -0
  77. package/dist/packages/autotrade/src/store.js +250 -0
  78. package/dist/packages/autotrade/src/strategy.js +258 -0
  79. package/dist/packages/autotrade/src/trade-ledger.js +241 -0
  80. package/dist/packages/autotrade/src/yolo.js +140 -0
  81. package/dist/packages/cli/assets/claude/analyst-system.md +4 -4
  82. package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +1 -1
  83. package/dist/packages/cli/src/ai-cmd.js +412 -0
  84. package/dist/packages/cli/src/analyst/backend.js +83 -15
  85. package/dist/packages/cli/src/analyst/codex.js +15 -9
  86. package/dist/packages/cli/src/analyst/ollama.js +263 -0
  87. package/dist/packages/cli/src/analyst/session.js +5 -2
  88. package/dist/packages/cli/src/app-help-gen.js +56 -8
  89. package/dist/packages/cli/src/autotrade-cmd/audit.js +74 -0
  90. package/dist/packages/cli/src/autotrade-cmd/backtest.js +216 -0
  91. package/dist/packages/cli/src/autotrade-cmd/executor.js +91 -0
  92. package/dist/packages/cli/src/autotrade-cmd/flatten.js +64 -0
  93. package/dist/packages/cli/src/autotrade-cmd/fleet.js +401 -0
  94. package/dist/packages/cli/src/autotrade-cmd/forward.js +283 -0
  95. package/dist/packages/cli/src/autotrade-cmd/journey.js +208 -0
  96. package/dist/packages/cli/src/autotrade-cmd/limits.js +393 -0
  97. package/dist/packages/cli/src/autotrade-cmd/receipt.js +63 -0
  98. package/dist/packages/cli/src/autotrade-cmd/report.js +79 -0
  99. package/dist/packages/cli/src/autotrade-cmd/requests.js +79 -0
  100. package/dist/packages/cli/src/autotrade-cmd/run.js +657 -0
  101. package/dist/packages/cli/src/autotrade-cmd/service.js +873 -0
  102. package/dist/packages/cli/src/autotrade-cmd/signal.js +824 -0
  103. package/dist/packages/cli/src/autotrade-cmd/stop.js +76 -0
  104. package/dist/packages/cli/src/autotrade-cmd/strategies.js +198 -0
  105. package/dist/packages/cli/src/autotrade-cmd/strategy-control.js +174 -0
  106. package/dist/packages/cli/src/autotrade-cmd/telegram-host.js +101 -0
  107. package/dist/packages/cli/src/autotrade-cmd.js +214 -0
  108. package/dist/packages/cli/src/display.js +156 -17
  109. package/dist/packages/cli/src/doctor.js +62 -3
  110. package/dist/packages/cli/src/export.js +10 -2
  111. package/dist/packages/cli/src/index.js +1 -1
  112. package/dist/packages/cli/src/ledger-cmd.js +290 -0
  113. package/dist/packages/cli/src/live/chart-fills.js +46 -0
  114. package/dist/packages/cli/src/live/index.js +23 -89
  115. package/dist/packages/cli/src/live/screens/token-live.js +9 -6
  116. package/dist/packages/cli/src/live/trade.js +12 -457
  117. package/dist/packages/cli/src/live/watchlist.js +1 -1
  118. package/dist/packages/cli/src/main.js +147 -190
  119. package/dist/packages/cli/src/mcp-cmd.js +7 -1
  120. package/dist/packages/cli/src/plan-cmd.js +1 -1
  121. package/dist/packages/cli/src/pnl-app.js +31 -21
  122. package/dist/packages/cli/src/pnl-card.js +162 -21
  123. package/dist/packages/cli/src/popup.js +22 -6
  124. package/dist/packages/cli/src/record-cmd.js +141 -20
  125. package/dist/packages/cli/src/screens/agent-hud.js +34 -2
  126. package/dist/packages/cli/src/screens/analyst-session.js +7 -4
  127. package/dist/packages/cli/src/screens/analyst.js +3 -2
  128. package/dist/packages/cli/src/screens/autotrade-journey.js +134 -0
  129. package/dist/packages/cli/src/screens/autotrade-keys.js +182 -0
  130. package/dist/packages/cli/src/screens/autotrade-proposals.js +123 -0
  131. package/dist/packages/cli/src/screens/autotrade-screen.js +776 -0
  132. package/dist/packages/cli/src/screens/autotrade-ui.js +650 -0
  133. package/dist/packages/cli/src/screens/autotrade-worker.js +91 -0
  134. package/dist/packages/cli/src/screens/brain.js +37 -11
  135. package/dist/packages/cli/src/screens/overlay.js +5 -2
  136. package/dist/packages/cli/src/screens/plans.js +5 -17
  137. package/dist/packages/cli/src/screens/pnl-chip.js +9 -8
  138. package/dist/packages/cli/src/screens/positions.js +6 -28
  139. package/dist/packages/cli/src/screens/ticket.js +38 -205
  140. package/dist/packages/cli/src/screens/token.js +3 -3
  141. package/dist/packages/cli/src/state.js +25 -19
  142. package/dist/packages/cli/src/telegram-cmd.js +454 -0
  143. package/dist/packages/cli/src/trade.js +3 -128
  144. package/dist/packages/cli/src/version.js +1 -1
  145. package/dist/packages/cli/src/wallet-cmd.js +39 -340
  146. package/dist/packages/cli/src/wallet-command.js +8 -11
  147. package/dist/packages/cli/src/widgets.js +0 -12
  148. package/dist/packages/custom/src/config.js +20 -2
  149. package/dist/packages/custom/src/schema.js +35 -10
  150. package/dist/packages/custom/src/workspace.js +3 -3
  151. package/dist/packages/data/src/basis.js +191 -0
  152. package/dist/packages/data/src/detail.js +53 -2
  153. package/dist/packages/data/src/index.js +0 -14
  154. package/dist/packages/data/src/store.js +14 -5
  155. package/dist/packages/data/src/trade/agent/paper-desk.js +228 -16
  156. package/dist/packages/data/src/trade/agent/rendezvous.js +3 -2
  157. package/dist/packages/data/src/trade/bridge.js +4 -102
  158. package/dist/packages/data/src/trade/ledger/export.js +101 -0
  159. package/dist/packages/data/src/trade/ledger/file.js +135 -0
  160. package/dist/packages/data/src/trade/ledger/fold.js +191 -0
  161. package/dist/packages/data/src/trade/ledger/index.js +9 -0
  162. package/dist/packages/data/src/trade/ledger/schema.js +83 -0
  163. package/dist/packages/data/src/trade/ledger/sources.js +307 -0
  164. package/dist/packages/data/src/trade/ledger/stats.js +123 -0
  165. package/dist/packages/data/src/trade/ledger/tags.js +116 -0
  166. package/dist/packages/data/src/trade/ledger/view.js +51 -0
  167. package/dist/packages/data/src/trade/plans/index.js +0 -1
  168. package/dist/packages/data/src/trade/plans/service.js +3 -27
  169. package/dist/packages/mcp/assets/kb/app-help/autotrade-chat.md +48 -0
  170. package/dist/packages/mcp/assets/kb/app-help/autotrade-executor-kit.md +44 -0
  171. package/dist/packages/mcp/assets/kb/app-help/autotrade-journey.md +46 -0
  172. package/dist/packages/mcp/assets/kb/app-help/autotrade-limits.md +48 -0
  173. package/dist/packages/mcp/assets/kb/app-help/autotrade-parallel.md +42 -0
  174. package/dist/packages/mcp/assets/kb/app-help/autotrade-real-signal.md +45 -0
  175. package/dist/packages/mcp/assets/kb/app-help/autotrade-runner.md +35 -0
  176. package/dist/packages/mcp/assets/kb/app-help/autotrade-stop.md +37 -0
  177. package/dist/packages/mcp/assets/kb/app-help/autotrade-strategies.md +35 -0
  178. package/dist/packages/mcp/assets/kb/app-help/autotrade-telegram.md +40 -0
  179. package/dist/packages/mcp/assets/kb/app-help/chart-trade-markers.md +42 -0
  180. package/dist/packages/mcp/assets/kb/app-help/link-a-wallet.md +4 -10
  181. package/dist/packages/mcp/assets/kb/app-help/live-trading.md +38 -0
  182. package/dist/packages/mcp/assets/kb/app-help/live-yolo.md +34 -0
  183. package/dist/packages/mcp/assets/kb/app-help/order-plans.md +1 -1
  184. package/dist/packages/mcp/assets/kb/app-help/price-or-marketcap.md +5 -2
  185. package/dist/packages/mcp/assets/kb/app-help/screen-analyst.md +3 -0
  186. package/dist/packages/mcp/assets/kb/app-help/screen-autotrade.md +229 -0
  187. package/dist/packages/mcp/assets/kb/app-help/screen-kol.md +3 -0
  188. package/dist/packages/mcp/assets/kb/app-help/screen-newpairs.md +3 -0
  189. package/dist/packages/mcp/assets/kb/app-help/screen-positions.md +3 -0
  190. package/dist/packages/mcp/assets/kb/app-help/screen-screener.md +3 -0
  191. package/dist/packages/mcp/assets/kb/app-help/screen-token.md +3 -0
  192. package/dist/packages/mcp/assets/kb/app-help/screen-trending.md +3 -0
  193. package/dist/packages/mcp/assets/kb/app-help/screen-watchlist.md +3 -0
  194. package/dist/packages/mcp/assets/kb/app-help/standing-mandates.md +1 -1
  195. package/dist/packages/mcp/assets/kb/app-help/trade-ledger.md +54 -0
  196. package/dist/packages/mcp/assets/kb/app-help/use-local-model.md +38 -0
  197. package/dist/packages/mcp/assets/kb/docs/docs-agents-agent-paper-trading.md +4 -1
  198. package/dist/packages/mcp/assets/kb/docs/docs-agents-reading-your-trade-ledger.md +31 -0
  199. package/dist/packages/mcp/assets/kb/docs/docs-agents-untrusted-by-default.md +1 -1
  200. package/dist/packages/mcp/assets/kb/docs/docs-analyst-if-claude-is-missing.md +1 -1
  201. package/dist/packages/mcp/assets/kb/docs/docs-analyst-use-a-local-model-instead.md +27 -0
  202. package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-sees.md +2 -0
  203. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-backtests-and-their-limits.md +56 -0
  204. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-change-a-strategy-by-chat.md +51 -0
  205. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-checking-the-record-of-a-run.md +28 -0
  206. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-comparing-them.md +41 -0
  207. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-exits-and-wakes.md +76 -0
  208. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-how-a-stop-reaches-the-runner.md +32 -0
  209. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-on-the-q-screen.md +38 -0
  210. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-one-strategy-or-all-of-them.md +35 -0
  211. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-paper-accounts.md +50 -0
  212. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-presets.md +37 -0
  213. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-running-it-all-day.md +31 -0
  214. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-sessions-and-their-limits.md +31 -0
  215. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-several-strategies-at-once.md +33 -0
  216. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-stopping-it.md +37 -0
  217. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-strategies-and-presets.md +34 -0
  218. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-always-on-service.md +57 -0
  219. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-autotrade-json-file.md +48 -0
  220. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-heartbeat.md +27 -0
  221. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-run-file-and-the-heartbeat.md +34 -0
  222. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-runner-and-candidate-sessions.md +45 -0
  223. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-each-session-shows-first.md +31 -0
  224. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-costs-claude-usage-per-session.md +58 -0
  225. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-is-paper-self-directed.md +50 -0
  226. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-will-not-do.md +31 -0
  227. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-which-account-day-caps-and-the-usage-guard.md +44 -0
  228. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-your-strategies.md +37 -0
  229. package/dist/packages/mcp/assets/kb/docs/docs-autotrade.md +22 -0
  230. package/dist/packages/mcp/assets/kb/docs/docs-beginners-before-any-experimental-trading.md +2 -2
  231. package/dist/packages/mcp/assets/kb/docs/docs-beginners.md +1 -1
  232. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-1-ask-for-a-strategy.md +27 -0
  233. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-2-backtest-it-held-out-split.md +31 -0
  234. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-3-forward-test-it-on-live-data.md +44 -0
  235. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-4-promote-it-to-always-on-paper.md +36 -0
  236. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-5-real-only-if-you-choose.md +36 -0
  237. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-the-ladder.md +39 -0
  238. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-the-report.md +31 -0
  239. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-what-the-analyst-knows.md +30 -0
  240. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat.md +24 -0
  241. package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-markers.md +30 -0
  242. package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-y-axis.md +1 -1
  243. package/dist/packages/mcp/assets/kb/docs/docs-configuration-environment-variables.md +4 -1
  244. package/dist/packages/mcp/assets/kb/docs/docs-configuration-files-on-disk.md +1 -0
  245. package/dist/packages/mcp/assets/kb/docs/docs-configuration-headless-recorder-dexterm-record.md +3 -1
  246. package/dist/packages/mcp/assets/kb/docs/docs-configuration-price-display-mode.md +8 -6
  247. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-2-the-one-key-mirror-ticket-a-proposal.md +1 -1
  248. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-3-capped-auto-mirror-default-off-less.md +1 -1
  249. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-what-is-proven-what-is-not.md +1 -1
  250. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading.md +1 -1
  251. package/dist/packages/mcp/assets/kb/docs/docs-data-sources-recorded-history-and-retention.md +36 -0
  252. package/dist/packages/mcp/assets/kb/docs/docs-data-sources-sources.md +1 -0
  253. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-first-run.md +1 -1
  254. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-install.md +3 -3
  255. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-requirements.md +1 -1
  256. package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +1 -1
  257. package/dist/packages/mcp/assets/kb/docs/docs-going-real-executor-health.md +38 -0
  258. package/dist/packages/mcp/assets/kb/docs/docs-going-real-paper-vs-real.md +33 -0
  259. package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-digest.md +36 -0
  260. package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-executor-kit.md +48 -0
  261. package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-whole-path.md +37 -0
  262. package/dist/packages/mcp/assets/kb/docs/docs-going-real-what-dexterm-does-and-never-does.md +44 -0
  263. package/dist/packages/mcp/assets/kb/docs/docs-going-real-your-limits.md +77 -0
  264. package/dist/packages/mcp/assets/kb/docs/docs-going-real.md +24 -0
  265. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-changed-in-0-1-7.md +26 -0
  266. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-real-mode-your-strategy-s-trades-to-your.md +31 -0
  267. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-stopping.md +28 -0
  268. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-the-short-version.md +34 -0
  269. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-using-a-trading-bot-with-dexterm.md +31 -0
  270. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does-not-do.md +30 -0
  271. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does.md +29 -0
  272. package/dist/packages/mcp/assets/kb/docs/docs-live-trading.md +23 -0
  273. package/dist/packages/mcp/assets/kb/docs/docs-ollama-another-machine.md +28 -0
  274. package/dist/packages/mcp/assets/kb/docs/docs-ollama-autotrade-on-a-local-model.md +29 -0
  275. package/dist/packages/mcp/assets/kb/docs/docs-ollama-check-your-model-dexterm-ai-probe.md +38 -0
  276. package/dist/packages/mcp/assets/kb/docs/docs-ollama-how-we-checked.md +27 -0
  277. package/dist/packages/mcp/assets/kb/docs/docs-ollama-models-without-tool-calling.md +32 -0
  278. package/dist/packages/mcp/assets/kb/docs/docs-ollama-pick-the-engine-globally-or-per-surface.md +43 -0
  279. package/dist/packages/mcp/assets/kb/docs/docs-ollama-restriction-profiles.md +35 -0
  280. package/dist/packages/mcp/assets/kb/docs/docs-ollama-set-it-up-in-two-minutes.md +39 -0
  281. package/dist/packages/mcp/assets/kb/docs/docs-ollama-troubleshooting.md +35 -0
  282. package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-runs-on-a-local-model.md +39 -0
  283. package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-stays-outside-the-model.md +36 -0
  284. package/dist/packages/mcp/assets/kb/docs/docs-ollama-which-model.md +38 -0
  285. package/dist/packages/mcp/assets/kb/docs/docs-ollama-your-own-agent-on-the-local-model.md +28 -0
  286. package/dist/packages/mcp/assets/kb/docs/docs-ollama.md +28 -0
  287. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-letting-an-agent-paper-trade-experimental.md +3 -4
  288. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet-read-only.md +30 -0
  289. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-order-plans-and-standing-mandates.md +3 -4
  290. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-panic.md +4 -7
  291. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-paper-only-mandates.md +6 -7
  292. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-pnl-cards.md +7 -7
  293. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-safety-model.md +34 -0
  294. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-ticket.md +3 -4
  295. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-trade-ledger.md +42 -0
  296. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-wallet.md +4 -5
  297. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-trade-moments.md +4 -5
  298. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading.md +4 -5
  299. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-buy-and-sell-markers.md +37 -0
  300. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +2 -1
  301. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-receipts-what-your-executor-did.md +42 -0
  302. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-safety.md +34 -0
  303. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-set-it-up.md +47 -0
  304. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-the-channels.md +42 -0
  305. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-the-signal.md +48 -0
  306. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-what-it-is.md +35 -0
  307. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-what-it-will-not-do.md +34 -0
  308. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-where-you-see-it.md +34 -0
  309. package/dist/packages/mcp/assets/kb/docs/docs-real-mode.md +27 -0
  310. package/dist/packages/mcp/assets/kb/docs/docs-screens-autotrade-paper.md +26 -0
  311. package/dist/packages/mcp/assets/kb/docs/docs-screens-order-plans.md +1 -1
  312. package/dist/packages/mcp/assets/kb/docs/docs-screens-token-screen.md +2 -0
  313. package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-brain-view-and-the-pnl-chip.md +1 -1
  314. package/dist/packages/mcp/assets/kb/docs/docs-telegram-approve-one-tap-entries.md +50 -0
  315. package/dist/packages/mcp/assets/kb/docs/docs-telegram-control-the-commands.md +43 -0
  316. package/dist/packages/mcp/assets/kb/docs/docs-telegram-if-something-goes-wrong.md +30 -0
  317. package/dist/packages/mcp/assets/kb/docs/docs-telegram-notify-what-reaches-your-phone.md +41 -0
  318. package/dist/packages/mcp/assets/kb/docs/docs-telegram-set-it-up.md +47 -0
  319. package/dist/packages/mcp/assets/kb/docs/docs-telegram-the-record.md +26 -0
  320. package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-is.md +33 -0
  321. package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-will-not-do.md +31 -0
  322. package/dist/packages/mcp/assets/kb/docs/docs-telegram.md +23 -0
  323. package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-common-questions.md +1 -1
  324. package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-doctor-lines.md +4 -0
  325. package/dist/packages/mcp/assets/kb/docs/docs-voice-linux-and-windows.md +1 -1
  326. package/dist/packages/mcp/assets/kb/docs/docs-voice.md +1 -1
  327. package/dist/packages/mcp/assets/kb/docs/docs-yolo-1-replay-it-on-your-own-history.md +42 -0
  328. package/dist/packages/mcp/assets/kb/docs/docs-yolo-2-run-it-on-paper.md +34 -0
  329. package/dist/packages/mcp/assets/kb/docs/docs-yolo-3-watch-it-and-stop-it.md +32 -0
  330. package/dist/packages/mcp/assets/kb/docs/docs-yolo-the-rules.md +37 -0
  331. package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-is.md +34 -0
  332. package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-will-not-do.md +31 -0
  333. package/dist/packages/mcp/assets/kb/docs/docs-yolo.md +26 -0
  334. package/dist/packages/mcp/assets/kb/entries/autotrade.md +40 -0
  335. package/dist/packages/mcp/src/app-help.js +1 -1
  336. package/dist/packages/mcp/src/autotrade-tools.js +1107 -0
  337. package/dist/packages/mcp/src/backtest-requests.js +71 -0
  338. package/dist/packages/mcp/src/engine/config.js +159 -0
  339. package/dist/packages/mcp/src/engine/index.js +10 -0
  340. package/dist/packages/mcp/src/engine/loop.js +101 -0
  341. package/dist/packages/mcp/src/engine/mcp-client.js +123 -0
  342. package/dist/packages/mcp/src/engine/ollama.js +258 -0
  343. package/dist/packages/mcp/src/engine/probe.js +110 -0
  344. package/dist/packages/mcp/src/engine/reason.js +35 -0
  345. package/dist/packages/mcp/src/engine/restrictions.js +111 -0
  346. package/dist/packages/mcp/src/index.js +7 -1
  347. package/dist/packages/mcp/src/ledger-tools.js +494 -0
  348. package/dist/packages/mcp/src/paper-agent.js +2 -0
  349. package/dist/packages/mcp/src/server.js +138 -19
  350. package/dist/packages/packs/src/backtest.js +3 -1
  351. package/dist/packages/popup/src/pages/chart-lib.js +134 -21
  352. package/dist/packages/popup/src/pages/chart.css +9 -0
  353. package/dist/packages/popup/src/pages/chart.html +3 -1
  354. package/dist/packages/popup/src/pages/chart.js +104 -7
  355. package/dist/packages/popup/src/protocol.js +2 -0
  356. package/dist/packages/popup/src/server.js +4 -0
  357. package/dist/packages/recorder/src/index.js +2 -0
  358. package/dist/packages/recorder/src/recorder.js +63 -6
  359. package/dist/packages/recorder/src/retention.js +100 -0
  360. package/dist/packages/recorder/src/schema.js +34 -1
  361. package/dist/packages/recorder/src/ticks.js +237 -0
  362. package/dist/packages/tui/src/index.js +1 -0
  363. package/dist/packages/tui/src/keymap.js +28 -1
  364. package/dist/packages/tui/src/markers.js +219 -0
  365. package/dist/packages/tui/src/widgets.js +149 -2
  366. package/package.json +2 -1
  367. package/dist/packages/data/src/trade/caps.js +0 -323
  368. package/dist/packages/data/src/trade/executor.js +0 -933
  369. package/dist/packages/data/src/trade/plans/executor-live.js +0 -220
  370. package/dist/packages/data/src/trade/rpc-exec.js +0 -229
  371. package/dist/packages/data/src/trade/signer/client.js +0 -197
  372. package/dist/packages/data/src/trade/signer/fast-wallet.js +0 -154
  373. package/dist/packages/data/src/trade/signer/host.js +0 -97
  374. package/dist/packages/data/src/trade/signer/main.js +0 -121
  375. package/dist/packages/data/src/trade/signer/probe-builder.js +0 -85
  376. package/dist/packages/data/src/trade/signer/protocol.js +0 -92
  377. package/dist/packages/data/src/trade/signer/service.js +0 -400
  378. package/dist/packages/data/src/trade/signer/sol-usd-feed.js +0 -98
  379. package/dist/packages/data/src/trade/sol-usd.js +0 -86
  380. package/dist/packages/data/src/trade/swap-build.js +0 -108
  381. package/dist/packages/data/src/trade/token-delta.js +0 -201
  382. package/dist/packages/data/vendor/solana-web3/LICENSE +0 -20
  383. package/dist/packages/data/vendor/solana-web3/NOTICE.md +0 -13
  384. package/dist/packages/data/vendor/solana-web3/index.iife.min.js +0 -20
  385. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-a-live-ticket.md +0 -42
  386. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-before-you-press-size-vs-caps.md +0 -34
  387. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-devnet-signer-mainnet-token.md +0 -35
  388. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-jupiter-rate-limits.md +0 -33
  389. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet.md +0 -32
  390. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-live-trading-devnet-first.md +0 -30
  391. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-mainnet.md +0 -31
  392. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-live-fire-path-devnet-the-fast-wallet.md +0 -41
  393. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-signer-process.md +0 -34
  394. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-what-the-live-path-keeps.md +0 -37
  395. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-your-first-live-trade.md +0 -41
@@ -0,0 +1,216 @@
1
+ // `dexterm autotrade backtest|sweep|extract` (task-1503 AT-1, AUTOTRADE-SPEC §3/§3a). PAPER, recorded data only:
2
+ // the recorder DB is opened read-only, fills are modelled, no network, no model, no keys. Mechanical entries
3
+ // (`auto`): the agent's judgement is what the runner card measures, so a backtest never spawns a session.
4
+ import { dextermHome } from '../../../custom/src/index.js';
5
+ import { defaultDbPath } from '../../../data/src/index.js';
6
+ import { openHistoryReadOnly } from '../../../recorder/src/index.js';
7
+ import { backtest, backtestEvidence, everyCandidate, recordBacktestEvidence, renderHeldOut, fmtIssue, loadTape, renderRecall, renderReport, renderSweep, renderYoloReplay, builtinTapePath, runnerRecall, saveTape, sweep, tapeFromDb, tapeFromDoc, yoloReplay, } from '../../../autotrade/src/index.js';
8
+ import { parseArgs, resolveStrategyArg, storeFor } from "./strategies.js";
9
+ const BOOL = ['json', 'every-candidate', 'no-held-out'];
10
+ function strategyFrom(pos, opts, io, usage, anyMode = false) {
11
+ const arg = typeof opts.strategy === 'string' ? opts.strategy : pos[0];
12
+ const r = resolveStrategyArg(arg, io);
13
+ if (!r) {
14
+ io.stderr.write(`usage: ${usage}\n`);
15
+ return null;
16
+ }
17
+ for (const w of r.warnings)
18
+ io.stderr.write(`warning ${fmtIssue(w)}\n`);
19
+ if (!r.ok) {
20
+ for (const e of r.errors)
21
+ io.stderr.write(`error ${fmtIssue(e)}\n`);
22
+ return null;
23
+ }
24
+ if (r.strategy.mode !== 'paper' && !anyMode) {
25
+ io.stderr.write(`dexterm autotrade: ${r.strategy.id} is mode "${r.strategy.mode}": autotrade runs paper only\n`);
26
+ return null;
27
+ }
28
+ return r.strategy;
29
+ }
30
+ function numOpt(opts, k, dflt) {
31
+ const v = opts[k];
32
+ const n = typeof v === 'string' ? Number(v) : NaN;
33
+ return Number.isFinite(n) ? n : dflt;
34
+ }
35
+ /**
36
+ * `dexterm autotrade yolo-replay <id|file>` (task-1532): a full-port paper replay of a strategy (a live-mode copy too:
37
+ * the replay always runs a paper copy) over recorded history, with the rugs, the loss spread and how often a run of
38
+ * entries zeroed the wallet. Read-only: recorded data, modelled fills, no network, no model, no keys.
39
+ */
40
+ export async function yoloReplayCmd(argv, io) {
41
+ const { pos, opts } = parseArgs(argv, ['json']);
42
+ const usage = 'dexterm autotrade yolo-replay <id|file> [--tape FILE | --db PATH [--days N | --since T] [--until T]] [--seed N] [--json]';
43
+ const s = strategyFrom(pos, opts, io, usage, true);
44
+ if (!s)
45
+ return 2;
46
+ const tape = tapeFrom(opts, io);
47
+ if (!tape)
48
+ return 2;
49
+ const r = await yoloReplay(s, tape, { seed: numOpt(opts, 'seed', 1) });
50
+ io.stdout.write(opts.json ? JSON.stringify(r, null, 2) + '\n' : renderYoloReplay(r) + '\n');
51
+ return 0;
52
+ }
53
+ /** `--since/--until`: epoch ms or an ISO time (pins a backtest to the exact tape window of an earlier run). */
54
+ function timeOpt(v) {
55
+ if (typeof v !== 'string')
56
+ return undefined;
57
+ const n = /^\d+$/.test(v) ? Number(v) : Date.parse(v);
58
+ return Number.isFinite(n) ? n : undefined;
59
+ }
60
+ /** The recorder DB, read-only; null when it is missing, in memory, or not a recorder DB. */
61
+ function openDb(path) {
62
+ if (path === ':memory:')
63
+ return null;
64
+ try {
65
+ return openHistoryReadOnly(path);
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
71
+ /** A tape from --tape FILE, else read-only from the recorder DB (--db, DEXTERM_DB_PATH, the default path). */
72
+ export function tapeFrom(opts, io) {
73
+ if (typeof opts.tape === 'string') {
74
+ try {
75
+ return loadTape(builtinTapePath(opts.tape));
76
+ }
77
+ catch (e) {
78
+ io.stderr.write(`dexterm autotrade: ${e.message}\n`);
79
+ return null;
80
+ }
81
+ }
82
+ const path = typeof opts.db === 'string' ? opts.db : (io.env.DEXTERM_DB_PATH || defaultDbPath(io.env));
83
+ const db = openDb(path);
84
+ if (!db) {
85
+ io.stderr.write(`dexterm autotrade: no recorded history in ${path} (run the app with the recorder on first, or pass --tape FILE)\n`);
86
+ return null;
87
+ }
88
+ try {
89
+ const days = numOpt(opts, 'days', 0);
90
+ return tapeFromDoc(tapeFromDb(db, {
91
+ since: timeOpt(opts.since) ?? (days > 0 ? Date.now() - days * 86_400_000 : undefined),
92
+ until: timeOpt(opts.until),
93
+ minPeakLiqUsd: numOpt(opts, 'min-peak-liq', 20_000),
94
+ spanHours: numOpt(opts, 'span-hours', 80),
95
+ }));
96
+ }
97
+ finally {
98
+ db.close();
99
+ }
100
+ }
101
+ export async function backtestCmd(argv, io) {
102
+ const { pos, opts } = parseArgs(argv, BOOL);
103
+ const usage = 'dexterm autotrade backtest <id|file> [--tape FILE | --db PATH] [--days N | --since T] [--until T] [--every-candidate [--unit-usd 20]] [--recall 5,10] [--no-held-out] [--json]';
104
+ const arg = typeof opts.strategy === 'string' ? opts.strategy : pos[0];
105
+ const s0 = strategyFrom(pos, opts, io, usage);
106
+ if (!s0)
107
+ return 2;
108
+ const tape = tapeFrom(opts, io);
109
+ if (!tape)
110
+ return 2;
111
+ const s = opts['every-candidate'] ? everyCandidate(s0, numOpt(opts, 'unit-usd', 20)) : s0;
112
+ const { report, run } = await backtest(s, tape);
113
+ const recallAt = typeof opts.recall === 'string' ? opts.recall.split(',').map(Number).filter((x) => Number.isFinite(x) && x > 1) : [];
114
+ const recall = recallAt.length ? runnerRecall(s, tape, run, recallAt) : null;
115
+ if (!opts['every-candidate']) {
116
+ try {
117
+ storeFor(io).recordBacktest({ hash: s.hash, t: Date.now(), trades: report.trades, netUsd: report.netUsd, netPct: report.netPct, maxDrawdownPct: report.maxDrawdownPct, tape: `${report.tape.mints} coins ${report.tape.from ?? ''}..${report.tape.to ?? ''}` });
118
+ }
119
+ catch { /* the line is a convenience for `list`; never fail a backtest on it */ }
120
+ }
121
+ // task-1647: a stored strategy's backtest is journey evidence: the same rules on each half of the held-out split.
122
+ let evidence = null;
123
+ const stored = !!arg && !opts['every-candidate'] && !opts['no-held-out'] && storeFor(io).get(arg)?.ok === true && arg === s.id;
124
+ if (stored) {
125
+ const days = numOpt(opts, 'days', 0);
126
+ evidence = (await backtestEvidence(s, tape, { by: 'user', days: days > 0 ? days : null, full: { report, run } })).evidence;
127
+ try {
128
+ recordBacktestEvidence(dextermHome(io.env), evidence);
129
+ }
130
+ catch (e) {
131
+ io.stderr.write(`warning: the journey record was not written (${e.message})\n`);
132
+ }
133
+ }
134
+ if (opts.json) {
135
+ io.stdout.write(JSON.stringify({ ...report, ...(recall ? { recall } : {}), ...(evidence ? { heldOut: evidence.heldOut, evidence: { verdict: evidence.verdict, claim: evidence.claim, rulesHash: evidence.rulesHash } } : {}) }, null, 2) + '\n');
136
+ return 0;
137
+ }
138
+ io.stdout.write(renderReport(report) + '\n');
139
+ if (evidence)
140
+ io.stdout.write(renderHeldOut(evidence).join('\n') + `\n journey: recorded as the backtest of ${s.id} v${s.version} (dexterm autotrade journey ${s.id})\n`);
141
+ if (opts['every-candidate'])
142
+ io.stdout.write(` every-candidate copy of ${s0.id}: each candidate entered at $${numOpt(opts, 'unit-usd', 20)} with the book caps lifted (an evaluation, not a strategy to run)\n`);
143
+ if (recall)
144
+ io.stdout.write(renderRecall(recall, s) + '\n');
145
+ io.stdout.write(' Paper only, recorded data, not financial advice. A backtest is not a forecast.\n');
146
+ return 0;
147
+ }
148
+ export async function sweepCmd(argv, io) {
149
+ const { pos, opts } = parseArgs(argv, BOOL);
150
+ const usage = 'dexterm autotrade sweep <id|file> [--tape FILE | --db PATH] [--grid JSON] [--mode grid|random] [--max N] [--seed N] [--test-frac 0.3] [--json]';
151
+ const s0 = strategyFrom(pos, opts, io, usage);
152
+ if (!s0)
153
+ return 2;
154
+ let grid;
155
+ try {
156
+ grid = typeof opts.grid === 'string' ? JSON.parse(opts.grid) : defaultGrid(s0);
157
+ if (!grid || typeof grid !== 'object' || !Object.values(grid).every((v) => Array.isArray(v) && v.every((x) => typeof x === 'number')))
158
+ throw new Error('the grid maps parameter paths to arrays of numbers');
159
+ }
160
+ catch (e) {
161
+ io.stderr.write(`dexterm autotrade: --grid: ${e.message}\n`);
162
+ return 2;
163
+ }
164
+ const tape = tapeFrom(opts, io);
165
+ if (!tape)
166
+ return 2;
167
+ const s = opts['every-candidate'] ? everyCandidate(s0, numOpt(opts, 'unit-usd', 20)) : s0;
168
+ let r;
169
+ try {
170
+ r = await sweep(s, tape, grid, { mode: opts.mode === 'random' ? 'random' : 'grid', max: numOpt(opts, 'max', 64), seed: numOpt(opts, 'seed', 1), testFrac: numOpt(opts, 'test-frac', 0.3) });
171
+ }
172
+ catch (e) {
173
+ io.stderr.write(`dexterm autotrade: ${e.message}\n`);
174
+ return 2;
175
+ }
176
+ io.stdout.write(opts.json ? JSON.stringify(r, null, 2) + '\n' : renderSweep(r) + '\n Paper only, recorded data, not financial advice.\n');
177
+ return 0;
178
+ }
179
+ /** A small default grid on the default exit profile's own knobs (only the ones the profile has). */
180
+ export function defaultGrid(s) {
181
+ const p = s.exits.profiles[s.exits.default];
182
+ const g = {};
183
+ if (p.trailingStop)
184
+ g['profile.trailingStop.trailPct'] = [15, 25, 35];
185
+ if (p.tpLadder.length)
186
+ g['profile.tpLadder.0.atPct'] = [30, 50, 80];
187
+ if (p.costRecovery)
188
+ g['profile.costRecovery.atPct'] = [60, 100, 150];
189
+ if (p.bagTrail)
190
+ g['profile.bagTrail.trailPct'] = [35, 55, 75];
191
+ if (s.sizing.mode === 'pct' && s.sizing.pct !== undefined)
192
+ g['sizing.pct'] = [s.sizing.pct / 2, s.sizing.pct].map((x) => Math.round(x * 10) / 10);
193
+ return g;
194
+ }
195
+ export function extractCmd(argv, io) {
196
+ const { opts } = parseArgs(argv);
197
+ if (typeof opts.out !== 'string') {
198
+ io.stderr.write('usage: dexterm autotrade extract --out FILE [--db PATH] [--max-mints N] [--min-peak-liq USD] [--span-hours H]\n');
199
+ return 2;
200
+ }
201
+ const path = typeof opts.db === 'string' ? opts.db : (io.env.DEXTERM_DB_PATH || defaultDbPath(io.env));
202
+ const db = openDb(path);
203
+ if (!db) {
204
+ io.stderr.write(`dexterm autotrade: no recorded history in ${path}\n`);
205
+ return 2;
206
+ }
207
+ try {
208
+ const doc = tapeFromDb(db, { maxMints: typeof opts['max-mints'] === 'string' ? Number(opts['max-mints']) : undefined, minPeakLiqUsd: numOpt(opts, 'min-peak-liq', 20_000), spanHours: numOpt(opts, 'span-hours', 80) });
209
+ saveTape(opts.out, doc);
210
+ io.stdout.write(`wrote ${opts.out}: ${doc.mints.length} coins, ${doc.mints.reduce((a, m) => a + m.rows.length, 0)} rows (recorded market data only)\n`);
211
+ return 0;
212
+ }
213
+ finally {
214
+ db.close();
215
+ }
216
+ }
@@ -0,0 +1,91 @@
1
+ // `dexterm autotrade executor …` (task-1654, 0.2.0 card E): is YOUR executor alive?
2
+ //
3
+ // status the last heartbeat, the last receipt, the receipt lag, and whether a real run would pause new buys now
4
+ // heartbeat append one heartbeat (for executors that prefer to shell out; the kit appends or POSTs its own)
5
+ // kit copy the executor reference kit (webhook / signal-cmd / JSONL tail, all dry run) to a folder of yours
6
+ //
7
+ // A heartbeat is data: it can only keep new buy signals from pausing. It cannot raise a limit, lift the kill switch,
8
+ // reset the breaker or confirm a position (receipts do that, and only as data).
9
+ import { copyFileSync, existsSync, mkdirSync, readdirSync } from 'node:fs';
10
+ import { join, resolve } from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { dextermHome } from '../../../custom/src/index.js';
13
+ import { Outbox, appendHeartbeat, effectiveLimits, executorHealth, healthLine, heartbeatPath, loadLimits, readReceipts, ACCOUNT_ID_RE } from '../../../autotrade/src/index.js';
14
+ import { parseArgs } from "./strategies.js";
15
+ /** The kit inside the app (shipped in the npm package too: build-dist copies examples/). */
16
+ export const KIT_DIR = fileURLToPath(new URL('../../../autotrade/examples/executor/', import.meta.url));
17
+ const out = (io, s) => { io.stdout.write(`${s}\n`); };
18
+ const err = (io, s) => { io.stderr.write(`dexterm autotrade executor: ${s}\n`); };
19
+ export async function executorCmd(argv, io, deps = {}) {
20
+ const home = dextermHome(io.env);
21
+ const now = deps.now ?? Date.now;
22
+ const { pos, opts } = parseArgs(argv.slice(1), ['json', 'dry-run']);
23
+ switch (argv[0]) {
24
+ case undefined:
25
+ case 'help':
26
+ out(io, 'dexterm autotrade executor status [--json] | heartbeat [--name N] [--account ID] [--dry-run] [--nonce N] [--note TEXT] | kit --out DIR');
27
+ return 0;
28
+ case 'kit': {
29
+ if (typeof opts.out !== 'string') {
30
+ err(io, 'kit --out DIR (a new or empty folder)');
31
+ return 2;
32
+ }
33
+ const dir = resolve(opts.out);
34
+ if (existsSync(dir) && readdirSync(dir).length) {
35
+ err(io, `${dir} is not empty`);
36
+ return 1;
37
+ }
38
+ mkdirSync(dir, { recursive: true });
39
+ const files = readdirSync(KIT_DIR).filter((f) => /\.(mjs|md)$/.test(f));
40
+ for (const f of files)
41
+ copyFileSync(join(KIT_DIR, f), join(dir, f));
42
+ out(io, `executor reference kit (DRY RUN: it logs what it would do; no wallet code) copied to ${dir}: ${files.join(', ')}`);
43
+ out(io, ` start one: node ${join(dir, 'webhook-executor.mjs')} --account main`);
44
+ out(io, ' wire it: dexterm autotrade signal channels --webhook http://127.0.0.1:8787/signal');
45
+ out(io, ' prove it: dexterm autotrade signal test (then dexterm autotrade executor status)');
46
+ return 0;
47
+ }
48
+ case 'status': {
49
+ const l = loadLimits(home);
50
+ const e = effectiveLimits(l.ok ? l.doc : null, { strategyId: '-', accountId: '-', mode: 'real' });
51
+ const ob = Outbox.open(home, { channels: [], noLock: true });
52
+ const h = executorHealth(home, { now: now(), windowMin: e.values.executorSilenceMin ?? null, signal: (n) => ob.get(n), receipts: readReceipts(home).receipts });
53
+ if (opts.json) {
54
+ out(io, JSON.stringify(h, null, 2));
55
+ return 0;
56
+ }
57
+ out(io, `executor ${healthLine(h)}`);
58
+ out(io, ` heartbeats: ${heartbeatPath(home)} (append, POST to the run's listener, or dexterm autotrade executor heartbeat)`);
59
+ if (h.alive === false)
60
+ out(io, ' a real run would PAUSE new buy signals now (exits still go out); start your executor, then dexterm autotrade signal test');
61
+ return 0;
62
+ }
63
+ case 'heartbeat': {
64
+ if (pos.length) {
65
+ err(io, `unexpected ${pos.join(' ')}`);
66
+ return 2;
67
+ }
68
+ const accountId = typeof opts.account === 'string' ? opts.account : null;
69
+ if (accountId && !ACCOUNT_ID_RE.test(accountId)) {
70
+ err(io, '--account: lowercase letters, digits, - and _');
71
+ return 2;
72
+ }
73
+ const nonce = opts.nonce === undefined ? null : Number(opts.nonce);
74
+ try {
75
+ const hb = appendHeartbeat(home, { at: now(), executor: typeof opts.name === 'string' ? opts.name : 'cli', accountId, dryRun: opts['dry-run'] === true ? true : null, lastNonce: nonce, note: typeof opts.note === 'string' ? opts.note : null });
76
+ if (opts.json)
77
+ out(io, JSON.stringify(hb));
78
+ else
79
+ out(io, `heartbeat from ${hb.executor} recorded`);
80
+ return 0;
81
+ }
82
+ catch (e) {
83
+ err(io, e.message);
84
+ return 2;
85
+ }
86
+ }
87
+ default:
88
+ err(io, `unknown subcommand ${JSON.stringify(argv[0])}`);
89
+ return 2;
90
+ }
91
+ }
@@ -0,0 +1,64 @@
1
+ // `dexterm autotrade flatten` (task-1509 AT-7, AUTOTRADE-SPEC §6.3). PAPER ONLY.
2
+ //
3
+ // A stop (no new entries, sessions closed, orders dropped), then every paper position sells at its next tick; one
4
+ // that cannot sell (a pulled pool) stays stuck and is retried every tick. The runner ends once nothing is held. It
5
+ // asks for a y keypress on a real terminal first, or takes `--yes` (selling only lowers risk; nothing here can buy,
6
+ // arm a mandate or sign). Nothing here touches a wallet, a key or the signer.
7
+ import { dextermHome } from '../../../custom/src/index.js';
8
+ import { activeRunner } from '../../../autotrade/src/index.js';
9
+ import { parseArgs } from "./strategies.js";
10
+ import { sendControl, waitArg } from "./stop.js";
11
+ export const FLATTEN_USAGE = 'dexterm autotrade flatten [--strategy ID] [--yes] [--wait SEC] [--json]';
12
+ export async function flattenCmd(argv, io, over = {}) {
13
+ const { pos, opts } = parseArgs(argv, ['json', 'yes']);
14
+ if (pos.length) {
15
+ io.stderr.write(`usage: ${FLATTEN_USAGE}\n`);
16
+ return 2;
17
+ }
18
+ const home = dextermHome(io.env);
19
+ const member = typeof opts.strategy === 'string' ? opts.strategy : null;
20
+ const r = activeRunner(home);
21
+ if (!r) {
22
+ if (opts.json)
23
+ io.stdout.write(`${JSON.stringify({ requested: false, runId: null, why: 'no autotrade runner is running' })}\n`);
24
+ else
25
+ io.stdout.write('no autotrade runner is running; nothing to flatten.\n');
26
+ return 0;
27
+ }
28
+ if (!opts.yes) {
29
+ const stdin = io.stdin;
30
+ if (!stdin || stdin.isTTY !== true) {
31
+ io.stderr.write('dexterm autotrade flatten: confirm with y on a real terminal, or pass --yes\n');
32
+ return 2;
33
+ }
34
+ io.stdout.write(member ? `flatten strategy ${member} only: stop it, then sell its paper positions at their next tick (the other strategies keep running)? y to confirm, any other key cancels… `
35
+ : `flatten run ${r.runId}: stop, then sell every paper position at its next tick (${r.positions} open)? y to confirm, any other key cancels… `);
36
+ const { ttyKeypress } = await import("../wallet-cmd.js");
37
+ const key = await ttyKeypress(stdin, over.keypressTimeoutMs ?? 30_000);
38
+ io.stdout.write('\n');
39
+ if (key !== 'y' && key !== 'Y') {
40
+ io.stdout.write('flatten cancelled; nothing was sold\n');
41
+ return 1;
42
+ }
43
+ }
44
+ // task-1529: one strategy of a parallel run; the others keep running.
45
+ if (member)
46
+ return (await import("./strategy-control.js")).memberStopCmd(io, member, 'flatten', opts);
47
+ const res = await sendControl(io, 'flatten', waitArg(opts.wait), r);
48
+ if ('error' in res) {
49
+ io.stderr.write(`dexterm autotrade flatten: ${res.error}\n`);
50
+ return 1;
51
+ }
52
+ if (opts.json) {
53
+ io.stdout.write(`${JSON.stringify(res)}\n`);
54
+ return 0;
55
+ }
56
+ io.stdout.write(`flatten ${res.already ? 'was already requested' : 'requested'} for run ${r.runId} (pid ${r.pid})\n`);
57
+ if (!res.acknowledged)
58
+ io.stdout.write('the runner has not confirmed yet: it reads the request on its next tick. Watch the Q screen, or run this again.\n');
59
+ else if (res.ended)
60
+ io.stdout.write('✓ flat: the runner sold what it held and stopped\n');
61
+ else
62
+ io.stdout.write(`✓ flattening: no new entries, sessions closed; ${res.positions} paper position${res.positions === 1 ? '' : 's'} sell${res.positions === 1 ? 's' : ''} at the next tick (a stuck one is retried every tick)\n`);
63
+ return 0;
64
+ }