@tangle-network/agent-eval 0.125.0 → 0.126.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.
Files changed (82) hide show
  1. package/CHANGELOG.md +48 -35
  2. package/README.md +270 -189
  3. package/dist/analyst/index.d.ts +15 -145
  4. package/dist/analyst/index.js +33 -47
  5. package/dist/analyst/index.js.map +1 -1
  6. package/dist/benchmarks/index.d.ts +45 -162
  7. package/dist/benchmarks/index.js +8 -9
  8. package/dist/campaign/index.d.ts +3671 -5389
  9. package/dist/campaign/index.js +21 -95
  10. package/dist/{chunk-R226UZOI.js → chunk-474LBSOX.js} +2 -2
  11. package/dist/{chunk-W5B3ZGP3.js → chunk-4B7ZZHPX.js} +8 -6
  12. package/dist/{chunk-W5B3ZGP3.js.map → chunk-4B7ZZHPX.js.map} +1 -1
  13. package/dist/{chunk-DT7OXY3C.js → chunk-CM4OILD2.js} +535 -846
  14. package/dist/chunk-CM4OILD2.js.map +1 -0
  15. package/dist/{chunk-HM6V7F3M.js → chunk-FO7HEH76.js} +3 -3
  16. package/dist/chunk-IILEIWGW.js +635 -0
  17. package/dist/chunk-IILEIWGW.js.map +1 -0
  18. package/dist/{chunk-EQUK3RFS.js → chunk-J5SQWP6Y.js} +8 -5
  19. package/dist/chunk-J5SQWP6Y.js.map +1 -0
  20. package/dist/chunk-KO2PZOGP.js +4637 -0
  21. package/dist/chunk-KO2PZOGP.js.map +1 -0
  22. package/dist/chunk-NTOV7RU5.js +7152 -0
  23. package/dist/chunk-NTOV7RU5.js.map +1 -0
  24. package/dist/{chunk-QFQZ3U3X.js → chunk-OCFJACJU.js} +2 -2
  25. package/dist/{chunk-GID26AN4.js → chunk-P22LJ3Y2.js} +4 -6
  26. package/dist/{chunk-GID26AN4.js.map → chunk-P22LJ3Y2.js.map} +1 -1
  27. package/dist/{chunk-SJT4OBVL.js → chunk-SDPM6554.js} +3 -3
  28. package/dist/{chunk-D5JZ7UDZ.js → chunk-UCLVDLCH.js} +136 -50
  29. package/dist/chunk-UCLVDLCH.js.map +1 -0
  30. package/dist/chunk-UI4YMIN2.js +105 -0
  31. package/dist/chunk-UI4YMIN2.js.map +1 -0
  32. package/dist/{chunk-JKDNAOF5.js → chunk-W4L6C2XT.js} +2 -2
  33. package/dist/{chunk-GRCDRKII.js → chunk-WS3NZZQQ.js} +58 -20
  34. package/dist/chunk-WS3NZZQQ.js.map +1 -0
  35. package/dist/cli.js +3 -3
  36. package/dist/contract/index.d.ts +3221 -3094
  37. package/dist/contract/index.js +173 -42
  38. package/dist/contract/index.js.map +1 -1
  39. package/dist/control.js +2 -3
  40. package/dist/fuzz.d.ts +14 -1
  41. package/dist/fuzz.js +1 -1
  42. package/dist/hosted/index.d.ts +8 -1
  43. package/dist/index.d.ts +71 -687
  44. package/dist/index.js +178 -497
  45. package/dist/index.js.map +1 -1
  46. package/dist/openapi.json +1 -1
  47. package/dist/rl.d.ts +5 -100
  48. package/dist/rl.js +4 -5
  49. package/dist/rl.js.map +1 -1
  50. package/dist/{run-campaign-I3JXKVAK.js → run-campaign-LVFKZCEU.js} +3 -3
  51. package/dist/traces.js +2 -3
  52. package/dist/wire/index.d.ts +14 -1
  53. package/dist/wire/index.js +3 -3
  54. package/docs/campaign-proposers.md +363 -168
  55. package/docs/design/loop-taxonomy.md +142 -190
  56. package/docs/design.md +1 -1
  57. package/docs/distributed-driver.md +8 -11
  58. package/docs/feature-guide.md +20 -19
  59. package/docs/knowledge-readiness.md +2 -5
  60. package/docs/multi-shot-optimization.md +35 -27
  61. package/docs/rollout.md +5 -5
  62. package/package.json +4 -4
  63. package/dist/chunk-A62YMFWA.js +0 -9269
  64. package/dist/chunk-A62YMFWA.js.map +0 -1
  65. package/dist/chunk-A6GT67HT.js +0 -550
  66. package/dist/chunk-A6GT67HT.js.map +0 -1
  67. package/dist/chunk-D5JZ7UDZ.js.map +0 -1
  68. package/dist/chunk-DT7OXY3C.js.map +0 -1
  69. package/dist/chunk-EQUK3RFS.js.map +0 -1
  70. package/dist/chunk-GC4ATIKK.js +0 -317
  71. package/dist/chunk-GC4ATIKK.js.map +0 -1
  72. package/dist/chunk-GRCDRKII.js.map +0 -1
  73. package/dist/chunk-LOW3U7JZ.js +0 -328
  74. package/dist/chunk-LOW3U7JZ.js.map +0 -1
  75. package/dist/chunk-PMITBABE.js +0 -3841
  76. package/dist/chunk-PMITBABE.js.map +0 -1
  77. /package/dist/{chunk-R226UZOI.js.map → chunk-474LBSOX.js.map} +0 -0
  78. /package/dist/{chunk-HM6V7F3M.js.map → chunk-FO7HEH76.js.map} +0 -0
  79. /package/dist/{chunk-QFQZ3U3X.js.map → chunk-OCFJACJU.js.map} +0 -0
  80. /package/dist/{chunk-SJT4OBVL.js.map → chunk-SDPM6554.js.map} +0 -0
  81. /package/dist/{chunk-JKDNAOF5.js.map → chunk-W4L6C2XT.js.map} +0 -0
  82. /package/dist/{run-campaign-I3JXKVAK.js.map → run-campaign-LVFKZCEU.js.map} +0 -0
@@ -14,17 +14,19 @@ import {
14
14
  import {
15
15
  analyzeRuns,
16
16
  summarizeExecution
17
- } from "../chunk-SJT4OBVL.js";
17
+ } from "../chunk-SDPM6554.js";
18
18
  import {
19
19
  REFERENCE_EQUIVALENCE_INPUT_LIMITS,
20
20
  REFERENCE_EQUIVALENCE_JUDGE_VERSION,
21
+ assertOptimizationResult,
21
22
  buildEvidenceVector,
23
+ compareOptimizationMethods,
22
24
  composeGate,
23
25
  createReferenceEquivalenceJudge,
24
26
  defaultProductionGate,
25
27
  emitLoopProvenance,
26
- evolutionaryProposer,
27
- gepaProposer,
28
+ externalTextOptimizationMethod,
29
+ gepaOptimizationMethod,
28
30
  heldOutGate,
29
31
  heldoutSignificance,
30
32
  llmJudge,
@@ -35,9 +37,10 @@ import {
35
37
  runEval,
36
38
  runImprovementLoop,
37
39
  runReferenceEquivalenceJudge,
40
+ skillOptOptimizationMethod,
38
41
  surfaceContentHash,
39
42
  surfaceHash
40
- } from "../chunk-PMITBABE.js";
43
+ } from "../chunk-NTOV7RU5.js";
41
44
  import {
42
45
  campaignSplitDigest,
43
46
  createRunCostLedger,
@@ -45,24 +48,24 @@ import {
45
48
  inMemoryCampaignStorage,
46
49
  resolveRunDir,
47
50
  runCampaign
48
- } from "../chunk-D5JZ7UDZ.js";
51
+ } from "../chunk-UCLVDLCH.js";
49
52
  import {
50
53
  buildDefaultAnalystRegistry,
51
54
  createChatClient
52
- } from "../chunk-A6GT67HT.js";
55
+ } from "../chunk-CM4OILD2.js";
53
56
  import "../chunk-HHWE3POT.js";
54
- import "../chunk-DT7OXY3C.js";
57
+ import "../chunk-UI4YMIN2.js";
55
58
  import {
56
59
  FileSystemOutcomeStore,
57
60
  InMemoryOutcomeStore
58
61
  } from "../chunk-3RF76KTD.js";
59
62
  import "../chunk-ARU2PZFM.js";
60
- import "../chunk-EQUK3RFS.js";
63
+ import "../chunk-J5SQWP6Y.js";
61
64
  import "../chunk-DPZAEKA6.js";
62
65
  import {
63
66
  pairedBootstrap
64
67
  } from "../chunk-PJQFMIOX.js";
65
- import "../chunk-GRCDRKII.js";
68
+ import "../chunk-WS3NZZQQ.js";
66
69
  import "../chunk-VI2UW6B6.js";
67
70
  import {
68
71
  recordAggregateMeasurements,
@@ -75,9 +78,8 @@ import "../chunk-IR3KBHOY.js";
75
78
  import "../chunk-PC4UYEBM.js";
76
79
  import {
77
80
  parseRunRecordSafe
78
- } from "../chunk-LOW3U7JZ.js";
81
+ } from "../chunk-IILEIWGW.js";
79
82
  import "../chunk-MA6HLL3S.js";
80
- import "../chunk-GC4ATIKK.js";
81
83
  import "../chunk-VSMTAMNK.js";
82
84
  import "../chunk-ONWEPEDO.js";
83
85
  import {
@@ -98,16 +100,95 @@ var SelfImproveRunError = class extends Error {
98
100
  this.receipts = ledger.list();
99
101
  }
100
102
  };
101
- function splitTrainHoldout(scenarios, fraction) {
102
- function hash(s) {
103
- let h = 2166136261 >>> 0;
104
- for (let i = 0; i < s.length; i++) {
105
- h ^= s.charCodeAt(i);
106
- h = Math.imul(h, 16777619) >>> 0;
103
+ function assertSelfImproveSearchMode(opts) {
104
+ if (opts.method && opts.proposer) {
105
+ throw new Error("selfImprove: method and proposer are mutually exclusive");
106
+ }
107
+ if (!opts.method) {
108
+ if (opts.selectionScenarios !== void 0) {
109
+ throw new Error("selfImprove: selectionScenarios requires method");
110
+ }
111
+ return;
112
+ }
113
+ if (typeof opts.method.name !== "string" || !opts.method.name.trim() || opts.method.name.trim() !== opts.method.name || typeof opts.method.optimize !== "function") {
114
+ throw new Error("selfImprove: method must have a trimmed name and optimize(input)");
115
+ }
116
+ const budget = opts.budget;
117
+ if (budget?.generations !== void 0 && budget.generations !== 1) {
118
+ throw new Error("selfImprove: method owns its rounds; budget.generations must be 1 when set");
119
+ }
120
+ if (budget?.populationSize !== void 0 && budget.populationSize !== 1) {
121
+ throw new Error(
122
+ "selfImprove: method owns its candidates; budget.populationSize must be 1 when set"
123
+ );
124
+ }
125
+ if (budget?.candidateConcurrency !== void 0 || budget?.maxImprovementShots !== void 0 || opts.analyzeGeneration !== void 0 || opts.findings !== void 0) {
126
+ throw new Error(
127
+ "selfImprove: candidateConcurrency, maxImprovementShots, analyzeGeneration, and findings apply only to proposer mode"
128
+ );
129
+ }
130
+ }
131
+ function splitMethodPartitions(searchScenarios, explicitSelection, fraction) {
132
+ if (!Number.isFinite(fraction) || fraction <= 0 || fraction >= 1) {
133
+ throw new Error("selfImprove: budget.selectionFraction must be in (0, 1)");
134
+ }
135
+ const byId = /* @__PURE__ */ new Map();
136
+ for (const scenario of searchScenarios) {
137
+ if (byId.has(scenario.id)) {
138
+ throw new Error(`selfImprove: duplicate scenario id '${scenario.id}'`);
107
139
  }
108
- return h;
140
+ byId.set(scenario.id, scenario);
109
141
  }
110
- const sorted = [...scenarios].sort((a, b) => hash(a.id) - hash(b.id));
142
+ if (explicitSelection) {
143
+ if (explicitSelection.length === 0) {
144
+ throw new Error("selfImprove: selectionScenarios must not be empty");
145
+ }
146
+ const selectionIds = /* @__PURE__ */ new Set();
147
+ for (const scenario of explicitSelection) {
148
+ if (!byId.has(scenario.id)) {
149
+ throw new Error(
150
+ `selfImprove: selection scenario '${scenario.id}' is absent from the non-final cases`
151
+ );
152
+ }
153
+ if (selectionIds.has(scenario.id)) {
154
+ throw new Error(`selfImprove: duplicate selection scenario id '${scenario.id}'`);
155
+ }
156
+ selectionIds.add(scenario.id);
157
+ }
158
+ const train = searchScenarios.filter((scenario) => !selectionIds.has(scenario.id));
159
+ if (train.length === 0) {
160
+ throw new Error("selfImprove: method train split is empty");
161
+ }
162
+ return {
163
+ train,
164
+ selection: explicitSelection.map((scenario) => byId.get(scenario.id))
165
+ };
166
+ }
167
+ if (searchScenarios.length < 2) {
168
+ throw new Error("selfImprove: method requires at least two non-final scenarios");
169
+ }
170
+ const sorted = [...searchScenarios].sort(
171
+ (a, b) => stableScenarioHash(a.id) - stableScenarioHash(b.id)
172
+ );
173
+ const count = Math.max(1, Math.min(sorted.length - 1, Math.round(sorted.length * fraction)));
174
+ return {
175
+ selection: sorted.slice(0, count),
176
+ train: sorted.slice(count)
177
+ };
178
+ }
179
+ function safeRunComponent(value) {
180
+ return value.replace(/[^a-zA-Z0-9._-]/g, "_");
181
+ }
182
+ function stableScenarioHash(value) {
183
+ let hash = 2166136261 >>> 0;
184
+ for (let index = 0; index < value.length; index++) {
185
+ hash ^= value.charCodeAt(index);
186
+ hash = Math.imul(hash, 16777619) >>> 0;
187
+ }
188
+ return hash;
189
+ }
190
+ function splitTrainHoldout(scenarios, fraction) {
191
+ const sorted = [...scenarios].sort((a, b) => stableScenarioHash(a.id) - stableScenarioHash(b.id));
111
192
  const nHoldout = Math.max(1, Math.min(sorted.length - 1, Math.round(sorted.length * fraction)));
112
193
  return {
113
194
  holdout: sorted.slice(0, nHoldout),
@@ -137,7 +218,7 @@ function winnerSearchCampaign(result) {
137
218
  }
138
219
  async function selfImprove(opts) {
139
220
  const startedAt = Date.now();
140
- const requestedRunDir = opts.runDir ?? `mem://selfImprove-${startedAt}`;
221
+ const requestedRunDir = opts.runDir ?? (opts.method ? `.agent-eval/runs/self-improve-${startedAt}` : `mem://selfImprove-${startedAt}`);
141
222
  const runDir = resolveRunDir(requestedRunDir);
142
223
  const storage = opts.storage ?? (runDir.startsWith("mem://") ? inMemoryCampaignStorage() : fsCampaignStorage());
143
224
  const costLedger = createRunCostLedger({
@@ -153,8 +234,9 @@ async function selfImprove(opts) {
153
234
  }
154
235
  async function runSelfImprove(opts, costLedger, startedAt, runDir, storage) {
155
236
  const budget = opts.budget ?? {};
156
- const generations = budget.generations ?? 3;
157
- const populationSize = budget.populationSize ?? 2;
237
+ assertSelfImproveSearchMode(opts);
238
+ const generations = opts.method ? 1 : budget.generations ?? 3;
239
+ const populationSize = opts.method ? 1 : budget.populationSize ?? 2;
158
240
  const maxConcurrency = budget.maxConcurrency ?? 2;
159
241
  const holdoutFraction = budget.holdoutFraction ?? 0.25;
160
242
  const holdoutMode = budget.holdout ?? "measured";
@@ -173,17 +255,55 @@ async function runSelfImprove(opts, costLedger, startedAt, runDir, storage) {
173
255
  if (holdout.length === 0 && !holdoutDeferred) {
174
256
  throw new Error("selfImprove: holdout split is empty. Pass more scenarios.");
175
257
  }
176
- const proposer = opts.proposer ?? gepaProposer({
177
- llm: {
178
- baseUrl: opts.llm?.baseUrl ?? "https://router.tangle.tools/v1",
179
- apiKey: opts.llm?.apiKey ?? process.env.OPENAI_API_KEY ?? ""
180
- },
181
- model: opts.llm?.model ?? "anthropic/claude-sonnet-4.6",
182
- target: opts.proposerTarget ?? "agent surface (system prompt or config) being optimized by selfImprove",
183
- // Pass-through: when unset, gepaProposer falls back to its own
184
- // domain-neutral engineering primitives.
185
- mutationPrimitives: opts.mutationPrimitives
186
- });
258
+ if (generations > 0 && !opts.proposer && !opts.method) {
259
+ throw new Error(
260
+ "selfImprove: method or proposer is required when budget.generations is greater than zero"
261
+ );
262
+ }
263
+ let optimizationResult;
264
+ const methodPartitions = opts.method ? splitMethodPartitions(train, opts.selectionScenarios, budget.selectionFraction ?? 0.25) : void 0;
265
+ const proposer = opts.method ? {
266
+ kind: `method:${opts.method.name}`,
267
+ propose: async (context) => {
268
+ if (context.generation > 0) return [];
269
+ const result2 = await opts.method.optimize(
270
+ Object.freeze({
271
+ baselineSurface: structuredClone(context.currentSurface),
272
+ trainScenarios: Object.freeze(
273
+ methodPartitions.train.map((scenario) => structuredClone(scenario))
274
+ ),
275
+ selectionScenarios: Object.freeze(
276
+ methodPartitions.selection.map((scenario) => structuredClone(scenario))
277
+ ),
278
+ dispatchWithSurface: opts.agent,
279
+ judges: Object.freeze([opts.judge]),
280
+ runDir: `${runDir}/optimization/${safeRunComponent(opts.method.name)}`,
281
+ seed: 42,
282
+ runOptions: Object.freeze({
283
+ storage,
284
+ maxConcurrency,
285
+ reps: budget.reps,
286
+ dispatchTimeoutMs: opts.dispatchTimeoutMs,
287
+ expectUsage,
288
+ costCeiling: budget.dollars
289
+ }),
290
+ costLedger
291
+ })
292
+ );
293
+ assertOptimizationResult(opts.method.name, result2);
294
+ optimizationResult = structuredClone(result2);
295
+ return [
296
+ {
297
+ surface: structuredClone(result2.winnerSurface),
298
+ label: opts.method.name,
299
+ rationale: `${opts.method.name} selected this surface without final cases.`
300
+ }
301
+ ];
302
+ }
303
+ } : opts.proposer ?? {
304
+ kind: "baseline-only",
305
+ propose: async () => []
306
+ };
187
307
  const gate = opts.gate ?? defaultProductionGate({
188
308
  holdoutScenarios: holdout,
189
309
  deltaThreshold: 0.05
@@ -201,7 +321,6 @@ async function runSelfImprove(opts, costLedger, startedAt, runDir, storage) {
201
321
  populationSize,
202
322
  maxGenerations: generations,
203
323
  candidateConcurrency: budget.candidateConcurrency,
204
- promoteTopK: budget.promoteTopK,
205
324
  reps: budget.reps,
206
325
  maxImprovementShots: budget.maxImprovementShots,
207
326
  holdoutScenarios: holdout,
@@ -293,6 +412,14 @@ async function runSelfImprove(opts, costLedger, startedAt, runDir, storage) {
293
412
  totalCostUsd: totalCost,
294
413
  totalDurationMs: durationMs
295
414
  }),
415
+ ...optimizationResult ? {
416
+ optimizationMethod: {
417
+ name: opts.method.name,
418
+ cost: structuredClone(optimizationResult.cost),
419
+ ...optimizationResult.durationMs === void 0 ? {} : { durationMs: optimizationResult.durationMs },
420
+ ...optimizationResult.provenance === void 0 ? {} : { provenance: structuredClone(optimizationResult.provenance) }
421
+ }
422
+ } : {},
296
423
  storage,
297
424
  hostedClient: opts.hostedTenant ? createHostedClient(opts.hostedTenant) : void 0
298
425
  });
@@ -314,6 +441,14 @@ async function runSelfImprove(opts, costLedger, startedAt, runDir, storage) {
314
441
  totalCostUsd: totalCost,
315
442
  cost,
316
443
  receipts: costLedger.list(),
444
+ ...optimizationResult ? {
445
+ optimization: {
446
+ name: opts.method.name,
447
+ cost: structuredClone(optimizationResult.cost),
448
+ ...optimizationResult.durationMs === void 0 ? {} : { durationMs: optimizationResult.durationMs },
449
+ ...optimizationResult.provenance === void 0 ? {} : { provenance: structuredClone(optimizationResult.provenance) }
450
+ }
451
+ } : {},
317
452
  insight,
318
453
  ...power ? { power } : {},
319
454
  raw: result
@@ -487,17 +622,14 @@ function defineAgentEval(defaults) {
487
622
  const {
488
623
  budget: budgetOverride,
489
624
  hostedTenant: hostedTenantOverride,
490
- llm: llmOverride,
491
625
  ...topLevelOverrides
492
626
  } = opts;
493
627
  const merged = mergeDefined(defaults, topLevelOverrides);
494
628
  const budget = mergeBudget(defaults.budget, budgetOverride);
495
- const llm = mergeLlm(defaults.llm, llmOverride);
496
629
  const hostedTenant = mergeHostedTenant(defaults.hostedTenant, hostedTenantOverride);
497
630
  return selfImprove({
498
631
  ...merged,
499
632
  ...budget ? { budget } : {},
500
- ...llm ? { llm } : {},
501
633
  ...hostedTenant ? { hostedTenant } : {}
502
634
  });
503
635
  }
@@ -522,9 +654,6 @@ function mergeBudget(defaults, overrides) {
522
654
  if (merged?.reps !== void 0) merged.reps = requirePositiveInteger(merged.reps, "budget.reps");
523
655
  return merged;
524
656
  }
525
- function mergeLlm(defaults, overrides) {
526
- return mergeOptionalObject(defaults, overrides);
527
- }
528
657
  function mergeHostedTenant(defaults, overrides) {
529
658
  const merged = mergeOptionalObject(defaults, overrides);
530
659
  if (!merged) return void 0;
@@ -1682,6 +1811,7 @@ export {
1682
1811
  buildDefaultAnalystRegistry,
1683
1812
  buildEvidenceVector,
1684
1813
  campaignSplitDigest,
1814
+ compareOptimizationMethods,
1685
1815
  composeGate,
1686
1816
  createChatClient,
1687
1817
  createReferenceEquivalenceJudge,
@@ -1691,7 +1821,7 @@ export {
1691
1821
  diffRunBaselineToWinner,
1692
1822
  diffRuns,
1693
1823
  evalReportingSuite,
1694
- evolutionaryProposer,
1824
+ externalTextOptimizationMethod,
1695
1825
  fromClaudeCodeSession,
1696
1826
  fromCodexSession,
1697
1827
  fromFeedbackTable,
@@ -1702,7 +1832,7 @@ export {
1702
1832
  fromPigraphSession,
1703
1833
  fromRunRecordDir,
1704
1834
  fsCampaignStorage,
1705
- gepaProposer,
1835
+ gepaOptimizationMethod,
1706
1836
  heldOutGate,
1707
1837
  inMemoryCampaignStorage,
1708
1838
  llmJudge,
@@ -1722,6 +1852,7 @@ export {
1722
1852
  sealCandidateBenchmarkTask,
1723
1853
  sealCandidateExperiment,
1724
1854
  selfImprove,
1855
+ skillOptOptimizationMethod,
1725
1856
  summarizeExecution,
1726
1857
  verifyCandidateBenchmarkSuite,
1727
1858
  verifyCandidateBenchmarkSuiteInputs,