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
|
@@ -44,6 +44,9 @@ import { OwnPnlTracker } from "./screens/pnl-chip.js";
|
|
|
44
44
|
import { positionRow } from "./live/trade.js";
|
|
45
45
|
import { widgetPage, widgetEnabled, syncWidgetPopups } from "./widgets.js";
|
|
46
46
|
import { recordLarpVerdict } from "./larp-record.js";
|
|
47
|
+
import { newAutotradeUi, defaultDeps as autotradeDeps, autotradeCapturing, autotradeTick, reloadList as autotradeReload, refreshRunner as autotradeRefreshRunner } from "./screens/autotrade-ui.js";
|
|
48
|
+
import { autotradeAction, autotradeKey } from "./screens/autotrade-keys.js";
|
|
49
|
+
import { workerJobs as autotradeWorkerJobs } from "./screens/autotrade-worker.js";
|
|
47
50
|
import { rulesUiOf, rulesTick, rulesMove, beginRuleInput, saveRuleInput, dryRunNow, removeSelectedRule, toggleSelectedRule, dismissSelectedProposal, actOnSelectedProposal, RULE_INPUT_MAX } from "./rules.js";
|
|
48
51
|
import { buildNotifier, hasPushChannel } from "./alerts/notifier.js";
|
|
49
52
|
import { copyAlertToDelivery } from "./alerts/format.js";
|
|
@@ -51,6 +54,7 @@ import { readTelegramCreds, readDiscordCreds } from "./alerts/creds.js";
|
|
|
51
54
|
import { launchIntelCells, launchRetryable } from "./live/intel.js";
|
|
52
55
|
import { AnalystSession } from "./analyst/session.js";
|
|
53
56
|
import { analystCliOnPath, parseEngineChoice, resolveEngine } from "./analyst/codex.js";
|
|
57
|
+
import { analystEngineHas, analystAiChoice } from "./ai-cmd.js";
|
|
54
58
|
import { resolveAnalystResults } from "./analyst/results.js";
|
|
55
59
|
import { parseScanCommand, SCAN_FLAGS, checkScanFlag, SCAN_HELP } from "./scan/command.js";
|
|
56
60
|
import { parseWalletCommand, WALLET_HELP } from "./wallet-command.js";
|
|
@@ -61,11 +65,11 @@ import { cleanText } from "./screener/rows.js";
|
|
|
61
65
|
import { resolveImagesConfig } from "./images-config.js";
|
|
62
66
|
import { popupImagePath } from "./screens/coin.js";
|
|
63
67
|
import { VoiceController, selectStt, selectTts, SayTts, voiceStyleDefaults } from '../../voice/src/index.js';
|
|
64
|
-
import {
|
|
68
|
+
import { defaultPlansJournalPath } from '../../data/src/trade/plans/index.js';
|
|
65
69
|
import { isWalletAddress, shortAddr, buildMirror, leaderSoldSince, autoSizeCap } from '../../data/src/trade/copy/index.js';
|
|
66
70
|
import { FOLLOW_INPUT_MAX } from "./screens/follows.js";
|
|
67
71
|
import { HUD_MIN_H, hudAnimating } from "./screens/agent-hud.js";
|
|
68
|
-
import { isPriceMode, configPriceMode, togglePriceMode, priceModeOf, planLevels, configChartAxis, setChartAxis, chartAxisOf } from "./display.js";
|
|
72
|
+
import { isPriceMode, configPriceMode, takeBasisFlags, togglePriceMode, setPriceMode, parseDisplayCommand, priceModeNotice, priceModeOf, planLevels, configChartAxis, setChartAxis, chartAxisOf, configChartMarkers, setChartMarkers, chartMarkersOn } from "./display.js";
|
|
69
73
|
import { VERSION } from "./version.js";
|
|
70
74
|
import { initCustom, planWorkspace, planPopupOpens, findWorkspace, nextWorkspaceName, workspaceSlots, saveWorkspace, themeFor, themeByName, cycleTheme, themeNames, CHORD_TTL_MS, MAX_WORKSPACE_NAME } from "./custom.js";
|
|
71
75
|
import { DEFAULT_WORKSPACE, MORNING_HUD, applyAndJournal, policyCheck } from '../../custom/src/index.js';
|
|
@@ -135,7 +139,8 @@ export function buildScreenState(state) {
|
|
|
135
139
|
const x = r;
|
|
136
140
|
if (!x?.mint)
|
|
137
141
|
return null;
|
|
138
|
-
|
|
142
|
+
// task-1537: the row's market cap rides along (the analyst's context leads with it by default)
|
|
143
|
+
return { mint: x.mint, symbol: x.symbol ?? '', priceUsd: x.price ?? null, mcap: x.mcap ?? null, chg1h: x.chg?.h1 ?? null, chg24h: x.chg?.h24 ?? null, liq: x.liq ?? null, vol24: x.vol24 ?? null };
|
|
139
144
|
};
|
|
140
145
|
const toNewPairRow = (r) => {
|
|
141
146
|
const x = r;
|
|
@@ -298,14 +303,17 @@ export const HELP = `dexterm ${VERSION} (live: screener, token, new pairs, watch
|
|
|
298
303
|
dexterm update [--off|--on] check npm + GitHub for a newer version and print the upgrade command;
|
|
299
304
|
--off/--on toggles the once-a-day startup notice (no telemetry)
|
|
300
305
|
dexterm recorder stats|label|prune|export the history recorder's tables (no network; 'dexterm recorder help')
|
|
301
|
-
dexterm kb list|show|new|edit|check|reset|path your knowledge-base entries (~/.dexterm/kb/entries) over the bundled
|
|
306
|
+
dexterm kb list|show|new|edit|check|reset|path your knowledge-base entries (~/.dexterm/kb/entries) over the bundled 18
|
|
302
307
|
dexterm skill list|show|new|edit|check|reset|path your analyst skills (~/.dexterm/skills) over the bundled ones (read tools only)
|
|
303
308
|
dexterm narrative [--window 1h|24h] [--summary] the narrative board over recorded history (no network, no model)
|
|
304
309
|
dexterm backtest [--subject heuristic|pack_verdicts] [--horizon SEC] honest rug-model metrics over recorded outcomes (no network, no model)
|
|
305
|
-
dexterm
|
|
310
|
+
dexterm ledger trades|positions|summary|equity|compare|export|card|sync|verify the unified trade ledger: paper, agent desk, autotrade runs (no network; 'dexterm ledger help')
|
|
311
|
+
dexterm wallet link|unlink|status|panic|resume link a Phantom wallet via a local bridge (pubkey only); panic halts autotrade + the paper desk, resume needs a TTY keypress
|
|
306
312
|
dexterm plan propose|list|arm|cancel|journal conditional order plans (entry/ladder/take-profit/moon bag/stop); arming needs a physical keypress
|
|
307
|
-
dexterm mandate draft|list|arm|revoke standing capped mandates (
|
|
313
|
+
dexterm mandate draft|list|arm|revoke standing capped mandates (paper fills); arming needs a physical keypress — voice/agents can never arm
|
|
308
314
|
dexterm follow add|remove|list|stats|trades|mirror|purge copy trading tier 1: follow a wallet (your list, local labels), its decoded swaps + FIFO PnL + win rate/early-entry; 'mirror' previews a one-key MIRROR TICKET from the wallet's latest buy (inert; arm in the app)
|
|
315
|
+
dexterm ai [status|engine|model|host|restrictions|probe|ask|agent] the AI engine: your claude / codex CLI or a free LOCAL model on
|
|
316
|
+
your own Ollama (localhost); restriction profiles observe|propose|paper|full ('dexterm ai help')
|
|
309
317
|
dexterm mcp [install <client>|doctor] read-only MCP server for your own agent; 'install' writes the config for claude-code|claude-desktop|cursor|codex|generic (asks first, idempotent, backs up); 'doctor' verifies the connection
|
|
310
318
|
dexterm alerts status|enable|disable|set-telegram|set-discord|test where rule alerts are delivered (desktop / your Telegram / Discord; creds stay local, never logged)
|
|
311
319
|
dexterm watch [--interval S] [--once] [--replay FILE] run your rules headless and push alerts when the terminal is closed (no signer, proposals only)
|
|
@@ -344,8 +352,9 @@ export const HELP = `dexterm ${VERSION} (live: screener, token, new pairs, watch
|
|
|
344
352
|
--selected N highlighted row / token index
|
|
345
353
|
--seed N fixture PRNG seed (default 7)
|
|
346
354
|
--no-ai hide the analyst panel on the token screen
|
|
347
|
-
--analyst-engine E auto | claude | codex: which of YOUR
|
|
348
|
-
if installed, else codex; DEXTERM_ANALYST_ENGINE
|
|
355
|
+
--analyst-engine E auto | claude | codex | ollama: which of YOUR engines runs the analyst (default auto = claude
|
|
356
|
+
if installed, else codex, else a local Ollama model; DEXTERM_ANALYST_ENGINE, config analyst.engine
|
|
357
|
+
or ai.json too; /engine in chat). ollama = a free local model, see 'dexterm ai help'
|
|
349
358
|
|
|
350
359
|
--intensity LEVEL off | normal | fever (default fever: rain, trails, glitch, blink, scanlines at 30 fps;
|
|
351
360
|
normal: 15 fps, sparser rain, no idle aberration; off = calm: neon theme, no motion)
|
|
@@ -364,12 +373,16 @@ export const HELP = `dexterm ${VERSION} (live: screener, token, new pairs, watch
|
|
|
364
373
|
result only; muted by default (also DEXTERM_SOUND=1); ~/.dexterm/sounds holds the WAVs
|
|
365
374
|
--workspace NAME start in a workspace: default | morning-hud | a file in ~/.dexterm/workspaces/ (task-1358);
|
|
366
375
|
in the app ctrl+w then w (list) · n/N (next/prev) · s (save as) · m (morning HUD) · o (popups) · d · 1-9
|
|
367
|
-
--price-mode MODE
|
|
368
|
-
|
|
376
|
+
--price-mode MODE mcap | price: show MARKET CAP (price × a known supply; the default) or USD price on every screen,
|
|
377
|
+
the CLI text and in the assistants' language for this run (default: config.json display.priceMode,
|
|
378
|
+
mcap; \$ in the app toggles and saves it). --mcap / --price (any command) and
|
|
379
|
+
DEXTERM_PRICE_BASIS=mcap|price do the same for one run
|
|
380
|
+
--mcap / --price the price basis for this run on ANY command (dexterm --price autotrade run …), not saved
|
|
369
381
|
dexterm workspace list|show|remove|init the workspace files (no network)
|
|
370
382
|
dexterm theme list|show|init|check user themes in ~/.dexterm/themes (extends a built-in; contrast + hue guarded)
|
|
371
383
|
dexterm keymap [screen] the effective keys (defaults + config.keymap overrides, marked ·)
|
|
372
|
-
dexterm display [price
|
|
384
|
+
dexterm display [mcap|price] show or set the price basis (default market cap = price × a known supply)
|
|
385
|
+
dexterm display markers [on|off] show or hide the BUY/SELL markers of your fills on both charts
|
|
373
386
|
dexterm rules list|add|remove|enable|disable|check|dry-run|fields
|
|
374
387
|
"when <cond> [for n ticks] then alert|ticket|ask|popup|tag|sound|watch" rules in config.json (task-1358);
|
|
375
388
|
parsed never eval'd; mandatory cooldown + max/h; rules only alert or PROPOSE (ctrl+r in the app)
|
|
@@ -382,14 +395,10 @@ export const HELP = `dexterm ${VERSION} (live: screener, token, new pairs, watch
|
|
|
382
395
|
AI SCAN MODE (off by default; observe + analyze only — it can never open a ticket, sign or trade):
|
|
383
396
|
${SCAN_HELP}
|
|
384
397
|
|
|
385
|
-
LIVE TRADING (
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
--
|
|
389
|
-
--max-sol-out N SOL that may leave the wallet in one tx (default 1, ceiling 5)
|
|
390
|
-
--max-slippage-bps N slippage ceiling (default 500, ceiling 1000)
|
|
391
|
-
--trade-rpc URL the signer's RPC (default devnet; must be devnet unless --mainnet)
|
|
392
|
-
--no-live paper only: never start the signer process
|
|
398
|
+
WALLET + LIVE TRADING (dexterm never holds a key and never signs a transaction):
|
|
399
|
+
live trading happens in the Telegram trading bot of your choice, which holds its own wallet; dexterm sends alerts,
|
|
400
|
+
signals and run control to your chat through your own bot (dexterm telegram setup). dexterm places no live order.
|
|
401
|
+
--no-live accepted for older scripts; changes nothing (trading in dexterm is paper only)
|
|
393
402
|
${WALLET_HELP}
|
|
394
403
|
|
|
395
404
|
LOGIN WITH X (task-1357; your own X app, your limits, your bill; read scopes only, no scraping, dexterm never posts):
|
|
@@ -414,17 +423,15 @@ ${X_HELP}
|
|
|
414
423
|
social (task-1330): T trending in the space · K KOL lists · token screen: s social panel · f filter · x hidden spam
|
|
415
424
|
dexterm kol list | create <name> | add <list> @handle | remove <list> @handle | mute @handle | unmute @handle | enable <list> | disable <list> | import <dir> | import-x
|
|
416
425
|
Login with X (task-1357): dexterm x login · then the SOCIAL panel + TRENDING read X with your own limits · KOL screen: X imports your X lists · o = only this handle
|
|
417
|
-
token: B/S buy/sell ticket (PAPER
|
|
426
|
+
token: B/S buy/sell ticket (PAPER) · P positions · w watch
|
|
418
427
|
token: M bubble map (holder graph: clusters by funder / same-slot buys / transfers; colour = rule) · bubble map: M popup · m treemap · z zoom · D deep scan
|
|
419
428
|
demo events on --fixtures: n new pair (glitch) · u pump (gold rain) · d dump (red rain) · x rug flag
|
|
420
429
|
AI scan: Z on/off · R resume scanning after a lock · esc (on the locked coin) cancel the analysis
|
|
421
430
|
any key skips the boot sequence or a blink transition
|
|
422
431
|
|
|
423
432
|
State: ~/.dexterm/state.json remembers launches (DEXTERM_HOME overrides the directory).
|
|
424
|
-
DEXTERM_OFFLINE=1 refuses live data (tests and CI). Trading is PAPER
|
|
425
|
-
priced from live Jupiter quotes.
|
|
426
|
-
quotes, builds, decodes, simulates and enforces the caps; Phantom signs in your browser; dexterm never
|
|
427
|
-
holds a key. The analyst, voice and scan mode can never open, confirm or sign a live trade.
|
|
433
|
+
DEXTERM_OFFLINE=1 refuses live data (tests and CI). Trading in dexterm is PAPER only — a simulated wallet
|
|
434
|
+
priced from live Jupiter quotes. dexterm never holds a key and never signs or sends a transaction.
|
|
428
435
|
RPC: DEXTERM_RPC_URL, else ~/.dexterm/helius.key (Helius, metered with a credit meter), else the public RPC.
|
|
429
436
|
Updates: at most once a day a live run asks npm + GitHub for the newest version (two anonymous GETs, no telemetry)
|
|
430
437
|
and shows one toast if there is one; DEXTERM_NO_UPDATE_CHECK=1 or 'dexterm update --off' turns that off.`;
|
|
@@ -438,7 +445,6 @@ export function parseArgs(argv) {
|
|
|
438
445
|
scan: false, scanConfig: {},
|
|
439
446
|
noRecorder: false,
|
|
440
447
|
sound: false,
|
|
441
|
-
trade: [], live: true,
|
|
442
448
|
workspace: null, priceMode: null,
|
|
443
449
|
spectateMcp: false, spectateThoughts: null, agentPaper: null,
|
|
444
450
|
help: false, version: false, unknown: [],
|
|
@@ -533,7 +539,7 @@ export function parseArgs(argv) {
|
|
|
533
539
|
const s = str();
|
|
534
540
|
const e = parseEngineChoice(s);
|
|
535
541
|
if (!e)
|
|
536
|
-
throw new Error(`unknown analyst engine ${s} (expected auto|claude|codex)`);
|
|
542
|
+
throw new Error(`unknown analyst engine ${s} (expected auto|claude|codex|ollama)`);
|
|
537
543
|
a.analystEngine = e;
|
|
538
544
|
}
|
|
539
545
|
else if (k === '--calm')
|
|
@@ -611,18 +617,10 @@ export function parseArgs(argv) {
|
|
|
611
617
|
a.noRecorder = true;
|
|
612
618
|
else if (k === '--sound')
|
|
613
619
|
a.sound = true;
|
|
614
|
-
// task-
|
|
615
|
-
|
|
616
|
-
else if (k === '--
|
|
617
|
-
a.
|
|
618
|
-
else if (k === '--max-usd' || k === '--daily-usd' || k === '--max-sol-out' || k === '--max-slippage-bps') {
|
|
619
|
-
a.trade.push(k, String(num()));
|
|
620
|
-
}
|
|
621
|
-
else if (k === '--trade-rpc') {
|
|
622
|
-
a.trade.push('--rpc', str());
|
|
623
|
-
}
|
|
624
|
-
else if (k === '--no-live')
|
|
625
|
-
a.live = false;
|
|
620
|
+
// task-1571: dexterm has no live trading of its own; `--no-live` (0.1.6) is accepted and changes nothing.
|
|
621
|
+
else if (k === '--no-live') { /* paper only is the only mode */ }
|
|
622
|
+
else if (k === '--price' || k === '--mcap')
|
|
623
|
+
a.priceMode = k === '--price' ? 'price' : 'mcap'; // task-1537 (main() also takes them before any subcommand)
|
|
626
624
|
else if (k === '--price-mode') {
|
|
627
625
|
const s = str();
|
|
628
626
|
if (!isPriceMode(s))
|
|
@@ -831,6 +829,8 @@ export function fastLaneEndpoints(rpc) {
|
|
|
831
829
|
return out;
|
|
832
830
|
}
|
|
833
831
|
export async function main(argv, io = process, proc = process) {
|
|
832
|
+
// task-1537: `--price` / `--mcap` anywhere = the price basis for this run (every screen, CLI text and agent prompt).
|
|
833
|
+
argv = takeBasisFlags(argv, io.env);
|
|
834
834
|
// `dexterm mcp` → the read-only MCP server on stdio (SPEC §5.1; `claude mcp add dexterm -- dexterm mcp`),
|
|
835
835
|
// plus `dexterm mcp install <client>` (one-command setup) and `dexterm mcp doctor` (verify the connection).
|
|
836
836
|
if (argv[0] === 'mcp') {
|
|
@@ -859,6 +859,17 @@ export async function main(argv, io = process, proc = process) {
|
|
|
859
859
|
const { narrativeCommand } = await import("./narrative-cmd.js");
|
|
860
860
|
return narrativeCommand(argv.slice(1), { stdout: io.stdout, stderr: io.stderr, env: io.env });
|
|
861
861
|
}
|
|
862
|
+
// `dexterm ledger …` → the unified trade ledger (task-1530): reads fold the file + the sources; only `sync` writes. No network, no model, no keys.
|
|
863
|
+
if (argv[0] === 'ledger') {
|
|
864
|
+
const { ledgerCommand } = await import("./ledger-cmd.js");
|
|
865
|
+
return ledgerCommand(argv.slice(1), { stdout: io.stdout, stderr: io.stderr, env: io.env });
|
|
866
|
+
}
|
|
867
|
+
// `dexterm autotrade validate|list|backtest|sweep …` and `dexterm backtest --subject strategy` → the paper autotrade engine (task-1503). No network, no model, no keys.
|
|
868
|
+
if (argv[0] === 'autotrade' || argv[0] === 'backtest') {
|
|
869
|
+
const at = await import("./autotrade-cmd.js");
|
|
870
|
+
if (at.handles(argv))
|
|
871
|
+
return at.autotradeCommand(argv, { stdout: io.stdout, stderr: io.stderr, env: io.env, stdin: io.stdin });
|
|
872
|
+
}
|
|
862
873
|
// `dexterm backtest [--subject heuristic|pack_verdicts] [--horizon SEC]` → honest rug-model metrics over recorded outcomes (task-1356). No network, no model.
|
|
863
874
|
if (argv[0] === 'backtest') {
|
|
864
875
|
const { backtestCommand } = await import("./backtest-cmd.js");
|
|
@@ -921,6 +932,12 @@ export async function main(argv, io = process, proc = process) {
|
|
|
921
932
|
const { alertsCommand } = await import("./alerts-cmd.js");
|
|
922
933
|
return alertsCommand(argv.slice(1), { stdout: io.stdout, stderr: io.stderr, env: io.env, stdin: io.stdin });
|
|
923
934
|
}
|
|
935
|
+
// `dexterm telegram setup|pair|status|approvals|notify|set|test|audit|revoke` → your own bot for the autotrade runner
|
|
936
|
+
// (task-1527). The token goes in the OS secret store (or a 0600 file), never config/argv/env/logs.
|
|
937
|
+
if (argv[0] === 'telegram') {
|
|
938
|
+
const { telegramCommand } = await import("./telegram-cmd.js");
|
|
939
|
+
return telegramCommand(argv.slice(1), { stdout: io.stdout, stderr: io.stderr, env: io.env, stdin: io.stdin });
|
|
940
|
+
}
|
|
924
941
|
// `dexterm watch [--interval S] [--once|--ticks N] [--replay FILE]` → run the rules engine headless and
|
|
925
942
|
// PUSH alerts to the enabled channels so they reach you when the terminal is closed (task-1398). No signer.
|
|
926
943
|
if (argv[0] === 'watch') {
|
|
@@ -943,6 +960,11 @@ export async function main(argv, io = process, proc = process) {
|
|
|
943
960
|
}
|
|
944
961
|
// `dexterm wallet <link|unlink|status>` → link a Phantom wallet via the loopback bridge (keys never
|
|
945
962
|
// enter dexterm; only the pubkey is stored), unlink it, or show the link + trade caps (task-1310 T1).
|
|
963
|
+
// task-1571: `dexterm live …` (the 0.1.7 local signer) was removed before release. dexterm holds no key.
|
|
964
|
+
if (argv[0] === 'live') {
|
|
965
|
+
io.stderr.write('dexterm live: not available. dexterm never holds a key and never signs; live trading happens in the Telegram trading bot of your choice (dexterm telegram setup sends alerts and run control to your chat)\n');
|
|
966
|
+
return 2;
|
|
967
|
+
}
|
|
946
968
|
if (argv[0] === 'wallet') {
|
|
947
969
|
const { runWallet } = await import("./wallet-cmd.js");
|
|
948
970
|
return runWallet(argv.slice(1), io);
|
|
@@ -974,6 +996,11 @@ export async function main(argv, io = process, proc = process) {
|
|
|
974
996
|
const { voiceCommand } = await import("./voice-cmd.js");
|
|
975
997
|
return voiceCommand(argv.slice(1), { stdin: io.stdin, stdout: io.stdout, stderr: io.stderr, env: io.env });
|
|
976
998
|
}
|
|
999
|
+
// task-1543: `dexterm ai …` (engine, local model, restriction profile, probe) and `dexterm ask` (a headless question).
|
|
1000
|
+
if (argv[0] === 'ai' || argv[0] === 'ask') {
|
|
1001
|
+
const { aiCommand } = await import("./ai-cmd.js");
|
|
1002
|
+
return aiCommand(argv[0] === 'ask' ? ['ask', ...argv.slice(1)] : argv.slice(1), { stdin: io.stdin, stdout: io.stdout, stderr: io.stderr, env: io.env });
|
|
1003
|
+
}
|
|
977
1004
|
// `dexterm doctor` → a pre-flight that says whether dexterm will run here and how to fix what won't (task-1305).
|
|
978
1005
|
if (argv[0] === 'doctor') {
|
|
979
1006
|
const { defaultDeps, runDoctor, renderDoctor } = await import("./doctor.js");
|
|
@@ -1069,9 +1096,8 @@ export async function main(argv, io = process, proc = process) {
|
|
|
1069
1096
|
});
|
|
1070
1097
|
ctx = new LiveContext(feed.dl, {
|
|
1071
1098
|
mode: 'live', dbPath: dbOpt, rpc: { provider: rpc.provider, basis: rpc.basis }, record: args.record ? feed.recording ?? undefined : undefined, interval: args.interval, fastEndpoints: fastLaneEndpoints(rpc), onLog: args.verbose ? (l) => io.stderr.write(l) : undefined, allowedSigners: join(dextermHome(io.env), 'allowed_signers'),
|
|
1072
|
-
//
|
|
1073
|
-
|
|
1074
|
-
...(args.live && !io.env.DEXTERM_OFFLINE ? { trade: { signerArgv: args.trade } } : {}),
|
|
1099
|
+
// The wallet link (public key only) is available in a real live run (never replay/offline).
|
|
1100
|
+
...(!io.env.DEXTERM_OFFLINE ? { trade: {} } : {}),
|
|
1075
1101
|
});
|
|
1076
1102
|
// task-1329: the history recorder listens to the data layer's normaliser (zero requests of its own)
|
|
1077
1103
|
// and keeps snapshots / feed membership / outcome labels in the same --db file. Live mode only (a
|
|
@@ -1089,7 +1115,7 @@ export async function main(argv, io = process, proc = process) {
|
|
|
1089
1115
|
ctx.newpairs.onCreator = (mint, creator, source, createdAt) => { recorder.recordCreator(mint, creator, source, undefined, createdAt); };
|
|
1090
1116
|
}
|
|
1091
1117
|
if (args.verbose)
|
|
1092
|
-
io.stderr.write(`dexterm: rpc ${rpc.provider} (${rpc.basis}) · db ${dbPath} · recorder ${ctx.recorder ? 'on' : 'off'} ·
|
|
1118
|
+
io.stderr.write(`dexterm: rpc ${rpc.provider} (${rpc.basis}) · db ${dbPath} · recorder ${ctx.recorder ? 'on' : 'off'} · paper trading only (dexterm holds no key)\n`);
|
|
1093
1119
|
}
|
|
1094
1120
|
if (args.preset && !feed.setPreset(args.preset)) {
|
|
1095
1121
|
const v = feed.presets().find((p) => p.id === args.preset);
|
|
@@ -1151,8 +1177,11 @@ export async function main(argv, io = process, proc = process) {
|
|
|
1151
1177
|
}
|
|
1152
1178
|
for (const e of state.custom.themeErrors)
|
|
1153
1179
|
io.stderr.write(`dexterm: ${e}\n`);
|
|
1154
|
-
|
|
1180
|
+
if (args.priceMode)
|
|
1181
|
+
io.env.DEXTERM_PRICE_BASIS = args.priceMode; // task-1537: the agents follow the run's basis
|
|
1182
|
+
state.priceMode = args.priceMode ?? configPriceMode(state.custom.config, io.env); // task-1366: --price-mode wins for the run; task-1537: then --price/--mcap/env, config, mcap
|
|
1155
1183
|
state.chartAxis = configChartAxis(state.custom.config); // task-1472: default MARKET CAP, `A` toggles + saves
|
|
1184
|
+
state.chartMarkers = configChartMarkers(state.custom.config); // task-1483: BUY/SELL markers on both charts (default on)
|
|
1156
1185
|
if (args.workspace) {
|
|
1157
1186
|
const r = switchWorkspace(state, args.workspace, []);
|
|
1158
1187
|
if (!r.ok) {
|
|
@@ -1385,6 +1414,18 @@ function followsMove(state, delta) {
|
|
|
1385
1414
|
state.copyUi.selected = Math.max(0, Math.min(n - 1, state.copyUi.selected + delta));
|
|
1386
1415
|
return true;
|
|
1387
1416
|
}
|
|
1417
|
+
// task-1508: open (or return to) the AUTOTRADE screen; the strategy list and the runner status are re-read each time.
|
|
1418
|
+
function openAutotrade(state, stack) {
|
|
1419
|
+
if (state.screen !== 'autotrade')
|
|
1420
|
+
stack.push(state.screen);
|
|
1421
|
+
state.screen = 'autotrade';
|
|
1422
|
+
if (!state.autotradeUi) {
|
|
1423
|
+
state.autotradeUi = newAutotradeUi(autotradeDeps(process.env, autotradeWorkerJobs(process.env)));
|
|
1424
|
+
return;
|
|
1425
|
+
}
|
|
1426
|
+
autotradeReload(state.autotradeUi);
|
|
1427
|
+
autotradeRefreshRunner(state.autotradeUi);
|
|
1428
|
+
}
|
|
1388
1429
|
// task-1358 Tier 3: j/k on the RULES screen move the cursor of the active pane (frozen while a rule is being typed).
|
|
1389
1430
|
function rulesScreenMove(state, delta) {
|
|
1390
1431
|
if (state.screen !== 'rules' || !state.rulesUi)
|
|
@@ -1395,7 +1436,7 @@ function rulesScreenMove(state, delta) {
|
|
|
1395
1436
|
function plansMove(state, delta) {
|
|
1396
1437
|
if (state.screen !== 'plans' || !state.plansUi)
|
|
1397
1438
|
return false;
|
|
1398
|
-
if (state.plansUi.arming || state.plansUi.riskModal
|
|
1439
|
+
if (state.plansUi.arming || state.plansUi.riskModal)
|
|
1399
1440
|
return true;
|
|
1400
1441
|
const n = plansRows(state).length;
|
|
1401
1442
|
if (n <= 0) {
|
|
@@ -1441,6 +1482,14 @@ export function applyAction(state, action, stack) {
|
|
|
1441
1482
|
}
|
|
1442
1483
|
return null;
|
|
1443
1484
|
};
|
|
1485
|
+
// task-1508 AUTOTRADE (paper): `Q` opens the screen; while it is open it handles its own verbs and movement
|
|
1486
|
+
// (esc on its strategies list falls through to the normal back). Nothing it does reaches live mode or the signer.
|
|
1487
|
+
if (action === 'screen.autotrade') {
|
|
1488
|
+
openAutotrade(state, stack);
|
|
1489
|
+
return;
|
|
1490
|
+
}
|
|
1491
|
+
if (state.screen === 'autotrade' && state.autotradeUi && autotradeAction(state.autotradeUi, action))
|
|
1492
|
+
return;
|
|
1444
1493
|
switch (action) {
|
|
1445
1494
|
case 'quit': return 'quit';
|
|
1446
1495
|
case 'screen.screener':
|
|
@@ -2090,24 +2139,6 @@ export function applyAction(state, action, stack) {
|
|
|
2090
2139
|
}
|
|
2091
2140
|
break;
|
|
2092
2141
|
}
|
|
2093
|
-
case 'plans.live': {
|
|
2094
|
-
// task-1363: raise the FIRE PATH modal (paper ⇄ live devnet fast wallet). Exactly like arm and gate this
|
|
2095
|
-
// ONLY sets a modal flag; the switch itself happens in the interactive key loop on a captured physical
|
|
2096
|
-
// keypress, and PlanService.useLive refuses any gesture but 'keypress' — so applyAction (a pipe, an
|
|
2097
|
-
// agent, the voice router) can never move fills off paper.
|
|
2098
|
-
if (state.screen !== 'plans')
|
|
2099
|
-
break;
|
|
2100
|
-
const svc = state.plansSvc;
|
|
2101
|
-
if (!svc)
|
|
2102
|
-
break;
|
|
2103
|
-
if (state.plansUi) {
|
|
2104
|
-
state.plansUi.arming = null;
|
|
2105
|
-
state.plansUi.riskModal = false;
|
|
2106
|
-
state.plansUi.liveModal = true;
|
|
2107
|
-
state.plansUi.notice = null;
|
|
2108
|
-
}
|
|
2109
|
-
break;
|
|
2110
|
-
}
|
|
2111
2142
|
// task-1360 copy trading Tier 1: the FOLLOWED WALLETS screen. Opening it binds the follow store (+ the live
|
|
2112
2143
|
// tracker when there is one). `follows.add` only opens the typed-address line (the loop captures the keys);
|
|
2113
2144
|
// `follows.remove` unfollows the selected row. Nothing here trades, proposes or signs.
|
|
@@ -2718,11 +2749,12 @@ export function applyScanAnalystAction(state, raw) {
|
|
|
2718
2749
|
* The analyst engine for a run (0.1.5): `--analyst-engine`, then DEXTERM_ANALYST_ENGINE, then config
|
|
2719
2750
|
* `analyst.engine`, then auto (claude when installed, else codex). Only the user picks it; models cannot.
|
|
2720
2751
|
*/
|
|
2721
|
-
export function analystEngineFor(flag, env, configured, has = (b) => analystCliOnPath(b, env)) {
|
|
2722
|
-
|
|
2752
|
+
export function analystEngineFor(flag, env, configured, has = (b) => analystCliOnPath(b, env), aiChoice) {
|
|
2753
|
+
// task-1543: ai.json (provider / surfaces.analyst / DEXTERM_AI_PROVIDER) comes after the analyst's own settings.
|
|
2754
|
+
const choice = parseEngineChoice(flag) ?? parseEngineChoice(env.DEXTERM_ANALYST_ENGINE) ?? parseEngineChoice(configured) ?? parseEngineChoice(aiChoice) ?? 'auto';
|
|
2723
2755
|
return resolveEngine(choice, has);
|
|
2724
2756
|
}
|
|
2725
|
-
/** `/engine [auto|claude|codex]` in the chat box (0.1.5). Null when the input is not this command. */
|
|
2757
|
+
/** `/engine [auto|claude|codex|ollama]` in the chat box (0.1.5; ollama task-1543). Null when the input is not this command. */
|
|
2726
2758
|
export function parseEngineCommand(q) {
|
|
2727
2759
|
const m = /^\/engine(?:\s+(\S+))?\s*$/i.exec(q.trim());
|
|
2728
2760
|
if (!m)
|
|
@@ -2730,23 +2762,24 @@ export function parseEngineCommand(q) {
|
|
|
2730
2762
|
if (!m[1])
|
|
2731
2763
|
return { show: true };
|
|
2732
2764
|
const c = parseEngineChoice(m[1]);
|
|
2733
|
-
return c ? { choice: c } : { error: `unknown analyst engine "${m[1].slice(0, 16)}" (use /engine auto|claude|codex)` };
|
|
2765
|
+
return c ? { choice: c } : { error: `unknown analyst engine "${m[1].slice(0, 16)}" (use /engine auto|claude|codex|ollama)` };
|
|
2734
2766
|
}
|
|
2735
2767
|
/**
|
|
2736
2768
|
* Apply `/engine`: switch the CLI for NEW conversations this run (cached per-coin chats are dropped so the next
|
|
2737
2769
|
* `a` starts on the chosen engine; a running turn finishes where it started). Returns the line to show.
|
|
2738
2770
|
*/
|
|
2739
|
-
export function engineCommand(state, cmd, env, has = (
|
|
2740
|
-
const installed = ['claude', 'codex'].filter((b) => has(b));
|
|
2741
|
-
const list = installed.length ? installed.join(' + ') : '
|
|
2771
|
+
export function engineCommand(state, cmd, env, has = analystEngineHas(env)) {
|
|
2772
|
+
const installed = ['claude', 'codex', 'ollama'].filter((b) => has(b));
|
|
2773
|
+
const list = installed.length ? installed.join(' + ') : 'no AI engine yet';
|
|
2742
2774
|
if ('error' in cmd)
|
|
2743
2775
|
return cmd.error;
|
|
2744
2776
|
const cur = state.analystEngine ?? 'claude';
|
|
2745
2777
|
if ('show' in cmd)
|
|
2746
|
-
return `analyst engine: ${cur} · installed: ${list} · /engine claude|codex|auto switches (config analyst.engine keeps it)`;
|
|
2778
|
+
return `analyst engine: ${cur} · installed: ${list} · /engine claude|codex|ollama|auto switches (config analyst.engine keeps it)`;
|
|
2747
2779
|
const next = resolveEngine(cmd.choice, has);
|
|
2780
|
+
const how = next === 'codex' ? 'npm i -g @openai/codex && codex login' : next === 'ollama' ? 'install Ollama (https://ollama.com/download), `ollama pull qwen3:8b`, `dexterm ai engine ollama`' : 'install Claude Code, then run claude once to log in';
|
|
2748
2781
|
if (cmd.choice !== 'auto' && !has(next))
|
|
2749
|
-
return `${next} is not
|
|
2782
|
+
return `${next} is not ${next === 'ollama' ? 'set up' : 'installed'} (installed: ${list}); ${how}`;
|
|
2750
2783
|
if (next !== cur) {
|
|
2751
2784
|
for (const [k, sess] of state.analystByMint ?? []) {
|
|
2752
2785
|
if (!sess.busy)
|
|
@@ -2756,6 +2789,8 @@ export function engineCommand(state, cmd, env, has = (b) => analystCliOnPath(b,
|
|
|
2756
2789
|
state.analyst = null;
|
|
2757
2790
|
}
|
|
2758
2791
|
state.analystEngine = next;
|
|
2792
|
+
if (next === 'ollama')
|
|
2793
|
+
return 'analyst engine: ollama (a local model on your own Ollama, $0) for new conversations · `dexterm ai engine ollama` keeps it';
|
|
2759
2794
|
return `analyst engine: ${next} (your own ${next} CLI and login) for new conversations · set analyst.engine in config.json to keep it`;
|
|
2760
2795
|
}
|
|
2761
2796
|
/**
|
|
@@ -2771,7 +2806,7 @@ export function createScanSession(state, mint, symbol, hooks = {}, deps = {}) {
|
|
|
2771
2806
|
const type = typeof raw.type === 'string' ? raw.type.replace(/[^a-z_]/gi, '').slice(0, 24) : '?';
|
|
2772
2807
|
hooks.onBlocked?.(type, r.error ?? 'refused');
|
|
2773
2808
|
};
|
|
2774
|
-
return new AnalystSession({ skill: 'token-dossier', mint, symbol, screenState: ss, onAction, actionTypes: SCAN_ACTION_TYPES, scan: true, ...(state.analystEngine
|
|
2809
|
+
return new AnalystSession({ skill: 'token-dossier', mint, symbol, screenState: ss, onAction, actionTypes: SCAN_ACTION_TYPES, scan: true, ...(state.analystEngine && state.analystEngine !== 'claude' ? { engine: state.analystEngine } : {}) }, hooks.onChange ?? (() => { }), deps);
|
|
2775
2810
|
}
|
|
2776
2811
|
/**
|
|
2777
2812
|
* Resolve a mint to an openable seed from what the app already knows (screener view → new pairs →
|
|
@@ -3069,7 +3104,7 @@ export function ownHeldSample(state, now) {
|
|
|
3069
3104
|
if (!ownOpenedMemo || ownOpenedMemo.mint !== mint || now - ownOpenedMemo.at > 5000) {
|
|
3070
3105
|
let t = null;
|
|
3071
3106
|
try {
|
|
3072
|
-
t = currentPositionFills(
|
|
3107
|
+
t = currentPositionFills(live.wallet.trades(500).filter((x) => x.mint === mint))[0]?.t ?? null;
|
|
3073
3108
|
}
|
|
3074
3109
|
catch {
|
|
3075
3110
|
t = null;
|
|
@@ -3077,7 +3112,7 @@ export function ownHeldSample(state, now) {
|
|
|
3077
3112
|
ownOpenedMemo = { mint, at: now, t };
|
|
3078
3113
|
}
|
|
3079
3114
|
return {
|
|
3080
|
-
mint, symbol: held.symbol, kind:
|
|
3115
|
+
mint, symbol: held.symbol, kind: 'paper',
|
|
3081
3116
|
entryUsd: r.avgEntryUsd, markUsd: r.priceUsd, pnlPct: r.unrealizedPct, pnlUsd: r.unrealizedUsd,
|
|
3082
3117
|
openedAt: ownOpenedMemo.t, targetUsd: r.targetUsd,
|
|
3083
3118
|
};
|
|
@@ -3330,7 +3365,7 @@ export function applyKey(state, key, stack) {
|
|
|
3330
3365
|
popups.push('plans');
|
|
3331
3366
|
const widgets = (p?.openWidgets?.() ?? []).map((w) => w.key); // task-1358 Tier 5: open pack widgets are saved by ref
|
|
3332
3367
|
const entry = saveWorkspace(ui, {
|
|
3333
|
-
name, screen: state.screen, theme: state.theme.name, intensity: state.vfx.intensity, priceMode: state
|
|
3368
|
+
name, screen: state.screen, theme: state.theme.name, intensity: state.vfx.intensity, priceMode: priceModeOf(state),
|
|
3334
3369
|
screener: { preset: sc.preset, filter: sc.query ?? null, sort: `${sc.sort.key}:${sc.sort.dir}` },
|
|
3335
3370
|
token: { tape: !!state.tokenTape, social: !!state.tokenSocial, analyst: state.aiOpen !== false },
|
|
3336
3371
|
popups, widgets,
|
|
@@ -3356,6 +3391,12 @@ export function applyKey(state, key, stack) {
|
|
|
3356
3391
|
// task-1360: typing a wallet address on the FOLLOWED WALLETS screen captures every key until ⏎ / esc.
|
|
3357
3392
|
// task-1358 Tier 3: typing a rule on the RULES screen captures every key until ⏎ / esc. Every keystroke re-runs the
|
|
3358
3393
|
// dry-run ("would match N rows right now"); ⏎ parses + saves (never eval'd), a refusal is the notice.
|
|
3394
|
+
// task-1508: the AUTOTRADE screen's typed lines (a strategy id, a file to import, a field value) and the flatten
|
|
3395
|
+
// confirm capture every key until ⏎ / esc, so q and the screen keys never leak out of a half-typed value.
|
|
3396
|
+
if (state.screen === 'autotrade' && state.autotradeUi && autotradeCapturing(state.autotradeUi)) {
|
|
3397
|
+
autotradeKey(state.autotradeUi, key);
|
|
3398
|
+
return;
|
|
3399
|
+
}
|
|
3359
3400
|
if (state.screen === 'rules' && state.rulesUi && state.rulesUi.input !== null) {
|
|
3360
3401
|
const ui = state.rulesUi;
|
|
3361
3402
|
const cur = state.rulesUi.input;
|
|
@@ -3694,8 +3735,8 @@ export function fpsFor(args, intensity) {
|
|
|
3694
3735
|
const SYNC_ON = '\x1b[?2026h';
|
|
3695
3736
|
const SYNC_OFF = '\x1b[?2026l';
|
|
3696
3737
|
export function interactive(state, io, depth, args, proc = process) {
|
|
3697
|
-
// 0.1.5: the analyst engine for new conversations (the user's own claude or codex CLI; never a shipped key).
|
|
3698
|
-
state.analystEngine ??= analystEngineFor(args.analystEngine, io.env, state.custom?.config.analyst?.engine);
|
|
3738
|
+
// 0.1.5: the analyst engine for new conversations (the user's own claude or codex CLI, or task-1543 a local Ollama model; never a shipped key).
|
|
3739
|
+
state.analystEngine ??= analystEngineFor(args.analystEngine, io.env, state.custom?.config.analyst?.engine, analystEngineHas(io.env), analystAiChoice(io.env));
|
|
3699
3740
|
const out = io.stdout;
|
|
3700
3741
|
const inp = io.stdin;
|
|
3701
3742
|
const rnd = mulberry32(99);
|
|
@@ -4121,7 +4162,7 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
4121
4162
|
// task-1340: a send in flight shows the neutral scanning sweep (never a verdict); it clears when the ticket settles.
|
|
4122
4163
|
if (reason === 'ticket') {
|
|
4123
4164
|
const ph = live.ticket?.ticket.phase;
|
|
4124
|
-
if (ph === 'filling'
|
|
4165
|
+
if (ph === 'filling') {
|
|
4125
4166
|
if (v.moment?.kind !== 'inflight')
|
|
4126
4167
|
fireInflight(v, live.ticket?.ticket.symbol ?? '', ticketOrigin());
|
|
4127
4168
|
}
|
|
@@ -4313,7 +4354,7 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
4313
4354
|
maybeSpeakVoiceAnswer(session); // task-1282: speak a voice-initiated answer when it settles
|
|
4314
4355
|
scheduleDraw();
|
|
4315
4356
|
};
|
|
4316
|
-
const session = new AnalystSession({ skill: p.skill, mint: p.mint, symbol: p.symbol, screenState: buildScreenState(state), model: p.model, onAction, ...(state.analystEngine
|
|
4357
|
+
const session = new AnalystSession({ skill: p.skill, mint: p.mint, symbol: p.symbol, screenState: buildScreenState(state), model: p.model, onAction, ...(state.analystEngine && state.analystEngine !== 'claude' ? { engine: state.analystEngine } : {}) }, onChange);
|
|
4317
4358
|
if (p.question)
|
|
4318
4359
|
session.ask(p.question, buildScreenState(state));
|
|
4319
4360
|
else
|
|
@@ -4523,7 +4564,7 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
4523
4564
|
livePrice: (mint) => (live.badgeFor(mint) === 'LIVE' ? live.livePrice(mint) : null),
|
|
4524
4565
|
feed: (mint) => (live.badgeFor(mint) === 'LIVE' ? 'LIVE' : 'POLL'),
|
|
4525
4566
|
positions: live.positionSource,
|
|
4526
|
-
fills: (mint) =>
|
|
4567
|
+
fills: (mint) => live.wallet.trades(500).filter((t) => t.mint === mint),
|
|
4527
4568
|
solUsd: () => state.sol?.price ?? live.positions.solUsd(),
|
|
4528
4569
|
imagePath: (v) => popupImagePath(state, v.image),
|
|
4529
4570
|
priceMode: () => priceModeOf(state), // task-1366
|
|
@@ -4531,6 +4572,10 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
4531
4572
|
setChartAxis: (a) => { say(setChartAxis(state, a), 'info', 3); if (!done)
|
|
4532
4573
|
draw(); }, // task-1472: the popup's MCAP | PRICE control
|
|
4533
4574
|
pnlChip: () => pnlChipFor(state, state.agentHud?.clock() ?? Date.now()), // task-1473 r2: the chip on the chart popup
|
|
4575
|
+
markFills: (mint) => live.chartFills.for(mint), // task-1483: BUY/SELL markers (the paper ledger, no fetch)
|
|
4576
|
+
chartMarkers: () => chartMarkersOn(state),
|
|
4577
|
+
setChartMarkers: (on) => { say(setChartMarkers(state, on ? 'on' : 'off'), 'info', 3); if (!done)
|
|
4578
|
+
draw(); }, // task-1483: the popup's MARKERS control
|
|
4534
4579
|
} : null,
|
|
4535
4580
|
});
|
|
4536
4581
|
}
|
|
@@ -4794,7 +4839,7 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
4794
4839
|
else {
|
|
4795
4840
|
try {
|
|
4796
4841
|
const s = seedForMint(state, live, tk.mint, tk.symbol);
|
|
4797
|
-
live.openTicket({ mint: s.mint, symbol: s.symbol, name: s.name }, tk.side
|
|
4842
|
+
live.openTicket({ mint: s.mint, symbol: s.symbol, name: s.name }, tk.side);
|
|
4798
4843
|
if (state.screen !== 'ticket')
|
|
4799
4844
|
stack.push(state.screen);
|
|
4800
4845
|
state.screen = 'ticket';
|
|
@@ -5038,7 +5083,7 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
5038
5083
|
const res = resolveVoiceToken(d.target);
|
|
5039
5084
|
if (res.kind === 'ok' && live) {
|
|
5040
5085
|
const s = seedForMint(state, live, res.mint);
|
|
5041
|
-
live.openTicket({ mint: s.mint, symbol: s.symbol, name: s.name }, d.side
|
|
5086
|
+
live.openTicket({ mint: s.mint, symbol: s.symbol, name: s.name }, d.side);
|
|
5042
5087
|
if (state.screen !== 'ticket')
|
|
5043
5088
|
stack.push(state.screen);
|
|
5044
5089
|
state.screen = 'ticket';
|
|
@@ -5353,7 +5398,9 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
5353
5398
|
// task-1388 GO-TO prompt: while the "open any coin" input is open it owns the keyboard. Route the key
|
|
5354
5399
|
// straight to applyKey (which does the capture / open) and skip the voice, calm, demo and keymap
|
|
5355
5400
|
// handlers below — otherwise a base58 char like v / m / c would toggle voice or calm instead of typing.
|
|
5356
|
-
|
|
5401
|
+
// task-1508: the AUTOTRADE screen's typed lines (an id, a file, a field value) and its flatten confirm own the
|
|
5402
|
+
// keyboard the same way, so v / m / c / n / d / x type instead of toggling voice, calm or a demo event.
|
|
5403
|
+
if (state.goto || (state.screen === 'autotrade' && state.autotradeUi && autotradeCapturing(state.autotradeUi))) {
|
|
5357
5404
|
const before = state.screen;
|
|
5358
5405
|
try {
|
|
5359
5406
|
applyKey(state, key, stack);
|
|
@@ -5583,33 +5630,10 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
5583
5630
|
}
|
|
5584
5631
|
// else: fall through to the keymap (quit/navigation remain responsive while filling)
|
|
5585
5632
|
}
|
|
5586
|
-
// task-1328 LIVE: while the signer builds the plan, esc cancels; while Phantom has the plan
|
|
5587
|
-
// (signing) no key does anything — the signer finishes or times out, and nothing here can
|
|
5588
|
-
// confirm, so navigation keys still fall through to the keymap.
|
|
5589
|
-
if (state.screen === 'ticket' && live?.ticket && live.ticket.ticket.phase === 'planning') {
|
|
5590
|
-
if (key.name === 'esc') {
|
|
5591
|
-
live.ticket.cancelPlan();
|
|
5592
|
-
draw();
|
|
5593
|
-
continue;
|
|
5594
|
-
}
|
|
5595
|
-
// task-1368: while Jupiter is rate limiting the signer the ticket waits and retries by itself; r retries now.
|
|
5596
|
-
if (key.name === 'char' && (key.ch === 'r' || key.ch === 'R') && !key.ctrl && !key.alt) {
|
|
5597
|
-
live.ticket.retryPlan();
|
|
5598
|
-
draw();
|
|
5599
|
-
continue;
|
|
5600
|
-
}
|
|
5601
|
-
}
|
|
5602
|
-
if (state.screen === 'ticket' && live?.ticket && live.ticket.ticket.phase === 'signing') {
|
|
5603
|
-
if (key.name === 'esc') {
|
|
5604
|
-
state.pendingToast = 'waiting for Phantom — approve or reject it in the browser';
|
|
5605
|
-
draw();
|
|
5606
|
-
continue;
|
|
5607
|
-
}
|
|
5608
|
-
}
|
|
5609
5633
|
// PAPER trade ticket (task-1310): the ticket captures every key (digits/y/esc/tab/…) so the
|
|
5610
5634
|
// confirm gate can never be satisfied by a stray key, and `q`/`1`-`4` cannot quit or navigate
|
|
5611
5635
|
// out from under a half-typed order. `filling` is handled above so the user is never trapped.
|
|
5612
|
-
const ticketActive = state.screen === 'ticket' && live?.ticket && live.ticket.ticket.phase !== 'filled' && live.ticket.ticket.phase !== 'error' && live.ticket.ticket.phase !== '
|
|
5636
|
+
const ticketActive = state.screen === 'ticket' && live?.ticket && live.ticket.ticket.phase !== 'filled' && live.ticket.ticket.phase !== 'error' && live.ticket.ticket.phase !== 'filling';
|
|
5613
5637
|
if (ticketActive && live?.ticket) {
|
|
5614
5638
|
let eff;
|
|
5615
5639
|
try {
|
|
@@ -5715,79 +5739,6 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
5715
5739
|
// 'keypress'}) — which the engine takes ONLY from a real keypress, journals, and auto-expires in 24h;
|
|
5716
5740
|
// restoreGate() puts it back. There is no path here for a pipe/agent (TTY-only loop, no way to raise
|
|
5717
5741
|
// the modal except a person pressing G), and signer caps/allow-lists/panic are unaffected either way.
|
|
5718
|
-
// task-1363 — the FIRE PATH modal: paper ⇄ LIVE (devnet, the capped fast wallet). Same captured-keypress
|
|
5719
|
-
// discipline as arm/gate: enter/y switches, esc cancels, every other key is swallowed. Going LIVE needs
|
|
5720
|
-
// the run's signer process (never started in replay/offline/--no-live), the signer on DEVNET with a fast
|
|
5721
|
-
// wallet loaded (checked by LivePlanExecutor.ready), and no armed/filled plans; PlanService.useLive
|
|
5722
|
-
// takes ONLY a keypress gesture and journals the switch. Nothing here signs: fills still go through the
|
|
5723
|
-
// signer's own policy, simulation and caps, and the fast wallet never signs for the main wallet.
|
|
5724
|
-
if (state.screen === 'plans' && state.plansUi?.liveModal) {
|
|
5725
|
-
const ui = state.plansUi;
|
|
5726
|
-
if (key.name === 'esc') {
|
|
5727
|
-
ui.liveModal = false;
|
|
5728
|
-
ui.notice = 'fire path unchanged';
|
|
5729
|
-
draw();
|
|
5730
|
-
continue;
|
|
5731
|
-
}
|
|
5732
|
-
const confirmKey = key.name === 'enter' || (key.name === 'char' && !key.ctrl && !key.alt && (key.ch === 'y' || key.ch === 'Y'));
|
|
5733
|
-
if (confirmKey) {
|
|
5734
|
-
const svc = state.plansSvc;
|
|
5735
|
-
ui.liveModal = false;
|
|
5736
|
-
if (!svc) {
|
|
5737
|
-
ui.notice = 'no plan service';
|
|
5738
|
-
draw();
|
|
5739
|
-
continue;
|
|
5740
|
-
}
|
|
5741
|
-
if (svc.mode() === 'live') {
|
|
5742
|
-
try {
|
|
5743
|
-
svc.usePaper();
|
|
5744
|
-
ui.notice = 'fire path: PAPER — fills are simulated again';
|
|
5745
|
-
}
|
|
5746
|
-
catch (e) {
|
|
5747
|
-
ui.notice = `switch refused: ${describeError(e)}`;
|
|
5748
|
-
}
|
|
5749
|
-
draw();
|
|
5750
|
-
continue;
|
|
5751
|
-
}
|
|
5752
|
-
const port = live?.ensureSigner() ?? null;
|
|
5753
|
-
if (!port) {
|
|
5754
|
-
ui.notice = 'LIVE fills need the signer process: start dexterm live (not replay/offline/--no-live)';
|
|
5755
|
-
draw();
|
|
5756
|
-
continue;
|
|
5757
|
-
}
|
|
5758
|
-
if (svc.engine.openPlans().length) {
|
|
5759
|
-
ui.notice = `switch refused: cancel or finish ${svc.engine.openPlans().length} open plan(s) first`;
|
|
5760
|
-
draw();
|
|
5761
|
-
continue;
|
|
5762
|
-
}
|
|
5763
|
-
const ex = new LivePlanExecutor({ signer: port, clock: { now: () => Date.now(), sleep: (ms) => new Promise((r) => setTimeout(r, ms)) }, solUsd: () => state.sol?.price ?? live?.positions.solUsd() ?? null, onChange: () => { if (!done) {
|
|
5764
|
-
plansTick();
|
|
5765
|
-
draw();
|
|
5766
|
-
} }, log: (l) => args.verbose && io.stderr.write(` plans-live ${l}\n`) });
|
|
5767
|
-
ui.notice = 'checking the signer and the fast wallet…';
|
|
5768
|
-
void ex.ready().then((r) => {
|
|
5769
|
-
if (done)
|
|
5770
|
-
return;
|
|
5771
|
-
if (!r.ok) {
|
|
5772
|
-
ui.notice = `LIVE refused: ${r.why}`;
|
|
5773
|
-
draw();
|
|
5774
|
-
return;
|
|
5775
|
-
}
|
|
5776
|
-
try {
|
|
5777
|
-
svc.useLive(ex, { gesture: 'keypress' });
|
|
5778
|
-
ui.notice = `fire path: ${ex.describe(r.fastWallet)} · balance ${r.balanceLamports === null ? '?' : (Number(r.balanceLamports) / 1e9).toFixed(4)} SOL · L again for paper`;
|
|
5779
|
-
}
|
|
5780
|
-
catch (e) {
|
|
5781
|
-
ui.notice = `switch refused: ${describeError(e)}`;
|
|
5782
|
-
}
|
|
5783
|
-
draw();
|
|
5784
|
-
});
|
|
5785
|
-
draw();
|
|
5786
|
-
continue;
|
|
5787
|
-
}
|
|
5788
|
-
draw();
|
|
5789
|
-
continue;
|
|
5790
|
-
}
|
|
5791
5742
|
if (state.screen === 'plans' && state.plansUi?.riskModal) {
|
|
5792
5743
|
const ui = state.plansUi;
|
|
5793
5744
|
if (key.name === 'esc') {
|
|
@@ -5844,7 +5795,7 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
5844
5795
|
draw();
|
|
5845
5796
|
continue;
|
|
5846
5797
|
}
|
|
5847
|
-
// 0.1.5: `/engine [auto|claude|codex]` switches the analyst
|
|
5798
|
+
// 0.1.5: `/engine [auto|claude|codex|ollama]` switches the analyst engine for new conversations; never sent to a model.
|
|
5848
5799
|
const en0 = q.startsWith('/') ? parseEngineCommand(q) : null;
|
|
5849
5800
|
if (en0) {
|
|
5850
5801
|
state.aiInput = '';
|
|
@@ -5852,6 +5803,14 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
5852
5803
|
draw();
|
|
5853
5804
|
continue;
|
|
5854
5805
|
}
|
|
5806
|
+
// task-1537: `/display mcap|price` (also `/basis …`, `/set basis …`) sets the price basis; never sent to a model.
|
|
5807
|
+
const dc0 = q.startsWith('/') ? parseDisplayCommand(q) : null;
|
|
5808
|
+
if (dc0) {
|
|
5809
|
+
state.aiInput = '';
|
|
5810
|
+
say('error' in dc0 ? dc0.error : 'mode' in dc0 ? setPriceMode(state, dc0.mode, '/display') : priceModeNotice(state), 'error' in dc0 ? 'warn' : 'info', 6);
|
|
5811
|
+
draw();
|
|
5812
|
+
continue;
|
|
5813
|
+
}
|
|
5855
5814
|
// task-1324: `/scan …` in the chat input is a command, never sent to claude.
|
|
5856
5815
|
const sc0 = q.startsWith('/') ? parseScanCommand(q) : null;
|
|
5857
5816
|
if (sc0) {
|
|
@@ -6012,7 +5971,8 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
6012
5971
|
const sc = state.screener;
|
|
6013
5972
|
const editing = state.screen === 'screener' && sc.mode !== 'table';
|
|
6014
5973
|
const plain = key.name === 'char' && !key.ctrl && !key.alt && key.ch !== undefined;
|
|
6015
|
-
|
|
5974
|
+
// task-1508: on the AUTOTRADE screen `c` marks strategies to compare (calm stays reachable from any other screen).
|
|
5975
|
+
if (!editing && plain && key.ch === 'c' && state.screen !== 'autotrade') {
|
|
6016
5976
|
// calm toggle: off ↔ the last active tier
|
|
6017
5977
|
if (isCalm(v)) {
|
|
6018
5978
|
v.intensity = lastIntensity;
|
|
@@ -6026,7 +5986,7 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
6026
5986
|
flusher.invalidate();
|
|
6027
5987
|
continue;
|
|
6028
5988
|
}
|
|
6029
|
-
if (!editing && plain && sc.source === 'fixtures' && Object.hasOwn(DEMO_KEYS, key.ch)) {
|
|
5989
|
+
if (!editing && plain && sc.source === 'fixtures' && state.screen !== 'autotrade' && Object.hasOwn(DEMO_KEYS, key.ch)) {
|
|
6030
5990
|
const kind = DEMO_KEYS[key.ch];
|
|
6031
5991
|
try {
|
|
6032
5992
|
const text = demoEvent(state, kind, rnd);
|
|
@@ -6095,7 +6055,7 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
6095
6055
|
if (state.screen === 'plans')
|
|
6096
6056
|
syncPlansPopup(); // arm / cancel / tick status changes reach the popup
|
|
6097
6057
|
syncWidgets(); // task-1358 Tier 5: open pack widgets follow the terminal (throttled per widget + topic)
|
|
6098
|
-
// task-1328: `/wallet …` — performed here because link opens a browser
|
|
6058
|
+
// task-1328: `/wallet …` — performed here because link opens a browser.
|
|
6099
6059
|
if (state.pendingWallet) {
|
|
6100
6060
|
const wc = state.pendingWallet;
|
|
6101
6061
|
state.pendingWallet = null;
|
|
@@ -6107,12 +6067,6 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
6107
6067
|
void live.walletCommand(wc).then((line) => {
|
|
6108
6068
|
if (done)
|
|
6109
6069
|
return;
|
|
6110
|
-
if (wc === 'probe' && live.ticket && live.ticket.ticket.mode === 'live') {
|
|
6111
|
-
if (state.screen !== 'ticket') {
|
|
6112
|
-
stack.push(state.screen);
|
|
6113
|
-
state.screen = 'ticket';
|
|
6114
|
-
}
|
|
6115
|
-
}
|
|
6116
6070
|
say(line, wc === 'panic' ? 'warn' : 'info', 8);
|
|
6117
6071
|
scheduleDraw();
|
|
6118
6072
|
}).catch((e) => { say(`wallet ${wc} failed: ${describeError(e)}`, 'warn', 6); scheduleDraw(); });
|
|
@@ -6215,6 +6169,9 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
6215
6169
|
say(state.updateNotice, 'info', 8);
|
|
6216
6170
|
state.updateNotice = null;
|
|
6217
6171
|
}
|
|
6172
|
+
// task-1508: the autotrade screen re-reads the paper runner's status file every 2 s while it is open.
|
|
6173
|
+
if (state.screen === 'autotrade' && state.autotradeUi)
|
|
6174
|
+
autotradeTick(state.autotradeUi);
|
|
6218
6175
|
if (feed) {
|
|
6219
6176
|
if (!state.paused && Date.now() - lastRefresh >= LIVE_REFRESH_MS)
|
|
6220
6177
|
refresh();
|