@chanl-ai/cli 2.0.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.
Files changed (77) hide show
  1. package/bin/chanl.js +10 -0
  2. package/dist/__tests__/cli.test.d.ts +2 -0
  3. package/dist/__tests__/cli.test.js +2313 -0
  4. package/dist/__tests__/cli.test.js.map +1 -0
  5. package/dist/cli.d.ts +12 -0
  6. package/dist/cli.js +72 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/agents.d.ts +8 -0
  9. package/dist/commands/agents.js +671 -0
  10. package/dist/commands/agents.js.map +1 -0
  11. package/dist/commands/auth.d.ts +16 -0
  12. package/dist/commands/auth.js +294 -0
  13. package/dist/commands/auth.js.map +1 -0
  14. package/dist/commands/call.d.ts +8 -0
  15. package/dist/commands/call.js +166 -0
  16. package/dist/commands/call.js.map +1 -0
  17. package/dist/commands/calls.d.ts +8 -0
  18. package/dist/commands/calls.js +719 -0
  19. package/dist/commands/calls.js.map +1 -0
  20. package/dist/commands/chat.d.ts +8 -0
  21. package/dist/commands/chat.js +203 -0
  22. package/dist/commands/chat.js.map +1 -0
  23. package/dist/commands/config.d.ts +8 -0
  24. package/dist/commands/config.js +231 -0
  25. package/dist/commands/config.js.map +1 -0
  26. package/dist/commands/health.d.ts +8 -0
  27. package/dist/commands/health.js +55 -0
  28. package/dist/commands/health.js.map +1 -0
  29. package/dist/commands/index.d.ts +18 -0
  30. package/dist/commands/index.js +39 -0
  31. package/dist/commands/index.js.map +1 -0
  32. package/dist/commands/knowledge.d.ts +8 -0
  33. package/dist/commands/knowledge.js +539 -0
  34. package/dist/commands/knowledge.js.map +1 -0
  35. package/dist/commands/mcp.d.ts +8 -0
  36. package/dist/commands/mcp.js +589 -0
  37. package/dist/commands/mcp.js.map +1 -0
  38. package/dist/commands/memory.d.ts +8 -0
  39. package/dist/commands/memory.js +408 -0
  40. package/dist/commands/memory.js.map +1 -0
  41. package/dist/commands/personas.d.ts +8 -0
  42. package/dist/commands/personas.js +356 -0
  43. package/dist/commands/personas.js.map +1 -0
  44. package/dist/commands/prompts.d.ts +8 -0
  45. package/dist/commands/prompts.js +295 -0
  46. package/dist/commands/prompts.js.map +1 -0
  47. package/dist/commands/scenarios.d.ts +8 -0
  48. package/dist/commands/scenarios.js +591 -0
  49. package/dist/commands/scenarios.js.map +1 -0
  50. package/dist/commands/scorecards.d.ts +8 -0
  51. package/dist/commands/scorecards.js +570 -0
  52. package/dist/commands/scorecards.js.map +1 -0
  53. package/dist/commands/tools.d.ts +8 -0
  54. package/dist/commands/tools.js +632 -0
  55. package/dist/commands/tools.js.map +1 -0
  56. package/dist/commands/toolsets.d.ts +8 -0
  57. package/dist/commands/toolsets.js +464 -0
  58. package/dist/commands/toolsets.js.map +1 -0
  59. package/dist/commands/workspaces.d.ts +8 -0
  60. package/dist/commands/workspaces.js +170 -0
  61. package/dist/commands/workspaces.js.map +1 -0
  62. package/dist/index.d.ts +2 -0
  63. package/dist/index.js +6 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/utils/config-store.d.ts +117 -0
  66. package/dist/utils/config-store.js +191 -0
  67. package/dist/utils/config-store.js.map +1 -0
  68. package/dist/utils/interactive.d.ts +41 -0
  69. package/dist/utils/interactive.js +83 -0
  70. package/dist/utils/interactive.js.map +1 -0
  71. package/dist/utils/output.d.ts +100 -0
  72. package/dist/utils/output.js +221 -0
  73. package/dist/utils/output.js.map +1 -0
  74. package/dist/utils/sdk-factory.d.ts +15 -0
  75. package/dist/utils/sdk-factory.js +34 -0
  76. package/dist/utils/sdk-factory.js.map +1 -0
  77. package/package.json +67 -0
@@ -0,0 +1,591 @@
1
+ import { Command } from "commander";
2
+ import ora from "ora";
3
+ import chalk from "chalk";
4
+ import { createSdk } from "../utils/sdk-factory.js";
5
+ import {
6
+ printError,
7
+ printInfo,
8
+ printBlank,
9
+ printSimpleTable,
10
+ printLabel,
11
+ isJsonOutput,
12
+ printJson,
13
+ formatDate
14
+ } from "../utils/output.js";
15
+ import {
16
+ formatElapsed,
17
+ printSegment,
18
+ displayScorecard
19
+ } from "../utils/interactive.js";
20
+ function createScenariosCommand() {
21
+ const scenarios = new Command("scenarios").description("Manage and run test scenarios").addHelpText(
22
+ "after",
23
+ `
24
+ What are Scenarios?
25
+ Scenarios are test cases that run against your AI agents. Each scenario
26
+ defines a conversation flow, expected responses, and scoring criteria.
27
+
28
+ Quick Start:
29
+ $ chanl scenarios list # See all scenarios
30
+ $ chanl scenarios run <id> # Execute a scenario
31
+ $ chanl scenarios run <id> --watch # Execute and watch progress
32
+ $ chanl scenarios history <id> # View past runs
33
+
34
+ Execution Workflow:
35
+ 1. List scenarios to find the one you want to test
36
+ 2. Run the scenario (optionally with --watch)
37
+ 3. Check execution status with 'executions' or 'execution <id>'
38
+ 4. Review history with 'history <scenarioId>'`
39
+ );
40
+ scenarios.command("list").description("List all scenarios").option("-s, --status <status>", "Filter by status (draft, active, paused, completed, archived)").option("-c, --category <category>", "Filter by category").option("-l, --limit <number>", "Number of items per page", "20").option("-p, --page <number>", "Page number", "1").addHelpText(
41
+ "after",
42
+ `
43
+ Examples:
44
+ $ chanl scenarios list # List all scenarios
45
+ $ chanl scenarios list --status active # Only active scenarios
46
+ $ chanl scenarios list --category sales # Filter by category
47
+ $ chanl scenarios list --json # Output as JSON`
48
+ ).action(handleScenariosList);
49
+ scenarios.command("get <id>").description("Get a scenario by ID").addHelpText(
50
+ "after",
51
+ `
52
+ Examples:
53
+ $ chanl scenarios get abc123 # Get scenario details
54
+ $ chanl scenarios get abc123 --json # Output as JSON`
55
+ ).action(handleScenariosGet);
56
+ scenarios.command("run <id>").description("Execute a scenario").option("-a, --agent <agentId>", "Specific agent to run against").option("-m, --mode <mode>", "Simulation mode: text, websocket, phone", "websocket").option("-p, --phone <number>", "Phone number for phone mode (E.164 format)").option("-w, --watch", "Watch execution progress until completion").option("--dry-run", "Validate without actually executing").addHelpText(
57
+ "after",
58
+ `
59
+ Examples:
60
+ $ chanl scenarios run abc123 # Run with defaults
61
+ $ chanl scenarios run abc123 --watch # Run and watch progress
62
+ $ chanl scenarios run abc123 --agent agent_xyz # Run against specific agent
63
+ $ chanl scenarios run abc123 --mode phone --phone +14155551234
64
+ $ chanl scenarios run abc123 --dry-run # Validate only
65
+
66
+ Simulation Modes:
67
+ text Free, instant text-based testing
68
+ websocket Real WebSocket testing (requires provider API key)
69
+ phone Real phone call (requires provider + phone number)`
70
+ ).action(handleScenariosRun);
71
+ scenarios.command("executions").description("List scenario executions").option("-s, --scenario <scenarioId>", "Filter by scenario ID").option("--status <status>", "Filter by status (queued, running, completed, failed, timeout, cancelled)").option("-l, --limit <number>", "Number of items", "10").option("-p, --page <number>", "Page number", "1").addHelpText(
72
+ "after",
73
+ `
74
+ Examples:
75
+ $ chanl scenarios executions # List recent executions
76
+ $ chanl scenarios executions --scenario abc123 # For specific scenario
77
+ $ chanl scenarios executions --status completed # Only completed
78
+ $ chanl scenarios executions --json # Output as JSON`
79
+ ).action(handleScenariosExecutions);
80
+ scenarios.command("execution <executionId>").description("Get execution details").addHelpText(
81
+ "after",
82
+ `
83
+ Examples:
84
+ $ chanl scenarios execution exec_abc123 # Get execution details
85
+ $ chanl scenarios execution exec_abc123 --json`
86
+ ).action(handleScenariosExecution);
87
+ scenarios.command("history <scenarioId>").description("Get simulation history for a scenario").option("-l, --limit <number>", "Number of simulations to show", "10").addHelpText(
88
+ "after",
89
+ `
90
+ Examples:
91
+ $ chanl scenarios history abc123 # Last 10 runs
92
+ $ chanl scenarios history abc123 --limit 5 # Last 5 runs
93
+ $ chanl scenarios history abc123 --json # Output as JSON`
94
+ ).action(handleScenariosHistory);
95
+ scenarios.command("run-all").description("Run all scenarios for an agent and show aggregate results").requiredOption("-a, --agent <agentId>", "Agent ID to run scenarios against").option("--min-score <score>", "Minimum passing score (0-100)", "0").option("--parallel <count>", "Max concurrent executions", "3").option("-m, --mode <mode>", "Simulation mode: text, phone", "text").addHelpText(
96
+ "after",
97
+ `
98
+ Examples:
99
+ $ chanl scenarios run-all --agent agent_abc # Run all with defaults
100
+ $ chanl scenarios run-all --agent agent_abc --min-score 80 # Fail if any score < 80
101
+ $ chanl scenarios run-all --agent agent_abc --parallel 5 # Run 5 at a time
102
+ $ chanl scenarios run-all --agent agent_abc --json # Output as JSON
103
+
104
+ Exit Codes:
105
+ 0 All scenarios passed (score >= min-score)
106
+ 1 One or more scenarios failed`
107
+ ).action(handleScenariosRunAll);
108
+ return scenarios;
109
+ }
110
+ async function handleScenariosList(options) {
111
+ const sdk = createSdk();
112
+ if (!sdk) return;
113
+ const spinner = ora("Fetching scenarios...").start();
114
+ try {
115
+ const response = await sdk.scenarios.list({
116
+ status: options.status,
117
+ category: options.category,
118
+ limit: parseInt(options.limit, 10),
119
+ page: parseInt(options.page, 10)
120
+ });
121
+ spinner.stop();
122
+ if (!response.success || !response.data) {
123
+ printError("Failed to fetch scenarios", response.message);
124
+ process.exitCode = 1;
125
+ return;
126
+ }
127
+ const { scenarios, pagination } = response.data;
128
+ if (isJsonOutput()) {
129
+ printJson(response.data);
130
+ return;
131
+ }
132
+ if (scenarios.length === 0) {
133
+ printInfo("No scenarios found");
134
+ return;
135
+ }
136
+ printBlank();
137
+ printSimpleTable(
138
+ ["Name", "Status", "Category", "Difficulty", "Created"],
139
+ scenarios.map((s) => [
140
+ s.name,
141
+ formatStatus(s.status),
142
+ s.category || "-",
143
+ s.difficulty || "-",
144
+ formatDate(s.createdAt)
145
+ ])
146
+ );
147
+ printBlank();
148
+ printInfo(`Total: ${pagination.total} scenarios (Page ${pagination.page} of ${pagination.pages})`);
149
+ } catch (error) {
150
+ spinner.fail("Failed to fetch scenarios");
151
+ const message = error instanceof Error ? error.message : "Unknown error";
152
+ printError("Error", message);
153
+ process.exitCode = 1;
154
+ }
155
+ }
156
+ async function handleScenariosGet(id) {
157
+ const sdk = createSdk();
158
+ if (!sdk) return;
159
+ const spinner = ora("Fetching scenario...").start();
160
+ try {
161
+ const response = await sdk.scenarios.get(id);
162
+ spinner.stop();
163
+ if (!response.success || !response.data) {
164
+ printError("Failed to fetch scenario", response.message);
165
+ process.exitCode = 1;
166
+ return;
167
+ }
168
+ if (isJsonOutput()) {
169
+ printJson(response.data);
170
+ return;
171
+ }
172
+ const { scenario } = response.data;
173
+ printBlank();
174
+ console.log(chalk.bold("Scenario Details:"));
175
+ console.log(` Name: ${scenario.name}`);
176
+ console.log(` ID: ${scenario.id}`);
177
+ console.log(` Status: ${formatStatus(scenario.status)}`);
178
+ console.log(` Category: ${scenario.category || "-"}`);
179
+ console.log(` Difficulty: ${scenario.difficulty || "-"}`);
180
+ console.log(` Created: ${formatDate(scenario.createdAt)}`);
181
+ if (scenario.description) {
182
+ console.log(` Description: ${scenario.description}`);
183
+ }
184
+ printBlank();
185
+ } catch (error) {
186
+ spinner.fail("Failed to fetch scenario");
187
+ const message = error instanceof Error ? error.message : "Unknown error";
188
+ printError("Error", message);
189
+ process.exitCode = 1;
190
+ }
191
+ }
192
+ function formatStatus(status) {
193
+ switch (status) {
194
+ case "active":
195
+ return chalk.green("active");
196
+ case "paused":
197
+ return chalk.yellow("paused");
198
+ case "completed":
199
+ return chalk.blue("completed");
200
+ case "archived":
201
+ return chalk.gray("archived");
202
+ case "draft":
203
+ default:
204
+ return chalk.gray(status || "draft");
205
+ }
206
+ }
207
+ function formatExecutionStatus(status) {
208
+ switch (status) {
209
+ case "completed":
210
+ return chalk.green("completed");
211
+ case "running":
212
+ return chalk.cyan("running");
213
+ case "queued":
214
+ return chalk.blue("queued");
215
+ case "failed":
216
+ return chalk.red("failed");
217
+ case "timeout":
218
+ return chalk.yellow("timeout");
219
+ case "cancelled":
220
+ return chalk.gray("cancelled");
221
+ default:
222
+ return chalk.gray(status || "unknown");
223
+ }
224
+ }
225
+ function formatScore(score) {
226
+ if (score === void 0 || score === null) return "-";
227
+ if (score >= 80) return chalk.green(`${score}%`);
228
+ if (score >= 60) return chalk.yellow(`${score}%`);
229
+ return chalk.red(`${score}%`);
230
+ }
231
+ function formatDuration(seconds) {
232
+ if (!seconds) return "-";
233
+ if (seconds < 60) return `${seconds.toFixed(1)}s`;
234
+ const mins = Math.floor(seconds / 60);
235
+ const secs = seconds % 60;
236
+ return `${mins}m ${secs.toFixed(0)}s`;
237
+ }
238
+ async function handleScenariosRun(id, options) {
239
+ const sdk = createSdk();
240
+ if (!sdk) return;
241
+ const spinner = ora("Starting scenario execution...").start();
242
+ try {
243
+ const response = await sdk.scenarios.run(id, {
244
+ agentId: options.agent,
245
+ simulationMode: options.mode,
246
+ phoneNumber: options.phone,
247
+ dryRun: options.dryRun
248
+ });
249
+ if (!response.success || !response.data) {
250
+ spinner.fail("Failed to start execution");
251
+ printError("Error", response.message || "Unknown error");
252
+ process.exitCode = 1;
253
+ return;
254
+ }
255
+ const { execution, executionId } = response.data;
256
+ const execId = executionId || execution?.id || execution?.executionId;
257
+ if (options.dryRun) {
258
+ spinner.succeed("Dry run validation passed");
259
+ printInfo("Scenario is valid and ready to execute");
260
+ return;
261
+ }
262
+ spinner.succeed(`Execution started: ${execId}`);
263
+ if (isJsonOutput()) {
264
+ printJson(response.data);
265
+ return;
266
+ }
267
+ if (!options.watch) {
268
+ printBlank();
269
+ printLabel("Execution ID", execId || "N/A");
270
+ printLabel("Status", formatExecutionStatus(execution?.status));
271
+ printInfo(`Run 'chanl scenarios execution ${execId}' to check status`);
272
+ printBlank();
273
+ return;
274
+ }
275
+ await watchExecution(sdk, execId, options.mode === "phone");
276
+ } catch (error) {
277
+ spinner.fail("Failed to execute scenario");
278
+ const message = error instanceof Error ? error.message : "Unknown error";
279
+ printError("Error", message);
280
+ process.exitCode = 1;
281
+ }
282
+ }
283
+ async function watchExecution(sdk, executionId, isPhoneMode = false) {
284
+ const startTime = /* @__PURE__ */ new Date();
285
+ let spinner = ora(
286
+ isPhoneMode ? `${chalk.red("LIVE")} \u2014 ${formatElapsed(startTime)} | Watching voice execution...` : "Watching execution..."
287
+ ).start();
288
+ const live = sdk.scenarios.watchExecution(executionId);
289
+ let finalExecution;
290
+ let scorecardReceived = false;
291
+ live.on("status", (status) => {
292
+ if (isPhoneMode) {
293
+ spinner.text = `${chalk.red("LIVE")} \u2014 ${formatElapsed(startTime)} | Status: ${status}`;
294
+ } else {
295
+ spinner.text = `Status: ${status}`;
296
+ }
297
+ });
298
+ live.on("step", (step) => {
299
+ if (!isPhoneMode) {
300
+ spinner.stop();
301
+ const stepStatus = step.status === "completed" ? chalk.green("\u2713") : chalk.red("\u2717");
302
+ console.log(` ${stepStatus} Step ${step.stepId}: ${step.response?.slice(0, 80) || "-"}`);
303
+ if (step.toolCalls.length > 0) {
304
+ for (const tc of step.toolCalls) {
305
+ const tcIcon = tc.status === "success" ? chalk.green("\u2713") : chalk.red("\u2717");
306
+ const dur = tc.durationMs ? chalk.dim(` (${tc.durationMs}ms)`) : "";
307
+ console.log(` ${tcIcon} ${chalk.yellow(tc.name)}${dur}`);
308
+ }
309
+ }
310
+ spinner.start();
311
+ }
312
+ });
313
+ live.on("transcript", (seg) => {
314
+ spinner.stop();
315
+ printSegment(seg);
316
+ spinner.start();
317
+ });
318
+ live.on("completed", (execution) => {
319
+ finalExecution = execution;
320
+ const status = execution.status;
321
+ if (status === "completed") {
322
+ spinner.succeed(
323
+ isPhoneMode ? `Execution complete \u2014 ${formatElapsed(startTime)}` : "Execution completed"
324
+ );
325
+ } else if (status === "failed") {
326
+ spinner.fail(
327
+ isPhoneMode ? `Execution failed \u2014 ${formatElapsed(startTime)}` : "Execution failed"
328
+ );
329
+ } else {
330
+ spinner.warn(`Execution ${status}`);
331
+ }
332
+ printBlank();
333
+ printExecutionDetails(execution);
334
+ if (isPhoneMode && execution.callDetails?.callId) {
335
+ spinner = ora("Checking for scorecard...").start();
336
+ }
337
+ });
338
+ live.on("scorecard", (results) => {
339
+ scorecardReceived = true;
340
+ spinner.stop();
341
+ displayScorecard(results);
342
+ printBlank();
343
+ });
344
+ live.on("timeout", () => {
345
+ spinner.warn("Timeout waiting for execution to complete");
346
+ printInfo(`Run 'chanl scenarios execution ${executionId}' to check status`);
347
+ });
348
+ live.on("error", (err) => {
349
+ spinner.fail("Error while watching");
350
+ printError("Error", err.message);
351
+ process.exitCode = 1;
352
+ });
353
+ await live.completed;
354
+ if (finalExecution && isPhoneMode && finalExecution.callDetails?.callId && !scorecardReceived) {
355
+ spinner.stop();
356
+ }
357
+ }
358
+ function printExecutionDetails(execution) {
359
+ console.log(chalk.bold("Execution Results:"));
360
+ console.log(` Execution ID: ${execution.id || execution.executionId}`);
361
+ console.log(` Scenario ID: ${execution.scenarioId}`);
362
+ console.log(` Status: ${formatExecutionStatus(execution.status)}`);
363
+ console.log(` Score: ${formatScore(execution.overallScore)}`);
364
+ console.log(` Duration: ${formatDuration(execution.duration)}`);
365
+ if (execution.metrics) {
366
+ console.log(chalk.bold("\n Metrics:"));
367
+ if (execution.metrics.responseTime !== void 0) {
368
+ console.log(` Response Time: ${execution.metrics.responseTime.toFixed(0)}ms`);
369
+ }
370
+ if (execution.metrics.accuracy !== void 0) {
371
+ console.log(` Accuracy: ${formatScore(execution.metrics.accuracy)}`);
372
+ }
373
+ if (execution.metrics.completion !== void 0) {
374
+ console.log(` Completion: ${formatScore(execution.metrics.completion)}`);
375
+ }
376
+ }
377
+ if (execution.callDetails?.callId) {
378
+ console.log(chalk.bold("\n Call Details:"));
379
+ console.log(` Call ID: ${execution.callDetails.callId}`);
380
+ if (execution.callDetails.phoneNumber) {
381
+ console.log(` Phone: ${execution.callDetails.phoneNumber}`);
382
+ }
383
+ }
384
+ const allToolCalls = (execution.stepResults ?? []).flatMap((s) => s.toolCalls ?? []);
385
+ if (allToolCalls.length > 0) {
386
+ console.log(chalk.bold("\n Tool Calls:"));
387
+ printScenarioToolCalls(allToolCalls);
388
+ }
389
+ if (execution.errorMessages && execution.errorMessages.length > 0) {
390
+ console.log(chalk.bold("\n Errors:"));
391
+ execution.errorMessages.forEach((msg) => {
392
+ console.log(chalk.red(` - ${msg}`));
393
+ });
394
+ }
395
+ printBlank();
396
+ }
397
+ function printScenarioToolCalls(toolCalls) {
398
+ for (const tc of toolCalls) {
399
+ const statusIcon = tc.status === "success" ? chalk.green("\u2713") : tc.status === "error" ? chalk.red("\u2717") : tc.status === "timeout" ? chalk.yellow("\u23F1") : chalk.dim("\u2026");
400
+ const duration = tc.durationMs ? chalk.dim(` (${tc.durationMs}ms)`) : "";
401
+ const params = Object.keys(tc.parameters).length ? chalk.dim(` ${JSON.stringify(tc.parameters)}`) : "";
402
+ console.log(` ${statusIcon} ${chalk.yellow(tc.name)}${params}${duration}`);
403
+ if (tc.status === "error" && tc.error) {
404
+ console.log(` ${chalk.red(tc.error.message)}`);
405
+ }
406
+ }
407
+ }
408
+ async function handleScenariosExecutions(options) {
409
+ const sdk = createSdk();
410
+ if (!sdk) return;
411
+ const spinner = ora("Fetching executions...").start();
412
+ try {
413
+ const response = await sdk.scenarios.getExecutions({
414
+ scenarioId: options.scenario,
415
+ status: options.status,
416
+ limit: parseInt(options.limit, 10),
417
+ page: parseInt(options.page, 10)
418
+ });
419
+ spinner.stop();
420
+ if (!response.success || !response.data) {
421
+ printError("Failed to fetch executions", response.message);
422
+ process.exitCode = 1;
423
+ return;
424
+ }
425
+ const { executions, total } = response.data;
426
+ if (isJsonOutput()) {
427
+ printJson(response.data);
428
+ return;
429
+ }
430
+ if (executions.length === 0) {
431
+ printInfo("No executions found");
432
+ return;
433
+ }
434
+ printBlank();
435
+ printSimpleTable(
436
+ ["Execution ID", "Scenario", "Status", "Score", "Duration", "Started"],
437
+ executions.map((e) => [
438
+ (e.id || e.executionId || "").slice(-12),
439
+ e.scenarioId?.slice(-8) || "-",
440
+ formatExecutionStatus(e.status),
441
+ formatScore(e.overallScore),
442
+ formatDuration(e.duration),
443
+ e.startTime ? formatDate(e.startTime) : "-"
444
+ ])
445
+ );
446
+ printBlank();
447
+ printInfo(`Total: ${total} executions`);
448
+ } catch (error) {
449
+ spinner.fail("Failed to fetch executions");
450
+ const message = error instanceof Error ? error.message : "Unknown error";
451
+ printError("Error", message);
452
+ process.exitCode = 1;
453
+ }
454
+ }
455
+ async function handleScenariosExecution(executionId) {
456
+ const sdk = createSdk();
457
+ if (!sdk) return;
458
+ const spinner = ora("Fetching execution...").start();
459
+ try {
460
+ const response = await sdk.scenarios.getExecution(executionId);
461
+ spinner.stop();
462
+ if (!response.success || !response.data) {
463
+ printError("Failed to fetch execution", response.message);
464
+ process.exitCode = 1;
465
+ return;
466
+ }
467
+ if (isJsonOutput()) {
468
+ printJson(response.data);
469
+ return;
470
+ }
471
+ const { execution } = response.data;
472
+ printBlank();
473
+ printExecutionDetails(execution);
474
+ } catch (error) {
475
+ spinner.fail("Failed to fetch execution");
476
+ const message = error instanceof Error ? error.message : "Unknown error";
477
+ printError("Error", message);
478
+ process.exitCode = 1;
479
+ }
480
+ }
481
+ async function handleScenariosHistory(scenarioId, options) {
482
+ const sdk = createSdk();
483
+ if (!sdk) return;
484
+ const spinner = ora("Fetching simulation history...").start();
485
+ try {
486
+ const response = await sdk.scenarios.getSimulations(
487
+ scenarioId,
488
+ parseInt(options.limit, 10)
489
+ );
490
+ spinner.stop();
491
+ if (!response.success || !response.data) {
492
+ printError("Failed to fetch history", response.message);
493
+ process.exitCode = 1;
494
+ return;
495
+ }
496
+ const { simulations } = response.data;
497
+ if (isJsonOutput()) {
498
+ printJson(response.data);
499
+ return;
500
+ }
501
+ if (simulations.length === 0) {
502
+ printInfo("No simulation history found for this scenario");
503
+ return;
504
+ }
505
+ printBlank();
506
+ console.log(chalk.bold(`Simulation History for ${scenarioId}`));
507
+ console.log(chalk.dim("\u2500".repeat(60)));
508
+ printSimpleTable(
509
+ ["#", "Status", "Score", "Duration", "Started"],
510
+ simulations.map((s, i) => [
511
+ (i + 1).toString(),
512
+ formatExecutionStatus(s.status),
513
+ formatScore(s.overallScore),
514
+ formatDuration(s.duration),
515
+ s.startTime ? formatDate(s.startTime) : "-"
516
+ ])
517
+ );
518
+ printBlank();
519
+ printInfo(`Showing last ${simulations.length} simulations`);
520
+ } catch (error) {
521
+ spinner.fail("Failed to fetch history");
522
+ const message = error instanceof Error ? error.message : "Unknown error";
523
+ printError("Error", message);
524
+ process.exitCode = 1;
525
+ }
526
+ }
527
+ async function handleScenariosRunAll(options) {
528
+ const sdk = createSdk();
529
+ if (!sdk) return;
530
+ const minScore = parseInt(options.minScore, 10);
531
+ const parallel = parseInt(options.parallel, 10);
532
+ const spinner = ora(`Running all scenarios for agent ${options.agent}...`).start();
533
+ try {
534
+ const result = await sdk.scenarios.runAll({
535
+ agentId: options.agent,
536
+ minScore,
537
+ parallel,
538
+ mode: options.mode
539
+ });
540
+ spinner.stop();
541
+ if (isJsonOutput()) {
542
+ printJson(result);
543
+ if (!result.allPassed) {
544
+ process.exitCode = 1;
545
+ }
546
+ return;
547
+ }
548
+ if (result.totalScenarios === 0) {
549
+ printInfo("No active scenarios found for this agent");
550
+ return;
551
+ }
552
+ printBlank();
553
+ console.log(chalk.bold("Batch Scenario Results"));
554
+ console.log(chalk.dim("\u2500".repeat(60)));
555
+ printSimpleTable(
556
+ ["Scenario", "Status", "Score", "Duration", "Tools", "Result"],
557
+ result.results.map((r) => [
558
+ r.scenarioName,
559
+ formatExecutionStatus(r.status),
560
+ formatScore(r.score),
561
+ formatDuration(r.duration),
562
+ r.toolCallCount.toString(),
563
+ r.passed ? chalk.green("PASS") : chalk.red("FAIL")
564
+ ])
565
+ );
566
+ printBlank();
567
+ console.log(chalk.bold("Summary"));
568
+ console.log(` Total: ${result.totalScenarios}`);
569
+ console.log(` Passed: ${chalk.green(result.passed.toString())}`);
570
+ console.log(` Failed: ${result.failed > 0 ? chalk.red(result.failed.toString()) : "0"}`);
571
+ console.log(` Average Score: ${formatScore(result.averageScore)}`);
572
+ console.log(` Min Score: ${result.minScore}`);
573
+ printBlank();
574
+ if (result.allPassed) {
575
+ console.log(chalk.green(`All ${result.totalScenarios} scenarios passed`));
576
+ } else {
577
+ console.log(chalk.red(`${result.failed} of ${result.totalScenarios} scenarios failed`));
578
+ process.exitCode = 1;
579
+ }
580
+ printBlank();
581
+ } catch (error) {
582
+ spinner.fail("Failed to run scenarios");
583
+ const message = error instanceof Error ? error.message : "Unknown error";
584
+ printError("Error", message);
585
+ process.exitCode = 1;
586
+ }
587
+ }
588
+ export {
589
+ createScenariosCommand
590
+ };
591
+ //# sourceMappingURL=scenarios.js.map