@tangle-network/agent-eval 0.144.0 → 0.144.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/analyst/index.d.ts +82 -17
  3. package/dist/analyst/index.d.ts.map +1 -1
  4. package/dist/analyst/index.js +4 -4
  5. package/dist/{benchmark-command-4c7N_rlw.js → benchmark-command-95Zqd1e8.js} +331 -110
  6. package/dist/benchmark-command-95Zqd1e8.js.map +1 -0
  7. package/dist/benchmarks/index.d.ts +1 -1
  8. package/dist/benchmarks/index.js +1 -1
  9. package/dist/{benchmarks-05UGZ8sZ.js → benchmarks-CRT4ScEA.js} +4 -4
  10. package/dist/{benchmarks-05UGZ8sZ.js.map → benchmarks-CRT4ScEA.js.map} +1 -1
  11. package/dist/campaign/index.d.ts +4 -4
  12. package/dist/campaign/index.js +4 -4
  13. package/dist/{campaign-BKOtvRAB.js → campaign-CefP3fPS.js} +4 -4
  14. package/dist/{campaign-BKOtvRAB.js.map → campaign-CefP3fPS.js.map} +1 -1
  15. package/dist/cli.js +2 -2
  16. package/dist/contract/index.d.ts +1 -1
  17. package/dist/contract/index.js +3 -3
  18. package/dist/{default-registry-DfHJEwYh.js → default-registry-SOyHB6qG.js} +2 -2
  19. package/dist/{default-registry-DfHJEwYh.js.map → default-registry-SOyHB6qG.js.map} +1 -1
  20. package/dist/{dspy-rlm-engine-CBFwlyaY.js → dspy-rlm-engine-BR7TtB0o.js} +61 -105
  21. package/dist/dspy-rlm-engine-BR7TtB0o.js.map +1 -0
  22. package/dist/{eval-campaign-YdkpWWoT.js → eval-campaign-lI7wB9DH.js} +2 -2
  23. package/dist/{eval-campaign-YdkpWWoT.js.map → eval-campaign-lI7wB9DH.js.map} +1 -1
  24. package/dist/{external-optimizer-contracts-iK0yu4AR.d.ts → external-optimizer-contracts-CdmX2K2S.d.ts} +47 -10
  25. package/dist/external-optimizer-contracts-CdmX2K2S.d.ts.map +1 -0
  26. package/dist/{index-DgbFl4cv.d.ts → index-BrpxwELi.d.ts} +2 -2
  27. package/dist/{index-DgbFl4cv.d.ts.map → index-BrpxwELi.d.ts.map} +1 -1
  28. package/dist/{index-DtMpBKVF.d.ts → index-DRI1DU5z.d.ts} +3 -3
  29. package/dist/{index-DtMpBKVF.d.ts.map → index-DRI1DU5z.d.ts.map} +1 -1
  30. package/dist/index.d.ts +4 -4
  31. package/dist/index.js +9 -9
  32. package/dist/{llm-client-B3WXSH5Y.js → llm-client-D3EoChAU.js} +7 -7
  33. package/dist/llm-client-D3EoChAU.js.map +1 -0
  34. package/dist/openapi.json +1 -1
  35. package/dist/rl.js +1 -1
  36. package/dist/{semantic-concept-judge-DJQtFr95.js → semantic-concept-judge-l8Lb3Kqz.js} +2 -2
  37. package/dist/{semantic-concept-judge-DJQtFr95.js.map → semantic-concept-judge-l8Lb3Kqz.js.map} +1 -1
  38. package/dist/{server-Cu4M3NSO.js → server-Df00sdwz.js} +3 -3
  39. package/dist/{server-Cu4M3NSO.js.map → server-Df00sdwz.js.map} +1 -1
  40. package/dist/{single-run-lock-t1si1ob7.js → single-run-lock-B-cFnnNn.js} +718 -186
  41. package/dist/single-run-lock-B-cFnnNn.js.map +1 -0
  42. package/dist/{skill-usage-BiVEU0QY.d.ts → skill-usage-3vUWdZ9n.d.ts} +23 -4
  43. package/dist/skill-usage-3vUWdZ9n.d.ts.map +1 -0
  44. package/dist/{skillopt-optimization-method-Ds8J1_K8.js → skillopt-optimization-method-DA5mJmFE.js} +15 -204
  45. package/dist/skillopt-optimization-method-DA5mJmFE.js.map +1 -0
  46. package/dist/{skillopt-optimization-method-B7o01OdX.d.ts → skillopt-optimization-method-DNniakI5.d.ts} +6 -2
  47. package/dist/{skillopt-optimization-method-B7o01OdX.d.ts.map → skillopt-optimization-method-DNniakI5.d.ts.map} +1 -1
  48. package/dist/types-BjMFz88h.d.ts.map +1 -1
  49. package/dist/wire/index.js +1 -1
  50. package/docs/trace-analysis.md +43 -32
  51. package/package.json +1 -1
  52. package/dist/benchmark-command-4c7N_rlw.js.map +0 -1
  53. package/dist/dspy-rlm-engine-CBFwlyaY.js.map +0 -1
  54. package/dist/external-optimizer-contracts-iK0yu4AR.d.ts.map +0 -1
  55. package/dist/llm-client-B3WXSH5Y.js.map +0 -1
  56. package/dist/single-run-lock-t1si1ob7.js.map +0 -1
  57. package/dist/skill-usage-BiVEU0QY.d.ts.map +0 -1
  58. package/dist/skillopt-optimization-method-Ds8J1_K8.js.map +0 -1
@@ -1,12 +1,12 @@
1
1
  import { c as ValidationError, t as AgentEvalError } from "./errors-D-LKuDhb.js";
2
2
  import { s as resolveModelPricing } from "./metrics-C9YY1OcL.js";
3
3
  import { a as CostLedgerPersistenceError, i as CostLedger, n as CostCallConflictError, o as CostReceiptCaptureError, r as CostCeilingReachedError, s as CostReservationExceededError, t as CostAccountingIncompleteError } from "./cost-ledger-DMFxsLKr.js";
4
- import { c as callLlmJson, f as maximumChargeForLlmRequest, l as costReceiptFromLlm, r as LlmResponseError, t as LlmCallError, u as costReceiptFromLlmError } from "./llm-client-B3WXSH5Y.js";
4
+ import { c as callLlmJson, r as LlmResponseError, t as LlmCallError } from "./llm-client-D3EoChAU.js";
5
5
  import { O as evidenceRefsFromRawFinding, h as TRACE_ANALYSIS_LIMITS, i as runTraceAnalyst } from "./kind-factory-Bvwe3pup.js";
6
6
  import { o as makeFinding, r as usageReceiptFromCostLedger } from "./usage-receipt-CgxMEBZq.js";
7
7
  import { i as hashCanonical, r as canonicalString } from "./canonical-D011XM8r.js";
8
- import { n as createRunCostLedger, r as fsCampaignStorage, t as acquireSingleRunLock } from "./single-run-lock-t1si1ob7.js";
9
- import { t as createDspyRlmTraceEngine } from "./dspy-rlm-engine-CBFwlyaY.js";
8
+ import { M as resolveExternalOptimizerProcessLimits, f as runWithCleanup, n as createRunCostLedger, p as startExternalOptimizerModelProxy, r as fsCampaignStorage, t as acquireSingleRunLock } from "./single-run-lock-B-cFnnNn.js";
9
+ import { t as createDspyRlmTraceEngine } from "./dspy-rlm-engine-BR7TtB0o.js";
10
10
  import { c as writeLedgerFileAtomically, s as withLedgerFileLock } from "./ledger-core-Dxz0Rkwa.js";
11
11
  import { E as pairedBootstrap } from "./statistics-ByxzSiOM.js";
12
12
  import { i as otlpTextToTraceAnalysisStore, r as createOtlpBufferTraceStore, t as DEFAULT_MAX_TRACE_FILE_BYTES } from "./store-otlp-D4I90_vR.js";
@@ -19,6 +19,7 @@ import { createHash, randomUUID } from "node:crypto";
19
19
  import { link, lstat, mkdir, open, readFile, readdir, realpath, stat, unlink } from "node:fs/promises";
20
20
  import { arch, platform } from "node:os";
21
21
  import { TextDecoder as TextDecoder$1 } from "node:util";
22
+ import { pathToFileURL } from "node:url";
22
23
  //#region src/analyst/benchmark-dataset-utils.ts
23
24
  function normalizeBenchmarkLabel(value) {
24
25
  const normalized = nonEmpty$1(value, "benchmark label").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -1070,8 +1071,34 @@ const artifactSchema = z.strictObject({
1070
1071
  concurrency: positiveInteger$1,
1071
1072
  rlmSamples: positiveInteger$1.optional(),
1072
1073
  model: nonEmptyString,
1074
+ modelOwnerCallRef: nonEmptyString.optional(),
1073
1075
  maxOutputTokens: positiveInteger$1,
1076
+ maxReasoningTokens: nonNegativeInteger.optional(),
1077
+ maxModelRequestBytes: positiveInteger$1.optional(),
1078
+ maxModelResponseBytes: positiveInteger$1.optional(),
1079
+ modelRequestTimeoutMs: positiveInteger$1.optional(),
1074
1080
  timeoutMs: positiveInteger$1,
1081
+ pricing: z.strictObject({
1082
+ inputUsdPerMillion: nonNegativeNumber,
1083
+ cachedInputUsdPerMillion: nonNegativeNumber.optional(),
1084
+ cacheWriteUsdPerMillion: nonNegativeNumber.optional(),
1085
+ outputUsdPerMillion: nonNegativeNumber
1086
+ }).optional(),
1087
+ recursiveLimits: z.strictObject({
1088
+ maxIterations: positiveInteger$1,
1089
+ maxLlmCalls: positiveInteger$1,
1090
+ maxToolCalls: positiveInteger$1,
1091
+ maxOutputChars: positiveInteger$1,
1092
+ maxModelRequests: positiveInteger$1.nullable(),
1093
+ traceToolRequestBytes: positiveInteger$1,
1094
+ traceToolResponseBytes: positiveInteger$1,
1095
+ traceToolTimeoutMs: positiveInteger$1
1096
+ }).optional(),
1097
+ processLimits: z.strictObject({
1098
+ maxInputBytes: positiveInteger$1,
1099
+ maxResultBytes: positiveInteger$1,
1100
+ maxOutputChars: positiveInteger$1
1101
+ }).optional(),
1075
1102
  maxCostUsd: nonNegativeNumber,
1076
1103
  maxArtifactBytes: positiveInteger$1,
1077
1104
  analystProtocolSha256: sha256,
@@ -1173,7 +1200,7 @@ const ANALYST_BENCHMARK_DEPENDENCY_LOCK_FILES = Object.freeze([
1173
1200
  "package.json",
1174
1201
  "pnpm-lock.yaml"
1175
1202
  ]);
1176
- const ANALYST_BENCHMARK_DEPENDENCY_LOCK_SHA256 = "6327c48fa39d9fc6da2fc1dda5d89b08e16dd1de717c2eaf18c855ad5a4282c5";
1203
+ const ANALYST_BENCHMARK_DEPENDENCY_LOCK_SHA256 = "044bf5b84d7902c43e627dd302dad22332f8787aa5ae70b72f52fbf9db667d93";
1177
1204
  /** The published benchmark evidence was produced at this package version, by
1178
1205
  * the retired one-shot direct runner, before trace analysts moved to the
1179
1206
  * recursive DSPy RLM engine. Both evidence digests below are historical facts
@@ -1228,9 +1255,11 @@ const ANALYST_BENCHMARK_IMPLEMENTATION_FILES = Object.freeze([
1228
1255
  "src/analyst/trace-tool-callback.ts",
1229
1256
  "src/analyst/types.ts",
1230
1257
  "src/analyst/usage-receipt.ts",
1258
+ "src/campaign/external-optimizer-callback.ts",
1231
1259
  "src/campaign/external-optimizer-contracts.ts",
1232
1260
  "src/campaign/external-optimizer-http.ts",
1233
1261
  "src/campaign/external-optimizer-model-proxy.ts",
1262
+ "src/campaign/external-optimizer-process.ts",
1234
1263
  "src/campaign/external-optimizer-resources.ts",
1235
1264
  "src/campaign/external-optimizer-subprocess.ts",
1236
1265
  "src/campaign/search-ledger-errors.ts",
@@ -1270,7 +1299,7 @@ const ANALYST_BENCHMARK_IMPLEMENTATION_FILES = Object.freeze([
1270
1299
  "src/trace/raw-provider-sink.ts",
1271
1300
  "src/verdict-cache.ts"
1272
1301
  ]);
1273
- const ANALYST_BENCHMARK_IMPLEMENTATION_SHA256 = "02ffe561616f79e62fcc3292ccd17cf55d5b385b8749367ce6b64e9f40586ac5";
1302
+ const ANALYST_BENCHMARK_IMPLEMENTATION_SHA256 = "d317d9e7593ddc13f22a4a1e3d62d2fa1e4591395ef3984a0c7585a75794cf8d";
1274
1303
  function analystBenchmarkImplementationDigest() {
1275
1304
  return ANALYST_BENCHMARK_IMPLEMENTATION_SHA256;
1276
1305
  }
@@ -2328,6 +2357,7 @@ async function prepareOutputLockPath(outDir) {
2328
2357
  return `${directory}.lock`;
2329
2358
  }
2330
2359
  function createRunIdentity(config, prepared) {
2360
+ const model = commandModelIdentity(config.model);
2331
2361
  const caseDefinitions = prepared.cases.map((testCase) => ({
2332
2362
  id: testCase.id,
2333
2363
  clusterId: testCase.clusterId,
@@ -2344,8 +2374,7 @@ function createRunIdentity(config, prepared) {
2344
2374
  datasetSplit: config.split,
2345
2375
  model: {
2346
2376
  id: config.model.model,
2347
- maxOutputTokens: config.model.maxOutputTokens,
2348
- timeoutMs: config.model.timeoutMs
2377
+ ...model
2349
2378
  },
2350
2379
  limit: config.limit,
2351
2380
  seed: config.seed,
@@ -2370,6 +2399,36 @@ function createRunIdentity(config, prepared) {
2370
2399
  }
2371
2400
  };
2372
2401
  }
2402
+ function commandModelIdentity(config) {
2403
+ const catalogPricing = resolveModelPricing(config.model);
2404
+ const pricing = config.pricing ?? (catalogPricing ? {
2405
+ inputUsdPerMillion: catalogPricing.input * 1e3,
2406
+ outputUsdPerMillion: catalogPricing.output * 1e3
2407
+ } : void 0);
2408
+ if (!pricing) throw new Error(`benchmark model '${config.model}' has no recorded pricing`);
2409
+ const recursive = config.dspyRlm;
2410
+ return {
2411
+ ownerCallRef: config.callRef,
2412
+ maxOutputTokens: config.maxOutputTokens,
2413
+ maxReasoningTokens: config.maxReasoningTokens ?? config.maxOutputTokens * 4,
2414
+ maxRequestBytes: config.maxModelRequestBytes ?? 16 * 1024 * 1024,
2415
+ maxResponseBytes: config.maxModelResponseBytes ?? 4 * 1024 * 1024,
2416
+ requestTimeoutMs: config.modelRequestTimeoutMs ?? config.timeoutMs,
2417
+ timeoutMs: config.timeoutMs,
2418
+ pricing: { ...pricing },
2419
+ recursiveLimits: {
2420
+ maxIterations: recursive?.maxIterations ?? 14,
2421
+ maxLlmCalls: recursive?.maxLlmCalls ?? 8,
2422
+ maxToolCalls: recursive?.maxToolCalls ?? 80,
2423
+ maxOutputChars: recursive?.maxOutputChars ?? 8e3,
2424
+ maxModelRequests: recursive?.maxModelRequests ?? null,
2425
+ traceToolRequestBytes: recursive?.traceToolRequestBytes ?? 1e6,
2426
+ traceToolResponseBytes: recursive?.traceToolResponseBytes ?? 4e6,
2427
+ traceToolTimeoutMs: recursive?.traceToolTimeoutMs ?? 6e4
2428
+ },
2429
+ processLimits: resolveExternalOptimizerProcessLimits(recursive?.runner?.limits)
2430
+ };
2431
+ }
2373
2432
  function createLocalRunReceipt(config, paths) {
2374
2433
  return {
2375
2434
  kind: "agent-eval/analyst-benchmark-local-run",
@@ -2378,8 +2437,7 @@ function createLocalRunReceipt(config, paths) {
2378
2437
  traceDir: resolve(config.traceDir),
2379
2438
  ...config.artifactDir ? { artifactDir: resolve(config.artifactDir) } : {},
2380
2439
  outputDir: paths.directory,
2381
- baseUrl: config.model.baseUrl,
2382
- apiKeyEnvironment: config.apiKeyEnv
2440
+ modelOwnerModule: config.modelOwnerModule
2383
2441
  },
2384
2442
  command: config.command,
2385
2443
  environment: {
@@ -2451,7 +2509,7 @@ async function readAndValidateResumeFiles(paths, currentIdentity, currentIdentit
2451
2509
  runIdentitySha256: currentIdentitySha256,
2452
2510
  localIdentitySha256: currentLocalIdentitySha256
2453
2511
  };
2454
- if (digestCanonical(value.local) !== currentLocalIdentitySha256 || canonicalJson(value.local) !== canonicalJson(localReceiptInput.local)) throw new Error("benchmark local paths or endpoint do not match the requested resume");
2512
+ if (digestCanonical(value.local) !== currentLocalIdentitySha256 || canonicalJson(value.local) !== canonicalJson(localReceiptInput.local)) throw new Error("benchmark local paths or model-owner module do not match the requested resume");
2455
2513
  if (localReceiptContent !== `${JSON.stringify(expectedLocalReceipt, null, 2)}\n`) throw new Error(`benchmark local run receipt does not exactly match: ${paths.localReceipt}`);
2456
2514
  if (await readRegularFile(paths.initializationComplete, "benchmark initialization marker") !== renderInitializationComplete(manifest)) throw new Error(`benchmark initialization marker does not match the run manifest: ${paths.initializationComplete}`);
2457
2515
  return manifest;
@@ -2997,8 +3055,16 @@ function assertCompletedArtifactMatchesRun(artifact, manifest, observations, pre
2997
3055
  concurrency: config.concurrency,
2998
3056
  ...config.rlmSamples === void 0 ? {} : { rlmSamples: config.rlmSamples },
2999
3057
  model: config.model.id,
3058
+ modelOwnerCallRef: config.model.ownerCallRef,
3000
3059
  maxOutputTokens: config.model.maxOutputTokens,
3060
+ maxReasoningTokens: config.model.maxReasoningTokens,
3061
+ maxModelRequestBytes: config.model.maxRequestBytes,
3062
+ maxModelResponseBytes: config.model.maxResponseBytes,
3063
+ modelRequestTimeoutMs: config.model.requestTimeoutMs,
3001
3064
  timeoutMs: config.model.timeoutMs,
3065
+ pricing: config.model.pricing,
3066
+ recursiveLimits: config.model.recursiveLimits,
3067
+ processLimits: config.model.processLimits,
3002
3068
  maxCostUsd: config.maxCostUsd,
3003
3069
  maxArtifactBytes: config.maxArtifactBytes,
3004
3070
  analystProtocolSha256: config.analystProtocolSha256,
@@ -3015,7 +3081,7 @@ function assertCompletedArtifactMatchesRun(artifact, manifest, observations, pre
3015
3081
  id: expectedDatasetId,
3016
3082
  revision: config.datasetRevision,
3017
3083
  split: config.datasetSplit
3018
- }) || provenance.caseCount !== inputs.selectedCaseIds.length || canonicalJson(provenance.runnerIds) !== canonicalJson(config.runnerIds) || provenance.repetitions !== config.repetitions || provenance.maxConcurrency !== Math.min(config.concurrency, expectedCount) || provenance.runnerOrderSeed !== config.seed || provenance.metadata?.model !== config.model.id || provenance.metadata?.rlmSamples !== config.rlmSamples || provenance.metadata?.outputAdapter !== expectedOutputAdapter || provenance.metadata?.caseSelection !== prepared.selection.method || provenance.metadata?.caseSelectionSeed !== config.seed || provenance.metadata?.selectionStratified !== prepared.selection.stratified || provenance.metadata?.protocolSha256 !== config.analystProtocolSha256 || provenance.metadata?.implementationSha256 !== config.implementationSha256 || provenance.metadata?.dependencyLockSha256 !== config.dependencyLockSha256 || provenance.metadata?.populationRepresentativenessProven !== false) throw new Error("completed benchmark result provenance does not match the run manifest");
3084
+ }) || provenance.caseCount !== inputs.selectedCaseIds.length || canonicalJson(provenance.runnerIds) !== canonicalJson(config.runnerIds) || provenance.repetitions !== config.repetitions || provenance.maxConcurrency !== Math.min(config.concurrency, expectedCount) || provenance.runnerOrderSeed !== config.seed || provenance.metadata?.model !== config.model.id || provenance.metadata?.modelOwnerCallRef !== config.model.ownerCallRef || provenance.metadata?.rlmSamples !== config.rlmSamples || provenance.metadata?.outputAdapter !== expectedOutputAdapter || provenance.metadata?.caseSelection !== prepared.selection.method || provenance.metadata?.caseSelectionSeed !== config.seed || provenance.metadata?.selectionStratified !== prepared.selection.stratified || provenance.metadata?.protocolSha256 !== config.analystProtocolSha256 || provenance.metadata?.implementationSha256 !== config.implementationSha256 || provenance.metadata?.dependencyLockSha256 !== config.dependencyLockSha256 || provenance.metadata?.populationRepresentativenessProven !== false) throw new Error("completed benchmark result provenance does not match the run manifest");
3019
3085
  const expectedSummaries = config.runnerIds.map((runnerId) => summarizeAnalystBenchmarkRunner(runnerId, observations.filter((observation) => observation.runnerId === runnerId)));
3020
3086
  if (canonicalJson(artifact.result.summaries) !== canonicalJson(expectedSummaries)) throw new Error("completed benchmark summaries do not match durable observations");
3021
3087
  const expectedComparisons = [compareAnalystRunners(artifact.result, {
@@ -3521,10 +3587,17 @@ function fileContext() {
3521
3587
  function createPublicBenchmarkDirectRunner(dataset, config) {
3522
3588
  if (config.instructionsOverride) throw new Error("the direct runner executes only the stock protocol; an instructions override requires the dspy-rlm runner");
3523
3589
  const model = requiredString(config.model, "model");
3524
- const baseUrl = requiredString(config.baseUrl, "baseUrl");
3525
- const apiKey = requiredString(config.apiKey, "apiKey");
3590
+ const callRef = requiredString(config.callRef, "callRef");
3591
+ if (typeof config.call !== "function") throw new TypeError("call must be a function");
3592
+ if (typeof config.recordExecution !== "function") throw new TypeError("recordExecution must be a function");
3526
3593
  const maxOutputTokens = positiveSafeInteger(config.maxOutputTokens, "maxOutputTokens");
3527
3594
  const timeoutMs = positiveSafeInteger(config.timeoutMs, "timeoutMs");
3595
+ const maxReasoningTokens = config.maxReasoningTokens ?? maxOutputTokens * 4;
3596
+ const maxModelRequestBytes = config.maxModelRequestBytes ?? 16 * 1024 * 1024;
3597
+ const maxModelResponseBytes = config.maxModelResponseBytes ?? 4 * 1024 * 1024;
3598
+ const modelRequestTimeoutMs = config.modelRequestTimeoutMs ?? timeoutMs;
3599
+ const pricing = config.pricing ?? pricingForModel$1(model);
3600
+ const maxCostUsd = config.maxCostUsdPerAnalysis ?? 1;
3528
3601
  const costLedger = config.costLedger ?? new CostLedger();
3529
3602
  const durability = config.durability ? {
3530
3603
  runIdentitySha256: requiredString(config.durability.runIdentitySha256, "durability.runIdentitySha256"),
@@ -3532,15 +3605,6 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
3532
3605
  } : void 0;
3533
3606
  const actor = dataset === "agentrx" ? "agentrx-root-cause-localizer" : "codetracebench-step-localizer";
3534
3607
  const outputAdapter = dataset === "agentrx" ? "agentrx-taxonomy-and-root-step" : "codetracebench-incorrect-block";
3535
- const llmOptions = {
3536
- baseUrl,
3537
- apiKey,
3538
- maximumAttempts: 1,
3539
- jsonSchemaTransport: "json-object",
3540
- jsonPayloadMode: "exact",
3541
- thinking: "disabled",
3542
- ...config.fetchImpl ? { fetch: config.fetchImpl } : {}
3543
- };
3544
3608
  return {
3545
3609
  id: "direct",
3546
3610
  async analyze(input, context) {
@@ -3558,7 +3622,8 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
3558
3622
  let modelMetadata = {
3559
3623
  analysisMode: "direct-baseline",
3560
3624
  outputAdapter,
3561
- protocolSha256: publicBenchmarkProtocolSha256(dataset)
3625
+ protocolSha256: publicBenchmarkProtocolSha256(dataset),
3626
+ callRef
3562
3627
  };
3563
3628
  try {
3564
3629
  if (!input.traceStore) throw new Error(`${dataset} model runner requires a trace store`);
@@ -3576,7 +3641,7 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
3576
3641
  jsonMode: true,
3577
3642
  thinking: "disabled",
3578
3643
  maxTokens: maxOutputTokens,
3579
- timeoutMs
3644
+ timeoutMs: modelRequestTimeoutMs
3580
3645
  };
3581
3646
  const cacheIdentity = durability ? {
3582
3647
  runIdentitySha256: durability.runIdentitySha256,
@@ -3615,26 +3680,51 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
3615
3680
  };
3616
3681
  } else {
3617
3682
  assertNoSettledResponseWithoutCache(costLedger, callId);
3618
- let completedResult;
3619
- const paid = await costLedger.runPaidCall({
3620
- ...callId ? { callId } : {},
3621
- channel: "analyst",
3622
- phase: "analyst.public-benchmark",
3623
- actor,
3624
- model,
3625
- signal: context.signal,
3626
- maximumCharge: maximumChargeForLlmRequest(request, llmOptions),
3627
- tags: costTags,
3628
- execute: async (signal, providerCallId) => {
3683
+ const providerCallId = callId ?? `analyst-benchmark-${randomUUID()}`;
3684
+ let modelProxy;
3685
+ const completed = await runWithCleanup({
3686
+ label: "public benchmark direct model resources",
3687
+ run: async () => {
3688
+ modelProxy = await startExternalOptimizerModelProxy({
3689
+ call: config.call,
3690
+ callRef,
3691
+ recordExecution: config.recordExecution,
3692
+ model,
3693
+ budget: {
3694
+ maxCostUsd,
3695
+ maxRequests: 1,
3696
+ maxRequestBytes: maxModelRequestBytes,
3697
+ maxResponseBytes: maxModelResponseBytes,
3698
+ maxOutputTokensPerRequest: maxOutputTokens,
3699
+ maxReasoningTokensPerRequest: maxReasoningTokens,
3700
+ pricing,
3701
+ requestTimeoutMs: modelRequestTimeoutMs
3702
+ },
3703
+ costLedger,
3704
+ channel: "analyst",
3705
+ phase: "analyst.public-benchmark",
3706
+ actor,
3707
+ tags: costTags,
3708
+ callId: providerCallId,
3709
+ ...context.signal ? { signal: context.signal } : {}
3710
+ });
3711
+ const llmOptions = {
3712
+ baseUrl: modelProxy.baseUrl,
3713
+ apiKey: modelProxy.apiKey,
3714
+ maximumAttempts: 1,
3715
+ jsonSchemaTransport: "json-object",
3716
+ jsonPayloadMode: "exact",
3717
+ thinking: "disabled"
3718
+ };
3629
3719
  try {
3630
3720
  const completed = await callLlmJson(request, {
3631
3721
  ...llmOptions,
3632
- signal,
3722
+ ...context.signal ? { signal: context.signal } : {},
3633
3723
  idempotencyKey: providerCallId
3634
3724
  });
3635
- completedResult = completed.result;
3636
3725
  const response = parsePublicBenchmarkModelResponse(dataset, completed.value);
3637
3726
  const responseProducedAt = (/* @__PURE__ */ new Date()).toISOString();
3727
+ const receipt = requiredSettledReceipt(costLedger, providerCallId);
3638
3728
  if (cacheIdentity) writePublicBenchmarkResponseCache(durability.responseCacheDir, {
3639
3729
  kind: "agent-eval/public-benchmark-model-response",
3640
3730
  ...cacheIdentity,
@@ -3647,42 +3737,49 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
3647
3737
  finishReason: completed.result.finishReason ?? null,
3648
3738
  producedAt: responseProducedAt
3649
3739
  },
3650
- receipt: costReceiptFromLlm(completed.result)
3740
+ receipt: cacheReceiptInput(receipt)
3651
3741
  });
3742
+ modelProxy.assertExecutionComplete();
3652
3743
  return {
3653
3744
  ...completed,
3654
3745
  response,
3655
- producedAt: responseProducedAt
3746
+ producedAt: responseProducedAt,
3747
+ receipt
3656
3748
  };
3657
3749
  } catch (error) {
3658
- if (cacheIdentity) writePublicBenchmarkResponseCache(durability.responseCacheDir, {
3659
- kind: "agent-eval/public-benchmark-model-response",
3660
- ...cacheIdentity,
3661
- callId: providerCallId,
3662
- status: "failed",
3663
- error: publicBenchmarkError(error, [apiKey]),
3664
- receipt: receiptForProviderFailure(error, completedResult, model)
3665
- });
3750
+ const controlFailure = modelProxy.failures().find(isPaidCallControlError$1);
3751
+ if (controlFailure) throw controlFailure;
3752
+ const receipt = settledReceipt(costLedger, providerCallId);
3753
+ if (cacheIdentity) {
3754
+ if (receipt) writePublicBenchmarkResponseCache(durability.responseCacheDir, {
3755
+ kind: "agent-eval/public-benchmark-model-response",
3756
+ ...cacheIdentity,
3757
+ callId: providerCallId,
3758
+ status: "failed",
3759
+ error: publicBenchmarkError(error, []),
3760
+ receipt: cacheReceiptInput(receipt)
3761
+ });
3762
+ }
3666
3763
  throw error;
3667
3764
  }
3668
3765
  },
3669
- receipt: ({ result }) => costReceiptFromLlm(result),
3670
- receiptFromError: (error) => receiptForProviderFailure(error, completedResult, model)
3766
+ cleanup: async () => {
3767
+ await modelProxy?.close();
3768
+ }
3671
3769
  });
3672
- if (!paid.succeeded) throw paid.error;
3673
- const response = paid.value.response;
3770
+ const response = completed.response;
3674
3771
  rawPredictions = response.findings;
3675
3772
  rejectedBlocks = response.rejectedBlocks;
3676
- providerModel = paid.value.result.model;
3677
- producedAt = paid.value.producedAt;
3773
+ providerModel = completed.result.model;
3774
+ producedAt = completed.producedAt;
3678
3775
  modelMetadata = {
3679
3776
  ...modelMetadata,
3680
3777
  responseSource: "provider",
3681
3778
  report: response.report,
3682
- providerModel: paid.value.result.model,
3683
- providerDurationMs: paid.value.result.durationMs,
3684
- finishReason: paid.value.result.finishReason ?? null,
3685
- cost: costReceiptMetadata(paid.receipt)
3779
+ providerModel: completed.result.model,
3780
+ providerDurationMs: completed.result.durationMs,
3781
+ finishReason: completed.result.finishReason ?? null,
3782
+ cost: costReceiptMetadata(completed.receipt)
3686
3783
  };
3687
3784
  }
3688
3785
  const converted = await publicBenchmarkPredictionsToFindings({
@@ -3726,7 +3823,7 @@ function createPublicBenchmarkDirectRunner(dataset, config) {
3726
3823
  channel: "analyst",
3727
3824
  tags: costTags
3728
3825
  }),
3729
- error: publicBenchmarkError(error, [apiKey]),
3826
+ error: publicBenchmarkError(error, []),
3730
3827
  metadata: {
3731
3828
  ...modelMetadata,
3732
3829
  rawPredictions,
@@ -3760,18 +3857,48 @@ function assertCacheReceiptMatches(cached, receipt) {
3760
3857
  function isPaidCallControlError$1(error) {
3761
3858
  return error instanceof CostAccountingIncompleteError || error instanceof CostCallConflictError || error instanceof CostCeilingReachedError || error instanceof CostLedgerPersistenceError || error instanceof CostReceiptCaptureError || error instanceof CostReservationExceededError;
3762
3859
  }
3763
- function receiptForProviderFailure(error, completedResult, model) {
3764
- if (completedResult) return costReceiptFromLlm(completedResult);
3765
- if (error instanceof Error) {
3766
- const captured = costReceiptFromLlmError(error);
3767
- if (captured) return captured;
3768
- }
3860
+ function settledReceipt(costLedger, callId) {
3861
+ return costLedger.list().find((receipt) => receipt.callId === callId);
3862
+ }
3863
+ function requiredSettledReceipt(costLedger, callId) {
3864
+ const receipt = settledReceipt(costLedger, callId);
3865
+ if (!receipt) throw new CostAccountingIncompleteError(`caller-owned model call '${callId}' produced no cost receipt`);
3866
+ return receipt;
3867
+ }
3868
+ function cacheReceiptInput(receipt) {
3869
+ const usage = {
3870
+ model: receipt.model,
3871
+ inputTokens: receipt.inputTokens,
3872
+ outputTokens: receipt.outputTokens,
3873
+ ...receipt.reasoningTokens === void 0 ? {} : { reasoningTokens: receipt.reasoningTokens },
3874
+ ...receipt.cachedTokens === void 0 ? {} : { cachedTokens: receipt.cachedTokens },
3875
+ ...receipt.cacheWriteTokens === void 0 ? {} : { cacheWriteTokens: receipt.cacheWriteTokens },
3876
+ ...receipt.usageUnknown === void 0 ? {} : { usageUnknown: receipt.usageUnknown }
3877
+ };
3878
+ if (receipt.costUnknown) return {
3879
+ ...usage,
3880
+ costUnknown: true
3881
+ };
3882
+ if (receipt.actualCostUsd !== void 0) return {
3883
+ ...usage,
3884
+ actualCostUsd: receipt.actualCostUsd
3885
+ };
3886
+ if (receipt.estimatedCostUsd !== void 0) return {
3887
+ ...usage,
3888
+ estimatedCostUsd: receipt.estimatedCostUsd
3889
+ };
3890
+ if (receipt.pricing) return {
3891
+ ...usage,
3892
+ customTokenPricing: {
3893
+ inputUsdPerMillion: receipt.pricing.inputUsdPerThousand * 1e3,
3894
+ ...receipt.pricing.cachedInputUsdPerThousand === void 0 ? {} : { cachedInputUsdPerMillion: receipt.pricing.cachedInputUsdPerThousand * 1e3 },
3895
+ ...receipt.pricing.cacheWriteUsdPerThousand === void 0 ? {} : { cacheWriteUsdPerMillion: receipt.pricing.cacheWriteUsdPerThousand * 1e3 },
3896
+ outputUsdPerMillion: receipt.pricing.outputUsdPerThousand * 1e3
3897
+ }
3898
+ };
3769
3899
  return {
3770
- model,
3771
- inputTokens: 0,
3772
- outputTokens: 0,
3773
- costUnknown: true,
3774
- usageUnknown: true
3900
+ ...usage,
3901
+ estimatedCostUsd: receipt.costUsd
3775
3902
  };
3776
3903
  }
3777
3904
  function costReceiptMetadata(receipt) {
@@ -3793,6 +3920,14 @@ function costReceiptMetadata(receipt) {
3793
3920
  estimatedCostUsd: null
3794
3921
  };
3795
3922
  }
3923
+ function pricingForModel$1(model) {
3924
+ const pricing = resolveModelPricing(model);
3925
+ if (!pricing) throw new Error(`no pricing is configured for '${model}'; provide PublicAnalystBenchmarkModelConfig.pricing`);
3926
+ return {
3927
+ inputUsdPerMillion: pricing.input * 1e3,
3928
+ outputUsdPerMillion: pricing.output * 1e3
3929
+ };
3930
+ }
3796
3931
  const ModelSeveritySchema = z.enum([
3797
3932
  "critical",
3798
3933
  "high",
@@ -4112,13 +4247,24 @@ function createPublicBenchmarkRlmRunner(dataset, config) {
4112
4247
  };
4113
4248
  const pricing = config.pricing ?? pricingForModel(config.model);
4114
4249
  const engine = createDspyRlmTraceEngine({
4115
- baseUrl: config.baseUrl,
4116
- apiKey: config.apiKey,
4250
+ call: config.call,
4251
+ callRef: config.callRef,
4252
+ recordExecution: config.recordExecution,
4117
4253
  model: config.model,
4118
4254
  maxOutputTokens: config.maxOutputTokens,
4119
4255
  timeoutMs: config.timeoutMs,
4120
4256
  maxCostUsd: config.maxCostUsdPerAnalysis ?? 1,
4121
4257
  pricing,
4258
+ ...config.maxReasoningTokens === void 0 ? {} : { maxReasoningTokens: config.maxReasoningTokens },
4259
+ ...config.maxModelRequestBytes === void 0 ? {} : { maxModelRequestBytes: config.maxModelRequestBytes },
4260
+ ...config.maxModelResponseBytes === void 0 ? {} : { maxModelResponseBytes: config.maxModelResponseBytes },
4261
+ ...config.modelRequestTimeoutMs === void 0 ? {} : { modelRequestTimeoutMs: config.modelRequestTimeoutMs },
4262
+ ...config.dspyRlm?.maxModelRequests === void 0 ? {} : { maxModelRequests: config.dspyRlm.maxModelRequests },
4263
+ ...config.dspyRlm?.traceToolRequestBytes === void 0 && config.dspyRlm?.traceToolResponseBytes === void 0 ? {} : { traceToolLimits: {
4264
+ ...config.dspyRlm?.traceToolRequestBytes === void 0 ? {} : { maxRequestBytes: config.dspyRlm.traceToolRequestBytes },
4265
+ ...config.dspyRlm?.traceToolResponseBytes === void 0 ? {} : { maxResponseBytes: config.dspyRlm.traceToolResponseBytes }
4266
+ } },
4267
+ ...config.dspyRlm?.traceToolTimeoutMs === void 0 ? {} : { traceToolTimeoutMs: config.dspyRlm.traceToolTimeoutMs },
4122
4268
  ...config.dspyRlm?.runner ? { runner: config.dspyRlm.runner } : {}
4123
4269
  });
4124
4270
  const instructions = config.instructionsOverride?.text ?? publicBenchmarkRlmInstructions(dataset);
@@ -4329,7 +4475,7 @@ function createPublicBenchmarkRlmRunner(dataset, config) {
4329
4475
  return {
4330
4476
  findings: [],
4331
4477
  usage,
4332
- error: publicBenchmarkError(error, [config.apiKey]),
4478
+ error: publicBenchmarkError(error, []),
4333
4479
  metadata: {
4334
4480
  analysisMode: "recursive",
4335
4481
  engine: "dspy-rlm",
@@ -4787,7 +4933,7 @@ async function runAnalystBenchmarkCommand(argv, env = process.env, dependencies
4787
4933
  process.stdout.write(`${ANALYST_BENCHMARK_HELP}\n`);
4788
4934
  return 0;
4789
4935
  }
4790
- const config = parseCommandConfig(argv, env);
4936
+ const config = await parseCommandConfig(argv, env, dependencies);
4791
4937
  const outputLock = acquireSingleRunLock({ lockPath: await prepareOutputLockPath(config.outDir) });
4792
4938
  try {
4793
4939
  return await executeAnalystBenchmarkCommand(config, dependencies);
@@ -4870,6 +5016,7 @@ async function executeAnalystBenchmarkCommand(config, dependencies) {
4870
5016
  },
4871
5017
  metadata: {
4872
5018
  model: config.model.model,
5019
+ modelOwnerCallRef: config.model.callRef,
4873
5020
  rlmSamples: config.rlmSamples,
4874
5021
  outputAdapter: config.dataset === "agentrx" ? "agentrx-taxonomy-and-root-step" : "codetracebench-incorrect-block",
4875
5022
  caseSelection: prepared.selection.method,
@@ -4921,8 +5068,16 @@ async function executeAnalystBenchmarkCommand(config, dependencies) {
4921
5068
  concurrency: config.concurrency,
4922
5069
  rlmSamples: config.rlmSamples,
4923
5070
  model: config.model.model,
4924
- maxOutputTokens: config.model.maxOutputTokens,
4925
- timeoutMs: config.model.timeoutMs,
5071
+ modelOwnerCallRef: manifest.identity.config.model.ownerCallRef,
5072
+ maxOutputTokens: manifest.identity.config.model.maxOutputTokens,
5073
+ maxReasoningTokens: manifest.identity.config.model.maxReasoningTokens,
5074
+ maxModelRequestBytes: manifest.identity.config.model.maxRequestBytes,
5075
+ maxModelResponseBytes: manifest.identity.config.model.maxResponseBytes,
5076
+ modelRequestTimeoutMs: manifest.identity.config.model.requestTimeoutMs,
5077
+ timeoutMs: manifest.identity.config.model.timeoutMs,
5078
+ pricing: manifest.identity.config.model.pricing,
5079
+ recursiveLimits: manifest.identity.config.model.recursiveLimits,
5080
+ processLimits: manifest.identity.config.model.processLimits,
4926
5081
  maxCostUsd: config.maxCostUsd,
4927
5082
  maxArtifactBytes: config.maxArtifactBytes,
4928
5083
  analystProtocolSha256: effectiveAnalystProtocolSha256(config.dataset, config.model.instructionsOverride),
@@ -4989,16 +5144,15 @@ Run the recursive DSPy trace analyst against public AgentRx or CodeTraceBench la
4989
5144
  Required:
4990
5145
  --dataset agentrx|codetracebench
4991
5146
  --analyst dspy-rlm|direct Scored analyst. Default: dspy-rlm.
4992
- 'direct' is the retired one-shot runner that
4993
- produced the published evidence.
5147
+ 'direct' is the one-shot comparison arm.
4994
5148
  --labels <dataset.json|dataset.jsonl>
4995
5149
  --trace-dir <one-trace-per-file OTLP JSONL directory>
4996
5150
  --artifact-dir <extracted artifact root> Required for CodeTraceBench
4997
5151
  --out <new output directory>
4998
5152
  --revision <full 40- or 64-character hex digest>
4999
5153
  --split <dataset split>
5000
- --base-url <OpenAI-compatible /v1 URL>
5001
- --api-key-env <environment variable containing the bearer>
5154
+ --model-owner-module <module> Module exporting createModelExecutionOwner;
5155
+ the owner keeps provider credentials and policy
5002
5156
  --model <provider model id>
5003
5157
  --limit <positive case count>
5004
5158
 
@@ -5016,6 +5170,22 @@ Controls:
5016
5170
  protocol to the override text, and
5017
5171
  result.json records instructionsOverrideSha256.
5018
5172
  --max-output-tokens <positive> Model output limit per call. Default: 16384
5173
+ --max-reasoning-tokens <integer> Reasoning-token limit per call. Default: 65536
5174
+ --max-model-requests <positive> Caller-owned model calls per analysis.
5175
+ Default: max iterations + model calls + 1
5176
+ --max-model-request-bytes <positive> Default: 16777216
5177
+ --max-model-response-bytes <positive> Default: 4194304
5178
+ --model-request-timeout-ms <positive> Default: --timeout-ms
5179
+ --max-iterations <positive> Recursive iterations per analysis. Default: 14
5180
+ --max-llm-calls <positive> DSPy model calls per analysis. Default: 8
5181
+ --max-tool-calls <positive> Trace-tool calls per analysis. Default: 80
5182
+ --max-analysis-output-chars <positive> Default: 8000
5183
+ --trace-tool-request-bytes <positive> Default: 1000000
5184
+ --trace-tool-response-bytes <positive> Default: 4000000
5185
+ --trace-tool-timeout-ms <positive> Default: 60000
5186
+ --max-process-input-bytes <positive> Default: 67108864
5187
+ --max-process-result-bytes <positive> Default: 4194304
5188
+ --max-process-output-chars <positive> Default: 64000
5019
5189
  --python <executable> Python with agent-eval-rpc[dspy]. Default: python
5020
5190
  --timeout-ms <positive> Model analyst deadline per case. Default: 300000
5021
5191
  --max-cost-usd <positive> Run-wide spend limit. Default: 5
@@ -5025,20 +5195,15 @@ Writes result.json with every observation, metric, usage field, error, compariso
5025
5195
  input digest, artifact digest, case distribution, selected case id, and explicit
5026
5196
  unknown cost. Limited deterministic-hash subsets are marked non-representative.
5027
5197
  Completed observations are fsynced to observations.jsonl. Shareable output is in
5028
- result.json and report.md. Machine-local paths, endpoint, and command are isolated
5029
- in run.local.json.
5030
- The key is read from the named environment variable and is never written.`;
5031
- function parseCommandConfig(argv, env) {
5198
+ result.json and report.md. Machine-local paths, execution-owner module, and command
5199
+ are isolated in run.local.json. Provider credentials never enter this command.`;
5200
+ async function parseCommandConfig(argv, env, dependencies) {
5032
5201
  const flags = parseFlags(argv);
5033
5202
  assertKnownFlags(flags);
5034
5203
  const dataset = requiredFlag(flags, "dataset");
5035
5204
  if (dataset !== "agentrx" && dataset !== "codetracebench") throw new Error("--dataset must be 'agentrx' or 'codetracebench'");
5036
5205
  const artifactDir = flags.get("artifact-dir")?.trim();
5037
5206
  if (dataset === "codetracebench" && !artifactDir) throw new Error("--artifact-dir is required for CodeTraceBench");
5038
- const apiKeyEnv = requiredFlag(flags, "api-key-env");
5039
- if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(apiKeyEnv)) throw new Error("--api-key-env must be a valid environment variable name");
5040
- const apiKey = env[apiKeyEnv]?.trim();
5041
- if (!apiKey) throw new Error(`--api-key-env points to an empty or missing variable: ${apiKeyEnv}`);
5042
5207
  const maxCostUsd = positiveFiniteFlag(flags, "max-cost-usd", 5);
5043
5208
  const python = flags.get("python")?.trim();
5044
5209
  const analyst = flags.get("analyst")?.trim() ?? "dspy-rlm";
@@ -5049,6 +5214,16 @@ function parseCommandConfig(argv, env) {
5049
5214
  if (instructionsFile && analyst !== "dspy-rlm") throw new Error("--instructions-file requires --analyst dspy-rlm");
5050
5215
  const instructionsOverride = instructionsFile ? readAnalystInstructionsOverride(instructionsFile) : void 0;
5051
5216
  if (rlmSamples > 1 && dataset !== "codetracebench") throw new Error("--rlm-samples above 1 requires --dataset codetracebench; step-level consensus is defined on its block grammar");
5217
+ const model = requiredFlag(flags, "model");
5218
+ const modelOwnerModule = requiredFlag(flags, "model-owner-module");
5219
+ const owner = await (dependencies.loadModelExecutionOwner ?? loadModelExecutionOwner)(modelOwnerModule, {
5220
+ model,
5221
+ environment: Object.freeze({ ...env })
5222
+ });
5223
+ assertModelExecutionOwner(owner);
5224
+ const pricing = owner.pricing ?? benchmarkModelPricing(model);
5225
+ const maxOutputTokens = positiveFlag(flags, "max-output-tokens", 16384);
5226
+ const timeoutMs = positiveFlag(flags, "timeout-ms", 3e5);
5052
5227
  return {
5053
5228
  dataset,
5054
5229
  analyst,
@@ -5059,15 +5234,36 @@ function parseCommandConfig(argv, env) {
5059
5234
  revision: immutableRevision(requiredFlag(flags, "revision")),
5060
5235
  split: requiredFlag(flags, "split"),
5061
5236
  model: {
5062
- baseUrl: openAiCompatibleBaseUrl(requiredFlag(flags, "base-url")),
5063
- apiKey,
5064
- model: requiredFlag(flags, "model"),
5065
- maxOutputTokens: positiveFlag(flags, "max-output-tokens", 16384),
5066
- timeoutMs: positiveFlag(flags, "timeout-ms", 3e5),
5237
+ call: owner.call,
5238
+ callRef: owner.callRef,
5239
+ recordExecution: owner.recordExecution,
5240
+ model,
5241
+ maxOutputTokens,
5242
+ timeoutMs,
5243
+ maxReasoningTokens: nonNegativeFlag(flags, "max-reasoning-tokens", maxOutputTokens * 4),
5244
+ maxModelRequestBytes: positiveFlag(flags, "max-model-request-bytes", 16 * 1024 * 1024),
5245
+ maxModelResponseBytes: positiveFlag(flags, "max-model-response-bytes", 4 * 1024 * 1024),
5246
+ modelRequestTimeoutMs: positiveFlag(flags, "model-request-timeout-ms", timeoutMs),
5247
+ pricing,
5067
5248
  maxCostUsdPerAnalysis: maxCostUsd,
5068
5249
  ...instructionsOverride ? { instructionsOverride } : {},
5069
5250
  dspyRlm: {
5070
- ...python ? { runner: { command: python } } : {},
5251
+ runner: {
5252
+ ...python ? { command: python } : {},
5253
+ limits: {
5254
+ maxInputBytes: positiveFlag(flags, "max-process-input-bytes", 64 * 1024 * 1024),
5255
+ maxResultBytes: positiveFlag(flags, "max-process-result-bytes", 4 * 1024 * 1024),
5256
+ maxOutputChars: positiveFlag(flags, "max-process-output-chars", 64e3)
5257
+ }
5258
+ },
5259
+ maxIterations: positiveFlag(flags, "max-iterations", 14),
5260
+ maxLlmCalls: positiveFlag(flags, "max-llm-calls", 8),
5261
+ maxToolCalls: positiveFlag(flags, "max-tool-calls", 80),
5262
+ maxOutputChars: positiveFlag(flags, "max-analysis-output-chars", 8e3),
5263
+ ...flags.has("max-model-requests") ? { maxModelRequests: positiveFlag(flags, "max-model-requests") } : {},
5264
+ traceToolRequestBytes: positiveFlag(flags, "trace-tool-request-bytes", 1e6),
5265
+ traceToolResponseBytes: positiveFlag(flags, "trace-tool-response-bytes", 4e6),
5266
+ traceToolTimeoutMs: positiveFlag(flags, "trace-tool-timeout-ms", 6e4),
5071
5267
  samples: rlmSamples
5072
5268
  }
5073
5269
  },
@@ -5078,7 +5274,7 @@ function parseCommandConfig(argv, env) {
5078
5274
  rlmSamples,
5079
5275
  maxCostUsd,
5080
5276
  maxArtifactBytes: positiveFlag(flags, "max-artifact-bytes", DEFAULT_MAX_VERIFICATION_ARTIFACT_BYTES),
5081
- apiKeyEnv,
5277
+ modelOwnerModule,
5082
5278
  command: `agent-eval analyst-benchmark ${argv.filter((argument) => argument !== "--resume").map(shellQuote).join(" ")}`,
5083
5279
  resume: flags.has("resume")
5084
5280
  };
@@ -5114,8 +5310,7 @@ const KNOWN_FLAGS = /* @__PURE__ */ new Set([
5114
5310
  "out",
5115
5311
  "revision",
5116
5312
  "split",
5117
- "base-url",
5118
- "api-key-env",
5313
+ "model-owner-module",
5119
5314
  "model",
5120
5315
  "limit",
5121
5316
  "seed",
@@ -5124,6 +5319,21 @@ const KNOWN_FLAGS = /* @__PURE__ */ new Set([
5124
5319
  "rlm-samples",
5125
5320
  "instructions-file",
5126
5321
  "max-output-tokens",
5322
+ "max-reasoning-tokens",
5323
+ "max-model-requests",
5324
+ "max-model-request-bytes",
5325
+ "max-model-response-bytes",
5326
+ "model-request-timeout-ms",
5327
+ "max-iterations",
5328
+ "max-llm-calls",
5329
+ "max-tool-calls",
5330
+ "max-analysis-output-chars",
5331
+ "trace-tool-request-bytes",
5332
+ "trace-tool-response-bytes",
5333
+ "trace-tool-timeout-ms",
5334
+ "max-process-input-bytes",
5335
+ "max-process-result-bytes",
5336
+ "max-process-output-chars",
5127
5337
  "python",
5128
5338
  "timeout-ms",
5129
5339
  "max-cost-usd",
@@ -5153,6 +5363,13 @@ function integerFlag(flags, name, defaultValue) {
5153
5363
  if (!Number.isSafeInteger(value)) throw new Error(`--${name} must be a safe integer`);
5154
5364
  return value;
5155
5365
  }
5366
+ function nonNegativeFlag(flags, name, defaultValue) {
5367
+ const raw = flags.get(name);
5368
+ if (raw === void 0) return defaultValue;
5369
+ const value = Number(raw);
5370
+ if (!Number.isSafeInteger(value) || value < 0) throw new Error(`--${name} must be a non-negative safe integer`);
5371
+ return value;
5372
+ }
5156
5373
  function positiveFiniteFlag(flags, name, defaultValue) {
5157
5374
  const raw = flags.get(name);
5158
5375
  if (raw === void 0) return defaultValue;
@@ -5160,20 +5377,24 @@ function positiveFiniteFlag(flags, name, defaultValue) {
5160
5377
  if (!Number.isFinite(value) || value <= 0) throw new Error(`--${name} must be a positive finite number`);
5161
5378
  return value;
5162
5379
  }
5163
- function openAiCompatibleBaseUrl(value) {
5164
- let parsed;
5165
- try {
5166
- parsed = new URL(value);
5167
- } catch {
5168
- throw new Error("--base-url must be an absolute HTTP or HTTPS URL");
5169
- }
5170
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || parsed.username || parsed.password || parsed.search || parsed.hash) throw new Error("--base-url must use HTTP or HTTPS without credentials, query, or fragment");
5171
- if (parsed.protocol === "http:" && !isLoopbackHost(parsed.hostname)) throw new Error("--base-url must use HTTPS unless the endpoint is on the local machine");
5172
- return value;
5380
+ async function loadModelExecutionOwner(moduleRef, context) {
5381
+ const imported = await (moduleRef.startsWith(".") || moduleRef.startsWith("/") ? import(pathToFileURL(resolve(moduleRef)).href) : import(moduleRef));
5382
+ if (typeof imported.createModelExecutionOwner !== "function") throw new Error(`${moduleRef} must export createModelExecutionOwner({ model, environment })`);
5383
+ return imported.createModelExecutionOwner(context);
5384
+ }
5385
+ function assertModelExecutionOwner(value) {
5386
+ if (!value || typeof value !== "object") throw new Error("createModelExecutionOwner must return an object");
5387
+ if (typeof value.call !== "function") throw new Error("model execution owner call must be a function");
5388
+ if (typeof value.callRef !== "string" || !value.callRef.trim() || value.callRef !== value.callRef.trim()) throw new Error("model execution owner callRef must be trimmed and non-empty");
5389
+ if (typeof value.recordExecution !== "function") throw new Error("model execution owner recordExecution must be a function");
5173
5390
  }
5174
- function isLoopbackHost(hostname) {
5175
- const normalized = hostname.toLowerCase();
5176
- return normalized === "localhost" || normalized === "[::1]" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
5391
+ function benchmarkModelPricing(model) {
5392
+ const pricing = resolveModelPricing(model);
5393
+ if (!pricing) throw new Error(`model execution owner must supply pricing for uncatalogued model '${model}'`);
5394
+ return {
5395
+ inputUsdPerMillion: pricing.input * 1e3,
5396
+ outputUsdPerMillion: pricing.output * 1e3
5397
+ };
5177
5398
  }
5178
5399
  function immutableRevision(value) {
5179
5400
  if (!/^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(value)) throw new Error("--revision must be a full 40- or 64-character hexadecimal digest");
@@ -5248,4 +5469,4 @@ function shellQuote(value) {
5248
5469
  //#endregion
5249
5470
  export { normalizeAgentRxCategory as $, parseVerificationOutcome as A, analystBenchmarkDependencyLockDigest as B, MAX_INCORRECT_BLOCK_STEPS as C, DEFAULT_MAX_VERIFICATION_ARTIFACT_BYTES as D, publicBenchmarkSystemPrompt as E, ANALYST_BENCHMARK_EVIDENCE_IMPLEMENTATION_SHA256 as F, ANALYST_BENCHMARK_OBSERVATIONS_FILE as G, ANALYST_BENCHMARK_COST_LEDGER_FILE as H, ANALYST_BENCHMARK_EVIDENCE_PACKAGE_VERSION as I, summarizeAgentRxCalibration as J, AGENT_RX_UPSTREAM_REVISION as K, ANALYST_BENCHMARK_IMPLEMENTATION_DIGEST_ALGORITHM as L, ANALYST_BENCHMARK_DEPENDENCY_LOCK_FILES as M, ANALYST_BENCHMARK_DEPENDENCY_LOCK_SHA256 as N, appendVerificationArtifactsToOtlp as O, ANALYST_BENCHMARK_EVIDENCE_DEPENDENCY_LOCK_SHA256 as P, agentRxPredictionsToFindings as Q, ANALYST_BENCHMARK_IMPLEMENTATION_FILES as R, MAX_INCORRECT_BLOCKS as S, publicBenchmarkRlmInstructions as T, ANALYST_BENCHMARK_LOCAL_RECEIPT_FILE as U, analystBenchmarkImplementationDigest as V, ANALYST_BENCHMARK_MANIFEST_FILE as W, codeTracerPredictionsToFindings as X, codeTraceBenchCase as Y, agentRxBenchmarkCase as Z, compareAnalystRunners as _, preparePublicAnalystBenchmark as a, readAnalystInstructionsOverride as b, selectPublicBenchmarkRows as c, adaptPublicBenchmarkFindings as d, roundAgentRxStep as et, emptyPublicBenchmarkRunner as f, summarizeCodeTraceCalibration as g, renderCodeTraceCalibrationMarkdown as h, loadPublicBenchmarkRows as i, ANALYST_BENCHMARK_DEPENDENCY_LOCK_DIGEST_ALGORITHM as j, loadCodeTraceVerificationArtifacts as k, createPublicBenchmarkRlmRunner as l, readAnalystBenchmarkArtifact as m, runAnalystBenchmarkCommand as n, publicBenchmarkDistributions as o, expandCodeTraceFailureBlocks as p, renderAgentRxCalibrationMarkdown as q, renderAnalystBenchmarkMarkdown as r, publicBenchmarkSelectionReport as s, ANALYST_BENCHMARK_HELP as t, normalizeBenchmarkLabel as tt, createPublicBenchmarkDirectRunner as u, analystInstructionsOverrideFromText as v, publicBenchmarkProtocolSha256 as w, CODE_TRACE_BENCH_ANALYST_PROMPT as x, effectiveAnalystProtocolSha256 as y, ANALYST_BENCHMARK_IMPLEMENTATION_SHA256 as z };
5250
5471
 
5251
- //# sourceMappingURL=benchmark-command-4c7N_rlw.js.map
5472
+ //# sourceMappingURL=benchmark-command-95Zqd1e8.js.map