agent-relay 1.5.2 → 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 (1314) 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 +65 -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.d.ts +25 -0
  747. package/packages/dashboard-server/dist/server.js +5099 -0
  748. package/packages/dashboard-server/dist/start.js +13 -0
  749. package/packages/dashboard-server/dist/types/threading.d.ts +8 -0
  750. package/packages/dashboard-server/dist/types/threading.js +2 -0
  751. package/packages/dashboard-server/dist/user-bridge.d.ts +154 -0
  752. package/packages/dashboard-server/dist/user-bridge.js +372 -0
  753. package/packages/dashboard-server/package.json +49 -0
  754. package/packages/hooks/dist/browser.d.ts +2 -0
  755. package/packages/hooks/dist/browser.js +3 -0
  756. package/packages/hooks/dist/index.d.ts +11 -0
  757. package/packages/hooks/dist/index.js +11 -0
  758. package/packages/hooks/dist/registry.js +476 -0
  759. package/packages/hooks/dist/trajectory-hooks.js +183 -0
  760. package/packages/hooks/dist/types.d.ts +285 -0
  761. package/packages/hooks/dist/types.js +10 -0
  762. package/packages/hooks/package.json +52 -0
  763. package/packages/mcp/LICENSE +190 -0
  764. package/packages/mcp/README.md +214 -0
  765. package/packages/mcp/SPEC.md +1922 -0
  766. package/packages/mcp/STAFFING_PLAN.md +294 -0
  767. package/packages/mcp/dist/bin.d.ts +12 -0
  768. package/packages/mcp/dist/bin.js +127 -0
  769. package/packages/mcp/dist/client.d.ts +68 -0
  770. package/packages/mcp/dist/client.js +115 -0
  771. package/packages/mcp/dist/cloud.d.ts +108 -0
  772. package/packages/mcp/dist/cloud.js +279 -0
  773. package/packages/mcp/dist/errors.d.ts +27 -0
  774. package/packages/mcp/dist/errors.js +48 -0
  775. package/packages/mcp/dist/index.d.ts +10 -0
  776. package/packages/mcp/dist/index.js +16 -0
  777. package/packages/mcp/dist/install-cli.d.ts +35 -0
  778. package/packages/mcp/dist/install-cli.js +157 -0
  779. package/packages/mcp/dist/install.d.ts +101 -0
  780. package/packages/mcp/dist/install.js +398 -0
  781. package/packages/mcp/dist/prompts/index.d.ts +2 -0
  782. package/packages/mcp/dist/prompts/index.js +2 -0
  783. package/packages/mcp/dist/prompts/protocol.d.ts +11 -0
  784. package/packages/mcp/dist/prompts/protocol.js +168 -0
  785. package/packages/mcp/dist/resources/agents.d.ts +11 -0
  786. package/packages/mcp/dist/resources/agents.js +17 -0
  787. package/packages/mcp/dist/resources/inbox.d.ts +11 -0
  788. package/packages/mcp/dist/resources/inbox.js +17 -0
  789. package/packages/mcp/dist/resources/index.d.ts +4 -0
  790. package/packages/mcp/dist/resources/index.js +4 -0
  791. package/packages/mcp/dist/resources/project.d.ts +11 -0
  792. package/packages/mcp/dist/resources/project.js +21 -0
  793. package/packages/mcp/dist/server.d.ts +19 -0
  794. package/packages/mcp/dist/server.js +215 -0
  795. package/packages/mcp/dist/simple.d.ts +173 -0
  796. package/packages/mcp/dist/simple.js +120 -0
  797. package/packages/mcp/dist/tools/index.d.ts +10 -0
  798. package/packages/mcp/dist/tools/index.js +10 -0
  799. package/packages/mcp/dist/tools/relay-health.d.ts +23 -0
  800. package/packages/mcp/dist/tools/relay-health.js +138 -0
  801. package/packages/mcp/dist/tools/relay-inbox.d.ts +26 -0
  802. package/packages/mcp/dist/tools/relay-inbox.js +58 -0
  803. package/packages/mcp/dist/tools/relay-logs.d.ts +20 -0
  804. package/packages/mcp/dist/tools/relay-logs.js +88 -0
  805. package/packages/mcp/dist/tools/relay-metrics.d.ts +20 -0
  806. package/packages/mcp/dist/tools/relay-metrics.js +135 -0
  807. package/packages/mcp/dist/tools/relay-release.d.ts +20 -0
  808. package/packages/mcp/dist/tools/relay-release.js +44 -0
  809. package/packages/mcp/dist/tools/relay-send.d.ts +29 -0
  810. package/packages/mcp/dist/tools/relay-send.js +71 -0
  811. package/packages/mcp/dist/tools/relay-spawn.d.ts +36 -0
  812. package/packages/mcp/dist/tools/relay-spawn.js +73 -0
  813. package/packages/mcp/dist/tools/relay-status.d.ts +11 -0
  814. package/packages/mcp/dist/tools/relay-status.js +43 -0
  815. package/packages/mcp/dist/tools/relay-who.d.ts +20 -0
  816. package/packages/mcp/dist/tools/relay-who.js +47 -0
  817. package/packages/mcp/package.json +69 -0
  818. package/packages/memory/dist/memory-hooks.d.ts +60 -0
  819. package/packages/memory/package.json +35 -0
  820. package/packages/policy/dist/agent-policy.js +665 -0
  821. package/packages/policy/dist/index.d.ts +12 -0
  822. package/packages/policy/dist/index.js +12 -0
  823. package/packages/policy/package.json +35 -0
  824. package/packages/protocol/dist/channels.d.ts +137 -0
  825. package/packages/protocol/dist/channels.js +154 -0
  826. package/packages/protocol/dist/framing.d.ts +80 -0
  827. package/packages/protocol/dist/framing.js +206 -0
  828. package/packages/protocol/dist/index.d.ts +5 -0
  829. package/packages/protocol/dist/index.js +5 -0
  830. package/packages/protocol/dist/relay-pty-schemas.d.ts +258 -0
  831. package/packages/protocol/dist/types.d.ts +341 -0
  832. package/packages/protocol/dist/types.js +8 -0
  833. package/packages/protocol/package.json +56 -0
  834. package/packages/resiliency/dist/memory-monitor.js +599 -0
  835. package/packages/resiliency/dist/provider-context.d.ts +100 -0
  836. package/packages/resiliency/package.json +33 -0
  837. package/packages/sdk/README.md +171 -0
  838. package/packages/sdk/dist/client.d.ts +181 -0
  839. package/packages/sdk/dist/client.js +695 -0
  840. package/packages/sdk/dist/index.d.ts +32 -0
  841. package/packages/sdk/dist/index.js +36 -0
  842. package/packages/sdk/dist/protocol/framing.d.ts +80 -0
  843. package/packages/sdk/dist/protocol/framing.js +206 -0
  844. package/packages/sdk/dist/protocol/index.d.ts +6 -0
  845. package/packages/sdk/dist/protocol/index.js +6 -0
  846. package/packages/sdk/dist/protocol/types.d.ts +341 -0
  847. package/packages/sdk/dist/protocol/types.js +8 -0
  848. package/packages/sdk/dist/standalone.d.ts +87 -0
  849. package/packages/sdk/dist/standalone.js +126 -0
  850. package/packages/sdk/package.json +80 -0
  851. package/packages/spawner/API.md +256 -0
  852. package/packages/spawner/dist/index.d.ts +8 -0
  853. package/packages/spawner/dist/index.js +8 -0
  854. package/packages/spawner/dist/types.d.ts +552 -0
  855. package/packages/spawner/dist/types.js +193 -0
  856. package/packages/spawner/package.json +47 -0
  857. package/packages/state/dist/agent-state.js +120 -0
  858. package/packages/state/dist/index.d.ts +8 -0
  859. package/packages/state/dist/index.js +8 -0
  860. package/packages/state/package.json +32 -0
  861. package/packages/storage/dist/adapter.d.ts +156 -0
  862. package/packages/storage/dist/batched-sqlite-adapter.d.ts +75 -0
  863. package/packages/storage/dist/batched-sqlite-adapter.js +189 -0
  864. package/packages/storage/dist/index.d.ts +5 -0
  865. package/packages/storage/dist/index.js +6 -0
  866. package/packages/storage/dist/sqlite-adapter.d.ts +113 -0
  867. package/packages/storage/dist/sqlite-adapter.js +752 -0
  868. package/packages/storage/package.json +69 -0
  869. package/packages/trajectory/dist/index.d.ts +2 -0
  870. package/packages/trajectory/dist/index.js +2 -0
  871. package/packages/trajectory/dist/integration.js +987 -0
  872. package/packages/trajectory/package.json +35 -0
  873. package/packages/user-directory/dist/index.d.ts +7 -0
  874. package/packages/user-directory/dist/index.js +7 -0
  875. package/packages/user-directory/dist/user-directory.d.ts +121 -0
  876. package/packages/user-directory/dist/user-directory.js +267 -0
  877. package/packages/user-directory/package.json +35 -0
  878. package/packages/utils/dist/command-resolver.js +80 -0
  879. package/packages/utils/dist/error-tracking.d.ts +103 -0
  880. package/packages/utils/dist/error-tracking.js +149 -0
  881. package/packages/utils/dist/index.d.ts +9 -0
  882. package/packages/utils/dist/index.js +9 -0
  883. package/packages/utils/dist/model-mapping.d.ts +28 -0
  884. package/packages/utils/dist/model-mapping.js +55 -0
  885. package/packages/utils/package.json +75 -0
  886. package/packages/wrapper/dist/__fixtures__/claude-outputs.d.ts +49 -0
  887. package/packages/wrapper/dist/__fixtures__/claude-outputs.js +443 -0
  888. package/packages/wrapper/dist/__fixtures__/codex-outputs.d.ts +9 -0
  889. package/packages/wrapper/dist/__fixtures__/codex-outputs.js +94 -0
  890. package/packages/wrapper/dist/__fixtures__/gemini-outputs.d.ts +19 -0
  891. package/packages/wrapper/dist/__fixtures__/gemini-outputs.js +144 -0
  892. package/packages/wrapper/dist/__fixtures__/index.d.ts +68 -0
  893. package/packages/wrapper/dist/__fixtures__/index.js +44 -0
  894. package/packages/wrapper/dist/base-wrapper.d.ts +225 -0
  895. package/packages/wrapper/dist/base-wrapper.js +572 -0
  896. package/packages/wrapper/dist/client.d.ts +254 -0
  897. package/packages/wrapper/dist/client.js +801 -0
  898. package/packages/wrapper/dist/id-generator.d.ts +35 -0
  899. package/packages/wrapper/dist/id-generator.js +60 -0
  900. package/packages/wrapper/dist/idle-detector.d.ts +110 -0
  901. package/packages/wrapper/dist/idle-detector.js +304 -0
  902. package/packages/wrapper/dist/index.d.ts +37 -0
  903. package/packages/wrapper/dist/index.js +47 -0
  904. package/packages/wrapper/dist/parser.d.ts +236 -0
  905. package/packages/wrapper/dist/parser.js +1238 -0
  906. package/packages/wrapper/dist/relay-pty-orchestrator.d.ts +407 -0
  907. package/packages/wrapper/dist/relay-pty-orchestrator.js +1885 -0
  908. package/packages/wrapper/dist/shared.d.ts +201 -0
  909. package/packages/wrapper/dist/shared.js +341 -0
  910. package/packages/wrapper/dist/stuck-detector.d.ts +161 -0
  911. package/packages/wrapper/dist/stuck-detector.js +402 -0
  912. package/packages/wrapper/dist/tmux-wrapper.d.ts +345 -0
  913. package/packages/wrapper/dist/tmux-wrapper.js +1747 -0
  914. package/packages/wrapper/dist/trajectory-integration.d.ts +292 -0
  915. package/packages/wrapper/dist/trajectory-integration.js +979 -0
  916. package/packages/wrapper/dist/wrapper-types.d.ts +41 -0
  917. package/packages/wrapper/dist/wrapper-types.js +7 -0
  918. package/packages/wrapper/package.json +63 -0
  919. package/scripts/setup-stripe-products.ts +312 -0
  920. package/scripts/stress-test-orchestrator-integration.mts +1366 -0
  921. package/scripts/stress-test-orchestrator.mjs +584 -0
  922. package/scripts/stress-test-relay-pty.sh +452 -0
  923. package/scripts/verify-schema.js +1 -1
  924. package/turbo.json +37 -0
  925. package/dist/bridge/config.d.ts +0 -41
  926. package/dist/bridge/config.js +0 -143
  927. package/dist/bridge/index.d.ts +0 -10
  928. package/dist/bridge/index.js +0 -10
  929. package/dist/bridge/multi-project-client.d.ts +0 -99
  930. package/dist/bridge/multi-project-client.js +0 -389
  931. package/dist/bridge/shadow-cli.js +0 -75
  932. package/dist/bridge/shadow-config.d.ts +0 -87
  933. package/dist/bridge/spawner.d.ts +0 -167
  934. package/dist/bridge/spawner.js +0 -858
  935. package/dist/bridge/types.d.ts +0 -129
  936. package/dist/bridge/utils.d.ts +0 -30
  937. package/dist/bridge/utils.js +0 -54
  938. package/dist/cli/index.js +0 -2781
  939. package/dist/cloud/api/admin.js +0 -225
  940. package/dist/cloud/api/billing.js +0 -564
  941. package/dist/cloud/api/cli-pty-runner.d.ts +0 -54
  942. package/dist/cloud/api/cli-pty-runner.js +0 -119
  943. package/dist/cloud/api/codex-auth-helper.js +0 -327
  944. package/dist/cloud/api/consensus.js +0 -259
  945. package/dist/cloud/api/coordinators.js +0 -749
  946. package/dist/cloud/api/daemons.js +0 -535
  947. package/dist/cloud/api/generic-webhooks.js +0 -129
  948. package/dist/cloud/api/github-app.js +0 -223
  949. package/dist/cloud/api/monitoring.js +0 -578
  950. package/dist/cloud/api/nango-auth.js +0 -658
  951. package/dist/cloud/api/onboarding.d.ts +0 -15
  952. package/dist/cloud/api/onboarding.js +0 -666
  953. package/dist/cloud/api/policy.js +0 -229
  954. package/dist/cloud/api/provider-env.d.ts +0 -5
  955. package/dist/cloud/api/provider-env.js +0 -27
  956. package/dist/cloud/api/providers.js +0 -511
  957. package/dist/cloud/api/repos.js +0 -576
  958. package/dist/cloud/api/teams.js +0 -279
  959. package/dist/cloud/api/test-helpers.js +0 -745
  960. package/dist/cloud/api/workspaces.js +0 -1783
  961. package/dist/cloud/billing/plans.js +0 -245
  962. package/dist/cloud/config.d.ts +0 -75
  963. package/dist/cloud/config.js +0 -109
  964. package/dist/cloud/db/drizzle.d.ts +0 -246
  965. package/dist/cloud/db/drizzle.js +0 -1249
  966. package/dist/cloud/db/schema.d.ts +0 -4854
  967. package/dist/cloud/db/schema.js +0 -610
  968. package/dist/cloud/index.d.ts +0 -11
  969. package/dist/cloud/index.js +0 -38
  970. package/dist/cloud/provisioner/index.d.ts +0 -207
  971. package/dist/cloud/provisioner/index.js +0 -2069
  972. package/dist/cloud/server.js +0 -1599
  973. package/dist/cloud/services/index.d.ts +0 -17
  974. package/dist/cloud/services/index.js +0 -25
  975. package/dist/cloud/services/intro-expiration.d.ts +0 -55
  976. package/dist/cloud/services/intro-expiration.js +0 -211
  977. package/dist/cloud/services/nango.d.ts +0 -199
  978. package/dist/cloud/services/nango.js +0 -382
  979. package/dist/cloud/services/persistence.d.ts +0 -131
  980. package/dist/config/relay-config.d.ts +0 -23
  981. package/dist/config/relay-config.js +0 -23
  982. package/dist/continuity/index.d.ts +0 -45
  983. package/dist/continuity/index.js +0 -48
  984. package/dist/continuity/types.d.ts +0 -180
  985. package/dist/continuity/types.js +0 -9
  986. package/dist/daemon/agent-manager.d.ts +0 -134
  987. package/dist/daemon/agent-manager.js +0 -564
  988. package/dist/daemon/agent-registry.js +0 -213
  989. package/dist/daemon/api.d.ts +0 -83
  990. package/dist/daemon/api.js +0 -780
  991. package/dist/daemon/channel-membership-store.d.ts +0 -48
  992. package/dist/daemon/channel-membership-store.js +0 -149
  993. package/dist/daemon/cli-auth.d.ts +0 -82
  994. package/dist/daemon/cli-auth.js +0 -700
  995. package/dist/daemon/cloud-sync.d.ts +0 -150
  996. package/dist/daemon/cloud-sync.js +0 -424
  997. package/dist/daemon/connection.d.ts +0 -130
  998. package/dist/daemon/connection.js +0 -438
  999. package/dist/daemon/consensus-integration.js +0 -371
  1000. package/dist/daemon/delivery-tracker.d.ts +0 -34
  1001. package/dist/daemon/delivery-tracker.js +0 -104
  1002. package/dist/daemon/enhanced-features.d.ts +0 -118
  1003. package/dist/daemon/enhanced-features.js +0 -178
  1004. package/dist/daemon/index.d.ts +0 -14
  1005. package/dist/daemon/index.js +0 -17
  1006. package/dist/daemon/orchestrator.d.ts +0 -157
  1007. package/dist/daemon/orchestrator.js +0 -792
  1008. package/dist/daemon/repo-manager.js +0 -384
  1009. package/dist/daemon/router.d.ts +0 -332
  1010. package/dist/daemon/router.js +0 -1259
  1011. package/dist/daemon/server.d.ts +0 -148
  1012. package/dist/daemon/server.js +0 -773
  1013. package/dist/daemon/services/browser-testing.d.ts +0 -88
  1014. package/dist/daemon/services/browser-testing.js +0 -244
  1015. package/dist/daemon/services/container-spawner.d.ts +0 -135
  1016. package/dist/daemon/services/container-spawner.js +0 -313
  1017. package/dist/daemon/sync-queue.d.ts +0 -116
  1018. package/dist/daemon/sync-queue.js +0 -361
  1019. package/dist/daemon/types.d.ts +0 -131
  1020. package/dist/daemon/user-directory.d.ts +0 -111
  1021. package/dist/daemon/user-directory.js +0 -233
  1022. package/dist/daemon/workspace-manager.js +0 -314
  1023. package/dist/dashboard/out/_next/static/chunks/116-eacf84a131b80db9.js +0 -1
  1024. package/dist/dashboard/out/_next/static/chunks/64-f4268c2ac6f4d7d4.js +0 -1
  1025. package/dist/dashboard/out/_next/static/chunks/766-aa7c8c9900ff5f53.js +0 -1
  1026. package/dist/dashboard/out/_next/static/chunks/891-a024fbe4b619cf6f.js +0 -1
  1027. package/dist/dashboard/out/_next/static/chunks/app/app/page-ffad986adfcc8b31.js +0 -1
  1028. package/dist/dashboard/out/_next/static/chunks/app/page-671037943b2f2e43.js +0 -1
  1029. package/dist/dashboard/out/_next/static/chunks/app/providers/page-57cbd738c6a73859.js +0 -1
  1030. package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-5ab0854472b402b0.js +0 -1
  1031. package/dist/dashboard/out/_next/static/css/8f9ed310f454e5a5.css +0 -1
  1032. package/dist/dashboard-server/server.d.ts +0 -15
  1033. package/dist/dashboard-server/server.js +0 -4799
  1034. package/dist/dashboard-server/start.js +0 -13
  1035. package/dist/dashboard-server/user-bridge.d.ts +0 -138
  1036. package/dist/dashboard-server/user-bridge.js +0 -348
  1037. package/dist/hooks/index.d.ts +0 -10
  1038. package/dist/hooks/index.js +0 -10
  1039. package/dist/hooks/registry.js +0 -476
  1040. package/dist/hooks/trajectory-hooks.js +0 -183
  1041. package/dist/hooks/types.d.ts +0 -284
  1042. package/dist/hooks/types.js +0 -8
  1043. package/dist/index.d.ts +0 -13
  1044. package/dist/index.js +0 -16
  1045. package/dist/memory/memory-hooks.d.ts +0 -60
  1046. package/dist/policy/agent-policy.js +0 -665
  1047. package/dist/protocol/channels.d.ts +0 -211
  1048. package/dist/protocol/channels.js +0 -154
  1049. package/dist/protocol/framing.d.ts +0 -94
  1050. package/dist/protocol/framing.js +0 -240
  1051. package/dist/protocol/index.d.ts +0 -4
  1052. package/dist/protocol/index.js +0 -4
  1053. package/dist/protocol/relay-pty-schemas.d.ts +0 -209
  1054. package/dist/protocol/types.d.ts +0 -168
  1055. package/dist/protocol/types.js +0 -6
  1056. package/dist/resiliency/memory-monitor.js +0 -593
  1057. package/dist/resiliency/provider-context.d.ts +0 -100
  1058. package/dist/shared/cli-auth-config.js +0 -320
  1059. package/dist/state/agent-state.js +0 -120
  1060. package/dist/storage/adapter.d.ts +0 -154
  1061. package/dist/storage/batched-sqlite-adapter.d.ts +0 -71
  1062. package/dist/storage/batched-sqlite-adapter.js +0 -183
  1063. package/dist/storage/sqlite-adapter.d.ts +0 -107
  1064. package/dist/storage/sqlite-adapter.js +0 -717
  1065. package/dist/trajectory/config.d.ts +0 -102
  1066. package/dist/trajectory/config.js +0 -185
  1067. package/dist/trajectory/index.d.ts +0 -8
  1068. package/dist/trajectory/index.js +0 -8
  1069. package/dist/trajectory/integration.js +0 -987
  1070. package/dist/utils/command-resolver.js +0 -76
  1071. package/dist/utils/index.d.ts +0 -4
  1072. package/dist/utils/index.js +0 -4
  1073. package/dist/utils/project-namespace.d.ts +0 -70
  1074. package/dist/utils/project-namespace.js +0 -216
  1075. package/dist/wrapper/base-wrapper.d.ts +0 -217
  1076. package/dist/wrapper/base-wrapper.js +0 -538
  1077. package/dist/wrapper/client.d.ts +0 -199
  1078. package/dist/wrapper/client.js +0 -677
  1079. package/dist/wrapper/idle-detector.d.ts +0 -102
  1080. package/dist/wrapper/idle-detector.js +0 -279
  1081. package/dist/wrapper/index.d.ts +0 -4
  1082. package/dist/wrapper/index.js +0 -7
  1083. package/dist/wrapper/parser.d.ts +0 -230
  1084. package/dist/wrapper/parser.js +0 -1178
  1085. package/dist/wrapper/pty-wrapper.d.ts +0 -343
  1086. package/dist/wrapper/pty-wrapper.js +0 -1593
  1087. package/dist/wrapper/relay-pty-orchestrator.d.ts +0 -272
  1088. package/dist/wrapper/relay-pty-orchestrator.js +0 -1023
  1089. package/dist/wrapper/shared.d.ts +0 -165
  1090. package/dist/wrapper/shared.js +0 -290
  1091. package/dist/wrapper/stuck-detector.d.ts +0 -101
  1092. package/dist/wrapper/stuck-detector.js +0 -228
  1093. package/dist/wrapper/tmux-wrapper.d.ts +0 -344
  1094. package/dist/wrapper/tmux-wrapper.js +0 -1711
  1095. /package/dist/dashboard/out/_next/static/{GJBDsC7hXtM9tz8MXWjHf → ZCFjHbkF8yDKS2md3lVgb}/_buildManifest.js +0 -0
  1096. /package/dist/dashboard/out/_next/static/{GJBDsC7hXtM9tz8MXWjHf → ZCFjHbkF8yDKS2md3lVgb}/_ssgManifest.js +0 -0
  1097. /package/dist/dashboard/out/_next/static/chunks/app/cloud/link/{page-cfeb437f08a12ed9.js → page-5011ae044b90449d.js} +0 -0
  1098. /package/dist/dashboard/out/_next/static/chunks/app/history/{page-240f91e8b06ba8ac.js → page-b2ce7c96ed0931da.js} +0 -0
  1099. /package/dist/dashboard/out/_next/static/chunks/app/metrics/{page-82938ab8fcf44694.js → page-bf2cb1e5915bc92d.js} +0 -0
  1100. /package/dist/{cli → src/cli}/index.d.ts +0 -0
  1101. /package/dist/{health-worker-manager.d.ts → src/health-worker-manager.d.ts} +0 -0
  1102. /package/dist/{health-worker-manager.js → src/health-worker-manager.js} +0 -0
  1103. /package/dist/{health-worker.d.ts → src/health-worker.d.ts} +0 -0
  1104. /package/dist/{health-worker.js → src/health-worker.js} +0 -0
  1105. /package/{dist/bridge → packages/bridge/dist}/shadow-cli.d.ts +0 -0
  1106. /package/{dist/bridge → packages/bridge/dist}/types.js +0 -0
  1107. /package/{dist/cloud → packages/cloud/dist}/api/admin.d.ts +0 -0
  1108. /package/{dist/cloud → packages/cloud/dist}/api/auth.d.ts +0 -0
  1109. /package/{dist/cloud → packages/cloud/dist}/api/auth.js +0 -0
  1110. /package/{dist/cloud → packages/cloud/dist}/api/billing.d.ts +0 -0
  1111. /package/{dist/cloud → packages/cloud/dist}/api/codex-auth-helper.d.ts +0 -0
  1112. /package/{dist/cloud → packages/cloud/dist}/api/consensus.d.ts +0 -0
  1113. /package/{dist/cloud → packages/cloud/dist}/api/coordinators.d.ts +0 -0
  1114. /package/{dist/cloud → packages/cloud/dist}/api/daemons.d.ts +0 -0
  1115. /package/{dist/cloud → packages/cloud/dist}/api/generic-webhooks.d.ts +0 -0
  1116. /package/{dist/cloud → packages/cloud/dist}/api/git.d.ts +0 -0
  1117. /package/{dist/cloud → packages/cloud/dist}/api/git.js +0 -0
  1118. /package/{dist/cloud → packages/cloud/dist}/api/github-app.d.ts +0 -0
  1119. /package/{dist/cloud → packages/cloud/dist}/api/middleware/planLimits.d.ts +0 -0
  1120. /package/{dist/cloud → packages/cloud/dist}/api/middleware/planLimits.js +0 -0
  1121. /package/{dist/cloud → packages/cloud/dist}/api/monitoring.d.ts +0 -0
  1122. /package/{dist/cloud → packages/cloud/dist}/api/nango-auth.d.ts +0 -0
  1123. /package/{dist/cloud → packages/cloud/dist}/api/policy.d.ts +0 -0
  1124. /package/{dist/cloud → packages/cloud/dist}/api/providers.d.ts +0 -0
  1125. /package/{dist/cloud → packages/cloud/dist}/api/repos.d.ts +0 -0
  1126. /package/{dist/cloud → packages/cloud/dist}/api/teams.d.ts +0 -0
  1127. /package/{dist/cloud → packages/cloud/dist}/api/test-helpers.d.ts +0 -0
  1128. /package/{dist/cloud → packages/cloud/dist}/api/usage.d.ts +0 -0
  1129. /package/{dist/cloud → packages/cloud/dist}/api/usage.js +0 -0
  1130. /package/{dist/cloud → packages/cloud/dist}/api/webhooks.d.ts +0 -0
  1131. /package/{dist/cloud → packages/cloud/dist}/api/webhooks.js +0 -0
  1132. /package/{dist/cloud → packages/cloud/dist}/api/workspaces.d.ts +0 -0
  1133. /package/{dist/cloud → packages/cloud/dist}/billing/index.d.ts +0 -0
  1134. /package/{dist/cloud → packages/cloud/dist}/billing/index.js +0 -0
  1135. /package/{dist/cloud → packages/cloud/dist}/billing/plans.d.ts +0 -0
  1136. /package/{dist/cloud → packages/cloud/dist}/billing/service.d.ts +0 -0
  1137. /package/{dist/cloud → packages/cloud/dist}/billing/service.js +0 -0
  1138. /package/{dist/cloud → packages/cloud/dist}/billing/types.d.ts +0 -0
  1139. /package/{dist/cloud → packages/cloud/dist}/billing/types.js +0 -0
  1140. /package/{dist/cloud → packages/cloud/dist}/db/bulk-ingest.d.ts +0 -0
  1141. /package/{dist/cloud → packages/cloud/dist}/db/bulk-ingest.js +0 -0
  1142. /package/{dist/cloud → packages/cloud/dist}/db/index.d.ts +0 -0
  1143. /package/{dist/cloud → packages/cloud/dist}/db/index.js +0 -0
  1144. /package/{dist/cloud → packages/cloud/dist}/server.d.ts +0 -0
  1145. /package/{dist/cloud → packages/cloud/dist}/services/auto-scaler.d.ts +0 -0
  1146. /package/{dist/cloud → packages/cloud/dist}/services/auto-scaler.js +0 -0
  1147. /package/{dist/cloud → packages/cloud/dist}/services/capacity-manager.d.ts +0 -0
  1148. /package/{dist/cloud → packages/cloud/dist}/services/capacity-manager.js +0 -0
  1149. /package/{dist/cloud → packages/cloud/dist}/services/ci-agent-spawner.d.ts +0 -0
  1150. /package/{dist/cloud → packages/cloud/dist}/services/ci-agent-spawner.js +0 -0
  1151. /package/{dist/cloud → packages/cloud/dist}/services/cloud-message-bus.d.ts +0 -0
  1152. /package/{dist/cloud → packages/cloud/dist}/services/cloud-message-bus.js +0 -0
  1153. /package/{dist/cloud → packages/cloud/dist}/services/compute-enforcement.d.ts +0 -0
  1154. /package/{dist/cloud → packages/cloud/dist}/services/compute-enforcement.js +0 -0
  1155. /package/{dist/cloud → packages/cloud/dist}/services/coordinator.d.ts +0 -0
  1156. /package/{dist/cloud → packages/cloud/dist}/services/coordinator.js +0 -0
  1157. /package/{dist/cloud → packages/cloud/dist}/services/mention-handler.d.ts +0 -0
  1158. /package/{dist/cloud → packages/cloud/dist}/services/mention-handler.js +0 -0
  1159. /package/{dist/cloud → packages/cloud/dist}/services/persistence.js +0 -0
  1160. /package/{dist/cloud → packages/cloud/dist}/services/planLimits.d.ts +0 -0
  1161. /package/{dist/cloud → packages/cloud/dist}/services/planLimits.js +0 -0
  1162. /package/{dist/cloud → packages/cloud/dist}/services/presence-registry.d.ts +0 -0
  1163. /package/{dist/cloud → packages/cloud/dist}/services/presence-registry.js +0 -0
  1164. /package/{dist/cloud → packages/cloud/dist}/services/scaling-orchestrator.d.ts +0 -0
  1165. /package/{dist/cloud → packages/cloud/dist}/services/scaling-orchestrator.js +0 -0
  1166. /package/{dist/cloud → packages/cloud/dist}/services/scaling-policy.d.ts +0 -0
  1167. /package/{dist/cloud → packages/cloud/dist}/services/scaling-policy.js +0 -0
  1168. /package/{dist/cloud → packages/cloud/dist}/services/ssh-security.d.ts +0 -0
  1169. /package/{dist/cloud → packages/cloud/dist}/services/ssh-security.js +0 -0
  1170. /package/{dist/cloud → packages/cloud/dist}/services/workspace-keepalive.d.ts +0 -0
  1171. /package/{dist/cloud → packages/cloud/dist}/services/workspace-keepalive.js +0 -0
  1172. /package/{dist/cloud → packages/cloud/dist}/webhooks/index.d.ts +0 -0
  1173. /package/{dist/cloud → packages/cloud/dist}/webhooks/index.js +0 -0
  1174. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/github.d.ts +0 -0
  1175. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/github.js +0 -0
  1176. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/index.d.ts +0 -0
  1177. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/index.js +0 -0
  1178. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/linear.d.ts +0 -0
  1179. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/linear.js +0 -0
  1180. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/slack.d.ts +0 -0
  1181. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/slack.js +0 -0
  1182. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/github.d.ts +0 -0
  1183. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/github.js +0 -0
  1184. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/index.d.ts +0 -0
  1185. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/index.js +0 -0
  1186. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/linear.d.ts +0 -0
  1187. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/linear.js +0 -0
  1188. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/slack.d.ts +0 -0
  1189. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/slack.js +0 -0
  1190. /package/{dist/cloud → packages/cloud/dist}/webhooks/router.d.ts +0 -0
  1191. /package/{dist/cloud → packages/cloud/dist}/webhooks/router.js +0 -0
  1192. /package/{dist/cloud → packages/cloud/dist}/webhooks/rules-engine.d.ts +0 -0
  1193. /package/{dist/cloud → packages/cloud/dist}/webhooks/rules-engine.js +0 -0
  1194. /package/{dist/cloud → packages/cloud/dist}/webhooks/types.d.ts +0 -0
  1195. /package/{dist/cloud → packages/cloud/dist}/webhooks/types.js +0 -0
  1196. /package/{dist/utils → packages/config/dist}/agent-config.d.ts +0 -0
  1197. /package/{dist/utils → packages/config/dist}/agent-config.js +0 -0
  1198. /package/{dist/shared → packages/config/dist}/cli-auth-config.d.ts +0 -0
  1199. /package/{dist/bridge → packages/config/dist}/shadow-config.js +0 -0
  1200. /package/{dist/bridge → packages/config/dist}/teams-config.d.ts +0 -0
  1201. /package/{dist/bridge → packages/config/dist}/teams-config.js +0 -0
  1202. /package/{dist/continuity → packages/continuity/dist}/formatter.d.ts +0 -0
  1203. /package/{dist/continuity → packages/continuity/dist}/formatter.js +0 -0
  1204. /package/{dist/continuity → packages/continuity/dist}/handoff-store.d.ts +0 -0
  1205. /package/{dist/continuity → packages/continuity/dist}/handoff-store.js +0 -0
  1206. /package/{dist/continuity → packages/continuity/dist}/ledger-store.d.ts +0 -0
  1207. /package/{dist/continuity → packages/continuity/dist}/ledger-store.js +0 -0
  1208. /package/{dist/continuity → packages/continuity/dist}/manager.d.ts +0 -0
  1209. /package/{dist/continuity → packages/continuity/dist}/manager.js +0 -0
  1210. /package/{dist/continuity → packages/continuity/dist}/parser.d.ts +0 -0
  1211. /package/{dist/continuity → packages/continuity/dist}/parser.js +0 -0
  1212. /package/{dist/daemon → packages/daemon/dist}/agent-registry.d.ts +0 -0
  1213. /package/{dist/daemon → packages/daemon/dist}/agent-signing.d.ts +0 -0
  1214. /package/{dist/daemon → packages/daemon/dist}/agent-signing.js +0 -0
  1215. /package/{dist/daemon → packages/daemon/dist}/auth.d.ts +0 -0
  1216. /package/{dist/daemon → packages/daemon/dist}/auth.js +0 -0
  1217. /package/{dist/daemon → packages/daemon/dist}/consensus-integration.d.ts +0 -0
  1218. /package/{dist/daemon → packages/daemon/dist}/consensus.d.ts +0 -0
  1219. /package/{dist/daemon → packages/daemon/dist}/consensus.js +0 -0
  1220. /package/{dist/daemon → packages/daemon/dist}/rate-limiter.d.ts +0 -0
  1221. /package/{dist/daemon → packages/daemon/dist}/rate-limiter.js +0 -0
  1222. /package/{dist/daemon → packages/daemon/dist}/registry.d.ts +0 -0
  1223. /package/{dist/daemon → packages/daemon/dist}/registry.js +0 -0
  1224. /package/{dist/daemon → packages/daemon/dist}/repo-manager.d.ts +0 -0
  1225. /package/{dist/daemon → packages/daemon/dist}/types.js +0 -0
  1226. /package/{dist/daemon → packages/daemon/dist}/workspace-manager.d.ts +0 -0
  1227. /package/{dist/dashboard-server → packages/dashboard-server/dist}/metrics.d.ts +0 -0
  1228. /package/{dist/dashboard-server → packages/dashboard-server/dist}/metrics.js +0 -0
  1229. /package/{dist/dashboard-server → packages/dashboard-server/dist}/needs-attention.d.ts +0 -0
  1230. /package/{dist/dashboard-server → packages/dashboard-server/dist}/needs-attention.js +0 -0
  1231. /package/{dist/dashboard-server → packages/dashboard-server/dist}/start.d.ts +0 -0
  1232. /package/{dist/hooks → packages/hooks/dist}/emitter.d.ts +0 -0
  1233. /package/{dist/hooks → packages/hooks/dist}/emitter.js +0 -0
  1234. /package/{dist/hooks → packages/hooks/dist}/inbox-check/hook.d.ts +0 -0
  1235. /package/{dist/hooks → packages/hooks/dist}/inbox-check/hook.js +0 -0
  1236. /package/{dist/hooks → packages/hooks/dist}/inbox-check/index.d.ts +0 -0
  1237. /package/{dist/hooks → packages/hooks/dist}/inbox-check/index.js +0 -0
  1238. /package/{dist/hooks → packages/hooks/dist}/inbox-check/types.d.ts +0 -0
  1239. /package/{dist/hooks → packages/hooks/dist}/inbox-check/types.js +0 -0
  1240. /package/{dist/hooks → packages/hooks/dist}/inbox-check/utils.d.ts +0 -0
  1241. /package/{dist/hooks → packages/hooks/dist}/inbox-check/utils.js +0 -0
  1242. /package/{dist/hooks → packages/hooks/dist}/registry.d.ts +0 -0
  1243. /package/{dist/hooks → packages/hooks/dist}/trajectory-hooks.d.ts +0 -0
  1244. /package/{dist/memory → packages/memory/dist}/adapters/index.d.ts +0 -0
  1245. /package/{dist/memory → packages/memory/dist}/adapters/index.js +0 -0
  1246. /package/{dist/memory → packages/memory/dist}/adapters/inmemory.d.ts +0 -0
  1247. /package/{dist/memory → packages/memory/dist}/adapters/inmemory.js +0 -0
  1248. /package/{dist/memory → packages/memory/dist}/adapters/supermemory.d.ts +0 -0
  1249. /package/{dist/memory → packages/memory/dist}/adapters/supermemory.js +0 -0
  1250. /package/{dist/memory → packages/memory/dist}/context-compaction.d.ts +0 -0
  1251. /package/{dist/memory → packages/memory/dist}/context-compaction.js +0 -0
  1252. /package/{dist/memory → packages/memory/dist}/factory.d.ts +0 -0
  1253. /package/{dist/memory → packages/memory/dist}/factory.js +0 -0
  1254. /package/{dist/memory → packages/memory/dist}/index.d.ts +0 -0
  1255. /package/{dist/memory → packages/memory/dist}/index.js +0 -0
  1256. /package/{dist/memory → packages/memory/dist}/memory-hooks.js +0 -0
  1257. /package/{dist/memory → packages/memory/dist}/service.d.ts +0 -0
  1258. /package/{dist/memory → packages/memory/dist}/service.js +0 -0
  1259. /package/{dist/memory → packages/memory/dist}/types.d.ts +0 -0
  1260. /package/{dist/memory → packages/memory/dist}/types.js +0 -0
  1261. /package/{dist/policy → packages/policy/dist}/agent-policy.d.ts +0 -0
  1262. /package/{dist/policy → packages/policy/dist}/cloud-policy-fetcher.d.ts +0 -0
  1263. /package/{dist/policy → packages/policy/dist}/cloud-policy-fetcher.js +0 -0
  1264. /package/{dist/utils → packages/protocol/dist}/id-generator.d.ts +0 -0
  1265. /package/{dist/utils → packages/protocol/dist}/id-generator.js +0 -0
  1266. /package/{dist/protocol → packages/protocol/dist}/relay-pty-schemas.js +0 -0
  1267. /package/{dist/resiliency → packages/resiliency/dist}/context-persistence.d.ts +0 -0
  1268. /package/{dist/resiliency → packages/resiliency/dist}/context-persistence.js +0 -0
  1269. /package/{dist/resiliency → packages/resiliency/dist}/crash-insights.d.ts +0 -0
  1270. /package/{dist/resiliency → packages/resiliency/dist}/crash-insights.js +0 -0
  1271. /package/{dist/resiliency → packages/resiliency/dist}/gossip-health.d.ts +0 -0
  1272. /package/{dist/resiliency → packages/resiliency/dist}/gossip-health.js +0 -0
  1273. /package/{dist/resiliency → packages/resiliency/dist}/health-monitor.d.ts +0 -0
  1274. /package/{dist/resiliency → packages/resiliency/dist}/health-monitor.js +0 -0
  1275. /package/{dist/resiliency → packages/resiliency/dist}/index.d.ts +0 -0
  1276. /package/{dist/resiliency → packages/resiliency/dist}/index.js +0 -0
  1277. /package/{dist/resiliency → packages/resiliency/dist}/leader-watchdog.d.ts +0 -0
  1278. /package/{dist/resiliency → packages/resiliency/dist}/leader-watchdog.js +0 -0
  1279. /package/{dist/resiliency → packages/resiliency/dist}/logger.d.ts +0 -0
  1280. /package/{dist/resiliency → packages/resiliency/dist}/logger.js +0 -0
  1281. /package/{dist/resiliency → packages/resiliency/dist}/memory-monitor.d.ts +0 -0
  1282. /package/{dist/resiliency → packages/resiliency/dist}/metrics.d.ts +0 -0
  1283. /package/{dist/resiliency → packages/resiliency/dist}/metrics.js +0 -0
  1284. /package/{dist/resiliency → packages/resiliency/dist}/provider-context.js +0 -0
  1285. /package/{dist/resiliency → packages/resiliency/dist}/stateless-lead.d.ts +0 -0
  1286. /package/{dist/resiliency → packages/resiliency/dist}/stateless-lead.js +0 -0
  1287. /package/{dist/resiliency → packages/resiliency/dist}/supervisor.d.ts +0 -0
  1288. /package/{dist/resiliency → packages/resiliency/dist}/supervisor.js +0 -0
  1289. /package/{dist/state → packages/state/dist}/agent-state.d.ts +0 -0
  1290. /package/{dist/storage → packages/storage/dist}/adapter.js +0 -0
  1291. /package/{dist/storage → packages/storage/dist}/dead-letter-queue.d.ts +0 -0
  1292. /package/{dist/storage → packages/storage/dist}/dead-letter-queue.js +0 -0
  1293. /package/{dist/storage → packages/storage/dist}/dlq-adapter.d.ts +0 -0
  1294. /package/{dist/storage → packages/storage/dist}/dlq-adapter.js +0 -0
  1295. /package/{dist/trajectory → packages/trajectory/dist}/integration.d.ts +0 -0
  1296. /package/{dist/utils → packages/utils/dist}/command-resolver.d.ts +0 -0
  1297. /package/{dist/utils → packages/utils/dist}/git-remote.d.ts +0 -0
  1298. /package/{dist/utils → packages/utils/dist}/git-remote.js +0 -0
  1299. /package/{dist/utils → packages/utils/dist}/logger.d.ts +0 -0
  1300. /package/{dist/utils → packages/utils/dist}/logger.js +0 -0
  1301. /package/{dist/utils → packages/utils/dist}/name-generator.d.ts +0 -0
  1302. /package/{dist/utils → packages/utils/dist}/name-generator.js +0 -0
  1303. /package/{dist/utils → packages/utils/dist}/precompiled-patterns.d.ts +0 -0
  1304. /package/{dist/utils → packages/utils/dist}/precompiled-patterns.js +0 -0
  1305. /package/{dist/utils → packages/utils/dist}/update-checker.d.ts +0 -0
  1306. /package/{dist/utils → packages/utils/dist}/update-checker.js +0 -0
  1307. /package/{dist/wrapper → packages/wrapper/dist}/auth-detection.d.ts +0 -0
  1308. /package/{dist/wrapper → packages/wrapper/dist}/auth-detection.js +0 -0
  1309. /package/{dist/wrapper → packages/wrapper/dist}/inbox.d.ts +0 -0
  1310. /package/{dist/wrapper → packages/wrapper/dist}/inbox.js +0 -0
  1311. /package/{dist/wrapper → packages/wrapper/dist}/prompt-composer.d.ts +0 -0
  1312. /package/{dist/wrapper → packages/wrapper/dist}/prompt-composer.js +0 -0
  1313. /package/{dist/utils → packages/wrapper/dist}/tmux-resolver.d.ts +0 -0
  1314. /package/{dist/utils → packages/wrapper/dist}/tmux-resolver.js +0 -0
@@ -1,1599 +0,0 @@
1
- /**
2
- * Agent Relay Cloud - Express Server
3
- */
4
- import express from 'express';
5
- import session from 'express-session';
6
- import cors from 'cors';
7
- import helmet from 'helmet';
8
- import crypto from 'crypto';
9
- import path from 'node:path';
10
- import http from 'node:http';
11
- import fs from 'node:fs';
12
- import { fileURLToPath } from 'node:url';
13
- import { createClient } from 'redis';
14
- import { RedisStore } from 'connect-redis';
15
- import { WebSocketServer, WebSocket } from 'ws';
16
- import { getConfig } from './config.js';
17
- import { runMigrations } from './db/index.js';
18
- import { getScalingOrchestrator, getComputeEnforcementService, getIntroExpirationService, getWorkspaceKeepaliveService } from './services/index.js';
19
- const __filename = fileURLToPath(import.meta.url);
20
- const __dirname = path.dirname(__filename);
21
- // API routers
22
- import { authRouter, requireAuth } from './api/auth.js';
23
- import { providersRouter } from './api/providers.js';
24
- import { workspacesRouter } from './api/workspaces.js';
25
- import { reposRouter } from './api/repos.js';
26
- import { onboardingRouter } from './api/onboarding.js';
27
- import { teamsRouter } from './api/teams.js';
28
- import { billingRouter } from './api/billing.js';
29
- import { usageRouter } from './api/usage.js';
30
- import { coordinatorsRouter } from './api/coordinators.js';
31
- import { daemonsRouter } from './api/daemons.js';
32
- import { monitoringRouter } from './api/monitoring.js';
33
- import { testHelpersRouter } from './api/test-helpers.js';
34
- import { webhooksRouter } from './api/webhooks.js';
35
- import { githubAppRouter } from './api/github-app.js';
36
- import { nangoAuthRouter } from './api/nango-auth.js';
37
- import { gitRouter } from './api/git.js';
38
- import { codexAuthHelperRouter } from './api/codex-auth-helper.js';
39
- import { adminRouter } from './api/admin.js';
40
- import { consensusRouter } from './api/consensus.js';
41
- import { db } from './db/index.js';
42
- import { validateSshSecurityConfig } from './services/ssh-security.js';
43
- import { registerUserPresence, unregisterUserPresence, updateUserLastSeen } from './services/presence-registry.js';
44
- import { cloudMessageBus } from './services/cloud-message-bus.js';
45
- /**
46
- * Proxy a request to the user's primary running workspace
47
- */
48
- async function proxyToUserWorkspace(req, res, path, options) {
49
- const userId = req.session.userId;
50
- if (!userId) {
51
- res.status(401).json({ error: 'Unauthorized' });
52
- return;
53
- }
54
- try {
55
- // Find user's running workspace
56
- const workspaces = await db.workspaces.findByUserId(userId);
57
- const runningWorkspace = workspaces.find(w => w.status === 'running' && w.publicUrl);
58
- if (!runningWorkspace || !runningWorkspace.publicUrl) {
59
- res.status(404).json({ error: 'No running workspace found', success: false });
60
- return;
61
- }
62
- // Proxy to workspace
63
- const targetUrl = `${runningWorkspace.publicUrl}${path}`;
64
- console.log(`[workspace-proxy] ${options?.method || 'GET'} ${targetUrl}`);
65
- const fetchOptions = {
66
- method: options?.method || 'GET',
67
- headers: { 'Content-Type': 'application/json' },
68
- };
69
- if (options?.body) {
70
- fetchOptions.body = JSON.stringify(options.body);
71
- }
72
- const proxyRes = await fetch(targetUrl, fetchOptions);
73
- const contentType = proxyRes.headers.get('content-type') || '';
74
- console.log(`[workspace-proxy] Response: ${proxyRes.status} ${proxyRes.statusText}, content-type: ${contentType}`);
75
- // Check if response is JSON
76
- if (!contentType.includes('application/json')) {
77
- const text = await proxyRes.text();
78
- console.error(`[workspace-proxy] Non-JSON response: ${text.substring(0, 200)}`);
79
- res.status(502).json({ error: 'Workspace returned non-JSON response', success: false });
80
- return;
81
- }
82
- const data = await proxyRes.json();
83
- res.status(proxyRes.status).json(data);
84
- }
85
- catch (error) {
86
- console.error('[workspace-proxy] Error:', error);
87
- res.status(500).json({ error: 'Failed to proxy request to workspace', success: false });
88
- }
89
- }
90
- export async function createServer() {
91
- const config = getConfig();
92
- // Validate security configuration at startup
93
- validateSshSecurityConfig();
94
- const app = express();
95
- app.set('trust proxy', 1);
96
- // Redis client for sessions
97
- const redisClient = createClient({ url: config.redisUrl });
98
- redisClient.on('error', (err) => {
99
- console.error('[redis] error', err);
100
- });
101
- redisClient.on('reconnecting', () => {
102
- console.warn('[redis] reconnecting...');
103
- });
104
- await redisClient.connect();
105
- // Middleware
106
- // Configure helmet to allow Next.js inline scripts and Nango Connect UI
107
- app.use(helmet({
108
- contentSecurityPolicy: {
109
- directives: {
110
- defaultSrc: ["'self'"],
111
- scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'", "https://connect.nango.dev"],
112
- styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com", "https://connect.nango.dev"],
113
- fontSrc: ["'self'", "https://fonts.gstatic.com", "data:"],
114
- imgSrc: ["'self'", "data:", "https:", "blob:"],
115
- connectSrc: ["'self'", "wss:", "ws:", "https:", "https://api.nango.dev", "https://connect.nango.dev"],
116
- frameSrc: ["'self'", "https://connect.nango.dev", "https://github.com"],
117
- childSrc: ["'self'", "https://connect.nango.dev", "blob:"],
118
- workerSrc: ["'self'", "blob:"],
119
- },
120
- },
121
- }));
122
- app.use(cors({
123
- origin: config.publicUrl,
124
- credentials: true,
125
- }));
126
- // Custom JSON parser that preserves raw body for webhook signature verification
127
- // Increase limit to 10mb for base64 image uploads (screenshots)
128
- app.use(express.json({
129
- limit: '10mb',
130
- verify: (req, _res, buf) => {
131
- // Store raw body for webhook signature verification
132
- req.rawBody = buf.toString();
133
- },
134
- }));
135
- // Session middleware
136
- app.use(session({
137
- store: new RedisStore({ client: redisClient }),
138
- secret: config.sessionSecret,
139
- resave: false,
140
- saveUninitialized: false,
141
- cookie: {
142
- secure: config.publicUrl.startsWith('https'),
143
- httpOnly: true,
144
- sameSite: 'lax',
145
- maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
146
- },
147
- }));
148
- // Basic audit log (request/response)
149
- app.use((req, res, next) => {
150
- const started = Date.now();
151
- res.on('finish', () => {
152
- const duration = Date.now() - started;
153
- const user = req.session?.userId ?? 'anon';
154
- console.log(`[audit] ${req.method} ${req.originalUrl} ${res.statusCode} user=${user} ip=${req.ip} ${duration}ms`);
155
- });
156
- next();
157
- });
158
- // Simple in-memory rate limiting per IP
159
- const RATE_LIMIT_WINDOW_MS = 60_000;
160
- // Higher limit in development mode
161
- const RATE_LIMIT_MAX = process.env.NODE_ENV === 'development' ? 1000 : 300;
162
- const rateLimits = new Map();
163
- app.use((req, res, next) => {
164
- // Skip rate limiting for localhost in development
165
- if (process.env.NODE_ENV === 'development') {
166
- const ip = req.ip || '';
167
- if (ip === '127.0.0.1' || ip === '::1' || ip === '::ffff:127.0.0.1') {
168
- return next();
169
- }
170
- }
171
- const now = Date.now();
172
- const key = req.ip || 'unknown';
173
- const entry = rateLimits.get(key);
174
- if (!entry || entry.resetAt <= now) {
175
- rateLimits.set(key, { count: 1, resetAt: now + RATE_LIMIT_WINDOW_MS });
176
- }
177
- else {
178
- entry.count += 1;
179
- }
180
- const current = rateLimits.get(key);
181
- res.setHeader('X-RateLimit-Limit', RATE_LIMIT_MAX.toString());
182
- res.setHeader('X-RateLimit-Remaining', Math.max(RATE_LIMIT_MAX - current.count, 0).toString());
183
- res.setHeader('X-RateLimit-Reset', Math.floor(current.resetAt / 1000).toString());
184
- if (current.count > RATE_LIMIT_MAX) {
185
- return res.status(429).json({ error: 'Too many requests' });
186
- }
187
- // Opportunistic cleanup
188
- if (rateLimits.size > 5000) {
189
- for (const [ip, data] of rateLimits) {
190
- if (data.resetAt <= now) {
191
- rateLimits.delete(ip);
192
- }
193
- }
194
- }
195
- next();
196
- });
197
- // Lightweight CSRF protection using session token
198
- const SAFE_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
199
- // Paths exempt from CSRF (webhooks from external services, workspace proxy, local auth callbacks, admin API)
200
- const CSRF_EXEMPT_PATHS = [
201
- '/api/webhooks/',
202
- '/api/auth/nango/webhook',
203
- '/api/auth/codex-helper/callback',
204
- '/api/admin/', // Admin API uses X-Admin-Secret header auth
205
- '/api/channels/', // Channels API routes to local daemon, not cloud
206
- ];
207
- // Additional pattern for workspace proxy routes (contains /proxy/)
208
- const isWorkspaceProxyRoute = (path) => /^\/api\/workspaces\/[^/]+\/proxy\//.test(path);
209
- app.use((req, res, next) => {
210
- // Skip CSRF for webhook endpoints and workspace proxy routes
211
- const isExemptPath = CSRF_EXEMPT_PATHS.some(exemptPath => req.path.startsWith(exemptPath));
212
- if (isExemptPath || isWorkspaceProxyRoute(req.path)) {
213
- return next();
214
- }
215
- if (!req.session)
216
- return res.status(500).json({ error: 'Session unavailable' });
217
- // Generate CSRF token if not present
218
- // Use session.save() to ensure the session is persisted even for unauthenticated users
219
- // This is necessary because saveUninitialized: false won't auto-save new sessions
220
- if (!req.session.csrfToken) {
221
- req.session.csrfToken = crypto.randomBytes(32).toString('hex');
222
- // Explicitly save session to persist the CSRF token
223
- req.session.save((err) => {
224
- if (err) {
225
- console.error('[csrf] Failed to save session:', err);
226
- }
227
- });
228
- }
229
- res.setHeader('X-CSRF-Token', req.session.csrfToken);
230
- if (SAFE_METHODS.has(req.method.toUpperCase())) {
231
- return next();
232
- }
233
- // Skip CSRF for Bearer-authenticated endpoints (daemon API, test helpers)
234
- const authHeader = req.get('authorization');
235
- if (authHeader?.startsWith('Bearer ')) {
236
- return next();
237
- }
238
- // Skip CSRF for admin API key authenticated requests
239
- const adminSecret = req.get('x-admin-secret');
240
- if (adminSecret) {
241
- return next();
242
- }
243
- // Skip CSRF for test endpoints in non-production
244
- if (process.env.NODE_ENV !== 'production' && req.path.startsWith('/api/test/')) {
245
- return next();
246
- }
247
- const token = req.get('x-csrf-token');
248
- if (!token || token !== req.session.csrfToken) {
249
- console.log(`[csrf] Token mismatch: received=${token?.substring(0, 8)}... expected=${req.session.csrfToken?.substring(0, 8)}...`);
250
- return res.status(403).json({
251
- error: 'CSRF token invalid or missing',
252
- code: 'CSRF_MISMATCH',
253
- });
254
- }
255
- return next();
256
- });
257
- // Health check
258
- app.get('/health', (req, res) => {
259
- res.json({ status: 'ok', timestamp: new Date().toISOString() });
260
- });
261
- // API routes
262
- //
263
- // IMPORTANT: Route order matters! Routes with non-session auth (webhooks, API keys, tokens)
264
- // must be mounted BEFORE teamsRouter, which catches all /api/* with requireAuth.
265
- //
266
- // --- Routes with alternative auth (must be before teamsRouter) ---
267
- app.use('/api/auth', authRouter); // Login endpoints (public)
268
- app.use('/api/auth/nango', nangoAuthRouter); // Nango webhook (signature verification)
269
- app.use('/api/auth/codex-helper', codexAuthHelperRouter);
270
- app.use('/api/git', gitRouter); // Workspace token auth
271
- app.use('/api/webhooks', webhooksRouter); // GitHub webhooks (signature verification)
272
- app.use('/api/monitoring', monitoringRouter); // Daemon API key auth endpoints
273
- app.use('/api/daemons', daemonsRouter); // Daemon API key auth endpoints
274
- app.use('/api/admin', adminRouter); // Admin API secret auth
275
- // --- Routes with session auth ---
276
- app.use('/api/providers', providersRouter);
277
- app.use('/api/workspaces', workspacesRouter);
278
- app.use('/api', consensusRouter); // Consensus API (nested under /api/workspaces/:id/consensus)
279
- app.use('/api/repos', reposRouter);
280
- app.use('/api/onboarding', onboardingRouter);
281
- app.use('/api/billing', billingRouter);
282
- app.use('/api/usage', usageRouter);
283
- app.use('/api/project-groups', coordinatorsRouter);
284
- app.use('/api/github-app', githubAppRouter);
285
- // Trajectory proxy routes - auto-detect user's workspace and forward
286
- // These are convenience routes so the dashboard doesn't need to know the workspace ID
287
- // MUST be before teamsRouter to avoid being caught by its catch-all
288
- app.get('/api/trajectory', requireAuth, async (req, res) => {
289
- await proxyToUserWorkspace(req, res, '/api/trajectory');
290
- });
291
- app.get('/api/trajectory/steps', requireAuth, async (req, res) => {
292
- const queryString = req.query.trajectoryId
293
- ? `?trajectoryId=${encodeURIComponent(req.query.trajectoryId)}`
294
- : '';
295
- await proxyToUserWorkspace(req, res, `/api/trajectory/steps${queryString}`);
296
- });
297
- app.get('/api/trajectory/history', requireAuth, async (req, res) => {
298
- await proxyToUserWorkspace(req, res, '/api/trajectory/history');
299
- });
300
- // Channel proxy routes - forward to local dashboard-server (not workspace)
301
- // Channels talk to the local daemon, so they need the local dashboard-server
302
- // MUST be before teamsRouter to avoid being caught by its catch-all
303
- // Auto-detect local dashboard URL if not configured
304
- let localDashboardUrl = config.localDashboardUrl;
305
- const defaultPorts = [3889, 3888, 3890]; // 3889 first (common alternate port)
306
- async function detectLocalDashboard() {
307
- console.log('[channel-proxy] Auto-detecting local dashboard...');
308
- for (const port of defaultPorts) {
309
- try {
310
- const controller = new AbortController();
311
- const timeout = setTimeout(() => controller.abort(), 2000);
312
- const res = await fetch(`http://localhost:${port}/health`, {
313
- method: 'GET',
314
- signal: controller.signal,
315
- });
316
- clearTimeout(timeout);
317
- if (res.ok) {
318
- console.log(`[channel-proxy] Detected local dashboard at http://localhost:${port}`);
319
- return `http://localhost:${port}`;
320
- }
321
- console.log(`[channel-proxy] Port ${port}: responded but not OK (${res.status})`);
322
- }
323
- catch (err) {
324
- const msg = err instanceof Error ? err.message : String(err);
325
- console.log(`[channel-proxy] Port ${port}: ${msg}`);
326
- }
327
- }
328
- console.log('[channel-proxy] No local dashboard detected, using fallback');
329
- return null;
330
- }
331
- // Detect at startup if not configured - use a promise to ensure detection completes before first use
332
- let detectionPromise = null;
333
- if (localDashboardUrl) {
334
- console.log(`[channel-proxy] Using configured dashboard URL: ${localDashboardUrl}`);
335
- }
336
- else {
337
- // Start detection immediately
338
- detectionPromise = detectLocalDashboard().then((detected) => {
339
- if (detected) {
340
- localDashboardUrl = detected;
341
- }
342
- else {
343
- localDashboardUrl = 'http://localhost:3889';
344
- console.log(`[channel-proxy] Falling back to ${localDashboardUrl}`);
345
- }
346
- });
347
- }
348
- async function getLocalDashboardUrl() {
349
- // Wait for detection to complete if it's in progress
350
- if (detectionPromise) {
351
- await detectionPromise;
352
- detectionPromise = null;
353
- }
354
- // If still not set (shouldn't happen), detect now
355
- if (!localDashboardUrl) {
356
- const detected = await detectLocalDashboard();
357
- localDashboardUrl = detected || 'http://localhost:3889';
358
- }
359
- return localDashboardUrl;
360
- }
361
- async function proxyToLocalDashboard(req, res, path, options) {
362
- try {
363
- const dashboardUrl = await getLocalDashboardUrl();
364
- const targetUrl = `${dashboardUrl}${path}`;
365
- console.log(`[channel-proxy] ${options?.method || 'GET'} ${targetUrl}`);
366
- const fetchOptions = {
367
- method: options?.method || 'GET',
368
- headers: { 'Content-Type': 'application/json' },
369
- };
370
- if (options?.body) {
371
- fetchOptions.body = JSON.stringify(options.body);
372
- }
373
- const proxyRes = await fetch(targetUrl, fetchOptions);
374
- const contentType = proxyRes.headers.get('content-type') || '';
375
- if (!contentType.includes('application/json')) {
376
- const text = await proxyRes.text();
377
- console.error(`[channel-proxy] Non-JSON response from ${targetUrl}: ${text.substring(0, 100)}`);
378
- res.status(502).json({
379
- error: 'Local dashboard not available or returned non-JSON response',
380
- hint: 'Make sure the dashboard-server is running (agent-relay start)',
381
- });
382
- return;
383
- }
384
- const data = await proxyRes.json();
385
- res.status(proxyRes.status).json(data);
386
- }
387
- catch (error) {
388
- console.error('[channel-proxy] Error:', error);
389
- res.status(502).json({
390
- error: 'Failed to connect to local dashboard',
391
- hint: 'Make sure the dashboard-server is running (agent-relay start)',
392
- });
393
- }
394
- }
395
- // =========================================================================
396
- // Channel metadata endpoints (stored in cloud PostgreSQL)
397
- // =========================================================================
398
- /**
399
- * GET /api/channels - List channels for a workspace
400
- * Channels are workspace-scoped, not user-scoped
401
- */
402
- app.get('/api/channels', requireAuth, async (req, res) => {
403
- try {
404
- const workspaceId = req.query.workspaceId;
405
- if (!workspaceId) {
406
- return res.status(400).json({ error: 'workspaceId query param required' });
407
- }
408
- // Verify user has access to this workspace
409
- const userId = req.session.userId;
410
- const workspace = await db.workspaces.findById(workspaceId);
411
- if (!workspace) {
412
- return res.status(404).json({ error: 'Workspace not found' });
413
- }
414
- if (workspace.userId !== userId) {
415
- const membership = await db.workspaceMembers.findMembership(workspaceId, userId);
416
- if (!membership || !membership.acceptedAt) {
417
- return res.status(403).json({ error: 'Access denied' });
418
- }
419
- }
420
- const allChannels = await db.channels.findByWorkspaceId(workspaceId);
421
- const activeChannels = allChannels.filter(c => c.status === 'active');
422
- const archivedChannels = allChannels.filter(c => c.status === 'archived');
423
- // Get member counts for all channels in one query
424
- const channelUuids = allChannels.map(c => c.id);
425
- const memberCounts = await db.channelMembers.countByChannelIds(channelUuids);
426
- // Transform to API response format
427
- const mapChannel = (c) => ({
428
- id: c.channelId,
429
- name: c.name,
430
- description: c.description,
431
- visibility: c.visibility,
432
- status: c.status,
433
- createdAt: c.createdAt.toISOString(),
434
- createdBy: c.createdBy || '__system__',
435
- lastActivityAt: c.lastActivityAt?.toISOString(),
436
- memberCount: memberCounts.get(c.id) ?? 0,
437
- unreadCount: 0,
438
- hasMentions: false,
439
- isDm: c.channelId.startsWith('dm:'),
440
- });
441
- res.json({
442
- channels: activeChannels.map(mapChannel),
443
- archivedChannels: archivedChannels.map(mapChannel),
444
- });
445
- }
446
- catch (error) {
447
- console.error('[channels] Error listing channels:', error);
448
- res.status(500).json({ error: 'Failed to list channels' });
449
- }
450
- });
451
- /**
452
- * POST /api/channels - Create a new channel
453
- */
454
- app.post('/api/channels', requireAuth, express.json(), async (req, res) => {
455
- try {
456
- const { name, description, isPrivate, workspaceId, invites } = req.body;
457
- if (!name || !workspaceId) {
458
- return res.status(400).json({ error: 'name and workspaceId are required' });
459
- }
460
- // Verify user has access to this workspace
461
- const userId = req.session.userId;
462
- const workspace = await db.workspaces.findById(workspaceId);
463
- if (!workspace) {
464
- return res.status(404).json({ error: 'Workspace not found' });
465
- }
466
- if (workspace.userId !== userId) {
467
- const membership = await db.workspaceMembers.findMembership(workspaceId, userId);
468
- if (!membership || !membership.acceptedAt) {
469
- return res.status(403).json({ error: 'Access denied' });
470
- }
471
- }
472
- // Get creator username from session
473
- const user = await db.users.findById(userId);
474
- const createdBy = user?.githubUsername || 'unknown';
475
- // Normalize channel name (remove # prefix if present)
476
- const channelId = name.startsWith('#') ? name.slice(1) : name;
477
- const displayName = channelId;
478
- // Check if channel already exists
479
- const existing = await db.channels.findByWorkspaceAndChannelId(workspaceId, channelId);
480
- if (existing) {
481
- return res.status(409).json({ error: 'Channel already exists' });
482
- }
483
- // Create the channel
484
- console.log('[channels] Creating channel:', { workspaceId, channelId, displayName, createdBy });
485
- let channel;
486
- try {
487
- channel = await db.channels.create({
488
- workspaceId,
489
- channelId,
490
- name: displayName,
491
- description,
492
- visibility: isPrivate ? 'private' : 'public',
493
- status: 'active',
494
- createdBy,
495
- });
496
- console.log('[channels] Channel created:', channel.id);
497
- }
498
- catch (createError) {
499
- const err = createError;
500
- console.error('[channels] Failed to create channel in database:', {
501
- message: err.message,
502
- stack: err.stack,
503
- });
504
- throw createError;
505
- }
506
- // Add creator as owner
507
- try {
508
- await db.channelMembers.addMember({
509
- channelId: channel.id,
510
- memberId: createdBy,
511
- memberType: 'user',
512
- role: 'owner',
513
- });
514
- console.log('[channels] Added creator as owner:', createdBy);
515
- }
516
- catch (memberError) {
517
- const err = memberError;
518
- console.error('[channels] Failed to add channel member:', {
519
- message: err.message,
520
- stack: err.stack,
521
- channelId: channel.id,
522
- memberId: createdBy,
523
- });
524
- throw memberError;
525
- }
526
- // Handle invites if provided
527
- // Supports: comma-separated string, array of strings, or array of {id, type} objects
528
- const addedMembers = [
529
- { id: createdBy, type: 'user', role: 'owner' },
530
- ];
531
- const memberWarnings = [];
532
- if (invites) {
533
- let inviteList = [];
534
- if (typeof invites === 'string') {
535
- // Comma-separated string: "alice,bob" -> all as users
536
- inviteList = invites.split(',')
537
- .map((s) => s.trim())
538
- .filter(Boolean)
539
- .map(id => ({ id, type: 'user' }));
540
- }
541
- else if (Array.isArray(invites)) {
542
- // Array of strings or objects
543
- inviteList = invites.map((inv) => {
544
- if (typeof inv === 'string') {
545
- return { id: inv, type: 'user' };
546
- }
547
- return {
548
- id: inv.id,
549
- type: (inv.type === 'agent' ? 'agent' : 'user'),
550
- };
551
- });
552
- }
553
- for (const invitee of inviteList) {
554
- await db.channelMembers.addMember({
555
- channelId: channel.id,
556
- memberId: invitee.id,
557
- memberType: invitee.type,
558
- role: 'member',
559
- invitedBy: createdBy,
560
- });
561
- addedMembers.push({ id: invitee.id, type: invitee.type, role: 'member' });
562
- // For agent members, sync to local daemon's in-memory channel membership
563
- if (invitee.type === 'agent') {
564
- try {
565
- const channelName = channelId.startsWith('#') ? channelId : `#${channelId}`;
566
- // Route to local dashboard where the daemon and channel routing lives
567
- const dashboardUrl = await getLocalDashboardUrl();
568
- const joinResponse = await fetch(`${dashboardUrl}/api/channels/admin-join`, {
569
- method: 'POST',
570
- headers: { 'Content-Type': 'application/json' },
571
- body: JSON.stringify({ channel: channelName, member: invitee.id, workspaceId }),
572
- });
573
- const joinResult = await joinResponse.json();
574
- console.log(`[channels] Synced agent ${invitee.id} to channel ${channelName} via local dashboard`);
575
- // Check for warning about unconnected agent
576
- if (joinResult.warning) {
577
- memberWarnings.push({ member: invitee.id, warning: joinResult.warning });
578
- console.log(`[channels] Warning for ${invitee.id}: ${joinResult.warning}`);
579
- }
580
- }
581
- catch (err) {
582
- // Non-fatal - daemon sync is best-effort
583
- console.warn(`[channels] Failed to sync agent ${invitee.id} to daemon:`, err);
584
- }
585
- }
586
- }
587
- }
588
- res.status(201).json({
589
- success: true,
590
- channel: {
591
- id: channel.channelId,
592
- name: channel.name,
593
- description: channel.description,
594
- visibility: channel.visibility,
595
- status: channel.status,
596
- createdAt: channel.createdAt.toISOString(),
597
- createdBy: channel.createdBy,
598
- members: addedMembers,
599
- },
600
- warnings: memberWarnings.length > 0 ? memberWarnings : undefined,
601
- });
602
- }
603
- catch (error) {
604
- const err = error;
605
- console.error('[channels] Error creating channel:', {
606
- message: err.message,
607
- stack: err.stack,
608
- name: err.name,
609
- workspaceId: req.body.workspaceId,
610
- channelName: req.body.name,
611
- });
612
- // Include error message for debugging (safe since this is authenticated)
613
- res.status(500).json({
614
- error: 'Failed to create channel',
615
- message: err.message,
616
- });
617
- }
618
- });
619
- /**
620
- * POST /api/channels/join - Join a channel
621
- */
622
- app.post('/api/channels/join', requireAuth, express.json(), async (req, res) => {
623
- try {
624
- const { channel: rawChannelId, workspaceId, username } = req.body;
625
- if (!rawChannelId || !workspaceId) {
626
- return res.status(400).json({ error: 'channel and workspaceId are required' });
627
- }
628
- // Normalize channel ID (remove # prefix if present)
629
- const channelId = rawChannelId.startsWith('#') ? rawChannelId.slice(1) : rawChannelId;
630
- const userId = req.session.userId;
631
- const user = await db.users.findById(userId);
632
- const memberId = username || user?.githubUsername || 'unknown';
633
- // Find the channel
634
- const channel = await db.channels.findByWorkspaceAndChannelId(workspaceId, channelId);
635
- if (!channel) {
636
- return res.status(404).json({ error: 'Channel not found' });
637
- }
638
- // Check if already a member
639
- const existing = await db.channelMembers.findMembership(channel.id, memberId);
640
- if (!existing) {
641
- await db.channelMembers.addMember({
642
- channelId: channel.id,
643
- memberId,
644
- memberType: 'user',
645
- role: 'member',
646
- });
647
- }
648
- // Also subscribe the user on the daemon side for real-time messages
649
- try {
650
- const dashboardUrl = await getLocalDashboardUrl();
651
- const channelWithHash = rawChannelId.startsWith('#') ? rawChannelId : `#${rawChannelId}`;
652
- await fetch(`${dashboardUrl}/api/channels/subscribe`, {
653
- method: 'POST',
654
- headers: { 'Content-Type': 'application/json' },
655
- body: JSON.stringify({
656
- username: memberId,
657
- channels: [channelWithHash],
658
- workspaceId,
659
- }),
660
- });
661
- console.log(`[cloud] Subscribed ${memberId} to ${channelWithHash} on local daemon`);
662
- }
663
- catch (err) {
664
- // Non-fatal - daemon sync is best-effort
665
- console.warn(`[cloud] Failed to sync join to daemon:`, err);
666
- }
667
- res.json({ success: true, channel: channelId });
668
- }
669
- catch (error) {
670
- console.error('[channels] Error joining channel:', error);
671
- res.status(500).json({ error: 'Failed to join channel' });
672
- }
673
- });
674
- /**
675
- * POST /api/channels/leave - Leave a channel
676
- */
677
- app.post('/api/channels/leave', requireAuth, express.json(), async (req, res) => {
678
- try {
679
- const { channel: rawChannelId, workspaceId, username } = req.body;
680
- if (!rawChannelId || !workspaceId) {
681
- return res.status(400).json({ error: 'channel and workspaceId are required' });
682
- }
683
- // Normalize channel ID (remove # prefix if present)
684
- const channelId = rawChannelId.startsWith('#') ? rawChannelId.slice(1) : rawChannelId;
685
- const userId = req.session.userId;
686
- const user = await db.users.findById(userId);
687
- const memberId = username || user?.githubUsername || 'unknown';
688
- const channel = await db.channels.findByWorkspaceAndChannelId(workspaceId, channelId);
689
- if (!channel) {
690
- return res.status(404).json({ error: 'Channel not found' });
691
- }
692
- await db.channelMembers.removeMember(channel.id, memberId);
693
- res.json({ success: true, channel: channelId });
694
- }
695
- catch (error) {
696
- console.error('[channels] Error leaving channel:', error);
697
- res.status(500).json({ error: 'Failed to leave channel' });
698
- }
699
- });
700
- /**
701
- * POST /api/channels/invite - Invite users to a channel
702
- */
703
- app.post('/api/channels/invite', requireAuth, express.json(), async (req, res) => {
704
- try {
705
- const { channel: rawChannelId, workspaceId, invites, invitedBy } = req.body;
706
- if (!rawChannelId || !workspaceId || !invites) {
707
- return res.status(400).json({ error: 'channel, workspaceId, and invites are required' });
708
- }
709
- // Normalize channel ID (remove # prefix if present)
710
- const channelId = rawChannelId.startsWith('#') ? rawChannelId.slice(1) : rawChannelId;
711
- const channel = await db.channels.findByWorkspaceAndChannelId(workspaceId, channelId);
712
- if (!channel) {
713
- return res.status(404).json({ error: 'Channel not found' });
714
- }
715
- const inviteList = typeof invites === 'string'
716
- ? invites.split(',').map((s) => s.trim()).filter(Boolean)
717
- : invites;
718
- const results = [];
719
- for (const invitee of inviteList) {
720
- const existing = await db.channelMembers.findMembership(channel.id, invitee);
721
- if (!existing) {
722
- await db.channelMembers.addMember({
723
- channelId: channel.id,
724
- memberId: invitee,
725
- memberType: 'user',
726
- role: 'member',
727
- invitedBy,
728
- });
729
- results.push({ username: invitee, success: true });
730
- }
731
- else {
732
- results.push({ username: invitee, success: true, reason: 'already_member' });
733
- }
734
- }
735
- res.json({ channel: channelId, invited: results });
736
- }
737
- catch (error) {
738
- console.error('[channels] Error inviting to channel:', error);
739
- res.status(500).json({ error: 'Failed to invite to channel' });
740
- }
741
- });
742
- /**
743
- * POST /api/channels/archive - Archive a channel
744
- */
745
- app.post('/api/channels/archive', requireAuth, express.json(), async (req, res) => {
746
- try {
747
- const { channel: rawChannelId, workspaceId } = req.body;
748
- if (!rawChannelId || !workspaceId) {
749
- return res.status(400).json({ error: 'channel and workspaceId are required' });
750
- }
751
- // Normalize channel ID (remove # prefix if present)
752
- const channelId = rawChannelId.startsWith('#') ? rawChannelId.slice(1) : rawChannelId;
753
- const channel = await db.channels.findByWorkspaceAndChannelId(workspaceId, channelId);
754
- if (!channel) {
755
- return res.status(404).json({ error: 'Channel not found' });
756
- }
757
- await db.channels.archive(channel.id);
758
- res.json({ success: true, channel: channelId, status: 'archived' });
759
- }
760
- catch (error) {
761
- console.error('[channels] Error archiving channel:', error);
762
- res.status(500).json({ error: 'Failed to archive channel' });
763
- }
764
- });
765
- /**
766
- * POST /api/channels/unarchive - Unarchive a channel
767
- */
768
- app.post('/api/channels/unarchive', requireAuth, express.json(), async (req, res) => {
769
- try {
770
- const { channel: rawChannelId, workspaceId } = req.body;
771
- if (!rawChannelId || !workspaceId) {
772
- return res.status(400).json({ error: 'channel and workspaceId are required' });
773
- }
774
- // Normalize channel ID (remove # prefix if present)
775
- const channelId = rawChannelId.startsWith('#') ? rawChannelId.slice(1) : rawChannelId;
776
- const channel = await db.channels.findByWorkspaceAndChannelId(workspaceId, channelId);
777
- if (!channel) {
778
- return res.status(404).json({ error: 'Channel not found' });
779
- }
780
- await db.channels.unarchive(channel.id);
781
- res.json({ success: true, channel: channelId, status: 'active' });
782
- }
783
- catch (error) {
784
- console.error('[channels] Error unarchiving channel:', error);
785
- res.status(500).json({ error: 'Failed to unarchive channel' });
786
- }
787
- });
788
- // =========================================================================
789
- // Channel message endpoints (proxied to workspace container)
790
- // Messages are stored in the daemon's SQLite for real-time performance
791
- // =========================================================================
792
- app.post('/api/channels/message', requireAuth, express.json(), async (req, res) => {
793
- // Route to local dashboard where relay daemon and channel routing lives
794
- await proxyToLocalDashboard(req, res, '/api/channels/message', { method: 'POST', body: req.body });
795
- });
796
- app.get('/api/channels/:channel/messages', requireAuth, async (req, res) => {
797
- const channel = encodeURIComponent(req.params.channel);
798
- const params = new URLSearchParams();
799
- if (req.query.limit)
800
- params.set('limit', req.query.limit);
801
- if (req.query.before)
802
- params.set('before', req.query.before);
803
- const queryString = params.toString() ? `?${params.toString()}` : '';
804
- await proxyToLocalDashboard(req, res, `/api/channels/${channel}/messages${queryString}`);
805
- });
806
- /**
807
- * GET /api/channels/:channel/members - Get members of a channel
808
- */
809
- app.get('/api/channels/:channel/members', requireAuth, async (req, res) => {
810
- const channel = encodeURIComponent(req.params.channel);
811
- await proxyToLocalDashboard(req, res, `/api/channels/${channel}/members`);
812
- });
813
- /**
814
- * GET /api/channels/available-members - Get available members for channel invites
815
- * Returns workspace members (humans) and agents from linked daemons
816
- */
817
- app.get('/api/channels/available-members', requireAuth, async (req, res) => {
818
- try {
819
- const userId = req.session.userId;
820
- const workspaceId = req.query.workspaceId;
821
- // Get workspace ID - either from query param or user's default workspace
822
- let targetWorkspaceId = workspaceId;
823
- if (!targetWorkspaceId) {
824
- // Find user's default or first workspace
825
- const memberships = await db.workspaceMembers.findByUserId(userId);
826
- if (memberships.length > 0) {
827
- targetWorkspaceId = memberships[0].workspaceId;
828
- }
829
- }
830
- if (!targetWorkspaceId) {
831
- return res.json({ members: [], agents: [] });
832
- }
833
- // Verify user has access to this workspace
834
- const canView = await db.workspaceMembers.canView(targetWorkspaceId, userId);
835
- if (!canView) {
836
- const workspace = await db.workspaces.findById(targetWorkspaceId);
837
- if (!workspace || workspace.userId !== userId) {
838
- return res.status(403).json({ error: 'Access denied' });
839
- }
840
- }
841
- // Get workspace members (humans)
842
- const workspaceMembers = await db.workspaceMembers.findByWorkspaceId(targetWorkspaceId);
843
- const members = await Promise.all(workspaceMembers.map(async (m) => {
844
- const user = await db.users.findById(m.userId);
845
- return {
846
- id: user?.githubUsername || m.userId,
847
- displayName: user?.githubUsername || 'Unknown',
848
- type: 'user',
849
- avatarUrl: user?.avatarUrl ?? undefined,
850
- };
851
- }));
852
- // Get agents from linked daemons for this workspace
853
- const daemons = await db.linkedDaemons.findByWorkspaceId(targetWorkspaceId);
854
- const agents = [];
855
- for (const daemon of daemons) {
856
- const metadata = daemon.metadata;
857
- const daemonAgents = metadata?.agents || [];
858
- for (const agent of daemonAgents) {
859
- // Skip human users from daemon agent list (they're in workspace members)
860
- if (agent.isHuman)
861
- continue;
862
- // Avoid duplicates
863
- if (!agents.some((a) => a.id === agent.name)) {
864
- agents.push({
865
- id: agent.name,
866
- displayName: agent.name,
867
- type: 'agent',
868
- status: agent.status,
869
- });
870
- }
871
- }
872
- }
873
- res.json({ members, agents });
874
- }
875
- catch (error) {
876
- console.error('[channels] Error getting available members:', error);
877
- res.status(500).json({ error: 'Failed to get available members' });
878
- }
879
- });
880
- app.get('/api/channels/users', requireAuth, async (req, res) => {
881
- await proxyToLocalDashboard(req, res, '/api/channels/users');
882
- });
883
- // Test helper routes (only available in non-production)
884
- // MUST be before teamsRouter to avoid auth interception
885
- if (process.env.NODE_ENV !== 'production') {
886
- app.use('/api/test', testHelpersRouter);
887
- console.log('[cloud] Test helper routes enabled (non-production mode)');
888
- }
889
- // Teams router - MUST BE LAST among /api routes
890
- // Handles /workspaces/:id/members and /invites with requireAuth on all routes
891
- app.use('/api', teamsRouter);
892
- // Serve static dashboard files (Next.js static export)
893
- // Path: dist/cloud/server.js -> ../../src/dashboard/out
894
- const dashboardPath = path.join(__dirname, '../../src/dashboard/out');
895
- // Serve static files (JS, CSS, images, etc.)
896
- app.use(express.static(dashboardPath));
897
- // Handle clean URLs for Next.js static export
898
- // When a directory exists (e.g., /app/), express.static won't serve app.html
899
- // So we need to explicitly check for .html files
900
- app.get('/{*splat}', (req, res, next) => {
901
- // Don't handle API routes
902
- if (req.path.startsWith('/api/')) {
903
- return next();
904
- }
905
- // Clean the path (remove trailing slash)
906
- const cleanPath = req.path.replace(/\/$/, '') || '/';
907
- // Try to serve the corresponding .html file
908
- const htmlFile = cleanPath === '/' ? 'index.html' : `${cleanPath}.html`;
909
- const htmlPath = path.join(dashboardPath, htmlFile);
910
- // Check if the HTML file exists
911
- if (fs.existsSync(htmlPath)) {
912
- res.sendFile(htmlPath);
913
- }
914
- else {
915
- // Fallback to index.html for SPA-style routing
916
- res.sendFile(path.join(dashboardPath, 'index.html'));
917
- }
918
- });
919
- // Error handler
920
- app.use((err, req, res, _next) => {
921
- console.error('Error:', err);
922
- res.status(500).json({
923
- error: 'Internal server error',
924
- message: process.env.NODE_ENV === 'development' ? err.message : undefined,
925
- });
926
- });
927
- // Server lifecycle
928
- let server = null;
929
- let scalingOrchestrator = null;
930
- let computeEnforcement = null;
931
- let introExpiration = null;
932
- let workspaceKeepalive = null;
933
- let daemonStaleCheckInterval = null;
934
- // Create HTTP server for WebSocket upgrade handling
935
- const httpServer = http.createServer(app);
936
- // ===== Presence WebSocket =====
937
- const wssPresence = new WebSocketServer({
938
- noServer: true,
939
- perMessageDeflate: false,
940
- maxPayload: 1024 * 1024, // 1MB - presence messages are small
941
- });
942
- const onlineUsers = new Map();
943
- // Validation helpers
944
- const isValidUsername = (username) => {
945
- if (typeof username !== 'string')
946
- return false;
947
- return /^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$/.test(username);
948
- };
949
- const isValidAvatarUrl = (url) => {
950
- if (url === undefined || url === null)
951
- return true;
952
- if (typeof url !== 'string')
953
- return false;
954
- try {
955
- const parsed = new URL(url);
956
- return parsed.protocol === 'https:' &&
957
- (parsed.hostname === 'avatars.githubusercontent.com' ||
958
- parsed.hostname === 'github.com' ||
959
- parsed.hostname.endsWith('.githubusercontent.com'));
960
- }
961
- catch {
962
- return false;
963
- }
964
- };
965
- // WebSocket server for agent logs (proxied to workspace daemon)
966
- const wssLogs = new WebSocketServer({ noServer: true, perMessageDeflate: false });
967
- // WebSocket server for channel messages (proxied to workspace daemon)
968
- const wssChannels = new WebSocketServer({ noServer: true, perMessageDeflate: false });
969
- // Handle agent logs WebSocket connections
970
- wssLogs.on('connection', async (clientWs, workspaceId, agentName) => {
971
- console.log(`[ws/logs] Client connected for workspace=${workspaceId} agent=${agentName}`);
972
- let daemonWs = null;
973
- try {
974
- // Find the workspace (needed to verify it exists and get its URL)
975
- const workspace = await db.workspaces.findById(workspaceId);
976
- if (!workspace) {
977
- clientWs.send(JSON.stringify({ type: 'error', message: 'Workspace not found' }));
978
- clientWs.close();
979
- return;
980
- }
981
- // Connect to the workspace's dashboard where the agent was spawned
982
- // IMPORTANT: Must use workspace.publicUrl (not getLocalDashboardUrl) because
983
- // agents are spawned on the workspace server, so logs must connect there too
984
- const dashboardUrl = workspace.publicUrl || await getLocalDashboardUrl();
985
- const baseUrl = dashboardUrl.replace(/^http/, 'ws').replace(/\/$/, '');
986
- const daemonWsUrl = `${baseUrl}/ws/logs/${encodeURIComponent(agentName)}`;
987
- console.log(`[ws/logs] Connecting to daemon: ${daemonWsUrl}`);
988
- daemonWs = new WebSocket(daemonWsUrl, { perMessageDeflate: false });
989
- daemonWs.on('open', () => {
990
- console.log(`[ws/logs] Connected to daemon for ${agentName}`);
991
- // Note: No need to send subscribe message - the agent name in the URL path
992
- // triggers auto-subscription in the dashboard server
993
- });
994
- daemonWs.on('message', (data) => {
995
- // Forward daemon messages to client
996
- if (clientWs.readyState === WebSocket.OPEN) {
997
- clientWs.send(data.toString());
998
- }
999
- });
1000
- daemonWs.on('close', () => {
1001
- console.log(`[ws/logs] Daemon connection closed for ${agentName}`);
1002
- if (clientWs.readyState === WebSocket.OPEN) {
1003
- clientWs.close();
1004
- }
1005
- });
1006
- daemonWs.on('error', (err) => {
1007
- console.error(`[ws/logs] Daemon WebSocket error:`, err);
1008
- if (clientWs.readyState === WebSocket.OPEN) {
1009
- clientWs.send(JSON.stringify({ type: 'error', message: 'Daemon connection error' }));
1010
- clientWs.close();
1011
- }
1012
- });
1013
- // Forward client messages to daemon (for user input)
1014
- clientWs.on('message', (data) => {
1015
- if (daemonWs && daemonWs.readyState === WebSocket.OPEN) {
1016
- daemonWs.send(data.toString());
1017
- }
1018
- });
1019
- clientWs.on('close', () => {
1020
- console.log(`[ws/logs] Client disconnected for ${agentName}`);
1021
- if (daemonWs && daemonWs.readyState === WebSocket.OPEN) {
1022
- daemonWs.close();
1023
- }
1024
- });
1025
- clientWs.on('error', (err) => {
1026
- console.error(`[ws/logs] Client WebSocket error:`, err);
1027
- if (daemonWs && daemonWs.readyState === WebSocket.OPEN) {
1028
- daemonWs.close();
1029
- }
1030
- });
1031
- }
1032
- catch (err) {
1033
- console.error(`[ws/logs] Setup error:`, err);
1034
- if (clientWs.readyState === WebSocket.OPEN) {
1035
- clientWs.send(JSON.stringify({ type: 'error', message: 'Failed to connect to workspace' }));
1036
- clientWs.close();
1037
- }
1038
- }
1039
- });
1040
- // Handle channel WebSocket connections (proxied to workspace daemon)
1041
- // This allows cloud users to receive real-time channel messages
1042
- wssChannels.on('connection', async (clientWs, workspaceId, username) => {
1043
- console.log(`[ws/channels] Client connected for workspace=${workspaceId} user=${username}`);
1044
- let daemonWs = null;
1045
- try {
1046
- // Find the workspace (needed to verify it exists)
1047
- const workspace = await db.workspaces.findById(workspaceId);
1048
- if (!workspace) {
1049
- clientWs.send(JSON.stringify({ type: 'error', message: 'Workspace not found' }));
1050
- clientWs.close();
1051
- return;
1052
- }
1053
- // Connect to local dashboard where the daemon actually runs
1054
- const dashboardUrl = await getLocalDashboardUrl();
1055
- const baseUrl = dashboardUrl.replace(/^http/, 'ws').replace(/\/$/, '');
1056
- const daemonWsUrl = `${baseUrl}/ws/presence`;
1057
- console.log(`[ws/channels] Connecting to daemon: ${daemonWsUrl}`);
1058
- daemonWs = new WebSocket(daemonWsUrl, { perMessageDeflate: false });
1059
- daemonWs.on('open', () => {
1060
- console.log(`[ws/channels] Connected to daemon for ${username}`);
1061
- // Register with the daemon's presence system
1062
- daemonWs.send(JSON.stringify({
1063
- type: 'presence',
1064
- action: 'join',
1065
- user: { username },
1066
- }));
1067
- });
1068
- daemonWs.on('message', (data) => {
1069
- // Forward daemon messages to client
1070
- // Only forward channel_message type messages for this user
1071
- try {
1072
- const msg = JSON.parse(data.toString());
1073
- if (msg.type === 'channel_message') {
1074
- // Only forward if this message is for this user
1075
- if (msg.targetUser === username) {
1076
- console.log(`[ws/channels] Forwarding channel message to ${username}: ${msg.from} -> ${msg.channel}`);
1077
- clientWs.send(data.toString());
1078
- }
1079
- }
1080
- // Also forward presence updates so client stays in sync
1081
- if (msg.type === 'presence_join' || msg.type === 'presence_leave' || msg.type === 'presence_list') {
1082
- clientWs.send(data.toString());
1083
- }
1084
- }
1085
- catch {
1086
- // Non-JSON message, skip
1087
- }
1088
- });
1089
- daemonWs.on('close', () => {
1090
- console.log(`[ws/channels] Daemon connection closed for ${username}`);
1091
- if (clientWs.readyState === WebSocket.OPEN) {
1092
- clientWs.close();
1093
- }
1094
- });
1095
- daemonWs.on('error', (err) => {
1096
- console.error(`[ws/channels] Daemon WebSocket error:`, err);
1097
- if (clientWs.readyState === WebSocket.OPEN) {
1098
- clientWs.send(JSON.stringify({ type: 'error', message: 'Daemon connection error' }));
1099
- clientWs.close();
1100
- }
1101
- });
1102
- // Forward client messages to daemon (for sending channel messages)
1103
- clientWs.on('message', (data) => {
1104
- if (daemonWs && daemonWs.readyState === WebSocket.OPEN) {
1105
- daemonWs.send(data.toString());
1106
- }
1107
- });
1108
- clientWs.on('close', () => {
1109
- console.log(`[ws/channels] Client disconnected for ${username}`);
1110
- // Send leave message to daemon
1111
- if (daemonWs && daemonWs.readyState === WebSocket.OPEN) {
1112
- daemonWs.send(JSON.stringify({
1113
- type: 'presence',
1114
- action: 'leave',
1115
- username,
1116
- }));
1117
- daemonWs.close();
1118
- }
1119
- });
1120
- clientWs.on('error', (err) => {
1121
- console.error(`[ws/channels] Client WebSocket error:`, err);
1122
- if (daemonWs && daemonWs.readyState === WebSocket.OPEN) {
1123
- daemonWs.close();
1124
- }
1125
- });
1126
- }
1127
- catch (err) {
1128
- console.error(`[ws/channels] Setup error:`, err);
1129
- if (clientWs.readyState === WebSocket.OPEN) {
1130
- clientWs.send(JSON.stringify({ type: 'error', message: 'Failed to connect to workspace' }));
1131
- clientWs.close();
1132
- }
1133
- }
1134
- });
1135
- // Handle HTTP upgrade for WebSocket
1136
- httpServer.on('upgrade', (request, socket, head) => {
1137
- const pathname = new URL(request.url || '', `http://${request.headers.host}`).pathname;
1138
- if (pathname === '/ws/presence') {
1139
- wssPresence.handleUpgrade(request, socket, head, (ws) => {
1140
- wssPresence.emit('connection', ws, request);
1141
- });
1142
- }
1143
- else if (pathname.startsWith('/ws/logs/')) {
1144
- // Parse /ws/logs/:workspaceId/:agentName
1145
- const parts = pathname.split('/').filter(Boolean);
1146
- if (parts.length >= 4) {
1147
- const workspaceId = decodeURIComponent(parts[2]);
1148
- const agentName = decodeURIComponent(parts[3]);
1149
- wssLogs.handleUpgrade(request, socket, head, (ws) => {
1150
- wssLogs.emit('connection', ws, workspaceId, agentName);
1151
- });
1152
- }
1153
- else {
1154
- socket.destroy();
1155
- }
1156
- }
1157
- else if (pathname.startsWith('/ws/channels/')) {
1158
- // Parse /ws/channels/:workspaceId/:username
1159
- const parts = pathname.split('/').filter(Boolean);
1160
- if (parts.length >= 4) {
1161
- const workspaceId = decodeURIComponent(parts[2]);
1162
- const username = decodeURIComponent(parts[3]);
1163
- wssChannels.handleUpgrade(request, socket, head, (ws) => {
1164
- wssChannels.emit('connection', ws, workspaceId, username);
1165
- });
1166
- }
1167
- else {
1168
- socket.destroy();
1169
- }
1170
- }
1171
- else {
1172
- // Unknown WebSocket path - destroy socket
1173
- socket.destroy();
1174
- }
1175
- });
1176
- // Broadcast to all presence clients
1177
- const broadcastPresence = (message, exclude) => {
1178
- const payload = JSON.stringify(message);
1179
- wssPresence.clients.forEach((client) => {
1180
- if (client !== exclude && client.readyState === WebSocket.OPEN) {
1181
- client.send(payload);
1182
- }
1183
- });
1184
- };
1185
- // Get online users list
1186
- const getOnlineUsersList = () => {
1187
- return Array.from(onlineUsers.values()).map((state) => state.info);
1188
- };
1189
- // Heartbeat interval to detect dead connections (30 seconds)
1190
- const PRESENCE_HEARTBEAT_INTERVAL = 30000;
1191
- const _PRESENCE_HEARTBEAT_TIMEOUT = 35000; // Allow 5s grace period (reserved for future use)
1192
- // Track connection health for heartbeat
1193
- const connectionHealth = new WeakMap();
1194
- // Heartbeat interval to clean up dead connections
1195
- const presenceHeartbeat = setInterval(() => {
1196
- const now = Date.now();
1197
- wssPresence.clients.forEach((ws) => {
1198
- const health = connectionHealth.get(ws);
1199
- if (!health) {
1200
- // New connection without health tracking - initialize it
1201
- connectionHealth.set(ws, { isAlive: true, lastPing: now });
1202
- return;
1203
- }
1204
- if (!health.isAlive) {
1205
- // Connection didn't respond to last ping - terminate it
1206
- ws.terminate();
1207
- return;
1208
- }
1209
- // Mark as not alive until we get a pong
1210
- health.isAlive = false;
1211
- health.lastPing = now;
1212
- ws.ping();
1213
- });
1214
- }, PRESENCE_HEARTBEAT_INTERVAL);
1215
- // Clean up interval on server close
1216
- wssPresence.on('close', () => {
1217
- clearInterval(presenceHeartbeat);
1218
- });
1219
- // Track daemon proxy connections for channel message forwarding
1220
- const daemonProxies = new Map(); // clientWs -> workspaceId -> daemonWs
1221
- // Set up daemon proxy for channel messages
1222
- async function setupDaemonChannelProxy(clientWs, workspaceId, username) {
1223
- // Check if already have a proxy for this workspace
1224
- const clientProxies = daemonProxies.get(clientWs) || new Map();
1225
- if (clientProxies.has(workspaceId)) {
1226
- return; // Already connected
1227
- }
1228
- try {
1229
- const workspace = await db.workspaces.findById(workspaceId);
1230
- if (!workspace) {
1231
- console.log(`[cloud] Workspace ${workspaceId} not found`);
1232
- return;
1233
- }
1234
- // Use local dashboard URL where the daemon actually runs
1235
- const dashboardUrl = await getLocalDashboardUrl();
1236
- const daemonWsUrl = dashboardUrl.replace(/^http/, 'ws').replace(/\/$/, '') + '/ws/presence';
1237
- console.log(`[cloud] Connecting channel proxy to daemon: ${daemonWsUrl} for ${username}`);
1238
- // First, register the user for channel messages on the daemon side
1239
- // This creates a relay client for them so they receive channel messages
1240
- try {
1241
- const subscribeRes = await fetch(`${dashboardUrl}/api/channels/subscribe`, {
1242
- method: 'POST',
1243
- headers: { 'Content-Type': 'application/json' },
1244
- body: JSON.stringify({
1245
- username,
1246
- channels: ['#general'], // Start with general, others can be joined later
1247
- workspaceId,
1248
- }),
1249
- });
1250
- if (subscribeRes.ok) {
1251
- const result = (await subscribeRes.json());
1252
- console.log(`[cloud] Subscribed ${username} to channels: ${result.channels?.join(', ')}`);
1253
- }
1254
- else {
1255
- console.warn(`[cloud] Failed to subscribe ${username} to channels: ${subscribeRes.status}`);
1256
- }
1257
- }
1258
- catch (err) {
1259
- console.warn(`[cloud] Error subscribing ${username} to channels:`, err);
1260
- // Continue anyway - we can still set up the proxy
1261
- }
1262
- const daemonWs = new WebSocket(daemonWsUrl, { perMessageDeflate: false });
1263
- daemonWs.on('open', () => {
1264
- console.log(`[cloud] Channel proxy connected for ${username} in workspace ${workspaceId}`);
1265
- });
1266
- daemonWs.on('message', (data) => {
1267
- try {
1268
- const msg = JSON.parse(data.toString());
1269
- // Forward channel messages targeted at this user
1270
- if (msg.type === 'channel_message' && msg.targetUser === username) {
1271
- console.log(`[cloud] Forwarding channel message to ${username}: ${msg.from} -> ${msg.channel}`);
1272
- if (clientWs.readyState === WebSocket.OPEN) {
1273
- clientWs.send(data.toString());
1274
- }
1275
- }
1276
- }
1277
- catch {
1278
- // Non-JSON, ignore
1279
- }
1280
- });
1281
- daemonWs.on('close', () => {
1282
- console.log(`[cloud] Channel proxy closed for ${username} in workspace ${workspaceId}`);
1283
- clientProxies.delete(workspaceId);
1284
- });
1285
- daemonWs.on('error', (err) => {
1286
- console.error(`[cloud] Channel proxy error for ${username}:`, err);
1287
- clientProxies.delete(workspaceId);
1288
- });
1289
- clientProxies.set(workspaceId, daemonWs);
1290
- daemonProxies.set(clientWs, clientProxies);
1291
- }
1292
- catch (err) {
1293
- console.error(`[cloud] Failed to setup channel proxy for ${username}:`, err);
1294
- }
1295
- }
1296
- // Clean up daemon proxies for a client
1297
- function cleanupDaemonProxies(clientWs) {
1298
- const clientProxies = daemonProxies.get(clientWs);
1299
- if (clientProxies) {
1300
- for (const [workspaceId, daemonWs] of clientProxies) {
1301
- console.log(`[cloud] Cleaning up channel proxy for workspace ${workspaceId}`);
1302
- if (daemonWs.readyState === WebSocket.OPEN) {
1303
- daemonWs.close();
1304
- }
1305
- }
1306
- daemonProxies.delete(clientWs);
1307
- }
1308
- }
1309
- // Handle presence connections
1310
- wssPresence.on('connection', (ws) => {
1311
- // Initialize health tracking (no log - too noisy)
1312
- connectionHealth.set(ws, { isAlive: true, lastPing: Date.now() });
1313
- // Handle pong responses (heartbeat)
1314
- ws.on('pong', () => {
1315
- const health = connectionHealth.get(ws);
1316
- if (health) {
1317
- health.isAlive = true;
1318
- }
1319
- });
1320
- let clientUsername;
1321
- ws.on('message', (data) => {
1322
- try {
1323
- const msg = JSON.parse(data.toString());
1324
- if (msg.type === 'presence') {
1325
- if (msg.action === 'join' && msg.user?.username) {
1326
- const username = msg.user.username;
1327
- const avatarUrl = msg.user.avatarUrl;
1328
- if (!isValidUsername(username)) {
1329
- console.warn(`[cloud] Invalid username rejected: ${username}`);
1330
- return;
1331
- }
1332
- if (!isValidAvatarUrl(avatarUrl)) {
1333
- console.warn(`[cloud] Invalid avatar URL rejected for user ${username}`);
1334
- return;
1335
- }
1336
- clientUsername = username;
1337
- const now = new Date().toISOString();
1338
- const existing = onlineUsers.get(username);
1339
- if (existing) {
1340
- existing.connections.add(ws);
1341
- existing.info.lastSeen = now;
1342
- // Update last seen in shared presence registry
1343
- updateUserLastSeen(username);
1344
- // Only log at milestones to reduce noise
1345
- const count = existing.connections.size;
1346
- if (count === 2 || count === 5 || count === 10 || count % 50 === 0) {
1347
- console.log(`[cloud] User ${username} has ${count} connections`);
1348
- }
1349
- }
1350
- else {
1351
- onlineUsers.set(username, {
1352
- info: { username, avatarUrl, connectedAt: now, lastSeen: now },
1353
- connections: new Set([ws]),
1354
- });
1355
- // Register with shared presence registry for cross-module access
1356
- registerUserPresence({ username, avatarUrl, connectedAt: now, lastSeen: now });
1357
- console.log(`[cloud] User ${username} came online`);
1358
- broadcastPresence({
1359
- type: 'presence_join',
1360
- user: { username, avatarUrl, connectedAt: now, lastSeen: now },
1361
- }, ws);
1362
- }
1363
- ws.send(JSON.stringify({
1364
- type: 'presence_list',
1365
- users: getOnlineUsersList(),
1366
- }));
1367
- }
1368
- else if (msg.action === 'leave') {
1369
- if (!clientUsername || msg.username !== clientUsername)
1370
- return;
1371
- const userState = onlineUsers.get(clientUsername);
1372
- if (userState) {
1373
- userState.connections.delete(ws);
1374
- if (userState.connections.size === 0) {
1375
- onlineUsers.delete(clientUsername);
1376
- // Unregister from shared presence registry
1377
- unregisterUserPresence(clientUsername);
1378
- console.log(`[cloud] User ${clientUsername} went offline`);
1379
- broadcastPresence({ type: 'presence_leave', username: clientUsername });
1380
- }
1381
- }
1382
- }
1383
- }
1384
- else if (msg.type === 'typing') {
1385
- if (!clientUsername || msg.username !== clientUsername)
1386
- return;
1387
- const userState = onlineUsers.get(clientUsername);
1388
- if (userState) {
1389
- userState.info.lastSeen = new Date().toISOString();
1390
- // Update last seen in shared presence registry
1391
- updateUserLastSeen(clientUsername);
1392
- }
1393
- broadcastPresence({
1394
- type: 'typing',
1395
- username: clientUsername,
1396
- avatarUrl: userState?.info.avatarUrl,
1397
- isTyping: msg.isTyping,
1398
- }, ws);
1399
- }
1400
- else if (msg.type === 'subscribe_channels') {
1401
- // Subscribe to channel messages for a specific workspace
1402
- if (!clientUsername) {
1403
- console.warn(`[cloud] subscribe_channels from unauthenticated client`);
1404
- return;
1405
- }
1406
- if (!msg.workspaceId || typeof msg.workspaceId !== 'string') {
1407
- console.warn(`[cloud] subscribe_channels missing workspaceId`);
1408
- return;
1409
- }
1410
- console.log(`[cloud] User ${clientUsername} subscribing to channels in workspace ${msg.workspaceId}`);
1411
- setupDaemonChannelProxy(ws, msg.workspaceId, clientUsername).catch((err) => {
1412
- console.error(`[cloud] Failed to setup channel subscription:`, err);
1413
- });
1414
- }
1415
- else if (msg.type === 'channel_message') {
1416
- // Proxy channel message to daemon via HTTP API
1417
- if (!clientUsername) {
1418
- console.warn(`[cloud] channel_message from unauthenticated client`);
1419
- return;
1420
- }
1421
- if (!msg.channel || !msg.body) {
1422
- console.warn(`[cloud] channel_message missing channel or body`);
1423
- return;
1424
- }
1425
- // Note: This should be handled by the HTTP API, but support WebSocket too
1426
- console.log(`[cloud] Channel message via WebSocket from ${clientUsername} to ${msg.channel}`);
1427
- // The HTTP proxy will handle actual sending - just log for now
1428
- }
1429
- }
1430
- catch (err) {
1431
- console.error('[cloud] Invalid presence message:', err);
1432
- }
1433
- });
1434
- ws.on('close', () => {
1435
- // Clean up daemon proxies
1436
- cleanupDaemonProxies(ws);
1437
- if (clientUsername) {
1438
- const userState = onlineUsers.get(clientUsername);
1439
- if (userState) {
1440
- userState.connections.delete(ws);
1441
- if (userState.connections.size === 0) {
1442
- onlineUsers.delete(clientUsername);
1443
- // Unregister from shared presence registry
1444
- unregisterUserPresence(clientUsername);
1445
- console.log(`[cloud] User ${clientUsername} disconnected`);
1446
- broadcastPresence({ type: 'presence_leave', username: clientUsername });
1447
- }
1448
- }
1449
- }
1450
- });
1451
- ws.on('error', (err) => {
1452
- console.error('[cloud] Presence WebSocket error:', err);
1453
- });
1454
- });
1455
- wssPresence.on('error', (err) => {
1456
- console.error('[cloud] Presence WebSocket server error:', err);
1457
- });
1458
- // Subscribe to cloud message bus for delivering messages to cloud users
1459
- cloudMessageBus.on('user-message', ({ username, message }) => {
1460
- const userState = onlineUsers.get(username);
1461
- if (!userState) {
1462
- console.warn(`[cloud] Cannot deliver message to ${username}: user not online`);
1463
- return;
1464
- }
1465
- // Deliver to all of the user's WebSocket connections
1466
- const payload = JSON.stringify({
1467
- type: 'direct_message',
1468
- from: message.from.agent,
1469
- body: message.body,
1470
- timestamp: message.timestamp,
1471
- metadata: {
1472
- ...message.metadata,
1473
- daemonId: message.from.daemonId,
1474
- daemonName: message.from.daemonName,
1475
- },
1476
- });
1477
- let delivered = 0;
1478
- userState.connections.forEach((ws) => {
1479
- if (ws.readyState === WebSocket.OPEN) {
1480
- ws.send(payload);
1481
- delivered++;
1482
- }
1483
- });
1484
- console.log(`[cloud] Delivered message to ${username} (${delivered} connections)`);
1485
- });
1486
- return {
1487
- app,
1488
- async start() {
1489
- // Run database migrations before accepting connections
1490
- console.log('[cloud] Running database migrations...');
1491
- await runMigrations();
1492
- // Initialize scaling orchestrator for auto-scaling
1493
- if (process.env.RELAY_CLOUD_ENABLED === 'true') {
1494
- try {
1495
- scalingOrchestrator = getScalingOrchestrator();
1496
- await scalingOrchestrator.initialize(config.redisUrl);
1497
- console.log('[cloud] Scaling orchestrator initialized');
1498
- // Log scaling events
1499
- scalingOrchestrator.on('scaling_started', (op) => {
1500
- console.log(`[scaling] Started: ${op.action} for user ${op.userId}`);
1501
- });
1502
- scalingOrchestrator.on('scaling_completed', (op) => {
1503
- console.log(`[scaling] Completed: ${op.action} for user ${op.userId}`);
1504
- });
1505
- scalingOrchestrator.on('scaling_error', ({ operation, error }) => {
1506
- console.error(`[scaling] Error: ${operation.action} for ${operation.userId}:`, error);
1507
- });
1508
- scalingOrchestrator.on('workspace_provisioned', (data) => {
1509
- console.log(`[scaling] Provisioned workspace ${data.workspaceId} for user ${data.userId}`);
1510
- });
1511
- }
1512
- catch (error) {
1513
- console.warn('[cloud] Failed to initialize scaling orchestrator:', error);
1514
- // Non-fatal - server can run without auto-scaling
1515
- }
1516
- // Start compute enforcement service (checks every 15 min)
1517
- try {
1518
- computeEnforcement = getComputeEnforcementService();
1519
- computeEnforcement.start();
1520
- console.log('[cloud] Compute enforcement service started');
1521
- }
1522
- catch (error) {
1523
- console.warn('[cloud] Failed to start compute enforcement:', error);
1524
- }
1525
- // Start intro expiration service (checks every hour for expired intro periods)
1526
- try {
1527
- introExpiration = getIntroExpirationService();
1528
- introExpiration.start();
1529
- console.log('[cloud] Intro expiration service started');
1530
- }
1531
- catch (error) {
1532
- console.warn('[cloud] Failed to start intro expiration:', error);
1533
- }
1534
- // Start workspace keepalive service (pings workspaces with active agents)
1535
- // This prevents Fly.io from idling machines that have running Claude agents
1536
- try {
1537
- workspaceKeepalive = getWorkspaceKeepaliveService();
1538
- workspaceKeepalive.start();
1539
- console.log('[cloud] Workspace keepalive service started');
1540
- }
1541
- catch (error) {
1542
- console.warn('[cloud] Failed to start workspace keepalive:', error);
1543
- }
1544
- }
1545
- // Start daemon stale check (mark daemons offline if no heartbeat for 2+ minutes)
1546
- // Runs every 60 seconds regardless of RELAY_CLOUD_ENABLED
1547
- daemonStaleCheckInterval = setInterval(async () => {
1548
- try {
1549
- const count = await db.linkedDaemons.markStale();
1550
- if (count > 0) {
1551
- console.log(`[cloud] Marked ${count} daemon(s) as offline (stale)`);
1552
- }
1553
- }
1554
- catch (error) {
1555
- console.error('[cloud] Failed to mark stale daemons:', error);
1556
- }
1557
- }, 60_000); // Every 60 seconds
1558
- console.log('[cloud] Daemon stale check started (60s interval)');
1559
- return new Promise((resolve) => {
1560
- server = httpServer.listen(config.port, () => {
1561
- console.log(`Agent Relay Cloud running on port ${config.port}`);
1562
- console.log(`Public URL: ${config.publicUrl}`);
1563
- console.log(`WebSocket: ws://localhost:${config.port}/ws/presence`);
1564
- resolve();
1565
- });
1566
- });
1567
- },
1568
- async stop() {
1569
- // Shutdown scaling orchestrator
1570
- if (scalingOrchestrator) {
1571
- await scalingOrchestrator.shutdown();
1572
- }
1573
- // Stop compute enforcement service
1574
- if (computeEnforcement) {
1575
- computeEnforcement.stop();
1576
- }
1577
- // Stop intro expiration service
1578
- if (introExpiration) {
1579
- introExpiration.stop();
1580
- }
1581
- // Stop workspace keepalive service
1582
- if (workspaceKeepalive) {
1583
- workspaceKeepalive.stop();
1584
- }
1585
- // Stop daemon stale check
1586
- if (daemonStaleCheckInterval) {
1587
- clearInterval(daemonStaleCheckInterval);
1588
- daemonStaleCheckInterval = null;
1589
- }
1590
- // Close WebSocket server
1591
- wssPresence.close();
1592
- if (server) {
1593
- await new Promise((resolve) => server.close(() => resolve()));
1594
- }
1595
- await redisClient.quit();
1596
- },
1597
- };
1598
- }
1599
- //# sourceMappingURL=server.js.map