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
|
@@ -12,8 +12,11 @@
|
|
|
12
12
|
const $ = (id) => document.getElementById(id);
|
|
13
13
|
const titleEl = $('title'), legendEl = $('legend'), liveEl = $('live'), bannerEl = $('banner'), hintEl = $('hint');
|
|
14
14
|
const posEl = $('pos'), posTitleEl = $('pos-title'), posCapEl = $('pos-cap'), posCellsEl = $('pos-cells');
|
|
15
|
+
const chipEl = $('pnlchip');
|
|
15
16
|
const imgSlot = $('coin-img-slot');
|
|
16
17
|
const chartEl = $('chart'), drawCv = $('draw'), dctx = drawCv.getContext('2d');
|
|
18
|
+
// task-1483: the BUY / SELL marker hover card (built with textContent only)
|
|
19
|
+
const tipEl = document.createElement('div'); tipEl.className = 'mtip'; tipEl.hidden = true; chartEl.parentNode.appendChild(tipEl);
|
|
17
20
|
const STALE_MS = 20_000;
|
|
18
21
|
const DEFAULT_IND = ['volume', 'tape', 'ema9', 'ema21'];
|
|
19
22
|
/** Exposed for the headless harness (measure/popup-v2-1325): first paint + setData → repaint latency. */
|
|
@@ -25,6 +28,8 @@
|
|
|
25
28
|
draw: null, tPending: null, hover: null, drawings: [], lastDataAt: 0, firstPainted: false, fitNext: true,
|
|
26
29
|
banners: { fallback: null, data: null },
|
|
27
30
|
display: C.displayOf(null), // task-1366: price | mcap (from the VM's priceMode + supply)
|
|
31
|
+
marks: null, // task-1483: { set, on } — the BUY / SELL markers for the bars on screen (chart-lib chartMarkers)
|
|
32
|
+
mouse: null, // task-1483: crosshair point for the marker hover card
|
|
28
33
|
};
|
|
29
34
|
|
|
30
35
|
const banner = () => {
|
|
@@ -57,7 +62,7 @@
|
|
|
57
62
|
if (type === 2) return String(d.getUTCDate());
|
|
58
63
|
return `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}`;
|
|
59
64
|
}
|
|
60
|
-
const volFmt = (v) => C.
|
|
65
|
+
const volFmt = (v) => C.fmtCompactUsd(v); // task-1472: volume stays USD, compact k/M
|
|
61
66
|
|
|
62
67
|
// ---------------------------------------------------------------- chart + series
|
|
63
68
|
const chart = L.createChart(chartEl, {
|
|
@@ -80,14 +85,15 @@
|
|
|
80
85
|
handleScroll: { mouseWheel: true, pressedMouseMove: true, horzTouchDrag: true, vertTouchDrag: false },
|
|
81
86
|
handleScale: { axisPressedMouseMove: { time: true, price: true }, axisDoubleClickReset: true, mouseWheel: true, pinch: true },
|
|
82
87
|
});
|
|
83
|
-
// task-1366: the axis formatter follows the terminal's
|
|
88
|
+
// task-1366/1472: the axis formatter follows the terminal's chart axis (mcap = price × the current supply, compact k/M/B)
|
|
84
89
|
const pricePF = (p) => ({ type: 'custom', formatter: C.axisFormatter(S.display), minMove: C.priceFormatFor(p).minMove });
|
|
85
90
|
// Keep the position levels (entry / stop / target) and the live price in view: autoscale widens to include them
|
|
86
91
|
// when they are within 3× of the last close (a far-away level would squash the candles; its row cell still shows it).
|
|
87
92
|
function levels() {
|
|
88
93
|
const vm = S.vm || {}, pos = vm.position || null, out = [];
|
|
89
94
|
const last = S.bars.length ? S.bars[S.bars.length - 1].close : null;
|
|
90
|
-
|
|
95
|
+
const mk = S.marks && S.marks.on ? S.marks.set.markers.map((m) => m.priceUsd) : []; // task-1483: keep the fills in view
|
|
96
|
+
for (const v of [pos && pos.avgEntryUsd, pos && pos.stopUsd, pos && pos.targetUsd, vm.feed === 'LIVE' ? vm.livePrice : null, ...mk]) {
|
|
91
97
|
if (typeof v === 'number' && v > 0 && last && v / last < 3 && last / v < 3) out.push(v);
|
|
92
98
|
}
|
|
93
99
|
return out;
|
|
@@ -159,13 +165,18 @@
|
|
|
159
165
|
DT.onTheme(applyChartTheme);
|
|
160
166
|
|
|
161
167
|
// ---------------------------------------------------------------- toolbar (buttons built with textContent only)
|
|
162
|
-
const btns = { tf: new Map(), styles: new Map(), scales: new Map(), inds: new Map(), draws: new Map() };
|
|
168
|
+
const btns = { tf: new Map(), axis: new Map(), marks: new Map(), styles: new Map(), scales: new Map(), inds: new Map(), draws: new Map() };
|
|
163
169
|
function mkBtn(group, id, label, title, onClick) {
|
|
164
170
|
const b = document.createElement('button'); b.type = 'button'; b.className = 'tb'; b.textContent = label; b.title = title;
|
|
165
171
|
b.addEventListener('click', (e) => { e.preventDefault(); onClick(); });
|
|
166
172
|
$(group).appendChild(b); btns[group].set(id, b); return b;
|
|
167
173
|
}
|
|
168
174
|
C.INTERVALS.forEach((iv, i) => mkBtn('tf', iv, iv, `timeframe ${iv} (${i + 1})`, () => requestInterval(iv)));
|
|
175
|
+
// task-1472: MCAP | PRICE asks the terminal to switch (and save) the chart axis; the next VM re-labels the page
|
|
176
|
+
mkBtn('axis', 'mcap', 'MCAP', 'Y axis: market cap (A / y toggles; saved by the terminal)', () => setAxis('mcap'));
|
|
177
|
+
mkBtn('axis', 'price', 'PRICE', 'Y axis: USD price (A / y toggles; saved by the terminal)', () => setAxis('price'));
|
|
178
|
+
// task-1483: MARKERS on/off asks the terminal to switch (and save) display.chartMarkers; the next VM carries it
|
|
179
|
+
mkBtn('marks', 'on', 'MARKERS', 'BUY / SELL markers of your paper + live fills (k toggles; saved by the terminal)', () => setMarkers(!(S.vm && S.vm.marks && S.vm.marks.on)));
|
|
169
180
|
mkBtn('styles', 'candles', 'candles', 'candlesticks (c cycles)', () => setStyle('candles', true));
|
|
170
181
|
mkBtn('styles', 'line', 'line', 'line (c cycles)', () => setStyle('line', true));
|
|
171
182
|
mkBtn('styles', 'area', 'area', 'area (c cycles)', () => setStyle('area', true));
|
|
@@ -183,6 +194,10 @@
|
|
|
183
194
|
mkBtn('draws', 'x', '✕ clear', 'clear drawings (x; backspace = undo last)', () => clearDrawings());
|
|
184
195
|
function syncToolbar() {
|
|
185
196
|
for (const [iv, b] of btns.tf) { b.classList.toggle('on', iv === S.interval); b.classList.toggle('pending', iv === S.pendingInterval && iv !== S.interval); }
|
|
197
|
+
const ax = S.vm && S.vm.priceMode === 'mcap' ? 'mcap' : 'price';
|
|
198
|
+
for (const [k, b] of btns.axis) b.classList.toggle('on', k === ax);
|
|
199
|
+
const mOn = !!(S.vm && S.vm.marks && S.vm.marks.on);
|
|
200
|
+
for (const [, b] of btns.marks) { b.classList.toggle('on', mOn); b.hidden = !(S.vm && S.vm.marks); }
|
|
186
201
|
for (const [k, b] of btns.styles) b.classList.toggle('on', k === S.style);
|
|
187
202
|
for (const [k, b] of btns.scales) b.classList.toggle('on', k === S.scale);
|
|
188
203
|
for (const [k, b] of btns.inds) b.classList.toggle('on', S.ind.has(k));
|
|
@@ -196,6 +211,16 @@
|
|
|
196
211
|
S.pendingInterval = iv; S.reqAt = performance.now(); syncToolbar();
|
|
197
212
|
DT.send({ type: 'event', name: 'chart.interval', payload: { interval: iv } });
|
|
198
213
|
}
|
|
214
|
+
/** task-1472: ask the terminal for a Y axis; nothing changes here until its next VM carries the new mode. */
|
|
215
|
+
function setAxis(axis) {
|
|
216
|
+
if (axis !== 'mcap' && axis !== 'price') return;
|
|
217
|
+
DT.send({ type: 'event', name: 'chart.axis', payload: { axis } });
|
|
218
|
+
}
|
|
219
|
+
/** task-1483: ask the terminal to show / hide the markers; nothing changes here until its next VM says so. */
|
|
220
|
+
function setMarkers(on) {
|
|
221
|
+
if (typeof on !== 'boolean') return;
|
|
222
|
+
DT.send({ type: 'event', name: 'chart.markers', payload: { on } });
|
|
223
|
+
}
|
|
199
224
|
function setStyle(st, user) {
|
|
200
225
|
if (!C.STYLES.includes(st) || st === S.style) return;
|
|
201
226
|
S.style = st;
|
|
@@ -260,9 +285,82 @@
|
|
|
260
285
|
const times = new Set(S.bars.map((b) => b.time));
|
|
261
286
|
const list = [];
|
|
262
287
|
if (S.ind.has('tape')) list.push(...C.tapeMarkers(vm.trades, periodMs(), times, { up: DT.rgba(T.up, 0.85), down: DT.rgba(T.down, 0.85) }));
|
|
263
|
-
if (vm.position && vm.position.fills) list.push(...C.fillMarkers(vm.position.fills, periodMs(), times, { buy: T.accent, sell: T.warn }));
|
|
264
288
|
list.sort((a, b) => a.time - b.time);
|
|
265
289
|
markers[S.style].setMarkers(list);
|
|
290
|
+
computeMarks();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ---------------------------------------------------------------- task-1483: BUY / SELL markers of the ledgers' fills
|
|
294
|
+
// Bucketed to THIS page's timeframe by the bars' real times (re-bucketed on every timeframe change), drawn on the
|
|
295
|
+
// overlay canvas so paper (hollow) and live (solid) read apart, re-clustered when zooming out, hover card per marker.
|
|
296
|
+
function computeMarks() {
|
|
297
|
+
const mk = S.vm && S.vm.marks;
|
|
298
|
+
if (!mk) { S.marks = null; return; }
|
|
299
|
+
S.marks = { on: !!mk.on, truncated: mk.truncated | 0, set: C.chartMarkers(mk.fills, periodMs(), S.bars.map((b) => b.t)) };
|
|
300
|
+
}
|
|
301
|
+
const MARK_PX = 6;
|
|
302
|
+
let markHits = [];
|
|
303
|
+
function drawMarks(ts, s, paneH) {
|
|
304
|
+
markHits = [];
|
|
305
|
+
const mk = S.marks;
|
|
306
|
+
if (!mk || !mk.on || !S.bars.length) return;
|
|
307
|
+
const x0 = ts.logicalToCoordinate(0), x1 = ts.logicalToCoordinate(1);
|
|
308
|
+
const spacing = x0 != null && x1 != null ? Math.abs(x1 - x0) : 7;
|
|
309
|
+
// closed round trips: a faint wash entry → exit (green when sold above the entry)
|
|
310
|
+
for (const r of mk.set.trips) {
|
|
311
|
+
const a = C.logicalOf(S.bars, C.chartTime(Math.floor(r.openT / periodMs()) * periodMs()), periodMs() / 1000);
|
|
312
|
+
const b = C.logicalOf(S.bars, C.chartTime(Math.floor(r.closeT / periodMs()) * periodMs()), periodMs() / 1000);
|
|
313
|
+
const xa = ts.logicalToCoordinate(a), xb = ts.logicalToCoordinate(b);
|
|
314
|
+
if (xa == null || xb == null) continue;
|
|
315
|
+
const win = r.entryUsd !== null && r.exitUsd !== null ? r.exitUsd >= r.entryUsd : null;
|
|
316
|
+
dctx.fillStyle = DT.rgba(win === null ? T.muted : win ? T.up : T.down, 0.07);
|
|
317
|
+
dctx.fillRect(Math.min(xa, xb) - spacing / 2, 0, Math.abs(xb - xa) + spacing, paneH);
|
|
318
|
+
}
|
|
319
|
+
const shown = C.clusterMarkers(mk.set.markers, spacing, 14);
|
|
320
|
+
const used = new Map();
|
|
321
|
+
dctx.font = 'bold 10px ui-monospace, Menlo, monospace'; dctx.textAlign = 'center'; dctx.textBaseline = 'middle';
|
|
322
|
+
for (const m of shown) {
|
|
323
|
+
const x = ts.logicalToCoordinate(m.index);
|
|
324
|
+
const bar = S.bars[m.index];
|
|
325
|
+
if (x == null || !bar) continue;
|
|
326
|
+
const buy = m.side === 'buy';
|
|
327
|
+
let y = m.priceUsd !== null ? s.priceToCoordinate(m.priceUsd) : s.priceToCoordinate(buy ? bar.low : bar.high);
|
|
328
|
+
if (y == null) continue;
|
|
329
|
+
if (m.priceUsd === null) y += buy ? 4 : -4; // no recorded price: against the bar, never at a made-up price
|
|
330
|
+
// a second marker on the same bar and side steps away from the bar, never across it
|
|
331
|
+
const k = `${m.index}|${m.side}`; const n = used.get(k) || 0; used.set(k, n + 1);
|
|
332
|
+
if (n) y += (buy ? 1 : -1) * n * (MARK_PX * 1.6 + 12);
|
|
333
|
+
if (y < -20 || y > paneH + 20) continue;
|
|
334
|
+
const g = C.markerShape(m.side, x, y, MARK_PX);
|
|
335
|
+
const col = buy ? T.up : T.down;
|
|
336
|
+
dctx.beginPath(); dctx.moveTo(g.tri[0][0], g.tri[0][1]); dctx.lineTo(g.tri[1][0], g.tri[1][1]); dctx.lineTo(g.tri[2][0], g.tri[2][1]); dctx.closePath();
|
|
337
|
+
// a dark halo first, so a green buy still reads on a green candle (and a red sell on a red one)
|
|
338
|
+
dctx.setLineDash([]); dctx.lineJoin = 'round'; dctx.lineWidth = 4; dctx.strokeStyle = DT.rgba(T.bg, 0.92); dctx.stroke();
|
|
339
|
+
if (m.source === 'live') { dctx.fillStyle = col; dctx.fill(); dctx.lineWidth = 1.2; dctx.strokeStyle = DT.rgba(T.text, 0.95); dctx.stroke(); } // solid + a light edge: never mistaken for a hollow paper mark on a same-colour candle
|
|
340
|
+
else { dctx.fillStyle = DT.rgba(T.bg, 0.85); dctx.fill(); dctx.fillStyle = DT.rgba(col, 0.22); dctx.fill(); dctx.lineWidth = 1.6; dctx.strokeStyle = col; dctx.stroke(); }
|
|
341
|
+
const txt = `${C.markerLetter(m.side)}${m.count > 1 ? '×' + m.count : ''}`;
|
|
342
|
+
dctx.lineWidth = 3; dctx.strokeStyle = DT.rgba(T.bg, 0.92); dctx.strokeText(txt, g.labelX, g.labelY);
|
|
343
|
+
dctx.fillStyle = col; dctx.fillText(txt, g.labelX, g.labelY);
|
|
344
|
+
markHits.push({ m, hit: g.hit, x, y });
|
|
345
|
+
}
|
|
346
|
+
hoverMarks();
|
|
347
|
+
}
|
|
348
|
+
/** The hover card for the marker under the crosshair (time, price, size, source). Text only. */
|
|
349
|
+
function hoverMarks() {
|
|
350
|
+
const p = S.mouse;
|
|
351
|
+
const hit = p ? markHits.find((h) => p.x >= h.hit.x0 && p.x <= h.hit.x1 && p.y >= h.hit.y0 && p.y <= h.hit.y1) : null;
|
|
352
|
+
if (!hit) { if (!tipEl.hidden) tipEl.hidden = true; return; }
|
|
353
|
+
const lines = C.markerTooltip(hit.m, S.display, (ms) => fmtTime(C.chartTime(ms)));
|
|
354
|
+
const key = lines.join('|');
|
|
355
|
+
if (tipEl.dataset.k !== key) {
|
|
356
|
+
tipEl.dataset.k = key;
|
|
357
|
+
while (tipEl.firstChild) tipEl.removeChild(tipEl.firstChild);
|
|
358
|
+
lines.forEach((t, i) => tipEl.appendChild(el('div', i === 0 ? `h ${hit.m.side}` : i === lines.length - 1 ? `src ${hit.m.source}` : null, t)));
|
|
359
|
+
}
|
|
360
|
+
tipEl.hidden = false;
|
|
361
|
+
const w = chartEl.clientWidth;
|
|
362
|
+
const left = hit.x + 14 + 190 > w ? hit.x - 14 - tipEl.offsetWidth : hit.x + 14;
|
|
363
|
+
tipEl.style.left = `${Math.max(4, left)}px`; tipEl.style.top = `${Math.max(4, hit.y - 20)}px`;
|
|
266
364
|
}
|
|
267
365
|
|
|
268
366
|
function renderOverlays() {
|
|
@@ -270,7 +368,8 @@
|
|
|
270
368
|
const pos = vm.position || null;
|
|
271
369
|
if (pos && typeof pos.avgEntryUsd === 'number' && pos.avgEntryUsd > 0) {
|
|
272
370
|
const pct = typeof pos.unrealizedPct === 'number' ? ` ${C.fmtPct(pos.unrealizedPct, 1)}` : '';
|
|
273
|
-
|
|
371
|
+
// task-1483: the average entry of the open position is a DASHED line (fills are the triangles)
|
|
372
|
+
setLine('entry', { price: pos.avgEntryUsd, color: pos.kind === 'paper' ? T.warn : T.text, lineWidth: 1, lineStyle: L.LineStyle.LargeDashed, axisLabelVisible: true, axisLabelColor: pos.kind === 'paper' ? T.warn : T.text, axisLabelTextColor: T.bg, title: `AVG ENTRY ${pos.sizeLabel}${pct}` });
|
|
274
373
|
} else setLine('entry', null);
|
|
275
374
|
setLine('stop', pos && typeof pos.stopUsd === 'number' && pos.stopUsd > 0 ? { price: pos.stopUsd, color: T.down, lineWidth: 1, lineStyle: L.LineStyle.Dashed, axisLabelVisible: true, title: 'STOP' } : null);
|
|
276
375
|
setLine('target', pos && typeof pos.targetUsd === 'number' && pos.targetUsd > 0 ? { price: pos.targetUsd, color: T.up, lineWidth: 1, lineStyle: L.LineStyle.Dashed, axisLabelVisible: true, title: 'TARGET' } : null);
|
|
@@ -331,8 +430,14 @@
|
|
|
331
430
|
r2.appendChild(s);
|
|
332
431
|
}
|
|
333
432
|
if (r2.firstChild) legendEl.appendChild(r2);
|
|
433
|
+
// task-1483: which markers are on screen, and what the window left off (never moved onto another bar)
|
|
434
|
+
if (S.marks && S.marks.on) {
|
|
435
|
+
const lg = C.markerLegend(S.marks.set.markers);
|
|
436
|
+
const om = C.omittedNote({ ...S.marks.set, before: S.marks.set.before + S.marks.truncated });
|
|
437
|
+
if (lg || om) { const r3 = el('div', 'row3'); if (lg) r3.appendChild(el('span', S.marks.set.markers.some((m) => m.source === 'paper') ? 'paper' : null, lg)); if (om) r3.appendChild(el('span', null, `${lg ? ' · ' : ''}${om}`)); legendEl.appendChild(r3); }
|
|
438
|
+
}
|
|
334
439
|
}
|
|
335
|
-
chart.subscribeCrosshairMove((p) => { S.hover = p && p.time != null ? p.time : null; renderLegend(S.hover); });
|
|
440
|
+
chart.subscribeCrosshairMove((p) => { S.hover = p && p.time != null ? p.time : null; S.mouse = p && p.point ? { x: p.point.x, y: p.point.y } : null; renderLegend(S.hover); });
|
|
336
441
|
|
|
337
442
|
// ---------------------------------------------------------------- header, LIVE badge, banner, position row
|
|
338
443
|
function renderHeader() {
|
|
@@ -397,6 +502,23 @@
|
|
|
397
502
|
}
|
|
398
503
|
}
|
|
399
504
|
|
|
505
|
+
// task-1473 r2: the POSITION PnL chip (formatted terminal-side; textContent only, display only)
|
|
506
|
+
function renderChip() {
|
|
507
|
+
const chip = S.vm && S.vm.chip;
|
|
508
|
+
if (!chipEl) return;
|
|
509
|
+
if (!chip || !Array.isArray(chip.segments) || !chip.segments.length) { chipEl.hidden = true; return; }
|
|
510
|
+
chipEl.hidden = false;
|
|
511
|
+
while (chipEl.firstChild) chipEl.removeChild(chipEl.firstChild);
|
|
512
|
+
const tone = ['up', 'down'].includes(chip.tone) ? chip.tone : '';
|
|
513
|
+
for (const sg of chip.segments.slice(0, 8)) {
|
|
514
|
+
const id = ['head', 'pnl', 'peak', 'px', 'held', 'dd', 'tp'].includes(sg.id) ? sg.id : 'x';
|
|
515
|
+
let cls = `seg ${id}`;
|
|
516
|
+
if (id === 'pnl') cls += ` ${tone}${chip.newPeak ? ' flash' : ''}`;
|
|
517
|
+
if (id === 'peak') cls += ` ${/^peak −/.test(String(sg.text)) ? 'down' : 'up'}`;
|
|
518
|
+
chipEl.appendChild(el('span', cls, String(sg.text).slice(0, 48)));
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
400
522
|
// ---------------------------------------------------------------- incoming view models
|
|
401
523
|
function onData(vm) {
|
|
402
524
|
if (!vm || typeof vm !== 'object') return;
|
|
@@ -409,7 +531,7 @@
|
|
|
409
531
|
// task-1366: a mode / supply change re-labels the axis in place (the bars are prices either way)
|
|
410
532
|
const disp = C.displayOf(vm);
|
|
411
533
|
if (disp.key !== S.display.key) { S.display = disp; applyPriceFormat(); }
|
|
412
|
-
if (tail && (!vm.seriesKey || vm.seriesKey !== S.key)) { S.vm = { ...vm, candles: [] }; renderHeader(); renderPosition(); renderOverlays(); return; }
|
|
534
|
+
if (tail && (!vm.seriesKey || vm.seriesKey !== S.key)) { S.vm = { ...vm, candles: [] }; renderHeader(); renderPosition(); renderChip(); renderOverlays(); computeMarks(); syncToolbar(); return; }
|
|
413
535
|
const intervalChanged = vm.interval !== S.interval;
|
|
414
536
|
S.interval = vm.interval;
|
|
415
537
|
const answered = S.pendingInterval === vm.interval ? S.reqAt : null;
|
|
@@ -425,7 +547,7 @@
|
|
|
425
547
|
if (intervalChanged || S.key !== prevKey) S.fitNext = true;
|
|
426
548
|
renderFull();
|
|
427
549
|
}
|
|
428
|
-
renderHeader(); renderLegend(S.hover); renderDataBanner(); renderPosition(); syncToolbar(); renderLive();
|
|
550
|
+
renderHeader(); renderLegend(S.hover); renderDataBanner(); renderPosition(); renderChip(); syncToolbar(); renderLive();
|
|
429
551
|
// rain mood follows direction (gold on a pump, red-shift on a dump), as in the v1 HUD; chg is in percent
|
|
430
552
|
const dir = vm.chg ? (vm.chg.h24 ?? vm.chg.h1 ?? 0) : 0;
|
|
431
553
|
if (rain) { rain.setMood(dir > 1 ? 'rainPump' : dir < -1 ? 'rainDump' : 'rain'); rain.setActivity(Math.min(1, 0.4 + Math.abs(dir) / 100)); rain.setSources([String(vm.symbol || ''), String(vm.mint || '').slice(0, 6)]); }
|
|
@@ -492,10 +614,12 @@
|
|
|
492
614
|
dctx.clearRect(0, 0, w, h);
|
|
493
615
|
const segs = S.drawings.filter((d) => d.kind === 't').map((d) => [d.a, d.b]);
|
|
494
616
|
if (S.tPending && mouse) segs.push([S.tPending, mouse]);
|
|
495
|
-
if (!
|
|
617
|
+
if (!S.bars.length) return;
|
|
496
618
|
const ts = chart.timeScale(), s = active(), pS = periodMs() / 1000;
|
|
497
619
|
const paneH = chart.panes()[0] ? chart.panes()[0].getHeight() : h;
|
|
498
620
|
dctx.save(); dctx.beginPath(); dctx.rect(0, 0, ts.width(), paneH); dctx.clip();
|
|
621
|
+
drawMarks(ts, s, paneH); // task-1483
|
|
622
|
+
if (!segs.length) { dctx.restore(); return; }
|
|
499
623
|
dctx.strokeStyle = T.accent; dctx.fillStyle = T.accent; dctx.lineWidth = 1.5;
|
|
500
624
|
for (const [a, b] of segs) {
|
|
501
625
|
const xa = ts.logicalToCoordinate(C.logicalOf(S.bars, a.time, pS)), xb = ts.logicalToCoordinate(C.logicalOf(S.bars, b.time, pS));
|
|
@@ -514,6 +638,7 @@
|
|
|
514
638
|
const n = parseInt(k, 10);
|
|
515
639
|
if (n >= 1 && n <= 6) { requestInterval(C.INTERVALS[n - 1]); return; }
|
|
516
640
|
switch (k) {
|
|
641
|
+
case 'A': case 'y': setAxis(S.vm && S.vm.priceMode === 'mcap' ? 'price' : 'mcap'); break; // task-1472
|
|
517
642
|
case 'c': setStyle(C.STYLES[(C.STYLES.indexOf(S.style) + 1) % C.STYLES.length], true); break;
|
|
518
643
|
case 'a': setScale('auto', true); break;
|
|
519
644
|
case 'l': setScale(S.scale === 'log' ? 'auto' : 'log', true); break;
|
|
@@ -523,6 +648,7 @@
|
|
|
523
648
|
case 'm': toggleInd('volma'); break;
|
|
524
649
|
case 'v': toggleInd('volume'); break;
|
|
525
650
|
case 'b': toggleInd('tape'); break;
|
|
651
|
+
case 'k': setMarkers(!(S.vm && S.vm.marks && S.vm.marks.on)); break; // task-1483
|
|
526
652
|
case 'h': armDraw('h'); break;
|
|
527
653
|
case 't': armDraw('t'); break;
|
|
528
654
|
case 'x': clearDrawings(); break;
|
|
@@ -43,3 +43,48 @@
|
|
|
43
43
|
.spec-act-age { color: var(--warn); }
|
|
44
44
|
|
|
45
45
|
.spec-foot-redact { color: var(--up); font-weight: 600; }
|
|
46
|
+
|
|
47
|
+
/* task-1466 spectator v2: the agent story (phase rail + heartbeat, thought ribbon, call timeline, vetting + PAPER cards) */
|
|
48
|
+
.spec-story { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; font: 12px ui-monospace, Menlo, monospace; }
|
|
49
|
+
.spec-rail { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
|
|
50
|
+
.spec-heart { width: 10px; height: 10px; border-radius: 50%; background: var(--down); margin-right: 6px; box-shadow: 0 0 8px var(--down); animation: spec-beat 1s infinite ease-out; }
|
|
51
|
+
.spec-heart.still { animation: none; background: var(--warn); box-shadow: none; }
|
|
52
|
+
.spec-heart.dead { animation: none; background: var(--dim); box-shadow: none; }
|
|
53
|
+
@keyframes spec-beat { 0% { transform: scale(1.35); opacity: 1; } 30% { transform: scale(0.9); opacity: 0.7; } 100% { transform: scale(1); opacity: 0.85; } }
|
|
54
|
+
.spec-bpm { color: var(--muted); margin-right: 8px; min-width: 44px; }
|
|
55
|
+
.spec-phase { padding: 2px 8px; border-radius: 4px; color: var(--dim); border: 1px solid transparent; letter-spacing: 0.05em; }
|
|
56
|
+
.spec-phase.done { color: var(--muted); }
|
|
57
|
+
.spec-phase.on { color: #000; background: var(--accent); font-weight: 700; box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 60%, transparent); }
|
|
58
|
+
.spec-phase.on.p-vetting { background: var(--borderFocus); box-shadow: 0 0 12px color-mix(in srgb, var(--borderFocus) 60%, transparent); }
|
|
59
|
+
.spec-phase.on.p-sizing { background: var(--warn); }
|
|
60
|
+
.spec-phase.on.p-executing { background: var(--up); }
|
|
61
|
+
.spec-phase.on.p-holding { background: var(--pump); }
|
|
62
|
+
.spec-phase.on.p-exiting { background: var(--ai, var(--accent)); }
|
|
63
|
+
.spec-sep { color: var(--border); }
|
|
64
|
+
.spec-paper { margin-left: auto; padding: 1px 6px; border-radius: 4px; background: var(--warn); color: #000; font-weight: 700; }
|
|
65
|
+
.spec-ctlstate { padding: 1px 6px; border-radius: 4px; font-weight: 700; color: #000; }
|
|
66
|
+
.spec-ctlstate.paused { background: var(--warn); }
|
|
67
|
+
.spec-ctlstate.takeover { background: var(--accent); }
|
|
68
|
+
.spec-ctlstate.killed { background: var(--down); color: #fff; }
|
|
69
|
+
.spec-ribbon { padding: 6px 8px; border-left: 3px solid var(--ai, var(--accent)); background: color-mix(in srgb, var(--panel) 85%, transparent); color: var(--text); min-height: 1.4em; }
|
|
70
|
+
.spec-ribbon.ours { border-left-color: var(--border); color: var(--muted); font-style: italic; }
|
|
71
|
+
.spec-ribbon-who { color: var(--ai, var(--accent)); margin-right: 6px; font-style: normal; }
|
|
72
|
+
.spec-timeline { display: flex; align-items: flex-start; gap: 0; overflow: hidden; justify-content: flex-end; }
|
|
73
|
+
.spec-node { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 0 2px; }
|
|
74
|
+
.spec-node-l { color: var(--text); white-space: nowrap; }
|
|
75
|
+
.spec-node.paper .spec-node-l { color: var(--warn); font-weight: 700; }
|
|
76
|
+
.spec-chip { font-size: 10px; padding: 0 5px; border-radius: 3px; background: color-mix(in srgb, var(--up) 18%, transparent); color: var(--up); }
|
|
77
|
+
.spec-chip.slow { background: color-mix(in srgb, var(--warn) 18%, transparent); color: var(--warn); }
|
|
78
|
+
.spec-chip.fail, .spec-chip.refused { background: color-mix(in srgb, var(--down) 22%, transparent); color: var(--down); }
|
|
79
|
+
.spec-link { color: var(--border); align-self: flex-start; margin-top: 1px; }
|
|
80
|
+
.spec-cards { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
81
|
+
.spec-card { flex: 1 1 220px; border: 1px solid var(--border); border-radius: 6px; padding: 6px 8px; background: color-mix(in srgb, var(--panel) 85%, transparent); }
|
|
82
|
+
.spec-card-h { color: #000; background: var(--borderFocus); font-weight: 700; padding: 0 6px; border-radius: 3px; display: inline-block; margin-bottom: 4px; }
|
|
83
|
+
.spec-card.trade .spec-card-h { background: var(--pump); }
|
|
84
|
+
.spec-check { margin-right: 8px; color: var(--dim); }
|
|
85
|
+
.spec-check.ok { color: var(--up); font-weight: 600; }
|
|
86
|
+
.spec-big { font-size: 30px; font-weight: 800; letter-spacing: 0.02em; line-height: 1.1; }
|
|
87
|
+
.spec-big.up { color: var(--up); text-shadow: 0 0 14px color-mix(in srgb, var(--up) 45%, transparent); }
|
|
88
|
+
.spec-big.down { color: var(--down); }
|
|
89
|
+
.spec-kv { color: var(--muted); }
|
|
90
|
+
.spec-kv b { color: var(--text); font-weight: 600; }
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
<div id="hud" class="hud">
|
|
13
13
|
<div id="drag" class="drag"><span class="mark">✦</span><span id="title" class="title">dexterm · WATCH THE AGENT COOK</span><span id="status" class="status">connecting…</span><button id="close" class="close" type="button" aria-label="close">✕</button></div>
|
|
14
14
|
<div class="stage"><canvas id="rain"></canvas><div class="body">
|
|
15
|
+
<div id="story" class="spec-story"></div>
|
|
15
16
|
<div id="screen" class="spec-screen"></div>
|
|
16
17
|
<div id="agents" class="spec-agents"></div>
|
|
17
18
|
<div class="spec-activity-head">agent activity</div>
|
|
@@ -14,8 +14,77 @@
|
|
|
14
14
|
|
|
15
15
|
let vm = null;
|
|
16
16
|
|
|
17
|
+
const pctS = (p) => (p == null ? '—' : `${p >= 0 ? '+' : '−'}${Math.abs(p * 100).toFixed(1)}%`);
|
|
18
|
+
const px = (n) => (n == null ? '—' : n >= 1 ? `$${n.toFixed(4)}` : `$${Number(n.toPrecision(3))}`);
|
|
19
|
+
const fmtMs = (ms) => (ms == null ? '·' : ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(1)}s`);
|
|
20
|
+
const CHECKS = ['price', 'tape', 'chart', 'holders', 'rug', 'dev', 'larp', 'verdict'];
|
|
21
|
+
|
|
22
|
+
// task-1466 spectator v2: the agent story above the activity list (textContent only; strings redacted TUI-side).
|
|
23
|
+
function renderStory(st) {
|
|
24
|
+
const host = $('story'); host.textContent = '';
|
|
25
|
+
if (!st) return;
|
|
26
|
+
const rail = el('div', 'spec-rail');
|
|
27
|
+
const heart = el('span', 'spec-heart' + (st.control === 'killed' ? ' dead' : st.control !== 'running' ? ' still' : ''));
|
|
28
|
+
if (st.bpm > 0) heart.style.animationDuration = `${(60 / st.bpm).toFixed(2)}s`;
|
|
29
|
+
rail.appendChild(heart);
|
|
30
|
+
rail.appendChild(el('span', 'spec-bpm', st.control === 'killed' ? '— bpm' : `${st.bpm} bpm`));
|
|
31
|
+
const ai = st.rail.indexOf(st.phase);
|
|
32
|
+
st.rail.forEach((p, i) => {
|
|
33
|
+
if (i) rail.appendChild(el('span', 'spec-sep', '─'));
|
|
34
|
+
const on = i === ai && st.control !== 'killed';
|
|
35
|
+
rail.appendChild(el('span', 'spec-phase p-' + p + (on ? ' on' : i < ai ? ' done' : ''), (on ? '▸' : '') + p.toUpperCase() + (on && st.sub ? ` · ${st.sub}` : '')));
|
|
36
|
+
});
|
|
37
|
+
if (st.control !== 'running') rail.appendChild(el('span', 'spec-ctlstate ' + st.control, st.control === 'killed' ? '■ KILLED' : st.control === 'paused' ? '❚❚ PAUSED' : 'YOU ARE DRIVING'));
|
|
38
|
+
rail.appendChild(el('span', 'spec-paper', 'PAPER'));
|
|
39
|
+
host.appendChild(rail);
|
|
40
|
+
const th = (st.thoughts || []).slice().reverse();
|
|
41
|
+
const agentT = th.find((x) => x.source === 'agent');
|
|
42
|
+
const ours = th.find((x) => x.source === 'dexterm');
|
|
43
|
+
const pick = agentT && (!ours || agentT.t >= ours.t - 1500 || Date.now() - agentT.t < 9000) ? agentT : ours || agentT;
|
|
44
|
+
const rib = el('div', 'spec-ribbon' + (pick && pick.source === 'dexterm' ? ' ours' : ''));
|
|
45
|
+
if (pick) { if (pick.source === 'agent') rib.appendChild(el('span', 'spec-ribbon-who', '❯')); rib.appendChild(el('span', '', pick.text)); }
|
|
46
|
+
else rib.appendChild(el('span', 'spec-dim', 'the agent has not said anything yet'));
|
|
47
|
+
host.appendChild(rib);
|
|
48
|
+
const tl = el('div', 'spec-timeline');
|
|
49
|
+
(st.nodes || []).slice(-14).forEach((n, i) => {
|
|
50
|
+
if (i) tl.appendChild(el('span', 'spec-link', '──'));
|
|
51
|
+
const node = el('div', 'spec-node' + (n.paper ? ' paper' : ''));
|
|
52
|
+
node.appendChild(el('span', 'spec-node-l', `${n.status === 'refused' ? '✗' : n.paper ? '■' : '●'} ${n.label}${n.count > 1 ? ` ×${n.count}` : ''}`));
|
|
53
|
+
node.appendChild(el('span', 'spec-chip ' + n.status, n.status === 'refused' ? 'refused' : fmtMs(n.ms)));
|
|
54
|
+
tl.appendChild(node);
|
|
55
|
+
});
|
|
56
|
+
host.appendChild(tl);
|
|
57
|
+
const cards = el('div', 'spec-cards');
|
|
58
|
+
if (st.focus) {
|
|
59
|
+
const c = el('div', 'spec-card');
|
|
60
|
+
c.appendChild(el('span', 'spec-card-h', `VETTING $${st.focus.symbol}`));
|
|
61
|
+
const row = el('div');
|
|
62
|
+
for (const k of CHECKS) row.appendChild(el('span', 'spec-check' + (st.focus.checks.includes(k) ? ' ok' : ''), `${st.focus.checks.includes(k) ? '✓' : '·'}${k}`));
|
|
63
|
+
c.appendChild(row);
|
|
64
|
+
if (st.focus.larpFlags != null) c.appendChild(el('div', 'spec-kv', `LARP evidence: ${st.focus.larpFlags} flag${st.focus.larpFlags === 1 ? '' : 's'} (not a verdict)`));
|
|
65
|
+
if (st.focus.verdict) c.appendChild(el('div', 'spec-kv', `verdict ${st.focus.verdict}${st.focus.rug != null ? ` · rug heuristic ${Math.round(st.focus.rug * 100)}%` : ''}`));
|
|
66
|
+
cards.appendChild(c);
|
|
67
|
+
}
|
|
68
|
+
if (st.arc) {
|
|
69
|
+
const a = st.arc;
|
|
70
|
+
const c = el('div', 'spec-card trade');
|
|
71
|
+
c.appendChild(el('span', 'spec-card-h', `PAPER · $${a.symbol} · ${a.stage === 'closed' ? 'RESULT' : a.stage === 'open' ? 'HOLDING' : a.stage === 'refused' ? 'REFUSED' : 'TICKET'}`));
|
|
72
|
+
const big = a.stage === 'closed' ? a.resultPct : a.pnlPct;
|
|
73
|
+
if (big != null) c.appendChild(el('div', 'spec-big ' + (big >= 0 ? 'up' : 'down'), pctS(big)));
|
|
74
|
+
const kv = el('div', 'spec-kv');
|
|
75
|
+
kv.textContent = [a.sizeUsd != null ? `size $${a.sizeUsd.toFixed(2)}` : null, a.entryUsd != null ? `entry ${px(a.entryUsd)}` : null, a.markUsd != null && a.stage !== 'closed' ? `mark ${px(a.markUsd)}` : null,
|
|
76
|
+
a.peakPct != null ? `peak ${pctS(a.peakPct)}` : null, a.exits ? `exits ${a.exits}` : null, a.realizedSol != null ? `realized ${a.realizedSol >= 0 ? '+' : ''}${a.realizedSol.toFixed(4)} SOL` : null,
|
|
77
|
+
a.refusal ? `refused: ${a.refusal}` : null].filter(Boolean).join(' · ');
|
|
78
|
+
c.appendChild(kv);
|
|
79
|
+
c.appendChild(el('div', 'spec-dim', 'simulated paper trade · not a result'));
|
|
80
|
+
cards.appendChild(c);
|
|
81
|
+
}
|
|
82
|
+
if (cards.childNodes.length) host.appendChild(cards);
|
|
83
|
+
}
|
|
84
|
+
|
|
17
85
|
function render() {
|
|
18
86
|
if (!vm) return;
|
|
87
|
+
renderStory(vm.story || null);
|
|
19
88
|
|
|
20
89
|
const scr = $('screen'); scr.textContent = '';
|
|
21
90
|
const s = vm.screen || {};
|
|
@@ -28,4 +28,8 @@ export const CHART_INDICATORS = ['ema9', 'ema21', 'vwap', 'volma', 'volume', 'ta
|
|
|
28
28
|
export const CHART_STYLES = ['candles', 'line', 'area'];
|
|
29
29
|
/** Price-scale mode: auto (normal, autoscaled), logarithmic, percent (from the first visible bar). */
|
|
30
30
|
export const CHART_SCALES = ['auto', 'log', 'percent'];
|
|
31
|
+
/** task-1472: what the chart's Y axis shows (the popup's MCAP | PRICE control / `A` ask the terminal to switch). */
|
|
32
|
+
export const CHART_AXES = ['mcap', 'price'];
|
|
33
|
+
/** The most fills one chart VM carries (newest kept). */
|
|
34
|
+
export const CHART_MARKS_MAX = 500;
|
|
31
35
|
export const PROTOCOL_VERSION = 'dexterm-popup/1';
|
|
@@ -26,7 +26,7 @@ import { createHash, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
|
26
26
|
import { readFileSync, existsSync } from 'node:fs';
|
|
27
27
|
import { fileURLToPath } from 'node:url';
|
|
28
28
|
import path from 'node:path';
|
|
29
|
-
import { PROTOCOL_VERSION, CHART_INTERVALS, CHART_INDICATORS, CHART_STYLES, CHART_SCALES, WIDGET_TOPICS, WIDGET_HTML_MAX } from "./protocol.js";
|
|
29
|
+
import { PROTOCOL_VERSION, CHART_INTERVALS, CHART_INDICATORS, CHART_STYLES, CHART_SCALES, CHART_AXES, WIDGET_TOPICS, WIDGET_HTML_MAX } from "./protocol.js";
|
|
30
30
|
import { auditWidgetHtml, inlineHashes, normalizeWidgetHtml } from "./widget-html.js";
|
|
31
31
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
32
32
|
const PAGES_DIR = path.join(here, 'pages');
|
|
@@ -48,6 +48,10 @@ export const POPUP_EVENTS = new Set([
|
|
|
48
48
|
'event:popup.close-request', 'event:popup.focus', 'event:popup.drag',
|
|
49
49
|
// task-1325 chart v2 requests (payloads validated by validateEventPayload below)
|
|
50
50
|
'event:chart.interval', 'event:chart.indicator', 'event:chart.style', 'event:chart.scale', 'event:chart.painted',
|
|
51
|
+
// task-1472: the chart's Y axis (market cap ⇄ price): a display preference the terminal saves, nothing else
|
|
52
|
+
'event:chart.axis',
|
|
53
|
+
// task-1483: show / hide the chart's BUY / SELL markers (display.chartMarkers): a display preference, nothing else
|
|
54
|
+
'event:chart.markers',
|
|
51
55
|
// task-1345 agent roster: per-agent pause / kick, by agent name (the only writes this popup can send)
|
|
52
56
|
'event:roster.pause', 'event:roster.resume', 'event:roster.kick',
|
|
53
57
|
// task-1355 order plans: cancel a plan by id (the ONLY write the plans popup can send — never arm/cap/sign)
|
|
@@ -94,6 +98,10 @@ export function validateEventPayload(name, payload) {
|
|
|
94
98
|
return oneOf(CHART_STYLES, p.style) ? { style: p.style } : null;
|
|
95
99
|
case 'chart.scale':
|
|
96
100
|
return oneOf(CHART_SCALES, p.scale) ? { scale: p.scale } : null;
|
|
101
|
+
case 'chart.axis':
|
|
102
|
+
return oneOf(CHART_AXES, p.axis) ? { axis: p.axis } : null;
|
|
103
|
+
case 'chart.markers': // task-1483: show / hide the BUY / SELL markers (a display setting; nothing else)
|
|
104
|
+
return typeof p.on === 'boolean' ? { on: p.on } : null;
|
|
97
105
|
case 'chart.painted':
|
|
98
106
|
return (p.kind === 'first' || p.kind === 'data') && finiteIn(p.ms, 0, 600_000) && finiteIn(p.sentAt, 0, 1e15)
|
|
99
107
|
? { kind: p.kind, ms: p.ms, sentAt: p.sentAt } : null;
|
|
@@ -38,7 +38,7 @@ export function queryDevHistory(db, q) {
|
|
|
38
38
|
creator: q.creator, status: 'unknown', asOf, source: DEV_HISTORY_SOURCE,
|
|
39
39
|
launches: { n: 0, newestT: null, ageSec: null },
|
|
40
40
|
labelled: { n: 0, rug: 0, dead: 0, fade: 0, flat: 0, runner: 0, horizon: '72h preferred', tier: 'keyless-proxy', newestT: null, ageSec: null },
|
|
41
|
-
rugRate: null, badRate: null, devExit: { n: 0, medianMin: null, within60m: 0 }, serialRugger: false, recent: [],
|
|
41
|
+
rugRate: null, badRate: null, devExit: { n: 0, medianMin: null, within60m: 0, newestT: null, ageSec: null }, serialRugger: false, recent: [],
|
|
42
42
|
};
|
|
43
43
|
let links;
|
|
44
44
|
try {
|
|
@@ -56,6 +56,7 @@ export function queryDevHistory(db, q) {
|
|
|
56
56
|
const counts = { rug: 0, dead: 0, fade: 0, flat: 0, runner: 0 };
|
|
57
57
|
let labelledN = 0, labelledNewest = null;
|
|
58
58
|
const exits = [];
|
|
59
|
+
let exitNewest = null;
|
|
59
60
|
const launches = [];
|
|
60
61
|
for (const l of links) {
|
|
61
62
|
const firstT = Number(l.first_t);
|
|
@@ -93,6 +94,7 @@ export function queryDevHistory(db, q) {
|
|
|
93
94
|
const from = createdAt ?? Number(series[held].t);
|
|
94
95
|
devExitMin = Math.max(0, (Number(out.t) - from) / 60_000);
|
|
95
96
|
exits.push(devExitMin);
|
|
97
|
+
exitNewest = Math.max(exitNewest ?? 0, Number(out.t));
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
100
|
}
|
|
@@ -109,12 +111,14 @@ export function queryDevHistory(db, q) {
|
|
|
109
111
|
labelled: { ...empty.labelled, n: labelledN, ...counts, newestT: labelledNewest, ageSec: labelledNewest === null ? null : Math.max(0, Math.round((asOf - labelledNewest) / 1000)) },
|
|
110
112
|
rugRate: labelledN ? counts.rug / labelledN : null,
|
|
111
113
|
badRate: labelledN ? (counts.rug + counts.dead) / labelledN : null,
|
|
112
|
-
devExit: { n: exits.length, medianMin: median(exits), within60m: exits.filter((m) => m <= 60).length },
|
|
114
|
+
devExit: { n: exits.length, medianMin: median(exits), within60m: exits.filter((m) => m <= 60).length, newestT: exitNewest, ageSec: exitNewest === null ? null : Math.max(0, Math.round((asOf - exitNewest) / 1000)) },
|
|
113
115
|
serialRugger: counts.rug >= SERIAL_RUGGER_MIN,
|
|
114
116
|
recent: launches,
|
|
115
117
|
};
|
|
116
118
|
}
|
|
117
|
-
|
|
119
|
+
/** Compact age for a panel cell: `5m`, `3h`, `40d`; `age ?` when unknown. */
|
|
120
|
+
export const ageShort = (sec) => sec === null ? 'age ?' : sec < 3600 ? `${Math.max(1, Math.round(sec / 60))}m` : sec < 172800 ? `${Math.round(sec / 3600)}h` : `${Math.round(sec / 86400)}d`;
|
|
121
|
+
const ago = (sec) => sec === null ? 'age unknown' : `${ageShort(sec)} ago`;
|
|
118
122
|
/**
|
|
119
123
|
* The one-line summary every surface shows (DEV panel, rug-signal row, MCP note): counts with the sample size and
|
|
120
124
|
* the age, or `unknown` with why. Plain wording: a risk flag from observed history, never "rug confirmed" or "safe".
|
|
@@ -9,6 +9,8 @@ export * from "./open.js";
|
|
|
9
9
|
export * from "./verdicts.js";
|
|
10
10
|
export * from "./schedule.js";
|
|
11
11
|
export * from "./dev-history.js";
|
|
12
|
+
export * from "./ticks.js";
|
|
13
|
+
export * from "./retention.js";
|
|
12
14
|
export { recorderCli, RECORDER_HELP } from "./cli.js";
|
|
13
15
|
/** `--no-recorder` / `DEXTERM_RECORDER=0` resolution: the recorder is on in live mode unless either says no. */
|
|
14
16
|
export function recorderEnabled(env, flagOff) {
|