@swarmify/agents-cli 1.13.4 → 1.14.2
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/README.md +4 -319
- package/bin/agents.js +2 -0
- package/package.json +13 -79
- package/scripts/postinstall.js +4 -71
- package/CHANGELOG.md +0 -316
- package/LICENSE +0 -21
- package/dist/commands/__tests__/sessions-tail.test.d.ts +0 -2
- package/dist/commands/__tests__/sessions-tail.test.d.ts.map +0 -1
- package/dist/commands/__tests__/sessions-tail.test.js +0 -108
- package/dist/commands/__tests__/sessions-tail.test.js.map +0 -1
- 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 +0 -11
- package/dist/commands/cloud.d.ts.map +0 -1
- package/dist/commands/cloud.js +0 -363
- package/dist/commands/cloud.js.map +0 -1
- package/dist/commands/commands.d.ts +0 -12
- package/dist/commands/commands.d.ts.map +0 -1
- package/dist/commands/commands.js +0 -629
- package/dist/commands/commands.js.map +0 -1
- package/dist/commands/daemon.d.ts +0 -11
- package/dist/commands/daemon.d.ts.map +0 -1
- package/dist/commands/daemon.js +0 -119
- package/dist/commands/daemon.js.map +0 -1
- package/dist/commands/drive.d.ts +0 -11
- package/dist/commands/drive.d.ts.map +0 -1
- package/dist/commands/drive.js +0 -175
- package/dist/commands/drive.js.map +0 -1
- package/dist/commands/exec.d.ts +0 -11
- package/dist/commands/exec.d.ts.map +0 -1
- package/dist/commands/exec.js +0 -251
- package/dist/commands/exec.js.map +0 -1
- package/dist/commands/factory.d.ts +0 -11
- package/dist/commands/factory.d.ts.map +0 -1
- package/dist/commands/factory.js +0 -445
- package/dist/commands/factory.js.map +0 -1
- package/dist/commands/fork.d.ts +0 -11
- package/dist/commands/fork.d.ts.map +0 -1
- package/dist/commands/fork.js +0 -147
- package/dist/commands/fork.js.map +0 -1
- package/dist/commands/hooks.d.ts +0 -12
- package/dist/commands/hooks.d.ts.map +0 -1
- package/dist/commands/hooks.js +0 -690
- package/dist/commands/hooks.js.map +0 -1
- package/dist/commands/init.d.ts +0 -15
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -137
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/mcp.d.ts +0 -12
- package/dist/commands/mcp.d.ts.map +0 -1
- package/dist/commands/mcp.js +0 -583
- package/dist/commands/mcp.js.map +0 -1
- package/dist/commands/models.d.ts +0 -11
- package/dist/commands/models.d.ts.map +0 -1
- package/dist/commands/models.js +0 -170
- package/dist/commands/models.js.map +0 -1
- package/dist/commands/packages.d.ts +0 -11
- package/dist/commands/packages.d.ts.map +0 -1
- package/dist/commands/packages.js +0 -551
- package/dist/commands/packages.js.map +0 -1
- package/dist/commands/permissions.d.ts +0 -12
- package/dist/commands/permissions.d.ts.map +0 -1
- package/dist/commands/permissions.js +0 -724
- package/dist/commands/permissions.js.map +0 -1
- package/dist/commands/plugins.d.ts +0 -11
- package/dist/commands/plugins.d.ts.map +0 -1
- package/dist/commands/plugins.js +0 -393
- package/dist/commands/plugins.js.map +0 -1
- package/dist/commands/profiles.d.ts +0 -12
- package/dist/commands/profiles.d.ts.map +0 -1
- package/dist/commands/profiles.js +0 -255
- package/dist/commands/profiles.js.map +0 -1
- package/dist/commands/pty.d.ts +0 -21
- package/dist/commands/pty.d.ts.map +0 -1
- package/dist/commands/pty.js +0 -391
- package/dist/commands/pty.js.map +0 -1
- package/dist/commands/pull.d.ts +0 -11
- package/dist/commands/pull.d.ts.map +0 -1
- package/dist/commands/pull.js +0 -456
- package/dist/commands/pull.js.map +0 -1
- package/dist/commands/push.d.ts +0 -11
- package/dist/commands/push.d.ts.map +0 -1
- package/dist/commands/push.js +0 -188
- package/dist/commands/push.js.map +0 -1
- package/dist/commands/refresh-memory.d.ts +0 -16
- package/dist/commands/refresh-memory.d.ts.map +0 -1
- package/dist/commands/refresh-memory.js +0 -52
- package/dist/commands/refresh-memory.js.map +0 -1
- package/dist/commands/resource-view.d.ts +0 -39
- package/dist/commands/resource-view.d.ts.map +0 -1
- package/dist/commands/resource-view.js +0 -197
- package/dist/commands/resource-view.js.map +0 -1
- package/dist/commands/routines.d.ts +0 -11
- package/dist/commands/routines.d.ts.map +0 -1
- package/dist/commands/routines.js +0 -590
- package/dist/commands/routines.js.map +0 -1
- package/dist/commands/rules.d.ts +0 -12
- package/dist/commands/rules.d.ts.map +0 -1
- package/dist/commands/rules.js +0 -489
- package/dist/commands/rules.js.map +0 -1
- package/dist/commands/secrets.d.ts +0 -11
- package/dist/commands/secrets.d.ts.map +0 -1
- package/dist/commands/secrets.js +0 -352
- package/dist/commands/secrets.js.map +0 -1
- package/dist/commands/sessions-picker.d.ts +0 -18
- package/dist/commands/sessions-picker.d.ts.map +0 -1
- package/dist/commands/sessions-picker.js +0 -265
- package/dist/commands/sessions-picker.js.map +0 -1
- package/dist/commands/sessions-tail.d.ts +0 -20
- package/dist/commands/sessions-tail.d.ts.map +0 -1
- package/dist/commands/sessions-tail.js +0 -236
- package/dist/commands/sessions-tail.js.map +0 -1
- package/dist/commands/sessions.d.ts +0 -18
- package/dist/commands/sessions.d.ts.map +0 -1
- package/dist/commands/sessions.js +0 -1173
- package/dist/commands/sessions.js.map +0 -1
- package/dist/commands/skills.d.ts +0 -12
- package/dist/commands/skills.d.ts.map +0 -1
- package/dist/commands/skills.js +0 -717
- package/dist/commands/skills.js.map +0 -1
- package/dist/commands/status.d.ts +0 -10
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/status.js +0 -26
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/subagents.d.ts +0 -11
- package/dist/commands/subagents.d.ts.map +0 -1
- package/dist/commands/subagents.js +0 -361
- package/dist/commands/subagents.js.map +0 -1
- package/dist/commands/sync.d.ts +0 -11
- package/dist/commands/sync.d.ts.map +0 -1
- package/dist/commands/sync.js +0 -70
- package/dist/commands/sync.js.map +0 -1
- package/dist/commands/teams-picker.d.ts +0 -18
- package/dist/commands/teams-picker.d.ts.map +0 -1
- package/dist/commands/teams-picker.js +0 -290
- package/dist/commands/teams-picker.js.map +0 -1
- package/dist/commands/teams.d.ts +0 -18
- package/dist/commands/teams.d.ts.map +0 -1
- package/dist/commands/teams.js +0 -1144
- package/dist/commands/teams.js.map +0 -1
- package/dist/commands/utils.d.ts +0 -45
- package/dist/commands/utils.d.ts.map +0 -1
- package/dist/commands/utils.js +0 -106
- package/dist/commands/utils.js.map +0 -1
- package/dist/commands/versions.d.ts +0 -11
- package/dist/commands/versions.d.ts.map +0 -1
- package/dist/commands/versions.js +0 -701
- package/dist/commands/versions.js.map +0 -1
- package/dist/commands/view.d.ts +0 -43
- package/dist/commands/view.d.ts.map +0 -1
- package/dist/commands/view.js +0 -894
- package/dist/commands/view.js.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -496
- 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 -57
- 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 +0 -158
- package/dist/lib/agents.d.ts.map +0 -1
- package/dist/lib/agents.js +0 -1159
- package/dist/lib/agents.js.map +0 -1
- package/dist/lib/artifact-actions.d.ts +0 -27
- package/dist/lib/artifact-actions.d.ts.map +0 -1
- package/dist/lib/artifact-actions.js +0 -58
- package/dist/lib/artifact-actions.js.map +0 -1
- package/dist/lib/cloud/codex.d.ts +0 -26
- package/dist/lib/cloud/codex.d.ts.map +0 -1
- package/dist/lib/cloud/codex.js +0 -237
- package/dist/lib/cloud/codex.js.map +0 -1
- package/dist/lib/cloud/factory.d.ts +0 -32
- package/dist/lib/cloud/factory.d.ts.map +0 -1
- package/dist/lib/cloud/factory.js +0 -43
- package/dist/lib/cloud/factory.js.map +0 -1
- package/dist/lib/cloud/registry.d.ts +0 -16
- package/dist/lib/cloud/registry.d.ts.map +0 -1
- package/dist/lib/cloud/registry.js +0 -68
- package/dist/lib/cloud/registry.js.map +0 -1
- package/dist/lib/cloud/rush.d.ts +0 -37
- package/dist/lib/cloud/rush.d.ts.map +0 -1
- package/dist/lib/cloud/rush.js +0 -230
- package/dist/lib/cloud/rush.js.map +0 -1
- package/dist/lib/cloud/rush.test.d.ts +0 -2
- package/dist/lib/cloud/rush.test.d.ts.map +0 -1
- package/dist/lib/cloud/rush.test.js +0 -63
- package/dist/lib/cloud/rush.test.js.map +0 -1
- package/dist/lib/cloud/store.d.ts +0 -23
- package/dist/lib/cloud/store.d.ts.map +0 -1
- package/dist/lib/cloud/store.js +0 -116
- package/dist/lib/cloud/store.js.map +0 -1
- package/dist/lib/cloud/stream.d.ts +0 -24
- package/dist/lib/cloud/stream.d.ts.map +0 -1
- package/dist/lib/cloud/stream.js +0 -145
- package/dist/lib/cloud/stream.js.map +0 -1
- package/dist/lib/cloud/types.d.ts +0 -109
- package/dist/lib/cloud/types.d.ts.map +0 -1
- package/dist/lib/cloud/types.js +0 -33
- package/dist/lib/cloud/types.js.map +0 -1
- package/dist/lib/cloud/types.test.d.ts +0 -2
- package/dist/lib/cloud/types.test.d.ts.map +0 -1
- package/dist/lib/cloud/types.test.js +0 -41
- package/dist/lib/cloud/types.test.js.map +0 -1
- package/dist/lib/commands.d.ts +0 -141
- package/dist/lib/commands.d.ts.map +0 -1
- package/dist/lib/commands.js +0 -514
- package/dist/lib/commands.js.map +0 -1
- package/dist/lib/convert.d.ts +0 -21
- package/dist/lib/convert.d.ts.map +0 -1
- package/dist/lib/convert.js +0 -54
- package/dist/lib/convert.js.map +0 -1
- package/dist/lib/daemon.d.ts +0 -43
- package/dist/lib/daemon.d.ts.map +0 -1
- package/dist/lib/daemon.js +0 -332
- package/dist/lib/daemon.js.map +0 -1
- package/dist/lib/drive-sync.d.ts +0 -46
- package/dist/lib/drive-sync.d.ts.map +0 -1
- package/dist/lib/drive-sync.js +0 -209
- package/dist/lib/drive-sync.js.map +0 -1
- package/dist/lib/exec.d.ts +0 -101
- package/dist/lib/exec.d.ts.map +0 -1
- package/dist/lib/exec.js +0 -450
- package/dist/lib/exec.js.map +0 -1
- package/dist/lib/factory/__tests__/config.test.d.ts +0 -2
- package/dist/lib/factory/__tests__/config.test.d.ts.map +0 -1
- package/dist/lib/factory/__tests__/config.test.js +0 -128
- package/dist/lib/factory/__tests__/config.test.js.map +0 -1
- package/dist/lib/factory/config.d.ts +0 -49
- package/dist/lib/factory/config.d.ts.map +0 -1
- package/dist/lib/factory/config.js +0 -127
- package/dist/lib/factory/config.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 -107
- package/dist/lib/factory.js.map +0 -1
- package/dist/lib/git.d.ts +0 -157
- package/dist/lib/git.d.ts.map +0 -1
- package/dist/lib/git.js +0 -647
- package/dist/lib/git.js.map +0 -1
- package/dist/lib/help.d.ts +0 -10
- package/dist/lib/help.d.ts.map +0 -1
- package/dist/lib/help.js +0 -66
- package/dist/lib/help.js.map +0 -1
- package/dist/lib/hooks.d.ts +0 -125
- package/dist/lib/hooks.d.ts.map +0 -1
- package/dist/lib/hooks.js +0 -846
- package/dist/lib/hooks.js.map +0 -1
- package/dist/lib/ledger/__tests__/local.test.d.ts +0 -2
- package/dist/lib/ledger/__tests__/local.test.d.ts.map +0 -1
- package/dist/lib/ledger/__tests__/local.test.js +0 -177
- package/dist/lib/ledger/__tests__/local.test.js.map +0 -1
- package/dist/lib/ledger/__tests__/sync.test.d.ts +0 -2
- package/dist/lib/ledger/__tests__/sync.test.d.ts.map +0 -1
- package/dist/lib/ledger/__tests__/sync.test.js +0 -117
- package/dist/lib/ledger/__tests__/sync.test.js.map +0 -1
- package/dist/lib/ledger/index.d.ts +0 -18
- package/dist/lib/ledger/index.d.ts.map +0 -1
- package/dist/lib/ledger/index.js +0 -32
- package/dist/lib/ledger/index.js.map +0 -1
- package/dist/lib/ledger/local.d.ts +0 -22
- package/dist/lib/ledger/local.d.ts.map +0 -1
- package/dist/lib/ledger/local.js +0 -333
- package/dist/lib/ledger/local.js.map +0 -1
- package/dist/lib/ledger/r2.d.ts +0 -41
- package/dist/lib/ledger/r2.d.ts.map +0 -1
- package/dist/lib/ledger/r2.js +0 -335
- package/dist/lib/ledger/r2.js.map +0 -1
- package/dist/lib/ledger/sync.d.ts +0 -33
- package/dist/lib/ledger/sync.d.ts.map +0 -1
- package/dist/lib/ledger/sync.js +0 -106
- package/dist/lib/ledger/sync.js.map +0 -1
- package/dist/lib/ledger/types.d.ts +0 -100
- package/dist/lib/ledger/types.d.ts.map +0 -1
- package/dist/lib/ledger/types.js +0 -21
- package/dist/lib/ledger/types.js.map +0 -1
- package/dist/lib/manifest.d.ts +0 -14
- package/dist/lib/manifest.d.ts.map +0 -1
- package/dist/lib/manifest.js +0 -48
- package/dist/lib/manifest.js.map +0 -1
- package/dist/lib/markdown.d.ts +0 -5
- package/dist/lib/markdown.d.ts.map +0 -1
- package/dist/lib/markdown.js +0 -17
- package/dist/lib/markdown.js.map +0 -1
- package/dist/lib/mcp.d.ts +0 -64
- package/dist/lib/mcp.d.ts.map +0 -1
- package/dist/lib/mcp.js +0 -327
- package/dist/lib/mcp.js.map +0 -1
- package/dist/lib/memory-compile.d.ts +0 -65
- package/dist/lib/memory-compile.d.ts.map +0 -1
- package/dist/lib/memory-compile.js +0 -174
- package/dist/lib/memory-compile.js.map +0 -1
- package/dist/lib/memory.d.ts +0 -64
- package/dist/lib/memory.d.ts.map +0 -1
- package/dist/lib/memory.js +0 -275
- package/dist/lib/memory.js.map +0 -1
- package/dist/lib/models.d.ts +0 -98
- package/dist/lib/models.d.ts.map +0 -1
- package/dist/lib/models.js +0 -728
- package/dist/lib/models.js.map +0 -1
- package/dist/lib/permissions.d.ts +0 -227
- package/dist/lib/permissions.d.ts.map +0 -1
- package/dist/lib/permissions.js +0 -1085
- package/dist/lib/permissions.js.map +0 -1
- package/dist/lib/picker.d.ts +0 -27
- package/dist/lib/picker.d.ts.map +0 -1
- package/dist/lib/picker.js +0 -110
- package/dist/lib/picker.js.map +0 -1
- package/dist/lib/plugins.d.ts +0 -80
- package/dist/lib/plugins.d.ts.map +0 -1
- package/dist/lib/plugins.js +0 -556
- package/dist/lib/plugins.js.map +0 -1
- package/dist/lib/profiles-keychain.d.ts +0 -11
- package/dist/lib/profiles-keychain.d.ts.map +0 -1
- package/dist/lib/profiles-keychain.js +0 -14
- package/dist/lib/profiles-keychain.js.map +0 -1
- package/dist/lib/profiles-presets.d.ts +0 -25
- package/dist/lib/profiles-presets.d.ts.map +0 -1
- package/dist/lib/profiles-presets.js +0 -104
- package/dist/lib/profiles-presets.js.map +0 -1
- package/dist/lib/profiles.d.ts +0 -70
- package/dist/lib/profiles.d.ts.map +0 -1
- package/dist/lib/profiles.js +0 -145
- package/dist/lib/profiles.js.map +0 -1
- package/dist/lib/pty-client.d.ts +0 -23
- package/dist/lib/pty-client.d.ts.map +0 -1
- package/dist/lib/pty-client.js +0 -181
- package/dist/lib/pty-client.js.map +0 -1
- package/dist/lib/pty-server.d.ts +0 -21
- package/dist/lib/pty-server.d.ts.map +0 -1
- package/dist/lib/pty-server.js +0 -427
- package/dist/lib/pty-server.js.map +0 -1
- package/dist/lib/registry.d.ts +0 -45
- package/dist/lib/registry.d.ts.map +0 -1
- package/dist/lib/registry.js +0 -220
- package/dist/lib/registry.js.map +0 -1
- package/dist/lib/resources.d.ts +0 -55
- package/dist/lib/resources.d.ts.map +0 -1
- package/dist/lib/resources.js +0 -103
- package/dist/lib/resources.js.map +0 -1
- package/dist/lib/rotate.d.ts +0 -58
- package/dist/lib/rotate.d.ts.map +0 -1
- package/dist/lib/rotate.js +0 -93
- package/dist/lib/rotate.js.map +0 -1
- package/dist/lib/routines.d.ts +0 -99
- package/dist/lib/routines.d.ts.map +0 -1
- package/dist/lib/routines.js +0 -352
- package/dist/lib/routines.js.map +0 -1
- package/dist/lib/runner.d.ts +0 -26
- package/dist/lib/runner.d.ts.map +0 -1
- package/dist/lib/runner.js +0 -325
- package/dist/lib/runner.js.map +0 -1
- package/dist/lib/sandbox.d.ts +0 -26
- package/dist/lib/sandbox.d.ts.map +0 -1
- package/dist/lib/sandbox.js +0 -218
- package/dist/lib/sandbox.js.map +0 -1
- package/dist/lib/scheduler.d.ts +0 -26
- package/dist/lib/scheduler.d.ts.map +0 -1
- package/dist/lib/scheduler.js +0 -77
- package/dist/lib/scheduler.js.map +0 -1
- package/dist/lib/secrets-bundles.d.ts +0 -38
- package/dist/lib/secrets-bundles.d.ts.map +0 -1
- package/dist/lib/secrets-bundles.js +0 -176
- package/dist/lib/secrets-bundles.js.map +0 -1
- package/dist/lib/secrets.d.ts +0 -53
- package/dist/lib/secrets.d.ts.map +0 -1
- package/dist/lib/secrets.js +0 -140
- 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/active.d.ts +0 -44
- package/dist/lib/session/active.d.ts.map +0 -1
- package/dist/lib/session/active.js +0 -379
- package/dist/lib/session/active.js.map +0 -1
- package/dist/lib/session/artifacts.d.ts +0 -15
- package/dist/lib/session/artifacts.d.ts.map +0 -1
- package/dist/lib/session/artifacts.js +0 -86
- package/dist/lib/session/artifacts.js.map +0 -1
- package/dist/lib/session/db.d.ts +0 -140
- package/dist/lib/session/db.d.ts.map +0 -1
- package/dist/lib/session/db.js +0 -599
- package/dist/lib/session/db.js.map +0 -1
- package/dist/lib/session/discover.d.ts +0 -72
- package/dist/lib/session/discover.d.ts.map +0 -1
- package/dist/lib/session/discover.js +0 -1315
- package/dist/lib/session/discover.js.map +0 -1
- package/dist/lib/session/parse.d.ts +0 -34
- package/dist/lib/session/parse.d.ts.map +0 -1
- package/dist/lib/session/parse.js +0 -663
- package/dist/lib/session/parse.js.map +0 -1
- package/dist/lib/session/prompt.d.ts +0 -13
- package/dist/lib/session/prompt.d.ts.map +0 -1
- package/dist/lib/session/prompt.js +0 -79
- 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 +0 -103
- package/dist/lib/session/render.d.ts.map +0 -1
- package/dist/lib/session/render.js +0 -798
- package/dist/lib/session/render.js.map +0 -1
- package/dist/lib/session/team-filter.d.ts +0 -35
- package/dist/lib/session/team-filter.d.ts.map +0 -1
- package/dist/lib/session/team-filter.js +0 -75
- 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 +0 -84
- package/dist/lib/session/types.d.ts.map +0 -1
- package/dist/lib/session/types.js +0 -11
- package/dist/lib/session/types.js.map +0 -1
- package/dist/lib/shims.d.ts +0 -272
- package/dist/lib/shims.d.ts.map +0 -1
- package/dist/lib/shims.js +0 -1322
- package/dist/lib/shims.js.map +0 -1
- package/dist/lib/skills.d.ts +0 -142
- package/dist/lib/skills.d.ts.map +0 -1
- package/dist/lib/skills.js +0 -791
- package/dist/lib/skills.js.map +0 -1
- package/dist/lib/state.d.ts +0 -87
- package/dist/lib/state.d.ts.map +0 -1
- package/dist/lib/state.js +0 -333
- package/dist/lib/state.js.map +0 -1
- package/dist/lib/subagents.d.ts +0 -84
- package/dist/lib/subagents.d.ts.map +0 -1
- package/dist/lib/subagents.js +0 -410
- package/dist/lib/subagents.js.map +0 -1
- package/dist/lib/teams/__tests__/oracle.test.d.ts +0 -2
- package/dist/lib/teams/__tests__/oracle.test.d.ts.map +0 -1
- package/dist/lib/teams/__tests__/oracle.test.js +0 -89
- package/dist/lib/teams/__tests__/oracle.test.js.map +0 -1
- package/dist/lib/teams/__tests__/supervisor.test.d.ts +0 -2
- package/dist/lib/teams/__tests__/supervisor.test.d.ts.map +0 -1
- package/dist/lib/teams/__tests__/supervisor.test.js +0 -179
- package/dist/lib/teams/__tests__/supervisor.test.js.map +0 -1
- package/dist/lib/teams/agents.d.ts +0 -247
- package/dist/lib/teams/agents.d.ts.map +0 -1
- package/dist/lib/teams/agents.js +0 -1244
- package/dist/lib/teams/agents.js.map +0 -1
- package/dist/lib/teams/api.d.ts +0 -91
- package/dist/lib/teams/api.d.ts.map +0 -1
- package/dist/lib/teams/api.js +0 -239
- 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 +0 -8
- package/dist/lib/teams/debug.d.ts.map +0 -1
- package/dist/lib/teams/debug.js +0 -12
- package/dist/lib/teams/debug.js.map +0 -1
- package/dist/lib/teams/file_ops.d.ts +0 -13
- package/dist/lib/teams/file_ops.d.ts.map +0 -1
- package/dist/lib/teams/file_ops.js +0 -66
- package/dist/lib/teams/file_ops.js.map +0 -1
- package/dist/lib/teams/index.d.ts +0 -16
- package/dist/lib/teams/index.d.ts.map +0 -1
- package/dist/lib/teams/index.js +0 -15
- package/dist/lib/teams/index.js.map +0 -1
- package/dist/lib/teams/oracle.d.ts +0 -20
- package/dist/lib/teams/oracle.d.ts.map +0 -1
- package/dist/lib/teams/oracle.js +0 -59
- package/dist/lib/teams/oracle.js.map +0 -1
- package/dist/lib/teams/parsers.d.ts +0 -9
- package/dist/lib/teams/parsers.d.ts.map +0 -1
- package/dist/lib/teams/parsers.js +0 -837
- package/dist/lib/teams/parsers.js.map +0 -1
- package/dist/lib/teams/persistence.d.ts +0 -43
- package/dist/lib/teams/persistence.d.ts.map +0 -1
- package/dist/lib/teams/persistence.js +0 -299
- 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 +0 -18
- package/dist/lib/teams/registry.d.ts.map +0 -1
- package/dist/lib/teams/registry.js +0 -68
- package/dist/lib/teams/registry.js.map +0 -1
- package/dist/lib/teams/summarizer.d.ts +0 -73
- package/dist/lib/teams/summarizer.d.ts.map +0 -1
- package/dist/lib/teams/summarizer.js +0 -780
- package/dist/lib/teams/summarizer.js.map +0 -1
- package/dist/lib/teams/supervisor.d.ts +0 -49
- package/dist/lib/teams/supervisor.d.ts.map +0 -1
- package/dist/lib/teams/supervisor.js +0 -74
- package/dist/lib/teams/supervisor.js.map +0 -1
- package/dist/lib/template.d.ts +0 -27
- package/dist/lib/template.d.ts.map +0 -1
- package/dist/lib/template.js +0 -60
- package/dist/lib/template.js.map +0 -1
- package/dist/lib/types.d.ts +0 -331
- package/dist/lib/types.d.ts.map +0 -1
- package/dist/lib/types.js +0 -29
- package/dist/lib/types.js.map +0 -1
- package/dist/lib/usage.d.ts +0 -105
- package/dist/lib/usage.d.ts.map +0 -1
- package/dist/lib/usage.js +0 -686
- package/dist/lib/usage.js.map +0 -1
- package/dist/lib/versions.d.ts +0 -253
- package/dist/lib/versions.d.ts.map +0 -1
- package/dist/lib/versions.js +0 -1796
- package/dist/lib/versions.js.map +0 -1
- package/scripts/rebuild-sqlite.sh +0 -46
package/dist/commands/teams.js
DELETED
|
@@ -1,1144 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import * as fs from 'fs/promises';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
import { AgentManager, checkAllClis, getAgentsDir, VALID_TASK_TYPES, } from '../lib/teams/agents.js';
|
|
5
|
-
import { resolveProvider } from '../lib/cloud/registry.js';
|
|
6
|
-
import { resolveLedger, syncTeammate } from '../lib/ledger/index.js';
|
|
7
|
-
import { maybeFileBugfix } from '../lib/teams/oracle.js';
|
|
8
|
-
import { runSupervisor } from '../lib/teams/supervisor.js';
|
|
9
|
-
import { handleSpawn, handleStatus, handleStop, handleTasks, } from '../lib/teams/api.js';
|
|
10
|
-
import { createTeam, ensureTeam, loadTeams, removeTeam, teamExists, } from '../lib/teams/registry.js';
|
|
11
|
-
import { isVersionInstalled } from '../lib/versions.js';
|
|
12
|
-
import { discoverSessions, parseTimeFilter, resolveSessionById } from '../lib/session/discover.js';
|
|
13
|
-
import { buildPreview as buildSessionPreview } from './sessions-picker.js';
|
|
14
|
-
import { parseExecEnv } from '../lib/exec.js';
|
|
15
|
-
import { teamPicker, printTeamTable } from './teams-picker.js';
|
|
16
|
-
import { itemPicker } from '../lib/picker.js';
|
|
17
|
-
import { isPromptCancelled, isInteractiveTerminal, requireDestructiveArg, requireInteractiveSelection, } from './utils.js';
|
|
18
|
-
const AGENT_NAMES = {
|
|
19
|
-
claude: 'Claude',
|
|
20
|
-
codex: 'Codex',
|
|
21
|
-
gemini: 'Gemini',
|
|
22
|
-
cursor: 'Cursor',
|
|
23
|
-
opencode: 'OpenCode',
|
|
24
|
-
};
|
|
25
|
-
const VALID_AGENTS = Object.keys(AGENT_NAMES);
|
|
26
|
-
const VALID_MODES = ['plan', 'edit', 'full'];
|
|
27
|
-
const VALID_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max', 'auto'];
|
|
28
|
-
const VALID_CLOUD_PROVIDERS = ['rush', 'codex', 'factory'];
|
|
29
|
-
// Auto-enable JSON mode when piped / not a TTY so AI agent consumers get
|
|
30
|
-
// parseable output by default.
|
|
31
|
-
function isJsonMode(opts) {
|
|
32
|
-
return Boolean(opts.json) || !process.stdout.isTTY;
|
|
33
|
-
}
|
|
34
|
-
function die(msg, code = 1) {
|
|
35
|
-
console.error(chalk.red(msg));
|
|
36
|
-
process.exit(code);
|
|
37
|
-
}
|
|
38
|
-
function statusColor(status) {
|
|
39
|
-
switch (status) {
|
|
40
|
-
case 'pending': return chalk.blue;
|
|
41
|
-
case 'running': return chalk.yellow;
|
|
42
|
-
case 'completed': return chalk.green;
|
|
43
|
-
case 'failed': return chalk.red;
|
|
44
|
-
case 'stopped': return chalk.gray;
|
|
45
|
-
default: return chalk.white;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function relTime(iso) {
|
|
49
|
-
const secs = Math.floor((Date.now() - new Date(iso).getTime()) / 1000);
|
|
50
|
-
if (secs < 10)
|
|
51
|
-
return 'just now';
|
|
52
|
-
if (secs < 60)
|
|
53
|
-
return `${secs}s ago`;
|
|
54
|
-
if (secs < 3600)
|
|
55
|
-
return `${Math.floor(secs / 60)}m ago`;
|
|
56
|
-
if (secs < 86400)
|
|
57
|
-
return `${Math.floor(secs / 3600)}h ago`;
|
|
58
|
-
return `${Math.floor(secs / 86400)}d ago`;
|
|
59
|
-
}
|
|
60
|
-
function truncate(s, n) {
|
|
61
|
-
if (s.length <= n)
|
|
62
|
-
return s;
|
|
63
|
-
return s.slice(0, n - 1) + '…';
|
|
64
|
-
}
|
|
65
|
-
function padRight(s, width) {
|
|
66
|
-
return s.length >= width ? s : s + ' '.repeat(width - s.length);
|
|
67
|
-
}
|
|
68
|
-
function fullName(type, version) {
|
|
69
|
-
const name = AGENT_NAMES[type];
|
|
70
|
-
return version ? `${name} ${version}` : name;
|
|
71
|
-
}
|
|
72
|
-
function parseTeammate(spec) {
|
|
73
|
-
const [name, version] = spec.split('@');
|
|
74
|
-
if (!VALID_AGENTS.includes(name)) {
|
|
75
|
-
die(`Unknown teammate '${name}'. Available: ${VALID_AGENTS.join(', ')}.\n` +
|
|
76
|
-
` Use the form 'claude' or 'claude@2.1.112' (see 'agents view' for installed versions).`);
|
|
77
|
-
}
|
|
78
|
-
return { agent: name, version: version || null };
|
|
79
|
-
}
|
|
80
|
-
function shortId(id) {
|
|
81
|
-
return id.slice(0, 8);
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Preamble injected into every factory worker's prompt. Tells the worker:
|
|
85
|
-
* - which team + teammate name + task-type it is
|
|
86
|
-
* - the 4 Ledger MCP tools it has access to
|
|
87
|
-
* - how to file more tasks via `agents teams add`
|
|
88
|
-
*
|
|
89
|
-
* The actual how-to lives in the /factory-worker skill; this preamble just
|
|
90
|
-
* summarises and points at it so workers get the dynamic-DAG pattern even
|
|
91
|
-
* when the spawning agent forgets to mention it.
|
|
92
|
-
*/
|
|
93
|
-
function factoryWorkerPreamble(team, name, taskType, after) {
|
|
94
|
-
const n = name ?? '<anonymous>';
|
|
95
|
-
const deps = after.length > 0 ? after.join(', ') : '(none)';
|
|
96
|
-
return [
|
|
97
|
-
`FACTORY WORKER — team="${team}", name="${n}", task_type="${taskType}", after=${deps}`,
|
|
98
|
-
`You are a teammate in a Software Factory. Read the /factory-worker skill for the full pattern.`,
|
|
99
|
-
`Key rules:`,
|
|
100
|
-
` - Other teammates may be running now. Coordinate via git, tests, and the Team Ledger (never peer-to-peer).`,
|
|
101
|
-
` - Read dependency outputs via MCP: LedgerRead(team_id="${team}", task_id=<dep-agent-id>).`,
|
|
102
|
-
` - If you discover work beyond your task, file a new teammate via Bash:`,
|
|
103
|
-
` agents teams add "${team}" claude "<ask>" --name <slug> --task-type <implement|test|review|bugfix|docs> [--after <dep>]`,
|
|
104
|
-
` A background supervisor picks up new tasks every wave.`,
|
|
105
|
-
` - Before exiting, call LedgerNote(team_id="${team}", task_id=<your-agent-id>, teammate="${n}", text="...") with what you tried, what failed, what worked.`,
|
|
106
|
-
` - test-type teammates: print "TESTS: N passed, M failed" as your last line. Failed tests auto-file a bugfix.`,
|
|
107
|
-
``,
|
|
108
|
-
`YOUR TASK:`,
|
|
109
|
-
].join('\n');
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Build an AgentManager with the Ledger sync hook pre-wired. Every `teams`
|
|
113
|
-
* command call path that touches status goes through this so completions
|
|
114
|
-
* automatically land in the Ledger.
|
|
115
|
-
*/
|
|
116
|
-
function mkManager() {
|
|
117
|
-
const mgr = new AgentManager();
|
|
118
|
-
const ledger = resolveLedger();
|
|
119
|
-
mgr.setCompletionHook(async (agent) => {
|
|
120
|
-
// 1. Push teammate outputs to the Ledger so other teammates can read
|
|
121
|
-
// them via MCP tools.
|
|
122
|
-
const snap = await agent.toSnapshot();
|
|
123
|
-
await syncTeammate(snap, ledger);
|
|
124
|
-
// 2. Run the test-oracle: failed test-type teammates auto-file a
|
|
125
|
-
// bugfix teammate.
|
|
126
|
-
await maybeFileBugfix(agent, mgr);
|
|
127
|
-
});
|
|
128
|
-
return mgr;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Register the generic cloud dispatcher — staged cloud teammates get
|
|
132
|
-
* dispatched when their --after deps resolve, using repo/branch stored on
|
|
133
|
-
* the teammate itself so we don't need the original --cloud CLI args.
|
|
134
|
-
*/
|
|
135
|
-
export function wireCloudDispatcher(mgr) {
|
|
136
|
-
mgr.setCloudDispatcher(async (a) => {
|
|
137
|
-
if (!a.cloudProvider) {
|
|
138
|
-
throw new Error(`Teammate ${a.agentId} has no cloud provider set`);
|
|
139
|
-
}
|
|
140
|
-
const prov = resolveProvider(a.cloudProvider);
|
|
141
|
-
const dispatchOpts = {
|
|
142
|
-
prompt: a.prompt,
|
|
143
|
-
agent: a.agentType,
|
|
144
|
-
repo: a.cloudRepo ?? undefined,
|
|
145
|
-
branch: a.cloudBranch ?? undefined,
|
|
146
|
-
model: a.model ?? undefined,
|
|
147
|
-
};
|
|
148
|
-
const cloudTask = await prov.dispatch(dispatchOpts);
|
|
149
|
-
return { cloudSessionId: cloudTask.id };
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
/** Single-wave start used by `teams start` without --watch. */
|
|
153
|
-
async function runOneWave(mgr, team, json) {
|
|
154
|
-
const launched = await mgr.startReady(team);
|
|
155
|
-
const all = await mgr.listByTask(team);
|
|
156
|
-
const stillPending = all.filter((a) => a.status === 'pending');
|
|
157
|
-
if (json) {
|
|
158
|
-
console.log(JSON.stringify({
|
|
159
|
-
team,
|
|
160
|
-
launched: launched.map((a) => ({ agent_id: a.agentId, name: a.name, after: a.after })),
|
|
161
|
-
still_pending: stillPending.map((a) => ({ agent_id: a.agentId, name: a.name, after: a.after })),
|
|
162
|
-
}, null, 2));
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
if (launched.length === 0 && stillPending.length === 0) {
|
|
166
|
-
console.log(chalk.gray(`No pending teammates in team ${team}.`));
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
if (launched.length > 0) {
|
|
170
|
-
console.log(chalk.green(`Launched ${launched.length} teammate(s) in team ${chalk.cyan(team)}:`));
|
|
171
|
-
for (const a of launched) {
|
|
172
|
-
const who = fullName(a.agentType, a.version);
|
|
173
|
-
const h = a.name || shortId(a.agentId);
|
|
174
|
-
console.log(` ${chalk.cyan(h)} ${who}`);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (stillPending.length > 0) {
|
|
178
|
-
console.log();
|
|
179
|
-
console.log(chalk.gray(`Still pending (${stillPending.length}):`));
|
|
180
|
-
for (const a of stillPending) {
|
|
181
|
-
const h = a.name || shortId(a.agentId);
|
|
182
|
-
console.log(` ${chalk.blue(h)} ${chalk.gray('after')} ${a.after.join(', ')}`);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
// Pick the display handle for a teammate: their given name if they have one,
|
|
187
|
-
// otherwise the 8-char UUID prefix.
|
|
188
|
-
function handle(a) {
|
|
189
|
-
return a.name || shortId(a.agent_id);
|
|
190
|
-
}
|
|
191
|
-
// Resolve a teammate reference (name / UUID / UUID prefix) by scanning every
|
|
192
|
-
// meta.json under the agents dir. Team hint narrows the search.
|
|
193
|
-
async function resolveTeammateAcrossTeams(base, ref, teamHint) {
|
|
194
|
-
let entries = [];
|
|
195
|
-
try {
|
|
196
|
-
entries = await fs.readdir(base);
|
|
197
|
-
}
|
|
198
|
-
catch {
|
|
199
|
-
return { kind: 'none' };
|
|
200
|
-
}
|
|
201
|
-
// Cheap path: exact UUID or unique UUID prefix match by directory name.
|
|
202
|
-
const byDir = entries.filter((e) => e === ref || e.startsWith(ref));
|
|
203
|
-
if (byDir.length === 1 && byDir[0] === ref) {
|
|
204
|
-
return { kind: 'ok', agentId: ref };
|
|
205
|
-
}
|
|
206
|
-
// Otherwise scan meta.json files to match on name as well, and respect the
|
|
207
|
-
// team hint if given.
|
|
208
|
-
const candidates = [];
|
|
209
|
-
for (const dir of entries) {
|
|
210
|
-
try {
|
|
211
|
-
const meta = JSON.parse(await fs.readFile(path.join(base, dir, 'meta.json'), 'utf-8'));
|
|
212
|
-
if (teamHint && meta.task_name !== teamHint)
|
|
213
|
-
continue;
|
|
214
|
-
const matchesName = meta.name && meta.name === ref;
|
|
215
|
-
const matchesPrefix = dir.startsWith(ref);
|
|
216
|
-
if (matchesName || matchesPrefix) {
|
|
217
|
-
candidates.push({
|
|
218
|
-
team: meta.task_name || '(none)',
|
|
219
|
-
agentId: dir,
|
|
220
|
-
display: meta.name || shortId(dir),
|
|
221
|
-
name: meta.name || null,
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
catch {
|
|
226
|
-
/* skip entries without readable meta.json */
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
if (candidates.length === 0)
|
|
230
|
-
return { kind: 'none' };
|
|
231
|
-
if (candidates.length === 1)
|
|
232
|
-
return { kind: 'ok', agentId: candidates[0].agentId };
|
|
233
|
-
// If multiple match but one is an exact name hit, prefer it.
|
|
234
|
-
const exactName = candidates.filter((c) => c.name === ref);
|
|
235
|
-
if (exactName.length === 1)
|
|
236
|
-
return { kind: 'ok', agentId: exactName[0].agentId };
|
|
237
|
-
return { kind: 'ambiguous', candidates };
|
|
238
|
-
}
|
|
239
|
-
// Print a teammate block using the same session preview the sessions picker
|
|
240
|
-
// uses — one canonical renderer across `agents sessions`, teams picker
|
|
241
|
-
// preview, and teams status output.
|
|
242
|
-
//
|
|
243
|
-
// Layout:
|
|
244
|
-
// alice claude COMPLETED · 5.0 minutes
|
|
245
|
-
// after: bob
|
|
246
|
-
// <buildSessionPreview output> (when the session file was found)
|
|
247
|
-
// ! reported an error (if flagged)
|
|
248
|
-
// PR: <url> (if set)
|
|
249
|
-
function printAgentDetail(a, session) {
|
|
250
|
-
const label = statusColor(a.status)(a.status.toUpperCase());
|
|
251
|
-
const who = fullName(a.agent_type, a.version);
|
|
252
|
-
const h = handle(a);
|
|
253
|
-
const secondary = a.name ? chalk.gray(`(${shortId(a.agent_id)})`) : '';
|
|
254
|
-
const duration = a.duration ? `${chalk.gray(' · ')}${chalk.white(a.duration)}` : '';
|
|
255
|
-
console.log(` ${chalk.cyan(h.padEnd(10))} ${secondary.padEnd(11)} ${who.padEnd(18)} ${label}${duration}`);
|
|
256
|
-
if (a.after && a.after.length) {
|
|
257
|
-
console.log(` ${chalk.gray('after ')} ${a.after.join(', ')}`);
|
|
258
|
-
}
|
|
259
|
-
// If the agent's internal session id differs from ours (non-Claude), show
|
|
260
|
-
// it as a hint for `agents sessions <id>`.
|
|
261
|
-
if (a.remote_session_id && a.remote_session_id !== a.agent_id) {
|
|
262
|
-
console.log(` ${chalk.gray('session ')} ${chalk.gray(a.remote_session_id)}`);
|
|
263
|
-
}
|
|
264
|
-
if (session) {
|
|
265
|
-
// Hand off to the same renderer the sessions picker uses. Indent so the
|
|
266
|
-
// block visually belongs to this teammate.
|
|
267
|
-
const preview = buildSessionPreview(session);
|
|
268
|
-
for (const line of preview.split('\n')) {
|
|
269
|
-
console.log(line ? ` ${line}` : '');
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
else {
|
|
273
|
-
// Session file not yet on disk (e.g. teammate is pending, or their
|
|
274
|
-
// agent type writes sessions elsewhere). Fall back to a compact summary
|
|
275
|
-
// derived from the live status payload.
|
|
276
|
-
const activity = [];
|
|
277
|
-
if (a.files_modified.length)
|
|
278
|
-
activity.push(`${a.files_modified.length} modified`);
|
|
279
|
-
if (a.files_created.length)
|
|
280
|
-
activity.push(`${a.files_created.length} created`);
|
|
281
|
-
if (a.files_read.length)
|
|
282
|
-
activity.push(`${a.files_read.length} read`);
|
|
283
|
-
if (a.tool_count)
|
|
284
|
-
activity.push(`${a.tool_count} tools`);
|
|
285
|
-
if (activity.length) {
|
|
286
|
-
console.log(` ${chalk.gray(activity.join(' · '))}`);
|
|
287
|
-
}
|
|
288
|
-
const lastMsg = a.last_messages[a.last_messages.length - 1];
|
|
289
|
-
if (lastMsg) {
|
|
290
|
-
const firstLine = lastMsg.split(/\r?\n/).find((l) => l.trim()) || '';
|
|
291
|
-
if (firstLine)
|
|
292
|
-
console.log(` ${chalk.gray('> ' + truncate(firstLine, 96))}`);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
if (a.has_errors)
|
|
296
|
-
console.log(` ${chalk.red('! reported an error')}`);
|
|
297
|
-
if (a.pr_url)
|
|
298
|
-
console.log(` ${chalk.gray('PR ')}${a.pr_url}`);
|
|
299
|
-
}
|
|
300
|
-
// Resolve each live teammate to its on-disk session (Claude/Codex/Gemini/
|
|
301
|
-
// OpenCode all write parseable session files). `agent_id === remote_session_id`
|
|
302
|
-
// for Claude teammates; non-Claude agents may carry their own session UUID on
|
|
303
|
-
// `remote_session_id`. We try both.
|
|
304
|
-
async function resolveTeammateSessions(agents) {
|
|
305
|
-
const map = new Map();
|
|
306
|
-
if (agents.length === 0)
|
|
307
|
-
return map;
|
|
308
|
-
// Scan every project dir — team teammates may have run from anywhere.
|
|
309
|
-
const all = await discoverSessions({ all: true, limit: 5000 });
|
|
310
|
-
for (const a of agents) {
|
|
311
|
-
const candidates = [a.remote_session_id, a.agent_id].filter(Boolean);
|
|
312
|
-
let found = null;
|
|
313
|
-
for (const id of candidates) {
|
|
314
|
-
const hits = resolveSessionById(all, id);
|
|
315
|
-
if (hits.length) {
|
|
316
|
-
found = hits[0];
|
|
317
|
-
break;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
map.set(a.agent_id, found);
|
|
321
|
-
}
|
|
322
|
-
return map;
|
|
323
|
-
}
|
|
324
|
-
// Render a team's status in the same format the `status` subcommand uses, so
|
|
325
|
-
// the interactive picker's Enter action drops the user into a familiar view.
|
|
326
|
-
async function printTeamStatus(team, result) {
|
|
327
|
-
const { summary, agents } = result;
|
|
328
|
-
console.log(chalk.bold(`Team ${chalk.cyan(team)} `) +
|
|
329
|
-
chalk.gray(summary.pending > 0
|
|
330
|
-
? `(${summary.pending} pending, ${summary.running} working, ${summary.completed} done, ${summary.failed} failed, ${summary.stopped} stopped)`
|
|
331
|
-
: `(${summary.running} working, ${summary.completed} done, ${summary.failed} failed, ${summary.stopped} stopped)`));
|
|
332
|
-
if (agents.length === 0) {
|
|
333
|
-
console.log(chalk.gray(' (no teammates yet — add one with `agents teams add`)'));
|
|
334
|
-
}
|
|
335
|
-
else {
|
|
336
|
-
const sessions = await resolveTeammateSessions(agents);
|
|
337
|
-
const width = Math.min(process.stdout.columns || 80, 80);
|
|
338
|
-
const divider = chalk.gray('┈'.repeat(width));
|
|
339
|
-
for (let i = 0; i < agents.length; i++) {
|
|
340
|
-
console.log();
|
|
341
|
-
if (i > 0) {
|
|
342
|
-
console.log(divider);
|
|
343
|
-
console.log();
|
|
344
|
-
}
|
|
345
|
-
printAgentDetail(agents[i], sessions.get(agents[i].agent_id) ?? null);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
console.log();
|
|
349
|
-
console.log(chalk.gray(`cursor: ${result.cursor}`));
|
|
350
|
-
}
|
|
351
|
-
// Classify a team into a single bucket for --status filtering.
|
|
352
|
-
// - empty: no teammates (created but nobody added yet)
|
|
353
|
-
// - waiting: only staged teammates — call `teams start` to kick them off
|
|
354
|
-
// - working: at least one teammate still running
|
|
355
|
-
// - failed: at least one teammate failed or was stopped (any failure wins —
|
|
356
|
-
// even if others finished, you want to know about the failure)
|
|
357
|
-
// - done: everyone finished successfully, no failures
|
|
358
|
-
function classifyTeamStatus(t) {
|
|
359
|
-
if (t.agent_count === 0)
|
|
360
|
-
return 'empty';
|
|
361
|
-
if (t.running > 0)
|
|
362
|
-
return 'working';
|
|
363
|
-
if (t.failed + t.stopped > 0)
|
|
364
|
-
return 'failed';
|
|
365
|
-
// At this point nobody is running/failed/stopped. If there's any pending
|
|
366
|
-
// teammate (agent_count > running+completed+failed+stopped), it's "waiting".
|
|
367
|
-
const accounted = t.running + t.completed + t.failed + t.stopped;
|
|
368
|
-
if (accounted < t.agent_count)
|
|
369
|
-
return 'waiting';
|
|
370
|
-
return 'done';
|
|
371
|
-
}
|
|
372
|
-
// Merge persistent team registry with tasks derived from live agents so empty
|
|
373
|
-
// teams (created but no teammates yet) still show up.
|
|
374
|
-
function mergeTeams(registry, tasks) {
|
|
375
|
-
const byName = new Map();
|
|
376
|
-
for (const t of tasks)
|
|
377
|
-
byName.set(t.task_name, t);
|
|
378
|
-
for (const [name, meta] of Object.entries(registry)) {
|
|
379
|
-
if (!byName.has(name)) {
|
|
380
|
-
byName.set(name, {
|
|
381
|
-
task_name: name,
|
|
382
|
-
agent_count: 0,
|
|
383
|
-
pending: 0,
|
|
384
|
-
running: 0,
|
|
385
|
-
completed: 0,
|
|
386
|
-
failed: 0,
|
|
387
|
-
stopped: 0,
|
|
388
|
-
workspace_dir: null,
|
|
389
|
-
created_at: meta.created_at,
|
|
390
|
-
modified_at: meta.created_at,
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
return Array.from(byName.values()).sort((a, b) => new Date(b.modified_at).getTime() - new Date(a.modified_at).getTime());
|
|
395
|
-
}
|
|
396
|
-
// Build the same enriched rows the `list` picker uses. Shared between `list`
|
|
397
|
-
// (interactive default) and the picker fallback for `status` / `start`.
|
|
398
|
-
async function loadTeamRows(mgr) {
|
|
399
|
-
const [tasks, registry] = await Promise.all([handleTasks(mgr, 1000), loadTeams()]);
|
|
400
|
-
const merged = mergeTeams(registry, tasks.tasks);
|
|
401
|
-
const rows = await Promise.all(merged.map(async (team) => {
|
|
402
|
-
let agents = [];
|
|
403
|
-
try {
|
|
404
|
-
const res = await handleStatus(mgr, team.task_name, 'all');
|
|
405
|
-
agents = res.agents;
|
|
406
|
-
}
|
|
407
|
-
catch {
|
|
408
|
-
// Empty teams (no live agents) throw in some code paths.
|
|
409
|
-
}
|
|
410
|
-
return { team, agents, description: registry[team.task_name]?.description };
|
|
411
|
-
}));
|
|
412
|
-
return { rows, names: merged.map((t) => t.task_name) };
|
|
413
|
-
}
|
|
414
|
-
// Picker fallback for `teams logs` when the teammate ref is omitted. Shows a
|
|
415
|
-
// flat list of every teammate with their team context; Enter picks one.
|
|
416
|
-
async function pickTeammateOr(mgr, command) {
|
|
417
|
-
if (!isInteractiveTerminal()) {
|
|
418
|
-
requireInteractiveSelection(`Picking a teammate for \`${command}\``, [
|
|
419
|
-
`${command} <teammate>`,
|
|
420
|
-
`agents teams list # to see teammates per team`,
|
|
421
|
-
]);
|
|
422
|
-
}
|
|
423
|
-
const all = await mgr.listAll();
|
|
424
|
-
if (all.length === 0) {
|
|
425
|
-
console.log(chalk.gray('No teammates on any team yet.'));
|
|
426
|
-
console.log(chalk.gray(' Add one with: agents teams add <team> <agent> <task>'));
|
|
427
|
-
return null;
|
|
428
|
-
}
|
|
429
|
-
const nameW = Math.max(8, ...all.map((a) => (a.name || shortId(a.agentId)).length));
|
|
430
|
-
const teamW = Math.max(6, ...all.map((a) => a.taskName.length));
|
|
431
|
-
try {
|
|
432
|
-
const picked = await itemPicker({
|
|
433
|
-
message: 'Select a teammate:',
|
|
434
|
-
items: all,
|
|
435
|
-
filter: (query) => {
|
|
436
|
-
const q = query.trim().toLowerCase();
|
|
437
|
-
if (!q)
|
|
438
|
-
return all;
|
|
439
|
-
return all.filter((a) => {
|
|
440
|
-
const hay = [a.name ?? '', a.agentId, a.taskName, a.agentType, a.status].join(' ').toLowerCase();
|
|
441
|
-
return hay.includes(q);
|
|
442
|
-
});
|
|
443
|
-
},
|
|
444
|
-
labelFor: (a) => {
|
|
445
|
-
const h = (a.name || shortId(a.agentId)).padEnd(nameW);
|
|
446
|
-
const team = a.taskName.padEnd(teamW);
|
|
447
|
-
const who = fullName(a.agentType, a.version);
|
|
448
|
-
return `${chalk.cyan(h)} ${chalk.gray(team)} ${who} ${statusColor(a.status)(a.status)}`;
|
|
449
|
-
},
|
|
450
|
-
shortIdFor: (a) => a.name || shortId(a.agentId),
|
|
451
|
-
pageSize: 10,
|
|
452
|
-
emptyMessage: 'No teammates match.',
|
|
453
|
-
enterHint: 'view log',
|
|
454
|
-
});
|
|
455
|
-
if (!picked)
|
|
456
|
-
return null;
|
|
457
|
-
return { agentId: picked.item.agentId, team: picked.item.taskName };
|
|
458
|
-
}
|
|
459
|
-
catch (err) {
|
|
460
|
-
if (isPromptCancelled(err))
|
|
461
|
-
return null;
|
|
462
|
-
throw err;
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
// Fallback for read-only / constructive subcommands when the user omits the
|
|
466
|
-
// team argument. In a TTY, show the picker and return the chosen team. Outside
|
|
467
|
-
// a TTY, hard-fail with a clear error so scripts surface the missing arg.
|
|
468
|
-
async function pickTeamOr(mgr, command) {
|
|
469
|
-
if (!isInteractiveTerminal()) {
|
|
470
|
-
requireInteractiveSelection(`Picking a team for \`${command}\``, [
|
|
471
|
-
`${command} <team>`,
|
|
472
|
-
`agents teams list # to see your teams`,
|
|
473
|
-
]);
|
|
474
|
-
}
|
|
475
|
-
const { rows } = await loadTeamRows(mgr);
|
|
476
|
-
if (rows.length === 0) {
|
|
477
|
-
console.log(chalk.gray("You haven't started any teams yet."));
|
|
478
|
-
console.log(chalk.gray(' Start one with: agents teams create <name>'));
|
|
479
|
-
return null;
|
|
480
|
-
}
|
|
481
|
-
try {
|
|
482
|
-
const picked = await teamPicker(rows);
|
|
483
|
-
return picked?.team ?? null;
|
|
484
|
-
}
|
|
485
|
-
catch (err) {
|
|
486
|
-
if (isPromptCancelled(err))
|
|
487
|
-
return null;
|
|
488
|
-
throw err;
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
/** Register the `agents teams` command tree (list, create, add, status, start, remove, disband, logs, doctor). */
|
|
492
|
-
export function registerTeamsCommands(program) {
|
|
493
|
-
const teams = program
|
|
494
|
-
.command('teams')
|
|
495
|
-
.description('Organize AI coding agents into teams that collaborate on a shared task')
|
|
496
|
-
.addHelpText('after', `
|
|
497
|
-
A team is a named group of agents working together on a shared task. Each teammate
|
|
498
|
-
runs in the background; you use 'status' to check in on progress. Use --after to
|
|
499
|
-
create DAG-style dependencies (one teammate waits for another to finish first).
|
|
500
|
-
|
|
501
|
-
Teammate sessions appear in 'agents sessions --teams' with a [team/name · mode] tag.
|
|
502
|
-
|
|
503
|
-
Examples:
|
|
504
|
-
# Start a new team for a feature
|
|
505
|
-
agents teams create auth-feature
|
|
506
|
-
|
|
507
|
-
# Add Alice (Claude) to work on the backend
|
|
508
|
-
agents teams add auth-feature claude "Add JWT auth middleware" --name alice
|
|
509
|
-
|
|
510
|
-
# Add Bob (Codex 0.116.0) to write tests, but wait for Alice to finish first
|
|
511
|
-
agents teams add auth-feature codex@0.116.0 "Write integration tests" --name bob --after alice
|
|
512
|
-
|
|
513
|
-
# Kick off any staged teammates whose dependencies are satisfied
|
|
514
|
-
agents teams start auth-feature
|
|
515
|
-
|
|
516
|
-
# Check in on progress (delta polling with --since for efficiency)
|
|
517
|
-
agents teams status auth-feature
|
|
518
|
-
agents teams status auth-feature --since 2026-04-19T10:30:00Z
|
|
519
|
-
|
|
520
|
-
# Let Alice go when she's done
|
|
521
|
-
agents teams remove auth-feature alice
|
|
522
|
-
|
|
523
|
-
# Wind down the whole team when work is complete
|
|
524
|
-
agents teams disband auth-feature
|
|
525
|
-
|
|
526
|
-
Short aliases:
|
|
527
|
-
teams c = create teams a = add teams s = status
|
|
528
|
-
teams rm = remove teams d = disband teams ls = list
|
|
529
|
-
|
|
530
|
-
Teammate syntax (same as the rest of agents-cli):
|
|
531
|
-
'claude' -> the default Claude version on this machine
|
|
532
|
-
'claude@2.1.112' -> a specific installed version (see 'agents view')
|
|
533
|
-
|
|
534
|
-
Name teammates with --name alice to refer to them as 'alice' instead of a UUID.
|
|
535
|
-
`);
|
|
536
|
-
// list
|
|
537
|
-
teams
|
|
538
|
-
.command('list [query]')
|
|
539
|
-
.alias('ls')
|
|
540
|
-
.description('List your teams, most recent activity first')
|
|
541
|
-
.option('-a, --agent <agent>', 'Filter: only teams with this agent (e.g. claude or claude@2.1.112)')
|
|
542
|
-
.option('--status <status>', 'Filter: only teams with this status (working, done, failed, or empty)')
|
|
543
|
-
.option('--since <time>', 'Filter: teams active after this time (e.g. "2h", "7d", or ISO date)')
|
|
544
|
-
.option('--until <time>', 'Filter: teams active before this time (e.g. "30d", or ISO date)')
|
|
545
|
-
.option('-n, --limit <n>', 'Show at most this many teams (default: 20)', '20')
|
|
546
|
-
.option('--json', 'Output machine-readable JSON instead of formatted table')
|
|
547
|
-
.action(async (query, opts) => {
|
|
548
|
-
const mgr = mkManager();
|
|
549
|
-
const limit = Math.max(1, parseInt(opts.limit, 10) || 20);
|
|
550
|
-
const [tasks, registry, everyAgent] = await Promise.all([
|
|
551
|
-
handleTasks(mgr, 1000),
|
|
552
|
-
loadTeams(),
|
|
553
|
-
mgr.listAll(),
|
|
554
|
-
]);
|
|
555
|
-
// Group agents by team so we can filter on agent-type / version.
|
|
556
|
-
const byTeam = new Map();
|
|
557
|
-
for (const a of everyAgent) {
|
|
558
|
-
const arr = byTeam.get(a.taskName) || [];
|
|
559
|
-
arr.push({ agent_type: a.agentType, version: a.version });
|
|
560
|
-
byTeam.set(a.taskName, arr);
|
|
561
|
-
}
|
|
562
|
-
let merged = mergeTeams(registry, tasks.tasks);
|
|
563
|
-
// --- query: substring match on team name ---
|
|
564
|
-
if (query) {
|
|
565
|
-
const q = query.toLowerCase();
|
|
566
|
-
merged = merged.filter((t) => t.task_name.toLowerCase().includes(q));
|
|
567
|
-
}
|
|
568
|
-
// --- --agent: filter teams containing a matching teammate ---
|
|
569
|
-
if (opts.agent) {
|
|
570
|
-
const [wantType, wantVersion] = opts.agent.split('@');
|
|
571
|
-
merged = merged.filter((t) => {
|
|
572
|
-
const teammates = byTeam.get(t.task_name) || [];
|
|
573
|
-
return teammates.some((m) => m.agent_type === wantType && (!wantVersion || m.version === wantVersion));
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
|
-
// --- --status: classify each team, filter ---
|
|
577
|
-
if (opts.status) {
|
|
578
|
-
const want = opts.status.toLowerCase();
|
|
579
|
-
const validStatuses = ['working', 'done', 'failed', 'empty'];
|
|
580
|
-
if (!validStatuses.includes(want)) {
|
|
581
|
-
die(`Invalid --status '${opts.status}'. Use one of: ${validStatuses.join(', ')}`);
|
|
582
|
-
}
|
|
583
|
-
merged = merged.filter((t) => classifyTeamStatus(t) === want);
|
|
584
|
-
}
|
|
585
|
-
// --- --since / --until: filter by activity window ---
|
|
586
|
-
if (opts.since) {
|
|
587
|
-
const cutoff = parseTimeFilter(opts.since);
|
|
588
|
-
if (!cutoff)
|
|
589
|
-
die(`Could not parse --since '${opts.since}'`);
|
|
590
|
-
merged = merged.filter((t) => new Date(t.modified_at).getTime() >= cutoff);
|
|
591
|
-
}
|
|
592
|
-
if (opts.until) {
|
|
593
|
-
const cutoff = parseTimeFilter(opts.until);
|
|
594
|
-
if (!cutoff)
|
|
595
|
-
die(`Could not parse --until '${opts.until}'`);
|
|
596
|
-
merged = merged.filter((t) => new Date(t.modified_at).getTime() <= cutoff);
|
|
597
|
-
}
|
|
598
|
-
merged = merged.slice(0, limit);
|
|
599
|
-
if (isJsonMode(opts)) {
|
|
600
|
-
console.log(JSON.stringify({ teams: merged }, null, 2));
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
if (merged.length === 0) {
|
|
604
|
-
if (query || opts.agent || opts.status || opts.since || opts.until) {
|
|
605
|
-
console.log(chalk.gray('No teams match those filters.'));
|
|
606
|
-
}
|
|
607
|
-
else {
|
|
608
|
-
console.log(chalk.gray("You haven't started any teams yet."));
|
|
609
|
-
console.log(chalk.gray(' Start one with: agents teams create <name>'));
|
|
610
|
-
}
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
// Enrich teams with teammate details for the picker's preview pane.
|
|
614
|
-
const rows = await Promise.all(merged.map(async (team) => {
|
|
615
|
-
let agents = [];
|
|
616
|
-
try {
|
|
617
|
-
const res = await handleStatus(mgr, team.task_name, 'all');
|
|
618
|
-
agents = res.agents;
|
|
619
|
-
}
|
|
620
|
-
catch {
|
|
621
|
-
// Empty teams (no live agents) throw in some code paths — preview
|
|
622
|
-
// will just show "no teammates yet".
|
|
623
|
-
}
|
|
624
|
-
return { team, agents, description: registry[team.task_name]?.description };
|
|
625
|
-
}));
|
|
626
|
-
if (isInteractiveTerminal()) {
|
|
627
|
-
try {
|
|
628
|
-
const picked = await teamPicker(rows, query);
|
|
629
|
-
if (picked) {
|
|
630
|
-
// Fall through to the status subcommand's action for the picked team.
|
|
631
|
-
const result = await handleStatus(mgr, picked.team, 'all');
|
|
632
|
-
await printTeamStatus(picked.team, result);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
catch (err) {
|
|
636
|
-
if (!isPromptCancelled(err))
|
|
637
|
-
throw err;
|
|
638
|
-
}
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
641
|
-
// Non-interactive fallback: rows flow without a header, matching the
|
|
642
|
-
// shape of `agents sessions` when piped.
|
|
643
|
-
printTeamTable(rows);
|
|
644
|
-
});
|
|
645
|
-
// create
|
|
646
|
-
teams
|
|
647
|
-
.command('create <team>')
|
|
648
|
-
.aliases(['c', 'new'])
|
|
649
|
-
.description('Start a new team. No teammates yet; add them with `teams add`.')
|
|
650
|
-
.option('-d, --description <text>', 'One-line summary of what this team is working on')
|
|
651
|
-
.option('--json', 'Output machine-readable JSON')
|
|
652
|
-
.action(async (team, opts) => {
|
|
653
|
-
try {
|
|
654
|
-
const meta = await createTeam(team, opts.description);
|
|
655
|
-
if (isJsonMode(opts)) {
|
|
656
|
-
console.log(JSON.stringify({ team, ...meta }, null, 2));
|
|
657
|
-
return;
|
|
658
|
-
}
|
|
659
|
-
console.log(chalk.green(`New team: ${chalk.cyan(team)}`));
|
|
660
|
-
if (meta.description)
|
|
661
|
-
console.log(chalk.gray(` ${meta.description}`));
|
|
662
|
-
console.log();
|
|
663
|
-
console.log(chalk.gray('Add your first teammate:'));
|
|
664
|
-
console.log(chalk.gray(` agents teams add ${team} claude "your task here"`));
|
|
665
|
-
}
|
|
666
|
-
catch (err) {
|
|
667
|
-
die(err.message);
|
|
668
|
-
}
|
|
669
|
-
});
|
|
670
|
-
// add
|
|
671
|
-
teams
|
|
672
|
-
.command('add <team> <teammate> <task>')
|
|
673
|
-
.alias('a')
|
|
674
|
-
.description("Add a teammate to work on a task. Runs in background; returns immediately. Use 'status' to check in.")
|
|
675
|
-
.option('-n, --name <name>', 'Friendly name for this teammate (e.g. alice). Required if using --after. Unique within team.')
|
|
676
|
-
.option('-m, --mode <mode>', `Permissions: plan (read-only) | edit (can write files) | full (write + skip permission prompts)`, 'edit')
|
|
677
|
-
.option('-e, --effort <effort>', `Reasoning intensity: ${VALID_EFFORTS.join('|')}`, 'medium')
|
|
678
|
-
.option('--model <model>', 'Override the effort tier and use this specific model (e.g. claude-opus-4-6)')
|
|
679
|
-
.option('--env <key=value>', 'Set an environment variable for this teammate (repeatable for multiple vars)', (val, prev) => [...prev, val], [])
|
|
680
|
-
.option('--cwd <dir>', 'Working directory for this teammate (default: current directory)')
|
|
681
|
-
.option('--after <names>', "DAG dependencies: comma-separated teammate names to wait for. Stages as PENDING; run 'teams start' to launch when ready.")
|
|
682
|
-
.option('--task-type <type>', `Factory label: ${VALID_TASK_TYPES.join('|')}. Drives planner fan-out + test-oracle bugfix loop.`)
|
|
683
|
-
.option('--cloud <provider>', `Dispatch to cloud backend instead of local CLI: ${VALID_CLOUD_PROVIDERS.join('|')}`)
|
|
684
|
-
.option('--repo <owner/repo>', 'GitHub repository (required for --cloud rush)')
|
|
685
|
-
.option('--branch <name>', 'Target git branch for cloud dispatch')
|
|
686
|
-
.option('--json', 'Output machine-readable JSON')
|
|
687
|
-
.action(async (team, teammate, task, opts) => {
|
|
688
|
-
if (!VALID_MODES.includes(opts.mode)) {
|
|
689
|
-
die(`Invalid mode '${opts.mode}'. Use one of: ${VALID_MODES.join(', ')}`);
|
|
690
|
-
}
|
|
691
|
-
if (!VALID_EFFORTS.includes(opts.effort)) {
|
|
692
|
-
die(`Invalid effort '${opts.effort}'. Use one of: ${VALID_EFFORTS.join(', ')}`);
|
|
693
|
-
}
|
|
694
|
-
let taskType = null;
|
|
695
|
-
if (opts.taskType) {
|
|
696
|
-
if (!VALID_TASK_TYPES.includes(opts.taskType)) {
|
|
697
|
-
die(`Invalid task-type '${opts.taskType}'. Use one of: ${VALID_TASK_TYPES.join(', ')}`);
|
|
698
|
-
}
|
|
699
|
-
taskType = opts.taskType;
|
|
700
|
-
}
|
|
701
|
-
let cloudProviderId = null;
|
|
702
|
-
if (opts.cloud) {
|
|
703
|
-
if (!VALID_CLOUD_PROVIDERS.includes(opts.cloud)) {
|
|
704
|
-
die(`Invalid cloud provider '${opts.cloud}'. Use one of: ${VALID_CLOUD_PROVIDERS.join(', ')}`);
|
|
705
|
-
}
|
|
706
|
-
cloudProviderId = opts.cloud;
|
|
707
|
-
if (cloudProviderId === 'rush' && !opts.repo) {
|
|
708
|
-
die(`--cloud rush requires --repo <owner/repo>`);
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
const { agent, version } = parseTeammate(teammate);
|
|
712
|
-
if (version && !isVersionInstalled(agent, version)) {
|
|
713
|
-
die(`${AGENT_NAMES[agent]} ${version} isn't installed.\n` +
|
|
714
|
-
` Install it: agents add ${agent}@${version}\n` +
|
|
715
|
-
` Or see what's installed: agents view ${agent}`);
|
|
716
|
-
}
|
|
717
|
-
if (opts.name !== undefined) {
|
|
718
|
-
if (!opts.name || !/^[A-Za-z0-9_-]+$/.test(opts.name)) {
|
|
719
|
-
die(`Invalid teammate name '${opts.name}'. Use letters, numbers, '-', or '_'.`);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
const after = opts.after
|
|
723
|
-
? opts.after.split(',').map((s) => s.trim()).filter(Boolean)
|
|
724
|
-
: [];
|
|
725
|
-
if (after.length > 0 && !opts.name) {
|
|
726
|
-
die("--after requires --name (dependencies reference teammates by name).");
|
|
727
|
-
}
|
|
728
|
-
let envOverrides;
|
|
729
|
-
try {
|
|
730
|
-
envOverrides = parseExecEnv(opts.env);
|
|
731
|
-
}
|
|
732
|
-
catch (err) {
|
|
733
|
-
die(err.message);
|
|
734
|
-
}
|
|
735
|
-
// Auto-create the team if it doesn't exist yet (friendlier UX than erroring).
|
|
736
|
-
await ensureTeam(team);
|
|
737
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
738
|
-
const mgr = mkManager();
|
|
739
|
-
// Factory teammates: prepend the worker-skill preamble to every task
|
|
740
|
-
// prompt so implementers/testers/reviewers know about the Ledger, the
|
|
741
|
-
// dynamic DAG, and the pattern for filing new tasks mid-flight. No
|
|
742
|
-
// preamble when --task-type isn't set (plain teammates work as before).
|
|
743
|
-
let effectiveTask = task;
|
|
744
|
-
if (taskType) {
|
|
745
|
-
effectiveTask = factoryWorkerPreamble(team, opts.name ?? null, taskType, after) + '\n\n' + task;
|
|
746
|
-
}
|
|
747
|
-
// Dispatcher callback: when a staged cloud teammate's deps resolve,
|
|
748
|
-
// AgentManager.startReady() invokes this to kick off the remote task.
|
|
749
|
-
if (cloudProviderId) {
|
|
750
|
-
const providerId = cloudProviderId;
|
|
751
|
-
mgr.setCloudDispatcher(async (a) => {
|
|
752
|
-
const prov = resolveProvider(providerId);
|
|
753
|
-
const dispatchOpts = {
|
|
754
|
-
prompt: a.prompt,
|
|
755
|
-
agent: a.agentType,
|
|
756
|
-
repo: opts.repo,
|
|
757
|
-
branch: opts.branch,
|
|
758
|
-
model: a.model ?? undefined,
|
|
759
|
-
};
|
|
760
|
-
const cloudTask = await prov.dispatch(dispatchOpts);
|
|
761
|
-
return { cloudSessionId: cloudTask.id };
|
|
762
|
-
});
|
|
763
|
-
}
|
|
764
|
-
let cloudSessionId = null;
|
|
765
|
-
const isStaged = after.length > 0;
|
|
766
|
-
if (cloudProviderId && !isStaged) {
|
|
767
|
-
// Ready to run now: dispatch to the cloud provider before registering
|
|
768
|
-
// the teammate so we have the remote session id up front.
|
|
769
|
-
const prov = resolveProvider(cloudProviderId);
|
|
770
|
-
const dispatchOpts = {
|
|
771
|
-
prompt: effectiveTask,
|
|
772
|
-
agent,
|
|
773
|
-
repo: opts.repo,
|
|
774
|
-
branch: opts.branch,
|
|
775
|
-
model: opts.model,
|
|
776
|
-
};
|
|
777
|
-
try {
|
|
778
|
-
const cloudTask = await prov.dispatch(dispatchOpts);
|
|
779
|
-
cloudSessionId = cloudTask.id;
|
|
780
|
-
}
|
|
781
|
-
catch (err) {
|
|
782
|
-
die(`Cloud dispatch failed: ${err.message}`);
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
try {
|
|
786
|
-
const result = await handleSpawn(mgr, team, agent, effectiveTask, cwd, opts.mode, opts.effort, null, cwd, version, opts.name ?? null, after, opts.model ?? null, envOverrides ?? null, taskType, cloudProviderId, cloudSessionId, opts.repo ?? null, opts.branch ?? null);
|
|
787
|
-
if (isJsonMode(opts)) {
|
|
788
|
-
console.log(JSON.stringify(result, null, 2));
|
|
789
|
-
return;
|
|
790
|
-
}
|
|
791
|
-
const who = fullName(agent, version);
|
|
792
|
-
const staged = result.status === 'pending';
|
|
793
|
-
const verb = staged ? 'Staged' : 'Welcomed';
|
|
794
|
-
const greeting = result.name
|
|
795
|
-
? `${verb} ${chalk.cyan(result.name)} (${who}) ${staged ? 'in' : 'to'} team ${chalk.cyan(team)}`
|
|
796
|
-
: `${verb} ${who} ${staged ? 'in' : 'to'} team ${chalk.cyan(team)}`;
|
|
797
|
-
console.log(chalk.green(greeting));
|
|
798
|
-
if (result.name) {
|
|
799
|
-
console.log(` ${chalk.gray('name ')} ${chalk.cyan(result.name)}`);
|
|
800
|
-
}
|
|
801
|
-
console.log(` ${chalk.gray('agent_id')} ${chalk.cyan(shortId(result.agent_id))} ${chalk.gray(`(${result.agent_id})`)}`);
|
|
802
|
-
console.log(` ${chalk.gray('status ')} ${statusColor(result.status)(result.status)}`);
|
|
803
|
-
console.log(` ${chalk.gray('mode ')} ${opts.mode}`);
|
|
804
|
-
console.log(` ${chalk.gray('working ')} ${cwd}`);
|
|
805
|
-
if (result.task_type) {
|
|
806
|
-
console.log(` ${chalk.gray('task ')} ${chalk.cyan(result.task_type)}`);
|
|
807
|
-
}
|
|
808
|
-
if (result.cloud_provider) {
|
|
809
|
-
console.log(` ${chalk.gray('cloud ')} ${chalk.magenta(result.cloud_provider)}${result.cloud_session_id ? chalk.gray(' — ' + result.cloud_session_id.slice(0, 12)) : ''}`);
|
|
810
|
-
}
|
|
811
|
-
if (result.after && result.after.length) {
|
|
812
|
-
console.log(` ${chalk.gray('after ')} ${result.after.join(', ')}`);
|
|
813
|
-
}
|
|
814
|
-
console.log();
|
|
815
|
-
if (staged) {
|
|
816
|
-
console.log(chalk.gray(`Start the ready teammates: agents teams start ${team}`));
|
|
817
|
-
}
|
|
818
|
-
else {
|
|
819
|
-
console.log(chalk.gray(`Check in later: agents teams status ${team}`));
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
catch (err) {
|
|
823
|
-
die(`Could not add ${fullName(agent, version)} to ${team}: ${err.message}`);
|
|
824
|
-
}
|
|
825
|
-
});
|
|
826
|
-
// status
|
|
827
|
-
teams
|
|
828
|
-
.command('status [team]')
|
|
829
|
-
.aliases(['s', 'st', 'check'])
|
|
830
|
-
.description("Check in on a team: who's working, what files they touched, recent commands, last output. Pass --since for efficient delta polling.")
|
|
831
|
-
.option('-f, --filter <state>', 'Show only teammates in this state: working, completed, failed, stopped, or all (default: all)', 'all')
|
|
832
|
-
.option('-s, --since <iso>', 'Cursor from a previous status call; only show updates after this timestamp (enables efficient polling)')
|
|
833
|
-
.option('--agent-id <id>', 'Show only this one teammate (by UUID or UUID prefix)')
|
|
834
|
-
.option('--json', 'Output machine-readable JSON')
|
|
835
|
-
.action(async (team, opts) => {
|
|
836
|
-
// Map friendly 'working' → internal 'running' for filter.
|
|
837
|
-
const filter = opts.filter === 'working' ? 'running' : opts.filter;
|
|
838
|
-
const mgr = mkManager();
|
|
839
|
-
// No team given → drop into the picker (TTY) or fail clearly (script).
|
|
840
|
-
if (!team) {
|
|
841
|
-
const picked = await pickTeamOr(mgr, 'agents teams status');
|
|
842
|
-
if (!picked)
|
|
843
|
-
return;
|
|
844
|
-
team = picked;
|
|
845
|
-
}
|
|
846
|
-
try {
|
|
847
|
-
const result = await handleStatus(mgr, team, filter, opts.since);
|
|
848
|
-
const agents = opts.agentId
|
|
849
|
-
? result.agents.filter((a) => a.agent_id.startsWith(opts.agentId))
|
|
850
|
-
: result.agents;
|
|
851
|
-
if (isJsonMode(opts)) {
|
|
852
|
-
console.log(JSON.stringify({ ...result, agents }, null, 2));
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
const exists = await teamExists(team);
|
|
856
|
-
if (!exists && result.agents.length === 0) {
|
|
857
|
-
console.log(chalk.yellow(`No team called '${team}'. Create it with: agents teams create ${team}`));
|
|
858
|
-
return;
|
|
859
|
-
}
|
|
860
|
-
await printTeamStatus(team, { ...result, agents });
|
|
861
|
-
}
|
|
862
|
-
catch (err) {
|
|
863
|
-
die(`Could not check on team ${team}: ${err.message}`);
|
|
864
|
-
}
|
|
865
|
-
});
|
|
866
|
-
// active — list every live teammate across every team, grouped by team.
|
|
867
|
-
teams
|
|
868
|
-
.command('active')
|
|
869
|
-
.description('List every teammate running right now, across all teams (PID-alive check).')
|
|
870
|
-
.option('--json', 'Output machine-readable JSON')
|
|
871
|
-
.action(async (opts) => {
|
|
872
|
-
const mgr = mkManager();
|
|
873
|
-
const running = await mgr.listRunning();
|
|
874
|
-
if (isJsonMode(opts)) {
|
|
875
|
-
console.log(JSON.stringify({ agents: running.map((a) => ({
|
|
876
|
-
agent_id: a.agentId,
|
|
877
|
-
team: a.taskName,
|
|
878
|
-
name: a.name,
|
|
879
|
-
agent_type: a.agentType,
|
|
880
|
-
pid: a.pid,
|
|
881
|
-
started_at: a.startedAt.toISOString(),
|
|
882
|
-
cwd: a.cwd,
|
|
883
|
-
version: a.version,
|
|
884
|
-
})) }, null, 2));
|
|
885
|
-
return;
|
|
886
|
-
}
|
|
887
|
-
if (running.length === 0) {
|
|
888
|
-
console.log(chalk.gray('No teammates are running right now.'));
|
|
889
|
-
return;
|
|
890
|
-
}
|
|
891
|
-
const byTeam = new Map();
|
|
892
|
-
for (const a of running) {
|
|
893
|
-
const arr = byTeam.get(a.taskName) || [];
|
|
894
|
-
arr.push(a);
|
|
895
|
-
byTeam.set(a.taskName, arr);
|
|
896
|
-
}
|
|
897
|
-
for (const [team, agents] of byTeam) {
|
|
898
|
-
console.log(chalk.bold(`Team ${chalk.cyan(team)} ${chalk.gray(`(${agents.length} working)`)}`));
|
|
899
|
-
for (const a of agents) {
|
|
900
|
-
const ident = a.name || shortId(a.agentId);
|
|
901
|
-
const pidStr = a.pid ? chalk.yellow(`pid ${a.pid}`) : chalk.gray('pid ?');
|
|
902
|
-
const started = chalk.gray(relTime(a.startedAt.toISOString()));
|
|
903
|
-
console.log(` ${chalk.magenta(padRight(fullName(a.agentType, a.version), 18))} ${chalk.white(padRight(ident, 20))} ${pidStr} ${started}`);
|
|
904
|
-
}
|
|
905
|
-
console.log();
|
|
906
|
-
}
|
|
907
|
-
console.log(chalk.gray(`${running.length} teammate${running.length === 1 ? '' : 's'} running. See 'agents sessions --active' for the full cross-context view.`));
|
|
908
|
-
});
|
|
909
|
-
// start — fire any staged teammates whose --after deps have all completed
|
|
910
|
-
teams
|
|
911
|
-
.command('start [team]')
|
|
912
|
-
.description('Launch any pending teammates whose --after dependencies are satisfied. Use --watch to keep draining the DAG as teammates finish and as new tasks are added mid-flight.')
|
|
913
|
-
.option('--json', 'Output machine-readable JSON')
|
|
914
|
-
.option('--watch', 'Keep running: poll every --interval seconds, fire new waves, exit when the DAG drains.')
|
|
915
|
-
.option('--interval <seconds>', 'Seconds between waves in --watch mode (default 8)', '8')
|
|
916
|
-
.option('--max-waves <n>', 'Safety cap on waves in --watch mode (default 1000)', '1000')
|
|
917
|
-
.action(async (team, opts) => {
|
|
918
|
-
const mgr = mkManager();
|
|
919
|
-
wireCloudDispatcher(mgr);
|
|
920
|
-
if (!team) {
|
|
921
|
-
const picked = await pickTeamOr(mgr, 'agents teams start');
|
|
922
|
-
if (!picked)
|
|
923
|
-
return;
|
|
924
|
-
team = picked;
|
|
925
|
-
}
|
|
926
|
-
if (!opts.watch) {
|
|
927
|
-
await runOneWave(mgr, team, Boolean(opts.json));
|
|
928
|
-
return;
|
|
929
|
-
}
|
|
930
|
-
const intervalMs = Math.max(1000, Number.parseInt(opts.interval, 10) * 1000 || 8000);
|
|
931
|
-
const maxWaves = Math.max(1, Number.parseInt(opts.maxWaves, 10) || 1000);
|
|
932
|
-
const json = isJsonMode(opts);
|
|
933
|
-
const result = await runSupervisor(mgr, {
|
|
934
|
-
team,
|
|
935
|
-
intervalMs,
|
|
936
|
-
maxWaves,
|
|
937
|
-
onWave: (s) => {
|
|
938
|
-
const ts = s.timestamp.slice(11, 19);
|
|
939
|
-
if (json) {
|
|
940
|
-
console.log(JSON.stringify({
|
|
941
|
-
wave: s.wave, ts, team: s.team, launched: s.launched.length,
|
|
942
|
-
pending: s.pending, running: s.running, completed: s.completed, failed: s.failed,
|
|
943
|
-
}));
|
|
944
|
-
return;
|
|
945
|
-
}
|
|
946
|
-
console.log(`[${ts}] wave ${s.wave} team ${chalk.cyan(s.team)} ` +
|
|
947
|
-
`launched=${chalk.green(s.launched.length)} running=${chalk.yellow(s.running)} ` +
|
|
948
|
-
`pending=${chalk.blue(s.pending)} done=${chalk.green(s.completed)} ` +
|
|
949
|
-
`failed=${s.failed > 0 ? chalk.red(s.failed) : '0'}`);
|
|
950
|
-
},
|
|
951
|
-
});
|
|
952
|
-
const elapsed = Math.floor(result.elapsed_ms / 1000);
|
|
953
|
-
if (result.stoppedBy === 'drained') {
|
|
954
|
-
console.log(chalk.green(`Factory drained in ${elapsed}s (${result.waves} waves).`));
|
|
955
|
-
}
|
|
956
|
-
else if (result.stoppedBy === 'max-waves') {
|
|
957
|
-
console.error(chalk.yellow(`Hit --max-waves=${maxWaves}; stopping. Re-run to continue.`));
|
|
958
|
-
}
|
|
959
|
-
else if (result.stoppedBy === 'signal') {
|
|
960
|
-
console.error(chalk.yellow(`Stopped by signal after ${result.waves} waves.`));
|
|
961
|
-
}
|
|
962
|
-
});
|
|
963
|
-
// remove
|
|
964
|
-
teams
|
|
965
|
-
.command('remove [team] [teammate]')
|
|
966
|
-
.alias('rm')
|
|
967
|
-
.description("Remove a teammate from the team. Stops them cleanly if still working. Accepts name, UUID, or UUID prefix.")
|
|
968
|
-
.option('--keep-logs', 'Keep their log files on disk (default: delete them)')
|
|
969
|
-
.option('--json', 'Output machine-readable JSON')
|
|
970
|
-
.action(async (team, ref, opts) => {
|
|
971
|
-
const mgr = mkManager();
|
|
972
|
-
if (!team) {
|
|
973
|
-
const { names } = await loadTeamRows(mgr);
|
|
974
|
-
requireDestructiveArg({
|
|
975
|
-
argName: 'team',
|
|
976
|
-
command: 'agents teams remove',
|
|
977
|
-
itemNoun: 'team',
|
|
978
|
-
available: names,
|
|
979
|
-
emptyHint: "You don't have any teams yet.",
|
|
980
|
-
});
|
|
981
|
-
}
|
|
982
|
-
if (!ref) {
|
|
983
|
-
const roster = await mgr.listByTask(team);
|
|
984
|
-
requireDestructiveArg({
|
|
985
|
-
argName: 'teammate',
|
|
986
|
-
command: `agents teams remove ${team}`,
|
|
987
|
-
itemNoun: 'teammate',
|
|
988
|
-
available: roster.map((a) => a.name || shortId(a.agentId)),
|
|
989
|
-
emptyHint: `Team ${team} has no teammates.`,
|
|
990
|
-
});
|
|
991
|
-
}
|
|
992
|
-
const lookup = await mgr.resolveAgentIdInTask(team, ref);
|
|
993
|
-
if (lookup.kind === 'none') {
|
|
994
|
-
die(`No teammate matching '${ref}' in team ${team}`, 2);
|
|
995
|
-
}
|
|
996
|
-
if (lookup.kind === 'ambiguous') {
|
|
997
|
-
const shorts = lookup.matches.map(shortId).join(', ');
|
|
998
|
-
die(`'${ref}' matches multiple teammates: ${shorts}. Use more characters or a name.`, 2);
|
|
999
|
-
}
|
|
1000
|
-
const agentId = lookup.agentId;
|
|
1001
|
-
// Look up the display handle (name if they had one) before we tear down.
|
|
1002
|
-
const agent = await mgr.get(agentId);
|
|
1003
|
-
const display = agent?.name || shortId(agentId);
|
|
1004
|
-
const stopRes = await handleStop(mgr, team, agentId);
|
|
1005
|
-
if ('error' in stopRes)
|
|
1006
|
-
die(stopRes.error);
|
|
1007
|
-
if (!opts.keepLogs && stopRes.not_found.length === 0) {
|
|
1008
|
-
try {
|
|
1009
|
-
const dir = path.join(await getAgentsDir(), agentId);
|
|
1010
|
-
await fs.rm(dir, { recursive: true, force: true });
|
|
1011
|
-
}
|
|
1012
|
-
catch {
|
|
1013
|
-
// best-effort cleanup
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
if (isJsonMode(opts)) {
|
|
1017
|
-
console.log(JSON.stringify({ team, agent_id: agentId, name: agent?.name ?? null, result: stopRes }, null, 2));
|
|
1018
|
-
return;
|
|
1019
|
-
}
|
|
1020
|
-
if (stopRes.stopped.length) {
|
|
1021
|
-
console.log(chalk.green(`${display} has left team ${chalk.cyan(team)} (was working, now stopped).`));
|
|
1022
|
-
}
|
|
1023
|
-
else {
|
|
1024
|
-
console.log(chalk.green(`${display} has left team ${chalk.cyan(team)}.`));
|
|
1025
|
-
}
|
|
1026
|
-
});
|
|
1027
|
-
// disband
|
|
1028
|
-
teams
|
|
1029
|
-
.command('disband [team]')
|
|
1030
|
-
.alias('d')
|
|
1031
|
-
.description('Disband the team. Stops all teammates cleanly and removes the team registry entry.')
|
|
1032
|
-
.option('--keep-logs', 'Keep all teammate logs on disk (default: delete them)')
|
|
1033
|
-
.option('--json', 'Output machine-readable JSON')
|
|
1034
|
-
.action(async (team, opts) => {
|
|
1035
|
-
const mgr = mkManager();
|
|
1036
|
-
if (!team) {
|
|
1037
|
-
const { names } = await loadTeamRows(mgr);
|
|
1038
|
-
requireDestructiveArg({
|
|
1039
|
-
argName: 'team',
|
|
1040
|
-
command: 'agents teams disband',
|
|
1041
|
-
itemNoun: 'team',
|
|
1042
|
-
available: names,
|
|
1043
|
-
emptyHint: "You don't have any teams to disband.",
|
|
1044
|
-
});
|
|
1045
|
-
}
|
|
1046
|
-
const stopRes = await handleStop(mgr, team);
|
|
1047
|
-
if ('error' in stopRes)
|
|
1048
|
-
die(stopRes.error);
|
|
1049
|
-
const status = await handleStatus(mgr, team, 'all');
|
|
1050
|
-
const removedIds = [];
|
|
1051
|
-
if (!opts.keepLogs) {
|
|
1052
|
-
const base = await getAgentsDir();
|
|
1053
|
-
for (const a of status.agents) {
|
|
1054
|
-
try {
|
|
1055
|
-
await fs.rm(path.join(base, a.agent_id), { recursive: true, force: true });
|
|
1056
|
-
removedIds.push(a.agent_id);
|
|
1057
|
-
}
|
|
1058
|
-
catch { /* best-effort */ }
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
const existed = await removeTeam(team);
|
|
1062
|
-
if (isJsonMode(opts)) {
|
|
1063
|
-
console.log(JSON.stringify({ team, existed, stopped: stopRes.stopped, removed_members: removedIds }, null, 2));
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
if (!existed && stopRes.stopped.length === 0 && status.agents.length === 0) {
|
|
1067
|
-
die(`No team called '${team}'`, 2);
|
|
1068
|
-
}
|
|
1069
|
-
console.log(chalk.green(`Team ${chalk.cyan(team)} disbanded.`));
|
|
1070
|
-
if (stopRes.stopped.length)
|
|
1071
|
-
console.log(chalk.gray(` Stopped ${stopRes.stopped.length} working teammate(s).`));
|
|
1072
|
-
if (removedIds.length)
|
|
1073
|
-
console.log(chalk.gray(` Cleared ${removedIds.length} teammate log(s).`));
|
|
1074
|
-
});
|
|
1075
|
-
// logs
|
|
1076
|
-
teams
|
|
1077
|
-
.command('logs [teammate]')
|
|
1078
|
-
.alias('log')
|
|
1079
|
-
.description("Read a teammate's raw log output. Accepts name, UUID, or UUID prefix.")
|
|
1080
|
-
.option('-n, --tail <n>', 'Show only the last N lines instead of the full log')
|
|
1081
|
-
.option('--team <team>', 'Disambiguate when the same name appears in multiple teams')
|
|
1082
|
-
.action(async (ref, opts) => {
|
|
1083
|
-
const base = await getAgentsDir();
|
|
1084
|
-
// No teammate → picker in TTY, hard fail outside.
|
|
1085
|
-
let agentId;
|
|
1086
|
-
if (!ref) {
|
|
1087
|
-
const mgr = mkManager();
|
|
1088
|
-
const picked = await pickTeammateOr(mgr, 'agents teams logs');
|
|
1089
|
-
if (!picked)
|
|
1090
|
-
return;
|
|
1091
|
-
agentId = picked.agentId;
|
|
1092
|
-
}
|
|
1093
|
-
else {
|
|
1094
|
-
const resolved = await resolveTeammateAcrossTeams(base, ref, opts.team);
|
|
1095
|
-
if (resolved.kind === 'none') {
|
|
1096
|
-
die(`No notes on record for teammate '${ref}'`, 2);
|
|
1097
|
-
}
|
|
1098
|
-
if (resolved.kind === 'ambiguous') {
|
|
1099
|
-
const hints = resolved.candidates.map((c) => `${c.team}/${c.display}`).join(', ');
|
|
1100
|
-
die(`'${ref}' matches multiple teammates: ${hints}.\n` +
|
|
1101
|
-
` Narrow it with --team <team>, or pass a UUID prefix.`, 2);
|
|
1102
|
-
}
|
|
1103
|
-
agentId = resolved.agentId;
|
|
1104
|
-
}
|
|
1105
|
-
const logPath = path.join(base, agentId, 'stdout.log');
|
|
1106
|
-
try {
|
|
1107
|
-
const content = await fs.readFile(logPath, 'utf-8');
|
|
1108
|
-
if (!opts.tail) {
|
|
1109
|
-
process.stdout.write(content);
|
|
1110
|
-
return;
|
|
1111
|
-
}
|
|
1112
|
-
const n = Math.max(1, parseInt(opts.tail, 10) || 50);
|
|
1113
|
-
const lines = content.split('\n');
|
|
1114
|
-
process.stdout.write(lines.slice(-n).join('\n'));
|
|
1115
|
-
}
|
|
1116
|
-
catch {
|
|
1117
|
-
die(`No notes on record for teammate '${ref ?? agentId}' (looked in ${logPath})`, 2);
|
|
1118
|
-
}
|
|
1119
|
-
});
|
|
1120
|
-
// doctor
|
|
1121
|
-
teams
|
|
1122
|
-
.command('doctor')
|
|
1123
|
-
.alias('dr')
|
|
1124
|
-
.description('Check which agents are installed and available to join a team. Verifies CLI paths.')
|
|
1125
|
-
.option('--json', 'Output machine-readable JSON')
|
|
1126
|
-
.action(async (opts) => {
|
|
1127
|
-
const info = checkAllClis();
|
|
1128
|
-
if (isJsonMode(opts)) {
|
|
1129
|
-
console.log(JSON.stringify(info, null, 2));
|
|
1130
|
-
return;
|
|
1131
|
-
}
|
|
1132
|
-
console.log(chalk.bold('Who can join a team:'));
|
|
1133
|
-
for (const [name, entry] of Object.entries(info)) {
|
|
1134
|
-
const pretty = AGENT_NAMES[name] || name;
|
|
1135
|
-
if (entry.installed) {
|
|
1136
|
-
console.log(` ${chalk.green('ready')} ${pretty.padEnd(10)} ${chalk.gray(entry.path || '')}`);
|
|
1137
|
-
}
|
|
1138
|
-
else {
|
|
1139
|
-
console.log(` ${chalk.red('no ')} ${pretty.padEnd(10)} ${chalk.gray(entry.error || 'not installed')}`);
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
});
|
|
1143
|
-
}
|
|
1144
|
-
//# sourceMappingURL=teams.js.map
|