agent-relay 1.6.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1313) hide show
  1. package/.cursor/mcp.json +11 -0
  2. package/.gitleaks.toml +26 -0
  3. package/.mcp.json +11 -0
  4. package/.nvmrc +1 -1
  5. package/.turbo/cache/013415461711937f-meta.json +1 -0
  6. package/.turbo/cache/013415461711937f.tar.zst +0 -0
  7. package/.turbo/cache/0562b1ff326acd6d-meta.json +1 -0
  8. package/.turbo/cache/0562b1ff326acd6d.tar.zst +0 -0
  9. package/.turbo/cache/0b46e0e17254882f-meta.json +1 -0
  10. package/.turbo/cache/0b46e0e17254882f.tar.zst +0 -0
  11. package/.turbo/cache/3799eda981d53d14-meta.json +1 -0
  12. package/.turbo/cache/3799eda981d53d14.tar.zst +0 -0
  13. package/.turbo/cache/47e9d8f404ed064d-meta.json +1 -0
  14. package/.turbo/cache/47e9d8f404ed064d.tar.zst +0 -0
  15. package/.turbo/cache/4cde1d1e5b298099-meta.json +1 -0
  16. package/.turbo/cache/4cde1d1e5b298099.tar.zst +0 -0
  17. package/.turbo/cache/538eea955c0936ef-meta.json +1 -0
  18. package/.turbo/cache/538eea955c0936ef.tar.zst +0 -0
  19. package/.turbo/cache/5dceac7f229f5d5d-meta.json +1 -0
  20. package/.turbo/cache/5dceac7f229f5d5d.tar.zst +0 -0
  21. package/.turbo/cache/64c15b201819367d-meta.json +1 -0
  22. package/.turbo/cache/64c15b201819367d.tar.zst +0 -0
  23. package/.turbo/cache/6d6a21a05efca434-meta.json +1 -0
  24. package/.turbo/cache/6d6a21a05efca434.tar.zst +0 -0
  25. package/.turbo/cache/7562610cb03ec040-meta.json +1 -0
  26. package/.turbo/cache/7562610cb03ec040.tar.zst +0 -0
  27. package/.turbo/cache/81a2456e17af4d7f-meta.json +1 -0
  28. package/.turbo/cache/81a2456e17af4d7f.tar.zst +0 -0
  29. package/.turbo/cache/823fc2a7b12f724c-meta.json +1 -0
  30. package/.turbo/cache/823fc2a7b12f724c.tar.zst +0 -0
  31. package/.turbo/cache/9daad16a073d1f91-meta.json +1 -0
  32. package/.turbo/cache/9daad16a073d1f91.tar.zst +0 -0
  33. package/.turbo/cache/b81ccbab0a606b60-meta.json +1 -0
  34. package/.turbo/cache/b81ccbab0a606b60.tar.zst +0 -0
  35. package/.turbo/cache/cf98487988bfcf91-meta.json +1 -0
  36. package/.turbo/cache/cf98487988bfcf91.tar.zst +0 -0
  37. package/.turbo/cache/cfdf7c57dca71f27-meta.json +1 -0
  38. package/.turbo/cache/cfdf7c57dca71f27.tar.zst +0 -0
  39. package/.turbo/cache/d3063ef43811b1e5-meta.json +1 -0
  40. package/.turbo/cache/d3063ef43811b1e5.tar.zst +0 -0
  41. package/.turbo/cache/de28892eb7678e65-meta.json +1 -0
  42. package/.turbo/cache/de28892eb7678e65.tar.zst +0 -0
  43. package/.turbo/cache/ec29adce408132ba-meta.json +1 -0
  44. package/.turbo/cache/ec29adce408132ba.tar.zst +0 -0
  45. package/.turbo/cache/f70450d8d305f172-meta.json +1 -0
  46. package/.turbo/cache/f70450d8d305f172.tar.zst +0 -0
  47. package/.turbo/cache/fe384d5d6b7a983a-meta.json +1 -0
  48. package/.turbo/cache/fe384d5d6b7a983a.tar.zst +0 -0
  49. package/ARCHITECTURE.md +10 -10
  50. package/CHANGELOG.md +38 -0
  51. package/LICENSE +185 -17
  52. package/README.md +43 -5
  53. package/SESSION_HANDOFF.md +67 -0
  54. package/bin/relay-pty +0 -0
  55. package/bin/relay-pty-darwin-arm64 +0 -0
  56. package/bin/relay-pty-darwin-x64 +0 -0
  57. package/bin/relay-pty-linux-x64 +0 -0
  58. package/deploy/workspace/entrypoint.sh +79 -11
  59. package/deploy/workspace/git-credential-relay +152 -27
  60. package/deploy/workspace/git-credential-relay.test.sh +230 -0
  61. package/dist/dashboard/out/404.html +1 -1
  62. package/dist/dashboard/out/_next/static/chunks/116-a883fca163f3a5bc.js +1 -0
  63. package/dist/dashboard/out/_next/static/chunks/320-900169c942e31422.js +1 -0
  64. package/dist/dashboard/out/_next/static/chunks/631-af51bad94027527a.js +1 -0
  65. package/dist/dashboard/out/_next/static/chunks/766-2aea80818f7eb0d8.js +1 -0
  66. package/dist/dashboard/out/_next/static/chunks/891-5cb1513eeb97a891.js +1 -0
  67. package/dist/dashboard/out/_next/static/chunks/app/app/page-2e525b1dcc790967.js +1 -0
  68. package/dist/dashboard/out/_next/static/chunks/app/page-4e64923d73c35bc9.js +1 -0
  69. package/dist/dashboard/out/_next/static/chunks/app/providers/page-e65a0010da6ea5be.js +1 -0
  70. package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-84161c802b020a1f.js +1 -0
  71. package/dist/dashboard/out/_next/static/css/99c2552394077586.css +1 -0
  72. package/dist/dashboard/out/app/onboarding.html +1 -1
  73. package/dist/dashboard/out/app/onboarding.txt +1 -1
  74. package/dist/dashboard/out/app.html +1 -1
  75. package/dist/dashboard/out/app.txt +2 -2
  76. package/dist/dashboard/out/cloud/link.html +1 -1
  77. package/dist/dashboard/out/cloud/link.txt +2 -2
  78. package/dist/dashboard/out/connect-repos.html +1 -1
  79. package/dist/dashboard/out/connect-repos.txt +1 -1
  80. package/dist/dashboard/out/history.html +1 -1
  81. package/dist/dashboard/out/history.txt +2 -2
  82. package/dist/dashboard/out/index.html +1 -1
  83. package/dist/dashboard/out/index.txt +2 -2
  84. package/dist/dashboard/out/login.html +2 -2
  85. package/dist/dashboard/out/login.txt +1 -1
  86. package/dist/dashboard/out/metrics.html +1 -1
  87. package/dist/dashboard/out/metrics.txt +2 -2
  88. package/dist/dashboard/out/pricing.html +3 -3
  89. package/dist/dashboard/out/pricing.txt +2 -2
  90. package/dist/dashboard/out/providers/setup/claude.html +1 -1
  91. package/dist/dashboard/out/providers/setup/claude.txt +2 -2
  92. package/dist/dashboard/out/providers/setup/codex.html +1 -1
  93. package/dist/dashboard/out/providers/setup/codex.txt +2 -2
  94. package/dist/dashboard/out/providers/setup/cursor.html +1 -0
  95. package/dist/dashboard/out/providers/setup/cursor.txt +8 -0
  96. package/dist/dashboard/out/providers.html +1 -1
  97. package/dist/dashboard/out/providers.txt +2 -2
  98. package/dist/dashboard/out/signup.html +2 -2
  99. package/dist/dashboard/out/signup.txt +1 -1
  100. package/dist/src/bridge/index.d.ts +8 -0
  101. package/dist/src/bridge/index.js +8 -0
  102. package/dist/src/cli/index.js +3089 -0
  103. package/dist/src/cloud/index.d.ts +8 -0
  104. package/dist/src/cloud/index.js +8 -0
  105. package/dist/src/config/relay-config.d.ts +5 -0
  106. package/dist/src/config/relay-config.js +5 -0
  107. package/dist/src/continuity/index.d.ts +5 -0
  108. package/dist/src/continuity/index.js +5 -0
  109. package/dist/src/daemon/index.d.ts +8 -0
  110. package/dist/src/daemon/index.js +9 -0
  111. package/dist/src/dashboard-server/index.d.ts +8 -0
  112. package/dist/src/dashboard-server/index.js +8 -0
  113. package/dist/src/hooks/index.d.ts +10 -0
  114. package/dist/src/hooks/index.js +10 -0
  115. package/dist/src/index.d.ts +13 -0
  116. package/dist/src/index.js +16 -0
  117. package/dist/src/memory/index.d.ts +5 -0
  118. package/dist/src/memory/index.js +5 -0
  119. package/dist/src/policy/index.d.ts +5 -0
  120. package/dist/src/policy/index.js +5 -0
  121. package/dist/src/protocol/index.d.ts +8 -0
  122. package/dist/src/protocol/index.js +8 -0
  123. package/dist/src/resiliency/index.d.ts +5 -0
  124. package/dist/src/resiliency/index.js +5 -0
  125. package/dist/src/shared/cli-auth-config.d.ts +5 -0
  126. package/dist/src/shared/cli-auth-config.js +5 -0
  127. package/dist/src/state/index.d.ts +5 -0
  128. package/dist/src/state/index.js +5 -0
  129. package/dist/src/storage/index.d.ts +8 -0
  130. package/dist/src/storage/index.js +8 -0
  131. package/dist/src/trajectory/index.d.ts +5 -0
  132. package/dist/src/trajectory/index.js +5 -0
  133. package/dist/src/utils/index.d.ts +5 -0
  134. package/dist/src/utils/index.js +5 -0
  135. package/dist/src/wrapper/index.d.ts +8 -0
  136. package/dist/src/wrapper/index.js +11 -0
  137. package/package.json +64 -19
  138. package/packages/api-types/dist/index.d.ts +21 -0
  139. package/packages/api-types/dist/index.js +22 -0
  140. package/packages/api-types/dist/schemas/agent.d.ts +259 -0
  141. package/packages/api-types/dist/schemas/agent.js +102 -0
  142. package/packages/api-types/dist/schemas/api.d.ts +290 -0
  143. package/packages/api-types/dist/schemas/api.js +162 -0
  144. package/packages/api-types/dist/schemas/decision.d.ts +230 -0
  145. package/packages/api-types/dist/schemas/decision.js +104 -0
  146. package/packages/api-types/dist/schemas/fleet.d.ts +615 -0
  147. package/packages/api-types/dist/schemas/fleet.js +71 -0
  148. package/packages/api-types/dist/schemas/history.d.ts +180 -0
  149. package/packages/api-types/dist/schemas/history.js +72 -0
  150. package/packages/api-types/dist/schemas/index.d.ts +14 -0
  151. package/packages/api-types/dist/schemas/index.js +22 -0
  152. package/packages/api-types/dist/schemas/message.d.ts +456 -0
  153. package/packages/api-types/dist/schemas/message.js +88 -0
  154. package/packages/api-types/dist/schemas/session.d.ts +60 -0
  155. package/packages/api-types/dist/schemas/session.js +36 -0
  156. package/packages/api-types/dist/schemas/task.d.ts +111 -0
  157. package/packages/api-types/dist/schemas/task.js +64 -0
  158. package/packages/api-types/package.json +61 -0
  159. package/packages/api-types/scripts/generate-openapi.ts +106 -0
  160. package/packages/bridge/dist/index.d.ts +8 -0
  161. package/packages/bridge/dist/index.js +9 -0
  162. package/packages/bridge/dist/multi-project-client.d.ts +99 -0
  163. package/packages/bridge/dist/multi-project-client.js +389 -0
  164. package/packages/bridge/dist/shadow-cli.js +75 -0
  165. package/packages/bridge/dist/spawner.d.ts +210 -0
  166. package/packages/bridge/dist/spawner.js +1276 -0
  167. package/packages/bridge/dist/types.d.ts +131 -0
  168. package/packages/bridge/dist/utils.d.ts +15 -0
  169. package/packages/bridge/dist/utils.js +60 -0
  170. package/packages/bridge/package.json +40 -0
  171. package/packages/cloud/dist/api/admin.js +225 -0
  172. package/packages/cloud/dist/api/billing.js +564 -0
  173. package/packages/cloud/dist/api/cli-pty-runner.d.ts +53 -0
  174. package/packages/cloud/dist/api/cli-pty-runner.js +193 -0
  175. package/packages/cloud/dist/api/codex-auth-helper.js +327 -0
  176. package/packages/cloud/dist/api/consensus.js +261 -0
  177. package/packages/cloud/dist/api/coordinators.js +750 -0
  178. package/packages/cloud/dist/api/daemons.js +535 -0
  179. package/packages/cloud/dist/api/generic-webhooks.js +129 -0
  180. package/packages/cloud/dist/api/github-app.js +223 -0
  181. package/packages/cloud/dist/api/monitoring.js +578 -0
  182. package/packages/cloud/dist/api/nango-auth.js +674 -0
  183. package/packages/cloud/dist/api/onboarding.d.ts +15 -0
  184. package/packages/cloud/dist/api/onboarding.js +679 -0
  185. package/packages/cloud/dist/api/policy.js +229 -0
  186. package/packages/cloud/dist/api/provider-env.d.ts +14 -0
  187. package/packages/cloud/dist/api/provider-env.js +75 -0
  188. package/packages/cloud/dist/api/providers.js +564 -0
  189. package/packages/cloud/dist/api/repos.js +577 -0
  190. package/packages/cloud/dist/api/sessions.d.ts +11 -0
  191. package/packages/cloud/dist/api/sessions.js +302 -0
  192. package/packages/cloud/dist/api/teams.js +281 -0
  193. package/packages/cloud/dist/api/test-helpers.js +745 -0
  194. package/packages/cloud/dist/api/workspaces.js +1799 -0
  195. package/packages/cloud/dist/billing/plans.js +245 -0
  196. package/packages/cloud/dist/config.d.ts +5 -0
  197. package/packages/cloud/dist/config.js +5 -0
  198. package/packages/cloud/dist/db/drizzle.d.ts +256 -0
  199. package/packages/cloud/dist/db/drizzle.js +1286 -0
  200. package/packages/cloud/dist/db/schema.d.ts +4873 -0
  201. package/packages/cloud/dist/db/schema.js +620 -0
  202. package/packages/cloud/dist/index.d.ts +11 -0
  203. package/packages/cloud/dist/index.js +38 -0
  204. package/packages/cloud/dist/provisioner/index.d.ts +207 -0
  205. package/packages/cloud/dist/provisioner/index.js +2114 -0
  206. package/packages/cloud/dist/server.js +1924 -0
  207. package/packages/cloud/dist/services/index.d.ts +17 -0
  208. package/packages/cloud/dist/services/index.js +25 -0
  209. package/packages/cloud/dist/services/intro-expiration.d.ts +60 -0
  210. package/packages/cloud/dist/services/intro-expiration.js +252 -0
  211. package/packages/cloud/dist/services/nango.d.ts +201 -0
  212. package/packages/cloud/dist/services/nango.js +392 -0
  213. package/packages/cloud/dist/services/persistence.d.ts +131 -0
  214. package/packages/cloud/dist/shims/consensus.d.ts +23 -0
  215. package/packages/cloud/dist/shims/consensus.js +5 -0
  216. package/packages/cloud/package.json +55 -0
  217. package/packages/config/dist/bridge-config.d.ts +52 -0
  218. package/packages/config/dist/bridge-config.js +143 -0
  219. package/packages/config/dist/bridge-utils.d.ts +30 -0
  220. package/packages/config/dist/bridge-utils.js +54 -0
  221. package/packages/config/dist/cli-auth-config.js +391 -0
  222. package/packages/config/dist/cloud-config.d.ts +75 -0
  223. package/packages/config/dist/cloud-config.js +109 -0
  224. package/packages/config/dist/index.d.ts +13 -0
  225. package/packages/config/dist/index.js +13 -0
  226. package/packages/config/dist/project-namespace.d.ts +73 -0
  227. package/packages/config/dist/project-namespace.js +280 -0
  228. package/packages/config/dist/relay-config.d.ts +25 -0
  229. package/packages/config/dist/relay-config.js +25 -0
  230. package/packages/config/dist/relay-file-writer.d.ts +200 -0
  231. package/packages/config/dist/relay-file-writer.js +407 -0
  232. package/packages/config/dist/schemas.d.ts +672 -0
  233. package/packages/config/dist/schemas.js +180 -0
  234. package/packages/config/dist/shadow-config.d.ts +87 -0
  235. package/packages/config/dist/trajectory-config.d.ts +102 -0
  236. package/packages/config/dist/trajectory-config.js +185 -0
  237. package/packages/config/package.json +98 -0
  238. package/packages/continuity/dist/index.d.ts +9 -0
  239. package/packages/continuity/dist/index.js +9 -0
  240. package/packages/continuity/dist/types.d.ts +180 -0
  241. package/packages/continuity/dist/types.js +2 -0
  242. package/packages/continuity/package.json +32 -0
  243. package/packages/daemon/dist/agent-manager.d.ts +134 -0
  244. package/packages/daemon/dist/agent-manager.js +578 -0
  245. package/packages/daemon/dist/agent-registry.js +213 -0
  246. package/packages/daemon/dist/api.d.ts +106 -0
  247. package/packages/daemon/dist/api.js +876 -0
  248. package/packages/daemon/dist/channel-membership-store.d.ts +55 -0
  249. package/packages/daemon/dist/channel-membership-store.js +176 -0
  250. package/packages/daemon/dist/cli-auth.d.ts +89 -0
  251. package/packages/daemon/dist/cli-auth.js +792 -0
  252. package/packages/daemon/dist/cloud-sync.d.ts +150 -0
  253. package/packages/daemon/dist/cloud-sync.js +446 -0
  254. package/packages/daemon/dist/connection.d.ts +130 -0
  255. package/packages/daemon/dist/connection.js +438 -0
  256. package/packages/daemon/dist/consensus-integration.js +371 -0
  257. package/packages/daemon/dist/delivery-tracker.d.ts +34 -0
  258. package/packages/daemon/dist/delivery-tracker.js +104 -0
  259. package/packages/daemon/dist/enhanced-features.d.ts +118 -0
  260. package/packages/daemon/dist/enhanced-features.js +176 -0
  261. package/packages/daemon/dist/index.d.ts +31 -0
  262. package/packages/daemon/dist/index.js +37 -0
  263. package/packages/daemon/dist/migrations/index.d.ts +73 -0
  264. package/packages/daemon/dist/migrations/index.js +241 -0
  265. package/packages/daemon/dist/orchestrator.d.ts +217 -0
  266. package/packages/daemon/dist/orchestrator.js +1143 -0
  267. package/packages/daemon/dist/relay-ledger.d.ts +261 -0
  268. package/packages/daemon/dist/relay-ledger.js +532 -0
  269. package/packages/daemon/dist/relay-watchdog.d.ts +125 -0
  270. package/packages/daemon/dist/relay-watchdog.js +611 -0
  271. package/packages/daemon/dist/repo-manager.js +384 -0
  272. package/packages/daemon/dist/router.d.ts +370 -0
  273. package/packages/daemon/dist/router.js +1437 -0
  274. package/packages/daemon/dist/server.d.ts +174 -0
  275. package/packages/daemon/dist/server.js +1001 -0
  276. package/packages/daemon/dist/spawn-manager.d.ts +78 -0
  277. package/packages/daemon/dist/spawn-manager.js +165 -0
  278. package/packages/daemon/dist/sync-queue.d.ts +116 -0
  279. package/packages/daemon/dist/sync-queue.js +361 -0
  280. package/packages/daemon/dist/types.d.ts +133 -0
  281. package/packages/daemon/dist/workspace-manager.js +314 -0
  282. package/packages/daemon/package.json +52 -0
  283. package/packages/dashboard/README.md +48 -0
  284. package/packages/dashboard/dist/health-worker-manager.d.ts +62 -0
  285. package/packages/dashboard/dist/health-worker-manager.js +144 -0
  286. package/packages/dashboard/dist/health-worker.d.ts +9 -0
  287. package/packages/dashboard/dist/health-worker.js +79 -0
  288. package/packages/dashboard/dist/index.d.ts +20 -0
  289. package/packages/dashboard/dist/index.js +19 -0
  290. package/packages/dashboard/dist/metrics.d.ts +105 -0
  291. package/packages/dashboard/dist/metrics.js +193 -0
  292. package/packages/dashboard/dist/needs-attention.d.ts +24 -0
  293. package/packages/dashboard/dist/needs-attention.js +78 -0
  294. package/packages/dashboard/dist/server.d.ts +25 -0
  295. package/packages/dashboard/dist/server.js +5107 -0
  296. package/packages/dashboard/dist/start.d.ts +6 -0
  297. package/packages/dashboard/dist/start.js +13 -0
  298. package/packages/dashboard/dist/types/threading.d.ts +8 -0
  299. package/packages/dashboard/dist/types/threading.js +2 -0
  300. package/packages/dashboard/dist/user-bridge.d.ts +154 -0
  301. package/packages/dashboard/dist/user-bridge.js +372 -0
  302. package/packages/dashboard/package.json +72 -0
  303. package/packages/dashboard/ui/.next/BUILD_ID +1 -0
  304. package/packages/dashboard/ui/.next/app-build-manifest.json +135 -0
  305. package/packages/dashboard/ui/.next/app-path-routes-manifest.json +1 -0
  306. package/packages/dashboard/ui/.next/build-manifest.json +32 -0
  307. package/packages/dashboard/ui/.next/cache/config.json +7 -0
  308. package/packages/dashboard/ui/.next/cache/eslint/.cache_1asv1h5 +1 -0
  309. package/packages/dashboard/ui/.next/cache/webpack/client-production/0.pack +0 -0
  310. package/packages/dashboard/ui/.next/cache/webpack/client-production/index.pack +0 -0
  311. package/packages/dashboard/ui/.next/cache/webpack/edge-server-production/0.pack +0 -0
  312. package/packages/dashboard/ui/.next/cache/webpack/edge-server-production/index.pack +0 -0
  313. package/packages/dashboard/ui/.next/cache/webpack/server-production/0.pack +0 -0
  314. package/packages/dashboard/ui/.next/cache/webpack/server-production/index.pack +0 -0
  315. package/packages/dashboard/ui/.next/export-detail.json +1 -0
  316. package/packages/dashboard/ui/.next/export-marker.json +1 -0
  317. package/packages/dashboard/ui/.next/images-manifest.json +1 -0
  318. package/packages/dashboard/ui/.next/next-minimal-server.js.nft.json +1 -0
  319. package/packages/dashboard/ui/.next/next-server.js.nft.json +1 -0
  320. package/packages/dashboard/ui/.next/package.json +1 -0
  321. package/packages/dashboard/ui/.next/prerender-manifest.json +1 -0
  322. package/packages/dashboard/ui/.next/react-loadable-manifest.json +1970 -0
  323. package/packages/dashboard/ui/.next/required-server-files.json +1 -0
  324. package/packages/dashboard/ui/.next/routes-manifest.json +1 -0
  325. package/packages/dashboard/ui/.next/server/app/_not-found/page.js +1 -0
  326. package/packages/dashboard/ui/.next/server/app/_not-found/page.js.nft.json +1 -0
  327. package/packages/dashboard/ui/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  328. package/packages/dashboard/ui/.next/server/app/_not-found.html +1 -0
  329. package/packages/dashboard/ui/.next/server/app/_not-found.meta +6 -0
  330. package/packages/dashboard/ui/.next/server/app/_not-found.rsc +9 -0
  331. package/packages/dashboard/ui/.next/server/app/app/onboarding/page.js +6 -0
  332. package/packages/dashboard/ui/.next/server/app/app/onboarding/page.js.nft.json +1 -0
  333. package/packages/dashboard/ui/.next/server/app/app/onboarding/page_client-reference-manifest.js +1 -0
  334. package/packages/dashboard/ui/.next/server/app/app/onboarding.html +1 -0
  335. package/packages/dashboard/ui/.next/server/app/app/onboarding.meta +5 -0
  336. package/packages/dashboard/ui/.next/server/app/app/onboarding.rsc +7 -0
  337. package/packages/dashboard/ui/.next/server/app/app/page.js +436 -0
  338. package/packages/dashboard/ui/.next/server/app/app/page.js.nft.json +1 -0
  339. package/packages/dashboard/ui/.next/server/app/app/page_client-reference-manifest.js +1 -0
  340. package/packages/dashboard/ui/.next/server/app/app.html +1 -0
  341. package/packages/dashboard/ui/.next/server/app/app.meta +5 -0
  342. package/packages/dashboard/ui/.next/server/app/app.rsc +7 -0
  343. package/packages/dashboard/ui/.next/server/app/apple-icon.png/route.js +12 -0
  344. package/packages/dashboard/ui/.next/server/app/apple-icon.png/route.js.nft.json +1 -0
  345. package/packages/dashboard/ui/.next/server/app/apple-icon.png.body +0 -0
  346. package/packages/dashboard/ui/.next/server/app/apple-icon.png.meta +1 -0
  347. package/packages/dashboard/ui/.next/server/app/cloud/link/page.js +1 -0
  348. package/packages/dashboard/ui/.next/server/app/cloud/link/page.js.nft.json +1 -0
  349. package/packages/dashboard/ui/.next/server/app/cloud/link/page_client-reference-manifest.js +1 -0
  350. package/packages/dashboard/ui/.next/server/app/cloud/link.html +1 -0
  351. package/packages/dashboard/ui/.next/server/app/cloud/link.meta +5 -0
  352. package/packages/dashboard/ui/.next/server/app/cloud/link.rsc +7 -0
  353. package/packages/dashboard/ui/.next/server/app/connect-repos/page.js +6 -0
  354. package/packages/dashboard/ui/.next/server/app/connect-repos/page.js.nft.json +1 -0
  355. package/packages/dashboard/ui/.next/server/app/connect-repos/page_client-reference-manifest.js +1 -0
  356. package/packages/dashboard/ui/.next/server/app/connect-repos.html +1 -0
  357. package/packages/dashboard/ui/.next/server/app/connect-repos.meta +5 -0
  358. package/packages/dashboard/ui/.next/server/app/connect-repos.rsc +7 -0
  359. package/packages/dashboard/ui/.next/server/app/history/page.js +1 -0
  360. package/packages/dashboard/ui/.next/server/app/history/page.js.nft.json +1 -0
  361. package/packages/dashboard/ui/.next/server/app/history/page_client-reference-manifest.js +1 -0
  362. package/packages/dashboard/ui/.next/server/app/history.html +1 -0
  363. package/packages/dashboard/ui/.next/server/app/history.meta +5 -0
  364. package/packages/dashboard/ui/.next/server/app/history.rsc +7 -0
  365. package/packages/dashboard/ui/.next/server/app/index.html +1 -0
  366. package/packages/dashboard/ui/.next/server/app/index.meta +5 -0
  367. package/packages/dashboard/ui/.next/server/app/index.rsc +7 -0
  368. package/packages/dashboard/ui/.next/server/app/login/page.js +6 -0
  369. package/packages/dashboard/ui/.next/server/app/login/page.js.nft.json +1 -0
  370. package/packages/dashboard/ui/.next/server/app/login/page_client-reference-manifest.js +1 -0
  371. package/packages/dashboard/ui/.next/server/app/login.html +5 -0
  372. package/packages/dashboard/ui/.next/server/app/login.meta +5 -0
  373. package/packages/dashboard/ui/.next/server/app/login.rsc +7 -0
  374. package/packages/dashboard/ui/.next/server/app/metrics/page.js +1 -0
  375. package/packages/dashboard/ui/.next/server/app/metrics/page.js.nft.json +1 -0
  376. package/packages/dashboard/ui/.next/server/app/metrics/page_client-reference-manifest.js +1 -0
  377. package/packages/dashboard/ui/.next/server/app/metrics.html +1 -0
  378. package/packages/dashboard/ui/.next/server/app/metrics.meta +5 -0
  379. package/packages/dashboard/ui/.next/server/app/metrics.rsc +7 -0
  380. package/packages/dashboard/ui/.next/server/app/page.js +1 -0
  381. package/packages/dashboard/ui/.next/server/app/page.js.nft.json +1 -0
  382. package/packages/dashboard/ui/.next/server/app/page_client-reference-manifest.js +1 -0
  383. package/packages/dashboard/ui/.next/server/app/pricing/page.js +5 -0
  384. package/packages/dashboard/ui/.next/server/app/pricing/page.js.nft.json +1 -0
  385. package/packages/dashboard/ui/.next/server/app/pricing/page_client-reference-manifest.js +1 -0
  386. package/packages/dashboard/ui/.next/server/app/pricing.html +13 -0
  387. package/packages/dashboard/ui/.next/server/app/pricing.meta +5 -0
  388. package/packages/dashboard/ui/.next/server/app/pricing.rsc +7 -0
  389. package/packages/dashboard/ui/.next/server/app/providers/page.js +2 -0
  390. package/packages/dashboard/ui/.next/server/app/providers/page.js.nft.json +1 -0
  391. package/packages/dashboard/ui/.next/server/app/providers/page_client-reference-manifest.js +1 -0
  392. package/packages/dashboard/ui/.next/server/app/providers/setup/[provider]/page.js +1 -0
  393. package/packages/dashboard/ui/.next/server/app/providers/setup/[provider]/page.js.nft.json +1 -0
  394. package/packages/dashboard/ui/.next/server/app/providers/setup/[provider]/page_client-reference-manifest.js +1 -0
  395. package/packages/dashboard/ui/.next/server/app/providers/setup/claude.html +1 -0
  396. package/packages/dashboard/ui/.next/server/app/providers/setup/claude.meta +5 -0
  397. package/packages/dashboard/ui/.next/server/app/providers/setup/claude.rsc +8 -0
  398. package/packages/dashboard/ui/.next/server/app/providers/setup/codex.html +1 -0
  399. package/packages/dashboard/ui/.next/server/app/providers/setup/codex.meta +5 -0
  400. package/packages/dashboard/ui/.next/server/app/providers/setup/codex.rsc +8 -0
  401. package/packages/dashboard/ui/.next/server/app/providers/setup/cursor.html +1 -0
  402. package/packages/dashboard/ui/.next/server/app/providers/setup/cursor.meta +5 -0
  403. package/packages/dashboard/ui/.next/server/app/providers/setup/cursor.rsc +8 -0
  404. package/packages/dashboard/ui/.next/server/app/providers.html +1 -0
  405. package/packages/dashboard/ui/.next/server/app/providers.meta +5 -0
  406. package/packages/dashboard/ui/.next/server/app/providers.rsc +7 -0
  407. package/packages/dashboard/ui/.next/server/app/signup/page.js +6 -0
  408. package/packages/dashboard/ui/.next/server/app/signup/page.js.nft.json +1 -0
  409. package/packages/dashboard/ui/.next/server/app/signup/page_client-reference-manifest.js +1 -0
  410. package/packages/dashboard/ui/.next/server/app/signup.html +6 -0
  411. package/packages/dashboard/ui/.next/server/app/signup.meta +5 -0
  412. package/packages/dashboard/ui/.next/server/app/signup.rsc +7 -0
  413. package/packages/dashboard/ui/.next/server/app-paths-manifest.json +16 -0
  414. package/packages/dashboard/ui/.next/server/chunks/190.js +1 -0
  415. package/packages/dashboard/ui/.next/server/chunks/205.js +1 -0
  416. package/packages/dashboard/ui/.next/server/chunks/251.js +9 -0
  417. package/packages/dashboard/ui/.next/server/chunks/288.js +1 -0
  418. package/packages/dashboard/ui/.next/server/chunks/434.js +1 -0
  419. package/packages/dashboard/ui/.next/server/chunks/471.js +2 -0
  420. package/packages/dashboard/ui/.next/server/chunks/621.js +1 -0
  421. package/packages/dashboard/ui/.next/server/chunks/680.js +5 -0
  422. package/packages/dashboard/ui/.next/server/chunks/682.js +6 -0
  423. package/packages/dashboard/ui/.next/server/chunks/684.js +1 -0
  424. package/packages/dashboard/ui/.next/server/chunks/71.js +196 -0
  425. package/packages/dashboard/ui/.next/server/chunks/711.js +1 -0
  426. package/packages/dashboard/ui/.next/server/chunks/90.js +17 -0
  427. package/packages/dashboard/ui/.next/server/chunks/948.js +2 -0
  428. package/packages/dashboard/ui/.next/server/chunks/font-manifest.json +1 -0
  429. package/packages/dashboard/ui/.next/server/font-manifest.json +1 -0
  430. package/packages/dashboard/ui/.next/server/functions-config-manifest.json +1 -0
  431. package/packages/dashboard/ui/.next/server/interception-route-rewrite-manifest.js +1 -0
  432. package/packages/dashboard/ui/.next/server/middleware-build-manifest.js +1 -0
  433. package/packages/dashboard/ui/.next/server/middleware-manifest.json +6 -0
  434. package/packages/dashboard/ui/.next/server/middleware-react-loadable-manifest.js +1 -0
  435. package/packages/dashboard/ui/.next/server/next-font-manifest.js +1 -0
  436. package/packages/dashboard/ui/.next/server/next-font-manifest.json +1 -0
  437. package/packages/dashboard/ui/.next/server/pages/404.html +1 -0
  438. package/packages/dashboard/ui/.next/server/pages/500.html +1 -0
  439. package/packages/dashboard/ui/.next/server/pages/_app.js +1 -0
  440. package/packages/dashboard/ui/.next/server/pages/_app.js.nft.json +1 -0
  441. package/packages/dashboard/ui/.next/server/pages/_document.js +1 -0
  442. package/packages/dashboard/ui/.next/server/pages/_document.js.nft.json +1 -0
  443. package/packages/dashboard/ui/.next/server/pages/_error.js +1 -0
  444. package/packages/dashboard/ui/.next/server/pages/_error.js.nft.json +1 -0
  445. package/packages/dashboard/ui/.next/server/pages-manifest.json +1 -0
  446. package/packages/dashboard/ui/.next/server/server-reference-manifest.js +1 -0
  447. package/packages/dashboard/ui/.next/server/server-reference-manifest.json +1 -0
  448. package/packages/dashboard/ui/.next/server/webpack-runtime.js +1 -0
  449. package/packages/dashboard/ui/.next/static/HR7W9z1PPVPFqUboUVZFZ/_buildManifest.js +1 -0
  450. package/packages/dashboard/ui/.next/static/HR7W9z1PPVPFqUboUVZFZ/_ssgManifest.js +1 -0
  451. package/packages/dashboard/ui/.next/static/chunks/116-a883fca163f3a5bc.js +1 -0
  452. package/packages/dashboard/ui/.next/static/chunks/117-c8afed19e821a35d.js +2 -0
  453. package/packages/dashboard/ui/.next/static/chunks/282-980c2eb8fff20123.js +1 -0
  454. package/packages/dashboard/ui/.next/static/chunks/532-bace199897eeab37.js +9 -0
  455. package/packages/dashboard/ui/.next/static/chunks/631-af51bad94027527a.js +1 -0
  456. package/packages/dashboard/ui/.next/static/chunks/648-acb2ff9f77cbfbd3.js +1 -0
  457. package/packages/dashboard/ui/.next/static/chunks/677-30e60cb0b47875b6.js +1 -0
  458. package/packages/dashboard/ui/.next/static/chunks/766-2aea80818f7eb0d8.js +1 -0
  459. package/packages/dashboard/ui/.next/static/chunks/83-4f08122d4e7e79a6.js +1 -0
  460. package/packages/dashboard/ui/.next/static/chunks/847-f1f467060f32afff.js +1 -0
  461. package/packages/dashboard/ui/.next/static/chunks/891-5cb1513eeb97a891.js +1 -0
  462. package/packages/dashboard/ui/.next/static/chunks/app/_not-found/page-60501fddbafba9dc.js +1 -0
  463. package/packages/dashboard/ui/.next/static/chunks/app/app/onboarding/page-9914652442f7e4fb.js +1 -0
  464. package/packages/dashboard/ui/.next/static/chunks/app/app/page-44813aa26ad19681.js +1 -0
  465. package/packages/dashboard/ui/.next/static/chunks/app/cloud/link/page-fa1d5842aa90e8a6.js +1 -0
  466. package/packages/dashboard/ui/.next/static/chunks/app/connect-repos/page-113060009ef35bc2.js +1 -0
  467. package/packages/dashboard/ui/.next/static/chunks/app/history/page-9965d2483011b846.js +1 -0
  468. package/packages/dashboard/ui/.next/static/chunks/app/layout-6b91e33784c20610.js +1 -0
  469. package/packages/dashboard/ui/.next/static/chunks/app/login/page-a0ca6f7ca6a100b8.js +1 -0
  470. package/packages/dashboard/ui/.next/static/chunks/app/metrics/page-1e37ef8e73940b40.js +1 -0
  471. package/packages/dashboard/ui/.next/static/chunks/app/page-7993778218818ace.js +1 -0
  472. package/packages/dashboard/ui/.next/static/chunks/app/pricing/page-9db3ebdfa567a7c9.js +1 -0
  473. package/packages/dashboard/ui/.next/static/chunks/app/providers/page-bcf46064ac4474ce.js +1 -0
  474. package/packages/dashboard/ui/.next/static/chunks/app/providers/setup/[provider]/page-4dbe33f0f7691b7c.js +1 -0
  475. package/packages/dashboard/ui/.next/static/chunks/app/signup/page-1ede2205b58649ca.js +1 -0
  476. package/packages/dashboard/ui/.next/static/chunks/e868780c-48e5f147c90a3a41.js +18 -0
  477. package/packages/dashboard/ui/.next/static/chunks/fd9d1056-609918ca7b6280bb.js +1 -0
  478. package/packages/dashboard/ui/.next/static/chunks/framework-f66176bb897dc684.js +1 -0
  479. package/packages/dashboard/ui/.next/static/chunks/main-5a40a5ae29646e1b.js +1 -0
  480. package/packages/dashboard/ui/.next/static/chunks/main-app-fdbeb09028f57c9f.js +1 -0
  481. package/packages/dashboard/ui/.next/static/chunks/pages/_app-72b849fbd24ac258.js +1 -0
  482. package/packages/dashboard/ui/.next/static/chunks/pages/_error-7ba65e1336b92748.js +1 -0
  483. package/packages/dashboard/ui/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  484. package/packages/dashboard/ui/.next/static/chunks/webpack-1cdd8ed57114d5e1.js +1 -0
  485. package/packages/dashboard/ui/.next/static/css/4034f236dd1a3178.css +1 -0
  486. package/packages/dashboard/ui/.next/static/css/99c2552394077586.css +1 -0
  487. package/packages/dashboard/ui/.next/trace +63 -0
  488. package/packages/dashboard/ui/.next/types/app/app/onboarding/page.ts +79 -0
  489. package/packages/dashboard/ui/.next/types/app/app/page.ts +79 -0
  490. package/packages/dashboard/ui/.next/types/app/cloud/link/page.ts +79 -0
  491. package/packages/dashboard/ui/.next/types/app/connect-repos/page.ts +79 -0
  492. package/packages/dashboard/ui/.next/types/app/history/page.ts +79 -0
  493. package/packages/dashboard/ui/.next/types/app/layout.ts +79 -0
  494. package/packages/dashboard/ui/.next/types/app/login/page.ts +79 -0
  495. package/packages/dashboard/ui/.next/types/app/metrics/page.ts +79 -0
  496. package/packages/dashboard/ui/.next/types/app/page.ts +79 -0
  497. package/packages/dashboard/ui/.next/types/app/pricing/page.ts +79 -0
  498. package/packages/dashboard/ui/.next/types/app/providers/page.ts +79 -0
  499. package/packages/dashboard/ui/.next/types/app/providers/setup/[provider]/page.ts +79 -0
  500. package/packages/dashboard/ui/.next/types/app/signup/page.ts +79 -0
  501. package/packages/dashboard/ui/.next/types/package.json +1 -0
  502. package/packages/dashboard/ui/app/app/onboarding/page.tsx +394 -0
  503. package/packages/dashboard/ui/app/app/page.tsx +667 -0
  504. package/packages/dashboard/ui/app/apple-icon.png +0 -0
  505. package/packages/dashboard/ui/app/cloud/link/page.tsx +464 -0
  506. package/packages/dashboard/ui/app/connect-repos/page.tsx +410 -0
  507. package/packages/dashboard/ui/app/favicon.png +0 -0
  508. package/packages/dashboard/ui/app/globals.css +59 -0
  509. package/packages/dashboard/ui/app/history/page.tsx +658 -0
  510. package/packages/dashboard/ui/app/layout.tsx +25 -0
  511. package/packages/dashboard/ui/app/login/page.tsx +280 -0
  512. package/packages/dashboard/ui/app/metrics/page.tsx +751 -0
  513. package/packages/dashboard/ui/app/page.tsx +59 -0
  514. package/packages/dashboard/ui/app/pricing/page.tsx +7 -0
  515. package/packages/dashboard/ui/app/providers/page.tsx +193 -0
  516. package/packages/dashboard/ui/app/providers/setup/[provider]/ProviderSetupClient.tsx +148 -0
  517. package/packages/dashboard/ui/app/providers/setup/[provider]/constants.ts +35 -0
  518. package/packages/dashboard/ui/app/providers/setup/[provider]/page.tsx +42 -0
  519. package/packages/dashboard/ui/app/signup/page.tsx +343 -0
  520. package/packages/dashboard/ui/index.ts +49 -0
  521. package/packages/dashboard/ui/landing/LandingPage.tsx +713 -0
  522. package/packages/dashboard/ui/landing/PricingPage.tsx +559 -0
  523. package/packages/dashboard/ui/landing/index.ts +6 -0
  524. package/packages/dashboard/ui/landing/styles.css +2850 -0
  525. package/packages/dashboard/ui/lib/agent-merge.ts +35 -0
  526. package/packages/dashboard/ui/lib/api.ts +1155 -0
  527. package/packages/dashboard/ui/lib/cloudApi.ts +876 -0
  528. package/packages/dashboard/ui/lib/colors.ts +218 -0
  529. package/packages/dashboard/ui/lib/hierarchy.ts +242 -0
  530. package/packages/dashboard/ui/lib/stuckDetection.ts +142 -0
  531. package/packages/dashboard/ui/next-env.d.ts +5 -0
  532. package/packages/dashboard/ui/next.config.js +41 -0
  533. package/packages/dashboard/ui/package-lock.json +2882 -0
  534. package/packages/dashboard/ui/package.json +33 -0
  535. package/packages/dashboard/ui/postcss.config.js +5 -0
  536. package/packages/dashboard/ui/react-components/ActivityFeed.tsx +216 -0
  537. package/packages/dashboard/ui/react-components/AddWorkspaceModal.tsx +170 -0
  538. package/packages/dashboard/ui/react-components/AgentCard.tsx +587 -0
  539. package/packages/dashboard/ui/react-components/AgentList.tsx +411 -0
  540. package/packages/dashboard/ui/react-components/AgentProfilePanel.tsx +564 -0
  541. package/packages/dashboard/ui/react-components/App.tsx +3447 -0
  542. package/packages/dashboard/ui/react-components/BillingPanel.tsx +922 -0
  543. package/packages/dashboard/ui/react-components/BillingResult.tsx +447 -0
  544. package/packages/dashboard/ui/react-components/BroadcastComposer.tsx +690 -0
  545. package/packages/dashboard/ui/react-components/ChannelAdminPanel.tsx +773 -0
  546. package/packages/dashboard/ui/react-components/ChannelBrowser.tsx +385 -0
  547. package/packages/dashboard/ui/react-components/ChannelChat.tsx +307 -0
  548. package/packages/dashboard/ui/react-components/ChannelSidebar.tsx +399 -0
  549. package/packages/dashboard/ui/react-components/CloudSessionProvider.tsx +130 -0
  550. package/packages/dashboard/ui/react-components/CommandPalette.tsx +815 -0
  551. package/packages/dashboard/ui/react-components/ConfirmationDialog.tsx +133 -0
  552. package/packages/dashboard/ui/react-components/ConversationHistory.tsx +518 -0
  553. package/packages/dashboard/ui/react-components/CoordinatorPanel.tsx +944 -0
  554. package/packages/dashboard/ui/react-components/DecisionQueue.tsx +717 -0
  555. package/packages/dashboard/ui/react-components/DirectMessageView.tsx +164 -0
  556. package/packages/dashboard/ui/react-components/FileAutocomplete.tsx +368 -0
  557. package/packages/dashboard/ui/react-components/FleetOverview.tsx +278 -0
  558. package/packages/dashboard/ui/react-components/LogViewer.tsx +310 -0
  559. package/packages/dashboard/ui/react-components/LogViewerPanel.tsx +482 -0
  560. package/packages/dashboard/ui/react-components/Logo.tsx +284 -0
  561. package/packages/dashboard/ui/react-components/MentionAutocomplete.tsx +384 -0
  562. package/packages/dashboard/ui/react-components/MessageList.tsx +649 -0
  563. package/packages/dashboard/ui/react-components/MessageSenderName.tsx +91 -0
  564. package/packages/dashboard/ui/react-components/MessageStatusIndicator.tsx +142 -0
  565. package/packages/dashboard/ui/react-components/NewConversationModal.tsx +400 -0
  566. package/packages/dashboard/ui/react-components/NotificationToast.tsx +488 -0
  567. package/packages/dashboard/ui/react-components/OnlineUsersIndicator.tsx +164 -0
  568. package/packages/dashboard/ui/react-components/Pagination.tsx +124 -0
  569. package/packages/dashboard/ui/react-components/PricingPlans.tsx +386 -0
  570. package/packages/dashboard/ui/react-components/ProjectList.tsx +625 -0
  571. package/packages/dashboard/ui/react-components/ProviderAuthFlow.tsx +843 -0
  572. package/packages/dashboard/ui/react-components/ProviderConnectionList.tsx +363 -0
  573. package/packages/dashboard/ui/react-components/ProvisioningProgress.tsx +730 -0
  574. package/packages/dashboard/ui/react-components/RepoAccessPanel.tsx +392 -0
  575. package/packages/dashboard/ui/react-components/ServerCard.tsx +202 -0
  576. package/packages/dashboard/ui/react-components/SessionExpiredModal.tsx +128 -0
  577. package/packages/dashboard/ui/react-components/SpawnModal.tsx +704 -0
  578. package/packages/dashboard/ui/react-components/TaskAssignmentUI.tsx +375 -0
  579. package/packages/dashboard/ui/react-components/TerminalProviderSetup.tsx +608 -0
  580. package/packages/dashboard/ui/react-components/ThemeProvider.tsx +325 -0
  581. package/packages/dashboard/ui/react-components/ThinkingIndicator.tsx +231 -0
  582. package/packages/dashboard/ui/react-components/ThreadList.tsx +198 -0
  583. package/packages/dashboard/ui/react-components/ThreadPanel.tsx +346 -0
  584. package/packages/dashboard/ui/react-components/TrajectoryViewer.tsx +698 -0
  585. package/packages/dashboard/ui/react-components/TypingIndicator.tsx +69 -0
  586. package/packages/dashboard/ui/react-components/UsageBanner.tsx +231 -0
  587. package/packages/dashboard/ui/react-components/UserProfilePanel.tsx +233 -0
  588. package/packages/dashboard/ui/react-components/WorkspaceContext.tsx +107 -0
  589. package/packages/dashboard/ui/react-components/WorkspaceSelector.tsx +234 -0
  590. package/packages/dashboard/ui/react-components/WorkspaceStatusIndicator.tsx +370 -0
  591. package/packages/dashboard/ui/react-components/XTermInteractive.tsx +510 -0
  592. package/packages/dashboard/ui/react-components/XTermLogViewer.tsx +719 -0
  593. package/packages/dashboard/ui/react-components/channels/ChannelDialogs.tsx +1411 -0
  594. package/packages/dashboard/ui/react-components/channels/ChannelHeader.tsx +317 -0
  595. package/packages/dashboard/ui/react-components/channels/ChannelMessageList.tsx +463 -0
  596. package/packages/dashboard/ui/react-components/channels/ChannelViewV1.tsx +146 -0
  597. package/packages/dashboard/ui/react-components/channels/MessageInput.tsx +288 -0
  598. package/packages/dashboard/ui/react-components/channels/SearchInput.tsx +172 -0
  599. package/packages/dashboard/ui/react-components/channels/SearchResults.tsx +336 -0
  600. package/packages/dashboard/ui/react-components/channels/api.ts +697 -0
  601. package/packages/dashboard/ui/react-components/channels/index.ts +76 -0
  602. package/packages/dashboard/ui/react-components/channels/mockApi.ts +344 -0
  603. package/packages/dashboard/ui/react-components/channels/types.ts +566 -0
  604. package/packages/dashboard/ui/react-components/hooks/index.ts +57 -0
  605. package/packages/dashboard/ui/react-components/hooks/useAgentLogs.ts +394 -0
  606. package/packages/dashboard/ui/react-components/hooks/useAgents.ts +127 -0
  607. package/packages/dashboard/ui/react-components/hooks/useBroadcastDedup.ts +86 -0
  608. package/packages/dashboard/ui/react-components/hooks/useChannelAdmin.ts +329 -0
  609. package/packages/dashboard/ui/react-components/hooks/useChannelBrowser.ts +239 -0
  610. package/packages/dashboard/ui/react-components/hooks/useChannelCommands.ts +138 -0
  611. package/packages/dashboard/ui/react-components/hooks/useChannels.ts +328 -0
  612. package/packages/dashboard/ui/react-components/hooks/useDebounce.ts +29 -0
  613. package/packages/dashboard/ui/react-components/hooks/useDirectMessage.ts +141 -0
  614. package/packages/dashboard/ui/react-components/hooks/useMessages.ts +309 -0
  615. package/packages/dashboard/ui/react-components/hooks/useOrchestrator.ts +364 -0
  616. package/packages/dashboard/ui/react-components/hooks/usePinnedAgents.ts +140 -0
  617. package/packages/dashboard/ui/react-components/hooks/usePresence.ts +340 -0
  618. package/packages/dashboard/ui/react-components/hooks/useRecentRepos.ts +130 -0
  619. package/packages/dashboard/ui/react-components/hooks/useSession.ts +209 -0
  620. package/packages/dashboard/ui/react-components/hooks/useTrajectory.ts +265 -0
  621. package/packages/dashboard/ui/react-components/hooks/useWebSocket.ts +169 -0
  622. package/packages/dashboard/ui/react-components/hooks/useWorkspaceMembers.ts +120 -0
  623. package/packages/dashboard/ui/react-components/hooks/useWorkspaceRepos.ts +73 -0
  624. package/packages/dashboard/ui/react-components/hooks/useWorkspaceStatus.ts +237 -0
  625. package/packages/dashboard/ui/react-components/index.ts +81 -0
  626. package/packages/dashboard/ui/react-components/layout/Header.tsx +355 -0
  627. package/packages/dashboard/ui/react-components/layout/RepoContextHeader.tsx +361 -0
  628. package/packages/dashboard/ui/react-components/layout/Sidebar.archive.test.tsx +126 -0
  629. package/packages/dashboard/ui/react-components/layout/Sidebar.test.tsx +691 -0
  630. package/packages/dashboard/ui/react-components/layout/Sidebar.tsx +930 -0
  631. package/packages/dashboard/ui/react-components/layout/index.ts +7 -0
  632. package/packages/dashboard/ui/react-components/settings/BillingSettingsPanel.tsx +564 -0
  633. package/packages/dashboard/ui/react-components/settings/SettingsPage.tsx +544 -0
  634. package/packages/dashboard/ui/react-components/settings/TeamSettingsPanel.tsx +560 -0
  635. package/packages/dashboard/ui/react-components/settings/WorkspaceSettingsPanel.tsx +1329 -0
  636. package/packages/dashboard/ui/react-components/settings/index.ts +11 -0
  637. package/packages/dashboard/ui/react-components/settings/types.ts +53 -0
  638. package/packages/dashboard/ui/react-components/utils/messageFormatting.tsx +370 -0
  639. package/packages/dashboard/ui/tailwind.config.js +148 -0
  640. package/packages/dashboard/ui/types/index.ts +304 -0
  641. package/packages/dashboard/ui/types/threading.ts +7 -0
  642. package/packages/dashboard/ui-dist/404.html +1 -0
  643. package/packages/dashboard/ui-dist/_next/static/HR7W9z1PPVPFqUboUVZFZ/_buildManifest.js +1 -0
  644. package/packages/dashboard/ui-dist/_next/static/HR7W9z1PPVPFqUboUVZFZ/_ssgManifest.js +1 -0
  645. package/packages/dashboard/ui-dist/_next/static/ZCFjHbkF8yDKS2md3lVgb/_buildManifest.js +1 -0
  646. package/packages/dashboard/ui-dist/_next/static/ZCFjHbkF8yDKS2md3lVgb/_ssgManifest.js +1 -0
  647. package/packages/dashboard/ui-dist/_next/static/chunks/116-a883fca163f3a5bc.js +1 -0
  648. package/packages/dashboard/ui-dist/_next/static/chunks/117-c8afed19e821a35d.js +2 -0
  649. package/packages/dashboard/ui-dist/_next/static/chunks/282-980c2eb8fff20123.js +1 -0
  650. package/packages/dashboard/ui-dist/_next/static/chunks/320-900169c942e31422.js +1 -0
  651. package/packages/dashboard/ui-dist/_next/static/chunks/532-bace199897eeab37.js +9 -0
  652. package/packages/dashboard/ui-dist/_next/static/chunks/631-af51bad94027527a.js +1 -0
  653. package/packages/dashboard/ui-dist/_next/static/chunks/648-acb2ff9f77cbfbd3.js +1 -0
  654. package/packages/dashboard/ui-dist/_next/static/chunks/677-30e60cb0b47875b6.js +1 -0
  655. package/packages/dashboard/ui-dist/_next/static/chunks/766-2aea80818f7eb0d8.js +1 -0
  656. package/packages/dashboard/ui-dist/_next/static/chunks/83-4f08122d4e7e79a6.js +1 -0
  657. package/packages/dashboard/ui-dist/_next/static/chunks/847-f1f467060f32afff.js +1 -0
  658. package/packages/dashboard/ui-dist/_next/static/chunks/891-5cb1513eeb97a891.js +1 -0
  659. package/packages/dashboard/ui-dist/_next/static/chunks/app/_not-found/page-60501fddbafba9dc.js +1 -0
  660. package/packages/dashboard/ui-dist/_next/static/chunks/app/app/onboarding/page-9914652442f7e4fb.js +1 -0
  661. package/packages/dashboard/ui-dist/_next/static/chunks/app/app/onboarding/page-f746f29e01fffc43.js +1 -0
  662. package/packages/dashboard/ui-dist/_next/static/chunks/app/app/page-2e525b1dcc790967.js +1 -0
  663. package/packages/dashboard/ui-dist/_next/static/chunks/app/app/page-44813aa26ad19681.js +1 -0
  664. package/packages/dashboard/ui-dist/_next/static/chunks/app/cloud/link/page-5011ae044b90449d.js +1 -0
  665. package/packages/dashboard/ui-dist/_next/static/chunks/app/cloud/link/page-fa1d5842aa90e8a6.js +1 -0
  666. package/packages/dashboard/ui-dist/_next/static/chunks/app/connect-repos/page-03ac6f35a6654ea6.js +1 -0
  667. package/packages/dashboard/ui-dist/_next/static/chunks/app/connect-repos/page-113060009ef35bc2.js +1 -0
  668. package/packages/dashboard/ui-dist/_next/static/chunks/app/history/page-9965d2483011b846.js +1 -0
  669. package/packages/dashboard/ui-dist/_next/static/chunks/app/history/page-b2ce7c96ed0931da.js +1 -0
  670. package/packages/dashboard/ui-dist/_next/static/chunks/app/layout-6b91e33784c20610.js +1 -0
  671. package/packages/dashboard/ui-dist/_next/static/chunks/app/layout-c0d118c0f92d969c.js +1 -0
  672. package/packages/dashboard/ui-dist/_next/static/chunks/app/login/page-6ec54eee75877971.js +1 -0
  673. package/packages/dashboard/ui-dist/_next/static/chunks/app/login/page-a0ca6f7ca6a100b8.js +1 -0
  674. package/packages/dashboard/ui-dist/_next/static/chunks/app/metrics/page-1e37ef8e73940b40.js +1 -0
  675. package/packages/dashboard/ui-dist/_next/static/chunks/app/metrics/page-bf2cb1e5915bc92d.js +1 -0
  676. package/packages/dashboard/ui-dist/_next/static/chunks/app/page-4e64923d73c35bc9.js +1 -0
  677. package/packages/dashboard/ui-dist/_next/static/chunks/app/page-7993778218818ace.js +1 -0
  678. package/packages/dashboard/ui-dist/_next/static/chunks/app/pricing/page-0efa024c28ba4597.js +1 -0
  679. package/packages/dashboard/ui-dist/_next/static/chunks/app/pricing/page-9db3ebdfa567a7c9.js +1 -0
  680. package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/page-bcf46064ac4474ce.js +1 -0
  681. package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/page-e65a0010da6ea5be.js +1 -0
  682. package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/setup/[provider]/page-4dbe33f0f7691b7c.js +1 -0
  683. package/packages/dashboard/ui-dist/_next/static/chunks/app/providers/setup/[provider]/page-84161c802b020a1f.js +1 -0
  684. package/packages/dashboard/ui-dist/_next/static/chunks/app/signup/page-18a4665665f6be11.js +1 -0
  685. package/packages/dashboard/ui-dist/_next/static/chunks/app/signup/page-1ede2205b58649ca.js +1 -0
  686. package/packages/dashboard/ui-dist/_next/static/chunks/e868780c-48e5f147c90a3a41.js +18 -0
  687. package/packages/dashboard/ui-dist/_next/static/chunks/fd9d1056-609918ca7b6280bb.js +1 -0
  688. package/packages/dashboard/ui-dist/_next/static/chunks/framework-f66176bb897dc684.js +1 -0
  689. package/packages/dashboard/ui-dist/_next/static/chunks/main-5a40a5ae29646e1b.js +1 -0
  690. package/packages/dashboard/ui-dist/_next/static/chunks/main-app-6e8e8d3ef4e0192a.js +1 -0
  691. package/packages/dashboard/ui-dist/_next/static/chunks/main-app-fdbeb09028f57c9f.js +1 -0
  692. package/packages/dashboard/ui-dist/_next/static/chunks/pages/_app-72b849fbd24ac258.js +1 -0
  693. package/packages/dashboard/ui-dist/_next/static/chunks/pages/_error-7ba65e1336b92748.js +1 -0
  694. package/packages/dashboard/ui-dist/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  695. package/packages/dashboard/ui-dist/_next/static/chunks/webpack-1cdd8ed57114d5e1.js +1 -0
  696. package/packages/dashboard/ui-dist/_next/static/css/4034f236dd1a3178.css +1 -0
  697. package/packages/dashboard/ui-dist/_next/static/css/99c2552394077586.css +1 -0
  698. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-128.png +0 -0
  699. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-256.png +0 -0
  700. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-32.png +0 -0
  701. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-512.png +0 -0
  702. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo-64.png +0 -0
  703. package/packages/dashboard/ui-dist/alt-logos/agent-relay-logo.svg +45 -0
  704. package/packages/dashboard/ui-dist/alt-logos/logo.svg +38 -0
  705. package/packages/dashboard/ui-dist/alt-logos/monogram-logo-128.png +0 -0
  706. package/packages/dashboard/ui-dist/alt-logos/monogram-logo-256.png +0 -0
  707. package/packages/dashboard/ui-dist/alt-logos/monogram-logo-32.png +0 -0
  708. package/packages/dashboard/ui-dist/alt-logos/monogram-logo-512.png +0 -0
  709. package/packages/dashboard/ui-dist/alt-logos/monogram-logo-64.png +0 -0
  710. package/packages/dashboard/ui-dist/alt-logos/monogram-logo.svg +38 -0
  711. package/packages/dashboard/ui-dist/app/onboarding.html +1 -0
  712. package/packages/dashboard/ui-dist/app/onboarding.txt +7 -0
  713. package/packages/dashboard/ui-dist/app.html +1 -0
  714. package/packages/dashboard/ui-dist/app.txt +7 -0
  715. package/packages/dashboard/ui-dist/apple-icon.png +0 -0
  716. package/packages/dashboard/ui-dist/cloud/link.html +1 -0
  717. package/packages/dashboard/ui-dist/cloud/link.txt +7 -0
  718. package/packages/dashboard/ui-dist/connect-repos.html +1 -0
  719. package/packages/dashboard/ui-dist/connect-repos.txt +7 -0
  720. package/packages/dashboard/ui-dist/history.html +1 -0
  721. package/packages/dashboard/ui-dist/history.txt +7 -0
  722. package/packages/dashboard/ui-dist/index.html +1 -0
  723. package/packages/dashboard/ui-dist/index.txt +7 -0
  724. package/packages/dashboard/ui-dist/login.html +5 -0
  725. package/packages/dashboard/ui-dist/login.txt +7 -0
  726. package/packages/dashboard/ui-dist/metrics.html +1 -0
  727. package/packages/dashboard/ui-dist/metrics.txt +7 -0
  728. package/packages/dashboard/ui-dist/pricing.html +13 -0
  729. package/packages/dashboard/ui-dist/pricing.txt +7 -0
  730. package/packages/dashboard/ui-dist/providers/setup/claude.html +1 -0
  731. package/packages/dashboard/ui-dist/providers/setup/claude.txt +8 -0
  732. package/packages/dashboard/ui-dist/providers/setup/codex.html +1 -0
  733. package/packages/dashboard/ui-dist/providers/setup/codex.txt +8 -0
  734. package/packages/dashboard/ui-dist/providers/setup/cursor.html +1 -0
  735. package/packages/dashboard/ui-dist/providers/setup/cursor.txt +8 -0
  736. package/packages/dashboard/ui-dist/providers.html +1 -0
  737. package/packages/dashboard/ui-dist/providers.txt +7 -0
  738. package/packages/dashboard/ui-dist/signup.html +6 -0
  739. package/packages/dashboard/ui-dist/signup.txt +7 -0
  740. package/packages/dashboard-server/dist/health-worker-manager.d.ts +62 -0
  741. package/packages/dashboard-server/dist/health-worker-manager.js +144 -0
  742. package/packages/dashboard-server/dist/health-worker.d.ts +9 -0
  743. package/packages/dashboard-server/dist/health-worker.js +79 -0
  744. package/packages/dashboard-server/dist/index.d.ts +18 -0
  745. package/packages/dashboard-server/dist/index.js +17 -0
  746. package/packages/dashboard-server/dist/server.js +5099 -0
  747. package/packages/dashboard-server/dist/start.js +13 -0
  748. package/packages/dashboard-server/dist/types/threading.d.ts +8 -0
  749. package/packages/dashboard-server/dist/types/threading.js +2 -0
  750. package/packages/dashboard-server/dist/user-bridge.d.ts +154 -0
  751. package/packages/dashboard-server/dist/user-bridge.js +372 -0
  752. package/packages/dashboard-server/package.json +49 -0
  753. package/packages/hooks/dist/browser.d.ts +2 -0
  754. package/packages/hooks/dist/browser.js +3 -0
  755. package/packages/hooks/dist/index.d.ts +11 -0
  756. package/packages/hooks/dist/index.js +11 -0
  757. package/packages/hooks/dist/registry.js +476 -0
  758. package/packages/hooks/dist/trajectory-hooks.js +183 -0
  759. package/packages/hooks/dist/types.d.ts +285 -0
  760. package/packages/hooks/dist/types.js +10 -0
  761. package/packages/hooks/package.json +52 -0
  762. package/packages/mcp/LICENSE +190 -0
  763. package/packages/mcp/README.md +214 -0
  764. package/packages/mcp/SPEC.md +1922 -0
  765. package/packages/mcp/STAFFING_PLAN.md +294 -0
  766. package/packages/mcp/dist/bin.d.ts +12 -0
  767. package/packages/mcp/dist/bin.js +127 -0
  768. package/packages/mcp/dist/client.d.ts +68 -0
  769. package/packages/mcp/dist/client.js +115 -0
  770. package/packages/mcp/dist/cloud.d.ts +108 -0
  771. package/packages/mcp/dist/cloud.js +279 -0
  772. package/packages/mcp/dist/errors.d.ts +27 -0
  773. package/packages/mcp/dist/errors.js +48 -0
  774. package/packages/mcp/dist/index.d.ts +10 -0
  775. package/packages/mcp/dist/index.js +16 -0
  776. package/packages/mcp/dist/install-cli.d.ts +35 -0
  777. package/packages/mcp/dist/install-cli.js +157 -0
  778. package/packages/mcp/dist/install.d.ts +101 -0
  779. package/packages/mcp/dist/install.js +398 -0
  780. package/packages/mcp/dist/prompts/index.d.ts +2 -0
  781. package/packages/mcp/dist/prompts/index.js +2 -0
  782. package/packages/mcp/dist/prompts/protocol.d.ts +11 -0
  783. package/packages/mcp/dist/prompts/protocol.js +168 -0
  784. package/packages/mcp/dist/resources/agents.d.ts +11 -0
  785. package/packages/mcp/dist/resources/agents.js +17 -0
  786. package/packages/mcp/dist/resources/inbox.d.ts +11 -0
  787. package/packages/mcp/dist/resources/inbox.js +17 -0
  788. package/packages/mcp/dist/resources/index.d.ts +4 -0
  789. package/packages/mcp/dist/resources/index.js +4 -0
  790. package/packages/mcp/dist/resources/project.d.ts +11 -0
  791. package/packages/mcp/dist/resources/project.js +21 -0
  792. package/packages/mcp/dist/server.d.ts +19 -0
  793. package/packages/mcp/dist/server.js +215 -0
  794. package/packages/mcp/dist/simple.d.ts +173 -0
  795. package/packages/mcp/dist/simple.js +120 -0
  796. package/packages/mcp/dist/tools/index.d.ts +10 -0
  797. package/packages/mcp/dist/tools/index.js +10 -0
  798. package/packages/mcp/dist/tools/relay-health.d.ts +23 -0
  799. package/packages/mcp/dist/tools/relay-health.js +138 -0
  800. package/packages/mcp/dist/tools/relay-inbox.d.ts +26 -0
  801. package/packages/mcp/dist/tools/relay-inbox.js +58 -0
  802. package/packages/mcp/dist/tools/relay-logs.d.ts +20 -0
  803. package/packages/mcp/dist/tools/relay-logs.js +88 -0
  804. package/packages/mcp/dist/tools/relay-metrics.d.ts +20 -0
  805. package/packages/mcp/dist/tools/relay-metrics.js +135 -0
  806. package/packages/mcp/dist/tools/relay-release.d.ts +20 -0
  807. package/packages/mcp/dist/tools/relay-release.js +44 -0
  808. package/packages/mcp/dist/tools/relay-send.d.ts +29 -0
  809. package/packages/mcp/dist/tools/relay-send.js +71 -0
  810. package/packages/mcp/dist/tools/relay-spawn.d.ts +36 -0
  811. package/packages/mcp/dist/tools/relay-spawn.js +73 -0
  812. package/packages/mcp/dist/tools/relay-status.d.ts +11 -0
  813. package/packages/mcp/dist/tools/relay-status.js +43 -0
  814. package/packages/mcp/dist/tools/relay-who.d.ts +20 -0
  815. package/packages/mcp/dist/tools/relay-who.js +47 -0
  816. package/packages/mcp/package.json +69 -0
  817. package/packages/memory/dist/memory-hooks.d.ts +60 -0
  818. package/packages/memory/package.json +35 -0
  819. package/packages/policy/dist/agent-policy.js +665 -0
  820. package/packages/policy/dist/index.d.ts +12 -0
  821. package/packages/policy/dist/index.js +12 -0
  822. package/packages/policy/package.json +35 -0
  823. package/packages/protocol/dist/channels.d.ts +137 -0
  824. package/packages/protocol/dist/channels.js +154 -0
  825. package/packages/protocol/dist/framing.d.ts +80 -0
  826. package/packages/protocol/dist/framing.js +206 -0
  827. package/packages/protocol/dist/index.d.ts +5 -0
  828. package/packages/protocol/dist/index.js +5 -0
  829. package/packages/protocol/dist/relay-pty-schemas.d.ts +258 -0
  830. package/packages/protocol/dist/types.d.ts +341 -0
  831. package/packages/protocol/dist/types.js +8 -0
  832. package/packages/protocol/package.json +56 -0
  833. package/packages/resiliency/dist/memory-monitor.js +599 -0
  834. package/packages/resiliency/dist/provider-context.d.ts +100 -0
  835. package/packages/resiliency/package.json +33 -0
  836. package/packages/sdk/README.md +171 -0
  837. package/packages/sdk/dist/client.d.ts +181 -0
  838. package/packages/sdk/dist/client.js +695 -0
  839. package/packages/sdk/dist/index.d.ts +32 -0
  840. package/packages/sdk/dist/index.js +36 -0
  841. package/packages/sdk/dist/protocol/framing.d.ts +80 -0
  842. package/packages/sdk/dist/protocol/framing.js +206 -0
  843. package/packages/sdk/dist/protocol/index.d.ts +6 -0
  844. package/packages/sdk/dist/protocol/index.js +6 -0
  845. package/packages/sdk/dist/protocol/types.d.ts +341 -0
  846. package/packages/sdk/dist/protocol/types.js +8 -0
  847. package/packages/sdk/dist/standalone.d.ts +87 -0
  848. package/packages/sdk/dist/standalone.js +126 -0
  849. package/packages/sdk/package.json +80 -0
  850. package/packages/spawner/API.md +256 -0
  851. package/packages/spawner/dist/index.d.ts +8 -0
  852. package/packages/spawner/dist/index.js +8 -0
  853. package/packages/spawner/dist/types.d.ts +552 -0
  854. package/packages/spawner/dist/types.js +193 -0
  855. package/packages/spawner/package.json +47 -0
  856. package/packages/state/dist/agent-state.js +120 -0
  857. package/packages/state/dist/index.d.ts +8 -0
  858. package/packages/state/dist/index.js +8 -0
  859. package/packages/state/package.json +32 -0
  860. package/packages/storage/dist/adapter.d.ts +156 -0
  861. package/packages/storage/dist/batched-sqlite-adapter.d.ts +75 -0
  862. package/packages/storage/dist/batched-sqlite-adapter.js +189 -0
  863. package/packages/storage/dist/index.d.ts +5 -0
  864. package/packages/storage/dist/index.js +6 -0
  865. package/packages/storage/dist/sqlite-adapter.d.ts +113 -0
  866. package/packages/storage/dist/sqlite-adapter.js +752 -0
  867. package/packages/storage/package.json +69 -0
  868. package/packages/trajectory/dist/index.d.ts +2 -0
  869. package/packages/trajectory/dist/index.js +2 -0
  870. package/packages/trajectory/dist/integration.js +987 -0
  871. package/packages/trajectory/package.json +35 -0
  872. package/packages/user-directory/dist/index.d.ts +7 -0
  873. package/packages/user-directory/dist/index.js +7 -0
  874. package/packages/user-directory/dist/user-directory.d.ts +121 -0
  875. package/packages/user-directory/dist/user-directory.js +267 -0
  876. package/packages/user-directory/package.json +35 -0
  877. package/packages/utils/dist/command-resolver.js +80 -0
  878. package/packages/utils/dist/error-tracking.d.ts +103 -0
  879. package/packages/utils/dist/error-tracking.js +149 -0
  880. package/packages/utils/dist/index.d.ts +9 -0
  881. package/packages/utils/dist/index.js +9 -0
  882. package/packages/utils/dist/model-mapping.d.ts +28 -0
  883. package/packages/utils/dist/model-mapping.js +55 -0
  884. package/packages/utils/package.json +75 -0
  885. package/packages/wrapper/dist/__fixtures__/claude-outputs.d.ts +49 -0
  886. package/packages/wrapper/dist/__fixtures__/claude-outputs.js +443 -0
  887. package/packages/wrapper/dist/__fixtures__/codex-outputs.d.ts +9 -0
  888. package/packages/wrapper/dist/__fixtures__/codex-outputs.js +94 -0
  889. package/packages/wrapper/dist/__fixtures__/gemini-outputs.d.ts +19 -0
  890. package/packages/wrapper/dist/__fixtures__/gemini-outputs.js +144 -0
  891. package/packages/wrapper/dist/__fixtures__/index.d.ts +68 -0
  892. package/packages/wrapper/dist/__fixtures__/index.js +44 -0
  893. package/packages/wrapper/dist/base-wrapper.d.ts +225 -0
  894. package/packages/wrapper/dist/base-wrapper.js +572 -0
  895. package/packages/wrapper/dist/client.d.ts +254 -0
  896. package/packages/wrapper/dist/client.js +801 -0
  897. package/packages/wrapper/dist/id-generator.d.ts +35 -0
  898. package/packages/wrapper/dist/id-generator.js +60 -0
  899. package/packages/wrapper/dist/idle-detector.d.ts +110 -0
  900. package/packages/wrapper/dist/idle-detector.js +304 -0
  901. package/packages/wrapper/dist/index.d.ts +37 -0
  902. package/packages/wrapper/dist/index.js +47 -0
  903. package/packages/wrapper/dist/parser.d.ts +236 -0
  904. package/packages/wrapper/dist/parser.js +1238 -0
  905. package/packages/wrapper/dist/relay-pty-orchestrator.d.ts +407 -0
  906. package/packages/wrapper/dist/relay-pty-orchestrator.js +1885 -0
  907. package/packages/wrapper/dist/shared.d.ts +201 -0
  908. package/packages/wrapper/dist/shared.js +341 -0
  909. package/packages/wrapper/dist/stuck-detector.d.ts +161 -0
  910. package/packages/wrapper/dist/stuck-detector.js +402 -0
  911. package/packages/wrapper/dist/tmux-wrapper.d.ts +345 -0
  912. package/packages/wrapper/dist/tmux-wrapper.js +1747 -0
  913. package/packages/wrapper/dist/trajectory-integration.d.ts +292 -0
  914. package/packages/wrapper/dist/trajectory-integration.js +979 -0
  915. package/packages/wrapper/dist/wrapper-types.d.ts +41 -0
  916. package/packages/wrapper/dist/wrapper-types.js +7 -0
  917. package/packages/wrapper/package.json +63 -0
  918. package/scripts/setup-stripe-products.ts +312 -0
  919. package/scripts/stress-test-orchestrator-integration.mts +1366 -0
  920. package/scripts/stress-test-orchestrator.mjs +584 -0
  921. package/scripts/stress-test-relay-pty.sh +452 -0
  922. package/scripts/verify-schema.js +1 -1
  923. package/turbo.json +37 -0
  924. package/dist/bridge/config.d.ts +0 -41
  925. package/dist/bridge/config.js +0 -143
  926. package/dist/bridge/index.d.ts +0 -10
  927. package/dist/bridge/index.js +0 -10
  928. package/dist/bridge/multi-project-client.d.ts +0 -99
  929. package/dist/bridge/multi-project-client.js +0 -389
  930. package/dist/bridge/shadow-cli.js +0 -75
  931. package/dist/bridge/shadow-config.d.ts +0 -87
  932. package/dist/bridge/spawner.d.ts +0 -186
  933. package/dist/bridge/spawner.js +0 -920
  934. package/dist/bridge/types.d.ts +0 -129
  935. package/dist/bridge/utils.d.ts +0 -30
  936. package/dist/bridge/utils.js +0 -54
  937. package/dist/cli/index.js +0 -2784
  938. package/dist/cloud/api/admin.js +0 -225
  939. package/dist/cloud/api/billing.js +0 -564
  940. package/dist/cloud/api/cli-pty-runner.d.ts +0 -54
  941. package/dist/cloud/api/cli-pty-runner.js +0 -119
  942. package/dist/cloud/api/codex-auth-helper.js +0 -327
  943. package/dist/cloud/api/consensus.js +0 -259
  944. package/dist/cloud/api/coordinators.js +0 -749
  945. package/dist/cloud/api/daemons.js +0 -535
  946. package/dist/cloud/api/generic-webhooks.js +0 -129
  947. package/dist/cloud/api/github-app.js +0 -223
  948. package/dist/cloud/api/monitoring.js +0 -578
  949. package/dist/cloud/api/nango-auth.js +0 -658
  950. package/dist/cloud/api/onboarding.d.ts +0 -15
  951. package/dist/cloud/api/onboarding.js +0 -666
  952. package/dist/cloud/api/policy.js +0 -229
  953. package/dist/cloud/api/provider-env.d.ts +0 -5
  954. package/dist/cloud/api/provider-env.js +0 -27
  955. package/dist/cloud/api/providers.js +0 -511
  956. package/dist/cloud/api/repos.js +0 -576
  957. package/dist/cloud/api/teams.js +0 -279
  958. package/dist/cloud/api/test-helpers.js +0 -745
  959. package/dist/cloud/api/workspaces.js +0 -1783
  960. package/dist/cloud/billing/plans.js +0 -245
  961. package/dist/cloud/config.d.ts +0 -75
  962. package/dist/cloud/config.js +0 -109
  963. package/dist/cloud/db/drizzle.d.ts +0 -246
  964. package/dist/cloud/db/drizzle.js +0 -1249
  965. package/dist/cloud/db/schema.d.ts +0 -4854
  966. package/dist/cloud/db/schema.js +0 -610
  967. package/dist/cloud/index.d.ts +0 -11
  968. package/dist/cloud/index.js +0 -38
  969. package/dist/cloud/provisioner/index.d.ts +0 -207
  970. package/dist/cloud/provisioner/index.js +0 -2069
  971. package/dist/cloud/server.js +0 -1599
  972. package/dist/cloud/services/index.d.ts +0 -17
  973. package/dist/cloud/services/index.js +0 -25
  974. package/dist/cloud/services/intro-expiration.d.ts +0 -55
  975. package/dist/cloud/services/intro-expiration.js +0 -211
  976. package/dist/cloud/services/nango.d.ts +0 -199
  977. package/dist/cloud/services/nango.js +0 -382
  978. package/dist/cloud/services/persistence.d.ts +0 -131
  979. package/dist/config/relay-config.d.ts +0 -23
  980. package/dist/config/relay-config.js +0 -23
  981. package/dist/continuity/index.d.ts +0 -45
  982. package/dist/continuity/index.js +0 -48
  983. package/dist/continuity/types.d.ts +0 -180
  984. package/dist/continuity/types.js +0 -9
  985. package/dist/daemon/agent-manager.d.ts +0 -134
  986. package/dist/daemon/agent-manager.js +0 -564
  987. package/dist/daemon/agent-registry.js +0 -213
  988. package/dist/daemon/api.d.ts +0 -83
  989. package/dist/daemon/api.js +0 -780
  990. package/dist/daemon/channel-membership-store.d.ts +0 -48
  991. package/dist/daemon/channel-membership-store.js +0 -149
  992. package/dist/daemon/cli-auth.d.ts +0 -82
  993. package/dist/daemon/cli-auth.js +0 -700
  994. package/dist/daemon/cloud-sync.d.ts +0 -150
  995. package/dist/daemon/cloud-sync.js +0 -424
  996. package/dist/daemon/connection.d.ts +0 -130
  997. package/dist/daemon/connection.js +0 -438
  998. package/dist/daemon/consensus-integration.js +0 -371
  999. package/dist/daemon/delivery-tracker.d.ts +0 -34
  1000. package/dist/daemon/delivery-tracker.js +0 -104
  1001. package/dist/daemon/enhanced-features.d.ts +0 -118
  1002. package/dist/daemon/enhanced-features.js +0 -178
  1003. package/dist/daemon/index.d.ts +0 -14
  1004. package/dist/daemon/index.js +0 -17
  1005. package/dist/daemon/orchestrator.d.ts +0 -157
  1006. package/dist/daemon/orchestrator.js +0 -792
  1007. package/dist/daemon/repo-manager.js +0 -384
  1008. package/dist/daemon/router.d.ts +0 -358
  1009. package/dist/daemon/router.js +0 -1333
  1010. package/dist/daemon/server.d.ts +0 -159
  1011. package/dist/daemon/server.js +0 -788
  1012. package/dist/daemon/services/browser-testing.d.ts +0 -88
  1013. package/dist/daemon/services/browser-testing.js +0 -244
  1014. package/dist/daemon/services/container-spawner.d.ts +0 -135
  1015. package/dist/daemon/services/container-spawner.js +0 -313
  1016. package/dist/daemon/sync-queue.d.ts +0 -116
  1017. package/dist/daemon/sync-queue.js +0 -361
  1018. package/dist/daemon/types.d.ts +0 -131
  1019. package/dist/daemon/user-directory.d.ts +0 -111
  1020. package/dist/daemon/user-directory.js +0 -233
  1021. package/dist/daemon/workspace-manager.js +0 -314
  1022. package/dist/dashboard/out/_next/static/chunks/116-eacf84a131b80db9.js +0 -1
  1023. package/dist/dashboard/out/_next/static/chunks/64-f4268c2ac6f4d7d4.js +0 -1
  1024. package/dist/dashboard/out/_next/static/chunks/766-aa7c8c9900ff5f53.js +0 -1
  1025. package/dist/dashboard/out/_next/static/chunks/891-a024fbe4b619cf6f.js +0 -1
  1026. package/dist/dashboard/out/_next/static/chunks/app/app/page-ffad986adfcc8b31.js +0 -1
  1027. package/dist/dashboard/out/_next/static/chunks/app/page-671037943b2f2e43.js +0 -1
  1028. package/dist/dashboard/out/_next/static/chunks/app/providers/page-57cbd738c6a73859.js +0 -1
  1029. package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-5ab0854472b402b0.js +0 -1
  1030. package/dist/dashboard/out/_next/static/css/8f9ed310f454e5a5.css +0 -1
  1031. package/dist/dashboard-server/server.js +0 -4806
  1032. package/dist/dashboard-server/start.js +0 -13
  1033. package/dist/dashboard-server/user-bridge.d.ts +0 -138
  1034. package/dist/dashboard-server/user-bridge.js +0 -348
  1035. package/dist/hooks/index.d.ts +0 -10
  1036. package/dist/hooks/index.js +0 -10
  1037. package/dist/hooks/registry.js +0 -476
  1038. package/dist/hooks/trajectory-hooks.js +0 -183
  1039. package/dist/hooks/types.d.ts +0 -284
  1040. package/dist/hooks/types.js +0 -8
  1041. package/dist/index.d.ts +0 -13
  1042. package/dist/index.js +0 -16
  1043. package/dist/memory/memory-hooks.d.ts +0 -60
  1044. package/dist/policy/agent-policy.js +0 -665
  1045. package/dist/protocol/channels.d.ts +0 -211
  1046. package/dist/protocol/channels.js +0 -154
  1047. package/dist/protocol/framing.d.ts +0 -94
  1048. package/dist/protocol/framing.js +0 -240
  1049. package/dist/protocol/index.d.ts +0 -4
  1050. package/dist/protocol/index.js +0 -4
  1051. package/dist/protocol/relay-pty-schemas.d.ts +0 -209
  1052. package/dist/protocol/types.d.ts +0 -168
  1053. package/dist/protocol/types.js +0 -6
  1054. package/dist/resiliency/memory-monitor.js +0 -593
  1055. package/dist/resiliency/provider-context.d.ts +0 -100
  1056. package/dist/shared/cli-auth-config.js +0 -320
  1057. package/dist/state/agent-state.js +0 -120
  1058. package/dist/storage/adapter.d.ts +0 -154
  1059. package/dist/storage/batched-sqlite-adapter.d.ts +0 -71
  1060. package/dist/storage/batched-sqlite-adapter.js +0 -183
  1061. package/dist/storage/sqlite-adapter.d.ts +0 -107
  1062. package/dist/storage/sqlite-adapter.js +0 -717
  1063. package/dist/trajectory/config.d.ts +0 -102
  1064. package/dist/trajectory/config.js +0 -185
  1065. package/dist/trajectory/index.d.ts +0 -8
  1066. package/dist/trajectory/index.js +0 -8
  1067. package/dist/trajectory/integration.js +0 -987
  1068. package/dist/utils/command-resolver.js +0 -76
  1069. package/dist/utils/index.d.ts +0 -4
  1070. package/dist/utils/index.js +0 -4
  1071. package/dist/utils/project-namespace.d.ts +0 -70
  1072. package/dist/utils/project-namespace.js +0 -216
  1073. package/dist/wrapper/base-wrapper.d.ts +0 -217
  1074. package/dist/wrapper/base-wrapper.js +0 -538
  1075. package/dist/wrapper/client.d.ts +0 -199
  1076. package/dist/wrapper/client.js +0 -677
  1077. package/dist/wrapper/idle-detector.d.ts +0 -102
  1078. package/dist/wrapper/idle-detector.js +0 -279
  1079. package/dist/wrapper/index.d.ts +0 -4
  1080. package/dist/wrapper/index.js +0 -7
  1081. package/dist/wrapper/parser.d.ts +0 -230
  1082. package/dist/wrapper/parser.js +0 -1178
  1083. package/dist/wrapper/pty-wrapper.d.ts +0 -343
  1084. package/dist/wrapper/pty-wrapper.js +0 -1593
  1085. package/dist/wrapper/relay-pty-orchestrator.d.ts +0 -296
  1086. package/dist/wrapper/relay-pty-orchestrator.js +0 -1088
  1087. package/dist/wrapper/shared.d.ts +0 -168
  1088. package/dist/wrapper/shared.js +0 -291
  1089. package/dist/wrapper/stuck-detector.d.ts +0 -101
  1090. package/dist/wrapper/stuck-detector.js +0 -228
  1091. package/dist/wrapper/tmux-wrapper.d.ts +0 -344
  1092. package/dist/wrapper/tmux-wrapper.js +0 -1711
  1093. /package/dist/dashboard/out/_next/static/{BffXAqxm-_rUlj2mAnK26 → ZCFjHbkF8yDKS2md3lVgb}/_buildManifest.js +0 -0
  1094. /package/dist/dashboard/out/_next/static/{BffXAqxm-_rUlj2mAnK26 → ZCFjHbkF8yDKS2md3lVgb}/_ssgManifest.js +0 -0
  1095. /package/dist/dashboard/out/_next/static/chunks/app/cloud/link/{page-cfeb437f08a12ed9.js → page-5011ae044b90449d.js} +0 -0
  1096. /package/dist/dashboard/out/_next/static/chunks/app/history/{page-240f91e8b06ba8ac.js → page-b2ce7c96ed0931da.js} +0 -0
  1097. /package/dist/dashboard/out/_next/static/chunks/app/metrics/{page-82938ab8fcf44694.js → page-bf2cb1e5915bc92d.js} +0 -0
  1098. /package/dist/{cli → src/cli}/index.d.ts +0 -0
  1099. /package/dist/{health-worker-manager.d.ts → src/health-worker-manager.d.ts} +0 -0
  1100. /package/dist/{health-worker-manager.js → src/health-worker-manager.js} +0 -0
  1101. /package/dist/{health-worker.d.ts → src/health-worker.d.ts} +0 -0
  1102. /package/dist/{health-worker.js → src/health-worker.js} +0 -0
  1103. /package/{dist/bridge → packages/bridge/dist}/shadow-cli.d.ts +0 -0
  1104. /package/{dist/bridge → packages/bridge/dist}/types.js +0 -0
  1105. /package/{dist/cloud → packages/cloud/dist}/api/admin.d.ts +0 -0
  1106. /package/{dist/cloud → packages/cloud/dist}/api/auth.d.ts +0 -0
  1107. /package/{dist/cloud → packages/cloud/dist}/api/auth.js +0 -0
  1108. /package/{dist/cloud → packages/cloud/dist}/api/billing.d.ts +0 -0
  1109. /package/{dist/cloud → packages/cloud/dist}/api/codex-auth-helper.d.ts +0 -0
  1110. /package/{dist/cloud → packages/cloud/dist}/api/consensus.d.ts +0 -0
  1111. /package/{dist/cloud → packages/cloud/dist}/api/coordinators.d.ts +0 -0
  1112. /package/{dist/cloud → packages/cloud/dist}/api/daemons.d.ts +0 -0
  1113. /package/{dist/cloud → packages/cloud/dist}/api/generic-webhooks.d.ts +0 -0
  1114. /package/{dist/cloud → packages/cloud/dist}/api/git.d.ts +0 -0
  1115. /package/{dist/cloud → packages/cloud/dist}/api/git.js +0 -0
  1116. /package/{dist/cloud → packages/cloud/dist}/api/github-app.d.ts +0 -0
  1117. /package/{dist/cloud → packages/cloud/dist}/api/middleware/planLimits.d.ts +0 -0
  1118. /package/{dist/cloud → packages/cloud/dist}/api/middleware/planLimits.js +0 -0
  1119. /package/{dist/cloud → packages/cloud/dist}/api/monitoring.d.ts +0 -0
  1120. /package/{dist/cloud → packages/cloud/dist}/api/nango-auth.d.ts +0 -0
  1121. /package/{dist/cloud → packages/cloud/dist}/api/policy.d.ts +0 -0
  1122. /package/{dist/cloud → packages/cloud/dist}/api/providers.d.ts +0 -0
  1123. /package/{dist/cloud → packages/cloud/dist}/api/repos.d.ts +0 -0
  1124. /package/{dist/cloud → packages/cloud/dist}/api/teams.d.ts +0 -0
  1125. /package/{dist/cloud → packages/cloud/dist}/api/test-helpers.d.ts +0 -0
  1126. /package/{dist/cloud → packages/cloud/dist}/api/usage.d.ts +0 -0
  1127. /package/{dist/cloud → packages/cloud/dist}/api/usage.js +0 -0
  1128. /package/{dist/cloud → packages/cloud/dist}/api/webhooks.d.ts +0 -0
  1129. /package/{dist/cloud → packages/cloud/dist}/api/webhooks.js +0 -0
  1130. /package/{dist/cloud → packages/cloud/dist}/api/workspaces.d.ts +0 -0
  1131. /package/{dist/cloud → packages/cloud/dist}/billing/index.d.ts +0 -0
  1132. /package/{dist/cloud → packages/cloud/dist}/billing/index.js +0 -0
  1133. /package/{dist/cloud → packages/cloud/dist}/billing/plans.d.ts +0 -0
  1134. /package/{dist/cloud → packages/cloud/dist}/billing/service.d.ts +0 -0
  1135. /package/{dist/cloud → packages/cloud/dist}/billing/service.js +0 -0
  1136. /package/{dist/cloud → packages/cloud/dist}/billing/types.d.ts +0 -0
  1137. /package/{dist/cloud → packages/cloud/dist}/billing/types.js +0 -0
  1138. /package/{dist/cloud → packages/cloud/dist}/db/bulk-ingest.d.ts +0 -0
  1139. /package/{dist/cloud → packages/cloud/dist}/db/bulk-ingest.js +0 -0
  1140. /package/{dist/cloud → packages/cloud/dist}/db/index.d.ts +0 -0
  1141. /package/{dist/cloud → packages/cloud/dist}/db/index.js +0 -0
  1142. /package/{dist/cloud → packages/cloud/dist}/server.d.ts +0 -0
  1143. /package/{dist/cloud → packages/cloud/dist}/services/auto-scaler.d.ts +0 -0
  1144. /package/{dist/cloud → packages/cloud/dist}/services/auto-scaler.js +0 -0
  1145. /package/{dist/cloud → packages/cloud/dist}/services/capacity-manager.d.ts +0 -0
  1146. /package/{dist/cloud → packages/cloud/dist}/services/capacity-manager.js +0 -0
  1147. /package/{dist/cloud → packages/cloud/dist}/services/ci-agent-spawner.d.ts +0 -0
  1148. /package/{dist/cloud → packages/cloud/dist}/services/ci-agent-spawner.js +0 -0
  1149. /package/{dist/cloud → packages/cloud/dist}/services/cloud-message-bus.d.ts +0 -0
  1150. /package/{dist/cloud → packages/cloud/dist}/services/cloud-message-bus.js +0 -0
  1151. /package/{dist/cloud → packages/cloud/dist}/services/compute-enforcement.d.ts +0 -0
  1152. /package/{dist/cloud → packages/cloud/dist}/services/compute-enforcement.js +0 -0
  1153. /package/{dist/cloud → packages/cloud/dist}/services/coordinator.d.ts +0 -0
  1154. /package/{dist/cloud → packages/cloud/dist}/services/coordinator.js +0 -0
  1155. /package/{dist/cloud → packages/cloud/dist}/services/mention-handler.d.ts +0 -0
  1156. /package/{dist/cloud → packages/cloud/dist}/services/mention-handler.js +0 -0
  1157. /package/{dist/cloud → packages/cloud/dist}/services/persistence.js +0 -0
  1158. /package/{dist/cloud → packages/cloud/dist}/services/planLimits.d.ts +0 -0
  1159. /package/{dist/cloud → packages/cloud/dist}/services/planLimits.js +0 -0
  1160. /package/{dist/cloud → packages/cloud/dist}/services/presence-registry.d.ts +0 -0
  1161. /package/{dist/cloud → packages/cloud/dist}/services/presence-registry.js +0 -0
  1162. /package/{dist/cloud → packages/cloud/dist}/services/scaling-orchestrator.d.ts +0 -0
  1163. /package/{dist/cloud → packages/cloud/dist}/services/scaling-orchestrator.js +0 -0
  1164. /package/{dist/cloud → packages/cloud/dist}/services/scaling-policy.d.ts +0 -0
  1165. /package/{dist/cloud → packages/cloud/dist}/services/scaling-policy.js +0 -0
  1166. /package/{dist/cloud → packages/cloud/dist}/services/ssh-security.d.ts +0 -0
  1167. /package/{dist/cloud → packages/cloud/dist}/services/ssh-security.js +0 -0
  1168. /package/{dist/cloud → packages/cloud/dist}/services/workspace-keepalive.d.ts +0 -0
  1169. /package/{dist/cloud → packages/cloud/dist}/services/workspace-keepalive.js +0 -0
  1170. /package/{dist/cloud → packages/cloud/dist}/webhooks/index.d.ts +0 -0
  1171. /package/{dist/cloud → packages/cloud/dist}/webhooks/index.js +0 -0
  1172. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/github.d.ts +0 -0
  1173. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/github.js +0 -0
  1174. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/index.d.ts +0 -0
  1175. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/index.js +0 -0
  1176. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/linear.d.ts +0 -0
  1177. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/linear.js +0 -0
  1178. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/slack.d.ts +0 -0
  1179. /package/{dist/cloud → packages/cloud/dist}/webhooks/parsers/slack.js +0 -0
  1180. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/github.d.ts +0 -0
  1181. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/github.js +0 -0
  1182. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/index.d.ts +0 -0
  1183. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/index.js +0 -0
  1184. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/linear.d.ts +0 -0
  1185. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/linear.js +0 -0
  1186. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/slack.d.ts +0 -0
  1187. /package/{dist/cloud → packages/cloud/dist}/webhooks/responders/slack.js +0 -0
  1188. /package/{dist/cloud → packages/cloud/dist}/webhooks/router.d.ts +0 -0
  1189. /package/{dist/cloud → packages/cloud/dist}/webhooks/router.js +0 -0
  1190. /package/{dist/cloud → packages/cloud/dist}/webhooks/rules-engine.d.ts +0 -0
  1191. /package/{dist/cloud → packages/cloud/dist}/webhooks/rules-engine.js +0 -0
  1192. /package/{dist/cloud → packages/cloud/dist}/webhooks/types.d.ts +0 -0
  1193. /package/{dist/cloud → packages/cloud/dist}/webhooks/types.js +0 -0
  1194. /package/{dist/utils → packages/config/dist}/agent-config.d.ts +0 -0
  1195. /package/{dist/utils → packages/config/dist}/agent-config.js +0 -0
  1196. /package/{dist/shared → packages/config/dist}/cli-auth-config.d.ts +0 -0
  1197. /package/{dist/bridge → packages/config/dist}/shadow-config.js +0 -0
  1198. /package/{dist/bridge → packages/config/dist}/teams-config.d.ts +0 -0
  1199. /package/{dist/bridge → packages/config/dist}/teams-config.js +0 -0
  1200. /package/{dist/continuity → packages/continuity/dist}/formatter.d.ts +0 -0
  1201. /package/{dist/continuity → packages/continuity/dist}/formatter.js +0 -0
  1202. /package/{dist/continuity → packages/continuity/dist}/handoff-store.d.ts +0 -0
  1203. /package/{dist/continuity → packages/continuity/dist}/handoff-store.js +0 -0
  1204. /package/{dist/continuity → packages/continuity/dist}/ledger-store.d.ts +0 -0
  1205. /package/{dist/continuity → packages/continuity/dist}/ledger-store.js +0 -0
  1206. /package/{dist/continuity → packages/continuity/dist}/manager.d.ts +0 -0
  1207. /package/{dist/continuity → packages/continuity/dist}/manager.js +0 -0
  1208. /package/{dist/continuity → packages/continuity/dist}/parser.d.ts +0 -0
  1209. /package/{dist/continuity → packages/continuity/dist}/parser.js +0 -0
  1210. /package/{dist/daemon → packages/daemon/dist}/agent-registry.d.ts +0 -0
  1211. /package/{dist/daemon → packages/daemon/dist}/agent-signing.d.ts +0 -0
  1212. /package/{dist/daemon → packages/daemon/dist}/agent-signing.js +0 -0
  1213. /package/{dist/daemon → packages/daemon/dist}/auth.d.ts +0 -0
  1214. /package/{dist/daemon → packages/daemon/dist}/auth.js +0 -0
  1215. /package/{dist/daemon → packages/daemon/dist}/consensus-integration.d.ts +0 -0
  1216. /package/{dist/daemon → packages/daemon/dist}/consensus.d.ts +0 -0
  1217. /package/{dist/daemon → packages/daemon/dist}/consensus.js +0 -0
  1218. /package/{dist/daemon → packages/daemon/dist}/rate-limiter.d.ts +0 -0
  1219. /package/{dist/daemon → packages/daemon/dist}/rate-limiter.js +0 -0
  1220. /package/{dist/daemon → packages/daemon/dist}/registry.d.ts +0 -0
  1221. /package/{dist/daemon → packages/daemon/dist}/registry.js +0 -0
  1222. /package/{dist/daemon → packages/daemon/dist}/repo-manager.d.ts +0 -0
  1223. /package/{dist/daemon → packages/daemon/dist}/types.js +0 -0
  1224. /package/{dist/daemon → packages/daemon/dist}/workspace-manager.d.ts +0 -0
  1225. /package/{dist/dashboard-server → packages/dashboard-server/dist}/metrics.d.ts +0 -0
  1226. /package/{dist/dashboard-server → packages/dashboard-server/dist}/metrics.js +0 -0
  1227. /package/{dist/dashboard-server → packages/dashboard-server/dist}/needs-attention.d.ts +0 -0
  1228. /package/{dist/dashboard-server → packages/dashboard-server/dist}/needs-attention.js +0 -0
  1229. /package/{dist/dashboard-server → packages/dashboard-server/dist}/server.d.ts +0 -0
  1230. /package/{dist/dashboard-server → packages/dashboard-server/dist}/start.d.ts +0 -0
  1231. /package/{dist/hooks → packages/hooks/dist}/emitter.d.ts +0 -0
  1232. /package/{dist/hooks → packages/hooks/dist}/emitter.js +0 -0
  1233. /package/{dist/hooks → packages/hooks/dist}/inbox-check/hook.d.ts +0 -0
  1234. /package/{dist/hooks → packages/hooks/dist}/inbox-check/hook.js +0 -0
  1235. /package/{dist/hooks → packages/hooks/dist}/inbox-check/index.d.ts +0 -0
  1236. /package/{dist/hooks → packages/hooks/dist}/inbox-check/index.js +0 -0
  1237. /package/{dist/hooks → packages/hooks/dist}/inbox-check/types.d.ts +0 -0
  1238. /package/{dist/hooks → packages/hooks/dist}/inbox-check/types.js +0 -0
  1239. /package/{dist/hooks → packages/hooks/dist}/inbox-check/utils.d.ts +0 -0
  1240. /package/{dist/hooks → packages/hooks/dist}/inbox-check/utils.js +0 -0
  1241. /package/{dist/hooks → packages/hooks/dist}/registry.d.ts +0 -0
  1242. /package/{dist/hooks → packages/hooks/dist}/trajectory-hooks.d.ts +0 -0
  1243. /package/{dist/memory → packages/memory/dist}/adapters/index.d.ts +0 -0
  1244. /package/{dist/memory → packages/memory/dist}/adapters/index.js +0 -0
  1245. /package/{dist/memory → packages/memory/dist}/adapters/inmemory.d.ts +0 -0
  1246. /package/{dist/memory → packages/memory/dist}/adapters/inmemory.js +0 -0
  1247. /package/{dist/memory → packages/memory/dist}/adapters/supermemory.d.ts +0 -0
  1248. /package/{dist/memory → packages/memory/dist}/adapters/supermemory.js +0 -0
  1249. /package/{dist/memory → packages/memory/dist}/context-compaction.d.ts +0 -0
  1250. /package/{dist/memory → packages/memory/dist}/context-compaction.js +0 -0
  1251. /package/{dist/memory → packages/memory/dist}/factory.d.ts +0 -0
  1252. /package/{dist/memory → packages/memory/dist}/factory.js +0 -0
  1253. /package/{dist/memory → packages/memory/dist}/index.d.ts +0 -0
  1254. /package/{dist/memory → packages/memory/dist}/index.js +0 -0
  1255. /package/{dist/memory → packages/memory/dist}/memory-hooks.js +0 -0
  1256. /package/{dist/memory → packages/memory/dist}/service.d.ts +0 -0
  1257. /package/{dist/memory → packages/memory/dist}/service.js +0 -0
  1258. /package/{dist/memory → packages/memory/dist}/types.d.ts +0 -0
  1259. /package/{dist/memory → packages/memory/dist}/types.js +0 -0
  1260. /package/{dist/policy → packages/policy/dist}/agent-policy.d.ts +0 -0
  1261. /package/{dist/policy → packages/policy/dist}/cloud-policy-fetcher.d.ts +0 -0
  1262. /package/{dist/policy → packages/policy/dist}/cloud-policy-fetcher.js +0 -0
  1263. /package/{dist/utils → packages/protocol/dist}/id-generator.d.ts +0 -0
  1264. /package/{dist/utils → packages/protocol/dist}/id-generator.js +0 -0
  1265. /package/{dist/protocol → packages/protocol/dist}/relay-pty-schemas.js +0 -0
  1266. /package/{dist/resiliency → packages/resiliency/dist}/context-persistence.d.ts +0 -0
  1267. /package/{dist/resiliency → packages/resiliency/dist}/context-persistence.js +0 -0
  1268. /package/{dist/resiliency → packages/resiliency/dist}/crash-insights.d.ts +0 -0
  1269. /package/{dist/resiliency → packages/resiliency/dist}/crash-insights.js +0 -0
  1270. /package/{dist/resiliency → packages/resiliency/dist}/gossip-health.d.ts +0 -0
  1271. /package/{dist/resiliency → packages/resiliency/dist}/gossip-health.js +0 -0
  1272. /package/{dist/resiliency → packages/resiliency/dist}/health-monitor.d.ts +0 -0
  1273. /package/{dist/resiliency → packages/resiliency/dist}/health-monitor.js +0 -0
  1274. /package/{dist/resiliency → packages/resiliency/dist}/index.d.ts +0 -0
  1275. /package/{dist/resiliency → packages/resiliency/dist}/index.js +0 -0
  1276. /package/{dist/resiliency → packages/resiliency/dist}/leader-watchdog.d.ts +0 -0
  1277. /package/{dist/resiliency → packages/resiliency/dist}/leader-watchdog.js +0 -0
  1278. /package/{dist/resiliency → packages/resiliency/dist}/logger.d.ts +0 -0
  1279. /package/{dist/resiliency → packages/resiliency/dist}/logger.js +0 -0
  1280. /package/{dist/resiliency → packages/resiliency/dist}/memory-monitor.d.ts +0 -0
  1281. /package/{dist/resiliency → packages/resiliency/dist}/metrics.d.ts +0 -0
  1282. /package/{dist/resiliency → packages/resiliency/dist}/metrics.js +0 -0
  1283. /package/{dist/resiliency → packages/resiliency/dist}/provider-context.js +0 -0
  1284. /package/{dist/resiliency → packages/resiliency/dist}/stateless-lead.d.ts +0 -0
  1285. /package/{dist/resiliency → packages/resiliency/dist}/stateless-lead.js +0 -0
  1286. /package/{dist/resiliency → packages/resiliency/dist}/supervisor.d.ts +0 -0
  1287. /package/{dist/resiliency → packages/resiliency/dist}/supervisor.js +0 -0
  1288. /package/{dist/state → packages/state/dist}/agent-state.d.ts +0 -0
  1289. /package/{dist/storage → packages/storage/dist}/adapter.js +0 -0
  1290. /package/{dist/storage → packages/storage/dist}/dead-letter-queue.d.ts +0 -0
  1291. /package/{dist/storage → packages/storage/dist}/dead-letter-queue.js +0 -0
  1292. /package/{dist/storage → packages/storage/dist}/dlq-adapter.d.ts +0 -0
  1293. /package/{dist/storage → packages/storage/dist}/dlq-adapter.js +0 -0
  1294. /package/{dist/trajectory → packages/trajectory/dist}/integration.d.ts +0 -0
  1295. /package/{dist/utils → packages/utils/dist}/command-resolver.d.ts +0 -0
  1296. /package/{dist/utils → packages/utils/dist}/git-remote.d.ts +0 -0
  1297. /package/{dist/utils → packages/utils/dist}/git-remote.js +0 -0
  1298. /package/{dist/utils → packages/utils/dist}/logger.d.ts +0 -0
  1299. /package/{dist/utils → packages/utils/dist}/logger.js +0 -0
  1300. /package/{dist/utils → packages/utils/dist}/name-generator.d.ts +0 -0
  1301. /package/{dist/utils → packages/utils/dist}/name-generator.js +0 -0
  1302. /package/{dist/utils → packages/utils/dist}/precompiled-patterns.d.ts +0 -0
  1303. /package/{dist/utils → packages/utils/dist}/precompiled-patterns.js +0 -0
  1304. /package/{dist/utils → packages/utils/dist}/update-checker.d.ts +0 -0
  1305. /package/{dist/utils → packages/utils/dist}/update-checker.js +0 -0
  1306. /package/{dist/wrapper → packages/wrapper/dist}/auth-detection.d.ts +0 -0
  1307. /package/{dist/wrapper → packages/wrapper/dist}/auth-detection.js +0 -0
  1308. /package/{dist/wrapper → packages/wrapper/dist}/inbox.d.ts +0 -0
  1309. /package/{dist/wrapper → packages/wrapper/dist}/inbox.js +0 -0
  1310. /package/{dist/wrapper → packages/wrapper/dist}/prompt-composer.d.ts +0 -0
  1311. /package/{dist/wrapper → packages/wrapper/dist}/prompt-composer.js +0 -0
  1312. /package/{dist/utils → packages/wrapper/dist}/tmux-resolver.d.ts +0 -0
  1313. /package/{dist/utils → packages/wrapper/dist}/tmux-resolver.js +0 -0
@@ -1,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