@tangle-network/agent-eval 0.126.0 → 0.126.2
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 +26 -0
- package/dist/analyst/index.js +3 -3
- package/dist/benchmarks/index.js +3 -3
- package/dist/campaign/index.d.ts +27 -6
- package/dist/campaign/index.js +5 -3
- package/dist/{chunk-NTOV7RU5.js → chunk-7AN2E7BU.js} +233 -57
- package/dist/chunk-7AN2E7BU.js.map +1 -0
- package/dist/{chunk-4B7ZZHPX.js → chunk-KE2VWPZX.js} +3 -3
- package/dist/{chunk-CM4OILD2.js → chunk-LUNF2SEL.js} +4 -6
- package/dist/{chunk-CM4OILD2.js.map → chunk-LUNF2SEL.js.map} +1 -1
- package/dist/{chunk-UI4YMIN2.js → chunk-WGXIEX7P.js} +12 -1
- package/dist/chunk-WGXIEX7P.js.map +1 -0
- package/dist/{chunk-KO2PZOGP.js → chunk-Y5CLI4PY.js} +3 -3
- package/dist/contract/index.d.ts +29 -5
- package/dist/contract/index.js +5 -4
- package/dist/contract/index.js.map +1 -1
- package/dist/index.js +5 -5
- package/dist/openapi.json +1 -1
- package/docs/campaign-proposers.md +3 -3
- package/package.json +1 -1
- package/dist/chunk-NTOV7RU5.js.map +0 -1
- package/dist/chunk-UI4YMIN2.js.map +0 -1
- /package/dist/{chunk-4B7ZZHPX.js.map → chunk-KE2VWPZX.js.map} +0 -0
- /package/dist/{chunk-KO2PZOGP.js.map → chunk-Y5CLI4PY.js.map} +0 -0
|
@@ -16,8 +16,9 @@ import {
|
|
|
16
16
|
} from "./chunk-UCLVDLCH.js";
|
|
17
17
|
import {
|
|
18
18
|
clamp01,
|
|
19
|
+
combineAbortSignals,
|
|
19
20
|
mapConcurrent
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-WGXIEX7P.js";
|
|
21
22
|
import {
|
|
22
23
|
detectRewardHacking
|
|
23
24
|
} from "./chunk-ARU2PZFM.js";
|
|
@@ -1513,6 +1514,29 @@ function campaignMeanComposite(campaign) {
|
|
|
1513
1514
|
}
|
|
1514
1515
|
return composites.length === 0 ? 0 : composites.reduce((a, b) => a + b, 0) / composites.length;
|
|
1515
1516
|
}
|
|
1517
|
+
function assertFiniteRankKey(key, label, expectedLength) {
|
|
1518
|
+
if (!Array.isArray(key) || key.length === 0) {
|
|
1519
|
+
throw new Error(`${label} must return a non-empty array`);
|
|
1520
|
+
}
|
|
1521
|
+
if (expectedLength !== void 0 && key.length !== expectedLength) {
|
|
1522
|
+
throw new Error(`${label} returned ${key.length} elements; expected ${expectedLength}`);
|
|
1523
|
+
}
|
|
1524
|
+
for (let index = 0; index < key.length; index++) {
|
|
1525
|
+
if (!Number.isFinite(key[index])) {
|
|
1526
|
+
throw new Error(`${label}[${index}] must be finite`);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
function compareRankKeys(a, b) {
|
|
1531
|
+
assertFiniteRankKey(a, "rank key a");
|
|
1532
|
+
assertFiniteRankKey(b, "rank key b", a.length);
|
|
1533
|
+
for (let i = 0; i < a.length; i++) {
|
|
1534
|
+
const av = a[i];
|
|
1535
|
+
const bv = b[i];
|
|
1536
|
+
if (av !== bv) return av - bv;
|
|
1537
|
+
}
|
|
1538
|
+
return 0;
|
|
1539
|
+
}
|
|
1516
1540
|
function campaignBreakdown(campaign) {
|
|
1517
1541
|
const dimSums = {};
|
|
1518
1542
|
const dimCounts = {};
|
|
@@ -1696,7 +1720,6 @@ ${describe(winnerSurface)}`;
|
|
|
1696
1720
|
}
|
|
1697
1721
|
|
|
1698
1722
|
// src/campaign/presets/compare-optimization-methods.ts
|
|
1699
|
-
import { randomUUID } from "crypto";
|
|
1700
1723
|
async function compareOptimizationMethods(opts) {
|
|
1701
1724
|
assertOptimizationMethods(opts.methods);
|
|
1702
1725
|
assertComparisonPartitions(opts);
|
|
@@ -1711,20 +1734,22 @@ async function compareOptimizationMethods(opts) {
|
|
|
1711
1734
|
assertComparisonControls(opts, seed, resamples, confidence);
|
|
1712
1735
|
const storage = opts.storage ?? fsCampaignStorage();
|
|
1713
1736
|
const resolvedRunDir = resolveRunDir(opts.runDir, opts.repo);
|
|
1714
|
-
const
|
|
1715
|
-
const
|
|
1737
|
+
const baselineSurface = structuredClone(opts.baselineSurface);
|
|
1738
|
+
const costLedger = opts.costLedger ?? createRunCostLedger({
|
|
1716
1739
|
storage,
|
|
1717
|
-
runDir: `${resolvedRunDir}/
|
|
1740
|
+
runDir: `${resolvedRunDir}/cost`,
|
|
1718
1741
|
costCeilingUsd: opts.costCeiling
|
|
1719
1742
|
});
|
|
1720
|
-
const scoreOnTest = async (surface, tag) => {
|
|
1743
|
+
const scoreOnTest = async (surface, tag, costPhase) => {
|
|
1744
|
+
const measuredSurface = structuredClone(surface);
|
|
1721
1745
|
const campaign = await runCampaign({
|
|
1722
1746
|
...opts,
|
|
1723
1747
|
storage,
|
|
1724
|
-
costLedger
|
|
1725
|
-
costPhase
|
|
1748
|
+
costLedger,
|
|
1749
|
+
costPhase,
|
|
1726
1750
|
scenarios: opts.testScenarios.map((scenario) => structuredClone(scenario)),
|
|
1727
|
-
dispatch: (scenario, ctx) => opts.dispatchWithSurface(
|
|
1751
|
+
dispatch: (scenario, ctx) => opts.dispatchWithSurface(structuredClone(measuredSurface), scenario, ctx),
|
|
1752
|
+
dispatchRef: finalDispatchRef(opts, measuredSurface),
|
|
1728
1753
|
runDir: `${resolvedRunDir}/${tag}`
|
|
1729
1754
|
});
|
|
1730
1755
|
const byScenario = {};
|
|
@@ -1745,22 +1770,50 @@ async function compareOptimizationMethods(opts) {
|
|
|
1745
1770
|
}
|
|
1746
1771
|
return scenarioIds.map((id) => byScenario[id]);
|
|
1747
1772
|
};
|
|
1773
|
+
const optimizationOwner = new AbortController();
|
|
1748
1774
|
const optimized = await mapConcurrent(opts.methods, optimizationConcurrency, async (method) => {
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1775
|
+
try {
|
|
1776
|
+
const out = await method.optimize(
|
|
1777
|
+
createOptimizationMethodInput(
|
|
1778
|
+
opts,
|
|
1779
|
+
method.name,
|
|
1780
|
+
resolvedRunDir,
|
|
1781
|
+
seed,
|
|
1782
|
+
baselineSurface,
|
|
1783
|
+
costLedger,
|
|
1784
|
+
optimizationOwner.signal
|
|
1785
|
+
)
|
|
1786
|
+
);
|
|
1787
|
+
assertOptimizationResult(method.name, out);
|
|
1788
|
+
const winnerSurface = structuredClone(out.winnerSurface);
|
|
1789
|
+
return {
|
|
1790
|
+
name: method.name,
|
|
1791
|
+
winnerSurface,
|
|
1792
|
+
cost: out.cost,
|
|
1793
|
+
durationMs: out.durationMs,
|
|
1794
|
+
provenance: out.provenance
|
|
1795
|
+
};
|
|
1796
|
+
} catch (error) {
|
|
1797
|
+
if (!optimizationOwner.signal.aborted) optimizationOwner.abort(error);
|
|
1798
|
+
throw error;
|
|
1799
|
+
}
|
|
1761
1800
|
});
|
|
1762
|
-
|
|
1763
|
-
|
|
1801
|
+
assertReportedCostWithinCeiling(
|
|
1802
|
+
combineCosts(
|
|
1803
|
+
optimized.map((result) => ({
|
|
1804
|
+
label: `method '${result.name}'`,
|
|
1805
|
+
cost: result.cost
|
|
1806
|
+
}))
|
|
1807
|
+
).totalCostUsd,
|
|
1808
|
+
opts.costCeiling,
|
|
1809
|
+
"optimization"
|
|
1810
|
+
);
|
|
1811
|
+
const testCostPhase = finalCostPhase(opts, baselineSurface, optimized, seed);
|
|
1812
|
+
const baselineArr = align(
|
|
1813
|
+
await scoreOnTest(baselineSurface, "test/baseline", testCostPhase),
|
|
1814
|
+
"baseline"
|
|
1815
|
+
);
|
|
1816
|
+
const testScoresBySurface = /* @__PURE__ */ new Map([[surfaceContentHash(baselineSurface), baselineArr]]);
|
|
1764
1817
|
const winners = [];
|
|
1765
1818
|
for (const winner of optimized) {
|
|
1766
1819
|
const surfaceKey = surfaceContentHash(winner.winnerSurface);
|
|
@@ -1768,7 +1821,8 @@ async function compareOptimizationMethods(opts) {
|
|
|
1768
1821
|
if (!arr) {
|
|
1769
1822
|
const byScenario = await scoreOnTest(
|
|
1770
1823
|
winner.winnerSurface,
|
|
1771
|
-
`test/methods/${slug(winner.name)}
|
|
1824
|
+
`test/methods/${slug(winner.name)}`,
|
|
1825
|
+
testCostPhase
|
|
1772
1826
|
);
|
|
1773
1827
|
arr = align(byScenario, `method "${winner.name}"`);
|
|
1774
1828
|
testScoresBySurface.set(surfaceKey, arr);
|
|
@@ -1798,7 +1852,7 @@ async function compareOptimizationMethods(opts) {
|
|
|
1798
1852
|
winnerComposite: w.arr[index],
|
|
1799
1853
|
lift: w.arr[index] - baselineArr[index]
|
|
1800
1854
|
})),
|
|
1801
|
-
winnerSurface: w.winnerSurface,
|
|
1855
|
+
winnerSurface: structuredClone(w.winnerSurface),
|
|
1802
1856
|
rank: 0
|
|
1803
1857
|
};
|
|
1804
1858
|
if (w.durationMs !== void 0) score.durationMs = w.durationMs;
|
|
@@ -1843,11 +1897,12 @@ async function compareOptimizationMethods(opts) {
|
|
|
1843
1897
|
const optimizationCost = combineCosts(
|
|
1844
1898
|
scores.map((score) => ({ label: `method '${score.name}'`, cost: score.optimizationCost }))
|
|
1845
1899
|
);
|
|
1846
|
-
const testCost = costFromLedgerSummary(
|
|
1900
|
+
const testCost = costFromLedgerSummary(costLedger.summary({ phase: testCostPhase }));
|
|
1847
1901
|
const totalCost = combineCosts([
|
|
1848
1902
|
{ label: "optimization", cost: optimizationCost },
|
|
1849
1903
|
{ label: "final test", cost: testCost }
|
|
1850
1904
|
]);
|
|
1905
|
+
assertReportedCostWithinCeiling(totalCost.totalCostUsd, opts.costCeiling, "total");
|
|
1851
1906
|
return {
|
|
1852
1907
|
scores,
|
|
1853
1908
|
best,
|
|
@@ -1864,6 +1919,14 @@ async function compareOptimizationMethods(opts) {
|
|
|
1864
1919
|
reps: opts.reps ?? 1
|
|
1865
1920
|
};
|
|
1866
1921
|
}
|
|
1922
|
+
function assertReportedCostWithinCeiling(totalCostUsd, costCeiling, phase) {
|
|
1923
|
+
const tolerance = Number.EPSILON * Math.max(1, Math.abs(totalCostUsd), Math.abs(costCeiling ?? 0)) * 8;
|
|
1924
|
+
if (costCeiling !== void 0 && totalCostUsd > costCeiling + tolerance) {
|
|
1925
|
+
throw new Error(
|
|
1926
|
+
`compareOptimizationMethods: reported ${phase} cost ${totalCostUsd} exceeds costCeiling ${costCeiling}`
|
|
1927
|
+
);
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1867
1930
|
function assertOptimizationMethods(methods) {
|
|
1868
1931
|
if (!Array.isArray(methods) || methods.length === 0) {
|
|
1869
1932
|
throw new Error("compareOptimizationMethods: no methods to compare");
|
|
@@ -1961,12 +2024,22 @@ function assertOptimizationProvenance(methodName, value) {
|
|
|
1961
2024
|
}
|
|
1962
2025
|
}
|
|
1963
2026
|
function assertComparisonControls(opts, seed, resamples, confidence) {
|
|
2027
|
+
if (opts.optimizationRunOptions && "costCeiling" in opts.optimizationRunOptions) {
|
|
2028
|
+
throw new Error(
|
|
2029
|
+
"compareOptimizationMethods: optimizationRunOptions.costCeiling is not supported; costCeiling covers optimization and final scoring"
|
|
2030
|
+
);
|
|
2031
|
+
}
|
|
1964
2032
|
if (!opts.judges || opts.judges.length === 0) {
|
|
1965
2033
|
throw new Error("compareOptimizationMethods: at least one judge is required");
|
|
1966
2034
|
}
|
|
1967
2035
|
if (typeof opts.dispatchWithSurface !== "function") {
|
|
1968
2036
|
throw new Error("compareOptimizationMethods: dispatchWithSurface must be a function");
|
|
1969
2037
|
}
|
|
2038
|
+
if (opts.dispatchRef !== void 0 && (typeof opts.dispatchRef !== "string" || opts.dispatchRef.trim().length === 0 || opts.dispatchRef.trim() !== opts.dispatchRef)) {
|
|
2039
|
+
throw new Error(
|
|
2040
|
+
"compareOptimizationMethods: dispatchRef must be trimmed and non-empty when provided"
|
|
2041
|
+
);
|
|
2042
|
+
}
|
|
1970
2043
|
try {
|
|
1971
2044
|
surfaceContentHash(opts.baselineSurface);
|
|
1972
2045
|
} catch (cause) {
|
|
@@ -2112,9 +2185,8 @@ function minimumBootstrapResamples(confidence, comparisonCount) {
|
|
|
2112
2185
|
const exact = 2 * comparisonCount / (1 - confidence);
|
|
2113
2186
|
return Math.ceil(exact - Number.EPSILON * Math.max(1, exact) * 32);
|
|
2114
2187
|
}
|
|
2115
|
-
function createOptimizationMethodInput(opts, methodName, resolvedRunDir, seed) {
|
|
2188
|
+
function createOptimizationMethodInput(opts, methodName, resolvedRunDir, seed, baselineSurface, costLedger, optimizationSignal) {
|
|
2116
2189
|
const methodRunDir = `${resolvedRunDir}/optimization/${slug(methodName)}`;
|
|
2117
|
-
const storage = opts.storage ?? fsCampaignStorage();
|
|
2118
2190
|
const cloneScenarios = (scenarios) => Object.freeze(scenarios.map((scenario) => structuredClone(scenario)));
|
|
2119
2191
|
const judges = opts.judges.map(
|
|
2120
2192
|
(judge) => Object.freeze({
|
|
@@ -2124,22 +2196,54 @@ function createOptimizationMethodInput(opts, methodName, resolvedRunDir, seed) {
|
|
|
2124
2196
|
)
|
|
2125
2197
|
})
|
|
2126
2198
|
);
|
|
2199
|
+
const signal = combineAbortSignals(
|
|
2200
|
+
opts.signal,
|
|
2201
|
+
opts.optimizationRunOptions?.signal,
|
|
2202
|
+
optimizationSignal
|
|
2203
|
+
);
|
|
2127
2204
|
return Object.freeze({
|
|
2128
|
-
baselineSurface: structuredClone(
|
|
2205
|
+
baselineSurface: structuredClone(baselineSurface),
|
|
2129
2206
|
trainScenarios: cloneScenarios(opts.trainScenarios),
|
|
2130
2207
|
selectionScenarios: cloneScenarios(opts.selectionScenarios),
|
|
2131
2208
|
dispatchWithSurface: opts.dispatchWithSurface,
|
|
2132
2209
|
judges: Object.freeze(judges),
|
|
2133
2210
|
runDir: methodRunDir,
|
|
2134
2211
|
seed,
|
|
2135
|
-
runOptions: Object.freeze({
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
})
|
|
2212
|
+
runOptions: Object.freeze({
|
|
2213
|
+
...opts.optimizationRunOptions ?? {},
|
|
2214
|
+
...signal ? { signal } : {}
|
|
2215
|
+
}),
|
|
2216
|
+
costLedger
|
|
2141
2217
|
});
|
|
2142
2218
|
}
|
|
2219
|
+
function finalCostPhase(opts, baselineSurface, winners, seed) {
|
|
2220
|
+
const identity = contentHash({
|
|
2221
|
+
baseline: surfaceContentHash(baselineSurface),
|
|
2222
|
+
winners: winners.map((winner) => ({
|
|
2223
|
+
name: winner.name,
|
|
2224
|
+
surface: surfaceContentHash(winner.winnerSurface)
|
|
2225
|
+
})),
|
|
2226
|
+
testScenarios: opts.testScenarios,
|
|
2227
|
+
judges: opts.judges.map((judge) => ({
|
|
2228
|
+
name: judge.name,
|
|
2229
|
+
dimensions: judge.dimensions,
|
|
2230
|
+
version: judge.judgeVersion ?? contentHash({
|
|
2231
|
+
score: judge.score.toString(),
|
|
2232
|
+
appliesTo: judge.appliesTo?.toString() ?? null
|
|
2233
|
+
})
|
|
2234
|
+
})),
|
|
2235
|
+
dispatch: callerDispatchRef(opts),
|
|
2236
|
+
seed,
|
|
2237
|
+
reps: opts.reps ?? 1
|
|
2238
|
+
});
|
|
2239
|
+
return `compareOptimizationMethods.test:${identity}`;
|
|
2240
|
+
}
|
|
2241
|
+
function finalDispatchRef(opts, surface) {
|
|
2242
|
+
return `compareOptimizationMethods:${callerDispatchRef(opts)}:${surfaceContentHash(surface)}`;
|
|
2243
|
+
}
|
|
2244
|
+
function callerDispatchRef(opts) {
|
|
2245
|
+
return (opts.dispatchRef ?? opts.dispatchWithSurface.name) || "anonymous";
|
|
2246
|
+
}
|
|
2143
2247
|
function costFromLedgerSummary(summary) {
|
|
2144
2248
|
const cost = {
|
|
2145
2249
|
totalCostUsd: summary.totalCostUsd,
|
|
@@ -2384,6 +2488,7 @@ function sendJson(response, status, body) {
|
|
|
2384
2488
|
var MAX_CALLBACK_BODY_BYTES = 1e6;
|
|
2385
2489
|
async function startExternalOptimizerCallback(args) {
|
|
2386
2490
|
assertCallbackConfig(args);
|
|
2491
|
+
args.signal?.throwIfAborted();
|
|
2387
2492
|
let evaluations = 0;
|
|
2388
2493
|
let accepting = true;
|
|
2389
2494
|
let closePromise;
|
|
@@ -2397,6 +2502,7 @@ async function startExternalOptimizerCallback(args) {
|
|
|
2397
2502
|
const controller = new AbortController();
|
|
2398
2503
|
const abortRequest = () => {
|
|
2399
2504
|
request.destroy();
|
|
2505
|
+
response.destroy();
|
|
2400
2506
|
};
|
|
2401
2507
|
activeControllers.add(controller);
|
|
2402
2508
|
controller.signal.addEventListener("abort", abortRequest, { once: true });
|
|
@@ -2419,16 +2525,23 @@ async function startExternalOptimizerCallback(args) {
|
|
|
2419
2525
|
void handler.catch(() => void 0);
|
|
2420
2526
|
});
|
|
2421
2527
|
const port = await listenLocal(server);
|
|
2528
|
+
const close = () => {
|
|
2529
|
+
closePromise ??= closeCallbackServer();
|
|
2530
|
+
return closePromise;
|
|
2531
|
+
};
|
|
2532
|
+
const onAbort = () => {
|
|
2533
|
+
void close().catch(() => void 0);
|
|
2534
|
+
};
|
|
2535
|
+
args.signal?.addEventListener("abort", onAbort, { once: true });
|
|
2536
|
+
if (args.signal?.aborted) onAbort();
|
|
2422
2537
|
return {
|
|
2423
2538
|
url: `http://127.0.0.1:${port}/evaluate`,
|
|
2424
2539
|
token: args.token,
|
|
2425
2540
|
evaluations: () => evaluations,
|
|
2426
|
-
close
|
|
2427
|
-
closePromise ??= closeCallbackServer();
|
|
2428
|
-
return closePromise;
|
|
2429
|
-
}
|
|
2541
|
+
close
|
|
2430
2542
|
};
|
|
2431
2543
|
async function closeCallbackServer() {
|
|
2544
|
+
args.signal?.removeEventListener("abort", onAbort);
|
|
2432
2545
|
accepting = false;
|
|
2433
2546
|
const closingServer = closeServer(server);
|
|
2434
2547
|
server.closeIdleConnections?.();
|
|
@@ -2525,6 +2638,7 @@ import { createServer as createServer2 } from "http";
|
|
|
2525
2638
|
var MODEL_PROXY_PATHS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
|
|
2526
2639
|
async function startExternalOptimizerModelProxy(args) {
|
|
2527
2640
|
assertModelProxyConfig(args);
|
|
2641
|
+
args.signal?.throwIfAborted();
|
|
2528
2642
|
const token = randomLocalToken();
|
|
2529
2643
|
const fetchImpl = args.fetchImpl ?? fetch;
|
|
2530
2644
|
let requestCount = 0;
|
|
@@ -2544,6 +2658,7 @@ async function startExternalOptimizerModelProxy(args) {
|
|
|
2544
2658
|
const controller = new AbortController();
|
|
2545
2659
|
const abortRequest = () => {
|
|
2546
2660
|
request.destroy();
|
|
2661
|
+
response.destroy();
|
|
2547
2662
|
};
|
|
2548
2663
|
activeControllers.add(controller);
|
|
2549
2664
|
controller.signal.addEventListener("abort", abortRequest, { once: true });
|
|
@@ -2583,17 +2698,24 @@ async function startExternalOptimizerModelProxy(args) {
|
|
|
2583
2698
|
void handler.catch(() => void 0);
|
|
2584
2699
|
});
|
|
2585
2700
|
const port = await listenLocal(server);
|
|
2701
|
+
const close = () => {
|
|
2702
|
+
closePromise ??= closeModelProxy();
|
|
2703
|
+
return closePromise;
|
|
2704
|
+
};
|
|
2705
|
+
const onAbort = () => {
|
|
2706
|
+
void close().catch(() => void 0);
|
|
2707
|
+
};
|
|
2708
|
+
args.signal?.addEventListener("abort", onAbort, { once: true });
|
|
2709
|
+
if (args.signal?.aborted) onAbort();
|
|
2586
2710
|
return {
|
|
2587
2711
|
baseUrl: `http://127.0.0.1:${port}/v1`,
|
|
2588
2712
|
apiKey: token,
|
|
2589
2713
|
requestAttempts: () => requestCount,
|
|
2590
2714
|
successfulCompletions: () => successfulCompletionCount,
|
|
2591
|
-
close
|
|
2592
|
-
closePromise ??= closeModelProxy();
|
|
2593
|
-
return closePromise;
|
|
2594
|
-
}
|
|
2715
|
+
close
|
|
2595
2716
|
};
|
|
2596
2717
|
async function closeModelProxy() {
|
|
2718
|
+
args.signal?.removeEventListener("abort", onAbort);
|
|
2597
2719
|
accepting = false;
|
|
2598
2720
|
const closingServer = closeServer(server);
|
|
2599
2721
|
server.closeIdleConnections?.();
|
|
@@ -3041,6 +3163,7 @@ async function runExternalOptimizerProcess(args) {
|
|
|
3041
3163
|
`${args.label} requires POSIX process-group cleanup; run the optimizer through WSL or Linux`
|
|
3042
3164
|
);
|
|
3043
3165
|
}
|
|
3166
|
+
throwIfAborted(args.signal, args.label);
|
|
3044
3167
|
const dir = await mkdtemp(join2(tmpdir2(), args.tempPrefix));
|
|
3045
3168
|
const inputPath = join2(dir, "input.json");
|
|
3046
3169
|
const outputPath = join2(dir, "output.json");
|
|
@@ -3074,11 +3197,14 @@ async function runExternalOptimizerProcess(args) {
|
|
|
3074
3197
|
args: commandArgs,
|
|
3075
3198
|
cwd: dir,
|
|
3076
3199
|
env: args.runner?.env,
|
|
3077
|
-
timeoutMs: args.timeoutMs
|
|
3200
|
+
timeoutMs: args.timeoutMs,
|
|
3201
|
+
signal: args.signal
|
|
3078
3202
|
});
|
|
3203
|
+
throwIfAborted(args.signal, args.label);
|
|
3079
3204
|
const raw = JSON.parse(
|
|
3080
3205
|
await readBoundedTextFile(outputPath, MAX_PROCESS_RESULT_BYTES, `${args.label} output`)
|
|
3081
3206
|
);
|
|
3207
|
+
throwIfAborted(args.signal, args.label);
|
|
3082
3208
|
if (!isRecord(raw)) throw new Error(`${args.label} output must be a JSON object`);
|
|
3083
3209
|
return raw;
|
|
3084
3210
|
},
|
|
@@ -3106,6 +3232,7 @@ async function readBoundedTextFile(path, maxBytes, label) {
|
|
|
3106
3232
|
}
|
|
3107
3233
|
}
|
|
3108
3234
|
function runProcess(args) {
|
|
3235
|
+
throwIfAborted(args.signal, args.label);
|
|
3109
3236
|
return new Promise((resolvePromise, reject) => {
|
|
3110
3237
|
const child = spawn(args.command, args.args, {
|
|
3111
3238
|
cwd: args.cwd,
|
|
@@ -3118,10 +3245,12 @@ function runProcess(args) {
|
|
|
3118
3245
|
const stderr = createProcessOutputCapture();
|
|
3119
3246
|
let settled = false;
|
|
3120
3247
|
let timeout;
|
|
3248
|
+
const onAbort = () => finish(abortReason(args.signal, args.label));
|
|
3121
3249
|
const finish = (error) => {
|
|
3122
3250
|
if (settled) return;
|
|
3123
3251
|
settled = true;
|
|
3124
3252
|
if (timeout) clearTimeout(timeout);
|
|
3253
|
+
args.signal?.removeEventListener("abort", onAbort);
|
|
3125
3254
|
void terminateProcessTree(child).then(
|
|
3126
3255
|
() => {
|
|
3127
3256
|
if (error) reject(error);
|
|
@@ -3149,6 +3278,8 @@ function runProcess(args) {
|
|
|
3149
3278
|
timeout = setTimeout(() => {
|
|
3150
3279
|
finish(new Error(`${args.label} exceeded ${args.timeoutMs}ms`));
|
|
3151
3280
|
}, args.timeoutMs);
|
|
3281
|
+
args.signal?.addEventListener("abort", onAbort, { once: true });
|
|
3282
|
+
if (args.signal?.aborted) onAbort();
|
|
3152
3283
|
child.stdout.on("data", (chunk) => {
|
|
3153
3284
|
appendProcessOutput(stdout, chunk);
|
|
3154
3285
|
});
|
|
@@ -3171,6 +3302,12 @@ function runProcess(args) {
|
|
|
3171
3302
|
});
|
|
3172
3303
|
});
|
|
3173
3304
|
}
|
|
3305
|
+
function throwIfAborted(signal, label) {
|
|
3306
|
+
if (signal?.aborted) throw abortReason(signal, label);
|
|
3307
|
+
}
|
|
3308
|
+
function abortReason(signal, label) {
|
|
3309
|
+
return signal.reason instanceof Error ? signal.reason : new Error(`${label} aborted`, { cause: signal.reason });
|
|
3310
|
+
}
|
|
3174
3311
|
function safeProcessEnvironment() {
|
|
3175
3312
|
const allowed = [
|
|
3176
3313
|
"PATH",
|
|
@@ -4912,7 +5049,8 @@ async function inspectExternalOptimizerRuntime(args) {
|
|
|
4912
5049
|
engineModules: [...args.engineModules ?? []]
|
|
4913
5050
|
},
|
|
4914
5051
|
...args.runner ? { runner: args.runner } : {},
|
|
4915
|
-
timeoutMs: args.timeoutMs
|
|
5052
|
+
timeoutMs: args.timeoutMs,
|
|
5053
|
+
...args.signal ? { signal: args.signal } : {}
|
|
4916
5054
|
});
|
|
4917
5055
|
assertExternalOptimizerRuntimeIdentity(result.runtime, args.package, args.label);
|
|
4918
5056
|
return result.runtime;
|
|
@@ -5311,6 +5449,8 @@ function gepaOptimizationMethod(config) {
|
|
|
5311
5449
|
return {
|
|
5312
5450
|
name,
|
|
5313
5451
|
async optimize(input) {
|
|
5452
|
+
const signal = input.runOptions.signal;
|
|
5453
|
+
signal?.throwIfAborted();
|
|
5314
5454
|
if (typeof input.baselineSurface !== "string" && input.baselineSurface.kind !== "components") {
|
|
5315
5455
|
throw new Error(`${name}: GEPA bridge supports text and component surfaces`);
|
|
5316
5456
|
}
|
|
@@ -5337,7 +5477,8 @@ function gepaOptimizationMethod(config) {
|
|
|
5337
5477
|
module: "agent_eval_rpc.gepa_bridge",
|
|
5338
5478
|
engineModules: config.engineModules,
|
|
5339
5479
|
...bridgeRunner ? { runner: bridgeRunner } : {},
|
|
5340
|
-
timeoutMs: config.timeoutMs ?? GEPA_DEFAULT_TIMEOUT_MS
|
|
5480
|
+
timeoutMs: config.timeoutMs ?? GEPA_DEFAULT_TIMEOUT_MS,
|
|
5481
|
+
...signal ? { signal } : {}
|
|
5341
5482
|
});
|
|
5342
5483
|
const seedCandidate = encodeExternalTextCandidate(input.baselineSurface);
|
|
5343
5484
|
const trainSet = input.trainScenarios.map(
|
|
@@ -5408,7 +5549,8 @@ function gepaOptimizationMethod(config) {
|
|
|
5408
5549
|
token: randomBytes3(32).toString("hex"),
|
|
5409
5550
|
maxEvaluations: evaluationLimit,
|
|
5410
5551
|
acceptEvaluation: () => runBudget.acceptEvaluation(),
|
|
5411
|
-
evaluate
|
|
5552
|
+
evaluate,
|
|
5553
|
+
...signal ? { signal } : {}
|
|
5412
5554
|
});
|
|
5413
5555
|
const runnerEnv = bridgeRunner?.env ?? {};
|
|
5414
5556
|
let modelProxy;
|
|
@@ -5438,7 +5580,8 @@ function gepaOptimizationMethod(config) {
|
|
|
5438
5580
|
initialUsage: {
|
|
5439
5581
|
requests: priorOptimizerUsage.totalCalls,
|
|
5440
5582
|
costUsd: priorOptimizerUsage.totalCostUsd
|
|
5441
|
-
}
|
|
5583
|
+
},
|
|
5584
|
+
...signal ? { signal } : {}
|
|
5442
5585
|
});
|
|
5443
5586
|
}
|
|
5444
5587
|
const outputDir2 = `${runDir}/external`;
|
|
@@ -5481,12 +5624,14 @@ function gepaOptimizationMethod(config) {
|
|
|
5481
5624
|
...bridgeRunner,
|
|
5482
5625
|
env: removeCredentialEnvironment(runnerEnv)
|
|
5483
5626
|
} : bridgeRunner,
|
|
5484
|
-
timeoutMs: config.timeoutMs ?? GEPA_DEFAULT_TIMEOUT_MS
|
|
5627
|
+
timeoutMs: config.timeoutMs ?? GEPA_DEFAULT_TIMEOUT_MS,
|
|
5628
|
+
...signal ? { signal } : {}
|
|
5485
5629
|
});
|
|
5486
5630
|
return { result: result2, outputDir: outputDir2 };
|
|
5487
5631
|
},
|
|
5488
5632
|
cleanup: closeResources
|
|
5489
5633
|
});
|
|
5634
|
+
signal?.throwIfAborted();
|
|
5490
5635
|
assertGepaBridgeOutput(
|
|
5491
5636
|
result,
|
|
5492
5637
|
name,
|
|
@@ -5636,9 +5781,12 @@ async function runOptimization(opts) {
|
|
|
5636
5781
|
const generations = [];
|
|
5637
5782
|
const history = [];
|
|
5638
5783
|
let currentFindings = opts.findings ?? [];
|
|
5784
|
+
const selectionRankKey = opts.selectionRankKey ?? ((campaign) => [campaignMeanComposite(campaign)]);
|
|
5639
5785
|
let winnerSurface = opts.baselineSurface;
|
|
5640
5786
|
let winnerSurfaceHash = surfaceHash(opts.baselineSurface);
|
|
5641
5787
|
let winnerComposite = campaignMeanComposite(baselineCampaign);
|
|
5788
|
+
let winnerRankKey = selectionRankKey(baselineCampaign);
|
|
5789
|
+
assertFiniteRankKey(winnerRankKey, "selectionRankKey for baseline");
|
|
5642
5790
|
const baselineOutcome = toScoredSurfaceOutcome(
|
|
5643
5791
|
winnerSurfaceHash,
|
|
5644
5792
|
baselineCampaign,
|
|
@@ -5705,6 +5853,12 @@ async function runOptimization(opts) {
|
|
|
5705
5853
|
runDir: `${opts.runDir}/gen-${gen}/candidate-${i}`
|
|
5706
5854
|
});
|
|
5707
5855
|
const composite = campaignMeanComposite(campaign);
|
|
5856
|
+
const rankKey = selectionRankKey(campaign);
|
|
5857
|
+
assertFiniteRankKey(
|
|
5858
|
+
rankKey,
|
|
5859
|
+
`selectionRankKey for generation ${gen} candidate ${i}`,
|
|
5860
|
+
winnerRankKey.length
|
|
5861
|
+
);
|
|
5708
5862
|
const coverage = campaignCoverage(
|
|
5709
5863
|
campaign.cells,
|
|
5710
5864
|
opts.scenarios,
|
|
@@ -5718,6 +5872,7 @@ async function runOptimization(opts) {
|
|
|
5718
5872
|
rationale,
|
|
5719
5873
|
campaign,
|
|
5720
5874
|
composite,
|
|
5875
|
+
rankKey,
|
|
5721
5876
|
coverage
|
|
5722
5877
|
};
|
|
5723
5878
|
}
|
|
@@ -5732,16 +5887,17 @@ async function runOptimization(opts) {
|
|
|
5732
5887
|
}
|
|
5733
5888
|
surfaceResults.sort((a, b) => {
|
|
5734
5889
|
if (a.coverage.complete !== b.coverage.complete) return a.coverage.complete ? -1 : 1;
|
|
5735
|
-
return b.
|
|
5890
|
+
return compareRankKeys(b.rankKey, a.rankKey);
|
|
5736
5891
|
});
|
|
5737
5892
|
const eligibleResults = surfaceResults.filter((result) => result.coverage.complete);
|
|
5738
5893
|
const top = eligibleResults[0];
|
|
5739
|
-
const promoted = top && top.
|
|
5894
|
+
const promoted = top && compareRankKeys(top.rankKey, winnerRankKey) > 0 ? [top] : [];
|
|
5740
5895
|
if (promoted[0]) {
|
|
5741
5896
|
const top2 = promoted[0];
|
|
5742
5897
|
winnerSurface = top2.surface;
|
|
5743
5898
|
winnerSurfaceHash = top2.surfaceHash;
|
|
5744
5899
|
winnerComposite = top2.composite;
|
|
5900
|
+
winnerRankKey = top2.rankKey;
|
|
5745
5901
|
winnerOutcome = toScoredSurfaceOutcome(top2.surfaceHash, top2.campaign, top2.coverage, gen);
|
|
5746
5902
|
winnerLabel = top2.label || void 0;
|
|
5747
5903
|
winnerRationale = top2.rationale || void 0;
|
|
@@ -6840,6 +6996,8 @@ function skillOptOptimizationMethod(config) {
|
|
|
6840
6996
|
return {
|
|
6841
6997
|
name,
|
|
6842
6998
|
async optimize(input) {
|
|
6999
|
+
const signal = input.runOptions.signal;
|
|
7000
|
+
signal?.throwIfAborted();
|
|
6843
7001
|
if (typeof input.baselineSurface !== "string") {
|
|
6844
7002
|
throw new Error(`${name}: SkillOpt requires a string baselineSurface`);
|
|
6845
7003
|
}
|
|
@@ -6861,7 +7019,8 @@ function skillOptOptimizationMethod(config) {
|
|
|
6861
7019
|
package: "skillopt",
|
|
6862
7020
|
module: "agent_eval_rpc.skillopt_bridge",
|
|
6863
7021
|
...bridgeRunner ? { runner: bridgeRunner } : {},
|
|
6864
|
-
timeoutMs: config.timeoutMs ?? SKILLOPT_DEFAULT_TIMEOUT_MS
|
|
7022
|
+
timeoutMs: config.timeoutMs ?? SKILLOPT_DEFAULT_TIMEOUT_MS,
|
|
7023
|
+
...signal ? { signal } : {}
|
|
6865
7024
|
});
|
|
6866
7025
|
const trainSet = input.trainScenarios.map(
|
|
6867
7026
|
(scenario) => describeExternalScenario(scenario, "SkillOpt", maxEvidenceChars, config.describeScenario)
|
|
@@ -6927,7 +7086,8 @@ function skillOptOptimizationMethod(config) {
|
|
|
6927
7086
|
token: randomBytes4(32).toString("hex"),
|
|
6928
7087
|
maxEvaluations: config.maxEvaluations,
|
|
6929
7088
|
acceptEvaluation: () => runBudget.acceptEvaluation(),
|
|
6930
|
-
evaluate
|
|
7089
|
+
evaluate,
|
|
7090
|
+
...signal ? { signal } : {}
|
|
6931
7091
|
});
|
|
6932
7092
|
const runnerEnv = bridgeRunner?.env ?? {};
|
|
6933
7093
|
let activeModelProxy;
|
|
@@ -6956,7 +7116,8 @@ function skillOptOptimizationMethod(config) {
|
|
|
6956
7116
|
initialUsage: {
|
|
6957
7117
|
requests: priorOptimizerUsage.totalCalls,
|
|
6958
7118
|
costUsd: priorOptimizerUsage.totalCostUsd
|
|
6959
|
-
}
|
|
7119
|
+
},
|
|
7120
|
+
...signal ? { signal } : {}
|
|
6960
7121
|
});
|
|
6961
7122
|
activeModelProxy = modelProxy2;
|
|
6962
7123
|
const outputDir2 = `${runDir}/external`;
|
|
@@ -6998,15 +7159,29 @@ function skillOptOptimizationMethod(config) {
|
|
|
6998
7159
|
OPTIMIZER_OPENAI_COMPATIBLE_BASE_URL: modelProxy2.baseUrl,
|
|
6999
7160
|
OPTIMIZER_OPENAI_COMPATIBLE_API_KEY: modelProxy2.apiKey,
|
|
7000
7161
|
TARGET_OPENAI_COMPATIBLE_BASE_URL: modelProxy2.baseUrl,
|
|
7001
|
-
TARGET_OPENAI_COMPATIBLE_API_KEY: modelProxy2.apiKey
|
|
7162
|
+
TARGET_OPENAI_COMPATIBLE_API_KEY: modelProxy2.apiKey,
|
|
7163
|
+
OPENAI_COMPATIBLE_MODEL: config.optimizer.model,
|
|
7164
|
+
OPENAI_COMPATIBLE_MAX_TOKENS: String(
|
|
7165
|
+
config.optimizer.budget.maxOutputTokensPerRequest
|
|
7166
|
+
),
|
|
7167
|
+
OPTIMIZER_OPENAI_COMPATIBLE_MODEL: config.optimizer.model,
|
|
7168
|
+
OPTIMIZER_OPENAI_COMPATIBLE_MAX_TOKENS: String(
|
|
7169
|
+
config.optimizer.budget.maxOutputTokensPerRequest
|
|
7170
|
+
),
|
|
7171
|
+
TARGET_OPENAI_COMPATIBLE_MODEL: config.optimizer.model,
|
|
7172
|
+
TARGET_OPENAI_COMPATIBLE_MAX_TOKENS: String(
|
|
7173
|
+
config.optimizer.budget.maxOutputTokensPerRequest
|
|
7174
|
+
)
|
|
7002
7175
|
}
|
|
7003
7176
|
},
|
|
7004
|
-
timeoutMs: config.timeoutMs ?? SKILLOPT_DEFAULT_TIMEOUT_MS
|
|
7177
|
+
timeoutMs: config.timeoutMs ?? SKILLOPT_DEFAULT_TIMEOUT_MS,
|
|
7178
|
+
...signal ? { signal } : {}
|
|
7005
7179
|
});
|
|
7006
7180
|
return { result: result2, outputDir: outputDir2, modelProxy: modelProxy2 };
|
|
7007
7181
|
},
|
|
7008
7182
|
cleanup: closeResources
|
|
7009
7183
|
});
|
|
7184
|
+
signal?.throwIfAborted();
|
|
7010
7185
|
assertSkillOptBridgeOutput(result, name, maxCandidateChars, config.maxEvaluations);
|
|
7011
7186
|
assertExternalOptimizerRunBinding({
|
|
7012
7187
|
label: name,
|
|
@@ -7106,6 +7281,7 @@ export {
|
|
|
7106
7281
|
buildReflectionPrompt,
|
|
7107
7282
|
parseReflectionResponse,
|
|
7108
7283
|
campaignMeanComposite,
|
|
7284
|
+
compareRankKeys,
|
|
7109
7285
|
campaignBreakdown,
|
|
7110
7286
|
assertCodeSurfaceIdentity,
|
|
7111
7287
|
assertComponentSurface,
|
|
@@ -7149,4 +7325,4 @@ export {
|
|
|
7149
7325
|
emitLoopProvenance,
|
|
7150
7326
|
skillOptOptimizationMethod
|
|
7151
7327
|
};
|
|
7152
|
-
//# sourceMappingURL=chunk-
|
|
7328
|
+
//# sourceMappingURL=chunk-7AN2E7BU.js.map
|