@armadra/agent 0.5.1 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +203 -304
- package/CHANGELOG.zh-CN.md +462 -0
- package/README.md +408 -364
- package/README.zh-CN.md +705 -0
- package/dist/agent/session-plan.js +2 -2
- package/dist/agent/session-state.d.ts +3 -0
- package/dist/agent/session-state.js +20 -0
- package/dist/agent/session-subagent.d.ts +15 -1
- package/dist/agent/session-subagent.js +26 -3
- package/dist/agent/session-telemetry.d.ts +16 -2
- package/dist/agent/session-telemetry.js +29 -7
- package/dist/agent/session-tools.js +5 -2
- package/dist/agent/session-trace-writer.d.ts +27 -0
- package/dist/agent/session-trace-writer.js +253 -0
- package/dist/agent/session.d.ts +2 -0
- package/dist/agent/session.js +12 -0
- package/dist/agent/subagent-direct.d.ts +20 -0
- package/dist/agent/subagent-direct.js +76 -0
- package/dist/agent/subagent-registry.d.ts +8 -1
- package/dist/agent/subagent-registry.js +28 -1
- package/dist/agent/system-prompt.d.ts +3 -1
- package/dist/agent/system-prompt.js +3 -0
- package/dist/agent/tool-runner.d.ts +2 -1
- package/dist/agent/tool-runner.js +5 -4
- package/dist/agent/types-w6.d.ts +39 -0
- package/dist/agent/types-w6.js +4 -0
- package/dist/agent/types.d.ts +5 -2
- package/dist/agents/external.js +1 -1
- package/dist/agents/task-record.d.ts +74 -1
- package/dist/agents/task-record.js +100 -0
- package/dist/ai/apis/cache-params.js +2 -1
- package/dist/ai/apis/chatgpt-backend.d.ts +52 -0
- package/dist/ai/apis/chatgpt-backend.js +224 -0
- package/dist/ai/apis/chatgpt-rate-limits.d.ts +26 -0
- package/dist/ai/apis/chatgpt-rate-limits.js +91 -0
- package/dist/ai/apis/openai-responses-request.d.ts +2 -1
- package/dist/ai/apis/openai-responses-request.js +8 -2
- package/dist/ai/apis/openai-responses.d.ts +2 -0
- package/dist/ai/apis/openai-responses.js +51 -16
- package/dist/ai/overflow.d.ts +1 -1
- package/dist/ai/overflow.js +10 -7
- package/dist/ai/providers/auth.d.ts +15 -2
- package/dist/ai/providers/auth.js +69 -2
- package/dist/ai/providers/builtin.js +27 -0
- package/dist/ai/providers/catalog-data.js +1 -0
- package/dist/ai/providers/discovered-cache.d.ts +48 -0
- package/dist/ai/providers/discovered-cache.js +102 -0
- package/dist/ai/providers/enrich.js +2 -7
- package/dist/ai/providers/model-visibility.d.ts +33 -0
- package/dist/ai/providers/model-visibility.js +70 -0
- package/dist/ai/providers/models-dev-cache.js +15 -19
- package/dist/ai/providers/models-dev-snapshot.js +8 -7
- package/dist/ai/providers/models-dev.js +5 -15
- package/dist/ai/providers/registry.d.ts +2 -0
- package/dist/ai/providers/registry.js +6 -1
- package/dist/ai/providers/suggest.js +2 -16
- package/dist/ai/types.d.ts +27 -1
- package/dist/auth/chatgpt/backend-client.d.ts +26 -0
- package/dist/auth/chatgpt/backend-client.js +74 -0
- package/dist/auth/chatgpt/claims.d.ts +17 -0
- package/dist/auth/chatgpt/claims.js +46 -0
- package/dist/auth/chatgpt/cli.d.ts +35 -0
- package/dist/auth/chatgpt/cli.js +279 -0
- package/dist/auth/chatgpt/doctor.d.ts +17 -0
- package/dist/auth/chatgpt/doctor.js +36 -0
- package/dist/auth/chatgpt/host-id.d.ts +7 -0
- package/dist/auth/chatgpt/host-id.js +26 -0
- package/dist/auth/chatgpt/login.d.ts +30 -0
- package/dist/auth/chatgpt/login.js +130 -0
- package/dist/auth/chatgpt/presets.d.ts +66 -0
- package/dist/auth/chatgpt/presets.js +120 -0
- package/dist/auth/chatgpt/quota-text.d.ts +13 -0
- package/dist/auth/chatgpt/quota-text.js +36 -0
- package/dist/auth/oauth/browser.d.ts +12 -0
- package/dist/auth/oauth/browser.js +27 -0
- package/dist/auth/oauth/callback-server.d.ts +47 -0
- package/dist/auth/oauth/callback-server.js +147 -0
- package/dist/auth/oauth/flows.d.ts +62 -0
- package/dist/auth/oauth/flows.js +113 -0
- package/dist/auth/oauth/jwt.d.ts +24 -0
- package/dist/auth/oauth/jwt.js +81 -0
- package/dist/auth/oauth/live.d.ts +21 -0
- package/dist/auth/oauth/live.js +25 -0
- package/dist/auth/oauth/oidc.d.ts +26 -0
- package/dist/auth/oauth/oidc.js +72 -0
- package/dist/auth/oauth/pkce.d.ts +15 -0
- package/dist/auth/oauth/pkce.js +20 -0
- package/dist/auth/oauth/refresh.d.ts +35 -0
- package/dist/auth/oauth/refresh.js +129 -0
- package/dist/auth/oauth/token-client.d.ts +33 -0
- package/dist/auth/oauth/token-client.js +121 -0
- package/dist/auth/oauth/token-store.d.ts +23 -0
- package/dist/auth/oauth/token-store.js +125 -0
- package/dist/auth/testing/fake-oauth.d.ts +73 -0
- package/dist/auth/testing/fake-oauth.js +271 -0
- package/dist/auth/testing/refresh-child.d.ts +5 -0
- package/dist/auth/testing/refresh-child.js +16 -0
- package/dist/bundle/ama.cjs +26532 -11045
- package/dist/checkpoints/backend.js +6 -5
- package/dist/checkpoints/restore.js +3 -2
- package/dist/checkpoints/settings.js +2 -1
- package/dist/checkpoints/shadow-git.js +7 -6
- package/dist/checkpoints/shadow-restore.js +3 -2
- package/dist/checkpoints/tracker.js +4 -3
- package/dist/cli/args.d.ts +9 -2
- package/dist/cli/args.js +74 -27
- package/dist/cli/bootstrap.js +53 -31
- package/dist/cli/choice-prompt.js +8 -6
- package/dist/cli/codemode-notice.js +2 -2
- package/dist/cli/compose-agents.js +2 -1
- package/dist/cli/compose-extensions.js +2 -0
- package/dist/cli/compose-memory.d.ts +53 -0
- package/dist/cli/compose-memory.js +127 -0
- package/dist/cli/compose-providers.d.ts +6 -0
- package/dist/cli/compose-providers.js +38 -2
- package/dist/cli/compose-session.d.ts +5 -0
- package/dist/cli/compose-session.js +27 -13
- package/dist/cli/compose-store.d.ts +2 -0
- package/dist/cli/compose-store.js +9 -5
- package/dist/cli/compose.d.ts +2 -0
- package/dist/cli/compose.js +13 -5
- package/dist/cli/default-model.d.ts +0 -2
- package/dist/cli/default-model.js +5 -8
- package/dist/cli/deps.d.ts +5 -1
- package/dist/cli/exit-codes.d.ts +1 -1
- package/dist/cli/exit-codes.js +7 -16
- package/dist/cli/from-prompt.js +3 -2
- package/dist/cli/help-text.d.ts +2 -1
- package/dist/cli/help-text.js +5 -99
- package/dist/cli/main.d.ts +5 -0
- package/dist/cli/main.js +21 -2
- package/dist/cli/proxy.js +14 -9
- package/dist/cli/runtime.d.ts +5 -0
- package/dist/cli/startup-screen.js +20 -27
- package/dist/cli/startup-steps.js +6 -8
- package/dist/cli/subcommands/auth.d.ts +6 -3
- package/dist/cli/subcommands/auth.js +52 -22
- package/dist/cli/subcommands/config-set.d.ts +21 -0
- package/dist/cli/subcommands/config-set.js +145 -0
- package/dist/cli/subcommands/config.d.ts +2 -1
- package/dist/cli/subcommands/config.js +51 -37
- package/dist/cli/subcommands/doctor.d.ts +2 -1
- package/dist/cli/subcommands/doctor.js +97 -58
- package/dist/cli/subcommands/init.d.ts +1 -1
- package/dist/cli/subcommands/init.js +8 -7
- package/dist/cli/subcommands/memory.d.ts +18 -0
- package/dist/cli/subcommands/memory.js +189 -0
- package/dist/cli/subcommands/model-meta.js +11 -9
- package/dist/cli/subcommands/models-cache-probe.js +23 -20
- package/dist/cli/subcommands/models-discover.d.ts +4 -0
- package/dist/cli/subcommands/models-discover.js +60 -21
- package/dist/cli/subcommands/models-enable.d.ts +13 -0
- package/dist/cli/subcommands/models-enable.js +145 -0
- package/dist/cli/subcommands/models.d.ts +3 -1
- package/dist/cli/subcommands/models.js +39 -24
- package/dist/cli/subcommands/probe-runner.js +8 -7
- package/dist/cli/subcommands/providers-list.js +32 -21
- package/dist/cli/subcommands/providers-plan.js +24 -25
- package/dist/cli/subcommands/providers-probe.js +5 -6
- package/dist/cli/subcommands/providers.d.ts +1 -1
- package/dist/cli/subcommands/providers.js +45 -50
- package/dist/cli/subcommands/sessions-export.d.ts +1 -1
- package/dist/cli/subcommands/sessions-export.js +10 -9
- package/dist/cli/subcommands/sessions-search.d.ts +1 -1
- package/dist/cli/subcommands/sessions-search.js +11 -10
- package/dist/cli/subcommands/sessions-trace.d.ts +30 -0
- package/dist/cli/subcommands/sessions-trace.js +156 -0
- package/dist/cli/subcommands/sessions.d.ts +4 -3
- package/dist/cli/subcommands/sessions.js +40 -37
- package/dist/cli/subcommands/stats.d.ts +1 -1
- package/dist/cli/subcommands/stats.js +49 -30
- package/dist/cli/system-prompt-arg.js +3 -2
- package/dist/codemode/capability.js +3 -2
- package/dist/compaction/post-compact.d.ts +1 -0
- package/dist/compaction/post-compact.js +15 -1
- package/dist/compaction/prune-tier.d.ts +1 -1
- package/dist/compaction/prune-tier.js +3 -3
- package/dist/compaction/serialize.js +2 -1
- package/dist/config/auth-file.d.ts +12 -2
- package/dist/config/auth-file.js +32 -10
- package/dist/config/checker.js +12 -11
- package/dist/config/context-files.js +3 -2
- package/dist/config/edit.d.ts +106 -0
- package/dist/config/edit.js +350 -0
- package/dist/config/init.d.ts +4 -3
- package/dist/config/init.js +10 -18
- package/dist/config/json-schema.d.ts +2 -1
- package/dist/config/json-schema.js +102 -69
- package/dist/config/key-docs.d.ts +18 -7
- package/dist/config/key-docs.js +43 -128
- package/dist/config/load.js +7 -6
- package/dist/config/merge.d.ts +4 -1
- package/dist/config/merge.js +42 -22
- package/dist/config/paths.js +6 -5
- package/dist/config/profile.d.ts +5 -1
- package/dist/config/profile.js +7 -2
- package/dist/config/schema-w5.js +12 -4
- package/dist/config/schema-w6.d.ts +19 -0
- package/dist/config/schema-w6.js +115 -0
- package/dist/config/schema.js +34 -20
- package/dist/config/settings-registry.d.ts +81 -0
- package/dist/config/settings-registry.js +185 -0
- package/dist/config/types-w5.d.ts +7 -0
- package/dist/config/types-w5.js +2 -0
- package/dist/config/types-w6.d.ts +109 -0
- package/dist/config/types-w6.js +19 -0
- package/dist/config/types.d.ts +11 -8
- package/dist/config/types.js +1 -0
- package/dist/drivers/acp/client.js +1 -1
- package/dist/drivers/acp/driver.js +13 -8
- package/dist/drivers/agents.js +4 -3
- package/dist/drivers/base.js +3 -2
- package/dist/drivers/host-runners.js +2 -1
- package/dist/drivers/native/claude-stream.js +12 -11
- package/dist/drivers/native/codex-app-server.js +17 -12
- package/dist/drivers/native/oneshot.js +8 -7
- package/dist/drivers/pool.js +1 -1
- package/dist/drivers/runner.d.ts +3 -1
- package/dist/drivers/runner.js +68 -20
- package/dist/drivers/turn.js +1 -1
- package/dist/hooks/config.js +3 -2
- package/dist/hooks/protocol.js +18 -12
- package/dist/host/api-impl.js +11 -10
- package/dist/host/loader.js +9 -8
- package/dist/host/types.d.ts +3 -0
- package/dist/i18n/catalog.d.ts +2209 -0
- package/dist/i18n/catalog.js +72 -0
- package/dist/i18n/format.d.ts +21 -0
- package/dist/i18n/format.js +58 -0
- package/dist/i18n/index.d.ts +58 -0
- package/dist/i18n/index.js +72 -0
- package/dist/i18n/messages/agents.d.ts +84 -0
- package/dist/i18n/messages/agents.js +85 -0
- package/dist/i18n/messages/approval.d.ts +99 -0
- package/dist/i18n/messages/approval.js +100 -0
- package/dist/i18n/messages/auth.d.ts +189 -0
- package/dist/i18n/messages/auth.js +201 -0
- package/dist/i18n/messages/cli-args.d.ts +46 -0
- package/dist/i18n/messages/cli-args.js +46 -0
- package/dist/i18n/messages/cli-help.d.ts +12 -0
- package/dist/i18n/messages/cli-help.js +248 -0
- package/dist/i18n/messages/cli.d.ts +336 -0
- package/dist/i18n/messages/cli.js +311 -0
- package/dist/i18n/messages/config-keys.d.ts +293 -0
- package/dist/i18n/messages/config-keys.js +296 -0
- package/dist/i18n/messages/config.d.ts +508 -0
- package/dist/i18n/messages/config.js +241 -0
- package/dist/i18n/messages/drivers.d.ts +123 -0
- package/dist/i18n/messages/drivers.js +124 -0
- package/dist/i18n/messages/errors.d.ts +83 -0
- package/dist/i18n/messages/errors.js +171 -0
- package/dist/i18n/messages/interactive-line.d.ts +61 -0
- package/dist/i18n/messages/interactive-line.js +69 -0
- package/dist/i18n/messages/interactive-startup.d.ts +99 -0
- package/dist/i18n/messages/interactive-startup.js +100 -0
- package/dist/i18n/messages/interactive-view.d.ts +140 -0
- package/dist/i18n/messages/interactive-view.js +141 -0
- package/dist/i18n/messages/interactive.d.ts +489 -0
- package/dist/i18n/messages/interactive.js +248 -0
- package/dist/i18n/messages/memory.d.ts +123 -0
- package/dist/i18n/messages/memory.js +128 -0
- package/dist/i18n/messages/panels.d.ts +233 -0
- package/dist/i18n/messages/panels.js +232 -0
- package/dist/i18n/messages/permissions.d.ts +126 -0
- package/dist/i18n/messages/permissions.js +151 -0
- package/dist/i18n/messages/plan.d.ts +123 -0
- package/dist/i18n/messages/plan.js +124 -0
- package/dist/i18n/messages/print.d.ts +86 -0
- package/dist/i18n/messages/print.js +91 -0
- package/dist/i18n/messages/report.d.ts +391 -0
- package/dist/i18n/messages/report.js +490 -0
- package/dist/i18n/messages/rewind.d.ts +198 -0
- package/dist/i18n/messages/rewind.js +217 -0
- package/dist/i18n/messages/session.d.ts +230 -0
- package/dist/i18n/messages/session.js +258 -0
- package/dist/i18n/messages/settings.d.ts +355 -0
- package/dist/i18n/messages/settings.js +343 -0
- package/dist/i18n/messages/subcommands-config.d.ts +113 -0
- package/dist/i18n/messages/subcommands-config.js +129 -0
- package/dist/i18n/messages/subcommands-models.d.ts +34 -0
- package/dist/i18n/messages/subcommands-models.js +34 -0
- package/dist/i18n/messages/subcommands.d.ts +576 -0
- package/dist/i18n/messages/subcommands.js +477 -0
- package/dist/i18n/messages/trace.d.ts +243 -0
- package/dist/i18n/messages/trace.js +238 -0
- package/dist/i18n/types.d.ts +15 -0
- package/dist/i18n/types.js +7 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -0
- package/dist/memory/edit.d.ts +24 -0
- package/dist/memory/edit.js +63 -0
- package/dist/memory/frontmatter.d.ts +37 -0
- package/dist/memory/frontmatter.js +79 -0
- package/dist/memory/index.d.ts +28 -0
- package/dist/memory/index.js +126 -0
- package/dist/memory/lock.d.ts +17 -0
- package/dist/memory/lock.js +62 -0
- package/dist/memory/paths.d.ts +57 -0
- package/dist/memory/paths.js +175 -0
- package/dist/memory/report.d.ts +36 -0
- package/dist/memory/report.js +86 -0
- package/dist/memory/runtime.d.ts +42 -0
- package/dist/memory/runtime.js +36 -0
- package/dist/memory/secrets.d.ts +8 -0
- package/dist/memory/secrets.js +27 -0
- package/dist/memory/section.d.ts +28 -0
- package/dist/memory/section.js +59 -0
- package/dist/memory/store.d.ts +70 -0
- package/dist/memory/store.js +284 -0
- package/dist/memory/tool.d.ts +31 -0
- package/dist/memory/tool.js +94 -0
- package/dist/modes/acp/acp-events.js +2 -1
- package/dist/modes/acp/acp-server.js +13 -12
- package/dist/modes/commands-core.d.ts +11 -0
- package/dist/modes/commands-core.js +93 -62
- package/dist/modes/image-input.js +20 -6
- package/dist/modes/interactive/agent-bar.d.ts +95 -0
- package/dist/modes/interactive/agent-bar.js +248 -0
- package/dist/modes/interactive/agent-panels.js +27 -26
- package/dist/modes/interactive/agent-transcript.d.ts +47 -0
- package/dist/modes/interactive/agent-transcript.js +191 -0
- package/dist/modes/interactive/agent-ui.d.ts +36 -1
- package/dist/modes/interactive/agent-ui.js +180 -14
- package/dist/modes/interactive/agent-view.d.ts +72 -0
- package/dist/modes/interactive/agent-view.js +281 -0
- package/dist/modes/interactive/approval-dialog.js +46 -34
- package/dist/modes/interactive/clipboard-paste.d.ts +2 -2
- package/dist/modes/interactive/clipboard-paste.js +9 -4
- package/dist/modes/interactive/commands.d.ts +22 -1
- package/dist/modes/interactive/commands.js +100 -49
- package/dist/modes/interactive/completion.js +2 -1
- package/dist/modes/interactive/config-panel.d.ts +70 -0
- package/dist/modes/interactive/config-panel.js +319 -0
- package/dist/modes/interactive/config-ui.d.ts +96 -0
- package/dist/modes/interactive/config-ui.js +397 -0
- package/dist/modes/interactive/confirm-dialog.js +6 -7
- package/dist/modes/interactive/event-notices.js +11 -9
- package/dist/modes/interactive/interactive-mode.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode.js +21 -22
- package/dist/modes/interactive/key-dispatch.d.ts +12 -0
- package/dist/modes/interactive/key-dispatch.js +24 -9
- package/dist/modes/interactive/line/line-editor.js +2 -1
- package/dist/modes/interactive/line/line-mode.js +18 -7
- package/dist/modes/interactive/line/line-render.js +25 -24
- package/dist/modes/interactive/memory-panel.d.ts +64 -0
- package/dist/modes/interactive/memory-panel.js +221 -0
- package/dist/modes/interactive/message-view.d.ts +4 -2
- package/dist/modes/interactive/message-view.js +42 -33
- package/dist/modes/interactive/model-items.d.ts +45 -0
- package/dist/modes/interactive/model-items.js +134 -0
- package/dist/modes/interactive/model-picker.d.ts +57 -0
- package/dist/modes/interactive/model-picker.js +191 -0
- package/dist/modes/interactive/panels.js +39 -31
- package/dist/modes/interactive/pickers.d.ts +2 -1
- package/dist/modes/interactive/pickers.js +10 -6
- package/dist/modes/interactive/plan-command.d.ts +1 -1
- package/dist/modes/interactive/plan-command.js +24 -27
- package/dist/modes/interactive/plan-dialog.js +18 -17
- package/dist/modes/interactive/plan-flow.js +6 -5
- package/dist/modes/interactive/rewind-command.d.ts +1 -1
- package/dist/modes/interactive/rewind-command.js +18 -16
- package/dist/modes/interactive/rewind-flow.d.ts +0 -1
- package/dist/modes/interactive/rewind-flow.js +13 -14
- package/dist/modes/interactive/rewind-list.js +7 -6
- package/dist/modes/interactive/rewind-panel.js +40 -40
- package/dist/modes/interactive/rewind-text.d.ts +5 -3
- package/dist/modes/interactive/rewind-text.js +48 -38
- package/dist/modes/interactive/run-indicator.js +15 -12
- package/dist/modes/interactive/session-events.js +3 -2
- package/dist/modes/interactive/startup-header.js +22 -23
- package/dist/modes/interactive/startup-ui.d.ts +3 -9
- package/dist/modes/interactive/startup-ui.js +44 -88
- package/dist/modes/interactive/status-area.d.ts +2 -0
- package/dist/modes/interactive/status-area.js +8 -2
- package/dist/modes/interactive/status-bar.js +4 -3
- package/dist/modes/interactive/subagent-view.js +9 -7
- package/dist/modes/interactive/tasks-report.d.ts +6 -0
- package/dist/modes/interactive/tasks-report.js +28 -31
- package/dist/modes/interactive/terminal-setup.d.ts +9 -0
- package/dist/modes/interactive/terminal-setup.js +23 -0
- package/dist/modes/interactive/tool-summary.js +19 -17
- package/dist/modes/interactive/tool-view.js +7 -4
- package/dist/modes/interactive/trace-view.d.ts +89 -0
- package/dist/modes/interactive/trace-view.js +332 -0
- package/dist/modes/print/print-mode.js +14 -15
- package/dist/modes/rpc/commands.js +7 -3
- package/dist/modes/rpc/rpc-mode.js +9 -3
- package/dist/modes/session-report.d.ts +2 -0
- package/dist/modes/session-report.js +101 -105
- package/dist/modes/startup-ui-text.js +11 -6
- package/dist/permissions/bypass.d.ts +8 -10
- package/dist/permissions/bypass.js +19 -10
- package/dist/permissions/memory-class.d.ts +23 -0
- package/dist/permissions/memory-class.js +54 -0
- package/dist/permissions/modes.d.ts +3 -3
- package/dist/permissions/modes.js +21 -16
- package/dist/permissions/pipeline.d.ts +1 -1
- package/dist/permissions/pipeline.js +9 -2
- package/dist/permissions/preview.js +49 -42
- package/dist/permissions/rules.js +5 -2
- package/dist/permissions/types.d.ts +4 -0
- package/dist/plan/store.js +2 -1
- package/dist/rpc.d.ts +39 -1
- package/dist/rpc.js +3 -0
- package/dist/sandbox/bash.js +11 -8
- package/dist/sandbox/detect.js +14 -11
- package/dist/sdk.d.ts +17 -1
- package/dist/sdk.js +29 -7
- package/dist/session/export.js +31 -30
- package/dist/session/manager.d.ts +1 -1
- package/dist/session/manager.js +5 -3
- package/dist/session/reuse.js +5 -4
- package/dist/session/scan.js +3 -2
- package/dist/session/stats-aggregate.d.ts +3 -1
- package/dist/session/stats-aggregate.js +5 -1
- package/dist/session/stats-index.js +2 -1
- package/dist/session/stats-scan.d.ts +4 -1
- package/dist/session/stats-scan.js +6 -2
- package/dist/session/store.d.ts +11 -0
- package/dist/session/store.js +48 -1
- package/dist/session/types.d.ts +2 -0
- package/dist/skills/builtin.js +2 -1
- package/dist/tools/image-file.d.ts +26 -1
- package/dist/tools/image-file.js +55 -13
- package/dist/tools/presets.d.ts +14 -1
- package/dist/tools/presets.js +3 -3
- package/dist/tools/registry.js +1 -1
- package/dist/tools/truncate.d.ts +1 -1
- package/dist/tools/truncate.js +2 -2
- package/dist/tools/types.d.ts +17 -1
- package/dist/trace/build-index.d.ts +91 -0
- package/dist/trace/build-index.js +127 -0
- package/dist/trace/build-nodes.d.ts +24 -0
- package/dist/trace/build-nodes.js +279 -0
- package/dist/trace/build-util.d.ts +43 -0
- package/dist/trace/build-util.js +120 -0
- package/dist/trace/build.d.ts +82 -0
- package/dist/trace/build.js +382 -0
- package/dist/trace/detail.d.ts +35 -0
- package/dist/trace/detail.js +205 -0
- package/dist/trace/flatten.d.ts +69 -0
- package/dist/trace/flatten.js +173 -0
- package/dist/trace/format.d.ts +47 -0
- package/dist/trace/format.js +329 -0
- package/dist/trace/html-template.d.ts +19 -0
- package/dist/trace/html-template.js +150 -0
- package/dist/trace/html.d.ts +104 -0
- package/dist/trace/html.js +292 -0
- package/dist/trace/preview.d.ts +29 -0
- package/dist/trace/preview.js +59 -0
- package/dist/trace/query-session.d.ts +14 -0
- package/dist/trace/query-session.js +38 -0
- package/dist/trace/query.d.ts +55 -0
- package/dist/trace/query.js +188 -0
- package/dist/trace/session.d.ts +40 -0
- package/dist/trace/session.js +168 -0
- package/dist/trace/types.d.ts +243 -0
- package/dist/trace/types.js +13 -0
- package/dist/tui/components/editor-paste.d.ts +2 -0
- package/dist/tui/components/editor-paste.js +6 -3
- package/dist/tui/components/editor.js +2 -2
- package/dist/tui/components/loader.d.ts +3 -0
- package/dist/tui/components/loader.js +14 -0
- package/dist/tui/components/select-list.d.ts +2 -0
- package/dist/tui/components/select-list.js +7 -0
- package/dist/tui/components/settings-list.d.ts +61 -0
- package/dist/tui/components/settings-list.js +135 -0
- package/dist/tui/keybindings.d.ts +5 -0
- package/dist/tui/keybindings.js +17 -5
- package/dist/tui.d.ts +1 -0
- package/dist/tui.js +2 -0
- package/docs/en/host-api.md +167 -0
- package/docs/en/permissions.md +214 -0
- package/docs/en/providers.md +627 -0
- package/docs/en/rpc.md +361 -0
- package/docs/en/sessions.md +219 -0
- package/docs/en/tui.md +534 -0
- package/docs/host-api.md +18 -17
- package/docs/memory.md +172 -0
- package/docs/permissions.md +2 -2
- package/docs/providers.md +73 -1
- package/docs/rpc.md +31 -3
- package/docs/session-format.md +8 -2
- package/docs/sessions.md +29 -1
- package/docs/tui.md +140 -4
- package/package.json +8 -3
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Host adapter API (@armadra/agent/host)
|
|
2
|
+
|
|
3
|
+
English · [简体中文](../host-api.md)
|
|
4
|
+
|
|
5
|
+
> Translated from the Chinese [docs/host-api.md](../host-api.md) as of commit `0065cf4`. When the two differ, the Chinese
|
|
6
|
+
> version is authoritative.
|
|
7
|
+
|
|
8
|
+
A host adapter is a local JS module that ama loads at startup and hands a `HostApi`. With it the adapter can register tools, append to the system prompt, observe events, answer approvals, inject user messages and show notifications and status in the interface. The Armadra canvas plugs in as a host adapter (the canvas tools `canvas_*` / `context_*` are all registered by the adapter). The types are defined in `src/host/types.ts` and exported from `@armadra/agent/host`; `HOST_API_VERSION = 1`. The design rationale is in [design.md](../design.md) §6.2, §6.3 and §11.1 step 13 (Chinese).
|
|
9
|
+
|
|
10
|
+
## Module shape
|
|
11
|
+
|
|
12
|
+
```js
|
|
13
|
+
// my-host.mjs
|
|
14
|
+
export const hostApi = 1;
|
|
15
|
+
export function create(api) {
|
|
16
|
+
if (!api.env.MY_HOST_ENABLED) return undefined; // not activated: ama falls back to plain standalone mode
|
|
17
|
+
api.tools.register({
|
|
18
|
+
name: "my_lookup",
|
|
19
|
+
description: "Look up a ticket by id.",
|
|
20
|
+
parameters: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
|
|
21
|
+
permission: "read",
|
|
22
|
+
async execute(input) {
|
|
23
|
+
return { content: `ticket ${input.id}: …` };
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
api.instructions.add({
|
|
27
|
+
kind: "text",
|
|
28
|
+
name: "my-host",
|
|
29
|
+
text: "Tickets live in the tracker; use my_lookup.",
|
|
30
|
+
});
|
|
31
|
+
api.events.on("agent_settled", () => api.ui.setStatus("my-host", "idle"));
|
|
32
|
+
return { id: "my-host", dispose() {} };
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- Export `hostApi` (must equal `HOST_API_VERSION`) and `create(api)`; they may also sit on the default export (ESM `export default { hostApi, create }` or CJS `module.exports = { hostApi, create }`).
|
|
37
|
+
- `create` activates the adapter by returning a `HostAdapter` (`{ id: string, dispose?() }` with a non-empty `id`); returning `undefined` means "not activated this time". It may be async.
|
|
38
|
+
- `dispose()` is called on exit (after the `session_shutdown` event) and is idempotent.
|
|
39
|
+
|
|
40
|
+
## Loading
|
|
41
|
+
|
|
42
|
+
- Source: `--host <module>` or the profile's `host` (the command line wins); relative paths resolve against cwd.
|
|
43
|
+
- `.mjs` uses dynamic `import()`; `.cjs` uses `require`; `.js` tries `require` first and falls back to `import()` on ESM errors (`ERR_REQUIRE_ESM` etc.). The single-file build `ama.cjs` can load ESM adapters too.
|
|
44
|
+
- Timing: step 13 of the startup sequence, after config, resources, the model and the tool registry are ready and before the session is assembled. Tools and instructions registered in `create()` enter the system prompt and tool table of the first request, so the prefix is stable from the first request on.
|
|
45
|
+
- Failures:
|
|
46
|
+
|
|
47
|
+
| Case | Exit code |
|
|
48
|
+
| ---------------------------------------------------------- | --------- |
|
|
49
|
+
| File missing, loading throws, `hostApi` / `create` missing | 6 |
|
|
50
|
+
| `hostApi` differs from `HOST_API_VERSION` | 78 |
|
|
51
|
+
| `create()` throws or does not return within 10 seconds | 6 |
|
|
52
|
+
| The returned adapter has no `id` | 6 |
|
|
53
|
+
|
|
54
|
+
## HostApi
|
|
55
|
+
|
|
56
|
+
| Member | Description |
|
|
57
|
+
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `version` | `HOST_API_VERSION` |
|
|
59
|
+
| `agent` | `{ name: "ama", version }` |
|
|
60
|
+
| `env` | A frozen copy of the environment variables at startup |
|
|
61
|
+
| `mode` | `interactive` / `line` / `print` / `rpc` |
|
|
62
|
+
| `session.id()` / `file()` / `cwd()` / `model()` | The current session (follows the new session after a switch); `file()` is `undefined` until the first request is written to disk |
|
|
63
|
+
| `tools.register(tool)` | Register a tool (shape below); the name must match `^[a-z][a-z0-9_]{1,63}$`, and an existing name throws `tool_exists`. A prefix is recommended (`canvas_*`) |
|
|
64
|
+
| `tools.disable(name)` | Hide a built-in tool (Armadra disables `task`, for example); the tools section of the system prompt stops listing it |
|
|
65
|
+
| `tools.list()` | All current tool names |
|
|
66
|
+
| `instructions.add(source)` | Append to the final `host` section of the system prompt; `{ kind: "file", path }` or `{ kind: "text", text, name? }` |
|
|
67
|
+
| `events.on(name, handler)` | Observe events (table below); returns an unsubscribe function |
|
|
68
|
+
| `approvals.setBroker(broker)` | Set the approval answerer (see "Approvals") |
|
|
69
|
+
| `messages.sendUser(text, origin?)` | Inject a user message: when idle it starts a run (`"started"`), while running it is queued as a steer (`"queued"`); `origin` defaults to `"host"`, is persisted on the message and shown as `↳ host` |
|
|
70
|
+
| `ui.notify(message, level?)` | Goes to the message area in interactive / line mode; becomes a `notification` event in rpc mode (with a copy on stderr); written to stderr in print mode |
|
|
71
|
+
| `ui.setStatus(key, text?)` | A host item in the status bar; an empty or missing `text` removes the key |
|
|
72
|
+
| `log(level, message, detail?)` | Logging; `warn` / `error` go to stderr |
|
|
73
|
+
| `cache?.onWarmingDecision(handler)` | Veto hook for cache warming (see "Cache warming"); an optional facet missing in older runtimes, so check `api.cache !== undefined` before use |
|
|
74
|
+
|
|
75
|
+
During `create()` the session is not assembled yet: `session.*` returns the values fixed at startup, and `sendUser` is rejected with `busy`. To send a message at startup, wait for the `session_start` event.
|
|
76
|
+
|
|
77
|
+
### Tool definition
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
interface ToolDefinition<I = unknown> {
|
|
81
|
+
name: string;
|
|
82
|
+
label?: string; // TUI title
|
|
83
|
+
description: string;
|
|
84
|
+
parameters: JsonSchema;
|
|
85
|
+
permission: "read" | "write" | "execute"; // class used by the permission pipeline
|
|
86
|
+
executionMode?: "sequential" | "parallel"; // default: read runs in parallel, the rest sequentially
|
|
87
|
+
annotations?: { readOnly?: boolean; destructive?: boolean; openWorld?: boolean };
|
|
88
|
+
promptSnippet?: string; // one line in the system prompt's tools section
|
|
89
|
+
promptGuidelines?: string[]; // system prompt rules section
|
|
90
|
+
execute(input: I, ctx: ToolContext): Promise<ToolResult>;
|
|
91
|
+
renderCall?(input: I, width: number): string[];
|
|
92
|
+
renderResult?(result: ToolResult, width: number, expanded: boolean): string[];
|
|
93
|
+
}
|
|
94
|
+
interface ToolResult {
|
|
95
|
+
content: string | ContentBlock[];
|
|
96
|
+
isError?: boolean;
|
|
97
|
+
details?: unknown; // persisted, never enters the context
|
|
98
|
+
structured?: unknown; // return value of tools.<name>() in codemode scripts
|
|
99
|
+
terminate?: boolean; // the run ends early only when every result in the batch sets it
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`ToolContext` provides `toolCallId`, `cwd`, `sessionId`, `sessionFile?`, `signal`, `depth`, `model?`, `thinkingLevel?`, `outputDir?`, `onUpdate(partial)` (output while running), `readFiles` / `markRead`, `tools.executeTool(name, input)` (nested calls through the same pipeline), `session.appendCustom` / `lastCustom` (custom entries that never enter the context, see [session-format.md](../session-format.md), Chinese), `spawnSubagent?` and `log`.
|
|
104
|
+
|
|
105
|
+
Host tools take the same path as built-in tools: schema validation → command hook PreToolUse → permission pipeline (classified by `permission`) → approval → execution → PostToolUse. They can also be called from codemode scripts as `tools.<name>()`.
|
|
106
|
+
|
|
107
|
+
## Events
|
|
108
|
+
|
|
109
|
+
`events.on` handlers only observe: a throw is just logged and does not affect the run; handlers are called and awaited in order, and `session_shutdown` is awaited (so you can clean up before exit).
|
|
110
|
+
|
|
111
|
+
| Event | Payload | Source |
|
|
112
|
+
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
113
|
+
| `session_start` | `sessionId`, `sessionFile?`, `cwd`, `reason: startup \| resume \| new \| fork` | Startup and session switches |
|
|
114
|
+
| `before_agent_start` | `prompt` | After the user prompt is expanded, before the run starts |
|
|
115
|
+
| `agent_start` / `turn_start` / `turn_end` / `agent_before_settle` | `{}` | Runs and turns |
|
|
116
|
+
| `agent_end` | `stopReason`, `willRetry` | |
|
|
117
|
+
| `agent_settled` | `warning?` | The run has fully ended |
|
|
118
|
+
| `tool_call` | `toolCallId`, `toolName`, `input` | A tool starts executing (permission already granted) |
|
|
119
|
+
| `tool_result` | `toolCallId`, `toolName`, `isError` | A tool finished executing |
|
|
120
|
+
| `tool_approval_requested` | `requestId`, `toolName` | Approval needed |
|
|
121
|
+
| `tool_approval_resolved` | `requestId`, `decision` | Approval decided |
|
|
122
|
+
| `session_compact` | `tokensBefore` | Compaction succeeded |
|
|
123
|
+
| `model_select` | `model: { provider, id }` | Model switched |
|
|
124
|
+
| `hook_executed` | `event`, `command`, `exitCode`, `durationMs` | Each command hook finished |
|
|
125
|
+
| `cache_miss` | `missedTokens`, `missedCost?`, `reason`, `detail?`, `idleMs` | A cache miss (including those below the interface threshold) |
|
|
126
|
+
| `context_pressure` | `percent`, `threshold: 70 \| 90`, `remainingTokens?`, `estimatedTurnsLeft?` | Context usage crossed 70% / 90% |
|
|
127
|
+
| `quota_update` | `provider`, `planType?`, `primary?`, `secondary?` (`{ usedPercent, resetsAt?, windowMinutes? }`) | ChatGPT subscription quota updated ([W6-O]; an exhausted quota has its own error code `quota_exceeded`, an expired login `auth_expired`) |
|
|
128
|
+
| `session_shutdown` | `{}` | Before exit (followed by the SessionEnd hook and `dispose`) |
|
|
129
|
+
|
|
130
|
+
For token-level streaming content or the full event stream, use RPC or the SDK's `subscribe`; host events are a trimmed set.
|
|
131
|
+
|
|
132
|
+
## Approvals
|
|
133
|
+
|
|
134
|
+
`approvals.setBroker({ ask(request, signal) })`: when a tool call needs confirmation, the approval chain asks **the host broker → the UI (TUI dialog / RPC client / SDK callback) → deny when nobody answers**, in that order.
|
|
135
|
+
|
|
136
|
+
- `ask` answers by returning `"allow"` / `"deny"` / `"allow_session"`; returning `undefined` passes to the next answerer; a throw counts as deny.
|
|
137
|
+
- `request`: `requestId`, `toolName`, `input`, `reason: "mode" | "dangerous" | "hook"`, `hookReason?`, `preview?` (the pre-execution preview, see [rpc.md](rpc.md) "Approvals"), `context?` (`depth > 0` means it comes from a `task` sub-agent; codemode inner calls carry `parentToolCallId`).
|
|
138
|
+
- On timeout (10 minutes by default, `AMA_APPROVAL_TIMEOUT_MS`) or when the run is interrupted, `signal` aborts and the decision is deny. Approvals are serial: only one request waits at a time.
|
|
139
|
+
- Timing: the broker is looked up at each approval, so it can be set in `create()` or set / replaced at any later time; the last `setBroker` wins.
|
|
140
|
+
- The host broker only decides "who answers an ask"; it cannot loosen deny rules, command hook denies or dangerous-command detection ([design.md](../design.md) §6.3, Chinese).
|
|
141
|
+
|
|
142
|
+
## Cache warming
|
|
143
|
+
|
|
144
|
+
`api.cache.onWarmingDecision(handler)` calls `handler(decision)` with the built-in decision before every cache warming request:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
interface WarmDecision {
|
|
148
|
+
action: "warm" | "stop"; // built-in decision
|
|
149
|
+
phase: "streaming" | "idle";
|
|
150
|
+
promptTokens: number; // input + cacheRead + cacheWrite of the last real request
|
|
151
|
+
warmCost: number | undefined; // cost of one warming request (USD)
|
|
152
|
+
missCost: number | undefined; // extra cost if the cache expires without warming
|
|
153
|
+
probability: number; // probability that another request follows after expiry: streaming 1, idle 0.15
|
|
154
|
+
reason?: string; // reason for stop
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Return `"warm"` / `"stop"` (a Promise is fine). `"stop"` skips the request and stops this warming round (when the built-in decision was warm, the stop reason is recorded as `declined`); `"warm"` can override a built-in stop. If the handler fails, the built-in decision applies. With several handlers, the last one registered and not unsubscribed wins; the return value is an unsubscribe function. The warming mechanism itself is described in [providers.md](providers.md) "Caching".
|
|
159
|
+
|
|
160
|
+
## Exit
|
|
161
|
+
|
|
162
|
+
- Process exit: `session_shutdown` event (awaited) → SessionEnd hook (`reason: "exit"`) → `adapter.dispose()` → session dispose. A throw from `dispose` is only logged as a warning.
|
|
163
|
+
- `/new`, `/resume`, `/fork` and RPC session switches: the adapter stays active and no `session_shutdown` is sent; the order is SessionEnd hook (`new` / `switch`) → old session dispose → `session_start` of the new session → SessionStart hook. `api.session.*` then points to the new session.
|
|
164
|
+
|
|
165
|
+
## Embedding in Armadra
|
|
166
|
+
|
|
167
|
+
Armadra starts ama with a profile: `ama --profile <path>`. The profile's `host` points to its adapter (`ama-armadra.cjs`) and also carries instructions, skillDirs, hooksFile, authFile, sessionDir and `trustProject`. The adapter returns `undefined` when `ARMADRA_NODE_ID` is missing, so the same profile behaves as plain ama outside the canvas. Contract details are in [docs/design/coordinator-agent.md](https://github.com/yovinchen/Armadra/blob/main/docs/design/coordinator-agent.md) in the Armadra repository.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Permission modes and auto decisions
|
|
2
|
+
|
|
3
|
+
English · [简体中文](../permissions.md)
|
|
4
|
+
|
|
5
|
+
> Translated from the Chinese [docs/permissions.md](../permissions.md) as of commit `ee89edb`. When the two differ, the
|
|
6
|
+
> Chinese version is authoritative.
|
|
7
|
+
|
|
8
|
+
This document covers ama's six permission modes, the decision order for every tool call, and how the three tiers of `auto` mode, "rule tier → static judgement → model classifier", decide between allowing and asking. The overall design is in [design.md](../design.md) §6.3 and §7 (Chinese); hook input and output are in [hooks.md](../hooks.md) (Chinese).
|
|
9
|
+
|
|
10
|
+
## Modes
|
|
11
|
+
|
|
12
|
+
| Value | Display name | Read | Write (inside the project) | Execute (bash etc.) | When to use |
|
|
13
|
+
| ----------- | ------------------ | ---- | ----------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
14
|
+
| `default` | Manual | ✓ | ask | ask | Default |
|
|
15
|
+
| `auto-edit` | Accept edits | ✓ | ✓ | ask | You trust it to edit code but want to see each command |
|
|
16
|
+
| `plan` | Plan | ✓ | deny | read-only commands allowed, everything else denied | Read-only research, then a plan for approval ([plan.md](../plan.md), Chinese) |
|
|
17
|
+
| `auto` | Auto | ✓ | ✓ (protected paths and outside the project ask) | safe-list commands allowed, the rest judged by a classifier | Recommended: routine work is not interrupted, only risky steps ask |
|
|
18
|
+
| `full-auto` | Bypass permissions | ✓ | ✓ | ✓ | Throwaway sandboxes, containers |
|
|
19
|
+
| `allowlist` | Allowlist only | ✓ | only calls matching allow rules | read-only commands and calls matching allow rules | CI: never asks; anything not listed is denied |
|
|
20
|
+
|
|
21
|
+
In every mode, deny rules and hook denies are checked first and deny outright; the dangerous-command list (`rm -rf /`, `git push --force`, `curl … | sh` and so on, see the README "Safety" section) always asks, which becomes deny under `allowlist` and when unattended.
|
|
22
|
+
|
|
23
|
+
How to set it: `--permission-mode <value>`, config `permission.mode`, `/permission` (picker) or `Shift+Tab` in the interactive UI, RPC `set_permission_mode`, SDK `permission.mode`.
|
|
24
|
+
|
|
25
|
+
### Strictness and project config
|
|
26
|
+
|
|
27
|
+
From strictest to loosest: `plan < allowlist < default < auto-edit < auto < full-auto`. The project-level `.ama/config.json` can only move the mode towards stricter; in addition it **cannot set `auto` or `full-auto`** (these let ama decide by itself, or allow without any judgement, so they must be turned on by user config, the command line or a profile). Setting them there is ignored with a warning.
|
|
28
|
+
|
|
29
|
+
`allowlist` sits between `plan` and `default`: the calls it allows are those `plan` allows (read-only tools, [read-only commands](#plan-mode-and-read-only-commands), `task`) plus those listed explicitly by allow rules; the set `default` allows contains it (read-only + allow rules), and everything else asks under `default` and is denied under `allowlist`. So `plan ⊆ allowlist ⊆ default`. Read tools are allowed under `allowlist` as in every other mode; to restrict even reads, use deny rules.
|
|
30
|
+
|
|
31
|
+
Read-only commands are a static list (next section) shared by `plan` and `allowlist`, so the total order of strictness holds; allowing commands such as `ls` and `git log` under `allowlist` in CI is harmless. `task` is allowed in both modes: sub-sessions share the same permission pipeline, so a sub-agent can never do more than the parent session. With `plan.bash: "ask"`, plan asks for commands outside the list (`allowlist` never asks), and the set of "allowed without asking" still satisfies the inclusions above.
|
|
32
|
+
|
|
33
|
+
### Interface
|
|
34
|
+
|
|
35
|
+
- The status bar shows the display name: `mode:Auto`; `Bypass permissions` is yellow.
|
|
36
|
+
- `/permission` without arguments opens a picker: titled `Mode`, each item "display name + one line of explanation", number shortcuts 1–6 on the right, a check on the current mode, `Default` on the default mode from config and `Recommended` on Auto. In line mode `/permission` prints the same list.
|
|
37
|
+
- `Shift+Tab` cycles: Manual → Accept edits → Plan → Auto → Bypass permissions → Manual. `Allowlist only` is not in the cycle and must be chosen explicitly.
|
|
38
|
+
- **Entering Bypass**: switching to Bypass in the interactive UI (Tab / Shift+Tab cycling, the `/permission` picker, `/permission full-auto`) first shows a confirmation dialog with "Cancel" selected by default; cancelling while cycling skips Bypass and returns to Manual, cancelling from the picker or command keeps the previous mode. Once confirmed in a run, it is not asked again. `--permission-mode full-auto` on the command line, user config and profiles do not prompt (those are explicit choices); line mode asks a `[y/N]` question; piped input, RPC `set_permission_mode` and ACP `session/set_mode` are the caller's responsibility and do not prompt. Details in [tui.md](tui.md) "Entering Bypass".
|
|
39
|
+
|
|
40
|
+
### Origin labels in the approval dialog
|
|
41
|
+
|
|
42
|
+
Approvals do not only come from the main session. The dialog (and RPC `permission_request.context`) shows where a request comes from; the options are always just "allow / allow this kind for the session / deny":
|
|
43
|
+
|
|
44
|
+
| Origin | Title prefix | Body | Who decides |
|
|
45
|
+
| --------------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
46
|
+
| Tool calls of a `task` sub-agent | `[task:explore]` (`[task]` when the type is unknown) | Same as the main session | The same permission pipeline; read-only types (`explore` / `plan`) are judged as plan and never prompt |
|
|
47
|
+
| Permission requests from external agents (claude / codex / ACP) | `[claude · session abc12345]` | The title, kind, paths involved and input summary given by the external agent | A human only: host → interface → deny when unattended; neither the auto classifier nor the model takes part |
|
|
48
|
+
| First run of an external agent in this session | Title "first run of an external agent" | An explanation (runs with your login in that CLI) and the mode | allow / deny rules `task(<id>)` and `full-auto` let it through; otherwise a human decides (no classifier) |
|
|
49
|
+
|
|
50
|
+
"Allow for this session" of an external agent is remembered by that agent itself. In Manual mode the approval of a `task(agent=…)` call and the first-run confirmation are merged into one (see [agents.md](../agents.md), Chinese). The RPC `context` is `{ depth, taskId, origin }` ([rpc.md](rpc.md) "Approvals").
|
|
51
|
+
|
|
52
|
+
## Plan mode and read-only commands
|
|
53
|
+
|
|
54
|
+
Step ③ of plan mode looks at the input (implemented by `planDecision` in `src/permissions/pipeline.ts`); the flow and plan approval are in [plan.md](../plan.md) (Chinese):
|
|
55
|
+
|
|
56
|
+
| Call | Under plan |
|
|
57
|
+
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| read / grep / glob / ls | Allowed |
|
|
59
|
+
| `todo` | `get` allowed; `set` / `update` denied, with a hint to put the steps into `<proposed_plan>` (the list is generated from the plan on approval) |
|
|
60
|
+
| bash | Per `plan.bash`: `readonly` (default) allows read-only commands and denies the rest; `ask` asks for the rest (denied when unattended); `deny` denies all |
|
|
61
|
+
| write / edit etc. | Denied with guidance: `Plan mode is active: write/execute tools are disabled. Finish the plan with a <proposed_plan> block.` |
|
|
62
|
+
| task | Allowed (sub-sessions share the same pipeline and are in plan too; sub-sessions do not extract plan blocks) |
|
|
63
|
+
| deny rules, dangerous commands, hooks | Decided before the mode (unchanged) |
|
|
64
|
+
|
|
65
|
+
Read-only commands (`src/permissions/readonly-bash.ts`): first they pass auto's static judgement (tokenizing, nested expansion, network / deletion / write targets / secret paths, command substitution, variable expansion, dotfile globs); then every segment must be on the list below, with no output redirection (except `/dev/null`), no nested shell (`sh -c`, `eval`, `xargs`, `find -exec`) or process substitution, and no environment assignment or wrapper command at the start of a segment (`GIT_EXTERNAL_DIFF=… git diff`, `env …`).
|
|
66
|
+
|
|
67
|
+
| Command | Restrictions |
|
|
68
|
+
| ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
69
|
+
| `ls cat head tail wc stat echo printf pwd which du basename dirname realpath true false cd` | — |
|
|
70
|
+
| `grep egrep fgrep`, `rg`, `fd`, `find` | `rg --pre`, `fd -x / -X / --exec*`, `find -exec / -ok / -delete / -fprint*` do not count |
|
|
71
|
+
| `tree`, `file`, `jq` | `tree -o`, `file -C`, `jq -i` do not count |
|
|
72
|
+
| `git status / log / show / diff / rev-parse / blame / ls-files / branch` | Only the git global options `-C` and `--no-pager` are allowed; `--output`, `--ext-diff`, `--textconv` and branch-changing options do not count |
|
|
73
|
+
|
|
74
|
+
This is narrower than auto's safe list: no test / build runners (`npm test` and `cargo build` run project scripts), and no `env` / `printenv` (they would print secrets in environment variables into the context). Reading secret paths (`cat .env`) is not read-only.
|
|
75
|
+
|
|
76
|
+
## Decision order
|
|
77
|
+
|
|
78
|
+
One tool call (issued directly by the model or nested inside codemode / task, alike):
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
schema validation
|
|
82
|
+
→ command hook PreToolUse (deny vetoes; allow / ask go to the pipeline)
|
|
83
|
+
→ permission pipeline:
|
|
84
|
+
① rule tier (no model call)
|
|
85
|
+
deny rules (including built-in deny), hook deny → deny
|
|
86
|
+
dangerous-command list → ask
|
|
87
|
+
[auto] protected paths, writes outside the project, network, deletion → ask
|
|
88
|
+
hook ask → ask
|
|
89
|
+
allow rules, hook allow, session memory → allow
|
|
90
|
+
② mode
|
|
91
|
+
plan: read-only tools, read-only commands and task allowed, everything else denied (with plan.bash: ask, other commands ask)
|
|
92
|
+
default / auto-edit / full-auto: the usual mode truth table
|
|
93
|
+
[default / auto-edit] bash the mode would ask for: besides allow rules / hook allow / session memory,
|
|
94
|
+
approval-free inside the sandbox (see below) → allow; a hook ask still turns the result back into ask
|
|
95
|
+
allowlist: read-only tools, read-only commands and task allowed, everything else denied (Not in the allowlist)
|
|
96
|
+
auto: [with the sandbox active] a sandbox:false request to leave the sandbox → ask (after allow rules / hook allow / session memory)
|
|
97
|
+
static judgement (no model call) → allow; undecided → ③
|
|
98
|
+
③ [auto] model classifier (sandboxed bash gets an os_sandbox input): allow → allow; ask / error / timeout → ask
|
|
99
|
+
→ when asking, the approval chain runs (host broker → interface → deny when unattended)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
- Later steps cannot loosen earlier results: allow rules cannot override dangerous commands or auto's rule tier, and the classifier only handles calls neither ① nor ② decided.
|
|
103
|
+
- `allowlist` never asks: anything that would ask (dangerous commands, hook ask) is denied, with the denial text `Not in the allowlist` (text returned to the model is always English).
|
|
104
|
+
- When unattended (`-p`, RPC without approvals), asking always means deny; in auto mode the classifier still runs first, and calls it judges allow are executed.
|
|
105
|
+
|
|
106
|
+
### Approval-free commands inside the sandbox
|
|
107
|
+
|
|
108
|
+
With `sandbox.bash: auto` and an OS sandbox on the machine that can restrict writes ([sandbox.md](../sandbox.md) "phase two", Chinese), bash runs through the sandbox. Under default / auto-edit, a bash call needs no approval (`PermissionVerdict.sandboxed: true`) when all of the following hold:
|
|
109
|
+
|
|
110
|
+
1. It will run inside the sandbox: no `sandbox: false`;
|
|
111
|
+
2. `sandbox.network: deny` (network access can exfiltrate data, so `allow` asks as usual);
|
|
112
|
+
3. The command text (including nested commands in `sh -c`, `eval`, `xargs`, `find -exec`) touches no secret paths (`cat .env`, `~/.ssh/…`) and is not nested too deeply;
|
|
113
|
+
4. It was not denied earlier by deny rules or a hook deny, is not on the dangerous-command list (`rm -rf` on paths outside the workspace, `git push --force`, `git reset --hard` etc. ask as usual), and no hook ask follows.
|
|
114
|
+
|
|
115
|
+
| Mode | bash inside the sandbox | `sandbox: false` (leaving the sandbox) |
|
|
116
|
+
| ------------------ | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
117
|
+
| default, auto-edit | Allowed when the conditions above hold, otherwise ask | Ask (allow rules, hook allow and session memory can allow) |
|
|
118
|
+
| auto | Rule tier and static judgement as usual; the classifier gets an extra `os_sandbox` input | The rule tier asks (allow rules, hook allow and session memory can allow) |
|
|
119
|
+
| plan, allowlist | Unchanged | Unchanged |
|
|
120
|
+
| full-auto | Allowed | Allowed |
|
|
121
|
+
|
|
122
|
+
When unattended "ask" always means deny, so calls leaving the sandbox are denied in `-p`. auto does not allow sandboxed commands outright: its rule tier (network, deletion, protected paths, writes outside the project) is a deliberately finer line of defense than default's, and the classifier remains the last gate; the cost is that some commands default + sandbox would allow (`rm -r dist` in the workspace) still ask under auto.
|
|
123
|
+
|
|
124
|
+
## The three tiers of auto
|
|
125
|
+
|
|
126
|
+
### ① Rule tier
|
|
127
|
+
|
|
128
|
+
No model call; a match asks (denied when unattended):
|
|
129
|
+
|
|
130
|
+
| Category | Contents |
|
|
131
|
+
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
132
|
+
| Dangerous commands | The whole list in `dangerous.ts` (shared by all modes) |
|
|
133
|
+
| Secret paths | Reading or writing `.env`, `.env.*` (except `.env.example` / `.sample` / `.template` / `.dist`), `.ssh/`, `.gnupg/`, `.aws/`, `.kube/config`, `.docker/config.json`, `.netrc`, `.pgpass`, private keys (`id_rsa` etc., `*.pem`, `*.key`, `*.p12`, `*.pfx`, `*.jks`), ama's `auth.json` |
|
|
134
|
+
| Protected writes | Writing inside `.git/`, the project's `.ama/` (could change hooks and config), or any path outside the project directory (except `/dev/null` and the like) |
|
|
135
|
+
| Network commands | `curl`, `wget`, `ssh`, `scp`, `rsync`, `nc`, `gh`; `git push / pull / fetch / clone`; `npm / pnpm / yarn / bun install / add / ci / update / publish / dlx`, `npx`; `pip install`, `cargo install / publish`, `go get / install`, `brew / apt install`, `docker pull / push / login` and so on |
|
|
136
|
+
| Deletion and rollback | `rm -r` / `rm -f`, `find -delete`, `git clean`, `git checkout -- …` / `git restore`, `git stash drop / clear`, `shred`, `truncate` |
|
|
137
|
+
| Paths in bash | Redirect targets (`>`, `>>`, `&>`, `tee`), and targets of `cp` / `mv` / `mkdir` / `touch` / `ln` / `chmod` outside the project or protected; secret paths among command arguments (`cat .env`) |
|
|
138
|
+
|
|
139
|
+
"The project directory" is the session cwd. File tools are judged by their `path` argument; bash is judged segment by segment with the same tokenizing and nested expansion as `dangerous.ts` (`sh -c`, `eval`, `xargs`, `find -exec`).
|
|
140
|
+
|
|
141
|
+
### ② Static judgement
|
|
142
|
+
|
|
143
|
+
No model call; allowed when satisfied:
|
|
144
|
+
|
|
145
|
+
- Read-only tools (read, ls, grep, glob etc., `permission: "read"`).
|
|
146
|
+
- write / edit with a target inside the project directory and not on a protected path (protected ones already asked in ①).
|
|
147
|
+
- bash: every segment of the command (split at `&&`, `||`, `;`, `|`) is on the **safe list**, and
|
|
148
|
+
- there is no command substitution `$(…)`, backtick or `<(…)`;
|
|
149
|
+
- arguments contain no variable expansion `$X` and no globs that may match dotfiles (`.e*`);
|
|
150
|
+
- there is no nesting such as `sh -c` (shells, `eval` and `xargs` are not on the list).
|
|
151
|
+
Piping into safe commands (`cat a | grep b | wc -l`) is fine; piping into a shell is not on the list. Redirecting into the project is allowed; writing outside the project already asked in ①.
|
|
152
|
+
- A matching allow rule (already allowed at the end of ①).
|
|
153
|
+
|
|
154
|
+
The safe list (`src/permissions/auto-safe.ts`, each entry with positive and negative tests):
|
|
155
|
+
|
|
156
|
+
| Command | Restrictions |
|
|
157
|
+
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
158
|
+
| `ls`, `cat`, `head`, `tail`, `wc`, `grep`, `egrep`, `fgrep`, `rg`, `pwd`, `echo`, `printf`, `which`, `env` and `printenv` (printing only), `true`, `false`, `sort`, `cut`, `tr`, `diff`, `basename`, `dirname`, `realpath`, `stat`, `file`, `du`, `df`, `date`, `whoami`, `uname`, `cd` / `pushd` / `popd` (later relative paths resolve against the new directory) | `env FOO=1 cmd` is judged as `cmd` |
|
|
159
|
+
| `find` | Without `-exec`, `-execdir`, `-ok`, `-okdir`, `-delete`, `-fprint*`, `-fls` |
|
|
160
|
+
| `git status / diff / log / show / rev-parse / blame / ls-files` (`diff / log / show` without `--output`, `--ext-diff`, `--textconv`; `rg` without `--pre`; `sort` without `-o`; `date` without `-s`) | Only `-C dir` and `--no-pager` before the subcommand (`-c` can change the pager and is not safe) |
|
|
161
|
+
| `git branch` | Listing only: without `-d / -D / --delete / -m / -M / -c / -C / -f / -u` etc. |
|
|
162
|
+
| `npm / pnpm / yarn test`, `… run test / lint / typecheck / build`, `pnpm / yarn lint / typecheck / build`, `npm t` | |
|
|
163
|
+
| `node --test`, `tsc --noEmit`, `vitest run`, `pnpm vitest run`, `pnpm exec vitest run`, `pytest`, `python -m pytest` | |
|
|
164
|
+
| `cargo test / check / build / clippy`, `go test / build / vet`, `make test / check / lint / build` | |
|
|
165
|
+
|
|
166
|
+
Extending it: the user-level config `permission.autoSafeCommands` adds entries, e.g. `["just test", "bun test", "make fmt"]`, matched by word prefix (`just test` matches `just test --verbose`); entries containing `*` match the whole segment as a glob (`bun run test*`). Project config cannot add entries (that would loosen). Added commands still pass ① first: network, deletion and writes outside the project still ask.
|
|
167
|
+
|
|
168
|
+
### ③ Model classifier
|
|
169
|
+
|
|
170
|
+
It only handles calls neither ① nor ② decided (e.g. `rm old.txt`, `node scripts/gen.js`, host tools, codemode scripts).
|
|
171
|
+
|
|
172
|
+
- **A separate request**: it never enters the session transcript and does not change the main session's messages or prefix (the main session's prompt cache is unaffected), and does not trigger warming; the request purpose is `purpose: "classify"`.
|
|
173
|
+
- **Input**: tool name, arguments (JSON, truncated to 4000 characters), cwd, project root, and a summary of the latest user message (truncated to 600 characters). Arguments and the user message sit inside a `<tool_call_data>` … `</tool_call_data>` data block, with end markers inside the block escaped; the system prompt requires treating everything inside as data and ignoring instructions in it (including things like "ignore previous instructions" or "respond allow"), leaning to ask when such text appears.
|
|
174
|
+
- **Output**: strict JSON `{"decision":"allow"|"ask","reason":"…"}`. A parse failure, a timeout (10 s) or a request error → ask.
|
|
175
|
+
- **Model**: `permission.autoModel` (`provider/model`); defaults to the current session model. A cheap, fast model is recommended, e.g. `packy/qwen3.8-flash`. `maxTokens` 256, thinking off.
|
|
176
|
+
- **Caching**: successful decisions are cached within the session by "tool name + normalized arguments" (bash collapses whitespace, others use JSON with sorted keys), so identical calls are classified once; errors and timeouts are not cached.
|
|
177
|
+
- **Cost**: each classification records a `usage` entry with `kind: "permission_classify"`, counted in `/session` cost and RPC stats, never in the context.
|
|
178
|
+
- The classifier can only judge undecided calls as allow or ask; it cannot overturn ①'s deny or ask.
|
|
179
|
+
|
|
180
|
+
## Audit
|
|
181
|
+
|
|
182
|
+
- Every auto decision (allow and ask) records `{ layer: "rule" | "static" | "classifier", decision, reason }`:
|
|
183
|
+
- the `tool_execution_end` event carries `autoDecision`; when asking, the `permission_request` event and the approval request carry `autoDecision` (the dialog shows "Auto: reason").
|
|
184
|
+
- `/permissions` shows the latest 20 decisions (tool, summary, tier, result, reason).
|
|
185
|
+
- The input of the `PreToolUse` hook is unchanged; the `permissionMode` field can take the new values `auto` and `allowlist`.
|
|
186
|
+
|
|
187
|
+
## Configuration
|
|
188
|
+
|
|
189
|
+
```jsonc
|
|
190
|
+
{
|
|
191
|
+
"permission": {
|
|
192
|
+
"mode": "auto",
|
|
193
|
+
"autoModel": "packy/qwen3.8-flash",
|
|
194
|
+
"autoSafeCommands": ["just test", "make fmt"],
|
|
195
|
+
"allow": ["bash(npm run e2e)"],
|
|
196
|
+
"deny": ["bash(terraform *)"],
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
allowlist in CI:
|
|
202
|
+
|
|
203
|
+
```sh
|
|
204
|
+
ama -p "fix lint and run the tests" --permission-mode allowlist \
|
|
205
|
+
--allow 'write(src/**)' --allow 'edit(src/**)' --allow 'bash(pnpm lint*)' --allow 'bash(pnpm test*)'
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Known limitations
|
|
209
|
+
|
|
210
|
+
- Static judgement looks at the command text, not at what the command really reads: `grep -r token .` reads the project's `.env` and is allowed by the safe list. For stricter behavior, add deny rules for `.env` (`read(**/.env*)`, `bash(*.env*)`).
|
|
211
|
+
- "The project directory" is the cwd and does not follow symbolic links; when started in a subdirectory, parent directories count as outside the project.
|
|
212
|
+
- Commands like `npm test` / `make test` run the project's own scripts; the safe list allows them as "running tests and builds inside the project". For untrusted repositories use `default` or `plan`.
|
|
213
|
+
- Commands prefixed with `sudo` / `doas` are never safe, even when followed by a safe command (`sudo` itself is on the dangerous-command list and asks).
|
|
214
|
+
- The classifier is a model's judgement, not a security boundary. The rule tier before it makes no model calls and can be reviewed; write deny rules for operations that are truly unacceptable.
|