@tangle-network/agent-eval 0.83.0 → 0.85.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/belief-state/index.d.ts +82 -2
- package/dist/belief-state/index.js +293 -4
- package/dist/belief-state/index.js.map +1 -1
- package/dist/chunk-T4SQEITX.js +95 -0
- package/dist/chunk-T4SQEITX.js.map +1 -0
- package/dist/index.d.ts +192 -1
- package/dist/index.js +235 -7
- package/dist/index.js.map +1 -1
- package/dist/openapi.json +1 -1
- package/dist/runtime-trajectory-BLRiaifm.d.ts +49 -0
- package/docs/building-doctrine.md +42 -0
- package/docs/research/belief-state-agent-eval-roadmap.md +3 -0
- package/package.json +13 -26
package/dist/index.js
CHANGED
|
@@ -6,6 +6,10 @@ import {
|
|
|
6
6
|
parseCorrectnessResponse,
|
|
7
7
|
verifyCompletion
|
|
8
8
|
} from "./chunk-YGYXHNAQ.js";
|
|
9
|
+
import {
|
|
10
|
+
parseRuntimeTrajectoryHookEvent,
|
|
11
|
+
projectRuntimeTrajectoryEvidence
|
|
12
|
+
} from "./chunk-T4SQEITX.js";
|
|
9
13
|
import {
|
|
10
14
|
HoldoutAuditor,
|
|
11
15
|
canaryLeakView,
|
|
@@ -1747,6 +1751,107 @@ function canonicalize2(value) {
|
|
|
1747
1751
|
return out;
|
|
1748
1752
|
}
|
|
1749
1753
|
|
|
1754
|
+
// src/integrity/preflight.ts
|
|
1755
|
+
function stripSlash(url) {
|
|
1756
|
+
return url.replace(/\/+$/, "");
|
|
1757
|
+
}
|
|
1758
|
+
function errorMessage(body) {
|
|
1759
|
+
if (body == null || typeof body !== "object") return null;
|
|
1760
|
+
const b = body;
|
|
1761
|
+
if (b.error && typeof b.error.message === "string") return b.error.message;
|
|
1762
|
+
if (typeof b.message === "string") return b.message;
|
|
1763
|
+
return null;
|
|
1764
|
+
}
|
|
1765
|
+
async function preflightModels(opts) {
|
|
1766
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
1767
|
+
const baseUrl = stripSlash(opts.baseUrl);
|
|
1768
|
+
const authHeaders = { authorization: `Bearer ${opts.apiKey}` };
|
|
1769
|
+
let served;
|
|
1770
|
+
try {
|
|
1771
|
+
const res = await fetchImpl(`${baseUrl}/models`, { method: "GET", headers: authHeaders });
|
|
1772
|
+
if (!res.ok) {
|
|
1773
|
+
const text = await res.text().catch(() => "");
|
|
1774
|
+
return {
|
|
1775
|
+
succeeded: false,
|
|
1776
|
+
value: null,
|
|
1777
|
+
error: `preflightModels: GET ${baseUrl}/models \u2192 ${res.status} ${text.slice(0, 400)}`
|
|
1778
|
+
};
|
|
1779
|
+
}
|
|
1780
|
+
const body = await res.json();
|
|
1781
|
+
const ids = Array.isArray(body.data) ? body.data : [];
|
|
1782
|
+
served = new Set(ids.map((m) => m.id).filter((id) => typeof id === "string"));
|
|
1783
|
+
} catch (err) {
|
|
1784
|
+
return {
|
|
1785
|
+
succeeded: false,
|
|
1786
|
+
value: null,
|
|
1787
|
+
error: `preflightModels: GET ${baseUrl}/models failed \u2014 ${err instanceof Error ? err.message : String(err)}`
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
const results = [];
|
|
1791
|
+
for (const model of opts.models) {
|
|
1792
|
+
const listed = served.has(model);
|
|
1793
|
+
if (!opts.probe) {
|
|
1794
|
+
results.push({ model, listed, served: null, status: null, detail: null });
|
|
1795
|
+
continue;
|
|
1796
|
+
}
|
|
1797
|
+
try {
|
|
1798
|
+
const res = await fetchImpl(`${baseUrl}/chat/completions`, {
|
|
1799
|
+
method: "POST",
|
|
1800
|
+
headers: { ...authHeaders, "content-type": "application/json" },
|
|
1801
|
+
body: JSON.stringify({
|
|
1802
|
+
model,
|
|
1803
|
+
messages: [{ role: "user", content: "ping" }],
|
|
1804
|
+
max_tokens: 5
|
|
1805
|
+
})
|
|
1806
|
+
});
|
|
1807
|
+
let detail = null;
|
|
1808
|
+
if (!res.ok) {
|
|
1809
|
+
const body = await res.json().catch(() => null);
|
|
1810
|
+
detail = errorMessage(body);
|
|
1811
|
+
}
|
|
1812
|
+
results.push({ model, listed, served: res.ok, status: res.status, detail });
|
|
1813
|
+
} catch (err) {
|
|
1814
|
+
return {
|
|
1815
|
+
succeeded: false,
|
|
1816
|
+
value: null,
|
|
1817
|
+
error: `preflightModels: probe POST ${baseUrl}/chat/completions (model ${model}) failed \u2014 ${err instanceof Error ? err.message : String(err)}`
|
|
1818
|
+
};
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
return { succeeded: true, value: results, error: null };
|
|
1822
|
+
}
|
|
1823
|
+
var ModelsUnreachableError = class extends AgentEvalError {
|
|
1824
|
+
constructor(message, results) {
|
|
1825
|
+
super("config", message);
|
|
1826
|
+
this.results = results;
|
|
1827
|
+
this.name = "ModelsUnreachableError";
|
|
1828
|
+
}
|
|
1829
|
+
results;
|
|
1830
|
+
};
|
|
1831
|
+
function describeFailure(r) {
|
|
1832
|
+
if (!r.listed) {
|
|
1833
|
+
const probeNote = r.served === false ? ` (probe ${r.status}${r.detail ? `: ${r.detail}` : ""})` : "";
|
|
1834
|
+
return `${r.model}: not in /models${probeNote}`;
|
|
1835
|
+
}
|
|
1836
|
+
return `${r.model}: listed but probe ${r.status}${r.detail ? ` \u2014 ${r.detail}` : ""}`;
|
|
1837
|
+
}
|
|
1838
|
+
async function assertModelsServed(opts) {
|
|
1839
|
+
const outcome = await preflightModels(opts);
|
|
1840
|
+
if (!outcome.succeeded || outcome.value === null) {
|
|
1841
|
+
throw new ConfigError(
|
|
1842
|
+
outcome.error ?? "assertModelsServed: preflight failed without an error message"
|
|
1843
|
+
);
|
|
1844
|
+
}
|
|
1845
|
+
const dead = outcome.value.filter((r) => !r.listed || r.served === false);
|
|
1846
|
+
if (dead.length > 0) {
|
|
1847
|
+
throw new ModelsUnreachableError(
|
|
1848
|
+
`assertModelsServed: ${dead.length}/${outcome.value.length} model(s) unreachable on the router \u2014 ${dead.map(describeFailure).join("; ")}`,
|
|
1849
|
+
outcome.value
|
|
1850
|
+
);
|
|
1851
|
+
}
|
|
1852
|
+
return outcome.value;
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1750
1855
|
// src/integrity/single-backend.ts
|
|
1751
1856
|
var SingleBackendError = class extends AgentEvalError {
|
|
1752
1857
|
constructor(message, report) {
|
|
@@ -1756,7 +1861,7 @@ var SingleBackendError = class extends AgentEvalError {
|
|
|
1756
1861
|
}
|
|
1757
1862
|
report;
|
|
1758
1863
|
};
|
|
1759
|
-
function
|
|
1864
|
+
function stripSlash2(url) {
|
|
1760
1865
|
return url.replace(/\/+$/, "");
|
|
1761
1866
|
}
|
|
1762
1867
|
function assertSingleBackend(agent, judge, opts = {}) {
|
|
@@ -1764,7 +1869,7 @@ function assertSingleBackend(agent, judge, opts = {}) {
|
|
|
1764
1869
|
if (agent.kind !== judge.kind) {
|
|
1765
1870
|
divergences.push({ field: "kind", agent: agent.kind, judge: judge.kind });
|
|
1766
1871
|
}
|
|
1767
|
-
if (
|
|
1872
|
+
if (stripSlash2(agent.baseUrl) !== stripSlash2(judge.baseUrl)) {
|
|
1768
1873
|
divergences.push({ field: "baseUrl", agent: agent.baseUrl, judge: judge.baseUrl });
|
|
1769
1874
|
}
|
|
1770
1875
|
if (agent.model !== judge.model) {
|
|
@@ -2911,14 +3016,14 @@ async function runHarnessExperiment(config) {
|
|
|
2911
3016
|
const score = config.score ?? ((trace) => critic.scoreTrace(trace));
|
|
2912
3017
|
const results = await mapLimit(jobs, config.parallelism ?? 1, async (request) => {
|
|
2913
3018
|
const trace = await config.adapter.run(request);
|
|
2914
|
-
const
|
|
3019
|
+
const runScore3 = await score(trace, request);
|
|
2915
3020
|
const result = {
|
|
2916
3021
|
variant: request.variant,
|
|
2917
3022
|
scenario: request.scenario,
|
|
2918
3023
|
trialIndex: request.trialIndex,
|
|
2919
3024
|
trace,
|
|
2920
|
-
score:
|
|
2921
|
-
aggregate: aggregateRunScore(
|
|
3025
|
+
score: runScore3,
|
|
3026
|
+
aggregate: aggregateRunScore(runScore3, config.weights)
|
|
2922
3027
|
};
|
|
2923
3028
|
await config.onResult?.(result);
|
|
2924
3029
|
return result;
|
|
@@ -7089,6 +7194,121 @@ function createDefaultReviewer(options) {
|
|
|
7089
7194
|
};
|
|
7090
7195
|
}
|
|
7091
7196
|
|
|
7197
|
+
// src/description-length-gate.ts
|
|
7198
|
+
import { gzipSync } from "zlib";
|
|
7199
|
+
function runScore2(run) {
|
|
7200
|
+
const o = run.outcome;
|
|
7201
|
+
const s = o.holdoutScore ?? o.searchScore ?? o.raw?.score;
|
|
7202
|
+
return typeof s === "number" && Number.isFinite(s) ? s : void 0;
|
|
7203
|
+
}
|
|
7204
|
+
function taskKey(run) {
|
|
7205
|
+
return run.scenarioId ?? run.experimentId;
|
|
7206
|
+
}
|
|
7207
|
+
function perTaskMeanScore(runs) {
|
|
7208
|
+
const acc = /* @__PURE__ */ new Map();
|
|
7209
|
+
for (const run of runs) {
|
|
7210
|
+
const s = runScore2(run);
|
|
7211
|
+
if (s === void 0) continue;
|
|
7212
|
+
const key = taskKey(run);
|
|
7213
|
+
const cur = acc.get(key) ?? { sum: 0, n: 0 };
|
|
7214
|
+
cur.sum += s;
|
|
7215
|
+
cur.n += 1;
|
|
7216
|
+
acc.set(key, cur);
|
|
7217
|
+
}
|
|
7218
|
+
return new Map([...acc].map(([k, v]) => [k, v.sum / v.n]));
|
|
7219
|
+
}
|
|
7220
|
+
function modelDescriptionBits(content) {
|
|
7221
|
+
return gzipSync(Buffer.from(content, "utf8")).byteLength * 8;
|
|
7222
|
+
}
|
|
7223
|
+
function dataDescriptionBits(scoreByTask, keys, scoreFloor) {
|
|
7224
|
+
let bits = 0;
|
|
7225
|
+
for (const key of keys) {
|
|
7226
|
+
const s = scoreByTask.get(key);
|
|
7227
|
+
if (s === void 0) continue;
|
|
7228
|
+
bits += -Math.log2(Math.max(s, scoreFloor));
|
|
7229
|
+
}
|
|
7230
|
+
return bits;
|
|
7231
|
+
}
|
|
7232
|
+
var DescriptionLengthGate = class {
|
|
7233
|
+
baselineKey;
|
|
7234
|
+
lambda;
|
|
7235
|
+
marginBits;
|
|
7236
|
+
scoreFloor;
|
|
7237
|
+
minTasks;
|
|
7238
|
+
constructor(config) {
|
|
7239
|
+
if (!config.baselineKey) throw new Error("DescriptionLengthGate: baselineKey is required");
|
|
7240
|
+
this.baselineKey = config.baselineKey;
|
|
7241
|
+
this.lambda = config.lambda ?? 1;
|
|
7242
|
+
this.marginBits = config.marginBits ?? 0;
|
|
7243
|
+
this.scoreFloor = config.scoreFloor ?? 2 ** -10;
|
|
7244
|
+
this.minTasks = config.minTasks ?? 3;
|
|
7245
|
+
if (!(this.lambda >= 0)) throw new Error("DescriptionLengthGate: lambda must be \u2265 0");
|
|
7246
|
+
if (!(this.scoreFloor > 0 && this.scoreFloor < 1))
|
|
7247
|
+
throw new Error("DescriptionLengthGate: scoreFloor must be in (0,1)");
|
|
7248
|
+
}
|
|
7249
|
+
/** Decide whether `candidate` should replace `baseline`. Both are scored on
|
|
7250
|
+
* the shared task set (the enlarged evidence); the candidate promotes only
|
|
7251
|
+
* if λ·L_model + L_data is strictly lower by at least `marginBits`. */
|
|
7252
|
+
evaluate(candidate, baseline) {
|
|
7253
|
+
const candidateId = inferCandidateId(candidate.runs, this.baselineKey);
|
|
7254
|
+
const candScores = perTaskMeanScore(candidate.runs);
|
|
7255
|
+
const baseScores = perTaskMeanScore(baseline.runs);
|
|
7256
|
+
const shared = [...candScores.keys()].filter((k) => baseScores.has(k));
|
|
7257
|
+
const modelBits = {
|
|
7258
|
+
candidate: this.lambda * modelDescriptionBits(candidate.content),
|
|
7259
|
+
baseline: this.lambda * modelDescriptionBits(baseline.content)
|
|
7260
|
+
};
|
|
7261
|
+
const dataBits = {
|
|
7262
|
+
candidate: dataDescriptionBits(candScores, shared, this.scoreFloor),
|
|
7263
|
+
baseline: dataDescriptionBits(baseScores, shared, this.scoreFloor)
|
|
7264
|
+
};
|
|
7265
|
+
const totalBits = {
|
|
7266
|
+
candidate: modelBits.candidate + dataBits.candidate,
|
|
7267
|
+
baseline: modelBits.baseline + dataBits.baseline
|
|
7268
|
+
};
|
|
7269
|
+
const evidence = {
|
|
7270
|
+
tasks: shared.length,
|
|
7271
|
+
modelBits,
|
|
7272
|
+
dataBits,
|
|
7273
|
+
totalBits,
|
|
7274
|
+
deltaBits: totalBits.candidate - totalBits.baseline,
|
|
7275
|
+
modelBitsDelta: modelBits.candidate - modelBits.baseline,
|
|
7276
|
+
dataBitsDelta: dataBits.candidate - dataBits.baseline
|
|
7277
|
+
};
|
|
7278
|
+
const base = { candidateId, baselineId: this.baselineKey, evidence };
|
|
7279
|
+
const fmt2 = (n) => n.toFixed(1);
|
|
7280
|
+
if (shared.length < this.minTasks) {
|
|
7281
|
+
return {
|
|
7282
|
+
...base,
|
|
7283
|
+
promote: false,
|
|
7284
|
+
reason: `few_tasks: ${shared.length} shared task(s) < min ${this.minTasks}`,
|
|
7285
|
+
rejectionCode: "few_tasks"
|
|
7286
|
+
};
|
|
7287
|
+
}
|
|
7288
|
+
if (!(evidence.deltaBits < -this.marginBits)) {
|
|
7289
|
+
const code = evidence.dataBitsDelta < 0 ? "model_bloat" : "no_total_gain";
|
|
7290
|
+
const why = code === "model_bloat" ? `model grew ${fmt2(evidence.modelBitsDelta)} bits, outpacing a ${fmt2(-evidence.dataBitsDelta)}-bit data gain` : `outcomes did not improve (data \u0394=${fmt2(evidence.dataBitsDelta)} bits)`;
|
|
7291
|
+
return {
|
|
7292
|
+
...base,
|
|
7293
|
+
promote: false,
|
|
7294
|
+
reason: `${code}: total \u0394=${fmt2(evidence.deltaBits)} bits does not clear the ${fmt2(this.marginBits)}-bit margin \u2014 ${why}`,
|
|
7295
|
+
rejectionCode: code
|
|
7296
|
+
};
|
|
7297
|
+
}
|
|
7298
|
+
return {
|
|
7299
|
+
...base,
|
|
7300
|
+
promote: true,
|
|
7301
|
+
reason: `promote: total \u0394=${fmt2(evidence.deltaBits)} bits (model \u0394=${fmt2(evidence.modelBitsDelta)}, data \u0394=${fmt2(evidence.dataBitsDelta)}) over ${shared.length} tasks`,
|
|
7302
|
+
rejectionCode: null
|
|
7303
|
+
};
|
|
7304
|
+
}
|
|
7305
|
+
};
|
|
7306
|
+
function inferCandidateId(runs, baselineKey) {
|
|
7307
|
+
for (const run of runs)
|
|
7308
|
+
if (run.candidateId && run.candidateId !== baselineKey) return run.candidateId;
|
|
7309
|
+
return runs[0]?.candidateId ?? "(unknown candidate)";
|
|
7310
|
+
}
|
|
7311
|
+
|
|
7092
7312
|
// src/discover-personas.ts
|
|
7093
7313
|
import { promises as fs } from "fs";
|
|
7094
7314
|
import { basename, extname, join as join3 } from "path";
|
|
@@ -7240,7 +7460,7 @@ var HeldOutGate = class {
|
|
|
7240
7460
|
* the candidate run with the matching baseline run. Pairs without
|
|
7241
7461
|
* a holdout score on both sides are dropped. */
|
|
7242
7462
|
evaluate(candidate, baseline) {
|
|
7243
|
-
const candidateId =
|
|
7463
|
+
const candidateId = inferCandidateId2(candidate, this.baselineKey);
|
|
7244
7464
|
const baselineId = this.baselineKey;
|
|
7245
7465
|
const baselineHoldoutByKey = indexHoldoutByKey(baseline);
|
|
7246
7466
|
const beforeHoldout = [];
|
|
@@ -7343,7 +7563,7 @@ var HeldOutGate = class {
|
|
|
7343
7563
|
};
|
|
7344
7564
|
}
|
|
7345
7565
|
};
|
|
7346
|
-
function
|
|
7566
|
+
function inferCandidateId2(candidate, baselineKey) {
|
|
7347
7567
|
for (const run of candidate) {
|
|
7348
7568
|
if (run.candidateId && run.candidateId !== baselineKey) return run.candidateId;
|
|
7349
7569
|
}
|
|
@@ -8314,6 +8534,7 @@ export {
|
|
|
8314
8534
|
DEFAULT_TRACE_ANALYST_BUDGETS,
|
|
8315
8535
|
DEFAULT_TRACE_ANALYST_KINDS,
|
|
8316
8536
|
Dataset,
|
|
8537
|
+
DescriptionLengthGate,
|
|
8317
8538
|
DockerSandboxDriver,
|
|
8318
8539
|
DualAgentBench,
|
|
8319
8540
|
ERROR_COUNT_PATTERNS,
|
|
@@ -8342,6 +8563,7 @@ export {
|
|
|
8342
8563
|
LockedJsonlAppender,
|
|
8343
8564
|
MODEL_PRICING,
|
|
8344
8565
|
MetricsCollector,
|
|
8566
|
+
ModelsUnreachableError,
|
|
8345
8567
|
MultiLayerVerifier,
|
|
8346
8568
|
Mutex,
|
|
8347
8569
|
NoopRawProviderSink,
|
|
@@ -8401,6 +8623,7 @@ export {
|
|
|
8401
8623
|
asString,
|
|
8402
8624
|
assertCrossFamily,
|
|
8403
8625
|
assertLlmRoute,
|
|
8626
|
+
assertModelsServed,
|
|
8404
8627
|
assertRealBackend,
|
|
8405
8628
|
assertReleaseConfidence,
|
|
8406
8629
|
assertRunAgentProfileCell,
|
|
@@ -8485,6 +8708,7 @@ export {
|
|
|
8485
8708
|
createTraceAnalystKind,
|
|
8486
8709
|
crossTraceDiff,
|
|
8487
8710
|
crowdingDistance,
|
|
8711
|
+
dataDescriptionBits,
|
|
8488
8712
|
decideNextUserTurn,
|
|
8489
8713
|
decideReferenceReplayPromotion,
|
|
8490
8714
|
decideReferenceReplayRunPromotion,
|
|
@@ -8591,6 +8815,7 @@ export {
|
|
|
8591
8815
|
matchGoldens,
|
|
8592
8816
|
mergeLayerResults,
|
|
8593
8817
|
mergeSteeringBundle,
|
|
8818
|
+
modelDescriptionBits,
|
|
8594
8819
|
multiToolchainLayer,
|
|
8595
8820
|
nistAiRmfReport,
|
|
8596
8821
|
normalizeScores,
|
|
@@ -8613,16 +8838,19 @@ export {
|
|
|
8613
8838
|
parseGoldJsonl,
|
|
8614
8839
|
parseReflectionResponse,
|
|
8615
8840
|
parseRunRecordSafe,
|
|
8841
|
+
parseRuntimeTrajectoryHookEvent,
|
|
8616
8842
|
partialCredit,
|
|
8617
8843
|
passOrthogonality,
|
|
8618
8844
|
pixelDeltaRatio,
|
|
8619
8845
|
planTraceInsightQuestions,
|
|
8620
8846
|
politenessPrefixMutator,
|
|
8621
8847
|
positionalBias,
|
|
8848
|
+
preflightModels,
|
|
8622
8849
|
printDriverSummary,
|
|
8623
8850
|
probeLlm,
|
|
8624
8851
|
profile_exports as profile,
|
|
8625
8852
|
projectOtlpFlatLine,
|
|
8853
|
+
projectRuntimeTrajectoryEvidence,
|
|
8626
8854
|
promptBisect,
|
|
8627
8855
|
proposeAutomatedPullRequest,
|
|
8628
8856
|
proposeSynthesisTargets,
|