@agentuity/cli 2.0.10 → 3.0.0-alpha.0

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 (353) hide show
  1. package/dist/cmd/ai/prompt/index.d.ts.map +1 -1
  2. package/dist/cmd/ai/prompt/index.js +2 -7
  3. package/dist/cmd/ai/prompt/index.js.map +1 -1
  4. package/dist/cmd/build/adapters/generic.d.ts +29 -0
  5. package/dist/cmd/build/adapters/generic.d.ts.map +1 -0
  6. package/dist/cmd/build/adapters/generic.js +190 -0
  7. package/dist/cmd/build/adapters/generic.js.map +1 -0
  8. package/dist/cmd/build/adapters/index.d.ts +15 -0
  9. package/dist/cmd/build/adapters/index.d.ts.map +1 -0
  10. package/dist/cmd/build/adapters/index.js +24 -0
  11. package/dist/cmd/build/adapters/index.js.map +1 -0
  12. package/dist/cmd/build/adapters/nextjs.d.ts +11 -0
  13. package/dist/cmd/build/adapters/nextjs.d.ts.map +1 -0
  14. package/dist/cmd/build/adapters/nextjs.js +118 -0
  15. package/dist/cmd/build/adapters/nextjs.js.map +1 -0
  16. package/dist/cmd/build/adapters/static-server.d.ts +23 -0
  17. package/dist/cmd/build/adapters/static-server.d.ts.map +1 -0
  18. package/dist/cmd/build/adapters/static-server.js +137 -0
  19. package/dist/cmd/build/adapters/static-server.js.map +1 -0
  20. package/dist/cmd/build/adapters/types.d.ts +71 -0
  21. package/dist/cmd/build/adapters/types.d.ts.map +1 -0
  22. package/dist/cmd/build/adapters/types.js +8 -0
  23. package/dist/cmd/build/adapters/types.js.map +1 -0
  24. package/dist/cmd/build/detect/engine.d.ts +24 -0
  25. package/dist/cmd/build/detect/engine.d.ts.map +1 -0
  26. package/dist/cmd/build/detect/engine.js +91 -0
  27. package/dist/cmd/build/detect/engine.js.map +1 -0
  28. package/dist/cmd/build/detect/frameworks.d.ts +66 -0
  29. package/dist/cmd/build/detect/frameworks.d.ts.map +1 -0
  30. package/dist/cmd/build/detect/frameworks.js +278 -0
  31. package/dist/cmd/build/detect/frameworks.js.map +1 -0
  32. package/dist/cmd/build/detect/generic.d.ts +13 -0
  33. package/dist/cmd/build/detect/generic.d.ts.map +1 -0
  34. package/dist/cmd/build/detect/generic.js +62 -0
  35. package/dist/cmd/build/detect/generic.js.map +1 -0
  36. package/dist/cmd/build/detect/index.d.ts +27 -0
  37. package/dist/cmd/build/detect/index.d.ts.map +1 -0
  38. package/dist/cmd/build/detect/index.js +76 -0
  39. package/dist/cmd/build/detect/index.js.map +1 -0
  40. package/dist/cmd/build/detect/types.d.ts +91 -0
  41. package/dist/cmd/build/detect/types.d.ts.map +1 -0
  42. package/dist/cmd/build/detect/types.js +9 -0
  43. package/dist/cmd/build/detect/types.js.map +1 -0
  44. package/dist/cmd/build/detect/util.d.ts +41 -0
  45. package/dist/cmd/build/detect/util.d.ts.map +1 -0
  46. package/dist/cmd/build/detect/util.js +101 -0
  47. package/dist/cmd/build/detect/util.js.map +1 -0
  48. package/dist/cmd/build/index.d.ts.map +1 -1
  49. package/dist/cmd/build/index.js +49 -22
  50. package/dist/cmd/build/index.js.map +1 -1
  51. package/dist/cmd/build/package/index.d.ts +30 -0
  52. package/dist/cmd/build/package/index.d.ts.map +1 -0
  53. package/dist/cmd/build/package/index.js +39 -0
  54. package/dist/cmd/build/package/index.js.map +1 -0
  55. package/dist/cmd/build/package/launch.d.ts +56 -0
  56. package/dist/cmd/build/package/launch.d.ts.map +1 -0
  57. package/dist/cmd/build/package/launch.js +56 -0
  58. package/dist/cmd/build/package/launch.js.map +1 -0
  59. package/dist/cmd/build/typecheck.d.ts.map +1 -1
  60. package/dist/cmd/build/typecheck.js +8 -0
  61. package/dist/cmd/build/typecheck.js.map +1 -1
  62. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  63. package/dist/cmd/cloud/deploy.js +63 -13
  64. package/dist/cmd/cloud/deploy.js.map +1 -1
  65. package/dist/cmd/coder/create.d.ts.map +1 -1
  66. package/dist/cmd/coder/create.js +18 -0
  67. package/dist/cmd/coder/create.js.map +1 -1
  68. package/dist/cmd/coder/index.d.ts.map +1 -1
  69. package/dist/cmd/coder/index.js +4 -0
  70. package/dist/cmd/coder/index.js.map +1 -1
  71. package/dist/cmd/coder/start.d.ts.map +1 -1
  72. package/dist/cmd/coder/start.js +49 -1
  73. package/dist/cmd/coder/start.js.map +1 -1
  74. package/dist/cmd/coder/update.d.ts.map +1 -1
  75. package/dist/cmd/coder/update.js +21 -1
  76. package/dist/cmd/coder/update.js.map +1 -1
  77. package/dist/cmd/coder/workspace/create.d.ts.map +1 -1
  78. package/dist/cmd/coder/workspace/create.js +17 -1
  79. package/dist/cmd/coder/workspace/create.js.map +1 -1
  80. package/dist/cmd/coder/workspace/list.js +2 -2
  81. package/dist/cmd/coder/workspace/list.js.map +1 -1
  82. package/dist/cmd/dev/index.d.ts +9 -0
  83. package/dist/cmd/dev/index.d.ts.map +1 -1
  84. package/dist/cmd/dev/index.js +127 -923
  85. package/dist/cmd/dev/index.js.map +1 -1
  86. package/dist/cmd/project/auth/shared.d.ts.map +1 -1
  87. package/dist/cmd/project/auth/shared.js +14 -38
  88. package/dist/cmd/project/auth/shared.js.map +1 -1
  89. package/dist/cmd/project/create.d.ts.map +1 -1
  90. package/dist/cmd/project/create.js +12 -19
  91. package/dist/cmd/project/create.js.map +1 -1
  92. package/dist/cmd/project/frameworks-ai-examples.d.ts +15 -0
  93. package/dist/cmd/project/frameworks-ai-examples.d.ts.map +1 -0
  94. package/dist/cmd/project/frameworks-ai-examples.js +160 -0
  95. package/dist/cmd/project/frameworks-ai-examples.js.map +1 -0
  96. package/dist/cmd/project/frameworks-landing-pages.d.ts +17 -0
  97. package/dist/cmd/project/frameworks-landing-pages.d.ts.map +1 -0
  98. package/dist/cmd/project/frameworks-landing-pages.js +242 -0
  99. package/dist/cmd/project/frameworks-landing-pages.js.map +1 -0
  100. package/dist/cmd/project/frameworks.d.ts +58 -0
  101. package/dist/cmd/project/frameworks.d.ts.map +1 -0
  102. package/dist/cmd/project/frameworks.js +152 -0
  103. package/dist/cmd/project/frameworks.js.map +1 -0
  104. package/dist/cmd/project/reconcile.d.ts.map +1 -1
  105. package/dist/cmd/project/reconcile.js +10 -23
  106. package/dist/cmd/project/reconcile.js.map +1 -1
  107. package/dist/cmd/project/remote-import.js +1 -1
  108. package/dist/cmd/project/scaffold.d.ts +58 -0
  109. package/dist/cmd/project/scaffold.d.ts.map +1 -0
  110. package/dist/cmd/project/scaffold.js +223 -0
  111. package/dist/cmd/project/scaffold.js.map +1 -0
  112. package/dist/cmd/project/template-flow.d.ts +8 -4
  113. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  114. package/dist/cmd/project/template-flow.js +93 -144
  115. package/dist/cmd/project/template-flow.js.map +1 -1
  116. package/dist/deploy-metadata.d.ts +49 -0
  117. package/dist/deploy-metadata.d.ts.map +1 -0
  118. package/dist/deploy-metadata.js +183 -0
  119. package/dist/deploy-metadata.js.map +1 -0
  120. package/dist/index.d.ts +1 -1
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/index.js.map +1 -1
  123. package/dist/types.d.ts +25 -31
  124. package/dist/types.d.ts.map +1 -1
  125. package/dist/types.js.map +1 -1
  126. package/package.json +13 -8
  127. package/src/cmd/ai/prompt/index.ts +2 -7
  128. package/src/cmd/build/adapters/generic.ts +239 -0
  129. package/src/cmd/build/adapters/index.ts +30 -0
  130. package/src/cmd/build/adapters/nextjs.ts +146 -0
  131. package/src/cmd/build/adapters/static-server.ts +143 -0
  132. package/src/cmd/build/adapters/types.ts +93 -0
  133. package/src/cmd/build/detect/engine.ts +111 -0
  134. package/src/cmd/build/detect/frameworks.ts +335 -0
  135. package/src/cmd/build/detect/generic.ts +71 -0
  136. package/src/cmd/build/detect/index.ts +122 -0
  137. package/src/cmd/build/detect/types.ts +109 -0
  138. package/src/cmd/build/detect/util.ts +104 -0
  139. package/src/cmd/build/index.ts +64 -24
  140. package/src/cmd/build/package/index.ts +66 -0
  141. package/src/cmd/build/package/launch.ts +104 -0
  142. package/src/cmd/build/typecheck.ts +9 -0
  143. package/src/cmd/cloud/deploy.ts +86 -13
  144. package/src/cmd/coder/create.ts +24 -1
  145. package/src/cmd/coder/index.ts +4 -0
  146. package/src/cmd/coder/start.ts +60 -1
  147. package/src/cmd/coder/update.ts +18 -1
  148. package/src/cmd/coder/workspace/create.ts +20 -2
  149. package/src/cmd/coder/workspace/list.ts +2 -2
  150. package/src/cmd/dev/index.ts +155 -1059
  151. package/src/cmd/project/auth/shared.ts +14 -39
  152. package/src/cmd/project/create.ts +14 -19
  153. package/src/cmd/project/frameworks-ai-examples.ts +166 -0
  154. package/src/cmd/project/frameworks-landing-pages.ts +267 -0
  155. package/src/cmd/project/frameworks.ts +223 -0
  156. package/src/cmd/project/reconcile.ts +10 -22
  157. package/src/cmd/project/remote-import.ts +1 -1
  158. package/src/cmd/project/scaffold.ts +300 -0
  159. package/src/cmd/project/template-flow.ts +102 -156
  160. package/src/deploy-metadata.ts +253 -0
  161. package/src/index.ts +0 -2
  162. package/src/types.ts +0 -31
  163. package/dist/agents-docs.d.ts +0 -23
  164. package/dist/agents-docs.d.ts.map +0 -1
  165. package/dist/agents-docs.js +0 -56
  166. package/dist/agents-docs.js.map +0 -1
  167. package/dist/cmd/ai/prompt/agent.d.ts +0 -10
  168. package/dist/cmd/ai/prompt/agent.d.ts.map +0 -1
  169. package/dist/cmd/ai/prompt/agent.js +0 -28
  170. package/dist/cmd/ai/prompt/agent.js.map +0 -1
  171. package/dist/cmd/build/app-router-detector.d.ts +0 -39
  172. package/dist/cmd/build/app-router-detector.d.ts.map +0 -1
  173. package/dist/cmd/build/app-router-detector.js +0 -229
  174. package/dist/cmd/build/app-router-detector.js.map +0 -1
  175. package/dist/cmd/build/format-schema.d.ts +0 -6
  176. package/dist/cmd/build/format-schema.d.ts.map +0 -1
  177. package/dist/cmd/build/format-schema.js +0 -60
  178. package/dist/cmd/build/format-schema.js.map +0 -1
  179. package/dist/cmd/build/vite/agent-discovery.d.ts +0 -37
  180. package/dist/cmd/build/vite/agent-discovery.d.ts.map +0 -1
  181. package/dist/cmd/build/vite/agent-discovery.js +0 -263
  182. package/dist/cmd/build/vite/agent-discovery.js.map +0 -1
  183. package/dist/cmd/build/vite/beacon-plugin.d.ts +0 -19
  184. package/dist/cmd/build/vite/beacon-plugin.d.ts.map +0 -1
  185. package/dist/cmd/build/vite/beacon-plugin.js +0 -137
  186. package/dist/cmd/build/vite/beacon-plugin.js.map +0 -1
  187. package/dist/cmd/build/vite/browser-env-plugin.d.ts +0 -9
  188. package/dist/cmd/build/vite/browser-env-plugin.d.ts.map +0 -1
  189. package/dist/cmd/build/vite/browser-env-plugin.js +0 -28
  190. package/dist/cmd/build/vite/browser-env-plugin.js.map +0 -1
  191. package/dist/cmd/build/vite/bun-dev-server.d.ts +0 -67
  192. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +0 -1
  193. package/dist/cmd/build/vite/bun-dev-server.js +0 -340
  194. package/dist/cmd/build/vite/bun-dev-server.js.map +0 -1
  195. package/dist/cmd/build/vite/bundle-files.d.ts +0 -12
  196. package/dist/cmd/build/vite/bundle-files.d.ts.map +0 -1
  197. package/dist/cmd/build/vite/bundle-files.js +0 -107
  198. package/dist/cmd/build/vite/bundle-files.js.map +0 -1
  199. package/dist/cmd/build/vite/config-loader.d.ts +0 -29
  200. package/dist/cmd/build/vite/config-loader.d.ts.map +0 -1
  201. package/dist/cmd/build/vite/config-loader.js +0 -57
  202. package/dist/cmd/build/vite/config-loader.js.map +0 -1
  203. package/dist/cmd/build/vite/db-rewrite.d.ts +0 -50
  204. package/dist/cmd/build/vite/db-rewrite.d.ts.map +0 -1
  205. package/dist/cmd/build/vite/db-rewrite.js +0 -169
  206. package/dist/cmd/build/vite/db-rewrite.js.map +0 -1
  207. package/dist/cmd/build/vite/docs-generator.d.ts +0 -13
  208. package/dist/cmd/build/vite/docs-generator.d.ts.map +0 -1
  209. package/dist/cmd/build/vite/docs-generator.js +0 -97
  210. package/dist/cmd/build/vite/docs-generator.js.map +0 -1
  211. package/dist/cmd/build/vite/env-types-generator.d.ts +0 -26
  212. package/dist/cmd/build/vite/env-types-generator.d.ts.map +0 -1
  213. package/dist/cmd/build/vite/env-types-generator.js +0 -110
  214. package/dist/cmd/build/vite/env-types-generator.js.map +0 -1
  215. package/dist/cmd/build/vite/index.d.ts +0 -3
  216. package/dist/cmd/build/vite/index.d.ts.map +0 -1
  217. package/dist/cmd/build/vite/index.js +0 -4
  218. package/dist/cmd/build/vite/index.js.map +0 -1
  219. package/dist/cmd/build/vite/lifecycle-generator.d.ts +0 -19
  220. package/dist/cmd/build/vite/lifecycle-generator.d.ts.map +0 -1
  221. package/dist/cmd/build/vite/lifecycle-generator.js +0 -328
  222. package/dist/cmd/build/vite/lifecycle-generator.js.map +0 -1
  223. package/dist/cmd/build/vite/metadata-generator.d.ts +0 -36
  224. package/dist/cmd/build/vite/metadata-generator.d.ts.map +0 -1
  225. package/dist/cmd/build/vite/metadata-generator.js +0 -575
  226. package/dist/cmd/build/vite/metadata-generator.js.map +0 -1
  227. package/dist/cmd/build/vite/prompt-generator.d.ts +0 -23
  228. package/dist/cmd/build/vite/prompt-generator.d.ts.map +0 -1
  229. package/dist/cmd/build/vite/prompt-generator.js +0 -123
  230. package/dist/cmd/build/vite/prompt-generator.js.map +0 -1
  231. package/dist/cmd/build/vite/public-asset-path-plugin.d.ts +0 -45
  232. package/dist/cmd/build/vite/public-asset-path-plugin.d.ts.map +0 -1
  233. package/dist/cmd/build/vite/public-asset-path-plugin.js +0 -166
  234. package/dist/cmd/build/vite/public-asset-path-plugin.js.map +0 -1
  235. package/dist/cmd/build/vite/route-discovery.d.ts +0 -64
  236. package/dist/cmd/build/vite/route-discovery.d.ts.map +0 -1
  237. package/dist/cmd/build/vite/route-discovery.js +0 -187
  238. package/dist/cmd/build/vite/route-discovery.js.map +0 -1
  239. package/dist/cmd/build/vite/server-bundler.d.ts +0 -20
  240. package/dist/cmd/build/vite/server-bundler.d.ts.map +0 -1
  241. package/dist/cmd/build/vite/server-bundler.js +0 -388
  242. package/dist/cmd/build/vite/server-bundler.js.map +0 -1
  243. package/dist/cmd/build/vite/static-renderer.d.ts +0 -26
  244. package/dist/cmd/build/vite/static-renderer.d.ts.map +0 -1
  245. package/dist/cmd/build/vite/static-renderer.js +0 -188
  246. package/dist/cmd/build/vite/static-renderer.js.map +0 -1
  247. package/dist/cmd/build/vite/tailwind-source-plugin.d.ts +0 -15
  248. package/dist/cmd/build/vite/tailwind-source-plugin.d.ts.map +0 -1
  249. package/dist/cmd/build/vite/tailwind-source-plugin.js +0 -61
  250. package/dist/cmd/build/vite/tailwind-source-plugin.js.map +0 -1
  251. package/dist/cmd/build/vite/vite-asset-server-config.d.ts +0 -24
  252. package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +0 -1
  253. package/dist/cmd/build/vite/vite-asset-server-config.js +0 -285
  254. package/dist/cmd/build/vite/vite-asset-server-config.js.map +0 -1
  255. package/dist/cmd/build/vite/vite-asset-server.d.ts +0 -30
  256. package/dist/cmd/build/vite/vite-asset-server.d.ts.map +0 -1
  257. package/dist/cmd/build/vite/vite-asset-server.js +0 -109
  258. package/dist/cmd/build/vite/vite-asset-server.js.map +0 -1
  259. package/dist/cmd/build/vite/vite-builder.d.ts +0 -59
  260. package/dist/cmd/build/vite/vite-builder.d.ts.map +0 -1
  261. package/dist/cmd/build/vite/vite-builder.js +0 -401
  262. package/dist/cmd/build/vite/vite-builder.js.map +0 -1
  263. package/dist/cmd/build/vite/workbench-generator.d.ts +0 -10
  264. package/dist/cmd/build/vite/workbench-generator.d.ts.map +0 -1
  265. package/dist/cmd/build/vite/workbench-generator.js +0 -135
  266. package/dist/cmd/build/vite/workbench-generator.js.map +0 -1
  267. package/dist/cmd/build/vite/ws-proxy.d.ts +0 -53
  268. package/dist/cmd/build/vite/ws-proxy.d.ts.map +0 -1
  269. package/dist/cmd/build/vite/ws-proxy.js +0 -95
  270. package/dist/cmd/build/vite/ws-proxy.js.map +0 -1
  271. package/dist/cmd/build/vite-bundler.d.ts +0 -29
  272. package/dist/cmd/build/vite-bundler.d.ts.map +0 -1
  273. package/dist/cmd/build/vite-bundler.js +0 -93
  274. package/dist/cmd/build/vite-bundler.js.map +0 -1
  275. package/dist/cmd/dev/agents.d.ts +0 -2
  276. package/dist/cmd/dev/agents.d.ts.map +0 -1
  277. package/dist/cmd/dev/agents.js +0 -123
  278. package/dist/cmd/dev/agents.js.map +0 -1
  279. package/dist/cmd/dev/api.d.ts +0 -20
  280. package/dist/cmd/dev/api.d.ts.map +0 -1
  281. package/dist/cmd/dev/api.js +0 -42
  282. package/dist/cmd/dev/api.js.map +0 -1
  283. package/dist/cmd/dev/dev-lock.d.ts +0 -62
  284. package/dist/cmd/dev/dev-lock.d.ts.map +0 -1
  285. package/dist/cmd/dev/dev-lock.js +0 -250
  286. package/dist/cmd/dev/dev-lock.js.map +0 -1
  287. package/dist/cmd/dev/download.d.ts +0 -11
  288. package/dist/cmd/dev/download.d.ts.map +0 -1
  289. package/dist/cmd/dev/download.js +0 -94
  290. package/dist/cmd/dev/download.js.map +0 -1
  291. package/dist/cmd/dev/file-watcher.d.ts +0 -24
  292. package/dist/cmd/dev/file-watcher.d.ts.map +0 -1
  293. package/dist/cmd/dev/file-watcher.js +0 -349
  294. package/dist/cmd/dev/file-watcher.js.map +0 -1
  295. package/dist/cmd/dev/process-manager.d.ts +0 -104
  296. package/dist/cmd/dev/process-manager.d.ts.map +0 -1
  297. package/dist/cmd/dev/process-manager.js +0 -204
  298. package/dist/cmd/dev/process-manager.js.map +0 -1
  299. package/dist/cmd/dev/sync.d.ts +0 -12
  300. package/dist/cmd/dev/sync.d.ts.map +0 -1
  301. package/dist/cmd/dev/sync.js +0 -227
  302. package/dist/cmd/dev/sync.js.map +0 -1
  303. package/dist/cmd/dev/templates.d.ts +0 -3
  304. package/dist/cmd/dev/templates.d.ts.map +0 -1
  305. package/dist/cmd/dev/templates.js +0 -58
  306. package/dist/cmd/dev/templates.js.map +0 -1
  307. package/dist/cmd/project/download.d.ts +0 -35
  308. package/dist/cmd/project/download.d.ts.map +0 -1
  309. package/dist/cmd/project/download.js +0 -403
  310. package/dist/cmd/project/download.js.map +0 -1
  311. package/dist/cmd/project/templates.d.ts +0 -9
  312. package/dist/cmd/project/templates.d.ts.map +0 -1
  313. package/dist/cmd/project/templates.js +0 -34
  314. package/dist/cmd/project/templates.js.map +0 -1
  315. package/src/agents-docs.ts +0 -86
  316. package/src/cmd/ai/prompt/agent.md +0 -305
  317. package/src/cmd/ai/prompt/agent.ts +0 -31
  318. package/src/cmd/build/app-router-detector.ts +0 -320
  319. package/src/cmd/build/format-schema.ts +0 -66
  320. package/src/cmd/build/vite/agent-discovery.ts +0 -380
  321. package/src/cmd/build/vite/beacon-plugin.ts +0 -164
  322. package/src/cmd/build/vite/browser-env-plugin.ts +0 -34
  323. package/src/cmd/build/vite/bun-dev-server.ts +0 -458
  324. package/src/cmd/build/vite/bundle-files.ts +0 -135
  325. package/src/cmd/build/vite/config-loader.ts +0 -76
  326. package/src/cmd/build/vite/db-rewrite.ts +0 -189
  327. package/src/cmd/build/vite/docs-generator.ts +0 -103
  328. package/src/cmd/build/vite/env-types-generator.ts +0 -145
  329. package/src/cmd/build/vite/index.ts +0 -3
  330. package/src/cmd/build/vite/lifecycle-generator.ts +0 -381
  331. package/src/cmd/build/vite/metadata-generator.ts +0 -713
  332. package/src/cmd/build/vite/prompt-generator.ts +0 -169
  333. package/src/cmd/build/vite/public-asset-path-plugin.ts +0 -209
  334. package/src/cmd/build/vite/route-discovery.ts +0 -271
  335. package/src/cmd/build/vite/server-bundler.ts +0 -481
  336. package/src/cmd/build/vite/static-renderer.ts +0 -239
  337. package/src/cmd/build/vite/tailwind-source-plugin.ts +0 -73
  338. package/src/cmd/build/vite/vite-asset-server-config.ts +0 -349
  339. package/src/cmd/build/vite/vite-asset-server.ts +0 -154
  340. package/src/cmd/build/vite/vite-builder.ts +0 -503
  341. package/src/cmd/build/vite/workbench-generator.ts +0 -152
  342. package/src/cmd/build/vite/ws-proxy.ts +0 -126
  343. package/src/cmd/build/vite-bundler.ts +0 -137
  344. package/src/cmd/dev/agents.ts +0 -140
  345. package/src/cmd/dev/api.ts +0 -65
  346. package/src/cmd/dev/dev-lock.ts +0 -332
  347. package/src/cmd/dev/download.ts +0 -117
  348. package/src/cmd/dev/file-watcher.ts +0 -423
  349. package/src/cmd/dev/process-manager.ts +0 -261
  350. package/src/cmd/dev/sync.ts +0 -411
  351. package/src/cmd/dev/templates.ts +0 -66
  352. package/src/cmd/project/download.ts +0 -505
  353. package/src/cmd/project/templates.ts +0 -56
@@ -1,1116 +1,212 @@
1
+ /**
2
+ * Dev command — runs the project's own dev script.
3
+ *
4
+ * Detects the package manager (bun/npm/pnpm/yarn) from the project,
5
+ * then runs `<pm> run dev`. Before spawning, injects Agentuity AI
6
+ * Gateway environment variables so LLM SDK calls (OpenAI, Anthropic,
7
+ * Groq) are automatically routed through the gateway when the user
8
+ * has an AGENTUITY_SDK_KEY configured.
9
+ */
10
+
11
+ import { resolve } from 'node:path';
1
12
  import { z } from 'zod';
2
- import { resolve, join } from 'node:path';
3
- import { existsSync } from 'node:fs';
4
- import { getServiceUrls } from '@agentuity/server';
5
13
  import { createCommand } from '../../types';
6
- import { startBunDevServer } from '../build/vite/bun-dev-server';
7
- import { startViteAssetServer } from '../build/vite/vite-asset-server';
8
14
  import * as tui from '../../tui';
9
15
  import { getCommand } from '../../command-prefix';
10
- import { generateEndpoint, type DevmodeResponse } from './api';
11
- import { APIClient, getAPIBaseURL, getAppBaseURL, getGravityDevModeURL } from '../../api';
12
- import { download } from './download';
13
- import { createDevmodeSyncService } from './sync';
14
- import { getDevmodeDeploymentId } from '../build/ids';
15
- import { getDefaultConfigDir, saveConfig, loadProjectSDKKey, getAuth } from '../../config';
16
- import type { Config } from '../../types';
17
- import { typecheck } from '../build/typecheck';
18
- import { validateGravityRequiresUpgrade } from '../../runtime';
19
- import { isTTY, hasLoggedInBefore } from '../../auth';
20
-
21
- import { prepareDevLock, releaseLockSync } from './dev-lock';
22
- import { checkAndUpgradeDependencies } from '../../utils/dependency-checker';
23
- import { initProcessManager } from './process-manager';
24
- import { detectVersionMismatch, formatVersionMismatchWarning } from '../../utils/version-mismatch';
25
-
26
16
  import { ErrorCode } from '../../errors';
17
+ import { loadProjectSDKKey, getAuth, loadConfig } from '../../config';
18
+ import { detectFrameworkWithPackageJson } from '../build/detect';
19
+ import { detectPackageManager, getRunCommand } from '../build/detect/util';
27
20
 
28
- const DEFAULT_PORT = 3500;
29
- const MIN_PORT = 1024;
30
- const MAX_PORT = 65535;
31
-
32
- // Minimal interface for subprocess management
33
- interface ProcessLike {
34
- kill: (signal?: number | NodeJS.Signals) => void;
35
- exitCode: number | null;
36
- pid?: number;
37
- stdout?: AsyncIterable<Uint8Array>;
38
- stderr?: AsyncIterable<Uint8Array>;
39
- }
40
-
41
- interface ServerLike {
42
- close: () => void | Promise<void>;
43
- }
44
-
45
- /**
46
- * Kill any lingering gravity processes from previous dev sessions.
47
- * This is a defensive measure to clean up orphaned processes.
48
- */
49
- async function killLingeringGravityProcesses(logger: {
50
- debug: (msg: string, ...args: unknown[]) => void;
51
- }): Promise<void> {
52
- // Only attempt on Unix-like systems (macOS, Linux)
53
- if (process.platform === 'win32') {
54
- return;
55
- }
56
-
57
- try {
58
- // Use pkill to kill gravity processes owned by current user
59
- // The -f flag matches against full command line
60
- // We specifically match the gravity binary name to avoid killing unrelated processes
61
- const result = Bun.spawnSync(['pkill', '-f', 'gravity.*--endpoint-id'], {
62
- stdout: 'ignore',
63
- stderr: 'ignore',
64
- });
65
-
66
- // Exit code 0 = processes killed, 1 = no matching processes, other = error
67
- if (result.exitCode === 0) {
68
- logger.debug('Killed lingering gravity processes from previous session');
69
- // Brief pause to let processes fully terminate
70
- await new Promise((resolve) => setTimeout(resolve, 100));
71
- } else if (result.exitCode === 1) {
72
- logger.debug('no lingering gravity processes found');
73
- }
74
- } catch {
75
- // pkill not available or failed - not critical, continue
76
- }
77
- }
78
-
79
- /**
80
- * Kill the Bun backend subprocess if one is running.
81
- */
82
- function killBunSubprocess(logger: { debug: (msg: string, ...args: unknown[]) => void }): void {
83
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
- const globalAny = globalThis as any;
85
- const bunSubprocess = globalAny.__AGENTUITY_BUN_SUBPROCESS__ as ProcessLike | undefined;
86
- if (!bunSubprocess) return;
87
-
88
- try {
89
- bunSubprocess.kill('SIGTERM');
90
- logger.debug('Bun subprocess killed');
91
- } catch (err) {
92
- logger.debug('Error killing Bun subprocess: %s', err);
93
- }
94
- globalAny.__AGENTUITY_BUN_SUBPROCESS__ = undefined;
95
- }
96
-
97
- const getDefaultPort = (): number => {
98
- const envPort = process.env.PORT;
99
- if (!envPort) {
100
- return DEFAULT_PORT;
101
- }
102
- const trimmed = envPort.trim();
103
- if (!trimmed || !/^\d+$/.test(trimmed)) {
104
- return DEFAULT_PORT;
105
- }
106
- const parsed = Number(trimmed);
107
- if (!Number.isInteger(parsed) || parsed < MIN_PORT || parsed > MAX_PORT) {
108
- return DEFAULT_PORT;
109
- }
110
- return parsed;
111
- };
112
-
113
- const shouldDisableInteractive = (interactive?: boolean) => {
114
- if (!interactive) {
115
- return true;
116
- }
117
- return process.env.TERM_PROGRAM === 'vscode';
118
- };
21
+ const DEFAULT_PORT = 3000;
119
22
 
120
23
  export const command = createCommand({
121
24
  name: 'dev',
122
- description: 'Build and run the development server',
123
- tags: ['mutating', 'slow', 'requires-project'],
25
+ description: 'Run the project development server',
26
+ tags: ['mutating', 'slow'],
124
27
  idempotent: true,
28
+ optional: { project: true },
125
29
  examples: [
126
30
  { command: getCommand('dev'), description: 'Start development server' },
127
31
  { command: getCommand('dev --port 8080'), description: 'Specify custom port' },
128
- { command: getCommand('dev --local'), description: 'Run in local mode' },
129
- { command: getCommand('dev --no-public'), description: 'Disable public URL' },
130
32
  ],
131
33
  schema: {
132
34
  options: z.object({
133
- local: z.boolean().optional().describe('Turn on local services (instead of cloud)'),
134
- interactive: z.boolean().default(true).optional().describe('Turn on interactive mode'),
135
- public: z
136
- .boolean()
137
- .optional()
138
- .default(!process.env.CI)
139
- .describe('Turn on or off the public url'),
140
35
  port: z
141
36
  .number()
142
- .min(MIN_PORT)
143
- .max(MAX_PORT)
144
- .default(getDefaultPort())
145
- .describe('The TCP port to start the dev server (also reads from PORT env)'),
146
- inspect: z.boolean().optional().describe('Enable bun debugger on available port'),
147
- inspectWait: z
148
- .boolean()
37
+ .min(1024)
38
+ .max(65535)
149
39
  .optional()
150
- .describe('Enable bun debugger and wait for connection before executing'),
151
- inspectBrk: z
152
- .boolean()
40
+ .describe('Port to pass to the dev server via PORT env var'),
41
+ script: z
42
+ .string()
153
43
  .optional()
154
- .describe('Enable bun debugger with breakpoint at first line'),
155
-
156
- noTypecheck: z
157
- .boolean()
158
- .optional()
159
- .describe('Skip TypeScript type checking on startup and restarts'),
160
-
161
- resume: z.string().optional().describe('Resume a paused Hub session by ID'),
44
+ .describe('Custom script name to run instead of "dev" (e.g., "dev:web")'),
162
45
  }),
163
46
  },
164
- optional: { project: true },
165
47
 
166
48
  async handler(ctx) {
167
- const { opts, logger, projectDir } = ctx;
168
- let { config, project } = ctx;
169
-
170
- // Get auth state - we handle auth ourselves based on project state
171
- let auth = await getAuth();
172
-
49
+ const { opts, projectDir, logger } = ctx;
173
50
  const rootDir = resolve(projectDir);
174
- const appTs = join(rootDir, 'app.ts');
175
- const srcDir = join(rootDir, 'src');
176
51
 
177
- // Verify required files exist
178
- const mustHaves = [join(rootDir, 'package.json'), appTs, srcDir];
179
- const missing: string[] = [];
52
+ // Read package.json
53
+ const { packageJson } = await detectFrameworkWithPackageJson(rootDir);
180
54
 
181
- const interactive = !shouldDisableInteractive(opts.interactive);
182
-
183
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
184
- let originalExit = (globalThis as any).AGENTUITY_PROCESS_EXIT;
185
-
186
- if (!originalExit) {
187
- originalExit = process.exit.bind(process);
55
+ if (!packageJson) {
56
+ tui.fatal(
57
+ 'No package.json found. Ensure you are in a JS/TS project directory.',
58
+ ErrorCode.CONFIG_INVALID
59
+ );
188
60
  }
189
61
 
190
- for (const filename of mustHaves) {
191
- if (!existsSync(filename)) {
192
- missing.push(filename);
193
- }
194
- }
62
+ // Determine which script to run
63
+ const scriptName = opts.script ?? 'dev';
195
64
 
196
- if (missing.length) {
197
- tui.error(`${rootDir} does not appear to be a valid Agentuity project`);
198
- for (const filename of missing) {
199
- tui.bullet(`Missing ${filename}`);
200
- }
201
- originalExit(1);
65
+ if (!packageJson.scripts?.[scriptName]) {
66
+ const available = packageJson.scripts
67
+ ? Object.keys(packageJson.scripts).join(', ')
68
+ : 'none';
69
+ tui.fatal(
70
+ `No "${scriptName}" script found in package.json. Available scripts: ${available}`,
71
+ ErrorCode.CONFIG_INVALID
72
+ );
202
73
  }
203
74
 
204
- // Handle authentication state based on project registration
205
- if (project) {
206
- // Registered project (has agentuity.json) - check if user needs to login
207
- const isValidAuth = auth && auth.expires > new Date();
208
- if (!isValidAuth) {
209
- if (isTTY()) {
210
- const hasProfile = await hasLoggedInBefore();
211
- const message = hasProfile
212
- ? 'Your session has expired or you are not logged in.'
213
- : 'This project is registered with Agentuity Cloud but you are not logged in.';
75
+ // Detect package manager
76
+ const pm = await detectPackageManager(rootDir);
77
+ const runCmd = getRunCommand(pm);
214
78
 
215
- tui.warning(message);
216
- tui.newline();
217
-
218
- const shouldLogin = await tui.confirm(
219
- hasProfile
220
- ? 'Would you like to login now?'
221
- : 'Would you like to login or create an account?',
222
- true
223
- );
224
-
225
- if (shouldLogin) {
226
- tui.newline();
227
-
228
- // Run login flow inline
229
- const { loginCommand } = await import('../auth/login');
230
-
231
- // Ensure apiClient is available for login handler
232
- const loginCtx = ctx as unknown as Record<string, unknown>;
233
- if (!loginCtx.apiClient) {
234
- loginCtx.apiClient = new APIClient(getAPIBaseURL(config), logger, config);
235
- }
79
+ // Build the command
80
+ const cmd = runCmd.split(' ');
81
+ cmd.push(scriptName);
236
82
 
237
- if (loginCommand.handler) {
238
- await loginCommand.handler(
239
- loginCtx as Parameters<NonNullable<typeof loginCommand.handler>>[0]
240
- );
241
- }
83
+ // Build environment
84
+ const env: Record<string, string> = { ...process.env } as Record<string, string>;
85
+ const port = opts.port ?? DEFAULT_PORT;
86
+ env.PORT = String(port);
242
87
 
243
- // Refresh auth state after login
244
- const freshAuth = await getAuth();
245
- if (!freshAuth || freshAuth.expires <= new Date()) {
246
- tui.fatal('Login was not completed successfully.', ErrorCode.AUTH_FAILED);
247
- }
248
- auth = freshAuth;
249
- tui.newline();
250
- tui.success('Login successful! Continuing with dev server...');
251
- tui.newline();
252
- } else {
253
- // User chose not to login - show warning about disabled features
254
- tui.newline();
255
- tui.showLoggedOutMessage(getAppBaseURL(config), hasProfile);
256
- }
257
- } else {
258
- // Non-TTY: fatal error with instruction
259
- logger.fatal(
260
- `Authentication required for this project.\n` +
261
- `Run "${getCommand('auth login')}" to login to Agentuity`,
262
- ErrorCode.AUTH_REQUIRED
88
+ // Resolve SDK key: env → .env files → auth profile
89
+ if (!env.AGENTUITY_SDK_KEY) {
90
+ const sdkKey = await loadProjectSDKKey(logger, rootDir);
91
+ if (sdkKey) {
92
+ env.AGENTUITY_SDK_KEY = sdkKey;
93
+ } else {
94
+ // No project-level SDK key — fall back to CLI auth key
95
+ const auth = await getAuth();
96
+ if (auth?.apiKey) {
97
+ env.AGENTUITY_SDK_KEY = auth.apiKey;
98
+ tui.warning(
99
+ 'No linked Agentuity project found. Using your auth key for AI Gateway.'
100
+ );
101
+ tui.arrow(
102
+ `Link this project: ${tui.colorInfo(tui.bold('agentuity project import'))}`
263
103
  );
264
- }
265
- }
266
-
267
- // After auth is established, verify project access
268
- if (auth && config) {
269
- const { reconcileProject } = await import('../project/reconcile');
270
- const apiClient = new APIClient(getAPIBaseURL(config), logger, auth.apiKey, config);
271
-
272
- const result = await reconcileProject({
273
- dir: rootDir,
274
- auth,
275
- apiClient,
276
- config,
277
- logger,
278
- interactive: isTTY(),
279
- });
280
-
281
- if (result.status === 'error') {
282
- tui.fatal(result.message!, ErrorCode.PROJECT_NOT_FOUND);
283
- } else if (result.status === 'imported' && result.project) {
284
- // Project was re-imported to user's org
285
- project = result.project;
286
- tui.newline();
287
- } else if (result.status === 'skipped') {
288
- // User declined import - can't continue with cloud features
289
- tui.warning('Continuing in local-only mode.');
290
- project = undefined;
291
- }
292
- }
293
- } else {
294
- // No agentuity.json - check if this is a valid project that needs importing
295
- if (auth && config) {
296
- const { reconcileProject } = await import('../project/reconcile');
297
- const apiClient = new APIClient(getAPIBaseURL(config), logger, auth.apiKey, config);
298
-
299
- const result = await reconcileProject({
300
- dir: rootDir,
301
- auth,
302
- apiClient,
303
- config,
304
- logger,
305
- interactive: isTTY(),
306
- });
307
-
308
- if (result.status === 'error') {
309
- // Not a valid project - show local-only warning
310
- tui.showLocalOnlyWarning();
311
- } else if (result.status === 'imported' && result.project) {
312
- // Project was imported - reload project config
313
- project = result.project;
314
104
  tui.newline();
315
- } else if (result.status === 'skipped') {
316
- // User declined import - continue in local-only mode
317
- tui.showLocalOnlyWarning();
318
105
  }
319
- } else {
320
- // Not authenticated - local-only mode
321
- tui.showLocalOnlyWarning();
322
106
  }
323
107
  }
324
108
 
325
- // Prepare dev lock: cleans up stale processes from previous sessions
326
- // and creates a new lockfile for this session
327
- const devLock = await prepareDevLock(rootDir, opts.port, logger);
328
-
329
- // Kill any lingering gravity processes from previous dev sessions
330
- // This is a fallback for cases where the lockfile was corrupted
331
- await killLingeringGravityProcesses(logger);
332
-
333
- // Check and upgrade @agentuity/* dependencies if needed
334
- const upgradeResult = await checkAndUpgradeDependencies(rootDir, logger);
335
- if (upgradeResult.failed.length > 0) {
336
- devLock.release();
337
- tui.fatal(
338
- `Failed to upgrade dependencies: ${upgradeResult.failed.join(', ')}`,
339
- ErrorCode.BUILD_FAILED
340
- );
109
+ // Load profile config to get transport URL for gateway routing
110
+ const config = await loadConfig();
111
+ if (config?.overrides?.transport_url && !env.AGENTUITY_TRANSPORT_URL) {
112
+ env.AGENTUITY_TRANSPORT_URL = config.overrides.transport_url;
341
113
  }
342
-
343
- // Check for version mismatches (v1 vs v2 SDK packages)
344
- const versionMismatch = detectVersionMismatch(rootDir, logger);
345
- if (versionMismatch.hasV1Packages || versionMismatch.hasMajorMismatches) {
346
- tui.newline();
347
- tui.warning(formatVersionMismatchWarning(versionMismatch));
348
- tui.newline();
114
+ if (config?.overrides?.catalyst_url && !env.AGENTUITY_CATALYST_URL) {
115
+ env.AGENTUITY_CATALYST_URL = config.overrides.catalyst_url;
349
116
  }
350
117
 
351
- try {
352
- // Setup devmode and gravity (if using public URL)
353
- const useMockService = process.env.DEVMODE_SYNC_SERVICE_MOCK === 'true';
354
- // Create apiClient with fresh auth API key (important after inline login)
355
- const apiClient = auth
356
- ? new APIClient(getAPIBaseURL(config), logger, auth.apiKey, config)
357
- : null;
358
- const syncService = apiClient
359
- ? createDevmodeSyncService({
360
- logger,
361
- apiClient,
362
- mock: useMockService,
363
- })
364
- : null;
365
-
366
- // Track previous metadata for sync diffing
367
- let previousMetadata:
368
- | Awaited<
369
- ReturnType<typeof import('../build/vite/metadata-generator').generateMetadata>
370
- >
371
- | undefined;
372
-
373
- let devmode: DevmodeResponse | undefined;
374
- let gravityBin: string | undefined;
375
- let gravityURL: string | undefined;
376
- let appURL: string | undefined;
377
- let savedPrivateKey: string | undefined = config?.devmode?.privateKey
378
- ? Buffer.from(config.devmode.privateKey, 'base64').toString('utf-8')
379
- : undefined;
380
-
381
- if (auth && project && opts.public) {
382
- // Generate devmode endpoint for public URL
383
- const endpoint = await tui.spinner({
384
- message: 'Connecting to Gravity',
385
- callback: () => {
386
- return generateEndpoint(
387
- apiClient!,
388
- project.projectId,
389
- config?.devmode?.hostname,
390
- savedPrivateKey
391
- );
392
- },
393
- clearOnSuccess: true,
394
- });
395
-
396
- if (endpoint.privateKey) {
397
- savedPrivateKey = endpoint.privateKey;
398
- }
399
- const _config = { ...config } as Config;
400
- _config.devmode = {
401
- hostname: endpoint.hostname,
402
- privateKey: savedPrivateKey
403
- ? Buffer.from(savedPrivateKey).toString('base64')
404
- : undefined,
405
- };
406
- await saveConfig(_config);
407
- config = _config;
408
- devmode = endpoint;
409
- gravityURL = getGravityDevModeURL(project.region, config);
410
- appURL = `${getAppBaseURL(config)}/r/${project.projectId}`;
411
-
412
- // Download gravity client
413
- const configDir = getDefaultConfigDir();
414
- const gravityDir = join(configDir, 'gravity');
415
- let mustCheck = true;
416
-
417
- if (
418
- config?.gravity?.version &&
419
- existsSync(join(gravityDir, config.gravity.version, 'gravity')) &&
420
- config?.gravity?.checked &&
421
- !validateGravityRequiresUpgrade(config.gravity.version)
422
- ) {
423
- if (Date.now() - config.gravity.checked < 3.6e6) {
424
- mustCheck = false;
425
- gravityBin = join(gravityDir, config.gravity.version, 'gravity');
426
- }
427
- }
428
-
429
- if (mustCheck) {
430
- const res = await download(gravityDir);
431
- gravityBin = res.filename;
432
- const _config = { ...config } as Config;
433
- _config.gravity = {
434
- checked: Date.now(),
435
- version: res.version,
436
- };
437
- await saveConfig(_config);
438
- config = _config;
439
- }
440
- }
441
-
442
- // Get workbench info from createApp() in app.ts (v2 approach)
443
- const { getWorkbenchConfig, loadRuntimeConfig } = await import(
444
- '../build/vite/config-loader'
118
+ // Inject AI Gateway env vars so LLM SDKs route through Agentuity
119
+ const gatewayInjected = injectGatewayEnv(env, logger);
120
+ if (gatewayInjected) {
121
+ tui.info('AI Gateway: routing LLM requests through Agentuity');
122
+ } else if (!env.OPENAI_API_KEY && !env.ANTHROPIC_API_KEY) {
123
+ tui.warning(
124
+ 'No AI API keys found. Run ' +
125
+ tui.bold('agentuity auth login') +
126
+ ' to enable AI Gateway routing.'
445
127
  );
446
- const runtimeConfig = await loadRuntimeConfig(rootDir, logger);
447
- const workbenchConfigData = getWorkbenchConfig(true, runtimeConfig); // dev mode
448
- const workbench = {
449
- hasWorkbench: workbenchConfigData.enabled,
450
- config: workbenchConfigData.enabled
451
- ? { route: workbenchConfigData.route, headers: workbenchConfigData.headers }
452
- : null,
453
- };
454
-
455
- const deploymentId = getDevmodeDeploymentId(project?.projectId ?? '', devmode?.id ?? '');
456
-
457
- // Calculate URLs for banner
458
- const padding = 12;
459
- const workbenchUrl =
460
- auth && project?.projectId
461
- ? `${getAppBaseURL(config)}/w/${project.projectId}`
462
- : `http://127.0.0.1:${opts.port}${workbench.config?.route ?? '/workbench'}`;
463
-
464
- const devmodebody =
465
- tui.muted(tui.padRight('Local:', padding)) +
466
- tui.link(`http://127.0.0.1:${opts.port}`) +
467
- '\n' +
468
- tui.muted(tui.padRight('Public:', padding)) +
469
- (devmode?.hostname ? tui.link(`https://${devmode.hostname}`) : tui.warn('Disabled')) +
470
- '\n' +
471
- tui.muted(tui.padRight('Workbench:', padding)) +
472
- (workbench.hasWorkbench ? tui.link(workbenchUrl) : tui.warn('Disabled')) +
473
- '\n' +
474
- tui.muted(tui.padRight('Dashboard:', padding)) +
475
- (appURL ? tui.link(appURL) : tui.warn('Disabled')) +
476
- '\n' +
477
- (interactive
478
- ? '\n' + tui.muted('Press ') + tui.bold('h') + tui.muted(' for keyboard shortcuts')
479
- : '');
480
-
481
- tui.banner('⨺ Agentuity DevMode', devmodebody, {
482
- padding: 2,
483
- topSpacer: false,
484
- bottomSpacer: false,
485
- centerTitle: false,
486
- });
487
-
488
- // Detect user route mount paths for Vite proxy configuration
489
- // This is a quick AST scan of app.ts — runs before Vite starts
490
- let routePaths: string[] = ['/api']; // Default fallback
491
- try {
492
- const { detectExplicitRouter } = await import('../build/app-router-detector');
493
- const detection = await detectExplicitRouter(rootDir, logger);
494
- if (detection.detected && detection.mounts.length > 0) {
495
- routePaths = detection.mounts.map((m) => m.path);
496
- logger.debug('Detected route mount paths: %s', routePaths.join(', '));
497
- }
498
- } catch (err) {
499
- logger.debug('Route detection failed, using default /api: %s', err);
500
- }
501
-
502
- // Pick internal ports (neither is user-facing — the front-door proxy is)
503
- const bunBackendPort = opts.port + 1;
504
- const viteInternalPort = opts.port + 2;
505
-
506
- // No-bundle dev mode guard: ensure stale bundled app artifact cannot be executed.
507
- // We keep other .agentuity artifacts (metadata/workbench files) intact.
508
- try {
509
- const staleBundlePath = join(rootDir, '.agentuity', 'app.js');
510
- if (existsSync(staleBundlePath)) {
511
- await Bun.file(staleBundlePath).delete();
512
- logger.debug('Removed stale dev bundle artifact: %s', staleBundlePath);
513
- }
514
- } catch (err) {
515
- logger.debug('Failed to remove stale dev bundle artifact: %s', err);
516
- }
517
-
518
- // Debug trace: locate unexpected legacy credential warnings.
519
- // Enable with AGENTUITY_TRACE_CREDENTIAL_WARNINGS=true.
520
- if (process.env.AGENTUITY_TRACE_CREDENTIAL_WARNINGS === 'true') {
521
- const originalConsoleError = console.error.bind(console);
522
- console.error = (...args: unknown[]) => {
523
- try {
524
- const first = typeof args[0] === 'string' ? args[0] : '';
525
- if (first.includes('No credentials found for this AI provider')) {
526
- const stack = new Error('Credential warning trace').stack;
527
- originalConsoleError('[TRACE] Credential warning origin stack:');
528
- if (stack) originalConsoleError(stack);
529
- }
530
- } catch {
531
- // ignore tracing errors
532
- }
533
- originalConsoleError(...args);
534
- };
535
- }
536
-
537
- // Start Vite dev server on an internal port.
538
- // The user-facing port is handled by the front-door TCP proxy (ws-proxy)
539
- // which routes WS upgrades to Bun and everything else to Vite.
540
- let viteServer: ServerLike | null = null;
541
- let vitePort: number;
542
-
543
- // Initialize process manager to track all servers/processes
544
- const procManager = initProcessManager(logger);
545
-
546
- try {
547
- logger.debug('Starting Vite dev server (internal port %d)...', viteInternalPort);
548
- const viteResult = await startViteAssetServer({
549
- rootDir,
550
- logger,
551
- workbenchPath: workbench.config?.route,
552
- port: viteInternalPort,
553
- backendPort: bunBackendPort,
554
- routePaths,
555
- liveHostname: devmode?.hostname,
556
- });
557
- viteServer = viteResult.server;
558
- vitePort = viteResult.port;
559
-
560
- // Register Vite server with process manager
561
- procManager.registerServer({
562
- id: 'vite',
563
- server: viteServer,
564
- description: 'Vite dev server (frontend assets)',
565
- port: vitePort,
566
- });
567
-
568
- // Update dev lock with actual Vite port
569
- await devLock.updatePorts({ vite: vitePort });
570
-
571
- logger.debug(
572
- `Vite dev server running on port ${vitePort} (internal, proxying backend on port ${bunBackendPort})`
573
- );
574
- } catch (error) {
575
- tui.error(`Failed to start Vite dev server: ${error}`);
576
- await procManager.cleanup('vite startup failure');
577
- await devLock.release();
578
- originalExit(1);
579
- return;
580
- }
581
-
582
- // Start the front-door TCP proxy on the user-facing port.
583
- // Routes WebSocket upgrades (for /api/*, /_agentuity/*) directly to Bun
584
- // and everything else (HTTP, HMR WebSocket) to Vite.
585
- // This works around Bun's broken node:http upgrade socket implementation.
586
- let frontDoorServer: import('node:net').Server | null = null;
587
- try {
588
- const { startWsProxy } = await import('../build/vite/ws-proxy');
589
- frontDoorServer = await startWsProxy({
590
- port: opts.port,
591
- vitePort,
592
- backendPort: bunBackendPort,
593
- routePaths,
594
- logger,
595
- });
596
-
597
- // Register front-door proxy with process manager
598
- procManager.registerServer({
599
- id: 'front-door-proxy',
600
- server: {
601
- close: () => {
602
- frontDoorServer?.close();
603
- },
604
- },
605
- description: 'Front-door TCP proxy (WS routing)',
606
- port: opts.port,
607
- });
608
-
609
- logger.debug(
610
- `Front-door proxy on port ${opts.port} (Vite:${vitePort}, Bun:${bunBackendPort})`
611
- );
612
- } catch (error) {
613
- tui.error(`Failed to start front-door proxy: ${error}`);
614
- await procManager.cleanup('front-door proxy startup failure');
615
- await devLock.release();
616
- originalExit(1);
617
- return;
618
- }
619
-
620
- // --- State for long-running processes ---
621
- let gravityProcess: ProcessLike | null = null;
622
- let gravityHeartbeatInterval: ReturnType<typeof setInterval> | null = null;
623
- let stdinListenerRegistered = false;
624
- let stdinDataHandler: ((data: Buffer | string) => void) | null = null;
625
- let shutdownRequested = false;
626
-
627
- /**
628
- * Centralized cleanup function for all resources.
629
- * Uses the process manager for tracked servers/processes.
630
- */
631
- const cleanup = async (exitAfter = false, exitCode = 0, silent = false) => {
632
- if (shutdownRequested) return;
633
- shutdownRequested = true;
634
-
635
- if (!silent) {
636
- tui.info('Shutting down...');
637
- }
638
-
639
- // Stop gravity heartbeat interval first
640
- if (gravityHeartbeatInterval) {
641
- clearInterval(gravityHeartbeatInterval);
642
- gravityHeartbeatInterval = null;
643
- }
644
-
645
- // Use process manager for tracked cleanup
646
- await procManager.cleanup('shutdown');
647
-
648
- // Additional cleanup for non-tracked resources
649
- await devLock.release();
650
- await killLingeringGravityProcesses(logger);
651
-
652
- if (exitAfter) {
653
- if (stdinListenerRegistered && process.stdin.isTTY) {
654
- try {
655
- if (stdinDataHandler) {
656
- process.stdin.removeListener('data', stdinDataHandler);
657
- stdinDataHandler = null;
658
- }
659
- process.stdin.setRawMode(false);
660
- process.stdin.pause();
661
- process.stdin.unref();
662
- } catch {
663
- // Ignore
664
- }
665
- }
666
- originalExit(exitCode);
667
- }
668
- };
669
-
670
- // Signal handlers
671
- let exitingFromSignal = false;
672
- const safeExit = (code: number, reason?: string) => {
673
- if (exitingFromSignal) return;
674
- exitingFromSignal = true;
675
- if (reason) logger.debug('DevMode terminating (%d): %s', code, reason);
676
- shutdownRequested = true;
677
- cleanup(true, code).catch(() => originalExit(1));
678
- };
679
-
680
- process.on('SIGINT', () => safeExit(0, 'SIGINT'));
681
- process.on('SIGTERM', () => safeExit(0, 'SIGTERM'));
682
- process.on('SIGHUP', () => safeExit(0, 'SIGHUP'));
683
- process.on('uncaughtException', (err) => {
684
- tui.error(
685
- `Uncaught exception: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}`
686
- );
687
- void safeExit(1, 'uncaughtException');
688
- });
689
- process.on('unhandledRejection', (reason) => {
690
- logger.warn(
691
- 'Unhandled promise rejection: %s',
692
- reason instanceof Error ? (reason.stack ?? reason.message) : String(reason)
693
- );
694
- });
695
- process.on('exit', () => {
696
- if (gravityProcess?.exitCode === null) {
697
- try {
698
- gravityProcess.kill('SIGKILL');
699
- } catch {
700
- // Ignore
701
- }
702
- }
703
- if (viteServer) {
704
- try {
705
- viteServer.close();
706
- } catch {
707
- // Ignore
708
- }
709
- }
710
- killBunSubprocess(logger);
711
- releaseLockSync(rootDir);
712
- });
713
-
714
- // ================================================================
715
- // Step 0b: Early environment setup
716
- // ================================================================
717
- // Load SDK key and set gateway env vars BEFORE agent discovery.
718
- // Agent discovery imports eval files, which may import LLM SDKs at
719
- // module scope. Those SDKs check for API keys (e.g. GROQ_API_KEY)
720
- // at import time, so the gateway env patching must happen first.
721
-
722
- if (!process.env.AGENTUITY_SDK_KEY) {
723
- const sdkKey = await loadProjectSDKKey(logger, rootDir);
724
- if (sdkKey) {
725
- process.env.AGENTUITY_SDK_KEY = sdkKey;
726
- } else if (project) {
727
- tui.warning(
728
- 'AGENTUITY_SDK_KEY not found in .env file. Numerous features will be unavailable.'
729
- );
730
- tui.bullet(
731
- `Run "${getCommand('cloud env pull')}" to sync your SDK key, or add AGENTUITY_SDK_KEY to your .env file.`
732
- );
733
- }
734
- }
735
-
736
- process.env.NODE_ENV = 'development';
737
- process.env.AGENTUITY_ENV = 'development';
738
-
739
- if (project) {
740
- const earlyServiceUrls = getServiceUrls(project.region);
741
- if (!process.env.AGENTUITY_TRANSPORT_URL) {
742
- process.env.AGENTUITY_TRANSPORT_URL = earlyServiceUrls.catalyst;
743
- }
744
- }
745
-
746
- // Apply gateway env patching so LLM SDK API keys are set before
747
- // agent discovery imports eval files that may reference them.
748
- {
749
- const sdkKey = process.env.AGENTUITY_SDK_KEY;
750
- const gatewayUrl =
751
- process.env.AGENTUITY_AIGATEWAY_URL ||
752
- process.env.AGENTUITY_TRANSPORT_URL ||
753
- (sdkKey ? 'https://catalyst.agentuity.cloud' : '');
754
-
755
- const gatewayConfigs = [
756
- {
757
- apiKeyEnv: 'ANTHROPIC_API_KEY',
758
- baseUrlEnv: 'ANTHROPIC_BASE_URL',
759
- provider: 'anthropic',
760
- },
761
- { apiKeyEnv: 'GROQ_API_KEY', baseUrlEnv: 'GROQ_BASE_URL', provider: 'groq' },
762
- { apiKeyEnv: 'OPENAI_API_KEY', baseUrlEnv: 'OPENAI_BASE_URL', provider: 'openai' },
763
- ];
764
-
765
- for (const cfg of gatewayConfigs) {
766
- const currentKey = process.env[cfg.apiKeyEnv];
767
- if (currentKey && currentKey !== sdkKey) continue;
768
- if (gatewayUrl && sdkKey) {
769
- process.env[cfg.apiKeyEnv] = sdkKey;
770
- process.env[cfg.baseUrlEnv] = `${gatewayUrl}/gateway/${cfg.provider}`;
771
- logger.debug('Enabled Agentuity AI Gateway for %s', cfg.provider);
772
- }
773
- }
774
- }
775
-
776
- // ================================================================
777
- // Step 1: Prepare dev server (once)
778
- // ================================================================
779
-
780
- await tui.spinner({
781
- message: 'Preparing dev server',
782
- callback: async () => {
783
- // Typecheck (skip with --no-typecheck)
784
- if (!opts.noTypecheck) {
785
- const typeResult = await typecheck(rootDir);
786
- if (!typeResult.success) {
787
- // Non-fatal in dev: log errors and continue
788
- console.log('');
789
- console.log(typeResult.output);
790
- console.log('');
791
- }
792
- }
793
-
794
- // Generate workbench files if enabled
795
- if (workbenchConfigData.enabled) {
796
- const { generateWorkbenchFiles } = await import(
797
- '../build/vite/workbench-generator'
798
- );
799
- await generateWorkbenchFiles(
800
- rootDir,
801
- project?.projectId ?? '',
802
- workbenchConfigData,
803
- logger
804
- );
805
- }
806
-
807
- // Discover agents and routes in parallel
808
- const srcDir = join(rootDir, 'src');
809
- const { discoverAgents } = await import('../build/vite/agent-discovery');
810
- const { discoverRoutes } = await import('../build/vite/route-discovery');
811
-
812
- const [agentMetadata, { routes }] = await Promise.all([
813
- discoverAgents(srcDir, project?.projectId ?? '', deploymentId, logger),
814
- discoverRoutes(srcDir, project?.projectId ?? '', deploymentId, logger),
815
- ]);
816
-
817
- // Generate metadata file
818
- const { generateMetadata, writeMetadataFile } = await import(
819
- '../build/vite/metadata-generator'
820
- );
821
-
822
- const promises: Promise<void>[] = [];
823
-
824
- // Generate prompt files (non-blocking)
825
- promises.push(
826
- import('../build/vite/prompt-generator')
827
- .then(({ generatePromptFiles }) => generatePromptFiles(srcDir, logger))
828
- .catch((err) =>
829
- logger.warn('Failed to generate prompt files: %s', err.message)
830
- )
831
- );
832
-
833
- const metadata = await generateMetadata({
834
- rootDir,
835
- projectId: project?.projectId ?? '',
836
- orgId: project?.orgId ?? '',
837
- deploymentId,
838
- agents: agentMetadata,
839
- routes,
840
- dev: true,
841
- logger,
842
- });
843
-
844
- writeMetadataFile(rootDir, metadata, true, logger);
845
-
846
- // Sync metadata with backend
847
- if (syncService && project?.projectId) {
848
- promises.push(
849
- syncService.sync(metadata, previousMetadata, project.projectId, deploymentId)
850
- );
851
- previousMetadata = metadata;
852
- }
853
- await Promise.all(promises);
854
- },
855
- clearOnSuccess: true,
856
- });
857
-
858
- // ================================================================
859
- // Step 2: Set remaining environment variables
860
- // ================================================================
861
- // Note: AGENTUITY_SDK_KEY, NODE_ENV, AGENTUITY_ENV, and
862
- // AGENTUITY_TRANSPORT_URL are already set in Step 0b (before
863
- // agent discovery) to support gateway env patching.
864
-
865
- process.env.AGENTUITY_SDK_DEV_MODE = 'true';
866
- process.env.AGENTUITY_RUNTIME = 'yes';
867
- process.env.AGENTUITY_PROJECT_DIR = rootDir;
868
- if (project?.region) {
869
- process.env.AGENTUITY_REGION = project.region;
870
- }
871
- process.env.PORT = String(bunBackendPort);
872
- process.env.AGENTUITY_PORT = String(bunBackendPort);
873
- process.env.AGENTUITY_BASE_URL =
874
- process.env.AGENTUITY_BASE_URL || `http://localhost:${vitePort}`;
875
- process.env.AGENTUITY_NO_BUNDLE = 'true';
876
-
877
- if (opts.resume) {
878
- process.env.AGENTUITY_CODER_RESUME_SESSION = opts.resume;
879
- }
880
-
881
- if (project) {
882
- const serviceUrls = getServiceUrls(project.region);
883
- process.env.AGENTUITY_TRANSPORT_URL = serviceUrls.catalyst;
884
- process.env.AGENTUITY_CATALYST_URL = serviceUrls.catalyst;
885
- process.env.AGENTUITY_VECTOR_URL = serviceUrls.vector;
886
- process.env.AGENTUITY_KEYVALUE_URL = serviceUrls.keyvalue;
887
- process.env.AGENTUITY_SANDBOX_URL = serviceUrls.sandbox;
888
- process.env.AGENTUITY_STREAM_URL = serviceUrls.stream;
889
- process.env.AGENTUITY_CLOUD_ORG_ID = project.orgId;
890
- process.env.AGENTUITY_CLOUD_PROJECT_ID = project.projectId;
891
- process.env.AGENTUITY_CLOUD_DEPLOYMENT_ID = deploymentId;
892
- }
893
-
894
- if (devmode?.hostname) {
895
- process.env.AGENTUITY_DEVMODE_URL = `https://${devmode.hostname}`;
896
- } else {
897
- process.env.AGENTUITY_DEVMODE_URL = `http://localhost:${vitePort}`;
898
- }
899
-
900
- // ================================================================
901
- // Step 3: Start Bun backend with --hot (handles its own HMR)
902
- // ================================================================
903
-
904
- try {
905
- await startBunDevServer({
906
- rootDir,
907
- port: bunBackendPort,
908
- logger,
909
- vitePort,
910
- inspect: opts.inspect,
911
- inspectWait: opts.inspectWait,
912
- inspectBrk: opts.inspectBrk,
913
- });
914
-
915
- // Register Bun subprocess with process manager
916
- // The subprocess is stored in globalThis.__AGENTUITY_BUN_SUBPROCESS__
917
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
918
- const bunSubprocess = (globalThis as any).__AGENTUITY_BUN_SUBPROCESS__ as ProcessLike;
919
- if (bunSubprocess) {
920
- procManager.registerProcess({
921
- id: 'bun-backend',
922
- process: bunSubprocess,
923
- description: 'Bun backend server (--hot)',
924
- port: bunBackendPort,
925
- critical: true,
926
- });
927
- }
928
- } catch (error) {
929
- tui.error(`Failed to start Bun backend server: ${error}`);
930
- await cleanup(true, 1, true);
931
- return;
932
- }
933
-
934
- // ================================================================
935
- // Step 4: Start gravity tunnel (if public URL enabled)
936
- // ================================================================
937
-
938
- if (gravityBin && gravityURL && devmode && project) {
939
- const privateKeyPEM = devmode.privateKey ?? savedPrivateKey;
940
- if (!privateKeyPEM) {
941
- tui.error(
942
- 'No private key available for gravity connection. Please re-run to generate a new key.'
943
- );
944
- await cleanup(true, 1, true);
945
- return;
946
- }
947
-
948
- try {
949
- gravityProcess = Bun.spawn(
950
- [
951
- gravityBin,
952
- '--endpoint-id',
953
- devmode.id,
954
- '--port',
955
- vitePort.toString(),
956
- '--url',
957
- gravityURL,
958
- '--log-level',
959
- process.env.AGENTUITY_GRAVITY_LOG_LEVEL ?? 'error',
960
- '--org-id',
961
- project.orgId,
962
- '--project-id',
963
- project.projectId,
964
- '--private-key',
965
- Buffer.from(privateKeyPEM).toString('base64'),
966
- '--health-check',
967
- ],
968
- {
969
- cwd: rootDir,
970
- stdout: 'pipe',
971
- stderr: 'pipe',
972
- detached: false,
973
- }
974
- );
128
+ }
975
129
 
976
- const gravityPid = (gravityProcess as { pid?: number }).pid;
977
- if (gravityPid) {
978
- await devLock.registerChild({
979
- pid: gravityPid,
980
- type: 'gravity',
981
- description: 'Gravity public URL tunnel',
982
- });
130
+ // Run the dev command, inheriting stdio for full interactivity
131
+ const proc = Bun.spawn(cmd, {
132
+ cwd: rootDir,
133
+ env,
134
+ stdin: 'inherit',
135
+ stdout: 'inherit',
136
+ stderr: 'inherit',
137
+ });
983
138
 
984
- // Register with process manager
985
- procManager.registerProcess({
986
- id: 'gravity',
987
- process: gravityProcess,
988
- description: 'Gravity public URL tunnel',
989
- critical: false,
990
- });
991
- }
139
+ // Forward signals
140
+ const signalHandler = (signal: NodeJS.Signals) => {
141
+ proc.kill(signal === 'SIGINT' ? 'SIGINT' : 'SIGTERM');
142
+ };
143
+ process.on('SIGINT', signalHandler);
144
+ process.on('SIGTERM', signalHandler);
992
145
 
993
- // Log gravity output and detect heartbeat port
994
- (async () => {
995
- try {
996
- if (gravityProcess?.stdout) {
997
- for await (const chunk of gravityProcess.stdout) {
998
- const text = new TextDecoder().decode(chunk);
999
- const trimmed = text.trim();
146
+ const exitCode = await proc.exited;
1000
147
 
1001
- const match = trimmed.match(/^HEARTBEAT_PORT=(\d+)$/m);
1002
- if (match?.[1]) {
1003
- const heartbeatPort = parseInt(match[1], 10);
1004
- logger.debug('Gravity heartbeat port: %d', heartbeatPort);
148
+ process.off('SIGINT', signalHandler);
149
+ process.off('SIGTERM', signalHandler);
1005
150
 
1006
- if (!gravityHeartbeatInterval) {
1007
- const sendHeartbeat = async () => {
1008
- try {
1009
- await fetch(`http://127.0.0.1:${heartbeatPort}/heartbeat`, {
1010
- method: 'POST',
1011
- signal: AbortSignal.timeout(2000),
1012
- });
1013
- } catch {
1014
- // Ignore heartbeat failures
1015
- }
1016
- };
1017
- sendHeartbeat();
1018
- gravityHeartbeatInterval = setInterval(sendHeartbeat, 5000);
1019
- }
1020
- } else if (trimmed) {
1021
- logger.debug('[gravity] %s', trimmed);
1022
- }
1023
- }
1024
- }
1025
- } catch (err) {
1026
- logger.error('Error reading gravity stdout: %s', err);
1027
- }
1028
- })();
151
+ if (exitCode !== 0 && exitCode !== 130) {
152
+ // 130 = SIGINT (Ctrl+C), which is normal
153
+ logger.debug('Dev server exited with code %d', exitCode);
154
+ }
1029
155
 
1030
- (async () => {
1031
- try {
1032
- if (gravityProcess?.stderr) {
1033
- for await (const chunk of gravityProcess.stderr) {
1034
- logger.warn('[gravity] %s', new TextDecoder().decode(chunk).trim());
1035
- }
1036
- }
1037
- } catch (err) {
1038
- logger.error('Error reading gravity stderr: %s', err);
1039
- }
1040
- })();
1041
- } catch (error) {
1042
- tui.error(`Failed to start gravity tunnel: ${error}`);
1043
- await cleanup(true, 1, true);
1044
- return;
1045
- }
1046
- }
156
+ process.exit(exitCode ?? 0);
157
+ },
158
+ });
1047
159
 
1048
- // ================================================================
1049
- // Step 5: Keyboard shortcuts + wait for shutdown
1050
- // ================================================================
160
+ // ─── AI Gateway Env Injection ─────────────────────────────────────────────────
1051
161
 
1052
- if (interactive && process.stdin.isTTY && process.stdout.isTTY) {
1053
- stdinListenerRegistered = true;
1054
- process.stdin.setRawMode(true);
1055
- process.stdin.resume();
1056
- process.stdin.setEncoding('utf8');
162
+ interface GatewayProvider {
163
+ apiKeyEnv: string;
164
+ baseUrlEnv: string;
165
+ provider: string;
166
+ }
1057
167
 
1058
- const showHelp = () => {
1059
- console.log('\n' + tui.bold('Keyboard Shortcuts:'));
1060
- console.log(tui.muted(' h') + ' - show this help');
1061
- console.log(tui.muted(' c') + ' - clear console');
1062
- console.log(tui.muted(' q') + ' - quit\n');
1063
- };
168
+ const GATEWAY_PROVIDERS: GatewayProvider[] = [
169
+ { apiKeyEnv: 'OPENAI_API_KEY', baseUrlEnv: 'OPENAI_BASE_URL', provider: 'openai' },
170
+ { apiKeyEnv: 'ANTHROPIC_API_KEY', baseUrlEnv: 'ANTHROPIC_BASE_URL', provider: 'anthropic' },
171
+ { apiKeyEnv: 'GROQ_API_KEY', baseUrlEnv: 'GROQ_BASE_URL', provider: 'groq' },
172
+ ];
1064
173
 
1065
- stdinDataHandler = (data) => {
1066
- const key = data.toString();
1067
- if (key === '\u0003' || key === 'q') {
1068
- if (stdinDataHandler) {
1069
- process.stdin.removeListener('data', stdinDataHandler);
1070
- stdinDataHandler = null;
1071
- }
1072
- shutdownRequested = true;
1073
- cleanup(true, 0).catch(() => originalExit(1));
1074
- return;
1075
- }
1076
- switch (key) {
1077
- case 'h':
1078
- showHelp();
1079
- break;
1080
- case 'c':
1081
- console.clear();
1082
- tui.banner('⨺ Agentuity DevMode', devmodebody, {
1083
- padding: 2,
1084
- topSpacer: false,
1085
- bottomSpacer: false,
1086
- centerTitle: false,
1087
- });
1088
- break;
1089
- default:
1090
- process.stdout.write(data);
1091
- break;
1092
- }
1093
- };
1094
- process.stdin.on('data', stdinDataHandler);
1095
- }
174
+ /**
175
+ * Inject AI Gateway environment variables into the child process env.
176
+ *
177
+ * For each LLM provider, if the user hasn't set their own API key
178
+ * (or it matches the SDK key), we redirect to the Agentuity gateway.
179
+ * This lets `openai`, `@anthropic-ai/sdk`, and `groq-sdk` work
180
+ * out of the box without separate provider API keys.
181
+ */
182
+ function injectGatewayEnv(
183
+ env: Record<string, string>,
184
+ logger: { debug: (...args: unknown[]) => void }
185
+ ): boolean {
186
+ const sdkKey = env.AGENTUITY_SDK_KEY;
187
+ if (!sdkKey) return false;
188
+
189
+ let injected = false;
190
+
191
+ const gatewayUrl =
192
+ env.AGENTUITY_AIGATEWAY_URL ||
193
+ env.AGENTUITY_TRANSPORT_URL ||
194
+ env.AGENTUITY_CATALYST_URL ||
195
+ 'https://catalyst-usc.agentuity.cloud';
196
+
197
+ for (const { apiKeyEnv, baseUrlEnv, provider } of GATEWAY_PROVIDERS) {
198
+ const currentKey = env[apiKeyEnv];
199
+
200
+ // If the user provided their own key (different from SDK key), leave it alone
201
+ if (currentKey && currentKey !== sdkKey) {
202
+ continue;
203
+ }
1096
204
 
1097
- logger.info('DevMode ready 🚀');
205
+ env[apiKeyEnv] = sdkKey;
206
+ env[baseUrlEnv] = `${gatewayUrl}/gateway/${provider}`;
207
+ logger.debug('AI Gateway: routing %s through %s', provider, env[baseUrlEnv]);
208
+ injected = true;
209
+ }
1098
210
 
1099
- // Block until shutdown — bun --hot handles backend HMR,
1100
- // Vite handles frontend HMR. Nothing to restart.
1101
- await new Promise<void>((resolve) => {
1102
- const check = setInterval(() => {
1103
- if (shutdownRequested) {
1104
- clearInterval(check);
1105
- resolve();
1106
- }
1107
- }, 200);
1108
- });
1109
- } finally {
1110
- /* brute force clean up */
1111
- await devLock.release();
1112
- await killLingeringGravityProcesses(logger);
1113
- releaseLockSync(rootDir);
1114
- }
1115
- },
1116
- });
211
+ return injected;
212
+ }