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,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gossip-Based Health Broadcast
|
|
3
|
+
*
|
|
4
|
+
* Implements P4: Agents broadcast heartbeats via relay.
|
|
5
|
+
* Collective failure detection without central monitor.
|
|
6
|
+
*
|
|
7
|
+
* Each agent:
|
|
8
|
+
* - Periodically broadcasts HEARTBEAT message to all agents
|
|
9
|
+
* - Tracks health of all known peers
|
|
10
|
+
* - Detects failures when peer heartbeats go stale
|
|
11
|
+
* - Emits events for peer health changes
|
|
12
|
+
*/
|
|
13
|
+
import { EventEmitter } from 'events';
|
|
14
|
+
const DEFAULT_CONFIG = {
|
|
15
|
+
broadcastIntervalMs: 10000,
|
|
16
|
+
staleThresholdMs: 30000,
|
|
17
|
+
checkIntervalMs: 5000,
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Gossip Health Monitor
|
|
21
|
+
*
|
|
22
|
+
* Broadcasts heartbeats and tracks peer health via gossip protocol.
|
|
23
|
+
*/
|
|
24
|
+
export class GossipHealthMonitor extends EventEmitter {
|
|
25
|
+
config;
|
|
26
|
+
peers = new Map();
|
|
27
|
+
broadcastInterval;
|
|
28
|
+
checkInterval;
|
|
29
|
+
isRunning = false;
|
|
30
|
+
healthy = true;
|
|
31
|
+
constructor(config) {
|
|
32
|
+
super();
|
|
33
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Start gossip health monitoring
|
|
37
|
+
*/
|
|
38
|
+
start() {
|
|
39
|
+
if (this.isRunning)
|
|
40
|
+
return;
|
|
41
|
+
this.isRunning = true;
|
|
42
|
+
console.log(`[gossip] Started health broadcast for ${this.config.agentName}`);
|
|
43
|
+
// Start broadcasting heartbeats
|
|
44
|
+
this.broadcastInterval = setInterval(async () => {
|
|
45
|
+
try {
|
|
46
|
+
await this.broadcastHeartbeat();
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
console.error('[gossip] Broadcast error:', err);
|
|
50
|
+
}
|
|
51
|
+
}, this.config.broadcastIntervalMs);
|
|
52
|
+
// Start checking for stale peers
|
|
53
|
+
this.checkInterval = setInterval(() => {
|
|
54
|
+
this.checkStalePeers();
|
|
55
|
+
}, this.config.checkIntervalMs);
|
|
56
|
+
// Initial broadcast
|
|
57
|
+
this.broadcastHeartbeat().catch((err) => {
|
|
58
|
+
console.error('[gossip] Initial broadcast error:', err);
|
|
59
|
+
});
|
|
60
|
+
this.emit('started');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Stop gossip health monitoring
|
|
64
|
+
*/
|
|
65
|
+
stop() {
|
|
66
|
+
if (!this.isRunning)
|
|
67
|
+
return;
|
|
68
|
+
this.isRunning = false;
|
|
69
|
+
if (this.broadcastInterval) {
|
|
70
|
+
clearInterval(this.broadcastInterval);
|
|
71
|
+
this.broadcastInterval = undefined;
|
|
72
|
+
}
|
|
73
|
+
if (this.checkInterval) {
|
|
74
|
+
clearInterval(this.checkInterval);
|
|
75
|
+
this.checkInterval = undefined;
|
|
76
|
+
}
|
|
77
|
+
console.log(`[gossip] Stopped health broadcast for ${this.config.agentName}`);
|
|
78
|
+
this.emit('stopped');
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Broadcast heartbeat to all agents
|
|
82
|
+
*/
|
|
83
|
+
async broadcastHeartbeat() {
|
|
84
|
+
const heartbeat = {
|
|
85
|
+
type: 'HEARTBEAT',
|
|
86
|
+
agent: this.config.agentName,
|
|
87
|
+
agentId: this.config.agentId,
|
|
88
|
+
timestamp: Date.now(),
|
|
89
|
+
load: this.config.getLoad?.() ?? 0,
|
|
90
|
+
healthy: this.healthy,
|
|
91
|
+
isLeader: this.config.isLeader?.() ?? false,
|
|
92
|
+
taskCount: this.config.getTaskCount?.() ?? 0,
|
|
93
|
+
};
|
|
94
|
+
const message = `HEARTBEAT: ${JSON.stringify(heartbeat)}`;
|
|
95
|
+
await this.config.broadcast(message);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Process incoming heartbeat from another agent
|
|
99
|
+
*/
|
|
100
|
+
processHeartbeat(heartbeat) {
|
|
101
|
+
// Ignore our own heartbeats
|
|
102
|
+
if (heartbeat.agentId === this.config.agentId)
|
|
103
|
+
return;
|
|
104
|
+
const existing = this.peers.get(heartbeat.agent);
|
|
105
|
+
const wasHealthy = existing?.healthy ?? true;
|
|
106
|
+
const wasLeader = existing?.isLeader ?? false;
|
|
107
|
+
// Update peer state
|
|
108
|
+
const peer = {
|
|
109
|
+
name: heartbeat.agent,
|
|
110
|
+
lastHeartbeat: heartbeat.timestamp,
|
|
111
|
+
load: heartbeat.load,
|
|
112
|
+
healthy: heartbeat.healthy,
|
|
113
|
+
isLeader: heartbeat.isLeader,
|
|
114
|
+
taskCount: heartbeat.taskCount,
|
|
115
|
+
};
|
|
116
|
+
this.peers.set(heartbeat.agent, peer);
|
|
117
|
+
// Emit events for state changes
|
|
118
|
+
if (!existing) {
|
|
119
|
+
this.emit('peerDiscovered', peer);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
if (!wasHealthy && heartbeat.healthy) {
|
|
123
|
+
this.emit('peerRecovered', peer);
|
|
124
|
+
}
|
|
125
|
+
if (wasHealthy && !heartbeat.healthy) {
|
|
126
|
+
this.emit('peerUnhealthy', peer);
|
|
127
|
+
}
|
|
128
|
+
if (!wasLeader && heartbeat.isLeader) {
|
|
129
|
+
this.emit('newLeader', peer);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Parse heartbeat from relay message
|
|
135
|
+
*/
|
|
136
|
+
static parseHeartbeat(message) {
|
|
137
|
+
const match = message.match(/^HEARTBEAT:\s*(.+)$/);
|
|
138
|
+
if (!match)
|
|
139
|
+
return null;
|
|
140
|
+
try {
|
|
141
|
+
const data = JSON.parse(match[1]);
|
|
142
|
+
if (data.type === 'HEARTBEAT') {
|
|
143
|
+
return data;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// Invalid JSON
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Check for stale peers
|
|
153
|
+
*/
|
|
154
|
+
checkStalePeers() {
|
|
155
|
+
const now = Date.now();
|
|
156
|
+
for (const [name, peer] of this.peers) {
|
|
157
|
+
const age = now - peer.lastHeartbeat;
|
|
158
|
+
if (age > this.config.staleThresholdMs) {
|
|
159
|
+
if (peer.healthy) {
|
|
160
|
+
// Mark as unhealthy
|
|
161
|
+
peer.healthy = false;
|
|
162
|
+
console.log(`[gossip] Peer ${name} is stale (${Math.round(age / 1000)}s since last heartbeat)`);
|
|
163
|
+
this.emit('peerStale', { peer, age });
|
|
164
|
+
// If the stale peer was leader, emit leader lost
|
|
165
|
+
if (peer.isLeader) {
|
|
166
|
+
this.emit('leaderLost', peer);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Set this agent's health status
|
|
174
|
+
*/
|
|
175
|
+
setHealthy(healthy) {
|
|
176
|
+
if (this.healthy !== healthy) {
|
|
177
|
+
this.healthy = healthy;
|
|
178
|
+
// Broadcast immediately on health change
|
|
179
|
+
this.broadcastHeartbeat().catch((err) => {
|
|
180
|
+
console.error('[gossip] Immediate broadcast error:', err);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get all known peers
|
|
186
|
+
*/
|
|
187
|
+
getPeers() {
|
|
188
|
+
return Array.from(this.peers.values());
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get healthy peers
|
|
192
|
+
*/
|
|
193
|
+
getHealthyPeers() {
|
|
194
|
+
return this.getPeers().filter((p) => p.healthy);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get current leader from gossip
|
|
198
|
+
*/
|
|
199
|
+
getLeader() {
|
|
200
|
+
for (const peer of this.peers.values()) {
|
|
201
|
+
if (peer.isLeader && peer.healthy) {
|
|
202
|
+
return peer;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Get peer by name
|
|
209
|
+
*/
|
|
210
|
+
getPeer(name) {
|
|
211
|
+
return this.peers.get(name);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get status
|
|
215
|
+
*/
|
|
216
|
+
getStatus() {
|
|
217
|
+
const leader = this.getLeader();
|
|
218
|
+
return {
|
|
219
|
+
isRunning: this.isRunning,
|
|
220
|
+
agentName: this.config.agentName,
|
|
221
|
+
peerCount: this.peers.size,
|
|
222
|
+
healthyPeerCount: this.getHealthyPeers().length,
|
|
223
|
+
leader: leader?.name ?? null,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Create gossip health monitor with defaults
|
|
229
|
+
*/
|
|
230
|
+
export function createGossipHealth(agentName, agentId, broadcast, options) {
|
|
231
|
+
return new GossipHealthMonitor({
|
|
232
|
+
agentName,
|
|
233
|
+
agentId,
|
|
234
|
+
broadcast,
|
|
235
|
+
broadcastIntervalMs: 10000,
|
|
236
|
+
staleThresholdMs: 30000,
|
|
237
|
+
checkIntervalMs: 5000,
|
|
238
|
+
...options,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=gossip-health.js.map
|
|
@@ -60,4 +60,9 @@ export { metrics, type AgentMetrics, type SystemMetrics, type MetricPoint } from
|
|
|
60
60
|
export { AgentSupervisor, getSupervisor, type SupervisedAgent, type SupervisorConfig, } from './supervisor.js';
|
|
61
61
|
export { ContextPersistence, getContextPersistence, type AgentState, type Decision, type Artifact, type Handoff, type LedgerEntry, } from './context-persistence.js';
|
|
62
62
|
export { createContextHandler, detectProvider, ClaudeContextHandler, CodexContextHandler, GeminiContextHandler, type ProviderType, type ProviderContextConfig, type ClaudeHooksConfig, type CodexContextConfig, } from './provider-context.js';
|
|
63
|
+
export { AgentMemoryMonitor, getMemoryMonitor, formatBytes, type MemorySnapshot, type AgentMemoryMetrics, type MemoryThresholds, type MemoryMonitorConfig, type MemoryAlert, type CrashMemoryContext, } from './memory-monitor.js';
|
|
64
|
+
export { CrashInsightsService, getCrashInsights, type CrashRecord, type CrashAnalysis, type CrashPattern, type CrashStats, } from './crash-insights.js';
|
|
65
|
+
export { StatelessLeadCoordinator, createStatelessLead, type BeadsTask, type LeadHeartbeat, type StatelessLeadConfig, } from './stateless-lead.js';
|
|
66
|
+
export { LeaderWatchdog, createLeaderWatchdog, type LeaderWatchdogConfig, type ElectionResult, } from './leader-watchdog.js';
|
|
67
|
+
export { GossipHealthMonitor, createGossipHealth, type GossipHeartbeat, type PeerHealth, type GossipHealthConfig, } from './gossip-health.js';
|
|
63
68
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/resiliency/index.js
CHANGED
|
@@ -60,4 +60,9 @@ export { metrics } from './metrics.js';
|
|
|
60
60
|
export { AgentSupervisor, getSupervisor, } from './supervisor.js';
|
|
61
61
|
export { ContextPersistence, getContextPersistence, } from './context-persistence.js';
|
|
62
62
|
export { createContextHandler, detectProvider, ClaudeContextHandler, CodexContextHandler, GeminiContextHandler, } from './provider-context.js';
|
|
63
|
+
export { AgentMemoryMonitor, getMemoryMonitor, formatBytes, } from './memory-monitor.js';
|
|
64
|
+
export { CrashInsightsService, getCrashInsights, } from './crash-insights.js';
|
|
65
|
+
export { StatelessLeadCoordinator, createStatelessLead, } from './stateless-lead.js';
|
|
66
|
+
export { LeaderWatchdog, createLeaderWatchdog, } from './leader-watchdog.js';
|
|
67
|
+
export { GossipHealthMonitor, createGossipHealth, } from './gossip-health.js';
|
|
63
68
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leader Watchdog
|
|
3
|
+
*
|
|
4
|
+
* Implements P3: Monitor lead health, trigger promotion if lead dies.
|
|
5
|
+
* Integrates with AgentSupervisor and heartbeat system.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Monitors leader heartbeat file
|
|
9
|
+
* - Detects stale/missing leader
|
|
10
|
+
* - Triggers leader election or self-promotion
|
|
11
|
+
* - Integrates with supervisor events
|
|
12
|
+
*/
|
|
13
|
+
import { EventEmitter } from 'events';
|
|
14
|
+
import { LeadHeartbeat } from './stateless-lead.js';
|
|
15
|
+
/**
|
|
16
|
+
* Watchdog configuration
|
|
17
|
+
*/
|
|
18
|
+
export interface LeaderWatchdogConfig {
|
|
19
|
+
/** Path to .beads directory */
|
|
20
|
+
beadsDir: string;
|
|
21
|
+
/** This agent's name */
|
|
22
|
+
agentName: string;
|
|
23
|
+
/** This agent's unique ID */
|
|
24
|
+
agentId: string;
|
|
25
|
+
/** How often to check leader health (ms) */
|
|
26
|
+
checkIntervalMs: number;
|
|
27
|
+
/** Leader considered stale after this duration (ms) */
|
|
28
|
+
staleThresholdMs: number;
|
|
29
|
+
/** Callback when this agent should become leader */
|
|
30
|
+
onBecomeLeader: () => Promise<void>;
|
|
31
|
+
/** Callback to get all healthy agents for election */
|
|
32
|
+
getHealthyAgents: () => Promise<Array<{
|
|
33
|
+
name: string;
|
|
34
|
+
id: string;
|
|
35
|
+
spawnedAt: Date;
|
|
36
|
+
}>>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Election result
|
|
40
|
+
*/
|
|
41
|
+
export interface ElectionResult {
|
|
42
|
+
winner: string;
|
|
43
|
+
winnerId: string;
|
|
44
|
+
candidates: string[];
|
|
45
|
+
method: 'oldest' | 'self' | 'none';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Leader Watchdog
|
|
49
|
+
*
|
|
50
|
+
* Runs on each agent, monitors leader health, triggers election if needed.
|
|
51
|
+
*/
|
|
52
|
+
export declare class LeaderWatchdog extends EventEmitter {
|
|
53
|
+
private config;
|
|
54
|
+
private heartbeatPath;
|
|
55
|
+
private checkInterval?;
|
|
56
|
+
private isRunning;
|
|
57
|
+
private currentLeader;
|
|
58
|
+
private isLeader;
|
|
59
|
+
constructor(config: LeaderWatchdogConfig);
|
|
60
|
+
/**
|
|
61
|
+
* Start watching for leader health
|
|
62
|
+
*/
|
|
63
|
+
start(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Stop watching
|
|
66
|
+
*/
|
|
67
|
+
stop(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Check if current leader is healthy
|
|
70
|
+
*/
|
|
71
|
+
private checkLeaderHealth;
|
|
72
|
+
/**
|
|
73
|
+
* Trigger leader election
|
|
74
|
+
*/
|
|
75
|
+
private triggerElection;
|
|
76
|
+
/**
|
|
77
|
+
* Simple leader election: oldest healthy agent wins
|
|
78
|
+
*/
|
|
79
|
+
private electLeader;
|
|
80
|
+
/**
|
|
81
|
+
* Check if this agent is currently the leader
|
|
82
|
+
*/
|
|
83
|
+
isCurrentLeader(): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Get current leader info
|
|
86
|
+
*/
|
|
87
|
+
getCurrentLeader(): LeadHeartbeat | null;
|
|
88
|
+
/**
|
|
89
|
+
* Get watchdog status
|
|
90
|
+
*/
|
|
91
|
+
getStatus(): {
|
|
92
|
+
isRunning: boolean;
|
|
93
|
+
isLeader: boolean;
|
|
94
|
+
currentLeader: LeadHeartbeat | null;
|
|
95
|
+
agentName: string;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create a leader watchdog with defaults
|
|
100
|
+
*/
|
|
101
|
+
export declare function createLeaderWatchdog(beadsDir: string, agentName: string, agentId: string, callbacks: {
|
|
102
|
+
onBecomeLeader: () => Promise<void>;
|
|
103
|
+
getHealthyAgents: () => Promise<Array<{
|
|
104
|
+
name: string;
|
|
105
|
+
id: string;
|
|
106
|
+
spawnedAt: Date;
|
|
107
|
+
}>>;
|
|
108
|
+
}): LeaderWatchdog;
|
|
109
|
+
//# sourceMappingURL=leader-watchdog.d.ts.map
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leader Watchdog
|
|
3
|
+
*
|
|
4
|
+
* Implements P3: Monitor lead health, trigger promotion if lead dies.
|
|
5
|
+
* Integrates with AgentSupervisor and heartbeat system.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Monitors leader heartbeat file
|
|
9
|
+
* - Detects stale/missing leader
|
|
10
|
+
* - Triggers leader election or self-promotion
|
|
11
|
+
* - Integrates with supervisor events
|
|
12
|
+
*/
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { EventEmitter } from 'events';
|
|
15
|
+
import { StatelessLeadCoordinator } from './stateless-lead.js';
|
|
16
|
+
const DEFAULT_CONFIG = {
|
|
17
|
+
checkIntervalMs: 5000,
|
|
18
|
+
staleThresholdMs: 30000,
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Leader Watchdog
|
|
22
|
+
*
|
|
23
|
+
* Runs on each agent, monitors leader health, triggers election if needed.
|
|
24
|
+
*/
|
|
25
|
+
export class LeaderWatchdog extends EventEmitter {
|
|
26
|
+
config;
|
|
27
|
+
heartbeatPath;
|
|
28
|
+
checkInterval;
|
|
29
|
+
isRunning = false;
|
|
30
|
+
currentLeader = null;
|
|
31
|
+
isLeader = false;
|
|
32
|
+
constructor(config) {
|
|
33
|
+
super();
|
|
34
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
35
|
+
this.heartbeatPath = path.join(this.config.beadsDir, 'leader-heartbeat.json');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Start watching for leader health
|
|
39
|
+
*/
|
|
40
|
+
start() {
|
|
41
|
+
if (this.isRunning)
|
|
42
|
+
return;
|
|
43
|
+
this.isRunning = true;
|
|
44
|
+
console.log(`[watchdog] Started monitoring leader health (${this.config.agentName})`);
|
|
45
|
+
this.checkInterval = setInterval(async () => {
|
|
46
|
+
try {
|
|
47
|
+
await this.checkLeaderHealth();
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
console.error('[watchdog] Check error:', err);
|
|
51
|
+
this.emit('error', err);
|
|
52
|
+
}
|
|
53
|
+
}, this.config.checkIntervalMs);
|
|
54
|
+
// Initial check
|
|
55
|
+
this.checkLeaderHealth().catch((err) => {
|
|
56
|
+
console.error('[watchdog] Initial check error:', err);
|
|
57
|
+
});
|
|
58
|
+
this.emit('started');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Stop watching
|
|
62
|
+
*/
|
|
63
|
+
stop() {
|
|
64
|
+
if (!this.isRunning)
|
|
65
|
+
return;
|
|
66
|
+
this.isRunning = false;
|
|
67
|
+
if (this.checkInterval) {
|
|
68
|
+
clearInterval(this.checkInterval);
|
|
69
|
+
this.checkInterval = undefined;
|
|
70
|
+
}
|
|
71
|
+
console.log(`[watchdog] Stopped monitoring (${this.config.agentName})`);
|
|
72
|
+
this.emit('stopped');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if current leader is healthy
|
|
76
|
+
*/
|
|
77
|
+
async checkLeaderHealth() {
|
|
78
|
+
const heartbeat = await StatelessLeadCoordinator.readHeartbeat(this.config.beadsDir);
|
|
79
|
+
// No leader - trigger election
|
|
80
|
+
if (!heartbeat) {
|
|
81
|
+
console.log('[watchdog] No leader detected, triggering election');
|
|
82
|
+
await this.triggerElection('no_leader');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// Check if this is us
|
|
86
|
+
if (heartbeat.leadId === this.config.agentId) {
|
|
87
|
+
this.isLeader = true;
|
|
88
|
+
this.currentLeader = heartbeat;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.isLeader = false;
|
|
92
|
+
// Check if stale
|
|
93
|
+
const age = Date.now() - heartbeat.timestamp;
|
|
94
|
+
if (age > this.config.staleThresholdMs) {
|
|
95
|
+
console.log(`[watchdog] Leader ${heartbeat.leadName} is stale (${Math.round(age / 1000)}s old)`);
|
|
96
|
+
this.emit('leaderStale', { leader: heartbeat, age });
|
|
97
|
+
await this.triggerElection('stale_leader');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Leader is healthy
|
|
101
|
+
if (!this.currentLeader || this.currentLeader.leadId !== heartbeat.leadId) {
|
|
102
|
+
console.log(`[watchdog] Leader detected: ${heartbeat.leadName}`);
|
|
103
|
+
this.emit('leaderDetected', heartbeat);
|
|
104
|
+
}
|
|
105
|
+
this.currentLeader = heartbeat;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Trigger leader election
|
|
109
|
+
*/
|
|
110
|
+
async triggerElection(reason) {
|
|
111
|
+
console.log(`[watchdog] Triggering election (reason: ${reason})`);
|
|
112
|
+
this.emit('electionStarted', { reason });
|
|
113
|
+
const result = await this.electLeader();
|
|
114
|
+
if (result.method === 'none') {
|
|
115
|
+
console.log('[watchdog] No candidates for election');
|
|
116
|
+
this.emit('electionFailed', { reason: 'no_candidates' });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
console.log(`[watchdog] Election result: ${result.winner} (method: ${result.method})`);
|
|
120
|
+
this.emit('electionComplete', result);
|
|
121
|
+
// If we won, become leader
|
|
122
|
+
if (result.winnerId === this.config.agentId) {
|
|
123
|
+
console.log(`[watchdog] This agent (${this.config.agentName}) won the election, becoming leader`);
|
|
124
|
+
this.isLeader = true;
|
|
125
|
+
await this.config.onBecomeLeader();
|
|
126
|
+
this.emit('becameLeader');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Simple leader election: oldest healthy agent wins
|
|
131
|
+
*/
|
|
132
|
+
async electLeader() {
|
|
133
|
+
const candidates = await this.config.getHealthyAgents();
|
|
134
|
+
if (candidates.length === 0) {
|
|
135
|
+
return {
|
|
136
|
+
winner: '',
|
|
137
|
+
winnerId: '',
|
|
138
|
+
candidates: [],
|
|
139
|
+
method: 'none',
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// Sort by spawn time (oldest first)
|
|
143
|
+
candidates.sort((a, b) => a.spawnedAt.getTime() - b.spawnedAt.getTime());
|
|
144
|
+
const winner = candidates[0];
|
|
145
|
+
return {
|
|
146
|
+
winner: winner.name,
|
|
147
|
+
winnerId: winner.id,
|
|
148
|
+
candidates: candidates.map((c) => c.name),
|
|
149
|
+
method: 'oldest',
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check if this agent is currently the leader
|
|
154
|
+
*/
|
|
155
|
+
isCurrentLeader() {
|
|
156
|
+
return this.isLeader;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get current leader info
|
|
160
|
+
*/
|
|
161
|
+
getCurrentLeader() {
|
|
162
|
+
return this.currentLeader;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get watchdog status
|
|
166
|
+
*/
|
|
167
|
+
getStatus() {
|
|
168
|
+
return {
|
|
169
|
+
isRunning: this.isRunning,
|
|
170
|
+
isLeader: this.isLeader,
|
|
171
|
+
currentLeader: this.currentLeader,
|
|
172
|
+
agentName: this.config.agentName,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Create a leader watchdog with defaults
|
|
178
|
+
*/
|
|
179
|
+
export function createLeaderWatchdog(beadsDir, agentName, agentId, callbacks) {
|
|
180
|
+
return new LeaderWatchdog({
|
|
181
|
+
beadsDir,
|
|
182
|
+
agentName,
|
|
183
|
+
agentId,
|
|
184
|
+
...callbacks,
|
|
185
|
+
checkIntervalMs: 5000,
|
|
186
|
+
staleThresholdMs: 30000,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=leader-watchdog.js.map
|