@agentuity/cli 0.0.100 → 0.0.102

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 (264) hide show
  1. package/AGENTS.md +19 -188
  2. package/bin/cli.ts +13 -6
  3. package/dist/api.d.ts +1 -0
  4. package/dist/api.d.ts.map +1 -1
  5. package/dist/api.js +1 -1
  6. package/dist/api.js.map +1 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +41 -12
  9. package/dist/cli.js.map +1 -1
  10. package/dist/cmd/ai/index.d.ts.map +1 -1
  11. package/dist/cmd/ai/index.js +6 -1
  12. package/dist/cmd/ai/index.js.map +1 -1
  13. package/dist/cmd/ai/prompt/agent.d.ts +7 -0
  14. package/dist/cmd/ai/prompt/agent.d.ts.map +1 -1
  15. package/dist/cmd/ai/prompt/agent.js +12 -323
  16. package/dist/cmd/ai/prompt/agent.js.map +1 -1
  17. package/dist/cmd/ai/prompt/api.d.ts +7 -0
  18. package/dist/cmd/ai/prompt/api.d.ts.map +1 -1
  19. package/dist/cmd/ai/prompt/api.js +12 -260
  20. package/dist/cmd/ai/prompt/api.js.map +1 -1
  21. package/dist/cmd/ai/prompt/version.d.ts +35 -0
  22. package/dist/cmd/ai/prompt/version.d.ts.map +1 -0
  23. package/dist/cmd/ai/prompt/version.js +55 -0
  24. package/dist/cmd/ai/prompt/version.js.map +1 -0
  25. package/dist/cmd/ai/prompt/web.d.ts +7 -0
  26. package/dist/cmd/ai/prompt/web.d.ts.map +1 -1
  27. package/dist/cmd/ai/prompt/web.js +12 -283
  28. package/dist/cmd/ai/prompt/web.js.map +1 -1
  29. package/dist/cmd/ai/skills/generate.d.ts +3 -0
  30. package/dist/cmd/ai/skills/generate.d.ts.map +1 -0
  31. package/dist/cmd/ai/skills/generate.js +65 -0
  32. package/dist/cmd/ai/skills/generate.js.map +1 -0
  33. package/dist/cmd/ai/skills/generator.d.ts +4 -0
  34. package/dist/cmd/ai/skills/generator.d.ts.map +1 -0
  35. package/dist/cmd/ai/skills/generator.js +402 -0
  36. package/dist/cmd/ai/skills/generator.js.map +1 -0
  37. package/dist/cmd/ai/skills/index.d.ts +4 -0
  38. package/dist/cmd/ai/skills/index.d.ts.map +1 -0
  39. package/dist/cmd/ai/skills/index.js +21 -0
  40. package/dist/cmd/ai/skills/index.js.map +1 -0
  41. package/dist/cmd/auth/signup.d.ts.map +1 -1
  42. package/dist/cmd/auth/signup.js +1 -0
  43. package/dist/cmd/auth/signup.js.map +1 -1
  44. package/dist/cmd/build/ast.d.ts +2 -1
  45. package/dist/cmd/build/ast.d.ts.map +1 -1
  46. package/dist/cmd/build/ast.js +135 -47
  47. package/dist/cmd/build/ast.js.map +1 -1
  48. package/dist/cmd/build/entry-generator.d.ts.map +1 -1
  49. package/dist/cmd/build/entry-generator.js +255 -188
  50. package/dist/cmd/build/entry-generator.js.map +1 -1
  51. package/dist/cmd/build/vite/agent-discovery.d.ts.map +1 -1
  52. package/dist/cmd/build/vite/agent-discovery.js +103 -45
  53. package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
  54. package/dist/cmd/build/vite/bun-dev-server.d.ts +7 -1
  55. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
  56. package/dist/cmd/build/vite/bun-dev-server.js +52 -26
  57. package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
  58. package/dist/cmd/build/vite/docs-generator.d.ts +13 -0
  59. package/dist/cmd/build/vite/docs-generator.d.ts.map +1 -0
  60. package/dist/cmd/build/vite/docs-generator.js +81 -0
  61. package/dist/cmd/build/vite/docs-generator.js.map +1 -0
  62. package/dist/cmd/build/vite/index.d.ts +3 -3
  63. package/dist/cmd/build/vite/index.d.ts.map +1 -1
  64. package/dist/cmd/build/vite/index.js +9 -7
  65. package/dist/cmd/build/vite/index.js.map +1 -1
  66. package/dist/cmd/build/vite/lifecycle-generator.d.ts +1 -1
  67. package/dist/cmd/build/vite/lifecycle-generator.d.ts.map +1 -1
  68. package/dist/cmd/build/vite/lifecycle-generator.js +19 -5
  69. package/dist/cmd/build/vite/lifecycle-generator.js.map +1 -1
  70. package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
  71. package/dist/cmd/build/vite/metadata-generator.js +203 -7
  72. package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
  73. package/dist/cmd/build/vite/prompt-generator.d.ts +23 -0
  74. package/dist/cmd/build/vite/prompt-generator.d.ts.map +1 -0
  75. package/dist/cmd/build/vite/prompt-generator.js +123 -0
  76. package/dist/cmd/build/vite/prompt-generator.js.map +1 -0
  77. package/dist/cmd/build/vite/registry-generator.d.ts +3 -3
  78. package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
  79. package/dist/cmd/build/vite/registry-generator.js +644 -103
  80. package/dist/cmd/build/vite/registry-generator.js.map +1 -1
  81. package/dist/cmd/build/vite/route-discovery.d.ts +4 -0
  82. package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
  83. package/dist/cmd/build/vite/route-discovery.js.map +1 -1
  84. package/dist/cmd/build/vite/server-bundler.d.ts +4 -0
  85. package/dist/cmd/build/vite/server-bundler.d.ts.map +1 -1
  86. package/dist/cmd/build/vite/server-bundler.js +63 -17
  87. package/dist/cmd/build/vite/server-bundler.js.map +1 -1
  88. package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
  89. package/dist/cmd/build/vite/vite-asset-server-config.js +4 -0
  90. package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
  91. package/dist/cmd/build/vite/vite-builder.d.ts +1 -1
  92. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  93. package/dist/cmd/build/vite/vite-builder.js +118 -96
  94. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  95. package/dist/cmd/build/vite-bundler.js +6 -6
  96. package/dist/cmd/build/vite-bundler.js.map +1 -1
  97. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  98. package/dist/cmd/cloud/deploy.js +89 -32
  99. package/dist/cmd/cloud/deploy.js.map +1 -1
  100. package/dist/cmd/cloud/keyvalue/create-namespace.d.ts.map +1 -1
  101. package/dist/cmd/cloud/keyvalue/create-namespace.js +3 -1
  102. package/dist/cmd/cloud/keyvalue/create-namespace.js.map +1 -1
  103. package/dist/cmd/cloud/keyvalue/delete-namespace.d.ts.map +1 -1
  104. package/dist/cmd/cloud/keyvalue/delete-namespace.js +3 -1
  105. package/dist/cmd/cloud/keyvalue/delete-namespace.js.map +1 -1
  106. package/dist/cmd/cloud/keyvalue/delete.d.ts.map +1 -1
  107. package/dist/cmd/cloud/keyvalue/delete.js +3 -1
  108. package/dist/cmd/cloud/keyvalue/delete.js.map +1 -1
  109. package/dist/cmd/cloud/keyvalue/set.d.ts.map +1 -1
  110. package/dist/cmd/cloud/keyvalue/set.js +4 -2
  111. package/dist/cmd/cloud/keyvalue/set.js.map +1 -1
  112. package/dist/cmd/cloud/stream/get.d.ts.map +1 -1
  113. package/dist/cmd/cloud/stream/get.js +2 -13
  114. package/dist/cmd/cloud/stream/get.js.map +1 -1
  115. package/dist/cmd/cloud/vector/delete-namespace.d.ts +3 -0
  116. package/dist/cmd/cloud/vector/delete-namespace.d.ts.map +1 -0
  117. package/dist/cmd/cloud/vector/delete-namespace.js +77 -0
  118. package/dist/cmd/cloud/vector/delete-namespace.js.map +1 -0
  119. package/dist/cmd/cloud/vector/index.d.ts.map +1 -1
  120. package/dist/cmd/cloud/vector/index.js +21 -4
  121. package/dist/cmd/cloud/vector/index.js.map +1 -1
  122. package/dist/cmd/cloud/vector/list-namespaces.d.ts +3 -0
  123. package/dist/cmd/cloud/vector/list-namespaces.d.ts.map +1 -0
  124. package/dist/cmd/cloud/vector/list-namespaces.js +42 -0
  125. package/dist/cmd/cloud/vector/list-namespaces.js.map +1 -0
  126. package/dist/cmd/cloud/vector/stats.d.ts +3 -0
  127. package/dist/cmd/cloud/vector/stats.d.ts.map +1 -0
  128. package/dist/cmd/cloud/vector/stats.js +142 -0
  129. package/dist/cmd/cloud/vector/stats.js.map +1 -0
  130. package/dist/cmd/cloud/vector/upsert.d.ts +3 -0
  131. package/dist/cmd/cloud/vector/upsert.d.ts.map +1 -0
  132. package/dist/cmd/cloud/vector/upsert.js +192 -0
  133. package/dist/cmd/cloud/vector/upsert.js.map +1 -0
  134. package/dist/cmd/dev/file-watcher.d.ts.map +1 -1
  135. package/dist/cmd/dev/file-watcher.js +94 -33
  136. package/dist/cmd/dev/file-watcher.js.map +1 -1
  137. package/dist/cmd/dev/index.d.ts.map +1 -1
  138. package/dist/cmd/dev/index.js +298 -61
  139. package/dist/cmd/dev/index.js.map +1 -1
  140. package/dist/cmd/dev/skills.d.ts +10 -0
  141. package/dist/cmd/dev/skills.d.ts.map +1 -0
  142. package/dist/cmd/dev/skills.js +57 -0
  143. package/dist/cmd/dev/skills.js.map +1 -0
  144. package/dist/cmd/dev/sync.d.ts.map +1 -1
  145. package/dist/cmd/dev/sync.js +19 -3
  146. package/dist/cmd/dev/sync.js.map +1 -1
  147. package/dist/cmd/index.d.ts.map +1 -1
  148. package/dist/cmd/index.js +1 -0
  149. package/dist/cmd/index.js.map +1 -1
  150. package/dist/cmd/project/create.d.ts.map +1 -1
  151. package/dist/cmd/project/create.js +3 -0
  152. package/dist/cmd/project/create.js.map +1 -1
  153. package/dist/cmd/project/template-flow.d.ts +1 -0
  154. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  155. package/dist/cmd/project/template-flow.js +30 -5
  156. package/dist/cmd/project/template-flow.js.map +1 -1
  157. package/dist/cmd/setup/index.d.ts.map +1 -1
  158. package/dist/cmd/setup/index.js +1 -0
  159. package/dist/cmd/setup/index.js.map +1 -1
  160. package/dist/cmd/upgrade/index.d.ts +15 -0
  161. package/dist/cmd/upgrade/index.d.ts.map +1 -1
  162. package/dist/cmd/upgrade/index.js +59 -4
  163. package/dist/cmd/upgrade/index.js.map +1 -1
  164. package/dist/config.d.ts.map +1 -1
  165. package/dist/config.js +8 -0
  166. package/dist/config.js.map +1 -1
  167. package/dist/domain.d.ts +45 -0
  168. package/dist/domain.d.ts.map +1 -0
  169. package/dist/domain.js +200 -0
  170. package/dist/domain.js.map +1 -0
  171. package/dist/index.d.ts +0 -1
  172. package/dist/index.d.ts.map +1 -1
  173. package/dist/index.js +0 -1
  174. package/dist/index.js.map +1 -1
  175. package/dist/schema-generator.d.ts +2 -0
  176. package/dist/schema-generator.d.ts.map +1 -1
  177. package/dist/schema-generator.js +18 -0
  178. package/dist/schema-generator.js.map +1 -1
  179. package/dist/steps.d.ts +1 -1
  180. package/dist/steps.d.ts.map +1 -1
  181. package/dist/steps.js +16 -5
  182. package/dist/steps.js.map +1 -1
  183. package/dist/tui/prompt.d.ts +1 -2
  184. package/dist/tui/prompt.d.ts.map +1 -1
  185. package/dist/tui/prompt.js +8 -4
  186. package/dist/tui/prompt.js.map +1 -1
  187. package/dist/tui.d.ts +16 -0
  188. package/dist/tui.d.ts.map +1 -1
  189. package/dist/tui.js +23 -2
  190. package/dist/tui.js.map +1 -1
  191. package/dist/types.d.ts +9 -2
  192. package/dist/types.d.ts.map +1 -1
  193. package/dist/types.js +3 -3
  194. package/dist/types.js.map +1 -1
  195. package/package.json +5 -8
  196. package/src/api.ts +1 -1
  197. package/src/cli.ts +47 -12
  198. package/src/cmd/ai/index.ts +6 -1
  199. package/src/cmd/ai/prompt/agent.md +306 -0
  200. package/src/cmd/ai/prompt/agent.ts +12 -322
  201. package/src/cmd/ai/prompt/api.md +360 -0
  202. package/src/cmd/ai/prompt/api.ts +13 -260
  203. package/src/cmd/ai/prompt/version.ts +61 -0
  204. package/src/cmd/ai/prompt/web.md +509 -0
  205. package/src/cmd/ai/prompt/web.ts +12 -282
  206. package/src/cmd/ai/skills/generate.ts +75 -0
  207. package/src/cmd/ai/skills/generator.ts +519 -0
  208. package/src/cmd/ai/skills/index.ts +23 -0
  209. package/src/cmd/auth/signup.ts +1 -0
  210. package/src/cmd/build/ast.ts +161 -48
  211. package/src/cmd/build/entry-generator.ts +258 -187
  212. package/src/cmd/build/vite/agent-discovery.ts +151 -58
  213. package/src/cmd/build/vite/bun-dev-server.ts +57 -27
  214. package/src/cmd/build/vite/docs-generator.ts +87 -0
  215. package/src/cmd/build/vite/index.ts +9 -7
  216. package/src/cmd/build/vite/lifecycle-generator.ts +19 -5
  217. package/src/cmd/build/vite/metadata-generator.ts +251 -7
  218. package/src/cmd/build/vite/prompt-generator.ts +169 -0
  219. package/src/cmd/build/vite/registry-generator.ts +750 -108
  220. package/src/cmd/build/vite/route-discovery.ts +4 -0
  221. package/src/cmd/build/vite/server-bundler.ts +73 -23
  222. package/src/cmd/build/vite/vite-asset-server-config.ts +5 -0
  223. package/src/cmd/build/vite/vite-builder.ts +134 -100
  224. package/src/cmd/build/vite-bundler.ts +6 -6
  225. package/src/cmd/cloud/deploy.ts +114 -36
  226. package/src/cmd/cloud/keyvalue/create-namespace.ts +3 -1
  227. package/src/cmd/cloud/keyvalue/delete-namespace.ts +3 -1
  228. package/src/cmd/cloud/keyvalue/delete.ts +3 -1
  229. package/src/cmd/cloud/keyvalue/set.ts +4 -2
  230. package/src/cmd/cloud/stream/get.ts +2 -9
  231. package/src/cmd/cloud/vector/delete-namespace.ts +89 -0
  232. package/src/cmd/cloud/vector/index.ts +21 -4
  233. package/src/cmd/cloud/vector/list-namespaces.ts +46 -0
  234. package/src/cmd/cloud/vector/stats.ts +160 -0
  235. package/src/cmd/cloud/vector/upsert.ts +216 -0
  236. package/src/cmd/dev/file-watcher.ts +109 -34
  237. package/src/cmd/dev/index.ts +364 -60
  238. package/src/cmd/dev/skills.ts +82 -0
  239. package/src/cmd/dev/sync.ts +41 -6
  240. package/src/cmd/index.ts +1 -0
  241. package/src/cmd/project/create.ts +3 -0
  242. package/src/cmd/project/template-flow.ts +37 -5
  243. package/src/cmd/setup/index.ts +1 -0
  244. package/src/cmd/upgrade/index.ts +68 -4
  245. package/src/config.ts +9 -0
  246. package/src/domain.ts +273 -0
  247. package/src/index.ts +0 -5
  248. package/src/runtime-bootstrap.md +1 -1
  249. package/src/schema-generator.ts +23 -0
  250. package/src/steps.ts +16 -5
  251. package/src/tui/prompt.ts +11 -5
  252. package/src/tui.ts +21 -2
  253. package/src/types/md.d.ts +8 -0
  254. package/src/types.ts +12 -3
  255. package/dist/cmd/cloud/domain.d.ts +0 -17
  256. package/dist/cmd/cloud/domain.d.ts.map +0 -1
  257. package/dist/cmd/cloud/domain.js +0 -79
  258. package/dist/cmd/cloud/domain.js.map +0 -1
  259. package/dist/runtime-bootstrap.d.ts +0 -56
  260. package/dist/runtime-bootstrap.d.ts.map +0 -1
  261. package/dist/runtime-bootstrap.js +0 -95
  262. package/dist/runtime-bootstrap.js.map +0 -1
  263. package/src/cmd/cloud/domain.ts +0 -100
  264. package/src/runtime-bootstrap.ts +0 -131
@@ -171,9 +171,21 @@ class DevmodeSyncService implements IDevmodeSyncService {
171
171
  for (const agent of currentMetadata.agents || []) {
172
172
  if (agent.evals) {
173
173
  currentEvalCount += agent.evals.length;
174
+ this.logger.debug(
175
+ '[CLI EVAL SYNC] Agent "%s" has %d eval(s)',
176
+ agent.name,
177
+ agent.evals.length
178
+ );
179
+ for (const evalItem of agent.evals) {
180
+ this.logger.debug(
181
+ '[CLI EVAL SYNC] - %s (evalId: %s)',
182
+ evalItem.name,
183
+ evalItem.evalId
184
+ );
185
+ }
174
186
  }
175
187
  }
176
- this.logger.debug('Processing %d current eval(s)', currentEvalCount);
188
+ this.logger.debug('[CLI EVAL SYNC] Total current eval(s): %d', currentEvalCount);
177
189
 
178
190
  // Get agents and evals to sync using shared diff logic
179
191
  const { create: agentsToCreate, delete: agentsToDelete } = getAgentsToSync(
@@ -261,7 +273,14 @@ class DevmodeSyncService implements IDevmodeSyncService {
261
273
  evalsToDelete: string[],
262
274
  deploymentId: string
263
275
  ): Promise<void> {
276
+ this.logger.info(
277
+ '[CLI EVAL SYNC] syncEvals called: %d to create, %d to delete',
278
+ evals.length,
279
+ evalsToDelete.length
280
+ );
281
+
264
282
  if (evals.length === 0 && evalsToDelete.length === 0) {
283
+ this.logger.debug('[CLI EVAL SYNC] No evals to sync, skipping');
265
284
  return;
266
285
  }
267
286
 
@@ -270,12 +289,28 @@ class DevmodeSyncService implements IDevmodeSyncService {
270
289
  create: evals,
271
290
  delete: evalsToDelete,
272
291
  };
273
- this.logger.trace(
274
- '[CLI EVAL SYNC] Sending payload to POST /cli/devmode/eval: %s',
275
- JSON.stringify(payload, null, 2)
276
- );
277
292
 
278
- await this.apiClient.post('/cli/devmode/eval', payload, z.object({ success: z.boolean() }));
293
+ this.logger.debug('[CLI EVAL SYNC] Sending payload to POST /cli/devmode/eval:');
294
+ for (const evalItem of evals) {
295
+ this.logger.debug(
296
+ '[CLI EVAL SYNC] - %s (id: %s, evalId: %s)',
297
+ evalItem.name,
298
+ evalItem.id,
299
+ evalItem.evalId
300
+ );
301
+ }
302
+
303
+ try {
304
+ await this.apiClient.post(
305
+ '/cli/devmode/eval',
306
+ payload,
307
+ z.object({ success: z.boolean() })
308
+ );
309
+ this.logger.debug('[CLI EVAL SYNC] Sync successful');
310
+ } catch (error) {
311
+ this.logger.error('[CLI EVAL SYNC] Sync failed: %s', error);
312
+ throw error;
313
+ }
279
314
  }
280
315
  }
281
316
 
package/src/cmd/index.ts CHANGED
@@ -39,6 +39,7 @@ export async function discoverCommands(): Promise<CommandDefinition[]> {
39
39
  description: subcommand.description,
40
40
  aliases: subcommand.aliases,
41
41
  hidden: true,
42
+ skipSkill: true,
42
43
  requires: subcommand.requires,
43
44
  optional: subcommand.optional,
44
45
  schema: subcommand.schema,
@@ -12,6 +12,7 @@ const ProjectCreateResponseSchema = z.object({
12
12
  template: z.string().describe('Template used'),
13
13
  installed: z.boolean().describe('Whether dependencies were installed'),
14
14
  built: z.boolean().describe('Whether the project was built'),
15
+ domains: z.array(z.string()).optional().describe('Array of custom domains'),
15
16
  });
16
17
 
17
18
  export const createProjectSubcommand = createSubcommand({
@@ -40,6 +41,7 @@ export const createProjectSubcommand = createSubcommand({
40
41
  options: z.object({
41
42
  name: z.string().optional().describe('Project name'),
42
43
  dir: z.string().optional().describe('Directory to create the project in'),
44
+ domains: z.array(z.string()).optional().describe('Array of custom domains'),
43
45
  template: z.string().optional().describe('Template to use'),
44
46
  templateDir: z
45
47
  .string()
@@ -84,6 +86,7 @@ export const createProjectSubcommand = createSubcommand({
84
86
  await runCreateFlow({
85
87
  projectName: opts.name,
86
88
  dir: opts.dir,
89
+ domains: opts.domains,
87
90
  template: opts.template,
88
91
  templateDir: opts.templateDir,
89
92
  templateBranch: opts.templateBranch,
@@ -29,12 +29,14 @@ import {
29
29
  filterAgentuitySdkKeys,
30
30
  splitEnvAndSecrets,
31
31
  } from '../../env-util';
32
+ import { promptForDNS } from '../../domain';
32
33
 
33
34
  type ResourcesTypes = z.infer<typeof Resources>;
34
35
 
35
36
  interface CreateFlowOptions {
36
37
  projectName?: string;
37
38
  dir?: string;
39
+ domains?: string[];
38
40
  template?: string;
39
41
  templateDir?: string;
40
42
  templateBranch?: string;
@@ -63,6 +65,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
63
65
  orgId: selectedOrgId,
64
66
  region,
65
67
  apiClient,
68
+ domains,
66
69
  } = options;
67
70
 
68
71
  // Fetch available templates
@@ -105,7 +108,8 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
105
108
  if (!projectName && !skipPrompts) {
106
109
  projectName = await prompt.text({
107
110
  message: 'What is the name of your project?',
108
- initial: 'My First Agent',
111
+ hint: 'The name must be unique for your organization',
112
+ initial: '',
109
113
  validate: async (value: string) => {
110
114
  if (!value || value.trim().length === 0) {
111
115
  return 'Project name is required';
@@ -249,6 +253,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
249
253
  }
250
254
 
251
255
  const resourceConfig: ResourcesTypes = Resources.parse({});
256
+ let _domains = domains;
252
257
 
253
258
  if (auth && apiClient && catalystClient && orgId && region && !skipPrompts) {
254
259
  // Fetch resources for selected org and region using Catalyst API
@@ -265,8 +270,8 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
265
270
  const db_action = await prompt.select({
266
271
  message: 'Create SQL Database?',
267
272
  options: [
268
- { value: 'Create New', label: 'Create a new (free)' },
269
273
  { value: 'Skip', label: 'Skip or Setup later' },
274
+ { value: 'Create New', label: 'Create a new database' },
270
275
  ...resources.db.map((db) => ({
271
276
  value: db.name,
272
277
  label: `Use database: ${tui.tuiColors.primary(db.name)}`,
@@ -277,8 +282,8 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
277
282
  const s3_action = await prompt.select({
278
283
  message: 'Create Storage Bucket?',
279
284
  options: [
280
- { value: 'Create New', label: 'Create a new (free)' },
281
285
  { value: 'Skip', label: 'Skip or Setup later' },
286
+ { value: 'Create New', label: 'Create a new bucket' },
282
287
  ...resources.s3.map((bucket) => ({
283
288
  value: bucket.bucket_name,
284
289
  label: `Use bucket: ${tui.tuiColors.primary(bucket.bucket_name)}`,
@@ -286,6 +291,22 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
286
291
  ],
287
292
  });
288
293
 
294
+ if (!domains?.length) {
295
+ const customDns = await prompt.text({
296
+ message: 'Setup custom DNS?',
297
+ hint: 'Enter a domain name or press Enter to skip',
298
+ validate: (val: string) =>
299
+ val === ''
300
+ ? true
301
+ : /^(?=.{1,253}$)(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[A-Za-z]{2,63}$/.test(
302
+ val
303
+ ),
304
+ });
305
+ if (customDns) {
306
+ _domains = [customDns];
307
+ }
308
+ }
309
+
289
310
  const choices = { db_action, s3_action };
290
311
  switch (choices.s3_action) {
291
312
  case 'Create New': {
@@ -329,9 +350,9 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
329
350
  }
330
351
  }
331
352
 
332
- if (auth && apiClient && orgId) {
333
- let projectId: string | undefined;
353
+ let projectId: string | undefined;
334
354
 
355
+ if (auth && apiClient && orgId) {
335
356
  const cloudRegion = region ?? process.env.AGENTUITY_REGION ?? 'usc';
336
357
 
337
358
  const pkgJsonPath = resolve(dest, 'package.json');
@@ -355,6 +376,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
355
376
  tags: tags.length > 0 ? tags : undefined,
356
377
  orgId,
357
378
  cloudRegion,
379
+ domains: _domains,
358
380
  });
359
381
  projectId = project.id;
360
382
  return createProjectConfig(dest, {
@@ -363,6 +385,7 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
363
385
  sdkKey: project.sdkKey,
364
386
  deployment: {
365
387
  resources: resourceConfig,
388
+ domains: _domains,
366
389
  },
367
390
  region: cloudRegion,
368
391
  });
@@ -426,6 +449,15 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<void> {
426
449
  }
427
450
 
428
451
  playSound();
452
+
453
+ if (process.stdin.isTTY && !skipPrompts && _domains?.length && projectId) {
454
+ tui.newline();
455
+ const ok = await tui.confirm('Would you like to configure DNS now?', true);
456
+ if (ok) {
457
+ tui.newline();
458
+ await promptForDNS(projectId, _domains, config);
459
+ }
460
+ }
429
461
  }
430
462
 
431
463
  /**
@@ -9,6 +9,7 @@ export const command = createCommand({
9
9
  description: 'Display first-run setup information (internal use)',
10
10
  hidden: true,
11
11
  skipUpgradeCheck: true,
12
+ skipSkill: true,
12
13
  tags: ['read-only', 'fast'],
13
14
  optional: { auth: true },
14
15
  schema: {
@@ -6,9 +6,39 @@ import { ErrorCode, createError, exitWithError } from '../../errors';
6
6
  import * as tui from '../../tui';
7
7
  import { downloadWithProgress } from '../../download';
8
8
  import { $ } from 'bun';
9
- import { join } from 'node:path';
9
+ import { join, dirname } from 'node:path';
10
10
  import { tmpdir } from 'node:os';
11
11
  import { randomUUID } from 'node:crypto';
12
+ import { access, constants } from 'node:fs/promises';
13
+ import { StructuredError } from '@agentuity/core';
14
+
15
+ export const PermissionError = StructuredError('PermissionError')<{
16
+ binaryPath: string;
17
+ reason: string;
18
+ }>();
19
+
20
+ async function checkWritePermission(binaryPath: string): Promise<void> {
21
+ try {
22
+ await access(binaryPath, constants.W_OK);
23
+ } catch {
24
+ throw new PermissionError({
25
+ binaryPath,
26
+ reason: `Cannot write to ${binaryPath}. You may need to run with elevated permissions (e.g., sudo) or reinstall to a user-writable location.`,
27
+ message: `Permission denied: Cannot write to ${binaryPath}`,
28
+ });
29
+ }
30
+
31
+ const parentDir = dirname(binaryPath);
32
+ try {
33
+ await access(parentDir, constants.W_OK);
34
+ } catch {
35
+ throw new PermissionError({
36
+ binaryPath,
37
+ reason: `Cannot write to directory ${parentDir}. You may need to run with elevated permissions (e.g., sudo) or reinstall to a user-writable location.`,
38
+ message: `Permission denied: Cannot write to directory ${parentDir}`,
39
+ });
40
+ }
41
+ }
12
42
 
13
43
  const UpgradeOptionsSchema = z.object({
14
44
  force: z.boolean().optional().describe('Force upgrade even if version is the same'),
@@ -316,7 +346,7 @@ export const command = createCommand({
316
346
  };
317
347
  }
318
348
 
319
- // Confirm upgrade
349
+ // Show version info
320
350
  if (!force) {
321
351
  tui.info(`Current version: ${tui.muted(normalizedCurrent)}`);
322
352
  tui.info(`Latest version: ${tui.bold(normalizedLatest)}`);
@@ -328,7 +358,43 @@ export const command = createCommand({
328
358
  }
329
359
  tui.success(`Release notes: ${tui.link(getReleaseUrl(latestVersion))}`);
330
360
  tui.newline();
361
+ }
331
362
 
363
+ // Check write permissions before prompting - fail early with helpful message
364
+ try {
365
+ await checkWritePermission(currentBinaryPath);
366
+ } catch (error) {
367
+ if (error instanceof PermissionError) {
368
+ tui.error('Unable to upgrade: permission denied');
369
+ tui.newline();
370
+ tui.warning(`The CLI binary at ${tui.bold(error.binaryPath)} is not writable.`);
371
+ tui.newline();
372
+ if (process.env.AGENTUITY_RUNTIME) {
373
+ console.log('You cannot self-upgrade the agentuity cli in the cloud runtime.');
374
+ console.log('The runtime will automatically update the cli and other software');
375
+ console.log('within a day or so. If you need assistance, please contact us');
376
+ console.log('at support@agentuity.com.');
377
+ } else {
378
+ console.log('To fix this, you can either:');
379
+ console.log(
380
+ ` 1. Run with elevated permissions: ${tui.muted('sudo agentuity upgrade')}`
381
+ );
382
+ console.log(` 2. Reinstall to a user-writable location`);
383
+ }
384
+ tui.newline();
385
+ exitWithError(
386
+ createError(ErrorCode.PERMISSION_DENIED, 'Upgrade failed: permission denied', {
387
+ path: error.binaryPath,
388
+ }),
389
+ logger,
390
+ options.errorFormat
391
+ );
392
+ }
393
+ throw error;
394
+ }
395
+
396
+ // Confirm upgrade
397
+ if (!force) {
332
398
  const shouldUpgrade = await tui.confirm('Do you want to upgrade?', true);
333
399
 
334
400
  if (!shouldUpgrade) {
@@ -383,13 +449,11 @@ export const command = createCommand({
383
449
  message,
384
450
  };
385
451
  } catch (error) {
386
- // Parse validation errors to extract stdout/stderr if present
387
452
  let errorDetails: Record<string, unknown> = {
388
453
  error: error instanceof Error ? error.message : 'Unknown error',
389
454
  };
390
455
 
391
456
  if (error instanceof Error && error.message.includes('Binary validation failed')) {
392
- // Extract stdout/stderr from validation error
393
457
  const match = error.message.match(
394
458
  /Failed with exit code (\d+)\n(stdout: .+\n)?(stderr: .+)?/s
395
459
  );
package/src/config.ts CHANGED
@@ -364,6 +364,15 @@ export async function getAuth(): Promise<AuthData | null> {
364
364
  };
365
365
  }
366
366
 
367
+ // Priority 1a: Allow automated login from environment variables (this is set in deployment)
368
+ if (process.env.AGENTUITY_API_KEY) {
369
+ return {
370
+ apiKey: process.env.AGENTUITY_API_KEY,
371
+ userId: '',
372
+ expires: new Date(Date.now() + 30 * 60_000),
373
+ };
374
+ }
375
+
367
376
  // Priority 2: On macOS, try to read from Keychain
368
377
  if (isMacOS()) {
369
378
  try {
package/src/domain.ts ADDED
@@ -0,0 +1,273 @@
1
+ import type { Config } from './types';
2
+ import { StructuredError } from '@agentuity/core';
3
+ import * as tui from './tui';
4
+
5
+ interface BaseDNSResult {
6
+ domain: string;
7
+ target: string;
8
+ recordType: string;
9
+ }
10
+
11
+ interface DNSSuccess extends BaseDNSResult {
12
+ success: true;
13
+ }
14
+
15
+ interface DNSPending extends BaseDNSResult {
16
+ success: true;
17
+ pending: true;
18
+ }
19
+
20
+ interface DNSMissing extends BaseDNSResult {
21
+ success: false;
22
+ pending: false;
23
+ }
24
+
25
+ interface DNSError extends BaseDNSResult {
26
+ success: false;
27
+ error: string;
28
+ }
29
+
30
+ interface DNSMisconfigured extends BaseDNSResult {
31
+ success: false;
32
+ misconfigured: string;
33
+ }
34
+
35
+ export type DNSResult = DNSSuccess | DNSPending | DNSMissing | DNSError | DNSMisconfigured;
36
+ export type DNSFailed = DNSPending | DNSMissing | DNSError | DNSMisconfigured;
37
+
38
+ export function isMisconfigured(x: DNSResult): x is DNSMisconfigured {
39
+ return 'misconfigured' in x && !!x.misconfigured;
40
+ }
41
+
42
+ export function isMissing(x: DNSResult): x is DNSMissing {
43
+ return 'pending' in x && x.pending === false && 'success' in x && x.success === false;
44
+ }
45
+
46
+ export function isError(x: DNSResult): x is DNSError {
47
+ return 'error' in x && !!x.error;
48
+ }
49
+
50
+ export function isPending(x: DNSResult): x is DNSPending {
51
+ return 'pending' in x && x.pending === true && x.success === true;
52
+ }
53
+
54
+ export function isSuccess(x: DNSResult): x is DNSSuccess {
55
+ return x.success == true && !('pending' in x) && !('error' in x) && !('misconfigured' in x);
56
+ }
57
+
58
+ const timeoutMs = 5000;
59
+
60
+ const DNSTimeoutError = StructuredError(
61
+ 'DNSTimeoutError',
62
+ `DNS lookup timed out after ${timeoutMs}ms`
63
+ );
64
+
65
+ interface CFRecord {
66
+ Answer?: {
67
+ data: string;
68
+ }[];
69
+ }
70
+
71
+ async function fetchDNSRecord(name: string, type: string): Promise<string | null> {
72
+ const params = new URLSearchParams();
73
+ params.set('name', name);
74
+ params.set('type', type);
75
+ const res = await fetch(`https://cloudflare-dns.com/dns-query?${params.toString()}`, {
76
+ headers: {
77
+ Accept: 'application/dns-json',
78
+ },
79
+ });
80
+ if (res.ok) {
81
+ const result = (await res.json()) as CFRecord;
82
+ if (result?.Answer?.length) {
83
+ return result.Answer[0].data.replace(/\.$/, ''); // DNS records end with . so we remove that
84
+ }
85
+ }
86
+ return null;
87
+ }
88
+
89
+ const LOCAL_DNS = 'agentuity.io';
90
+ const PRODUCTION_DNS = 'agentuity.run';
91
+
92
+ /**
93
+ * This function will check for each of the custom domains and make sure they are correctly
94
+ * configured in DNS
95
+ *
96
+ * @param projectId the project id
97
+ * @param config Config
98
+ * @param domains array of domains to check
99
+ * @returns
100
+ */
101
+ export async function checkCustomDomainForDNS(
102
+ projectId: string,
103
+ domains: string[],
104
+ config?: Config | null
105
+ ): Promise<DNSResult[]> {
106
+ const suffix = config?.overrides?.api_url?.includes('agentuity.io') ? LOCAL_DNS : PRODUCTION_DNS;
107
+ const id = Bun.hash.xxHash64(projectId).toString(16);
108
+ const proxy = `p${id}.${suffix}`;
109
+
110
+ return Promise.all(
111
+ domains.map(async (domain) => {
112
+ try {
113
+ let timeoutId: Timer | undefined;
114
+
115
+ const timeoutPromise = new Promise<never>((_, reject) => {
116
+ timeoutId = setTimeout(() => {
117
+ reject(new DNSTimeoutError());
118
+ }, timeoutMs);
119
+ });
120
+
121
+ const result = await Promise.race([
122
+ fetchDNSRecord(domain, 'CNAME'),
123
+ timeoutPromise,
124
+ ]).finally(() => {
125
+ if (timeoutId) clearTimeout(timeoutId);
126
+ });
127
+
128
+ if (result) {
129
+ if (result === proxy) {
130
+ return {
131
+ domain,
132
+ target: proxy,
133
+ recordType: 'CNAME',
134
+ success: true,
135
+ } as DNSSuccess;
136
+ }
137
+ return {
138
+ domain,
139
+ target: proxy,
140
+ recordType: 'CNAME',
141
+ success: false,
142
+ misconfigured: `CNAME record is ${result}`,
143
+ } as DNSMisconfigured;
144
+ }
145
+ } catch (ex) {
146
+ const _ex = ex as { code: string; message?: string };
147
+ if (_ex.message?.includes('timed out')) {
148
+ return {
149
+ domain,
150
+ target: proxy,
151
+ recordType: 'CNAME',
152
+ success: false,
153
+ error: `DNS lookup timed out after 5 seconds. Please check your DNS configuration.`,
154
+ } as DNSError;
155
+ }
156
+ if (_ex.code !== 'ENOTFOUND') {
157
+ const errMsg =
158
+ ex instanceof Error
159
+ ? ex.message
160
+ : typeof ex === 'string'
161
+ ? ex
162
+ : JSON.stringify(ex);
163
+ return {
164
+ domain,
165
+ target: proxy,
166
+ recordType: 'CNAME',
167
+ success: false,
168
+ error: errMsg,
169
+ } as DNSError;
170
+ }
171
+ }
172
+ return {
173
+ domain,
174
+ success: false,
175
+ target: proxy,
176
+ recordType: 'CNAME',
177
+ pending: false,
178
+ } as DNSMissing;
179
+ })
180
+ );
181
+ }
182
+
183
+ export async function promptForDNS(
184
+ projectId: string,
185
+ domains: string[],
186
+ config?: Config,
187
+ resumeFn?: () => () => void
188
+ ) {
189
+ let paused = false;
190
+ let resume: (() => void) | undefined;
191
+ for (;;) {
192
+ const result = await checkCustomDomainForDNS(projectId, domains, config);
193
+ const failed = result.filter((x): x is DNSFailed => !isSuccess(x));
194
+ if (failed.length) {
195
+ const records: {
196
+ domain: string;
197
+ type: string;
198
+ target: string;
199
+ status: string;
200
+ }[] = [];
201
+ result.forEach((r) => {
202
+ if (isSuccess(r)) {
203
+ records.push({
204
+ domain: r.domain,
205
+ type: r.recordType,
206
+ target: r.target,
207
+ status: tui.colorSuccess(`${tui.ICONS.success} Configured`),
208
+ });
209
+ }
210
+ });
211
+ if (!paused) {
212
+ resume = resumeFn?.();
213
+ paused = true;
214
+ }
215
+ tui.error(
216
+ `You have ${tui.plural(failed.length, 'a ', '')}DNS configuration ${tui.plural(failed.length, 'issue', 'issues')} that must be resolved before deploying:`
217
+ );
218
+ for (const r of failed) {
219
+ if (isError(r)) {
220
+ resume?.();
221
+ throw new Error(r.error);
222
+ } else if (isMisconfigured(r)) {
223
+ records.push({
224
+ domain: r.domain,
225
+ type: r.recordType,
226
+ target: r.target,
227
+ status: tui.colorWarning(`${tui.ICONS.error} ${r.misconfigured}`),
228
+ });
229
+ } else if (isPending(r)) {
230
+ records.push({
231
+ domain: r.domain,
232
+ type: r.recordType,
233
+ target: r.target,
234
+ status: tui.colorWarning('⌛️ Pending'),
235
+ });
236
+ } else if (isMissing(r)) {
237
+ records.push({
238
+ domain: r.domain,
239
+ type: r.recordType,
240
+ target: r.target,
241
+ status: tui.colorError(`${tui.ICONS.error} Missing`),
242
+ });
243
+ }
244
+ }
245
+
246
+ let linesShown = 2; // header + footer
247
+ for (const record of records) {
248
+ console.log();
249
+ console.log(`${tui.colorInfo('Domain:')} ${tui.colorPrimary(record.domain)}`);
250
+ console.log(`${tui.colorInfo('Type:')} ${tui.colorPrimary(record.type)}`);
251
+ console.log(`${tui.colorInfo('Target:')} ${tui.colorPrimary(record.target)}`);
252
+ console.log(`${tui.colorInfo('Status:')} ${tui.colorPrimary(record.status)}`);
253
+ console.log();
254
+ linesShown += 6;
255
+ }
256
+
257
+ // await tui.waitForAnyKey('Press any key to check again or ctrl+c to cancel...');
258
+ await tui.spinner({
259
+ message: 'Checking again in 5s...',
260
+ clearOnSuccess: true,
261
+ callback: () => {
262
+ return Bun.sleep(5000);
263
+ },
264
+ });
265
+ tui.clearLastLines(linesShown);
266
+ linesShown = 0;
267
+ continue;
268
+ }
269
+ tui.clearLastLines(1);
270
+ resume?.();
271
+ break;
272
+ }
273
+ }
package/src/index.ts CHANGED
@@ -75,11 +75,6 @@ export { showBanner } from './banner';
75
75
  export { discoverCommands } from './cmd';
76
76
  export { detectColorScheme } from './terminal';
77
77
  export { getCommandPrefix, getCommand } from './command-prefix';
78
- export {
79
- bootstrapRuntimeEnv,
80
- type RuntimeBootstrapOptions,
81
- type RuntimeBootstrapResult,
82
- } from './runtime-bootstrap';
83
78
  export * as tui from './tui';
84
79
  export {
85
80
  createRepl,
@@ -43,7 +43,7 @@ Call `bootstrapRuntimeEnv()` at the top of your `app.ts` **before** `createApp()
43
43
 
44
44
  ```ts
45
45
  import { createApp } from '@agentuity/runtime';
46
- import { bootstrapRuntimeEnv } from '@agentuity/cli';
46
+ import { bootstrapRuntimeEnv } from '@agentuity/runtime';
47
47
 
48
48
  // Bootstrap runtime environment based on active profile
49
49
  await bootstrapRuntimeEnv();
@@ -48,6 +48,8 @@ export interface SchemaCommand {
48
48
  prerequisites?: string[];
49
49
  pagination?: SchemaPagination;
50
50
  tags?: string[];
51
+ skipSkill?: boolean;
52
+ toplevel?: boolean;
51
53
  subcommands?: SchemaCommand[];
52
54
  requires?: {
53
55
  auth?: boolean;
@@ -121,6 +123,13 @@ function extractCommandSchema(def: CommandDefinition): SchemaCommand {
121
123
  schema.tags = (def as any).tags;
122
124
  }
123
125
 
126
+ // Extract skipSkill
127
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
+ if ((def as any).skipSkill !== undefined) {
129
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
+ schema.skipSkill = (def as any).skipSkill;
131
+ }
132
+
124
133
  // Extract requires/optional
125
134
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
126
135
  const d = def as any;
@@ -202,6 +211,20 @@ function extractSubcommandSchema(def: SubcommandDefinition): SchemaCommand {
202
211
  schema.tags = (def as any).tags;
203
212
  }
204
213
 
214
+ // Extract skipSkill
215
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
216
+ if ((def as any).skipSkill !== undefined) {
217
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
218
+ schema.skipSkill = (def as any).skipSkill;
219
+ }
220
+
221
+ // Extract toplevel
222
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
223
+ if ((def as any).toplevel !== undefined) {
224
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
225
+ schema.toplevel = (def as any).toplevel;
226
+ }
227
+
205
228
  // Extract requires/optional
206
229
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
207
230
  const d = def as any;