@agentuity/cli 2.0.11 → 2.0.13

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 (274) hide show
  1. package/dist/cache/resource-region.d.ts.map +1 -1
  2. package/dist/cache/resource-region.js +48 -25
  3. package/dist/cache/resource-region.js.map +1 -1
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +15 -8
  6. package/dist/cli.js.map +1 -1
  7. package/dist/cmd/build/vite/bun-dev-server.d.ts +20 -0
  8. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
  9. package/dist/cmd/build/vite/bun-dev-server.js +62 -4
  10. package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
  11. package/dist/cmd/build/vite/index.d.ts +0 -1
  12. package/dist/cmd/build/vite/index.d.ts.map +1 -1
  13. package/dist/cmd/build/vite/index.js +0 -1
  14. package/dist/cmd/build/vite/index.js.map +1 -1
  15. package/dist/cmd/build/vite/static-renderer.d.ts +17 -0
  16. package/dist/cmd/build/vite/static-renderer.d.ts.map +1 -1
  17. package/dist/cmd/build/vite/static-renderer.js +18 -6
  18. package/dist/cmd/build/vite/static-renderer.js.map +1 -1
  19. package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
  20. package/dist/cmd/build/vite/vite-asset-server-config.js +34 -27
  21. package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
  22. package/dist/cmd/build/vite/vite-asset-server.d.ts +9 -0
  23. package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
  24. package/dist/cmd/build/vite/vite-asset-server.js +5 -1
  25. package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
  26. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  27. package/dist/cmd/build/vite/vite-builder.js +12 -1
  28. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  29. package/dist/cmd/build/vite/ws-proxy.d.ts +15 -1
  30. package/dist/cmd/build/vite/ws-proxy.d.ts.map +1 -1
  31. package/dist/cmd/build/vite/ws-proxy.js +33 -0
  32. package/dist/cmd/build/vite/ws-proxy.js.map +1 -1
  33. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  34. package/dist/cmd/cloud/deploy.js +98 -39
  35. package/dist/cmd/cloud/deploy.js.map +1 -1
  36. package/dist/cmd/cloud/sandbox/checkpoint/create.d.ts.map +1 -1
  37. package/dist/cmd/cloud/sandbox/checkpoint/create.js +3 -4
  38. package/dist/cmd/cloud/sandbox/checkpoint/create.js.map +1 -1
  39. package/dist/cmd/cloud/sandbox/checkpoint/delete.d.ts.map +1 -1
  40. package/dist/cmd/cloud/sandbox/checkpoint/delete.js +3 -4
  41. package/dist/cmd/cloud/sandbox/checkpoint/delete.js.map +1 -1
  42. package/dist/cmd/cloud/sandbox/checkpoint/list.d.ts.map +1 -1
  43. package/dist/cmd/cloud/sandbox/checkpoint/list.js +3 -4
  44. package/dist/cmd/cloud/sandbox/checkpoint/list.js.map +1 -1
  45. package/dist/cmd/cloud/sandbox/checkpoint/restore.d.ts.map +1 -1
  46. package/dist/cmd/cloud/sandbox/checkpoint/restore.js +3 -4
  47. package/dist/cmd/cloud/sandbox/checkpoint/restore.js.map +1 -1
  48. package/dist/cmd/cloud/sandbox/create.d.ts.map +1 -1
  49. package/dist/cmd/cloud/sandbox/create.js +13 -4
  50. package/dist/cmd/cloud/sandbox/create.js.map +1 -1
  51. package/dist/cmd/cloud/sandbox/delete.d.ts.map +1 -1
  52. package/dist/cmd/cloud/sandbox/delete.js +3 -4
  53. package/dist/cmd/cloud/sandbox/delete.js.map +1 -1
  54. package/dist/cmd/cloud/sandbox/env.d.ts.map +1 -1
  55. package/dist/cmd/cloud/sandbox/env.js +3 -5
  56. package/dist/cmd/cloud/sandbox/env.js.map +1 -1
  57. package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
  58. package/dist/cmd/cloud/sandbox/exec.js +114 -41
  59. package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
  60. package/dist/cmd/cloud/sandbox/execution/list.d.ts.map +1 -1
  61. package/dist/cmd/cloud/sandbox/execution/list.js +3 -5
  62. package/dist/cmd/cloud/sandbox/execution/list.js.map +1 -1
  63. package/dist/cmd/cloud/sandbox/fs/cp.d.ts.map +1 -1
  64. package/dist/cmd/cloud/sandbox/fs/cp.js +61 -113
  65. package/dist/cmd/cloud/sandbox/fs/cp.js.map +1 -1
  66. package/dist/cmd/cloud/sandbox/fs/download.d.ts.map +1 -1
  67. package/dist/cmd/cloud/sandbox/fs/download.js +11 -22
  68. package/dist/cmd/cloud/sandbox/fs/download.js.map +1 -1
  69. package/dist/cmd/cloud/sandbox/fs/ls.d.ts.map +1 -1
  70. package/dist/cmd/cloud/sandbox/fs/ls.js +3 -5
  71. package/dist/cmd/cloud/sandbox/fs/ls.js.map +1 -1
  72. package/dist/cmd/cloud/sandbox/fs/mkdir.d.ts.map +1 -1
  73. package/dist/cmd/cloud/sandbox/fs/mkdir.js +3 -5
  74. package/dist/cmd/cloud/sandbox/fs/mkdir.js.map +1 -1
  75. package/dist/cmd/cloud/sandbox/fs/rm.d.ts.map +1 -1
  76. package/dist/cmd/cloud/sandbox/fs/rm.js +3 -5
  77. package/dist/cmd/cloud/sandbox/fs/rm.js.map +1 -1
  78. package/dist/cmd/cloud/sandbox/fs/rmdir.d.ts.map +1 -1
  79. package/dist/cmd/cloud/sandbox/fs/rmdir.js +3 -5
  80. package/dist/cmd/cloud/sandbox/fs/rmdir.js.map +1 -1
  81. package/dist/cmd/cloud/sandbox/fs/upload.d.ts.map +1 -1
  82. package/dist/cmd/cloud/sandbox/fs/upload.js +7 -8
  83. package/dist/cmd/cloud/sandbox/fs/upload.js.map +1 -1
  84. package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -1
  85. package/dist/cmd/cloud/sandbox/get.js +21 -7
  86. package/dist/cmd/cloud/sandbox/get.js.map +1 -1
  87. package/dist/cmd/cloud/sandbox/job/create.d.ts.map +1 -1
  88. package/dist/cmd/cloud/sandbox/job/create.js +3 -4
  89. package/dist/cmd/cloud/sandbox/job/create.js.map +1 -1
  90. package/dist/cmd/cloud/sandbox/job/destroy.d.ts.map +1 -1
  91. package/dist/cmd/cloud/sandbox/job/destroy.js +3 -4
  92. package/dist/cmd/cloud/sandbox/job/destroy.js.map +1 -1
  93. package/dist/cmd/cloud/sandbox/job/get.d.ts.map +1 -1
  94. package/dist/cmd/cloud/sandbox/job/get.js +3 -4
  95. package/dist/cmd/cloud/sandbox/job/get.js.map +1 -1
  96. package/dist/cmd/cloud/sandbox/job/list.d.ts.map +1 -1
  97. package/dist/cmd/cloud/sandbox/job/list.js +3 -4
  98. package/dist/cmd/cloud/sandbox/job/list.js.map +1 -1
  99. package/dist/cmd/cloud/sandbox/job/logs.d.ts.map +1 -1
  100. package/dist/cmd/cloud/sandbox/job/logs.js +4 -4
  101. package/dist/cmd/cloud/sandbox/job/logs.js.map +1 -1
  102. package/dist/cmd/cloud/sandbox/pause.d.ts.map +1 -1
  103. package/dist/cmd/cloud/sandbox/pause.js +21 -5
  104. package/dist/cmd/cloud/sandbox/pause.js.map +1 -1
  105. package/dist/cmd/cloud/sandbox/resume.d.ts.map +1 -1
  106. package/dist/cmd/cloud/sandbox/resume.js +3 -4
  107. package/dist/cmd/cloud/sandbox/resume.js.map +1 -1
  108. package/dist/cmd/cloud/sandbox/run.d.ts.map +1 -1
  109. package/dist/cmd/cloud/sandbox/run.js +36 -7
  110. package/dist/cmd/cloud/sandbox/run.js.map +1 -1
  111. package/dist/cmd/cloud/sandbox/snapshot/create.js +4 -4
  112. package/dist/cmd/cloud/sandbox/snapshot/create.js.map +1 -1
  113. package/dist/cmd/cloud/sandbox/util.d.ts +19 -0
  114. package/dist/cmd/cloud/sandbox/util.d.ts.map +1 -1
  115. package/dist/cmd/cloud/sandbox/util.js +40 -2
  116. package/dist/cmd/cloud/sandbox/util.js.map +1 -1
  117. package/dist/cmd/coder/create.js +7 -7
  118. package/dist/cmd/coder/create.js.map +1 -1
  119. package/dist/cmd/coder/start.d.ts.map +1 -1
  120. package/dist/cmd/coder/start.js +3 -0
  121. package/dist/cmd/coder/start.js.map +1 -1
  122. package/dist/cmd/coder/tui-init.js +1 -1
  123. package/dist/cmd/coder/tui-init.js.map +1 -1
  124. package/dist/cmd/coder/update.js +8 -8
  125. package/dist/cmd/coder/update.js.map +1 -1
  126. package/dist/cmd/coder/workspace/common.d.ts +29 -0
  127. package/dist/cmd/coder/workspace/common.d.ts.map +1 -0
  128. package/dist/cmd/coder/workspace/common.js +83 -0
  129. package/dist/cmd/coder/workspace/common.js.map +1 -0
  130. package/dist/cmd/coder/workspace/create.d.ts.map +1 -1
  131. package/dist/cmd/coder/workspace/create.js +57 -32
  132. package/dist/cmd/coder/workspace/create.js.map +1 -1
  133. package/dist/cmd/coder/workspace/get.d.ts.map +1 -1
  134. package/dist/cmd/coder/workspace/get.js +2 -5
  135. package/dist/cmd/coder/workspace/get.js.map +1 -1
  136. package/dist/cmd/coder/workspace/index.d.ts.map +1 -1
  137. package/dist/cmd/coder/workspace/index.js +11 -1
  138. package/dist/cmd/coder/workspace/index.js.map +1 -1
  139. package/dist/cmd/coder/workspace/list.d.ts.map +1 -1
  140. package/dist/cmd/coder/workspace/list.js +4 -0
  141. package/dist/cmd/coder/workspace/list.js.map +1 -1
  142. package/dist/cmd/coder/workspace/refresh.d.ts +2 -0
  143. package/dist/cmd/coder/workspace/refresh.d.ts.map +1 -0
  144. package/dist/cmd/coder/workspace/refresh.js +59 -0
  145. package/dist/cmd/coder/workspace/refresh.js.map +1 -0
  146. package/dist/cmd/coder/workspace/update.d.ts +2 -0
  147. package/dist/cmd/coder/workspace/update.d.ts.map +1 -0
  148. package/dist/cmd/coder/workspace/update.js +131 -0
  149. package/dist/cmd/coder/workspace/update.js.map +1 -0
  150. package/dist/cmd/coder/workspace/validate-dependencies.d.ts +2 -0
  151. package/dist/cmd/coder/workspace/validate-dependencies.d.ts.map +1 -0
  152. package/dist/cmd/coder/workspace/validate-dependencies.js +70 -0
  153. package/dist/cmd/coder/workspace/validate-dependencies.js.map +1 -0
  154. package/dist/cmd/dev/dev-lock.d.ts.map +1 -1
  155. package/dist/cmd/dev/dev-lock.js +43 -17
  156. package/dist/cmd/dev/dev-lock.js.map +1 -1
  157. package/dist/cmd/dev/index.d.ts.map +1 -1
  158. package/dist/cmd/dev/index.js +211 -125
  159. package/dist/cmd/dev/index.js.map +1 -1
  160. package/dist/cmd/dev/process-manager.d.ts +41 -1
  161. package/dist/cmd/dev/process-manager.d.ts.map +1 -1
  162. package/dist/cmd/dev/process-manager.js +160 -31
  163. package/dist/cmd/dev/process-manager.js.map +1 -1
  164. package/dist/cmd/project/create.d.ts.map +1 -1
  165. package/dist/cmd/project/create.js +0 -2
  166. package/dist/cmd/project/create.js.map +1 -1
  167. package/dist/cmd/project/index.d.ts.map +1 -1
  168. package/dist/cmd/project/index.js +0 -3
  169. package/dist/cmd/project/index.js.map +1 -1
  170. package/dist/cmd/project/random-name.d.ts +17 -0
  171. package/dist/cmd/project/random-name.d.ts.map +1 -0
  172. package/dist/cmd/project/random-name.js +144 -0
  173. package/dist/cmd/project/random-name.js.map +1 -0
  174. package/dist/cmd/project/template-flow.d.ts +0 -1
  175. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  176. package/dist/cmd/project/template-flow.js +180 -275
  177. package/dist/cmd/project/template-flow.js.map +1 -1
  178. package/dist/composite-logger.d.ts.map +1 -1
  179. package/dist/composite-logger.js +19 -0
  180. package/dist/composite-logger.js.map +1 -1
  181. package/dist/config.d.ts +18 -16
  182. package/dist/config.d.ts.map +1 -1
  183. package/dist/config.js +46 -16
  184. package/dist/config.js.map +1 -1
  185. package/dist/tui/prompt.d.ts +29 -0
  186. package/dist/tui/prompt.d.ts.map +1 -1
  187. package/dist/tui/prompt.js +180 -8
  188. package/dist/tui/prompt.js.map +1 -1
  189. package/package.json +7 -7
  190. package/src/cache/resource-region.ts +68 -44
  191. package/src/cli.ts +30 -8
  192. package/src/cmd/ai/prompt/web.md +43 -17
  193. package/src/cmd/build/vite/bun-dev-server.ts +92 -6
  194. package/src/cmd/build/vite/index.ts +0 -1
  195. package/src/cmd/build/vite/static-renderer.ts +18 -7
  196. package/src/cmd/build/vite/vite-asset-server-config.ts +37 -27
  197. package/src/cmd/build/vite/vite-asset-server.ts +5 -1
  198. package/src/cmd/build/vite/vite-builder.ts +12 -1
  199. package/src/cmd/build/vite/ws-proxy.ts +52 -3
  200. package/src/cmd/cloud/deploy.ts +117 -49
  201. package/src/cmd/cloud/sandbox/checkpoint/create.ts +10 -4
  202. package/src/cmd/cloud/sandbox/checkpoint/delete.ts +10 -4
  203. package/src/cmd/cloud/sandbox/checkpoint/list.ts +10 -4
  204. package/src/cmd/cloud/sandbox/checkpoint/restore.ts +10 -4
  205. package/src/cmd/cloud/sandbox/create.ts +14 -4
  206. package/src/cmd/cloud/sandbox/delete.ts +10 -4
  207. package/src/cmd/cloud/sandbox/env.ts +10 -5
  208. package/src/cmd/cloud/sandbox/exec.ts +157 -42
  209. package/src/cmd/cloud/sandbox/execution/list.ts +10 -5
  210. package/src/cmd/cloud/sandbox/fs/cp.ts +94 -126
  211. package/src/cmd/cloud/sandbox/fs/download.ts +18 -25
  212. package/src/cmd/cloud/sandbox/fs/ls.ts +10 -5
  213. package/src/cmd/cloud/sandbox/fs/mkdir.ts +10 -5
  214. package/src/cmd/cloud/sandbox/fs/rm.ts +10 -5
  215. package/src/cmd/cloud/sandbox/fs/rmdir.ts +10 -5
  216. package/src/cmd/cloud/sandbox/fs/upload.ts +14 -8
  217. package/src/cmd/cloud/sandbox/get.ts +28 -7
  218. package/src/cmd/cloud/sandbox/job/create.ts +10 -4
  219. package/src/cmd/cloud/sandbox/job/destroy.ts +10 -4
  220. package/src/cmd/cloud/sandbox/job/get.ts +10 -4
  221. package/src/cmd/cloud/sandbox/job/list.ts +10 -4
  222. package/src/cmd/cloud/sandbox/job/logs.ts +11 -4
  223. package/src/cmd/cloud/sandbox/pause.ts +31 -5
  224. package/src/cmd/cloud/sandbox/resume.ts +10 -4
  225. package/src/cmd/cloud/sandbox/run.ts +49 -11
  226. package/src/cmd/cloud/sandbox/snapshot/create.ts +6 -6
  227. package/src/cmd/cloud/sandbox/util.ts +63 -2
  228. package/src/cmd/coder/create.ts +8 -8
  229. package/src/cmd/coder/start.ts +3 -0
  230. package/src/cmd/coder/tui-init.ts +1 -1
  231. package/src/cmd/coder/update.ts +7 -7
  232. package/src/cmd/coder/workspace/common.ts +103 -0
  233. package/src/cmd/coder/workspace/create.ts +84 -37
  234. package/src/cmd/coder/workspace/get.ts +2 -5
  235. package/src/cmd/coder/workspace/index.ts +13 -1
  236. package/src/cmd/coder/workspace/list.ts +4 -0
  237. package/src/cmd/coder/workspace/refresh.ts +63 -0
  238. package/src/cmd/coder/workspace/update.ts +154 -0
  239. package/src/cmd/coder/workspace/validate-dependencies.ts +75 -0
  240. package/src/cmd/dev/dev-lock.ts +50 -16
  241. package/src/cmd/dev/index.ts +249 -134
  242. package/src/cmd/dev/process-manager.ts +173 -33
  243. package/src/cmd/project/create.ts +0 -2
  244. package/src/cmd/project/index.ts +0 -3
  245. package/src/cmd/project/random-name.ts +152 -0
  246. package/src/cmd/project/template-flow.ts +196 -305
  247. package/src/composite-logger.ts +20 -0
  248. package/src/config.ts +69 -19
  249. package/src/tui/prompt.ts +214 -8
  250. package/dist/cmd/build/vite/public-asset-path-plugin.d.ts +0 -45
  251. package/dist/cmd/build/vite/public-asset-path-plugin.d.ts.map +0 -1
  252. package/dist/cmd/build/vite/public-asset-path-plugin.js +0 -166
  253. package/dist/cmd/build/vite/public-asset-path-plugin.js.map +0 -1
  254. package/dist/cmd/project/auth/generate.d.ts +0 -5
  255. package/dist/cmd/project/auth/generate.d.ts.map +0 -1
  256. package/dist/cmd/project/auth/generate.js +0 -102
  257. package/dist/cmd/project/auth/generate.js.map +0 -1
  258. package/dist/cmd/project/auth/index.d.ts +0 -2
  259. package/dist/cmd/project/auth/index.d.ts.map +0 -1
  260. package/dist/cmd/project/auth/index.js +0 -21
  261. package/dist/cmd/project/auth/index.js.map +0 -1
  262. package/dist/cmd/project/auth/init.d.ts +0 -2
  263. package/dist/cmd/project/auth/init.d.ts.map +0 -1
  264. package/dist/cmd/project/auth/init.js +0 -213
  265. package/dist/cmd/project/auth/init.js.map +0 -1
  266. package/dist/cmd/project/auth/shared.d.ts +0 -93
  267. package/dist/cmd/project/auth/shared.d.ts.map +0 -1
  268. package/dist/cmd/project/auth/shared.js +0 -475
  269. package/dist/cmd/project/auth/shared.js.map +0 -1
  270. package/src/cmd/build/vite/public-asset-path-plugin.ts +0 -209
  271. package/src/cmd/project/auth/generate.ts +0 -116
  272. package/src/cmd/project/auth/index.ts +0 -21
  273. package/src/cmd/project/auth/init.ts +0 -256
  274. package/src/cmd/project/auth/shared.ts +0 -591
@@ -11,11 +11,13 @@ import { playSound } from '../../sound';
11
11
  import * as tui from '../../tui';
12
12
  import { createPrompt, note } from '../../tui';
13
13
  import { getGithubBotIdentity } from '../git/api';
14
- import { ensureAuthDependencies, generateAuthFileContent, generateAuthSchemaSql, printIntegrationExamples, runAuthMigrations, } from './auth/shared';
15
14
  import { downloadTemplate, initGitRepo, setupProject } from './download';
15
+ import { suggestBucketName, suggestDatabaseName } from './random-name';
16
16
  import { fetchTemplates } from './templates';
17
+ // Domain validator shared between the multi-select branch and the standalone prompt.
18
+ const DOMAIN_REGEX = /^(?=.{1,253}$)(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[A-Za-z]{2,63}$/;
17
19
  export async function runCreateFlow(options) {
18
- const { projectName: initialProjectName, dir: targetDir, template: initialTemplate, templateDir, templateBranch, skipPrompts, logger, auth, config, orgId: selectedOrgId, region, apiClient, domains, database: databaseOption, storage: storageOption, enableAuth: enableAuthOption, } = options;
20
+ const { projectName: initialProjectName, dir: targetDir, template: initialTemplate, templateDir, templateBranch, skipPrompts, logger, auth, config, orgId: selectedOrgId, region, apiClient, domains, database: databaseOption, storage: storageOption, } = options;
19
21
  const isHeadless = !process.stdin.isTTY || !process.stdout.isTTY;
20
22
  const isInteractive = !skipPrompts && !isHeadless;
21
23
  // Fetch available templates
@@ -188,7 +190,7 @@ export async function runCreateFlow(options) {
188
190
  error: 'Project setup completed with errors',
189
191
  };
190
192
  }
191
- // Add separator bar if we're going to show resource prompts
193
+ // Resource provisioning gates
192
194
  const canProvision = auth && apiClient && catalystClient && orgId && region;
193
195
  // Only count as resource flags if actually requesting provisioning (not explicit skip)
194
196
  const hasResourceFlags = (databaseOption !== undefined && databaseOption.toLowerCase() !== 'skip') ||
@@ -204,17 +206,57 @@ export async function runCreateFlow(options) {
204
206
  logger.fatal('Cannot provision database/storage without being authenticated and registering the project.\n' +
205
207
  'Remove --no-register or omit --database/--storage flags.', ErrorCode.VALIDATION_FAILED);
206
208
  }
207
- // Validate that --enable-auth requires authentication and registration
208
- if (enableAuthOption && !canProvision) {
209
- logger.fatal('Cannot enable Agentuity Auth without being authenticated and registering the project.\n' +
210
- 'Remove --no-register or omit --enable-auth flag.', ErrorCode.VALIDATION_FAILED);
211
- }
212
209
  if (canProvision) {
213
- // Fetch resources for selected org and region using Catalyst API (needed for both interactive and CLI flags)
210
+ // CLI flags pre-resolve their respective per-resource decision; the multi-select
211
+ // is only used for resources where the user didn't pass a flag.
212
+ const dbFlagAction = resolveFlagAction(databaseOption, 'database');
213
+ const storageFlagAction = resolveFlagAction(storageOption, 'storage');
214
+ const domainFlagProvided = (domains?.length ?? 0) > 0;
215
+ // Determine which resources should run through the configuration phase.
216
+ // In interactive mode, ask the user via a single multi-select.
217
+ // In headless / non-interactive mode, only flagged resources are considered.
218
+ let wantDb = dbFlagAction !== undefined && dbFlagAction !== 'Skip';
219
+ let wantStorage = storageFlagAction !== undefined && storageFlagAction !== 'Skip';
220
+ let wantDomain = domainFlagProvided;
221
+ if (isInteractive) {
222
+ // Build multi-select options dynamically: only show resources the user hasn't
223
+ // already decided about via CLI flags. If all three came from flags, skip the prompt.
224
+ const msOptions = [];
225
+ if (dbFlagAction === undefined) {
226
+ msOptions.push({ value: 'database', label: 'SQL Database', hint: 'PostgreSQL' });
227
+ }
228
+ if (storageFlagAction === undefined) {
229
+ msOptions.push({ value: 'storage', label: 'Storage Bucket', hint: 'S3-compatible' });
230
+ }
231
+ if (!domainFlagProvided) {
232
+ msOptions.push({ value: 'domain', label: 'Custom Domain', hint: 'BYO domain' });
233
+ }
234
+ if (msOptions.length > 0) {
235
+ const picked = await prompt.multiselect({
236
+ message: 'What would you like to set up? (all optional)',
237
+ options: msOptions,
238
+ initial: [],
239
+ });
240
+ if (dbFlagAction === undefined)
241
+ wantDb = picked.includes('database');
242
+ if (storageFlagAction === undefined)
243
+ wantStorage = picked.includes('storage');
244
+ if (!domainFlagProvided)
245
+ wantDomain = picked.includes('domain');
246
+ }
247
+ }
248
+ // Fetch existing resources only if we'll actually need them.
249
+ // Need them when:
250
+ // - user wants db/storage in interactive mode (to offer "use existing")
251
+ // - a CLI flag pointed at an existing resource by name
214
252
  let resources;
215
- const needResources = isInteractive ||
216
- (databaseOption && databaseOption !== 'skip' && databaseOption !== 'new') ||
217
- (storageOption && storageOption !== 'skip' && storageOption !== 'new');
253
+ const needResources = (isInteractive && (wantDb || wantStorage)) ||
254
+ (databaseOption !== undefined &&
255
+ dbFlagAction !== 'Create New' &&
256
+ dbFlagAction !== 'Skip') ||
257
+ (storageOption !== undefined &&
258
+ storageFlagAction !== 'Create New' &&
259
+ storageFlagAction !== 'Skip');
218
260
  if (needResources) {
219
261
  resources = await tui.spinner({
220
262
  message: 'Fetching resources',
@@ -227,301 +269,162 @@ export async function runCreateFlow(options) {
227
269
  logger.debug(`Resources for org ${orgId} in region ${region}: ${resources.db.length} databases, ${resources.s3.length} storage buckets`);
228
270
  logger.debug(`Database names: ${resources.db.map((d) => d.name).join(', ') || '(none)'}`);
229
271
  logger.debug(`Storage buckets: ${resources.s3.map((b) => b.bucket_name).join(', ') || '(none)'}`);
230
- }
231
- // Determine database action: CLI flag > interactive prompt > skip (headless)
232
- let db_action;
233
- if (databaseOption !== undefined) {
234
- // CLI flag provided - normalize to expected values
235
- if (databaseOption.toLowerCase() === 'new') {
236
- db_action = 'Create New';
237
- }
238
- else if (databaseOption.toLowerCase() === 'skip') {
239
- db_action = 'Skip';
272
+ // Validate flag-supplied resource names against the fetched list.
273
+ if (databaseOption !== undefined &&
274
+ dbFlagAction !== 'Create New' &&
275
+ dbFlagAction !== 'Skip' &&
276
+ !resources.db.find((d) => d.name === dbFlagAction)) {
277
+ logger.fatal(`Database '${databaseOption}' not found. Use 'new' to create a new database or 'skip' to skip.`, ErrorCode.RESOURCE_NOT_FOUND);
240
278
  }
241
- else {
242
- // Existing database name - validate it exists
243
- const existingDb = resources?.db.find((d) => d.name === databaseOption);
244
- if (!existingDb) {
245
- logger.fatal(`Database '${databaseOption}' not found. Use 'new' to create a new database or 'skip' to skip.`, ErrorCode.RESOURCE_NOT_FOUND);
246
- }
247
- db_action = databaseOption;
279
+ if (storageOption !== undefined &&
280
+ storageFlagAction !== 'Create New' &&
281
+ storageFlagAction !== 'Skip' &&
282
+ !resources.s3.find((b) => b.bucket_name === storageFlagAction)) {
283
+ logger.fatal(`Storage bucket '${storageOption}' not found. Use 'new' to create a new bucket or 'skip' to skip.`, ErrorCode.RESOURCE_NOT_FOUND);
248
284
  }
249
285
  }
250
- else if (isInteractive) {
251
- db_action = await prompt.select({
252
- message: 'Create SQL Database?',
253
- options: [
254
- { value: 'Skip', label: 'Skip or Setup later' },
255
- { value: 'Create New', label: 'Create a new database' },
256
- ...resources.db.map((db) => ({
257
- value: db.name,
258
- label: `Use database: ${tui.tuiColors.primary(db.name)}`,
259
- })),
260
- ],
261
- });
262
- }
263
- else {
264
- // Headless without flag - skip
265
- db_action = 'Skip';
266
- }
267
- // Determine storage action: CLI flag > interactive prompt > skip (headless)
268
- let s3_action;
269
- if (storageOption !== undefined) {
270
- // CLI flag provided - normalize to expected values
271
- if (storageOption.toLowerCase() === 'new') {
272
- s3_action = 'Create New';
273
- }
274
- else if (storageOption.toLowerCase() === 'skip') {
275
- s3_action = 'Skip';
276
- }
277
- else {
278
- // Existing bucket name - validate it exists
279
- const existingBucket = resources?.s3.find((b) => b.bucket_name === storageOption);
280
- if (!existingBucket) {
281
- logger.fatal(`Storage bucket '${storageOption}' not found. Use 'new' to create a new bucket or 'skip' to skip.`, ErrorCode.RESOURCE_NOT_FOUND);
286
+ // === Configure each selected resource: Database → Storage → Domain ===
287
+ // Database
288
+ if (wantDb) {
289
+ let dbAction = dbFlagAction;
290
+ if (dbAction === undefined && isInteractive) {
291
+ const existing = resources?.db ?? [];
292
+ if (existing.length > 0) {
293
+ dbAction = await prompt.select({
294
+ message: 'SQL Database',
295
+ options: [
296
+ { value: 'Create New', label: 'Create a new database' },
297
+ ...existing.map((db) => ({
298
+ value: db.name,
299
+ label: `Use database: ${tui.tuiColors.primary(db.name)}`,
300
+ })),
301
+ ],
302
+ });
303
+ }
304
+ else {
305
+ // No existing databases — user already opted in via the multi-select, so create new.
306
+ dbAction = 'Create New';
282
307
  }
283
- s3_action = storageOption;
284
- }
285
- }
286
- else if (isInteractive) {
287
- s3_action = await prompt.select({
288
- message: 'Create Storage Bucket?',
289
- options: [
290
- { value: 'Skip', label: 'Skip or Setup later' },
291
- { value: 'Create New', label: 'Create a new bucket' },
292
- ...resources.s3.map((bucket) => ({
293
- value: bucket.bucket_name,
294
- label: `Use bucket: ${tui.tuiColors.primary(bucket.bucket_name)}`,
295
- })),
296
- ],
297
- });
298
- }
299
- else {
300
- // Headless without flag - skip
301
- s3_action = 'Skip';
302
- }
303
- // Custom DNS: only prompt in interactive mode if not already provided
304
- if (!domains?.length && isInteractive) {
305
- const customDns = await prompt.text({
306
- message: 'Setup custom DNS?',
307
- hint: 'Enter a domain name or press Enter to skip',
308
- validate: (val) => val === ''
309
- ? true
310
- : /^(?=.{1,253}$)(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[A-Za-z]{2,63}$/.test(val),
311
- });
312
- if (customDns) {
313
- _domains = [customDns];
314
308
  }
315
- }
316
- // Process storage action
317
- switch (s3_action) {
318
- case 'Create New': {
319
- let bucketName;
320
- let bucketDescription;
321
- // Only prompt for name/description in interactive mode
309
+ if (dbAction === 'Create New') {
310
+ let dbName;
311
+ let dbDescription;
322
312
  if (isInteractive) {
323
- const bucketNameInput = await prompt.text({
324
- message: 'Bucket name',
325
- hint: 'Optional - lowercase letters, digits, hyphens only',
313
+ const suggestion = suggestDatabaseName(projectName);
314
+ const dbNameInput = await prompt.text({
315
+ message: 'Database name',
316
+ hint: 'Optional · lowercase letters, digits, underscores',
317
+ placeholder: suggestion,
326
318
  validate: (value) => {
327
319
  const trimmed = value.trim();
328
320
  if (trimmed === '')
329
321
  return true;
330
- const result = validateBucketName(trimmed);
322
+ const result = validateDatabaseName(trimmed);
331
323
  return result.valid ? true : result.error;
332
324
  },
333
325
  });
334
- bucketName = bucketNameInput.trim() || undefined;
335
- bucketDescription =
326
+ dbName = dbNameInput.trim() || undefined;
327
+ dbDescription =
336
328
  (await prompt.text({
337
- message: 'Bucket description',
338
- hint: 'Optional - press Enter to skip',
329
+ message: 'Database description',
330
+ hint: 'Optional · press Enter to skip',
339
331
  })) || undefined;
340
332
  }
341
333
  const created = await tui.spinner({
342
- message: 'Provisioning New Bucket',
334
+ message: 'Provisioning New SQL Database',
343
335
  clearOnSuccess: true,
344
336
  callback: async () => {
345
337
  return createResources(catalystClient, orgId, region, [
346
- {
347
- type: 's3',
348
- name: bucketName,
349
- description: bucketDescription,
350
- },
338
+ { type: 'db', name: dbName, description: dbDescription },
351
339
  ]);
352
340
  },
353
341
  });
354
- // Collect env vars from newly created resource
355
- if (created[0]?.env) {
342
+ if (created[0]?.env)
356
343
  Object.assign(resourceEnvVars, created[0].env);
357
- }
358
- break;
359
344
  }
360
- case 'Skip': {
361
- break;
345
+ else if (dbAction && dbAction !== 'Skip') {
346
+ // Existing database selected — reuse its env vars.
347
+ const selectedDb = resources?.db.find((d) => d.name === dbAction);
348
+ if (selectedDb?.env)
349
+ Object.assign(resourceEnvVars, selectedDb.env);
362
350
  }
363
- default: {
364
- // User selected an existing bucket - get env vars from the resources list
365
- const selectedBucket = resources?.s3.find((b) => b.bucket_name === s3_action);
366
- if (selectedBucket?.env) {
367
- Object.assign(resourceEnvVars, selectedBucket.env);
351
+ }
352
+ // Storage
353
+ if (wantStorage) {
354
+ let s3Action = storageFlagAction;
355
+ if (s3Action === undefined && isInteractive) {
356
+ const existing = resources?.s3 ?? [];
357
+ if (existing.length > 0) {
358
+ s3Action = await prompt.select({
359
+ message: 'Storage Bucket',
360
+ options: [
361
+ { value: 'Create New', label: 'Create a new bucket' },
362
+ ...existing.map((bucket) => ({
363
+ value: bucket.bucket_name,
364
+ label: `Use bucket: ${tui.tuiColors.primary(bucket.bucket_name)}`,
365
+ })),
366
+ ],
367
+ });
368
+ }
369
+ else {
370
+ s3Action = 'Create New';
368
371
  }
369
- break;
370
372
  }
371
- }
372
- // Process database action
373
- switch (db_action) {
374
- case 'Create New': {
375
- let dbName;
376
- let dbDescription;
377
- // Only prompt for name/description in interactive mode
373
+ if (s3Action === 'Create New') {
374
+ let bucketName;
375
+ let bucketDescription;
378
376
  if (isInteractive) {
379
- const dbNameInput = await prompt.text({
380
- message: 'Database name',
381
- hint: 'Optional - lowercase letters, digits, underscores only',
377
+ const suggestion = suggestBucketName(projectName);
378
+ const bucketNameInput = await prompt.text({
379
+ message: 'Bucket name',
380
+ hint: 'Optional · lowercase letters, digits, hyphens',
381
+ placeholder: suggestion,
382
382
  validate: (value) => {
383
383
  const trimmed = value.trim();
384
384
  if (trimmed === '')
385
385
  return true;
386
- const result = validateDatabaseName(trimmed);
386
+ const result = validateBucketName(trimmed);
387
387
  return result.valid ? true : result.error;
388
388
  },
389
389
  });
390
- dbName = dbNameInput.trim() || undefined;
391
- dbDescription =
390
+ bucketName = bucketNameInput.trim() || undefined;
391
+ bucketDescription =
392
392
  (await prompt.text({
393
- message: 'Database description',
394
- hint: 'Optional - press Enter to skip',
393
+ message: 'Bucket description',
394
+ hint: 'Optional · press Enter to skip',
395
395
  })) || undefined;
396
396
  }
397
397
  const created = await tui.spinner({
398
- message: 'Provisioning New SQL Database',
398
+ message: 'Provisioning New Bucket',
399
399
  clearOnSuccess: true,
400
400
  callback: async () => {
401
401
  return createResources(catalystClient, orgId, region, [
402
- {
403
- type: 'db',
404
- name: dbName,
405
- description: dbDescription,
406
- },
402
+ { type: 's3', name: bucketName, description: bucketDescription },
407
403
  ]);
408
404
  },
409
405
  });
410
- // Collect env vars from newly created resource
411
- if (created[0]?.env) {
406
+ if (created[0]?.env)
412
407
  Object.assign(resourceEnvVars, created[0].env);
413
- }
414
- break;
415
- }
416
- case 'Skip': {
417
- break;
418
- }
419
- default: {
420
- // User selected an existing database - get env vars from the resources list
421
- const selectedDb = resources?.db.find((d) => d.name === db_action);
422
- if (selectedDb?.env) {
423
- Object.assign(resourceEnvVars, selectedDb.env);
424
- }
425
- break;
426
- }
427
- }
428
- }
429
- // Auth setup - either from template, CLI flag, or user choice
430
- const templateHasAuth = selectedTemplate.id === 'agentuity-auth';
431
- let authEnabled = templateHasAuth; // Auth templates have auth enabled by default
432
- let authDatabaseName;
433
- let authDatabaseUrl;
434
- // Handle auth enablement: CLI flag > interactive prompt > disabled (headless)
435
- if (enableAuthOption !== undefined) {
436
- // CLI flag provided
437
- authEnabled = enableAuthOption;
438
- }
439
- else if (canProvision && isInteractive && !templateHasAuth) {
440
- // For non-auth templates in interactive mode, ask if they want to enable auth
441
- const enableAuth = await prompt.select({
442
- message: 'Enable Agentuity Authentication?',
443
- options: [
444
- { value: 'no', label: "No, I'll add auth later" },
445
- { value: 'yes', label: 'Yes, set up Agentuity Auth' },
446
- ],
447
- });
448
- if (enableAuth === 'yes') {
449
- authEnabled = true;
450
- }
451
- }
452
- // In headless mode without --enable-auth flag, authEnabled stays false (unless template has auth)
453
- // Set up database and secret for any auth-enabled project
454
- if (authEnabled && canProvision) {
455
- // If a database was already selected/created above, use it for auth
456
- if (resourceEnvVars.DATABASE_URL) {
457
- authDatabaseUrl = resourceEnvVars.DATABASE_URL;
458
- // Extract database name from URL using proper URL parsing
459
- try {
460
- const dbUrl = new URL(authDatabaseUrl);
461
- const dbName = dbUrl.pathname.replace(/^\/+/, ''); // Remove leading slashes
462
- // Validate: non-empty and contains only safe characters
463
- if (dbName && /^[A-Za-z0-9_-]+$/.test(dbName)) {
464
- authDatabaseName = dbName;
465
- }
466
- }
467
- catch {
468
- // Invalid URL format, authDatabaseName stays undefined
469
- }
470
- }
471
- else {
472
- // No database selected yet, create one for auth
473
- const created = await tui.spinner({
474
- message: 'Provisioning database for auth',
475
- clearOnSuccess: true,
476
- callback: async () => {
477
- return createResources(catalystClient, orgId, region, [{ type: 'db' }]);
478
- },
479
- });
480
- const createdDb = created[0];
481
- if (!createdDb) {
482
- logger.fatal('Failed to create database for auth', ErrorCode.RESOURCE_NOT_FOUND);
483
- return undefined;
484
408
  }
485
- authDatabaseName = createdDb.name;
486
- // Get env vars from created resource
487
- if (createdDb.env) {
488
- authDatabaseUrl = createdDb.env.DATABASE_URL;
489
- // Also add to resourceEnvVars if not already set
490
- if (!resourceEnvVars.DATABASE_URL) {
491
- Object.assign(resourceEnvVars, createdDb.env);
492
- }
493
- }
494
- }
495
- // Install auth dependencies (skip for agentuity-auth template which has them)
496
- if (!templateHasAuth) {
497
- await ensureAuthDependencies({ projectDir: dest, logger });
498
- // Generate auth.ts
499
- const authFilePath = resolve(dest, 'src', 'auth.ts');
500
- if (!existsSync(authFilePath)) {
501
- const srcDir = resolve(dest, 'src');
502
- if (!existsSync(srcDir)) {
503
- await Bun.write(resolve(srcDir, '.gitkeep'), '');
504
- }
505
- await Bun.write(authFilePath, generateAuthFileContent());
506
- tui.success('Created src/auth.ts');
409
+ else if (s3Action && s3Action !== 'Skip') {
410
+ const selectedBucket = resources?.s3.find((b) => b.bucket_name === s3Action);
411
+ if (selectedBucket?.env)
412
+ Object.assign(resourceEnvVars, selectedBucket.env);
507
413
  }
508
414
  }
509
- // Run migrations
510
- if (authDatabaseName) {
511
- const sql = await tui.spinner({
512
- message: 'Preparing auth database schema...',
513
- clearOnSuccess: true,
514
- callback: () => generateAuthSchemaSql(logger, dest),
515
- });
516
- await runAuthMigrations({
517
- logger,
518
- auth,
519
- orgId,
520
- region,
521
- databaseName: authDatabaseName,
522
- sql,
523
- config,
415
+ // Custom Domain
416
+ if (wantDomain && !domainFlagProvided && isInteractive) {
417
+ const customDns = await prompt.text({
418
+ message: 'Custom domain',
419
+ hint: 'e.g. agents.example.com',
420
+ validate: (val) => val === ''
421
+ ? 'Domain is required (or go back and uncheck Custom Domain)'
422
+ : DOMAIN_REGEX.test(val)
423
+ ? true
424
+ : 'Invalid domain',
524
425
  });
426
+ if (customDns)
427
+ _domains = [customDns];
525
428
  }
526
429
  }
527
430
  let projectId;
@@ -558,24 +461,9 @@ export async function runCreateFlow(options) {
558
461
  });
559
462
  },
560
463
  });
561
- // Add auth secret to resourceEnvVars if auth is enabled
562
- if (authEnabled && !resourceEnvVars.AGENTUITY_AUTH_SECRET) {
563
- const devSecret = `dev-${crypto.randomUUID()}`;
564
- resourceEnvVars.AGENTUITY_AUTH_SECRET = devSecret;
565
- }
566
464
  // Write resource environment variables to .env
567
465
  if (Object.keys(resourceEnvVars).length > 0) {
568
466
  await addResourceEnvVars(dest, resourceEnvVars);
569
- // Show user feedback for auth-related env vars
570
- if (authEnabled) {
571
- if (resourceEnvVars.DATABASE_URL) {
572
- tui.success('DATABASE_URL added to .env');
573
- }
574
- if (resourceEnvVars.AGENTUITY_AUTH_SECRET) {
575
- tui.success('AGENTUITY_AUTH_SECRET added to .env');
576
- tui.info(`Generate one with: ${tui.muted('npx @better-auth/cli secret')} or ${tui.muted('openssl rand -hex 32')}`);
577
- }
578
- }
579
467
  }
580
468
  // After registration, push any existing env/secrets from .env
581
469
  if (projectId) {
@@ -659,10 +547,6 @@ export async function runCreateFlow(options) {
659
547
  await promptForDNS(projectId, _domains, cloudRegion, config);
660
548
  }
661
549
  }
662
- // Print auth integration examples if auth was enabled (skip for auth template - already set up)
663
- if (authEnabled && !templateHasAuth) {
664
- printIntegrationExamples();
665
- }
666
550
  return {
667
551
  projectId,
668
552
  orgId,
@@ -676,6 +560,27 @@ export async function runCreateFlow(options) {
676
560
  error: setupResult.success ? undefined : 'Project setup completed with errors',
677
561
  };
678
562
  }
563
+ /**
564
+ * Normalize a CLI flag value (`--database` / `--storage`) into the same
565
+ * action vocabulary the interactive flow uses:
566
+ * - 'new' -> 'Create New'
567
+ * - 'skip' -> 'Skip'
568
+ * - any other string -> treated as an existing-resource name (returned as-is)
569
+ * - undefined -> undefined (no flag passed; multi-select decides)
570
+ *
571
+ * The existence check for named resources happens later, after the resource
572
+ * list is fetched.
573
+ */
574
+ function resolveFlagAction(flag, _kind) {
575
+ if (flag === undefined)
576
+ return undefined;
577
+ const lower = flag.toLowerCase();
578
+ if (lower === 'new')
579
+ return 'Create New';
580
+ if (lower === 'skip')
581
+ return 'Skip';
582
+ return flag;
583
+ }
679
584
  /**
680
585
  * Sanitize a project name to create a safe directory/package name
681
586
  * - Converts to lowercase