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
@@ -2,59 +2,62 @@
2
2
  * Onboarding API Routes
3
3
  *
4
4
  * Handles CLI proxy authentication for Claude Code and other providers.
5
- * Spawns CLI tools to get auth URLs, captures tokens.
5
+ * Spawns CLI tools via PTY to get auth URLs, captures tokens.
6
+ *
7
+ * We use node-pty instead of child_process.spawn because:
8
+ * 1. Many CLIs detect if they're in a TTY and behave differently
9
+ * 2. Interactive OAuth flows often require TTY for proper output
10
+ * 3. PTY ensures the CLI outputs auth URLs correctly
6
11
  */
7
12
  import { Router } from 'express';
8
- import { spawn } from 'child_process';
9
- import crypto from 'crypto';
13
+ import * as crypto from 'crypto';
10
14
  import { requireAuth } from './auth.js';
11
15
  import { db } from '../db/index.js';
12
16
  import { vault } from '../vault/index.js';
17
+ // Import for local use
18
+ import { CLI_AUTH_CONFIG, runCLIAuthViaPTY, stripAnsiCodes, matchesSuccessPattern, findMatchingPrompt, validateProviderConfig, validateAllProviderConfigs, getSupportedProviders, } from './cli-pty-runner.js';
19
+ // Re-export from shared module for backward compatibility
20
+ export { CLI_AUTH_CONFIG, runCLIAuthViaPTY, stripAnsiCodes, matchesSuccessPattern, findMatchingPrompt, validateProviderConfig, validateAllProviderConfigs, getSupportedProviders, };
13
21
  export const onboardingRouter = Router();
22
+ // Debug: log all requests to this router
23
+ onboardingRouter.use((req, res, next) => {
24
+ console.log(`[onboarding] ${req.method} ${req.path} - body:`, JSON.stringify(req.body));
25
+ next();
26
+ });
14
27
  // All routes require authentication
15
28
  onboardingRouter.use(requireAuth);
16
29
  const activeSessions = new Map();
17
30
  // Clean up old sessions periodically
18
31
  setInterval(() => {
19
32
  const now = Date.now();
20
- for (const [id, session] of activeSessions) {
33
+ activeSessions.forEach((session, id) => {
21
34
  // Remove sessions older than 10 minutes
22
35
  if (now - session.createdAt.getTime() > 10 * 60 * 1000) {
23
36
  if (session.process) {
24
- session.process.kill();
37
+ try {
38
+ session.process.kill();
39
+ }
40
+ catch {
41
+ // Process may already be dead
42
+ }
25
43
  }
26
44
  activeSessions.delete(id);
27
45
  }
28
- }
46
+ });
29
47
  }, 60000);
30
- /**
31
- * CLI commands and URL patterns for each provider
32
- */
33
- const CLI_AUTH_CONFIG = {
34
- anthropic: {
35
- // Claude Code CLI login
36
- command: 'claude',
37
- args: ['login', '--no-open'],
38
- // Claude outputs: "Please open: https://..."
39
- urlPattern: /(?:open|visit|go to)[:\s]+(\S+anthropic\S+)/i,
40
- // Token might be in output or in credentials file
41
- credentialPath: '~/.claude/credentials.json',
42
- },
43
- openai: {
44
- // Codex CLI auth
45
- command: 'codex',
46
- args: ['auth', '--no-browser'],
47
- urlPattern: /(?:open|visit|go to)[:\s]+(\S+openai\S+)/i,
48
- credentialPath: '~/.codex/credentials.json',
49
- },
50
- };
51
48
  /**
52
49
  * POST /api/onboarding/cli/:provider/start
53
- * Start CLI-based auth - spawns the CLI and captures auth URL
50
+ * Start CLI-based auth - forwards to workspace daemon if available
51
+ *
52
+ * CLI auth requires a running workspace since CLI tools are installed there.
53
+ * For onboarding without a workspace, users should use the API key flow.
54
54
  */
55
55
  onboardingRouter.post('/cli/:provider/start', async (req, res) => {
56
+ console.log('[onboarding] Route handler entered! provider:', req.params.provider);
56
57
  const { provider } = req.params;
57
58
  const userId = req.session.userId;
59
+ const { workspaceId, useDeviceFlow } = req.body; // Optional: specific workspace, device flow option
60
+ console.log('[onboarding] userId:', userId, 'workspaceId:', workspaceId, 'useDeviceFlow:', useDeviceFlow);
58
61
  const config = CLI_AUTH_CONFIG[provider];
59
62
  if (!config) {
60
63
  return res.status(400).json({
@@ -62,93 +65,108 @@ onboardingRouter.post('/cli/:provider/start', async (req, res) => {
62
65
  supportedProviders: Object.keys(CLI_AUTH_CONFIG),
63
66
  });
64
67
  }
65
- // Create session
66
- const sessionId = crypto.randomUUID();
67
- const session = {
68
- userId,
69
- provider,
70
- status: 'starting',
71
- createdAt: new Date(),
72
- };
73
- activeSessions.set(sessionId, session);
74
68
  try {
75
- // Spawn CLI process
76
- const proc = spawn(config.command, config.args, {
77
- env: { ...process.env, NO_COLOR: '1' },
78
- stdio: ['pipe', 'pipe', 'pipe'],
79
- });
80
- session.process = proc;
81
- let _output = '';
82
- // Capture stdout/stderr for auth URL
83
- const handleOutput = (data) => {
84
- const text = data.toString();
85
- _output += text;
86
- // Look for auth URL
87
- const match = text.match(config.urlPattern);
88
- if (match && match[1]) {
89
- session.authUrl = match[1];
90
- session.status = 'waiting_auth';
91
- }
92
- // Look for success indicators
93
- if (text.toLowerCase().includes('success') ||
94
- text.toLowerCase().includes('authenticated') ||
95
- text.toLowerCase().includes('logged in')) {
96
- session.status = 'success';
97
- }
98
- };
99
- proc.stdout.on('data', handleOutput);
100
- proc.stderr.on('data', handleOutput);
101
- proc.on('error', (err) => {
102
- session.status = 'error';
103
- session.error = `Failed to start CLI: ${err.message}`;
104
- });
105
- proc.on('exit', async (code) => {
106
- if (code === 0 && session.status !== 'error') {
107
- session.status = 'success';
108
- // Try to read credentials from file
109
- await extractCredentials(session, config);
69
+ // Find a running workspace to use for CLI auth
70
+ let workspace;
71
+ if (workspaceId) {
72
+ workspace = await db.workspaces.findById(workspaceId);
73
+ if (!workspace) {
74
+ console.log(`[onboarding] Workspace ${workspaceId} not found in database`);
75
+ return res.status(404).json({ error: 'Workspace not found' });
110
76
  }
111
- else if (session.status === 'starting') {
112
- session.status = 'error';
113
- session.error = `CLI exited with code ${code}`;
77
+ if (workspace.userId !== userId) {
78
+ console.log(`[onboarding] Workspace ${workspaceId} belongs to ${workspace.userId}, not ${userId}`);
79
+ return res.status(404).json({ error: 'Workspace not found' });
114
80
  }
115
- });
116
- // Wait a moment for URL to appear
117
- await new Promise(resolve => setTimeout(resolve, 2000));
118
- // Return session info
119
- if (session.authUrl) {
120
- res.json({
121
- sessionId,
122
- status: 'waiting_auth',
123
- authUrl: session.authUrl,
124
- message: 'Open the auth URL to complete login',
81
+ }
82
+ else {
83
+ // Find any running workspace for this user
84
+ const workspaces = await db.workspaces.findByUserId(userId);
85
+ workspace = workspaces.find(w => w.status === 'running' && w.publicUrl);
86
+ }
87
+ if (!workspace || workspace.status !== 'running' || !workspace.publicUrl) {
88
+ return res.status(400).json({
89
+ error: 'CLI auth requires a running workspace',
90
+ code: 'NO_RUNNING_WORKSPACE',
91
+ message: 'Please start a workspace first, or use the API key input to connect your provider.',
92
+ hint: 'You can create a workspace without providers and connect them afterward using CLI auth.',
125
93
  });
126
94
  }
127
- else if (session.status === 'error') {
128
- activeSessions.delete(sessionId);
129
- res.status(500).json({ error: session.error || 'CLI auth failed to start' });
95
+ // Forward auth request to workspace daemon
96
+ // When running in Docker, localhost refers to the container, not the host
97
+ // Use host.docker.internal on Mac/Windows to reach the host machine
98
+ // When running on Fly.io, use internal networking (.internal) instead of public DNS
99
+ let workspaceUrl = workspace.publicUrl.replace(/\/$/, '');
100
+ // Detect Fly.io by checking FLY_APP_NAME env var
101
+ const isOnFly = !!process.env.FLY_APP_NAME;
102
+ // Detect Docker by checking for /.dockerenv file or RUNNING_IN_DOCKER env var
103
+ const isInDocker = process.env.RUNNING_IN_DOCKER === 'true' ||
104
+ await import('fs').then(fs => fs.existsSync('/.dockerenv')).catch(() => false);
105
+ console.log('[onboarding] isOnFly:', isOnFly, 'isInDocker:', isInDocker);
106
+ if (isOnFly && workspaceUrl.includes('.fly.dev')) {
107
+ // Use Fly.io internal networking for server-to-server communication
108
+ // ar-583f273b.fly.dev -> http://ar-583f273b.internal:3888
109
+ // .internal uses IPv6 and works by default for apps in the same org
110
+ const appName = workspaceUrl.match(/https?:\/\/([^.]+)\.fly\.dev/)?.[1];
111
+ if (appName) {
112
+ workspaceUrl = `http://${appName}.internal:3888`;
113
+ console.log('[onboarding] Using Fly internal network:', workspaceUrl);
114
+ }
130
115
  }
131
- else {
132
- // Still starting, return session ID to poll
133
- res.json({
134
- sessionId,
135
- status: 'starting',
136
- message: 'Auth session starting, poll for status',
116
+ else if (isInDocker && workspaceUrl.includes('localhost')) {
117
+ workspaceUrl = workspaceUrl.replace('localhost', 'host.docker.internal');
118
+ console.log('[onboarding] Translated localhost to host.docker.internal');
119
+ }
120
+ const targetUrl = `${workspaceUrl}/auth/cli/${provider}/start`;
121
+ console.log('[onboarding] Forwarding to workspace daemon:', targetUrl);
122
+ const authResponse = await fetch(targetUrl, {
123
+ method: 'POST',
124
+ headers: { 'Content-Type': 'application/json' },
125
+ body: JSON.stringify({ useDeviceFlow }),
126
+ });
127
+ console.log('[onboarding] Workspace daemon response:', authResponse.status);
128
+ if (!authResponse.ok) {
129
+ const errorData = await authResponse.json().catch(() => ({}));
130
+ console.log('[onboarding] Workspace daemon error:', errorData);
131
+ return res.status(authResponse.status).json({
132
+ error: errorData.error || 'Failed to start CLI auth in workspace',
137
133
  });
138
134
  }
135
+ const workspaceSession = await authResponse.json();
136
+ // Create cloud session to track this
137
+ const sessionId = crypto.randomUUID();
138
+ const session = {
139
+ userId,
140
+ provider,
141
+ status: workspaceSession.status || 'starting',
142
+ authUrl: workspaceSession.authUrl,
143
+ createdAt: new Date(),
144
+ output: '',
145
+ // Store workspace info for status polling and auth code forwarding
146
+ workspaceUrl,
147
+ workspaceSessionId: workspaceSession.sessionId,
148
+ };
149
+ activeSessions.set(sessionId, session);
150
+ console.log('[onboarding] Session created:', { sessionId, workspaceUrl, workspaceSessionId: workspaceSession.sessionId });
151
+ res.json({
152
+ sessionId,
153
+ status: session.status,
154
+ authUrl: session.authUrl,
155
+ workspaceId: workspace.id,
156
+ message: session.authUrl ? 'Open the auth URL to complete login' : 'Auth session starting, poll for status',
157
+ });
139
158
  }
140
159
  catch (error) {
141
- activeSessions.delete(sessionId);
142
160
  console.error(`Error starting CLI auth for ${provider}:`, error);
143
161
  res.status(500).json({ error: 'Failed to start CLI authentication' });
144
162
  }
145
163
  });
146
164
  /**
147
165
  * GET /api/onboarding/cli/:provider/status/:sessionId
148
- * Check status of CLI auth session
166
+ * Check status of CLI auth session - forwards to workspace daemon
149
167
  */
150
- onboardingRouter.get('/cli/:provider/status/:sessionId', (req, res) => {
151
- const { sessionId } = req.params;
168
+ onboardingRouter.get('/cli/:provider/status/:sessionId', async (req, res) => {
169
+ const { provider, sessionId } = req.params;
152
170
  const userId = req.session.userId;
153
171
  const session = activeSessions.get(sessionId);
154
172
  if (!session) {
@@ -157,6 +175,22 @@ onboardingRouter.get('/cli/:provider/status/:sessionId', (req, res) => {
157
175
  if (session.userId !== userId) {
158
176
  return res.status(403).json({ error: 'Unauthorized' });
159
177
  }
178
+ // If we have workspace info, poll the workspace for status
179
+ if (session.workspaceUrl && session.workspaceSessionId) {
180
+ try {
181
+ const statusResponse = await fetch(`${session.workspaceUrl}/auth/cli/${provider}/status/${session.workspaceSessionId}`);
182
+ if (statusResponse.ok) {
183
+ const workspaceStatus = await statusResponse.json();
184
+ // Update local session with workspace status
185
+ session.status = workspaceStatus.status || session.status;
186
+ session.authUrl = workspaceStatus.authUrl || session.authUrl;
187
+ session.error = workspaceStatus.error;
188
+ }
189
+ }
190
+ catch (err) {
191
+ console.error('[onboarding] Failed to poll workspace status:', err);
192
+ }
193
+ }
160
194
  res.json({
161
195
  status: session.status,
162
196
  authUrl: session.authUrl,
@@ -166,11 +200,16 @@ onboardingRouter.get('/cli/:provider/status/:sessionId', (req, res) => {
166
200
  /**
167
201
  * POST /api/onboarding/cli/:provider/complete/:sessionId
168
202
  * Mark CLI auth as complete and store credentials
203
+ *
204
+ * Handles two modes:
205
+ * 1. Workspace delegation: Forwards to workspace daemon to complete auth, then fetches credentials
206
+ * 2. Direct: Uses token from body or session
169
207
  */
170
208
  onboardingRouter.post('/cli/:provider/complete/:sessionId', async (req, res) => {
171
209
  const { provider, sessionId } = req.params;
172
210
  const userId = req.session.userId;
173
- const { token } = req.body; // Optional: user can paste token directly
211
+ const { token, authCode } = req.body; // token for direct mode, authCode for Codex redirect
212
+ console.log(`[onboarding] POST /cli/${provider}/complete/${sessionId} - token: ${token ? 'provided' : 'none'}, authCode: ${authCode ? 'provided' : 'none'}`);
174
213
  const session = activeSessions.get(sessionId);
175
214
  if (!session) {
176
215
  return res.status(404).json({ error: 'Session not found or expired' });
@@ -179,14 +218,49 @@ onboardingRouter.post('/cli/:provider/complete/:sessionId', async (req, res) =>
179
218
  return res.status(403).json({ error: 'Unauthorized' });
180
219
  }
181
220
  try {
182
- // If token provided directly, use it
183
221
  let accessToken = token || session.token;
184
- // If no token yet, try to read from credentials file
185
- if (!accessToken) {
186
- const config = CLI_AUTH_CONFIG[provider];
187
- if (config) {
188
- await extractCredentials(session, config);
189
- accessToken = session.token;
222
+ let refreshToken = session.refreshToken;
223
+ let tokenExpiresAt = session.tokenExpiresAt;
224
+ // If using workspace delegation, forward complete request first
225
+ if (session.workspaceUrl && session.workspaceSessionId) {
226
+ // Forward authCode to workspace if provided (for Codex-style redirects)
227
+ if (authCode) {
228
+ const backendProviderId = provider === 'anthropic' ? 'anthropic' : provider;
229
+ const targetUrl = `${session.workspaceUrl}/auth/cli/${backendProviderId}/complete/${session.workspaceSessionId}`;
230
+ console.log('[onboarding] Forwarding complete request to workspace:', targetUrl);
231
+ const completeResponse = await fetch(targetUrl, {
232
+ method: 'POST',
233
+ headers: { 'Content-Type': 'application/json' },
234
+ body: JSON.stringify({ authCode }),
235
+ });
236
+ if (!completeResponse.ok) {
237
+ const errorData = await completeResponse.json().catch(() => ({}));
238
+ return res.status(completeResponse.status).json({
239
+ error: errorData.error || 'Failed to complete authentication in workspace',
240
+ });
241
+ }
242
+ session.status = 'success';
243
+ }
244
+ // Fetch credentials from workspace
245
+ if (!accessToken) {
246
+ try {
247
+ const credsResponse = await fetch(`${session.workspaceUrl}/auth/cli/${provider}/creds/${session.workspaceSessionId}`);
248
+ if (credsResponse.ok) {
249
+ const creds = await credsResponse.json();
250
+ accessToken = creds.token;
251
+ refreshToken = creds.refreshToken;
252
+ if (creds.expiresAt) {
253
+ tokenExpiresAt = new Date(creds.expiresAt);
254
+ }
255
+ console.log('[onboarding] Fetched credentials from workspace:', {
256
+ hasToken: !!accessToken,
257
+ hasRefreshToken: !!refreshToken,
258
+ });
259
+ }
260
+ }
261
+ catch (err) {
262
+ console.error('[onboarding] Failed to get credentials from workspace:', err);
263
+ }
190
264
  }
191
265
  }
192
266
  if (!accessToken) {
@@ -194,17 +268,16 @@ onboardingRouter.post('/cli/:provider/complete/:sessionId', async (req, res) =>
194
268
  error: 'No token found. Please complete authentication or paste your token.',
195
269
  });
196
270
  }
197
- // Store in vault
271
+ // Store in vault with refresh token and expiry
198
272
  await vault.storeCredential({
199
273
  userId,
200
274
  provider,
201
275
  accessToken,
276
+ refreshToken,
277
+ tokenExpiresAt,
202
278
  scopes: getProviderScopes(provider),
203
279
  });
204
280
  // Clean up session
205
- if (session.process) {
206
- session.process.kill();
207
- }
208
281
  activeSessions.delete(sessionId);
209
282
  res.json({
210
283
  success: true,
@@ -216,17 +289,93 @@ onboardingRouter.post('/cli/:provider/complete/:sessionId', async (req, res) =>
216
289
  res.status(500).json({ error: 'Failed to complete authentication' });
217
290
  }
218
291
  });
292
+ /**
293
+ * POST /api/onboarding/cli/:provider/code/:sessionId
294
+ * Submit auth code to the CLI PTY session
295
+ * Used when OAuth returns a code that must be pasted into the CLI
296
+ */
297
+ onboardingRouter.post('/cli/:provider/code/:sessionId', async (req, res) => {
298
+ const { provider, sessionId } = req.params;
299
+ const userId = req.session.userId;
300
+ const { code } = req.body;
301
+ console.log('[onboarding] Auth code submission request:', { provider, sessionId, codeLength: code?.length });
302
+ if (!code || typeof code !== 'string') {
303
+ return res.status(400).json({ error: 'Auth code is required' });
304
+ }
305
+ const session = activeSessions.get(sessionId);
306
+ if (!session) {
307
+ console.log('[onboarding] Session not found:', { sessionId, activeSessions: Array.from(activeSessions.keys()) });
308
+ return res.status(404).json({ error: 'Session not found or expired. Please try connecting again.' });
309
+ }
310
+ if (session.userId !== userId) {
311
+ return res.status(403).json({ error: 'Unauthorized' });
312
+ }
313
+ console.log('[onboarding] Session found:', {
314
+ sessionId,
315
+ workspaceUrl: session.workspaceUrl,
316
+ workspaceSessionId: session.workspaceSessionId,
317
+ status: session.status,
318
+ });
319
+ // Forward to workspace daemon
320
+ if (session.workspaceUrl && session.workspaceSessionId) {
321
+ try {
322
+ const targetUrl = `${session.workspaceUrl}/auth/cli/${provider}/code/${session.workspaceSessionId}`;
323
+ console.log('[onboarding] Forwarding auth code to workspace:', targetUrl);
324
+ const codeResponse = await fetch(targetUrl, {
325
+ method: 'POST',
326
+ headers: { 'Content-Type': 'application/json' },
327
+ body: JSON.stringify({ code }),
328
+ });
329
+ console.log('[onboarding] Workspace response:', { status: codeResponse.status });
330
+ if (codeResponse.ok) {
331
+ return res.json({ success: true, message: 'Auth code submitted' });
332
+ }
333
+ const errorData = await codeResponse.json().catch(() => ({}));
334
+ console.log('[onboarding] Workspace error:', errorData);
335
+ // Provide more helpful error message
336
+ const needsRestart = errorData.needsRestart;
337
+ if (codeResponse.status === 404 || codeResponse.status === 400) {
338
+ return res.status(400).json({
339
+ error: errorData.error || 'Auth session expired in workspace. The CLI process may have timed out. Please try connecting again.',
340
+ needsRestart: needsRestart ?? true,
341
+ });
342
+ }
343
+ return res.status(codeResponse.status).json({
344
+ error: errorData.error || 'Failed to submit auth code to workspace',
345
+ needsRestart,
346
+ });
347
+ }
348
+ catch (err) {
349
+ console.error('[onboarding] Failed to submit auth code to workspace:', err);
350
+ return res.status(500).json({
351
+ error: 'Failed to reach workspace. Please ensure your workspace is running and try again.',
352
+ });
353
+ }
354
+ }
355
+ console.log('[onboarding] No workspace session info available');
356
+ return res.status(400).json({
357
+ error: 'No workspace session available. This can happen if the workspace was restarted. Please try connecting again.',
358
+ });
359
+ });
360
+ // Note: POST /cli/:provider/complete/:sessionId handler is defined above (lines 269-368)
361
+ // It handles both direct token storage and workspace delegation with authCode forwarding
219
362
  /**
220
363
  * POST /api/onboarding/cli/:provider/cancel/:sessionId
221
364
  * Cancel a CLI auth session
222
365
  */
223
- onboardingRouter.post('/cli/:provider/cancel/:sessionId', (req, res) => {
224
- const { sessionId } = req.params;
366
+ onboardingRouter.post('/cli/:provider/cancel/:sessionId', async (req, res) => {
367
+ const { provider, sessionId } = req.params;
225
368
  const userId = req.session.userId;
226
369
  const session = activeSessions.get(sessionId);
227
370
  if (session?.userId === userId) {
228
- if (session.process) {
229
- session.process.kill();
371
+ // Cancel on workspace side if applicable
372
+ if (session.workspaceUrl && session.workspaceSessionId) {
373
+ try {
374
+ await fetch(`${session.workspaceUrl}/auth/cli/${provider}/cancel/${session.workspaceSessionId}`, { method: 'POST' });
375
+ }
376
+ catch {
377
+ // Ignore cancel errors
378
+ }
230
379
  }
231
380
  activeSessions.delete(sessionId);
232
381
  }
@@ -319,8 +468,9 @@ onboardingRouter.post('/complete', async (req, res) => {
319
468
  });
320
469
  /**
321
470
  * Helper: Extract credentials from CLI credential file
471
+ * @deprecated Currently unused - kept for potential future use
322
472
  */
323
- async function extractCredentials(session, config) {
473
+ async function _extractCredentials(session, config) {
324
474
  if (!config.credentialPath)
325
475
  return;
326
476
  try {
@@ -331,12 +481,31 @@ async function extractCredentials(session, config) {
331
481
  const creds = JSON.parse(content);
332
482
  // Extract token based on provider structure
333
483
  if (session.provider === 'anthropic') {
334
- // Claude stores: { "oauth_token": "...", ... } or { "api_key": "..." }
335
- session.token = creds.oauth_token || creds.access_token || creds.api_key;
484
+ // Claude stores OAuth in: { claudeAiOauth: { accessToken: "...", refreshToken: "...", expiresAt: ... } }
485
+ if (creds.claudeAiOauth?.accessToken) {
486
+ session.token = creds.claudeAiOauth.accessToken;
487
+ session.refreshToken = creds.claudeAiOauth.refreshToken;
488
+ if (creds.claudeAiOauth.expiresAt) {
489
+ session.tokenExpiresAt = new Date(creds.claudeAiOauth.expiresAt);
490
+ }
491
+ }
492
+ else {
493
+ // Fallback to legacy formats
494
+ session.token = creds.oauth_token || creds.access_token || creds.api_key;
495
+ }
336
496
  }
337
497
  else if (session.provider === 'openai') {
338
- // Codex might store: { "token": "..." } or { "api_key": "..." }
339
- session.token = creds.token || creds.access_token || creds.api_key;
498
+ // Codex stores OAuth in: { tokens: { access_token: "...", refresh_token: "...", ... } }
499
+ if (creds.tokens?.access_token) {
500
+ session.token = creds.tokens.access_token;
501
+ session.refreshToken = creds.tokens.refresh_token;
502
+ // Codex doesn't store expiry in the file, but JWTs have exp claim
503
+ // We could decode it, but for now just skip
504
+ }
505
+ else {
506
+ // Fallback: API key or legacy formats
507
+ session.token = creds.OPENAI_API_KEY || creds.token || creds.access_token || creds.api_key;
508
+ }
340
509
  }
341
510
  }
342
511
  catch (error) {
@@ -358,9 +527,34 @@ function getProviderScopes(provider) {
358
527
  }
359
528
  /**
360
529
  * Helper: Validate a provider token by making a test API call
530
+ *
531
+ * Note: OAuth tokens from CLI flows (like `claude` CLI) are different from API keys.
532
+ * - API keys: sk-ant-api03-... (can be validated via API)
533
+ * - OAuth tokens: Session tokens from OAuth flow (can't be validated the same way)
534
+ *
535
+ * For OAuth tokens, we accept them if they look valid (non-empty, reasonable length).
536
+ * The CLI already validated the OAuth flow, so we trust those tokens.
361
537
  */
362
538
  async function validateProviderToken(provider, token) {
539
+ // Basic sanity check
540
+ if (!token || token.length < 10) {
541
+ return false;
542
+ }
363
543
  try {
544
+ // Check if this looks like an API key vs OAuth token
545
+ const isAnthropicApiKey = token.startsWith('sk-ant-');
546
+ const isOpenAIApiKey = token.startsWith('sk-');
547
+ // For OAuth tokens (not API keys), accept them without API validation
548
+ // The OAuth flow already authenticated the user
549
+ if (provider === 'anthropic' && !isAnthropicApiKey) {
550
+ console.log('[onboarding] Accepting OAuth token for anthropic (not an API key)');
551
+ return true;
552
+ }
553
+ if (provider === 'openai' && !isOpenAIApiKey) {
554
+ console.log('[onboarding] Accepting OAuth token for openai (not an API key)');
555
+ return true;
556
+ }
557
+ // For API keys, validate via API call
364
558
  const endpoints = {
365
559
  anthropic: {
366
560
  url: 'https://api.anthropic.com/v1/messages',
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Agent Policy API Routes
3
+ *
4
+ * Provides endpoints for managing workspace-level agent policies.
5
+ * These policies serve as fallbacks when repos don't have .claude/policies/ files.
6
+ */
7
+ export declare const policyRouter: import("express-serve-static-core").Router;
8
+ //# sourceMappingURL=policy.d.ts.map