agent-relay 1.0.21 → 1.1.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 (283) hide show
  1. package/dist/bridge/shadow-cli.d.ts +17 -0
  2. package/dist/bridge/shadow-cli.d.ts.map +1 -0
  3. package/dist/bridge/shadow-cli.js +75 -0
  4. package/dist/bridge/shadow-cli.js.map +1 -0
  5. package/dist/bridge/shadow-config.d.ts +87 -0
  6. package/dist/bridge/shadow-config.d.ts.map +1 -0
  7. package/dist/bridge/shadow-config.js +134 -0
  8. package/dist/bridge/shadow-config.js.map +1 -0
  9. package/dist/bridge/spawner.d.ts +15 -1
  10. package/dist/bridge/spawner.d.ts.map +1 -1
  11. package/dist/bridge/spawner.js +164 -4
  12. package/dist/bridge/spawner.js.map +1 -1
  13. package/dist/bridge/types.d.ts +55 -0
  14. package/dist/bridge/types.d.ts.map +1 -1
  15. package/dist/cli/index.js +796 -11
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/cloud/api/auth.d.ts +19 -0
  18. package/dist/cloud/api/auth.d.ts.map +1 -0
  19. package/dist/cloud/api/auth.js +216 -0
  20. package/dist/cloud/api/auth.js.map +1 -0
  21. package/dist/cloud/api/billing.d.ts +17 -0
  22. package/dist/cloud/api/billing.d.ts.map +1 -0
  23. package/dist/cloud/api/billing.js +353 -0
  24. package/dist/cloud/api/billing.js.map +1 -0
  25. package/dist/cloud/api/coordinators.d.ts +8 -0
  26. package/dist/cloud/api/coordinators.d.ts.map +1 -0
  27. package/dist/cloud/api/coordinators.js +347 -0
  28. package/dist/cloud/api/coordinators.js.map +1 -0
  29. package/dist/cloud/api/daemons.d.ts +12 -0
  30. package/dist/cloud/api/daemons.d.ts.map +1 -0
  31. package/dist/cloud/api/daemons.js +320 -0
  32. package/dist/cloud/api/daemons.js.map +1 -0
  33. package/dist/cloud/api/middleware/planLimits.d.ts +36 -0
  34. package/dist/cloud/api/middleware/planLimits.d.ts.map +1 -0
  35. package/dist/cloud/api/middleware/planLimits.js +164 -0
  36. package/dist/cloud/api/middleware/planLimits.js.map +1 -0
  37. package/dist/cloud/api/onboarding.d.ts +8 -0
  38. package/dist/cloud/api/onboarding.d.ts.map +1 -0
  39. package/dist/cloud/api/onboarding.js +407 -0
  40. package/dist/cloud/api/onboarding.js.map +1 -0
  41. package/dist/cloud/api/providers.d.ts +7 -0
  42. package/dist/cloud/api/providers.d.ts.map +1 -0
  43. package/dist/cloud/api/providers.js +435 -0
  44. package/dist/cloud/api/providers.js.map +1 -0
  45. package/dist/cloud/api/repos.d.ts +7 -0
  46. package/dist/cloud/api/repos.d.ts.map +1 -0
  47. package/dist/cloud/api/repos.js +314 -0
  48. package/dist/cloud/api/repos.js.map +1 -0
  49. package/dist/cloud/api/teams.d.ts +7 -0
  50. package/dist/cloud/api/teams.d.ts.map +1 -0
  51. package/dist/cloud/api/teams.js +279 -0
  52. package/dist/cloud/api/teams.js.map +1 -0
  53. package/dist/cloud/api/usage.d.ts +7 -0
  54. package/dist/cloud/api/usage.d.ts.map +1 -0
  55. package/dist/cloud/api/usage.js +98 -0
  56. package/dist/cloud/api/usage.js.map +1 -0
  57. package/dist/cloud/api/workspaces.d.ts +7 -0
  58. package/dist/cloud/api/workspaces.d.ts.map +1 -0
  59. package/dist/cloud/api/workspaces.js +510 -0
  60. package/dist/cloud/api/workspaces.js.map +1 -0
  61. package/dist/cloud/billing/index.d.ts +9 -0
  62. package/dist/cloud/billing/index.d.ts.map +1 -0
  63. package/dist/cloud/billing/index.js +9 -0
  64. package/dist/cloud/billing/index.js.map +1 -0
  65. package/dist/cloud/billing/plans.d.ts +39 -0
  66. package/dist/cloud/billing/plans.d.ts.map +1 -0
  67. package/dist/cloud/billing/plans.js +232 -0
  68. package/dist/cloud/billing/plans.js.map +1 -0
  69. package/dist/cloud/billing/service.d.ts +80 -0
  70. package/dist/cloud/billing/service.d.ts.map +1 -0
  71. package/dist/cloud/billing/service.js +388 -0
  72. package/dist/cloud/billing/service.js.map +1 -0
  73. package/dist/cloud/billing/types.d.ts +135 -0
  74. package/dist/cloud/billing/types.d.ts.map +1 -0
  75. package/dist/cloud/billing/types.js +7 -0
  76. package/dist/cloud/billing/types.js.map +1 -0
  77. package/dist/cloud/config.d.ts +59 -0
  78. package/dist/cloud/config.d.ts.map +1 -0
  79. package/dist/cloud/config.js +83 -0
  80. package/dist/cloud/config.js.map +1 -0
  81. package/dist/cloud/db/drizzle.d.ts +132 -0
  82. package/dist/cloud/db/drizzle.d.ts.map +1 -0
  83. package/dist/cloud/db/drizzle.js +613 -0
  84. package/dist/cloud/db/drizzle.js.map +1 -0
  85. package/dist/cloud/db/index.d.ts +30 -0
  86. package/dist/cloud/db/index.d.ts.map +1 -0
  87. package/dist/cloud/db/index.js +44 -0
  88. package/dist/cloud/db/index.js.map +1 -0
  89. package/dist/cloud/db/schema.d.ts +1792 -0
  90. package/dist/cloud/db/schema.d.ts.map +1 -0
  91. package/dist/cloud/db/schema.js +234 -0
  92. package/dist/cloud/db/schema.js.map +1 -0
  93. package/dist/cloud/index.d.ts +11 -0
  94. package/dist/cloud/index.d.ts.map +1 -0
  95. package/dist/cloud/index.js +37 -0
  96. package/dist/cloud/index.js.map +1 -0
  97. package/dist/cloud/provisioner/index.d.ts +51 -0
  98. package/dist/cloud/provisioner/index.d.ts.map +1 -0
  99. package/dist/cloud/provisioner/index.js +676 -0
  100. package/dist/cloud/provisioner/index.js.map +1 -0
  101. package/dist/cloud/server.d.ts +16 -0
  102. package/dist/cloud/server.d.ts.map +1 -0
  103. package/dist/cloud/server.js +190 -0
  104. package/dist/cloud/server.js.map +1 -0
  105. package/dist/cloud/services/coordinator.d.ts +62 -0
  106. package/dist/cloud/services/coordinator.d.ts.map +1 -0
  107. package/dist/cloud/services/coordinator.js +389 -0
  108. package/dist/cloud/services/coordinator.js.map +1 -0
  109. package/dist/cloud/services/planLimits.d.ts +110 -0
  110. package/dist/cloud/services/planLimits.d.ts.map +1 -0
  111. package/dist/cloud/services/planLimits.js +254 -0
  112. package/dist/cloud/services/planLimits.js.map +1 -0
  113. package/dist/cloud/vault/index.d.ts +76 -0
  114. package/dist/cloud/vault/index.d.ts.map +1 -0
  115. package/dist/cloud/vault/index.js +219 -0
  116. package/dist/cloud/vault/index.js.map +1 -0
  117. package/dist/daemon/agent-manager.d.ts +87 -0
  118. package/dist/daemon/agent-manager.d.ts.map +1 -0
  119. package/dist/daemon/agent-manager.js +412 -0
  120. package/dist/daemon/agent-manager.js.map +1 -0
  121. package/dist/daemon/agent-registry.d.ts +2 -0
  122. package/dist/daemon/agent-registry.d.ts.map +1 -1
  123. package/dist/daemon/agent-registry.js +3 -0
  124. package/dist/daemon/agent-registry.js.map +1 -1
  125. package/dist/daemon/api.d.ts +69 -0
  126. package/dist/daemon/api.d.ts.map +1 -0
  127. package/dist/daemon/api.js +425 -0
  128. package/dist/daemon/api.js.map +1 -0
  129. package/dist/daemon/cloud-sync.d.ts +101 -0
  130. package/dist/daemon/cloud-sync.d.ts.map +1 -0
  131. package/dist/daemon/cloud-sync.js +261 -0
  132. package/dist/daemon/cloud-sync.js.map +1 -0
  133. package/dist/daemon/index.d.ts +4 -0
  134. package/dist/daemon/index.d.ts.map +1 -1
  135. package/dist/daemon/index.js +6 -0
  136. package/dist/daemon/index.js.map +1 -1
  137. package/dist/daemon/orchestrator.d.ts +155 -0
  138. package/dist/daemon/orchestrator.d.ts.map +1 -0
  139. package/dist/daemon/orchestrator.js +736 -0
  140. package/dist/daemon/orchestrator.js.map +1 -0
  141. package/dist/daemon/router.d.ts +24 -0
  142. package/dist/daemon/router.d.ts.map +1 -1
  143. package/dist/daemon/router.js +71 -1
  144. package/dist/daemon/router.js.map +1 -1
  145. package/dist/daemon/server.d.ts +37 -0
  146. package/dist/daemon/server.d.ts.map +1 -1
  147. package/dist/daemon/server.js +191 -16
  148. package/dist/daemon/server.js.map +1 -1
  149. package/dist/daemon/types.d.ts +127 -0
  150. package/dist/daemon/types.d.ts.map +1 -0
  151. package/dist/daemon/types.js +6 -0
  152. package/dist/daemon/types.js.map +1 -0
  153. package/dist/daemon/workspace-manager.d.ts +75 -0
  154. package/dist/daemon/workspace-manager.d.ts.map +1 -0
  155. package/dist/daemon/workspace-manager.js +289 -0
  156. package/dist/daemon/workspace-manager.js.map +1 -0
  157. package/dist/dashboard/out/404.html +1 -1
  158. package/dist/dashboard/out/_next/static/chunks/693-7b3301d8f6bc5014.js +1 -0
  159. package/dist/dashboard/out/_next/static/chunks/713-f78477eb185f1f4d.js +1 -0
  160. package/dist/dashboard/out/_next/static/chunks/766-e53e1cfe39b0b5b5.js +1 -0
  161. package/dist/dashboard/out/_next/static/chunks/900-037c64bfd797fb2a.js +1 -0
  162. package/dist/dashboard/out/_next/static/chunks/app/app/page-e3d9e1f4466b9bae.js +1 -0
  163. package/dist/dashboard/out/_next/static/chunks/app/history/page-b6edd4dde8d08194.js +1 -0
  164. package/dist/dashboard/out/_next/static/chunks/app/layout-2433bb48965f4333.js +1 -0
  165. package/dist/dashboard/out/_next/static/chunks/app/metrics/page-e68825a81db67ba1.js +1 -0
  166. package/dist/dashboard/out/_next/static/chunks/app/page-cc108bf68c8a657f.js +1 -0
  167. package/dist/dashboard/out/_next/static/chunks/app/pricing/page-d80e03a5297f95b6.js +1 -0
  168. package/dist/dashboard/out/_next/static/chunks/main-app-5d692157a8eb1fd9.js +1 -0
  169. package/dist/dashboard/out/_next/static/chunks/{main-e0a1f53fe0617a63.js → main-c2f423b9c9f4591b.js} +1 -1
  170. package/dist/dashboard/out/_next/static/chunks/{webpack-c81f7fd28659d64f.js → webpack-a5acc2831d094776.js} +1 -1
  171. package/dist/dashboard/out/_next/static/css/79b80143647a07d7.css +1 -0
  172. package/dist/dashboard/out/_next/static/css/8cf277370ad48cfe.css +1 -0
  173. package/dist/dashboard/out/alt-logos/agent-relay-logo-128.png +0 -0
  174. package/dist/dashboard/out/alt-logos/agent-relay-logo-256.png +0 -0
  175. package/dist/dashboard/out/alt-logos/agent-relay-logo-32.png +0 -0
  176. package/dist/dashboard/out/alt-logos/agent-relay-logo-512.png +0 -0
  177. package/dist/dashboard/out/alt-logos/agent-relay-logo-64.png +0 -0
  178. package/dist/dashboard/out/alt-logos/agent-relay-logo.svg +45 -0
  179. package/dist/dashboard/out/alt-logos/logo.svg +38 -0
  180. package/dist/dashboard/out/alt-logos/monogram-logo-128.png +0 -0
  181. package/dist/dashboard/out/alt-logos/monogram-logo-256.png +0 -0
  182. package/dist/dashboard/out/alt-logos/monogram-logo-32.png +0 -0
  183. package/dist/dashboard/out/alt-logos/monogram-logo-512.png +0 -0
  184. package/dist/dashboard/out/alt-logos/monogram-logo-64.png +0 -0
  185. package/dist/dashboard/out/alt-logos/monogram-logo.svg +38 -0
  186. package/dist/dashboard/out/app.html +14 -0
  187. package/dist/dashboard/out/app.txt +7 -0
  188. package/dist/dashboard/out/history.html +1 -0
  189. package/dist/dashboard/out/history.txt +7 -0
  190. package/dist/dashboard/out/index.html +1 -1
  191. package/dist/dashboard/out/index.txt +2 -2
  192. package/dist/dashboard/out/metrics.html +1 -515
  193. package/dist/dashboard/out/metrics.txt +2 -2
  194. package/dist/dashboard/out/pricing.html +13 -0
  195. package/dist/dashboard/out/pricing.txt +7 -0
  196. package/dist/dashboard-server/metrics.d.ts.map +1 -1
  197. package/dist/dashboard-server/metrics.js +3 -2
  198. package/dist/dashboard-server/metrics.js.map +1 -1
  199. package/dist/dashboard-server/server.d.ts.map +1 -1
  200. package/dist/dashboard-server/server.js +1279 -56
  201. package/dist/dashboard-server/server.js.map +1 -1
  202. package/dist/protocol/types.d.ts +10 -1
  203. package/dist/protocol/types.d.ts.map +1 -1
  204. package/dist/resiliency/context-persistence.d.ts +140 -0
  205. package/dist/resiliency/context-persistence.d.ts.map +1 -0
  206. package/dist/resiliency/context-persistence.js +397 -0
  207. package/dist/resiliency/context-persistence.js.map +1 -0
  208. package/dist/resiliency/health-monitor.d.ts +97 -0
  209. package/dist/resiliency/health-monitor.d.ts.map +1 -0
  210. package/dist/resiliency/health-monitor.js +291 -0
  211. package/dist/resiliency/health-monitor.js.map +1 -0
  212. package/dist/resiliency/index.d.ts +63 -0
  213. package/dist/resiliency/index.d.ts.map +1 -0
  214. package/dist/resiliency/index.js +63 -0
  215. package/dist/resiliency/index.js.map +1 -0
  216. package/dist/resiliency/logger.d.ts +114 -0
  217. package/dist/resiliency/logger.d.ts.map +1 -0
  218. package/dist/resiliency/logger.js +250 -0
  219. package/dist/resiliency/logger.js.map +1 -0
  220. package/dist/resiliency/metrics.d.ts +115 -0
  221. package/dist/resiliency/metrics.d.ts.map +1 -0
  222. package/dist/resiliency/metrics.js +239 -0
  223. package/dist/resiliency/metrics.js.map +1 -0
  224. package/dist/resiliency/provider-context.d.ts +100 -0
  225. package/dist/resiliency/provider-context.d.ts.map +1 -0
  226. package/dist/resiliency/provider-context.js +360 -0
  227. package/dist/resiliency/provider-context.js.map +1 -0
  228. package/dist/resiliency/supervisor.d.ts +109 -0
  229. package/dist/resiliency/supervisor.d.ts.map +1 -0
  230. package/dist/resiliency/supervisor.js +337 -0
  231. package/dist/resiliency/supervisor.js.map +1 -0
  232. package/dist/storage/adapter.d.ts +2 -0
  233. package/dist/storage/adapter.d.ts.map +1 -1
  234. package/dist/storage/adapter.js +12 -2
  235. package/dist/storage/adapter.js.map +1 -1
  236. package/dist/storage/sqlite-adapter.d.ts.map +1 -1
  237. package/dist/storage/sqlite-adapter.js +18 -14
  238. package/dist/storage/sqlite-adapter.js.map +1 -1
  239. package/dist/utils/index.d.ts +1 -0
  240. package/dist/utils/index.d.ts.map +1 -1
  241. package/dist/utils/index.js +1 -0
  242. package/dist/utils/index.js.map +1 -1
  243. package/dist/utils/logger.d.ts +40 -0
  244. package/dist/utils/logger.d.ts.map +1 -0
  245. package/dist/utils/logger.js +84 -0
  246. package/dist/utils/logger.js.map +1 -0
  247. package/dist/wrapper/client.d.ts +16 -1
  248. package/dist/wrapper/client.d.ts.map +1 -1
  249. package/dist/wrapper/client.js +32 -1
  250. package/dist/wrapper/client.js.map +1 -1
  251. package/dist/wrapper/parser.d.ts +3 -0
  252. package/dist/wrapper/parser.d.ts.map +1 -1
  253. package/dist/wrapper/parser.js +121 -18
  254. package/dist/wrapper/parser.js.map +1 -1
  255. package/dist/wrapper/pty-wrapper.d.ts +28 -1
  256. package/dist/wrapper/pty-wrapper.d.ts.map +1 -1
  257. package/dist/wrapper/pty-wrapper.js +166 -30
  258. package/dist/wrapper/pty-wrapper.js.map +1 -1
  259. package/dist/wrapper/tmux-wrapper.d.ts +5 -0
  260. package/dist/wrapper/tmux-wrapper.d.ts.map +1 -1
  261. package/dist/wrapper/tmux-wrapper.js +58 -18
  262. package/dist/wrapper/tmux-wrapper.js.map +1 -1
  263. package/docs/CLOUD-ARCHITECTURE.md +652 -0
  264. package/docs/CLOUD-ONBOARDING-DESIGN.md +1983 -0
  265. package/docs/TESTING_PRESENCE_FEATURES.md +327 -0
  266. package/docs/agent-relay-snippet.md +107 -4
  267. package/docs/guides/CLOUD.md +236 -0
  268. package/docs/guides/LOCAL.md +535 -0
  269. package/docs/guides/SELF-HOSTED.md +494 -0
  270. package/docs/proposals/shadow-as-subagent.md +765 -0
  271. package/docs/proposals/slack-bot-integration.md +1457 -0
  272. package/package.json +33 -4
  273. package/dist/dashboard/out/_next/static/chunks/app/layout-c9d8c5d95e48c6bf.js +0 -1
  274. package/dist/dashboard/out/_next/static/chunks/app/metrics/page-8aa9936bc6c771ab.js +0 -1
  275. package/dist/dashboard/out/_next/static/chunks/app/page-49055e5d2b5e34ec.js +0 -1
  276. package/dist/dashboard/out/_next/static/chunks/main-app-bae2e535de00de50.js +0 -1
  277. package/dist/dashboard/out/_next/static/css/50ed6996e3df7bdd.css +0 -1
  278. /package/dist/dashboard/out/_next/static/{gZXwjIKGDKJ0hiTH-HMeJ → 6HHWb2ZmnJ4OSm0zUP7h4}/_buildManifest.js +0 -0
  279. /package/dist/dashboard/out/_next/static/{gZXwjIKGDKJ0hiTH-HMeJ → 6HHWb2ZmnJ4OSm0zUP7h4}/_ssgManifest.js +0 -0
  280. /package/dist/dashboard/out/_next/static/chunks/{117-3bef7b19f3e60751.js → 117-b2cd8d6485aacf2b.js} +0 -0
  281. /package/dist/dashboard/out/_next/static/chunks/{648-6cf686106c891ad3.js → 648-8f3f26864ce515e5.js} +0 -0
  282. /package/dist/dashboard/out/_next/static/chunks/app/_not-found/{page-8ff6572bc7c9bc61.js → page-0b990dbb71d72a98.js} +0 -0
  283. /package/dist/dashboard/out/_next/static/chunks/{fd9d1056-26bd8d656b496dba.js → fd9d1056-bf46c09eb57e019c.js} +0 -0
@@ -0,0 +1,652 @@
1
+ # Agent Relay Cloud - Architecture
2
+
3
+ ## System Overview
4
+
5
+ ```
6
+ ┌─────────────────────────────────────────────────────────────────────────────────┐
7
+ │ AGENT RELAY CLOUD │
8
+ │ │
9
+ │ ┌─────────────────────────────────────────────────────────────────────────┐ │
10
+ │ │ CONTROL PLANE │ │
11
+ │ │ │ │
12
+ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
13
+ │ │ │ API │ │ Auth │ │Credential│ │Workspace │ │ Dashboard│ │ │
14
+ │ │ │ Server │ │ Service │ │ Vault │ │Provisioner│ │ (React) │ │ │
15
+ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │
16
+ │ │ │ │ │ │ │ │ │
17
+ │ │ └─────────────┴─────────────┴─────────────┴─────────────┘ │ │
18
+ │ │ │ │ │
19
+ │ │ ┌──────┴──────┐ │ │
20
+ │ │ │ PostgreSQL │ │ │
21
+ │ │ │ + Redis │ │ │
22
+ │ │ └─────────────┘ │ │
23
+ │ └─────────────────────────────────────────────────────────────────────────┘ │
24
+ │ │ │
25
+ │ │ Provision & Manage │
26
+ │ ▼ │
27
+ │ ┌─────────────────────────────────────────────────────────────────────────┐ │
28
+ │ │ COMPUTE PLANE │ │
29
+ │ │ │ │
30
+ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │
31
+ │ │ │ Workspace A │ │ Workspace B │ │ Workspace C │ ... │ │
32
+ │ │ │ (user-123) │ │ (user-456) │ │ (team-789) │ │ │
33
+ │ │ │ │ │ │ │ │ │ │
34
+ │ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ │
35
+ │ │ │ │agent-relay│ │ │ │agent-relay│ │ │ │agent-relay│ │ │ │
36
+ │ │ │ │ daemon │ │ │ │ daemon │ │ │ │ daemon │ │ │ │
37
+ │ │ │ └─────┬─────┘ │ │ └─────┬─────┘ │ │ └─────┬─────┘ │ │ │
38
+ │ │ │ │ │ │ │ │ │ │ │ │ │
39
+ │ │ │ ┌─────┴─────┐ │ │ ┌─────┴─────┐ │ │ ┌─────┴─────┐ │ │ │
40
+ │ │ │ │ Agents │ │ │ │ Agents │ │ │ │ Agents │ │ │ │
41
+ │ │ │ │(claude, │ │ │ │(codex) │ │ │ │(claude, │ │ │ │
42
+ │ │ │ │ codex) │ │ │ │ │ │ │ │ gemini) │ │ │ │
43
+ │ │ │ └───────────┘ │ │ └───────────┘ │ │ └───────────┘ │ │ │
44
+ │ │ │ │ │ │ │ │ │ │
45
+ │ │ │ /repos/ │ │ /repos/ │ │ /repos/ │ │ │
46
+ │ │ │ ├─ project-a │ │ └─ my-app │ │ ├─ backend │ │ │
47
+ │ │ │ └─ project-b │ │ │ │ └─ frontend │ │ │
48
+ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │
49
+ │ │ │ │
50
+ │ │ Compute Options: Fly.io | Railway | AWS ECS | GCP Cloud Run │ │
51
+ │ └─────────────────────────────────────────────────────────────────────────┘ │
52
+ │ │
53
+ └─────────────────────────────────────────────────────────────────────────────────┘
54
+ ```
55
+
56
+ ## One-Click Provisioning Flow
57
+
58
+ ```
59
+ User signs up
60
+
61
+
62
+ ┌─────────────────────────────────────────────────────────────────┐
63
+ │ 1. AUTHENTICATE │
64
+ │ • GitHub OAuth login │
65
+ │ • Create user record │
66
+ │ • Store GitHub token │
67
+ └─────────────────────────────────────────────────────────────────┘
68
+
69
+
70
+ ┌─────────────────────────────────────────────────────────────────┐
71
+ │ 2. CONNECT PROVIDERS │
72
+ │ • Device flow for Claude/Codex │
73
+ │ • Store tokens in credential vault │
74
+ │ • (Can be done during or after onboarding) │
75
+ └─────────────────────────────────────────────────────────────────┘
76
+
77
+
78
+ ┌─────────────────────────────────────────────────────────────────┐
79
+ │ 3. SELECT REPOSITORIES │
80
+ │ • List repos from GitHub │
81
+ │ • User selects which to connect │
82
+ │ • Install GitHub App on selected repos │
83
+ └─────────────────────────────────────────────────────────────────┘
84
+
85
+
86
+ ┌─────────────────────────────────────────────────────────────────┐
87
+ │ 4. PROVISION WORKSPACE (automatic, ~30 seconds) │
88
+ │ • Allocate compute resources │
89
+ │ • Deploy agent-relay container │
90
+ │ • Clone selected repositories │
91
+ │ • Inject credentials from vault │
92
+ │ • Start daemon with supervisor │
93
+ │ • Configure webhooks │
94
+ └─────────────────────────────────────────────────────────────────┘
95
+
96
+
97
+ ┌─────────────────────────────────────────────────────────────────┐
98
+ │ 5. READY │
99
+ │ • Dashboard URL live │
100
+ │ • Agents ready to spawn │
101
+ │ • GitHub webhooks configured │
102
+ └─────────────────────────────────────────────────────────────────┘
103
+ ```
104
+
105
+ ## Components
106
+
107
+ ### 1. Control Plane Services
108
+
109
+ #### API Server (`/src/cloud/api/`)
110
+ - Express.js REST API
111
+ - Handles all cloud operations
112
+ - Routes:
113
+ - `/auth/*` - GitHub OAuth, session management
114
+ - `/providers/*` - Device flow auth for AI providers
115
+ - `/workspaces/*` - Workspace CRUD, provisioning
116
+ - `/repos/*` - Repository management
117
+ - `/teams/*` - Team management
118
+
119
+ #### Auth Service (`/src/cloud/auth/`)
120
+ - GitHub OAuth for user login
121
+ - Device flow for AI providers
122
+ - Session management (Redis)
123
+ - JWT tokens for API auth
124
+
125
+ #### Credential Vault (`/src/cloud/vault/`)
126
+ - Encrypted storage for OAuth tokens
127
+ - Per-user encryption keys
128
+ - Automatic token refresh
129
+ - Sync to workspaces
130
+
131
+ #### Workspace Provisioner (`/src/cloud/provisioner/`)
132
+ - Provisions compute resources
133
+ - Deploys agent-relay containers
134
+ - Manages workspace lifecycle
135
+ - Supports multiple backends:
136
+ - Fly.io (default)
137
+ - Railway
138
+ - AWS ECS
139
+ - Docker (local dev)
140
+
141
+ ### 2. Compute Plane
142
+
143
+ #### Workspace Container
144
+ ```dockerfile
145
+ FROM node:20-slim
146
+
147
+ # Install agent CLIs
148
+ RUN npm install -g agent-relay
149
+ RUN npm install -g @anthropic/claude-code
150
+ # Codex installed via their installer
151
+
152
+ # Workspace directory
153
+ WORKDIR /workspace
154
+
155
+ # Entry point
156
+ COPY entrypoint.sh /entrypoint.sh
157
+ CMD ["/entrypoint.sh"]
158
+ ```
159
+
160
+ #### Entrypoint Script
161
+ ```bash
162
+ #!/bin/bash
163
+
164
+ # Fetch credentials from vault
165
+ agent-relay cloud sync-credentials
166
+
167
+ # Clone repositories
168
+ for repo in $REPOS; do
169
+ git clone "https://x-access-token:${GITHUB_TOKEN}@github.com/${repo}.git"
170
+ done
171
+
172
+ # Start agent-relay daemon with supervisor
173
+ agent-relay up --watch
174
+ ```
175
+
176
+ ## Database Schema
177
+
178
+ ```sql
179
+ -- Users
180
+ CREATE TABLE users (
181
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
182
+ github_id TEXT UNIQUE NOT NULL,
183
+ github_username TEXT NOT NULL,
184
+ email TEXT,
185
+ created_at TIMESTAMP DEFAULT NOW(),
186
+ onboarding_completed_at TIMESTAMP
187
+ );
188
+
189
+ -- Provider Credentials (encrypted)
190
+ CREATE TABLE credentials (
191
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
192
+ user_id UUID REFERENCES users(id),
193
+ provider TEXT NOT NULL, -- 'anthropic', 'openai', 'google', etc.
194
+ encrypted_access_token TEXT NOT NULL,
195
+ encrypted_refresh_token TEXT,
196
+ token_expires_at TIMESTAMP,
197
+ scopes TEXT[],
198
+ provider_account_id TEXT,
199
+ provider_account_email TEXT,
200
+ created_at TIMESTAMP DEFAULT NOW(),
201
+ last_refreshed_at TIMESTAMP,
202
+ UNIQUE(user_id, provider)
203
+ );
204
+
205
+ -- Workspaces
206
+ CREATE TABLE workspaces (
207
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
208
+ user_id UUID REFERENCES users(id),
209
+ name TEXT NOT NULL,
210
+ status TEXT DEFAULT 'provisioning', -- provisioning, running, stopped, failed
211
+ compute_provider TEXT NOT NULL, -- 'fly', 'railway', 'ecs'
212
+ compute_id TEXT, -- Provider-specific instance ID
213
+ public_url TEXT, -- Dashboard URL
214
+ internal_url TEXT, -- For API calls
215
+ created_at TIMESTAMP DEFAULT NOW(),
216
+ started_at TIMESTAMP,
217
+ stopped_at TIMESTAMP
218
+ );
219
+
220
+ -- Connected Repositories
221
+ CREATE TABLE repositories (
222
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
223
+ workspace_id UUID REFERENCES workspaces(id),
224
+ github_repo_id TEXT NOT NULL,
225
+ github_full_name TEXT NOT NULL, -- 'owner/repo'
226
+ default_branch TEXT DEFAULT 'main',
227
+ webhook_id TEXT,
228
+ last_synced_at TIMESTAMP,
229
+ created_at TIMESTAMP DEFAULT NOW()
230
+ );
231
+
232
+ -- Teams (for collaboration)
233
+ CREATE TABLE teams (
234
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
235
+ name TEXT NOT NULL,
236
+ owner_id UUID REFERENCES users(id),
237
+ created_at TIMESTAMP DEFAULT NOW()
238
+ );
239
+
240
+ CREATE TABLE team_members (
241
+ team_id UUID REFERENCES teams(id),
242
+ user_id UUID REFERENCES users(id),
243
+ role TEXT DEFAULT 'member', -- 'owner', 'admin', 'member'
244
+ PRIMARY KEY (team_id, user_id)
245
+ );
246
+ ```
247
+
248
+ ## API Endpoints
249
+
250
+ ### Auth
251
+ ```
252
+ POST /api/auth/github # Start GitHub OAuth
253
+ GET /api/auth/github/callback # OAuth callback
254
+ POST /api/auth/logout # Logout
255
+ GET /api/auth/me # Get current user
256
+ ```
257
+
258
+ ### Providers
259
+ ```
260
+ GET /api/providers # List providers + connection status
261
+ POST /api/providers/:provider/connect # Start device flow
262
+ GET /api/providers/:provider/status # Check device flow status
263
+ DELETE /api/providers/:provider # Disconnect provider
264
+ ```
265
+
266
+ ### Workspaces
267
+ ```
268
+ GET /api/workspaces # List user's workspaces
269
+ POST /api/workspaces # Create (provisions automatically)
270
+ GET /api/workspaces/:id # Get workspace details
271
+ DELETE /api/workspaces/:id # Delete workspace
272
+ POST /api/workspaces/:id/start # Start stopped workspace
273
+ POST /api/workspaces/:id/stop # Stop workspace
274
+ POST /api/workspaces/:id/restart # Restart workspace
275
+ GET /api/workspaces/:id/logs # Get logs (SSE stream)
276
+ ```
277
+
278
+ ### Repositories
279
+ ```
280
+ GET /api/repos/available # List GitHub repos user can add
281
+ POST /api/workspaces/:id/repos # Add repo to workspace
282
+ DELETE /api/workspaces/:id/repos/:repoId # Remove repo
283
+ POST /api/workspaces/:id/repos/:repoId/sync # Force sync
284
+ ```
285
+
286
+ ### Agents
287
+ ```
288
+ GET /api/workspaces/:id/agents # List agents in workspace
289
+ POST /api/workspaces/:id/agents # Spawn new agent
290
+ DELETE /api/workspaces/:id/agents/:name # Kill agent
291
+ POST /api/workspaces/:id/agents/:name/message # Send message to agent
292
+ ```
293
+
294
+ ## Workspace Provisioner Implementation
295
+
296
+ ### Interface
297
+ ```typescript
298
+ interface WorkspaceProvisioner {
299
+ provision(config: ProvisionConfig): Promise<Workspace>;
300
+ start(workspaceId: string): Promise<void>;
301
+ stop(workspaceId: string): Promise<void>;
302
+ destroy(workspaceId: string): Promise<void>;
303
+ getLogs(workspaceId: string): AsyncIterable<string>;
304
+ getStatus(workspaceId: string): Promise<WorkspaceStatus>;
305
+ }
306
+
307
+ interface ProvisionConfig {
308
+ userId: string;
309
+ name: string;
310
+ repos: string[]; // ['owner/repo', ...]
311
+ providers: string[]; // ['anthropic', 'openai', ...]
312
+ resources?: {
313
+ cpu?: string; // '1' = 1 core
314
+ memory?: string; // '512Mi', '1Gi'
315
+ };
316
+ }
317
+ ```
318
+
319
+ ### Fly.io Implementation
320
+ ```typescript
321
+ class FlyProvisioner implements WorkspaceProvisioner {
322
+ async provision(config: ProvisionConfig): Promise<Workspace> {
323
+ // 1. Create Fly app
324
+ const app = await this.fly.createApp({
325
+ name: `relay-${config.userId.slice(0, 8)}`,
326
+ org: 'agent-relay-cloud'
327
+ });
328
+
329
+ // 2. Set secrets (credentials)
330
+ const credentials = await vault.getCredentials(config.userId, config.providers);
331
+ await this.fly.setSecrets(app.name, {
332
+ ANTHROPIC_AUTH_TOKEN: credentials.anthropic?.accessToken,
333
+ OPENAI_AUTH_TOKEN: credentials.openai?.accessToken,
334
+ GITHUB_TOKEN: await this.getGitHubToken(config.userId),
335
+ REPOS: config.repos.join(','),
336
+ CLOUD_API_URL: process.env.CLOUD_API_URL,
337
+ WORKSPACE_ID: app.name
338
+ });
339
+
340
+ // 3. Deploy container
341
+ await this.fly.deploy(app.name, {
342
+ image: 'ghcr.io/agent-relay/workspace:latest',
343
+ region: 'iad', // or user's preferred region
344
+ vm: {
345
+ cpus: 1,
346
+ memory: 512
347
+ }
348
+ });
349
+
350
+ // 4. Wait for healthy
351
+ await this.waitForHealthy(app.name);
352
+
353
+ return {
354
+ id: app.name,
355
+ publicUrl: `https://${app.name}.fly.dev`,
356
+ status: 'running'
357
+ };
358
+ }
359
+ }
360
+ ```
361
+
362
+ ## Directory Structure
363
+
364
+ ```
365
+ src/cloud/
366
+ ├── index.ts # Cloud service entry point
367
+ ├── server.ts # Express server setup
368
+ ├── config.ts # Configuration
369
+
370
+ ├── api/ # API routes
371
+ │ ├── index.ts
372
+ │ ├── auth.ts # Auth routes
373
+ │ ├── providers.ts # Provider connection routes
374
+ │ ├── workspaces.ts # Workspace management
375
+ │ ├── repos.ts # Repository management
376
+ │ └── agents.ts # Agent management
377
+
378
+ ├── auth/ # Auth services
379
+ │ ├── github.ts # GitHub OAuth
380
+ │ ├── device-flow.ts # Device flow for providers
381
+ │ └── session.ts # Session management
382
+
383
+ ├── vault/ # Credential vault
384
+ │ ├── index.ts
385
+ │ ├── encryption.ts # AES-256-GCM encryption
386
+ │ └── refresh.ts # Token refresh service
387
+
388
+ ├── provisioner/ # Workspace provisioning
389
+ │ ├── index.ts # Provisioner interface
390
+ │ ├── fly.ts # Fly.io implementation
391
+ │ ├── railway.ts # Railway implementation
392
+ │ ├── docker.ts # Local Docker (dev)
393
+ │ └── workspace-image/ # Container image
394
+ │ ├── Dockerfile
395
+ │ └── entrypoint.sh
396
+
397
+ ├── db/ # Database
398
+ │ ├── index.ts # Connection
399
+ │ ├── schema.sql # Schema
400
+ │ └── migrations/ # Migrations
401
+
402
+ └── services/ # Business logic
403
+ ├── users.ts
404
+ ├── workspaces.ts
405
+ ├── credentials.ts
406
+ └── github.ts
407
+ ```
408
+
409
+ ## Environment Variables
410
+
411
+ ```bash
412
+ # Database
413
+ DATABASE_URL=postgres://user:pass@host:5432/agent_relay_cloud
414
+ REDIS_URL=redis://host:6379
415
+
416
+ # GitHub OAuth
417
+ GITHUB_CLIENT_ID=xxx
418
+ GITHUB_CLIENT_SECRET=xxx
419
+ GITHUB_APP_ID=xxx
420
+ GITHUB_APP_PRIVATE_KEY=xxx
421
+
422
+ # Provider OAuth (for device flow)
423
+ ANTHROPIC_CLIENT_ID=xxx
424
+ OPENAI_CLIENT_ID=xxx
425
+ GOOGLE_CLIENT_ID=xxx
426
+
427
+ # Encryption
428
+ VAULT_MASTER_KEY=xxx # 32 bytes, base64
429
+
430
+ # Compute provider
431
+ COMPUTE_PROVIDER=fly # fly, railway, docker
432
+ FLY_API_TOKEN=xxx
433
+ FLY_ORG=agent-relay-cloud
434
+
435
+ # Server
436
+ PORT=3000
437
+ PUBLIC_URL=https://relay.cloud
438
+ SESSION_SECRET=xxx
439
+ ```
440
+
441
+ ## Security
442
+
443
+ ### Credential Vault Encryption
444
+ - AES-256-GCM for token encryption
445
+ - Per-user keys derived from master key + user ID
446
+ - Tokens never stored in plaintext
447
+ - Encryption keys never leave control plane
448
+
449
+ ### Workspace Isolation
450
+ - Each workspace runs in isolated container
451
+ - No shared filesystem between workspaces
452
+ - Network isolation (workspaces can't talk to each other)
453
+ - Credentials injected as environment variables (encrypted in transit)
454
+
455
+ ### API Security
456
+ - All API calls require authentication
457
+ - CSRF protection on mutations
458
+ - Rate limiting per user
459
+ - Audit logging for sensitive operations
460
+
461
+ ## Scaling
462
+
463
+ ### Control Plane
464
+ - Stateless API servers behind load balancer
465
+ - PostgreSQL with read replicas
466
+ - Redis cluster for sessions/caching
467
+
468
+ ### Compute Plane
469
+ - Workspaces scale independently
470
+ - Auto-sleep inactive workspaces (cost optimization)
471
+ - Wake on webhook or API call
472
+ - Regional deployment for latency
473
+
474
+ ---
475
+
476
+ ## Cloud Coordinators (Project Groups)
477
+
478
+ Coordinators are high-level AI agents that oversee multiple projects (repositories). They enable cross-workspace communication and coordination at scale.
479
+
480
+ ### Workspace vs Project Group
481
+
482
+ **Workspace** = A single compute instance (Fly.io VM) that can hold multiple repos:
483
+ ```
484
+ ┌─────────────────────────────────────────────┐
485
+ │ Workspace (1 Fly.io VM) │
486
+ │ /repos/ │
487
+ │ ├── frontend-app/ ← Repo 1 │
488
+ │ ├── backend-api/ ← Repo 2 │
489
+ │ └── shared-libs/ ← Repo 3 │
490
+ │ │
491
+ │ agent-relay daemon (1 per workspace) │
492
+ │ Agents communicate via local Unix socket │
493
+ └─────────────────────────────────────────────┘
494
+ ```
495
+
496
+ **Project Group** = A logical grouping of repos that may span multiple workspaces:
497
+ - Repos in the **same workspace** → agents talk via local daemon (fast)
498
+ - Repos in **different workspaces** → need Redis pub/sub (cross-VM messaging)
499
+ - The **Coordinator** oversees all repos regardless of which workspace they're in
500
+
501
+ ### Architecture Overview
502
+
503
+ ```
504
+ ┌─────────────────────────────────────────────────┐
505
+ │ Cloud Dashboard │
506
+ │ (User creates Project Group, selects repos) │
507
+ └──────────────────┬──────────────────────────────┘
508
+ │ Creates Project Group
509
+
510
+ ┌─────────────────────────────────────────────────┐
511
+ │ Project Group │
512
+ │ ├─ Repo 1 (connected via Cloud Worker) │
513
+ │ ├─ Repo 2 (connected via Cloud Worker) │
514
+ │ └─ Coordinator Agent (cloud-hosted) │
515
+ └──────────────────┬──────────────────────────────┘
516
+ │ Redis Pub/Sub
517
+
518
+ ┌─────────────────────────────────────────────────┐
519
+ │ Per-Workspace Workers (Fly.io Machines) │
520
+ │ Each maintains connection to local project │
521
+ │ daemon and relays messages to/from cloud │
522
+ └─────────────────────────────────────────────────┘
523
+ ```
524
+
525
+ ### Local vs Cloud Comparison
526
+
527
+ | Feature | Local Bridge (`relay bridge`) | Cloud Coordinator |
528
+ |---------|-------------------------------|-------------------|
529
+ | Spawning | tmux sessions on local machine | Cloud-hosted process (Fly.io) |
530
+ | Messaging | Direct Unix socket connections | Redis pub/sub across workspaces |
531
+ | State | `bridge-state.json` file | PostgreSQL (project_groups table) |
532
+ | Scaling | Single machine | Multi-tenant, horizontal scaling |
533
+ | Dashboard | Local dashboard server | Cloud dashboard with auth |
534
+
535
+ ### Database Schema
536
+
537
+ ```sql
538
+ -- Project Groups (collection of repos with optional coordinator)
539
+ CREATE TABLE project_groups (
540
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
541
+ user_id UUID REFERENCES users(id),
542
+ name TEXT NOT NULL,
543
+ created_at TIMESTAMP DEFAULT NOW()
544
+ );
545
+
546
+ -- Repos in a Project Group
547
+ CREATE TABLE project_group_repos (
548
+ project_group_id UUID REFERENCES project_groups(id),
549
+ repository_id UUID REFERENCES repositories(id),
550
+ PRIMARY KEY (project_group_id, repository_id)
551
+ );
552
+
553
+ -- Coordinator Agents (one per project group)
554
+ CREATE TABLE coordinators (
555
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
556
+ project_group_id UUID REFERENCES project_groups(id) UNIQUE,
557
+ name TEXT DEFAULT 'Architect',
558
+ model TEXT DEFAULT 'claude-sonnet',
559
+ status TEXT DEFAULT 'stopped', -- stopped, starting, running, error
560
+ compute_id TEXT, -- Fly.io machine ID
561
+ started_at TIMESTAMP,
562
+ stopped_at TIMESTAMP
563
+ );
564
+ ```
565
+
566
+ ### API Endpoints
567
+
568
+ ```
569
+ # Project Groups
570
+ GET /api/project-groups # List user's project groups
571
+ POST /api/project-groups # Create project group
572
+ GET /api/project-groups/:id # Get project group details
573
+ DELETE /api/project-groups/:id # Delete project group
574
+
575
+ # Coordinators
576
+ POST /api/project-groups/:id/coordinator/enable # Start coordinator
577
+ POST /api/project-groups/:id/coordinator/disable # Stop coordinator
578
+ GET /api/project-groups/:id/coordinator/status # Get coordinator status
579
+ POST /api/project-groups/:id/coordinator/message # Send message to coordinator
580
+ ```
581
+
582
+ ### Cross-Workspace Messaging
583
+
584
+ Coordinators use Redis pub/sub for cross-workspace communication:
585
+
586
+ ```typescript
587
+ // Publish to a workspace
588
+ redis.publish(`workspace:${workspaceId}:messages`, JSON.stringify({
589
+ from: 'Architect',
590
+ to: 'Lead',
591
+ content: 'Please prioritize the auth module',
592
+ timestamp: Date.now()
593
+ }));
594
+
595
+ // Subscribe to messages for a workspace
596
+ redis.subscribe(`workspace:${workspaceId}:messages`, (message) => {
597
+ // Route to local agent via daemon
598
+ });
599
+ ```
600
+
601
+ ### Message Routing
602
+
603
+ ```
604
+ Coordinator → Redis → Workspace Worker → Local Daemon → Agent
605
+ ↑ │
606
+ └────────────────────────────────────────────────────┘
607
+ (response path)
608
+ ```
609
+
610
+ ### Coordinator Prompt Template
611
+
612
+ When a coordinator is started, it receives context about its project group:
613
+
614
+ ```
615
+ You are the Architect, a cross-project coordinator overseeing multiple codebases.
616
+
617
+ ## Connected Projects
618
+ - project-1: /repos/frontend (Lead: FrontendLead)
619
+ - project-2: /repos/backend (Lead: BackendLead)
620
+
621
+ ## Your Role
622
+ - Coordinate high-level work across all projects
623
+ - Assign tasks to project leads
624
+ - Ensure consistency and resolve cross-project dependencies
625
+ - Review overall architecture decisions
626
+
627
+ ## Cross-Project Messaging
628
+
629
+ Use this syntax to message agents in specific projects:
630
+ ->relay:project-id:AgentName <<<
631
+ Your message>>>
632
+
633
+ ->relay:project-id:* <<<
634
+ Broadcast to all agents in a project>>>
635
+
636
+ ->relay:*:* <<<
637
+ Broadcast to ALL agents in ALL projects>>>
638
+ ```
639
+
640
+ ### Dashboard UI (CoordinatorPanel)
641
+
642
+ The dashboard provides a UI for managing coordinators:
643
+
644
+ 1. **Create Project Group** - Select repositories to group together
645
+ 2. **Enable Coordinator** - Start the coordinator agent
646
+ 3. **Disable Coordinator** - Stop the coordinator agent
647
+ 4. **Delete Project Group** - Remove the group and stop coordinator
648
+
649
+ For local bridge mode, the panel shows:
650
+ - "Spawn Architect" button (when in bridge mode with multiple projects)
651
+ - CLI selector (Claude, Claude Opus, Sonnet, Codex)
652
+ - Instructions for using `relay bridge --architect` flag