@phnx-labs/agents-cli 1.12.0 → 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/CHANGELOG.md +7 -1
- package/README.md +308 -297
- package/dist/commands/alias.d.ts +11 -0
- package/dist/commands/alias.js +117 -0
- package/dist/commands/beta.d.ts +2 -0
- package/dist/commands/beta.js +53 -0
- package/dist/commands/cloud.d.ts +10 -0
- package/dist/commands/cloud.js +408 -0
- package/dist/commands/commands.d.ts +9 -1
- package/dist/commands/commands.js +24 -172
- package/dist/commands/daemon.d.ts +8 -1
- package/dist/commands/daemon.js +13 -5
- package/dist/commands/doctor.d.ts +15 -0
- package/dist/commands/doctor.js +132 -0
- package/dist/commands/drive.d.ts +8 -1
- package/dist/commands/drive.js +20 -3
- package/dist/commands/exec.d.ts +8 -1
- package/dist/commands/exec.js +207 -20
- package/dist/commands/factory.d.ts +19 -0
- package/dist/commands/factory.js +71 -0
- package/dist/commands/fork.d.ts +8 -1
- package/dist/commands/fork.js +11 -4
- package/dist/commands/hooks.d.ts +9 -1
- package/dist/commands/hooks.js +30 -182
- package/dist/commands/init.d.ts +15 -1
- package/dist/commands/init.js +168 -74
- package/dist/commands/mcp.d.ts +9 -1
- package/dist/commands/mcp.js +11 -7
- package/dist/commands/models.d.ts +8 -1
- package/dist/commands/models.js +45 -6
- package/dist/commands/packages.d.ts +8 -1
- package/dist/commands/packages.js +13 -7
- package/dist/commands/permissions.d.ts +9 -1
- package/dist/commands/permissions.js +3 -3
- package/dist/commands/plugins.d.ts +8 -1
- package/dist/commands/plugins.js +13 -2
- package/dist/commands/profiles.d.ts +11 -0
- package/dist/commands/profiles.js +291 -0
- package/dist/commands/prune.d.ts +22 -0
- package/dist/commands/prune.js +191 -0
- package/dist/commands/pty.d.ts +1 -1
- package/dist/commands/pty.js +2 -1
- package/dist/commands/pull.d.ts +8 -1
- package/dist/commands/pull.js +93 -129
- package/dist/commands/refresh-memory.d.ts +7 -1
- package/dist/commands/refresh-memory.js +7 -1
- package/dist/commands/repo.d.ts +15 -0
- package/dist/commands/repo.js +570 -0
- package/dist/commands/resource-view.d.ts +10 -3
- package/dist/commands/resource-view.js +18 -5
- package/dist/commands/routines.d.ts +8 -1
- package/dist/commands/routines.js +17 -4
- package/dist/commands/rules.d.ts +9 -1
- package/dist/commands/rules.js +16 -11
- package/dist/commands/secrets.d.ts +10 -0
- package/dist/commands/secrets.js +518 -0
- package/dist/commands/sessions-picker.d.ts +2 -1
- package/dist/commands/sessions-picker.js +88 -11
- package/dist/commands/sessions-tail.d.ts +19 -0
- package/dist/commands/sessions-tail.js +235 -0
- package/dist/commands/sessions.d.ts +2 -1
- package/dist/commands/sessions.js +288 -7
- package/dist/commands/skills.d.ts +9 -1
- package/dist/commands/skills.js +28 -178
- package/dist/commands/status.d.ts +7 -1
- package/dist/commands/status.js +7 -1
- package/dist/commands/subagents.d.ts +8 -1
- package/dist/commands/subagents.js +11 -1
- package/dist/commands/sync.d.ts +8 -1
- package/dist/commands/sync.js +8 -1
- package/dist/commands/teams-picker.d.ts +4 -1
- package/dist/commands/teams-picker.js +55 -3
- package/dist/commands/teams.d.ts +15 -1
- package/dist/commands/teams.js +323 -69
- package/dist/commands/usage.d.ts +11 -0
- package/dist/commands/usage.js +60 -0
- package/dist/commands/utils.d.ts +6 -1
- package/dist/commands/utils.js +6 -1
- package/dist/commands/versions.d.ts +8 -1
- package/dist/commands/versions.js +4 -3
- package/dist/commands/view.d.ts +47 -2
- package/dist/commands/view.js +353 -20
- package/dist/index.d.ts +7 -2
- package/dist/index.js +205 -38
- package/dist/lib/acp/client.d.ts +31 -0
- package/dist/lib/acp/client.js +117 -0
- package/dist/lib/acp/harnesses.d.ts +26 -0
- package/dist/lib/acp/harnesses.js +65 -0
- package/dist/lib/acp/run.d.ts +18 -0
- package/dist/lib/acp/run.js +39 -0
- package/dist/lib/agents.d.ts +74 -2
- package/dist/lib/agents.js +207 -23
- package/dist/lib/artifact-actions.d.ts +8 -4
- package/dist/lib/artifact-actions.js +8 -6
- package/dist/lib/auto-pull-worker.d.ts +11 -0
- package/dist/lib/auto-pull-worker.js +121 -0
- package/dist/lib/auto-pull.d.ts +31 -0
- package/dist/lib/auto-pull.js +97 -0
- package/dist/lib/beta.d.ts +23 -0
- package/dist/lib/beta.js +90 -0
- package/dist/lib/capabilities.d.ts +29 -0
- package/dist/lib/capabilities.js +74 -0
- package/dist/lib/cloud/codex.d.ts +25 -0
- package/dist/lib/cloud/codex.js +250 -0
- package/dist/lib/cloud/factory.d.ts +31 -0
- package/dist/lib/cloud/factory.js +53 -0
- package/dist/lib/cloud/registry.d.ts +15 -0
- package/dist/lib/cloud/registry.js +67 -0
- package/dist/lib/cloud/rush.d.ts +75 -0
- package/dist/lib/cloud/rush.js +438 -0
- package/dist/lib/cloud/store.d.ts +22 -0
- package/dist/lib/cloud/store.js +115 -0
- package/dist/lib/cloud/stream.d.ts +23 -0
- package/dist/lib/cloud/stream.js +194 -0
- package/dist/lib/cloud/types.d.ts +205 -0
- package/dist/lib/cloud/types.js +34 -0
- package/dist/lib/command-skills.d.ts +20 -0
- package/dist/lib/command-skills.js +142 -0
- package/dist/lib/commands.d.ts +22 -2
- package/dist/lib/commands.js +51 -11
- package/dist/lib/convert.d.ts +10 -1
- package/dist/lib/convert.js +9 -1
- package/dist/lib/daemon.d.ts +21 -1
- package/dist/lib/daemon.js +97 -4
- package/dist/lib/drive-sync.d.ts +18 -1
- package/dist/lib/drive-sync.js +57 -15
- package/dist/lib/exec.d.ts +25 -5
- package/dist/lib/exec.js +72 -27
- package/dist/lib/fs-walk.d.ts +2 -0
- package/dist/lib/fs-walk.js +40 -0
- package/dist/lib/fuzzy.d.ts +53 -0
- package/dist/lib/fuzzy.js +72 -0
- package/dist/lib/gemini-settings.d.ts +4 -0
- package/dist/lib/gemini-settings.js +33 -0
- package/dist/lib/git.d.ts +12 -2
- package/dist/lib/git.js +17 -6
- package/dist/lib/help.d.ts +20 -1
- package/dist/lib/help.js +45 -6
- package/dist/lib/hooks/match.d.ts +32 -0
- package/dist/lib/hooks/match.js +120 -0
- package/dist/lib/hooks.d.ts +17 -4
- package/dist/lib/hooks.js +191 -21
- package/dist/lib/manifest.d.ts +6 -1
- package/dist/lib/manifest.js +15 -4
- package/dist/lib/markdown.d.ts +0 -1
- package/dist/lib/markdown.js +6 -1
- package/dist/lib/mcp.d.ts +0 -1
- package/dist/lib/mcp.js +29 -33
- package/dist/lib/memory-compile.d.ts +13 -3
- package/dist/lib/memory-compile.js +31 -9
- package/dist/lib/memory.d.ts +14 -7
- package/dist/lib/memory.js +67 -38
- package/dist/lib/migrate.d.ts +8 -0
- package/dist/lib/migrate.js +85 -0
- package/dist/lib/models.d.ts +25 -11
- package/dist/lib/models.js +405 -16
- package/dist/lib/onepassword.d.ts +63 -0
- package/dist/lib/onepassword.js +186 -0
- package/dist/lib/paths.d.ts +8 -0
- package/dist/lib/paths.js +20 -0
- package/dist/lib/permissions.d.ts +24 -2
- package/dist/lib/permissions.js +117 -48
- package/dist/lib/picker.d.ts +10 -1
- package/dist/lib/picker.js +15 -1
- package/dist/lib/plugins.d.ts +7 -1
- package/dist/lib/plugins.js +10 -1
- package/dist/lib/profiles-presets.d.ts +24 -0
- package/dist/lib/profiles-presets.js +103 -0
- package/dist/lib/profiles.d.ts +69 -0
- package/dist/lib/profiles.js +144 -0
- package/dist/lib/pty-client.d.ts +1 -1
- package/dist/lib/pty-client.js +0 -1
- package/dist/lib/pty-server.d.ts +16 -2
- package/dist/lib/pty-server.js +92 -3
- package/dist/lib/registry.d.ts +23 -3
- package/dist/lib/registry.js +153 -8
- package/dist/lib/resources.d.ts +28 -1
- package/dist/lib/resources.js +79 -1
- package/dist/lib/rotate.d.ts +89 -0
- package/dist/lib/rotate.js +327 -0
- package/dist/lib/routines.d.ts +29 -1
- package/dist/lib/routines.js +32 -5
- package/dist/lib/runner.d.ts +14 -1
- package/dist/lib/runner.js +22 -3
- package/dist/lib/sandbox.d.ts +16 -1
- package/dist/lib/sandbox.js +39 -16
- package/dist/lib/scheduler.d.ts +8 -1
- package/dist/lib/scheduler.js +8 -1
- package/dist/lib/secrets/AgentsKeychain.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/AgentsKeychain.app/Contents/Info.plist +22 -0
- package/dist/lib/secrets/AgentsKeychain.app/Contents/MacOS/AgentsKeychain +0 -0
- package/dist/lib/secrets/AgentsKeychain.app/Contents/_CodeSignature/CodeResources +123 -0
- package/dist/lib/secrets/AgentsKeychain.app/Contents/embedded.provisionprofile +0 -0
- package/dist/lib/secrets/bundles.d.ts +39 -0
- package/dist/lib/secrets/bundles.js +189 -0
- package/dist/lib/secrets/index.d.ts +55 -0
- package/dist/lib/secrets/index.js +211 -0
- package/dist/lib/secrets/profiles.d.ts +10 -0
- package/dist/lib/secrets/profiles.js +13 -0
- package/dist/lib/session/active.d.ts +43 -0
- package/dist/lib/session/active.js +392 -0
- package/dist/lib/session/artifacts.d.ts +16 -0
- package/dist/lib/session/artifacts.js +95 -0
- package/dist/lib/session/cloud.d.ts +30 -0
- package/dist/lib/session/cloud.js +121 -0
- package/dist/lib/session/db.d.ts +23 -2
- package/dist/lib/session/db.js +76 -12
- package/dist/lib/session/discover.d.ts +19 -4
- package/dist/lib/session/discover.js +344 -48
- package/dist/lib/session/parse.d.ts +28 -1
- package/dist/lib/session/parse.js +267 -9
- package/dist/lib/session/prompt.d.ts +9 -1
- package/dist/lib/session/prompt.js +17 -3
- package/dist/lib/session/render.d.ts +13 -1
- package/dist/lib/session/render.js +20 -1
- package/dist/lib/session/team-filter.d.ts +9 -1
- package/dist/lib/session/team-filter.js +11 -2
- package/dist/lib/session/types.d.ts +24 -2
- package/dist/lib/session/types.js +10 -2
- package/dist/lib/shims.d.ts +93 -5
- package/dist/lib/shims.js +380 -67
- package/dist/lib/skills.d.ts +27 -2
- package/dist/lib/skills.js +127 -65
- package/dist/lib/sqlite.d.ts +43 -0
- package/dist/lib/sqlite.js +94 -0
- package/dist/lib/state.d.ts +114 -22
- package/dist/lib/state.js +323 -138
- package/dist/lib/subagents.d.ts +9 -1
- package/dist/lib/subagents.js +70 -63
- package/dist/lib/sync-manifest.d.ts +81 -0
- package/dist/lib/sync-manifest.js +450 -0
- package/dist/lib/teams/agents.d.ts +103 -5
- package/dist/lib/teams/agents.js +414 -91
- package/dist/lib/teams/api.d.ts +26 -3
- package/dist/lib/teams/api.js +63 -3
- package/dist/lib/teams/debug.d.ts +6 -1
- package/dist/lib/teams/debug.js +6 -1
- package/dist/lib/teams/file_ops.d.ts +7 -1
- package/dist/lib/teams/file_ops.js +7 -1
- package/dist/lib/teams/index.d.ts +15 -0
- package/dist/lib/teams/index.js +14 -0
- package/dist/lib/teams/parsers.d.ts +4 -1
- package/dist/lib/teams/parsers.js +11 -1
- package/dist/lib/teams/persistence.d.ts +15 -1
- package/dist/lib/teams/persistence.js +102 -20
- package/dist/lib/teams/registry.d.ts +12 -1
- package/dist/lib/teams/registry.js +116 -33
- package/dist/lib/teams/summarizer.d.ts +15 -1
- package/dist/lib/teams/summarizer.js +14 -1
- package/dist/lib/teams/supervisor.d.ts +48 -0
- package/dist/lib/teams/supervisor.js +73 -0
- package/dist/lib/template.d.ts +8 -6
- package/dist/lib/template.js +8 -6
- package/dist/lib/types.d.ts +147 -8
- package/dist/lib/types.js +26 -3
- package/dist/lib/usage.d.ts +48 -1
- package/dist/lib/usage.js +97 -16
- package/dist/lib/version-duplicates.d.ts +21 -0
- package/dist/lib/version-duplicates.js +90 -0
- package/dist/lib/versions.d.ts +39 -4
- package/dist/lib/versions.js +401 -111
- package/package.json +33 -18
- package/scripts/postinstall.js +126 -30
- package/dist/commands/__tests__/sessions.test.d.ts +0 -2
- package/dist/commands/__tests__/sessions.test.d.ts.map +0 -1
- package/dist/commands/__tests__/sessions.test.js +0 -636
- package/dist/commands/__tests__/sessions.test.js.map +0 -1
- package/dist/commands/commands.d.ts.map +0 -1
- package/dist/commands/commands.js.map +0 -1
- package/dist/commands/daemon.d.ts.map +0 -1
- package/dist/commands/daemon.js.map +0 -1
- package/dist/commands/drive.d.ts.map +0 -1
- package/dist/commands/drive.js.map +0 -1
- package/dist/commands/exec.d.ts.map +0 -1
- package/dist/commands/exec.js.map +0 -1
- package/dist/commands/fork.d.ts.map +0 -1
- package/dist/commands/fork.js.map +0 -1
- package/dist/commands/hooks.d.ts.map +0 -1
- package/dist/commands/hooks.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/mcp.d.ts.map +0 -1
- package/dist/commands/mcp.js.map +0 -1
- package/dist/commands/models.d.ts.map +0 -1
- package/dist/commands/models.js.map +0 -1
- package/dist/commands/packages.d.ts.map +0 -1
- package/dist/commands/packages.js.map +0 -1
- package/dist/commands/permissions.d.ts.map +0 -1
- package/dist/commands/permissions.js.map +0 -1
- package/dist/commands/plugins.d.ts.map +0 -1
- package/dist/commands/plugins.js.map +0 -1
- package/dist/commands/pty.d.ts.map +0 -1
- package/dist/commands/pty.js.map +0 -1
- package/dist/commands/pull.d.ts.map +0 -1
- package/dist/commands/pull.js.map +0 -1
- package/dist/commands/push.d.ts +0 -3
- package/dist/commands/push.d.ts.map +0 -1
- package/dist/commands/push.js +0 -180
- package/dist/commands/push.js.map +0 -1
- package/dist/commands/refresh-memory.d.ts.map +0 -1
- package/dist/commands/refresh-memory.js.map +0 -1
- package/dist/commands/resource-view.d.ts.map +0 -1
- package/dist/commands/resource-view.js.map +0 -1
- package/dist/commands/routines.d.ts.map +0 -1
- package/dist/commands/routines.js.map +0 -1
- package/dist/commands/rules.d.ts.map +0 -1
- package/dist/commands/rules.js.map +0 -1
- package/dist/commands/sessions-picker.d.ts.map +0 -1
- package/dist/commands/sessions-picker.js.map +0 -1
- package/dist/commands/sessions.d.ts.map +0 -1
- package/dist/commands/sessions.js.map +0 -1
- package/dist/commands/skills.d.ts.map +0 -1
- package/dist/commands/skills.js.map +0 -1
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/subagents.d.ts.map +0 -1
- package/dist/commands/subagents.js.map +0 -1
- package/dist/commands/sync.d.ts.map +0 -1
- package/dist/commands/sync.js.map +0 -1
- package/dist/commands/teams-picker.d.ts.map +0 -1
- package/dist/commands/teams-picker.js.map +0 -1
- package/dist/commands/teams.d.ts.map +0 -1
- package/dist/commands/teams.js.map +0 -1
- package/dist/commands/utils.d.ts.map +0 -1
- package/dist/commands/utils.js.map +0 -1
- package/dist/commands/versions.d.ts.map +0 -1
- package/dist/commands/versions.js.map +0 -1
- package/dist/commands/view.d.ts.map +0 -1
- package/dist/commands/view.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/__tests__/bugfixes.test.d.ts +0 -2
- package/dist/lib/__tests__/bugfixes.test.d.ts.map +0 -1
- package/dist/lib/__tests__/bugfixes.test.js +0 -192
- package/dist/lib/__tests__/bugfixes.test.js.map +0 -1
- package/dist/lib/__tests__/exec.test.d.ts +0 -2
- package/dist/lib/__tests__/exec.test.d.ts.map +0 -1
- package/dist/lib/__tests__/exec.test.js +0 -446
- package/dist/lib/__tests__/exec.test.js.map +0 -1
- package/dist/lib/__tests__/git-sync.test.d.ts +0 -2
- package/dist/lib/__tests__/git-sync.test.d.ts.map +0 -1
- package/dist/lib/__tests__/git-sync.test.js +0 -138
- package/dist/lib/__tests__/git-sync.test.js.map +0 -1
- package/dist/lib/__tests__/hooks.test.d.ts +0 -2
- package/dist/lib/__tests__/hooks.test.d.ts.map +0 -1
- package/dist/lib/__tests__/hooks.test.js +0 -203
- package/dist/lib/__tests__/hooks.test.js.map +0 -1
- package/dist/lib/__tests__/memory-compile.test.d.ts +0 -2
- package/dist/lib/__tests__/memory-compile.test.d.ts.map +0 -1
- package/dist/lib/__tests__/memory-compile.test.js +0 -95
- package/dist/lib/__tests__/memory-compile.test.js.map +0 -1
- package/dist/lib/__tests__/models.test.d.ts +0 -2
- package/dist/lib/__tests__/models.test.d.ts.map +0 -1
- package/dist/lib/__tests__/models.test.js +0 -184
- package/dist/lib/__tests__/models.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 -218
- package/dist/lib/__tests__/usage.test.js.map +0 -1
- package/dist/lib/agents.d.ts.map +0 -1
- package/dist/lib/agents.js.map +0 -1
- package/dist/lib/artifact-actions.d.ts.map +0 -1
- package/dist/lib/artifact-actions.js.map +0 -1
- package/dist/lib/commands.d.ts.map +0 -1
- package/dist/lib/commands.js.map +0 -1
- package/dist/lib/convert.d.ts.map +0 -1
- package/dist/lib/convert.js.map +0 -1
- package/dist/lib/daemon.d.ts.map +0 -1
- package/dist/lib/daemon.js.map +0 -1
- package/dist/lib/drive-sync.d.ts.map +0 -1
- package/dist/lib/drive-sync.js.map +0 -1
- package/dist/lib/exec.d.ts.map +0 -1
- package/dist/lib/exec.js.map +0 -1
- package/dist/lib/factory.d.ts +0 -57
- package/dist/lib/factory.d.ts.map +0 -1
- package/dist/lib/factory.js +0 -110
- package/dist/lib/factory.js.map +0 -1
- package/dist/lib/git.d.ts.map +0 -1
- package/dist/lib/git.js.map +0 -1
- package/dist/lib/help.d.ts.map +0 -1
- package/dist/lib/help.js.map +0 -1
- package/dist/lib/hooks.d.ts.map +0 -1
- package/dist/lib/hooks.js.map +0 -1
- package/dist/lib/manifest.d.ts.map +0 -1
- package/dist/lib/manifest.js.map +0 -1
- package/dist/lib/markdown.d.ts.map +0 -1
- package/dist/lib/markdown.js.map +0 -1
- package/dist/lib/mcp.d.ts.map +0 -1
- package/dist/lib/mcp.js.map +0 -1
- package/dist/lib/memory-compile.d.ts.map +0 -1
- package/dist/lib/memory-compile.js.map +0 -1
- package/dist/lib/memory.d.ts.map +0 -1
- package/dist/lib/memory.js.map +0 -1
- package/dist/lib/models.d.ts.map +0 -1
- package/dist/lib/models.js.map +0 -1
- package/dist/lib/permissions.d.ts.map +0 -1
- package/dist/lib/permissions.js.map +0 -1
- package/dist/lib/picker.d.ts.map +0 -1
- package/dist/lib/picker.js.map +0 -1
- package/dist/lib/plugins.d.ts.map +0 -1
- package/dist/lib/plugins.js.map +0 -1
- package/dist/lib/pty-client.d.ts.map +0 -1
- package/dist/lib/pty-client.js.map +0 -1
- package/dist/lib/pty-server.d.ts.map +0 -1
- package/dist/lib/pty-server.js.map +0 -1
- package/dist/lib/registry.d.ts.map +0 -1
- package/dist/lib/registry.js.map +0 -1
- package/dist/lib/resources.d.ts.map +0 -1
- package/dist/lib/resources.js.map +0 -1
- package/dist/lib/routines.d.ts.map +0 -1
- package/dist/lib/routines.js.map +0 -1
- package/dist/lib/runner.d.ts.map +0 -1
- package/dist/lib/runner.js.map +0 -1
- package/dist/lib/sandbox.d.ts.map +0 -1
- package/dist/lib/sandbox.js.map +0 -1
- package/dist/lib/scheduler.d.ts.map +0 -1
- package/dist/lib/scheduler.js.map +0 -1
- package/dist/lib/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/db.d.ts.map +0 -1
- package/dist/lib/session/db.js.map +0 -1
- package/dist/lib/session/discover.d.ts.map +0 -1
- package/dist/lib/session/discover.js.map +0 -1
- package/dist/lib/session/parse.d.ts.map +0 -1
- package/dist/lib/session/parse.js.map +0 -1
- package/dist/lib/session/prompt.d.ts.map +0 -1
- package/dist/lib/session/prompt.js.map +0 -1
- package/dist/lib/session/prompt.test.d.ts +0 -2
- package/dist/lib/session/prompt.test.d.ts.map +0 -1
- package/dist/lib/session/prompt.test.js +0 -57
- package/dist/lib/session/prompt.test.js.map +0 -1
- package/dist/lib/session/render.d.ts.map +0 -1
- package/dist/lib/session/render.js.map +0 -1
- package/dist/lib/session/team-filter.d.ts.map +0 -1
- package/dist/lib/session/team-filter.js.map +0 -1
- package/dist/lib/session/team-filter.test.d.ts +0 -2
- package/dist/lib/session/team-filter.test.d.ts.map +0 -1
- package/dist/lib/session/team-filter.test.js +0 -157
- package/dist/lib/session/team-filter.test.js.map +0 -1
- package/dist/lib/session/types.d.ts.map +0 -1
- package/dist/lib/session/types.js.map +0 -1
- package/dist/lib/shims.d.ts.map +0 -1
- package/dist/lib/shims.js.map +0 -1
- package/dist/lib/skills.d.ts.map +0 -1
- package/dist/lib/skills.js.map +0 -1
- package/dist/lib/state.d.ts.map +0 -1
- package/dist/lib/state.js.map +0 -1
- package/dist/lib/subagents.d.ts.map +0 -1
- package/dist/lib/subagents.js.map +0 -1
- package/dist/lib/teams/agents.d.ts.map +0 -1
- package/dist/lib/teams/agents.js.map +0 -1
- package/dist/lib/teams/api.d.ts.map +0 -1
- package/dist/lib/teams/api.js.map +0 -1
- package/dist/lib/teams/cloud.d.ts +0 -11
- package/dist/lib/teams/cloud.d.ts.map +0 -1
- package/dist/lib/teams/cloud.js +0 -169
- package/dist/lib/teams/cloud.js.map +0 -1
- package/dist/lib/teams/debug.d.ts.map +0 -1
- package/dist/lib/teams/debug.js.map +0 -1
- package/dist/lib/teams/file_ops.d.ts.map +0 -1
- package/dist/lib/teams/file_ops.js.map +0 -1
- package/dist/lib/teams/parsers.d.ts.map +0 -1
- package/dist/lib/teams/parsers.js.map +0 -1
- package/dist/lib/teams/persistence.d.ts.map +0 -1
- package/dist/lib/teams/persistence.js.map +0 -1
- package/dist/lib/teams/ralph.d.ts +0 -8
- package/dist/lib/teams/ralph.d.ts.map +0 -1
- package/dist/lib/teams/ralph.js +0 -59
- package/dist/lib/teams/ralph.js.map +0 -1
- package/dist/lib/teams/registry.d.ts.map +0 -1
- package/dist/lib/teams/registry.js.map +0 -1
- package/dist/lib/teams/summarizer.d.ts.map +0 -1
- package/dist/lib/teams/summarizer.js.map +0 -1
- package/dist/lib/template.d.ts.map +0 -1
- package/dist/lib/template.js.map +0 -1
- package/dist/lib/types.d.ts.map +0 -1
- package/dist/lib/types.js.map +0 -1
- package/dist/lib/usage.d.ts.map +0 -1
- package/dist/lib/usage.js.map +0 -1
- package/dist/lib/versions.d.ts.map +0 -1
- package/dist/lib/versions.js.map +0 -1
- package/scripts/rebuild-sqlite.sh +0 -46
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 1Password CLI (op) integration for importing secrets from vaults.
|
|
3
|
+
*/
|
|
4
|
+
import { spawnSync } from 'child_process';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as os from 'os';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
function runOp(args, input) {
|
|
9
|
+
const result = spawnSync('op', args, {
|
|
10
|
+
stdio: [input !== undefined ? 'pipe' : 'ignore', 'pipe', 'pipe'],
|
|
11
|
+
encoding: 'utf-8',
|
|
12
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
13
|
+
input,
|
|
14
|
+
});
|
|
15
|
+
if (result.error) {
|
|
16
|
+
if (result.error.code === 'ENOENT') {
|
|
17
|
+
return { ok: false, error: '1Password CLI not found. Install: brew install 1password-cli' };
|
|
18
|
+
}
|
|
19
|
+
return { ok: false, error: result.error.message };
|
|
20
|
+
}
|
|
21
|
+
if (result.status !== 0) {
|
|
22
|
+
const stderr = result.stderr?.trim() || '';
|
|
23
|
+
if (stderr.includes('not signed in') || stderr.includes('sign in') || stderr.includes('no active session')) {
|
|
24
|
+
return { ok: false, error: 'Not signed in to 1Password. Run: op signin' };
|
|
25
|
+
}
|
|
26
|
+
return { ok: false, error: stderr || `op exited with code ${result.status}` };
|
|
27
|
+
}
|
|
28
|
+
return { ok: true, stdout: result.stdout };
|
|
29
|
+
}
|
|
30
|
+
export function assertOpAvailable() {
|
|
31
|
+
// `op account list` works with both CLI session tokens and the 1Password
|
|
32
|
+
// desktop biometric integration; `op whoami` fails on the latter.
|
|
33
|
+
const result = runOp(['account', 'list', '--format=json']);
|
|
34
|
+
if (!result.ok) {
|
|
35
|
+
throw new Error(result.error);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function listVaults() {
|
|
39
|
+
const result = runOp(['vault', 'list', '--format=json']);
|
|
40
|
+
if (!result.ok)
|
|
41
|
+
throw new Error(result.error);
|
|
42
|
+
return JSON.parse(result.stdout);
|
|
43
|
+
}
|
|
44
|
+
export function listItems(vaultName) {
|
|
45
|
+
const result = runOp(['item', 'list', '--vault', vaultName, '--format=json']);
|
|
46
|
+
if (!result.ok) {
|
|
47
|
+
if (result.error.includes('vault') && result.error.includes('not found')) {
|
|
48
|
+
const vaults = listVaults();
|
|
49
|
+
const available = vaults.map((v) => v.name).join(', ');
|
|
50
|
+
throw new Error(`Vault '${vaultName}' not found. Available: ${available || '(none)'}`);
|
|
51
|
+
}
|
|
52
|
+
throw new Error(result.error);
|
|
53
|
+
}
|
|
54
|
+
const items = JSON.parse(result.stdout);
|
|
55
|
+
return items || [];
|
|
56
|
+
}
|
|
57
|
+
export function getItem(itemId, vaultName) {
|
|
58
|
+
const result = runOp(['item', 'get', itemId, '--vault', vaultName, '--format=json', '--reveal']);
|
|
59
|
+
if (!result.ok)
|
|
60
|
+
throw new Error(result.error);
|
|
61
|
+
return JSON.parse(result.stdout);
|
|
62
|
+
}
|
|
63
|
+
export function toEnvKey(title) {
|
|
64
|
+
return title
|
|
65
|
+
.toUpperCase()
|
|
66
|
+
.replace(/[^A-Z0-9]+/g, '_')
|
|
67
|
+
.replace(/^_+|_+$/g, '')
|
|
68
|
+
.replace(/^(\d)/, '_$1');
|
|
69
|
+
}
|
|
70
|
+
export function slugify(name) {
|
|
71
|
+
return name
|
|
72
|
+
.toLowerCase()
|
|
73
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
74
|
+
.replace(/^-+|-+$/g, '');
|
|
75
|
+
}
|
|
76
|
+
const IMPORTABLE_FIELD_TYPES = new Set([
|
|
77
|
+
'CONCEALED', 'concealed',
|
|
78
|
+
'STRING', 'string', 'text', 'TEXT',
|
|
79
|
+
'URL', 'url',
|
|
80
|
+
]);
|
|
81
|
+
const SKIP_FIELD_LABELS = new Set(['username', 'notesPlain', 'notes']);
|
|
82
|
+
function pickBestField(fields) {
|
|
83
|
+
const dominated = fields.filter((f) => IMPORTABLE_FIELD_TYPES.has(f.type) &&
|
|
84
|
+
f.value &&
|
|
85
|
+
!SKIP_FIELD_LABELS.has(f.label?.toLowerCase() || ''));
|
|
86
|
+
if (dominated.length === 0)
|
|
87
|
+
return null;
|
|
88
|
+
// Prefer concealed fields (credentials/passwords)
|
|
89
|
+
const concealed = dominated.find((f) => f.type.toLowerCase() === 'concealed');
|
|
90
|
+
if (concealed)
|
|
91
|
+
return concealed;
|
|
92
|
+
// Then prefer fields labeled credential/password/secret/key/token
|
|
93
|
+
const secretLabels = ['credential', 'password', 'secret', 'key', 'token', 'api_key', 'apikey'];
|
|
94
|
+
const labeled = dominated.find((f) => secretLabels.includes(f.label?.toLowerCase() || ''));
|
|
95
|
+
if (labeled)
|
|
96
|
+
return labeled;
|
|
97
|
+
// Fall back to first importable field
|
|
98
|
+
return dominated[0];
|
|
99
|
+
}
|
|
100
|
+
export function extractSecrets(items, vaultName) {
|
|
101
|
+
const secrets = [];
|
|
102
|
+
const skipped = [];
|
|
103
|
+
for (const summary of items) {
|
|
104
|
+
let item;
|
|
105
|
+
try {
|
|
106
|
+
item = getItem(summary.id, vaultName);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
skipped.push({
|
|
110
|
+
itemTitle: summary.title,
|
|
111
|
+
fieldLabel: '*',
|
|
112
|
+
reason: err.message,
|
|
113
|
+
});
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const field = pickBestField(item.fields || []);
|
|
117
|
+
if (!field) {
|
|
118
|
+
skipped.push({
|
|
119
|
+
itemTitle: item.title,
|
|
120
|
+
fieldLabel: '*',
|
|
121
|
+
reason: 'no importable fields',
|
|
122
|
+
});
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (field.value.includes('\n')) {
|
|
126
|
+
skipped.push({
|
|
127
|
+
itemTitle: item.title,
|
|
128
|
+
fieldLabel: field.label,
|
|
129
|
+
reason: 'contains newlines (keychain limitation)',
|
|
130
|
+
});
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const envKey = toEnvKey(item.title);
|
|
134
|
+
secrets.push({
|
|
135
|
+
envKey,
|
|
136
|
+
itemTitle: item.title,
|
|
137
|
+
fieldLabel: field.label,
|
|
138
|
+
value: field.value,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return { secrets, skipped };
|
|
142
|
+
}
|
|
143
|
+
export function buildPasswordItemTemplate(title, value) {
|
|
144
|
+
return {
|
|
145
|
+
title,
|
|
146
|
+
category: 'PASSWORD',
|
|
147
|
+
tags: ['agents-cli'],
|
|
148
|
+
fields: [
|
|
149
|
+
{ id: 'password', type: 'CONCEALED', purpose: 'PASSWORD', label: 'password', value },
|
|
150
|
+
],
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
export function itemExistsByTitle(title, vaultName) {
|
|
154
|
+
const result = runOp(['item', 'get', title, '--vault', vaultName, '--format=json']);
|
|
155
|
+
if (result.ok)
|
|
156
|
+
return true;
|
|
157
|
+
if (/isn't an item|not found|no item found/i.test(result.error))
|
|
158
|
+
return false;
|
|
159
|
+
throw new Error(result.error);
|
|
160
|
+
}
|
|
161
|
+
export function deleteItemByTitle(title, vaultName) {
|
|
162
|
+
const result = runOp(['item', 'delete', title, '--vault', vaultName]);
|
|
163
|
+
if (!result.ok)
|
|
164
|
+
throw new Error(result.error);
|
|
165
|
+
}
|
|
166
|
+
export function createPasswordItem(title, value, vaultName) {
|
|
167
|
+
// op item create reads stdin templates only from a real pipe; spawnSync's
|
|
168
|
+
// input plumbing is detected as empty and op silently ignores the template.
|
|
169
|
+
// The supported alternative is --template <file>, which works reliably.
|
|
170
|
+
const template = JSON.stringify(buildPasswordItemTemplate(title, value));
|
|
171
|
+
const tmpFile = path.join(os.tmpdir(), `agents-op-tpl-${process.pid}-${Date.now()}.json`);
|
|
172
|
+
fs.writeFileSync(tmpFile, template, { mode: 0o600 });
|
|
173
|
+
try {
|
|
174
|
+
const result = runOp(['item', 'create', '--template', tmpFile, '--vault', vaultName]);
|
|
175
|
+
if (!result.ok)
|
|
176
|
+
throw new Error(result.error);
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
try {
|
|
180
|
+
fs.unlinkSync(tmpFile);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// best-effort cleanup
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve base + name while preventing path-traversal attacks.
|
|
3
|
+
* Rejects path separators, null bytes, '.' and '..', and any resolved path
|
|
4
|
+
* that escapes the base directory. Dot-prefixed names like '.env.example'
|
|
5
|
+
* are allowed — actual traversal is caught by the containment check below.
|
|
6
|
+
* Allows spaces, unicode, and other common filename characters.
|
|
7
|
+
*/
|
|
8
|
+
export declare function safeJoin(base: string, name: string): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve base + name while preventing path-traversal attacks.
|
|
4
|
+
* Rejects path separators, null bytes, '.' and '..', and any resolved path
|
|
5
|
+
* that escapes the base directory. Dot-prefixed names like '.env.example'
|
|
6
|
+
* are allowed — actual traversal is caught by the containment check below.
|
|
7
|
+
* Allows spaces, unicode, and other common filename characters.
|
|
8
|
+
*/
|
|
9
|
+
export function safeJoin(base, name) {
|
|
10
|
+
if (!name ||
|
|
11
|
+
name === '.' || name === '..' ||
|
|
12
|
+
/[\/\\\x00]/.test(name) ||
|
|
13
|
+
name.length > 255) {
|
|
14
|
+
throw new Error(`Invalid name: ${name}`);
|
|
15
|
+
}
|
|
16
|
+
const resolved = path.resolve(base, name);
|
|
17
|
+
if (!resolved.startsWith(path.resolve(base) + path.sep))
|
|
18
|
+
throw new Error(`Path escape: ${name}`);
|
|
19
|
+
return resolved;
|
|
20
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { AgentId, PermissionSet, InstalledPermission, ClaudePermissions, OpenCodePermissions, CodexPermissions } from './types.js';
|
|
2
|
+
/** Agents that support the permissions subsystem. */
|
|
2
3
|
export declare const PERMISSIONS_CAPABLE_AGENTS: AgentId[];
|
|
4
|
+
/** Filename used for Codex Starlark deny-rules generated from permission groups. */
|
|
3
5
|
export declare const CODEX_RULES_FILENAME = "agents-deny.rules";
|
|
4
6
|
/**
|
|
5
7
|
* Convert canonical deny rules to Codex Starlark .rules format.
|
|
6
|
-
* E.g. "Bash(git reset:*)"
|
|
8
|
+
* E.g. "Bash(git reset:*)" -> prefix_rule(pattern=["git", "reset"], decision="forbidden")
|
|
7
9
|
*/
|
|
8
10
|
export declare function convertDenyToCodexRules(deny: string[]): string | null;
|
|
9
11
|
/**
|
|
@@ -39,6 +41,27 @@ export declare function discoverPermissionGroups(): PermissionGroupInfo[];
|
|
|
39
41
|
* Get total rule count across all permission groups.
|
|
40
42
|
*/
|
|
41
43
|
export declare function getTotalPermissionRuleCount(): number;
|
|
44
|
+
/**
|
|
45
|
+
* A permission set recipe — names a set and lists which groups it composes.
|
|
46
|
+
* Lives at ~/.agents/permissions/sets/<name>.yaml.
|
|
47
|
+
*/
|
|
48
|
+
export interface PermissionSetRecipe {
|
|
49
|
+
name: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
includes: string[];
|
|
52
|
+
}
|
|
53
|
+
/** Env var that selects which set recipe to apply at sync time. */
|
|
54
|
+
export declare const PERMISSION_SET_ENV_VAR = "AGENTS_PERMISSION_SET";
|
|
55
|
+
/**
|
|
56
|
+
* Read a permission set recipe by name from ~/.agents/permissions/sets/.
|
|
57
|
+
* Returns null if the recipe file is missing or malformed.
|
|
58
|
+
*/
|
|
59
|
+
export declare function readPermissionSetRecipe(name: string): PermissionSetRecipe | null;
|
|
60
|
+
/**
|
|
61
|
+
* Return the active permission set name from AGENTS_PERMISSION_SET env var,
|
|
62
|
+
* or null if unset. Caller decides the default behavior when null.
|
|
63
|
+
*/
|
|
64
|
+
export declare function getActivePermissionSetName(): string | null;
|
|
42
65
|
/**
|
|
43
66
|
* Build a PermissionSet from selected groups.
|
|
44
67
|
* Concatenates allow/deny rules from each group.
|
|
@@ -201,4 +224,3 @@ export declare function saveDefaultPermissionSet(set: PermissionSet): {
|
|
|
201
224
|
success: boolean;
|
|
202
225
|
error?: string;
|
|
203
226
|
};
|
|
204
|
-
//# sourceMappingURL=permissions.d.ts.map
|
package/dist/lib/permissions.js
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission management for AI coding agents.
|
|
3
|
+
*
|
|
4
|
+
* Provides a canonical permission format (PermissionSet with allow/deny rules)
|
|
5
|
+
* and converters to/from each agent's native format (Claude settings.json,
|
|
6
|
+
* OpenCode opencode.jsonc, Codex config.toml + .rules). Handles discovery,
|
|
7
|
+
* installation, removal, and merging of permission groups stored in
|
|
8
|
+
* ~/.agents/permissions/groups/.
|
|
9
|
+
*/
|
|
1
10
|
import * as fs from 'fs';
|
|
2
11
|
import * as path from 'path';
|
|
3
12
|
import * as os from 'os';
|
|
4
13
|
import * as yaml from 'yaml';
|
|
5
14
|
import * as TOML from 'smol-toml';
|
|
6
|
-
import { getPermissionsDir, ensureAgentsDir } from './state.js';
|
|
15
|
+
import { getPermissionsDir, getUserPermissionsDir, ensureAgentsDir } from './state.js';
|
|
16
|
+
import { safeJoin } from './paths.js';
|
|
7
17
|
const HOME = os.homedir();
|
|
8
|
-
|
|
18
|
+
/** Agents that support the permissions subsystem. */
|
|
9
19
|
export const PERMISSIONS_CAPABLE_AGENTS = ['claude', 'codex', 'opencode'];
|
|
10
|
-
|
|
20
|
+
/** Filename used for Codex Starlark deny-rules generated from permission groups. */
|
|
11
21
|
export const CODEX_RULES_FILENAME = 'agents-deny.rules';
|
|
12
22
|
/**
|
|
13
23
|
* Convert canonical deny rules to Codex Starlark .rules format.
|
|
14
|
-
* E.g. "Bash(git reset:*)"
|
|
24
|
+
* E.g. "Bash(git reset:*)" -> prefix_rule(pattern=["git", "reset"], decision="forbidden")
|
|
15
25
|
*/
|
|
16
26
|
export function convertDenyToCodexRules(deny) {
|
|
17
27
|
const rules = [];
|
|
@@ -24,7 +34,7 @@ export function convertDenyToCodexRules(deny) {
|
|
|
24
34
|
if (!command)
|
|
25
35
|
continue;
|
|
26
36
|
const parts = command.split(/\s+/);
|
|
27
|
-
const patternStr = parts.map(p =>
|
|
37
|
+
const patternStr = parts.map(p => JSON.stringify(p)).join(', ');
|
|
28
38
|
rules.push(`prefix_rule(\n pattern = [${patternStr}],\n decision = "forbidden",\n)`);
|
|
29
39
|
}
|
|
30
40
|
if (rules.length === 0)
|
|
@@ -35,7 +45,7 @@ export function convertDenyToCodexRules(deny) {
|
|
|
35
45
|
* Ensure central permissions directory exists.
|
|
36
46
|
*/
|
|
37
47
|
export function ensurePermissionsDir() {
|
|
38
|
-
const dir =
|
|
48
|
+
const dir = getUserPermissionsDir();
|
|
39
49
|
if (!fs.existsSync(dir)) {
|
|
40
50
|
fs.mkdirSync(dir, { recursive: true });
|
|
41
51
|
}
|
|
@@ -108,38 +118,37 @@ export function discoverPermissionsFromRepo(repoPath) {
|
|
|
108
118
|
* Returns groups with their rule counts.
|
|
109
119
|
*/
|
|
110
120
|
export function discoverPermissionGroups() {
|
|
111
|
-
const
|
|
112
|
-
if (!fs.existsSync(groupsDir)) {
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
121
|
+
const seen = new Set();
|
|
115
122
|
const groups = [];
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
123
|
+
// Search user dir first, then system (user wins on name collision)
|
|
124
|
+
for (const baseDir of [getUserPermissionsDir(), getPermissionsDir()]) {
|
|
125
|
+
const groupsDir = path.join(baseDir, 'groups');
|
|
126
|
+
if (!fs.existsSync(groupsDir))
|
|
127
|
+
continue;
|
|
128
|
+
try {
|
|
129
|
+
const entries = fs.readdirSync(groupsDir, { withFileTypes: true });
|
|
130
|
+
for (const entry of entries) {
|
|
131
|
+
if (!entry.isFile())
|
|
132
|
+
continue;
|
|
133
|
+
if (!entry.name.endsWith('.yml') && !entry.name.endsWith('.yaml'))
|
|
134
|
+
continue;
|
|
135
|
+
const name = entry.name.replace(/\.(yaml|yml)$/, '');
|
|
136
|
+
if (seen.has(name))
|
|
137
|
+
continue;
|
|
138
|
+
seen.add(name);
|
|
139
|
+
const filePath = path.join(groupsDir, entry.name);
|
|
140
|
+
let ruleCount = 0;
|
|
141
|
+
try {
|
|
142
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
143
|
+
const matches = content.match(/^\s*-\s*"/gm);
|
|
144
|
+
ruleCount = matches ? matches.length : 0;
|
|
145
|
+
}
|
|
146
|
+
catch { /* Skip files we can't read */ }
|
|
147
|
+
groups.push({ name, ruleCount, path: filePath });
|
|
135
148
|
}
|
|
136
|
-
groups.push({ name, ruleCount, path: filePath });
|
|
137
149
|
}
|
|
150
|
+
catch { /* Skip inaccessible directory */ }
|
|
138
151
|
}
|
|
139
|
-
catch {
|
|
140
|
-
// Skip inaccessible directory
|
|
141
|
-
}
|
|
142
|
-
// Sort by name (which sorts by numeric prefix)
|
|
143
152
|
return groups.sort((a, b) => a.name.localeCompare(b.name));
|
|
144
153
|
}
|
|
145
154
|
/**
|
|
@@ -149,6 +158,45 @@ export function getTotalPermissionRuleCount() {
|
|
|
149
158
|
const groups = discoverPermissionGroups();
|
|
150
159
|
return groups.reduce((sum, g) => sum + g.ruleCount, 0);
|
|
151
160
|
}
|
|
161
|
+
/** Env var that selects which set recipe to apply at sync time. */
|
|
162
|
+
export const PERMISSION_SET_ENV_VAR = 'AGENTS_PERMISSION_SET';
|
|
163
|
+
/**
|
|
164
|
+
* Read a permission set recipe by name from ~/.agents/permissions/sets/.
|
|
165
|
+
* Returns null if the recipe file is missing or malformed.
|
|
166
|
+
*/
|
|
167
|
+
export function readPermissionSetRecipe(name) {
|
|
168
|
+
const setsDir = path.join(getPermissionsDir(), 'sets');
|
|
169
|
+
for (const ext of ['.yaml', '.yml']) {
|
|
170
|
+
const filePath = safeJoin(setsDir, name + ext);
|
|
171
|
+
if (!fs.existsSync(filePath))
|
|
172
|
+
continue;
|
|
173
|
+
try {
|
|
174
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
175
|
+
const parsed = yaml.parse(content);
|
|
176
|
+
if (!parsed || typeof parsed !== 'object')
|
|
177
|
+
return null;
|
|
178
|
+
if (!Array.isArray(parsed.includes))
|
|
179
|
+
return null;
|
|
180
|
+
return {
|
|
181
|
+
name: parsed.name || name,
|
|
182
|
+
description: parsed.description,
|
|
183
|
+
includes: parsed.includes.filter((v) => typeof v === 'string'),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Return the active permission set name from AGENTS_PERMISSION_SET env var,
|
|
194
|
+
* or null if unset. Caller decides the default behavior when null.
|
|
195
|
+
*/
|
|
196
|
+
export function getActivePermissionSetName() {
|
|
197
|
+
const v = process.env[PERMISSION_SET_ENV_VAR];
|
|
198
|
+
return v && v.trim() ? v.trim() : null;
|
|
199
|
+
}
|
|
152
200
|
/**
|
|
153
201
|
* Build a PermissionSet from selected groups.
|
|
154
202
|
* Concatenates allow/deny rules from each group.
|
|
@@ -157,18 +205,25 @@ export function getTotalPermissionRuleCount() {
|
|
|
157
205
|
* permission files often contain unescaped nested quotes that break YAML.
|
|
158
206
|
*/
|
|
159
207
|
export function buildPermissionsFromGroups(groupNames) {
|
|
160
|
-
const groupsDir = path.join(getPermissionsDir(), 'groups');
|
|
161
208
|
const allAllow = [];
|
|
162
209
|
const allDeny = [];
|
|
163
210
|
for (const groupName of groupNames) {
|
|
164
|
-
//
|
|
165
|
-
let filePath =
|
|
166
|
-
|
|
167
|
-
|
|
211
|
+
// Search user dir first, then system dir
|
|
212
|
+
let filePath = null;
|
|
213
|
+
for (const baseDir of [getUserPermissionsDir(), getPermissionsDir()]) {
|
|
214
|
+
const groupsDir = path.join(baseDir, 'groups');
|
|
215
|
+
for (const ext of ['.yaml', '.yml']) {
|
|
216
|
+
const candidate = safeJoin(groupsDir, `${groupName}${ext}`);
|
|
217
|
+
if (fs.existsSync(candidate)) {
|
|
218
|
+
filePath = candidate;
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (filePath)
|
|
223
|
+
break;
|
|
168
224
|
}
|
|
169
|
-
if (!
|
|
225
|
+
if (!filePath)
|
|
170
226
|
continue;
|
|
171
|
-
}
|
|
172
227
|
try {
|
|
173
228
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
174
229
|
// Extract rules using line-by-line regex (more robust than YAML parsing)
|
|
@@ -241,7 +296,7 @@ export function listInstalledPermissions() {
|
|
|
241
296
|
export function getPermissionSet(name) {
|
|
242
297
|
const dir = getPermissionsDir();
|
|
243
298
|
for (const ext of ['.yml', '.yaml']) {
|
|
244
|
-
const filePath =
|
|
299
|
+
const filePath = safeJoin(dir, name + ext);
|
|
245
300
|
if (fs.existsSync(filePath)) {
|
|
246
301
|
const set = parsePermissionSet(filePath);
|
|
247
302
|
if (set) {
|
|
@@ -260,7 +315,7 @@ export function installPermissionSet(sourcePath, name) {
|
|
|
260
315
|
if (!set) {
|
|
261
316
|
return { success: false, error: 'Invalid permission file' };
|
|
262
317
|
}
|
|
263
|
-
const targetPath =
|
|
318
|
+
const targetPath = safeJoin(getPermissionsDir(), name + '.yml');
|
|
264
319
|
try {
|
|
265
320
|
fs.copyFileSync(sourcePath, targetPath);
|
|
266
321
|
return { success: true };
|
|
@@ -275,7 +330,7 @@ export function installPermissionSet(sourcePath, name) {
|
|
|
275
330
|
export function removePermissionSet(name) {
|
|
276
331
|
const dir = getPermissionsDir();
|
|
277
332
|
for (const ext of ['.yml', '.yaml']) {
|
|
278
|
-
const filePath =
|
|
333
|
+
const filePath = safeJoin(dir, name + ext);
|
|
279
334
|
if (fs.existsSync(filePath)) {
|
|
280
335
|
try {
|
|
281
336
|
fs.unlinkSync(filePath);
|
|
@@ -316,6 +371,8 @@ function parseCanonicalPattern(permission) {
|
|
|
316
371
|
return null;
|
|
317
372
|
return { tool: match[1].toLowerCase(), pattern: match[2] };
|
|
318
373
|
}
|
|
374
|
+
/** Blanket-Bash canonical forms that mean "allow any bash command". */
|
|
375
|
+
const BLANKET_BASH_FORMS = new Set(['Bash', 'Bash(*)', 'Bash(**)']);
|
|
319
376
|
/**
|
|
320
377
|
* Convert canonical permission set to OpenCode format.
|
|
321
378
|
* OpenCode uses: { permission: { bash: { "git *": "allow", "rm *": "deny" } } }
|
|
@@ -324,6 +381,12 @@ export function convertToOpenCodeFormat(set) {
|
|
|
324
381
|
const bashPermissions = {};
|
|
325
382
|
// Process allow list
|
|
326
383
|
for (const perm of set.allow) {
|
|
384
|
+
if (BLANKET_BASH_FORMS.has(perm)) {
|
|
385
|
+
// Bare "Bash" has no parens so parseCanonicalPattern returns null;
|
|
386
|
+
// normalize all three blanket forms to "*".
|
|
387
|
+
bashPermissions['*'] = 'allow';
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
327
390
|
const parsed = parseCanonicalPattern(perm);
|
|
328
391
|
if (parsed && parsed.tool === 'bash') {
|
|
329
392
|
bashPermissions[parsed.pattern] = 'allow';
|
|
@@ -350,10 +413,16 @@ export function convertToOpenCodeFormat(set) {
|
|
|
350
413
|
*/
|
|
351
414
|
export function convertToCodexFormat(set, cwd) {
|
|
352
415
|
const result = {};
|
|
353
|
-
// Check for broad bash permissions -> suggest full-auto
|
|
416
|
+
// Check for broad bash permissions -> suggest full-auto.
|
|
417
|
+
// Treat the bare blanket form "Bash" the same as "Bash(*)" / "Bash(**)";
|
|
418
|
+
// parseCanonicalPattern requires parens so "Bash" alone wouldn't match
|
|
419
|
+
// otherwise — the difference determines whether a pod runs unattended
|
|
420
|
+
// (approval_policy: 'never') or stalls on interactive approvals.
|
|
354
421
|
const hasBroadBash = set.allow.some((p) => {
|
|
422
|
+
if (BLANKET_BASH_FORMS.has(p))
|
|
423
|
+
return true;
|
|
355
424
|
const parsed = parseCanonicalPattern(p);
|
|
356
|
-
return parsed && parsed.tool === 'bash' && (parsed.pattern === '*' || parsed.pattern === '**');
|
|
425
|
+
return parsed !== null && parsed.tool === 'bash' && (parsed.pattern === '*' || parsed.pattern === '**');
|
|
357
426
|
});
|
|
358
427
|
if (hasBroadBash) {
|
|
359
428
|
result.approval_policy = 'never';
|
|
@@ -946,7 +1015,7 @@ export function exportPermissionsFromPath(filePath) {
|
|
|
946
1015
|
*/
|
|
947
1016
|
export function savePermissionSet(set) {
|
|
948
1017
|
ensurePermissionsDir();
|
|
949
|
-
const filePath =
|
|
1018
|
+
const filePath = safeJoin(getUserPermissionsDir(), set.name + '.yml');
|
|
950
1019
|
try {
|
|
951
1020
|
const content = yaml.stringify({
|
|
952
1021
|
name: set.name,
|
|
@@ -961,6 +1030,7 @@ export function savePermissionSet(set) {
|
|
|
961
1030
|
return { success: false, error: err.message };
|
|
962
1031
|
}
|
|
963
1032
|
}
|
|
1033
|
+
/** Name used for the default permission set in central storage. */
|
|
964
1034
|
const DEFAULT_PERMISSION_SET_NAME = 'default';
|
|
965
1035
|
/**
|
|
966
1036
|
* Get the default permission set from central storage.
|
|
@@ -1019,4 +1089,3 @@ export function saveDefaultPermissionSet(set) {
|
|
|
1019
1089
|
set.name = DEFAULT_PERMISSION_SET_NAME;
|
|
1020
1090
|
return savePermissionSet(set);
|
|
1021
1091
|
}
|
|
1022
|
-
//# sourceMappingURL=permissions.js.map
|
package/dist/lib/picker.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive fuzzy-filter picker built on @inquirer/core.
|
|
3
|
+
*
|
|
4
|
+
* Provides a searchable, paginated list UI with optional preview pane
|
|
5
|
+
* for selecting items in the terminal. Used by session picker, command
|
|
6
|
+
* picker, and other interactive selection flows.
|
|
7
|
+
*/
|
|
8
|
+
/** Configuration for the interactive picker prompt. */
|
|
1
9
|
export interface PickerConfig<T> {
|
|
2
10
|
message: string;
|
|
3
11
|
items: T[];
|
|
@@ -10,8 +18,9 @@ export interface PickerConfig<T> {
|
|
|
10
18
|
emptyMessage?: string;
|
|
11
19
|
enterHint?: string;
|
|
12
20
|
}
|
|
21
|
+
/** The result returned when the user selects an item. */
|
|
13
22
|
export interface PickedItem<T> {
|
|
14
23
|
item: T;
|
|
15
24
|
}
|
|
25
|
+
/** Show an interactive fuzzy-filter picker and return the selected item, or null on cancel. */
|
|
16
26
|
export declare function itemPicker<T>(config: PickerConfig<T>): Promise<PickedItem<T> | null>;
|
|
17
|
-
//# sourceMappingURL=picker.d.ts.map
|
package/dist/lib/picker.js
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive fuzzy-filter picker built on @inquirer/core.
|
|
3
|
+
*
|
|
4
|
+
* Provides a searchable, paginated list UI with optional preview pane
|
|
5
|
+
* for selecting items in the terminal. Used by session picker, command
|
|
6
|
+
* picker, and other interactive selection flows.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Custom inquirer prompt for searchable, scrollable selection lists.
|
|
10
|
+
*
|
|
11
|
+
* Extends @inquirer/core to support type-ahead filtering, column-aligned
|
|
12
|
+
* display, and keyboard navigation. Used by sessions, teams, and other
|
|
13
|
+
* interactive pickers throughout the CLI.
|
|
14
|
+
*/
|
|
1
15
|
import { createPrompt, useState, useKeypress, useEffect, useMemo, usePagination, usePrefix, makeTheme, isEnterKey, isUpKey, isDownKey, isSpaceKey, Separator, } from '@inquirer/core';
|
|
2
16
|
import chalk from 'chalk';
|
|
17
|
+
/** Show an interactive fuzzy-filter picker and return the selected item, or null on cancel. */
|
|
3
18
|
export function itemPicker(config) {
|
|
4
19
|
const prompt = createPrompt((cfg, done) => {
|
|
5
20
|
const theme = makeTheme({});
|
|
@@ -92,4 +107,3 @@ export function itemPicker(config) {
|
|
|
92
107
|
});
|
|
93
108
|
return prompt(config);
|
|
94
109
|
}
|
|
95
|
-
//# sourceMappingURL=picker.js.map
|
package/dist/lib/plugins.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin discovery, validation, and syncing.
|
|
3
|
+
*
|
|
4
|
+
* Plugins are bundles in ~/.agents/plugins/ that package skills, hooks, and
|
|
5
|
+
* scripts under a single manifest (plugin.yaml). This module discovers plugins,
|
|
6
|
+
* validates their manifests, and syncs their contents into agent version homes.
|
|
7
|
+
*/
|
|
1
8
|
import type { AgentId, DiscoveredPlugin, PluginManifest } from './types.js';
|
|
2
9
|
/**
|
|
3
10
|
* Discover all plugins in ~/.agents/plugins/.
|
|
@@ -70,4 +77,3 @@ export declare function removePluginFromVersion(pluginName: string, pluginRoot:
|
|
|
70
77
|
* where the plugin no longer exists in ~/.agents/plugins/.
|
|
71
78
|
*/
|
|
72
79
|
export declare function cleanOrphanedPluginSkills(agent: AgentId, versionHome: string, activePluginNames: Set<string>): string[];
|
|
73
|
-
//# sourceMappingURL=plugins.d.ts.map
|
package/dist/lib/plugins.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin discovery, validation, and syncing.
|
|
3
|
+
*
|
|
4
|
+
* Plugins are bundles in ~/.agents/plugins/ that package skills, hooks, and
|
|
5
|
+
* scripts under a single manifest (plugin.yaml). This module discovers plugins,
|
|
6
|
+
* validates their manifests, and syncs their contents into agent version homes.
|
|
7
|
+
*/
|
|
1
8
|
import * as fs from 'fs';
|
|
2
9
|
import * as path from 'path';
|
|
3
10
|
import { getPluginsDir } from './state.js';
|
|
@@ -46,6 +53,9 @@ export function loadPluginManifest(pluginRoot) {
|
|
|
46
53
|
const parsed = JSON.parse(content);
|
|
47
54
|
if (!parsed.name || !parsed.version)
|
|
48
55
|
return null;
|
|
56
|
+
if (/[/\\]/.test(parsed.name) || parsed.name.includes('..') || parsed.name.includes('\0')) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
49
59
|
return parsed;
|
|
50
60
|
}
|
|
51
61
|
catch {
|
|
@@ -546,4 +556,3 @@ export function cleanOrphanedPluginSkills(agent, versionHome, activePluginNames)
|
|
|
546
556
|
}
|
|
547
557
|
return removed;
|
|
548
558
|
}
|
|
549
|
-
//# sourceMappingURL=plugins.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in profile presets for popular model providers.
|
|
3
|
+
*
|
|
4
|
+
* Each preset bundles a host CLI, API base URL, default model, and provider
|
|
5
|
+
* name so users can `agents profiles add kimi` without manual configuration.
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentId } from './types.js';
|
|
8
|
+
/** A pre-configured profile template for a model provider. */
|
|
9
|
+
export interface Preset {
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
provider: string;
|
|
13
|
+
host: AgentId;
|
|
14
|
+
env: Record<string, string>;
|
|
15
|
+
authEnvVar: string;
|
|
16
|
+
signupUrl?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const PRESETS: Preset[];
|
|
19
|
+
/** Look up a preset by name (case-sensitive). */
|
|
20
|
+
export declare function getPreset(name: string): Preset | undefined;
|
|
21
|
+
/** Return a copy of all available presets. */
|
|
22
|
+
export declare function listPresets(): Preset[];
|
|
23
|
+
/** Return the unique set of provider names across all presets. */
|
|
24
|
+
export declare function listProviders(): string[];
|