@opensearch-project/agent-health 0.5.2 → 0.7.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/README.md +1 -0
- package/cli/dist/index.js +2325 -961
- package/dist/assets/index-D-Np_l_T.js +246 -0
- package/dist/assets/index-vZt9QZKf.css +1 -0
- package/dist/index.html +2 -2
- package/docs/CLI.md +183 -3
- package/docs/CONFIGURATION.md +1 -1
- package/docs/CONNECTORS.md +1 -1
- package/docs/INSTRUMENT_WITH_OTEL.md +7 -0
- package/docs/SDK.md +178 -5
- package/docs/STORAGE_INDEX_FIELD_LIMITS.md +216 -0
- package/docs/skills/AGENT_HEALTH.md +55 -1
- package/docs/skills/add-connector/SKILL.md +5 -1
- package/examples/eval-files/demo.eval.js +1 -1
- package/examples/eval-files/ops-rca-classification.eval.js +71 -0
- package/examples/eval-files/ops-rca-evaluator.json +15 -0
- package/examples/eval-files/sdk-demo.eval.js +72 -0
- package/examples/eval-files/sdk-describe-demo.eval.js +50 -0
- package/examples/eval-files/sdk-hooks-demo.eval.js +1 -1
- package/lib/dist/lib/agentTrends.d.ts +210 -0
- package/lib/dist/lib/agentTrends.d.ts.map +1 -0
- package/lib/dist/lib/agentTrends.js +360 -0
- package/lib/dist/lib/agentTrends.js.map +1 -0
- package/lib/dist/lib/bedrockCompat.d.ts +27 -0
- package/lib/dist/lib/bedrockCompat.d.ts.map +1 -0
- package/lib/dist/lib/bedrockCompat.js +83 -0
- package/lib/dist/lib/bedrockCompat.js.map +1 -0
- package/lib/dist/lib/benchmarkCaseReview.d.ts +114 -0
- package/lib/dist/lib/benchmarkCaseReview.d.ts.map +1 -0
- package/lib/dist/lib/benchmarkCaseReview.js +177 -0
- package/lib/dist/lib/benchmarkCaseReview.js.map +1 -0
- package/lib/dist/lib/benchmarkImage.d.ts +52 -0
- package/lib/dist/lib/benchmarkImage.d.ts.map +1 -0
- package/lib/dist/lib/benchmarkImage.js +113 -0
- package/lib/dist/lib/benchmarkImage.js.map +1 -0
- package/lib/dist/lib/benchmarkRunsTable.d.ts +109 -0
- package/lib/dist/lib/benchmarkRunsTable.d.ts.map +1 -0
- package/lib/dist/lib/benchmarkRunsTable.js +212 -0
- package/lib/dist/lib/benchmarkRunsTable.js.map +1 -0
- package/lib/dist/lib/benchmarkVersionUtils.d.ts +13 -0
- package/lib/dist/lib/benchmarkVersionUtils.d.ts.map +1 -1
- package/lib/dist/lib/benchmarkVersionUtils.js +21 -0
- package/lib/dist/lib/benchmarkVersionUtils.js.map +1 -1
- package/lib/dist/lib/chunkedFetch.d.ts +18 -0
- package/lib/dist/lib/chunkedFetch.d.ts.map +1 -0
- package/lib/dist/lib/chunkedFetch.js +40 -0
- package/lib/dist/lib/chunkedFetch.js.map +1 -0
- package/lib/dist/lib/comparisonInsights.d.ts +151 -0
- package/lib/dist/lib/comparisonInsights.d.ts.map +1 -0
- package/lib/dist/lib/comparisonInsights.js +270 -0
- package/lib/dist/lib/comparisonInsights.js.map +1 -0
- package/lib/dist/lib/config/loader.d.ts.map +1 -1
- package/lib/dist/lib/config/loader.js +16 -1
- package/lib/dist/lib/config/loader.js.map +1 -1
- package/lib/dist/lib/config/types.d.ts +14 -0
- package/lib/dist/lib/config/types.d.ts.map +1 -1
- package/lib/dist/lib/constants.d.ts +11 -0
- package/lib/dist/lib/constants.d.ts.map +1 -1
- package/lib/dist/lib/constants.js +10 -1
- package/lib/dist/lib/constants.js.map +1 -1
- package/lib/dist/lib/contextFormat.d.ts +26 -0
- package/lib/dist/lib/contextFormat.d.ts.map +1 -0
- package/lib/dist/lib/contextFormat.js +28 -0
- package/lib/dist/lib/contextFormat.js.map +1 -0
- package/lib/dist/lib/dashboardMetrics.d.ts +11 -2
- package/lib/dist/lib/dashboardMetrics.d.ts.map +1 -1
- package/lib/dist/lib/dashboardMetrics.js +38 -3
- package/lib/dist/lib/dashboardMetrics.js.map +1 -1
- package/lib/dist/lib/envCompat.d.ts.map +1 -1
- package/lib/dist/lib/envCompat.js +14 -5
- package/lib/dist/lib/envCompat.js.map +1 -1
- package/lib/dist/lib/evaluationRerun.d.ts +102 -0
- package/lib/dist/lib/evaluationRerun.d.ts.map +1 -0
- package/lib/dist/lib/evaluationRerun.js +134 -0
- package/lib/dist/lib/evaluationRerun.js.map +1 -0
- package/lib/dist/lib/judgeFailureSummary.d.ts +66 -0
- package/lib/dist/lib/judgeFailureSummary.d.ts.map +1 -0
- package/lib/dist/lib/judgeFailureSummary.js +68 -0
- package/lib/dist/lib/judgeFailureSummary.js.map +1 -0
- package/lib/dist/lib/judgeStrategies.d.ts +108 -0
- package/lib/dist/lib/judgeStrategies.d.ts.map +1 -0
- package/lib/dist/lib/judgeStrategies.js +135 -0
- package/lib/dist/lib/judgeStrategies.js.map +1 -0
- package/lib/dist/lib/matchers/expect.d.ts +21 -1
- package/lib/dist/lib/matchers/expect.d.ts.map +1 -1
- package/lib/dist/lib/matchers/expect.js +51 -0
- package/lib/dist/lib/matchers/expect.js.map +1 -1
- package/lib/dist/lib/matchers/judgeAccessor.d.ts +4 -0
- package/lib/dist/lib/matchers/judgeAccessor.d.ts.map +1 -1
- package/lib/dist/lib/matchers/judgeAccessor.js +13 -2
- package/lib/dist/lib/matchers/judgeAccessor.js.map +1 -1
- package/lib/dist/lib/matchers/judgeReasoningParse.d.ts +49 -0
- package/lib/dist/lib/matchers/judgeReasoningParse.d.ts.map +1 -0
- package/lib/dist/lib/matchers/judgeReasoningParse.js +128 -0
- package/lib/dist/lib/matchers/judgeReasoningParse.js.map +1 -0
- package/lib/dist/lib/matchers/traces.d.ts +17 -2
- package/lib/dist/lib/matchers/traces.d.ts.map +1 -1
- package/lib/dist/lib/matchers/traces.js +136 -16
- package/lib/dist/lib/matchers/traces.js.map +1 -1
- package/lib/dist/lib/matchers/tracesPricing.d.ts +38 -0
- package/lib/dist/lib/matchers/tracesPricing.d.ts.map +1 -0
- package/lib/dist/lib/matchers/tracesPricing.js +64 -0
- package/lib/dist/lib/matchers/tracesPricing.js.map +1 -0
- package/lib/dist/lib/matchers/types.d.ts +25 -0
- package/lib/dist/lib/matchers/types.d.ts.map +1 -1
- package/lib/dist/lib/resolveCanonicalRun.d.ts +23 -0
- package/lib/dist/lib/resolveCanonicalRun.d.ts.map +1 -0
- package/lib/dist/lib/resolveCanonicalRun.js +26 -0
- package/lib/dist/lib/resolveCanonicalRun.js.map +1 -0
- package/lib/dist/lib/runActions.d.ts +120 -0
- package/lib/dist/lib/runActions.d.ts.map +1 -0
- package/lib/dist/lib/runActions.js +130 -0
- package/lib/dist/lib/runActions.js.map +1 -0
- package/lib/dist/lib/runInsights.d.ts +86 -0
- package/lib/dist/lib/runInsights.d.ts.map +1 -0
- package/lib/dist/lib/runInsights.js +185 -0
- package/lib/dist/lib/runInsights.js.map +1 -0
- package/lib/dist/lib/runName.d.ts +29 -0
- package/lib/dist/lib/runName.d.ts.map +1 -0
- package/lib/dist/lib/runName.js +38 -0
- package/lib/dist/lib/runName.js.map +1 -0
- package/lib/dist/lib/runReportPath.d.ts +16 -0
- package/lib/dist/lib/runReportPath.d.ts.map +1 -0
- package/lib/dist/lib/runReportPath.js +22 -0
- package/lib/dist/lib/runReportPath.js.map +1 -0
- package/lib/dist/lib/runSort.d.ts +27 -0
- package/lib/dist/lib/runSort.d.ts.map +1 -0
- package/lib/dist/lib/runSort.js +31 -0
- package/lib/dist/lib/runSort.js.map +1 -0
- package/lib/dist/lib/runStats.d.ts +109 -5
- package/lib/dist/lib/runStats.d.ts.map +1 -1
- package/lib/dist/lib/runStats.js +193 -10
- package/lib/dist/lib/runStats.js.map +1 -1
- package/lib/dist/lib/testCases/define.d.ts.map +1 -1
- package/lib/dist/lib/testCases/define.js +93 -46
- package/lib/dist/lib/testCases/define.js.map +1 -1
- package/lib/dist/lib/testCases/judge.d.ts.map +1 -1
- package/lib/dist/lib/testCases/judge.js +22 -4
- package/lib/dist/lib/testCases/judge.js.map +1 -1
- package/lib/dist/lib/testCases/loader.d.ts +35 -1
- package/lib/dist/lib/testCases/loader.d.ts.map +1 -1
- package/lib/dist/lib/testCases/loader.js +278 -31
- package/lib/dist/lib/testCases/loader.js.map +1 -1
- package/lib/dist/lib/trajectoryStepDisplay.d.ts +25 -0
- package/lib/dist/lib/trajectoryStepDisplay.d.ts.map +1 -0
- package/lib/dist/lib/trajectoryStepDisplay.js +42 -0
- package/lib/dist/lib/trajectoryStepDisplay.js.map +1 -0
- package/lib/dist/lib/utils.d.ts +34 -0
- package/lib/dist/lib/utils.d.ts.map +1 -1
- package/lib/dist/lib/utils.js +49 -0
- package/lib/dist/lib/utils.js.map +1 -1
- package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.d.ts +68 -22
- package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.d.ts.map +1 -1
- package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.js +148 -111
- package/lib/dist/services/connectors/claude-code/ClaudeCodeConnector.js.map +1 -1
- package/lib/dist/services/connectors/kiro/KiroConnector.d.ts +21 -13
- package/lib/dist/services/connectors/kiro/KiroConnector.d.ts.map +1 -1
- package/lib/dist/services/connectors/kiro/KiroConnector.js +22 -25
- package/lib/dist/services/connectors/kiro/KiroConnector.js.map +1 -1
- package/lib/dist/services/connectors/pi/PiConnector.d.ts +49 -10
- package/lib/dist/services/connectors/pi/PiConnector.d.ts.map +1 -1
- package/lib/dist/services/connectors/pi/PiConnector.js +102 -86
- package/lib/dist/services/connectors/pi/PiConnector.js.map +1 -1
- package/lib/dist/services/connectors/subprocess/SubprocessConnector.d.ts +59 -14
- package/lib/dist/services/connectors/subprocess/SubprocessConnector.d.ts.map +1 -1
- package/lib/dist/services/connectors/subprocess/SubprocessConnector.js +95 -61
- package/lib/dist/services/connectors/subprocess/SubprocessConnector.js.map +1 -1
- package/lib/dist/services/evaluation/bedrockJudge.d.ts +18 -0
- package/lib/dist/services/evaluation/bedrockJudge.d.ts.map +1 -1
- package/lib/dist/services/evaluation/bedrockJudge.js +4 -0
- package/lib/dist/services/evaluation/bedrockJudge.js.map +1 -1
- package/lib/dist/services/evaluation/index.d.ts +18 -1
- package/lib/dist/services/evaluation/index.d.ts.map +1 -1
- package/lib/dist/services/evaluation/index.js +156 -19
- package/lib/dist/services/evaluation/index.js.map +1 -1
- package/lib/dist/services/metrics.d.ts +55 -0
- package/lib/dist/services/metrics.d.ts.map +1 -0
- package/lib/dist/services/metrics.js +89 -0
- package/lib/dist/services/metrics.js.map +1 -0
- package/lib/dist/services/storage/asyncBenchmarkStorage.d.ts +1 -1
- package/lib/dist/services/storage/asyncBenchmarkStorage.d.ts.map +1 -1
- package/lib/dist/services/storage/asyncBenchmarkStorage.js +30 -3
- package/lib/dist/services/storage/asyncBenchmarkStorage.js.map +1 -1
- package/lib/dist/services/storage/asyncRunStorage.d.ts +20 -1
- package/lib/dist/services/storage/asyncRunStorage.d.ts.map +1 -1
- package/lib/dist/services/storage/asyncRunStorage.js +125 -2
- package/lib/dist/services/storage/asyncRunStorage.js.map +1 -1
- package/lib/dist/services/storage/asyncTestCaseStorage.d.ts +18 -4
- package/lib/dist/services/storage/asyncTestCaseStorage.d.ts.map +1 -1
- package/lib/dist/services/storage/asyncTestCaseStorage.js +21 -4
- package/lib/dist/services/storage/asyncTestCaseStorage.js.map +1 -1
- package/lib/dist/services/storage/opensearchClient.d.ts +47 -12
- package/lib/dist/services/storage/opensearchClient.d.ts.map +1 -1
- package/lib/dist/services/storage/opensearchClient.js +12 -5
- package/lib/dist/services/storage/opensearchClient.js.map +1 -1
- package/lib/dist/services/traces/browserRecovery.d.ts +12 -1
- package/lib/dist/services/traces/browserRecovery.d.ts.map +1 -1
- package/lib/dist/services/traces/browserRecovery.js +35 -5
- package/lib/dist/services/traces/browserRecovery.js.map +1 -1
- package/lib/dist/services/traces/index.d.ts +8 -1
- package/lib/dist/services/traces/index.d.ts.map +1 -1
- package/lib/dist/services/traces/index.js +33 -12
- package/lib/dist/services/traces/index.js.map +1 -1
- package/lib/dist/services/traces/judgeAgentsHints.d.ts +98 -3
- package/lib/dist/services/traces/judgeAgentsHints.d.ts.map +1 -1
- package/lib/dist/services/traces/judgeAgentsHints.js +144 -3
- package/lib/dist/services/traces/judgeAgentsHints.js.map +1 -1
- package/lib/dist/services/traces/messageExtraction.d.ts.map +1 -1
- package/lib/dist/services/traces/messageExtraction.js +95 -33
- package/lib/dist/services/traces/messageExtraction.js.map +1 -1
- package/lib/dist/services/traces/spansToTrajectory.d.ts.map +1 -1
- package/lib/dist/services/traces/spansToTrajectory.js +51 -13
- package/lib/dist/services/traces/spansToTrajectory.js.map +1 -1
- package/lib/dist/services/traces/tracePoller.d.ts +27 -3
- package/lib/dist/services/traces/tracePoller.d.ts.map +1 -1
- package/lib/dist/services/traces/tracePoller.js +196 -33
- package/lib/dist/services/traces/tracePoller.js.map +1 -1
- package/lib/dist/services/traces/trajectoryMerge.d.ts +79 -0
- package/lib/dist/services/traces/trajectoryMerge.d.ts.map +1 -0
- package/lib/dist/services/traces/trajectoryMerge.js +109 -0
- package/lib/dist/services/traces/trajectoryMerge.js.map +1 -0
- package/lib/dist/types/index.d.ts +250 -3
- package/lib/dist/types/index.d.ts.map +1 -1
- package/lib/dist/types/index.js +24 -0
- package/lib/dist/types/index.js.map +1 -1
- package/package.json +8 -5
- package/server/dist/app.js +5490 -1557
- package/server/dist/index.js +5490 -1557
- package/dist/assets/index-CCQRDlO0.js +0 -243
- package/dist/assets/index-CNHQVbcj.css +0 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright OpenSearch Contributors
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Bedrock model compatibility helpers shared by every Bedrock Converse call
|
|
7
|
+
* site (judge, skill eval generator, skill improver, failure clustering,
|
|
8
|
+
* assistant fallback).
|
|
9
|
+
*
|
|
10
|
+
* Two concerns live here so the policy is defined exactly once:
|
|
11
|
+
*
|
|
12
|
+
* 1. **Temperature deprecation** — newer Anthropic models (Claude Opus 4.5+,
|
|
13
|
+
* Sonnet 4.6+, and the Claude 5 family incl. Fable/Mythos) reject an
|
|
14
|
+
* explicit `temperature` with `ValidationException: 'temperature' is
|
|
15
|
+
* deprecated for this model`. `buildInferenceConfig()` omits the field for
|
|
16
|
+
* those models and lets the model use its default. (GitHub issue #299)
|
|
17
|
+
*
|
|
18
|
+
* 2. **Region-aware inference profiles** — the default model registry pins
|
|
19
|
+
* `us.`-prefixed cross-region inference profile ids, which only resolve
|
|
20
|
+
* from US regions. `resolveRegionAwareModelId()` swaps the prefix to the
|
|
21
|
+
* one matching the active AWS region (`eu.` / `apac.`) at call time, so
|
|
22
|
+
* the registry itself stays region-neutral. (GitHub issue #298)
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Model-id patterns that have deprecated the `temperature` parameter.
|
|
26
|
+
* Matched case-insensitively against the full model/inference-profile id.
|
|
27
|
+
*/
|
|
28
|
+
const TEMPERATURE_DEPRECATED_PATTERNS = [
|
|
29
|
+
/claude-opus-4-[5-9]/, // Opus 4.5, 4.6, 4.7, 4.8, ...
|
|
30
|
+
/claude-sonnet-4-[6-9]/, // Sonnet 4.6+ (4.5 still accepts temperature)
|
|
31
|
+
/claude-[a-z]+-5(?![0-9])/, // Claude 5 family: fable-5, mythos-5, opus-5, sonnet-5, ...
|
|
32
|
+
];
|
|
33
|
+
/** Whether the given Bedrock model still accepts an explicit `temperature`. */
|
|
34
|
+
export function modelSupportsTemperature(modelId) {
|
|
35
|
+
const id = (modelId || '').toLowerCase();
|
|
36
|
+
return !TEMPERATURE_DEPRECATED_PATTERNS.some((p) => p.test(id));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build a Converse `inferenceConfig`, including `temperature` only when the
|
|
40
|
+
* target model accepts it. Callers pass their preferred temperature; for
|
|
41
|
+
* models that have deprecated the parameter it is silently omitted (the
|
|
42
|
+
* model's own default applies).
|
|
43
|
+
*/
|
|
44
|
+
export function buildInferenceConfig(modelId, opts) {
|
|
45
|
+
const cfg = { maxTokens: opts.maxTokens };
|
|
46
|
+
if (opts.temperature !== undefined && modelSupportsTemperature(modelId)) {
|
|
47
|
+
cfg.temperature = opts.temperature;
|
|
48
|
+
}
|
|
49
|
+
return cfg;
|
|
50
|
+
}
|
|
51
|
+
/** Inference-profile prefix appropriate for the given (or current) AWS region. */
|
|
52
|
+
export function regionInferencePrefix(region) {
|
|
53
|
+
const r = (region ||
|
|
54
|
+
process.env.AWS_REGION ||
|
|
55
|
+
process.env.AWS_DEFAULT_REGION ||
|
|
56
|
+
'us-east-1').toLowerCase();
|
|
57
|
+
if (r.startsWith('eu-'))
|
|
58
|
+
return 'eu.';
|
|
59
|
+
if (r.startsWith('ap-'))
|
|
60
|
+
return 'apac.';
|
|
61
|
+
return 'us.';
|
|
62
|
+
}
|
|
63
|
+
const CROSS_REGION_PREFIXES = ['us.', 'eu.', 'apac.'];
|
|
64
|
+
/**
|
|
65
|
+
* Re-home a cross-region inference-profile id to the active AWS region.
|
|
66
|
+
*
|
|
67
|
+
* `us.anthropic.claude-...` → `eu.anthropic.claude-...` when running in an
|
|
68
|
+
* EU region, etc. Ids that carry no regional prefix (bare model ids,
|
|
69
|
+
* `global.` profiles, non-Bedrock ids like `mock://` or `gpt-4o`) are
|
|
70
|
+
* returned unchanged.
|
|
71
|
+
*/
|
|
72
|
+
export function resolveRegionAwareModelId(modelId, region) {
|
|
73
|
+
if (!modelId)
|
|
74
|
+
return modelId;
|
|
75
|
+
const target = regionInferencePrefix(region);
|
|
76
|
+
for (const prefix of CROSS_REGION_PREFIXES) {
|
|
77
|
+
if (modelId.startsWith(prefix)) {
|
|
78
|
+
return prefix === target ? modelId : target + modelId.slice(prefix.length);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return modelId;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=bedrockCompat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bedrockCompat.js","sourceRoot":"","sources":["../../bedrockCompat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;GAGG;AACH,MAAM,+BAA+B,GAAa;IAChD,qBAAqB,EAAE,+BAA+B;IACtD,uBAAuB,EAAE,8CAA8C;IACvE,0BAA0B,EAAE,4DAA4D;CACzF,CAAC;AAEF,+EAA+E;AAC/E,MAAM,UAAU,wBAAwB,CAAC,OAAe;IACtD,MAAM,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACzC,OAAO,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,IAAiD;IAEjD,MAAM,GAAG,GAAgD,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;IACvF,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,wBAAwB,CAAC,OAAO,CAAC,EAAE,CAAC;QACxE,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IACrC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,qBAAqB,CAAC,MAAe;IACnD,MAAM,CAAC,GAAG,CACR,MAAM;QACN,OAAO,CAAC,GAAG,CAAC,UAAU;QACtB,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAC9B,WAAW,CACZ,CAAC,WAAW,EAAE,CAAC;IAChB,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAU,CAAC;AAE/D;;;;;;;GAOG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAe,EAAE,MAAe;IACxE,IAAI,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC;IAC7B,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC7C,KAAK,MAAM,MAAM,IAAI,qBAAqB,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,OAAO,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helpers for the benchmark case-review matrix.
|
|
3
|
+
*
|
|
4
|
+
* The benchmark document supplies the canonical run/case relationship, while
|
|
5
|
+
* lightweight report summaries supply the actual pass/fail/error verdicts.
|
|
6
|
+
* Keeping this logic outside React makes the bucket priority and pager order
|
|
7
|
+
* deterministic (and cheap to test) for suites with hundreds of cases.
|
|
8
|
+
*/
|
|
9
|
+
export type CaseVerdict = 'passed' | 'failed' | 'errored' | 'not-run';
|
|
10
|
+
export type CaseReviewBucket = 'needs-attention' | 'flaky' | 'stable' | 'no-data';
|
|
11
|
+
export type CaseReviewFilter = 'all' | Exclude<CaseReviewBucket, 'no-data'>;
|
|
12
|
+
export type SwipeDirection = 'prev' | 'next';
|
|
13
|
+
export interface PagerDragInput {
|
|
14
|
+
dx: number;
|
|
15
|
+
dy: number;
|
|
16
|
+
latched: boolean;
|
|
17
|
+
atStart: boolean;
|
|
18
|
+
atEnd: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface PagerDragResult {
|
|
21
|
+
offset: number;
|
|
22
|
+
latched: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Latch a horizontal pager drag after a small slop, then preserve that latch
|
|
26
|
+
* for the rest of the gesture. Pulling beyond either end receives resistance
|
|
27
|
+
* so the pane communicates the boundary without changing cases.
|
|
28
|
+
*
|
|
29
|
+
* Reduced-motion behavior intentionally stays out of this geometry helper;
|
|
30
|
+
* callers suppress the returned offset while retaining gesture navigation.
|
|
31
|
+
*/
|
|
32
|
+
export declare function computePagerDrag({ dx, dy, latched, atStart, atEnd, }: PagerDragInput): PagerDragResult;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve a completed gesture without suppressing native touch movement. A
|
|
35
|
+
* negative x displacement is a left swipe (next); a positive one is previous.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveSwipeDirection(dx: number, dy: number, touchCount?: number): SwipeDirection | null;
|
|
38
|
+
export interface VerdictReportSummary {
|
|
39
|
+
status?: string;
|
|
40
|
+
passFailStatus?: 'passed' | 'failed' | null;
|
|
41
|
+
metricsStatus?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface VerdictRunResult {
|
|
44
|
+
reportId?: string;
|
|
45
|
+
status?: string;
|
|
46
|
+
/** Present on newer embedded benchmark results; reports remain authoritative. */
|
|
47
|
+
passFailStatus?: 'passed' | 'failed';
|
|
48
|
+
}
|
|
49
|
+
export interface VerdictRun {
|
|
50
|
+
id: string;
|
|
51
|
+
createdAt: string;
|
|
52
|
+
status?: string;
|
|
53
|
+
results?: Record<string, VerdictRunResult>;
|
|
54
|
+
}
|
|
55
|
+
export interface ReviewableCase {
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
prompt?: string;
|
|
59
|
+
}
|
|
60
|
+
export interface CaseReviewRow<T extends ReviewableCase = ReviewableCase> {
|
|
61
|
+
testCase: T;
|
|
62
|
+
verdicts: CaseVerdict[];
|
|
63
|
+
bucket: CaseReviewBucket;
|
|
64
|
+
passRate: number | null;
|
|
65
|
+
}
|
|
66
|
+
/** A legacy run with no top-level status is complete once all results are terminal. */
|
|
67
|
+
export declare function isCompletedVerdictRun(run: VerdictRun): boolean;
|
|
68
|
+
export declare function getRecentCompletedRuns<T extends VerdictRun>(runs: T[], limit?: number): T[];
|
|
69
|
+
/**
|
|
70
|
+
* Resolve one case×run cell. A real pass/fail verdict from the report is
|
|
71
|
+
* authoritative and outranks `metricsStatus === 'error'`: metrics/cost
|
|
72
|
+
* enrichment runs after the agent-vs-judge verdict is already known, so a
|
|
73
|
+
* later enrichment failure must not overwrite a genuine pass/fail with
|
|
74
|
+
* 'errored'. `metricsStatus === 'error'` only decides the cell when the
|
|
75
|
+
* report has no real passFailStatus yet.
|
|
76
|
+
*/
|
|
77
|
+
export declare function deriveCaseVerdict(run: VerdictRun, testCaseId: string, reportsById: Record<string, VerdictReportSummary | undefined>): CaseVerdict;
|
|
78
|
+
export declare function deriveCaseVerdicts(runs: VerdictRun[], testCaseId: string, reportsById: Record<string, VerdictReportSummary | undefined>): CaseVerdict[];
|
|
79
|
+
/**
|
|
80
|
+
* Buckets are disjoint by priority. Evaluator errors require attention but do
|
|
81
|
+
* not become failed verdicts or enter the pass-rate denominator.
|
|
82
|
+
*/
|
|
83
|
+
export declare function classifyCaseVerdicts(verdicts: CaseVerdict[]): CaseReviewBucket;
|
|
84
|
+
export declare function getCasePassRate(verdicts: CaseVerdict[]): number | null;
|
|
85
|
+
export declare function buildCaseReviewRows<T extends ReviewableCase>(testCases: T[], recentRuns: VerdictRun[], reportsById: Record<string, VerdictReportSummary | undefined>): CaseReviewRow<T>[];
|
|
86
|
+
/** Search/filter first, then pass-rate ascending; no-data sorts last. */
|
|
87
|
+
export declare function filterAndSortCaseRows<T extends ReviewableCase>(rows: CaseReviewRow<T>[], search: string, filter: CaseReviewFilter): CaseReviewRow<T>[];
|
|
88
|
+
export declare function getCasePagerPosition<T extends ReviewableCase>(rows: CaseReviewRow<T>[], selectedCaseId: string | undefined): {
|
|
89
|
+
index: number;
|
|
90
|
+
position: number;
|
|
91
|
+
total: number;
|
|
92
|
+
previousId?: string;
|
|
93
|
+
nextId?: string;
|
|
94
|
+
};
|
|
95
|
+
export interface VersionedRunResult {
|
|
96
|
+
reportId?: string;
|
|
97
|
+
}
|
|
98
|
+
export interface VersionedRun {
|
|
99
|
+
results?: Record<string, VersionedRunResult>;
|
|
100
|
+
}
|
|
101
|
+
export interface VersionedReportSummary {
|
|
102
|
+
testCaseVersion?: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The Cases tab always renders a case's *current* definition, even when the
|
|
106
|
+
* user arrived from a specific historical run (e.g. a heat-strip cell click).
|
|
107
|
+
* This detects that mismatch so callers can show a minimal, honest notice
|
|
108
|
+
* instead of silently presenting a definition the run never actually used.
|
|
109
|
+
* Deliberately does not resurrect the old per-version selector — just a
|
|
110
|
+
* disclosure that the definition may have changed since some of the runs
|
|
111
|
+
* shown here.
|
|
112
|
+
*/
|
|
113
|
+
export declare function hasHistoricalVersionMismatch(currentVersion: number, runs: VersionedRun[], testCaseId: string, reportsById: Record<string, VersionedReportSummary | undefined>): boolean;
|
|
114
|
+
//# sourceMappingURL=benchmarkCaseReview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmarkCaseReview.d.ts","sourceRoot":"","sources":["../../benchmarkCaseReview.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright OpenSearch Contributors
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
const MIN_SWIPE_DISTANCE = 48;
|
|
6
|
+
const HORIZONTAL_SWIPE_RATIO = 1.5;
|
|
7
|
+
const PAGER_DRAG_SLOP = 10;
|
|
8
|
+
const PAGER_EDGE_RESISTANCE = 0.35;
|
|
9
|
+
/**
|
|
10
|
+
* Latch a horizontal pager drag after a small slop, then preserve that latch
|
|
11
|
+
* for the rest of the gesture. Pulling beyond either end receives resistance
|
|
12
|
+
* so the pane communicates the boundary without changing cases.
|
|
13
|
+
*
|
|
14
|
+
* Reduced-motion behavior intentionally stays out of this geometry helper;
|
|
15
|
+
* callers suppress the returned offset while retaining gesture navigation.
|
|
16
|
+
*/
|
|
17
|
+
export function computePagerDrag({ dx, dy, latched, atStart, atEnd, }) {
|
|
18
|
+
const nextLatched = latched || (Math.abs(dx) > PAGER_DRAG_SLOP &&
|
|
19
|
+
Math.abs(dx) > Math.abs(dy));
|
|
20
|
+
if (!nextLatched)
|
|
21
|
+
return { offset: 0, latched: false };
|
|
22
|
+
const beyondStart = atStart && dx > 0;
|
|
23
|
+
const beyondEnd = atEnd && dx < 0;
|
|
24
|
+
return {
|
|
25
|
+
offset: (beyondStart || beyondEnd) ? dx * PAGER_EDGE_RESISTANCE : dx,
|
|
26
|
+
latched: true,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a completed gesture without suppressing native touch movement. A
|
|
31
|
+
* negative x displacement is a left swipe (next); a positive one is previous.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveSwipeDirection(dx, dy, touchCount = 1) {
|
|
34
|
+
if (touchCount !== 1)
|
|
35
|
+
return null;
|
|
36
|
+
if (Math.abs(dx) < MIN_SWIPE_DISTANCE)
|
|
37
|
+
return null;
|
|
38
|
+
if (Math.abs(dx) < HORIZONTAL_SWIPE_RATIO * Math.abs(dy))
|
|
39
|
+
return null;
|
|
40
|
+
return dx < 0 ? 'next' : 'prev';
|
|
41
|
+
}
|
|
42
|
+
/** A legacy run with no top-level status is complete once all results are terminal. */
|
|
43
|
+
export function isCompletedVerdictRun(run) {
|
|
44
|
+
if (run.status)
|
|
45
|
+
return run.status === 'completed';
|
|
46
|
+
const results = Object.values(run.results || {});
|
|
47
|
+
return results.length > 0 && results.every(result => result.status !== 'pending' && result.status !== 'running');
|
|
48
|
+
}
|
|
49
|
+
export function getRecentCompletedRuns(runs, limit = 5) {
|
|
50
|
+
return [...runs]
|
|
51
|
+
.filter(isCompletedVerdictRun)
|
|
52
|
+
.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())
|
|
53
|
+
.slice(0, limit);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve one case×run cell. A real pass/fail verdict from the report is
|
|
57
|
+
* authoritative and outranks `metricsStatus === 'error'`: metrics/cost
|
|
58
|
+
* enrichment runs after the agent-vs-judge verdict is already known, so a
|
|
59
|
+
* later enrichment failure must not overwrite a genuine pass/fail with
|
|
60
|
+
* 'errored'. `metricsStatus === 'error'` only decides the cell when the
|
|
61
|
+
* report has no real passFailStatus yet.
|
|
62
|
+
*/
|
|
63
|
+
export function deriveCaseVerdict(run, testCaseId, reportsById) {
|
|
64
|
+
const result = run.results?.[testCaseId];
|
|
65
|
+
if (!result || result.status === 'pending' || result.status === 'running')
|
|
66
|
+
return 'not-run';
|
|
67
|
+
const report = result.reportId ? reportsById[result.reportId] : undefined;
|
|
68
|
+
if (report?.passFailStatus === 'passed')
|
|
69
|
+
return 'passed';
|
|
70
|
+
if (report?.passFailStatus === 'failed')
|
|
71
|
+
return 'failed';
|
|
72
|
+
if (report?.metricsStatus === 'error')
|
|
73
|
+
return 'errored';
|
|
74
|
+
// New benchmark documents carry this summary. It is a resilience fallback
|
|
75
|
+
// for deleted/legacy report documents, not the primary source of truth.
|
|
76
|
+
if (result.passFailStatus === 'passed')
|
|
77
|
+
return 'passed';
|
|
78
|
+
if (result.passFailStatus === 'failed')
|
|
79
|
+
return 'failed';
|
|
80
|
+
if (result.status === 'failed' || result.status === 'cancelled' || report?.status === 'failed') {
|
|
81
|
+
return 'failed';
|
|
82
|
+
}
|
|
83
|
+
// A completed result without a verdict means the evaluator did not produce
|
|
84
|
+
// a usable score. Keep it visually/semantically separate from agent failure.
|
|
85
|
+
if (result.status === 'completed')
|
|
86
|
+
return 'errored';
|
|
87
|
+
return 'not-run';
|
|
88
|
+
}
|
|
89
|
+
export function deriveCaseVerdicts(runs, testCaseId, reportsById) {
|
|
90
|
+
return runs.map(run => deriveCaseVerdict(run, testCaseId, reportsById));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Buckets are disjoint by priority. Evaluator errors require attention but do
|
|
94
|
+
* not become failed verdicts or enter the pass-rate denominator.
|
|
95
|
+
*/
|
|
96
|
+
export function classifyCaseVerdicts(verdicts) {
|
|
97
|
+
const observed = verdicts.filter(verdict => verdict !== 'not-run');
|
|
98
|
+
if (observed.length === 0)
|
|
99
|
+
return 'no-data';
|
|
100
|
+
const latestThree = verdicts.slice(0, 3);
|
|
101
|
+
if (latestThree.some(verdict => verdict === 'failed' || verdict === 'errored')) {
|
|
102
|
+
return 'needs-attention';
|
|
103
|
+
}
|
|
104
|
+
const scored = verdicts.filter(verdict => verdict === 'passed' || verdict === 'failed');
|
|
105
|
+
const hasPass = scored.includes('passed');
|
|
106
|
+
const hasFail = scored.includes('failed');
|
|
107
|
+
if (hasPass && hasFail)
|
|
108
|
+
return 'flaky';
|
|
109
|
+
if (hasPass)
|
|
110
|
+
return 'stable';
|
|
111
|
+
// Sparse histories can put an old failure/error outside the last-three
|
|
112
|
+
// window. They still have data and are not passing, so attention is the only
|
|
113
|
+
// honest bucket.
|
|
114
|
+
return 'needs-attention';
|
|
115
|
+
}
|
|
116
|
+
export function getCasePassRate(verdicts) {
|
|
117
|
+
const passed = verdicts.filter(verdict => verdict === 'passed').length;
|
|
118
|
+
const failed = verdicts.filter(verdict => verdict === 'failed').length;
|
|
119
|
+
return passed + failed === 0 ? null : passed / (passed + failed);
|
|
120
|
+
}
|
|
121
|
+
export function buildCaseReviewRows(testCases, recentRuns, reportsById) {
|
|
122
|
+
return testCases.map(testCase => {
|
|
123
|
+
const verdicts = deriveCaseVerdicts(recentRuns, testCase.id, reportsById);
|
|
124
|
+
return {
|
|
125
|
+
testCase,
|
|
126
|
+
verdicts,
|
|
127
|
+
bucket: classifyCaseVerdicts(verdicts),
|
|
128
|
+
passRate: getCasePassRate(verdicts),
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/** Search/filter first, then pass-rate ascending; no-data sorts last. */
|
|
133
|
+
export function filterAndSortCaseRows(rows, search, filter) {
|
|
134
|
+
const query = search.trim().toLocaleLowerCase();
|
|
135
|
+
return rows
|
|
136
|
+
.filter(row => filter === 'all' || row.bucket === filter)
|
|
137
|
+
.filter(row => !query ||
|
|
138
|
+
row.testCase.name.toLocaleLowerCase().includes(query) ||
|
|
139
|
+
(row.testCase.prompt || '').toLocaleLowerCase().includes(query))
|
|
140
|
+
.sort((a, b) => {
|
|
141
|
+
if (a.passRate === null && b.passRate !== null)
|
|
142
|
+
return 1;
|
|
143
|
+
if (a.passRate !== null && b.passRate === null)
|
|
144
|
+
return -1;
|
|
145
|
+
if (a.passRate !== null && b.passRate !== null && a.passRate !== b.passRate) {
|
|
146
|
+
return a.passRate - b.passRate;
|
|
147
|
+
}
|
|
148
|
+
return a.testCase.name.localeCompare(b.testCase.name);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
export function getCasePagerPosition(rows, selectedCaseId) {
|
|
152
|
+
const index = selectedCaseId ? rows.findIndex(row => row.testCase.id === selectedCaseId) : -1;
|
|
153
|
+
return {
|
|
154
|
+
index,
|
|
155
|
+
position: index >= 0 ? index + 1 : 0,
|
|
156
|
+
total: rows.length,
|
|
157
|
+
previousId: index > 0 ? rows[index - 1].testCase.id : undefined,
|
|
158
|
+
nextId: index >= 0 && index < rows.length - 1 ? rows[index + 1].testCase.id : undefined,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The Cases tab always renders a case's *current* definition, even when the
|
|
163
|
+
* user arrived from a specific historical run (e.g. a heat-strip cell click).
|
|
164
|
+
* This detects that mismatch so callers can show a minimal, honest notice
|
|
165
|
+
* instead of silently presenting a definition the run never actually used.
|
|
166
|
+
* Deliberately does not resurrect the old per-version selector — just a
|
|
167
|
+
* disclosure that the definition may have changed since some of the runs
|
|
168
|
+
* shown here.
|
|
169
|
+
*/
|
|
170
|
+
export function hasHistoricalVersionMismatch(currentVersion, runs, testCaseId, reportsById) {
|
|
171
|
+
return runs.some(run => {
|
|
172
|
+
const result = run.results?.[testCaseId];
|
|
173
|
+
const report = result?.reportId ? reportsById[result.reportId] : undefined;
|
|
174
|
+
return typeof report?.testCaseVersion === 'number' && report.testCaseVersion !== currentVersion;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=benchmarkCaseReview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmarkCaseReview.js","sourceRoot":"","sources":["../../benchmarkCaseReview.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { BenchmarkImage, TestCase } from '../types/index.js';
|
|
2
|
+
/** Eval conditions frozen into an image digest. */
|
|
3
|
+
export interface ImageEvalConditions {
|
|
4
|
+
evaluatorId?: string;
|
|
5
|
+
judgeModelId?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Bump when the digest input shape changes (invalidates old digests). */
|
|
8
|
+
export declare const IMAGE_DIGEST_VERSION = 1;
|
|
9
|
+
/**
|
|
10
|
+
* Deterministic JSON: objects serialized with sorted keys, recursively.
|
|
11
|
+
* Arrays keep their order (order-sensitivity is decided by the caller).
|
|
12
|
+
*/
|
|
13
|
+
export declare function canonicalStringify(value: unknown): string;
|
|
14
|
+
/**
|
|
15
|
+
* Content fingerprint of a single test case. Uses CONTENT only — never the
|
|
16
|
+
* storage id — so re-imported test cases (fresh ids, same content) fingerprint
|
|
17
|
+
* identically. Fields chosen to match what actually changes agent behavior
|
|
18
|
+
* and judging: prompt, context, expected outcomes/trajectory, tools.
|
|
19
|
+
*/
|
|
20
|
+
export declare function fingerprintTestCase(tc: Partial<TestCase> & {
|
|
21
|
+
name: string;
|
|
22
|
+
}): {
|
|
23
|
+
name: string;
|
|
24
|
+
contentHash: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Compute the image digest for a set of test cases + eval conditions.
|
|
28
|
+
* Order-insensitive over test cases (fingerprints are sorted), content- and
|
|
29
|
+
* condition-sensitive.
|
|
30
|
+
*/
|
|
31
|
+
export declare function computeImageDigest(input: {
|
|
32
|
+
testCases: Array<Partial<TestCase> & {
|
|
33
|
+
name: string;
|
|
34
|
+
}>;
|
|
35
|
+
evalConditions?: ImageEvalConditions;
|
|
36
|
+
}): string;
|
|
37
|
+
/** Storage id for an image doc (content-addressed — one doc per digest). */
|
|
38
|
+
export declare function imageIdForDigest(digest: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Build a full image doc for storage. `create` on the storage side is
|
|
41
|
+
* find-or-create keyed on the digest, so calling this repeatedly for the
|
|
42
|
+
* same inputs is harmless.
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildImageDoc(input: {
|
|
45
|
+
testCases: Array<Partial<TestCase> & {
|
|
46
|
+
id?: string;
|
|
47
|
+
name: string;
|
|
48
|
+
}>;
|
|
49
|
+
evalConditions?: ImageEvalConditions;
|
|
50
|
+
tags?: string[];
|
|
51
|
+
}): BenchmarkImage;
|
|
52
|
+
//# sourceMappingURL=benchmarkImage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmarkImage.d.ts","sourceRoot":"","sources":["../../benchmarkImage.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExD,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,0EAA0E;AAC1E,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEzD;AAmBD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAYvC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,cAAc,CAAC,EAAE,mBAAmB,CAAC;CACtC,GAAG,MAAM,CAaT;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpE,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,GAAG,cAAc,CAkBjB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright OpenSearch Contributors
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Benchmark images — content-addressed identity for evaluation conditions.
|
|
7
|
+
*
|
|
8
|
+
* An image freezes the "controls" of an evaluation run: the test-case
|
|
9
|
+
* contents and the eval conditions (evaluator, judge model). The digest is a
|
|
10
|
+
* SHA-256 over a canonical serialization, so:
|
|
11
|
+
*
|
|
12
|
+
* - two runs with the same digest are comparable **by construction**
|
|
13
|
+
* (same tests, same judge conditions — only the agent varies);
|
|
14
|
+
* - re-running the same command yields the same digest → the image is
|
|
15
|
+
* found, not re-created (inherent dedup: identity is content, not name).
|
|
16
|
+
*
|
|
17
|
+
* Names are docker-style *tags*: mutable labels pointing at a digest, never
|
|
18
|
+
* identity. See the benchmark-dedup design discussion for rationale.
|
|
19
|
+
*/
|
|
20
|
+
import { createHash } from 'crypto';
|
|
21
|
+
/** Bump when the digest input shape changes (invalidates old digests). */
|
|
22
|
+
export const IMAGE_DIGEST_VERSION = 1;
|
|
23
|
+
/**
|
|
24
|
+
* Deterministic JSON: objects serialized with sorted keys, recursively.
|
|
25
|
+
* Arrays keep their order (order-sensitivity is decided by the caller).
|
|
26
|
+
*/
|
|
27
|
+
export function canonicalStringify(value) {
|
|
28
|
+
return JSON.stringify(sortValue(value));
|
|
29
|
+
}
|
|
30
|
+
function sortValue(value) {
|
|
31
|
+
if (Array.isArray(value))
|
|
32
|
+
return value.map(sortValue);
|
|
33
|
+
if (value && typeof value === 'object') {
|
|
34
|
+
const out = {};
|
|
35
|
+
for (const key of Object.keys(value).sort()) {
|
|
36
|
+
const v = value[key];
|
|
37
|
+
if (v !== undefined)
|
|
38
|
+
out[key] = sortValue(v);
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
function sha256Hex(input) {
|
|
45
|
+
return createHash('sha256').update(input, 'utf8').digest('hex');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Content fingerprint of a single test case. Uses CONTENT only — never the
|
|
49
|
+
* storage id — so re-imported test cases (fresh ids, same content) fingerprint
|
|
50
|
+
* identically. Fields chosen to match what actually changes agent behavior
|
|
51
|
+
* and judging: prompt, context, expected outcomes/trajectory, tools.
|
|
52
|
+
*/
|
|
53
|
+
export function fingerprintTestCase(tc) {
|
|
54
|
+
const content = {
|
|
55
|
+
name: tc.name,
|
|
56
|
+
initialPrompt: tc.initialPrompt ?? null,
|
|
57
|
+
context: tc.context ?? null,
|
|
58
|
+
tools: tc.tools ?? null,
|
|
59
|
+
expectedOutcomes: tc.expectedOutcomes ?? null,
|
|
60
|
+
expectedTrajectory: tc.expectedTrajectory ?? null,
|
|
61
|
+
// Code-imported cases: sourceHash already fingerprints the executable body.
|
|
62
|
+
sourceHash: tc.sourceHash ?? null,
|
|
63
|
+
};
|
|
64
|
+
return { name: tc.name, contentHash: sha256Hex(canonicalStringify(content)) };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Compute the image digest for a set of test cases + eval conditions.
|
|
68
|
+
* Order-insensitive over test cases (fingerprints are sorted), content- and
|
|
69
|
+
* condition-sensitive.
|
|
70
|
+
*/
|
|
71
|
+
export function computeImageDigest(input) {
|
|
72
|
+
const fingerprints = input.testCases
|
|
73
|
+
.map(fingerprintTestCase)
|
|
74
|
+
.sort((a, b) => a.contentHash.localeCompare(b.contentHash));
|
|
75
|
+
const payload = {
|
|
76
|
+
v: IMAGE_DIGEST_VERSION,
|
|
77
|
+
testCases: fingerprints.map((f) => f.contentHash),
|
|
78
|
+
evalConditions: {
|
|
79
|
+
evaluatorId: input.evalConditions?.evaluatorId ?? null,
|
|
80
|
+
judgeModelId: input.evalConditions?.judgeModelId ?? null,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
return sha256Hex(canonicalStringify(payload));
|
|
84
|
+
}
|
|
85
|
+
/** Storage id for an image doc (content-addressed — one doc per digest). */
|
|
86
|
+
export function imageIdForDigest(digest) {
|
|
87
|
+
return `img-${digest}`;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build a full image doc for storage. `create` on the storage side is
|
|
91
|
+
* find-or-create keyed on the digest, so calling this repeatedly for the
|
|
92
|
+
* same inputs is harmless.
|
|
93
|
+
*/
|
|
94
|
+
export function buildImageDoc(input) {
|
|
95
|
+
const digest = computeImageDigest(input);
|
|
96
|
+
const fingerprints = input.testCases
|
|
97
|
+
.map((tc) => ({ ...fingerprintTestCase(tc), id: tc.id }))
|
|
98
|
+
.sort((a, b) => a.contentHash.localeCompare(b.contentHash));
|
|
99
|
+
return {
|
|
100
|
+
id: imageIdForDigest(digest),
|
|
101
|
+
docType: 'benchmark-image',
|
|
102
|
+
digest,
|
|
103
|
+
tags: input.tags ?? [],
|
|
104
|
+
testCaseFingerprints: fingerprints,
|
|
105
|
+
testCaseCount: fingerprints.length,
|
|
106
|
+
evalConditions: {
|
|
107
|
+
...(input.evalConditions?.evaluatorId ? { evaluatorId: input.evalConditions.evaluatorId } : {}),
|
|
108
|
+
...(input.evalConditions?.judgeModelId ? { judgeModelId: input.evalConditions.judgeModelId } : {}),
|
|
109
|
+
},
|
|
110
|
+
createdAt: new Date().toISOString(),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=benchmarkImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmarkImage.js","sourceRoot":"","sources":["../../benchmarkImage.ts"],"names":[],"mappings":"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"}
|