@mastra/evals 1.4.0 → 1.5.0-alpha.1
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 +57 -0
- package/dist/checks.cjs +56 -0
- package/dist/checks.cjs.map +1 -0
- package/dist/checks.d.ts +3 -0
- package/dist/checks.d.ts.map +1 -0
- package/dist/checks.js +3 -0
- package/dist/checks.js.map +1 -0
- package/dist/chunk-NXVFY4CK.cjs +233 -0
- package/dist/chunk-NXVFY4CK.cjs.map +1 -0
- package/dist/chunk-QRAONHNV.js +216 -0
- package/dist/chunk-QRAONHNV.js.map +1 -0
- package/dist/docs/SKILL.md +3 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-evals-built-in-scorers.md +17 -1
- package/dist/docs/references/docs-evals-overview.md +2 -0
- package/dist/docs/references/docs-evals-quick-checks.md +136 -0
- package/dist/docs/references/reference-evals-checks.md +210 -0
- package/dist/scorers/code/checks/index.d.ts +214 -0
- package/dist/scorers/code/checks/index.d.ts.map +1 -0
- package/dist/scorers/code/index.d.ts +1 -0
- package/dist/scorers/code/index.d.ts.map +1 -1
- package/dist/scorers/prebuilt/index.cjs +56 -7
- package/dist/scorers/prebuilt/index.cjs.map +1 -1
- package/dist/scorers/prebuilt/index.js +8 -7
- package/dist/scorers/prebuilt/index.js.map +1 -1
- package/package.json +19 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,62 @@
|
|
|
1
1
|
# @mastra/evals
|
|
2
2
|
|
|
3
|
+
## 1.5.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- **Gates and verdict for `runEvals`** ([#18394](https://github.com/mastra-ai/mastra/pull/18394))
|
|
8
|
+
|
|
9
|
+
New optional `gates` field accepts scorers that must score 1.0 for the run to pass. Scorers can now use a `{ scorer, threshold }` form to set pass/fail thresholds. `threshold` accepts a number (minimum) or `{ min, max }` for range-based checks (e.g. hallucination where high = bad). The result includes `verdict`, `gateResults`, and `thresholdResults`. Fully backward compatible.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { runEvals } from '@mastra/core/evals';
|
|
13
|
+
import { checks } from '@mastra/evals/checks';
|
|
14
|
+
|
|
15
|
+
const result = await runEvals({
|
|
16
|
+
data: [{ input: 'What is the weather?' }],
|
|
17
|
+
target: weatherAgent,
|
|
18
|
+
gates: [checks.calledTool('get_weather')],
|
|
19
|
+
scorers: [
|
|
20
|
+
{ scorer: faithfulnessScorer, threshold: 0.7 },
|
|
21
|
+
{ scorer: hallucinationScorer, threshold: { max: 0.3 } },
|
|
22
|
+
],
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
result.verdict; // 'passed' | 'scored' | 'failed'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- Updated dependencies [[`86623c1`](https://github.com/mastra-ai/mastra/commit/86623c1adf7d22de32cc916dda17f4155184db36), [`7c9dd77`](https://github.com/mastra-ai/mastra/commit/7c9dd77bd18cb8dc72797e25f1a0fbdc71a11347), [`9990965`](https://github.com/mastra-ai/mastra/commit/999096571635a83b42ef40841fd7028cfa630779), [`c0ffa3c`](https://github.com/mastra-ai/mastra/commit/c0ffa3c897ccd326de880df734740a7f0681a18f), [`0504bf5`](https://github.com/mastra-ai/mastra/commit/0504bf5e8cffc571a4b343326178de371e6f859b), [`5afe423`](https://github.com/mastra-ai/mastra/commit/5afe423e4badf040f1b0d4525183a856fcb8146e), [`86623c1`](https://github.com/mastra-ai/mastra/commit/86623c1adf7d22de32cc916dda17f4155184db36), [`8c9f1c0`](https://github.com/mastra-ai/mastra/commit/8c9f1c0361d89066f9bcd14a2f69e761b01766c8)]:
|
|
29
|
+
- @mastra/core@1.47.0-alpha.2
|
|
30
|
+
|
|
31
|
+
## 1.5.0-alpha.0
|
|
32
|
+
|
|
33
|
+
### Minor Changes
|
|
34
|
+
|
|
35
|
+
- Added `checks`, a new namespace of micro-scorers for common eval assertions. ([#18392](https://github.com/mastra-ai/mastra/pull/18392))
|
|
36
|
+
|
|
37
|
+
**What changed**
|
|
38
|
+
- Added text checks: `includes`, `excludes`, `equals`, `matches`, and `similarity`.
|
|
39
|
+
- Added tool checks: `calledTool`, `didNotCall`, `toolOrder`, `maxToolCalls`, `usedNoTools`, and `noToolErrors`.
|
|
40
|
+
- You can now import checks from `@mastra/evals/checks`.
|
|
41
|
+
|
|
42
|
+
**Example**
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { checks } from '@mastra/evals/checks';
|
|
46
|
+
|
|
47
|
+
const scorers = [
|
|
48
|
+
checks.includes('sunny'),
|
|
49
|
+
checks.calledTool('get_weather'),
|
|
50
|
+
checks.toolOrder(['search', 'summarize']),
|
|
51
|
+
checks.noToolErrors(),
|
|
52
|
+
];
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Patch Changes
|
|
56
|
+
|
|
57
|
+
- Updated dependencies [[`7f9ae70`](https://github.com/mastra-ai/mastra/commit/7f9ae70826b047e5a66218f9e92f20e54a2d791f), [`1505c07`](https://github.com/mastra-ai/mastra/commit/1505c07603f6346bae12aa82f140e8b88ffea9ab), [`e940f09`](https://github.com/mastra-ai/mastra/commit/e940f099ef5d18b403e6f2b4937e086a4da857b1)]:
|
|
58
|
+
- @mastra/core@1.46.1-alpha.1
|
|
59
|
+
|
|
3
60
|
## 1.4.0
|
|
4
61
|
|
|
5
62
|
### Minor Changes
|
package/dist/checks.cjs
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkNXVFY4CK_cjs = require('./chunk-NXVFY4CK.cjs');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports, "calledTool", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () { return chunkNXVFY4CK_cjs.calledTool; }
|
|
10
|
+
});
|
|
11
|
+
Object.defineProperty(exports, "checks", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function () { return chunkNXVFY4CK_cjs.checks; }
|
|
14
|
+
});
|
|
15
|
+
Object.defineProperty(exports, "didNotCall", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return chunkNXVFY4CK_cjs.didNotCall; }
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports, "equals", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () { return chunkNXVFY4CK_cjs.equals; }
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports, "excludes", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
get: function () { return chunkNXVFY4CK_cjs.excludes; }
|
|
26
|
+
});
|
|
27
|
+
Object.defineProperty(exports, "includes", {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: function () { return chunkNXVFY4CK_cjs.includes; }
|
|
30
|
+
});
|
|
31
|
+
Object.defineProperty(exports, "matches", {
|
|
32
|
+
enumerable: true,
|
|
33
|
+
get: function () { return chunkNXVFY4CK_cjs.matches; }
|
|
34
|
+
});
|
|
35
|
+
Object.defineProperty(exports, "maxToolCalls", {
|
|
36
|
+
enumerable: true,
|
|
37
|
+
get: function () { return chunkNXVFY4CK_cjs.maxToolCalls; }
|
|
38
|
+
});
|
|
39
|
+
Object.defineProperty(exports, "noToolErrors", {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
get: function () { return chunkNXVFY4CK_cjs.noToolErrors; }
|
|
42
|
+
});
|
|
43
|
+
Object.defineProperty(exports, "similarity", {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
get: function () { return chunkNXVFY4CK_cjs.similarity; }
|
|
46
|
+
});
|
|
47
|
+
Object.defineProperty(exports, "toolOrder", {
|
|
48
|
+
enumerable: true,
|
|
49
|
+
get: function () { return chunkNXVFY4CK_cjs.toolOrder; }
|
|
50
|
+
});
|
|
51
|
+
Object.defineProperty(exports, "usedNoTools", {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
get: function () { return chunkNXVFY4CK_cjs.usedNoTools; }
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=checks.cjs.map
|
|
56
|
+
//# sourceMappingURL=checks.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"checks.cjs"}
|
package/dist/checks.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,cAAc,uBAAuB,CAAC"}
|
package/dist/checks.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"checks.js"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkUNQXHPOD_cjs = require('./chunk-UNQXHPOD.cjs');
|
|
4
|
+
var evals = require('@mastra/core/evals');
|
|
5
|
+
var stringSimilarity = require('string-similarity');
|
|
6
|
+
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var stringSimilarity__default = /*#__PURE__*/_interopDefault(stringSimilarity);
|
|
10
|
+
|
|
11
|
+
function includes(expected, options = {}) {
|
|
12
|
+
const { ignoreCase = true } = options;
|
|
13
|
+
return evals.createScorer({
|
|
14
|
+
id: "check-includes",
|
|
15
|
+
name: "Includes Check",
|
|
16
|
+
description: `Checks if output includes "${expected}"`,
|
|
17
|
+
type: "agent"
|
|
18
|
+
}).preprocess(async ({ run }) => {
|
|
19
|
+
let output = run.output.filter((m) => m.role === "assistant").map((m) => chunkUNQXHPOD_cjs.getTextContentFromMastraDBMessage(m)).join(" ");
|
|
20
|
+
let target = expected;
|
|
21
|
+
if (ignoreCase) {
|
|
22
|
+
output = output.toLowerCase();
|
|
23
|
+
target = target.toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
return { output, target, found: output.includes(target) };
|
|
26
|
+
}).generateScore(({ results }) => {
|
|
27
|
+
return results.preprocessStepResult?.found ? 1 : 0;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function excludes(unwanted, options = {}) {
|
|
31
|
+
const { ignoreCase = true } = options;
|
|
32
|
+
return evals.createScorer({
|
|
33
|
+
id: "check-excludes",
|
|
34
|
+
name: "Excludes Check",
|
|
35
|
+
description: `Checks that output does not include "${unwanted}"`,
|
|
36
|
+
type: "agent"
|
|
37
|
+
}).preprocess(async ({ run }) => {
|
|
38
|
+
let output = run.output.filter((m) => m.role === "assistant").map((m) => chunkUNQXHPOD_cjs.getTextContentFromMastraDBMessage(m)).join(" ");
|
|
39
|
+
let target = unwanted;
|
|
40
|
+
if (ignoreCase) {
|
|
41
|
+
output = output.toLowerCase();
|
|
42
|
+
target = target.toLowerCase();
|
|
43
|
+
}
|
|
44
|
+
return { output, target, excluded: !output.includes(target) };
|
|
45
|
+
}).generateScore(({ results }) => {
|
|
46
|
+
return results.preprocessStepResult?.excluded ? 1 : 0;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function equals(expected, options = {}) {
|
|
50
|
+
const { ignoreCase = true } = options;
|
|
51
|
+
return evals.createScorer({
|
|
52
|
+
id: "check-equals",
|
|
53
|
+
name: "Equals Check",
|
|
54
|
+
description: `Checks if output equals "${expected}"`,
|
|
55
|
+
type: "agent"
|
|
56
|
+
}).preprocess(async ({ run }) => {
|
|
57
|
+
let output = run.output.filter((m) => m.role === "assistant").map((m) => chunkUNQXHPOD_cjs.getTextContentFromMastraDBMessage(m)).join("");
|
|
58
|
+
let target = expected;
|
|
59
|
+
if (ignoreCase) {
|
|
60
|
+
output = output.toLowerCase();
|
|
61
|
+
target = target.toLowerCase();
|
|
62
|
+
}
|
|
63
|
+
return { output, target, isEqual: output === target };
|
|
64
|
+
}).generateScore(({ results }) => {
|
|
65
|
+
return results.preprocessStepResult?.isEqual ? 1 : 0;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function matches(pattern, options = {}) {
|
|
69
|
+
const { exact = false } = options;
|
|
70
|
+
return evals.createScorer({
|
|
71
|
+
id: "check-matches",
|
|
72
|
+
name: "Matches Check",
|
|
73
|
+
description: `Checks if output matches pattern ${pattern}`,
|
|
74
|
+
type: "agent"
|
|
75
|
+
}).preprocess(async ({ run }) => {
|
|
76
|
+
const output = run.output.filter((m) => m.role === "assistant").map((m) => chunkUNQXHPOD_cjs.getTextContentFromMastraDBMessage(m)).join("");
|
|
77
|
+
const regex = exact ? new RegExp(`^${pattern.source}$`, pattern.flags) : pattern;
|
|
78
|
+
const matched = regex.test(output);
|
|
79
|
+
return { output, pattern: pattern.toString(), matched };
|
|
80
|
+
}).generateScore(({ results }) => {
|
|
81
|
+
return results.preprocessStepResult?.matched ? 1 : 0;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function similarity(expected, options = {}) {
|
|
85
|
+
const { ignoreCase = true, threshold } = options;
|
|
86
|
+
return evals.createScorer({
|
|
87
|
+
id: "check-similarity",
|
|
88
|
+
name: "Similarity Check",
|
|
89
|
+
description: `Checks string similarity to "${expected}"`,
|
|
90
|
+
type: "agent"
|
|
91
|
+
}).preprocess(async ({ run }) => {
|
|
92
|
+
let output = run.output.filter((m) => m.role === "assistant").map((m) => chunkUNQXHPOD_cjs.getTextContentFromMastraDBMessage(m)).join(" ");
|
|
93
|
+
let target = expected;
|
|
94
|
+
if (ignoreCase) {
|
|
95
|
+
output = output.toLowerCase();
|
|
96
|
+
target = target.toLowerCase();
|
|
97
|
+
}
|
|
98
|
+
const score = stringSimilarity__default.default.compareTwoStrings(output, target);
|
|
99
|
+
return { output, target, score, threshold };
|
|
100
|
+
}).generateScore(({ results }) => {
|
|
101
|
+
const score = results.preprocessStepResult?.score ?? 0;
|
|
102
|
+
const t = results.preprocessStepResult?.threshold;
|
|
103
|
+
return t !== void 0 ? score >= t ? 1 : 0 : score;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function calledTool(toolName, options = {}) {
|
|
107
|
+
const { times = 1 } = options;
|
|
108
|
+
return evals.createScorer({
|
|
109
|
+
id: "check-called-tool",
|
|
110
|
+
name: "Called Tool Check",
|
|
111
|
+
description: `Checks that "${toolName}" was called${times > 1 ? ` at least ${times} times` : ""}`,
|
|
112
|
+
type: "agent"
|
|
113
|
+
}).preprocess(async ({ run }) => {
|
|
114
|
+
const { tools } = chunkUNQXHPOD_cjs.extractToolCalls(run.output);
|
|
115
|
+
const count = tools.filter((t) => t === toolName).length;
|
|
116
|
+
return { toolName, expectedTimes: times, actualCount: count, passed: count >= times };
|
|
117
|
+
}).generateScore(({ results }) => {
|
|
118
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
function didNotCall(toolName) {
|
|
122
|
+
return evals.createScorer({
|
|
123
|
+
id: "check-did-not-call",
|
|
124
|
+
name: "Did Not Call Check",
|
|
125
|
+
description: `Checks that "${toolName}" was NOT called`,
|
|
126
|
+
type: "agent"
|
|
127
|
+
}).preprocess(async ({ run }) => {
|
|
128
|
+
const { tools } = chunkUNQXHPOD_cjs.extractToolCalls(run.output);
|
|
129
|
+
const count = tools.filter((t) => t === toolName).length;
|
|
130
|
+
return { toolName, count, passed: count === 0 };
|
|
131
|
+
}).generateScore(({ results }) => {
|
|
132
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function toolOrder(expectedOrder) {
|
|
136
|
+
return evals.createScorer({
|
|
137
|
+
id: "check-tool-order",
|
|
138
|
+
name: "Tool Order Check",
|
|
139
|
+
description: `Checks tool call order: [${expectedOrder.join(" \u2192 ")}]`,
|
|
140
|
+
type: "agent"
|
|
141
|
+
}).preprocess(async ({ run }) => {
|
|
142
|
+
const { tools } = chunkUNQXHPOD_cjs.extractToolCalls(run.output);
|
|
143
|
+
let orderIndex = 0;
|
|
144
|
+
for (const tool of tools) {
|
|
145
|
+
if (orderIndex < expectedOrder.length && tool === expectedOrder[orderIndex]) {
|
|
146
|
+
orderIndex++;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const passed = orderIndex === expectedOrder.length;
|
|
150
|
+
return { actualTools: tools, expectedOrder, passed };
|
|
151
|
+
}).generateScore(({ results }) => {
|
|
152
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
function maxToolCalls(max) {
|
|
156
|
+
return evals.createScorer({
|
|
157
|
+
id: "check-max-tool-calls",
|
|
158
|
+
name: "Max Tool Calls Check",
|
|
159
|
+
description: `Checks that no more than ${max} tool calls were made`,
|
|
160
|
+
type: "agent"
|
|
161
|
+
}).preprocess(async ({ run }) => {
|
|
162
|
+
const { tools } = chunkUNQXHPOD_cjs.extractToolCalls(run.output);
|
|
163
|
+
return { count: tools.length, max, passed: tools.length <= max };
|
|
164
|
+
}).generateScore(({ results }) => {
|
|
165
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function usedNoTools() {
|
|
169
|
+
return evals.createScorer({
|
|
170
|
+
id: "check-used-no-tools",
|
|
171
|
+
name: "Used No Tools Check",
|
|
172
|
+
description: "Checks that no tools were called",
|
|
173
|
+
type: "agent"
|
|
174
|
+
}).preprocess(async ({ run }) => {
|
|
175
|
+
const { tools } = chunkUNQXHPOD_cjs.extractToolCalls(run.output);
|
|
176
|
+
return { count: tools.length, passed: tools.length === 0 };
|
|
177
|
+
}).generateScore(({ results }) => {
|
|
178
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function noToolErrors() {
|
|
182
|
+
return evals.createScorer({
|
|
183
|
+
id: "check-no-tool-errors",
|
|
184
|
+
name: "No Tool Errors Check",
|
|
185
|
+
description: "Checks that no tool calls resulted in errors",
|
|
186
|
+
type: "agent"
|
|
187
|
+
}).preprocess(async ({ run }) => {
|
|
188
|
+
const invocations = extractRawInvocations(run.output);
|
|
189
|
+
const errorCount = invocations.filter((inv) => inv.state === "call" || inv.result && inv.result.error).length;
|
|
190
|
+
return { errorCount, totalCalls: invocations.length, passed: errorCount === 0 };
|
|
191
|
+
}).generateScore(({ results }) => {
|
|
192
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function extractRawInvocations(output) {
|
|
196
|
+
const invocations = [];
|
|
197
|
+
for (const message of output) {
|
|
198
|
+
const legacy = message?.content?.toolInvocations;
|
|
199
|
+
const fromParts = legacy ? void 0 : message?.content?.parts?.filter((p) => p.type === "tool-invocation").map((p) => p.toolInvocation);
|
|
200
|
+
for (const inv of legacy ?? fromParts ?? []) {
|
|
201
|
+
if (inv) invocations.push(inv);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return invocations;
|
|
205
|
+
}
|
|
206
|
+
var checks = {
|
|
207
|
+
includes,
|
|
208
|
+
excludes,
|
|
209
|
+
equals,
|
|
210
|
+
matches,
|
|
211
|
+
similarity,
|
|
212
|
+
calledTool,
|
|
213
|
+
didNotCall,
|
|
214
|
+
toolOrder,
|
|
215
|
+
maxToolCalls,
|
|
216
|
+
usedNoTools,
|
|
217
|
+
noToolErrors
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
exports.calledTool = calledTool;
|
|
221
|
+
exports.checks = checks;
|
|
222
|
+
exports.didNotCall = didNotCall;
|
|
223
|
+
exports.equals = equals;
|
|
224
|
+
exports.excludes = excludes;
|
|
225
|
+
exports.includes = includes;
|
|
226
|
+
exports.matches = matches;
|
|
227
|
+
exports.maxToolCalls = maxToolCalls;
|
|
228
|
+
exports.noToolErrors = noToolErrors;
|
|
229
|
+
exports.similarity = similarity;
|
|
230
|
+
exports.toolOrder = toolOrder;
|
|
231
|
+
exports.usedNoTools = usedNoTools;
|
|
232
|
+
//# sourceMappingURL=chunk-NXVFY4CK.cjs.map
|
|
233
|
+
//# sourceMappingURL=chunk-NXVFY4CK.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/scorers/code/checks/index.ts"],"names":["createScorer","getTextContentFromMastraDBMessage","stringSimilarity","extractToolCalls"],"mappings":"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","file":"chunk-NXVFY4CK.cjs","sourcesContent":["import { createScorer } from '@mastra/core/evals';\nimport stringSimilarity from 'string-similarity';\nimport { extractToolCalls, getTextContentFromMastraDBMessage } from '../../utils';\n\n// ─── Output Text Checks ───────────────────────────────────────────────────────\n\nexport interface IncludesOptions {\n /** Case-insensitive match (default: true) */\n ignoreCase?: boolean;\n}\n\n/**\n * Scores 1 if the agent's output text contains the expected substring, 0 otherwise.\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.includes('sunny');\n * ```\n */\nexport function includes(expected: string, options: IncludesOptions = {}) {\n const { ignoreCase = true } = options;\n return createScorer({\n id: 'check-includes',\n name: 'Includes Check',\n description: `Checks if output includes \"${expected}\"`,\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n let output = run.output\n .filter(m => m.role === 'assistant')\n .map(m => getTextContentFromMastraDBMessage(m))\n .join(' ');\n let target = expected;\n if (ignoreCase) {\n output = output.toLowerCase();\n target = target.toLowerCase();\n }\n return { output, target, found: output.includes(target) };\n })\n .generateScore(({ results }) => {\n return results.preprocessStepResult?.found ? 1 : 0;\n });\n}\n\n/**\n * Scores 1 if the agent's output text does NOT contain the substring, 0 otherwise.\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.excludes('error');\n * ```\n */\nexport function excludes(unwanted: string, options: IncludesOptions = {}) {\n const { ignoreCase = true } = options;\n return createScorer({\n id: 'check-excludes',\n name: 'Excludes Check',\n description: `Checks that output does not include \"${unwanted}\"`,\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n let output = run.output\n .filter(m => m.role === 'assistant')\n .map(m => getTextContentFromMastraDBMessage(m))\n .join(' ');\n let target = unwanted;\n if (ignoreCase) {\n output = output.toLowerCase();\n target = target.toLowerCase();\n }\n return { output, target, excluded: !output.includes(target) };\n })\n .generateScore(({ results }) => {\n return results.preprocessStepResult?.excluded ? 1 : 0;\n });\n}\n\n/**\n * Scores 1 if the output text exactly equals the expected string (after optional normalization).\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.equals('Hello, world!');\n * ```\n */\nexport function equals(expected: string, options: IncludesOptions = {}) {\n const { ignoreCase = true } = options;\n return createScorer({\n id: 'check-equals',\n name: 'Equals Check',\n description: `Checks if output equals \"${expected}\"`,\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n let output = run.output\n .filter(m => m.role === 'assistant')\n .map(m => getTextContentFromMastraDBMessage(m))\n .join('');\n let target = expected;\n if (ignoreCase) {\n output = output.toLowerCase();\n target = target.toLowerCase();\n }\n return { output, target, isEqual: output === target };\n })\n .generateScore(({ results }) => {\n return results.preprocessStepResult?.isEqual ? 1 : 0;\n });\n}\n\nexport interface MatchesOptions {\n /** If true, the output must match the pattern exactly (anchored). Default: false (substring match). */\n exact?: boolean;\n}\n\n/**\n * Scores 1 if the output matches the given regular expression, 0 otherwise.\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.matches(/\\d{1,3}°[FC]/);\n * ```\n */\nexport function matches(pattern: RegExp, options: MatchesOptions = {}) {\n const { exact = false } = options;\n return createScorer({\n id: 'check-matches',\n name: 'Matches Check',\n description: `Checks if output matches pattern ${pattern}`,\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n const output = run.output\n .filter(m => m.role === 'assistant')\n .map(m => getTextContentFromMastraDBMessage(m))\n .join('');\n const regex = exact ? new RegExp(`^${pattern.source}$`, pattern.flags) : pattern;\n const matched = regex.test(output);\n return { output, pattern: pattern.toString(), matched };\n })\n .generateScore(({ results }) => {\n return results.preprocessStepResult?.matched ? 1 : 0;\n });\n}\n\nexport interface SimilarityOptions {\n /** Minimum similarity threshold (0-1) to score 1. Default: 0.7 */\n threshold?: number;\n /** Case-insensitive comparison (default: true) */\n ignoreCase?: boolean;\n}\n\n/**\n * Returns the string similarity score (0-1) between the output and an expected string.\n * Useful for fuzzy matching when exact equality is too strict.\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.similarity('Sunny, 72°F');\n * ```\n */\nexport function similarity(expected: string, options: SimilarityOptions = {}) {\n const { ignoreCase = true, threshold } = options;\n return createScorer({\n id: 'check-similarity',\n name: 'Similarity Check',\n description: `Checks string similarity to \"${expected}\"`,\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n let output = run.output\n .filter(m => m.role === 'assistant')\n .map(m => getTextContentFromMastraDBMessage(m))\n .join(' ');\n let target = expected;\n if (ignoreCase) {\n output = output.toLowerCase();\n target = target.toLowerCase();\n }\n const score = stringSimilarity.compareTwoStrings(output, target);\n return { output, target, score, threshold };\n })\n .generateScore(({ results }) => {\n const score = results.preprocessStepResult?.score ?? 0;\n const t = results.preprocessStepResult?.threshold;\n return t !== undefined ? (score >= t ? 1 : 0) : score;\n });\n}\n\n// ─── Tool Call Checks ─────────────────────────────────────────────────────────\n\nexport interface CalledToolOptions {\n /** Minimum number of times the tool must be called. Default: 1 */\n times?: number;\n}\n\n/**\n * Scores 1 if the agent called the specified tool (at least `times` times).\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.calledTool('get_weather');\n * const twice = checks.calledTool('search', { times: 2 });\n * ```\n */\nexport function calledTool(toolName: string, options: CalledToolOptions = {}) {\n const { times = 1 } = options;\n return createScorer({\n id: 'check-called-tool',\n name: 'Called Tool Check',\n description: `Checks that \"${toolName}\" was called${times > 1 ? ` at least ${times} times` : ''}`,\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n const { tools } = extractToolCalls(run.output);\n const count = tools.filter(t => t === toolName).length;\n return { toolName, expectedTimes: times, actualCount: count, passed: count >= times };\n })\n .generateScore(({ results }) => {\n return results.preprocessStepResult?.passed ? 1 : 0;\n });\n}\n\n/**\n * Scores 1 if the agent did NOT call the specified tool.\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.didNotCall('delete_user');\n * ```\n */\nexport function didNotCall(toolName: string) {\n return createScorer({\n id: 'check-did-not-call',\n name: 'Did Not Call Check',\n description: `Checks that \"${toolName}\" was NOT called`,\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n const { tools } = extractToolCalls(run.output);\n const count = tools.filter(t => t === toolName).length;\n return { toolName, count, passed: count === 0 };\n })\n .generateScore(({ results }) => {\n return results.preprocessStepResult?.passed ? 1 : 0;\n });\n}\n\n/**\n * Scores 1 if the tools were called in the specified order (relaxed: allows other calls in between).\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.toolOrder(['search', 'summarize', 'respond']);\n * ```\n */\nexport function toolOrder(expectedOrder: string[]) {\n return createScorer({\n id: 'check-tool-order',\n name: 'Tool Order Check',\n description: `Checks tool call order: [${expectedOrder.join(' → ')}]`,\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n const { tools } = extractToolCalls(run.output);\n // Check that expectedOrder appears as a subsequence of tools\n let orderIndex = 0;\n for (const tool of tools) {\n if (orderIndex < expectedOrder.length && tool === expectedOrder[orderIndex]) {\n orderIndex++;\n }\n }\n const passed = orderIndex === expectedOrder.length;\n return { actualTools: tools, expectedOrder, passed };\n })\n .generateScore(({ results }) => {\n return results.preprocessStepResult?.passed ? 1 : 0;\n });\n}\n\n/**\n * Scores 1 if the agent used no more than `max` tool calls.\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.maxToolCalls(5);\n * ```\n */\nexport function maxToolCalls(max: number) {\n return createScorer({\n id: 'check-max-tool-calls',\n name: 'Max Tool Calls Check',\n description: `Checks that no more than ${max} tool calls were made`,\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n const { tools } = extractToolCalls(run.output);\n return { count: tools.length, max, passed: tools.length <= max };\n })\n .generateScore(({ results }) => {\n return results.preprocessStepResult?.passed ? 1 : 0;\n });\n}\n\n/**\n * Scores 1 if the agent made no tool calls at all.\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.usedNoTools();\n * ```\n */\nexport function usedNoTools() {\n return createScorer({\n id: 'check-used-no-tools',\n name: 'Used No Tools Check',\n description: 'Checks that no tools were called',\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n const { tools } = extractToolCalls(run.output);\n return { count: tools.length, passed: tools.length === 0 };\n })\n .generateScore(({ results }) => {\n return results.preprocessStepResult?.passed ? 1 : 0;\n });\n}\n\n/**\n * Scores 1 if none of the tool invocations resulted in an error state.\n * Checks for tool invocations with state other than 'result' (i.e., missing results).\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n * const scorer = checks.noToolErrors();\n * ```\n */\nexport function noToolErrors() {\n return createScorer({\n id: 'check-no-tool-errors',\n name: 'No Tool Errors Check',\n description: 'Checks that no tool calls resulted in errors',\n type: 'agent',\n })\n .preprocess(async ({ run }) => {\n const invocations = extractRawInvocations(run.output);\n const errorCount = invocations.filter(inv => inv.state === 'call' || (inv.result && inv.result.error)).length;\n return { errorCount, totalCalls: invocations.length, passed: errorCount === 0 };\n })\n .generateScore(({ results }) => {\n return results.preprocessStepResult?.passed ? 1 : 0;\n });\n}\n\n// ─── Internal helpers ──────────────────────────────────────────────────────────\n\nfunction extractRawInvocations(output: Parameters<typeof extractToolCalls>[0]) {\n const invocations: any[] = [];\n for (const message of output) {\n const legacy = message?.content?.toolInvocations;\n const fromParts = legacy\n ? undefined\n : (message?.content as any)?.parts\n ?.filter((p: any) => p.type === 'tool-invocation')\n .map((p: any) => p.toolInvocation);\n for (const inv of legacy ?? fromParts ?? []) {\n if (inv) invocations.push(inv);\n }\n }\n return invocations;\n}\n\n// ─── Convenience namespace ────────────────────────────────────────────────────\n\n/**\n * Quick Checks — composable micro-scorers for common assertions.\n *\n * These are zero-LLM, zero-ceremony scorers that plug into the existing\n * `scorers: [...]` array anywhere scorers are used. Internally they are\n * standard `createScorer()` instances with the same observability, storage,\n * and pipeline integration as any other scorer.\n *\n * @example\n * ```ts\n * import { checks } from '@mastra/evals';\n *\n * await runEvals({\n * data: [...],\n * target: myAgent,\n * scorers: [\n * checks.includes('sunny'),\n * checks.calledTool('get_weather'),\n * checks.toolOrder(['search', 'summarize']),\n * checks.noToolErrors(),\n * ],\n * });\n * ```\n */\nexport const checks = {\n includes,\n excludes,\n equals,\n matches,\n similarity,\n calledTool,\n didNotCall,\n toolOrder,\n maxToolCalls,\n usedNoTools,\n noToolErrors,\n};\n"]}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { getTextContentFromMastraDBMessage, extractToolCalls } from './chunk-BE5F2OUQ.js';
|
|
2
|
+
import { createScorer } from '@mastra/core/evals';
|
|
3
|
+
import stringSimilarity from 'string-similarity';
|
|
4
|
+
|
|
5
|
+
function includes(expected, options = {}) {
|
|
6
|
+
const { ignoreCase = true } = options;
|
|
7
|
+
return createScorer({
|
|
8
|
+
id: "check-includes",
|
|
9
|
+
name: "Includes Check",
|
|
10
|
+
description: `Checks if output includes "${expected}"`,
|
|
11
|
+
type: "agent"
|
|
12
|
+
}).preprocess(async ({ run }) => {
|
|
13
|
+
let output = run.output.filter((m) => m.role === "assistant").map((m) => getTextContentFromMastraDBMessage(m)).join(" ");
|
|
14
|
+
let target = expected;
|
|
15
|
+
if (ignoreCase) {
|
|
16
|
+
output = output.toLowerCase();
|
|
17
|
+
target = target.toLowerCase();
|
|
18
|
+
}
|
|
19
|
+
return { output, target, found: output.includes(target) };
|
|
20
|
+
}).generateScore(({ results }) => {
|
|
21
|
+
return results.preprocessStepResult?.found ? 1 : 0;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function excludes(unwanted, options = {}) {
|
|
25
|
+
const { ignoreCase = true } = options;
|
|
26
|
+
return createScorer({
|
|
27
|
+
id: "check-excludes",
|
|
28
|
+
name: "Excludes Check",
|
|
29
|
+
description: `Checks that output does not include "${unwanted}"`,
|
|
30
|
+
type: "agent"
|
|
31
|
+
}).preprocess(async ({ run }) => {
|
|
32
|
+
let output = run.output.filter((m) => m.role === "assistant").map((m) => getTextContentFromMastraDBMessage(m)).join(" ");
|
|
33
|
+
let target = unwanted;
|
|
34
|
+
if (ignoreCase) {
|
|
35
|
+
output = output.toLowerCase();
|
|
36
|
+
target = target.toLowerCase();
|
|
37
|
+
}
|
|
38
|
+
return { output, target, excluded: !output.includes(target) };
|
|
39
|
+
}).generateScore(({ results }) => {
|
|
40
|
+
return results.preprocessStepResult?.excluded ? 1 : 0;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function equals(expected, options = {}) {
|
|
44
|
+
const { ignoreCase = true } = options;
|
|
45
|
+
return createScorer({
|
|
46
|
+
id: "check-equals",
|
|
47
|
+
name: "Equals Check",
|
|
48
|
+
description: `Checks if output equals "${expected}"`,
|
|
49
|
+
type: "agent"
|
|
50
|
+
}).preprocess(async ({ run }) => {
|
|
51
|
+
let output = run.output.filter((m) => m.role === "assistant").map((m) => getTextContentFromMastraDBMessage(m)).join("");
|
|
52
|
+
let target = expected;
|
|
53
|
+
if (ignoreCase) {
|
|
54
|
+
output = output.toLowerCase();
|
|
55
|
+
target = target.toLowerCase();
|
|
56
|
+
}
|
|
57
|
+
return { output, target, isEqual: output === target };
|
|
58
|
+
}).generateScore(({ results }) => {
|
|
59
|
+
return results.preprocessStepResult?.isEqual ? 1 : 0;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function matches(pattern, options = {}) {
|
|
63
|
+
const { exact = false } = options;
|
|
64
|
+
return createScorer({
|
|
65
|
+
id: "check-matches",
|
|
66
|
+
name: "Matches Check",
|
|
67
|
+
description: `Checks if output matches pattern ${pattern}`,
|
|
68
|
+
type: "agent"
|
|
69
|
+
}).preprocess(async ({ run }) => {
|
|
70
|
+
const output = run.output.filter((m) => m.role === "assistant").map((m) => getTextContentFromMastraDBMessage(m)).join("");
|
|
71
|
+
const regex = exact ? new RegExp(`^${pattern.source}$`, pattern.flags) : pattern;
|
|
72
|
+
const matched = regex.test(output);
|
|
73
|
+
return { output, pattern: pattern.toString(), matched };
|
|
74
|
+
}).generateScore(({ results }) => {
|
|
75
|
+
return results.preprocessStepResult?.matched ? 1 : 0;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function similarity(expected, options = {}) {
|
|
79
|
+
const { ignoreCase = true, threshold } = options;
|
|
80
|
+
return createScorer({
|
|
81
|
+
id: "check-similarity",
|
|
82
|
+
name: "Similarity Check",
|
|
83
|
+
description: `Checks string similarity to "${expected}"`,
|
|
84
|
+
type: "agent"
|
|
85
|
+
}).preprocess(async ({ run }) => {
|
|
86
|
+
let output = run.output.filter((m) => m.role === "assistant").map((m) => getTextContentFromMastraDBMessage(m)).join(" ");
|
|
87
|
+
let target = expected;
|
|
88
|
+
if (ignoreCase) {
|
|
89
|
+
output = output.toLowerCase();
|
|
90
|
+
target = target.toLowerCase();
|
|
91
|
+
}
|
|
92
|
+
const score = stringSimilarity.compareTwoStrings(output, target);
|
|
93
|
+
return { output, target, score, threshold };
|
|
94
|
+
}).generateScore(({ results }) => {
|
|
95
|
+
const score = results.preprocessStepResult?.score ?? 0;
|
|
96
|
+
const t = results.preprocessStepResult?.threshold;
|
|
97
|
+
return t !== void 0 ? score >= t ? 1 : 0 : score;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function calledTool(toolName, options = {}) {
|
|
101
|
+
const { times = 1 } = options;
|
|
102
|
+
return createScorer({
|
|
103
|
+
id: "check-called-tool",
|
|
104
|
+
name: "Called Tool Check",
|
|
105
|
+
description: `Checks that "${toolName}" was called${times > 1 ? ` at least ${times} times` : ""}`,
|
|
106
|
+
type: "agent"
|
|
107
|
+
}).preprocess(async ({ run }) => {
|
|
108
|
+
const { tools } = extractToolCalls(run.output);
|
|
109
|
+
const count = tools.filter((t) => t === toolName).length;
|
|
110
|
+
return { toolName, expectedTimes: times, actualCount: count, passed: count >= times };
|
|
111
|
+
}).generateScore(({ results }) => {
|
|
112
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function didNotCall(toolName) {
|
|
116
|
+
return createScorer({
|
|
117
|
+
id: "check-did-not-call",
|
|
118
|
+
name: "Did Not Call Check",
|
|
119
|
+
description: `Checks that "${toolName}" was NOT called`,
|
|
120
|
+
type: "agent"
|
|
121
|
+
}).preprocess(async ({ run }) => {
|
|
122
|
+
const { tools } = extractToolCalls(run.output);
|
|
123
|
+
const count = tools.filter((t) => t === toolName).length;
|
|
124
|
+
return { toolName, count, passed: count === 0 };
|
|
125
|
+
}).generateScore(({ results }) => {
|
|
126
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function toolOrder(expectedOrder) {
|
|
130
|
+
return createScorer({
|
|
131
|
+
id: "check-tool-order",
|
|
132
|
+
name: "Tool Order Check",
|
|
133
|
+
description: `Checks tool call order: [${expectedOrder.join(" \u2192 ")}]`,
|
|
134
|
+
type: "agent"
|
|
135
|
+
}).preprocess(async ({ run }) => {
|
|
136
|
+
const { tools } = extractToolCalls(run.output);
|
|
137
|
+
let orderIndex = 0;
|
|
138
|
+
for (const tool of tools) {
|
|
139
|
+
if (orderIndex < expectedOrder.length && tool === expectedOrder[orderIndex]) {
|
|
140
|
+
orderIndex++;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const passed = orderIndex === expectedOrder.length;
|
|
144
|
+
return { actualTools: tools, expectedOrder, passed };
|
|
145
|
+
}).generateScore(({ results }) => {
|
|
146
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
function maxToolCalls(max) {
|
|
150
|
+
return createScorer({
|
|
151
|
+
id: "check-max-tool-calls",
|
|
152
|
+
name: "Max Tool Calls Check",
|
|
153
|
+
description: `Checks that no more than ${max} tool calls were made`,
|
|
154
|
+
type: "agent"
|
|
155
|
+
}).preprocess(async ({ run }) => {
|
|
156
|
+
const { tools } = extractToolCalls(run.output);
|
|
157
|
+
return { count: tools.length, max, passed: tools.length <= max };
|
|
158
|
+
}).generateScore(({ results }) => {
|
|
159
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
function usedNoTools() {
|
|
163
|
+
return createScorer({
|
|
164
|
+
id: "check-used-no-tools",
|
|
165
|
+
name: "Used No Tools Check",
|
|
166
|
+
description: "Checks that no tools were called",
|
|
167
|
+
type: "agent"
|
|
168
|
+
}).preprocess(async ({ run }) => {
|
|
169
|
+
const { tools } = extractToolCalls(run.output);
|
|
170
|
+
return { count: tools.length, passed: tools.length === 0 };
|
|
171
|
+
}).generateScore(({ results }) => {
|
|
172
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
function noToolErrors() {
|
|
176
|
+
return createScorer({
|
|
177
|
+
id: "check-no-tool-errors",
|
|
178
|
+
name: "No Tool Errors Check",
|
|
179
|
+
description: "Checks that no tool calls resulted in errors",
|
|
180
|
+
type: "agent"
|
|
181
|
+
}).preprocess(async ({ run }) => {
|
|
182
|
+
const invocations = extractRawInvocations(run.output);
|
|
183
|
+
const errorCount = invocations.filter((inv) => inv.state === "call" || inv.result && inv.result.error).length;
|
|
184
|
+
return { errorCount, totalCalls: invocations.length, passed: errorCount === 0 };
|
|
185
|
+
}).generateScore(({ results }) => {
|
|
186
|
+
return results.preprocessStepResult?.passed ? 1 : 0;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
function extractRawInvocations(output) {
|
|
190
|
+
const invocations = [];
|
|
191
|
+
for (const message of output) {
|
|
192
|
+
const legacy = message?.content?.toolInvocations;
|
|
193
|
+
const fromParts = legacy ? void 0 : message?.content?.parts?.filter((p) => p.type === "tool-invocation").map((p) => p.toolInvocation);
|
|
194
|
+
for (const inv of legacy ?? fromParts ?? []) {
|
|
195
|
+
if (inv) invocations.push(inv);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return invocations;
|
|
199
|
+
}
|
|
200
|
+
var checks = {
|
|
201
|
+
includes,
|
|
202
|
+
excludes,
|
|
203
|
+
equals,
|
|
204
|
+
matches,
|
|
205
|
+
similarity,
|
|
206
|
+
calledTool,
|
|
207
|
+
didNotCall,
|
|
208
|
+
toolOrder,
|
|
209
|
+
maxToolCalls,
|
|
210
|
+
usedNoTools,
|
|
211
|
+
noToolErrors
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export { calledTool, checks, didNotCall, equals, excludes, includes, matches, maxToolCalls, noToolErrors, similarity, toolOrder, usedNoTools };
|
|
215
|
+
//# sourceMappingURL=chunk-QRAONHNV.js.map
|
|
216
|
+
//# sourceMappingURL=chunk-QRAONHNV.js.map
|