@tangle-network/agent-eval 0.143.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.
- package/CHANGELOG.md +34 -0
- package/README.md +21 -8
- package/dist/analyst/index.d.ts +82 -17
- package/dist/analyst/index.d.ts.map +1 -1
- package/dist/analyst/index.js +4 -4
- package/dist/{benchmark-command-CSddvlq7.js → benchmark-command-95Zqd1e8.js} +333 -111
- package/dist/benchmark-command-95Zqd1e8.js.map +1 -0
- package/dist/benchmarks/index.d.ts +1 -1
- package/dist/benchmarks/index.js +1 -1
- package/dist/{benchmarks-Dg0B56tK.js → benchmarks-CRT4ScEA.js} +4 -4
- package/dist/{benchmarks-Dg0B56tK.js.map → benchmarks-CRT4ScEA.js.map} +1 -1
- package/dist/campaign/index.d.ts +4 -3
- package/dist/campaign/index.js +4 -4
- package/dist/{campaign-C7ZGiZYG.js → campaign-CefP3fPS.js} +12 -10
- package/dist/campaign-CefP3fPS.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.js +3 -3
- package/dist/{default-registry-BupFSXSN.js → default-registry-SOyHB6qG.js} +3 -3
- package/dist/{default-registry-BupFSXSN.js.map → default-registry-SOyHB6qG.js.map} +1 -1
- package/dist/{dspy-rlm-engine-CJ4sN8Wx.js → dspy-rlm-engine-BR7TtB0o.js} +69 -31
- package/dist/dspy-rlm-engine-BR7TtB0o.js.map +1 -0
- package/dist/{eval-campaign-YdkpWWoT.js → eval-campaign-lI7wB9DH.js} +2 -2
- package/dist/{eval-campaign-YdkpWWoT.js.map → eval-campaign-lI7wB9DH.js.map} +1 -1
- package/dist/external-optimizer-contracts-CdmX2K2S.d.ts +165 -0
- package/dist/external-optimizer-contracts-CdmX2K2S.d.ts.map +1 -0
- package/dist/{index-BKjcUH13.d.ts → index-BZUe-ODI.d.ts} +41 -5
- package/dist/index-BZUe-ODI.d.ts.map +1 -0
- package/dist/{index-DY83M1WL.d.ts → index-BrpxwELi.d.ts} +9 -8
- package/dist/{index-DY83M1WL.d.ts.map → index-BrpxwELi.d.ts.map} +1 -1
- package/dist/{index-CaOjqCli.d.ts → index-DRI1DU5z.d.ts} +3 -3
- package/dist/{index-CaOjqCli.d.ts.map → index-DRI1DU5z.d.ts.map} +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +12 -11
- package/dist/index.js.map +1 -1
- package/dist/{integrity-hruKe6oe.js → integrity-DY6tIbl0.js} +48 -18
- package/dist/integrity-DY6tIbl0.js.map +1 -0
- package/dist/{llm-client-B3WXSH5Y.js → llm-client-D3EoChAU.js} +7 -7
- package/dist/llm-client-D3EoChAU.js.map +1 -0
- package/dist/openapi.json +1 -1
- package/dist/rl.js +1 -1
- package/dist/{semantic-concept-judge-DJQtFr95.js → semantic-concept-judge-l8Lb3Kqz.js} +2 -2
- package/dist/{semantic-concept-judge-DJQtFr95.js.map → semantic-concept-judge-l8Lb3Kqz.js.map} +1 -1
- package/dist/{server-Cu4M3NSO.js → server-Df00sdwz.js} +3 -3
- package/dist/{server-Cu4M3NSO.js.map → server-Df00sdwz.js.map} +1 -1
- package/dist/single-run-lock-B-cFnnNn.js +1799 -0
- package/dist/single-run-lock-B-cFnnNn.js.map +1 -0
- package/dist/{skill-usage-CRqaHi0R.d.ts → skill-usage-3vUWdZ9n.d.ts} +24 -5
- package/dist/skill-usage-3vUWdZ9n.d.ts.map +1 -0
- package/dist/{skillopt-optimization-method-Di8Xkalt.js → skillopt-optimization-method-DA5mJmFE.js} +225 -347
- package/dist/skillopt-optimization-method-DA5mJmFE.js.map +1 -0
- package/dist/{skillopt-optimization-method-CwRvi-rL.d.ts → skillopt-optimization-method-DNniakI5.d.ts} +47 -9
- package/dist/skillopt-optimization-method-DNniakI5.d.ts.map +1 -0
- package/dist/supervisor-run/index.d.ts +3 -3
- package/dist/supervisor-run/index.js +3 -3
- package/dist/{supervisor-run-BEns49Nx.js → supervisor-run-DiyQVczd.js} +301 -25
- package/dist/supervisor-run-DiyQVczd.js.map +1 -0
- package/dist/types-BjMFz88h.d.ts.map +1 -1
- package/dist/{types-Dea6tiVI.d.ts → types-yLK8gXE9.d.ts} +15 -2
- package/dist/types-yLK8gXE9.d.ts.map +1 -0
- package/dist/wire/index.js +1 -1
- package/docs/campaign-proposers.md +11 -7
- package/docs/trace-analysis.md +43 -32
- package/package.json +1 -1
- package/dist/benchmark-command-CSddvlq7.js.map +0 -1
- package/dist/campaign-C7ZGiZYG.js.map +0 -1
- package/dist/dspy-rlm-engine-CJ4sN8Wx.js.map +0 -1
- package/dist/external-optimizer-contracts-nb7c_WAR.d.ts +0 -42
- package/dist/external-optimizer-contracts-nb7c_WAR.d.ts.map +0 -1
- package/dist/index-BKjcUH13.d.ts.map +0 -1
- package/dist/integrity-hruKe6oe.js.map +0 -1
- package/dist/llm-client-B3WXSH5Y.js.map +0 -1
- package/dist/single-run-lock-Do-8vBIJ.js +0 -1049
- package/dist/single-run-lock-Do-8vBIJ.js.map +0 -1
- package/dist/skill-usage-CRqaHi0R.d.ts.map +0 -1
- package/dist/skillopt-optimization-method-CwRvi-rL.d.ts.map +0 -1
- package/dist/skillopt-optimization-method-Di8Xkalt.js.map +0 -1
- package/dist/supervisor-run-BEns49Nx.js.map +0 -1
- package/dist/types-Dea6tiVI.d.ts.map +0 -1
package/dist/{skillopt-optimization-method-Di8Xkalt.js → skillopt-optimization-method-DA5mJmFE.js}
RENAMED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { c as ValidationError, i as JudgeError, t as AgentEvalError } from "./errors-D-LKuDhb.js";
|
|
2
2
|
import { i as CostLedger, t as CostAccountingIncompleteError } from "./cost-ledger-DMFxsLKr.js";
|
|
3
|
-
import { f as maximumChargeForLlmRequest, l as costReceiptFromLlm, m as stripFencedJson, u as costReceiptFromLlmError } from "./llm-client-
|
|
3
|
+
import { f as maximumChargeForLlmRequest, l as costReceiptFromLlm, m as stripFencedJson, u as costReceiptFromLlmError } from "./llm-client-D3EoChAU.js";
|
|
4
4
|
import { a as clamp01, o as combineAbortSignals, t as assertProposalFindings } from "./proposal-findings-2GIUo1et.js";
|
|
5
|
-
import {
|
|
5
|
+
import { A as removeCredentialEnvironment, D as isCandidateText, E as assertNoCredentialValues, M as resolveExternalOptimizerProcessLimits, N as safePathComponent, O as isExternalTextCandidate, T as assertJsonValue, d as closeExternalOptimizerResources, f as runWithCleanup, j as resolveExternalOptimizerCallbackLimits, k as isRecord, l as startExternalOptimizerCallback, n as createRunCostLedger, p as startExternalOptimizerModelProxy, r as fsCampaignStorage, t as acquireSingleRunLock, u as runExternalOptimizerProcess, v as canonicalJson, w as assertExternalOptimizerModelBudget, y as contentHash } from "./single-run-lock-B-cFnnNn.js";
|
|
6
6
|
import { p as mapConcurrent } from "./ledger-core-Dxz0Rkwa.js";
|
|
7
7
|
import { E as pairedBootstrap, H as weightedComposite, M as pairedRiskDifferenceScore, N as pairedSignTest, O as pairedDeltaTieFraction, T as pairedBinaryScale, d as confidenceInterval, j as pairedRiskDifferenceExact } from "./statistics-ByxzSiOM.js";
|
|
8
8
|
import { t as DEFAULT_REDACTION_RULES } from "./redact-7Aq1ukl-.js";
|
|
9
9
|
import { a as campaignCellCostProvenance, o as campaignCellExecutionEvidence, t as detectRewardHacking, u as projectCampaignCellQuality } from "./reward-hacking-DjTi9HLb.js";
|
|
10
10
|
import { z } from "zod";
|
|
11
|
-
import {
|
|
11
|
+
import { writeFileSync } from "node:fs";
|
|
12
12
|
import { basename, isAbsolute, join } from "node:path";
|
|
13
13
|
import { createHash, randomBytes } from "node:crypto";
|
|
14
|
-
import { createServer } from "node:http";
|
|
15
14
|
import { execSync } from "node:child_process";
|
|
16
15
|
import { mkdir } from "node:fs/promises";
|
|
17
16
|
import { homedir, tmpdir } from "node:os";
|
|
@@ -656,160 +655,6 @@ function paretoFrontierWithCrowding(candidates, objectives) {
|
|
|
656
655
|
return crowdingDistance(frontier, objectives).sort((a, b) => b.distance - a.distance);
|
|
657
656
|
}
|
|
658
657
|
//#endregion
|
|
659
|
-
//#region src/verdict-cache.ts
|
|
660
|
-
/**
|
|
661
|
-
* Content-addressed judge-verdict caching.
|
|
662
|
-
*
|
|
663
|
-
* LAW: cache JUDGE VERDICTS only — judging the same artifact with the same
|
|
664
|
-
* judge+rubric is pure. NEVER cache agent rollouts. (A router that cached
|
|
665
|
-
* identical fanout prompts silently destroyed best-of-N diversity; rollout
|
|
666
|
-
* caching reintroduces that failure class. Judging has no diversity to
|
|
667
|
-
* destroy — same artifact + same rubric ⇒ same verdict is the desired
|
|
668
|
-
* property, not a bug.)
|
|
669
|
-
*
|
|
670
|
-
* The cache key is a sha-256 over the canonical JSON of everything that can
|
|
671
|
-
* change a verdict: the artifact content, the scenario id, the judge name,
|
|
672
|
-
* the full dimension list (key + description — the description IS the rubric
|
|
673
|
-
* text shown to the judge), and a caller-supplied `judgeVersion`.
|
|
674
|
-
* `judgeVersion` is REQUIRED: a judge whose prompt/model/ensemble changes
|
|
675
|
-
* without a version bump would otherwise silently serve stale verdicts.
|
|
676
|
-
*
|
|
677
|
-
* Strict canonicalization (`canonicalJson`) throws on undefined / function /
|
|
678
|
-
* symbol / non-finite numbers — an artifact that cannot be unambiguously
|
|
679
|
-
* serialized cannot be content-addressed, and coercing it would let two
|
|
680
|
-
* different artifacts collide on one key.
|
|
681
|
-
*/
|
|
682
|
-
function canonicalizeAt(value, path) {
|
|
683
|
-
if (value === null) return "null";
|
|
684
|
-
switch (typeof value) {
|
|
685
|
-
case "boolean": return value ? "true" : "false";
|
|
686
|
-
case "number":
|
|
687
|
-
if (!Number.isFinite(value)) throw new Error(`canonicalJson: non-finite number (${value}) at ${path} — ambiguity is an error, not a coercion`);
|
|
688
|
-
return JSON.stringify(value);
|
|
689
|
-
case "string": return JSON.stringify(value);
|
|
690
|
-
case "undefined":
|
|
691
|
-
case "function":
|
|
692
|
-
case "symbol": throw new Error(`canonicalJson: ${typeof value} at ${path} — ambiguity is an error, not a coercion`);
|
|
693
|
-
case "bigint": throw new Error(`canonicalJson: bigint at ${path} — not representable in JSON`);
|
|
694
|
-
case "object": break;
|
|
695
|
-
}
|
|
696
|
-
const obj = value;
|
|
697
|
-
if (typeof obj.toJSON === "function") return canonicalizeAt(obj.toJSON(), path);
|
|
698
|
-
if (Array.isArray(obj)) return `[${obj.map((item, i) => canonicalizeAt(item, `${path}[${i}]`)).join(",")}]`;
|
|
699
|
-
if (obj instanceof Map || obj instanceof Set) throw new Error(`canonicalJson: ${obj instanceof Map ? "Map" : "Set"} at ${path} — would serialize as '{}'; convert to a plain object/array first`);
|
|
700
|
-
return `{${Object.keys(obj).sort().map((k) => `${JSON.stringify(k)}:${canonicalizeAt(obj[k], `${path}.${k}`)}`).join(",")}}`;
|
|
701
|
-
}
|
|
702
|
-
/**
|
|
703
|
-
* Stable JSON stringify: object keys sorted recursively, so two semantically
|
|
704
|
-
* equal values produce byte-identical output regardless of key insertion
|
|
705
|
-
* order. Throws on undefined / function / symbol / NaN / ±Infinity / bigint /
|
|
706
|
-
* Map / Set — anything JSON.stringify would coerce or drop silently.
|
|
707
|
-
*
|
|
708
|
-
* Distinct from `pre-registration.ts`'s `canonicalize`/`hashJson`, which are
|
|
709
|
-
* permissive (coercion allowed) and async (web-crypto). Use THIS pair when a
|
|
710
|
-
* hash collision or silent coercion would corrupt a cache key or attestation.
|
|
711
|
-
*/
|
|
712
|
-
function canonicalJson(value) {
|
|
713
|
-
return canonicalizeAt(value, "$");
|
|
714
|
-
}
|
|
715
|
-
/** Hex sha-256 over `canonicalJson(value)`. The content address used by the
|
|
716
|
-
* verdict cache and report attestation. */
|
|
717
|
-
function contentHash(value) {
|
|
718
|
-
return createHash("sha256").update(canonicalJson(value)).digest("hex");
|
|
719
|
-
}
|
|
720
|
-
/** Process-local Map-backed store. */
|
|
721
|
-
function inMemoryVerdictCache() {
|
|
722
|
-
const entries = /* @__PURE__ */ new Map();
|
|
723
|
-
return {
|
|
724
|
-
get: (key) => entries.get(key),
|
|
725
|
-
set: (key, score) => {
|
|
726
|
-
entries.set(key, score);
|
|
727
|
-
}
|
|
728
|
-
};
|
|
729
|
-
}
|
|
730
|
-
function parseCacheLine(line, path, lineNo) {
|
|
731
|
-
let parsed;
|
|
732
|
-
try {
|
|
733
|
-
parsed = JSON.parse(line);
|
|
734
|
-
} catch (err) {
|
|
735
|
-
throw new Error(`fileVerdictCache: corrupt JSONL at ${path}:${lineNo} — ${err instanceof Error ? err.message : String(err)}`);
|
|
736
|
-
}
|
|
737
|
-
const rec = parsed;
|
|
738
|
-
if (typeof rec !== "object" || rec === null || typeof rec.key !== "string" || typeof rec.score !== "object" || rec.score === null || typeof rec.score.composite !== "number" || typeof rec.score.dimensions !== "object") throw new Error(`fileVerdictCache: invalid record shape at ${path}:${lineNo} — expected {key, score:{dimensions, composite, notes}}`);
|
|
739
|
-
return rec;
|
|
740
|
-
}
|
|
741
|
-
/**
|
|
742
|
-
* JSONL-file-backed store: the full file is loaded into an in-memory index at
|
|
743
|
-
* construction; every `set` appends one line synchronously (durable before
|
|
744
|
-
* the verdict is returned). A corrupt or malformed line throws at load with
|
|
745
|
-
* file:line — a skipped line would silently re-judge (cost) or, worse, mask
|
|
746
|
-
* a half-written file that needs operator attention.
|
|
747
|
-
*/
|
|
748
|
-
function fileVerdictCache(path) {
|
|
749
|
-
const entries = /* @__PURE__ */ new Map();
|
|
750
|
-
if (existsSync(path)) {
|
|
751
|
-
const lines = readFileSync(path, "utf8").split("\n");
|
|
752
|
-
for (let i = 0; i < lines.length; i++) {
|
|
753
|
-
const line = lines[i];
|
|
754
|
-
if (line === void 0 || line.trim() === "") continue;
|
|
755
|
-
const rec = parseCacheLine(line, path, i + 1);
|
|
756
|
-
entries.set(rec.key, rec.score);
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
return {
|
|
760
|
-
get: (key) => entries.get(key),
|
|
761
|
-
set: (key, score) => {
|
|
762
|
-
appendFileSync(path, `${JSON.stringify({
|
|
763
|
-
key,
|
|
764
|
-
score
|
|
765
|
-
})}\n`, "utf8");
|
|
766
|
-
entries.set(key, score);
|
|
767
|
-
}
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
/**
|
|
771
|
-
* Wrap a `JudgeConfig` so repeat judgments of the same artifact are served
|
|
772
|
-
* from the store instead of re-invoking `score()`. The wrapper is generic
|
|
773
|
-
* over the judge's own type parameters and preserves `appliesTo` — it is a
|
|
774
|
-
* drop-in replacement anywhere a `JudgeConfig` is accepted.
|
|
775
|
-
*
|
|
776
|
-
* A judge that throws is NOT cached: the error propagates and the next
|
|
777
|
-
* attempt re-judges (caching a failure would pin a transient outage forever).
|
|
778
|
-
*/
|
|
779
|
-
function cachedJudge(judge, store, options) {
|
|
780
|
-
if (typeof options.judgeVersion !== "string" || options.judgeVersion.trim() === "") throw new Error("cachedJudge: judgeVersion is required and must be a non-empty string");
|
|
781
|
-
const stats = {
|
|
782
|
-
hits: 0,
|
|
783
|
-
misses: 0
|
|
784
|
-
};
|
|
785
|
-
const wrapped = {
|
|
786
|
-
name: judge.name,
|
|
787
|
-
dimensions: judge.dimensions,
|
|
788
|
-
judgeVersion: options.judgeVersion,
|
|
789
|
-
async score(input) {
|
|
790
|
-
const key = contentHash({
|
|
791
|
-
artifact: canonicalJson(input.artifact),
|
|
792
|
-
scenarioId: input.scenario.id,
|
|
793
|
-
judgeName: judge.name,
|
|
794
|
-
dimensions: judge.dimensions,
|
|
795
|
-
judgeVersion: options.judgeVersion
|
|
796
|
-
});
|
|
797
|
-
const cached = await store.get(key);
|
|
798
|
-
if (cached !== void 0) {
|
|
799
|
-
stats.hits += 1;
|
|
800
|
-
return cached;
|
|
801
|
-
}
|
|
802
|
-
const score = await judge.score(input);
|
|
803
|
-
await store.set(key, score);
|
|
804
|
-
stats.misses += 1;
|
|
805
|
-
return score;
|
|
806
|
-
},
|
|
807
|
-
stats: () => ({ ...stats })
|
|
808
|
-
};
|
|
809
|
-
if (judge.appliesTo) wrapped.appliesTo = judge.appliesTo;
|
|
810
|
-
return wrapped;
|
|
811
|
-
}
|
|
812
|
-
//#endregion
|
|
813
658
|
//#region src/llm-judge.ts
|
|
814
659
|
/**
|
|
815
660
|
* `llmJudge` — the single-LLM-call bridge that turns a rubric prompt into a
|
|
@@ -1803,135 +1648,6 @@ function designedCellIds(scenarios, reps) {
|
|
|
1803
1648
|
return ids;
|
|
1804
1649
|
}
|
|
1805
1650
|
//#endregion
|
|
1806
|
-
//#region src/campaign/external-optimizer-callback.ts
|
|
1807
|
-
const MAX_CALLBACK_BODY_BYTES = 1e6;
|
|
1808
|
-
async function startExternalOptimizerCallback(args) {
|
|
1809
|
-
assertCallbackConfig(args);
|
|
1810
|
-
args.signal?.throwIfAborted();
|
|
1811
|
-
let evaluations = 0;
|
|
1812
|
-
let accepting = true;
|
|
1813
|
-
let closePromise;
|
|
1814
|
-
const activeControllers = /* @__PURE__ */ new Set();
|
|
1815
|
-
const activeHandlers = /* @__PURE__ */ new Set();
|
|
1816
|
-
const server = createServer((request, response) => {
|
|
1817
|
-
if (!accepting) {
|
|
1818
|
-
sendJsonIfOpen(response, 503, { error: "external optimizer callback is closing" });
|
|
1819
|
-
return;
|
|
1820
|
-
}
|
|
1821
|
-
const controller = new AbortController();
|
|
1822
|
-
const abortRequest = () => {
|
|
1823
|
-
request.destroy();
|
|
1824
|
-
response.destroy();
|
|
1825
|
-
};
|
|
1826
|
-
activeControllers.add(controller);
|
|
1827
|
-
controller.signal.addEventListener("abort", abortRequest, { once: true });
|
|
1828
|
-
let handler;
|
|
1829
|
-
handler = handleCallback(request, response, controller.signal, args, () => {
|
|
1830
|
-
const accepted = args.acceptEvaluation ? args.acceptEvaluation() : evaluations + 1;
|
|
1831
|
-
if (accepted === void 0) return void 0;
|
|
1832
|
-
if (!Number.isSafeInteger(accepted) || accepted <= 0) throw new Error("external optimizer callback: invalid accepted evaluation count");
|
|
1833
|
-
if (accepted > args.maxEvaluations) return void 0;
|
|
1834
|
-
evaluations += 1;
|
|
1835
|
-
return accepted;
|
|
1836
|
-
}).finally(() => {
|
|
1837
|
-
controller.signal.removeEventListener("abort", abortRequest);
|
|
1838
|
-
activeControllers.delete(controller);
|
|
1839
|
-
activeHandlers.delete(handler);
|
|
1840
|
-
});
|
|
1841
|
-
activeHandlers.add(handler);
|
|
1842
|
-
handler.catch(() => void 0);
|
|
1843
|
-
});
|
|
1844
|
-
const port = await listenLocal(server);
|
|
1845
|
-
const close = () => {
|
|
1846
|
-
closePromise ??= closeCallbackServer();
|
|
1847
|
-
return closePromise;
|
|
1848
|
-
};
|
|
1849
|
-
const onAbort = () => {
|
|
1850
|
-
close().catch(() => void 0);
|
|
1851
|
-
};
|
|
1852
|
-
args.signal?.addEventListener("abort", onAbort, { once: true });
|
|
1853
|
-
if (args.signal?.aborted) onAbort();
|
|
1854
|
-
return {
|
|
1855
|
-
url: `http://127.0.0.1:${port}/evaluate`,
|
|
1856
|
-
token: args.token,
|
|
1857
|
-
evaluations: () => evaluations,
|
|
1858
|
-
close
|
|
1859
|
-
};
|
|
1860
|
-
async function closeCallbackServer() {
|
|
1861
|
-
args.signal?.removeEventListener("abort", onAbort);
|
|
1862
|
-
accepting = false;
|
|
1863
|
-
const closingServer = closeServer(server);
|
|
1864
|
-
server.closeIdleConnections?.();
|
|
1865
|
-
for (const controller of activeControllers) controller.abort();
|
|
1866
|
-
const [serverResult] = await Promise.allSettled([closingServer, waitForActiveHandlers(activeHandlers)]);
|
|
1867
|
-
if (activeControllers.size !== 0 || activeHandlers.size !== 0) throw new Error("external optimizer callback closed with active request work");
|
|
1868
|
-
if (serverResult?.status === "rejected") throw serverResult.reason;
|
|
1869
|
-
}
|
|
1870
|
-
}
|
|
1871
|
-
async function handleCallback(request, response, signal, args, nextEvaluation) {
|
|
1872
|
-
try {
|
|
1873
|
-
if (request.method !== "POST" || request.url !== "/evaluate") {
|
|
1874
|
-
sendJsonIfOpen(response, 404, { error: "not found" });
|
|
1875
|
-
return;
|
|
1876
|
-
}
|
|
1877
|
-
if (request.headers.authorization !== `Bearer ${args.token}`) {
|
|
1878
|
-
sendJsonIfOpen(response, 401, { error: "unauthorized" });
|
|
1879
|
-
return;
|
|
1880
|
-
}
|
|
1881
|
-
const body = await readJson(request);
|
|
1882
|
-
if (!isRecord(body) || !isExternalTextCandidate(body.candidate) || typeof body.exampleId !== "string") {
|
|
1883
|
-
sendJsonIfOpen(response, 400, { error: "candidate and exampleId are required strings" });
|
|
1884
|
-
return;
|
|
1885
|
-
}
|
|
1886
|
-
if (nextEvaluation() === void 0) {
|
|
1887
|
-
sendJsonIfOpen(response, 429, { error: "evaluation limit reached" });
|
|
1888
|
-
return;
|
|
1889
|
-
}
|
|
1890
|
-
sendJsonIfOpen(response, 200, await args.evaluate({
|
|
1891
|
-
candidate: body.candidate,
|
|
1892
|
-
exampleId: body.exampleId
|
|
1893
|
-
}, signal));
|
|
1894
|
-
} catch {
|
|
1895
|
-
sendJsonIfOpen(response, 500, { error: "evaluation failed" });
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
async function waitForActiveHandlers(activeHandlers) {
|
|
1899
|
-
while (activeHandlers.size > 0) await Promise.allSettled([...activeHandlers]);
|
|
1900
|
-
}
|
|
1901
|
-
function sendJsonIfOpen(response, status, body) {
|
|
1902
|
-
if (response.destroyed || response.writableEnded) return;
|
|
1903
|
-
sendJson(response, status, body);
|
|
1904
|
-
}
|
|
1905
|
-
function readJson(request) {
|
|
1906
|
-
return new Promise((resolvePromise, reject) => {
|
|
1907
|
-
let size = 0;
|
|
1908
|
-
const chunks = [];
|
|
1909
|
-
request.on("data", (chunk) => {
|
|
1910
|
-
size += chunk.length;
|
|
1911
|
-
if (size > MAX_CALLBACK_BODY_BYTES) {
|
|
1912
|
-
reject(/* @__PURE__ */ new Error("callback body too large"));
|
|
1913
|
-
request.destroy();
|
|
1914
|
-
return;
|
|
1915
|
-
}
|
|
1916
|
-
chunks.push(chunk);
|
|
1917
|
-
});
|
|
1918
|
-
request.on("error", reject);
|
|
1919
|
-
request.on("end", () => {
|
|
1920
|
-
try {
|
|
1921
|
-
resolvePromise(JSON.parse(Buffer.concat(chunks).toString("utf8")));
|
|
1922
|
-
} catch (error) {
|
|
1923
|
-
reject(error);
|
|
1924
|
-
}
|
|
1925
|
-
});
|
|
1926
|
-
});
|
|
1927
|
-
}
|
|
1928
|
-
function assertCallbackConfig(args) {
|
|
1929
|
-
if (typeof args.token !== "string" || !args.token.trim()) throw new Error("external optimizer callback: token must be non-empty");
|
|
1930
|
-
if (!Number.isSafeInteger(args.maxEvaluations) || args.maxEvaluations <= 0) throw new Error("external optimizer callback: maxEvaluations must be a positive safe integer");
|
|
1931
|
-
if (args.acceptEvaluation !== void 0 && typeof args.acceptEvaluation !== "function") throw new Error("external optimizer callback: acceptEvaluation must be a function");
|
|
1932
|
-
if (typeof args.evaluate !== "function") throw new Error("external optimizer callback: evaluate must be a function");
|
|
1933
|
-
}
|
|
1934
|
-
//#endregion
|
|
1935
1651
|
//#region src/campaign/external-optimizer-run-budget.ts
|
|
1936
1652
|
function externalOptimizerRunKey(input) {
|
|
1937
1653
|
if (!input.attemptId.trim() || input.attemptId.trim() !== input.attemptId) throw new Error("external optimizer attemptId must be trimmed and non-empty");
|
|
@@ -3492,7 +3208,7 @@ async function compareOptimizationMethods(opts) {
|
|
|
3492
3208
|
throw error;
|
|
3493
3209
|
}
|
|
3494
3210
|
});
|
|
3495
|
-
assertReportedCostWithinCeiling(
|
|
3211
|
+
assertReportedCostWithinCeiling(combineComparisonCosts(optimized.map((result) => ({
|
|
3496
3212
|
label: `method '${result.name}'`,
|
|
3497
3213
|
cost: result.cost
|
|
3498
3214
|
}))).totalCostUsd, opts.costCeiling, "optimization");
|
|
@@ -3577,12 +3293,12 @@ async function compareOptimizationMethods(opts) {
|
|
|
3577
3293
|
favored
|
|
3578
3294
|
};
|
|
3579
3295
|
});
|
|
3580
|
-
const optimizationCost =
|
|
3296
|
+
const optimizationCost = combineComparisonCosts(scores.map((score) => ({
|
|
3581
3297
|
label: `method '${score.name}'`,
|
|
3582
3298
|
cost: score.optimizationCost
|
|
3583
3299
|
})));
|
|
3584
3300
|
const testCost = costFromLedgerSummary(costLedger.summary({ phase: testCostPhase }));
|
|
3585
|
-
const totalCost =
|
|
3301
|
+
const totalCost = combineComparisonCosts([{
|
|
3586
3302
|
label: "optimization",
|
|
3587
3303
|
cost: optimizationCost
|
|
3588
3304
|
}, {
|
|
@@ -3645,6 +3361,7 @@ function assertOptimizationProvenance(methodName, value) {
|
|
|
3645
3361
|
for (const [field, entry] of [["sourceUrl", value.source.sourceUrl], ["revision", value.source.revision]]) if (entry !== void 0 && (typeof entry !== "string" || !entry.trim())) fail(`source.${field}`);
|
|
3646
3362
|
if (typeof value.runId !== "string" || !value.runId.trim()) fail("runId");
|
|
3647
3363
|
if (value.optimizerModel !== void 0 && (typeof value.optimizerModel !== "string" || !value.optimizerModel.trim() || value.optimizerModel.trim() !== value.optimizerModel)) fail("optimizerModel");
|
|
3364
|
+
if (value.optimizerCallRef !== void 0 && (typeof value.optimizerCallRef !== "string" || !value.optimizerCallRef.trim() || value.optimizerCallRef.trim() !== value.optimizerCallRef)) fail("optimizerCallRef");
|
|
3648
3365
|
if (typeof value.resumed !== "boolean") fail("resumed");
|
|
3649
3366
|
if (!Number.isSafeInteger(value.evaluationCount) || value.evaluationCount < 0) fail("evaluationCount");
|
|
3650
3367
|
if (typeof value.artifactDir !== "string" || !value.artifactDir.trim()) fail("artifactDir");
|
|
@@ -3667,6 +3384,24 @@ function assertOptimizationProvenance(methodName, value) {
|
|
|
3667
3384
|
if (value.tokenUsage.reasoningTokens !== void 0 && value.tokenUsage.reasoningTokens > value.tokenUsage.outputTokens) fail("tokenUsage.reasoningTokens");
|
|
3668
3385
|
if (value.tokenUsage.totalTokens !== value.tokenUsage.inputTokens + value.tokenUsage.outputTokens) fail("tokenUsage.totalTokens");
|
|
3669
3386
|
}
|
|
3387
|
+
if (value.observations !== void 0) {
|
|
3388
|
+
if (value.observations.scope !== "callback-submitted-candidates" || typeof value.observations.path !== "string" || !value.observations.path.trim() || typeof value.observations.sha256 !== "string" || !/^sha256:[0-9a-f]{64}$/.test(value.observations.sha256)) fail("observations");
|
|
3389
|
+
for (const field of [
|
|
3390
|
+
"submittedCandidates",
|
|
3391
|
+
"evaluations",
|
|
3392
|
+
"refusals"
|
|
3393
|
+
]) if (!Number.isSafeInteger(value.observations[field]) || value.observations[field] < 0) fail(`observations.${field}`);
|
|
3394
|
+
}
|
|
3395
|
+
if (value.modelExecutions !== void 0) {
|
|
3396
|
+
if (value.modelExecutions.scope !== "runtime-model-calls" || typeof value.modelExecutions.path !== "string" || !value.modelExecutions.path.trim() || typeof value.modelExecutions.sha256 !== "string" || !/^sha256:[0-9a-f]{64}$/.test(value.modelExecutions.sha256)) fail("modelExecutions");
|
|
3397
|
+
for (const field of [
|
|
3398
|
+
"calls",
|
|
3399
|
+
"succeeded",
|
|
3400
|
+
"failed"
|
|
3401
|
+
]) if (!Number.isSafeInteger(value.modelExecutions[field]) || value.modelExecutions[field] < 0) fail(`modelExecutions.${field}`);
|
|
3402
|
+
if (value.modelExecutions.calls !== value.modelExecutions.succeeded + value.modelExecutions.failed) fail("modelExecutions.calls");
|
|
3403
|
+
}
|
|
3404
|
+
if (value.optimizerModel === void 0 !== (value.optimizerCallRef === void 0) || value.optimizerModel === void 0 !== (value.modelExecutions === void 0)) fail("optimizerModel execution provenance");
|
|
3670
3405
|
}
|
|
3671
3406
|
function assertComparisonControls(opts, seed, resamples, confidence) {
|
|
3672
3407
|
if (opts.optimizationRunOptions && "costCeiling" in opts.optimizationRunOptions) throw new Error("compareOptimizationMethods: optimizationRunOptions.costCeiling is not supported; costCeiling covers optimization and final scoring");
|
|
@@ -3810,6 +3545,7 @@ function callerDispatchRef(opts) {
|
|
|
3810
3545
|
function costFromLedgerSummary(summary) {
|
|
3811
3546
|
const cost = {
|
|
3812
3547
|
totalCostUsd: summary.totalCostUsd,
|
|
3548
|
+
costProvenance: structuredClone(summary.costProvenance),
|
|
3813
3549
|
accountingComplete: summary.accountingComplete,
|
|
3814
3550
|
incompleteReasons: [...summary.incompleteReasons]
|
|
3815
3551
|
};
|
|
@@ -3836,19 +3572,37 @@ function optimizationTokenUsageFromSummary(summary, receipts) {
|
|
|
3836
3572
|
calls: summary.totalCalls
|
|
3837
3573
|
};
|
|
3838
3574
|
}
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3575
|
+
/** Combine method costs without turning one unknown bill into a known total. */
|
|
3576
|
+
function combineComparisonCosts(entries) {
|
|
3577
|
+
const totalCostUsd = entries.reduce((total, entry) => total + entry.cost.totalCostUsd, 0);
|
|
3578
|
+
const cost = {
|
|
3579
|
+
totalCostUsd,
|
|
3580
|
+
costProvenance: entries.some((entry) => entry.cost.costProvenance.kind === "uncaptured") ? {
|
|
3581
|
+
kind: "uncaptured",
|
|
3582
|
+
usd: null
|
|
3583
|
+
} : entries.every((entry) => entry.cost.costProvenance.kind === "observed") ? {
|
|
3584
|
+
kind: "observed",
|
|
3585
|
+
usd: totalCostUsd
|
|
3586
|
+
} : {
|
|
3587
|
+
kind: "estimated",
|
|
3588
|
+
usd: totalCostUsd
|
|
3589
|
+
},
|
|
3842
3590
|
accountingComplete: entries.every((entry) => entry.cost.accountingComplete),
|
|
3843
3591
|
incompleteReasons: entries.flatMap((entry) => entry.cost.incompleteReasons.map((reason) => `${entry.label}: ${reason}`))
|
|
3844
3592
|
};
|
|
3593
|
+
assertComparisonCost(cost, "combined cost");
|
|
3594
|
+
return cost;
|
|
3845
3595
|
}
|
|
3846
3596
|
function assertComparisonCost(cost, label) {
|
|
3847
3597
|
if (!cost || typeof cost !== "object") throw new Error(`compareOptimizationMethods: ${label} returned no cost`);
|
|
3848
3598
|
if (!Number.isFinite(cost.totalCostUsd) || cost.totalCostUsd < 0) throw new Error(`compareOptimizationMethods: ${label} returned an invalid totalCostUsd`);
|
|
3599
|
+
const provenance = cost.costProvenance;
|
|
3600
|
+
if (!provenance || typeof provenance !== "object" || provenance.kind !== "observed" && provenance.kind !== "estimated" && provenance.kind !== "uncaptured" || (provenance.kind === "uncaptured" ? provenance.usd !== null : !Number.isFinite(provenance.usd) || provenance.usd < 0)) throw new Error(`compareOptimizationMethods: ${label} returned invalid costProvenance`);
|
|
3601
|
+
if (provenance.kind !== "uncaptured" && provenance.usd !== cost.totalCostUsd) throw new Error(`compareOptimizationMethods: ${label} returned costProvenance inconsistent with totalCostUsd`);
|
|
3849
3602
|
if (typeof cost.accountingComplete !== "boolean") throw new Error(`compareOptimizationMethods: ${label} returned invalid accountingComplete`);
|
|
3850
3603
|
if (!Array.isArray(cost.incompleteReasons) || cost.incompleteReasons.some((reason) => typeof reason !== "string" || reason.trim().length === 0)) throw new Error(`compareOptimizationMethods: ${label} returned invalid incompleteReasons`);
|
|
3851
3604
|
if (cost.accountingComplete !== (cost.incompleteReasons.length === 0)) throw new Error(`compareOptimizationMethods: ${label} returned inconsistent cost completeness and reasons`);
|
|
3605
|
+
if (cost.accountingComplete && provenance.kind === "uncaptured") throw new Error(`compareOptimizationMethods: ${label} cannot mark uncaptured cost as complete`);
|
|
3852
3606
|
}
|
|
3853
3607
|
//#endregion
|
|
3854
3608
|
//#region src/campaign/external-text-optimization.ts
|
|
@@ -4097,16 +3851,23 @@ function externalTextOptimizationMethod(config) {
|
|
|
4097
3851
|
status: "completed"
|
|
4098
3852
|
}
|
|
4099
3853
|
});
|
|
3854
|
+
const measuredCost = combineComparisonCosts([{
|
|
3855
|
+
label: "evaluation",
|
|
3856
|
+
cost: evaluationCost
|
|
3857
|
+
}, {
|
|
3858
|
+
label: "optimizer",
|
|
3859
|
+
cost: optimizerCost
|
|
3860
|
+
}]);
|
|
4100
3861
|
return {
|
|
4101
3862
|
winnerSurface: decodeExternalTextCandidate(result.bestCandidate),
|
|
4102
3863
|
cost: {
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
]
|
|
3864
|
+
...measuredCost,
|
|
3865
|
+
...externalCostReason ? { costProvenance: {
|
|
3866
|
+
kind: "uncaptured",
|
|
3867
|
+
usd: null
|
|
3868
|
+
} } : {},
|
|
3869
|
+
accountingComplete: measuredCost.accountingComplete && externalCostReason === void 0,
|
|
3870
|
+
incompleteReasons: [...measuredCost.incompleteReasons, ...externalCostReason ? [`optimizer: external spend is not observed: ${externalCostReason}`] : []]
|
|
4110
3871
|
},
|
|
4111
3872
|
durationMs: Date.now() - started,
|
|
4112
3873
|
provenance: {
|
|
@@ -5339,8 +5100,8 @@ const TOKEN_USAGE_FIELDS = [
|
|
|
5339
5100
|
"calls"
|
|
5340
5101
|
];
|
|
5341
5102
|
function assertPriorExternalOptimizerUsage(summary, budget, name) {
|
|
5342
|
-
if (!summary.
|
|
5343
|
-
if (summary.totalCalls > budget.maxRequests || summary.totalCostUsd > budget.maxCostUsd + Number.EPSILON) throw new Error(`${name}: prior optimizer-model usage exceeds the configured budget`);
|
|
5103
|
+
if (!summary.usageComplete || budget.maxCostUsd !== void 0 && !summary.accountingComplete) throw new Error(`${name}: cannot resume optimizer-model work with incomplete bounded usage`);
|
|
5104
|
+
if (summary.totalCalls > budget.maxRequests || budget.maxCostUsd !== void 0 && summary.totalCostUsd > budget.maxCostUsd + Number.EPSILON) throw new Error(`${name}: prior optimizer-model usage exceeds the configured budget`);
|
|
5344
5105
|
}
|
|
5345
5106
|
function assertExternalOptimizerTokenUsage(usage, name, optimizer) {
|
|
5346
5107
|
if (usage === void 0) return;
|
|
@@ -5355,12 +5116,85 @@ function assertExternalOptimizerCompletionCount(upstream, requestAttempts, succe
|
|
|
5355
5116
|
if (upstream.requestAttempts !== void 0 && upstream.requestAttempts !== requestAttempts) throw new Error(`${name}: ${optimizer} reported ${upstream.requestAttempts} model attempts but the proxy received ${requestAttempts}`);
|
|
5356
5117
|
}
|
|
5357
5118
|
//#endregion
|
|
5119
|
+
//#region src/campaign/external-optimizer-observations.ts
|
|
5120
|
+
/** Append-only observation log for one external-optimizer attempt. */
|
|
5121
|
+
function openExternalOptimizerObservationLog(input) {
|
|
5122
|
+
if (input.storage.read(input.path) !== void 0 || input.storage.exists(input.path)) throw new Error(`external optimizer observation log already exists at '${input.path}'`);
|
|
5123
|
+
input.storage.write(input.path, "");
|
|
5124
|
+
let revision = 0;
|
|
5125
|
+
const counts = {
|
|
5126
|
+
submittedCandidates: 0,
|
|
5127
|
+
evaluations: 0,
|
|
5128
|
+
refusals: 0
|
|
5129
|
+
};
|
|
5130
|
+
return {
|
|
5131
|
+
observe(observation) {
|
|
5132
|
+
const expectedSequence = counts.submittedCandidates + counts.evaluations + counts.refusals + 1;
|
|
5133
|
+
if (observation.sequence !== expectedSequence) throw new Error(`external optimizer observation log expected sequence ${expectedSequence}, got ${observation.sequence}`);
|
|
5134
|
+
const line = `${canonicalJson(observation)}\n`;
|
|
5135
|
+
const next = input.storage.append(input.path, line, revision);
|
|
5136
|
+
if (next === void 0) throw new Error(`external optimizer observation log changed concurrently at '${input.path}'`);
|
|
5137
|
+
revision = next;
|
|
5138
|
+
if (observation.kind === "proposal") counts.submittedCandidates += 1;
|
|
5139
|
+
else if (observation.kind === "evaluation") counts.evaluations += 1;
|
|
5140
|
+
else counts.refusals += 1;
|
|
5141
|
+
},
|
|
5142
|
+
summary() {
|
|
5143
|
+
const contents = input.storage.read(input.path) ?? "";
|
|
5144
|
+
const bytes = new TextEncoder().encode(contents);
|
|
5145
|
+
if (bytes.byteLength !== revision) throw new Error(`external optimizer observation log revision changed at '${input.path}'`);
|
|
5146
|
+
return {
|
|
5147
|
+
scope: "callback-submitted-candidates",
|
|
5148
|
+
path: input.path,
|
|
5149
|
+
sha256: `sha256:${createHash("sha256").update(bytes).digest("hex")}`,
|
|
5150
|
+
...counts
|
|
5151
|
+
};
|
|
5152
|
+
}
|
|
5153
|
+
};
|
|
5154
|
+
}
|
|
5155
|
+
/** Append-only opaque Runtime execution records for one optimizer attempt. */
|
|
5156
|
+
function openExternalOptimizerExecutionLog(input) {
|
|
5157
|
+
if (input.storage.read(input.path) !== void 0 || input.storage.exists(input.path)) throw new Error(`external optimizer execution log already exists at '${input.path}'`);
|
|
5158
|
+
input.storage.write(input.path, "");
|
|
5159
|
+
let revision = 0;
|
|
5160
|
+
const counts = {
|
|
5161
|
+
calls: 0,
|
|
5162
|
+
succeeded: 0,
|
|
5163
|
+
failed: 0
|
|
5164
|
+
};
|
|
5165
|
+
return {
|
|
5166
|
+
observe(observation) {
|
|
5167
|
+
if (observation.sequence !== counts.calls + 1) throw new Error(`external optimizer execution log expected sequence ${counts.calls + 1}, got ${observation.sequence}`);
|
|
5168
|
+
const line = `${canonicalJson(observation)}\n`;
|
|
5169
|
+
const next = input.storage.append(input.path, line, revision);
|
|
5170
|
+
if (next === void 0) throw new Error(`external optimizer execution log changed concurrently at '${input.path}'`);
|
|
5171
|
+
revision = next;
|
|
5172
|
+
counts.calls += 1;
|
|
5173
|
+
if (observation.succeeded) counts.succeeded += 1;
|
|
5174
|
+
else counts.failed += 1;
|
|
5175
|
+
},
|
|
5176
|
+
summary() {
|
|
5177
|
+
const contents = input.storage.read(input.path) ?? "";
|
|
5178
|
+
const bytes = new TextEncoder().encode(contents);
|
|
5179
|
+
if (bytes.byteLength !== revision) throw new Error(`external optimizer execution log revision changed at '${input.path}'`);
|
|
5180
|
+
if (counts.calls !== counts.succeeded + counts.failed) throw new Error(`external optimizer execution log counts disagree at '${input.path}'`);
|
|
5181
|
+
return {
|
|
5182
|
+
scope: "runtime-model-calls",
|
|
5183
|
+
path: input.path,
|
|
5184
|
+
sha256: `sha256:${createHash("sha256").update(bytes).digest("hex")}`,
|
|
5185
|
+
...counts
|
|
5186
|
+
};
|
|
5187
|
+
}
|
|
5188
|
+
};
|
|
5189
|
+
}
|
|
5190
|
+
//#endregion
|
|
5358
5191
|
//#region src/campaign/external-optimizer-run-config.ts
|
|
5359
5192
|
function externalOptimizerRunnerIdentity(runner, module) {
|
|
5360
5193
|
return {
|
|
5361
5194
|
command: runner?.command ?? "python",
|
|
5362
5195
|
args: [...runner?.args ?? ["-m", module]],
|
|
5363
|
-
environment: removeCredentialEnvironment(runner?.env ?? {})
|
|
5196
|
+
environment: removeCredentialEnvironment(runner?.env ?? {}),
|
|
5197
|
+
limits: resolveExternalOptimizerProcessLimits(runner?.limits)
|
|
5364
5198
|
};
|
|
5365
5199
|
}
|
|
5366
5200
|
function snapshotExternalOptimizerRunner(runner) {
|
|
@@ -5368,7 +5202,8 @@ function snapshotExternalOptimizerRunner(runner) {
|
|
|
5368
5202
|
return {
|
|
5369
5203
|
...runner,
|
|
5370
5204
|
...runner.args ? { args: [...runner.args] } : {},
|
|
5371
|
-
...runner.env ? { env: { ...runner.env } } : {}
|
|
5205
|
+
...runner.env ? { env: { ...runner.env } } : {},
|
|
5206
|
+
...runner.limits ? { limits: { ...runner.limits } } : {}
|
|
5372
5207
|
};
|
|
5373
5208
|
}
|
|
5374
5209
|
function snapshotJson(value, label) {
|
|
@@ -5446,27 +5281,16 @@ function assertExternalOptimizerRuntimeIdentity(value, expectedPackage, label) {
|
|
|
5446
5281
|
//#region src/campaign/optimizer-model.ts
|
|
5447
5282
|
function assertOptimizerModel(value, label) {
|
|
5448
5283
|
if (!value || typeof value !== "object") throw new Error(`${label} is required`);
|
|
5449
|
-
for (const field of [
|
|
5450
|
-
|
|
5451
|
-
"baseUrl",
|
|
5452
|
-
"apiKey"
|
|
5453
|
-
]) {
|
|
5454
|
-
const item = value[field];
|
|
5455
|
-
if (typeof item !== "string" || !item.trim() || item.trim() !== item) throw new Error(`${label}.${field} must be trimmed and non-empty`);
|
|
5456
|
-
}
|
|
5457
|
-
let url;
|
|
5458
|
-
try {
|
|
5459
|
-
url = new URL(value.baseUrl);
|
|
5460
|
-
} catch {
|
|
5461
|
-
throw new Error(`${label}.baseUrl must be an absolute HTTP URL`);
|
|
5462
|
-
}
|
|
5463
|
-
if (!["http:", "https:"].includes(url.protocol) || url.username || url.password || url.search || url.hash) throw new Error(`${label}.baseUrl must use HTTP or HTTPS without credentials, query, or fragment`);
|
|
5284
|
+
for (const [field, item] of [["model", value.model], ["callRef", value.callRef]]) if (typeof item !== "string" || !item.trim() || item.trim() !== item) throw new Error(`${label}.${field} must be trimmed and non-empty`);
|
|
5285
|
+
if (typeof value.call !== "function") throw new Error(`${label}.call must be a function`);
|
|
5464
5286
|
assertExternalOptimizerModelBudget(value.budget, `${label}.budget`);
|
|
5465
5287
|
}
|
|
5466
5288
|
function snapshotOptimizerModel(value) {
|
|
5467
5289
|
return {
|
|
5468
|
-
|
|
5469
|
-
budget: structuredClone(value.budget)
|
|
5290
|
+
model: value.model,
|
|
5291
|
+
budget: structuredClone(value.budget),
|
|
5292
|
+
call: value.call,
|
|
5293
|
+
callRef: value.callRef
|
|
5470
5294
|
};
|
|
5471
5295
|
}
|
|
5472
5296
|
const MAX_TIMER_DELAY_MS$1 = 2147483647;
|
|
@@ -5477,6 +5301,7 @@ function snapshotGepaOptimizationConfig(config) {
|
|
|
5477
5301
|
recipe: structuredClone(config.recipe),
|
|
5478
5302
|
...config.engineModules ? { engineModules: [...config.engineModules] } : {},
|
|
5479
5303
|
...config.optimizer ? { optimizer: snapshotOptimizerModel(config.optimizer) } : {},
|
|
5304
|
+
...config.evaluationCallbackLimits ? { evaluationCallbackLimits: { ...config.evaluationCallbackLimits } } : {},
|
|
5480
5305
|
...runner ? { runner } : {}
|
|
5481
5306
|
};
|
|
5482
5307
|
}
|
|
@@ -5495,6 +5320,7 @@ function assertGepaOptimizationConfig(config) {
|
|
|
5495
5320
|
const evidenceLimit = config.maxEvidenceChars ?? 1e5;
|
|
5496
5321
|
if (JSON.stringify(config.objective).length > evidenceLimit || JSON.stringify(config.background ?? "").length > evidenceLimit) throw new Error("gepaOptimizationMethod: objective and background must each fit maxEvidenceChars");
|
|
5497
5322
|
assertEngineModules(config.engineModules);
|
|
5323
|
+
resolveExternalOptimizerCallbackLimits(config.evaluationCallbackLimits, "gepaOptimizationMethod: evaluationCallbackLimits");
|
|
5498
5324
|
if (config.optimizer !== void 0) {
|
|
5499
5325
|
assertOptimizerModel(config.optimizer, "gepaOptimizationMethod: optimizer");
|
|
5500
5326
|
if (config.engineModules?.length) throw new Error("gepaOptimizationMethod: optimizer cannot be combined with engineModules because proxied reflection requires the built-in GEPA engine");
|
|
@@ -5581,7 +5407,7 @@ function assertEngineRun(run, label) {
|
|
|
5581
5407
|
function assertEngineOptions(run, label) {
|
|
5582
5408
|
if (!run || typeof run !== "object") throw new Error(`gepaOptimizationMethod: ${label} is required`);
|
|
5583
5409
|
if (typeof run.engine !== "string" || !run.engine.trim() || run.engine.trim() !== run.engine) throw new Error(`gepaOptimizationMethod: ${label}.engine must be a trimmed non-empty string`);
|
|
5584
|
-
if (!Number.isFinite(run.maxProposerCostUsd) || run.maxProposerCostUsd <= 0) throw new Error(`gepaOptimizationMethod: ${label}.maxProposerCostUsd must be a positive finite number`);
|
|
5410
|
+
if (run.maxProposerCostUsd !== void 0 && (!Number.isFinite(run.maxProposerCostUsd) || run.maxProposerCostUsd <= 0)) throw new Error(`gepaOptimizationMethod: ${label}.maxProposerCostUsd must be a positive finite number when supplied`);
|
|
5585
5411
|
if (run.maxConcurrency !== void 0) assertPositiveSafeInteger$1(run.maxConcurrency, `${label}.maxConcurrency`);
|
|
5586
5412
|
if (run.stopAtScore !== void 0 && !Number.isFinite(run.stopAtScore)) throw new Error(`gepaOptimizationMethod: ${label}.stopAtScore must be a finite number`);
|
|
5587
5413
|
if (run.sandbox !== void 0 && typeof run.sandbox !== "boolean") throw new Error(`gepaOptimizationMethod: ${label}.sandbox must be a boolean`);
|
|
@@ -5706,9 +5532,10 @@ function gepaOptimizationMethod(config) {
|
|
|
5706
5532
|
selectionSet,
|
|
5707
5533
|
maxCandidateChars,
|
|
5708
5534
|
maxEvidenceChars,
|
|
5535
|
+
evaluationCallbackLimits: resolveExternalOptimizerCallbackLimits(config.evaluationCallbackLimits),
|
|
5709
5536
|
optimizerModel: config.optimizer ? {
|
|
5710
5537
|
model: config.optimizer.model,
|
|
5711
|
-
|
|
5538
|
+
callRef: config.optimizer.callRef,
|
|
5712
5539
|
budget: config.optimizer.budget
|
|
5713
5540
|
} : null,
|
|
5714
5541
|
runner: externalOptimizerRunnerIdentity(bridgeRunner, "agent_eval_rpc.gepa_bridge"),
|
|
@@ -5727,6 +5554,14 @@ function gepaOptimizationMethod(config) {
|
|
|
5727
5554
|
attemptId,
|
|
5728
5555
|
maxEvaluations: evaluationLimit
|
|
5729
5556
|
});
|
|
5557
|
+
const observationLog = openExternalOptimizerObservationLog({
|
|
5558
|
+
storage,
|
|
5559
|
+
path: `${runDir}/observations-${attemptId}.jsonl`
|
|
5560
|
+
});
|
|
5561
|
+
const executionLog = config.optimizer ? openExternalOptimizerExecutionLog({
|
|
5562
|
+
storage,
|
|
5563
|
+
path: `${runDir}/model-executions-${attemptId}.jsonl`
|
|
5564
|
+
}) : void 0;
|
|
5730
5565
|
const scenarioById = mapExternalScenarios(input.trainScenarios, input.selectionScenarios, "GEPA bridge");
|
|
5731
5566
|
const evaluate = createExternalTextEvaluator({
|
|
5732
5567
|
input,
|
|
@@ -5746,6 +5581,8 @@ function gepaOptimizationMethod(config) {
|
|
|
5746
5581
|
maxEvaluations: evaluationLimit,
|
|
5747
5582
|
acceptEvaluation: () => runBudget.acceptEvaluation(),
|
|
5748
5583
|
evaluate,
|
|
5584
|
+
observe: observationLog.observe,
|
|
5585
|
+
...config.evaluationCallbackLimits ? { limits: config.evaluationCallbackLimits } : {},
|
|
5749
5586
|
...signal ? { signal } : {}
|
|
5750
5587
|
});
|
|
5751
5588
|
const runnerEnv = bridgeRunner?.env ?? {};
|
|
@@ -5765,8 +5602,9 @@ function gepaOptimizationMethod(config) {
|
|
|
5765
5602
|
});
|
|
5766
5603
|
assertPriorExternalOptimizerUsage(priorOptimizerUsage, config.optimizer.budget, name);
|
|
5767
5604
|
modelProxy = await startExternalOptimizerModelProxy({
|
|
5768
|
-
|
|
5769
|
-
|
|
5605
|
+
call: config.optimizer.call,
|
|
5606
|
+
callRef: config.optimizer.callRef,
|
|
5607
|
+
recordExecution: executionLog.observe,
|
|
5770
5608
|
model: config.optimizer.model,
|
|
5771
5609
|
budget: config.optimizer.budget,
|
|
5772
5610
|
costLedger,
|
|
@@ -5775,7 +5613,7 @@ function gepaOptimizationMethod(config) {
|
|
|
5775
5613
|
tags: { ...runBudget.attemptTags },
|
|
5776
5614
|
initialUsage: {
|
|
5777
5615
|
requests: priorOptimizerUsage.totalCalls,
|
|
5778
|
-
costUsd: priorOptimizerUsage.totalCostUsd
|
|
5616
|
+
...priorOptimizerUsage.costProvenance.kind === "uncaptured" ? {} : { costUsd: priorOptimizerUsage.totalCostUsd }
|
|
5779
5617
|
},
|
|
5780
5618
|
...signal ? { signal } : {}
|
|
5781
5619
|
});
|
|
@@ -5854,17 +5692,31 @@ function gepaOptimizationMethod(config) {
|
|
|
5854
5692
|
});
|
|
5855
5693
|
const optimizerCost = costFromLedgerSummary(optimizerSummary);
|
|
5856
5694
|
const reportedProposerCost = result.proposerCostUsd ?? 0;
|
|
5857
|
-
if (modelProxy)
|
|
5695
|
+
if (modelProxy) {
|
|
5696
|
+
modelProxy.assertExecutionComplete();
|
|
5697
|
+
assertExternalOptimizerCompletionCount(result.tokenUsage, modelProxy.requestAttempts(), modelProxy.successfulCompletions(), name, "GEPA");
|
|
5698
|
+
}
|
|
5858
5699
|
const tokenUsage = modelProxy ? optimizationTokenUsageFromSummary(optimizerSummary, optimizerReceipts) : void 0;
|
|
5859
5700
|
const runtime = observedExternalOptimizerRuntime(runtimeIdentity);
|
|
5701
|
+
const meteredCost = modelProxy ? combineComparisonCosts([{
|
|
5702
|
+
label: "evaluation",
|
|
5703
|
+
cost: evaluationCost
|
|
5704
|
+
}, {
|
|
5705
|
+
label: "optimizer model",
|
|
5706
|
+
cost: optimizerCost
|
|
5707
|
+
}]) : void 0;
|
|
5708
|
+
const externalTotalCostUsd = evaluationCost.totalCostUsd + reportedProposerCost;
|
|
5860
5709
|
return {
|
|
5861
5710
|
winnerSurface: decodeExternalTextCandidate(result.bestCandidate),
|
|
5862
|
-
cost: modelProxy ? {
|
|
5863
|
-
totalCostUsd:
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5711
|
+
cost: modelProxy ? meteredCost : {
|
|
5712
|
+
totalCostUsd: externalTotalCostUsd,
|
|
5713
|
+
costProvenance: result.proposerCostAccounting === "reported" && evaluationCost.costProvenance.kind !== "uncaptured" ? {
|
|
5714
|
+
kind: "estimated",
|
|
5715
|
+
usd: externalTotalCostUsd
|
|
5716
|
+
} : {
|
|
5717
|
+
kind: "uncaptured",
|
|
5718
|
+
usd: null
|
|
5719
|
+
},
|
|
5868
5720
|
accountingComplete: false,
|
|
5869
5721
|
incompleteReasons: [
|
|
5870
5722
|
...evaluationCost.incompleteReasons,
|
|
@@ -5875,13 +5727,18 @@ function gepaOptimizationMethod(config) {
|
|
|
5875
5727
|
durationMs: Date.now() - started,
|
|
5876
5728
|
provenance: {
|
|
5877
5729
|
...runtime,
|
|
5878
|
-
...config.optimizer ? {
|
|
5730
|
+
...config.optimizer ? {
|
|
5731
|
+
optimizerModel: config.optimizer.model,
|
|
5732
|
+
optimizerCallRef: config.optimizer.callRef
|
|
5733
|
+
} : {},
|
|
5879
5734
|
compatibleRunId,
|
|
5880
5735
|
runId,
|
|
5881
5736
|
resumed: result.resumed,
|
|
5882
5737
|
evaluationCount: runBudget.acceptedEvaluations(),
|
|
5883
5738
|
artifactDir: outputDir,
|
|
5884
|
-
...tokenUsage ? { tokenUsage } : {}
|
|
5739
|
+
...tokenUsage ? { tokenUsage } : {},
|
|
5740
|
+
observations: observationLog.summary(),
|
|
5741
|
+
...executionLog ? { modelExecutions: executionLog.summary() } : {}
|
|
5885
5742
|
}
|
|
5886
5743
|
};
|
|
5887
5744
|
}
|
|
@@ -6954,6 +6811,7 @@ function snapshotSkillOptOptimizationConfig(config) {
|
|
|
6954
6811
|
...config,
|
|
6955
6812
|
trainer: structuredClone(config.trainer),
|
|
6956
6813
|
optimizer: snapshotOptimizerModel(config.optimizer),
|
|
6814
|
+
...config.evaluationCallbackLimits ? { evaluationCallbackLimits: { ...config.evaluationCallbackLimits } } : {},
|
|
6957
6815
|
...runner ? { runner } : {}
|
|
6958
6816
|
};
|
|
6959
6817
|
}
|
|
@@ -7006,6 +6864,7 @@ function assertSkillOptOptimizationConfig(config) {
|
|
|
7006
6864
|
assertJsonValue(config.trainer.overrides ?? {}, "skillOptOptimizationMethod: trainer.overrides");
|
|
7007
6865
|
assertNoCredentialValues(config.trainer.overrides ?? {}, "skillOptOptimizationMethod: trainer.overrides", "optimizer");
|
|
7008
6866
|
assertOptimizerModel(config.optimizer, "skillOptOptimizationMethod: optimizer");
|
|
6867
|
+
resolveExternalOptimizerCallbackLimits(config.evaluationCallbackLimits, "skillOptOptimizationMethod: evaluationCallbackLimits");
|
|
7009
6868
|
const evidenceLimit = config.maxEvidenceChars ?? 1e5;
|
|
7010
6869
|
if (JSON.stringify(config.objective).length > evidenceLimit || JSON.stringify(config.background ?? "").length > evidenceLimit) throw new Error("skillOptOptimizationMethod: objective and background must each fit maxEvidenceChars");
|
|
7011
6870
|
}
|
|
@@ -7076,7 +6935,7 @@ function skillOptOptimizationMethod(config) {
|
|
|
7076
6935
|
background: config.background ?? "",
|
|
7077
6936
|
optimizerModel: {
|
|
7078
6937
|
model: config.optimizer.model,
|
|
7079
|
-
|
|
6938
|
+
callRef: config.optimizer.callRef,
|
|
7080
6939
|
budget: config.optimizer.budget
|
|
7081
6940
|
},
|
|
7082
6941
|
seedCandidate: input.baselineSurface,
|
|
@@ -7086,6 +6945,7 @@ function skillOptOptimizationMethod(config) {
|
|
|
7086
6945
|
hardScoreThreshold: config.hardScoreThreshold ?? 1,
|
|
7087
6946
|
maxCandidateChars,
|
|
7088
6947
|
maxEvidenceChars,
|
|
6948
|
+
evaluationCallbackLimits: resolveExternalOptimizerCallbackLimits(config.evaluationCallbackLimits),
|
|
7089
6949
|
runner: externalOptimizerRunnerIdentity(bridgeRunner, "agent_eval_rpc.skillopt_bridge")
|
|
7090
6950
|
};
|
|
7091
6951
|
const compatibleRunId = externalOptimizerCompatibleRunKey(runMaterial);
|
|
@@ -7101,6 +6961,14 @@ function skillOptOptimizationMethod(config) {
|
|
|
7101
6961
|
attemptId,
|
|
7102
6962
|
maxEvaluations: config.maxEvaluations
|
|
7103
6963
|
});
|
|
6964
|
+
const observationLog = openExternalOptimizerObservationLog({
|
|
6965
|
+
storage,
|
|
6966
|
+
path: `${runDir}/observations-${attemptId}.jsonl`
|
|
6967
|
+
});
|
|
6968
|
+
const executionLog = openExternalOptimizerExecutionLog({
|
|
6969
|
+
storage,
|
|
6970
|
+
path: `${runDir}/model-executions-${attemptId}.jsonl`
|
|
6971
|
+
});
|
|
7104
6972
|
const scenarioById = mapExternalScenarios(input.trainScenarios, input.selectionScenarios, "SkillOpt bridge");
|
|
7105
6973
|
const evaluate = createExternalTextEvaluator({
|
|
7106
6974
|
input,
|
|
@@ -7120,6 +6988,8 @@ function skillOptOptimizationMethod(config) {
|
|
|
7120
6988
|
maxEvaluations: config.maxEvaluations,
|
|
7121
6989
|
acceptEvaluation: () => runBudget.acceptEvaluation(),
|
|
7122
6990
|
evaluate,
|
|
6991
|
+
observe: observationLog.observe,
|
|
6992
|
+
...config.evaluationCallbackLimits ? { limits: config.evaluationCallbackLimits } : {},
|
|
7123
6993
|
...signal ? { signal } : {}
|
|
7124
6994
|
});
|
|
7125
6995
|
const runnerEnv = bridgeRunner?.env ?? {};
|
|
@@ -7138,8 +7008,9 @@ function skillOptOptimizationMethod(config) {
|
|
|
7138
7008
|
});
|
|
7139
7009
|
assertPriorExternalOptimizerUsage(priorOptimizerUsage, config.optimizer.budget, name);
|
|
7140
7010
|
const modelProxy = await startExternalOptimizerModelProxy({
|
|
7141
|
-
|
|
7142
|
-
|
|
7011
|
+
call: config.optimizer.call,
|
|
7012
|
+
callRef: config.optimizer.callRef,
|
|
7013
|
+
recordExecution: executionLog.observe,
|
|
7143
7014
|
model: config.optimizer.model,
|
|
7144
7015
|
budget: config.optimizer.budget,
|
|
7145
7016
|
costLedger,
|
|
@@ -7148,7 +7019,7 @@ function skillOptOptimizationMethod(config) {
|
|
|
7148
7019
|
tags: { ...runBudget.attemptTags },
|
|
7149
7020
|
initialUsage: {
|
|
7150
7021
|
requests: priorOptimizerUsage.totalCalls,
|
|
7151
|
-
costUsd: priorOptimizerUsage.totalCostUsd
|
|
7022
|
+
...priorOptimizerUsage.costProvenance.kind === "uncaptured" ? {} : { costUsd: priorOptimizerUsage.totalCostUsd }
|
|
7152
7023
|
},
|
|
7153
7024
|
...signal ? { signal } : {}
|
|
7154
7025
|
});
|
|
@@ -7237,32 +7108,39 @@ function skillOptOptimizationMethod(config) {
|
|
|
7237
7108
|
tags: runBudget.runTags
|
|
7238
7109
|
});
|
|
7239
7110
|
const optimizerCost = costFromLedgerSummary(optimizerUsage);
|
|
7111
|
+
modelProxy.assertExecutionComplete();
|
|
7240
7112
|
assertExternalOptimizerCompletionCount(result.tokenUsage, modelProxy.requestAttempts(), modelProxy.successfulCompletions(), name, "SkillOpt");
|
|
7241
7113
|
const tokenUsage = optimizationTokenUsageFromSummary(optimizerUsage, optimizerReceipts);
|
|
7242
7114
|
const runtime = observedExternalOptimizerRuntime(runtimeIdentity);
|
|
7115
|
+
const combinedCost = combineComparisonCosts([{
|
|
7116
|
+
label: "evaluation",
|
|
7117
|
+
cost: evaluationCost
|
|
7118
|
+
}, {
|
|
7119
|
+
label: "optimizer model",
|
|
7120
|
+
cost: optimizerCost
|
|
7121
|
+
}]);
|
|
7243
7122
|
return {
|
|
7244
7123
|
winnerSurface: result.bestCandidate,
|
|
7245
|
-
cost:
|
|
7246
|
-
totalCostUsd: evaluationCost.totalCostUsd + optimizerCost.totalCostUsd,
|
|
7247
|
-
accountingComplete: evaluationCost.accountingComplete && optimizerCost.accountingComplete,
|
|
7248
|
-
incompleteReasons: [...evaluationCost.incompleteReasons.map((reason) => `evaluation: ${reason}`), ...optimizerCost.incompleteReasons.map((reason) => `optimizer model: ${reason}`)]
|
|
7249
|
-
},
|
|
7124
|
+
cost: combinedCost,
|
|
7250
7125
|
durationMs: Date.now() - started,
|
|
7251
7126
|
provenance: {
|
|
7252
7127
|
...runtime,
|
|
7253
7128
|
optimizerModel: config.optimizer.model,
|
|
7129
|
+
optimizerCallRef: config.optimizer.callRef,
|
|
7254
7130
|
compatibleRunId,
|
|
7255
7131
|
runId,
|
|
7256
7132
|
resumed: result.resumed,
|
|
7257
7133
|
evaluationCount: runBudget.acceptedEvaluations(),
|
|
7258
7134
|
artifactDir: outputDir,
|
|
7259
|
-
...tokenUsage ? { tokenUsage } : {}
|
|
7135
|
+
...tokenUsage ? { tokenUsage } : {},
|
|
7136
|
+
observations: observationLog.summary(),
|
|
7137
|
+
modelExecutions: executionLog.summary()
|
|
7260
7138
|
}
|
|
7261
7139
|
};
|
|
7262
7140
|
}
|
|
7263
7141
|
};
|
|
7264
7142
|
}
|
|
7265
7143
|
//#endregion
|
|
7266
|
-
export {
|
|
7144
|
+
export { assertCampaignSplitIdentity as $, assertOptimizationResult as A, summarizeAgentReceiptIntegrity as At, surfaceContentHash as B, detectScale as C, decidePairedPromotion as Ct, runCanaries as D, BackendIntegrityError as Dt, pairHoldout as E, pairedDeltaTest as Et, assertCodeSurfaceIdentity as F, DEFAULT_MUTATION_PRIMITIVES as G, campaignBreakdown as H, assertComponentSurface as I, planCampaignRun as J, buildReflectionPrompt as K, codeSurfaceIdentityMaterial as L, compareOptimizationMethods as M, JudgeParseError as Mt, costFromLedgerSummary as N, composeGate as O, assertRealAgentReceipts as Ot, optimizationTokenUsageFromSummary as P, assertCampaignDesign as Q, componentSurfaceIdentityMaterial as R, defaultProductionGate as S, recoverTruncatedJson as St, heldoutSignificance as T, minimumPairsForPairedDeltaTest as Tt, campaignMeanComposite as U, surfaceHash as V, compareRankKeys as W, resolveRunDir as X, runCampaign as Y, tangleTracesRoot as Z, buildEvidenceVector as _, crowdingDistance as _t, emitLoopProvenance as a, REFERENCE_EQUIVALENCE_JUDGE_VERSION as at, powerPreflight as b, paretoFrontierWithCrowding as bt, provenanceRecordPath as c, DEFAULT_RED_TEAM_CORPUS as ct, runImprovementLoop as d, scoreRedTeamOutput as dt, campaignScenarioIdentity as et, runOptimization as f, toolNamesForRun as ft, gepaOptimizationMethod as g, llmJudge as gt, labelTrustRank as h, hashScenarios as ht, canonicalDigest as i, REFERENCE_EQUIVALENCE_INPUT_LIMITS as it, combineComparisonCosts as j, summarizeBackendIntegrity as jt, externalTextOptimizationMethod as k, assertRealBackend as kt, provenanceSpansPath as l, redTeamDataset as lt, isProposedCandidate as m, HoldoutLockedError as mt, buildLoopProvenanceRecord as n, campaignSplitDigestFromIdentities as nt, loopProvenanceArgsFromResult as o, createReferenceEquivalenceJudge as ot, runEval as p, Dataset as pt, parseReflectionResponse as q, campaignMeasurementDigest as r, openAutoPr as rt, loopProvenanceSpans as s, runReferenceEquivalenceJudge as st, skillOptOptimizationMethod as t, campaignSplitDigest as tt, verifyLoopProvenanceRecord as u, redTeamReport as ut, paretoPolicy as v, dominates as vt, dimensionRegressions as w, pairedDecisionShape as wt, heldOutGate as x, scalarScore as xt, paretoSignificanceGate as y, paretoFrontier as yt, renderSurfaceDiff as z };
|
|
7267
7145
|
|
|
7268
|
-
//# sourceMappingURL=skillopt-optimization-method-
|
|
7146
|
+
//# sourceMappingURL=skillopt-optimization-method-DA5mJmFE.js.map
|