rtr-bench 0.2.0 → 0.2.1
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/README.md +3 -1
- package/dist/cli.js +114 -22
- package/docs/development-pilot-2026-11-14.json +262 -0
- package/docs/distribution.md +1 -1
- package/docs/final-run-plan-8000.json +900 -0
- package/docs/final-run-plan-8000.md +73 -0
- package/docs/learn-room.md +7 -5
- package/docs/npm-release.md +5 -5
- package/docs/preflight-audit.md +81 -0
- package/docs/preflight-providers-2026-11-14.json +497 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -201,7 +201,9 @@ Predict and Learn currently execute requests sequentially. Each Learn episode co
|
|
|
201
201
|
|
|
202
202
|
On 45 targets, Predict and Learn together typically use about 270 model calls. Adding `--controls` brings that to about 360: 45 for Predict, 45 for each automatic control, and approximately five calls per Learn episode. Early stopping can reduce that number; additional agent turns and transport retries can increase it. The first final GLM run used 347 calls.
|
|
203
203
|
|
|
204
|
-
|
|
204
|
+
In version 0.2.1, the public commands default to 8,000 output tokens per response. Learn uses the published `transfer-check-v1` policy, up to three inspected examples, and eight model turns. Advanced runs can override `--max-tokens` and, for Learn, `--agent-policy`.
|
|
205
|
+
|
|
206
|
+
To resume a run created with the earlier 4,000-token default, repeat its original command with `--max-tokens 4000` explicitly. Changing the allowance creates a separate run. The [final evaluation plan](docs/final-run-plan-8000.md) declares 8,000 tokens for all eleven models, including a new GLM result under that same setting.
|
|
205
207
|
|
|
206
208
|
The current client uses OpenRouter. Direct connections to other hosted or local endpoints are not yet implemented.
|
|
207
209
|
|
package/dist/cli.js
CHANGED
|
@@ -1122,6 +1122,19 @@ function meanCI(values, groups, reps = 2e3) {
|
|
|
1122
1122
|
var API_URL = "https://openrouter.ai/api/v1/chat/completions";
|
|
1123
1123
|
var MAX_ATTEMPTS = 3;
|
|
1124
1124
|
var TIMEOUT_MS = 6e4;
|
|
1125
|
+
function errorCode(response, httpStatus) {
|
|
1126
|
+
const code = Number(response?.error?.code);
|
|
1127
|
+
return Number.isInteger(code) && code >= 400 && code <= 599 ? code : httpStatus;
|
|
1128
|
+
}
|
|
1129
|
+
function isSetupFailure(attempt) {
|
|
1130
|
+
if (attempt.status !== "error") return false;
|
|
1131
|
+
const type = attempt.response?.error?.metadata?.error_type;
|
|
1132
|
+
if (["refusal", "content_policy_violation", "max_tokens_exceeded", "rate_limit_exceeded", "provider_overloaded", "provider_unavailable", "server", "timeout"].includes(type)) return false;
|
|
1133
|
+
if (["authentication", "permission_denied", "payment_required", "invalid_request", "invalid_prompt", "not_found", "precondition_failed", "payload_too_large", "unprocessable", "context_length_exceeded", "string_too_long", "token_limit_exceeded"].includes(type)) return true;
|
|
1134
|
+
return [400, 401, 402, 404, 413, 422].includes(errorCode(attempt.response, attempt.httpStatus) ?? 0);
|
|
1135
|
+
}
|
|
1136
|
+
var RunSetupError = class extends Error {
|
|
1137
|
+
};
|
|
1125
1138
|
function retryDelayMs(attempt, previousAttempts) {
|
|
1126
1139
|
const metadata = attempt?.response?.error?.metadata;
|
|
1127
1140
|
const seconds = Number(metadata?.retry_after_seconds);
|
|
@@ -1147,6 +1160,8 @@ async function requestCompletion(body, apiKey2, fetcher = fetch) {
|
|
|
1147
1160
|
const error = !res.ok || response?.error ? `HTTP ${res.status}: ${JSON.stringify(response?.error ?? response).slice(0, 500)}` : null;
|
|
1148
1161
|
const retryHeader = res.headers.get("retry-after");
|
|
1149
1162
|
const retryAfterMs = retryHeader ? Number.isFinite(Number(retryHeader)) ? Math.max(0, Number(retryHeader) * 1e3) : Math.max(0, Date.parse(retryHeader) - Date.now()) : 0;
|
|
1163
|
+
const errorType = response?.error?.metadata?.error_type;
|
|
1164
|
+
const retryableError = errorType ? ["rate_limit_exceeded", "provider_overloaded", "provider_unavailable", "server", "timeout"].includes(errorType) : [429, 500, 502, 503, 504].includes(errorCode(response, res.status) ?? 0);
|
|
1150
1165
|
return {
|
|
1151
1166
|
status: error ? "error" : "response",
|
|
1152
1167
|
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1156,7 +1171,7 @@ async function requestCompletion(body, apiKey2, fetcher = fetch) {
|
|
|
1156
1171
|
provider: typeof response?.provider === "string" ? response.provider : null,
|
|
1157
1172
|
usage: response?.usage && typeof response.usage === "object" ? response.usage : null,
|
|
1158
1173
|
error,
|
|
1159
|
-
retriable:
|
|
1174
|
+
retriable: !!error && retryableError,
|
|
1160
1175
|
...Number.isFinite(retryAfterMs) && retryAfterMs > 0 ? { retryAfterMs } : {}
|
|
1161
1176
|
};
|
|
1162
1177
|
} catch (e) {
|
|
@@ -1621,8 +1636,8 @@ async function discoverSpendingPolicy(model, provider, limitUsd, fetcher = fetch
|
|
|
1621
1636
|
if (!suitable.length) throw new Error("No suitable text endpoint supports the spending guard");
|
|
1622
1637
|
return suitable[0];
|
|
1623
1638
|
}
|
|
1624
|
-
function spendingProvider(policy) {
|
|
1625
|
-
return { order: [policy.providerTag], allow_fallbacks: false, max_price: { prompt: policy.inputUsdPerToken * 1e6, completion: policy.outputUsdPerToken * 1e6, request: 0 } };
|
|
1639
|
+
function spendingProvider(policy, requireParameters = false) {
|
|
1640
|
+
return { order: [policy.providerTag], allow_fallbacks: false, max_price: { prompt: policy.inputUsdPerToken * 1e6, completion: policy.outputUsdPerToken * 1e6, request: 0 }, ...requireParameters ? { require_parameters: true } : {} };
|
|
1626
1641
|
}
|
|
1627
1642
|
function openSpendingLedger(file2, policy) {
|
|
1628
1643
|
if (!["reserved-context-v1", "reserved-text-v2"].includes(policy.version) || !Number.isFinite(policy.limitUsd) || policy.limitUsd <= 0 || !Number.isSafeInteger(policy.contextTokens) || policy.contextTokens < 1 || !policy.providerTag || [policy.inputUsdPerToken, policy.outputUsdPerToken].some((p) => !Number.isFinite(p) || p <= 0)) throw new Error("Invalid spending policy");
|
|
@@ -1632,12 +1647,14 @@ function openSpendingLedger(file2, policy) {
|
|
|
1632
1647
|
}
|
|
1633
1648
|
const ledger = fs10.existsSync(file2) ? readJson(file2) : { policy, entries: [] };
|
|
1634
1649
|
if (JSON.stringify(ledger.policy) !== JSON.stringify(policy)) throw new Error("Spending ledger policy mismatch");
|
|
1650
|
+
if (!Array.isArray(ledger.entries) || ledger.entries.some((e) => !Number.isSafeInteger(e.reservedUnits) || e.reservedUnits < 0 || e.chargedUnits !== null && (!Number.isSafeInteger(e.chargedUnits) || e.chargedUnits < 0))) throw new Error("Invalid spending ledger entries");
|
|
1635
1651
|
const accounted = () => ledger.entries.reduce((s, e) => s + (e.chargedUnits ?? e.reservedUnits), 0);
|
|
1636
1652
|
const save = () => writeJson(file2, ledger);
|
|
1637
1653
|
save();
|
|
1638
1654
|
return {
|
|
1639
|
-
reserve(request) {
|
|
1640
|
-
if (
|
|
1655
|
+
reserve(request, requestKey) {
|
|
1656
|
+
if (ledger.entries.some((e) => e.chargedUnits !== null && e.chargedUnits > e.reservedUnits)) throw new SpendingLimitError("A saved provider charge exceeded its reservation; stopping for review");
|
|
1657
|
+
if (JSON.stringify(request.provider) !== JSON.stringify(spendingProvider(policy, request.provider?.require_parameters === true))) throw new Error("Request must use the budget's pinned provider and price ceiling");
|
|
1641
1658
|
if (!Number.isSafeInteger(request.max_tokens) || request.max_tokens <= 0) throw new Error("Budgeted requests require a finite output limit");
|
|
1642
1659
|
if (policy.version === "reserved-text-v2") {
|
|
1643
1660
|
const allowed = ["model", "messages", "temperature", "max_tokens", "usage", "provider"];
|
|
@@ -1647,18 +1664,23 @@ function openSpendingLedger(file2, policy) {
|
|
|
1647
1664
|
}
|
|
1648
1665
|
if (Buffer.byteLength(JSON.stringify(request.messages), "utf8") + 1024 * request.messages.length > policy.contextTokens) throw new SpendingLimitError("Request is too large for the conservative spending guard");
|
|
1649
1666
|
const reservedUnits = units(policy.contextTokens * policy.inputUsdPerToken + request.max_tokens * policy.outputUsdPerToken);
|
|
1667
|
+
if (!Number.isSafeInteger(reservedUnits)) throw new SpendingLimitError("Reservation exceeds safe accounting precision");
|
|
1650
1668
|
if (accounted() + reservedUnits > Math.floor(policy.limitUsd * 1e9)) throw new SpendingLimitError("Spending limit reached; next request was not sent");
|
|
1651
|
-
ledger.entries.
|
|
1669
|
+
if (requestKey && ledger.entries.some((e) => e.requestKey === requestKey)) throw new SpendingLimitError("Saved reservation has no matching attempt; stopping for review");
|
|
1670
|
+
ledger.entries.push({ reservedUnits, chargedUnits: null, at: (/* @__PURE__ */ new Date()).toISOString(), ...requestKey ? { requestKey } : {} });
|
|
1652
1671
|
save();
|
|
1653
1672
|
return ledger.entries.length - 1;
|
|
1654
1673
|
},
|
|
1655
|
-
settle(index, usage, attempt) {
|
|
1674
|
+
settle(index, usage, attempt, requestKey) {
|
|
1675
|
+
const entry = ledger.entries[index];
|
|
1676
|
+
if (!Number.isSafeInteger(index) || !entry || requestKey !== void 0 && entry.requestKey !== requestKey) throw new Error("Spending reservation does not match saved attempt");
|
|
1656
1677
|
const response = attempt?.response;
|
|
1657
1678
|
const rejected = attempt?.httpStatus === 429 && response?.error?.code === 429 && response?.error?.metadata?.provider_error_code === "rate_limit_exceeded" && !response?.id && !response?.choices;
|
|
1658
1679
|
const cost = usage?.cost ?? usage?.total_cost ?? (rejected ? 0 : null);
|
|
1659
1680
|
if (typeof cost === "number" && Number.isFinite(cost) && cost >= 0) {
|
|
1660
|
-
const
|
|
1661
|
-
entry.chargedUnits
|
|
1681
|
+
const chargedUnits = units(cost);
|
|
1682
|
+
if (!Number.isSafeInteger(chargedUnits) || entry.chargedUnits !== null && entry.chargedUnits !== chargedUnits) throw new Error("Conflicting or invalid saved charge");
|
|
1683
|
+
entry.chargedUnits = chargedUnits;
|
|
1662
1684
|
entry.costBasis = typeof usage?.cost === "number" || typeof usage?.total_cost === "number" ? "reported-cost" : "unbilled-rate-limit: https://openrouter.ai/pricing";
|
|
1663
1685
|
save();
|
|
1664
1686
|
if (entry.chargedUnits > entry.reservedUnits) throw new SpendingLimitError("Provider cost exceeded its reservation; stopping for review");
|
|
@@ -1698,6 +1720,7 @@ function agentRequest(config, messages) {
|
|
|
1698
1720
|
const request = { model: config.model, messages: structuredClone(messages), ...config.settings.temperature === null ? {} : { temperature: config.settings.temperature }, max_tokens: config.settings.maxTokens, usage: { include: true } };
|
|
1699
1721
|
if (config.provider) request.provider = { order: [config.provider], allow_fallbacks: false };
|
|
1700
1722
|
if (config.spending) request.provider = spendingProvider(config.spending);
|
|
1723
|
+
if (config.version === "learn-room-runner-v4" && request.provider) request.provider.require_parameters = true;
|
|
1701
1724
|
return request;
|
|
1702
1725
|
}
|
|
1703
1726
|
function callFinished(attempts) {
|
|
@@ -1821,6 +1844,7 @@ function learnRoomMarkdown(r) {
|
|
|
1821
1844
|
"",
|
|
1822
1845
|
`${r.manifest.config.partition}; ${r.scope}; ${r.complete ? "complete" : "incomplete"}. Evidence budget: ${r.manifest.config.budget}; seed: ${r.manifest.config.seed}.${r.manifest.config.agentPolicy ? ` Agent policy: ${r.manifest.config.agentPolicy}.` : ""}`,
|
|
1823
1846
|
"",
|
|
1847
|
+
...r.manifest.stopReason ? [`Stopped: ${r.manifest.stopReason.replace(/\s+/g, " ")}`, ""] : [],
|
|
1824
1848
|
...temperatureNote(r) ? [temperatureNote(r), ""] : [],
|
|
1825
1849
|
"| Strategy | Score / 100 | Valid / invalid / missing / pending | Inspections | Model turns | API calls | Known tokens | Unknown-token attempts | Known cost USD | Unknown-cost attempts |",
|
|
1826
1850
|
"|---|---:|---|---:|---:|---:|---:|---:|---:|---:|",
|
|
@@ -1843,7 +1867,7 @@ function learnRoomHtml(r) {
|
|
|
1843
1867
|
const e = escapeHtml;
|
|
1844
1868
|
return `<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Learn the Room</title><style>body{font:16px system-ui;max-width:1100px;margin:40px auto;padding:0 20px;background:#f7f8fa;color:#20242b}article{background:white;padding:20px;margin:20px 0;border:1px solid #ccd3dd;border-radius:8px}table{border-collapse:collapse;width:100%}td,th{text-align:left;padding:9px;border-bottom:1px solid #ddd}pre{white-space:pre-wrap;overflow-wrap:anywhere;font-size:12px}summary{cursor:pointer}input,select{padding:8px;margin:8px}.badge{color:#843600;font-weight:bold}</style>
|
|
1845
1869
|
<h1>Learn the Room</h1><p class="badge">${r.manifest.config.mode === "fixture" ? "SYNTHETIC FIXTURE \u2014 not model performance" : e(r.manifest.config.model)}</p><p>${e(r.manifest.config.partition)} \xB7 ${r.scope} \xB7 ${r.complete ? "Complete" : "Incomplete"} \xB7 Inspection budget ${r.manifest.config.budget} \xB7 Seed ${r.manifest.config.seed}${r.manifest.config.agentPolicy ? ` \xB7 Agent policy ${e(r.manifest.config.agentPolicy)}` : ""}</p>
|
|
1846
|
-
${temperatureNote(r) ? `<p>${temperatureNote(r)}</p>` : ""}<table><tr><th>Strategy</th><th>Score / 100</th><th>95% interval</th><th>Inspections</th><th>Model turns</th><th>API calls</th><th>Known tokens</th><th>Unknown-token attempts</th><th>Known USD</th><th>Unknown-cost attempts</th></tr>${r.summaries.map((s) => `<tr><td>${s.strategy}</td><td>${fmt2(s.score)}</td><td>${s.scoreCI ? s.scoreCI.map(fmt2).join("\u2013") : "\u2014"}</td><td>${s.inspections}</td><td>${s.modelCalls}</td><td>${s.apiCalls}</td><td>${s.tokens.known}</td><td>${s.tokens.unknownAttempts}</td><td>${s.costUsd.known.toFixed(6)}</td><td>${s.costUsd.unknownAttempts}</td></tr>`).join("")}</table><p>Uniform: ${fmt2(r.baselines.uniformScore)}. Constant reference: ${fmt2(r.baselines.constantScore)}.</p><table><tr><th>Comparison</th><th>Gain (points)</th><th>Paired 95% interval</th></tr>${r.comparisons.map((p) => `<tr><td>${p.strategy} vs ${p.control}</td><td>${fmt2(p.scoreGain)}</td><td>${p.scoreGainCI.map(fmt2).join("\u2013")}</td></tr>`).join("")}</table><p>Scores are transformed distribution errors, not percentage accuracy. Invalid and missing predictions earn zero points. Usage is reported separately. Five-target synthetic pilots demonstrate the pipeline only.</p>
|
|
1870
|
+
${r.manifest.stopReason ? `<p>Stopped: ${e(r.manifest.stopReason)}</p>` : ""}${temperatureNote(r) ? `<p>${temperatureNote(r)}</p>` : ""}<table><tr><th>Strategy</th><th>Score / 100</th><th>95% interval</th><th>Inspections</th><th>Model turns</th><th>API calls</th><th>Known tokens</th><th>Unknown-token attempts</th><th>Known USD</th><th>Unknown-cost attempts</th></tr>${r.summaries.map((s) => `<tr><td>${s.strategy}</td><td>${fmt2(s.score)}</td><td>${s.scoreCI ? s.scoreCI.map(fmt2).join("\u2013") : "\u2014"}</td><td>${s.inspections}</td><td>${s.modelCalls}</td><td>${s.apiCalls}</td><td>${s.tokens.known}</td><td>${s.tokens.unknownAttempts}</td><td>${s.costUsd.known.toFixed(6)}</td><td>${s.costUsd.unknownAttempts}</td></tr>`).join("")}</table><p>Uniform: ${fmt2(r.baselines.uniformScore)}. Constant reference: ${fmt2(r.baselines.constantScore)}.</p><table><tr><th>Comparison</th><th>Gain (points)</th><th>Paired 95% interval</th></tr>${r.comparisons.map((p) => `<tr><td>${p.strategy} vs ${p.control}</td><td>${fmt2(p.scoreGain)}</td><td>${p.scoreGainCI.map(fmt2).join("\u2013")}</td></tr>`).join("")}</table><p>Scores are transformed distribution errors, not percentage accuracy. Invalid and missing predictions earn zero points. Usage is reported separately. Five-target synthetic pilots demonstrate the pipeline only.</p>
|
|
1847
1871
|
<label>Prompt <input id="query" type="search"></label><label>Strategy <select id="strategy"><option value="">All</option>${r.manifest.config.strategies.map((s) => `<option>${s}</option>`).join("")}</select></label>
|
|
1848
1872
|
${r.rows.map((row) => `<article data-search="${e(`${row.day} ${row.word}`.toLowerCase())}" data-strategy="${row.strategy}"><h2>${row.day}: ${e(row.word)} \xB7 ${row.strategy}</h2><p>${row.n} submissions \xB7 ${row.outcome ? `${row.outcome.status} \xB7 ${fmt2(row.outcome.score)} / 100 \xB7 ${row.outcome.inspections} inspections` : "Pending"}</p>${row.outcome?.failure ? `<p>${e(row.outcome.failure)}</p>` : ""}<table><tr><th>Quadrant</th><th>Predicted share</th><th>Observed share</th></tr>${QUADRANTS2.map((q) => `<tr><td>${q}</td><td>${row.outcome?.prediction ? fmt2(row.outcome.prediction[q]) : "\u2014"}</td><td>${fmt2(row.observed[q])}</td></tr>`).join("")}</table><details><summary>Actions and observations</summary><pre>${e(JSON.stringify(row.trace, null, 2))}</pre></details><details><summary>Model request and all attempts</summary><pre>${e(JSON.stringify({ request: row.request, attempts: row.attempts, agentCalls: row.agentCalls }, null, 2))}</pre></details></article>`).join("\n")}
|
|
1849
1873
|
<script>function filter(){const q=document.getElementById('query').value.toLowerCase(),s=document.getElementById('strategy').value;document.querySelectorAll('article').forEach(a=>a.hidden=!a.dataset.search.includes(q)||(s&&a.dataset.strategy!==s));}document.getElementById('query').addEventListener('input',filter);document.getElementById('strategy').addEventListener('change',filter);</script></html>`;
|
|
@@ -1857,6 +1881,31 @@ function writeLearnRoomReport(dir) {
|
|
|
1857
1881
|
}
|
|
1858
1882
|
|
|
1859
1883
|
// src/tracks/learn-room/run.ts
|
|
1884
|
+
function savedBudgetRun(root, config, limitUsd) {
|
|
1885
|
+
const identity = (c) => {
|
|
1886
|
+
const { spending, ...rest2 } = structuredClone(c);
|
|
1887
|
+
rest2.settings.temperature = 0;
|
|
1888
|
+
if (rest2.version === "learn-room-runner-v3") rest2.version = "learn-room-runner-v4";
|
|
1889
|
+
return JSON.stringify(rest2);
|
|
1890
|
+
};
|
|
1891
|
+
const prefix = config.model.replace(/[^a-zA-Z0-9]+/g, "-").toLowerCase() + "-";
|
|
1892
|
+
const matches = [];
|
|
1893
|
+
for (const entry of fs12.existsSync(root) ? fs12.readdirSync(root, { withFileTypes: true }) : []) {
|
|
1894
|
+
if (!entry.isDirectory() || !entry.name.startsWith(prefix)) continue;
|
|
1895
|
+
const file2 = path10.join(root, entry.name, "manifest.json");
|
|
1896
|
+
if (!fs12.existsSync(file2)) continue;
|
|
1897
|
+
const saved = readJson(file2);
|
|
1898
|
+
if (saved.config.spending?.limitUsd !== limitUsd || identity(saved.config) !== identity(config)) continue;
|
|
1899
|
+
if (saved.id !== digest(JSON.stringify(saved.config)) || entry.name !== prefix + saved.id.slice(0, 16)) throw new Error("Saved run fingerprint mismatch");
|
|
1900
|
+
if (saved.config.version !== config.version && saved.status !== "complete") throw new Error("An incomplete run from an older runner exists; review it before creating or resuming a paid run");
|
|
1901
|
+
matches.push(saved);
|
|
1902
|
+
}
|
|
1903
|
+
if (matches.length > 1) throw new Error("Multiple saved runs match this command; select a separate output directory after reviewing existing spending");
|
|
1904
|
+
return matches[0];
|
|
1905
|
+
}
|
|
1906
|
+
function stopForSetup(attempt) {
|
|
1907
|
+
if (isSetupFailure(attempt)) throw new RunSetupError(`API setup failed; run remains incomplete: ${attempt.error ?? "Inspect the saved API error"}`);
|
|
1908
|
+
}
|
|
1860
1909
|
function prepareEpisode(config, strategy, day, data = loadDistributionData()) {
|
|
1861
1910
|
const target = data.windows.find((w) => w.day === day);
|
|
1862
1911
|
if (!target || !config.targets.includes(day) || !config.strategies.includes(strategy)) throw new Error("Episode is outside the declared run");
|
|
@@ -1866,6 +1915,7 @@ function prepareEpisode(config, strategy, day, data = loadDistributionData()) {
|
|
|
1866
1915
|
const request = { model: config.model, messages, ...config.settings.temperature === null ? {} : { temperature: config.settings.temperature }, max_tokens: config.settings.maxTokens, usage: { include: true } };
|
|
1867
1916
|
if (config.provider) request.provider = { order: [config.provider], allow_fallbacks: false };
|
|
1868
1917
|
if (config.spending) request.provider = spendingProvider(config.spending);
|
|
1918
|
+
if (config.version === "learn-room-runner-v4" && request.provider) request.provider.require_parameters = true;
|
|
1869
1919
|
return { episode, request };
|
|
1870
1920
|
}
|
|
1871
1921
|
function finishEpisode(episode, attempts) {
|
|
@@ -1904,15 +1954,24 @@ async function runLearnRoom(options, client = requestCompletion) {
|
|
|
1904
1954
|
const model = fixture ? "fixture/synthetic" : options.model;
|
|
1905
1955
|
if (!model) throw new Error("Specify a model or --fixture <file>");
|
|
1906
1956
|
if (fixture && (options.maxUsd !== void 0 || options.spending)) throw new Error("Fixture runs do not need a spending policy");
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
if (spending?.version === "reserved-text-v2" && !spending.temperatureSupported) config.settings.temperature = null;
|
|
1911
|
-
config.version = "learn-room-runner-v3";
|
|
1957
|
+
if (options.maxUsd !== void 0 && (!Number.isFinite(options.maxUsd) || options.maxUsd <= 0 || !options.provider)) throw new Error("--max-usd must be positive and requires --provider");
|
|
1958
|
+
if (options.maxUsd !== void 0 && options.spending && options.spending.limitUsd !== options.maxUsd) throw new Error("Spending policy differs from requested budget");
|
|
1959
|
+
let config = { track: "learn-room", version: "learn-room-runner-v4", scorerVersion: DISTRIBUTION_VERSION, environmentVersion: ENVIRONMENT_VERSION, strategyVersion: STRATEGY_VERSION, similarityVersion: SIMILARITY_VERSION, agentVersion: AGENT_VERSION, agentPromptHash: policy.promptHash, maxModelCalls, promptHash: PROMPT_HASH2, evidenceInstruction: EVIDENCE_INSTRUCTION, datasetHash: data.datasetHash, splitHash: data.splitHash, partition, targets, reference: data.split.reference, strategies, budget, maxActions: MAX_ACTIONS, seed, model, provider: options.provider ?? null, mode: fixture ? "fixture" : "api", fixtureHash: fixtureRaw === null ? null : digest(fixtureRaw), settings: { temperature: 0, maxTokens, maxAttempts: MAX_ATTEMPTS, timeoutMs: TIMEOUT_MS, apiUrl: API_URL } };
|
|
1912
1960
|
config.settings.retryPolicy = "retry-after-v1";
|
|
1913
1961
|
if (options.replicate !== void 0) config.replicate = options.replicate;
|
|
1914
1962
|
if (policy.name !== "default") config.agentPolicy = policy.name;
|
|
1915
|
-
const
|
|
1963
|
+
const root = options.output ?? path10.join("results", "learn-room");
|
|
1964
|
+
const saved = !options.spending && options.maxUsd !== void 0 ? savedBudgetRun(root, config, options.maxUsd) : void 0;
|
|
1965
|
+
let spending = options.spending;
|
|
1966
|
+
if (saved) {
|
|
1967
|
+
config = saved.config;
|
|
1968
|
+
spending = config.spending;
|
|
1969
|
+
} else {
|
|
1970
|
+
spending ??= options.maxUsd !== void 0 ? await discoverSpendingPolicy(model, options.provider ?? "", options.maxUsd) : void 0;
|
|
1971
|
+
if (spending) config.spending = spending;
|
|
1972
|
+
if (spending?.version === "reserved-text-v2" && !spending.temperatureSupported) config.settings.temperature = null;
|
|
1973
|
+
}
|
|
1974
|
+
const id = digest(JSON.stringify(config)), dir = path10.join(root, `${model.replace(/[^a-zA-Z0-9]+/g, "-").toLowerCase()}-${id.slice(0, 16)}`);
|
|
1916
1975
|
fs12.mkdirSync(dir, { recursive: true });
|
|
1917
1976
|
const lock = path10.join(dir, "run.lock");
|
|
1918
1977
|
let fd;
|
|
@@ -1927,8 +1986,25 @@ async function runLearnRoom(options, client = requestCompletion) {
|
|
|
1927
1986
|
const manifestPath = path10.join(dir, "manifest.json");
|
|
1928
1987
|
const manifest = fs12.existsSync(manifestPath) ? readJson(manifestPath) : { id, createdAt: (/* @__PURE__ */ new Date()).toISOString(), config, status: "incomplete" };
|
|
1929
1988
|
if (manifest.id !== id || JSON.stringify(manifest.config) !== JSON.stringify(config)) throw new Error("Run manifest mismatch");
|
|
1989
|
+
if (spending && !fs12.existsSync(path10.join(dir, "spending.json")) && fs12.existsSync(path10.join(dir, "episodes"))) throw new Error("Spending ledger is missing for a saved run; refusing to reset its budget");
|
|
1990
|
+
if (fs12.existsSync(manifestPath)) {
|
|
1991
|
+
const prior = buildLearnRoomReport(dir);
|
|
1992
|
+
if (manifest.status === "complete" && prior.rows.some((row) => !fs12.existsSync(path10.join(dir, "episodes", row.strategy, `${row.day}.json`)))) throw new Error("Completed run has missing episodes; refusing to rerun saved evaluation targets");
|
|
1993
|
+
}
|
|
1930
1994
|
writeJson(manifestPath, manifest);
|
|
1931
1995
|
const ledger = spending ? openSpendingLedger(path10.join(dir, "spending.json"), spending) : null;
|
|
1996
|
+
if (ledger && config.version === "learn-room-runner-v4") {
|
|
1997
|
+
for (const s of strategies) for (const day of targets) {
|
|
1998
|
+
const file2 = path10.join(dir, "episodes", s, `${day}.json`);
|
|
1999
|
+
if (!fs12.existsSync(file2)) continue;
|
|
2000
|
+
const rec = readJson(file2);
|
|
2001
|
+
const calls = s === "agent" ? rec.agentCalls ?? [] : [{ attempts: rec.attempts }];
|
|
2002
|
+
for (const [turn, call2] of calls.entries()) for (const a of call2.attempts) {
|
|
2003
|
+
if (a.spendingReservation === void 0) throw new Error("Saved attempt has no spending reservation");
|
|
2004
|
+
ledger.settle(a.spendingReservation, a.usage, a, `${s}/${day}/${turn}/${a.index}`);
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
1932
2008
|
for (const s of strategies) for (const day of targets) {
|
|
1933
2009
|
const { episode, request } = prepareEpisode(config, s, day, data);
|
|
1934
2010
|
const file2 = path10.join(dir, "episodes", s, `${day}.json`);
|
|
@@ -1950,8 +2026,10 @@ async function runLearnRoom(options, client = requestCompletion) {
|
|
|
1950
2026
|
while (!callFinished(call2.attempts)) {
|
|
1951
2027
|
if (!fixture && !process.env.OPENROUTER_API_KEY) throw new Error("OPENROUTER_API_KEY is not set");
|
|
1952
2028
|
if (call2.attempts.length && !fixture) await new Promise((resolve) => setTimeout(resolve, retryDelayMs(call2.attempts.at(-1), call2.attempts.length)));
|
|
1953
|
-
const
|
|
2029
|
+
const requestKey = `${s}/${day}/${rec.agentCalls.length - 1}/${call2.attempts.length + 1}`;
|
|
2030
|
+
const reservation = ledger?.reserve(call2.request, requestKey);
|
|
1954
2031
|
const attempt = { index: call2.attempts.length + 1, startedAt: (/* @__PURE__ */ new Date()).toISOString(), status: "started", raw: "", response: null, provider: null, usage: null, error: null, retriable: true };
|
|
2032
|
+
if (reservation !== void 0) attempt.spendingReservation = reservation;
|
|
1955
2033
|
call2.attempts.push(attempt);
|
|
1956
2034
|
rec.attempts = rec.agentCalls.flatMap((c) => c.attempts);
|
|
1957
2035
|
writeJson(file2, rec);
|
|
@@ -1959,9 +2037,12 @@ async function runLearnRoom(options, client = requestCompletion) {
|
|
|
1959
2037
|
const raw = fixture[s][day][rec.agentCalls.length - 1] ?? "";
|
|
1960
2038
|
Object.assign(attempt, { status: "response", finishedAt: (/* @__PURE__ */ new Date()).toISOString(), raw, response: { fixture: true, content: raw }, usage: { total_tokens: 0, cost: 0 }, retriable: false });
|
|
1961
2039
|
} else Object.assign(attempt, await client(call2.request, process.env.OPENROUTER_API_KEY));
|
|
2040
|
+
if (isSetupFailure(attempt)) attempt.retriable = true;
|
|
1962
2041
|
writeJson(file2, rec);
|
|
1963
|
-
if (reservation !== void 0) ledger.settle(reservation, attempt.usage, attempt);
|
|
2042
|
+
if (reservation !== void 0) ledger.settle(reservation, attempt.usage, attempt, requestKey);
|
|
2043
|
+
stopForSetup(attempt);
|
|
1964
2044
|
}
|
|
2045
|
+
if (call2.attempts.length) stopForSetup(call2.attempts.at(-1));
|
|
1965
2046
|
applyAgentCall(episode, messages, call2);
|
|
1966
2047
|
call2.applied = true;
|
|
1967
2048
|
enforceAgentLimit(episode, rec.agentCalls, config);
|
|
@@ -1977,27 +2058,38 @@ async function runLearnRoom(options, client = requestCompletion) {
|
|
|
1977
2058
|
while (rec.attempts.length < MAX_ATTEMPTS && !(last && (last.status === "response" || last.status === "error" && !last.retriable))) {
|
|
1978
2059
|
if (!fixture && !process.env.OPENROUTER_API_KEY) throw new Error("OPENROUTER_API_KEY is not set");
|
|
1979
2060
|
if (rec.attempts.length && !fixture) await new Promise((resolve) => setTimeout(resolve, retryDelayMs(rec.attempts.at(-1), rec.attempts.length)));
|
|
1980
|
-
const
|
|
2061
|
+
const requestKey = `${s}/${day}/0/${rec.attempts.length + 1}`;
|
|
2062
|
+
const reservation = ledger?.reserve(request, requestKey);
|
|
1981
2063
|
const attempt = { index: rec.attempts.length + 1, startedAt: (/* @__PURE__ */ new Date()).toISOString(), status: "started", raw: "", response: null, provider: null, usage: null, error: null, retriable: true };
|
|
2064
|
+
if (reservation !== void 0) attempt.spendingReservation = reservation;
|
|
1982
2065
|
rec.attempts.push(attempt);
|
|
1983
2066
|
writeJson(file2, rec);
|
|
1984
2067
|
if (fixture) Object.assign(attempt, { status: "response", finishedAt: (/* @__PURE__ */ new Date()).toISOString(), raw: fixture[s][day], response: { fixture: true, content: fixture[s][day] }, usage: { total_tokens: 0, cost: 0 }, retriable: false });
|
|
1985
2068
|
else Object.assign(attempt, await client(request, process.env.OPENROUTER_API_KEY));
|
|
2069
|
+
if (isSetupFailure(attempt)) attempt.retriable = true;
|
|
1986
2070
|
writeJson(file2, rec);
|
|
1987
2071
|
last = attempt;
|
|
1988
|
-
if (reservation !== void 0) ledger.settle(reservation, attempt.usage, attempt);
|
|
2072
|
+
if (reservation !== void 0) ledger.settle(reservation, attempt.usage, attempt, requestKey);
|
|
2073
|
+
stopForSetup(attempt);
|
|
1989
2074
|
}
|
|
2075
|
+
if (last) stopForSetup(last);
|
|
1990
2076
|
Object.assign(rec, finishEpisode(episode, rec.attempts), { terminal: true });
|
|
1991
2077
|
writeJson(file2, rec);
|
|
1992
2078
|
console.log(`learn-room: ${s} day ${day} ${rec.outcome.status}, ${rec.outcome.inspections} inspections`);
|
|
1993
2079
|
}
|
|
1994
2080
|
manifest.status = "complete";
|
|
2081
|
+
delete manifest.stopReason;
|
|
1995
2082
|
manifest.completedAt ??= (/* @__PURE__ */ new Date()).toISOString();
|
|
1996
2083
|
writeJson(manifestPath, manifest);
|
|
1997
2084
|
if (ledger) console.log(`Spending: ${JSON.stringify(ledger.summary())}`);
|
|
1998
2085
|
return { dir, report: writeLearnRoomReport(dir) };
|
|
1999
2086
|
} catch (error) {
|
|
2000
|
-
if (error instanceof SpendingLimitError) {
|
|
2087
|
+
if (error instanceof SpendingLimitError || error instanceof RunSetupError) {
|
|
2088
|
+
const manifest = readJson(path10.join(dir, "manifest.json"));
|
|
2089
|
+
manifest.status = "incomplete";
|
|
2090
|
+
manifest.stopReason = error.message;
|
|
2091
|
+
delete manifest.completedAt;
|
|
2092
|
+
writeJson(path10.join(dir, "manifest.json"), manifest);
|
|
2001
2093
|
writeLearnRoomReport(dir);
|
|
2002
2094
|
console.error(`${error.message}. Incomplete report: ${dir}`);
|
|
2003
2095
|
}
|
|
@@ -2049,7 +2141,7 @@ if (["read-the-room", "predict", "learn", "learn-room"].includes(cmd)) {
|
|
|
2049
2141
|
partition: flags.split ?? "development",
|
|
2050
2142
|
strategy,
|
|
2051
2143
|
maxModelCalls: flags["max-model-calls"] === void 0 ? void 0 : Number(flags["max-model-calls"]),
|
|
2052
|
-
maxTokens: flags["max-tokens"] === void 0 ? legacy ? void 0 :
|
|
2144
|
+
maxTokens: flags["max-tokens"] === void 0 ? legacy ? void 0 : 8e3 : Number(flags["max-tokens"]),
|
|
2053
2145
|
replicate: flags.replicate,
|
|
2054
2146
|
agentPolicy: flags["agent-policy"] ?? (!legacy && cmd !== "predict" ? "transfer-check-v1" : void 0),
|
|
2055
2147
|
maxUsd: flags["max-usd"] === void 0 ? void 0 : Number(flags["max-usd"]),
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
{
|
|
2
|
+
"createdAt": "2026-11-14T22:47:51.731Z",
|
|
3
|
+
"purpose": "Development compatibility pilot; not a model ranking or final evaluation",
|
|
4
|
+
"protocol": {
|
|
5
|
+
"partition": "development",
|
|
6
|
+
"targets": [
|
|
7
|
+
100,
|
|
8
|
+
101,
|
|
9
|
+
102
|
|
10
|
+
],
|
|
11
|
+
"strategy": "all",
|
|
12
|
+
"budget": 3,
|
|
13
|
+
"seed": 7,
|
|
14
|
+
"maxModelCalls": 8,
|
|
15
|
+
"maxActions": 8,
|
|
16
|
+
"maxTokens": 4000,
|
|
17
|
+
"agentPolicy": "transfer-check-v1"
|
|
18
|
+
},
|
|
19
|
+
"models": [
|
|
20
|
+
{
|
|
21
|
+
"model": "z-ai/glm-5.3",
|
|
22
|
+
"provider": "wafer/us",
|
|
23
|
+
"quantization": "fp4",
|
|
24
|
+
"catalogStatus": 0,
|
|
25
|
+
"source": "https://openrouter.ai/api/v1/models/z-ai/glm-5.3/endpoints",
|
|
26
|
+
"estimateUsd": 0.024543114233333333,
|
|
27
|
+
"reservationUsd": 0.07889546239999999,
|
|
28
|
+
"capUsd": 0.2,
|
|
29
|
+
"spending": {
|
|
30
|
+
"version": "reserved-context-v1",
|
|
31
|
+
"limitUsd": 0.2,
|
|
32
|
+
"providerTag": "wafer/us",
|
|
33
|
+
"contextTokens": 1048576,
|
|
34
|
+
"inputUsdPerToken": 6.99e-08,
|
|
35
|
+
"outputUsdPerToken": 1.4e-06
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"model": "minimax/minimax-m3.1-flash",
|
|
40
|
+
"provider": "inferact-vllm/nvfp4",
|
|
41
|
+
"quantization": "nvfp4",
|
|
42
|
+
"catalogStatus": 0,
|
|
43
|
+
"source": "https://openrouter.ai/api/v1/models/minimax/minimax-m3.1-flash/endpoints",
|
|
44
|
+
"estimateUsd": 0.006733225,
|
|
45
|
+
"reservationUsd": 0.0798432,
|
|
46
|
+
"capUsd": 0.15,
|
|
47
|
+
"spending": {
|
|
48
|
+
"version": "reserved-context-v1",
|
|
49
|
+
"limitUsd": 0.15,
|
|
50
|
+
"providerTag": "inferact-vllm/nvfp4",
|
|
51
|
+
"contextTokens": 1048576,
|
|
52
|
+
"inputUsdPerToken": 7.5e-08,
|
|
53
|
+
"outputUsdPerToken": 3e-07
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"model": "xiaomi/mimo-v2.6-flash",
|
|
58
|
+
"provider": "xiaomi/fp8",
|
|
59
|
+
"quantization": "fp8",
|
|
60
|
+
"catalogStatus": 0,
|
|
61
|
+
"source": "https://openrouter.ai/api/v1/models/xiaomi/mimo-v2.6-flash/endpoints",
|
|
62
|
+
"estimateUsd": 0.008003380000000001,
|
|
63
|
+
"reservationUsd": 0.14792064000000002,
|
|
64
|
+
"capUsd": 0.2,
|
|
65
|
+
"spending": {
|
|
66
|
+
"version": "reserved-context-v1",
|
|
67
|
+
"limitUsd": 0.2,
|
|
68
|
+
"providerTag": "xiaomi/fp8",
|
|
69
|
+
"contextTokens": 1048576,
|
|
70
|
+
"inputUsdPerToken": 1.4e-07,
|
|
71
|
+
"outputUsdPerToken": 2.8e-07
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"model": "deepseek/deepseek-v4.1-flash-1017",
|
|
76
|
+
"provider": "sail-research/fp4/us",
|
|
77
|
+
"quantization": "fp4",
|
|
78
|
+
"catalogStatus": 0,
|
|
79
|
+
"source": "https://openrouter.ai/api/v1/models/deepseek/deepseek-v4.1-flash-1017/endpoints",
|
|
80
|
+
"estimateUsd": 0.0035467375200000004,
|
|
81
|
+
"reservationUsd": 0.07668444672000001,
|
|
82
|
+
"capUsd": 0.1,
|
|
83
|
+
"spending": {
|
|
84
|
+
"version": "reserved-context-v1",
|
|
85
|
+
"limitUsd": 0.1,
|
|
86
|
+
"providerTag": "sail-research/fp4/us",
|
|
87
|
+
"contextTokens": 1048576,
|
|
88
|
+
"inputUsdPerToken": 7.272e-08,
|
|
89
|
+
"outputUsdPerToken": 1.08e-07
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"model": "tencent/hy3",
|
|
94
|
+
"provider": "gmicloud/bf16",
|
|
95
|
+
"quantization": "bf16",
|
|
96
|
+
"catalogStatus": 0,
|
|
97
|
+
"source": "https://openrouter.ai/api/v1/models/tencent/hy3/endpoints",
|
|
98
|
+
"estimateUsd": 0.01289478,
|
|
99
|
+
"reservationUsd": 0.039020160000000005,
|
|
100
|
+
"capUsd": 0.1,
|
|
101
|
+
"spending": {
|
|
102
|
+
"version": "reserved-context-v1",
|
|
103
|
+
"limitUsd": 0.1,
|
|
104
|
+
"providerTag": "gmicloud/bf16",
|
|
105
|
+
"contextTokens": 262144,
|
|
106
|
+
"inputUsdPerToken": 1.4e-07,
|
|
107
|
+
"outputUsdPerToken": 5.8e-07
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"model": "google/gemini-3.8-flash",
|
|
112
|
+
"provider": "google-ai-studio",
|
|
113
|
+
"quantization": "unknown",
|
|
114
|
+
"catalogStatus": 0,
|
|
115
|
+
"source": "https://openrouter.ai/api/v1/models/google/gemini-3.8-flash/endpoints",
|
|
116
|
+
"estimateUsd": 0.07956075,
|
|
117
|
+
"reservationUsd": 0.801432,
|
|
118
|
+
"capUsd": 1.05,
|
|
119
|
+
"spending": {
|
|
120
|
+
"version": "reserved-text-v2",
|
|
121
|
+
"limitUsd": 1.05,
|
|
122
|
+
"providerTag": "google-ai-studio",
|
|
123
|
+
"contextTokens": 1048576,
|
|
124
|
+
"inputUsdPerToken": 7.5e-07,
|
|
125
|
+
"outputUsdPerToken": 3.75e-06,
|
|
126
|
+
"model": "google/gemini-3.8-flash",
|
|
127
|
+
"temperatureSupported": true,
|
|
128
|
+
"maxCompletionTokens": 65536,
|
|
129
|
+
"pricing": {
|
|
130
|
+
"audio": "0.00000075",
|
|
131
|
+
"completion": "0.00000375",
|
|
132
|
+
"discount": 0.5,
|
|
133
|
+
"image": "0.00000075",
|
|
134
|
+
"input_audio_cache": "0.000000075",
|
|
135
|
+
"input_cache_read": "0.000000075",
|
|
136
|
+
"input_cache_write": "0.0000000416666666666667",
|
|
137
|
+
"internal_reasoning": "0.00000375",
|
|
138
|
+
"prompt": "0.00000075",
|
|
139
|
+
"web_search": "0.014"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"model": "openai/gpt-6-luna",
|
|
145
|
+
"provider": "openai",
|
|
146
|
+
"quantization": "unknown",
|
|
147
|
+
"catalogStatus": 0,
|
|
148
|
+
"source": "https://openrouter.ai/api/v1/models/openai/gpt-6-luna/endpoints",
|
|
149
|
+
"estimateUsd": 0.010608099999999999,
|
|
150
|
+
"reservationUsd": 0.13275,
|
|
151
|
+
"capUsd": 0.2,
|
|
152
|
+
"spending": {
|
|
153
|
+
"version": "reserved-text-v2",
|
|
154
|
+
"limitUsd": 0.2,
|
|
155
|
+
"providerTag": "openai/flex",
|
|
156
|
+
"contextTokens": 1050000,
|
|
157
|
+
"inputUsdPerToken": 1.25e-07,
|
|
158
|
+
"outputUsdPerToken": 3.75e-07,
|
|
159
|
+
"model": "openai/gpt-6-luna",
|
|
160
|
+
"temperatureSupported": false,
|
|
161
|
+
"maxCompletionTokens": 128000,
|
|
162
|
+
"pricing": {
|
|
163
|
+
"completion": "0.00000025",
|
|
164
|
+
"discount": 0,
|
|
165
|
+
"input_cache_read": "0.000000005",
|
|
166
|
+
"input_cache_write": "0.0000000625",
|
|
167
|
+
"overrides": [
|
|
168
|
+
{
|
|
169
|
+
"completion": "0.000000375",
|
|
170
|
+
"input_cache_read": "0.00000001",
|
|
171
|
+
"input_cache_write": "0.000000125",
|
|
172
|
+
"min_prompt_tokens": 272000,
|
|
173
|
+
"prompt": "0.0000001"
|
|
174
|
+
}
|
|
175
|
+
],
|
|
176
|
+
"prompt": "0.00000005",
|
|
177
|
+
"web_search": "0.01"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"model": "anthropic/claude-haiku-5.5",
|
|
183
|
+
"provider": "anthropic",
|
|
184
|
+
"quantization": "unknown",
|
|
185
|
+
"catalogStatus": 0,
|
|
186
|
+
"source": "https://openrouter.ai/api/v1/models/anthropic/claude-haiku-5.5/endpoints",
|
|
187
|
+
"estimateUsd": 0.010608099999999999,
|
|
188
|
+
"reservationUsd": 1.01,
|
|
189
|
+
"capUsd": 1.05,
|
|
190
|
+
"spending": {
|
|
191
|
+
"version": "reserved-text-v2",
|
|
192
|
+
"limitUsd": 1.05,
|
|
193
|
+
"providerTag": "anthropic",
|
|
194
|
+
"contextTokens": 1000000,
|
|
195
|
+
"inputUsdPerToken": 1e-06,
|
|
196
|
+
"outputUsdPerToken": 2.5e-06,
|
|
197
|
+
"model": "anthropic/claude-haiku-5.5",
|
|
198
|
+
"temperatureSupported": false,
|
|
199
|
+
"maxCompletionTokens": 128000,
|
|
200
|
+
"pricing": {
|
|
201
|
+
"completion": "0.0000005",
|
|
202
|
+
"discount": 0,
|
|
203
|
+
"input_cache_read": "0.00000001",
|
|
204
|
+
"input_cache_write": "0.000000125",
|
|
205
|
+
"input_cache_write_1h": "0.0000002",
|
|
206
|
+
"overrides": [
|
|
207
|
+
{
|
|
208
|
+
"completion": "0.0000025",
|
|
209
|
+
"input_cache_read": "0.00000005",
|
|
210
|
+
"input_cache_write": "0.000000625",
|
|
211
|
+
"input_cache_write_1h": "0.000001",
|
|
212
|
+
"min_prompt_tokens": 100000,
|
|
213
|
+
"prompt": "0.0000005"
|
|
214
|
+
}
|
|
215
|
+
],
|
|
216
|
+
"prompt": "0.0000001",
|
|
217
|
+
"web_search": "0.01"
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"model": "thinkingmachines/inkling-small",
|
|
223
|
+
"provider": "deepinfra/fp4",
|
|
224
|
+
"quantization": "fp4",
|
|
225
|
+
"catalogStatus": 0,
|
|
226
|
+
"source": "https://openrouter.ai/api/v1/models/thinkingmachines/inkling-small/endpoints",
|
|
227
|
+
"estimateUsd": 0.03061655,
|
|
228
|
+
"reservationUsd": 0.2407296,
|
|
229
|
+
"capUsd": 0.35,
|
|
230
|
+
"spending": {
|
|
231
|
+
"version": "reserved-context-v1",
|
|
232
|
+
"limitUsd": 0.35,
|
|
233
|
+
"providerTag": "deepinfra/fp4",
|
|
234
|
+
"contextTokens": 524288,
|
|
235
|
+
"inputUsdPerToken": 4.5e-07,
|
|
236
|
+
"outputUsdPerToken": 1.2e-06
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"model": "openai/gpt-oss-120b",
|
|
241
|
+
"provider": "primeintellect/fp4",
|
|
242
|
+
"quantization": "fp4",
|
|
243
|
+
"catalogStatus": 0,
|
|
244
|
+
"source": "https://openrouter.ai/api/v1/models/openai/gpt-oss-120b/endpoints",
|
|
245
|
+
"estimateUsd": 0.0021967023333333336,
|
|
246
|
+
"reservationUsd": 0.005165664,
|
|
247
|
+
"capUsd": 0.05,
|
|
248
|
+
"spending": {
|
|
249
|
+
"version": "reserved-context-v1",
|
|
250
|
+
"limitUsd": 0.05,
|
|
251
|
+
"providerTag": "primeintellect/fp4",
|
|
252
|
+
"contextTokens": 131072,
|
|
253
|
+
"inputUsdPerToken": 3.7e-08,
|
|
254
|
+
"outputUsdPerToken": 7.9e-08
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
],
|
|
258
|
+
"estimateUsd": 0.18931143908666667,
|
|
259
|
+
"capUsd": 3.45,
|
|
260
|
+
"output": "results/development-preflight-2026-11-14",
|
|
261
|
+
"execution": "Sequential; identical commands resume saved records. Stop each model at its cap; never automatically raise caps, delete attempts, or launch final evaluation."
|
|
262
|
+
}
|
package/docs/distribution.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Distribution prediction protocol v1
|
|
2
2
|
|
|
3
|
-
For the public Predict track, use `node src/cli.ts predict <model>`; see the [Quickstart](../README.md#quickstart). This uses the shared Learn runner’s no-example condition with
|
|
3
|
+
For the public Predict track, use `node src/cli.ts predict <model>`; see the [Quickstart](../README.md#quickstart). This uses the shared Learn runner’s no-example condition with an 8,000-token default in version 0.2.1 and support for `--max-usd`. `read-the-room <model>` runs Predict and Learn together. The legacy `distribution` command and its fixture format remain available unchanged.
|
|
4
4
|
|
|
5
5
|
This is a separate RTR-bench track. The original winning-quadrant benchmark retains its prompts, scoring, and result paths. [Learn the Room](learn-room.md) reuses this protocol's probability validation and scorer for its interactive environment and initial baseline comparisons.
|
|
6
6
|
|