@langwatch/scenario 0.2.9 → 0.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -15
- package/dist/{chunk-7H6OGEQ5.mjs → chunk-7HLDX5EL.mjs} +9 -14
- package/dist/{chunk-YPJZSK4J.mjs → chunk-OL4RFXV4.mjs} +23 -11
- package/dist/index.d.mts +559 -72
- package/dist/index.d.ts +559 -72
- package/dist/index.js +746 -212
- package/dist/index.mjs +711 -187
- package/dist/integrations/vitest/config.d.mts +37 -0
- package/dist/integrations/vitest/config.d.ts +37 -0
- package/dist/integrations/vitest/config.js +3 -276
- package/dist/integrations/vitest/config.mjs +3 -10
- package/dist/integrations/vitest/reporter.js +69 -17
- package/dist/integrations/vitest/reporter.mjs +182 -4
- package/dist/integrations/vitest/setup.js +24 -12
- package/dist/integrations/vitest/setup.mjs +2 -2
- package/package.json +21 -22
- package/dist/chunk-K7KLHTDI.mjs +0 -146
package/README.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
|
|
6
5
|
[](https://badge.fury.io/js/%40langwatch%2Fscenario)
|
|
7
6
|
|
|
8
7
|
A powerful TypeScript library for testing AI agents in realistic, scripted scenarios.
|
|
@@ -89,7 +88,8 @@ describe("Weather Agent", () => {
|
|
|
89
88
|
parameters: z.object({
|
|
90
89
|
city: z.string().describe("The city to get the weather for."),
|
|
91
90
|
}),
|
|
92
|
-
execute: async ({ city }) =>
|
|
91
|
+
execute: async ({ city }) =>
|
|
92
|
+
`The weather in ${city} is cloudy with a temperature of 24°C.`,
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
// 2. Create an adapter for your agent
|
|
@@ -119,7 +119,8 @@ describe("Weather Agent", () => {
|
|
|
119
119
|
// 3. Define and run your scenario
|
|
120
120
|
const result = await scenario.run({
|
|
121
121
|
name: "Checking the weather",
|
|
122
|
-
description:
|
|
122
|
+
description:
|
|
123
|
+
"The user asks for the weather in a specific city, and the agent should use the weather tool to find it.",
|
|
123
124
|
agents: [
|
|
124
125
|
weatherAgent,
|
|
125
126
|
scenario.userSimulatorAgent({ model: openai("gpt-4.1") }),
|
|
@@ -254,10 +255,7 @@ const result = await scenario.run({
|
|
|
254
255
|
name: "my first scenario",
|
|
255
256
|
description: "A simple test to see if the agent responds.",
|
|
256
257
|
setId: "my-test-suite", // Group this scenario into a set
|
|
257
|
-
agents: [
|
|
258
|
-
myAgent,
|
|
259
|
-
scenario.userSimulatorAgent(),
|
|
260
|
-
],
|
|
258
|
+
agents: [myAgent, scenario.userSimulatorAgent()],
|
|
261
259
|
});
|
|
262
260
|
```
|
|
263
261
|
|
|
@@ -266,28 +264,64 @@ This will group all scenarios with the same `setId` together in the LangWatch UI
|
|
|
266
264
|
- The `setupFiles` entry enables Scenario's event logging for each test.
|
|
267
265
|
- The custom `VitestReporter` provides detailed scenario test reports in your test output.
|
|
268
266
|
|
|
269
|
-
|
|
270
267
|
## Vitest Integration
|
|
271
268
|
|
|
272
|
-
|
|
269
|
+
Scenario provides a convenient helper function to enhance your Vitest configuration with all the necessary setup files.
|
|
270
|
+
|
|
271
|
+
### Using the withScenario Helper (Recommended)
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
// vitest.config.ts
|
|
275
|
+
import { defineConfig } from "vitest/config";
|
|
276
|
+
import { withScenario } from "@langwatch/scenario/integrations/vitest/config";
|
|
277
|
+
import VitestReporter from "@langwatch/scenario/integrations/vitest/reporter";
|
|
278
|
+
|
|
279
|
+
export default withScenario(
|
|
280
|
+
defineConfig({
|
|
281
|
+
test: {
|
|
282
|
+
testTimeout: 180000, // 3 minutes, or however long you want to wait for the scenario to run
|
|
283
|
+
// Your existing setup files will be preserved and run after Scenario's setup
|
|
284
|
+
setupFiles: ["./my-custom-setup.ts"],
|
|
285
|
+
// Your existing global setup files will be preserved and run after Scenario's global setup
|
|
286
|
+
globalSetup: ["./my-global-setup.ts"],
|
|
287
|
+
// Optional: Add the Scenario reporter for detailed test reports
|
|
288
|
+
reporters: ["default", new VitestReporter()],
|
|
289
|
+
},
|
|
290
|
+
})
|
|
291
|
+
);
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
The `withScenario` helper automatically:
|
|
295
|
+
|
|
296
|
+
- Adds Scenario's setup files for event logging
|
|
297
|
+
- Adds Scenario's global setup files
|
|
298
|
+
- Preserves any existing setup configuration you have
|
|
299
|
+
- Handles both string and array configurations for setup files
|
|
300
|
+
|
|
301
|
+
### Manual Configuration
|
|
302
|
+
|
|
303
|
+
If you prefer to configure Vitest manually, you can add the Scenario setup files directly:
|
|
273
304
|
|
|
274
305
|
```typescript
|
|
275
306
|
// vitest.config.ts
|
|
276
307
|
import { defineConfig } from "vitest/config";
|
|
277
|
-
import VitestReporter from
|
|
308
|
+
import VitestReporter from "@langwatch/scenario/integrations/vitest/reporter";
|
|
278
309
|
|
|
279
310
|
export default defineConfig({
|
|
280
311
|
test: {
|
|
281
312
|
testTimeout: 180000, // 3 minutes, or however long you want to wait for the scenario to run
|
|
282
|
-
setupFiles: [
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
new VitestReporter(),
|
|
286
|
-
],
|
|
313
|
+
setupFiles: ["@langwatch/scenario/integrations/vitest/setup"],
|
|
314
|
+
// Optional: Add the Scenario reporter for detailed test reports
|
|
315
|
+
reporters: ["default", new VitestReporter()],
|
|
287
316
|
},
|
|
288
317
|
});
|
|
289
318
|
```
|
|
290
319
|
|
|
320
|
+
This configuration:
|
|
321
|
+
|
|
322
|
+
- The `setupFiles` entry enables Scenario's event logging for each test
|
|
323
|
+
- The custom `VitestReporter` provides detailed scenario test reports in your test output (optional)
|
|
324
|
+
|
|
291
325
|
## Development
|
|
292
326
|
|
|
293
327
|
This project uses `pnpm` for package management.
|
|
@@ -314,6 +348,7 @@ MIT
|
|
|
314
348
|
When running scenario tests, you can set the `SCENARIO_BATCH_RUN_ID` environment variable to uniquely identify a batch of test runs. This is especially useful for grouping results in reporting tools and CI pipelines.
|
|
315
349
|
|
|
316
350
|
Example:
|
|
351
|
+
|
|
317
352
|
```bash
|
|
318
353
|
SCENARIO_BATCH_RUN_ID=my-ci-run-123 pnpm test
|
|
319
354
|
```
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Logger,
|
|
3
|
-
|
|
4
|
-
} from "./chunk-
|
|
3
|
+
getEnv
|
|
4
|
+
} from "./chunk-OL4RFXV4.mjs";
|
|
5
5
|
import {
|
|
6
6
|
__export
|
|
7
7
|
} from "./chunk-7P6ASYW6.mjs";
|
|
@@ -27,24 +27,19 @@ var AgentRole = /* @__PURE__ */ ((AgentRole2) => {
|
|
|
27
27
|
AgentRole2["JUDGE"] = "Judge";
|
|
28
28
|
return AgentRole2;
|
|
29
29
|
})(AgentRole || {});
|
|
30
|
-
var allAgentRoles = [
|
|
30
|
+
var allAgentRoles = [
|
|
31
|
+
"User" /* USER */,
|
|
32
|
+
"Agent" /* AGENT */,
|
|
33
|
+
"Judge" /* JUDGE */
|
|
34
|
+
];
|
|
31
35
|
var AgentAdapter = class {
|
|
32
36
|
role = "Agent" /* AGENT */;
|
|
33
|
-
constructor(input) {
|
|
34
|
-
void input;
|
|
35
|
-
}
|
|
36
37
|
};
|
|
37
38
|
var UserSimulatorAgentAdapter = class {
|
|
38
39
|
role = "User" /* USER */;
|
|
39
|
-
constructor(input) {
|
|
40
|
-
void input;
|
|
41
|
-
}
|
|
42
40
|
};
|
|
43
41
|
var JudgeAgentAdapter = class {
|
|
44
42
|
role = "Judge" /* JUDGE */;
|
|
45
|
-
constructor(input) {
|
|
46
|
-
void input;
|
|
47
|
-
}
|
|
48
43
|
};
|
|
49
44
|
|
|
50
45
|
// src/domain/scenarios/index.ts
|
|
@@ -157,7 +152,6 @@ function getBatchRunId() {
|
|
|
157
152
|
return batchRunId;
|
|
158
153
|
}
|
|
159
154
|
if (process2.env.SCENARIO_BATCH_RUN_ID) {
|
|
160
|
-
console.log("process.env.SCENARIO_BATCH_RUN_ID", process2.env.SCENARIO_BATCH_RUN_ID);
|
|
161
155
|
return batchRunId = process2.env.SCENARIO_BATCH_RUN_ID;
|
|
162
156
|
}
|
|
163
157
|
if (process2.env.VITEST_WORKER_ID || process2.env.JEST_WORKER_ID) {
|
|
@@ -211,10 +205,11 @@ var EventAlertMessageLogger = class _EventAlertMessageLogger {
|
|
|
211
205
|
this.displayWatchMessage(params);
|
|
212
206
|
}
|
|
213
207
|
isGreetingDisabled() {
|
|
214
|
-
return
|
|
208
|
+
return getEnv().SCENARIO_DISABLE_SIMULATION_REPORT_INFO === true;
|
|
215
209
|
}
|
|
216
210
|
displayGreeting() {
|
|
217
211
|
const separator = "\u2500".repeat(60);
|
|
212
|
+
const env = getEnv();
|
|
218
213
|
if (!env.LANGWATCH_API_KEY) {
|
|
219
214
|
console.log(`
|
|
220
215
|
${separator}`);
|
|
@@ -9,6 +9,7 @@ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
|
9
9
|
LogLevel2["DEBUG"] = "DEBUG";
|
|
10
10
|
return LogLevel2;
|
|
11
11
|
})(LogLevel || {});
|
|
12
|
+
var LOG_LEVELS = Object.values(LogLevel);
|
|
12
13
|
|
|
13
14
|
// src/config/env.ts
|
|
14
15
|
var envSchema = z.object({
|
|
@@ -21,7 +22,7 @@ var envSchema = z.object({
|
|
|
21
22
|
* LangWatch endpoint URL for event reporting.
|
|
22
23
|
* Defaults to the production LangWatch endpoint.
|
|
23
24
|
*/
|
|
24
|
-
LANGWATCH_ENDPOINT: z.string().url().default("https://app.langwatch.ai"),
|
|
25
|
+
LANGWATCH_ENDPOINT: z.string().url().optional().default("https://app.langwatch.ai"),
|
|
25
26
|
/**
|
|
26
27
|
* Disables simulation report info messages when set to any truthy value.
|
|
27
28
|
* Useful for CI/CD environments or when you want cleaner output.
|
|
@@ -33,17 +34,19 @@ var envSchema = z.object({
|
|
|
33
34
|
*/
|
|
34
35
|
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
|
|
35
36
|
/**
|
|
36
|
-
*
|
|
37
|
+
* Case-insensitive log level for the scenario package.
|
|
37
38
|
* Defaults to 'info' if not specified.
|
|
38
39
|
*/
|
|
39
|
-
LOG_LEVEL: z.nativeEnum(LogLevel).optional(),
|
|
40
|
+
LOG_LEVEL: z.string().toUpperCase().pipe(z.nativeEnum(LogLevel)).optional().default("INFO" /* INFO */),
|
|
40
41
|
/**
|
|
41
42
|
* Scenario batch run ID.
|
|
42
43
|
* If not provided, a random ID will be generated.
|
|
43
44
|
*/
|
|
44
45
|
SCENARIO_BATCH_RUN_ID: z.string().optional()
|
|
45
46
|
});
|
|
46
|
-
|
|
47
|
+
function getEnv() {
|
|
48
|
+
return envSchema.parse(process.env);
|
|
49
|
+
}
|
|
47
50
|
|
|
48
51
|
// src/utils/logger.ts
|
|
49
52
|
var Logger = class _Logger {
|
|
@@ -56,18 +59,27 @@ var Logger = class _Logger {
|
|
|
56
59
|
static create(context) {
|
|
57
60
|
return new _Logger(context);
|
|
58
61
|
}
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Returns the current log level from environment.
|
|
64
|
+
* Uses a getter for clarity and idiomatic usage.
|
|
65
|
+
*/
|
|
66
|
+
get LOG_LEVEL() {
|
|
67
|
+
return getEnv().LOG_LEVEL;
|
|
61
68
|
}
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Returns the index of the given log level in the LOG_LEVELS array.
|
|
71
|
+
* @param level - The log level to get the index for.
|
|
72
|
+
* @returns The index of the log level in the LOG_LEVELS array.
|
|
73
|
+
*/
|
|
74
|
+
getLogLevelIndexFor(level) {
|
|
75
|
+
return LOG_LEVELS.indexOf(level);
|
|
64
76
|
}
|
|
65
77
|
/**
|
|
66
78
|
* Checks if logging should occur based on LOG_LEVEL env var
|
|
67
79
|
*/
|
|
68
80
|
shouldLog(level) {
|
|
69
|
-
const currentLevelIndex = this.
|
|
70
|
-
const requestedLevelIndex = this.
|
|
81
|
+
const currentLevelIndex = this.getLogLevelIndexFor(this.LOG_LEVEL);
|
|
82
|
+
const requestedLevelIndex = this.getLogLevelIndexFor(level);
|
|
71
83
|
return currentLevelIndex >= 0 && requestedLevelIndex <= currentLevelIndex;
|
|
72
84
|
}
|
|
73
85
|
formatMessage(message) {
|
|
@@ -116,6 +128,6 @@ var Logger = class _Logger {
|
|
|
116
128
|
};
|
|
117
129
|
|
|
118
130
|
export {
|
|
119
|
-
|
|
131
|
+
getEnv,
|
|
120
132
|
Logger
|
|
121
133
|
};
|