@agentuity/cli 0.0.69 → 0.0.71
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/AGENTS.md +1 -1
- package/README.md +1 -1
- package/dist/cmd/ai/capabilities/show.d.ts.map +1 -1
- package/dist/cmd/ai/capabilities/show.js +0 -13
- package/dist/cmd/ai/capabilities/show.js.map +1 -1
- package/dist/cmd/ai/prompt/agent.js +1 -1
- package/dist/cmd/ai/prompt/api.js +1 -1
- package/dist/cmd/build/ast.d.ts +1 -2
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +261 -260
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/bundler.d.ts +4 -1
- package/dist/cmd/build/bundler.d.ts.map +1 -1
- package/dist/cmd/build/bundler.js +89 -6
- package/dist/cmd/build/bundler.js.map +1 -1
- package/dist/cmd/build/index.d.ts.map +1 -1
- package/dist/cmd/build/index.js +2 -1
- package/dist/cmd/build/index.js.map +1 -1
- package/dist/cmd/build/plugin.d.ts.map +1 -1
- package/dist/cmd/build/plugin.js +152 -414
- package/dist/cmd/build/plugin.js.map +1 -1
- package/dist/cmd/build/route-registry.d.ts +36 -0
- package/dist/cmd/build/route-registry.d.ts.map +1 -0
- package/dist/cmd/build/route-registry.js +151 -0
- package/dist/cmd/build/route-registry.js.map +1 -0
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +2 -0
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/index.d.ts.map +1 -1
- package/dist/cmd/cloud/index.js +0 -2
- package/dist/cmd/cloud/index.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +4 -3
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/dev/sync.d.ts.map +1 -1
- package/dist/cmd/dev/sync.js +0 -15
- package/dist/cmd/dev/sync.js.map +1 -1
- package/dist/cmd/dev/templates.d.ts.map +1 -1
- package/dist/cmd/dev/templates.js +11 -35
- package/dist/cmd/dev/templates.js.map +1 -1
- package/dist/cmd/profile/create.d.ts.map +1 -1
- package/dist/cmd/profile/create.js +0 -1
- package/dist/cmd/profile/create.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +64 -53
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -3
- package/dist/config.js.map +1 -1
- package/dist/env-util.d.ts.map +1 -1
- package/dist/env-util.js +0 -3
- package/dist/env-util.js.map +1 -1
- package/dist/tui/box.d.ts +19 -0
- package/dist/tui/box.d.ts.map +1 -0
- package/dist/tui/box.js +160 -0
- package/dist/tui/box.js.map +1 -0
- package/dist/tui/colors.d.ts +20 -0
- package/dist/tui/colors.d.ts.map +1 -0
- package/dist/tui/colors.js +52 -0
- package/dist/tui/colors.js.map +1 -0
- package/dist/tui/group.d.ts +25 -0
- package/dist/tui/group.d.ts.map +1 -0
- package/dist/tui/group.js +32 -0
- package/dist/tui/group.js.map +1 -0
- package/dist/tui/prompt.d.ts +65 -0
- package/dist/tui/prompt.d.ts.map +1 -0
- package/dist/tui/prompt.js +377 -0
- package/dist/tui/prompt.js.map +1 -0
- package/dist/tui/symbols.d.ts +32 -0
- package/dist/tui/symbols.d.ts.map +1 -0
- package/dist/tui/symbols.js +52 -0
- package/dist/tui/symbols.js.map +1 -0
- package/dist/tui.d.ts +6 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +6 -0
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +0 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
- package/src/cmd/ai/capabilities/show.ts +0 -13
- package/src/cmd/ai/prompt/agent.ts +1 -1
- package/src/cmd/ai/prompt/api.ts +1 -1
- package/src/cmd/build/ast.ts +364 -334
- package/src/cmd/build/bundler.ts +123 -9
- package/src/cmd/build/index.ts +2 -1
- package/src/cmd/build/plugin.ts +171 -493
- package/src/cmd/build/route-registry.ts +198 -0
- package/src/cmd/cloud/deploy.ts +2 -0
- package/src/cmd/cloud/index.ts +0 -2
- package/src/cmd/dev/index.ts +4 -3
- package/src/cmd/dev/sync.ts +0 -28
- package/src/cmd/dev/templates.ts +11 -35
- package/src/cmd/profile/create.ts +0 -1
- package/src/cmd/project/template-flow.ts +77 -57
- package/src/config.ts +0 -3
- package/src/env-util.ts +0 -3
- package/src/tui/box.ts +202 -0
- package/src/tui/colors.ts +55 -0
- package/src/tui/group.ts +56 -0
- package/src/tui/prompt.ts +506 -0
- package/src/tui/symbols.ts +64 -0
- package/src/tui.ts +14 -0
- package/src/types.ts +0 -1
- package/dist/cmd/cloud/objectstore/delete-bucket.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/delete-bucket.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/delete-bucket.js +0 -72
- package/dist/cmd/cloud/objectstore/delete-bucket.js.map +0 -1
- package/dist/cmd/cloud/objectstore/delete.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/delete.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/delete.js +0 -65
- package/dist/cmd/cloud/objectstore/delete.js.map +0 -1
- package/dist/cmd/cloud/objectstore/get.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/get.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/get.js +0 -75
- package/dist/cmd/cloud/objectstore/get.js.map +0 -1
- package/dist/cmd/cloud/objectstore/index.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/index.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/index.js +0 -36
- package/dist/cmd/cloud/objectstore/index.js.map +0 -1
- package/dist/cmd/cloud/objectstore/list-buckets.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/list-buckets.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/list-buckets.js +0 -46
- package/dist/cmd/cloud/objectstore/list-buckets.js.map +0 -1
- package/dist/cmd/cloud/objectstore/list-keys.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/list-keys.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/list-keys.js +0 -58
- package/dist/cmd/cloud/objectstore/list-keys.js.map +0 -1
- package/dist/cmd/cloud/objectstore/put.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/put.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/put.js +0 -66
- package/dist/cmd/cloud/objectstore/put.js.map +0 -1
- package/dist/cmd/cloud/objectstore/repl.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/repl.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/repl.js +0 -224
- package/dist/cmd/cloud/objectstore/repl.js.map +0 -1
- package/dist/cmd/cloud/objectstore/url.d.ts +0 -3
- package/dist/cmd/cloud/objectstore/url.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/url.js +0 -64
- package/dist/cmd/cloud/objectstore/url.js.map +0 -1
- package/dist/cmd/cloud/objectstore/util.d.ts +0 -11
- package/dist/cmd/cloud/objectstore/util.d.ts.map +0 -1
- package/dist/cmd/cloud/objectstore/util.js +0 -18
- package/dist/cmd/cloud/objectstore/util.js.map +0 -1
- package/src/cmd/build/ast.test.ts +0 -418
- package/src/cmd/build/fix-duplicate-exports.test.ts +0 -387
- package/src/cmd/cloud/objectstore/delete-bucket.ts +0 -77
- package/src/cmd/cloud/objectstore/delete.ts +0 -67
- package/src/cmd/cloud/objectstore/get.ts +0 -77
- package/src/cmd/cloud/objectstore/index.ts +0 -36
- package/src/cmd/cloud/objectstore/list-buckets.ts +0 -51
- package/src/cmd/cloud/objectstore/list-keys.ts +0 -63
- package/src/cmd/cloud/objectstore/put.ts +0 -74
- package/src/cmd/cloud/objectstore/repl.ts +0 -239
- package/src/cmd/cloud/objectstore/url.ts +0 -67
- package/src/cmd/cloud/objectstore/util.ts +0 -29
- package/src/crypto/box.test.ts +0 -431
- package/src/env-util.test.ts +0 -194
package/src/cmd/build/ast.ts
CHANGED
|
@@ -174,6 +174,14 @@ function generateStableEvalId(projectId: string, agentId: string, name: string):
|
|
|
174
174
|
return `evalid_${hashSHA1(projectId, agentId, name)}`.substring(0, 64);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Type guard to check if an AST node is an ObjectExpression
|
|
179
|
+
*/
|
|
180
|
+
function isObjectExpression(node: unknown): node is ASTObjectExpression {
|
|
181
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
182
|
+
return typeof node === 'object' && node !== null && (node as any).type === 'ObjectExpression';
|
|
183
|
+
}
|
|
184
|
+
|
|
177
185
|
/**
|
|
178
186
|
* Extract schema code from createAgent call arguments
|
|
179
187
|
* Returns input and output schema code as strings
|
|
@@ -227,7 +235,6 @@ const MetadataError = StructuredError('MetatadataNameMissingError')<{
|
|
|
227
235
|
function augmentAgentMetadataNode(
|
|
228
236
|
projectId: string,
|
|
229
237
|
id: string,
|
|
230
|
-
identifier: string,
|
|
231
238
|
rel: string,
|
|
232
239
|
version: string,
|
|
233
240
|
ast: AcornParseResultType,
|
|
@@ -246,19 +253,10 @@ function augmentAgentMetadataNode(
|
|
|
246
253
|
});
|
|
247
254
|
}
|
|
248
255
|
const name = metadata.get('name')!;
|
|
249
|
-
if (metadata.has('identifier') && identifier !== metadata.get('identifier')) {
|
|
250
|
-
const location = ast.loc?.start?.line ? ` on line ${ast.loc.start.line}` : '';
|
|
251
|
-
throw new MetadataError({
|
|
252
|
-
filename,
|
|
253
|
-
line: ast.loc?.start?.line,
|
|
254
|
-
message: `metadata.identifier (${metadata.get('identifier')}) in ${filename}${location} is mismatched (${name}). This is an internal error.`,
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
256
|
const descriptionNode = propvalue.properties.find((x) => x.key.name === 'description')?.value;
|
|
258
257
|
const description = descriptionNode ? (descriptionNode as ASTLiteral).value : '';
|
|
259
258
|
const agentId = generateStableAgentId(projectId, name);
|
|
260
259
|
metadata.set('version', version);
|
|
261
|
-
metadata.set('identifier', identifier);
|
|
262
260
|
metadata.set('filename', rel);
|
|
263
261
|
metadata.set('id', id);
|
|
264
262
|
metadata.set('agentId', agentId);
|
|
@@ -273,7 +271,6 @@ function augmentAgentMetadataNode(
|
|
|
273
271
|
createObjectPropertyNode('id', id),
|
|
274
272
|
createObjectPropertyNode('agentId', agentId),
|
|
275
273
|
createObjectPropertyNode('version', version),
|
|
276
|
-
createObjectPropertyNode('identifier', name),
|
|
277
274
|
createObjectPropertyNode('filename', rel),
|
|
278
275
|
createObjectPropertyNode('description', description)
|
|
279
276
|
);
|
|
@@ -297,15 +294,25 @@ function createAgentMetadataNode(
|
|
|
297
294
|
version: string,
|
|
298
295
|
ast: AcornParseResultType,
|
|
299
296
|
callargexp: ASTObjectExpression,
|
|
300
|
-
_filename: string
|
|
297
|
+
_filename: string,
|
|
298
|
+
projectId: string,
|
|
299
|
+
inputSchemaCode?: string,
|
|
300
|
+
outputSchemaCode?: string
|
|
301
301
|
): [string, Map<string, string>] {
|
|
302
302
|
const newmetadata = createNewMetadataNode();
|
|
303
|
+
const agentId = generateStableAgentId(projectId, name);
|
|
303
304
|
const md = new Map<string, string>();
|
|
304
305
|
md.set('id', id);
|
|
306
|
+
md.set('agentId', agentId);
|
|
305
307
|
md.set('version', version);
|
|
306
308
|
md.set('name', name);
|
|
307
|
-
md.set('identifier', name);
|
|
308
309
|
md.set('filename', rel);
|
|
310
|
+
if (inputSchemaCode) {
|
|
311
|
+
md.set('inputSchemaCode', inputSchemaCode);
|
|
312
|
+
}
|
|
313
|
+
if (outputSchemaCode) {
|
|
314
|
+
md.set('outputSchemaCode', outputSchemaCode);
|
|
315
|
+
}
|
|
309
316
|
for (const [key, value] of md) {
|
|
310
317
|
newmetadata.value.properties.push(createObjectPropertyNode(key, value));
|
|
311
318
|
}
|
|
@@ -317,132 +324,6 @@ function createAgentMetadataNode(
|
|
|
317
324
|
return [newsource, md];
|
|
318
325
|
}
|
|
319
326
|
|
|
320
|
-
function camelToKebab(str: string): string {
|
|
321
|
-
return str
|
|
322
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
323
|
-
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
|
|
324
|
-
.toLowerCase();
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
function setLiteralValue(literal: ASTLiteral, value: string) {
|
|
328
|
-
literal.value = value;
|
|
329
|
-
if (literal.raw !== undefined) {
|
|
330
|
-
literal.raw = JSON.stringify(value);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
function augmentEvalMetadataNode(
|
|
335
|
-
projectId: string,
|
|
336
|
-
agentId: string,
|
|
337
|
-
id: string,
|
|
338
|
-
name: string,
|
|
339
|
-
rel: string,
|
|
340
|
-
version: string,
|
|
341
|
-
_ast: AcornParseResultType,
|
|
342
|
-
metadataObj: ASTObjectExpression,
|
|
343
|
-
_filename: string
|
|
344
|
-
): void {
|
|
345
|
-
const metadata = parseObjectExpressionToMap(metadataObj);
|
|
346
|
-
// Name can come from metadata.name or variable name (already resolved in caller)
|
|
347
|
-
// If metadata doesn't have name, we'll add it from the resolved name
|
|
348
|
-
if (!metadata.has('name')) {
|
|
349
|
-
metadataObj.properties.push(createObjectPropertyNode('name', name));
|
|
350
|
-
}
|
|
351
|
-
const descriptionNode = metadataObj.properties.find((x) => x.key.name === 'description')?.value;
|
|
352
|
-
const description = descriptionNode ? (descriptionNode as ASTLiteral).value : '';
|
|
353
|
-
const effectiveAgentId = agentId || '';
|
|
354
|
-
const _evalId = getEvalId(projectId, effectiveAgentId, rel, name, version); // Deployment-specific ID (not used, kept for potential future use)
|
|
355
|
-
const stableEvalId = generateStableEvalId(projectId, effectiveAgentId, name);
|
|
356
|
-
|
|
357
|
-
// Check if id, version, identifier, filename, evalId already exist
|
|
358
|
-
const existingKeys = new Set<string>();
|
|
359
|
-
for (const prop of metadataObj.properties) {
|
|
360
|
-
if (prop.key.type === 'Identifier') {
|
|
361
|
-
existingKeys.add(prop.key.name);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Add or update metadata properties
|
|
366
|
-
if (!existingKeys.has('id')) {
|
|
367
|
-
metadataObj.properties.push(createObjectPropertyNode('id', id));
|
|
368
|
-
} else {
|
|
369
|
-
// Update existing id
|
|
370
|
-
for (const prop of metadataObj.properties) {
|
|
371
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'id') {
|
|
372
|
-
if (prop.value.type === 'Literal') {
|
|
373
|
-
setLiteralValue(prop.value as ASTLiteral, id);
|
|
374
|
-
}
|
|
375
|
-
break;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
if (!existingKeys.has('version')) {
|
|
381
|
-
metadataObj.properties.push(createObjectPropertyNode('version', version));
|
|
382
|
-
} else {
|
|
383
|
-
for (const prop of metadataObj.properties) {
|
|
384
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'version') {
|
|
385
|
-
if (prop.value.type === 'Literal') {
|
|
386
|
-
setLiteralValue(prop.value as ASTLiteral, version);
|
|
387
|
-
}
|
|
388
|
-
break;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
if (!existingKeys.has('identifier')) {
|
|
394
|
-
metadataObj.properties.push(createObjectPropertyNode('identifier', name));
|
|
395
|
-
} else {
|
|
396
|
-
for (const prop of metadataObj.properties) {
|
|
397
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'identifier') {
|
|
398
|
-
if (prop.value.type === 'Literal') {
|
|
399
|
-
setLiteralValue(prop.value as ASTLiteral, name);
|
|
400
|
-
}
|
|
401
|
-
break;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
if (!existingKeys.has('filename')) {
|
|
407
|
-
metadataObj.properties.push(createObjectPropertyNode('filename', rel));
|
|
408
|
-
} else {
|
|
409
|
-
for (const prop of metadataObj.properties) {
|
|
410
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'filename') {
|
|
411
|
-
if (prop.value.type === 'Literal') {
|
|
412
|
-
setLiteralValue(prop.value as ASTLiteral, rel);
|
|
413
|
-
}
|
|
414
|
-
break;
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
if (!existingKeys.has('evalId')) {
|
|
420
|
-
metadataObj.properties.push(createObjectPropertyNode('evalId', stableEvalId));
|
|
421
|
-
} else {
|
|
422
|
-
for (const prop of metadataObj.properties) {
|
|
423
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'evalId') {
|
|
424
|
-
if (prop.value.type === 'Literal') {
|
|
425
|
-
setLiteralValue(prop.value as ASTLiteral, stableEvalId);
|
|
426
|
-
}
|
|
427
|
-
break;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
if (!existingKeys.has('description')) {
|
|
433
|
-
metadataObj.properties.push(createObjectPropertyNode('description', description));
|
|
434
|
-
} else {
|
|
435
|
-
for (const prop of metadataObj.properties) {
|
|
436
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'description') {
|
|
437
|
-
if (prop.value.type === 'Literal') {
|
|
438
|
-
setLiteralValue(prop.value as ASTLiteral, description);
|
|
439
|
-
}
|
|
440
|
-
break;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
327
|
const DuplicateNameError = StructuredError('DuplicateNameError')<{ filename: string }>();
|
|
447
328
|
|
|
448
329
|
export function parseEvalMetadata(
|
|
@@ -458,7 +339,6 @@ export function parseEvalMetadata(
|
|
|
458
339
|
filename: string;
|
|
459
340
|
id: string;
|
|
460
341
|
version: string;
|
|
461
|
-
identifier: string;
|
|
462
342
|
name: string;
|
|
463
343
|
evalId: string;
|
|
464
344
|
description?: string;
|
|
@@ -483,7 +363,6 @@ export function parseEvalMetadata(
|
|
|
483
363
|
filename: string;
|
|
484
364
|
id: string;
|
|
485
365
|
version: string;
|
|
486
|
-
identifier: string;
|
|
487
366
|
name: string;
|
|
488
367
|
evalId: string;
|
|
489
368
|
description?: string;
|
|
@@ -520,110 +399,73 @@ export function parseEvalMetadata(
|
|
|
520
399
|
property.name === 'createEval'
|
|
521
400
|
) {
|
|
522
401
|
// Found agent.createEval() call
|
|
523
|
-
|
|
402
|
+
// New signature: agent.createEval(name, { description?, handler })
|
|
403
|
+
if (call.arguments.length >= 2) {
|
|
524
404
|
const firstArg = call.arguments[0] as ASTNode;
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
405
|
+
const secondArg = call.arguments[1] as ASTNode;
|
|
406
|
+
|
|
407
|
+
let evalName: string | undefined;
|
|
408
|
+
let evalDescription: string | undefined;
|
|
409
|
+
let configObj: ASTObjectExpression | undefined;
|
|
410
|
+
|
|
411
|
+
// First argument should be a string literal (the name)
|
|
412
|
+
if (
|
|
413
|
+
firstArg.type === 'Literal' &&
|
|
414
|
+
typeof (firstArg as ASTLiteral).value === 'string'
|
|
415
|
+
) {
|
|
416
|
+
evalName = (firstArg as ASTLiteral).value;
|
|
417
|
+
} else {
|
|
418
|
+
throw new MetadataError({
|
|
419
|
+
filename,
|
|
420
|
+
line: body.loc?.start?.line,
|
|
421
|
+
message:
|
|
422
|
+
'agent.createEval() first argument must be a string literal name.',
|
|
423
|
+
});
|
|
424
|
+
}
|
|
536
425
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
} else if (
|
|
550
|
-
metaProp.key.name === 'description' &&
|
|
551
|
-
metaProp.value.type === 'Literal'
|
|
552
|
-
) {
|
|
553
|
-
evalDescription = (metaProp.value as ASTLiteral).value;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
}
|
|
426
|
+
// Second argument should be the config object
|
|
427
|
+
if (secondArg.type === 'ObjectExpression') {
|
|
428
|
+
configObj = secondArg as ASTObjectExpression;
|
|
429
|
+
|
|
430
|
+
// Extract description from config object
|
|
431
|
+
for (const prop of configObj.properties) {
|
|
432
|
+
if (
|
|
433
|
+
prop.key.type === 'Identifier' &&
|
|
434
|
+
prop.key.name === 'description'
|
|
435
|
+
) {
|
|
436
|
+
if (prop.value.type === 'Literal') {
|
|
437
|
+
evalDescription = (prop.value as ASTLiteral).value;
|
|
557
438
|
}
|
|
558
439
|
}
|
|
559
440
|
}
|
|
441
|
+
}
|
|
560
442
|
|
|
561
|
-
|
|
562
|
-
// Throw error if neither is available (should never happen)
|
|
563
|
-
let finalName: string;
|
|
564
|
-
if (evalName) {
|
|
565
|
-
finalName = evalName;
|
|
566
|
-
} else if (variableName) {
|
|
567
|
-
finalName = camelToKebab(variableName);
|
|
568
|
-
} else {
|
|
569
|
-
throw new MetadataError({
|
|
570
|
-
filename,
|
|
571
|
-
line: body.loc?.start?.line,
|
|
572
|
-
message:
|
|
573
|
-
'Eval is missing a name. Please provide metadata.name or use a named export.',
|
|
574
|
-
});
|
|
575
|
-
}
|
|
443
|
+
const finalName = evalName;
|
|
576
444
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
projectId,
|
|
582
|
-
deploymentId,
|
|
583
|
-
rel,
|
|
584
|
-
finalName,
|
|
585
|
-
version
|
|
586
|
-
);
|
|
445
|
+
logger.trace(
|
|
446
|
+
`Found eval: ${finalName}${evalDescription ? ` - ${evalDescription}` : ''}`
|
|
447
|
+
);
|
|
448
|
+
const evalId = getEvalId(projectId, deploymentId, rel, finalName, version);
|
|
587
449
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
evalId,
|
|
596
|
-
finalName,
|
|
597
|
-
rel,
|
|
598
|
-
version,
|
|
599
|
-
ast,
|
|
600
|
-
metadataObj,
|
|
601
|
-
filename
|
|
602
|
-
);
|
|
603
|
-
// Extract evalId from metadata after augmentation
|
|
604
|
-
const metadata = parseObjectExpressionToMap(metadataObj);
|
|
605
|
-
stableEvalId =
|
|
606
|
-
metadata.get('evalId') ||
|
|
607
|
-
generateStableEvalId(projectId, effectiveAgentId, finalName);
|
|
608
|
-
} else {
|
|
609
|
-
// If no metadata object, generate stable evalId
|
|
610
|
-
stableEvalId = generateStableEvalId(
|
|
611
|
-
projectId,
|
|
612
|
-
effectiveAgentId,
|
|
613
|
-
finalName
|
|
614
|
-
);
|
|
615
|
-
}
|
|
450
|
+
// Generate stable evalId
|
|
451
|
+
const effectiveAgentId = agentId || '';
|
|
452
|
+
const stableEvalId = generateStableEvalId(
|
|
453
|
+
projectId,
|
|
454
|
+
effectiveAgentId,
|
|
455
|
+
finalName
|
|
456
|
+
);
|
|
616
457
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
458
|
+
// Note: We no longer inject metadata into the AST since there's no metadata object
|
|
459
|
+
// The runtime will generate IDs from the name parameter
|
|
460
|
+
|
|
461
|
+
evals.push({
|
|
462
|
+
filename: rel,
|
|
463
|
+
id: evalId,
|
|
464
|
+
version,
|
|
465
|
+
name: finalName,
|
|
466
|
+
evalId: stableEvalId,
|
|
467
|
+
description: evalDescription,
|
|
468
|
+
});
|
|
627
469
|
}
|
|
628
470
|
}
|
|
629
471
|
}
|
|
@@ -662,7 +504,6 @@ export function parseEvalMetadata(
|
|
|
662
504
|
}
|
|
663
505
|
|
|
664
506
|
const InvalidExportError = StructuredError('InvalidExportError')<{ filename: string }>();
|
|
665
|
-
const InvalidCreateAgentError = StructuredError('InvalidCreateAgentError')<{ filename: string }>();
|
|
666
507
|
|
|
667
508
|
export async function parseAgentMetadata(
|
|
668
509
|
rootDir: string,
|
|
@@ -670,7 +511,12 @@ export async function parseAgentMetadata(
|
|
|
670
511
|
contents: string,
|
|
671
512
|
projectId: string,
|
|
672
513
|
deploymentId: string
|
|
673
|
-
): Promise<[string, Map<string, string>]> {
|
|
514
|
+
): Promise<[string, Map<string, string>] | undefined> {
|
|
515
|
+
// Quick string search optimization - skip AST parsing if no createAgent call
|
|
516
|
+
if (!contents.includes('createAgent')) {
|
|
517
|
+
return undefined;
|
|
518
|
+
}
|
|
519
|
+
|
|
674
520
|
const ast = acornLoose.parse(contents, {
|
|
675
521
|
locations: true,
|
|
676
522
|
ecmaVersion: 'latest',
|
|
@@ -690,63 +536,87 @@ export async function parseAgentMetadata(
|
|
|
690
536
|
if (body.declaration?.type === 'CallExpression') {
|
|
691
537
|
const call = body.declaration as ASTCallExpression;
|
|
692
538
|
if (call.callee.name === 'createAgent') {
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
if (!schemaCodeExtracted) {
|
|
700
|
-
const schemaCode = extractSchemaCode(callargexp);
|
|
701
|
-
inputSchemaCode = schemaCode.inputSchemaCode;
|
|
702
|
-
outputSchemaCode = schemaCode.outputSchemaCode;
|
|
703
|
-
schemaCodeExtracted = true;
|
|
704
|
-
}
|
|
539
|
+
// Enforce new API: createAgent('name', {config})
|
|
540
|
+
if (call.arguments.length < 2) {
|
|
541
|
+
throw new Error(
|
|
542
|
+
`createAgent requires 2 arguments: createAgent('name', config) in ${filename}`
|
|
543
|
+
);
|
|
544
|
+
}
|
|
705
545
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
546
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
547
|
+
const nameArg = call.arguments[0] as any;
|
|
548
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
549
|
+
const configArg = call.arguments[1] as any;
|
|
550
|
+
|
|
551
|
+
if (!nameArg || nameArg.type !== 'Literal' || typeof nameArg.value !== 'string') {
|
|
552
|
+
throw new Error(
|
|
553
|
+
`createAgent first argument must be a string literal in ${filename}`
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
if (!isObjectExpression(configArg)) {
|
|
558
|
+
throw new Error(
|
|
559
|
+
`createAgent second argument must be a config object in ${filename}`
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const callargexp = configArg;
|
|
564
|
+
|
|
565
|
+
// Extract schema code before processing metadata
|
|
566
|
+
let inputSchemaCode: string | undefined;
|
|
567
|
+
let outputSchemaCode: string | undefined;
|
|
568
|
+
if (!schemaCodeExtracted) {
|
|
569
|
+
const schemaCode = extractSchemaCode(callargexp);
|
|
570
|
+
inputSchemaCode = schemaCode.inputSchemaCode;
|
|
571
|
+
outputSchemaCode = schemaCode.outputSchemaCode;
|
|
572
|
+
schemaCodeExtracted = true;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
for (const prop of callargexp.properties) {
|
|
576
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'metadata') {
|
|
577
|
+
result = augmentAgentMetadataNode(
|
|
578
|
+
projectId,
|
|
725
579
|
id,
|
|
726
|
-
name,
|
|
727
580
|
rel,
|
|
728
581
|
version,
|
|
729
582
|
ast,
|
|
730
|
-
|
|
731
|
-
filename
|
|
583
|
+
prop.value as ASTObjectExpression,
|
|
584
|
+
filename,
|
|
585
|
+
inputSchemaCode,
|
|
586
|
+
outputSchemaCode
|
|
732
587
|
);
|
|
588
|
+
break;
|
|
733
589
|
}
|
|
734
|
-
break;
|
|
735
590
|
}
|
|
591
|
+
if (!result) {
|
|
592
|
+
result = createAgentMetadataNode(
|
|
593
|
+
id,
|
|
594
|
+
name,
|
|
595
|
+
rel,
|
|
596
|
+
version,
|
|
597
|
+
ast,
|
|
598
|
+
callargexp,
|
|
599
|
+
filename,
|
|
600
|
+
projectId,
|
|
601
|
+
inputSchemaCode,
|
|
602
|
+
outputSchemaCode
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
break;
|
|
736
606
|
}
|
|
737
607
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
608
|
+
}
|
|
609
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
610
|
+
if (!result && (body as any).declaration?.type === 'Identifier') {
|
|
611
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
612
|
+
const identifier = (body as any).declaration as ASTNodeIdentifier;
|
|
613
|
+
exportName = identifier.name;
|
|
614
|
+
break;
|
|
743
615
|
}
|
|
744
616
|
}
|
|
617
|
+
// If no default export or createAgent found, skip this file (it's not an agent)
|
|
745
618
|
if (!result && !exportName) {
|
|
746
|
-
|
|
747
|
-
filename,
|
|
748
|
-
message: `could not find default export for ${filename} using ${rootDir}`,
|
|
749
|
-
});
|
|
619
|
+
return undefined;
|
|
750
620
|
}
|
|
751
621
|
if (!result) {
|
|
752
622
|
for (const body of ast.body) {
|
|
@@ -758,52 +628,77 @@ export async function parseAgentMetadata(
|
|
|
758
628
|
if (vardecl.init?.type === 'CallExpression') {
|
|
759
629
|
const call = vardecl.init as ASTCallExpression;
|
|
760
630
|
if (call.callee.name === 'createAgent') {
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
if (!schemaCodeExtracted) {
|
|
768
|
-
const schemaCode = extractSchemaCode(callargexp);
|
|
769
|
-
inputSchemaCode = schemaCode.inputSchemaCode;
|
|
770
|
-
outputSchemaCode = schemaCode.outputSchemaCode;
|
|
771
|
-
schemaCodeExtracted = true;
|
|
772
|
-
}
|
|
631
|
+
// Enforce new API: createAgent('name', {config})
|
|
632
|
+
if (call.arguments.length < 2) {
|
|
633
|
+
throw new Error(
|
|
634
|
+
`createAgent requires 2 arguments: createAgent('name', config) in ${filename}`
|
|
635
|
+
);
|
|
636
|
+
}
|
|
773
637
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
638
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
639
|
+
const nameArg = call.arguments[0] as any;
|
|
640
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
641
|
+
const configArg = call.arguments[1] as any;
|
|
642
|
+
|
|
643
|
+
if (
|
|
644
|
+
!nameArg ||
|
|
645
|
+
nameArg.type !== 'Literal' ||
|
|
646
|
+
typeof nameArg.value !== 'string'
|
|
647
|
+
) {
|
|
648
|
+
throw new Error(
|
|
649
|
+
`createAgent first argument must be a string literal in ${filename}`
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
if (!isObjectExpression(configArg)) {
|
|
654
|
+
throw new Error(
|
|
655
|
+
`createAgent second argument must be a config object in ${filename}`
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
const callargexp = configArg;
|
|
660
|
+
|
|
661
|
+
// Extract schema code before processing metadata
|
|
662
|
+
let inputSchemaCode: string | undefined;
|
|
663
|
+
let outputSchemaCode: string | undefined;
|
|
664
|
+
if (!schemaCodeExtracted) {
|
|
665
|
+
const schemaCode = extractSchemaCode(callargexp);
|
|
666
|
+
inputSchemaCode = schemaCode.inputSchemaCode;
|
|
667
|
+
outputSchemaCode = schemaCode.outputSchemaCode;
|
|
668
|
+
schemaCodeExtracted = true;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
for (const prop of callargexp.properties) {
|
|
672
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'metadata') {
|
|
673
|
+
result = augmentAgentMetadataNode(
|
|
674
|
+
projectId,
|
|
796
675
|
id,
|
|
797
|
-
name,
|
|
798
676
|
rel,
|
|
799
677
|
version,
|
|
800
678
|
ast,
|
|
801
|
-
|
|
802
|
-
filename
|
|
679
|
+
prop.value as ASTObjectExpression,
|
|
680
|
+
filename,
|
|
681
|
+
inputSchemaCode,
|
|
682
|
+
outputSchemaCode
|
|
803
683
|
);
|
|
684
|
+
break;
|
|
804
685
|
}
|
|
805
|
-
break;
|
|
806
686
|
}
|
|
687
|
+
if (!result) {
|
|
688
|
+
result = createAgentMetadataNode(
|
|
689
|
+
id,
|
|
690
|
+
name,
|
|
691
|
+
rel,
|
|
692
|
+
version,
|
|
693
|
+
ast,
|
|
694
|
+
callargexp,
|
|
695
|
+
filename,
|
|
696
|
+
projectId,
|
|
697
|
+
inputSchemaCode,
|
|
698
|
+
outputSchemaCode
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
break;
|
|
807
702
|
}
|
|
808
703
|
}
|
|
809
704
|
}
|
|
@@ -812,11 +707,9 @@ export async function parseAgentMetadata(
|
|
|
812
707
|
}
|
|
813
708
|
}
|
|
814
709
|
}
|
|
710
|
+
// If no createAgent found after checking all declarations, skip this file
|
|
815
711
|
if (!result) {
|
|
816
|
-
|
|
817
|
-
filename,
|
|
818
|
-
message: `error parsing: ${filename}. could not find an proper createAgent defined in this file`,
|
|
819
|
-
});
|
|
712
|
+
return undefined;
|
|
820
713
|
}
|
|
821
714
|
|
|
822
715
|
// Parse evals from eval.ts file in the same directory
|
|
@@ -869,6 +762,89 @@ const InvalidRouterConfigError = StructuredError('InvalidRouterConfigError')<{
|
|
|
869
762
|
line?: number;
|
|
870
763
|
}>();
|
|
871
764
|
|
|
765
|
+
/**
|
|
766
|
+
* Check if an AST node contains a validator() call
|
|
767
|
+
*/
|
|
768
|
+
interface ValidatorInfo {
|
|
769
|
+
hasValidator: boolean;
|
|
770
|
+
agentVariable?: string;
|
|
771
|
+
inputSchemaVariable?: string;
|
|
772
|
+
outputSchemaVariable?: string;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
function hasValidatorCall(args: unknown[]): ValidatorInfo {
|
|
776
|
+
if (!args || args.length === 0) return { hasValidator: false };
|
|
777
|
+
|
|
778
|
+
for (const arg of args) {
|
|
779
|
+
if (!arg || typeof arg !== 'object') continue;
|
|
780
|
+
const node = arg as ASTNode;
|
|
781
|
+
|
|
782
|
+
// Check if this is a CallExpression with callee named 'validator'
|
|
783
|
+
if (node.type === 'CallExpression') {
|
|
784
|
+
const callExpr = node as ASTCallExpression;
|
|
785
|
+
if (callExpr.callee.type === 'Identifier') {
|
|
786
|
+
const identifier = callExpr.callee as ASTNodeIdentifier;
|
|
787
|
+
if (identifier.name === 'validator') {
|
|
788
|
+
// Try to extract schema variables from validator({ input, output })
|
|
789
|
+
const schemas = extractValidatorSchemas(callExpr);
|
|
790
|
+
return { hasValidator: true, ...schemas };
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
// Check for agent.validator()
|
|
794
|
+
if (callExpr.callee.type === 'MemberExpression') {
|
|
795
|
+
const member = callExpr.callee as ASTMemberExpression;
|
|
796
|
+
if (member.property && (member.property as ASTNodeIdentifier).name === 'validator') {
|
|
797
|
+
// Extract agent variable name (the object before .validator())
|
|
798
|
+
const agentVariable =
|
|
799
|
+
member.object.type === 'Identifier'
|
|
800
|
+
? (member.object as ASTNodeIdentifier).name
|
|
801
|
+
: undefined;
|
|
802
|
+
return { hasValidator: true, agentVariable };
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
return { hasValidator: false };
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Extract schema variable names from validator() call arguments
|
|
813
|
+
* Example: validator({ input: myInputSchema, output: myOutputSchema })
|
|
814
|
+
*/
|
|
815
|
+
function extractValidatorSchemas(callExpr: ASTCallExpression): {
|
|
816
|
+
inputSchemaVariable?: string;
|
|
817
|
+
outputSchemaVariable?: string;
|
|
818
|
+
} {
|
|
819
|
+
const result: { inputSchemaVariable?: string; outputSchemaVariable?: string } = {};
|
|
820
|
+
|
|
821
|
+
// Check if validator has arguments
|
|
822
|
+
if (!callExpr.arguments || callExpr.arguments.length === 0) {
|
|
823
|
+
return result;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// First argument should be an object expression
|
|
827
|
+
const firstArg = callExpr.arguments[0] as ASTNode;
|
|
828
|
+
if (!firstArg || firstArg.type !== 'ObjectExpression') {
|
|
829
|
+
return result;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
const objExpr = firstArg as ASTObjectExpression;
|
|
833
|
+
for (const prop of objExpr.properties) {
|
|
834
|
+
const keyName = prop.key.name;
|
|
835
|
+
if ((keyName === 'input' || keyName === 'output') && prop.value.type === 'Identifier') {
|
|
836
|
+
const valueName = (prop.value as ASTNodeIdentifier).name;
|
|
837
|
+
if (keyName === 'input') {
|
|
838
|
+
result.inputSchemaVariable = valueName;
|
|
839
|
+
} else {
|
|
840
|
+
result.outputSchemaVariable = valueName;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
return result;
|
|
846
|
+
}
|
|
847
|
+
|
|
872
848
|
export async function parseRoute(
|
|
873
849
|
rootDir: string,
|
|
874
850
|
filename: string,
|
|
@@ -884,6 +860,32 @@ export async function parseRoute(
|
|
|
884
860
|
});
|
|
885
861
|
let exportName: string | undefined;
|
|
886
862
|
let variableName: string | undefined;
|
|
863
|
+
|
|
864
|
+
// Extract import statements to map variable names to their import sources
|
|
865
|
+
const importMap = new Map<string, string>(); // Maps variable name to import path
|
|
866
|
+
for (const body of ast.body) {
|
|
867
|
+
if (body.type === 'ImportDeclaration') {
|
|
868
|
+
const importDecl = body as {
|
|
869
|
+
source?: { value?: string };
|
|
870
|
+
specifiers?: Array<{
|
|
871
|
+
type: string;
|
|
872
|
+
local?: { name?: string };
|
|
873
|
+
}>;
|
|
874
|
+
};
|
|
875
|
+
const importPath = importDecl.source?.value;
|
|
876
|
+
if (importPath && importDecl.specifiers) {
|
|
877
|
+
for (const spec of importDecl.specifiers) {
|
|
878
|
+
if (spec.type === 'ImportDefaultSpecifier' && spec.local?.name) {
|
|
879
|
+
// import hello from '@agent/hello'
|
|
880
|
+
importMap.set(spec.local.name, importPath);
|
|
881
|
+
} else if (spec.type === 'ImportSpecifier' && spec.local?.name) {
|
|
882
|
+
// import { hello } from './shared'
|
|
883
|
+
importMap.set(spec.local.name, importPath);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
887
889
|
for (const body of ast.body) {
|
|
888
890
|
if (body.type === 'ExportDefaultDeclaration') {
|
|
889
891
|
const identifier = body.declaration as ASTNodeIdentifier;
|
|
@@ -905,10 +907,18 @@ export async function parseRoute(
|
|
|
905
907
|
if (identifier.name === exportName) {
|
|
906
908
|
if (vardecl.init?.type === 'CallExpression') {
|
|
907
909
|
const call = vardecl.init as ASTCallExpression;
|
|
910
|
+
// Support both createRouter() and new Hono()
|
|
908
911
|
if (call.callee.name === 'createRouter') {
|
|
909
912
|
variableName = identifier.name;
|
|
910
913
|
break;
|
|
911
914
|
}
|
|
915
|
+
} else if (vardecl.init?.type === 'NewExpression') {
|
|
916
|
+
const newExpr = vardecl.init as ASTCallExpression;
|
|
917
|
+
// Support new Hono() pattern
|
|
918
|
+
if (newExpr.callee.name === 'Hono') {
|
|
919
|
+
variableName = identifier.name;
|
|
920
|
+
break;
|
|
921
|
+
}
|
|
912
922
|
}
|
|
913
923
|
}
|
|
914
924
|
}
|
|
@@ -918,7 +928,7 @@ export async function parseRoute(
|
|
|
918
928
|
if (!variableName) {
|
|
919
929
|
throw new InvalidCreateRouterError({
|
|
920
930
|
filename,
|
|
921
|
-
message: `error parsing: ${filename}. could not find an proper createRouter defined in this file`,
|
|
931
|
+
message: `error parsing: ${filename}. could not find an proper createRouter or new Hono() defined in this file`,
|
|
922
932
|
});
|
|
923
933
|
}
|
|
924
934
|
|
|
@@ -926,16 +936,12 @@ export async function parseRoute(
|
|
|
926
936
|
const dir = dirname(filename);
|
|
927
937
|
const name = basename(dir);
|
|
928
938
|
|
|
929
|
-
//
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
.replace(/^src\/web\//, '');
|
|
933
|
-
const pathParts = relativePath.split('/').filter(Boolean);
|
|
934
|
-
const isSubagent = pathParts.length === 2 && filename.includes('src/agent');
|
|
935
|
-
const routeName = isSubagent ? pathParts.join('/') : name;
|
|
939
|
+
// For src/api/index.ts, we don't want to add the folder name since it's the root API router
|
|
940
|
+
const isRootApi = filename.includes('src/api/index.ts');
|
|
941
|
+
const routeName = isRootApi ? '' : name;
|
|
936
942
|
|
|
937
943
|
const routes: RouteDefinition = [];
|
|
938
|
-
const routePrefix =
|
|
944
|
+
const routePrefix = '/api';
|
|
939
945
|
|
|
940
946
|
try {
|
|
941
947
|
for (const body of ast.body) {
|
|
@@ -1067,6 +1073,30 @@ export async function parseRoute(
|
|
|
1067
1073
|
thepath,
|
|
1068
1074
|
version
|
|
1069
1075
|
);
|
|
1076
|
+
|
|
1077
|
+
// Check if this route uses validator middleware
|
|
1078
|
+
const validatorInfo = hasValidatorCall(statement.expression.arguments);
|
|
1079
|
+
|
|
1080
|
+
// Store validator info in config if present
|
|
1081
|
+
const routeConfig = config ? { ...config } : {};
|
|
1082
|
+
if (validatorInfo.hasValidator) {
|
|
1083
|
+
routeConfig.hasValidator = true;
|
|
1084
|
+
if (validatorInfo.agentVariable) {
|
|
1085
|
+
routeConfig.agentVariable = validatorInfo.agentVariable;
|
|
1086
|
+
// Look up where this agent variable is imported from
|
|
1087
|
+
const agentImportPath = importMap.get(validatorInfo.agentVariable);
|
|
1088
|
+
if (agentImportPath) {
|
|
1089
|
+
routeConfig.agentImportPath = agentImportPath;
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
if (validatorInfo.inputSchemaVariable) {
|
|
1093
|
+
routeConfig.inputSchemaVariable = validatorInfo.inputSchemaVariable;
|
|
1094
|
+
}
|
|
1095
|
+
if (validatorInfo.outputSchemaVariable) {
|
|
1096
|
+
routeConfig.outputSchemaVariable = validatorInfo.outputSchemaVariable;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1070
1100
|
routes.push({
|
|
1071
1101
|
id,
|
|
1072
1102
|
method: method as 'get' | 'post' | 'put' | 'delete' | 'patch',
|
|
@@ -1074,7 +1104,7 @@ export async function parseRoute(
|
|
|
1074
1104
|
filename: rel,
|
|
1075
1105
|
path: thepath,
|
|
1076
1106
|
version,
|
|
1077
|
-
config,
|
|
1107
|
+
config: Object.keys(routeConfig).length > 0 ? routeConfig : undefined,
|
|
1078
1108
|
});
|
|
1079
1109
|
}
|
|
1080
1110
|
}
|