@agentuity/cli 1.0.59 → 2.0.0-beta.1

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 (189) hide show
  1. package/bin/cli.ts +2 -3
  2. package/dist/cmd/build/app-config-extractor.d.ts +27 -0
  3. package/dist/cmd/build/app-config-extractor.d.ts.map +1 -0
  4. package/dist/cmd/build/app-config-extractor.js +152 -0
  5. package/dist/cmd/build/app-config-extractor.js.map +1 -0
  6. package/dist/cmd/build/app-router-detector.d.ts +2 -5
  7. package/dist/cmd/build/app-router-detector.d.ts.map +1 -1
  8. package/dist/cmd/build/app-router-detector.js +130 -154
  9. package/dist/cmd/build/app-router-detector.js.map +1 -1
  10. package/dist/cmd/build/ci.d.ts.map +1 -1
  11. package/dist/cmd/build/ci.js +5 -21
  12. package/dist/cmd/build/ci.js.map +1 -1
  13. package/dist/cmd/build/ids.d.ts +11 -0
  14. package/dist/cmd/build/ids.d.ts.map +1 -0
  15. package/dist/cmd/build/ids.js +18 -0
  16. package/dist/cmd/build/ids.js.map +1 -0
  17. package/dist/cmd/build/index.d.ts.map +1 -1
  18. package/dist/cmd/build/index.js +8 -0
  19. package/dist/cmd/build/index.js.map +1 -1
  20. package/dist/cmd/build/vite/agent-discovery.d.ts +8 -4
  21. package/dist/cmd/build/vite/agent-discovery.d.ts.map +1 -1
  22. package/dist/cmd/build/vite/agent-discovery.js +166 -487
  23. package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
  24. package/dist/cmd/build/vite/bun-dev-server.d.ts +43 -14
  25. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
  26. package/dist/cmd/build/vite/bun-dev-server.js +290 -129
  27. package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
  28. package/dist/cmd/build/vite/config-loader.d.ts +15 -20
  29. package/dist/cmd/build/vite/config-loader.d.ts.map +1 -1
  30. package/dist/cmd/build/vite/config-loader.js +41 -74
  31. package/dist/cmd/build/vite/config-loader.js.map +1 -1
  32. package/dist/cmd/build/vite/docs-generator.d.ts.map +1 -1
  33. package/dist/cmd/build/vite/docs-generator.js +0 -2
  34. package/dist/cmd/build/vite/docs-generator.js.map +1 -1
  35. package/dist/cmd/build/vite/index.d.ts.map +1 -1
  36. package/dist/cmd/build/vite/index.js +0 -36
  37. package/dist/cmd/build/vite/index.js.map +1 -1
  38. package/dist/cmd/build/vite/lifecycle-generator.d.ts +10 -2
  39. package/dist/cmd/build/vite/lifecycle-generator.d.ts.map +1 -1
  40. package/dist/cmd/build/vite/lifecycle-generator.js +302 -23
  41. package/dist/cmd/build/vite/lifecycle-generator.js.map +1 -1
  42. package/dist/cmd/build/vite/route-discovery.d.ts +11 -38
  43. package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
  44. package/dist/cmd/build/vite/route-discovery.js +97 -177
  45. package/dist/cmd/build/vite/route-discovery.js.map +1 -1
  46. package/dist/cmd/build/vite/server-bundler.js +1 -1
  47. package/dist/cmd/build/vite/server-bundler.js.map +1 -1
  48. package/dist/cmd/build/vite/static-renderer.d.ts +0 -2
  49. package/dist/cmd/build/vite/static-renderer.d.ts.map +1 -1
  50. package/dist/cmd/build/vite/static-renderer.js +19 -13
  51. package/dist/cmd/build/vite/static-renderer.js.map +1 -1
  52. package/dist/cmd/build/vite/vite-asset-server-config.d.ts +6 -3
  53. package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
  54. package/dist/cmd/build/vite/vite-asset-server-config.js +175 -69
  55. package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
  56. package/dist/cmd/build/vite/vite-asset-server.d.ts +8 -3
  57. package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
  58. package/dist/cmd/build/vite/vite-asset-server.js +14 -13
  59. package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
  60. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  61. package/dist/cmd/build/vite/vite-builder.js +42 -190
  62. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  63. package/dist/cmd/build/vite/ws-proxy.d.ts +53 -0
  64. package/dist/cmd/build/vite/ws-proxy.d.ts.map +1 -0
  65. package/dist/cmd/build/vite/ws-proxy.js +95 -0
  66. package/dist/cmd/build/vite/ws-proxy.js.map +1 -0
  67. package/dist/cmd/build/vite-bundler.d.ts.map +1 -1
  68. package/dist/cmd/build/vite-bundler.js +0 -3
  69. package/dist/cmd/build/vite-bundler.js.map +1 -1
  70. package/dist/cmd/cloud/deploy-fork.d.ts.map +1 -1
  71. package/dist/cmd/cloud/deploy-fork.js +15 -36
  72. package/dist/cmd/cloud/deploy-fork.js.map +1 -1
  73. package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
  74. package/dist/cmd/cloud/sandbox/exec.js +28 -86
  75. package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
  76. package/dist/cmd/cloud/sandbox/run.d.ts.map +1 -1
  77. package/dist/cmd/cloud/sandbox/run.js +2 -9
  78. package/dist/cmd/cloud/sandbox/run.js.map +1 -1
  79. package/dist/cmd/cloud/sandbox/snapshot/build.js +2 -2
  80. package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
  81. package/dist/cmd/coder/hub-url.d.ts.map +1 -1
  82. package/dist/cmd/coder/hub-url.js +1 -3
  83. package/dist/cmd/coder/hub-url.js.map +1 -1
  84. package/dist/cmd/coder/start.js +6 -6
  85. package/dist/cmd/coder/start.js.map +1 -1
  86. package/dist/cmd/coder/tui-init.d.ts +2 -2
  87. package/dist/cmd/coder/tui-init.js +2 -2
  88. package/dist/cmd/coder/tui-init.js.map +1 -1
  89. package/dist/cmd/dev/file-watcher.d.ts.map +1 -1
  90. package/dist/cmd/dev/file-watcher.js +2 -8
  91. package/dist/cmd/dev/file-watcher.js.map +1 -1
  92. package/dist/cmd/dev/index.d.ts.map +1 -1
  93. package/dist/cmd/dev/index.js +432 -752
  94. package/dist/cmd/dev/index.js.map +1 -1
  95. package/dist/cmd/dev/process-manager.d.ts +104 -0
  96. package/dist/cmd/dev/process-manager.d.ts.map +1 -0
  97. package/dist/cmd/dev/process-manager.js +204 -0
  98. package/dist/cmd/dev/process-manager.js.map +1 -0
  99. package/dist/errors.d.ts +10 -24
  100. package/dist/errors.d.ts.map +1 -1
  101. package/dist/errors.js +12 -42
  102. package/dist/errors.js.map +1 -1
  103. package/dist/schema-generator.d.ts.map +1 -1
  104. package/dist/schema-generator.js +12 -2
  105. package/dist/schema-generator.js.map +1 -1
  106. package/dist/tui.d.ts.map +1 -1
  107. package/dist/tui.js +5 -19
  108. package/dist/tui.js.map +1 -1
  109. package/dist/utils/version-mismatch.d.ts +39 -0
  110. package/dist/utils/version-mismatch.d.ts.map +1 -0
  111. package/dist/utils/version-mismatch.js +161 -0
  112. package/dist/utils/version-mismatch.js.map +1 -0
  113. package/package.json +6 -6
  114. package/src/cmd/ai/prompt/agent.md +0 -1
  115. package/src/cmd/ai/prompt/api.md +0 -7
  116. package/src/cmd/ai/prompt/web.md +51 -213
  117. package/src/cmd/build/app-config-extractor.ts +186 -0
  118. package/src/cmd/build/app-router-detector.ts +152 -182
  119. package/src/cmd/build/ci.ts +5 -21
  120. package/src/cmd/build/ids.ts +19 -0
  121. package/src/cmd/build/index.ts +10 -0
  122. package/src/cmd/build/vite/agent-discovery.ts +208 -679
  123. package/src/cmd/build/vite/bun-dev-server.ts +383 -146
  124. package/src/cmd/build/vite/config-loader.ts +45 -77
  125. package/src/cmd/build/vite/docs-generator.ts +0 -2
  126. package/src/cmd/build/vite/index.ts +1 -42
  127. package/src/cmd/build/vite/lifecycle-generator.ts +345 -21
  128. package/src/cmd/build/vite/route-discovery.ts +116 -274
  129. package/src/cmd/build/vite/server-bundler.ts +1 -1
  130. package/src/cmd/build/vite/static-renderer.ts +23 -15
  131. package/src/cmd/build/vite/vite-asset-server-config.ts +200 -70
  132. package/src/cmd/build/vite/vite-asset-server.ts +25 -15
  133. package/src/cmd/build/vite/vite-builder.ts +49 -220
  134. package/src/cmd/build/vite/ws-proxy.ts +126 -0
  135. package/src/cmd/build/vite-bundler.ts +0 -4
  136. package/src/cmd/cloud/deploy-fork.ts +16 -39
  137. package/src/cmd/cloud/sandbox/exec.ts +23 -130
  138. package/src/cmd/cloud/sandbox/run.ts +2 -9
  139. package/src/cmd/cloud/sandbox/snapshot/build.ts +2 -2
  140. package/src/cmd/coder/hub-url.ts +1 -3
  141. package/src/cmd/coder/start.ts +6 -6
  142. package/src/cmd/coder/tui-init.ts +4 -4
  143. package/src/cmd/dev/file-watcher.ts +2 -9
  144. package/src/cmd/dev/index.ts +476 -859
  145. package/src/cmd/dev/process-manager.ts +261 -0
  146. package/src/errors.ts +12 -44
  147. package/src/schema-generator.ts +12 -2
  148. package/src/tui.ts +5 -18
  149. package/src/utils/version-mismatch.ts +204 -0
  150. package/dist/cmd/build/ast.d.ts +0 -78
  151. package/dist/cmd/build/ast.d.ts.map +0 -1
  152. package/dist/cmd/build/ast.js +0 -2703
  153. package/dist/cmd/build/ast.js.map +0 -1
  154. package/dist/cmd/build/entry-generator.d.ts +0 -25
  155. package/dist/cmd/build/entry-generator.d.ts.map +0 -1
  156. package/dist/cmd/build/entry-generator.js +0 -695
  157. package/dist/cmd/build/entry-generator.js.map +0 -1
  158. package/dist/cmd/build/vite/api-mount-path.d.ts +0 -61
  159. package/dist/cmd/build/vite/api-mount-path.d.ts.map +0 -1
  160. package/dist/cmd/build/vite/api-mount-path.js +0 -83
  161. package/dist/cmd/build/vite/api-mount-path.js.map +0 -1
  162. package/dist/cmd/build/vite/registry-generator.d.ts +0 -19
  163. package/dist/cmd/build/vite/registry-generator.d.ts.map +0 -1
  164. package/dist/cmd/build/vite/registry-generator.js +0 -1108
  165. package/dist/cmd/build/vite/registry-generator.js.map +0 -1
  166. package/dist/cmd/build/webanalytics-generator.d.ts +0 -16
  167. package/dist/cmd/build/webanalytics-generator.d.ts.map +0 -1
  168. package/dist/cmd/build/webanalytics-generator.js +0 -178
  169. package/dist/cmd/build/webanalytics-generator.js.map +0 -1
  170. package/dist/cmd/build/workbench.d.ts +0 -7
  171. package/dist/cmd/build/workbench.d.ts.map +0 -1
  172. package/dist/cmd/build/workbench.js +0 -55
  173. package/dist/cmd/build/workbench.js.map +0 -1
  174. package/dist/utils/route-migration.d.ts +0 -62
  175. package/dist/utils/route-migration.d.ts.map +0 -1
  176. package/dist/utils/route-migration.js +0 -630
  177. package/dist/utils/route-migration.js.map +0 -1
  178. package/dist/utils/stream-capture.d.ts +0 -9
  179. package/dist/utils/stream-capture.d.ts.map +0 -1
  180. package/dist/utils/stream-capture.js +0 -34
  181. package/dist/utils/stream-capture.js.map +0 -1
  182. package/src/cmd/build/ast.ts +0 -3529
  183. package/src/cmd/build/entry-generator.ts +0 -760
  184. package/src/cmd/build/vite/api-mount-path.ts +0 -87
  185. package/src/cmd/build/vite/registry-generator.ts +0 -1267
  186. package/src/cmd/build/webanalytics-generator.ts +0 -197
  187. package/src/cmd/build/workbench.ts +0 -58
  188. package/src/utils/route-migration.ts +0 -757
  189. package/src/utils/stream-capture.ts +0 -39
@@ -0,0 +1,261 @@
1
+ /**
2
+ * Process Manager for Dev Mode
3
+ *
4
+ * Tracks all spawned processes and ensures they're cleaned up on:
5
+ * - Startup failure (any server fails to start)
6
+ * - Runtime crash (uncaught exception)
7
+ * - Graceful shutdown (SIGINT/SIGTERM)
8
+ *
9
+ * This prevents orphan processes and port conflicts between dev sessions.
10
+ */
11
+
12
+ import type { Logger } from '../../types';
13
+
14
+ export interface ManagedProcess {
15
+ /** Process identifier for logging */
16
+ id: string;
17
+ /** The process handle */
18
+ process: {
19
+ kill: (signal?: number | NodeJS.Signals) => void;
20
+ exitCode: number | null;
21
+ pid?: number;
22
+ };
23
+ /** Human-readable description */
24
+ description: string;
25
+ /** The port this process uses (if any) */
26
+ port?: number;
27
+ /** Whether this process is critical (startup fails if it dies) */
28
+ critical?: boolean;
29
+ }
30
+
31
+ export interface ManagedServer {
32
+ /** Server identifier */
33
+ id: string;
34
+ /** The server handle */
35
+ server: {
36
+ close: () => void | Promise<void>;
37
+ };
38
+ /** Human-readable description */
39
+ description: string;
40
+ /** The port this server uses */
41
+ port?: number;
42
+ }
43
+
44
+ /**
45
+ * Process Manager
46
+ *
47
+ * Tracks all processes and servers started during dev mode and provides
48
+ * centralized cleanup on failure or shutdown.
49
+ */
50
+ export class ProcessManager {
51
+ private processes: ManagedProcess[] = [];
52
+ private servers: ManagedServer[] = [];
53
+ private logger: Logger;
54
+ private cleaningUp = false;
55
+
56
+ constructor(logger: Logger) {
57
+ this.logger = logger;
58
+ }
59
+
60
+ /**
61
+ * Register a spawned process for tracking.
62
+ */
63
+ registerProcess(proc: ManagedProcess): void {
64
+ this.processes.push(proc);
65
+ this.logger.debug(
66
+ 'Registered process: %s (pid=%s, port=%s)',
67
+ proc.id,
68
+ proc.process.pid ?? 'unknown',
69
+ proc.port ?? 'n/a'
70
+ );
71
+ }
72
+
73
+ /**
74
+ * Register a server for tracking.
75
+ */
76
+ registerServer(server: ManagedServer): void {
77
+ this.servers.push(server);
78
+ this.logger.debug('Registered server: %s (port=%s)', server.id, server.port ?? 'n/a');
79
+ }
80
+
81
+ /**
82
+ * Unregister a process (e.g., after it exits normally).
83
+ */
84
+ unregisterProcess(id: string): void {
85
+ const idx = this.processes.findIndex((p) => p.id === id);
86
+ if (idx !== -1) {
87
+ this.processes.splice(idx, 1);
88
+ this.logger.debug('Unregistered process: %s', id);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Unregister a server.
94
+ */
95
+ unregisterServer(id: string): void {
96
+ const idx = this.servers.findIndex((s) => s.id === id);
97
+ if (idx !== -1) {
98
+ this.servers.splice(idx, 1);
99
+ this.logger.debug('Unregistered server: %s', id);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Get all registered ports (for cleanup verification).
105
+ */
106
+ getPorts(): number[] {
107
+ const ports: number[] = [];
108
+ for (const proc of this.processes) {
109
+ if (proc.port) ports.push(proc.port);
110
+ }
111
+ for (const server of this.servers) {
112
+ if (server.port) ports.push(server.port);
113
+ }
114
+ return ports;
115
+ }
116
+
117
+ /**
118
+ * Clean up all tracked processes and servers.
119
+ *
120
+ * @param reason - Why cleanup is happening (for logging)
121
+ * @param timeout - Max time to wait for graceful shutdown (ms)
122
+ */
123
+ async cleanup(reason: string, timeout = 3000): Promise<void> {
124
+ if (this.cleaningUp) {
125
+ this.logger.debug('Cleanup already in progress, skipping');
126
+ return;
127
+ }
128
+ this.cleaningUp = true;
129
+
130
+ this.logger.debug('Starting cleanup (reason: %s)', reason);
131
+
132
+ // Kill processes in reverse order (LIFO)
133
+ for (let i = this.processes.length - 1; i >= 0; i--) {
134
+ const proc = this.processes[i];
135
+ if (!proc) continue;
136
+
137
+ try {
138
+ if (proc.process.exitCode === null) {
139
+ this.logger.debug(
140
+ 'Killing process %s (pid=%s)',
141
+ proc.id,
142
+ proc.process.pid ?? 'unknown'
143
+ );
144
+ proc.process.kill('SIGTERM');
145
+ }
146
+ } catch (err) {
147
+ this.logger.debug('Error killing process %s: %s', proc.id, err);
148
+ }
149
+ }
150
+
151
+ // Close servers
152
+ for (let i = this.servers.length - 1; i >= 0; i--) {
153
+ const server = this.servers[i];
154
+ if (!server) continue;
155
+
156
+ try {
157
+ this.logger.debug('Closing server %s', server.id);
158
+ const closePromise = server.server.close();
159
+ if (closePromise instanceof Promise) {
160
+ await Promise.race([
161
+ closePromise,
162
+ new Promise<void>((resolve) => setTimeout(resolve, 1000)),
163
+ ]);
164
+ }
165
+ } catch (err) {
166
+ this.logger.debug('Error closing server %s: %s', server.id, err);
167
+ }
168
+ }
169
+
170
+ // Wait for processes to exit, then force-kill if needed
171
+ const startTime = Date.now();
172
+ while (Date.now() - startTime < timeout) {
173
+ const allExited = this.processes.every((p) => p.process.exitCode !== null);
174
+ if (allExited) break;
175
+ await new Promise((resolve) => setTimeout(resolve, 100));
176
+ }
177
+
178
+ // Force kill any remaining
179
+ for (const proc of this.processes) {
180
+ if (proc.process.exitCode === null) {
181
+ try {
182
+ this.logger.debug('Force killing process %s', proc.id);
183
+ proc.process.kill('SIGKILL');
184
+ } catch (err) {
185
+ this.logger.debug('Error force killing process %s: %s', proc.id, err);
186
+ }
187
+ }
188
+ }
189
+
190
+ this.logger.debug('Cleanup complete');
191
+ this.processes = [];
192
+ this.servers = [];
193
+ }
194
+
195
+ /**
196
+ * Verify that all ports used by tracked processes are released.
197
+ * Used after cleanup to ensure no orphan processes remain.
198
+ */
199
+ async verifyPortsReleased(): Promise<{ port: number; released: boolean }[]> {
200
+ const results: { port: number; released: boolean }[] = [];
201
+ const ports = this.getPorts();
202
+
203
+ for (const port of ports) {
204
+ const released = await this.isPortAvailable(port);
205
+ results.push({ port, released });
206
+
207
+ if (!released) {
208
+ this.logger.warn('Port %d is still in use after cleanup', port);
209
+ }
210
+ }
211
+
212
+ return results;
213
+ }
214
+
215
+ /**
216
+ * Check if a port is available.
217
+ */
218
+ private isPortAvailable(port: number, host = '127.0.0.1'): Promise<boolean> {
219
+ return new Promise((resolve) => {
220
+ const net = require('node:net');
221
+ const server = net.createServer();
222
+ server.once('error', () => resolve(false));
223
+ server.listen(port, host, () => {
224
+ server.close(() => resolve(true));
225
+ });
226
+ });
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Global process manager instance for dev mode.
232
+ * Set in dev/index.ts during startup.
233
+ */
234
+ let globalProcessManager: ProcessManager | null = null;
235
+
236
+ /**
237
+ * Get the global process manager (throws if not initialized).
238
+ */
239
+ export function getProcessManager(): ProcessManager {
240
+ if (!globalProcessManager) {
241
+ throw new Error('ProcessManager not initialized. Call initProcessManager first.');
242
+ }
243
+ return globalProcessManager;
244
+ }
245
+
246
+ /**
247
+ * Initialize the global process manager.
248
+ */
249
+ export function initProcessManager(logger: Logger): ProcessManager {
250
+ globalProcessManager = new ProcessManager(logger);
251
+ return globalProcessManager;
252
+ }
253
+
254
+ /**
255
+ * Cleanup helper that can be called from signal handlers or error handlers.
256
+ */
257
+ export async function cleanupAll(reason: string): Promise<void> {
258
+ if (globalProcessManager) {
259
+ await globalProcessManager.cleanup(reason);
260
+ }
261
+ }
package/src/errors.ts CHANGED
@@ -1,51 +1,22 @@
1
1
  import type { Logger } from './types';
2
2
 
3
3
  /**
4
- * Standard exit codes for the CLI.
5
- *
6
- * Values start at 10 to avoid collisions with Unix signal numbers (1-9)
7
- * and shell conventions (e.g. 2 = misuse of builtins, 9 = SIGKILL/OOM).
8
- * Range 10-125 is safe — below shell-reserved 126-128 and signal-death
9
- * codes 128+N.
10
- *
11
- * 0 and 1 are kept as universal success/failure codes.
4
+ * Standard exit codes for the CLI
12
5
  */
13
6
  export enum ExitCode {
14
7
  SUCCESS = 0,
15
8
  GENERAL_ERROR = 1,
16
- VALIDATION_ERROR = 10,
17
- AUTH_ERROR = 11,
18
- NOT_FOUND = 12,
19
- PERMISSION_ERROR = 13,
20
- NETWORK_ERROR = 14,
21
- FILE_ERROR = 15,
22
- USER_CANCELLED = 16,
23
- BUILD_FAILED = 17,
24
- SECURITY_ERROR = 18,
25
- PAYMENT_REQUIRED = 19,
26
- UPGRADE_REQUIRED = 20,
9
+ VALIDATION_ERROR = 2,
10
+ AUTH_ERROR = 3,
11
+ NOT_FOUND = 4,
12
+ PERMISSION_ERROR = 5,
13
+ NETWORK_ERROR = 6,
14
+ FILE_ERROR = 7,
15
+ USER_CANCELLED = 8,
16
+ BUILD_FAILED = 9,
17
+ SECURITY_ERROR = 10,
27
18
  }
28
19
 
29
- /**
30
- * Human-readable descriptions for each exit code.
31
- * This is the single source of truth consumed by the schema generator and AI help.
32
- */
33
- export const exitCodeDescriptions: Record<number, string> = {
34
- [ExitCode.SUCCESS]: 'Success',
35
- [ExitCode.GENERAL_ERROR]: 'General error',
36
- [ExitCode.VALIDATION_ERROR]: 'Validation error (invalid arguments or options)',
37
- [ExitCode.AUTH_ERROR]: 'Authentication error (login required or credentials invalid)',
38
- [ExitCode.NOT_FOUND]: 'Resource not found (project, file, deployment, etc.)',
39
- [ExitCode.PERMISSION_ERROR]: 'Permission denied (insufficient access rights)',
40
- [ExitCode.NETWORK_ERROR]: 'Network error (API unreachable or timeout)',
41
- [ExitCode.FILE_ERROR]: 'File system error (file read/write failed)',
42
- [ExitCode.USER_CANCELLED]: 'User cancelled (operation aborted by user)',
43
- [ExitCode.BUILD_FAILED]: 'Build failed',
44
- [ExitCode.SECURITY_ERROR]: 'Security error (malware detected)',
45
- [ExitCode.PAYMENT_REQUIRED]: 'Payment required (plan upgrade needed)',
46
- [ExitCode.UPGRADE_REQUIRED]: 'Upgrade required (CLI version too old)',
47
- };
48
-
49
20
  /**
50
21
  * Standard error codes for the CLI
51
22
  */
@@ -181,11 +152,7 @@ export function getExitCode(errorCode: ErrorCode): ExitCode {
181
152
 
182
153
  // Payment required - user needs to upgrade their plan
183
154
  case ErrorCode.PAYMENT_REQUIRED:
184
- return ExitCode.PAYMENT_REQUIRED;
185
-
186
- // Upgrade required - CLI version too old
187
- case ErrorCode.UPGRADE_REQUIRED:
188
- return ExitCode.UPGRADE_REQUIRED;
155
+ return ExitCode.GENERAL_ERROR;
189
156
 
190
157
  // Resource conflicts and other errors
191
158
  case ErrorCode.RESOURCE_ALREADY_EXISTS:
@@ -195,6 +162,7 @@ export function getExitCode(errorCode: ErrorCode): ExitCode {
195
162
  case ErrorCode.RUNTIME_ERROR:
196
163
  case ErrorCode.INTERNAL_ERROR:
197
164
  case ErrorCode.NOT_IMPLEMENTED:
165
+ case ErrorCode.UPGRADE_REQUIRED:
198
166
  default:
199
167
  return ExitCode.GENERAL_ERROR;
200
168
  }
@@ -1,6 +1,5 @@
1
1
  import type { Command } from 'commander';
2
2
  import type { CommandDefinition, SubcommandDefinition, CommandSchemas } from './types';
3
- import { exitCodeDescriptions } from './errors';
4
3
  import { parseArgsSchema, parseOptionsSchema } from './schema-parser';
5
4
  import * as z from 'zod';
6
5
 
@@ -314,7 +313,18 @@ export function generateCLISchema(
314
313
  name: 'agentuity',
315
314
  version,
316
315
  description: 'Agentuity CLI',
317
- exitCodes: { ...exitCodeDescriptions },
316
+ exitCodes: {
317
+ 0: 'Success',
318
+ 1: 'General error',
319
+ 2: 'Validation error (invalid arguments or options)',
320
+ 3: 'Authentication error (login required or credentials invalid)',
321
+ 4: 'Resource not found (project, file, deployment, etc.)',
322
+ 5: 'Permission denied (insufficient access rights)',
323
+ 6: 'Network error (API unreachable or timeout)',
324
+ 7: 'File system error (file read/write failed)',
325
+ 8: 'User cancelled (operation aborted by user)',
326
+ 9: 'Build failed',
327
+ },
318
328
  globalOptions: [
319
329
  {
320
330
  name: 'config',
package/src/tui.ts CHANGED
@@ -25,12 +25,6 @@ function ensureCursorRestoration(): void {
25
25
  exitHandlerInstalled = true;
26
26
 
27
27
  const restoreCursor = () => {
28
- // Only write ANSI escape sequences when stderr is a real terminal.
29
- // Writing to non-TTY streams (pipes, command substitution, etc.)
30
- // pollutes captured output with invisible control characters.
31
- if (!process.stderr.isTTY) {
32
- return;
33
- }
34
28
  // Skip cursor restoration in CI - terminals don't support these sequences
35
29
  if (process.env.CI) {
36
30
  return;
@@ -299,13 +293,8 @@ export function getSeverityColor(severity: string): (text: string) => string {
299
293
  export function success(message: string): void {
300
294
  const color = getColor('success');
301
295
  const reset = getColor('reset');
302
- if (process.stderr.isTTY) {
303
- // Clear line first to ensure no leftover content from previous output
304
- process.stderr.write(`\r\x1b[2K${color}${ICONS.success} ${message}${reset}\n`);
305
- } else {
306
- // No ANSI control sequences for non-TTY streams (pipes, command substitution)
307
- process.stderr.write(`${ICONS.success} ${message}\n`);
308
- }
296
+ // Clear line first to ensure no leftover content from previous output
297
+ process.stderr.write(`\r\x1b[2K${color}${ICONS.success} ${message}${reset}\n`);
309
298
  }
310
299
 
311
300
  /**
@@ -1254,11 +1243,9 @@ export async function spinner<T>(
1254
1243
  const outputOptions = getOutputOptions();
1255
1244
  const noProgress = outputOptions ? shouldDisableProgress(outputOptions) : false;
1256
1245
 
1257
- // If stderr is not a real terminal or progress disabled, just execute
1258
- // the callback without animation. We check stderr specifically because
1259
- // the spinner writes ANSI sequences to stderr — isTTYLike() may return
1260
- // true when stdout is a TTY but stderr is piped (e.g. 2>&1 in $()).
1261
- if (!process.stderr.isTTY || noProgress) {
1246
+ // If no interactive TTY-like environment or progress disabled, just execute
1247
+ // the callback without animation
1248
+ if (!isTTYLike() || noProgress) {
1262
1249
  try {
1263
1250
  const result =
1264
1251
  options.type === 'progress'
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Version mismatch detection for @agentuity/* packages.
3
+ *
4
+ * Detects when a project uses outdated v1 SDK packages while the CLI is v2,
5
+ * and recommends running the migration tool.
6
+ */
7
+
8
+ import { existsSync, readFileSync } from 'node:fs';
9
+ import { join } from 'node:path';
10
+ import { getVersion } from '../version';
11
+ import type { Logger } from '../types';
12
+
13
+ export interface VersionInfo {
14
+ name: string;
15
+ version: string;
16
+ major: number;
17
+ }
18
+
19
+ export interface VersionMismatchResult {
20
+ /** CLI major version */
21
+ cliMajor: number;
22
+ /** All @agentuity/* packages found */
23
+ packages: VersionInfo[];
24
+ /** Packages with major version mismatch */
25
+ mismatched: VersionInfo[];
26
+ /** Packages that are v1 when CLI is v2+ */
27
+ outdated: VersionInfo[];
28
+ /** Whether any v1 packages were found */
29
+ hasV1Packages: boolean;
30
+ /** Whether there are major version mismatches across packages */
31
+ hasMajorMismatches: boolean;
32
+ }
33
+
34
+ /**
35
+ * Extract major version from semver string
36
+ */
37
+ function extractMajor(version: string): number {
38
+ // Handle ranges like ^1.0.0, ~2.0.0, >=1.0.0
39
+ const match = version.match(/(\d+)\.\d+\.\d+/);
40
+ if (match?.[1]) {
41
+ return parseInt(match[1], 10);
42
+ }
43
+ // Handle "latest" or "*"
44
+ if (version === 'latest' || version === '*') {
45
+ return 0; // Unknown major
46
+ }
47
+ return 0;
48
+ }
49
+
50
+ /**
51
+ * Get installed version from node_modules
52
+ */
53
+ function getInstalledVersion(projectDir: string, packageName: string): string | null {
54
+ try {
55
+ const pkgPath = join(projectDir, 'node_modules', packageName, 'package.json');
56
+ if (!existsSync(pkgPath)) {
57
+ return null;
58
+ }
59
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
60
+ return pkg.version || null;
61
+ } catch {
62
+ return null;
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Detect version mismatches in @agentuity/* packages.
68
+ *
69
+ * @param projectDir - Root directory of the user's project
70
+ * @param logger - Logger instance
71
+ * @returns Version mismatch detection result
72
+ */
73
+ export function detectVersionMismatch(projectDir: string, logger: Logger): VersionMismatchResult {
74
+ const cliVersion = getVersion();
75
+ const cliMajor = extractMajor(cliVersion);
76
+
77
+ const result: VersionMismatchResult = {
78
+ cliMajor,
79
+ packages: [],
80
+ mismatched: [],
81
+ outdated: [],
82
+ hasV1Packages: false,
83
+ hasMajorMismatches: false,
84
+ };
85
+
86
+ // Skip check for canary versions
87
+ if (cliVersion.includes('-')) {
88
+ logger.debug('Skipping version mismatch check for canary version: %s', cliVersion);
89
+ return result;
90
+ }
91
+
92
+ // Read package.json
93
+ const packageJsonPath = join(projectDir, 'package.json');
94
+ if (!existsSync(packageJsonPath)) {
95
+ logger.debug('No package.json found, skipping version mismatch check');
96
+ return result;
97
+ }
98
+
99
+ let packageJson: {
100
+ dependencies?: Record<string, string>;
101
+ devDependencies?: Record<string, string>;
102
+ };
103
+ try {
104
+ packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
105
+ } catch (error) {
106
+ logger.debug('Failed to read package.json: %s', error);
107
+ return result;
108
+ }
109
+
110
+ // Collect all @agentuity/* packages
111
+ const allDeps = {
112
+ ...packageJson.dependencies,
113
+ ...packageJson.devDependencies,
114
+ };
115
+
116
+ const agentuitPackages = Object.entries(allDeps)
117
+ .filter(([name]) => name.startsWith('@agentuity/'))
118
+ .map(([name, specifier]) => ({ name, specifier }));
119
+
120
+ if (agentuitPackages.length === 0) {
121
+ logger.debug('No @agentuity/* packages found in package.json');
122
+ return result;
123
+ }
124
+
125
+ // Check each package's installed version
126
+ for (const { name } of agentuitPackages) {
127
+ const installedVersion = getInstalledVersion(projectDir, name);
128
+ if (!installedVersion) {
129
+ logger.debug('%s: not installed, skipping', name);
130
+ continue;
131
+ }
132
+
133
+ const major = extractMajor(installedVersion);
134
+ const info: VersionInfo = {
135
+ name,
136
+ version: installedVersion,
137
+ major,
138
+ };
139
+
140
+ result.packages.push(info);
141
+
142
+ // Check if this is a v1 package when CLI is v2+
143
+ if (major === 1 && cliMajor >= 2) {
144
+ result.outdated.push(info);
145
+ result.hasV1Packages = true;
146
+ }
147
+ }
148
+
149
+ // Check for major version mismatches across installed packages
150
+ if (result.packages.length > 1) {
151
+ const majors = new Set(result.packages.map((p) => p.major));
152
+ if (majors.size > 1) {
153
+ result.hasMajorMismatches = true;
154
+ // Find packages that don't match the most common major version
155
+ const majorCounts = new Map<number, number>();
156
+ for (const pkg of result.packages) {
157
+ majorCounts.set(pkg.major, (majorCounts.get(pkg.major) || 0) + 1);
158
+ }
159
+ const mostCommonMajor =
160
+ [...majorCounts.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] || cliMajor;
161
+
162
+ for (const pkg of result.packages) {
163
+ if (pkg.major !== mostCommonMajor) {
164
+ result.mismatched.push(pkg);
165
+ }
166
+ }
167
+ }
168
+ }
169
+
170
+ return result;
171
+ }
172
+
173
+ /**
174
+ * Format a warning message for version mismatches.
175
+ */
176
+ export function formatVersionMismatchWarning(result: VersionMismatchResult): string {
177
+ const lines: string[] = [];
178
+
179
+ if (result.hasV1Packages) {
180
+ lines.push('You are using Agentuity SDK v1 packages, but v2 is now available.');
181
+ lines.push('');
182
+ lines.push(' Outdated packages:');
183
+ for (const pkg of result.outdated) {
184
+ lines.push(` • ${pkg.name}@${pkg.version}`);
185
+ }
186
+ lines.push('');
187
+ lines.push(' → Run `npx @agentuity/migrate` to upgrade your project to v2.');
188
+ lines.push(' This will automatically update your code and dependencies.');
189
+ lines.push('');
190
+ lines.push(' See the migration guide: https://docs.agentuity.com/migration/v1-to-v2');
191
+ } else if (result.hasMajorMismatches) {
192
+ lines.push('Your project has mismatched major versions across @agentuity/* packages.');
193
+ lines.push('');
194
+ lines.push(' Packages:');
195
+ for (const pkg of result.packages) {
196
+ const marker = result.mismatched.includes(pkg) ? ' ⚠️' : '';
197
+ lines.push(` • ${pkg.name}@${pkg.version} (v${pkg.major})${marker}`);
198
+ }
199
+ lines.push('');
200
+ lines.push(' → Run `bun install` to sync versions, or pin to the same major version.');
201
+ }
202
+
203
+ return lines.join('\n');
204
+ }
@@ -1,78 +0,0 @@
1
- import type { BuildMetadata } from '../../types';
2
- import { type WorkbenchConfig } from '@agentuity/core';
3
- export declare function getDevmodeDeploymentId(projectId: string, endpointId: string): string;
4
- export declare function parseEvalMetadata(rootDir: string, filename: string, contents: string, projectId: string, deploymentId: string, agentId?: string, agentMetadata?: Map<string, Map<string, string>>): Promise<[
5
- string,
6
- Array<{
7
- filename: string;
8
- id: string;
9
- version: string;
10
- name: string;
11
- evalId: string;
12
- description?: string;
13
- }>
14
- ]>;
15
- export declare function parseAgentMetadata(rootDir: string, filename: string, contents: string, projectId: string, deploymentId: string): Promise<[string, Map<string, string>] | undefined>;
16
- export interface ParseRouteOptions {
17
- visitedFiles?: Set<string>;
18
- mountedSubrouters?: Set<string>;
19
- /**
20
- * Explicit mount prefix for this router file, derived from code-based routing
21
- * (e.g., from `createApp({ router })` or `.route()` calls).
22
- * When provided, overrides the filesystem-derived mount path.
23
- */
24
- mountPrefix?: string;
25
- }
26
- export declare function parseRoute(rootDir: string, filename: string, projectId: string, deploymentId: string, visitedFilesOrOptions?: Set<string> | ParseRouteOptions, mountedSubrouters?: Set<string>): Promise<BuildMetadata['routes']>;
27
- /**
28
- * Result of workbench analysis
29
- */
30
- export interface WorkbenchAnalysis {
31
- hasWorkbench: boolean;
32
- config: WorkbenchConfig | null;
33
- }
34
- /**
35
- * Check if a TypeScript file actively uses a specific function
36
- * (ignores comments and unused imports)
37
- *
38
- * @param content - The TypeScript source code
39
- * @param functionName - The function name to check for (e.g., 'createWorkbench')
40
- * @returns true if the function is both imported and called
41
- */
42
- export declare function checkFunctionUsage(content: string, functionName: string): boolean;
43
- /**
44
- * Check if app.ts contains conflicting routes for a given endpoint
45
- */
46
- export declare function checkRouteConflicts(content: string, workbenchEndpoint: string): boolean;
47
- /**
48
- * Extract AppState type from setup() return value in createApp call
49
- *
50
- * @param content - The TypeScript source code from app.ts
51
- * @returns Type definition string or null if no setup found
52
- */
53
- export declare function extractAppStateType(content: string): string | null;
54
- /**
55
- * Generate lifecycle type files (src/generated/state.ts and src/generated/router.ts)
56
- *
57
- * @param rootDir - Root directory of the project
58
- * @param outDir - Output directory (typically src/generated/)
59
- * @param appFilePath - Path to app.ts file
60
- * @returns true if files were generated, false if no setup found
61
- */
62
- export declare function generateLifecycleTypes(rootDir: string, outDir: string, appFilePath: string): Promise<boolean>;
63
- /**
64
- * Analyze workbench usage and extract configuration
65
- *
66
- * @param content - The TypeScript source code
67
- * @returns workbench analysis including usage and config
68
- */
69
- export declare function analyzeWorkbench(content: string): WorkbenchAnalysis;
70
- /**
71
- * Find the end position of createApp call statement in the source code
72
- * Uses AST parsing to reliably find the complete statement including await/const assignment
73
- *
74
- * @param content - The source code content
75
- * @returns The character position after the createApp statement, or -1 if not found
76
- */
77
- export declare function findCreateAppEndPosition(content: string): number;
78
- //# sourceMappingURL=ast.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../../src/cmd/build/ast.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAqIxE,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEpF;AAoTD,wBAAsB,iBAAiB,CACtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAC9C,OAAO,CACT;IACC,MAAM;IACN,KAAK,CAAC;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACF,CACD,CAyNA;AAID,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GAClB,OAAO,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,CAqPpD;AA4pBD,MAAM,WAAW,iBAAiB;IACjC,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,UAAU,CAC/B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,qBAAqB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,iBAAiB,EACvD,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAC7B,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAo+BlC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAoCjF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CA+BvF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgOlE;AAkED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC3C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CA8LlB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAsLnE;AA+BD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA0EhE"}