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
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaling Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Main integration layer that connects:
|
|
5
|
+
* - AutoScaler (policy evaluation and scaling decisions)
|
|
6
|
+
* - CapacityManager (workspace capacity tracking)
|
|
7
|
+
* - WorkspaceProvisioner (actual instance provisioning)
|
|
8
|
+
* - Monitoring (memory/CPU metrics from agents)
|
|
9
|
+
*
|
|
10
|
+
* Handles the complete scaling lifecycle:
|
|
11
|
+
* 1. Receives metrics from monitoring
|
|
12
|
+
* 2. Updates capacity manager
|
|
13
|
+
* 3. Triggers auto-scaler evaluation
|
|
14
|
+
* 4. Executes scaling via provisioner
|
|
15
|
+
* 5. Updates capacity after scaling
|
|
16
|
+
*/
|
|
17
|
+
import { EventEmitter } from 'events';
|
|
18
|
+
import { createAutoScaler } from './auto-scaler.js';
|
|
19
|
+
import { createCapacityManager } from './capacity-manager.js';
|
|
20
|
+
import { getScalingPolicyService } from './scaling-policy.js';
|
|
21
|
+
import { getProvisioner, RESOURCE_TIERS, } from '../provisioner/index.js';
|
|
22
|
+
import { db } from '../db/index.js';
|
|
23
|
+
const DEFAULT_CONFIG = {
|
|
24
|
+
enabled: true,
|
|
25
|
+
autoProvision: true,
|
|
26
|
+
autoDeprovision: false, // Disabled by default for safety
|
|
27
|
+
idleTimeoutMs: 30 * 60 * 1000, // 30 minutes
|
|
28
|
+
minUserWorkspaces: 1,
|
|
29
|
+
};
|
|
30
|
+
export class ScalingOrchestrator extends EventEmitter {
|
|
31
|
+
config;
|
|
32
|
+
autoScaler;
|
|
33
|
+
capacityManager;
|
|
34
|
+
provisioner;
|
|
35
|
+
initialized = false;
|
|
36
|
+
scalingHistory = [];
|
|
37
|
+
maxHistorySize = 1000;
|
|
38
|
+
constructor(config = {}) {
|
|
39
|
+
super();
|
|
40
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
41
|
+
this.autoScaler = createAutoScaler({ enabled: this.config.enabled });
|
|
42
|
+
this.capacityManager = createCapacityManager();
|
|
43
|
+
this.provisioner = getProvisioner();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Initialize the orchestrator with Redis for cross-server coordination
|
|
47
|
+
*/
|
|
48
|
+
async initialize(redisUrl) {
|
|
49
|
+
if (this.initialized)
|
|
50
|
+
return;
|
|
51
|
+
const url = redisUrl || this.config.redisUrl;
|
|
52
|
+
if (!url) {
|
|
53
|
+
console.warn('[ScalingOrchestrator] No Redis URL provided, running in local mode');
|
|
54
|
+
this.initialized = true;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
// Initialize both services with Redis
|
|
59
|
+
await Promise.all([
|
|
60
|
+
this.autoScaler.initialize(url),
|
|
61
|
+
this.capacityManager.initialize(url),
|
|
62
|
+
]);
|
|
63
|
+
// Set up event handlers
|
|
64
|
+
this.setupEventHandlers();
|
|
65
|
+
this.initialized = true;
|
|
66
|
+
this.emit('initialized');
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
this.emit('error', { context: 'initialization', error });
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Set up event handlers between components
|
|
75
|
+
*/
|
|
76
|
+
setupEventHandlers() {
|
|
77
|
+
// Handle scaling execution requests from auto-scaler
|
|
78
|
+
this.autoScaler.on('execute_scaling', async ({ operation, decision }) => {
|
|
79
|
+
try {
|
|
80
|
+
await this.executeScaling(operation, decision);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
this.recordEvent({
|
|
84
|
+
type: operation.action,
|
|
85
|
+
userId: operation.userId,
|
|
86
|
+
operation,
|
|
87
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
88
|
+
timestamp: new Date(),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
// Handle capacity updates
|
|
93
|
+
this.capacityManager.on('capacity_updated', (capacity) => {
|
|
94
|
+
// Check if any user needs scaling based on new capacity data
|
|
95
|
+
this.checkScalingNeeded(capacity.userId);
|
|
96
|
+
});
|
|
97
|
+
// Handle stale workspaces
|
|
98
|
+
this.capacityManager.on('workspace_stale', async ({ workspaceId }) => {
|
|
99
|
+
this.emit('workspace_stale', workspaceId);
|
|
100
|
+
// Could trigger health check or restart here
|
|
101
|
+
});
|
|
102
|
+
// Forward auto-scaler events
|
|
103
|
+
this.autoScaler.on('scaling_started', (op) => this.emit('scaling_started', op));
|
|
104
|
+
this.autoScaler.on('scaling_completed', (op) => this.emit('scaling_completed', op));
|
|
105
|
+
this.autoScaler.on('scaling_error', (data) => this.emit('scaling_error', data));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if scaling is needed for a user
|
|
109
|
+
*/
|
|
110
|
+
async checkScalingNeeded(userId) {
|
|
111
|
+
const forecast = this.capacityManager.getCapacityForecast(userId);
|
|
112
|
+
if (!forecast)
|
|
113
|
+
return;
|
|
114
|
+
// Emit forecast for monitoring
|
|
115
|
+
this.emit('capacity_forecast', forecast);
|
|
116
|
+
// Take action based on recommendation
|
|
117
|
+
if (forecast.recommendation === 'critical' || forecast.recommendation === 'scale_now') {
|
|
118
|
+
this.emit('scaling_recommended', {
|
|
119
|
+
userId,
|
|
120
|
+
recommendation: forecast.recommendation,
|
|
121
|
+
forecast,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Execute a scaling operation
|
|
127
|
+
*/
|
|
128
|
+
async executeScaling(operation, decision) {
|
|
129
|
+
const event = {
|
|
130
|
+
type: operation.action,
|
|
131
|
+
userId: operation.userId,
|
|
132
|
+
decision,
|
|
133
|
+
operation,
|
|
134
|
+
timestamp: new Date(),
|
|
135
|
+
};
|
|
136
|
+
try {
|
|
137
|
+
switch (operation.action) {
|
|
138
|
+
// Horizontal scaling
|
|
139
|
+
case 'scale_up':
|
|
140
|
+
await this.handleScaleUp(operation, decision, event);
|
|
141
|
+
break;
|
|
142
|
+
case 'scale_down':
|
|
143
|
+
await this.handleScaleDown(operation, decision, event);
|
|
144
|
+
break;
|
|
145
|
+
// Vertical scaling (in-workspace)
|
|
146
|
+
case 'resize_up':
|
|
147
|
+
case 'resize_down':
|
|
148
|
+
await this.handleResize(operation, decision, event);
|
|
149
|
+
break;
|
|
150
|
+
case 'increase_agent_limit':
|
|
151
|
+
await this.handleAgentLimitIncrease(operation, decision, event);
|
|
152
|
+
break;
|
|
153
|
+
case 'migrate_agents':
|
|
154
|
+
await this.handleMigrateAgents(operation, decision, event);
|
|
155
|
+
break;
|
|
156
|
+
case 'rebalance':
|
|
157
|
+
await this.handleRebalance(operation, decision, event);
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
event.error = error instanceof Error ? error.message : 'Unknown error';
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
165
|
+
finally {
|
|
166
|
+
this.recordEvent(event);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Handle scale up - provision new workspace
|
|
171
|
+
*/
|
|
172
|
+
async handleScaleUp(operation, decision, event) {
|
|
173
|
+
if (!this.config.autoProvision) {
|
|
174
|
+
this.emit('scaling_blocked', {
|
|
175
|
+
reason: 'auto_provision_disabled',
|
|
176
|
+
operation,
|
|
177
|
+
});
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
// Get user's existing workspace config as template
|
|
181
|
+
const existingWorkspaces = await db.workspaces.findByUserId(operation.userId);
|
|
182
|
+
if (existingWorkspaces.length === 0) {
|
|
183
|
+
throw new Error('No existing workspace to use as template');
|
|
184
|
+
}
|
|
185
|
+
const template = existingWorkspaces[0];
|
|
186
|
+
const workspaceNumber = existingWorkspaces.length + 1;
|
|
187
|
+
// Provision new workspace
|
|
188
|
+
const provisionConfig = {
|
|
189
|
+
userId: operation.userId,
|
|
190
|
+
name: `${template.name}-${workspaceNumber}`,
|
|
191
|
+
providers: template.config.providers || [],
|
|
192
|
+
repositories: template.config.repositories || [],
|
|
193
|
+
supervisorEnabled: template.config.supervisorEnabled,
|
|
194
|
+
maxAgents: template.config.maxAgents,
|
|
195
|
+
};
|
|
196
|
+
const result = await this.provisioner.provision(provisionConfig);
|
|
197
|
+
event.result = result;
|
|
198
|
+
event.workspaceId = result.workspaceId;
|
|
199
|
+
if (result.status === 'error') {
|
|
200
|
+
throw new Error(result.error || 'Provisioning failed');
|
|
201
|
+
}
|
|
202
|
+
this.emit('workspace_provisioned', {
|
|
203
|
+
userId: operation.userId,
|
|
204
|
+
workspaceId: result.workspaceId,
|
|
205
|
+
publicUrl: result.publicUrl,
|
|
206
|
+
triggeredBy: operation.triggeredBy,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Handle scale down - deprovision workspace
|
|
211
|
+
*/
|
|
212
|
+
async handleScaleDown(operation, decision, event) {
|
|
213
|
+
if (!this.config.autoDeprovision) {
|
|
214
|
+
this.emit('scaling_blocked', {
|
|
215
|
+
reason: 'auto_deprovision_disabled',
|
|
216
|
+
operation,
|
|
217
|
+
});
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
// Get user's workspaces
|
|
221
|
+
const workspaces = await db.workspaces.findByUserId(operation.userId);
|
|
222
|
+
// Don't scale below minimum
|
|
223
|
+
if (workspaces.length <= this.config.minUserWorkspaces) {
|
|
224
|
+
this.emit('scaling_blocked', {
|
|
225
|
+
reason: 'at_minimum_workspaces',
|
|
226
|
+
operation,
|
|
227
|
+
});
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// Find the best workspace to deprovision (lowest utilization)
|
|
231
|
+
const recommendations = this.capacityManager.recommendPlacement(operation.userId, 0);
|
|
232
|
+
const bestToRemove = recommendations[recommendations.length - 1]; // Highest score = lowest utilization
|
|
233
|
+
if (!bestToRemove) {
|
|
234
|
+
throw new Error('No workspace found to deprovision');
|
|
235
|
+
}
|
|
236
|
+
// Check if workspace has active agents
|
|
237
|
+
const capacity = this.capacityManager.getUserWorkspaces(operation.userId)
|
|
238
|
+
.find(w => w.workspaceId === bestToRemove.workspaceId);
|
|
239
|
+
if (capacity && capacity.currentAgents > 0) {
|
|
240
|
+
// Need to migrate agents first
|
|
241
|
+
this.emit('migration_required', {
|
|
242
|
+
fromWorkspaceId: bestToRemove.workspaceId,
|
|
243
|
+
agentCount: capacity.currentAgents,
|
|
244
|
+
});
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
// Deprovision
|
|
248
|
+
await this.provisioner.deprovision(bestToRemove.workspaceId);
|
|
249
|
+
await this.capacityManager.removeWorkspace(bestToRemove.workspaceId);
|
|
250
|
+
event.workspaceId = bestToRemove.workspaceId;
|
|
251
|
+
this.emit('workspace_deprovisioned', {
|
|
252
|
+
userId: operation.userId,
|
|
253
|
+
workspaceId: bestToRemove.workspaceId,
|
|
254
|
+
triggeredBy: operation.triggeredBy,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Handle rebalance - redistribute agents across workspaces
|
|
259
|
+
*/
|
|
260
|
+
async handleRebalance(operation, _decision, _event) {
|
|
261
|
+
// Rebalancing would involve:
|
|
262
|
+
// 1. Identifying overloaded workspaces
|
|
263
|
+
// 2. Finding agents that can be migrated
|
|
264
|
+
// 3. Selecting target workspaces
|
|
265
|
+
// 4. Coordinating agent migration via coordinator service
|
|
266
|
+
this.emit('rebalance_requested', {
|
|
267
|
+
userId: operation.userId,
|
|
268
|
+
// Would include specific migration plan
|
|
269
|
+
});
|
|
270
|
+
// Actual implementation would coordinate with the agent coordinator
|
|
271
|
+
// to move agents between workspaces
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Handle resize - vertical scaling (increase/decrease workspace resources)
|
|
275
|
+
*/
|
|
276
|
+
async handleResize(operation, decision, event) {
|
|
277
|
+
// Get target workspace
|
|
278
|
+
const targetWorkspaceId = operation.targetWorkspaceId;
|
|
279
|
+
if (!targetWorkspaceId) {
|
|
280
|
+
// Find the workspace that triggered the scaling
|
|
281
|
+
const workspaces = await db.workspaces.findByUserId(operation.userId);
|
|
282
|
+
if (workspaces.length === 0) {
|
|
283
|
+
throw new Error('No workspace found to resize');
|
|
284
|
+
}
|
|
285
|
+
// For now, resize the first workspace (could use metrics to pick the right one)
|
|
286
|
+
operation.targetWorkspaceId = workspaces[0].id;
|
|
287
|
+
}
|
|
288
|
+
const workspace = await db.workspaces.findById(operation.targetWorkspaceId);
|
|
289
|
+
if (!workspace) {
|
|
290
|
+
throw new Error('Workspace not found');
|
|
291
|
+
}
|
|
292
|
+
// Determine the target tier
|
|
293
|
+
let targetTier;
|
|
294
|
+
if (operation.targetResourceTier) {
|
|
295
|
+
targetTier = RESOURCE_TIERS[operation.targetResourceTier];
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
// Calculate next tier up/down
|
|
299
|
+
const currentTier = await this.provisioner.getCurrentTier(workspace.id);
|
|
300
|
+
const tierOrder = ['small', 'medium', 'large', 'xlarge'];
|
|
301
|
+
const currentIndex = tierOrder.indexOf(currentTier.name);
|
|
302
|
+
if (operation.action === 'resize_up') {
|
|
303
|
+
const nextIndex = Math.min(currentIndex + 1, tierOrder.length - 1);
|
|
304
|
+
targetTier = RESOURCE_TIERS[tierOrder[nextIndex]];
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
const nextIndex = Math.max(currentIndex - 1, 0);
|
|
308
|
+
targetTier = RESOURCE_TIERS[tierOrder[nextIndex]];
|
|
309
|
+
}
|
|
310
|
+
event.previousTier = currentTier.name;
|
|
311
|
+
}
|
|
312
|
+
// Perform the resize
|
|
313
|
+
await this.provisioner.resize(workspace.id, targetTier);
|
|
314
|
+
event.workspaceId = workspace.id;
|
|
315
|
+
event.newTier = targetTier.name;
|
|
316
|
+
this.emit('workspace_resized', {
|
|
317
|
+
userId: operation.userId,
|
|
318
|
+
workspaceId: workspace.id,
|
|
319
|
+
previousTier: event.previousTier,
|
|
320
|
+
newTier: targetTier.name,
|
|
321
|
+
triggeredBy: operation.triggeredBy,
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Handle agent limit increase within a workspace
|
|
326
|
+
*/
|
|
327
|
+
async handleAgentLimitIncrease(operation, decision, event) {
|
|
328
|
+
// Get target workspace
|
|
329
|
+
const targetWorkspaceId = operation.targetWorkspaceId;
|
|
330
|
+
const workspaces = await db.workspaces.findByUserId(operation.userId);
|
|
331
|
+
if (!targetWorkspaceId && workspaces.length === 0) {
|
|
332
|
+
throw new Error('No workspace found to update agent limit');
|
|
333
|
+
}
|
|
334
|
+
const workspace = await db.workspaces.findById(targetWorkspaceId || workspaces[0].id);
|
|
335
|
+
if (!workspace) {
|
|
336
|
+
throw new Error('Workspace not found');
|
|
337
|
+
}
|
|
338
|
+
const currentLimit = workspace.config.maxAgents || 10;
|
|
339
|
+
let newLimit;
|
|
340
|
+
if (operation.targetAgentLimit) {
|
|
341
|
+
newLimit = operation.targetAgentLimit;
|
|
342
|
+
}
|
|
343
|
+
else if (decision.action?.percentage) {
|
|
344
|
+
// Increase by percentage
|
|
345
|
+
newLimit = Math.ceil(currentLimit * (1 + decision.action.percentage / 100));
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
// Default: increase by 50%
|
|
349
|
+
newLimit = Math.ceil(currentLimit * 1.5);
|
|
350
|
+
}
|
|
351
|
+
// Cap at plan maximum
|
|
352
|
+
const policyService = getScalingPolicyService();
|
|
353
|
+
const userPlan = 'pro'; // Would get from user context
|
|
354
|
+
const thresholds = policyService.getThresholds(userPlan);
|
|
355
|
+
newLimit = Math.min(newLimit, thresholds.agentsPerWorkspaceMax);
|
|
356
|
+
// Update the agent limit
|
|
357
|
+
await this.provisioner.updateAgentLimit(workspace.id, newLimit);
|
|
358
|
+
event.workspaceId = workspace.id;
|
|
359
|
+
event.previousAgentLimit = currentLimit;
|
|
360
|
+
event.newAgentLimit = newLimit;
|
|
361
|
+
this.emit('agent_limit_updated', {
|
|
362
|
+
userId: operation.userId,
|
|
363
|
+
workspaceId: workspace.id,
|
|
364
|
+
previousLimit: currentLimit,
|
|
365
|
+
newLimit,
|
|
366
|
+
triggeredBy: operation.triggeredBy,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Handle agent migration between workspaces
|
|
371
|
+
*/
|
|
372
|
+
async handleMigrateAgents(operation, _decision, _event) {
|
|
373
|
+
// Agent migration would involve:
|
|
374
|
+
// 1. Identifying agents to migrate
|
|
375
|
+
// 2. Selecting target workspace(s)
|
|
376
|
+
// 3. Coordinating graceful migration via coordinator service
|
|
377
|
+
// 4. Updating capacity tracking
|
|
378
|
+
this.emit('migration_requested', {
|
|
379
|
+
userId: operation.userId,
|
|
380
|
+
fromWorkspaceId: operation.targetWorkspaceId,
|
|
381
|
+
// Would include specific migration plan
|
|
382
|
+
});
|
|
383
|
+
// Actual implementation would coordinate with the agent coordinator
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Record a scaling event in history
|
|
387
|
+
*/
|
|
388
|
+
recordEvent(event) {
|
|
389
|
+
this.scalingHistory.push(event);
|
|
390
|
+
// Trim history if too large
|
|
391
|
+
if (this.scalingHistory.length > this.maxHistorySize) {
|
|
392
|
+
this.scalingHistory = this.scalingHistory.slice(-this.maxHistorySize);
|
|
393
|
+
}
|
|
394
|
+
// Persist to database if significant
|
|
395
|
+
const significantEvents = [
|
|
396
|
+
'scale_up',
|
|
397
|
+
'scale_down',
|
|
398
|
+
'resize_up',
|
|
399
|
+
'resize_down',
|
|
400
|
+
'increase_agent_limit',
|
|
401
|
+
];
|
|
402
|
+
if (significantEvents.includes(event.type)) {
|
|
403
|
+
this.persistScalingEvent(event).catch((err) => {
|
|
404
|
+
console.error('[ScalingOrchestrator] Failed to persist event:', err);
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Persist scaling event to database
|
|
410
|
+
*/
|
|
411
|
+
async persistScalingEvent(event) {
|
|
412
|
+
// Would insert into scaling_events table
|
|
413
|
+
// For now, just emit for external handling
|
|
414
|
+
this.emit('event_recorded', event);
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Report metrics from monitoring service
|
|
418
|
+
* This is the main entry point for metrics from agents
|
|
419
|
+
*/
|
|
420
|
+
async reportMetrics(userId, workspaces) {
|
|
421
|
+
// Update capacity manager
|
|
422
|
+
for (const workspace of workspaces) {
|
|
423
|
+
const capacityUpdate = this.capacityManager.fromWorkspaceMetrics(userId, workspace);
|
|
424
|
+
await this.capacityManager.reportCapacity(workspace.workspaceId, userId, capacityUpdate);
|
|
425
|
+
}
|
|
426
|
+
// Report to auto-scaler for policy evaluation
|
|
427
|
+
await this.autoScaler.reportMetrics(userId, workspaces);
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Manually trigger scaling evaluation for a user
|
|
431
|
+
*/
|
|
432
|
+
async evaluateScaling(userId) {
|
|
433
|
+
return this.autoScaler.triggerEvaluation(userId);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Get capacity forecast for a user
|
|
437
|
+
*/
|
|
438
|
+
getCapacityForecast(userId) {
|
|
439
|
+
return this.capacityManager.getCapacityForecast(userId);
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Get best placement for new agents
|
|
443
|
+
*/
|
|
444
|
+
recommendPlacement(userId, agentCount = 1) {
|
|
445
|
+
return this.capacityManager.recommendPlacement(userId, agentCount);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Get scaling history for a user
|
|
449
|
+
*/
|
|
450
|
+
getScalingHistory(userId) {
|
|
451
|
+
if (userId) {
|
|
452
|
+
return this.scalingHistory.filter((e) => e.userId === userId);
|
|
453
|
+
}
|
|
454
|
+
return [...this.scalingHistory];
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Get current status of the orchestrator
|
|
458
|
+
*/
|
|
459
|
+
getStatus() {
|
|
460
|
+
return {
|
|
461
|
+
initialized: this.initialized,
|
|
462
|
+
autoScaler: this.autoScaler.getStatus(),
|
|
463
|
+
capacity: this.capacityManager.getGlobalMetrics(),
|
|
464
|
+
config: {
|
|
465
|
+
autoProvision: this.config.autoProvision,
|
|
466
|
+
autoDeprovision: this.config.autoDeprovision,
|
|
467
|
+
minUserWorkspaces: this.config.minUserWorkspaces,
|
|
468
|
+
},
|
|
469
|
+
historySize: this.scalingHistory.length,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Update user's plan tier
|
|
474
|
+
*/
|
|
475
|
+
async setUserPlan(userId, plan) {
|
|
476
|
+
await this.autoScaler.setUserPlan(userId, plan);
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Clean shutdown
|
|
480
|
+
*/
|
|
481
|
+
async shutdown() {
|
|
482
|
+
await Promise.all([
|
|
483
|
+
this.autoScaler.shutdown(),
|
|
484
|
+
this.capacityManager.shutdown(),
|
|
485
|
+
]);
|
|
486
|
+
this.initialized = false;
|
|
487
|
+
this.emit('shutdown');
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
// Singleton instance
|
|
491
|
+
let _orchestrator = null;
|
|
492
|
+
export function getScalingOrchestrator() {
|
|
493
|
+
if (!_orchestrator) {
|
|
494
|
+
_orchestrator = new ScalingOrchestrator();
|
|
495
|
+
}
|
|
496
|
+
return _orchestrator;
|
|
497
|
+
}
|
|
498
|
+
export function createScalingOrchestrator(config = {}) {
|
|
499
|
+
_orchestrator = new ScalingOrchestrator(config);
|
|
500
|
+
return _orchestrator;
|
|
501
|
+
}
|
|
502
|
+
//# sourceMappingURL=scaling-orchestrator.js.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaling Policy Service
|
|
3
|
+
*
|
|
4
|
+
* Defines rules and policies for auto-scaling workspaces based on:
|
|
5
|
+
* - Memory pressure
|
|
6
|
+
* - Agent count
|
|
7
|
+
* - CPU usage
|
|
8
|
+
* - Trend analysis
|
|
9
|
+
*
|
|
10
|
+
* Policies are configurable per user/plan tier.
|
|
11
|
+
*/
|
|
12
|
+
import { EventEmitter } from 'events';
|
|
13
|
+
export interface ScalingThresholds {
|
|
14
|
+
memoryWarningBytes: number;
|
|
15
|
+
memoryCriticalBytes: number;
|
|
16
|
+
memoryScaleUpBytes: number;
|
|
17
|
+
memoryGrowthRateWarning: number;
|
|
18
|
+
memoryGrowthRateScaleUp: number;
|
|
19
|
+
agentsPerWorkspaceWarning: number;
|
|
20
|
+
agentsPerWorkspaceMax: number;
|
|
21
|
+
cpuWarningPercent: number;
|
|
22
|
+
cpuScaleUpPercent: number;
|
|
23
|
+
evaluationWindowMs: number;
|
|
24
|
+
cooldownMs: number;
|
|
25
|
+
}
|
|
26
|
+
export interface ScalingPolicy {
|
|
27
|
+
id: string;
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
|
+
enabled: boolean;
|
|
31
|
+
priority: number;
|
|
32
|
+
conditions: ScalingCondition[];
|
|
33
|
+
action: ScalingAction;
|
|
34
|
+
maxInstances: number;
|
|
35
|
+
minInstances: number;
|
|
36
|
+
}
|
|
37
|
+
export interface ScalingCondition {
|
|
38
|
+
metric: 'memory_usage' | 'memory_trend' | 'agent_count' | 'cpu_usage' | 'workspace_count';
|
|
39
|
+
operator: 'gt' | 'gte' | 'lt' | 'lte' | 'eq';
|
|
40
|
+
value: number;
|
|
41
|
+
duration?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface ScalingAction {
|
|
44
|
+
type: 'scale_up' | 'scale_down' | 'resize_up' | 'resize_down' | 'increase_agent_limit' | 'migrate_agents' | 'rebalance' | 'alert_only';
|
|
45
|
+
targetCount?: number;
|
|
46
|
+
percentage?: number;
|
|
47
|
+
targetWorkspaceId?: string;
|
|
48
|
+
resourceTier?: 'small' | 'medium' | 'large' | 'xlarge';
|
|
49
|
+
newAgentLimit?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface ScalingDecision {
|
|
52
|
+
shouldScale: boolean;
|
|
53
|
+
action: ScalingAction | null;
|
|
54
|
+
reason: string;
|
|
55
|
+
triggeredPolicy: string | null;
|
|
56
|
+
metrics: Record<string, number>;
|
|
57
|
+
timestamp: Date;
|
|
58
|
+
}
|
|
59
|
+
export interface WorkspaceMetrics {
|
|
60
|
+
workspaceId: string;
|
|
61
|
+
totalMemoryBytes: number;
|
|
62
|
+
averageMemoryBytes: number;
|
|
63
|
+
peakMemoryBytes: number;
|
|
64
|
+
memoryTrendPerMinute: number;
|
|
65
|
+
agentCount: number;
|
|
66
|
+
healthyAgentCount: number;
|
|
67
|
+
cpuPercent: number;
|
|
68
|
+
uptimeMs: number;
|
|
69
|
+
}
|
|
70
|
+
export interface UserScalingContext {
|
|
71
|
+
userId: string;
|
|
72
|
+
plan: 'free' | 'pro' | 'team' | 'enterprise';
|
|
73
|
+
currentWorkspaceCount: number;
|
|
74
|
+
maxWorkspaces: number;
|
|
75
|
+
workspaceMetrics: WorkspaceMetrics[];
|
|
76
|
+
lastScalingAction?: Date;
|
|
77
|
+
}
|
|
78
|
+
export declare class ScalingPolicyService extends EventEmitter {
|
|
79
|
+
private thresholds;
|
|
80
|
+
private policies;
|
|
81
|
+
private conditionHistory;
|
|
82
|
+
constructor();
|
|
83
|
+
/**
|
|
84
|
+
* Get thresholds for a plan tier
|
|
85
|
+
*/
|
|
86
|
+
getThresholds(plan: string): ScalingThresholds;
|
|
87
|
+
/**
|
|
88
|
+
* Set custom thresholds for a plan
|
|
89
|
+
*/
|
|
90
|
+
setThresholds(plan: string, thresholds: Partial<ScalingThresholds>): void;
|
|
91
|
+
/**
|
|
92
|
+
* Get policies for a user (default + custom)
|
|
93
|
+
*/
|
|
94
|
+
getPolicies(userId: string): ScalingPolicy[];
|
|
95
|
+
/**
|
|
96
|
+
* Add custom policy for a user
|
|
97
|
+
*/
|
|
98
|
+
addPolicy(userId: string, policy: ScalingPolicy): void;
|
|
99
|
+
/**
|
|
100
|
+
* Evaluate scaling decision based on current context
|
|
101
|
+
*/
|
|
102
|
+
evaluate(context: UserScalingContext): ScalingDecision;
|
|
103
|
+
/**
|
|
104
|
+
* Calculate aggregate metrics from workspace metrics
|
|
105
|
+
*/
|
|
106
|
+
private calculateAggregateMetrics;
|
|
107
|
+
/**
|
|
108
|
+
* Evaluate conditions with duration support
|
|
109
|
+
*/
|
|
110
|
+
private evaluateConditions;
|
|
111
|
+
/**
|
|
112
|
+
* Compare values based on operator
|
|
113
|
+
*/
|
|
114
|
+
private compareValues;
|
|
115
|
+
/**
|
|
116
|
+
* Get max workspaces for a plan
|
|
117
|
+
*/
|
|
118
|
+
getMaxWorkspaces(plan: string): number;
|
|
119
|
+
}
|
|
120
|
+
export declare function getScalingPolicyService(): ScalingPolicyService;
|
|
121
|
+
//# sourceMappingURL=scaling-policy.d.ts.map
|