@remnic/bench 9.6.20 → 9.6.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +31 -0
- package/dist/index.js +591 -465
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5497,17 +5497,473 @@ var BENCHMARK_RESULT_SCHEMA = {
|
|
|
5497
5497
|
|
|
5498
5498
|
// src/repro-manifest.ts
|
|
5499
5499
|
import { execFileSync } from "child_process";
|
|
5500
|
-
import { createHash as
|
|
5500
|
+
import { createHash as createHash4 } from "crypto";
|
|
5501
5501
|
import { createReadStream } from "fs";
|
|
5502
|
-
import { lstat as lstat3, mkdir as
|
|
5503
|
-
import
|
|
5504
|
-
import
|
|
5502
|
+
import { lstat as lstat3, mkdir as mkdir4, readFile as readFile5, readdir as readdir4, readlink, realpath as realpath3, stat as stat2, writeFile as writeFile4 } from "fs/promises";
|
|
5503
|
+
import os3 from "os";
|
|
5504
|
+
import path5 from "path";
|
|
5505
5505
|
|
|
5506
|
-
// src/
|
|
5507
|
-
import {
|
|
5508
|
-
import
|
|
5506
|
+
// src/providers/codex-credit-budget.ts
|
|
5507
|
+
import { createHash as createHash3 } from "crypto";
|
|
5508
|
+
import { mkdir as mkdir2, open, readFile as readFile3, rename as rename2, rmdir, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
|
|
5509
5509
|
import os from "os";
|
|
5510
5510
|
import path3 from "path";
|
|
5511
|
+
var ONE_MILLION = 1e6;
|
|
5512
|
+
var MAX_BOUNDED_CALL_CREDITS = 300;
|
|
5513
|
+
var SOL_MODEL = /^gpt-5\.6-sol$/i;
|
|
5514
|
+
var CREDIT_RATES = [
|
|
5515
|
+
[/^gpt-5\.6-sol$/i, { input: 125, cachedInput: 12.5, output: 750 }],
|
|
5516
|
+
[/^gpt-5\.6-terra$/i, { input: 62.5, cachedInput: 6.25, output: 375 }],
|
|
5517
|
+
[/^gpt-5\.6-luna$/i, { input: 25, cachedInput: 2.5, output: 150 }],
|
|
5518
|
+
[/^gpt-5\.5$/i, { input: 125, cachedInput: 12.5, output: 750 }],
|
|
5519
|
+
[/^gpt-5\.4-mini$/i, { input: 18.75, cachedInput: 1.875, output: 113 }],
|
|
5520
|
+
[/^gpt-5\.4$/i, { input: 62.5, cachedInput: 6.25, output: 375 }],
|
|
5521
|
+
[/^gpt-5\.3-codex$/i, { input: 43.75, cachedInput: 4.375, output: 350 }],
|
|
5522
|
+
[/^gpt-5\.2$/i, { input: 43.75, cachedInput: 4.375, output: 350 }]
|
|
5523
|
+
];
|
|
5524
|
+
var completionQueue = Promise.resolve();
|
|
5525
|
+
var CodexCreditAccountingError = class extends Error {
|
|
5526
|
+
constructor(message) {
|
|
5527
|
+
super(message);
|
|
5528
|
+
this.name = "CodexCreditAccountingError";
|
|
5529
|
+
}
|
|
5530
|
+
};
|
|
5531
|
+
var CodexCreditDispatchError = class extends Error {
|
|
5532
|
+
constructor(message, options) {
|
|
5533
|
+
super(message, options);
|
|
5534
|
+
this.name = "CodexCreditDispatchError";
|
|
5535
|
+
}
|
|
5536
|
+
};
|
|
5537
|
+
function resolveCodexCreditBudgetConfig(env = process.env, fallbackRunId) {
|
|
5538
|
+
const rawBudget = env.REMNIC_BENCH_CODEX_CREDIT_BUDGET?.trim();
|
|
5539
|
+
if (!rawBudget) return void 0;
|
|
5540
|
+
const budgetCredits = parsePositiveNumber(
|
|
5541
|
+
rawBudget,
|
|
5542
|
+
"REMNIC_BENCH_CODEX_CREDIT_BUDGET"
|
|
5543
|
+
);
|
|
5544
|
+
const reserveCredits = parseNonNegativeNumber(
|
|
5545
|
+
env.REMNIC_BENCH_CODEX_CREDIT_RESERVE?.trim() ?? "473",
|
|
5546
|
+
"REMNIC_BENCH_CODEX_CREDIT_RESERVE"
|
|
5547
|
+
);
|
|
5548
|
+
if (reserveCredits >= budgetCredits) {
|
|
5549
|
+
throw new Error(
|
|
5550
|
+
"REMNIC_BENCH_CODEX_CREDIT_RESERVE must be smaller than REMNIC_BENCH_CODEX_CREDIT_BUDGET"
|
|
5551
|
+
);
|
|
5552
|
+
}
|
|
5553
|
+
if (reserveCredits < MAX_BOUNDED_CALL_CREDITS) {
|
|
5554
|
+
throw new Error(
|
|
5555
|
+
`REMNIC_BENCH_CODEX_CREDIT_RESERVE must be at least ${MAX_BOUNDED_CALL_CREDITS} credits to cover the conservative maximum cost of the one serialized in-flight call`
|
|
5556
|
+
);
|
|
5557
|
+
}
|
|
5558
|
+
const ledgerPath = path3.resolve(
|
|
5559
|
+
expandHomeRelativePath(
|
|
5560
|
+
env.REMNIC_BENCH_CODEX_CREDIT_LEDGER?.trim() || ".remnic/bench/codex-credit-ledger.json"
|
|
5561
|
+
)
|
|
5562
|
+
);
|
|
5563
|
+
const runId = parseOptionalRunId(env.REMNIC_BENCH_RUN_ID) ?? parseOptionalRunId(fallbackRunId);
|
|
5564
|
+
return {
|
|
5565
|
+
budgetCredits,
|
|
5566
|
+
reserveCredits,
|
|
5567
|
+
ledgerPath,
|
|
5568
|
+
allowSol: /^(?:1|true|yes|on)$/i.test(
|
|
5569
|
+
env.REMNIC_BENCH_CODEX_ALLOW_SOL?.trim() ?? ""
|
|
5570
|
+
),
|
|
5571
|
+
...runId ? { runId } : {}
|
|
5572
|
+
};
|
|
5573
|
+
}
|
|
5574
|
+
async function runWithinCodexCreditBudget(args) {
|
|
5575
|
+
if (!args.config) {
|
|
5576
|
+
return (await args.run()).value;
|
|
5577
|
+
}
|
|
5578
|
+
const previous = completionQueue;
|
|
5579
|
+
let release;
|
|
5580
|
+
completionQueue = new Promise((resolve) => {
|
|
5581
|
+
release = resolve;
|
|
5582
|
+
});
|
|
5583
|
+
await previous;
|
|
5584
|
+
const lockPath = `${args.config.ledgerPath}.lock`;
|
|
5585
|
+
let lock;
|
|
5586
|
+
let dispatchStarted = false;
|
|
5587
|
+
let accountingSettled = false;
|
|
5588
|
+
try {
|
|
5589
|
+
await mkdir2(path3.dirname(lockPath), { recursive: true, mode: 448 });
|
|
5590
|
+
lock = await acquireLedgerLock(lockPath);
|
|
5591
|
+
assertModelAllowed(args.model, args.config);
|
|
5592
|
+
const ledger = await readLedger(args.config);
|
|
5593
|
+
if (ledger.blockedReason) {
|
|
5594
|
+
throw new Error(
|
|
5595
|
+
`Codex credit ledger is blocked pending manual reconciliation: ${ledger.blockedReason}`
|
|
5596
|
+
);
|
|
5597
|
+
}
|
|
5598
|
+
const usableCredits = args.config.budgetCredits - args.config.reserveCredits;
|
|
5599
|
+
const dispatchHeadroom = usableCredits - ledger.spentCredits;
|
|
5600
|
+
if (dispatchHeadroom < MAX_BOUNDED_CALL_CREDITS) {
|
|
5601
|
+
throw new Error(
|
|
5602
|
+
`Codex credit budget cannot safely dispatch another call: ${ledger.spentCredits.toFixed(3)} spent; ${dispatchHeadroom.toFixed(3)} remains below the ${usableCredits.toFixed(3)} planned-spend ceiling, but ${MAX_BOUNDED_CALL_CREDITS.toFixed(3)} credits of worst-case call headroom are required.`
|
|
5603
|
+
);
|
|
5604
|
+
}
|
|
5605
|
+
await writeLockState(lock, "in-flight");
|
|
5606
|
+
dispatchStarted = true;
|
|
5607
|
+
let result;
|
|
5608
|
+
try {
|
|
5609
|
+
result = await args.run();
|
|
5610
|
+
} catch (error) {
|
|
5611
|
+
if (error instanceof CodexCreditDispatchError) {
|
|
5612
|
+
await writeLockState(lock, "settled");
|
|
5613
|
+
accountingSettled = true;
|
|
5614
|
+
} else {
|
|
5615
|
+
const blockedLedger = {
|
|
5616
|
+
...ledger,
|
|
5617
|
+
blockedReason: error instanceof CodexCreditAccountingError ? error.message : `Codex dispatch outcome is unknown after an unexpected error: ${safeErrorMessage(error)}`
|
|
5618
|
+
};
|
|
5619
|
+
await writeLedger(args.config.ledgerPath, blockedLedger);
|
|
5620
|
+
await writeLockState(lock, "settled");
|
|
5621
|
+
accountingSettled = true;
|
|
5622
|
+
}
|
|
5623
|
+
throw error;
|
|
5624
|
+
}
|
|
5625
|
+
const credits = calculateCodexCredits(args.model, result.usage);
|
|
5626
|
+
const nextSpent = ledger.spentCredits + credits;
|
|
5627
|
+
const nextLedger = {
|
|
5628
|
+
...ledger,
|
|
5629
|
+
spentCredits: nextSpent,
|
|
5630
|
+
entries: [
|
|
5631
|
+
...ledger.entries,
|
|
5632
|
+
{
|
|
5633
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5634
|
+
model: args.model,
|
|
5635
|
+
credits,
|
|
5636
|
+
...args.config.runId ? { runId: args.config.runId } : {},
|
|
5637
|
+
...result.usage
|
|
5638
|
+
}
|
|
5639
|
+
]
|
|
5640
|
+
};
|
|
5641
|
+
await writeLedger(args.config.ledgerPath, nextLedger);
|
|
5642
|
+
await writeLockState(lock, "settled");
|
|
5643
|
+
accountingSettled = true;
|
|
5644
|
+
args.onUsagePersisted?.(result.usage);
|
|
5645
|
+
if (nextSpent > usableCredits) {
|
|
5646
|
+
throw new Error(
|
|
5647
|
+
`Codex planned-spend ceiling exceeded by completed call: ${nextSpent.toFixed(3)} > ${usableCredits.toFixed(3)} credits. Usage was persisted; stop the benchmark immediately.`
|
|
5648
|
+
);
|
|
5649
|
+
}
|
|
5650
|
+
return result.value;
|
|
5651
|
+
} finally {
|
|
5652
|
+
try {
|
|
5653
|
+
if (lock) {
|
|
5654
|
+
try {
|
|
5655
|
+
await lock.close();
|
|
5656
|
+
} finally {
|
|
5657
|
+
if (!dispatchStarted || accountingSettled) {
|
|
5658
|
+
await removeOwnedLedgerLock(lockPath);
|
|
5659
|
+
}
|
|
5660
|
+
}
|
|
5661
|
+
}
|
|
5662
|
+
} finally {
|
|
5663
|
+
release();
|
|
5664
|
+
}
|
|
5665
|
+
}
|
|
5666
|
+
}
|
|
5667
|
+
async function acquireLedgerLock(lockPath) {
|
|
5668
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
5669
|
+
try {
|
|
5670
|
+
await mkdir2(lockPath, { mode: 448 });
|
|
5671
|
+
} catch (error) {
|
|
5672
|
+
if (error.code !== "EEXIST") throw error;
|
|
5673
|
+
const owner = await readLockOwner(lockPath);
|
|
5674
|
+
if (!owner || isProcessAlive(owner.pid) || owner.phase === "in-flight") {
|
|
5675
|
+
throw new Error(
|
|
5676
|
+
`Codex credit ledger is locked${owner?.phase === "in-flight" ? " with unreconciled in-flight usage" : " by another benchmark process"} (${lockPath}); refusing credit spend.`
|
|
5677
|
+
);
|
|
5678
|
+
}
|
|
5679
|
+
await reclaimStaleLedgerLock(lockPath, owner);
|
|
5680
|
+
continue;
|
|
5681
|
+
}
|
|
5682
|
+
let createdLock;
|
|
5683
|
+
try {
|
|
5684
|
+
await mkdir2(lockHeldPath(lockPath));
|
|
5685
|
+
createdLock = await open(lockOwnerPath(lockPath), "wx", 384);
|
|
5686
|
+
await writeLockState(createdLock, "preflight");
|
|
5687
|
+
return createdLock;
|
|
5688
|
+
} catch (error) {
|
|
5689
|
+
await createdLock?.close().catch(() => void 0);
|
|
5690
|
+
await unlink2(lockOwnerPath(lockPath)).catch(() => void 0);
|
|
5691
|
+
await rmdir(lockHeldPath(lockPath)).catch(() => void 0);
|
|
5692
|
+
await rmdir(lockPath).catch(() => void 0);
|
|
5693
|
+
throw error;
|
|
5694
|
+
}
|
|
5695
|
+
}
|
|
5696
|
+
throw new Error(`Unable to acquire Codex credit ledger lock (${lockPath})`);
|
|
5697
|
+
}
|
|
5698
|
+
async function readLockOwner(lockPath) {
|
|
5699
|
+
try {
|
|
5700
|
+
const parsed = JSON.parse(await readFile3(lockOwnerPath(lockPath), "utf8"));
|
|
5701
|
+
if (!Number.isSafeInteger(parsed.pid) || parsed.pid <= 0 || parsed.phase !== "preflight" && parsed.phase !== "in-flight" && parsed.phase !== "settled") {
|
|
5702
|
+
return void 0;
|
|
5703
|
+
}
|
|
5704
|
+
return { pid: parsed.pid, phase: parsed.phase };
|
|
5705
|
+
} catch {
|
|
5706
|
+
return void 0;
|
|
5707
|
+
}
|
|
5708
|
+
}
|
|
5709
|
+
async function reclaimStaleLedgerLock(lockPath, expectedOwner) {
|
|
5710
|
+
try {
|
|
5711
|
+
await rmdir(lockHeldPath(lockPath));
|
|
5712
|
+
} catch (error) {
|
|
5713
|
+
throw new Error(
|
|
5714
|
+
`Codex credit ledger stale-lock reclamation is already claimed or incomplete (${lockPath}); refusing credit spend: ${safeErrorMessage(error)}`
|
|
5715
|
+
);
|
|
5716
|
+
}
|
|
5717
|
+
const currentOwner = await readLockOwner(lockPath);
|
|
5718
|
+
if (!currentOwner || currentOwner.pid !== expectedOwner.pid || currentOwner.phase !== expectedOwner.phase || isProcessAlive(currentOwner.pid) || currentOwner.phase === "in-flight") {
|
|
5719
|
+
throw new Error(
|
|
5720
|
+
`Codex credit ledger owner changed during stale-lock reclamation (${lockPath}); refusing credit spend.`
|
|
5721
|
+
);
|
|
5722
|
+
}
|
|
5723
|
+
await unlink2(lockOwnerPath(lockPath));
|
|
5724
|
+
await rmdir(lockPath);
|
|
5725
|
+
}
|
|
5726
|
+
async function removeOwnedLedgerLock(lockPath) {
|
|
5727
|
+
await rmdir(lockHeldPath(lockPath));
|
|
5728
|
+
await unlink2(lockOwnerPath(lockPath));
|
|
5729
|
+
await rmdir(lockPath);
|
|
5730
|
+
}
|
|
5731
|
+
function lockOwnerPath(lockPath) {
|
|
5732
|
+
return path3.join(lockPath, "owner.json");
|
|
5733
|
+
}
|
|
5734
|
+
function lockHeldPath(lockPath) {
|
|
5735
|
+
return path3.join(lockPath, "held");
|
|
5736
|
+
}
|
|
5737
|
+
async function writeLockState(lock, phase) {
|
|
5738
|
+
const contents = `${JSON.stringify({
|
|
5739
|
+
pid: process.pid,
|
|
5740
|
+
phase,
|
|
5741
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5742
|
+
})}
|
|
5743
|
+
`;
|
|
5744
|
+
await lock.truncate(0);
|
|
5745
|
+
await lock.write(contents, 0, "utf8");
|
|
5746
|
+
await lock.sync();
|
|
5747
|
+
}
|
|
5748
|
+
function isProcessAlive(pid) {
|
|
5749
|
+
try {
|
|
5750
|
+
process.kill(pid, 0);
|
|
5751
|
+
return true;
|
|
5752
|
+
} catch (error) {
|
|
5753
|
+
return error.code === "EPERM";
|
|
5754
|
+
}
|
|
5755
|
+
}
|
|
5756
|
+
function parseCodexJsonlUsage(output) {
|
|
5757
|
+
let usage;
|
|
5758
|
+
for (const line of output.split(/\r?\n/)) {
|
|
5759
|
+
const trimmed = line.trim();
|
|
5760
|
+
if (!trimmed.startsWith("{")) continue;
|
|
5761
|
+
try {
|
|
5762
|
+
const event = JSON.parse(trimmed);
|
|
5763
|
+
if (event.type !== "turn.completed" || !event.usage) continue;
|
|
5764
|
+
const inputTokens = readCounter(event.usage.input_tokens);
|
|
5765
|
+
const outputTokens = readCounter(event.usage.output_tokens);
|
|
5766
|
+
const cachedInputTokens = readOptionalCounter(
|
|
5767
|
+
event.usage.cached_input_tokens
|
|
5768
|
+
);
|
|
5769
|
+
const reasoningOutputTokens = readOptionalCounter(
|
|
5770
|
+
event.usage.reasoning_output_tokens
|
|
5771
|
+
);
|
|
5772
|
+
if (inputTokens !== void 0 && outputTokens !== void 0 && cachedInputTokens !== void 0 && reasoningOutputTokens !== void 0) {
|
|
5773
|
+
usage = {
|
|
5774
|
+
inputTokens,
|
|
5775
|
+
cachedInputTokens,
|
|
5776
|
+
outputTokens,
|
|
5777
|
+
reasoningOutputTokens
|
|
5778
|
+
};
|
|
5779
|
+
}
|
|
5780
|
+
} catch {
|
|
5781
|
+
}
|
|
5782
|
+
}
|
|
5783
|
+
return usage;
|
|
5784
|
+
}
|
|
5785
|
+
function calculateCodexCredits(model, usage) {
|
|
5786
|
+
const rate = resolveRate(model);
|
|
5787
|
+
const cached = Math.min(usage.inputTokens, usage.cachedInputTokens);
|
|
5788
|
+
const uncached = usage.inputTokens - cached;
|
|
5789
|
+
return (uncached * rate.input + cached * rate.cachedInput + usage.outputTokens * rate.output) / ONE_MILLION;
|
|
5790
|
+
}
|
|
5791
|
+
async function buildCodexCreditReceipt(ledgerPath, runId) {
|
|
5792
|
+
const resolvedPath = path3.resolve(expandHomeRelativePath(ledgerPath));
|
|
5793
|
+
const contents = await readFile3(resolvedPath);
|
|
5794
|
+
const ledger = parseLedger(JSON.parse(contents.toString("utf8")));
|
|
5795
|
+
const normalizedRunId = parseOptionalRunId(runId);
|
|
5796
|
+
const cumulative = summarizeLedgerEntries(ledger.entries);
|
|
5797
|
+
const runEntries = normalizedRunId ? ledger.entries.filter((entry) => entry.runId === normalizedRunId) : [];
|
|
5798
|
+
return {
|
|
5799
|
+
schemaVersion: 1,
|
|
5800
|
+
ledgerSha256: createHash3("sha256").update(contents).digest("hex"),
|
|
5801
|
+
budgetCredits: ledger.budgetCredits,
|
|
5802
|
+
reserveCredits: ledger.reserveCredits,
|
|
5803
|
+
plannedSpendCeilingCredits: ledger.budgetCredits - ledger.reserveCredits,
|
|
5804
|
+
totalSpentCredits: ledger.spentCredits,
|
|
5805
|
+
totalRemainingCredits: ledger.budgetCredits - ledger.spentCredits,
|
|
5806
|
+
blocked: ledger.blockedReason !== void 0,
|
|
5807
|
+
cumulative,
|
|
5808
|
+
...normalizedRunId ? { run: { id: normalizedRunId, ...summarizeLedgerEntries(runEntries) } } : {}
|
|
5809
|
+
};
|
|
5810
|
+
}
|
|
5811
|
+
function resolveRate(model) {
|
|
5812
|
+
const match = CREDIT_RATES.find(([pattern]) => pattern.test(model));
|
|
5813
|
+
if (!match) {
|
|
5814
|
+
throw new Error(
|
|
5815
|
+
`No Codex credit rate is configured for model ${JSON.stringify(model)}; refusing to run under a bounded credit budget.`
|
|
5816
|
+
);
|
|
5817
|
+
}
|
|
5818
|
+
return match[1];
|
|
5819
|
+
}
|
|
5820
|
+
function assertModelAllowed(model, config) {
|
|
5821
|
+
resolveRate(model);
|
|
5822
|
+
if (SOL_MODEL.test(model) && !config.allowSol) {
|
|
5823
|
+
throw new Error(
|
|
5824
|
+
"gpt-5.6-sol is disabled for bounded benchmark runs because it is the most expensive GPT-5.6 tier. Use gpt-5.6-terra or gpt-5.6-luna, or explicitly set REMNIC_BENCH_CODEX_ALLOW_SOL=1."
|
|
5825
|
+
);
|
|
5826
|
+
}
|
|
5827
|
+
}
|
|
5828
|
+
async function readLedger(config) {
|
|
5829
|
+
try {
|
|
5830
|
+
const parsed = parseLedger(
|
|
5831
|
+
JSON.parse(await readFile3(config.ledgerPath, "utf8"))
|
|
5832
|
+
);
|
|
5833
|
+
if (parsed.budgetCredits !== config.budgetCredits || parsed.reserveCredits !== config.reserveCredits) {
|
|
5834
|
+
throw new Error("ledger schema or budget does not match this run");
|
|
5835
|
+
}
|
|
5836
|
+
return parsed;
|
|
5837
|
+
} catch (error) {
|
|
5838
|
+
if (error.code !== "ENOENT") {
|
|
5839
|
+
throw new Error(`Invalid Codex credit ledger at ${config.ledgerPath}: ${String(error)}`);
|
|
5840
|
+
}
|
|
5841
|
+
return {
|
|
5842
|
+
schemaVersion: 1,
|
|
5843
|
+
budgetCredits: config.budgetCredits,
|
|
5844
|
+
reserveCredits: config.reserveCredits,
|
|
5845
|
+
spentCredits: 0,
|
|
5846
|
+
entries: []
|
|
5847
|
+
};
|
|
5848
|
+
}
|
|
5849
|
+
}
|
|
5850
|
+
function parseLedger(parsed) {
|
|
5851
|
+
const entryCredits = Array.isArray(parsed.entries) ? parsed.entries.reduce(
|
|
5852
|
+
(sum, entry) => sum + (typeof entry?.credits === "number" ? entry.credits ?? 0 : 0),
|
|
5853
|
+
0
|
|
5854
|
+
) : Number.NaN;
|
|
5855
|
+
if (parsed.schemaVersion !== 1 || typeof parsed.budgetCredits !== "number" || !Number.isFinite(parsed.budgetCredits) || parsed.budgetCredits <= 0 || typeof parsed.reserveCredits !== "number" || !Number.isFinite(parsed.reserveCredits) || parsed.reserveCredits < 0 || parsed.reserveCredits >= parsed.budgetCredits || typeof parsed.spentCredits !== "number" || !Number.isFinite(parsed.spentCredits) || parsed.spentCredits < 0 || !Array.isArray(parsed.entries) || !parsed.entries.every(isLedgerEntry) || Math.abs(entryCredits - parsed.spentCredits) > 1e-9 || parsed.blockedReason !== void 0 && typeof parsed.blockedReason !== "string") {
|
|
5856
|
+
throw new Error("ledger schema is invalid");
|
|
5857
|
+
}
|
|
5858
|
+
return parsed;
|
|
5859
|
+
}
|
|
5860
|
+
function isLedgerEntry(entry) {
|
|
5861
|
+
if (!entry || typeof entry !== "object") return false;
|
|
5862
|
+
const candidate = entry;
|
|
5863
|
+
return typeof candidate.at === "string" && typeof candidate.model === "string" && candidate.model.length > 0 && typeof candidate.credits === "number" && Number.isFinite(candidate.credits) && candidate.credits >= 0 && (candidate.runId === void 0 || isValidStoredRunId(candidate.runId)) && readCounter(candidate.inputTokens) !== void 0 && readCounter(candidate.cachedInputTokens) !== void 0 && readCounter(candidate.outputTokens) !== void 0 && readCounter(candidate.reasoningOutputTokens) !== void 0 && (candidate.cachedInputTokens ?? 0) <= (candidate.inputTokens ?? 0) && isEntryCreditConsistent(candidate);
|
|
5864
|
+
}
|
|
5865
|
+
function isEntryCreditConsistent(entry) {
|
|
5866
|
+
try {
|
|
5867
|
+
return Math.abs(calculateCodexCredits(entry.model, entry) - entry.credits) <= 1e-9;
|
|
5868
|
+
} catch {
|
|
5869
|
+
return false;
|
|
5870
|
+
}
|
|
5871
|
+
}
|
|
5872
|
+
function summarizeLedgerEntries(entries) {
|
|
5873
|
+
const byModel = /* @__PURE__ */ new Map();
|
|
5874
|
+
for (const entry of entries) {
|
|
5875
|
+
const modelEntries = byModel.get(entry.model) ?? [];
|
|
5876
|
+
modelEntries.push(entry);
|
|
5877
|
+
byModel.set(entry.model, modelEntries);
|
|
5878
|
+
}
|
|
5879
|
+
const totals = summarizeUsage(entries);
|
|
5880
|
+
return {
|
|
5881
|
+
calls: entries.length,
|
|
5882
|
+
credits: entries.reduce((sum, entry) => sum + entry.credits, 0),
|
|
5883
|
+
...totals,
|
|
5884
|
+
models: [...byModel.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([model, modelEntries]) => ({
|
|
5885
|
+
model,
|
|
5886
|
+
calls: modelEntries.length,
|
|
5887
|
+
credits: modelEntries.reduce((sum, entry) => sum + entry.credits, 0),
|
|
5888
|
+
...summarizeUsage(modelEntries)
|
|
5889
|
+
}))
|
|
5890
|
+
};
|
|
5891
|
+
}
|
|
5892
|
+
function summarizeUsage(entries) {
|
|
5893
|
+
return entries.reduce(
|
|
5894
|
+
(totals, entry) => ({
|
|
5895
|
+
inputTokens: totals.inputTokens + entry.inputTokens,
|
|
5896
|
+
cachedInputTokens: totals.cachedInputTokens + entry.cachedInputTokens,
|
|
5897
|
+
outputTokens: totals.outputTokens + entry.outputTokens,
|
|
5898
|
+
reasoningOutputTokens: totals.reasoningOutputTokens + entry.reasoningOutputTokens
|
|
5899
|
+
}),
|
|
5900
|
+
{ inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, reasoningOutputTokens: 0 }
|
|
5901
|
+
);
|
|
5902
|
+
}
|
|
5903
|
+
async function writeLedger(filePath, ledger) {
|
|
5904
|
+
await mkdir2(path3.dirname(filePath), { recursive: true, mode: 448 });
|
|
5905
|
+
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
5906
|
+
await writeFile2(tempPath, `${JSON.stringify(ledger, null, 2)}
|
|
5907
|
+
`, {
|
|
5908
|
+
encoding: "utf8",
|
|
5909
|
+
mode: 384
|
|
5910
|
+
});
|
|
5911
|
+
await rename2(tempPath, filePath);
|
|
5912
|
+
}
|
|
5913
|
+
function readCounter(value) {
|
|
5914
|
+
return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
5915
|
+
}
|
|
5916
|
+
function readOptionalCounter(value) {
|
|
5917
|
+
return value === void 0 ? 0 : readCounter(value);
|
|
5918
|
+
}
|
|
5919
|
+
function safeErrorMessage(error) {
|
|
5920
|
+
return error instanceof Error ? error.message : String(error);
|
|
5921
|
+
}
|
|
5922
|
+
function expandHomeRelativePath(value) {
|
|
5923
|
+
if (value === "~") return os.homedir();
|
|
5924
|
+
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
5925
|
+
return path3.join(os.homedir(), value.slice(2));
|
|
5926
|
+
}
|
|
5927
|
+
return value;
|
|
5928
|
+
}
|
|
5929
|
+
function parsePositiveNumber(value, name) {
|
|
5930
|
+
const parsed = Number(value);
|
|
5931
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
5932
|
+
throw new Error(`${name} must be a finite number greater than zero`);
|
|
5933
|
+
}
|
|
5934
|
+
return parsed;
|
|
5935
|
+
}
|
|
5936
|
+
function parseNonNegativeNumber(value, name) {
|
|
5937
|
+
const parsed = Number(value);
|
|
5938
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
5939
|
+
throw new Error(`${name} must be a finite non-negative number`);
|
|
5940
|
+
}
|
|
5941
|
+
return parsed;
|
|
5942
|
+
}
|
|
5943
|
+
function parseOptionalRunId(value) {
|
|
5944
|
+
const runId = value?.trim();
|
|
5945
|
+
if (!runId) return void 0;
|
|
5946
|
+
if (runId.length > 128 || hasControlCharacters(runId)) {
|
|
5947
|
+
throw new Error("REMNIC_BENCH_RUN_ID must be at most 128 characters without control characters");
|
|
5948
|
+
}
|
|
5949
|
+
return runId;
|
|
5950
|
+
}
|
|
5951
|
+
function isValidStoredRunId(value) {
|
|
5952
|
+
return typeof value === "string" && value.length > 0 && value.length <= 128 && value === value.trim() && !hasControlCharacters(value);
|
|
5953
|
+
}
|
|
5954
|
+
function hasControlCharacters(value) {
|
|
5955
|
+
for (const character of value) {
|
|
5956
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
5957
|
+
if (codePoint <= 31 || codePoint === 127) return true;
|
|
5958
|
+
}
|
|
5959
|
+
return false;
|
|
5960
|
+
}
|
|
5961
|
+
|
|
5962
|
+
// src/results-store.ts
|
|
5963
|
+
import { mkdir as mkdir3, readdir as readdir3, readFile as readFile4, unlink as unlink3, writeFile as writeFile3 } from "fs/promises";
|
|
5964
|
+
import fs from "fs";
|
|
5965
|
+
import os2 from "os";
|
|
5966
|
+
import path4 from "path";
|
|
5511
5967
|
|
|
5512
5968
|
// src/integrity/contamination.ts
|
|
5513
5969
|
var EMPTY_CONTAMINATION_MANIFEST = {
|
|
@@ -5972,14 +6428,14 @@ ${renderProvenance(result, provenance)}
|
|
|
5972
6428
|
var BASELINE_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
5973
6429
|
var REPRO_MANIFEST_FILENAME = "MANIFEST.json";
|
|
5974
6430
|
function defaultBenchmarkBaselineDir() {
|
|
5975
|
-
const homeDir = process.env.HOME ?? process.env.USERPROFILE ??
|
|
5976
|
-
return
|
|
6431
|
+
const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? os2.homedir();
|
|
6432
|
+
return path4.join(homeDir, ".remnic", "bench", "baselines");
|
|
5977
6433
|
}
|
|
5978
6434
|
function defaultBenchmarkPublishPath(target) {
|
|
5979
|
-
const homeDir = process.env.HOME ?? process.env.USERPROFILE ??
|
|
6435
|
+
const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? os2.homedir();
|
|
5980
6436
|
switch (target) {
|
|
5981
6437
|
case "remnic-ai":
|
|
5982
|
-
return
|
|
6438
|
+
return path4.join(homeDir, ".remnic", "published", "benchmarks.json");
|
|
5983
6439
|
}
|
|
5984
6440
|
}
|
|
5985
6441
|
function compareResultSummaries(left, right) {
|
|
@@ -6004,10 +6460,10 @@ function isFiniteNumber(value) {
|
|
|
6004
6460
|
return typeof value === "number" && Number.isFinite(value);
|
|
6005
6461
|
}
|
|
6006
6462
|
async function loadBenchmarkReportCardProvenance(outputDir, resultId) {
|
|
6007
|
-
const manifestPath =
|
|
6463
|
+
const manifestPath = path4.join(outputDir, REPRO_MANIFEST_FILENAME);
|
|
6008
6464
|
let parsed;
|
|
6009
6465
|
try {
|
|
6010
|
-
parsed = JSON.parse(await
|
|
6466
|
+
parsed = JSON.parse(await readFile4(manifestPath, "utf8"));
|
|
6011
6467
|
} catch {
|
|
6012
6468
|
return {};
|
|
6013
6469
|
}
|
|
@@ -6114,7 +6570,7 @@ function toBaselineSummary(baseline, filePath) {
|
|
|
6114
6570
|
};
|
|
6115
6571
|
}
|
|
6116
6572
|
async function loadBenchmarkResult(filePath) {
|
|
6117
|
-
const content = await
|
|
6573
|
+
const content = await readFile4(filePath, "utf8");
|
|
6118
6574
|
const parsed = JSON.parse(content);
|
|
6119
6575
|
if (!isBenchmarkResult(parsed)) {
|
|
6120
6576
|
throw new Error(`Invalid benchmark result file: ${filePath}`);
|
|
@@ -6131,7 +6587,7 @@ async function listBenchmarkResults(outputDir) {
|
|
|
6131
6587
|
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
6132
6588
|
continue;
|
|
6133
6589
|
}
|
|
6134
|
-
const filePath =
|
|
6590
|
+
const filePath = path4.join(outputDir, entry.name);
|
|
6135
6591
|
try {
|
|
6136
6592
|
const result = await loadBenchmarkResult(filePath);
|
|
6137
6593
|
results.push(toSummary(result, filePath));
|
|
@@ -6144,20 +6600,20 @@ async function listBenchmarkResults(outputDir) {
|
|
|
6144
6600
|
async function saveBenchmarkBaseline(baselineDir, name, result, source) {
|
|
6145
6601
|
assertValidBaselineName(name);
|
|
6146
6602
|
assertUsableBaselineDir(baselineDir);
|
|
6147
|
-
await
|
|
6148
|
-
const filePath =
|
|
6603
|
+
await mkdir3(baselineDir, { recursive: true });
|
|
6604
|
+
const filePath = path4.join(baselineDir, `${name}.json`);
|
|
6149
6605
|
const payload = {
|
|
6150
6606
|
name,
|
|
6151
6607
|
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6152
6608
|
result,
|
|
6153
6609
|
source
|
|
6154
6610
|
};
|
|
6155
|
-
await
|
|
6611
|
+
await writeFile3(filePath, `${JSON.stringify(payload, null, 2)}
|
|
6156
6612
|
`);
|
|
6157
6613
|
return filePath;
|
|
6158
6614
|
}
|
|
6159
6615
|
async function loadBenchmarkBaseline(filePath) {
|
|
6160
|
-
const content = await
|
|
6616
|
+
const content = await readFile4(filePath, "utf8");
|
|
6161
6617
|
const parsed = JSON.parse(content);
|
|
6162
6618
|
if (!isStoredBenchmarkBaseline(parsed)) {
|
|
6163
6619
|
throw new Error(`Invalid benchmark baseline file: ${filePath}`);
|
|
@@ -6175,7 +6631,7 @@ async function listBenchmarkBaselines(baselineDir) {
|
|
|
6175
6631
|
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
6176
6632
|
continue;
|
|
6177
6633
|
}
|
|
6178
|
-
const filePath =
|
|
6634
|
+
const filePath = path4.join(baselineDir, entry.name);
|
|
6179
6635
|
try {
|
|
6180
6636
|
const baseline = await loadBenchmarkBaseline(filePath);
|
|
6181
6637
|
baselines.push(toBaselineSummary(baseline, filePath));
|
|
@@ -6192,7 +6648,7 @@ async function resolveBenchmarkResultReference(outputDir, reference) {
|
|
|
6192
6648
|
return exactIdMatch;
|
|
6193
6649
|
}
|
|
6194
6650
|
const basenameMatch = summaries.find(
|
|
6195
|
-
(summary) =>
|
|
6651
|
+
(summary) => path4.basename(summary.path) === reference
|
|
6196
6652
|
);
|
|
6197
6653
|
if (basenameMatch) {
|
|
6198
6654
|
return basenameMatch;
|
|
@@ -6208,7 +6664,7 @@ async function resolveBenchmarkResultReference(outputDir, reference) {
|
|
|
6208
6664
|
return void 0;
|
|
6209
6665
|
}
|
|
6210
6666
|
function looksLikeFilesystemPath(reference) {
|
|
6211
|
-
return
|
|
6667
|
+
return path4.isAbsolute(reference) || reference.includes("/") || reference.includes(path4.sep) || reference.endsWith(".json");
|
|
6212
6668
|
}
|
|
6213
6669
|
async function deleteBenchmarkResults(outputDir, references) {
|
|
6214
6670
|
const summaries = await listBenchmarkResults(outputDir);
|
|
@@ -6216,9 +6672,9 @@ async function deleteBenchmarkResults(outputDir, references) {
|
|
|
6216
6672
|
const missing = [];
|
|
6217
6673
|
const seenPaths = /* @__PURE__ */ new Set();
|
|
6218
6674
|
for (const reference of references) {
|
|
6219
|
-
let summary = summaries.find((entry) => entry.id === reference) ?? summaries.find((entry) =>
|
|
6675
|
+
let summary = summaries.find((entry) => entry.id === reference) ?? summaries.find((entry) => path4.basename(entry.path) === reference);
|
|
6220
6676
|
if (!summary && looksLikeFilesystemPath(reference)) {
|
|
6221
|
-
const canonicalRef =
|
|
6677
|
+
const canonicalRef = path4.resolve(reference);
|
|
6222
6678
|
if (seenPaths.has(canonicalRef)) {
|
|
6223
6679
|
continue;
|
|
6224
6680
|
}
|
|
@@ -6235,13 +6691,13 @@ async function deleteBenchmarkResults(outputDir, references) {
|
|
|
6235
6691
|
missing.push(reference);
|
|
6236
6692
|
continue;
|
|
6237
6693
|
}
|
|
6238
|
-
const canonicalPath =
|
|
6694
|
+
const canonicalPath = path4.resolve(summary.path);
|
|
6239
6695
|
if (seenPaths.has(canonicalPath)) {
|
|
6240
6696
|
continue;
|
|
6241
6697
|
}
|
|
6242
6698
|
seenPaths.add(canonicalPath);
|
|
6243
6699
|
try {
|
|
6244
|
-
await
|
|
6700
|
+
await unlink3(summary.path);
|
|
6245
6701
|
} catch (error) {
|
|
6246
6702
|
if (error.code === "ENOENT") {
|
|
6247
6703
|
} else {
|
|
@@ -6366,8 +6822,8 @@ async function buildBenchmarkPublishFeed(outputDir, target, options = {}) {
|
|
|
6366
6822
|
};
|
|
6367
6823
|
}
|
|
6368
6824
|
async function writeBenchmarkPublishFeed(feed, outputPath) {
|
|
6369
|
-
await
|
|
6370
|
-
await
|
|
6825
|
+
await mkdir3(path4.dirname(outputPath), { recursive: true });
|
|
6826
|
+
await writeFile3(outputPath, `${JSON.stringify(feed, null, 2)}
|
|
6371
6827
|
`);
|
|
6372
6828
|
return outputPath;
|
|
6373
6829
|
}
|
|
@@ -6422,8 +6878,8 @@ function renderBenchmarkResultExport(result, format, options = {}) {
|
|
|
6422
6878
|
// src/run-identity.ts
|
|
6423
6879
|
var BENCHMARK_RUN_ID_ENV = "REMNIC_BENCH_RUN_ID";
|
|
6424
6880
|
var generatedBenchmarkRunId;
|
|
6425
|
-
function resolveBenchmarkRunId() {
|
|
6426
|
-
const explicit =
|
|
6881
|
+
function resolveBenchmarkRunId(env = process.env) {
|
|
6882
|
+
const explicit = env[BENCHMARK_RUN_ID_ENV]?.trim();
|
|
6427
6883
|
if (explicit) {
|
|
6428
6884
|
return explicit;
|
|
6429
6885
|
}
|
|
@@ -6627,14 +7083,22 @@ var BENCH_OPTION_BOUNDARY_FLAGS = /* @__PURE__ */ new Set([
|
|
|
6627
7083
|
]);
|
|
6628
7084
|
var SECRET_KEY_PATTERN = /(^|[-_])(?:api[-_]?key|secret[-_]?access[-_]?key|secret[-_]?key|client[-_]?secret(?:[-_]?key)?|app[-_]?secret(?:[-_]?key)?|provider[-_]?secret(?:[-_]?key)?|access[-_]?key|private[-_]?key|secret|password|authorization|credential|access[-_]?token|auth[-_]?token|refresh[-_]?token|id[-_]?token|token)$/i;
|
|
6629
7085
|
var REDACTED_ARG_VALUE = "[redacted]";
|
|
7086
|
+
var CODEX_CREDIT_REPRO_ENV_KEYS = [
|
|
7087
|
+
"REMNIC_BENCH_CODEX_ALLOW_SOL",
|
|
7088
|
+
"REMNIC_BENCH_CODEX_CREDIT_BUDGET",
|
|
7089
|
+
"REMNIC_BENCH_CODEX_CREDIT_LEDGER",
|
|
7090
|
+
"REMNIC_BENCH_CODEX_CREDIT_RESERVE",
|
|
7091
|
+
"REMNIC_BENCH_CODEX_CLI_DIAGNOSTICS_MODE",
|
|
7092
|
+
"REMNIC_BENCH_RUN_ID"
|
|
7093
|
+
];
|
|
6630
7094
|
function sha256String(value) {
|
|
6631
|
-
return
|
|
7095
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
6632
7096
|
}
|
|
6633
7097
|
function sha256Buffer(value) {
|
|
6634
|
-
return
|
|
7098
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
6635
7099
|
}
|
|
6636
7100
|
async function sha256File(filePath) {
|
|
6637
|
-
const hash =
|
|
7101
|
+
const hash = createHash4("sha256");
|
|
6638
7102
|
await new Promise((resolve, reject) => {
|
|
6639
7103
|
const stream = createReadStream(filePath);
|
|
6640
7104
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
@@ -7137,7 +7601,10 @@ function isAsciiAlnum2(char) {
|
|
|
7137
7601
|
return isUppercaseAscii(char) || isLowercaseAscii(char) || char >= "0" && char <= "9";
|
|
7138
7602
|
}
|
|
7139
7603
|
function sanitizeEnvKeys(env, explicitKeys) {
|
|
7140
|
-
const sourceKeys =
|
|
7604
|
+
const sourceKeys = [
|
|
7605
|
+
...explicitKeys ?? Object.keys(env ?? {}),
|
|
7606
|
+
...CODEX_CREDIT_REPRO_ENV_KEYS.filter((key) => env?.[key] !== void 0)
|
|
7607
|
+
];
|
|
7141
7608
|
return [...new Set(sourceKeys)].filter((key) => typeof key === "string" && key.length > 0).sort((left, right) => left.localeCompare(right));
|
|
7142
7609
|
}
|
|
7143
7610
|
function gitOutput(args, cwd) {
|
|
@@ -7191,7 +7658,8 @@ function buildArtifactHashIdentity(manifest) {
|
|
|
7191
7658
|
...manifest.qmd ? { qmd: manifest.qmd } : {},
|
|
7192
7659
|
configFiles: manifest.configFiles,
|
|
7193
7660
|
datasets: manifest.datasets,
|
|
7194
|
-
results: manifest.results
|
|
7661
|
+
results: manifest.results,
|
|
7662
|
+
...manifest.codexCredit ? { codexCredit: manifest.codexCredit } : {}
|
|
7195
7663
|
};
|
|
7196
7664
|
}
|
|
7197
7665
|
async function scanDatasetFiles(root) {
|
|
@@ -7200,18 +7668,18 @@ async function scanDatasetFiles(root) {
|
|
|
7200
7668
|
const entries = await readdir4(directory, { withFileTypes: true });
|
|
7201
7669
|
entries.sort((left, right) => left.name.localeCompare(right.name));
|
|
7202
7670
|
for (const entry of entries) {
|
|
7203
|
-
const entryPath =
|
|
7671
|
+
const entryPath = path5.join(directory, entry.name);
|
|
7204
7672
|
const entryStat = await lstat3(entryPath);
|
|
7205
|
-
const relativePath =
|
|
7673
|
+
const relativePath = path5.relative(root, entryPath).split(path5.sep).join("/");
|
|
7206
7674
|
if (entryStat.isSymbolicLink()) {
|
|
7207
7675
|
const target = await readlink(entryPath);
|
|
7208
|
-
const resolvedTarget =
|
|
7676
|
+
const resolvedTarget = path5.resolve(directory, target);
|
|
7209
7677
|
const realTarget = await realpath3(resolvedTarget);
|
|
7210
|
-
const targetRelativePath =
|
|
7211
|
-
if (targetRelativePath.length === 0 || targetRelativePath === ".." || targetRelativePath.startsWith(`..${
|
|
7678
|
+
const targetRelativePath = path5.relative(root, realTarget);
|
|
7679
|
+
if (targetRelativePath.length === 0 || targetRelativePath === ".." || targetRelativePath.startsWith(`..${path5.sep}`) || path5.isAbsolute(targetRelativePath)) {
|
|
7212
7680
|
throw new Error(`dataset symlink target must be inside ${root}: ${entryPath}`);
|
|
7213
7681
|
}
|
|
7214
|
-
const manifestTarget =
|
|
7682
|
+
const manifestTarget = path5.isAbsolute(target) ? targetRelativePath.split(path5.sep).join("/") : target;
|
|
7215
7683
|
files.push({
|
|
7216
7684
|
path: relativePath,
|
|
7217
7685
|
kind: "symlink",
|
|
@@ -7239,9 +7707,9 @@ async function scanDatasetFiles(root) {
|
|
|
7239
7707
|
return files.sort((left, right) => left.path.localeCompare(right.path));
|
|
7240
7708
|
}
|
|
7241
7709
|
async function lstatPathWithoutSymlinkComponents(targetPath) {
|
|
7242
|
-
const parsed =
|
|
7243
|
-
const relativePath =
|
|
7244
|
-
const parts = relativePath.length > 0 ? relativePath.split(
|
|
7710
|
+
const parsed = path5.parse(targetPath);
|
|
7711
|
+
const relativePath = path5.relative(parsed.root, targetPath);
|
|
7712
|
+
const parts = relativePath.length > 0 ? relativePath.split(path5.sep) : [];
|
|
7245
7713
|
let currentPath = parsed.root;
|
|
7246
7714
|
let currentStat;
|
|
7247
7715
|
try {
|
|
@@ -7249,7 +7717,7 @@ async function lstatPathWithoutSymlinkComponents(targetPath) {
|
|
|
7249
7717
|
currentStat = await lstat3(currentPath);
|
|
7250
7718
|
}
|
|
7251
7719
|
for (const part of parts) {
|
|
7252
|
-
currentPath =
|
|
7720
|
+
currentPath = path5.join(currentPath, part);
|
|
7253
7721
|
currentStat = await lstat3(currentPath);
|
|
7254
7722
|
if (currentStat.isSymbolicLink()) {
|
|
7255
7723
|
return void 0;
|
|
@@ -7270,7 +7738,7 @@ async function buildDatasetManifest(benchmark, datasetDir) {
|
|
|
7270
7738
|
files: []
|
|
7271
7739
|
};
|
|
7272
7740
|
}
|
|
7273
|
-
const datasetRoot =
|
|
7741
|
+
const datasetRoot = path5.resolve(datasetDir);
|
|
7274
7742
|
const datasetStat = await lstatPathWithoutSymlinkComponents(datasetRoot);
|
|
7275
7743
|
if (!datasetStat) {
|
|
7276
7744
|
return {
|
|
@@ -7312,7 +7780,7 @@ async function buildResultManifest(resultsDir, resultPath, result) {
|
|
|
7312
7780
|
await assertRegularFileWithoutSymlinkComponents(resultPath, "result path");
|
|
7313
7781
|
const fileStats = await stat2(resultPath);
|
|
7314
7782
|
return {
|
|
7315
|
-
path:
|
|
7783
|
+
path: path5.relative(resultsDir, resultPath).split(path5.sep).join("/"),
|
|
7316
7784
|
sha256: await sha256File(resultPath),
|
|
7317
7785
|
sizeBytes: fileStats.size,
|
|
7318
7786
|
resultId: result.meta.id,
|
|
@@ -7334,7 +7802,7 @@ async function resolveResultPaths(resultsDir, explicitPaths) {
|
|
|
7334
7802
|
if (explicitPaths !== void 0) {
|
|
7335
7803
|
const resolvedPaths = await Promise.all(
|
|
7336
7804
|
explicitPaths.map(async (entry) => {
|
|
7337
|
-
const resultPath =
|
|
7805
|
+
const resultPath = path5.resolve(entry);
|
|
7338
7806
|
assertPathInsideRoot(resultsDir, resultPath, "result path");
|
|
7339
7807
|
await assertRegularFileWithoutSymlinkComponents(resultPath, "result path");
|
|
7340
7808
|
return resultPath;
|
|
@@ -7343,20 +7811,20 @@ async function resolveResultPaths(resultsDir, explicitPaths) {
|
|
|
7343
7811
|
return [...new Set(resolvedPaths)].sort((left, right) => left.localeCompare(right));
|
|
7344
7812
|
}
|
|
7345
7813
|
const summaries = await listBenchmarkResults(resultsDir);
|
|
7346
|
-
return summaries.map((summary) =>
|
|
7814
|
+
return summaries.map((summary) => path5.resolve(summary.path));
|
|
7347
7815
|
}
|
|
7348
7816
|
function assertPathInsideRoot(root, targetPath, label) {
|
|
7349
|
-
const resolvedRoot =
|
|
7350
|
-
const resolvedTargetPath =
|
|
7351
|
-
const relativePath =
|
|
7352
|
-
if (relativePath.length === 0 || relativePath === ".." || relativePath.startsWith(`..${
|
|
7817
|
+
const resolvedRoot = path5.resolve(root);
|
|
7818
|
+
const resolvedTargetPath = path5.resolve(targetPath);
|
|
7819
|
+
const relativePath = path5.relative(resolvedRoot, resolvedTargetPath);
|
|
7820
|
+
if (relativePath.length === 0 || relativePath === ".." || relativePath.startsWith(`..${path5.sep}`) || path5.isAbsolute(relativePath)) {
|
|
7353
7821
|
throw new Error(`${label} must be inside ${resolvedRoot}: ${resolvedTargetPath}`);
|
|
7354
7822
|
}
|
|
7355
7823
|
}
|
|
7356
7824
|
async function assertRegularFileWithoutSymlinkComponents(targetPath, label) {
|
|
7357
|
-
const targetStat = await lstatPathWithoutSymlinkComponents(
|
|
7825
|
+
const targetStat = await lstatPathWithoutSymlinkComponents(path5.resolve(targetPath));
|
|
7358
7826
|
if (!targetStat?.isFile()) {
|
|
7359
|
-
throw new Error(`${label} must be a regular file without symlink components: ${
|
|
7827
|
+
throw new Error(`${label} must be a regular file without symlink components: ${path5.resolve(targetPath)}`);
|
|
7360
7828
|
}
|
|
7361
7829
|
}
|
|
7362
7830
|
function isKnownNonSecretOptionFlag(arg) {
|
|
@@ -7402,7 +7870,7 @@ async function buildConfigFileEntries(configFiles = []) {
|
|
|
7402
7870
|
entries.push({ label: configFile.label, path: configFile.path, missing: true });
|
|
7403
7871
|
continue;
|
|
7404
7872
|
}
|
|
7405
|
-
const content = await
|
|
7873
|
+
const content = await readFile5(configFile.path);
|
|
7406
7874
|
const sanitizedConfig = sanitizeConfigFileContent(content);
|
|
7407
7875
|
entries.push({
|
|
7408
7876
|
label: configFile.label,
|
|
@@ -7469,7 +7937,7 @@ function resolvePackageManager(cwd) {
|
|
|
7469
7937
|
}
|
|
7470
7938
|
}
|
|
7471
7939
|
async function buildBenchmarkReproManifest(resultsDir, options = {}) {
|
|
7472
|
-
const resolvedResultsDir =
|
|
7940
|
+
const resolvedResultsDir = path5.resolve(resultsDir);
|
|
7473
7941
|
const cwd = options.command?.cwd ?? process.cwd();
|
|
7474
7942
|
const resultPaths = await resolveResultPaths(resolvedResultsDir, options.resultPaths);
|
|
7475
7943
|
const loadedResults = await Promise.all(resultPaths.map((resultPath) => loadBenchmarkResult(resultPath)));
|
|
@@ -7487,11 +7955,23 @@ async function buildBenchmarkReproManifest(resultsDir, options = {}) {
|
|
|
7487
7955
|
);
|
|
7488
7956
|
const qmdCollections = collectQmdCollections(options.qmd?.collections, loadedResults);
|
|
7489
7957
|
const pnpmVersion = resolvePackageManager(cwd);
|
|
7958
|
+
const commandEnv = options.command?.env ?? process.env;
|
|
7959
|
+
const runId = options.runId ?? resolveBenchmarkRunId(commandEnv);
|
|
7960
|
+
const resolvedCreditConfig = resolveCodexCreditBudgetConfig(commandEnv, runId);
|
|
7961
|
+
const creditConfig = resolvedCreditConfig ? { ...resolvedCreditConfig, runId } : void 0;
|
|
7962
|
+
let codexCredit;
|
|
7963
|
+
if (creditConfig) {
|
|
7964
|
+
try {
|
|
7965
|
+
codexCredit = await buildCodexCreditReceipt(creditConfig.ledgerPath, creditConfig.runId);
|
|
7966
|
+
} catch (error) {
|
|
7967
|
+
if (error.code !== "ENOENT") throw error;
|
|
7968
|
+
}
|
|
7969
|
+
}
|
|
7490
7970
|
const manifestWithoutHash = {
|
|
7491
7971
|
schemaVersion: BENCHMARK_REPRO_MANIFEST_SCHEMA_VERSION,
|
|
7492
7972
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7493
7973
|
run: {
|
|
7494
|
-
id:
|
|
7974
|
+
id: runId,
|
|
7495
7975
|
...options.mode ? { mode: options.mode } : {},
|
|
7496
7976
|
selectedBenchmarks,
|
|
7497
7977
|
runtimeProfiles: options.runtimeProfiles ?? [],
|
|
@@ -7503,13 +7983,13 @@ async function buildBenchmarkReproManifest(resultsDir, options = {}) {
|
|
|
7503
7983
|
command: {
|
|
7504
7984
|
cwd,
|
|
7505
7985
|
argv: sanitizeArgv(options.command?.argv ?? process.argv.slice(2)),
|
|
7506
|
-
envKeys: sanitizeEnvKeys(
|
|
7986
|
+
envKeys: sanitizeEnvKeys(commandEnv, options.command?.envKeys)
|
|
7507
7987
|
},
|
|
7508
7988
|
environment: {
|
|
7509
7989
|
platform: process.platform,
|
|
7510
7990
|
arch: process.arch,
|
|
7511
7991
|
nodeVersion: process.version,
|
|
7512
|
-
hostname:
|
|
7992
|
+
hostname: os3.hostname(),
|
|
7513
7993
|
...pnpmVersion ? { packageManager: `pnpm@${pnpmVersion}` } : {}
|
|
7514
7994
|
},
|
|
7515
7995
|
...options.qmd || qmdCollections.length > 0 ? {
|
|
@@ -7521,7 +8001,8 @@ async function buildBenchmarkReproManifest(resultsDir, options = {}) {
|
|
|
7521
8001
|
} : {},
|
|
7522
8002
|
configFiles: await buildConfigFileEntries(options.configFiles),
|
|
7523
8003
|
datasets,
|
|
7524
|
-
results: resultEntries.sort((left, right) => left.path.localeCompare(right.path))
|
|
8004
|
+
results: resultEntries.sort((left, right) => left.path.localeCompare(right.path)),
|
|
8005
|
+
...codexCredit ? { codexCredit } : {}
|
|
7525
8006
|
};
|
|
7526
8007
|
return {
|
|
7527
8008
|
...manifestWithoutHash,
|
|
@@ -7529,18 +8010,18 @@ async function buildBenchmarkReproManifest(resultsDir, options = {}) {
|
|
|
7529
8010
|
};
|
|
7530
8011
|
}
|
|
7531
8012
|
async function writeBenchmarkReproManifest(resultsDir, options = {}) {
|
|
7532
|
-
await
|
|
8013
|
+
await mkdir4(resultsDir, { recursive: true });
|
|
7533
8014
|
const manifest = await buildBenchmarkReproManifest(resultsDir, options);
|
|
7534
|
-
const manifestPath =
|
|
7535
|
-
await
|
|
8015
|
+
const manifestPath = path5.join(resultsDir, BENCHMARK_REPRO_MANIFEST_FILENAME);
|
|
8016
|
+
await writeFile4(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
7536
8017
|
`);
|
|
7537
8018
|
return manifestPath;
|
|
7538
8019
|
}
|
|
7539
8020
|
|
|
7540
8021
|
// src/published-artifact.ts
|
|
7541
|
-
import { createHash as
|
|
7542
|
-
import { mkdir as
|
|
7543
|
-
import
|
|
8022
|
+
import { createHash as createHash5 } from "crypto";
|
|
8023
|
+
import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
8024
|
+
import path6 from "path";
|
|
7544
8025
|
var BENCHMARK_ARTIFACT_SCHEMA_VERSION = 1;
|
|
7545
8026
|
var PUBLISHED_BENCHMARK_ARTIFACT_IDS = Object.freeze([
|
|
7546
8027
|
"ama-bench",
|
|
@@ -7681,25 +8162,25 @@ function serializeBenchmarkArtifact(artifact) {
|
|
|
7681
8162
|
`;
|
|
7682
8163
|
}
|
|
7683
8164
|
function hashBenchmarkArtifact(artifact) {
|
|
7684
|
-
return
|
|
8165
|
+
return createHash5("sha256").update(serializeBenchmarkArtifact(artifact)).digest("hex");
|
|
7685
8166
|
}
|
|
7686
8167
|
async function writeBenchmarkArtifact(artifact, outputDir) {
|
|
7687
|
-
await
|
|
8168
|
+
await mkdir5(outputDir, { recursive: true });
|
|
7688
8169
|
const filename = buildBenchmarkArtifactFilename(artifact);
|
|
7689
8170
|
const body = serializeBenchmarkArtifact(artifact);
|
|
7690
|
-
const resolvedDir =
|
|
7691
|
-
const abs =
|
|
7692
|
-
const relative =
|
|
7693
|
-
if (relative.length === 0 || relative.startsWith("..") ||
|
|
8171
|
+
const resolvedDir = path6.resolve(outputDir);
|
|
8172
|
+
const abs = path6.resolve(resolvedDir, filename);
|
|
8173
|
+
const relative = path6.relative(resolvedDir, abs);
|
|
8174
|
+
if (relative.length === 0 || relative.startsWith("..") || path6.isAbsolute(relative) || relative.includes(path6.sep)) {
|
|
7694
8175
|
throw new Error(
|
|
7695
8176
|
`writeBenchmarkArtifact: refusing to write outside outputDir (filename="${filename}", resolved="${abs}").`
|
|
7696
8177
|
);
|
|
7697
8178
|
}
|
|
7698
|
-
await
|
|
8179
|
+
await writeFile5(abs, body);
|
|
7699
8180
|
return {
|
|
7700
8181
|
path: abs,
|
|
7701
8182
|
filename,
|
|
7702
|
-
sha256:
|
|
8183
|
+
sha256: createHash5("sha256").update(body).digest("hex"),
|
|
7703
8184
|
bytes: Buffer.byteLength(body, "utf8")
|
|
7704
8185
|
};
|
|
7705
8186
|
}
|
|
@@ -7804,11 +8285,11 @@ function parseBenchmarkArtifact(raw) {
|
|
|
7804
8285
|
return parsed;
|
|
7805
8286
|
}
|
|
7806
8287
|
async function loadBenchmarkArtifact(filePath) {
|
|
7807
|
-
const raw = await
|
|
8288
|
+
const raw = await readFile6(filePath, "utf8");
|
|
7808
8289
|
const artifact = parseBenchmarkArtifact(raw);
|
|
7809
8290
|
return {
|
|
7810
8291
|
artifact,
|
|
7811
|
-
sha256:
|
|
8292
|
+
sha256: createHash5("sha256").update(raw).digest("hex"),
|
|
7812
8293
|
bytes: Buffer.byteLength(raw, "utf8")
|
|
7813
8294
|
};
|
|
7814
8295
|
}
|
|
@@ -8211,8 +8692,8 @@ function createAnthropicProvider(config) {
|
|
|
8211
8692
|
// src/providers/claude-cli.ts
|
|
8212
8693
|
import { spawn } from "child_process";
|
|
8213
8694
|
import { mkdtemp as mkdtemp2, rm as rm2 } from "fs/promises";
|
|
8214
|
-
import
|
|
8215
|
-
import
|
|
8695
|
+
import os4 from "os";
|
|
8696
|
+
import path7 from "path";
|
|
8216
8697
|
var CLAUDE_CLI_STDIO_LIMIT = 64e3;
|
|
8217
8698
|
var CLAUDE_CLI_PARENT_SIGNALS = ["SIGHUP", "SIGINT", "SIGTERM"];
|
|
8218
8699
|
var CLAUDE_CLI_FORCED_PARENT_EXIT_MS = 1e3;
|
|
@@ -8365,7 +8846,7 @@ var ClaudeCliProvider = class {
|
|
|
8365
8846
|
let transientAttempt = 1;
|
|
8366
8847
|
let usageLimitAttempt = 1;
|
|
8367
8848
|
while (true) {
|
|
8368
|
-
const tempDir = await mkdtemp2(
|
|
8849
|
+
const tempDir = await mkdtemp2(path7.join(os4.tmpdir(), "remnic-claude-cli-"));
|
|
8369
8850
|
try {
|
|
8370
8851
|
const request = this.buildRunRequest(prompt, opts, tempDir);
|
|
8371
8852
|
const result = await this.runClaudeCli(request);
|
|
@@ -8577,14 +9058,14 @@ function resolveClaudeCliExecutable(config) {
|
|
|
8577
9058
|
if (trimmed.length === 0) {
|
|
8578
9059
|
throw new Error(`${CLAUDE_CLI_EXECUTABLE_ENV} / claude-cli executable must not be empty`);
|
|
8579
9060
|
}
|
|
8580
|
-
return
|
|
9061
|
+
return expandHomeRelativePath2(trimmed);
|
|
8581
9062
|
}
|
|
8582
|
-
function
|
|
9063
|
+
function expandHomeRelativePath2(value) {
|
|
8583
9064
|
if (value === "~") {
|
|
8584
|
-
return
|
|
9065
|
+
return os4.homedir();
|
|
8585
9066
|
}
|
|
8586
9067
|
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
8587
|
-
return
|
|
9068
|
+
return path7.join(os4.homedir(), value.slice(2));
|
|
8588
9069
|
}
|
|
8589
9070
|
return value;
|
|
8590
9071
|
}
|
|
@@ -8971,7 +9452,7 @@ function createClaudeCliProvider(config, deps) {
|
|
|
8971
9452
|
|
|
8972
9453
|
// src/providers/codex-cli.ts
|
|
8973
9454
|
import { spawn as spawn2 } from "child_process";
|
|
8974
|
-
import { createHash as
|
|
9455
|
+
import { createHash as createHash6, randomUUID } from "crypto";
|
|
8975
9456
|
import { mkdir as mkdir6, mkdtemp as mkdtemp3, readFile as readFile7, rm as rm3, writeFile as writeFile6 } from "fs/promises";
|
|
8976
9457
|
import os5 from "os";
|
|
8977
9458
|
import path8 from "path";
|
|
@@ -9165,364 +9646,6 @@ function throwJudgeFailure(provider, failure) {
|
|
|
9165
9646
|
throw provider.createJudgeError?.(failure) ?? new StructuredJudgeError(failure);
|
|
9166
9647
|
}
|
|
9167
9648
|
|
|
9168
|
-
// src/providers/codex-credit-budget.ts
|
|
9169
|
-
import { mkdir as mkdir5, open, readFile as readFile6, rename as rename2, rmdir, unlink as unlink3, writeFile as writeFile5 } from "fs/promises";
|
|
9170
|
-
import os4 from "os";
|
|
9171
|
-
import path7 from "path";
|
|
9172
|
-
var ONE_MILLION = 1e6;
|
|
9173
|
-
var MAX_BOUNDED_CALL_CREDITS = 300;
|
|
9174
|
-
var SOL_MODEL = /^gpt-5\.6-sol$/i;
|
|
9175
|
-
var CREDIT_RATES = [
|
|
9176
|
-
[/^gpt-5\.6-sol$/i, { input: 125, cachedInput: 12.5, output: 750 }],
|
|
9177
|
-
[/^gpt-5\.6-terra$/i, { input: 62.5, cachedInput: 6.25, output: 375 }],
|
|
9178
|
-
[/^gpt-5\.6-luna$/i, { input: 25, cachedInput: 2.5, output: 150 }],
|
|
9179
|
-
[/^gpt-5\.5$/i, { input: 125, cachedInput: 12.5, output: 750 }],
|
|
9180
|
-
[/^gpt-5\.4-mini$/i, { input: 18.75, cachedInput: 1.875, output: 113 }],
|
|
9181
|
-
[/^gpt-5\.4$/i, { input: 62.5, cachedInput: 6.25, output: 375 }],
|
|
9182
|
-
[/^gpt-5\.3-codex$/i, { input: 43.75, cachedInput: 4.375, output: 350 }],
|
|
9183
|
-
[/^gpt-5\.2$/i, { input: 43.75, cachedInput: 4.375, output: 350 }]
|
|
9184
|
-
];
|
|
9185
|
-
var completionQueue = Promise.resolve();
|
|
9186
|
-
var CodexCreditAccountingError = class extends Error {
|
|
9187
|
-
constructor(message) {
|
|
9188
|
-
super(message);
|
|
9189
|
-
this.name = "CodexCreditAccountingError";
|
|
9190
|
-
}
|
|
9191
|
-
};
|
|
9192
|
-
var CodexCreditDispatchError = class extends Error {
|
|
9193
|
-
constructor(message, options) {
|
|
9194
|
-
super(message, options);
|
|
9195
|
-
this.name = "CodexCreditDispatchError";
|
|
9196
|
-
}
|
|
9197
|
-
};
|
|
9198
|
-
function resolveCodexCreditBudgetConfig(env = process.env) {
|
|
9199
|
-
const rawBudget = env.REMNIC_BENCH_CODEX_CREDIT_BUDGET?.trim();
|
|
9200
|
-
if (!rawBudget) return void 0;
|
|
9201
|
-
const budgetCredits = parsePositiveNumber(
|
|
9202
|
-
rawBudget,
|
|
9203
|
-
"REMNIC_BENCH_CODEX_CREDIT_BUDGET"
|
|
9204
|
-
);
|
|
9205
|
-
const reserveCredits = parseNonNegativeNumber(
|
|
9206
|
-
env.REMNIC_BENCH_CODEX_CREDIT_RESERVE?.trim() ?? "473",
|
|
9207
|
-
"REMNIC_BENCH_CODEX_CREDIT_RESERVE"
|
|
9208
|
-
);
|
|
9209
|
-
if (reserveCredits >= budgetCredits) {
|
|
9210
|
-
throw new Error(
|
|
9211
|
-
"REMNIC_BENCH_CODEX_CREDIT_RESERVE must be smaller than REMNIC_BENCH_CODEX_CREDIT_BUDGET"
|
|
9212
|
-
);
|
|
9213
|
-
}
|
|
9214
|
-
if (reserveCredits < MAX_BOUNDED_CALL_CREDITS) {
|
|
9215
|
-
throw new Error(
|
|
9216
|
-
`REMNIC_BENCH_CODEX_CREDIT_RESERVE must be at least ${MAX_BOUNDED_CALL_CREDITS} credits to cover the conservative maximum cost of the one serialized in-flight call`
|
|
9217
|
-
);
|
|
9218
|
-
}
|
|
9219
|
-
const ledgerPath = path7.resolve(
|
|
9220
|
-
expandHomeRelativePath2(
|
|
9221
|
-
env.REMNIC_BENCH_CODEX_CREDIT_LEDGER?.trim() || ".remnic/bench/codex-credit-ledger.json"
|
|
9222
|
-
)
|
|
9223
|
-
);
|
|
9224
|
-
return {
|
|
9225
|
-
budgetCredits,
|
|
9226
|
-
reserveCredits,
|
|
9227
|
-
ledgerPath,
|
|
9228
|
-
allowSol: /^(?:1|true|yes|on)$/i.test(
|
|
9229
|
-
env.REMNIC_BENCH_CODEX_ALLOW_SOL?.trim() ?? ""
|
|
9230
|
-
)
|
|
9231
|
-
};
|
|
9232
|
-
}
|
|
9233
|
-
async function runWithinCodexCreditBudget(args) {
|
|
9234
|
-
if (!args.config) {
|
|
9235
|
-
return (await args.run()).value;
|
|
9236
|
-
}
|
|
9237
|
-
const previous = completionQueue;
|
|
9238
|
-
let release;
|
|
9239
|
-
completionQueue = new Promise((resolve) => {
|
|
9240
|
-
release = resolve;
|
|
9241
|
-
});
|
|
9242
|
-
await previous;
|
|
9243
|
-
const lockPath = `${args.config.ledgerPath}.lock`;
|
|
9244
|
-
let lock;
|
|
9245
|
-
let dispatchStarted = false;
|
|
9246
|
-
let accountingSettled = false;
|
|
9247
|
-
try {
|
|
9248
|
-
await mkdir5(path7.dirname(lockPath), { recursive: true, mode: 448 });
|
|
9249
|
-
lock = await acquireLedgerLock(lockPath);
|
|
9250
|
-
assertModelAllowed(args.model, args.config);
|
|
9251
|
-
const ledger = await readLedger(args.config);
|
|
9252
|
-
if (ledger.blockedReason) {
|
|
9253
|
-
throw new Error(
|
|
9254
|
-
`Codex credit ledger is blocked pending manual reconciliation: ${ledger.blockedReason}`
|
|
9255
|
-
);
|
|
9256
|
-
}
|
|
9257
|
-
const usableCredits = args.config.budgetCredits - args.config.reserveCredits;
|
|
9258
|
-
if (ledger.spentCredits >= usableCredits) {
|
|
9259
|
-
throw new Error(
|
|
9260
|
-
`Codex credit budget exhausted: ${ledger.spentCredits.toFixed(3)} spent; ${usableCredits.toFixed(3)} usable after the ${args.config.reserveCredits.toFixed(3)} safety reserve.`
|
|
9261
|
-
);
|
|
9262
|
-
}
|
|
9263
|
-
await writeLockState(lock, "in-flight");
|
|
9264
|
-
dispatchStarted = true;
|
|
9265
|
-
let result;
|
|
9266
|
-
try {
|
|
9267
|
-
result = await args.run();
|
|
9268
|
-
} catch (error) {
|
|
9269
|
-
if (error instanceof CodexCreditDispatchError) {
|
|
9270
|
-
await writeLockState(lock, "settled");
|
|
9271
|
-
accountingSettled = true;
|
|
9272
|
-
} else {
|
|
9273
|
-
const blockedLedger = {
|
|
9274
|
-
...ledger,
|
|
9275
|
-
blockedReason: error instanceof CodexCreditAccountingError ? error.message : `Codex dispatch outcome is unknown after an unexpected error: ${safeErrorMessage(error)}`
|
|
9276
|
-
};
|
|
9277
|
-
await writeLedger(args.config.ledgerPath, blockedLedger);
|
|
9278
|
-
await writeLockState(lock, "settled");
|
|
9279
|
-
accountingSettled = true;
|
|
9280
|
-
}
|
|
9281
|
-
throw error;
|
|
9282
|
-
}
|
|
9283
|
-
const credits = calculateCodexCredits(args.model, result.usage);
|
|
9284
|
-
const nextSpent = ledger.spentCredits + credits;
|
|
9285
|
-
const nextLedger = {
|
|
9286
|
-
...ledger,
|
|
9287
|
-
spentCredits: nextSpent,
|
|
9288
|
-
entries: [
|
|
9289
|
-
...ledger.entries,
|
|
9290
|
-
{
|
|
9291
|
-
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9292
|
-
model: args.model,
|
|
9293
|
-
credits,
|
|
9294
|
-
...result.usage
|
|
9295
|
-
}
|
|
9296
|
-
]
|
|
9297
|
-
};
|
|
9298
|
-
await writeLedger(args.config.ledgerPath, nextLedger);
|
|
9299
|
-
await writeLockState(lock, "settled");
|
|
9300
|
-
accountingSettled = true;
|
|
9301
|
-
args.onUsagePersisted?.(result.usage);
|
|
9302
|
-
if (nextSpent > args.config.budgetCredits) {
|
|
9303
|
-
throw new Error(
|
|
9304
|
-
`Codex credit budget exceeded by completed call: ${nextSpent.toFixed(3)} > ${args.config.budgetCredits.toFixed(3)} credits. Usage was persisted; stop the benchmark immediately.`
|
|
9305
|
-
);
|
|
9306
|
-
}
|
|
9307
|
-
return result.value;
|
|
9308
|
-
} finally {
|
|
9309
|
-
try {
|
|
9310
|
-
if (lock) {
|
|
9311
|
-
try {
|
|
9312
|
-
await lock.close();
|
|
9313
|
-
} finally {
|
|
9314
|
-
if (!dispatchStarted || accountingSettled) {
|
|
9315
|
-
await removeOwnedLedgerLock(lockPath);
|
|
9316
|
-
}
|
|
9317
|
-
}
|
|
9318
|
-
}
|
|
9319
|
-
} finally {
|
|
9320
|
-
release();
|
|
9321
|
-
}
|
|
9322
|
-
}
|
|
9323
|
-
}
|
|
9324
|
-
async function acquireLedgerLock(lockPath) {
|
|
9325
|
-
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
9326
|
-
try {
|
|
9327
|
-
await mkdir5(lockPath, { mode: 448 });
|
|
9328
|
-
} catch (error) {
|
|
9329
|
-
if (error.code !== "EEXIST") throw error;
|
|
9330
|
-
const owner = await readLockOwner(lockPath);
|
|
9331
|
-
if (!owner || isProcessAlive(owner.pid) || owner.phase === "in-flight") {
|
|
9332
|
-
throw new Error(
|
|
9333
|
-
`Codex credit ledger is locked${owner?.phase === "in-flight" ? " with unreconciled in-flight usage" : " by another benchmark process"} (${lockPath}); refusing credit spend.`
|
|
9334
|
-
);
|
|
9335
|
-
}
|
|
9336
|
-
await reclaimStaleLedgerLock(lockPath, owner);
|
|
9337
|
-
continue;
|
|
9338
|
-
}
|
|
9339
|
-
let createdLock;
|
|
9340
|
-
try {
|
|
9341
|
-
await mkdir5(lockHeldPath(lockPath));
|
|
9342
|
-
createdLock = await open(lockOwnerPath(lockPath), "wx", 384);
|
|
9343
|
-
await writeLockState(createdLock, "preflight");
|
|
9344
|
-
return createdLock;
|
|
9345
|
-
} catch (error) {
|
|
9346
|
-
await createdLock?.close().catch(() => void 0);
|
|
9347
|
-
await unlink3(lockOwnerPath(lockPath)).catch(() => void 0);
|
|
9348
|
-
await rmdir(lockHeldPath(lockPath)).catch(() => void 0);
|
|
9349
|
-
await rmdir(lockPath).catch(() => void 0);
|
|
9350
|
-
throw error;
|
|
9351
|
-
}
|
|
9352
|
-
}
|
|
9353
|
-
throw new Error(`Unable to acquire Codex credit ledger lock (${lockPath})`);
|
|
9354
|
-
}
|
|
9355
|
-
async function readLockOwner(lockPath) {
|
|
9356
|
-
try {
|
|
9357
|
-
const parsed = JSON.parse(await readFile6(lockOwnerPath(lockPath), "utf8"));
|
|
9358
|
-
if (!Number.isSafeInteger(parsed.pid) || parsed.pid <= 0 || parsed.phase !== "preflight" && parsed.phase !== "in-flight" && parsed.phase !== "settled") {
|
|
9359
|
-
return void 0;
|
|
9360
|
-
}
|
|
9361
|
-
return { pid: parsed.pid, phase: parsed.phase };
|
|
9362
|
-
} catch {
|
|
9363
|
-
return void 0;
|
|
9364
|
-
}
|
|
9365
|
-
}
|
|
9366
|
-
async function reclaimStaleLedgerLock(lockPath, expectedOwner) {
|
|
9367
|
-
try {
|
|
9368
|
-
await rmdir(lockHeldPath(lockPath));
|
|
9369
|
-
} catch (error) {
|
|
9370
|
-
throw new Error(
|
|
9371
|
-
`Codex credit ledger stale-lock reclamation is already claimed or incomplete (${lockPath}); refusing credit spend: ${safeErrorMessage(error)}`
|
|
9372
|
-
);
|
|
9373
|
-
}
|
|
9374
|
-
const currentOwner = await readLockOwner(lockPath);
|
|
9375
|
-
if (!currentOwner || currentOwner.pid !== expectedOwner.pid || currentOwner.phase !== expectedOwner.phase || isProcessAlive(currentOwner.pid) || currentOwner.phase === "in-flight") {
|
|
9376
|
-
throw new Error(
|
|
9377
|
-
`Codex credit ledger owner changed during stale-lock reclamation (${lockPath}); refusing credit spend.`
|
|
9378
|
-
);
|
|
9379
|
-
}
|
|
9380
|
-
await unlink3(lockOwnerPath(lockPath));
|
|
9381
|
-
await rmdir(lockPath);
|
|
9382
|
-
}
|
|
9383
|
-
async function removeOwnedLedgerLock(lockPath) {
|
|
9384
|
-
await rmdir(lockHeldPath(lockPath));
|
|
9385
|
-
await unlink3(lockOwnerPath(lockPath));
|
|
9386
|
-
await rmdir(lockPath);
|
|
9387
|
-
}
|
|
9388
|
-
function lockOwnerPath(lockPath) {
|
|
9389
|
-
return path7.join(lockPath, "owner.json");
|
|
9390
|
-
}
|
|
9391
|
-
function lockHeldPath(lockPath) {
|
|
9392
|
-
return path7.join(lockPath, "held");
|
|
9393
|
-
}
|
|
9394
|
-
async function writeLockState(lock, phase) {
|
|
9395
|
-
const contents = `${JSON.stringify({
|
|
9396
|
-
pid: process.pid,
|
|
9397
|
-
phase,
|
|
9398
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9399
|
-
})}
|
|
9400
|
-
`;
|
|
9401
|
-
await lock.truncate(0);
|
|
9402
|
-
await lock.write(contents, 0, "utf8");
|
|
9403
|
-
await lock.sync();
|
|
9404
|
-
}
|
|
9405
|
-
function isProcessAlive(pid) {
|
|
9406
|
-
try {
|
|
9407
|
-
process.kill(pid, 0);
|
|
9408
|
-
return true;
|
|
9409
|
-
} catch (error) {
|
|
9410
|
-
return error.code === "EPERM";
|
|
9411
|
-
}
|
|
9412
|
-
}
|
|
9413
|
-
function parseCodexJsonlUsage(output) {
|
|
9414
|
-
let usage;
|
|
9415
|
-
for (const line of output.split(/\r?\n/)) {
|
|
9416
|
-
const trimmed = line.trim();
|
|
9417
|
-
if (!trimmed.startsWith("{")) continue;
|
|
9418
|
-
try {
|
|
9419
|
-
const event = JSON.parse(trimmed);
|
|
9420
|
-
if (event.type !== "turn.completed" || !event.usage) continue;
|
|
9421
|
-
const inputTokens = readCounter(event.usage.input_tokens);
|
|
9422
|
-
const outputTokens = readCounter(event.usage.output_tokens);
|
|
9423
|
-
const cachedInputTokens = readOptionalCounter(
|
|
9424
|
-
event.usage.cached_input_tokens
|
|
9425
|
-
);
|
|
9426
|
-
const reasoningOutputTokens = readOptionalCounter(
|
|
9427
|
-
event.usage.reasoning_output_tokens
|
|
9428
|
-
);
|
|
9429
|
-
if (inputTokens !== void 0 && outputTokens !== void 0 && cachedInputTokens !== void 0 && reasoningOutputTokens !== void 0) {
|
|
9430
|
-
usage = {
|
|
9431
|
-
inputTokens,
|
|
9432
|
-
cachedInputTokens,
|
|
9433
|
-
outputTokens,
|
|
9434
|
-
reasoningOutputTokens
|
|
9435
|
-
};
|
|
9436
|
-
}
|
|
9437
|
-
} catch {
|
|
9438
|
-
}
|
|
9439
|
-
}
|
|
9440
|
-
return usage;
|
|
9441
|
-
}
|
|
9442
|
-
function calculateCodexCredits(model, usage) {
|
|
9443
|
-
const rate = resolveRate(model);
|
|
9444
|
-
const cached = Math.min(usage.inputTokens, usage.cachedInputTokens);
|
|
9445
|
-
const uncached = usage.inputTokens - cached;
|
|
9446
|
-
return (uncached * rate.input + cached * rate.cachedInput + usage.outputTokens * rate.output) / ONE_MILLION;
|
|
9447
|
-
}
|
|
9448
|
-
function resolveRate(model) {
|
|
9449
|
-
const match = CREDIT_RATES.find(([pattern]) => pattern.test(model));
|
|
9450
|
-
if (!match) {
|
|
9451
|
-
throw new Error(
|
|
9452
|
-
`No Codex credit rate is configured for model ${JSON.stringify(model)}; refusing to run under a bounded credit budget.`
|
|
9453
|
-
);
|
|
9454
|
-
}
|
|
9455
|
-
return match[1];
|
|
9456
|
-
}
|
|
9457
|
-
function assertModelAllowed(model, config) {
|
|
9458
|
-
resolveRate(model);
|
|
9459
|
-
if (SOL_MODEL.test(model) && !config.allowSol) {
|
|
9460
|
-
throw new Error(
|
|
9461
|
-
"gpt-5.6-sol is disabled for bounded benchmark runs because it is the most expensive GPT-5.6 tier. Use gpt-5.6-terra or gpt-5.6-luna, or explicitly set REMNIC_BENCH_CODEX_ALLOW_SOL=1."
|
|
9462
|
-
);
|
|
9463
|
-
}
|
|
9464
|
-
}
|
|
9465
|
-
async function readLedger(config) {
|
|
9466
|
-
try {
|
|
9467
|
-
const parsed = JSON.parse(await readFile6(config.ledgerPath, "utf8"));
|
|
9468
|
-
if (parsed.schemaVersion !== 1 || parsed.budgetCredits !== config.budgetCredits || parsed.reserveCredits !== config.reserveCredits || typeof parsed.spentCredits !== "number" || !Number.isFinite(parsed.spentCredits) || parsed.spentCredits < 0 || !Array.isArray(parsed.entries)) {
|
|
9469
|
-
throw new Error("ledger schema or budget does not match this run");
|
|
9470
|
-
}
|
|
9471
|
-
return parsed;
|
|
9472
|
-
} catch (error) {
|
|
9473
|
-
if (error.code !== "ENOENT") {
|
|
9474
|
-
throw new Error(`Invalid Codex credit ledger at ${config.ledgerPath}: ${String(error)}`);
|
|
9475
|
-
}
|
|
9476
|
-
return {
|
|
9477
|
-
schemaVersion: 1,
|
|
9478
|
-
budgetCredits: config.budgetCredits,
|
|
9479
|
-
reserveCredits: config.reserveCredits,
|
|
9480
|
-
spentCredits: 0,
|
|
9481
|
-
entries: []
|
|
9482
|
-
};
|
|
9483
|
-
}
|
|
9484
|
-
}
|
|
9485
|
-
async function writeLedger(filePath, ledger) {
|
|
9486
|
-
await mkdir5(path7.dirname(filePath), { recursive: true, mode: 448 });
|
|
9487
|
-
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
9488
|
-
await writeFile5(tempPath, `${JSON.stringify(ledger, null, 2)}
|
|
9489
|
-
`, {
|
|
9490
|
-
encoding: "utf8",
|
|
9491
|
-
mode: 384
|
|
9492
|
-
});
|
|
9493
|
-
await rename2(tempPath, filePath);
|
|
9494
|
-
}
|
|
9495
|
-
function readCounter(value) {
|
|
9496
|
-
return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
9497
|
-
}
|
|
9498
|
-
function readOptionalCounter(value) {
|
|
9499
|
-
return value === void 0 ? 0 : readCounter(value);
|
|
9500
|
-
}
|
|
9501
|
-
function safeErrorMessage(error) {
|
|
9502
|
-
return error instanceof Error ? error.message : String(error);
|
|
9503
|
-
}
|
|
9504
|
-
function expandHomeRelativePath2(value) {
|
|
9505
|
-
if (value === "~") return os4.homedir();
|
|
9506
|
-
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
9507
|
-
return path7.join(os4.homedir(), value.slice(2));
|
|
9508
|
-
}
|
|
9509
|
-
return value;
|
|
9510
|
-
}
|
|
9511
|
-
function parsePositiveNumber(value, name) {
|
|
9512
|
-
const parsed = Number(value);
|
|
9513
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
9514
|
-
throw new Error(`${name} must be a finite number greater than zero`);
|
|
9515
|
-
}
|
|
9516
|
-
return parsed;
|
|
9517
|
-
}
|
|
9518
|
-
function parseNonNegativeNumber(value, name) {
|
|
9519
|
-
const parsed = Number(value);
|
|
9520
|
-
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
9521
|
-
throw new Error(`${name} must be a finite non-negative number`);
|
|
9522
|
-
}
|
|
9523
|
-
return parsed;
|
|
9524
|
-
}
|
|
9525
|
-
|
|
9526
9649
|
// src/providers/codex-cli.ts
|
|
9527
9650
|
var DEFAULT_REASONING_EFFORT = "xhigh";
|
|
9528
9651
|
var DEFAULT_SERVICE_TIER = "default";
|
|
@@ -9611,7 +9734,10 @@ var CodexCliProvider = class {
|
|
|
9611
9734
|
throw codexCliAbortError(opts.signal);
|
|
9612
9735
|
}
|
|
9613
9736
|
const startedAt = performance.now();
|
|
9614
|
-
const creditBudget = resolveCodexCreditBudgetConfig(
|
|
9737
|
+
const creditBudget = resolveCodexCreditBudgetConfig(
|
|
9738
|
+
process.env,
|
|
9739
|
+
resolveBenchmarkRunId()
|
|
9740
|
+
);
|
|
9615
9741
|
if (creditBudget) {
|
|
9616
9742
|
await this.assertChatGptCreditAuth();
|
|
9617
9743
|
}
|
|
@@ -10194,7 +10320,7 @@ function resolveCodexCliDiagnosticsMode(config) {
|
|
|
10194
10320
|
}
|
|
10195
10321
|
function inspectCodexCompletionPrompt(prompt) {
|
|
10196
10322
|
const stats = {
|
|
10197
|
-
sha256:
|
|
10323
|
+
sha256: createHash6("sha256").update(prompt).digest("hex"),
|
|
10198
10324
|
chars: prompt.length,
|
|
10199
10325
|
lines: prompt.length === 0 ? 0 : prompt.split("\n").length
|
|
10200
10326
|
};
|
|
@@ -15061,11 +15187,11 @@ async function resolveLocalLabRuntimeProfile(options) {
|
|
|
15061
15187
|
// src/benchmark.ts
|
|
15062
15188
|
import fs2 from "fs";
|
|
15063
15189
|
import path35 from "path";
|
|
15064
|
-
import { createHash as
|
|
15190
|
+
import { createHash as createHash12 } from "crypto";
|
|
15065
15191
|
import { expandTildePath as expandTildePath3 } from "@remnic/core";
|
|
15066
15192
|
|
|
15067
15193
|
// src/judges/judge-cache.ts
|
|
15068
|
-
import { createHash as
|
|
15194
|
+
import { createHash as createHash7, randomBytes as randomBytes2 } from "crypto";
|
|
15069
15195
|
import {
|
|
15070
15196
|
mkdir as mkdir9,
|
|
15071
15197
|
readFile as readFile11,
|
|
@@ -15108,8 +15234,8 @@ var JudgeCache = class {
|
|
|
15108
15234
|
}
|
|
15109
15235
|
/** Compute the sha256-hex key for a set of parts. Pure, sync, side-effect-free. */
|
|
15110
15236
|
computeKey(parts) {
|
|
15111
|
-
const fieldDigest = (value) =>
|
|
15112
|
-
return
|
|
15237
|
+
const fieldDigest = (value) => createHash7("sha256").update(value).digest();
|
|
15238
|
+
return createHash7("sha256").update(fieldDigest(parts.benchmarkId)).update(fieldDigest(parts.datasetVersion)).update(fieldDigest(parts.questionId)).update(fieldDigest(parts.answerText)).update(fieldDigest(parts.judgePromptHash)).update(fieldDigest(parts.judgeModelId)).update(fieldDigest(parts.judgeParamsHash)).digest("hex");
|
|
15113
15239
|
}
|
|
15114
15240
|
/**
|
|
15115
15241
|
* Read a previously-stored verdict. Returns `undefined` on miss, corrupted
|
|
@@ -15304,7 +15430,7 @@ function runJudgeWithCache(options) {
|
|
|
15304
15430
|
// Binary prompts are content-sensitive: two distinct prompts of
|
|
15305
15431
|
// the same character length would collide on the previous
|
|
15306
15432
|
// `binary:N` key, so key on a sha256 prefix of the prompt body.
|
|
15307
|
-
questionId: `binary:${
|
|
15433
|
+
questionId: `binary:${createHash7("sha256").update(prompt).digest("hex").slice(0, 16)}`,
|
|
15308
15434
|
answerText: prompt,
|
|
15309
15435
|
judgePromptHash: keyExtras.judgePromptHash ?? "unknown-prompt",
|
|
15310
15436
|
judgeModelId: keyExtras.judgeModelId ?? "unknown-judge",
|
|
@@ -22795,7 +22921,7 @@ var StructuredLiteralParser = class {
|
|
|
22795
22921
|
};
|
|
22796
22922
|
|
|
22797
22923
|
// src/benchmarks/published/personamem/runner.ts
|
|
22798
|
-
import { createHash as
|
|
22924
|
+
import { createHash as createHash8, randomUUID as randomUUID7 } from "crypto";
|
|
22799
22925
|
import { readFile as readFile16, realpath as realpath4 } from "fs/promises";
|
|
22800
22926
|
import path19 from "path";
|
|
22801
22927
|
|
|
@@ -23400,7 +23526,7 @@ function buildMcqPrompt(sample, seed) {
|
|
|
23400
23526
|
function deterministicShuffle(values, seedMaterial) {
|
|
23401
23527
|
return values.map((value, index) => ({
|
|
23402
23528
|
value,
|
|
23403
|
-
key:
|
|
23529
|
+
key: createHash8("sha256").update(`${seedMaterial}:${index}:${value}`).digest("hex"),
|
|
23404
23530
|
index
|
|
23405
23531
|
})).sort((left, right) => {
|
|
23406
23532
|
const byKey = left.key.localeCompare(right.key);
|
|
@@ -31859,7 +31985,7 @@ function pairedDeltaConfidenceInterval(candidateValues, baselineValues, options
|
|
|
31859
31985
|
}
|
|
31860
31986
|
|
|
31861
31987
|
// src/judges/sealed-rubric.ts
|
|
31862
|
-
import { createHash as
|
|
31988
|
+
import { createHash as createHash9 } from "crypto";
|
|
31863
31989
|
import { appendFileSync, mkdirSync } from "fs";
|
|
31864
31990
|
import path31 from "path";
|
|
31865
31991
|
|
|
@@ -31968,7 +32094,7 @@ function loadSealedRubric(id = DEFAULT_ASSISTANT_RUBRIC_ID, options = {}) {
|
|
|
31968
32094
|
if (typeof prompt !== "string" || prompt.length === 0) {
|
|
31969
32095
|
throw new Error(`sealed rubric not found in registry: ${id}`);
|
|
31970
32096
|
}
|
|
31971
|
-
const sha256 =
|
|
32097
|
+
const sha256 = createHash9("sha256").update(prompt, "utf8").digest("hex");
|
|
31972
32098
|
const version = parseVersionFromId(id);
|
|
31973
32099
|
return { id, version, prompt, sha256 };
|
|
31974
32100
|
}
|
|
@@ -34171,7 +34297,7 @@ async function runRetentionAgedDatasetBenchmark(options) {
|
|
|
34171
34297
|
import { randomUUID as randomUUID31 } from "crypto";
|
|
34172
34298
|
|
|
34173
34299
|
// src/benchmarks/remnic/memcorrect/generator.ts
|
|
34174
|
-
import { createHash as
|
|
34300
|
+
import { createHash as createHash10 } from "crypto";
|
|
34175
34301
|
|
|
34176
34302
|
// src/benchmarks/remnic/memcorrect/token-pools.ts
|
|
34177
34303
|
var PERSONAS = [
|
|
@@ -34495,7 +34621,7 @@ function corpusHash(corpus) {
|
|
|
34495
34621
|
uptakeLatencyCap: corpus.options.uptakeLatencyCap,
|
|
34496
34622
|
scenarios: corpus.scenarios
|
|
34497
34623
|
});
|
|
34498
|
-
return
|
|
34624
|
+
return createHash10("sha256").update(canonical).digest("hex");
|
|
34499
34625
|
}
|
|
34500
34626
|
|
|
34501
34627
|
// src/benchmarks/remnic/memcorrect/schema.ts
|
|
@@ -35450,7 +35576,7 @@ import { mkdir as mkdir17, writeFile as writeFile16 } from "fs/promises";
|
|
|
35450
35576
|
import path34 from "path";
|
|
35451
35577
|
|
|
35452
35578
|
// src/benchmarks/remnic/bounded-memory-contracts/fixture.ts
|
|
35453
|
-
import { createHash as
|
|
35579
|
+
import { createHash as createHash11 } from "crypto";
|
|
35454
35580
|
var SCOPE_ACME = "project:acme";
|
|
35455
35581
|
var SCOPE_BETA = "project:beta";
|
|
35456
35582
|
var SCOPE_ALICE = "user:alice";
|
|
@@ -35933,7 +36059,7 @@ var BOUNDED_MEMORY_SMOKE_FIXTURE = [
|
|
|
35933
36059
|
function fixtureHash(tasks) {
|
|
35934
36060
|
const source = tasks ?? BOUNDED_MEMORY_FIXTURE;
|
|
35935
36061
|
const payload = JSON.stringify(source);
|
|
35936
|
-
return
|
|
36062
|
+
return createHash11("sha256").update(payload, "utf8").digest("hex");
|
|
35937
36063
|
}
|
|
35938
36064
|
|
|
35939
36065
|
// src/benchmarks/remnic/bounded-memory-contracts/agent.ts
|
|
@@ -37193,13 +37319,13 @@ function wrapJudgeWithCache(args) {
|
|
|
37193
37319
|
// differentiator is part of the prompt hash. Bumping
|
|
37194
37320
|
// JUDGE_CACHE_PROTOCOL_VERSION invalidates verdicts when judge
|
|
37195
37321
|
// prompt/parse semantics change (PR #1591, High).
|
|
37196
|
-
judgePromptHash:
|
|
37322
|
+
judgePromptHash: createHash12("sha256").update(JUDGE_CACHE_PROTOCOL_VERSION).update("").update(args.amaBenchJudgeProtocol).update("").update(args.role).digest("hex"),
|
|
37197
37323
|
judgeModelId: args.provider?.model !== void 0 && args.provider.model.length > 0 ? `${args.provider.model}${crossJudgeIdSuffix}` : `unknown-${args.role}-judge`,
|
|
37198
37324
|
// Full judge configuration, deterministically serialized (sorted
|
|
37199
37325
|
// keys) so provider/base-url/retry changes produce fresh cache
|
|
37200
37326
|
// keys. `role` is included so primary and cross judges never
|
|
37201
37327
|
// share a paramsHash.
|
|
37202
|
-
judgeParamsHash:
|
|
37328
|
+
judgeParamsHash: createHash12("sha256").update(
|
|
37203
37329
|
stableStringify2({
|
|
37204
37330
|
role: args.role,
|
|
37205
37331
|
provider: args.provider
|
|
@@ -39307,7 +39433,7 @@ var chatFixture = {
|
|
|
39307
39433
|
};
|
|
39308
39434
|
|
|
39309
39435
|
// src/judges/calibration-slice.ts
|
|
39310
|
-
import { createHash as
|
|
39436
|
+
import { createHash as createHash13, randomBytes as randomBytes3 } from "crypto";
|
|
39311
39437
|
import { mkdir as mkdir18, readFile as readFile22, rename as rename4, unlink as unlink4, writeFile as writeFile17 } from "fs/promises";
|
|
39312
39438
|
import path37 from "path";
|
|
39313
39439
|
|
|
@@ -39454,7 +39580,7 @@ function selectCalibrationSlice(questionIds, size = CALIBRATION_SLICE_SIZE) {
|
|
|
39454
39580
|
unique.push(id);
|
|
39455
39581
|
}
|
|
39456
39582
|
}
|
|
39457
|
-
return unique.map((id) => ({ id, digest:
|
|
39583
|
+
return unique.map((id) => ({ id, digest: createHash13("sha256").update(id, "utf8").digest("hex") })).sort((a, b) => a.digest < b.digest ? -1 : a.digest > b.digest ? 1 : 0).slice(0, Math.min(size, unique.length)).map((entry) => entry.id);
|
|
39458
39584
|
}
|
|
39459
39585
|
async function runJudgeCalibration(options) {
|
|
39460
39586
|
const binScore = options.binScore ?? ((score) => binarizeJudgeScore(score));
|
|
@@ -39529,7 +39655,7 @@ function validatePinnedQuestionIds(ids, availableIds) {
|
|
|
39529
39655
|
return [...ids];
|
|
39530
39656
|
}
|
|
39531
39657
|
function hashCalibrationAnswerSet(answers) {
|
|
39532
|
-
return
|
|
39658
|
+
return createHash13("sha256").update(JSON.stringify(answers.map((answer) => [
|
|
39533
39659
|
answer.questionId,
|
|
39534
39660
|
answer.question,
|
|
39535
39661
|
answer.predicted,
|
|
@@ -40985,7 +41111,7 @@ function createMitigatedTarget(config) {
|
|
|
40985
41111
|
}
|
|
40986
41112
|
|
|
40987
41113
|
// src/coding-graph/generator.ts
|
|
40988
|
-
import { createHash as
|
|
41114
|
+
import { createHash as createHash14 } from "crypto";
|
|
40989
41115
|
function createSeededRng3(seed) {
|
|
40990
41116
|
let state = seed >>> 0;
|
|
40991
41117
|
return function rng() {
|
|
@@ -41014,7 +41140,7 @@ var EDGE_TYPE_WEIGHTS = [
|
|
|
41014
41140
|
var PROVENANCE_VALUES = ["heuristic", "heuristic", "heuristic", "trace"];
|
|
41015
41141
|
var AVG_BYTES_PER_LINE = 40;
|
|
41016
41142
|
function hashContent(input) {
|
|
41017
|
-
return
|
|
41143
|
+
return createHash14("sha256").update(input).digest("hex").slice(0, 16);
|
|
41018
41144
|
}
|
|
41019
41145
|
function generateSyntheticRepo(config) {
|
|
41020
41146
|
const rng = createSeededRng3(config.seed);
|