@agentuity/cli 0.1.41 → 0.1.42

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 (230) hide show
  1. package/dist/agent-detection.d.ts.map +1 -1
  2. package/dist/agent-detection.js +8 -2
  3. package/dist/agent-detection.js.map +1 -1
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +9 -5
  6. package/dist/cli.js.map +1 -1
  7. package/dist/cmd/ai/index.d.ts.map +1 -1
  8. package/dist/cmd/ai/index.js +1 -8
  9. package/dist/cmd/ai/index.js.map +1 -1
  10. package/dist/cmd/ai/prompt/version.js +1 -1
  11. package/dist/cmd/ai/prompt/version.js.map +1 -1
  12. package/dist/cmd/auth/api.d.ts.map +1 -1
  13. package/dist/cmd/auth/api.js +4 -1
  14. package/dist/cmd/auth/api.js.map +1 -1
  15. package/dist/cmd/auth/ssh/api.js +2 -2
  16. package/dist/cmd/auth/ssh/api.js.map +1 -1
  17. package/dist/cmd/build/ast.d.ts.map +1 -1
  18. package/dist/cmd/build/ast.js +14 -13
  19. package/dist/cmd/build/ast.js.map +1 -1
  20. package/dist/cmd/build/patch/index.d.ts.map +1 -1
  21. package/dist/cmd/build/patch/index.js +3 -0
  22. package/dist/cmd/build/patch/index.js.map +1 -1
  23. package/dist/cmd/build/vite/index.d.ts +1 -0
  24. package/dist/cmd/build/vite/index.d.ts.map +1 -1
  25. package/dist/cmd/build/vite/index.js +1 -0
  26. package/dist/cmd/build/vite/index.js.map +1 -1
  27. package/dist/cmd/build/vite/public-asset-path-plugin.d.ts +34 -0
  28. package/dist/cmd/build/vite/public-asset-path-plugin.d.ts.map +1 -0
  29. package/dist/cmd/build/vite/public-asset-path-plugin.js +107 -0
  30. package/dist/cmd/build/vite/public-asset-path-plugin.js.map +1 -0
  31. package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
  32. package/dist/cmd/build/vite/registry-generator.js +14 -5
  33. package/dist/cmd/build/vite/registry-generator.js.map +1 -1
  34. package/dist/cmd/build/vite/route-discovery.js +1 -1
  35. package/dist/cmd/build/vite/route-discovery.js.map +1 -1
  36. package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
  37. package/dist/cmd/build/vite/vite-asset-server-config.js +11 -2
  38. package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
  39. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  40. package/dist/cmd/build/vite/vite-builder.js +3 -0
  41. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  42. package/dist/cmd/canary/index.d.ts.map +1 -1
  43. package/dist/cmd/canary/index.js +9 -1
  44. package/dist/cmd/canary/index.js.map +1 -1
  45. package/dist/cmd/cloud/db/create.d.ts.map +1 -1
  46. package/dist/cmd/cloud/db/create.js +2 -2
  47. package/dist/cmd/cloud/db/create.js.map +1 -1
  48. package/dist/cmd/cloud/db/delete.d.ts.map +1 -1
  49. package/dist/cmd/cloud/db/delete.js +2 -2
  50. package/dist/cmd/cloud/db/delete.js.map +1 -1
  51. package/dist/cmd/cloud/env/import.d.ts.map +1 -1
  52. package/dist/cmd/cloud/env/import.js +4 -1
  53. package/dist/cmd/cloud/env/import.js.map +1 -1
  54. package/dist/cmd/cloud/env/list.d.ts.map +1 -1
  55. package/dist/cmd/cloud/env/list.js +4 -1
  56. package/dist/cmd/cloud/env/list.js.map +1 -1
  57. package/dist/cmd/cloud/env/push.d.ts.map +1 -1
  58. package/dist/cmd/cloud/env/push.js +4 -1
  59. package/dist/cmd/cloud/env/push.js.map +1 -1
  60. package/dist/cmd/cloud/region/index.js +1 -1
  61. package/dist/cmd/cloud/region/index.js.map +1 -1
  62. package/dist/cmd/cloud/sandbox/snapshot/build.d.ts.map +1 -1
  63. package/dist/cmd/cloud/sandbox/snapshot/build.js +22 -10
  64. package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
  65. package/dist/cmd/cloud/sandbox/snapshot/get.d.ts.map +1 -1
  66. package/dist/cmd/cloud/sandbox/snapshot/get.js +12 -2
  67. package/dist/cmd/cloud/sandbox/snapshot/get.js.map +1 -1
  68. package/dist/cmd/cloud/storage/create.d.ts.map +1 -1
  69. package/dist/cmd/cloud/storage/create.js +2 -2
  70. package/dist/cmd/cloud/storage/create.js.map +1 -1
  71. package/dist/cmd/cloud/storage/delete.d.ts.map +1 -1
  72. package/dist/cmd/cloud/storage/delete.js +2 -2
  73. package/dist/cmd/cloud/storage/delete.js.map +1 -1
  74. package/dist/cmd/dev/download.d.ts.map +1 -1
  75. package/dist/cmd/dev/download.js +9 -2
  76. package/dist/cmd/dev/download.js.map +1 -1
  77. package/dist/cmd/dev/index.js +1 -1
  78. package/dist/cmd/dev/index.js.map +1 -1
  79. package/dist/cmd/git/account/add.d.ts.map +1 -1
  80. package/dist/cmd/git/account/add.js +4 -3
  81. package/dist/cmd/git/account/add.js.map +1 -1
  82. package/dist/cmd/git/link.js +2 -2
  83. package/dist/cmd/git/link.js.map +1 -1
  84. package/dist/cmd/git/list.d.ts.map +1 -1
  85. package/dist/cmd/git/list.js +3 -2
  86. package/dist/cmd/git/list.js.map +1 -1
  87. package/dist/cmd/project/auth/init.js +1 -1
  88. package/dist/cmd/project/auth/init.js.map +1 -1
  89. package/dist/cmd/project/auth/shared.d.ts.map +1 -1
  90. package/dist/cmd/project/auth/shared.js +8 -3
  91. package/dist/cmd/project/auth/shared.js.map +1 -1
  92. package/dist/cmd/project/delete.d.ts.map +1 -1
  93. package/dist/cmd/project/delete.js +3 -2
  94. package/dist/cmd/project/delete.js.map +1 -1
  95. package/dist/cmd/project/reconcile.d.ts.map +1 -1
  96. package/dist/cmd/project/reconcile.js +9 -5
  97. package/dist/cmd/project/reconcile.js.map +1 -1
  98. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  99. package/dist/cmd/project/template-flow.js +15 -5
  100. package/dist/cmd/project/template-flow.js.map +1 -1
  101. package/dist/config.d.ts.map +1 -1
  102. package/dist/config.js +3 -2
  103. package/dist/config.js.map +1 -1
  104. package/dist/domain.d.ts.map +1 -1
  105. package/dist/domain.js +4 -3
  106. package/dist/domain.js.map +1 -1
  107. package/dist/internal-logger.d.ts.map +1 -1
  108. package/dist/internal-logger.js +3 -2
  109. package/dist/internal-logger.js.map +1 -1
  110. package/dist/repl.d.ts.map +1 -1
  111. package/dist/repl.js +31 -14
  112. package/dist/repl.js.map +1 -1
  113. package/dist/schema-parser.d.ts.map +1 -1
  114. package/dist/schema-parser.js +4 -1
  115. package/dist/schema-parser.js.map +1 -1
  116. package/dist/sound.d.ts.map +1 -1
  117. package/dist/sound.js +2 -1
  118. package/dist/sound.js.map +1 -1
  119. package/dist/steps.d.ts.map +1 -1
  120. package/dist/steps.js +13 -6
  121. package/dist/steps.js.map +1 -1
  122. package/dist/terminal.js +2 -0
  123. package/dist/terminal.js.map +1 -1
  124. package/dist/tsc-output-parser.d.ts +3 -0
  125. package/dist/tsc-output-parser.d.ts.map +1 -1
  126. package/dist/tsc-output-parser.js +32 -9
  127. package/dist/tsc-output-parser.js.map +1 -1
  128. package/dist/tui/prompt.d.ts.map +1 -1
  129. package/dist/tui/prompt.js +6 -2
  130. package/dist/tui/prompt.js.map +1 -1
  131. package/dist/tui.d.ts.map +1 -1
  132. package/dist/tui.js +26 -15
  133. package/dist/tui.js.map +1 -1
  134. package/dist/typescript-errors.d.ts.map +1 -1
  135. package/dist/typescript-errors.js +5 -2
  136. package/dist/typescript-errors.js.map +1 -1
  137. package/dist/utils/date.d.ts.map +1 -1
  138. package/dist/utils/date.js +5 -1
  139. package/dist/utils/date.js.map +1 -1
  140. package/dist/utils/deps.d.ts.map +1 -1
  141. package/dist/utils/deps.js +5 -3
  142. package/dist/utils/deps.js.map +1 -1
  143. package/dist/utils/detectSubagent.js +1 -1
  144. package/dist/utils/detectSubagent.js.map +1 -1
  145. package/package.json +6 -6
  146. package/src/agent-detection.ts +9 -2
  147. package/src/cli.ts +9 -5
  148. package/src/cmd/ai/index.ts +1 -8
  149. package/src/cmd/ai/prompt/version.ts +1 -1
  150. package/src/cmd/auth/api.ts +4 -1
  151. package/src/cmd/auth/ssh/api.ts +2 -2
  152. package/src/cmd/build/ast.ts +14 -13
  153. package/src/cmd/build/patch/index.ts +3 -0
  154. package/src/cmd/build/vite/index.ts +1 -0
  155. package/src/cmd/build/vite/public-asset-path-plugin.ts +137 -0
  156. package/src/cmd/build/vite/registry-generator.ts +14 -5
  157. package/src/cmd/build/vite/route-discovery.ts +1 -1
  158. package/src/cmd/build/vite/vite-asset-server-config.ts +13 -4
  159. package/src/cmd/build/vite/vite-builder.ts +3 -0
  160. package/src/cmd/canary/index.ts +9 -1
  161. package/src/cmd/cloud/db/create.ts +16 -17
  162. package/src/cmd/cloud/db/delete.ts +19 -20
  163. package/src/cmd/cloud/env/import.ts +6 -3
  164. package/src/cmd/cloud/env/list.ts +11 -9
  165. package/src/cmd/cloud/env/push.ts +6 -3
  166. package/src/cmd/cloud/region/index.ts +3 -3
  167. package/src/cmd/cloud/sandbox/snapshot/build.ts +42 -33
  168. package/src/cmd/cloud/sandbox/snapshot/get.ts +21 -15
  169. package/src/cmd/cloud/storage/create.ts +16 -17
  170. package/src/cmd/cloud/storage/delete.ts +19 -20
  171. package/src/cmd/dev/download.ts +10 -2
  172. package/src/cmd/dev/index.ts +4 -4
  173. package/src/cmd/git/account/add.ts +5 -4
  174. package/src/cmd/git/link.ts +2 -2
  175. package/src/cmd/git/list.ts +7 -6
  176. package/src/cmd/project/auth/init.ts +6 -6
  177. package/src/cmd/project/auth/shared.ts +8 -3
  178. package/src/cmd/project/delete.ts +3 -2
  179. package/src/cmd/project/reconcile.ts +9 -5
  180. package/src/cmd/project/template-flow.ts +15 -5
  181. package/src/config.ts +3 -2
  182. package/src/domain.ts +4 -3
  183. package/src/internal-logger.ts +3 -2
  184. package/src/repl.ts +27 -14
  185. package/src/schema-parser.ts +4 -1
  186. package/src/sound.ts +2 -1
  187. package/src/steps.ts +11 -6
  188. package/src/terminal.ts +2 -1
  189. package/src/tsc-output-parser.ts +61 -38
  190. package/src/tui/prompt.ts +6 -2
  191. package/src/tui.ts +26 -17
  192. package/src/typescript-errors.ts +5 -2
  193. package/src/utils/date.ts +5 -1
  194. package/src/utils/deps.ts +5 -3
  195. package/src/utils/detectSubagent.ts +1 -1
  196. package/dist/cmd/ai/cadence/index.d.ts +0 -3
  197. package/dist/cmd/ai/cadence/index.d.ts.map +0 -1
  198. package/dist/cmd/ai/cadence/index.js +0 -35
  199. package/dist/cmd/ai/cadence/index.js.map +0 -1
  200. package/dist/cmd/ai/cadence/list.d.ts +0 -3
  201. package/dist/cmd/ai/cadence/list.d.ts.map +0 -1
  202. package/dist/cmd/ai/cadence/list.js +0 -167
  203. package/dist/cmd/ai/cadence/list.js.map +0 -1
  204. package/dist/cmd/ai/cadence/pause.d.ts +0 -3
  205. package/dist/cmd/ai/cadence/pause.d.ts.map +0 -1
  206. package/dist/cmd/ai/cadence/pause.js +0 -103
  207. package/dist/cmd/ai/cadence/pause.js.map +0 -1
  208. package/dist/cmd/ai/cadence/resume.d.ts +0 -3
  209. package/dist/cmd/ai/cadence/resume.d.ts.map +0 -1
  210. package/dist/cmd/ai/cadence/resume.js +0 -106
  211. package/dist/cmd/ai/cadence/resume.js.map +0 -1
  212. package/dist/cmd/ai/cadence/status.d.ts +0 -3
  213. package/dist/cmd/ai/cadence/status.d.ts.map +0 -1
  214. package/dist/cmd/ai/cadence/status.js +0 -129
  215. package/dist/cmd/ai/cadence/status.js.map +0 -1
  216. package/dist/cmd/ai/cadence/stop.d.ts +0 -3
  217. package/dist/cmd/ai/cadence/stop.d.ts.map +0 -1
  218. package/dist/cmd/ai/cadence/stop.js +0 -107
  219. package/dist/cmd/ai/cadence/stop.js.map +0 -1
  220. package/dist/cmd/ai/cadence/util.d.ts +0 -44
  221. package/dist/cmd/ai/cadence/util.d.ts.map +0 -1
  222. package/dist/cmd/ai/cadence/util.js +0 -52
  223. package/dist/cmd/ai/cadence/util.js.map +0 -1
  224. package/src/cmd/ai/cadence/index.ts +0 -36
  225. package/src/cmd/ai/cadence/list.ts +0 -183
  226. package/src/cmd/ai/cadence/pause.ts +0 -119
  227. package/src/cmd/ai/cadence/resume.ts +0 -124
  228. package/src/cmd/ai/cadence/status.ts +0 -141
  229. package/src/cmd/ai/cadence/stop.ts +0 -124
  230. package/src/cmd/ai/cadence/util.ts +0 -86
@@ -183,23 +183,26 @@ function buildFileTree(files: SnapshotFileInfo[]): TreeNode {
183
183
  const parts = file.path.split('/');
184
184
  let current = root;
185
185
 
186
- for (let i = 0; i < parts.length; i++) {
187
- const part = parts[i];
188
- if (!current.children.has(part)) {
189
- current.children.set(part, {
190
- name: part,
191
- isFile: i === parts.length - 1,
192
- children: new Map(),
193
- });
194
- }
195
- current = current.children.get(part)!;
186
+ for (let i = 0; i < parts.length; i++) {
187
+ const part = parts[i];
188
+ if (!part) continue;
189
+ if (!current.children.has(part)) {
190
+ current.children.set(part, {
191
+ name: part,
192
+ isFile: i === parts.length - 1,
193
+ children: new Map(),
194
+ });
195
+ }
196
+ const child = current.children.get(part);
197
+ if (!child) continue;
198
+ current = child;
196
199
 
197
- if (i === parts.length - 1) {
198
- current.size = file.size;
199
- current.isFile = true;
200
- }
200
+ if (i === parts.length - 1) {
201
+ current.size = file.size;
202
+ current.isFile = true;
201
203
  }
202
204
  }
205
+ }
203
206
 
204
207
  return root;
205
208
  }
@@ -218,7 +221,9 @@ function printTreeNode(node: TreeNode, prefix: string): void {
218
221
  });
219
222
 
220
223
  for (let i = 0; i < entries.length; i++) {
221
- const [, child] = entries[i];
224
+ const entry = entries[i];
225
+ if (!entry) continue;
226
+ const [, child] = entry;
222
227
  const isLast = i === entries.length - 1;
223
228
  const connector = tui.muted(isLast ? '└── ' : '├── ');
224
229
  const sizeStr =
@@ -237,6 +242,7 @@ function printSandboxTree(sandboxes: SandboxInfo[]): void {
237
242
  const sorted = [...sandboxes].sort((a, b) => a.sandboxId.localeCompare(b.sandboxId));
238
243
  for (let i = 0; i < sorted.length; i++) {
239
244
  const sandbox = sorted[i];
245
+ if (!sandbox) continue;
240
246
  const isLast = i === sorted.length - 1;
241
247
  const connector = tui.muted(isLast ? '└── ' : '├── ');
242
248
  const statusColor = sandbox.status === 'running' ? tui.success : tui.muted;
@@ -67,25 +67,24 @@ export const createSubcommand = defineSubcommand({
67
67
  },
68
68
  });
69
69
 
70
- if (created.length > 0) {
71
- const resource = created[0];
72
-
73
- // Write environment variables to .env if running inside a project
74
- if (ctx.projectDir && resource.env && Object.keys(resource.env).length > 0) {
75
- await addResourceEnvVars(ctx.projectDir, resource.env);
76
- if (!options.json) {
77
- tui.info('Environment variables written to .env');
78
- }
79
- }
80
-
70
+ const resource = created[0];
71
+ if (resource) {
72
+ // Write environment variables to .env if running inside a project
73
+ if (ctx.projectDir && resource.env && Object.keys(resource.env).length > 0) {
74
+ await addResourceEnvVars(ctx.projectDir, resource.env);
81
75
  if (!options.json) {
82
- tui.success(`Created storage: ${tui.bold(resource.name)}`);
76
+ tui.info('Environment variables written to .env');
83
77
  }
84
- return {
85
- success: true,
86
- name: resource.name,
87
- };
88
- } else {
78
+ }
79
+
80
+ if (!options.json) {
81
+ tui.success(`Created storage: ${tui.bold(resource.name)}`);
82
+ }
83
+ return {
84
+ success: true,
85
+ name: resource.name,
86
+ };
87
+ } else {
89
88
  tui.fatal('Failed to create storage');
90
89
  }
91
90
  },
@@ -242,28 +242,27 @@ export const deleteSubcommand = createSubcommand({
242
242
  },
243
243
  });
244
244
 
245
- if (deleted.length > 0) {
246
- const resource = deleted[0];
247
-
248
- // Clear cache entry for deleted bucket
249
- await deleteResourceRegion('bucket', profileName, resource.name);
250
-
251
- // Remove env vars from .env if running inside a project
252
- if (ctx.projectDir && resource.env_keys.length > 0) {
253
- await removeResourceEnvVars(ctx.projectDir, resource.env_keys);
254
- if (!options.json) {
255
- tui.info(`Removed ${resource.env_keys.join(', ')} from .env`);
256
- }
257
- }
258
-
245
+ const resource = deleted[0];
246
+ if (resource) {
247
+ // Clear cache entry for deleted bucket
248
+ await deleteResourceRegion('bucket', profileName, resource.name);
249
+
250
+ // Remove env vars from .env if running inside a project
251
+ if (ctx.projectDir && resource.env_keys.length > 0) {
252
+ await removeResourceEnvVars(ctx.projectDir, resource.env_keys);
259
253
  if (!options.json) {
260
- tui.success(`Deleted storage bucket: ${tui.bold(resource.name)}`);
254
+ tui.info(`Removed ${resource.env_keys.join(', ')} from .env`);
261
255
  }
262
- return {
263
- success: true,
264
- name: resource.name,
265
- };
266
- } else {
256
+ }
257
+
258
+ if (!options.json) {
259
+ tui.success(`Deleted storage bucket: ${tui.bold(resource.name)}`);
260
+ }
261
+ return {
262
+ success: true,
263
+ name: resource.name,
264
+ };
265
+ } else {
267
266
  tui.error('Failed to delete storage bucket');
268
267
  return { success: false, name: bucketName };
269
268
  }
@@ -54,7 +54,7 @@ export async function download(gravityDir: string): Promise<GravityClient> {
54
54
  })) as { release: string; assetFileNames: string[] };
55
55
 
56
56
  const versionTok = res.release.split('@');
57
- const version = versionTok[1];
57
+ const version = versionTok[1] ?? 'unknown';
58
58
  const releaseFilename = join(gravityDir, version, 'gravity');
59
59
  const mustDownload = !existsSync(releaseFilename);
60
60
 
@@ -76,7 +76,11 @@ export async function download(gravityDir: string): Promise<GravityClient> {
76
76
  false,
77
77
  ''
78
78
  )) as string[];
79
- return res[0] as string;
79
+ const file = res[0];
80
+ if (!file) {
81
+ throw new Error('No file downloaded from release');
82
+ }
83
+ return file;
80
84
  },
81
85
  clearOnSuccess: true,
82
86
  });
@@ -107,5 +111,9 @@ export async function download(gravityDir: string): Promise<GravityClient> {
107
111
  rmSync(outputdir, { recursive: true });
108
112
  }
109
113
 
114
+ if (!existsSync(releaseFilename)) {
115
+ throw new Error(`Failed to extract gravity binary to ${releaseFilename}`);
116
+ }
117
+
110
118
  return { filename: releaseFilename, version };
111
119
  }
@@ -1177,10 +1177,10 @@ export const command = createCommand({
1177
1177
  const text = new TextDecoder().decode(chunk);
1178
1178
  const trimmed = text.trim();
1179
1179
 
1180
- // Check for heartbeat port announcement
1181
- const match = trimmed.match(/^HEARTBEAT_PORT=(\d+)$/m);
1182
- if (match) {
1183
- const heartbeatPort = parseInt(match[1], 10);
1180
+ // Check for heartbeat port announcement
1181
+ const match = trimmed.match(/^HEARTBEAT_PORT=(\d+)$/m);
1182
+ if (match?.[1]) {
1183
+ const heartbeatPort = parseInt(match[1], 10);
1184
1184
  logger.debug('Gravity heartbeat port detected: %d', heartbeatPort);
1185
1185
 
1186
1186
  // Start sending heartbeats every 5 seconds
@@ -252,10 +252,11 @@ export const addSubcommand = createSubcommand({
252
252
 
253
253
  const sortedOrgs = [...orgStatuses].sort((a, b) => a.name.localeCompare(b.name));
254
254
 
255
- if (orgs.length === 1) {
256
- orgId = orgs[0].id;
257
- selectedOrg = orgs[0];
258
- } else {
255
+ const firstOrg = orgs[0];
256
+ if (orgs.length === 1 && firstOrg) {
257
+ orgId = firstOrg.id;
258
+ selectedOrg = firstOrg;
259
+ } else {
259
260
  const choices = sortedOrgs.map((org) => {
260
261
  const count = org.integrations.length;
261
262
  const suffix =
@@ -36,10 +36,10 @@ export function detectGitInfo(): DetectedGitInfo {
36
36
  // https://github.com/owner/repo.git
37
37
  // git@github.com:owner/repo.git
38
38
  const httpsMatch = url.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?$/);
39
- if (httpsMatch) repo = httpsMatch[1];
39
+ if (httpsMatch?.[1]) repo = httpsMatch[1];
40
40
 
41
41
  const sshMatch = url.match(/github\.com:([^/]+\/[^/]+?)(?:\.git)?$/);
42
- if (sshMatch) repo = sshMatch[1];
42
+ if (sshMatch?.[1]) repo = sshMatch[1];
43
43
  }
44
44
 
45
45
  // Detect current branch
@@ -53,12 +53,13 @@ export const listSubcommand = createSubcommand({
53
53
  return [];
54
54
  }
55
55
 
56
- // Select org
57
- let orgId = opts.org;
58
- if (!orgId) {
59
- if (orgs.length === 1) {
60
- orgId = orgs[0].id;
61
- } else {
56
+ // Select org
57
+ let orgId = opts.org;
58
+ if (!orgId) {
59
+ const firstOrg = orgs[0];
60
+ if (orgs.length === 1 && firstOrg) {
61
+ orgId = firstOrg.id;
62
+ } else {
62
63
  tui.newline();
63
64
  const orgChoices = orgs.map((o) => ({
64
65
  name: o.id,
@@ -73,14 +73,14 @@ export const initSubcommand = createSubcommand({
73
73
  if (!databaseUrl) {
74
74
  // Check .env file
75
75
  const envPath = path.join(projectDir, '.env');
76
- if (fs.existsSync(envPath)) {
77
- const envContent = fs.readFileSync(envPath, 'utf-8');
78
- const match = envContent.match(/^DATABASE_URL=(.+)$/m);
79
- if (match) {
80
- databaseUrl = match[1].trim().replace(/^["']|["']$/g, '');
81
- }
76
+ if (fs.existsSync(envPath)) {
77
+ const envContent = fs.readFileSync(envPath, 'utf-8');
78
+ const match = envContent.match(/^DATABASE_URL=(.+)$/m);
79
+ if (match?.[1]) {
80
+ databaseUrl = match[1].trim().replace(/^["']|["']$/g, '');
82
81
  }
83
82
  }
83
+ }
84
84
 
85
85
  // Show database picker (with existing as first option if configured)
86
86
  const dbInfo = await selectOrCreateDatabase({
@@ -117,7 +117,8 @@ export async function selectOrCreateDatabase(options: {
117
117
  }
118
118
 
119
119
  if (!region) {
120
- region = databases.length > 0 ? databases[0].cloud_region : 'usc';
120
+ const firstDb = databases[0];
121
+ region = firstDb ? firstDb.cloud_region : 'usc';
121
122
  logger.trace(`[auth init] Using fallback region: ${region}`);
122
123
  }
123
124
 
@@ -129,11 +130,11 @@ export async function selectOrCreateDatabase(options: {
129
130
  callback: async () => createResources(regionalClient, orgId, region, [{ type: 'db' }]),
130
131
  });
131
132
 
132
- if (created.length === 0) {
133
+ const newDb = created[0];
134
+ if (!newDb) {
133
135
  tui.fatal('Failed to create database');
134
136
  }
135
137
 
136
- const newDb = created[0];
137
138
  tui.success(`Created database: ${tui.bold(newDb.name)}`);
138
139
 
139
140
  // Fetch updated list to get the URL
@@ -142,6 +143,8 @@ export async function selectOrCreateDatabase(options: {
142
143
 
143
144
  if (!dbInfo?.url) {
144
145
  tui.fatal('Failed to retrieve database connection URL');
146
+ // TypeScript doesn't know fatal never returns, so we need this
147
+ throw new Error('Unreachable');
145
148
  }
146
149
 
147
150
  return { name: newDb.name, url: dbInfo.url, region };
@@ -150,6 +153,8 @@ export async function selectOrCreateDatabase(options: {
150
153
  const selectedDb = databases.find((d) => d.name === response.database);
151
154
  if (!selectedDb?.url) {
152
155
  tui.fatal('Failed to retrieve database connection URL');
156
+ // TypeScript doesn't know fatal never returns, so we need this
157
+ throw new Error('Unreachable');
153
158
  }
154
159
 
155
160
  return { name: selectedDb.name, url: selectedDb.url, region: selectedDb.cloud_region };
@@ -144,9 +144,10 @@ export const deleteSubcommand = createSubcommand({
144
144
 
145
145
  // Confirm deletion
146
146
  if (!skipConfirm) {
147
+ const firstProject = projectsToDelete[0];
147
148
  const projectDisplay =
148
- projectsToDelete.length === 1
149
- ? formatProjectDisplay(projectsToDelete[0])
149
+ projectsToDelete.length === 1 && firstProject
150
+ ? formatProjectDisplay(firstProject)
150
151
  : projectsToDelete.map((p) => `\n • ${formatProjectDisplay(p)}`).join('');
151
152
  tui.warning(`You are about to delete: ${tui.bold(projectDisplay)}`);
152
153
 
@@ -217,8 +217,9 @@ async function selectRegion(regions: RegionList, defaultRegion?: string): Promis
217
217
  throw new Error('No cloud regions available');
218
218
  }
219
219
 
220
- if (regions.length === 1) {
221
- return regions[0].region;
220
+ const firstRegion = regions[0];
221
+ if (regions.length === 1 && firstRegion) {
222
+ return firstRegion.region;
222
223
  }
223
224
 
224
225
  // Build options from API regions
@@ -228,18 +229,21 @@ async function selectRegion(regions: RegionList, defaultRegion?: string): Promis
228
229
  }));
229
230
 
230
231
  // Move default to top if found
231
- const defaultValue = defaultRegion ?? regions[0].region;
232
+ const defaultValue = defaultRegion ?? firstRegion?.region ?? '';
232
233
  const defaultIndex = options.findIndex((r) => r.value === defaultValue);
233
234
  if (defaultIndex > 0) {
234
235
  const [defaultItem] = options.splice(defaultIndex, 1);
235
- options.unshift(defaultItem);
236
+ if (defaultItem) {
237
+ options.unshift(defaultItem);
238
+ }
236
239
  }
237
240
 
238
241
  const prompt = createPrompt();
242
+ const firstOption = options[0];
239
243
  return prompt.select({
240
244
  message: 'Select a region:',
241
245
  options,
242
- initial: options[0].value,
246
+ initial: firstOption?.value ?? '',
243
247
  });
244
248
  }
245
249
 
@@ -220,7 +220,12 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
220
220
  }
221
221
  selectedTemplate = found;
222
222
  } else if (!isInteractive || templates.length === 1) {
223
- selectedTemplate = templates[0];
223
+ const firstTemplate = templates[0];
224
+ if (!firstTemplate) {
225
+ logger.fatal('No templates available', ErrorCode.RESOURCE_NOT_FOUND);
226
+ return undefined as never;
227
+ }
228
+ selectedTemplate = firstTemplate;
224
229
  } else {
225
230
  let maxLength = 15;
226
231
  templates.forEach((t) => {
@@ -572,14 +577,19 @@ export async function runCreateFlow(options: CreateFlowOptions): Promise<CreateF
572
577
  return createResources(catalystClient!, orgId!, region!, [{ type: 'db' }]);
573
578
  },
574
579
  });
575
- authDatabaseName = created[0].name;
580
+ const createdDb = created[0];
581
+ if (!createdDb) {
582
+ logger.fatal('Failed to create database for auth', ErrorCode.RESOURCE_NOT_FOUND);
583
+ return undefined as never;
584
+ }
585
+ authDatabaseName = createdDb.name;
576
586
 
577
587
  // Get env vars from created resource
578
- if (created[0]?.env) {
579
- authDatabaseUrl = created[0].env.DATABASE_URL;
588
+ if (createdDb.env) {
589
+ authDatabaseUrl = createdDb.env.DATABASE_URL;
580
590
  // Also add to resourceEnvVars if not already set
581
591
  if (!resourceEnvVars.DATABASE_URL) {
582
- Object.assign(resourceEnvVars, created[0].env);
592
+ Object.assign(resourceEnvVars, createdDb.env);
583
593
  }
584
594
  }
585
595
  }
package/src/config.ts CHANGED
@@ -789,8 +789,9 @@ export async function getDefaultRegion(
789
789
  const file = Bun.file(cachePath);
790
790
  if (await file.exists()) {
791
791
  const data: RegionsCacheData = await file.json();
792
- if (data.regions && data.regions.length > 0) {
793
- return data.regions[0].region;
792
+ const firstRegion = data.regions?.[0];
793
+ if (firstRegion) {
794
+ return firstRegion.region;
794
795
  }
795
796
  }
796
797
  } catch {
package/src/domain.ts CHANGED
@@ -79,8 +79,9 @@ async function fetchDNSRecord(name: string, type: string): Promise<string | null
79
79
  });
80
80
  if (res.ok) {
81
81
  const result = (await res.json()) as CFRecord;
82
- if (result?.Answer?.length) {
83
- return result.Answer[0].data.replace(/\.$/, ''); // DNS records end with . so we remove that
82
+ const firstAnswer = result?.Answer?.[0];
83
+ if (firstAnswer) {
84
+ return firstAnswer.data.replace(/\.$/, ''); // DNS records end with . so we remove that
84
85
  }
85
86
  }
86
87
  return null;
@@ -104,7 +105,7 @@ export async function checkCustomDomainForDNS(
104
105
  config?: Config | null
105
106
  ): Promise<DNSResult[]> {
106
107
  const suffix = config?.overrides?.api_url?.includes('agentuity.io') ? LOCAL_DNS : PRODUCTION_DNS;
107
- const id = Bun.hash.xxHash64(projectId).toString(16);
108
+ const id = Bun.hash.xxHash64(projectId).toString(16).padStart(16, '0');
108
109
  const proxy = `p${id}.${suffix}`;
109
110
 
110
111
  return Promise.all(
@@ -434,12 +434,13 @@ export function getLatestLogSession(): string | null {
434
434
  const entries = readdirSync(logsDir, { withFileTypes: true });
435
435
  const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
436
436
 
437
- if (dirs.length === 0) {
437
+ const firstDir = dirs[0];
438
+ if (!firstDir) {
438
439
  return null;
439
440
  }
440
441
 
441
442
  // Return the first directory (should be the only one due to cleanup)
442
- return join(logsDir, dirs[0]);
443
+ return join(logsDir, firstDir);
443
444
  } catch {
444
445
  return null;
445
446
  }
package/src/repl.ts CHANGED
@@ -184,6 +184,7 @@ function parseCommandLine(line: string): ParsedCommand {
184
184
  // Parse remaining tokens into args and options
185
185
  for (let i = 1; i < tokens.length; i++) {
186
186
  const token = tokens[i];
187
+ if (token === undefined) continue;
187
188
 
188
189
  if (token.startsWith('--')) {
189
190
  // Long option: --name=value or --flag
@@ -194,8 +195,9 @@ function parseCommandLine(line: string): ParsedCommand {
194
195
  options[name.slice(0, eqIndex)] = name.slice(eqIndex + 1);
195
196
  } else {
196
197
  // Check if next token is a value
197
- if (i + 1 < tokens.length && !tokens[i + 1].startsWith('-')) {
198
- options[name] = tokens[i + 1];
198
+ const nextToken = tokens[i + 1];
199
+ if (i + 1 < tokens.length && nextToken !== undefined && !nextToken.startsWith('-')) {
200
+ options[name] = nextToken;
199
201
  i++;
200
202
  } else {
201
203
  options[name] = true;
@@ -206,8 +208,9 @@ function parseCommandLine(line: string): ParsedCommand {
206
208
  const name = token.slice(1);
207
209
 
208
210
  // Check if next token is a value
209
- if (i + 1 < tokens.length && !tokens[i + 1].startsWith('-')) {
210
- options[name] = tokens[i + 1];
211
+ const nextToken = tokens[i + 1];
212
+ if (i + 1 < tokens.length && nextToken !== undefined && !nextToken.startsWith('-')) {
213
+ options[name] = nextToken;
211
214
  i++;
212
215
  } else {
213
216
  options[name] = true;
@@ -603,7 +606,7 @@ function getAutocompleteMatches(
603
606
  if (!buffer.trim()) return [];
604
607
 
605
608
  const tokens = buffer.trim().split(/\s+/);
606
- const firstToken = tokens[0].toLowerCase();
609
+ const firstToken = tokens[0]?.toLowerCase() ?? '';
607
610
 
608
611
  // If we're typing the first word (no trailing space), suggest commands
609
612
  if (tokens.length === 1 && buffer === buffer.trimEnd()) {
@@ -623,7 +626,7 @@ function getAutocompleteMatches(
623
626
  if (tokens.length === 2 && buffer === buffer.trimEnd() && commandMap) {
624
627
  const cmd = commandMap.get(firstToken);
625
628
  if (cmd?.subcommands) {
626
- const subToken = tokens[1].toLowerCase();
629
+ const subToken = tokens[1]?.toLowerCase() ?? '';
627
630
  return cmd.subcommands
628
631
  .filter((sub) => sub.name.startsWith(subToken) && sub.name !== subToken)
629
632
  .map((sub) => sub.name);
@@ -647,8 +650,10 @@ function getAutocompleteSuggestion(
647
650
  if (matches.length === 0) return '';
648
651
 
649
652
  const selectedMatch = matches[cycleIndex % matches.length];
653
+ if (selectedMatch === undefined) return '';
654
+
650
655
  const tokens = buffer.trim().split(/\s+/);
651
- const firstToken = tokens[0].toLowerCase();
656
+ const firstToken = tokens[0]?.toLowerCase() ?? '';
652
657
 
653
658
  // Typing first word (command name)
654
659
  if (tokens.length === 1 && buffer === buffer.trimEnd()) {
@@ -675,7 +680,7 @@ function getAutocompleteSuggestion(
675
680
  // Typing subcommand name
676
681
  if (tokens.length === 2 && buffer === buffer.trimEnd()) {
677
682
  const cmd = commandMap.get(firstToken);
678
- const subToken = tokens[1];
683
+ const subToken = tokens[1] ?? '';
679
684
  const subcommand = cmd?.subcommands?.find((sub) => sub.name === selectedMatch);
680
685
 
681
686
  let suggestion = selectedMatch.slice(subToken.length);
@@ -791,7 +796,7 @@ class ActivityIndicator {
791
796
  }
792
797
 
793
798
  private draw() {
794
- const frame = this.frames[this.currentFrame];
799
+ const frame = this.frames[this.currentFrame] ?? this.frames[0] ?? '⠋';
795
800
  // Clear line, draw spinner, stay on same line
796
801
  process.stdout.write('\r\x1b[K'); // Clear line from cursor
797
802
  process.stdout.write(`${tui.muted(frame)} ${tui.muted(this.message)}...`);
@@ -855,6 +860,7 @@ async function showCommandPicker(
855
860
  // Draw commands
856
861
  for (let i = 0; i < commands.length; i++) {
857
862
  const cmd = commands[i];
863
+ if (cmd === undefined) continue;
858
864
  const isSelected = i === selectedIndex;
859
865
  const prefix = isSelected ? '▶ ' : ' ';
860
866
  const style = isSelected ? '\x1b[7m' : ''; // Reverse video for selected
@@ -913,7 +919,11 @@ async function showCommandPicker(
913
919
  const selected = commands[selectedIndex];
914
920
  cleanup();
915
921
  clearPicker();
916
- resolve(selected.name + (selected.argHint ? ' ' : ''));
922
+ if (selected) {
923
+ resolve(selected.name + (selected.argHint ? ' ' : ''));
924
+ } else {
925
+ resolve(null);
926
+ }
917
927
  return;
918
928
  }
919
929
 
@@ -957,6 +967,7 @@ function applySyntaxHighlighting(buffer: string, commands: string[]): string {
957
967
 
958
968
  for (let i = 0; i < tokens.length; i++) {
959
969
  const token = tokens[i];
970
+ if (token === undefined) continue;
960
971
 
961
972
  // Skip whitespace
962
973
  if (/^\s+$/.test(token)) {
@@ -1018,7 +1029,8 @@ async function readLine(
1018
1029
 
1019
1030
  const searchHistory = (query: string, startFrom: number): number => {
1020
1031
  for (let i = startFrom - 1; i >= 0; i--) {
1021
- if (history[i].toLowerCase().includes(query.toLowerCase())) {
1032
+ const historyEntry = history[i];
1033
+ if (historyEntry !== undefined && historyEntry.toLowerCase().includes(query.toLowerCase())) {
1022
1034
  return i;
1023
1035
  }
1024
1036
  }
@@ -1057,7 +1069,8 @@ async function readLine(
1057
1069
  }
1058
1070
  const linePrompt = currentLineIndex === 0 ? prompt : '... ';
1059
1071
  process.stdout.write('\r');
1060
- process.stdout.write(linePrompt + lines[currentLineIndex].slice(0, cursorPos));
1072
+ const currentLine = lines[currentLineIndex] ?? '';
1073
+ process.stdout.write(linePrompt + currentLine.slice(0, cursorPos));
1061
1074
  } else {
1062
1075
  // Single-line mode (original behavior)
1063
1076
  process.stdout.write('\r\x1b[K');
@@ -1282,7 +1295,7 @@ async function readLine(
1282
1295
  lines.push('');
1283
1296
  currentLineIndex++;
1284
1297
  cursorPos = 0;
1285
- buffer = lines[currentLineIndex];
1298
+ buffer = lines[currentLineIndex] ?? '';
1286
1299
  process.stdout.write('\n');
1287
1300
  process.stdout.write('... ');
1288
1301
  return;
@@ -1293,7 +1306,7 @@ async function readLine(
1293
1306
  if (searchMode) {
1294
1307
  // Accept search result
1295
1308
  if (searchResultIndex >= 0) {
1296
- buffer = history[searchResultIndex];
1309
+ buffer = history[searchResultIndex] ?? '';
1297
1310
  }
1298
1311
  searchMode = false;
1299
1312
  process.stdout.write('\n');
@@ -373,7 +373,10 @@ export function buildValidationInput(
373
373
  if (schemas.args) {
374
374
  const parsed = parseArgsSchema(schemas.args);
375
375
  for (let i = 0; i < parsed.names.length; i++) {
376
- result.args[parsed.names[i]] = rawArgs[i];
376
+ const name = parsed.names[i];
377
+ if (name !== undefined) {
378
+ result.args[name] = rawArgs[i];
379
+ }
377
380
  }
378
381
  }
379
382
 
package/src/sound.ts CHANGED
@@ -17,7 +17,8 @@ export function playSound(): void {
17
17
  return;
18
18
  }
19
19
 
20
- if (process.stdout.isTTY && Bun.which(command[0])) {
20
+ const executable = command[0];
21
+ if (process.stdout.isTTY && executable && Bun.which(executable)) {
21
22
  try {
22
23
  Bun.spawn(command, {
23
24
  stdio: ['ignore', 'ignore', 'ignore'],