@agentuity/cli 0.0.68 → 0.0.70
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/bin/cli.ts +20 -8
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +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.d.ts.map +1 -1
- package/dist/cmd/ai/prompt/agent.js +23 -24
- package/dist/cmd/ai/prompt/agent.js.map +1 -1
- package/dist/cmd/ai/prompt/api.d.ts.map +1 -1
- package/dist/cmd/ai/prompt/api.js +12 -9
- package/dist/cmd/ai/prompt/api.js.map +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 +2 -1
- package/dist/cmd/build/bundler.d.ts.map +1 -1
- package/dist/cmd/build/bundler.js +11 -2
- package/dist/cmd/build/bundler.js.map +1 -1
- package/dist/cmd/build/index.js +1 -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 -416
- 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 +1 -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.js +3 -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 +14 -31
- 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/keychain.d.ts.map +1 -1
- package/dist/keychain.js +8 -4
- package/dist/keychain.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/cli.ts +19 -0
- package/src/cmd/ai/capabilities/show.ts +0 -13
- package/src/cmd/ai/prompt/agent.ts +23 -24
- package/src/cmd/ai/prompt/api.ts +12 -9
- package/src/cmd/build/ast.ts +364 -334
- package/src/cmd/build/bundler.ts +16 -1
- package/src/cmd/build/index.ts +1 -1
- package/src/cmd/build/plugin.ts +171 -495
- package/src/cmd/build/route-registry.ts +198 -0
- package/src/cmd/cloud/deploy.ts +1 -0
- package/src/cmd/cloud/index.ts +0 -2
- package/src/cmd/dev/index.ts +3 -3
- package/src/cmd/dev/sync.ts +0 -28
- package/src/cmd/dev/templates.ts +14 -31
- package/src/cmd/profile/create.ts +0 -1
- package/src/cmd/project/template-flow.ts +77 -57
- package/src/config.ts +1 -5
- package/src/keychain.ts +9 -11
- 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/build/ast.test.d.ts +0 -2
- package/dist/cmd/build/ast.test.d.ts.map +0 -1
- package/dist/cmd/build/ast.test.js +0 -339
- package/dist/cmd/build/ast.test.js.map +0 -1
- package/dist/cmd/build/fix-duplicate-exports.test.d.ts +0 -2
- package/dist/cmd/build/fix-duplicate-exports.test.d.ts.map +0 -1
- package/dist/cmd/build/fix-duplicate-exports.test.js +0 -300
- package/dist/cmd/build/fix-duplicate-exports.test.js.map +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/dist/crypto/box.test.d.ts +0 -2
- package/dist/crypto/box.test.d.ts.map +0 -1
- package/dist/crypto/box.test.js +0 -317
- package/dist/crypto/box.test.js.map +0 -1
- package/dist/env-util.test.d.ts +0 -2
- package/dist/env-util.test.d.ts.map +0 -1
- package/dist/env-util.test.js +0 -146
- package/dist/env-util.test.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/dist/cmd/build/ast.js
CHANGED
|
@@ -81,6 +81,13 @@ function generateStableAgentId(projectId, name) {
|
|
|
81
81
|
function generateStableEvalId(projectId, agentId, name) {
|
|
82
82
|
return `evalid_${hashSHA1(projectId, agentId, name)}`.substring(0, 64);
|
|
83
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Type guard to check if an AST node is an ObjectExpression
|
|
86
|
+
*/
|
|
87
|
+
function isObjectExpression(node) {
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
89
|
+
return typeof node === 'object' && node !== null && node.type === 'ObjectExpression';
|
|
90
|
+
}
|
|
84
91
|
/**
|
|
85
92
|
* Extract schema code from createAgent call arguments
|
|
86
93
|
* Returns input and output schema code as strings
|
|
@@ -117,7 +124,7 @@ function extractSchemaCode(callargexp) {
|
|
|
117
124
|
return { inputSchemaCode, outputSchemaCode };
|
|
118
125
|
}
|
|
119
126
|
const MetadataError = StructuredError('MetatadataNameMissingError')();
|
|
120
|
-
function augmentAgentMetadataNode(projectId, id,
|
|
127
|
+
function augmentAgentMetadataNode(projectId, id, rel, version, ast, propvalue, filename, inputSchemaCode, outputSchemaCode) {
|
|
121
128
|
const metadata = parseObjectExpressionToMap(propvalue);
|
|
122
129
|
if (!metadata.has('name')) {
|
|
123
130
|
const location = ast.loc?.start?.line ? ` on line ${ast.loc.start.line}` : '';
|
|
@@ -128,19 +135,10 @@ function augmentAgentMetadataNode(projectId, id, identifier, rel, version, ast,
|
|
|
128
135
|
});
|
|
129
136
|
}
|
|
130
137
|
const name = metadata.get('name');
|
|
131
|
-
if (metadata.has('identifier') && identifier !== metadata.get('identifier')) {
|
|
132
|
-
const location = ast.loc?.start?.line ? ` on line ${ast.loc.start.line}` : '';
|
|
133
|
-
throw new MetadataError({
|
|
134
|
-
filename,
|
|
135
|
-
line: ast.loc?.start?.line,
|
|
136
|
-
message: `metadata.identifier (${metadata.get('identifier')}) in ${filename}${location} is mismatched (${name}). This is an internal error.`,
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
138
|
const descriptionNode = propvalue.properties.find((x) => x.key.name === 'description')?.value;
|
|
140
139
|
const description = descriptionNode ? descriptionNode.value : '';
|
|
141
140
|
const agentId = generateStableAgentId(projectId, name);
|
|
142
141
|
metadata.set('version', version);
|
|
143
|
-
metadata.set('identifier', identifier);
|
|
144
142
|
metadata.set('filename', rel);
|
|
145
143
|
metadata.set('id', id);
|
|
146
144
|
metadata.set('agentId', agentId);
|
|
@@ -151,7 +149,7 @@ function augmentAgentMetadataNode(projectId, id, identifier, rel, version, ast,
|
|
|
151
149
|
if (outputSchemaCode) {
|
|
152
150
|
metadata.set('outputSchemaCode', outputSchemaCode);
|
|
153
151
|
}
|
|
154
|
-
propvalue.properties.push(createObjectPropertyNode('id', id), createObjectPropertyNode('agentId', agentId), createObjectPropertyNode('version', version), createObjectPropertyNode('
|
|
152
|
+
propvalue.properties.push(createObjectPropertyNode('id', id), createObjectPropertyNode('agentId', agentId), createObjectPropertyNode('version', version), createObjectPropertyNode('filename', rel), createObjectPropertyNode('description', description));
|
|
155
153
|
if (inputSchemaCode) {
|
|
156
154
|
propvalue.properties.push(createObjectPropertyNode('inputSchemaCode', inputSchemaCode));
|
|
157
155
|
}
|
|
@@ -162,14 +160,21 @@ function augmentAgentMetadataNode(projectId, id, identifier, rel, version, ast,
|
|
|
162
160
|
// Evals imports are now handled in registry.generated.ts
|
|
163
161
|
return [newsource, metadata];
|
|
164
162
|
}
|
|
165
|
-
function createAgentMetadataNode(id, name, rel, version, ast, callargexp, _filename) {
|
|
163
|
+
function createAgentMetadataNode(id, name, rel, version, ast, callargexp, _filename, projectId, inputSchemaCode, outputSchemaCode) {
|
|
166
164
|
const newmetadata = createNewMetadataNode();
|
|
165
|
+
const agentId = generateStableAgentId(projectId, name);
|
|
167
166
|
const md = new Map();
|
|
168
167
|
md.set('id', id);
|
|
168
|
+
md.set('agentId', agentId);
|
|
169
169
|
md.set('version', version);
|
|
170
170
|
md.set('name', name);
|
|
171
|
-
md.set('identifier', name);
|
|
172
171
|
md.set('filename', rel);
|
|
172
|
+
if (inputSchemaCode) {
|
|
173
|
+
md.set('inputSchemaCode', inputSchemaCode);
|
|
174
|
+
}
|
|
175
|
+
if (outputSchemaCode) {
|
|
176
|
+
md.set('outputSchemaCode', outputSchemaCode);
|
|
177
|
+
}
|
|
173
178
|
for (const [key, value] of md) {
|
|
174
179
|
newmetadata.value.properties.push(createObjectPropertyNode(key, value));
|
|
175
180
|
}
|
|
@@ -178,118 +183,6 @@ function createAgentMetadataNode(id, name, rel, version, ast, callargexp, _filen
|
|
|
178
183
|
// Evals imports are now handled in registry.generated.ts
|
|
179
184
|
return [newsource, md];
|
|
180
185
|
}
|
|
181
|
-
function camelToKebab(str) {
|
|
182
|
-
return str
|
|
183
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
184
|
-
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
|
|
185
|
-
.toLowerCase();
|
|
186
|
-
}
|
|
187
|
-
function setLiteralValue(literal, value) {
|
|
188
|
-
literal.value = value;
|
|
189
|
-
if (literal.raw !== undefined) {
|
|
190
|
-
literal.raw = JSON.stringify(value);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
function augmentEvalMetadataNode(projectId, agentId, id, name, rel, version, _ast, metadataObj, _filename) {
|
|
194
|
-
const metadata = parseObjectExpressionToMap(metadataObj);
|
|
195
|
-
// Name can come from metadata.name or variable name (already resolved in caller)
|
|
196
|
-
// If metadata doesn't have name, we'll add it from the resolved name
|
|
197
|
-
if (!metadata.has('name')) {
|
|
198
|
-
metadataObj.properties.push(createObjectPropertyNode('name', name));
|
|
199
|
-
}
|
|
200
|
-
const descriptionNode = metadataObj.properties.find((x) => x.key.name === 'description')?.value;
|
|
201
|
-
const description = descriptionNode ? descriptionNode.value : '';
|
|
202
|
-
const effectiveAgentId = agentId || '';
|
|
203
|
-
const _evalId = getEvalId(projectId, effectiveAgentId, rel, name, version); // Deployment-specific ID (not used, kept for potential future use)
|
|
204
|
-
const stableEvalId = generateStableEvalId(projectId, effectiveAgentId, name);
|
|
205
|
-
// Check if id, version, identifier, filename, evalId already exist
|
|
206
|
-
const existingKeys = new Set();
|
|
207
|
-
for (const prop of metadataObj.properties) {
|
|
208
|
-
if (prop.key.type === 'Identifier') {
|
|
209
|
-
existingKeys.add(prop.key.name);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
// Add or update metadata properties
|
|
213
|
-
if (!existingKeys.has('id')) {
|
|
214
|
-
metadataObj.properties.push(createObjectPropertyNode('id', id));
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
// Update existing id
|
|
218
|
-
for (const prop of metadataObj.properties) {
|
|
219
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'id') {
|
|
220
|
-
if (prop.value.type === 'Literal') {
|
|
221
|
-
setLiteralValue(prop.value, id);
|
|
222
|
-
}
|
|
223
|
-
break;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
if (!existingKeys.has('version')) {
|
|
228
|
-
metadataObj.properties.push(createObjectPropertyNode('version', version));
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
for (const prop of metadataObj.properties) {
|
|
232
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'version') {
|
|
233
|
-
if (prop.value.type === 'Literal') {
|
|
234
|
-
setLiteralValue(prop.value, version);
|
|
235
|
-
}
|
|
236
|
-
break;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
if (!existingKeys.has('identifier')) {
|
|
241
|
-
metadataObj.properties.push(createObjectPropertyNode('identifier', name));
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
for (const prop of metadataObj.properties) {
|
|
245
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'identifier') {
|
|
246
|
-
if (prop.value.type === 'Literal') {
|
|
247
|
-
setLiteralValue(prop.value, name);
|
|
248
|
-
}
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
if (!existingKeys.has('filename')) {
|
|
254
|
-
metadataObj.properties.push(createObjectPropertyNode('filename', rel));
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
for (const prop of metadataObj.properties) {
|
|
258
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'filename') {
|
|
259
|
-
if (prop.value.type === 'Literal') {
|
|
260
|
-
setLiteralValue(prop.value, rel);
|
|
261
|
-
}
|
|
262
|
-
break;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
if (!existingKeys.has('evalId')) {
|
|
267
|
-
metadataObj.properties.push(createObjectPropertyNode('evalId', stableEvalId));
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
for (const prop of metadataObj.properties) {
|
|
271
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'evalId') {
|
|
272
|
-
if (prop.value.type === 'Literal') {
|
|
273
|
-
setLiteralValue(prop.value, stableEvalId);
|
|
274
|
-
}
|
|
275
|
-
break;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
if (!existingKeys.has('description')) {
|
|
280
|
-
metadataObj.properties.push(createObjectPropertyNode('description', description));
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
for (const prop of metadataObj.properties) {
|
|
284
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'description') {
|
|
285
|
-
if (prop.value.type === 'Literal') {
|
|
286
|
-
setLiteralValue(prop.value, description);
|
|
287
|
-
}
|
|
288
|
-
break;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
186
|
const DuplicateNameError = StructuredError('DuplicateNameError')();
|
|
294
187
|
export function parseEvalMetadata(rootDir, filename, contents, projectId, deploymentId, agentId) {
|
|
295
188
|
const logLevel = (process.env.AGENTUITY_LOG_LEVEL || 'info');
|
|
@@ -326,81 +219,54 @@ export function parseEvalMetadata(rootDir, filename, contents, projectId, deploy
|
|
|
326
219
|
property.type === 'Identifier' &&
|
|
327
220
|
property.name === 'createEval') {
|
|
328
221
|
// Found agent.createEval() call
|
|
329
|
-
|
|
222
|
+
// New signature: agent.createEval(name, { description?, handler })
|
|
223
|
+
if (call.arguments.length >= 2) {
|
|
330
224
|
const firstArg = call.arguments[0];
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
}
|
|
225
|
+
const secondArg = call.arguments[1];
|
|
226
|
+
let evalName;
|
|
227
|
+
let evalDescription;
|
|
228
|
+
let configObj;
|
|
229
|
+
// First argument should be a string literal (the name)
|
|
230
|
+
if (firstArg.type === 'Literal' &&
|
|
231
|
+
typeof firstArg.value === 'string') {
|
|
232
|
+
evalName = firstArg.value;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
throw new MetadataError({
|
|
236
|
+
filename,
|
|
237
|
+
line: body.loc?.start?.line,
|
|
238
|
+
message: 'agent.createEval() first argument must be a string literal name.',
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
// Second argument should be the config object
|
|
242
|
+
if (secondArg.type === 'ObjectExpression') {
|
|
243
|
+
configObj = secondArg;
|
|
244
|
+
// Extract description from config object
|
|
245
|
+
for (const prop of configObj.properties) {
|
|
246
|
+
if (prop.key.type === 'Identifier' &&
|
|
247
|
+
prop.key.name === 'description') {
|
|
248
|
+
if (prop.value.type === 'Literal') {
|
|
249
|
+
evalDescription = prop.value.value;
|
|
358
250
|
}
|
|
359
251
|
}
|
|
360
252
|
}
|
|
361
|
-
// Use metadata.name if provided, otherwise use variable name
|
|
362
|
-
// Throw error if neither is available (should never happen)
|
|
363
|
-
let finalName;
|
|
364
|
-
if (evalName) {
|
|
365
|
-
finalName = evalName;
|
|
366
|
-
}
|
|
367
|
-
else if (variableName) {
|
|
368
|
-
finalName = camelToKebab(variableName);
|
|
369
|
-
}
|
|
370
|
-
else {
|
|
371
|
-
throw new MetadataError({
|
|
372
|
-
filename,
|
|
373
|
-
line: body.loc?.start?.line,
|
|
374
|
-
message: 'Eval is missing a name. Please provide metadata.name or use a named export.',
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
logger.trace(`Found eval: ${finalName}${evalDescription ? ` - ${evalDescription}` : ''}`);
|
|
378
|
-
const evalId = getEvalId(projectId, deploymentId, rel, finalName, version);
|
|
379
|
-
// Inject metadata into AST if metadata object exists
|
|
380
|
-
let stableEvalId;
|
|
381
|
-
const effectiveAgentId = agentId || '';
|
|
382
|
-
if (metadataObj) {
|
|
383
|
-
augmentEvalMetadataNode(projectId, effectiveAgentId, evalId, finalName, rel, version, ast, metadataObj, filename);
|
|
384
|
-
// Extract evalId from metadata after augmentation
|
|
385
|
-
const metadata = parseObjectExpressionToMap(metadataObj);
|
|
386
|
-
stableEvalId =
|
|
387
|
-
metadata.get('evalId') ||
|
|
388
|
-
generateStableEvalId(projectId, effectiveAgentId, finalName);
|
|
389
|
-
}
|
|
390
|
-
else {
|
|
391
|
-
// If no metadata object, generate stable evalId
|
|
392
|
-
stableEvalId = generateStableEvalId(projectId, effectiveAgentId, finalName);
|
|
393
|
-
}
|
|
394
|
-
evals.push({
|
|
395
|
-
filename: rel,
|
|
396
|
-
id: evalId,
|
|
397
|
-
version,
|
|
398
|
-
identifier: finalName,
|
|
399
|
-
name: finalName,
|
|
400
|
-
evalId: stableEvalId,
|
|
401
|
-
description: evalDescription,
|
|
402
|
-
});
|
|
403
253
|
}
|
|
254
|
+
const finalName = evalName;
|
|
255
|
+
logger.trace(`Found eval: ${finalName}${evalDescription ? ` - ${evalDescription}` : ''}`);
|
|
256
|
+
const evalId = getEvalId(projectId, deploymentId, rel, finalName, version);
|
|
257
|
+
// Generate stable evalId
|
|
258
|
+
const effectiveAgentId = agentId || '';
|
|
259
|
+
const stableEvalId = generateStableEvalId(projectId, effectiveAgentId, finalName);
|
|
260
|
+
// Note: We no longer inject metadata into the AST since there's no metadata object
|
|
261
|
+
// The runtime will generate IDs from the name parameter
|
|
262
|
+
evals.push({
|
|
263
|
+
filename: rel,
|
|
264
|
+
id: evalId,
|
|
265
|
+
version,
|
|
266
|
+
name: finalName,
|
|
267
|
+
evalId: stableEvalId,
|
|
268
|
+
description: evalDescription,
|
|
269
|
+
});
|
|
404
270
|
}
|
|
405
271
|
}
|
|
406
272
|
}
|
|
@@ -433,8 +299,11 @@ export function parseEvalMetadata(rootDir, filename, contents, projectId, deploy
|
|
|
433
299
|
return [newsource, evals];
|
|
434
300
|
}
|
|
435
301
|
const InvalidExportError = StructuredError('InvalidExportError')();
|
|
436
|
-
const InvalidCreateAgentError = StructuredError('InvalidCreateAgentError')();
|
|
437
302
|
export async function parseAgentMetadata(rootDir, filename, contents, projectId, deploymentId) {
|
|
303
|
+
// Quick string search optimization - skip AST parsing if no createAgent call
|
|
304
|
+
if (!contents.includes('createAgent')) {
|
|
305
|
+
return undefined;
|
|
306
|
+
}
|
|
438
307
|
const ast = acornLoose.parse(contents, {
|
|
439
308
|
locations: true,
|
|
440
309
|
ecmaVersion: 'latest',
|
|
@@ -452,42 +321,54 @@ export async function parseAgentMetadata(rootDir, filename, contents, projectId,
|
|
|
452
321
|
if (body.declaration?.type === 'CallExpression') {
|
|
453
322
|
const call = body.declaration;
|
|
454
323
|
if (call.callee.name === 'createAgent') {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
324
|
+
// Enforce new API: createAgent('name', {config})
|
|
325
|
+
if (call.arguments.length < 2) {
|
|
326
|
+
throw new Error(`createAgent requires 2 arguments: createAgent('name', config) in ${filename}`);
|
|
327
|
+
}
|
|
328
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
329
|
+
const nameArg = call.arguments[0];
|
|
330
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
331
|
+
const configArg = call.arguments[1];
|
|
332
|
+
if (!nameArg || nameArg.type !== 'Literal' || typeof nameArg.value !== 'string') {
|
|
333
|
+
throw new Error(`createAgent first argument must be a string literal in ${filename}`);
|
|
334
|
+
}
|
|
335
|
+
if (!isObjectExpression(configArg)) {
|
|
336
|
+
throw new Error(`createAgent second argument must be a config object in ${filename}`);
|
|
337
|
+
}
|
|
338
|
+
const callargexp = configArg;
|
|
339
|
+
// Extract schema code before processing metadata
|
|
340
|
+
let inputSchemaCode;
|
|
341
|
+
let outputSchemaCode;
|
|
342
|
+
if (!schemaCodeExtracted) {
|
|
343
|
+
const schemaCode = extractSchemaCode(callargexp);
|
|
344
|
+
inputSchemaCode = schemaCode.inputSchemaCode;
|
|
345
|
+
outputSchemaCode = schemaCode.outputSchemaCode;
|
|
346
|
+
schemaCodeExtracted = true;
|
|
347
|
+
}
|
|
348
|
+
for (const prop of callargexp.properties) {
|
|
349
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'metadata') {
|
|
350
|
+
result = augmentAgentMetadataNode(projectId, id, rel, version, ast, prop.value, filename, inputSchemaCode, outputSchemaCode);
|
|
351
|
+
break;
|
|
474
352
|
}
|
|
475
|
-
break;
|
|
476
353
|
}
|
|
354
|
+
if (!result) {
|
|
355
|
+
result = createAgentMetadataNode(id, name, rel, version, ast, callargexp, filename, projectId, inputSchemaCode, outputSchemaCode);
|
|
356
|
+
}
|
|
357
|
+
break;
|
|
477
358
|
}
|
|
478
359
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
360
|
+
}
|
|
361
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
362
|
+
if (!result && body.declaration?.type === 'Identifier') {
|
|
363
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
364
|
+
const identifier = body.declaration;
|
|
365
|
+
exportName = identifier.name;
|
|
366
|
+
break;
|
|
484
367
|
}
|
|
485
368
|
}
|
|
369
|
+
// If no default export or createAgent found, skip this file (it's not an agent)
|
|
486
370
|
if (!result && !exportName) {
|
|
487
|
-
|
|
488
|
-
filename,
|
|
489
|
-
message: `could not find default export for ${filename} using ${rootDir}`,
|
|
490
|
-
});
|
|
371
|
+
return undefined;
|
|
491
372
|
}
|
|
492
373
|
if (!result) {
|
|
493
374
|
for (const body of ast.body) {
|
|
@@ -499,29 +380,42 @@ export async function parseAgentMetadata(rootDir, filename, contents, projectId,
|
|
|
499
380
|
if (vardecl.init?.type === 'CallExpression') {
|
|
500
381
|
const call = vardecl.init;
|
|
501
382
|
if (call.callee.name === 'createAgent') {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
383
|
+
// Enforce new API: createAgent('name', {config})
|
|
384
|
+
if (call.arguments.length < 2) {
|
|
385
|
+
throw new Error(`createAgent requires 2 arguments: createAgent('name', config) in ${filename}`);
|
|
386
|
+
}
|
|
387
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
388
|
+
const nameArg = call.arguments[0];
|
|
389
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
390
|
+
const configArg = call.arguments[1];
|
|
391
|
+
if (!nameArg ||
|
|
392
|
+
nameArg.type !== 'Literal' ||
|
|
393
|
+
typeof nameArg.value !== 'string') {
|
|
394
|
+
throw new Error(`createAgent first argument must be a string literal in ${filename}`);
|
|
395
|
+
}
|
|
396
|
+
if (!isObjectExpression(configArg)) {
|
|
397
|
+
throw new Error(`createAgent second argument must be a config object in ${filename}`);
|
|
398
|
+
}
|
|
399
|
+
const callargexp = configArg;
|
|
400
|
+
// Extract schema code before processing metadata
|
|
401
|
+
let inputSchemaCode;
|
|
402
|
+
let outputSchemaCode;
|
|
403
|
+
if (!schemaCodeExtracted) {
|
|
404
|
+
const schemaCode = extractSchemaCode(callargexp);
|
|
405
|
+
inputSchemaCode = schemaCode.inputSchemaCode;
|
|
406
|
+
outputSchemaCode = schemaCode.outputSchemaCode;
|
|
407
|
+
schemaCodeExtracted = true;
|
|
408
|
+
}
|
|
409
|
+
for (const prop of callargexp.properties) {
|
|
410
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'metadata') {
|
|
411
|
+
result = augmentAgentMetadataNode(projectId, id, rel, version, ast, prop.value, filename, inputSchemaCode, outputSchemaCode);
|
|
412
|
+
break;
|
|
522
413
|
}
|
|
523
|
-
break;
|
|
524
414
|
}
|
|
415
|
+
if (!result) {
|
|
416
|
+
result = createAgentMetadataNode(id, name, rel, version, ast, callargexp, filename, projectId, inputSchemaCode, outputSchemaCode);
|
|
417
|
+
}
|
|
418
|
+
break;
|
|
525
419
|
}
|
|
526
420
|
}
|
|
527
421
|
}
|
|
@@ -530,11 +424,9 @@ export async function parseAgentMetadata(rootDir, filename, contents, projectId,
|
|
|
530
424
|
}
|
|
531
425
|
}
|
|
532
426
|
}
|
|
427
|
+
// If no createAgent found after checking all declarations, skip this file
|
|
533
428
|
if (!result) {
|
|
534
|
-
|
|
535
|
-
filename,
|
|
536
|
-
message: `error parsing: ${filename}. could not find an proper createAgent defined in this file`,
|
|
537
|
-
});
|
|
429
|
+
return undefined;
|
|
538
430
|
}
|
|
539
431
|
// Parse evals from eval.ts file in the same directory
|
|
540
432
|
const logLevel = (process.env.AGENTUITY_LOG_LEVEL || 'info');
|
|
@@ -565,6 +457,69 @@ export async function parseAgentMetadata(rootDir, filename, contents, projectId,
|
|
|
565
457
|
}
|
|
566
458
|
const InvalidCreateRouterError = StructuredError('InvalidCreateRouterError')();
|
|
567
459
|
const InvalidRouterConfigError = StructuredError('InvalidRouterConfigError')();
|
|
460
|
+
function hasValidatorCall(args) {
|
|
461
|
+
if (!args || args.length === 0)
|
|
462
|
+
return { hasValidator: false };
|
|
463
|
+
for (const arg of args) {
|
|
464
|
+
if (!arg || typeof arg !== 'object')
|
|
465
|
+
continue;
|
|
466
|
+
const node = arg;
|
|
467
|
+
// Check if this is a CallExpression with callee named 'validator'
|
|
468
|
+
if (node.type === 'CallExpression') {
|
|
469
|
+
const callExpr = node;
|
|
470
|
+
if (callExpr.callee.type === 'Identifier') {
|
|
471
|
+
const identifier = callExpr.callee;
|
|
472
|
+
if (identifier.name === 'validator') {
|
|
473
|
+
// Try to extract schema variables from validator({ input, output })
|
|
474
|
+
const schemas = extractValidatorSchemas(callExpr);
|
|
475
|
+
return { hasValidator: true, ...schemas };
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
// Check for agent.validator()
|
|
479
|
+
if (callExpr.callee.type === 'MemberExpression') {
|
|
480
|
+
const member = callExpr.callee;
|
|
481
|
+
if (member.property && member.property.name === 'validator') {
|
|
482
|
+
// Extract agent variable name (the object before .validator())
|
|
483
|
+
const agentVariable = member.object.type === 'Identifier'
|
|
484
|
+
? member.object.name
|
|
485
|
+
: undefined;
|
|
486
|
+
return { hasValidator: true, agentVariable };
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return { hasValidator: false };
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Extract schema variable names from validator() call arguments
|
|
495
|
+
* Example: validator({ input: myInputSchema, output: myOutputSchema })
|
|
496
|
+
*/
|
|
497
|
+
function extractValidatorSchemas(callExpr) {
|
|
498
|
+
const result = {};
|
|
499
|
+
// Check if validator has arguments
|
|
500
|
+
if (!callExpr.arguments || callExpr.arguments.length === 0) {
|
|
501
|
+
return result;
|
|
502
|
+
}
|
|
503
|
+
// First argument should be an object expression
|
|
504
|
+
const firstArg = callExpr.arguments[0];
|
|
505
|
+
if (!firstArg || firstArg.type !== 'ObjectExpression') {
|
|
506
|
+
return result;
|
|
507
|
+
}
|
|
508
|
+
const objExpr = firstArg;
|
|
509
|
+
for (const prop of objExpr.properties) {
|
|
510
|
+
const keyName = prop.key.name;
|
|
511
|
+
if ((keyName === 'input' || keyName === 'output') && prop.value.type === 'Identifier') {
|
|
512
|
+
const valueName = prop.value.name;
|
|
513
|
+
if (keyName === 'input') {
|
|
514
|
+
result.inputSchemaVariable = valueName;
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
result.outputSchemaVariable = valueName;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return result;
|
|
522
|
+
}
|
|
568
523
|
export async function parseRoute(rootDir, filename, projectId, deploymentId) {
|
|
569
524
|
const contents = await Bun.file(filename).text();
|
|
570
525
|
const version = hash(contents);
|
|
@@ -575,6 +530,26 @@ export async function parseRoute(rootDir, filename, projectId, deploymentId) {
|
|
|
575
530
|
});
|
|
576
531
|
let exportName;
|
|
577
532
|
let variableName;
|
|
533
|
+
// Extract import statements to map variable names to their import sources
|
|
534
|
+
const importMap = new Map(); // Maps variable name to import path
|
|
535
|
+
for (const body of ast.body) {
|
|
536
|
+
if (body.type === 'ImportDeclaration') {
|
|
537
|
+
const importDecl = body;
|
|
538
|
+
const importPath = importDecl.source?.value;
|
|
539
|
+
if (importPath && importDecl.specifiers) {
|
|
540
|
+
for (const spec of importDecl.specifiers) {
|
|
541
|
+
if (spec.type === 'ImportDefaultSpecifier' && spec.local?.name) {
|
|
542
|
+
// import hello from '@agent/hello'
|
|
543
|
+
importMap.set(spec.local.name, importPath);
|
|
544
|
+
}
|
|
545
|
+
else if (spec.type === 'ImportSpecifier' && spec.local?.name) {
|
|
546
|
+
// import { hello } from './shared'
|
|
547
|
+
importMap.set(spec.local.name, importPath);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
578
553
|
for (const body of ast.body) {
|
|
579
554
|
if (body.type === 'ExportDefaultDeclaration') {
|
|
580
555
|
const identifier = body.declaration;
|
|
@@ -596,11 +571,20 @@ export async function parseRoute(rootDir, filename, projectId, deploymentId) {
|
|
|
596
571
|
if (identifier.name === exportName) {
|
|
597
572
|
if (vardecl.init?.type === 'CallExpression') {
|
|
598
573
|
const call = vardecl.init;
|
|
574
|
+
// Support both createRouter() and new Hono()
|
|
599
575
|
if (call.callee.name === 'createRouter') {
|
|
600
576
|
variableName = identifier.name;
|
|
601
577
|
break;
|
|
602
578
|
}
|
|
603
579
|
}
|
|
580
|
+
else if (vardecl.init?.type === 'NewExpression') {
|
|
581
|
+
const newExpr = vardecl.init;
|
|
582
|
+
// Support new Hono() pattern
|
|
583
|
+
if (newExpr.callee.name === 'Hono') {
|
|
584
|
+
variableName = identifier.name;
|
|
585
|
+
break;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
604
588
|
}
|
|
605
589
|
}
|
|
606
590
|
}
|
|
@@ -609,21 +593,17 @@ export async function parseRoute(rootDir, filename, projectId, deploymentId) {
|
|
|
609
593
|
if (!variableName) {
|
|
610
594
|
throw new InvalidCreateRouterError({
|
|
611
595
|
filename,
|
|
612
|
-
message: `error parsing: ${filename}. could not find an proper createRouter defined in this file`,
|
|
596
|
+
message: `error parsing: ${filename}. could not find an proper createRouter or new Hono() defined in this file`,
|
|
613
597
|
});
|
|
614
598
|
}
|
|
615
599
|
const rel = relative(rootDir, filename);
|
|
616
600
|
const dir = dirname(filename);
|
|
617
601
|
const name = basename(dir);
|
|
618
|
-
//
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
.replace(/^src\/web\//, '');
|
|
622
|
-
const pathParts = relativePath.split('/').filter(Boolean);
|
|
623
|
-
const isSubagent = pathParts.length === 2 && filename.includes('src/agent');
|
|
624
|
-
const routeName = isSubagent ? pathParts.join('/') : name;
|
|
602
|
+
// For src/api/index.ts, we don't want to add the folder name since it's the root API router
|
|
603
|
+
const isRootApi = filename.includes('src/api/index.ts');
|
|
604
|
+
const routeName = isRootApi ? '' : name;
|
|
625
605
|
const routes = [];
|
|
626
|
-
const routePrefix =
|
|
606
|
+
const routePrefix = '/api';
|
|
627
607
|
try {
|
|
628
608
|
for (const body of ast.body) {
|
|
629
609
|
if (body.type === 'ExpressionStatement') {
|
|
@@ -744,6 +724,27 @@ export async function parseRoute(rootDir, filename, projectId, deploymentId) {
|
|
|
744
724
|
.replaceAll(/\/{2,}/g, '/')
|
|
745
725
|
.replaceAll(/\/$/g, '');
|
|
746
726
|
const id = generateRouteId(projectId, deploymentId, type, method, rel, thepath, version);
|
|
727
|
+
// Check if this route uses validator middleware
|
|
728
|
+
const validatorInfo = hasValidatorCall(statement.expression.arguments);
|
|
729
|
+
// Store validator info in config if present
|
|
730
|
+
const routeConfig = config ? { ...config } : {};
|
|
731
|
+
if (validatorInfo.hasValidator) {
|
|
732
|
+
routeConfig.hasValidator = true;
|
|
733
|
+
if (validatorInfo.agentVariable) {
|
|
734
|
+
routeConfig.agentVariable = validatorInfo.agentVariable;
|
|
735
|
+
// Look up where this agent variable is imported from
|
|
736
|
+
const agentImportPath = importMap.get(validatorInfo.agentVariable);
|
|
737
|
+
if (agentImportPath) {
|
|
738
|
+
routeConfig.agentImportPath = agentImportPath;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
if (validatorInfo.inputSchemaVariable) {
|
|
742
|
+
routeConfig.inputSchemaVariable = validatorInfo.inputSchemaVariable;
|
|
743
|
+
}
|
|
744
|
+
if (validatorInfo.outputSchemaVariable) {
|
|
745
|
+
routeConfig.outputSchemaVariable = validatorInfo.outputSchemaVariable;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
747
748
|
routes.push({
|
|
748
749
|
id,
|
|
749
750
|
method: method,
|
|
@@ -751,7 +752,7 @@ export async function parseRoute(rootDir, filename, projectId, deploymentId) {
|
|
|
751
752
|
filename: rel,
|
|
752
753
|
path: thepath,
|
|
753
754
|
version,
|
|
754
|
-
config,
|
|
755
|
+
config: Object.keys(routeConfig).length > 0 ? routeConfig : undefined,
|
|
755
756
|
});
|
|
756
757
|
}
|
|
757
758
|
}
|