dexterm-cli 0.1.6 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/agents/src/schema.js +22 -1
- package/dist/packages/agents/src/spectator.js +3 -1
- package/dist/packages/agents/src/story.js +11 -2
- package/dist/packages/agents/src/tiers.js +36 -2
- package/dist/packages/agents/src/tools.js +35 -2
- package/dist/packages/autotrade/assets/exit-profile.schema.json +492 -0
- package/dist/packages/autotrade/assets/limits.schema.json +569 -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/examples/executor/README.md +70 -0
- package/dist/packages/autotrade/examples/executor/jsonl-tail-executor.mjs +57 -0
- package/dist/packages/autotrade/examples/executor/kit.mjs +144 -0
- package/dist/packages/autotrade/examples/executor/signal-cmd-executor.mjs +25 -0
- package/dist/packages/autotrade/examples/executor/telegram-bot-recipe.md +47 -0
- package/dist/packages/autotrade/examples/executor/webhook-executor.mjs +47 -0
- package/dist/packages/autotrade/src/account.js +74 -0
- package/dist/packages/autotrade/src/backtest.js +358 -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 +95 -0
- package/dist/packages/autotrade/src/chat/connector.js +24 -0
- package/dist/packages/autotrade/src/chat/control.js +104 -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 +302 -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 +106 -0
- package/dist/packages/autotrade/src/chat/service.js +251 -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 +401 -0
- package/dist/packages/autotrade/src/execution-port.js +97 -0
- package/dist/packages/autotrade/src/executor-health.js +217 -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 +642 -0
- package/dist/packages/autotrade/src/forward.js +355 -0
- package/dist/packages/autotrade/src/index.js +72 -0
- package/dist/packages/autotrade/src/journey.js +477 -0
- package/dist/packages/autotrade/src/ledger.js +108 -0
- package/dist/packages/autotrade/src/limits.js +682 -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/outbox.js +394 -0
- package/dist/packages/autotrade/src/paper-accounts.js +72 -0
- package/dist/packages/autotrade/src/paper-limits.js +87 -0
- package/dist/packages/autotrade/src/real-mode.js +688 -0
- package/dist/packages/autotrade/src/receipts.js +330 -0
- package/dist/packages/autotrade/src/replay.js +198 -0
- package/dist/packages/autotrade/src/report.js +168 -0
- package/dist/packages/autotrade/src/runner-config.js +99 -0
- package/dist/packages/autotrade/src/runner.js +923 -0
- package/dist/packages/autotrade/src/safety.js +243 -0
- package/dist/packages/autotrade/src/service-guard.js +125 -0
- package/dist/packages/autotrade/src/service-install.js +213 -0
- package/dist/packages/autotrade/src/service-recover.js +232 -0
- package/dist/packages/autotrade/src/service.js +289 -0
- package/dist/packages/autotrade/src/session.js +269 -0
- package/dist/packages/autotrade/src/sessions.js +503 -0
- package/dist/packages/autotrade/src/signal-channels.js +312 -0
- package/dist/packages/autotrade/src/signal.js +196 -0
- package/dist/packages/autotrade/src/store.js +250 -0
- package/dist/packages/autotrade/src/strategy.js +258 -0
- package/dist/packages/autotrade/src/trade-ledger.js +241 -0
- package/dist/packages/autotrade/src/yolo.js +140 -0
- package/dist/packages/cli/assets/claude/analyst-system.md +4 -4
- package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +1 -1
- package/dist/packages/cli/src/ai-cmd.js +412 -0
- package/dist/packages/cli/src/analyst/backend.js +83 -15
- package/dist/packages/cli/src/analyst/codex.js +15 -9
- package/dist/packages/cli/src/analyst/ollama.js +263 -0
- package/dist/packages/cli/src/analyst/session.js +5 -2
- package/dist/packages/cli/src/app-help-gen.js +56 -8
- package/dist/packages/cli/src/autotrade-cmd/audit.js +74 -0
- package/dist/packages/cli/src/autotrade-cmd/backtest.js +216 -0
- package/dist/packages/cli/src/autotrade-cmd/executor.js +91 -0
- package/dist/packages/cli/src/autotrade-cmd/flatten.js +64 -0
- package/dist/packages/cli/src/autotrade-cmd/fleet.js +401 -0
- package/dist/packages/cli/src/autotrade-cmd/forward.js +283 -0
- package/dist/packages/cli/src/autotrade-cmd/journey.js +208 -0
- package/dist/packages/cli/src/autotrade-cmd/limits.js +393 -0
- package/dist/packages/cli/src/autotrade-cmd/receipt.js +63 -0
- package/dist/packages/cli/src/autotrade-cmd/report.js +79 -0
- package/dist/packages/cli/src/autotrade-cmd/requests.js +79 -0
- package/dist/packages/cli/src/autotrade-cmd/run.js +657 -0
- package/dist/packages/cli/src/autotrade-cmd/service.js +873 -0
- package/dist/packages/cli/src/autotrade-cmd/signal.js +824 -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 +214 -0
- package/dist/packages/cli/src/display.js +156 -17
- package/dist/packages/cli/src/doctor.js +62 -3
- package/dist/packages/cli/src/export.js +10 -2
- package/dist/packages/cli/src/index.js +1 -1
- package/dist/packages/cli/src/ledger-cmd.js +290 -0
- package/dist/packages/cli/src/live/chart-fills.js +46 -0
- package/dist/packages/cli/src/live/index.js +23 -89
- package/dist/packages/cli/src/live/screens/token-live.js +9 -6
- package/dist/packages/cli/src/live/trade.js +12 -457
- package/dist/packages/cli/src/live/watchlist.js +1 -1
- package/dist/packages/cli/src/main.js +147 -190
- package/dist/packages/cli/src/mcp-cmd.js +7 -1
- package/dist/packages/cli/src/plan-cmd.js +1 -1
- package/dist/packages/cli/src/pnl-app.js +31 -21
- package/dist/packages/cli/src/pnl-card.js +162 -21
- package/dist/packages/cli/src/popup.js +22 -6
- package/dist/packages/cli/src/record-cmd.js +141 -20
- package/dist/packages/cli/src/screens/agent-hud.js +34 -2
- package/dist/packages/cli/src/screens/analyst-session.js +7 -4
- package/dist/packages/cli/src/screens/analyst.js +3 -2
- package/dist/packages/cli/src/screens/autotrade-journey.js +134 -0
- package/dist/packages/cli/src/screens/autotrade-keys.js +182 -0
- package/dist/packages/cli/src/screens/autotrade-proposals.js +123 -0
- package/dist/packages/cli/src/screens/autotrade-screen.js +776 -0
- package/dist/packages/cli/src/screens/autotrade-ui.js +650 -0
- package/dist/packages/cli/src/screens/autotrade-worker.js +91 -0
- package/dist/packages/cli/src/screens/brain.js +37 -11
- package/dist/packages/cli/src/screens/overlay.js +5 -2
- package/dist/packages/cli/src/screens/plans.js +5 -17
- package/dist/packages/cli/src/screens/pnl-chip.js +9 -8
- package/dist/packages/cli/src/screens/positions.js +6 -28
- package/dist/packages/cli/src/screens/ticket.js +38 -205
- package/dist/packages/cli/src/screens/token.js +3 -3
- package/dist/packages/cli/src/state.js +25 -19
- package/dist/packages/cli/src/telegram-cmd.js +454 -0
- package/dist/packages/cli/src/trade.js +3 -128
- package/dist/packages/cli/src/version.js +1 -1
- package/dist/packages/cli/src/wallet-cmd.js +39 -340
- package/dist/packages/cli/src/wallet-command.js +8 -11
- package/dist/packages/cli/src/widgets.js +0 -12
- package/dist/packages/custom/src/config.js +20 -2
- package/dist/packages/custom/src/schema.js +35 -10
- package/dist/packages/custom/src/workspace.js +3 -3
- package/dist/packages/data/src/basis.js +191 -0
- package/dist/packages/data/src/detail.js +53 -2
- package/dist/packages/data/src/index.js +0 -14
- package/dist/packages/data/src/store.js +14 -5
- package/dist/packages/data/src/trade/agent/paper-desk.js +228 -16
- package/dist/packages/data/src/trade/agent/rendezvous.js +3 -2
- package/dist/packages/data/src/trade/bridge.js +4 -102
- package/dist/packages/data/src/trade/ledger/export.js +101 -0
- package/dist/packages/data/src/trade/ledger/file.js +135 -0
- package/dist/packages/data/src/trade/ledger/fold.js +191 -0
- package/dist/packages/data/src/trade/ledger/index.js +9 -0
- package/dist/packages/data/src/trade/ledger/schema.js +83 -0
- package/dist/packages/data/src/trade/ledger/sources.js +307 -0
- package/dist/packages/data/src/trade/ledger/stats.js +123 -0
- package/dist/packages/data/src/trade/ledger/tags.js +116 -0
- package/dist/packages/data/src/trade/ledger/view.js +51 -0
- package/dist/packages/data/src/trade/plans/index.js +0 -1
- package/dist/packages/data/src/trade/plans/service.js +3 -27
- package/dist/packages/mcp/assets/kb/app-help/autotrade-chat.md +48 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-executor-kit.md +44 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-journey.md +46 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-limits.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-real-signal.md +45 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-runner.md +35 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-stop.md +37 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-strategies.md +35 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-telegram.md +40 -0
- package/dist/packages/mcp/assets/kb/app-help/chart-trade-markers.md +42 -0
- package/dist/packages/mcp/assets/kb/app-help/link-a-wallet.md +4 -10
- package/dist/packages/mcp/assets/kb/app-help/live-trading.md +38 -0
- package/dist/packages/mcp/assets/kb/app-help/live-yolo.md +34 -0
- package/dist/packages/mcp/assets/kb/app-help/order-plans.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/price-or-marketcap.md +5 -2
- package/dist/packages/mcp/assets/kb/app-help/screen-analyst.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-autotrade.md +229 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-kol.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-newpairs.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-positions.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-screener.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-token.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-trending.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-watchlist.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/standing-mandates.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/trade-ledger.md +54 -0
- package/dist/packages/mcp/assets/kb/app-help/use-local-model.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-agent-paper-trading.md +4 -1
- package/dist/packages/mcp/assets/kb/docs/docs-agents-reading-your-trade-ledger.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-untrusted-by-default.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-if-claude-is-missing.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-use-a-local-model-instead.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-sees.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-backtests-and-their-limits.md +56 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-change-a-strategy-by-chat.md +51 -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 +38 -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 +37 -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-always-on-service.md +57 -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 +50 -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-build-a-strategy-by-chat-1-ask-for-a-strategy.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-2-backtest-it-held-out-split.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-3-forward-test-it-on-live-data.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-4-promote-it-to-always-on-paper.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-5-real-only-if-you-choose.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-the-ladder.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-the-report.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-what-the-analyst-knows.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat.md +24 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-markers.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-y-axis.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-environment-variables.md +4 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-files-on-disk.md +1 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-headless-recorder-dexterm-record.md +3 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-price-display-mode.md +8 -6
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-2-the-one-key-mirror-ticket-a-proposal.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-3-capped-auto-mirror-default-off-less.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-what-is-proven-what-is-not.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-recorded-history-and-retention.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-sources.md +1 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-first-run.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-install.md +3 -3
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-requirements.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-executor-health.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-paper-vs-real.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-digest.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-executor-kit.md +48 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-whole-path.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-what-dexterm-does-and-never-does.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real-your-limits.md +77 -0
- package/dist/packages/mcp/assets/kb/docs/docs-going-real.md +24 -0
- 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-real-mode-your-strategy-s-trades-to-your.md +31 -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 +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does-not-do.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading.md +23 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-another-machine.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-autotrade-on-a-local-model.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-check-your-model-dexterm-ai-probe.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-how-we-checked.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-models-without-tool-calling.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-pick-the-engine-globally-or-per-surface.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-restriction-profiles.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-set-it-up-in-two-minutes.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-troubleshooting.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-runs-on-a-local-model.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-stays-outside-the-model.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-which-model.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-your-own-agent-on-the-local-model.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-letting-an-agent-paper-trade-experimental.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet-read-only.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-order-plans-and-standing-mandates.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-panic.md +4 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-paper-only-mandates.md +6 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-pnl-cards.md +7 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-safety-model.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-ticket.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-trade-ledger.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-wallet.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-trade-moments.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-buy-and-sell-markers.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +2 -1
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-receipts-what-your-executor-did.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-safety.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-set-it-up.md +47 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-the-channels.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-the-signal.md +48 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-what-it-is.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-what-it-will-not-do.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode-where-you-see-it.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-real-mode.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-autotrade-paper.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-order-plans.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-screens-token-screen.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-brain-view-and-the-pnl-chip.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-approve-one-tap-entries.md +50 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-control-the-commands.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-if-something-goes-wrong.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-notify-what-reaches-your-phone.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-set-it-up.md +47 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-the-record.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-is.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram.md +23 -0
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-common-questions.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-doctor-lines.md +4 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-linux-and-windows.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-voice.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-1-replay-it-on-your-own-history.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-2-run-it-on-paper.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-3-watch-it-and-stop-it.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-the-rules.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-is.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo.md +26 -0
- package/dist/packages/mcp/assets/kb/entries/autotrade.md +40 -0
- package/dist/packages/mcp/src/app-help.js +1 -1
- package/dist/packages/mcp/src/autotrade-tools.js +1107 -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 +494 -0
- package/dist/packages/mcp/src/paper-agent.js +2 -0
- package/dist/packages/mcp/src/server.js +138 -19
- package/dist/packages/packs/src/backtest.js +3 -1
- package/dist/packages/popup/src/pages/chart-lib.js +134 -21
- package/dist/packages/popup/src/pages/chart.css +9 -0
- package/dist/packages/popup/src/pages/chart.html +3 -1
- package/dist/packages/popup/src/pages/chart.js +104 -7
- package/dist/packages/popup/src/protocol.js +2 -0
- package/dist/packages/popup/src/server.js +4 -0
- package/dist/packages/recorder/src/index.js +2 -0
- package/dist/packages/recorder/src/recorder.js +63 -6
- package/dist/packages/recorder/src/retention.js +100 -0
- package/dist/packages/recorder/src/schema.js +34 -1
- package/dist/packages/recorder/src/ticks.js +237 -0
- package/dist/packages/tui/src/index.js +1 -0
- package/dist/packages/tui/src/keymap.js +28 -1
- package/dist/packages/tui/src/markers.js +219 -0
- package/dist/packages/tui/src/widgets.js +149 -2
- package/package.json +2 -1
- package/dist/packages/data/src/trade/caps.js +0 -323
- package/dist/packages/data/src/trade/executor.js +0 -933
- package/dist/packages/data/src/trade/plans/executor-live.js +0 -220
- package/dist/packages/data/src/trade/rpc-exec.js +0 -229
- package/dist/packages/data/src/trade/signer/client.js +0 -197
- package/dist/packages/data/src/trade/signer/fast-wallet.js +0 -154
- package/dist/packages/data/src/trade/signer/host.js +0 -97
- package/dist/packages/data/src/trade/signer/main.js +0 -121
- package/dist/packages/data/src/trade/signer/probe-builder.js +0 -85
- package/dist/packages/data/src/trade/signer/protocol.js +0 -92
- package/dist/packages/data/src/trade/signer/service.js +0 -400
- package/dist/packages/data/src/trade/signer/sol-usd-feed.js +0 -98
- package/dist/packages/data/src/trade/sol-usd.js +0 -86
- package/dist/packages/data/src/trade/swap-build.js +0 -108
- package/dist/packages/data/src/trade/token-delta.js +0 -201
- package/dist/packages/data/vendor/solana-web3/LICENSE +0 -20
- package/dist/packages/data/vendor/solana-web3/NOTICE.md +0 -13
- package/dist/packages/data/vendor/solana-web3/index.iife.min.js +0 -20
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-a-live-ticket.md +0 -42
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-before-you-press-size-vs-caps.md +0 -34
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-devnet-signer-mainnet-token.md +0 -35
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-jupiter-rate-limits.md +0 -33
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet.md +0 -32
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-live-trading-devnet-first.md +0 -30
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-mainnet.md +0 -31
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-live-fire-path-devnet-the-fast-wallet.md +0 -41
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-signer-process.md +0 -34
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-what-the-live-path-keeps.md +0 -37
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-your-first-live-trade.md +0 -41
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
// dexterm local engine: a minimal client for the user's own Ollama server (task-1543).
|
|
2
|
+
//
|
|
3
|
+
// Ollama runs models on the user's machine; dexterm talks to it over HTTP on the loopback interface
|
|
4
|
+
// (http://127.0.0.1:11434 by default). Nothing here ships a model, a key or a download: the user installs
|
|
5
|
+
// Ollama and pulls a model themselves. A host that is not on this machine is allowed only when the user
|
|
6
|
+
// configures it, and every surface that shows the host warns about it (data would leave the machine).
|
|
7
|
+
//
|
|
8
|
+
// Endpoints used: GET /api/version, GET /api/tags, POST /api/show, POST /api/chat (streamed NDJSON or one
|
|
9
|
+
// JSON object). No other host is ever contacted by this module.
|
|
10
|
+
export const DEFAULT_OLLAMA_HOST = 'http://127.0.0.1:11434';
|
|
11
|
+
export const DEFAULT_OLLAMA_PORT = 11434;
|
|
12
|
+
/** True for a loopback host name or address. */
|
|
13
|
+
export function isLoopbackHost(hostname) {
|
|
14
|
+
const h = hostname.replace(/^\[|\]$/g, '').toLowerCase();
|
|
15
|
+
if (h === 'localhost' || h.endsWith('.localhost'))
|
|
16
|
+
return true;
|
|
17
|
+
if (h === '::1' || h === '0:0:0:0:0:0:0:1')
|
|
18
|
+
return true;
|
|
19
|
+
return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse a user-supplied Ollama host ("127.0.0.1", "localhost:11434", "http://[::1]:11434"). Only http(s), no
|
|
23
|
+
* credentials, no path or query. The default port is 11434. Returns an error string for anything else.
|
|
24
|
+
*/
|
|
25
|
+
export function parseOllamaHost(raw) {
|
|
26
|
+
const s = String(raw ?? '').trim();
|
|
27
|
+
if (!s)
|
|
28
|
+
return parseOllamaHost(DEFAULT_OLLAMA_HOST);
|
|
29
|
+
let u;
|
|
30
|
+
try {
|
|
31
|
+
u = new URL(/^[a-z][a-z0-9+.-]*:\/\//i.test(s) ? s : `http://${s}`);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { error: `not a host: ${s.slice(0, 80)}` };
|
|
35
|
+
}
|
|
36
|
+
if (u.protocol !== 'http:' && u.protocol !== 'https:')
|
|
37
|
+
return { error: `only http or https hosts (got ${u.protocol.replace(':', '')})` };
|
|
38
|
+
if (u.username || u.password)
|
|
39
|
+
return { error: 'a host with a user name or password is refused (it would be stored in plain text)' };
|
|
40
|
+
if ((u.pathname && u.pathname !== '/') || u.search || u.hash)
|
|
41
|
+
return { error: 'give the host only, without a path or query (e.g. http://127.0.0.1:11434)' };
|
|
42
|
+
// The URL parser drops a scheme-default port (:80 / :443), so read an explicit port from the text itself.
|
|
43
|
+
const explicit = /^(?:[a-z][a-z0-9+.-]*:\/\/)?(?:\[[^\]]+\]|[^:/]+):(\d+)\/?$/i.exec(s);
|
|
44
|
+
const port = explicit ? explicit[1] : /^https:\/\//i.test(s) ? '443' : String(DEFAULT_OLLAMA_PORT);
|
|
45
|
+
const hostname = u.hostname; // IPv6 keeps its brackets here
|
|
46
|
+
return { url: `${u.protocol}//${hostname}:${port}`, hostname, local: isLoopbackHost(hostname) };
|
|
47
|
+
}
|
|
48
|
+
/** The one warning every surface shows for a host that is not this machine. */
|
|
49
|
+
export function remoteHostWarning(h) {
|
|
50
|
+
return h.local ? null : `the Ollama host ${h.hostname} is not this machine: prompts, screen context and tool results are sent to it over the network`;
|
|
51
|
+
}
|
|
52
|
+
export class OllamaError extends Error {
|
|
53
|
+
kind;
|
|
54
|
+
status;
|
|
55
|
+
/** task-1551: the host answered with a redirect, which is never followed (kind is 'unreachable'). */
|
|
56
|
+
redirect;
|
|
57
|
+
constructor(kind, message, status, redirect) { super(message); this.kind = kind; this.status = status; if (redirect)
|
|
58
|
+
this.redirect = true; }
|
|
59
|
+
}
|
|
60
|
+
/** task-1551: why a redirect is refused, for doctor / ask / ai probe. */
|
|
61
|
+
export const REDIRECT_REFUSED = 'answered with a redirect, which dexterm never follows for the local engine (it would send your prompt to another host); set the Ollama host to the Ollama server itself';
|
|
62
|
+
/** Strip a <think>…</think> block some models put in the content. */
|
|
63
|
+
export const stripThink = (s) => s.replace(/<think>[\s\S]*?(<\/think>|$)/g, '');
|
|
64
|
+
function normaliseToolCalls(raw) {
|
|
65
|
+
if (!Array.isArray(raw))
|
|
66
|
+
return [];
|
|
67
|
+
const out = [];
|
|
68
|
+
for (const c of raw) {
|
|
69
|
+
const f = c?.function;
|
|
70
|
+
if (!f || typeof f.name !== 'string' || !f.name)
|
|
71
|
+
continue;
|
|
72
|
+
let args = f.arguments;
|
|
73
|
+
if (typeof args === 'string') {
|
|
74
|
+
try {
|
|
75
|
+
args = JSON.parse(args);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
args = {};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
out.push({ function: { name: f.name, arguments: args && typeof args === 'object' && !Array.isArray(args) ? args : {} } });
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
export class OllamaClient {
|
|
86
|
+
host;
|
|
87
|
+
f;
|
|
88
|
+
metaTimeoutMs;
|
|
89
|
+
constructor(o) {
|
|
90
|
+
this.host = o.host;
|
|
91
|
+
this.f = o.fetch ?? ((url, init) => fetch(url, init));
|
|
92
|
+
this.metaTimeoutMs = o.metaTimeoutMs ?? 4000;
|
|
93
|
+
}
|
|
94
|
+
async req(path, init = {}, timeoutMs = this.metaTimeoutMs, outer) {
|
|
95
|
+
const ac = new AbortController();
|
|
96
|
+
const timer = setTimeout(() => ac.abort(new OllamaError('timeout', `Ollama did not answer within ${Math.round(timeoutMs / 1000)} s`)), timeoutMs);
|
|
97
|
+
timer.unref?.();
|
|
98
|
+
const onOuter = () => ac.abort(new OllamaError('aborted', 'cancelled'));
|
|
99
|
+
if (outer) {
|
|
100
|
+
if (outer.aborted)
|
|
101
|
+
onOuter();
|
|
102
|
+
else
|
|
103
|
+
outer.addEventListener('abort', onOuter, { once: true });
|
|
104
|
+
}
|
|
105
|
+
let res;
|
|
106
|
+
try {
|
|
107
|
+
// task-1551: redirect 'error' so a 3xx from the configured host never re-sends the prompt to another host.
|
|
108
|
+
res = await this.f(`${this.host.url}${path}`, {
|
|
109
|
+
method: init.method ?? 'GET',
|
|
110
|
+
headers: init.body !== undefined ? { 'content-type': 'application/json' } : undefined,
|
|
111
|
+
body: init.body !== undefined ? JSON.stringify(init.body) : undefined,
|
|
112
|
+
signal: ac.signal,
|
|
113
|
+
redirect: 'error',
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
const reason = ac.signal.reason;
|
|
118
|
+
if (reason instanceof OllamaError)
|
|
119
|
+
throw reason;
|
|
120
|
+
const cause = e?.cause?.message;
|
|
121
|
+
if (/redirect/i.test(String(cause ?? '')) || /redirect/i.test(e?.message ?? ''))
|
|
122
|
+
throw new OllamaError('unreachable', `Ollama at ${this.host.url} ${REDIRECT_REFUSED}`, undefined, true);
|
|
123
|
+
throw new OllamaError('unreachable', `cannot reach Ollama at ${this.host.url} (${e.message})`);
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
clearTimeout(timer);
|
|
127
|
+
outer?.removeEventListener('abort', onOuter);
|
|
128
|
+
}
|
|
129
|
+
// A fetch that ignored the init (or answered 'manual'): never use a redirect or a redirected answer.
|
|
130
|
+
if (res.redirected || (res.status >= 300 && res.status < 400)) {
|
|
131
|
+
try {
|
|
132
|
+
await res.body?.cancel();
|
|
133
|
+
}
|
|
134
|
+
catch { /* ignore */ }
|
|
135
|
+
throw new OllamaError('unreachable', `Ollama at ${this.host.url} ${REDIRECT_REFUSED}`, res.status, true);
|
|
136
|
+
}
|
|
137
|
+
return res;
|
|
138
|
+
}
|
|
139
|
+
static async fail(res, model) {
|
|
140
|
+
let msg = '';
|
|
141
|
+
try {
|
|
142
|
+
const j = await res.json();
|
|
143
|
+
msg = String(j?.error ?? '');
|
|
144
|
+
}
|
|
145
|
+
catch { /* not json */ }
|
|
146
|
+
if (res.status === 404 && model && /not found|pull/i.test(msg || 'not found'))
|
|
147
|
+
throw new OllamaError('model-missing', `model ${model} is not pulled on this Ollama (run: ollama pull ${model})`, 404);
|
|
148
|
+
throw new OllamaError('http', `Ollama answered HTTP ${res.status}${msg ? `: ${msg.slice(0, 200)}` : ''}`, res.status);
|
|
149
|
+
}
|
|
150
|
+
async version() {
|
|
151
|
+
const res = await this.req('/api/version');
|
|
152
|
+
if (!res.ok)
|
|
153
|
+
return OllamaClient.fail(res);
|
|
154
|
+
const j = await res.json();
|
|
155
|
+
return typeof j.version === 'string' ? j.version : 'unknown';
|
|
156
|
+
}
|
|
157
|
+
/** Pulled model names (e.g. "qwen3:8b"). */
|
|
158
|
+
async tags() {
|
|
159
|
+
const res = await this.req('/api/tags');
|
|
160
|
+
if (!res.ok)
|
|
161
|
+
return OllamaClient.fail(res);
|
|
162
|
+
const j = await res.json();
|
|
163
|
+
return (j.models ?? []).map((m) => String(m.name ?? m.model ?? '')).filter(Boolean);
|
|
164
|
+
}
|
|
165
|
+
/** Model metadata: capabilities (tools, thinking, …) and the trained context length. */
|
|
166
|
+
async show(model) {
|
|
167
|
+
const res = await this.req('/api/show', { method: 'POST', body: { model } });
|
|
168
|
+
if (!res.ok)
|
|
169
|
+
return OllamaClient.fail(res, model);
|
|
170
|
+
const j = await res.json();
|
|
171
|
+
let ctx = null;
|
|
172
|
+
for (const [k, v] of Object.entries(j.model_info ?? {}))
|
|
173
|
+
if (/\.context_length$/.test(k) && typeof v === 'number')
|
|
174
|
+
ctx = v;
|
|
175
|
+
return {
|
|
176
|
+
capabilities: Array.isArray(j.capabilities) ? j.capabilities.map(String) : null,
|
|
177
|
+
contextLength: ctx,
|
|
178
|
+
parameterSize: typeof j.details?.parameter_size === 'string' ? j.details.parameter_size : null,
|
|
179
|
+
family: typeof j.details?.family === 'string' ? j.details.family : null,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* One /api/chat call. With `onDelta` the response is streamed (NDJSON) and content deltas arrive as they
|
|
184
|
+
* are generated; tool calls and the final counters are returned either way.
|
|
185
|
+
*/
|
|
186
|
+
async chat(r, o = {}) {
|
|
187
|
+
const stream = !!o.onDelta;
|
|
188
|
+
const res = await this.req('/api/chat', { method: 'POST', body: { ...r, stream } }, o.timeoutMs ?? 600_000, o.signal);
|
|
189
|
+
if (!res.ok)
|
|
190
|
+
return OllamaClient.fail(res, r.model);
|
|
191
|
+
const out = { content: '', toolCalls: [], doneReason: null, promptTokens: 0, evalTokens: 0, totalMs: null, model: null };
|
|
192
|
+
const take = (j) => {
|
|
193
|
+
if (typeof j.error === 'string')
|
|
194
|
+
throw new OllamaError('http', `Ollama: ${j.error.slice(0, 200)}`);
|
|
195
|
+
const m = (j.message ?? {});
|
|
196
|
+
if (typeof m.content === 'string' && m.content) {
|
|
197
|
+
out.content += m.content;
|
|
198
|
+
o.onDelta?.(m.content);
|
|
199
|
+
}
|
|
200
|
+
out.toolCalls.push(...normaliseToolCalls(m.tool_calls));
|
|
201
|
+
if (typeof j.model === 'string')
|
|
202
|
+
out.model = j.model;
|
|
203
|
+
if (j.done) {
|
|
204
|
+
out.doneReason = typeof j.done_reason === 'string' ? j.done_reason : 'stop';
|
|
205
|
+
out.promptTokens = Number(j.prompt_eval_count) || 0;
|
|
206
|
+
out.evalTokens = Number(j.eval_count) || 0;
|
|
207
|
+
out.totalMs = typeof j.total_duration === 'number' ? Math.round(j.total_duration / 1e6) : null;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
if (!stream || !res.body) {
|
|
211
|
+
let j;
|
|
212
|
+
try {
|
|
213
|
+
j = await res.json();
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
throw new OllamaError('bad-response', 'Ollama sent a response that is not JSON');
|
|
217
|
+
}
|
|
218
|
+
take(j);
|
|
219
|
+
return out;
|
|
220
|
+
}
|
|
221
|
+
const dec = new TextDecoder();
|
|
222
|
+
let buf = '';
|
|
223
|
+
try {
|
|
224
|
+
for await (const chunk of res.body) {
|
|
225
|
+
buf += dec.decode(chunk, { stream: true });
|
|
226
|
+
let i;
|
|
227
|
+
while ((i = buf.indexOf('\n')) >= 0) {
|
|
228
|
+
const line = buf.slice(0, i).trim();
|
|
229
|
+
buf = buf.slice(i + 1);
|
|
230
|
+
if (!line)
|
|
231
|
+
continue;
|
|
232
|
+
let j;
|
|
233
|
+
try {
|
|
234
|
+
j = JSON.parse(line);
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
take(j);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
if (e instanceof OllamaError)
|
|
245
|
+
throw e;
|
|
246
|
+
if (o.signal?.aborted)
|
|
247
|
+
throw new OllamaError('aborted', 'cancelled');
|
|
248
|
+
throw new OllamaError('unreachable', `the Ollama stream broke (${e.message})`);
|
|
249
|
+
}
|
|
250
|
+
if (buf.trim()) {
|
|
251
|
+
try {
|
|
252
|
+
take(JSON.parse(buf));
|
|
253
|
+
}
|
|
254
|
+
catch { /* trailing garbage */ }
|
|
255
|
+
}
|
|
256
|
+
return out;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// dexterm local engine: the capability probe and the bar per restriction profile (task-1543).
|
|
2
|
+
//
|
|
3
|
+
// `dexterm doctor` and `dexterm ai probe` ask the user's Ollama: is it reachable, is the model pulled, can it call
|
|
4
|
+
// tools, how much context does it have, and (for paper/full) does it answer a fixed JSON protocol reliably. A
|
|
5
|
+
// model below the bar for the enabled profile gets a warning with the fix; nothing is blocked by the probe
|
|
6
|
+
// itself (the user decides), but the limits outside the model apply regardless.
|
|
7
|
+
import { OllamaError } from "./ollama.js";
|
|
8
|
+
import { RESTRICTION_RANK } from "./restrictions.js";
|
|
9
|
+
/**
|
|
10
|
+
* Tool-capable model families to start with. These are suggestions from Ollama's public library ("tools"
|
|
11
|
+
* capability), not a dexterm benchmark: the probe checks the copy you pulled. Smaller = faster, weaker.
|
|
12
|
+
*/
|
|
13
|
+
export const SUGGESTED_MODELS = [
|
|
14
|
+
{ name: 'qwen3:8b', size: '~5 GB', note: 'good default on a 16 GB machine' },
|
|
15
|
+
{ name: 'qwen3:14b', size: '~9 GB', note: 'steadier tool use, needs ~16 GB free' },
|
|
16
|
+
{ name: 'llama3.1:8b', size: '~5 GB', note: 'widely used tool caller' },
|
|
17
|
+
{ name: 'mistral-small3.2', size: '~15 GB', note: 'strong tool use on a 32 GB machine' },
|
|
18
|
+
];
|
|
19
|
+
/** What a model should manage at each profile (json = passes out of 3 protocol probes). */
|
|
20
|
+
export const BAR = {
|
|
21
|
+
observe: { tools: false, minCtx: 4096, json: 0 },
|
|
22
|
+
propose: { tools: true, minCtx: 8192, json: 0 },
|
|
23
|
+
paper: { tools: true, minCtx: 8192, json: 2 },
|
|
24
|
+
full: { tools: true, minCtx: 16384, json: 3 },
|
|
25
|
+
};
|
|
26
|
+
const PROBE_SCHEMA = {
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: { action: { type: 'string', enum: ['enter', 'wait', 'skip'] }, confidence: { type: 'number' }, reason: { type: 'string' } },
|
|
29
|
+
required: ['action', 'confidence', 'reason'],
|
|
30
|
+
};
|
|
31
|
+
const PROBE_PROMPTS = [
|
|
32
|
+
'Coin A: price up 12% in 5 minutes, buyers 40 vs sellers 12, liquidity $80K. Decide.',
|
|
33
|
+
'Coin B: price down 30% in 5 minutes, liquidity halved, top holder sold. Decide.',
|
|
34
|
+
'Coin C: flat for an hour, liquidity $5K, 3 holders. Decide.',
|
|
35
|
+
];
|
|
36
|
+
/** Run the probe. Never throws; `json` runs only when asked (it costs three short generations). */
|
|
37
|
+
export async function probeModel(client, model, o) {
|
|
38
|
+
const p = { host: client.host.url, local: client.host.local, reachable: false, version: null, error: null, models: [], model, present: false, capabilities: null, tools: null, contextLength: null, parameterSize: null, numCtx: o.numCtx, json: null };
|
|
39
|
+
try {
|
|
40
|
+
p.version = await client.version();
|
|
41
|
+
p.reachable = true;
|
|
42
|
+
p.models = await client.tags();
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
p.error = e.message;
|
|
46
|
+
if (e instanceof OllamaError && e.redirect)
|
|
47
|
+
p.redirect = true;
|
|
48
|
+
return p;
|
|
49
|
+
}
|
|
50
|
+
if (!model)
|
|
51
|
+
return p;
|
|
52
|
+
p.present = p.models.includes(model) || p.models.includes(`${model}:latest`) || (!model.includes(':') && p.models.some((m) => m.startsWith(`${model}:`)));
|
|
53
|
+
if (!p.present)
|
|
54
|
+
return p;
|
|
55
|
+
try {
|
|
56
|
+
const s = await client.show(model);
|
|
57
|
+
p.capabilities = s.capabilities;
|
|
58
|
+
p.tools = s.capabilities ? s.capabilities.includes('tools') : null;
|
|
59
|
+
p.contextLength = s.contextLength;
|
|
60
|
+
p.parameterSize = s.parameterSize;
|
|
61
|
+
if (s.contextLength)
|
|
62
|
+
p.numCtx = Math.min(o.numCtx, s.contextLength);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
p.error = e.message;
|
|
66
|
+
if (e instanceof OllamaError && e.kind === 'model-missing')
|
|
67
|
+
p.present = false;
|
|
68
|
+
return p;
|
|
69
|
+
}
|
|
70
|
+
if (o.json) {
|
|
71
|
+
let pass = 0;
|
|
72
|
+
for (const q of PROBE_PROMPTS) {
|
|
73
|
+
try {
|
|
74
|
+
const r = await client.chat({ model, messages: [{ role: 'system', content: 'Answer with the JSON object only: {"action":"enter|wait|skip","confidence":0..1,"reason":"short"}' }, { role: 'user', content: q }], format: PROBE_SCHEMA, options: { num_ctx: Math.min(p.numCtx, 4096), temperature: 0 } }, { timeoutMs: 120_000 });
|
|
75
|
+
const v = JSON.parse(r.content.trim());
|
|
76
|
+
if (['enter', 'wait', 'skip'].includes(String(v.action)) && typeof v.confidence === 'number' && v.confidence >= 0 && v.confidence <= 1 && typeof v.reason === 'string')
|
|
77
|
+
pass++;
|
|
78
|
+
}
|
|
79
|
+
catch { /* a failed run is a miss */ }
|
|
80
|
+
}
|
|
81
|
+
p.json = { pass, runs: PROBE_PROMPTS.length };
|
|
82
|
+
}
|
|
83
|
+
return p;
|
|
84
|
+
}
|
|
85
|
+
/** Warnings when the probed model is below the bar for a profile (empty = fine). Each says how to fix it. */
|
|
86
|
+
export function belowBar(level, p) {
|
|
87
|
+
const bar = BAR[level];
|
|
88
|
+
const w = [];
|
|
89
|
+
if (!p.reachable || !p.present)
|
|
90
|
+
return w;
|
|
91
|
+
if (bar.tools && p.tools === false)
|
|
92
|
+
w.push(`${p.model} cannot call tools: at ${level} it answers from the dossier only; pull a tool-capable model (e.g. ollama pull ${SUGGESTED_MODELS[0].name})`);
|
|
93
|
+
const ctx = p.contextLength ?? p.numCtx;
|
|
94
|
+
if (ctx < bar.minCtx)
|
|
95
|
+
w.push(`${p.model} has a ${ctx}-token context; ${level} wants at least ${bar.minCtx} (long dossiers get cut)`);
|
|
96
|
+
if (p.json && p.json.pass < bar.json)
|
|
97
|
+
w.push(`${p.model} answered ${p.json.pass}/${p.json.runs} protocol probes; ${level} wants ${bar.json}/3 (decisions it cannot format are refused, which means fewer trades, not bigger ones)`);
|
|
98
|
+
if (RESTRICTION_RANK[level] >= RESTRICTION_RANK.paper && p.json === null)
|
|
99
|
+
w.push(`run \`dexterm ai probe --json\` to check ${p.model} formats decisions reliably before ${level}`);
|
|
100
|
+
return w;
|
|
101
|
+
}
|
|
102
|
+
/** Pick a model when none is configured: the first suggested one that is pulled, else the first pulled model. */
|
|
103
|
+
export function pickModel(pulled) {
|
|
104
|
+
for (const s of SUGGESTED_MODELS) {
|
|
105
|
+
const hit = pulled.find((m) => m === s.name || m === `${s.name}:latest`);
|
|
106
|
+
if (hit)
|
|
107
|
+
return hit;
|
|
108
|
+
}
|
|
109
|
+
return pulled.find((m) => !/embed/i.test(m)) ?? null;
|
|
110
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// dexterm local engine: the pack REASON stage on Ollama (task-1543).
|
|
2
|
+
//
|
|
3
|
+
// Same contract as the claude runner in @dexterm/packs (reason.ts): one tool-less call over an assembled dossier,
|
|
4
|
+
// structured output forced by the schema, and the reply shaped like `claude -p --output-format json` so the
|
|
5
|
+
// packs' grounding / tighten-only / flags-kept checks run unchanged. The model id of the call is the local one.
|
|
6
|
+
import { stripThink } from "./ollama.js";
|
|
7
|
+
export function ollamaReasonRunner(client, model, numCtx = 16384) {
|
|
8
|
+
return async ({ prompt, system, schema, timeoutMs }) => {
|
|
9
|
+
const t0 = Date.now();
|
|
10
|
+
try {
|
|
11
|
+
const r = await client.chat({
|
|
12
|
+
model,
|
|
13
|
+
messages: [{ role: 'system', content: system }, { role: 'user', content: prompt }],
|
|
14
|
+
format: schema,
|
|
15
|
+
options: { num_ctx: numCtx, temperature: 0 },
|
|
16
|
+
}, { timeoutMs });
|
|
17
|
+
let structured = null;
|
|
18
|
+
try {
|
|
19
|
+
structured = JSON.parse(stripThink(r.content).trim());
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
structured = null;
|
|
23
|
+
}
|
|
24
|
+
const ok = !!structured && typeof structured === 'object' && !Array.isArray(structured);
|
|
25
|
+
return {
|
|
26
|
+
stdout: JSON.stringify({ type: 'result', is_error: !ok, structured_output: ok ? structured : null, total_cost_usd: 0, duration_api_ms: Date.now() - t0, num_turns: 1, engine: 'ollama', model: r.model ?? model }),
|
|
27
|
+
exitCode: ok ? 0 : 1,
|
|
28
|
+
...(ok ? {} : { stderr: 'the local model did not return the JSON object' }),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
return { stdout: '', exitCode: 127, stderr: `ollama: ${e.message}` };
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// dexterm local engine: restriction profiles and the engine-parity matrix (task-1543).
|
|
2
|
+
//
|
|
3
|
+
// A local engine (Ollama) can do everything the Claude path does, behind a restriction profile the USER picks:
|
|
4
|
+
//
|
|
5
|
+
// observe analyse only: read tools, no UI actions, no proposals, no orders
|
|
6
|
+
// propose the analyst's surface: read tools + UI actions (open_ticket only OPENS a paper ticket) + strategy
|
|
7
|
+
// proposals the user applies by keypress. The default for a new local setup.
|
|
8
|
+
// paper propose + paper orders (autotrade paper sessions, agent paper trading inside a mandate you armed)
|
|
9
|
+
// full everything the Claude path may do, subject to the same user-set mandate tiers and gates
|
|
10
|
+
//
|
|
11
|
+
// The profile only decides what the engine may ASK for. Every limit that protects money is enforced outside
|
|
12
|
+
// the model and is identical for every engine: the signer's caps, the kill switch, the dead-man switch, live-mode
|
|
13
|
+
// gating, mandate tiers, the strategy clamp and the Telegram button/nonce rules. A model can request; it can
|
|
14
|
+
// never raise a cap, arm a mandate or turn live on, and no tool, MCP call or chat message changes the profile.
|
|
15
|
+
import { ANALYST_ACTION_TYPES } from '../../../data/src/index.js';
|
|
16
|
+
import { PAPER_NOTE_TOOLS, PAPER_READ_TOOLS, PAPER_WRITE_TOOLS, READ_ONLY_TOOLS } from "../server.js";
|
|
17
|
+
import { JOURNEY_CONTROL_TOOLS, JOURNEY_PROPOSE_TOOLS, PARALLEL_CONTROL_TOOLS, STRATEGY_PROPOSE_TOOLS } from "../autotrade-tools.js";
|
|
18
|
+
import { LEDGER_PROPOSE_TOOLS } from "../ledger-tools.js";
|
|
19
|
+
export const RESTRICTION_LEVELS = ['observe', 'propose', 'paper', 'full'];
|
|
20
|
+
export const RESTRICTION_RANK = { observe: 0, propose: 1, paper: 2, full: 3 };
|
|
21
|
+
/** A new local-engine setup starts here. `full` needs a typed confirmation (`dexterm ai engine ollama --full`). */
|
|
22
|
+
export const DEFAULT_RESTRICTION = 'propose';
|
|
23
|
+
export const RESTRICTION_HELP = {
|
|
24
|
+
observe: 'analyse only (read tools; no UI actions, no proposals, no orders)',
|
|
25
|
+
propose: 'analyst + proposals (UI actions, a PAPER ticket you confirm, strategy proposals you apply); no orders',
|
|
26
|
+
paper: 'proposals + paper orders (autotrade paper sessions, agent paper trading inside a mandate you armed)',
|
|
27
|
+
full: 'everything the Claude path may do, inside the same caps, mandate tiers, kill switch and live gating',
|
|
28
|
+
};
|
|
29
|
+
export function isRestriction(v) {
|
|
30
|
+
return typeof v === 'string' && RESTRICTION_LEVELS.includes(v);
|
|
31
|
+
}
|
|
32
|
+
export function atLeast(have, need) {
|
|
33
|
+
return RESTRICTION_RANK[have] >= RESTRICTION_RANK[need];
|
|
34
|
+
}
|
|
35
|
+
export function lowerOf(a, b) {
|
|
36
|
+
return RESTRICTION_RANK[a] <= RESTRICTION_RANK[b] ? a : b;
|
|
37
|
+
}
|
|
38
|
+
/** What an engine may ask for, by the lowest profile that allows it. */
|
|
39
|
+
export const CAPABILITY_LEVEL = {
|
|
40
|
+
analyse: 'observe',
|
|
41
|
+
'ui-actions': 'propose',
|
|
42
|
+
'strategy-proposals': 'propose',
|
|
43
|
+
'paper-orders': 'paper',
|
|
44
|
+
'live-orders': 'full',
|
|
45
|
+
};
|
|
46
|
+
export function allows(level, cap) {
|
|
47
|
+
return atLeast(level, CAPABILITY_LEVEL[cap]);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Tool names no local engine is ever handed, whatever a server grows (defence in depth: the dexterm MCP server
|
|
51
|
+
* has no such tool, and its no-sign registry test keeps it that way).
|
|
52
|
+
*/
|
|
53
|
+
export const NEVER_TOOL = /(^|_)(sign|signer|send|transfer|withdraw|arm|disarm|caps?|key|keys|seed|keystore|live|mainnet|unlock|resume|panic|restrictions?|engine)(_|$)/i;
|
|
54
|
+
/**
|
|
55
|
+
* The dexterm MCP tools a local engine may call at a profile. `actionTypes` is the session's UI-action list
|
|
56
|
+
* exactly as the claude path reads it: absent = all of them, `[]` (AI scan) = none and no proposals either.
|
|
57
|
+
*/
|
|
58
|
+
export function engineToolAllowlist(level, actionTypes) {
|
|
59
|
+
const actions = ANALYST_ACTION_TYPES;
|
|
60
|
+
const reads = READ_ONLY_TOOLS.filter((n) => !/^paper_/.test(n) && !actions.includes(n));
|
|
61
|
+
const out = new Set(reads);
|
|
62
|
+
const observeOnly = !!actionTypes && actionTypes.length === 0;
|
|
63
|
+
if (allows(level, 'ui-actions') && !observeOnly)
|
|
64
|
+
for (const t of actions)
|
|
65
|
+
if (!actionTypes || actionTypes.includes(t))
|
|
66
|
+
out.add(t);
|
|
67
|
+
if (allows(level, 'strategy-proposals') && !observeOnly)
|
|
68
|
+
for (const t of [...STRATEGY_PROPOSE_TOOLS, ...JOURNEY_PROPOSE_TOOLS])
|
|
69
|
+
out.add(t);
|
|
70
|
+
// Paper tools: the MCP server still refuses them unless the user armed a mandate and enabled agent paper trading.
|
|
71
|
+
if (allows(level, 'paper-orders') && !observeOnly)
|
|
72
|
+
for (const t of [...PAPER_READ_TOOLS, ...PAPER_WRITE_TOOLS])
|
|
73
|
+
out.add(t);
|
|
74
|
+
// v0.1.7 integration: the other paper-side writes (start / stop / pause one listed parallel strategy, a paper
|
|
75
|
+
// journal tag, a backtest request file) join at `paper`, so `paper` and `full` offer every tool the claude path has
|
|
76
|
+
if (allows(level, 'paper-orders') && !observeOnly)
|
|
77
|
+
for (const t of [...PARALLEL_CONTROL_TOOLS, ...JOURNEY_CONTROL_TOOLS, ...PAPER_NOTE_TOOLS, ...LEDGER_PROPOSE_TOOLS])
|
|
78
|
+
out.add(t);
|
|
79
|
+
return [...out].filter((n) => !NEVER_TOOL.test(n));
|
|
80
|
+
}
|
|
81
|
+
/** The surfaces that run a model, and the profile each needs on a local engine. */
|
|
82
|
+
export const SURFACES = ['analyst', 'autotrade', 'packs', 'agent'];
|
|
83
|
+
/** The profile a surface needs before a local engine may run it (live autotrade needs `full`). */
|
|
84
|
+
export function requiredLevel(surface, o = {}) {
|
|
85
|
+
if (surface === 'autotrade')
|
|
86
|
+
return o.live ? 'full' : 'paper';
|
|
87
|
+
if (surface === 'agent')
|
|
88
|
+
return 'propose';
|
|
89
|
+
return 'observe';
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Every place the Claude CLI is spawned or assumed, and its local-engine equivalent. Kept in code so the docs,
|
|
93
|
+
* `dexterm ai status` and the parity test read the same list.
|
|
94
|
+
*/
|
|
95
|
+
export const ENGINE_PARITY = [
|
|
96
|
+
{ id: 'analyst-chat', surface: 'Analyst chat (token screen, `a`, follow-ups)', claude: 'claude -p with the read-only dexterm MCP server', local: 'Ollama /api/chat (streamed) with the same dexterm MCP server over stdio, same tools, same firewall', status: 'equivalent', minLevel: 'observe', test: 'packages/cli/test/ollama-analyst-1543.test.ts' },
|
|
97
|
+
{ id: 'analyst-skills', surface: 'Structured skills (dossier, rug-check, larp-check, trench-scan)', claude: '--json-schema structured output', local: 'tool loop, then Ollama structured output (format = the same schema)', status: 'equivalent', minLevel: 'observe', test: 'packages/cli/test/ollama-analyst-1543.test.ts' },
|
|
98
|
+
{ id: 'analyst-no-tools', surface: 'A model without tool calling', claude: 'n/a (Claude always has tools)', local: 'dexterm fetches the dossier itself and the model answers from it without tools, and says so', status: 'degrade', minLevel: 'observe', test: 'packages/cli/test/ollama-analyst-1543.test.ts' },
|
|
99
|
+
{ id: 'ai-scan', surface: 'AI scan mode (Z)', claude: 'observe-only analyst session', local: 'same session on the local engine, observe-only at the allowlist, the MCP server and the app', status: 'equivalent', minLevel: 'observe', test: 'packages/cli/test/ollama-analyst-1543.test.ts' },
|
|
100
|
+
{ id: 'jarvis', surface: 'Jarvis voice questions', claude: 'asks through the analyst session', local: 'asks through the same session, on whichever engine /engine picked', status: 'equivalent', minLevel: 'observe', test: 'packages/cli/test/ollama-analyst-1543.test.ts' },
|
|
101
|
+
{ id: 'ask', surface: 'Headless question (`dexterm ai ask`)', claude: 'the analyst backend on claude', local: 'the analyst backend on Ollama', status: 'equivalent', minLevel: 'observe', test: 'packages/cli/test/ollama-analyst-1543.test.ts' },
|
|
102
|
+
{ id: 'strategy-proposals', surface: 'Tune by chat (strategy_propose_edit / _new)', claude: 'MCP propose tools; the user applies by keypress', local: 'the same tools at `propose`; the same keypress apply path', status: 'equivalent', minLevel: 'propose', test: 'packages/mcp/test/ollama-engine-1543.test.ts' },
|
|
103
|
+
{ id: 'autotrade-sessions', surface: 'Autotrade candidate + position sessions', claude: 'tool-less claude -p, DECISION line, engine clamp', local: 'tool-less Ollama session, the same DECISION line (structured output), the same clamp, caps and ledger', status: 'equivalent', minLevel: 'paper', test: 'packages/autotrade/test/ollama-sessions-1543.test.ts' },
|
|
104
|
+
{ id: 'live-executors', surface: 'Live orders (signer, mandates)', claude: 'requests only; the signer enforces the caps', local: 'requests only, at `full`; the same signer, caps, mandate tiers, kill switch and live gating', status: 'equivalent', minLevel: 'full', test: 'packages/autotrade/test/ollama-sessions-1543.test.ts' },
|
|
105
|
+
{ id: 'packs-reason', surface: 'Pack reasoning stage (tighten-only verdict; a library stage no app screen calls today)', claude: 'tool-less claude -p with --json-schema', local: 'tool-less Ollama structured output, the same grounding/tighten-only checks (ollamaReasonRunner)', status: 'equivalent', minLevel: 'observe', test: 'packages/mcp/test/ollama-engine-1543.test.ts' },
|
|
106
|
+
{ id: 'mcp-agent', surface: 'MCP agent (incl. agent paper trading in an armed mandate)', claude: 'claude -p connected to `dexterm mcp`', local: '`dexterm ai agent`: Ollama as the MCP client, tools by profile, paper tools only at `paper`', status: 'equivalent', minLevel: 'propose', test: 'packages/cli/test/ollama-analyst-1543.test.ts' },
|
|
107
|
+
{ id: 'telegram', surface: 'Telegram control + approvals', claude: 'human buttons (one-time, nonce/hash/expiry, sender allowlist)', local: 'the same: approvals are taps by the user, never by a model, whichever engine proposed', status: 'engine-independent', minLevel: null, test: 'packages/autotrade/test/ollama-sessions-1543.test.ts' },
|
|
108
|
+
{ id: 'agent-bus', surface: 'Loopback agent bus / SDK agents', claude: 'agents bring their own model', local: 'the same; a local agent can use the SDK or `dexterm ai agent`', status: 'engine-independent', minLevel: null, test: 'packages/mcp/test/ollama-engine-1543.test.ts' },
|
|
109
|
+
{ id: 'allowance-guard', surface: 'Claude allowance guard (rate_limit_event)', claude: 'pauses sessions near the plan limit', local: 'no plan limit and $0 cost; the day turn and session caps still apply', status: 'degrade', minLevel: null, test: 'packages/autotrade/test/ollama-sessions-1543.test.ts' },
|
|
110
|
+
{ id: 'routines', surface: 'Scheduled routines', claude: 'none run in the app today (daily-digest is defined only)', local: 'any future routine goes through the same engine seam', status: 'not-in-app', minLevel: null, test: 'packages/mcp/test/ollama-engine-1543.test.ts' },
|
|
111
|
+
];
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
// @dexterm/mcp — read-only MCP server over stdio (SPEC §5, D-09 / task-1302).
|
|
2
2
|
// Every tool is read-only and schema-described; nothing in this package may build,
|
|
3
3
|
// sign or send a transaction (SPEC §5.2, §6.3).
|
|
4
|
-
export { runStdioServer, selfTest, McpTools, TOOLS, READ_ONLY_TOOLS, PAPER_WRITE_TOOLS, PAPER_READ_TOOLS, appHelpAnswer, firewall, listPrompts, getPrompt, resourceList, resourceRead, overlayCounts, userSkillPreamble, BUNDLED_KB_DIR, BUNDLED_SKILLS_DIR } from "./server.js";
|
|
4
|
+
export { runStdioServer, selfTest, McpTools, TOOLS, READ_ONLY_TOOLS, PAPER_WRITE_TOOLS, PAPER_READ_TOOLS, PAPER_NOTE_TOOLS, appHelpAnswer, firewall, listPrompts, getPrompt, resourceList, resourceRead, overlayCounts, userSkillPreamble, BUNDLED_KB_DIR, BUNDLED_SKILLS_DIR } from "./server.js";
|
|
5
5
|
// task-1443: resolve the paper agent desk from the running app's rendezvous (null when agent paper trading is off).
|
|
6
6
|
export { resolvePaperAgentDesk, paperAgentDeskDb } from "./paper-agent.js";
|
|
7
7
|
export { OverlayStore, mergeOverlay, loadBundled, checkKb, checkSkill, moneyToolMentions, isMoneyToolName, parseFrontmatter, dextermHome, userKbDir, userSkillsDir, userDir, contentJournalPath, journalContent, writeOverlayFile, resetOverlayFile, templateFor, KB_LIMITS, SKILL_LIMITS, KB_ID, SKILL_NAME, KB_RULE, MONEY_TOOLS, } from "./user-content.js";
|
|
8
|
+
// task-1507: the AUTOTRADE chat tools (strategy reads + proposals), the model deny-list, the risk delta and the
|
|
9
|
+
// proposal files the Q screen's keypress path re-checks and applies.
|
|
10
|
+
export { AutotradeTools, ProposalFiles, checkProposal, riskDelta, diffLines, screenDelta, deniedChanges, opsPolicyErrors, opsShapeErrors, proposalCardView, proposalsDir, isProposalId, cleanText, loadEngine, STRATEGY_DENIED_FOR_MODELS, STRATEGY_READ_TOOLS, STRATEGY_PROPOSE_TOOLS, AUTOTRADE_TOOLS, PARALLEL_READ_TOOLS, PARALLEL_CONTROL_TOOLS, PARALLEL_TOOLS, JOURNEY_READ_TOOLS, JOURNEY_CONTROL_TOOLS, JOURNEY_PROPOSE_TOOLS, JOURNEY_TOOLS, FORWARD_START_RATE, defaultForwardSpawner, MAX_PROPOSAL_OPS, BACKTEST_MAX_DAYS, BACKTEST_RATE, PROPOSAL_SCHEMA, RUNNER_STATUS_SCHEMA, } from "./autotrade-tools.js";
|
|
8
11
|
export { buildDossier } from "./dossier.js";
|
|
12
|
+
// task-1530: the trade-ledger tools (reads + the backtest request), and the request files the CLI runs or dismisses.
|
|
13
|
+
export { LedgerTools, LEDGER_TOOLS, LEDGER_READ_TOOLS, LEDGER_PROPOSE_TOOLS, tradeView, filterFromArgs } from "./ledger-tools.js";
|
|
14
|
+
export { BacktestRequests, requestsDir, isRequestId, BACKTEST_REQUEST_SCHEMA, REQUEST_MAX_DAYS, MAX_PENDING_REQUESTS, REQUEST_RATE_PER_HOUR } from "./backtest-requests.js";
|
|
9
15
|
// task-1406 + task-1421: the spectator sink the tool-call path writes to when a spectator surface is open
|
|
10
16
|
// (via DEXTERM_SPECTATOR_FILE, or the ~/.dexterm rendezvous an external `dexterm mcp` client uses).
|
|
11
17
|
export { recordForToolCall, maxAgeSec, fileSpectatorSinkFromEnv, resolveSpectatorSink, rendezvousPath, MCP_SPECTATOR_RENDEZVOUS, MCP_FOLLOW_SCREEN, FOLLOW_NAV_ACTIONS, followScreenPath, readFollowScreen, writeFollowScreen, clearFollowScreen, } from "./spectator-sink.js";
|