agent-relay 1.6.0 → 2.0.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 (1313) hide show
  1. package/.cursor/mcp.json +11 -0
  2. package/.gitleaks.toml +26 -0
  3. package/.mcp.json +11 -0
  4. package/.nvmrc +1 -1
  5. package/.turbo/cache/013415461711937f-meta.json +1 -0
  6. package/.turbo/cache/013415461711937f.tar.zst +0 -0
  7. package/.turbo/cache/0562b1ff326acd6d-meta.json +1 -0
  8. package/.turbo/cache/0562b1ff326acd6d.tar.zst +0 -0
  9. package/.turbo/cache/0b46e0e17254882f-meta.json +1 -0
  10. package/.turbo/cache/0b46e0e17254882f.tar.zst +0 -0
  11. package/.turbo/cache/3799eda981d53d14-meta.json +1 -0
  12. package/.turbo/cache/3799eda981d53d14.tar.zst +0 -0
  13. package/.turbo/cache/47e9d8f404ed064d-meta.json +1 -0
  14. package/.turbo/cache/47e9d8f404ed064d.tar.zst +0 -0
  15. package/.turbo/cache/4cde1d1e5b298099-meta.json +1 -0
  16. package/.turbo/cache/4cde1d1e5b298099.tar.zst +0 -0
  17. package/.turbo/cache/538eea955c0936ef-meta.json +1 -0
  18. package/.turbo/cache/538eea955c0936ef.tar.zst +0 -0
  19. package/.turbo/cache/5dceac7f229f5d5d-meta.json +1 -0
  20. package/.turbo/cache/5dceac7f229f5d5d.tar.zst +0 -0
  21. package/.turbo/cache/64c15b201819367d-meta.json +1 -0
  22. package/.turbo/cache/64c15b201819367d.tar.zst +0 -0
  23. package/.turbo/cache/6d6a21a05efca434-meta.json +1 -0
  24. package/.turbo/cache/6d6a21a05efca434.tar.zst +0 -0
  25. package/.turbo/cache/7562610cb03ec040-meta.json +1 -0
  26. package/.turbo/cache/7562610cb03ec040.tar.zst +0 -0
  27. package/.turbo/cache/81a2456e17af4d7f-meta.json +1 -0
  28. package/.turbo/cache/81a2456e17af4d7f.tar.zst +0 -0
  29. package/.turbo/cache/823fc2a7b12f724c-meta.json +1 -0
  30. package/.turbo/cache/823fc2a7b12f724c.tar.zst +0 -0
  31. package/.turbo/cache/9daad16a073d1f91-meta.json +1 -0
  32. package/.turbo/cache/9daad16a073d1f91.tar.zst +0 -0
  33. package/.turbo/cache/b81ccbab0a606b60-meta.json +1 -0
  34. package/.turbo/cache/b81ccbab0a606b60.tar.zst +0 -0
  35. package/.turbo/cache/cf98487988bfcf91-meta.json +1 -0
  36. package/.turbo/cache/cf98487988bfcf91.tar.zst +0 -0
  37. package/.turbo/cache/cfdf7c57dca71f27-meta.json +1 -0
  38. package/.turbo/cache/cfdf7c57dca71f27.tar.zst +0 -0
  39. package/.turbo/cache/d3063ef43811b1e5-meta.json +1 -0
  40. package/.turbo/cache/d3063ef43811b1e5.tar.zst +0 -0
  41. package/.turbo/cache/de28892eb7678e65-meta.json +1 -0
  42. package/.turbo/cache/de28892eb7678e65.tar.zst +0 -0
  43. package/.turbo/cache/ec29adce408132ba-meta.json +1 -0
  44. package/.turbo/cache/ec29adce408132ba.tar.zst +0 -0
  45. package/.turbo/cache/f70450d8d305f172-meta.json +1 -0
  46. package/.turbo/cache/f70450d8d305f172.tar.zst +0 -0
  47. package/.turbo/cache/fe384d5d6b7a983a-meta.json +1 -0
  48. package/.turbo/cache/fe384d5d6b7a983a.tar.zst +0 -0
  49. package/ARCHITECTURE.md +10 -10
  50. package/CHANGELOG.md +38 -0
  51. package/LICENSE +185 -17
  52. package/README.md +43 -5
  53. package/SESSION_HANDOFF.md +67 -0
  54. package/bin/relay-pty +0 -0
  55. package/bin/relay-pty-darwin-arm64 +0 -0
  56. package/bin/relay-pty-darwin-x64 +0 -0
  57. package/bin/relay-pty-linux-x64 +0 -0
  58. package/deploy/workspace/entrypoint.sh +79 -11
  59. package/deploy/workspace/git-credential-relay +152 -27
  60. package/deploy/workspace/git-credential-relay.test.sh +230 -0
  61. package/dist/dashboard/out/404.html +1 -1
  62. package/dist/dashboard/out/_next/static/chunks/116-a883fca163f3a5bc.js +1 -0
  63. package/dist/dashboard/out/_next/static/chunks/320-900169c942e31422.js +1 -0
  64. package/dist/dashboard/out/_next/static/chunks/631-af51bad94027527a.js +1 -0
  65. package/dist/dashboard/out/_next/static/chunks/766-2aea80818f7eb0d8.js +1 -0
  66. package/dist/dashboard/out/_next/static/chunks/891-5cb1513eeb97a891.js +1 -0
  67. package/dist/dashboard/out/_next/static/chunks/app/app/page-2e525b1dcc790967.js +1 -0
  68. package/dist/dashboard/out/_next/static/chunks/app/page-4e64923d73c35bc9.js +1 -0
  69. package/dist/dashboard/out/_next/static/chunks/app/providers/page-e65a0010da6ea5be.js +1 -0
  70. package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-84161c802b020a1f.js +1 -0
  71. package/dist/dashboard/out/_next/static/css/99c2552394077586.css +1 -0
  72. package/dist/dashboard/out/app/onboarding.html +1 -1
  73. package/dist/dashboard/out/app/onboarding.txt +1 -1
  74. package/dist/dashboard/out/app.html +1 -1
  75. package/dist/dashboard/out/app.txt +2 -2
  76. package/dist/dashboard/out/cloud/link.html +1 -1
  77. package/dist/dashboard/out/cloud/link.txt +2 -2
  78. package/dist/dashboard/out/connect-repos.html +1 -1
  79. package/dist/dashboard/out/connect-repos.txt +1 -1
  80. package/dist/dashboard/out/history.html +1 -1
  81. package/dist/dashboard/out/history.txt +2 -2
  82. package/dist/dashboard/out/index.html +1 -1
  83. package/dist/dashboard/out/index.txt +2 -2
  84. package/dist/dashboard/out/login.html +2 -2
  85. package/dist/dashboard/out/login.txt +1 -1
  86. package/dist/dashboard/out/metrics.html +1 -1
  87. package/dist/dashboard/out/metrics.txt +2 -2
  88. package/dist/dashboard/out/pricing.html +3 -3
  89. package/dist/dashboard/out/pricing.txt +2 -2
  90. package/dist/dashboard/out/providers/setup/claude.html +1 -1
  91. package/dist/dashboard/out/providers/setup/claude.txt +2 -2
  92. package/dist/dashboard/out/providers/setup/codex.html +1 -1
  93. package/dist/dashboard/out/providers/setup/codex.txt +2 -2
  94. package/dist/dashboard/out/providers/setup/cursor.html +1 -0
  95. package/dist/dashboard/out/providers/setup/cursor.txt +8 -0
  96. package/dist/dashboard/out/providers.html +1 -1
  97. package/dist/dashboard/out/providers.txt +2 -2
  98. package/dist/dashboard/out/signup.html +2 -2
  99. package/dist/dashboard/out/signup.txt +1 -1
  100. package/dist/src/bridge/index.d.ts +8 -0
  101. package/dist/src/bridge/index.js +8 -0
  102. package/dist/src/cli/index.js +3089 -0
  103. package/dist/src/cloud/index.d.ts +8 -0
  104. package/dist/src/cloud/index.js +8 -0
  105. package/dist/src/config/relay-config.d.ts +5 -0
  106. package/dist/src/config/relay-config.js +5 -0
  107. package/dist/src/continuity/index.d.ts +5 -0
  108. package/dist/src/continuity/index.js +5 -0
  109. package/dist/src/daemon/index.d.ts +8 -0
  110. package/dist/src/daemon/index.js +9 -0
  111. package/dist/src/dashboard-server/index.d.ts +8 -0
  112. package/dist/src/dashboard-server/index.js +8 -0
  113. package/dist/src/hooks/index.d.ts +10 -0
  114. package/dist/src/hooks/index.js +10 -0
  115. package/dist/src/index.d.ts +13 -0
  116. package/dist/src/index.js +16 -0
  117. package/dist/src/memory/index.d.ts +5 -0
  118. package/dist/src/memory/index.js +5 -0
  119. package/dist/src/policy/index.d.ts +5 -0
  120. package/dist/src/policy/index.js +5 -0
  121. package/dist/src/protocol/index.d.ts +8 -0
  122. package/dist/src/protocol/index.js +8 -0
  123. package/dist/src/resiliency/index.d.ts +5 -0
  124. package/dist/src/resiliency/index.js +5 -0
  125. package/dist/src/shared/cli-auth-config.d.ts +5 -0
  126. package/dist/src/shared/cli-auth-config.js +5 -0
  127. package/dist/src/state/index.d.ts +5 -0
  128. package/dist/src/state/index.js +5 -0
  129. package/dist/src/storage/index.d.ts +8 -0
  130. package/dist/src/storage/index.js +8 -0
  131. package/dist/src/trajectory/index.d.ts +5 -0
  132. package/dist/src/trajectory/index.js +5 -0
  133. package/dist/src/utils/index.d.ts +5 -0
  134. package/dist/src/utils/index.js +5 -0
  135. package/dist/src/wrapper/index.d.ts +8 -0
  136. package/dist/src/wrapper/index.js +11 -0
  137. package/package.json +64 -19
  138. package/packages/api-types/dist/index.d.ts +21 -0
  139. package/packages/api-types/dist/index.js +22 -0
  140. package/packages/api-types/dist/schemas/agent.d.ts +259 -0
  141. package/packages/api-types/dist/schemas/agent.js +102 -0
  142. package/packages/api-types/dist/schemas/api.d.ts +290 -0
  143. package/packages/api-types/dist/schemas/api.js +162 -0
  144. package/packages/api-types/dist/schemas/decision.d.ts +230 -0
  145. package/packages/api-types/dist/schemas/decision.js +104 -0
  146. package/packages/api-types/dist/schemas/fleet.d.ts +615 -0
  147. package/packages/api-types/dist/schemas/fleet.js +71 -0
  148. package/packages/api-types/dist/schemas/history.d.ts +180 -0
  149. package/packages/api-types/dist/schemas/history.js +72 -0
  150. package/packages/api-types/dist/schemas/index.d.ts +14 -0
  151. package/packages/api-types/dist/schemas/index.js +22 -0
  152. package/packages/api-types/dist/schemas/message.d.ts +456 -0
  153. package/packages/api-types/dist/schemas/message.js +88 -0
  154. package/packages/api-types/dist/schemas/session.d.ts +60 -0
  155. package/packages/api-types/dist/schemas/session.js +36 -0
  156. package/packages/api-types/dist/schemas/task.d.ts +111 -0
  157. package/packages/api-types/dist/schemas/task.js +64 -0
  158. package/packages/api-types/package.json +61 -0
  159. package/packages/api-types/scripts/generate-openapi.ts +106 -0
  160. package/packages/bridge/dist/index.d.ts +8 -0
  161. package/packages/bridge/dist/index.js +9 -0
  162. package/packages/bridge/dist/multi-project-client.d.ts +99 -0
  163. package/packages/bridge/dist/multi-project-client.js +389 -0
  164. package/packages/bridge/dist/shadow-cli.js +75 -0
  165. package/packages/bridge/dist/spawner.d.ts +210 -0
  166. package/packages/bridge/dist/spawner.js +1276 -0
  167. package/packages/bridge/dist/types.d.ts +131 -0
  168. package/packages/bridge/dist/utils.d.ts +15 -0
  169. package/packages/bridge/dist/utils.js +60 -0
  170. package/packages/bridge/package.json +40 -0
  171. package/packages/cloud/dist/api/admin.js +225 -0
  172. package/packages/cloud/dist/api/billing.js +564 -0
  173. package/packages/cloud/dist/api/cli-pty-runner.d.ts +53 -0
  174. package/packages/cloud/dist/api/cli-pty-runner.js +193 -0
  175. package/packages/cloud/dist/api/codex-auth-helper.js +327 -0
  176. package/packages/cloud/dist/api/consensus.js +261 -0
  177. package/packages/cloud/dist/api/coordinators.js +750 -0
  178. package/packages/cloud/dist/api/daemons.js +535 -0
  179. package/packages/cloud/dist/api/generic-webhooks.js +129 -0
  180. package/packages/cloud/dist/api/github-app.js +223 -0
  181. package/packages/cloud/dist/api/monitoring.js +578 -0
  182. package/packages/cloud/dist/api/nango-auth.js +674 -0
  183. package/packages/cloud/dist/api/onboarding.d.ts +15 -0
  184. package/packages/cloud/dist/api/onboarding.js +679 -0
  185. package/packages/cloud/dist/api/policy.js +229 -0
  186. package/packages/cloud/dist/api/provider-env.d.ts +14 -0
  187. package/packages/cloud/dist/api/provider-env.js +75 -0
  188. package/packages/cloud/dist/api/providers.js +564 -0
  189. package/packages/cloud/dist/api/repos.js +577 -0
  190. package/packages/cloud/dist/api/sessions.d.ts +11 -0
  191. package/packages/cloud/dist/api/sessions.js +302 -0
  192. package/packages/cloud/dist/api/teams.js +281 -0
  193. package/packages/cloud/dist/api/test-helpers.js +745 -0
  194. package/packages/cloud/dist/api/workspaces.js +1799 -0
  195. package/packages/cloud/dist/billing/plans.js +245 -0
  196. package/packages/cloud/dist/config.d.ts +5 -0
  197. package/packages/cloud/dist/config.js +5 -0
  198. package/packages/cloud/dist/db/drizzle.d.ts +256 -0
  199. package/packages/cloud/dist/db/drizzle.js +1286 -0
  200. package/packages/cloud/dist/db/schema.d.ts +4873 -0
  201. package/packages/cloud/dist/db/schema.js +620 -0
  202. package/packages/cloud/dist/index.d.ts +11 -0
  203. package/packages/cloud/dist/index.js +38 -0
  204. package/packages/cloud/dist/provisioner/index.d.ts +207 -0
  205. package/packages/cloud/dist/provisioner/index.js +2114 -0
  206. package/packages/cloud/dist/server.js +1924 -0
  207. package/packages/cloud/dist/services/index.d.ts +17 -0
  208. package/packages/cloud/dist/services/index.js +25 -0
  209. package/packages/cloud/dist/services/intro-expiration.d.ts +60 -0
  210. package/packages/cloud/dist/services/intro-expiration.js +252 -0
  211. package/packages/cloud/dist/services/nango.d.ts +201 -0
  212. package/packages/cloud/dist/services/nango.js +392 -0
  213. package/packages/cloud/dist/services/persistence.d.ts +131 -0
  214. package/packages/cloud/dist/shims/consensus.d.ts +23 -0
  215. package/packages/cloud/dist/shims/consensus.js +5 -0
  216. package/packages/cloud/package.json +55 -0
  217. package/packages/config/dist/bridge-config.d.ts +52 -0
  218. package/packages/config/dist/bridge-config.js +143 -0
  219. package/packages/config/dist/bridge-utils.d.ts +30 -0
  220. package/packages/config/dist/bridge-utils.js +54 -0
  221. package/packages/config/dist/cli-auth-config.js +391 -0
  222. package/packages/config/dist/cloud-config.d.ts +75 -0
  223. package/packages/config/dist/cloud-config.js +109 -0
  224. package/packages/config/dist/index.d.ts +13 -0
  225. package/packages/config/dist/index.js +13 -0
  226. package/packages/config/dist/project-namespace.d.ts +73 -0
  227. package/packages/config/dist/project-namespace.js +280 -0
  228. package/packages/config/dist/relay-config.d.ts +25 -0
  229. package/packages/config/dist/relay-config.js +25 -0
  230. package/packages/config/dist/relay-file-writer.d.ts +200 -0
  231. package/packages/config/dist/relay-file-writer.js +407 -0
  232. package/packages/config/dist/schemas.d.ts +672 -0
  233. package/packages/config/dist/schemas.js +180 -0
  234. package/packages/config/dist/shadow-config.d.ts +87 -0
  235. package/packages/config/dist/trajectory-config.d.ts +102 -0
  236. package/packages/config/dist/trajectory-config.js +185 -0
  237. package/packages/config/package.json +98 -0
  238. package/packages/continuity/dist/index.d.ts +9 -0
  239. package/packages/continuity/dist/index.js +9 -0
  240. package/packages/continuity/dist/types.d.ts +180 -0
  241. package/packages/continuity/dist/types.js +2 -0
  242. package/packages/continuity/package.json +32 -0
  243. package/packages/daemon/dist/agent-manager.d.ts +134 -0
  244. package/packages/daemon/dist/agent-manager.js +578 -0
  245. package/packages/daemon/dist/agent-registry.js +213 -0
  246. package/packages/daemon/dist/api.d.ts +106 -0
  247. package/packages/daemon/dist/api.js +876 -0
  248. package/packages/daemon/dist/channel-membership-store.d.ts +55 -0
  249. package/packages/daemon/dist/channel-membership-store.js +176 -0
  250. package/packages/daemon/dist/cli-auth.d.ts +89 -0
  251. package/packages/daemon/dist/cli-auth.js +792 -0
  252. package/packages/daemon/dist/cloud-sync.d.ts +150 -0
  253. package/packages/daemon/dist/cloud-sync.js +446 -0
  254. package/packages/daemon/dist/connection.d.ts +130 -0
  255. package/packages/daemon/dist/connection.js +438 -0
  256. package/packages/daemon/dist/consensus-integration.js +371 -0
  257. package/packages/daemon/dist/delivery-tracker.d.ts +34 -0
  258. package/packages/daemon/dist/delivery-tracker.js +104 -0
  259. package/packages/daemon/dist/enhanced-features.d.ts +118 -0
  260. package/packages/daemon/dist/enhanced-features.js +176 -0
  261. package/packages/daemon/dist/index.d.ts +31 -0
  262. package/packages/daemon/dist/index.js +37 -0
  263. package/packages/daemon/dist/migrations/index.d.ts +73 -0
  264. package/packages/daemon/dist/migrations/index.js +241 -0
  265. package/packages/daemon/dist/orchestrator.d.ts +217 -0
  266. package/packages/daemon/dist/orchestrator.js +1143 -0
  267. package/packages/daemon/dist/relay-ledger.d.ts +261 -0
  268. package/packages/daemon/dist/relay-ledger.js +532 -0
  269. package/packages/daemon/dist/relay-watchdog.d.ts +125 -0
  270. package/packages/daemon/dist/relay-watchdog.js +611 -0
  271. package/packages/daemon/dist/repo-manager.js +384 -0
  272. package/packages/daemon/dist/router.d.ts +370 -0
  273. package/packages/daemon/dist/router.js +1437 -0
  274. package/packages/daemon/dist/server.d.ts +174 -0
  275. package/packages/daemon/dist/server.js +1001 -0
  276. package/packages/daemon/dist/spawn-manager.d.ts +78 -0
  277. package/packages/daemon/dist/spawn-manager.js +165 -0
  278. package/packages/daemon/dist/sync-queue.d.ts +116 -0
  279. package/packages/daemon/dist/sync-queue.js +361 -0
  280. package/packages/daemon/dist/types.d.ts +133 -0
  281. package/packages/daemon/dist/workspace-manager.js +314 -0
  282. package/packages/daemon/package.json +52 -0
  283. package/packages/dashboard/README.md +48 -0
  284. package/packages/dashboard/dist/health-worker-manager.d.ts +62 -0
  285. package/packages/dashboard/dist/health-worker-manager.js +144 -0
  286. package/packages/dashboard/dist/health-worker.d.ts +9 -0
  287. package/packages/dashboard/dist/health-worker.js +79 -0
  288. package/packages/dashboard/dist/index.d.ts +20 -0
  289. package/packages/dashboard/dist/index.js +19 -0
  290. package/packages/dashboard/dist/metrics.d.ts +105 -0
  291. package/packages/dashboard/dist/metrics.js +193 -0
  292. package/packages/dashboard/dist/needs-attention.d.ts +24 -0
  293. package/packages/dashboard/dist/needs-attention.js +78 -0
  294. package/packages/dashboard/dist/server.d.ts +25 -0
  295. package/packages/dashboard/dist/server.js +5107 -0
  296. package/packages/dashboard/dist/start.d.ts +6 -0
  297. package/packages/dashboard/dist/start.js +13 -0
  298. package/packages/dashboard/dist/types/threading.d.ts +8 -0
  299. package/packages/dashboard/dist/types/threading.js +2 -0
  300. package/packages/dashboard/dist/user-bridge.d.ts +154 -0
  301. package/packages/dashboard/dist/user-bridge.js +372 -0
  302. package/packages/dashboard/package.json +72 -0
  303. package/packages/dashboard/ui/.next/BUILD_ID +1 -0
  304. package/packages/dashboard/ui/.next/app-build-manifest.json +135 -0
  305. package/packages/dashboard/ui/.next/app-path-routes-manifest.json +1 -0
  306. package/packages/dashboard/ui/.next/build-manifest.json +32 -0
  307. package/packages/dashboard/ui/.next/cache/config.json +7 -0
  308. package/packages/dashboard/ui/.next/cache/eslint/.cache_1asv1h5 +1 -0
  309. package/packages/dashboard/ui/.next/cache/webpack/client-production/0.pack +0 -0
  310. package/packages/dashboard/ui/.next/cache/webpack/client-production/index.pack +0 -0
  311. package/packages/dashboard/ui/.next/cache/webpack/edge-server-production/0.pack +0 -0
  312. package/packages/dashboard/ui/.next/cache/webpack/edge-server-production/index.pack +0 -0
  313. package/packages/dashboard/ui/.next/cache/webpack/server-production/0.pack +0 -0
  314. package/packages/dashboard/ui/.next/cache/webpack/server-production/index.pack +0 -0
  315. package/packages/dashboard/ui/.next/export-detail.json +1 -0
  316. package/packages/dashboard/ui/.next/export-marker.json +1 -0
  317. package/packages/dashboard/ui/.next/images-manifest.json +1 -0
  318. package/packages/dashboard/ui/.next/next-minimal-server.js.nft.json +1 -0
  319. package/packages/dashboard/ui/.next/next-server.js.nft.json +1 -0
  320. package/packages/dashboard/ui/.next/package.json +1 -0
  321. package/packages/dashboard/ui/.next/prerender-manifest.json +1 -0
  322. package/packages/dashboard/ui/.next/react-loadable-manifest.json +1970 -0
  323. package/packages/dashboard/ui/.next/required-server-files.json +1 -0
  324. package/packages/dashboard/ui/.next/routes-manifest.json +1 -0
  325. package/packages/dashboard/ui/.next/server/app/_not-found/page.js +1 -0
  326. package/packages/dashboard/ui/.next/server/app/_not-found/page.js.nft.json +1 -0
  327. package/packages/dashboard/ui/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  328. package/packages/dashboard/ui/.next/server/app/_not-found.html +1 -0
  329. package/packages/dashboard/ui/.next/server/app/_not-found.meta +6 -0
  330. package/packages/dashboard/ui/.next/server/app/_not-found.rsc +9 -0
  331. package/packages/dashboard/ui/.next/server/app/app/onboarding/page.js +6 -0
  332. package/packages/dashboard/ui/.next/server/app/app/onboarding/page.js.nft.json +1 -0
  333. package/packages/dashboard/ui/.next/server/app/app/onboarding/page_client-reference-manifest.js +1 -0
  334. package/packages/dashboard/ui/.next/server/app/app/onboarding.html +1 -0
  335. package/packages/dashboard/ui/.next/server/app/app/onboarding.meta +5 -0
  336. package/packages/dashboard/ui/.next/server/app/app/onboarding.rsc +7 -0
  337. package/packages/dashboard/ui/.next/server/app/app/page.js +436 -0
  338. package/packages/dashboard/ui/.next/server/app/app/page.js.nft.json +1 -0
  339. package/packages/dashboard/ui/.next/server/app/app/page_client-reference-manifest.js +1 -0
  340. package/packages/dashboard/ui/.next/server/app/app.html +1 -0
  341. package/packages/dashboard/ui/.next/server/app/app.meta +5 -0
  342. package/packages/dashboard/ui/.next/server/app/app.rsc +7 -0
  343. package/packages/dashboard/ui/.next/server/app/apple-icon.png/route.js +12 -0
  344. package/packages/dashboard/ui/.next/server/app/apple-icon.png/route.js.nft.json +1 -0
  345. package/packages/dashboard/ui/.next/server/app/apple-icon.png.body +0 -0
  346. package/packages/dashboard/ui/.next/server/app/apple-icon.png.meta +1 -0
  347. package/packages/dashboard/ui/.next/server/app/cloud/link/page.js +1 -0
  348. package/packages/dashboard/ui/.next/server/app/cloud/link/page.js.nft.json +1 -0
  349. package/packages/dashboard/ui/.next/server/app/cloud/link/page_client-reference-manifest.js +1 -0
  350. package/packages/dashboard/ui/.next/server/app/cloud/link.html +1 -0
  351. package/packages/dashboard/ui/.next/server/app/cloud/link.meta +5 -0
  352. package/packages/dashboard/ui/.next/server/app/cloud/link.rsc +7 -0
  353. package/packages/dashboard/ui/.next/server/app/connect-repos/page.js +6 -0
  354. package/packages/dashboard/ui/.next/server/app/connect-repos/page.js.nft.json +1 -0
  355. package/packages/dashboard/ui/.next/server/app/connect-repos/page_client-reference-manifest.js +1 -0
  356. package/packages/dashboard/ui/.next/server/app/connect-repos.html +1 -0
  357. package/packages/dashboard/ui/.next/server/app/connect-repos.meta +5 -0
  358. package/packages/dashboard/ui/.next/server/app/connect-repos.rsc +7 -0
  359. package/packages/dashboard/ui/.next/server/app/history/page.js +1 -0
  360. package/packages/dashboard/ui/.next/server/app/history/page.js.nft.json +1 -0
  361. package/packages/dashboard/ui/.next/server/app/history/page_client-reference-manifest.js +1 -0
  362. package/packages/dashboard/ui/.next/server/app/history.html +1 -0
  363. package/packages/dashboard/ui/.next/server/app/history.meta +5 -0
  364. package/packages/dashboard/ui/.next/server/app/history.rsc +7 -0
  365. package/packages/dashboard/ui/.next/server/app/index.html +1 -0
  366. package/packages/dashboard/ui/.next/server/app/index.meta +5 -0
  367. package/packages/dashboard/ui/.next/server/app/index.rsc +7 -0
  368. package/packages/dashboard/ui/.next/server/app/login/page.js +6 -0
  369. package/packages/dashboard/ui/.next/server/app/login/page.js.nft.json +1 -0
  370. package/packages/dashboard/ui/.next/server/app/login/page_client-reference-manifest.js +1 -0
  371. package/packages/dashboard/ui/.next/server/app/login.html +5 -0
  372. package/packages/dashboard/ui/.next/server/app/login.meta +5 -0
  373. package/packages/dashboard/ui/.next/server/app/login.rsc +7 -0
  374. package/packages/dashboard/ui/.next/server/app/metrics/page.js +1 -0
  375. package/packages/dashboard/ui/.next/server/app/metrics/page.js.nft.json +1 -0
  376. package/packages/dashboard/ui/.next/server/app/metrics/page_client-reference-manifest.js +1 -0
  377. package/packages/dashboard/ui/.next/server/app/metrics.html +1 -0
  378. package/packages/dashboard/ui/.next/server/app/metrics.meta +5 -0
  379. package/packages/dashboard/ui/.next/server/app/metrics.rsc +7 -0
  380. package/packages/dashboard/ui/.next/server/app/page.js +1 -0
  381. package/packages/dashboard/ui/.next/server/app/page.js.nft.json +1 -0
  382. package/packages/dashboard/ui/.next/server/app/page_client-reference-manifest.js +1 -0
  383. package/packages/dashboard/ui/.next/server/app/pricing/page.js +5 -0
  384. package/packages/dashboard/ui/.next/server/app/pricing/page.js.nft.json +1 -0
  385. package/packages/dashboard/ui/.next/server/app/pricing/page_client-reference-manifest.js +1 -0
  386. package/packages/dashboard/ui/.next/server/app/pricing.html +13 -0
  387. package/packages/dashboard/ui/.next/server/app/pricing.meta +5 -0
  388. package/packages/dashboard/ui/.next/server/app/pricing.rsc +7 -0
  389. package/packages/dashboard/ui/.next/server/app/providers/page.js +2 -0
  390. package/packages/dashboard/ui/.next/server/app/providers/page.js.nft.json +1 -0
  391. package/packages/dashboard/ui/.next/server/app/providers/page_client-reference-manifest.js +1 -0
  392. package/packages/dashboard/ui/.next/server/app/providers/setup/[provider]/page.js +1 -0
  393. package/packages/dashboard/ui/.next/server/app/providers/setup/[provider]/page.js.nft.json +1 -0
  394. package/packages/dashboard/ui/.next/server/app/providers/setup/[provider]/page_client-reference-manifest.js +1 -0
  395. package/packages/dashboard/ui/.next/server/app/providers/setup/claude.html +1 -0
  396. package/packages/dashboard/ui/.next/server/app/providers/setup/claude.meta +5 -0
  397. package/packages/dashboard/ui/.next/server/app/providers/setup/claude.rsc +8 -0
  398. package/packages/dashboard/ui/.next/server/app/providers/setup/codex.html +1 -0
  399. package/packages/dashboard/ui/.next/server/app/providers/setup/codex.meta +5 -0
  400. package/packages/dashboard/ui/.next/server/app/providers/setup/codex.rsc +8 -0
  401. package/packages/dashboard/ui/.next/server/app/providers/setup/cursor.html +1 -0
  402. package/packages/dashboard/ui/.next/server/app/providers/setup/cursor.meta +5 -0
  403. package/packages/dashboard/ui/.next/server/app/providers/setup/cursor.rsc +8 -0
  404. package/packages/dashboard/ui/.next/server/app/providers.html +1 -0
  405. package/packages/dashboard/ui/.next/server/app/providers.meta +5 -0
  406. package/packages/dashboard/ui/.next/server/app/providers.rsc +7 -0
  407. package/packages/dashboard/ui/.next/server/app/signup/page.js +6 -0
  408. package/packages/dashboard/ui/.next/server/app/signup/page.js.nft.json +1 -0
  409. package/packages/dashboard/ui/.next/server/app/signup/page_client-reference-manifest.js +1 -0
  410. package/packages/dashboard/ui/.next/server/app/signup.html +6 -0
  411. package/packages/dashboard/ui/.next/server/app/signup.meta +5 -0
  412. package/packages/dashboard/ui/.next/server/app/signup.rsc +7 -0
  413. package/packages/dashboard/ui/.next/server/app-paths-manifest.json +16 -0
  414. package/packages/dashboard/ui/.next/server/chunks/190.js +1 -0
  415. package/packages/dashboard/ui/.next/server/chunks/205.js +1 -0
  416. package/packages/dashboard/ui/.next/server/chunks/251.js +9 -0
  417. package/packages/dashboard/ui/.next/server/chunks/288.js +1 -0
  418. package/packages/dashboard/ui/.next/server/chunks/434.js +1 -0
  419. package/packages/dashboard/ui/.next/server/chunks/471.js +2 -0
  420. package/packages/dashboard/ui/.next/server/chunks/621.js +1 -0
  421. package/packages/dashboard/ui/.next/server/chunks/680.js +5 -0
  422. package/packages/dashboard/ui/.next/server/chunks/682.js +6 -0
  423. package/packages/dashboard/ui/.next/server/chunks/684.js +1 -0
  424. package/packages/dashboard/ui/.next/server/chunks/71.js +196 -0
  425. package/packages/dashboard/ui/.next/server/chunks/711.js +1 -0
  426. package/packages/dashboard/ui/.next/server/chunks/90.js +17 -0
  427. package/packages/dashboard/ui/.next/server/chunks/948.js +2 -0
  428. package/packages/dashboard/ui/.next/server/chunks/font-manifest.json +1 -0
  429. package/packages/dashboard/ui/.next/server/font-manifest.json +1 -0
  430. package/packages/dashboard/ui/.next/server/functions-config-manifest.json +1 -0
  431. package/packages/dashboard/ui/.next/server/interception-route-rewrite-manifest.js +1 -0
  432. package/packages/dashboard/ui/.next/server/middleware-build-manifest.js +1 -0
  433. package/packages/dashboard/ui/.next/server/middleware-manifest.json +6 -0
  434. package/packages/dashboard/ui/.next/server/middleware-react-loadable-manifest.js +1 -0
  435. package/packages/dashboard/ui/.next/server/next-font-manifest.js +1 -0
  436. package/packages/dashboard/ui/.next/server/next-font-manifest.json +1 -0
  437. package/packages/dashboard/ui/.next/server/pages/404.html +1 -0
  438. package/packages/dashboard/ui/.next/server/pages/500.html +1 -0
  439. package/packages/dashboard/ui/.next/server/pages/_app.js +1 -0
  440. package/packages/dashboard/ui/.next/server/pages/_app.js.nft.json +1 -0
  441. package/packages/dashboard/ui/.next/server/pages/_document.js +1 -0
  442. package/packages/dashboard/ui/.next/server/pages/_document.js.nft.json +1 -0
  443. package/packages/dashboard/ui/.next/server/pages/_error.js +1 -0
  444. package/packages/dashboard/ui/.next/server/pages/_error.js.nft.json +1 -0
  445. package/packages/dashboard/ui/.next/server/pages-manifest.json +1 -0
  446. package/packages/dashboard/ui/.next/server/server-reference-manifest.js +1 -0
  447. package/packages/dashboard/ui/.next/server/server-reference-manifest.json +1 -0
  448. package/packages/dashboard/ui/.next/server/webpack-runtime.js +1 -0
  449. package/packages/dashboard/ui/.next/static/HR7W9z1PPVPFqUboUVZFZ/_buildManifest.js +1 -0
  450. package/packages/dashboard/ui/.next/static/HR7W9z1PPVPFqUboUVZFZ/_ssgManifest.js +1 -0
  451. package/packages/dashboard/ui/.next/static/chunks/116-a883fca163f3a5bc.js +1 -0
  452. package/packages/dashboard/ui/.next/static/chunks/117-c8afed19e821a35d.js +2 -0
  453. package/packages/dashboard/ui/.next/static/chunks/282-980c2eb8fff20123.js +1 -0
  454. package/packages/dashboard/ui/.next/static/chunks/532-bace199897eeab37.js +9 -0
  455. package/packages/dashboard/ui/.next/static/chunks/631-af51bad94027527a.js +1 -0
  456. package/packages/dashboard/ui/.next/static/chunks/648-acb2ff9f77cbfbd3.js +1 -0
  457. package/packages/dashboard/ui/.next/static/chunks/677-30e60cb0b47875b6.js +1 -0
  458. package/packages/dashboard/ui/.next/static/chunks/766-2aea80818f7eb0d8.js +1 -0
  459. package/packages/dashboard/ui/.next/static/chunks/83-4f08122d4e7e79a6.js +1 -0
  460. package/packages/dashboard/ui/.next/static/chunks/847-f1f467060f32afff.js +1 -0
  461. package/packages/dashboard/ui/.next/static/chunks/891-5cb1513eeb97a891.js +1 -0
  462. package/packages/dashboard/ui/.next/static/chunks/app/_not-found/page-60501fddbafba9dc.js +1 -0
  463. package/packages/dashboard/ui/.next/static/chunks/app/app/onboarding/page-9914652442f7e4fb.js +1 -0
  464. package/packages/dashboard/ui/.next/static/chunks/app/app/page-44813aa26ad19681.js +1 -0
  465. package/packages/dashboard/ui/.next/static/chunks/app/cloud/link/page-fa1d5842aa90e8a6.js +1 -0
  466. package/packages/dashboard/ui/.next/static/chunks/app/connect-repos/page-113060009ef35bc2.js +1 -0
  467. package/packages/dashboard/ui/.next/static/chunks/app/history/page-9965d2483011b846.js +1 -0
  468. package/packages/dashboard/ui/.next/static/chunks/app/layout-6b91e33784c20610.js +1 -0
  469. package/packages/dashboard/ui/.next/static/chunks/app/login/page-a0ca6f7ca6a100b8.js +1 -0
  470. package/packages/dashboard/ui/.next/static/chunks/app/metrics/page-1e37ef8e73940b40.js +1 -0
  471. package/packages/dashboard/ui/.next/static/chunks/app/page-7993778218818ace.js +1 -0
  472. package/packages/dashboard/ui/.next/static/chunks/app/pricing/page-9db3ebdfa567a7c9.js +1 -0
  473. package/packages/dashboard/ui/.next/static/chunks/app/providers/page-bcf46064ac4474ce.js +1 -0
  474. package/packages/dashboard/ui/.next/static/chunks/app/providers/setup/[provider]/page-4dbe33f0f7691b7c.js +1 -0
  475. package/packages/dashboard/ui/.next/static/chunks/app/signup/page-1ede2205b58649ca.js +1 -0
  476. package/packages/dashboard/ui/.next/static/chunks/e868780c-48e5f147c90a3a41.js +18 -0
  477. package/packages/dashboard/ui/.next/static/chunks/fd9d1056-609918ca7b6280bb.js +1 -0
  478. package/packages/dashboard/ui/.next/static/chunks/framework-f66176bb897dc684.js +1 -0
  479. package/packages/dashboard/ui/.next/static/chunks/main-5a40a5ae29646e1b.js +1 -0
  480. package/packages/dashboard/ui/.next/static/chunks/main-app-fdbeb09028f57c9f.js +1 -0
  481. package/packages/dashboard/ui/.next/static/chunks/pages/_app-72b849fbd24ac258.js +1 -0
  482. package/packages/dashboard/ui/.next/static/chunks/pages/_error-7ba65e1336b92748.js +1 -0
  483. package/packages/dashboard/ui/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  484. package/packages/dashboard/ui/.next/static/chunks/webpack-1cdd8ed57114d5e1.js +1 -0
  485. package/packages/dashboard/ui/.next/static/css/4034f236dd1a3178.css +1 -0
  486. package/packages/dashboard/ui/.next/static/css/99c2552394077586.css +1 -0
  487. package/packages/dashboard/ui/.next/trace +63 -0
  488. package/packages/dashboard/ui/.next/types/app/app/onboarding/page.ts +79 -0
  489. package/packages/dashboard/ui/.next/types/app/app/page.ts +79 -0
  490. package/packages/dashboard/ui/.next/types/app/cloud/link/page.ts +79 -0
  491. package/packages/dashboard/ui/.next/types/app/connect-repos/page.ts +79 -0
  492. package/packages/dashboard/ui/.next/types/app/history/page.ts +79 -0
  493. package/packages/dashboard/ui/.next/types/app/layout.ts +79 -0
  494. package/packages/dashboard/ui/.next/types/app/login/page.ts +79 -0
  495. package/packages/dashboard/ui/.next/types/app/metrics/page.ts +79 -0
  496. package/packages/dashboard/ui/.next/types/app/page.ts +79 -0
  497. package/packages/dashboard/ui/.next/types/app/pricing/page.ts +79 -0
  498. package/packages/dashboard/ui/.next/types/app/providers/page.ts +79 -0
  499. package/packages/dashboard/ui/.next/types/app/providers/setup/[provider]/page.ts +79 -0
  500. package/packages/dashboard/ui/.next/types/app/signup/page.ts +79 -0
  501. package/packages/dashboard/ui/.next/types/package.json +1 -0
  502. package/packages/dashboard/ui/app/app/onboarding/page.tsx +394 -0
  503. package/packages/dashboard/ui/app/app/page.tsx +667 -0
  504. package/packages/dashboard/ui/app/apple-icon.png +0 -0
  505. package/packages/dashboard/ui/app/cloud/link/page.tsx +464 -0
  506. package/packages/dashboard/ui/app/connect-repos/page.tsx +410 -0
  507. package/packages/dashboard/ui/app/favicon.png +0 -0
  508. package/packages/dashboard/ui/app/globals.css +59 -0
  509. package/packages/dashboard/ui/app/history/page.tsx +658 -0
  510. package/packages/dashboard/ui/app/layout.tsx +25 -0
  511. package/packages/dashboard/ui/app/login/page.tsx +280 -0
  512. package/packages/dashboard/ui/app/metrics/page.tsx +751 -0
  513. package/packages/dashboard/ui/app/page.tsx +59 -0
  514. package/packages/dashboard/ui/app/pricing/page.tsx +7 -0
  515. package/packages/dashboard/ui/app/providers/page.tsx +193 -0
  516. package/packages/dashboard/ui/app/providers/setup/[provider]/ProviderSetupClient.tsx +148 -0
  517. package/packages/dashboard/ui/app/providers/setup/[provider]/constants.ts +35 -0
  518. package/packages/dashboard/ui/app/providers/setup/[provider]/page.tsx +42 -0
  519. package/packages/dashboard/ui/app/signup/page.tsx +343 -0
  520. package/packages/dashboard/ui/index.ts +49 -0
  521. package/packages/dashboard/ui/landing/LandingPage.tsx +713 -0
  522. package/packages/dashboard/ui/landing/PricingPage.tsx +559 -0
  523. package/packages/dashboard/ui/landing/index.ts +6 -0
  524. package/packages/dashboard/ui/landing/styles.css +2850 -0
  525. package/packages/dashboard/ui/lib/agent-merge.ts +35 -0
  526. package/packages/dashboard/ui/lib/api.ts +1155 -0
  527. package/packages/dashboard/ui/lib/cloudApi.ts +876 -0
  528. package/packages/dashboard/ui/lib/colors.ts +218 -0
  529. package/packages/dashboard/ui/lib/hierarchy.ts +242 -0
  530. package/packages/dashboard/ui/lib/stuckDetection.ts +142 -0
  531. package/packages/dashboard/ui/next-env.d.ts +5 -0
  532. package/packages/dashboard/ui/next.config.js +41 -0
  533. package/packages/dashboard/ui/package-lock.json +2882 -0
  534. package/packages/dashboard/ui/package.json +33 -0
  535. package/packages/dashboard/ui/postcss.config.js +5 -0
  536. package/packages/dashboard/ui/react-components/ActivityFeed.tsx +216 -0
  537. package/packages/dashboard/ui/react-components/AddWorkspaceModal.tsx +170 -0
  538. package/packages/dashboard/ui/react-components/AgentCard.tsx +587 -0
  539. package/packages/dashboard/ui/react-components/AgentList.tsx +411 -0
  540. package/packages/dashboard/ui/react-components/AgentProfilePanel.tsx +564 -0
  541. package/packages/dashboard/ui/react-components/App.tsx +3447 -0
  542. package/packages/dashboard/ui/react-components/BillingPanel.tsx +922 -0
  543. package/packages/dashboard/ui/react-components/BillingResult.tsx +447 -0
  544. package/packages/dashboard/ui/react-components/BroadcastComposer.tsx +690 -0
  545. package/packages/dashboard/ui/react-components/ChannelAdminPanel.tsx +773 -0
  546. package/packages/dashboard/ui/react-components/ChannelBrowser.tsx +385 -0
  547. package/packages/dashboard/ui/react-components/ChannelChat.tsx +307 -0
  548. package/packages/dashboard/ui/react-components/ChannelSidebar.tsx +399 -0
  549. package/packages/dashboard/ui/react-components/CloudSessionProvider.tsx +130 -0
  550. package/packages/dashboard/ui/react-components/CommandPalette.tsx +815 -0
  551. package/packages/dashboard/ui/react-components/ConfirmationDialog.tsx +133 -0
  552. package/packages/dashboard/ui/react-components/ConversationHistory.tsx +518 -0
  553. package/packages/dashboard/ui/react-components/CoordinatorPanel.tsx +944 -0
  554. package/packages/dashboard/ui/react-components/DecisionQueue.tsx +717 -0
  555. package/packages/dashboard/ui/react-components/DirectMessageView.tsx +164 -0
  556. package/packages/dashboard/ui/react-components/FileAutocomplete.tsx +368 -0
  557. package/packages/dashboard/ui/react-components/FleetOverview.tsx +278 -0
  558. package/packages/dashboard/ui/react-components/LogViewer.tsx +310 -0
  559. package/packages/dashboard/ui/react-components/LogViewerPanel.tsx +482 -0
  560. package/packages/dashboard/ui/react-components/Logo.tsx +284 -0
  561. package/packages/dashboard/ui/react-components/MentionAutocomplete.tsx +384 -0
  562. package/packages/dashboard/ui/react-components/MessageList.tsx +649 -0
  563. package/packages/dashboard/ui/react-components/MessageSenderName.tsx +91 -0
  564. package/packages/dashboard/ui/react-components/MessageStatusIndicator.tsx +142 -0
  565. package/packages/dashboard/ui/react-components/NewConversationModal.tsx +400 -0
  566. package/packages/dashboard/ui/react-components/NotificationToast.tsx +488 -0
  567. package/packages/dashboard/ui/react-components/OnlineUsersIndicator.tsx +164 -0
  568. package/packages/dashboard/ui/react-components/Pagination.tsx +124 -0
  569. package/packages/dashboard/ui/react-components/PricingPlans.tsx +386 -0
  570. package/packages/dashboard/ui/react-components/ProjectList.tsx +625 -0
  571. package/packages/dashboard/ui/react-components/ProviderAuthFlow.tsx +843 -0
  572. package/packages/dashboard/ui/react-components/ProviderConnectionList.tsx +363 -0
  573. package/packages/dashboard/ui/react-components/ProvisioningProgress.tsx +730 -0
  574. package/packages/dashboard/ui/react-components/RepoAccessPanel.tsx +392 -0
  575. package/packages/dashboard/ui/react-components/ServerCard.tsx +202 -0
  576. package/packages/dashboard/ui/react-components/SessionExpiredModal.tsx +128 -0
  577. package/packages/dashboard/ui/react-components/SpawnModal.tsx +704 -0
  578. package/packages/dashboard/ui/react-components/TaskAssignmentUI.tsx +375 -0
  579. package/packages/dashboard/ui/react-components/TerminalProviderSetup.tsx +608 -0
  580. package/packages/dashboard/ui/react-components/ThemeProvider.tsx +325 -0
  581. package/packages/dashboard/ui/react-components/ThinkingIndicator.tsx +231 -0
  582. package/packages/dashboard/ui/react-components/ThreadList.tsx +198 -0
  583. package/packages/dashboard/ui/react-components/ThreadPanel.tsx +346 -0
  584. package/packages/dashboard/ui/react-components/TrajectoryViewer.tsx +698 -0
  585. package/packages/dashboard/ui/react-components/TypingIndicator.tsx +69 -0
  586. package/packages/dashboard/ui/react-components/UsageBanner.tsx +231 -0
  587. package/packages/dashboard/ui/react-components/UserProfilePanel.tsx +233 -0
  588. package/packages/dashboard/ui/react-components/WorkspaceContext.tsx +107 -0
  589. package/packages/dashboard/ui/react-components/WorkspaceSelector.tsx +234 -0
  590. package/packages/dashboard/ui/react-components/WorkspaceStatusIndicator.tsx +370 -0
  591. package/packages/dashboard/ui/react-components/XTermInteractive.tsx +510 -0
  592. package/packages/dashboard/ui/react-components/XTermLogViewer.tsx +719 -0
  593. package/packages/dashboard/ui/react-components/channels/ChannelDialogs.tsx +1411 -0
  594. package/packages/dashboard/ui/react-components/channels/ChannelHeader.tsx +317 -0
  595. package/packages/dashboard/ui/react-components/channels/ChannelMessageList.tsx +463 -0
  596. package/packages/dashboard/ui/react-components/channels/ChannelViewV1.tsx +146 -0
  597. package/packages/dashboard/ui/react-components/channels/MessageInput.tsx +288 -0
  598. package/packages/dashboard/ui/react-components/channels/SearchInput.tsx +172 -0
  599. package/packages/dashboard/ui/react-components/channels/SearchResults.tsx +336 -0
  600. package/packages/dashboard/ui/react-components/channels/api.ts +697 -0
  601. package/packages/dashboard/ui/react-components/channels/index.ts +76 -0
  602. package/packages/dashboard/ui/react-components/channels/mockApi.ts +344 -0
  603. package/packages/dashboard/ui/react-components/channels/types.ts +566 -0
  604. package/packages/dashboard/ui/react-components/hooks/index.ts +57 -0
  605. package/packages/dashboard/ui/react-components/hooks/useAgentLogs.ts +394 -0
  606. package/packages/dashboard/ui/react-components/hooks/useAgents.ts +127 -0
  607. package/packages/dashboard/ui/react-components/hooks/useBroadcastDedup.ts +86 -0
  608. package/packages/dashboard/ui/react-components/hooks/useChannelAdmin.ts +329 -0
  609. package/packages/dashboard/ui/react-components/hooks/useChannelBrowser.ts +239 -0
  610. package/packages/dashboard/ui/react-components/hooks/useChannelCommands.ts +138 -0
  611. package/packages/dashboard/ui/react-components/hooks/useChannels.ts +328 -0
  612. package/packages/dashboard/ui/react-components/hooks/useDebounce.ts +29 -0
  613. package/packages/dashboard/ui/react-components/hooks/useDirectMessage.ts +141 -0
  614. package/packages/dashboard/ui/react-components/hooks/useMessages.ts +309 -0
  615. package/packages/dashboard/ui/react-components/hooks/useOrchestrator.ts +364 -0
  616. package/packages/dashboard/ui/react-components/hooks/usePinnedAgents.ts +140 -0
  617. package/packages/dashboard/ui/react-components/hooks/usePresence.ts +340 -0
  618. package/packages/dashboard/ui/react-components/hooks/useRecentRepos.ts +130 -0
  619. package/packages/dashboard/ui/react-components/hooks/useSession.ts +209 -0
  620. package/packages/dashboard/ui/react-components/hooks/useTrajectory.ts +265 -0
  621. package/packages/dashboard/ui/react-components/hooks/useWebSocket.ts +169 -0
  622. package/packages/dashboard/ui/react-components/hooks/useWorkspaceMembers.ts +120 -0
  623. package/packages/dashboard/ui/react-components/hooks/useWorkspaceRepos.ts +73 -0
  624. package/packages/dashboard/ui/react-components/hooks/useWorkspaceStatus.ts +237 -0
  625. package/packages/dashboard/ui/react-components/index.ts +81 -0
  626. package/packages/dashboard/ui/react-components/layout/Header.tsx +355 -0
  627. package/packages/dashboard/ui/react-components/layout/RepoContextHeader.tsx +361 -0
  628. package/packages/dashboard/ui/react-components/layout/Sidebar.archive.test.tsx +126 -0
  629. package/packages/dashboard/ui/react-components/layout/Sidebar.test.tsx +691 -0
  630. package/packages/dashboard/ui/react-components/layout/Sidebar.tsx +930 -0
  631. package/packages/dashboard/ui/react-components/layout/index.ts +7 -0
  632. package/packages/dashboard/ui/react-components/settings/BillingSettingsPanel.tsx +564 -0
  633. package/packages/dashboard/ui/react-components/settings/SettingsPage.tsx +544 -0
  634. package/packages/dashboard/ui/react-components/settings/TeamSettingsPanel.tsx +560 -0
  635. package/packages/dashboard/ui/react-components/settings/WorkspaceSettingsPanel.tsx +1329 -0
  636. package/packages/dashboard/ui/react-components/settings/index.ts +11 -0
  637. package/packages/dashboard/ui/react-components/settings/types.ts +53 -0
  638. package/packages/dashboard/ui/react-components/utils/messageFormatting.tsx +370 -0
  639. package/packages/dashboard/ui/tailwind.config.js +148 -0
  640. package/packages/dashboard/ui/types/index.ts +304 -0
  641. package/packages/dashboard/ui/types/threading.ts +7 -0
  642. package/packages/dashboard/ui-dist/404.html +1 -0
  643. package/packages/dashboard/ui-dist/_next/static/HR7W9z1PPVPFqUboUVZFZ/_buildManifest.js +1 -0
  644. package/packages/dashboard/ui-dist/_next/static/HR7W9z1PPVPFqUboUVZFZ/_ssgManifest.js +1 -0
  645. package/packages/dashboard/ui-dist/_next/static/ZCFjHbkF8yDKS2md3lVgb/_buildManifest.js +1 -0
  646. package/packages/dashboard/ui-dist/_next/static/ZCFjHbkF8yDKS2md3lVgb/_ssgManifest.js +1 -0
  647. package/packages/dashboard/ui-dist/_next/static/chunks/116-a883fca163f3a5bc.js +1 -0
  648. package/packages/dashboard/ui-dist/_next/static/chunks/117-c8afed19e821a35d.js +2 -0
  649. package/packages/dashboard/ui-dist/_next/static/chunks/282-980c2eb8fff20123.js +1 -0
  650. package/packages/dashboard/ui-dist/_next/static/chunks/320-900169c942e31422.js +1 -0
  651. package/packages/dashboard/ui-dist/_next/static/chunks/532-bace199897eeab37.js +9 -0
  652. package/packages/dashboard/ui-dist/_next/static/chunks/631-af51bad94027527a.js +1 -0
  653. package/packages/dashboard/ui-dist/_next/static/chunks/648-acb2ff9f77cbfbd3.js +1 -0
  654. package/packages/dashboard/ui-dist/_next/static/chunks/677-30e60cb0b47875b6.js +1 -0
  655. package/packages/dashboard/ui-dist/_next/static/chunks/766-2aea80818f7eb0d8.js +1 -0
  656. package/packages/dashboard/ui-dist/_next/static/chunks/83-4f08122d4e7e79a6.js +1 -0
  657. package/packages/dashboard/ui-dist/_next/static/chunks/847-f1f467060f32afff.js +1 -0
  658. package/packages/dashboard/ui-dist/_next/static/chunks/891-5cb1513eeb97a891.js +1 -0
  659. package/packages/dashboard/ui-dist/_next/static/chunks/app/_not-found/page-60501fddbafba9dc.js +1 -0
  660. package/packages/dashboard/ui-dist/_next/static/chunks/app/app/onboarding/page-9914652442f7e4fb.js +1 -0
  661. package/packages/dashboard/ui-dist/_next/static/chunks/app/app/onboarding/page-f746f29e01fffc43.js +1 -0
  662. package/packages/dashboard/ui-dist/_next/static/chunks/app/app/page-2e525b1dcc790967.js +1 -0
  663. package/packages/dashboard/ui-dist/_next/static/chunks/app/app/page-44813aa26ad19681.js +1 -0
  664. package/packages/dashboard/ui-dist/_next/static/chunks/app/cloud/link/page-5011ae044b90449d.js +1 -0
  665. package/packages/dashboard/ui-dist/_next/static/chunks/app/cloud/link/page-fa1d5842aa90e8a6.js +1 -0
  666. package/packages/dashboard/ui-dist/_next/static/chunks/app/connect-repos/page-03ac6f35a6654ea6.js +1 -0
  667. package/packages/dashboard/ui-dist/_next/static/chunks/app/connect-repos/page-113060009ef35bc2.js +1 -0
  668. package/packages/dashboard/ui-dist/_next/static/chunks/app/history/page-9965d2483011b846.js +1 -0
  669. package/packages/dashboard/ui-dist/_next/static/chunks/app/history/page-b2ce7c96ed0931da.js +1 -0
  670. package/packages/dashboard/ui-dist/_next/static/chunks/app/layout-6b91e33784c20610.js +1 -0
  671. package/packages/dashboard/ui-dist/_next/static/chunks/app/layout-c0d118c0f92d969c.js +1 -0
  672. package/packages/dashboard/ui-dist/_next/static/chunks/app/login/page-6ec54eee75877971.js +1 -0
  673. package/packages/dashboard/ui-dist/_next/static/chunks/app/login/page-a0ca6f7ca6a100b8.js +1 -0
  674. package/packages/dashboard/ui-dist/_next/static/chunks/app/metrics/page-1e37ef8e73940b40.js +1 -0
  675. package/packages/dashboard/ui-dist/_next/static/chunks/app/metrics/page-bf2cb1e5915bc92d.js +1 -0
  676. package/packages/dashboard/ui-dist/_next/static/chunks/app/page-4e64923d73c35bc9.js +1 -0
  677. package/packages/dashboard/ui-dist/_next/static/chunks/app/page-7993778218818ace.js +1 -0
  678. package/packages/dashboard/ui-dist/_next/static/chunks/app/pricing/page-0efa024c28ba4597.js +1 -0
  679. package/packages/dashboard/ui-dist/_next/static/chunks/app/pricing/page-9db3ebdfa567a7c9.js +1 -0
  680. package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/page-bcf46064ac4474ce.js +1 -0
  681. package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/page-e65a0010da6ea5be.js +1 -0
  682. package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/setup/[provider]/page-4dbe33f0f7691b7c.js +1 -0
  683. package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/setup/[provider]/page-84161c802b020a1f.js +1 -0
  684. package/packages/dashboard/ui-dist/_next/static/chunks/app/signup/page-18a4665665f6be11.js +1 -0
  685. package/packages/dashboard/ui-dist/_next/static/chunks/app/signup/page-1ede2205b58649ca.js +1 -0
  686. package/packages/dashboard/ui-dist/_next/static/chunks/e868780c-48e5f147c90a3a41.js +18 -0
  687. package/packages/dashboard/ui-dist/_next/static/chunks/fd9d1056-609918ca7b6280bb.js +1 -0
  688. package/packages/dashboard/ui-dist/_next/static/chunks/framework-f66176bb897dc684.js +1 -0
  689. package/packages/dashboard/ui-dist/_next/static/chunks/main-5a40a5ae29646e1b.js +1 -0
  690. package/packages/dashboard/ui-dist/_next/static/chunks/main-app-6e8e8d3ef4e0192a.js +1 -0
  691. package/packages/dashboard/ui-dist/_next/static/chunks/main-app-fdbeb09028f57c9f.js +1 -0
  692. package/packages/dashboard/ui-dist/_next/static/chunks/pages/_app-72b849fbd24ac258.js +1 -0
  693. package/packages/dashboard/ui-dist/_next/static/chunks/pages/_error-7ba65e1336b92748.js +1 -0
  694. package/packages/dashboard/ui-dist/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  695. package/packages/dashboard/ui-dist/_next/static/chunks/webpack-1cdd8ed57114d5e1.js +1 -0
  696. package/packages/dashboard/ui-dist/_next/static/css/4034f236dd1a3178.css +1 -0
  697. package/packages/dashboard/ui-dist/_next/static/css/99c2552394077586.css +1 -0
  698. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-128.png +0 -0
  699. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-256.png +0 -0
  700. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-32.png +0 -0
  701. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-512.png +0 -0
  702. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-64.png +0 -0
  703. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo.svg +45 -0
  704. package/packages/dashboard/ui-dist/alt-logos/logo.svg +38 -0
  705. package/packages/dashboard/ui-dist/alt-logos/monogram-logo-128.png +0 -0
  706. package/packages/dashboard/ui-dist/alt-logos/monogram-logo-256.png +0 -0
  707. package/packages/dashboard/ui-dist/alt-logos/monogram-logo-32.png +0 -0
  708. package/packages/dashboard/ui-dist/alt-logos/monogram-logo-512.png +0 -0
  709. package/packages/dashboard/ui-dist/alt-logos/monogram-logo-64.png +0 -0
  710. package/packages/dashboard/ui-dist/alt-logos/monogram-logo.svg +38 -0
  711. package/packages/dashboard/ui-dist/app/onboarding.html +1 -0
  712. package/packages/dashboard/ui-dist/app/onboarding.txt +7 -0
  713. package/packages/dashboard/ui-dist/app.html +1 -0
  714. package/packages/dashboard/ui-dist/app.txt +7 -0
  715. package/packages/dashboard/ui-dist/apple-icon.png +0 -0
  716. package/packages/dashboard/ui-dist/cloud/link.html +1 -0
  717. package/packages/dashboard/ui-dist/cloud/link.txt +7 -0
  718. package/packages/dashboard/ui-dist/connect-repos.html +1 -0
  719. package/packages/dashboard/ui-dist/connect-repos.txt +7 -0
  720. package/packages/dashboard/ui-dist/history.html +1 -0
  721. package/packages/dashboard/ui-dist/history.txt +7 -0
  722. package/packages/dashboard/ui-dist/index.html +1 -0
  723. package/packages/dashboard/ui-dist/index.txt +7 -0
  724. package/packages/dashboard/ui-dist/login.html +5 -0
  725. package/packages/dashboard/ui-dist/login.txt +7 -0
  726. package/packages/dashboard/ui-dist/metrics.html +1 -0
  727. package/packages/dashboard/ui-dist/metrics.txt +7 -0
  728. package/packages/dashboard/ui-dist/pricing.html +13 -0
  729. package/packages/dashboard/ui-dist/pricing.txt +7 -0
  730. package/packages/dashboard/ui-dist/providers/setup/claude.html +1 -0
  731. package/packages/dashboard/ui-dist/providers/setup/claude.txt +8 -0
  732. package/packages/dashboard/ui-dist/providers/setup/codex.html +1 -0
  733. package/packages/dashboard/ui-dist/providers/setup/codex.txt +8 -0
  734. package/packages/dashboard/ui-dist/providers/setup/cursor.html +1 -0
  735. package/packages/dashboard/ui-dist/providers/setup/cursor.txt +8 -0
  736. package/packages/dashboard/ui-dist/providers.html +1 -0
  737. package/packages/dashboard/ui-dist/providers.txt +7 -0
  738. package/packages/dashboard/ui-dist/signup.html +6 -0
  739. package/packages/dashboard/ui-dist/signup.txt +7 -0
  740. package/packages/dashboard-server/dist/health-worker-manager.d.ts +62 -0
  741. package/packages/dashboard-server/dist/health-worker-manager.js +144 -0
  742. package/packages/dashboard-server/dist/health-worker.d.ts +9 -0
  743. package/packages/dashboard-server/dist/health-worker.js +79 -0
  744. package/packages/dashboard-server/dist/index.d.ts +18 -0
  745. package/packages/dashboard-server/dist/index.js +17 -0
  746. package/packages/dashboard-server/dist/server.js +5099 -0
  747. package/packages/dashboard-server/dist/start.js +13 -0
  748. package/packages/dashboard-server/dist/types/threading.d.ts +8 -0
  749. package/packages/dashboard-server/dist/types/threading.js +2 -0
  750. package/packages/dashboard-server/dist/user-bridge.d.ts +154 -0
  751. package/packages/dashboard-server/dist/user-bridge.js +372 -0
  752. package/packages/dashboard-server/package.json +49 -0
  753. package/packages/hooks/dist/browser.d.ts +2 -0
  754. package/packages/hooks/dist/browser.js +3 -0
  755. package/packages/hooks/dist/index.d.ts +11 -0
  756. package/packages/hooks/dist/index.js +11 -0
  757. package/packages/hooks/dist/registry.js +476 -0
  758. package/packages/hooks/dist/trajectory-hooks.js +183 -0
  759. package/packages/hooks/dist/types.d.ts +285 -0
  760. package/packages/hooks/dist/types.js +10 -0
  761. package/packages/hooks/package.json +52 -0
  762. package/packages/mcp/LICENSE +190 -0
  763. package/packages/mcp/README.md +214 -0
  764. package/packages/mcp/SPEC.md +1922 -0
  765. package/packages/mcp/STAFFING_PLAN.md +294 -0
  766. package/packages/mcp/dist/bin.d.ts +12 -0
  767. package/packages/mcp/dist/bin.js +127 -0
  768. package/packages/mcp/dist/client.d.ts +68 -0
  769. package/packages/mcp/dist/client.js +115 -0
  770. package/packages/mcp/dist/cloud.d.ts +108 -0
  771. package/packages/mcp/dist/cloud.js +279 -0
  772. package/packages/mcp/dist/errors.d.ts +27 -0
  773. package/packages/mcp/dist/errors.js +48 -0
  774. package/packages/mcp/dist/index.d.ts +10 -0
  775. package/packages/mcp/dist/index.js +16 -0
  776. package/packages/mcp/dist/install-cli.d.ts +35 -0
  777. package/packages/mcp/dist/install-cli.js +157 -0
  778. package/packages/mcp/dist/install.d.ts +101 -0
  779. package/packages/mcp/dist/install.js +398 -0
  780. package/packages/mcp/dist/prompts/index.d.ts +2 -0
  781. package/packages/mcp/dist/prompts/index.js +2 -0
  782. package/packages/mcp/dist/prompts/protocol.d.ts +11 -0
  783. package/packages/mcp/dist/prompts/protocol.js +168 -0
  784. package/packages/mcp/dist/resources/agents.d.ts +11 -0
  785. package/packages/mcp/dist/resources/agents.js +17 -0
  786. package/packages/mcp/dist/resources/inbox.d.ts +11 -0
  787. package/packages/mcp/dist/resources/inbox.js +17 -0
  788. package/packages/mcp/dist/resources/index.d.ts +4 -0
  789. package/packages/mcp/dist/resources/index.js +4 -0
  790. package/packages/mcp/dist/resources/project.d.ts +11 -0
  791. package/packages/mcp/dist/resources/project.js +21 -0
  792. package/packages/mcp/dist/server.d.ts +19 -0
  793. package/packages/mcp/dist/server.js +215 -0
  794. package/packages/mcp/dist/simple.d.ts +173 -0
  795. package/packages/mcp/dist/simple.js +120 -0
  796. package/packages/mcp/dist/tools/index.d.ts +10 -0
  797. package/packages/mcp/dist/tools/index.js +10 -0
  798. package/packages/mcp/dist/tools/relay-health.d.ts +23 -0
  799. package/packages/mcp/dist/tools/relay-health.js +138 -0
  800. package/packages/mcp/dist/tools/relay-inbox.d.ts +26 -0
  801. package/packages/mcp/dist/tools/relay-inbox.js +58 -0
  802. package/packages/mcp/dist/tools/relay-logs.d.ts +20 -0
  803. package/packages/mcp/dist/tools/relay-logs.js +88 -0
  804. package/packages/mcp/dist/tools/relay-metrics.d.ts +20 -0
  805. package/packages/mcp/dist/tools/relay-metrics.js +135 -0
  806. package/packages/mcp/dist/tools/relay-release.d.ts +20 -0
  807. package/packages/mcp/dist/tools/relay-release.js +44 -0
  808. package/packages/mcp/dist/tools/relay-send.d.ts +29 -0
  809. package/packages/mcp/dist/tools/relay-send.js +71 -0
  810. package/packages/mcp/dist/tools/relay-spawn.d.ts +36 -0
  811. package/packages/mcp/dist/tools/relay-spawn.js +73 -0
  812. package/packages/mcp/dist/tools/relay-status.d.ts +11 -0
  813. package/packages/mcp/dist/tools/relay-status.js +43 -0
  814. package/packages/mcp/dist/tools/relay-who.d.ts +20 -0
  815. package/packages/mcp/dist/tools/relay-who.js +47 -0
  816. package/packages/mcp/package.json +69 -0
  817. package/packages/memory/dist/memory-hooks.d.ts +60 -0
  818. package/packages/memory/package.json +35 -0
  819. package/packages/policy/dist/agent-policy.js +665 -0
  820. package/packages/policy/dist/index.d.ts +12 -0
  821. package/packages/policy/dist/index.js +12 -0
  822. package/packages/policy/package.json +35 -0
  823. package/packages/protocol/dist/channels.d.ts +137 -0
  824. package/packages/protocol/dist/channels.js +154 -0
  825. package/packages/protocol/dist/framing.d.ts +80 -0
  826. package/packages/protocol/dist/framing.js +206 -0
  827. package/packages/protocol/dist/index.d.ts +5 -0
  828. package/packages/protocol/dist/index.js +5 -0
  829. package/packages/protocol/dist/relay-pty-schemas.d.ts +258 -0
  830. package/packages/protocol/dist/types.d.ts +341 -0
  831. package/packages/protocol/dist/types.js +8 -0
  832. package/packages/protocol/package.json +56 -0
  833. package/packages/resiliency/dist/memory-monitor.js +599 -0
  834. package/packages/resiliency/dist/provider-context.d.ts +100 -0
  835. package/packages/resiliency/package.json +33 -0
  836. package/packages/sdk/README.md +171 -0
  837. package/packages/sdk/dist/client.d.ts +181 -0
  838. package/packages/sdk/dist/client.js +695 -0
  839. package/packages/sdk/dist/index.d.ts +32 -0
  840. package/packages/sdk/dist/index.js +36 -0
  841. package/packages/sdk/dist/protocol/framing.d.ts +80 -0
  842. package/packages/sdk/dist/protocol/framing.js +206 -0
  843. package/packages/sdk/dist/protocol/index.d.ts +6 -0
  844. package/packages/sdk/dist/protocol/index.js +6 -0
  845. package/packages/sdk/dist/protocol/types.d.ts +341 -0
  846. package/packages/sdk/dist/protocol/types.js +8 -0
  847. package/packages/sdk/dist/standalone.d.ts +87 -0
  848. package/packages/sdk/dist/standalone.js +126 -0
  849. package/packages/sdk/package.json +80 -0
  850. package/packages/spawner/API.md +256 -0
  851. package/packages/spawner/dist/index.d.ts +8 -0
  852. package/packages/spawner/dist/index.js +8 -0
  853. package/packages/spawner/dist/types.d.ts +552 -0
  854. package/packages/spawner/dist/types.js +193 -0
  855. package/packages/spawner/package.json +47 -0
  856. package/packages/state/dist/agent-state.js +120 -0
  857. package/packages/state/dist/index.d.ts +8 -0
  858. package/packages/state/dist/index.js +8 -0
  859. package/packages/state/package.json +32 -0
  860. package/packages/storage/dist/adapter.d.ts +156 -0
  861. package/packages/storage/dist/batched-sqlite-adapter.d.ts +75 -0
  862. package/packages/storage/dist/batched-sqlite-adapter.js +189 -0
  863. package/packages/storage/dist/index.d.ts +5 -0
  864. package/packages/storage/dist/index.js +6 -0
  865. package/packages/storage/dist/sqlite-adapter.d.ts +113 -0
  866. package/packages/storage/dist/sqlite-adapter.js +752 -0
  867. package/packages/storage/package.json +69 -0
  868. package/packages/trajectory/dist/index.d.ts +2 -0
  869. package/packages/trajectory/dist/index.js +2 -0
  870. package/packages/trajectory/dist/integration.js +987 -0
  871. package/packages/trajectory/package.json +35 -0
  872. package/packages/user-directory/dist/index.d.ts +7 -0
  873. package/packages/user-directory/dist/index.js +7 -0
  874. package/packages/user-directory/dist/user-directory.d.ts +121 -0
  875. package/packages/user-directory/dist/user-directory.js +267 -0
  876. package/packages/user-directory/package.json +35 -0
  877. package/packages/utils/dist/command-resolver.js +80 -0
  878. package/packages/utils/dist/error-tracking.d.ts +103 -0
  879. package/packages/utils/dist/error-tracking.js +149 -0
  880. package/packages/utils/dist/index.d.ts +9 -0
  881. package/packages/utils/dist/index.js +9 -0
  882. package/packages/utils/dist/model-mapping.d.ts +28 -0
  883. package/packages/utils/dist/model-mapping.js +55 -0
  884. package/packages/utils/package.json +75 -0
  885. package/packages/wrapper/dist/__fixtures__/claude-outputs.d.ts +49 -0
  886. package/packages/wrapper/dist/__fixtures__/claude-outputs.js +443 -0
  887. package/packages/wrapper/dist/__fixtures__/codex-outputs.d.ts +9 -0
  888. package/packages/wrapper/dist/__fixtures__/codex-outputs.js +94 -0
  889. package/packages/wrapper/dist/__fixtures__/gemini-outputs.d.ts +19 -0
  890. package/packages/wrapper/dist/__fixtures__/gemini-outputs.js +144 -0
  891. package/packages/wrapper/dist/__fixtures__/index.d.ts +68 -0
  892. package/packages/wrapper/dist/__fixtures__/index.js +44 -0
  893. package/packages/wrapper/dist/base-wrapper.d.ts +225 -0
  894. package/packages/wrapper/dist/base-wrapper.js +572 -0
  895. package/packages/wrapper/dist/client.d.ts +254 -0
  896. package/packages/wrapper/dist/client.js +801 -0
  897. package/packages/wrapper/dist/id-generator.d.ts +35 -0
  898. package/packages/wrapper/dist/id-generator.js +60 -0
  899. package/packages/wrapper/dist/idle-detector.d.ts +110 -0
  900. package/packages/wrapper/dist/idle-detector.js +304 -0
  901. package/packages/wrapper/dist/index.d.ts +37 -0
  902. package/packages/wrapper/dist/index.js +47 -0
  903. package/packages/wrapper/dist/parser.d.ts +236 -0
  904. package/packages/wrapper/dist/parser.js +1238 -0
  905. package/packages/wrapper/dist/relay-pty-orchestrator.d.ts +407 -0
  906. package/packages/wrapper/dist/relay-pty-orchestrator.js +1885 -0
  907. package/packages/wrapper/dist/shared.d.ts +201 -0
  908. package/packages/wrapper/dist/shared.js +341 -0
  909. package/packages/wrapper/dist/stuck-detector.d.ts +161 -0
  910. package/packages/wrapper/dist/stuck-detector.js +402 -0
  911. package/packages/wrapper/dist/tmux-wrapper.d.ts +345 -0
  912. package/packages/wrapper/dist/tmux-wrapper.js +1747 -0
  913. package/packages/wrapper/dist/trajectory-integration.d.ts +292 -0
  914. package/packages/wrapper/dist/trajectory-integration.js +979 -0
  915. package/packages/wrapper/dist/wrapper-types.d.ts +41 -0
  916. package/packages/wrapper/dist/wrapper-types.js +7 -0
  917. package/packages/wrapper/package.json +63 -0
  918. package/scripts/setup-stripe-products.ts +312 -0
  919. package/scripts/stress-test-orchestrator-integration.mts +1366 -0
  920. package/scripts/stress-test-orchestrator.mjs +584 -0
  921. package/scripts/stress-test-relay-pty.sh +452 -0
  922. package/scripts/verify-schema.js +1 -1
  923. package/turbo.json +37 -0
  924. package/dist/bridge/config.d.ts +0 -41
  925. package/dist/bridge/config.js +0 -143
  926. package/dist/bridge/index.d.ts +0 -10
  927. package/dist/bridge/index.js +0 -10
  928. package/dist/bridge/multi-project-client.d.ts +0 -99
  929. package/dist/bridge/multi-project-client.js +0 -389
  930. package/dist/bridge/shadow-cli.js +0 -75
  931. package/dist/bridge/shadow-config.d.ts +0 -87
  932. package/dist/bridge/spawner.d.ts +0 -186
  933. package/dist/bridge/spawner.js +0 -920
  934. package/dist/bridge/types.d.ts +0 -129
  935. package/dist/bridge/utils.d.ts +0 -30
  936. package/dist/bridge/utils.js +0 -54
  937. package/dist/cli/index.js +0 -2784
  938. package/dist/cloud/api/admin.js +0 -225
  939. package/dist/cloud/api/billing.js +0 -564
  940. package/dist/cloud/api/cli-pty-runner.d.ts +0 -54
  941. package/dist/cloud/api/cli-pty-runner.js +0 -119
  942. package/dist/cloud/api/codex-auth-helper.js +0 -327
  943. package/dist/cloud/api/consensus.js +0 -259
  944. package/dist/cloud/api/coordinators.js +0 -749
  945. package/dist/cloud/api/daemons.js +0 -535
  946. package/dist/cloud/api/generic-webhooks.js +0 -129
  947. package/dist/cloud/api/github-app.js +0 -223
  948. package/dist/cloud/api/monitoring.js +0 -578
  949. package/dist/cloud/api/nango-auth.js +0 -658
  950. package/dist/cloud/api/onboarding.d.ts +0 -15
  951. package/dist/cloud/api/onboarding.js +0 -666
  952. package/dist/cloud/api/policy.js +0 -229
  953. package/dist/cloud/api/provider-env.d.ts +0 -5
  954. package/dist/cloud/api/provider-env.js +0 -27
  955. package/dist/cloud/api/providers.js +0 -511
  956. package/dist/cloud/api/repos.js +0 -576
  957. package/dist/cloud/api/teams.js +0 -279
  958. package/dist/cloud/api/test-helpers.js +0 -745
  959. package/dist/cloud/api/workspaces.js +0 -1783
  960. package/dist/cloud/billing/plans.js +0 -245
  961. package/dist/cloud/config.d.ts +0 -75
  962. package/dist/cloud/config.js +0 -109
  963. package/dist/cloud/db/drizzle.d.ts +0 -246
  964. package/dist/cloud/db/drizzle.js +0 -1249
  965. package/dist/cloud/db/schema.d.ts +0 -4854
  966. package/dist/cloud/db/schema.js +0 -610
  967. package/dist/cloud/index.d.ts +0 -11
  968. package/dist/cloud/index.js +0 -38
  969. package/dist/cloud/provisioner/index.d.ts +0 -207
  970. package/dist/cloud/provisioner/index.js +0 -2069
  971. package/dist/cloud/server.js +0 -1599
  972. package/dist/cloud/services/index.d.ts +0 -17
  973. package/dist/cloud/services/index.js +0 -25
  974. package/dist/cloud/services/intro-expiration.d.ts +0 -55
  975. package/dist/cloud/services/intro-expiration.js +0 -211
  976. package/dist/cloud/services/nango.d.ts +0 -199
  977. package/dist/cloud/services/nango.js +0 -382
  978. package/dist/cloud/services/persistence.d.ts +0 -131
  979. package/dist/config/relay-config.d.ts +0 -23
  980. package/dist/config/relay-config.js +0 -23
  981. package/dist/continuity/index.d.ts +0 -45
  982. package/dist/continuity/index.js +0 -48
  983. package/dist/continuity/types.d.ts +0 -180
  984. package/dist/continuity/types.js +0 -9
  985. package/dist/daemon/agent-manager.d.ts +0 -134
  986. package/dist/daemon/agent-manager.js +0 -564
  987. package/dist/daemon/agent-registry.js +0 -213
  988. package/dist/daemon/api.d.ts +0 -83
  989. package/dist/daemon/api.js +0 -780
  990. package/dist/daemon/channel-membership-store.d.ts +0 -48
  991. package/dist/daemon/channel-membership-store.js +0 -149
  992. package/dist/daemon/cli-auth.d.ts +0 -82
  993. package/dist/daemon/cli-auth.js +0 -700
  994. package/dist/daemon/cloud-sync.d.ts +0 -150
  995. package/dist/daemon/cloud-sync.js +0 -424
  996. package/dist/daemon/connection.d.ts +0 -130
  997. package/dist/daemon/connection.js +0 -438
  998. package/dist/daemon/consensus-integration.js +0 -371
  999. package/dist/daemon/delivery-tracker.d.ts +0 -34
  1000. package/dist/daemon/delivery-tracker.js +0 -104
  1001. package/dist/daemon/enhanced-features.d.ts +0 -118
  1002. package/dist/daemon/enhanced-features.js +0 -178
  1003. package/dist/daemon/index.d.ts +0 -14
  1004. package/dist/daemon/index.js +0 -17
  1005. package/dist/daemon/orchestrator.d.ts +0 -157
  1006. package/dist/daemon/orchestrator.js +0 -792
  1007. package/dist/daemon/repo-manager.js +0 -384
  1008. package/dist/daemon/router.d.ts +0 -358
  1009. package/dist/daemon/router.js +0 -1333
  1010. package/dist/daemon/server.d.ts +0 -159
  1011. package/dist/daemon/server.js +0 -788
  1012. package/dist/daemon/services/browser-testing.d.ts +0 -88
  1013. package/dist/daemon/services/browser-testing.js +0 -244
  1014. package/dist/daemon/services/container-spawner.d.ts +0 -135
  1015. package/dist/daemon/services/container-spawner.js +0 -313
  1016. package/dist/daemon/sync-queue.d.ts +0 -116
  1017. package/dist/daemon/sync-queue.js +0 -361
  1018. package/dist/daemon/types.d.ts +0 -131
  1019. package/dist/daemon/user-directory.d.ts +0 -111
  1020. package/dist/daemon/user-directory.js +0 -233
  1021. package/dist/daemon/workspace-manager.js +0 -314
  1022. package/dist/dashboard/out/_next/static/chunks/116-eacf84a131b80db9.js +0 -1
  1023. package/dist/dashboard/out/_next/static/chunks/64-f4268c2ac6f4d7d4.js +0 -1
  1024. package/dist/dashboard/out/_next/static/chunks/766-aa7c8c9900ff5f53.js +0 -1
  1025. package/dist/dashboard/out/_next/static/chunks/891-a024fbe4b619cf6f.js +0 -1
  1026. package/dist/dashboard/out/_next/static/chunks/app/app/page-ffad986adfcc8b31.js +0 -1
  1027. package/dist/dashboard/out/_next/static/chunks/app/page-671037943b2f2e43.js +0 -1
  1028. package/dist/dashboard/out/_next/static/chunks/app/providers/page-57cbd738c6a73859.js +0 -1
  1029. package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-5ab0854472b402b0.js +0 -1
  1030. package/dist/dashboard/out/_next/static/css/8f9ed310f454e5a5.css +0 -1
  1031. package/dist/dashboard-server/server.js +0 -4806
  1032. package/dist/dashboard-server/start.js +0 -13
  1033. package/dist/dashboard-server/user-bridge.d.ts +0 -138
  1034. package/dist/dashboard-server/user-bridge.js +0 -348
  1035. package/dist/hooks/index.d.ts +0 -10
  1036. package/dist/hooks/index.js +0 -10
  1037. package/dist/hooks/registry.js +0 -476
  1038. package/dist/hooks/trajectory-hooks.js +0 -183
  1039. package/dist/hooks/types.d.ts +0 -284
  1040. package/dist/hooks/types.js +0 -8
  1041. package/dist/index.d.ts +0 -13
  1042. package/dist/index.js +0 -16
  1043. package/dist/memory/memory-hooks.d.ts +0 -60
  1044. package/dist/policy/agent-policy.js +0 -665
  1045. package/dist/protocol/channels.d.ts +0 -211
  1046. package/dist/protocol/channels.js +0 -154
  1047. package/dist/protocol/framing.d.ts +0 -94
  1048. package/dist/protocol/framing.js +0 -240
  1049. package/dist/protocol/index.d.ts +0 -4
  1050. package/dist/protocol/index.js +0 -4
  1051. package/dist/protocol/relay-pty-schemas.d.ts +0 -209
  1052. package/dist/protocol/types.d.ts +0 -168
  1053. package/dist/protocol/types.js +0 -6
  1054. package/dist/resiliency/memory-monitor.js +0 -593
  1055. package/dist/resiliency/provider-context.d.ts +0 -100
  1056. package/dist/shared/cli-auth-config.js +0 -320
  1057. package/dist/state/agent-state.js +0 -120
  1058. package/dist/storage/adapter.d.ts +0 -154
  1059. package/dist/storage/batched-sqlite-adapter.d.ts +0 -71
  1060. package/dist/storage/batched-sqlite-adapter.js +0 -183
  1061. package/dist/storage/sqlite-adapter.d.ts +0 -107
  1062. package/dist/storage/sqlite-adapter.js +0 -717
  1063. package/dist/trajectory/config.d.ts +0 -102
  1064. package/dist/trajectory/config.js +0 -185
  1065. package/dist/trajectory/index.d.ts +0 -8
  1066. package/dist/trajectory/index.js +0 -8
  1067. package/dist/trajectory/integration.js +0 -987
  1068. package/dist/utils/command-resolver.js +0 -76
  1069. package/dist/utils/index.d.ts +0 -4
  1070. package/dist/utils/index.js +0 -4
  1071. package/dist/utils/project-namespace.d.ts +0 -70
  1072. package/dist/utils/project-namespace.js +0 -216
  1073. package/dist/wrapper/base-wrapper.d.ts +0 -217
  1074. package/dist/wrapper/base-wrapper.js +0 -538
  1075. package/dist/wrapper/client.d.ts +0 -199
  1076. package/dist/wrapper/client.js +0 -677
  1077. package/dist/wrapper/idle-detector.d.ts +0 -102
  1078. package/dist/wrapper/idle-detector.js +0 -279
  1079. package/dist/wrapper/index.d.ts +0 -4
  1080. package/dist/wrapper/index.js +0 -7
  1081. package/dist/wrapper/parser.d.ts +0 -230
  1082. package/dist/wrapper/parser.js +0 -1178
  1083. package/dist/wrapper/pty-wrapper.d.ts +0 -343
  1084. package/dist/wrapper/pty-wrapper.js +0 -1593
  1085. package/dist/wrapper/relay-pty-orchestrator.d.ts +0 -296
  1086. package/dist/wrapper/relay-pty-orchestrator.js +0 -1088
  1087. package/dist/wrapper/shared.d.ts +0 -168
  1088. package/dist/wrapper/shared.js +0 -291
  1089. package/dist/wrapper/stuck-detector.d.ts +0 -101
  1090. package/dist/wrapper/stuck-detector.js +0 -228
  1091. package/dist/wrapper/tmux-wrapper.d.ts +0 -344
  1092. package/dist/wrapper/tmux-wrapper.js +0 -1711
  1093. /package/dist/dashboard/out/_next/static/{BffXAqxm-_rUlj2mAnK26 → ZCFjHbkF8yDKS2md3lVgb}/_buildManifest.js +0 -0
  1094. /package/dist/dashboard/out/_next/static/{BffXAqxm-_rUlj2mAnK26 → ZCFjHbkF8yDKS2md3lVgb}/_ssgManifest.js +0 -0
  1095. /package/dist/dashboard/out/_next/static/chunks/app/cloud/link/{page-cfeb437f08a12ed9.js → page-5011ae044b90449d.js} +0 -0
  1096. /package/dist/dashboard/out/_next/static/chunks/app/history/{page-240f91e8b06ba8ac.js → page-b2ce7c96ed0931da.js} +0 -0
  1097. /package/dist/dashboard/out/_next/static/chunks/app/metrics/{page-82938ab8fcf44694.js → page-bf2cb1e5915bc92d.js} +0 -0
  1098. /package/dist/{cli → src/cli}/index.d.ts +0 -0
  1099. /package/dist/{health-worker-manager.d.ts → src/health-worker-manager.d.ts} +0 -0
  1100. /package/dist/{health-worker-manager.js → src/health-worker-manager.js} +0 -0
  1101. /package/dist/{health-worker.d.ts → src/health-worker.d.ts} +0 -0
  1102. /package/dist/{health-worker.js → src/health-worker.js} +0 -0
  1103. /package/{dist/bridge → packages/bridge/dist}/shadow-cli.d.ts +0 -0
  1104. /package/{dist/bridge → packages/bridge/dist}/types.js +0 -0
  1105. /package/{dist/cloud → packages/cloud/dist}/api/admin.d.ts +0 -0
  1106. /package/{dist/cloud → packages/cloud/dist}/api/auth.d.ts +0 -0
  1107. /package/{dist/cloud → packages/cloud/dist}/api/auth.js +0 -0
  1108. /package/{dist/cloud → packages/cloud/dist}/api/billing.d.ts +0 -0
  1109. /package/{dist/cloud → packages/cloud/dist}/api/codex-auth-helper.d.ts +0 -0
  1110. /package/{dist/cloud → packages/cloud/dist}/api/consensus.d.ts +0 -0
  1111. /package/{dist/cloud → packages/cloud/dist}/api/coordinators.d.ts +0 -0
  1112. /package/{dist/cloud → packages/cloud/dist}/api/daemons.d.ts +0 -0
  1113. /package/{dist/cloud → packages/cloud/dist}/api/generic-webhooks.d.ts +0 -0
  1114. /package/{dist/cloud → packages/cloud/dist}/api/git.d.ts +0 -0
  1115. /package/{dist/cloud → packages/cloud/dist}/api/git.js +0 -0
  1116. /package/{dist/cloud → packages/cloud/dist}/api/github-app.d.ts +0 -0
  1117. /package/{dist/cloud → packages/cloud/dist}/api/middleware/planLimits.d.ts +0 -0
  1118. /package/{dist/cloud → packages/cloud/dist}/api/middleware/planLimits.js +0 -0
  1119. /package/{dist/cloud → packages/cloud/dist}/api/monitoring.d.ts +0 -0
  1120. /package/{dist/cloud → packages/cloud/dist}/api/nango-auth.d.ts +0 -0
  1121. /package/{dist/cloud → packages/cloud/dist}/api/policy.d.ts +0 -0
  1122. /package/{dist/cloud → packages/cloud/dist}/api/providers.d.ts +0 -0
  1123. /package/{dist/cloud → packages/cloud/dist}/api/repos.d.ts +0 -0
  1124. /package/{dist/cloud → packages/cloud/dist}/api/teams.d.ts +0 -0
  1125. /package/{dist/cloud → packages/cloud/dist}/api/test-helpers.d.ts +0 -0
  1126. /package/{dist/cloud → packages/cloud/dist}/api/usage.d.ts +0 -0
  1127. /package/{dist/cloud → packages/cloud/dist}/api/usage.js +0 -0
  1128. /package/{dist/cloud → packages/cloud/dist}/api/webhooks.d.ts +0 -0
  1129. /package/{dist/cloud → packages/cloud/dist}/api/webhooks.js +0 -0
  1130. /package/{dist/cloud → packages/cloud/dist}/api/workspaces.d.ts +0 -0
  1131. /package/{dist/cloud → packages/cloud/dist}/billing/index.d.ts +0 -0
  1132. /package/{dist/cloud → packages/cloud/dist}/billing/index.js +0 -0
  1133. /package/{dist/cloud → packages/cloud/dist}/billing/plans.d.ts +0 -0
  1134. /package/{dist/cloud → packages/cloud/dist}/billing/service.d.ts +0 -0
  1135. /package/{dist/cloud → packages/cloud/dist}/billing/service.js +0 -0
  1136. /package/{dist/cloud → packages/cloud/dist}/billing/types.d.ts +0 -0
  1137. /package/{dist/cloud → packages/cloud/dist}/billing/types.js +0 -0
  1138. /package/{dist/cloud → packages/cloud/dist}/db/bulk-ingest.d.ts +0 -0
  1139. /package/{dist/cloud → packages/cloud/dist}/db/bulk-ingest.js +0 -0
  1140. /package/{dist/cloud → packages/cloud/dist}/db/index.d.ts +0 -0
  1141. /package/{dist/cloud → packages/cloud/dist}/db/index.js +0 -0
  1142. /package/{dist/cloud → packages/cloud/dist}/server.d.ts +0 -0
  1143. /package/{dist/cloud → packages/cloud/dist}/services/auto-scaler.d.ts +0 -0
  1144. /package/{dist/cloud → packages/cloud/dist}/services/auto-scaler.js +0 -0
  1145. /package/{dist/cloud → packages/cloud/dist}/services/capacity-manager.d.ts +0 -0
  1146. /package/{dist/cloud → packages/cloud/dist}/services/capacity-manager.js +0 -0
  1147. /package/{dist/cloud → packages/cloud/dist}/services/ci-agent-spawner.d.ts +0 -0
  1148. /package/{dist/cloud → packages/cloud/dist}/services/ci-agent-spawner.js +0 -0
  1149. /package/{dist/cloud → packages/cloud/dist}/services/cloud-message-bus.d.ts +0 -0
  1150. /package/{dist/cloud → packages/cloud/dist}/services/cloud-message-bus.js +0 -0
  1151. /package/{dist/cloud → packages/cloud/dist}/services/compute-enforcement.d.ts +0 -0
  1152. /package/{dist/cloud → packages/cloud/dist}/services/compute-enforcement.js +0 -0
  1153. /package/{dist/cloud → packages/cloud/dist}/services/coordinator.d.ts +0 -0
  1154. /package/{dist/cloud → packages/cloud/dist}/services/coordinator.js +0 -0
  1155. /package/{dist/cloud → packages/cloud/dist}/services/mention-handler.d.ts +0 -0
  1156. /package/{dist/cloud → packages/cloud/dist}/services/mention-handler.js +0 -0
  1157. /package/{dist/cloud → packages/cloud/dist}/services/persistence.js +0 -0
  1158. /package/{dist/cloud → packages/cloud/dist}/services/planLimits.d.ts +0 -0
  1159. /package/{dist/cloud → packages/cloud/dist}/services/planLimits.js +0 -0
  1160. /package/{dist/cloud → packages/cloud/dist}/services/presence-registry.d.ts +0 -0
  1161. /package/{dist/cloud → packages/cloud/dist}/services/presence-registry.js +0 -0
  1162. /package/{dist/cloud → packages/cloud/dist}/services/scaling-orchestrator.d.ts +0 -0
  1163. /package/{dist/cloud → packages/cloud/dist}/services/scaling-orchestrator.js +0 -0
  1164. /package/{dist/cloud → packages/cloud/dist}/services/scaling-policy.d.ts +0 -0
  1165. /package/{dist/cloud → packages/cloud/dist}/services/scaling-policy.js +0 -0
  1166. /package/{dist/cloud → packages/cloud/dist}/services/ssh-security.d.ts +0 -0
  1167. /package/{dist/cloud → packages/cloud/dist}/services/ssh-security.js +0 -0
  1168. /package/{dist/cloud → packages/cloud/dist}/services/workspace-keepalive.d.ts +0 -0
  1169. /package/{dist/cloud → packages/cloud/dist}/services/workspace-keepalive.js +0 -0
  1170. /package/{dist/cloud → packages/cloud/dist}/webhooks/index.d.ts +0 -0
  1171. /package/{dist/cloud → packages/cloud/dist}/webhooks/index.js +0 -0
  1172. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/github.d.ts +0 -0
  1173. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/github.js +0 -0
  1174. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/index.d.ts +0 -0
  1175. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/index.js +0 -0
  1176. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/linear.d.ts +0 -0
  1177. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/linear.js +0 -0
  1178. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/slack.d.ts +0 -0
  1179. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/slack.js +0 -0
  1180. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/github.d.ts +0 -0
  1181. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/github.js +0 -0
  1182. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/index.d.ts +0 -0
  1183. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/index.js +0 -0
  1184. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/linear.d.ts +0 -0
  1185. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/linear.js +0 -0
  1186. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/slack.d.ts +0 -0
  1187. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/slack.js +0 -0
  1188. /package/{dist/cloud → packages/cloud/dist}/webhooks/router.d.ts +0 -0
  1189. /package/{dist/cloud → packages/cloud/dist}/webhooks/router.js +0 -0
  1190. /package/{dist/cloud → packages/cloud/dist}/webhooks/rules-engine.d.ts +0 -0
  1191. /package/{dist/cloud → packages/cloud/dist}/webhooks/rules-engine.js +0 -0
  1192. /package/{dist/cloud → packages/cloud/dist}/webhooks/types.d.ts +0 -0
  1193. /package/{dist/cloud → packages/cloud/dist}/webhooks/types.js +0 -0
  1194. /package/{dist/utils → packages/config/dist}/agent-config.d.ts +0 -0
  1195. /package/{dist/utils → packages/config/dist}/agent-config.js +0 -0
  1196. /package/{dist/shared → packages/config/dist}/cli-auth-config.d.ts +0 -0
  1197. /package/{dist/bridge → packages/config/dist}/shadow-config.js +0 -0
  1198. /package/{dist/bridge → packages/config/dist}/teams-config.d.ts +0 -0
  1199. /package/{dist/bridge → packages/config/dist}/teams-config.js +0 -0
  1200. /package/{dist/continuity → packages/continuity/dist}/formatter.d.ts +0 -0
  1201. /package/{dist/continuity → packages/continuity/dist}/formatter.js +0 -0
  1202. /package/{dist/continuity → packages/continuity/dist}/handoff-store.d.ts +0 -0
  1203. /package/{dist/continuity → packages/continuity/dist}/handoff-store.js +0 -0
  1204. /package/{dist/continuity → packages/continuity/dist}/ledger-store.d.ts +0 -0
  1205. /package/{dist/continuity → packages/continuity/dist}/ledger-store.js +0 -0
  1206. /package/{dist/continuity → packages/continuity/dist}/manager.d.ts +0 -0
  1207. /package/{dist/continuity → packages/continuity/dist}/manager.js +0 -0
  1208. /package/{dist/continuity → packages/continuity/dist}/parser.d.ts +0 -0
  1209. /package/{dist/continuity → packages/continuity/dist}/parser.js +0 -0
  1210. /package/{dist/daemon → packages/daemon/dist}/agent-registry.d.ts +0 -0
  1211. /package/{dist/daemon → packages/daemon/dist}/agent-signing.d.ts +0 -0
  1212. /package/{dist/daemon → packages/daemon/dist}/agent-signing.js +0 -0
  1213. /package/{dist/daemon → packages/daemon/dist}/auth.d.ts +0 -0
  1214. /package/{dist/daemon → packages/daemon/dist}/auth.js +0 -0
  1215. /package/{dist/daemon → packages/daemon/dist}/consensus-integration.d.ts +0 -0
  1216. /package/{dist/daemon → packages/daemon/dist}/consensus.d.ts +0 -0
  1217. /package/{dist/daemon → packages/daemon/dist}/consensus.js +0 -0
  1218. /package/{dist/daemon → packages/daemon/dist}/rate-limiter.d.ts +0 -0
  1219. /package/{dist/daemon → packages/daemon/dist}/rate-limiter.js +0 -0
  1220. /package/{dist/daemon → packages/daemon/dist}/registry.d.ts +0 -0
  1221. /package/{dist/daemon → packages/daemon/dist}/registry.js +0 -0
  1222. /package/{dist/daemon → packages/daemon/dist}/repo-manager.d.ts +0 -0
  1223. /package/{dist/daemon → packages/daemon/dist}/types.js +0 -0
  1224. /package/{dist/daemon → packages/daemon/dist}/workspace-manager.d.ts +0 -0
  1225. /package/{dist/dashboard-server → packages/dashboard-server/dist}/metrics.d.ts +0 -0
  1226. /package/{dist/dashboard-server → packages/dashboard-server/dist}/metrics.js +0 -0
  1227. /package/{dist/dashboard-server → packages/dashboard-server/dist}/needs-attention.d.ts +0 -0
  1228. /package/{dist/dashboard-server → packages/dashboard-server/dist}/needs-attention.js +0 -0
  1229. /package/{dist/dashboard-server → packages/dashboard-server/dist}/server.d.ts +0 -0
  1230. /package/{dist/dashboard-server → packages/dashboard-server/dist}/start.d.ts +0 -0
  1231. /package/{dist/hooks → packages/hooks/dist}/emitter.d.ts +0 -0
  1232. /package/{dist/hooks → packages/hooks/dist}/emitter.js +0 -0
  1233. /package/{dist/hooks → packages/hooks/dist}/inbox-check/hook.d.ts +0 -0
  1234. /package/{dist/hooks → packages/hooks/dist}/inbox-check/hook.js +0 -0
  1235. /package/{dist/hooks → packages/hooks/dist}/inbox-check/index.d.ts +0 -0
  1236. /package/{dist/hooks → packages/hooks/dist}/inbox-check/index.js +0 -0
  1237. /package/{dist/hooks → packages/hooks/dist}/inbox-check/types.d.ts +0 -0
  1238. /package/{dist/hooks → packages/hooks/dist}/inbox-check/types.js +0 -0
  1239. /package/{dist/hooks → packages/hooks/dist}/inbox-check/utils.d.ts +0 -0
  1240. /package/{dist/hooks → packages/hooks/dist}/inbox-check/utils.js +0 -0
  1241. /package/{dist/hooks → packages/hooks/dist}/registry.d.ts +0 -0
  1242. /package/{dist/hooks → packages/hooks/dist}/trajectory-hooks.d.ts +0 -0
  1243. /package/{dist/memory → packages/memory/dist}/adapters/index.d.ts +0 -0
  1244. /package/{dist/memory → packages/memory/dist}/adapters/index.js +0 -0
  1245. /package/{dist/memory → packages/memory/dist}/adapters/inmemory.d.ts +0 -0
  1246. /package/{dist/memory → packages/memory/dist}/adapters/inmemory.js +0 -0
  1247. /package/{dist/memory → packages/memory/dist}/adapters/supermemory.d.ts +0 -0
  1248. /package/{dist/memory → packages/memory/dist}/adapters/supermemory.js +0 -0
  1249. /package/{dist/memory → packages/memory/dist}/context-compaction.d.ts +0 -0
  1250. /package/{dist/memory → packages/memory/dist}/context-compaction.js +0 -0
  1251. /package/{dist/memory → packages/memory/dist}/factory.d.ts +0 -0
  1252. /package/{dist/memory → packages/memory/dist}/factory.js +0 -0
  1253. /package/{dist/memory → packages/memory/dist}/index.d.ts +0 -0
  1254. /package/{dist/memory → packages/memory/dist}/index.js +0 -0
  1255. /package/{dist/memory → packages/memory/dist}/memory-hooks.js +0 -0
  1256. /package/{dist/memory → packages/memory/dist}/service.d.ts +0 -0
  1257. /package/{dist/memory → packages/memory/dist}/service.js +0 -0
  1258. /package/{dist/memory → packages/memory/dist}/types.d.ts +0 -0
  1259. /package/{dist/memory → packages/memory/dist}/types.js +0 -0
  1260. /package/{dist/policy → packages/policy/dist}/agent-policy.d.ts +0 -0
  1261. /package/{dist/policy → packages/policy/dist}/cloud-policy-fetcher.d.ts +0 -0
  1262. /package/{dist/policy → packages/policy/dist}/cloud-policy-fetcher.js +0 -0
  1263. /package/{dist/utils → packages/protocol/dist}/id-generator.d.ts +0 -0
  1264. /package/{dist/utils → packages/protocol/dist}/id-generator.js +0 -0
  1265. /package/{dist/protocol → packages/protocol/dist}/relay-pty-schemas.js +0 -0
  1266. /package/{dist/resiliency → packages/resiliency/dist}/context-persistence.d.ts +0 -0
  1267. /package/{dist/resiliency → packages/resiliency/dist}/context-persistence.js +0 -0
  1268. /package/{dist/resiliency → packages/resiliency/dist}/crash-insights.d.ts +0 -0
  1269. /package/{dist/resiliency → packages/resiliency/dist}/crash-insights.js +0 -0
  1270. /package/{dist/resiliency → packages/resiliency/dist}/gossip-health.d.ts +0 -0
  1271. /package/{dist/resiliency → packages/resiliency/dist}/gossip-health.js +0 -0
  1272. /package/{dist/resiliency → packages/resiliency/dist}/health-monitor.d.ts +0 -0
  1273. /package/{dist/resiliency → packages/resiliency/dist}/health-monitor.js +0 -0
  1274. /package/{dist/resiliency → packages/resiliency/dist}/index.d.ts +0 -0
  1275. /package/{dist/resiliency → packages/resiliency/dist}/index.js +0 -0
  1276. /package/{dist/resiliency → packages/resiliency/dist}/leader-watchdog.d.ts +0 -0
  1277. /package/{dist/resiliency → packages/resiliency/dist}/leader-watchdog.js +0 -0
  1278. /package/{dist/resiliency → packages/resiliency/dist}/logger.d.ts +0 -0
  1279. /package/{dist/resiliency → packages/resiliency/dist}/logger.js +0 -0
  1280. /package/{dist/resiliency → packages/resiliency/dist}/memory-monitor.d.ts +0 -0
  1281. /package/{dist/resiliency → packages/resiliency/dist}/metrics.d.ts +0 -0
  1282. /package/{dist/resiliency → packages/resiliency/dist}/metrics.js +0 -0
  1283. /package/{dist/resiliency → packages/resiliency/dist}/provider-context.js +0 -0
  1284. /package/{dist/resiliency → packages/resiliency/dist}/stateless-lead.d.ts +0 -0
  1285. /package/{dist/resiliency → packages/resiliency/dist}/stateless-lead.js +0 -0
  1286. /package/{dist/resiliency → packages/resiliency/dist}/supervisor.d.ts +0 -0
  1287. /package/{dist/resiliency → packages/resiliency/dist}/supervisor.js +0 -0
  1288. /package/{dist/state → packages/state/dist}/agent-state.d.ts +0 -0
  1289. /package/{dist/storage → packages/storage/dist}/adapter.js +0 -0
  1290. /package/{dist/storage → packages/storage/dist}/dead-letter-queue.d.ts +0 -0
  1291. /package/{dist/storage → packages/storage/dist}/dead-letter-queue.js +0 -0
  1292. /package/{dist/storage → packages/storage/dist}/dlq-adapter.d.ts +0 -0
  1293. /package/{dist/storage → packages/storage/dist}/dlq-adapter.js +0 -0
  1294. /package/{dist/trajectory → packages/trajectory/dist}/integration.d.ts +0 -0
  1295. /package/{dist/utils → packages/utils/dist}/command-resolver.d.ts +0 -0
  1296. /package/{dist/utils → packages/utils/dist}/git-remote.d.ts +0 -0
  1297. /package/{dist/utils → packages/utils/dist}/git-remote.js +0 -0
  1298. /package/{dist/utils → packages/utils/dist}/logger.d.ts +0 -0
  1299. /package/{dist/utils → packages/utils/dist}/logger.js +0 -0
  1300. /package/{dist/utils → packages/utils/dist}/name-generator.d.ts +0 -0
  1301. /package/{dist/utils → packages/utils/dist}/name-generator.js +0 -0
  1302. /package/{dist/utils → packages/utils/dist}/precompiled-patterns.d.ts +0 -0
  1303. /package/{dist/utils → packages/utils/dist}/precompiled-patterns.js +0 -0
  1304. /package/{dist/utils → packages/utils/dist}/update-checker.d.ts +0 -0
  1305. /package/{dist/utils → packages/utils/dist}/update-checker.js +0 -0
  1306. /package/{dist/wrapper → packages/wrapper/dist}/auth-detection.d.ts +0 -0
  1307. /package/{dist/wrapper → packages/wrapper/dist}/auth-detection.js +0 -0
  1308. /package/{dist/wrapper → packages/wrapper/dist}/inbox.d.ts +0 -0
  1309. /package/{dist/wrapper → packages/wrapper/dist}/inbox.js +0 -0
  1310. /package/{dist/wrapper → packages/wrapper/dist}/prompt-composer.d.ts +0 -0
  1311. /package/{dist/wrapper → packages/wrapper/dist}/prompt-composer.js +0 -0
  1312. /package/{dist/utils → packages/wrapper/dist}/tmux-resolver.d.ts +0 -0
  1313. /package/{dist/utils → packages/wrapper/dist}/tmux-resolver.js +0 -0
@@ -1,2069 +0,0 @@
1
- /**
2
- * Agent Relay Cloud - Workspace Provisioner
3
- *
4
- * One-click provisioning for compute resources (Fly.io, Railway, Docker).
5
- */
6
- import * as crypto from 'crypto';
7
- import { createHash } from 'node:crypto';
8
- import { getConfig } from '../config.js';
9
- import { db } from '../db/index.js';
10
- import { nangoService } from '../services/nango.js';
11
- import { canAutoScale, canScaleToTier, getResourceTierForPlan, } from '../services/planLimits.js';
12
- import { deriveSshPassword } from '../services/ssh-security.js';
13
- // ============================================================================
14
- // Daemon API Key Management
15
- // ============================================================================
16
- /**
17
- * Generate a daemon API key in the format ar_live_<32 hex chars>
18
- */
19
- function generateDaemonApiKey() {
20
- const random = crypto.randomBytes(32).toString('hex');
21
- return `ar_live_${random}`;
22
- }
23
- /**
24
- * Hash an API key for secure storage
25
- */
26
- function hashApiKey(apiKey) {
27
- return createHash('sha256').update(apiKey).digest('hex');
28
- }
29
- /**
30
- * Create a linked daemon record for a workspace during provisioning
31
- * @param preGeneratedApiKey - Pre-generated API key (if not provided, one will be generated)
32
- */
33
- async function createLinkedDaemon(userId, workspaceId, machineId, preGeneratedApiKey) {
34
- const apiKey = preGeneratedApiKey ?? generateDaemonApiKey();
35
- const apiKeyHash = hashApiKey(apiKey);
36
- const daemon = await db.linkedDaemons.create({
37
- userId,
38
- workspaceId,
39
- name: `auto-provisioned-${Date.now()}`,
40
- machineId,
41
- apiKeyHash,
42
- status: 'offline',
43
- });
44
- return { daemonId: daemon.id, apiKey };
45
- }
46
- const WORKSPACE_PORT = 3888;
47
- const WORKSPACE_HEALTH_PORT = 3889; // Health check on separate thread - always responsive
48
- const WORKSPACE_SSH_PORT = 3022;
49
- const CODEX_OAUTH_PORT = 1455; // Codex CLI OAuth callback port - must be mapped for local dev
50
- const FETCH_TIMEOUT_MS = 10_000;
51
- const WORKSPACE_IMAGE = process.env.WORKSPACE_IMAGE || 'ghcr.io/agentworkforce/relay-workspace:latest';
52
- // In-memory tracker for provisioning progress (workspace ID -> progress)
53
- const provisioningProgress = new Map();
54
- /**
55
- * Update the provisioning stage for a workspace
56
- */
57
- function updateProvisioningStage(workspaceId, stage) {
58
- const existing = provisioningProgress.get(workspaceId);
59
- provisioningProgress.set(workspaceId, {
60
- stage,
61
- startedAt: existing?.startedAt ?? Date.now(),
62
- updatedAt: Date.now(),
63
- });
64
- console.log(`[provisioner] Workspace ${workspaceId.substring(0, 8)} stage: ${stage}`);
65
- }
66
- /**
67
- * Get the current provisioning stage for a workspace
68
- */
69
- export function getProvisioningStage(workspaceId) {
70
- return provisioningProgress.get(workspaceId) ?? null;
71
- }
72
- /**
73
- * Clear provisioning progress (call when complete or failed)
74
- */
75
- function clearProvisioningProgress(workspaceId) {
76
- provisioningProgress.delete(workspaceId);
77
- }
78
- /**
79
- * Schedule cleanup of provisioning progress after a delay
80
- * This gives the frontend time to poll and see the 'complete' stage
81
- */
82
- function scheduleProgressCleanup(workspaceId, delayMs = 30_000) {
83
- setTimeout(() => {
84
- clearProvisioningProgress(workspaceId);
85
- console.log(`[provisioner] Cleaned up provisioning progress for ${workspaceId.substring(0, 8)}`);
86
- }, delayMs);
87
- }
88
- /**
89
- * Get a fresh GitHub App installation token from Nango.
90
- * Looks up the user's connected repositories to find a valid Nango connection.
91
- */
92
- async function getGithubAppTokenForUser(userId) {
93
- try {
94
- // Find any repository with a Nango connection for this user
95
- const repos = await db.repositories.findByUserId(userId);
96
- const repoWithConnection = repos.find(r => r.nangoConnectionId);
97
- if (!repoWithConnection?.nangoConnectionId) {
98
- console.warn(`[provisioner] No Nango GitHub App connection found for user ${userId}`);
99
- return null;
100
- }
101
- // Get fresh installation token from Nango (handles refresh automatically)
102
- const token = await nangoService.getGithubAppToken(repoWithConnection.nangoConnectionId);
103
- return token;
104
- }
105
- catch (error) {
106
- console.error(`[provisioner] Failed to get GitHub App token for user ${userId}:`, error);
107
- return null;
108
- }
109
- }
110
- async function wait(ms) {
111
- return new Promise((resolve) => setTimeout(resolve, ms));
112
- }
113
- async function fetchWithRetry(url, options = {}) {
114
- const retries = options.retries ?? 2;
115
- let attempt = 0;
116
- while (attempt <= retries) {
117
- const controller = new AbortController();
118
- const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
119
- try {
120
- const response = await fetch(url, { ...options, signal: controller.signal });
121
- clearTimeout(timer);
122
- if (!response.ok && response.status >= 500 && attempt < retries) {
123
- attempt += 1;
124
- await wait(500 * attempt);
125
- continue;
126
- }
127
- return response;
128
- }
129
- catch (error) {
130
- clearTimeout(timer);
131
- if (attempt >= retries) {
132
- throw error;
133
- }
134
- attempt += 1;
135
- await wait(500 * attempt);
136
- }
137
- }
138
- throw new Error('fetchWithRetry exhausted retries');
139
- }
140
- async function softHealthCheck(url) {
141
- try {
142
- const res = await fetchWithRetry(`${url.replace(/\/$/, '')}/health`, { method: 'GET', retries: 1 });
143
- if (!res.ok) {
144
- console.warn(`[health] Non-200 from ${url}/health: ${res.status}`);
145
- }
146
- }
147
- catch (error) {
148
- console.warn(`[health] Failed to reach ${url}/health`, error);
149
- }
150
- }
151
- /**
152
- * Wait for machine to be in "started" state using Fly.io's /wait endpoint
153
- * This is more efficient than polling - the API blocks until the state is reached
154
- * @see https://fly.io/docs/machines/api/machines-resource/#wait-for-a-machine-to-reach-a-specific-state
155
- */
156
- async function waitForMachineStarted(apiToken, appName, machineId, timeoutSeconds = 120) {
157
- console.log(`[provisioner] Waiting for machine ${machineId} to start (timeout: ${timeoutSeconds}s)...`);
158
- // Fly.io /wait endpoint has max timeout of 60s, so we need to loop for longer waits
159
- const maxSingleWait = 60;
160
- const startTime = Date.now();
161
- const deadline = startTime + timeoutSeconds * 1000;
162
- while (Date.now() < deadline) {
163
- const remainingMs = deadline - Date.now();
164
- const waitSeconds = Math.min(maxSingleWait, Math.ceil(remainingMs / 1000));
165
- if (waitSeconds <= 0)
166
- break;
167
- try {
168
- // Use Fly.io's /wait endpoint - blocks until machine reaches target state
169
- // timeout is an integer in seconds (max 60)
170
- const res = await fetch(`https://api.machines.dev/v1/apps/${appName}/machines/${machineId}/wait?state=started&timeout=${waitSeconds}`, {
171
- headers: { Authorization: `Bearer ${apiToken}` },
172
- });
173
- if (res.ok) {
174
- console.log(`[provisioner] Machine ${machineId} is now started`);
175
- return;
176
- }
177
- // 408 = timeout, machine didn't reach state in time - try again if we have time
178
- if (res.status === 408) {
179
- console.log(`[provisioner] Machine ${machineId} not ready yet, continuing to wait...`);
180
- continue;
181
- }
182
- // Other error
183
- const errorText = await res.text();
184
- throw new Error(`Wait for machine failed: ${res.status} ${errorText}`);
185
- }
186
- catch (error) {
187
- if (error instanceof Error && error.message.includes('Wait for machine failed')) {
188
- throw error;
189
- }
190
- console.warn(`[provisioner] Error waiting for machine:`, error);
191
- throw new Error(`Failed to wait for machine ${machineId}: ${error.message}`);
192
- }
193
- }
194
- // Timeout reached - get current state for error message
195
- const stateRes = await fetch(`https://api.machines.dev/v1/apps/${appName}/machines/${machineId}`, { headers: { Authorization: `Bearer ${apiToken}` } });
196
- const machine = stateRes.ok ? (await stateRes.json()) : { state: 'unknown' };
197
- throw new Error(`Machine ${machineId} did not start within ${timeoutSeconds}s (last state: ${machine.state})`);
198
- }
199
- /**
200
- * Wait for health check to pass (with DNS propagation time)
201
- * Tries internal Fly network first if available, then falls back to public URL
202
- */
203
- async function waitForHealthy(url, appName, maxWaitMs = 90_000) {
204
- const startTime = Date.now();
205
- // Build list of URLs to try - internal first (faster, more reliable from inside Fly)
206
- const urlsToTry = [];
207
- // If running on Fly and app name provided, try internal network first
208
- const isOnFly = !!process.env.FLY_APP_NAME;
209
- if (isOnFly && appName) {
210
- urlsToTry.push(`http://${appName}.internal:8080/health`);
211
- }
212
- // Always add the public URL as fallback
213
- urlsToTry.push(`${url.replace(/\/$/, '')}/health`);
214
- console.log(`[provisioner] Waiting for workspace to become healthy (trying: ${urlsToTry.join(', ')})...`);
215
- while (Date.now() - startTime < maxWaitMs) {
216
- // Try each URL in order
217
- for (const healthUrl of urlsToTry) {
218
- try {
219
- const controller = new AbortController();
220
- const timer = setTimeout(() => controller.abort(), 5_000);
221
- const res = await fetch(healthUrl, {
222
- method: 'GET',
223
- signal: controller.signal,
224
- });
225
- clearTimeout(timer);
226
- if (res.ok) {
227
- console.log(`[provisioner] Health check passed via ${healthUrl}`);
228
- return;
229
- }
230
- console.log(`[provisioner] Health check to ${healthUrl} returned ${res.status}`);
231
- }
232
- catch (error) {
233
- const elapsed = Math.round((Date.now() - startTime) / 1000);
234
- const errMsg = error.message;
235
- // Only log detailed error for last URL attempt
236
- if (healthUrl === urlsToTry[urlsToTry.length - 1]) {
237
- console.log(`[provisioner] Health check failed (${elapsed}s elapsed): ${errMsg}`);
238
- }
239
- }
240
- }
241
- await wait(3000);
242
- }
243
- // Don't throw - workspace is provisioned, health check is best-effort
244
- console.warn(`[provisioner] Health check did not pass within ${maxWaitMs}ms, continuing anyway`);
245
- }
246
- // Resource tiers sized for Claude Code agents (~1-2GB RAM per agent)
247
- // cpuKind: 'shared' = cheaper but can be throttled, 'performance' = dedicated
248
- export const RESOURCE_TIERS = {
249
- small: { name: 'small', cpuCores: 2, memoryMb: 2048, maxAgents: 2, cpuKind: 'shared' },
250
- medium: { name: 'medium', cpuCores: 2, memoryMb: 4096, maxAgents: 5, cpuKind: 'shared' },
251
- large: { name: 'large', cpuCores: 4, memoryMb: 8192, maxAgents: 10, cpuKind: 'performance' },
252
- xlarge: { name: 'xlarge', cpuCores: 8, memoryMb: 16384, maxAgents: 20, cpuKind: 'performance' },
253
- };
254
- /**
255
- * Fly.io provisioner
256
- */
257
- class FlyProvisioner {
258
- apiToken;
259
- org;
260
- region;
261
- workspaceDomain;
262
- cloudApiUrl;
263
- sessionSecret;
264
- registryAuth;
265
- snapshotRetentionDays;
266
- volumeSizeGb;
267
- constructor() {
268
- const config = getConfig();
269
- if (!config.compute.fly) {
270
- throw new Error('Fly.io configuration missing');
271
- }
272
- this.apiToken = config.compute.fly.apiToken;
273
- this.org = config.compute.fly.org;
274
- this.region = config.compute.fly.region || 'sjc';
275
- this.workspaceDomain = config.compute.fly.workspaceDomain;
276
- this.registryAuth = config.compute.fly.registryAuth;
277
- this.cloudApiUrl = config.publicUrl;
278
- this.sessionSecret = config.sessionSecret;
279
- // Snapshot settings: default 14 days retention, 10GB volume
280
- this.snapshotRetentionDays = Math.min(60, Math.max(1, config.compute.fly.snapshotRetentionDays ?? 14));
281
- this.volumeSizeGb = config.compute.fly.volumeSizeGb ?? 10;
282
- }
283
- /**
284
- * Generate a workspace token for API authentication
285
- * This is a simple HMAC - in production, consider using JWTs
286
- */
287
- generateWorkspaceToken(workspaceId) {
288
- return crypto
289
- .createHmac('sha256', this.sessionSecret)
290
- .update(`workspace:${workspaceId}`)
291
- .digest('hex');
292
- }
293
- /**
294
- * Create a volume with automatic snapshot settings
295
- * Fly.io takes daily snapshots automatically; we configure retention
296
- */
297
- async createVolume(appName) {
298
- const volumeName = 'workspace_data';
299
- console.log(`[fly] Creating volume ${volumeName} with ${this.snapshotRetentionDays}-day snapshot retention...`);
300
- const response = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/volumes`, {
301
- method: 'POST',
302
- headers: {
303
- Authorization: `Bearer ${this.apiToken}`,
304
- 'Content-Type': 'application/json',
305
- },
306
- body: JSON.stringify({
307
- name: volumeName,
308
- region: this.region,
309
- size_gb: this.volumeSizeGb,
310
- // Enable automatic daily snapshots (default is true, but be explicit)
311
- auto_backup_enabled: true,
312
- // Retain snapshots for configured days (default 5, we use 14)
313
- snapshot_retention: this.snapshotRetentionDays,
314
- }),
315
- });
316
- if (!response.ok) {
317
- const error = await response.text();
318
- throw new Error(`Failed to create volume: ${error}`);
319
- }
320
- const volume = await response.json();
321
- console.log(`[fly] Volume ${volume.id} created with auto-snapshots (${this.snapshotRetentionDays} days retention)`);
322
- return volume;
323
- }
324
- /**
325
- * Create an on-demand snapshot of a workspace volume
326
- * Use before risky operations or as manual backup
327
- */
328
- async createSnapshot(appName, volumeId) {
329
- console.log(`[fly] Creating on-demand snapshot for volume ${volumeId}...`);
330
- const response = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/volumes/${volumeId}/snapshots`, {
331
- method: 'POST',
332
- headers: {
333
- Authorization: `Bearer ${this.apiToken}`,
334
- 'Content-Type': 'application/json',
335
- },
336
- });
337
- if (!response.ok) {
338
- const error = await response.text();
339
- throw new Error(`Failed to create snapshot: ${error}`);
340
- }
341
- const snapshot = await response.json();
342
- console.log(`[fly] Snapshot ${snapshot.id} created`);
343
- return snapshot;
344
- }
345
- /**
346
- * List snapshots for a workspace volume
347
- */
348
- async listSnapshots(appName, volumeId) {
349
- const response = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/volumes/${volumeId}/snapshots`, {
350
- headers: {
351
- Authorization: `Bearer ${this.apiToken}`,
352
- },
353
- });
354
- if (!response.ok) {
355
- return [];
356
- }
357
- return await response.json();
358
- }
359
- /**
360
- * Get volume info for a workspace
361
- */
362
- async getVolume(appName) {
363
- const response = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/volumes`, {
364
- headers: {
365
- Authorization: `Bearer ${this.apiToken}`,
366
- },
367
- });
368
- if (!response.ok) {
369
- return null;
370
- }
371
- const volumes = await response.json();
372
- return volumes.find(v => v.name === 'workspace_data') || null;
373
- }
374
- async provision(workspace, credentials) {
375
- const appName = `ar-${workspace.id.substring(0, 8)}`;
376
- // Stage: Creating workspace
377
- updateProvisioningStage(workspace.id, 'creating');
378
- // Create Fly app
379
- await fetchWithRetry('https://api.machines.dev/v1/apps', {
380
- method: 'POST',
381
- headers: {
382
- Authorization: `Bearer ${this.apiToken}`,
383
- 'Content-Type': 'application/json',
384
- },
385
- body: JSON.stringify({
386
- app_name: appName,
387
- org_slug: this.org,
388
- }),
389
- });
390
- // Stage: Networking
391
- updateProvisioningStage(workspace.id, 'networking');
392
- // Allocate IPs for the app (required for public DNS)
393
- // Must use GraphQL API - Machines REST API doesn't support IP allocation
394
- // IMPORTANT: We use dedicated IPv4 ($2/mo) instead of shared because:
395
- // - Shared IPv4 doesn't properly handle raw TCP on non-standard ports (like SSH on 3022)
396
- // - SSH tunnel connections fail with "Connection closed by remote host" on shared IPs
397
- // - Dedicated IPv4 is required for raw TCP services to work correctly
398
- console.log(`[fly] Allocating IPs for ${appName}...`);
399
- const allocateIP = async (type) => {
400
- try {
401
- // Map our type to Fly GraphQL enum (v4 = dedicated IPv4)
402
- const graphqlType = type;
403
- const res = await fetchWithRetry('https://api.fly.io/graphql', {
404
- method: 'POST',
405
- headers: {
406
- Authorization: `Bearer ${this.apiToken}`,
407
- 'Content-Type': 'application/json',
408
- },
409
- body: JSON.stringify({
410
- query: `
411
- mutation AllocateIPAddress($input: AllocateIPAddressInput!) {
412
- allocateIpAddress(input: $input) {
413
- ipAddress {
414
- id
415
- address
416
- type
417
- }
418
- }
419
- }
420
- `,
421
- variables: {
422
- input: {
423
- appId: appName,
424
- type: graphqlType,
425
- },
426
- },
427
- }),
428
- });
429
- if (!res.ok) {
430
- const errorText = await res.text();
431
- console.warn(`[fly] Failed to allocate ${type}: ${res.status} ${errorText}`);
432
- return false;
433
- }
434
- const data = await res.json();
435
- if (data.errors?.length) {
436
- // Ignore "already allocated" errors
437
- const alreadyAllocated = data.errors.some(e => e.message.includes('already') || e.message.includes('exists'));
438
- if (!alreadyAllocated) {
439
- console.warn(`[fly] GraphQL error allocating ${type}: ${data.errors[0].message}`);
440
- return false;
441
- }
442
- console.log(`[fly] IP ${type} already allocated`);
443
- return true;
444
- }
445
- const address = data.data?.allocateIpAddress?.ipAddress?.address;
446
- console.log(`[fly] Allocated ${type}: ${address}`);
447
- return true;
448
- }
449
- catch (err) {
450
- console.warn(`[fly] Failed to allocate ${type}: ${err.message}`);
451
- return false;
452
- }
453
- };
454
- const [v4Result, v6Result] = await Promise.all([
455
- allocateIP('v4'),
456
- allocateIP('v6'),
457
- ]);
458
- console.log(`[fly] IP allocation results: v4=${v4Result}, v6=${v6Result}`);
459
- // Stage: Secrets
460
- updateProvisioningStage(workspace.id, 'secrets');
461
- // Set secrets (provider credentials)
462
- const secrets = {};
463
- for (const [provider, token] of credentials) {
464
- secrets[`${provider.toUpperCase()}_TOKEN`] = token;
465
- // Also set GH_TOKEN for gh CLI compatibility
466
- if (provider === 'github') {
467
- secrets['GH_TOKEN'] = token;
468
- }
469
- }
470
- if (Object.keys(secrets).length > 0) {
471
- await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/secrets`, {
472
- method: 'POST',
473
- headers: {
474
- Authorization: `Bearer ${this.apiToken}`,
475
- 'Content-Type': 'application/json',
476
- },
477
- body: JSON.stringify(secrets),
478
- });
479
- }
480
- // If custom workspace domain is configured, add certificate
481
- const customHostname = this.workspaceDomain
482
- ? `${appName}.${this.workspaceDomain}`
483
- : null;
484
- if (customHostname) {
485
- await this.allocateCertificate(appName, customHostname);
486
- }
487
- // Stage: Machine (includes volume creation)
488
- updateProvisioningStage(workspace.id, 'machine');
489
- // Generate API key for cloud message sync BEFORE creating the machine
490
- // The key is set as an env var on the machine and stored hashed in linkedDaemons
491
- const machineApiKey = generateDaemonApiKey();
492
- // Create volume with automatic daily snapshots before machine
493
- // Fly.io takes daily snapshots automatically; we configure retention
494
- const volume = await this.createVolume(appName);
495
- // Determine instance size based on user's plan
496
- // Free tier: 1 CPU, 2GB (~$10/mo) - Claude needs 2GB minimum
497
- // Paid tiers: 2 CPU, 2GB (~$15/mo)
498
- // Introductory bonus: Free users get Pro-level resources for first 14 days
499
- const user = await db.users.findById(workspace.userId);
500
- const userPlan = user?.plan || 'free';
501
- const isFreeTier = userPlan === 'free';
502
- // Check if user is in introductory period (first 14 days)
503
- const INTRO_PERIOD_DAYS = 14;
504
- const userCreatedAt = user?.createdAt ? new Date(user.createdAt) : new Date();
505
- const daysSinceSignup = (Date.now() - userCreatedAt.getTime()) / (1000 * 60 * 60 * 24);
506
- const isIntroPeriod = isFreeTier && daysSinceSignup < INTRO_PERIOD_DAYS;
507
- const guestConfig = {
508
- cpu_kind: 'shared',
509
- cpus: isIntroPeriod ? 2 : (isFreeTier ? 1 : 2), // Intro gets 2 CPUs like Pro
510
- memory_mb: isIntroPeriod ? 4096 : 2048, // Intro gets 4GB like Pro
511
- };
512
- if (isIntroPeriod) {
513
- const daysRemaining = Math.ceil(INTRO_PERIOD_DAYS - daysSinceSignup);
514
- console.log(`[fly] Introductory bonus active (${daysRemaining} days remaining) - 2 CPU / 4GB`);
515
- }
516
- console.log(`[fly] Using ${guestConfig.cpus} CPU / ${guestConfig.memory_mb}MB for ${userPlan} plan`);
517
- // Create machine with auto-stop/start for cost optimization
518
- const machineResponse = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/machines`, {
519
- method: 'POST',
520
- headers: {
521
- Authorization: `Bearer ${this.apiToken}`,
522
- 'Content-Type': 'application/json',
523
- },
524
- body: JSON.stringify({
525
- region: this.region,
526
- config: {
527
- image: WORKSPACE_IMAGE,
528
- // Registry auth for private ghcr.io images
529
- ...(this.registryAuth && {
530
- image_registry_auth: {
531
- registry: 'ghcr.io',
532
- username: this.registryAuth.username,
533
- password: this.registryAuth.password,
534
- },
535
- }),
536
- env: {
537
- WORKSPACE_ID: workspace.id,
538
- WORKSPACE_OWNER_USER_ID: workspace.userId,
539
- SUPERVISOR_ENABLED: String(workspace.config.supervisorEnabled ?? false),
540
- MAX_AGENTS: String(workspace.config.maxAgents ?? 10),
541
- REPOSITORIES: (workspace.config.repositories ?? []).join(','),
542
- PROVIDERS: (workspace.config.providers ?? []).join(','),
543
- PORT: String(WORKSPACE_PORT),
544
- AGENT_RELAY_DASHBOARD_PORT: String(WORKSPACE_PORT),
545
- // Store repos on persistent volume (/data) so they survive container restarts
546
- // Without this, repos are cloned to /workspace (ephemeral) and lost on restart
547
- WORKSPACE_DIR: '/data/repos',
548
- // Git gateway configuration
549
- CLOUD_API_URL: this.cloudApiUrl,
550
- WORKSPACE_TOKEN: this.generateWorkspaceToken(workspace.id),
551
- // Daemon API key for cloud message sync
552
- // Auto-generated during provisioning, stored in linkedDaemons table
553
- AGENT_RELAY_API_KEY: machineApiKey,
554
- // SSH for CLI tunneling (Codex OAuth callback forwarding)
555
- // Each workspace gets a unique password derived from its ID + secret salt
556
- ENABLE_SSH: 'true',
557
- SSH_PASSWORD: deriveSshPassword(workspace.id),
558
- SSH_PORT: String(WORKSPACE_SSH_PORT),
559
- },
560
- services: [
561
- {
562
- ports: [
563
- {
564
- port: 443,
565
- handlers: ['tls', 'http'],
566
- // Force HTTP/1.1 to backend for WebSocket upgrade compatibility
567
- // HTTP/2 doesn't support traditional WebSocket upgrade mechanism
568
- http_options: {
569
- h2_backend: false,
570
- },
571
- },
572
- { port: 80, handlers: ['http'] },
573
- ],
574
- protocol: 'tcp',
575
- internal_port: WORKSPACE_PORT,
576
- // Auto-stop after inactivity to reduce costs
577
- // Fly Proxy automatically wakes machines on incoming requests
578
- auto_stop_machines: 'stop', // stop (not suspend) for faster wake
579
- auto_start_machines: true,
580
- min_machines_running: 0,
581
- // Idle timeout before auto-stop (in seconds)
582
- // Longer timeout = better UX, shorter = lower costs
583
- concurrency: {
584
- type: 'requests',
585
- soft_limit: 25,
586
- hard_limit: 50,
587
- },
588
- },
589
- // SSH service for CLI tunneling (Codex OAuth callback forwarding)
590
- // Exposes port 3022 publicly for SSH connections from user's machine
591
- {
592
- ports: [
593
- {
594
- port: WORKSPACE_SSH_PORT,
595
- handlers: [], // Empty handlers = raw TCP passthrough
596
- },
597
- ],
598
- protocol: 'tcp',
599
- internal_port: WORKSPACE_SSH_PORT,
600
- // SSH connections should also wake the machine
601
- auto_stop_machines: 'stop',
602
- auto_start_machines: true,
603
- min_machines_running: 0,
604
- },
605
- ],
606
- checks: {
607
- health: {
608
- type: 'http',
609
- port: WORKSPACE_HEALTH_PORT, // Health worker thread - responds even when main loop blocked
610
- path: '/health',
611
- interval: '30s',
612
- timeout: '10s', // Increased timeout for safety
613
- grace_period: '30s', // Longer grace period for startup
614
- },
615
- },
616
- // Instance size based on plan - free tier gets smaller instance
617
- guest: guestConfig,
618
- // Mount the volume we created with snapshot settings
619
- mounts: [
620
- {
621
- volume: volume.id,
622
- path: '/data',
623
- },
624
- ],
625
- },
626
- }),
627
- });
628
- if (!machineResponse.ok) {
629
- const error = await machineResponse.text();
630
- throw new Error(`Failed to create Fly machine: ${error}`);
631
- }
632
- const machine = (await machineResponse.json());
633
- // Create linked daemon for cloud message sync
634
- // Pass the pre-generated API key so it matches what was set in the machine env vars
635
- const { daemonId } = await createLinkedDaemon(workspace.userId, workspace.id, machine.id, // Use Fly machine ID as daemon's machine ID
636
- machineApiKey);
637
- console.log(`[fly] Created linked daemon ${daemonId.substring(0, 8)} for workspace ${workspace.id.substring(0, 8)}`);
638
- // Return custom domain URL if configured, otherwise default fly.dev
639
- const publicUrl = customHostname
640
- ? `https://${customHostname}`
641
- : `https://${appName}.fly.dev`;
642
- // Stage: Booting
643
- updateProvisioningStage(workspace.id, 'booting');
644
- // Wait for machine to be in started state
645
- await waitForMachineStarted(this.apiToken, appName, machine.id);
646
- // Stage: Health check
647
- updateProvisioningStage(workspace.id, 'health');
648
- // Wait for health check to pass (includes DNS propagation time)
649
- // Pass appName to enable internal Fly network health checks
650
- await waitForHealthy(publicUrl, appName);
651
- // Stage: Complete
652
- updateProvisioningStage(workspace.id, 'complete');
653
- // Schedule cleanup of provisioning progress after 30s (gives frontend time to see 'complete')
654
- scheduleProgressCleanup(workspace.id);
655
- return {
656
- computeId: machine.id,
657
- publicUrl,
658
- };
659
- }
660
- /**
661
- * Allocate SSL certificate for custom domain
662
- */
663
- async allocateCertificate(appName, hostname) {
664
- const response = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/certificates`, {
665
- method: 'POST',
666
- headers: {
667
- Authorization: `Bearer ${this.apiToken}`,
668
- 'Content-Type': 'application/json',
669
- },
670
- body: JSON.stringify({ hostname }),
671
- });
672
- if (!response.ok) {
673
- const error = await response.text();
674
- // Don't fail if cert already exists
675
- if (!error.includes('already exists')) {
676
- throw new Error(`Failed to allocate certificate for ${hostname}: ${error}`);
677
- }
678
- }
679
- }
680
- async deprovision(workspace) {
681
- const appName = `ar-${workspace.id.substring(0, 8)}`;
682
- await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}`, {
683
- method: 'DELETE',
684
- headers: {
685
- Authorization: `Bearer ${this.apiToken}`,
686
- },
687
- });
688
- }
689
- async getStatus(workspace) {
690
- if (!workspace.computeId)
691
- return 'error';
692
- const appName = `ar-${workspace.id.substring(0, 8)}`;
693
- const response = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/machines/${workspace.computeId}`, {
694
- headers: {
695
- Authorization: `Bearer ${this.apiToken}`,
696
- },
697
- });
698
- if (!response.ok)
699
- return 'error';
700
- const machine = await response.json();
701
- switch (machine.state) {
702
- case 'started':
703
- return 'running';
704
- case 'stopped':
705
- return 'stopped';
706
- case 'created':
707
- case 'starting':
708
- return 'provisioning';
709
- default:
710
- return 'error';
711
- }
712
- }
713
- async restart(workspace) {
714
- if (!workspace.computeId)
715
- return;
716
- const appName = `ar-${workspace.id.substring(0, 8)}`;
717
- await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/machines/${workspace.computeId}/restart`, {
718
- method: 'POST',
719
- headers: {
720
- Authorization: `Bearer ${this.apiToken}`,
721
- },
722
- });
723
- }
724
- /**
725
- * Resize workspace - vertical scaling via Fly Machines API
726
- * @param skipRestart - If true, config is saved but machine won't restart (changes apply on next start)
727
- */
728
- async resize(workspaceOrId, tier, skipRestart = false) {
729
- const workspaceId = typeof workspaceOrId === 'string' ? workspaceOrId : workspaceOrId.id;
730
- const computeId = typeof workspaceOrId === 'string' ? undefined : workspaceOrId.computeId;
731
- // If passed just an ID, look up the workspace
732
- let machineId = computeId;
733
- if (!machineId) {
734
- const workspace = await db.workspaces.findById(workspaceId);
735
- if (!workspace?.computeId)
736
- return;
737
- machineId = workspace.computeId;
738
- }
739
- const appName = `ar-${workspaceId.substring(0, 8)}`;
740
- // Update machine configuration
741
- // If running: reboots with new specs (unless skip_launch: true)
742
- // If stopped: config saved, applies on next start
743
- await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/machines/${machineId}`, {
744
- method: 'POST',
745
- headers: {
746
- Authorization: `Bearer ${this.apiToken}`,
747
- 'Content-Type': 'application/json',
748
- },
749
- body: JSON.stringify({
750
- config: {
751
- guest: {
752
- // Use tier-specific CPU type (shared for cost, performance for power)
753
- cpu_kind: tier.cpuKind,
754
- cpus: tier.cpuCores,
755
- memory_mb: tier.memoryMb,
756
- },
757
- env: {
758
- MAX_AGENTS: String(tier.maxAgents),
759
- },
760
- },
761
- skip_launch: skipRestart, // If true, don't restart - changes apply on next start
762
- }),
763
- });
764
- const restartNote = skipRestart ? ' (will apply on next restart)' : ' (restarting)';
765
- console.log(`[fly] Resized workspace ${workspaceId.substring(0, 8)} to ${tier.name} (${tier.cpuCores} CPU, ${tier.memoryMb}MB RAM)${restartNote}`);
766
- }
767
- /**
768
- * Update the max agent limit for a workspace
769
- */
770
- async updateAgentLimit(workspace, newLimit) {
771
- if (!workspace.computeId)
772
- return;
773
- const appName = `ar-${workspace.id.substring(0, 8)}`;
774
- // Update environment variable
775
- await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/machines/${workspace.computeId}`, {
776
- method: 'POST',
777
- headers: {
778
- Authorization: `Bearer ${this.apiToken}`,
779
- 'Content-Type': 'application/json',
780
- },
781
- body: JSON.stringify({
782
- config: {
783
- env: {
784
- MAX_AGENTS: String(newLimit),
785
- },
786
- },
787
- }),
788
- });
789
- console.log(`[fly] Updated workspace ${workspace.id} agent limit to ${newLimit}`);
790
- }
791
- /**
792
- * Get current resource tier for a workspace
793
- */
794
- async getCurrentTier(workspace) {
795
- if (!workspace.computeId) {
796
- return RESOURCE_TIERS.small;
797
- }
798
- const appName = `ar-${workspace.id.substring(0, 8)}`;
799
- const response = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/machines/${workspace.computeId}`, {
800
- headers: {
801
- Authorization: `Bearer ${this.apiToken}`,
802
- },
803
- });
804
- if (!response.ok) {
805
- return RESOURCE_TIERS.small;
806
- }
807
- const machine = await response.json();
808
- const _cpus = machine.config?.guest?.cpus || 1;
809
- const memoryMb = machine.config?.guest?.memory_mb || 512;
810
- // Map to nearest tier
811
- if (memoryMb >= 4096)
812
- return RESOURCE_TIERS.xlarge;
813
- if (memoryMb >= 2048)
814
- return RESOURCE_TIERS.large;
815
- if (memoryMb >= 1024)
816
- return RESOURCE_TIERS.medium;
817
- return RESOURCE_TIERS.small;
818
- }
819
- /**
820
- * Update machine image without restarting
821
- * Note: The machine needs to be restarted later to use the new image
822
- */
823
- async updateMachineImage(workspace, newImage) {
824
- if (!workspace.computeId)
825
- return;
826
- const appName = `ar-${workspace.id.substring(0, 8)}`;
827
- // Get current machine config first
828
- const getResponse = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/machines/${workspace.computeId}`, {
829
- headers: {
830
- Authorization: `Bearer ${this.apiToken}`,
831
- },
832
- });
833
- if (!getResponse.ok) {
834
- throw new Error(`Failed to get machine config: ${await getResponse.text()}`);
835
- }
836
- const machine = await getResponse.json();
837
- // Update the image in the config
838
- const updatedConfig = {
839
- ...machine.config,
840
- image: newImage,
841
- // Include registry auth if configured
842
- ...(this.registryAuth && {
843
- image_registry_auth: {
844
- registry: 'ghcr.io',
845
- username: this.registryAuth.username,
846
- password: this.registryAuth.password,
847
- },
848
- }),
849
- };
850
- // Update machine with new image config (skip_launch keeps it in current state)
851
- const updateResponse = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/machines/${workspace.computeId}?skip_launch=true`, {
852
- method: 'POST',
853
- headers: {
854
- Authorization: `Bearer ${this.apiToken}`,
855
- 'Content-Type': 'application/json',
856
- },
857
- body: JSON.stringify({ config: updatedConfig }),
858
- });
859
- if (!updateResponse.ok) {
860
- throw new Error(`Failed to update machine image: ${await updateResponse.text()}`);
861
- }
862
- console.log(`[fly] Updated machine image for workspace ${workspace.id.substring(0, 8)} to ${newImage}`);
863
- }
864
- /**
865
- * Set secrets as environment variables for a workspace.
866
- */
867
- async setSecrets(workspace, secrets) {
868
- if (!workspace.computeId || Object.keys(secrets).length === 0)
869
- return;
870
- const appName = `ar-${workspace.id.substring(0, 8)}`;
871
- await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/secrets`, {
872
- method: 'POST',
873
- headers: {
874
- Authorization: `Bearer ${this.apiToken}`,
875
- 'Content-Type': 'application/json',
876
- },
877
- body: JSON.stringify(secrets),
878
- });
879
- }
880
- /**
881
- * Check if workspace has active agents by querying the daemon
882
- * Retries up to 3 times with backoff to handle machines that are starting up
883
- */
884
- async checkActiveAgents(workspace) {
885
- if (!workspace.publicUrl) {
886
- return { hasActiveAgents: false, agentCount: 0, agents: [], verified: true };
887
- }
888
- // Use internal Fly network URL if available (more reliable)
889
- const appName = `ar-${workspace.id.substring(0, 8)}`;
890
- const isOnFly = !!process.env.FLY_APP_NAME;
891
- const baseUrl = isOnFly
892
- ? `http://${appName}.internal:3888`
893
- : workspace.publicUrl;
894
- const maxRetries = 3;
895
- const retryDelays = [2000, 4000, 6000]; // 2s, 4s, 6s backoff
896
- for (let attempt = 0; attempt < maxRetries; attempt++) {
897
- try {
898
- const controller = new AbortController();
899
- const timer = setTimeout(() => controller.abort(), 10_000);
900
- // Use /api/data endpoint which returns { agents: [...], ... }
901
- // Note: /api/agents doesn't exist on the workspace dashboard-server
902
- const response = await fetch(`${baseUrl}/api/data`, {
903
- method: 'GET',
904
- headers: {
905
- 'Accept': 'application/json',
906
- },
907
- signal: controller.signal,
908
- });
909
- clearTimeout(timer);
910
- if (!response.ok) {
911
- console.warn(`[fly] Failed to check agents for ${workspace.id.substring(0, 8)}: HTTP ${response.status} (attempt ${attempt + 1}/${maxRetries})`);
912
- if (attempt < maxRetries - 1) {
913
- await new Promise(resolve => setTimeout(resolve, retryDelays[attempt]));
914
- continue;
915
- }
916
- return { hasActiveAgents: false, agentCount: 0, agents: [], verified: false };
917
- }
918
- const data = await response.json();
919
- const agents = data.agents || [];
920
- // Diagnostic logging: capture raw agent data before filtering
921
- if (agents.length > 0) {
922
- console.log(`[fly] Workspace ${workspace.id.substring(0, 8)} raw agent data:`, agents.map(a => ({ name: a.name, status: a.status, activityState: a.activityState })));
923
- }
924
- // Treat any online agent as active unless explicitly disconnected/offline.
925
- const activeAgents = agents.filter(a => {
926
- const status = (a.status ?? '').toLowerCase();
927
- const activityState = (a.activityState ?? '').toLowerCase();
928
- const isProcessing = a.isProcessing === true;
929
- if (activityState === 'active' || activityState === 'idle')
930
- return true;
931
- if (status && status !== 'disconnected' && status !== 'offline')
932
- return true;
933
- if (isProcessing)
934
- return true;
935
- return false;
936
- });
937
- // Log filtering results for diagnostics
938
- if (agents.length > 0 && activeAgents.length !== agents.length) {
939
- const filteredOut = agents.filter(a => {
940
- const status = (a.status ?? '').toLowerCase();
941
- const activityState = (a.activityState ?? '').toLowerCase();
942
- const isProcessing = a.isProcessing === true;
943
- if (activityState === 'active' || activityState === 'idle')
944
- return false;
945
- if (status && status !== 'disconnected' && status !== 'offline')
946
- return false;
947
- if (isProcessing)
948
- return false;
949
- return true;
950
- });
951
- console.log(`[fly] Workspace ${workspace.id.substring(0, 8)} filtered out agents:`, filteredOut.map(a => ({ name: a.name, status: a.status, activityState: a.activityState })));
952
- }
953
- return {
954
- hasActiveAgents: activeAgents.length > 0,
955
- agentCount: activeAgents.length,
956
- agents: agents.map(a => ({ name: a.name, status: a.status || a.activityState || 'unknown' })),
957
- verified: true,
958
- };
959
- }
960
- catch (error) {
961
- // Workspace might be stopped or unreachable - retry with backoff
962
- console.warn(`[fly] Could not reach workspace ${workspace.id.substring(0, 8)} (attempt ${attempt + 1}/${maxRetries}):`, error.message);
963
- if (attempt < maxRetries - 1) {
964
- await new Promise(resolve => setTimeout(resolve, retryDelays[attempt]));
965
- continue;
966
- }
967
- }
968
- }
969
- // All retries exhausted
970
- console.warn(`[fly] Workspace ${workspace.id.substring(0, 8)} unreachable after ${maxRetries} attempts`);
971
- return { hasActiveAgents: false, agentCount: 0, agents: [], verified: false };
972
- }
973
- /**
974
- * Get the current machine state
975
- */
976
- async getMachineState(workspace) {
977
- if (!workspace.computeId)
978
- return 'unknown';
979
- const appName = `ar-${workspace.id.substring(0, 8)}`;
980
- try {
981
- const response = await fetchWithRetry(`https://api.machines.dev/v1/apps/${appName}/machines/${workspace.computeId}`, {
982
- headers: {
983
- Authorization: `Bearer ${this.apiToken}`,
984
- },
985
- });
986
- if (!response.ok)
987
- return 'unknown';
988
- const machine = await response.json();
989
- return machine.state;
990
- }
991
- catch {
992
- return 'unknown';
993
- }
994
- }
995
- }
996
- /**
997
- * Railway provisioner
998
- */
999
- class RailwayProvisioner {
1000
- apiToken;
1001
- cloudApiUrl;
1002
- sessionSecret;
1003
- constructor() {
1004
- const config = getConfig();
1005
- if (!config.compute.railway) {
1006
- throw new Error('Railway configuration missing');
1007
- }
1008
- this.apiToken = config.compute.railway.apiToken;
1009
- this.cloudApiUrl = config.publicUrl;
1010
- this.sessionSecret = config.sessionSecret;
1011
- }
1012
- generateWorkspaceToken(workspaceId) {
1013
- return crypto
1014
- .createHmac('sha256', this.sessionSecret)
1015
- .update(`workspace:${workspaceId}`)
1016
- .digest('hex');
1017
- }
1018
- async provision(workspace, credentials) {
1019
- // Create project
1020
- const projectResponse = await fetchWithRetry('https://backboard.railway.app/graphql/v2', {
1021
- method: 'POST',
1022
- headers: {
1023
- Authorization: `Bearer ${this.apiToken}`,
1024
- 'Content-Type': 'application/json',
1025
- },
1026
- body: JSON.stringify({
1027
- query: `
1028
- mutation CreateProject($input: ProjectCreateInput!) {
1029
- projectCreate(input: $input) {
1030
- id
1031
- name
1032
- }
1033
- }
1034
- `,
1035
- variables: {
1036
- input: {
1037
- name: `agent-relay-${workspace.id.substring(0, 8)}`,
1038
- },
1039
- },
1040
- }),
1041
- });
1042
- const projectData = await projectResponse.json();
1043
- const projectId = projectData.data.projectCreate.id;
1044
- // Deploy service
1045
- const serviceResponse = await fetchWithRetry('https://backboard.railway.app/graphql/v2', {
1046
- method: 'POST',
1047
- headers: {
1048
- Authorization: `Bearer ${this.apiToken}`,
1049
- 'Content-Type': 'application/json',
1050
- },
1051
- body: JSON.stringify({
1052
- query: `
1053
- mutation CreateService($input: ServiceCreateInput!) {
1054
- serviceCreate(input: $input) {
1055
- id
1056
- }
1057
- }
1058
- `,
1059
- variables: {
1060
- input: {
1061
- projectId,
1062
- name: 'workspace',
1063
- source: {
1064
- image: WORKSPACE_IMAGE,
1065
- },
1066
- },
1067
- },
1068
- }),
1069
- });
1070
- const serviceData = await serviceResponse.json();
1071
- const serviceId = serviceData.data.serviceCreate.id;
1072
- // Create linked daemon for cloud message sync
1073
- // This generates an API key and registers the daemon in the linkedDaemons table
1074
- const { daemonId, apiKey: railwayApiKey } = await createLinkedDaemon(workspace.userId, workspace.id, serviceId);
1075
- console.log(`[railway] Created linked daemon ${daemonId.substring(0, 8)} for workspace ${workspace.id.substring(0, 8)}`);
1076
- // Set environment variables
1077
- const envVars = {
1078
- WORKSPACE_ID: workspace.id,
1079
- WORKSPACE_OWNER_USER_ID: workspace.userId,
1080
- SUPERVISOR_ENABLED: String(workspace.config.supervisorEnabled ?? false),
1081
- MAX_AGENTS: String(workspace.config.maxAgents ?? 10),
1082
- REPOSITORIES: (workspace.config.repositories ?? []).join(','),
1083
- PROVIDERS: (workspace.config.providers ?? []).join(','),
1084
- PORT: String(WORKSPACE_PORT),
1085
- AGENT_RELAY_DASHBOARD_PORT: String(WORKSPACE_PORT),
1086
- // Store repos on persistent volume so they survive container restarts
1087
- WORKSPACE_DIR: '/data/repos',
1088
- CLOUD_API_URL: this.cloudApiUrl,
1089
- WORKSPACE_TOKEN: this.generateWorkspaceToken(workspace.id),
1090
- // Daemon API key for cloud message sync
1091
- // Auto-generated during provisioning, stored in linkedDaemons table
1092
- AGENT_RELAY_API_KEY: railwayApiKey,
1093
- };
1094
- for (const [provider, token] of credentials) {
1095
- envVars[`${provider.toUpperCase()}_TOKEN`] = token;
1096
- // Also set GH_TOKEN for gh CLI compatibility
1097
- if (provider === 'github') {
1098
- envVars['GH_TOKEN'] = token;
1099
- }
1100
- }
1101
- await fetchWithRetry('https://backboard.railway.app/graphql/v2', {
1102
- method: 'POST',
1103
- headers: {
1104
- Authorization: `Bearer ${this.apiToken}`,
1105
- 'Content-Type': 'application/json',
1106
- },
1107
- body: JSON.stringify({
1108
- query: `
1109
- mutation SetVariables($input: VariableCollectionUpsertInput!) {
1110
- variableCollectionUpsert(input: $input)
1111
- }
1112
- `,
1113
- variables: {
1114
- input: {
1115
- projectId,
1116
- serviceId,
1117
- variables: envVars,
1118
- },
1119
- },
1120
- }),
1121
- });
1122
- // Generate domain
1123
- const domainResponse = await fetchWithRetry('https://backboard.railway.app/graphql/v2', {
1124
- method: 'POST',
1125
- headers: {
1126
- Authorization: `Bearer ${this.apiToken}`,
1127
- 'Content-Type': 'application/json',
1128
- },
1129
- body: JSON.stringify({
1130
- query: `
1131
- mutation CreateDomain($input: ServiceDomainCreateInput!) {
1132
- serviceDomainCreate(input: $input) {
1133
- domain
1134
- }
1135
- }
1136
- `,
1137
- variables: {
1138
- input: {
1139
- serviceId,
1140
- },
1141
- },
1142
- }),
1143
- });
1144
- const domainData = await domainResponse.json();
1145
- const domain = domainData.data.serviceDomainCreate.domain;
1146
- await softHealthCheck(`https://${domain}`);
1147
- return {
1148
- computeId: projectId,
1149
- publicUrl: `https://${domain}`,
1150
- };
1151
- }
1152
- async deprovision(workspace) {
1153
- if (!workspace.computeId)
1154
- return;
1155
- await fetchWithRetry('https://backboard.railway.app/graphql/v2', {
1156
- method: 'POST',
1157
- headers: {
1158
- Authorization: `Bearer ${this.apiToken}`,
1159
- 'Content-Type': 'application/json',
1160
- },
1161
- body: JSON.stringify({
1162
- query: `
1163
- mutation DeleteProject($id: String!) {
1164
- projectDelete(id: $id)
1165
- }
1166
- `,
1167
- variables: {
1168
- id: workspace.computeId,
1169
- },
1170
- }),
1171
- });
1172
- }
1173
- async getStatus(workspace) {
1174
- if (!workspace.computeId)
1175
- return 'error';
1176
- const response = await fetchWithRetry('https://backboard.railway.app/graphql/v2', {
1177
- method: 'POST',
1178
- headers: {
1179
- Authorization: `Bearer ${this.apiToken}`,
1180
- 'Content-Type': 'application/json',
1181
- },
1182
- body: JSON.stringify({
1183
- query: `
1184
- query GetProject($id: String!) {
1185
- project(id: $id) {
1186
- deployments {
1187
- edges {
1188
- node {
1189
- status
1190
- }
1191
- }
1192
- }
1193
- }
1194
- }
1195
- `,
1196
- variables: {
1197
- id: workspace.computeId,
1198
- },
1199
- }),
1200
- });
1201
- const data = await response.json();
1202
- const deployments = data.data?.project?.deployments?.edges;
1203
- if (!deployments || deployments.length === 0)
1204
- return 'provisioning';
1205
- const latestStatus = deployments[0].node.status;
1206
- switch (latestStatus) {
1207
- case 'SUCCESS':
1208
- return 'running';
1209
- case 'BUILDING':
1210
- case 'DEPLOYING':
1211
- return 'provisioning';
1212
- case 'CRASHED':
1213
- case 'FAILED':
1214
- return 'error';
1215
- default:
1216
- return 'stopped';
1217
- }
1218
- }
1219
- async restart(workspace) {
1220
- // Railway doesn't have a direct restart - redeploy instead
1221
- if (!workspace.computeId)
1222
- return;
1223
- await fetchWithRetry('https://backboard.railway.app/graphql/v2', {
1224
- method: 'POST',
1225
- headers: {
1226
- Authorization: `Bearer ${this.apiToken}`,
1227
- 'Content-Type': 'application/json',
1228
- },
1229
- body: JSON.stringify({
1230
- query: `
1231
- mutation RedeployService($input: DeploymentTriggerInput!) {
1232
- deploymentTrigger(input: $input)
1233
- }
1234
- `,
1235
- variables: {
1236
- input: {
1237
- projectId: workspace.computeId,
1238
- },
1239
- },
1240
- }),
1241
- });
1242
- }
1243
- async setEnvVars(workspace, envVars) {
1244
- if (!workspace.computeId || Object.keys(envVars).length === 0)
1245
- return;
1246
- const linkedDaemons = await db.linkedDaemons.findByWorkspaceId(workspace.id);
1247
- const serviceId = linkedDaemons[0]?.machineId;
1248
- if (!serviceId) {
1249
- console.warn(`[railway] No service ID found for workspace ${workspace.id}`);
1250
- return;
1251
- }
1252
- await fetchWithRetry('https://backboard.railway.app/graphql/v2', {
1253
- method: 'POST',
1254
- headers: {
1255
- Authorization: `Bearer ${this.apiToken}`,
1256
- 'Content-Type': 'application/json',
1257
- },
1258
- body: JSON.stringify({
1259
- query: `
1260
- mutation SetVariables($input: VariableCollectionUpsertInput!) {
1261
- variableCollectionUpsert(input: $input)
1262
- }
1263
- `,
1264
- variables: {
1265
- input: {
1266
- projectId: workspace.computeId,
1267
- serviceId,
1268
- variables: envVars,
1269
- },
1270
- },
1271
- }),
1272
- });
1273
- }
1274
- }
1275
- /**
1276
- * Local Docker provisioner (for development/self-hosted)
1277
- */
1278
- class DockerProvisioner {
1279
- cloudApiUrl;
1280
- cloudApiUrlForContainer;
1281
- sessionSecret;
1282
- constructor() {
1283
- const config = getConfig();
1284
- this.cloudApiUrl = config.publicUrl;
1285
- this.sessionSecret = config.sessionSecret;
1286
- // For Docker containers, localhost won't work - they need to reach the host
1287
- // Convert localhost URLs to host.docker.internal for container access
1288
- if (this.cloudApiUrl.includes('localhost') || this.cloudApiUrl.includes('127.0.0.1')) {
1289
- this.cloudApiUrlForContainer = this.cloudApiUrl
1290
- .replace('localhost', 'host.docker.internal')
1291
- .replace('127.0.0.1', 'host.docker.internal');
1292
- console.log(`[docker] Container API URL: ${this.cloudApiUrlForContainer} (host: ${this.cloudApiUrl})`);
1293
- }
1294
- else {
1295
- this.cloudApiUrlForContainer = this.cloudApiUrl;
1296
- }
1297
- }
1298
- generateWorkspaceToken(workspaceId) {
1299
- return crypto
1300
- .createHmac('sha256', this.sessionSecret)
1301
- .update(`workspace:${workspaceId}`)
1302
- .digest('hex');
1303
- }
1304
- /**
1305
- * Wait for container to be healthy by polling the health endpoint
1306
- */
1307
- async waitForHealthy(publicUrl, timeoutMs = 60_000) {
1308
- const startTime = Date.now();
1309
- const pollInterval = 2000;
1310
- console.log(`[docker] Waiting for container to be healthy at ${publicUrl}...`);
1311
- while (Date.now() - startTime < timeoutMs) {
1312
- try {
1313
- const response = await fetch(`${publicUrl}/health`, {
1314
- method: 'GET',
1315
- signal: AbortSignal.timeout(5000),
1316
- });
1317
- if (response.ok) {
1318
- console.log(`[docker] Container healthy after ${Date.now() - startTime}ms`);
1319
- return;
1320
- }
1321
- }
1322
- catch {
1323
- // Container not ready yet, continue polling
1324
- }
1325
- await wait(pollInterval);
1326
- }
1327
- throw new Error(`Container did not become healthy within ${timeoutMs}ms`);
1328
- }
1329
- async provision(workspace, credentials) {
1330
- const containerName = `ar-${workspace.id.substring(0, 8)}`;
1331
- // Create linked daemon for cloud message sync
1332
- // This generates an API key and registers the daemon in the linkedDaemons table
1333
- // Use container name as daemon's machine ID (will be updated to actual container ID after creation)
1334
- const { daemonId, apiKey: dockerApiKey } = await createLinkedDaemon(workspace.userId, workspace.id, containerName);
1335
- console.log(`[docker] Created linked daemon ${daemonId.substring(0, 8)} for workspace ${workspace.id.substring(0, 8)}`);
1336
- // Build environment variables
1337
- const envArgs = [
1338
- `-e WORKSPACE_ID=${workspace.id}`,
1339
- `-e WORKSPACE_OWNER_USER_ID=${workspace.userId}`,
1340
- `-e SUPERVISOR_ENABLED=${workspace.config.supervisorEnabled ?? false}`,
1341
- `-e MAX_AGENTS=${workspace.config.maxAgents ?? 10}`,
1342
- `-e REPOSITORIES=${(workspace.config.repositories ?? []).join(',')}`,
1343
- `-e PROVIDERS=${(workspace.config.providers ?? []).join(',')}`,
1344
- `-e PORT=${WORKSPACE_PORT}`,
1345
- `-e AGENT_RELAY_DASHBOARD_PORT=${WORKSPACE_PORT}`,
1346
- // Store repos on persistent volume so they survive container restarts
1347
- `-e WORKSPACE_DIR=/data/repos`,
1348
- `-e CLOUD_API_URL=${this.cloudApiUrlForContainer}`,
1349
- `-e WORKSPACE_TOKEN=${this.generateWorkspaceToken(workspace.id)}`,
1350
- // Daemon API key for cloud message sync
1351
- // Auto-generated during provisioning, stored in linkedDaemons table
1352
- `-e AGENT_RELAY_API_KEY=${dockerApiKey}`,
1353
- ];
1354
- for (const [provider, token] of credentials) {
1355
- envArgs.push(`-e ${provider.toUpperCase()}_TOKEN=${token}`);
1356
- // Also set GH_TOKEN for gh CLI compatibility
1357
- if (provider === 'github') {
1358
- envArgs.push(`-e GH_TOKEN=${token}`);
1359
- }
1360
- }
1361
- // Run container
1362
- const { execSync } = await import('child_process');
1363
- const hostPort = 3000 + Math.floor(Math.random() * 1000);
1364
- // SSH port for tunneling (Codex OAuth callback forwarding)
1365
- // Derive from hostPort to avoid collisions: API port 3500 -> SSH port 22500
1366
- const sshHostPort = 22000 + (hostPort - 3000);
1367
- // When running in Docker, connect to the same network for container-to-container communication
1368
- const runningInDocker = process.env.RUNNING_IN_DOCKER === 'true';
1369
- const networkArg = runningInDocker ? '--network agent-relay-dev' : '';
1370
- // In development, mount local dist and docs folders for faster iteration
1371
- // Set WORKSPACE_DEV_MOUNT=true to enable
1372
- const devMount = process.env.WORKSPACE_DEV_MOUNT === 'true';
1373
- const volumeArgs = devMount
1374
- ? `-v "${process.cwd()}/dist:/app/dist:ro" -v "${process.cwd()}/docs:/app/docs:ro"`
1375
- : '';
1376
- if (devMount) {
1377
- console.log('[provisioner] Dev mode: mounting local dist/ and docs/ folders into workspace container');
1378
- }
1379
- try {
1380
- // Map workspace API port and SSH port (for tunneling)
1381
- // SSH is used by CLI to forward localhost:1455 to workspace container for Codex OAuth
1382
- // Set CODEX_DIRECT_PORT=true to also map port 1455 directly (for debugging only)
1383
- const directCodexPort = process.env.CODEX_DIRECT_PORT === 'true';
1384
- const portMappings = directCodexPort
1385
- ? `-p ${hostPort}:${WORKSPACE_PORT} -p ${sshHostPort}:${WORKSPACE_SSH_PORT} -p ${CODEX_OAUTH_PORT}:${CODEX_OAUTH_PORT}`
1386
- : `-p ${hostPort}:${WORKSPACE_PORT} -p ${sshHostPort}:${WORKSPACE_SSH_PORT}`;
1387
- // Enable SSH in the container for tunneling
1388
- // Each workspace gets a unique password derived from its ID + secret salt
1389
- envArgs.push('-e ENABLE_SSH=true');
1390
- envArgs.push(`-e SSH_PASSWORD=${deriveSshPassword(workspace.id)}`);
1391
- envArgs.push(`-e SSH_PORT=${WORKSPACE_SSH_PORT}`);
1392
- execSync(`docker run -d --user root --name ${containerName} ${networkArg} ${volumeArgs} ${portMappings} ${envArgs.join(' ')} ${WORKSPACE_IMAGE}`, { stdio: 'pipe' });
1393
- const publicUrl = `http://localhost:${hostPort}`;
1394
- // Wait for container to be healthy before returning
1395
- // When running in Docker, use the internal container name for health check
1396
- const healthCheckUrl = runningInDocker
1397
- ? `http://${containerName}:${WORKSPACE_PORT}`
1398
- : publicUrl;
1399
- await this.waitForHealthy(healthCheckUrl);
1400
- return {
1401
- computeId: containerName,
1402
- publicUrl,
1403
- sshPort: sshHostPort,
1404
- };
1405
- }
1406
- catch (error) {
1407
- // Clean up container if it was created but health check failed
1408
- try {
1409
- const { execSync: execSyncCleanup } = await import('child_process');
1410
- execSyncCleanup(`docker rm -f ${containerName}`, { stdio: 'pipe' });
1411
- }
1412
- catch {
1413
- // Ignore cleanup errors
1414
- }
1415
- throw new Error(`Failed to start Docker container: ${error}`);
1416
- }
1417
- }
1418
- async deprovision(workspace) {
1419
- if (!workspace.computeId)
1420
- return;
1421
- const { execSync } = await import('child_process');
1422
- try {
1423
- execSync(`docker rm -f ${workspace.computeId}`, { stdio: 'pipe' });
1424
- }
1425
- catch {
1426
- // Container may already be removed
1427
- }
1428
- }
1429
- async getStatus(workspace) {
1430
- if (!workspace.computeId)
1431
- return 'error';
1432
- const { execSync } = await import('child_process');
1433
- try {
1434
- const result = execSync(`docker inspect -f '{{.State.Status}}' ${workspace.computeId}`, { stdio: 'pipe' }).toString().trim();
1435
- switch (result) {
1436
- case 'running':
1437
- return 'running';
1438
- case 'exited':
1439
- case 'dead':
1440
- return 'stopped';
1441
- case 'created':
1442
- case 'restarting':
1443
- return 'provisioning';
1444
- default:
1445
- return 'error';
1446
- }
1447
- }
1448
- catch {
1449
- return 'error';
1450
- }
1451
- }
1452
- async restart(workspace) {
1453
- if (!workspace.computeId)
1454
- return;
1455
- const { execSync } = await import('child_process');
1456
- try {
1457
- execSync(`docker restart ${workspace.computeId}`, { stdio: 'pipe' });
1458
- }
1459
- catch (error) {
1460
- throw new Error(`Failed to restart container: ${error}`);
1461
- }
1462
- }
1463
- async setEnvVars(_workspace, _envVars) {
1464
- console.warn('[docker] Updating environment variables for running containers is not supported.');
1465
- }
1466
- }
1467
- /**
1468
- * Main Workspace Provisioner
1469
- */
1470
- export class WorkspaceProvisioner {
1471
- provisioner;
1472
- constructor() {
1473
- const config = getConfig();
1474
- switch (config.compute.provider) {
1475
- case 'fly':
1476
- this.provisioner = new FlyProvisioner();
1477
- break;
1478
- case 'railway':
1479
- this.provisioner = new RailwayProvisioner();
1480
- break;
1481
- case 'docker':
1482
- default:
1483
- this.provisioner = new DockerProvisioner();
1484
- }
1485
- }
1486
- /**
1487
- * Provision a new workspace (one-click)
1488
- * Returns immediately with 'provisioning' status and runs actual provisioning in background
1489
- */
1490
- async provision(config) {
1491
- // Create workspace record
1492
- const workspace = await db.workspaces.create({
1493
- userId: config.userId,
1494
- name: config.name,
1495
- computeProvider: getConfig().compute.provider,
1496
- config: {
1497
- providers: config.providers,
1498
- repositories: config.repositories,
1499
- supervisorEnabled: config.supervisorEnabled ?? true,
1500
- maxAgents: config.maxAgents ?? 10,
1501
- },
1502
- });
1503
- // Add creator as owner in workspace_members for team collaboration support
1504
- await db.workspaceMembers.addMember({
1505
- workspaceId: workspace.id,
1506
- userId: config.userId,
1507
- role: 'owner',
1508
- invitedBy: config.userId, // Self-invited as creator
1509
- });
1510
- // Auto-accept the creator's membership
1511
- await db.workspaceMembers.acceptInvite(workspace.id, config.userId);
1512
- // Link repositories to this workspace
1513
- // This enables auto-access for users with GitHub access to these repos
1514
- for (const repoFullName of config.repositories) {
1515
- try {
1516
- // Find the user's repo record (may not exist if user didn't import it first)
1517
- const userRepos = await db.repositories.findByUserId(config.userId);
1518
- const repoRecord = userRepos.find(r => r.githubFullName.toLowerCase() === repoFullName.toLowerCase());
1519
- if (repoRecord) {
1520
- await db.repositories.assignToWorkspace(repoRecord.id, workspace.id);
1521
- console.log(`[provisioner] Linked repo ${repoFullName} to workspace ${workspace.id.substring(0, 8)}`);
1522
- }
1523
- else {
1524
- // Create a placeholder repo record if it doesn't exist
1525
- // This ensures the repo is tracked for workspace access checks
1526
- console.log(`[provisioner] Creating repo record for ${repoFullName}`);
1527
- const newRepo = await db.repositories.upsert({
1528
- userId: config.userId,
1529
- githubFullName: repoFullName,
1530
- githubId: 0, // Will be updated when actually synced
1531
- defaultBranch: 'main',
1532
- isPrivate: true, // Assume private, will be updated
1533
- workspaceId: workspace.id,
1534
- });
1535
- console.log(`[provisioner] Created and linked repo ${repoFullName} (id: ${newRepo.id.substring(0, 8)})`);
1536
- }
1537
- }
1538
- catch (err) {
1539
- console.warn(`[provisioner] Failed to link repo ${repoFullName}:`, err);
1540
- // Continue with other repos
1541
- }
1542
- }
1543
- // Initialize stage tracking immediately
1544
- updateProvisioningStage(workspace.id, 'creating');
1545
- // Run provisioning in the background so frontend can poll for stages
1546
- this.runProvisioningAsync(workspace, config).catch((error) => {
1547
- console.error(`[provisioner] Background provisioning failed for ${workspace.id}:`, error);
1548
- });
1549
- // Return immediately with 'provisioning' status
1550
- return {
1551
- workspaceId: workspace.id,
1552
- status: 'provisioning',
1553
- };
1554
- }
1555
- /**
1556
- * Run the actual provisioning work asynchronously
1557
- */
1558
- async runProvisioningAsync(workspace, config) {
1559
- // Build credentials map for workspace provisioning
1560
- // Note: Provider tokens (Claude, Codex, etc.) are no longer stored centrally.
1561
- // CLI tools authenticate directly on workspace instances.
1562
- // Only GitHub App tokens are obtained from Nango for repository cloning.
1563
- const credentials = new Map();
1564
- // GitHub token is required for cloning repositories
1565
- // Use direct token if provided (for testing), otherwise get from Nango
1566
- if (config.repositories.length > 0) {
1567
- if (config.githubToken) {
1568
- // Direct token provided (for testing)
1569
- credentials.set('github', config.githubToken);
1570
- console.log('[provisioner] Using provided GitHub token');
1571
- }
1572
- else {
1573
- // Get fresh installation token from Nango GitHub App
1574
- const githubToken = await getGithubAppTokenForUser(config.userId);
1575
- if (githubToken) {
1576
- credentials.set('github', githubToken);
1577
- }
1578
- else {
1579
- console.warn(`[provisioner] No GitHub App token for user ${config.userId}; repository cloning may fail.`);
1580
- }
1581
- }
1582
- }
1583
- // Provision compute
1584
- try {
1585
- const { computeId, publicUrl } = await this.provisioner.provision(workspace, credentials);
1586
- await db.workspaces.updateStatus(workspace.id, 'running', {
1587
- computeId,
1588
- publicUrl,
1589
- });
1590
- // Schedule cleanup of provisioning progress after 30s (gives frontend time to see 'complete')
1591
- setTimeout(() => {
1592
- clearProvisioningProgress(workspace.id);
1593
- console.log(`[provisioner] Cleaned up provisioning progress for ${workspace.id.substring(0, 8)}`);
1594
- }, 30_000);
1595
- console.log(`[provisioner] Workspace ${workspace.id} provisioned successfully at ${publicUrl}`);
1596
- }
1597
- catch (error) {
1598
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
1599
- await db.workspaces.updateStatus(workspace.id, 'error', {
1600
- errorMessage,
1601
- });
1602
- // Clear provisioning progress on error
1603
- clearProvisioningProgress(workspace.id);
1604
- console.error(`[provisioner] Workspace ${workspace.id} provisioning failed:`, errorMessage);
1605
- }
1606
- }
1607
- /**
1608
- * Deprovision a workspace
1609
- */
1610
- async deprovision(workspaceId) {
1611
- const workspace = await db.workspaces.findById(workspaceId);
1612
- if (!workspace) {
1613
- throw new Error('Workspace not found');
1614
- }
1615
- await this.provisioner.deprovision(workspace);
1616
- await db.workspaces.delete(workspaceId);
1617
- }
1618
- /**
1619
- * Get workspace status
1620
- */
1621
- async getStatus(workspaceId) {
1622
- const workspace = await db.workspaces.findById(workspaceId);
1623
- if (!workspace) {
1624
- throw new Error('Workspace not found');
1625
- }
1626
- // During early provisioning, computeId isn't set yet
1627
- // Return the database status instead of querying the provider
1628
- if (!workspace.computeId && workspace.status === 'provisioning') {
1629
- return 'provisioning';
1630
- }
1631
- const status = await this.provisioner.getStatus(workspace);
1632
- // Update database if status changed
1633
- if (status !== workspace.status) {
1634
- await db.workspaces.updateStatus(workspaceId, status);
1635
- }
1636
- return status;
1637
- }
1638
- /**
1639
- * Restart a workspace
1640
- */
1641
- async restart(workspaceId) {
1642
- const workspace = await db.workspaces.findById(workspaceId);
1643
- if (!workspace) {
1644
- throw new Error('Workspace not found');
1645
- }
1646
- await this.provisioner.restart(workspace);
1647
- }
1648
- /**
1649
- * Update environment variables for a workspace instance.
1650
- */
1651
- async setWorkspaceEnvVars(workspace, envVars) {
1652
- if (Object.keys(envVars).length === 0)
1653
- return;
1654
- if (this.provisioner instanceof FlyProvisioner) {
1655
- await this.provisioner.setSecrets(workspace, envVars);
1656
- return;
1657
- }
1658
- if (this.provisioner instanceof RailwayProvisioner) {
1659
- await this.provisioner.setEnvVars(workspace, envVars);
1660
- return;
1661
- }
1662
- if (this.provisioner instanceof DockerProvisioner) {
1663
- await this.provisioner.setEnvVars(workspace, envVars);
1664
- return;
1665
- }
1666
- }
1667
- /**
1668
- * Stop a workspace
1669
- */
1670
- async stop(workspaceId) {
1671
- const workspace = await db.workspaces.findById(workspaceId);
1672
- if (!workspace) {
1673
- throw new Error('Workspace not found');
1674
- }
1675
- // For now, just deprovision to stop
1676
- await this.provisioner.deprovision(workspace);
1677
- await db.workspaces.updateStatus(workspaceId, 'stopped');
1678
- }
1679
- /**
1680
- * Resize a workspace (vertical scaling)
1681
- * @param skipRestart - If true, config is saved but machine won't restart (changes apply on next start)
1682
- */
1683
- async resize(workspaceId, tier, skipRestart = false) {
1684
- const workspace = await db.workspaces.findById(workspaceId);
1685
- if (!workspace) {
1686
- throw new Error('Workspace not found');
1687
- }
1688
- if (!this.provisioner.resize) {
1689
- throw new Error('Resize not supported by current compute provider');
1690
- }
1691
- await this.provisioner.resize(workspace, tier, skipRestart);
1692
- // Update workspace config with new limits
1693
- await db.workspaces.updateConfig(workspaceId, {
1694
- ...workspace.config,
1695
- maxAgents: tier.maxAgents,
1696
- resourceTier: tier.name,
1697
- });
1698
- }
1699
- /**
1700
- * Update the max agent limit for a workspace
1701
- */
1702
- async updateAgentLimit(workspaceId, newLimit) {
1703
- const workspace = await db.workspaces.findById(workspaceId);
1704
- if (!workspace) {
1705
- throw new Error('Workspace not found');
1706
- }
1707
- if (this.provisioner.updateAgentLimit) {
1708
- await this.provisioner.updateAgentLimit(workspace, newLimit);
1709
- }
1710
- // Update workspace config
1711
- await db.workspaces.updateConfig(workspaceId, {
1712
- ...workspace.config,
1713
- maxAgents: newLimit,
1714
- });
1715
- }
1716
- /**
1717
- * Get current resource tier for a workspace
1718
- */
1719
- async getCurrentTier(workspaceId) {
1720
- const workspace = await db.workspaces.findById(workspaceId);
1721
- if (!workspace) {
1722
- throw new Error('Workspace not found');
1723
- }
1724
- if (this.provisioner.getCurrentTier) {
1725
- return this.provisioner.getCurrentTier(workspace);
1726
- }
1727
- // Fallback: determine from config or default to small
1728
- const tierName = workspace.config.resourceTier || 'small';
1729
- return RESOURCE_TIERS[tierName] || RESOURCE_TIERS.small;
1730
- }
1731
- /**
1732
- * Get recommended tier based on agent count
1733
- * Uses 1.5-2GB per agent as baseline for Claude Code
1734
- */
1735
- getRecommendedTier(agentCount) {
1736
- // Find the smallest tier that supports this agent count
1737
- const tiers = Object.values(RESOURCE_TIERS).sort((a, b) => a.maxAgents - b.maxAgents);
1738
- for (const tier of tiers) {
1739
- if (tier.maxAgents >= agentCount) {
1740
- return tier;
1741
- }
1742
- }
1743
- // If agent count exceeds all tiers, return the largest
1744
- return RESOURCE_TIERS.xlarge;
1745
- }
1746
- /**
1747
- * Auto-scale workspace based on current agent count
1748
- * Respects plan limits - free tier cannot scale, others have max tier limits
1749
- * Returns { scaled: boolean, reason?: string }
1750
- */
1751
- async autoScale(workspaceId, currentAgentCount) {
1752
- const workspace = await db.workspaces.findById(workspaceId);
1753
- if (!workspace) {
1754
- throw new Error('Workspace not found');
1755
- }
1756
- // Get user's plan
1757
- const user = await db.users.findById(workspace.userId);
1758
- const plan = user?.plan || 'free';
1759
- // Check if plan allows auto-scaling
1760
- if (!canAutoScale(plan)) {
1761
- return {
1762
- scaled: false,
1763
- reason: 'Auto-scaling requires Pro plan or higher',
1764
- };
1765
- }
1766
- const currentTier = await this.getCurrentTier(workspaceId);
1767
- const recommendedTier = this.getRecommendedTier(currentAgentCount);
1768
- // Only scale UP, never down (to avoid disruption)
1769
- if (recommendedTier.memoryMb <= currentTier.memoryMb) {
1770
- return {
1771
- scaled: false,
1772
- currentTier: currentTier.name,
1773
- };
1774
- }
1775
- // Check if plan allows scaling to the recommended tier
1776
- if (!canScaleToTier(plan, recommendedTier.name)) {
1777
- // Find the max tier allowed for this plan
1778
- const maxTierName = getResourceTierForPlan(plan);
1779
- const maxTier = RESOURCE_TIERS[maxTierName];
1780
- if (maxTier.memoryMb <= currentTier.memoryMb) {
1781
- return {
1782
- scaled: false,
1783
- reason: `Already at max tier (${currentTier.name}) for ${plan} plan`,
1784
- currentTier: currentTier.name,
1785
- };
1786
- }
1787
- // Scale to max allowed tier instead
1788
- console.log(`[provisioner] Auto-scaling workspace ${workspaceId.substring(0, 8)} from ${currentTier.name} to ${maxTierName} (max for ${plan} plan)`);
1789
- await this.resize(workspaceId, maxTier);
1790
- return {
1791
- scaled: true,
1792
- currentTier: currentTier.name,
1793
- targetTier: maxTierName,
1794
- reason: `Scaled to max tier for ${plan} plan`,
1795
- };
1796
- }
1797
- console.log(`[provisioner] Auto-scaling workspace ${workspaceId.substring(0, 8)} from ${currentTier.name} to ${recommendedTier.name} (${currentAgentCount} agents)`);
1798
- await this.resize(workspaceId, recommendedTier);
1799
- return {
1800
- scaled: true,
1801
- currentTier: currentTier.name,
1802
- targetTier: recommendedTier.name,
1803
- };
1804
- }
1805
- // ============================================================================
1806
- // Snapshot Management
1807
- // ============================================================================
1808
- /**
1809
- * Create an on-demand snapshot of a workspace's volume
1810
- * Use before risky operations (e.g., major refactors, untrusted code execution)
1811
- */
1812
- async createSnapshot(workspaceId) {
1813
- const workspace = await db.workspaces.findById(workspaceId);
1814
- if (!workspace) {
1815
- throw new Error('Workspace not found');
1816
- }
1817
- // Only Fly.io provisioner supports snapshots
1818
- if (!(this.provisioner instanceof FlyProvisioner)) {
1819
- console.warn('[provisioner] Snapshots only supported on Fly.io');
1820
- return null;
1821
- }
1822
- const appName = `ar-${workspace.id.substring(0, 8)}`;
1823
- const flyProvisioner = this.provisioner;
1824
- // Get the volume
1825
- const volume = await flyProvisioner.getVolume(appName);
1826
- if (!volume) {
1827
- throw new Error('No volume found for workspace');
1828
- }
1829
- // Create snapshot
1830
- const snapshot = await flyProvisioner.createSnapshot(appName, volume.id);
1831
- return { snapshotId: snapshot.id };
1832
- }
1833
- /**
1834
- * List available snapshots for a workspace
1835
- * Includes both automatic daily snapshots and on-demand snapshots
1836
- */
1837
- async listSnapshots(workspaceId) {
1838
- const workspace = await db.workspaces.findById(workspaceId);
1839
- if (!workspace) {
1840
- throw new Error('Workspace not found');
1841
- }
1842
- // Only Fly.io provisioner supports snapshots
1843
- if (!(this.provisioner instanceof FlyProvisioner)) {
1844
- return [];
1845
- }
1846
- const appName = `ar-${workspace.id.substring(0, 8)}`;
1847
- const flyProvisioner = this.provisioner;
1848
- // Get the volume
1849
- const volume = await flyProvisioner.getVolume(appName);
1850
- if (!volume) {
1851
- return [];
1852
- }
1853
- // List snapshots
1854
- const snapshots = await flyProvisioner.listSnapshots(appName, volume.id);
1855
- return snapshots.map(s => ({
1856
- id: s.id,
1857
- createdAt: s.created_at,
1858
- sizeBytes: s.size,
1859
- }));
1860
- }
1861
- /**
1862
- * Get the volume ID for a workspace (needed for restore operations)
1863
- */
1864
- async getVolumeId(workspaceId) {
1865
- const workspace = await db.workspaces.findById(workspaceId);
1866
- if (!workspace) {
1867
- throw new Error('Workspace not found');
1868
- }
1869
- if (!(this.provisioner instanceof FlyProvisioner)) {
1870
- return null;
1871
- }
1872
- const appName = `ar-${workspace.id.substring(0, 8)}`;
1873
- const flyProvisioner = this.provisioner;
1874
- const volume = await flyProvisioner.getVolume(appName);
1875
- return volume?.id || null;
1876
- }
1877
- // ============================================================================
1878
- // Graceful Image Update
1879
- // ============================================================================
1880
- /**
1881
- * Result of a graceful update attempt
1882
- */
1883
- static UpdateResult = {
1884
- UPDATED: 'updated',
1885
- UPDATED_PENDING_RESTART: 'updated_pending_restart',
1886
- SKIPPED_ACTIVE_AGENTS: 'skipped_active_agents',
1887
- SKIPPED_VERIFICATION_FAILED: 'skipped_verification_failed',
1888
- SKIPPED_NOT_RUNNING: 'skipped_not_running',
1889
- NOT_SUPPORTED: 'not_supported',
1890
- ERROR: 'error',
1891
- };
1892
- /**
1893
- * Gracefully update a single workspace's image
1894
- *
1895
- * Behavior:
1896
- * - If workspace is stopped: Update config, will use new image on next wake
1897
- * - If workspace is running with no agents: Update config and restart
1898
- * - If workspace is running with active agents: Skip (or force if specified)
1899
- *
1900
- * @param workspaceId - Workspace to update
1901
- * @param newImage - New Docker image to use
1902
- * @param options - Update options
1903
- * @returns Update result with details
1904
- */
1905
- async gracefulUpdateImage(workspaceId, newImage, options = {}) {
1906
- const workspace = await db.workspaces.findById(workspaceId);
1907
- if (!workspace) {
1908
- return {
1909
- result: WorkspaceProvisioner.UpdateResult.ERROR,
1910
- workspaceId,
1911
- error: 'Workspace not found',
1912
- };
1913
- }
1914
- // Only Fly.io supports graceful updates
1915
- if (!(this.provisioner instanceof FlyProvisioner)) {
1916
- return {
1917
- result: WorkspaceProvisioner.UpdateResult.NOT_SUPPORTED,
1918
- workspaceId,
1919
- error: 'Graceful updates only supported on Fly.io',
1920
- };
1921
- }
1922
- const flyProvisioner = this.provisioner;
1923
- try {
1924
- // Check machine state
1925
- const machineState = await flyProvisioner.getMachineState(workspace);
1926
- if (machineState === 'stopped' || machineState === 'suspended') {
1927
- // Machine is not running - safe to update, will apply on next wake
1928
- await flyProvisioner.updateMachineImage(workspace, newImage);
1929
- console.log(`[provisioner] Updated stopped workspace ${workspaceId.substring(0, 8)} to ${newImage}`);
1930
- return {
1931
- result: WorkspaceProvisioner.UpdateResult.UPDATED_PENDING_RESTART,
1932
- workspaceId,
1933
- machineState,
1934
- };
1935
- }
1936
- if (machineState === 'started') {
1937
- // Machine is running - check for active agents
1938
- const agentCheck = await flyProvisioner.checkActiveAgents(workspace);
1939
- // If we couldn't verify agent status and not forcing, skip to be safe
1940
- // This is expected behavior for workspaces that are waking up from auto-stop
1941
- // or experiencing temporary network issues - not an error condition
1942
- if (!agentCheck.verified && !options.force) {
1943
- console.log(`[provisioner] Skipped workspace ${workspaceId.substring(0, 8)}: workspace unreachable (will update on next restart)`);
1944
- return {
1945
- result: WorkspaceProvisioner.UpdateResult.SKIPPED_VERIFICATION_FAILED,
1946
- workspaceId,
1947
- machineState,
1948
- // Use 'reason' instead of 'error' - this is expected behavior, not an error
1949
- reason: 'Workspace unreachable - will update on next restart or when accessible',
1950
- };
1951
- }
1952
- if (agentCheck.hasActiveAgents && !options.force) {
1953
- // Has active agents and not forcing - skip
1954
- console.log(`[provisioner] Skipped workspace ${workspaceId.substring(0, 8)}: ${agentCheck.agentCount} active agents`);
1955
- return {
1956
- result: WorkspaceProvisioner.UpdateResult.SKIPPED_ACTIVE_AGENTS,
1957
- workspaceId,
1958
- machineState,
1959
- agentCount: agentCheck.agentCount,
1960
- agents: agentCheck.agents,
1961
- };
1962
- }
1963
- // Update the image config
1964
- await flyProvisioner.updateMachineImage(workspace, newImage);
1965
- if (options.skipRestart) {
1966
- // Config updated but not restarting - will apply on next restart/auto-stop-wake
1967
- console.log(`[provisioner] Updated workspace ${workspaceId.substring(0, 8)} config (restart skipped)`);
1968
- return {
1969
- result: WorkspaceProvisioner.UpdateResult.UPDATED_PENDING_RESTART,
1970
- workspaceId,
1971
- machineState,
1972
- agentCount: agentCheck.agentCount,
1973
- agents: agentCheck.agents,
1974
- };
1975
- }
1976
- // Restart to apply new image
1977
- await flyProvisioner.restart(workspace);
1978
- console.log(`[provisioner] Updated and restarted workspace ${workspaceId.substring(0, 8)}`);
1979
- return {
1980
- result: WorkspaceProvisioner.UpdateResult.UPDATED,
1981
- workspaceId,
1982
- machineState,
1983
- agentCount: agentCheck.agentCount,
1984
- };
1985
- }
1986
- // Unknown state
1987
- return {
1988
- result: WorkspaceProvisioner.UpdateResult.SKIPPED_NOT_RUNNING,
1989
- workspaceId,
1990
- machineState,
1991
- };
1992
- }
1993
- catch (error) {
1994
- console.error(`[provisioner] Error updating workspace ${workspaceId.substring(0, 8)}:`, error);
1995
- return {
1996
- result: WorkspaceProvisioner.UpdateResult.ERROR,
1997
- workspaceId,
1998
- error: error.message,
1999
- };
2000
- }
2001
- }
2002
- /**
2003
- * Gracefully update all workspaces to a new image
2004
- *
2005
- * Processes workspaces in batches, respecting active agents unless forced.
2006
- * Returns detailed results for each workspace.
2007
- *
2008
- * @param newImage - New Docker image to use
2009
- * @param options - Update options
2010
- * @returns Summary and per-workspace results
2011
- */
2012
- async gracefulUpdateAllImages(newImage, options = {}) {
2013
- // Get all workspaces to update
2014
- let workspaces;
2015
- if (options.workspaceIds?.length) {
2016
- // Specific workspaces
2017
- workspaces = (await Promise.all(options.workspaceIds.map(id => db.workspaces.findById(id)))).filter((w) => w !== null);
2018
- }
2019
- else if (options.userIds?.length) {
2020
- // Workspaces for specific users
2021
- const allWorkspaces = await Promise.all(options.userIds.map(userId => db.workspaces.findByUserId(userId)));
2022
- workspaces = allWorkspaces.flat();
2023
- }
2024
- else {
2025
- // All workspaces - need to query by status to get running ones
2026
- // For now, we'll get all workspaces from the provisioning provider
2027
- workspaces = await db.workspaces.findAll();
2028
- }
2029
- // Filter to only Fly.io workspaces
2030
- workspaces = workspaces.filter(w => w.computeProvider === 'fly' && w.computeId);
2031
- console.log(`[provisioner] Starting graceful update of ${workspaces.length} workspaces to ${newImage}`);
2032
- const batchSize = options.batchSize ?? 5;
2033
- const results = [];
2034
- // Process in batches
2035
- for (let i = 0; i < workspaces.length; i += batchSize) {
2036
- const batch = workspaces.slice(i, i + batchSize);
2037
- const batchResults = await Promise.all(batch.map(workspace => this.gracefulUpdateImage(workspace.id, newImage, {
2038
- force: options.force,
2039
- skipRestart: options.skipRestart,
2040
- })));
2041
- results.push(...batchResults);
2042
- // Small delay between batches to avoid overwhelming Fly API
2043
- if (i + batchSize < workspaces.length) {
2044
- await wait(1000);
2045
- }
2046
- }
2047
- // Compute summary
2048
- const summary = {
2049
- total: results.length,
2050
- updated: results.filter(r => r.result === WorkspaceProvisioner.UpdateResult.UPDATED).length,
2051
- pendingRestart: results.filter(r => r.result === WorkspaceProvisioner.UpdateResult.UPDATED_PENDING_RESTART).length,
2052
- skippedActiveAgents: results.filter(r => r.result === WorkspaceProvisioner.UpdateResult.SKIPPED_ACTIVE_AGENTS).length,
2053
- skippedVerificationFailed: results.filter(r => r.result === WorkspaceProvisioner.UpdateResult.SKIPPED_VERIFICATION_FAILED).length,
2054
- skippedNotRunning: results.filter(r => r.result === WorkspaceProvisioner.UpdateResult.SKIPPED_NOT_RUNNING).length,
2055
- errors: results.filter(r => r.result === WorkspaceProvisioner.UpdateResult.ERROR).length,
2056
- };
2057
- console.log(`[provisioner] Graceful update complete:`, summary);
2058
- return { summary, results };
2059
- }
2060
- }
2061
- // Singleton instance
2062
- let _provisioner = null;
2063
- export function getProvisioner() {
2064
- if (!_provisioner) {
2065
- _provisioner = new WorkspaceProvisioner();
2066
- }
2067
- return _provisioner;
2068
- }
2069
- //# sourceMappingURL=index.js.map