@apralabs/apra-fleet 0.2.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/LICENSE +182 -0
- package/README.md +324 -0
- package/dist/cli/auth.d.ts +2 -0
- package/dist/cli/auth.d.ts.map +1 -0
- package/dist/cli/auth.js +210 -0
- package/dist/cli/auth.js.map +1 -0
- package/dist/cli/config.d.ts +30 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +157 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/install.d.ts +37 -0
- package/dist/cli/install.d.ts.map +1 -0
- package/dist/cli/install.js +630 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/secret.d.ts +2 -0
- package/dist/cli/secret.d.ts.map +1 -0
- package/dist/cli/secret.js +366 -0
- package/dist/cli/secret.js.map +1 -0
- package/dist/cli/uninstall.d.ts +2 -0
- package/dist/cli/uninstall.d.ts.map +1 -0
- package/dist/cli/uninstall.js +312 -0
- package/dist/cli/uninstall.js.map +1 -0
- package/dist/cli/update.d.ts +2 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +105 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/delivery-mode.d.ts +19 -0
- package/dist/delivery-mode.d.ts.map +1 -0
- package/dist/delivery-mode.js +26 -0
- package/dist/delivery-mode.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +272 -0
- package/dist/index.js.map +1 -0
- package/dist/onboarding/text.d.ts +83 -0
- package/dist/onboarding/text.d.ts.map +1 -0
- package/dist/onboarding/text.js +126 -0
- package/dist/onboarding/text.js.map +1 -0
- package/dist/os/index.d.ts +9 -0
- package/dist/os/index.d.ts.map +1 -0
- package/dist/os/index.js +16 -0
- package/dist/os/index.js.map +1 -0
- package/dist/os/linux.d.ts +50 -0
- package/dist/os/linux.d.ts.map +1 -0
- package/dist/os/linux.js +244 -0
- package/dist/os/linux.js.map +1 -0
- package/dist/os/macos.d.ts +12 -0
- package/dist/os/macos.d.ts.map +1 -0
- package/dist/os/macos.js +41 -0
- package/dist/os/macos.js.map +1 -0
- package/dist/os/os-commands.d.ts +47 -0
- package/dist/os/os-commands.d.ts.map +1 -0
- package/dist/os/os-commands.js +3 -0
- package/dist/os/os-commands.js.map +1 -0
- package/dist/os/windows-wrapper.d.ts +6 -0
- package/dist/os/windows-wrapper.d.ts.map +1 -0
- package/dist/os/windows-wrapper.js +9 -0
- package/dist/os/windows-wrapper.js.map +1 -0
- package/dist/os/windows.d.ts +44 -0
- package/dist/os/windows.d.ts.map +1 -0
- package/dist/os/windows.js +269 -0
- package/dist/os/windows.js.map +1 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +4 -0
- package/dist/paths.js.map +1 -0
- package/dist/providers/agy.d.ts +41 -0
- package/dist/providers/agy.d.ts.map +1 -0
- package/dist/providers/agy.js +208 -0
- package/dist/providers/agy.js.map +1 -0
- package/dist/providers/claude.d.ts +40 -0
- package/dist/providers/claude.d.ts.map +1 -0
- package/dist/providers/claude.js +178 -0
- package/dist/providers/claude.js.map +1 -0
- package/dist/providers/codex.d.ts +44 -0
- package/dist/providers/codex.d.ts.map +1 -0
- package/dist/providers/codex.js +173 -0
- package/dist/providers/codex.js.map +1 -0
- package/dist/providers/copilot.d.ts +40 -0
- package/dist/providers/copilot.d.ts.map +1 -0
- package/dist/providers/copilot.js +172 -0
- package/dist/providers/copilot.js.map +1 -0
- package/dist/providers/gemini.d.ts +41 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +192 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +10 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +27 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/provider.d.ts +85 -0
- package/dist/providers/provider.d.ts.map +1 -0
- package/dist/providers/provider.js +21 -0
- package/dist/providers/provider.js.map +1 -0
- package/dist/services/auth-socket.d.ts +87 -0
- package/dist/services/auth-socket.d.ts.map +1 -0
- package/dist/services/auth-socket.js +684 -0
- package/dist/services/auth-socket.js.map +1 -0
- package/dist/services/auth-web.d.ts +31 -0
- package/dist/services/auth-web.d.ts.map +1 -0
- package/dist/services/auth-web.js +202 -0
- package/dist/services/auth-web.js.map +1 -0
- package/dist/services/cloud/activity.d.ts +16 -0
- package/dist/services/cloud/activity.d.ts.map +1 -0
- package/dist/services/cloud/activity.js +61 -0
- package/dist/services/cloud/activity.js.map +1 -0
- package/dist/services/cloud/aws.d.ts +24 -0
- package/dist/services/cloud/aws.d.ts.map +1 -0
- package/dist/services/cloud/aws.js +114 -0
- package/dist/services/cloud/aws.js.map +1 -0
- package/dist/services/cloud/cost.d.ts +46 -0
- package/dist/services/cloud/cost.d.ts.map +1 -0
- package/dist/services/cloud/cost.js +161 -0
- package/dist/services/cloud/cost.js.map +1 -0
- package/dist/services/cloud/idle-manager.d.ts +20 -0
- package/dist/services/cloud/idle-manager.d.ts.map +1 -0
- package/dist/services/cloud/idle-manager.js +103 -0
- package/dist/services/cloud/idle-manager.js.map +1 -0
- package/dist/services/cloud/lifecycle.d.ts +14 -0
- package/dist/services/cloud/lifecycle.d.ts.map +1 -0
- package/dist/services/cloud/lifecycle.js +128 -0
- package/dist/services/cloud/lifecycle.js.map +1 -0
- package/dist/services/cloud/task-wrapper.d.ts +30 -0
- package/dist/services/cloud/task-wrapper.d.ts.map +1 -0
- package/dist/services/cloud/task-wrapper.js +116 -0
- package/dist/services/cloud/task-wrapper.js.map +1 -0
- package/dist/services/cloud/types.d.ts +26 -0
- package/dist/services/cloud/types.d.ts.map +1 -0
- package/dist/services/cloud/types.js +2 -0
- package/dist/services/cloud/types.js.map +1 -0
- package/dist/services/credential-cleanup.d.ts +4 -0
- package/dist/services/credential-cleanup.d.ts.map +1 -0
- package/dist/services/credential-cleanup.js +61 -0
- package/dist/services/credential-cleanup.js.map +1 -0
- package/dist/services/credential-store.d.ts +56 -0
- package/dist/services/credential-store.d.ts.map +1 -0
- package/dist/services/credential-store.js +280 -0
- package/dist/services/credential-store.js.map +1 -0
- package/dist/services/file-transfer.d.ts +22 -0
- package/dist/services/file-transfer.d.ts.map +1 -0
- package/dist/services/file-transfer.js +14 -0
- package/dist/services/file-transfer.js.map +1 -0
- package/dist/services/git-config.d.ts +6 -0
- package/dist/services/git-config.d.ts.map +1 -0
- package/dist/services/git-config.js +31 -0
- package/dist/services/git-config.js.map +1 -0
- package/dist/services/github-app.d.ts +30 -0
- package/dist/services/github-app.d.ts.map +1 -0
- package/dist/services/github-app.js +96 -0
- package/dist/services/github-app.js.map +1 -0
- package/dist/services/icons.d.ts +16 -0
- package/dist/services/icons.d.ts.map +1 -0
- package/dist/services/icons.js +67 -0
- package/dist/services/icons.js.map +1 -0
- package/dist/services/known-hosts.d.ts +23 -0
- package/dist/services/known-hosts.d.ts.map +1 -0
- package/dist/services/known-hosts.js +86 -0
- package/dist/services/known-hosts.js.map +1 -0
- package/dist/services/onboarding.d.ts +68 -0
- package/dist/services/onboarding.d.ts.map +1 -0
- package/dist/services/onboarding.js +205 -0
- package/dist/services/onboarding.js.map +1 -0
- package/dist/services/registry.d.ts +16 -0
- package/dist/services/registry.d.ts.map +1 -0
- package/dist/services/registry.js +156 -0
- package/dist/services/registry.js.map +1 -0
- package/dist/services/sftp.d.ts +16 -0
- package/dist/services/sftp.d.ts.map +1 -0
- package/dist/services/sftp.js +104 -0
- package/dist/services/sftp.js.map +1 -0
- package/dist/services/ssh.d.ts +29 -0
- package/dist/services/ssh.d.ts.map +1 -0
- package/dist/services/ssh.js +297 -0
- package/dist/services/ssh.js.map +1 -0
- package/dist/services/stall/find-log-file.d.ts +2 -0
- package/dist/services/stall/find-log-file.d.ts.map +1 -0
- package/dist/services/stall/find-log-file.js +153 -0
- package/dist/services/stall/find-log-file.js.map +1 -0
- package/dist/services/stall/index.d.ts +4 -0
- package/dist/services/stall/index.d.ts.map +1 -0
- package/dist/services/stall/index.js +4 -0
- package/dist/services/stall/index.js.map +1 -0
- package/dist/services/stall/log-path-resolver.d.ts +4 -0
- package/dist/services/stall/log-path-resolver.d.ts.map +1 -0
- package/dist/services/stall/log-path-resolver.js +32 -0
- package/dist/services/stall/log-path-resolver.js.map +1 -0
- package/dist/services/stall/log-path-resolver.test.d.ts +2 -0
- package/dist/services/stall/log-path-resolver.test.d.ts.map +1 -0
- package/dist/services/stall/log-path-resolver.test.js +76 -0
- package/dist/services/stall/log-path-resolver.test.js.map +1 -0
- package/dist/services/stall/read-log-tail.d.ts +6 -0
- package/dist/services/stall/read-log-tail.d.ts.map +1 -0
- package/dist/services/stall/read-log-tail.js +44 -0
- package/dist/services/stall/read-log-tail.js.map +1 -0
- package/dist/services/stall/stall-detector.d.ts +25 -0
- package/dist/services/stall/stall-detector.d.ts.map +1 -0
- package/dist/services/stall/stall-detector.js +153 -0
- package/dist/services/stall/stall-detector.js.map +1 -0
- package/dist/services/stall/stall-poller.d.ts +6 -0
- package/dist/services/stall/stall-poller.d.ts.map +1 -0
- package/dist/services/stall/stall-poller.js +75 -0
- package/dist/services/stall/stall-poller.js.map +1 -0
- package/dist/services/stall/time-utils.d.ts +4 -0
- package/dist/services/stall/time-utils.d.ts.map +1 -0
- package/dist/services/stall/time-utils.js +22 -0
- package/dist/services/stall/time-utils.js.map +1 -0
- package/dist/services/statusline.d.ts +10 -0
- package/dist/services/statusline.d.ts.map +1 -0
- package/dist/services/statusline.js +84 -0
- package/dist/services/statusline.js.map +1 -0
- package/dist/services/strategy.d.ts +16 -0
- package/dist/services/strategy.d.ts.map +1 -0
- package/dist/services/strategy.js +241 -0
- package/dist/services/strategy.js.map +1 -0
- package/dist/services/task-cleanup.d.ts +3 -0
- package/dist/services/task-cleanup.d.ts.map +1 -0
- package/dist/services/task-cleanup.js +81 -0
- package/dist/services/task-cleanup.js.map +1 -0
- package/dist/services/update-check.d.ts +15 -0
- package/dist/services/update-check.d.ts.map +1 -0
- package/dist/services/update-check.js +67 -0
- package/dist/services/update-check.js.map +1 -0
- package/dist/services/user-config.d.ts +12 -0
- package/dist/services/user-config.d.ts.map +1 -0
- package/dist/services/user-config.js +73 -0
- package/dist/services/user-config.js.map +1 -0
- package/dist/services/vcs/azure-devops.d.ts +7 -0
- package/dist/services/vcs/azure-devops.d.ts.map +1 -0
- package/dist/services/vcs/azure-devops.js +38 -0
- package/dist/services/vcs/azure-devops.js.map +1 -0
- package/dist/services/vcs/bitbucket.d.ts +6 -0
- package/dist/services/vcs/bitbucket.d.ts.map +1 -0
- package/dist/services/vcs/bitbucket.js +31 -0
- package/dist/services/vcs/bitbucket.js.map +1 -0
- package/dist/services/vcs/constants.d.ts +2 -0
- package/dist/services/vcs/constants.d.ts.map +1 -0
- package/dist/services/vcs/constants.js +6 -0
- package/dist/services/vcs/constants.js.map +1 -0
- package/dist/services/vcs/github.d.ts +6 -0
- package/dist/services/vcs/github.d.ts.map +1 -0
- package/dist/services/vcs/github.js +81 -0
- package/dist/services/vcs/github.js.map +1 -0
- package/dist/services/vcs/types.d.ts +52 -0
- package/dist/services/vcs/types.d.ts.map +1 -0
- package/dist/services/vcs/types.js +8 -0
- package/dist/services/vcs/types.js.map +1 -0
- package/dist/smoke-test.d.ts +10 -0
- package/dist/smoke-test.d.ts.map +1 -0
- package/dist/smoke-test.js +102 -0
- package/dist/smoke-test.js.map +1 -0
- package/dist/tools/check-status.d.ts +11 -0
- package/dist/tools/check-status.d.ts.map +1 -0
- package/dist/tools/check-status.js +247 -0
- package/dist/tools/check-status.js.map +1 -0
- package/dist/tools/cloud-control.d.ts +17 -0
- package/dist/tools/cloud-control.d.ts.map +1 -0
- package/dist/tools/cloud-control.js +102 -0
- package/dist/tools/cloud-control.js.map +1 -0
- package/dist/tools/compose-permissions.d.ts +26 -0
- package/dist/tools/compose-permissions.d.ts.map +1 -0
- package/dist/tools/compose-permissions.js +217 -0
- package/dist/tools/compose-permissions.js.map +1 -0
- package/dist/tools/credential-store-delete.d.ts +11 -0
- package/dist/tools/credential-store-delete.d.ts.map +1 -0
- package/dist/tools/credential-store-delete.js +15 -0
- package/dist/tools/credential-store-delete.js.map +1 -0
- package/dist/tools/credential-store-list.d.ts +4 -0
- package/dist/tools/credential-store-list.d.ts.map +1 -0
- package/dist/tools/credential-store-list.js +30 -0
- package/dist/tools/credential-store-list.js.map +1 -0
- package/dist/tools/credential-store-set.d.ts +26 -0
- package/dist/tools/credential-store-set.d.ts.map +1 -0
- package/dist/tools/credential-store-set.js +28 -0
- package/dist/tools/credential-store-set.js.map +1 -0
- package/dist/tools/credential-store-update.d.ts +20 -0
- package/dist/tools/credential-store-update.d.ts.map +1 -0
- package/dist/tools/credential-store-update.js +38 -0
- package/dist/tools/credential-store-update.js.map +1 -0
- package/dist/tools/execute-command.d.ts +33 -0
- package/dist/tools/execute-command.d.ts.map +1 -0
- package/dist/tools/execute-command.js +231 -0
- package/dist/tools/execute-command.js.map +1 -0
- package/dist/tools/execute-prompt.d.ts +36 -0
- package/dist/tools/execute-prompt.d.ts.map +1 -0
- package/dist/tools/execute-prompt.js +310 -0
- package/dist/tools/execute-prompt.js.map +1 -0
- package/dist/tools/list-members.d.ts +11 -0
- package/dist/tools/list-members.d.ts.map +1 -0
- package/dist/tools/list-members.js +108 -0
- package/dist/tools/list-members.js.map +1 -0
- package/dist/tools/member-detail.d.ts +17 -0
- package/dist/tools/member-detail.d.ts.map +1 -0
- package/dist/tools/member-detail.js +263 -0
- package/dist/tools/member-detail.js.map +1 -0
- package/dist/tools/monitor-task.d.ts +20 -0
- package/dist/tools/monitor-task.d.ts.map +1 -0
- package/dist/tools/monitor-task.js +89 -0
- package/dist/tools/monitor-task.js.map +1 -0
- package/dist/tools/provision-auth.d.ts +17 -0
- package/dist/tools/provision-auth.d.ts.map +1 -0
- package/dist/tools/provision-auth.js +256 -0
- package/dist/tools/provision-auth.js.map +1 -0
- package/dist/tools/provision-vcs-auth.d.ts +50 -0
- package/dist/tools/provision-vcs-auth.d.ts.map +1 -0
- package/dist/tools/provision-vcs-auth.js +187 -0
- package/dist/tools/provision-vcs-auth.js.map +1 -0
- package/dist/tools/receive-files.d.ts +20 -0
- package/dist/tools/receive-files.d.ts.map +1 -0
- package/dist/tools/receive-files.js +82 -0
- package/dist/tools/receive-files.js.map +1 -0
- package/dist/tools/register-member.d.ts +74 -0
- package/dist/tools/register-member.d.ts.map +1 -0
- package/dist/tools/register-member.js +310 -0
- package/dist/tools/register-member.js.map +1 -0
- package/dist/tools/remove-member.d.ts +17 -0
- package/dist/tools/remove-member.d.ts.map +1 -0
- package/dist/tools/remove-member.js +126 -0
- package/dist/tools/remove-member.js.map +1 -0
- package/dist/tools/revoke-vcs-auth.d.ts +23 -0
- package/dist/tools/revoke-vcs-auth.d.ts.map +1 -0
- package/dist/tools/revoke-vcs-auth.js +55 -0
- package/dist/tools/revoke-vcs-auth.js.map +1 -0
- package/dist/tools/send-files.d.ts +20 -0
- package/dist/tools/send-files.d.ts.map +1 -0
- package/dist/tools/send-files.js +103 -0
- package/dist/tools/send-files.js.map +1 -0
- package/dist/tools/setup-git-app.d.ts +17 -0
- package/dist/tools/setup-git-app.d.ts.map +1 -0
- package/dist/tools/setup-git-app.js +89 -0
- package/dist/tools/setup-git-app.js.map +1 -0
- package/dist/tools/setup-ssh-key.d.ts +14 -0
- package/dist/tools/setup-ssh-key.d.ts.map +1 -0
- package/dist/tools/setup-ssh-key.js +119 -0
- package/dist/tools/setup-ssh-key.js.map +1 -0
- package/dist/tools/shutdown-server.d.ts +4 -0
- package/dist/tools/shutdown-server.d.ts.map +1 -0
- package/dist/tools/shutdown-server.js +9 -0
- package/dist/tools/shutdown-server.js.map +1 -0
- package/dist/tools/stop-prompt.d.ts +14 -0
- package/dist/tools/stop-prompt.d.ts.map +1 -0
- package/dist/tools/stop-prompt.js +44 -0
- package/dist/tools/stop-prompt.js.map +1 -0
- package/dist/tools/update-agent-cli.d.ts +17 -0
- package/dist/tools/update-agent-cli.d.ts.map +1 -0
- package/dist/tools/update-agent-cli.js +110 -0
- package/dist/tools/update-agent-cli.js.map +1 -0
- package/dist/tools/update-member.d.ts +77 -0
- package/dist/tools/update-member.d.ts.map +1 -0
- package/dist/tools/update-member.js +202 -0
- package/dist/tools/update-member.js.map +1 -0
- package/dist/tools/version.d.ts +4 -0
- package/dist/tools/version.d.ts.map +1 -0
- package/dist/tools/version.js +7 -0
- package/dist/tools/version.js.map +1 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/agent-helpers.d.ts +41 -0
- package/dist/utils/agent-helpers.d.ts.map +1 -0
- package/dist/utils/agent-helpers.js +84 -0
- package/dist/utils/agent-helpers.js.map +1 -0
- package/dist/utils/ansi.d.ts +6 -0
- package/dist/utils/ansi.d.ts.map +1 -0
- package/dist/utils/ansi.js +20 -0
- package/dist/utils/ansi.js.map +1 -0
- package/dist/utils/auth-env.d.ts +8 -0
- package/dist/utils/auth-env.d.ts.map +1 -0
- package/dist/utils/auth-env.js +30 -0
- package/dist/utils/auth-env.js.map +1 -0
- package/dist/utils/collect-secret.d.ts +2 -0
- package/dist/utils/collect-secret.d.ts.map +1 -0
- package/dist/utils/collect-secret.js +80 -0
- package/dist/utils/collect-secret.js.map +1 -0
- package/dist/utils/credential-validation.d.ts +13 -0
- package/dist/utils/credential-validation.d.ts.map +1 -0
- package/dist/utils/credential-validation.js +35 -0
- package/dist/utils/credential-validation.js.map +1 -0
- package/dist/utils/crypto.d.ts +3 -0
- package/dist/utils/crypto.d.ts.map +1 -0
- package/dist/utils/crypto.js +61 -0
- package/dist/utils/crypto.js.map +1 -0
- package/dist/utils/deep-merge.d.ts +3 -0
- package/dist/utils/deep-merge.d.ts.map +1 -0
- package/dist/utils/deep-merge.js +23 -0
- package/dist/utils/deep-merge.js.map +1 -0
- package/dist/utils/file-permissions.d.ts +8 -0
- package/dist/utils/file-permissions.d.ts.map +1 -0
- package/dist/utils/file-permissions.js +13 -0
- package/dist/utils/file-permissions.js.map +1 -0
- package/dist/utils/gpu-parser.d.ts +6 -0
- package/dist/utils/gpu-parser.d.ts.map +1 -0
- package/dist/utils/gpu-parser.js +15 -0
- package/dist/utils/gpu-parser.js.map +1 -0
- package/dist/utils/log-helpers.d.ts +29 -0
- package/dist/utils/log-helpers.d.ts.map +1 -0
- package/dist/utils/log-helpers.js +128 -0
- package/dist/utils/log-helpers.js.map +1 -0
- package/dist/utils/oob-timeout.d.ts +2 -0
- package/dist/utils/oob-timeout.d.ts.map +1 -0
- package/dist/utils/oob-timeout.js +2 -0
- package/dist/utils/oob-timeout.js.map +1 -0
- package/dist/utils/pid-helpers.d.ts +11 -0
- package/dist/utils/pid-helpers.d.ts.map +1 -0
- package/dist/utils/pid-helpers.js +21 -0
- package/dist/utils/pid-helpers.js.map +1 -0
- package/dist/utils/platform.d.ts +13 -0
- package/dist/utils/platform.d.ts.map +1 -0
- package/dist/utils/platform.js +60 -0
- package/dist/utils/platform.js.map +1 -0
- package/dist/utils/prompt-errors.d.ts +5 -0
- package/dist/utils/prompt-errors.d.ts.map +1 -0
- package/dist/utils/prompt-errors.js +15 -0
- package/dist/utils/prompt-errors.js.map +1 -0
- package/dist/utils/resolve-member.d.ts +18 -0
- package/dist/utils/resolve-member.d.ts.map +1 -0
- package/dist/utils/resolve-member.js +23 -0
- package/dist/utils/resolve-member.js.map +1 -0
- package/dist/utils/secure-input.d.ts +6 -0
- package/dist/utils/secure-input.d.ts.map +1 -0
- package/dist/utils/secure-input.js +60 -0
- package/dist/utils/secure-input.js.map +1 -0
- package/dist/utils/shell-escape.d.ts +43 -0
- package/dist/utils/shell-escape.d.ts.map +1 -0
- package/dist/utils/shell-escape.js +67 -0
- package/dist/utils/shell-escape.js.map +1 -0
- package/dist/utils/ssh-error-messages.d.ts +5 -0
- package/dist/utils/ssh-error-messages.d.ts.map +1 -0
- package/dist/utils/ssh-error-messages.js +20 -0
- package/dist/utils/ssh-error-messages.js.map +1 -0
- package/dist/version.d.ts +18 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +101 -0
- package/dist/version.js.map +1 -0
- package/hooks/hooks-config.json +15 -0
- package/hooks/post-register-member.sh +10 -0
- package/package.json +82 -0
- package/scripts/agy-settings-merge.js +27 -0
- package/scripts/agy-transcript-reader.js +62 -0
- package/scripts/fleet-statusline.sh +43 -0
- package/skills/fleet/SKILL.md +262 -0
- package/skills/fleet/auth-azdevops.md +72 -0
- package/skills/fleet/auth-bitbucket.md +65 -0
- package/skills/fleet/auth-github.md +86 -0
- package/skills/fleet/beads.md +90 -0
- package/skills/fleet/onboarding.md +92 -0
- package/skills/fleet/permissions.md +23 -0
- package/skills/fleet/profiles/base-dev.json +18 -0
- package/skills/fleet/profiles/base-reviewer.json +14 -0
- package/skills/fleet/profiles/cpp.json +4 -0
- package/skills/fleet/profiles/dotnet.json +4 -0
- package/skills/fleet/profiles/go.json +4 -0
- package/skills/fleet/profiles/jvm.json +4 -0
- package/skills/fleet/profiles/node.json +4 -0
- package/skills/fleet/profiles/python.json +4 -0
- package/skills/fleet/profiles/rust.json +4 -0
- package/skills/fleet/profiles/tpl-permissions.json +5 -0
- package/skills/fleet/skill-matrix.md +34 -0
- package/skills/fleet/troubleshooting.md +13 -0
- package/skills/pm/SKILL.md +110 -0
- package/skills/pm/backlog-item.md +65 -0
- package/skills/pm/beads.md +192 -0
- package/skills/pm/cleanup.md +15 -0
- package/skills/pm/context-file.md +40 -0
- package/skills/pm/doer-reviewer.md +123 -0
- package/skills/pm/init.md +25 -0
- package/skills/pm/multi-pair-sprint.md +64 -0
- package/skills/pm/plan-prompt.md +94 -0
- package/skills/pm/simple-sprint.md +42 -0
- package/skills/pm/single-pair-sprint.md +178 -0
- package/skills/pm/tpl-deploy.md +24 -0
- package/skills/pm/tpl-design.md +29 -0
- package/skills/pm/tpl-doer.md +43 -0
- package/skills/pm/tpl-plan.md +72 -0
- package/skills/pm/tpl-pm.md +2 -0
- package/skills/pm/tpl-progress.json +28 -0
- package/skills/pm/tpl-projects.md +4 -0
- package/skills/pm/tpl-requirements.md +21 -0
- package/skills/pm/tpl-reviewer-plan.md +53 -0
- package/skills/pm/tpl-reviewer.md +72 -0
- package/skills/pm/tpl-status.md +29 -0
- package/version.json +3 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getAllAgents } from '../services/registry.js';
|
|
3
|
+
import { getStrategy } from '../services/strategy.js';
|
|
4
|
+
import { getOsCommands } from '../os/index.js';
|
|
5
|
+
import { getProvider } from '../providers/index.js';
|
|
6
|
+
import { formatAgentHost, getAgentOS } from '../utils/agent-helpers.js';
|
|
7
|
+
import { serverVersion } from '../version.js';
|
|
8
|
+
import { DEFAULT_ICON } from '../services/icons.js';
|
|
9
|
+
import { writeStatusline } from '../services/statusline.js';
|
|
10
|
+
import { getStallDetector } from '../services/stall/index.js';
|
|
11
|
+
import { fmtElapsed } from '../services/stall/time-utils.js';
|
|
12
|
+
import { awsProvider } from '../services/cloud/aws.js';
|
|
13
|
+
import { estimateCost, hourlyRate, formatUptimeDuration, uptimeHoursFromLaunch, costWarning } from '../services/cloud/cost.js';
|
|
14
|
+
import { parseGpuUtilization } from '../utils/gpu-parser.js';
|
|
15
|
+
import { getUpdateNotice } from '../services/update-check.js';
|
|
16
|
+
import { getActiveLogFile } from '../utils/log-helpers.js';
|
|
17
|
+
export const fleetStatusSchema = z.object({
|
|
18
|
+
format: z.enum(['compact', 'json']).default('compact').describe('Output format: "compact" (default, few lines) or "json" (structured data for detailed rendering)'),
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Build the busy label for a member confirmed running via SSH process check.
|
|
22
|
+
* Uses the stall detector entry to show elapsed time since last log activity,
|
|
23
|
+
* or 'unknown' if the stall threshold has already fired.
|
|
24
|
+
*/
|
|
25
|
+
function busyLabel(agentId) {
|
|
26
|
+
const entry = getStallDetector().getEntry(agentId);
|
|
27
|
+
if (!entry)
|
|
28
|
+
return 'BUSY';
|
|
29
|
+
if (entry.stallReported)
|
|
30
|
+
return 'unknown';
|
|
31
|
+
if (!entry.provisional) {
|
|
32
|
+
return `BUSY(${fmtElapsed(Date.now() - entry.lastActivityAt)})`;
|
|
33
|
+
}
|
|
34
|
+
return 'BUSY';
|
|
35
|
+
}
|
|
36
|
+
function formatTimeAgo(isoDate) {
|
|
37
|
+
if (!isoDate)
|
|
38
|
+
return 'never';
|
|
39
|
+
const diff = Date.now() - new Date(isoDate).getTime();
|
|
40
|
+
const minutes = Math.floor(diff / 60000);
|
|
41
|
+
if (minutes < 1)
|
|
42
|
+
return 'just now';
|
|
43
|
+
if (minutes < 60)
|
|
44
|
+
return `${minutes}m ago`;
|
|
45
|
+
const hours = Math.floor(minutes / 60);
|
|
46
|
+
if (hours < 24)
|
|
47
|
+
return `${hours}h ago`;
|
|
48
|
+
const days = Math.floor(hours / 24);
|
|
49
|
+
return `${days}d ago`;
|
|
50
|
+
}
|
|
51
|
+
async function checkAgent(agent) {
|
|
52
|
+
const hostLabel = formatAgentHost(agent);
|
|
53
|
+
const row = {
|
|
54
|
+
icon: agent.icon ?? DEFAULT_ICON,
|
|
55
|
+
name: agent.friendlyName,
|
|
56
|
+
host: hostLabel,
|
|
57
|
+
status: 'OFFLINE',
|
|
58
|
+
busy: '-',
|
|
59
|
+
session: agent.sessionId ? agent.sessionId.substring(0, 8) + '...' : '(none)',
|
|
60
|
+
lastActivity: formatTimeAgo(agent.lastUsed),
|
|
61
|
+
lastLlmActivityAt: agent.lastLlmActivityAt,
|
|
62
|
+
branch: agent.lastBranch,
|
|
63
|
+
tokenUsage: agent.tokenUsage,
|
|
64
|
+
};
|
|
65
|
+
const strategy = getStrategy(agent);
|
|
66
|
+
// For cloud members: fetch instance details in parallel with SSH connection test
|
|
67
|
+
if (agent.cloud) {
|
|
68
|
+
const [detailsResult, connResult] = await Promise.allSettled([
|
|
69
|
+
awsProvider.getInstanceDetails(agent.cloud),
|
|
70
|
+
Promise.race([
|
|
71
|
+
strategy.testConnection(),
|
|
72
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 10000)),
|
|
73
|
+
]),
|
|
74
|
+
]);
|
|
75
|
+
// Process cloud details
|
|
76
|
+
if (detailsResult.status === 'fulfilled') {
|
|
77
|
+
const details = detailsResult.value;
|
|
78
|
+
row.cloudInfo = {
|
|
79
|
+
state: details.state,
|
|
80
|
+
instanceType: details.instanceType,
|
|
81
|
+
launchTime: details.launchTime,
|
|
82
|
+
};
|
|
83
|
+
// If cloud is not running/pending, mark as off and skip SSH entirely
|
|
84
|
+
if (details.state !== 'running' && details.state !== 'pending') {
|
|
85
|
+
row.status = 'OFFLINE';
|
|
86
|
+
row.busy = 'OFF(cloud)';
|
|
87
|
+
return row;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Process SSH connection result
|
|
91
|
+
if (connResult.status === 'fulfilled' && connResult.value.ok) {
|
|
92
|
+
row.status = 'online';
|
|
93
|
+
const cmds = getOsCommands(getAgentOS(agent));
|
|
94
|
+
const provider = getProvider(agent.llmProvider);
|
|
95
|
+
// Run fleet process check and GPU utilization in parallel
|
|
96
|
+
const [busyResult, gpuResult] = await Promise.allSettled([
|
|
97
|
+
strategy.execCommand(cmds.fleetProcessCheck(agent.workFolder, agent.sessionId, provider.processName), 10000),
|
|
98
|
+
strategy.execCommand(cmds.gpuUtilization(), 10000),
|
|
99
|
+
]);
|
|
100
|
+
if (busyResult.status === 'fulfilled') {
|
|
101
|
+
const output = busyResult.value.stdout.trim().toLowerCase();
|
|
102
|
+
if (output.includes('fleet-busy')) {
|
|
103
|
+
row.busy = busyLabel(agent.id);
|
|
104
|
+
}
|
|
105
|
+
else if (output.includes('other-busy')) {
|
|
106
|
+
row.busy = 'idle*';
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
row.busy = 'idle';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
row.busy = 'unknown';
|
|
114
|
+
}
|
|
115
|
+
if (gpuResult.status === 'fulfilled' && row.cloudInfo) {
|
|
116
|
+
const gpuNum = parseGpuUtilization(gpuResult.value.stdout);
|
|
117
|
+
if (gpuNum !== undefined) {
|
|
118
|
+
row.cloudInfo.gpuUtil = gpuNum;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return row;
|
|
123
|
+
}
|
|
124
|
+
// Non-cloud members: original logic
|
|
125
|
+
try {
|
|
126
|
+
const conn = await Promise.race([
|
|
127
|
+
strategy.testConnection(),
|
|
128
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 10000)),
|
|
129
|
+
]);
|
|
130
|
+
if (conn.ok) {
|
|
131
|
+
row.status = 'online';
|
|
132
|
+
try {
|
|
133
|
+
const cmds = getOsCommands(getAgentOS(agent));
|
|
134
|
+
const provider = getProvider(agent.llmProvider);
|
|
135
|
+
const busyCheck = await strategy.execCommand(cmds.fleetProcessCheck(agent.workFolder, agent.sessionId, provider.processName), 10000);
|
|
136
|
+
const output = busyCheck.stdout.trim().toLowerCase();
|
|
137
|
+
if (output.includes('fleet-busy')) {
|
|
138
|
+
row.busy = 'BUSY';
|
|
139
|
+
}
|
|
140
|
+
else if (output.includes('other-busy')) {
|
|
141
|
+
row.busy = 'idle*';
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
row.busy = 'idle';
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
row.busy = 'unknown';
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
row.status = 'OFFLINE';
|
|
154
|
+
}
|
|
155
|
+
return row;
|
|
156
|
+
}
|
|
157
|
+
export async function fleetStatus(input) {
|
|
158
|
+
const format = input?.format ?? 'compact';
|
|
159
|
+
const agents = getAllAgents();
|
|
160
|
+
if (agents.length === 0) {
|
|
161
|
+
return 'No members registered. Use register_member to add one.';
|
|
162
|
+
}
|
|
163
|
+
// Query all members in parallel
|
|
164
|
+
const results = await Promise.allSettled(agents.map(a => checkAgent(a)));
|
|
165
|
+
const rows = results.map((r, i) => {
|
|
166
|
+
if (r.status === 'fulfilled')
|
|
167
|
+
return r.value;
|
|
168
|
+
const hostLabel = formatAgentHost(agents[i]);
|
|
169
|
+
return {
|
|
170
|
+
icon: agents[i].icon ?? DEFAULT_ICON,
|
|
171
|
+
name: agents[i].friendlyName,
|
|
172
|
+
host: hostLabel,
|
|
173
|
+
status: 'OFFLINE',
|
|
174
|
+
busy: '-',
|
|
175
|
+
session: agents[i].sessionId ? agents[i].sessionId.substring(0, 8) + '...' : '(none)',
|
|
176
|
+
lastActivity: formatTimeAgo(agents[i].lastUsed),
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
// Count cloud-stopped members as offline for the summary
|
|
180
|
+
const online = rows.filter(r => r.status === 'online').length;
|
|
181
|
+
// Update statusline with connectivity state from this check.
|
|
182
|
+
// For busy/unknown members the stall detector owns the statusline (it writes
|
|
183
|
+
// busy(mm:ss) or unknown on each 30s poll); we only override offline and idle
|
|
184
|
+
// so we don't clobber the richer stall-detector state.
|
|
185
|
+
const statusOverrides = new Map();
|
|
186
|
+
for (let i = 0; i < agents.length; i++) {
|
|
187
|
+
const row = rows[i];
|
|
188
|
+
if (row.status === 'OFFLINE') {
|
|
189
|
+
statusOverrides.set(agents[i].id, 'offline');
|
|
190
|
+
}
|
|
191
|
+
else if (row.busy === 'idle' || row.busy === 'idle*') {
|
|
192
|
+
// SSH confirmed no fleet process running — clear any stale busy/unknown
|
|
193
|
+
statusOverrides.set(agents[i].id, 'idle');
|
|
194
|
+
}
|
|
195
|
+
// BUSY / BUSY(mm:ss) / unknown (stall fired but process still alive):
|
|
196
|
+
// stall detector already wrote the authoritative value — don't override
|
|
197
|
+
}
|
|
198
|
+
writeStatusline(statusOverrides);
|
|
199
|
+
const updateNotice = getUpdateNotice();
|
|
200
|
+
const logFile = getActiveLogFile();
|
|
201
|
+
if (format === 'json') {
|
|
202
|
+
const payload = {
|
|
203
|
+
version: serverVersion,
|
|
204
|
+
summary: { total: rows.length, online, offline: rows.length - online },
|
|
205
|
+
members: rows,
|
|
206
|
+
};
|
|
207
|
+
if (logFile)
|
|
208
|
+
payload.logFile = logFile;
|
|
209
|
+
if (updateNotice) {
|
|
210
|
+
const m = updateNotice.match(/apra-fleet (v[\d.]+) is available \(installed: (v[\d.]+)/);
|
|
211
|
+
if (m)
|
|
212
|
+
payload.updateAvailable = { latest: m[1], installed: m[2] };
|
|
213
|
+
}
|
|
214
|
+
return JSON.stringify(payload);
|
|
215
|
+
}
|
|
216
|
+
// Compact: 1 summary line + 1 line per member, multiple fields per line
|
|
217
|
+
let t = updateNotice ? `${updateNotice}\n` : '';
|
|
218
|
+
t += `Fleet ${serverVersion}: ${online}/${rows.length} online | `;
|
|
219
|
+
if (logFile)
|
|
220
|
+
t += `log=${logFile} | `;
|
|
221
|
+
t += rows.map(r => {
|
|
222
|
+
const st = r.status === 'online' ? r.busy : (r.busy === 'OFF(cloud)' ? 'OFF(cloud)' : 'OFF');
|
|
223
|
+
return `${r.icon} ${r.name}(${st})`;
|
|
224
|
+
}).join(', ');
|
|
225
|
+
t += '\n';
|
|
226
|
+
for (const r of rows) {
|
|
227
|
+
const branchStr = r.branch ? ` | branch=${r.branch}` : '';
|
|
228
|
+
const tokenStr = (r.tokenUsage && (r.tokenUsage.input > 0 || r.tokenUsage.output > 0))
|
|
229
|
+
? ` | tokens=in:${r.tokenUsage.input} out:${r.tokenUsage.output}` : '';
|
|
230
|
+
let line = ` ${r.icon} ${r.name}: ${r.host} | session=${r.session} | ${r.lastActivity}${branchStr}${tokenStr}`;
|
|
231
|
+
if (r.cloudInfo) {
|
|
232
|
+
const ci = r.cloudInfo;
|
|
233
|
+
const uptimeHrs = uptimeHoursFromLaunch(ci.launchTime);
|
|
234
|
+
const uptime = ci.launchTime ? formatUptimeDuration(uptimeHrs) : '-';
|
|
235
|
+
const cost = estimateCost(ci.instanceType, uptimeHrs);
|
|
236
|
+
const rate = hourlyRate(ci.instanceType);
|
|
237
|
+
const warn = costWarning(ci.instanceType, uptimeHrs);
|
|
238
|
+
const gpuStr = ci.gpuUtil !== undefined ? ` GPU:${ci.gpuUtil}%` : '';
|
|
239
|
+
const typeStr = ci.instanceType ? ` ${ci.instanceType}` : '';
|
|
240
|
+
const warnStr = warn ? ' ⚠' : '';
|
|
241
|
+
line += ` | [cloud:${ci.state}${typeStr} ${uptime} ${cost} @${rate}${gpuStr}${warnStr}]`;
|
|
242
|
+
}
|
|
243
|
+
t += line + '\n';
|
|
244
|
+
}
|
|
245
|
+
return t;
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=check-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-status.js","sourceRoot":"","sources":["../../src/tools/check-status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const cloudControlSchema: z.ZodObject<{
|
|
3
|
+
action: z.ZodEnum<["start", "stop", "status"]>;
|
|
4
|
+
member_id: z.ZodOptional<z.ZodString>;
|
|
5
|
+
member_name: z.ZodOptional<z.ZodString>;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
action: "start" | "status" | "stop";
|
|
8
|
+
member_id?: string | undefined;
|
|
9
|
+
member_name?: string | undefined;
|
|
10
|
+
}, {
|
|
11
|
+
action: "start" | "status" | "stop";
|
|
12
|
+
member_id?: string | undefined;
|
|
13
|
+
member_name?: string | undefined;
|
|
14
|
+
}>;
|
|
15
|
+
export type CloudControlInput = z.infer<typeof cloudControlSchema>;
|
|
16
|
+
export declare function cloudControl(input: CloudControlInput): Promise<string>;
|
|
17
|
+
//# sourceMappingURL=cloud-control.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-control.d.ts","sourceRoot":"","sources":["../../src/tools/cloud-control.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;EAK7B,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEnE,wBAAsB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0F5E"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getAgentOS } from '../utils/agent-helpers.js';
|
|
3
|
+
import { memberIdentifier, resolveMember } from '../utils/resolve-member.js';
|
|
4
|
+
import { getStrategy } from '../services/strategy.js';
|
|
5
|
+
import { getOsCommands } from '../os/index.js';
|
|
6
|
+
import { ensureCloudReady } from '../services/cloud/lifecycle.js';
|
|
7
|
+
import { awsProvider } from '../services/cloud/aws.js';
|
|
8
|
+
import { estimateCost, hourlyRate, formatUptimeDuration, uptimeHoursFromLaunch, costWarning, uptimeWarning } from '../services/cloud/cost.js';
|
|
9
|
+
import { parseGpuUtilization } from '../utils/gpu-parser.js';
|
|
10
|
+
export const cloudControlSchema = z.object({
|
|
11
|
+
...memberIdentifier,
|
|
12
|
+
action: z.enum(['start', 'stop', 'status']).describe('start: auto-start and wait for SSH ready | stop: stop instance immediately | status: return current state'),
|
|
13
|
+
});
|
|
14
|
+
export async function cloudControl(input) {
|
|
15
|
+
const agentOrError = resolveMember(input.member_id, input.member_name);
|
|
16
|
+
if (typeof agentOrError === 'string')
|
|
17
|
+
return agentOrError;
|
|
18
|
+
const agent = agentOrError;
|
|
19
|
+
if (!agent.cloud) {
|
|
20
|
+
return `Member "${agent.friendlyName}" is not a cloud member (no cloud config).`;
|
|
21
|
+
}
|
|
22
|
+
switch (input.action) {
|
|
23
|
+
case 'start': {
|
|
24
|
+
try {
|
|
25
|
+
const readyAgent = await ensureCloudReady(agent);
|
|
26
|
+
return `Started "${readyAgent.friendlyName}" — SSH ready at ${readyAgent.host ?? agent.host ?? '(unknown IP)'}.`;
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
return `Failed to start "${agent.friendlyName}": ${err.message}`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
case 'stop': {
|
|
33
|
+
try {
|
|
34
|
+
await awsProvider.stopInstance(agent.cloud);
|
|
35
|
+
return `Stopped "${agent.friendlyName}" (${agent.cloud.instanceId}).`;
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
return `Failed to stop "${agent.friendlyName}": ${err.message}`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
case 'status': {
|
|
42
|
+
try {
|
|
43
|
+
const details = await awsProvider.getInstanceDetails(agent.cloud);
|
|
44
|
+
const uptimeHrs = uptimeHoursFromLaunch(details.launchTime);
|
|
45
|
+
const uptime = details.launchTime ? formatUptimeDuration(uptimeHrs) : '-';
|
|
46
|
+
const cost = estimateCost(details.instanceType, uptimeHrs);
|
|
47
|
+
const rate = hourlyRate(details.instanceType);
|
|
48
|
+
const typeStr = details.instanceType ?? 'unknown type';
|
|
49
|
+
const ipStr = details.publicIp ?? 'no public IP';
|
|
50
|
+
const warn = costWarning(details.instanceType, uptimeHrs);
|
|
51
|
+
const uptimeWarn = uptimeWarning(uptimeHrs);
|
|
52
|
+
// Anomaly: running but no recent activity and uptime is long
|
|
53
|
+
const lastUsedMs = agent.lastUsed ? Date.now() - new Date(agent.lastUsed).getTime() : undefined;
|
|
54
|
+
const idleAnomalyWarn = (details.state === 'running' &&
|
|
55
|
+
lastUsedMs !== undefined &&
|
|
56
|
+
lastUsedMs > 2 * 3_600_000 && // >2h since last activity
|
|
57
|
+
uptimeHrs > 2) ? '⚠ Instance running but no recent activity — idle manager may not be active' : null;
|
|
58
|
+
// GPU utilization check (only when running and SSH is available)
|
|
59
|
+
let gpuLine = '';
|
|
60
|
+
if (details.state === 'running') {
|
|
61
|
+
try {
|
|
62
|
+
const strategy = getStrategy(agent);
|
|
63
|
+
const cmds = getOsCommands(getAgentOS(agent));
|
|
64
|
+
const gpuResult = await strategy.execCommand(cmds.gpuUtilization(), 10000);
|
|
65
|
+
const gpuUtil = parseGpuUtilization(gpuResult.stdout);
|
|
66
|
+
if (gpuUtil !== undefined) {
|
|
67
|
+
gpuLine = `\n gpu: ${gpuUtil}%`;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// Empty stdout: nvidia-smi not found (suppressed by 2>/dev/null)
|
|
71
|
+
gpuLine = '\n gpu: n/a (nvidia-smi not found)';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
gpuLine = '\n gpu: n/a (check failed)';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
let out = (`"${agent.friendlyName}" cloud status:\n` +
|
|
79
|
+
` state: ${details.state}\n` +
|
|
80
|
+
` instance: ${agent.cloud.instanceId} (${typeStr})\n` +
|
|
81
|
+
` region: ${agent.cloud.region}\n` +
|
|
82
|
+
` ip: ${ipStr}\n` +
|
|
83
|
+
` uptime: ${uptime}\n` +
|
|
84
|
+
` rate: ${rate}\n` +
|
|
85
|
+
` est cost: ${cost}` +
|
|
86
|
+
gpuLine +
|
|
87
|
+
`\n idle timeout: ${agent.cloud.idleTimeoutMin}min`);
|
|
88
|
+
if (warn)
|
|
89
|
+
out += `\n warning: ${warn}`;
|
|
90
|
+
if (uptimeWarn)
|
|
91
|
+
out += `\n warning: ⚠ ${uptimeWarn}`;
|
|
92
|
+
if (idleAnomalyWarn)
|
|
93
|
+
out += `\n warning: ${idleAnomalyWarn}`;
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
return `Failed to get status for "${agent.friendlyName}": ${err.message}`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=cloud-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-control.js","sourceRoot":"","sources":["../../src/tools/cloud-control.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const composePermissionsSchema: z.ZodObject<{
|
|
3
|
+
role: z.ZodEnum<["doer", "reviewer"]>;
|
|
4
|
+
project_folder: z.ZodOptional<z.ZodString>;
|
|
5
|
+
grant: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
6
|
+
grant_reason: z.ZodOptional<z.ZodString>;
|
|
7
|
+
member_id: z.ZodOptional<z.ZodString>;
|
|
8
|
+
member_name: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
role: "doer" | "reviewer";
|
|
11
|
+
member_id?: string | undefined;
|
|
12
|
+
member_name?: string | undefined;
|
|
13
|
+
project_folder?: string | undefined;
|
|
14
|
+
grant?: string[] | undefined;
|
|
15
|
+
grant_reason?: string | undefined;
|
|
16
|
+
}, {
|
|
17
|
+
role: "doer" | "reviewer";
|
|
18
|
+
member_id?: string | undefined;
|
|
19
|
+
member_name?: string | undefined;
|
|
20
|
+
project_folder?: string | undefined;
|
|
21
|
+
grant?: string[] | undefined;
|
|
22
|
+
grant_reason?: string | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
export type ComposePermissionsInput = z.infer<typeof composePermissionsSchema>;
|
|
25
|
+
export declare function composePermissions(input: ComposePermissionsInput): Promise<string>;
|
|
26
|
+
//# sourceMappingURL=compose-permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-permissions.d.ts","sourceRoot":"","sources":["../../src/tools/compose-permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;EAMnC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AA8I/E,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkFxF"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { dirname } from 'path';
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
import { getStrategy } from '../services/strategy.js';
|
|
10
|
+
import { memberIdentifier, resolveMember } from '../utils/resolve-member.js';
|
|
11
|
+
import { getProvider } from '../providers/index.js';
|
|
12
|
+
export const composePermissionsSchema = z.object({
|
|
13
|
+
...memberIdentifier,
|
|
14
|
+
role: z.enum(['doer', 'reviewer']).describe('Role determines base profile (doer = broad build/test, reviewer = read + feedback + test)'),
|
|
15
|
+
project_folder: z.string().optional().describe('Local project folder containing permissions.json ledger. Omit to skip ledger merge.'),
|
|
16
|
+
grant: z.array(z.string()).optional().describe('Reactive mode: additional permissions to grant (e.g. ["Bash(docker:*)", "Bash(docker-compose:*)"]). Appended to current permissions and re-delivered.'),
|
|
17
|
+
grant_reason: z.string().optional().describe('Reason for the grant (stored in ledger)'),
|
|
18
|
+
});
|
|
19
|
+
// Stack marker files -> profile keys
|
|
20
|
+
const STACK_MAP = {
|
|
21
|
+
'package.json': 'node',
|
|
22
|
+
'Cargo.toml': 'rust',
|
|
23
|
+
'requirements.txt': 'python',
|
|
24
|
+
'pyproject.toml': 'python',
|
|
25
|
+
'setup.py': 'python',
|
|
26
|
+
'go.mod': 'go',
|
|
27
|
+
'build.gradle': 'jvm',
|
|
28
|
+
'pom.xml': 'jvm',
|
|
29
|
+
'Makefile': 'cpp',
|
|
30
|
+
'CMakeLists.txt': 'cpp',
|
|
31
|
+
'composer.json': 'php',
|
|
32
|
+
};
|
|
33
|
+
// Co-occurrence: granting one tool often means needing related tools
|
|
34
|
+
const CO_OCCURRENCE = {
|
|
35
|
+
'Bash(docker:*)': ['Bash(docker-compose:*)', 'Bash(docker buildx:*)'],
|
|
36
|
+
'Bash(kubectl:*)': ['Bash(helm:*)'],
|
|
37
|
+
'Bash(terraform:*)': ['Bash(terragrunt:*)'],
|
|
38
|
+
'Bash(pip:*)': ['Bash(pip3:*)'],
|
|
39
|
+
'Bash(python:*)': ['Bash(python3:*)'],
|
|
40
|
+
};
|
|
41
|
+
// Never auto-grant - require user escalation
|
|
42
|
+
const NEVER_AUTO_GRANT = new Set([
|
|
43
|
+
'Bash(sudo:*)', 'Bash(su:*)', 'Bash(env:*)', 'Bash(printenv:*)',
|
|
44
|
+
'Bash(nc:*)', 'Bash(nmap:*)', 'Bash(chmod 777:*)',
|
|
45
|
+
]);
|
|
46
|
+
function findProfilesDir() {
|
|
47
|
+
// Installed: ~/.claude/skills/fleet/profiles/ (new location after skill split)
|
|
48
|
+
const installedFleet = path.join(os.homedir(), '.claude', 'skills', 'fleet', 'profiles');
|
|
49
|
+
if (fs.existsSync(installedFleet))
|
|
50
|
+
return installedFleet;
|
|
51
|
+
// Installed (legacy): ~/.claude/skills/pm/profiles/
|
|
52
|
+
const installedPm = path.join(os.homedir(), '.claude', 'skills', 'pm', 'profiles');
|
|
53
|
+
if (fs.existsSync(installedPm))
|
|
54
|
+
return installedPm;
|
|
55
|
+
// Dev: walk up from __dirname looking for skills/fleet/profiles/
|
|
56
|
+
let dir = __dirname;
|
|
57
|
+
for (let i = 0; i < 6; i++) {
|
|
58
|
+
const candidateFleet = path.join(dir, 'skills', 'fleet', 'profiles');
|
|
59
|
+
if (fs.existsSync(candidateFleet))
|
|
60
|
+
return candidateFleet;
|
|
61
|
+
const candidatePm = path.join(dir, 'skills', 'pm', 'profiles');
|
|
62
|
+
if (fs.existsSync(candidatePm))
|
|
63
|
+
return candidatePm;
|
|
64
|
+
dir = path.dirname(dir);
|
|
65
|
+
}
|
|
66
|
+
throw new Error('Cannot find profiles directory');
|
|
67
|
+
}
|
|
68
|
+
function loadProfile(profilesDir, name) {
|
|
69
|
+
const filePath = path.join(profilesDir, `${name}.json`);
|
|
70
|
+
if (!fs.existsSync(filePath))
|
|
71
|
+
return null;
|
|
72
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
73
|
+
}
|
|
74
|
+
function loadLedger(projectFolder) {
|
|
75
|
+
const ledgerPath = path.join(projectFolder, 'permissions.json');
|
|
76
|
+
if (fs.existsSync(ledgerPath)) {
|
|
77
|
+
const raw = JSON.parse(fs.readFileSync(ledgerPath, 'utf-8'));
|
|
78
|
+
return { stacks: raw.stacks ?? [], granted: raw.granted ?? [] };
|
|
79
|
+
}
|
|
80
|
+
return { stacks: [], granted: [] };
|
|
81
|
+
}
|
|
82
|
+
function saveLedger(projectFolder, ledger) {
|
|
83
|
+
const ledgerPath = path.join(projectFolder, 'permissions.json');
|
|
84
|
+
fs.writeFileSync(ledgerPath, JSON.stringify(ledger, null, 2) + '\n');
|
|
85
|
+
}
|
|
86
|
+
async function detectStacks(agent, projectSubdir) {
|
|
87
|
+
const strategy = getStrategy(agent);
|
|
88
|
+
const markers = Object.keys(STACK_MAP).join(' ');
|
|
89
|
+
// Resolve the directory to check on the member: prefer <workFolder>/<projectSubdir>,
|
|
90
|
+
// fall back to workFolder root. Using an absolute cd ensures remote (SSH) members
|
|
91
|
+
// check the right directory instead of defaulting to their home directory.
|
|
92
|
+
const checkDir = projectSubdir
|
|
93
|
+
? `${agent.workFolder}/${projectSubdir}`.replace(/\\/g, '/')
|
|
94
|
+
: agent.workFolder.replace(/\\/g, '/');
|
|
95
|
+
const result = await strategy.execCommand(`cd "${checkDir}" 2>/dev/null && ls ${markers} 2>/dev/null || true`, 10000);
|
|
96
|
+
const found = new Set();
|
|
97
|
+
for (const line of result.stdout.split('\n')) {
|
|
98
|
+
const file = line.trim();
|
|
99
|
+
if (STACK_MAP[file])
|
|
100
|
+
found.add(STACK_MAP[file]);
|
|
101
|
+
}
|
|
102
|
+
// .sln/.csproj need glob - check separately
|
|
103
|
+
const dotnetCheck = await strategy.execCommand(`cd "${checkDir}" 2>/dev/null && ls *.sln *.csproj 2>/dev/null || true`, 5000);
|
|
104
|
+
if (dotnetCheck.stdout.trim())
|
|
105
|
+
found.add('dotnet');
|
|
106
|
+
return [...found];
|
|
107
|
+
}
|
|
108
|
+
function compose(profilesDir, role, stacks, ledger) {
|
|
109
|
+
const baseName = role === 'doer' ? 'base-dev' : 'base-reviewer';
|
|
110
|
+
const base = loadProfile(profilesDir, baseName);
|
|
111
|
+
const perms = new Set(base?.permissions?.allow ?? []);
|
|
112
|
+
const roleKey = role === 'doer' ? 'dev' : 'reviewer';
|
|
113
|
+
for (const stack of stacks) {
|
|
114
|
+
const profile = loadProfile(profilesDir, stack);
|
|
115
|
+
if (profile?.[roleKey]) {
|
|
116
|
+
for (const p of profile[roleKey])
|
|
117
|
+
perms.add(p);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Merge ledger grants
|
|
121
|
+
for (const entry of ledger.granted) {
|
|
122
|
+
perms.add(entry.permission);
|
|
123
|
+
}
|
|
124
|
+
return [...perms];
|
|
125
|
+
}
|
|
126
|
+
/** Deliver a single config file to the member.
|
|
127
|
+
* Creates parent directory and writes the content (JSON object or TOML string). */
|
|
128
|
+
async function deliverConfigFile(strategy, agentOs, filePath, content) {
|
|
129
|
+
const dir = filePath.split('/').slice(0, -1).join('/');
|
|
130
|
+
const mkdirCmd = agentOs === 'windows'
|
|
131
|
+
? `New-Item -ItemType Directory -Force "${dir.replace(/\//g, '\\')}"`
|
|
132
|
+
: `mkdir -p ${dir}`;
|
|
133
|
+
await strategy.execCommand(mkdirCmd, 5000);
|
|
134
|
+
const contentStr = typeof content === 'string'
|
|
135
|
+
? content
|
|
136
|
+
: JSON.stringify(content, null, 2);
|
|
137
|
+
const writeCmd = agentOs === 'windows'
|
|
138
|
+
? `[System.IO.File]::WriteAllText("${filePath.replace(/\//g, '\\')}", '${contentStr.replace(/'/g, "''")}', (New-Object System.Text.UTF8Encoding($false)))`
|
|
139
|
+
: `cat > ${filePath} << 'FLEET_PERMS_EOF'\n${contentStr}\nFLEET_PERMS_EOF`;
|
|
140
|
+
await strategy.execCommand(writeCmd, 5000);
|
|
141
|
+
}
|
|
142
|
+
export async function composePermissions(input) {
|
|
143
|
+
const agentOrError = resolveMember(input.member_id, input.member_name);
|
|
144
|
+
if (typeof agentOrError === 'string')
|
|
145
|
+
return agentOrError;
|
|
146
|
+
const agent = agentOrError;
|
|
147
|
+
const provider = getProvider(agent.llmProvider);
|
|
148
|
+
const strategy = getStrategy(agent);
|
|
149
|
+
const profilesDir = findProfilesDir();
|
|
150
|
+
const ledger = input.project_folder ? loadLedger(input.project_folder) : { stacks: [], granted: [] };
|
|
151
|
+
// Reactive grant mode
|
|
152
|
+
if (input.grant?.length) {
|
|
153
|
+
const blocked = input.grant.filter(p => NEVER_AUTO_GRANT.has(p));
|
|
154
|
+
if (blocked.length) {
|
|
155
|
+
return `❌ Cannot auto-grant dangerous permissions: ${blocked.join(', ')}. Escalate to user.`;
|
|
156
|
+
}
|
|
157
|
+
// Expand co-occurrences
|
|
158
|
+
const expanded = new Set(input.grant);
|
|
159
|
+
for (const p of input.grant) {
|
|
160
|
+
for (const co of CO_OCCURRENCE[p] ?? [])
|
|
161
|
+
expanded.add(co);
|
|
162
|
+
}
|
|
163
|
+
let allow;
|
|
164
|
+
if (provider.name === 'claude') {
|
|
165
|
+
// Claude: read existing allow list and merge
|
|
166
|
+
const readResult = await strategy.execCommand('cat .claude/settings.local.json 2>/dev/null || echo "{}"', 5000);
|
|
167
|
+
let current;
|
|
168
|
+
try {
|
|
169
|
+
current = JSON.parse(readResult.stdout.trim());
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
current = { permissions: { allow: [] } };
|
|
173
|
+
}
|
|
174
|
+
const existingAllow = new Set(current?.permissions?.allow ?? []);
|
|
175
|
+
for (const p of expanded)
|
|
176
|
+
existingAllow.add(p);
|
|
177
|
+
allow = [...existingAllow];
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
// Non-Claude: pass grants directly; provider incorporates into role-based config
|
|
181
|
+
allow = [...expanded];
|
|
182
|
+
}
|
|
183
|
+
const configs = provider.composePermissionConfig(input.role, allow);
|
|
184
|
+
const paths = provider.permissionConfigPaths();
|
|
185
|
+
for (let i = 0; i < paths.length; i++) {
|
|
186
|
+
await deliverConfigFile(strategy, agent.os ?? 'linux', paths[i], configs[i]);
|
|
187
|
+
}
|
|
188
|
+
// Update ledger
|
|
189
|
+
if (input.project_folder) {
|
|
190
|
+
const reason = input.grant_reason ?? 'granted mid-sprint';
|
|
191
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
192
|
+
for (const p of expanded) {
|
|
193
|
+
if (!ledger.granted.some(e => e.permission === p)) {
|
|
194
|
+
ledger.granted.push({ permission: p, reason, date });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
saveLedger(input.project_folder, ledger);
|
|
198
|
+
}
|
|
199
|
+
return `✅ Granted ${[...expanded].length} permissions on "${agent.friendlyName}" (${provider.name}):\n ${[...expanded].join('\n ')}`;
|
|
200
|
+
}
|
|
201
|
+
// Proactive compose mode
|
|
202
|
+
const projectSubdir = input.project_folder ? path.basename(input.project_folder) : undefined;
|
|
203
|
+
const stacks = await detectStacks(agent, projectSubdir);
|
|
204
|
+
// Update ledger stacks
|
|
205
|
+
if (input.project_folder) {
|
|
206
|
+
ledger.stacks = stacks;
|
|
207
|
+
saveLedger(input.project_folder, ledger);
|
|
208
|
+
}
|
|
209
|
+
const allow = compose(profilesDir, input.role, stacks, ledger);
|
|
210
|
+
const configs = provider.composePermissionConfig(input.role, allow);
|
|
211
|
+
const paths = provider.permissionConfigPaths();
|
|
212
|
+
for (let i = 0; i < paths.length; i++) {
|
|
213
|
+
await deliverConfigFile(strategy, agent.os ?? 'linux', paths[i], configs[i]);
|
|
214
|
+
}
|
|
215
|
+
return `✅ Permissions composed for "${agent.friendlyName}" (${input.role}, ${provider.name}):\n Stacks: ${stacks.join(', ') || 'none detected'}\n Config: ${paths.join(', ')}\n Ledger grants: ${ledger.granted.length}`;
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=compose-permissions.js.map
|