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
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
import { Router } from 'express';
|
|
7
7
|
import { requireAuth } from './auth.js';
|
|
8
8
|
import { db } from '../db/index.js';
|
|
9
|
-
import { getProvisioner } from '../provisioner/index.js';
|
|
9
|
+
import { getProvisioner, getProvisioningStage } from '../provisioner/index.js';
|
|
10
10
|
import { checkWorkspaceLimit } from './middleware/planLimits.js';
|
|
11
|
+
import { getConfig } from '../config.js';
|
|
11
12
|
export const workspacesRouter = Router();
|
|
12
13
|
// All routes require authentication
|
|
13
14
|
workspacesRouter.use(requireAuth);
|
|
@@ -90,6 +91,126 @@ workspacesRouter.post('/', checkWorkspaceLimit, async (req, res) => {
|
|
|
90
91
|
res.status(500).json({ error: 'Failed to create workspace' });
|
|
91
92
|
}
|
|
92
93
|
});
|
|
94
|
+
/**
|
|
95
|
+
* GET /api/workspaces/summary
|
|
96
|
+
* Get summary of all user workspaces for dashboard status indicator
|
|
97
|
+
* NOTE: This route MUST be before /:id to avoid being caught by parameterized route
|
|
98
|
+
*/
|
|
99
|
+
workspacesRouter.get('/summary', async (req, res) => {
|
|
100
|
+
const userId = req.session.userId;
|
|
101
|
+
try {
|
|
102
|
+
const workspaces = await db.workspaces.findByUserId(userId);
|
|
103
|
+
const provisioner = getProvisioner();
|
|
104
|
+
// Get live status for each workspace
|
|
105
|
+
const workspaceSummaries = await Promise.all(workspaces.map(async (w) => {
|
|
106
|
+
let liveStatus = w.status;
|
|
107
|
+
try {
|
|
108
|
+
liveStatus = await provisioner.getStatus(w.id);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Fall back to DB status
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
id: w.id,
|
|
115
|
+
name: w.name,
|
|
116
|
+
status: liveStatus,
|
|
117
|
+
publicUrl: w.publicUrl,
|
|
118
|
+
isStopped: liveStatus === 'stopped',
|
|
119
|
+
isRunning: liveStatus === 'running',
|
|
120
|
+
isProvisioning: liveStatus === 'provisioning',
|
|
121
|
+
hasError: liveStatus === 'error',
|
|
122
|
+
};
|
|
123
|
+
}));
|
|
124
|
+
// Overall status for quick dashboard indicator
|
|
125
|
+
const hasRunningWorkspace = workspaceSummaries.some(w => w.isRunning);
|
|
126
|
+
const hasStoppedWorkspace = workspaceSummaries.some(w => w.isStopped);
|
|
127
|
+
const hasProvisioningWorkspace = workspaceSummaries.some(w => w.isProvisioning);
|
|
128
|
+
res.json({
|
|
129
|
+
workspaces: workspaceSummaries,
|
|
130
|
+
summary: {
|
|
131
|
+
total: workspaceSummaries.length,
|
|
132
|
+
running: workspaceSummaries.filter(w => w.isRunning).length,
|
|
133
|
+
stopped: workspaceSummaries.filter(w => w.isStopped).length,
|
|
134
|
+
provisioning: workspaceSummaries.filter(w => w.isProvisioning).length,
|
|
135
|
+
error: workspaceSummaries.filter(w => w.hasError).length,
|
|
136
|
+
},
|
|
137
|
+
overallStatus: hasRunningWorkspace
|
|
138
|
+
? 'ready'
|
|
139
|
+
: hasProvisioningWorkspace
|
|
140
|
+
? 'provisioning'
|
|
141
|
+
: hasStoppedWorkspace
|
|
142
|
+
? 'stopped'
|
|
143
|
+
: workspaceSummaries.length === 0
|
|
144
|
+
? 'none'
|
|
145
|
+
: 'error',
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
console.error('Error getting workspace summary:', error);
|
|
150
|
+
res.status(500).json({ error: 'Failed to get workspace summary' });
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
/**
|
|
154
|
+
* GET /api/workspaces/primary
|
|
155
|
+
* Get the user's primary workspace (first/default) with live status
|
|
156
|
+
* Used by dashboard to show quick status indicator
|
|
157
|
+
* NOTE: This route MUST be before /:id to avoid being caught by parameterized route
|
|
158
|
+
*/
|
|
159
|
+
workspacesRouter.get('/primary', async (req, res) => {
|
|
160
|
+
const userId = req.session.userId;
|
|
161
|
+
try {
|
|
162
|
+
const workspaces = await db.workspaces.findByUserId(userId);
|
|
163
|
+
if (workspaces.length === 0) {
|
|
164
|
+
return res.json({
|
|
165
|
+
exists: false,
|
|
166
|
+
message: 'No workspace found. Connect a repository to auto-provision one.',
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
const primary = workspaces[0];
|
|
170
|
+
const provisioner = getProvisioner();
|
|
171
|
+
let liveStatus = primary.status;
|
|
172
|
+
try {
|
|
173
|
+
liveStatus = await provisioner.getStatus(primary.id);
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// Fall back to DB status
|
|
177
|
+
}
|
|
178
|
+
res.json({
|
|
179
|
+
exists: true,
|
|
180
|
+
workspace: {
|
|
181
|
+
id: primary.id,
|
|
182
|
+
name: primary.name,
|
|
183
|
+
status: liveStatus,
|
|
184
|
+
publicUrl: primary.publicUrl,
|
|
185
|
+
isStopped: liveStatus === 'stopped',
|
|
186
|
+
isRunning: liveStatus === 'running',
|
|
187
|
+
isProvisioning: liveStatus === 'provisioning',
|
|
188
|
+
hasError: liveStatus === 'error',
|
|
189
|
+
config: {
|
|
190
|
+
providers: primary.config.providers || [],
|
|
191
|
+
repositories: primary.config.repositories || [],
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
// Quick messages for UI
|
|
195
|
+
statusMessage: liveStatus === 'running'
|
|
196
|
+
? 'Workspace is running'
|
|
197
|
+
: liveStatus === 'stopped'
|
|
198
|
+
? 'Workspace is idle (will start automatically when needed)'
|
|
199
|
+
: liveStatus === 'provisioning'
|
|
200
|
+
? 'Workspace is being provisioned...'
|
|
201
|
+
: 'Workspace has an error',
|
|
202
|
+
actionNeeded: liveStatus === 'stopped'
|
|
203
|
+
? 'wakeup'
|
|
204
|
+
: liveStatus === 'error'
|
|
205
|
+
? 'check_error'
|
|
206
|
+
: null,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
console.error('Error getting primary workspace:', error);
|
|
211
|
+
res.status(500).json({ error: 'Failed to get primary workspace' });
|
|
212
|
+
}
|
|
213
|
+
});
|
|
93
214
|
/**
|
|
94
215
|
* GET /api/workspaces/:id
|
|
95
216
|
* Get workspace details
|
|
@@ -147,7 +268,17 @@ workspacesRouter.get('/:id/status', async (req, res) => {
|
|
|
147
268
|
}
|
|
148
269
|
const provisioner = getProvisioner();
|
|
149
270
|
const status = await provisioner.getStatus(id);
|
|
150
|
-
|
|
271
|
+
// Include provisioning progress info if it exists (even after status changes to 'running')
|
|
272
|
+
// This allows the frontend to see all stages including 'complete'
|
|
273
|
+
const provisioningProgress = getProvisioningStage(id);
|
|
274
|
+
res.json({
|
|
275
|
+
status,
|
|
276
|
+
provisioning: provisioningProgress ? {
|
|
277
|
+
stage: provisioningProgress.stage,
|
|
278
|
+
startedAt: provisioningProgress.startedAt,
|
|
279
|
+
elapsedMs: Date.now() - provisioningProgress.startedAt,
|
|
280
|
+
} : null,
|
|
281
|
+
});
|
|
151
282
|
}
|
|
152
283
|
catch (error) {
|
|
153
284
|
console.error('Error getting workspace status:', error);
|
|
@@ -256,6 +387,77 @@ workspacesRouter.post('/:id/repos', async (req, res) => {
|
|
|
256
387
|
res.status(500).json({ error: 'Failed to add repositories' });
|
|
257
388
|
}
|
|
258
389
|
});
|
|
390
|
+
/**
|
|
391
|
+
* POST /api/workspaces/:id/autoscale
|
|
392
|
+
* Trigger auto-scaling based on current agent count
|
|
393
|
+
* Supports both user session auth and workspace token auth
|
|
394
|
+
* Called by workspace container when spawning new agents
|
|
395
|
+
*/
|
|
396
|
+
workspacesRouter.post('/:id/autoscale', async (req, res) => {
|
|
397
|
+
const { id } = req.params;
|
|
398
|
+
const { agentCount } = req.body;
|
|
399
|
+
if (typeof agentCount !== 'number' || agentCount < 0) {
|
|
400
|
+
return res.status(400).json({ error: 'agentCount must be a non-negative number' });
|
|
401
|
+
}
|
|
402
|
+
try {
|
|
403
|
+
const workspace = await db.workspaces.findById(id);
|
|
404
|
+
if (!workspace) {
|
|
405
|
+
return res.status(404).json({ error: 'Workspace not found' });
|
|
406
|
+
}
|
|
407
|
+
// Verify auth: either user session or workspace token
|
|
408
|
+
const userId = req.session?.userId;
|
|
409
|
+
const authHeader = req.get('authorization');
|
|
410
|
+
if (userId) {
|
|
411
|
+
// User session auth
|
|
412
|
+
if (workspace.userId !== userId) {
|
|
413
|
+
return res.status(403).json({ error: 'Unauthorized' });
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
else if (authHeader?.startsWith('Bearer ')) {
|
|
417
|
+
// Workspace token auth (for calls from within the workspace)
|
|
418
|
+
const crypto = await import('crypto');
|
|
419
|
+
const config = getConfig();
|
|
420
|
+
const providedToken = authHeader.slice(7);
|
|
421
|
+
const expectedToken = crypto.default
|
|
422
|
+
.createHmac('sha256', config.sessionSecret)
|
|
423
|
+
.update(`workspace:${id}`)
|
|
424
|
+
.digest('hex');
|
|
425
|
+
const isValid = crypto.default.timingSafeEqual(Buffer.from(providedToken), Buffer.from(expectedToken));
|
|
426
|
+
if (!isValid) {
|
|
427
|
+
return res.status(401).json({ error: 'Invalid workspace token' });
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
return res.status(401).json({ error: 'Authentication required' });
|
|
432
|
+
}
|
|
433
|
+
const provisioner = getProvisioner();
|
|
434
|
+
const currentTier = await provisioner.getCurrentTier(id);
|
|
435
|
+
const recommendedTier = provisioner.getRecommendedTier(agentCount);
|
|
436
|
+
// Check if scaling is needed
|
|
437
|
+
if (recommendedTier.memoryMb <= currentTier.memoryMb) {
|
|
438
|
+
return res.json({
|
|
439
|
+
scaled: false,
|
|
440
|
+
currentTier: currentTier.name,
|
|
441
|
+
message: 'Current tier is sufficient',
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
// Perform the scale-up (respects plan limits)
|
|
445
|
+
const result = await provisioner.autoScale(id, agentCount);
|
|
446
|
+
res.json({
|
|
447
|
+
scaled: result.scaled,
|
|
448
|
+
previousTier: result.currentTier || currentTier.name,
|
|
449
|
+
newTier: result.targetTier || currentTier.name,
|
|
450
|
+
reason: result.reason,
|
|
451
|
+
message: result.scaled
|
|
452
|
+
? `Scaled up to ${result.targetTier} tier`
|
|
453
|
+
: result.reason || 'Scaling not required',
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
catch (error) {
|
|
457
|
+
console.error('Error auto-scaling workspace:', error);
|
|
458
|
+
res.status(500).json({ error: 'Failed to auto-scale workspace' });
|
|
459
|
+
}
|
|
460
|
+
});
|
|
259
461
|
/**
|
|
260
462
|
* POST /api/workspaces/:id/domain
|
|
261
463
|
* Add or update custom domain (Premium feature - Team/Enterprise only)
|
|
@@ -304,7 +506,7 @@ workspacesRouter.post('/:id/domain', async (req, res) => {
|
|
|
304
506
|
instructions: {
|
|
305
507
|
type: 'CNAME',
|
|
306
508
|
name: domain,
|
|
307
|
-
value: workspace.publicUrl?.replace('https://', '') || `${id}.
|
|
509
|
+
value: workspace.publicUrl?.replace('https://', '') || `${id}.agent-relay.com`,
|
|
308
510
|
ttl: 300,
|
|
309
511
|
},
|
|
310
512
|
verifyEndpoint: `/api/workspaces/${id}/domain/verify`,
|
|
@@ -338,7 +540,7 @@ workspacesRouter.post('/:id/domain/verify', async (req, res) => {
|
|
|
338
540
|
const dns = await import('dns').then(m => m.promises);
|
|
339
541
|
try {
|
|
340
542
|
const records = await dns.resolveCname(workspace.customDomain);
|
|
341
|
-
const expectedTarget = workspace.publicUrl?.replace('https://', '') || `${id}.
|
|
543
|
+
const expectedTarget = workspace.publicUrl?.replace('https://', '') || `${id}.agent-relay.com`;
|
|
342
544
|
if (records.some(r => r.includes(expectedTarget) || r.includes('agentrelay'))) {
|
|
343
545
|
// DNS is configured, now provision SSL cert
|
|
344
546
|
await db.workspaces.updateCustomDomainStatus(id, 'verifying');
|
|
@@ -457,9 +659,117 @@ async function removeDomainFromCompute(workspace) {
|
|
|
457
659
|
}
|
|
458
660
|
// Railway and Docker: similar cleanup
|
|
459
661
|
}
|
|
662
|
+
/**
|
|
663
|
+
* POST /api/workspaces/:id/proxy/*
|
|
664
|
+
* Proxy API requests to the workspace container
|
|
665
|
+
* This allows the dashboard to make REST calls through the cloud server
|
|
666
|
+
*/
|
|
667
|
+
workspacesRouter.all('/:id/proxy/{*proxyPath}', async (req, res) => {
|
|
668
|
+
const userId = req.session.userId;
|
|
669
|
+
const { id } = req.params;
|
|
670
|
+
// Express 5 wildcard params return an array of path segments, not a slash-separated string
|
|
671
|
+
const proxyPathParam = req.params.proxyPath;
|
|
672
|
+
const proxyPath = Array.isArray(proxyPathParam) ? proxyPathParam.join('/') : proxyPathParam;
|
|
673
|
+
try {
|
|
674
|
+
const workspace = await db.workspaces.findById(id);
|
|
675
|
+
if (!workspace) {
|
|
676
|
+
return res.status(404).json({ error: 'Workspace not found' });
|
|
677
|
+
}
|
|
678
|
+
if (workspace.userId !== userId) {
|
|
679
|
+
return res.status(403).json({ error: 'Unauthorized' });
|
|
680
|
+
}
|
|
681
|
+
if (workspace.status !== 'running' || !workspace.publicUrl) {
|
|
682
|
+
return res.status(400).json({ error: 'Workspace is not running' });
|
|
683
|
+
}
|
|
684
|
+
// Determine the internal URL for proxying
|
|
685
|
+
// When running inside Docker or Fly.io, use internal networking
|
|
686
|
+
let targetBaseUrl = workspace.publicUrl;
|
|
687
|
+
const runningInDocker = process.env.RUNNING_IN_DOCKER === 'true';
|
|
688
|
+
const runningOnFly = !!process.env.FLY_APP_NAME;
|
|
689
|
+
if (runningOnFly && targetBaseUrl.includes('.fly.dev')) {
|
|
690
|
+
// Use Fly.io internal networking (.internal uses IPv6, works by default)
|
|
691
|
+
// ar-583f273b.fly.dev -> http://ar-583f273b.internal:3888
|
|
692
|
+
const appName = targetBaseUrl.match(/https?:\/\/([^.]+)\.fly\.dev/)?.[1];
|
|
693
|
+
if (appName) {
|
|
694
|
+
targetBaseUrl = `http://${appName}.internal:3888`;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
else if (runningInDocker && workspace.computeId && targetBaseUrl.includes('localhost')) {
|
|
698
|
+
// Replace localhost URL with container name for Docker networking
|
|
699
|
+
// workspace.computeId is the container name (e.g., "ar-abc12345")
|
|
700
|
+
// The workspace port is 3888 inside the container
|
|
701
|
+
targetBaseUrl = `http://${workspace.computeId}:3888`;
|
|
702
|
+
}
|
|
703
|
+
const targetUrl = `${targetBaseUrl}/api/${proxyPath}`;
|
|
704
|
+
console.log(`[workspace-proxy] ${req.method} ${targetUrl}`);
|
|
705
|
+
// Store targetUrl for error handling
|
|
706
|
+
req._proxyTargetUrl = targetUrl;
|
|
707
|
+
// Add timeout to prevent hanging requests
|
|
708
|
+
const controller = new AbortController();
|
|
709
|
+
const timeout = setTimeout(() => controller.abort(), 15000); // 15s timeout
|
|
710
|
+
const fetchOptions = {
|
|
711
|
+
method: req.method,
|
|
712
|
+
headers: {
|
|
713
|
+
'Content-Type': 'application/json',
|
|
714
|
+
},
|
|
715
|
+
signal: controller.signal,
|
|
716
|
+
};
|
|
717
|
+
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
718
|
+
fetchOptions.body = JSON.stringify(req.body);
|
|
719
|
+
}
|
|
720
|
+
let proxyRes;
|
|
721
|
+
try {
|
|
722
|
+
proxyRes = await fetch(targetUrl, fetchOptions);
|
|
723
|
+
}
|
|
724
|
+
finally {
|
|
725
|
+
clearTimeout(timeout);
|
|
726
|
+
}
|
|
727
|
+
console.log(`[workspace-proxy] Response: ${proxyRes.status} ${proxyRes.statusText}`);
|
|
728
|
+
// Handle non-JSON responses gracefully
|
|
729
|
+
const contentType = proxyRes.headers.get('content-type');
|
|
730
|
+
if (contentType?.includes('application/json')) {
|
|
731
|
+
const data = await proxyRes.json();
|
|
732
|
+
res.status(proxyRes.status).json(data);
|
|
733
|
+
}
|
|
734
|
+
else {
|
|
735
|
+
const text = await proxyRes.text();
|
|
736
|
+
res.status(proxyRes.status).send(text);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
catch (error) {
|
|
740
|
+
const targetUrl = req._proxyTargetUrl || 'unknown';
|
|
741
|
+
console.error('[workspace-proxy] Error proxying to:', targetUrl);
|
|
742
|
+
console.error('[workspace-proxy] Error details:', error);
|
|
743
|
+
// Check for timeout/abort errors
|
|
744
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
745
|
+
res.status(504).json({
|
|
746
|
+
error: 'Workspace request timed out',
|
|
747
|
+
details: 'The workspace did not respond within 15 seconds',
|
|
748
|
+
targetUrl: targetUrl,
|
|
749
|
+
});
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
// Check for connection refused (workspace not running)
|
|
753
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
754
|
+
if (errorMessage.includes('ECONNREFUSED') || errorMessage.includes('fetch failed')) {
|
|
755
|
+
res.status(503).json({
|
|
756
|
+
error: 'Workspace is not reachable',
|
|
757
|
+
details: 'The workspace container may not be running or accepting connections',
|
|
758
|
+
targetUrl: targetUrl,
|
|
759
|
+
});
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
res.status(500).json({
|
|
763
|
+
error: 'Failed to proxy request to workspace',
|
|
764
|
+
details: errorMessage,
|
|
765
|
+
targetUrl: targetUrl, // Include target URL for debugging
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
});
|
|
460
769
|
/**
|
|
461
770
|
* POST /api/workspaces/quick
|
|
462
771
|
* Quick provision: one-click with defaults
|
|
772
|
+
* Providers are optional - can be connected after workspace creation via CLI login
|
|
463
773
|
*/
|
|
464
774
|
workspacesRouter.post('/quick', checkWorkspaceLimit, async (req, res) => {
|
|
465
775
|
const userId = req.session.userId;
|
|
@@ -468,23 +778,18 @@ workspacesRouter.post('/quick', checkWorkspaceLimit, async (req, res) => {
|
|
|
468
778
|
return res.status(400).json({ error: 'Repository name is required' });
|
|
469
779
|
}
|
|
470
780
|
try {
|
|
471
|
-
// Get user's connected providers
|
|
781
|
+
// Get user's connected providers (optional now)
|
|
472
782
|
const credentials = await db.credentials.findByUserId(userId);
|
|
473
783
|
const providers = credentials
|
|
474
784
|
.filter((c) => c.provider !== 'github')
|
|
475
785
|
.map((c) => c.provider);
|
|
476
|
-
if (providers.length === 0) {
|
|
477
|
-
return res.status(400).json({
|
|
478
|
-
error: 'No AI providers connected. Please connect at least one provider.',
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
786
|
// Create workspace with defaults
|
|
482
787
|
const provisioner = getProvisioner();
|
|
483
788
|
const workspaceName = name || `Workspace for ${repositoryFullName}`;
|
|
484
789
|
const result = await provisioner.provision({
|
|
485
790
|
userId,
|
|
486
791
|
name: workspaceName,
|
|
487
|
-
providers,
|
|
792
|
+
providers: providers.length > 0 ? providers : [], // Empty is OK now
|
|
488
793
|
repositories: [repositoryFullName],
|
|
489
794
|
supervisorEnabled: true,
|
|
490
795
|
maxAgents: 10,
|
|
@@ -499,7 +804,10 @@ workspacesRouter.post('/quick', checkWorkspaceLimit, async (req, res) => {
|
|
|
499
804
|
workspaceId: result.workspaceId,
|
|
500
805
|
status: result.status,
|
|
501
806
|
publicUrl: result.publicUrl,
|
|
502
|
-
|
|
807
|
+
providersConnected: providers.length > 0,
|
|
808
|
+
message: providers.length > 0
|
|
809
|
+
? 'Workspace provisioned successfully!'
|
|
810
|
+
: 'Workspace provisioned! Connect an AI provider to start using agents.',
|
|
503
811
|
});
|
|
504
812
|
}
|
|
505
813
|
catch (error) {
|
|
@@ -10,56 +10,59 @@ export const BILLING_PLANS = {
|
|
|
10
10
|
free: {
|
|
11
11
|
id: 'free',
|
|
12
12
|
name: 'Free',
|
|
13
|
-
description: '
|
|
13
|
+
description: 'Try AI agent workflows with limited access',
|
|
14
14
|
priceMonthly: 0,
|
|
15
15
|
priceYearly: 0,
|
|
16
16
|
limits: {
|
|
17
|
-
maxWorkspaces:
|
|
18
|
-
maxAgentsPerWorkspace:
|
|
17
|
+
maxWorkspaces: 1,
|
|
18
|
+
maxAgentsPerWorkspace: 2,
|
|
19
19
|
maxTeamMembers: 1,
|
|
20
20
|
maxStorageGB: 1,
|
|
21
|
-
maxComputeHoursPerMonth:
|
|
21
|
+
maxComputeHoursPerMonth: 5, // Limited to 5 hours/month
|
|
22
22
|
customDomains: false,
|
|
23
23
|
prioritySupport: false,
|
|
24
24
|
sla: false,
|
|
25
25
|
ssoEnabled: false,
|
|
26
26
|
auditLogs: false,
|
|
27
|
+
sessionPersistence: false,
|
|
27
28
|
},
|
|
28
29
|
features: [
|
|
29
|
-
'
|
|
30
|
-
'Up to
|
|
31
|
-
'
|
|
32
|
-
'
|
|
30
|
+
'1 workspace',
|
|
31
|
+
'Up to 2 agents',
|
|
32
|
+
'5 compute hours/month',
|
|
33
|
+
'Shared CPU (may throttle)',
|
|
33
34
|
'Community support',
|
|
34
35
|
],
|
|
35
36
|
},
|
|
36
37
|
pro: {
|
|
37
38
|
id: 'pro',
|
|
38
39
|
name: 'Pro',
|
|
39
|
-
description: 'For professional developers
|
|
40
|
-
priceMonthly:
|
|
41
|
-
priceYearly:
|
|
40
|
+
description: 'For professional developers building with AI agents',
|
|
41
|
+
priceMonthly: 4900, // $49/month
|
|
42
|
+
priceYearly: 47000, // $470/year (2 months free)
|
|
42
43
|
stripePriceIdMonthly: process.env.STRIPE_PRO_MONTHLY_PRICE_ID,
|
|
43
44
|
stripePriceIdYearly: process.env.STRIPE_PRO_YEARLY_PRICE_ID,
|
|
44
45
|
limits: {
|
|
45
|
-
maxWorkspaces:
|
|
46
|
-
maxAgentsPerWorkspace:
|
|
47
|
-
maxTeamMembers:
|
|
46
|
+
maxWorkspaces: 5,
|
|
47
|
+
maxAgentsPerWorkspace: 5,
|
|
48
|
+
maxTeamMembers: 3,
|
|
48
49
|
maxStorageGB: 10,
|
|
49
|
-
maxComputeHoursPerMonth:
|
|
50
|
+
maxComputeHoursPerMonth: 50,
|
|
50
51
|
customDomains: true,
|
|
51
52
|
prioritySupport: false,
|
|
52
53
|
sla: false,
|
|
53
54
|
ssoEnabled: false,
|
|
54
55
|
auditLogs: false,
|
|
56
|
+
sessionPersistence: true,
|
|
55
57
|
},
|
|
56
58
|
features: [
|
|
57
|
-
'Up to
|
|
58
|
-
'Up to
|
|
59
|
-
'
|
|
59
|
+
'Up to 5 workspaces',
|
|
60
|
+
'Up to 5 agents per workspace',
|
|
61
|
+
'50 compute hours/month',
|
|
60
62
|
'10 GB storage',
|
|
61
|
-
'
|
|
63
|
+
'3 team members',
|
|
62
64
|
'Custom domains',
|
|
65
|
+
'Session persistence',
|
|
63
66
|
'Email support',
|
|
64
67
|
],
|
|
65
68
|
},
|
|
@@ -82,6 +85,7 @@ export const BILLING_PLANS = {
|
|
|
82
85
|
sla: false,
|
|
83
86
|
ssoEnabled: false,
|
|
84
87
|
auditLogs: true,
|
|
88
|
+
sessionPersistence: true,
|
|
85
89
|
},
|
|
86
90
|
features: [
|
|
87
91
|
'Up to 50 workspaces',
|
|
@@ -90,6 +94,7 @@ export const BILLING_PLANS = {
|
|
|
90
94
|
'50 GB storage',
|
|
91
95
|
'25 team members',
|
|
92
96
|
'Custom domains',
|
|
97
|
+
'Session persistence',
|
|
93
98
|
'Priority support',
|
|
94
99
|
'Audit logs',
|
|
95
100
|
],
|
|
@@ -113,6 +118,7 @@ export const BILLING_PLANS = {
|
|
|
113
118
|
sla: true,
|
|
114
119
|
ssoEnabled: true,
|
|
115
120
|
auditLogs: true,
|
|
121
|
+
sessionPersistence: true,
|
|
116
122
|
},
|
|
117
123
|
features: [
|
|
118
124
|
'Unlimited workspaces',
|
|
@@ -121,6 +127,7 @@ export const BILLING_PLANS = {
|
|
|
121
127
|
'500 GB storage',
|
|
122
128
|
'Unlimited team members',
|
|
123
129
|
'Custom domains',
|
|
130
|
+
'Session persistence',
|
|
124
131
|
'Priority support with SLA',
|
|
125
132
|
'SSO/SAML integration',
|
|
126
133
|
'Audit logs & compliance',
|
|
@@ -227,6 +234,12 @@ export function comparePlans(from, to) {
|
|
|
227
234
|
else if (!toPlan.limits.auditLogs && fromPlan.limits.auditLogs) {
|
|
228
235
|
downgrades.push('Audit logs');
|
|
229
236
|
}
|
|
237
|
+
if (toPlan.limits.sessionPersistence && !fromPlan.limits.sessionPersistence) {
|
|
238
|
+
upgrades.push('Session persistence');
|
|
239
|
+
}
|
|
240
|
+
else if (!toPlan.limits.sessionPersistence && fromPlan.limits.sessionPersistence) {
|
|
241
|
+
downgrades.push('Session persistence');
|
|
242
|
+
}
|
|
230
243
|
return { upgrades, downgrades };
|
|
231
244
|
}
|
|
232
245
|
//# sourceMappingURL=plans.js.map
|
|
@@ -18,13 +18,17 @@ export interface BillingPlan {
|
|
|
18
18
|
priceYearly: number;
|
|
19
19
|
stripePriceIdMonthly?: string;
|
|
20
20
|
stripePriceIdYearly?: string;
|
|
21
|
-
limits:
|
|
21
|
+
limits: BillingPlanLimits;
|
|
22
22
|
features: string[];
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* Resource limits per plan
|
|
25
|
+
* Resource limits per plan for billing/display purposes.
|
|
26
|
+
* These limits are shown to customers on pricing pages and in account settings.
|
|
27
|
+
*
|
|
28
|
+
* Note: For runtime limit checking (API enforcement), use PlanLimits from
|
|
29
|
+
* src/cloud/services/planLimits.ts which has a focused subset of limits.
|
|
26
30
|
*/
|
|
27
|
-
export interface
|
|
31
|
+
export interface BillingPlanLimits {
|
|
28
32
|
maxWorkspaces: number;
|
|
29
33
|
maxAgentsPerWorkspace: number;
|
|
30
34
|
maxTeamMembers: number;
|
|
@@ -35,6 +39,8 @@ export interface PlanLimits {
|
|
|
35
39
|
sla: boolean;
|
|
36
40
|
ssoEnabled: boolean;
|
|
37
41
|
auditLogs: boolean;
|
|
42
|
+
/** Cloud session persistence (summaries, session tracking) - Pro+ only */
|
|
43
|
+
sessionPersistence: boolean;
|
|
38
44
|
}
|
|
39
45
|
/**
|
|
40
46
|
* Customer billing information
|
package/dist/cloud/config.d.ts
CHANGED
|
@@ -10,8 +10,7 @@ export interface CloudConfig {
|
|
|
10
10
|
github: {
|
|
11
11
|
clientId: string;
|
|
12
12
|
clientSecret: string;
|
|
13
|
-
|
|
14
|
-
appPrivateKey?: string;
|
|
13
|
+
webhookSecret?: string;
|
|
15
14
|
};
|
|
16
15
|
providers: {
|
|
17
16
|
anthropic?: {
|
|
@@ -35,11 +34,19 @@ export interface CloudConfig {
|
|
|
35
34
|
org: string;
|
|
36
35
|
region?: string;
|
|
37
36
|
workspaceDomain?: string;
|
|
37
|
+
registryAuth?: {
|
|
38
|
+
username: string;
|
|
39
|
+
password: string;
|
|
40
|
+
};
|
|
38
41
|
};
|
|
39
42
|
railway?: {
|
|
40
43
|
apiToken: string;
|
|
41
44
|
};
|
|
42
45
|
};
|
|
46
|
+
nango: {
|
|
47
|
+
secretKey: string;
|
|
48
|
+
host?: string;
|
|
49
|
+
};
|
|
43
50
|
stripe: {
|
|
44
51
|
secretKey: string;
|
|
45
52
|
publishableKey: string;
|
package/dist/cloud/config.js
CHANGED
|
@@ -13,16 +13,15 @@ function optionalEnv(name) {
|
|
|
13
13
|
}
|
|
14
14
|
export function loadConfig() {
|
|
15
15
|
return {
|
|
16
|
-
port: parseInt(process.env.PORT || '
|
|
17
|
-
publicUrl: process.env.PUBLIC_URL || 'http://localhost:
|
|
16
|
+
port: parseInt(process.env.PORT || '4567', 10),
|
|
17
|
+
publicUrl: process.env.PUBLIC_URL || 'http://localhost:4567',
|
|
18
18
|
sessionSecret: requireEnv('SESSION_SECRET'),
|
|
19
19
|
databaseUrl: requireEnv('DATABASE_URL'),
|
|
20
20
|
redisUrl: process.env.REDIS_URL || 'redis://localhost:6379',
|
|
21
21
|
github: {
|
|
22
22
|
clientId: requireEnv('GITHUB_CLIENT_ID'),
|
|
23
23
|
clientSecret: requireEnv('GITHUB_CLIENT_SECRET'),
|
|
24
|
-
|
|
25
|
-
appPrivateKey: optionalEnv('GITHUB_APP_PRIVATE_KEY'),
|
|
24
|
+
webhookSecret: optionalEnv('GITHUB_WEBHOOK_SECRET'),
|
|
26
25
|
},
|
|
27
26
|
providers: {
|
|
28
27
|
anthropic: optionalEnv('ANTHROPIC_CLIENT_ID')
|
|
@@ -49,6 +48,12 @@ export function loadConfig() {
|
|
|
49
48
|
org: optionalEnv('FLY_ORG') || 'personal',
|
|
50
49
|
region: optionalEnv('FLY_REGION') || 'sjc',
|
|
51
50
|
workspaceDomain: optionalEnv('FLY_WORKSPACE_DOMAIN'),
|
|
51
|
+
registryAuth: optionalEnv('GHCR_USERNAME') && optionalEnv('GHCR_TOKEN')
|
|
52
|
+
? {
|
|
53
|
+
username: optionalEnv('GHCR_USERNAME'),
|
|
54
|
+
password: optionalEnv('GHCR_TOKEN'),
|
|
55
|
+
}
|
|
56
|
+
: undefined,
|
|
52
57
|
}
|
|
53
58
|
: undefined,
|
|
54
59
|
railway: optionalEnv('RAILWAY_API_TOKEN')
|
|
@@ -57,6 +62,10 @@ export function loadConfig() {
|
|
|
57
62
|
}
|
|
58
63
|
: undefined,
|
|
59
64
|
},
|
|
65
|
+
nango: {
|
|
66
|
+
secretKey: requireEnv('NANGO_SECRET_KEY'),
|
|
67
|
+
host: optionalEnv('NANGO_HOST'),
|
|
68
|
+
},
|
|
60
69
|
stripe: {
|
|
61
70
|
secretKey: requireEnv('STRIPE_SECRET_KEY'),
|
|
62
71
|
publishableKey: requireEnv('STRIPE_PUBLISHABLE_KEY'),
|