@agentuity/cli 0.0.42 → 0.0.44
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 +7 -5
- package/dist/api.d.ts +3 -3
- package/dist/api.d.ts.map +1 -1
- package/dist/auth.d.ts +10 -2
- package/dist/auth.d.ts.map +1 -1
- package/dist/banner.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cmd/auth/api.d.ts +4 -4
- package/dist/cmd/auth/api.d.ts.map +1 -1
- package/dist/cmd/auth/index.d.ts.map +1 -1
- package/dist/cmd/auth/login.d.ts.map +1 -1
- package/dist/cmd/auth/signup.d.ts.map +1 -1
- package/dist/cmd/auth/ssh/add.d.ts +2 -0
- package/dist/cmd/auth/ssh/add.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/api.d.ts +16 -0
- package/dist/cmd/auth/ssh/api.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/delete.d.ts +2 -0
- package/dist/cmd/auth/ssh/delete.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/index.d.ts +3 -0
- package/dist/cmd/auth/ssh/index.d.ts.map +1 -0
- package/dist/cmd/auth/ssh/list.d.ts +2 -0
- package/dist/cmd/auth/ssh/list.d.ts.map +1 -0
- package/dist/cmd/auth/whoami.d.ts +2 -0
- package/dist/cmd/auth/whoami.d.ts.map +1 -0
- package/dist/cmd/bundle/ast.d.ts +14 -3
- package/dist/cmd/bundle/ast.d.ts.map +1 -1
- package/dist/cmd/bundle/ast.test.d.ts +2 -0
- package/dist/cmd/bundle/ast.test.d.ts.map +1 -0
- package/dist/cmd/bundle/bundler.d.ts +6 -1
- package/dist/cmd/bundle/bundler.d.ts.map +1 -1
- package/dist/cmd/bundle/file.d.ts.map +1 -1
- package/dist/cmd/bundle/fix-duplicate-exports.d.ts +2 -0
- package/dist/cmd/bundle/fix-duplicate-exports.d.ts.map +1 -0
- package/dist/cmd/bundle/fix-duplicate-exports.test.d.ts +2 -0
- package/dist/cmd/bundle/fix-duplicate-exports.test.d.ts.map +1 -0
- package/dist/cmd/bundle/index.d.ts +1 -1
- package/dist/cmd/bundle/index.d.ts.map +1 -1
- package/dist/cmd/bundle/plugin.d.ts +2 -0
- package/dist/cmd/bundle/plugin.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -0
- package/dist/cmd/cloud/domain.d.ts +17 -0
- package/dist/cmd/cloud/domain.d.ts.map +1 -0
- package/dist/cmd/cloud/index.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/add.d.ts +2 -0
- package/dist/cmd/cloud/resource/add.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/delete.d.ts +2 -0
- package/dist/cmd/cloud/resource/delete.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/index.d.ts +3 -0
- package/dist/cmd/cloud/resource/index.d.ts.map +1 -0
- package/dist/cmd/cloud/resource/list.d.ts +2 -0
- package/dist/cmd/cloud/resource/list.d.ts.map +1 -0
- package/dist/cmd/cloud/scp/download.d.ts +2 -0
- package/dist/cmd/cloud/scp/download.d.ts.map +1 -0
- package/dist/cmd/cloud/scp/index.d.ts +3 -0
- package/dist/cmd/cloud/scp/index.d.ts.map +1 -0
- package/dist/cmd/cloud/scp/upload.d.ts +2 -0
- package/dist/cmd/cloud/scp/upload.d.ts.map +1 -0
- package/dist/cmd/cloud/ssh.d.ts +2 -0
- package/dist/cmd/cloud/ssh.d.ts.map +1 -0
- package/dist/cmd/dev/api.d.ts +18 -0
- package/dist/cmd/dev/api.d.ts.map +1 -0
- package/dist/cmd/dev/download.d.ts +11 -0
- package/dist/cmd/dev/download.d.ts.map +1 -0
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/templates.d.ts +3 -0
- package/dist/cmd/dev/templates.d.ts.map +1 -0
- package/dist/cmd/env/delete.d.ts +2 -0
- package/dist/cmd/env/delete.d.ts.map +1 -0
- package/dist/cmd/env/get.d.ts +2 -0
- package/dist/cmd/env/get.d.ts.map +1 -0
- package/dist/cmd/env/import.d.ts +2 -0
- package/dist/cmd/env/import.d.ts.map +1 -0
- package/dist/cmd/env/index.d.ts +2 -0
- package/dist/cmd/env/index.d.ts.map +1 -0
- package/dist/cmd/env/list.d.ts.map +1 -0
- package/dist/cmd/env/pull.d.ts +2 -0
- package/dist/cmd/env/pull.d.ts.map +1 -0
- package/dist/cmd/env/push.d.ts +2 -0
- package/dist/cmd/env/push.d.ts.map +1 -0
- package/dist/cmd/env/set.d.ts +2 -0
- package/dist/cmd/env/set.d.ts.map +1 -0
- package/dist/cmd/profile/show.d.ts.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/delete.d.ts.map +1 -1
- package/dist/cmd/project/download.d.ts +1 -1
- package/dist/cmd/project/download.d.ts.map +1 -1
- package/dist/cmd/project/list.d.ts.map +1 -1
- package/dist/cmd/project/show.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.d.ts +5 -1
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/secret/delete.d.ts +2 -0
- package/dist/cmd/secret/delete.d.ts.map +1 -0
- package/dist/cmd/secret/get.d.ts +2 -0
- package/dist/cmd/secret/get.d.ts.map +1 -0
- package/dist/cmd/secret/import.d.ts +2 -0
- package/dist/cmd/secret/import.d.ts.map +1 -0
- package/dist/cmd/secret/index.d.ts +2 -0
- package/dist/cmd/secret/index.d.ts.map +1 -0
- package/dist/cmd/secret/list.d.ts +2 -0
- package/dist/cmd/secret/list.d.ts.map +1 -0
- package/dist/cmd/secret/pull.d.ts +2 -0
- package/dist/cmd/secret/pull.d.ts.map +1 -0
- package/dist/cmd/secret/push.d.ts +2 -0
- package/dist/cmd/secret/push.d.ts.map +1 -0
- package/dist/cmd/secret/set.d.ts +2 -0
- package/dist/cmd/secret/set.d.ts.map +1 -0
- package/dist/cmd/version/index.d.ts.map +1 -1
- package/dist/config.d.ts +11 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/crypto/box.d.ts +65 -0
- package/dist/crypto/box.d.ts.map +1 -0
- package/dist/crypto/box.test.d.ts +2 -0
- package/dist/crypto/box.test.d.ts.map +1 -0
- package/dist/download.d.ts.map +1 -1
- package/dist/env-util.d.ts +67 -0
- package/dist/env-util.d.ts.map +1 -0
- package/dist/env-util.test.d.ts +2 -0
- package/dist/env-util.test.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/schema-parser.d.ts.map +1 -1
- package/dist/steps.d.ts +4 -1
- package/dist/steps.d.ts.map +1 -1
- package/dist/terminal.d.ts.map +1 -1
- package/dist/tui.d.ts +32 -2
- package/dist/tui.d.ts.map +1 -1
- package/dist/types.d.ts +250 -127
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/detectSubagent.d.ts +15 -0
- package/dist/utils/detectSubagent.d.ts.map +1 -0
- package/dist/utils/zip.d.ts +7 -0
- package/dist/utils/zip.d.ts.map +1 -0
- package/package.json +11 -3
- package/src/api-errors.md +2 -2
- package/src/api.ts +12 -7
- package/src/auth.ts +116 -7
- package/src/banner.ts +13 -6
- package/src/cli.ts +709 -36
- package/src/cmd/auth/api.ts +10 -16
- package/src/cmd/auth/index.ts +3 -1
- package/src/cmd/auth/login.ts +24 -8
- package/src/cmd/auth/signup.ts +15 -11
- package/src/cmd/auth/ssh/add.ts +263 -0
- package/src/cmd/auth/ssh/api.ts +94 -0
- package/src/cmd/auth/ssh/delete.ts +102 -0
- package/src/cmd/auth/ssh/index.ts +10 -0
- package/src/cmd/auth/ssh/list.ts +74 -0
- package/src/cmd/auth/whoami.ts +69 -0
- package/src/cmd/bundle/ast.test.ts +565 -0
- package/src/cmd/bundle/ast.ts +457 -44
- package/src/cmd/bundle/bundler.ts +255 -57
- package/src/cmd/bundle/file.ts +6 -12
- package/src/cmd/bundle/fix-duplicate-exports.test.ts +387 -0
- package/src/cmd/bundle/fix-duplicate-exports.ts +204 -0
- package/src/cmd/bundle/index.ts +11 -11
- package/src/cmd/bundle/patch/aisdk.ts +1 -1
- package/src/cmd/bundle/plugin.ts +373 -53
- package/src/cmd/cloud/deploy.ts +336 -0
- package/src/cmd/cloud/domain.ts +92 -0
- package/src/cmd/cloud/index.ts +11 -0
- package/src/cmd/cloud/resource/add.ts +56 -0
- package/src/cmd/cloud/resource/delete.ts +120 -0
- package/src/cmd/cloud/resource/index.ts +11 -0
- package/src/cmd/cloud/resource/list.ts +69 -0
- package/src/cmd/cloud/scp/download.ts +59 -0
- package/src/cmd/cloud/scp/index.ts +9 -0
- package/src/cmd/cloud/scp/upload.ts +62 -0
- package/src/cmd/cloud/ssh.ts +68 -0
- package/src/cmd/dev/api.ts +46 -0
- package/src/cmd/dev/download.ts +111 -0
- package/src/cmd/dev/index.ts +362 -34
- package/src/cmd/dev/templates.ts +84 -0
- package/src/cmd/env/delete.ts +47 -0
- package/src/cmd/env/get.ts +53 -0
- package/src/cmd/env/import.ts +102 -0
- package/src/cmd/env/index.ts +22 -0
- package/src/cmd/env/list.ts +56 -0
- package/src/cmd/env/pull.ts +80 -0
- package/src/cmd/env/push.ts +37 -0
- package/src/cmd/env/set.ts +71 -0
- package/src/cmd/index.ts +2 -2
- package/src/cmd/profile/show.ts +15 -6
- package/src/cmd/project/create.ts +7 -2
- package/src/cmd/project/delete.ts +75 -18
- package/src/cmd/project/download.ts +3 -3
- package/src/cmd/project/list.ts +8 -8
- package/src/cmd/project/show.ts +3 -7
- package/src/cmd/project/template-flow.ts +186 -48
- package/src/cmd/secret/delete.ts +40 -0
- package/src/cmd/secret/get.ts +54 -0
- package/src/cmd/secret/import.ts +64 -0
- package/src/cmd/secret/index.ts +22 -0
- package/src/cmd/secret/list.ts +56 -0
- package/src/cmd/secret/pull.ts +78 -0
- package/src/cmd/secret/push.ts +37 -0
- package/src/cmd/secret/set.ts +45 -0
- package/src/cmd/version/index.ts +2 -1
- package/src/config.ts +257 -27
- package/src/crypto/box.test.ts +431 -0
- package/src/crypto/box.ts +477 -0
- package/src/download.ts +1 -0
- package/src/env-util.test.ts +194 -0
- package/src/env-util.ts +290 -0
- package/src/index.ts +5 -1
- package/src/schema-parser.ts +2 -3
- package/src/steps.ts +144 -10
- package/src/terminal.ts +24 -23
- package/src/tui.ts +208 -68
- package/src/types.ts +292 -202
- package/src/utils/detectSubagent.ts +31 -0
- package/src/utils/zip.ts +38 -0
- package/dist/cmd/example/create-user.d.ts +0 -2
- package/dist/cmd/example/create-user.d.ts.map +0 -1
- package/dist/cmd/example/create.d.ts +0 -2
- package/dist/cmd/example/create.d.ts.map +0 -1
- package/dist/cmd/example/deploy.d.ts.map +0 -1
- package/dist/cmd/example/index.d.ts.map +0 -1
- package/dist/cmd/example/list.d.ts.map +0 -1
- package/dist/cmd/example/optional-auth.d.ts +0 -3
- package/dist/cmd/example/optional-auth.d.ts.map +0 -1
- package/dist/cmd/example/run-command.d.ts +0 -2
- package/dist/cmd/example/run-command.d.ts.map +0 -1
- package/dist/cmd/example/sound.d.ts +0 -3
- package/dist/cmd/example/sound.d.ts.map +0 -1
- package/dist/cmd/example/spinner.d.ts +0 -2
- package/dist/cmd/example/spinner.d.ts.map +0 -1
- package/dist/cmd/example/steps.d.ts +0 -2
- package/dist/cmd/example/steps.d.ts.map +0 -1
- package/dist/cmd/example/version.d.ts +0 -2
- package/dist/cmd/example/version.d.ts.map +0 -1
- package/dist/logger.d.ts +0 -24
- package/dist/logger.d.ts.map +0 -1
- package/src/cmd/example/create-user.ts +0 -38
- package/src/cmd/example/create.ts +0 -31
- package/src/cmd/example/deploy.ts +0 -36
- package/src/cmd/example/index.ts +0 -29
- package/src/cmd/example/list.ts +0 -32
- package/src/cmd/example/optional-auth.ts +0 -38
- package/src/cmd/example/run-command.ts +0 -45
- package/src/cmd/example/sound.ts +0 -14
- package/src/cmd/example/spinner.ts +0 -44
- package/src/cmd/example/steps.ts +0 -66
- package/src/cmd/example/version.ts +0 -13
- package/src/logger.ts +0 -235
- /package/dist/cmd/{example → cloud}/deploy.d.ts +0 -0
- /package/dist/cmd/{example → cloud}/index.d.ts +0 -0
- /package/dist/cmd/{example → env}/list.d.ts +0 -0
package/src/cmd/bundle/ast.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as acornLoose from 'acorn-loose';
|
|
2
2
|
import { basename, dirname, relative } from 'node:path';
|
|
3
3
|
import { generate } from 'astring';
|
|
4
|
-
import { BuildMetadata } from '../../types';
|
|
4
|
+
import type { BuildMetadata } from '../../types';
|
|
5
|
+
import { createLogger } from '@agentuity/server';
|
|
5
6
|
|
|
6
7
|
interface ASTNode {
|
|
7
8
|
type: string;
|
|
@@ -32,6 +33,7 @@ interface ASTObjectExpression extends ASTNode {
|
|
|
32
33
|
|
|
33
34
|
interface ASTLiteral extends ASTNode {
|
|
34
35
|
value: string;
|
|
36
|
+
raw?: string;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
interface ASTMemberExpression extends ASTNode {
|
|
@@ -46,6 +48,11 @@ interface ASTExpressionStatement extends ASTNode {
|
|
|
46
48
|
expression: ASTCallExpression;
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
interface ASTVariableDeclarator extends ASTNode {
|
|
52
|
+
id: ASTNode;
|
|
53
|
+
init?: ASTNode;
|
|
54
|
+
}
|
|
55
|
+
|
|
49
56
|
function parseObjectExpressionToMap(expr: ASTObjectExpression): Map<string, string> {
|
|
50
57
|
const result = new Map<string, string>();
|
|
51
58
|
for (const prop of expr.properties) {
|
|
@@ -97,20 +104,47 @@ function createNewMetadataNode() {
|
|
|
97
104
|
};
|
|
98
105
|
}
|
|
99
106
|
|
|
100
|
-
const projectId = process.env.AGENTUITY_CLOUD_PROJECT_ID ?? '';
|
|
101
|
-
|
|
102
107
|
function hash(...val: string[]): string {
|
|
103
108
|
const hasher = new Bun.CryptoHasher('sha256');
|
|
104
|
-
val.
|
|
109
|
+
val.map((val) => hasher.update(val));
|
|
105
110
|
return hasher.digest().toHex();
|
|
106
111
|
}
|
|
107
112
|
|
|
108
|
-
function
|
|
109
|
-
|
|
113
|
+
function hashSHA1(...val: string[]): string {
|
|
114
|
+
const hasher = new Bun.CryptoHasher('sha1');
|
|
115
|
+
val.map((val) => hasher.update(val));
|
|
116
|
+
return hasher.digest().toHex();
|
|
110
117
|
}
|
|
111
118
|
|
|
112
|
-
function
|
|
113
|
-
|
|
119
|
+
function getAgentId(
|
|
120
|
+
projectId: string,
|
|
121
|
+
deploymentId: string,
|
|
122
|
+
filename: string,
|
|
123
|
+
version: string
|
|
124
|
+
): string {
|
|
125
|
+
return `agent_${hashSHA1(projectId, deploymentId, filename, version)}`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function getEvalId(
|
|
129
|
+
projectId: string,
|
|
130
|
+
deploymentId: string,
|
|
131
|
+
filename: string,
|
|
132
|
+
name: string,
|
|
133
|
+
version: string
|
|
134
|
+
): string {
|
|
135
|
+
return `eval_${hashSHA1(projectId, deploymentId, filename, name, version)}`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function generateRouteId(
|
|
139
|
+
projectId: string,
|
|
140
|
+
deploymentId: string,
|
|
141
|
+
type: string,
|
|
142
|
+
method: string,
|
|
143
|
+
filename: string,
|
|
144
|
+
path: string,
|
|
145
|
+
version: string
|
|
146
|
+
): string {
|
|
147
|
+
return `route_${hashSHA1(projectId, deploymentId, type, method, filename, path, version)}`;
|
|
114
148
|
}
|
|
115
149
|
|
|
116
150
|
type AcornParseResultType = ReturnType<typeof acornLoose.parse>;
|
|
@@ -121,7 +155,8 @@ function augmentAgentMetadataNode(
|
|
|
121
155
|
rel: string,
|
|
122
156
|
version: string,
|
|
123
157
|
ast: AcornParseResultType,
|
|
124
|
-
propvalue: ASTObjectExpression
|
|
158
|
+
propvalue: ASTObjectExpression,
|
|
159
|
+
_filename: string
|
|
125
160
|
): [string, Map<string, string>] {
|
|
126
161
|
const metadata = parseObjectExpressionToMap(propvalue);
|
|
127
162
|
if (!metadata.has('name')) {
|
|
@@ -138,7 +173,10 @@ function augmentAgentMetadataNode(
|
|
|
138
173
|
createObjectPropertyNode('identifier', name),
|
|
139
174
|
createObjectPropertyNode('filename', rel)
|
|
140
175
|
);
|
|
176
|
+
|
|
141
177
|
const newsource = generate(ast);
|
|
178
|
+
|
|
179
|
+
// Evals imports are now handled in registry.generated.ts
|
|
142
180
|
return [newsource, metadata];
|
|
143
181
|
}
|
|
144
182
|
|
|
@@ -148,7 +186,8 @@ function createAgentMetadataNode(
|
|
|
148
186
|
rel: string,
|
|
149
187
|
version: string,
|
|
150
188
|
ast: AcornParseResultType,
|
|
151
|
-
callargexp: ASTObjectExpression
|
|
189
|
+
callargexp: ASTObjectExpression,
|
|
190
|
+
_filename: string
|
|
152
191
|
): [string, Map<string, string>] {
|
|
153
192
|
const newmetadata = createNewMetadataNode();
|
|
154
193
|
const md = new Map<string, string>();
|
|
@@ -161,21 +200,303 @@ function createAgentMetadataNode(
|
|
|
161
200
|
newmetadata.value.properties.push(createObjectPropertyNode(key, value));
|
|
162
201
|
}
|
|
163
202
|
callargexp.properties.push(newmetadata);
|
|
203
|
+
|
|
164
204
|
const newsource = generate(ast);
|
|
205
|
+
|
|
206
|
+
// Evals imports are now handled in registry.generated.ts
|
|
165
207
|
return [newsource, md];
|
|
166
208
|
}
|
|
167
209
|
|
|
168
|
-
|
|
210
|
+
function camelToKebab(str: string): string {
|
|
211
|
+
return str
|
|
212
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
213
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
|
214
|
+
.toLowerCase();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function setLiteralValue(literal: ASTLiteral, value: string) {
|
|
218
|
+
literal.value = value;
|
|
219
|
+
if (literal.raw !== undefined) {
|
|
220
|
+
literal.raw = JSON.stringify(value);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function augmentEvalMetadataNode(
|
|
225
|
+
id: string,
|
|
226
|
+
name: string,
|
|
227
|
+
rel: string,
|
|
228
|
+
version: string,
|
|
229
|
+
identifier: string,
|
|
230
|
+
metadataObj: ASTObjectExpression
|
|
231
|
+
): void {
|
|
232
|
+
// Check if id, version, identifier, filename already exist
|
|
233
|
+
const existingKeys = new Set<string>();
|
|
234
|
+
for (const prop of metadataObj.properties) {
|
|
235
|
+
if (prop.key.type === 'Identifier') {
|
|
236
|
+
existingKeys.add(prop.key.name);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Add or update metadata properties
|
|
241
|
+
if (!existingKeys.has('id')) {
|
|
242
|
+
metadataObj.properties.push(createObjectPropertyNode('id', id));
|
|
243
|
+
} else {
|
|
244
|
+
// Update existing id
|
|
245
|
+
for (const prop of metadataObj.properties) {
|
|
246
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'id') {
|
|
247
|
+
if (prop.value.type === 'Literal') {
|
|
248
|
+
setLiteralValue(prop.value as ASTLiteral, id);
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (!existingKeys.has('version')) {
|
|
256
|
+
metadataObj.properties.push(createObjectPropertyNode('version', version));
|
|
257
|
+
} else {
|
|
258
|
+
for (const prop of metadataObj.properties) {
|
|
259
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'version') {
|
|
260
|
+
if (prop.value.type === 'Literal') {
|
|
261
|
+
setLiteralValue(prop.value as ASTLiteral, version);
|
|
262
|
+
}
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (!existingKeys.has('identifier')) {
|
|
269
|
+
metadataObj.properties.push(createObjectPropertyNode('identifier', identifier));
|
|
270
|
+
} else {
|
|
271
|
+
for (const prop of metadataObj.properties) {
|
|
272
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'identifier') {
|
|
273
|
+
if (prop.value.type === 'Literal') {
|
|
274
|
+
setLiteralValue(prop.value as ASTLiteral, identifier);
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (!existingKeys.has('filename')) {
|
|
282
|
+
metadataObj.properties.push(createObjectPropertyNode('filename', rel));
|
|
283
|
+
} else {
|
|
284
|
+
for (const prop of metadataObj.properties) {
|
|
285
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'filename') {
|
|
286
|
+
if (prop.value.type === 'Literal') {
|
|
287
|
+
setLiteralValue(prop.value as ASTLiteral, rel);
|
|
288
|
+
}
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function parseEvalMetadata(
|
|
169
296
|
rootDir: string,
|
|
170
297
|
filename: string,
|
|
171
|
-
contents: string
|
|
172
|
-
|
|
298
|
+
contents: string,
|
|
299
|
+
projectId: string,
|
|
300
|
+
deploymentId: string
|
|
301
|
+
): [
|
|
302
|
+
string,
|
|
303
|
+
Array<{
|
|
304
|
+
filename: string;
|
|
305
|
+
id: string;
|
|
306
|
+
version: string;
|
|
307
|
+
identifier: string;
|
|
308
|
+
name: string;
|
|
309
|
+
description?: string;
|
|
310
|
+
}>,
|
|
311
|
+
] {
|
|
312
|
+
const logLevel = (process.env.AGENTUITY_LOG_LEVEL || 'info') as
|
|
313
|
+
| 'trace'
|
|
314
|
+
| 'debug'
|
|
315
|
+
| 'info'
|
|
316
|
+
| 'warn'
|
|
317
|
+
| 'error';
|
|
318
|
+
const logger = createLogger(logLevel);
|
|
319
|
+
logger.trace(`Parsing evals from ${filename}`);
|
|
320
|
+
const ast = acornLoose.parse(contents, { ecmaVersion: 'latest', sourceType: 'module' });
|
|
321
|
+
const rel = relative(rootDir, filename);
|
|
322
|
+
const dir = dirname(filename);
|
|
323
|
+
const identifier = basename(dir);
|
|
324
|
+
const version = hash(contents);
|
|
325
|
+
const evals: Array<{
|
|
326
|
+
filename: string;
|
|
327
|
+
id: string;
|
|
328
|
+
version: string;
|
|
329
|
+
identifier: string;
|
|
330
|
+
name: string;
|
|
331
|
+
description?: string;
|
|
332
|
+
}> = [];
|
|
333
|
+
|
|
334
|
+
// Find all agent.createEval() calls
|
|
335
|
+
for (const body of ast.body) {
|
|
336
|
+
let variableDeclaration: { declarations: Array<ASTVariableDeclarator> } | undefined;
|
|
337
|
+
|
|
338
|
+
// Handle both direct VariableDeclaration and ExportNamedDeclaration
|
|
339
|
+
if (body.type === 'VariableDeclaration') {
|
|
340
|
+
variableDeclaration = body as { declarations: Array<ASTVariableDeclarator> };
|
|
341
|
+
} else if (body.type === 'ExportNamedDeclaration') {
|
|
342
|
+
const exportDecl = body as {
|
|
343
|
+
declaration?: { type: string; declarations?: Array<ASTVariableDeclarator> };
|
|
344
|
+
};
|
|
345
|
+
if (exportDecl.declaration?.type === 'VariableDeclaration') {
|
|
346
|
+
variableDeclaration = exportDecl.declaration as {
|
|
347
|
+
declarations: Array<ASTVariableDeclarator>;
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (variableDeclaration) {
|
|
353
|
+
for (const vardecl of variableDeclaration.declarations) {
|
|
354
|
+
if (vardecl.type === 'VariableDeclarator' && vardecl.init?.type === 'CallExpression') {
|
|
355
|
+
const call = vardecl.init as ASTCallExpression;
|
|
356
|
+
if (call.callee.type === 'MemberExpression') {
|
|
357
|
+
const memberExpr = call.callee as ASTMemberExpression;
|
|
358
|
+
const object = memberExpr.object as ASTNodeIdentifier;
|
|
359
|
+
const property = memberExpr.property as ASTNodeIdentifier;
|
|
360
|
+
if (
|
|
361
|
+
object.type === 'Identifier' &&
|
|
362
|
+
object.name === 'agent' &&
|
|
363
|
+
property.type === 'Identifier' &&
|
|
364
|
+
property.name === 'createEval'
|
|
365
|
+
) {
|
|
366
|
+
// Found agent.createEval() call
|
|
367
|
+
if (call.arguments.length > 0) {
|
|
368
|
+
const firstArg = call.arguments[0] as ASTNode;
|
|
369
|
+
if (firstArg.type === 'ObjectExpression') {
|
|
370
|
+
const evalConfig = firstArg as ASTObjectExpression;
|
|
371
|
+
let evalName: string | undefined;
|
|
372
|
+
let evalDescription: string | undefined;
|
|
373
|
+
let variableName: string | undefined;
|
|
374
|
+
let metadataObj: ASTObjectExpression | undefined;
|
|
375
|
+
|
|
376
|
+
// Capture variable name if available
|
|
377
|
+
if (vardecl.id.type === 'Identifier') {
|
|
378
|
+
variableName = (vardecl.id as ASTNodeIdentifier).name;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Extract metadata from the eval config
|
|
382
|
+
for (const prop of evalConfig.properties) {
|
|
383
|
+
if (prop.key.type === 'Identifier' && prop.key.name === 'metadata') {
|
|
384
|
+
if (prop.value.type === 'ObjectExpression') {
|
|
385
|
+
metadataObj = prop.value as ASTObjectExpression;
|
|
386
|
+
for (const metaProp of metadataObj.properties) {
|
|
387
|
+
if (metaProp.key.type === 'Identifier') {
|
|
388
|
+
if (
|
|
389
|
+
metaProp.key.name === 'name' &&
|
|
390
|
+
metaProp.value.type === 'Literal'
|
|
391
|
+
) {
|
|
392
|
+
evalName = (metaProp.value as ASTLiteral).value;
|
|
393
|
+
} else if (
|
|
394
|
+
metaProp.key.name === 'description' &&
|
|
395
|
+
metaProp.value.type === 'Literal'
|
|
396
|
+
) {
|
|
397
|
+
evalDescription = (metaProp.value as ASTLiteral).value;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Use metadata.name if provided, otherwise use variable name
|
|
406
|
+
// Throw error if neither is available (should never happen)
|
|
407
|
+
let finalName: string;
|
|
408
|
+
if (evalName) {
|
|
409
|
+
finalName = evalName;
|
|
410
|
+
} else if (variableName) {
|
|
411
|
+
finalName = camelToKebab(variableName);
|
|
412
|
+
} else {
|
|
413
|
+
throw new Error(
|
|
414
|
+
'Eval is missing a name. Please provide metadata.name or use a named export.'
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
logger.trace(
|
|
419
|
+
`Found eval: ${finalName}${evalDescription ? ` - ${evalDescription}` : ''}`
|
|
420
|
+
);
|
|
421
|
+
const evalId = getEvalId(
|
|
422
|
+
projectId,
|
|
423
|
+
deploymentId,
|
|
424
|
+
rel,
|
|
425
|
+
finalName,
|
|
426
|
+
version
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
// Inject metadata into AST if metadata object exists
|
|
430
|
+
if (metadataObj) {
|
|
431
|
+
augmentEvalMetadataNode(
|
|
432
|
+
evalId,
|
|
433
|
+
finalName,
|
|
434
|
+
rel,
|
|
435
|
+
version,
|
|
436
|
+
identifier,
|
|
437
|
+
metadataObj
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
evals.push({
|
|
442
|
+
filename: rel,
|
|
443
|
+
id: evalId,
|
|
444
|
+
version,
|
|
445
|
+
identifier,
|
|
446
|
+
name: finalName,
|
|
447
|
+
description: evalDescription,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Check for duplicate eval names in the same file
|
|
459
|
+
// This prevents hash collisions when projectId/deploymentId are empty
|
|
460
|
+
const seenNames = new Map<string, number>();
|
|
461
|
+
for (const evalItem of evals) {
|
|
462
|
+
const count = seenNames.get(evalItem.name) || 0;
|
|
463
|
+
seenNames.set(evalItem.name, count + 1);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const duplicates: string[] = [];
|
|
467
|
+
for (const [name, count] of seenNames.entries()) {
|
|
468
|
+
if (count > 1) {
|
|
469
|
+
duplicates.push(name);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (duplicates.length > 0) {
|
|
474
|
+
throw new Error(
|
|
475
|
+
`Duplicate eval names found in ${rel}: ${duplicates.join(', ')}. ` +
|
|
476
|
+
'Eval names must be unique within the same file to prevent ID collisions.'
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const newsource = generate(ast);
|
|
481
|
+
logger.trace(`Parsed ${evals.length} eval(s) from ${filename}`);
|
|
482
|
+
return [newsource, evals];
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
export async function parseAgentMetadata(
|
|
486
|
+
rootDir: string,
|
|
487
|
+
filename: string,
|
|
488
|
+
contents: string,
|
|
489
|
+
projectId: string,
|
|
490
|
+
deploymentId: string
|
|
491
|
+
): Promise<[string, Map<string, string>]> {
|
|
173
492
|
const ast = acornLoose.parse(contents, { ecmaVersion: 'latest', sourceType: 'module' });
|
|
174
493
|
let exportName: string | undefined;
|
|
175
494
|
const rel = relative(rootDir, filename);
|
|
176
495
|
const name = basename(dirname(filename));
|
|
177
|
-
const id = getAgentId(name);
|
|
178
496
|
const version = hash(contents);
|
|
497
|
+
const id = getAgentId(projectId, deploymentId, rel, version);
|
|
498
|
+
|
|
499
|
+
let result: [string, Map<string, string>] | undefined;
|
|
179
500
|
|
|
180
501
|
for (const body of ast.body) {
|
|
181
502
|
if (body.type === 'ExportDefaultDeclaration') {
|
|
@@ -186,52 +507,85 @@ export function parseAgentMetadata(
|
|
|
186
507
|
const callargexp = callarg as ASTObjectExpression;
|
|
187
508
|
for (const prop of callargexp.properties) {
|
|
188
509
|
if (prop.key.type === 'Identifier' && prop.key.name === 'metadata') {
|
|
189
|
-
|
|
510
|
+
result = augmentAgentMetadataNode(
|
|
190
511
|
id,
|
|
191
512
|
name,
|
|
192
513
|
rel,
|
|
193
514
|
version,
|
|
194
515
|
ast,
|
|
195
|
-
prop.value as ASTObjectExpression
|
|
516
|
+
prop.value as ASTObjectExpression,
|
|
517
|
+
filename
|
|
196
518
|
);
|
|
519
|
+
break;
|
|
197
520
|
}
|
|
198
521
|
}
|
|
199
|
-
|
|
522
|
+
if (!result) {
|
|
523
|
+
result = createAgentMetadataNode(
|
|
524
|
+
id,
|
|
525
|
+
name,
|
|
526
|
+
rel,
|
|
527
|
+
version,
|
|
528
|
+
ast,
|
|
529
|
+
callargexp,
|
|
530
|
+
filename
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
break;
|
|
200
534
|
}
|
|
201
535
|
}
|
|
202
536
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
537
|
+
if (!result) {
|
|
538
|
+
const identifier = body.declaration as ASTNodeIdentifier;
|
|
539
|
+
exportName = identifier.name;
|
|
540
|
+
break;
|
|
541
|
+
}
|
|
206
542
|
}
|
|
207
543
|
}
|
|
208
|
-
if (!exportName) {
|
|
544
|
+
if (!result && !exportName) {
|
|
209
545
|
throw new Error(`could not find default export for ${filename} using ${rootDir}`);
|
|
210
546
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
547
|
+
if (!result) {
|
|
548
|
+
for (const body of ast.body) {
|
|
549
|
+
if (body.type === 'VariableDeclaration') {
|
|
550
|
+
for (const vardecl of body.declarations) {
|
|
551
|
+
if (vardecl.type === 'VariableDeclarator' && vardecl.id.type === 'Identifier') {
|
|
552
|
+
const identifier = vardecl.id as ASTNodeIdentifier;
|
|
553
|
+
if (identifier.name === exportName) {
|
|
554
|
+
if (vardecl.init?.type === 'CallExpression') {
|
|
555
|
+
const call = vardecl.init as ASTCallExpression;
|
|
556
|
+
if (call.callee.name === 'createAgent') {
|
|
557
|
+
for (const callarg of call.arguments) {
|
|
558
|
+
const callargexp = callarg as ASTObjectExpression;
|
|
559
|
+
for (const prop of callargexp.properties) {
|
|
560
|
+
if (
|
|
561
|
+
prop.key.type === 'Identifier' &&
|
|
562
|
+
prop.key.name === 'metadata'
|
|
563
|
+
) {
|
|
564
|
+
result = augmentAgentMetadataNode(
|
|
565
|
+
id,
|
|
566
|
+
name,
|
|
567
|
+
rel,
|
|
568
|
+
version,
|
|
569
|
+
ast,
|
|
570
|
+
prop.value as ASTObjectExpression,
|
|
571
|
+
filename
|
|
572
|
+
);
|
|
573
|
+
break;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (!result) {
|
|
577
|
+
result = createAgentMetadataNode(
|
|
225
578
|
id,
|
|
226
579
|
name,
|
|
227
580
|
rel,
|
|
228
581
|
version,
|
|
229
582
|
ast,
|
|
230
|
-
|
|
583
|
+
callargexp,
|
|
584
|
+
filename
|
|
231
585
|
);
|
|
232
586
|
}
|
|
587
|
+
break;
|
|
233
588
|
}
|
|
234
|
-
return createAgentMetadataNode(id, name, rel, version, ast, callargexp);
|
|
235
589
|
}
|
|
236
590
|
}
|
|
237
591
|
}
|
|
@@ -240,16 +594,56 @@ export function parseAgentMetadata(
|
|
|
240
594
|
}
|
|
241
595
|
}
|
|
242
596
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
597
|
+
if (!result) {
|
|
598
|
+
throw new Error(
|
|
599
|
+
`error parsing: ${filename}. could not find an proper createAgent defined in this file`
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Parse evals from eval.ts file in the same directory
|
|
604
|
+
const logLevel = (process.env.AGENTUITY_LOG_LEVEL || 'info') as
|
|
605
|
+
| 'trace'
|
|
606
|
+
| 'debug'
|
|
607
|
+
| 'info'
|
|
608
|
+
| 'warn'
|
|
609
|
+
| 'error';
|
|
610
|
+
const logger = createLogger(logLevel);
|
|
611
|
+
const agentDir = dirname(filename);
|
|
612
|
+
const evalsPath = `${agentDir}/eval.ts`;
|
|
613
|
+
logger.trace(`Checking for evals file at ${evalsPath}`);
|
|
614
|
+
const evalsFile = Bun.file(evalsPath);
|
|
615
|
+
if (await evalsFile.exists()) {
|
|
616
|
+
logger.trace(`Found evals file at ${evalsPath}, parsing...`);
|
|
617
|
+
const evalsSource = await evalsFile.text();
|
|
618
|
+
const transpiler = new Bun.Transpiler({ loader: 'ts' });
|
|
619
|
+
const evalsContents = transpiler.transformSync(evalsSource);
|
|
620
|
+
const [, evals] = parseEvalMetadata(
|
|
621
|
+
rootDir,
|
|
622
|
+
evalsPath,
|
|
623
|
+
evalsContents,
|
|
624
|
+
projectId,
|
|
625
|
+
deploymentId
|
|
626
|
+
);
|
|
627
|
+
if (evals.length > 0) {
|
|
628
|
+
logger.trace(`Adding ${evals.length} eval(s) to agent metadata for ${name}`);
|
|
629
|
+
result[1].set('evals', JSON.stringify(evals));
|
|
630
|
+
} else {
|
|
631
|
+
logger.trace(`No evals found in ${evalsPath}`);
|
|
632
|
+
}
|
|
633
|
+
} else {
|
|
634
|
+
logger.trace(`No evals file found at ${evalsPath}`);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
return result;
|
|
246
638
|
}
|
|
247
639
|
|
|
248
640
|
type RouteDefinition = BuildMetadata['routes'];
|
|
249
641
|
|
|
250
642
|
export async function parseRoute(
|
|
251
643
|
rootDir: string,
|
|
252
|
-
filename: string
|
|
644
|
+
filename: string,
|
|
645
|
+
projectId: string,
|
|
646
|
+
deploymentId: string
|
|
253
647
|
): Promise<BuildMetadata['routes']> {
|
|
254
648
|
const contents = await Bun.file(filename).text();
|
|
255
649
|
const version = hash(contents);
|
|
@@ -291,7 +685,17 @@ export async function parseRoute(
|
|
|
291
685
|
}
|
|
292
686
|
|
|
293
687
|
const rel = relative(rootDir, filename);
|
|
294
|
-
const
|
|
688
|
+
const dir = dirname(filename);
|
|
689
|
+
const name = basename(dir);
|
|
690
|
+
|
|
691
|
+
// Detect if this is a subagent route and build proper path
|
|
692
|
+
const relativePath = relative(rootDir, dir)
|
|
693
|
+
.replace(/^src\/agents\//, '')
|
|
694
|
+
.replace(/^src\/apis\//, '');
|
|
695
|
+
const pathParts = relativePath.split('/').filter(Boolean);
|
|
696
|
+
const isSubagent = pathParts.length === 2 && filename.includes('src/agents');
|
|
697
|
+
const routeName = isSubagent ? pathParts.join('/') : name;
|
|
698
|
+
|
|
295
699
|
const routes: RouteDefinition = [];
|
|
296
700
|
const routePrefix = filename.includes('src/agents') ? '/agent' : '/api';
|
|
297
701
|
|
|
@@ -376,11 +780,20 @@ export async function parseRoute(
|
|
|
376
780
|
break;
|
|
377
781
|
}
|
|
378
782
|
}
|
|
379
|
-
const thepath = `${routePrefix}/${
|
|
783
|
+
const thepath = `${routePrefix}/${routeName}/${suffix}`
|
|
380
784
|
.replaceAll(/\/{2,}/g, '/')
|
|
381
785
|
.replaceAll(/\/$/g, '');
|
|
786
|
+
const id = generateRouteId(
|
|
787
|
+
projectId,
|
|
788
|
+
deploymentId,
|
|
789
|
+
type,
|
|
790
|
+
method,
|
|
791
|
+
rel,
|
|
792
|
+
thepath,
|
|
793
|
+
version
|
|
794
|
+
);
|
|
382
795
|
routes.push({
|
|
383
|
-
id
|
|
796
|
+
id,
|
|
384
797
|
method: method as 'get' | 'post' | 'put' | 'delete' | 'patch',
|
|
385
798
|
type: type as 'api' | 'sms' | 'email' | 'cron',
|
|
386
799
|
filename: rel,
|