dexterm-cli 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/agents/src/schema.js +22 -1
- package/dist/packages/agents/src/story.js +11 -2
- package/dist/packages/agents/src/tiers.js +27 -2
- package/dist/packages/agents/src/tools.js +30 -2
- package/dist/packages/autotrade/assets/exit-profile.schema.json +492 -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/src/account.js +74 -0
- package/dist/packages/autotrade/src/backtest.js +357 -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 +93 -0
- package/dist/packages/autotrade/src/chat/connector.js +24 -0
- package/dist/packages/autotrade/src/chat/control.js +103 -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 +292 -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 +99 -0
- package/dist/packages/autotrade/src/chat/service.js +248 -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 +387 -0
- package/dist/packages/autotrade/src/execution-port.js +97 -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 +639 -0
- package/dist/packages/autotrade/src/index.js +53 -0
- package/dist/packages/autotrade/src/ledger.js +108 -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/paper-accounts.js +72 -0
- package/dist/packages/autotrade/src/replay.js +198 -0
- package/dist/packages/autotrade/src/runner-config.js +99 -0
- package/dist/packages/autotrade/src/runner.js +872 -0
- package/dist/packages/autotrade/src/safety.js +243 -0
- package/dist/packages/autotrade/src/session.js +269 -0
- package/dist/packages/autotrade/src/sessions.js +503 -0
- package/dist/packages/autotrade/src/store.js +250 -0
- package/dist/packages/autotrade/src/strategy.js +256 -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 +82 -15
- package/dist/packages/cli/src/analyst/codex.js +14 -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 +44 -8
- package/dist/packages/cli/src/autotrade-cmd/audit.js +57 -0
- package/dist/packages/cli/src/autotrade-cmd/backtest.js +199 -0
- package/dist/packages/cli/src/autotrade-cmd/flatten.js +64 -0
- package/dist/packages/cli/src/autotrade-cmd/fleet.js +397 -0
- package/dist/packages/cli/src/autotrade-cmd/requests.js +79 -0
- package/dist/packages/cli/src/autotrade-cmd/run.js +413 -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 +168 -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 +288 -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 +158 -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-keys.js +169 -0
- package/dist/packages/cli/src/screens/autotrade-proposals.js +123 -0
- package/dist/packages/cli/src/screens/autotrade-screen.js +725 -0
- package/dist/packages/cli/src/screens/autotrade-ui.js +640 -0
- package/dist/packages/cli/src/screens/autotrade-worker.js +89 -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 +451 -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-parallel.md +42 -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 +217 -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 +49 -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 +37 -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 +35 -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-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 +43 -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-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-live-trading-changed-in-0-1-7.md +26 -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 +33 -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-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 +38 -0
- package/dist/packages/mcp/src/app-help.js +1 -1
- package/dist/packages/mcp/src/autotrade-tools.js +944 -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 +346 -0
- package/dist/packages/mcp/src/paper-agent.js +2 -0
- package/dist/packages/mcp/src/server.js +127 -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 +21 -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,89 @@
|
|
|
1
|
+
// dexterm — AUTOTRADE screen backtests off the render loop (task-1508). A lockstep backtest over two weeks of
|
|
2
|
+
// recorded history is CPU-bound for seconds and a sweep for much longer, so the Q screen runs them in a worker
|
|
3
|
+
// thread: the worker opens the recorder DB read-only, builds the tape once, runs the engine and posts the
|
|
4
|
+
// report back. PAPER, recorded data only: no network, no model, no keys. The same module is the worker entry
|
|
5
|
+
// (it checks workerData) and the main-thread client (workerJobs). Tests use inlineJobs over a fixture tape.
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import { Worker, isMainThread, parentPort, workerData } from 'node:worker_threads';
|
|
8
|
+
import { defaultDbPath } from '../../../data/src/index.js';
|
|
9
|
+
import { openHistoryReadOnly } from '../../../recorder/src/index.js';
|
|
10
|
+
import { backtest, sweep, tapeFromDb, tapeFromDoc } from '../../../autotrade/src/index.js';
|
|
11
|
+
const DAY_MS = 86_400_000;
|
|
12
|
+
/** The equity curve is resampled to this many points before it crosses the thread boundary (it feeds a sparkline). */
|
|
13
|
+
const CURVE_POINTS = 240;
|
|
14
|
+
const TAG = 'dexterm-autotrade-job/1';
|
|
15
|
+
function resample(xs, n) {
|
|
16
|
+
if (xs.length <= n)
|
|
17
|
+
return xs;
|
|
18
|
+
return Array.from({ length: n }, (_, i) => xs[Math.round((i * (xs.length - 1)) / (n - 1))]);
|
|
19
|
+
}
|
|
20
|
+
/** The recorder's history as a tape, read-only (the same window rules as `dexterm autotrade backtest --days N`). */
|
|
21
|
+
export function tapeFromRecorder(dbPath, days, until) {
|
|
22
|
+
const none = `no recorded history in ${dbPath} (run the app with the recorder on first)`;
|
|
23
|
+
if (!existsSync(dbPath))
|
|
24
|
+
throw new Error(none);
|
|
25
|
+
let db;
|
|
26
|
+
try {
|
|
27
|
+
db = openHistoryReadOnly(dbPath);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
throw new Error(none);
|
|
31
|
+
}
|
|
32
|
+
if (!db)
|
|
33
|
+
throw new Error(none);
|
|
34
|
+
try {
|
|
35
|
+
return tapeFromDoc(tapeFromDb(db, { since: until - days * DAY_MS, until, minPeakLiqUsd: 20_000, spanHours: 80 }));
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
db.close();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function backtestOn(tape, ss) {
|
|
42
|
+
const out = [];
|
|
43
|
+
for (const s of ss) {
|
|
44
|
+
const { report, run } = await backtest(s, tape);
|
|
45
|
+
out.push({ report, curve: resample(run.equityCurve.map((p) => p.equity), CURVE_POINTS) });
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
/** Jobs that run on the calling thread over a tape the caller supplies (tests, over a committed fixture tape). */
|
|
50
|
+
export function inlineJobs(tape) {
|
|
51
|
+
return {
|
|
52
|
+
backtest: async (ss) => backtestOn(tape(), ss),
|
|
53
|
+
sweep: async (s, grid) => sweep(s, tape(), grid),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Jobs in a worker thread over the recorder DB (the app). One worker per job; it exits when done. */
|
|
57
|
+
export function workerJobs(env = process.env) {
|
|
58
|
+
const dbPath = env.DEXTERM_DB_PATH || defaultDbPath(env);
|
|
59
|
+
const run = (job) => new Promise((resolve, reject) => {
|
|
60
|
+
const w = new Worker(new URL(import.meta.url), { workerData: { tag: TAG, job } });
|
|
61
|
+
w.unref();
|
|
62
|
+
w.once('message', (m) => { if (m.ok)
|
|
63
|
+
resolve(m.value);
|
|
64
|
+
else
|
|
65
|
+
reject(new Error(m.error)); });
|
|
66
|
+
w.once('error', reject);
|
|
67
|
+
w.once('exit', (code) => { if (code !== 0)
|
|
68
|
+
reject(new Error(`backtest worker exited with code ${code}`)); });
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
backtest: (strategies, o) => run({ kind: 'backtest', strategies, days: o.days, until: o.until, dbPath }),
|
|
72
|
+
sweep: (strategy, grid, o) => run({ kind: 'sweep', strategy, grid, days: o.days, until: o.until, dbPath }),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// ───────────────────────────── worker entry ─────────────────────────────
|
|
76
|
+
if (!isMainThread && parentPort && workerData?.tag === TAG) {
|
|
77
|
+
const job = workerData.job;
|
|
78
|
+
const port = parentPort;
|
|
79
|
+
void (async () => {
|
|
80
|
+
try {
|
|
81
|
+
const tape = tapeFromRecorder(job.dbPath, job.days, job.until);
|
|
82
|
+
const value = job.kind === 'backtest' ? await backtestOn(tape, job.strategies) : await sweep(job.strategy, tape, job.grid);
|
|
83
|
+
port.postMessage({ ok: true, value });
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
port.postMessage({ ok: false, error: e.message ?? String(e) });
|
|
87
|
+
}
|
|
88
|
+
})();
|
|
89
|
+
}
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
// mode: the scan's own log plus the scan analyst's answer.
|
|
7
7
|
// 2. VETTING $SYM: the checklist for the coin in focus, each box with the number the app computed and pass / warn /
|
|
8
8
|
// fail / pending (pending = the number is not in yet). A ◆ marks the checks the agent itself ran.
|
|
9
|
-
// 3. DATA: mcap, price, liquidity, 5m / 1h, buy/sell flow, holders, and a candle trace
|
|
9
|
+
// 3. DATA: mcap, price, liquidity, 5m / 1h, buy/sell flow, holders, and a candle trace (task-1483: with a B / S cell
|
|
10
|
+
// on the candle of every paper / live fill of the coin, from the ledgers; the rest is said, never moved).
|
|
10
11
|
// 4. PLAN · POSITION (only while a PAPER ticket / position exists): entry, size, TP / stop, mark PnL, peak, time held,
|
|
11
12
|
// what it is waiting for.
|
|
12
13
|
// 5. DECISIONS: the session log (passed X because…, rejected Y, entered Z) and the scoreboard (PAPER, simulated).
|
|
@@ -15,7 +16,7 @@
|
|
|
15
16
|
// panel has no input. Agent text arrives scrubbed and clipped (story.ribbonText) with addresses shortened.
|
|
16
17
|
// Smaller panels drop blocks in priority order (decisions, then data, then the vetting list folds to two columns);
|
|
17
18
|
// calm mode shows the same information with no typing; NO_COLOR keeps meaning in glyphs (✓ ! ✗ · ◆ ❯ ›).
|
|
18
|
-
import { mix, clock, decryptText, fmtUsd, fmtPrice, fmtNum, wrap } from '../../../tui/src/index.js';
|
|
19
|
+
import { mix, clock, decryptText, fmtUsd, fmtPrice, fmtMcap, fmtNum, wrap, chartMarkers, markerLetter, MARKER_PERIOD_MS } from '../../../tui/src/index.js';
|
|
19
20
|
import { ribbonText, ribbonLines, fmtPx } from '../../../agents/src/index.js';
|
|
20
21
|
// ---------------------------------------------------------------------------------------------------------------
|
|
21
22
|
// formatting (deterministic, no locale)
|
|
@@ -73,8 +74,18 @@ export function factsFromView(v, extra = {}) {
|
|
|
73
74
|
holders: v.holders, top10: extra.top10 ?? v.top10, mintAuth: v.mintAuth, freezeAuth: v.freezeAuth, lpLocked: v.lpLocked,
|
|
74
75
|
dev: extra.dev ?? (v.devMints === null ? null : [`${v.devMints} mints by dev (jup)`, v.devMints > 3 ? 'warn' : 'ok']),
|
|
75
76
|
rugScore: v.rug?.score ?? null, larpVerdict: extra.larpVerdict ?? null, closes: v.candles.map((k) => k.c),
|
|
77
|
+
closeTimes: v.candles.map((k) => k.t), periodMs: MARKER_PERIOD_MS[v.interval], fills: extra.fills ?? undefined,
|
|
76
78
|
};
|
|
77
79
|
}
|
|
80
|
+
/** task-1483: the trace's B / S cells for the last `width` closes (the same model as the charts; display only). */
|
|
81
|
+
export function traceMarks(f, width = 240) {
|
|
82
|
+
if (!f || !f.fills?.length || !f.closeTimes || f.closeTimes.length !== f.closes.length || !f.periodMs)
|
|
83
|
+
return null;
|
|
84
|
+
const times = f.closeTimes.slice(-width);
|
|
85
|
+
const set = chartMarkers(f.fills, { periodMs: f.periodMs, barTimes: times });
|
|
86
|
+
const off0 = f.closes.length - times.length;
|
|
87
|
+
return { cells: set.markers.map((m) => ({ index: off0 + m.index, side: m.side, source: m.source, count: m.count })), off: set.before + set.after + set.gap };
|
|
88
|
+
}
|
|
78
89
|
// ---------------------------------------------------------------------------------------------------------------
|
|
79
90
|
// 1) reasoning stream
|
|
80
91
|
/** Agent thoughts and dexterm narration, newest last (≤ max). */
|
|
@@ -216,12 +227,18 @@ export function planFromThoughts(thoughts, since) {
|
|
|
216
227
|
return { tp, stop };
|
|
217
228
|
}
|
|
218
229
|
/** The PLAN / POSITION block for the agent's PAPER arc (null when there is no ticket or position). */
|
|
219
|
-
|
|
230
|
+
/** task-1537: the coin's supply from its facts (mcap ÷ price at the same tick), null when either is missing. */
|
|
231
|
+
function capScale(f) {
|
|
232
|
+
return f.mcap !== null && f.price !== null && f.price > 0 && f.mcap > 0 ? { mint: f.mint, supply: f.mcap / f.price } : null;
|
|
233
|
+
}
|
|
234
|
+
export function planVM(v, now, cap = null) {
|
|
220
235
|
const a = v.arc;
|
|
221
236
|
if (!a || a.stage === 'closed' || a.stage === 'refused')
|
|
222
237
|
return null;
|
|
223
238
|
const said = planFromThoughts(v.thoughts, a.openedAt);
|
|
224
239
|
const open = a.stage === 'open';
|
|
240
|
+
// task-1537: entry / mark as market caps when the card's coin has a known supply, else prices
|
|
241
|
+
const lvl = (u) => (cap && cap.mint === a.mint ? fmtMcap(u * cap.supply) : `$${fmtPx(u)}`);
|
|
225
242
|
const pnlUsd = open && a.pnlPct !== null && a.sizeUsd !== null ? a.sizeUsd * a.pnlPct : null;
|
|
226
243
|
const dd = open && a.pnlPct !== null && a.peakPct !== null ? (1 + a.pnlPct) / (1 + a.peakPct) - 1 : null;
|
|
227
244
|
const tp = said.tp ? `TP ${said.tp} (agent's plan)` : 'TP agent-managed';
|
|
@@ -231,12 +248,12 @@ export function planVM(v, now) {
|
|
|
231
248
|
: said.tp ? `TP ${said.tp} · agent-managed exit, no resting order on PAPER` : 'the agent\'s exit call · no resting orders on PAPER';
|
|
232
249
|
return {
|
|
233
250
|
symbol: a.symbol, stage: a.stage,
|
|
234
|
-
entry: a.entryUsd !== null ?
|
|
251
|
+
entry: a.entryUsd !== null ? lvl(a.entryUsd) : '—',
|
|
235
252
|
size: a.sizeUsd !== null ? `$${a.sizeUsd.toFixed(2)}${a.spentSol > 0 ? ` (${a.spentSol.toFixed(4)} SOL)` : ''}` : a.spentSol > 0 ? `${a.spentSol.toFixed(4)} SOL` : 'sizing…',
|
|
236
253
|
tp, stop,
|
|
237
254
|
pnlPct: open ? a.pnlPct : null, pnlUsd, peakPct: open ? a.peakPct : null, ddPct: dd,
|
|
238
255
|
heldMs: open && a.filledAt !== null ? now - a.filledAt : null,
|
|
239
|
-
mark: a.mark ?
|
|
256
|
+
mark: a.mark ? lvl(a.mark.priceUsd) : '—',
|
|
240
257
|
waiting, trace: a.trace.map((s) => s.pct),
|
|
241
258
|
refused: open && a.refusal && v.beats.refusedAt !== null && now - v.beats.refusedAt < 3500 ? a.refusal : null,
|
|
242
259
|
};
|
|
@@ -261,15 +278,15 @@ export function scanLogLines(log, tz) {
|
|
|
261
278
|
}
|
|
262
279
|
// ---------------------------------------------------------------------------------------------------------------
|
|
263
280
|
// the whole model
|
|
264
|
-
export function agentBrainModel(v, facts, now, tz) {
|
|
281
|
+
export function agentBrainModel(v, facts, now, tz, mcap = false) {
|
|
265
282
|
const s = agentStream(v, tz);
|
|
266
283
|
const status = v.control === 'paused' ? '❚❚ paused by you · its next call is held' : v.control === 'takeover' ? 'you are driving · the agent is frozen' : null;
|
|
267
284
|
return {
|
|
268
285
|
mode: 'agent', title: `✦ BRAIN · ${v.agent}`, streamLabel: s.label, demo: s.demo, stream: s.lines, status,
|
|
269
286
|
coin: facts ? { symbol: facts.symbol, mint: facts.mint } : v.focus ? { symbol: v.focus.symbol, mint: v.focus.mint } : null,
|
|
270
287
|
vet: facts ? vetRows(facts, v.focus) : [],
|
|
271
|
-
data: facts ? dataCells(facts) : [], closes: facts?.closes ?? [],
|
|
272
|
-
plan: planVM(v, now), log: decisionLog(v, tz), score: scoreLine(v.score),
|
|
288
|
+
data: facts ? dataCells(facts) : [], closes: facts?.closes ?? [], marks: traceMarks(facts),
|
|
289
|
+
plan: planVM(v, now, mcap && facts ? capScale(facts) : null), log: decisionLog(v, tz), score: scoreLine(v.score),
|
|
273
290
|
};
|
|
274
291
|
}
|
|
275
292
|
export function scanBrainModel(s, facts, tz) {
|
|
@@ -279,7 +296,7 @@ export function scanBrainModel(s, facts, tz) {
|
|
|
279
296
|
mode: 'scan', title: '✦ BRAIN · AI scan', streamLabel: 'scan log + the scan analyst (observe-only)', demo: false,
|
|
280
297
|
stream: scanStream(s.log, s.answer, tz), status: `◉ ${s.mode}${s.lock ? ` $${s.lock.symbol} · score ${s.lock.score} · read ${s.lock.reads}` : ''} · ${s.scanned} coins${s.note ? ` · ${s.note}` : ''}`,
|
|
281
298
|
coin: facts ? { symbol: facts.symbol, mint: facts.mint } : null,
|
|
282
|
-
vet: facts ? vetRows(facts, null, s.floorUsd) : [], data: facts ? dataCells(facts) : [], closes: facts?.closes ?? [],
|
|
299
|
+
vet: facts ? vetRows(facts, null, s.floorUsd) : [], data: facts ? dataCells(facts) : [], closes: facts?.closes ?? [], marks: traceMarks(facts),
|
|
283
300
|
plan: null, log: scanLogLines(s.log, tz), score: `locks ${locks} · reads ${reads} · ${s.usage || 'ai cap'} · observe-only · never trades`,
|
|
284
301
|
};
|
|
285
302
|
}
|
|
@@ -491,7 +508,7 @@ function drawVet(c, x, y, w, rows, m, compact, bg) {
|
|
|
491
508
|
}
|
|
492
509
|
function drawData(c, x, y, w, m, bg) {
|
|
493
510
|
const t = c.theme;
|
|
494
|
-
section(c, x, y, w, 'DATA', 'app numbers · no extra fetch', bg, t.accent);
|
|
511
|
+
section(c, x, y, w, 'DATA', m.marks?.cells.length ? 'app numbers · B/S = your fills' : 'app numbers · no extra fetch', bg, t.accent);
|
|
495
512
|
let cx = x + 1;
|
|
496
513
|
for (const d of m.data) {
|
|
497
514
|
const need = d.k.length + 1 + d.v.length + 2;
|
|
@@ -510,6 +527,15 @@ function drawData(c, x, y, w, m, bg) {
|
|
|
510
527
|
const up = cl[cl.length - 1] >= cl[0];
|
|
511
528
|
c.text(x + 1, y + 2, up ? '▲' : '▼', { fg: up ? t.up : t.down, bg, b: true });
|
|
512
529
|
cl.forEach((v, i) => c.put(x + 3 + i, y + 2, LV[Math.round(((v - lo) / span) * 7)], { fg: mix(bg, up ? t.up : t.down, 0.45 + 0.55 * (i / Math.max(1, cl.length - 1))), bg, soft: true }));
|
|
530
|
+
// task-1483: a B / S cell on the candle of each fill (live = solid, paper = tinted); a buy wins a shared cell's colour
|
|
531
|
+
const first = m.closes.length - cl.length;
|
|
532
|
+
for (const mk of m.marks?.cells ?? []) {
|
|
533
|
+
const i = mk.index - first;
|
|
534
|
+
if (i < 0 || i >= cl.length)
|
|
535
|
+
continue;
|
|
536
|
+
const col = mk.side === 'buy' ? t.up : t.down;
|
|
537
|
+
c.put(x + 3 + i, y + 2, markerLetter(mk.side), mk.source === 'live' ? { fg: '#000000', bg: col, b: true, hard: true } : { fg: col, bg: mix(bg, col, 0.25), b: true, hard: true });
|
|
538
|
+
}
|
|
513
539
|
}
|
|
514
540
|
else
|
|
515
541
|
c.text(x + 1, y + 2, '· no candles yet', { fg: t.dim, bg, i: true });
|
|
@@ -586,7 +612,7 @@ export function brainFor(h, facts, calm, scanUsage = '') {
|
|
|
586
612
|
const now = hud.clock();
|
|
587
613
|
const v = hud.story.view(now);
|
|
588
614
|
if (agentBrainActive(v, now))
|
|
589
|
-
return { model: agentBrainModel(v, facts, now, h.timeZone), opts: { now, calm: calm || !!hud.reduced, depth: h.colorDepth, frame: h.vfx.frame } };
|
|
615
|
+
return { model: agentBrainModel(v, facts, now, h.timeZone, h.priceMode !== 'price'), opts: { now, calm: calm || !!hud.reduced, depth: h.colorDepth, frame: h.vfx.frame } };
|
|
590
616
|
}
|
|
591
617
|
const scan = h.scan;
|
|
592
618
|
if (scan?.engine.on) {
|
|
@@ -49,13 +49,15 @@ function keysDisplay(b) {
|
|
|
49
49
|
* `--fixtures`.
|
|
50
50
|
*/
|
|
51
51
|
export function OVERLAY_HINTS(screen, fixtures) {
|
|
52
|
+
// task-1508: on the AUTOTRADE screen c / n / u / d / x are its own verbs (the loop skips calm and the demo keys there).
|
|
53
|
+
const own = screen === 'autotrade';
|
|
52
54
|
const rows = [
|
|
53
|
-
{ keys: 'c', label: 'calm mode (effects off)' },
|
|
55
|
+
...(own ? [] : [{ keys: 'c', label: 'calm mode (effects off)' }]),
|
|
54
56
|
{ keys: '?', label: 'this help' },
|
|
55
57
|
];
|
|
56
58
|
if (screen === 'analyst')
|
|
57
59
|
rows.unshift({ keys: 'type', label: 'ask a follow-up · ⏎ send · esc clear/back' });
|
|
58
|
-
if (fixtures)
|
|
60
|
+
if (fixtures && !own)
|
|
59
61
|
rows.push({ keys: 'n/u/d/x', label: 'demo: new pair · pump · dump · rug' });
|
|
60
62
|
return rows;
|
|
61
63
|
}
|
|
@@ -102,6 +104,7 @@ const SCREEN_TITLE = {
|
|
|
102
104
|
ticket: 'Paper trade ticket', positions: 'Paper positions',
|
|
103
105
|
trending: 'Trending in the space', kol: 'KOL lists', bubbles: 'Bubble map', narrative: 'Narrative board',
|
|
104
106
|
plans: 'Order plans & mandates', follows: 'Followed wallets', rules: 'Rules (alerts + proposals only)',
|
|
107
|
+
autotrade: 'Autotrade (paper)',
|
|
105
108
|
};
|
|
106
109
|
/** Draw a centered modal card and return its inner rect, or null when the terminal is too small. */
|
|
107
110
|
function card(c, want, title, caption) {
|
|
@@ -27,11 +27,10 @@ export function renderPlans(c, state) {
|
|
|
27
27
|
const top = 2, bottom = c.h - 1;
|
|
28
28
|
const risk = svc ? svc.riskStatus() : { gateOff: false, acceptedAt: null, expiresAt: null, active: false };
|
|
29
29
|
const gateLabel = risk.active ? 'HANDS-FREE' : 'GATE ON';
|
|
30
|
-
// task-
|
|
31
|
-
const
|
|
32
|
-
const fireLabel = liveFire ? '◉ LIVE · DEVNET · FAST WALLET' : 'PAPER';
|
|
30
|
+
// task-1571: plans fire on PAPER only (dexterm holds no key; there is no live fire path).
|
|
31
|
+
const fireLabel = 'PAPER';
|
|
33
32
|
const title = `ORDER PLANS & MANDATES · ${tab === 'plans' ? `${plans.length} plans` : `${mandates.length} mandates`} · ${fireLabel} · ${gateLabel}`;
|
|
34
|
-
const caption = bp === 'compact' ? undefined : 'voice/agents PROPOSE only · arming needs a physical keypress hold ·
|
|
33
|
+
const caption = bp === 'compact' ? undefined : 'voice/agents PROPOSE only · arming needs a physical keypress hold · paper fills only · panic revokes all';
|
|
35
34
|
const box = c.box(0, top, c.w, bottom - top, { title, caption, focus: true });
|
|
36
35
|
const bg = box.bg;
|
|
37
36
|
const now = state.now.getTime();
|
|
@@ -89,7 +88,7 @@ export function renderPlans(c, state) {
|
|
|
89
88
|
const mbox = c.box(mx, my, mw, mh, { title: '⚠ ARM — physical keypress', focus: true });
|
|
90
89
|
const label = a.kind === 'plan' ? `Arm plan ${a.id} into ${a.mandateId}?` : `Arm standing mandate ${a.id}?`;
|
|
91
90
|
c.textC(mbox.x, mbox.y, mbox.w, label, { fg: t.text, bg: mbox.bg, b: true });
|
|
92
|
-
c.textC(mbox.x, mbox.y + 1, mbox.w, a.kind === 'mandate' ? 'armed plans can fire at machine speed
|
|
91
|
+
c.textC(mbox.x, mbox.y + 1, mbox.w, a.kind === 'mandate' ? 'armed plans can fire at machine speed on paper (simulated fills)' : 'the caps are re-checked on every paper fill; voice/agents can never arm', { fg: t.muted, bg: mbox.bg });
|
|
93
92
|
c.textC(mbox.x, mbox.y + 3, mbox.w, 'Hold and release [enter] or [y] to confirm · [esc] cancels · a pipe/agent cannot arm', { fg: t.accent, bg: mbox.bg });
|
|
94
93
|
}
|
|
95
94
|
// The "less safe" hands-free opt-in modal (Tier 4): keypress-only, journaled, auto-expires 24h, reversible.
|
|
@@ -102,17 +101,6 @@ export function renderPlans(c, state) {
|
|
|
102
101
|
c.textC(mbox.x, mbox.y + 3, mbox.w, 'signer caps, allow-lists and panic still apply · this auto-expires in 24h · logged to the journal', { fg: t.muted, bg: mbox.bg });
|
|
103
102
|
c.textC(mbox.x, mbox.y + 5, mbox.w, risk.active ? 'Hold+release [enter]/[y] to restore the gate · [esc] cancels' : 'Hold+release [enter]/[y] to accept (keypress only) · [esc] cancels · a pipe/agent cannot', { fg: t.accent, bg: mbox.bg });
|
|
104
103
|
}
|
|
105
|
-
// task-1363: the FIRE PATH modal (paper ⇄ live). Switched by a captured keypress in the loop; this paints the prompt.
|
|
106
|
-
if (ui?.liveModal) {
|
|
107
|
-
const mw = Math.min(box.w - 4, 78), mh = 9;
|
|
108
|
-
const mx = box.x + Math.floor((box.w - mw) / 2), my = box.y + Math.floor((box.h - mh) / 2);
|
|
109
|
-
const mbox = c.box(mx, my, mw, mh, { title: liveFire ? 'FIRE PATH — back to PAPER' : '⚠ FIRE PATH — go LIVE on DEVNET', focus: true });
|
|
110
|
-
c.textC(mbox.x, mbox.y, mbox.w, liveFire ? 'Switch plan fills back to the paper executor?' : 'Fire armed plans through the SIGNER from the capped fast wallet (devnet)?', { fg: t.text, bg: mbox.bg, b: true });
|
|
111
|
-
c.textC(mbox.x, mbox.y + 2, mbox.w, liveFire ? 'fills are then simulated again at the tick price; nothing on chain' : 'real devnet lamports move (fees of a wrap-and-unwrap sized to the plan); the token leg is modelled — Jupiter has no devnet', { fg: liveFire ? t.muted : t.down, bg: mbox.bg });
|
|
112
|
-
c.textC(mbox.x, mbox.y + 3, mbox.w, 'the signer re-checks policy, simulation, USD per-trade/daily caps and the 0.05 SOL per-fill ceiling on every fill', { fg: t.muted, bg: mbox.bg });
|
|
113
|
-
c.textC(mbox.x, mbox.y + 4, mbox.w, 'needs: a live run with the signer, `dexterm wallet fast create`, no armed/filled plans · never mainnet · journaled', { fg: t.muted, bg: mbox.bg });
|
|
114
|
-
c.textC(mbox.x, mbox.y + 6, mbox.w, 'Hold+release [enter]/[y] to switch (keypress only) · [esc] cancels · a pipe/agent/voice cannot', { fg: t.accent, bg: mbox.bg });
|
|
115
|
-
}
|
|
116
104
|
// task-1366: the selected plan's levels with BOTH market cap and price (display only; mc first in mcap mode)
|
|
117
105
|
if (tab === 'plans' && svc && !ui?.notice) {
|
|
118
106
|
const r = rows[sel];
|
|
@@ -122,5 +110,5 @@ export function renderPlans(c, state) {
|
|
|
122
110
|
}
|
|
123
111
|
if (ui?.notice)
|
|
124
112
|
c.text(box.x + 1, box.y + box.h - 1, ui.notice, { fg: t.accent, bg });
|
|
125
|
-
footer(c, [['↑↓', 'move'], ['tab', 'plans/mandates'], ['a', 'arm (hold)'], tab === 'plans' ? ['c', 'cancel'] : ['r', 'revoke'], ['
|
|
113
|
+
footer(c, [['↑↓', 'move'], ['tab', 'plans/mandates'], ['a', 'arm (hold)'], tab === 'plans' ? ['c', 'cancel'] : ['r', 'revoke'], ['G', risk.active ? 'gate on' : 'hands-free'], ['!', 'PANIC'], ['esc', 'back'], ['q', 'quit']], t.name);
|
|
126
114
|
}
|
|
@@ -11,8 +11,9 @@ import { mix } from '../../../tui/src/index.js';
|
|
|
11
11
|
import { fmtPx } from '../../../agents/src/index.js';
|
|
12
12
|
import { planFromThoughts, fmtDur } from "./brain.js";
|
|
13
13
|
export const PEAK_FLASH_MS = 1200;
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
export const CHIP_PRICE_LEVEL = (u) => `$${fmtPx(u)}`;
|
|
15
|
+
const PRICE_LEVEL = CHIP_PRICE_LEVEL;
|
|
16
|
+
export function pnlChipVM(v, now, lvl = PRICE_LEVEL) {
|
|
16
17
|
const a = v.arc;
|
|
17
18
|
if (!a || a.stage !== 'open')
|
|
18
19
|
return null;
|
|
@@ -22,8 +23,8 @@ export function pnlChipVM(v, now) {
|
|
|
22
23
|
symbol: a.symbol,
|
|
23
24
|
pnlPct: a.pnlPct,
|
|
24
25
|
pnlUsd: a.pnlPct !== null && a.sizeUsd !== null ? a.sizeUsd * a.pnlPct : null,
|
|
25
|
-
entry: a.entryUsd !== null ?
|
|
26
|
-
mark: a.mark ?
|
|
26
|
+
entry: a.entryUsd !== null ? lvl(a.entryUsd, a.mint) : '—',
|
|
27
|
+
mark: a.mark ? lvl(a.mark.priceUsd, a.mint) : '—',
|
|
27
28
|
peakPct: a.peakPct,
|
|
28
29
|
ddPct: dd,
|
|
29
30
|
heldMs: a.filledAt !== null ? now - a.filledAt : null,
|
|
@@ -53,7 +54,7 @@ export class OwnPnlTracker {
|
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
get mint() { return this.cur?.s.mint ?? null; }
|
|
56
|
-
vm(now) {
|
|
57
|
+
vm(now, lvl = PRICE_LEVEL) {
|
|
57
58
|
const c = this.cur;
|
|
58
59
|
if (!c)
|
|
59
60
|
return null;
|
|
@@ -64,12 +65,12 @@ export class OwnPnlTracker {
|
|
|
64
65
|
symbol: s.symbol,
|
|
65
66
|
pnlPct: s.pnlPct,
|
|
66
67
|
pnlUsd: s.pnlUsd,
|
|
67
|
-
entry: s.entryUsd !== null ?
|
|
68
|
-
mark: s.markUsd !== null ?
|
|
68
|
+
entry: s.entryUsd !== null ? lvl(s.entryUsd, s.mint) : '—',
|
|
69
|
+
mark: s.markUsd !== null ? lvl(s.markUsd, s.mint) : '—',
|
|
69
70
|
peakPct: c.peakPct,
|
|
70
71
|
ddPct: dd,
|
|
71
72
|
heldMs: s.openedAt !== null ? Math.max(0, now - s.openedAt) : null,
|
|
72
|
-
tp: s.targetUsd !== null ?
|
|
73
|
+
tp: s.targetUsd !== null ? lvl(s.targetUsd, s.mint) : null,
|
|
73
74
|
tpNone: 'not set',
|
|
74
75
|
newPeak: c.peakAt !== null && now - c.peakAt < PEAK_FLASH_MS && c.peakPct !== null && c.peakPct > 0,
|
|
75
76
|
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { Canvas, header, footer, breakpoint, mix, isCalm, fmtPriceBare, fmtMcap, fmtNum, fmtPct, fmtAgeSec, shortAddr, } from '../../../tui/src/index.js';
|
|
5
5
|
import { lamportsToSol, rawToTokens, positionPnl } from '../../../data/src/index.js';
|
|
6
6
|
import { headerModel } from "../state.js";
|
|
7
|
-
import { priceModeOf, supplyRatio, FALLBACK_MARK } from "../display.js";
|
|
7
|
+
import { priceModeOf, supplyRatio, supplyForMint, FALLBACK_MARK } from "../display.js";
|
|
8
8
|
export function sol(n, digits = 4) {
|
|
9
9
|
return `${n >= 0 ? '' : '-'}${Math.abs(n).toFixed(digits)}`;
|
|
10
10
|
}
|
|
@@ -75,7 +75,7 @@ export function renderPositions(c, state) {
|
|
|
75
75
|
// task-1366: mcap mode reads AVG / PRICE as market cap = SOL price × SOL/USD × the token's CURRENT supply (from the
|
|
76
76
|
// screener rows); a token without a supply (or no SOL/USD yet) keeps its SOL price, marked ᵖ. PnL stays SOL.
|
|
77
77
|
const mode = priceModeOf(state);
|
|
78
|
-
const supplyOf = (mint) =>
|
|
78
|
+
const supplyOf = (mint) => supplyForMint(state, mint); // task-1537: + the open token view and pump.fun's 1B
|
|
79
79
|
const mcCell = (pSol, mint) => {
|
|
80
80
|
if (pSol === null)
|
|
81
81
|
return '—';
|
|
@@ -126,33 +126,9 @@ export function renderPositions(c, state) {
|
|
|
126
126
|
}
|
|
127
127
|
py += 1;
|
|
128
128
|
}
|
|
129
|
-
// task-1328: LIVE positions (the signer's ledger file, read-only), only when there are any.
|
|
130
|
-
const liveSrc = state.live?.livePositions ?? null;
|
|
131
|
-
const livePos = liveSrc ? liveSrc.positions().filter((p) => p.tokensRaw > 0n) : [];
|
|
132
129
|
y += half;
|
|
133
|
-
if (livePos.length > 0) {
|
|
134
|
-
const lh = Math.min(livePos.length + 3, Math.max(5, Math.floor((bottom - y) * 0.4)));
|
|
135
|
-
const lb = c.box(0, y, c.w, lh, { title: '◉ LIVE POSITIONS', titleFg: t.up, caption: 'confirmed on-chain fills · signer ledger' });
|
|
136
|
-
let ly = lb.y;
|
|
137
|
-
for (const p of livePos) {
|
|
138
|
-
if (ly >= lb.y + lb.h)
|
|
139
|
-
break;
|
|
140
|
-
const mark = liveSrc?.held(p.mint)?.markSol ?? null;
|
|
141
|
-
const pnl = positionPnl(p, mark);
|
|
142
|
-
let cx = c.text(lb.x + 1, ly, `$${p.symbol}`, { fg: t.text, bg: lb.bg, b: true });
|
|
143
|
-
cx = c.text(cx + 2, ly, fmtNum(rawToTokens(p.tokensRaw, p.decimals)), { fg: t.muted, bg: lb.bg });
|
|
144
|
-
cx = c.text(cx + 2, ly, `cost ${sol(pnl.costSol)} SOL`, { fg: t.dim, bg: lb.bg });
|
|
145
|
-
if (pnl.avgEntrySol !== null)
|
|
146
|
-
cx = c.text(cx + 2, ly, `avg ${fmtPriceBare(pnl.avgEntrySol)}`, { fg: t.dim, bg: lb.bg });
|
|
147
|
-
if (pnl.unrealizedSol !== null)
|
|
148
|
-
c.text(cx + 2, ly, `uPnL ${signedSol(pnl.unrealizedSol)} SOL${pnl.unrealizedPct !== null ? ` ${fmtPct(pnl.unrealizedPct * 100)}` : ''}`, { fg: pnl.unrealizedSol >= 0 ? t.up : t.down, bg: lb.bg, b: true });
|
|
149
|
-
c.textR(lb.x + 1, ly, lb.w - 2, `${shortAddr(p.mint, 4)} · LIVE`, { fg: t.up, bg: lb.bg });
|
|
150
|
-
ly += 1;
|
|
151
|
-
}
|
|
152
|
-
y += lh;
|
|
153
|
-
}
|
|
154
130
|
// history
|
|
155
|
-
const hb = c.box(0, y, c.w, bottom - y, { title: 'TRADE HISTORY', caption: `${v.history.length} paper fills
|
|
131
|
+
const hb = c.box(0, y, c.w, bottom - y, { title: 'TRADE HISTORY', caption: `${v.history.length} paper fills` });
|
|
156
132
|
let yy = hb.y;
|
|
157
133
|
for (const h of v.history) {
|
|
158
134
|
if (yy >= hb.y + hb.h)
|
|
@@ -163,7 +139,9 @@ export function renderPositions(c, state) {
|
|
|
163
139
|
let cx = c.text(hb.x + 1, yy, fmtAgeSec(Math.max(0, Math.round((state.now.getTime() - h.t) / 1000))).padStart(4), { fg: t.dim, bg: hb.bg });
|
|
164
140
|
cx = c.text(cx + 1, yy, h.side === 'buy' ? '▲ BUY ' : '▼ SELL', { fg: sideColor, bg: hb.bg, b: true });
|
|
165
141
|
cx = c.text(cx + 1, yy, `$${h.symbol}`, { fg: t.text, bg: hb.bg, b: true });
|
|
166
|
-
|
|
142
|
+
// task-1537: a fill reads as the market cap it filled at (the coin's current known supply), the SOL price kept
|
|
143
|
+
const hsup = mode === 'mcap' ? supplyOf(h.mint) : null;
|
|
144
|
+
cx = c.text(cx + 1, yy, `${fmtNum(gotTokens)} @ ${hsup !== null && v.solPriceUsd ? `${fmtMcap(h.priceSol * v.solPriceUsd * hsup)} mcap (${fmtPriceBare(h.priceSol)} SOL)` : `${fmtPriceBare(h.priceSol)} SOL`}`, { fg: t.muted, bg: hb.bg });
|
|
167
145
|
cx = c.text(cx + 2, yy, `${signedSol(solAmt)} SOL`, { fg: solAmt >= 0 ? t.up : t.muted, bg: hb.bg });
|
|
168
146
|
if (h.side === 'sell')
|
|
169
147
|
c.text(cx + 2, yy, `pnl ${signedSol(lamportsToSol(h.realizedLamports))}`, { fg: h.realizedLamports >= 0n ? t.up : t.down, bg: hb.bg });
|