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,665 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Policy Service
|
|
3
|
+
*
|
|
4
|
+
* Manages agent permissions and rules with multi-level fallback:
|
|
5
|
+
* 1. Repo-level policy (.claude/agents/*.md)
|
|
6
|
+
* 2. Workspace-level policy (from cloud API)
|
|
7
|
+
* 3. Built-in safe defaults
|
|
8
|
+
*
|
|
9
|
+
* Provides spawn authorization, tool permission checks, and audit logging.
|
|
10
|
+
*/
|
|
11
|
+
import fs from 'node:fs';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import { findAgentConfig } from '../utils/agent-config.js';
|
|
14
|
+
import os from 'node:os';
|
|
15
|
+
/** Built-in safe defaults when no policy exists */
|
|
16
|
+
const DEFAULT_POLICY = {
|
|
17
|
+
name: '*',
|
|
18
|
+
allowedTools: undefined, // All tools allowed by default
|
|
19
|
+
canSpawn: undefined, // Can spawn any agent
|
|
20
|
+
canMessage: undefined, // Can message any agent
|
|
21
|
+
maxSpawns: 10,
|
|
22
|
+
rateLimit: 60, // 60 messages per minute
|
|
23
|
+
canBeSpawned: true,
|
|
24
|
+
};
|
|
25
|
+
/** Restrictive defaults for unknown agents in strict mode */
|
|
26
|
+
const STRICT_DEFAULT_POLICY = {
|
|
27
|
+
name: '*',
|
|
28
|
+
allowedTools: ['Read', 'Grep', 'Glob'], // Read-only by default
|
|
29
|
+
canSpawn: [], // Cannot spawn
|
|
30
|
+
canMessage: ['Lead', 'Coordinator'], // Can only message leads
|
|
31
|
+
maxSpawns: 0,
|
|
32
|
+
rateLimit: 10,
|
|
33
|
+
canBeSpawned: false,
|
|
34
|
+
};
|
|
35
|
+
export class AgentPolicyService {
|
|
36
|
+
projectRoot;
|
|
37
|
+
workspaceId;
|
|
38
|
+
cloudFetcher;
|
|
39
|
+
cachedWorkspacePolicy;
|
|
40
|
+
cachedLocalPolicy;
|
|
41
|
+
policyCacheExpiry = 0;
|
|
42
|
+
localPolicyCacheExpiry = 0;
|
|
43
|
+
auditLog = [];
|
|
44
|
+
strictMode;
|
|
45
|
+
/** Cache TTL in milliseconds (5 minutes) */
|
|
46
|
+
static CACHE_TTL_MS = 5 * 60 * 1000;
|
|
47
|
+
/** Local policy cache TTL (1 minute - files can change) */
|
|
48
|
+
static LOCAL_CACHE_TTL_MS = 60 * 1000;
|
|
49
|
+
/** Maximum audit log entries to keep in memory */
|
|
50
|
+
static MAX_AUDIT_ENTRIES = 1000;
|
|
51
|
+
constructor(options) {
|
|
52
|
+
this.projectRoot = options.projectRoot;
|
|
53
|
+
this.workspaceId = options.workspaceId;
|
|
54
|
+
this.cloudFetcher = options.cloudFetcher;
|
|
55
|
+
this.strictMode = options.strictMode ?? false;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get the user-level policies directory
|
|
59
|
+
* Uses ~/.config/agent-relay/policies/ (not in source control)
|
|
60
|
+
*/
|
|
61
|
+
getUserPoliciesDir() {
|
|
62
|
+
const configDir = process.env.AGENT_RELAY_CONFIG_DIR ??
|
|
63
|
+
path.join(os.homedir(), '.config', 'agent-relay');
|
|
64
|
+
return path.join(configDir, 'policies');
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Load policies from user-level directory (PRPM-installable)
|
|
68
|
+
* Files are YAML/JSON with agent policy definitions
|
|
69
|
+
* Location: ~/.config/agent-relay/policies/*.yaml
|
|
70
|
+
*/
|
|
71
|
+
loadLocalPolicies() {
|
|
72
|
+
// Check cache
|
|
73
|
+
if (this.cachedLocalPolicy && Date.now() < this.localPolicyCacheExpiry) {
|
|
74
|
+
return this.cachedLocalPolicy;
|
|
75
|
+
}
|
|
76
|
+
const policiesDir = this.getUserPoliciesDir();
|
|
77
|
+
if (!fs.existsSync(policiesDir)) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const files = fs.readdirSync(policiesDir).filter(f => f.endsWith('.yaml') || f.endsWith('.yml') || f.endsWith('.json'));
|
|
82
|
+
if (files.length === 0) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
// Merge all policy files
|
|
86
|
+
const mergedAgents = [];
|
|
87
|
+
let mergedSettings = {
|
|
88
|
+
requireExplicitAgents: false,
|
|
89
|
+
auditEnabled: true,
|
|
90
|
+
maxTotalAgents: 50,
|
|
91
|
+
};
|
|
92
|
+
let mergedDefault = { ...DEFAULT_POLICY };
|
|
93
|
+
for (const file of files) {
|
|
94
|
+
const filePath = path.join(policiesDir, file);
|
|
95
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
96
|
+
let parsed;
|
|
97
|
+
if (file.endsWith('.json')) {
|
|
98
|
+
parsed = JSON.parse(content);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// Simple YAML parsing for policy files
|
|
102
|
+
parsed = this.parseSimpleYaml(content);
|
|
103
|
+
}
|
|
104
|
+
// Merge agents
|
|
105
|
+
if (Array.isArray(parsed.agents)) {
|
|
106
|
+
for (const agent of parsed.agents) {
|
|
107
|
+
if (agent && typeof agent === 'object' && 'name' in agent) {
|
|
108
|
+
mergedAgents.push(agent);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Merge settings (later files override)
|
|
113
|
+
if (parsed.settings && typeof parsed.settings === 'object') {
|
|
114
|
+
mergedSettings = { ...mergedSettings, ...parsed.settings };
|
|
115
|
+
}
|
|
116
|
+
// Merge default policy
|
|
117
|
+
if (parsed.defaultPolicy && typeof parsed.defaultPolicy === 'object') {
|
|
118
|
+
mergedDefault = { ...mergedDefault, ...parsed.defaultPolicy };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const policy = {
|
|
122
|
+
defaultPolicy: mergedDefault,
|
|
123
|
+
agents: mergedAgents,
|
|
124
|
+
settings: mergedSettings,
|
|
125
|
+
};
|
|
126
|
+
this.cachedLocalPolicy = policy;
|
|
127
|
+
this.localPolicyCacheExpiry = Date.now() + AgentPolicyService.LOCAL_CACHE_TTL_MS;
|
|
128
|
+
return policy;
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
console.error('[policy] Failed to load local policies:', err);
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Simple YAML parser for policy files
|
|
137
|
+
* Handles basic key: value and arrays
|
|
138
|
+
*/
|
|
139
|
+
parseSimpleYaml(content) {
|
|
140
|
+
const result = {};
|
|
141
|
+
const lines = content.split('\n');
|
|
142
|
+
let _currentKey = '';
|
|
143
|
+
let currentArray = null;
|
|
144
|
+
let currentObject = null;
|
|
145
|
+
let indent = 0;
|
|
146
|
+
for (const line of lines) {
|
|
147
|
+
const trimmed = line.trim();
|
|
148
|
+
// Skip comments and empty lines
|
|
149
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
150
|
+
continue;
|
|
151
|
+
// Calculate indentation
|
|
152
|
+
const lineIndent = line.length - line.trimStart().length;
|
|
153
|
+
// Array item
|
|
154
|
+
if (trimmed.startsWith('- ')) {
|
|
155
|
+
const value = trimmed.slice(2).trim();
|
|
156
|
+
// Object in array (e.g., "- name: Worker")
|
|
157
|
+
if (value.includes(':')) {
|
|
158
|
+
const [key, val] = value.split(':').map(s => s.trim());
|
|
159
|
+
currentObject = { [key]: this.parseValue(val) };
|
|
160
|
+
if (currentArray) {
|
|
161
|
+
currentArray.push(currentObject);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// Simple array value
|
|
166
|
+
if (currentArray) {
|
|
167
|
+
currentArray.push(this.parseValue(value));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// Key: value pair
|
|
173
|
+
const colonIdx = trimmed.indexOf(':');
|
|
174
|
+
if (colonIdx > 0) {
|
|
175
|
+
const key = trimmed.slice(0, colonIdx).trim();
|
|
176
|
+
const value = trimmed.slice(colonIdx + 1).trim();
|
|
177
|
+
// If we're inside an object in an array
|
|
178
|
+
if (currentObject && lineIndent > indent) {
|
|
179
|
+
currentObject[key] = this.parseValue(value);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
// Top-level or section key
|
|
183
|
+
if (value === '' || value === '|' || value === '>') {
|
|
184
|
+
// Start of array or nested object
|
|
185
|
+
_currentKey = key;
|
|
186
|
+
currentArray = [];
|
|
187
|
+
currentObject = null;
|
|
188
|
+
indent = lineIndent;
|
|
189
|
+
result[key] = currentArray;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// Simple key: value
|
|
193
|
+
if (lineIndent === 0) {
|
|
194
|
+
result[key] = this.parseValue(value);
|
|
195
|
+
_currentKey = '';
|
|
196
|
+
currentArray = null;
|
|
197
|
+
currentObject = null;
|
|
198
|
+
}
|
|
199
|
+
else if (currentObject) {
|
|
200
|
+
currentObject[key] = this.parseValue(value);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Parse a YAML value string
|
|
209
|
+
*/
|
|
210
|
+
parseValue(value) {
|
|
211
|
+
if (!value || value === '~' || value === 'null')
|
|
212
|
+
return null;
|
|
213
|
+
if (value === 'true')
|
|
214
|
+
return true;
|
|
215
|
+
if (value === 'false')
|
|
216
|
+
return false;
|
|
217
|
+
// Array notation [a, b, c]
|
|
218
|
+
if (value.startsWith('[') && value.endsWith(']')) {
|
|
219
|
+
const inner = value.slice(1, -1);
|
|
220
|
+
if (!inner.trim())
|
|
221
|
+
return [];
|
|
222
|
+
return inner.split(',').map(s => {
|
|
223
|
+
const trimmed = s.trim().replace(/^["']|["']$/g, '');
|
|
224
|
+
return trimmed;
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
// Number
|
|
228
|
+
if (/^-?\d+(\.\d+)?$/.test(value)) {
|
|
229
|
+
return parseFloat(value);
|
|
230
|
+
}
|
|
231
|
+
// String (remove quotes if present)
|
|
232
|
+
return value.replace(/^["']|["']$/g, '');
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Check if an agent can spawn another agent
|
|
236
|
+
*/
|
|
237
|
+
async canSpawn(spawnerName, targetName, targetCli) {
|
|
238
|
+
const spawnerPolicy = await this.getAgentPolicy(spawnerName);
|
|
239
|
+
const targetPolicy = await this.getAgentPolicy(targetName);
|
|
240
|
+
// Check if target can be spawned
|
|
241
|
+
if (targetPolicy.matchedPolicy?.canBeSpawned === false) {
|
|
242
|
+
const decision = {
|
|
243
|
+
allowed: false,
|
|
244
|
+
reason: `Agent "${targetName}" is not allowed to be spawned`,
|
|
245
|
+
policySource: targetPolicy.policySource,
|
|
246
|
+
matchedPolicy: targetPolicy.matchedPolicy,
|
|
247
|
+
};
|
|
248
|
+
this.audit('spawn', spawnerName, targetName, decision, { cli: targetCli });
|
|
249
|
+
return decision;
|
|
250
|
+
}
|
|
251
|
+
// Check if spawner can spawn
|
|
252
|
+
const canSpawnList = spawnerPolicy.matchedPolicy?.canSpawn;
|
|
253
|
+
if (canSpawnList !== undefined && canSpawnList.length > 0) {
|
|
254
|
+
const canSpawn = this.matchesPattern(targetName, canSpawnList);
|
|
255
|
+
if (!canSpawn) {
|
|
256
|
+
const decision = {
|
|
257
|
+
allowed: false,
|
|
258
|
+
reason: `Agent "${spawnerName}" is not allowed to spawn "${targetName}"`,
|
|
259
|
+
policySource: spawnerPolicy.policySource,
|
|
260
|
+
matchedPolicy: spawnerPolicy.matchedPolicy,
|
|
261
|
+
};
|
|
262
|
+
this.audit('spawn', spawnerName, targetName, decision, { cli: targetCli });
|
|
263
|
+
return decision;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// Check max spawns (would need spawn count tracking - placeholder)
|
|
267
|
+
const decision = {
|
|
268
|
+
allowed: true,
|
|
269
|
+
reason: 'Spawn permitted by policy',
|
|
270
|
+
policySource: spawnerPolicy.policySource,
|
|
271
|
+
matchedPolicy: spawnerPolicy.matchedPolicy,
|
|
272
|
+
};
|
|
273
|
+
this.audit('spawn', spawnerName, targetName, decision, { cli: targetCli });
|
|
274
|
+
return decision;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Check if an agent can send a message to another agent
|
|
278
|
+
*/
|
|
279
|
+
async canMessage(senderName, recipientName) {
|
|
280
|
+
const senderPolicy = await this.getAgentPolicy(senderName);
|
|
281
|
+
const canMessageList = senderPolicy.matchedPolicy?.canMessage;
|
|
282
|
+
if (canMessageList !== undefined && canMessageList.length > 0) {
|
|
283
|
+
const canMessage = this.matchesPattern(recipientName, canMessageList);
|
|
284
|
+
if (!canMessage) {
|
|
285
|
+
const decision = {
|
|
286
|
+
allowed: false,
|
|
287
|
+
reason: `Agent "${senderName}" is not allowed to message "${recipientName}"`,
|
|
288
|
+
policySource: senderPolicy.policySource,
|
|
289
|
+
matchedPolicy: senderPolicy.matchedPolicy,
|
|
290
|
+
};
|
|
291
|
+
this.audit('message', senderName, recipientName, decision);
|
|
292
|
+
return decision;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const decision = {
|
|
296
|
+
allowed: true,
|
|
297
|
+
reason: 'Message permitted by policy',
|
|
298
|
+
policySource: senderPolicy.policySource,
|
|
299
|
+
matchedPolicy: senderPolicy.matchedPolicy,
|
|
300
|
+
};
|
|
301
|
+
this.audit('message', senderName, recipientName, decision);
|
|
302
|
+
return decision;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Check if an agent can use a specific tool
|
|
306
|
+
*/
|
|
307
|
+
async canUseTool(agentName, toolName) {
|
|
308
|
+
const policy = await this.getAgentPolicy(agentName);
|
|
309
|
+
const allowedTools = policy.matchedPolicy?.allowedTools;
|
|
310
|
+
if (allowedTools !== undefined) {
|
|
311
|
+
// ["none"] means no tools allowed
|
|
312
|
+
if (allowedTools.length === 1 && allowedTools[0] === 'none') {
|
|
313
|
+
const decision = {
|
|
314
|
+
allowed: false,
|
|
315
|
+
reason: `Agent "${agentName}" is not allowed to use any tools`,
|
|
316
|
+
policySource: policy.policySource,
|
|
317
|
+
matchedPolicy: policy.matchedPolicy,
|
|
318
|
+
};
|
|
319
|
+
this.audit('tool', agentName, toolName, decision);
|
|
320
|
+
return decision;
|
|
321
|
+
}
|
|
322
|
+
// Check if tool is in allowed list
|
|
323
|
+
const allowed = this.matchesPattern(toolName, allowedTools);
|
|
324
|
+
if (!allowed) {
|
|
325
|
+
const decision = {
|
|
326
|
+
allowed: false,
|
|
327
|
+
reason: `Agent "${agentName}" is not allowed to use tool "${toolName}"`,
|
|
328
|
+
policySource: policy.policySource,
|
|
329
|
+
matchedPolicy: policy.matchedPolicy,
|
|
330
|
+
};
|
|
331
|
+
this.audit('tool', agentName, toolName, decision);
|
|
332
|
+
return decision;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const decision = {
|
|
336
|
+
allowed: true,
|
|
337
|
+
reason: 'Tool usage permitted by policy',
|
|
338
|
+
policySource: policy.policySource,
|
|
339
|
+
matchedPolicy: policy.matchedPolicy,
|
|
340
|
+
};
|
|
341
|
+
this.audit('tool', agentName, toolName, decision);
|
|
342
|
+
return decision;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Get the effective policy for an agent
|
|
346
|
+
* Fallback chain: repo config → user PRPM policies → cloud workspace → defaults
|
|
347
|
+
*/
|
|
348
|
+
async getAgentPolicy(agentName) {
|
|
349
|
+
// 1. Try repo-level config (.claude/agents/*.md)
|
|
350
|
+
const repoConfig = findAgentConfig(agentName, this.projectRoot);
|
|
351
|
+
if (repoConfig) {
|
|
352
|
+
return {
|
|
353
|
+
matchedPolicy: this.configToPolicy(repoConfig),
|
|
354
|
+
policySource: 'repo',
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
// 2. Try user-level PRPM policies (~/.config/agent-relay/policies/*.yaml)
|
|
358
|
+
const localPolicy = this.loadLocalPolicies();
|
|
359
|
+
if (localPolicy) {
|
|
360
|
+
// Check for strict mode in local policy
|
|
361
|
+
if (localPolicy.settings?.requireExplicitAgents) {
|
|
362
|
+
const matchedPolicy = this.findMatchingPolicy(agentName, localPolicy.agents);
|
|
363
|
+
if (matchedPolicy) {
|
|
364
|
+
return { matchedPolicy, policySource: 'local' };
|
|
365
|
+
}
|
|
366
|
+
// Unknown agent in strict mode
|
|
367
|
+
return {
|
|
368
|
+
matchedPolicy: { ...STRICT_DEFAULT_POLICY, name: agentName },
|
|
369
|
+
policySource: 'local',
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
// Find matching policy
|
|
373
|
+
const matchedPolicy = this.findMatchingPolicy(agentName, localPolicy.agents);
|
|
374
|
+
if (matchedPolicy) {
|
|
375
|
+
return { matchedPolicy, policySource: 'local' };
|
|
376
|
+
}
|
|
377
|
+
// Use local default
|
|
378
|
+
if (localPolicy.defaultPolicy) {
|
|
379
|
+
return {
|
|
380
|
+
matchedPolicy: { ...localPolicy.defaultPolicy, name: agentName },
|
|
381
|
+
policySource: 'local',
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
// 3. Try workspace-level policy from cloud
|
|
386
|
+
const workspacePolicy = await this.getWorkspacePolicy();
|
|
387
|
+
if (workspacePolicy) {
|
|
388
|
+
// Check for strict mode
|
|
389
|
+
if (workspacePolicy.settings?.requireExplicitAgents) {
|
|
390
|
+
// In strict mode, unknown agents get restrictive defaults
|
|
391
|
+
const matchedPolicy = this.findMatchingPolicy(agentName, workspacePolicy.agents);
|
|
392
|
+
if (matchedPolicy) {
|
|
393
|
+
return { matchedPolicy, policySource: 'workspace' };
|
|
394
|
+
}
|
|
395
|
+
// Unknown agent in strict mode
|
|
396
|
+
return {
|
|
397
|
+
matchedPolicy: { ...STRICT_DEFAULT_POLICY, name: agentName },
|
|
398
|
+
policySource: 'workspace',
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
// Find matching policy
|
|
402
|
+
const matchedPolicy = this.findMatchingPolicy(agentName, workspacePolicy.agents);
|
|
403
|
+
if (matchedPolicy) {
|
|
404
|
+
return { matchedPolicy, policySource: 'workspace' };
|
|
405
|
+
}
|
|
406
|
+
// Use workspace default
|
|
407
|
+
if (workspacePolicy.defaultPolicy) {
|
|
408
|
+
return {
|
|
409
|
+
matchedPolicy: { ...workspacePolicy.defaultPolicy, name: agentName },
|
|
410
|
+
policySource: 'workspace',
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// 4. Fall back to built-in defaults
|
|
415
|
+
const defaultPolicy = this.strictMode ? STRICT_DEFAULT_POLICY : DEFAULT_POLICY;
|
|
416
|
+
return {
|
|
417
|
+
matchedPolicy: { ...defaultPolicy, name: agentName },
|
|
418
|
+
policySource: 'default',
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Get workspace policy from cloud (with caching)
|
|
423
|
+
*/
|
|
424
|
+
async getWorkspacePolicy() {
|
|
425
|
+
if (!this.workspaceId || !this.cloudFetcher) {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
// Check cache
|
|
429
|
+
if (this.cachedWorkspacePolicy && Date.now() < this.policyCacheExpiry) {
|
|
430
|
+
return this.cachedWorkspacePolicy;
|
|
431
|
+
}
|
|
432
|
+
try {
|
|
433
|
+
const policy = await this.cloudFetcher.getWorkspacePolicy(this.workspaceId);
|
|
434
|
+
if (policy) {
|
|
435
|
+
this.cachedWorkspacePolicy = policy;
|
|
436
|
+
this.policyCacheExpiry = Date.now() + AgentPolicyService.CACHE_TTL_MS;
|
|
437
|
+
}
|
|
438
|
+
return policy;
|
|
439
|
+
}
|
|
440
|
+
catch (err) {
|
|
441
|
+
console.error('[policy] Failed to fetch workspace policy:', err);
|
|
442
|
+
// Return cached policy if available, even if expired
|
|
443
|
+
return this.cachedWorkspacePolicy ?? null;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Find matching policy from a list (supports wildcards)
|
|
448
|
+
*/
|
|
449
|
+
findMatchingPolicy(agentName, policies) {
|
|
450
|
+
// First try exact match
|
|
451
|
+
const exactMatch = policies.find(p => p.name.toLowerCase() === agentName.toLowerCase());
|
|
452
|
+
if (exactMatch)
|
|
453
|
+
return exactMatch;
|
|
454
|
+
// Then try pattern match
|
|
455
|
+
for (const policy of policies) {
|
|
456
|
+
if (this.matchesPattern(agentName, [policy.name])) {
|
|
457
|
+
return policy;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Check if a name matches any pattern in the list
|
|
464
|
+
* Supports: exact match, prefix* match, *suffix match, * (all)
|
|
465
|
+
*/
|
|
466
|
+
matchesPattern(name, patterns) {
|
|
467
|
+
const lowerName = name.toLowerCase();
|
|
468
|
+
for (const pattern of patterns) {
|
|
469
|
+
const lowerPattern = pattern.toLowerCase();
|
|
470
|
+
// Wildcard all
|
|
471
|
+
if (lowerPattern === '*')
|
|
472
|
+
return true;
|
|
473
|
+
// Exact match
|
|
474
|
+
if (lowerPattern === lowerName)
|
|
475
|
+
return true;
|
|
476
|
+
// Prefix match (e.g., "Worker*" matches "WorkerA")
|
|
477
|
+
if (lowerPattern.endsWith('*')) {
|
|
478
|
+
const prefix = lowerPattern.slice(0, -1);
|
|
479
|
+
if (lowerName.startsWith(prefix))
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
// Suffix match (e.g., "*Lead" matches "TeamLead")
|
|
483
|
+
if (lowerPattern.startsWith('*')) {
|
|
484
|
+
const suffix = lowerPattern.slice(1);
|
|
485
|
+
if (lowerName.endsWith(suffix))
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Convert AgentConfig to AgentPolicy
|
|
493
|
+
*/
|
|
494
|
+
configToPolicy(config) {
|
|
495
|
+
return {
|
|
496
|
+
name: config.name,
|
|
497
|
+
allowedTools: config.allowedTools,
|
|
498
|
+
// Other fields come from defaults since repo config doesn't specify them
|
|
499
|
+
canSpawn: undefined,
|
|
500
|
+
canMessage: undefined,
|
|
501
|
+
maxSpawns: 10,
|
|
502
|
+
rateLimit: 60,
|
|
503
|
+
canBeSpawned: true,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Record an audit entry
|
|
508
|
+
*/
|
|
509
|
+
audit(action, actor, target, decision, context) {
|
|
510
|
+
const entry = {
|
|
511
|
+
timestamp: Date.now(),
|
|
512
|
+
action,
|
|
513
|
+
actor,
|
|
514
|
+
target,
|
|
515
|
+
decision,
|
|
516
|
+
context,
|
|
517
|
+
};
|
|
518
|
+
this.auditLog.push(entry);
|
|
519
|
+
// Trim log if too large
|
|
520
|
+
if (this.auditLog.length > AgentPolicyService.MAX_AUDIT_ENTRIES) {
|
|
521
|
+
this.auditLog = this.auditLog.slice(-AgentPolicyService.MAX_AUDIT_ENTRIES / 2);
|
|
522
|
+
}
|
|
523
|
+
// Log denied actions
|
|
524
|
+
if (!decision.allowed) {
|
|
525
|
+
console.warn(`[policy] DENIED: ${action} by ${actor}${target ? ` -> ${target}` : ''}: ${decision.reason}`);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Get audit log entries
|
|
530
|
+
*/
|
|
531
|
+
getAuditLog(options) {
|
|
532
|
+
let entries = [...this.auditLog];
|
|
533
|
+
if (options?.action) {
|
|
534
|
+
entries = entries.filter(e => e.action === options.action);
|
|
535
|
+
}
|
|
536
|
+
if (options?.actor) {
|
|
537
|
+
entries = entries.filter(e => e.actor === options.actor);
|
|
538
|
+
}
|
|
539
|
+
if (options?.deniedOnly) {
|
|
540
|
+
entries = entries.filter(e => !e.decision.allowed);
|
|
541
|
+
}
|
|
542
|
+
if (options?.limit) {
|
|
543
|
+
entries = entries.slice(-options.limit);
|
|
544
|
+
}
|
|
545
|
+
return entries;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Clear audit log
|
|
549
|
+
*/
|
|
550
|
+
clearAuditLog() {
|
|
551
|
+
this.auditLog = [];
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Invalidate cached workspace policy
|
|
555
|
+
*/
|
|
556
|
+
invalidateCache() {
|
|
557
|
+
this.cachedWorkspacePolicy = undefined;
|
|
558
|
+
this.policyCacheExpiry = 0;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Get a human-readable policy summary for an agent
|
|
562
|
+
* This can be injected into agent prompts to inform them of their permissions
|
|
563
|
+
*/
|
|
564
|
+
async getPolicySummary(agentName) {
|
|
565
|
+
const { matchedPolicy, policySource } = await this.getAgentPolicy(agentName);
|
|
566
|
+
const lines = [
|
|
567
|
+
`# Agent Policy for ${agentName}`,
|
|
568
|
+
`Source: ${policySource}`,
|
|
569
|
+
'',
|
|
570
|
+
];
|
|
571
|
+
// Tools
|
|
572
|
+
if (matchedPolicy.allowedTools) {
|
|
573
|
+
if (matchedPolicy.allowedTools.length === 1 && matchedPolicy.allowedTools[0] === 'none') {
|
|
574
|
+
lines.push('**Tools**: No tools allowed');
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
lines.push(`**Allowed Tools**: ${matchedPolicy.allowedTools.join(', ')}`);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
lines.push('**Tools**: All tools allowed');
|
|
582
|
+
}
|
|
583
|
+
// Spawning
|
|
584
|
+
if (matchedPolicy.canSpawn) {
|
|
585
|
+
if (matchedPolicy.canSpawn.length === 0) {
|
|
586
|
+
lines.push('**Spawning**: Cannot spawn other agents');
|
|
587
|
+
}
|
|
588
|
+
else {
|
|
589
|
+
lines.push(`**Can Spawn**: ${matchedPolicy.canSpawn.join(', ')}`);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
lines.push('**Spawning**: Can spawn any agent');
|
|
594
|
+
}
|
|
595
|
+
// Messaging
|
|
596
|
+
if (matchedPolicy.canMessage) {
|
|
597
|
+
if (matchedPolicy.canMessage.length === 0) {
|
|
598
|
+
lines.push('**Messaging**: Cannot message other agents');
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
lines.push(`**Can Message**: ${matchedPolicy.canMessage.join(', ')}`);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
lines.push('**Messaging**: Can message any agent');
|
|
606
|
+
}
|
|
607
|
+
// Limits
|
|
608
|
+
if (matchedPolicy.maxSpawns !== undefined) {
|
|
609
|
+
lines.push(`**Max Spawns**: ${matchedPolicy.maxSpawns}`);
|
|
610
|
+
}
|
|
611
|
+
if (matchedPolicy.rateLimit !== undefined) {
|
|
612
|
+
lines.push(`**Rate Limit**: ${matchedPolicy.rateLimit} messages/min`);
|
|
613
|
+
}
|
|
614
|
+
return lines.join('\n');
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Get a concise policy instruction for injection into agent prompts
|
|
618
|
+
*/
|
|
619
|
+
async getPolicyInstruction(agentName) {
|
|
620
|
+
const { matchedPolicy, policySource: _policySource } = await this.getAgentPolicy(agentName);
|
|
621
|
+
// Only generate instructions if there are restrictions
|
|
622
|
+
const hasRestrictions = matchedPolicy.allowedTools !== undefined ||
|
|
623
|
+
matchedPolicy.canSpawn !== undefined ||
|
|
624
|
+
matchedPolicy.canMessage !== undefined;
|
|
625
|
+
if (!hasRestrictions) {
|
|
626
|
+
return null; // No restrictions, no need to inform agent
|
|
627
|
+
}
|
|
628
|
+
const restrictions = [];
|
|
629
|
+
if (matchedPolicy.allowedTools) {
|
|
630
|
+
if (matchedPolicy.allowedTools.length === 1 && matchedPolicy.allowedTools[0] === 'none') {
|
|
631
|
+
restrictions.push('You are not allowed to use any tools.');
|
|
632
|
+
}
|
|
633
|
+
else {
|
|
634
|
+
restrictions.push(`You may only use these tools: ${matchedPolicy.allowedTools.join(', ')}.`);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
if (matchedPolicy.canSpawn) {
|
|
638
|
+
if (matchedPolicy.canSpawn.length === 0) {
|
|
639
|
+
restrictions.push('You are not allowed to spawn other agents.');
|
|
640
|
+
}
|
|
641
|
+
else {
|
|
642
|
+
restrictions.push(`You may only spawn these agents: ${matchedPolicy.canSpawn.join(', ')}.`);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
if (matchedPolicy.canMessage) {
|
|
646
|
+
if (matchedPolicy.canMessage.length === 0) {
|
|
647
|
+
restrictions.push('You are not allowed to message other agents.');
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
restrictions.push(`You may only message these agents: ${matchedPolicy.canMessage.join(', ')}.`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
if (restrictions.length === 0) {
|
|
654
|
+
return null;
|
|
655
|
+
}
|
|
656
|
+
return `[Policy Restrictions]\n${restrictions.join('\n')}`;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Create a policy service for a project
|
|
661
|
+
*/
|
|
662
|
+
export function createPolicyService(options) {
|
|
663
|
+
return new AgentPolicyService(options);
|
|
664
|
+
}
|
|
665
|
+
//# sourceMappingURL=agent-policy.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud Policy Fetcher
|
|
3
|
+
*
|
|
4
|
+
* Fetches workspace agent policies from the cloud API.
|
|
5
|
+
* Used by workspace containers to get their policy configuration.
|
|
6
|
+
*/
|
|
7
|
+
import type { CloudPolicyFetcher } from './agent-policy.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create a cloud policy fetcher for workspace containers
|
|
10
|
+
*/
|
|
11
|
+
export declare function createCloudPolicyFetcher(): CloudPolicyFetcher | null;
|
|
12
|
+
//# sourceMappingURL=cloud-policy-fetcher.d.ts.map
|