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
|
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { defaultDbPath, LINK_RUBRIC_V0, DEFAULT_LINK_RUBRIC } from '../../data/src/index.js';
|
|
4
4
|
import { exportRecorded, openHistoryReadOnly, readLarpJoin } from '../../recorder/src/index.js';
|
|
5
|
-
import { runBacktest, h1Model, larpEval, renderLarpEvalText, skillBacktest, renderSkillBacktestText, tuneLinkRubric, tuneRugRules, RUG_RULES_V0, RUG_RULES_V1, SKILL_EVAL_SCHEMA, } from '../../packs/src/index.js';
|
|
5
|
+
import { runBacktest, h1Model, larpEval, renderLarpEvalText, skillBacktest, renderSkillBacktestText, tuneLinkRubric, tuneRugRules, larpScoreBacktest, renderLarpScoreBacktestText, RUG_RULES_V0, RUG_RULES_V1, SKILL_EVAL_SCHEMA, } from '../../packs/src/index.js';
|
|
6
6
|
import { buildSkillEvalSet } from "./skill-eval-build.js";
|
|
7
7
|
/** task-1401: the committed eval set the skill backtest reads by default. */
|
|
8
8
|
export const DEFAULT_SKILL_EVAL = fileURLToPath(new URL('../../packs/eval/skills-eval.json', import.meta.url));
|
|
@@ -11,6 +11,7 @@ export const BACKTEST_HELP = `dexterm backtest: score the rug model against reco
|
|
|
11
11
|
|
|
12
12
|
dexterm backtest [--subject heuristic|pack_verdicts|larp] [--horizon SEC] [--db PATH] [--json]
|
|
13
13
|
dexterm backtest --subject skills [--eval FILE] [--tune] [--report FILE] [--json]
|
|
14
|
+
dexterm backtest --subject larp-score [--eval FILE] [--report FILE] [--json]
|
|
14
15
|
dexterm backtest --build-eval FILE [--db PATH] [--horizon SEC] [--max-lag SEC]
|
|
15
16
|
|
|
16
17
|
--subject heuristic (default, the pre-registered H1 rug model), pack_verdicts (recorded pack rug_p), or
|
|
@@ -20,6 +21,9 @@ export const BACKTEST_HELP = `dexterm backtest: score the rug model against reco
|
|
|
20
21
|
check's links-only baseline, the rug-check verdict rules), per-grade precision/recall on a train
|
|
21
22
|
and a held-out TEST split. Default eval: packages/packs/eval/skills-eval.json. --tune re-tunes on
|
|
22
23
|
the train split only and prints before (v0) vs tuned; --report writes the JSON report.
|
|
24
|
+
larp-score task-1471: the 0-100 LARP score's link-shape points fitted on the same eval set's train split,
|
|
25
|
+
with AUROC and P(bad) per band on train and the held-out TEST split. Page, domain, GitHub and
|
|
26
|
+
X-account points are pre-registered priors (not replayable on history) and are listed as such.
|
|
23
27
|
--build-eval build that eval set from a recorder DB (read-only; no network; no URLs or names written).
|
|
24
28
|
--horizon outcome horizon in seconds: ${HORIZONS.join(', ')} (default 3600 = 1h).
|
|
25
29
|
--json print the full result object instead of the human table.
|
|
@@ -98,7 +102,7 @@ export function backtestCommand(argv, io) {
|
|
|
98
102
|
io.stdout.write(BACKTEST_HELP + '\n');
|
|
99
103
|
return 0;
|
|
100
104
|
}
|
|
101
|
-
if (opts.subject === 'skills')
|
|
105
|
+
if (opts.subject === 'skills' || opts.subject === 'larp-score')
|
|
102
106
|
return skillsCommand(opts, io);
|
|
103
107
|
const path = typeof opts.db === 'string' ? opts.db : (io.env.DEXTERM_DB_PATH || defaultDbPath(io.env));
|
|
104
108
|
if (path === ':memory:') {
|
|
@@ -191,6 +195,13 @@ function skillsCommand(opts, io) {
|
|
|
191
195
|
io.stderr.write(`dexterm backtest: ${file} is not a ${SKILL_EVAL_SCHEMA} file\n`);
|
|
192
196
|
return 2;
|
|
193
197
|
}
|
|
198
|
+
if (opts.subject === 'larp-score') {
|
|
199
|
+
const r = larpScoreBacktest(set);
|
|
200
|
+
if (typeof opts.report === 'string')
|
|
201
|
+
writeFileSync(opts.report, JSON.stringify(r, null, 1) + '\n');
|
|
202
|
+
io.stdout.write(opts.json ? JSON.stringify(r, null, 2) + '\n' : renderLarpScoreBacktestText(r));
|
|
203
|
+
return 0;
|
|
204
|
+
}
|
|
194
205
|
let larpAfter = DEFAULT_LINK_RUBRIC, rugAfter = RUG_RULES_V1, tuned = null;
|
|
195
206
|
if (opts.tune) {
|
|
196
207
|
const train = set.rows.filter((r) => r.split === 'train');
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// dexterm — the price display mode (task-1366): show USD price or MARKET CAP on every screen
|
|
1
|
+
// dexterm — the price display mode (task-1366): show USD price or MARKET CAP on every screen; task-1472: the chart
|
|
2
|
+
// Y axis (both charts) is its own setting, `display.chartAxis`, default MARKET CAP, toggled with `A`.
|
|
2
3
|
//
|
|
3
4
|
// A DISPLAY mode only. Market cap = price × supply, where the supply is what the data layer already reports
|
|
4
5
|
// (the row's mcap / price at the latest tick: the "supply ratio"). Historical candles are scaled by the CURRENT
|
|
@@ -7,13 +8,16 @@
|
|
|
7
8
|
// missing / zero), the screen falls back to price and SAYS so; it never invents a number.
|
|
8
9
|
//
|
|
9
10
|
// No network calls, nothing here is read by the signer, the caps, tickets, plans or the confirm gate.
|
|
10
|
-
import { fmtMcap,
|
|
11
|
-
import { applyAndJournal, configPath, dextermHome, loadConfig, DEFAULT_PRICE_MODE, PRICE_MODES } from '../../custom/src/index.js';
|
|
12
|
-
|
|
11
|
+
import { fmtMcap, fmtCompact, fmtPrice } from '../../tui/src/index.js';
|
|
12
|
+
import { applyAndJournal, configPath, dextermHome, loadConfig, DEFAULT_PRICE_MODE, PRICE_MODES, CHART_AXES, DEFAULT_CHART_AXIS, CHART_MARKERS, DEFAULT_CHART_MARKERS } from '../../custom/src/index.js';
|
|
13
|
+
import { knownSupply, pickBasis, PRICE_BASIS_ENV } from '../../data/src/basis.js';
|
|
14
|
+
export { PRICE_MODES, DEFAULT_PRICE_MODE, CHART_AXES, DEFAULT_CHART_AXIS, CHART_MARKERS, DEFAULT_CHART_MARKERS };
|
|
13
15
|
/** Axis / caption label for an mcap chart: the history is scaled by today's supply, and says so. */
|
|
14
16
|
export const MCAP_AXIS_LABEL = 'mcap (current supply)';
|
|
15
17
|
/** Shown wherever mcap mode is on but a token's supply is unknown, so the number on screen is a price. */
|
|
16
18
|
export const MCAP_FALLBACK_NOTE = 'supply unknown · showing price';
|
|
19
|
+
/** task-1472: the chart title when the Y axis wants market cap but the token's supply is unknown (it plots price). */
|
|
20
|
+
export const MCAP_UNAVAILABLE_LABEL = 'price (mcap unavailable)';
|
|
17
21
|
/** Short per-cell marker for a price shown in an MCAP column (fallback). */
|
|
18
22
|
export const FALLBACK_MARK = 'ᵖ';
|
|
19
23
|
export function isPriceMode(v) { return PRICE_MODES.includes(v); }
|
|
@@ -78,14 +82,24 @@ export function fallbackCount(rows, get) {
|
|
|
78
82
|
export function fallbackCaption(n) {
|
|
79
83
|
return n > 0 ? `${FALLBACK_MARK} ${n} price${n > 1 ? 's' : ''} (supply unknown)` : null;
|
|
80
84
|
}
|
|
81
|
-
/**
|
|
85
|
+
/**
|
|
86
|
+
* The chart scale for a token: an mcap axis with a known supply scales by the CURRENT supply ratio (labels in the shared
|
|
87
|
+
* compact k/M/B formatter), else prices (+ `price (mcap unavailable)`). task-1472: the charts pass the chart axis
|
|
88
|
+
* (chartAxisOf, default mcap); the token header still passes the table price mode.
|
|
89
|
+
*/
|
|
82
90
|
export function chartMode(mode, price, mcap) {
|
|
83
91
|
if (mode !== 'mcap')
|
|
84
92
|
return { scale: null, axisFmt: undefined, kind: 'price', label: null };
|
|
85
93
|
const ratio = supplyRatio(price, mcap);
|
|
86
94
|
if (ratio === null)
|
|
87
|
-
return { scale: null, axisFmt: undefined, kind: 'price', label:
|
|
88
|
-
return { scale: ratio, axisFmt:
|
|
95
|
+
return { scale: null, axisFmt: undefined, kind: 'price', label: MCAP_UNAVAILABLE_LABEL };
|
|
96
|
+
return { scale: ratio, axisFmt: fmtCompact, kind: 'mcap', label: MCAP_AXIS_LABEL };
|
|
97
|
+
}
|
|
98
|
+
/** task-1472: the chart box title: `WIF · MCAP (current supply) · 1h`, `WIF/USD · 1h`, or `WIF/USD · price (mcap unavailable) · 1h`. */
|
|
99
|
+
export function chartTitle(symbol, interval, cm, quote = 'USD') {
|
|
100
|
+
if (cm.kind === 'mcap')
|
|
101
|
+
return `${symbol} · MCAP ${MCAP_AXIS_LABEL.replace(/^mcap /, '')} · ${interval}`;
|
|
102
|
+
return cm.label ? `${symbol}/${quote} · ${cm.label} · ${interval}` : `${symbol}/${quote} · ${interval}`;
|
|
89
103
|
}
|
|
90
104
|
/**
|
|
91
105
|
* One plan level with BOTH numbers, in the order the mode prefers: mcap mode `mc ≤ $300K ($0.0003)`, price mode
|
|
@@ -129,29 +143,65 @@ export function positionPriceCells(mode, supply, avgUsd, priceUsd, avgText, pric
|
|
|
129
143
|
const mark = mode === 'mcap' ? FALLBACK_MARK : '';
|
|
130
144
|
return { avg: { label: 'AVG ENTRY', value: avgText === '—' ? avgText : avgText + mark }, price: { label: 'PRICE', value: priceText === '—' ? priceText : priceText + mark } };
|
|
131
145
|
}
|
|
132
|
-
/**
|
|
146
|
+
/**
|
|
147
|
+
* task-1537: the known supply for a coin the app is showing: the open token view's (mcap ÷ price at its latest tick),
|
|
148
|
+
* else its screener row's, else pump.fun's fixed 1B (the PnL card's rule, @dexterm/data/basis knownSupply). Never
|
|
149
|
+
* guessed: null means the caller shows the price and marks it.
|
|
150
|
+
*/
|
|
151
|
+
export function supplyForMint(state, mint) {
|
|
152
|
+
if (!mint)
|
|
153
|
+
return null;
|
|
154
|
+
const v = state.live?.token?.view;
|
|
155
|
+
if (v && v.mint === mint) {
|
|
156
|
+
const r = supplyRatio(v.price, v.mcap);
|
|
157
|
+
if (r !== null)
|
|
158
|
+
return r;
|
|
159
|
+
}
|
|
160
|
+
const row = state.screener?.rows.find((x) => x.mint === mint);
|
|
161
|
+
if (row) {
|
|
162
|
+
const r = supplyRatio(row.price, row.mcap);
|
|
163
|
+
if (r !== null)
|
|
164
|
+
return r;
|
|
165
|
+
}
|
|
166
|
+
return knownSupply({ mint, launchpad: row?.launchpad ?? (v && v.mint === mint ? v.launchpad : null) })?.tokens ?? null;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* task-1537: one more price LEVEL in a row (a stop, a target, a fill, a tape trade): its market cap at the given supply
|
|
170
|
+
* in mcap mode, else the price (marked ᵖ when mcap mode had no supply). Display only.
|
|
171
|
+
*/
|
|
172
|
+
export function levelCell(mode, supply, usd) {
|
|
173
|
+
if (usd === null || usd === undefined || !Number.isFinite(usd))
|
|
174
|
+
return '—';
|
|
175
|
+
if (mode === 'mcap' && supply != null && supply > 0)
|
|
176
|
+
return fmtMcap(usd * supply);
|
|
177
|
+
return fmtPrice(usd) + (mode === 'mcap' ? FALLBACK_MARK : '');
|
|
178
|
+
}
|
|
179
|
+
/** The mode in effect: the state's (set from config, a workspace, `$` or a one-run override), default MARKET CAP (task-1537). */
|
|
133
180
|
export function priceModeOf(state) {
|
|
134
|
-
return state?.priceMode === '
|
|
181
|
+
return state?.priceMode === 'price' ? 'price' : 'mcap';
|
|
135
182
|
}
|
|
136
|
-
/**
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
183
|
+
/**
|
|
184
|
+
* The mode a run starts in: the one-run override (`DEXTERM_PRICE_BASIS=price|mcap`, which `--price` / `--mcap` /
|
|
185
|
+
* `--price-mode` also set), else config.display.priceMode, else market cap (task-1537: @dexterm/data/basis pickBasis).
|
|
186
|
+
*/
|
|
187
|
+
export function configPriceMode(cfg, env) {
|
|
188
|
+
return pickBasis(cfg?.display?.priceMode, env);
|
|
140
189
|
}
|
|
141
190
|
/**
|
|
142
|
-
*
|
|
143
|
-
*
|
|
191
|
+
* `$` (and `/display mcap|price` in the chat box, task-1537): set the mode (`next` absent = flip) and persist it to
|
|
192
|
+
* config.display.priceMode through the journal (actor user, so `undo` works). Returns the notice for the toast.
|
|
193
|
+
* Persistence failure keeps the new mode for this run and says why.
|
|
144
194
|
*/
|
|
145
|
-
export function
|
|
146
|
-
const
|
|
147
|
-
state.priceMode =
|
|
148
|
-
const what =
|
|
195
|
+
export function setPriceMode(state, next, why = '$') {
|
|
196
|
+
const mode = next ?? (priceModeOf(state) === 'mcap' ? 'price' : 'mcap');
|
|
197
|
+
state.priceMode = mode;
|
|
198
|
+
const what = mode === 'mcap' ? 'showing MARKET CAP' : 'showing USD PRICE'; // task-1472: the charts follow A, not $
|
|
149
199
|
const ui = state.custom;
|
|
150
200
|
if (!ui)
|
|
151
201
|
return `${what} (not saved: no config on this run)`;
|
|
152
202
|
try {
|
|
153
|
-
const op = ui.config.display ? { op: 'add', path: '/display/priceMode', value:
|
|
154
|
-
const { config } = applyAndJournal(ui.home, [op], { actor: 'user', why: `$ price mode ${
|
|
203
|
+
const op = ui.config.display ? { op: 'add', path: '/display/priceMode', value: mode } : { op: 'add', path: '/display', value: { priceMode: mode } };
|
|
204
|
+
const { config } = applyAndJournal(ui.home, [op], { actor: 'user', why: `${why} price mode ${mode}`, now: state.now.getTime() });
|
|
155
205
|
ui.config = config;
|
|
156
206
|
return `${what} · saved ($ to switch back)`;
|
|
157
207
|
}
|
|
@@ -159,7 +209,112 @@ export function togglePriceMode(state) {
|
|
|
159
209
|
return `${what} (not saved: ${e.message})`;
|
|
160
210
|
}
|
|
161
211
|
}
|
|
162
|
-
|
|
212
|
+
/** `$`: flip the mode and persist it (see setPriceMode). */
|
|
213
|
+
export function togglePriceMode(state) { return setPriceMode(state); }
|
|
214
|
+
/**
|
|
215
|
+
* task-1537: the chat box command for the price basis, never sent to a model: `/display` (show), `/display mcap|price`,
|
|
216
|
+
* `/basis mcap|price`, `/set basis mcap|price` (also `/set priceMode …`). null = not this command.
|
|
217
|
+
*/
|
|
218
|
+
export function parseDisplayCommand(q) {
|
|
219
|
+
const w = q.trim().replace(/^\//, '').split(/\s+/).filter(Boolean).map((x) => x.toLowerCase());
|
|
220
|
+
let arg;
|
|
221
|
+
if (w[0] === 'display' || w[0] === 'basis') {
|
|
222
|
+
if (w[1] === 'markers')
|
|
223
|
+
return null;
|
|
224
|
+
arg = w[1];
|
|
225
|
+
}
|
|
226
|
+
else if (w[0] === 'set' && (w[1] === 'basis' || w[1] === 'pricemode' || w[1] === 'price-basis' || w[1] === 'display.pricemode'))
|
|
227
|
+
arg = w[2];
|
|
228
|
+
else
|
|
229
|
+
return null;
|
|
230
|
+
if (arg === undefined)
|
|
231
|
+
return { show: true };
|
|
232
|
+
return isPriceMode(arg) ? { mode: arg } : { error: `/display expects mcap or price, got ${JSON.stringify(arg.slice(0, 20))}` };
|
|
233
|
+
}
|
|
234
|
+
/** The toast for `/display` with no argument. */
|
|
235
|
+
export function priceModeNotice(state) {
|
|
236
|
+
return priceModeOf(state) === 'mcap'
|
|
237
|
+
? 'price basis: MARKET CAP (default) · coins with no known supply show price ᵖ · /display price or $ to switch'
|
|
238
|
+
: 'price basis: USD PRICE · /display mcap or $ to switch back to market cap';
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* task-1537: the one-run basis flags, accepted before any subcommand (`dexterm --price positions`, `dexterm autotrade
|
|
242
|
+
* list --mcap`): `--price` / `--mcap` are removed from argv and set DEXTERM_PRICE_BASIS in `env` for this process (so
|
|
243
|
+
* child agents and every CLI text follow it); nothing is saved. Returns argv without them.
|
|
244
|
+
*/
|
|
245
|
+
export function takeBasisFlags(argv, env) {
|
|
246
|
+
const out = [];
|
|
247
|
+
for (const a of argv) {
|
|
248
|
+
if (a === '--price' || a === '--mcap')
|
|
249
|
+
env[PRICE_BASIS_ENV] = a.slice(2);
|
|
250
|
+
else
|
|
251
|
+
out.push(a);
|
|
252
|
+
}
|
|
253
|
+
return out;
|
|
254
|
+
}
|
|
255
|
+
export function isChartAxis(v) { return CHART_AXES.includes(v); }
|
|
256
|
+
/** task-1472: the chart Y axis in effect: the state's (from config or `A`), default MARKET CAP. */
|
|
257
|
+
export function chartAxisOf(state) {
|
|
258
|
+
return state?.chartAxis === 'price' ? 'price' : 'mcap';
|
|
259
|
+
}
|
|
260
|
+
/** task-1472: the chart axis a run starts with: config.display.chartAxis, else mcap (also for configs written before it). */
|
|
261
|
+
export function configChartAxis(cfg) {
|
|
262
|
+
const a = cfg?.display?.chartAxis;
|
|
263
|
+
return isChartAxis(a) ? a : DEFAULT_CHART_AXIS;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* task-1472: set the chart Y axis (both chart surfaces) and persist it to config.display.chartAxis through the journal
|
|
267
|
+
* (actor user, so `undo` works). `next` absent = flip. Returns the toast text; a save failure keeps it for this run.
|
|
268
|
+
*/
|
|
269
|
+
export function setChartAxis(state, next) {
|
|
270
|
+
const axis = next ?? (chartAxisOf(state) === 'mcap' ? 'price' : 'mcap');
|
|
271
|
+
state.chartAxis = axis;
|
|
272
|
+
const what = axis === 'mcap' ? 'chart Y axis: MARKET CAP' : 'chart Y axis: PRICE';
|
|
273
|
+
const ui = state.custom;
|
|
274
|
+
if (!ui)
|
|
275
|
+
return `${what} (not saved: no config on this run)`;
|
|
276
|
+
try {
|
|
277
|
+
const op = ui.config.display ? { op: 'add', path: '/display/chartAxis', value: axis } : { op: 'add', path: '/display', value: { chartAxis: axis } };
|
|
278
|
+
const { config } = applyAndJournal(ui.home, [op], { actor: 'user', why: `A chart axis ${axis}`, now: state.now.getTime() });
|
|
279
|
+
ui.config = config;
|
|
280
|
+
return `${what} · saved (A to switch)`;
|
|
281
|
+
}
|
|
282
|
+
catch (e) {
|
|
283
|
+
return `${what} (not saved: ${e.message})`;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
export function isChartMarkers(v) { return CHART_MARKERS.includes(v); }
|
|
287
|
+
/** task-1483: are the BUY / SELL markers on (both charts)? Default on; only an explicit 'off' hides them. */
|
|
288
|
+
export function chartMarkersOn(state) {
|
|
289
|
+
return state?.chartMarkers !== 'off';
|
|
290
|
+
}
|
|
291
|
+
/** task-1483: the markers setting a run starts with: config.display.chartMarkers, else on. */
|
|
292
|
+
export function configChartMarkers(cfg) {
|
|
293
|
+
const m = cfg?.display?.chartMarkers;
|
|
294
|
+
return isChartMarkers(m) ? m : DEFAULT_CHART_MARKERS;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* task-1483: show / hide the chart BUY / SELL markers (both chart surfaces) and persist config.display.chartMarkers through
|
|
298
|
+
* the journal (actor user, so `undo` works). `next` absent = flip. Returns the toast text. Display only.
|
|
299
|
+
*/
|
|
300
|
+
export function setChartMarkers(state, next) {
|
|
301
|
+
const v = next ?? (chartMarkersOn(state) ? 'off' : 'on');
|
|
302
|
+
state.chartMarkers = v;
|
|
303
|
+
const what = v === 'on' ? 'chart BUY/SELL markers: ON' : 'chart BUY/SELL markers: OFF';
|
|
304
|
+
const ui = state.custom;
|
|
305
|
+
if (!ui)
|
|
306
|
+
return `${what} (not saved: no config on this run)`;
|
|
307
|
+
try {
|
|
308
|
+
const op = ui.config.display ? { op: 'add', path: '/display/chartMarkers', value: v } : { op: 'add', path: '/display', value: { chartMarkers: v } };
|
|
309
|
+
const { config } = applyAndJournal(ui.home, [op], { actor: 'user', why: `chart markers ${v}`, now: state.now.getTime() });
|
|
310
|
+
ui.config = config;
|
|
311
|
+
return `${what} · saved`;
|
|
312
|
+
}
|
|
313
|
+
catch (e) {
|
|
314
|
+
return `${what} (not saved: ${e.message})`;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
export const DISPLAY_USAGE = 'usage: dexterm display [price|mcap] show or set display.priceMode in ~/.dexterm/config.json ($ in the app toggles it)\n dexterm display markers [on|off] show or set display.chartMarkers (BUY/SELL markers on both charts)';
|
|
163
318
|
/** `dexterm display [price|mcap]`: print the saved price display mode, or set it (journaled, actor user). No network. */
|
|
164
319
|
export function displayCommand(argv, io) {
|
|
165
320
|
const home = dextermHome(io.env);
|
|
@@ -171,7 +326,37 @@ export function displayCommand(argv, io) {
|
|
|
171
326
|
return 1;
|
|
172
327
|
}
|
|
173
328
|
const m = configPriceMode(loaded.config);
|
|
174
|
-
io.stdout.write(`display.priceMode = ${m}${m === 'mcap' ?
|
|
329
|
+
io.stdout.write(`display.priceMode = ${m}${m === 'mcap' ? ' (tables show MCAP; tokens without a supply fall back to price)' : ' (USD price per token)'}\n`);
|
|
330
|
+
const a = configChartAxis(loaded.config);
|
|
331
|
+
io.stdout.write(`display.chartAxis = ${a}${a === 'mcap' ? ` (charts: ${MCAP_AXIS_LABEL}; A switches)` : ' (charts plot USD price; A switches)'}\n`);
|
|
332
|
+
const mk = configChartMarkers(loaded.config);
|
|
333
|
+
io.stdout.write(`display.chartMarkers = ${mk}${mk === 'on' ? ' (charts mark your paper and live fills; dexterm display markers off hides them)' : ' (no fill markers on the charts)'}\n`);
|
|
334
|
+
return 0;
|
|
335
|
+
}
|
|
336
|
+
// task-1483: `dexterm display markers [on|off]`
|
|
337
|
+
if (arg === 'markers') {
|
|
338
|
+
const v = argv[1];
|
|
339
|
+
if (v === undefined) {
|
|
340
|
+
if (!loaded.ok) {
|
|
341
|
+
io.stderr.write(`dexterm display: ${loaded.errors[0]}\n`);
|
|
342
|
+
return 1;
|
|
343
|
+
}
|
|
344
|
+
io.stdout.write(`display.chartMarkers = ${configChartMarkers(loaded.config)}\n`);
|
|
345
|
+
return 0;
|
|
346
|
+
}
|
|
347
|
+
if (!isChartMarkers(v)) {
|
|
348
|
+
io.stderr.write(`dexterm display markers: expected on or off, got ${JSON.stringify(v.slice(0, 20))}\n${DISPLAY_USAGE}\n`);
|
|
349
|
+
return 2;
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
352
|
+
const op = loaded.config.display ? { op: 'add', path: '/display/chartMarkers', value: v } : { op: 'add', path: '/display', value: { chartMarkers: v } };
|
|
353
|
+
applyAndJournal(home, [op], { actor: 'user', why: `dexterm display markers ${v}` });
|
|
354
|
+
}
|
|
355
|
+
catch (e) {
|
|
356
|
+
io.stderr.write(`dexterm display: ${e.message}\n`);
|
|
357
|
+
return 1;
|
|
358
|
+
}
|
|
359
|
+
io.stdout.write(`display.chartMarkers = ${v} (saved to ${configPath(home)})\n`);
|
|
175
360
|
return 0;
|
|
176
361
|
}
|
|
177
362
|
if (!isPriceMode(arg)) {
|
|
@@ -18,6 +18,7 @@ import { SayTts, voiceDoctor, resolveVoice, WHISPER_MODEL, resolvePiperRuntime,
|
|
|
18
18
|
import { loadConfig, dextermHome } from '../../custom/src/index.js';
|
|
19
19
|
import { kbStore, skillStore } from "./kb-skill-cmd.js";
|
|
20
20
|
import { analystCliOnPath, CODEX_MIN_VERSION, parseEngineChoice, resolveEngine, versionAtLeast } from "./analyst/codex.js";
|
|
21
|
+
import { OllamaClient, SUGGESTED_MODELS, SURFACES, belowBar, effectiveRestriction, engineChoiceFor, loadAiConfig, ollamaSettings, pickModel, probeModel, remoteHostWarning } from '../../mcp/src/engine/index.js';
|
|
21
22
|
/** The minimum Node that runs dexterm (type-stripping of the .ts entry needs 22.18). */
|
|
22
23
|
export const MIN_NODE = [22, 18, 0];
|
|
23
24
|
/** Cheap PATH lookup (no spawn). Windows (task-1423): PATH is `;`-separated and commands carry an extension
|
|
@@ -142,6 +143,18 @@ export async function claudeProbe(timeoutMs = 4000, platform = process.platform,
|
|
|
142
143
|
}
|
|
143
144
|
});
|
|
144
145
|
}
|
|
146
|
+
/** Default Ollama facts: ai.json + a short probe of the configured host (127.0.0.1 by default). Never throws. */
|
|
147
|
+
export async function ollamaFacts(env = process.env) {
|
|
148
|
+
const c = loadAiConfig(env).config;
|
|
149
|
+
const set = ollamaSettings(c, env);
|
|
150
|
+
const client = new OllamaClient({ host: set.host, metaTimeoutMs: 2500 });
|
|
151
|
+
const probe = await probeModel(client, set.model, { numCtx: set.numCtx });
|
|
152
|
+
if (!probe.model && probe.models.length)
|
|
153
|
+
probe.model = null;
|
|
154
|
+
const surfaces = SURFACES.filter((sf) => engineChoiceFor(sf, c, env) === 'ollama');
|
|
155
|
+
const eff = effectiveRestriction(c, set.model ?? pickModel(probe.models), env);
|
|
156
|
+
return { probe, setUp: !!set.model || surfaces.length > 0, surfaces, level: eff.level, note: eff.note, hostWarning: remoteHostWarning(set.host) };
|
|
157
|
+
}
|
|
145
158
|
/**
|
|
146
159
|
* Default codex probe (0.1.5): PATH (spawnable form only), then `codex --version` and `codex login status`. The
|
|
147
160
|
* status command is the user's own CLI reporting on its own login; dexterm never reads the credential itself.
|
|
@@ -190,6 +203,7 @@ export function defaultDeps(env = process.env, isTTY = process.stdout.isTTY ===
|
|
|
190
203
|
platform: process.platform,
|
|
191
204
|
claude: () => claudeProbe(),
|
|
192
205
|
codex: () => codexProbe(4000, env),
|
|
206
|
+
ollama: () => ollamaFacts(env),
|
|
193
207
|
analystEngine: env.DEXTERM_ANALYST_ENGINE ?? loadConfig(dextermHome(env)).config.analyst?.engine ?? null,
|
|
194
208
|
probe: (url) => livingProbe(url),
|
|
195
209
|
checkWritable: writableProbe,
|
|
@@ -262,7 +276,16 @@ export async function runDoctor(deps) {
|
|
|
262
276
|
// 0.1.5: codex is the optional second engine; a missing claude is fine when codex can run the analyst.
|
|
263
277
|
const codex = deps.codex ? await deps.codex() : null;
|
|
264
278
|
const codexUsable = codex?.state === 'present';
|
|
265
|
-
|
|
279
|
+
// task-1543: a reachable Ollama with a pulled model can run the analyst too (a free local engine).
|
|
280
|
+
const ol = deps.ollama ? await deps.ollama().catch(() => null) : null;
|
|
281
|
+
const ollamaUsable = !!ol && ol.probe.reachable && (ol.probe.model ? ol.probe.present : ol.probe.models.length > 0);
|
|
282
|
+
if (claude === 'missing' && !codexUsable && ollamaUsable) {
|
|
283
|
+
checks.push({
|
|
284
|
+
name: 'Claude CLI', status: 'pass',
|
|
285
|
+
detail: 'not found on PATH (optional now): the analyst runs on your local Ollama model instead',
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
else if (claude === 'missing' && codexUsable) {
|
|
266
289
|
checks.push({
|
|
267
290
|
name: 'Claude CLI', status: 'pass',
|
|
268
291
|
detail: 'not found on PATH (optional now): the analyst runs on your codex CLI instead',
|
|
@@ -272,7 +295,7 @@ export async function runDoctor(deps) {
|
|
|
272
295
|
checks.push({
|
|
273
296
|
name: 'Claude CLI', status: 'warn',
|
|
274
297
|
detail: 'not found on PATH; the analyst (a) is disabled, the rest of dexterm works',
|
|
275
|
-
fix: '
|
|
298
|
+
fix: 'Set up an AI backend: install Claude Code (https://claude.com/claude-code) and run `claude` once to log in, or Codex (`npm i -g @openai/codex && codex login`), or a free local model (install Ollama from https://ollama.com/download, `ollama pull qwen3:8b`, `dexterm ai engine ollama`).',
|
|
276
299
|
});
|
|
277
300
|
}
|
|
278
301
|
else {
|
|
@@ -284,7 +307,7 @@ export async function runDoctor(deps) {
|
|
|
284
307
|
// 3b. Codex CLI (0.1.5): optional second analyst engine, the user's own codex login. Read-only lock needs >= CODEX_MIN_VERSION.
|
|
285
308
|
if (codex) {
|
|
286
309
|
const choice = parseEngineChoice(deps.analystEngine) ?? 'auto';
|
|
287
|
-
const engine = resolveEngine(choice, (b) => b === 'claude' ? claude !== 'missing' : codexUsable);
|
|
310
|
+
const engine = resolveEngine(choice, (b) => b === 'claude' ? claude !== 'missing' : b === 'codex' ? codexUsable : ollamaUsable && !!ol?.setUp);
|
|
288
311
|
const eng = `analyst engine: ${engine}${choice === 'auto' ? ' (auto)' : ''}`;
|
|
289
312
|
if (codex.state === 'missing') {
|
|
290
313
|
checks.push({ name: 'Codex CLI', status: engine === 'codex' ? 'warn' : 'pass', detail: `not installed (optional second analyst engine) · ${eng}`, ...(engine === 'codex' ? { fix: 'npm i -g @openai/codex && codex login, or set analyst.engine to claude' } : {}) });
|
|
@@ -299,6 +322,9 @@ export async function runDoctor(deps) {
|
|
|
299
322
|
checks.push({ name: 'Codex CLI', status: 'pass', detail: `found${codex.version ? ` (codex-cli ${codex.version})` : ''}${codex.loggedIn ? ', logged in' : ''}; runs the analyst read-only on your own codex login (/engine codex) · ${eng}` });
|
|
300
323
|
}
|
|
301
324
|
}
|
|
325
|
+
// 3c. Local engine (task-1543): the user's own Ollama on this machine, the model, tool calling, context, profile.
|
|
326
|
+
if (ol)
|
|
327
|
+
checks.push(ollamaCheck(ol, claude !== 'missing' || codexUsable));
|
|
302
328
|
// 4b. Login with X (optional, task-1357): the user's own X app + login unlock X posts in the SOCIAL panel / TRENDING.
|
|
303
329
|
{
|
|
304
330
|
const xs = new XTokenStore({ env: deps.env });
|
|
@@ -445,3 +471,36 @@ export function renderDoctor(result, opts = {}) {
|
|
|
445
471
|
lines.push(paint(`${fails} check${fails === 1 ? '' : 's'} failed — fix the ✗ lines above, then re-run \`dexterm doctor\`.`, color ? ANSI.fail : ''));
|
|
446
472
|
return lines.join('\n');
|
|
447
473
|
}
|
|
474
|
+
/**
|
|
475
|
+
* The Ollama line (task-1543). Optional while claude/codex can run the analyst; a warning with the 2-minute
|
|
476
|
+
* setup when nothing can, or when the user chose ollama and it is not ready.
|
|
477
|
+
*/
|
|
478
|
+
export function ollamaCheck(o, otherEngine) {
|
|
479
|
+
const p = o.probe;
|
|
480
|
+
const pull = `ollama pull ${SUGGESTED_MODELS[0].name}`;
|
|
481
|
+
const setup = `Install Ollama (https://ollama.com/download) and open it, then \`${pull}\` and \`dexterm ai engine ollama\` (\`dexterm ai model ${SUGGESTED_MODELS[0].name}\`).`;
|
|
482
|
+
const used = o.surfaces.length ? ` · runs: ${o.surfaces.join(', ')}` : '';
|
|
483
|
+
const prof = ` · profile ${o.level}${o.note ? ` (${o.note})` : ''}`;
|
|
484
|
+
const remote = o.hostWarning ? ` · WARNING ${o.hostWarning}` : '';
|
|
485
|
+
if (!p.reachable) {
|
|
486
|
+
// task-1551: a redirect is refused before anything is sent on; say so, whatever the setup state.
|
|
487
|
+
if (p.redirect)
|
|
488
|
+
return { name: 'Ollama (local AI)', status: 'warn', detail: `${p.host} answered with a redirect: refused, nothing was sent on${used}${remote}`, fix: 'dexterm never follows a redirect for the local engine (it would send your prompt to another host). Point it at the Ollama server itself with `dexterm ai host <host:port>` (or DEXTERM_OLLAMA_HOST), then re-run `dexterm doctor`.' };
|
|
489
|
+
if (!o.setUp)
|
|
490
|
+
return otherEngine
|
|
491
|
+
? { name: 'Ollama (local AI)', status: 'pass', detail: 'not set up (optional free local engine; no login, no key, nothing leaves this machine)' }
|
|
492
|
+
: { name: 'Ollama (local AI)', status: 'warn', detail: 'no AI engine on this machine yet: a free local model works without any login or key', fix: setup };
|
|
493
|
+
return { name: 'Ollama (local AI)', status: 'warn', detail: `not reachable at ${p.host}${used}${remote}`, fix: `Start Ollama (open the app, or run \`ollama serve\`), then re-run \`dexterm doctor\`. Not installed? ${setup}` };
|
|
494
|
+
}
|
|
495
|
+
if (!p.model) {
|
|
496
|
+
const pick = pickModel(p.models);
|
|
497
|
+
return { name: 'Ollama (local AI)', status: o.setUp || !otherEngine ? 'warn' : 'pass', detail: `Ollama ${p.version ?? ''} running · pulled: ${p.models.slice(0, 5).join(', ') || 'none'} · no model chosen${used}${remote}`, ...(o.setUp || !otherEngine ? { fix: pick ? `dexterm ai model ${pick}` : `${pull} && dexterm ai model ${SUGGESTED_MODELS[0].name}` } : {}) };
|
|
498
|
+
}
|
|
499
|
+
if (!p.present)
|
|
500
|
+
return { name: 'Ollama (local AI)', status: 'warn', detail: `${p.model} is not pulled on ${p.host}${used}${remote}`, fix: `ollama pull ${p.model}` };
|
|
501
|
+
const warns = belowBar(o.level, p);
|
|
502
|
+
const facts = `${p.model} · tools ${p.tools === null ? '?' : p.tools ? 'yes' : 'no'} · context ${p.contextLength ?? '?'}`;
|
|
503
|
+
if (warns.length || o.hostWarning)
|
|
504
|
+
return { name: 'Ollama (local AI)', status: 'warn', detail: `${facts}${used}${prof}${remote}${warns.length ? ` · ${warns[0]}` : ''}`, fix: warns.length ? `\`dexterm ai probe --json\` checks it in detail; pull a stronger tool-capable model (e.g. ${pull}) or lower the profile (\`dexterm ai restrictions observe\`).` : 'Point dexterm at this machine: dexterm ai host 127.0.0.1' };
|
|
505
|
+
return { name: 'Ollama (local AI)', status: 'pass', detail: `${facts} · ${p.local ? 'local' : 'remote'} · $0${used}${prof}` };
|
|
506
|
+
}
|
|
@@ -12,6 +12,7 @@ import { mkdirSync, writeFileSync } from 'node:fs';
|
|
|
12
12
|
import { join } from 'node:path';
|
|
13
13
|
import { Canvas, rasterizeCanvas, fmtUsd, fmtPrice, fmtPct } from '../../tui/src/index.js';
|
|
14
14
|
import { encodePng } from '../../data/src/index.js';
|
|
15
|
+
import { priceModeOf } from "./display.js";
|
|
15
16
|
import { dextermHome } from "./boot-state.js";
|
|
16
17
|
import { cleanText } from "./screener/rows.js";
|
|
17
18
|
import { rugP, fmtRugP, RUG_MODEL_LABEL } from "./screener/rug.js";
|
|
@@ -152,8 +153,15 @@ const yesNo = (b) => (b === null ? 'unknown' : b ? 'ENABLED' : 'revoked');
|
|
|
152
153
|
export function tokenReport(state, v, now) {
|
|
153
154
|
const L = [];
|
|
154
155
|
L.push(`coin $${cleanText(v.symbol, 16)}${v.name ? ` · ${cleanText(v.name, 40)}` : ''} · ${v.launchpad}`);
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
const moves = `5m ${fmtPct(v.chg.m5)} 1h ${fmtPct(v.chg.h1)} 6h ${fmtPct(v.chg.h6)} 24h ${fmtPct(v.chg.h24)}`;
|
|
157
|
+
if (priceModeOf(state) === 'mcap' && v.mcap !== null) { // task-1537: the market cap leads by default; both numbers stay
|
|
158
|
+
L.push(`market cap ${fmtUsd(v.mcap)}${v.mcapFlagged ? ' (flagged)' : ''} price ${fmtPrice(v.price)} ${moves}`);
|
|
159
|
+
L.push(`liquidity ${fmtUsd(v.liq)} vol 24h ${fmtUsd(v.vol24)}`);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
L.push(`price ${fmtPrice(v.price)} ${moves}`);
|
|
163
|
+
L.push(`market cap ${fmtUsd(v.mcap)}${v.mcapFlagged ? ' (flagged)' : ''} liquidity ${fmtUsd(v.liq)} vol 24h ${fmtUsd(v.vol24)}`);
|
|
164
|
+
}
|
|
157
165
|
L.push(`holders ${v.holders ?? '—'} top-10 ${v.top10 === null ? '—' : `${v.top10.toFixed(1)}%`} dev ${v.dev === null ? '—' : `${v.dev.toFixed(1)}%`}${v.holdersSample ? ` (${v.holdersSample})` : ''}`);
|
|
158
166
|
L.push(`age ${v.ageMin === null ? '—' : fmtAge(v.ageMin * 60)}`);
|
|
159
167
|
L.push(`authorities mint ${yesNo(v.mintAuth)} · freeze ${yesNo(v.freezeAuth)}${v.riskyExtensions.length ? ` · risky extensions: ${v.riskyExtensions.join(', ')}` : ''}`);
|
|
@@ -19,7 +19,7 @@ export { renderAnalyst, renderContextRail, renderCoinList } from "./screens/anal
|
|
|
19
19
|
export { renderTicket } from "./screens/ticket.js";
|
|
20
20
|
export { renderPositions } from "./screens/positions.js";
|
|
21
21
|
export * from "./trade.js";
|
|
22
|
-
export { TradeTicketLive, PositionsLive,
|
|
22
|
+
export { TradeTicketLive, PositionsLive, POSITIONS_REFRESH_MS } from "./live/trade.js";
|
|
23
23
|
export { parseWalletCommand, WALLET_HELP } from "./wallet-command.js";
|
|
24
24
|
export * from "./screener/filter.js";
|
|
25
25
|
export * from "./screener/sort.js";
|