@agentuity/cli 0.0.101 → 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 (210) hide show
  1. package/AGENTS.md +19 -188
  2. package/bin/cli.ts +13 -6
  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 +52 -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 +78 -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 +213 -57
  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 +57 -27
  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 +99 -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 +304 -111
  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,31 @@ 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.map((i) => `${i.path.join('.')}: ${i.message}`).join(', ');
129
+ logger.warn(`Invalid AGENTUITY_DEPLOYMENT schema: ${errors}`);
130
+ }
131
+ } catch (err) {
132
+ logger.warn(`Failed to parse AGENTUITY_DEPLOYMENT: ${err instanceof Error ? err.message : String(err)}`);
133
+ }
134
+ }
135
+
110
136
  const sdkKey = await loadProjectSDKKey(ctx.logger, ctx.projectDir);
111
137
 
112
138
  // Ensure SDK key is present before proceeding
@@ -124,24 +150,20 @@ export const deploySubcommand = createSubcommand({
124
150
  !project.deployment?.domains?.length
125
151
  ? null
126
152
  : {
127
- label: `Validate Custom Domain${project.deployment.domains.length > 1 ? `s: ${project.deployment.domains.join(', ')}` : `: ${project.deployment.domains[0]}`}`,
153
+ label: `Validate Custom ${tui.plural(project.deployment.domains.length, 'Domain', 'Domains')}`,
128
154
  run: async () => {
129
155
  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
156
+ try {
157
+ await domain.promptForDNS(
158
+ project.projectId,
159
+ project.deployment.domains,
160
+ config!,
161
+ () => pauseStepUI(true)
162
+ );
163
+ return stepSuccess();
164
+ } catch (ex) {
165
+ return stepError(String(ex), ex as Error);
143
166
  }
144
- return stepSuccess();
145
167
  }
146
168
  return stepSkipped();
147
169
  },
@@ -186,6 +208,9 @@ export const deploySubcommand = createSubcommand({
186
208
  {
187
209
  label: 'Create Deployment',
188
210
  run: async () => {
211
+ if (useExistingDeployment && deployment) {
212
+ return stepSkipped('using existing deployment');
213
+ }
189
214
  try {
190
215
  deployment = await projectDeploymentCreate(
191
216
  apiClient,
@@ -334,6 +359,7 @@ export const deploySubcommand = createSubcommand({
334
359
  }
335
360
 
336
361
  progress(80);
362
+ let bytes = 0;
337
363
  if (build?.assets) {
338
364
  ctx.logger.trace(`Uploading ${build.assets.length} assets`);
339
365
  if (!instructions.assets) {
@@ -343,9 +369,9 @@ export const deploySubcommand = createSubcommand({
343
369
  }
344
370
 
345
371
  // 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
372
+ // Use limited concurrency (1 at a time) for executables to avoid parallel fetch crash
347
373
  const isExecutable = isRunningFromExecutable();
348
- const concurrency = isExecutable ? 2 : build.assets.length;
374
+ const concurrency = isExecutable ? 1 : Math.min(4, build.assets.length);
349
375
 
350
376
  if (isExecutable) {
351
377
  ctx.logger.trace(
@@ -367,15 +393,34 @@ export const deploySubcommand = createSubcommand({
367
393
  }
368
394
 
369
395
  // Asset filename already includes the subdirectory (e.g., "client/assets/main-abc123.js")
370
- const file = Bun.file(join(projectDir, '.agentuity', asset.filename));
396
+ const filePath = join(projectDir, '.agentuity', asset.filename);
397
+
398
+ const headers: Record<string, string> = {
399
+ 'Content-Type': asset.contentType,
400
+ };
401
+
402
+ bytes += asset.size;
403
+
404
+ let body: Uint8Array | Blob;
405
+ if (asset.contentEncoding === 'gzip') {
406
+ const file = Bun.file(filePath);
407
+ const ab = await file.arrayBuffer();
408
+ const gzipped = Bun.gzipSync(new Uint8Array(ab));
409
+ headers['Content-Encoding'] = 'gzip';
410
+ body = gzipped;
411
+ ctx.logger.trace(
412
+ `Compressing ${asset.filename} (${asset.size} -> ${gzipped.byteLength} bytes)`
413
+ );
414
+ } else {
415
+ body = Bun.file(filePath);
416
+ }
417
+
371
418
  promises.push(
372
419
  fetch(assetUrl, {
373
420
  method: 'PUT',
374
421
  duplex: 'half',
375
- headers: {
376
- 'Content-Type': asset.contentType,
377
- },
378
- body: file,
422
+ headers,
423
+ body,
379
424
  })
380
425
  );
381
426
  }
@@ -392,7 +437,14 @@ export const deploySubcommand = createSubcommand({
392
437
  }
393
438
 
394
439
  progress(100);
395
- return stepSuccess();
440
+ const output = build?.assets.length
441
+ ? [
442
+ tui.muted(
443
+ `✓ Uploaded ${build.assets.length} ${tui.plural(build.assets.length, 'asset', 'assets')} (${tui.formatBytes(bytes)}) to CDN`
444
+ ),
445
+ ]
446
+ : undefined;
447
+ return stepSuccess(output);
396
448
  },
397
449
  },
398
450
  {
@@ -406,7 +458,7 @@ export const deploySubcommand = createSubcommand({
406
458
  },
407
459
  },
408
460
  ].filter(Boolean) as Step[],
409
- options.logLevel
461
+ useExistingDeployment ? 'debug' : options.logLevel
410
462
  );
411
463
 
412
464
  if (!deployment) {
@@ -617,20 +669,36 @@ export const deploySubcommand = createSubcommand({
617
669
 
618
670
  // Show deployment URLs
619
671
  if (complete?.publicUrls) {
672
+ const lines: string[] = [];
620
673
  if (complete.publicUrls.custom?.length) {
621
674
  for (const url of complete.publicUrls.custom) {
622
- tui.arrow(tui.bold(tui.padRight('Deployment URL:', 17)) + tui.link(url));
675
+ lines.push(
676
+ `${tui.ICONS.arrow} ${tui.bold(tui.padRight('Deployment:', 12)) + tui.link(url)}`
677
+ );
623
678
  }
624
679
  } else {
625
- tui.arrow(
626
- tui.bold(tui.padRight('Deployment URL:', 17)) +
680
+ lines.push(
681
+ `${tui.ICONS.arrow} ${
682
+ tui.bold(tui.padRight('Deployment:', 12)) +
627
683
  tui.link(complete.publicUrls.deployment)
684
+ }`
628
685
  );
629
- tui.arrow(
630
- tui.bold(tui.padRight('Project URL:', 17)) + tui.link(complete.publicUrls.latest)
686
+ lines.push(
687
+ `${tui.ICONS.arrow} ${
688
+ tui.bold(tui.padRight('Project:', 12)) + tui.link(complete.publicUrls.latest)
689
+ }`
631
690
  );
632
- tui.arrow(tui.bold(tui.padRight('Dashboard URL:', 17)) + tui.link(dashboard));
633
691
  }
692
+ lines.push(
693
+ `${tui.ICONS.arrow} ${
694
+ tui.bold(tui.padRight('Dashboard:', 12)) + tui.link(dashboard)
695
+ }`
696
+ );
697
+ tui.banner(`Deployment: ${tui.colorPrimary(deployment.id)}`, lines.join('\n'), {
698
+ centerTitle: false,
699
+ topSpacer: false,
700
+ bottomSpacer: false,
701
+ });
634
702
  }
635
703
 
636
704
  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;