@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 CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  ![scenario](https://github.com/langwatch/scenario/raw/refs/heads/main/assets/scenario-wide.webp)
4
4
 
5
-
6
5
  [![npm version](https://badge.fury.io/js/%40langwatch%2Fscenario.svg)](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 }) => `The weather in ${city} is cloudy with a temperature of 24°C.`,
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: "The user asks for the weather in a specific city, and the agent should use the weather tool to find it.",
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
- To get rich scenario reporting and logging with Vitest, add the Scenario custom reporter and setup file to your `vitest.config.ts`:
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 '@langwatch/scenario/integrations/vitest/reporter';
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: ['@langwatch/scenario/integrations/vitest/setup'],
283
- reporters: [
284
- 'default',
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
- env
4
- } from "./chunk-YPJZSK4J.mjs";
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 = ["User" /* USER */, "Agent" /* AGENT */, "Judge" /* JUDGE */];
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 env.SCENARIO_DISABLE_SIMULATION_REPORT_INFO === true;
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
- * Log level for the scenario package.
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
- var env = envSchema.parse(process.env);
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
- getLogLevel() {
60
- return env.LOG_LEVEL ?? "INFO" /* INFO */;
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
- getLogLevelIndex(level) {
63
- return Object.values(LogLevel).indexOf(level);
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.getLogLevelIndex(this.getLogLevel());
70
- const requestedLevelIndex = this.getLogLevelIndex(level);
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
- env,
131
+ getEnv,
120
132
  Logger
121
133
  };