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.
- package/.gitattributes +3 -0
- package/.nvmrc +1 -0
- package/.trajectories/completed/2026-01/traj_1dviorhnkcb5.json +65 -0
- package/.trajectories/completed/2026-01/traj_1dviorhnkcb5.md +37 -0
- package/.trajectories/completed/2026-01/traj_1k5if5snst2e.json +65 -0
- package/.trajectories/completed/2026-01/traj_1k5if5snst2e.md +37 -0
- package/.trajectories/completed/2026-01/traj_1rp3rges5811.json +49 -0
- package/.trajectories/completed/2026-01/traj_1rp3rges5811.md +31 -0
- package/.trajectories/completed/2026-01/traj_22bhyulruouw.json +113 -0
- package/.trajectories/completed/2026-01/traj_22bhyulruouw.md +57 -0
- package/.trajectories/completed/2026-01/traj_2dao7ddgnta0.json +53 -0
- package/.trajectories/completed/2026-01/traj_2dao7ddgnta0.md +32 -0
- package/.trajectories/completed/2026-01/traj_3t0440mjeunc.json +26 -0
- package/.trajectories/completed/2026-01/traj_3t0440mjeunc.md +6 -0
- package/.trajectories/completed/2026-01/traj_45x9494d9xnr.json +47 -0
- package/.trajectories/completed/2026-01/traj_45x9494d9xnr.md +32 -0
- package/.trajectories/completed/2026-01/traj_4aa0bb77s4nh.json +53 -0
- package/.trajectories/completed/2026-01/traj_4aa0bb77s4nh.md +32 -0
- package/.trajectories/completed/2026-01/traj_5lhmzq8rxpqv.json +59 -0
- package/.trajectories/completed/2026-01/traj_5lhmzq8rxpqv.md +33 -0
- package/.trajectories/completed/2026-01/traj_5vr4e9erb1fs.json +53 -0
- package/.trajectories/completed/2026-01/traj_5vr4e9erb1fs.md +32 -0
- package/.trajectories/completed/2026-01/traj_6fgiwdoklvym.json +48 -0
- package/.trajectories/completed/2026-01/traj_6fgiwdoklvym.md +24 -0
- package/.trajectories/completed/2026-01/traj_7ludwvz45veh.json +209 -0
- package/.trajectories/completed/2026-01/traj_7ludwvz45veh.md +97 -0
- package/.trajectories/completed/2026-01/traj_9921cuhel0pj.json +48 -0
- package/.trajectories/completed/2026-01/traj_9921cuhel0pj.md +24 -0
- package/.trajectories/completed/2026-01/traj_ajs7zqfux4wc.json +49 -0
- package/.trajectories/completed/2026-01/traj_ajs7zqfux4wc.md +23 -0
- package/.trajectories/completed/2026-01/traj_cvtqhlwcq9s0.json +53 -0
- package/.trajectories/completed/2026-01/traj_cvtqhlwcq9s0.md +32 -0
- package/.trajectories/completed/2026-01/traj_cxofprm2m2en.json +49 -0
- package/.trajectories/completed/2026-01/traj_cxofprm2m2en.md +31 -0
- package/.trajectories/completed/2026-01/traj_d2hhz3k0vrhn.json +26 -0
- package/.trajectories/completed/2026-01/traj_d2hhz3k0vrhn.md +6 -0
- package/.trajectories/completed/2026-01/traj_dfuvww9pege5.json +59 -0
- package/.trajectories/completed/2026-01/traj_dfuvww9pege5.md +37 -0
- package/.trajectories/completed/2026-01/traj_g0fisy9h51mf.json +77 -0
- package/.trajectories/completed/2026-01/traj_g0fisy9h51mf.md +42 -0
- package/.trajectories/completed/2026-01/traj_gjdre5voouod.json +53 -0
- package/.trajectories/completed/2026-01/traj_gjdre5voouod.md +32 -0
- package/.trajectories/completed/2026-01/traj_gtlyqtta3x8l.json +25 -0
- package/.trajectories/completed/2026-01/traj_gtlyqtta3x8l.md +15 -0
- package/.trajectories/completed/2026-01/traj_h4xijiuip3w4.json +101 -0
- package/.trajectories/completed/2026-01/traj_h4xijiuip3w4.md +44 -0
- package/.trajectories/completed/2026-01/traj_hhxte7w4gjjx.json +22 -0
- package/.trajectories/completed/2026-01/traj_hhxte7w4gjjx.md +5 -0
- package/.trajectories/completed/2026-01/traj_hpungyhoj6v5.json +53 -0
- package/.trajectories/completed/2026-01/traj_hpungyhoj6v5.md +32 -0
- package/.trajectories/completed/2026-01/traj_m2xkjv0w2sq7.json +25 -0
- package/.trajectories/completed/2026-01/traj_m2xkjv0w2sq7.md +15 -0
- package/.trajectories/completed/2026-01/traj_noq5zbvnrdvz.json +53 -0
- package/.trajectories/completed/2026-01/traj_noq5zbvnrdvz.md +32 -0
- package/.trajectories/completed/2026-01/traj_ntbs6ppopf46.json +53 -0
- package/.trajectories/completed/2026-01/traj_ntbs6ppopf46.md +32 -0
- package/.trajectories/completed/2026-01/traj_ozd98si6a7ns.json +48 -0
- package/.trajectories/completed/2026-01/traj_ozd98si6a7ns.md +24 -0
- package/.trajectories/completed/2026-01/traj_prdza7a5cxp5.json +53 -0
- package/.trajectories/completed/2026-01/traj_prdza7a5cxp5.md +32 -0
- package/.trajectories/completed/2026-01/traj_qb3twvvywfwi.json +77 -0
- package/.trajectories/completed/2026-01/traj_qb3twvvywfwi.md +42 -0
- package/.trajectories/completed/2026-01/traj_qft54mi7nfor.json +53 -0
- package/.trajectories/completed/2026-01/traj_qft54mi7nfor.md +32 -0
- package/.trajectories/completed/2026-01/traj_qx9uhf8whhxo.json +83 -0
- package/.trajectories/completed/2026-01/traj_qx9uhf8whhxo.md +47 -0
- package/.trajectories/completed/2026-01/traj_rd9toccj18a0.json +59 -0
- package/.trajectories/completed/2026-01/traj_rd9toccj18a0.md +37 -0
- package/.trajectories/completed/2026-01/traj_rt4fiw3ecp50.json +48 -0
- package/.trajectories/completed/2026-01/traj_rt4fiw3ecp50.md +16 -0
- package/.trajectories/completed/2026-01/traj_st8j35b0hrlc.json +59 -0
- package/.trajectories/completed/2026-01/traj_st8j35b0hrlc.md +37 -0
- package/.trajectories/completed/2026-01/traj_t1yy8m7hbuxp.json +53 -0
- package/.trajectories/completed/2026-01/traj_t1yy8m7hbuxp.md +32 -0
- package/.trajectories/completed/2026-01/traj_tmux_orchestrator_analysis.json +84 -0
- package/.trajectories/completed/2026-01/traj_tmux_orchestrator_analysis.md +109 -0
- package/.trajectories/completed/2026-01/traj_u9n9eqasw16k.json +53 -0
- package/.trajectories/completed/2026-01/traj_u9n9eqasw16k.md +32 -0
- package/.trajectories/completed/2026-01/traj_v87hypnongqx.json +71 -0
- package/.trajectories/completed/2026-01/traj_v87hypnongqx.md +42 -0
- package/.trajectories/completed/2026-01/traj_wkp2fgzdyinb.json +53 -0
- package/.trajectories/completed/2026-01/traj_wkp2fgzdyinb.md +32 -0
- package/.trajectories/completed/2026-01/traj_x14t8w8rn7xg.json +20 -0
- package/.trajectories/completed/2026-01/traj_x14t8w8rn7xg.md +6 -0
- package/.trajectories/completed/2026-01/traj_xnwbznkvv8ua.json +175 -0
- package/.trajectories/completed/2026-01/traj_xnwbznkvv8ua.md +82 -0
- package/.trajectories/completed/2026-01/traj_ysjc8zaeqtd3.json +47 -0
- package/.trajectories/completed/2026-01/traj_ysjc8zaeqtd3.md +32 -0
- package/.trajectories/completed/2026-01/traj_yvdadtvdgnz3.json +59 -0
- package/.trajectories/completed/2026-01/traj_yvdadtvdgnz3.md +37 -0
- package/.trajectories/completed/2026-01/traj_z0vcw1wrzide.json +53 -0
- package/.trajectories/completed/2026-01/traj_z0vcw1wrzide.md +32 -0
- package/.trajectories/index.json +314 -0
- package/ARCHITECTURE.md +1245 -0
- package/README.md +1 -1
- package/TESTING.md +278 -0
- package/deploy/init-db.sql +5 -0
- package/deploy/scripts/setup-fly-workspaces.sh +69 -0
- package/deploy/scripts/setup-railway.sh +75 -0
- package/deploy/workspace/entrypoint-browser.sh +118 -0
- package/deploy/workspace/entrypoint.sh +348 -0
- package/deploy/workspace/git-credential-relay +111 -0
- package/dist/bridge/spawner.d.ts +53 -0
- package/dist/bridge/spawner.js +203 -19
- package/dist/bridge/types.d.ts +12 -0
- package/dist/cli/index.js +618 -5
- package/dist/cloud/api/auth.d.ts +3 -2
- package/dist/cloud/api/auth.js +10 -98
- package/dist/cloud/api/billing.js +30 -9
- package/dist/cloud/api/cli-pty-runner.d.ts +54 -0
- package/dist/cloud/api/cli-pty-runner.js +119 -0
- package/dist/cloud/api/codex-auth-helper.d.ts +15 -0
- package/dist/cloud/api/codex-auth-helper.js +100 -0
- package/dist/cloud/api/generic-webhooks.d.ts +8 -0
- package/dist/cloud/api/generic-webhooks.js +129 -0
- package/dist/cloud/api/git.d.ts +8 -0
- package/dist/cloud/api/git.js +152 -0
- package/dist/cloud/api/github-app.d.ts +11 -0
- package/dist/cloud/api/github-app.js +189 -0
- package/dist/cloud/api/middleware/planLimits.d.ts +7 -0
- package/dist/cloud/api/middleware/planLimits.js +39 -1
- package/dist/cloud/api/monitoring.d.ts +11 -0
- package/dist/cloud/api/monitoring.js +578 -0
- package/dist/cloud/api/nango-auth.d.ts +9 -0
- package/dist/cloud/api/nango-auth.js +377 -0
- package/dist/cloud/api/onboarding.d.ts +8 -1
- package/dist/cloud/api/onboarding.js +313 -119
- package/dist/cloud/api/policy.d.ts +8 -0
- package/dist/cloud/api/policy.js +229 -0
- package/dist/cloud/api/providers.js +114 -42
- package/dist/cloud/api/repos.d.ts +1 -0
- package/dist/cloud/api/repos.js +186 -0
- package/dist/cloud/api/test-helpers.d.ts +10 -0
- package/dist/cloud/api/test-helpers.js +575 -0
- package/dist/cloud/api/webhooks.d.ts +8 -0
- package/dist/cloud/api/webhooks.js +645 -0
- package/dist/cloud/api/workspaces.js +320 -12
- package/dist/cloud/billing/plans.js +32 -19
- package/dist/cloud/billing/types.d.ts +9 -3
- package/dist/cloud/config.d.ts +9 -2
- package/dist/cloud/config.js +13 -4
- package/dist/cloud/db/drizzle.d.ts +84 -1
- package/dist/cloud/db/drizzle.js +470 -0
- package/dist/cloud/db/index.d.ts +9 -4
- package/dist/cloud/db/index.js +11 -3
- package/dist/cloud/db/schema.d.ts +3283 -556
- package/dist/cloud/db/schema.js +314 -1
- package/dist/cloud/index.d.ts +1 -0
- package/dist/cloud/index.js +2 -0
- package/dist/cloud/provisioner/index.d.ts +56 -0
- package/dist/cloud/provisioner/index.js +676 -34
- package/dist/cloud/server.d.ts +1 -0
- package/dist/cloud/server.js +362 -13
- package/dist/cloud/services/auto-scaler.d.ts +152 -0
- package/dist/cloud/services/auto-scaler.js +439 -0
- package/dist/cloud/services/capacity-manager.d.ts +148 -0
- package/dist/cloud/services/capacity-manager.js +449 -0
- package/dist/cloud/services/ci-agent-spawner.d.ts +49 -0
- package/dist/cloud/services/ci-agent-spawner.js +373 -0
- package/dist/cloud/services/index.d.ts +12 -0
- package/dist/cloud/services/index.js +15 -0
- package/dist/cloud/services/mention-handler.d.ts +65 -0
- package/dist/cloud/services/mention-handler.js +405 -0
- package/dist/cloud/services/nango.d.ts +186 -0
- package/dist/cloud/services/nango.js +344 -0
- package/dist/cloud/services/persistence.d.ts +131 -0
- package/dist/cloud/services/persistence.js +200 -0
- package/dist/cloud/services/planLimits.d.ts +37 -0
- package/dist/cloud/services/planLimits.js +86 -5
- package/dist/cloud/services/scaling-orchestrator.d.ts +159 -0
- package/dist/cloud/services/scaling-orchestrator.js +502 -0
- package/dist/cloud/services/scaling-policy.d.ts +121 -0
- package/dist/cloud/services/scaling-policy.js +415 -0
- package/dist/cloud/vault/index.js +1 -1
- package/dist/cloud/webhooks/index.d.ts +24 -0
- package/dist/cloud/webhooks/index.js +29 -0
- package/dist/cloud/webhooks/parsers/github.d.ts +8 -0
- package/dist/cloud/webhooks/parsers/github.js +234 -0
- package/dist/cloud/webhooks/parsers/index.d.ts +23 -0
- package/dist/cloud/webhooks/parsers/index.js +30 -0
- package/dist/cloud/webhooks/parsers/linear.d.ts +9 -0
- package/dist/cloud/webhooks/parsers/linear.js +258 -0
- package/dist/cloud/webhooks/parsers/slack.d.ts +9 -0
- package/dist/cloud/webhooks/parsers/slack.js +214 -0
- package/dist/cloud/webhooks/responders/github.d.ts +8 -0
- package/dist/cloud/webhooks/responders/github.js +73 -0
- package/dist/cloud/webhooks/responders/index.d.ts +23 -0
- package/dist/cloud/webhooks/responders/index.js +30 -0
- package/dist/cloud/webhooks/responders/linear.d.ts +9 -0
- package/dist/cloud/webhooks/responders/linear.js +149 -0
- package/dist/cloud/webhooks/responders/slack.d.ts +20 -0
- package/dist/cloud/webhooks/responders/slack.js +178 -0
- package/dist/cloud/webhooks/router.d.ts +25 -0
- package/dist/cloud/webhooks/router.js +504 -0
- package/dist/cloud/webhooks/rules-engine.d.ts +24 -0
- package/dist/cloud/webhooks/rules-engine.js +287 -0
- package/dist/cloud/webhooks/types.d.ts +186 -0
- package/dist/cloud/webhooks/types.js +8 -0
- package/dist/continuity/formatter.d.ts +51 -0
- package/dist/continuity/formatter.js +313 -0
- package/dist/continuity/handoff-store.d.ts +67 -0
- package/dist/continuity/handoff-store.js +472 -0
- package/dist/continuity/index.d.ts +45 -0
- package/dist/continuity/index.js +48 -0
- package/dist/continuity/ledger-store.d.ts +110 -0
- package/dist/continuity/ledger-store.js +500 -0
- package/dist/continuity/manager.d.ts +178 -0
- package/dist/continuity/manager.js +562 -0
- package/dist/continuity/parser.d.ts +76 -0
- package/dist/continuity/parser.js +579 -0
- package/dist/continuity/types.d.ts +180 -0
- package/dist/continuity/types.js +9 -0
- package/dist/daemon/agent-manager.d.ts +27 -0
- package/dist/daemon/agent-manager.js +107 -6
- package/dist/daemon/agent-registry.d.ts +32 -0
- package/dist/daemon/agent-registry.js +42 -2
- package/dist/daemon/api.d.ts +12 -0
- package/dist/daemon/api.js +131 -2
- package/dist/daemon/cli-auth.d.ts +67 -0
- package/dist/daemon/cli-auth.js +537 -0
- package/dist/daemon/cloud-sync.js +9 -7
- package/dist/daemon/orchestrator.js +30 -0
- package/dist/daemon/router.d.ts +5 -0
- package/dist/daemon/router.js +78 -26
- package/dist/daemon/server.d.ts +5 -0
- package/dist/daemon/server.js +9 -1
- package/dist/daemon/services/browser-testing.d.ts +88 -0
- package/dist/daemon/services/browser-testing.js +244 -0
- package/dist/daemon/services/container-spawner.d.ts +135 -0
- package/dist/daemon/services/container-spawner.js +313 -0
- package/dist/daemon/types.d.ts +5 -1
- package/dist/dashboard/out/404.html +1 -1
- package/dist/dashboard/out/_next/static/chunks/116-2502180def231162.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/282-980c2eb8fff20123.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/699-3b1cd6618a45d259.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/724-2dae7627550ab88f.js +9 -0
- package/dist/dashboard/out/_next/static/chunks/766-1f2dd8cb7f766b0b.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/app/onboarding/page-3fdfa60e53f2810d.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/app/page-e6381e5a6e1fbcfd.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/connect-repos/page-3538dfe0ffe984b8.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/history/{page-b6edd4dde8d08194.js → page-abb9ab2d329f56e9.js} +1 -1
- package/dist/dashboard/out/_next/static/chunks/app/layout-c0d118c0f92d969c.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/login/page-c22d080201cbd9fb.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/metrics/page-67a3e98d9a43a6ed.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/page-77e9c65420a06cfb.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/pricing/page-b08ed1c34d14434a.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/providers/page-e88bc117ef7671c3.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/app/signup/page-68d34f50baa8ab6b.js +1 -0
- package/dist/dashboard/out/_next/static/chunks/e868780c-48e5f147c90a3a41.js +18 -0
- package/dist/dashboard/out/_next/static/chunks/{main-app-5d692157a8eb1fd9.js → main-app-6e8e8d3ef4e0192a.js} +1 -1
- package/dist/dashboard/out/_next/static/chunks/{main-c2f423b9c9f4591b.js → main-ed4e1fb6f29c34cf.js} +1 -1
- package/dist/dashboard/out/_next/static/chunks/webpack-1cdd8ed57114d5e1.js +1 -0
- package/dist/dashboard/out/_next/static/css/29852f26181969a0.css +1 -0
- package/dist/dashboard/out/_next/static/css/7c3ae9e8617d42a5.css +1 -0
- package/dist/dashboard/out/app/onboarding.html +1 -0
- package/dist/dashboard/out/app/onboarding.txt +7 -0
- package/dist/dashboard/out/app.html +1 -14
- package/dist/dashboard/out/app.txt +2 -2
- package/dist/dashboard/out/connect-repos.html +1 -0
- package/dist/dashboard/out/connect-repos.txt +7 -0
- package/dist/dashboard/out/history.html +1 -1
- package/dist/dashboard/out/history.txt +2 -2
- package/dist/dashboard/out/index.html +1 -1
- package/dist/dashboard/out/index.txt +2 -2
- package/dist/dashboard/out/login.html +6 -0
- package/dist/dashboard/out/login.txt +7 -0
- package/dist/dashboard/out/metrics.html +1 -1
- package/dist/dashboard/out/metrics.txt +2 -2
- package/dist/dashboard/out/pricing.html +3 -3
- package/dist/dashboard/out/pricing.txt +2 -2
- package/dist/dashboard/out/providers.html +1 -0
- package/dist/dashboard/out/providers.txt +7 -0
- package/dist/dashboard/out/signup.html +6 -0
- package/dist/dashboard/out/signup.txt +7 -0
- package/dist/dashboard-server/server.js +1308 -8
- package/dist/hooks/emitter.d.ts +40 -0
- package/dist/hooks/emitter.js +63 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.js +3 -0
- package/dist/hooks/registry.d.ts +173 -0
- package/dist/hooks/registry.js +476 -0
- package/dist/hooks/trajectory-hooks.d.ts +52 -0
- package/dist/hooks/trajectory-hooks.js +183 -0
- package/dist/hooks/types.d.ts +141 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/memory/adapters/index.d.ts +8 -0
- package/dist/memory/adapters/index.js +8 -0
- package/dist/memory/adapters/inmemory.d.ts +59 -0
- package/dist/memory/adapters/inmemory.js +195 -0
- package/dist/memory/adapters/supermemory.d.ts +71 -0
- package/dist/memory/adapters/supermemory.js +338 -0
- package/dist/memory/factory.d.ts +48 -0
- package/dist/memory/factory.js +143 -0
- package/dist/memory/index.d.ts +32 -0
- package/dist/memory/index.js +32 -0
- package/dist/memory/memory-hooks.d.ts +60 -0
- package/dist/memory/memory-hooks.js +313 -0
- package/dist/memory/service.d.ts +49 -0
- package/dist/memory/service.js +146 -0
- package/dist/memory/types.d.ts +195 -0
- package/dist/memory/types.js +8 -0
- package/dist/policy/agent-policy.d.ts +225 -0
- package/dist/policy/agent-policy.js +665 -0
- package/dist/policy/cloud-policy-fetcher.d.ts +12 -0
- package/dist/policy/cloud-policy-fetcher.js +64 -0
- package/dist/resiliency/crash-insights.d.ts +156 -0
- package/dist/resiliency/crash-insights.js +492 -0
- package/dist/resiliency/gossip-health.d.ts +137 -0
- package/dist/resiliency/gossip-health.js +241 -0
- package/dist/resiliency/index.d.ts +5 -0
- package/dist/resiliency/index.js +5 -0
- package/dist/resiliency/leader-watchdog.d.ts +109 -0
- package/dist/resiliency/leader-watchdog.js +189 -0
- package/dist/resiliency/memory-monitor.d.ts +172 -0
- package/dist/resiliency/memory-monitor.js +593 -0
- package/dist/resiliency/stateless-lead.d.ts +149 -0
- package/dist/resiliency/stateless-lead.js +308 -0
- package/dist/resiliency/supervisor.d.ts +38 -0
- package/dist/resiliency/supervisor.js +122 -0
- package/dist/shared/cli-auth-config.d.ts +91 -0
- package/dist/shared/cli-auth-config.js +264 -0
- package/dist/storage/adapter.d.ts +1 -1
- package/dist/trajectory/config.d.ts +84 -0
- package/dist/trajectory/config.js +163 -0
- package/dist/trajectory/index.d.ts +8 -0
- package/dist/trajectory/index.js +8 -0
- package/dist/trajectory/integration.d.ts +292 -0
- package/dist/trajectory/integration.js +834 -0
- package/dist/utils/logger.js +1 -1
- package/dist/utils/project-namespace.d.ts +24 -0
- package/dist/utils/project-namespace.js +84 -0
- package/dist/wrapper/parser.d.ts +10 -0
- package/dist/wrapper/parser.js +100 -33
- package/dist/wrapper/pty-wrapper.d.ts +197 -16
- package/dist/wrapper/pty-wrapper.js +943 -106
- package/dist/wrapper/shared.d.ts +165 -0
- package/dist/wrapper/shared.js +270 -0
- package/dist/wrapper/tmux-wrapper.d.ts +73 -11
- package/dist/wrapper/tmux-wrapper.js +541 -120
- package/package.json +16 -16
- package/scripts/postinstall.js +60 -0
- package/test-push.txt +1 -0
- package/bin/tmux +0 -0
- package/dist/bridge/config.d.ts.map +0 -1
- package/dist/bridge/config.js.map +0 -1
- package/dist/bridge/index.d.ts.map +0 -1
- package/dist/bridge/index.js.map +0 -1
- package/dist/bridge/multi-project-client.d.ts.map +0 -1
- package/dist/bridge/multi-project-client.js.map +0 -1
- package/dist/bridge/shadow-cli.d.ts.map +0 -1
- package/dist/bridge/shadow-cli.js.map +0 -1
- package/dist/bridge/shadow-config.d.ts.map +0 -1
- package/dist/bridge/shadow-config.js.map +0 -1
- package/dist/bridge/spawner.d.ts.map +0 -1
- package/dist/bridge/spawner.js.map +0 -1
- package/dist/bridge/teams-config.d.ts.map +0 -1
- package/dist/bridge/teams-config.js.map +0 -1
- package/dist/bridge/types.d.ts.map +0 -1
- package/dist/bridge/types.js.map +0 -1
- package/dist/bridge/utils.d.ts.map +0 -1
- package/dist/bridge/utils.js.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/cloud/api/auth.d.ts.map +0 -1
- package/dist/cloud/api/auth.js.map +0 -1
- package/dist/cloud/api/billing.d.ts.map +0 -1
- package/dist/cloud/api/billing.js.map +0 -1
- package/dist/cloud/api/coordinators.d.ts.map +0 -1
- package/dist/cloud/api/coordinators.js.map +0 -1
- package/dist/cloud/api/daemons.d.ts.map +0 -1
- package/dist/cloud/api/daemons.js.map +0 -1
- package/dist/cloud/api/middleware/planLimits.d.ts.map +0 -1
- package/dist/cloud/api/middleware/planLimits.js.map +0 -1
- package/dist/cloud/api/onboarding.d.ts.map +0 -1
- package/dist/cloud/api/onboarding.js.map +0 -1
- package/dist/cloud/api/providers.d.ts.map +0 -1
- package/dist/cloud/api/providers.js.map +0 -1
- package/dist/cloud/api/repos.d.ts.map +0 -1
- package/dist/cloud/api/repos.js.map +0 -1
- package/dist/cloud/api/teams.d.ts.map +0 -1
- package/dist/cloud/api/teams.js.map +0 -1
- package/dist/cloud/api/usage.d.ts.map +0 -1
- package/dist/cloud/api/usage.js.map +0 -1
- package/dist/cloud/api/workspaces.d.ts.map +0 -1
- package/dist/cloud/api/workspaces.js.map +0 -1
- package/dist/cloud/billing/index.d.ts.map +0 -1
- package/dist/cloud/billing/index.js.map +0 -1
- package/dist/cloud/billing/plans.d.ts.map +0 -1
- package/dist/cloud/billing/plans.js.map +0 -1
- package/dist/cloud/billing/service.d.ts.map +0 -1
- package/dist/cloud/billing/service.js.map +0 -1
- package/dist/cloud/billing/types.d.ts.map +0 -1
- package/dist/cloud/billing/types.js.map +0 -1
- package/dist/cloud/config.d.ts.map +0 -1
- package/dist/cloud/config.js.map +0 -1
- package/dist/cloud/db/drizzle.d.ts.map +0 -1
- package/dist/cloud/db/drizzle.js.map +0 -1
- package/dist/cloud/db/index.d.ts.map +0 -1
- package/dist/cloud/db/index.js.map +0 -1
- package/dist/cloud/db/schema.d.ts.map +0 -1
- package/dist/cloud/db/schema.js.map +0 -1
- package/dist/cloud/index.d.ts.map +0 -1
- package/dist/cloud/index.js.map +0 -1
- package/dist/cloud/provisioner/index.d.ts.map +0 -1
- package/dist/cloud/provisioner/index.js.map +0 -1
- package/dist/cloud/server.d.ts.map +0 -1
- package/dist/cloud/server.js.map +0 -1
- package/dist/cloud/services/coordinator.d.ts.map +0 -1
- package/dist/cloud/services/coordinator.js.map +0 -1
- package/dist/cloud/services/planLimits.d.ts.map +0 -1
- package/dist/cloud/services/planLimits.js.map +0 -1
- package/dist/cloud/vault/index.d.ts.map +0 -1
- package/dist/cloud/vault/index.js.map +0 -1
- package/dist/daemon/agent-manager.d.ts.map +0 -1
- package/dist/daemon/agent-manager.js.map +0 -1
- package/dist/daemon/agent-registry.d.ts.map +0 -1
- package/dist/daemon/agent-registry.js.map +0 -1
- package/dist/daemon/api.d.ts.map +0 -1
- package/dist/daemon/api.js.map +0 -1
- package/dist/daemon/auth.d.ts.map +0 -1
- package/dist/daemon/auth.js.map +0 -1
- package/dist/daemon/cloud-sync.d.ts.map +0 -1
- package/dist/daemon/cloud-sync.js.map +0 -1
- package/dist/daemon/connection.d.ts.map +0 -1
- package/dist/daemon/connection.js.map +0 -1
- package/dist/daemon/index.d.ts.map +0 -1
- package/dist/daemon/index.js.map +0 -1
- package/dist/daemon/orchestrator.d.ts.map +0 -1
- package/dist/daemon/orchestrator.js.map +0 -1
- package/dist/daemon/registry.d.ts.map +0 -1
- package/dist/daemon/registry.js.map +0 -1
- package/dist/daemon/router.d.ts.map +0 -1
- package/dist/daemon/router.js.map +0 -1
- package/dist/daemon/server.d.ts.map +0 -1
- package/dist/daemon/server.js.map +0 -1
- package/dist/daemon/types.d.ts.map +0 -1
- package/dist/daemon/types.js.map +0 -1
- package/dist/daemon/workspace-manager.d.ts.map +0 -1
- package/dist/daemon/workspace-manager.js.map +0 -1
- package/dist/dashboard/out/_next/static/chunks/693-7b3301d8f6bc5014.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/713-f78477eb185f1f4d.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/766-e53e1cfe39b0b5b5.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/900-037c64bfd797fb2a.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/app/page-e3d9e1f4466b9bae.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/layout-2433bb48965f4333.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/metrics/page-e68825a81db67ba1.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/page-cc108bf68c8a657f.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/app/pricing/page-d80e03a5297f95b6.js +0 -1
- package/dist/dashboard/out/_next/static/chunks/webpack-a5acc2831d094776.js +0 -1
- package/dist/dashboard/out/_next/static/css/79b80143647a07d7.css +0 -1
- package/dist/dashboard/out/_next/static/css/8cf277370ad48cfe.css +0 -1
- package/dist/dashboard-server/metrics.d.ts.map +0 -1
- package/dist/dashboard-server/metrics.js.map +0 -1
- package/dist/dashboard-server/needs-attention.d.ts.map +0 -1
- package/dist/dashboard-server/needs-attention.js.map +0 -1
- package/dist/dashboard-server/server.d.ts.map +0 -1
- package/dist/dashboard-server/server.js.map +0 -1
- package/dist/dashboard-server/start.d.ts.map +0 -1
- package/dist/dashboard-server/start.js.map +0 -1
- package/dist/hooks/inbox-check/hook.d.ts.map +0 -1
- package/dist/hooks/inbox-check/hook.js.map +0 -1
- package/dist/hooks/inbox-check/index.d.ts.map +0 -1
- package/dist/hooks/inbox-check/index.js.map +0 -1
- package/dist/hooks/inbox-check/types.d.ts.map +0 -1
- package/dist/hooks/inbox-check/types.js.map +0 -1
- package/dist/hooks/inbox-check/utils.d.ts.map +0 -1
- package/dist/hooks/inbox-check/utils.js.map +0 -1
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/types.d.ts.map +0 -1
- package/dist/hooks/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/protocol/framing.d.ts.map +0 -1
- package/dist/protocol/framing.js.map +0 -1
- package/dist/protocol/index.d.ts.map +0 -1
- package/dist/protocol/index.js.map +0 -1
- package/dist/protocol/types.d.ts.map +0 -1
- package/dist/protocol/types.js.map +0 -1
- package/dist/resiliency/context-persistence.d.ts.map +0 -1
- package/dist/resiliency/context-persistence.js.map +0 -1
- package/dist/resiliency/health-monitor.d.ts.map +0 -1
- package/dist/resiliency/health-monitor.js.map +0 -1
- package/dist/resiliency/index.d.ts.map +0 -1
- package/dist/resiliency/index.js.map +0 -1
- package/dist/resiliency/logger.d.ts.map +0 -1
- package/dist/resiliency/logger.js.map +0 -1
- package/dist/resiliency/metrics.d.ts.map +0 -1
- package/dist/resiliency/metrics.js.map +0 -1
- package/dist/resiliency/provider-context.d.ts.map +0 -1
- package/dist/resiliency/provider-context.js.map +0 -1
- package/dist/resiliency/supervisor.d.ts.map +0 -1
- package/dist/resiliency/supervisor.js.map +0 -1
- package/dist/state/agent-state.d.ts.map +0 -1
- package/dist/state/agent-state.js.map +0 -1
- package/dist/storage/adapter.d.ts.map +0 -1
- package/dist/storage/adapter.js.map +0 -1
- package/dist/storage/sqlite-adapter.d.ts.map +0 -1
- package/dist/storage/sqlite-adapter.js.map +0 -1
- package/dist/utils/agent-config.d.ts.map +0 -1
- package/dist/utils/agent-config.js.map +0 -1
- package/dist/utils/command-resolver.d.ts.map +0 -1
- package/dist/utils/command-resolver.js.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/name-generator.d.ts.map +0 -1
- package/dist/utils/name-generator.js.map +0 -1
- package/dist/utils/project-namespace.d.ts.map +0 -1
- package/dist/utils/project-namespace.js.map +0 -1
- package/dist/utils/tmux-resolver.d.ts.map +0 -1
- package/dist/utils/tmux-resolver.js.map +0 -1
- package/dist/utils/update-checker.d.ts.map +0 -1
- package/dist/utils/update-checker.js.map +0 -1
- package/dist/wrapper/client.d.ts.map +0 -1
- package/dist/wrapper/client.js.map +0 -1
- package/dist/wrapper/inbox.d.ts.map +0 -1
- package/dist/wrapper/inbox.js.map +0 -1
- package/dist/wrapper/index.d.ts.map +0 -1
- package/dist/wrapper/index.js.map +0 -1
- package/dist/wrapper/parser.d.ts.map +0 -1
- package/dist/wrapper/parser.js.map +0 -1
- package/dist/wrapper/pty-wrapper.d.ts.map +0 -1
- package/dist/wrapper/pty-wrapper.js.map +0 -1
- package/dist/wrapper/tmux-wrapper.d.ts.map +0 -1
- package/dist/wrapper/tmux-wrapper.js.map +0 -1
- package/docs/AGENTS.md +0 -513
- package/docs/ARCHITECTURE_DECISIONS.md +0 -175
- package/docs/CHANGELOG.md +0 -11
- package/docs/CLI-SIMPLIFICATION-COMPLETE.md +0 -48
- package/docs/CLOUD-ARCHITECTURE.md +0 -652
- package/docs/CLOUD-ONBOARDING-DESIGN.md +0 -1983
- package/docs/COMPETITIVE_ANALYSIS.md +0 -897
- package/docs/CONTRIBUTING.md +0 -151
- package/docs/DESIGN_BRIDGE_STAFFING.md +0 -878
- package/docs/DESIGN_V2.md +0 -1079
- package/docs/INTEGRATION-GUIDE.md +0 -926
- package/docs/MONETIZATION.md +0 -1679
- package/docs/PROPOSAL-trajectories.md +0 -1582
- package/docs/PROTOCOL.md +0 -325
- package/docs/SCALING_ANALYSIS.md +0 -280
- package/docs/TESTING_PRESENCE_FEATURES.md +0 -327
- package/docs/TMUX_IMPLEMENTATION_NOTES.md +0 -364
- package/docs/TMUX_IMPROVEMENTS.md +0 -968
- package/docs/agent-relay-snippet.md +0 -168
- package/docs/competitive-analysis-mcp-agent-mail.md +0 -389
- package/docs/dashboard-v2-plan.md +0 -179
- package/docs/guides/CLOUD.md +0 -236
- package/docs/guides/LOCAL.md +0 -535
- package/docs/guides/SELF-HOSTED.md +0 -494
- package/docs/proposals/shadow-as-subagent.md +0 -765
- package/docs/proposals/slack-bot-integration.md +0 -1457
- package/docs/removable-code-analysis.md +0 -24
- package/scripts/dev/PUBLIC_RELEASE_PLAN.md +0 -88
- package/scripts/dev/dev-team-setup.sh +0 -431
- package/scripts/e2e-test.sh +0 -119
- package/scripts/games/game-protocol.md +0 -79
- package/scripts/games/hearts-setup.sh +0 -264
- package/scripts/tictactoe-setup.sh +0 -181
- /package/dist/dashboard/out/_next/static/chunks/{117-b2cd8d6485aacf2b.js → 117-f7b8ab0809342e77.js} +0 -0
- /package/dist/dashboard/out/_next/static/chunks/{648-8f3f26864ce515e5.js → 648-5cc6e1921389a58a.js} +0 -0
- /package/dist/dashboard/out/_next/static/chunks/app/_not-found/{page-0b990dbb71d72a98.js → page-53b8a69f76db17d0.js} +0 -0
- /package/dist/dashboard/out/_next/static/chunks/{fd9d1056-bf46c09eb57e019c.js → fd9d1056-609918ca7b6280bb.js} +0 -0
- /package/dist/dashboard/out/_next/static/{6HHWb2ZmnJ4OSm0zUP7h4 → wPgKJtcOmTFLpUncDg16A}/_buildManifest.js +0 -0
- /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
|
|
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
|
-
|
|
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
|
-
|
|
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 -
|
|
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
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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; //
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
|
229
|
-
|
|
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
|
|
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: {
|
|
335
|
-
|
|
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
|
|
339
|
-
|
|
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
|