agent-relay 1.1.0 → 1.2.3

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 (567) hide show
  1. package/.gitattributes +3 -0
  2. package/.nvmrc +1 -0
  3. package/.trajectories/completed/2026-01/traj_1dviorhnkcb5.json +65 -0
  4. package/.trajectories/completed/2026-01/traj_1dviorhnkcb5.md +37 -0
  5. package/.trajectories/completed/2026-01/traj_1k5if5snst2e.json +65 -0
  6. package/.trajectories/completed/2026-01/traj_1k5if5snst2e.md +37 -0
  7. package/.trajectories/completed/2026-01/traj_1rp3rges5811.json +49 -0
  8. package/.trajectories/completed/2026-01/traj_1rp3rges5811.md +31 -0
  9. package/.trajectories/completed/2026-01/traj_22bhyulruouw.json +113 -0
  10. package/.trajectories/completed/2026-01/traj_22bhyulruouw.md +57 -0
  11. package/.trajectories/completed/2026-01/traj_2dao7ddgnta0.json +53 -0
  12. package/.trajectories/completed/2026-01/traj_2dao7ddgnta0.md +32 -0
  13. package/.trajectories/completed/2026-01/traj_3t0440mjeunc.json +26 -0
  14. package/.trajectories/completed/2026-01/traj_3t0440mjeunc.md +6 -0
  15. package/.trajectories/completed/2026-01/traj_45x9494d9xnr.json +47 -0
  16. package/.trajectories/completed/2026-01/traj_45x9494d9xnr.md +32 -0
  17. package/.trajectories/completed/2026-01/traj_4aa0bb77s4nh.json +53 -0
  18. package/.trajectories/completed/2026-01/traj_4aa0bb77s4nh.md +32 -0
  19. package/.trajectories/completed/2026-01/traj_5lhmzq8rxpqv.json +59 -0
  20. package/.trajectories/completed/2026-01/traj_5lhmzq8rxpqv.md +33 -0
  21. package/.trajectories/completed/2026-01/traj_5vr4e9erb1fs.json +53 -0
  22. package/.trajectories/completed/2026-01/traj_5vr4e9erb1fs.md +32 -0
  23. package/.trajectories/completed/2026-01/traj_6fgiwdoklvym.json +48 -0
  24. package/.trajectories/completed/2026-01/traj_6fgiwdoklvym.md +24 -0
  25. package/.trajectories/completed/2026-01/traj_7ludwvz45veh.json +209 -0
  26. package/.trajectories/completed/2026-01/traj_7ludwvz45veh.md +97 -0
  27. package/.trajectories/completed/2026-01/traj_9921cuhel0pj.json +48 -0
  28. package/.trajectories/completed/2026-01/traj_9921cuhel0pj.md +24 -0
  29. package/.trajectories/completed/2026-01/traj_ajs7zqfux4wc.json +49 -0
  30. package/.trajectories/completed/2026-01/traj_ajs7zqfux4wc.md +23 -0
  31. package/.trajectories/completed/2026-01/traj_cvtqhlwcq9s0.json +53 -0
  32. package/.trajectories/completed/2026-01/traj_cvtqhlwcq9s0.md +32 -0
  33. package/.trajectories/completed/2026-01/traj_cxofprm2m2en.json +49 -0
  34. package/.trajectories/completed/2026-01/traj_cxofprm2m2en.md +31 -0
  35. package/.trajectories/completed/2026-01/traj_d2hhz3k0vrhn.json +26 -0
  36. package/.trajectories/completed/2026-01/traj_d2hhz3k0vrhn.md +6 -0
  37. package/.trajectories/completed/2026-01/traj_dfuvww9pege5.json +59 -0
  38. package/.trajectories/completed/2026-01/traj_dfuvww9pege5.md +37 -0
  39. package/.trajectories/completed/2026-01/traj_g0fisy9h51mf.json +77 -0
  40. package/.trajectories/completed/2026-01/traj_g0fisy9h51mf.md +42 -0
  41. package/.trajectories/completed/2026-01/traj_gjdre5voouod.json +53 -0
  42. package/.trajectories/completed/2026-01/traj_gjdre5voouod.md +32 -0
  43. package/.trajectories/completed/2026-01/traj_gtlyqtta3x8l.json +25 -0
  44. package/.trajectories/completed/2026-01/traj_gtlyqtta3x8l.md +15 -0
  45. package/.trajectories/completed/2026-01/traj_h4xijiuip3w4.json +101 -0
  46. package/.trajectories/completed/2026-01/traj_h4xijiuip3w4.md +44 -0
  47. package/.trajectories/completed/2026-01/traj_hhxte7w4gjjx.json +22 -0
  48. package/.trajectories/completed/2026-01/traj_hhxte7w4gjjx.md +5 -0
  49. package/.trajectories/completed/2026-01/traj_hpungyhoj6v5.json +53 -0
  50. package/.trajectories/completed/2026-01/traj_hpungyhoj6v5.md +32 -0
  51. package/.trajectories/completed/2026-01/traj_m2xkjv0w2sq7.json +25 -0
  52. package/.trajectories/completed/2026-01/traj_m2xkjv0w2sq7.md +15 -0
  53. package/.trajectories/completed/2026-01/traj_noq5zbvnrdvz.json +53 -0
  54. package/.trajectories/completed/2026-01/traj_noq5zbvnrdvz.md +32 -0
  55. package/.trajectories/completed/2026-01/traj_ntbs6ppopf46.json +53 -0
  56. package/.trajectories/completed/2026-01/traj_ntbs6ppopf46.md +32 -0
  57. package/.trajectories/completed/2026-01/traj_ozd98si6a7ns.json +48 -0
  58. package/.trajectories/completed/2026-01/traj_ozd98si6a7ns.md +24 -0
  59. package/.trajectories/completed/2026-01/traj_prdza7a5cxp5.json +53 -0
  60. package/.trajectories/completed/2026-01/traj_prdza7a5cxp5.md +32 -0
  61. package/.trajectories/completed/2026-01/traj_qb3twvvywfwi.json +77 -0
  62. package/.trajectories/completed/2026-01/traj_qb3twvvywfwi.md +42 -0
  63. package/.trajectories/completed/2026-01/traj_qft54mi7nfor.json +53 -0
  64. package/.trajectories/completed/2026-01/traj_qft54mi7nfor.md +32 -0
  65. package/.trajectories/completed/2026-01/traj_qx9uhf8whhxo.json +83 -0
  66. package/.trajectories/completed/2026-01/traj_qx9uhf8whhxo.md +47 -0
  67. package/.trajectories/completed/2026-01/traj_rd9toccj18a0.json +59 -0
  68. package/.trajectories/completed/2026-01/traj_rd9toccj18a0.md +37 -0
  69. package/.trajectories/completed/2026-01/traj_rt4fiw3ecp50.json +48 -0
  70. package/.trajectories/completed/2026-01/traj_rt4fiw3ecp50.md +16 -0
  71. package/.trajectories/completed/2026-01/traj_st8j35b0hrlc.json +59 -0
  72. package/.trajectories/completed/2026-01/traj_st8j35b0hrlc.md +37 -0
  73. package/.trajectories/completed/2026-01/traj_t1yy8m7hbuxp.json +53 -0
  74. package/.trajectories/completed/2026-01/traj_t1yy8m7hbuxp.md +32 -0
  75. package/.trajectories/completed/2026-01/traj_tmux_orchestrator_analysis.json +84 -0
  76. package/.trajectories/completed/2026-01/traj_tmux_orchestrator_analysis.md +109 -0
  77. package/.trajectories/completed/2026-01/traj_u9n9eqasw16k.json +53 -0
  78. package/.trajectories/completed/2026-01/traj_u9n9eqasw16k.md +32 -0
  79. package/.trajectories/completed/2026-01/traj_v87hypnongqx.json +71 -0
  80. package/.trajectories/completed/2026-01/traj_v87hypnongqx.md +42 -0
  81. package/.trajectories/completed/2026-01/traj_wkp2fgzdyinb.json +53 -0
  82. package/.trajectories/completed/2026-01/traj_wkp2fgzdyinb.md +32 -0
  83. package/.trajectories/completed/2026-01/traj_x14t8w8rn7xg.json +20 -0
  84. package/.trajectories/completed/2026-01/traj_x14t8w8rn7xg.md +6 -0
  85. package/.trajectories/completed/2026-01/traj_xnwbznkvv8ua.json +175 -0
  86. package/.trajectories/completed/2026-01/traj_xnwbznkvv8ua.md +82 -0
  87. package/.trajectories/completed/2026-01/traj_ysjc8zaeqtd3.json +47 -0
  88. package/.trajectories/completed/2026-01/traj_ysjc8zaeqtd3.md +32 -0
  89. package/.trajectories/completed/2026-01/traj_yvdadtvdgnz3.json +59 -0
  90. package/.trajectories/completed/2026-01/traj_yvdadtvdgnz3.md +37 -0
  91. package/.trajectories/completed/2026-01/traj_z0vcw1wrzide.json +53 -0
  92. package/.trajectories/completed/2026-01/traj_z0vcw1wrzide.md +32 -0
  93. package/.trajectories/index.json +314 -0
  94. package/ARCHITECTURE.md +1245 -0
  95. package/README.md +1 -1
  96. package/TESTING.md +278 -0
  97. package/deploy/init-db.sql +5 -0
  98. package/deploy/scripts/setup-fly-workspaces.sh +69 -0
  99. package/deploy/scripts/setup-railway.sh +75 -0
  100. package/deploy/workspace/entrypoint-browser.sh +118 -0
  101. package/deploy/workspace/entrypoint.sh +348 -0
  102. package/deploy/workspace/git-credential-relay +111 -0
  103. package/dist/bridge/spawner.d.ts +53 -0
  104. package/dist/bridge/spawner.js +203 -19
  105. package/dist/bridge/types.d.ts +12 -0
  106. package/dist/cli/index.js +618 -5
  107. package/dist/cloud/api/auth.d.ts +3 -2
  108. package/dist/cloud/api/auth.js +10 -98
  109. package/dist/cloud/api/billing.js +30 -9
  110. package/dist/cloud/api/cli-pty-runner.d.ts +54 -0
  111. package/dist/cloud/api/cli-pty-runner.js +119 -0
  112. package/dist/cloud/api/codex-auth-helper.d.ts +15 -0
  113. package/dist/cloud/api/codex-auth-helper.js +100 -0
  114. package/dist/cloud/api/generic-webhooks.d.ts +8 -0
  115. package/dist/cloud/api/generic-webhooks.js +129 -0
  116. package/dist/cloud/api/git.d.ts +8 -0
  117. package/dist/cloud/api/git.js +152 -0
  118. package/dist/cloud/api/github-app.d.ts +11 -0
  119. package/dist/cloud/api/github-app.js +189 -0
  120. package/dist/cloud/api/middleware/planLimits.d.ts +7 -0
  121. package/dist/cloud/api/middleware/planLimits.js +39 -1
  122. package/dist/cloud/api/monitoring.d.ts +11 -0
  123. package/dist/cloud/api/monitoring.js +578 -0
  124. package/dist/cloud/api/nango-auth.d.ts +9 -0
  125. package/dist/cloud/api/nango-auth.js +377 -0
  126. package/dist/cloud/api/onboarding.d.ts +8 -1
  127. package/dist/cloud/api/onboarding.js +313 -119
  128. package/dist/cloud/api/policy.d.ts +8 -0
  129. package/dist/cloud/api/policy.js +229 -0
  130. package/dist/cloud/api/providers.js +114 -42
  131. package/dist/cloud/api/repos.d.ts +1 -0
  132. package/dist/cloud/api/repos.js +186 -0
  133. package/dist/cloud/api/test-helpers.d.ts +10 -0
  134. package/dist/cloud/api/test-helpers.js +575 -0
  135. package/dist/cloud/api/webhooks.d.ts +8 -0
  136. package/dist/cloud/api/webhooks.js +645 -0
  137. package/dist/cloud/api/workspaces.js +320 -12
  138. package/dist/cloud/billing/plans.js +32 -19
  139. package/dist/cloud/billing/types.d.ts +9 -3
  140. package/dist/cloud/config.d.ts +9 -2
  141. package/dist/cloud/config.js +13 -4
  142. package/dist/cloud/db/drizzle.d.ts +84 -1
  143. package/dist/cloud/db/drizzle.js +470 -0
  144. package/dist/cloud/db/index.d.ts +9 -4
  145. package/dist/cloud/db/index.js +11 -3
  146. package/dist/cloud/db/schema.d.ts +3283 -556
  147. package/dist/cloud/db/schema.js +314 -1
  148. package/dist/cloud/index.d.ts +1 -0
  149. package/dist/cloud/index.js +2 -0
  150. package/dist/cloud/provisioner/index.d.ts +56 -0
  151. package/dist/cloud/provisioner/index.js +676 -34
  152. package/dist/cloud/server.d.ts +1 -0
  153. package/dist/cloud/server.js +362 -13
  154. package/dist/cloud/services/auto-scaler.d.ts +152 -0
  155. package/dist/cloud/services/auto-scaler.js +439 -0
  156. package/dist/cloud/services/capacity-manager.d.ts +148 -0
  157. package/dist/cloud/services/capacity-manager.js +449 -0
  158. package/dist/cloud/services/ci-agent-spawner.d.ts +49 -0
  159. package/dist/cloud/services/ci-agent-spawner.js +373 -0
  160. package/dist/cloud/services/index.d.ts +12 -0
  161. package/dist/cloud/services/index.js +15 -0
  162. package/dist/cloud/services/mention-handler.d.ts +65 -0
  163. package/dist/cloud/services/mention-handler.js +405 -0
  164. package/dist/cloud/services/nango.d.ts +186 -0
  165. package/dist/cloud/services/nango.js +344 -0
  166. package/dist/cloud/services/persistence.d.ts +131 -0
  167. package/dist/cloud/services/persistence.js +200 -0
  168. package/dist/cloud/services/planLimits.d.ts +37 -0
  169. package/dist/cloud/services/planLimits.js +86 -5
  170. package/dist/cloud/services/scaling-orchestrator.d.ts +159 -0
  171. package/dist/cloud/services/scaling-orchestrator.js +502 -0
  172. package/dist/cloud/services/scaling-policy.d.ts +121 -0
  173. package/dist/cloud/services/scaling-policy.js +415 -0
  174. package/dist/cloud/vault/index.js +1 -1
  175. package/dist/cloud/webhooks/index.d.ts +24 -0
  176. package/dist/cloud/webhooks/index.js +29 -0
  177. package/dist/cloud/webhooks/parsers/github.d.ts +8 -0
  178. package/dist/cloud/webhooks/parsers/github.js +234 -0
  179. package/dist/cloud/webhooks/parsers/index.d.ts +23 -0
  180. package/dist/cloud/webhooks/parsers/index.js +30 -0
  181. package/dist/cloud/webhooks/parsers/linear.d.ts +9 -0
  182. package/dist/cloud/webhooks/parsers/linear.js +258 -0
  183. package/dist/cloud/webhooks/parsers/slack.d.ts +9 -0
  184. package/dist/cloud/webhooks/parsers/slack.js +214 -0
  185. package/dist/cloud/webhooks/responders/github.d.ts +8 -0
  186. package/dist/cloud/webhooks/responders/github.js +73 -0
  187. package/dist/cloud/webhooks/responders/index.d.ts +23 -0
  188. package/dist/cloud/webhooks/responders/index.js +30 -0
  189. package/dist/cloud/webhooks/responders/linear.d.ts +9 -0
  190. package/dist/cloud/webhooks/responders/linear.js +149 -0
  191. package/dist/cloud/webhooks/responders/slack.d.ts +20 -0
  192. package/dist/cloud/webhooks/responders/slack.js +178 -0
  193. package/dist/cloud/webhooks/router.d.ts +25 -0
  194. package/dist/cloud/webhooks/router.js +504 -0
  195. package/dist/cloud/webhooks/rules-engine.d.ts +24 -0
  196. package/dist/cloud/webhooks/rules-engine.js +287 -0
  197. package/dist/cloud/webhooks/types.d.ts +186 -0
  198. package/dist/cloud/webhooks/types.js +8 -0
  199. package/dist/continuity/formatter.d.ts +51 -0
  200. package/dist/continuity/formatter.js +313 -0
  201. package/dist/continuity/handoff-store.d.ts +67 -0
  202. package/dist/continuity/handoff-store.js +472 -0
  203. package/dist/continuity/index.d.ts +45 -0
  204. package/dist/continuity/index.js +48 -0
  205. package/dist/continuity/ledger-store.d.ts +110 -0
  206. package/dist/continuity/ledger-store.js +500 -0
  207. package/dist/continuity/manager.d.ts +178 -0
  208. package/dist/continuity/manager.js +562 -0
  209. package/dist/continuity/parser.d.ts +76 -0
  210. package/dist/continuity/parser.js +579 -0
  211. package/dist/continuity/types.d.ts +180 -0
  212. package/dist/continuity/types.js +9 -0
  213. package/dist/daemon/agent-manager.d.ts +27 -0
  214. package/dist/daemon/agent-manager.js +107 -6
  215. package/dist/daemon/agent-registry.d.ts +32 -0
  216. package/dist/daemon/agent-registry.js +42 -2
  217. package/dist/daemon/api.d.ts +12 -0
  218. package/dist/daemon/api.js +131 -2
  219. package/dist/daemon/cli-auth.d.ts +67 -0
  220. package/dist/daemon/cli-auth.js +537 -0
  221. package/dist/daemon/cloud-sync.js +9 -7
  222. package/dist/daemon/orchestrator.js +30 -0
  223. package/dist/daemon/router.d.ts +5 -0
  224. package/dist/daemon/router.js +78 -26
  225. package/dist/daemon/server.d.ts +5 -0
  226. package/dist/daemon/server.js +9 -1
  227. package/dist/daemon/services/browser-testing.d.ts +88 -0
  228. package/dist/daemon/services/browser-testing.js +244 -0
  229. package/dist/daemon/services/container-spawner.d.ts +135 -0
  230. package/dist/daemon/services/container-spawner.js +313 -0
  231. package/dist/daemon/types.d.ts +5 -1
  232. package/dist/dashboard/out/404.html +1 -1
  233. package/dist/dashboard/out/_next/static/chunks/116-2502180def231162.js +1 -0
  234. package/dist/dashboard/out/_next/static/chunks/282-980c2eb8fff20123.js +1 -0
  235. package/dist/dashboard/out/_next/static/chunks/699-3b1cd6618a45d259.js +1 -0
  236. package/dist/dashboard/out/_next/static/chunks/724-2dae7627550ab88f.js +9 -0
  237. package/dist/dashboard/out/_next/static/chunks/766-1f2dd8cb7f766b0b.js +1 -0
  238. package/dist/dashboard/out/_next/static/chunks/app/app/onboarding/page-3fdfa60e53f2810d.js +1 -0
  239. package/dist/dashboard/out/_next/static/chunks/app/app/page-e6381e5a6e1fbcfd.js +1 -0
  240. package/dist/dashboard/out/_next/static/chunks/app/connect-repos/page-3538dfe0ffe984b8.js +1 -0
  241. package/dist/dashboard/out/_next/static/chunks/app/history/{page-b6edd4dde8d08194.js → page-abb9ab2d329f56e9.js} +1 -1
  242. package/dist/dashboard/out/_next/static/chunks/app/layout-c0d118c0f92d969c.js +1 -0
  243. package/dist/dashboard/out/_next/static/chunks/app/login/page-c22d080201cbd9fb.js +1 -0
  244. package/dist/dashboard/out/_next/static/chunks/app/metrics/page-67a3e98d9a43a6ed.js +1 -0
  245. package/dist/dashboard/out/_next/static/chunks/app/page-77e9c65420a06cfb.js +1 -0
  246. package/dist/dashboard/out/_next/static/chunks/app/pricing/page-b08ed1c34d14434a.js +1 -0
  247. package/dist/dashboard/out/_next/static/chunks/app/providers/page-e88bc117ef7671c3.js +1 -0
  248. package/dist/dashboard/out/_next/static/chunks/app/signup/page-68d34f50baa8ab6b.js +1 -0
  249. package/dist/dashboard/out/_next/static/chunks/e868780c-48e5f147c90a3a41.js +18 -0
  250. package/dist/dashboard/out/_next/static/chunks/{main-app-5d692157a8eb1fd9.js → main-app-6e8e8d3ef4e0192a.js} +1 -1
  251. package/dist/dashboard/out/_next/static/chunks/{main-c2f423b9c9f4591b.js → main-ed4e1fb6f29c34cf.js} +1 -1
  252. package/dist/dashboard/out/_next/static/chunks/webpack-1cdd8ed57114d5e1.js +1 -0
  253. package/dist/dashboard/out/_next/static/css/29852f26181969a0.css +1 -0
  254. package/dist/dashboard/out/_next/static/css/7c3ae9e8617d42a5.css +1 -0
  255. package/dist/dashboard/out/app/onboarding.html +1 -0
  256. package/dist/dashboard/out/app/onboarding.txt +7 -0
  257. package/dist/dashboard/out/app.html +1 -14
  258. package/dist/dashboard/out/app.txt +2 -2
  259. package/dist/dashboard/out/connect-repos.html +1 -0
  260. package/dist/dashboard/out/connect-repos.txt +7 -0
  261. package/dist/dashboard/out/history.html +1 -1
  262. package/dist/dashboard/out/history.txt +2 -2
  263. package/dist/dashboard/out/index.html +1 -1
  264. package/dist/dashboard/out/index.txt +2 -2
  265. package/dist/dashboard/out/login.html +6 -0
  266. package/dist/dashboard/out/login.txt +7 -0
  267. package/dist/dashboard/out/metrics.html +1 -1
  268. package/dist/dashboard/out/metrics.txt +2 -2
  269. package/dist/dashboard/out/pricing.html +3 -3
  270. package/dist/dashboard/out/pricing.txt +2 -2
  271. package/dist/dashboard/out/providers.html +1 -0
  272. package/dist/dashboard/out/providers.txt +7 -0
  273. package/dist/dashboard/out/signup.html +6 -0
  274. package/dist/dashboard/out/signup.txt +7 -0
  275. package/dist/dashboard-server/server.js +1308 -8
  276. package/dist/hooks/emitter.d.ts +40 -0
  277. package/dist/hooks/emitter.js +63 -0
  278. package/dist/hooks/index.d.ts +3 -0
  279. package/dist/hooks/index.js +3 -0
  280. package/dist/hooks/registry.d.ts +173 -0
  281. package/dist/hooks/registry.js +476 -0
  282. package/dist/hooks/trajectory-hooks.d.ts +52 -0
  283. package/dist/hooks/trajectory-hooks.js +183 -0
  284. package/dist/hooks/types.d.ts +141 -0
  285. package/dist/index.d.ts +2 -0
  286. package/dist/index.js +3 -0
  287. package/dist/memory/adapters/index.d.ts +8 -0
  288. package/dist/memory/adapters/index.js +8 -0
  289. package/dist/memory/adapters/inmemory.d.ts +59 -0
  290. package/dist/memory/adapters/inmemory.js +195 -0
  291. package/dist/memory/adapters/supermemory.d.ts +71 -0
  292. package/dist/memory/adapters/supermemory.js +338 -0
  293. package/dist/memory/factory.d.ts +48 -0
  294. package/dist/memory/factory.js +143 -0
  295. package/dist/memory/index.d.ts +32 -0
  296. package/dist/memory/index.js +32 -0
  297. package/dist/memory/memory-hooks.d.ts +60 -0
  298. package/dist/memory/memory-hooks.js +313 -0
  299. package/dist/memory/service.d.ts +49 -0
  300. package/dist/memory/service.js +146 -0
  301. package/dist/memory/types.d.ts +195 -0
  302. package/dist/memory/types.js +8 -0
  303. package/dist/policy/agent-policy.d.ts +225 -0
  304. package/dist/policy/agent-policy.js +665 -0
  305. package/dist/policy/cloud-policy-fetcher.d.ts +12 -0
  306. package/dist/policy/cloud-policy-fetcher.js +64 -0
  307. package/dist/resiliency/crash-insights.d.ts +156 -0
  308. package/dist/resiliency/crash-insights.js +492 -0
  309. package/dist/resiliency/gossip-health.d.ts +137 -0
  310. package/dist/resiliency/gossip-health.js +241 -0
  311. package/dist/resiliency/index.d.ts +5 -0
  312. package/dist/resiliency/index.js +5 -0
  313. package/dist/resiliency/leader-watchdog.d.ts +109 -0
  314. package/dist/resiliency/leader-watchdog.js +189 -0
  315. package/dist/resiliency/memory-monitor.d.ts +172 -0
  316. package/dist/resiliency/memory-monitor.js +593 -0
  317. package/dist/resiliency/stateless-lead.d.ts +149 -0
  318. package/dist/resiliency/stateless-lead.js +308 -0
  319. package/dist/resiliency/supervisor.d.ts +38 -0
  320. package/dist/resiliency/supervisor.js +122 -0
  321. package/dist/shared/cli-auth-config.d.ts +91 -0
  322. package/dist/shared/cli-auth-config.js +264 -0
  323. package/dist/storage/adapter.d.ts +1 -1
  324. package/dist/trajectory/config.d.ts +84 -0
  325. package/dist/trajectory/config.js +163 -0
  326. package/dist/trajectory/index.d.ts +8 -0
  327. package/dist/trajectory/index.js +8 -0
  328. package/dist/trajectory/integration.d.ts +292 -0
  329. package/dist/trajectory/integration.js +834 -0
  330. package/dist/utils/logger.js +1 -1
  331. package/dist/utils/project-namespace.d.ts +24 -0
  332. package/dist/utils/project-namespace.js +84 -0
  333. package/dist/wrapper/parser.d.ts +10 -0
  334. package/dist/wrapper/parser.js +100 -33
  335. package/dist/wrapper/pty-wrapper.d.ts +197 -16
  336. package/dist/wrapper/pty-wrapper.js +943 -106
  337. package/dist/wrapper/shared.d.ts +165 -0
  338. package/dist/wrapper/shared.js +270 -0
  339. package/dist/wrapper/tmux-wrapper.d.ts +73 -11
  340. package/dist/wrapper/tmux-wrapper.js +541 -120
  341. package/package.json +16 -16
  342. package/scripts/postinstall.js +60 -0
  343. package/test-push.txt +1 -0
  344. package/bin/tmux +0 -0
  345. package/dist/bridge/config.d.ts.map +0 -1
  346. package/dist/bridge/config.js.map +0 -1
  347. package/dist/bridge/index.d.ts.map +0 -1
  348. package/dist/bridge/index.js.map +0 -1
  349. package/dist/bridge/multi-project-client.d.ts.map +0 -1
  350. package/dist/bridge/multi-project-client.js.map +0 -1
  351. package/dist/bridge/shadow-cli.d.ts.map +0 -1
  352. package/dist/bridge/shadow-cli.js.map +0 -1
  353. package/dist/bridge/shadow-config.d.ts.map +0 -1
  354. package/dist/bridge/shadow-config.js.map +0 -1
  355. package/dist/bridge/spawner.d.ts.map +0 -1
  356. package/dist/bridge/spawner.js.map +0 -1
  357. package/dist/bridge/teams-config.d.ts.map +0 -1
  358. package/dist/bridge/teams-config.js.map +0 -1
  359. package/dist/bridge/types.d.ts.map +0 -1
  360. package/dist/bridge/types.js.map +0 -1
  361. package/dist/bridge/utils.d.ts.map +0 -1
  362. package/dist/bridge/utils.js.map +0 -1
  363. package/dist/cli/index.d.ts.map +0 -1
  364. package/dist/cli/index.js.map +0 -1
  365. package/dist/cloud/api/auth.d.ts.map +0 -1
  366. package/dist/cloud/api/auth.js.map +0 -1
  367. package/dist/cloud/api/billing.d.ts.map +0 -1
  368. package/dist/cloud/api/billing.js.map +0 -1
  369. package/dist/cloud/api/coordinators.d.ts.map +0 -1
  370. package/dist/cloud/api/coordinators.js.map +0 -1
  371. package/dist/cloud/api/daemons.d.ts.map +0 -1
  372. package/dist/cloud/api/daemons.js.map +0 -1
  373. package/dist/cloud/api/middleware/planLimits.d.ts.map +0 -1
  374. package/dist/cloud/api/middleware/planLimits.js.map +0 -1
  375. package/dist/cloud/api/onboarding.d.ts.map +0 -1
  376. package/dist/cloud/api/onboarding.js.map +0 -1
  377. package/dist/cloud/api/providers.d.ts.map +0 -1
  378. package/dist/cloud/api/providers.js.map +0 -1
  379. package/dist/cloud/api/repos.d.ts.map +0 -1
  380. package/dist/cloud/api/repos.js.map +0 -1
  381. package/dist/cloud/api/teams.d.ts.map +0 -1
  382. package/dist/cloud/api/teams.js.map +0 -1
  383. package/dist/cloud/api/usage.d.ts.map +0 -1
  384. package/dist/cloud/api/usage.js.map +0 -1
  385. package/dist/cloud/api/workspaces.d.ts.map +0 -1
  386. package/dist/cloud/api/workspaces.js.map +0 -1
  387. package/dist/cloud/billing/index.d.ts.map +0 -1
  388. package/dist/cloud/billing/index.js.map +0 -1
  389. package/dist/cloud/billing/plans.d.ts.map +0 -1
  390. package/dist/cloud/billing/plans.js.map +0 -1
  391. package/dist/cloud/billing/service.d.ts.map +0 -1
  392. package/dist/cloud/billing/service.js.map +0 -1
  393. package/dist/cloud/billing/types.d.ts.map +0 -1
  394. package/dist/cloud/billing/types.js.map +0 -1
  395. package/dist/cloud/config.d.ts.map +0 -1
  396. package/dist/cloud/config.js.map +0 -1
  397. package/dist/cloud/db/drizzle.d.ts.map +0 -1
  398. package/dist/cloud/db/drizzle.js.map +0 -1
  399. package/dist/cloud/db/index.d.ts.map +0 -1
  400. package/dist/cloud/db/index.js.map +0 -1
  401. package/dist/cloud/db/schema.d.ts.map +0 -1
  402. package/dist/cloud/db/schema.js.map +0 -1
  403. package/dist/cloud/index.d.ts.map +0 -1
  404. package/dist/cloud/index.js.map +0 -1
  405. package/dist/cloud/provisioner/index.d.ts.map +0 -1
  406. package/dist/cloud/provisioner/index.js.map +0 -1
  407. package/dist/cloud/server.d.ts.map +0 -1
  408. package/dist/cloud/server.js.map +0 -1
  409. package/dist/cloud/services/coordinator.d.ts.map +0 -1
  410. package/dist/cloud/services/coordinator.js.map +0 -1
  411. package/dist/cloud/services/planLimits.d.ts.map +0 -1
  412. package/dist/cloud/services/planLimits.js.map +0 -1
  413. package/dist/cloud/vault/index.d.ts.map +0 -1
  414. package/dist/cloud/vault/index.js.map +0 -1
  415. package/dist/daemon/agent-manager.d.ts.map +0 -1
  416. package/dist/daemon/agent-manager.js.map +0 -1
  417. package/dist/daemon/agent-registry.d.ts.map +0 -1
  418. package/dist/daemon/agent-registry.js.map +0 -1
  419. package/dist/daemon/api.d.ts.map +0 -1
  420. package/dist/daemon/api.js.map +0 -1
  421. package/dist/daemon/auth.d.ts.map +0 -1
  422. package/dist/daemon/auth.js.map +0 -1
  423. package/dist/daemon/cloud-sync.d.ts.map +0 -1
  424. package/dist/daemon/cloud-sync.js.map +0 -1
  425. package/dist/daemon/connection.d.ts.map +0 -1
  426. package/dist/daemon/connection.js.map +0 -1
  427. package/dist/daemon/index.d.ts.map +0 -1
  428. package/dist/daemon/index.js.map +0 -1
  429. package/dist/daemon/orchestrator.d.ts.map +0 -1
  430. package/dist/daemon/orchestrator.js.map +0 -1
  431. package/dist/daemon/registry.d.ts.map +0 -1
  432. package/dist/daemon/registry.js.map +0 -1
  433. package/dist/daemon/router.d.ts.map +0 -1
  434. package/dist/daemon/router.js.map +0 -1
  435. package/dist/daemon/server.d.ts.map +0 -1
  436. package/dist/daemon/server.js.map +0 -1
  437. package/dist/daemon/types.d.ts.map +0 -1
  438. package/dist/daemon/types.js.map +0 -1
  439. package/dist/daemon/workspace-manager.d.ts.map +0 -1
  440. package/dist/daemon/workspace-manager.js.map +0 -1
  441. package/dist/dashboard/out/_next/static/chunks/693-7b3301d8f6bc5014.js +0 -1
  442. package/dist/dashboard/out/_next/static/chunks/713-f78477eb185f1f4d.js +0 -1
  443. package/dist/dashboard/out/_next/static/chunks/766-e53e1cfe39b0b5b5.js +0 -1
  444. package/dist/dashboard/out/_next/static/chunks/900-037c64bfd797fb2a.js +0 -1
  445. package/dist/dashboard/out/_next/static/chunks/app/app/page-e3d9e1f4466b9bae.js +0 -1
  446. package/dist/dashboard/out/_next/static/chunks/app/layout-2433bb48965f4333.js +0 -1
  447. package/dist/dashboard/out/_next/static/chunks/app/metrics/page-e68825a81db67ba1.js +0 -1
  448. package/dist/dashboard/out/_next/static/chunks/app/page-cc108bf68c8a657f.js +0 -1
  449. package/dist/dashboard/out/_next/static/chunks/app/pricing/page-d80e03a5297f95b6.js +0 -1
  450. package/dist/dashboard/out/_next/static/chunks/webpack-a5acc2831d094776.js +0 -1
  451. package/dist/dashboard/out/_next/static/css/79b80143647a07d7.css +0 -1
  452. package/dist/dashboard/out/_next/static/css/8cf277370ad48cfe.css +0 -1
  453. package/dist/dashboard-server/metrics.d.ts.map +0 -1
  454. package/dist/dashboard-server/metrics.js.map +0 -1
  455. package/dist/dashboard-server/needs-attention.d.ts.map +0 -1
  456. package/dist/dashboard-server/needs-attention.js.map +0 -1
  457. package/dist/dashboard-server/server.d.ts.map +0 -1
  458. package/dist/dashboard-server/server.js.map +0 -1
  459. package/dist/dashboard-server/start.d.ts.map +0 -1
  460. package/dist/dashboard-server/start.js.map +0 -1
  461. package/dist/hooks/inbox-check/hook.d.ts.map +0 -1
  462. package/dist/hooks/inbox-check/hook.js.map +0 -1
  463. package/dist/hooks/inbox-check/index.d.ts.map +0 -1
  464. package/dist/hooks/inbox-check/index.js.map +0 -1
  465. package/dist/hooks/inbox-check/types.d.ts.map +0 -1
  466. package/dist/hooks/inbox-check/types.js.map +0 -1
  467. package/dist/hooks/inbox-check/utils.d.ts.map +0 -1
  468. package/dist/hooks/inbox-check/utils.js.map +0 -1
  469. package/dist/hooks/index.d.ts.map +0 -1
  470. package/dist/hooks/index.js.map +0 -1
  471. package/dist/hooks/types.d.ts.map +0 -1
  472. package/dist/hooks/types.js.map +0 -1
  473. package/dist/index.d.ts.map +0 -1
  474. package/dist/index.js.map +0 -1
  475. package/dist/protocol/framing.d.ts.map +0 -1
  476. package/dist/protocol/framing.js.map +0 -1
  477. package/dist/protocol/index.d.ts.map +0 -1
  478. package/dist/protocol/index.js.map +0 -1
  479. package/dist/protocol/types.d.ts.map +0 -1
  480. package/dist/protocol/types.js.map +0 -1
  481. package/dist/resiliency/context-persistence.d.ts.map +0 -1
  482. package/dist/resiliency/context-persistence.js.map +0 -1
  483. package/dist/resiliency/health-monitor.d.ts.map +0 -1
  484. package/dist/resiliency/health-monitor.js.map +0 -1
  485. package/dist/resiliency/index.d.ts.map +0 -1
  486. package/dist/resiliency/index.js.map +0 -1
  487. package/dist/resiliency/logger.d.ts.map +0 -1
  488. package/dist/resiliency/logger.js.map +0 -1
  489. package/dist/resiliency/metrics.d.ts.map +0 -1
  490. package/dist/resiliency/metrics.js.map +0 -1
  491. package/dist/resiliency/provider-context.d.ts.map +0 -1
  492. package/dist/resiliency/provider-context.js.map +0 -1
  493. package/dist/resiliency/supervisor.d.ts.map +0 -1
  494. package/dist/resiliency/supervisor.js.map +0 -1
  495. package/dist/state/agent-state.d.ts.map +0 -1
  496. package/dist/state/agent-state.js.map +0 -1
  497. package/dist/storage/adapter.d.ts.map +0 -1
  498. package/dist/storage/adapter.js.map +0 -1
  499. package/dist/storage/sqlite-adapter.d.ts.map +0 -1
  500. package/dist/storage/sqlite-adapter.js.map +0 -1
  501. package/dist/utils/agent-config.d.ts.map +0 -1
  502. package/dist/utils/agent-config.js.map +0 -1
  503. package/dist/utils/command-resolver.d.ts.map +0 -1
  504. package/dist/utils/command-resolver.js.map +0 -1
  505. package/dist/utils/index.d.ts.map +0 -1
  506. package/dist/utils/index.js.map +0 -1
  507. package/dist/utils/logger.d.ts.map +0 -1
  508. package/dist/utils/logger.js.map +0 -1
  509. package/dist/utils/name-generator.d.ts.map +0 -1
  510. package/dist/utils/name-generator.js.map +0 -1
  511. package/dist/utils/project-namespace.d.ts.map +0 -1
  512. package/dist/utils/project-namespace.js.map +0 -1
  513. package/dist/utils/tmux-resolver.d.ts.map +0 -1
  514. package/dist/utils/tmux-resolver.js.map +0 -1
  515. package/dist/utils/update-checker.d.ts.map +0 -1
  516. package/dist/utils/update-checker.js.map +0 -1
  517. package/dist/wrapper/client.d.ts.map +0 -1
  518. package/dist/wrapper/client.js.map +0 -1
  519. package/dist/wrapper/inbox.d.ts.map +0 -1
  520. package/dist/wrapper/inbox.js.map +0 -1
  521. package/dist/wrapper/index.d.ts.map +0 -1
  522. package/dist/wrapper/index.js.map +0 -1
  523. package/dist/wrapper/parser.d.ts.map +0 -1
  524. package/dist/wrapper/parser.js.map +0 -1
  525. package/dist/wrapper/pty-wrapper.d.ts.map +0 -1
  526. package/dist/wrapper/pty-wrapper.js.map +0 -1
  527. package/dist/wrapper/tmux-wrapper.d.ts.map +0 -1
  528. package/dist/wrapper/tmux-wrapper.js.map +0 -1
  529. package/docs/AGENTS.md +0 -513
  530. package/docs/ARCHITECTURE_DECISIONS.md +0 -175
  531. package/docs/CHANGELOG.md +0 -11
  532. package/docs/CLI-SIMPLIFICATION-COMPLETE.md +0 -48
  533. package/docs/CLOUD-ARCHITECTURE.md +0 -652
  534. package/docs/CLOUD-ONBOARDING-DESIGN.md +0 -1983
  535. package/docs/COMPETITIVE_ANALYSIS.md +0 -897
  536. package/docs/CONTRIBUTING.md +0 -151
  537. package/docs/DESIGN_BRIDGE_STAFFING.md +0 -878
  538. package/docs/DESIGN_V2.md +0 -1079
  539. package/docs/INTEGRATION-GUIDE.md +0 -926
  540. package/docs/MONETIZATION.md +0 -1679
  541. package/docs/PROPOSAL-trajectories.md +0 -1582
  542. package/docs/PROTOCOL.md +0 -325
  543. package/docs/SCALING_ANALYSIS.md +0 -280
  544. package/docs/TESTING_PRESENCE_FEATURES.md +0 -327
  545. package/docs/TMUX_IMPLEMENTATION_NOTES.md +0 -364
  546. package/docs/TMUX_IMPROVEMENTS.md +0 -968
  547. package/docs/agent-relay-snippet.md +0 -168
  548. package/docs/competitive-analysis-mcp-agent-mail.md +0 -389
  549. package/docs/dashboard-v2-plan.md +0 -179
  550. package/docs/guides/CLOUD.md +0 -236
  551. package/docs/guides/LOCAL.md +0 -535
  552. package/docs/guides/SELF-HOSTED.md +0 -494
  553. package/docs/proposals/shadow-as-subagent.md +0 -765
  554. package/docs/proposals/slack-bot-integration.md +0 -1457
  555. package/docs/removable-code-analysis.md +0 -24
  556. package/scripts/dev/PUBLIC_RELEASE_PLAN.md +0 -88
  557. package/scripts/dev/dev-team-setup.sh +0 -431
  558. package/scripts/e2e-test.sh +0 -119
  559. package/scripts/games/game-protocol.md +0 -79
  560. package/scripts/games/hearts-setup.sh +0 -264
  561. package/scripts/tictactoe-setup.sh +0 -181
  562. /package/dist/dashboard/out/_next/static/chunks/{117-b2cd8d6485aacf2b.js → 117-f7b8ab0809342e77.js} +0 -0
  563. /package/dist/dashboard/out/_next/static/chunks/{648-8f3f26864ce515e5.js → 648-5cc6e1921389a58a.js} +0 -0
  564. /package/dist/dashboard/out/_next/static/chunks/app/_not-found/{page-0b990dbb71d72a98.js → page-53b8a69f76db17d0.js} +0 -0
  565. /package/dist/dashboard/out/_next/static/chunks/{fd9d1056-bf46c09eb57e019c.js → fd9d1056-609918ca7b6280bb.js} +0 -0
  566. /package/dist/dashboard/out/_next/static/{6HHWb2ZmnJ4OSm0zUP7h4 → wPgKJtcOmTFLpUncDg16A}/_buildManifest.js +0 -0
  567. /package/dist/dashboard/out/_next/static/{6HHWb2ZmnJ4OSm0zUP7h4 → wPgKJtcOmTFLpUncDg16A}/_ssgManifest.js +0 -0
@@ -6,8 +6,9 @@
6
6
  import { Router } from 'express';
7
7
  import { requireAuth } from './auth.js';
8
8
  import { db } from '../db/index.js';
9
- import { getProvisioner } from '../provisioner/index.js';
9
+ import { getProvisioner, getProvisioningStage } from '../provisioner/index.js';
10
10
  import { checkWorkspaceLimit } from './middleware/planLimits.js';
11
+ import { getConfig } from '../config.js';
11
12
  export const workspacesRouter = Router();
12
13
  // All routes require authentication
13
14
  workspacesRouter.use(requireAuth);
@@ -90,6 +91,126 @@ workspacesRouter.post('/', checkWorkspaceLimit, async (req, res) => {
90
91
  res.status(500).json({ error: 'Failed to create workspace' });
91
92
  }
92
93
  });
94
+ /**
95
+ * GET /api/workspaces/summary
96
+ * Get summary of all user workspaces for dashboard status indicator
97
+ * NOTE: This route MUST be before /:id to avoid being caught by parameterized route
98
+ */
99
+ workspacesRouter.get('/summary', async (req, res) => {
100
+ const userId = req.session.userId;
101
+ try {
102
+ const workspaces = await db.workspaces.findByUserId(userId);
103
+ const provisioner = getProvisioner();
104
+ // Get live status for each workspace
105
+ const workspaceSummaries = await Promise.all(workspaces.map(async (w) => {
106
+ let liveStatus = w.status;
107
+ try {
108
+ liveStatus = await provisioner.getStatus(w.id);
109
+ }
110
+ catch {
111
+ // Fall back to DB status
112
+ }
113
+ return {
114
+ id: w.id,
115
+ name: w.name,
116
+ status: liveStatus,
117
+ publicUrl: w.publicUrl,
118
+ isStopped: liveStatus === 'stopped',
119
+ isRunning: liveStatus === 'running',
120
+ isProvisioning: liveStatus === 'provisioning',
121
+ hasError: liveStatus === 'error',
122
+ };
123
+ }));
124
+ // Overall status for quick dashboard indicator
125
+ const hasRunningWorkspace = workspaceSummaries.some(w => w.isRunning);
126
+ const hasStoppedWorkspace = workspaceSummaries.some(w => w.isStopped);
127
+ const hasProvisioningWorkspace = workspaceSummaries.some(w => w.isProvisioning);
128
+ res.json({
129
+ workspaces: workspaceSummaries,
130
+ summary: {
131
+ total: workspaceSummaries.length,
132
+ running: workspaceSummaries.filter(w => w.isRunning).length,
133
+ stopped: workspaceSummaries.filter(w => w.isStopped).length,
134
+ provisioning: workspaceSummaries.filter(w => w.isProvisioning).length,
135
+ error: workspaceSummaries.filter(w => w.hasError).length,
136
+ },
137
+ overallStatus: hasRunningWorkspace
138
+ ? 'ready'
139
+ : hasProvisioningWorkspace
140
+ ? 'provisioning'
141
+ : hasStoppedWorkspace
142
+ ? 'stopped'
143
+ : workspaceSummaries.length === 0
144
+ ? 'none'
145
+ : 'error',
146
+ });
147
+ }
148
+ catch (error) {
149
+ console.error('Error getting workspace summary:', error);
150
+ res.status(500).json({ error: 'Failed to get workspace summary' });
151
+ }
152
+ });
153
+ /**
154
+ * GET /api/workspaces/primary
155
+ * Get the user's primary workspace (first/default) with live status
156
+ * Used by dashboard to show quick status indicator
157
+ * NOTE: This route MUST be before /:id to avoid being caught by parameterized route
158
+ */
159
+ workspacesRouter.get('/primary', async (req, res) => {
160
+ const userId = req.session.userId;
161
+ try {
162
+ const workspaces = await db.workspaces.findByUserId(userId);
163
+ if (workspaces.length === 0) {
164
+ return res.json({
165
+ exists: false,
166
+ message: 'No workspace found. Connect a repository to auto-provision one.',
167
+ });
168
+ }
169
+ const primary = workspaces[0];
170
+ const provisioner = getProvisioner();
171
+ let liveStatus = primary.status;
172
+ try {
173
+ liveStatus = await provisioner.getStatus(primary.id);
174
+ }
175
+ catch {
176
+ // Fall back to DB status
177
+ }
178
+ res.json({
179
+ exists: true,
180
+ workspace: {
181
+ id: primary.id,
182
+ name: primary.name,
183
+ status: liveStatus,
184
+ publicUrl: primary.publicUrl,
185
+ isStopped: liveStatus === 'stopped',
186
+ isRunning: liveStatus === 'running',
187
+ isProvisioning: liveStatus === 'provisioning',
188
+ hasError: liveStatus === 'error',
189
+ config: {
190
+ providers: primary.config.providers || [],
191
+ repositories: primary.config.repositories || [],
192
+ },
193
+ },
194
+ // Quick messages for UI
195
+ statusMessage: liveStatus === 'running'
196
+ ? 'Workspace is running'
197
+ : liveStatus === 'stopped'
198
+ ? 'Workspace is idle (will start automatically when needed)'
199
+ : liveStatus === 'provisioning'
200
+ ? 'Workspace is being provisioned...'
201
+ : 'Workspace has an error',
202
+ actionNeeded: liveStatus === 'stopped'
203
+ ? 'wakeup'
204
+ : liveStatus === 'error'
205
+ ? 'check_error'
206
+ : null,
207
+ });
208
+ }
209
+ catch (error) {
210
+ console.error('Error getting primary workspace:', error);
211
+ res.status(500).json({ error: 'Failed to get primary workspace' });
212
+ }
213
+ });
93
214
  /**
94
215
  * GET /api/workspaces/:id
95
216
  * Get workspace details
@@ -147,7 +268,17 @@ workspacesRouter.get('/:id/status', async (req, res) => {
147
268
  }
148
269
  const provisioner = getProvisioner();
149
270
  const status = await provisioner.getStatus(id);
150
- res.json({ status });
271
+ // Include provisioning progress info if it exists (even after status changes to 'running')
272
+ // This allows the frontend to see all stages including 'complete'
273
+ const provisioningProgress = getProvisioningStage(id);
274
+ res.json({
275
+ status,
276
+ provisioning: provisioningProgress ? {
277
+ stage: provisioningProgress.stage,
278
+ startedAt: provisioningProgress.startedAt,
279
+ elapsedMs: Date.now() - provisioningProgress.startedAt,
280
+ } : null,
281
+ });
151
282
  }
152
283
  catch (error) {
153
284
  console.error('Error getting workspace status:', error);
@@ -256,6 +387,77 @@ workspacesRouter.post('/:id/repos', async (req, res) => {
256
387
  res.status(500).json({ error: 'Failed to add repositories' });
257
388
  }
258
389
  });
390
+ /**
391
+ * POST /api/workspaces/:id/autoscale
392
+ * Trigger auto-scaling based on current agent count
393
+ * Supports both user session auth and workspace token auth
394
+ * Called by workspace container when spawning new agents
395
+ */
396
+ workspacesRouter.post('/:id/autoscale', async (req, res) => {
397
+ const { id } = req.params;
398
+ const { agentCount } = req.body;
399
+ if (typeof agentCount !== 'number' || agentCount < 0) {
400
+ return res.status(400).json({ error: 'agentCount must be a non-negative number' });
401
+ }
402
+ try {
403
+ const workspace = await db.workspaces.findById(id);
404
+ if (!workspace) {
405
+ return res.status(404).json({ error: 'Workspace not found' });
406
+ }
407
+ // Verify auth: either user session or workspace token
408
+ const userId = req.session?.userId;
409
+ const authHeader = req.get('authorization');
410
+ if (userId) {
411
+ // User session auth
412
+ if (workspace.userId !== userId) {
413
+ return res.status(403).json({ error: 'Unauthorized' });
414
+ }
415
+ }
416
+ else if (authHeader?.startsWith('Bearer ')) {
417
+ // Workspace token auth (for calls from within the workspace)
418
+ const crypto = await import('crypto');
419
+ const config = getConfig();
420
+ const providedToken = authHeader.slice(7);
421
+ const expectedToken = crypto.default
422
+ .createHmac('sha256', config.sessionSecret)
423
+ .update(`workspace:${id}`)
424
+ .digest('hex');
425
+ const isValid = crypto.default.timingSafeEqual(Buffer.from(providedToken), Buffer.from(expectedToken));
426
+ if (!isValid) {
427
+ return res.status(401).json({ error: 'Invalid workspace token' });
428
+ }
429
+ }
430
+ else {
431
+ return res.status(401).json({ error: 'Authentication required' });
432
+ }
433
+ const provisioner = getProvisioner();
434
+ const currentTier = await provisioner.getCurrentTier(id);
435
+ const recommendedTier = provisioner.getRecommendedTier(agentCount);
436
+ // Check if scaling is needed
437
+ if (recommendedTier.memoryMb <= currentTier.memoryMb) {
438
+ return res.json({
439
+ scaled: false,
440
+ currentTier: currentTier.name,
441
+ message: 'Current tier is sufficient',
442
+ });
443
+ }
444
+ // Perform the scale-up (respects plan limits)
445
+ const result = await provisioner.autoScale(id, agentCount);
446
+ res.json({
447
+ scaled: result.scaled,
448
+ previousTier: result.currentTier || currentTier.name,
449
+ newTier: result.targetTier || currentTier.name,
450
+ reason: result.reason,
451
+ message: result.scaled
452
+ ? `Scaled up to ${result.targetTier} tier`
453
+ : result.reason || 'Scaling not required',
454
+ });
455
+ }
456
+ catch (error) {
457
+ console.error('Error auto-scaling workspace:', error);
458
+ res.status(500).json({ error: 'Failed to auto-scale workspace' });
459
+ }
460
+ });
259
461
  /**
260
462
  * POST /api/workspaces/:id/domain
261
463
  * Add or update custom domain (Premium feature - Team/Enterprise only)
@@ -304,7 +506,7 @@ workspacesRouter.post('/:id/domain', async (req, res) => {
304
506
  instructions: {
305
507
  type: 'CNAME',
306
508
  name: domain,
307
- value: workspace.publicUrl?.replace('https://', '') || `${id}.agentrelay.dev`,
509
+ value: workspace.publicUrl?.replace('https://', '') || `${id}.agent-relay.com`,
308
510
  ttl: 300,
309
511
  },
310
512
  verifyEndpoint: `/api/workspaces/${id}/domain/verify`,
@@ -338,7 +540,7 @@ workspacesRouter.post('/:id/domain/verify', async (req, res) => {
338
540
  const dns = await import('dns').then(m => m.promises);
339
541
  try {
340
542
  const records = await dns.resolveCname(workspace.customDomain);
341
- const expectedTarget = workspace.publicUrl?.replace('https://', '') || `${id}.agentrelay.dev`;
543
+ const expectedTarget = workspace.publicUrl?.replace('https://', '') || `${id}.agent-relay.com`;
342
544
  if (records.some(r => r.includes(expectedTarget) || r.includes('agentrelay'))) {
343
545
  // DNS is configured, now provision SSL cert
344
546
  await db.workspaces.updateCustomDomainStatus(id, 'verifying');
@@ -457,9 +659,117 @@ async function removeDomainFromCompute(workspace) {
457
659
  }
458
660
  // Railway and Docker: similar cleanup
459
661
  }
662
+ /**
663
+ * POST /api/workspaces/:id/proxy/*
664
+ * Proxy API requests to the workspace container
665
+ * This allows the dashboard to make REST calls through the cloud server
666
+ */
667
+ workspacesRouter.all('/:id/proxy/{*proxyPath}', async (req, res) => {
668
+ const userId = req.session.userId;
669
+ const { id } = req.params;
670
+ // Express 5 wildcard params return an array of path segments, not a slash-separated string
671
+ const proxyPathParam = req.params.proxyPath;
672
+ const proxyPath = Array.isArray(proxyPathParam) ? proxyPathParam.join('/') : proxyPathParam;
673
+ try {
674
+ const workspace = await db.workspaces.findById(id);
675
+ if (!workspace) {
676
+ return res.status(404).json({ error: 'Workspace not found' });
677
+ }
678
+ if (workspace.userId !== userId) {
679
+ return res.status(403).json({ error: 'Unauthorized' });
680
+ }
681
+ if (workspace.status !== 'running' || !workspace.publicUrl) {
682
+ return res.status(400).json({ error: 'Workspace is not running' });
683
+ }
684
+ // Determine the internal URL for proxying
685
+ // When running inside Docker or Fly.io, use internal networking
686
+ let targetBaseUrl = workspace.publicUrl;
687
+ const runningInDocker = process.env.RUNNING_IN_DOCKER === 'true';
688
+ const runningOnFly = !!process.env.FLY_APP_NAME;
689
+ if (runningOnFly && targetBaseUrl.includes('.fly.dev')) {
690
+ // Use Fly.io internal networking (.internal uses IPv6, works by default)
691
+ // ar-583f273b.fly.dev -> http://ar-583f273b.internal:3888
692
+ const appName = targetBaseUrl.match(/https?:\/\/([^.]+)\.fly\.dev/)?.[1];
693
+ if (appName) {
694
+ targetBaseUrl = `http://${appName}.internal:3888`;
695
+ }
696
+ }
697
+ else if (runningInDocker && workspace.computeId && targetBaseUrl.includes('localhost')) {
698
+ // Replace localhost URL with container name for Docker networking
699
+ // workspace.computeId is the container name (e.g., "ar-abc12345")
700
+ // The workspace port is 3888 inside the container
701
+ targetBaseUrl = `http://${workspace.computeId}:3888`;
702
+ }
703
+ const targetUrl = `${targetBaseUrl}/api/${proxyPath}`;
704
+ console.log(`[workspace-proxy] ${req.method} ${targetUrl}`);
705
+ // Store targetUrl for error handling
706
+ req._proxyTargetUrl = targetUrl;
707
+ // Add timeout to prevent hanging requests
708
+ const controller = new AbortController();
709
+ const timeout = setTimeout(() => controller.abort(), 15000); // 15s timeout
710
+ const fetchOptions = {
711
+ method: req.method,
712
+ headers: {
713
+ 'Content-Type': 'application/json',
714
+ },
715
+ signal: controller.signal,
716
+ };
717
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
718
+ fetchOptions.body = JSON.stringify(req.body);
719
+ }
720
+ let proxyRes;
721
+ try {
722
+ proxyRes = await fetch(targetUrl, fetchOptions);
723
+ }
724
+ finally {
725
+ clearTimeout(timeout);
726
+ }
727
+ console.log(`[workspace-proxy] Response: ${proxyRes.status} ${proxyRes.statusText}`);
728
+ // Handle non-JSON responses gracefully
729
+ const contentType = proxyRes.headers.get('content-type');
730
+ if (contentType?.includes('application/json')) {
731
+ const data = await proxyRes.json();
732
+ res.status(proxyRes.status).json(data);
733
+ }
734
+ else {
735
+ const text = await proxyRes.text();
736
+ res.status(proxyRes.status).send(text);
737
+ }
738
+ }
739
+ catch (error) {
740
+ const targetUrl = req._proxyTargetUrl || 'unknown';
741
+ console.error('[workspace-proxy] Error proxying to:', targetUrl);
742
+ console.error('[workspace-proxy] Error details:', error);
743
+ // Check for timeout/abort errors
744
+ if (error instanceof Error && error.name === 'AbortError') {
745
+ res.status(504).json({
746
+ error: 'Workspace request timed out',
747
+ details: 'The workspace did not respond within 15 seconds',
748
+ targetUrl: targetUrl,
749
+ });
750
+ return;
751
+ }
752
+ // Check for connection refused (workspace not running)
753
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
754
+ if (errorMessage.includes('ECONNREFUSED') || errorMessage.includes('fetch failed')) {
755
+ res.status(503).json({
756
+ error: 'Workspace is not reachable',
757
+ details: 'The workspace container may not be running or accepting connections',
758
+ targetUrl: targetUrl,
759
+ });
760
+ return;
761
+ }
762
+ res.status(500).json({
763
+ error: 'Failed to proxy request to workspace',
764
+ details: errorMessage,
765
+ targetUrl: targetUrl, // Include target URL for debugging
766
+ });
767
+ }
768
+ });
460
769
  /**
461
770
  * POST /api/workspaces/quick
462
771
  * Quick provision: one-click with defaults
772
+ * Providers are optional - can be connected after workspace creation via CLI login
463
773
  */
464
774
  workspacesRouter.post('/quick', checkWorkspaceLimit, async (req, res) => {
465
775
  const userId = req.session.userId;
@@ -468,23 +778,18 @@ workspacesRouter.post('/quick', checkWorkspaceLimit, async (req, res) => {
468
778
  return res.status(400).json({ error: 'Repository name is required' });
469
779
  }
470
780
  try {
471
- // Get user's connected providers
781
+ // Get user's connected providers (optional now)
472
782
  const credentials = await db.credentials.findByUserId(userId);
473
783
  const providers = credentials
474
784
  .filter((c) => c.provider !== 'github')
475
785
  .map((c) => c.provider);
476
- if (providers.length === 0) {
477
- return res.status(400).json({
478
- error: 'No AI providers connected. Please connect at least one provider.',
479
- });
480
- }
481
786
  // Create workspace with defaults
482
787
  const provisioner = getProvisioner();
483
788
  const workspaceName = name || `Workspace for ${repositoryFullName}`;
484
789
  const result = await provisioner.provision({
485
790
  userId,
486
791
  name: workspaceName,
487
- providers,
792
+ providers: providers.length > 0 ? providers : [], // Empty is OK now
488
793
  repositories: [repositoryFullName],
489
794
  supervisorEnabled: true,
490
795
  maxAgents: 10,
@@ -499,7 +804,10 @@ workspacesRouter.post('/quick', checkWorkspaceLimit, async (req, res) => {
499
804
  workspaceId: result.workspaceId,
500
805
  status: result.status,
501
806
  publicUrl: result.publicUrl,
502
- message: 'Workspace provisioned successfully!',
807
+ providersConnected: providers.length > 0,
808
+ message: providers.length > 0
809
+ ? 'Workspace provisioned successfully!'
810
+ : 'Workspace provisioned! Connect an AI provider to start using agents.',
503
811
  });
504
812
  }
505
813
  catch (error) {
@@ -10,56 +10,59 @@ export const BILLING_PLANS = {
10
10
  free: {
11
11
  id: 'free',
12
12
  name: 'Free',
13
- description: 'For individuals exploring AI agent workflows',
13
+ description: 'Try AI agent workflows with limited access',
14
14
  priceMonthly: 0,
15
15
  priceYearly: 0,
16
16
  limits: {
17
- maxWorkspaces: 2,
18
- maxAgentsPerWorkspace: 3,
17
+ maxWorkspaces: 1,
18
+ maxAgentsPerWorkspace: 2,
19
19
  maxTeamMembers: 1,
20
20
  maxStorageGB: 1,
21
- maxComputeHoursPerMonth: 10,
21
+ maxComputeHoursPerMonth: 5, // Limited to 5 hours/month
22
22
  customDomains: false,
23
23
  prioritySupport: false,
24
24
  sla: false,
25
25
  ssoEnabled: false,
26
26
  auditLogs: false,
27
+ sessionPersistence: false,
27
28
  },
28
29
  features: [
29
- 'Up to 2 workspaces',
30
- 'Up to 3 agents per workspace',
31
- '10 compute hours/month',
32
- '1 GB storage',
30
+ '1 workspace',
31
+ 'Up to 2 agents',
32
+ '5 compute hours/month',
33
+ 'Shared CPU (may throttle)',
33
34
  'Community support',
34
35
  ],
35
36
  },
36
37
  pro: {
37
38
  id: 'pro',
38
39
  name: 'Pro',
39
- description: 'For professional developers and small teams',
40
- priceMonthly: 2900, // $29/month
41
- priceYearly: 29000, // $290/year (2 months free)
40
+ description: 'For professional developers building with AI agents',
41
+ priceMonthly: 4900, // $49/month
42
+ priceYearly: 47000, // $470/year (2 months free)
42
43
  stripePriceIdMonthly: process.env.STRIPE_PRO_MONTHLY_PRICE_ID,
43
44
  stripePriceIdYearly: process.env.STRIPE_PRO_YEARLY_PRICE_ID,
44
45
  limits: {
45
- maxWorkspaces: 10,
46
- maxAgentsPerWorkspace: 10,
47
- maxTeamMembers: 5,
46
+ maxWorkspaces: 5,
47
+ maxAgentsPerWorkspace: 5,
48
+ maxTeamMembers: 3,
48
49
  maxStorageGB: 10,
49
- maxComputeHoursPerMonth: 100,
50
+ maxComputeHoursPerMonth: 50,
50
51
  customDomains: true,
51
52
  prioritySupport: false,
52
53
  sla: false,
53
54
  ssoEnabled: false,
54
55
  auditLogs: false,
56
+ sessionPersistence: true,
55
57
  },
56
58
  features: [
57
- 'Up to 10 workspaces',
58
- 'Up to 10 agents per workspace',
59
- '100 compute hours/month',
59
+ 'Up to 5 workspaces',
60
+ 'Up to 5 agents per workspace',
61
+ '50 compute hours/month',
60
62
  '10 GB storage',
61
- '5 team members',
63
+ '3 team members',
62
64
  'Custom domains',
65
+ 'Session persistence',
63
66
  'Email support',
64
67
  ],
65
68
  },
@@ -82,6 +85,7 @@ export const BILLING_PLANS = {
82
85
  sla: false,
83
86
  ssoEnabled: false,
84
87
  auditLogs: true,
88
+ sessionPersistence: true,
85
89
  },
86
90
  features: [
87
91
  'Up to 50 workspaces',
@@ -90,6 +94,7 @@ export const BILLING_PLANS = {
90
94
  '50 GB storage',
91
95
  '25 team members',
92
96
  'Custom domains',
97
+ 'Session persistence',
93
98
  'Priority support',
94
99
  'Audit logs',
95
100
  ],
@@ -113,6 +118,7 @@ export const BILLING_PLANS = {
113
118
  sla: true,
114
119
  ssoEnabled: true,
115
120
  auditLogs: true,
121
+ sessionPersistence: true,
116
122
  },
117
123
  features: [
118
124
  'Unlimited workspaces',
@@ -121,6 +127,7 @@ export const BILLING_PLANS = {
121
127
  '500 GB storage',
122
128
  'Unlimited team members',
123
129
  'Custom domains',
130
+ 'Session persistence',
124
131
  'Priority support with SLA',
125
132
  'SSO/SAML integration',
126
133
  'Audit logs & compliance',
@@ -227,6 +234,12 @@ export function comparePlans(from, to) {
227
234
  else if (!toPlan.limits.auditLogs && fromPlan.limits.auditLogs) {
228
235
  downgrades.push('Audit logs');
229
236
  }
237
+ if (toPlan.limits.sessionPersistence && !fromPlan.limits.sessionPersistence) {
238
+ upgrades.push('Session persistence');
239
+ }
240
+ else if (!toPlan.limits.sessionPersistence && fromPlan.limits.sessionPersistence) {
241
+ downgrades.push('Session persistence');
242
+ }
230
243
  return { upgrades, downgrades };
231
244
  }
232
245
  //# sourceMappingURL=plans.js.map
@@ -18,13 +18,17 @@ export interface BillingPlan {
18
18
  priceYearly: number;
19
19
  stripePriceIdMonthly?: string;
20
20
  stripePriceIdYearly?: string;
21
- limits: PlanLimits;
21
+ limits: BillingPlanLimits;
22
22
  features: string[];
23
23
  }
24
24
  /**
25
- * Resource limits per plan
25
+ * Resource limits per plan for billing/display purposes.
26
+ * These limits are shown to customers on pricing pages and in account settings.
27
+ *
28
+ * Note: For runtime limit checking (API enforcement), use PlanLimits from
29
+ * src/cloud/services/planLimits.ts which has a focused subset of limits.
26
30
  */
27
- export interface PlanLimits {
31
+ export interface BillingPlanLimits {
28
32
  maxWorkspaces: number;
29
33
  maxAgentsPerWorkspace: number;
30
34
  maxTeamMembers: number;
@@ -35,6 +39,8 @@ export interface PlanLimits {
35
39
  sla: boolean;
36
40
  ssoEnabled: boolean;
37
41
  auditLogs: boolean;
42
+ /** Cloud session persistence (summaries, session tracking) - Pro+ only */
43
+ sessionPersistence: boolean;
38
44
  }
39
45
  /**
40
46
  * Customer billing information
@@ -10,8 +10,7 @@ export interface CloudConfig {
10
10
  github: {
11
11
  clientId: string;
12
12
  clientSecret: string;
13
- appId?: string;
14
- appPrivateKey?: string;
13
+ webhookSecret?: string;
15
14
  };
16
15
  providers: {
17
16
  anthropic?: {
@@ -35,11 +34,19 @@ export interface CloudConfig {
35
34
  org: string;
36
35
  region?: string;
37
36
  workspaceDomain?: string;
37
+ registryAuth?: {
38
+ username: string;
39
+ password: string;
40
+ };
38
41
  };
39
42
  railway?: {
40
43
  apiToken: string;
41
44
  };
42
45
  };
46
+ nango: {
47
+ secretKey: string;
48
+ host?: string;
49
+ };
43
50
  stripe: {
44
51
  secretKey: string;
45
52
  publishableKey: string;
@@ -13,16 +13,15 @@ function optionalEnv(name) {
13
13
  }
14
14
  export function loadConfig() {
15
15
  return {
16
- port: parseInt(process.env.PORT || '3000', 10),
17
- publicUrl: process.env.PUBLIC_URL || 'http://localhost:3000',
16
+ port: parseInt(process.env.PORT || '4567', 10),
17
+ publicUrl: process.env.PUBLIC_URL || 'http://localhost:4567',
18
18
  sessionSecret: requireEnv('SESSION_SECRET'),
19
19
  databaseUrl: requireEnv('DATABASE_URL'),
20
20
  redisUrl: process.env.REDIS_URL || 'redis://localhost:6379',
21
21
  github: {
22
22
  clientId: requireEnv('GITHUB_CLIENT_ID'),
23
23
  clientSecret: requireEnv('GITHUB_CLIENT_SECRET'),
24
- appId: optionalEnv('GITHUB_APP_ID'),
25
- appPrivateKey: optionalEnv('GITHUB_APP_PRIVATE_KEY'),
24
+ webhookSecret: optionalEnv('GITHUB_WEBHOOK_SECRET'),
26
25
  },
27
26
  providers: {
28
27
  anthropic: optionalEnv('ANTHROPIC_CLIENT_ID')
@@ -49,6 +48,12 @@ export function loadConfig() {
49
48
  org: optionalEnv('FLY_ORG') || 'personal',
50
49
  region: optionalEnv('FLY_REGION') || 'sjc',
51
50
  workspaceDomain: optionalEnv('FLY_WORKSPACE_DOMAIN'),
51
+ registryAuth: optionalEnv('GHCR_USERNAME') && optionalEnv('GHCR_TOKEN')
52
+ ? {
53
+ username: optionalEnv('GHCR_USERNAME'),
54
+ password: optionalEnv('GHCR_TOKEN'),
55
+ }
56
+ : undefined,
52
57
  }
53
58
  : undefined,
54
59
  railway: optionalEnv('RAILWAY_API_TOKEN')
@@ -57,6 +62,10 @@ export function loadConfig() {
57
62
  }
58
63
  : undefined,
59
64
  },
65
+ nango: {
66
+ secretKey: requireEnv('NANGO_SECRET_KEY'),
67
+ host: optionalEnv('NANGO_HOST'),
68
+ },
60
69
  stripe: {
61
70
  secretKey: requireEnv('STRIPE_SECRET_KEY'),
62
71
  publishableKey: requireEnv('STRIPE_PUBLISHABLE_KEY'),