@dvina/agents 0.3.7 → 0.4.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.
@@ -0,0 +1,519 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/eval/index.ts
31
+ var eval_exports = {};
32
+ __export(eval_exports, {
33
+ ai: () => ai,
34
+ configureEvals: () => configureEvals,
35
+ contains: () => contains,
36
+ defineSuite: () => defineSuite,
37
+ human: () => human,
38
+ llmJudge: () => llmJudge,
39
+ noTools: () => noTools,
40
+ notContains: () => notContains,
41
+ respondsInLanguage: () => respondsInLanguage,
42
+ toolResult: () => toolResult,
43
+ toolsCalled: () => toolsCalled
44
+ });
45
+ module.exports = __toCommonJS(eval_exports);
46
+
47
+ // src/eval/config.ts
48
+ var _config = null;
49
+ function configureEvals(config) {
50
+ _config = config;
51
+ }
52
+ function getEvalConfig() {
53
+ if (!_config) {
54
+ throw new Error("Evals not configured. Call configureEvals() in your vitest setupFiles.");
55
+ }
56
+ return _config;
57
+ }
58
+
59
+ // src/eval/suite.ts
60
+ var ls = __toESM(require("langsmith/vitest"));
61
+
62
+ // src/eval/target.ts
63
+ var import_tools = require("@langchain/core/tools");
64
+ var import_messages = require("@langchain/core/messages");
65
+ var import_zod = require("zod");
66
+
67
+ // src/runtime/langchain/model-resolver.ts
68
+ var import_openai = require("@langchain/openai");
69
+ var LangchainModelResolver = class {
70
+ constructor(config) {
71
+ this.config = config;
72
+ }
73
+ resolve(modelString, tags) {
74
+ const parts = modelString.split(":");
75
+ if (parts.length === 2) {
76
+ const [provider, modelName] = parts;
77
+ return this.resolveByProvider(provider, "default", modelName, tags);
78
+ }
79
+ if (parts.length === 3) {
80
+ const [provider, configName, modelName] = parts;
81
+ return this.resolveByProvider(provider, configName, modelName, tags);
82
+ }
83
+ throw new Error(
84
+ 'Model string must follow format "provider:modelName" (uses "default" config) or "provider:configName:modelName"'
85
+ );
86
+ }
87
+ resolveByProvider(provider, configName, modelName, tags) {
88
+ switch (provider) {
89
+ case "openai":
90
+ return this.resolveOpenAI(configName, modelName, tags);
91
+ case "azure":
92
+ return this.resolveAzure(configName, modelName, tags);
93
+ default:
94
+ throw new Error(`Unsupported model provider: ${provider}`);
95
+ }
96
+ }
97
+ resolveOpenAI(configName, modelName, tags) {
98
+ const providerConfig = this.config.openai?.[configName];
99
+ if (!providerConfig) {
100
+ throw new Error(`Configuration "${configName}" for provider "openai" is missing`);
101
+ }
102
+ return new import_openai.ChatOpenAI({
103
+ apiKey: providerConfig.apiKey,
104
+ modelName,
105
+ tags
106
+ });
107
+ }
108
+ resolveAzure(configName, deploymentName, tags) {
109
+ const providerConfig = this.config.azure?.[configName];
110
+ if (!providerConfig) {
111
+ throw new Error(`Configuration "${configName}" for provider "azure" is missing`);
112
+ }
113
+ return new import_openai.AzureChatOpenAI({
114
+ model: providerConfig.model,
115
+ // shows (perhaps even uses) 3.5-turbo when not specifid
116
+ azureOpenAIApiKey: providerConfig.apiKey,
117
+ azureOpenAIApiInstanceName: this.extractInstanceName(providerConfig.endpoint),
118
+ azureOpenAIApiDeploymentName: deploymentName,
119
+ azureOpenAIApiVersion: providerConfig.apiVersion,
120
+ tags
121
+ });
122
+ }
123
+ extractInstanceName(endpoint) {
124
+ try {
125
+ const url = new URL(endpoint);
126
+ return url.hostname.split(".")[0];
127
+ } catch (e) {
128
+ return endpoint;
129
+ }
130
+ }
131
+ };
132
+
133
+ // src/eval/target.ts
134
+ var MAX_AGENT_LOOPS = 10;
135
+ function convertMessages(msgs) {
136
+ const result = [];
137
+ let tcIdx = 0;
138
+ let pendingToolCalls = [];
139
+ for (const msg of msgs) {
140
+ if (msg.role === "human") {
141
+ result.push(new import_messages.HumanMessage(msg.content));
142
+ } else if (msg.role === "ai") {
143
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
144
+ pendingToolCalls = msg.toolCalls.map((name) => ({
145
+ id: `hist_tc${++tcIdx}`,
146
+ name
147
+ }));
148
+ result.push(
149
+ new import_messages.AIMessage({
150
+ content: msg.content,
151
+ tool_calls: pendingToolCalls.map((tc) => ({
152
+ id: tc.id,
153
+ name: tc.name,
154
+ args: {}
155
+ }))
156
+ })
157
+ );
158
+ } else {
159
+ result.push(new import_messages.AIMessage(msg.content));
160
+ }
161
+ } else if (msg.role === "tool") {
162
+ const tc = pendingToolCalls.shift();
163
+ if (!tc) throw new Error("toolResult() without a preceding ai() with toolCalls");
164
+ result.push(
165
+ new import_messages.ToolMessage({
166
+ content: msg.content,
167
+ tool_call_id: tc.id,
168
+ name: tc.name
169
+ })
170
+ );
171
+ }
172
+ }
173
+ return result;
174
+ }
175
+ function createEvalTarget(modelConfig, modelString) {
176
+ return async (inputs) => {
177
+ const config = modelConfig && modelString ? { modelConfig, model: modelString } : getEvalConfig();
178
+ const resolver = new LangchainModelResolver(config.modelConfig);
179
+ const model = resolver.resolve(config.model);
180
+ const toolCallCounts = {};
181
+ const langchainTools = inputs.tools.map((mockTool) => {
182
+ toolCallCounts[mockTool.name] = 0;
183
+ return (0, import_tools.tool)(
184
+ async (toolInput) => {
185
+ toolCallCounts[mockTool.name]++;
186
+ if (typeof mockTool.response === "function") {
187
+ return mockTool.response(toolInput, toolCallCounts[mockTool.name]);
188
+ }
189
+ return mockTool.response;
190
+ },
191
+ {
192
+ name: mockTool.name,
193
+ description: mockTool.description,
194
+ schema: import_zod.z.object(
195
+ Object.fromEntries(
196
+ Object.entries(mockTool.schema).map(([key, val]) => {
197
+ if (typeof val === "string") return [key, import_zod.z.string().describe(val)];
198
+ if (typeof val === "number") return [key, import_zod.z.number().describe(String(val))];
199
+ return [key, import_zod.z.any()];
200
+ })
201
+ )
202
+ )
203
+ }
204
+ );
205
+ });
206
+ const boundModel = langchainTools.length > 0 ? model.bindTools(langchainTools) : model;
207
+ const messages = [];
208
+ if (inputs.systemPrompt) {
209
+ messages.push(new import_messages.SystemMessage(inputs.systemPrompt));
210
+ }
211
+ const inputMessages = inputs.messages ?? (inputs.userMessages ?? []).map((content) => ({ role: "human", content }));
212
+ messages.push(...convertMessages(inputMessages));
213
+ let loopCount = 0;
214
+ while (loopCount < MAX_AGENT_LOOPS) {
215
+ loopCount++;
216
+ const response = await boundModel.invoke(messages);
217
+ messages.push(response);
218
+ const aiMessage = response;
219
+ if (!aiMessage.tool_calls || aiMessage.tool_calls.length === 0) {
220
+ break;
221
+ }
222
+ for (const tc of aiMessage.tool_calls) {
223
+ const mockTool = langchainTools.find((t) => t.name === tc.name);
224
+ if (mockTool) {
225
+ const result = await mockTool.invoke(tc.args);
226
+ messages.push(
227
+ new import_messages.ToolMessage({
228
+ content: typeof result === "string" ? result : JSON.stringify(result),
229
+ tool_call_id: tc.id,
230
+ name: tc.name
231
+ })
232
+ );
233
+ } else {
234
+ messages.push(
235
+ new import_messages.ToolMessage({
236
+ content: `Tool "${tc.name}" not found`,
237
+ tool_call_id: tc.id,
238
+ name: tc.name
239
+ })
240
+ );
241
+ }
242
+ }
243
+ }
244
+ return { messages };
245
+ };
246
+ }
247
+
248
+ // src/eval/suite.ts
249
+ function human(content) {
250
+ return { role: "human", content };
251
+ }
252
+ function ai(content, toolCalls) {
253
+ return { role: "ai", content, ...toolCalls ? { toolCalls } : {} };
254
+ }
255
+ function toolResult(content) {
256
+ return { role: "tool", content };
257
+ }
258
+ function toMockTools(defs) {
259
+ return Object.entries(defs).map(([name, def]) => ({
260
+ name,
261
+ description: def.description,
262
+ schema: def.schema ?? {},
263
+ response: typeof def.response === "function" ? def.response : typeof def.response === "string" ? def.response : JSON.stringify(def.response)
264
+ }));
265
+ }
266
+ function toSerializableTools(tools) {
267
+ return tools.map((t) => ({
268
+ ...t,
269
+ response: typeof t.response === "function" ? "<function>" : t.response
270
+ }));
271
+ }
272
+ function lastHumanContent(messages) {
273
+ for (let i = messages.length - 1; i >= 0; i--) {
274
+ if (messages[i].role === "human") return messages[i].content;
275
+ }
276
+ return messages[0]?.content ?? "";
277
+ }
278
+ function resolveTarget(config) {
279
+ if (typeof config.target === "function") return config.target;
280
+ const evalConfig = getEvalConfig();
281
+ const model = typeof config.target === "string" ? config.target : evalConfig.model;
282
+ return createEvalTarget(evalConfig.modelConfig, model);
283
+ }
284
+ function defineSuite(name, config) {
285
+ const target = resolveTarget(config);
286
+ const suiteTools = config.tools;
287
+ const globalPrompt = getEvalConfig().systemPrompt;
288
+ ls.describe(name, () => {
289
+ for (const tc of config.cases) {
290
+ const testName = tc.name ?? lastHumanContent(tc.messages);
291
+ const tools = toMockTools(tc.tools ?? suiteTools);
292
+ const ctx = { message: lastHumanContent(tc.messages) };
293
+ const resolved = tc.expect.map((exp) => exp(ctx));
294
+ const evaluators = resolved.map((r) => r.evaluator);
295
+ const referenceOutputs = Object.assign({}, ...resolved.map((r) => r.referenceOutputs));
296
+ const systemPrompt = tc.systemPrompt ?? config.systemPrompt ?? globalPrompt;
297
+ const targetInputs = {
298
+ messages: tc.messages,
299
+ tools,
300
+ ...systemPrompt ? { systemPrompt } : {}
301
+ };
302
+ ls.test(
303
+ testName,
304
+ {
305
+ inputs: {
306
+ messages: tc.messages,
307
+ tools: toSerializableTools(tools),
308
+ ...systemPrompt ? { systemPrompt } : {}
309
+ },
310
+ referenceOutputs
311
+ },
312
+ async ({ referenceOutputs: refOut }) => {
313
+ const output = await target(targetInputs);
314
+ ls.logOutputs(output);
315
+ for (const evaluator of evaluators) {
316
+ await evaluator({ outputs: output, referenceOutputs: refOut ?? {} });
317
+ }
318
+ }
319
+ );
320
+ }
321
+ });
322
+ }
323
+
324
+ // src/eval/expectations.ts
325
+ var ls2 = __toESM(require("langsmith/vitest"));
326
+ var import_agentevals = require("agentevals");
327
+
328
+ // src/eval/evaluators/language.ts
329
+ var import_messages2 = require("@langchain/core/messages");
330
+ function createLanguageEvaluator(modelConfig, model) {
331
+ const resolver = new LangchainModelResolver(modelConfig);
332
+ const judge = resolver.resolve(model);
333
+ return async ({
334
+ outputs,
335
+ referenceOutputs
336
+ }) => {
337
+ const expectedLanguage = referenceOutputs?.expectedLanguage;
338
+ if (!expectedLanguage) {
339
+ return { key: "language_match", score: true, comment: "No expected language specified, skipping" };
340
+ }
341
+ const messages = outputs.messages || [];
342
+ const lastAiMessage = [...messages].reverse().find((m) => m instanceof import_messages2.AIMessage);
343
+ if (!lastAiMessage) {
344
+ return { key: "language_match", score: false, comment: "No AI message found in trajectory" };
345
+ }
346
+ const responseText = typeof lastAiMessage.content === "string" ? lastAiMessage.content : JSON.stringify(lastAiMessage.content);
347
+ const detection = await judge.invoke([
348
+ {
349
+ role: "system",
350
+ content: 'You are a language detection tool. Respond with ONLY the ISO 639-1 language code (e.g., "en", "tr", "de", "fr") of the text provided. Nothing else.'
351
+ },
352
+ {
353
+ role: "user",
354
+ content: responseText
355
+ }
356
+ ]);
357
+ const detectedLanguage = (typeof detection.content === "string" ? detection.content : "").trim().toLowerCase();
358
+ const matches = detectedLanguage === expectedLanguage.toLowerCase();
359
+ return {
360
+ key: "language_match",
361
+ score: matches,
362
+ comment: matches ? `Response language matches expected: ${expectedLanguage}` : `Expected "${expectedLanguage}" but detected "${detectedLanguage}"`
363
+ };
364
+ };
365
+ }
366
+
367
+ // src/eval/evaluators/response-content.ts
368
+ var import_messages3 = require("@langchain/core/messages");
369
+ function createResponseContentEvaluator() {
370
+ return async ({
371
+ outputs,
372
+ referenceOutputs
373
+ }) => {
374
+ const mustContain = referenceOutputs?.responseContains || [];
375
+ const mustNotContain = referenceOutputs?.responseMustNotContain || [];
376
+ if (mustContain.length === 0 && mustNotContain.length === 0) {
377
+ return { key: "response_content", score: true, comment: "No content assertions specified, skipping" };
378
+ }
379
+ const messages = outputs.messages || [];
380
+ const lastAiMessage = [...messages].reverse().find((m) => m instanceof import_messages3.AIMessage);
381
+ if (!lastAiMessage) {
382
+ return { key: "response_content", score: false, comment: "No AI message found in trajectory" };
383
+ }
384
+ const responseText = (typeof lastAiMessage.content === "string" ? lastAiMessage.content : JSON.stringify(lastAiMessage.content)).toLowerCase();
385
+ const failures = [];
386
+ for (const expected of mustContain) {
387
+ if (!responseText.includes(expected.toLowerCase())) {
388
+ failures.push(`Missing expected text: "${expected}"`);
389
+ }
390
+ }
391
+ for (const forbidden of mustNotContain) {
392
+ if (responseText.includes(forbidden.toLowerCase())) {
393
+ failures.push(`Contains forbidden text: "${forbidden}"`);
394
+ }
395
+ }
396
+ const passed = failures.length === 0;
397
+ return {
398
+ key: "response_content",
399
+ score: passed,
400
+ comment: passed ? "All content assertions passed" : failures.join("; ")
401
+ };
402
+ };
403
+ }
404
+
405
+ // src/eval/evaluators/no-tool-calls.ts
406
+ var import_messages4 = require("@langchain/core/messages");
407
+ function createNoToolCallsEvaluator() {
408
+ return async ({
409
+ outputs,
410
+ referenceOutputs
411
+ }) => {
412
+ if (referenceOutputs?.maxToolCalls !== 0 && referenceOutputs?.expectNoToolCalls !== true) {
413
+ return { key: "no_tool_calls", score: true, comment: "No tool call restriction specified, skipping" };
414
+ }
415
+ const messages = outputs.messages || [];
416
+ const toolCalls = messages.filter((m) => m instanceof import_messages4.AIMessage).flatMap((m) => m.tool_calls || []);
417
+ const passed = toolCalls.length === 0;
418
+ return {
419
+ key: "no_tool_calls",
420
+ score: passed,
421
+ comment: passed ? "No tool calls made (as expected)" : `Agent made ${toolCalls.length} tool call(s): ${toolCalls.map((tc) => tc.name).join(", ")}`
422
+ };
423
+ };
424
+ }
425
+
426
+ // src/eval/expectations.ts
427
+ function withTrajectoryGuard(evaluator, key) {
428
+ return async ({ outputs, referenceOutputs }) => {
429
+ if (!referenceOutputs?.referenceTrajectory) {
430
+ return { key, score: true, comment: "No referenceTrajectory specified, skipping" };
431
+ }
432
+ return evaluator({ outputs, referenceOutputs: referenceOutputs.referenceTrajectory });
433
+ };
434
+ }
435
+ function buildTrajectory(message, toolNames) {
436
+ const trajectory = [];
437
+ let tcIdx = 0;
438
+ trajectory.push({ role: "user", content: message });
439
+ for (const name of toolNames) {
440
+ const id = `tc${++tcIdx}`;
441
+ trajectory.push({
442
+ role: "assistant",
443
+ content: "",
444
+ tool_calls: [{ function: { name, arguments: "{}" }, id, type: "function" }]
445
+ });
446
+ trajectory.push({ role: "tool", content: "...", tool_call_id: id });
447
+ }
448
+ trajectory.push({ role: "assistant", content: "..." });
449
+ return trajectory;
450
+ }
451
+ function toolsCalled(tools) {
452
+ return (ctx) => ({
453
+ evaluator: ls2.wrapEvaluator(
454
+ withTrajectoryGuard(
455
+ (0, import_agentevals.createTrajectoryMatchEvaluator)({ trajectoryMatchMode: "superset", toolArgsMatchMode: "ignore" }),
456
+ "trajectory_match"
457
+ )
458
+ ),
459
+ referenceOutputs: { referenceTrajectory: buildTrajectory(ctx.message, tools) }
460
+ });
461
+ }
462
+ function llmJudge() {
463
+ return () => {
464
+ const config = getEvalConfig();
465
+ const model = config.evaluatorModel ?? config.model;
466
+ return {
467
+ evaluator: ls2.wrapEvaluator(
468
+ withTrajectoryGuard(
469
+ (0, import_agentevals.createTrajectoryLLMAsJudge)({ prompt: import_agentevals.TRAJECTORY_ACCURACY_PROMPT, model }),
470
+ "trajectory_llm_judge"
471
+ )
472
+ ),
473
+ referenceOutputs: {}
474
+ };
475
+ };
476
+ }
477
+ function noTools() {
478
+ return () => ({
479
+ evaluator: ls2.wrapEvaluator(createNoToolCallsEvaluator()),
480
+ referenceOutputs: { expectNoToolCalls: true }
481
+ });
482
+ }
483
+ function respondsInLanguage(code) {
484
+ return () => {
485
+ const config = getEvalConfig();
486
+ const model = config.evaluatorModel ?? config.model;
487
+ return {
488
+ evaluator: ls2.wrapEvaluator(createLanguageEvaluator(config.modelConfig, model)),
489
+ referenceOutputs: { expectedLanguage: code }
490
+ };
491
+ };
492
+ }
493
+ function contains(strings) {
494
+ return () => ({
495
+ evaluator: ls2.wrapEvaluator(createResponseContentEvaluator()),
496
+ referenceOutputs: { responseContains: strings }
497
+ });
498
+ }
499
+ function notContains(strings) {
500
+ return () => ({
501
+ evaluator: ls2.wrapEvaluator(createResponseContentEvaluator()),
502
+ referenceOutputs: { responseMustNotContain: strings }
503
+ });
504
+ }
505
+ // Annotate the CommonJS export names for ESM import in node:
506
+ 0 && (module.exports = {
507
+ ai,
508
+ configureEvals,
509
+ contains,
510
+ defineSuite,
511
+ human,
512
+ llmJudge,
513
+ noTools,
514
+ notContains,
515
+ respondsInLanguage,
516
+ toolResult,
517
+ toolsCalled
518
+ });
519
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/eval/index.ts","../../src/eval/config.ts","../../src/eval/suite.ts","../../src/eval/target.ts","../../src/runtime/langchain/model-resolver.ts","../../src/eval/expectations.ts","../../src/eval/evaluators/language.ts","../../src/eval/evaluators/response-content.ts","../../src/eval/evaluators/no-tool-calls.ts"],"sourcesContent":["// ── Configuration ───────────────────────────────────────────────────\nexport { configureEvals } from './config';\nexport type { EvalConfig } from './config';\n\n// ── Suite API ────────────────────────────────────────────────────────\nexport { defineSuite, human, ai, toolResult } from './suite';\nexport type { SuiteConfig, TestCase, ToolDef } from './suite';\n\n// ── Expectations ─────────────────────────────────────────────────────\nexport { toolsCalled, llmJudge, noTools, respondsInLanguage, contains, notContains } from './expectations';\nexport type { Expectation } from './expectations';\n","import type { LangchainModelConfig } from '../runtime/langchain/model-resolver';\n\nexport interface EvalConfig {\n\tmodelConfig: LangchainModelConfig;\n\tmodel: string;\n\t/** Model for evaluators needing LLM calls (language detection, LLM-as-judge). Defaults to `model`. */\n\tevaluatorModel?: string;\n\t/** System prompt prepended to every eval invocation. Can be overridden per-suite or per-case. */\n\tsystemPrompt?: string;\n}\n\nlet _config: EvalConfig | null = null;\n\nexport function configureEvals(config: EvalConfig): void {\n\t_config = config;\n}\n\nexport function getEvalConfig(): EvalConfig {\n\tif (!_config) {\n\t\tthrow new Error('Evals not configured. Call configureEvals() in your vitest setupFiles.');\n\t}\n\treturn _config;\n}\n","import * as ls from 'langsmith/vitest';\nimport { BaseMessage } from '@langchain/core/messages';\nimport { createEvalTarget, type MockToolDef } from './target';\nimport { type Expectation } from './expectations';\nimport { getEvalConfig } from './config';\n\n// ── Message builders ─────────────────────────────────────────────────\n\nexport function human(content: string) {\n\treturn { role: 'human' as const, content };\n}\n\nexport function ai(content: string, toolCalls?: string[]) {\n\treturn { role: 'ai' as const, content, ...(toolCalls ? { toolCalls } : {}) };\n}\n\nexport function toolResult(content: string) {\n\treturn { role: 'tool' as const, content };\n}\n\n// ── Public types ─────────────────────────────────────────────────────\n\ntype Message = ReturnType<typeof human> | ReturnType<typeof ai> | ReturnType<typeof toolResult>;\n\nexport interface ToolDef {\n\tdescription: string;\n\tschema?: Record<string, string>;\n\t/** Auto-stringified if not a string or function. */\n\tresponse: unknown | ((input: Record<string, unknown>, callCount: number) => string);\n}\n\nexport interface TestCase {\n\t/** Test name. Defaults to the last human message content if omitted. */\n\tname?: string;\n\tmessages: Message[];\n\tsystemPrompt?: string;\n\t/** Override suite-level tools for this case. */\n\ttools?: Record<string, ToolDef>;\n\texpect: Expectation[];\n}\n\ntype TargetFn = (inputs: { systemPrompt?: string; messages: Message[]; tools: MockToolDef[] }) => Promise<{ messages: BaseMessage[] }>;\n\nexport interface SuiteConfig {\n\t/** Custom target function, or model string override. Auto-created from global config if omitted. */\n\ttarget?: TargetFn | string;\n\t/** System prompt for all cases in this suite. Overrides the global prompt; can be overridden per-case. */\n\tsystemPrompt?: string;\n\ttools: Record<string, ToolDef>;\n\tcases: TestCase[];\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nfunction toMockTools(defs: Record<string, ToolDef>): MockToolDef[] {\n\treturn Object.entries(defs).map(([name, def]) => ({\n\t\tname,\n\t\tdescription: def.description,\n\t\tschema: def.schema ?? {},\n\t\tresponse:\n\t\t\ttypeof def.response === 'function'\n\t\t\t\t? (def.response as MockToolDef['response'])\n\t\t\t\t: typeof def.response === 'string'\n\t\t\t\t\t? def.response\n\t\t\t\t\t: JSON.stringify(def.response),\n\t}));\n}\n\n/** Strip function responses so the object is JSON-serialisable for langsmith hashing. */\nfunction toSerializableTools(tools: MockToolDef[]): Record<string, unknown>[] {\n\treturn tools.map((t) => ({\n\t\t...t,\n\t\tresponse: typeof t.response === 'function' ? '<function>' : t.response,\n\t}));\n}\n\nfunction lastHumanContent(messages: Message[]): string {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tif (messages[i].role === 'human') return messages[i].content;\n\t}\n\treturn messages[0]?.content ?? '';\n}\n\n// ── Main entry point ─────────────────────────────────────────────────\n\n/**\n * Defines an eval suite. Internally registers `ls.describe` / `ls.test`\n * so vitest discovers the tests — eval files only need to call this function.\n */\nfunction resolveTarget(config: SuiteConfig): TargetFn {\n\tif (typeof config.target === 'function') return config.target;\n\tconst evalConfig = getEvalConfig();\n\tconst model = typeof config.target === 'string' ? config.target : evalConfig.model;\n\treturn createEvalTarget(evalConfig.modelConfig, model);\n}\n\nexport function defineSuite(name: string, config: SuiteConfig): void {\n\tconst target = resolveTarget(config);\n\tconst suiteTools = config.tools;\n\tconst globalPrompt = getEvalConfig().systemPrompt;\n\n\tls.describe(name, () => {\n\t\tfor (const tc of config.cases) {\n\t\t\tconst testName = tc.name ?? lastHumanContent(tc.messages);\n\t\t\tconst tools = toMockTools(tc.tools ?? suiteTools);\n\t\t\tconst ctx = { message: lastHumanContent(tc.messages) };\n\n\t\t\tconst resolved = tc.expect.map((exp) => exp(ctx));\n\t\t\tconst evaluators = resolved.map((r) => r.evaluator);\n\t\t\tconst referenceOutputs = Object.assign({}, ...resolved.map((r) => r.referenceOutputs));\n\n\t\t\t// Precedence: case > suite > global\n\t\t\tconst systemPrompt = tc.systemPrompt ?? config.systemPrompt ?? globalPrompt;\n\n\t\t\tconst targetInputs = {\n\t\t\t\tmessages: tc.messages,\n\t\t\t\ttools,\n\t\t\t\t...(systemPrompt ? { systemPrompt } : {}),\n\t\t\t};\n\n\t\t\tls.test(\n\t\t\t\ttestName,\n\t\t\t\t{\n\t\t\t\t\tinputs: {\n\t\t\t\t\t\tmessages: tc.messages,\n\t\t\t\t\t\ttools: toSerializableTools(tools),\n\t\t\t\t\t\t...(systemPrompt ? { systemPrompt } : {}),\n\t\t\t\t\t},\n\t\t\t\t\treferenceOutputs,\n\t\t\t\t},\n\t\t\t\tasync ({ referenceOutputs: refOut }) => {\n\t\t\t\t\tconst output = await target(targetInputs);\n\t\t\t\t\tls.logOutputs(output);\n\t\t\t\t\tfor (const evaluator of evaluators) {\n\t\t\t\t\t\tawait evaluator({ outputs: output, referenceOutputs: refOut ?? {} });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t});\n}\n","import { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport { tool } from '@langchain/core/tools';\nimport { AIMessage, BaseMessage, HumanMessage, SystemMessage, ToolMessage } from '@langchain/core/messages';\nimport { z } from 'zod';\nimport { LangchainModelResolver, type LangchainModelConfig } from '../runtime/langchain/model-resolver';\nimport { getEvalConfig } from './config';\n\nexport interface MockToolDef {\n\tname: string;\n\tdescription: string;\n\tschema: Record<string, unknown>;\n\t/**\n\t * Canned response the mock tool returns.\n\t * Can be a static string, or a function that receives input and returns a response.\n\t * If a function is provided, it receives the full invocation count as a second arg\n\t * to support scenarios like \"first call fails, second call succeeds\".\n\t */\n\tresponse: string | ((input: Record<string, unknown>, callCount: number) => string);\n}\n\nexport interface EvalTargetInput {\n\tsystemPrompt?: string;\n\tmessages: Array<{ role: string; content: string; toolCalls?: string[] }>;\n\t/** @deprecated Use `messages` with `human()` builders instead. */\n\tuserMessages?: string[];\n\ttools: MockToolDef[];\n}\n\nconst MAX_AGENT_LOOPS = 10;\n\n/**\n * Converts the simple message format into LangChain BaseMessage instances.\n * For `ai` messages with `toolCalls`, generates tool_call IDs and wires up\n * the following `tool` messages as ToolMessages with matching IDs.\n */\nfunction convertMessages(msgs: EvalTargetInput['messages']): BaseMessage[] {\n\tconst result: BaseMessage[] = [];\n\tlet tcIdx = 0;\n\tlet pendingToolCalls: Array<{ id: string; name: string }> = [];\n\n\tfor (const msg of msgs) {\n\t\tif (msg.role === 'human') {\n\t\t\tresult.push(new HumanMessage(msg.content));\n\t\t} else if (msg.role === 'ai') {\n\t\t\tif (msg.toolCalls && msg.toolCalls.length > 0) {\n\t\t\t\tpendingToolCalls = msg.toolCalls.map((name) => ({\n\t\t\t\t\tid: `hist_tc${++tcIdx}`,\n\t\t\t\t\tname,\n\t\t\t\t}));\n\t\t\t\tresult.push(\n\t\t\t\t\tnew AIMessage({\n\t\t\t\t\t\tcontent: msg.content,\n\t\t\t\t\t\ttool_calls: pendingToolCalls.map((tc) => ({\n\t\t\t\t\t\t\tid: tc.id,\n\t\t\t\t\t\t\tname: tc.name,\n\t\t\t\t\t\t\targs: {},\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tresult.push(new AIMessage(msg.content));\n\t\t\t}\n\t\t} else if (msg.role === 'tool') {\n\t\t\tconst tc = pendingToolCalls.shift();\n\t\t\tif (!tc) throw new Error('toolResult() without a preceding ai() with toolCalls');\n\t\t\tresult.push(\n\t\t\t\tnew ToolMessage({\n\t\t\t\t\tcontent: msg.content,\n\t\t\t\t\ttool_call_id: tc.id,\n\t\t\t\t\tname: tc.name,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Creates a LangSmith-compatible target function that runs an agentic loop\n * with mock tools and returns the full message trajectory.\n */\nexport function createEvalTarget(modelConfig?: LangchainModelConfig, modelString?: string) {\n\treturn async (inputs: EvalTargetInput): Promise<{ messages: BaseMessage[] }> => {\n\t\tconst config = modelConfig && modelString ? { modelConfig, model: modelString } : getEvalConfig();\n\t\tconst resolver = new LangchainModelResolver(config.modelConfig);\n\t\tconst model = resolver.resolve(config.model) as BaseChatModel;\n\n\t\t// Track invocation counts per tool for stateful mock responses\n\t\tconst toolCallCounts: Record<string, number> = {};\n\n\t\t// Create langchain tools from mock definitions\n\t\tconst langchainTools = inputs.tools.map((mockTool) => {\n\t\t\ttoolCallCounts[mockTool.name] = 0;\n\n\t\t\treturn tool(\n\t\t\t\tasync (toolInput: Record<string, unknown>) => {\n\t\t\t\t\ttoolCallCounts[mockTool.name]++;\n\t\t\t\t\tif (typeof mockTool.response === 'function') {\n\t\t\t\t\t\treturn mockTool.response(toolInput, toolCallCounts[mockTool.name]);\n\t\t\t\t\t}\n\t\t\t\t\treturn mockTool.response;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: mockTool.name,\n\t\t\t\t\tdescription: mockTool.description,\n\t\t\t\t\tschema: z.object(\n\t\t\t\t\t\tObject.fromEntries(\n\t\t\t\t\t\t\tObject.entries(mockTool.schema).map(([key, val]) => {\n\t\t\t\t\t\t\t\tif (typeof val === 'string') return [key, z.string().describe(val)];\n\t\t\t\t\t\t\t\tif (typeof val === 'number') return [key, z.number().describe(String(val))];\n\t\t\t\t\t\t\t\treturn [key, z.any()];\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\n\t\tconst boundModel = langchainTools.length > 0 ? model.bindTools!(langchainTools) : model;\n\n\t\tconst messages: BaseMessage[] = [];\n\n\t\tif (inputs.systemPrompt) {\n\t\t\tmessages.push(new SystemMessage(inputs.systemPrompt));\n\t\t}\n\n\t\t// Normalize: support legacy userMessages format from existing datasets\n\t\tconst inputMessages =\n\t\t\tinputs.messages ?? (inputs.userMessages ?? []).map((content: string) => ({ role: 'human', content }));\n\n\t\t// Convert and push all messages (history + final human)\n\t\tmessages.push(...convertMessages(inputMessages));\n\n\t\t// Agentic loop: keep calling model until it stops making tool calls\n\t\tlet loopCount = 0;\n\t\twhile (loopCount < MAX_AGENT_LOOPS) {\n\t\t\tloopCount++;\n\n\t\t\tconst response = await boundModel.invoke(messages);\n\t\t\tmessages.push(response as BaseMessage);\n\n\t\t\tconst aiMessage = response as AIMessage;\n\t\t\tif (!aiMessage.tool_calls || aiMessage.tool_calls.length === 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Execute tool calls and add results\n\t\t\tfor (const tc of aiMessage.tool_calls) {\n\t\t\t\tconst mockTool = langchainTools.find((t) => t.name === tc.name);\n\t\t\t\tif (mockTool) {\n\t\t\t\t\tconst result = await mockTool.invoke(tc.args);\n\t\t\t\t\tmessages.push(\n\t\t\t\t\t\tnew ToolMessage({\n\t\t\t\t\t\t\tcontent: typeof result === 'string' ? result : JSON.stringify(result),\n\t\t\t\t\t\t\ttool_call_id: tc.id!,\n\t\t\t\t\t\t\tname: tc.name,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tmessages.push(\n\t\t\t\t\t\tnew ToolMessage({\n\t\t\t\t\t\t\tcontent: `Tool \"${tc.name}\" not found`,\n\t\t\t\t\t\t\ttool_call_id: tc.id!,\n\t\t\t\t\t\t\tname: tc.name,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { messages };\n\t};\n}\n","import { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';\n\nexport type LangchainOpenAIConfig = {\n\tapiKey: string;\n};\n\nexport type LangchainAzureConfig = {\n\tmodel: string;\n\tapiKey: string;\n\tendpoint: string;\n\tapiVersion: string;\n};\n\nexport type LangchainModelConfig = {\n\topenai?: Record<string, LangchainOpenAIConfig>;\n\tazure?: Record<string, LangchainAzureConfig>;\n};\n\nexport class LangchainModelResolver {\n\tconstructor(private config: LangchainModelConfig) {}\n\n\tresolve(modelString: string, tags?: string[]): BaseLanguageModel {\n\t\tconst parts = modelString.split(':');\n\n\t\tif (parts.length === 2) {\n\t\t\tconst [provider, modelName] = parts;\n\t\t\treturn this.resolveByProvider(provider, 'default', modelName, tags);\n\t\t}\n\n\t\tif (parts.length === 3) {\n\t\t\tconst [provider, configName, modelName] = parts;\n\t\t\treturn this.resolveByProvider(provider, configName, modelName, tags);\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t'Model string must follow format \"provider:modelName\" (uses \"default\" config) or \"provider:configName:modelName\"',\n\t\t);\n\t}\n\n\tprivate resolveByProvider(\n\t\tprovider: string,\n\t\tconfigName: string,\n\t\tmodelName: string,\n\t\ttags?: string[],\n\t): BaseLanguageModel {\n\t\tswitch (provider) {\n\t\t\tcase 'openai':\n\t\t\t\treturn this.resolveOpenAI(configName, modelName, tags);\n\t\t\tcase 'azure':\n\t\t\t\treturn this.resolveAzure(configName, modelName, tags);\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported model provider: ${provider}`);\n\t\t}\n\t}\n\n\tprivate resolveOpenAI(configName: string, modelName: string, tags?: string[]): ChatOpenAI {\n\t\tconst providerConfig = this.config.openai?.[configName];\n\t\tif (!providerConfig) {\n\t\t\tthrow new Error(`Configuration \"${configName}\" for provider \"openai\" is missing`);\n\t\t}\n\n\t\treturn new ChatOpenAI({\n\t\t\tapiKey: providerConfig.apiKey,\n\t\t\tmodelName: modelName,\n\t\t\ttags: tags,\n\t\t});\n\t}\n\n\tprivate resolveAzure(configName: string, deploymentName: string, tags?: string[]): AzureChatOpenAI {\n\t\tconst providerConfig = this.config.azure?.[configName];\n\t\tif (!providerConfig) {\n\t\t\tthrow new Error(`Configuration \"${configName}\" for provider \"azure\" is missing`);\n\t\t}\n\n\t\treturn new AzureChatOpenAI({\n\t\t\tmodel: providerConfig.model, // shows (perhaps even uses) 3.5-turbo when not specifid\n\t\t\tazureOpenAIApiKey: providerConfig.apiKey,\n\t\t\tazureOpenAIApiInstanceName: this.extractInstanceName(providerConfig.endpoint),\n\t\t\tazureOpenAIApiDeploymentName: deploymentName,\n\t\t\tazureOpenAIApiVersion: providerConfig.apiVersion,\n\t\t\ttags: tags,\n\t\t});\n\t}\n\n\tprivate extractInstanceName(endpoint: string): string {\n\t\ttry {\n\t\t\tconst url = new URL(endpoint);\n\t\t\treturn url.hostname.split('.')[0];\n\t\t} catch (e) {\n\t\t\treturn endpoint;\n\t\t}\n\t}\n}\n","import * as ls from 'langsmith/vitest';\nimport {\n\tcreateTrajectoryMatchEvaluator,\n\tcreateTrajectoryLLMAsJudge,\n\tTRAJECTORY_ACCURACY_PROMPT,\n} from 'agentevals';\nimport { createLanguageEvaluator } from './evaluators/language';\nimport { createResponseContentEvaluator } from './evaluators/response-content';\nimport { createNoToolCallsEvaluator } from './evaluators/no-tool-calls';\nimport { getEvalConfig } from './config';\n\n// ── Types ────────────────────────────────────────────────────────────\n\ntype EvaluatorFn = (args: {\n\toutputs: Record<string, any>;\n\treferenceOutputs: Record<string, any>;\n}) => Promise<any>;\n\ninterface ResolvedExpectation {\n\tevaluator: EvaluatorFn;\n\treferenceOutputs: Record<string, unknown>;\n}\n\n/** A factory that receives test context and returns an evaluator + its referenceOutputs. */\nexport type Expectation = (ctx: { message: string }) => ResolvedExpectation;\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nfunction withTrajectoryGuard(evaluator: any, key: string): EvaluatorFn {\n\treturn async ({ outputs, referenceOutputs }) => {\n\t\tif (!referenceOutputs?.referenceTrajectory) {\n\t\t\treturn { key, score: true, comment: 'No referenceTrajectory specified, skipping' };\n\t\t}\n\t\treturn evaluator({ outputs, referenceOutputs: referenceOutputs.referenceTrajectory });\n\t};\n}\n\nfunction buildTrajectory(message: string, toolNames: string[]): Record<string, unknown>[] {\n\tconst trajectory: Record<string, unknown>[] = [];\n\tlet tcIdx = 0;\n\n\ttrajectory.push({ role: 'user', content: message });\n\n\tfor (const name of toolNames) {\n\t\tconst id = `tc${++tcIdx}`;\n\t\ttrajectory.push({\n\t\t\trole: 'assistant',\n\t\t\tcontent: '',\n\t\t\ttool_calls: [{ function: { name, arguments: '{}' }, id, type: 'function' }],\n\t\t});\n\t\ttrajectory.push({ role: 'tool', content: '...', tool_call_id: id });\n\t}\n\n\ttrajectory.push({ role: 'assistant', content: '...' });\n\n\treturn trajectory;\n}\n\n// ── Expectation functions ────────────────────────────────────────────\n\n/**\n * Expect the agent to call tools in order (superset trajectory match).\n * Empty `[]` means the agent should answer directly without calling any tools.\n */\nexport function toolsCalled(tools: string[]): Expectation {\n\treturn (ctx) => ({\n\t\tevaluator: ls.wrapEvaluator(\n\t\t\twithTrajectoryGuard(\n\t\t\t\tcreateTrajectoryMatchEvaluator({ trajectoryMatchMode: 'superset', toolArgsMatchMode: 'ignore' }) as any,\n\t\t\t\t'trajectory_match',\n\t\t\t),\n\t\t),\n\t\treferenceOutputs: { referenceTrajectory: buildTrajectory(ctx.message, tools) },\n\t});\n}\n\n/**\n * Run an LLM-as-judge evaluator on the trajectory.\n * Requires `toolsCalled` in the same expect array.\n * Uses the globally configured evaluator model.\n */\nexport function llmJudge(): Expectation {\n\treturn () => {\n\t\tconst config = getEvalConfig();\n\t\tconst model = config.evaluatorModel ?? config.model;\n\t\treturn {\n\t\t\tevaluator: ls.wrapEvaluator(\n\t\t\t\twithTrajectoryGuard(\n\t\t\t\t\tcreateTrajectoryLLMAsJudge({ prompt: TRAJECTORY_ACCURACY_PROMPT, model }) as any,\n\t\t\t\t\t'trajectory_llm_judge',\n\t\t\t\t),\n\t\t\t),\n\t\t\treferenceOutputs: {},\n\t\t};\n\t};\n}\n\n/** Assert the agent made zero tool calls. */\nexport function noTools(): Expectation {\n\treturn () => ({\n\t\tevaluator: ls.wrapEvaluator(createNoToolCallsEvaluator()),\n\t\treferenceOutputs: { expectNoToolCalls: true },\n\t});\n}\n\n/**\n * Assert the response is in the given language (ISO 639-1 code).\n * Uses the globally configured evaluator model for language detection.\n * @param code - ISO 639-1 language code (e.g. 'en', 'tr', 'de').\n */\nexport function respondsInLanguage(code: string): Expectation {\n\treturn () => {\n\t\tconst config = getEvalConfig();\n\t\tconst model = config.evaluatorModel ?? config.model;\n\t\treturn {\n\t\t\tevaluator: ls.wrapEvaluator(createLanguageEvaluator(config.modelConfig, model)),\n\t\t\treferenceOutputs: { expectedLanguage: code },\n\t\t};\n\t};\n}\n\n/** Assert the response contains all given strings. */\nexport function contains(strings: string[]): Expectation {\n\treturn () => ({\n\t\tevaluator: ls.wrapEvaluator(createResponseContentEvaluator()),\n\t\treferenceOutputs: { responseContains: strings },\n\t});\n}\n\n/** Assert the response does not contain any of the given strings. */\nexport function notContains(strings: string[]): Expectation {\n\treturn () => ({\n\t\tevaluator: ls.wrapEvaluator(createResponseContentEvaluator()),\n\t\treferenceOutputs: { responseMustNotContain: strings },\n\t});\n}\n","import { AIMessage, BaseMessage } from '@langchain/core/messages';\nimport { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport { LangchainModelResolver, type LangchainModelConfig } from '../../runtime/langchain/model-resolver';\n\n/**\n * Creates a custom evaluator that checks whether the agent's final response\n * is in the expected language. Uses a cheap LLM call for language detection.\n */\nexport function createLanguageEvaluator(modelConfig: LangchainModelConfig, model: string) {\n\tconst resolver = new LangchainModelResolver(modelConfig);\n\tconst judge = resolver.resolve(model) as BaseChatModel;\n\n\treturn async ({\n\t\toutputs,\n\t\treferenceOutputs,\n\t}: {\n\t\toutputs: Record<string, any>;\n\t\treferenceOutputs?: Record<string, any>;\n\t}) => {\n\t\tconst expectedLanguage = referenceOutputs?.expectedLanguage;\n\t\tif (!expectedLanguage) {\n\t\t\treturn { key: 'language_match', score: true, comment: 'No expected language specified, skipping' };\n\t\t}\n\n\t\t// Extract the last AI message text from the trajectory\n\t\tconst messages: BaseMessage[] = outputs.messages || [];\n\t\tconst lastAiMessage = [...messages].reverse().find((m) => m instanceof AIMessage);\n\n\t\tif (!lastAiMessage) {\n\t\t\treturn { key: 'language_match', score: false, comment: 'No AI message found in trajectory' };\n\t\t}\n\n\t\tconst responseText = typeof lastAiMessage.content === 'string' ? lastAiMessage.content : JSON.stringify(lastAiMessage.content);\n\n\t\t// Use LLM to detect the language\n\t\tconst detection = await judge.invoke([\n\t\t\t{\n\t\t\t\trole: 'system',\n\t\t\t\tcontent: 'You are a language detection tool. Respond with ONLY the ISO 639-1 language code (e.g., \"en\", \"tr\", \"de\", \"fr\") of the text provided. Nothing else.',\n\t\t\t},\n\t\t\t{\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: responseText,\n\t\t\t},\n\t\t]);\n\n\t\tconst detectedLanguage = (typeof detection.content === 'string' ? detection.content : '').trim().toLowerCase();\n\n\t\tconst matches = detectedLanguage === expectedLanguage.toLowerCase();\n\n\t\treturn {\n\t\t\tkey: 'language_match',\n\t\t\tscore: matches,\n\t\t\tcomment: matches\n\t\t\t\t? `Response language matches expected: ${expectedLanguage}`\n\t\t\t\t: `Expected \"${expectedLanguage}\" but detected \"${detectedLanguage}\"`,\n\t\t};\n\t};\n}\n","import { AIMessage, BaseMessage } from '@langchain/core/messages';\n\n/**\n * Creates a custom evaluator that checks whether the agent's final response\n * contains expected strings and doesn't contain forbidden strings.\n */\nexport function createResponseContentEvaluator() {\n\treturn async ({\n\t\toutputs,\n\t\treferenceOutputs,\n\t}: {\n\t\toutputs: Record<string, any>;\n\t\treferenceOutputs?: Record<string, any>;\n\t}) => {\n\t\tconst mustContain: string[] = referenceOutputs?.responseContains || [];\n\t\tconst mustNotContain: string[] = referenceOutputs?.responseMustNotContain || [];\n\n\t\tif (mustContain.length === 0 && mustNotContain.length === 0) {\n\t\t\treturn { key: 'response_content', score: true, comment: 'No content assertions specified, skipping' };\n\t\t}\n\n\t\t// Extract the last AI message text from the trajectory\n\t\tconst messages: BaseMessage[] = outputs.messages || [];\n\t\tconst lastAiMessage = [...messages].reverse().find((m) => m instanceof AIMessage);\n\n\t\tif (!lastAiMessage) {\n\t\t\treturn { key: 'response_content', score: false, comment: 'No AI message found in trajectory' };\n\t\t}\n\n\t\tconst responseText = (typeof lastAiMessage.content === 'string' ? lastAiMessage.content : JSON.stringify(lastAiMessage.content)).toLowerCase();\n\n\t\tconst failures: string[] = [];\n\n\t\tfor (const expected of mustContain) {\n\t\t\tif (!responseText.includes(expected.toLowerCase())) {\n\t\t\t\tfailures.push(`Missing expected text: \"${expected}\"`);\n\t\t\t}\n\t\t}\n\n\t\tfor (const forbidden of mustNotContain) {\n\t\t\tif (responseText.includes(forbidden.toLowerCase())) {\n\t\t\t\tfailures.push(`Contains forbidden text: \"${forbidden}\"`);\n\t\t\t}\n\t\t}\n\n\t\tconst passed = failures.length === 0;\n\n\t\treturn {\n\t\t\tkey: 'response_content',\n\t\t\tscore: passed,\n\t\t\tcomment: passed ? 'All content assertions passed' : failures.join('; '),\n\t\t};\n\t};\n}\n","import { AIMessage, BaseMessage } from '@langchain/core/messages';\n\n/**\n * Creates a custom evaluator that asserts the agent made zero tool calls.\n * Useful for scenarios like greetings where the agent should just respond with text.\n */\nexport function createNoToolCallsEvaluator() {\n\treturn async ({\n\t\toutputs,\n\t\treferenceOutputs,\n\t}: {\n\t\toutputs: Record<string, any>;\n\t\treferenceOutputs?: Record<string, any>;\n\t}) => {\n\t\t// Only run this evaluator if the reference explicitly expects no tool calls\n\t\tif (referenceOutputs?.maxToolCalls !== 0 && referenceOutputs?.expectNoToolCalls !== true) {\n\t\t\treturn { key: 'no_tool_calls', score: true, comment: 'No tool call restriction specified, skipping' };\n\t\t}\n\n\t\tconst messages: BaseMessage[] = outputs.messages || [];\n\n\t\tconst toolCalls = messages\n\t\t\t.filter((m) => m instanceof AIMessage)\n\t\t\t.flatMap((m) => (m as AIMessage).tool_calls || []);\n\n\t\tconst passed = toolCalls.length === 0;\n\n\t\treturn {\n\t\t\tkey: 'no_tool_calls',\n\t\t\tscore: passed,\n\t\t\tcomment: passed\n\t\t\t\t? 'No tool calls made (as expected)'\n\t\t\t\t: `Agent made ${toolCalls.length} tool call(s): ${toolCalls.map((tc) => tc.name).join(', ')}`,\n\t\t};\n\t};\n}\n"],"mappings":"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","names":["ls","import_messages","import_messages","import_messages"]}