dexterm-cli 0.1.6 → 0.1.7

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 (331) hide show
  1. package/dist/packages/agents/src/schema.js +22 -1
  2. package/dist/packages/agents/src/story.js +11 -2
  3. package/dist/packages/agents/src/tiers.js +27 -2
  4. package/dist/packages/agents/src/tools.js +30 -2
  5. package/dist/packages/autotrade/assets/exit-profile.schema.json +492 -0
  6. package/dist/packages/autotrade/assets/profiles/moonbag.json +46 -0
  7. package/dist/packages/autotrade/assets/profiles/runner.json +88 -0
  8. package/dist/packages/autotrade/assets/profiles/scalp.json +88 -0
  9. package/dist/packages/autotrade/assets/profiles/swing.json +88 -0
  10. package/dist/packages/autotrade/assets/strategies/moonbag.json +101 -0
  11. package/dist/packages/autotrade/assets/strategies/runner.json +101 -0
  12. package/dist/packages/autotrade/assets/strategies/sample-dip-ladder.json +188 -0
  13. package/dist/packages/autotrade/assets/strategies/scalp.json +98 -0
  14. package/dist/packages/autotrade/assets/strategies/swing.json +97 -0
  15. package/dist/packages/autotrade/assets/strategies/yolo.json +157 -0
  16. package/dist/packages/autotrade/assets/tapes/yolo-rehearsal.json +1 -0
  17. package/dist/packages/autotrade/src/account.js +74 -0
  18. package/dist/packages/autotrade/src/backtest.js +357 -0
  19. package/dist/packages/autotrade/src/basis-text.js +32 -0
  20. package/dist/packages/autotrade/src/chat/approvals.js +484 -0
  21. package/dist/packages/autotrade/src/chat/audit.js +140 -0
  22. package/dist/packages/autotrade/src/chat/config.js +93 -0
  23. package/dist/packages/autotrade/src/chat/connector.js +24 -0
  24. package/dist/packages/autotrade/src/chat/control.js +103 -0
  25. package/dist/packages/autotrade/src/chat/fake.js +100 -0
  26. package/dist/packages/autotrade/src/chat/format.js +71 -0
  27. package/dist/packages/autotrade/src/chat/hub.js +187 -0
  28. package/dist/packages/autotrade/src/chat/index.js +18 -0
  29. package/dist/packages/autotrade/src/chat/notify.js +292 -0
  30. package/dist/packages/autotrade/src/chat/pairing.js +46 -0
  31. package/dist/packages/autotrade/src/chat/redact.js +48 -0
  32. package/dist/packages/autotrade/src/chat/secrets.js +99 -0
  33. package/dist/packages/autotrade/src/chat/service.js +248 -0
  34. package/dist/packages/autotrade/src/chat/telegram.js +290 -0
  35. package/dist/packages/autotrade/src/desk-executor.js +188 -0
  36. package/dist/packages/autotrade/src/engine.js +387 -0
  37. package/dist/packages/autotrade/src/execution-port.js +97 -0
  38. package/dist/packages/autotrade/src/fleet-config.js +169 -0
  39. package/dist/packages/autotrade/src/fleet-control.js +276 -0
  40. package/dist/packages/autotrade/src/fleet.js +639 -0
  41. package/dist/packages/autotrade/src/index.js +53 -0
  42. package/dist/packages/autotrade/src/ledger.js +108 -0
  43. package/dist/packages/autotrade/src/live-source.js +182 -0
  44. package/dist/packages/autotrade/src/monitor-daemon.js +715 -0
  45. package/dist/packages/autotrade/src/monitor.js +190 -0
  46. package/dist/packages/autotrade/src/ollama-sessions.js +137 -0
  47. package/dist/packages/autotrade/src/paper-accounts.js +72 -0
  48. package/dist/packages/autotrade/src/replay.js +198 -0
  49. package/dist/packages/autotrade/src/runner-config.js +99 -0
  50. package/dist/packages/autotrade/src/runner.js +872 -0
  51. package/dist/packages/autotrade/src/safety.js +243 -0
  52. package/dist/packages/autotrade/src/session.js +269 -0
  53. package/dist/packages/autotrade/src/sessions.js +503 -0
  54. package/dist/packages/autotrade/src/store.js +250 -0
  55. package/dist/packages/autotrade/src/strategy.js +256 -0
  56. package/dist/packages/autotrade/src/trade-ledger.js +241 -0
  57. package/dist/packages/autotrade/src/yolo.js +140 -0
  58. package/dist/packages/cli/assets/claude/analyst-system.md +4 -4
  59. package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +1 -1
  60. package/dist/packages/cli/src/ai-cmd.js +412 -0
  61. package/dist/packages/cli/src/analyst/backend.js +82 -15
  62. package/dist/packages/cli/src/analyst/codex.js +14 -9
  63. package/dist/packages/cli/src/analyst/ollama.js +263 -0
  64. package/dist/packages/cli/src/analyst/session.js +5 -2
  65. package/dist/packages/cli/src/app-help-gen.js +44 -8
  66. package/dist/packages/cli/src/autotrade-cmd/audit.js +57 -0
  67. package/dist/packages/cli/src/autotrade-cmd/backtest.js +199 -0
  68. package/dist/packages/cli/src/autotrade-cmd/flatten.js +64 -0
  69. package/dist/packages/cli/src/autotrade-cmd/fleet.js +397 -0
  70. package/dist/packages/cli/src/autotrade-cmd/requests.js +79 -0
  71. package/dist/packages/cli/src/autotrade-cmd/run.js +413 -0
  72. package/dist/packages/cli/src/autotrade-cmd/stop.js +76 -0
  73. package/dist/packages/cli/src/autotrade-cmd/strategies.js +198 -0
  74. package/dist/packages/cli/src/autotrade-cmd/strategy-control.js +174 -0
  75. package/dist/packages/cli/src/autotrade-cmd/telegram-host.js +101 -0
  76. package/dist/packages/cli/src/autotrade-cmd.js +168 -0
  77. package/dist/packages/cli/src/display.js +156 -17
  78. package/dist/packages/cli/src/doctor.js +62 -3
  79. package/dist/packages/cli/src/export.js +10 -2
  80. package/dist/packages/cli/src/index.js +1 -1
  81. package/dist/packages/cli/src/ledger-cmd.js +288 -0
  82. package/dist/packages/cli/src/live/chart-fills.js +46 -0
  83. package/dist/packages/cli/src/live/index.js +23 -89
  84. package/dist/packages/cli/src/live/screens/token-live.js +9 -6
  85. package/dist/packages/cli/src/live/trade.js +12 -457
  86. package/dist/packages/cli/src/live/watchlist.js +1 -1
  87. package/dist/packages/cli/src/main.js +147 -190
  88. package/dist/packages/cli/src/mcp-cmd.js +7 -1
  89. package/dist/packages/cli/src/plan-cmd.js +1 -1
  90. package/dist/packages/cli/src/pnl-app.js +31 -21
  91. package/dist/packages/cli/src/pnl-card.js +158 -21
  92. package/dist/packages/cli/src/popup.js +22 -6
  93. package/dist/packages/cli/src/record-cmd.js +141 -20
  94. package/dist/packages/cli/src/screens/agent-hud.js +34 -2
  95. package/dist/packages/cli/src/screens/analyst-session.js +7 -4
  96. package/dist/packages/cli/src/screens/analyst.js +3 -2
  97. package/dist/packages/cli/src/screens/autotrade-keys.js +169 -0
  98. package/dist/packages/cli/src/screens/autotrade-proposals.js +123 -0
  99. package/dist/packages/cli/src/screens/autotrade-screen.js +725 -0
  100. package/dist/packages/cli/src/screens/autotrade-ui.js +640 -0
  101. package/dist/packages/cli/src/screens/autotrade-worker.js +89 -0
  102. package/dist/packages/cli/src/screens/brain.js +37 -11
  103. package/dist/packages/cli/src/screens/overlay.js +5 -2
  104. package/dist/packages/cli/src/screens/plans.js +5 -17
  105. package/dist/packages/cli/src/screens/pnl-chip.js +9 -8
  106. package/dist/packages/cli/src/screens/positions.js +6 -28
  107. package/dist/packages/cli/src/screens/ticket.js +38 -205
  108. package/dist/packages/cli/src/screens/token.js +3 -3
  109. package/dist/packages/cli/src/state.js +25 -19
  110. package/dist/packages/cli/src/telegram-cmd.js +451 -0
  111. package/dist/packages/cli/src/trade.js +3 -128
  112. package/dist/packages/cli/src/version.js +1 -1
  113. package/dist/packages/cli/src/wallet-cmd.js +39 -340
  114. package/dist/packages/cli/src/wallet-command.js +8 -11
  115. package/dist/packages/cli/src/widgets.js +0 -12
  116. package/dist/packages/custom/src/config.js +20 -2
  117. package/dist/packages/custom/src/schema.js +35 -10
  118. package/dist/packages/custom/src/workspace.js +3 -3
  119. package/dist/packages/data/src/basis.js +191 -0
  120. package/dist/packages/data/src/detail.js +53 -2
  121. package/dist/packages/data/src/index.js +0 -14
  122. package/dist/packages/data/src/store.js +14 -5
  123. package/dist/packages/data/src/trade/agent/paper-desk.js +228 -16
  124. package/dist/packages/data/src/trade/agent/rendezvous.js +3 -2
  125. package/dist/packages/data/src/trade/bridge.js +4 -102
  126. package/dist/packages/data/src/trade/ledger/export.js +101 -0
  127. package/dist/packages/data/src/trade/ledger/file.js +135 -0
  128. package/dist/packages/data/src/trade/ledger/fold.js +191 -0
  129. package/dist/packages/data/src/trade/ledger/index.js +9 -0
  130. package/dist/packages/data/src/trade/ledger/schema.js +83 -0
  131. package/dist/packages/data/src/trade/ledger/sources.js +307 -0
  132. package/dist/packages/data/src/trade/ledger/stats.js +123 -0
  133. package/dist/packages/data/src/trade/ledger/tags.js +116 -0
  134. package/dist/packages/data/src/trade/ledger/view.js +51 -0
  135. package/dist/packages/data/src/trade/plans/index.js +0 -1
  136. package/dist/packages/data/src/trade/plans/service.js +3 -27
  137. package/dist/packages/mcp/assets/kb/app-help/autotrade-chat.md +48 -0
  138. package/dist/packages/mcp/assets/kb/app-help/autotrade-parallel.md +42 -0
  139. package/dist/packages/mcp/assets/kb/app-help/autotrade-runner.md +35 -0
  140. package/dist/packages/mcp/assets/kb/app-help/autotrade-stop.md +37 -0
  141. package/dist/packages/mcp/assets/kb/app-help/autotrade-strategies.md +35 -0
  142. package/dist/packages/mcp/assets/kb/app-help/autotrade-telegram.md +40 -0
  143. package/dist/packages/mcp/assets/kb/app-help/chart-trade-markers.md +42 -0
  144. package/dist/packages/mcp/assets/kb/app-help/link-a-wallet.md +4 -10
  145. package/dist/packages/mcp/assets/kb/app-help/live-trading.md +38 -0
  146. package/dist/packages/mcp/assets/kb/app-help/live-yolo.md +34 -0
  147. package/dist/packages/mcp/assets/kb/app-help/order-plans.md +1 -1
  148. package/dist/packages/mcp/assets/kb/app-help/price-or-marketcap.md +5 -2
  149. package/dist/packages/mcp/assets/kb/app-help/screen-analyst.md +3 -0
  150. package/dist/packages/mcp/assets/kb/app-help/screen-autotrade.md +217 -0
  151. package/dist/packages/mcp/assets/kb/app-help/screen-kol.md +3 -0
  152. package/dist/packages/mcp/assets/kb/app-help/screen-newpairs.md +3 -0
  153. package/dist/packages/mcp/assets/kb/app-help/screen-positions.md +3 -0
  154. package/dist/packages/mcp/assets/kb/app-help/screen-screener.md +3 -0
  155. package/dist/packages/mcp/assets/kb/app-help/screen-token.md +3 -0
  156. package/dist/packages/mcp/assets/kb/app-help/screen-trending.md +3 -0
  157. package/dist/packages/mcp/assets/kb/app-help/screen-watchlist.md +3 -0
  158. package/dist/packages/mcp/assets/kb/app-help/standing-mandates.md +1 -1
  159. package/dist/packages/mcp/assets/kb/app-help/trade-ledger.md +54 -0
  160. package/dist/packages/mcp/assets/kb/app-help/use-local-model.md +38 -0
  161. package/dist/packages/mcp/assets/kb/docs/docs-agents-agent-paper-trading.md +4 -1
  162. package/dist/packages/mcp/assets/kb/docs/docs-agents-reading-your-trade-ledger.md +31 -0
  163. package/dist/packages/mcp/assets/kb/docs/docs-agents-untrusted-by-default.md +1 -1
  164. package/dist/packages/mcp/assets/kb/docs/docs-analyst-if-claude-is-missing.md +1 -1
  165. package/dist/packages/mcp/assets/kb/docs/docs-analyst-use-a-local-model-instead.md +27 -0
  166. package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-sees.md +2 -0
  167. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-backtests-and-their-limits.md +56 -0
  168. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-change-a-strategy-by-chat.md +49 -0
  169. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-checking-the-record-of-a-run.md +28 -0
  170. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-comparing-them.md +41 -0
  171. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-exits-and-wakes.md +76 -0
  172. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-how-a-stop-reaches-the-runner.md +32 -0
  173. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-on-the-q-screen.md +37 -0
  174. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-one-strategy-or-all-of-them.md +35 -0
  175. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-paper-accounts.md +50 -0
  176. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-presets.md +37 -0
  177. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-running-it-all-day.md +31 -0
  178. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-sessions-and-their-limits.md +31 -0
  179. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-several-strategies-at-once.md +33 -0
  180. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-stopping-it.md +35 -0
  181. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-strategies-and-presets.md +34 -0
  182. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-autotrade-json-file.md +48 -0
  183. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-heartbeat.md +27 -0
  184. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-run-file-and-the-heartbeat.md +34 -0
  185. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-runner-and-candidate-sessions.md +45 -0
  186. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-each-session-shows-first.md +31 -0
  187. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-costs-claude-usage-per-session.md +58 -0
  188. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-is-paper-self-directed.md +43 -0
  189. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-will-not-do.md +31 -0
  190. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-which-account-day-caps-and-the-usage-guard.md +44 -0
  191. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-your-strategies.md +37 -0
  192. package/dist/packages/mcp/assets/kb/docs/docs-autotrade.md +22 -0
  193. package/dist/packages/mcp/assets/kb/docs/docs-beginners-before-any-experimental-trading.md +2 -2
  194. package/dist/packages/mcp/assets/kb/docs/docs-beginners.md +1 -1
  195. package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-markers.md +30 -0
  196. package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-y-axis.md +1 -1
  197. package/dist/packages/mcp/assets/kb/docs/docs-configuration-environment-variables.md +4 -1
  198. package/dist/packages/mcp/assets/kb/docs/docs-configuration-files-on-disk.md +1 -0
  199. package/dist/packages/mcp/assets/kb/docs/docs-configuration-headless-recorder-dexterm-record.md +3 -1
  200. package/dist/packages/mcp/assets/kb/docs/docs-configuration-price-display-mode.md +8 -6
  201. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-2-the-one-key-mirror-ticket-a-proposal.md +1 -1
  202. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-3-capped-auto-mirror-default-off-less.md +1 -1
  203. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-what-is-proven-what-is-not.md +1 -1
  204. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading.md +1 -1
  205. package/dist/packages/mcp/assets/kb/docs/docs-data-sources-recorded-history-and-retention.md +36 -0
  206. package/dist/packages/mcp/assets/kb/docs/docs-data-sources-sources.md +1 -0
  207. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-first-run.md +1 -1
  208. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-install.md +3 -3
  209. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-requirements.md +1 -1
  210. package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +1 -1
  211. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-changed-in-0-1-7.md +26 -0
  212. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-stopping.md +28 -0
  213. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-the-short-version.md +34 -0
  214. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-using-a-trading-bot-with-dexterm.md +33 -0
  215. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does-not-do.md +30 -0
  216. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does.md +29 -0
  217. package/dist/packages/mcp/assets/kb/docs/docs-live-trading.md +23 -0
  218. package/dist/packages/mcp/assets/kb/docs/docs-ollama-another-machine.md +28 -0
  219. package/dist/packages/mcp/assets/kb/docs/docs-ollama-autotrade-on-a-local-model.md +29 -0
  220. package/dist/packages/mcp/assets/kb/docs/docs-ollama-check-your-model-dexterm-ai-probe.md +38 -0
  221. package/dist/packages/mcp/assets/kb/docs/docs-ollama-how-we-checked.md +27 -0
  222. package/dist/packages/mcp/assets/kb/docs/docs-ollama-models-without-tool-calling.md +32 -0
  223. package/dist/packages/mcp/assets/kb/docs/docs-ollama-pick-the-engine-globally-or-per-surface.md +43 -0
  224. package/dist/packages/mcp/assets/kb/docs/docs-ollama-restriction-profiles.md +35 -0
  225. package/dist/packages/mcp/assets/kb/docs/docs-ollama-set-it-up-in-two-minutes.md +39 -0
  226. package/dist/packages/mcp/assets/kb/docs/docs-ollama-troubleshooting.md +35 -0
  227. package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-runs-on-a-local-model.md +39 -0
  228. package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-stays-outside-the-model.md +36 -0
  229. package/dist/packages/mcp/assets/kb/docs/docs-ollama-which-model.md +38 -0
  230. package/dist/packages/mcp/assets/kb/docs/docs-ollama-your-own-agent-on-the-local-model.md +28 -0
  231. package/dist/packages/mcp/assets/kb/docs/docs-ollama.md +28 -0
  232. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-letting-an-agent-paper-trade-experimental.md +3 -4
  233. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet-read-only.md +30 -0
  234. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-order-plans-and-standing-mandates.md +3 -4
  235. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-panic.md +4 -7
  236. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-paper-only-mandates.md +6 -7
  237. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-pnl-cards.md +7 -7
  238. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-safety-model.md +34 -0
  239. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-ticket.md +3 -4
  240. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-trade-ledger.md +42 -0
  241. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-wallet.md +4 -5
  242. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-trade-moments.md +4 -5
  243. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading.md +4 -5
  244. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-buy-and-sell-markers.md +37 -0
  245. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +2 -1
  246. package/dist/packages/mcp/assets/kb/docs/docs-screens-autotrade-paper.md +26 -0
  247. package/dist/packages/mcp/assets/kb/docs/docs-screens-order-plans.md +1 -1
  248. package/dist/packages/mcp/assets/kb/docs/docs-screens-token-screen.md +2 -0
  249. package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-brain-view-and-the-pnl-chip.md +1 -1
  250. package/dist/packages/mcp/assets/kb/docs/docs-telegram-approve-one-tap-entries.md +50 -0
  251. package/dist/packages/mcp/assets/kb/docs/docs-telegram-control-the-commands.md +43 -0
  252. package/dist/packages/mcp/assets/kb/docs/docs-telegram-if-something-goes-wrong.md +30 -0
  253. package/dist/packages/mcp/assets/kb/docs/docs-telegram-notify-what-reaches-your-phone.md +41 -0
  254. package/dist/packages/mcp/assets/kb/docs/docs-telegram-set-it-up.md +47 -0
  255. package/dist/packages/mcp/assets/kb/docs/docs-telegram-the-record.md +26 -0
  256. package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-is.md +33 -0
  257. package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-will-not-do.md +31 -0
  258. package/dist/packages/mcp/assets/kb/docs/docs-telegram.md +23 -0
  259. package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-common-questions.md +1 -1
  260. package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-doctor-lines.md +4 -0
  261. package/dist/packages/mcp/assets/kb/docs/docs-voice-linux-and-windows.md +1 -1
  262. package/dist/packages/mcp/assets/kb/docs/docs-voice.md +1 -1
  263. package/dist/packages/mcp/assets/kb/docs/docs-yolo-1-replay-it-on-your-own-history.md +42 -0
  264. package/dist/packages/mcp/assets/kb/docs/docs-yolo-2-run-it-on-paper.md +34 -0
  265. package/dist/packages/mcp/assets/kb/docs/docs-yolo-3-watch-it-and-stop-it.md +32 -0
  266. package/dist/packages/mcp/assets/kb/docs/docs-yolo-the-rules.md +37 -0
  267. package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-is.md +34 -0
  268. package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-will-not-do.md +31 -0
  269. package/dist/packages/mcp/assets/kb/docs/docs-yolo.md +26 -0
  270. package/dist/packages/mcp/assets/kb/entries/autotrade.md +38 -0
  271. package/dist/packages/mcp/src/app-help.js +1 -1
  272. package/dist/packages/mcp/src/autotrade-tools.js +944 -0
  273. package/dist/packages/mcp/src/backtest-requests.js +71 -0
  274. package/dist/packages/mcp/src/engine/config.js +159 -0
  275. package/dist/packages/mcp/src/engine/index.js +10 -0
  276. package/dist/packages/mcp/src/engine/loop.js +101 -0
  277. package/dist/packages/mcp/src/engine/mcp-client.js +123 -0
  278. package/dist/packages/mcp/src/engine/ollama.js +258 -0
  279. package/dist/packages/mcp/src/engine/probe.js +110 -0
  280. package/dist/packages/mcp/src/engine/reason.js +35 -0
  281. package/dist/packages/mcp/src/engine/restrictions.js +111 -0
  282. package/dist/packages/mcp/src/index.js +7 -1
  283. package/dist/packages/mcp/src/ledger-tools.js +346 -0
  284. package/dist/packages/mcp/src/paper-agent.js +2 -0
  285. package/dist/packages/mcp/src/server.js +127 -19
  286. package/dist/packages/packs/src/backtest.js +3 -1
  287. package/dist/packages/popup/src/pages/chart-lib.js +134 -21
  288. package/dist/packages/popup/src/pages/chart.css +9 -0
  289. package/dist/packages/popup/src/pages/chart.html +3 -1
  290. package/dist/packages/popup/src/pages/chart.js +104 -7
  291. package/dist/packages/popup/src/protocol.js +2 -0
  292. package/dist/packages/popup/src/server.js +4 -0
  293. package/dist/packages/recorder/src/index.js +2 -0
  294. package/dist/packages/recorder/src/recorder.js +63 -6
  295. package/dist/packages/recorder/src/retention.js +100 -0
  296. package/dist/packages/recorder/src/schema.js +34 -1
  297. package/dist/packages/recorder/src/ticks.js +237 -0
  298. package/dist/packages/tui/src/index.js +1 -0
  299. package/dist/packages/tui/src/keymap.js +21 -1
  300. package/dist/packages/tui/src/markers.js +219 -0
  301. package/dist/packages/tui/src/widgets.js +149 -2
  302. package/package.json +2 -1
  303. package/dist/packages/data/src/trade/caps.js +0 -323
  304. package/dist/packages/data/src/trade/executor.js +0 -933
  305. package/dist/packages/data/src/trade/plans/executor-live.js +0 -220
  306. package/dist/packages/data/src/trade/rpc-exec.js +0 -229
  307. package/dist/packages/data/src/trade/signer/client.js +0 -197
  308. package/dist/packages/data/src/trade/signer/fast-wallet.js +0 -154
  309. package/dist/packages/data/src/trade/signer/host.js +0 -97
  310. package/dist/packages/data/src/trade/signer/main.js +0 -121
  311. package/dist/packages/data/src/trade/signer/probe-builder.js +0 -85
  312. package/dist/packages/data/src/trade/signer/protocol.js +0 -92
  313. package/dist/packages/data/src/trade/signer/service.js +0 -400
  314. package/dist/packages/data/src/trade/signer/sol-usd-feed.js +0 -98
  315. package/dist/packages/data/src/trade/sol-usd.js +0 -86
  316. package/dist/packages/data/src/trade/swap-build.js +0 -108
  317. package/dist/packages/data/src/trade/token-delta.js +0 -201
  318. package/dist/packages/data/vendor/solana-web3/LICENSE +0 -20
  319. package/dist/packages/data/vendor/solana-web3/NOTICE.md +0 -13
  320. package/dist/packages/data/vendor/solana-web3/index.iife.min.js +0 -20
  321. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-a-live-ticket.md +0 -42
  322. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-before-you-press-size-vs-caps.md +0 -34
  323. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-devnet-signer-mainnet-token.md +0 -35
  324. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-jupiter-rate-limits.md +0 -33
  325. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet.md +0 -32
  326. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-live-trading-devnet-first.md +0 -30
  327. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-mainnet.md +0 -31
  328. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-live-fire-path-devnet-the-fast-wallet.md +0 -41
  329. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-signer-process.md +0 -34
  330. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-what-the-live-path-keeps.md +0 -37
  331. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-your-first-live-trade.md +0 -41
@@ -9,8 +9,9 @@
9
9
  //
10
10
  // No network calls, nothing here is read by the signer, the caps, tickets, plans or the confirm gate.
11
11
  import { fmtMcap, fmtCompact, fmtPrice } from '../../tui/src/index.js';
12
- import { applyAndJournal, configPath, dextermHome, loadConfig, DEFAULT_PRICE_MODE, PRICE_MODES, CHART_AXES, DEFAULT_CHART_AXIS } from '../../custom/src/index.js';
13
- export { PRICE_MODES, DEFAULT_PRICE_MODE, CHART_AXES, DEFAULT_CHART_AXIS };
12
+ import { applyAndJournal, configPath, dextermHome, loadConfig, DEFAULT_PRICE_MODE, PRICE_MODES, CHART_AXES, DEFAULT_CHART_AXIS, CHART_MARKERS, DEFAULT_CHART_MARKERS } from '../../custom/src/index.js';
13
+ import { knownSupply, pickBasis, PRICE_BASIS_ENV } from '../../data/src/basis.js';
14
+ export { PRICE_MODES, DEFAULT_PRICE_MODE, CHART_AXES, DEFAULT_CHART_AXIS, CHART_MARKERS, DEFAULT_CHART_MARKERS };
14
15
  /** Axis / caption label for an mcap chart: the history is scaled by today's supply, and says so. */
15
16
  export const MCAP_AXIS_LABEL = 'mcap (current supply)';
16
17
  /** Shown wherever mcap mode is on but a token's supply is unknown, so the number on screen is a price. */
@@ -142,29 +143,65 @@ export function positionPriceCells(mode, supply, avgUsd, priceUsd, avgText, pric
142
143
  const mark = mode === 'mcap' ? FALLBACK_MARK : '';
143
144
  return { avg: { label: 'AVG ENTRY', value: avgText === '—' ? avgText : avgText + mark }, price: { label: 'PRICE', value: priceText === '—' ? priceText : priceText + mark } };
144
145
  }
145
- /** The mode in effect: the state's (set from config, a workspace or `$`), default price. */
146
+ /**
147
+ * task-1537: the known supply for a coin the app is showing: the open token view's (mcap ÷ price at its latest tick),
148
+ * else its screener row's, else pump.fun's fixed 1B (the PnL card's rule, @dexterm/data/basis knownSupply). Never
149
+ * guessed: null means the caller shows the price and marks it.
150
+ */
151
+ export function supplyForMint(state, mint) {
152
+ if (!mint)
153
+ return null;
154
+ const v = state.live?.token?.view;
155
+ if (v && v.mint === mint) {
156
+ const r = supplyRatio(v.price, v.mcap);
157
+ if (r !== null)
158
+ return r;
159
+ }
160
+ const row = state.screener?.rows.find((x) => x.mint === mint);
161
+ if (row) {
162
+ const r = supplyRatio(row.price, row.mcap);
163
+ if (r !== null)
164
+ return r;
165
+ }
166
+ return knownSupply({ mint, launchpad: row?.launchpad ?? (v && v.mint === mint ? v.launchpad : null) })?.tokens ?? null;
167
+ }
168
+ /**
169
+ * task-1537: one more price LEVEL in a row (a stop, a target, a fill, a tape trade): its market cap at the given supply
170
+ * in mcap mode, else the price (marked ᵖ when mcap mode had no supply). Display only.
171
+ */
172
+ export function levelCell(mode, supply, usd) {
173
+ if (usd === null || usd === undefined || !Number.isFinite(usd))
174
+ return '—';
175
+ if (mode === 'mcap' && supply != null && supply > 0)
176
+ return fmtMcap(usd * supply);
177
+ return fmtPrice(usd) + (mode === 'mcap' ? FALLBACK_MARK : '');
178
+ }
179
+ /** The mode in effect: the state's (set from config, a workspace, `$` or a one-run override), default MARKET CAP (task-1537). */
146
180
  export function priceModeOf(state) {
147
- return state?.priceMode === 'mcap' ? 'mcap' : 'price';
181
+ return state?.priceMode === 'price' ? 'price' : 'mcap';
148
182
  }
149
- /** The mode a run starts in: config.display.priceMode, else price. */
150
- export function configPriceMode(cfg) {
151
- const m = cfg?.display?.priceMode;
152
- return isPriceMode(m) ? m : DEFAULT_PRICE_MODE;
183
+ /**
184
+ * The mode a run starts in: the one-run override (`DEXTERM_PRICE_BASIS=price|mcap`, which `--price` / `--mcap` /
185
+ * `--price-mode` also set), else config.display.priceMode, else market cap (task-1537: @dexterm/data/basis pickBasis).
186
+ */
187
+ export function configPriceMode(cfg, env) {
188
+ return pickBasis(cfg?.display?.priceMode, env);
153
189
  }
154
190
  /**
155
- * `$`: flip the mode and persist it to config.display.priceMode through the journal (actor user, so `undo` works).
156
- * Returns the notice for the toast. Persistence failure keeps the new mode for this run and says why.
191
+ * `$` (and `/display mcap|price` in the chat box, task-1537): set the mode (`next` absent = flip) and persist it to
192
+ * config.display.priceMode through the journal (actor user, so `undo` works). Returns the notice for the toast.
193
+ * Persistence failure keeps the new mode for this run and says why.
157
194
  */
158
- export function togglePriceMode(state) {
159
- const next = priceModeOf(state) === 'mcap' ? 'price' : 'mcap';
160
- state.priceMode = next;
161
- const what = next === 'mcap' ? 'showing MARKET CAP' : 'showing USD PRICE'; // task-1472: the charts follow A, not $
195
+ export function setPriceMode(state, next, why = '$') {
196
+ const mode = next ?? (priceModeOf(state) === 'mcap' ? 'price' : 'mcap');
197
+ state.priceMode = mode;
198
+ const what = mode === 'mcap' ? 'showing MARKET CAP' : 'showing USD PRICE'; // task-1472: the charts follow A, not $
162
199
  const ui = state.custom;
163
200
  if (!ui)
164
201
  return `${what} (not saved: no config on this run)`;
165
202
  try {
166
- const op = ui.config.display ? { op: 'add', path: '/display/priceMode', value: next } : { op: 'add', path: '/display', value: { priceMode: next } };
167
- const { config } = applyAndJournal(ui.home, [op], { actor: 'user', why: `$ price mode ${next}`, now: state.now.getTime() });
203
+ const op = ui.config.display ? { op: 'add', path: '/display/priceMode', value: mode } : { op: 'add', path: '/display', value: { priceMode: mode } };
204
+ const { config } = applyAndJournal(ui.home, [op], { actor: 'user', why: `${why} price mode ${mode}`, now: state.now.getTime() });
168
205
  ui.config = config;
169
206
  return `${what} · saved ($ to switch back)`;
170
207
  }
@@ -172,6 +209,49 @@ export function togglePriceMode(state) {
172
209
  return `${what} (not saved: ${e.message})`;
173
210
  }
174
211
  }
212
+ /** `$`: flip the mode and persist it (see setPriceMode). */
213
+ export function togglePriceMode(state) { return setPriceMode(state); }
214
+ /**
215
+ * task-1537: the chat box command for the price basis, never sent to a model: `/display` (show), `/display mcap|price`,
216
+ * `/basis mcap|price`, `/set basis mcap|price` (also `/set priceMode …`). null = not this command.
217
+ */
218
+ export function parseDisplayCommand(q) {
219
+ const w = q.trim().replace(/^\//, '').split(/\s+/).filter(Boolean).map((x) => x.toLowerCase());
220
+ let arg;
221
+ if (w[0] === 'display' || w[0] === 'basis') {
222
+ if (w[1] === 'markers')
223
+ return null;
224
+ arg = w[1];
225
+ }
226
+ else if (w[0] === 'set' && (w[1] === 'basis' || w[1] === 'pricemode' || w[1] === 'price-basis' || w[1] === 'display.pricemode'))
227
+ arg = w[2];
228
+ else
229
+ return null;
230
+ if (arg === undefined)
231
+ return { show: true };
232
+ return isPriceMode(arg) ? { mode: arg } : { error: `/display expects mcap or price, got ${JSON.stringify(arg.slice(0, 20))}` };
233
+ }
234
+ /** The toast for `/display` with no argument. */
235
+ export function priceModeNotice(state) {
236
+ return priceModeOf(state) === 'mcap'
237
+ ? 'price basis: MARKET CAP (default) · coins with no known supply show price ᵖ · /display price or $ to switch'
238
+ : 'price basis: USD PRICE · /display mcap or $ to switch back to market cap';
239
+ }
240
+ /**
241
+ * task-1537: the one-run basis flags, accepted before any subcommand (`dexterm --price positions`, `dexterm autotrade
242
+ * list --mcap`): `--price` / `--mcap` are removed from argv and set DEXTERM_PRICE_BASIS in `env` for this process (so
243
+ * child agents and every CLI text follow it); nothing is saved. Returns argv without them.
244
+ */
245
+ export function takeBasisFlags(argv, env) {
246
+ const out = [];
247
+ for (const a of argv) {
248
+ if (a === '--price' || a === '--mcap')
249
+ env[PRICE_BASIS_ENV] = a.slice(2);
250
+ else
251
+ out.push(a);
252
+ }
253
+ return out;
254
+ }
175
255
  export function isChartAxis(v) { return CHART_AXES.includes(v); }
176
256
  /** task-1472: the chart Y axis in effect: the state's (from config or `A`), default MARKET CAP. */
177
257
  export function chartAxisOf(state) {
@@ -203,7 +283,38 @@ export function setChartAxis(state, next) {
203
283
  return `${what} (not saved: ${e.message})`;
204
284
  }
205
285
  }
206
- export const DISPLAY_USAGE = 'usage: dexterm display [price|mcap] show or set display.priceMode in ~/.dexterm/config.json ($ in the app toggles it)';
286
+ export function isChartMarkers(v) { return CHART_MARKERS.includes(v); }
287
+ /** task-1483: are the BUY / SELL markers on (both charts)? Default on; only an explicit 'off' hides them. */
288
+ export function chartMarkersOn(state) {
289
+ return state?.chartMarkers !== 'off';
290
+ }
291
+ /** task-1483: the markers setting a run starts with: config.display.chartMarkers, else on. */
292
+ export function configChartMarkers(cfg) {
293
+ const m = cfg?.display?.chartMarkers;
294
+ return isChartMarkers(m) ? m : DEFAULT_CHART_MARKERS;
295
+ }
296
+ /**
297
+ * task-1483: show / hide the chart BUY / SELL markers (both chart surfaces) and persist config.display.chartMarkers through
298
+ * the journal (actor user, so `undo` works). `next` absent = flip. Returns the toast text. Display only.
299
+ */
300
+ export function setChartMarkers(state, next) {
301
+ const v = next ?? (chartMarkersOn(state) ? 'off' : 'on');
302
+ state.chartMarkers = v;
303
+ const what = v === 'on' ? 'chart BUY/SELL markers: ON' : 'chart BUY/SELL markers: OFF';
304
+ const ui = state.custom;
305
+ if (!ui)
306
+ return `${what} (not saved: no config on this run)`;
307
+ try {
308
+ const op = ui.config.display ? { op: 'add', path: '/display/chartMarkers', value: v } : { op: 'add', path: '/display', value: { chartMarkers: v } };
309
+ const { config } = applyAndJournal(ui.home, [op], { actor: 'user', why: `chart markers ${v}`, now: state.now.getTime() });
310
+ ui.config = config;
311
+ return `${what} · saved`;
312
+ }
313
+ catch (e) {
314
+ return `${what} (not saved: ${e.message})`;
315
+ }
316
+ }
317
+ export const DISPLAY_USAGE = 'usage: dexterm display [price|mcap] show or set display.priceMode in ~/.dexterm/config.json ($ in the app toggles it)\n dexterm display markers [on|off] show or set display.chartMarkers (BUY/SELL markers on both charts)';
207
318
  /** `dexterm display [price|mcap]`: print the saved price display mode, or set it (journaled, actor user). No network. */
208
319
  export function displayCommand(argv, io) {
209
320
  const home = dextermHome(io.env);
@@ -218,6 +329,34 @@ export function displayCommand(argv, io) {
218
329
  io.stdout.write(`display.priceMode = ${m}${m === 'mcap' ? ' (tables show MCAP; tokens without a supply fall back to price)' : ' (USD price per token)'}\n`);
219
330
  const a = configChartAxis(loaded.config);
220
331
  io.stdout.write(`display.chartAxis = ${a}${a === 'mcap' ? ` (charts: ${MCAP_AXIS_LABEL}; A switches)` : ' (charts plot USD price; A switches)'}\n`);
332
+ const mk = configChartMarkers(loaded.config);
333
+ io.stdout.write(`display.chartMarkers = ${mk}${mk === 'on' ? ' (charts mark your paper and live fills; dexterm display markers off hides them)' : ' (no fill markers on the charts)'}\n`);
334
+ return 0;
335
+ }
336
+ // task-1483: `dexterm display markers [on|off]`
337
+ if (arg === 'markers') {
338
+ const v = argv[1];
339
+ if (v === undefined) {
340
+ if (!loaded.ok) {
341
+ io.stderr.write(`dexterm display: ${loaded.errors[0]}\n`);
342
+ return 1;
343
+ }
344
+ io.stdout.write(`display.chartMarkers = ${configChartMarkers(loaded.config)}\n`);
345
+ return 0;
346
+ }
347
+ if (!isChartMarkers(v)) {
348
+ io.stderr.write(`dexterm display markers: expected on or off, got ${JSON.stringify(v.slice(0, 20))}\n${DISPLAY_USAGE}\n`);
349
+ return 2;
350
+ }
351
+ try {
352
+ const op = loaded.config.display ? { op: 'add', path: '/display/chartMarkers', value: v } : { op: 'add', path: '/display', value: { chartMarkers: v } };
353
+ applyAndJournal(home, [op], { actor: 'user', why: `dexterm display markers ${v}` });
354
+ }
355
+ catch (e) {
356
+ io.stderr.write(`dexterm display: ${e.message}\n`);
357
+ return 1;
358
+ }
359
+ io.stdout.write(`display.chartMarkers = ${v} (saved to ${configPath(home)})\n`);
221
360
  return 0;
222
361
  }
223
362
  if (!isPriceMode(arg)) {
@@ -18,6 +18,7 @@ import { SayTts, voiceDoctor, resolveVoice, WHISPER_MODEL, resolvePiperRuntime,
18
18
  import { loadConfig, dextermHome } from '../../custom/src/index.js';
19
19
  import { kbStore, skillStore } from "./kb-skill-cmd.js";
20
20
  import { analystCliOnPath, CODEX_MIN_VERSION, parseEngineChoice, resolveEngine, versionAtLeast } from "./analyst/codex.js";
21
+ import { OllamaClient, SUGGESTED_MODELS, SURFACES, belowBar, effectiveRestriction, engineChoiceFor, loadAiConfig, ollamaSettings, pickModel, probeModel, remoteHostWarning } from '../../mcp/src/engine/index.js';
21
22
  /** The minimum Node that runs dexterm (type-stripping of the .ts entry needs 22.18). */
22
23
  export const MIN_NODE = [22, 18, 0];
23
24
  /** Cheap PATH lookup (no spawn). Windows (task-1423): PATH is `;`-separated and commands carry an extension
@@ -142,6 +143,18 @@ export async function claudeProbe(timeoutMs = 4000, platform = process.platform,
142
143
  }
143
144
  });
144
145
  }
146
+ /** Default Ollama facts: ai.json + a short probe of the configured host (127.0.0.1 by default). Never throws. */
147
+ export async function ollamaFacts(env = process.env) {
148
+ const c = loadAiConfig(env).config;
149
+ const set = ollamaSettings(c, env);
150
+ const client = new OllamaClient({ host: set.host, metaTimeoutMs: 2500 });
151
+ const probe = await probeModel(client, set.model, { numCtx: set.numCtx });
152
+ if (!probe.model && probe.models.length)
153
+ probe.model = null;
154
+ const surfaces = SURFACES.filter((sf) => engineChoiceFor(sf, c, env) === 'ollama');
155
+ const eff = effectiveRestriction(c, set.model ?? pickModel(probe.models), env);
156
+ return { probe, setUp: !!set.model || surfaces.length > 0, surfaces, level: eff.level, note: eff.note, hostWarning: remoteHostWarning(set.host) };
157
+ }
145
158
  /**
146
159
  * Default codex probe (0.1.5): PATH (spawnable form only), then `codex --version` and `codex login status`. The
147
160
  * status command is the user's own CLI reporting on its own login; dexterm never reads the credential itself.
@@ -190,6 +203,7 @@ export function defaultDeps(env = process.env, isTTY = process.stdout.isTTY ===
190
203
  platform: process.platform,
191
204
  claude: () => claudeProbe(),
192
205
  codex: () => codexProbe(4000, env),
206
+ ollama: () => ollamaFacts(env),
193
207
  analystEngine: env.DEXTERM_ANALYST_ENGINE ?? loadConfig(dextermHome(env)).config.analyst?.engine ?? null,
194
208
  probe: (url) => livingProbe(url),
195
209
  checkWritable: writableProbe,
@@ -262,7 +276,16 @@ export async function runDoctor(deps) {
262
276
  // 0.1.5: codex is the optional second engine; a missing claude is fine when codex can run the analyst.
263
277
  const codex = deps.codex ? await deps.codex() : null;
264
278
  const codexUsable = codex?.state === 'present';
265
- if (claude === 'missing' && codexUsable) {
279
+ // task-1543: a reachable Ollama with a pulled model can run the analyst too (a free local engine).
280
+ const ol = deps.ollama ? await deps.ollama().catch(() => null) : null;
281
+ const ollamaUsable = !!ol && ol.probe.reachable && (ol.probe.model ? ol.probe.present : ol.probe.models.length > 0);
282
+ if (claude === 'missing' && !codexUsable && ollamaUsable) {
283
+ checks.push({
284
+ name: 'Claude CLI', status: 'pass',
285
+ detail: 'not found on PATH (optional now): the analyst runs on your local Ollama model instead',
286
+ });
287
+ }
288
+ else if (claude === 'missing' && codexUsable) {
266
289
  checks.push({
267
290
  name: 'Claude CLI', status: 'pass',
268
291
  detail: 'not found on PATH (optional now): the analyst runs on your codex CLI instead',
@@ -272,7 +295,7 @@ export async function runDoctor(deps) {
272
295
  checks.push({
273
296
  name: 'Claude CLI', status: 'warn',
274
297
  detail: 'not found on PATH; the analyst (a) is disabled, the rest of dexterm works',
275
- fix: 'Install Claude Code (https://claude.com/claude-code) and run `claude` once to log in, or use Codex: `npm i -g @openai/codex && codex login`.',
298
+ fix: 'Set up an AI backend: install Claude Code (https://claude.com/claude-code) and run `claude` once to log in, or Codex (`npm i -g @openai/codex && codex login`), or a free local model (install Ollama from https://ollama.com/download, `ollama pull qwen3:8b`, `dexterm ai engine ollama`).',
276
299
  });
277
300
  }
278
301
  else {
@@ -284,7 +307,7 @@ export async function runDoctor(deps) {
284
307
  // 3b. Codex CLI (0.1.5): optional second analyst engine, the user's own codex login. Read-only lock needs >= CODEX_MIN_VERSION.
285
308
  if (codex) {
286
309
  const choice = parseEngineChoice(deps.analystEngine) ?? 'auto';
287
- const engine = resolveEngine(choice, (b) => b === 'claude' ? claude !== 'missing' : codexUsable);
310
+ const engine = resolveEngine(choice, (b) => b === 'claude' ? claude !== 'missing' : b === 'codex' ? codexUsable : ollamaUsable && !!ol?.setUp);
288
311
  const eng = `analyst engine: ${engine}${choice === 'auto' ? ' (auto)' : ''}`;
289
312
  if (codex.state === 'missing') {
290
313
  checks.push({ name: 'Codex CLI', status: engine === 'codex' ? 'warn' : 'pass', detail: `not installed (optional second analyst engine) · ${eng}`, ...(engine === 'codex' ? { fix: 'npm i -g @openai/codex && codex login, or set analyst.engine to claude' } : {}) });
@@ -299,6 +322,9 @@ export async function runDoctor(deps) {
299
322
  checks.push({ name: 'Codex CLI', status: 'pass', detail: `found${codex.version ? ` (codex-cli ${codex.version})` : ''}${codex.loggedIn ? ', logged in' : ''}; runs the analyst read-only on your own codex login (/engine codex) · ${eng}` });
300
323
  }
301
324
  }
325
+ // 3c. Local engine (task-1543): the user's own Ollama on this machine, the model, tool calling, context, profile.
326
+ if (ol)
327
+ checks.push(ollamaCheck(ol, claude !== 'missing' || codexUsable));
302
328
  // 4b. Login with X (optional, task-1357): the user's own X app + login unlock X posts in the SOCIAL panel / TRENDING.
303
329
  {
304
330
  const xs = new XTokenStore({ env: deps.env });
@@ -445,3 +471,36 @@ export function renderDoctor(result, opts = {}) {
445
471
  lines.push(paint(`${fails} check${fails === 1 ? '' : 's'} failed — fix the ✗ lines above, then re-run \`dexterm doctor\`.`, color ? ANSI.fail : ''));
446
472
  return lines.join('\n');
447
473
  }
474
+ /**
475
+ * The Ollama line (task-1543). Optional while claude/codex can run the analyst; a warning with the 2-minute
476
+ * setup when nothing can, or when the user chose ollama and it is not ready.
477
+ */
478
+ export function ollamaCheck(o, otherEngine) {
479
+ const p = o.probe;
480
+ const pull = `ollama pull ${SUGGESTED_MODELS[0].name}`;
481
+ const setup = `Install Ollama (https://ollama.com/download) and open it, then \`${pull}\` and \`dexterm ai engine ollama\` (\`dexterm ai model ${SUGGESTED_MODELS[0].name}\`).`;
482
+ const used = o.surfaces.length ? ` · runs: ${o.surfaces.join(', ')}` : '';
483
+ const prof = ` · profile ${o.level}${o.note ? ` (${o.note})` : ''}`;
484
+ const remote = o.hostWarning ? ` · WARNING ${o.hostWarning}` : '';
485
+ if (!p.reachable) {
486
+ // task-1551: a redirect is refused before anything is sent on; say so, whatever the setup state.
487
+ if (p.redirect)
488
+ return { name: 'Ollama (local AI)', status: 'warn', detail: `${p.host} answered with a redirect: refused, nothing was sent on${used}${remote}`, fix: 'dexterm never follows a redirect for the local engine (it would send your prompt to another host). Point it at the Ollama server itself with `dexterm ai host <host:port>` (or DEXTERM_OLLAMA_HOST), then re-run `dexterm doctor`.' };
489
+ if (!o.setUp)
490
+ return otherEngine
491
+ ? { name: 'Ollama (local AI)', status: 'pass', detail: 'not set up (optional free local engine; no login, no key, nothing leaves this machine)' }
492
+ : { name: 'Ollama (local AI)', status: 'warn', detail: 'no AI engine on this machine yet: a free local model works without any login or key', fix: setup };
493
+ return { name: 'Ollama (local AI)', status: 'warn', detail: `not reachable at ${p.host}${used}${remote}`, fix: `Start Ollama (open the app, or run \`ollama serve\`), then re-run \`dexterm doctor\`. Not installed? ${setup}` };
494
+ }
495
+ if (!p.model) {
496
+ const pick = pickModel(p.models);
497
+ return { name: 'Ollama (local AI)', status: o.setUp || !otherEngine ? 'warn' : 'pass', detail: `Ollama ${p.version ?? ''} running · pulled: ${p.models.slice(0, 5).join(', ') || 'none'} · no model chosen${used}${remote}`, ...(o.setUp || !otherEngine ? { fix: pick ? `dexterm ai model ${pick}` : `${pull} && dexterm ai model ${SUGGESTED_MODELS[0].name}` } : {}) };
498
+ }
499
+ if (!p.present)
500
+ return { name: 'Ollama (local AI)', status: 'warn', detail: `${p.model} is not pulled on ${p.host}${used}${remote}`, fix: `ollama pull ${p.model}` };
501
+ const warns = belowBar(o.level, p);
502
+ const facts = `${p.model} · tools ${p.tools === null ? '?' : p.tools ? 'yes' : 'no'} · context ${p.contextLength ?? '?'}`;
503
+ if (warns.length || o.hostWarning)
504
+ return { name: 'Ollama (local AI)', status: 'warn', detail: `${facts}${used}${prof}${remote}${warns.length ? ` · ${warns[0]}` : ''}`, fix: warns.length ? `\`dexterm ai probe --json\` checks it in detail; pull a stronger tool-capable model (e.g. ${pull}) or lower the profile (\`dexterm ai restrictions observe\`).` : 'Point dexterm at this machine: dexterm ai host 127.0.0.1' };
505
+ return { name: 'Ollama (local AI)', status: 'pass', detail: `${facts} · ${p.local ? 'local' : 'remote'} · $0${used}${prof}` };
506
+ }
@@ -12,6 +12,7 @@ import { mkdirSync, writeFileSync } from 'node:fs';
12
12
  import { join } from 'node:path';
13
13
  import { Canvas, rasterizeCanvas, fmtUsd, fmtPrice, fmtPct } from '../../tui/src/index.js';
14
14
  import { encodePng } from '../../data/src/index.js';
15
+ import { priceModeOf } from "./display.js";
15
16
  import { dextermHome } from "./boot-state.js";
16
17
  import { cleanText } from "./screener/rows.js";
17
18
  import { rugP, fmtRugP, RUG_MODEL_LABEL } from "./screener/rug.js";
@@ -152,8 +153,15 @@ const yesNo = (b) => (b === null ? 'unknown' : b ? 'ENABLED' : 'revoked');
152
153
  export function tokenReport(state, v, now) {
153
154
  const L = [];
154
155
  L.push(`coin $${cleanText(v.symbol, 16)}${v.name ? ` · ${cleanText(v.name, 40)}` : ''} · ${v.launchpad}`);
155
- L.push(`price ${fmtPrice(v.price)} 5m ${fmtPct(v.chg.m5)} 1h ${fmtPct(v.chg.h1)} 6h ${fmtPct(v.chg.h6)} 24h ${fmtPct(v.chg.h24)}`);
156
- L.push(`market cap ${fmtUsd(v.mcap)}${v.mcapFlagged ? ' (flagged)' : ''} liquidity ${fmtUsd(v.liq)} vol 24h ${fmtUsd(v.vol24)}`);
156
+ const moves = `5m ${fmtPct(v.chg.m5)} 1h ${fmtPct(v.chg.h1)} 6h ${fmtPct(v.chg.h6)} 24h ${fmtPct(v.chg.h24)}`;
157
+ if (priceModeOf(state) === 'mcap' && v.mcap !== null) { // task-1537: the market cap leads by default; both numbers stay
158
+ L.push(`market cap ${fmtUsd(v.mcap)}${v.mcapFlagged ? ' (flagged)' : ''} price ${fmtPrice(v.price)} ${moves}`);
159
+ L.push(`liquidity ${fmtUsd(v.liq)} vol 24h ${fmtUsd(v.vol24)}`);
160
+ }
161
+ else {
162
+ L.push(`price ${fmtPrice(v.price)} ${moves}`);
163
+ L.push(`market cap ${fmtUsd(v.mcap)}${v.mcapFlagged ? ' (flagged)' : ''} liquidity ${fmtUsd(v.liq)} vol 24h ${fmtUsd(v.vol24)}`);
164
+ }
157
165
  L.push(`holders ${v.holders ?? '—'} top-10 ${v.top10 === null ? '—' : `${v.top10.toFixed(1)}%`} dev ${v.dev === null ? '—' : `${v.dev.toFixed(1)}%`}${v.holdersSample ? ` (${v.holdersSample})` : ''}`);
158
166
  L.push(`age ${v.ageMin === null ? '—' : fmtAge(v.ageMin * 60)}`);
159
167
  L.push(`authorities mint ${yesNo(v.mintAuth)} · freeze ${yesNo(v.freezeAuth)}${v.riskyExtensions.length ? ` · risky extensions: ${v.riskyExtensions.join(', ')}` : ''}`);
@@ -19,7 +19,7 @@ export { renderAnalyst, renderContextRail, renderCoinList } from "./screens/anal
19
19
  export { renderTicket } from "./screens/ticket.js";
20
20
  export { renderPositions } from "./screens/positions.js";
21
21
  export * from "./trade.js";
22
- export { TradeTicketLive, PositionsLive, LivePositions, CombinedPositions, POSITIONS_REFRESH_MS } from "./live/trade.js";
22
+ export { TradeTicketLive, PositionsLive, POSITIONS_REFRESH_MS } from "./live/trade.js";
23
23
  export { parseWalletCommand, WALLET_HELP } from "./wallet-command.js";
24
24
  export * from "./screener/filter.js";
25
25
  export * from "./screener/sort.js";