@phnx-labs/agents-cli 0.1.0 → 1.14.1
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/CHANGELOG.md +7 -1
- package/README.md +283 -372
- package/dist/commands/alias.d.ts +11 -0
- package/dist/commands/alias.js +117 -0
- package/dist/commands/beta.d.ts +2 -0
- package/dist/commands/beta.js +53 -0
- package/dist/commands/cloud.d.ts +8 -1
- package/dist/commands/cloud.js +108 -22
- package/dist/commands/commands.d.ts +9 -1
- package/dist/commands/commands.js +24 -172
- package/dist/commands/daemon.d.ts +8 -1
- package/dist/commands/daemon.js +13 -5
- package/dist/commands/doctor.d.ts +15 -0
- package/dist/commands/doctor.js +132 -0
- package/dist/commands/drive.d.ts +8 -1
- package/dist/commands/drive.js +20 -3
- package/dist/commands/exec.d.ts +8 -1
- package/dist/commands/exec.js +96 -27
- package/dist/commands/factory.d.ts +19 -0
- package/dist/commands/factory.js +71 -0
- package/dist/commands/fork.d.ts +8 -1
- package/dist/commands/fork.js +11 -4
- package/dist/commands/hooks.d.ts +9 -1
- package/dist/commands/hooks.js +30 -182
- package/dist/commands/init.d.ts +15 -1
- package/dist/commands/init.js +168 -74
- package/dist/commands/mcp.d.ts +9 -1
- package/dist/commands/mcp.js +11 -7
- package/dist/commands/models.d.ts +8 -1
- package/dist/commands/models.js +16 -4
- package/dist/commands/packages.d.ts +8 -1
- package/dist/commands/packages.js +13 -7
- package/dist/commands/permissions.d.ts +9 -1
- package/dist/commands/permissions.js +3 -3
- package/dist/commands/plugins.d.ts +8 -1
- package/dist/commands/plugins.js +13 -2
- package/dist/commands/profiles.d.ts +9 -1
- package/dist/commands/profiles.js +56 -7
- package/dist/commands/prune.d.ts +22 -0
- package/dist/commands/prune.js +191 -0
- package/dist/commands/pty.d.ts +1 -1
- package/dist/commands/pty.js +2 -1
- package/dist/commands/pull.d.ts +8 -1
- package/dist/commands/pull.js +58 -128
- package/dist/commands/refresh-memory.d.ts +7 -1
- package/dist/commands/refresh-memory.js +7 -1
- package/dist/commands/repo.d.ts +15 -0
- package/dist/commands/repo.js +570 -0
- package/dist/commands/resource-view.d.ts +10 -3
- package/dist/commands/resource-view.js +18 -5
- package/dist/commands/routines.d.ts +8 -1
- package/dist/commands/routines.js +17 -4
- package/dist/commands/rules.d.ts +9 -1
- package/dist/commands/rules.js +16 -11
- package/dist/commands/secrets.d.ts +8 -1
- package/dist/commands/secrets.js +235 -63
- package/dist/commands/sessions-picker.d.ts +2 -1
- package/dist/commands/sessions-picker.js +88 -11
- package/dist/commands/sessions-tail.d.ts +19 -0
- package/dist/commands/sessions-tail.js +235 -0
- package/dist/commands/sessions.d.ts +2 -1
- package/dist/commands/sessions.js +188 -7
- package/dist/commands/skills.d.ts +9 -1
- package/dist/commands/skills.js +28 -178
- package/dist/commands/status.d.ts +7 -1
- package/dist/commands/status.js +7 -1
- package/dist/commands/subagents.d.ts +8 -1
- package/dist/commands/subagents.js +11 -1
- package/dist/commands/sync.d.ts +8 -1
- package/dist/commands/sync.js +8 -1
- package/dist/commands/teams-picker.d.ts +4 -1
- package/dist/commands/teams-picker.js +55 -3
- package/dist/commands/teams.d.ts +15 -1
- package/dist/commands/teams.js +323 -69
- package/dist/commands/usage.d.ts +11 -0
- package/dist/commands/usage.js +60 -0
- package/dist/commands/utils.d.ts +6 -1
- package/dist/commands/utils.js +6 -1
- package/dist/commands/versions.d.ts +8 -1
- package/dist/commands/versions.js +4 -3
- package/dist/commands/view.d.ts +47 -2
- package/dist/commands/view.js +317 -24
- package/dist/index.d.ts +7 -2
- package/dist/index.js +172 -34
- package/dist/lib/acp/client.d.ts +31 -0
- package/dist/lib/acp/client.js +117 -0
- package/dist/lib/acp/harnesses.d.ts +26 -0
- package/dist/lib/acp/harnesses.js +65 -0
- package/dist/lib/acp/run.d.ts +18 -0
- package/dist/lib/acp/run.js +39 -0
- package/dist/lib/agents.d.ts +74 -2
- package/dist/lib/agents.js +197 -21
- package/dist/lib/artifact-actions.d.ts +8 -4
- package/dist/lib/artifact-actions.js +8 -6
- package/dist/lib/auto-pull-worker.d.ts +11 -0
- package/dist/lib/auto-pull-worker.js +121 -0
- package/dist/lib/auto-pull.d.ts +31 -0
- package/dist/lib/auto-pull.js +97 -0
- package/dist/lib/beta.d.ts +23 -0
- package/dist/lib/beta.js +90 -0
- package/dist/lib/capabilities.d.ts +29 -0
- package/dist/lib/capabilities.js +74 -0
- package/dist/lib/cloud/codex.d.ts +9 -3
- package/dist/lib/cloud/codex.js +53 -13
- package/dist/lib/cloud/factory.d.ts +8 -3
- package/dist/lib/cloud/factory.js +19 -3
- package/dist/lib/cloud/registry.d.ts +10 -1
- package/dist/lib/cloud/registry.js +14 -3
- package/dist/lib/cloud/rush.d.ts +63 -3
- package/dist/lib/cloud/rush.js +273 -20
- package/dist/lib/cloud/store.d.ts +13 -1
- package/dist/lib/cloud/store.js +23 -4
- package/dist/lib/cloud/stream.d.ts +6 -1
- package/dist/lib/cloud/stream.js +95 -39
- package/dist/lib/cloud/types.d.ts +153 -8
- package/dist/lib/cloud/types.js +34 -2
- package/dist/lib/command-skills.d.ts +20 -0
- package/dist/lib/command-skills.js +142 -0
- package/dist/lib/commands.d.ts +22 -2
- package/dist/lib/commands.js +51 -11
- package/dist/lib/convert.d.ts +10 -1
- package/dist/lib/convert.js +9 -1
- package/dist/lib/daemon.d.ts +21 -1
- package/dist/lib/daemon.js +97 -4
- package/dist/lib/drive-sync.d.ts +18 -1
- package/dist/lib/drive-sync.js +57 -15
- package/dist/lib/exec.d.ts +23 -6
- package/dist/lib/exec.js +53 -17
- package/dist/lib/fs-walk.d.ts +2 -0
- package/dist/lib/fs-walk.js +40 -0
- package/dist/lib/fuzzy.d.ts +53 -0
- package/dist/lib/fuzzy.js +72 -0
- package/dist/lib/gemini-settings.d.ts +4 -0
- package/dist/lib/gemini-settings.js +33 -0
- package/dist/lib/git.d.ts +12 -2
- package/dist/lib/git.js +17 -6
- package/dist/lib/help.d.ts +20 -1
- package/dist/lib/help.js +45 -6
- package/dist/lib/hooks/match.d.ts +32 -0
- package/dist/lib/hooks/match.js +120 -0
- package/dist/lib/hooks.d.ts +17 -4
- package/dist/lib/hooks.js +119 -101
- package/dist/lib/manifest.d.ts +6 -1
- package/dist/lib/manifest.js +15 -4
- package/dist/lib/markdown.d.ts +0 -1
- package/dist/lib/markdown.js +6 -1
- package/dist/lib/mcp.d.ts +0 -1
- package/dist/lib/mcp.js +29 -33
- package/dist/lib/memory-compile.d.ts +13 -3
- package/dist/lib/memory-compile.js +31 -9
- package/dist/lib/memory.d.ts +14 -7
- package/dist/lib/memory.js +67 -38
- package/dist/lib/migrate.d.ts +8 -0
- package/dist/lib/migrate.js +85 -0
- package/dist/lib/models.d.ts +10 -4
- package/dist/lib/models.js +36 -15
- package/dist/lib/onepassword.d.ts +63 -0
- package/dist/lib/onepassword.js +186 -0
- package/dist/lib/paths.d.ts +8 -0
- package/dist/lib/paths.js +20 -0
- package/dist/lib/permissions.d.ts +24 -2
- package/dist/lib/permissions.js +117 -48
- package/dist/lib/picker.d.ts +10 -1
- package/dist/lib/picker.js +15 -1
- package/dist/lib/plugins.d.ts +7 -1
- package/dist/lib/plugins.js +10 -1
- package/dist/lib/profiles-presets.d.ts +10 -1
- package/dist/lib/profiles-presets.js +9 -1
- package/dist/lib/profiles.d.ts +35 -1
- package/dist/lib/profiles.js +36 -15
- package/dist/lib/pty-client.d.ts +1 -1
- package/dist/lib/pty-client.js +0 -1
- package/dist/lib/pty-server.d.ts +16 -2
- package/dist/lib/pty-server.js +92 -3
- package/dist/lib/registry.d.ts +23 -3
- package/dist/lib/registry.js +153 -8
- package/dist/lib/resources.d.ts +28 -1
- package/dist/lib/resources.js +79 -1
- package/dist/lib/rotate.d.ts +40 -13
- package/dist/lib/rotate.js +238 -40
- package/dist/lib/routines.d.ts +29 -1
- package/dist/lib/routines.js +32 -5
- package/dist/lib/runner.d.ts +14 -1
- package/dist/lib/runner.js +22 -3
- package/dist/lib/sandbox.d.ts +16 -1
- package/dist/lib/sandbox.js +39 -16
- package/dist/lib/scheduler.d.ts +8 -1
- package/dist/lib/scheduler.js +8 -1
- package/dist/lib/secrets/AgentsKeychain.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/AgentsKeychain.app/Contents/Info.plist +22 -0
- package/dist/lib/secrets/AgentsKeychain.app/Contents/MacOS/AgentsKeychain +0 -0
- package/dist/lib/secrets/AgentsKeychain.app/Contents/_CodeSignature/CodeResources +123 -0
- package/dist/lib/secrets/AgentsKeychain.app/Contents/embedded.provisionprofile +0 -0
- package/dist/lib/{secrets-bundles.d.ts → secrets/bundles.d.ts} +12 -2
- package/dist/lib/{secrets-bundles.js → secrets/bundles.js} +38 -17
- package/dist/lib/secrets/index.d.ts +55 -0
- package/dist/lib/secrets/index.js +211 -0
- package/dist/lib/secrets/profiles.d.ts +10 -0
- package/dist/lib/secrets/profiles.js +13 -0
- package/dist/lib/session/active.d.ts +43 -0
- package/dist/lib/session/active.js +392 -0
- package/dist/lib/session/artifacts.d.ts +12 -1
- package/dist/lib/session/artifacts.js +25 -5
- package/dist/lib/session/cloud.d.ts +30 -0
- package/dist/lib/session/cloud.js +121 -0
- package/dist/lib/session/db.d.ts +23 -2
- package/dist/lib/session/db.js +76 -12
- package/dist/lib/session/discover.d.ts +19 -4
- package/dist/lib/session/discover.js +344 -48
- package/dist/lib/session/parse.d.ts +28 -1
- package/dist/lib/session/parse.js +267 -9
- package/dist/lib/session/prompt.d.ts +9 -1
- package/dist/lib/session/prompt.js +17 -3
- package/dist/lib/session/render.d.ts +13 -1
- package/dist/lib/session/render.js +20 -1
- package/dist/lib/session/team-filter.d.ts +9 -1
- package/dist/lib/session/team-filter.js +11 -2
- package/dist/lib/session/types.d.ts +16 -2
- package/dist/lib/session/types.js +10 -2
- package/dist/lib/shims.d.ts +64 -5
- package/dist/lib/shims.js +309 -47
- package/dist/lib/skills.d.ts +27 -2
- package/dist/lib/skills.js +127 -65
- package/dist/lib/sqlite.d.ts +43 -0
- package/dist/lib/sqlite.js +94 -0
- package/dist/lib/state.d.ts +112 -27
- package/dist/lib/state.js +320 -148
- package/dist/lib/subagents.d.ts +9 -1
- package/dist/lib/subagents.js +70 -63
- package/dist/lib/sync-manifest.d.ts +81 -0
- package/dist/lib/sync-manifest.js +450 -0
- package/dist/lib/teams/agents.d.ts +103 -5
- package/dist/lib/teams/agents.js +414 -91
- package/dist/lib/teams/api.d.ts +26 -3
- package/dist/lib/teams/api.js +63 -3
- package/dist/lib/teams/debug.d.ts +6 -1
- package/dist/lib/teams/debug.js +6 -1
- package/dist/lib/teams/file_ops.d.ts +7 -1
- package/dist/lib/teams/file_ops.js +7 -1
- package/dist/lib/teams/index.d.ts +15 -0
- package/dist/lib/teams/index.js +14 -0
- package/dist/lib/teams/parsers.d.ts +4 -1
- package/dist/lib/teams/parsers.js +11 -1
- package/dist/lib/teams/persistence.d.ts +15 -1
- package/dist/lib/teams/persistence.js +102 -20
- package/dist/lib/teams/registry.d.ts +12 -1
- package/dist/lib/teams/registry.js +116 -33
- package/dist/lib/teams/summarizer.d.ts +15 -1
- package/dist/lib/teams/summarizer.js +14 -1
- package/dist/lib/teams/supervisor.d.ts +48 -0
- package/dist/lib/teams/supervisor.js +73 -0
- package/dist/lib/template.d.ts +8 -6
- package/dist/lib/template.js +8 -6
- package/dist/lib/types.d.ts +147 -8
- package/dist/lib/types.js +26 -3
- package/dist/lib/usage.d.ts +32 -1
- package/dist/lib/usage.js +70 -6
- package/dist/lib/version-duplicates.d.ts +21 -0
- package/dist/lib/version-duplicates.js +90 -0
- package/dist/lib/versions.d.ts +33 -4
- package/dist/lib/versions.js +376 -108
- package/package.json +32 -17
- package/scripts/postinstall.js +126 -30
- package/dist/commands/__tests__/sessions.test.d.ts +0 -2
- package/dist/commands/__tests__/sessions.test.d.ts.map +0 -1
- package/dist/commands/__tests__/sessions.test.js +0 -636
- package/dist/commands/__tests__/sessions.test.js.map +0 -1
- package/dist/commands/cloud.d.ts.map +0 -1
- package/dist/commands/cloud.js.map +0 -1
- package/dist/commands/commands.d.ts.map +0 -1
- package/dist/commands/commands.js.map +0 -1
- package/dist/commands/daemon.d.ts.map +0 -1
- package/dist/commands/daemon.js.map +0 -1
- package/dist/commands/drive.d.ts.map +0 -1
- package/dist/commands/drive.js.map +0 -1
- package/dist/commands/exec.d.ts.map +0 -1
- package/dist/commands/exec.js.map +0 -1
- package/dist/commands/fork.d.ts.map +0 -1
- package/dist/commands/fork.js.map +0 -1
- package/dist/commands/hooks.d.ts.map +0 -1
- package/dist/commands/hooks.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/mcp.d.ts.map +0 -1
- package/dist/commands/mcp.js.map +0 -1
- package/dist/commands/models.d.ts.map +0 -1
- package/dist/commands/models.js.map +0 -1
- package/dist/commands/packages.d.ts.map +0 -1
- package/dist/commands/packages.js.map +0 -1
- package/dist/commands/permissions.d.ts.map +0 -1
- package/dist/commands/permissions.js.map +0 -1
- package/dist/commands/plugins.d.ts.map +0 -1
- package/dist/commands/plugins.js.map +0 -1
- package/dist/commands/profiles.d.ts.map +0 -1
- package/dist/commands/profiles.js.map +0 -1
- package/dist/commands/pty.d.ts.map +0 -1
- package/dist/commands/pty.js.map +0 -1
- package/dist/commands/pull.d.ts.map +0 -1
- package/dist/commands/pull.js.map +0 -1
- package/dist/commands/push.d.ts +0 -3
- package/dist/commands/push.d.ts.map +0 -1
- package/dist/commands/push.js +0 -180
- package/dist/commands/push.js.map +0 -1
- package/dist/commands/refresh-memory.d.ts.map +0 -1
- package/dist/commands/refresh-memory.js.map +0 -1
- package/dist/commands/resource-view.d.ts.map +0 -1
- package/dist/commands/resource-view.js.map +0 -1
- package/dist/commands/routines.d.ts.map +0 -1
- package/dist/commands/routines.js.map +0 -1
- package/dist/commands/rules.d.ts.map +0 -1
- package/dist/commands/rules.js.map +0 -1
- package/dist/commands/secrets.d.ts.map +0 -1
- package/dist/commands/secrets.js.map +0 -1
- package/dist/commands/sessions-picker.d.ts.map +0 -1
- package/dist/commands/sessions-picker.js.map +0 -1
- package/dist/commands/sessions.d.ts.map +0 -1
- package/dist/commands/sessions.js.map +0 -1
- package/dist/commands/skills.d.ts.map +0 -1
- package/dist/commands/skills.js.map +0 -1
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/subagents.d.ts.map +0 -1
- package/dist/commands/subagents.js.map +0 -1
- package/dist/commands/sync.d.ts.map +0 -1
- package/dist/commands/sync.js.map +0 -1
- package/dist/commands/teams-picker.d.ts.map +0 -1
- package/dist/commands/teams-picker.js.map +0 -1
- package/dist/commands/teams.d.ts.map +0 -1
- package/dist/commands/teams.js.map +0 -1
- package/dist/commands/utils.d.ts.map +0 -1
- package/dist/commands/utils.js.map +0 -1
- package/dist/commands/versions.d.ts.map +0 -1
- package/dist/commands/versions.js.map +0 -1
- package/dist/commands/view.d.ts.map +0 -1
- package/dist/commands/view.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/__tests__/bugfixes.test.d.ts +0 -2
- package/dist/lib/__tests__/bugfixes.test.d.ts.map +0 -1
- package/dist/lib/__tests__/bugfixes.test.js +0 -192
- package/dist/lib/__tests__/bugfixes.test.js.map +0 -1
- package/dist/lib/__tests__/exec.test.d.ts +0 -2
- package/dist/lib/__tests__/exec.test.d.ts.map +0 -1
- package/dist/lib/__tests__/exec.test.js +0 -446
- package/dist/lib/__tests__/exec.test.js.map +0 -1
- package/dist/lib/__tests__/git-sync.test.d.ts +0 -2
- package/dist/lib/__tests__/git-sync.test.d.ts.map +0 -1
- package/dist/lib/__tests__/git-sync.test.js +0 -138
- package/dist/lib/__tests__/git-sync.test.js.map +0 -1
- package/dist/lib/__tests__/hooks.test.d.ts +0 -2
- package/dist/lib/__tests__/hooks.test.d.ts.map +0 -1
- package/dist/lib/__tests__/hooks.test.js +0 -203
- package/dist/lib/__tests__/hooks.test.js.map +0 -1
- package/dist/lib/__tests__/memory-compile.test.d.ts +0 -2
- package/dist/lib/__tests__/memory-compile.test.d.ts.map +0 -1
- package/dist/lib/__tests__/memory-compile.test.js +0 -95
- package/dist/lib/__tests__/memory-compile.test.js.map +0 -1
- package/dist/lib/__tests__/models.test.d.ts +0 -2
- package/dist/lib/__tests__/models.test.d.ts.map +0 -1
- package/dist/lib/__tests__/models.test.js +0 -239
- package/dist/lib/__tests__/models.test.js.map +0 -1
- package/dist/lib/__tests__/rotate.test.d.ts +0 -2
- package/dist/lib/__tests__/rotate.test.d.ts.map +0 -1
- package/dist/lib/__tests__/rotate.test.js +0 -80
- package/dist/lib/__tests__/rotate.test.js.map +0 -1
- package/dist/lib/__tests__/secrets-bundles.test.d.ts +0 -2
- package/dist/lib/__tests__/secrets-bundles.test.d.ts.map +0 -1
- package/dist/lib/__tests__/secrets-bundles.test.js +0 -104
- package/dist/lib/__tests__/secrets-bundles.test.js.map +0 -1
- package/dist/lib/__tests__/secrets.test.d.ts +0 -2
- package/dist/lib/__tests__/secrets.test.d.ts.map +0 -1
- package/dist/lib/__tests__/secrets.test.js +0 -90
- package/dist/lib/__tests__/secrets.test.js.map +0 -1
- package/dist/lib/__tests__/shims.test.d.ts +0 -2
- package/dist/lib/__tests__/shims.test.d.ts.map +0 -1
- package/dist/lib/__tests__/shims.test.js +0 -39
- package/dist/lib/__tests__/shims.test.js.map +0 -1
- package/dist/lib/__tests__/usage.test.d.ts +0 -2
- package/dist/lib/__tests__/usage.test.d.ts.map +0 -1
- package/dist/lib/__tests__/usage.test.js +0 -220
- package/dist/lib/__tests__/usage.test.js.map +0 -1
- package/dist/lib/__tests__/versions.test.d.ts +0 -2
- package/dist/lib/__tests__/versions.test.d.ts.map +0 -1
- package/dist/lib/__tests__/versions.test.js +0 -63
- package/dist/lib/__tests__/versions.test.js.map +0 -1
- package/dist/lib/agents.d.ts.map +0 -1
- package/dist/lib/agents.js.map +0 -1
- package/dist/lib/artifact-actions.d.ts.map +0 -1
- package/dist/lib/artifact-actions.js.map +0 -1
- package/dist/lib/cloud/codex.d.ts.map +0 -1
- package/dist/lib/cloud/codex.js.map +0 -1
- package/dist/lib/cloud/factory.d.ts.map +0 -1
- package/dist/lib/cloud/factory.js.map +0 -1
- package/dist/lib/cloud/registry.d.ts.map +0 -1
- package/dist/lib/cloud/registry.js.map +0 -1
- package/dist/lib/cloud/rush.d.ts.map +0 -1
- package/dist/lib/cloud/rush.js.map +0 -1
- package/dist/lib/cloud/store.d.ts.map +0 -1
- package/dist/lib/cloud/store.js.map +0 -1
- package/dist/lib/cloud/stream.d.ts.map +0 -1
- package/dist/lib/cloud/stream.js.map +0 -1
- package/dist/lib/cloud/types.d.ts.map +0 -1
- package/dist/lib/cloud/types.js.map +0 -1
- package/dist/lib/commands.d.ts.map +0 -1
- package/dist/lib/commands.js.map +0 -1
- package/dist/lib/convert.d.ts.map +0 -1
- package/dist/lib/convert.js.map +0 -1
- package/dist/lib/daemon.d.ts.map +0 -1
- package/dist/lib/daemon.js.map +0 -1
- package/dist/lib/drive-sync.d.ts.map +0 -1
- package/dist/lib/drive-sync.js.map +0 -1
- package/dist/lib/exec.d.ts.map +0 -1
- package/dist/lib/exec.js.map +0 -1
- package/dist/lib/factory.d.ts +0 -57
- package/dist/lib/factory.d.ts.map +0 -1
- package/dist/lib/factory.js +0 -110
- package/dist/lib/factory.js.map +0 -1
- package/dist/lib/git.d.ts.map +0 -1
- package/dist/lib/git.js.map +0 -1
- package/dist/lib/help.d.ts.map +0 -1
- package/dist/lib/help.js.map +0 -1
- package/dist/lib/hooks.d.ts.map +0 -1
- package/dist/lib/hooks.js.map +0 -1
- package/dist/lib/manifest.d.ts.map +0 -1
- package/dist/lib/manifest.js.map +0 -1
- package/dist/lib/markdown.d.ts.map +0 -1
- package/dist/lib/markdown.js.map +0 -1
- package/dist/lib/mcp.d.ts.map +0 -1
- package/dist/lib/mcp.js.map +0 -1
- package/dist/lib/memory-compile.d.ts.map +0 -1
- package/dist/lib/memory-compile.js.map +0 -1
- package/dist/lib/memory.d.ts.map +0 -1
- package/dist/lib/memory.js.map +0 -1
- package/dist/lib/models.d.ts.map +0 -1
- package/dist/lib/models.js.map +0 -1
- package/dist/lib/permissions.d.ts.map +0 -1
- package/dist/lib/permissions.js.map +0 -1
- package/dist/lib/picker.d.ts.map +0 -1
- package/dist/lib/picker.js.map +0 -1
- package/dist/lib/plugins.d.ts.map +0 -1
- package/dist/lib/plugins.js.map +0 -1
- package/dist/lib/profiles-keychain.d.ts +0 -3
- package/dist/lib/profiles-keychain.d.ts.map +0 -1
- package/dist/lib/profiles-keychain.js +0 -10
- package/dist/lib/profiles-keychain.js.map +0 -1
- package/dist/lib/profiles-presets.d.ts.map +0 -1
- package/dist/lib/profiles-presets.js.map +0 -1
- package/dist/lib/profiles.d.ts.map +0 -1
- package/dist/lib/profiles.js.map +0 -1
- package/dist/lib/pty-client.d.ts.map +0 -1
- package/dist/lib/pty-client.js.map +0 -1
- package/dist/lib/pty-server.d.ts.map +0 -1
- package/dist/lib/pty-server.js.map +0 -1
- package/dist/lib/registry.d.ts.map +0 -1
- package/dist/lib/registry.js.map +0 -1
- package/dist/lib/resources.d.ts.map +0 -1
- package/dist/lib/resources.js.map +0 -1
- package/dist/lib/rotate.d.ts.map +0 -1
- package/dist/lib/rotate.js.map +0 -1
- package/dist/lib/routines.d.ts.map +0 -1
- package/dist/lib/routines.js.map +0 -1
- package/dist/lib/runner.d.ts.map +0 -1
- package/dist/lib/runner.js.map +0 -1
- package/dist/lib/sandbox.d.ts.map +0 -1
- package/dist/lib/sandbox.js.map +0 -1
- package/dist/lib/scheduler.d.ts.map +0 -1
- package/dist/lib/scheduler.js.map +0 -1
- package/dist/lib/secrets-bundles.d.ts.map +0 -1
- package/dist/lib/secrets-bundles.js.map +0 -1
- package/dist/lib/secrets.d.ts +0 -27
- package/dist/lib/secrets.d.ts.map +0 -1
- package/dist/lib/secrets.js +0 -127
- package/dist/lib/secrets.js.map +0 -1
- package/dist/lib/session/__tests__/db.test.d.ts +0 -2
- package/dist/lib/session/__tests__/db.test.d.ts.map +0 -1
- package/dist/lib/session/__tests__/db.test.js +0 -54
- package/dist/lib/session/__tests__/db.test.js.map +0 -1
- package/dist/lib/session/__tests__/discover.test.d.ts +0 -2
- package/dist/lib/session/__tests__/discover.test.d.ts.map +0 -1
- package/dist/lib/session/__tests__/discover.test.js +0 -63
- package/dist/lib/session/__tests__/discover.test.js.map +0 -1
- package/dist/lib/session/__tests__/prompt.test.d.ts +0 -2
- package/dist/lib/session/__tests__/prompt.test.d.ts.map +0 -1
- package/dist/lib/session/__tests__/prompt.test.js +0 -44
- package/dist/lib/session/__tests__/prompt.test.js.map +0 -1
- package/dist/lib/session/__tests__/render.test.d.ts +0 -2
- package/dist/lib/session/__tests__/render.test.d.ts.map +0 -1
- package/dist/lib/session/__tests__/render.test.js +0 -602
- package/dist/lib/session/__tests__/render.test.js.map +0 -1
- package/dist/lib/session/artifacts.d.ts.map +0 -1
- package/dist/lib/session/artifacts.js.map +0 -1
- package/dist/lib/session/db.d.ts.map +0 -1
- package/dist/lib/session/db.js.map +0 -1
- package/dist/lib/session/discover.d.ts.map +0 -1
- package/dist/lib/session/discover.js.map +0 -1
- package/dist/lib/session/parse.d.ts.map +0 -1
- package/dist/lib/session/parse.js.map +0 -1
- package/dist/lib/session/prompt.d.ts.map +0 -1
- package/dist/lib/session/prompt.js.map +0 -1
- package/dist/lib/session/prompt.test.d.ts +0 -2
- package/dist/lib/session/prompt.test.d.ts.map +0 -1
- package/dist/lib/session/prompt.test.js +0 -57
- package/dist/lib/session/prompt.test.js.map +0 -1
- package/dist/lib/session/render.d.ts.map +0 -1
- package/dist/lib/session/render.js.map +0 -1
- package/dist/lib/session/team-filter.d.ts.map +0 -1
- package/dist/lib/session/team-filter.js.map +0 -1
- package/dist/lib/session/team-filter.test.d.ts +0 -2
- package/dist/lib/session/team-filter.test.d.ts.map +0 -1
- package/dist/lib/session/team-filter.test.js +0 -157
- package/dist/lib/session/team-filter.test.js.map +0 -1
- package/dist/lib/session/types.d.ts.map +0 -1
- package/dist/lib/session/types.js.map +0 -1
- package/dist/lib/shims.d.ts.map +0 -1
- package/dist/lib/shims.js.map +0 -1
- package/dist/lib/skills.d.ts.map +0 -1
- package/dist/lib/skills.js.map +0 -1
- package/dist/lib/state.d.ts.map +0 -1
- package/dist/lib/state.js.map +0 -1
- package/dist/lib/subagents.d.ts.map +0 -1
- package/dist/lib/subagents.js.map +0 -1
- package/dist/lib/teams/agents.d.ts.map +0 -1
- package/dist/lib/teams/agents.js.map +0 -1
- package/dist/lib/teams/api.d.ts.map +0 -1
- package/dist/lib/teams/api.js.map +0 -1
- package/dist/lib/teams/cloud.d.ts +0 -11
- package/dist/lib/teams/cloud.d.ts.map +0 -1
- package/dist/lib/teams/cloud.js +0 -169
- package/dist/lib/teams/cloud.js.map +0 -1
- package/dist/lib/teams/debug.d.ts.map +0 -1
- package/dist/lib/teams/debug.js.map +0 -1
- package/dist/lib/teams/file_ops.d.ts.map +0 -1
- package/dist/lib/teams/file_ops.js.map +0 -1
- package/dist/lib/teams/parsers.d.ts.map +0 -1
- package/dist/lib/teams/parsers.js.map +0 -1
- package/dist/lib/teams/persistence.d.ts.map +0 -1
- package/dist/lib/teams/persistence.js.map +0 -1
- package/dist/lib/teams/ralph.d.ts +0 -8
- package/dist/lib/teams/ralph.d.ts.map +0 -1
- package/dist/lib/teams/ralph.js +0 -59
- package/dist/lib/teams/ralph.js.map +0 -1
- package/dist/lib/teams/registry.d.ts.map +0 -1
- package/dist/lib/teams/registry.js.map +0 -1
- package/dist/lib/teams/summarizer.d.ts.map +0 -1
- package/dist/lib/teams/summarizer.js.map +0 -1
- package/dist/lib/template.d.ts.map +0 -1
- package/dist/lib/template.js.map +0 -1
- package/dist/lib/types.d.ts.map +0 -1
- package/dist/lib/types.js.map +0 -1
- package/dist/lib/usage.d.ts.map +0 -1
- package/dist/lib/usage.js.map +0 -1
- package/dist/lib/versions.d.ts.map +0 -1
- package/dist/lib/versions.js.map +0 -1
- package/scripts/rebuild-sqlite.sh +0 -46
package/dist/lib/teams/agents.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Teams agent lifecycle management.
|
|
3
|
+
*
|
|
4
|
+
* Defines the AgentProcess and AgentManager classes that handle spawning,
|
|
5
|
+
* monitoring, stopping, and persisting teammate processes across all supported
|
|
6
|
+
* agent CLIs (Claude, Codex, Gemini, Cursor, OpenCode). Supports DAG-based
|
|
7
|
+
* dependency scheduling via --after, per-teammate model/effort overrides, and
|
|
8
|
+
* multiple permission modes (plan, edit, full).
|
|
9
|
+
*/
|
|
10
|
+
import { spawn, execSync, execFileSync } from 'child_process';
|
|
2
11
|
import * as fs from 'fs/promises';
|
|
12
|
+
import * as fsSync from 'fs';
|
|
3
13
|
import * as path from 'path';
|
|
4
14
|
import * as os from 'os';
|
|
5
15
|
import { randomUUID } from 'crypto';
|
|
@@ -7,6 +17,53 @@ import { resolveAgentsDir } from './persistence.js';
|
|
|
7
17
|
import { normalizeEvents } from './parsers.js';
|
|
8
18
|
import { debug } from './debug.js';
|
|
9
19
|
import { buildReasoningFlags } from '../models.js';
|
|
20
|
+
import { setGeminiAutoUpdateDisabled, updateGeminiSettings } from '../gemini-settings.js';
|
|
21
|
+
import { getAgentsDir as getSystemAgentsDir } from '../state.js';
|
|
22
|
+
let lastMemoryWarnAt = 0;
|
|
23
|
+
// On macOS, os.freemem() returns only the truly-free pool and ignores the
|
|
24
|
+
// large inactive+purgeable cache the kernel will reclaim under pressure, so
|
|
25
|
+
// it always looks alarmingly low on a healthy Mac. Parse vm_stat to get the
|
|
26
|
+
// real "available" figure: free + inactive + purgeable + speculative.
|
|
27
|
+
function availableMemoryBytes() {
|
|
28
|
+
if (process.platform !== 'darwin')
|
|
29
|
+
return os.freemem();
|
|
30
|
+
try {
|
|
31
|
+
const out = execSync('vm_stat', { encoding: 'utf8', timeout: 1000 });
|
|
32
|
+
const pageSizeMatch = out.match(/page size of (\d+) bytes/);
|
|
33
|
+
const pageSize = pageSizeMatch ? Number(pageSizeMatch[1]) : 4096;
|
|
34
|
+
const grab = (label) => {
|
|
35
|
+
const m = out.match(new RegExp(`${label}:\\s+(\\d+)\\.`));
|
|
36
|
+
return m ? Number(m[1]) : 0;
|
|
37
|
+
};
|
|
38
|
+
const pages = grab('Pages free') +
|
|
39
|
+
grab('Pages inactive') +
|
|
40
|
+
grab('Pages purgeable') +
|
|
41
|
+
grab('Pages speculative');
|
|
42
|
+
if (pages <= 0)
|
|
43
|
+
return os.freemem();
|
|
44
|
+
return pages * pageSize;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return os.freemem();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function warnIfMemoryLow(runningCount) {
|
|
51
|
+
const total = os.totalmem();
|
|
52
|
+
if (total <= 0)
|
|
53
|
+
return;
|
|
54
|
+
const available = availableMemoryBytes();
|
|
55
|
+
const freeRatio = available / total;
|
|
56
|
+
if (freeRatio >= 0.15)
|
|
57
|
+
return;
|
|
58
|
+
const now = Date.now();
|
|
59
|
+
if (now - lastMemoryWarnAt < 60_000)
|
|
60
|
+
return;
|
|
61
|
+
lastMemoryWarnAt = now;
|
|
62
|
+
const freeGb = (available / 1024 ** 3).toFixed(1);
|
|
63
|
+
const totalGb = (total / 1024 ** 3).toFixed(1);
|
|
64
|
+
process.stderr.write(`Heads up: only ${freeGb}GB of ${totalGb}GB free with ${runningCount} teammates already running. ` +
|
|
65
|
+
`Spawning more may slow your machine.\n`);
|
|
66
|
+
}
|
|
10
67
|
/**
|
|
11
68
|
* Compute the Lowest Common Ancestor (LCA) of multiple file paths.
|
|
12
69
|
* Returns the deepest common directory shared by all paths.
|
|
@@ -44,6 +101,7 @@ export function computePathLCA(paths) {
|
|
|
44
101
|
const lca = path.sep + commonSegments.join(path.sep);
|
|
45
102
|
return lca;
|
|
46
103
|
}
|
|
104
|
+
/** Lifecycle status of a teammate process. */
|
|
47
105
|
export var AgentStatus;
|
|
48
106
|
(function (AgentStatus) {
|
|
49
107
|
AgentStatus["PENDING"] = "pending";
|
|
@@ -52,6 +110,9 @@ export var AgentStatus;
|
|
|
52
110
|
AgentStatus["FAILED"] = "failed";
|
|
53
111
|
AgentStatus["STOPPED"] = "stopped";
|
|
54
112
|
})(AgentStatus || (AgentStatus = {}));
|
|
113
|
+
export const VALID_TASK_TYPES = [
|
|
114
|
+
'plan', 'implement', 'test', 'review', 'bugfix', 'docs',
|
|
115
|
+
];
|
|
55
116
|
/**
|
|
56
117
|
* Walk the `after` chain from `startName` within the given map; returns true
|
|
57
118
|
* if `targetName` appears anywhere in the transitive dependency closure.
|
|
@@ -72,14 +133,129 @@ function hasTransitiveDep(byName, startName, targetName, seen = new Set()) {
|
|
|
72
133
|
}
|
|
73
134
|
return false;
|
|
74
135
|
}
|
|
75
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Capture a stable identifier for a process at the moment it was started.
|
|
138
|
+
* Used to defeat PID reuse: a kill(pid, ...) is only safe when the process
|
|
139
|
+
* still occupies the PID we observed at spawn time. A bare kill(pid, 0)
|
|
140
|
+
* probe cannot tell whether the OS has recycled the slot to an unrelated
|
|
141
|
+
* process — combined with detached spawns and unref(), that's exactly how
|
|
142
|
+
* `agents teams stop` ends up SIGKILLing random process groups.
|
|
143
|
+
*
|
|
144
|
+
* Linux: field 22 of /proc/<pid>/stat (starttime in clock ticks since boot).
|
|
145
|
+
* macOS: output of `ps -o lstart= -p <pid>` (start time in human format).
|
|
146
|
+
* Returns null on any error so callers can skip the guard rather than crash.
|
|
147
|
+
*/
|
|
148
|
+
export function captureProcessStartTime(pid) {
|
|
149
|
+
if (!pid || pid <= 0)
|
|
150
|
+
return null;
|
|
151
|
+
try {
|
|
152
|
+
if (process.platform === 'linux') {
|
|
153
|
+
const stat = fsSync.readFileSync(`/proc/${pid}/stat`, 'utf-8');
|
|
154
|
+
const lastParen = stat.lastIndexOf(')');
|
|
155
|
+
if (lastParen < 0)
|
|
156
|
+
return null;
|
|
157
|
+
const tail = stat.slice(lastParen + 2);
|
|
158
|
+
const fields = tail.split(' ');
|
|
159
|
+
// After comm we are at field 3; starttime is field 22, so index 19 here.
|
|
160
|
+
return fields[19] || null;
|
|
161
|
+
}
|
|
162
|
+
const out = execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], {
|
|
163
|
+
encoding: 'utf-8',
|
|
164
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
165
|
+
});
|
|
166
|
+
const trimmed = out.trim();
|
|
167
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Base commands for plan mode (read-only). applyEditMode / applyFullMode
|
|
174
|
+
// rewrite these for write-capable modes. Each agent's read-only flag MUST be
|
|
175
|
+
// here so a plan-mode teammate truly cannot write — even if the teammate
|
|
176
|
+
// prompt tries to ignore the instruction. See agents.test.ts for the contract.
|
|
76
177
|
export const AGENT_COMMANDS = {
|
|
77
|
-
codex: ['codex', 'exec', '--sandbox', '
|
|
178
|
+
codex: ['codex', 'exec', '--sandbox', 'read-only', '{prompt}', '--json'],
|
|
78
179
|
cursor: ['cursor-agent', '-p', '--output-format', 'stream-json', '{prompt}'],
|
|
79
180
|
gemini: ['gemini', '{prompt}', '--output-format', 'stream-json', '--approval-mode', 'plan'],
|
|
80
181
|
claude: ['claude', '-p', '--verbose', '{prompt}', '--output-format', 'stream-json', '--permission-mode', 'plan'],
|
|
81
182
|
opencode: ['opencode', 'run', '--format', 'json', '{prompt}'],
|
|
82
183
|
};
|
|
184
|
+
/**
|
|
185
|
+
* Rewrite a plan-mode command into edit mode (writes inside cwd allowed,
|
|
186
|
+
* approval prompts may still appear). Pure function — exported for tests.
|
|
187
|
+
*/
|
|
188
|
+
export function applyEditMode(agentType, cmd) {
|
|
189
|
+
const editCmd = [...cmd];
|
|
190
|
+
switch (agentType) {
|
|
191
|
+
case 'codex': {
|
|
192
|
+
// Swap --sandbox read-only -> --sandbox workspace-write so the codex
|
|
193
|
+
// sandbox actually permits writes. --full-auto then disables approvals.
|
|
194
|
+
const sandboxIndex = editCmd.indexOf('--sandbox');
|
|
195
|
+
if (sandboxIndex !== -1 && sandboxIndex + 1 < editCmd.length) {
|
|
196
|
+
editCmd[sandboxIndex + 1] = 'workspace-write';
|
|
197
|
+
}
|
|
198
|
+
editCmd.push('--full-auto');
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
case 'cursor':
|
|
202
|
+
editCmd.push('-f');
|
|
203
|
+
break;
|
|
204
|
+
case 'gemini': {
|
|
205
|
+
const approvalIndex = editCmd.indexOf('--approval-mode');
|
|
206
|
+
if (approvalIndex !== -1) {
|
|
207
|
+
editCmd.splice(approvalIndex, 2);
|
|
208
|
+
}
|
|
209
|
+
editCmd.push('--yolo');
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case 'claude': {
|
|
213
|
+
const permModeIndex = editCmd.indexOf('--permission-mode');
|
|
214
|
+
if (permModeIndex !== -1 && permModeIndex + 1 < editCmd.length) {
|
|
215
|
+
editCmd[permModeIndex + 1] = 'acceptEdits';
|
|
216
|
+
}
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return editCmd;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Rewrite a plan-mode command into full mode (writes + approval gates
|
|
224
|
+
* bypassed). Pure function — exported for tests.
|
|
225
|
+
*/
|
|
226
|
+
export function applyFullMode(agentType, cmd) {
|
|
227
|
+
const fullCmd = [...cmd];
|
|
228
|
+
switch (agentType) {
|
|
229
|
+
case 'codex': {
|
|
230
|
+
const sandboxIndex = fullCmd.indexOf('--sandbox');
|
|
231
|
+
if (sandboxIndex !== -1 && sandboxIndex + 1 < fullCmd.length) {
|
|
232
|
+
fullCmd[sandboxIndex + 1] = 'workspace-write';
|
|
233
|
+
}
|
|
234
|
+
fullCmd.push('--full-auto');
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case 'cursor':
|
|
238
|
+
fullCmd.push('-f');
|
|
239
|
+
break;
|
|
240
|
+
case 'gemini': {
|
|
241
|
+
const approvalIndex = fullCmd.indexOf('--approval-mode');
|
|
242
|
+
if (approvalIndex !== -1) {
|
|
243
|
+
fullCmd.splice(approvalIndex, 2);
|
|
244
|
+
}
|
|
245
|
+
fullCmd.push('--yolo');
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
case 'claude': {
|
|
249
|
+
const permModeIndex = fullCmd.indexOf('--permission-mode');
|
|
250
|
+
if (permModeIndex !== -1) {
|
|
251
|
+
fullCmd.splice(permModeIndex, 2);
|
|
252
|
+
}
|
|
253
|
+
fullCmd.push('--dangerously-skip-permissions');
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return fullCmd;
|
|
258
|
+
}
|
|
83
259
|
// Minimal defaults — no per-effort model map. Configs on disk may still have
|
|
84
260
|
// a model pinned; launchProcess picks it up from agent.model when set.
|
|
85
261
|
function loadDefaultAgentConfigs() {
|
|
@@ -168,6 +344,7 @@ function extractTimestamp(raw) {
|
|
|
168
344
|
}
|
|
169
345
|
return null;
|
|
170
346
|
}
|
|
347
|
+
/** Resolve a mode string to a validated Mode, falling back to the given default. */
|
|
171
348
|
export function resolveMode(requestedMode, defaultMode = 'plan') {
|
|
172
349
|
const normalizedDefault = normalizeModeValue(defaultMode);
|
|
173
350
|
if (!normalizedDefault) {
|
|
@@ -182,28 +359,31 @@ export function resolveMode(requestedMode, defaultMode = 'plan') {
|
|
|
182
359
|
}
|
|
183
360
|
return normalizedDefault;
|
|
184
361
|
}
|
|
362
|
+
/** Ensure Gemini's settings.json has experimental.plan enabled for headless plan mode. */
|
|
185
363
|
export async function ensureGeminiPlanMode() {
|
|
186
364
|
const settingsPath = path.join(os.homedir(), '.gemini', 'settings.json');
|
|
187
365
|
try {
|
|
188
|
-
let
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
366
|
+
let changed = false;
|
|
367
|
+
const settings = updateGeminiSettings(settingsPath, (nextSettings) => {
|
|
368
|
+
setGeminiAutoUpdateDisabled(nextSettings);
|
|
369
|
+
const experimental = typeof nextSettings.experimental === 'object' && nextSettings.experimental !== null
|
|
370
|
+
? nextSettings.experimental
|
|
371
|
+
: {};
|
|
372
|
+
if (experimental.plan === true) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
nextSettings.experimental = { ...experimental, plan: true };
|
|
376
|
+
changed = true;
|
|
377
|
+
});
|
|
378
|
+
if (changed && settings.experimental && typeof settings.experimental === 'object' && settings.experimental.plan === true) {
|
|
379
|
+
console.error('[Swarm] Enabled Gemini experimental.plan in', settingsPath);
|
|
195
380
|
}
|
|
196
|
-
if (settings.experimental?.plan === true)
|
|
197
|
-
return;
|
|
198
|
-
settings.experimental = { ...settings.experimental, plan: true };
|
|
199
|
-
await fs.mkdir(path.dirname(settingsPath), { recursive: true });
|
|
200
|
-
await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
201
|
-
console.error('[Swarm] Enabled Gemini experimental.plan in', settingsPath);
|
|
202
381
|
}
|
|
203
382
|
catch (err) {
|
|
204
383
|
console.warn('[Swarm] Could not enable Gemini plan mode:', err);
|
|
205
384
|
}
|
|
206
385
|
}
|
|
386
|
+
/** Check whether the CLI binary for a given agent type exists in PATH. Returns [available, pathOrError]. */
|
|
207
387
|
export function checkCliAvailable(agentType) {
|
|
208
388
|
const cmdTemplate = AGENT_COMMANDS[agentType];
|
|
209
389
|
if (!cmdTemplate) {
|
|
@@ -218,6 +398,7 @@ export function checkCliAvailable(agentType) {
|
|
|
218
398
|
return [false, `CLI tool '${executable}' not found in PATH. Install it first.`];
|
|
219
399
|
}
|
|
220
400
|
}
|
|
401
|
+
/** Check availability of all known agent CLIs. Returns a map of agent type to install status. */
|
|
221
402
|
export function checkAllClis() {
|
|
222
403
|
const results = {};
|
|
223
404
|
for (const agentType of Object.keys(AGENT_COMMANDS)) {
|
|
@@ -232,12 +413,20 @@ export function checkAllClis() {
|
|
|
232
413
|
return results;
|
|
233
414
|
}
|
|
234
415
|
let AGENTS_DIR = null;
|
|
416
|
+
/** Resolve and cache the base directory where teammate process data is stored. */
|
|
235
417
|
export async function getAgentsDir() {
|
|
236
418
|
if (!AGENTS_DIR) {
|
|
237
419
|
AGENTS_DIR = await resolveAgentsDir();
|
|
238
420
|
}
|
|
239
421
|
return AGENTS_DIR;
|
|
240
422
|
}
|
|
423
|
+
/**
|
|
424
|
+
* Represents a single teammate process within a team.
|
|
425
|
+
*
|
|
426
|
+
* Tracks process metadata (PID, status, timestamps), reads incremental
|
|
427
|
+
* stdout events, persists state to disk as meta.json, and can be
|
|
428
|
+
* reconstituted from disk via loadFromDisk().
|
|
429
|
+
*/
|
|
241
430
|
export class AgentProcess {
|
|
242
431
|
agentId;
|
|
243
432
|
taskName;
|
|
@@ -247,6 +436,9 @@ export class AgentProcess {
|
|
|
247
436
|
workspaceDir;
|
|
248
437
|
mode = 'plan';
|
|
249
438
|
pid = null;
|
|
439
|
+
// Captured at spawn time so we can detect PID reuse before signaling.
|
|
440
|
+
// Compared against the live /proc or `ps` value at every kill() call.
|
|
441
|
+
startTime = null;
|
|
250
442
|
status = AgentStatus.RUNNING;
|
|
251
443
|
startedAt = new Date();
|
|
252
444
|
completedAt = null;
|
|
@@ -269,10 +461,17 @@ export class AgentProcess {
|
|
|
269
461
|
model = null;
|
|
270
462
|
// Extra env vars passed through to the child process (from --env KEY=VALUE).
|
|
271
463
|
envOverrides = null;
|
|
464
|
+
// Factory task-type label. Drives planner fan-out. Null for plain teammates — no behavioral change.
|
|
465
|
+
taskType = null;
|
|
466
|
+
// Repo/branch for cloud dispatches that stage behind --after. Captured
|
|
467
|
+
// at spawn time so startReady() can invoke the dispatcher with the same
|
|
468
|
+
// options the user originally supplied.
|
|
469
|
+
cloudRepo = null;
|
|
470
|
+
cloudBranch = null;
|
|
272
471
|
eventsCache = [];
|
|
273
472
|
lastReadPos = 0;
|
|
274
473
|
baseDir = null;
|
|
275
|
-
constructor(agentId, taskName, agentType, prompt, cwd = null, mode = 'plan', pid = null, status = AgentStatus.RUNNING, startedAt = new Date(), completedAt = null, baseDir = null, parentSessionId = null, workspaceDir = null, cloudSessionId = null, cloudProvider = null, prUrl = null, version = null, remoteSessionId = null, name = null, after = [], effort = null, model = null, envOverrides = null) {
|
|
474
|
+
constructor(agentId, taskName, agentType, prompt, cwd = null, mode = 'plan', pid = null, status = AgentStatus.RUNNING, startedAt = new Date(), completedAt = null, baseDir = null, parentSessionId = null, workspaceDir = null, cloudSessionId = null, cloudProvider = null, prUrl = null, version = null, remoteSessionId = null, name = null, after = [], effort = null, model = null, envOverrides = null, taskType = null, cloudRepo = null, cloudBranch = null) {
|
|
276
475
|
this.agentId = agentId;
|
|
277
476
|
this.remoteSessionId = remoteSessionId;
|
|
278
477
|
this.name = name;
|
|
@@ -280,6 +479,9 @@ export class AgentProcess {
|
|
|
280
479
|
this.effort = effort;
|
|
281
480
|
this.model = model;
|
|
282
481
|
this.envOverrides = envOverrides;
|
|
482
|
+
this.taskType = taskType;
|
|
483
|
+
this.cloudRepo = cloudRepo;
|
|
484
|
+
this.cloudBranch = cloudBranch;
|
|
283
485
|
this.taskName = taskName;
|
|
284
486
|
this.agentType = agentType;
|
|
285
487
|
this.prompt = prompt;
|
|
@@ -304,6 +506,29 @@ export class AgentProcess {
|
|
|
304
506
|
const base = this.baseDir || await getAgentsDir();
|
|
305
507
|
return path.join(base, this.agentId);
|
|
306
508
|
}
|
|
509
|
+
/**
|
|
510
|
+
* Dump the subset of state the Ledger sync hook needs. Keeps sync.ts
|
|
511
|
+
* free of any teams-internal imports.
|
|
512
|
+
*/
|
|
513
|
+
async toSnapshot() {
|
|
514
|
+
return {
|
|
515
|
+
agent_id: this.agentId,
|
|
516
|
+
team_id: this.taskName,
|
|
517
|
+
teammate_name: this.name,
|
|
518
|
+
agent_type: this.agentType,
|
|
519
|
+
task_type: this.taskType,
|
|
520
|
+
status: this.status,
|
|
521
|
+
started_at: this.startedAt.toISOString(),
|
|
522
|
+
completed_at: this.completedAt?.toISOString() ?? null,
|
|
523
|
+
after: this.after,
|
|
524
|
+
cloud_provider: this.cloudProvider,
|
|
525
|
+
cloud_session_id: this.cloudSessionId,
|
|
526
|
+
cloud_repo: this.cloudRepo,
|
|
527
|
+
cloud_branch: this.cloudBranch,
|
|
528
|
+
agent_dir: await this.getAgentDir(),
|
|
529
|
+
cwd: this.cwd,
|
|
530
|
+
};
|
|
531
|
+
}
|
|
307
532
|
async getStdoutPath() {
|
|
308
533
|
return path.join(await this.getAgentDir(), 'stdout.log');
|
|
309
534
|
}
|
|
@@ -333,6 +558,9 @@ export class AgentProcess {
|
|
|
333
558
|
effort: this.effort,
|
|
334
559
|
model: this.model,
|
|
335
560
|
env_overrides: this.envOverrides,
|
|
561
|
+
task_type: this.taskType,
|
|
562
|
+
cloud_repo: this.cloudRepo,
|
|
563
|
+
cloud_branch: this.cloudBranch,
|
|
336
564
|
};
|
|
337
565
|
}
|
|
338
566
|
duration() {
|
|
@@ -445,6 +673,7 @@ export class AgentProcess {
|
|
|
445
673
|
workspace_dir: this.workspaceDir,
|
|
446
674
|
mode: this.mode,
|
|
447
675
|
pid: this.pid,
|
|
676
|
+
start_time: this.startTime,
|
|
448
677
|
status: this.status,
|
|
449
678
|
started_at: this.startedAt.toISOString(),
|
|
450
679
|
completed_at: this.completedAt?.toISOString() || null,
|
|
@@ -459,6 +688,9 @@ export class AgentProcess {
|
|
|
459
688
|
effort: this.effort,
|
|
460
689
|
model: this.model,
|
|
461
690
|
env_overrides: this.envOverrides,
|
|
691
|
+
task_type: this.taskType,
|
|
692
|
+
cloud_repo: this.cloudRepo,
|
|
693
|
+
cloud_branch: this.cloudBranch,
|
|
462
694
|
};
|
|
463
695
|
const metaPath = await this.getMetaPath();
|
|
464
696
|
await fs.writeFile(metaPath, JSON.stringify(meta, null, 2));
|
|
@@ -492,7 +724,10 @@ export class AgentProcess {
|
|
|
492
724
|
const resolvedStatus = validStatuses.includes(meta.status)
|
|
493
725
|
? meta.status
|
|
494
726
|
: AgentStatus.RUNNING;
|
|
495
|
-
const agent = new AgentProcess(meta.agent_id, meta.task_name || 'default', meta.agent_type, meta.prompt, meta.cwd || null, resolvedMode, meta.pid || null, resolvedStatus, new Date(meta.started_at), meta.completed_at ? new Date(meta.completed_at) : null, baseDir, meta.parent_session_id || null, meta.workspace_dir || null, meta.cloud_session_id || null, meta.cloud_provider || null, meta.pr_url || null, meta.version || null, meta.remote_session_id || null, meta.name || null, Array.isArray(meta.after) ? meta.after : [], meta.effort || null, meta.model || null, meta.env_overrides || null)
|
|
727
|
+
const agent = new AgentProcess(meta.agent_id, meta.task_name || 'default', meta.agent_type, meta.prompt, meta.cwd || null, resolvedMode, meta.pid || null, resolvedStatus, new Date(meta.started_at), meta.completed_at ? new Date(meta.completed_at) : null, baseDir, meta.parent_session_id || null, meta.workspace_dir || null, meta.cloud_session_id || null, meta.cloud_provider || null, meta.pr_url || null, meta.version || null, meta.remote_session_id || null, meta.name || null, Array.isArray(meta.after) ? meta.after : [], meta.effort || null, meta.model || null, meta.env_overrides || null, meta.task_type && VALID_TASK_TYPES.includes(meta.task_type)
|
|
728
|
+
? meta.task_type
|
|
729
|
+
: null, meta.cloud_repo || null, meta.cloud_branch || null);
|
|
730
|
+
agent.startTime = typeof meta.start_time === 'string' ? meta.start_time : null;
|
|
496
731
|
return agent;
|
|
497
732
|
}
|
|
498
733
|
catch {
|
|
@@ -504,15 +739,61 @@ export class AgentProcess {
|
|
|
504
739
|
return false;
|
|
505
740
|
try {
|
|
506
741
|
process.kill(this.pid, 0);
|
|
507
|
-
return true;
|
|
508
742
|
}
|
|
509
743
|
catch {
|
|
510
744
|
return false;
|
|
511
745
|
}
|
|
746
|
+
// PID is occupied — but is it still OUR process? If we captured a
|
|
747
|
+
// start-time at spawn, refuse to claim aliveness when the live value
|
|
748
|
+
// differs. A null startTime means we never captured one (legacy
|
|
749
|
+
// teammates loaded from disk before this field existed) — fall back to
|
|
750
|
+
// the bare kill(pid, 0) result for those.
|
|
751
|
+
if (this.startTime !== null) {
|
|
752
|
+
const current = captureProcessStartTime(this.pid);
|
|
753
|
+
if (current === null || current !== this.startTime) {
|
|
754
|
+
return false;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
return true;
|
|
512
758
|
}
|
|
513
759
|
async updateStatusFromProcess() {
|
|
514
|
-
if (!this.pid)
|
|
760
|
+
if (!this.pid) {
|
|
761
|
+
await this.readNewEvents();
|
|
762
|
+
// Cloud-backed teammates have no local PID by design; their lifecycle
|
|
763
|
+
// is driven by the remote provider instead of a local process.
|
|
764
|
+
if (this.cloudProvider) {
|
|
765
|
+
if (!this.completedAt && this.status !== AgentStatus.RUNNING) {
|
|
766
|
+
const fallbackCompletion = this.getLatestEventTime() || this.startedAt || new Date();
|
|
767
|
+
this.completedAt = fallbackCompletion;
|
|
768
|
+
await this.saveMeta();
|
|
769
|
+
}
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
// Pending teammates with unresolved --after deps also have no PID yet.
|
|
773
|
+
// Leave them alone until startReady() launches them.
|
|
774
|
+
if (this.status === AgentStatus.PENDING) {
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
// A local teammate marked RUNNING without a PID is an impossible state:
|
|
778
|
+
// launch never produced a durable process identity, so it cannot still
|
|
779
|
+
// be doing work. Keep any terminal event parsed from stdout; otherwise
|
|
780
|
+
// fail it and stamp completion so team rollups stop showing it as live.
|
|
781
|
+
if (this.status === AgentStatus.RUNNING) {
|
|
782
|
+
const fallbackCompletion = this.getLatestEventTime() || this.startedAt || new Date();
|
|
783
|
+
if (this.status === AgentStatus.RUNNING) {
|
|
784
|
+
this.status = AgentStatus.FAILED;
|
|
785
|
+
this.completedAt = fallbackCompletion;
|
|
786
|
+
}
|
|
787
|
+
await this.saveMeta();
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
if (!this.completedAt) {
|
|
791
|
+
const fallbackCompletion = this.getLatestEventTime() || this.startedAt || new Date();
|
|
792
|
+
this.completedAt = fallbackCompletion;
|
|
793
|
+
await this.saveMeta();
|
|
794
|
+
}
|
|
515
795
|
return;
|
|
796
|
+
}
|
|
516
797
|
if (this.isProcessAlive()) {
|
|
517
798
|
await this.readNewEvents();
|
|
518
799
|
return;
|
|
@@ -553,7 +834,6 @@ export class AgentProcess {
|
|
|
553
834
|
export class AgentManager {
|
|
554
835
|
agents = new Map();
|
|
555
836
|
maxAgents;
|
|
556
|
-
maxConcurrent;
|
|
557
837
|
agentsDir = '';
|
|
558
838
|
filterByCwd;
|
|
559
839
|
cleanupAgeDays;
|
|
@@ -561,10 +841,10 @@ export class AgentManager {
|
|
|
561
841
|
agentConfigs;
|
|
562
842
|
constructorAgentConfigs = null;
|
|
563
843
|
initPromise = null;
|
|
844
|
+
cloudDispatcher = null;
|
|
564
845
|
constructorAgentsDir = null;
|
|
565
|
-
constructor(maxAgents = 50,
|
|
846
|
+
constructor(maxAgents = 50, agentsDir = null, defaultMode = null, filterByCwd = null, cleanupAgeDays = 7, agentConfigs = null) {
|
|
566
847
|
this.maxAgents = maxAgents;
|
|
567
|
-
this.maxConcurrent = maxConcurrent;
|
|
568
848
|
this.constructorAgentsDir = agentsDir;
|
|
569
849
|
this.filterByCwd = filterByCwd;
|
|
570
850
|
this.cleanupAgeDays = cleanupAgeDays;
|
|
@@ -594,9 +874,53 @@ export class AgentManager {
|
|
|
594
874
|
setModelOverrides(agentConfigs) {
|
|
595
875
|
this.agentConfigs = agentConfigs;
|
|
596
876
|
}
|
|
877
|
+
/**
|
|
878
|
+
* Register the callback used to dispatch cloud-backed teammates when their
|
|
879
|
+
* --after deps resolve. Called once at CLI startup by `agents teams`.
|
|
880
|
+
*/
|
|
881
|
+
setCloudDispatcher(fn) {
|
|
882
|
+
this.cloudDispatcher = fn;
|
|
883
|
+
}
|
|
597
884
|
registerAgent(agent) {
|
|
598
885
|
this.agents.set(agent.agentId, agent);
|
|
599
886
|
}
|
|
887
|
+
/**
|
|
888
|
+
* Scan the agents dir for meta.json files not already in the in-memory
|
|
889
|
+
* cache and load them. Needed when another process (e.g. a Planner
|
|
890
|
+
* teammate running `agents teams add`) creates new teammates while this
|
|
891
|
+
* manager is alive — the supervisor loop calls this each wave so
|
|
892
|
+
* dynamically-added teammates get picked up.
|
|
893
|
+
*
|
|
894
|
+
* Does not modify or re-load agents already in the cache; that path is
|
|
895
|
+
* covered by updateStatusFromProcess() which re-reads stdout.log.
|
|
896
|
+
*/
|
|
897
|
+
async rescanFromDisk() {
|
|
898
|
+
await this.initialize();
|
|
899
|
+
try {
|
|
900
|
+
await fs.access(this.agentsDir);
|
|
901
|
+
}
|
|
902
|
+
catch {
|
|
903
|
+
return 0;
|
|
904
|
+
}
|
|
905
|
+
const entries = await fs.readdir(this.agentsDir);
|
|
906
|
+
let added = 0;
|
|
907
|
+
for (const entry of entries) {
|
|
908
|
+
if (this.agents.has(entry))
|
|
909
|
+
continue;
|
|
910
|
+
const agentDir = path.join(this.agentsDir, entry);
|
|
911
|
+
const stat = await fs.stat(agentDir).catch(() => null);
|
|
912
|
+
if (!stat || !stat.isDirectory())
|
|
913
|
+
continue;
|
|
914
|
+
const agent = await AgentProcess.loadFromDisk(entry, this.agentsDir);
|
|
915
|
+
if (!agent)
|
|
916
|
+
continue;
|
|
917
|
+
if (this.filterByCwd !== null && agent.cwd !== this.filterByCwd)
|
|
918
|
+
continue;
|
|
919
|
+
this.agents.set(entry, agent);
|
|
920
|
+
added++;
|
|
921
|
+
}
|
|
922
|
+
return added;
|
|
923
|
+
}
|
|
600
924
|
async loadExistingAgents() {
|
|
601
925
|
try {
|
|
602
926
|
await fs.access(this.agentsDir);
|
|
@@ -647,7 +971,7 @@ export class AgentManager {
|
|
|
647
971
|
}
|
|
648
972
|
debug(`Loaded ${loadedCount} agents from disk`);
|
|
649
973
|
}
|
|
650
|
-
async spawn(taskName, agentType, prompt, cwd = null, mode = null, effort = 'medium', parentSessionId = null, workspaceDir = null, version = null, name = null, after = [], model = null, envOverrides = null) {
|
|
974
|
+
async spawn(taskName, agentType, prompt, cwd = null, mode = null, effort = 'medium', parentSessionId = null, workspaceDir = null, version = null, name = null, after = [], model = null, envOverrides = null, taskType = null, cloudProvider = null, cloudSessionId = null, cloudRepo = null, cloudBranch = null) {
|
|
651
975
|
await this.initialize();
|
|
652
976
|
const resolvedMode = resolveMode(mode, this.defaultMode);
|
|
653
977
|
// Enforce: teammate names are unique within a team.
|
|
@@ -689,15 +1013,24 @@ export class AgentManager {
|
|
|
689
1013
|
throw new Error(`Working directory is not a directory: ${cwd}`);
|
|
690
1014
|
}
|
|
691
1015
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
1016
|
+
// Cloud-backed teammates run on remote infrastructure; we don't need the
|
|
1017
|
+
// local CLI for them (the pod has its own). The caller has already
|
|
1018
|
+
// dispatched via the cloud provider and passed us the provider + session.
|
|
1019
|
+
const isCloudBacked = Boolean(cloudProvider);
|
|
1020
|
+
if (!isCloudBacked) {
|
|
1021
|
+
const [available, pathOrError] = checkCliAvailable(agentType);
|
|
1022
|
+
if (!available) {
|
|
1023
|
+
throw new Error(pathOrError || 'CLI tool not available');
|
|
1024
|
+
}
|
|
695
1025
|
}
|
|
696
1026
|
// Use a full UUIDv4 as the canonical agent_id. For Claude, we pass it via
|
|
697
1027
|
// --session-id so it's also Claude's session id (unified identity).
|
|
698
1028
|
const agentId = randomUUID();
|
|
699
1029
|
const isStaged = cleanAfter.length > 0;
|
|
700
|
-
const
|
|
1030
|
+
const initialStatus = isStaged || !isCloudBacked
|
|
1031
|
+
? AgentStatus.PENDING
|
|
1032
|
+
: AgentStatus.RUNNING;
|
|
1033
|
+
const agent = new AgentProcess(agentId, taskName, agentType, prompt, resolvedCwd, resolvedMode, null, initialStatus, new Date(), null, this.agentsDir, parentSessionId, workspaceDir, cloudSessionId, cloudProvider, null, version, null, name, cleanAfter, effort, model, envOverrides && Object.keys(envOverrides).length > 0 ? envOverrides : null, taskType, cloudRepo, cloudBranch);
|
|
701
1034
|
const agentDir = await agent.getAgentDir();
|
|
702
1035
|
try {
|
|
703
1036
|
await fs.mkdir(agentDir, { recursive: true });
|
|
@@ -705,13 +1038,19 @@ export class AgentManager {
|
|
|
705
1038
|
catch (err) {
|
|
706
1039
|
throw new Error(`Failed to create agent directory: ${err.message}`);
|
|
707
1040
|
}
|
|
708
|
-
await agent.saveMeta();
|
|
709
1041
|
this.agents.set(agentId, agent);
|
|
710
|
-
if (
|
|
711
|
-
await
|
|
1042
|
+
if (isStaged) {
|
|
1043
|
+
await agent.saveMeta();
|
|
1044
|
+
debug(`Staged ${agentType} teammate '${name}' in team '${taskName}' (after: ${cleanAfter.join(', ')})`);
|
|
1045
|
+
}
|
|
1046
|
+
else if (isCloudBacked) {
|
|
1047
|
+
// Cloud-backed teammate: the provider already dispatched a remote task.
|
|
1048
|
+
// No local process to launch; status polling walks the provider instead.
|
|
1049
|
+
await agent.saveMeta();
|
|
1050
|
+
debug(`Cloud-backed ${agentType} teammate via ${cloudProvider} (session=${cloudSessionId})`);
|
|
712
1051
|
}
|
|
713
1052
|
else {
|
|
714
|
-
|
|
1053
|
+
await this.launchProcess(agent);
|
|
715
1054
|
}
|
|
716
1055
|
await this.cleanupOldAgents();
|
|
717
1056
|
return agent;
|
|
@@ -722,9 +1061,7 @@ export class AgentManager {
|
|
|
722
1061
|
*/
|
|
723
1062
|
async launchProcess(agent) {
|
|
724
1063
|
const running = await this.listRunning();
|
|
725
|
-
|
|
726
|
-
throw new Error(`Maximum concurrent agents (${this.maxConcurrent}) reached. Wait for an agent to complete or stop one first.`);
|
|
727
|
-
}
|
|
1064
|
+
warnIfMemoryLow(running.length);
|
|
728
1065
|
const effort = agent.effort ?? 'medium';
|
|
729
1066
|
// Falls back to the pinned model in agentConfigs; null means "let the
|
|
730
1067
|
// CLI pick its own default" (no --model flag forwarded). Effort is a
|
|
@@ -750,6 +1087,11 @@ export class AgentManager {
|
|
|
750
1087
|
childProcess.unref();
|
|
751
1088
|
stdoutFile.close().catch(() => { });
|
|
752
1089
|
agent.pid = childProcess.pid || null;
|
|
1090
|
+
// Capture start-time NOW, while we know the PID is ours. Once the
|
|
1091
|
+
// OS reuses this PID slot, /proc and `ps` will report a different
|
|
1092
|
+
// value — that's the signal stop() uses to refuse to signal an
|
|
1093
|
+
// unrelated process.
|
|
1094
|
+
agent.startTime = agent.pid ? captureProcessStartTime(agent.pid) : null;
|
|
753
1095
|
agent.status = AgentStatus.RUNNING;
|
|
754
1096
|
agent.startedAt = new Date();
|
|
755
1097
|
await agent.saveMeta();
|
|
@@ -782,8 +1124,22 @@ export class AgentManager {
|
|
|
782
1124
|
if (!depsReady)
|
|
783
1125
|
continue;
|
|
784
1126
|
try {
|
|
785
|
-
|
|
786
|
-
|
|
1127
|
+
if (agent.cloudProvider) {
|
|
1128
|
+
if (!this.cloudDispatcher) {
|
|
1129
|
+
console.error(`Cannot start cloud-backed teammate ${agent.agentId}: no dispatcher registered.`);
|
|
1130
|
+
continue;
|
|
1131
|
+
}
|
|
1132
|
+
const { cloudSessionId } = await this.cloudDispatcher(agent);
|
|
1133
|
+
agent.cloudSessionId = cloudSessionId;
|
|
1134
|
+
agent.status = AgentStatus.RUNNING;
|
|
1135
|
+
agent.startedAt = new Date();
|
|
1136
|
+
await agent.saveMeta();
|
|
1137
|
+
launched.push(agent);
|
|
1138
|
+
}
|
|
1139
|
+
else {
|
|
1140
|
+
await this.launchProcess(agent);
|
|
1141
|
+
launched.push(agent);
|
|
1142
|
+
}
|
|
787
1143
|
}
|
|
788
1144
|
catch (err) {
|
|
789
1145
|
console.error(`Could not launch ${agent.agentId}:`, err);
|
|
@@ -821,6 +1177,14 @@ export class AgentManager {
|
|
|
821
1177
|
// ~/.claude/settings.json would override that and bind settings to the
|
|
822
1178
|
// *default* version rather than the one this teammate is running.
|
|
823
1179
|
}
|
|
1180
|
+
if (agentType === 'codex') {
|
|
1181
|
+
// Codex's workspace-write sandbox blocks writes outside cwd. Factory
|
|
1182
|
+
// teammates need to run further `agents teams add` commands,
|
|
1183
|
+
// which write to ~/.agents/. Grant that root so subprocess-issued
|
|
1184
|
+
// `agents teams add` calls hit the real store instead of the tmp
|
|
1185
|
+
// fallback (which the supervisor does not watch).
|
|
1186
|
+
cmd.push('--add-dir', getSystemAgentsDir());
|
|
1187
|
+
}
|
|
824
1188
|
// Add model flag for each agent type only when the teammate has a pinned
|
|
825
1189
|
// model. When null, the agent's CLI picks its own default.
|
|
826
1190
|
if (model) {
|
|
@@ -870,61 +1234,10 @@ export class AgentManager {
|
|
|
870
1234
|
return cmd;
|
|
871
1235
|
}
|
|
872
1236
|
applyEditMode(agentType, cmd) {
|
|
873
|
-
|
|
874
|
-
switch (agentType) {
|
|
875
|
-
case 'codex':
|
|
876
|
-
editCmd.push('--full-auto');
|
|
877
|
-
break;
|
|
878
|
-
case 'cursor':
|
|
879
|
-
editCmd.push('-f');
|
|
880
|
-
break;
|
|
881
|
-
case 'gemini': {
|
|
882
|
-
const approvalIndex = editCmd.indexOf('--approval-mode');
|
|
883
|
-
if (approvalIndex !== -1) {
|
|
884
|
-
editCmd.splice(approvalIndex, 2);
|
|
885
|
-
}
|
|
886
|
-
editCmd.push('--yolo');
|
|
887
|
-
break;
|
|
888
|
-
}
|
|
889
|
-
case 'claude':
|
|
890
|
-
const permModeIndex = editCmd.indexOf('--permission-mode');
|
|
891
|
-
if (permModeIndex !== -1 && permModeIndex + 1 < editCmd.length) {
|
|
892
|
-
editCmd[permModeIndex + 1] = 'acceptEdits';
|
|
893
|
-
}
|
|
894
|
-
break;
|
|
895
|
-
}
|
|
896
|
-
return editCmd;
|
|
1237
|
+
return applyEditMode(agentType, cmd);
|
|
897
1238
|
}
|
|
898
|
-
// "full" mode: edit-level write access with permission gates bypassed.
|
|
899
|
-
// For Claude that's --dangerously-skip-permissions; other agents already
|
|
900
|
-
// lack gates in edit mode so their commands match applyEditMode.
|
|
901
1239
|
applyFullMode(agentType, cmd) {
|
|
902
|
-
|
|
903
|
-
switch (agentType) {
|
|
904
|
-
case 'codex':
|
|
905
|
-
fullCmd.push('--full-auto');
|
|
906
|
-
break;
|
|
907
|
-
case 'cursor':
|
|
908
|
-
fullCmd.push('-f');
|
|
909
|
-
break;
|
|
910
|
-
case 'gemini': {
|
|
911
|
-
const approvalIndex = fullCmd.indexOf('--approval-mode');
|
|
912
|
-
if (approvalIndex !== -1) {
|
|
913
|
-
fullCmd.splice(approvalIndex, 2);
|
|
914
|
-
}
|
|
915
|
-
fullCmd.push('--yolo');
|
|
916
|
-
break;
|
|
917
|
-
}
|
|
918
|
-
case 'claude':
|
|
919
|
-
// Replace --permission-mode plan with --dangerously-skip-permissions
|
|
920
|
-
const permModeIndex = fullCmd.indexOf('--permission-mode');
|
|
921
|
-
if (permModeIndex !== -1) {
|
|
922
|
-
fullCmd.splice(permModeIndex, 2); // Remove --permission-mode and its value
|
|
923
|
-
}
|
|
924
|
-
fullCmd.push('--dangerously-skip-permissions');
|
|
925
|
-
break;
|
|
926
|
-
}
|
|
927
|
-
return fullCmd;
|
|
1240
|
+
return applyFullMode(agentType, cmd);
|
|
928
1241
|
}
|
|
929
1242
|
async get(agentId) {
|
|
930
1243
|
await this.initialize();
|
|
@@ -1019,6 +1332,17 @@ export class AgentManager {
|
|
|
1019
1332
|
return false;
|
|
1020
1333
|
}
|
|
1021
1334
|
if (agent.pid && agent.status === AgentStatus.RUNNING) {
|
|
1335
|
+
// PID-reuse guard: if the PID we recorded at spawn no longer maps to
|
|
1336
|
+
// our process (start-time mismatch), the OS has recycled it. Sending
|
|
1337
|
+
// SIGTERM/SIGKILL to -pid here would kill an unrelated process group.
|
|
1338
|
+
// Treat as already gone and just record the stop without signaling.
|
|
1339
|
+
if (!agent.isProcessAlive()) {
|
|
1340
|
+
debug(`Agent ${agentId} PID ${agent.pid} no longer ours (start-time mismatch or exited); skipping signal`);
|
|
1341
|
+
agent.status = AgentStatus.STOPPED;
|
|
1342
|
+
agent.completedAt = new Date();
|
|
1343
|
+
await agent.saveMeta();
|
|
1344
|
+
return true;
|
|
1345
|
+
}
|
|
1022
1346
|
try {
|
|
1023
1347
|
process.kill(-agent.pid, 'SIGTERM');
|
|
1024
1348
|
debug(`Sent SIGTERM to agent ${agentId} (PID ${agent.pid})`);
|
|
@@ -1069,4 +1393,3 @@ export class AgentManager {
|
|
|
1069
1393
|
}
|
|
1070
1394
|
}
|
|
1071
1395
|
}
|
|
1072
|
-
//# sourceMappingURL=agents.js.map
|