@agentuity/cli 0.0.101 → 0.0.103

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 (210) hide show
  1. package/AGENTS.md +19 -188
  2. package/bin/cli.ts +21 -14
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +41 -12
  5. package/dist/cli.js.map +1 -1
  6. package/dist/cmd/ai/index.d.ts.map +1 -1
  7. package/dist/cmd/ai/index.js +6 -1
  8. package/dist/cmd/ai/index.js.map +1 -1
  9. package/dist/cmd/ai/prompt/agent.d.ts +7 -0
  10. package/dist/cmd/ai/prompt/agent.d.ts.map +1 -1
  11. package/dist/cmd/ai/prompt/agent.js +12 -323
  12. package/dist/cmd/ai/prompt/agent.js.map +1 -1
  13. package/dist/cmd/ai/prompt/api.d.ts +7 -0
  14. package/dist/cmd/ai/prompt/api.d.ts.map +1 -1
  15. package/dist/cmd/ai/prompt/api.js +12 -260
  16. package/dist/cmd/ai/prompt/api.js.map +1 -1
  17. package/dist/cmd/ai/prompt/version.d.ts +35 -0
  18. package/dist/cmd/ai/prompt/version.d.ts.map +1 -0
  19. package/dist/cmd/ai/prompt/version.js +55 -0
  20. package/dist/cmd/ai/prompt/version.js.map +1 -0
  21. package/dist/cmd/ai/prompt/web.d.ts +7 -0
  22. package/dist/cmd/ai/prompt/web.d.ts.map +1 -1
  23. package/dist/cmd/ai/prompt/web.js +12 -283
  24. package/dist/cmd/ai/prompt/web.js.map +1 -1
  25. package/dist/cmd/ai/skills/generate.d.ts +3 -0
  26. package/dist/cmd/ai/skills/generate.d.ts.map +1 -0
  27. package/dist/cmd/ai/skills/generate.js +65 -0
  28. package/dist/cmd/ai/skills/generate.js.map +1 -0
  29. package/dist/cmd/ai/skills/generator.d.ts +4 -0
  30. package/dist/cmd/ai/skills/generator.d.ts.map +1 -0
  31. package/dist/cmd/ai/skills/generator.js +402 -0
  32. package/dist/cmd/ai/skills/generator.js.map +1 -0
  33. package/dist/cmd/ai/skills/index.d.ts +4 -0
  34. package/dist/cmd/ai/skills/index.d.ts.map +1 -0
  35. package/dist/cmd/ai/skills/index.js +21 -0
  36. package/dist/cmd/ai/skills/index.js.map +1 -0
  37. package/dist/cmd/auth/signup.d.ts.map +1 -1
  38. package/dist/cmd/auth/signup.js +1 -0
  39. package/dist/cmd/auth/signup.js.map +1 -1
  40. package/dist/cmd/build/entry-generator.d.ts.map +1 -1
  41. package/dist/cmd/build/entry-generator.js +40 -5
  42. package/dist/cmd/build/entry-generator.js.map +1 -1
  43. package/dist/cmd/build/vite/bun-dev-server.d.ts +7 -1
  44. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
  45. package/dist/cmd/build/vite/bun-dev-server.js +30 -26
  46. package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
  47. package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
  48. package/dist/cmd/build/vite/metadata-generator.js +58 -7
  49. package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
  50. package/dist/cmd/build/vite/prompt-generator.d.ts +23 -0
  51. package/dist/cmd/build/vite/prompt-generator.d.ts.map +1 -0
  52. package/dist/cmd/build/vite/prompt-generator.js +123 -0
  53. package/dist/cmd/build/vite/prompt-generator.js.map +1 -0
  54. package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
  55. package/dist/cmd/build/vite/registry-generator.js +28 -11
  56. package/dist/cmd/build/vite/registry-generator.js.map +1 -1
  57. package/dist/cmd/build/vite/server-bundler.d.ts +4 -0
  58. package/dist/cmd/build/vite/server-bundler.d.ts.map +1 -1
  59. package/dist/cmd/build/vite/server-bundler.js +45 -16
  60. package/dist/cmd/build/vite/server-bundler.js.map +1 -1
  61. package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
  62. package/dist/cmd/build/vite/vite-asset-server-config.js +4 -0
  63. package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
  64. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  65. package/dist/cmd/build/vite/vite-builder.js +99 -87
  66. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  67. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  68. package/dist/cmd/cloud/deploy.js +80 -27
  69. package/dist/cmd/cloud/deploy.js.map +1 -1
  70. package/dist/cmd/cloud/keyvalue/create-namespace.d.ts.map +1 -1
  71. package/dist/cmd/cloud/keyvalue/create-namespace.js +3 -1
  72. package/dist/cmd/cloud/keyvalue/create-namespace.js.map +1 -1
  73. package/dist/cmd/cloud/keyvalue/delete-namespace.d.ts.map +1 -1
  74. package/dist/cmd/cloud/keyvalue/delete-namespace.js +3 -1
  75. package/dist/cmd/cloud/keyvalue/delete-namespace.js.map +1 -1
  76. package/dist/cmd/cloud/keyvalue/delete.d.ts.map +1 -1
  77. package/dist/cmd/cloud/keyvalue/delete.js +3 -1
  78. package/dist/cmd/cloud/keyvalue/delete.js.map +1 -1
  79. package/dist/cmd/cloud/keyvalue/set.d.ts.map +1 -1
  80. package/dist/cmd/cloud/keyvalue/set.js +4 -2
  81. package/dist/cmd/cloud/keyvalue/set.js.map +1 -1
  82. package/dist/cmd/cloud/stream/get.d.ts.map +1 -1
  83. package/dist/cmd/cloud/stream/get.js +2 -13
  84. package/dist/cmd/cloud/stream/get.js.map +1 -1
  85. package/dist/cmd/cloud/vector/delete-namespace.d.ts +3 -0
  86. package/dist/cmd/cloud/vector/delete-namespace.d.ts.map +1 -0
  87. package/dist/cmd/cloud/vector/delete-namespace.js +77 -0
  88. package/dist/cmd/cloud/vector/delete-namespace.js.map +1 -0
  89. package/dist/cmd/cloud/vector/index.d.ts.map +1 -1
  90. package/dist/cmd/cloud/vector/index.js +21 -4
  91. package/dist/cmd/cloud/vector/index.js.map +1 -1
  92. package/dist/cmd/cloud/vector/list-namespaces.d.ts +3 -0
  93. package/dist/cmd/cloud/vector/list-namespaces.d.ts.map +1 -0
  94. package/dist/cmd/cloud/vector/list-namespaces.js +42 -0
  95. package/dist/cmd/cloud/vector/list-namespaces.js.map +1 -0
  96. package/dist/cmd/cloud/vector/stats.d.ts +3 -0
  97. package/dist/cmd/cloud/vector/stats.d.ts.map +1 -0
  98. package/dist/cmd/cloud/vector/stats.js +142 -0
  99. package/dist/cmd/cloud/vector/stats.js.map +1 -0
  100. package/dist/cmd/cloud/vector/upsert.d.ts +3 -0
  101. package/dist/cmd/cloud/vector/upsert.d.ts.map +1 -0
  102. package/dist/cmd/cloud/vector/upsert.js +192 -0
  103. package/dist/cmd/cloud/vector/upsert.js.map +1 -0
  104. package/dist/cmd/dev/file-watcher.d.ts.map +1 -1
  105. package/dist/cmd/dev/file-watcher.js +90 -31
  106. package/dist/cmd/dev/file-watcher.js.map +1 -1
  107. package/dist/cmd/dev/index.d.ts.map +1 -1
  108. package/dist/cmd/dev/index.js +244 -64
  109. package/dist/cmd/dev/index.js.map +1 -1
  110. package/dist/cmd/dev/skills.d.ts +10 -0
  111. package/dist/cmd/dev/skills.d.ts.map +1 -0
  112. package/dist/cmd/dev/skills.js +57 -0
  113. package/dist/cmd/dev/skills.js.map +1 -0
  114. package/dist/cmd/dev/sync.js +7 -7
  115. package/dist/cmd/dev/sync.js.map +1 -1
  116. package/dist/cmd/index.d.ts.map +1 -1
  117. package/dist/cmd/index.js +1 -0
  118. package/dist/cmd/index.js.map +1 -1
  119. package/dist/cmd/project/create.d.ts.map +1 -1
  120. package/dist/cmd/project/create.js +3 -0
  121. package/dist/cmd/project/create.js.map +1 -1
  122. package/dist/cmd/project/template-flow.d.ts +1 -0
  123. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  124. package/dist/cmd/project/template-flow.js +30 -5
  125. package/dist/cmd/project/template-flow.js.map +1 -1
  126. package/dist/cmd/setup/index.d.ts.map +1 -1
  127. package/dist/cmd/setup/index.js +1 -0
  128. package/dist/cmd/setup/index.js.map +1 -1
  129. package/dist/cmd/upgrade/index.d.ts +15 -0
  130. package/dist/cmd/upgrade/index.d.ts.map +1 -1
  131. package/dist/cmd/upgrade/index.js +59 -4
  132. package/dist/cmd/upgrade/index.js.map +1 -1
  133. package/dist/domain.d.ts +45 -0
  134. package/dist/domain.d.ts.map +1 -0
  135. package/dist/domain.js +200 -0
  136. package/dist/domain.js.map +1 -0
  137. package/dist/schema-generator.d.ts +2 -0
  138. package/dist/schema-generator.d.ts.map +1 -1
  139. package/dist/schema-generator.js +18 -0
  140. package/dist/schema-generator.js.map +1 -1
  141. package/dist/steps.d.ts +1 -1
  142. package/dist/steps.d.ts.map +1 -1
  143. package/dist/steps.js +16 -5
  144. package/dist/steps.js.map +1 -1
  145. package/dist/tui/prompt.d.ts +1 -2
  146. package/dist/tui/prompt.d.ts.map +1 -1
  147. package/dist/tui/prompt.js +8 -4
  148. package/dist/tui/prompt.js.map +1 -1
  149. package/dist/tui.d.ts +16 -0
  150. package/dist/tui.d.ts.map +1 -1
  151. package/dist/tui.js +23 -2
  152. package/dist/tui.js.map +1 -1
  153. package/dist/types.d.ts +9 -2
  154. package/dist/types.d.ts.map +1 -1
  155. package/dist/types.js +3 -3
  156. package/dist/types.js.map +1 -1
  157. package/package.json +4 -4
  158. package/src/cli.ts +47 -12
  159. package/src/cmd/ai/index.ts +6 -1
  160. package/src/cmd/ai/prompt/agent.md +306 -0
  161. package/src/cmd/ai/prompt/agent.ts +12 -322
  162. package/src/cmd/ai/prompt/api.md +360 -0
  163. package/src/cmd/ai/prompt/api.ts +13 -260
  164. package/src/cmd/ai/prompt/version.ts +61 -0
  165. package/src/cmd/ai/prompt/web.md +509 -0
  166. package/src/cmd/ai/prompt/web.ts +12 -282
  167. package/src/cmd/ai/skills/generate.ts +75 -0
  168. package/src/cmd/ai/skills/generator.ts +519 -0
  169. package/src/cmd/ai/skills/index.ts +23 -0
  170. package/src/cmd/auth/signup.ts +1 -0
  171. package/src/cmd/build/entry-generator.ts +43 -7
  172. package/src/cmd/build/vite/bun-dev-server.ts +31 -28
  173. package/src/cmd/build/vite/metadata-generator.ts +73 -7
  174. package/src/cmd/build/vite/prompt-generator.ts +169 -0
  175. package/src/cmd/build/vite/registry-generator.ts +33 -10
  176. package/src/cmd/build/vite/server-bundler.ts +53 -22
  177. package/src/cmd/build/vite/vite-asset-server-config.ts +5 -0
  178. package/src/cmd/build/vite/vite-builder.ts +107 -87
  179. package/src/cmd/cloud/deploy.ts +103 -31
  180. package/src/cmd/cloud/keyvalue/create-namespace.ts +3 -1
  181. package/src/cmd/cloud/keyvalue/delete-namespace.ts +3 -1
  182. package/src/cmd/cloud/keyvalue/delete.ts +3 -1
  183. package/src/cmd/cloud/keyvalue/set.ts +4 -2
  184. package/src/cmd/cloud/stream/get.ts +2 -9
  185. package/src/cmd/cloud/vector/delete-namespace.ts +89 -0
  186. package/src/cmd/cloud/vector/index.ts +21 -4
  187. package/src/cmd/cloud/vector/list-namespaces.ts +46 -0
  188. package/src/cmd/cloud/vector/stats.ts +160 -0
  189. package/src/cmd/cloud/vector/upsert.ts +216 -0
  190. package/src/cmd/dev/file-watcher.ts +101 -32
  191. package/src/cmd/dev/index.ts +343 -115
  192. package/src/cmd/dev/skills.ts +82 -0
  193. package/src/cmd/dev/sync.ts +7 -7
  194. package/src/cmd/index.ts +1 -0
  195. package/src/cmd/project/create.ts +3 -0
  196. package/src/cmd/project/template-flow.ts +37 -5
  197. package/src/cmd/setup/index.ts +1 -0
  198. package/src/cmd/upgrade/index.ts +68 -4
  199. package/src/domain.ts +273 -0
  200. package/src/schema-generator.ts +23 -0
  201. package/src/steps.ts +16 -5
  202. package/src/tui/prompt.ts +11 -5
  203. package/src/tui.ts +21 -2
  204. package/src/types/md.d.ts +8 -0
  205. package/src/types.ts +12 -3
  206. package/dist/cmd/cloud/domain.d.ts +0 -17
  207. package/dist/cmd/cloud/domain.d.ts.map +0 -1
  208. package/dist/cmd/cloud/domain.js +0 -79
  209. package/dist/cmd/cloud/domain.js.map +0 -1
  210. package/src/cmd/cloud/domain.ts +0 -100
@@ -5,10 +5,43 @@
5
5
  */
6
6
 
7
7
  import { join } from 'node:path';
8
- import type { InlineConfig } from 'vite';
8
+ import { existsSync, renameSync, rmSync } from 'node:fs';
9
+ import type { InlineConfig, Plugin } from 'vite';
9
10
  import type { Logger } from '../../../types';
10
11
  import { browserEnvPlugin } from './browser-env-plugin';
11
12
 
13
+ /**
14
+ * Vite plugin to flatten the output structure for index.html
15
+ *
16
+ * When root is set to the project root (for TanStack Router compatibility),
17
+ * Vite outputs index.html to .agentuity/client/src/web/index.html instead of
18
+ * .agentuity/client/index.html. This plugin moves it to the expected location.
19
+ */
20
+ function flattenHtmlOutputPlugin(outDir: string): Plugin {
21
+ return {
22
+ name: 'agentuity:flatten-html-output',
23
+ apply: 'build',
24
+ closeBundle() {
25
+ const nestedHtmlPath = join(outDir, 'src', 'web', 'index.html');
26
+ const targetHtmlPath = join(outDir, 'index.html');
27
+
28
+ if (existsSync(nestedHtmlPath)) {
29
+ renameSync(nestedHtmlPath, targetHtmlPath);
30
+
31
+ // Clean up empty src/web directory structure
32
+ const srcWebDir = join(outDir, 'src', 'web');
33
+ const srcDir = join(outDir, 'src');
34
+ try {
35
+ rmSync(srcWebDir, { recursive: true, force: true });
36
+ rmSync(srcDir, { recursive: true, force: true });
37
+ } catch {
38
+ // Ignore cleanup errors
39
+ }
40
+ }
41
+ },
42
+ };
43
+ }
44
+
12
45
  export interface ViteBuildOptions {
13
46
  rootDir: string;
14
47
  mode: 'client' | 'server' | 'workbench';
@@ -34,38 +67,40 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
34
67
 
35
68
  // For server mode, use Bun.build (preserves process.env at runtime)
36
69
  if (mode === 'server') {
37
- try {
38
- const srcDir = join(rootDir, 'src');
39
-
40
- // Generate documentation files (if they don't exist)
41
- const { generateDocumentation } = await import('./docs-generator');
42
- await generateDocumentation(srcDir, logger);
43
-
44
- // Generate lifecycle types (if setup() exists)
45
- const { generateLifecycleTypes } = await import('./lifecycle-generator');
46
- await generateLifecycleTypes(rootDir, srcDir, logger);
47
-
48
- // Then, generate the entry file
49
- const { generateEntryFile } = await import('../entry-generator');
50
- await generateEntryFile({
51
- rootDir,
52
- projectId,
53
- deploymentId: deploymentId || '',
54
- logger,
55
- mode: dev ? 'dev' : 'prod',
56
- });
57
-
58
- // Finally, build with Bun.build
59
- const { installExternalsAndBuild } = await import('./server-bundler');
60
- await installExternalsAndBuild({
61
- rootDir,
62
- dev,
63
- logger,
64
- });
65
- } catch (error) {
66
- logger.error('server-bundler import or execution failed: %s', error);
67
- throw error;
70
+ const srcDir = join(rootDir, 'src');
71
+
72
+ // Generate documentation files (if they don't exist)
73
+ const { generateDocumentation } = await import('./docs-generator');
74
+ await generateDocumentation(srcDir, logger);
75
+
76
+ // Generate/update prompt files in dev mode only (non-blocking)
77
+ if (dev) {
78
+ import('./prompt-generator')
79
+ .then(({ generatePromptFiles }) => generatePromptFiles(srcDir, logger))
80
+ .catch((err) => logger.warn('Failed to generate prompt files: %s', err.message));
68
81
  }
82
+
83
+ // Generate lifecycle types (if setup() exists)
84
+ const { generateLifecycleTypes } = await import('./lifecycle-generator');
85
+ await generateLifecycleTypes(rootDir, srcDir, logger);
86
+
87
+ // Then, generate the entry file
88
+ const { generateEntryFile } = await import('../entry-generator');
89
+ await generateEntryFile({
90
+ rootDir,
91
+ projectId,
92
+ deploymentId: deploymentId || '',
93
+ logger,
94
+ mode: dev ? 'dev' : 'prod',
95
+ });
96
+
97
+ // Finally, build with Bun.build
98
+ const { installExternalsAndBuild } = await import('./server-bundler');
99
+ await installExternalsAndBuild({
100
+ rootDir,
101
+ dev,
102
+ logger,
103
+ });
69
104
  return;
70
105
  }
71
106
 
@@ -85,7 +120,8 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
85
120
  const { workbenchEnabled = false, workbenchRoute = '/workbench' } = options;
86
121
 
87
122
  // Load custom user plugins from agentuity.config.ts if it exists
88
- const plugins = [react(), browserEnvPlugin()];
123
+ const clientOutDir = join(rootDir, '.agentuity/client');
124
+ const plugins = [react(), browserEnvPlugin(), flattenHtmlOutputPlugin(clientOutDir)];
89
125
  const { loadAgentuityConfig } = await import('./config-loader');
90
126
  const userConfig = await loadAgentuityConfig(rootDir, logger);
91
127
  const userPlugins = userConfig?.plugins || [];
@@ -104,14 +140,18 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
104
140
  }
105
141
 
106
142
  // Determine CDN base URL for production builds
143
+ // Use CDN for all non-dev builds with a deploymentId (including local region)
107
144
  const isLocalRegion = options.region === 'local';
145
+ const cdnDomain = isLocalRegion
146
+ ? 'localstack-static-assets.t3.storage.dev'
147
+ : 'static.agentuity.com';
108
148
  const cdnBaseUrl =
109
- !dev && deploymentId && !isLocalRegion
110
- ? `https://static.agentuity.com/${deploymentId}/client/`
111
- : undefined;
149
+ !dev && deploymentId ? `https://${cdnDomain}/${deploymentId}/client/` : undefined;
112
150
 
113
151
  viteConfig = {
114
- root: join(rootDir, 'src', 'web'), // Set web dir as root
152
+ // Use project root as Vite root so plugins (e.g., TanStack Router) resolve paths
153
+ // from the repo root, matching where agentuity.config.ts is located
154
+ root: rootDir,
115
155
  plugins,
116
156
  envPrefix: ['VITE_', 'AGENTUITY_PUBLIC_', 'PUBLIC_'],
117
157
  publicDir: join(rootDir, 'src', 'web', 'public'),
@@ -126,7 +166,7 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
126
166
  : 'undefined',
127
167
  },
128
168
  build: {
129
- outDir: join(rootDir, '.agentuity/client'),
169
+ outDir: clientOutDir,
130
170
  rollupOptions: {
131
171
  input: htmlPath,
132
172
  },
@@ -177,20 +217,15 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
177
217
  }
178
218
 
179
219
  // Build with Vite
180
- try {
181
- // Force the build to use the correct mode
182
- const buildMode = dev ? 'development' : 'production';
220
+ // Force the build to use the correct mode
221
+ const buildMode = dev ? 'development' : 'production';
183
222
 
184
- await viteBuild({
185
- ...viteConfig,
186
- mode: buildMode,
187
- });
223
+ await viteBuild({
224
+ ...viteConfig,
225
+ mode: buildMode,
226
+ });
188
227
 
189
- logger.debug(`Vite build complete for mode: ${mode}`);
190
- } catch (error) {
191
- logger.error(`Vite build failed for mode ${mode}:`, error);
192
- throw error;
193
- }
228
+ logger.debug(`Vite build complete for mode: ${mode}`);
194
229
  }
195
230
 
196
231
  interface BuildResult {
@@ -255,20 +290,15 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
255
290
  // 2. Build client (only if web frontend exists)
256
291
  if (hasWebFrontend) {
257
292
  logger.debug('Building client assets...');
258
- try {
259
- const started = Date.now();
260
- await runViteBuild({
261
- ...options,
262
- mode: 'client',
263
- workbenchEnabled: workbenchConfig.enabled,
264
- workbenchRoute: workbenchConfig.route,
265
- });
266
- result.client.included = true;
267
- result.client.duration = Date.now() - started;
268
- } catch (error) {
269
- logger.error('Client build failed:', error);
270
- throw error;
271
- }
293
+ const started = Date.now();
294
+ await runViteBuild({
295
+ ...options,
296
+ mode: 'client',
297
+ workbenchEnabled: workbenchConfig.enabled,
298
+ workbenchRoute: workbenchConfig.route,
299
+ });
300
+ result.client.included = true;
301
+ result.client.duration = Date.now() - started;
272
302
  } else {
273
303
  logger.debug('Skipping client build - no src/web/index.html found');
274
304
  }
@@ -276,33 +306,23 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
276
306
  // 3. Build workbench (if enabled in config)
277
307
  if (workbenchConfig.enabled) {
278
308
  logger.debug('Building workbench assets...');
279
- try {
280
- const started = Date.now();
281
- await runViteBuild({
282
- ...options,
283
- mode: 'workbench',
284
- workbenchRoute: workbenchConfig.route,
285
- workbenchEnabled: true,
286
- });
287
- result.workbench.included = true;
288
- result.workbench.duration = Date.now() - started;
289
- } catch (error) {
290
- logger.error('Workbench build failed:', error);
291
- throw error;
292
- }
309
+ const started = Date.now();
310
+ await runViteBuild({
311
+ ...options,
312
+ mode: 'workbench',
313
+ workbenchRoute: workbenchConfig.route,
314
+ workbenchEnabled: true,
315
+ });
316
+ result.workbench.included = true;
317
+ result.workbench.duration = Date.now() - started;
293
318
  }
294
319
 
295
320
  // 4. Build server
296
321
  logger.debug('Building server...');
297
- try {
298
- const started = Date.now();
299
- await runViteBuild({ ...options, mode: 'server' });
300
- result.server.included = true;
301
- result.server.duration = Date.now() - started;
302
- } catch (error) {
303
- logger.error('Server build failed:', error);
304
- throw error;
305
- }
322
+ const serverStarted = Date.now();
323
+ await runViteBuild({ ...options, mode: 'server' });
324
+ result.server.included = true;
325
+ result.server.duration = Date.now() - serverStarted;
306
326
 
307
327
  // 5. Generate metadata (after all builds complete)
308
328
  logger.debug('Generating metadata...');
@@ -14,6 +14,7 @@ import {
14
14
  stepSuccess,
15
15
  stepSkipped,
16
16
  stepError,
17
+ pauseStepUI,
17
18
  type Step,
18
19
  type StepContext,
19
20
  } from '../../steps';
@@ -41,7 +42,7 @@ import {
41
42
  import { zipDir } from '../../utils/zip';
42
43
  import { encryptFIPSKEMDEMStream } from '../../crypto/box';
43
44
  import { getCommand } from '../../command-prefix';
44
- import { checkCustomDomainForDNS } from './domain';
45
+ import * as domain from '../../domain';
45
46
  import { DeployOptionsSchema } from '../../schemas/deploy';
46
47
  import { ErrorCode } from '../../errors';
47
48
 
@@ -107,6 +108,35 @@ export const deploySubcommand = createSubcommand({
107
108
  let statusResult: DeploymentStatusResult | undefined;
108
109
  const logs: string[] = [];
109
110
 
111
+ // Check for pre-created deployment from CI/Nova
112
+ const deploymentEnv = process.env.AGENTUITY_DEPLOYMENT;
113
+ let useExistingDeployment = false;
114
+ if (deploymentEnv) {
115
+ const ExistingDeploymentSchema = z.object({
116
+ id: z.string(),
117
+ orgId: z.string(),
118
+ publicKey: z.string(),
119
+ });
120
+ try {
121
+ const parsed = JSON.parse(deploymentEnv);
122
+ const result = ExistingDeploymentSchema.safeParse(parsed);
123
+ if (result.success) {
124
+ deployment = result.data;
125
+ useExistingDeployment = true;
126
+ logger.info(`Using existing deployment: ${result.data.id}`);
127
+ } else {
128
+ const errors = result.error.issues
129
+ .map((i) => `${i.path.join('.')}: ${i.message}`)
130
+ .join(', ');
131
+ logger.warn(`Invalid AGENTUITY_DEPLOYMENT schema: ${errors}`);
132
+ }
133
+ } catch (err) {
134
+ logger.warn(
135
+ `Failed to parse AGENTUITY_DEPLOYMENT: ${err instanceof Error ? err.message : String(err)}`
136
+ );
137
+ }
138
+ }
139
+
110
140
  const sdkKey = await loadProjectSDKKey(ctx.logger, ctx.projectDir);
111
141
 
112
142
  // Ensure SDK key is present before proceeding
@@ -124,24 +154,20 @@ export const deploySubcommand = createSubcommand({
124
154
  !project.deployment?.domains?.length
125
155
  ? null
126
156
  : {
127
- label: `Validate Custom Domain${project.deployment.domains.length > 1 ? `s: ${project.deployment.domains.join(', ')}` : `: ${project.deployment.domains[0]}`}`,
157
+ label: `Validate Custom ${tui.plural(project.deployment.domains.length, 'Domain', 'Domains')}`,
128
158
  run: async () => {
129
159
  if (project.deployment?.domains?.length) {
130
- const result = await checkCustomDomainForDNS(
131
- project.projectId,
132
- project.deployment.domains,
133
- config
134
- );
135
- for (const r of result) {
136
- if (r.success) {
137
- continue;
138
- }
139
- if (r.message) {
140
- return stepError(r.message);
141
- }
142
- return stepError('unknown dns error'); // shouldn't get here
160
+ try {
161
+ await domain.promptForDNS(
162
+ project.projectId,
163
+ project.deployment.domains,
164
+ config!,
165
+ () => pauseStepUI(true)
166
+ );
167
+ return stepSuccess();
168
+ } catch (ex) {
169
+ return stepError(String(ex), ex as Error);
143
170
  }
144
- return stepSuccess();
145
171
  }
146
172
  return stepSkipped();
147
173
  },
@@ -186,6 +212,9 @@ export const deploySubcommand = createSubcommand({
186
212
  {
187
213
  label: 'Create Deployment',
188
214
  run: async () => {
215
+ if (useExistingDeployment && deployment) {
216
+ return stepSkipped('using existing deployment');
217
+ }
189
218
  try {
190
219
  deployment = await projectDeploymentCreate(
191
220
  apiClient,
@@ -334,6 +363,7 @@ export const deploySubcommand = createSubcommand({
334
363
  }
335
364
 
336
365
  progress(80);
366
+ let bytes = 0;
337
367
  if (build?.assets) {
338
368
  ctx.logger.trace(`Uploading ${build.assets.length} assets`);
339
369
  if (!instructions.assets) {
@@ -343,9 +373,9 @@ export const deploySubcommand = createSubcommand({
343
373
  }
344
374
 
345
375
  // Workaround for Bun crash in compiled executables (https://github.com/agentuity/sdk/issues/191)
346
- // Use limited concurrency (2 at a time) for executables to avoid parallel fetch crash
376
+ // Use limited concurrency (1 at a time) for executables to avoid parallel fetch crash
347
377
  const isExecutable = isRunningFromExecutable();
348
- const concurrency = isExecutable ? 2 : build.assets.length;
378
+ const concurrency = isExecutable ? 1 : Math.min(4, build.assets.length);
349
379
 
350
380
  if (isExecutable) {
351
381
  ctx.logger.trace(
@@ -367,15 +397,34 @@ export const deploySubcommand = createSubcommand({
367
397
  }
368
398
 
369
399
  // Asset filename already includes the subdirectory (e.g., "client/assets/main-abc123.js")
370
- const file = Bun.file(join(projectDir, '.agentuity', asset.filename));
400
+ const filePath = join(projectDir, '.agentuity', asset.filename);
401
+
402
+ const headers: Record<string, string> = {
403
+ 'Content-Type': asset.contentType,
404
+ };
405
+
406
+ bytes += asset.size;
407
+
408
+ let body: Uint8Array | Blob;
409
+ if (asset.contentEncoding === 'gzip') {
410
+ const file = Bun.file(filePath);
411
+ const ab = await file.arrayBuffer();
412
+ const gzipped = Bun.gzipSync(new Uint8Array(ab));
413
+ headers['Content-Encoding'] = 'gzip';
414
+ body = gzipped;
415
+ ctx.logger.trace(
416
+ `Compressing ${asset.filename} (${asset.size} -> ${gzipped.byteLength} bytes)`
417
+ );
418
+ } else {
419
+ body = Bun.file(filePath);
420
+ }
421
+
371
422
  promises.push(
372
423
  fetch(assetUrl, {
373
424
  method: 'PUT',
374
425
  duplex: 'half',
375
- headers: {
376
- 'Content-Type': asset.contentType,
377
- },
378
- body: file,
426
+ headers,
427
+ body,
379
428
  })
380
429
  );
381
430
  }
@@ -392,7 +441,14 @@ export const deploySubcommand = createSubcommand({
392
441
  }
393
442
 
394
443
  progress(100);
395
- return stepSuccess();
444
+ const output = build?.assets.length
445
+ ? [
446
+ tui.muted(
447
+ `✓ Uploaded ${build.assets.length} ${tui.plural(build.assets.length, 'asset', 'assets')} (${tui.formatBytes(bytes)}) to CDN`
448
+ ),
449
+ ]
450
+ : undefined;
451
+ return stepSuccess(output);
396
452
  },
397
453
  },
398
454
  {
@@ -406,7 +462,7 @@ export const deploySubcommand = createSubcommand({
406
462
  },
407
463
  },
408
464
  ].filter(Boolean) as Step[],
409
- options.logLevel
465
+ useExistingDeployment ? 'debug' : options.logLevel
410
466
  );
411
467
 
412
468
  if (!deployment) {
@@ -617,20 +673,36 @@ export const deploySubcommand = createSubcommand({
617
673
 
618
674
  // Show deployment URLs
619
675
  if (complete?.publicUrls) {
676
+ const lines: string[] = [];
620
677
  if (complete.publicUrls.custom?.length) {
621
678
  for (const url of complete.publicUrls.custom) {
622
- tui.arrow(tui.bold(tui.padRight('Deployment URL:', 17)) + tui.link(url));
679
+ lines.push(
680
+ `${tui.ICONS.arrow} ${tui.bold(tui.padRight('Deployment:', 12)) + tui.link(url)}`
681
+ );
623
682
  }
624
683
  } else {
625
- tui.arrow(
626
- tui.bold(tui.padRight('Deployment URL:', 17)) +
684
+ lines.push(
685
+ `${tui.ICONS.arrow} ${
686
+ tui.bold(tui.padRight('Deployment:', 12)) +
627
687
  tui.link(complete.publicUrls.deployment)
688
+ }`
628
689
  );
629
- tui.arrow(
630
- tui.bold(tui.padRight('Project URL:', 17)) + tui.link(complete.publicUrls.latest)
690
+ lines.push(
691
+ `${tui.ICONS.arrow} ${
692
+ tui.bold(tui.padRight('Project:', 12)) + tui.link(complete.publicUrls.latest)
693
+ }`
631
694
  );
632
- tui.arrow(tui.bold(tui.padRight('Dashboard URL:', 17)) + tui.link(dashboard));
633
695
  }
696
+ lines.push(
697
+ `${tui.ICONS.arrow} ${
698
+ tui.bold(tui.padRight('Dashboard:', 12)) + tui.link(dashboard)
699
+ }`
700
+ );
701
+ tui.banner(`Deployment: ${tui.colorPrimary(deployment.id)}`, lines.join('\n'), {
702
+ centerTitle: false,
703
+ topSpacer: false,
704
+ bottomSpacer: false,
705
+ });
634
706
  }
635
707
 
636
708
  return {
@@ -37,7 +37,9 @@ export const createNamespaceSubcommand = createCommand({
37
37
  const kv = await createStorageAdapter(ctx);
38
38
 
39
39
  await kv.createNamespace(args.name);
40
- tui.success(`Namespace ${tui.bold(args.name)} created`);
40
+ if (!ctx.options.json) {
41
+ tui.success(`Namespace ${tui.bold(args.name)} created`);
42
+ }
41
43
 
42
44
  return {
43
45
  success: true,
@@ -68,7 +68,9 @@ export const deleteNamespaceSubcommand = createCommand({
68
68
  }
69
69
 
70
70
  await kv.deleteNamespace(args.name);
71
- tui.success(`Namespace ${tui.bold(args.name)} deleted`);
71
+ if (!ctx.options.json) {
72
+ tui.success(`Namespace ${tui.bold(args.name)} deleted`);
73
+ }
72
74
 
73
75
  return {
74
76
  success: true,
@@ -39,7 +39,9 @@ export const deleteSubcommand = createCommand({
39
39
  const storage = await createStorageAdapter(ctx);
40
40
  await storage.delete(args.namespace, args.key);
41
41
  const durationMs = Date.now() - started;
42
- tui.success(`deleted in ${durationMs.toFixed(1)}ms`);
42
+ if (!ctx.options.json) {
43
+ tui.success(`deleted in ${durationMs.toFixed(1)}ms`);
44
+ }
43
45
 
44
46
  return {
45
47
  success: true,
@@ -47,7 +47,7 @@ export const setSubcommand = createCommand({
47
47
  },
48
48
 
49
49
  async handler(ctx) {
50
- const { args } = ctx;
50
+ const { args, options } = ctx;
51
51
  const started = Date.now();
52
52
  const storage = await createStorageAdapter(ctx);
53
53
  const contentType = isPossiblyJSON(args.value) ? 'application/json' : 'text/plain';
@@ -57,7 +57,9 @@ export const setSubcommand = createCommand({
57
57
  ttl,
58
58
  });
59
59
  const durationMs = Date.now() - started;
60
- tui.success(`saved in ${durationMs.toFixed(1)}ms (${contentType})`);
60
+ if (!options.json) {
61
+ tui.success(`saved in ${durationMs.toFixed(1)}ms (${contentType})`);
62
+ }
61
63
 
62
64
  return {
63
65
  success: true,
@@ -3,13 +3,6 @@ import { createCommand } from '../../../types';
3
3
  import * as tui from '../../../tui';
4
4
  import { createStorageAdapter } from './util';
5
5
  import { getCommand } from '../../../command-prefix';
6
- function formatBytes(bytes: number): string {
7
- if (bytes === 0) return '0 B';
8
- if (bytes < 1024) return `${bytes} B`;
9
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
10
- if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
11
- return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
12
- }
13
6
 
14
7
  const GetStreamResponseSchema = z.object({
15
8
  id: z.string().describe('Stream ID'),
@@ -70,7 +63,7 @@ export const getSubcommand = createCommand({
70
63
  const durationMs = Date.now() - started;
71
64
  const stats = await Bun.file(opts.output).stat();
72
65
  tui.success(
73
- `downloaded ${formatBytes(stats.size)} to ${opts.output} in ${durationMs.toFixed(1)}ms`
66
+ `downloaded ${tui.formatBytes(stats.size)} to ${opts.output} in ${durationMs.toFixed(1)}ms`
74
67
  );
75
68
 
76
69
  // Fetch stream metadata to populate the response
@@ -100,7 +93,7 @@ export const getSubcommand = createCommand({
100
93
 
101
94
  console.log(`Name: ${tui.bold(stream.name ?? 'unknown')}`);
102
95
  console.log(`ID: ${stream.id}`);
103
- console.log(`Size: ${formatBytes(sizeBytes)}`);
96
+ console.log(`Size: ${tui.formatBytes(sizeBytes)}`);
104
97
  console.log(`URL: ${tui.link(stream.url ?? 'unknown')}`);
105
98
  if (stream.metadata && Object.keys(stream.metadata).length > 0) {
106
99
  console.log(`Metadata:`);
@@ -0,0 +1,89 @@
1
+ import { z } from 'zod';
2
+ import { createCommand } from '../../../types';
3
+ import { ErrorCode } from '../../../errors';
4
+ import * as tui from '../../../tui';
5
+ import { createStorageAdapter } from './util';
6
+ import { getCommand } from '../../../command-prefix';
7
+
8
+ export const deleteNamespaceSubcommand = createCommand({
9
+ name: 'delete-namespace',
10
+ aliases: ['rm-namespace'],
11
+ description: 'Delete a vector namespace and all its vectors',
12
+ tags: ['destructive', 'deletes-resource', 'slow', 'requires-auth'],
13
+ idempotent: true,
14
+ requires: { auth: true, project: true },
15
+ examples: [
16
+ {
17
+ command: getCommand('vector delete-namespace staging'),
18
+ description: 'Delete staging namespace (interactive)',
19
+ },
20
+ {
21
+ command: getCommand('vector rm-namespace cache --confirm'),
22
+ description: 'Delete cache without confirmation',
23
+ },
24
+ {
25
+ command: getCommand('vector delete-namespace old-data --confirm'),
26
+ description: 'Force delete old-data namespace',
27
+ },
28
+ ],
29
+ schema: {
30
+ args: z.object({
31
+ name: z.string().min(1).describe('the namespace name to delete'),
32
+ }),
33
+ options: z.object({
34
+ confirm: z
35
+ .boolean()
36
+ .optional()
37
+ .default(false)
38
+ .describe('if true will not prompt for confirmation'),
39
+ }),
40
+ response: z.object({
41
+ success: z.boolean().describe('Whether the deletion succeeded'),
42
+ namespace: z.string().describe('Deleted namespace name'),
43
+ message: z.string().optional().describe('Confirmation message'),
44
+ }),
45
+ },
46
+
47
+ async handler(ctx) {
48
+ const { args, opts } = ctx;
49
+ const storage = await createStorageAdapter(ctx);
50
+
51
+ if (!opts.confirm) {
52
+ if (!process.stdin.isTTY) {
53
+ tui.fatal(
54
+ 'No TTY and --confirm is not set. Refusing to delete',
55
+ ErrorCode.VALIDATION_FAILED
56
+ );
57
+ }
58
+ tui.warning(
59
+ `This will delete namespace ${tui.bold(args.name)} and ALL its vectors permanently.`
60
+ );
61
+ const confirm = await new Promise<boolean>((resolve) => {
62
+ process.stdout.write('Are you sure? (yes/no): ');
63
+ process.stdin.once('data', (data) => {
64
+ const answer = data.toString().trim().toLowerCase();
65
+ resolve(answer === 'yes' || answer === 'y');
66
+ });
67
+ });
68
+
69
+ if (!confirm) {
70
+ tui.info('Cancelled');
71
+ return { success: false, namespace: args.name, message: 'Cancelled' };
72
+ }
73
+ }
74
+
75
+ await storage.deleteNamespace(args.name);
76
+
77
+ if (!ctx.options.json) {
78
+ tui.success(`Namespace ${tui.bold(args.name)} deleted`);
79
+ }
80
+
81
+ return {
82
+ success: true,
83
+ namespace: args.name,
84
+ message: `Namespace ${args.name} deleted`,
85
+ };
86
+ },
87
+ });
88
+
89
+ export default deleteNamespaceSubcommand;