@coinrithm/mcp-trading 0.7.11 → 0.7.13
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/CHANGELOG.md +573 -531
- package/README.md +364 -345
- package/dist/agent/act.js +37 -1
- package/dist/agent/client.d.ts +4 -0
- package/dist/agent/decision.d.ts +12 -12
- package/dist/agent/engine.d.ts +1 -1
- package/dist/agent/engine.js +1 -1
- package/dist/agent/observe.js +34 -4
- package/dist/agent/prompt.js +4 -0
- package/dist/agent/providers.d.ts +4 -0
- package/dist/agent/providers.js +16 -10
- package/dist/agent/runner.js +2 -1
- package/dist/agent/templates.js +30 -30
- package/dist/agent/types.d.ts +14 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.js +43 -0
- package/dist/httpCompletion.d.ts +1 -1
- package/dist/httpCompletion.js +2 -0
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +251 -48
- package/package.json +97 -97
package/dist/agent/act.js
CHANGED
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
// Act phase: fetch the quote evidence for an open (the runner does this, never
|
|
2
2
|
// the model) and execute a validated action (futures / spot / PM) with an
|
|
3
3
|
// idempotency key.
|
|
4
|
-
import { asObj, asNum } from "./extract.js";
|
|
4
|
+
import { asObj, asNum, asStr } from "./extract.js";
|
|
5
5
|
import { freshnessOf } from "./pmContext.js";
|
|
6
|
+
function fundingQuoteEvidence(value) {
|
|
7
|
+
if (value === null)
|
|
8
|
+
return null;
|
|
9
|
+
if (typeof value !== "object" || value === null)
|
|
10
|
+
return undefined;
|
|
11
|
+
const f = asObj(value);
|
|
12
|
+
const estimatedPerIntervalMusd = Object.prototype.hasOwnProperty.call(f, "estimatedPerIntervalMusd")
|
|
13
|
+
? (asNum(f.estimatedPerIntervalMusd) ??
|
|
14
|
+
(f.estimatedPerIntervalMusd === null ? null : undefined))
|
|
15
|
+
: undefined;
|
|
16
|
+
return {
|
|
17
|
+
...(asStr(f.venue) !== undefined ? { venue: asStr(f.venue) } : {}),
|
|
18
|
+
...(asStr(f.symbol) !== undefined ? { symbol: asStr(f.symbol) } : {}),
|
|
19
|
+
...(asNum(f.rate) !== undefined ? { rate: asNum(f.rate) } : {}),
|
|
20
|
+
...(asNum(f.intervalHours) !== undefined
|
|
21
|
+
? { intervalHours: asNum(f.intervalHours) }
|
|
22
|
+
: {}),
|
|
23
|
+
...(asStr(f.nextFundingTime) !== undefined
|
|
24
|
+
? { nextFundingTime: asStr(f.nextFundingTime) }
|
|
25
|
+
: {}),
|
|
26
|
+
...(asStr(f.asOf) !== undefined ? { asOf: asStr(f.asOf) } : {}),
|
|
27
|
+
...(estimatedPerIntervalMusd !== undefined
|
|
28
|
+
? { estimatedPerIntervalMusd }
|
|
29
|
+
: {}),
|
|
30
|
+
...(asNum(f.annualizedRate) !== undefined
|
|
31
|
+
? { annualizedRate: asNum(f.annualizedRate) }
|
|
32
|
+
: {}),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
6
35
|
function coinIdFor(observation, symbol) {
|
|
7
36
|
return (observation.watch.find((w) => w.symbol.toUpperCase() === symbol.toUpperCase())?.coinId ?? undefined);
|
|
8
37
|
}
|
|
@@ -32,6 +61,9 @@ export async function fetchQuote(client, action, observation, trace) {
|
|
|
32
61
|
slug: action.slug,
|
|
33
62
|
outcomeExternalMarketId: action.outcomeExternalMarketId,
|
|
34
63
|
stakeMusd: action.stakeMusd,
|
|
64
|
+
...(action.forecastProbability != null
|
|
65
|
+
? { forecastProbability: action.forecastProbability }
|
|
66
|
+
: {}),
|
|
35
67
|
}, trace);
|
|
36
68
|
}
|
|
37
69
|
else {
|
|
@@ -62,6 +94,9 @@ export async function fetchQuote(client, action, observation, trace) {
|
|
|
62
94
|
futuresFeeBps: asNum(asObj(d.executionModel).feeBps),
|
|
63
95
|
estimatedEntryFeeMusd: asNum(asObj(d.executionModel).estimatedEntryFeeMusd),
|
|
64
96
|
cashRequiredMusd: asNum(d.cashRequiredMusd),
|
|
97
|
+
...(Object.prototype.hasOwnProperty.call(d, "funding")
|
|
98
|
+
? { funding: fundingQuoteEvidence(d.funding) }
|
|
99
|
+
: {}),
|
|
65
100
|
}
|
|
66
101
|
: {}),
|
|
67
102
|
// Freshness lives in the response's `observation` block (anti-look-ahead).
|
|
@@ -146,6 +181,7 @@ provenance) {
|
|
|
146
181
|
...(action.forecastProbability != null
|
|
147
182
|
? { forecastProbability: action.forecastProbability }
|
|
148
183
|
: {}),
|
|
184
|
+
...(action.thesis?.summary ? { thesis: action.thesis.summary } : {}),
|
|
149
185
|
// Attach runner provenance only when present (byte-identical to before when absent).
|
|
150
186
|
...(provenance ? { provenance } : {}),
|
|
151
187
|
agentTrace: trace,
|
package/dist/agent/client.d.ts
CHANGED
|
@@ -91,6 +91,9 @@ export declare class CoinRithmClient {
|
|
|
91
91
|
slug: string;
|
|
92
92
|
outcomeExternalMarketId: string;
|
|
93
93
|
stakeMusd: number;
|
|
94
|
+
side?: "yes" | "no";
|
|
95
|
+
forecastProbability?: number;
|
|
96
|
+
bankrollMusd?: number;
|
|
94
97
|
}, trace?: AgentTrace): Promise<ApiResult>;
|
|
95
98
|
openFutures(body: {
|
|
96
99
|
coinId: string;
|
|
@@ -133,6 +136,7 @@ export declare class CoinRithmClient {
|
|
|
133
136
|
stakeMusd: number;
|
|
134
137
|
idempotencyKey: string;
|
|
135
138
|
forecastProbability?: number;
|
|
139
|
+
thesis?: string;
|
|
136
140
|
provenance?: ProvenanceReport;
|
|
137
141
|
agentTrace?: AgentTrace;
|
|
138
142
|
}): Promise<ApiResult>;
|
package/dist/agent/decision.d.ts
CHANGED
|
@@ -19,9 +19,9 @@ export declare const actionSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<
|
|
|
19
19
|
marginMusd?: any;
|
|
20
20
|
stopLossPrice?: any;
|
|
21
21
|
takeProfitPrice?: any;
|
|
22
|
+
thesis?: import("./types.js").Thesis | undefined;
|
|
22
23
|
confidence?: any;
|
|
23
24
|
rationaleSummary?: string | undefined;
|
|
24
|
-
thesis?: import("./types.js").Thesis | undefined;
|
|
25
25
|
}, {
|
|
26
26
|
symbol: string;
|
|
27
27
|
side: "long" | "short";
|
|
@@ -30,9 +30,9 @@ export declare const actionSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<
|
|
|
30
30
|
marginMusd?: unknown;
|
|
31
31
|
stopLossPrice?: unknown;
|
|
32
32
|
takeProfitPrice?: unknown;
|
|
33
|
+
thesis?: any;
|
|
33
34
|
confidence?: unknown;
|
|
34
35
|
rationaleSummary?: string | undefined;
|
|
35
|
-
thesis?: any;
|
|
36
36
|
}>, z.ZodObject<{
|
|
37
37
|
type: z.ZodLiteral<"futures_close">;
|
|
38
38
|
positionId: z.ZodEffects<z.ZodTypeAny, any, unknown>;
|
|
@@ -44,16 +44,16 @@ export declare const actionSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<
|
|
|
44
44
|
type: "futures_close";
|
|
45
45
|
positionId?: any;
|
|
46
46
|
fraction?: any;
|
|
47
|
+
thesis?: import("./types.js").Thesis | undefined;
|
|
47
48
|
confidence?: any;
|
|
48
49
|
rationaleSummary?: string | undefined;
|
|
49
|
-
thesis?: import("./types.js").Thesis | undefined;
|
|
50
50
|
}, {
|
|
51
51
|
type: "futures_close";
|
|
52
52
|
positionId?: unknown;
|
|
53
53
|
fraction?: unknown;
|
|
54
|
+
thesis?: any;
|
|
54
55
|
confidence?: unknown;
|
|
55
56
|
rationaleSummary?: string | undefined;
|
|
56
|
-
thesis?: any;
|
|
57
57
|
}>, z.ZodObject<{
|
|
58
58
|
type: z.ZodLiteral<"futures_set_sltp">;
|
|
59
59
|
positionId: z.ZodEffects<z.ZodTypeAny, any, unknown>;
|
|
@@ -67,17 +67,17 @@ export declare const actionSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<
|
|
|
67
67
|
stopLossPrice?: any;
|
|
68
68
|
takeProfitPrice?: any;
|
|
69
69
|
positionId?: any;
|
|
70
|
+
thesis?: import("./types.js").Thesis | undefined;
|
|
70
71
|
confidence?: any;
|
|
71
72
|
rationaleSummary?: string | undefined;
|
|
72
|
-
thesis?: import("./types.js").Thesis | undefined;
|
|
73
73
|
}, {
|
|
74
74
|
type: "futures_set_sltp";
|
|
75
75
|
stopLossPrice?: unknown;
|
|
76
76
|
takeProfitPrice?: unknown;
|
|
77
77
|
positionId?: unknown;
|
|
78
|
+
thesis?: any;
|
|
78
79
|
confidence?: unknown;
|
|
79
80
|
rationaleSummary?: string | undefined;
|
|
80
|
-
thesis?: any;
|
|
81
81
|
}>, z.ZodObject<{
|
|
82
82
|
type: z.ZodLiteral<"spot_order">;
|
|
83
83
|
symbol: z.ZodString;
|
|
@@ -97,9 +97,9 @@ export declare const actionSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<
|
|
|
97
97
|
quantity?: any;
|
|
98
98
|
limitPrice?: any;
|
|
99
99
|
stopPrice?: any;
|
|
100
|
+
thesis?: import("./types.js").Thesis | undefined;
|
|
100
101
|
confidence?: any;
|
|
101
102
|
rationaleSummary?: string | undefined;
|
|
102
|
-
thesis?: import("./types.js").Thesis | undefined;
|
|
103
103
|
}, {
|
|
104
104
|
symbol: string;
|
|
105
105
|
side: "buy" | "sell";
|
|
@@ -108,9 +108,9 @@ export declare const actionSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<
|
|
|
108
108
|
quantity?: unknown;
|
|
109
109
|
limitPrice?: unknown;
|
|
110
110
|
stopPrice?: unknown;
|
|
111
|
+
thesis?: any;
|
|
111
112
|
confidence?: unknown;
|
|
112
113
|
rationaleSummary?: string | undefined;
|
|
113
|
-
thesis?: any;
|
|
114
114
|
}>, z.ZodObject<{
|
|
115
115
|
type: z.ZodLiteral<"spot_cancel">;
|
|
116
116
|
orderId: z.ZodEffects<z.ZodTypeAny, any, unknown>;
|
|
@@ -119,16 +119,16 @@ export declare const actionSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<
|
|
|
119
119
|
thesis: z.ZodOptional<z.ZodEffects<z.ZodAny, import("./types.js").Thesis | undefined, any>>;
|
|
120
120
|
}, "strict", z.ZodTypeAny, {
|
|
121
121
|
type: "spot_cancel";
|
|
122
|
+
thesis?: import("./types.js").Thesis | undefined;
|
|
122
123
|
confidence?: any;
|
|
123
124
|
rationaleSummary?: string | undefined;
|
|
124
125
|
orderId?: any;
|
|
125
|
-
thesis?: import("./types.js").Thesis | undefined;
|
|
126
126
|
}, {
|
|
127
127
|
type: "spot_cancel";
|
|
128
|
+
thesis?: any;
|
|
128
129
|
confidence?: unknown;
|
|
129
130
|
rationaleSummary?: string | undefined;
|
|
130
131
|
orderId?: unknown;
|
|
131
|
-
thesis?: any;
|
|
132
132
|
}>, z.ZodObject<{
|
|
133
133
|
type: z.ZodLiteral<"pm_open">;
|
|
134
134
|
ref: z.ZodOptional<z.ZodString>;
|
|
@@ -147,9 +147,9 @@ export declare const actionSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<
|
|
|
147
147
|
outcomeExternalMarketId?: string | undefined;
|
|
148
148
|
stakeMusd?: any;
|
|
149
149
|
forecastProbability?: number | undefined;
|
|
150
|
+
thesis?: import("./types.js").Thesis | undefined;
|
|
150
151
|
confidence?: any;
|
|
151
152
|
rationaleSummary?: string | undefined;
|
|
152
|
-
thesis?: import("./types.js").Thesis | undefined;
|
|
153
153
|
ref?: string | undefined;
|
|
154
154
|
}, {
|
|
155
155
|
type: "pm_open";
|
|
@@ -158,9 +158,9 @@ export declare const actionSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<
|
|
|
158
158
|
outcomeExternalMarketId?: string | undefined;
|
|
159
159
|
stakeMusd?: unknown;
|
|
160
160
|
forecastProbability?: any;
|
|
161
|
+
thesis?: any;
|
|
161
162
|
confidence?: unknown;
|
|
162
163
|
rationaleSummary?: string | undefined;
|
|
163
|
-
thesis?: any;
|
|
164
164
|
ref?: string | undefined;
|
|
165
165
|
}>]>;
|
|
166
166
|
export declare const DECISION_JSON_SCHEMA: {
|
package/dist/agent/engine.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { runCycle, type RunnerDeps } from "./runner.js";
|
|
2
2
|
export { DECISION_INPUT_MAX_BYTES, sanitizeDecisionInputRecord, type DecisionInputRecord, } from "./decisionReceipt.js";
|
|
3
|
-
export { selectProvider, providerForRoute, type ProviderEnv, type Provider, type DecideInput, type DecideResult, type DecideRouteAttempt, type DecideRouteMeta, } from "./providers.js";
|
|
3
|
+
export { selectProvider, providerForRoute, classifyProviderFailure, type ProviderEnv, type Provider, type DecideInput, type DecideResult, type DecideRouteAttempt, type DecideRouteMeta, } from "./providers.js";
|
|
4
4
|
export { parseDecision } from "./decision.js";
|
|
5
5
|
export { chatShapeFor, buildChatBody, type ChatShape, } from "./providerCapabilities.js";
|
|
6
6
|
export { probeDecisionContract, type ProbeRoute, type ProbeDecisionResult, } from "./decisionProbe.js";
|
package/dist/agent/engine.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// stable engine pieces, never the CLI.
|
|
8
8
|
export { runCycle } from "./runner.js";
|
|
9
9
|
export { DECISION_INPUT_MAX_BYTES, sanitizeDecisionInputRecord, } from "./decisionReceipt.js";
|
|
10
|
-
export { selectProvider, providerForRoute, } from "./providers.js";
|
|
10
|
+
export { selectProvider, providerForRoute, classifyProviderFailure, } from "./providers.js";
|
|
11
11
|
export { parseDecision } from "./decision.js";
|
|
12
12
|
// Reliability slice A: the declarative request-capability table and the
|
|
13
13
|
// representative decision probe (route eligibility = a REAL parsed decision,
|
package/dist/agent/observe.js
CHANGED
|
@@ -90,8 +90,10 @@ async function fetchCandleContext(client, coinId, trace) {
|
|
|
90
90
|
}
|
|
91
91
|
if (!cr.ok)
|
|
92
92
|
return { indicators: null };
|
|
93
|
-
// Endpoint shape: { candles: [{ t, o, h, l, c, v }] } ascending (oldest first).
|
|
93
|
+
// Endpoint shape: { candles: [{ t, o, h, l, c, v, vm }] } ascending (oldest first).
|
|
94
94
|
const candles = [];
|
|
95
|
+
let latestVolume;
|
|
96
|
+
let latestVolumeMissingVenues;
|
|
95
97
|
for (const raw of asArr(asObj(cr.data).candles)) {
|
|
96
98
|
const c = asObj(raw);
|
|
97
99
|
const open = asNum(c.o);
|
|
@@ -100,12 +102,22 @@ async function fetchCandleContext(client, coinId, trace) {
|
|
|
100
102
|
const close = asNum(c.c);
|
|
101
103
|
if (open == null || high == null || low == null || close == null)
|
|
102
104
|
continue;
|
|
103
|
-
|
|
105
|
+
const volume = asNum(c.v);
|
|
106
|
+
candles.push({ open, high, low, close, volume: volume ?? undefined });
|
|
107
|
+
latestVolume = volume != null && volume >= 0 ? volume : undefined;
|
|
108
|
+
const coverage = asNum(c.vm);
|
|
109
|
+
latestVolumeMissingVenues =
|
|
110
|
+
latestVolume != null &&
|
|
111
|
+
coverage != null &&
|
|
112
|
+
Number.isInteger(coverage) &&
|
|
113
|
+
coverage >= 0
|
|
114
|
+
? coverage
|
|
115
|
+
: undefined;
|
|
104
116
|
}
|
|
105
|
-
const lastVolume = candles.length > 0 ? candles[candles.length - 1].volume : undefined;
|
|
106
117
|
return {
|
|
107
118
|
indicators: computeIndicators(candles),
|
|
108
|
-
volume24hUsd:
|
|
119
|
+
volume24hUsd: latestVolume,
|
|
120
|
+
volumeMissingVenues: latestVolumeMissingVenues,
|
|
109
121
|
};
|
|
110
122
|
}
|
|
111
123
|
// The fundamentals leg of a watch entry, read from the /market context the
|
|
@@ -141,6 +153,12 @@ async function enrichFromCandles(client, entry, coinId, trace) {
|
|
|
141
153
|
volume24hUsd: cc.volume24hUsd,
|
|
142
154
|
};
|
|
143
155
|
}
|
|
156
|
+
if (cc.volumeMissingVenues != null) {
|
|
157
|
+
entry.fundamentals = {
|
|
158
|
+
...(entry.fundamentals ?? {}),
|
|
159
|
+
volumeMissingVenues: cc.volumeMissingVenues,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
144
162
|
}
|
|
145
163
|
const HEADLINES_PER_COIN = 3;
|
|
146
164
|
const HEADLINE_TITLE_CHARS = 110;
|
|
@@ -316,6 +334,14 @@ export async function observe(client, spec, state, trace) {
|
|
|
316
334
|
// and could not tell a winner from a small loser before a manual close.
|
|
317
335
|
// Tolerant fallbacks keep older/mocked shapes working.
|
|
318
336
|
const coin = asObj(p.coin);
|
|
337
|
+
const fundingPaidMusd = Object.prototype.hasOwnProperty.call(p, "fundingPaidMusd")
|
|
338
|
+
? (asNum(p.fundingPaidMusd) ??
|
|
339
|
+
(p.fundingPaidMusd === null ? null : undefined))
|
|
340
|
+
: undefined;
|
|
341
|
+
const fundingAppliedThrough = Object.prototype.hasOwnProperty.call(p, "fundingAppliedThrough")
|
|
342
|
+
? (asStr(p.fundingAppliedThrough) ??
|
|
343
|
+
(p.fundingAppliedThrough === null ? null : undefined))
|
|
344
|
+
: undefined;
|
|
319
345
|
return {
|
|
320
346
|
venue: "futures",
|
|
321
347
|
id: Number(asNum(p.id) ?? p.id),
|
|
@@ -327,6 +353,10 @@ export async function observe(client, spec, state, trace) {
|
|
|
327
353
|
leverage: asNum(p.leverage),
|
|
328
354
|
marginMusd: asNum(p.marginMusd),
|
|
329
355
|
unrealizedPnlMusd: asNum(p.unrealizedPnlMusd),
|
|
356
|
+
...(fundingPaidMusd !== undefined ? { fundingPaidMusd } : {}),
|
|
357
|
+
...(fundingAppliedThrough !== undefined
|
|
358
|
+
? { fundingAppliedThrough }
|
|
359
|
+
: {}),
|
|
330
360
|
entryPrice: asNum(p.entryPrice),
|
|
331
361
|
markPrice: asNum(p.markPrice),
|
|
332
362
|
liquidationPrice: asNum(p.liquidationPrice),
|
package/dist/agent/prompt.js
CHANGED
|
@@ -338,6 +338,10 @@ export function buildUserPrompt(obs, journal, opts = {}) {
|
|
|
338
338
|
if (brokenTheses.length > 0) {
|
|
339
339
|
lines.push("", "## Positions whose thesis is INVALIDATED this cycle", ...brokenTheses.map((b) => `- ${b}`));
|
|
340
340
|
}
|
|
341
|
+
if (obs.openPositions.some((p) => p.fundingPaidMusd !== undefined ||
|
|
342
|
+
p.fundingAppliedThrough !== undefined)) {
|
|
343
|
+
lines.push("Futures funding shown in the position is already reflected in margin and balances; do not deduct it again when judging available capital or PnL.");
|
|
344
|
+
}
|
|
341
345
|
// Settlement-feedback loop: surface the agent's recently-RESOLVED PM bets so the
|
|
342
346
|
// model can reflect and adapt. Reflective context only — never a new action.
|
|
343
347
|
if (hasPm)
|
|
@@ -52,6 +52,10 @@ export interface ProviderEnv {
|
|
|
52
52
|
GEMINI_API_KEY?: string;
|
|
53
53
|
MODEL_API_KEY?: string;
|
|
54
54
|
}
|
|
55
|
+
/** Keep direct and routed cycle evidence consistent about NVIDIA backpressure. */
|
|
56
|
+
export declare function classifyProviderFailure(result: Extract<DecideResult, {
|
|
57
|
+
ok: false;
|
|
58
|
+
}>): "capacity" | "permanent" | "transient";
|
|
55
59
|
export declare function selectProvider(spec: AgentSpec, env: ProviderEnv, fetchFn?: typeof fetch): Provider;
|
|
56
60
|
export declare function providerForRoute(route: {
|
|
57
61
|
provider: ProviderName;
|
package/dist/agent/providers.js
CHANGED
|
@@ -29,6 +29,16 @@ const GEMINI_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai
|
|
|
29
29
|
// MUST stay below the scheduler's RUN_LOCK_SECONDS and HEARTBEAT_STALE_MS.
|
|
30
30
|
const DEFAULT_TIMEOUT_MS = 300_000;
|
|
31
31
|
const RETRYABLE_SERVER_STATUSES = new Set([500, 502, 503, 504]);
|
|
32
|
+
/** Keep direct and routed cycle evidence consistent about NVIDIA backpressure. */
|
|
33
|
+
export function classifyProviderFailure(result) {
|
|
34
|
+
if (result.status === 429 ||
|
|
35
|
+
(result.status === 503 &&
|
|
36
|
+
/resourceexhausted|worker local total request limit/i.test(result.error ?? "")))
|
|
37
|
+
return "capacity";
|
|
38
|
+
if (result.status === 404 || result.status === 410)
|
|
39
|
+
return "permanent";
|
|
40
|
+
return "transient";
|
|
41
|
+
}
|
|
32
42
|
// Per-route request quirks (reasoning toggles, token param, temperature) live
|
|
33
43
|
// in the capability table — providerCapabilities.ts is the single source; this
|
|
34
44
|
// module only assembles and sends.
|
|
@@ -332,15 +342,11 @@ class SameModelRetryProvider {
|
|
|
332
342
|
error: res.error,
|
|
333
343
|
status: res.status,
|
|
334
344
|
retryAfterMs: res.retryAfterMs,
|
|
335
|
-
|
|
336
|
-
?
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
? "transient"
|
|
341
|
-
: "permanent",
|
|
342
|
-
}
|
|
343
|
-
: {}),
|
|
345
|
+
failureClass: classifyProviderFailure(res) === "capacity"
|
|
346
|
+
? "capacity"
|
|
347
|
+
: res.status !== undefined && res.status < 500
|
|
348
|
+
? "permanent"
|
|
349
|
+
: "transient",
|
|
344
350
|
}
|
|
345
351
|
: {}),
|
|
346
352
|
});
|
|
@@ -350,7 +356,7 @@ class SameModelRetryProvider {
|
|
|
350
356
|
// or a certificate that returned text passed the trading-decision parser.
|
|
351
357
|
...result,
|
|
352
358
|
route: {
|
|
353
|
-
policyVersion: "coinrithm.configured-same-model-retry.
|
|
359
|
+
policyVersion: "coinrithm.configured-same-model-retry.v2",
|
|
354
360
|
profile: "configured",
|
|
355
361
|
effectiveProvider: this.provider,
|
|
356
362
|
effectiveModel: this.model,
|
package/dist/agent/runner.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// spot, futures, and prediction markets. Dry-run never writes. Live uses
|
|
3
3
|
// idempotency keys + agentTrace and exports run evidence. The client + provider
|
|
4
4
|
// are injected so the loop is fully unit-testable with no network/model calls.
|
|
5
|
+
import { classifyProviderFailure } from "./providers.js";
|
|
5
6
|
import { COINRITHM_API } from "./version.js";
|
|
6
7
|
import { spotBuyCost, DEFAULT_TRIGGER_POLICY, } from "./types.js";
|
|
7
8
|
import { usesCapitalSizing, prepareCapitalAction, validateCapitalAction, capitalCashCost, } from "./capitalSizing.js";
|
|
@@ -727,7 +728,7 @@ async function runCycleCore(deps, capture) {
|
|
|
727
728
|
// only capacity failures. Treat that exactly like a local capacity defer:
|
|
728
729
|
// no action, no fallback invented here, and no model-failure streak that
|
|
729
730
|
// could stop an otherwise healthy agent after repeated quota pressure.
|
|
730
|
-
const capacityOnlyFailure = (!route && res
|
|
731
|
+
const capacityOnlyFailure = (!route && classifyProviderFailure(res) === "capacity") ||
|
|
731
732
|
(!!route?.attempts?.length &&
|
|
732
733
|
route.attempts.every((attempt) => attempt.failureClass === "capacity"));
|
|
733
734
|
if (res.deferred || !actualCallMade || capacityOnlyFailure) {
|
package/dist/agent/templates.js
CHANGED
|
@@ -50,37 +50,37 @@ const PRESETS = {
|
|
|
50
50
|
modelFail: 5,
|
|
51
51
|
},
|
|
52
52
|
};
|
|
53
|
-
const THESIS_BODY = `# Momentum Futures — strategy
|
|
54
|
-
|
|
55
|
-
You operate a CoinRithm **paper-trading** futures account (50,000 virtual mUSD).
|
|
56
|
-
Everything here is simulated; it is not financial advice and never touches real
|
|
57
|
-
money. Edit this prose freely (any language) — it is your agent's borders.
|
|
58
|
-
|
|
59
|
-
## Each cycle
|
|
60
|
-
|
|
61
|
-
1. Ground yourself: read your portfolio and open positions first. Never assume
|
|
62
|
-
balances or what is already open.
|
|
63
|
-
2. Scan the watchlist. A candidate is a coin whose short and medium momentum
|
|
64
|
-
agree (both up, or both down) and is not already an open position.
|
|
65
|
-
3. Pick the strongest candidate and commit when the read is clear — even a
|
|
66
|
-
moderate-confidence one — sized small with a stop. Skip only when the signals
|
|
67
|
-
contradict or the data is stale; a quiet tape where your edge is still real
|
|
68
|
-
is an act, not a skip.
|
|
69
|
-
4. Quote before you open. Read the liquidation price and confirm it is sane. If
|
|
70
|
-
the quote is not eligible, relay the reason and stop.
|
|
71
|
-
5. Open small and protected: enter in the trend direction and set a stop-loss at
|
|
72
|
-
open. Place the take-profit a touch wider than the stop.
|
|
73
|
-
6. Stay in sync: poll your trades for any stop / take-profit / liquidation that
|
|
74
|
-
fired while you were not looking, and react to what actually happened.
|
|
75
|
-
|
|
76
|
-
The hard caps (leverage, margin, watchlist) live in the config blocks above and
|
|
53
|
+
const THESIS_BODY = `# Momentum Futures — strategy
|
|
54
|
+
|
|
55
|
+
You operate a CoinRithm **paper-trading** futures account (50,000 virtual mUSD).
|
|
56
|
+
Everything here is simulated; it is not financial advice and never touches real
|
|
57
|
+
money. Edit this prose freely (any language) — it is your agent's borders.
|
|
58
|
+
|
|
59
|
+
## Each cycle
|
|
60
|
+
|
|
61
|
+
1. Ground yourself: read your portfolio and open positions first. Never assume
|
|
62
|
+
balances or what is already open.
|
|
63
|
+
2. Scan the watchlist. A candidate is a coin whose short and medium momentum
|
|
64
|
+
agree (both up, or both down) and is not already an open position.
|
|
65
|
+
3. Pick the strongest candidate and commit when the read is clear — even a
|
|
66
|
+
moderate-confidence one — sized small with a stop. Skip only when the signals
|
|
67
|
+
contradict or the data is stale; a quiet tape where your edge is still real
|
|
68
|
+
is an act, not a skip.
|
|
69
|
+
4. Quote before you open. Read the liquidation price and confirm it is sane. If
|
|
70
|
+
the quote is not eligible, relay the reason and stop.
|
|
71
|
+
5. Open small and protected: enter in the trend direction and set a stop-loss at
|
|
72
|
+
open. Place the take-profit a touch wider than the stop.
|
|
73
|
+
6. Stay in sync: poll your trades for any stop / take-profit / liquidation that
|
|
74
|
+
fired while you were not looking, and react to what actually happened.
|
|
75
|
+
|
|
76
|
+
The hard caps (leverage, margin, watchlist) live in the config blocks above and
|
|
77
77
|
are enforced by the runner — change them there, not in this prose.`;
|
|
78
|
-
const PERSONA_STUB = `# Persona
|
|
79
|
-
|
|
80
|
-
Decisive and in character. Acts on a clear read — even a moderate-confidence one
|
|
81
|
-
— sized small and protected with a stop, and skips only when the read is
|
|
82
|
-
contradictory or the data is stale. States its reasoning plainly in its own
|
|
83
|
-
voice, and never frames paper results as real-money advice.
|
|
78
|
+
const PERSONA_STUB = `# Persona
|
|
79
|
+
|
|
80
|
+
Decisive and in character. Acts on a clear read — even a moderate-confidence one
|
|
81
|
+
— sized small and protected with a stop, and skips only when the read is
|
|
82
|
+
contradictory or the data is stale. States its reasoning plainly in its own
|
|
83
|
+
voice, and never frames paper results as real-money advice.
|
|
84
84
|
`;
|
|
85
85
|
export function buildAgentObject(name, preset) {
|
|
86
86
|
const p = PRESETS[preset];
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -153,6 +153,7 @@ export interface CoinFundamentals {
|
|
|
153
153
|
marketCapRank?: number;
|
|
154
154
|
marketCapUsd?: number;
|
|
155
155
|
volume24hUsd?: number;
|
|
156
|
+
volumeMissingVenues?: number;
|
|
156
157
|
headlines?: Array<{
|
|
157
158
|
title: string;
|
|
158
159
|
at?: string;
|
|
@@ -171,6 +172,8 @@ export interface OpenPosition {
|
|
|
171
172
|
leverage?: number;
|
|
172
173
|
marginMusd?: number;
|
|
173
174
|
unrealizedPnlMusd?: number;
|
|
175
|
+
fundingPaidMusd?: number | null;
|
|
176
|
+
fundingAppliedThrough?: string | null;
|
|
174
177
|
entryPrice?: number;
|
|
175
178
|
markPrice?: number;
|
|
176
179
|
liquidationPrice?: number;
|
|
@@ -397,10 +400,21 @@ export interface QuoteEvidence {
|
|
|
397
400
|
futuresFeeBps?: number;
|
|
398
401
|
estimatedEntryFeeMusd?: number;
|
|
399
402
|
cashRequiredMusd?: number;
|
|
403
|
+
funding?: FuturesFundingQuoteEvidence | null;
|
|
400
404
|
freshness?: Freshness;
|
|
401
405
|
openBlocked?: boolean;
|
|
402
406
|
openBlockReasons?: unknown;
|
|
403
407
|
}
|
|
408
|
+
export interface FuturesFundingQuoteEvidence {
|
|
409
|
+
venue?: string;
|
|
410
|
+
symbol?: string;
|
|
411
|
+
rate?: number;
|
|
412
|
+
intervalHours?: number;
|
|
413
|
+
nextFundingTime?: string;
|
|
414
|
+
asOf?: string;
|
|
415
|
+
estimatedPerIntervalMusd?: number | null;
|
|
416
|
+
annualizedRate?: number;
|
|
417
|
+
}
|
|
404
418
|
export interface RunState {
|
|
405
419
|
runId: string;
|
|
406
420
|
cyclesRun: number;
|
package/dist/client.d.ts
CHANGED
|
@@ -64,7 +64,11 @@ export declare class CoinRithmClient {
|
|
|
64
64
|
getPublicPmEvent(source: string, slug: string, query?: {
|
|
65
65
|
fiat?: string;
|
|
66
66
|
}): Promise<ApiResult>;
|
|
67
|
+
/** Best-effort anonymous interest marker for an explicitly viewed open event. */
|
|
68
|
+
markPublicPmEventViewed(source: string, slug: string): Promise<ApiResult>;
|
|
67
69
|
getPublicPmWhales(): Promise<ApiResult>;
|
|
70
|
+
getPublicPmWhaleWallets(window?: "7d" | "30d", source?: "polymarket" | "limitless" | "myriad"): Promise<ApiResult>;
|
|
71
|
+
getPublicPmWhaleWallet(source: string, wallet: string): Promise<ApiResult>;
|
|
68
72
|
getPublicPmMatches(query?: {
|
|
69
73
|
limit?: number;
|
|
70
74
|
offset?: number;
|
|
@@ -168,6 +172,8 @@ export declare class CoinRithmClient {
|
|
|
168
172
|
outcomeExternalMarketId: string;
|
|
169
173
|
side?: "yes" | "no";
|
|
170
174
|
stakeMusd: number;
|
|
175
|
+
forecastProbability?: number;
|
|
176
|
+
bankrollMusd?: number;
|
|
171
177
|
} & {
|
|
172
178
|
agentTrace?: AgentTrace;
|
|
173
179
|
}, apiKey?: string): Promise<ApiResult>;
|
|
@@ -215,6 +221,7 @@ export declare class CoinRithmClient {
|
|
|
215
221
|
stakeMusd: number;
|
|
216
222
|
idempotencyKey: string;
|
|
217
223
|
forecastProbability?: number;
|
|
224
|
+
thesis?: string;
|
|
218
225
|
provenance?: ProvenanceReport;
|
|
219
226
|
}>, apiKey?: string): Promise<ApiResult>;
|
|
220
227
|
reportPmOpportunity(body: TraceableBody<{
|
package/dist/client.js
CHANGED
|
@@ -216,9 +216,52 @@ export class CoinRithmClient {
|
|
|
216
216
|
getPublicPmEvent(source, slug, query) {
|
|
217
217
|
return this.publicRequest(`/api/prediction-markets/events/${encodeURIComponent(source)}/${encodeURIComponent(slug)}`, query);
|
|
218
218
|
}
|
|
219
|
+
/** Best-effort anonymous interest marker for an explicitly viewed open event. */
|
|
220
|
+
markPublicPmEventViewed(source, slug) {
|
|
221
|
+
const path = `/api/prediction-markets/events/${encodeURIComponent(source)}/${encodeURIComponent(slug)}/view`;
|
|
222
|
+
const controller = new AbortController();
|
|
223
|
+
const timer = setTimeout(() => controller.abort(), 1000);
|
|
224
|
+
return fetch(this.baseUrl + path, {
|
|
225
|
+
method: "POST",
|
|
226
|
+
headers: { Accept: "application/json" },
|
|
227
|
+
signal: controller.signal,
|
|
228
|
+
})
|
|
229
|
+
.then(async (res) => {
|
|
230
|
+
const text = await res.text();
|
|
231
|
+
let data = text;
|
|
232
|
+
if (text) {
|
|
233
|
+
try {
|
|
234
|
+
data = JSON.parse(text);
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
// leave as text
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return { ok: res.ok, status: res.status, data };
|
|
241
|
+
})
|
|
242
|
+
.catch((err) => ({
|
|
243
|
+
ok: false,
|
|
244
|
+
status: 0,
|
|
245
|
+
data: {
|
|
246
|
+
error: err instanceof DOMException && err.name === "AbortError"
|
|
247
|
+
? "timeout"
|
|
248
|
+
: "network_error",
|
|
249
|
+
},
|
|
250
|
+
}))
|
|
251
|
+
.finally(() => clearTimeout(timer));
|
|
252
|
+
}
|
|
219
253
|
getPublicPmWhales() {
|
|
220
254
|
return this.publicRequest("/api/prediction-markets/whales");
|
|
221
255
|
}
|
|
256
|
+
getPublicPmWhaleWallets(window, source) {
|
|
257
|
+
return this.publicRequest("/api/prediction-markets/whales/wallets", {
|
|
258
|
+
...(window ? { window } : {}),
|
|
259
|
+
...(source ? { source } : {}),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
getPublicPmWhaleWallet(source, wallet) {
|
|
263
|
+
return this.publicRequest(`/api/prediction-markets/whales/wallets/${encodeURIComponent(source)}/${encodeURIComponent(wallet)}`);
|
|
264
|
+
}
|
|
222
265
|
// Cross-venue disagreement clusters (approved event matches, graph-clustered).
|
|
223
266
|
getPublicPmMatches(query) {
|
|
224
267
|
return this.publicRequest("/api/prediction-markets/matches/public", query);
|
package/dist/httpCompletion.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
2
|
import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
3
|
-
export declare const COMPLETION_TOOL_NAMES: readonly ["whoami", "get_portfolio", "get_wallet", "list_open_orders", "get_positions", "resolve_symbol", "get_equity_curve", "get_my_trades", "get_market_context", "get_candles", "discover_pm_markets", "get_performance", "get_agent_ledger", "export_agent_ledger", "export_run_evidence", "get_arena_leaderboard", "get_arena_agent", "futures_quote", "pm_quote", "spot_quote", "place_spot_order", "cancel_spot_order", "open_futures_position", "set_futures_sl_tp", "close_futures_position", "open_pm_position", "report_pm_opportunity", "pm_data_overview", "pm_data_sources", "pm_data_sources_health", "pm_data_events", "pm_data_event", "pm_data_whales", "pm_data_disagreements", "pm_data_calibration", "pm_data_canonical", "pm_data_volume_history", "get_crypto_movers"];
|
|
3
|
+
export declare const COMPLETION_TOOL_NAMES: readonly ["whoami", "get_portfolio", "get_wallet", "list_open_orders", "get_positions", "resolve_symbol", "get_equity_curve", "get_my_trades", "get_market_context", "get_candles", "discover_pm_markets", "get_performance", "get_agent_ledger", "export_agent_ledger", "export_run_evidence", "get_arena_leaderboard", "get_arena_agent", "futures_quote", "pm_quote", "spot_quote", "place_spot_order", "cancel_spot_order", "open_futures_position", "set_futures_sl_tp", "close_futures_position", "open_pm_position", "report_pm_opportunity", "pm_data_overview", "pm_data_sources", "pm_data_sources_health", "pm_data_events", "pm_data_event", "pm_data_whales", "pm_data_whale_wallets", "pm_data_whale_wallet", "pm_data_disagreements", "pm_data_calibration", "pm_data_canonical", "pm_data_volume_history", "get_crypto_movers"];
|
|
4
4
|
type Operation = "initialize" | "tools_list" | "tools_call" | "notification" | "other" | "invalid";
|
|
5
5
|
type Outcome = "result" | "tool_error" | "protocol_error" | "no_response" | "not_applicable";
|
|
6
6
|
type ToolName = (typeof COMPLETION_TOOL_NAMES)[number] | "unknown" | null;
|
package/dist/httpCompletion.js
CHANGED
package/dist/tools.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export declare function compactPublicPmEvents(data: unknown): unknown;
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function compactPublicPmEvent(data: unknown): unknown;
|
|
16
16
|
export declare function compactPublicPmWhales(data: unknown, limit: number): unknown;
|
|
17
|
+
export declare function compactPublicPmWhaleWallets(data: unknown, limit: number, requestedSource?: string): unknown;
|
|
18
|
+
export declare function compactPublicPmWhaleWalletDetail(data: unknown): unknown;
|
|
17
19
|
export declare function compactPublicCryptoMovers(data: unknown): unknown;
|
|
18
20
|
/**
|
|
19
21
|
* Keep cross-venue disagreement clusters small enough for an agent context
|