@coinrithm/mcp-trading 0.7.8 → 0.7.10

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/README.md +93 -69
  3. package/dist/agent/capitalSizing.js +17 -4
  4. package/dist/agent/cli.js +11 -1
  5. package/dist/agent/client.d.ts +8 -1
  6. package/dist/agent/client.js +98 -39
  7. package/dist/agent/configurationWarnings.d.ts +1 -0
  8. package/dist/agent/configurationWarnings.js +21 -0
  9. package/dist/agent/decisionReceipt.d.ts +4 -1
  10. package/dist/agent/decisionReceipt.js +27 -3
  11. package/dist/agent/decisionValidator.js +4 -0
  12. package/dist/agent/engine.d.ts +1 -1
  13. package/dist/agent/engine.js +1 -1
  14. package/dist/agent/entryPredicates.d.ts +10 -0
  15. package/dist/agent/entryPredicates.js +67 -0
  16. package/dist/agent/gate.js +14 -11
  17. package/dist/agent/opportunityReporter.d.ts +16 -0
  18. package/dist/agent/opportunityReporter.js +38 -0
  19. package/dist/agent/prompt.js +5 -0
  20. package/dist/agent/providers.d.ts +2 -1
  21. package/dist/agent/providers.js +109 -19
  22. package/dist/agent/reconcileObservation.d.ts +2 -0
  23. package/dist/agent/reconcileObservation.js +33 -0
  24. package/dist/agent/runner.js +32 -74
  25. package/dist/agent/skill.js +6 -0
  26. package/dist/agent/skillValidator.js +3 -0
  27. package/dist/agent/state.js +17 -2
  28. package/dist/agent/strictLint.js +1 -0
  29. package/dist/agent/templates.js +34 -30
  30. package/dist/agent/types.d.ts +1 -0
  31. package/dist/agent/util.js +3 -3
  32. package/dist/client.js +3 -2
  33. package/dist/http.d.ts +7 -1
  34. package/dist/http.js +36 -16
  35. package/dist/httpCompletion.d.ts +33 -0
  36. package/dist/httpCompletion.js +220 -0
  37. package/dist/retryAfter.d.ts +1 -0
  38. package/dist/retryAfter.js +16 -0
  39. package/dist/tools.js +19 -1
  40. package/package.json +13 -2
package/CHANGELOG.md CHANGED
@@ -5,6 +5,127 @@ ships two binaries — `coinrithm-mcp` (the MCP server) and `coinrithm-agent` (t
5
5
  self-host agent runner) — versioned together. The CoinRithm **API contract** is
6
6
  versioned separately (see `openapi.yaml` `info.version`, currently `1.7.0`).
7
7
 
8
+ ## 0.7.10 — 2026-09-15
9
+
10
+ Source changes following the published 0.7.9 release. The TypeScript SDK remains
11
+ 0.3.1 and Python remains 1.8.1; their runtime source is unchanged.
12
+
13
+ - Persist file-backed run identity before execution so a first-cycle process
14
+ crash cannot discard the idempotency identity. Transport uncertainty is still
15
+ not automatically replayed or recorded as a completed trade.
16
+ - Fix runner startup on Node 18: use the imported Node crypto API instead of
17
+ depending on a global crypto object. The installed-package matrix reproduced
18
+ this failure on Linux, Windows and macOS.
19
+ - Add the supported `@coinrithm/mcp-trading/engine` entry point, preserving
20
+ existing deep imports, and separate observation accounting and opportunity
21
+ reporting from cycle ordering.
22
+ - Add opt-in, machine-checked crypto return predicates and visible warnings for
23
+ inactive/reserved configuration. Existing agents are not automatically opted in.
24
+ - Serialize scheduler migrations in a bounded transaction; add an offline
25
+ credential-rotation helper and interruption/recovery rehearsal.
26
+ - Pin workflow actions and verify release-tool checksums. Add installed-package
27
+ compatibility and restart smoke checks across operating systems and runtimes.
28
+
29
+ Source/CI checks, registry publication and production deployment are separate.
30
+ This entry does not claim that 0.7.10 is published or deployed.
31
+
32
+ ## 0.7.9 - 2026-09-15
33
+
34
+ Published on npm and verified on 2026-09-15: the registry archive matches the
35
+ reviewed artifact and passes fresh-install checks. See the
36
+ [combined release notes](https://github.com/CoinRithm/coinrithm-agent-trading/releases/tag/mcp-trading-v0.7.9)
37
+ for source provenance, verification and community acknowledgments.
38
+
39
+ Public market-data fidelity and runner reliability release. No MCP tool was
40
+ renamed or removed, and the API **contract stays 1.7.0**.
41
+
42
+ **PM evaluation budget.** Event-driven periodic prediction-market evaluations
43
+ now respect `maxLlmCallsPerHour` after their cooldown elapses. Budget skips make
44
+ no provider call and consume no call allowance. PM keeps its own cooldown;
45
+ open-position management and explicit always-on behavior retain their existing
46
+ exemptions. This runner gate is separate from hosted provider-capacity admission.
47
+
48
+ **Retry-After parsing.** Missing, blank or malformed headers no longer become
49
+ zero-delay retries. The runner API client uses its existing five-second fallback;
50
+ explicit zero, numeric seconds and HTTP dates remain supported. Model-provider
51
+ cooldowns share the parser and retain their existing one-hour cap.
52
+
53
+ **API request deadlines.** Each runner API operation now has a 30-second total
54
+ deadline covering response headers, body reads and all 429 retry waits. The
55
+ same client serves the hosted scheduler. Embedded callers can set a finite
56
+ `requestTimeoutMs` and supply an `AbortSignal`. A timeout or cancellation returns
57
+ an uncertain transport result without automatically replaying a trading write.
58
+ Timers and listeners are removed when the operation finishes.
59
+
60
+ **State persistence.** Self-host state is serialized to a private temporary file
61
+ and atomically renamed over the previous state. A failed serialization or rename
62
+ leaves the prior state intact. This is atomic replacement, not a claim of durable
63
+ storage across power loss.
64
+
65
+ **Agent conversion.** `coinrithm-agent eject` preserves explicit `triggerPolicy`
66
+ and `capitalSizing` blocks. Previously conversion could restore default hourly
67
+ budgets and drop equity sizing.
68
+
69
+ **Release verification.** All-source coverage gates, mandatory PostgreSQL CI,
70
+ dependency updates and corrected client setup docs are included. See the
71
+ [reliability record](https://github.com/CoinRithm/coinrithm-agent-trading/blob/main/docs/RELIABILITY.md).
72
+
73
+ **Confirmed-action journal.** Completed-action memory now requires an action
74
+ to be both accepted and executed. Failed writes and uncertain transport results
75
+ retain their attempt evidence without becoming completed moves in the next
76
+ decision prompt. Dry-run proposals remain unexecuted.
77
+
78
+ **Direct NVIDIA retry.** One complete HTTP 500/502/503/504 response can be
79
+ retried once on the identical direct NVIDIA route within the original deadline.
80
+ Both attempts are retained. This does not retry trading writes or change the
81
+ hosted shared-pool routing policy.
82
+
83
+ **Capital reconciliation.** Frozen-balance rounding residue down to -1e-8 is
84
+ normalized only in the sizing calculation after the independent reads agree.
85
+ Negative spendable cash still fails closed; wallet balances are not changed.
86
+
87
+ **Private decision input evidence.** The bounded numeric projection includes
88
+ nested indicator inputs and context movers, with legacy v1 records still readable.
89
+ It does not retain hidden reasoning or raw model output.
90
+
91
+ **Compact prediction-market evidence.** Discovery and compact event-detail
92
+ responses now retain the API's `source.quoteScale`, `source.methodology` and
93
+ `source.supportsMarketMetrics`, plus `spreadPoints`, `probabilityBook` and
94
+ each retained outcome's `normalizedProbability`. Venue-native bid/ask quotes
95
+ are never rescaled or interpreted from magnitude. Normalization remains the
96
+ API's calculation over the original full book, not the truncated top-five
97
+ outcome list. Existing payload bounds and explicit `detail: full` behavior
98
+ are unchanged.
99
+
100
+ **Settlement-time provenance.** Compact events retain `resolvedAtBasis` and
101
+ `settlementWindowClosedAt`, keeping provider expiration distinct from an
102
+ announced settlement time. Null and absent upstream evidence stay null and
103
+ absent; the MCP does not infer missing values.
104
+
105
+ **Candle semantics.** The `get_candles` description now states that these are
106
+ sampled composite-price bars. Each bar's `v` is a mean rolling 24-hour
107
+ quote-volume observation in USD, not volume traded during the candle, and
108
+ must not be summed across bars.
109
+
110
+ **HTTP completion diagnostics.** The hosted HTTP
111
+ entry now has a bounded, stderr-only completion observer with final SDK-result
112
+ and finish/abort accounting. Initialization, discovery, tool failures and
113
+ successful delivery are distinct; unknown tool names are normalized. Records
114
+ contain no arguments, bodies, credentials, caller/RPC IDs or caller-origin labels.
115
+ Credential presence is not authentication. Durations describe the HTTP request,
116
+ shared by batch members; server finish does not prove client receipt or use.
117
+ Stdio, tools, authentication and dependency versions are unchanged. See
118
+ `DEPLOY.md` for the measurement and retention limits. Hosted source/image
119
+ `18a0bb6a8a0665e91cebc10225fec6f7ebcdaaf7` passed a bounded anonymous smoke on
120
+ 2026-09-13. Hosted verification and npm publication are separate release steps.
121
+
122
+ **Deployment boundaries.** Hosted scheduler admission reasons are private
123
+ scheduler telemetry, not a new SDK or MCP response field. The API's corrected
124
+ comparison probabilities and enriched spread names use the existing response
125
+ shape and reach current clients through fresh API reads. Outcome display names
126
+ may change; use source/event/outcome identifiers for identity, never summed
127
+ prices or matching labels alone. These fixes do not establish trading returns.
128
+
8
129
  ## 0.7.8
9
130
 
10
131
  Runner decision-quality, evidence and paper-capital release. Additive: no MCP
package/README.md CHANGED
@@ -4,16 +4,18 @@
4
4
  (Claude, GPT, Gemini, Llama…) a 50,000 mUSD virtual account and let it trade
5
5
  spot, futures, and prediction markets on
6
6
  [CoinRithm](https://coinrithm.com/agentic-trading). No real money, no exchange,
7
- no risk — a proving ground to show an agent works *before* anything is on the
8
- line, with a public **Agent Arena** leaderboard using a versioned,
9
- confidence-weighted realized-PnL methodology.
7
+ with virtual funds and a public **Agent Arena** leaderboard using a versioned,
8
+ confidence-weighted realized-PnL methodology. Paper results do not establish
9
+ future returns or live execution performance.
10
10
 
11
11
  **Plus a free prediction-market data surface — no key at all.** The same server
12
12
  ships ten keyless `pm_data_*` tools serving CoinRithm's public cross-venue
13
- dataset: live odds across 12 venues (Polymarket, Kalshi, Smarkets, Limitless,
14
- Manifold, Metaculus, PredictIt, Rothera, Futuur, Myriad, ForecastEx, Gemini), cross-venue matches with a
15
- liquidity-aware reference probability, a whale-trade tape, and market-wide
16
- volume stats ($90B+ all-time tracked). Point any MCP client at the hosted
13
+ dataset: odds, cross-venue matches with a liquidity-aware reference probability,
14
+ a whale-trade tape, and market-wide volume statistics. Availability and freshness
15
+ vary by source; inspect the returned source-health and observation metadata.
16
+ The catalog covers 12 venues: Polymarket, Kalshi, Smarkets, Limitless, Manifold,
17
+ Metaculus, PredictIt, Rothera, Futuur, Myriad, ForecastEx and Gemini.
18
+ Point an MCP client that supports Streamable HTTP at the hosted
17
19
  endpoint `https://mcp.coinrithm.com/mcp` and call them anonymously — the API
18
20
  key is only needed for the trading tools.
19
21
 
@@ -23,8 +25,9 @@ Agents are **OKF bundles** — an open, model-agnostic folder of markdown + YAML
23
25
 
24
26
  - **Managed — nothing to install.** Build and deploy an agent in your browser
25
27
  with the **Agent Studio** (CoinRithm → My Agents → Studio): fork a house agent
26
- or write one from scratch, and CoinRithm runs it **free on Nemotron 3 Nano 30B**
27
- (NVIDIA NIM) on an always-on scheduler. The fastest path to a live agent.
28
+ or write one from scratch, and CoinRithm runs it on an always-on scheduler.
29
+ Studio shows the configured model; shared-pool routing can use another
30
+ eligible model. Check each agent's configuration and run evidence.
28
31
  - **Self-host — this package.** Bring your own model key and run the
29
32
  `observe→decide→validate→act` loop on your machine, or wire the MCP server
30
33
  into Claude Desktop / Cursor / Codex.
@@ -39,6 +42,24 @@ This package ships two binaries:
39
42
 
40
43
  > **Paper trading only** — virtual funds (50,000 mUSD). Not financial advice.
41
44
 
45
+ ## Version 0.7.10
46
+
47
+ This source version adds restart identity persistence, a supported engine
48
+ import, opt-in entry predicates and configuration warnings. It also fixes
49
+ runner startup on Node 18 by importing the Node crypto API explicitly. See
50
+ [CHANGELOG.md](./CHANGELOG.md). Check `npm view @coinrithm/mcp-trading
51
+ version` for the latest published version. Hosted deployments and npm releases
52
+ are separate.
53
+
54
+ Runner API operations have a 30-second total deadline, including response
55
+ bodies and 429 retry waits. Timeout and cancellation results remain unconfirmed;
56
+ the client does not automatically replay an uncertain trading write.
57
+
58
+ Embedding the runner? Import from `@coinrithm/mcp-trading/engine` for the
59
+ supported engine and state helpers. Existing `dist/agent/engine.js` imports
60
+ remain compatible. See the [entry conditions and engine guide](https://github.com/CoinRithm/coinrithm-agent-trading/blob/main/docs/agent-runner.md#binding-entry-conditions-and-strategy-prose)
61
+ for the exact opt-in policy and persistence contract.
62
+
42
63
  ## Quick start
43
64
 
44
65
  ```bash
@@ -48,13 +69,15 @@ COINRITHM_API_KEY=crk_live_… npx -y @coinrithm/mcp-trading
48
69
 
49
70
  Get a `crk_live_…` key from CoinRithm → Profile → API Keys. To author and run a
50
71
  self-host agent instead, see [Agent runner](#agent-runner-coinrithm-agent).
51
- Building from source? `npm install && npm run build`.
72
+ Building from source? Use Node 20.19+ or 22.12+, then `npm ci && npm run build`.
73
+ Run `npm run test:coverage` for the enforced 90% statement, branch, function,
74
+ and line gates. See the [coverage scope and reliability checks](https://github.com/CoinRithm/coinrithm-agent-trading/blob/main/docs/RELIABILITY.md).
52
75
 
53
76
  ## Agent runner (`coinrithm-agent`)
54
77
 
55
78
  This package also ships a **self-host agent runner**. You write an agent as a
56
79
  folder (strategy + hard caps in markdown/YAML); the runner compiles it and runs
57
- an `observe → decide → validate → act` loop, asking *your* model (bring-your-own
80
+ an `observe → decide → validate → act` loop, asking _your_ model (bring-your-own
58
81
  key) for structured decisions and executing only the ones that pass your caps —
59
82
  **dry-run by default**, paper-only across spot, futures, and prediction markets.
60
83
 
@@ -68,15 +91,15 @@ COINRITHM_API_KEY=crk_live_… ANTHROPIC_API_KEY=sk-ant-… \
68
91
  Full guide (env vars, fail-closed guarantees, folder layout):
69
92
  **[docs/agent-runner.md](https://github.com/CoinRithm/coinrithm-agent-trading/blob/main/docs/agent-runner.md)**.
70
93
  The CoinRithm hosted scheduler runs this same engine for you — see the
71
- [scheduler README](../../packages/scheduler/README.md) for the built,
94
+ [scheduler README](https://github.com/CoinRithm/coinrithm-agent-trading/blob/main/packages/scheduler/README.md) for the built,
72
95
  DB-driven runtime.
73
96
 
74
97
  ## Two ways to run
75
98
 
76
- | Mode | Entry | Auth | Who it's for |
77
- | --- | --- | --- | --- |
78
- | **stdio** (single-user, local) | `dist/index.js` | `COINRITHM_API_KEY` env var | Claude Desktop / Cursor / Codex on your machine |
79
- | **Streamable HTTP** (multi-user, hosted) | `dist/http.js` | **per-request** `Authorization: Bearer` header | The shared hosted endpoint at `mcp.coinrithm.com` |
99
+ | Mode | Entry | Auth | Who it's for |
100
+ | ---------------------------------------- | --------------- | ---------------------------------------------- | ------------------------------------------------- |
101
+ | **stdio** (single-user, local) | `dist/index.js` | `COINRITHM_API_KEY` env var | Claude Desktop / Cursor / Codex on your machine |
102
+ | **Streamable HTTP** (multi-user, hosted) | `dist/http.js` | **per-request** `Authorization: Bearer` header | The shared hosted endpoint at `mcp.coinrithm.com` |
80
103
 
81
104
  The hosted HTTP server holds **no** key: each request brings its own
82
105
  `crk_live_…` in the Authorization header, and the server forwards exactly that
@@ -89,15 +112,16 @@ tool requires it. See [`DEPLOY.md`](./DEPLOY.md).
89
112
  The hosted Agent Studio runs your agent free on a shared pool of NVIDIA-hosted
90
113
  models. That pool is a **fixed budget shared by every hosted agent**, so the
91
114
  scheduler floors how often a shared agent may run, and the floor stretches as
92
- more agents join. Bringing your own model key removes that floor entirely:
93
- your quota is yours, so there is nothing for us to ration.
115
+ more agents join. Bringing your own model key removes the shared-pool interval
116
+ floor. Provider quotas, execution time, trigger policies and account protections
117
+ still apply.
94
118
 
95
- | | Shared free pool | Your own key |
96
- | --- | --- | --- |
97
- | Models | the free hosted picks | any model your provider serves |
98
- | Interval | floored by fleet size | exactly what you configure |
99
- | Rerouting | we may serve a live alternate when a model is rate-limited | never rerouted, your route is pinned |
100
- | Cost | free | you pay your provider, not CoinRithm |
119
+ | | Shared free pool | Your own key |
120
+ | --------- | ---------------------------------------------------------- | ------------------------------------------------------------ |
121
+ | Models | the free hosted picks | any model your provider serves |
122
+ | Interval | floored by fleet size | configured interval after completion, subject to other gates |
123
+ | Rerouting | we may serve a live alternate when a model is rate-limited | never rerouted, your route is pinned |
124
+ | Cost | free | you pay your provider, not CoinRithm |
101
125
 
102
126
  Providers accepted: `nvidia`, `openai`, `groq`, `anthropic`, and any
103
127
  `openai-compatible` endpoint (https base URL required). The key is validated by
@@ -113,11 +137,11 @@ agent file.
113
137
 
114
138
  ## Configure (stdio)
115
139
 
116
- | Env var | Required | Default | Notes |
117
- | --- | --- | --- | --- |
118
- | `COINRITHM_API_KEY` | yes (stdio only) | — | A `crk_live_…` key from CoinRithm → Profile → API Keys. **Ignored by the HTTP entry.** |
119
- | `COINRITHM_API_URL` | no | `https://api.coinrithm.com` | Upstream base URL (live) |
120
- | `PORT` | no | `8787` | HTTP entry only |
140
+ | Env var | Required | Default | Notes |
141
+ | ------------------- | ---------------- | --------------------------- | -------------------------------------------------------------------------------------- |
142
+ | `COINRITHM_API_KEY` | yes (stdio only) | — | A `crk_live_…` key from CoinRithm → Profile → API Keys. **Ignored by the HTTP entry.** |
143
+ | `COINRITHM_API_URL` | no | `https://api.coinrithm.com` | Upstream base URL (live) |
144
+ | `PORT` | no | `8787` | HTTP entry only |
121
145
 
122
146
  ## Run
123
147
 
@@ -136,46 +160,46 @@ agent file.
136
160
 
137
161
  ## Tools
138
162
 
139
- | Tool | Scope | Wraps |
140
- | --- | --- | --- |
141
- | `whoami` | any | `GET /api/agent/me` |
142
- | `get_portfolio` | read | `GET /api/agent/portfolio` |
143
- | `get_wallet` | read | `GET /api/agent/wallet` |
144
- | `resolve_symbol` | read | `GET /api/agent/resolve` |
145
- | `get_equity_curve` | read | `GET /api/agent/equity-curve` |
146
- | `get_my_trades` (venue) | read | `GET /api/agent/trades` |
147
- | `get_market_context` (coinId) | read | `GET /api/agent/market/:coinId` |
148
- | `get_candles` (coinId, range) | read | `GET /api/agent/market/:coinId/candles` |
149
- | `discover_pm_markets` | read | `GET /api/agent/pm/discover` |
150
- | `get_performance` | read | `GET /api/agent/performance` |
151
- | `get_agent_ledger` | read | `GET /api/agent/ledger` |
152
- | `export_agent_ledger` | read | `GET /api/agent/ledger/export` |
153
- | `export_run_evidence` | read | `GET /api/agent/ledger/export?runId=...` |
154
- | `get_arena_leaderboard` | read | `GET /api/arena` |
155
- | `get_arena_agent` (handle) | read | `GET /api/arena/:handle` |
156
- | `list_open_orders` | read | `GET /api/agent/orders/open` |
157
- | `get_positions` (venue) | read | `GET /api/agent/positions/{futures,pm}` |
158
- | `spot_quote` | read | `POST /api/agent/spot/quote` |
159
- | `futures_quote` | read | `POST /api/agent/futures/quote` |
160
- | `pm_quote` | read | `POST /api/agent/pm/quote` |
161
- | `place_spot_order` | trade:spot | `POST /api/agent/spot/order` |
162
- | `cancel_spot_order` | trade:spot | `POST /api/agent/spot/order/:id/cancel` |
163
- | `open_futures_position` | trade:futures | `POST /api/agent/futures/open` ¹ |
164
- | `set_futures_sl_tp` | trade:futures | `POST /api/agent/futures/sl-tp` ² |
165
- | `close_futures_position` | trade:futures | `POST /api/agent/futures/close` |
166
- | `open_pm_position` | trade:pm | `POST /api/agent/pm/open` ¹ |
167
- | `report_pm_opportunity` | read | `POST /api/agent/pm/opportunity` |
168
- | `pm_data_overview` | none (public) | compact `GET /api/prediction-markets/overview` |
169
- | `pm_data_sources` | none (public) | venue methodology, coverage, and comparable volume bases |
170
- | `pm_data_sources_health` | none (public) | per-venue freshness, lag, and degraded reasons |
171
- | `pm_data_events` | none (public) | compact `GET /api/prediction-markets/events` |
172
- | `pm_data_event` (source, slug, detail?) | none (public) | bounded event evidence by default; `detail: "full"` returns the untouched API record |
173
- | `pm_data_whales` (limit, default 10) | none (public) | compact `GET /api/prediction-markets/whales` |
174
- | `pm_data_disagreements` (limit, sort, sourceKind, ...) | none (public) | compact `GET /api/prediction-markets/matches/public` |
175
- | `pm_data_calibration` | none (public) | `GET /api/prediction-markets/calibration` |
176
- | `pm_data_canonical` (key?, limit, cursor) | none (public) | `GET /api/prediction-markets/canonical` (+ `/:key` detail) |
177
- | `pm_data_volume_history` | none (public) | `GET /api/prediction-markets/volume-history` |
178
- | `get_crypto_movers` (direction, limit) | none (public) | `GET /api/coins/top-{gainers,losers}` |
163
+ | Tool | Scope | Wraps |
164
+ | ------------------------------------------------------ | ------------- | ------------------------------------------------------------------------------------ |
165
+ | `whoami` | any | `GET /api/agent/me` |
166
+ | `get_portfolio` | read | `GET /api/agent/portfolio` |
167
+ | `get_wallet` | read | `GET /api/agent/wallet` |
168
+ | `resolve_symbol` | read | `GET /api/agent/resolve` |
169
+ | `get_equity_curve` | read | `GET /api/agent/equity-curve` |
170
+ | `get_my_trades` (venue) | read | `GET /api/agent/trades` |
171
+ | `get_market_context` (coinId) | read | `GET /api/agent/market/:coinId` |
172
+ | `get_candles` (coinId, range) | read | `GET /api/agent/market/:coinId/candles` |
173
+ | `discover_pm_markets` | read | `GET /api/agent/pm/discover` |
174
+ | `get_performance` | read | `GET /api/agent/performance` |
175
+ | `get_agent_ledger` | read | `GET /api/agent/ledger` |
176
+ | `export_agent_ledger` | read | `GET /api/agent/ledger/export` |
177
+ | `export_run_evidence` | read | `GET /api/agent/ledger/export?runId=...` |
178
+ | `get_arena_leaderboard` | read | `GET /api/arena` |
179
+ | `get_arena_agent` (handle) | read | `GET /api/arena/:handle` |
180
+ | `list_open_orders` | read | `GET /api/agent/orders/open` |
181
+ | `get_positions` (venue) | read | `GET /api/agent/positions/{futures,pm}` |
182
+ | `spot_quote` | read | `POST /api/agent/spot/quote` |
183
+ | `futures_quote` | read | `POST /api/agent/futures/quote` |
184
+ | `pm_quote` | read | `POST /api/agent/pm/quote` |
185
+ | `place_spot_order` | trade:spot | `POST /api/agent/spot/order` |
186
+ | `cancel_spot_order` | trade:spot | `POST /api/agent/spot/order/:id/cancel` |
187
+ | `open_futures_position` | trade:futures | `POST /api/agent/futures/open` ¹ |
188
+ | `set_futures_sl_tp` | trade:futures | `POST /api/agent/futures/sl-tp` ² |
189
+ | `close_futures_position` | trade:futures | `POST /api/agent/futures/close` |
190
+ | `open_pm_position` | trade:pm | `POST /api/agent/pm/open` ¹ |
191
+ | `report_pm_opportunity` | read | `POST /api/agent/pm/opportunity` |
192
+ | `pm_data_overview` | none (public) | compact `GET /api/prediction-markets/overview` |
193
+ | `pm_data_sources` | none (public) | venue methodology, coverage, and comparable volume bases |
194
+ | `pm_data_sources_health` | none (public) | per-venue freshness, lag, and degraded reasons |
195
+ | `pm_data_events` | none (public) | compact `GET /api/prediction-markets/events` |
196
+ | `pm_data_event` (source, slug, detail?) | none (public) | bounded event evidence by default; `detail: "full"` returns the untouched API record |
197
+ | `pm_data_whales` (limit, default 10) | none (public) | compact `GET /api/prediction-markets/whales` |
198
+ | `pm_data_disagreements` (limit, sort, sourceKind, ...) | none (public) | compact `GET /api/prediction-markets/matches/public` |
199
+ | `pm_data_calibration` | none (public) | `GET /api/prediction-markets/calibration` |
200
+ | `pm_data_canonical` (key?, limit, cursor) | none (public) | `GET /api/prediction-markets/canonical` (+ `/:key` detail) |
201
+ | `pm_data_volume_history` | none (public) | `GET /api/prediction-markets/volume-history` |
202
+ | `get_crypto_movers` (direction, limit) | none (public) | `GET /api/coins/top-{gainers,losers}` |
179
203
 
180
204
  `get_crypto_movers` is the universe scan: the biggest 24h movers across every
181
205
  coin CoinRithm tracks, so an agent can find candidates it was never configured
@@ -8,6 +8,11 @@ export const CAPITAL_VALUATION_BASIS = "wallet_assets_spot_marked_futures_pm_at_
8
8
  // This is not an exchange-fill, funding or stop-execution guarantee.
9
9
  export const CAPITAL_FEE_BUFFER_BPS = 10;
10
10
  const CENT_TOLERANCE = 0.011;
11
+ // Paper settlement writers use EPS=1e-8 on floating-point frozen balances.
12
+ // Thawing the final position can leave negative dust (observed: -6.82e-13).
13
+ // Normalize only that bounded frozen residue, never spendable cash or debt.
14
+ // This is much tighter than reconciliation tolerance and does not edit balances.
15
+ const FROZEN_RESIDUE_TOLERANCE = 1e-8;
11
16
  const centsDown = (n) => Math.floor(n * 100) / 100;
12
17
  const positive = (n) => asNum(n) !== undefined && n > 0;
13
18
  const nonnegative = (n) => asNum(n) !== undefined && n >= 0;
@@ -18,7 +23,8 @@ const nonnegative = (n) => asNum(n) !== undefined && n >= 0;
18
23
  * for management; only explicitly attributed current-book rows reconcile its
19
24
  * cash and marks. Closed history never contributes unrealized. */
20
25
  export function deriveCapitalBook(portfolio, wallet, futures, pm) {
21
- const p = asObj(portfolio), w = asObj(wallet), eq = asObj(p.equity), cash = asObj(w.usdt);
26
+ const p = asObj(portfolio), w = asObj(wallet), eq = asObj(p.equity), rawCash = asObj(w.usdt);
27
+ const cash = { ...rawCash };
22
28
  const unavailable = (reason) => ({
23
29
  status: "unavailable",
24
30
  reason,
@@ -35,10 +41,17 @@ export function deriveCapitalBook(portfolio, wallet, futures, pm) {
35
41
  return unavailable("held_spot_valuation_unproven");
36
42
  const buckets = ["available", "frozen", "frozenPm", "frozenFutures"];
37
43
  for (const key of buckets) {
38
- if (!nonnegative(cash[key]) ||
39
- !nonnegative(eq[key]) ||
40
- Math.abs(cash[key] - eq[key]) > CENT_TOLERANCE)
44
+ const walletValue = asNum(rawCash[key]);
45
+ const portfolioValue = asNum(eq[key]);
46
+ const minimum = key === "available" ? 0 : -FROZEN_RESIDUE_TOLERANCE;
47
+ if (walletValue === undefined ||
48
+ portfolioValue === undefined ||
49
+ walletValue < minimum ||
50
+ portfolioValue < minimum ||
51
+ // Compare raw reads first: normalization must not hide snapshot drift.
52
+ Math.abs(walletValue - portfolioValue) > CENT_TOLERANCE)
41
53
  return unavailable("cash_partitions_incomplete_or_changed");
54
+ cash[key] = Math.max(0, walletValue);
42
55
  }
43
56
  const cashTotal = buckets.reduce((sum, k) => sum + cash[k], 0);
44
57
  if (eq.totalUsd + CENT_TOLERANCE < cashTotal)
package/dist/agent/cli.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { configurationWarnings } from "./configurationWarnings.js";
1
2
  // coinrithm-agent — the public scaffolder/inspector CLI.
2
3
  //
3
4
  // Authors, validates, ejects, locks, and inspects agent DEFINITIONS. It does
@@ -101,6 +102,7 @@ export function cmdValidate(path, mode = "self-host") {
101
102
  const spec = buildSpec(raw);
102
103
  const lint = [...strictLint(raw), ...checkCapabilityDrift(resolved, spec)];
103
104
  const v = validateSkill({ spec, body: resolved.mergedProse, raw }, mode);
105
+ const warnings = configurationWarnings(raw);
104
106
  // Hosted-only: the managed deploy/edit API caps the merged strategy prose at
105
107
  // HOSTED_PROSE_MAX_CHARS and REVERTS the save when it is exceeded, so a
106
108
  // bundle that resolves and lints perfectly can still be undeployable through
@@ -129,10 +131,16 @@ export function cmdValidate(path, mode = "self-host") {
129
131
  }
130
132
  for (const i of v.issues)
131
133
  lines.push(`✗ ${i.code}: ${i.reason}`);
134
+ lines.push(...warnings.map((warning) => `⚠ ${warning}`));
132
135
  lines.push(...pinWarnings(path));
133
136
  const ok = v.valid && (!lintFatal || lint.length === 0);
134
137
  lines.unshift(ok ? `✓ valid (${mode})` : `✗ invalid (${mode})`);
135
- return { ok, code: ok ? 0 : 1, lines, data: { lint, validation: v } };
138
+ return {
139
+ ok,
140
+ code: ok ? 0 : 1,
141
+ lines,
142
+ data: { lint, validation: v, warnings },
143
+ };
136
144
  }
137
145
  export function cmdLock(path) {
138
146
  const v = cmdValidate(path, "self-host");
@@ -215,6 +223,7 @@ export function cmdInspect(path, json = false) {
215
223
  ];
216
224
  const v = validateSkill({ spec, body: resolved.mergedProse, raw: resolved.rawFrontmatter }, "self-host");
217
225
  const output = {
226
+ warnings: configurationWarnings(resolved.rawFrontmatter),
218
227
  resolvedConfig: resolved.rawFrontmatter,
219
228
  provenance: resolved.provenance,
220
229
  contentHashes: resolved.contentHashes,
@@ -236,6 +245,7 @@ export function cmdInspect(path, json = false) {
236
245
  `risk: maxLeverage=${spec.risk.maxLeverage} perTradeMargin=${spec.risk.perTradeMarginMusd} requireStopLoss=${spec.risk.requireStopLoss}`,
237
246
  `sources: ${Object.keys(resolved.contentHashes).length} file(s)`,
238
247
  `validation: ${v.valid ? "valid" : "INVALID"}${lint.length ? ` (+${lint.length} lint note(s))` : ""}`,
248
+ ...output.warnings.map((warning) => `⚠ ${warning}`),
239
249
  ];
240
250
  return { ok: v.valid, code: 0, lines, data: output };
241
251
  }
@@ -1,5 +1,6 @@
1
1
  import { AgentTrace, ApiResult } from "./types.js";
2
2
  export declare const DEFAULT_BASE_URL = "https://api.coinrithm.com";
3
+ export declare const DEFAULT_REQUEST_TIMEOUT_MS = 30000;
3
4
  export type ProvenanceReport = {
4
5
  runtimeKind?: "hosted_scheduler" | "self_host_runner" | "byo_api" | "mcp_tool";
5
6
  packageVersion?: string;
@@ -21,14 +22,20 @@ export interface ClientConfig {
21
22
  fetchFn?: typeof fetch;
22
23
  sleepFn?: (ms: number) => Promise<void>;
23
24
  maxRetries?: number;
25
+ /** Total deadline, including response bodies and all 429 retry waits. */
26
+ requestTimeoutMs?: number;
27
+ /** Optional caller cancellation, applied to each request from this client. */
28
+ signal?: AbortSignal;
24
29
  extraHeaders?: Record<string, string>;
25
30
  }
26
31
  export declare class CoinRithmClient {
27
32
  private readonly apiKey;
28
33
  private readonly baseUrl;
29
34
  private readonly fetchFn;
30
- private readonly sleepFn;
35
+ private readonly sleepFn?;
31
36
  private readonly maxRetries;
37
+ private readonly requestTimeoutMs;
38
+ private readonly signal?;
32
39
  private readonly extraHeaders?;
33
40
  rateLimitHits: number;
34
41
  constructor(cfg: ClientConfig);