dexterm-cli 0.1.5 → 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/index.js +2 -0
- package/dist/packages/agents/src/schema.js +22 -1
- package/dist/packages/agents/src/spectator.js +54 -0
- package/dist/packages/agents/src/story.js +532 -0
- package/dist/packages/agents/src/tiers.js +28 -2
- package/dist/packages/agents/src/tools.js +31 -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/REGISTRY.json +1 -1
- package/dist/packages/cli/assets/claude/plugin/skills/larp-check/SKILL.md +15 -8
- package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +1 -1
- package/dist/packages/cli/src/agent-cmd.js +6 -4
- package/dist/packages/cli/src/agent-spectator.js +17 -1
- package/dist/packages/cli/src/ai-cmd.js +412 -0
- package/dist/packages/cli/src/analyst/backend.js +105 -15
- package/dist/packages/cli/src/analyst/codex.js +14 -9
- package/dist/packages/cli/src/analyst/larp-gauge.js +60 -0
- package/dist/packages/cli/src/analyst/ollama.js +263 -0
- package/dist/packages/cli/src/analyst/session.js +17 -3
- package/dist/packages/cli/src/app-help-gen.js +51 -15
- 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/backtest-cmd.js +13 -2
- package/dist/packages/cli/src/display.js +208 -23
- 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/dev-history.js +31 -15
- package/dist/packages/cli/src/live/index.js +28 -90
- package/dist/packages/cli/src/live/screens/newpairs-live.js +1 -1
- package/dist/packages/cli/src/live/screens/token-live.js +48 -15
- package/dist/packages/cli/src/live/screens/watchlist-live.js +1 -1
- package/dist/packages/cli/src/live/trade.js +30 -453
- package/dist/packages/cli/src/live/watchlist.js +1 -1
- package/dist/packages/cli/src/main.js +290 -199
- package/dist/packages/cli/src/mcp-cmd.js +7 -1
- package/dist/packages/cli/src/mcp-follow.js +103 -6
- package/dist/packages/cli/src/plan-cmd.js +15 -5
- 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 +38 -6
- package/dist/packages/cli/src/record-cmd.js +141 -20
- package/dist/packages/cli/src/scan/ui.js +7 -1
- package/dist/packages/cli/src/screens/agent-hud.js +773 -0
- package/dist/packages/cli/src/screens/analyst-session.js +11 -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 +634 -0
- package/dist/packages/cli/src/screens/newpairs.js +1 -1
- 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 +144 -0
- package/dist/packages/cli/src/screens/positions.js +6 -28
- package/dist/packages/cli/src/screens/screener.js +1 -0
- package/dist/packages/cli/src/screens/ticket.js +38 -205
- package/dist/packages/cli/src/screens/token.js +18 -9
- package/dist/packages/cli/src/screens/trending.js +1 -1
- package/dist/packages/cli/src/state.js +88 -18
- 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 +41 -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 +2 -14
- package/dist/packages/data/src/larp/score.js +220 -0
- package/dist/packages/data/src/larp/x-account.js +316 -0
- package/dist/packages/data/src/store.js +14 -5
- package/dist/packages/data/src/trade/agent/paper-desk.js +300 -23
- 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/engine.js +7 -0
- package/dist/packages/data/src/trade/plans/index.js +0 -1
- package/dist/packages/data/src/trade/plans/mandate.js +28 -15
- package/dist/packages/data/src/trade/plans/service.js +4 -28
- 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/dev-history.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/larp-check.md +5 -1
- 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/scan-mode.md +1 -1
- 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 +6 -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/spectate-an-agent.md +2 -1
- 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 +7 -3
- 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-starting-a-run.md +2 -0
- 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 +32 -0
- 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 +9 -7
- 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-running-the-tests.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-larp-measured-accuracy.md +1 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp-the-larp-score.md +60 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp-the-verdict.md +0 -2
- package/dist/packages/mcp/assets/kb/docs/docs-larp-what-it-looks-at.md +4 -1
- package/dist/packages/mcp/assets/kb/docs/docs-larp.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 +4 -13
- 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 +40 -0
- 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-market-cap-axis.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +3 -1
- package/dist/packages/mcp/assets/kb/docs/docs-scan-the-read.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-autotrade-paper.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-dev-history.md +10 -7
- 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-follow-over-mcp-in-the-running-terminal.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-limits.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-agent-hud-spectator-v2.md +58 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-brain-view-and-the-pnl-chip.md +46 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-three-surfaces.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-spectator.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 +5 -2
- package/dist/packages/mcp/src/server.js +285 -36
- package/dist/packages/mcp/src/spectator-sink.js +85 -0
- package/dist/packages/packs/src/backtest.js +3 -1
- package/dist/packages/packs/src/index.js +1 -0
- package/dist/packages/packs/src/larp-score-backtest.js +119 -0
- package/dist/packages/popup/src/pages/chart-lib.js +169 -35
- package/dist/packages/popup/src/pages/chart.css +18 -0
- package/dist/packages/popup/src/pages/chart.html +6 -1
- package/dist/packages/popup/src/pages/chart.js +136 -10
- package/dist/packages/popup/src/pages/spectator.css +45 -0
- package/dist/packages/popup/src/pages/spectator.html +1 -0
- package/dist/packages/popup/src/pages/spectator.js +69 -0
- package/dist/packages/popup/src/protocol.js +4 -0
- package/dist/packages/popup/src/server.js +9 -1
- package/dist/packages/recorder/src/dev-history.js +7 -3
- 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/canvas.js +7 -0
- package/dist/packages/tui/src/fmt.js +53 -0
- package/dist/packages/tui/src/index.js +1 -0
- package/dist/packages/tui/src/keymap.js +25 -1
- package/dist/packages/tui/src/markers.js +219 -0
- package/dist/packages/tui/src/widgets.js +158 -6
- 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
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
// dexterm — trade ticket screen (task-1310 T0
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// the RPC it talks to) — never from a flag the UI holds, so the label cannot disagree with the
|
|
7
|
-
// connection. Pure renderer: the state machine + bindings live elsewhere; nothing here signs.
|
|
8
|
-
import { Canvas, badge, header, footer, breakpoint, mix, isCalm, fmtPrice, fmtPriceBare, fmtAmount, fmtPct, } from '../../../tui/src/index.js';
|
|
1
|
+
// dexterm — trade ticket screen (task-1310 T0). PAPER only: a simulated buy/sell priced from a live keyless
|
|
2
|
+
// Jupiter quote, every frame labelled PAPER. task-1571: there is no LIVE ticket — dexterm holds no key and signs
|
|
3
|
+
// nothing; live trading happens in the Telegram trading bot of the user's choice. Pure renderer.
|
|
4
|
+
import { Canvas, badge, header, footer, breakpoint, mix, isCalm, fmtPrice, fmtPriceBare, fmtAmount, fmtPct, fmtMcap, } from '../../../tui/src/index.js';
|
|
5
|
+
import { priceModeOf, supplyForMint } from "../display.js";
|
|
9
6
|
import { lamportsToSol, rawToTokens } from '../../../data/src/index.js';
|
|
10
7
|
import { headerModel } from "../state.js";
|
|
11
|
-
import { slippageBps
|
|
8
|
+
import { slippageBps } from "../trade.js";
|
|
12
9
|
function fmtSol(sol, digits = 4) {
|
|
13
10
|
const a = Math.abs(sol);
|
|
14
11
|
return `${a.toFixed(digits)} SOL`;
|
|
@@ -22,83 +19,41 @@ function tokenAmount(raw, decimals, symbol, decimalsKnown) {
|
|
|
22
19
|
return `${symbol}: decimals unknown yet (raw ${raw.toString()})`;
|
|
23
20
|
return `${fmtAmount(rawToTokens(raw, decimals))} ${symbol}`;
|
|
24
21
|
}
|
|
25
|
-
/** Word-wrap `text` into at most `maxLines` lines of `width` columns; the last line is cut with an ellipsis. */
|
|
26
|
-
function wrapLines(text, width, maxLines) {
|
|
27
|
-
const words = text.split(/\s+/).filter((w) => w.length > 0);
|
|
28
|
-
const lines = [];
|
|
29
|
-
let cur = '';
|
|
30
|
-
for (const w of words) {
|
|
31
|
-
const next = cur ? `${cur} ${w}` : w;
|
|
32
|
-
if (next.length <= width) {
|
|
33
|
-
cur = next;
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
if (cur)
|
|
37
|
-
lines.push(cur);
|
|
38
|
-
cur = w.length > width ? `${w.slice(0, Math.max(1, width - 1))}…` : w;
|
|
39
|
-
if (lines.length === maxLines)
|
|
40
|
-
break;
|
|
41
|
-
}
|
|
42
|
-
if (cur && lines.length < maxLines)
|
|
43
|
-
lines.push(cur);
|
|
44
|
-
if (lines.length > maxLines)
|
|
45
|
-
lines.length = maxLines;
|
|
46
|
-
const joined = lines.join(' ');
|
|
47
|
-
if (joined.length < text.length && lines.length === maxLines) {
|
|
48
|
-
const last = lines[maxLines - 1];
|
|
49
|
-
lines[maxLines - 1] = last.length >= width - 1 ? `${last.slice(0, Math.max(1, width - 1))}…` : `${last}…`;
|
|
50
|
-
}
|
|
51
|
-
return lines;
|
|
52
|
-
}
|
|
53
22
|
export function renderTicket(c, state) {
|
|
54
23
|
const t = c.theme;
|
|
55
24
|
header(c, headerModel(state));
|
|
56
25
|
const bp = breakpoint(c.w);
|
|
57
26
|
// Live binding is the source of truth; the seeded demo view backs fixture/one-shot frames.
|
|
58
27
|
const view = (state.live?.ticket ? state.live.ticket.view() : state.ticket) ?? null;
|
|
59
|
-
|
|
60
|
-
const isLive = !!live;
|
|
61
|
-
// Always-on banner strip (never hidden, any state). PAPER = warn tint; LIVE = the signer's network.
|
|
28
|
+
// Always-on banner strip (never hidden, any state).
|
|
62
29
|
const bannerY = 2;
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
c.fill(0, bannerY, c.w, 1, ' ', { bg: mix(t.bg, bannerColor, mainnet ? 0.3 : 0.16) });
|
|
67
|
-
const banner = !isLive
|
|
68
|
-
? ' ◈ PAPER TRADING — simulated · no real orders · no keys · no signing '
|
|
69
|
-
: net === null
|
|
70
|
-
? ' ◉ LIVE — signer not reachable · nothing can be signed '
|
|
71
|
-
: mainnet
|
|
72
|
-
? ` ⚠ LIVE · MAINNET — REAL FUNDS · caps $${live?.signer?.caps.perTradeUsd ?? '?'}/trade $${live?.signer?.caps.dailyUsd ?? '?'}/day · Phantom signs · dexterm holds no key `
|
|
73
|
-
: ` ◉ LIVE · DEVNET — real signing via Phantom · devnet funds only · dexterm holds no key `;
|
|
74
|
-
c.text(2, bannerY, banner, { fg: bannerColor, bg: mix(t.bg, bannerColor, mainnet ? 0.3 : 0.16), b: true });
|
|
30
|
+
const bannerColor = t.warn;
|
|
31
|
+
c.fill(0, bannerY, c.w, 1, ' ', { bg: mix(t.bg, bannerColor, 0.16) });
|
|
32
|
+
c.text(2, bannerY, ' ◈ PAPER TRADING — simulated · no real orders · no keys · no signing ', { fg: bannerColor, bg: mix(t.bg, bannerColor, 0.16), b: true });
|
|
75
33
|
const linked = state.live?.linkedWallet;
|
|
76
34
|
if (linked)
|
|
77
|
-
c.textR(2, bannerY, c.w - 3, `linked: ${linked.publicKey.slice(0, 4)}…${linked.publicKey.slice(-4)} `, { fg: t.muted, bg: mix(t.bg, bannerColor,
|
|
35
|
+
c.textR(2, bannerY, c.w - 3, `linked: ${linked.publicKey.slice(0, 4)}…${linked.publicKey.slice(-4)} `, { fg: t.muted, bg: mix(t.bg, bannerColor, 0.16) });
|
|
78
36
|
c.noRain(0, bannerY, c.w, 1);
|
|
79
|
-
if (live && (live.signer?.panic || live.signer?.ledgerLocked)) {
|
|
80
|
-
c.fill(0, bannerY + 1, c.w, 1, ' ', { bg: mix(t.bg, t.down, 0.3) });
|
|
81
|
-
c.text(2, bannerY + 1, ' ⛔ PANIC — live signing is disabled · re-enable only from a shell: dexterm wallet resume ', { fg: t.down, bg: mix(t.bg, t.down, 0.3), b: true });
|
|
82
|
-
c.noRain(0, bannerY + 1, c.w, 1);
|
|
83
|
-
}
|
|
84
37
|
if (!view) {
|
|
85
|
-
c.text(2, 4, 'Open a trade ticket from a token screen: B buy · S sell
|
|
38
|
+
c.text(2, 4, 'Open a paper trade ticket from a token screen: B buy · S sell', { fg: t.muted, bg: t.bg });
|
|
86
39
|
footer(c, [['esc', 'back'], ['P', 'positions'], ['q', 'quit']], t.name, isCalm(state.vfx));
|
|
87
40
|
return;
|
|
88
41
|
}
|
|
89
42
|
const ts = view.ticket;
|
|
43
|
+
const mode = priceModeOf(state); // task-1537: fills and prices read as market caps by default
|
|
44
|
+
const sup = supplyForMint(state, ts.mint);
|
|
90
45
|
const buy = ts.side === 'buy';
|
|
91
46
|
const sideColor = buy ? t.up : t.down;
|
|
92
47
|
const top = 4;
|
|
93
48
|
const w = Math.min(bp === 'compact' ? c.w - 2 : 78, c.w - 2);
|
|
94
49
|
const x0 = 1;
|
|
95
50
|
const h = c.h - top - 1;
|
|
96
|
-
const title =
|
|
97
|
-
const caption =
|
|
51
|
+
const title = `◈ PAPER ${ts.side.toUpperCase()} TICKET`;
|
|
52
|
+
const caption = 'jupiter keyless quote · paper fill';
|
|
98
53
|
// task-1340: the ticket is PLAIN by construction — no heading (no chromatic split on its title) and every cell of
|
|
99
54
|
// its rect is shielded below, so no effect pass (rain, mosh, shake, scanlines, trade moments) can write a glyph, a
|
|
100
55
|
// colour or a background into it in any phase. The banner rows above it are shielded too.
|
|
101
|
-
const box = c.box(x0, top, w, h, { title, titleFg:
|
|
56
|
+
const box = c.box(x0, top, w, h, { title, titleFg: sideColor, caption, captionFg: t.dim, border: mix(t.border, sideColor, 0.5), plain: true });
|
|
102
57
|
c.shieldRect(x0, top, w, h);
|
|
103
58
|
c.shieldRect(0, bannerY, c.w, 2);
|
|
104
59
|
const bg = box.bg;
|
|
@@ -109,24 +64,18 @@ export function renderTicket(c, state) {
|
|
|
109
64
|
let x = c.text(ix, y, `$${ts.symbol}`, { fg: t.borderFocus, bg, b: true });
|
|
110
65
|
x = c.text(x + 1, y, `${ts.mint.slice(0, 4)}…${ts.mint.slice(-4)}`, { fg: t.dim, bg });
|
|
111
66
|
x = badge(c, x + 2, y, buy ? '▲ BUY' : '▼ SELL', sideColor, { on: bg, bold: true }) + 1;
|
|
112
|
-
x = badge(c, x + 1, y,
|
|
113
|
-
c.textR(ix, y, iw, ts.phase === 'editing' ? '← → flip side
|
|
67
|
+
x = badge(c, x + 1, y, 'PAPER', t.warn, { on: bg, bold: true }) + 1;
|
|
68
|
+
c.textR(ix, y, iw, ts.phase === 'editing' ? '← → flip side' : '', { fg: t.dim, bg });
|
|
114
69
|
y += 2;
|
|
115
70
|
// size field
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (showPlan && live?.plan) {
|
|
125
|
-
y = renderPlan(c, ix, y, iw, bg, live, ts.decimals, ts.symbol, buy, state.now.getTime());
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
// quote block (paper warm quote; LIVE editing shows the same keyless quote as a preview)
|
|
129
|
-
c.text(ix, y, isLive ? 'PREVIEW QUOTE (keyless; the signer re-quotes on ⏎)' : 'QUOTE', { fg: t.dim, bg });
|
|
71
|
+
const sizeUnit = buy ? (ts.sizeUnit === 'sol' ? 'SOL' : '% of balance') : '% of position';
|
|
72
|
+
field(c, ix, y, iw, bg, 'Size', `${ts.sizeInput || '—'} ${sizeUnit}`, ts.field === 'size' && ts.phase === 'editing', t);
|
|
73
|
+
y += 1;
|
|
74
|
+
field(c, ix, y, iw, bg, 'Slippage', `${slippageBps(ts)} bps`, ts.field === 'slippage' && ts.phase === 'editing', t);
|
|
75
|
+
y += 2;
|
|
76
|
+
{
|
|
77
|
+
// quote block (the paper warm quote)
|
|
78
|
+
c.text(ix, y, 'QUOTE', { fg: t.dim, bg });
|
|
130
79
|
c.textR(ix, y, iw, view.loading ? '· fetching…' : view.quote ? `· ${Math.max(0, Math.round((view.quoteAgeMs ?? 0) / 1000))}s ago` : view.error ? '· unavailable' : '', { fg: view.error ? t.down : t.dim, bg });
|
|
131
80
|
c.hline(box.x + 1, y + 1, box.w - 2, { fg: t.border, bg, soft: true });
|
|
132
81
|
y += 2;
|
|
@@ -139,51 +88,29 @@ export function renderTicket(c, state) {
|
|
|
139
88
|
const recv = buy ? tokenAmount(tokenAbs, ts.decimals, ts.symbol, decimalsKnown) : `${fmtSol(lamportsToSol(preview.solDelta))}`;
|
|
140
89
|
kv(c, ix, y++, iw, bg, 'You pay', spend, t, buy ? t.down : t.text);
|
|
141
90
|
kv(c, ix, y++, iw, bg, 'You receive', recv, t, buy && !decimalsKnown ? t.warn : t.up);
|
|
142
|
-
|
|
91
|
+
// task-1537: in the market-cap basis (default) the fill price reads as the cap it buys/sells at, the price beside it
|
|
92
|
+
const capAt = mode === 'mcap' && sup !== null && preview.priceUsd !== null ? fmtMcap(preview.priceUsd * sup) : null;
|
|
93
|
+
kv(c, ix, y++, iw, bg, capAt ? 'At mcap' : 'Price', decimalsKnown ? `${capAt ? `${capAt} · ` : ''}${fmtPriceBare(preview.priceSol)} SOL${preview.priceUsd !== null ? ` · ${fmtPrice(preview.priceUsd)}` : ''}` : 'per-token price needs the decimals', t, decimalsKnown ? t.text : t.warn);
|
|
143
94
|
const impact = preview.priceImpactPct;
|
|
144
95
|
kv(c, ix, y++, iw, bg, 'Price impact', impact === null ? '—' : fmtPct(impact, { sign: false }), t, impact !== null && impact > 5 ? t.down : impact !== null && impact > 1 ? t.warn : t.muted);
|
|
145
96
|
kv(c, ix, y++, iw, bg, 'Min received', buy ? tokenAmount(q.otherAmountThreshold, ts.decimals, ts.symbol, decimalsKnown) : fmtSol(lamportsToSol(q.otherAmountThreshold)), t, t.muted);
|
|
146
|
-
kv(c, ix, y++, iw, bg,
|
|
97
|
+
kv(c, ix, y++, iw, bg, 'Sim fee', fmtSol(lamportsToSol(preview.feeLamports), 6), t, t.muted);
|
|
147
98
|
kv(c, ix, y++, iw, bg, 'Route', q.route.length ? q.route.join(' → ') : 'direct', t, t.accent);
|
|
148
99
|
}
|
|
149
100
|
else if (view.error) {
|
|
150
101
|
c.text(ix, y++, `⚠ ${view.error}`, { fg: t.down, bg }, iw);
|
|
151
102
|
}
|
|
152
|
-
else if (live?.probe) {
|
|
153
|
-
c.text(ix, y++, 'wrap 0.001 SOL into your own WSOL account, sync, memo, close it back — fees only', { fg: t.dim, bg }, iw);
|
|
154
|
-
}
|
|
155
103
|
else {
|
|
156
104
|
c.text(ix, y++, view.loading ? 'fetching a live quote…' : 'enter a size to see a quote', { fg: t.dim, bg }, iw);
|
|
157
105
|
}
|
|
158
|
-
// task-1368 items b + c: BEFORE ⏎ on a LIVE ticket — the size in USD against the signer's caps (red when the
|
|
159
|
-
// signer would refuse it, with the size that fits), and the devnet-cannot-fill-mainnet-tokens line.
|
|
160
|
-
if (isLive && live && !live.probe && ts.phase === 'editing') {
|
|
161
|
-
const pf = live.preflight ?? null;
|
|
162
|
-
if (pf) {
|
|
163
|
-
const color = pf.over ? t.down : pf.sizeUsd === null && pf.sizeSol > 0 ? t.warn : t.muted;
|
|
164
|
-
for (const line of wrapLines(`${pf.over ? '✗ ' : ''}${pf.line}`, iw, 2))
|
|
165
|
-
c.text(ix, y++, line, { fg: color, bg, b: pf.over }, iw);
|
|
166
|
-
}
|
|
167
|
-
if (live.devnetWarning)
|
|
168
|
-
for (const line of wrapLines(`⚠ ${live.devnetWarning}`, iw, 2))
|
|
169
|
-
c.text(ix, y++, line, { fg: t.warn, bg, b: true }, iw);
|
|
170
|
-
}
|
|
171
106
|
y += 1;
|
|
172
107
|
}
|
|
173
108
|
// wallet line
|
|
174
109
|
c.hline(box.x + 1, y, box.w - 2, { fg: t.border, bg, soft: true });
|
|
175
110
|
y += 1;
|
|
176
|
-
|
|
177
|
-
kv(c, ix, y++, iw, bg, 'Signer', live?.signer ? `${live.signer.network.toUpperCase()} · ${live.signer.rpcHost} · pid ${live.signer.pid}` : (live?.error ?? 'not reachable'), t, live?.signer ? t.text : t.down);
|
|
178
|
-
if (live?.signer)
|
|
179
|
-
kv(c, ix, y++, iw, bg, 'Caps', `$${live.signer.caps.perTradeUsd}/trade · $${live.signer.caps.dailyUsd}/day · spent $${live.signer.spentTodayUsd.toFixed(2)} · impact ≤ ${live.signer.caps.maxPriceImpactPct}% · ≤ ${live.signer.caps.maxSolOut} SOL out`, t, t.muted);
|
|
180
|
-
kv(c, ix, y++, iw, bg, 'Wallet', live?.linked ? `${live.linked} (Phantom signs; dexterm holds no key)` : 'none linked', t, live?.linked ? t.text : t.down);
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
kv(c, ix, y++, iw, bg, 'Paper balance', fmtSol(view.balanceSol), t, t.text);
|
|
184
|
-
}
|
|
111
|
+
kv(c, ix, y++, iw, bg, 'Paper balance', fmtSol(view.balanceSol), t, t.text);
|
|
185
112
|
if (!buy || view.positionTokens > 0)
|
|
186
|
-
kv(c, ix, y++, iw, bg, `Position`, `${fmtAmount(view.positionTokens)} ${ts.symbol}
|
|
113
|
+
kv(c, ix, y++, iw, bg, `Position`, `${fmtAmount(view.positionTokens)} ${ts.symbol}`, t, t.muted);
|
|
187
114
|
y += 1;
|
|
188
115
|
// gate / receipt region
|
|
189
116
|
const gy = box.y + box.h - 3;
|
|
@@ -201,127 +128,33 @@ export function renderTicket(c, state) {
|
|
|
201
128
|
if (ts.message)
|
|
202
129
|
c.text(ix, gy + 1, ts.message, { fg: t.warn, bg: tint }, iw);
|
|
203
130
|
}
|
|
204
|
-
else if (ts.phase === 'planning' && live?.retryAt) {
|
|
205
|
-
// task-1368: rate limited by Jupiter — the plan is NOT dropped; countdown + r / esc.
|
|
206
|
-
const left = Math.max(0, Math.ceil((live.retryAt - state.now.getTime()) / 1000));
|
|
207
|
-
const what = (live.retryMessage ?? 'Jupiter is rate limiting this IP').replace(/; retry in \d+s$/, '');
|
|
208
|
-
c.fill(box.x + 1, gy, box.w - 2, 2, ' ', { bg: mix(bg, t.warn, 0.18) });
|
|
209
|
-
c.text(ix, gy, `⚠ ${what}, retrying in ${left}s`, { fg: t.warn, bg: mix(bg, t.warn, 0.18), b: true }, iw);
|
|
210
|
-
c.text(ix, gy + 1, 'r = retry now · esc = cancel · the plan is kept (nothing was built or signed)', { fg: t.muted, bg: mix(bg, t.warn, 0.18) }, iw);
|
|
211
|
-
}
|
|
212
|
-
else if (ts.phase === 'planning') {
|
|
213
|
-
c.text(ix, gy, 'signer: quote → build → decode → policy → simulate… (esc cancels)', { fg: t.ai, bg, b: true }, iw);
|
|
214
|
-
}
|
|
215
|
-
else if (ts.phase === 'plan' && live?.plan) {
|
|
216
|
-
const refused = !live.plan.policy.ok || !live.plan.precheck.ok;
|
|
217
|
-
c.fill(box.x + 1, gy, box.w - 2, 2, ' ', { bg: tint });
|
|
218
|
-
if (refused) {
|
|
219
|
-
const v = !live.plan.policy.ok ? live.plan.policy : live.plan.precheck;
|
|
220
|
-
c.text(ix, gy, `✗ the signer WILL REFUSE this plan: ${v.reason ?? ''} — ${v.message ?? ''}`, { fg: t.down, bg: tint, b: true }, iw);
|
|
221
|
-
c.text(ix, gy + 1, 'esc back to editing (Y asks anyway and gets the signer\'s refusal)', { fg: t.muted, bg: tint }, iw);
|
|
222
|
-
}
|
|
223
|
-
else if (ts.typebackRequired) {
|
|
224
|
-
c.text(ix, gy, `⚠ large order — type the size (${ts.sizeInput}) then press Y to sign in Phantom:`, { fg: t.warn, bg: tint, b: true }, iw);
|
|
225
|
-
c.text(ix, gy + 1, `▌ ${ts.typeback || ''}`, { fg: t.text, bg: tint, b: true });
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
c.text(ix, gy, `${mainnet ? '⚠ REAL FUNDS · ' : ''}Y = sign this exact plan in Phantom (esc cancels · any other key cancels)`, { fg: mainnet ? t.down : sideColor, bg: tint, b: true }, iw);
|
|
229
|
-
c.text(ix, gy + 1, `the signer re-checks caps, verifies the signed bytes and re-simulates before it submits`, { fg: t.muted, bg: tint }, iw);
|
|
230
|
-
}
|
|
231
|
-
if (ts.message)
|
|
232
|
-
c.text(ix, gy + 1, ts.message, { fg: t.warn, bg: tint }, iw);
|
|
233
|
-
}
|
|
234
|
-
else if (ts.phase === 'signing') {
|
|
235
|
-
c.text(ix, gy, 'approve in Phantom (browser) — the signer verifies, re-simulates and submits…', { fg: t.ai, bg, b: true }, iw);
|
|
236
|
-
c.text(ix, gy + 1, 'nothing is sent until the signed bytes match the plan', { fg: t.muted, bg }, iw);
|
|
237
|
-
}
|
|
238
131
|
else if (ts.phase === 'filling') {
|
|
239
132
|
const line = view.rateLimited
|
|
240
133
|
? '⚠ rate limited by Jupiter — retrying… (esc cancels)'
|
|
241
134
|
: 'booking paper fill from a fresh quote… (esc cancels)';
|
|
242
135
|
c.text(ix, gy, line, { fg: view.rateLimited ? t.warn : t.ai, bg, b: true }, iw);
|
|
243
136
|
}
|
|
244
|
-
else if (ts.phase === 'filled' && isLive && live?.outcome?.kind === 'filled') {
|
|
245
|
-
const o = live.outcome;
|
|
246
|
-
const got = live.probe ? `wrap-and-unwrap confirmed · fee ${fmtSol(lamportsToSol(BigInt(o.fill.feeLamports)), 6)}` : `${fmtAmount(rawToTokens(o.fill.side === 'buy' ? BigInt(o.fill.tokenDelta) : -BigInt(o.fill.tokenDelta), o.fill.decimals))} ${o.fill.symbol} @ ${fmtPriceBare(o.fill.priceSol)} SOL`;
|
|
247
|
-
c.text(ix, gy, `✓ LIVE ${o.network.toUpperCase()} ${live.probe ? 'PROBE' : o.fill.side.toUpperCase()} confirmed — ${got}${o.lighthouseTail ? ` · +${o.lighthouseTail} Lighthouse` : ''}`, { fg: t.up, bg, b: true }, iw);
|
|
248
|
-
c.text(ix, gy + 1, `sig ${o.signature.slice(0, 12)}…${o.signature.slice(-6)} · esc=back · P=positions`, { fg: t.muted, bg }, iw);
|
|
249
|
-
}
|
|
250
137
|
else if (ts.phase === 'filled' && view.receipt) {
|
|
251
138
|
const r = view.receipt;
|
|
252
139
|
const got = r.side === 'buy' ? `${fmtAmount(rawToTokens(r.tokenDelta, r.decimals))} ${r.symbol}` : fmtSol(lamportsToSol(r.solDelta));
|
|
253
|
-
|
|
140
|
+
const at = mode === 'mcap' && sup !== null && r.priceUsd !== null ? `${fmtMcap(r.priceUsd * sup)} mcap (${fmtPriceBare(r.priceSol)} SOL)` : `${fmtPriceBare(r.priceSol)} SOL`; // task-1537
|
|
141
|
+
c.text(ix, gy, `✓ PAPER ${r.side.toUpperCase()} filled — ${got} @ ${at}`, { fg: t.up, bg, b: true }, iw);
|
|
254
142
|
const extra = r.side === 'sell' ? `realized ${r.realizedLamports >= 0n ? '+' : ''}${fmtSol(lamportsToSol(r.realizedLamports))}` : 'cost booked to position';
|
|
255
143
|
c.text(ix, gy + 1, `${extra} · esc=back to token · P=positions`, { fg: t.muted, bg }, iw);
|
|
256
144
|
}
|
|
257
|
-
else if (ts.phase === 'refused') {
|
|
258
|
-
c.text(ix, gy, `✗ REFUSED by the signer — ${ts.message ?? 'refused'}`, { fg: t.down, bg, b: true }, iw);
|
|
259
|
-
c.text(ix, gy + 1, 'nothing was signed or sent · esc=back · any key = new ticket', { fg: t.muted, bg }, iw);
|
|
260
|
-
}
|
|
261
145
|
else if (ts.phase === 'error') {
|
|
262
|
-
const unknown = live?.outcome?.kind === 'send-unknown';
|
|
263
146
|
c.text(ix, gy, `⚠ ${ts.message ?? 'order failed'}`, { fg: t.down, bg, b: true }, iw);
|
|
264
|
-
c.text(ix, gy + 1,
|
|
147
|
+
c.text(ix, gy + 1, 'esc=back to token · P=positions', { fg: t.muted, bg }, iw);
|
|
265
148
|
}
|
|
266
149
|
else {
|
|
267
|
-
c.text(ix, gy,
|
|
150
|
+
c.text(ix, gy, `⏎ review → Y confirm · gate ${ts.gateOn ? 'ON' : 'off'} (keypress required)`, { fg: t.muted, bg }, iw);
|
|
268
151
|
if (ts.message)
|
|
269
152
|
c.text(ix, gy + 1, ts.message, { fg: t.warn, bg }, iw);
|
|
270
153
|
}
|
|
271
|
-
const keys = [['⏎',
|
|
272
|
-
if (isLive && buy && ts.phase === 'editing' && !live?.probe)
|
|
273
|
-
keys.push(['f', 'fit cap']);
|
|
274
|
-
if (ts.phase === 'planning' && live?.retryAt)
|
|
275
|
-
keys.push(['r', 'retry now']);
|
|
154
|
+
const keys = [['⏎', 'review'], ['Y', 'confirm'], ['tab', 'field'], ['←→', 'side'], ['u', 'unit']];
|
|
276
155
|
keys.push(['esc', 'cancel'], ['P', 'positions']);
|
|
277
156
|
footer(c, keys, t.name, isCalm(state.vfx));
|
|
278
157
|
}
|
|
279
|
-
/** The PLAN block: everything the signer will sign, from the signer's own view. */
|
|
280
|
-
function renderPlan(c, ix, y, iw, bg, live, decimals, symbol, buy, now) {
|
|
281
|
-
const t = c.theme;
|
|
282
|
-
const p = live.plan;
|
|
283
|
-
const left = Math.max(0, Math.round((p.expiresAt - now) / 1000));
|
|
284
|
-
c.text(ix, y, `PLAN · ${p.network.toUpperCase()} · ${p.kind === 'probe' ? 'devnet probe' : 'jupiter swap'}`, { fg: p.network === 'mainnet' ? t.down : t.up, bg, b: true });
|
|
285
|
-
c.textR(ix, y, iw, `expires in ${left}s · ${p.hash.slice(0, 8)}`, { fg: left < 15 ? t.warn : t.dim, bg });
|
|
286
|
-
c.hline(ix - 1, y + 1, iw + 2, { fg: t.border, bg, soft: true });
|
|
287
|
-
y += 2;
|
|
288
|
-
const inRaw = BigInt(p.amountInRaw), outRaw = BigInt(p.amountOutRaw), minRaw = BigInt(p.minOutRaw);
|
|
289
|
-
if (p.kind === 'probe') {
|
|
290
|
-
kv(c, ix, y++, iw, bg, 'Wraps', `${fmtSol(lamportsToSol(inRaw))} → your own WSOL account → back to you`, t, t.text);
|
|
291
|
-
}
|
|
292
|
-
else {
|
|
293
|
-
// The plan's decimals are the ones the order was built with (the signer echoes them back).
|
|
294
|
-
const pay = buy ? fmtSol(lamportsToSol(inRaw)) : `${fmtAmount(rawToTokens(inRaw, p.decimals ?? decimals))} ${symbol}`;
|
|
295
|
-
const recv = buy ? `${fmtAmount(rawToTokens(outRaw, p.decimals ?? decimals))} ${symbol}` : fmtSol(lamportsToSol(outRaw));
|
|
296
|
-
const min = buy ? `${fmtAmount(rawToTokens(minRaw, p.decimals ?? decimals))} ${symbol}` : fmtSol(lamportsToSol(minRaw));
|
|
297
|
-
kv(c, ix, y++, iw, bg, 'You pay', pay, t, buy ? t.down : t.text);
|
|
298
|
-
kv(c, ix, y++, iw, bg, 'You receive', recv, t, t.up);
|
|
299
|
-
kv(c, ix, y++, iw, bg, 'Min received', `${min} (${p.slippageBps} bps slippage)`, t, t.muted);
|
|
300
|
-
const impact = p.priceImpactPct;
|
|
301
|
-
kv(c, ix, y++, iw, bg, 'Price impact', impact === null ? 'unknown' : fmtPct(impact, { sign: false }), t, impact !== null && impact > 3 ? t.down : impact !== null && impact > 1 ? t.warn : t.muted);
|
|
302
|
-
kv(c, ix, y++, iw, bg, 'Route', p.route.length ? p.route.join(' → ') : 'direct', t, t.accent);
|
|
303
|
-
}
|
|
304
|
-
kv(c, ix, y++, iw, bg, 'Fee', `${fmtSol(lamportsToSol(BigInt(p.feeLamports)), 6)}${p.prioritizationFeeLamports ? ` (incl. ${p.prioritizationFeeLamports} lamports priority)` : ''}`, t, t.muted);
|
|
305
|
-
kv(c, ix, y++, iw, bg, 'Notional', p.notionalUsd !== null ? `$${p.notionalUsd.toFixed(2)} (SOL $${p.solUsd.price?.toFixed(2) ?? '?'} via ${p.solUsd.sources?.join('+') ?? '?'})` : (p.network === 'mainnet' ? `unpriced — ${p.solUsd.reason ?? ''}` : 'devnet (no USD value)'), t, p.notionalUsd === null && p.network === 'mainnet' ? t.down : t.muted);
|
|
306
|
-
if (!p.sim.ran || p.sim.ok) {
|
|
307
|
-
kv(c, ix, y++, iw, bg, 'Simulation', !p.sim.ran ? 'not run' : `ok · ${p.sim.solOutLamports !== null ? `${fmtSol(lamportsToSol(BigInt(p.sim.solOutLamports)), 6)} leaves the wallet` : 'wallet delta unknown'}`, t, p.sim.ok ? t.up : t.down);
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
// task-1368 item f: the FULL RPC error, wrapped (it used to be cut to `invalid transaction: Tr…`), then the hint.
|
|
311
|
-
kv(c, ix, y++, iw, bg, 'Simulation', 'FAILED', t, t.down);
|
|
312
|
-
for (const line of wrapLines(p.sim.error ?? 'unknown error', iw - 2, 3))
|
|
313
|
-
c.text(ix + 2, y++, line, { fg: t.down, bg }, iw - 2);
|
|
314
|
-
const hint = simFailureHint(p, live.signer ? { perTradeUsd: live.signer.caps.perTradeUsd, dailyUsd: live.signer.caps.dailyUsd } : undefined);
|
|
315
|
-
if (hint)
|
|
316
|
-
for (const line of wrapLines(`↳ ${hint}`, iw - 2, 4))
|
|
317
|
-
c.text(ix + 2, y++, line, { fg: t.warn, bg }, iw - 2);
|
|
318
|
-
}
|
|
319
|
-
const ins = p.instructions.map((i) => `${i.program}${i.op ? `:${i.op}` : ''}`).join(' · ');
|
|
320
|
-
kv(c, ix, y++, iw, bg, 'Will sign', ins || '—', t, t.text);
|
|
321
|
-
kv(c, ix, y++, iw, bg, 'Policy', p.policy.ok ? 'swap shape ok · route bound to this plan · no fee account' : `REFUSE ${p.policy.reason}: ${p.policy.message}`, t, p.policy.ok ? t.up : t.down);
|
|
322
|
-
kv(c, ix, y++, iw, bg, 'Caps', p.precheck.ok ? 'within caps' : `REFUSE ${p.precheck.reason}: ${p.precheck.message}`, t, p.precheck.ok ? t.up : t.down);
|
|
323
|
-
return y + 1;
|
|
324
|
-
}
|
|
325
158
|
function field(c, x, y, w, bg, label, value, active, t) {
|
|
326
159
|
const lblW = 10;
|
|
327
160
|
c.text(x, y, label, { fg: t.dim, bg });
|
|
@@ -8,8 +8,9 @@ import { renderTokenLive } from "../live/screens/token-live.js";
|
|
|
8
8
|
import { aiTranscript } from "../fixtures.js";
|
|
9
9
|
import { renderAnalystSession } from "./analyst-session.js";
|
|
10
10
|
import { renderSocialPanel } from "./social-panel.js";
|
|
11
|
+
import { brainFor, factsFromFixture, renderBrainPanel } from "./brain.js";
|
|
11
12
|
import { layoutFor } from "../custom.js";
|
|
12
|
-
import { chartMode, priceModeOf } from "../display.js";
|
|
13
|
+
import { chartMode, chartTitle, chartAxisOf, priceModeOf, levelCell, supplyRatio } from "../display.js";
|
|
13
14
|
export function renderToken(c, state) {
|
|
14
15
|
if (state.live?.token && state.screener.source !== 'fixtures')
|
|
15
16
|
return renderTokenLive(c, state, state.live.token.view); // task-1298: live data path
|
|
@@ -48,13 +49,13 @@ export function renderToken(c, state) {
|
|
|
48
49
|
// price line: pump glow = gold bg band, dump = red band (the rain ramp of the moment)
|
|
49
50
|
const priceBg = pumping ? mix(t.bg, t.rainPump[2], 0.3) : dumping ? mix(t.bg, t.rainDump[2], 0.3) : t.bg;
|
|
50
51
|
// task-1366: mcap mode leads with the market cap and keeps the price beside it (fixture tokens always carry a supply)
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
52
|
+
const pm = chartMode(priceModeOf(state), tk.price, tk.mcap);
|
|
53
|
+
if (pm.kind === 'mcap') {
|
|
53
54
|
x = c.text(1, y, fmtMcap(tk.mcap), { fg: pumping ? t.rainPump[3] : t.text, bg: priceBg, b: true });
|
|
54
|
-
x = c.text(x, y, ` (${fmtPrice(tk.price)})`, { fg: t.dim, bg: priceBg });
|
|
55
|
+
x = c.text(x, y, ` (${fmtPrice(tk.price)})`, { fg: priceBg === t.bg ? t.dim : t.text, bg: priceBg }); // task-1537: readable on the pump / dump band
|
|
55
56
|
}
|
|
56
57
|
else
|
|
57
|
-
x = c.text(1, y, fmtPrice(tk.price), { fg:
|
|
58
|
+
x = c.text(1, y, fmtPrice(tk.price), { fg: pm.label ? t.warn : pumping ? t.rainPump[3] : t.text, bg: priceBg, b: true });
|
|
58
59
|
const deltas = [['5m', tk.chg.m5], ['1h', tk.chg.h1], ['6h', tk.chg.h6], ['24h', tk.chg.h24]];
|
|
59
60
|
x = c.text(x, y, ' ', { bg: t.bg });
|
|
60
61
|
for (const [k, vv] of deltas) {
|
|
@@ -70,7 +71,9 @@ export function renderToken(c, state) {
|
|
|
70
71
|
y += 1;
|
|
71
72
|
// ---- chart
|
|
72
73
|
const chartH = Math.max(10, Math.floor((bottom - y) * lay.chartFrac));
|
|
73
|
-
|
|
74
|
+
// task-1472: the chart Y axis is its own setting (default MARKET CAP, `A` toggles); the header above keeps `$`
|
|
75
|
+
const cm = chartMode(chartAxisOf(state), tk.price, tk.mcap);
|
|
76
|
+
const cb = c.box(0, y, mainW, chartH, { title: chartTitle(tk.symbol, '1h', cm, 'SOL'), caption: 'ohlcv: geckoterminal' });
|
|
74
77
|
const tfx = cb.x + cb.w - 2;
|
|
75
78
|
const tfs = ['1m', '5m', '15m', '1h', '4h', '1d'];
|
|
76
79
|
let tx = tfx - tfs.reduce((s, f) => s + f.length + 1, 0) - 24;
|
|
@@ -159,7 +162,7 @@ export function renderToken(c, state) {
|
|
|
159
162
|
let cx = c.text(hb.x + 1, hy, fmtAgeSec(tr.ago).padStart(4), { fg: t.dim, bg: hb.bg });
|
|
160
163
|
cx = c.text(cx + 1, hy, tr.side === 'buy' ? '▲BUY ' : '▼SELL', { fg: color, bg: hb.bg, b: true });
|
|
161
164
|
cx = c.textR(cx + 1, hy, 8, fmtUsd(tr.usd), { fg: t.text, bg: hb.bg });
|
|
162
|
-
cx = c.text(cx + 2, hy,
|
|
165
|
+
cx = c.text(cx + 2, hy, levelCell(priceModeOf(state), supplyRatio(tk.price, tk.mcap), tr.price), { fg: t.muted, bg: hb.bg }); // task-1537
|
|
163
166
|
cx = c.text(cx + 2, hy, shortAddr(tr.addr, 3), { fg: t.dim, bg: hb.bg });
|
|
164
167
|
if (tr.tag)
|
|
165
168
|
badge(c, cx + 1, hy, tr.tag, tr.tag === 'smart' ? t.accent : t.warn, { on: hb.bg });
|
|
@@ -171,8 +174,14 @@ export function renderToken(c, state) {
|
|
|
171
174
|
}
|
|
172
175
|
}
|
|
173
176
|
}
|
|
174
|
-
if (showAi)
|
|
175
|
-
|
|
177
|
+
if (showAi) {
|
|
178
|
+
// task-1473: in an auto mode (following an agent / AI scan) the panel is the BRAIN VIEW; otherwise the analyst
|
|
179
|
+
const brain = brainFor(state, factsFromFixture(tk, state.larpByMint?.get(tk.mint)?.verdict ?? null), isCalm(v), state.live?.scanMeterLabel?.() ?? '');
|
|
180
|
+
if (brain)
|
|
181
|
+
renderBrainPanel(c, mainW, top, aiW, bottom - top, brain.model, brain.opts);
|
|
182
|
+
else
|
|
183
|
+
analystPanel(c, mainW, top, aiW, bottom - top, tk, state);
|
|
184
|
+
}
|
|
176
185
|
footer(c, state.tokenSocial
|
|
177
186
|
? [['esc', 'back'], ['s', 'on-chain'], ['f', 'filter'], ['x', state.socialShowSpam ? 'hide spam' : 'show hidden'], ['K', 'KOL lists'], ['a', showAi ? 'hide analyst' : 'analyst'], ['w', 'watch'], ['q', 'quit']]
|
|
178
187
|
: [['esc', 'back'], ['g', 'go to'], ['a', showAi ? 'hide analyst' : 'analyst'], ['h/t/r', 'holders/trades/traders'], ['w', 'watch'], ['b', 'alert'], ['1-6', 'timeframe'], ['q', 'quit']], state.theme.name, isCalm(v));
|
|
@@ -70,7 +70,7 @@ export function renderTrending(c, state) {
|
|
|
70
70
|
if (rows.length === 0)
|
|
71
71
|
c.textC(box.x, box.y + 2, box.w, all.length ? 'no rows match the filter — f cycles filters, n clears the narrative' : 'nothing trending yet — the keyless venues refresh every 60 s', { fg: t.muted, bg, i: true });
|
|
72
72
|
else
|
|
73
|
-
table(c, box.x + 1, box.y, box.w - 2, box.h, { columns: cols, rows, selected: sel, scroll, bg });
|
|
73
|
+
table(c, box.x + 1, box.y, box.w - 2, box.h, { columns: cols, rows, selected: sel, scroll, bg, rowKey: (r) => r.mint });
|
|
74
74
|
// sub-panels
|
|
75
75
|
const sy = top + boardH;
|
|
76
76
|
const news = feed.newsItems(12);
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// dexterm — app state consumed by the screens. Screens are pure render(canvas, state) functions;
|
|
2
2
|
// renderFrame() draws the screen, the toast, then runs the effects post-pass (VISUAL-V2 §3).
|
|
3
|
-
import { Canvas, THEMES, applyFx, toast, makeVfx, setSources, marketActivity, candleActivity, isCalm, } from '../../tui/src/index.js';
|
|
3
|
+
import { Canvas, THEMES, applyFx, toast, makeVfx, setSources, marketActivity, candleActivity, isCalm, breakpoint, fmtMcap, } from '../../tui/src/index.js';
|
|
4
4
|
import { makeFixtures } from "./fixtures.js";
|
|
5
5
|
import { fromFixture } from "./screener/rows.js";
|
|
6
6
|
import { makeScreenerState, screenerView } from "./screener/view.js";
|
|
7
7
|
import { renderScreener } from "./screens/screener.js";
|
|
8
8
|
import { renderToken } from "./screens/token.js";
|
|
9
|
+
import { agentBrainActive } from "./screens/brain.js";
|
|
10
|
+
import { pnlChipVM, renderPnlChip, CHIP_PRICE_LEVEL } from "./screens/pnl-chip.js";
|
|
9
11
|
import { renderNewPairs } from "./screens/newpairs.js";
|
|
10
12
|
import { renderWatchlist } from "./screens/watchlist.js";
|
|
11
13
|
import { renderAnalyst } from "./screens/analyst.js";
|
|
@@ -20,6 +22,7 @@ import { renderNarrative } from "./screens/narrative.js";
|
|
|
20
22
|
import { renderPlans } from "./screens/plans.js";
|
|
21
23
|
import { renderFollows } from "./screens/follows.js";
|
|
22
24
|
import { renderRules } from "./screens/rules.js";
|
|
25
|
+
import { renderAutotrade } from "./screens/autotrade-screen.js";
|
|
23
26
|
import { CopyLive } from "./live/copy.js";
|
|
24
27
|
import { CopyAuto, defaultCopyJournalPath, leaderSoldSince } from '../../data/src/trade/copy/index.js';
|
|
25
28
|
import { computeBoard, loadDefaultLexicon, recentNarrativeRows } from '../../packs/src/index.js';
|
|
@@ -28,7 +31,9 @@ import { openTicket } from "./trade.js";
|
|
|
28
31
|
import { computeFill } from '../../data/src/index.js';
|
|
29
32
|
import { renderScanTicker, scanIndicator } from "./scan/ui.js";
|
|
30
33
|
import { renderVoiceHud } from "./voice-hud.js";
|
|
34
|
+
import { composeHud, DOCK_ROWS, HUD_MIN_H } from "./screens/agent-hud.js";
|
|
31
35
|
import { workspaceBadge } from "./custom.js";
|
|
36
|
+
import { chartAxisOf, supplyRatio, priceModeOf, supplyForMint } from "./display.js";
|
|
32
37
|
/** Map key for the Analyst-tab's own conversation (not tied to a single token). */
|
|
33
38
|
export const ANALYST_TAB_KEY = '__analyst_tab__';
|
|
34
39
|
/**
|
|
@@ -97,7 +102,7 @@ export function computeNarrativeView(state, window, now = Date.now()) {
|
|
|
97
102
|
return { board: null, window, computedAt: now, source: 'none', selected: 0, error: e instanceof Error ? e.message : String(e) };
|
|
98
103
|
}
|
|
99
104
|
}
|
|
100
|
-
export function newPlansUi() { return { tab: 'plans', selected: 0, notice: null, arming: null, riskModal: false
|
|
105
|
+
export function newPlansUi() { return { tab: 'plans', selected: 0, notice: null, arming: null, riskModal: false }; }
|
|
101
106
|
/**
|
|
102
107
|
* task-1363: how old a board price may be and still fire a plan. The terminal feeds the plan engine from its
|
|
103
108
|
* screener/watchlist refresh (about every 10 s) and the token screen, so the engine's 3 s default would never
|
|
@@ -175,6 +180,7 @@ export const RENDERERS = {
|
|
|
175
180
|
plans: renderPlans,
|
|
176
181
|
follows: renderFollows,
|
|
177
182
|
rules: renderRules,
|
|
183
|
+
autotrade: renderAutotrade,
|
|
178
184
|
};
|
|
179
185
|
export const SCREEN_NAMES = Object.keys(RENDERERS);
|
|
180
186
|
export function isScreenKey(s) {
|
|
@@ -202,6 +208,9 @@ export function isDemoScreen(s) {
|
|
|
202
208
|
// task-1360: the follows screen shows the user's own list + the tracker's real state (unavailable when keyless).
|
|
203
209
|
if (s.screen === 'follows')
|
|
204
210
|
return false;
|
|
211
|
+
// task-1508: the autotrade screen reads the user's own strategy files and the runner's status file (PAPER badge).
|
|
212
|
+
if (s.screen === 'autotrade')
|
|
213
|
+
return false;
|
|
205
214
|
// analyst screen: a live Claude session (even mid-run or failed) is real output, not demo data
|
|
206
215
|
return !s.analyst;
|
|
207
216
|
}
|
|
@@ -232,13 +241,10 @@ export function headerModel(s) {
|
|
|
232
241
|
feedLabel = 'jupiter · gecko · boosts · coingecko · rss · keyless';
|
|
233
242
|
if (s.screen === 'kol')
|
|
234
243
|
feedLabel = 'kol lists · sqlite';
|
|
235
|
-
// task-1355: the plans screen
|
|
236
|
-
// task-1363: once the fire path is LIVE (devnet fast wallet, keypress opt-in) the header says so; anything not
|
|
237
|
-
// provably paper renders LIVE (fail-safe).
|
|
244
|
+
// task-1355: the plans screen fires on PAPER only (task-1571: there is no live fire path) and says so.
|
|
238
245
|
if (s.screen === 'plans') {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
feedLabel = paper ? 'order plans · standing mandates · hash-chained journal' : 'order plans · signer process · fast wallet · devnet';
|
|
246
|
+
status = '◈ PAPER · plans journal';
|
|
247
|
+
feedLabel = 'order plans · standing mandates · hash-chained journal';
|
|
242
248
|
}
|
|
243
249
|
// task-1360: the follows screen reads public history for the user's own list; it never trades.
|
|
244
250
|
if (s.screen === 'follows')
|
|
@@ -246,14 +252,13 @@ export function headerModel(s) {
|
|
|
246
252
|
// task-1358: the rules screen evaluates the screener rows locally; rules only alert or PROPOSE.
|
|
247
253
|
if (s.screen === 'rules')
|
|
248
254
|
feedLabel = 'rules · config.json · alerts + proposals only · nothing arms';
|
|
255
|
+
// task-1508: autotrade is paper only; the screen edits strategy files and reads recorded history.
|
|
256
|
+
if (s.screen === 'autotrade') {
|
|
257
|
+
status = '◈ PAPER · autotrade';
|
|
258
|
+
feedLabel = 'strategies · recorded history · paper runner status';
|
|
259
|
+
}
|
|
249
260
|
if (s.screen === 'bubbles')
|
|
250
261
|
feedLabel = `${s.live?.rpc.provider === 'helius' ? 'helius history · ' : ''}rpc holders · rules · sqlite`;
|
|
251
|
-
// task-1328: a LIVE ticket says so in the header, with the SIGNER's network (never a UI flag).
|
|
252
|
-
if (s.screen === 'ticket' && s.live?.ticket?.ticket.mode === 'live') {
|
|
253
|
-
const net = s.live.ticket.view().live?.signer?.network ?? null;
|
|
254
|
-
status = net === 'mainnet' ? '⚠ LIVE · MAINNET · real funds' : net === 'devnet' ? '◉ LIVE · DEVNET' : '◉ LIVE · signer unreachable';
|
|
255
|
-
feedLabel = 'signer process · jupiter · phantom';
|
|
256
|
-
}
|
|
257
262
|
// task-1324: while AI scan mode is on the header ALWAYS says so (state + the scan's analyst meter +
|
|
258
263
|
// any Helius credit warning), on every screen — the running indicator wins over every other status.
|
|
259
264
|
let scanStatus = null;
|
|
@@ -298,6 +303,8 @@ export function makeFixtureState(opts = {}) {
|
|
|
298
303
|
larpByMint: new Map(),
|
|
299
304
|
colorDepth: opts.colorDepth ?? 'truecolor',
|
|
300
305
|
};
|
|
306
|
+
if (opts.priceMode)
|
|
307
|
+
state.priceMode = opts.priceMode;
|
|
301
308
|
refreshVfx(state);
|
|
302
309
|
if (screen === 'ticket' || screen === 'positions')
|
|
303
310
|
seedDemoTrade(state);
|
|
@@ -426,8 +433,57 @@ export function refreshVfx(state) {
|
|
|
426
433
|
state.vfx.activity = act.activity;
|
|
427
434
|
state.vfx.mood = act.mood;
|
|
428
435
|
}
|
|
429
|
-
/**
|
|
436
|
+
/**
|
|
437
|
+
* Render one frame of the current screen into a fresh canvas: screen → toast → effects. task-1466: while the
|
|
438
|
+
* terminal follows an agent, the screen renders DOCK_ROWS shorter and the agent HUD's dock takes the bottom rows
|
|
439
|
+
* (so no data is hidden), with its overlays (row glow, cursor, cards, flashes, the kill cut) over the screen.
|
|
440
|
+
*/
|
|
430
441
|
export function renderFrame(state, w, h) {
|
|
442
|
+
const hud = state.agentHud;
|
|
443
|
+
if (!hud || state.screen === 'boot' || h < HUD_MIN_H)
|
|
444
|
+
return renderScreenFrame(state, w, h, true);
|
|
445
|
+
const now = hud.clock();
|
|
446
|
+
const screen = renderScreenFrame(state, w, h - DOCK_ROWS, false);
|
|
447
|
+
const view = hud.story.view(now);
|
|
448
|
+
// task-1473: on the token screen the analyst panel is the agent's brain view (same rule the screen used)
|
|
449
|
+
const brain = state.screen === 'token' && state.aiOpen !== false && breakpoint(w) !== 'compact' && !state.aiFocused && agentBrainActive(view, now);
|
|
450
|
+
return composeHud(new Canvas(w, h, state.theme), screen, view, {
|
|
451
|
+
now, reduced: !!hud.reduced || isCalm(state.vfx), depth: state.colorDepth, dataLabel: hud.dataLabel ?? null, screen: state.screen, brain,
|
|
452
|
+
chip: pnlChipFor(state, now, view),
|
|
453
|
+
mcapScale: priceModeOf(state) === 'mcap' ? (mint) => hudMcapScale(state, mint) : undefined, // task-1472; task-1537: the HUD's text follows the price basis (the charts keep A)
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
/** task-1472: the supply ratio for the HUD's position card: the open token's (live, else fixture), else its screener row. */
|
|
457
|
+
function hudMcapScale(state, mint) {
|
|
458
|
+
const v = state.live?.token?.view;
|
|
459
|
+
if (v && v.mint === mint)
|
|
460
|
+
return supplyRatio(v.price, v.mcap);
|
|
461
|
+
const tk = state.token;
|
|
462
|
+
if (tk && tk.mint === mint)
|
|
463
|
+
return supplyRatio(tk.price, tk.mcap);
|
|
464
|
+
const row = state.screener.rows.find((r) => r.mint === mint); // the card also shows over the lists (task-1473)
|
|
465
|
+
return row ? supplyRatio(row.price, row.mcap) : null;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* task-1473: the POSITION PnL chip for the app's current auto mode, or null. Following an agent: its open PAPER
|
|
469
|
+
* ticket (the folded story). Else, while AI scan mode runs: the user's own held paper / live position (ownPnl).
|
|
470
|
+
* The same chip feeds the HUD dock, the band row (no dock) and the chart popup. Display only.
|
|
471
|
+
*/
|
|
472
|
+
export function pnlChipFor(state, now, view) {
|
|
473
|
+
const hud = state.agentHud;
|
|
474
|
+
// task-1537: entry / mark / TP read as market caps by default (the coin's known supply), else prices
|
|
475
|
+
const mode = priceModeOf(state);
|
|
476
|
+
const lvl = (u, mint) => { const sup = mode === 'mcap' ? supplyForMint(state, mint) : null; return sup !== null ? fmtMcap(u * sup) : CHIP_PRICE_LEVEL(u, mint); };
|
|
477
|
+
if (hud) {
|
|
478
|
+
const m = pnlChipVM(view ?? hud.story.view(now), now, lvl);
|
|
479
|
+
if (m)
|
|
480
|
+
return m;
|
|
481
|
+
}
|
|
482
|
+
if (state.scan?.engine.on && state.ownPnl)
|
|
483
|
+
return state.ownPnl.vm(now, lvl);
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
function renderScreenFrame(state, w, h, bandChip = false) {
|
|
431
487
|
const c = new Canvas(w, h, state.theme);
|
|
432
488
|
c.fill(0, 0, w, h, ' ', { bg: state.theme.bg });
|
|
433
489
|
c.imageMode = state.images && state.imageProtocol && state.imageProtocol !== 'blocks' ? 'pixels' : 'cells';
|
|
@@ -445,11 +501,25 @@ export function renderFrame(state, w, h) {
|
|
|
445
501
|
renderVoiceHud(c, state.voice, state.theme);
|
|
446
502
|
// task-1358: the workspace badge (non-default name, a pending ctrl+w chord, the save-as input) on the band
|
|
447
503
|
// under the header, right-aligned, drawn after the effects so it is always legible. Nothing on `default`.
|
|
504
|
+
// task-1473 r2: no HUD dock (short terminal, or AI scan mode): the PnL chip rides the band, right-aligned,
|
|
505
|
+
// and the workspace badge moves to its left.
|
|
506
|
+
let bandRight = w - 1;
|
|
507
|
+
if (bandChip && state.screen !== 'boot') {
|
|
508
|
+
const now = state.agentHud?.clock() ?? state.now.getTime();
|
|
509
|
+
const chip = pnlChipFor(state, now);
|
|
510
|
+
if (chip) {
|
|
511
|
+
const x0 = renderPnlChip(c, w - 1, 1, Math.max(36, Math.floor(w * 0.7)), chip, { now, reduced: !!state.agentHud?.reduced || isCalm(state.vfx) });
|
|
512
|
+
if (x0 < w - 1) {
|
|
513
|
+
c.noRain(x0, 1, w - 1 - x0, 1);
|
|
514
|
+
bandRight = x0 - 1;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
448
518
|
const badge = state.screen !== 'boot' ? workspaceBadge(state.custom, state.now.getTime()) : null;
|
|
449
|
-
if (badge) {
|
|
519
|
+
if (badge && bandRight > 4) {
|
|
450
520
|
const t = state.theme;
|
|
451
|
-
const text = badge.text.slice(0, Math.max(0,
|
|
452
|
-
const x = Math.max(0,
|
|
521
|
+
const text = badge.text.slice(0, Math.max(0, bandRight - 1));
|
|
522
|
+
const x = Math.max(0, bandRight - text.length);
|
|
453
523
|
c.noRain(x, 1, text.length, 1);
|
|
454
524
|
c.text(x, 1, text, badge.kind === 'input' ? { fg: t.text, bg: t.accentSoft, b: true } : badge.kind === 'chord' ? { fg: t.warn, bg: t.warnSoft, b: true } : { fg: t.accent, bg: t.headBg, b: true });
|
|
455
525
|
}
|