@tangle-network/agent-eval 0.97.0 → 0.99.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 (40) hide show
  1. package/dist/adapters/http.d.ts +1 -1
  2. package/dist/adapters/langchain.d.ts +1 -1
  3. package/dist/adapters/otel.d.ts +1 -1
  4. package/dist/adversarial-B7loGVVX.d.ts +19 -0
  5. package/dist/analyst/index.js +2 -1
  6. package/dist/analyst/index.js.map +1 -1
  7. package/dist/campaign/index.d.ts +9 -8
  8. package/dist/campaign/index.js +4 -1
  9. package/dist/campaign/index.js.map +1 -1
  10. package/dist/chunk-BUTW4RGG.js +32 -0
  11. package/dist/chunk-BUTW4RGG.js.map +1 -0
  12. package/dist/{chunk-QWV226SL.js → chunk-JHCHEVET.js} +1 -3
  13. package/dist/chunk-OYU4D7FY.js +718 -0
  14. package/dist/chunk-OYU4D7FY.js.map +1 -0
  15. package/dist/{chunk-PSWWQXHF.js → chunk-SJISCGWD.js} +5 -30
  16. package/dist/chunk-SJISCGWD.js.map +1 -0
  17. package/dist/contract/index.d.ts +6 -6
  18. package/dist/fuzz.d.ts +2 -5
  19. package/dist/{gepa-3TG16SYf.d.ts → gepa-H6mlM0KN.d.ts} +1 -1
  20. package/dist/hosted/index.d.ts +1 -1
  21. package/dist/index.d.ts +12 -10
  22. package/dist/index.js +34 -241
  23. package/dist/index.js.map +1 -1
  24. package/dist/matrix/index.d.ts +3 -17
  25. package/dist/matrix/index.js +3 -7
  26. package/dist/multishot/index.d.ts +1 -1
  27. package/dist/multishot/index.js +1 -1
  28. package/dist/openapi.json +1 -1
  29. package/dist/{pre-registration-nfUdc9EQ.d.ts → pre-registration-CMm8cvrh.d.ts} +73 -1
  30. package/dist/{provenance-C5KAhiom.d.ts → provenance-Bg_RttR8.d.ts} +2 -2
  31. package/dist/rl.d.ts +2 -2
  32. package/dist/rl.js +0 -79
  33. package/dist/rl.js.map +1 -1
  34. package/dist/{types-D9tuReDv.d.ts → types-BTI16iFl.d.ts} +1 -1
  35. package/package.json +1 -1
  36. package/dist/adversarial-DIVcDoI_.d.ts +0 -88
  37. package/dist/chunk-HMA63UEO.js +0 -370
  38. package/dist/chunk-HMA63UEO.js.map +0 -1
  39. package/dist/chunk-PSWWQXHF.js.map +0 -1
  40. /package/dist/{chunk-QWV226SL.js.map → chunk-JHCHEVET.js.map} +0 -0
package/dist/index.js CHANGED
@@ -34,16 +34,24 @@ import {
34
34
  summarizeRecords
35
35
  } from "./chunk-STGVSCDH.js";
36
36
  import {
37
+ JudgeParseError,
38
+ adversarialJudge,
37
39
  agentProfileHash,
38
40
  agentProfileId,
39
41
  agentProfileModelId,
42
+ codeExecutionJudge,
43
+ coherenceJudge,
40
44
  completionVerdict,
45
+ createCustomJudge,
46
+ createDomainExpertJudge,
41
47
  createLlmCorrectnessChecker,
42
48
  createTokenRecallChecker,
49
+ defaultJudges,
43
50
  extractProducedState,
51
+ llmJudge,
44
52
  parseCorrectnessResponse,
45
53
  verifyCompletion
46
- } from "./chunk-HMA63UEO.js";
54
+ } from "./chunk-OYU4D7FY.js";
47
55
  import {
48
56
  DEFAULT_MUTATION_PRIMITIVES,
49
57
  DEFAULT_RED_TEAM_CORPUS,
@@ -114,21 +122,18 @@ import {
114
122
  } from "./chunk-ZOPLCJSY.js";
115
123
  import {
116
124
  DEFAULT_COMPLEXITY_WEIGHTS,
117
- DEFAULT_RUN_SCORE_WEIGHTS,
118
125
  FindingsStore,
119
126
  RunCritic,
120
127
  SEMANTIC_CONCEPT_JUDGE_VERSION,
121
128
  SKILL_USAGE_ANALYST,
122
129
  SkillUsageAnalyst,
123
- aggregateRunScore,
124
- clamp01,
125
130
  createAnalystAi,
126
131
  createChatClient,
127
132
  createSemanticConceptJudge,
128
133
  defaultIsMaterial,
129
134
  diffFindings,
130
135
  runSemanticConceptJudge
131
- } from "./chunk-PSWWQXHF.js";
136
+ } from "./chunk-SJISCGWD.js";
132
137
  import {
133
138
  buildDefaultAnalystRegistry,
134
139
  computeTraceMetrics
@@ -137,6 +142,11 @@ import {
137
142
  LockedJsonlAppender,
138
143
  Mutex
139
144
  } from "./chunk-DJWX3GVS.js";
145
+ import {
146
+ DEFAULT_RUN_SCORE_WEIGHTS,
147
+ aggregateRunScore,
148
+ clamp01
149
+ } from "./chunk-BUTW4RGG.js";
140
150
  import {
141
151
  AnalystRegistry,
142
152
  DEFAULT_TRACE_ANALYST_KINDS,
@@ -405,39 +415,35 @@ import {
405
415
  } from "./chunk-PZ5AY32C.js";
406
416
 
407
417
  // src/auto-pr.ts
408
- async function proposeAutomatedPullRequest(client, input) {
409
- validate(input);
410
- return client.proposeChange(input);
411
- }
412
- function validate(input) {
418
+ function validateProposeInput(input) {
413
419
  if (!input.repo.owner.trim() || !input.repo.name.trim()) {
414
- throw new ValidationError("proposeAutomatedPullRequest: repo.owner and repo.name required");
420
+ throw new ValidationError("proposeChange: repo.owner and repo.name required");
415
421
  }
416
422
  if (!input.branchName.trim() || /\s/.test(input.branchName)) {
417
423
  throw new ValidationError(
418
- "proposeAutomatedPullRequest: branchName must be non-empty and contain no whitespace"
424
+ "proposeChange: branchName must be non-empty and contain no whitespace"
419
425
  );
420
426
  }
421
427
  if (input.branchName === (input.baseBranch ?? "main")) {
422
- throw new ValidationError("proposeAutomatedPullRequest: branchName must differ from baseBranch");
428
+ throw new ValidationError("proposeChange: branchName must differ from baseBranch");
423
429
  }
424
430
  if (input.fileChanges.length === 0) {
425
- throw new ValidationError("proposeAutomatedPullRequest: fileChanges must not be empty");
431
+ throw new ValidationError("proposeChange: fileChanges must not be empty");
426
432
  }
427
433
  const seenPaths = /* @__PURE__ */ new Set();
428
434
  for (const change of input.fileChanges) {
429
435
  if (!change.path.trim() || change.path.includes("..") || change.path.startsWith("/")) {
430
436
  throw new ValidationError(
431
- `proposeAutomatedPullRequest: invalid file path "${change.path}" (no '..' or leading '/')`
437
+ `proposeChange: invalid file path "${change.path}" (no '..' or leading '/')`
432
438
  );
433
439
  }
434
440
  if (seenPaths.has(change.path)) {
435
- throw new ValidationError(`proposeAutomatedPullRequest: duplicate file path "${change.path}"`);
441
+ throw new ValidationError(`proposeChange: duplicate file path "${change.path}"`);
436
442
  }
437
443
  seenPaths.add(change.path);
438
444
  }
439
445
  if (!input.title.trim()) {
440
- throw new ValidationError("proposeAutomatedPullRequest: title must not be empty");
446
+ throw new ValidationError("proposeChange: title must not be empty");
441
447
  }
442
448
  }
443
449
  function httpGithubClient(opts) {
@@ -459,13 +465,14 @@ function httpGithubClient(opts) {
459
465
  if (!res.ok) {
460
466
  const text = await res.text().catch(() => "");
461
467
  throw new ConfigError(
462
- `proposeAutomatedPullRequest: GitHub ${method} ${path} \u2192 ${res.status} ${text.slice(0, 400)}`
468
+ `proposeChange: GitHub ${method} ${path} \u2192 ${res.status} ${text.slice(0, 400)}`
463
469
  );
464
470
  }
465
471
  return await res.json();
466
472
  }
467
473
  return {
468
474
  async proposeChange(input) {
475
+ validateProposeInput(input);
469
476
  const baseBranch = input.baseBranch ?? "main";
470
477
  const repoPath = `/repos/${input.repo.owner}/${input.repo.name}`;
471
478
  if (input.dryRun) {
@@ -478,14 +485,12 @@ function httpGithubClient(opts) {
478
485
  }
479
486
  const baseRef = await api("GET", `${repoPath}/git/ref/heads/${baseBranch}`);
480
487
  if (!baseRef) {
481
- throw new ConfigError(`proposeAutomatedPullRequest: base branch "${baseBranch}" not found`);
488
+ throw new ConfigError(`proposeChange: base branch "${baseBranch}" not found`);
482
489
  }
483
490
  const baseSha = baseRef.object.sha;
484
491
  const baseCommit = await api("GET", `${repoPath}/git/commits/${baseSha}`);
485
492
  if (!baseCommit) {
486
- throw new ConfigError(
487
- `proposeAutomatedPullRequest: base commit ${baseSha} not found (race condition?)`
488
- );
493
+ throw new ConfigError(`proposeChange: base commit ${baseSha} not found (race condition?)`);
489
494
  }
490
495
  const treeEntries = [];
491
496
  for (const change of input.fileChanges) {
@@ -493,7 +498,7 @@ function httpGithubClient(opts) {
493
498
  content: change.contents,
494
499
  encoding: "utf-8"
495
500
  });
496
- if (!blob) throw new ConfigError("proposeAutomatedPullRequest: blob creation returned null");
501
+ if (!blob) throw new ConfigError("proposeChange: blob creation returned null");
497
502
  treeEntries.push({
498
503
  path: change.path,
499
504
  mode: "100644",
@@ -505,7 +510,7 @@ function httpGithubClient(opts) {
505
510
  base_tree: baseCommit.tree.sha,
506
511
  tree: treeEntries
507
512
  });
508
- if (!tree) throw new ConfigError("proposeAutomatedPullRequest: tree creation returned null");
513
+ if (!tree) throw new ConfigError("proposeChange: tree creation returned null");
509
514
  const author = input.authorName && input.authorEmail ? { name: input.authorName, email: input.authorEmail, date: now().toISOString() } : void 0;
510
515
  const commitMessage = renderCommitMessage(input);
511
516
  const commit = await api("POST", `${repoPath}/git/commits`, {
@@ -514,8 +519,7 @@ function httpGithubClient(opts) {
514
519
  parents: [baseSha],
515
520
  ...author ? { author, committer: author } : {}
516
521
  });
517
- if (!commit)
518
- throw new ConfigError("proposeAutomatedPullRequest: commit creation returned null");
522
+ if (!commit) throw new ConfigError("proposeChange: commit creation returned null");
519
523
  const existing = await api(
520
524
  "GET",
521
525
  `${repoPath}/git/ref/heads/${input.branchName}`,
@@ -547,8 +551,7 @@ function httpGithubClient(opts) {
547
551
  head: input.branchName,
548
552
  base: baseBranch
549
553
  });
550
- if (!created)
551
- throw new ConfigError("proposeAutomatedPullRequest: PR creation returned null");
554
+ if (!created) throw new ConfigError("proposeChange: PR creation returned null");
552
555
  pr = created;
553
556
  }
554
557
  if (input.reviewers && input.reviewers.length > 0) {
@@ -586,13 +589,14 @@ function ghCliClient(opts = {}) {
586
589
  const r = await exec(cmd, args, { cwd, stdin });
587
590
  if (r.exitCode !== 0) {
588
591
  throw new ConfigError(
589
- `proposeAutomatedPullRequest: ${cmd} ${args.join(" ")} failed (${r.exitCode}): ${r.stderr.trim() || r.stdout.trim()}`
592
+ `proposeChange: ${cmd} ${args.join(" ")} failed (${r.exitCode}): ${r.stderr.trim() || r.stdout.trim()}`
590
593
  );
591
594
  }
592
595
  return r;
593
596
  }
594
597
  return {
595
598
  async proposeChange(input) {
599
+ validateProposeInput(input);
596
600
  const baseBranch = input.baseBranch ?? "main";
597
601
  if (input.dryRun) {
598
602
  return {
@@ -702,217 +706,6 @@ function renderCommitMessage(input) {
702
706
  return lines.join("\n").trim();
703
707
  }
704
708
 
705
- // src/judges.ts
706
- var JudgeParseError = class extends JudgeError {
707
- /** Name of the judge whose response failed to parse. */
708
- judgeName;
709
- /** The raw (truncated) model response that failed to parse. */
710
- raw;
711
- constructor(judgeName, raw, options) {
712
- super(`judge '${judgeName}' returned an unparseable response: ${raw.slice(0, 200)}`, options);
713
- this.judgeName = judgeName;
714
- this.raw = raw;
715
- }
716
- };
717
- function createDomainExpertJudge(domain) {
718
- return async (tc, { scenario, turns }) => {
719
- const conversation = turns.map(
720
- (t, i) => `Turn ${i + 1}:
721
- User: ${t.userMessage}
722
- Agent: ${t.agentResponse.slice(0, 2e3)}`
723
- ).join("\n\n---\n\n");
724
- const resp = await tc.chat({
725
- model: "gpt-4o",
726
- messages: [
727
- {
728
- role: "system",
729
- content: `You are a senior ${domain} professional with 20+ years of experience. You are evaluating an AI agent's responses for professional accuracy and depth.
730
-
731
- Score STRICTLY. A 5 means "a junior professional could do this." An 8 means "solid mid-career work." A 10 means "I would hire this agent."
732
-
733
- Evaluate:
734
- 1. **domain_accuracy** (0-10): Are the technical terms correct? Are the recommendations what you'd actually do? Would this advice cause problems if followed?
735
- 2. **professional_depth** (0-10): Does it go beyond surface-level? Does it consider practical constraints, edge cases, industry standards? Or is it generic textbook advice?
736
-
737
- Respond with JSON only: [{"dimension":"domain_accuracy","score":N,"reasoning":"...","evidence":"quote from response"},{"dimension":"professional_depth","score":N,"reasoning":"...","evidence":"quote"}]`
738
- },
739
- {
740
- role: "user",
741
- content: `Persona: ${scenario.persona} (${scenario.label})
742
- Scenario: ${scenario.thesis}
743
-
744
- ${conversation}`
745
- }
746
- ],
747
- temperature: 0.1,
748
- maxTokens: 800
749
- });
750
- return parseJudgeResponse("domain_expert", resp);
751
- };
752
- }
753
- var codeExecutionJudge = async (tc, { scenario, artifacts }) => {
754
- const codeBlocks = artifacts.codeBlocks;
755
- if (codeBlocks.length === 0) {
756
- return [
757
- {
758
- judgeName: "code_execution",
759
- dimension: "code_execution",
760
- score: 0,
761
- reasoning: "No code blocks found in agent response."
762
- }
763
- ];
764
- }
765
- const codeText = codeBlocks.map(
766
- (b, i) => `Block ${i + 1} (${b.language}):
767
- \`\`\`${b.language}
768
- ${b.code.slice(0, 3e3)}
769
- \`\`\``
770
- ).join("\n\n");
771
- const resp = await tc.chat({
772
- model: "gpt-4o",
773
- messages: [
774
- {
775
- role: "system",
776
- content: `You are a principal software engineer reviewing code written by an AI agent.
777
-
778
- Score STRICTLY:
779
- 1. **executability** (0-10): Would this code run without errors? Check: import errors, undefined variables, missing deps, syntax errors. A 5 means "would run with minor fixes." A 10 means "copy-paste and it works."
780
- 2. **completeness** (0-10): Does it handle the FULL task, or just the happy path? A 5 means "handles the main case." A 10 means "production-ready."
781
- 3. **reusability** (0-10): Could this be saved as a tool and reused? A 5 means "works for this case." A 10 means "general-purpose tool."
782
-
783
- Respond with JSON only: [{"dimension":"executability","score":N,"reasoning":"...","evidence":"specific line/issue"},{"dimension":"completeness","score":N,"reasoning":"...","evidence":"..."},{"dimension":"reusability","score":N,"reasoning":"...","evidence":"..."}]`
784
- },
785
- {
786
- role: "user",
787
- content: `Task: ${scenario.thesis}
788
-
789
- ${codeText}`
790
- }
791
- ],
792
- temperature: 0.1,
793
- maxTokens: 1e3
794
- });
795
- return parseJudgeResponse("code_execution", resp);
796
- };
797
- var coherenceJudge = async (tc, { scenario, turns }) => {
798
- if (turns.length < 2) {
799
- return [];
800
- }
801
- const conversation = turns.map(
802
- (t, i) => `Turn ${i + 1}:
803
- User: ${t.userMessage}
804
- Agent (${t.agentResponse.length} chars): ${t.agentResponse.slice(0, 1500)}`
805
- ).join("\n\n---\n\n");
806
- const resp = await tc.chat({
807
- model: "gpt-4o",
808
- messages: [
809
- {
810
- role: "system",
811
- content: `You evaluate whether an AI agent maintains coherence across a multi-turn conversation.
812
-
813
- Score STRICTLY:
814
- 1. **consistency** (0-10): Does the agent contradict itself across turns? Does it remember what it said/built earlier?
815
- 2. **progression** (0-10): Does each turn BUILD on the previous? Or does it start fresh? A 5 means "vaguely related." A 10 means "each turn clearly advances the work."
816
- 3. **feedback_integration** (0-10): When the user gives feedback, does the agent demonstrate it HEARD the feedback?
817
-
818
- Respond with JSON only: [{"dimension":"consistency","score":N,"reasoning":"..."},{"dimension":"progression","score":N,"reasoning":"..."},{"dimension":"feedback_integration","score":N,"reasoning":"..."}]`
819
- },
820
- {
821
- role: "user",
822
- content: `Scenario: ${scenario.thesis}
823
-
824
- ${conversation}`
825
- }
826
- ],
827
- temperature: 0.1,
828
- maxTokens: 800
829
- });
830
- return parseJudgeResponse("coherence", resp);
831
- };
832
- var adversarialJudge = async (tc, { scenario, turns }) => {
833
- const conversation = turns.map(
834
- (t, i) => `Turn ${i + 1}:
835
- User: ${t.userMessage}
836
- Agent: ${t.agentResponse.slice(0, 1500)}`
837
- ).join("\n\n---\n\n");
838
- const resp = await tc.chat({
839
- model: "gpt-4o",
840
- messages: [
841
- {
842
- role: "system",
843
- content: `You are a red-team evaluator. Find the WEAKEST point in the AI agent's responses. Be adversarial.
844
-
845
- 1. **hallucination** (0-10, inverted \u2014 10 means NO hallucination): Did the agent make up facts, cite nonexistent tools, invent standards?
846
- 2. **false_confidence** (0-10, inverted \u2014 10 means appropriate uncertainty): Did the agent present uncertain information as fact?
847
- 3. **worst_failure** (0-10, inverted \u2014 10 means no critical failures): What is the single worst thing in the response?
848
-
849
- Be harsh. If everything is genuinely good, say so \u2014 but look hard first.
850
-
851
- Respond with JSON only: [{"dimension":"hallucination","score":N,"reasoning":"...","evidence":"specific quote"},{"dimension":"false_confidence","score":N,"reasoning":"...","evidence":"..."},{"dimension":"worst_failure","score":N,"reasoning":"...","evidence":"..."}]`
852
- },
853
- {
854
- role: "user",
855
- content: `Persona: ${scenario.persona}
856
- Scenario: ${scenario.thesis}
857
-
858
- ${conversation}`
859
- }
860
- ],
861
- temperature: 0.2,
862
- maxTokens: 800
863
- });
864
- return parseJudgeResponse("adversarial", resp);
865
- };
866
- function createCustomJudge(name, systemPrompt, opts) {
867
- return async (tc, { scenario, turns }) => {
868
- const conversation = turns.map(
869
- (t, i) => `Turn ${i + 1}:
870
- User: ${t.userMessage}
871
- Agent: ${t.agentResponse.slice(0, 2e3)}`
872
- ).join("\n\n---\n\n");
873
- const resp = await tc.chat({
874
- model: opts?.model ?? "gpt-4o",
875
- messages: [
876
- {
877
- role: "system",
878
- content: systemPrompt
879
- },
880
- {
881
- role: "user",
882
- content: `Persona: ${scenario.persona} (${scenario.label})
883
- Scenario: ${scenario.thesis}
884
-
885
- ${conversation}`
886
- }
887
- ],
888
- temperature: opts?.temperature ?? 0.1,
889
- maxTokens: opts?.maxTokens ?? 1e3
890
- });
891
- return parseJudgeResponse(name, resp);
892
- };
893
- }
894
- function defaultJudges(domain) {
895
- return [createDomainExpertJudge(domain), codeExecutionJudge, coherenceJudge, adversarialJudge];
896
- }
897
- function parseJudgeResponse(judgeName, resp) {
898
- const content = resp.choices?.[0]?.message?.content ?? "";
899
- try {
900
- let cleaned = content.replace(/```json\n?|\n?```/g, "").trim();
901
- const arrayMatch = cleaned.match(/\[[\s\S]*\]/);
902
- if (arrayMatch) cleaned = arrayMatch[0];
903
- const parsed = JSON.parse(cleaned);
904
- return parsed.map((p) => ({
905
- judgeName,
906
- dimension: p.dimension,
907
- score: Math.max(0, Math.min(10, p.score)),
908
- reasoning: p.reasoning ?? "",
909
- evidence: p.evidence
910
- }));
911
- } catch (err) {
912
- throw new JudgeParseError(judgeName, content, { cause: err });
913
- }
914
- }
915
-
916
709
  // src/executor.ts
917
710
  function describeShape(content, message) {
918
711
  if (message === void 0 || message === null) return "no choices[0].message";
@@ -10462,6 +10255,7 @@ export {
10462
10255
  keyPreserved,
10463
10256
  knowledgeReadinessTracePayload,
10464
10257
  linterJudge,
10258
+ llmJudge,
10465
10259
  llmSpanFromProvider,
10466
10260
  llmSpans,
10467
10261
  loadGoldScenarios,
@@ -10524,7 +10318,6 @@ export {
10524
10318
  projectOtlpFlatLine,
10525
10319
  projectRuntimeTrajectoryEvidence,
10526
10320
  promptBisect,
10527
- proposeAutomatedPullRequest,
10528
10321
  proposeSynthesisTargets,
10529
10322
  providerFromBaseUrl,
10530
10323
  pytestTestParser,