@agentuity/cli 0.0.48 → 0.0.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/bin/cli.ts +26 -5
  2. package/dist/banner.d.ts +1 -1
  3. package/dist/banner.d.ts.map +1 -1
  4. package/dist/cli-logger.d.ts +27 -0
  5. package/dist/cli-logger.d.ts.map +1 -0
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cmd/auth/index.d.ts.map +1 -1
  8. package/dist/cmd/auth/login.d.ts.map +1 -1
  9. package/dist/cmd/auth/logout.d.ts.map +1 -1
  10. package/dist/cmd/auth/signup.d.ts.map +1 -1
  11. package/dist/cmd/auth/ssh/add.d.ts.map +1 -1
  12. package/dist/cmd/auth/ssh/delete.d.ts.map +1 -1
  13. package/dist/cmd/auth/ssh/index.d.ts +1 -2
  14. package/dist/cmd/auth/ssh/index.d.ts.map +1 -1
  15. package/dist/cmd/auth/ssh/list.d.ts.map +1 -1
  16. package/dist/cmd/auth/whoami.d.ts.map +1 -1
  17. package/dist/cmd/bundle/ast.d.ts.map +1 -1
  18. package/dist/cmd/bundle/index.d.ts.map +1 -1
  19. package/dist/cmd/bundle/plugin.d.ts.map +1 -1
  20. package/dist/cmd/capabilities/index.d.ts +4 -0
  21. package/dist/cmd/capabilities/index.d.ts.map +1 -0
  22. package/dist/cmd/capabilities/show.d.ts +20 -0
  23. package/dist/cmd/capabilities/show.d.ts.map +1 -0
  24. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  25. package/dist/cmd/cloud/deployment/index.d.ts.map +1 -1
  26. package/dist/cmd/cloud/deployment/list.d.ts.map +1 -1
  27. package/dist/cmd/cloud/deployment/remove.d.ts.map +1 -1
  28. package/dist/cmd/cloud/deployment/rollback.d.ts.map +1 -1
  29. package/dist/cmd/cloud/deployment/show.d.ts.map +1 -1
  30. package/dist/cmd/cloud/deployment/undeploy.d.ts.map +1 -1
  31. package/dist/cmd/cloud/deployment/utils.d.ts +4 -2
  32. package/dist/cmd/cloud/deployment/utils.d.ts.map +1 -1
  33. package/dist/cmd/cloud/domain.d.ts.map +1 -1
  34. package/dist/cmd/cloud/index.d.ts.map +1 -1
  35. package/dist/cmd/cloud/resource/add.d.ts.map +1 -1
  36. package/dist/cmd/cloud/resource/delete.d.ts.map +1 -1
  37. package/dist/cmd/cloud/resource/index.d.ts +1 -2
  38. package/dist/cmd/cloud/resource/index.d.ts.map +1 -1
  39. package/dist/cmd/cloud/resource/list.d.ts.map +1 -1
  40. package/dist/cmd/cloud/scp/download.d.ts.map +1 -1
  41. package/dist/cmd/cloud/scp/index.d.ts +1 -2
  42. package/dist/cmd/cloud/scp/index.d.ts.map +1 -1
  43. package/dist/cmd/cloud/scp/upload.d.ts.map +1 -1
  44. package/dist/cmd/cloud/ssh.d.ts.map +1 -1
  45. package/dist/cmd/dev/index.d.ts.map +1 -1
  46. package/dist/cmd/env/delete.d.ts.map +1 -1
  47. package/dist/cmd/env/get.d.ts.map +1 -1
  48. package/dist/cmd/env/import.d.ts.map +1 -1
  49. package/dist/cmd/env/index.d.ts.map +1 -1
  50. package/dist/cmd/env/list.d.ts.map +1 -1
  51. package/dist/cmd/env/pull.d.ts.map +1 -1
  52. package/dist/cmd/env/push.d.ts.map +1 -1
  53. package/dist/cmd/env/set.d.ts.map +1 -1
  54. package/dist/cmd/index.d.ts.map +1 -1
  55. package/dist/cmd/kv/create-namespace.d.ts +3 -0
  56. package/dist/cmd/kv/create-namespace.d.ts.map +1 -0
  57. package/dist/cmd/kv/delete-namespace.d.ts +3 -0
  58. package/dist/cmd/kv/delete-namespace.d.ts.map +1 -0
  59. package/dist/cmd/kv/delete.d.ts +3 -0
  60. package/dist/cmd/kv/delete.d.ts.map +1 -0
  61. package/dist/cmd/kv/get.d.ts +3 -0
  62. package/dist/cmd/kv/get.d.ts.map +1 -0
  63. package/dist/cmd/kv/index.d.ts +2 -0
  64. package/dist/cmd/kv/index.d.ts.map +1 -0
  65. package/dist/cmd/kv/keys.d.ts +3 -0
  66. package/dist/cmd/kv/keys.d.ts.map +1 -0
  67. package/dist/cmd/kv/list-namespaces.d.ts +3 -0
  68. package/dist/cmd/kv/list-namespaces.d.ts.map +1 -0
  69. package/dist/cmd/kv/repl.d.ts +3 -0
  70. package/dist/cmd/kv/repl.d.ts.map +1 -0
  71. package/dist/cmd/kv/search.d.ts +3 -0
  72. package/dist/cmd/kv/search.d.ts.map +1 -0
  73. package/dist/cmd/kv/set.d.ts +3 -0
  74. package/dist/cmd/kv/set.d.ts.map +1 -0
  75. package/dist/cmd/kv/stats.d.ts +3 -0
  76. package/dist/cmd/kv/stats.d.ts.map +1 -0
  77. package/dist/cmd/kv/util.d.ts +8 -0
  78. package/dist/cmd/kv/util.d.ts.map +1 -0
  79. package/dist/cmd/objectstore/delete-bucket.d.ts +3 -0
  80. package/dist/cmd/objectstore/delete-bucket.d.ts.map +1 -0
  81. package/dist/cmd/objectstore/delete.d.ts +3 -0
  82. package/dist/cmd/objectstore/delete.d.ts.map +1 -0
  83. package/dist/cmd/objectstore/get.d.ts +3 -0
  84. package/dist/cmd/objectstore/get.d.ts.map +1 -0
  85. package/dist/cmd/objectstore/index.d.ts +2 -0
  86. package/dist/cmd/objectstore/index.d.ts.map +1 -0
  87. package/dist/cmd/objectstore/list-buckets.d.ts +3 -0
  88. package/dist/cmd/objectstore/list-buckets.d.ts.map +1 -0
  89. package/dist/cmd/objectstore/list-keys.d.ts +3 -0
  90. package/dist/cmd/objectstore/list-keys.d.ts.map +1 -0
  91. package/dist/cmd/objectstore/put.d.ts +3 -0
  92. package/dist/cmd/objectstore/put.d.ts.map +1 -0
  93. package/dist/cmd/objectstore/repl.d.ts +3 -0
  94. package/dist/cmd/objectstore/repl.d.ts.map +1 -0
  95. package/dist/cmd/objectstore/url.d.ts +3 -0
  96. package/dist/cmd/objectstore/url.d.ts.map +1 -0
  97. package/dist/cmd/objectstore/util.d.ts +8 -0
  98. package/dist/cmd/objectstore/util.d.ts.map +1 -0
  99. package/dist/cmd/profile/create.d.ts.map +1 -1
  100. package/dist/cmd/profile/delete.d.ts.map +1 -1
  101. package/dist/cmd/profile/index.d.ts.map +1 -1
  102. package/dist/cmd/profile/list.d.ts +1 -2
  103. package/dist/cmd/profile/list.d.ts.map +1 -1
  104. package/dist/cmd/profile/show.d.ts.map +1 -1
  105. package/dist/cmd/profile/use.d.ts.map +1 -1
  106. package/dist/cmd/project/create.d.ts.map +1 -1
  107. package/dist/cmd/project/delete.d.ts.map +1 -1
  108. package/dist/cmd/project/index.d.ts.map +1 -1
  109. package/dist/cmd/project/list.d.ts.map +1 -1
  110. package/dist/cmd/project/show.d.ts.map +1 -1
  111. package/dist/cmd/project/template-flow.d.ts +1 -1
  112. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  113. package/dist/cmd/prompt/index.d.ts +4 -0
  114. package/dist/cmd/prompt/index.d.ts.map +1 -0
  115. package/dist/cmd/prompt/llm.d.ts +3 -0
  116. package/dist/cmd/prompt/llm.d.ts.map +1 -0
  117. package/dist/cmd/repl/index.d.ts +3 -0
  118. package/dist/cmd/repl/index.d.ts.map +1 -0
  119. package/dist/cmd/schema/index.d.ts +4 -0
  120. package/dist/cmd/schema/index.d.ts.map +1 -0
  121. package/dist/cmd/schema/show.d.ts +3 -0
  122. package/dist/cmd/schema/show.d.ts.map +1 -0
  123. package/dist/cmd/secret/delete.d.ts.map +1 -1
  124. package/dist/cmd/secret/get.d.ts.map +1 -1
  125. package/dist/cmd/secret/import.d.ts.map +1 -1
  126. package/dist/cmd/secret/index.d.ts.map +1 -1
  127. package/dist/cmd/secret/list.d.ts.map +1 -1
  128. package/dist/cmd/secret/pull.d.ts.map +1 -1
  129. package/dist/cmd/secret/push.d.ts.map +1 -1
  130. package/dist/cmd/secret/set.d.ts.map +1 -1
  131. package/dist/cmd/version/index.d.ts.map +1 -1
  132. package/dist/config.d.ts +1 -1
  133. package/dist/config.d.ts.map +1 -1
  134. package/dist/errors.d.ts +83 -0
  135. package/dist/errors.d.ts.map +1 -0
  136. package/dist/explain.d.ts +47 -0
  137. package/dist/explain.d.ts.map +1 -0
  138. package/dist/index.d.ts +6 -0
  139. package/dist/index.d.ts.map +1 -1
  140. package/dist/json.d.ts +3 -0
  141. package/dist/json.d.ts.map +1 -0
  142. package/dist/output.d.ts +136 -0
  143. package/dist/output.d.ts.map +1 -0
  144. package/dist/repl.d.ts +124 -0
  145. package/dist/repl.d.ts.map +1 -0
  146. package/dist/schema-generator.d.ts +67 -0
  147. package/dist/schema-generator.d.ts.map +1 -0
  148. package/dist/tui.d.ts +11 -1
  149. package/dist/tui.d.ts.map +1 -1
  150. package/dist/types.d.ts +65 -6
  151. package/dist/types.d.ts.map +1 -1
  152. package/package.json +9 -4
  153. package/src/banner.ts +7 -7
  154. package/src/cli-logger.ts +80 -0
  155. package/src/cli.ts +186 -54
  156. package/src/cmd/auth/index.ts +1 -0
  157. package/src/cmd/auth/login.ts +7 -2
  158. package/src/cmd/auth/logout.ts +4 -0
  159. package/src/cmd/auth/signup.ts +7 -2
  160. package/src/cmd/auth/ssh/add.ts +20 -3
  161. package/src/cmd/auth/ssh/delete.ts +57 -4
  162. package/src/cmd/auth/ssh/index.ts +4 -3
  163. package/src/cmd/auth/ssh/list.ts +29 -12
  164. package/src/cmd/auth/whoami.ts +32 -21
  165. package/src/cmd/bundle/ast.ts +27 -5
  166. package/src/cmd/bundle/index.ts +20 -0
  167. package/src/cmd/bundle/plugin.ts +36 -12
  168. package/src/cmd/capabilities/index.ts +12 -0
  169. package/src/cmd/capabilities/show.ts +256 -0
  170. package/src/cmd/cloud/deploy.ts +54 -0
  171. package/src/cmd/cloud/deployment/index.ts +1 -0
  172. package/src/cmd/cloud/deployment/list.ts +50 -3
  173. package/src/cmd/cloud/deployment/remove.ts +26 -2
  174. package/src/cmd/cloud/deployment/rollback.ts +35 -4
  175. package/src/cmd/cloud/deployment/show.ts +37 -2
  176. package/src/cmd/cloud/deployment/undeploy.ts +12 -1
  177. package/src/cmd/cloud/deployment/utils.ts +5 -2
  178. package/src/cmd/cloud/domain.ts +3 -2
  179. package/src/cmd/cloud/index.ts +8 -1
  180. package/src/cmd/cloud/resource/add.ts +19 -0
  181. package/src/cmd/cloud/resource/delete.ts +24 -3
  182. package/src/cmd/cloud/resource/index.ts +4 -3
  183. package/src/cmd/cloud/resource/list.ts +36 -10
  184. package/src/cmd/cloud/scp/download.ts +27 -1
  185. package/src/cmd/cloud/scp/index.ts +4 -3
  186. package/src/cmd/cloud/scp/upload.ts +27 -1
  187. package/src/cmd/cloud/ssh.ts +12 -0
  188. package/src/cmd/dev/index.ts +11 -7
  189. package/src/cmd/dev/templates.ts +1 -1
  190. package/src/cmd/env/delete.ts +17 -0
  191. package/src/cmd/env/get.ts +17 -1
  192. package/src/cmd/env/import.ts +47 -3
  193. package/src/cmd/env/index.ts +1 -0
  194. package/src/cmd/env/list.ts +13 -1
  195. package/src/cmd/env/pull.ts +20 -0
  196. package/src/cmd/env/push.ts +33 -1
  197. package/src/cmd/env/set.ts +25 -1
  198. package/src/cmd/index.ts +9 -2
  199. package/src/cmd/kv/create-namespace.ts +45 -0
  200. package/src/cmd/kv/delete-namespace.ts +73 -0
  201. package/src/cmd/kv/delete.ts +51 -0
  202. package/src/cmd/kv/get.ts +65 -0
  203. package/src/cmd/kv/index.ts +31 -0
  204. package/src/cmd/kv/keys.ts +57 -0
  205. package/src/cmd/kv/list-namespaces.ts +43 -0
  206. package/src/cmd/kv/repl.ts +284 -0
  207. package/src/cmd/kv/search.ts +80 -0
  208. package/src/cmd/kv/set.ts +63 -0
  209. package/src/cmd/kv/stats.ts +96 -0
  210. package/src/cmd/kv/util.ts +32 -0
  211. package/src/cmd/objectstore/delete-bucket.ts +72 -0
  212. package/src/cmd/objectstore/delete.ts +59 -0
  213. package/src/cmd/objectstore/get.ts +64 -0
  214. package/src/cmd/objectstore/index.ts +27 -0
  215. package/src/cmd/objectstore/list-buckets.ts +45 -0
  216. package/src/cmd/objectstore/list-keys.ts +60 -0
  217. package/src/cmd/objectstore/put.ts +62 -0
  218. package/src/cmd/objectstore/repl.ts +235 -0
  219. package/src/cmd/objectstore/url.ts +59 -0
  220. package/src/cmd/objectstore/util.ts +28 -0
  221. package/src/cmd/profile/create.ts +28 -2
  222. package/src/cmd/profile/delete.ts +17 -2
  223. package/src/cmd/profile/index.ts +1 -0
  224. package/src/cmd/profile/list.ts +7 -3
  225. package/src/cmd/profile/show.ts +20 -5
  226. package/src/cmd/profile/use.ts +8 -0
  227. package/src/cmd/project/create.ts +31 -0
  228. package/src/cmd/project/delete.ts +24 -2
  229. package/src/cmd/project/index.ts +1 -0
  230. package/src/cmd/project/list.ts +23 -9
  231. package/src/cmd/project/show.ts +27 -8
  232. package/src/cmd/project/template-flow.ts +10 -6
  233. package/src/cmd/prompt/index.ts +12 -0
  234. package/src/cmd/prompt/llm.ts +368 -0
  235. package/src/cmd/repl/index.ts +477 -0
  236. package/src/cmd/schema/index.ts +12 -0
  237. package/src/cmd/schema/show.ts +27 -0
  238. package/src/cmd/secret/delete.ts +17 -0
  239. package/src/cmd/secret/get.ts +20 -1
  240. package/src/cmd/secret/import.ts +45 -2
  241. package/src/cmd/secret/index.ts +1 -0
  242. package/src/cmd/secret/list.ts +10 -1
  243. package/src/cmd/secret/pull.ts +20 -0
  244. package/src/cmd/secret/push.ts +33 -1
  245. package/src/cmd/secret/set.ts +20 -0
  246. package/src/cmd/version/index.ts +15 -2
  247. package/src/config.ts +17 -4
  248. package/src/errors.ts +222 -0
  249. package/src/explain.ts +126 -0
  250. package/src/index.ts +51 -0
  251. package/src/json.ts +28 -0
  252. package/src/output.ts +307 -0
  253. package/src/repl.ts +1517 -0
  254. package/src/schema-generator.ts +389 -0
  255. package/src/tui.ts +84 -13
  256. package/src/types.ts +62 -12
@@ -1,40 +1,56 @@
1
1
  import { createSubcommand } from '../../../types';
2
2
  import { listSSHKeys } from './api';
3
3
  import * as tui from '../../../tui';
4
- import { z } from 'zod';
5
4
  import { Table } from 'console-table-printer';
5
+ import { getCommand } from '../../../command-prefix';
6
+ import { ErrorCode } from '../../../errors';
7
+ import { z } from 'zod';
8
+
9
+ const SSHListResponseSchema = z.array(
10
+ z.object({
11
+ id: z.string().describe('SSH key ID'),
12
+ fingerprint: z.string().describe('SSH key fingerprint'),
13
+ keyType: z.string().describe('SSH key type (e.g., ssh-rsa, ssh-ed25519)'),
14
+ comment: z.string().optional().describe('SSH key comment'),
15
+ createdAt: z.string().optional().describe('Creation timestamp'),
16
+ })
17
+ );
6
18
 
7
19
  export const listCommand = createSubcommand({
8
20
  name: 'list',
9
21
  aliases: ['ls'],
10
22
  description: 'List all SSH keys on your account',
23
+ tags: ['read-only', 'fast', 'requires-auth'],
11
24
  requires: { apiClient: true, auth: true },
25
+ idempotent: true,
26
+ examples: [
27
+ getCommand('auth ssh list'),
28
+ getCommand('auth ssh ls'),
29
+ getCommand('--json auth ssh list'),
30
+ ],
12
31
  schema: {
13
- options: z.object({
14
- format: z.enum(['text', 'json']).default('text').describe('output format'),
15
- }),
32
+ response: SSHListResponseSchema,
16
33
  },
17
34
  async handler(ctx) {
18
- const { logger, apiClient, opts } = ctx;
19
- const format = opts.format;
35
+ const { logger, apiClient, options } = ctx;
20
36
 
21
37
  if (!apiClient) {
22
- logger.fatal('API client is not available');
38
+ logger.fatal('API client is not available', ErrorCode.INTERNAL_ERROR);
23
39
  }
24
40
 
25
41
  try {
26
42
  const keys = await tui.spinner('Fetching SSH keys...', () => listSSHKeys(apiClient));
27
43
 
28
- if (format === 'json') {
44
+ if (options.json) {
29
45
  console.log(JSON.stringify(keys, null, 2));
30
- return;
46
+ return keys;
31
47
  }
32
48
 
33
49
  tui.newline();
34
50
 
35
51
  if (keys.length === 0) {
36
52
  console.log('No SSH keys found');
37
- return;
53
+ return [];
38
54
  }
39
55
 
40
56
  console.log(tui.bold('SSH Keys:'));
@@ -57,12 +73,13 @@ export const listCommand = createSubcommand({
57
73
  }
58
74
  table.printTable();
59
75
 
76
+ return keys;
60
77
  } catch (error) {
61
78
  logger.trace(error);
62
79
  if (error instanceof Error) {
63
- logger.fatal(`Failed to list SSH keys: ${error.message}`);
80
+ logger.fatal(`Failed to list SSH keys: ${error.message}`, ErrorCode.API_ERROR);
64
81
  } else {
65
- logger.fatal('Failed to list SSH keys');
82
+ logger.fatal('Failed to list SSH keys', ErrorCode.API_ERROR);
66
83
  }
67
84
  }
68
85
  },
@@ -1,23 +1,36 @@
1
- import { z } from 'zod';
2
1
  import { createSubcommand } from '../../types';
3
2
  import * as tui from '../../tui';
4
3
  import { whoami } from '@agentuity/server';
4
+ import { getCommand } from '../../command-prefix';
5
+ import { z } from 'zod';
6
+
7
+ const WhoamiResponseSchema = z.object({
8
+ userId: z.string().describe('Unique user identifier'),
9
+ firstName: z.string().describe('User first name'),
10
+ lastName: z.string().describe('User last name'),
11
+ organizations: z
12
+ .array(
13
+ z.object({
14
+ id: z.string().describe('Organization ID'),
15
+ name: z.string().describe('Organization name'),
16
+ })
17
+ )
18
+ .describe('Organizations the user belongs to'),
19
+ });
5
20
 
6
21
  export const whoamiCommand = createSubcommand({
7
22
  name: 'whoami',
8
23
  description: 'Display information about the currently authenticated user',
24
+ tags: ['read-only', 'fast', 'requires-auth'],
9
25
  requires: { auth: true, apiClient: true },
26
+ idempotent: true,
10
27
  schema: {
11
- options: z.object({
12
- format: z
13
- .enum(['json', 'table'])
14
- .optional()
15
- .describe('the output format: json, table (default)'),
16
- }),
28
+ response: WhoamiResponseSchema,
17
29
  },
30
+ examples: [getCommand('auth whoami'), getCommand('--json auth whoami')],
18
31
 
19
32
  async handler(ctx) {
20
- const { apiClient, opts, auth } = ctx;
33
+ const { apiClient, auth, options } = ctx;
21
34
 
22
35
  if (!apiClient) {
23
36
  throw new Error(
@@ -33,19 +46,15 @@ export const whoamiCommand = createSubcommand({
33
46
  },
34
47
  });
35
48
 
36
- if (opts?.format === 'json') {
37
- console.log(
38
- JSON.stringify(
39
- {
40
- userId: auth?.userId,
41
- firstName: user.firstName,
42
- lastName: user.lastName,
43
- organizations: user.organizations,
44
- },
45
- null,
46
- 2
47
- )
48
- );
49
+ const result = {
50
+ userId: auth?.userId || '',
51
+ firstName: user.firstName,
52
+ lastName: user.lastName,
53
+ organizations: user.organizations,
54
+ };
55
+
56
+ if (options.json) {
57
+ console.log(JSON.stringify(result, null, 2));
49
58
  } else {
50
59
  const fullName = `${user.firstName} ${user.lastName}`;
51
60
 
@@ -65,5 +74,7 @@ export const whoamiCommand = createSubcommand({
65
74
  }
66
75
  tui.newline();
67
76
  }
77
+
78
+ return result;
68
79
  },
69
80
  });
@@ -147,31 +147,51 @@ function generateRouteId(
147
147
  return `route_${hashSHA1(projectId, deploymentId, type, method, filename, path, version)}`;
148
148
  }
149
149
 
150
+ function generateStableAgentId(projectId: string, name: string): string {
151
+ return `agentid_${hashSHA1(projectId, name)}`.substring(0, 64);
152
+ }
153
+
150
154
  type AcornParseResultType = ReturnType<typeof acornLoose.parse>;
151
155
 
152
156
  function augmentAgentMetadataNode(
157
+ projectId: string,
153
158
  id: string,
154
159
  name: string,
155
160
  rel: string,
156
161
  version: string,
157
162
  ast: AcornParseResultType,
158
163
  propvalue: ASTObjectExpression,
159
- _filename: string
164
+ filename: string
160
165
  ): [string, Map<string, string>] {
161
166
  const metadata = parseObjectExpressionToMap(propvalue);
162
167
  if (!metadata.has('name')) {
163
- metadata.set('name', name);
164
- propvalue.properties.push(createObjectPropertyNode('name', name));
168
+ const location = ast.loc?.start ? ` on line ${ast.loc.start}` : '';
169
+ throw new Error(
170
+ `missing required metadata.name in ${filename}${location}. This Agent should have a unique and human readable name for this project.`
171
+ );
172
+ }
173
+ if (metadata.has('identifier') && name !== metadata.get('identifier')) {
174
+ const location = ast.loc?.start ? ` on line ${ast.loc.start}` : '';
175
+ throw new Error(
176
+ `metadata.identifier (${metadata.get('identifier')}) in ${filename}${location} is mismatched (${name}). This is an internal error.`
177
+ );
165
178
  }
179
+ const descriptionNode = propvalue.properties.find((x) => x.key.name === 'description')?.value;
180
+ const description = descriptionNode ? (descriptionNode as ASTLiteral).value : '';
181
+ const agentId = generateStableAgentId(projectId, name);
166
182
  metadata.set('version', version);
167
183
  metadata.set('identifier', name);
168
184
  metadata.set('filename', rel);
169
185
  metadata.set('id', id);
186
+ metadata.set('agentId', agentId);
187
+ metadata.set('description', description);
170
188
  propvalue.properties.push(
171
189
  createObjectPropertyNode('id', id),
190
+ createObjectPropertyNode('agentId', agentId),
172
191
  createObjectPropertyNode('version', version),
173
192
  createObjectPropertyNode('identifier', name),
174
- createObjectPropertyNode('filename', rel)
193
+ createObjectPropertyNode('filename', rel),
194
+ createObjectPropertyNode('description', description)
175
195
  );
176
196
 
177
197
  const newsource = generate(ast);
@@ -508,6 +528,7 @@ export async function parseAgentMetadata(
508
528
  for (const prop of callargexp.properties) {
509
529
  if (prop.key.type === 'Identifier' && prop.key.name === 'metadata') {
510
530
  result = augmentAgentMetadataNode(
531
+ projectId,
511
532
  id,
512
533
  name,
513
534
  rel,
@@ -562,6 +583,7 @@ export async function parseAgentMetadata(
562
583
  prop.key.name === 'metadata'
563
584
  ) {
564
585
  result = augmentAgentMetadataNode(
586
+ projectId,
565
587
  id,
566
588
  name,
567
589
  rel,
@@ -615,7 +637,7 @@ export async function parseAgentMetadata(
615
637
  if (await evalsFile.exists()) {
616
638
  logger.trace(`Found evals file at ${evalsPath}, parsing...`);
617
639
  const evalsSource = await evalsFile.text();
618
- const transpiler = new Bun.Transpiler({ loader: 'ts' });
640
+ const transpiler = new Bun.Transpiler({ loader: 'ts', target: 'bun' });
619
641
  const evalsContents = transpiler.transformSync(evalsSource);
620
642
  const [, evals] = parseEvalMetadata(
621
643
  rootDir,
@@ -2,16 +2,29 @@ import { createCommand } from '../../types';
2
2
  import { z } from 'zod';
3
3
  import { bundle } from './bundler';
4
4
  import * as tui from '../../tui';
5
+ import { getCommand } from '../../command-prefix';
6
+
7
+ const BundleResponseSchema = z.object({
8
+ success: z.boolean().describe('Whether the bundle succeeded'),
9
+ bundlePath: z.string().describe('Path to the bundle directory'),
10
+ projectName: z.string().describe('Project name'),
11
+ dev: z.boolean().describe('Whether dev mode was enabled'),
12
+ size: z.number().optional().describe('Bundle size in bytes'),
13
+ });
5
14
 
6
15
  export const command = createCommand({
7
16
  name: 'bundle',
8
17
  description: 'Bundle Agentuity application for deployment',
18
+ tags: ['read-only', 'slow', 'requires-project'],
9
19
  aliases: ['build'],
10
20
  optional: { project: true },
21
+ idempotent: false,
22
+ examples: [getCommand('bundle'), getCommand('bundle --dev'), getCommand('build')],
11
23
  schema: {
12
24
  options: z.object({
13
25
  dev: z.boolean().optional().describe('Enable development mode'),
14
26
  }),
27
+ response: BundleResponseSchema,
15
28
  },
16
29
 
17
30
  async handler(ctx) {
@@ -27,6 +40,13 @@ export const command = createCommand({
27
40
  });
28
41
 
29
42
  tui.success('Bundle complete');
43
+
44
+ return {
45
+ success: true,
46
+ bundlePath: `${projectDir}/.agentuity`,
47
+ projectName: project?.projectId || 'unknown',
48
+ dev: opts.dev || false,
49
+ };
30
50
  } catch (error) {
31
51
  if (error instanceof Error) {
32
52
  tui.fatal(`Bundle failed: ${error.message}`);
@@ -266,7 +266,7 @@ const AgentuityBundler: BunPlugin = {
266
266
  string,
267
267
  Map<string, string>
268
268
  >();
269
- const transpiler = new Bun.Transpiler({ loader: 'ts' });
269
+ const transpiler = new Bun.Transpiler({ loader: 'ts', target: 'bun' });
270
270
  let routeDefinitions: BuildMetadata['routes'] = [];
271
271
 
272
272
  build.onResolve({ filter: /\/route\.ts$/, namespace: 'file' }, async (args) => {
@@ -312,6 +312,16 @@ const AgentuityBundler: BunPlugin = {
312
312
  md.set('parent', parentName);
313
313
  }
314
314
 
315
+ const newAgentName = md.get('name');
316
+ for (const [, kv] of agentMetadata) {
317
+ const found = kv.get('name');
318
+ if (newAgentName === found) {
319
+ throw new Error(
320
+ `The agent in ${kv.get('filename')} and the agent in ${md.get('filename')} have the same name (${found}). Agent Names must be unique within a project.`
321
+ );
322
+ }
323
+ }
324
+
315
325
  agentMetadata.set(md.get('identifier')!, md);
316
326
  }
317
327
  return {
@@ -413,6 +423,7 @@ const AgentuityBundler: BunPlugin = {
413
423
  filename: md.get('filename')!,
414
424
  identifier: md.get('identifier')!,
415
425
  description: md.get('description') ?? '',
426
+ agentId: md.get('agentId')!,
416
427
  };
417
428
  if (isSubagent && parentName) {
418
429
  agentDetail.parent = parentName;
@@ -473,20 +484,31 @@ const AgentuityBundler: BunPlugin = {
473
484
  generateAgentRegistry(srcDir, agentInfo);
474
485
  }
475
486
 
487
+ // create the workbench routes
488
+ inserts.push(`await (async() => {
489
+ const { createWorkbenchMetadataRoute, getRouter } = await import('@agentuity/runtime');
490
+ const router = getRouter()!;
491
+ router.get('/_agentuity/workbench/metadata.json', createWorkbenchMetadataRoute());
492
+ })();`);
493
+
476
494
  const file = Bun.file(args.path);
477
495
  let contents = await file.text();
478
496
  let inserted = false;
479
- const index = contents.indexOf(' createApp(');
480
- if (index > 0) {
481
- const endSemi = contents.indexOf(');', index);
482
- if (endSemi > 0) {
483
- contents =
484
- contents.slice(0, endSemi + 2) +
485
- '\n\n' +
486
- inserts.join('\n') +
487
- contents.slice(endSemi + 2);
488
- inserted = true;
489
- }
497
+ let index = contents.indexOf(' createApp(');
498
+ if (index < 0) {
499
+ index = contents.indexOf(' createApp (');
500
+ }
501
+ if (index < 0) {
502
+ throw new Error(`couldn't find the required createApp function in ${args.path}`);
503
+ }
504
+ const endSemi = contents.indexOf(');', index);
505
+ if (endSemi > 0) {
506
+ contents =
507
+ contents.slice(0, endSemi + 2) +
508
+ '\n\n' +
509
+ inserts.join('\n') +
510
+ contents.slice(endSemi + 2);
511
+ inserted = true;
490
512
  }
491
513
  if (!inserted) {
492
514
  contents += `\n${inserts.join('\n')}`;
@@ -552,6 +574,7 @@ const AgentuityBundler: BunPlugin = {
552
574
  filename: v.get('filename')!,
553
575
  id: v.get('id')!,
554
576
  identifier: v.get('identifier')!,
577
+ agentId: v.get('agentId')!,
555
578
  version: v.get('version')!,
556
579
  name: v.get('name')!,
557
580
  description: v.get('description') ?? '<no description provided>',
@@ -587,6 +610,7 @@ const AgentuityBundler: BunPlugin = {
587
610
  filename: sub.get('filename')!,
588
611
  id: sub.get('id')!,
589
612
  identifier: sub.get('identifier')!,
613
+ agentId: sub.get('agentId')!,
590
614
  version: sub.get('version')!,
591
615
  name: sub.get('name')!,
592
616
  description: sub.get('description') ?? '<no description provided>',
@@ -0,0 +1,12 @@
1
+ import type { CommandDefinition } from '../../types';
2
+ import { createCommand } from '../../types';
3
+ import { showSubcommand } from './show';
4
+
5
+ export const capabilitiesCommand: CommandDefinition = createCommand({
6
+ name: 'capabilities',
7
+ description: 'Show CLI capabilities and available tasks',
8
+ tags: ['read-only', 'fast'],
9
+ subcommands: [showSubcommand],
10
+ });
11
+
12
+ export default capabilitiesCommand;
@@ -0,0 +1,256 @@
1
+ import { createSubcommand } from '../../types';
2
+ import type { CommandContext } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { getCommand } from '../../command-prefix';
5
+ import { z } from 'zod';
6
+
7
+ export interface Capability {
8
+ id: string;
9
+ name: string;
10
+ description: string;
11
+ commands: string[];
12
+ requiresAuth?: boolean;
13
+ requiresProject?: boolean;
14
+ }
15
+
16
+ export interface CapabilitiesResponse {
17
+ version: string;
18
+ capabilities: Capability[];
19
+ workflows: Array<{
20
+ name: string;
21
+ description: string;
22
+ steps: string[];
23
+ }>;
24
+ }
25
+
26
+ const CapabilitiesShowResponseSchema = z.object({
27
+ version: z.string().describe('CLI capabilities version'),
28
+ capabilities: z
29
+ .array(
30
+ z.object({
31
+ id: z.string().describe('Capability ID'),
32
+ name: z.string().describe('Capability name'),
33
+ description: z.string().describe('Description'),
34
+ commands: z.array(z.string()).describe('Available commands'),
35
+ requiresAuth: z.boolean().optional().describe('Requires authentication'),
36
+ requiresProject: z.boolean().optional().describe('Requires project'),
37
+ })
38
+ )
39
+ .describe('Available capabilities'),
40
+ workflows: z
41
+ .array(
42
+ z.object({
43
+ name: z.string().describe('Workflow name'),
44
+ description: z.string().describe('Workflow description'),
45
+ steps: z.array(z.string()).describe('Workflow steps'),
46
+ })
47
+ )
48
+ .describe('Common workflows'),
49
+ });
50
+
51
+ export const showSubcommand = createSubcommand({
52
+ name: 'show',
53
+ description: 'Display CLI capabilities',
54
+ tags: ['read-only', 'fast'],
55
+ examples: [getCommand('capabilities show'), getCommand('--json capabilities show')],
56
+ schema: {
57
+ response: CapabilitiesShowResponseSchema,
58
+ },
59
+ idempotent: true,
60
+ async handler(ctx: CommandContext) {
61
+ const { options } = ctx;
62
+
63
+ const capabilities: CapabilitiesResponse = {
64
+ version: '1.0.0',
65
+ capabilities: [
66
+ {
67
+ id: 'auth',
68
+ name: 'Authentication',
69
+ description: 'Login, logout, and manage API keys',
70
+ commands: ['auth login', 'auth logout', 'auth whoami', 'auth signup'],
71
+ requiresAuth: false,
72
+ },
73
+ {
74
+ id: 'ssh',
75
+ name: 'SSH Key Management',
76
+ description: 'Manage SSH keys for secure access',
77
+ commands: ['auth ssh list', 'auth ssh add', 'auth ssh delete'],
78
+ requiresAuth: true,
79
+ },
80
+ {
81
+ id: 'project',
82
+ name: 'Project Management',
83
+ description: 'Create, list, and manage projects',
84
+ commands: [
85
+ 'project init',
86
+ 'project list',
87
+ 'project show',
88
+ 'project download',
89
+ 'project update',
90
+ 'project delete',
91
+ ],
92
+ requiresAuth: true,
93
+ },
94
+ {
95
+ id: 'deployment',
96
+ name: 'Deployment',
97
+ description: 'Deploy and manage applications',
98
+ commands: [
99
+ 'bundle',
100
+ 'cloud deploy',
101
+ 'cloud deployment list',
102
+ 'cloud deployment show',
103
+ 'cloud deployment logs',
104
+ 'cloud deployment rollback',
105
+ ],
106
+ requiresAuth: true,
107
+ requiresProject: true,
108
+ },
109
+ {
110
+ id: 'secrets',
111
+ name: 'Secrets Management',
112
+ description: 'Store and retrieve secrets securely',
113
+ commands: ['secret list', 'secret set', 'secret get', 'secret delete'],
114
+ requiresAuth: true,
115
+ requiresProject: true,
116
+ },
117
+ {
118
+ id: 'env',
119
+ name: 'Environment Variables',
120
+ description: 'Manage environment variables',
121
+ commands: ['env list', 'env set', 'env get', 'env delete'],
122
+ requiresAuth: true,
123
+ requiresProject: true,
124
+ },
125
+ {
126
+ id: 'kv',
127
+ name: 'Key-Value Storage',
128
+ description: 'Store and retrieve key-value data',
129
+ commands: ['kv list', 'kv get', 'kv set', 'kv delete', 'kv stats'],
130
+ requiresAuth: true,
131
+ requiresProject: true,
132
+ },
133
+ {
134
+ id: 'objectstore',
135
+ name: 'Object Storage',
136
+ description: 'Manage object storage buckets and files',
137
+ commands: [
138
+ 'objectstore list',
139
+ 'objectstore upload',
140
+ 'objectstore download',
141
+ 'objectstore delete',
142
+ ],
143
+ requiresAuth: true,
144
+ requiresProject: true,
145
+ },
146
+ {
147
+ id: 'resources',
148
+ name: 'Cloud Resources',
149
+ description: 'View and manage cloud resources',
150
+ commands: ['cloud resource list'],
151
+ requiresAuth: true,
152
+ },
153
+ {
154
+ id: 'config',
155
+ name: 'Configuration',
156
+ description: 'Manage CLI profiles and configuration',
157
+ commands: [
158
+ 'profile list',
159
+ 'profile create',
160
+ 'profile delete',
161
+ 'profile show',
162
+ 'profile switch',
163
+ ],
164
+ },
165
+ {
166
+ id: 'dev',
167
+ name: 'Development',
168
+ description: 'Local development server and REPL',
169
+ commands: ['dev', 'repl'],
170
+ requiresProject: true,
171
+ },
172
+ {
173
+ id: 'introspection',
174
+ name: 'CLI Introspection',
175
+ description: 'Discover CLI structure and capabilities',
176
+ commands: ['schema show', 'capabilities show', 'version'],
177
+ },
178
+ ],
179
+ workflows: [
180
+ {
181
+ name: 'Initial Setup',
182
+ description: 'Get started with Agentuity',
183
+ steps: [
184
+ 'auth signup',
185
+ 'auth login',
186
+ 'project init',
187
+ 'secret set API_KEY <value>',
188
+ 'dev',
189
+ ],
190
+ },
191
+ {
192
+ name: 'Deploy Application',
193
+ description: 'Deploy your application to the cloud',
194
+ steps: ['bundle', 'cloud deploy', 'cloud deployment logs', 'cloud deployment show'],
195
+ },
196
+ {
197
+ name: 'Manage Secrets',
198
+ description: 'Configure application secrets',
199
+ steps: ['secret list', 'secret set <key> <value>', 'secret get <key>'],
200
+ },
201
+ {
202
+ name: 'SSH Key Setup',
203
+ description: 'Add SSH keys for secure access',
204
+ steps: ['auth ssh list', 'auth ssh add --file ~/.ssh/id_rsa.pub'],
205
+ },
206
+ ],
207
+ };
208
+
209
+ if (options.json) {
210
+ console.log(JSON.stringify(capabilities, null, 2));
211
+ } else {
212
+ // Human-readable output
213
+ console.log(tui.bold('Agentuity CLI Capabilities'));
214
+ tui.newline();
215
+
216
+ console.log(tui.bold('Available Tasks:'));
217
+ tui.newline();
218
+
219
+ for (const cap of capabilities.capabilities) {
220
+ console.log(` ${tui.bold(cap.name)}`);
221
+ console.log(` ${cap.description}`);
222
+
223
+ const requirements: string[] = [];
224
+ if (cap.requiresAuth) requirements.push('requires authentication');
225
+ if (cap.requiresProject) requirements.push('requires project');
226
+ if (requirements.length > 0) {
227
+ console.log(` ${tui.muted(`(${requirements.join(', ')})`)}`);
228
+ }
229
+
230
+ console.log(
231
+ ` ${tui.muted(`Commands: ${cap.commands.slice(0, 3).join(', ')}${cap.commands.length > 3 ? '...' : ''}`)}`
232
+ );
233
+ tui.newline();
234
+ }
235
+
236
+ console.log(tui.bold('Common Workflows:'));
237
+ tui.newline();
238
+
239
+ for (const workflow of capabilities.workflows) {
240
+ console.log(` ${tui.bold(workflow.name)}`);
241
+ console.log(` ${workflow.description}`);
242
+ console.log(` ${tui.muted('Steps:')}`);
243
+ for (let i = 0; i < workflow.steps.length; i++) {
244
+ console.log(` ${i + 1}. ${workflow.steps[i]}`);
245
+ }
246
+ tui.newline();
247
+ }
248
+
249
+ console.log(tui.muted('Tip: Use --json for machine-readable output'));
250
+ }
251
+
252
+ return capabilities;
253
+ },
254
+ });
255
+
256
+ export default showSubcommand;