@coinrithm/mcp-trading 0.7.15 → 0.7.17
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 +885 -692
- package/README.md +486 -400
- package/dist/agent/bench/bench.d.ts +59 -0
- package/dist/agent/bench/bench.js +319 -0
- package/dist/agent/bench/cassette.d.ts +97 -0
- package/dist/agent/bench/cassette.js +181 -0
- package/dist/agent/bench/costs.d.ts +28 -0
- package/dist/agent/bench/costs.js +60 -0
- package/dist/agent/bench/labelBuilder.d.ts +123 -0
- package/dist/agent/bench/labelBuilder.js +282 -0
- package/dist/agent/bench/labels.d.ts +75 -0
- package/dist/agent/bench/labels.js +259 -0
- package/dist/agent/bench/recordingClient.d.ts +51 -0
- package/dist/agent/bench/recordingClient.js +193 -0
- package/dist/agent/bench/replayClient.d.ts +41 -0
- package/dist/agent/bench/replayClient.js +262 -0
- package/dist/agent/bench/report.d.ts +115 -0
- package/dist/agent/bench/report.js +435 -0
- package/dist/agent/capitalSizing.d.ts +10 -1
- package/dist/agent/capitalSizing.js +28 -4
- package/dist/agent/cli.d.ts +25 -0
- package/dist/agent/cli.js +300 -2
- package/dist/agent/client.d.ts +14 -0
- package/dist/agent/client.js +23 -6
- package/dist/agent/configurationWarnings.js +11 -0
- package/dist/agent/decision.d.ts +24 -16
- package/dist/agent/decision.js +92 -3
- package/dist/agent/decisionValidator.d.ts +31 -0
- package/dist/agent/decisionValidator.js +148 -3
- package/dist/agent/engine.d.ts +5 -3
- package/dist/agent/engine.js +5 -3
- package/dist/agent/futuresCloseOutcome.d.ts +19 -0
- package/dist/agent/futuresCloseOutcome.js +54 -0
- package/dist/agent/futuresEligibility.d.ts +13 -0
- package/dist/agent/futuresEligibility.js +43 -5
- package/dist/agent/observe.d.ts +28 -2
- package/dist/agent/observe.js +530 -90
- package/dist/agent/pmPaperCandidates.d.ts +17 -0
- package/dist/agent/pmPaperCandidates.js +125 -0
- package/dist/agent/pmPaperCycle.d.ts +16 -0
- package/dist/agent/pmPaperCycle.js +372 -0
- package/dist/agent/pmPaperDecision.d.ts +187 -0
- package/dist/agent/pmPaperDecision.js +101 -0
- package/dist/agent/pmPaperPolicy.d.ts +71 -0
- package/dist/agent/pmPaperPolicy.js +46 -0
- package/dist/agent/prompt.d.ts +15 -1
- package/dist/agent/prompt.js +187 -9
- package/dist/agent/promptTables.d.ts +1 -0
- package/dist/agent/promptTables.js +33 -0
- package/dist/agent/providerCapabilities.d.ts +7 -0
- package/dist/agent/providerCapabilities.js +27 -1
- package/dist/agent/providers.d.ts +26 -7
- package/dist/agent/providers.js +193 -48
- package/dist/agent/resolve.js +3 -0
- package/dist/agent/runner.d.ts +17 -1
- package/dist/agent/runner.js +210 -38
- package/dist/agent/setups.d.ts +2 -1
- package/dist/agent/setups.js +17 -16
- package/dist/agent/signals.d.ts +33 -0
- package/dist/agent/signals.js +89 -0
- package/dist/agent/skill.js +46 -0
- package/dist/agent/skillValidator.js +56 -0
- package/dist/agent/strictLint.js +30 -0
- package/dist/agent/templates.js +30 -30
- package/dist/agent/types.d.ts +180 -12
- package/dist/agent/universe.d.ts +78 -0
- package/dist/agent/universe.js +215 -0
- package/dist/agent/version.d.ts +1 -1
- package/dist/agent/version.js +1 -1
- package/dist/client.d.ts +14 -0
- package/dist/client.js +31 -1
- package/dist/http.js +1 -1
- package/dist/pmPaperV2.d.ts +81 -0
- package/dist/pmPaperV2.js +53 -0
- package/dist/tools.js +84 -6
- package/package.json +100 -97
package/dist/agent/providers.js
CHANGED
|
@@ -3,7 +3,64 @@
|
|
|
3
3
|
// single structured-JSON decision (parsed in decision.ts). No free-form tool
|
|
4
4
|
// execution — the model only proposes; the runner disposes.
|
|
5
5
|
import { retryAfterSeconds } from "../retryAfter.js";
|
|
6
|
-
import {
|
|
6
|
+
import { parseDecisionForContract, } from "./decision.js";
|
|
7
|
+
import { chatShapeFor, buildChatBody, withJsonContentTransport, canRetrySuperToolOutput, DECISION_TOOL_NAME, NVIDIA_BASE_URL as CAP_NVIDIA_BASE_URL, } from "./providerCapabilities.js";
|
|
8
|
+
// A token count as Anthropic reports it: a non-negative safe integer. Zero
|
|
9
|
+
// is a real count; anything else (missing, null, negative, NaN, fractional,
|
|
10
|
+
// a string) is malformed.
|
|
11
|
+
function exactCount(value) {
|
|
12
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0
|
|
13
|
+
? value
|
|
14
|
+
: undefined;
|
|
15
|
+
}
|
|
16
|
+
// Anthropic usage, including prompt-cache reads and writes (and the 5m/1h
|
|
17
|
+
// write split) when reported. Strict, because paid metering prices it (root
|
|
18
|
+
// review of #118): input_tokens and output_tokens are mandatory, and a
|
|
19
|
+
// malformed reported field (mandatory or cache) makes the WHOLE usage unknown
|
|
20
|
+
// (undefined), never zero, so the call is metered uncertain instead of free.
|
|
21
|
+
// Cache fields the response does not carry at all stay absent. A reported
|
|
22
|
+
// write total must equal its 5m/1h split; a split without a total implies it.
|
|
23
|
+
export function anthropicUsage(raw) {
|
|
24
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw))
|
|
25
|
+
return undefined;
|
|
26
|
+
const u = raw;
|
|
27
|
+
const promptTokens = exactCount(u.input_tokens);
|
|
28
|
+
const completionTokens = exactCount(u.output_tokens);
|
|
29
|
+
if (promptTokens === undefined || completionTokens === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
const usage = { promptTokens, completionTokens };
|
|
32
|
+
const optional = (value) => value === undefined ? undefined : (exactCount(value) ?? null);
|
|
33
|
+
const cacheRead = optional(u.cache_read_input_tokens);
|
|
34
|
+
const cacheWrite = optional(u.cache_creation_input_tokens);
|
|
35
|
+
let write5m;
|
|
36
|
+
let write1h;
|
|
37
|
+
if (u.cache_creation !== undefined) {
|
|
38
|
+
const split = u.cache_creation;
|
|
39
|
+
if (typeof split !== "object" || split === null || Array.isArray(split))
|
|
40
|
+
return undefined;
|
|
41
|
+
const s = split;
|
|
42
|
+
write5m = optional(s.ephemeral_5m_input_tokens);
|
|
43
|
+
write1h = optional(s.ephemeral_1h_input_tokens);
|
|
44
|
+
}
|
|
45
|
+
if ([cacheRead, cacheWrite, write5m, write1h].includes(null))
|
|
46
|
+
return undefined;
|
|
47
|
+
if (write5m != null || write1h != null) {
|
|
48
|
+
const splitTotal = (write5m ?? 0) + (write1h ?? 0);
|
|
49
|
+
if (cacheWrite != null && cacheWrite !== splitTotal)
|
|
50
|
+
return undefined;
|
|
51
|
+
usage.cacheWriteTokens = splitTotal;
|
|
52
|
+
if (write5m != null)
|
|
53
|
+
usage.cacheWrite5mTokens = write5m;
|
|
54
|
+
if (write1h != null)
|
|
55
|
+
usage.cacheWrite1hTokens = write1h;
|
|
56
|
+
}
|
|
57
|
+
else if (cacheWrite != null) {
|
|
58
|
+
usage.cacheWriteTokens = cacheWrite;
|
|
59
|
+
}
|
|
60
|
+
if (cacheRead != null)
|
|
61
|
+
usage.cacheReadTokens = cacheRead;
|
|
62
|
+
return usage;
|
|
63
|
+
}
|
|
7
64
|
// NVIDIA NIM is OpenAI-compatible; the `nvidia` preset hard-wires the hosted
|
|
8
65
|
// endpoint so an agent only needs `{ provider: nvidia, name: "<model id>" }`.
|
|
9
66
|
const NVIDIA_BASE_URL = CAP_NVIDIA_BASE_URL;
|
|
@@ -31,6 +88,8 @@ const DEFAULT_TIMEOUT_MS = 300_000;
|
|
|
31
88
|
const RETRYABLE_SERVER_STATUSES = new Set([500, 502, 503, 504]);
|
|
32
89
|
/** Keep direct and routed cycle evidence consistent about NVIDIA backpressure. */
|
|
33
90
|
export function classifyProviderFailure(result) {
|
|
91
|
+
if (result.failureClass === "malformed")
|
|
92
|
+
return "malformed";
|
|
34
93
|
if (result.status === 429 ||
|
|
35
94
|
(result.status === 503 &&
|
|
36
95
|
/resourceexhausted|worker local total request limit/i.test(result.error ?? "")))
|
|
@@ -186,15 +245,27 @@ class AnthropicProvider {
|
|
|
186
245
|
}
|
|
187
246
|
const json = (await res.json());
|
|
188
247
|
const text = json.content?.map((c) => c.text ?? "").join("") ?? "";
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
248
|
+
// Absent or malformed usage is undefined (unknown), never zero.
|
|
249
|
+
const usage = anthropicUsage(json.usage);
|
|
250
|
+
if (json.stop_reason === "max_tokens" ||
|
|
251
|
+
json.stop_reason === "model_context_window_exceeded") {
|
|
252
|
+
return {
|
|
253
|
+
ok: false,
|
|
254
|
+
failureClass: "malformed",
|
|
255
|
+
error: json.stop_reason === "max_tokens"
|
|
256
|
+
? "provider returned incomplete decision (output token limit)"
|
|
257
|
+
: "provider returned incomplete decision (context window limit)",
|
|
258
|
+
usage,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
195
261
|
return text
|
|
196
262
|
? { ok: true, text, usage, responseSource: "content" }
|
|
197
|
-
:
|
|
263
|
+
: // Answered (and billed) with nothing usable: keep the usage.
|
|
264
|
+
{
|
|
265
|
+
ok: false,
|
|
266
|
+
error: "anthropic returned empty content",
|
|
267
|
+
...(usage ? { usage } : {}),
|
|
268
|
+
};
|
|
198
269
|
});
|
|
199
270
|
}
|
|
200
271
|
catch (err) {
|
|
@@ -213,24 +284,40 @@ class AnthropicProvider {
|
|
|
213
284
|
}
|
|
214
285
|
}
|
|
215
286
|
}
|
|
287
|
+
function wantsJsonContent(options) {
|
|
288
|
+
const v = options.nemotronJsonContent;
|
|
289
|
+
if (typeof v !== "function")
|
|
290
|
+
return v === true;
|
|
291
|
+
try {
|
|
292
|
+
return v() === true;
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
216
298
|
class OpenAiCompatProvider {
|
|
217
299
|
provider;
|
|
218
300
|
model;
|
|
219
301
|
apiKey;
|
|
220
302
|
baseUrl;
|
|
221
303
|
fetchFn;
|
|
304
|
+
options;
|
|
222
305
|
label;
|
|
223
|
-
constructor(provider, model, apiKey, baseUrl, fetchFn) {
|
|
306
|
+
constructor(provider, model, apiKey, baseUrl, fetchFn, options = {}) {
|
|
224
307
|
this.provider = provider;
|
|
225
308
|
this.model = model;
|
|
226
309
|
this.apiKey = apiKey;
|
|
227
310
|
this.baseUrl = baseUrl;
|
|
228
311
|
this.fetchFn = fetchFn;
|
|
312
|
+
this.options = options;
|
|
229
313
|
this.label = `${baseUrl}/${model}`;
|
|
230
314
|
}
|
|
231
315
|
async decide(input) {
|
|
232
316
|
const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
233
|
-
const
|
|
317
|
+
const baseShape = chatShapeFor(this.provider, this.model, this.baseUrl);
|
|
318
|
+
const shape = wantsJsonContent(this.options)
|
|
319
|
+
? withJsonContentTransport(baseShape)
|
|
320
|
+
: baseShape;
|
|
234
321
|
let failureResponse;
|
|
235
322
|
try {
|
|
236
323
|
return await withProviderTimeout(timeoutMs, async (signal) => {
|
|
@@ -247,6 +334,7 @@ class OpenAiCompatProvider {
|
|
|
247
334
|
user: input.user,
|
|
248
335
|
maxTokens: input.maxTokens ?? 1024,
|
|
249
336
|
excludeActionTypes: input.excludeActionTypes,
|
|
337
|
+
decisionContract: input.decisionContract,
|
|
250
338
|
})),
|
|
251
339
|
});
|
|
252
340
|
if (!res.ok) {
|
|
@@ -273,6 +361,14 @@ class OpenAiCompatProvider {
|
|
|
273
361
|
completionTokens: json.usage.completion_tokens ?? 0,
|
|
274
362
|
}
|
|
275
363
|
: undefined;
|
|
364
|
+
if (json.choices?.[0]?.finish_reason === "length") {
|
|
365
|
+
return {
|
|
366
|
+
ok: false,
|
|
367
|
+
failureClass: "malformed",
|
|
368
|
+
error: "provider returned incomplete decision (output token limit)",
|
|
369
|
+
usage,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
276
372
|
return text
|
|
277
373
|
? {
|
|
278
374
|
ok: true,
|
|
@@ -303,20 +399,24 @@ class OpenAiCompatProvider {
|
|
|
303
399
|
}
|
|
304
400
|
}
|
|
305
401
|
}
|
|
306
|
-
//
|
|
307
|
-
//
|
|
308
|
-
//
|
|
309
|
-
// receive this wrapper. No
|
|
310
|
-
//
|
|
402
|
+
// Direct NVIDIA recovery has one shared two-call/deadline budget. Explicit
|
|
403
|
+
// server refusals retry the original request; rejected Super tool encoding
|
|
404
|
+
// retries JSON content on the same configured route. The shared router owns
|
|
405
|
+
// its own admission budget and MUST NOT receive this wrapper. No model
|
|
406
|
+
// substitution or repair/coercion of a rejected decision is allowed.
|
|
311
407
|
class SameModelRetryProvider {
|
|
312
408
|
delegate;
|
|
313
409
|
provider;
|
|
314
410
|
model;
|
|
411
|
+
contentRetry;
|
|
412
|
+
baseUrl;
|
|
315
413
|
label;
|
|
316
|
-
constructor(delegate, provider, model) {
|
|
414
|
+
constructor(delegate, provider, model, contentRetry, baseUrl) {
|
|
317
415
|
this.delegate = delegate;
|
|
318
416
|
this.provider = provider;
|
|
319
417
|
this.model = model;
|
|
418
|
+
this.contentRetry = contentRetry;
|
|
419
|
+
this.baseUrl = baseUrl;
|
|
320
420
|
this.label = delegate.label;
|
|
321
421
|
}
|
|
322
422
|
async decide(input) {
|
|
@@ -324,56 +424,99 @@ class SameModelRetryProvider {
|
|
|
324
424
|
const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
325
425
|
const first = await this.delegate.decide(input);
|
|
326
426
|
const firstFinished = Date.now();
|
|
327
|
-
|
|
427
|
+
const parsedFirst = first.ok
|
|
428
|
+
? parseDecisionForContract(first.text, input.decisionContract)
|
|
429
|
+
: undefined;
|
|
430
|
+
const retryContent = first.ok &&
|
|
431
|
+
parsedFirst?.ok === false &&
|
|
432
|
+
this.contentRetry !== undefined &&
|
|
433
|
+
canRetrySuperToolOutput({ provider: this.provider, model: this.model, baseUrl: this.baseUrl }, first.responseSource, parsedFirst.actionsStringDiagnostic);
|
|
434
|
+
if (!retryContent && (first.ok || !first.retryableHttpFailure)) {
|
|
328
435
|
return first;
|
|
329
436
|
}
|
|
330
|
-
const delayMs =
|
|
437
|
+
const delayMs = retryContent
|
|
438
|
+
? 0
|
|
439
|
+
: Math.max(1000, first.ok ? 0 : (first.retryAfterMs ?? 0));
|
|
331
440
|
// Honor the provider's cooldown; a long one waits for the next cycle. Both
|
|
332
441
|
// attempts and this backoff share the ORIGINAL deadline, never two 5m caps.
|
|
333
442
|
if (delayMs > 5000 || delayMs >= timeoutMs - (firstFinished - started)) {
|
|
334
443
|
return first;
|
|
335
444
|
}
|
|
336
|
-
|
|
445
|
+
if (delayMs > 0)
|
|
446
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
337
447
|
const retryStarted = Date.now();
|
|
338
448
|
const remainingMs = timeoutMs - (retryStarted - started);
|
|
339
449
|
if (remainingMs <= 0)
|
|
340
450
|
return first;
|
|
341
|
-
const
|
|
451
|
+
const retryResult = await (retryContent ? this.contentRetry : this.delegate).decide({
|
|
342
452
|
...input,
|
|
343
453
|
timeoutMs: remainingMs,
|
|
344
454
|
});
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
:
|
|
362
|
-
|
|
455
|
+
const parsedRetry = retryResult.ok
|
|
456
|
+
? parseDecisionForContract(retryResult.text, input.decisionContract)
|
|
457
|
+
: undefined;
|
|
458
|
+
const result = retryResult.ok && parsedRetry?.ok === false
|
|
459
|
+
? {
|
|
460
|
+
ok: false,
|
|
461
|
+
failureClass: "malformed",
|
|
462
|
+
error: parsedRetry.error,
|
|
463
|
+
usage: retryResult.usage,
|
|
464
|
+
}
|
|
465
|
+
: retryResult;
|
|
466
|
+
const attempt = (res, latencyMs) => {
|
|
467
|
+
const parsed = res.ok
|
|
468
|
+
? parseDecisionForContract(res.text, input.decisionContract)
|
|
469
|
+
: undefined;
|
|
470
|
+
return {
|
|
471
|
+
provider: this.provider,
|
|
472
|
+
model: this.model,
|
|
473
|
+
outcome: res.ok && parsed?.ok ? "success" : "failed",
|
|
474
|
+
latencyMs,
|
|
475
|
+
...(res.ok ? { responseSource: res.responseSource } : {}),
|
|
476
|
+
...(parsed?.ok === false
|
|
477
|
+
? {
|
|
478
|
+
failureClass: "malformed",
|
|
479
|
+
error: parsed.error,
|
|
480
|
+
actionsStringDiagnostic: parsed.actionsStringDiagnostic,
|
|
481
|
+
}
|
|
482
|
+
: {}),
|
|
483
|
+
...(!res.ok
|
|
484
|
+
? {
|
|
485
|
+
error: res.error,
|
|
486
|
+
status: res.status,
|
|
487
|
+
retryAfterMs: res.retryAfterMs,
|
|
488
|
+
failureClass: res.failureClass ??
|
|
489
|
+
(classifyProviderFailure(res) === "capacity"
|
|
490
|
+
? "capacity"
|
|
491
|
+
: res.status !== undefined && res.status < 500
|
|
492
|
+
? "permanent"
|
|
493
|
+
: "transient"),
|
|
494
|
+
}
|
|
495
|
+
: {}),
|
|
496
|
+
};
|
|
497
|
+
};
|
|
498
|
+
// Sum reported usage from both physical calls, including rejected output.
|
|
499
|
+
// Missing usage is unknown, not evidence that a request consumed no tokens.
|
|
500
|
+
const usage = first.usage || result.usage
|
|
501
|
+
? {
|
|
502
|
+
promptTokens: (first.usage?.promptTokens ?? 0) +
|
|
503
|
+
(result.usage?.promptTokens ?? 0),
|
|
504
|
+
completionTokens: (first.usage?.completionTokens ?? 0) +
|
|
505
|
+
(result.usage?.completionTokens ?? 0),
|
|
506
|
+
}
|
|
507
|
+
: undefined;
|
|
363
508
|
return {
|
|
364
|
-
// Usage, when present, describes only the final response. The preceding
|
|
365
|
-
// 5xx did not report usage; attempt evidence is not total billed tokens
|
|
366
|
-
// or a certificate that returned text passed the trading-decision parser.
|
|
367
509
|
...result,
|
|
510
|
+
...(usage ? { usage } : {}),
|
|
368
511
|
route: {
|
|
369
|
-
policyVersion: "coinrithm.configured-same-model-retry.
|
|
512
|
+
policyVersion: "coinrithm.configured-same-model-retry.v3",
|
|
370
513
|
profile: "configured",
|
|
371
514
|
effectiveProvider: this.provider,
|
|
372
515
|
effectiveModel: this.model,
|
|
373
516
|
reason: "configured_direct",
|
|
374
517
|
attempts: [
|
|
375
518
|
attempt(first, firstFinished - started),
|
|
376
|
-
attempt(
|
|
519
|
+
attempt(retryResult, Date.now() - retryStarted),
|
|
377
520
|
],
|
|
378
521
|
},
|
|
379
522
|
};
|
|
@@ -382,7 +525,7 @@ class SameModelRetryProvider {
|
|
|
382
525
|
// Build the provider from the spec's model block + env key. Throws a clear
|
|
383
526
|
// error if no model is configured (self-host requires one) or the env key is
|
|
384
527
|
// missing. fetch is injectable for tests.
|
|
385
|
-
export function selectProvider(spec, env, fetchFn = fetch) {
|
|
528
|
+
export function selectProvider(spec, env, fetchFn = fetch, options = {}) {
|
|
386
529
|
if (!spec.model) {
|
|
387
530
|
throw new Error("no model configured: set model.provider + model.name in the agent (self-host needs an explicit model)");
|
|
388
531
|
}
|
|
@@ -411,15 +554,17 @@ export function selectProvider(spec, env, fetchFn = fetch) {
|
|
|
411
554
|
if (!resolvedBase) {
|
|
412
555
|
throw new Error("openai-compatible provider needs model.baseUrl");
|
|
413
556
|
}
|
|
414
|
-
const direct = new OpenAiCompatProvider(provider, name, key, resolvedBase, fetchFn);
|
|
557
|
+
const direct = new OpenAiCompatProvider(provider, name, key, resolvedBase, fetchFn, options);
|
|
415
558
|
return provider === "nvidia"
|
|
416
|
-
? new SameModelRetryProvider(direct, provider, name
|
|
559
|
+
? new SameModelRetryProvider(direct, provider, name, new OpenAiCompatProvider(provider, name, key, resolvedBase, fetchFn, {
|
|
560
|
+
nemotronJsonContent: true,
|
|
561
|
+
}), baseUrl)
|
|
417
562
|
: direct;
|
|
418
563
|
}
|
|
419
564
|
// Build a provider for an EXPLICIT route + raw key (no spec, no env) — the
|
|
420
565
|
// decision probe's entry point. Same classes as selectProvider, so a probe
|
|
421
566
|
// exercises byte-identical request shapes to a real cycle.
|
|
422
|
-
export function providerForRoute(route, apiKey, fetchFn = fetch) {
|
|
567
|
+
export function providerForRoute(route, apiKey, fetchFn = fetch, options = {}) {
|
|
423
568
|
if (route.provider === "mechanical")
|
|
424
569
|
return new MechanicalProvider(route.model);
|
|
425
570
|
if (route.provider === "anthropic")
|
|
@@ -428,5 +573,5 @@ export function providerForRoute(route, apiKey, fetchFn = fetch) {
|
|
|
428
573
|
if (!resolvedBase) {
|
|
429
574
|
throw new Error("openai-compatible route needs a baseUrl");
|
|
430
575
|
}
|
|
431
|
-
return new OpenAiCompatProvider(route.provider, route.model, apiKey, resolvedBase, fetchFn);
|
|
576
|
+
return new OpenAiCompatProvider(route.provider, route.model, apiKey, resolvedBase, fetchFn, options);
|
|
432
577
|
}
|
package/dist/agent/resolve.js
CHANGED
package/dist/agent/runner.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CoinRithmClient, ProvenanceReport } from "./client.js";
|
|
2
2
|
import { Provider } from "./providers.js";
|
|
3
|
-
import { AgentSpec, RunState, CycleResult, Decision, ProposedAction, PmMarket, PostedOpportunity, QuoteEvidence } from "./types.js";
|
|
3
|
+
import { AgentSpec, RunState, CycleResult, Decision, PlannedAction, ProposedAction, PmMarket, PostedOpportunity, QuoteEvidence, LastRejection, TakeProfitRepair } from "./types.js";
|
|
4
|
+
import { type ObserveOptions } from "./observe.js";
|
|
4
5
|
import { type DecisionInputRecord } from "./decisionReceipt.js";
|
|
5
6
|
export interface RunnerDeps {
|
|
6
7
|
client: CoinRithmClient;
|
|
@@ -13,6 +14,13 @@ export interface RunnerDeps {
|
|
|
13
14
|
log?: (line: string) => void;
|
|
14
15
|
/** Optional private storage hook. Its failure never changes cycle execution. */
|
|
15
16
|
onDecisionInputRecord?: (record: DecisionInputRecord) => void;
|
|
17
|
+
/** Hosted shared-pool admission only; protective checks still run every cycle. */
|
|
18
|
+
minModelIntervalSeconds?: number;
|
|
19
|
+
/** Opt-in hosted canary; changes presentation only, preserving all values. */
|
|
20
|
+
compactPromptTables?: boolean;
|
|
21
|
+
/** Bench replay only (bench.ts): observation overrides. Live runs never
|
|
22
|
+
* set it. */
|
|
23
|
+
observeOptions?: ObserveOptions;
|
|
16
24
|
}
|
|
17
25
|
export declare function houseAgentForecastEnabled(): boolean;
|
|
18
26
|
export declare function agentOpportunityCaptureEnabled(): boolean;
|
|
@@ -22,7 +30,15 @@ export declare function sanitizeForecastProbability(raw: unknown): number | unde
|
|
|
22
30
|
export declare function repairFuturesTakeProfit(action: ProposedAction, quote?: QuoteEvidence, capitalMinimumRewardRisk?: number): {
|
|
23
31
|
action: ProposedAction;
|
|
24
32
|
repaired: boolean;
|
|
33
|
+
reason?: TakeProfitRepair["reason"];
|
|
25
34
|
};
|
|
35
|
+
export declare const LAST_REJECTIONS_MAX = 5;
|
|
36
|
+
/**
|
|
37
|
+
* Pure: the rejected actions of one validated decision, newest decision only,
|
|
38
|
+
* for the next prompt. Undefined when nothing was rejected, so a fixed
|
|
39
|
+
* mistake drops out at once.
|
|
40
|
+
*/
|
|
41
|
+
export declare function lastRejectionsOf(planned: readonly PlannedAction[], at: string): LastRejection[] | undefined;
|
|
26
42
|
export declare function rationaleForAction(a: ProposedAction, decisionRationale: string | undefined, perActionSummary: string | undefined, totalActions: number): string | undefined;
|
|
27
43
|
export declare function buildSkipOpportunity(decision: Decision, pmMarkets: PmMarket[], forecastEnabled: boolean): PostedOpportunity | null;
|
|
28
44
|
export declare function runCycle(deps: RunnerDeps): Promise<CycleResult>;
|