dexterm-cli 0.1.3 → 0.1.5
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/cli/assets/claude/analyst-system.md +2 -1
- package/dist/packages/cli/src/agent-paper.js +60 -0
- package/dist/packages/cli/src/analyst/backend.js +183 -0
- package/dist/packages/cli/src/analyst/codex.js +301 -0
- package/dist/packages/cli/src/analyst/session.js +9 -2
- package/dist/packages/cli/src/app-help-gen.js +18 -9
- package/dist/packages/cli/src/docs-kb-gen.js +228 -0
- package/dist/packages/cli/src/doctor.js +80 -9
- package/dist/packages/cli/src/index.js +1 -1
- package/dist/packages/cli/src/kb-skill-cmd.js +3 -0
- package/dist/packages/cli/src/larp-detected.js +209 -0
- package/dist/packages/cli/src/live/dev-history.js +99 -0
- package/dist/packages/cli/src/live/newpairs.js +12 -0
- package/dist/packages/cli/src/live/screens/token-live.js +11 -1
- package/dist/packages/cli/src/live/token.js +39 -1
- package/dist/packages/cli/src/main.js +260 -7
- package/dist/packages/cli/src/mcp-follow.js +255 -0
- package/dist/packages/cli/src/record-cmd.js +2 -0
- package/dist/packages/cli/src/rules.js +25 -2
- package/dist/packages/cli/src/screens/analyst-session.js +5 -3
- package/dist/packages/cli/src/screens/analyst.js +4 -3
- package/dist/packages/cli/src/spectate-cmd.js +14 -3
- package/dist/packages/cli/src/version.js +1 -1
- package/dist/packages/cli/src/x-cmd.js +11 -5
- package/dist/packages/custom/src/rules.js +2 -2
- package/dist/packages/custom/src/schema.js +5 -1
- package/dist/packages/data/src/fixtures.js +28 -6
- package/dist/packages/data/src/index.js +3 -0
- package/dist/packages/data/src/sources/jupiter.js +1 -0
- package/dist/packages/data/src/trade/agent/paper-desk.js +336 -0
- package/dist/packages/data/src/trade/agent/rendezvous.js +161 -0
- package/dist/packages/mcp/assets/kb/app-help/agent-paper-trade.md +38 -0
- package/dist/packages/mcp/assets/kb/app-help/ask-the-analyst.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/connect-an-agent.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/dev-history.md +32 -0
- package/dist/packages/mcp/assets/kb/app-help/paper-trade.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/screen-positions.md +4 -1
- package/dist/packages/mcp/assets/kb/app-help/screen-token.md +1 -0
- package/dist/packages/mcp/assets/kb/app-help/spectate-an-agent.md +4 -1
- package/dist/packages/mcp/assets/kb/app-help/use-codex-analyst.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-agent-paper-trading.md +50 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-capability-tiers-enforced-server-side.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-directory-metadata-prepared-not-submitted.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-install-in-one-command.md +51 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-per-agent-mandates.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-recipes.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-red-team-coverage.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-two-ways-to-connect.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-untrusted-by-default.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-watch-an-agent-work-spectator-view.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-answer-style.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-if-claude-is-missing.md +25 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-it-knows-the-app.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-mcp-tools.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-plain-language-filters.md +25 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-skills.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-starting-a-run.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-use-codex-instead-of-claude.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-can-change-three-tiers.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-sees.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-the-analyst-can-never-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst.md +23 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-1-start-dexterm.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-2-open-a-real-coin-by-contract-address.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-3-read-the-safety-panel.md +40 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-4-read-the-holder-panel.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-5-optionally-ask-the-analyst.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-6-export-or-share-what-you-see.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-7-quit-safely.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-before-any-experimental-trading.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-check-the-installation-with-doctor.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-choose-a-setup-path.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-common-mistakes-and-recovery.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-copy-and-paste-without-surprises.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-if-data-says-unavailable-stale-or-rate-limited.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-if-dexterm-says-command-not-found.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-if-optional-help-is-unavailable.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-if-paste-does-nothing-or-pastes-twice.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-if-the-screen-looks-broken.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-if-you-typed-the-wrong-thing.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-install-node-js-first.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-linux.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-macos-homebrew.md +46 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-macos-or-linux-npm.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-macos.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-open-the-terminal.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-reopen-dexterm-later.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-ten-minute-first-win.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-terminal-shell-prompt-command-output-and-path.md +40 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-where-to-go-next.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-windows-expectations.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-windows-powershell-experimental.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-windows.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-cli-dexterm-help.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-cli-filter-grammar.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-cli-flags.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-cli-invocations.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-cli-presets.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-cli-scan-commands.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-cli-sort-keys.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-cli-subcommands.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-cli.md +25 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-environment-variables.md +47 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-files-on-disk.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-headless-recorder-dexterm-record.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-history-recorder.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-packs.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-price-display-mode.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-push-alerts-and-dexterm-watch.md +45 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-rules-engine.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-the-analyst-s-launch.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-the-optional-free-rpc-key.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-themes-and-keymaps.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-themes-and-look.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-widgets.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-workspaces.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration.md +25 -0
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-1-follow-a-wallet-see-what-it-does.md +51 -0
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-2-the-one-key-mirror-ticket-a-proposal.md +56 -0
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-3-capped-auto-mirror-default-off-less.md +47 -0
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-what-is-proven-what-is-not.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-cache.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-health-registry.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-rate-limits-and-pacing.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-request-budget-meter.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-sources.md +47 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-the-helius-credit-meter.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-dexterm-doctor.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-first-run.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-install.md +81 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-next.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-requirements.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-running-the-tests.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-supported-platforms.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-updating.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-keyboard-global-keys.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-keyboard-keys-handled-by-the-loop.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-keyboard-per-screen-keys.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-keyboard-what-shows.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-keyboard.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp-measured-accuracy.md +53 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp-open-link-keys.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp-paste-a-coin-on-the-web.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp-the-verdict.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp-timestamped-follow-up-drafts.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp-what-it-looks-at.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp.md +24 -0
- package/dist/packages/mcp/assets/kb/docs/docs-login-with-x-degraded-states-you-will-see.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-login-with-x-free-vs-paid-x-api-tiers-your-bill-your-limits.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-login-with-x-kol-lists-and-the-per-handle-filter.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-login-with-x-tests.md +25 -0
- package/dist/packages/mcp/assets/kb/docs/docs-login-with-x-what-is-read-and-when.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-login-with-x-what-you-set-up-once.md +40 -0
- package/dist/packages/mcp/assets/kb/docs/docs-login-with-x-where-the-tokens-live.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-login-with-x.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-a-live-ticket.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-before-you-press-size-vs-caps.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-devnet-signer-mainnet-token.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-jupiter-rate-limits.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-letting-an-agent-paper-trade-experimental.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-live-trading-devnet-first.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-mainnet.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-order-plans-and-standing-mandates.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-panic.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-pnl-cards.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-live-fire-path-devnet-the-fast-wallet.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-signer-process.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-ticket.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-wallet.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-trade-moments.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-what-the-live-path-keeps.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-your-first-live-trade.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-bubble-map-popup.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-build-the-native-window.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-config-dexterm-popup-json.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-docking-macos.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-keys-in-the-popup.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-market-cap-axis.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-security-model.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-token-and-feeds-popups.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scan-cost-control.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scan-keys-flag-command.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scan-safety-four-layers.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scan-states.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scan-the-read.md +25 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scan-triggers-and-score.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scan.md +24 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scorecard-frozen-canary.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scorecard-frozen-task-1401-evaluation.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scorecard-latest-skill-care-run.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scorecard-links-only-larp-baseline-where-it-is-weak.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scorecard-not-measured.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scorecard-rug-verdict-rules.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scorecard-source-and-rebuild.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-scorecard.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-1-screener.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-2-new-pairs.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-3-watchlist.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-4-analyst-tab.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-bubble-map.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-coin-images.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-dev-history.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-how-well-it-predicts-measured-held-out.md +46 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-live-holder-and-rug-signals.md +51 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-order-plans.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-paper-ticket-and-positions.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-the-look.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-token-screen.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-trending-social-and-kol-lists.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-1-the-agent-activity-window-follow-mode.md +56 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-2-the-read-only-stream-spectate.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-3-save-and-replay-record-file-dexterm-spectate.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-follow-over-mcp-in-the-running-terminal.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-limits.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-quick-start.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-security-model.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-see-also.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-streaming-it.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-three-surfaces.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-what-is-redacted.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-common-questions.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-doctor-lines.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-in-app-messages.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-reporting-a-problem.md +25 -0
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting.md +23 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-doctor.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-it-clarifies-it-never-guesses.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-latency.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-linux-and-windows.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-privacy.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-still-unverified.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-the-voice-neural-by-default.md +48 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-what-it-can-never-do.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-what-you-can-say.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice.md +25 -0
- package/dist/packages/mcp/src/app-help.js +123 -0
- package/dist/packages/mcp/src/firewall.js +2 -2
- package/dist/packages/mcp/src/index.js +8 -4
- package/dist/packages/mcp/src/paper-agent.js +92 -0
- package/dist/packages/mcp/src/server.js +261 -29
- package/dist/packages/mcp/src/spectator-sink.js +146 -5
- package/dist/packages/mcp/src/user-content.js +1 -0
- package/dist/packages/recorder/src/dev-history.js +129 -0
- package/dist/packages/recorder/src/index.js +1 -0
- package/dist/packages/recorder/src/recorder.js +23 -0
- package/dist/packages/recorder/src/schema.js +11 -0
- package/dist/packages/voice/src/stt/whisper.js +4 -2
- package/package.json +6 -5
|
@@ -29,6 +29,9 @@ import { makeFixtureState, makeFeedState, syncFeed, renderFrame, isScreenKey, ac
|
|
|
29
29
|
import { mulberry32, tick, spawnPair, shock } from "./fixtures.js";
|
|
30
30
|
import { createLiveFeed, createReplayFeed } from "./feed.js";
|
|
31
31
|
import { LiveContext, INTERVALS, WATCH_REFRESH_MS, POSITIONS_REFRESH_MS, popupBubbleVM } from "./live/index.js";
|
|
32
|
+
import { FOLLOW_NAV_ACTIONS } from '../../mcp/src/index.js';
|
|
33
|
+
import { McpFollowSession } from "./mcp-follow.js";
|
|
34
|
+
import { AgentPaperSwitch } from "./agent-paper.js";
|
|
32
35
|
import { TOKEN_REFRESH_MS, CandlePrefetcher } from "./live/token.js";
|
|
33
36
|
import { PRESETS, presetSpec } from "./screener/presets.js";
|
|
34
37
|
import { parseSortArg, SORT_KEYS } from "./screener/sort.js";
|
|
@@ -45,6 +48,7 @@ import { copyAlertToDelivery } from "./alerts/format.js";
|
|
|
45
48
|
import { readTelegramCreds, readDiscordCreds } from "./alerts/creds.js";
|
|
46
49
|
import { launchIntelCells, launchRetryable } from "./live/intel.js";
|
|
47
50
|
import { AnalystSession } from "./analyst/session.js";
|
|
51
|
+
import { analystCliOnPath, parseEngineChoice, resolveEngine } from "./analyst/codex.js";
|
|
48
52
|
import { resolveAnalystResults } from "./analyst/results.js";
|
|
49
53
|
import { parseScanCommand, SCAN_FLAGS, checkScanFlag, SCAN_HELP } from "./scan/command.js";
|
|
50
54
|
import { parseWalletCommand, WALLET_HELP } from "./wallet-command.js";
|
|
@@ -100,6 +104,21 @@ export function appStateBlock(state) {
|
|
|
100
104
|
alerts, // booleans only — never a token, webhook or key
|
|
101
105
|
};
|
|
102
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* task-1443: the reduced screen snapshot a terminal following an EXTERNAL agent (`--spectate-mcp`) publishes for
|
|
109
|
+
* that agent's `dexterm mcp` server: what is on screen plus a VIEW-ONLY nav allow-list. Never the watchlist,
|
|
110
|
+
* tickets, positions or app settings, and only the four follow nav action types (no watchlist add, no ticket).
|
|
111
|
+
*/
|
|
112
|
+
export function followSnapshot(state) {
|
|
113
|
+
const ss = buildScreenState(state);
|
|
114
|
+
const a = ss.actions;
|
|
115
|
+
return {
|
|
116
|
+
screen: ss.screen, selected: ss.selected, selectedDetail: ss.selectedDetail, filter: ss.filter, sort: ss.sort,
|
|
117
|
+
visible: ss.visible, visibleMints: ss.visibleMints,
|
|
118
|
+
actions: { enabled: a.enabled, mints: a.mints, feeds: a.feeds, sortKeys: a.sortKeys, screens: a.screens, workspaces: [], themes: [], types: [...FOLLOW_NAV_ACTIONS] },
|
|
119
|
+
now: ss.now,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
103
122
|
export function buildScreenState(state) {
|
|
104
123
|
const live = state.live;
|
|
105
124
|
const sc = state.screener;
|
|
@@ -272,6 +291,7 @@ export const HELP = `dexterm ${VERSION} (live: screener, token, new pairs, watch
|
|
|
272
291
|
dexterm alerts status|enable|disable|set-telegram|set-discord|test where rule alerts are delivered (desktop / your Telegram / Discord; creds stay local, never logged)
|
|
273
292
|
dexterm watch [--interval S] [--once] [--replay FILE] run your rules headless and push alerts when the terminal is closed (no signer, proposals only)
|
|
274
293
|
dexterm record run|install|uninstall|status keep the history recorder fed with no TUI open, as a user-level launchd agent (no network beyond the data layer; 'dexterm record help')
|
|
294
|
+
dexterm larp-detected --out DIR [--db PATH] build timestamped high-risk follow-up drafts/cards from recorder history; never posts
|
|
275
295
|
dexterm --fixtures interactive demo on seeded fixtures
|
|
276
296
|
dexterm --screen <name> one-shot frame to stdout (live)
|
|
277
297
|
dexterm --screen <name> --fixtures one-shot frame from fixtures
|
|
@@ -284,6 +304,11 @@ export const HELP = `dexterm ${VERSION} (live: screener, token, new pairs, watch
|
|
|
284
304
|
--sort KEY[:asc|desc] ${SORT_KEYS.map((k) => k.key).join(' | ')}
|
|
285
305
|
--preset NAME ${PRESETS.map((p) => p.id).join(' | ')}
|
|
286
306
|
--record FILE save every live response (and the PumpPortal session) to FILE (replay it with --replay)
|
|
307
|
+
--spectate-mcp follow an MCP agent's allowed navigation in this terminal; Ctrl+P pauses, Ctrl+K stops,
|
|
308
|
+
and any normal user keypress takes control (refused actions never move the UI)
|
|
309
|
+
--agent-paper MANDATE_ID (experimental, with --spectate-mcp) let that MCP agent PAPER-trade inside a mandate you
|
|
310
|
+
armed: simulated fills only, never signs or sends, never raises a cap; Ctrl+P / Ctrl+K /
|
|
311
|
+
any key also pause, stop or take over its paper trading
|
|
287
312
|
--max-requests N hard cap on live requests for this run (default: none)
|
|
288
313
|
--max-credits N hard cap on Helius credits for this run (default: 5000)
|
|
289
314
|
--mint MINT|LINK token to open on the token screen (a CA or a dexscreener / pump.fun / solscan / birdeye link)
|
|
@@ -298,6 +323,8 @@ export const HELP = `dexterm ${VERSION} (live: screener, token, new pairs, watch
|
|
|
298
323
|
--selected N highlighted row / token index
|
|
299
324
|
--seed N fixture PRNG seed (default 7)
|
|
300
325
|
--no-ai hide the analyst panel on the token screen
|
|
326
|
+
--analyst-engine E auto | claude | codex: which of YOUR installed CLIs runs the analyst (default auto = claude
|
|
327
|
+
if installed, else codex; DEXTERM_ANALYST_ENGINE or config analyst.engine too; /engine in chat)
|
|
301
328
|
|
|
302
329
|
--intensity LEVEL off | normal | fever (default fever: rain, trails, glitch, blink, scanlines at 30 fps;
|
|
303
330
|
normal: 15 fps, sparser rain, no idle aberration; off = calm: neon theme, no motion)
|
|
@@ -385,13 +412,14 @@ export function parseArgs(argv) {
|
|
|
385
412
|
screen: null, fixtures: false, replay: null, record: null, filter: null, sort: null, preset: null, maxRequests: 0, maxCredits: 0, db: null,
|
|
386
413
|
mint: null, interval: '1h', listen: 20, verbose: false,
|
|
387
414
|
width: null, height: null, html: null, export: null, theme: DEFAULT_THEME, selected: 0, seed: 7,
|
|
388
|
-
noAi: false, title: null, plain: false, ansi: false, color: null, tz: null,
|
|
415
|
+
noAi: false, analystEngine: null, title: null, plain: false, ansi: false, color: null, tz: null,
|
|
389
416
|
calm: false, intensity: null, fps: null, frame: 0, t: 1, event: null, ai: null, mood: null, activity: null, noBoot: false, fit: null, fontPx: null, asciiRain: false, noImages: false,
|
|
390
417
|
scan: false, scanConfig: {},
|
|
391
418
|
noRecorder: false,
|
|
392
419
|
sound: false,
|
|
393
420
|
trade: [], live: true,
|
|
394
421
|
workspace: null, priceMode: null,
|
|
422
|
+
spectateMcp: false, agentPaper: null,
|
|
395
423
|
help: false, version: false, unknown: [],
|
|
396
424
|
};
|
|
397
425
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -480,6 +508,13 @@ export function parseArgs(argv) {
|
|
|
480
508
|
}
|
|
481
509
|
else if (k === '--no-ai')
|
|
482
510
|
a.noAi = true;
|
|
511
|
+
else if (k === '--analyst-engine') {
|
|
512
|
+
const s = str();
|
|
513
|
+
const e = parseEngineChoice(s);
|
|
514
|
+
if (!e)
|
|
515
|
+
throw new Error(`unknown analyst engine ${s} (expected auto|claude|codex)`);
|
|
516
|
+
a.analystEngine = e;
|
|
517
|
+
}
|
|
483
518
|
else if (k === '--calm')
|
|
484
519
|
a.calm = true;
|
|
485
520
|
else if (k === '--intensity') {
|
|
@@ -573,6 +608,16 @@ export function parseArgs(argv) {
|
|
|
573
608
|
throw new Error(`--price-mode expects price|mcap, got ${JSON.stringify(s.slice(0, 20))}`);
|
|
574
609
|
a.priceMode = s;
|
|
575
610
|
}
|
|
611
|
+
// task-1421: follow an agent driving over MCP (the running terminal moves with it; a read-only stream opens).
|
|
612
|
+
else if (k === '--spectate-mcp')
|
|
613
|
+
a.spectateMcp = true;
|
|
614
|
+
// task-1443: agent PAPER trading inside a mandate the user armed (validated against the plans journal at start).
|
|
615
|
+
else if (k === '--agent-paper') {
|
|
616
|
+
const s = str();
|
|
617
|
+
if (!/^[A-Za-z0-9_-]{1,64}$/.test(s))
|
|
618
|
+
throw new Error(`--agent-paper expects a mandate id (see \`dexterm mandate list\`), got ${JSON.stringify(s.slice(0, 20))}`);
|
|
619
|
+
a.agentPaper = s;
|
|
620
|
+
}
|
|
576
621
|
else if (k === '--workspace') {
|
|
577
622
|
const s = str();
|
|
578
623
|
if (!/^[a-z][a-z0-9-]{0,39}(\/[a-z][a-z0-9-]{0,39})?$/.test(s))
|
|
@@ -610,6 +655,10 @@ export function parseArgs(argv) {
|
|
|
610
655
|
throw new Error('--scan needs live data or a recording (drop --fixtures)');
|
|
611
656
|
if (a.scan && a.screen)
|
|
612
657
|
throw new Error('--scan is interactive (drop --screen)');
|
|
658
|
+
if (a.agentPaper && !a.spectateMcp)
|
|
659
|
+
throw new Error('--agent-paper needs --spectate-mcp (every agent paper trade must be visible in this terminal)');
|
|
660
|
+
if (a.agentPaper && a.db === ':memory:')
|
|
661
|
+
throw new Error('--agent-paper needs an on-disk --db (the agent books into the same paper wallet)');
|
|
613
662
|
return a;
|
|
614
663
|
}
|
|
615
664
|
/**
|
|
@@ -790,6 +839,11 @@ export async function main(argv, io = process, proc = process) {
|
|
|
790
839
|
const { backtestCommand } = await import("./backtest-cmd.js");
|
|
791
840
|
return backtestCommand(argv.slice(1), { stdout: io.stdout, stderr: io.stderr, env: io.env });
|
|
792
841
|
}
|
|
842
|
+
// Local-only marketing evidence pipeline (task-1433): drafts and cards for human review, never posts.
|
|
843
|
+
if (argv[0] === 'larp-detected') {
|
|
844
|
+
const { larpDetectedCommand } = await import("./larp-detected.js");
|
|
845
|
+
return larpDetectedCommand(argv.slice(1), { stdout: io.stdout, stderr: io.stderr, env: io.env });
|
|
846
|
+
}
|
|
793
847
|
// `dexterm kol …` → KOL lists on the shared DB (task-1330): list/create/add/remove/mute/unmute/enable/disable/import.
|
|
794
848
|
if (argv[0] === 'kol')
|
|
795
849
|
return kolCommand(argv.slice(1), io);
|
|
@@ -1006,6 +1060,8 @@ export async function main(argv, io = process, proc = process) {
|
|
|
1006
1060
|
});
|
|
1007
1061
|
recorder.attach(feed.dl.store);
|
|
1008
1062
|
ctx.recorder = recorder;
|
|
1063
|
+
// 0.1.5 dev history: PumpPortal / RugCheck creators of new pairs go into the creator index too.
|
|
1064
|
+
ctx.newpairs.onCreator = (mint, creator, source, createdAt) => { recorder.recordCreator(mint, creator, source, undefined, createdAt); };
|
|
1009
1065
|
}
|
|
1010
1066
|
if (args.verbose)
|
|
1011
1067
|
io.stderr.write(`dexterm: rpc ${rpc.provider} (${rpc.basis}) · db ${dbPath} · recorder ${ctx.recorder ? 'on' : 'off'} · live trading ${args.live && !io.env.DEXTERM_OFFLINE ? 'available' : 'off'}\n`);
|
|
@@ -2626,6 +2682,50 @@ export function applyScanAnalystAction(state, raw) {
|
|
|
2626
2682
|
const res = validateAnalystAction(raw, { ...allow, types: SCAN_ACTION_TYPES });
|
|
2627
2683
|
return { ok: false, error: res.ok ? 'AI scan mode is observe-only' : res.error };
|
|
2628
2684
|
}
|
|
2685
|
+
/**
|
|
2686
|
+
* The analyst engine for a run (0.1.5): `--analyst-engine`, then DEXTERM_ANALYST_ENGINE, then config
|
|
2687
|
+
* `analyst.engine`, then auto (claude when installed, else codex). Only the user picks it; models cannot.
|
|
2688
|
+
*/
|
|
2689
|
+
export function analystEngineFor(flag, env, configured, has = (b) => analystCliOnPath(b, env)) {
|
|
2690
|
+
const choice = parseEngineChoice(flag) ?? parseEngineChoice(env.DEXTERM_ANALYST_ENGINE) ?? parseEngineChoice(configured) ?? 'auto';
|
|
2691
|
+
return resolveEngine(choice, has);
|
|
2692
|
+
}
|
|
2693
|
+
/** `/engine [auto|claude|codex]` in the chat box (0.1.5). Null when the input is not this command. */
|
|
2694
|
+
export function parseEngineCommand(q) {
|
|
2695
|
+
const m = /^\/engine(?:\s+(\S+))?\s*$/i.exec(q.trim());
|
|
2696
|
+
if (!m)
|
|
2697
|
+
return null;
|
|
2698
|
+
if (!m[1])
|
|
2699
|
+
return { show: true };
|
|
2700
|
+
const c = parseEngineChoice(m[1]);
|
|
2701
|
+
return c ? { choice: c } : { error: `unknown analyst engine "${m[1].slice(0, 16)}" (use /engine auto|claude|codex)` };
|
|
2702
|
+
}
|
|
2703
|
+
/**
|
|
2704
|
+
* Apply `/engine`: switch the CLI for NEW conversations this run (cached per-coin chats are dropped so the next
|
|
2705
|
+
* `a` starts on the chosen engine; a running turn finishes where it started). Returns the line to show.
|
|
2706
|
+
*/
|
|
2707
|
+
export function engineCommand(state, cmd, env, has = (b) => analystCliOnPath(b, env)) {
|
|
2708
|
+
const installed = ['claude', 'codex'].filter((b) => has(b));
|
|
2709
|
+
const list = installed.length ? installed.join(' + ') : 'neither claude nor codex';
|
|
2710
|
+
if ('error' in cmd)
|
|
2711
|
+
return cmd.error;
|
|
2712
|
+
const cur = state.analystEngine ?? 'claude';
|
|
2713
|
+
if ('show' in cmd)
|
|
2714
|
+
return `analyst engine: ${cur} · installed: ${list} · /engine claude|codex|auto switches (config analyst.engine keeps it)`;
|
|
2715
|
+
const next = resolveEngine(cmd.choice, has);
|
|
2716
|
+
if (cmd.choice !== 'auto' && !has(next))
|
|
2717
|
+
return `${next} is not installed (installed: ${list}); ${next === 'codex' ? 'npm i -g @openai/codex && codex login' : 'install Claude Code, then run claude once to log in'}`;
|
|
2718
|
+
if (next !== cur) {
|
|
2719
|
+
for (const [k, sess] of state.analystByMint ?? []) {
|
|
2720
|
+
if (!sess.busy)
|
|
2721
|
+
state.analystByMint.delete(k);
|
|
2722
|
+
}
|
|
2723
|
+
if (state.analyst && !state.analyst.busy && state.analyst.engine !== next)
|
|
2724
|
+
state.analyst = null;
|
|
2725
|
+
}
|
|
2726
|
+
state.analystEngine = next;
|
|
2727
|
+
return `analyst engine: ${next} (your own ${next} CLI and login) for new conversations · set analyst.engine in config.json to keep it`;
|
|
2728
|
+
}
|
|
2629
2729
|
/**
|
|
2630
2730
|
* The ONE way a scan-driven analyst conversation is built (task-1324; the loop and the safety tests both
|
|
2631
2731
|
* use it): the locked coin as the selected coin, `actionTypes: []` (observe-only at the validator, the
|
|
@@ -2639,7 +2739,7 @@ export function createScanSession(state, mint, symbol, hooks = {}, deps = {}) {
|
|
|
2639
2739
|
const type = typeof raw.type === 'string' ? raw.type.replace(/[^a-z_]/gi, '').slice(0, 24) : '?';
|
|
2640
2740
|
hooks.onBlocked?.(type, r.error ?? 'refused');
|
|
2641
2741
|
};
|
|
2642
|
-
return new AnalystSession({ skill: 'token-dossier', mint, symbol, screenState: ss, onAction, actionTypes: SCAN_ACTION_TYPES, scan: true }, hooks.onChange ?? (() => { }), deps);
|
|
2742
|
+
return new AnalystSession({ skill: 'token-dossier', mint, symbol, screenState: ss, onAction, actionTypes: SCAN_ACTION_TYPES, scan: true, ...(state.analystEngine === 'codex' ? { engine: 'codex' } : {}) }, hooks.onChange ?? (() => { }), deps);
|
|
2643
2743
|
}
|
|
2644
2744
|
/**
|
|
2645
2745
|
* Resolve a mint to an openable seed from what the app already knows (screener view → new pairs →
|
|
@@ -2895,6 +2995,76 @@ export function applyAnalystAction(state, raw, stack) {
|
|
|
2895
2995
|
times.push(now);
|
|
2896
2996
|
return { ok: true, label: res.label };
|
|
2897
2997
|
}
|
|
2998
|
+
/**
|
|
2999
|
+
* task-1421: move the REAL terminal to mirror an agent's navigation (follow mode, on the owner's own
|
|
3000
|
+
* machine). This is the same VIEW-ONLY navigation the analyst / go-to path uses — open a token, switch
|
|
3001
|
+
* screen/feed, set a filter, highlight a row, open the PAPER ticket editor. It never trades, sizes, confirms
|
|
3002
|
+
* or signs, and the key loop flips control to the user before any of it runs, so the human always wins the
|
|
3003
|
+
* screen. Unlike the analyst boundary it does not re-check the on-screen allow-list: the agent already made
|
|
3004
|
+
* the call on its own server and this only reflects where it went. A no-op when live navigation is off.
|
|
3005
|
+
*/
|
|
3006
|
+
export function applyFollowNav(state, nav, stack) {
|
|
3007
|
+
const sc = state.screener;
|
|
3008
|
+
const live = state.live && state.screener.source !== 'fixtures' ? state.live : null;
|
|
3009
|
+
const toScreen = (next) => { if (state.screen !== next) {
|
|
3010
|
+
stack.push(state.screen);
|
|
3011
|
+
state.screen = next;
|
|
3012
|
+
} };
|
|
3013
|
+
if (nav.mint && (!nav.screen || nav.screen === 'token')) {
|
|
3014
|
+
if (!live)
|
|
3015
|
+
return;
|
|
3016
|
+
try {
|
|
3017
|
+
live.openToken(seedForMint(state, live, nav.mint));
|
|
3018
|
+
toScreen('token');
|
|
3019
|
+
}
|
|
3020
|
+
catch { /* a stale mint never breaks follow */ }
|
|
3021
|
+
return;
|
|
3022
|
+
}
|
|
3023
|
+
if (nav.screen === 'ticket') {
|
|
3024
|
+
if (!live || !nav.mint)
|
|
3025
|
+
return;
|
|
3026
|
+
try {
|
|
3027
|
+
const seed = seedForMint(state, live, nav.mint);
|
|
3028
|
+
live.openTicket({ mint: seed.mint, symbol: seed.symbol, name: seed.name }, nav.side === 'sell' ? 'sell' : 'buy');
|
|
3029
|
+
toScreen('ticket');
|
|
3030
|
+
}
|
|
3031
|
+
catch { /* ignore */ }
|
|
3032
|
+
return;
|
|
3033
|
+
}
|
|
3034
|
+
if (nav.screen === 'watchlist') {
|
|
3035
|
+
if (live && nav.mint) {
|
|
3036
|
+
try {
|
|
3037
|
+
if (!live.watch.has(nav.mint))
|
|
3038
|
+
live.watch.add(LiveContext.candidate(seedForMint(state, live, nav.mint)));
|
|
3039
|
+
}
|
|
3040
|
+
catch { /* ignore */ }
|
|
3041
|
+
}
|
|
3042
|
+
toScreen('watchlist');
|
|
3043
|
+
return;
|
|
3044
|
+
}
|
|
3045
|
+
if (nav.feed || nav.filter || nav.highlight || nav.screen === 'screener') {
|
|
3046
|
+
toScreen('screener');
|
|
3047
|
+
if (nav.feed) {
|
|
3048
|
+
if (setPreset(sc, nav.feed) && state.feed)
|
|
3049
|
+
state.feed.setPreset(sc.preset);
|
|
3050
|
+
}
|
|
3051
|
+
if (nav.filter) {
|
|
3052
|
+
try {
|
|
3053
|
+
setFilter(sc, nav.filter);
|
|
3054
|
+
}
|
|
3055
|
+
catch { /* an invalid agent filter is ignored */ }
|
|
3056
|
+
}
|
|
3057
|
+
if (nav.highlight) {
|
|
3058
|
+
const i = screenerView(sc).findIndex((r) => r.mint === nav.highlight);
|
|
3059
|
+
if (i >= 0)
|
|
3060
|
+
state.selected = i;
|
|
3061
|
+
}
|
|
3062
|
+
state.selected = clampSelection(sc, state.selected);
|
|
3063
|
+
return;
|
|
3064
|
+
}
|
|
3065
|
+
if (nav.screen && isScreenKey(nav.screen))
|
|
3066
|
+
toScreen(nav.screen);
|
|
3067
|
+
}
|
|
2898
3068
|
/**
|
|
2899
3069
|
* task-1413: apply an accepted tier-(b) config proposal through the journaled path as actor `analyst`
|
|
2900
3070
|
* (so `ctrl+z` undoes it), creating the parent section when absent (exactly like the `$` / `,` handlers),
|
|
@@ -3393,7 +3563,14 @@ export function terminalGuard(io, onFatal = () => { }, proc = process, hooks = {
|
|
|
3393
3563
|
proc.exit(1);
|
|
3394
3564
|
};
|
|
3395
3565
|
const onExit = () => restore();
|
|
3396
|
-
const onSignal = (sig) => {
|
|
3566
|
+
const onSignal = (sig) => {
|
|
3567
|
+
restore();
|
|
3568
|
+
try {
|
|
3569
|
+
hooks.onSignal?.();
|
|
3570
|
+
}
|
|
3571
|
+
catch { /* cleanup is best-effort; the exit still happens */ }
|
|
3572
|
+
proc.exit(sig === 'SIGTERM' ? 143 : 129);
|
|
3573
|
+
};
|
|
3397
3574
|
const onTerm = () => onSignal('SIGTERM');
|
|
3398
3575
|
const onHup = () => onSignal('SIGHUP');
|
|
3399
3576
|
let installed = false;
|
|
@@ -3430,6 +3607,8 @@ export function fpsFor(args, intensity) {
|
|
|
3430
3607
|
const SYNC_ON = '\x1b[?2026h';
|
|
3431
3608
|
const SYNC_OFF = '\x1b[?2026l';
|
|
3432
3609
|
export function interactive(state, io, depth, args, proc = process) {
|
|
3610
|
+
// 0.1.5: the analyst engine for new conversations (the user's own claude or codex CLI; never a shipped key).
|
|
3611
|
+
state.analystEngine ??= analystEngineFor(args.analystEngine, io.env, state.custom?.config.analyst?.engine);
|
|
3433
3612
|
const out = io.stdout;
|
|
3434
3613
|
const inp = io.stdin;
|
|
3435
3614
|
const rnd = mulberry32(99);
|
|
@@ -3730,6 +3909,11 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
3730
3909
|
let timer = null;
|
|
3731
3910
|
let lastRefresh = 0;
|
|
3732
3911
|
let done = false;
|
|
3912
|
+
// task-1421: the MCP follow session (set below when `--spectate-mcp` is on). Declared here so the quit /
|
|
3913
|
+
// terminal-guard teardown closures can stop it.
|
|
3914
|
+
let followSession = null;
|
|
3915
|
+
// task-1443: `--agent-paper <mandate-id>` (with --spectate-mcp) lets that agent PAPER-trade inside the mandate.
|
|
3916
|
+
const agentPaper = args.spectateMcp && args.agentPaper ? new AgentPaperSwitch({ env: io.env, mandateId: args.agentPaper, db: args.db ?? defaultDbPath(io.env) }) : null;
|
|
3733
3917
|
// Idle economy (task-1303, retuned for task-1319 AC3): between events the ambient rain redraws at
|
|
3734
3918
|
// IDLE_FPS instead of the full frame cap, cutting idle CPU. A keypress opens a KEY_WAKE_S full-rate
|
|
3735
3919
|
// window (`wakeUntil`) so input and transitions stay smooth; data landings paint at once on their own
|
|
@@ -3758,10 +3942,13 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
3758
3942
|
say(`trade moment failed: ${describeError(e)}`, 'warn');
|
|
3759
3943
|
}
|
|
3760
3944
|
};
|
|
3761
|
-
const
|
|
3762
|
-
clearInterval(timer); state.analyst?.cancel(); if (state.analystByMint)
|
|
3945
|
+
const teardown = () => { done = true; prefetcher?.close(); if (timer)
|
|
3946
|
+
clearInterval(timer); void followSession?.stop(); agentPaper?.stop(); state.analyst?.cancel(); if (state.analystByMint)
|
|
3763
3947
|
for (const s of state.analystByMint.values())
|
|
3764
|
-
s.cancel(); state.popups?.shutdown(); voice?.disable(); images?.close(); live?.close(); feed?.close(); }
|
|
3948
|
+
s.cancel(); state.popups?.shutdown(); voice?.disable(); images?.close(); live?.close(); feed?.close(); };
|
|
3949
|
+
// task-1443: SIGTERM/SIGHUP (a closed terminal window) runs the same teardown as a fatal error, so the agent-paper
|
|
3950
|
+
// rendezvous, the spectator rendezvous and the --record file never outlive the terminal that owns them.
|
|
3951
|
+
const guard = terminalGuard(io, teardown, proc, { beforeLeave: () => layer?.teardown() ?? '', onSignal: teardown });
|
|
3765
3952
|
let lastTokenRefresh = 0;
|
|
3766
3953
|
let lastWatchRefresh = 0;
|
|
3767
3954
|
let lastPositionsRefresh = 0;
|
|
@@ -3930,6 +4117,41 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
3930
4117
|
// task-1326: an image landing (decoded, or found missing) repaints at most once per macrotask.
|
|
3931
4118
|
if (images)
|
|
3932
4119
|
images.onChange = () => scheduleDraw();
|
|
4120
|
+
// task-1421: `--spectate-mcp` → follow an agent driving over MCP. The rendezvous lets a `dexterm mcp`
|
|
4121
|
+
// server the external client spawned emit here; we tail it, move the terminal for navigation calls, and
|
|
4122
|
+
// the owner's controls (ctrl+p pause/resume · ctrl+k stop · any key = take over) are handled in onInput.
|
|
4123
|
+
// A read-only, loopback, token-gated stream opens too (`dexterm spectate --info`). Off (and zero-cost)
|
|
4124
|
+
// unless the flag is set; nothing it folds can arm, sign, confirm, send or raise a cap.
|
|
4125
|
+
if (args.spectateMcp) {
|
|
4126
|
+
followSession = new McpFollowSession({
|
|
4127
|
+
env: io.env,
|
|
4128
|
+
stream: true,
|
|
4129
|
+
onNav: (nav) => {
|
|
4130
|
+
const before = state.screen;
|
|
4131
|
+
try {
|
|
4132
|
+
applyFollowNav(state, nav, stack);
|
|
4133
|
+
}
|
|
4134
|
+
catch { /* a stale mint never breaks follow */ }
|
|
4135
|
+
if (state.screen !== before) {
|
|
4136
|
+
try {
|
|
4137
|
+
startTransition();
|
|
4138
|
+
}
|
|
4139
|
+
catch {
|
|
4140
|
+
transition = null;
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
scheduleDraw();
|
|
4144
|
+
},
|
|
4145
|
+
onStatus: (line) => { say(line, 'ai', 4); scheduleDraw(); },
|
|
4146
|
+
onEvent: () => scheduleDraw(),
|
|
4147
|
+
onControl: agentPaper ? (st) => agentPaper.control(st) : undefined,
|
|
4148
|
+
snapshot: () => followSnapshot(state),
|
|
4149
|
+
});
|
|
4150
|
+
void followSession.start();
|
|
4151
|
+
say('following agents over MCP · ctrl+p pause · ctrl+k stop · any key takes over', 'ai', 6);
|
|
4152
|
+
if (agentPaper)
|
|
4153
|
+
say(agentPaper.start(), 'ai', 8);
|
|
4154
|
+
}
|
|
3933
4155
|
// Launch a real Claude analyst session when a key asked for one (applyAction cannot spawn). A
|
|
3934
4156
|
// `question` means start it as a chat turn, not a paid structured skill run (task-1311, QA B3).
|
|
3935
4157
|
const beginAnalyst = () => {
|
|
@@ -3996,7 +4218,7 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
3996
4218
|
maybeSpeakVoiceAnswer(session); // task-1282: speak a voice-initiated answer when it settles
|
|
3997
4219
|
scheduleDraw();
|
|
3998
4220
|
};
|
|
3999
|
-
const session = new AnalystSession({ skill: p.skill, mint: p.mint, symbol: p.symbol, screenState: buildScreenState(state), model: p.model, onAction }, onChange);
|
|
4221
|
+
const session = new AnalystSession({ skill: p.skill, mint: p.mint, symbol: p.symbol, screenState: buildScreenState(state), model: p.model, onAction, ...(state.analystEngine === 'codex' ? { engine: 'codex' } : {}) }, onChange);
|
|
4000
4222
|
if (p.question)
|
|
4001
4223
|
session.ask(p.question, buildScreenState(state));
|
|
4002
4224
|
else
|
|
@@ -4919,6 +5141,8 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
4919
5141
|
prefetcher?.close();
|
|
4920
5142
|
if (timer)
|
|
4921
5143
|
clearInterval(timer);
|
|
5144
|
+
void followSession?.stop();
|
|
5145
|
+
agentPaper?.stop();
|
|
4922
5146
|
guard.restore();
|
|
4923
5147
|
guard.uninstall();
|
|
4924
5148
|
cancelAllAnalysts();
|
|
@@ -4973,6 +5197,27 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
4973
5197
|
quit();
|
|
4974
5198
|
return;
|
|
4975
5199
|
}
|
|
5200
|
+
// task-1421 follow-mode controls (only while following an MCP agent). ctrl+p pauses / resumes the
|
|
5201
|
+
// terminal mirroring; ctrl+k stops following (removes the rendezvous so the server stops emitting);
|
|
5202
|
+
// ANY other key while the agent is driving hands control to the user — the human and the agent never
|
|
5203
|
+
// fight over the screen. The control keys are consumed; the take-over key still does its own job.
|
|
5204
|
+
if (followSession) {
|
|
5205
|
+
if (key.ctrl && key.ch === 'k') {
|
|
5206
|
+
followSession.kill();
|
|
5207
|
+
draw();
|
|
5208
|
+
continue;
|
|
5209
|
+
}
|
|
5210
|
+
if (key.ctrl && key.ch === 'p') {
|
|
5211
|
+
if (followSession.isPaused)
|
|
5212
|
+
followSession.resume();
|
|
5213
|
+
else
|
|
5214
|
+
followSession.pause();
|
|
5215
|
+
draw();
|
|
5216
|
+
continue;
|
|
5217
|
+
}
|
|
5218
|
+
if (followSession.controlState === 'agent')
|
|
5219
|
+
followSession.userKey(); // take over, then fall through
|
|
5220
|
+
}
|
|
4976
5221
|
// task-1413: a pending analyst config PROPOSAL owns the next key. `y` accepts and journals it as
|
|
4977
5222
|
// actor 'analyst' (ctrl+z undoes); any other key dismisses it. A stray key never persists a change.
|
|
4978
5223
|
// Two guards (defect c): the proposal does NOT steal a key while a TEXT INPUT is open — the GO-TO
|
|
@@ -5496,6 +5741,14 @@ export function interactive(state, io, depth, args, proc = process) {
|
|
|
5496
5741
|
draw();
|
|
5497
5742
|
continue;
|
|
5498
5743
|
}
|
|
5744
|
+
// 0.1.5: `/engine [auto|claude|codex]` switches the analyst CLI for new conversations; never sent to a model.
|
|
5745
|
+
const en0 = q.startsWith('/') ? parseEngineCommand(q) : null;
|
|
5746
|
+
if (en0) {
|
|
5747
|
+
state.aiInput = '';
|
|
5748
|
+
say(engineCommand(state, en0, io.env), typeof en0 === 'object' && 'error' in en0 ? 'warn' : 'info', 6);
|
|
5749
|
+
draw();
|
|
5750
|
+
continue;
|
|
5751
|
+
}
|
|
5499
5752
|
// task-1324: `/scan …` in the chat input is a command, never sent to claude.
|
|
5500
5753
|
const sc0 = q.startsWith('/') ? parseScanCommand(q) : null;
|
|
5501
5754
|
if (sc0) {
|