@memberjunction/testing-engine 6.1.0-edge.6 → 6.1.0-edge.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/drivers/AgentPromptComposer.d.ts +50 -0
- package/dist/drivers/AgentPromptComposer.d.ts.map +1 -0
- package/dist/drivers/AgentPromptComposer.js +60 -0
- package/dist/drivers/AgentPromptComposer.js.map +1 -0
- package/dist/drivers/PinnedVendorPromptRunner.d.ts +30 -0
- package/dist/drivers/PinnedVendorPromptRunner.d.ts.map +1 -0
- package/dist/drivers/PinnedVendorPromptRunner.js +30 -0
- package/dist/drivers/PinnedVendorPromptRunner.js.map +1 -0
- package/dist/drivers/PromptEvalDriver.d.ts +158 -0
- package/dist/drivers/PromptEvalDriver.d.ts.map +1 -0
- package/dist/drivers/PromptEvalDriver.js +365 -0
- package/dist/drivers/PromptEvalDriver.js.map +1 -0
- package/dist/drivers/index.d.ts +1 -0
- package/dist/drivers/index.d.ts.map +1 -1
- package/dist/drivers/index.js +1 -0
- package/dist/drivers/index.js.map +1 -1
- package/dist/engine/TestEngine.d.ts.map +1 -1
- package/dist/engine/TestEngine.js +5 -0
- package/dist/engine/TestEngine.js.map +1 -1
- package/dist/eval/corpus.d.ts +91 -0
- package/dist/eval/corpus.d.ts.map +1 -0
- package/dist/eval/corpus.js +141 -0
- package/dist/eval/corpus.js.map +1 -0
- package/dist/eval/decision.d.ts +156 -0
- package/dist/eval/decision.d.ts.map +1 -0
- package/dist/eval/decision.js +257 -0
- package/dist/eval/decision.js.map +1 -0
- package/dist/eval/expectation.d.ts +76 -0
- package/dist/eval/expectation.d.ts.map +1 -0
- package/dist/eval/expectation.js +160 -0
- package/dist/eval/expectation.js.map +1 -0
- package/dist/eval/history.d.ts +17 -0
- package/dist/eval/history.d.ts.map +1 -0
- package/dist/eval/history.js +19 -0
- package/dist/eval/history.js.map +1 -0
- package/dist/eval/index.d.ts +15 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +15 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/matchers.d.ts +88 -0
- package/dist/eval/matchers.d.ts.map +1 -0
- package/dist/eval/matchers.js +119 -0
- package/dist/eval/matchers.js.map +1 -0
- package/dist/eval/subAgentTrace.d.ts +52 -0
- package/dist/eval/subAgentTrace.d.ts.map +1 -0
- package/dist/eval/subAgentTrace.js +61 -0
- package/dist/eval/subAgentTrace.js.map +1 -0
- package/dist/eval/wellFormed.d.ts +41 -0
- package/dist/eval/wellFormed.d.ts.map +1 -0
- package/dist/eval/wellFormed.js +83 -0
- package/dist/eval/wellFormed.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/oracles/AgentDecisionOracle.d.ts +54 -0
- package/dist/oracles/AgentDecisionOracle.d.ts.map +1 -0
- package/dist/oracles/AgentDecisionOracle.js +107 -0
- package/dist/oracles/AgentDecisionOracle.js.map +1 -0
- package/dist/oracles/TraceSubAgentValidatorOracle.d.ts +44 -0
- package/dist/oracles/TraceSubAgentValidatorOracle.d.ts.map +1 -0
- package/dist/oracles/TraceSubAgentValidatorOracle.js +105 -0
- package/dist/oracles/TraceSubAgentValidatorOracle.js.map +1 -0
- package/dist/oracles/index.d.ts +2 -0
- package/dist/oracles/index.d.ts.map +1 -1
- package/dist/oracles/index.js +2 -0
- package/dist/oracles/index.js.map +1 -1
- package/package.json +10 -10
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* matchers.ts — per-parameter matchers for LLM-authored values.
|
|
3
|
+
*
|
|
4
|
+
* Exact string equality is the wrong test for most action parameters, and using it would make the
|
|
5
|
+
* harness measure phrasing instead of correctness. A SQL string, a search query, a summary
|
|
6
|
+
* instruction — all are correct in many forms. But enums, ids and booleans genuinely are exact.
|
|
7
|
+
* So matching is declarative and chosen per parameter by whoever writes the case (§3.2).
|
|
8
|
+
*
|
|
9
|
+
* Every variant is JSON-serializable, because a matcher arrives inside a `MJ: Tests`
|
|
10
|
+
* `Configuration` blob and has to survive that round trip. That constraint is why there is no
|
|
11
|
+
* `predicate` variant, however tempting: a function cannot be stored as metadata, and a corpus that
|
|
12
|
+
* needs code to express an expectation is a corpus that cannot be generated or diffed.
|
|
13
|
+
*
|
|
14
|
+
* FRAMEWORK-FREE (test plan §2.1) — imports nothing from the testing engine.
|
|
15
|
+
*/
|
|
16
|
+
/** One check against one parameter value. */
|
|
17
|
+
export type ParamMatcher =
|
|
18
|
+
/** Deep equality against a literal. For enums, ids, booleans, numbers. */
|
|
19
|
+
{
|
|
20
|
+
kind: 'exact';
|
|
21
|
+
value: unknown;
|
|
22
|
+
}
|
|
23
|
+
/** The value is a string with non-whitespace content. The weakest useful check. */
|
|
24
|
+
| {
|
|
25
|
+
kind: 'nonEmptyString';
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'nonEmpty';
|
|
28
|
+
}
|
|
29
|
+
/** Case-insensitive substring. For free text where a keyword must appear. */
|
|
30
|
+
| {
|
|
31
|
+
kind: 'containsIgnoreCase';
|
|
32
|
+
value: string;
|
|
33
|
+
}
|
|
34
|
+
/** Membership in a fixed set. For value-list parameters. */
|
|
35
|
+
| {
|
|
36
|
+
kind: 'oneOf';
|
|
37
|
+
values: unknown[];
|
|
38
|
+
}
|
|
39
|
+
/** A regular expression, supplied as a string with optional flags. */
|
|
40
|
+
| {
|
|
41
|
+
kind: 'regex';
|
|
42
|
+
pattern: string;
|
|
43
|
+
flags?: string;
|
|
44
|
+
}
|
|
45
|
+
/** Numeric bound, either end optional. */
|
|
46
|
+
| {
|
|
47
|
+
kind: 'numberRange';
|
|
48
|
+
min?: number;
|
|
49
|
+
max?: number;
|
|
50
|
+
}
|
|
51
|
+
/** The value's JSON type. For asserting shape without asserting content. */
|
|
52
|
+
| {
|
|
53
|
+
kind: 'typeOf';
|
|
54
|
+
type: 'string' | 'number' | 'boolean' | 'object' | 'array';
|
|
55
|
+
}
|
|
56
|
+
/** The parameter must be absent or null — for asserting a default was left alone. */
|
|
57
|
+
| {
|
|
58
|
+
kind: 'absent';
|
|
59
|
+
};
|
|
60
|
+
/** One matcher bound to the parameter it checks. */
|
|
61
|
+
export interface ParamExpectation {
|
|
62
|
+
param: string;
|
|
63
|
+
matcher: ParamMatcher;
|
|
64
|
+
/**
|
|
65
|
+
* When true, an ABSENT parameter passes; a present one is still checked.
|
|
66
|
+
*
|
|
67
|
+
* This is how a case asserts "if the model sets `Format`, it must be `json`" without
|
|
68
|
+
* requiring it to set `Format` at all — the common shape for optional action params that
|
|
69
|
+
* carry a server-side default.
|
|
70
|
+
*/
|
|
71
|
+
optional?: boolean;
|
|
72
|
+
}
|
|
73
|
+
/** The outcome of one matcher, kept per-parameter so param fidelity aggregates without a re-run. */
|
|
74
|
+
export interface ParamMatchResult {
|
|
75
|
+
param: string;
|
|
76
|
+
matcherKind: ParamMatcher['kind'];
|
|
77
|
+
passed: boolean;
|
|
78
|
+
/** Why it failed, phrased for a human reading a test report. */
|
|
79
|
+
detail?: string;
|
|
80
|
+
}
|
|
81
|
+
/** Applies one matcher to one value, returning why it failed rather than just that it did. */
|
|
82
|
+
export declare function applyMatcher(matcher: ParamMatcher, value: unknown): {
|
|
83
|
+
passed: boolean;
|
|
84
|
+
detail?: string;
|
|
85
|
+
};
|
|
86
|
+
/** Runs every expectation against one params object. */
|
|
87
|
+
export declare function matchParams(expectations: ParamExpectation[], params: Record<string, unknown>): ParamMatchResult[];
|
|
88
|
+
//# sourceMappingURL=matchers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../src/eval/matchers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,6CAA6C;AAC7C,MAAM,MAAM,YAAY;AACpB,0EAA0E;AACxE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AACnC,mFAAmF;GACjF;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE;AACtB,6EAA6E;GAC3E;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAC/C,4DAA4D;GAC1D;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE;AACtC,sEAAsE;GACpE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;AACpD,0CAA0C;GACxC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE;AACrD,4EAA4E;GAC1E;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;CAAE;AAChF,qFAAqF;GACnF;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEzB,oDAAoD;AACpD,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,oGAAoG;AACpG,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AA8BD,8FAA8F;AAC9F,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA+DxG;AAED,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,YAAY,EAAE,gBAAgB,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,EAAE,CASjH"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* matchers.ts — per-parameter matchers for LLM-authored values.
|
|
3
|
+
*
|
|
4
|
+
* Exact string equality is the wrong test for most action parameters, and using it would make the
|
|
5
|
+
* harness measure phrasing instead of correctness. A SQL string, a search query, a summary
|
|
6
|
+
* instruction — all are correct in many forms. But enums, ids and booleans genuinely are exact.
|
|
7
|
+
* So matching is declarative and chosen per parameter by whoever writes the case (§3.2).
|
|
8
|
+
*
|
|
9
|
+
* Every variant is JSON-serializable, because a matcher arrives inside a `MJ: Tests`
|
|
10
|
+
* `Configuration` blob and has to survive that round trip. That constraint is why there is no
|
|
11
|
+
* `predicate` variant, however tempting: a function cannot be stored as metadata, and a corpus that
|
|
12
|
+
* needs code to express an expectation is a corpus that cannot be generated or diffed.
|
|
13
|
+
*
|
|
14
|
+
* FRAMEWORK-FREE (test plan §2.1) — imports nothing from the testing engine.
|
|
15
|
+
*/
|
|
16
|
+
function describe(value) {
|
|
17
|
+
if (value === undefined) {
|
|
18
|
+
return 'absent';
|
|
19
|
+
}
|
|
20
|
+
const rendered = typeof value === 'string' ? value : JSON.stringify(value);
|
|
21
|
+
return rendered !== undefined && rendered.length > 80 ? `${rendered.slice(0, 80)}…` : String(rendered);
|
|
22
|
+
}
|
|
23
|
+
function deepEqual(a, b) {
|
|
24
|
+
// JSON round-trip equality is the right notion here: both sides originate as JSON (one from
|
|
25
|
+
// the model, one from a test record), so key order is the only difference it could miss.
|
|
26
|
+
if (a === b) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (typeof a !== typeof b || a === null || b === null) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (typeof a !== 'object') {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
const aKeys = Object.keys(a).sort();
|
|
36
|
+
const bKeys = Object.keys(b).sort();
|
|
37
|
+
if (Array.isArray(a) !== Array.isArray(b) || aKeys.length !== bKeys.length) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return aKeys.every((k, i) => k === bKeys[i] && deepEqual(a[k], b[k]));
|
|
41
|
+
}
|
|
42
|
+
/** Applies one matcher to one value, returning why it failed rather than just that it did. */
|
|
43
|
+
export function applyMatcher(matcher, value) {
|
|
44
|
+
switch (matcher.kind) {
|
|
45
|
+
case 'absent':
|
|
46
|
+
return value === undefined || value === null
|
|
47
|
+
? { passed: true }
|
|
48
|
+
: { passed: false, detail: `expected absent, got ${describe(value)}` };
|
|
49
|
+
case 'exact':
|
|
50
|
+
return deepEqual(value, matcher.value)
|
|
51
|
+
? { passed: true }
|
|
52
|
+
: { passed: false, detail: `expected ${describe(matcher.value)}, got ${describe(value)}` };
|
|
53
|
+
case 'nonEmpty': {
|
|
54
|
+
// Generic non-emptiness (payload paths hold arrays and objects, not only strings).
|
|
55
|
+
const ok = typeof value === 'string' ? value.trim().length > 0
|
|
56
|
+
: Array.isArray(value) ? value.length > 0
|
|
57
|
+
: value !== null && typeof value === 'object' ? Object.keys(value).length > 0
|
|
58
|
+
: value !== null && value !== undefined;
|
|
59
|
+
return ok ? { passed: true } : { passed: false, detail: `expected a non-empty value, got ${describe(value)}` };
|
|
60
|
+
}
|
|
61
|
+
case 'nonEmptyString':
|
|
62
|
+
return typeof value === 'string' && value.trim().length > 0
|
|
63
|
+
? { passed: true }
|
|
64
|
+
: { passed: false, detail: `expected a non-empty string, got ${describe(value)}` };
|
|
65
|
+
case 'containsIgnoreCase':
|
|
66
|
+
return typeof value === 'string' && value.toLowerCase().includes(matcher.value.toLowerCase())
|
|
67
|
+
? { passed: true }
|
|
68
|
+
: { passed: false, detail: `expected text containing "${matcher.value}", got ${describe(value)}` };
|
|
69
|
+
case 'oneOf':
|
|
70
|
+
return matcher.values.some((candidate) => deepEqual(candidate, value))
|
|
71
|
+
? { passed: true }
|
|
72
|
+
: { passed: false, detail: `expected one of ${describe(matcher.values)}, got ${describe(value)}` };
|
|
73
|
+
case 'regex': {
|
|
74
|
+
// A bad pattern in a test record is a authoring bug, and reporting it as a failed
|
|
75
|
+
// match would hide it. Surface it as its own message instead.
|
|
76
|
+
let expression;
|
|
77
|
+
try {
|
|
78
|
+
expression = new RegExp(matcher.pattern, matcher.flags);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
return { passed: false, detail: `invalid regex in expectation: ${error.message}` };
|
|
82
|
+
}
|
|
83
|
+
return typeof value === 'string' && expression.test(value)
|
|
84
|
+
? { passed: true }
|
|
85
|
+
: { passed: false, detail: `expected /${matcher.pattern}/${matcher.flags ?? ''}, got ${describe(value)}` };
|
|
86
|
+
}
|
|
87
|
+
case 'numberRange': {
|
|
88
|
+
if (typeof value !== 'number' || Number.isNaN(value)) {
|
|
89
|
+
return { passed: false, detail: `expected a number, got ${describe(value)}` };
|
|
90
|
+
}
|
|
91
|
+
const belowMin = matcher.min !== undefined && value < matcher.min;
|
|
92
|
+
const aboveMax = matcher.max !== undefined && value > matcher.max;
|
|
93
|
+
return belowMin || aboveMax
|
|
94
|
+
? { passed: false, detail: `expected ${matcher.min ?? '-∞'}..${matcher.max ?? '∞'}, got ${value}` }
|
|
95
|
+
: { passed: true };
|
|
96
|
+
}
|
|
97
|
+
case 'typeOf': {
|
|
98
|
+
const actual = Array.isArray(value) ? 'array' : typeof value;
|
|
99
|
+
return actual === matcher.type
|
|
100
|
+
? { passed: true }
|
|
101
|
+
: { passed: false, detail: `expected type ${matcher.type}, got ${actual}` };
|
|
102
|
+
}
|
|
103
|
+
default:
|
|
104
|
+
// Exhaustive today; a `default` keeps the function total if a variant is added.
|
|
105
|
+
return { passed: false, detail: 'unknown matcher kind' };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/** Runs every expectation against one params object. */
|
|
109
|
+
export function matchParams(expectations, params) {
|
|
110
|
+
return expectations.map((expectation) => {
|
|
111
|
+
const value = params[expectation.param];
|
|
112
|
+
if (expectation.optional && (value === undefined || value === null)) {
|
|
113
|
+
return { param: expectation.param, matcherKind: expectation.matcher.kind, passed: true };
|
|
114
|
+
}
|
|
115
|
+
const { passed, detail } = applyMatcher(expectation.matcher, value);
|
|
116
|
+
return { param: expectation.param, matcherKind: expectation.matcher.kind, passed, detail };
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=matchers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchers.js","sourceRoot":"","sources":["../../src/eval/matchers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA6CH,SAAS,QAAQ,CAAC,KAAc;IAC5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,QAAQ,CAAC;IACpB,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3E,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC3G,CAAC;AAED,SAAS,SAAS,CAAC,CAAU,EAAE,CAAU;IACrC,4FAA4F;IAC5F,yFAAyF;IACzF,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAA4B,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAA4B,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/D,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;QACzE,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,SAAS,CAAE,CAA6B,CAAC,CAAC,CAAC,EAAG,CAA6B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpI,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,YAAY,CAAC,OAAqB,EAAE,KAAc;IAC9D,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,QAAQ;YACT,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;gBACxC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;gBAClB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QAC/E,KAAK,OAAO;YACR,OAAO,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC;gBAClC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;gBAClB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACnG,KAAK,UAAU,CAAC,CAAC,CAAC;YACd,mFAAmF;YACnF,MAAM,EAAE,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;gBAC1D,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;oBACzC,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;wBAC7E,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC;YAC5C,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,mCAAmC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACnH,CAAC;QACD,KAAK,gBAAgB;YACjB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;gBACvD,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;gBAClB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,oCAAoC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QAC3F,KAAK,oBAAoB;YACrB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;gBACzF,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;gBAClB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,6BAA6B,OAAO,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QAC3G,KAAK,OAAO;YACR,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBAClE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;gBAClB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QAC3G,KAAK,OAAO,CAAC,CAAC,CAAC;YACX,kFAAkF;YAClF,8DAA8D;YAC9D,IAAI,UAAkB,CAAC;YACvB,IAAI,CAAC;gBACD,UAAU,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YAC5D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAkC,KAAe,CAAC,OAAO,EAAE,EAAE,CAAC;YAClG,CAAC;YACD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;gBACtD,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;gBAClB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,IAAI,EAAE,SAAS,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACnH,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACjB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACnD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,0BAA0B,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;YAClF,CAAC;YACD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC;YAClE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC;YAClE,OAAO,QAAQ,IAAI,QAAQ;gBACvB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,OAAO,CAAC,GAAG,IAAI,IAAI,KAAK,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,KAAK,EAAE,EAAE;gBACnG,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACZ,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC;YAC7D,OAAO,MAAM,KAAK,OAAO,CAAC,IAAI;gBAC1B,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE;gBAClB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,OAAO,CAAC,IAAI,SAAS,MAAM,EAAE,EAAE,CAAC;QACpF,CAAC;QACD;YACI,gFAAgF;YAChF,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;IACjE,CAAC;AACL,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,WAAW,CAAC,YAAgC,EAAE,MAA+B;IACzF,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE;QACpC,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,WAAW,CAAC,QAAQ,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,EAAE,CAAC;YAClE,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC7F,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACpE,OAAO,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC/F,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* subAgentTrace.ts — the judgement half of the `trace-validate-sub-agents` oracle.
|
|
3
|
+
*
|
|
4
|
+
* Split from the traversal so the decision logic is a pure function over "which sub-agents ran and
|
|
5
|
+
* how many iterations happened" (test plan §2.1). The traversal needs a database; this does not,
|
|
6
|
+
* and this is the part with the semantics worth pinning in a unit test.
|
|
7
|
+
*
|
|
8
|
+
* FRAMEWORK-FREE — imports nothing from the testing engine.
|
|
9
|
+
*/
|
|
10
|
+
/** What the traversal found. */
|
|
11
|
+
export interface SubAgentTraceFacts {
|
|
12
|
+
/** Every sub-agent dispatched anywhere in the run tree, in dispatch order, duplicates kept. */
|
|
13
|
+
dispatchedAgents: string[];
|
|
14
|
+
/** Loop iterations on the top-level run. See {@link SubAgentTraceConfig.minIterations}. */
|
|
15
|
+
iterations: number;
|
|
16
|
+
}
|
|
17
|
+
/** The oracle's configuration, exactly as the shipped research-agent tests already supply it. */
|
|
18
|
+
export interface SubAgentTraceConfig {
|
|
19
|
+
/** Every one of these must have been dispatched. Compared case-insensitively. */
|
|
20
|
+
requiredAgents?: string[];
|
|
21
|
+
/** None of these may have been dispatched — the "didn't over-delegate" check. */
|
|
22
|
+
forbiddenAgents?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Minimum loop iterations.
|
|
25
|
+
*
|
|
26
|
+
* An "iteration" is one Prompt step on the top-level run: the Loop agent type runs exactly one
|
|
27
|
+
* prompt per pass, so prompt steps are the only honest proxy the run tree offers. Sub-agent
|
|
28
|
+
* prompt steps are excluded — they are the *child's* iterations, not the parent's.
|
|
29
|
+
*/
|
|
30
|
+
minIterations?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface SubAgentTraceResult {
|
|
33
|
+
passed: boolean;
|
|
34
|
+
score: number;
|
|
35
|
+
message: string;
|
|
36
|
+
details: {
|
|
37
|
+
dispatchedAgents: string[];
|
|
38
|
+
missingAgents: string[];
|
|
39
|
+
forbiddenDispatched: string[];
|
|
40
|
+
iterations: number;
|
|
41
|
+
minIterations?: number;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Judges a run's sub-agent dispatch against the expectation.
|
|
46
|
+
*
|
|
47
|
+
* Names are compared case-insensitively and after trimming, because an agent name in a test record
|
|
48
|
+
* is typed by a human while the one in the trace comes from the catalog — a casing difference is
|
|
49
|
+
* never the failure anyone means to report.
|
|
50
|
+
*/
|
|
51
|
+
export declare function evaluateSubAgentTrace(facts: SubAgentTraceFacts, config: SubAgentTraceConfig): SubAgentTraceResult;
|
|
52
|
+
//# sourceMappingURL=subAgentTrace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subAgentTrace.d.ts","sourceRoot":"","sources":["../../src/eval/subAgentTrace.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,gCAAgC;AAChC,MAAM,WAAW,kBAAkB;IAC/B,+FAA+F;IAC/F,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,2FAA2F;IAC3F,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,iGAAiG;AACjG,MAAM,WAAW,mBAAmB;IAChC,iFAAiF;IACjF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACL,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B,aAAa,EAAE,MAAM,EAAE,CAAC;QACxB,mBAAmB,EAAE,MAAM,EAAE,CAAC;QAC9B,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACL;AAID;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,mBAAmB,GAAG,mBAAmB,CA+CjH"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* subAgentTrace.ts — the judgement half of the `trace-validate-sub-agents` oracle.
|
|
3
|
+
*
|
|
4
|
+
* Split from the traversal so the decision logic is a pure function over "which sub-agents ran and
|
|
5
|
+
* how many iterations happened" (test plan §2.1). The traversal needs a database; this does not,
|
|
6
|
+
* and this is the part with the semantics worth pinning in a unit test.
|
|
7
|
+
*
|
|
8
|
+
* FRAMEWORK-FREE — imports nothing from the testing engine.
|
|
9
|
+
*/
|
|
10
|
+
const normalize = (name) => name.trim().toLowerCase();
|
|
11
|
+
/**
|
|
12
|
+
* Judges a run's sub-agent dispatch against the expectation.
|
|
13
|
+
*
|
|
14
|
+
* Names are compared case-insensitively and after trimming, because an agent name in a test record
|
|
15
|
+
* is typed by a human while the one in the trace comes from the catalog — a casing difference is
|
|
16
|
+
* never the failure anyone means to report.
|
|
17
|
+
*/
|
|
18
|
+
export function evaluateSubAgentTrace(facts, config) {
|
|
19
|
+
const dispatched = new Set(facts.dispatchedAgents.map(normalize));
|
|
20
|
+
const missingAgents = (config.requiredAgents ?? []).filter((name) => !dispatched.has(normalize(name)));
|
|
21
|
+
const forbiddenDispatched = (config.forbiddenAgents ?? []).filter((name) => dispatched.has(normalize(name)));
|
|
22
|
+
const iterationsShort = config.minIterations !== undefined && facts.iterations < config.minIterations;
|
|
23
|
+
const details = {
|
|
24
|
+
dispatchedAgents: facts.dispatchedAgents,
|
|
25
|
+
missingAgents,
|
|
26
|
+
forbiddenDispatched,
|
|
27
|
+
iterations: facts.iterations,
|
|
28
|
+
minIterations: config.minIterations
|
|
29
|
+
};
|
|
30
|
+
const problems = [];
|
|
31
|
+
if (missingAgents.length > 0) {
|
|
32
|
+
problems.push(`never dispatched required sub-agent(s): ${missingAgents.join(', ')}`);
|
|
33
|
+
}
|
|
34
|
+
if (forbiddenDispatched.length > 0) {
|
|
35
|
+
problems.push(`dispatched forbidden sub-agent(s): ${forbiddenDispatched.join(', ')}`);
|
|
36
|
+
}
|
|
37
|
+
if (iterationsShort) {
|
|
38
|
+
problems.push(`expected at least ${config.minIterations} iteration(s), saw ${facts.iterations}`);
|
|
39
|
+
}
|
|
40
|
+
if (problems.length > 0) {
|
|
41
|
+
// Partial credit, so a run that got two of three required sub-agents scores above one that
|
|
42
|
+
// got none. The three checks are weighted equally and only the ones configured count.
|
|
43
|
+
const checks = [];
|
|
44
|
+
if (config.requiredAgents?.length) {
|
|
45
|
+
checks.push(missingAgents.length === 0);
|
|
46
|
+
}
|
|
47
|
+
if (config.forbiddenAgents?.length) {
|
|
48
|
+
checks.push(forbiddenDispatched.length === 0);
|
|
49
|
+
}
|
|
50
|
+
if (config.minIterations !== undefined) {
|
|
51
|
+
checks.push(!iterationsShort);
|
|
52
|
+
}
|
|
53
|
+
const score = checks.length === 0 ? 0 : checks.filter(Boolean).length / checks.length;
|
|
54
|
+
return { passed: false, score, message: problems.join('; '), details };
|
|
55
|
+
}
|
|
56
|
+
const summary = facts.dispatchedAgents.length > 0
|
|
57
|
+
? `dispatched ${facts.dispatchedAgents.length} sub-agent step(s): ${[...new Set(facts.dispatchedAgents)].join(', ')}`
|
|
58
|
+
: 'no sub-agents dispatched (none required)';
|
|
59
|
+
return { passed: true, score: 1, message: `${summary}; ${facts.iterations} iteration(s)`, details };
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=subAgentTrace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subAgentTrace.js","sourceRoot":"","sources":["../../src/eval/subAgentTrace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ObservedDecision } from './decision.js';
|
|
2
|
+
/** What the harness knows about the turn beyond the decision itself. */
|
|
3
|
+
export interface WellFormedInput {
|
|
4
|
+
decision: ObservedDecision;
|
|
5
|
+
/** The provider's `finish_reason`, when the driver captured one. */
|
|
6
|
+
finishReason?: string | null;
|
|
7
|
+
/** Set when the prompt run itself failed (provider error, timeout, cancellation). */
|
|
8
|
+
executionError?: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface WellFormedConfig {
|
|
11
|
+
/**
|
|
12
|
+
* Whether an envelope was required on this turn.
|
|
13
|
+
*
|
|
14
|
+
* Native-mode cells set this false: a clean tool call with no text is a *complete* answer
|
|
15
|
+
* there, and text never accompanies a call on Google — so requiring an
|
|
16
|
+
* envelope would fail every correct native turn.
|
|
17
|
+
*/
|
|
18
|
+
requireEnvelope?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Finish reasons that indicate the model was cut off or refused rather than finishing.
|
|
21
|
+
*
|
|
22
|
+
* Defaults cover the values seen across the provider matrix plus the documented failure modes. Values are
|
|
23
|
+
* compared case-insensitively because providers disagree on casing — see MJ#4335.
|
|
24
|
+
*/
|
|
25
|
+
unacceptableFinishReasons?: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface WellFormedResult {
|
|
28
|
+
passed: boolean;
|
|
29
|
+
score: number;
|
|
30
|
+
message: string;
|
|
31
|
+
details: {
|
|
32
|
+
kind: ObservedDecision['kind'];
|
|
33
|
+
encoding: ObservedDecision['encoding'];
|
|
34
|
+
envelopeParsed: boolean | null;
|
|
35
|
+
stepType: string | null;
|
|
36
|
+
finishReason: string | null;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Judges whether a turn produced usable output. */
|
|
40
|
+
export declare function evaluateWellFormed(input: WellFormedInput, config?: WellFormedConfig): WellFormedResult;
|
|
41
|
+
//# sourceMappingURL=wellFormed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wellFormed.d.ts","sourceRoot":"","sources":["../../src/eval/wellFormed.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAanD,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC5B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,qFAAqF;IACrF,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC7B;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,MAAM,EAAE,CAAC;CACxC;AAWD,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACL,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC/B,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACvC,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;QAC/B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;KAC/B,CAAC;CACL;AAED,oDAAoD;AACpD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,GAAE,gBAAqB,GAAG,gBAAgB,CAqD1G"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wellFormed.ts — metrics 1 and 2: was the output usable at all?
|
|
3
|
+
*
|
|
4
|
+
* This is the oracle that measures the `MALFORMED_FUNCTION_CALL` class directly (test plan §3.2,
|
|
5
|
+
* §6.1) — the headline number the whole native-tool-calling effort exists to move. It answers a
|
|
6
|
+
* narrower question than {@link evaluateDecision}: not "was the decision right" but "did the model
|
|
7
|
+
* produce something the framework could read." A run can be well-formed and wrong; it cannot be
|
|
8
|
+
* malformed and right.
|
|
9
|
+
*
|
|
10
|
+
* Keeping the two separate matters for attribution. A comparison run weighs baseline against native, and
|
|
11
|
+
* "malformed rate fell" and "decision accuracy rose" are different claims with different causes.
|
|
12
|
+
*
|
|
13
|
+
* FRAMEWORK-FREE (test plan §2.1) — imports nothing from the testing engine.
|
|
14
|
+
*/
|
|
15
|
+
import { LOOP_NEXT_STEP_TYPES } from '@memberjunction/ai-agents';
|
|
16
|
+
/**
|
|
17
|
+
* The step types the runtime will actually dispatch, derived from the agent framework rather than
|
|
18
|
+
* restated here — a hand-copied list would drift the moment a step type is added.
|
|
19
|
+
*
|
|
20
|
+
* Casing is load-bearing: `LoopAgentType.DetermineNextStep` switches on the raw string, so a
|
|
21
|
+
* lower-cased `'chat'` passes the validator (which compares case-insensitively) and then falls
|
|
22
|
+
* through to `default:` — a forced Retry that costs a whole iteration. That is a malformed
|
|
23
|
+
* response by any measure the issue cares about, so it is checked here.
|
|
24
|
+
*/
|
|
25
|
+
const DISPATCHABLE_STEP_TYPES = new Set(LOOP_NEXT_STEP_TYPES);
|
|
26
|
+
const DEFAULT_UNACCEPTABLE_FINISH_REASONS = [
|
|
27
|
+
'malformed_function_call',
|
|
28
|
+
'content_filter',
|
|
29
|
+
'safety',
|
|
30
|
+
'recitation',
|
|
31
|
+
'length',
|
|
32
|
+
'max_tokens'
|
|
33
|
+
];
|
|
34
|
+
/** Judges whether a turn produced usable output. */
|
|
35
|
+
export function evaluateWellFormed(input, config = {}) {
|
|
36
|
+
const { decision } = input;
|
|
37
|
+
const details = {
|
|
38
|
+
kind: decision.kind,
|
|
39
|
+
encoding: decision.encoding,
|
|
40
|
+
envelopeParsed: decision.envelopeParsed,
|
|
41
|
+
stepType: decision.stepType ?? null,
|
|
42
|
+
finishReason: input.finishReason ?? null
|
|
43
|
+
};
|
|
44
|
+
const fail = (message) => ({ passed: false, score: 0, message, details });
|
|
45
|
+
// An execution error outranks everything: there is no output to judge.
|
|
46
|
+
if (input.executionError) {
|
|
47
|
+
return fail(`execution failed: ${input.executionError}`);
|
|
48
|
+
}
|
|
49
|
+
if (decision.kind === 'empty') {
|
|
50
|
+
return fail('no output received from model');
|
|
51
|
+
}
|
|
52
|
+
if (decision.kind === 'unparseable') {
|
|
53
|
+
return fail(decision.diagnostic ?? 'output could not be read as a decision');
|
|
54
|
+
}
|
|
55
|
+
const unacceptable = (config.unacceptableFinishReasons ?? DEFAULT_UNACCEPTABLE_FINISH_REASONS).map((r) => r.toLowerCase());
|
|
56
|
+
const finish = input.finishReason?.toLowerCase().trim();
|
|
57
|
+
if (finish && unacceptable.includes(finish)) {
|
|
58
|
+
return fail(`unacceptable finish reason: ${input.finishReason}`);
|
|
59
|
+
}
|
|
60
|
+
if (decision.stepType && !DISPATCHABLE_STEP_TYPES.has(decision.stepType)) {
|
|
61
|
+
const canonical = LOOP_NEXT_STEP_TYPES.find((t) => t.toLowerCase() === decision.stepType?.toLowerCase().trim());
|
|
62
|
+
return fail(canonical
|
|
63
|
+
? `nextStep.type '${decision.stepType}' is the wrong case — the dispatcher switches on '${canonical}' and would force a Retry`
|
|
64
|
+
: `nextStep.type '${decision.stepType}' is not a dispatchable step type`);
|
|
65
|
+
}
|
|
66
|
+
// Parsed JSON that is not a LoopAgentResponse at all: no dispatchable nextStep, not complete,
|
|
67
|
+
// no payload write, no responseForm. Production has nothing to act on and forces a Retry — the
|
|
68
|
+
// same cost as a bad step type above, so it belongs in the same bucket. Counting it as usable
|
|
69
|
+
// is what let Cerebras's `{"weather":"unavailable", ...}` score as a usable envelope response.
|
|
70
|
+
// Guarded on stepType being absent: a valid-but-contentless step ('Retry') IS dispatchable.
|
|
71
|
+
if (decision.kind === 'other' && !decision.stepType) {
|
|
72
|
+
return fail('parsed JSON is not a LoopAgentResponse — nothing for the loop to dispatch');
|
|
73
|
+
}
|
|
74
|
+
if (config.requireEnvelope === true && decision.envelopeParsed !== true) {
|
|
75
|
+
return fail(decision.encoding === 'native'
|
|
76
|
+
// Worth naming precisely: this is the exact mechanism the provider matrix reproduced, where a
|
|
77
|
+
// correct decision arrives through a channel the caller was not reading.
|
|
78
|
+
? 'answered with a native tool call while an envelope was required'
|
|
79
|
+
: 'envelope required but not parsed');
|
|
80
|
+
}
|
|
81
|
+
return { passed: true, score: 1, message: `usable ${decision.encoding} response (${decision.kind})`, details };
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=wellFormed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wellFormed.js","sourceRoot":"","sources":["../../src/eval/wellFormed.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
export * from './engine/TestEngine.js';
|
|
8
8
|
export * from './drivers/BaseTestDriver.js';
|
|
9
9
|
export * from './drivers/AgentEvalDriver.js';
|
|
10
|
+
export * from './drivers/PromptEvalDriver.js';
|
|
10
11
|
export * from './oracles/IOracle.js';
|
|
11
12
|
export * from './oracles/SchemaValidatorOracle.js';
|
|
12
13
|
export * from './oracles/TraceValidatorOracle.js';
|
|
14
|
+
export * from './oracles/TraceSubAgentValidatorOracle.js';
|
|
15
|
+
export * from './oracles/AgentDecisionOracle.js';
|
|
13
16
|
export * from './oracles/LLMJudgeOracle.js';
|
|
14
17
|
export * from './oracles/ExactMatchOracle.js';
|
|
15
18
|
export * from './oracles/SQLValidatorOracle.js';
|
|
@@ -19,4 +22,6 @@ export * from './utils/cost-calculator.js';
|
|
|
19
22
|
export * from './utils/result-formatter.js';
|
|
20
23
|
export * from './utils/execution-context.js';
|
|
21
24
|
export * from './utils/variable-resolver.js';
|
|
25
|
+
export * from './eval/index.js';
|
|
26
|
+
export * from './drivers/AgentPromptComposer.js';
|
|
22
27
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,qBAAqB,CAAC;AAGpC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,qBAAqB,CAAC;AAGpC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAG3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wCAAwC,CAAC;AACvD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAG7C,cAAc,SAAS,CAAC;AAGxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,QAAQ,CAAC;AACvB,cAAc,+BAA+B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,10 +10,13 @@ export * from './engine/TestEngine.js';
|
|
|
10
10
|
export * from './drivers/BaseTestDriver.js';
|
|
11
11
|
// Concrete drivers
|
|
12
12
|
export * from './drivers/AgentEvalDriver.js';
|
|
13
|
+
export * from './drivers/PromptEvalDriver.js';
|
|
13
14
|
// Oracle interface and implementations
|
|
14
15
|
export * from './oracles/IOracle.js';
|
|
15
16
|
export * from './oracles/SchemaValidatorOracle.js';
|
|
16
17
|
export * from './oracles/TraceValidatorOracle.js';
|
|
18
|
+
export * from './oracles/TraceSubAgentValidatorOracle.js';
|
|
19
|
+
export * from './oracles/AgentDecisionOracle.js';
|
|
17
20
|
export * from './oracles/LLMJudgeOracle.js';
|
|
18
21
|
export * from './oracles/ExactMatchOracle.js';
|
|
19
22
|
export * from './oracles/SQLValidatorOracle.js';
|
|
@@ -25,4 +28,6 @@ export * from './utils/cost-calculator.js';
|
|
|
25
28
|
export * from './utils/result-formatter.js';
|
|
26
29
|
export * from './utils/execution-context.js';
|
|
27
30
|
export * from './utils/variable-resolver.js';
|
|
31
|
+
export * from './eval/index.js';
|
|
32
|
+
export * from './drivers/AgentPromptComposer.js';
|
|
28
33
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc;AACd,cAAc,qBAAqB,CAAC;AAEpC,eAAe;AACf,cAAc,0BAA0B,CAAC;AAEzC,mBAAmB;AACnB,cAAc,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc;AACd,cAAc,qBAAqB,CAAC;AAEpC,eAAe;AACf,cAAc,0BAA0B,CAAC;AAEzC,mBAAmB;AACnB,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAE3C,uCAAuC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wCAAwC,CAAC;AACvD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAE7C,uBAAuB;AACvB,cAAc,SAAS,CAAC;AAExB,YAAY;AACZ,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,QAAQ,CAAC;AACvB,cAAc,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Agent-decision oracles — the centrepiece of the prompt-eval corpus (test plan §3.2).
|
|
3
|
+
* @module @memberjunction/testing-engine
|
|
4
|
+
*/
|
|
5
|
+
import { IOracle } from './IOracle.js';
|
|
6
|
+
import { OracleInput, OracleConfig, OracleResult } from '../types.js';
|
|
7
|
+
import { type RawTurn } from '../eval/decision.js';
|
|
8
|
+
/**
|
|
9
|
+
* The shape a driver hands oracles as `actualOutput` for a prompt-eval test.
|
|
10
|
+
*
|
|
11
|
+
* Deliberately minimal and encoding-neutral: the raw text and, when the driver requested tools, the
|
|
12
|
+
* normalized calls. Anything richer would couple the oracles to a driver, and the whole point of
|
|
13
|
+
* §2.1 is that the same evaluation runs under a different runner unchanged.
|
|
14
|
+
*/
|
|
15
|
+
export interface PromptEvalActualOutput {
|
|
16
|
+
turn: RawTurn;
|
|
17
|
+
finishReason?: string | null;
|
|
18
|
+
executionError?: string | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* `agent-decision-match` — did the agent decide the right thing?
|
|
22
|
+
*
|
|
23
|
+
* Reads the decision off whichever channel the model used (envelope or native tool calls) and
|
|
24
|
+
* compares it against an encoding-independent expectation. That normalization is what lets a
|
|
25
|
+
* baseline cell and a native cell be compared on an identical corpus case: the
|
|
26
|
+
* yardstick does not move between them, only the model's behavior does.
|
|
27
|
+
*
|
|
28
|
+
* The result's `details` carry the components separately — decision kind, action accuracy, param
|
|
29
|
+
* fidelity, per-matcher outcomes — so §6.1's metrics aggregate out of persisted `ResultDetails`
|
|
30
|
+
* without re-running anything.
|
|
31
|
+
*
|
|
32
|
+
* Configuration is the {@link DecisionExpectation} itself.
|
|
33
|
+
*/
|
|
34
|
+
export declare class AgentDecisionOracle implements IOracle {
|
|
35
|
+
readonly type = "agent-decision-match";
|
|
36
|
+
evaluate(input: OracleInput, config: OracleConfig): Promise<OracleResult>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* `response-well-formed` — was the output usable at all?
|
|
40
|
+
*
|
|
41
|
+
* This is the oracle that measures the malformed/discard class directly — the issue's headline
|
|
42
|
+
* number. It asks strictly less than {@link AgentDecisionOracle}: a turn can be well-formed and
|
|
43
|
+
* wrong, but never malformed and right. Keeping them apart is what lets a comparison say *which* of
|
|
44
|
+
* "malformed rate fell" and "decision accuracy rose" actually happened.
|
|
45
|
+
*
|
|
46
|
+
* Configuration is a {@link WellFormedConfig}. Note `requireEnvelope` defaults to **off**: measurement
|
|
47
|
+
* measured that a correct native tool call carries no text at all on Google, so requiring an
|
|
48
|
+
* envelope unconditionally would fail every correct native turn.
|
|
49
|
+
*/
|
|
50
|
+
export declare class ResponseWellFormedOracle implements IOracle {
|
|
51
|
+
readonly type = "response-well-formed";
|
|
52
|
+
evaluate(input: OracleInput, config: OracleConfig): Promise<OracleResult>;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=AgentDecisionOracle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentDecisionOracle.d.ts","sourceRoot":"","sources":["../../src/oracles/AgentDecisionOracle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACnE,OAAO,EAAqB,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAKnE;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AASD;;;;;;;;;;;;;GAaG;AACH,qBAAa,mBAAoB,YAAW,OAAO;IAC/C,QAAQ,CAAC,IAAI,0BAA0B;IAEjC,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CA+ClF;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,wBAAyB,YAAW,OAAO;IACpD,QAAQ,CAAC,IAAI,0BAA0B;IAEjC,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CAalF"}
|