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.
- package/dist/packages/agents/src/schema.js +22 -1
- package/dist/packages/agents/src/spectator.js +3 -1
- package/dist/packages/agents/src/story.js +11 -2
- package/dist/packages/agents/src/tiers.js +36 -2
- package/dist/packages/agents/src/tools.js +35 -2
- package/dist/packages/autotrade/assets/exit-profile.schema.json +492 -0
- package/dist/packages/autotrade/assets/limits.schema.json +569 -0
- package/dist/packages/autotrade/assets/profiles/moonbag.json +46 -0
- package/dist/packages/autotrade/assets/profiles/runner.json +88 -0
- package/dist/packages/autotrade/assets/profiles/scalp.json +88 -0
- package/dist/packages/autotrade/assets/profiles/swing.json +88 -0
- package/dist/packages/autotrade/assets/strategies/moonbag.json +101 -0
- package/dist/packages/autotrade/assets/strategies/runner.json +101 -0
- package/dist/packages/autotrade/assets/strategies/sample-dip-ladder.json +188 -0
- package/dist/packages/autotrade/assets/strategies/scalp.json +98 -0
- package/dist/packages/autotrade/assets/strategies/swing.json +97 -0
- package/dist/packages/autotrade/assets/strategies/yolo.json +157 -0
- package/dist/packages/autotrade/assets/tapes/yolo-rehearsal.json +1 -0
- package/dist/packages/autotrade/examples/executor/README.md +70 -0
- package/dist/packages/autotrade/examples/executor/jsonl-tail-executor.mjs +57 -0
- package/dist/packages/autotrade/examples/executor/kit.mjs +144 -0
- package/dist/packages/autotrade/examples/executor/signal-cmd-executor.mjs +25 -0
- package/dist/packages/autotrade/examples/executor/telegram-bot-recipe.md +47 -0
- package/dist/packages/autotrade/examples/executor/webhook-executor.mjs +47 -0
- package/dist/packages/autotrade/src/account.js +74 -0
- package/dist/packages/autotrade/src/backtest.js +358 -0
- package/dist/packages/autotrade/src/basis-text.js +32 -0
- package/dist/packages/autotrade/src/chat/approvals.js +484 -0
- package/dist/packages/autotrade/src/chat/audit.js +140 -0
- package/dist/packages/autotrade/src/chat/config.js +95 -0
- package/dist/packages/autotrade/src/chat/connector.js +24 -0
- package/dist/packages/autotrade/src/chat/control.js +104 -0
- package/dist/packages/autotrade/src/chat/fake.js +100 -0
- package/dist/packages/autotrade/src/chat/format.js +71 -0
- package/dist/packages/autotrade/src/chat/hub.js +187 -0
- package/dist/packages/autotrade/src/chat/index.js +18 -0
- package/dist/packages/autotrade/src/chat/notify.js +302 -0
- package/dist/packages/autotrade/src/chat/pairing.js +46 -0
- package/dist/packages/autotrade/src/chat/redact.js +48 -0
- package/dist/packages/autotrade/src/chat/secrets.js +106 -0
- package/dist/packages/autotrade/src/chat/service.js +251 -0
- package/dist/packages/autotrade/src/chat/telegram.js +290 -0
- package/dist/packages/autotrade/src/desk-executor.js +188 -0
- package/dist/packages/autotrade/src/engine.js +401 -0
- package/dist/packages/autotrade/src/execution-port.js +97 -0
- package/dist/packages/autotrade/src/executor-health.js +217 -0
- package/dist/packages/autotrade/src/fleet-config.js +169 -0
- package/dist/packages/autotrade/src/fleet-control.js +276 -0
- package/dist/packages/autotrade/src/fleet.js +642 -0
- package/dist/packages/autotrade/src/forward.js +355 -0
- package/dist/packages/autotrade/src/index.js +72 -0
- package/dist/packages/autotrade/src/journey.js +477 -0
- package/dist/packages/autotrade/src/ledger.js +108 -0
- package/dist/packages/autotrade/src/limits.js +682 -0
- package/dist/packages/autotrade/src/live-source.js +182 -0
- package/dist/packages/autotrade/src/monitor-daemon.js +715 -0
- package/dist/packages/autotrade/src/monitor.js +190 -0
- package/dist/packages/autotrade/src/ollama-sessions.js +137 -0
- package/dist/packages/autotrade/src/outbox.js +394 -0
- package/dist/packages/autotrade/src/paper-accounts.js +72 -0
- package/dist/packages/autotrade/src/paper-limits.js +87 -0
- package/dist/packages/autotrade/src/real-mode.js +688 -0
- package/dist/packages/autotrade/src/receipts.js +330 -0
- package/dist/packages/autotrade/src/replay.js +198 -0
- package/dist/packages/autotrade/src/report.js +168 -0
- package/dist/packages/autotrade/src/runner-config.js +99 -0
- package/dist/packages/autotrade/src/runner.js +923 -0
- package/dist/packages/autotrade/src/safety.js +243 -0
- package/dist/packages/autotrade/src/service-guard.js +125 -0
- package/dist/packages/autotrade/src/service-install.js +213 -0
- package/dist/packages/autotrade/src/service-recover.js +232 -0
- package/dist/packages/autotrade/src/service.js +289 -0
- package/dist/packages/autotrade/src/session.js +269 -0
- package/dist/packages/autotrade/src/sessions.js +503 -0
- package/dist/packages/autotrade/src/signal-channels.js +312 -0
- package/dist/packages/autotrade/src/signal.js +196 -0
- package/dist/packages/autotrade/src/store.js +250 -0
- package/dist/packages/autotrade/src/strategy.js +258 -0
- package/dist/packages/autotrade/src/trade-ledger.js +241 -0
- package/dist/packages/autotrade/src/yolo.js +140 -0
- package/dist/packages/cli/assets/claude/analyst-system.md +4 -4
- package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +1 -1
- package/dist/packages/cli/src/ai-cmd.js +412 -0
- package/dist/packages/cli/src/analyst/backend.js +83 -15
- package/dist/packages/cli/src/analyst/codex.js +15 -9
- package/dist/packages/cli/src/analyst/ollama.js +263 -0
- package/dist/packages/cli/src/analyst/session.js +5 -2
- package/dist/packages/cli/src/app-help-gen.js +56 -8
- package/dist/packages/cli/src/autotrade-cmd/audit.js +74 -0
- package/dist/packages/cli/src/autotrade-cmd/backtest.js +216 -0
- package/dist/packages/cli/src/autotrade-cmd/executor.js +91 -0
- package/dist/packages/cli/src/autotrade-cmd/flatten.js +64 -0
- package/dist/packages/cli/src/autotrade-cmd/fleet.js +401 -0
- package/dist/packages/cli/src/autotrade-cmd/forward.js +283 -0
- package/dist/packages/cli/src/autotrade-cmd/journey.js +208 -0
- package/dist/packages/cli/src/autotrade-cmd/limits.js +393 -0
- package/dist/packages/cli/src/autotrade-cmd/receipt.js +63 -0
- package/dist/packages/cli/src/autotrade-cmd/report.js +79 -0
- package/dist/packages/cli/src/autotrade-cmd/requests.js +79 -0
- package/dist/packages/cli/src/autotrade-cmd/run.js +657 -0
- package/dist/packages/cli/src/autotrade-cmd/service.js +873 -0
- package/dist/packages/cli/src/autotrade-cmd/signal.js +824 -0
- package/dist/packages/cli/src/autotrade-cmd/stop.js +76 -0
- package/dist/packages/cli/src/autotrade-cmd/strategies.js +198 -0
- package/dist/packages/cli/src/autotrade-cmd/strategy-control.js +174 -0
- package/dist/packages/cli/src/autotrade-cmd/telegram-host.js +101 -0
- package/dist/packages/cli/src/autotrade-cmd.js +214 -0
- package/dist/packages/cli/src/display.js +156 -17
- package/dist/packages/cli/src/doctor.js +62 -3
- package/dist/packages/cli/src/export.js +10 -2
- package/dist/packages/cli/src/index.js +1 -1
- package/dist/packages/cli/src/ledger-cmd.js +290 -0
- package/dist/packages/cli/src/live/chart-fills.js +46 -0
- package/dist/packages/cli/src/live/index.js +23 -89
- package/dist/packages/cli/src/live/screens/token-live.js +9 -6
- package/dist/packages/cli/src/live/trade.js +12 -457
- package/dist/packages/cli/src/live/watchlist.js +1 -1
- package/dist/packages/cli/src/main.js +147 -190
- package/dist/packages/cli/src/mcp-cmd.js +7 -1
- package/dist/packages/cli/src/plan-cmd.js +1 -1
- package/dist/packages/cli/src/pnl-app.js +31 -21
- package/dist/packages/cli/src/pnl-card.js +162 -21
- package/dist/packages/cli/src/popup.js +22 -6
- package/dist/packages/cli/src/record-cmd.js +141 -20
- package/dist/packages/cli/src/screens/agent-hud.js +34 -2
- package/dist/packages/cli/src/screens/analyst-session.js +7 -4
- package/dist/packages/cli/src/screens/analyst.js +3 -2
- package/dist/packages/cli/src/screens/autotrade-journey.js +134 -0
- package/dist/packages/cli/src/screens/autotrade-keys.js +182 -0
- package/dist/packages/cli/src/screens/autotrade-proposals.js +123 -0
- package/dist/packages/cli/src/screens/autotrade-screen.js +776 -0
- package/dist/packages/cli/src/screens/autotrade-ui.js +650 -0
- package/dist/packages/cli/src/screens/autotrade-worker.js +91 -0
- package/dist/packages/cli/src/screens/brain.js +37 -11
- package/dist/packages/cli/src/screens/overlay.js +5 -2
- package/dist/packages/cli/src/screens/plans.js +5 -17
- package/dist/packages/cli/src/screens/pnl-chip.js +9 -8
- package/dist/packages/cli/src/screens/positions.js +6 -28
- package/dist/packages/cli/src/screens/ticket.js +38 -205
- package/dist/packages/cli/src/screens/token.js +3 -3
- package/dist/packages/cli/src/state.js +25 -19
- package/dist/packages/cli/src/telegram-cmd.js +454 -0
- package/dist/packages/cli/src/trade.js +3 -128
- package/dist/packages/cli/src/version.js +1 -1
- package/dist/packages/cli/src/wallet-cmd.js +39 -340
- package/dist/packages/cli/src/wallet-command.js +8 -11
- package/dist/packages/cli/src/widgets.js +0 -12
- package/dist/packages/custom/src/config.js +20 -2
- package/dist/packages/custom/src/schema.js +35 -10
- package/dist/packages/custom/src/workspace.js +3 -3
- package/dist/packages/data/src/basis.js +191 -0
- package/dist/packages/data/src/detail.js +53 -2
- package/dist/packages/data/src/index.js +0 -14
- package/dist/packages/data/src/store.js +14 -5
- package/dist/packages/data/src/trade/agent/paper-desk.js +228 -16
- package/dist/packages/data/src/trade/agent/rendezvous.js +3 -2
- package/dist/packages/data/src/trade/bridge.js +4 -102
- package/dist/packages/data/src/trade/ledger/export.js +101 -0
- package/dist/packages/data/src/trade/ledger/file.js +135 -0
- package/dist/packages/data/src/trade/ledger/fold.js +191 -0
- package/dist/packages/data/src/trade/ledger/index.js +9 -0
- package/dist/packages/data/src/trade/ledger/schema.js +83 -0
- package/dist/packages/data/src/trade/ledger/sources.js +307 -0
- package/dist/packages/data/src/trade/ledger/stats.js +123 -0
- package/dist/packages/data/src/trade/ledger/tags.js +116 -0
- package/dist/packages/data/src/trade/ledger/view.js +51 -0
- package/dist/packages/data/src/trade/plans/index.js +0 -1
- package/dist/packages/data/src/trade/plans/service.js +3 -27
- package/dist/packages/mcp/assets/kb/app-help/autotrade-chat.md +48 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-executor-kit.md +44 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-journey.md +46 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-limits.md +48 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-parallel.md +42 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-real-signal.md +45 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-runner.md +35 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-stop.md +37 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-strategies.md +35 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-telegram.md +40 -0
- package/dist/packages/mcp/assets/kb/app-help/chart-trade-markers.md +42 -0
- package/dist/packages/mcp/assets/kb/app-help/link-a-wallet.md +4 -10
- package/dist/packages/mcp/assets/kb/app-help/live-trading.md +38 -0
- package/dist/packages/mcp/assets/kb/app-help/live-yolo.md +34 -0
- package/dist/packages/mcp/assets/kb/app-help/order-plans.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/price-or-marketcap.md +5 -2
- package/dist/packages/mcp/assets/kb/app-help/screen-analyst.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-autotrade.md +229 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-kol.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-newpairs.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-positions.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-screener.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-token.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-trending.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-watchlist.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/standing-mandates.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/trade-ledger.md +54 -0
- package/dist/packages/mcp/assets/kb/app-help/use-local-model.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-agent-paper-trading.md +4 -1
- package/dist/packages/mcp/assets/kb/docs/docs-agents-reading-your-trade-ledger.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-untrusted-by-default.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-if-claude-is-missing.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-use-a-local-model-instead.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-sees.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-backtests-and-their-limits.md +56 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-change-a-strategy-by-chat.md +51 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-checking-the-record-of-a-run.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-comparing-them.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-exits-and-wakes.md +76 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-how-a-stop-reaches-the-runner.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-on-the-q-screen.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-one-strategy-or-all-of-them.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-paper-accounts.md +50 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-presets.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-running-it-all-day.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-sessions-and-their-limits.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-several-strategies-at-once.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-stopping-it.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-strategies-and-presets.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-always-on-service.md +57 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-autotrade-json-file.md +48 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-heartbeat.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-run-file-and-the-heartbeat.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-runner-and-candidate-sessions.md +45 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-each-session-shows-first.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-costs-claude-usage-per-session.md +58 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-is-paper-self-directed.md +50 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-which-account-day-caps-and-the-usage-guard.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-your-strategies.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade.md +22 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-before-any-experimental-trading.md +2 -2
- package/dist/packages/mcp/assets/kb/docs/docs-beginners.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-1-ask-for-a-strategy.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-2-backtest-it-held-out-split.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-3-forward-test-it-on-live-data.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-4-promote-it-to-always-on-paper.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-5-real-only-if-you-choose.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-the-ladder.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-the-report.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-what-the-analyst-knows.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat.md +24 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-markers.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-y-axis.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-environment-variables.md +4 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-files-on-disk.md +1 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-headless-recorder-dexterm-record.md +3 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-price-display-mode.md +8 -6
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-2-the-one-key-mirror-ticket-a-proposal.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-3-capped-auto-mirror-default-off-less.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-what-is-proven-what-is-not.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-recorded-history-and-retention.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-sources.md +1 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-first-run.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-install.md +3 -3
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-requirements.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-executor-health.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-paper-vs-real.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-digest.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-executor-kit.md +48 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-whole-path.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-what-dexterm-does-and-never-does.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-your-limits.md +77 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real.md +24 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-changed-in-0-1-7.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-real-mode-your-strategy-s-trades-to-your.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-stopping.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-the-short-version.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-using-a-trading-bot-with-dexterm.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does-not-do.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading.md +23 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-another-machine.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-autotrade-on-a-local-model.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-check-your-model-dexterm-ai-probe.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-how-we-checked.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-models-without-tool-calling.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-pick-the-engine-globally-or-per-surface.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-restriction-profiles.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-set-it-up-in-two-minutes.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-troubleshooting.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-runs-on-a-local-model.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-stays-outside-the-model.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-which-model.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-your-own-agent-on-the-local-model.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-letting-an-agent-paper-trade-experimental.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet-read-only.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-order-plans-and-standing-mandates.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-panic.md +4 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-paper-only-mandates.md +6 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-pnl-cards.md +7 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-safety-model.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-ticket.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-trade-ledger.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-wallet.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-trade-moments.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-buy-and-sell-markers.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +2 -1
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-receipts-what-your-executor-did.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-safety.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-set-it-up.md +47 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-the-channels.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-the-signal.md +48 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-what-it-is.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-what-it-will-not-do.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-where-you-see-it.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-autotrade-paper.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-order-plans.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-screens-token-screen.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-brain-view-and-the-pnl-chip.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-approve-one-tap-entries.md +50 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-control-the-commands.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-if-something-goes-wrong.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-notify-what-reaches-your-phone.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-set-it-up.md +47 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-the-record.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-is.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram.md +23 -0
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-common-questions.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-doctor-lines.md +4 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-linux-and-windows.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-voice.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-1-replay-it-on-your-own-history.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-2-run-it-on-paper.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-3-watch-it-and-stop-it.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-the-rules.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-is.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo.md +26 -0
- package/dist/packages/mcp/assets/kb/entries/autotrade.md +40 -0
- package/dist/packages/mcp/src/app-help.js +1 -1
- package/dist/packages/mcp/src/autotrade-tools.js +1107 -0
- package/dist/packages/mcp/src/backtest-requests.js +71 -0
- package/dist/packages/mcp/src/engine/config.js +159 -0
- package/dist/packages/mcp/src/engine/index.js +10 -0
- package/dist/packages/mcp/src/engine/loop.js +101 -0
- package/dist/packages/mcp/src/engine/mcp-client.js +123 -0
- package/dist/packages/mcp/src/engine/ollama.js +258 -0
- package/dist/packages/mcp/src/engine/probe.js +110 -0
- package/dist/packages/mcp/src/engine/reason.js +35 -0
- package/dist/packages/mcp/src/engine/restrictions.js +111 -0
- package/dist/packages/mcp/src/index.js +7 -1
- package/dist/packages/mcp/src/ledger-tools.js +494 -0
- package/dist/packages/mcp/src/paper-agent.js +2 -0
- package/dist/packages/mcp/src/server.js +138 -19
- package/dist/packages/packs/src/backtest.js +3 -1
- package/dist/packages/popup/src/pages/chart-lib.js +134 -21
- package/dist/packages/popup/src/pages/chart.css +9 -0
- package/dist/packages/popup/src/pages/chart.html +3 -1
- package/dist/packages/popup/src/pages/chart.js +104 -7
- package/dist/packages/popup/src/protocol.js +2 -0
- package/dist/packages/popup/src/server.js +4 -0
- package/dist/packages/recorder/src/index.js +2 -0
- package/dist/packages/recorder/src/recorder.js +63 -6
- package/dist/packages/recorder/src/retention.js +100 -0
- package/dist/packages/recorder/src/schema.js +34 -1
- package/dist/packages/recorder/src/ticks.js +237 -0
- package/dist/packages/tui/src/index.js +1 -0
- package/dist/packages/tui/src/keymap.js +28 -1
- package/dist/packages/tui/src/markers.js +219 -0
- package/dist/packages/tui/src/widgets.js +149 -2
- package/package.json +2 -1
- package/dist/packages/data/src/trade/caps.js +0 -323
- package/dist/packages/data/src/trade/executor.js +0 -933
- package/dist/packages/data/src/trade/plans/executor-live.js +0 -220
- package/dist/packages/data/src/trade/rpc-exec.js +0 -229
- package/dist/packages/data/src/trade/signer/client.js +0 -197
- package/dist/packages/data/src/trade/signer/fast-wallet.js +0 -154
- package/dist/packages/data/src/trade/signer/host.js +0 -97
- package/dist/packages/data/src/trade/signer/main.js +0 -121
- package/dist/packages/data/src/trade/signer/probe-builder.js +0 -85
- package/dist/packages/data/src/trade/signer/protocol.js +0 -92
- package/dist/packages/data/src/trade/signer/service.js +0 -400
- package/dist/packages/data/src/trade/signer/sol-usd-feed.js +0 -98
- package/dist/packages/data/src/trade/sol-usd.js +0 -86
- package/dist/packages/data/src/trade/swap-build.js +0 -108
- package/dist/packages/data/src/trade/token-delta.js +0 -201
- package/dist/packages/data/vendor/solana-web3/LICENSE +0 -20
- package/dist/packages/data/vendor/solana-web3/NOTICE.md +0 -13
- package/dist/packages/data/vendor/solana-web3/index.iife.min.js +0 -20
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-a-live-ticket.md +0 -42
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-before-you-press-size-vs-caps.md +0 -34
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-devnet-signer-mainnet-token.md +0 -35
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-jupiter-rate-limits.md +0 -33
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet.md +0 -32
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-live-trading-devnet-first.md +0 -30
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-mainnet.md +0 -31
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-live-fire-path-devnet-the-fast-wallet.md +0 -41
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-signer-process.md +0 -34
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-what-the-live-path-keeps.md +0 -37
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-your-first-live-trade.md +0 -41
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// `dexterm autotrade <sub>` (task-1503 AT-1, AUTOTRADE-SPEC). No keys, no wallet, no signer: paper, or real mode
|
|
2
|
+
// (task-1645: trade-fire signals to the user's own executor, `signal` / `receipt` rows).
|
|
3
|
+
//
|
|
4
|
+
// A dispatcher table: each subcommand is one row that lazy-loads its own module under ./autotrade-cmd/, so
|
|
5
|
+
// later cards add a row (run, service, stop, flatten, audit) without editing anyone else's lines.
|
|
6
|
+
// `dexterm backtest --subject strategy …` is routed here too (the strategy subject runs on this engine).
|
|
7
|
+
export const SUBCOMMANDS = {
|
|
8
|
+
list: {
|
|
9
|
+
usage: 'dexterm autotrade list [--json]',
|
|
10
|
+
summary: 'your strategies (~/.dexterm/strategies) and the shipped presets: version, hash, mode, profiles, last backtest',
|
|
11
|
+
load: () => import("./autotrade-cmd/strategies.js").then((m) => m.listCmd),
|
|
12
|
+
},
|
|
13
|
+
validate: {
|
|
14
|
+
usage: 'dexterm autotrade validate <id|file> [--json]',
|
|
15
|
+
summary: 'check a strategy file or a stored strategy; every problem is printed with its path',
|
|
16
|
+
load: () => import("./autotrade-cmd/strategies.js").then((m) => m.validateCmd),
|
|
17
|
+
},
|
|
18
|
+
new: {
|
|
19
|
+
usage: 'dexterm autotrade new <new-id> --from <preset|id> [--name TEXT]',
|
|
20
|
+
summary: 'copy a preset (or one of your strategies) into ~/.dexterm/strategies/<new-id>.json to edit',
|
|
21
|
+
load: () => import("./autotrade-cmd/strategies.js").then((m) => m.newCmd),
|
|
22
|
+
},
|
|
23
|
+
import: {
|
|
24
|
+
usage: 'dexterm autotrade import <file> [--replace]',
|
|
25
|
+
summary: 'validate a strategy file and store it (mode is forced to paper; --replace needs a higher version)',
|
|
26
|
+
load: () => import("./autotrade-cmd/strategies.js").then((m) => m.importCmd),
|
|
27
|
+
},
|
|
28
|
+
remove: {
|
|
29
|
+
usage: 'dexterm autotrade remove <id>',
|
|
30
|
+
summary: 'move one of your strategies to ~/.dexterm/strategies/.removed/ (journaled; presets cannot be removed)',
|
|
31
|
+
load: () => import("./autotrade-cmd/strategies.js").then((m) => m.removeCmd),
|
|
32
|
+
},
|
|
33
|
+
journal: {
|
|
34
|
+
usage: 'dexterm autotrade journal [<id>] [--json]',
|
|
35
|
+
summary: 'the append-only change journal: who changed what, with the before and after hashes',
|
|
36
|
+
load: () => import("./autotrade-cmd/strategies.js").then((m) => m.journalCmd),
|
|
37
|
+
},
|
|
38
|
+
backtest: {
|
|
39
|
+
usage: 'dexterm autotrade backtest <id|file> [--tape FILE | --db PATH [--days N | --since T] [--until T]] [--every-candidate [--unit-usd 20]] [--recall 5,10] [--json]',
|
|
40
|
+
summary: 'replay a strategy over recorded history with modelled fills (paper); the limits of the data are always printed',
|
|
41
|
+
load: () => import("./autotrade-cmd/backtest.js").then((m) => m.backtestCmd),
|
|
42
|
+
},
|
|
43
|
+
sweep: {
|
|
44
|
+
usage: 'dexterm autotrade sweep <id|file> [--tape FILE | --db PATH] [--grid JSON] [--mode grid|random] [--max N] [--seed N] [--json]',
|
|
45
|
+
summary: 'tune on the older coins, check once on the newest 30% it never saw; no gain wording without enough trades and a held-out profit',
|
|
46
|
+
load: () => import("./autotrade-cmd/backtest.js").then((m) => m.sweepCmd),
|
|
47
|
+
},
|
|
48
|
+
'yolo-replay': {
|
|
49
|
+
usage: 'dexterm autotrade yolo-replay <id|file> [--tape FILE | --db PATH [--days N | --since T] [--until T]] [--seed N] [--json]',
|
|
50
|
+
summary: 'HIGH RISK check before arming a full-port strategy: replay it at 100% of the book over recorded history (paper): rugs, the loss spread, how often it zeroed the wallet',
|
|
51
|
+
load: () => import("./autotrade-cmd/backtest.js").then((m) => m.yoloReplayCmd),
|
|
52
|
+
},
|
|
53
|
+
requests: {
|
|
54
|
+
usage: 'dexterm autotrade requests [list [--all] [--json] | run <br_id> | dismiss <br_id>]',
|
|
55
|
+
summary: 'backtests an agent asked for over MCP (backtest_request): nothing runs until you run one here (paper, recorded data)',
|
|
56
|
+
load: () => import("./autotrade-cmd/requests.js").then((m) => m.requestsCmd),
|
|
57
|
+
},
|
|
58
|
+
run: {
|
|
59
|
+
usage: 'dexterm autotrade run <id|file> --paper|--real [--replay TAPE [--ms-per-tick 2000]] [--model M] [--max-minutes N] [--sol-usd N] [--stub] [--raw] [--quiet] [--no-telegram]',
|
|
60
|
+
summary: 'the runner: the screener hands each candidate to your own Claude (runner.json picks the account), every size clamped; ledger in autotrade/runs/; your paired Telegram bot starts with it (dexterm telegram setup). --real (a strategy you armed with signal arm) runs in the FOREGROUND only, on live data: the always-on service runs paper strategies, and while no real run is running NO signal goes out, sells included',
|
|
61
|
+
load: () => import("./autotrade-cmd/run.js").then((m) => m.runCmd),
|
|
62
|
+
},
|
|
63
|
+
'run --all': {
|
|
64
|
+
usage: 'dexterm autotrade run --all --paper [--config FILE] [--replay TAPE] [--sol-usd N] [--stub] [--max-minutes N]',
|
|
65
|
+
summary: 'every strategy of autotrade/autotrade.json at once on one data feed: each its own bankroll, ledger, caps and budget, under global caps',
|
|
66
|
+
load: () => import("./autotrade-cmd/fleet.js").then((m) => m.fleetRunCmd),
|
|
67
|
+
},
|
|
68
|
+
status: {
|
|
69
|
+
usage: 'dexterm autotrade status [--all] [--json]',
|
|
70
|
+
summary: 'the paper runner now; --all: every strategy of a parallel run side by side (P/L, win rate, rug exposure, missed runners, spend per entry)',
|
|
71
|
+
load: () => import("./autotrade-cmd/strategy-control.js").then((m) => m.statusCmd),
|
|
72
|
+
},
|
|
73
|
+
start: {
|
|
74
|
+
usage: 'dexterm autotrade start <strategy> [--wait SEC] [--json]',
|
|
75
|
+
summary: 'start one strategy of autotrade.json inside the running `run --all` (paper, its own book and caps)',
|
|
76
|
+
load: () => import("./autotrade-cmd/strategy-control.js").then((m) => m.startCmd),
|
|
77
|
+
},
|
|
78
|
+
pause: {
|
|
79
|
+
usage: 'dexterm autotrade pause [--strategy ID] [--json]',
|
|
80
|
+
summary: 'no new entries (every strategy, or just one with --strategy); open positions keep their exits',
|
|
81
|
+
load: () => import("./autotrade-cmd/strategy-control.js").then((m) => m.pauseCmd),
|
|
82
|
+
},
|
|
83
|
+
resume: {
|
|
84
|
+
usage: 'dexterm autotrade resume [--strategy ID] [--json]',
|
|
85
|
+
summary: 'lift a pause (every strategy, or just one with --strategy); a stop is final and is never lifted',
|
|
86
|
+
load: () => import("./autotrade-cmd/strategy-control.js").then((m) => m.resumeCmd),
|
|
87
|
+
},
|
|
88
|
+
stop: {
|
|
89
|
+
usage: 'dexterm autotrade stop [--strategy ID] [--wait SEC] [--json]',
|
|
90
|
+
summary: 'soft-stop the paper runner: no new entries, sessions closed, orders dropped; mechanical exits keep running until nothing is held',
|
|
91
|
+
load: () => import("./autotrade-cmd/stop.js").then((m) => m.stopCmd),
|
|
92
|
+
},
|
|
93
|
+
flatten: {
|
|
94
|
+
usage: 'dexterm autotrade flatten [--strategy ID] [--yes] [--wait SEC] [--json]',
|
|
95
|
+
summary: 'stop, then sell every paper position at its next tick (confirm with y on a terminal, or --yes)',
|
|
96
|
+
load: () => import("./autotrade-cmd/flatten.js").then((m) => m.flattenCmd),
|
|
97
|
+
},
|
|
98
|
+
audit: {
|
|
99
|
+
usage: 'dexterm autotrade audit [<run-id>|--last] [--verify] [--json]',
|
|
100
|
+
summary: 'list the run ledgers; --verify recomputes each hash chain and names the first edited, missing or reordered event',
|
|
101
|
+
load: () => import("./autotrade-cmd/audit.js").then((m) => m.auditCmd),
|
|
102
|
+
},
|
|
103
|
+
signal: {
|
|
104
|
+
usage: 'dexterm autotrade signal status|channels|secret|arm|disarm|caps|kill|unkill|held|release|test|flush|tail|reconcile …',
|
|
105
|
+
summary: 'real mode: a LIVE TRADE FIRE signal per trade to YOUR executor (webhook, --signal-cmd, JSONL, MCP, Telegram copy); arm on your own terminal; hard caps, kill switch; dexterm holds no key',
|
|
106
|
+
load: () => import("./autotrade-cmd/signal.js").then((m) => m.signalCmd),
|
|
107
|
+
},
|
|
108
|
+
receipt: {
|
|
109
|
+
usage: 'dexterm autotrade receipt <nonce|id> executed|rejected|failed [--price USD] [--size-sol N] [--tokens N] [--tx SIG] [--reason TEXT] | receipt list [--json]',
|
|
110
|
+
summary: 'what your executor did with a trade-fire signal, as data only (positions stay unconfirmed until a receipt); the drift between signals and fills',
|
|
111
|
+
load: () => import("./autotrade-cmd/receipt.js").then((m) => m.receiptCmd),
|
|
112
|
+
},
|
|
113
|
+
service: {
|
|
114
|
+
usage: 'dexterm autotrade service install|uninstall|ensure|run|start|stop|status|logs [--home PATH]',
|
|
115
|
+
summary: 'the always-on service: your PAPER strategies (autotrade.json) start at login, restart after a crash, stop on any kill switch and tell you when they cannot run; real mode does not run under it (run --real, in the foreground)',
|
|
116
|
+
load: () => import("./autotrade-cmd/service.js").then((m) => m.serviceCmd),
|
|
117
|
+
},
|
|
118
|
+
forward: {
|
|
119
|
+
usage: 'dexterm autotrade forward start <id> [--hours H] [--trades N] [--bankroll-usd N] | status [<id>] | stop <id> | report <id> [--json]',
|
|
120
|
+
summary: 'forward test: the strategy on the LIVE tape, on paper, own bankroll and run file, for hours or N trades; the report sets it next to its backtest',
|
|
121
|
+
load: () => import("./autotrade-cmd/forward.js").then((m) => m.forwardCmd),
|
|
122
|
+
},
|
|
123
|
+
journey: {
|
|
124
|
+
usage: 'dexterm autotrade journey [<id>] [--json]',
|
|
125
|
+
summary: 'where a strategy stands on the ladder draft → backtested → forward-tested → always-on → real, and what the next rung needs',
|
|
126
|
+
load: () => import("./autotrade-cmd/journey.js").then((m) => m.journeyCmd),
|
|
127
|
+
},
|
|
128
|
+
promote: {
|
|
129
|
+
usage: 'dexterm autotrade promote <id> --to always-on|real | list | show <pp-id> | apply <pp-id> | dismiss <pp-id>',
|
|
130
|
+
summary: 'a promotion with its evidence card: always-on needs your y on a real terminal; real needs the evidence floor (a completed forward test with minForwardTrades closed paper trades + a backtest) and hands over to signal arm (your caps, a typed phrase); no rung is skipped',
|
|
131
|
+
load: () => import("./autotrade-cmd/journey.js").then((m) => m.promoteCmd),
|
|
132
|
+
},
|
|
133
|
+
limits: {
|
|
134
|
+
usage: 'dexterm autotrade limits show|set|diff|reset|accept|breaker reset|explain|schema …',
|
|
135
|
+
summary: 'real mode: every limit is yours (per trade SOL or % of book, per day, open positions, exposure, loss limits, breaker, rate, slippage, TTL, executor silence), global / per mode / per strategy / per account, the stricter wins; raising is typed on your own terminal',
|
|
136
|
+
load: () => import("./autotrade-cmd/limits.js").then((m) => m.limitsCmd),
|
|
137
|
+
},
|
|
138
|
+
executor: {
|
|
139
|
+
usage: 'dexterm autotrade executor status [--json] | heartbeat [--name N] [--account ID] [--dry-run] [--nonce N] | kit --out DIR',
|
|
140
|
+
summary: 'real mode: is YOUR executor alive (heartbeat, last receipt, lag)? A silent executor pauses new buy signals; `kit --out DIR` copies the dry-run reference executors (webhook, signal-cmd, JSONL tail)',
|
|
141
|
+
load: () => import("./autotrade-cmd/executor.js").then((m) => m.executorCmd),
|
|
142
|
+
},
|
|
143
|
+
report: {
|
|
144
|
+
usage: 'dexterm autotrade report [--period day|week] [--strategy ID] [--json] [--telegram]',
|
|
145
|
+
summary: 'the digest per strategy and mode: trades, win rate with its interval, net, drawdown, refusals, limits hit, executor health, paper vs real fills, an honest small-sample note',
|
|
146
|
+
load: () => import("./autotrade-cmd/report.js").then((m) => m.reportCmd),
|
|
147
|
+
},
|
|
148
|
+
extract: {
|
|
149
|
+
usage: 'dexterm autotrade extract --out FILE [--db PATH] [--max-mints N] [--min-peak-liq USD] [--span-hours H]',
|
|
150
|
+
summary: 'save a replay tape from your recorder history (read-only) to a file you can backtest offline',
|
|
151
|
+
load: () => import("./autotrade-cmd/backtest.js").then((m) => m.extractCmd),
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
export function autotradeHelp() {
|
|
155
|
+
return [
|
|
156
|
+
'dexterm autotrade: strategies, backtests and the runner. PAPER by default; mode real sends a LIVE TRADE FIRE signal per trade to YOUR executor (`signal arm`, on your own terminal; dexterm holds no key). Not financial advice.',
|
|
157
|
+
'',
|
|
158
|
+
...Object.values(SUBCOMMANDS).map((s) => ` ${s.usage}\n ${s.summary}`),
|
|
159
|
+
'',
|
|
160
|
+
' Strategies live in $DEXTERM_HOME/strategies (default ~/.dexterm/strategies), one JSON file each, with an',
|
|
161
|
+
' append-only .journal.jsonl. Presets: scalp, swing, runner, moonbag, sample-dip-ladder, yolo (HIGH RISK) (read-only; copy one with `new`).',
|
|
162
|
+
' `dexterm backtest --subject strategy --strategy <id|file>` runs the same backtest.',
|
|
163
|
+
].join('\n') + '\n';
|
|
164
|
+
}
|
|
165
|
+
/** The value of `--subject` (or `--subject=x`) in an argv, if any. */
|
|
166
|
+
function subjectOf(argv) {
|
|
167
|
+
for (let i = 0; i < argv.length; i++) {
|
|
168
|
+
if (argv[i] === '--subject')
|
|
169
|
+
return argv[i + 1];
|
|
170
|
+
if (argv[i].startsWith('--subject='))
|
|
171
|
+
return argv[i].slice('--subject='.length);
|
|
172
|
+
}
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
/** True for `dexterm autotrade …` and `dexterm backtest --subject strategy …`. */
|
|
176
|
+
export function handles(argv) {
|
|
177
|
+
return argv[0] === 'autotrade' || (argv[0] === 'backtest' && subjectOf(argv) === 'strategy');
|
|
178
|
+
}
|
|
179
|
+
export async function autotradeCommand(argv, io) {
|
|
180
|
+
let rest;
|
|
181
|
+
if (argv[0] === 'backtest') {
|
|
182
|
+
// `dexterm backtest --subject strategy [--strategy X] …` → `dexterm autotrade backtest [X] …`
|
|
183
|
+
rest = ['backtest'];
|
|
184
|
+
for (let i = 1; i < argv.length; i++) {
|
|
185
|
+
if (argv[i] === '--subject') {
|
|
186
|
+
i++;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (argv[i].startsWith('--subject='))
|
|
190
|
+
continue;
|
|
191
|
+
rest.push(argv[i]);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else
|
|
195
|
+
rest = argv.slice(1);
|
|
196
|
+
const sub = rest[0];
|
|
197
|
+
if (!sub || sub === 'help' || sub === '--help' || sub === '-h') {
|
|
198
|
+
io.stdout.write(autotradeHelp());
|
|
199
|
+
return 0;
|
|
200
|
+
}
|
|
201
|
+
// `run --all` has its own row (parallel strategies, task-1529) so its --help shows its own flags.
|
|
202
|
+
const key = sub === 'run' && rest.includes('--all') ? 'run --all' : sub;
|
|
203
|
+
const row = Object.hasOwn(SUBCOMMANDS, key) ? SUBCOMMANDS[key] : undefined;
|
|
204
|
+
if (!row) {
|
|
205
|
+
io.stderr.write(`dexterm autotrade: unknown subcommand ${JSON.stringify(sub)}\n\n${autotradeHelp()}`);
|
|
206
|
+
return 2;
|
|
207
|
+
}
|
|
208
|
+
if (rest.includes('--help') || rest.includes('-h')) {
|
|
209
|
+
io.stdout.write(`${row.usage}\n ${row.summary}\n`);
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
const fn = await row.load();
|
|
213
|
+
return fn(rest.slice(1), io);
|
|
214
|
+
}
|
|
@@ -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
|
-
|
|
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
|
-
/**
|
|
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 === '
|
|
181
|
+
return state?.priceMode === 'price' ? 'price' : 'mcap';
|
|
148
182
|
}
|
|
149
|
-
/**
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
*
|
|
156
|
-
*
|
|
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
|
|
159
|
-
const
|
|
160
|
-
state.priceMode =
|
|
161
|
-
const what =
|
|
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:
|
|
167
|
-
const { config } = applyAndJournal(ui.home, [op], { actor: 'user', why: `$ price mode ${
|
|
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
|
|
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
|
-
|
|
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: '
|
|
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
|
-
|
|
156
|
-
|
|
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,
|
|
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";
|