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,500 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ledger Store
|
|
3
|
+
*
|
|
4
|
+
* Persists within-session state as JSON files.
|
|
5
|
+
* One ledger per agent, overwritten each session.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - agentId index for O(1) lookups
|
|
9
|
+
* - Hash-based filenames to avoid collisions
|
|
10
|
+
* - File locking for concurrent access safety
|
|
11
|
+
*/
|
|
12
|
+
import fs from 'node:fs/promises';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import crypto from 'node:crypto';
|
|
15
|
+
/** Lock expiry time in milliseconds (5 minutes) */
|
|
16
|
+
const LOCK_EXPIRY_MS = 5 * 60 * 1000;
|
|
17
|
+
export class LedgerStore {
|
|
18
|
+
basePath;
|
|
19
|
+
indexPath;
|
|
20
|
+
index = null;
|
|
21
|
+
locks = new Map();
|
|
22
|
+
indexLock = null; // Global lock for index operations
|
|
23
|
+
constructor(basePath) {
|
|
24
|
+
this.basePath = basePath;
|
|
25
|
+
this.indexPath = path.join(basePath, '_agent-id-index.json');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Ensure the ledgers directory exists
|
|
29
|
+
*/
|
|
30
|
+
async initialize() {
|
|
31
|
+
await fs.mkdir(this.basePath, { recursive: true });
|
|
32
|
+
await this.loadIndex();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generate a unique, collision-free filename from agent name
|
|
36
|
+
* Uses SHA-256 hash prefix + sanitized name for readability
|
|
37
|
+
*/
|
|
38
|
+
getFilenameForAgent(agentName) {
|
|
39
|
+
// Create a short hash to ensure uniqueness
|
|
40
|
+
const hash = crypto.createHash('sha256').update(agentName).digest('hex').slice(0, 8);
|
|
41
|
+
// Also include sanitized name for human readability
|
|
42
|
+
const safeName = agentName.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 32);
|
|
43
|
+
return `${safeName}_${hash}`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the file path for an agent's ledger
|
|
47
|
+
*/
|
|
48
|
+
getLedgerPath(agentName) {
|
|
49
|
+
const filename = this.getFilenameForAgent(agentName);
|
|
50
|
+
return path.join(this.basePath, `${filename}.json`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Load the agentId index from disk
|
|
54
|
+
*/
|
|
55
|
+
async loadIndex() {
|
|
56
|
+
try {
|
|
57
|
+
const content = await fs.readFile(this.indexPath, 'utf-8');
|
|
58
|
+
this.index = JSON.parse(content);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (error.code === 'ENOENT') {
|
|
62
|
+
this.index = {};
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Save the agentId index to disk (atomic write)
|
|
71
|
+
*/
|
|
72
|
+
async saveIndex() {
|
|
73
|
+
if (!this.index)
|
|
74
|
+
return;
|
|
75
|
+
const tempPath = `${this.indexPath}.tmp.${Date.now()}`;
|
|
76
|
+
await fs.writeFile(tempPath, JSON.stringify(this.index, null, 2), 'utf-8');
|
|
77
|
+
await fs.rename(tempPath, this.indexPath);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Acquire the global index lock
|
|
81
|
+
*/
|
|
82
|
+
async acquireIndexLock() {
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
const timeoutMs = 5000;
|
|
85
|
+
while (this.indexLock) {
|
|
86
|
+
// Check for expired lock
|
|
87
|
+
if (Date.now() - this.indexLock.acquiredAt > LOCK_EXPIRY_MS) {
|
|
88
|
+
this.indexLock.release();
|
|
89
|
+
this.indexLock = null;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
// Check timeout
|
|
93
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
94
|
+
throw new Error('Index lock acquisition timeout');
|
|
95
|
+
}
|
|
96
|
+
// Wait briefly and retry
|
|
97
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
98
|
+
}
|
|
99
|
+
let release = () => { };
|
|
100
|
+
const promise = new Promise((resolve) => {
|
|
101
|
+
release = resolve;
|
|
102
|
+
});
|
|
103
|
+
this.indexLock = { promise, release, acquiredAt: Date.now() };
|
|
104
|
+
return () => {
|
|
105
|
+
release();
|
|
106
|
+
this.indexLock = null;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Update the index with a new agentId -> agentName mapping (with locking)
|
|
111
|
+
*/
|
|
112
|
+
async updateIndex(agentId, agentName) {
|
|
113
|
+
const releaseIndexLock = await this.acquireIndexLock();
|
|
114
|
+
try {
|
|
115
|
+
if (!this.index)
|
|
116
|
+
await this.loadIndex();
|
|
117
|
+
if (this.index) {
|
|
118
|
+
this.index[agentId] = agentName;
|
|
119
|
+
await this.saveIndex();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
releaseIndexLock();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Remove an agentId from the index (with locking)
|
|
128
|
+
*/
|
|
129
|
+
async removeFromIndex(agentId) {
|
|
130
|
+
const releaseIndexLock = await this.acquireIndexLock();
|
|
131
|
+
try {
|
|
132
|
+
if (!this.index)
|
|
133
|
+
await this.loadIndex();
|
|
134
|
+
if (this.index && this.index[agentId]) {
|
|
135
|
+
delete this.index[agentId];
|
|
136
|
+
await this.saveIndex();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
releaseIndexLock();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Check and release expired locks
|
|
145
|
+
*/
|
|
146
|
+
cleanupExpiredLocks() {
|
|
147
|
+
const now = Date.now();
|
|
148
|
+
for (const [key, lock] of this.locks.entries()) {
|
|
149
|
+
if (now - lock.acquiredAt > LOCK_EXPIRY_MS) {
|
|
150
|
+
lock.release();
|
|
151
|
+
this.locks.delete(key);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Acquire a lock for an agent's ledger with retry logic
|
|
157
|
+
* @param agentName - Agent name to lock
|
|
158
|
+
* @param maxRetries - Maximum number of retry attempts (default: 5)
|
|
159
|
+
* @param baseDelayMs - Base delay for exponential backoff (default: 100ms)
|
|
160
|
+
* @param timeoutMs - Maximum time to wait for lock (default: 10000ms)
|
|
161
|
+
*/
|
|
162
|
+
async acquireLock(agentName, maxRetries = 5, baseDelayMs = 100, timeoutMs = 10000) {
|
|
163
|
+
const key = this.getFilenameForAgent(agentName);
|
|
164
|
+
const startTime = Date.now();
|
|
165
|
+
// Cleanup any expired locks first
|
|
166
|
+
this.cleanupExpiredLocks();
|
|
167
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
168
|
+
// Check timeout
|
|
169
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
170
|
+
throw new Error(`Lock acquisition timeout for agent "${agentName}" after ${timeoutMs}ms`);
|
|
171
|
+
}
|
|
172
|
+
const existingLock = this.locks.get(key);
|
|
173
|
+
// Check if existing lock is expired
|
|
174
|
+
if (existingLock && Date.now() - existingLock.acquiredAt > LOCK_EXPIRY_MS) {
|
|
175
|
+
existingLock.release();
|
|
176
|
+
this.locks.delete(key);
|
|
177
|
+
}
|
|
178
|
+
if (!existingLock || Date.now() - existingLock.acquiredAt > LOCK_EXPIRY_MS) {
|
|
179
|
+
// Lock is available, acquire it
|
|
180
|
+
let release = () => { };
|
|
181
|
+
const promise = new Promise((resolve) => {
|
|
182
|
+
release = resolve;
|
|
183
|
+
});
|
|
184
|
+
this.locks.set(key, { promise, release, acquiredAt: Date.now() });
|
|
185
|
+
return () => {
|
|
186
|
+
release();
|
|
187
|
+
this.locks.delete(key);
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
// Lock is occupied, wait with exponential backoff
|
|
191
|
+
const delay = Math.min(baseDelayMs * Math.pow(2, attempt), 2000); // Cap at 2s
|
|
192
|
+
try {
|
|
193
|
+
// Race between lock release and timeout
|
|
194
|
+
await Promise.race([
|
|
195
|
+
existingLock.promise,
|
|
196
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('retry')), delay)),
|
|
197
|
+
]);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// Timeout or retry, continue to next attempt
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Final attempt - wait for existing lock or throw
|
|
204
|
+
const existingLock = this.locks.get(key);
|
|
205
|
+
if (existingLock) {
|
|
206
|
+
const remainingTime = timeoutMs - (Date.now() - startTime);
|
|
207
|
+
if (remainingTime > 0) {
|
|
208
|
+
await Promise.race([
|
|
209
|
+
existingLock.promise,
|
|
210
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Lock acquisition timeout for agent "${agentName}"`)), remainingTime)),
|
|
211
|
+
]);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
throw new Error(`Lock acquisition timeout for agent "${agentName}" after ${maxRetries} retries`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// Lock should be available now
|
|
218
|
+
let release = () => { };
|
|
219
|
+
const promise = new Promise((resolve) => {
|
|
220
|
+
release = resolve;
|
|
221
|
+
});
|
|
222
|
+
this.locks.set(key, { promise, release, acquiredAt: Date.now() });
|
|
223
|
+
return () => {
|
|
224
|
+
release();
|
|
225
|
+
this.locks.delete(key);
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Save a ledger for an agent (with locking)
|
|
230
|
+
*/
|
|
231
|
+
async save(agentName, ledger) {
|
|
232
|
+
await this.initialize();
|
|
233
|
+
const releaseLock = await this.acquireLock(agentName);
|
|
234
|
+
try {
|
|
235
|
+
const filePath = this.getLedgerPath(agentName);
|
|
236
|
+
// Ensure updatedAt is set
|
|
237
|
+
const ledgerToSave = {
|
|
238
|
+
...ledger,
|
|
239
|
+
agentName,
|
|
240
|
+
updatedAt: new Date(),
|
|
241
|
+
};
|
|
242
|
+
// Write to temp file first, then rename (atomic write)
|
|
243
|
+
const tempPath = `${filePath}.tmp.${Date.now()}`;
|
|
244
|
+
await fs.writeFile(tempPath, JSON.stringify(ledgerToSave, null, 2), 'utf-8');
|
|
245
|
+
await fs.rename(tempPath, filePath);
|
|
246
|
+
// Update agentId index
|
|
247
|
+
if (ledger.agentId) {
|
|
248
|
+
await this.updateIndex(ledger.agentId, agentName);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
releaseLock();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Load a ledger for an agent
|
|
257
|
+
*/
|
|
258
|
+
async load(agentName) {
|
|
259
|
+
const filePath = this.getLedgerPath(agentName);
|
|
260
|
+
try {
|
|
261
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
262
|
+
const ledger = JSON.parse(content);
|
|
263
|
+
// Parse date strings back to Date objects
|
|
264
|
+
ledger.updatedAt = new Date(ledger.updatedAt);
|
|
265
|
+
if (ledger.keyDecisions) {
|
|
266
|
+
ledger.keyDecisions = ledger.keyDecisions.map((d) => ({
|
|
267
|
+
...d,
|
|
268
|
+
timestamp: new Date(d.timestamp),
|
|
269
|
+
}));
|
|
270
|
+
}
|
|
271
|
+
return ledger;
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
if (error.code === 'ENOENT') {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Delete a ledger for an agent
|
|
282
|
+
*/
|
|
283
|
+
async delete(agentName) {
|
|
284
|
+
const releaseLock = await this.acquireLock(agentName);
|
|
285
|
+
try {
|
|
286
|
+
// Load ledger to get agentId for index cleanup
|
|
287
|
+
const ledger = await this.load(agentName);
|
|
288
|
+
const filePath = this.getLedgerPath(agentName);
|
|
289
|
+
try {
|
|
290
|
+
await fs.unlink(filePath);
|
|
291
|
+
// Remove from index
|
|
292
|
+
if (ledger?.agentId) {
|
|
293
|
+
await this.removeFromIndex(ledger.agentId);
|
|
294
|
+
}
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
if (error.code === 'ENOENT') {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
throw error;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
finally {
|
|
305
|
+
releaseLock();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Check if a ledger exists for an agent
|
|
310
|
+
*/
|
|
311
|
+
async exists(agentName) {
|
|
312
|
+
const filePath = this.getLedgerPath(agentName);
|
|
313
|
+
try {
|
|
314
|
+
await fs.access(filePath);
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* List all agents with ledgers
|
|
323
|
+
*/
|
|
324
|
+
async listAgents() {
|
|
325
|
+
try {
|
|
326
|
+
await this.initialize();
|
|
327
|
+
const files = await fs.readdir(this.basePath);
|
|
328
|
+
const agents = [];
|
|
329
|
+
for (const file of files) {
|
|
330
|
+
// Skip index file and non-JSON files
|
|
331
|
+
if (!file.endsWith('.json') || file.startsWith('_'))
|
|
332
|
+
continue;
|
|
333
|
+
try {
|
|
334
|
+
const filePath = path.join(this.basePath, file);
|
|
335
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
336
|
+
const ledger = JSON.parse(content);
|
|
337
|
+
if (ledger.agentName) {
|
|
338
|
+
agents.push(ledger.agentName);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
// Skip corrupted files
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return agents;
|
|
346
|
+
}
|
|
347
|
+
catch (error) {
|
|
348
|
+
if (error.code === 'ENOENT') {
|
|
349
|
+
return [];
|
|
350
|
+
}
|
|
351
|
+
throw error;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Update specific fields in a ledger (merge, with locking)
|
|
356
|
+
*/
|
|
357
|
+
async update(agentName, updates) {
|
|
358
|
+
const releaseLock = await this.acquireLock(agentName);
|
|
359
|
+
try {
|
|
360
|
+
const existing = await this.load(agentName);
|
|
361
|
+
if (!existing) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
const updated = {
|
|
365
|
+
...existing,
|
|
366
|
+
...updates,
|
|
367
|
+
agentName,
|
|
368
|
+
agentId: existing.agentId, // Preserve agentId
|
|
369
|
+
updatedAt: new Date(),
|
|
370
|
+
};
|
|
371
|
+
// Use internal save that doesn't acquire lock again
|
|
372
|
+
const filePath = this.getLedgerPath(agentName);
|
|
373
|
+
const tempPath = `${filePath}.tmp.${Date.now()}`;
|
|
374
|
+
await fs.writeFile(tempPath, JSON.stringify(updated, null, 2), 'utf-8');
|
|
375
|
+
await fs.rename(tempPath, filePath);
|
|
376
|
+
return updated;
|
|
377
|
+
}
|
|
378
|
+
finally {
|
|
379
|
+
releaseLock();
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Add an item to a list field (completed, inProgress, etc.)
|
|
384
|
+
*/
|
|
385
|
+
async addToList(agentName, field, item) {
|
|
386
|
+
const releaseLock = await this.acquireLock(agentName);
|
|
387
|
+
try {
|
|
388
|
+
const ledger = await this.load(agentName);
|
|
389
|
+
if (!ledger) {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
if (!ledger[field].includes(item)) {
|
|
393
|
+
ledger[field].push(item);
|
|
394
|
+
const filePath = this.getLedgerPath(agentName);
|
|
395
|
+
const tempPath = `${filePath}.tmp.${Date.now()}`;
|
|
396
|
+
await fs.writeFile(tempPath, JSON.stringify({ ...ledger, updatedAt: new Date() }, null, 2), 'utf-8');
|
|
397
|
+
await fs.rename(tempPath, filePath);
|
|
398
|
+
}
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
finally {
|
|
402
|
+
releaseLock();
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Add a decision to the ledger
|
|
407
|
+
*/
|
|
408
|
+
async addDecision(agentName, decision) {
|
|
409
|
+
const releaseLock = await this.acquireLock(agentName);
|
|
410
|
+
try {
|
|
411
|
+
const ledger = await this.load(agentName);
|
|
412
|
+
if (!ledger) {
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
ledger.keyDecisions.push({
|
|
416
|
+
...decision,
|
|
417
|
+
timestamp: new Date(),
|
|
418
|
+
});
|
|
419
|
+
const filePath = this.getLedgerPath(agentName);
|
|
420
|
+
const tempPath = `${filePath}.tmp.${Date.now()}`;
|
|
421
|
+
await fs.writeFile(tempPath, JSON.stringify({ ...ledger, updatedAt: new Date() }, null, 2), 'utf-8');
|
|
422
|
+
await fs.rename(tempPath, filePath);
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
finally {
|
|
426
|
+
releaseLock();
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Create an empty ledger for an agent
|
|
431
|
+
*/
|
|
432
|
+
async create(agentName, cli, sessionId, agentId) {
|
|
433
|
+
const ledger = {
|
|
434
|
+
agentName,
|
|
435
|
+
agentId,
|
|
436
|
+
sessionId,
|
|
437
|
+
cli,
|
|
438
|
+
currentTask: '',
|
|
439
|
+
completed: [],
|
|
440
|
+
inProgress: [],
|
|
441
|
+
blocked: [],
|
|
442
|
+
keyDecisions: [],
|
|
443
|
+
uncertainItems: [],
|
|
444
|
+
fileContext: [],
|
|
445
|
+
updatedAt: new Date(),
|
|
446
|
+
};
|
|
447
|
+
await this.save(agentName, ledger);
|
|
448
|
+
return ledger;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Find a ledger by agent ID (O(1) via index)
|
|
452
|
+
*/
|
|
453
|
+
async findByAgentId(agentId) {
|
|
454
|
+
await this.initialize();
|
|
455
|
+
// Use index for O(1) lookup
|
|
456
|
+
if (this.index && this.index[agentId]) {
|
|
457
|
+
const agentName = this.index[agentId];
|
|
458
|
+
const ledger = await this.load(agentName);
|
|
459
|
+
// Verify the agentId still matches (index could be stale)
|
|
460
|
+
if (ledger && ledger.agentId === agentId) {
|
|
461
|
+
return ledger;
|
|
462
|
+
}
|
|
463
|
+
// Index is stale, remove it
|
|
464
|
+
await this.removeFromIndex(agentId);
|
|
465
|
+
}
|
|
466
|
+
// Fallback: scan all ledgers (and rebuild index)
|
|
467
|
+
const agents = await this.listAgents();
|
|
468
|
+
for (const agentName of agents) {
|
|
469
|
+
const ledger = await this.load(agentName);
|
|
470
|
+
if (ledger && ledger.agentId === agentId) {
|
|
471
|
+
// Update index for future lookups
|
|
472
|
+
await this.updateIndex(agentId, agentName);
|
|
473
|
+
return ledger;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Rebuild the agentId index from all ledgers
|
|
480
|
+
*/
|
|
481
|
+
async rebuildIndex() {
|
|
482
|
+
await this.initialize();
|
|
483
|
+
const releaseIndexLock = await this.acquireIndexLock();
|
|
484
|
+
try {
|
|
485
|
+
this.index = {};
|
|
486
|
+
const agents = await this.listAgents();
|
|
487
|
+
for (const agentName of agents) {
|
|
488
|
+
const ledger = await this.load(agentName);
|
|
489
|
+
if (ledger?.agentId) {
|
|
490
|
+
this.index[ledger.agentId] = agentName;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
await this.saveIndex();
|
|
494
|
+
}
|
|
495
|
+
finally {
|
|
496
|
+
releaseIndexLock();
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
//# sourceMappingURL=ledger-store.js.map
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuity Manager
|
|
3
|
+
*
|
|
4
|
+
* Central service for managing session continuity.
|
|
5
|
+
* Coordinates ledger storage, handoff creation, and context injection.
|
|
6
|
+
*/
|
|
7
|
+
import { type ParsedHandoffContent } from './parser.js';
|
|
8
|
+
import type { Ledger, Handoff, HandoffTrigger, ContinuityPaths, StartupContext, SaveLedgerOptions, SearchOptions, ContinuityCommand } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Options for ContinuityManager
|
|
11
|
+
*/
|
|
12
|
+
export interface ContinuityManagerOptions {
|
|
13
|
+
/** Base directory for continuity data (default: ~/.agent-relay/continuity) */
|
|
14
|
+
basePath?: string;
|
|
15
|
+
/** Default CLI type for new ledgers */
|
|
16
|
+
defaultCli?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* ContinuityManager - Central service for session continuity
|
|
20
|
+
*/
|
|
21
|
+
export declare class ContinuityManager {
|
|
22
|
+
private paths;
|
|
23
|
+
private ledgerStore;
|
|
24
|
+
private handoffStore;
|
|
25
|
+
private defaultCli;
|
|
26
|
+
private initialized;
|
|
27
|
+
constructor(options?: ContinuityManagerOptions);
|
|
28
|
+
/**
|
|
29
|
+
* Initialize the continuity system (create directories)
|
|
30
|
+
*/
|
|
31
|
+
initialize(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Generate a session ID
|
|
34
|
+
*/
|
|
35
|
+
private generateSessionId;
|
|
36
|
+
/**
|
|
37
|
+
* Generate a unique agent ID using UUID v4
|
|
38
|
+
*/
|
|
39
|
+
generateAgentId(): string;
|
|
40
|
+
/**
|
|
41
|
+
* Get or create a ledger for an agent
|
|
42
|
+
*/
|
|
43
|
+
getOrCreateLedger(agentName: string, cli?: string, agentId?: string): Promise<Ledger>;
|
|
44
|
+
/**
|
|
45
|
+
* Find a ledger by agent ID (for resume functionality)
|
|
46
|
+
*/
|
|
47
|
+
findLedgerByAgentId(agentId: string): Promise<Ledger | null>;
|
|
48
|
+
/**
|
|
49
|
+
* Get a ledger for an agent (returns null if not exists)
|
|
50
|
+
*/
|
|
51
|
+
getLedger(agentName: string): Promise<Ledger | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Save a ledger, optionally creating a handoff
|
|
54
|
+
*/
|
|
55
|
+
saveLedger(agentName: string, content: string | Partial<Ledger>, options?: SaveLedgerOptions): Promise<Ledger>;
|
|
56
|
+
/**
|
|
57
|
+
* Update specific fields in a ledger
|
|
58
|
+
*/
|
|
59
|
+
updateLedger(agentName: string, updates: Partial<Omit<Ledger, 'agentName' | 'updatedAt'>>): Promise<Ledger | null>;
|
|
60
|
+
/**
|
|
61
|
+
* Add an uncertain item to the ledger
|
|
62
|
+
*/
|
|
63
|
+
addUncertainItem(agentName: string, item: string): Promise<boolean>;
|
|
64
|
+
/**
|
|
65
|
+
* Delete a ledger
|
|
66
|
+
*/
|
|
67
|
+
deleteLedger(agentName: string): Promise<boolean>;
|
|
68
|
+
/**
|
|
69
|
+
* Create a handoff from a ledger
|
|
70
|
+
*/
|
|
71
|
+
createHandoffFromLedger(ledger: Ledger, triggerReason: HandoffTrigger): Promise<Handoff>;
|
|
72
|
+
/**
|
|
73
|
+
* Create a handoff from parsed content
|
|
74
|
+
*/
|
|
75
|
+
createHandoff(agentName: string, content: string | ParsedHandoffContent, triggerReason?: HandoffTrigger): Promise<Handoff>;
|
|
76
|
+
/**
|
|
77
|
+
* Get the latest handoff for an agent
|
|
78
|
+
*/
|
|
79
|
+
getLatestHandoff(agentName: string): Promise<Handoff | null>;
|
|
80
|
+
/**
|
|
81
|
+
* Get a handoff by ID
|
|
82
|
+
*/
|
|
83
|
+
getHandoff(handoffId: string): Promise<Handoff | null>;
|
|
84
|
+
/**
|
|
85
|
+
* List handoffs for an agent
|
|
86
|
+
*/
|
|
87
|
+
listHandoffs(agentName: string, limit?: number): Promise<Handoff[]>;
|
|
88
|
+
/**
|
|
89
|
+
* Search handoffs (basic text search - FTS to be added)
|
|
90
|
+
*/
|
|
91
|
+
searchHandoffs(query: string, options?: SearchOptions): Promise<Handoff[]>;
|
|
92
|
+
/**
|
|
93
|
+
* Get startup context for an agent (for injection on spawn).
|
|
94
|
+
* Applies defensive filtering to remove any placeholder values.
|
|
95
|
+
*/
|
|
96
|
+
getStartupContext(agentName: string): Promise<StartupContext | null>;
|
|
97
|
+
/**
|
|
98
|
+
* Filter placeholder values from a ledger (defensive)
|
|
99
|
+
*/
|
|
100
|
+
private filterLedgerPlaceholders;
|
|
101
|
+
/**
|
|
102
|
+
* Filter placeholder values from a handoff (defensive)
|
|
103
|
+
*/
|
|
104
|
+
private filterHandoffPlaceholders;
|
|
105
|
+
/**
|
|
106
|
+
* Format a ledger for display/injection
|
|
107
|
+
*/
|
|
108
|
+
formatLedger(ledger: Ledger, compact?: boolean): string;
|
|
109
|
+
/**
|
|
110
|
+
* Format a handoff for display/injection
|
|
111
|
+
*/
|
|
112
|
+
formatHandoff(handoff: Handoff, compact?: boolean): string;
|
|
113
|
+
/**
|
|
114
|
+
* Format search results
|
|
115
|
+
*/
|
|
116
|
+
formatSearchResults(handoffs: Handoff[], query: string): string;
|
|
117
|
+
/**
|
|
118
|
+
* Get a brief status summary
|
|
119
|
+
*/
|
|
120
|
+
getBriefStatus(agentName: string): Promise<string>;
|
|
121
|
+
/**
|
|
122
|
+
* Handle a continuity command from agent output
|
|
123
|
+
*/
|
|
124
|
+
handleCommand(agentName: string, command: ContinuityCommand): Promise<string | null>;
|
|
125
|
+
/**
|
|
126
|
+
* Auto-save current state (called by wrapper on agent exit)
|
|
127
|
+
* @param agentName - Name of the agent
|
|
128
|
+
* @param reason - Why the save is happening
|
|
129
|
+
* @param sessionEndData - Optional data from [[SESSION_END]] block to populate handoff
|
|
130
|
+
*/
|
|
131
|
+
autoSave(agentName: string, reason: 'crash' | 'restart' | 'session_end', sessionEndData?: {
|
|
132
|
+
summary?: string;
|
|
133
|
+
completedTasks?: string[];
|
|
134
|
+
}): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Clean placeholder data from all ledgers.
|
|
137
|
+
* Removes known placeholder/template values that were incorrectly saved.
|
|
138
|
+
* Returns the number of ledgers that were cleaned.
|
|
139
|
+
*/
|
|
140
|
+
cleanupPlaceholders(): Promise<{
|
|
141
|
+
cleaned: number;
|
|
142
|
+
agents: string[];
|
|
143
|
+
}>;
|
|
144
|
+
/**
|
|
145
|
+
* Clear all continuity data for an agent
|
|
146
|
+
*/
|
|
147
|
+
clearAgent(agentName: string): Promise<void>;
|
|
148
|
+
/**
|
|
149
|
+
* List all agents with continuity data
|
|
150
|
+
*/
|
|
151
|
+
listAgents(): Promise<string[]>;
|
|
152
|
+
/**
|
|
153
|
+
* Get continuity paths
|
|
154
|
+
*/
|
|
155
|
+
getPaths(): ContinuityPaths;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get the singleton ContinuityManager instance (sync version)
|
|
159
|
+
*
|
|
160
|
+
* Note: This is safe for most uses since ContinuityManager methods
|
|
161
|
+
* call initialize() internally. The race condition only matters
|
|
162
|
+
* if multiple calls happen before the first completes AND they
|
|
163
|
+
* pass different options (which is unlikely in practice).
|
|
164
|
+
*/
|
|
165
|
+
export declare function getContinuityManager(options?: ContinuityManagerOptions): ContinuityManager;
|
|
166
|
+
/**
|
|
167
|
+
* Get the singleton ContinuityManager instance (async version)
|
|
168
|
+
*
|
|
169
|
+
* This is the thread-safe version that ensures only one instance
|
|
170
|
+
* is created even with concurrent calls. Use this in async contexts
|
|
171
|
+
* where race conditions are possible.
|
|
172
|
+
*/
|
|
173
|
+
export declare function getContinuityManagerAsync(options?: ContinuityManagerOptions): Promise<ContinuityManager>;
|
|
174
|
+
/**
|
|
175
|
+
* Reset the singleton instance (for testing)
|
|
176
|
+
*/
|
|
177
|
+
export declare function resetContinuityManager(): void;
|
|
178
|
+
//# sourceMappingURL=manager.d.ts.map
|