@agentuity/cli 0.0.55 → 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.
- package/dist/cmd/ai/schema/generate.d.ts +3 -0
- package/dist/cmd/ai/schema/generate.d.ts.map +1 -0
- package/dist/cmd/ai/schema/generate.js +50 -0
- package/dist/cmd/ai/schema/generate.js.map +1 -0
- package/dist/cmd/ai/schema/index.d.ts.map +1 -1
- package/dist/cmd/ai/schema/index.js +2 -1
- package/dist/cmd/ai/schema/index.js.map +1 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +101 -81
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/ast.test.js +135 -370
- package/dist/cmd/build/ast.test.js.map +1 -1
- package/dist/cmd/build/bundler.d.ts.map +1 -1
- package/dist/cmd/build/bundler.js +8 -5
- package/dist/cmd/build/bundler.js.map +1 -1
- package/dist/cmd/build/plugin.d.ts.map +1 -1
- package/dist/cmd/build/plugin.js +9 -1
- package/dist/cmd/build/plugin.js.map +1 -1
- package/dist/cmd/cloud/session/get.d.ts.map +1 -1
- package/dist/cmd/cloud/session/get.js +77 -17
- package/dist/cmd/cloud/session/get.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +1 -0
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/config.d.ts +27 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +31 -3
- package/dist/config.js.map +1 -1
- package/dist/types.d.ts +24 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -75
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
- package/src/cmd/ai/schema/generate.ts +64 -0
- package/src/cmd/ai/schema/index.ts +2 -1
- package/src/cmd/build/ast.test.ts +157 -549
- package/src/cmd/build/ast.ts +115 -89
- package/src/cmd/build/bundler.ts +8 -5
- package/src/cmd/build/plugin.ts +10 -1
- package/src/cmd/cloud/session/get.ts +91 -19
- package/src/cmd/project/template-flow.ts +1 -0
- package/src/config.ts +44 -5
- package/src/types.ts +5 -84
|
@@ -1,565 +1,173 @@
|
|
|
1
1
|
import { describe, test, expect } from 'bun:test';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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
|
-
|
|
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
|
});
|