@tangle-network/agent-eval 0.136.0 → 0.137.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/CHANGELOG.md +38 -1
- package/README.md +4 -2
- package/dist/{agent-profile-cell-OhuTee9n.js → agent-profile-cell-CbfBm2g6.js} +2 -2
- package/dist/{agent-profile-cell-OhuTee9n.js.map → agent-profile-cell-CbfBm2g6.js.map} +1 -1
- package/dist/{agent-profile-cell-CCm3l2v2.d.ts → agent-profile-cell-Cw0PVwDr.d.ts} +2 -2
- package/dist/{agent-profile-cell-CCm3l2v2.d.ts.map → agent-profile-cell-Cw0PVwDr.d.ts.map} +1 -1
- package/dist/analyst/index.d.ts +139 -17
- package/dist/analyst/index.d.ts.map +1 -1
- package/dist/analyst/index.js +606 -4
- package/dist/analyst/index.js.map +1 -1
- package/dist/{analyze-runs-jjCmF8pU.js → analyze-runs-BScZvqMV.js} +6 -6
- package/dist/{analyze-runs-jjCmF8pU.js.map → analyze-runs-BScZvqMV.js.map} +1 -1
- package/dist/{analyze-runs-Cda5Xkj1.d.ts → analyze-runs-PVtnfjvA.d.ts} +6 -6
- package/dist/{analyze-runs-Cda5Xkj1.d.ts.map → analyze-runs-PVtnfjvA.d.ts.map} +1 -1
- package/dist/{baseline-BUeFcgrn.js → baseline-C-GocmIW.js} +2 -2
- package/dist/{baseline-BUeFcgrn.js.map → baseline-C-GocmIW.js.map} +1 -1
- package/dist/benchmark-CHX4orG7.d.ts +184 -0
- package/dist/benchmark-CHX4orG7.d.ts.map +1 -0
- package/dist/benchmark-YDrpumqB.js +414 -0
- package/dist/benchmark-YDrpumqB.js.map +1 -0
- package/dist/benchmarks/index.d.ts +1 -1
- package/dist/benchmarks/index.js +1 -1
- package/dist/{benchmarks-Dfgm9ts5.js → benchmarks-DCLkQOmc.js} +3 -3
- package/dist/{benchmarks-Dfgm9ts5.js.map → benchmarks-DCLkQOmc.js.map} +1 -1
- package/dist/builder-eval/index.js +2 -2
- package/dist/campaign/index.d.ts +6 -6
- package/dist/campaign/index.js +3 -3
- package/dist/{campaign-Dz8uQnhC.js → campaign-lgObcHFC.js} +212 -78
- package/dist/campaign-lgObcHFC.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/client-C8L6h6Wf.d.ts +202 -0
- package/dist/client-C8L6h6Wf.d.ts.map +1 -0
- package/dist/completion-verifier-DSyRNVzU.d.ts +240 -0
- package/dist/completion-verifier-DSyRNVzU.d.ts.map +1 -0
- package/dist/contract/index.d.ts +10 -9
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +10 -10
- package/dist/control.d.ts +2 -2
- package/dist/control.js +1 -1
- package/dist/{cost-ledger-DHAjwNj7.js → cost-ledger-D-5_-dhi.js} +2 -2
- package/dist/{cost-ledger-DHAjwNj7.js.map → cost-ledger-D-5_-dhi.js.map} +1 -1
- package/dist/{cost-ledger-fGS_u_O1.d.ts → cost-ledger-D2o6JOrL.d.ts} +2 -2
- package/dist/{cost-ledger-fGS_u_O1.d.ts.map → cost-ledger-D2o6JOrL.d.ts.map} +1 -1
- package/dist/{dataset-BvtnC8Dc.d.ts → dataset-v_Y5902-.d.ts} +2 -2
- package/dist/{dataset-BvtnC8Dc.d.ts.map → dataset-v_Y5902-.d.ts.map} +1 -1
- package/dist/{default-registry-CHmdy2An.js → default-registry-CLXbRt0f.js} +119 -38
- package/dist/default-registry-CLXbRt0f.js.map +1 -0
- package/dist/{default-registry-Brxr728w.d.ts → default-registry-Dc5D_Loc.d.ts} +63 -137
- package/dist/default-registry-Dc5D_Loc.d.ts.map +1 -0
- package/dist/{errors-8YnH8WlF.js → errors-D-LKuDhb.js} +8 -2
- package/dist/errors-D-LKuDhb.js.map +1 -0
- package/dist/{errors-CEk209JS.d.ts → errors-DkfjIDvD.d.ts} +9 -3
- package/dist/errors-DkfjIDvD.d.ts.map +1 -0
- package/dist/{eval-campaign-Cc8WZJ6b.js → eval-campaign-CHqfLnff.js} +6 -6
- package/dist/{eval-campaign-Cc8WZJ6b.js.map → eval-campaign-CHqfLnff.js.map} +1 -1
- package/dist/{extract-usage-DIQpN-ww.js → extract-usage-p-56bh8q.js} +3 -3
- package/dist/{extract-usage-DIQpN-ww.js.map → extract-usage-p-56bh8q.js.map} +1 -1
- package/dist/{feedback-trajectory-CVaeREXV.d.ts → feedback-trajectory-N_F0PwHz.d.ts} +90 -3
- package/dist/feedback-trajectory-N_F0PwHz.d.ts.map +1 -0
- package/dist/fuzz.d.ts +1 -1
- package/dist/fuzz.js +2 -2
- package/dist/hosted/index.d.ts +3 -2
- package/dist/hosted/index.d.ts.map +1 -1
- package/dist/index-BipJlj-C.d.ts +316 -0
- package/dist/index-BipJlj-C.d.ts.map +1 -0
- package/dist/{index-CQsJcqch.d.ts → index-BnP1QJUv.d.ts} +5 -5
- package/dist/{index-CQsJcqch.d.ts.map → index-BnP1QJUv.d.ts.map} +1 -1
- package/dist/{index-B4Fjfo5U.d.ts → index-C-Pr4OWg.d.ts} +88 -317
- package/dist/index-C-Pr4OWg.d.ts.map +1 -0
- package/dist/{index-DuhJaaiH.d.ts → index-DEb46kc6.d.ts} +2 -2
- package/dist/{index-DuhJaaiH.d.ts.map → index-DEb46kc6.d.ts.map} +1 -1
- package/dist/{index-C2fkZhv_.d.ts → index-DRNl6g_N.d.ts} +3 -3
- package/dist/{index-C2fkZhv_.d.ts.map → index-DRNl6g_N.d.ts.map} +1 -1
- package/dist/{index-AbhwHp0V.d.ts → index-U3RHOShi.d.ts} +2 -2
- package/dist/{index-AbhwHp0V.d.ts.map → index-U3RHOShi.d.ts.map} +1 -1
- package/dist/index.d.ts +29 -70
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +507 -33
- package/dist/index.js.map +1 -1
- package/dist/{client-DcvgkaZi.d.ts → insight-report-B9ooYH_g.d.ts} +5 -203
- package/dist/insight-report-B9ooYH_g.d.ts.map +1 -0
- package/dist/integrity-CCXTftiL.js +1360 -0
- package/dist/integrity-CCXTftiL.js.map +1 -0
- package/dist/{integrity-rmVhXWA7.d.ts → integrity-CKxosZ5Z.d.ts} +3 -3
- package/dist/{integrity-rmVhXWA7.d.ts.map → integrity-CKxosZ5Z.d.ts.map} +1 -1
- package/dist/{integrity-BzRbCHzi.js → integrity-fdt8XPAv.js} +2 -2
- package/dist/{integrity-BzRbCHzi.js.map → integrity-fdt8XPAv.js.map} +1 -1
- package/dist/ledger-core/index.d.ts +1 -1
- package/dist/ledger-core/index.js +1 -1
- package/dist/{ledger-core-DAKFKRzi.js → ledger-core-t6sItivm.js} +85 -85
- package/dist/{ledger-core-DAKFKRzi.js.map → ledger-core-t6sItivm.js.map} +1 -1
- package/dist/{llm-client-DHx8pzyJ.js → llm-client-DKB25jV8.js} +3 -3
- package/dist/{llm-client-DHx8pzyJ.js.map → llm-client-DKB25jV8.js.map} +1 -1
- package/dist/meta-eval/index.d.ts +2 -2
- package/dist/meta-eval/index.js +3 -3
- package/dist/{mint-DyRUc9k6.js → mint-Ctwk079K.js} +4 -4
- package/dist/{mint-DyRUc9k6.js.map → mint-Ctwk079K.js.map} +1 -1
- package/dist/multishot/index.d.ts +2 -2
- package/dist/openapi.json +1 -1
- package/dist/{paired-arms-BbFKrAU-.js → paired-arms-iZ08VFMN.js} +3 -3
- package/dist/{paired-arms-BbFKrAU-.js.map → paired-arms-iZ08VFMN.js.map} +1 -1
- package/dist/pipelines/index.js +2 -2
- package/dist/profile-cell.d.ts +1 -1
- package/dist/profile-cell.js +1 -1
- package/dist/{propose-review-control-SQ-n9-We.js → propose-review-control-DLXz4FCX.js} +2 -2
- package/dist/{propose-review-control-SQ-n9-We.js.map → propose-review-control-DLXz4FCX.js.map} +1 -1
- package/dist/registry-BdM7SuTr.d.ts +124 -0
- package/dist/registry-BdM7SuTr.d.ts.map +1 -0
- package/dist/{release-report-DooPguBc.js → release-report-B5XPBvAU.js} +4 -4
- package/dist/{release-report-DooPguBc.js.map → release-report-B5XPBvAU.js.map} +1 -1
- package/dist/{release-report-DpBxGGI1.d.ts → release-report-CofgVNZt.d.ts} +4 -4
- package/dist/{release-report-DpBxGGI1.d.ts.map → release-report-CofgVNZt.d.ts.map} +1 -1
- package/dist/{replay-C6wRg47C.js → replay-Bju0T8Ls.js} +248 -8
- package/dist/replay-Bju0T8Ls.js.map +1 -0
- package/dist/{replay-BRfMIs81.d.ts → replay-K8FaC0CB.d.ts} +227 -52
- package/dist/replay-K8FaC0CB.d.ts.map +1 -0
- package/dist/reporting.d.ts +4 -4
- package/dist/reporting.js +4 -4
- package/dist/{researcher-Doo95b50.d.ts → researcher-Da0Wj-bt.d.ts} +6 -7
- package/dist/researcher-Da0Wj-bt.d.ts.map +1 -0
- package/dist/{reward-hacking-D-QqXvg-.d.ts → reward-hacking-CQ3hTCO3.d.ts} +2 -2
- package/dist/{reward-hacking-D-QqXvg-.d.ts.map → reward-hacking-CQ3hTCO3.d.ts.map} +1 -1
- package/dist/{reward-hacking-a-kYs0-i.js → reward-hacking-GyN0kMd8.js} +3 -3
- package/dist/{reward-hacking-a-kYs0-i.js.map → reward-hacking-GyN0kMd8.js.map} +1 -1
- package/dist/rl.d.ts +6 -6
- package/dist/rl.js +9 -9
- package/dist/rollout/index.d.ts +1 -1
- package/dist/rollout/index.js +3 -3
- package/dist/{rollout-DLSUIWLu.js → rollout-DQFl0UXA.js} +2 -2
- package/dist/{rollout-DLSUIWLu.js.map → rollout-DQFl0UXA.js.map} +1 -1
- package/dist/{rubric-predictive-validity-BJf-8ejY.js → rubric-predictive-validity-BRR632r1.js} +2 -2
- package/dist/{rubric-predictive-validity-BJf-8ejY.js.map → rubric-predictive-validity-BRR632r1.js.map} +1 -1
- package/dist/{rubric-predictive-validity-C1dCLcvb.d.ts → rubric-predictive-validity-C4sztLR3.d.ts} +2 -2
- package/dist/{rubric-predictive-validity-C1dCLcvb.d.ts.map → rubric-predictive-validity-C4sztLR3.d.ts.map} +1 -1
- package/dist/{run-evidence-DokQtX0-.d.ts → run-evidence-BDIircdA.d.ts} +3 -3
- package/dist/{run-evidence-DokQtX0-.d.ts.map → run-evidence-BDIircdA.d.ts.map} +1 -1
- package/dist/{run-record-DcObtIGh.d.ts → run-record-BPCa2rQ8.d.ts} +4 -4
- package/dist/{run-record-DcObtIGh.d.ts.map → run-record-BPCa2rQ8.d.ts.map} +1 -1
- package/dist/{run-record-BIwU2wdV.js → run-record-vRgqWmJw.js} +3 -3
- package/dist/{run-record-BIwU2wdV.js.map → run-record-vRgqWmJw.js.map} +1 -1
- package/dist/{semantic-concept-judge-Btozx3Vc.js → semantic-concept-judge-Bz64IckK.js} +4 -4
- package/dist/{semantic-concept-judge-Btozx3Vc.js.map → semantic-concept-judge-Bz64IckK.js.map} +1 -1
- package/dist/{server-Bz3WQJs6.js → server-KjXZZUDX.js} +3 -3
- package/dist/{server-Bz3WQJs6.js.map → server-KjXZZUDX.js.map} +1 -1
- package/dist/{skill-usage-BDQVPIG1.d.ts → skill-usage-CFDLLlhF.d.ts} +25 -47
- package/dist/skill-usage-CFDLLlhF.d.ts.map +1 -0
- package/dist/{skillopt-optimization-method-CwSYkv35.d.ts → skillopt-optimization-method-BpbnlvAZ.d.ts} +11 -12
- package/dist/skillopt-optimization-method-BpbnlvAZ.d.ts.map +1 -0
- package/dist/{skillopt-optimization-method-0UmPD6aP.js → skillopt-optimization-method-f4o9sUT4.js} +7 -7
- package/dist/{skillopt-optimization-method-0UmPD6aP.js.map → skillopt-optimization-method-f4o9sUT4.js.map} +1 -1
- package/dist/{statistics-CnGCLLqc.js → statistics-ByxzSiOM.js} +2 -2
- package/dist/{statistics-CnGCLLqc.js.map → statistics-ByxzSiOM.js.map} +1 -1
- package/dist/{statistics-CKOqre5S.d.ts → statistics-_7P642CN.d.ts} +2 -2
- package/dist/{statistics-CKOqre5S.d.ts.map → statistics-_7P642CN.d.ts.map} +1 -1
- package/dist/{summary-report-BEk8OFLs.js → summary-report-9A5y7EsK.js} +4 -4
- package/dist/{summary-report-BEk8OFLs.js.map → summary-report-9A5y7EsK.js.map} +1 -1
- package/dist/{summary-report-CPMINBqs.d.ts → summary-report-DHipz9Kx.d.ts} +3 -3
- package/dist/{summary-report-CPMINBqs.d.ts.map → summary-report-DHipz9Kx.d.ts.map} +1 -1
- package/dist/supervisor-run/index.d.ts +3 -2
- package/dist/supervisor-run/index.js +3 -2
- package/dist/{supervisor-run-Dr5HnTup.js → supervisor-run-B2EWUmQY.js} +28 -454
- package/dist/supervisor-run-B2EWUmQY.js.map +1 -0
- package/dist/{test-graded-scenario-BsqWLmPt.js → test-graded-scenario-JHcKQNpq.js} +2 -2
- package/dist/{test-graded-scenario-BsqWLmPt.js.map → test-graded-scenario-JHcKQNpq.js.map} +1 -1
- package/dist/tools-DZk2Jn64.js +1876 -0
- package/dist/tools-DZk2Jn64.js.map +1 -0
- package/dist/traces.d.ts +6 -7
- package/dist/traces.js +5 -6
- package/dist/{types-DVjczBM9.d.ts → types-CKswbJGO.d.ts} +260 -6
- package/dist/types-CKswbJGO.d.ts.map +1 -0
- package/dist/{types-DiWLru6Z.d.ts → types-CTGbIm57.d.ts} +5 -5
- package/dist/{types-DiWLru6Z.d.ts.map → types-CTGbIm57.d.ts.map} +1 -1
- package/dist/types-CTvKfr5F.d.ts +804 -0
- package/dist/types-CTvKfr5F.d.ts.map +1 -0
- package/dist/{index-CyC1BTmn.d.ts → types-Dea6tiVI.d.ts} +16 -238
- package/dist/types-Dea6tiVI.d.ts.map +1 -0
- package/dist/wire/index.d.ts +3 -3
- package/dist/wire/index.js +1 -1
- package/docs/feedback-trajectories.md +100 -1
- package/docs/trace-analysis.md +374 -58
- package/package.json +5 -1
- package/dist/analyst-BkTS3C58.d.ts +0 -89
- package/dist/analyst-BkTS3C58.d.ts.map +0 -1
- package/dist/analyst-j5je5J7c.js +0 -152
- package/dist/analyst-j5je5J7c.js.map +0 -1
- package/dist/campaign-Dz8uQnhC.js.map +0 -1
- package/dist/client-DcvgkaZi.d.ts.map +0 -1
- package/dist/default-registry-Brxr728w.d.ts.map +0 -1
- package/dist/default-registry-CHmdy2An.js.map +0 -1
- package/dist/errors-8YnH8WlF.js.map +0 -1
- package/dist/errors-CEk209JS.d.ts.map +0 -1
- package/dist/feedback-trajectory-CVaeREXV.d.ts.map +0 -1
- package/dist/index-B4Fjfo5U.d.ts.map +0 -1
- package/dist/index-CyC1BTmn.d.ts.map +0 -1
- package/dist/llm-client-BiK4HW0u.d.ts +0 -290
- package/dist/llm-client-BiK4HW0u.d.ts.map +0 -1
- package/dist/raw-provider-sink-BU29Sh8h.d.ts +0 -134
- package/dist/raw-provider-sink-BU29Sh8h.d.ts.map +0 -1
- package/dist/replay-BRfMIs81.d.ts.map +0 -1
- package/dist/replay-C6wRg47C.js.map +0 -1
- package/dist/researcher-Doo95b50.d.ts.map +0 -1
- package/dist/skill-usage-BDQVPIG1.d.ts.map +0 -1
- package/dist/skillopt-optimization-method-CwSYkv35.d.ts.map +0 -1
- package/dist/store-CxJry_cs.d.ts +0 -229
- package/dist/store-CxJry_cs.d.ts.map +0 -1
- package/dist/supervisor-run-Dr5HnTup.js.map +0 -1
- package/dist/tools-D8yTtNSN.js +0 -1190
- package/dist/tools-D8yTtNSN.js.map +0 -1
- package/dist/types-Cc3qbqzj.d.ts +0 -387
- package/dist/types-Cc3qbqzj.d.ts.map +0 -1
- package/dist/types-DVjczBM9.d.ts.map +0 -1
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { c as AnalystRunInputs, f as AnalystUsageReceipt, i as AnalystFinding, p as EvidenceRef, x as TraceAnalysisStore } from "./types-CKswbJGO.js";
|
|
2
|
+
import { a as RegistryRunOpts, n as AnalystRegistry } from "./registry-BdM7SuTr.js";
|
|
3
|
+
//#region src/analyst/benchmark.d.ts
|
|
4
|
+
interface AnalystEvidenceExpectation {
|
|
5
|
+
uri: string;
|
|
6
|
+
kind?: EvidenceRef['kind'];
|
|
7
|
+
}
|
|
8
|
+
interface AnalystIssueExpectation {
|
|
9
|
+
id: string;
|
|
10
|
+
findingIds?: readonly string[];
|
|
11
|
+
areas?: readonly string[];
|
|
12
|
+
subjects?: readonly string[];
|
|
13
|
+
evidence?: readonly AnalystEvidenceExpectation[];
|
|
14
|
+
evidenceMode?: 'any' | 'all';
|
|
15
|
+
/** Exact evidence location for the first unrecoverable or causal step. */
|
|
16
|
+
criticalEvidence?: readonly AnalystEvidenceExpectation[];
|
|
17
|
+
}
|
|
18
|
+
interface AnalystBenchmarkCase<TInput = unknown> {
|
|
19
|
+
id: string;
|
|
20
|
+
input: TInput;
|
|
21
|
+
expectedIssues: readonly AnalystIssueExpectation[];
|
|
22
|
+
/** Complete set of labeled locations used to measure label-location agreement. */
|
|
23
|
+
labeledEvidence?: readonly AnalystEvidenceExpectation[];
|
|
24
|
+
tags?: readonly string[];
|
|
25
|
+
metadata?: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
interface AnalystFindingScore {
|
|
28
|
+
expectedIssueCount: number;
|
|
29
|
+
matchedIssueIds: string[];
|
|
30
|
+
missedIssueIds: string[];
|
|
31
|
+
supportedFindingIndexes: number[];
|
|
32
|
+
unsupportedFindingIndexes: number[];
|
|
33
|
+
unlabeledEvidence: EvidenceRef[];
|
|
34
|
+
issueRecall: number;
|
|
35
|
+
findingPrecision: number;
|
|
36
|
+
f1: number;
|
|
37
|
+
criticalStepAccuracy: number | null;
|
|
38
|
+
/** Share of findings that cite at least one evidence location. */
|
|
39
|
+
citationCoverage: number | null;
|
|
40
|
+
/** Share of citations that agree with a labeled case location. */
|
|
41
|
+
citationLabelAgreement: number | null;
|
|
42
|
+
cleanFalsePositive: boolean;
|
|
43
|
+
}
|
|
44
|
+
interface AnalystEvidenceResolutionError {
|
|
45
|
+
evidence: EvidenceRef;
|
|
46
|
+
class: string;
|
|
47
|
+
message: string;
|
|
48
|
+
}
|
|
49
|
+
interface AnalystEvidenceResolution {
|
|
50
|
+
checked: number;
|
|
51
|
+
resolved: number;
|
|
52
|
+
unresolvedEvidence: EvidenceRef[];
|
|
53
|
+
errors: AnalystEvidenceResolutionError[];
|
|
54
|
+
/** Null when no citations were checked or any resolution attempt failed. */
|
|
55
|
+
validity: number | null;
|
|
56
|
+
}
|
|
57
|
+
type AnalystEvidenceResolver<TInput = unknown> = (input: {
|
|
58
|
+
caseId: string;
|
|
59
|
+
caseInput: TInput;
|
|
60
|
+
evidence: EvidenceRef;
|
|
61
|
+
signal?: AbortSignal;
|
|
62
|
+
}) => boolean | Promise<boolean>;
|
|
63
|
+
/**
|
|
64
|
+
* Resolve canonical `trace://<trace>/span/<span>` evidence against a trace store.
|
|
65
|
+
* Other evidence kinds and URI schemes require a caller-supplied resolver.
|
|
66
|
+
*/
|
|
67
|
+
declare function traceStoreEvidenceResolver<TInput>(getStore: (input: TInput) => TraceAnalysisStore): AnalystEvidenceResolver<TInput>;
|
|
68
|
+
interface AnalystBenchmarkOutput {
|
|
69
|
+
findings: readonly AnalystFinding[];
|
|
70
|
+
usage?: AnalystUsageReceipt;
|
|
71
|
+
metadata?: Record<string, unknown>;
|
|
72
|
+
}
|
|
73
|
+
interface AnalystBenchmarkRunner<TInput = unknown> {
|
|
74
|
+
id: string;
|
|
75
|
+
analyze(input: TInput, context: {
|
|
76
|
+
caseId: string;
|
|
77
|
+
repetition: number;
|
|
78
|
+
signal?: AbortSignal;
|
|
79
|
+
}): AnalystBenchmarkOutput | Promise<AnalystBenchmarkOutput>;
|
|
80
|
+
}
|
|
81
|
+
interface AnalystBenchmarkObservation {
|
|
82
|
+
runnerId: string;
|
|
83
|
+
caseId: string;
|
|
84
|
+
repetition: number;
|
|
85
|
+
executionIndex: number;
|
|
86
|
+
latencyMs: number;
|
|
87
|
+
findings: readonly AnalystFinding[];
|
|
88
|
+
score: AnalystFindingScore;
|
|
89
|
+
evidenceResolution?: AnalystEvidenceResolution;
|
|
90
|
+
caseTags: readonly string[];
|
|
91
|
+
caseMetadata?: Record<string, unknown>;
|
|
92
|
+
usage?: AnalystUsageReceipt;
|
|
93
|
+
runnerMetadata?: Record<string, unknown>;
|
|
94
|
+
error?: {
|
|
95
|
+
class: string;
|
|
96
|
+
message: string;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
interface AnalystLatencyDistribution {
|
|
100
|
+
min: number;
|
|
101
|
+
mean: number;
|
|
102
|
+
p50: number;
|
|
103
|
+
p95: number;
|
|
104
|
+
max: number;
|
|
105
|
+
}
|
|
106
|
+
interface AnalystBenchmarkSummary {
|
|
107
|
+
runnerId: string;
|
|
108
|
+
plannedRuns: number;
|
|
109
|
+
completedRuns: number;
|
|
110
|
+
failedRuns: number;
|
|
111
|
+
issueRecall: number | null;
|
|
112
|
+
findingPrecision: number | null;
|
|
113
|
+
f1: number | null;
|
|
114
|
+
criticalStepAccuracy: number | null;
|
|
115
|
+
citationCoverage: number | null;
|
|
116
|
+
citationLabelAgreement: number | null;
|
|
117
|
+
citationResolution: number | null;
|
|
118
|
+
citationResolutionUnknownRuns: number;
|
|
119
|
+
unresolvedCitations: number;
|
|
120
|
+
citationResolutionErrors: number;
|
|
121
|
+
cleanCaseFalsePositiveRate: number | null;
|
|
122
|
+
cleanCaseFailureRate: number | null;
|
|
123
|
+
runAgreement: number | null;
|
|
124
|
+
latencyMs: AnalystLatencyDistribution;
|
|
125
|
+
calls: number;
|
|
126
|
+
callsUnknownRuns: number;
|
|
127
|
+
inputTokens: number;
|
|
128
|
+
outputTokens: number;
|
|
129
|
+
reasoningTokens: number;
|
|
130
|
+
cachedTokens: number;
|
|
131
|
+
cacheWriteTokens: number;
|
|
132
|
+
tokenUsageUnknownRuns: number;
|
|
133
|
+
reasoningTokenUsageUnknownRuns: number;
|
|
134
|
+
cachedTokenUsageUnknownRuns: number;
|
|
135
|
+
cacheWriteTokenUsageUnknownRuns: number;
|
|
136
|
+
knownCostUsd: number;
|
|
137
|
+
costUnknownRuns: number;
|
|
138
|
+
}
|
|
139
|
+
interface AnalystBenchmarkDatasetRef {
|
|
140
|
+
id: string;
|
|
141
|
+
revision: string;
|
|
142
|
+
split?: string;
|
|
143
|
+
}
|
|
144
|
+
interface AnalystBenchmarkDescriptor {
|
|
145
|
+
id?: string;
|
|
146
|
+
dataset?: AnalystBenchmarkDatasetRef;
|
|
147
|
+
command?: string;
|
|
148
|
+
environment?: Record<string, string>;
|
|
149
|
+
metadata?: Record<string, unknown>;
|
|
150
|
+
}
|
|
151
|
+
interface AnalystBenchmarkProvenance extends AnalystBenchmarkDescriptor {
|
|
152
|
+
startedAt: string;
|
|
153
|
+
endedAt: string;
|
|
154
|
+
caseCount: number;
|
|
155
|
+
runnerIds: string[];
|
|
156
|
+
repetitions: number;
|
|
157
|
+
maxConcurrency: number;
|
|
158
|
+
runnerOrderSeed: number;
|
|
159
|
+
}
|
|
160
|
+
interface AnalystBenchmarkResult {
|
|
161
|
+
provenance: AnalystBenchmarkProvenance;
|
|
162
|
+
observations: AnalystBenchmarkObservation[];
|
|
163
|
+
summaries: AnalystBenchmarkSummary[];
|
|
164
|
+
}
|
|
165
|
+
interface RunAnalystBenchmarkOptions<TInput> {
|
|
166
|
+
cases: readonly AnalystBenchmarkCase<TInput>[];
|
|
167
|
+
runners: readonly AnalystBenchmarkRunner<TInput>[];
|
|
168
|
+
repetitions?: number;
|
|
169
|
+
maxConcurrency?: number;
|
|
170
|
+
runnerOrderSeed?: number;
|
|
171
|
+
resolveEvidence?: AnalystEvidenceResolver<TInput>;
|
|
172
|
+
benchmark?: AnalystBenchmarkDescriptor;
|
|
173
|
+
signal?: AbortSignal;
|
|
174
|
+
}
|
|
175
|
+
declare function scoreAnalystFindings(testCase: Pick<AnalystBenchmarkCase, 'id' | 'expectedIssues' | 'labeledEvidence'>, findings: readonly AnalystFinding[]): AnalystFindingScore;
|
|
176
|
+
declare function runAnalystBenchmark<TInput>(options: RunAnalystBenchmarkOptions<TInput>): Promise<AnalystBenchmarkResult>;
|
|
177
|
+
declare function registryBenchmarkRunner(options: {
|
|
178
|
+
id: string;
|
|
179
|
+
registry: AnalystRegistry;
|
|
180
|
+
runOptions?: Omit<RegistryRunOpts, 'signal'>;
|
|
181
|
+
}): AnalystBenchmarkRunner<AnalystRunInputs>;
|
|
182
|
+
//#endregion
|
|
183
|
+
export { RunAnalystBenchmarkOptions as _, AnalystBenchmarkOutput as a, scoreAnalystFindings as b, AnalystBenchmarkRunner as c, AnalystEvidenceResolution as d, AnalystEvidenceResolutionError as f, AnalystLatencyDistribution as g, AnalystIssueExpectation as h, AnalystBenchmarkObservation as i, AnalystBenchmarkSummary as l, AnalystFindingScore as m, AnalystBenchmarkDatasetRef as n, AnalystBenchmarkProvenance as o, AnalystEvidenceResolver as p, AnalystBenchmarkDescriptor as r, AnalystBenchmarkResult as s, AnalystBenchmarkCase as t, AnalystEvidenceExpectation as u, registryBenchmarkRunner as v, traceStoreEvidenceResolver as x, runAnalystBenchmark as y };
|
|
184
|
+
//# sourceMappingURL=benchmark-CHX4orG7.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmark-CHX4orG7.d.ts","names":[],"sources":["../src/analyst/benchmark.ts"],"mappings":";;;UAYiB;EACf;EACA,OAAO;;UAGQ;EACf;EACA;EACA;EACA;EACA,oBAAoB;EACpB;;EAEA,4BAA4B;;UAGb,qBAAqB;EACpC;EACA,OAAO;EACP,yBAAyB;;EAEzB,2BAA2B;EAC3B;EACA,WAAW;;UAGI;EACf;EACA;EACA;EACA;EACA;EACA,mBAAmB;EACnB;EACA;EACA;EACA;;EAEA;;EAEA;EACA;;UAGe;EACf,UAAU;EACV;EACA;;UAGe;EACf;EACA;EACA,oBAAoB;EACpB,QAAQ;;EAER;;KAGU,wBAAwB,qBAAqB;EACvD;EACA,WAAW;EACX,UAAU;EACV,SAAS;gBACK;;;;;iBAMA,2BAA2B,QACzC,WAAW,OAAO,WAAW,qBAC5B,wBAAwB;UAiBV;EACf,mBAAmB;EACnB,QAAQ;EACR,WAAW;;UAGI,uBAAuB;EACtC;EACA,QACE,OAAO,QACP;IAAW;IAAgB;IAAoB,SAAS;MACvD,yBAAyB,QAAQ;;UAGrB;EACf;EACA;EACA;EACA;EACA;EACA,mBAAmB;EACnB,OAAO;EACP,qBAAqB;EACrB;EACA,eAAe;EACf,QAAQ;EACR,iBAAiB;EACjB;IAAU;IAAe;;;UAGV;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA,UAAU;EACV;EACA,cAAc;EACd,WAAW;;UAGI,mCAAmC;EAClD;EACA;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf,YAAY;EACZ,cAAc;EACd,WAAW;;UAGI,2BAA2B;EAC1C,gBAAgB,qBAAqB;EACrC,kBAAkB,uBAAuB;EACzC;EACA;EACA;EACA,kBAAkB,wBAAwB;EAC1C,YAAY;EACZ,SAAS;;iBAGK,qBACd,UAAU,KAAK,oEACf,mBAAmB,mBAClB;iBA0FmB,oBAAoB,QACxC,SAAS,2BAA2B,UACnC,QAAQ;iBAiDK,wBAAwB;EACtC;EACA,UAAU;EACV,aAAa,KAAK;IAChB,uBAAuB"}
|
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
import { linearSumAssignment } from "linear-sum-assignment";
|
|
3
|
+
//#region src/analyst/benchmark.ts
|
|
4
|
+
/**
|
|
5
|
+
* Resolve canonical `trace://<trace>/span/<span>` evidence against a trace store.
|
|
6
|
+
* Other evidence kinds and URI schemes require a caller-supplied resolver.
|
|
7
|
+
*/
|
|
8
|
+
function traceStoreEvidenceResolver(getStore) {
|
|
9
|
+
return async ({ caseInput, evidence }) => {
|
|
10
|
+
if (evidence.kind !== "span") return false;
|
|
11
|
+
const location = parseTraceSpanUri(evidence.uri);
|
|
12
|
+
if (!location) return false;
|
|
13
|
+
const result = await getStore(caseInput).viewSpans({
|
|
14
|
+
trace_id: location.traceId,
|
|
15
|
+
span_ids: [location.spanId]
|
|
16
|
+
});
|
|
17
|
+
return result.trace_id === location.traceId && result.missing_span_ids.length === 0 && result.spans.some((span) => span.span_id === location.spanId);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function scoreAnalystFindings(testCase, findings) {
|
|
21
|
+
validateCase(testCase);
|
|
22
|
+
const matchedFindingByIssue = matchFindingsToIssues(testCase.expectedIssues, findings);
|
|
23
|
+
const matchedIssueIds = testCase.expectedIssues.filter((_, index) => matchedFindingByIssue.has(index)).map((issue) => issue.id);
|
|
24
|
+
const missedIssueIds = testCase.expectedIssues.filter((_, index) => !matchedFindingByIssue.has(index)).map((issue) => issue.id);
|
|
25
|
+
const supportedFindingIndexes = new Set(matchedFindingByIssue.values());
|
|
26
|
+
const unsupportedFindingIndexes = findings.map((_, index) => index).filter((index) => !supportedFindingIndexes.has(index));
|
|
27
|
+
const expectedIssueCount = testCase.expectedIssues.length;
|
|
28
|
+
const issueRecall = expectedIssueCount === 0 ? 1 : matchedIssueIds.length / expectedIssueCount;
|
|
29
|
+
const findingPrecision = findings.length === 0 ? expectedIssueCount === 0 ? 1 : 0 : supportedFindingIndexes.size / findings.length;
|
|
30
|
+
const f1 = harmonicMean(findingPrecision, issueRecall);
|
|
31
|
+
const allEvidence = findings.flatMap((finding) => finding.evidence_refs);
|
|
32
|
+
const criticalIssues = testCase.expectedIssues.filter((issue) => (issue.criticalEvidence?.length ?? 0) > 0);
|
|
33
|
+
const criticalHits = testCase.expectedIssues.filter((issue) => {
|
|
34
|
+
if ((issue.criticalEvidence?.length ?? 0) === 0) return false;
|
|
35
|
+
return matchesEvidence(allEvidence, issue.criticalEvidence ?? [], "any");
|
|
36
|
+
}).length;
|
|
37
|
+
const findingsWithEvidence = findings.filter((finding) => finding.evidence_refs.length > 0).length;
|
|
38
|
+
const unlabeledEvidence = testCase.labeledEvidence ? allEvidence.filter((ref) => !testCase.labeledEvidence.some((expected) => evidenceMatches(ref, expected))) : [];
|
|
39
|
+
return {
|
|
40
|
+
expectedIssueCount,
|
|
41
|
+
matchedIssueIds,
|
|
42
|
+
missedIssueIds,
|
|
43
|
+
supportedFindingIndexes: [...supportedFindingIndexes].sort((a, b) => a - b),
|
|
44
|
+
unsupportedFindingIndexes,
|
|
45
|
+
unlabeledEvidence,
|
|
46
|
+
issueRecall,
|
|
47
|
+
findingPrecision,
|
|
48
|
+
f1,
|
|
49
|
+
criticalStepAccuracy: criticalIssues.length === 0 ? null : criticalHits / criticalIssues.length,
|
|
50
|
+
citationCoverage: findings.length === 0 ? null : findingsWithEvidence / findings.length,
|
|
51
|
+
citationLabelAgreement: testCase.labeledEvidence === void 0 ? null : allEvidence.length === 0 ? findings.length === 0 ? null : 0 : (allEvidence.length - unlabeledEvidence.length) / allEvidence.length,
|
|
52
|
+
cleanFalsePositive: expectedIssueCount === 0 && findings.length > 0
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function matchFindingsToIssues(issues, findings) {
|
|
56
|
+
if (issues.length === 0) return /* @__PURE__ */ new Map();
|
|
57
|
+
const cardinalityWeight = issues.length + 1;
|
|
58
|
+
const assignment = linearSumAssignment(issues.map((issue) => [...findings.map((finding) => {
|
|
59
|
+
if (!findingMatchesIssue(finding, issue)) return -1;
|
|
60
|
+
const criticalHit = (issue.criticalEvidence?.length ?? 0) > 0 && matchesEvidence(finding.evidence_refs, issue.criticalEvidence ?? [], "any");
|
|
61
|
+
return cardinalityWeight + Number(criticalHit);
|
|
62
|
+
}), ...Array.from({ length: issues.length }, () => 0)]), { maximaze: true }).rowAssignments;
|
|
63
|
+
const matches = /* @__PURE__ */ new Map();
|
|
64
|
+
for (const [issueIndex, column] of assignment.entries()) {
|
|
65
|
+
if (column < 0 || column >= findings.length) continue;
|
|
66
|
+
if (!findingMatchesIssue(findings[column], issues[issueIndex])) continue;
|
|
67
|
+
matches.set(issueIndex, column);
|
|
68
|
+
}
|
|
69
|
+
return matches;
|
|
70
|
+
}
|
|
71
|
+
async function runAnalystBenchmark(options) {
|
|
72
|
+
validateBenchmarkOptions(options);
|
|
73
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
74
|
+
const repetitions = options.repetitions ?? 1;
|
|
75
|
+
const runnerOrderSeed = options.runnerOrderSeed ?? 0;
|
|
76
|
+
const maxConcurrency = Math.min(options.maxConcurrency ?? 1, options.runners.length * options.cases.length * repetitions);
|
|
77
|
+
const jobs = benchmarkJobs(options.cases, options.runners, repetitions, runnerOrderSeed);
|
|
78
|
+
const observations = [];
|
|
79
|
+
let cursor = 0;
|
|
80
|
+
const worker = async () => {
|
|
81
|
+
while (cursor < jobs.length) {
|
|
82
|
+
options.signal?.throwIfAborted();
|
|
83
|
+
const job = jobs[cursor++];
|
|
84
|
+
observations.push(await runBenchmarkJob(job, options.signal, options.resolveEvidence));
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
await Promise.all(Array.from({ length: maxConcurrency }, worker));
|
|
88
|
+
const runnerOrder = new Map(options.runners.map((runner, index) => [runner.id, index]));
|
|
89
|
+
const caseOrder = new Map(options.cases.map((testCase, index) => [testCase.id, index]));
|
|
90
|
+
observations.sort((a, b) => (runnerOrder.get(a.runnerId) ?? 0) - (runnerOrder.get(b.runnerId) ?? 0) || (caseOrder.get(a.caseId) ?? 0) - (caseOrder.get(b.caseId) ?? 0) || a.repetition - b.repetition);
|
|
91
|
+
return {
|
|
92
|
+
provenance: {
|
|
93
|
+
...options.benchmark,
|
|
94
|
+
startedAt,
|
|
95
|
+
endedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
96
|
+
caseCount: options.cases.length,
|
|
97
|
+
runnerIds: options.runners.map((runner) => runner.id),
|
|
98
|
+
repetitions,
|
|
99
|
+
maxConcurrency,
|
|
100
|
+
runnerOrderSeed
|
|
101
|
+
},
|
|
102
|
+
observations,
|
|
103
|
+
summaries: options.runners.map((runner) => summarizeRunner(runner.id, observations.filter((observation) => observation.runnerId === runner.id)))
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function registryBenchmarkRunner(options) {
|
|
107
|
+
return {
|
|
108
|
+
id: options.id,
|
|
109
|
+
async analyze(input, context) {
|
|
110
|
+
const result = await options.registry.run(`${options.id}:${context.caseId}:${context.repetition}`, input, {
|
|
111
|
+
...options.runOptions,
|
|
112
|
+
signal: context.signal
|
|
113
|
+
});
|
|
114
|
+
return {
|
|
115
|
+
findings: result.findings,
|
|
116
|
+
usage: mergeRegistryUsage(result),
|
|
117
|
+
metadata: { analystRun: result }
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async function runBenchmarkJob(job, signal, resolveEvidence) {
|
|
123
|
+
const started = performance.now();
|
|
124
|
+
try {
|
|
125
|
+
const output = await job.runner.analyze(job.testCase.input, {
|
|
126
|
+
caseId: job.testCase.id,
|
|
127
|
+
repetition: job.repetition,
|
|
128
|
+
signal
|
|
129
|
+
});
|
|
130
|
+
return {
|
|
131
|
+
runnerId: job.runner.id,
|
|
132
|
+
caseId: job.testCase.id,
|
|
133
|
+
repetition: job.repetition,
|
|
134
|
+
executionIndex: job.executionIndex,
|
|
135
|
+
latencyMs: performance.now() - started,
|
|
136
|
+
findings: output.findings,
|
|
137
|
+
score: scoreAnalystFindings(job.testCase, output.findings),
|
|
138
|
+
evidenceResolution: resolveEvidence ? await resolveFindingEvidence(job.testCase, output.findings, resolveEvidence, signal) : void 0,
|
|
139
|
+
caseTags: [...job.testCase.tags ?? []],
|
|
140
|
+
caseMetadata: job.testCase.metadata,
|
|
141
|
+
usage: output.usage,
|
|
142
|
+
runnerMetadata: output.metadata
|
|
143
|
+
};
|
|
144
|
+
} catch (error) {
|
|
145
|
+
if (signal?.aborted) throw error;
|
|
146
|
+
const findings = [];
|
|
147
|
+
return {
|
|
148
|
+
runnerId: job.runner.id,
|
|
149
|
+
caseId: job.testCase.id,
|
|
150
|
+
repetition: job.repetition,
|
|
151
|
+
executionIndex: job.executionIndex,
|
|
152
|
+
latencyMs: performance.now() - started,
|
|
153
|
+
findings,
|
|
154
|
+
score: scoreAnalystFindings(job.testCase, findings),
|
|
155
|
+
caseTags: [...job.testCase.tags ?? []],
|
|
156
|
+
caseMetadata: job.testCase.metadata,
|
|
157
|
+
error: {
|
|
158
|
+
class: error instanceof Error ? error.constructor.name : "Error",
|
|
159
|
+
message: error instanceof Error ? error.message : String(error)
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function benchmarkJobs(cases, runners, repetitions, runnerOrderSeed) {
|
|
165
|
+
const seededRunners = [...runners].sort((left, right) => stableHash(`${runnerOrderSeed}\u0000${left.id}`) - stableHash(`${runnerOrderSeed}\u0000${right.id}`) || left.id.localeCompare(right.id));
|
|
166
|
+
let executionIndex = 0;
|
|
167
|
+
return cases.flatMap((testCase, caseIndex) => Array.from({ length: repetitions }, (_, repetition) => {
|
|
168
|
+
const rotation = (caseIndex * repetitions + repetition) % seededRunners.length;
|
|
169
|
+
return [...seededRunners.slice(rotation), ...seededRunners.slice(0, rotation)].map((runner) => ({
|
|
170
|
+
runner,
|
|
171
|
+
testCase,
|
|
172
|
+
repetition,
|
|
173
|
+
executionIndex: executionIndex++
|
|
174
|
+
}));
|
|
175
|
+
}).flat());
|
|
176
|
+
}
|
|
177
|
+
async function resolveFindingEvidence(testCase, findings, resolver, signal) {
|
|
178
|
+
const evidence = findings.flatMap((finding) => finding.evidence_refs);
|
|
179
|
+
const resolved = [];
|
|
180
|
+
const unresolvedEvidence = [];
|
|
181
|
+
const errors = [];
|
|
182
|
+
for (const ref of evidence) {
|
|
183
|
+
signal?.throwIfAborted();
|
|
184
|
+
try {
|
|
185
|
+
if (await resolver({
|
|
186
|
+
caseId: testCase.id,
|
|
187
|
+
caseInput: testCase.input,
|
|
188
|
+
evidence: ref,
|
|
189
|
+
signal
|
|
190
|
+
})) resolved.push(ref);
|
|
191
|
+
else unresolvedEvidence.push(ref);
|
|
192
|
+
} catch (error) {
|
|
193
|
+
if (signal?.aborted) throw error;
|
|
194
|
+
errors.push({
|
|
195
|
+
evidence: ref,
|
|
196
|
+
class: error instanceof Error ? error.constructor.name : "Error",
|
|
197
|
+
message: error instanceof Error ? error.message : String(error)
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
checked: evidence.length,
|
|
203
|
+
resolved: resolved.length,
|
|
204
|
+
unresolvedEvidence,
|
|
205
|
+
errors,
|
|
206
|
+
validity: evidence.length === 0 || errors.length > 0 ? null : resolved.length / evidence.length
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function summarizeRunner(runnerId, observations) {
|
|
210
|
+
const issueBearing = observations.filter((observation) => observation.score.expectedIssueCount > 0);
|
|
211
|
+
const expectedIssues = issueBearing.reduce((sum, observation) => sum + observation.score.expectedIssueCount, 0);
|
|
212
|
+
const matchedIssues = issueBearing.reduce((sum, observation) => sum + observation.score.matchedIssueIds.length, 0);
|
|
213
|
+
const issueFindings = issueBearing.reduce((sum, observation) => sum + observation.findings.length, 0);
|
|
214
|
+
const supportedFindings = issueBearing.reduce((sum, observation) => sum + observation.score.supportedFindingIndexes.length, 0);
|
|
215
|
+
const issueRecall = expectedIssues === 0 ? null : matchedIssues / expectedIssues;
|
|
216
|
+
const findingPrecision = expectedIssues === 0 ? null : issueFindings === 0 ? 0 : supportedFindings / issueFindings;
|
|
217
|
+
const critical = observations.map((observation) => observation.score.criticalStepAccuracy).filter((value) => value !== null);
|
|
218
|
+
const findingsWithEvidence = observations.reduce((sum, observation) => sum + observation.findings.filter((finding) => finding.evidence_refs.length > 0).length, 0);
|
|
219
|
+
const allFindings = observations.reduce((sum, observation) => sum + observation.findings.length, 0);
|
|
220
|
+
const citationObservations = observations.filter((observation) => observation.score.citationLabelAgreement !== null);
|
|
221
|
+
const citationCount = citationObservations.reduce((sum, observation) => sum + observation.findings.reduce((count, finding) => count + finding.evidence_refs.length, 0), 0);
|
|
222
|
+
const invalidCitationCount = citationObservations.reduce((sum, observation) => sum + observation.score.unlabeledEvidence.length, 0);
|
|
223
|
+
const clean = observations.filter((observation) => observation.score.expectedIssueCount === 0);
|
|
224
|
+
const completedClean = clean.filter((observation) => !observation.error);
|
|
225
|
+
const resolvedCitations = observations.reduce((sum, observation) => sum + (observation.evidenceResolution?.resolved ?? 0), 0);
|
|
226
|
+
const unresolvedCitations = observations.reduce((sum, observation) => sum + (observation.evidenceResolution?.unresolvedEvidence.length ?? 0), 0);
|
|
227
|
+
const citationResolutionErrors = observations.reduce((sum, observation) => sum + (observation.evidenceResolution?.errors.length ?? 0), 0);
|
|
228
|
+
const resolutionAttempts = observations.filter((observation) => observation.findings.some((finding) => finding.evidence_refs.length > 0));
|
|
229
|
+
const citationResolutionUnknownRuns = resolutionAttempts.filter((observation) => !observation.evidenceResolution || observation.evidenceResolution.errors.length > 0).length;
|
|
230
|
+
const usages = observations.map((observation) => observation.usage);
|
|
231
|
+
const knownCostUsd = usages.reduce((sum, usage) => {
|
|
232
|
+
if (!usage) return sum;
|
|
233
|
+
return sum + (usage.cost.kind === "uncaptured" ? usage.knownCostUsd ?? 0 : usage.cost.usd);
|
|
234
|
+
}, 0);
|
|
235
|
+
return {
|
|
236
|
+
runnerId,
|
|
237
|
+
plannedRuns: observations.length,
|
|
238
|
+
completedRuns: observations.filter((observation) => !observation.error).length,
|
|
239
|
+
failedRuns: observations.filter((observation) => Boolean(observation.error)).length,
|
|
240
|
+
issueRecall,
|
|
241
|
+
findingPrecision,
|
|
242
|
+
f1: findingPrecision === null || issueRecall === null ? null : harmonicMean(findingPrecision, issueRecall),
|
|
243
|
+
criticalStepAccuracy: critical.length === 0 ? null : mean(critical),
|
|
244
|
+
citationCoverage: allFindings === 0 ? null : findingsWithEvidence / allFindings,
|
|
245
|
+
citationLabelAgreement: citationObservations.length === 0 ? null : citationCount === 0 ? 0 : (citationCount - invalidCitationCount) / citationCount,
|
|
246
|
+
citationResolution: resolutionAttempts.length === 0 || citationResolutionUnknownRuns > 0 || resolvedCitations + unresolvedCitations === 0 ? null : resolvedCitations / (resolvedCitations + unresolvedCitations),
|
|
247
|
+
citationResolutionUnknownRuns,
|
|
248
|
+
unresolvedCitations,
|
|
249
|
+
citationResolutionErrors,
|
|
250
|
+
cleanCaseFalsePositiveRate: completedClean.length === 0 ? null : completedClean.filter((observation) => observation.score.cleanFalsePositive).length / completedClean.length,
|
|
251
|
+
cleanCaseFailureRate: clean.length === 0 ? null : clean.filter((observation) => Boolean(observation.error)).length / clean.length,
|
|
252
|
+
runAgreement: issueAgreement(observations.filter((observation) => !observation.error)),
|
|
253
|
+
latencyMs: latencyDistribution(observations.map((observation) => observation.latencyMs)),
|
|
254
|
+
calls: usages.reduce((sum, usage) => sum + (usage?.calls ?? 0), 0),
|
|
255
|
+
callsUnknownRuns: usages.filter((usage) => !usage || usage.calls === null).length,
|
|
256
|
+
inputTokens: usages.reduce((sum, usage) => sum + (usage?.tokens?.input ?? 0), 0),
|
|
257
|
+
outputTokens: usages.reduce((sum, usage) => sum + (usage?.tokens?.output ?? 0), 0),
|
|
258
|
+
reasoningTokens: usages.reduce((sum, usage) => sum + (usage?.tokens?.reasoning ?? 0), 0),
|
|
259
|
+
cachedTokens: usages.reduce((sum, usage) => sum + (usage?.tokens?.cached ?? 0), 0),
|
|
260
|
+
cacheWriteTokens: usages.reduce((sum, usage) => sum + (usage?.tokens?.cacheWrite ?? 0), 0),
|
|
261
|
+
tokenUsageUnknownRuns: usages.filter((usage) => !usage?.tokens).length,
|
|
262
|
+
reasoningTokenUsageUnknownRuns: usages.filter((usage) => usage?.tokens?.reasoning === void 0).length,
|
|
263
|
+
cachedTokenUsageUnknownRuns: usages.filter((usage) => usage?.tokens?.cached === void 0).length,
|
|
264
|
+
cacheWriteTokenUsageUnknownRuns: usages.filter((usage) => usage?.tokens?.cacheWrite === void 0).length,
|
|
265
|
+
knownCostUsd,
|
|
266
|
+
costUnknownRuns: usages.filter((usage) => !usage || usage.cost.kind === "uncaptured").length
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function findingMatchesIssue(finding, issue) {
|
|
270
|
+
if (issue.findingIds && !issue.findingIds.includes(finding.finding_id)) return false;
|
|
271
|
+
if (issue.areas && !issue.areas.includes(finding.area)) return false;
|
|
272
|
+
if (issue.subjects && (!finding.subject || !issue.subjects.includes(finding.subject))) return false;
|
|
273
|
+
if (issue.evidence && !matchesEvidence(finding.evidence_refs, issue.evidence, issue.evidenceMode ?? "any")) return false;
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
function matchesEvidence(actual, expected, mode) {
|
|
277
|
+
if (expected.length === 0) return true;
|
|
278
|
+
const match = (target) => actual.some((ref) => evidenceMatches(ref, target));
|
|
279
|
+
return mode === "all" ? expected.every(match) : expected.some(match);
|
|
280
|
+
}
|
|
281
|
+
function evidenceMatches(actual, expected) {
|
|
282
|
+
return actual.uri === expected.uri && (expected.kind === void 0 || actual.kind === expected.kind);
|
|
283
|
+
}
|
|
284
|
+
function parseTraceSpanUri(uri) {
|
|
285
|
+
const match = /^trace:\/\/([^/]+)\/span\/([^/]+)$/.exec(uri);
|
|
286
|
+
if (!match) return null;
|
|
287
|
+
try {
|
|
288
|
+
const traceId = decodeURIComponent(match[1]);
|
|
289
|
+
const spanId = decodeURIComponent(match[2]);
|
|
290
|
+
return traceId && spanId ? {
|
|
291
|
+
traceId,
|
|
292
|
+
spanId
|
|
293
|
+
} : null;
|
|
294
|
+
} catch {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function validateCase(testCase) {
|
|
299
|
+
if (!testCase.id.trim()) throw new TypeError("analyst benchmark case id must not be empty");
|
|
300
|
+
const ids = /* @__PURE__ */ new Set();
|
|
301
|
+
for (const issue of testCase.expectedIssues) {
|
|
302
|
+
if (!issue.id.trim()) throw new TypeError(`${testCase.id}: expected issue id must not be empty`);
|
|
303
|
+
if (ids.has(issue.id)) throw new TypeError(`${testCase.id}: duplicate expected issue id '${issue.id}'`);
|
|
304
|
+
ids.add(issue.id);
|
|
305
|
+
if (!issue.findingIds?.length && !issue.areas?.length && !issue.subjects?.length && !issue.evidence?.length) throw new TypeError(`${testCase.id}/${issue.id}: expected issue must identify a finding by id, area, subject, or evidence`);
|
|
306
|
+
}
|
|
307
|
+
for (const ref of testCase.labeledEvidence ?? []) if (!ref.uri.trim()) throw new TypeError(`${testCase.id}: labeled evidence URI must not be empty`);
|
|
308
|
+
}
|
|
309
|
+
function validateBenchmarkOptions(options) {
|
|
310
|
+
if (options.cases.length === 0) throw new TypeError("runAnalystBenchmark requires cases");
|
|
311
|
+
if (options.runners.length === 0) throw new TypeError("runAnalystBenchmark requires runners");
|
|
312
|
+
const repetitions = options.repetitions ?? 1;
|
|
313
|
+
const maxConcurrency = options.maxConcurrency ?? 1;
|
|
314
|
+
if (!Number.isSafeInteger(repetitions) || repetitions < 1) throw new RangeError("runAnalystBenchmark repetitions must be a positive safe integer");
|
|
315
|
+
if (!Number.isSafeInteger(maxConcurrency) || maxConcurrency < 1) throw new RangeError("runAnalystBenchmark maxConcurrency must be a positive safe integer");
|
|
316
|
+
if (!Number.isSafeInteger(options.runnerOrderSeed ?? 0)) throw new RangeError("runAnalystBenchmark runnerOrderSeed must be a safe integer");
|
|
317
|
+
assertUniqueNonEmpty(options.cases.map((testCase) => testCase.id), "case");
|
|
318
|
+
assertUniqueNonEmpty(options.runners.map((runner) => runner.id), "runner");
|
|
319
|
+
for (const testCase of options.cases) validateCase(testCase);
|
|
320
|
+
}
|
|
321
|
+
function assertUniqueNonEmpty(values, label) {
|
|
322
|
+
const seen = /* @__PURE__ */ new Set();
|
|
323
|
+
for (const value of values) {
|
|
324
|
+
if (!value.trim()) throw new TypeError(`analyst benchmark ${label} id must not be empty`);
|
|
325
|
+
if (seen.has(value)) throw new TypeError(`duplicate analyst benchmark ${label} id '${value}'`);
|
|
326
|
+
seen.add(value);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function harmonicMean(a, b) {
|
|
330
|
+
return a + b === 0 ? 0 : 2 * a * b / (a + b);
|
|
331
|
+
}
|
|
332
|
+
function mean(values) {
|
|
333
|
+
return values.length === 0 ? 0 : values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
334
|
+
}
|
|
335
|
+
function latencyDistribution(values) {
|
|
336
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
337
|
+
return {
|
|
338
|
+
min: sorted[0] ?? 0,
|
|
339
|
+
mean: mean(sorted),
|
|
340
|
+
p50: percentile(sorted, .5),
|
|
341
|
+
p95: percentile(sorted, .95),
|
|
342
|
+
max: sorted.at(-1) ?? 0
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function percentile(sorted, quantile) {
|
|
346
|
+
if (sorted.length === 0) return 0;
|
|
347
|
+
return sorted[Math.ceil(quantile * sorted.length) - 1] ?? sorted.at(-1) ?? 0;
|
|
348
|
+
}
|
|
349
|
+
function stableHash(value) {
|
|
350
|
+
let hash = 2166136261;
|
|
351
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
352
|
+
hash ^= value.charCodeAt(index);
|
|
353
|
+
hash = Math.imul(hash, 16777619);
|
|
354
|
+
}
|
|
355
|
+
return hash >>> 0;
|
|
356
|
+
}
|
|
357
|
+
function issueAgreement(observations) {
|
|
358
|
+
const byCase = /* @__PURE__ */ new Map();
|
|
359
|
+
for (const observation of observations) {
|
|
360
|
+
const rows = byCase.get(observation.caseId) ?? [];
|
|
361
|
+
rows.push(observation);
|
|
362
|
+
byCase.set(observation.caseId, rows);
|
|
363
|
+
}
|
|
364
|
+
const agreements = [];
|
|
365
|
+
for (const rows of byCase.values()) for (let left = 0; left < rows.length; left++) for (let right = left + 1; right < rows.length; right++) agreements.push(jaccard(rows[left].score.matchedIssueIds, rows[right].score.matchedIssueIds));
|
|
366
|
+
return agreements.length === 0 ? null : mean(agreements);
|
|
367
|
+
}
|
|
368
|
+
function jaccard(left, right) {
|
|
369
|
+
const a = new Set(left);
|
|
370
|
+
const b = new Set(right);
|
|
371
|
+
const union = /* @__PURE__ */ new Set([...a, ...b]);
|
|
372
|
+
if (union.size === 0) return 1;
|
|
373
|
+
let intersection = 0;
|
|
374
|
+
for (const value of a) if (b.has(value)) intersection += 1;
|
|
375
|
+
return intersection / union.size;
|
|
376
|
+
}
|
|
377
|
+
function mergeRegistryUsage(result) {
|
|
378
|
+
const usages = result.per_analyst.map((summary) => summary.usage);
|
|
379
|
+
const calls = usages.every((usage) => usage.calls !== null) ? usages.reduce((sum, usage) => sum + (usage.calls ?? 0), 0) : null;
|
|
380
|
+
const tokens = usages.every((usage) => usage.tokens !== null) ? usages.reduce((sum, usage) => ({
|
|
381
|
+
input: sum.input + (usage.tokens?.input ?? 0),
|
|
382
|
+
output: sum.output + (usage.tokens?.output ?? 0),
|
|
383
|
+
reasoning: sum.reasoning + (usage.tokens?.reasoning ?? 0),
|
|
384
|
+
cached: sum.cached + (usage.tokens?.cached ?? 0),
|
|
385
|
+
cacheWrite: sum.cacheWrite + (usage.tokens?.cacheWrite ?? 0)
|
|
386
|
+
}), {
|
|
387
|
+
input: 0,
|
|
388
|
+
output: 0,
|
|
389
|
+
reasoning: 0,
|
|
390
|
+
cached: 0,
|
|
391
|
+
cacheWrite: 0
|
|
392
|
+
}) : null;
|
|
393
|
+
const knownCostUsd = usages.reduce((sum, usage) => sum + (usage.cost.kind === "uncaptured" ? usage.knownCostUsd ?? 0 : usage.cost.usd), 0);
|
|
394
|
+
const cost = usages.some((usage) => usage.cost.kind === "uncaptured") ? {
|
|
395
|
+
kind: "uncaptured",
|
|
396
|
+
usd: null
|
|
397
|
+
} : usages.some((usage) => usage.cost.kind === "estimated") ? {
|
|
398
|
+
kind: "estimated",
|
|
399
|
+
usd: knownCostUsd
|
|
400
|
+
} : {
|
|
401
|
+
kind: "observed",
|
|
402
|
+
usd: knownCostUsd
|
|
403
|
+
};
|
|
404
|
+
return {
|
|
405
|
+
calls,
|
|
406
|
+
tokens,
|
|
407
|
+
cost,
|
|
408
|
+
...cost.kind === "uncaptured" ? { knownCostUsd } : {}
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
//#endregion
|
|
412
|
+
export { traceStoreEvidenceResolver as i, runAnalystBenchmark as n, scoreAnalystFindings as r, registryBenchmarkRunner as t };
|
|
413
|
+
|
|
414
|
+
//# sourceMappingURL=benchmark-YDrpumqB.js.map
|