@chanl/eval-cli 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.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/dist/agent-loader.d.ts +39 -0
  3. package/dist/agent-loader.d.ts.map +1 -0
  4. package/dist/agent-loader.js +166 -0
  5. package/dist/agent-loader.js.map +1 -0
  6. package/dist/analytics.d.ts +15 -0
  7. package/dist/analytics.d.ts.map +1 -0
  8. package/dist/analytics.js +94 -0
  9. package/dist/analytics.js.map +1 -0
  10. package/dist/assertions.d.ts +73 -0
  11. package/dist/assertions.d.ts.map +1 -0
  12. package/dist/assertions.js +282 -0
  13. package/dist/assertions.js.map +1 -0
  14. package/dist/baseline.d.ts +100 -0
  15. package/dist/baseline.d.ts.map +1 -0
  16. package/dist/baseline.js +327 -0
  17. package/dist/baseline.js.map +1 -0
  18. package/dist/bin/chanl.d.ts +3 -0
  19. package/dist/bin/chanl.d.ts.map +1 -0
  20. package/dist/bin/chanl.js +11 -0
  21. package/dist/bin/chanl.js.map +1 -0
  22. package/dist/client.d.ts +40 -0
  23. package/dist/client.d.ts.map +1 -0
  24. package/dist/client.js +99 -0
  25. package/dist/client.js.map +1 -0
  26. package/dist/commands/analytics.d.ts +3 -0
  27. package/dist/commands/analytics.d.ts.map +1 -0
  28. package/dist/commands/analytics.js +44 -0
  29. package/dist/commands/analytics.js.map +1 -0
  30. package/dist/commands/compare.d.ts +51 -0
  31. package/dist/commands/compare.d.ts.map +1 -0
  32. package/dist/commands/compare.js +429 -0
  33. package/dist/commands/compare.js.map +1 -0
  34. package/dist/commands/config.d.ts +3 -0
  35. package/dist/commands/config.d.ts.map +1 -0
  36. package/dist/commands/config.js +94 -0
  37. package/dist/commands/config.js.map +1 -0
  38. package/dist/commands/dataset.d.ts +6 -0
  39. package/dist/commands/dataset.d.ts.map +1 -0
  40. package/dist/commands/dataset.js +225 -0
  41. package/dist/commands/dataset.js.map +1 -0
  42. package/dist/commands/executions.d.ts +3 -0
  43. package/dist/commands/executions.d.ts.map +1 -0
  44. package/dist/commands/executions.js +249 -0
  45. package/dist/commands/executions.js.map +1 -0
  46. package/dist/commands/generate.d.ts +3 -0
  47. package/dist/commands/generate.d.ts.map +1 -0
  48. package/dist/commands/generate.js +159 -0
  49. package/dist/commands/generate.js.map +1 -0
  50. package/dist/commands/init.d.ts +29 -0
  51. package/dist/commands/init.d.ts.map +1 -0
  52. package/dist/commands/init.js +545 -0
  53. package/dist/commands/init.js.map +1 -0
  54. package/dist/commands/login.d.ts +3 -0
  55. package/dist/commands/login.d.ts.map +1 -0
  56. package/dist/commands/login.js +65 -0
  57. package/dist/commands/login.js.map +1 -0
  58. package/dist/commands/personas.d.ts +3 -0
  59. package/dist/commands/personas.d.ts.map +1 -0
  60. package/dist/commands/personas.js +269 -0
  61. package/dist/commands/personas.js.map +1 -0
  62. package/dist/commands/scenarios.d.ts +16 -0
  63. package/dist/commands/scenarios.d.ts.map +1 -0
  64. package/dist/commands/scenarios.js +755 -0
  65. package/dist/commands/scenarios.js.map +1 -0
  66. package/dist/commands/scorecards.d.ts +3 -0
  67. package/dist/commands/scorecards.d.ts.map +1 -0
  68. package/dist/commands/scorecards.js +220 -0
  69. package/dist/commands/scorecards.js.map +1 -0
  70. package/dist/commands/server.d.ts +8 -0
  71. package/dist/commands/server.d.ts.map +1 -0
  72. package/dist/commands/server.js +357 -0
  73. package/dist/commands/server.js.map +1 -0
  74. package/dist/commands/test.d.ts +3 -0
  75. package/dist/commands/test.d.ts.map +1 -0
  76. package/dist/commands/test.js +410 -0
  77. package/dist/commands/test.js.map +1 -0
  78. package/dist/commands/tool-fixtures.d.ts +3 -0
  79. package/dist/commands/tool-fixtures.d.ts.map +1 -0
  80. package/dist/commands/tool-fixtures.js +324 -0
  81. package/dist/commands/tool-fixtures.js.map +1 -0
  82. package/dist/config.d.ts +32 -0
  83. package/dist/config.d.ts.map +1 -0
  84. package/dist/config.js +132 -0
  85. package/dist/config.js.map +1 -0
  86. package/dist/index.d.ts +8 -0
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +146 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/output.d.ts +30 -0
  91. package/dist/output.d.ts.map +1 -0
  92. package/dist/output.js +77 -0
  93. package/dist/output.js.map +1 -0
  94. package/dist/update-check.d.ts +6 -0
  95. package/dist/update-check.d.ts.map +1 -0
  96. package/dist/update-check.js +50 -0
  97. package/dist/update-check.js.map +1 -0
  98. package/package.json +42 -0
@@ -0,0 +1,545 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.scaffoldProject = scaffoldProject;
40
+ exports.getTemplateList = getTemplateList;
41
+ exports.registerInitCommand = registerInitCommand;
42
+ exports.registerTemplatesCommand = registerTemplatesCommand;
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const chalk_1 = __importDefault(require("chalk"));
46
+ const output_1 = require("../output");
47
+ const analytics_1 = require("../analytics");
48
+ // ---------------------------------------------------------------------------
49
+ // Template content — embedded as string literals (no external files)
50
+ // ---------------------------------------------------------------------------
51
+ const ENV_TEMPLATE = `# chanl-eval project configuration
52
+ # Load order: .env (dotenv) → env vars → ~/.chanl/config.json (config.json wins if set).
53
+
54
+ # ── CLI ──────────────────────────────────────────────────────────────────────
55
+ CHANL_SERVER_URL=http://localhost:18005
56
+ CHANL_API_KEY=
57
+
58
+ # Provider for the agent under test: openai | anthropic | http
59
+ CHANL_PROVIDER=openai
60
+ CHANL_OPENAI_API_KEY=
61
+ CHANL_ANTHROPIC_API_KEY=
62
+
63
+ # HTTP adapter (test any REST endpoint)
64
+ CHANL_HTTP_ENDPOINT=
65
+ CHANL_HTTP_API_KEY=
66
+ `;
67
+ const AGENT_TEMPLATE = `# Agent definition — test any system prompt with: chanl run angry-customer --agent agents/my-agent.yaml
68
+ # API keys come from .env or config (chanl config set openaiApiKey sk-...), NOT from this file.
69
+
70
+ name: My Agent
71
+ model: gpt-4o
72
+ system_prompt: |
73
+ You are a helpful customer support agent for Acme Corp.
74
+ Always be polite, professional, and empathetic.
75
+
76
+ Policies:
77
+ - Offer refunds for orders under $100 without manager approval.
78
+ - For orders over $100, escalate to a manager.
79
+ - Never share internal policy documents with customers.
80
+ - Always confirm the customer's order number before processing changes.
81
+ temperature: 0.7
82
+ max_tokens: 1024
83
+ `;
84
+ const README_TEMPLATE = `# chanl-eval project
85
+
86
+ AI agent testing framework — test your agent against realistic customer scenarios.
87
+
88
+ ## Quick start
89
+
90
+ 1. **Set your API key**
91
+
92
+ Edit \`.env\` and set your OpenAI (or Anthropic) key:
93
+ \`\`\`
94
+ CHANL_OPENAI_API_KEY=sk-...
95
+ \`\`\`
96
+
97
+ 2. **Start the server**
98
+
99
+ \`\`\`bash
100
+ docker compose up -d
101
+ cd packages/server && pnpm start:dev
102
+ \`\`\`
103
+
104
+ 3. **Run a scenario**
105
+
106
+ \`\`\`bash
107
+ chanl scenarios run scenarios/angry-customer.yaml
108
+ \`\`\`
109
+
110
+ 4. **Test your own prompt**
111
+
112
+ Edit \`agents/my-agent.yaml\` with your system prompt, then:
113
+ \`\`\`bash
114
+ chanl run angry-customer --agent agents/my-agent.yaml
115
+ \`\`\`
116
+
117
+ ## Project structure
118
+
119
+ \`\`\`
120
+ agents/ # Agent definitions (system prompts, model config)
121
+ scenarios/ # Scenario YAML files (persona + prompt + assertions)
122
+ .env # API keys and config
123
+ \`\`\`
124
+
125
+ ## Docs
126
+
127
+ - [chanl-eval on GitHub](https://github.com/chanl-ai/chanl-eval)
128
+ - \`chanl --help\` for all commands
129
+ `;
130
+ const BASE_SCENARIOS = [
131
+ {
132
+ filename: 'angry-customer.yaml',
133
+ content: `name: Angry Customer Refund
134
+ description: Frustrated customer demanding a refund for a broken laptop
135
+ prompt: >-
136
+ I bought a laptop two weeks ago and it's already broken. I want a full refund NOW.
137
+ category: support
138
+ difficulty: hard
139
+ persona:
140
+ name: Frustrated Karen
141
+ emotion: frustrated
142
+ speechStyle: fast
143
+ intentClarity: very clear
144
+ behavior:
145
+ cooperationLevel: hostile
146
+ patience: impatient
147
+ assertions:
148
+ - type: keyword
149
+ must_include: ["refund", "policy"]
150
+ - type: response_time
151
+ max_seconds: 5
152
+ tags:
153
+ - refund
154
+ - support
155
+ - escalation
156
+ `,
157
+ },
158
+ {
159
+ filename: 'billing-dispute.yaml',
160
+ content: `name: Billing Dispute
161
+ description: Customer questioning an unexpected charge on their account
162
+ prompt: >-
163
+ I just noticed a charge of $49.99 on my credit card from your company.
164
+ I never authorized this. What is going on?
165
+ category: support
166
+ difficulty: medium
167
+ persona:
168
+ name: Concerned Account Holder
169
+ emotion: worried
170
+ speechStyle: normal
171
+ intentClarity: clear
172
+ behavior:
173
+ cooperationLevel: neutral
174
+ patience: moderate
175
+ assertions:
176
+ - type: keyword
177
+ must_include: ["credit", "charge"]
178
+ - type: response_time
179
+ max_seconds: 5
180
+ tags:
181
+ - billing
182
+ - support
183
+ - dispute
184
+ `,
185
+ },
186
+ {
187
+ filename: 'product-inquiry.yaml',
188
+ content: `name: Product Inquiry
189
+ description: Friendly customer asking about product features and pricing
190
+ prompt: >-
191
+ Hi! I'm looking at the Pro plan on your website. Can you tell me what's
192
+ included and whether there's a free trial?
193
+ category: sales
194
+ difficulty: easy
195
+ persona:
196
+ name: Curious Prospect
197
+ emotion: neutral
198
+ speechStyle: normal
199
+ intentClarity: clear
200
+ behavior:
201
+ cooperationLevel: cooperative
202
+ patience: patient
203
+ assertions:
204
+ - type: keyword
205
+ must_include: ["plan", "features"]
206
+ - type: response_time
207
+ max_seconds: 5
208
+ tags:
209
+ - sales
210
+ - inquiry
211
+ - pricing
212
+ `,
213
+ },
214
+ ];
215
+ // -- customer-support template scenarios ------------------------------------
216
+ const CUSTOMER_SUPPORT_SCENARIOS = [
217
+ ...BASE_SCENARIOS,
218
+ {
219
+ filename: 'technical-issue.yaml',
220
+ content: `name: Technical Issue
221
+ description: Customer struggling with a technical problem and getting frustrated
222
+ prompt: >-
223
+ Your app keeps crashing every time I try to upload a file. I've tried
224
+ restarting my phone three times. This is ridiculous.
225
+ category: support
226
+ difficulty: medium
227
+ persona:
228
+ name: Confused Elderly Customer
229
+ emotion: confused
230
+ speechStyle: slow
231
+ intentClarity: vague
232
+ behavior:
233
+ cooperationLevel: cooperative
234
+ patience: patient
235
+ assertions:
236
+ - type: keyword
237
+ must_include: ["troubleshoot", "steps"]
238
+ - type: response_time
239
+ max_seconds: 5
240
+ tags:
241
+ - technical
242
+ - support
243
+ - app-issue
244
+ `,
245
+ },
246
+ {
247
+ filename: 'escalation-request.yaml',
248
+ content: `name: Escalation Request
249
+ description: Impatient executive demanding to speak with a manager immediately
250
+ prompt: >-
251
+ I've been a premium customer for five years and this is the third time
252
+ I'm calling about the same issue. I want to speak with a manager RIGHT NOW.
253
+ category: support
254
+ difficulty: hard
255
+ persona:
256
+ name: Impatient Executive
257
+ emotion: angry
258
+ speechStyle: fast
259
+ intentClarity: very clear
260
+ behavior:
261
+ cooperationLevel: hostile
262
+ patience: none
263
+ assertions:
264
+ - type: keyword
265
+ must_include: ["manager", "escalate"]
266
+ - type: response_time
267
+ max_seconds: 5
268
+ tags:
269
+ - escalation
270
+ - support
271
+ - vip
272
+ `,
273
+ },
274
+ ];
275
+ // -- sales template scenarios -----------------------------------------------
276
+ const SALES_SCENARIOS = [
277
+ {
278
+ filename: 'cold-outreach.yaml',
279
+ content: `name: Cold Outreach Response
280
+ description: Prospect responding to a cold email with mild interest
281
+ prompt: >-
282
+ I got your email about your analytics platform. We're currently using
283
+ a competitor but our contract is up in two months. What makes you different?
284
+ category: sales
285
+ difficulty: medium
286
+ persona:
287
+ name: Skeptical Buyer
288
+ emotion: neutral
289
+ speechStyle: normal
290
+ intentClarity: clear
291
+ behavior:
292
+ cooperationLevel: neutral
293
+ patience: moderate
294
+ assertions:
295
+ - type: keyword
296
+ must_include: ["differentiate", "value"]
297
+ - type: response_time
298
+ max_seconds: 5
299
+ tags:
300
+ - sales
301
+ - outreach
302
+ - comparison
303
+ `,
304
+ },
305
+ {
306
+ filename: 'pricing-negotiation.yaml',
307
+ content: `name: Pricing Negotiation
308
+ description: Budget-conscious buyer pushing back on pricing
309
+ prompt: >-
310
+ We like the product but the pricing is way above our budget. Our team
311
+ is only 5 people. Is there a startup discount or a smaller plan?
312
+ category: sales
313
+ difficulty: medium
314
+ persona:
315
+ name: Budget-Conscious Startup Founder
316
+ emotion: neutral
317
+ speechStyle: normal
318
+ intentClarity: clear
319
+ behavior:
320
+ cooperationLevel: cooperative
321
+ patience: moderate
322
+ assertions:
323
+ - type: keyword
324
+ must_include: ["pricing", "plan"]
325
+ - type: response_time
326
+ max_seconds: 5
327
+ tags:
328
+ - sales
329
+ - pricing
330
+ - negotiation
331
+ `,
332
+ },
333
+ {
334
+ filename: 'demo-request.yaml',
335
+ content: `name: Demo Request
336
+ description: Enthusiastic prospect requesting a product demo
337
+ prompt: >-
338
+ I saw your product on Product Hunt and I'm really interested.
339
+ Can we schedule a demo this week? We need something like this for our team.
340
+ category: sales
341
+ difficulty: easy
342
+ persona:
343
+ name: Eager Early Adopter
344
+ emotion: excited
345
+ speechStyle: fast
346
+ intentClarity: very clear
347
+ behavior:
348
+ cooperationLevel: cooperative
349
+ patience: patient
350
+ assertions:
351
+ - type: keyword
352
+ must_include: ["demo", "schedule"]
353
+ - type: response_time
354
+ max_seconds: 5
355
+ tags:
356
+ - sales
357
+ - demo
358
+ - inbound
359
+ `,
360
+ },
361
+ {
362
+ filename: 'competitor-comparison.yaml',
363
+ content: `name: Competitor Comparison
364
+ description: Prospect actively comparing your product against a known competitor
365
+ prompt: >-
366
+ We've been evaluating both your platform and Competitor X. They offer
367
+ a similar feature set at a lower price point. Can you walk me through
368
+ why we should choose you instead?
369
+ category: sales
370
+ difficulty: hard
371
+ persona:
372
+ name: Analytical Decision Maker
373
+ emotion: neutral
374
+ speechStyle: normal
375
+ intentClarity: very clear
376
+ behavior:
377
+ cooperationLevel: neutral
378
+ patience: moderate
379
+ assertions:
380
+ - type: keyword
381
+ must_include: ["advantage", "compare"]
382
+ - type: response_time
383
+ max_seconds: 5
384
+ tags:
385
+ - sales
386
+ - competitor
387
+ - comparison
388
+ `,
389
+ },
390
+ ];
391
+ const TEMPLATE_MAP = {
392
+ 'customer-support': CUSTOMER_SUPPORT_SCENARIOS,
393
+ 'sales': SALES_SCENARIOS,
394
+ };
395
+ const AVAILABLE_TEMPLATES = Object.keys(TEMPLATE_MAP);
396
+ /**
397
+ * Scaffold a chanl-eval project directory.
398
+ *
399
+ * @param targetDir - Absolute path to the directory to scaffold into
400
+ * @param options - Template selection
401
+ * @returns Object describing created files (for testing)
402
+ */
403
+ function scaffoldProject(targetDir, options = {}) {
404
+ const createdFiles = [];
405
+ const createdDirs = [];
406
+ // Resolve scenario set
407
+ const scenarios = options.template
408
+ ? TEMPLATE_MAP[options.template] || BASE_SCENARIOS
409
+ : BASE_SCENARIOS;
410
+ // Create directories
411
+ const agentsDir = path.join(targetDir, 'agents');
412
+ const scenariosDir = path.join(targetDir, 'scenarios');
413
+ for (const dir of [targetDir, agentsDir, scenariosDir]) {
414
+ if (!fs.existsSync(dir)) {
415
+ fs.mkdirSync(dir, { recursive: true });
416
+ createdDirs.push(dir);
417
+ }
418
+ }
419
+ // Write files (skip if they already exist to avoid overwriting user work)
420
+ const filesToWrite = [
421
+ { rel: '.env', content: ENV_TEMPLATE },
422
+ { rel: 'agents/my-agent.yaml', content: AGENT_TEMPLATE },
423
+ { rel: 'README.md', content: README_TEMPLATE },
424
+ ...scenarios.map((s) => ({
425
+ rel: `scenarios/${s.filename}`,
426
+ content: s.content,
427
+ })),
428
+ ];
429
+ for (const { rel, content } of filesToWrite) {
430
+ const abs = path.join(targetDir, rel);
431
+ if (!fs.existsSync(abs)) {
432
+ fs.writeFileSync(abs, content, 'utf-8');
433
+ createdFiles.push(rel);
434
+ }
435
+ }
436
+ return { files: createdFiles, dirs: createdDirs };
437
+ }
438
+ const TEMPLATE_INFO = {
439
+ 'customer-support': {
440
+ name: 'customer-support',
441
+ description: 'Support scenarios: refunds, billing, technical issues, escalations',
442
+ scenarioCount: CUSTOMER_SUPPORT_SCENARIOS.length,
443
+ categories: ['support', 'sales'],
444
+ },
445
+ 'sales': {
446
+ name: 'sales',
447
+ description: 'Sales scenarios: outreach, pricing objections, demos, competitor comparison',
448
+ scenarioCount: SALES_SCENARIOS.length,
449
+ categories: ['sales'],
450
+ },
451
+ };
452
+ /**
453
+ * Get metadata about all available templates.
454
+ */
455
+ function getTemplateList() {
456
+ return Object.values(TEMPLATE_INFO);
457
+ }
458
+ // ---------------------------------------------------------------------------
459
+ // CLI command registration
460
+ // ---------------------------------------------------------------------------
461
+ function registerInitCommand(program) {
462
+ program
463
+ .command('init [directory]')
464
+ .description('Scaffold a chanl-eval project with agent and scenario files')
465
+ .option('-t, --template <name>', `Industry template: ${AVAILABLE_TEMPLATES.join(', ')}`)
466
+ .action(async (directory, options) => {
467
+ try {
468
+ runInit(directory, options);
469
+ }
470
+ catch (err) {
471
+ (0, output_1.printError)(err.message);
472
+ process.exit(1);
473
+ }
474
+ });
475
+ }
476
+ function registerTemplatesCommand(program) {
477
+ const templates = program
478
+ .command('templates')
479
+ .description('Manage scenario template packs');
480
+ templates
481
+ .command('list')
482
+ .description('List available scenario template packs')
483
+ .action(() => {
484
+ const list = getTemplateList();
485
+ console.log('');
486
+ console.log(chalk_1.default.bold('Available template packs:'));
487
+ console.log('');
488
+ for (const tpl of list) {
489
+ console.log(` ${chalk_1.default.green(tpl.name)}` +
490
+ chalk_1.default.dim(` (${tpl.scenarioCount} scenarios)`));
491
+ console.log(` ${chalk_1.default.dim(tpl.description)}`);
492
+ console.log('');
493
+ }
494
+ console.log(chalk_1.default.dim(' Usage: chanl init --template <name>'));
495
+ console.log(chalk_1.default.dim(' Example: chanl init --template customer-support'));
496
+ console.log('');
497
+ });
498
+ }
499
+ function runInit(directory, options) {
500
+ // Validate template name
501
+ if (options.template && !TEMPLATE_MAP[options.template]) {
502
+ (0, output_1.printError)(`Unknown template "${options.template}". Available: ${AVAILABLE_TEMPLATES.join(', ')}`);
503
+ process.exit(1);
504
+ }
505
+ // Resolve target directory
506
+ const targetDir = directory
507
+ ? path.resolve(process.cwd(), directory)
508
+ : process.cwd();
509
+ const { files } = scaffoldProject(targetDir, options);
510
+ if (files.length === 0) {
511
+ console.log(chalk_1.default.yellow('Project already initialized') +
512
+ ' — all files already exist.');
513
+ return;
514
+ }
515
+ // Print success
516
+ console.log('');
517
+ console.log(chalk_1.default.green('\u2713') + chalk_1.default.bold(' Created chanl-eval project'));
518
+ console.log('');
519
+ // List created files
520
+ const displayDir = directory || '.';
521
+ for (const f of files) {
522
+ console.log(chalk_1.default.dim(` ${displayDir}/${f}`));
523
+ }
524
+ // Next steps
525
+ console.log('');
526
+ console.log(chalk_1.default.bold(' Next steps:'));
527
+ console.log(` 1. Set your API key: Edit .env \u2192 set CHANL_OPENAI_API_KEY=sk-...`);
528
+ console.log(` 2. Start the server: docker compose up -d && cd packages/server && pnpm start:dev`);
529
+ console.log(` 3. Run a scenario: chanl scenarios run scenarios/angry-customer.yaml`);
530
+ console.log('');
531
+ console.log(' Or test a prompt directly:');
532
+ console.log(` 4. Edit agents/my-agent.yaml with your system prompt`);
533
+ console.log(` 5. chanl run angry-customer --agent agents/my-agent.yaml`);
534
+ console.log('');
535
+ console.log(chalk_1.default.dim(' \uD83D\uDCDA Docs: https://github.com/chanl-ai/chanl-eval'));
536
+ // Track analytics
537
+ (0, analytics_1.track)('cli_init', {
538
+ os: process.platform,
539
+ node_version: process.version,
540
+ template: options.template || 'none',
541
+ files_created: files.length,
542
+ directory: directory ? 'custom' : 'cwd',
543
+ });
544
+ }
545
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerLoginCommand(program: Command): void;
3
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyD3D"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerLoginCommand = registerLoginCommand;
7
+ const inquirer_1 = __importDefault(require("inquirer"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const axios_1 = __importDefault(require("axios"));
10
+ const config_1 = require("../config");
11
+ const client_1 = require("../client");
12
+ const output_1 = require("../output");
13
+ function registerLoginCommand(program) {
14
+ program
15
+ .command('login')
16
+ .description('Authenticate with the chanl-eval server')
17
+ .option('-k, --key <apiKey>', 'API key to store')
18
+ .action(async (options) => {
19
+ try {
20
+ let apiKey = options.key;
21
+ if (!apiKey) {
22
+ const answers = await inquirer_1.default.prompt([
23
+ {
24
+ type: 'password',
25
+ name: 'apiKey',
26
+ message: 'Enter your API key:',
27
+ mask: '*',
28
+ validate: (input) => {
29
+ if (!input || input.trim().length === 0) {
30
+ return 'API key is required';
31
+ }
32
+ return true;
33
+ },
34
+ },
35
+ ]);
36
+ apiKey = answers.apiKey;
37
+ }
38
+ if (!apiKey) {
39
+ (0, output_1.printError)('No API key provided');
40
+ process.exit(1);
41
+ }
42
+ // Store the key
43
+ (0, config_1.setConfig)('apiKey', apiKey);
44
+ // Verify the key works by hitting the health endpoint (root path, no /api/v1 prefix)
45
+ const server = (0, config_1.getConfig)('server');
46
+ try {
47
+ const res = await axios_1.default.get(`${server}/health`, { timeout: 3000 });
48
+ const health = res.data;
49
+ (0, output_1.printSuccess)(`Authenticated with ${server} (server v${health.version || 'unknown'})`);
50
+ }
51
+ catch (err) {
52
+ // Key is stored but server might not be available
53
+ console.log(chalk_1.default.yellow('Warning:') +
54
+ ` API key saved, but could not verify with server: ${(0, client_1.formatError)(err)}`);
55
+ console.log(`Server: ${server}`);
56
+ console.log('The key is stored and will be used for future requests.');
57
+ }
58
+ }
59
+ catch (err) {
60
+ (0, output_1.printError)((0, client_1.formatError)(err));
61
+ process.exit(1);
62
+ }
63
+ });
64
+ }
65
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":";;;;;AAQA,oDAyDC;AAhED,wDAAgC;AAChC,kDAA0B;AAC1B,kDAA0B;AAC1B,sCAAiD;AACjD,sCAAwC;AACxC,sCAAqD;AAErD,SAAgB,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;SAChD,MAAM,CAAC,KAAK,EAAE,OAAyB,EAAE,EAAE;QAC1C,IAAI,CAAC;YACH,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;YAEzB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,OAAO,GAAG,MAAM,kBAAQ,CAAC,MAAM,CAAC;oBACpC;wBACE,IAAI,EAAE,UAAU;wBAChB,IAAI,EAAE,QAAQ;wBACd,OAAO,EAAE,qBAAqB;wBAC9B,IAAI,EAAE,GAAG;wBACT,QAAQ,EAAE,CAAC,KAAa,EAAE,EAAE;4BAC1B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gCACxC,OAAO,qBAAqB,CAAC;4BAC/B,CAAC;4BACD,OAAO,IAAI,CAAC;wBACd,CAAC;qBACF;iBACF,CAAC,CAAC;gBACH,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAC1B,CAAC;YAED,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,IAAA,mBAAU,EAAC,qBAAqB,CAAC,CAAC;gBAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,gBAAgB;YAChB,IAAA,kBAAS,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAE5B,qFAAqF;YACrF,MAAM,MAAM,GAAG,IAAA,kBAAS,EAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,GAAG,MAAM,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBACnE,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC;gBACxB,IAAA,qBAAY,EACV,sBAAsB,MAAM,aAAa,MAAM,CAAC,OAAO,IAAI,SAAS,GAAG,CACxE,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,kDAAkD;gBAClD,OAAO,CAAC,GAAG,CACT,eAAK,CAAC,MAAM,CAAC,UAAU,CAAC;oBACtB,qDAAqD,IAAA,oBAAW,EAAC,GAAG,CAAC,EAAE,CAC1E,CAAC;gBACF,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAA,mBAAU,EAAC,IAAA,oBAAW,EAAC,GAAG,CAAC,CAAC,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerPersonasCommand(program: Command): void;
3
+ //# sourceMappingURL=personas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"personas.d.ts","sourceRoot":"","sources":["../../src/commands/personas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyP9D"}