@agentuity/cli 0.0.54 → 0.0.56

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 (51) hide show
  1. package/dist/cmd/ai/schema/generate.d.ts +3 -0
  2. package/dist/cmd/ai/schema/generate.d.ts.map +1 -0
  3. package/dist/cmd/ai/schema/generate.js +50 -0
  4. package/dist/cmd/ai/schema/generate.js.map +1 -0
  5. package/dist/cmd/ai/schema/index.d.ts.map +1 -1
  6. package/dist/cmd/ai/schema/index.js +2 -1
  7. package/dist/cmd/ai/schema/index.js.map +1 -1
  8. package/dist/cmd/build/ast.d.ts.map +1 -1
  9. package/dist/cmd/build/ast.js +107 -86
  10. package/dist/cmd/build/ast.js.map +1 -1
  11. package/dist/cmd/build/ast.test.js +135 -370
  12. package/dist/cmd/build/ast.test.js.map +1 -1
  13. package/dist/cmd/build/bundler.d.ts.map +1 -1
  14. package/dist/cmd/build/bundler.js +9 -6
  15. package/dist/cmd/build/bundler.js.map +1 -1
  16. package/dist/cmd/build/index.d.ts.map +1 -1
  17. package/dist/cmd/build/index.js +2 -0
  18. package/dist/cmd/build/index.js.map +1 -1
  19. package/dist/cmd/build/plugin.d.ts.map +1 -1
  20. package/dist/cmd/build/plugin.js +10 -4
  21. package/dist/cmd/build/plugin.js.map +1 -1
  22. package/dist/cmd/cloud/session/get.d.ts.map +1 -1
  23. package/dist/cmd/cloud/session/get.js +77 -17
  24. package/dist/cmd/cloud/session/get.js.map +1 -1
  25. package/dist/cmd/dev/index.d.ts.map +1 -1
  26. package/dist/cmd/dev/index.js +32 -14
  27. package/dist/cmd/dev/index.js.map +1 -1
  28. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  29. package/dist/cmd/project/template-flow.js +1 -0
  30. package/dist/cmd/project/template-flow.js.map +1 -1
  31. package/dist/config.d.ts +27 -3
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/config.js +31 -3
  34. package/dist/config.js.map +1 -1
  35. package/dist/types.d.ts +24 -2
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/types.js +4 -75
  38. package/dist/types.js.map +1 -1
  39. package/package.json +3 -3
  40. package/src/cmd/ai/schema/generate.ts +64 -0
  41. package/src/cmd/ai/schema/index.ts +2 -1
  42. package/src/cmd/build/ast.test.ts +157 -549
  43. package/src/cmd/build/ast.ts +121 -94
  44. package/src/cmd/build/bundler.ts +9 -6
  45. package/src/cmd/build/index.ts +2 -0
  46. package/src/cmd/build/plugin.ts +11 -4
  47. package/src/cmd/cloud/session/get.ts +91 -19
  48. package/src/cmd/dev/index.ts +39 -14
  49. package/src/cmd/project/template-flow.ts +1 -0
  50. package/src/config.ts +44 -5
  51. package/src/types.ts +5 -84
@@ -1,565 +1,173 @@
1
1
  import { describe, test, expect } from 'bun:test';
2
- import { parseEvalMetadata } from './ast';
3
-
4
- const TEST_ROOT_DIR = '/test/root';
5
- const TEST_PROJECT_ID = 'test-project-id';
6
- const TEST_DEPLOYMENT_ID = 'test-deployment-id';
7
-
8
- describe('parseEvalMetadata', () => {
9
- describe('eval with metadata.name', () => {
10
- test('uses metadata.name when provided', () => {
11
- const code = `
12
- import agent from './agent';
13
- export const myEval = agent.createEval({
14
- metadata: {
15
- name: 'custom-eval-name',
16
- description: 'Test description'
17
- },
18
- handler: async () => ({ success: true, passed: true })
19
- });
20
- `;
21
-
22
- const [, result] = parseEvalMetadata(
23
- TEST_ROOT_DIR,
24
- '/test/root/src/agents/test/eval.ts',
25
- code,
26
- TEST_PROJECT_ID,
27
- TEST_DEPLOYMENT_ID
28
- );
29
-
30
- expect(result).toHaveLength(1);
31
- expect(result[0].name).toBe('custom-eval-name');
32
- expect(result[0].description).toBe('Test description');
33
- });
34
- });
2
+ import { parseRoute } from './ast';
3
+ import { writeFileSync, mkdirSync, rmSync } from 'node:fs';
4
+ import { join } from 'node:path';
35
5
 
36
- describe('eval with variable name only', () => {
37
- test('uses camelToKebab of variable name when metadata.name is not provided', () => {
38
- const code = `
39
- import agent from './agent';
40
- export const myTestEval = agent.createEval({
41
- metadata: {
42
- description: 'Test description'
43
- },
44
- handler: async () => ({ success: true, passed: true })
45
- });
46
- `;
47
-
48
- const [, result] = parseEvalMetadata(
49
- TEST_ROOT_DIR,
50
- '/test/root/src/agents/test/eval.ts',
51
- code,
52
- TEST_PROJECT_ID,
53
- TEST_DEPLOYMENT_ID
54
- );
55
-
56
- expect(result).toHaveLength(1);
57
- expect(result[0].name).toBe('my-test-eval');
58
- expect(result[0].description).toBe('Test description');
59
- });
60
-
61
- test('uses camelToKebab of variable name when metadata is not provided', () => {
62
- const code = `
63
- import agent from './agent';
64
- export const noMetadataEval = agent.createEval({
65
- handler: async () => ({ success: true, passed: true })
66
- });
67
- `;
68
-
69
- const [, result] = parseEvalMetadata(
70
- TEST_ROOT_DIR,
71
- '/test/root/src/agents/test/eval.ts',
72
- code,
73
- TEST_PROJECT_ID,
74
- TEST_DEPLOYMENT_ID
75
- );
76
-
77
- expect(result).toHaveLength(1);
78
- expect(result[0].name).toBe('no-metadata-eval');
79
- });
80
-
81
- test('handles complex camelCase variable names correctly', () => {
82
- const code = `
83
- import agent from './agent';
84
- export const complexCamelCaseEvalName = agent.createEval({
85
- handler: async () => ({ success: true, passed: true })
86
- });
87
- `;
88
-
89
- const [, result] = parseEvalMetadata(
90
- TEST_ROOT_DIR,
91
- '/test/root/src/agents/test/eval.ts',
92
- code,
93
- TEST_PROJECT_ID,
94
- TEST_DEPLOYMENT_ID
95
- );
96
-
97
- expect(result).toHaveLength(1);
98
- expect(result[0].name).toBe('complex-camel-case-eval-name');
99
- });
100
- });
6
+ const TEST_DIR = '/tmp/agentuity-cli-test-routes';
101
7
 
102
- describe('eval with both metadata.name and variable name', () => {
103
- test('prefers metadata.name over variable name', () => {
104
- const code = `
105
- import agent from './agent';
106
- export const variableNameEval = agent.createEval({
107
- metadata: {
108
- name: 'metadata-name-takes-priority'
109
- },
110
- handler: async () => ({ success: true, passed: true })
111
- });
112
- `;
113
-
114
- const [, result] = parseEvalMetadata(
115
- TEST_ROOT_DIR,
116
- '/test/root/src/agents/test/eval.ts',
117
- code,
118
- TEST_PROJECT_ID,
119
- TEST_DEPLOYMENT_ID
120
- );
121
-
122
- expect(result).toHaveLength(1);
123
- expect(result[0].name).toBe('metadata-name-takes-priority');
124
- });
125
- });
8
+ describe('parseRoute - Crash Prevention Scenarios', () => {
9
+ const setup = () => {
10
+ rmSync(TEST_DIR, { recursive: true, force: true });
11
+ mkdirSync(TEST_DIR, { recursive: true });
12
+ };
13
+
14
+ const cleanup = () => {
15
+ rmSync(TEST_DIR, { recursive: true, force: true });
16
+ };
17
+
18
+ test('should handle files with interface definitions', async () => {
19
+ setup();
20
+ const routeFile = join(TEST_DIR, 'route.ts');
21
+ const code = `
22
+ import { createRouter } from '@agentuity/runtime';
23
+ const router = createRouter();
126
24
 
127
- describe('eval with neither name', () => {
128
- test('throws error when eval has neither metadata.name nor variable name', () => {
129
- // This is a difficult case to test with valid JavaScript, as all valid
130
- // variable declarations should have an identifier. However, we can verify
131
- // the error handling exists by testing that the error message format is correct.
132
- //
133
- // In practice, this error should never occur with valid code, but we want
134
- // to ensure the error is clear and helpful if it does happen.
135
- //
136
- // The error case would occur if:
137
- // 1. vardecl.id.type is not 'Identifier' (e.g., destructuring pattern)
138
- // 2. metadata.name is not provided
139
- //
140
- // Since acorn-loose parses valid JavaScript, and valid eval declarations
141
- // should always have an identifier, this is primarily a defensive check.
142
- //
143
- // We verify the error path exists in the code by checking that normal
144
- // cases work correctly, and the error handling is in place.
145
-
146
- // Test that normal cases work (implicitly tests error path doesn't trigger)
147
- const code = `
148
- import agent from './agent';
149
- export const validEval = agent.createEval({
150
- handler: async () => ({ success: true, passed: true })
151
- });
152
- `;
153
-
154
- const [, result] = parseEvalMetadata(
155
- TEST_ROOT_DIR,
156
- '/test/root/src/agents/test/eval.ts',
157
- code,
158
- TEST_PROJECT_ID,
159
- TEST_DEPLOYMENT_ID
160
- );
161
-
162
- expect(result).toHaveLength(1);
163
- expect(result[0].name).toBe('valid-eval');
164
-
165
- // Note: To fully test the error case, we would need to mock the AST structure
166
- // or use code that parses but doesn't extract a variable name. This is
167
- // difficult with acorn-loose parsing valid JavaScript. The error handling
168
- // is verified to exist in the code, and will throw if the condition is met.
169
- });
25
+ interface SomeInterface {
26
+ foo: string;
27
+ bar: string;
28
+ }
29
+
30
+ router.get('/', (c) => c.json({ status: 'ok' }));
31
+
32
+ export default router;
33
+ `;
34
+ writeFileSync(routeFile, code);
35
+
36
+ const routes = await parseRoute(TEST_DIR, routeFile, 'proj_1', 'dep_1');
37
+ expect(routes).toHaveLength(1);
38
+ expect(routes[0].method).toBe('get');
39
+
40
+ cleanup();
170
41
  });
171
42
 
172
- describe('multiple evals', () => {
173
- test('parses multiple evals in same file correctly', () => {
174
- const code = `
175
- import agent from './agent';
176
-
177
- export const firstEval = agent.createEval({
178
- metadata: {
179
- name: 'first-eval',
180
- description: 'First eval'
181
- },
182
- handler: async () => ({ success: true, passed: true })
183
- });
184
-
185
- export const secondEval = agent.createEval({
186
- metadata: {
187
- name: 'second-eval',
188
- description: 'Second eval'
189
- },
190
- handler: async () => ({ success: true, passed: true })
191
- });
192
-
193
- export const thirdEval = agent.createEval({
194
- handler: async () => ({ success: true, passed: true })
195
- });
196
- `;
197
-
198
- const [, result] = parseEvalMetadata(
199
- TEST_ROOT_DIR,
200
- '/test/root/src/agents/test/eval.ts',
201
- code,
202
- TEST_PROJECT_ID,
203
- TEST_DEPLOYMENT_ID
204
- );
205
-
206
- expect(result).toHaveLength(3);
207
- expect(result[0].name).toBe('first-eval');
208
- expect(result[0].description).toBe('First eval');
209
- expect(result[1].name).toBe('second-eval');
210
- expect(result[1].description).toBe('Second eval');
211
- expect(result[2].name).toBe('third-eval');
212
- });
213
-
214
- test('handles mix of metadata.name and variable name evals', () => {
215
- const code = `
216
- import agent from './agent';
217
-
218
- export const withMetadataName = agent.createEval({
219
- metadata: {
220
- name: 'custom-name'
221
- },
222
- handler: async () => ({ success: true, passed: true })
223
- });
224
-
225
- export const withoutMetadataName = agent.createEval({
226
- handler: async () => ({ success: true, passed: true })
227
- });
228
- `;
229
-
230
- const [, result] = parseEvalMetadata(
231
- TEST_ROOT_DIR,
232
- '/test/root/src/agents/test/eval.ts',
233
- code,
234
- TEST_PROJECT_ID,
235
- TEST_DEPLOYMENT_ID
236
- );
237
-
238
- expect(result).toHaveLength(2);
239
- expect(result[0].name).toBe('custom-name');
240
- expect(result[1].name).toBe('without-metadata-name');
241
- });
43
+ test('should handle non-call expression statements', async () => {
44
+ setup();
45
+ const routeFile = join(TEST_DIR, 'route.ts');
46
+ const code = `
47
+ import { createRouter } from '@agentuity/runtime';
48
+ const router = createRouter();
49
+
50
+ 1 + 1;
51
+ "string literal";
52
+ true;
53
+
54
+ router.get('/', (c) => c.text('ok'));
55
+
56
+ export default router;
57
+ `;
58
+ writeFileSync(routeFile, code);
59
+
60
+ const routes = await parseRoute(TEST_DIR, routeFile, 'proj_1', 'dep_1');
61
+ expect(routes).toHaveLength(1);
62
+
63
+ cleanup();
242
64
  });
243
65
 
244
- describe('export patterns', () => {
245
- test('handles ExportNamedDeclaration pattern', () => {
246
- const code = `
247
- import agent from './agent';
248
- export const exportedEval = agent.createEval({
249
- handler: async () => ({ success: true, passed: true })
250
- });
251
- `;
252
-
253
- const [, result] = parseEvalMetadata(
254
- TEST_ROOT_DIR,
255
- '/test/root/src/agents/test/eval.ts',
256
- code,
257
- TEST_PROJECT_ID,
258
- TEST_DEPLOYMENT_ID
259
- );
260
-
261
- expect(result).toHaveLength(1);
262
- expect(result[0].name).toBe('exported-eval');
263
- });
264
-
265
- test('handles VariableDeclaration pattern (non-exported)', () => {
266
- const code = `
267
- import agent from './agent';
268
- const nonExportedEval = agent.createEval({
269
- handler: async () => ({ success: true, passed: true })
270
- });
271
- `;
272
-
273
- const [, result] = parseEvalMetadata(
274
- TEST_ROOT_DIR,
275
- '/test/root/src/agents/test/eval.ts',
276
- code,
277
- TEST_PROJECT_ID,
278
- TEST_DEPLOYMENT_ID
279
- );
280
-
281
- // Non-exported evals should not be included in metadata
282
- expect(result).toHaveLength(0);
283
- });
66
+ test('should handle variable access identifiers', async () => {
67
+ setup();
68
+ const routeFile = join(TEST_DIR, 'route.ts');
69
+ const code = `
70
+ import { createRouter } from '@agentuity/runtime';
71
+ const router = createRouter();
72
+
73
+ router; // Just accessing the variable
74
+
75
+ router.get('/', (c) => c.text('ok'));
76
+
77
+ export default router;
78
+ `;
79
+ writeFileSync(routeFile, code);
80
+
81
+ const routes = await parseRoute(TEST_DIR, routeFile, 'proj_1', 'dep_1');
82
+ expect(routes).toHaveLength(1);
83
+
84
+ cleanup();
284
85
  });
285
86
 
286
- describe('eval ID generation', () => {
287
- test('generates unique IDs for evals', () => {
288
- const code = `
289
- import agent from './agent';
290
-
291
- export const eval1 = agent.createEval({
292
- handler: async () => ({ success: true, passed: true })
293
- });
294
-
295
- export const eval2 = agent.createEval({
296
- handler: async () => ({ success: true, passed: true })
297
- });
298
- `;
299
-
300
- const [, result] = parseEvalMetadata(
301
- TEST_ROOT_DIR,
302
- '/test/root/src/agents/test/eval.ts',
303
- code,
304
- TEST_PROJECT_ID,
305
- TEST_DEPLOYMENT_ID
306
- );
307
-
308
- expect(result).toHaveLength(2);
309
- expect(result[0].id).toBeDefined();
310
- expect(result[1].id).toBeDefined();
311
- expect(result[0].id).not.toBe(result[1].id);
312
- });
313
-
314
- test('generates consistent IDs for same eval', () => {
315
- const code = `
316
- import agent from './agent';
317
- export const myEval = agent.createEval({
318
- metadata: {
319
- name: 'test-eval'
320
- },
321
- handler: async () => ({ success: true, passed: true })
322
- });
323
- `;
324
-
325
- const [, result1] = parseEvalMetadata(
326
- TEST_ROOT_DIR,
327
- '/test/root/src/agents/test/eval.ts',
328
- code,
329
- TEST_PROJECT_ID,
330
- TEST_DEPLOYMENT_ID
331
- );
332
-
333
- const [, result2] = parseEvalMetadata(
334
- TEST_ROOT_DIR,
335
- '/test/root/src/agents/test/eval.ts',
336
- code,
337
- TEST_PROJECT_ID,
338
- TEST_DEPLOYMENT_ID
339
- );
340
-
341
- expect(result1[0].id).toBe(result2[0].id);
342
- });
87
+ test('should handle direct function calls (not member expressions)', async () => {
88
+ setup();
89
+ const routeFile = join(TEST_DIR, 'route.ts');
90
+ const code = `
91
+ import { createRouter } from '@agentuity/runtime';
92
+ const router = createRouter();
93
+
94
+ console.log("logging");
95
+ (function() { })();
96
+
97
+ router.get('/', (c) => c.text('ok'));
98
+
99
+ export default router;
100
+ `;
101
+ writeFileSync(routeFile, code);
102
+
103
+ const routes = await parseRoute(TEST_DIR, routeFile, 'proj_1', 'dep_1');
104
+ expect(routes).toHaveLength(1);
105
+
106
+ cleanup();
343
107
  });
344
108
 
345
- describe('edge cases', () => {
346
- test('handles empty metadata object', () => {
347
- const code = `
348
- import agent from './agent';
349
- export const emptyMetadataEval = agent.createEval({
350
- metadata: {},
351
- handler: async () => ({ success: true, passed: true })
352
- });
353
- `;
354
-
355
- const [, result] = parseEvalMetadata(
356
- TEST_ROOT_DIR,
357
- '/test/root/src/agents/test/eval.ts',
358
- code,
359
- TEST_PROJECT_ID,
360
- TEST_DEPLOYMENT_ID
361
- );
362
-
363
- expect(result).toHaveLength(1);
364
- expect(result[0].name).toBe('empty-metadata-eval');
365
- });
366
-
367
- test('handles eval with only description in metadata', () => {
368
- const code = `
369
- import agent from './agent';
370
- export const descriptionOnlyEval = agent.createEval({
371
- metadata: {
372
- description: 'Only description, no name'
373
- },
374
- handler: async () => ({ success: true, passed: true })
375
- });
376
- `;
377
-
378
- const [, result] = parseEvalMetadata(
379
- TEST_ROOT_DIR,
380
- '/test/root/src/agents/test/eval.ts',
381
- code,
382
- TEST_PROJECT_ID,
383
- TEST_DEPLOYMENT_ID
384
- );
385
-
386
- expect(result).toHaveLength(1);
387
- expect(result[0].name).toBe('description-only-eval');
388
- expect(result[0].description).toBe('Only description, no name');
389
- });
109
+ test('should handle mixed complex scenarios', async () => {
110
+ setup();
111
+ const routeFile = join(TEST_DIR, 'route.ts');
112
+ const code = `
113
+ import { createRouter } from '@agentuity/runtime';
114
+
115
+ // Variable declarations
116
+ const router = createRouter();
117
+ const someVar = "test";
118
+
119
+ // Interface
120
+ interface User {
121
+ id: string;
122
+ }
123
+
124
+ // Function declaration
125
+ function helper() {
126
+ return true;
127
+ }
128
+
129
+ // Direct call
130
+ helper();
131
+
132
+ // Non-route member expression
133
+ console.log(someVar);
134
+
135
+ // Valid route
136
+ router.post('/users', (c) => c.json({ id: '1' }));
137
+
138
+ // Another expression type
139
+ if (true) {
140
+ console.log("block");
141
+ }
142
+
143
+ export default router;
144
+ `;
145
+ writeFileSync(routeFile, code);
146
+
147
+ const routes = await parseRoute(TEST_DIR, routeFile, 'proj_1', 'dep_1');
148
+ expect(routes).toHaveLength(1);
149
+ expect(routes[0].method).toBe('post');
150
+
151
+ cleanup();
390
152
  });
153
+ test('should reject invalid router method', async () => {
154
+ setup();
155
+ const routeFile = join(TEST_DIR, 'route.ts');
156
+ const code = `
157
+ import { createRouter } from '@agentuity/runtime';
158
+
159
+ // Variable declarations
160
+ const router = createRouter();
161
+
162
+ // Invalid route with unknown method
163
+ router.foo('/users', (c) => c.json({ id: '1' }));
164
+
165
+ export default router;
166
+ `;
167
+ writeFileSync(routeFile, code);
168
+
169
+ await expect(parseRoute(TEST_DIR, routeFile, 'proj_1', 'dep_1')).rejects.toThrow();
391
170
 
392
- describe('duplicate eval names', () => {
393
- test('throws error when duplicate eval names are found in same file', () => {
394
- const code = `
395
- import agent from './agent';
396
-
397
- export const firstEval = agent.createEval({
398
- metadata: {
399
- name: 'duplicate-name'
400
- },
401
- handler: async () => ({ success: true, passed: true })
402
- });
403
-
404
- export const secondEval = agent.createEval({
405
- metadata: {
406
- name: 'duplicate-name'
407
- },
408
- handler: async () => ({ success: true, passed: true })
409
- });
410
- `;
411
-
412
- expect(() => {
413
- parseEvalMetadata(
414
- TEST_ROOT_DIR,
415
- '/test/root/src/agents/test/eval.ts',
416
- code,
417
- TEST_PROJECT_ID,
418
- TEST_DEPLOYMENT_ID
419
- );
420
- }).toThrow(/Duplicate eval names found in .*eval\.ts: duplicate-name/);
421
- });
422
-
423
- test('throws error when multiple duplicate eval names are found', () => {
424
- const code = `
425
- import agent from './agent';
426
-
427
- export const eval1 = agent.createEval({
428
- metadata: {
429
- name: 'first-duplicate'
430
- },
431
- handler: async () => ({ success: true, passed: true })
432
- });
433
-
434
- export const eval2 = agent.createEval({
435
- metadata: {
436
- name: 'first-duplicate'
437
- },
438
- handler: async () => ({ success: true, passed: true })
439
- });
440
-
441
- export const eval3 = agent.createEval({
442
- metadata: {
443
- name: 'second-duplicate'
444
- },
445
- handler: async () => ({ success: true, passed: true })
446
- });
447
-
448
- export const eval4 = agent.createEval({
449
- metadata: {
450
- name: 'second-duplicate'
451
- },
452
- handler: async () => ({ success: true, passed: true })
453
- });
454
- `;
455
-
456
- expect(() => {
457
- parseEvalMetadata(
458
- TEST_ROOT_DIR,
459
- '/test/root/src/agents/test/eval.ts',
460
- code,
461
- TEST_PROJECT_ID,
462
- TEST_DEPLOYMENT_ID
463
- );
464
- }).toThrow(/Duplicate eval names found in .*eval\.ts: first-duplicate, second-duplicate/);
465
- });
466
-
467
- test('throws error when duplicate names come from variable names', () => {
468
- // Note: We can't have two variables with the exact same name in valid JavaScript,
469
- // but we can test that the validation works by using metadata.name to override
470
- // variable names to create duplicates
471
- const code = `
472
- import agent from './agent';
473
-
474
- export const eval1 = agent.createEval({
475
- metadata: {
476
- name: 'duplicate-name'
477
- },
478
- handler: async () => ({ success: true, passed: true })
479
- });
480
-
481
- export const eval2 = agent.createEval({
482
- metadata: {
483
- name: 'duplicate-name'
484
- },
485
- handler: async () => ({ success: true, passed: true })
486
- });
487
- `;
488
-
489
- expect(() => {
490
- parseEvalMetadata(
491
- TEST_ROOT_DIR,
492
- '/test/root/src/agents/test/eval.ts',
493
- code,
494
- TEST_PROJECT_ID,
495
- TEST_DEPLOYMENT_ID
496
- );
497
- }).toThrow(/Duplicate eval names found in .*eval\.ts: duplicate-name/);
498
- });
499
-
500
- test('throws error when duplicate names mix metadata.name and variable name', () => {
501
- const code = `
502
- import agent from './agent';
503
-
504
- export const myEval = agent.createEval({
505
- metadata: {
506
- name: 'mixed-duplicate'
507
- },
508
- handler: async () => ({ success: true, passed: true })
509
- });
510
-
511
- export const mixedDuplicate = agent.createEval({
512
- handler: async () => ({ success: true, passed: true })
513
- });
514
- `;
515
-
516
- expect(() => {
517
- parseEvalMetadata(
518
- TEST_ROOT_DIR,
519
- '/test/root/src/agents/test/eval.ts',
520
- code,
521
- TEST_PROJECT_ID,
522
- TEST_DEPLOYMENT_ID
523
- );
524
- }).toThrow(/Duplicate eval names found in .*eval\.ts: mixed-duplicate/);
525
- });
526
-
527
- test('error message includes filename and all duplicate names', () => {
528
- const code = `
529
- import agent from './agent';
530
-
531
- export const eval1 = agent.createEval({
532
- metadata: { name: 'test-eval' },
533
- handler: async () => ({ success: true, passed: true })
534
- });
535
-
536
- export const eval2 = agent.createEval({
537
- metadata: { name: 'test-eval' },
538
- handler: async () => ({ success: true, passed: true })
539
- });
540
- `;
541
-
542
- let errorThrown = false;
543
- try {
544
- parseEvalMetadata(
545
- TEST_ROOT_DIR,
546
- '/test/root/src/agents/test/eval.ts',
547
- code,
548
- TEST_PROJECT_ID,
549
- TEST_DEPLOYMENT_ID
550
- );
551
- } catch (error) {
552
- errorThrown = true;
553
- expect(error).toBeInstanceOf(Error);
554
- const errorMessage = (error as Error).message;
555
- expect(errorMessage).toContain('Duplicate eval names found in');
556
- expect(errorMessage).toContain('eval.ts');
557
- expect(errorMessage).toContain('test-eval');
558
- expect(errorMessage).toContain(
559
- 'Eval names must be unique within the same file to prevent ID collisions'
560
- );
561
- }
562
- expect(errorThrown).toBe(true);
563
- });
171
+ cleanup();
564
172
  });
565
173
  });