@armadra/agent 0.3.0 → 0.5.0
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 +257 -0
- package/README.md +263 -95
- package/THIRD_PARTY_NOTICES.md +34 -0
- package/dist/acp.d.ts +18 -0
- package/dist/acp.js +19 -0
- package/dist/agent/limits.d.ts +38 -0
- package/dist/agent/limits.js +127 -0
- package/dist/agent/loop-guard.d.ts +38 -0
- package/dist/agent/loop-guard.js +95 -0
- package/dist/agent/loop.d.ts +4 -0
- package/dist/agent/loop.js +7 -0
- package/dist/agent/prompt-rules.d.ts +12 -0
- package/dist/agent/prompt-rules.js +18 -0
- package/dist/agent/reminders.d.ts +59 -0
- package/dist/agent/reminders.js +327 -0
- package/dist/agent/retry.d.ts +1 -1
- package/dist/agent/retry.js +2 -1
- package/dist/agent/session-cache.d.ts +5 -0
- package/dist/agent/session-cache.js +18 -2
- package/dist/agent/session-classifier.d.ts +18 -0
- package/dist/agent/session-classifier.js +105 -0
- package/dist/agent/session-compaction.d.ts +35 -6
- package/dist/agent/session-compaction.js +157 -31
- package/dist/agent/session-core.d.ts +40 -1
- package/dist/agent/session-extensions.d.ts +61 -0
- package/dist/agent/session-extensions.js +129 -0
- package/dist/agent/session-images.d.ts +23 -0
- package/dist/agent/session-images.js +97 -0
- package/dist/agent/session-plan.d.ts +21 -0
- package/dist/agent/session-plan.js +524 -0
- package/dist/agent/session-rewind.d.ts +81 -0
- package/dist/agent/session-rewind.js +354 -0
- package/dist/agent/session-run.d.ts +28 -1
- package/dist/agent/session-run.js +157 -6
- package/dist/agent/session-settings.d.ts +49 -0
- package/dist/agent/session-settings.js +95 -0
- package/dist/agent/session-subagent.d.ts +36 -24
- package/dist/agent/session-subagent.js +259 -129
- package/dist/agent/session-sync.d.ts +10 -3
- package/dist/agent/session-sync.js +37 -8
- package/dist/agent/session-telemetry.d.ts +39 -0
- package/dist/agent/session-telemetry.js +231 -0
- package/dist/agent/session-tools.js +63 -3
- package/dist/agent/session.d.ts +33 -29
- package/dist/agent/session.js +91 -126
- package/dist/agent/subagent-registry.d.ts +91 -0
- package/dist/agent/subagent-registry.js +494 -0
- package/dist/agent/system-prompt.d.ts +6 -3
- package/dist/agent/system-prompt.js +7 -2
- package/dist/agent/tool-runner.d.ts +8 -1
- package/dist/agent/tool-runner.js +72 -6
- package/dist/agent/types-w5.d.ts +192 -0
- package/dist/agent/types-w5.js +10 -0
- package/dist/agent/types.d.ts +55 -4
- package/dist/agent/types.js +2 -0
- package/dist/agent/worktree.d.ts +36 -0
- package/dist/agent/worktree.js +86 -0
- package/dist/agents/builtin.d.ts +14 -0
- package/dist/agents/builtin.js +39 -0
- package/dist/agents/catalog.d.ts +43 -0
- package/dist/agents/catalog.js +82 -0
- package/dist/agents/discover.d.ts +35 -0
- package/dist/agents/discover.js +83 -0
- package/dist/agents/external.d.ts +82 -0
- package/dist/agents/external.js +326 -0
- package/dist/agents/parse.d.ts +18 -0
- package/dist/agents/parse.js +116 -0
- package/dist/agents/result.d.ts +32 -0
- package/dist/agents/result.js +67 -0
- package/dist/agents/task-control.d.ts +17 -0
- package/dist/agents/task-control.js +17 -0
- package/dist/agents/task-record.d.ts +78 -0
- package/dist/agents/task-record.js +141 -0
- package/dist/agents/types.d.ts +46 -0
- package/dist/agents/types.js +8 -0
- package/dist/ai/apis/anthropic-compat.d.ts +36 -0
- package/dist/ai/apis/anthropic-compat.js +92 -0
- package/dist/ai/apis/anthropic-messages.js +3 -2
- package/dist/ai/apis/anthropic-request.d.ts +7 -6
- package/dist/ai/apis/anthropic-request.js +10 -28
- package/dist/ai/apis/cache-params.d.ts +11 -2
- package/dist/ai/apis/cache-params.js +25 -6
- package/dist/ai/apis/google-generative-ai.js +3 -2
- package/dist/ai/apis/openai-compat.d.ts +4 -1
- package/dist/ai/apis/openai-compat.js +8 -1
- package/dist/ai/apis/openai-completions.js +3 -2
- package/dist/ai/apis/openai-responses.js +3 -2
- package/dist/ai/http.d.ts +28 -6
- package/dist/ai/http.js +41 -8
- package/dist/ai/image-limits.d.ts +45 -0
- package/dist/ai/image-limits.js +68 -0
- package/dist/ai/providers/builtin.d.ts +18 -6
- package/dist/ai/providers/builtin.js +135 -6
- package/dist/ai/providers/catalog-data.js +17 -13
- package/dist/ai/providers/catalog.d.ts +60 -7
- package/dist/ai/providers/catalog.js +197 -38
- package/dist/ai/providers/channels.d.ts +33 -3
- package/dist/ai/providers/channels.js +108 -7
- package/dist/ai/providers/enrich.d.ts +6 -3
- package/dist/ai/providers/enrich.js +19 -4
- package/dist/ai/providers/models-dev-cache.d.ts +28 -24
- package/dist/ai/providers/models-dev-cache.js +92 -78
- package/dist/ai/providers/models-dev-data.d.ts +7 -0
- package/dist/ai/providers/models-dev-data.js +32 -0
- package/dist/ai/providers/models-dev-snapshot.d.ts +50 -0
- package/dist/ai/providers/models-dev-snapshot.js +137 -0
- package/dist/ai/providers/models-dev.d.ts +51 -10
- package/dist/ai/providers/models-dev.js +132 -39
- package/dist/ai/providers/registry.d.ts +28 -11
- package/dist/ai/providers/registry.js +112 -65
- package/dist/ai/providers/suggest.d.ts +18 -0
- package/dist/ai/providers/suggest.js +72 -0
- package/dist/ai/sse.d.ts +6 -2
- package/dist/ai/sse.js +22 -2
- package/dist/ai/types.d.ts +37 -4
- package/dist/ai/types.js +5 -0
- package/dist/bundle/ama.cjs +41979 -21147
- package/dist/checkpoints/backend.d.ts +61 -0
- package/dist/checkpoints/backend.js +135 -0
- package/dist/checkpoints/blobs.d.ts +60 -0
- package/dist/checkpoints/blobs.js +203 -0
- package/dist/checkpoints/gc.d.ts +47 -0
- package/dist/checkpoints/gc.js +144 -0
- package/dist/checkpoints/git-head.d.ts +15 -0
- package/dist/checkpoints/git-head.js +89 -0
- package/dist/checkpoints/index.d.ts +17 -0
- package/dist/checkpoints/index.js +17 -0
- package/dist/checkpoints/replay.d.ts +48 -0
- package/dist/checkpoints/replay.js +154 -0
- package/dist/checkpoints/restore.d.ts +86 -0
- package/dist/checkpoints/restore.js +263 -0
- package/dist/checkpoints/settings.d.ts +14 -0
- package/dist/checkpoints/settings.js +23 -0
- package/dist/checkpoints/shadow-git.d.ts +108 -0
- package/dist/checkpoints/shadow-git.js +491 -0
- package/dist/checkpoints/shadow-restore.d.ts +25 -0
- package/dist/checkpoints/shadow-restore.js +128 -0
- package/dist/checkpoints/tracker.d.ts +64 -0
- package/dist/checkpoints/tracker.js +192 -0
- package/dist/checkpoints/types.d.ts +99 -0
- package/dist/checkpoints/types.js +12 -0
- package/dist/cli/args.d.ts +26 -7
- package/dist/cli/args.js +75 -82
- package/dist/cli/bootstrap.js +40 -4
- package/dist/cli/codemode-notice.d.ts +21 -0
- package/dist/cli/codemode-notice.js +56 -0
- package/dist/cli/compose-agents.d.ts +27 -0
- package/dist/cli/compose-agents.js +111 -0
- package/dist/cli/compose-extensions.d.ts +29 -0
- package/dist/cli/compose-extensions.js +44 -0
- package/dist/cli/compose-session.d.ts +8 -0
- package/dist/cli/compose-session.js +76 -2
- package/dist/cli/compose-store.d.ts +1 -1
- package/dist/cli/compose-store.js +3 -1
- package/dist/cli/compose.d.ts +17 -4
- package/dist/cli/compose.js +60 -14
- package/dist/cli/default-model.d.ts +38 -1
- package/dist/cli/default-model.js +96 -9
- package/dist/cli/deps.d.ts +42 -0
- package/dist/cli/exit-codes.d.ts +12 -0
- package/dist/cli/exit-codes.js +15 -0
- package/dist/cli/fake-visibility.d.ts +13 -0
- package/dist/cli/fake-visibility.js +26 -0
- package/dist/cli/from-prompt.d.ts +18 -0
- package/dist/cli/from-prompt.js +49 -0
- package/dist/cli/help-text.d.ts +4 -0
- package/dist/cli/help-text.js +102 -0
- package/dist/cli/main.d.ts +9 -2
- package/dist/cli/main.js +77 -3
- package/dist/cli/proxy.d.ts +51 -0
- package/dist/cli/proxy.js +135 -0
- package/dist/cli/startup-screen.d.ts +29 -0
- package/dist/cli/startup-screen.js +51 -2
- package/dist/cli/startup-steps.d.ts +1 -1
- package/dist/cli/startup-steps.js +21 -13
- package/dist/cli/subcommands/config.d.ts +22 -3
- package/dist/cli/subcommands/config.js +119 -21
- package/dist/cli/subcommands/context.js +4 -1
- package/dist/cli/subcommands/doctor.js +33 -1
- package/dist/cli/subcommands/init.js +2 -1
- package/dist/cli/subcommands/models-discover.d.ts +15 -9
- package/dist/cli/subcommands/models-discover.js +58 -52
- package/dist/cli/subcommands/models.d.ts +2 -0
- package/dist/cli/subcommands/models.js +33 -14
- package/dist/cli/subcommands/probe-runner.d.ts +96 -0
- package/dist/cli/subcommands/probe-runner.js +264 -0
- package/dist/cli/subcommands/providers-probe.d.ts +34 -0
- package/dist/cli/subcommands/providers-probe.js +87 -0
- package/dist/cli/subcommands/providers.d.ts +3 -2
- package/dist/cli/subcommands/providers.js +53 -51
- package/dist/cli/subcommands/sessions-export.d.ts +10 -0
- package/dist/cli/subcommands/sessions-export.js +59 -0
- package/dist/cli/subcommands/sessions-search.d.ts +13 -0
- package/dist/cli/subcommands/sessions-search.js +103 -0
- package/dist/cli/subcommands/sessions.d.ts +6 -3
- package/dist/cli/subcommands/sessions.js +58 -3
- package/dist/cli/subcommands/stats.d.ts +17 -0
- package/dist/cli/subcommands/stats.js +198 -0
- package/dist/cli/system-prompt-arg.d.ts +11 -0
- package/dist/cli/system-prompt-arg.js +34 -0
- package/dist/codemode/capability.d.ts +24 -7
- package/dist/codemode/capability.js +38 -10
- package/dist/codemode/host-side.d.ts +14 -0
- package/dist/codemode/host-side.js +24 -1
- package/dist/codemode/modes.d.ts +4 -11
- package/dist/codemode/modes.js +5 -27
- package/dist/codemode/tool.d.ts +18 -14
- package/dist/codemode/tool.js +76 -31
- package/dist/compaction/breaker.d.ts +25 -9
- package/dist/compaction/breaker.js +47 -17
- package/dist/compaction/estimate.d.ts +11 -3
- package/dist/compaction/estimate.js +64 -22
- package/dist/compaction/image-budget.d.ts +45 -0
- package/dist/compaction/image-budget.js +115 -0
- package/dist/compaction/post-compact.d.ts +38 -0
- package/dist/compaction/post-compact.js +152 -0
- package/dist/compaction/protect.d.ts +27 -0
- package/dist/compaction/protect.js +56 -0
- package/dist/compaction/prune-tier.d.ts +58 -12
- package/dist/compaction/prune-tier.js +120 -54
- package/dist/compaction/summarize-tier.d.ts +23 -4
- package/dist/compaction/summarize-tier.js +100 -29
- package/dist/config/checker.d.ts +28 -0
- package/dist/config/checker.js +97 -0
- package/dist/config/init.d.ts +6 -2
- package/dist/config/init.js +12 -5
- package/dist/config/json-schema.d.ts +1 -0
- package/dist/config/json-schema.js +98 -4
- package/dist/config/key-docs.d.ts +22 -0
- package/dist/config/key-docs.js +174 -0
- package/dist/config/merge.d.ts +12 -9
- package/dist/config/merge.js +102 -13
- package/dist/config/profile.d.ts +2 -0
- package/dist/config/profile.js +2 -0
- package/dist/config/schema-w5.d.ts +18 -0
- package/dist/config/schema-w5.js +109 -0
- package/dist/config/schema.d.ts +5 -9
- package/dist/config/schema.js +91 -118
- package/dist/config/types-w5.d.ts +118 -0
- package/dist/config/types-w5.js +20 -0
- package/dist/config/types.d.ts +84 -7
- package/dist/config/types.js +29 -1
- package/dist/drivers/acp/client.d.ts +57 -0
- package/dist/drivers/acp/client.js +160 -0
- package/dist/drivers/acp/driver.d.ts +31 -0
- package/dist/drivers/acp/driver.js +274 -0
- package/dist/drivers/acp/testing/fake-agent-main.d.ts +5 -0
- package/dist/drivers/acp/testing/fake-agent-main.js +7 -0
- package/dist/drivers/acp/testing/fake-agent.d.ts +27 -0
- package/dist/drivers/acp/testing/fake-agent.js +211 -0
- package/dist/drivers/acp/types.d.ts +285 -0
- package/dist/drivers/acp/types.js +36 -0
- package/dist/drivers/agents.d.ts +58 -0
- package/dist/drivers/agents.js +142 -0
- package/dist/drivers/base.d.ts +35 -0
- package/dist/drivers/base.js +59 -0
- package/dist/drivers/catalog.d.ts +46 -0
- package/dist/drivers/catalog.js +167 -0
- package/dist/drivers/env.d.ts +20 -0
- package/dist/drivers/env.js +46 -0
- package/dist/drivers/host-runners.d.ts +18 -0
- package/dist/drivers/host-runners.js +45 -0
- package/dist/drivers/jsonrpc.d.ts +58 -0
- package/dist/drivers/jsonrpc.js +180 -0
- package/dist/drivers/native/claude-normalize.d.ts +46 -0
- package/dist/drivers/native/claude-normalize.js +106 -0
- package/dist/drivers/native/claude-stream.d.ts +29 -0
- package/dist/drivers/native/claude-stream.js +456 -0
- package/dist/drivers/native/codex-app-server.d.ts +26 -0
- package/dist/drivers/native/codex-app-server.js +407 -0
- package/dist/drivers/native/codex-normalize.d.ts +38 -0
- package/dist/drivers/native/codex-normalize.js +124 -0
- package/dist/drivers/native/oneshot.d.ts +28 -0
- package/dist/drivers/native/oneshot.js +312 -0
- package/dist/drivers/permissions.d.ts +40 -0
- package/dist/drivers/permissions.js +92 -0
- package/dist/drivers/pids.d.ts +32 -0
- package/dist/drivers/pids.js +93 -0
- package/dist/drivers/pool.d.ts +28 -0
- package/dist/drivers/pool.js +96 -0
- package/dist/drivers/probe.d.ts +47 -0
- package/dist/drivers/probe.js +172 -0
- package/dist/drivers/process.d.ts +48 -0
- package/dist/drivers/process.js +100 -0
- package/dist/drivers/runner.d.ts +61 -0
- package/dist/drivers/runner.js +388 -0
- package/dist/drivers/store.d.ts +49 -0
- package/dist/drivers/store.js +91 -0
- package/dist/drivers/turn.d.ts +41 -0
- package/dist/drivers/turn.js +99 -0
- package/dist/drivers/types.d.ts +122 -0
- package/dist/drivers/types.js +11 -0
- package/dist/git/info.d.ts +75 -0
- package/dist/git/info.js +191 -0
- package/dist/hooks/protocol.js +6 -1
- package/dist/hooks/types.d.ts +10 -1
- package/dist/hooks/types.js +2 -0
- package/dist/host/api-impl.d.ts +7 -0
- package/dist/host/api-impl.js +15 -0
- package/dist/host/types.d.ts +24 -2
- package/dist/host/types.js +4 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/modes/acp/acp-events.d.ts +46 -0
- package/dist/modes/acp/acp-events.js +233 -0
- package/dist/modes/acp/acp-mode.d.ts +17 -0
- package/dist/modes/acp/acp-mode.js +47 -0
- package/dist/modes/acp/acp-server.d.ts +79 -0
- package/dist/modes/acp/acp-server.js +315 -0
- package/dist/modes/commands-core.d.ts +7 -1
- package/dist/modes/commands-core.js +61 -5
- package/dist/modes/image-input.d.ts +12 -4
- package/dist/modes/image-input.js +22 -5
- package/dist/modes/interactive/agent-panels.d.ts +14 -0
- package/dist/modes/interactive/agent-panels.js +103 -0
- package/dist/modes/interactive/agent-ui.d.ts +73 -0
- package/dist/modes/interactive/agent-ui.js +234 -0
- package/dist/modes/interactive/approval-dialog.d.ts +40 -7
- package/dist/modes/interactive/approval-dialog.js +192 -35
- package/dist/modes/interactive/approval-merge.d.ts +41 -0
- package/dist/modes/interactive/approval-merge.js +89 -0
- package/dist/modes/interactive/clipboard-paste.d.ts +18 -0
- package/dist/modes/interactive/clipboard-paste.js +28 -0
- package/dist/modes/interactive/commands.d.ts +20 -3
- package/dist/modes/interactive/commands.js +75 -16
- package/dist/modes/interactive/double-esc.d.ts +20 -0
- package/dist/modes/interactive/double-esc.js +34 -0
- package/dist/modes/interactive/event-notices.d.ts +32 -0
- package/dist/modes/interactive/event-notices.js +79 -0
- package/dist/modes/interactive/external-editor.d.ts +16 -0
- package/dist/modes/interactive/external-editor.js +39 -0
- package/dist/modes/interactive/interactive-mode.d.ts +16 -2
- package/dist/modes/interactive/interactive-mode.js +184 -202
- package/dist/modes/interactive/key-dispatch.d.ts +18 -2
- package/dist/modes/interactive/key-dispatch.js +53 -6
- package/dist/modes/interactive/line/line-mode.d.ts +3 -1
- package/dist/modes/interactive/line/line-mode.js +28 -9
- package/dist/modes/interactive/line/line-render.d.ts +6 -1
- package/dist/modes/interactive/line/line-render.js +66 -8
- package/dist/modes/interactive/message-view.d.ts +49 -10
- package/dist/modes/interactive/message-view.js +262 -46
- package/dist/modes/interactive/panels.d.ts +35 -0
- package/dist/modes/interactive/panels.js +157 -0
- package/dist/modes/interactive/pickers.d.ts +23 -2
- package/dist/modes/interactive/pickers.js +48 -15
- package/dist/modes/interactive/plan-command.d.ts +40 -0
- package/dist/modes/interactive/plan-command.js +129 -0
- package/dist/modes/interactive/plan-dialog.d.ts +98 -0
- package/dist/modes/interactive/plan-dialog.js +290 -0
- package/dist/modes/interactive/plan-flow.d.ts +34 -0
- package/dist/modes/interactive/plan-flow.js +98 -0
- package/dist/modes/interactive/rewind-command.d.ts +31 -0
- package/dist/modes/interactive/rewind-command.js +106 -0
- package/dist/modes/interactive/rewind-flow.d.ts +37 -0
- package/dist/modes/interactive/rewind-flow.js +151 -0
- package/dist/modes/interactive/rewind-list.d.ts +36 -0
- package/dist/modes/interactive/rewind-list.js +123 -0
- package/dist/modes/interactive/rewind-panel.d.ts +77 -0
- package/dist/modes/interactive/rewind-panel.js +309 -0
- package/dist/modes/interactive/rewind-text.d.ts +40 -0
- package/dist/modes/interactive/rewind-text.js +139 -0
- package/dist/modes/interactive/run-indicator.d.ts +51 -0
- package/dist/modes/interactive/run-indicator.js +189 -0
- package/dist/modes/interactive/session-events.d.ts +24 -0
- package/dist/modes/interactive/session-events.js +96 -0
- package/dist/modes/interactive/startup-header.d.ts +40 -0
- package/dist/modes/interactive/startup-header.js +169 -0
- package/dist/modes/interactive/status-area.d.ts +73 -0
- package/dist/modes/interactive/status-area.js +190 -0
- package/dist/modes/interactive/status-bar.d.ts +107 -16
- package/dist/modes/interactive/status-bar.js +306 -81
- package/dist/modes/interactive/status-line.d.ts +33 -0
- package/dist/modes/interactive/status-line.js +113 -0
- package/dist/modes/interactive/subagent-view.d.ts +56 -0
- package/dist/modes/interactive/subagent-view.js +154 -0
- package/dist/modes/interactive/tasks-report.d.ts +27 -0
- package/dist/modes/interactive/tasks-report.js +114 -0
- package/dist/modes/interactive/tool-summary.d.ts +46 -0
- package/dist/modes/interactive/tool-summary.js +218 -0
- package/dist/modes/interactive/tool-view.d.ts +58 -15
- package/dist/modes/interactive/tool-view.js +233 -145
- package/dist/modes/print/print-mode.d.ts +40 -4
- package/dist/modes/print/print-mode.js +161 -8
- package/dist/modes/rpc/commands.d.ts +9 -0
- package/dist/modes/rpc/commands.js +49 -0
- package/dist/modes/rpc/rpc-mode.js +7 -1
- package/dist/modes/session-report.d.ts +11 -0
- package/dist/modes/session-report.js +48 -1
- package/dist/permissions/auto-safe.d.ts +65 -0
- package/dist/permissions/auto-safe.js +547 -0
- package/dist/permissions/classifier.d.ts +68 -0
- package/dist/permissions/classifier.js +186 -0
- package/dist/permissions/dangerous.d.ts +5 -0
- package/dist/permissions/dangerous.js +1 -1
- package/dist/permissions/modes.d.ts +30 -0
- package/dist/permissions/modes.js +78 -0
- package/dist/permissions/pipeline.d.ts +72 -6
- package/dist/permissions/pipeline.js +306 -11
- package/dist/permissions/protected.d.ts +19 -0
- package/dist/permissions/protected.js +74 -0
- package/dist/permissions/readonly-bash.d.ts +30 -0
- package/dist/permissions/readonly-bash.js +118 -0
- package/dist/permissions/rules.js +3 -0
- package/dist/permissions/types.d.ts +92 -3
- package/dist/permissions/types.js +3 -0
- package/dist/plan/compose.d.ts +9 -0
- package/dist/plan/compose.js +19 -0
- package/dist/plan/controller.d.ts +71 -0
- package/dist/plan/controller.js +27 -0
- package/dist/plan/done-markers.d.ts +17 -0
- package/dist/plan/done-markers.js +51 -0
- package/dist/plan/extract.d.ts +29 -0
- package/dist/plan/extract.js +160 -0
- package/dist/plan/prompts.d.ts +36 -0
- package/dist/plan/prompts.js +89 -0
- package/dist/plan/store.d.ts +37 -0
- package/dist/plan/store.js +90 -0
- package/dist/rpc.d.ts +58 -2
- package/dist/rpc.js +7 -0
- package/dist/sandbox/bash.d.ts +74 -0
- package/dist/sandbox/bash.js +126 -0
- package/dist/sandbox/detect.d.ts +48 -0
- package/dist/sandbox/detect.js +149 -0
- package/dist/sandbox/index.d.ts +5 -0
- package/dist/sandbox/index.js +5 -0
- package/dist/sandbox/profile.d.ts +33 -0
- package/dist/sandbox/profile.js +76 -0
- package/dist/sandbox/wrap.d.ts +29 -0
- package/dist/sandbox/wrap.js +117 -0
- package/dist/sdk.d.ts +42 -5
- package/dist/sdk.js +34 -4
- package/dist/session/export.d.ts +32 -0
- package/dist/session/export.js +187 -0
- package/dist/session/redact.d.ts +15 -0
- package/dist/session/redact.js +55 -0
- package/dist/session/reuse.d.ts +33 -0
- package/dist/session/reuse.js +86 -0
- package/dist/session/scan.d.ts +34 -0
- package/dist/session/scan.js +140 -0
- package/dist/session/search.d.ts +52 -0
- package/dist/session/search.js +211 -0
- package/dist/session/stats-aggregate.d.ts +63 -0
- package/dist/session/stats-aggregate.js +163 -0
- package/dist/session/stats-index.d.ts +26 -0
- package/dist/session/stats-index.js +91 -0
- package/dist/session/stats-scan.d.ts +54 -0
- package/dist/session/stats-scan.js +236 -0
- package/dist/session/types.d.ts +3 -1
- package/dist/session/types.js +1 -0
- package/dist/skills/builtin.d.ts +31 -0
- package/dist/skills/builtin.js +109 -0
- package/dist/skills/discover.d.ts +2 -1
- package/dist/skills/index-prompt.js +5 -8
- package/dist/tools/background-jobs.d.ts +71 -0
- package/dist/tools/background-jobs.js +198 -0
- package/dist/tools/bash.d.ts +53 -1
- package/dist/tools/bash.js +158 -7
- package/dist/tools/clipboard-image.d.ts +44 -0
- package/dist/tools/clipboard-image.js +148 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.js +18 -3
- package/dist/tools/image-file.d.ts +38 -3
- package/dist/tools/image-file.js +81 -10
- package/dist/tools/image-resize.d.ts +58 -0
- package/dist/tools/image-resize.js +97 -0
- package/dist/tools/presets.d.ts +40 -8
- package/dist/tools/presets.js +65 -19
- package/dist/tools/read.d.ts +5 -2
- package/dist/tools/read.js +13 -10
- package/dist/tools/registry.d.ts +7 -1
- package/dist/tools/registry.js +27 -4
- package/dist/tools/task-ctl.d.ts +22 -0
- package/dist/tools/task-ctl.js +116 -0
- package/dist/tools/task.d.ts +22 -10
- package/dist/tools/task.js +66 -26
- package/dist/tools/todo.d.ts +22 -2
- package/dist/tools/todo.js +58 -14
- package/dist/tools/truncate.d.ts +15 -0
- package/dist/tools/truncate.js +25 -0
- package/dist/tools/types.d.ts +113 -0
- package/dist/tools/types.js +5 -0
- package/dist/tools/write.js +3 -0
- package/dist/tui/component.d.ts +8 -2
- package/dist/tui/component.js +3 -1
- package/dist/tui/components/box.d.ts +6 -1
- package/dist/tui/components/box.js +16 -6
- package/dist/tui/components/card.d.ts +23 -0
- package/dist/tui/components/card.js +37 -0
- package/dist/tui/components/editor-history.d.ts +6 -0
- package/dist/tui/components/editor-history.js +45 -0
- package/dist/tui/components/editor-paste.d.ts +1 -1
- package/dist/tui/components/editor-paste.js +4 -4
- package/dist/tui/components/editor.d.ts +11 -5
- package/dist/tui/components/editor.js +52 -58
- package/dist/tui/components/key-value.d.ts +3 -0
- package/dist/tui/components/key-value.js +16 -6
- package/dist/tui/components/loader.d.ts +37 -7
- package/dist/tui/components/loader.js +84 -21
- package/dist/tui/components/markdown.d.ts +5 -1
- package/dist/tui/components/markdown.js +45 -21
- package/dist/tui/components/meter.d.ts +3 -3
- package/dist/tui/components/meter.js +13 -11
- package/dist/tui/components/select-list.d.ts +23 -1
- package/dist/tui/components/select-list.js +76 -13
- package/dist/tui/glyphs.d.ts +72 -0
- package/dist/tui/glyphs.js +118 -0
- package/dist/tui/keybindings.d.ts +5 -0
- package/dist/tui/keybindings.js +5 -0
- package/dist/tui/theme.d.ts +30 -6
- package/dist/tui/theme.js +103 -17
- package/dist/tui.d.ts +4 -2
- package/dist/tui.js +3 -1
- package/docs/acp.md +78 -0
- package/docs/agents.md +250 -0
- package/docs/codemode.md +28 -10
- package/docs/hooks.md +36 -32
- package/docs/permissions.md +212 -0
- package/docs/plan.md +107 -0
- package/docs/providers.md +261 -62
- package/docs/rewind-plan.md +181 -0
- package/docs/rpc.md +127 -40
- package/docs/sandbox.md +215 -0
- package/docs/session-format.md +43 -22
- package/docs/sessions.md +174 -0
- package/docs/tui-design.md +751 -0
- package/docs/tui.md +260 -64
- package/package.json +15 -2
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 审批对话框(设计 §12.6):模式层的 UI `ApprovalBroker`,底部覆盖层。[B7]
|
|
3
3
|
*
|
|
4
|
-
* -
|
|
4
|
+
* - 标题行:来源标注 + 工具名 + 原因标签。来源(W5-U):外部 Agent 的请求(`context.origin`)标
|
|
5
|
+
* `[claude · 会话 abc12345]`,正文取 `origin.toolCall` 的标题 / 种类 / 路径;task 子 Agent(`depth > 0`)标
|
|
6
|
+
* `[task:<agent>]`(类型名经 `ApprovalHost.taskAgent` 查注册表,查不到为 `[task]`);外部 Agent 首次运行确认
|
|
7
|
+
* (`toolName: "task"` 且输入带 `note`)标题为「首次运行外部 Agent」,正文是说明与模式;选项始终是
|
|
8
|
+
* 允许 / 本会话允许 / 拒绝三项(外部 Agent 的 `reject_always` 不由这里选);
|
|
5
9
|
* - 输入:bash 显示命令全文,write 显示路径与行数,edit 显示路径与每处修改的 −/+ 摘要,其它显示
|
|
6
10
|
* 一行摘要;`v` 展开 / 收起完整输入(JSON);
|
|
7
11
|
* - 执行前预览(W3-B9a-2,`request.preview`):输入摘要之后列出会碰到的路径与规模,danger 红、
|
|
8
12
|
* warn 黄、info 暗色;`other` 类预览与输入摘要重复,不显示;
|
|
9
13
|
* - 原因:mode(当前权限模式需要确认)/ dangerous / hook + Hook 给的文本;
|
|
10
|
-
* -
|
|
14
|
+
* - 选项(终端界面视觉设计 v1 §3.11):编号列表 `1. 允许 y` / `2. 本会话允许同类 a` / `3. 拒绝 n Esc`,
|
|
15
|
+
* 选中行 `›` + selection 底色;缺省选中:危险命令 → 拒绝,其余 → 允许。按键 `y / a / n / Esc / Ctrl+C /
|
|
16
|
+
* 1 2 3 / ↑↓ Enter / v` 都有效;
|
|
17
|
+
* - 标题按原因:需要确认 / 危险命令 / Hook 要求确认(子 Agent 发起前缀 `[task] `);边框颜色随预览严重度
|
|
18
|
+
* (danger error、warn warning);宽 < 56 时紧凑:工具名单独一行、去掉空行、按键提示缩短;
|
|
11
19
|
* - 超时与中断:broker 链在超时(缺省 10 分钟)或运行被中断时 abort `signal`,对话框关闭并返回
|
|
12
20
|
* undefined(链按 deny 处理),消息区留一行说明。
|
|
13
21
|
*
|
|
14
22
|
* broker 链本身串行化审批,所以同一时刻最多一个对话框。
|
|
15
23
|
*/
|
|
24
|
+
import { AUTO_LAYER_TEXT, isPermissionMode, permissionModeLabel } from "../../permissions/modes.js";
|
|
16
25
|
import { previewDisplayLines } from "../../permissions/preview.js";
|
|
17
|
-
import { Box,
|
|
26
|
+
import { Box, defaultKeybindings, matchesKey, padToWidth, truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "../../tui.js";
|
|
27
|
+
import { displayPath, flat } from "./tool-summary.js";
|
|
18
28
|
import { toolSummary } from "./tool-view.js";
|
|
19
29
|
const COMMAND_LINES = 8;
|
|
20
30
|
const EDIT_LINES = 3;
|
|
@@ -28,19 +38,83 @@ function lines(text, max) {
|
|
|
28
38
|
function record(input) {
|
|
29
39
|
return typeof input === "object" && input !== null ? input : {};
|
|
30
40
|
}
|
|
31
|
-
/**
|
|
41
|
+
/** 外部 Agent 首次运行确认(`requestApproval` 发来的 `task` 请求,输入带 `note`)。 */
|
|
42
|
+
export function isFirstRunRequest(request) {
|
|
43
|
+
return request.toolName === "task" && typeof record(request.input)["note"] === "string";
|
|
44
|
+
}
|
|
45
|
+
/** 来源标注:`[claude · 会话 abc12345]` / `[task:explore]` / `[task]`;主会话发起为 undefined。 */
|
|
46
|
+
export function sourceLabel(request, taskAgent) {
|
|
47
|
+
const context = request.context;
|
|
48
|
+
const origin = context?.origin;
|
|
49
|
+
if (origin !== undefined)
|
|
50
|
+
return `[${origin.agent} · 会话 ${origin.sessionId.slice(0, 8)}]`;
|
|
51
|
+
if ((context?.depth ?? 0) <= 0)
|
|
52
|
+
return undefined;
|
|
53
|
+
const taskId = context?.taskId;
|
|
54
|
+
const agent = taskId === undefined ? undefined : taskAgent?.(taskId);
|
|
55
|
+
return agent === undefined ? "[task]" : `[task:${agent}]`;
|
|
56
|
+
}
|
|
57
|
+
/** 原因 → 标题文字(带来源标注)。 */
|
|
58
|
+
export function approvalTitle(request, taskAgent) {
|
|
59
|
+
const label = sourceLabel(request, taskAgent);
|
|
60
|
+
const reason = isFirstRunRequest(request)
|
|
61
|
+
? "首次运行外部 Agent"
|
|
62
|
+
: request.reason === "dangerous"
|
|
63
|
+
? "危险命令"
|
|
64
|
+
: request.reason === "hook"
|
|
65
|
+
? "Hook 要求确认"
|
|
66
|
+
: "需要确认";
|
|
67
|
+
return label === undefined ? reason : `${label} ${reason}`;
|
|
68
|
+
}
|
|
69
|
+
/** 外部 Agent 请求的正文:标题 + 种类、涉及路径、输入摘要。 */
|
|
70
|
+
function originLines(origin, theme, cwd) {
|
|
71
|
+
const out = [];
|
|
72
|
+
for (const path of (origin.toolCall.locations ?? []).slice(0, 3))
|
|
73
|
+
out.push(theme.fg("muted", displayPath(path, cwd)));
|
|
74
|
+
const hidden = (origin.toolCall.locations?.length ?? 0) - 3;
|
|
75
|
+
if (hidden > 0)
|
|
76
|
+
out.push(theme.fg("dim", `… 另 ${hidden} 个路径`));
|
|
77
|
+
const summary = origin.toolCall.inputSummary;
|
|
78
|
+
if (summary !== undefined && summary.trim() !== "") {
|
|
79
|
+
const { shown, hidden: more } = lines(summary, COMMAND_LINES);
|
|
80
|
+
out.push(...shown.map((l) => theme.fg("code", l)));
|
|
81
|
+
if (more > 0)
|
|
82
|
+
out.push(theme.fg("dim", `… 另 ${more} 行`));
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
/** 对话框正文(不含选项与按键行)。 */
|
|
32
87
|
export function describeRequest(request, theme, options = {}) {
|
|
33
88
|
const out = [];
|
|
34
|
-
const
|
|
89
|
+
const label = sourceLabel(request, options.taskAgent);
|
|
90
|
+
const task = label === undefined ? "" : theme.fg("warning", `${label} `);
|
|
91
|
+
const origin = request.context?.origin;
|
|
92
|
+
const firstRun = isFirstRunRequest(request);
|
|
35
93
|
const tag = request.reason === "dangerous"
|
|
36
94
|
? theme.fg("error", "危险命令")
|
|
37
95
|
: request.reason === "hook"
|
|
38
96
|
? theme.fg("warning", "Hook 要求确认")
|
|
39
|
-
:
|
|
40
|
-
|
|
97
|
+
: origin !== undefined
|
|
98
|
+
? theme.fg("dim", origin.toolCall.kind)
|
|
99
|
+
: theme.fg("dim", firstRun ? "首次运行" : "需要确认");
|
|
41
100
|
const input = record(request.input);
|
|
101
|
+
const name = origin !== undefined
|
|
102
|
+
? theme.bold(theme.fg("tool", flat(origin.toolCall.title)))
|
|
103
|
+
: firstRun
|
|
104
|
+
? theme.bold(theme.fg("tool", `task ${String(input["agent"] ?? "")}`.trim()))
|
|
105
|
+
: theme.bold(theme.fg("tool", request.toolName));
|
|
106
|
+
out.push(options.compact === true ? `${task}${name}` : `${task}${name} ${tag}`);
|
|
42
107
|
const more = (n) => theme.fg("dim", `… 另 ${n} 行(v 查看)`);
|
|
43
|
-
if (options.expanded
|
|
108
|
+
if (origin !== undefined && options.expanded !== true) {
|
|
109
|
+
out.push(...originLines(origin, theme, options.cwd));
|
|
110
|
+
}
|
|
111
|
+
else if (firstRun && options.expanded !== true) {
|
|
112
|
+
out.push(String(input["note"]));
|
|
113
|
+
const mode = input["mode"];
|
|
114
|
+
if (typeof mode === "string")
|
|
115
|
+
out.push(theme.fg("dim", `模式 ${isPermissionMode(mode) ? permissionModeLabel(mode) : mode}`));
|
|
116
|
+
}
|
|
117
|
+
else if (options.expanded === true) {
|
|
44
118
|
const json = JSON.stringify(request.input, null, 2) ?? String(request.input);
|
|
45
119
|
const { shown, hidden } = lines(json, FULL_INPUT_LINES);
|
|
46
120
|
out.push(...shown.map((l) => theme.fg("code", l)));
|
|
@@ -80,46 +154,60 @@ export function describeRequest(request, theme, options = {}) {
|
|
|
80
154
|
const summary = toolSummary(request.toolName, input, options.cwd);
|
|
81
155
|
if (summary !== "")
|
|
82
156
|
out.push(summary);
|
|
157
|
+
const agent = input["agent"];
|
|
158
|
+
const runner = request.toolName === "task" && typeof agent === "string"
|
|
159
|
+
? options.externalRunner?.(agent)
|
|
160
|
+
: undefined;
|
|
161
|
+
// 与首次运行确认合并(approval-merge.ts):允许即同意本会话以你的登录运行该 CLI
|
|
162
|
+
if (runner !== undefined)
|
|
163
|
+
out.push(theme.fg("warning", `外部 Agent ${agent}:以你在 ${runner} CLI 的登录运行(含本会话首次运行确认)`));
|
|
83
164
|
}
|
|
84
165
|
const severity = request.preview?.severity;
|
|
85
166
|
const color = severity === "danger" ? "error" : severity === "warn" ? "warning" : "dim";
|
|
86
167
|
out.push(...previewDisplayLines(request.preview).map((l) => theme.fg(color, l)));
|
|
87
|
-
|
|
168
|
+
const auto = request.autoDecision;
|
|
169
|
+
if (origin !== undefined || firstRun) {
|
|
170
|
+
// 外部 Agent 的请求由它自己的策略决定要问;首次运行确认的说明已在正文
|
|
171
|
+
if (origin !== undefined)
|
|
172
|
+
out.push(theme.fg("dim", `${origin.agent} 请求确认`));
|
|
173
|
+
else
|
|
174
|
+
out.push(theme.fg("dim", "本会话首次以你的登录运行该 CLI"));
|
|
175
|
+
}
|
|
176
|
+
else if (request.reason === "hook") {
|
|
88
177
|
out.push(theme.fg("warning", `Hook:${request.hookReason ?? "(无说明)"}`));
|
|
89
178
|
}
|
|
90
179
|
else if (request.reason === "dangerous") {
|
|
91
180
|
out.push(theme.fg("error", "这条命令可能有破坏性,请确认"));
|
|
92
181
|
}
|
|
182
|
+
else if (auto !== undefined) {
|
|
183
|
+
out.push(theme.fg("warning", `Auto ${AUTO_LAYER_TEXT[auto.layer]}:${auto.reason}`));
|
|
184
|
+
}
|
|
93
185
|
else if (options.permissionMode !== undefined) {
|
|
94
|
-
|
|
186
|
+
const mode = options.permissionMode;
|
|
187
|
+
const label = isPermissionMode(mode) ? permissionModeLabel(mode) : mode;
|
|
188
|
+
out.push(theme.fg("dim", `权限模式 ${label} 下需要确认`));
|
|
95
189
|
}
|
|
96
190
|
return out;
|
|
97
191
|
}
|
|
98
|
-
export const
|
|
192
|
+
export const APPROVAL_OPTIONS = [
|
|
193
|
+
{ decision: "allow", label: "允许", keys: "y" },
|
|
194
|
+
{ decision: "allow_session", label: "本会话允许同类", keys: "a" },
|
|
195
|
+
{ decision: "deny", label: "拒绝", keys: "n Esc" },
|
|
196
|
+
];
|
|
197
|
+
/** 宽度低于它(Box 外宽)时用紧凑布局。 */
|
|
198
|
+
const COMPACT_WIDTH = 56;
|
|
99
199
|
class ApprovalDialog {
|
|
100
200
|
request;
|
|
101
201
|
host;
|
|
102
202
|
decide;
|
|
103
203
|
focused = false;
|
|
104
204
|
expanded = false;
|
|
105
|
-
|
|
205
|
+
selected;
|
|
106
206
|
constructor(request, host, decide) {
|
|
107
207
|
this.request = request;
|
|
108
208
|
this.host = host;
|
|
109
209
|
this.decide = decide;
|
|
110
|
-
this.
|
|
111
|
-
}
|
|
112
|
-
rebuild() {
|
|
113
|
-
const { theme } = this.host;
|
|
114
|
-
this.body.clear();
|
|
115
|
-
const options = {
|
|
116
|
-
permissionMode: this.host.permissionMode(),
|
|
117
|
-
expanded: this.expanded,
|
|
118
|
-
};
|
|
119
|
-
if (this.host.cwd !== undefined)
|
|
120
|
-
options.cwd = this.host.cwd;
|
|
121
|
-
this.body.addChild(new Text(describeRequest(this.request, theme, options).join("\n")));
|
|
122
|
-
this.body.addChild(new Text(theme.fg("accent", APPROVAL_KEYS_HINT)));
|
|
210
|
+
this.selected = request.reason === "dangerous" ? 2 : 0;
|
|
123
211
|
}
|
|
124
212
|
handleInput(data) {
|
|
125
213
|
const keys = this.host.keybindings ?? defaultKeybindings;
|
|
@@ -134,17 +222,78 @@ class ApprovalDialog {
|
|
|
134
222
|
keys.matches(data, "tui.select.cancel")) {
|
|
135
223
|
this.decide("deny");
|
|
136
224
|
}
|
|
137
|
-
else if (
|
|
138
|
-
this.
|
|
139
|
-
|
|
225
|
+
else if (/^[1-3]$/.test(data))
|
|
226
|
+
this.decide(APPROVAL_OPTIONS[Number(data) - 1].decision);
|
|
227
|
+
else if (keys.matches(data, "tui.select.up")) {
|
|
228
|
+
this.selected = (this.selected + APPROVAL_OPTIONS.length - 1) % APPROVAL_OPTIONS.length;
|
|
140
229
|
}
|
|
230
|
+
else if (keys.matches(data, "tui.select.down")) {
|
|
231
|
+
this.selected = (this.selected + 1) % APPROVAL_OPTIONS.length;
|
|
232
|
+
}
|
|
233
|
+
else if (matchesKey(data, "enter"))
|
|
234
|
+
this.decide(APPROVAL_OPTIONS[this.selected].decision);
|
|
235
|
+
else if (key === "v")
|
|
236
|
+
this.expanded = !this.expanded;
|
|
141
237
|
}
|
|
238
|
+
/** `width` 是 Box 内宽;紧凑与否按外宽(+ 4)判断。 */
|
|
142
239
|
render(width) {
|
|
143
|
-
|
|
240
|
+
const { theme } = this.host;
|
|
241
|
+
const compact = width + 4 < COMPACT_WIDTH;
|
|
242
|
+
const options = {
|
|
243
|
+
permissionMode: this.host.permissionMode(),
|
|
244
|
+
expanded: this.expanded,
|
|
245
|
+
compact,
|
|
246
|
+
};
|
|
247
|
+
if (this.host.cwd !== undefined)
|
|
248
|
+
options.cwd = this.host.cwd;
|
|
249
|
+
if (this.host.taskAgent !== undefined)
|
|
250
|
+
options.taskAgent = this.host.taskAgent;
|
|
251
|
+
if (this.host.externalRunner !== undefined)
|
|
252
|
+
options.externalRunner = this.host.externalRunner;
|
|
253
|
+
const body = describeRequest(this.request, theme, options);
|
|
254
|
+
const lines = [];
|
|
255
|
+
// 输入摘要(标题 + 命令)与预览 / 原因之间空一行
|
|
256
|
+
const head = this.inputLines(body);
|
|
257
|
+
for (const line of body.slice(0, head))
|
|
258
|
+
lines.push(...wrapTextWithAnsi(line, width));
|
|
259
|
+
if (!compact && head < body.length)
|
|
260
|
+
lines.push("");
|
|
261
|
+
for (const line of body.slice(head))
|
|
262
|
+
lines.push(...wrapTextWithAnsi(line, width));
|
|
263
|
+
if (!compact)
|
|
264
|
+
lines.push("");
|
|
265
|
+
lines.push(...this.optionLines(width, compact));
|
|
266
|
+
if (!compact)
|
|
267
|
+
lines.push("");
|
|
268
|
+
const arrows = theme.glyphs.arrowUp + theme.glyphs.arrowDown;
|
|
269
|
+
const hint = compact
|
|
270
|
+
? `${arrows} Enter · v 完整输入`
|
|
271
|
+
: `${arrows} 选择 · Enter 确认 · v 完整输入`;
|
|
272
|
+
lines.push(theme.fg("dim", hint));
|
|
273
|
+
return lines.map((l) => truncateToWidth(l, width));
|
|
274
|
+
}
|
|
275
|
+
/** 正文里属于「输入摘要」的行数(首行 + 命令 / 路径 / 修改摘要,止于预览或原因行)。 */
|
|
276
|
+
inputLines(body) {
|
|
277
|
+
const preview = previewDisplayLines(this.request.preview).length;
|
|
278
|
+
const reasonLines = body.length > 0 ? 1 : 0;
|
|
279
|
+
return Math.max(1, body.length - preview - reasonLines);
|
|
144
280
|
}
|
|
145
|
-
|
|
146
|
-
this.
|
|
281
|
+
optionLines(width, compact) {
|
|
282
|
+
const { theme } = this.host;
|
|
283
|
+
const g = theme.glyphs;
|
|
284
|
+
const keyWidth = compact ? 1 : Math.max(...APPROVAL_OPTIONS.map((o) => o.keys.length));
|
|
285
|
+
return APPROVAL_OPTIONS.map((option, i) => {
|
|
286
|
+
const selected = i === this.selected;
|
|
287
|
+
const keys = compact ? option.keys.slice(0, 1) : option.keys;
|
|
288
|
+
const left = `${selected ? g.prompt : " "} ${i + 1}. ${option.label}`;
|
|
289
|
+
const right = keys.padEnd(keyWidth);
|
|
290
|
+
const room = Math.max(1, width - visibleWidth(right) - 1);
|
|
291
|
+
const label = selected ? theme.fg("accent", theme.bold(left)) : left;
|
|
292
|
+
const line = padToWidth(truncateToWidth(label, room), room) + " " + theme.fg("dim", right);
|
|
293
|
+
return selected ? theme.bg("selection", line) : line;
|
|
294
|
+
});
|
|
147
295
|
}
|
|
296
|
+
invalidate() { }
|
|
148
297
|
}
|
|
149
298
|
/** UI broker:每个请求开一个底部覆盖层,等用户按键或 signal abort。 */
|
|
150
299
|
export class ApprovalDialogBroker {
|
|
@@ -177,18 +326,26 @@ export class ApprovalDialogBroker {
|
|
|
177
326
|
const dialog = new ApprovalDialog(request, this.host, settle);
|
|
178
327
|
this.open++;
|
|
179
328
|
this.host.onOpen?.();
|
|
329
|
+
const severity = request.preview?.severity;
|
|
180
330
|
handle = this.host.showOverlay(new Box(dialog, {
|
|
181
|
-
title: (request.
|
|
331
|
+
title: approvalTitle(request, this.host.taskAgent),
|
|
182
332
|
theme: this.host.theme,
|
|
333
|
+
...(severity === "danger"
|
|
334
|
+
? { borderColor: "error" }
|
|
335
|
+
: severity === "warn"
|
|
336
|
+
? { borderColor: "warning" }
|
|
337
|
+
: {}),
|
|
183
338
|
}));
|
|
184
339
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
185
340
|
});
|
|
186
341
|
}
|
|
187
342
|
}
|
|
188
343
|
/** 结果的一行说明(消息区)。 */
|
|
189
|
-
export function approvalOutcomeText(request, outcome) {
|
|
190
|
-
const
|
|
191
|
-
const
|
|
344
|
+
export function approvalOutcomeText(request, outcome, taskAgent) {
|
|
345
|
+
const label = sourceLabel(request, taskAgent);
|
|
346
|
+
const origin = request.context?.origin;
|
|
347
|
+
const tool = origin !== undefined ? flat(origin.toolCall.title, 60) : request.toolName;
|
|
348
|
+
const what = `${label === undefined ? "" : `${label} `}${tool}`;
|
|
192
349
|
switch (outcome) {
|
|
193
350
|
case "allow":
|
|
194
351
|
return `已允许 ${what}`;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* default 模式下 `task(agent="claude")` 会问两次:task 工具调用一次,外部 Agent 本会话首次运行再一次
|
|
3
|
+
* (agents/external.ts 的 `firstRun`)。界面层把它们合并成一次确认。[W5-U]
|
|
4
|
+
*
|
|
5
|
+
* 规则(不放宽权限语义):
|
|
6
|
+
* - 用户在对话框里**允许**了一次 `task` 工具调用,且它的 `agent` 是外部 Agent(类型的 runner 不是
|
|
7
|
+
* ama)——对话框已把「以你在该 CLI 的登录运行」写在正文里——记下 `{agent, 时刻}`;
|
|
8
|
+
* - **紧接着**的下一个审批请求若是同一 Agent 的首次运行确认(`toolName: "task"`、输入带 `note`),其
|
|
9
|
+
* `context.taskId` 对应的任务是该 Agent、且在允许之后才建立(同一次调用产生的任务),并在 60 s 内
|
|
10
|
+
* 到达,就以「允许」自动答复,不再弹框;
|
|
11
|
+
* - 记录只用一次;中间夹了任何别的审批请求、拒绝、超时,都作废——首次运行确认照常弹出。
|
|
12
|
+
*/
|
|
13
|
+
import type { ApprovalBroker, ApprovalDecision, ApprovalRequest } from "../../permissions/types.js";
|
|
14
|
+
export declare const MERGE_WINDOW_MS = 60000;
|
|
15
|
+
export interface FirstRunMergeDeps {
|
|
16
|
+
sessionId(): string;
|
|
17
|
+
now?(): number;
|
|
18
|
+
/** 类型名 → runner(`ama` / `claude` / …);缺省查会话的类型表。 */
|
|
19
|
+
runnerOf?(agent: string): string | undefined;
|
|
20
|
+
/** 任务 id → 类型名与建立时刻;缺省查注册表。 */
|
|
21
|
+
taskOf?(taskId: string): {
|
|
22
|
+
agent: string;
|
|
23
|
+
startedAt: number;
|
|
24
|
+
} | undefined;
|
|
25
|
+
windowMs?: number;
|
|
26
|
+
}
|
|
27
|
+
export declare class FirstRunMerge {
|
|
28
|
+
private readonly deps;
|
|
29
|
+
private pending;
|
|
30
|
+
constructor(deps: FirstRunMergeDeps);
|
|
31
|
+
private now;
|
|
32
|
+
/** `task` 调用的 agent 是外部 Agent 时返回它的 runner。 */
|
|
33
|
+
externalRunner(agent: string): string | undefined;
|
|
34
|
+
private taskOf;
|
|
35
|
+
/** 请求到来:命中合并返回 `allow`(不弹框);否则返回 undefined,并作废记录。 */
|
|
36
|
+
intercept(request: ApprovalRequest): ApprovalDecision | undefined;
|
|
37
|
+
/** 用户答复之后:允许了外部 Agent 的 task 调用就记下。 */
|
|
38
|
+
record(request: ApprovalRequest, decision: ApprovalDecision | undefined): void;
|
|
39
|
+
}
|
|
40
|
+
/** 把合并规则套在界面 broker 外面;自动答复时调 `onMerged`(消息区一行说明)。 */
|
|
41
|
+
export declare function mergingBroker(inner: ApprovalBroker, merge: FirstRunMerge, onMerged?: (request: ApprovalRequest) => void): ApprovalBroker;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* default 模式下 `task(agent="claude")` 会问两次:task 工具调用一次,外部 Agent 本会话首次运行再一次
|
|
3
|
+
* (agents/external.ts 的 `firstRun`)。界面层把它们合并成一次确认。[W5-U]
|
|
4
|
+
*
|
|
5
|
+
* 规则(不放宽权限语义):
|
|
6
|
+
* - 用户在对话框里**允许**了一次 `task` 工具调用,且它的 `agent` 是外部 Agent(类型的 runner 不是
|
|
7
|
+
* ama)——对话框已把「以你在该 CLI 的登录运行」写在正文里——记下 `{agent, 时刻}`;
|
|
8
|
+
* - **紧接着**的下一个审批请求若是同一 Agent 的首次运行确认(`toolName: "task"`、输入带 `note`),其
|
|
9
|
+
* `context.taskId` 对应的任务是该 Agent、且在允许之后才建立(同一次调用产生的任务),并在 60 s 内
|
|
10
|
+
* 到达,就以「允许」自动答复,不再弹框;
|
|
11
|
+
* - 记录只用一次;中间夹了任何别的审批请求、拒绝、超时,都作废——首次运行确认照常弹出。
|
|
12
|
+
*/
|
|
13
|
+
import { taskRegistryView } from "../../agent/subagent-registry.js";
|
|
14
|
+
import { isFirstRunRequest } from "./approval-dialog.js";
|
|
15
|
+
import { listAgents } from "./tasks-report.js";
|
|
16
|
+
export const MERGE_WINDOW_MS = 60_000;
|
|
17
|
+
function input(request) {
|
|
18
|
+
const value = request.input;
|
|
19
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
20
|
+
}
|
|
21
|
+
export class FirstRunMerge {
|
|
22
|
+
deps;
|
|
23
|
+
pending;
|
|
24
|
+
constructor(deps) {
|
|
25
|
+
this.deps = deps;
|
|
26
|
+
}
|
|
27
|
+
now() {
|
|
28
|
+
return this.deps.now?.() ?? Date.now();
|
|
29
|
+
}
|
|
30
|
+
/** `task` 调用的 agent 是外部 Agent 时返回它的 runner。 */
|
|
31
|
+
externalRunner(agent) {
|
|
32
|
+
const runner = this.deps.runnerOf?.(agent) ??
|
|
33
|
+
listAgents(this.deps.sessionId()).find((a) => a.name === agent)?.runner;
|
|
34
|
+
return runner === undefined || runner === "ama" ? undefined : runner;
|
|
35
|
+
}
|
|
36
|
+
taskOf(taskId) {
|
|
37
|
+
if (this.deps.taskOf !== undefined)
|
|
38
|
+
return this.deps.taskOf(taskId);
|
|
39
|
+
return taskRegistryView(this.deps.sessionId())?.get(taskId);
|
|
40
|
+
}
|
|
41
|
+
/** 请求到来:命中合并返回 `allow`(不弹框);否则返回 undefined,并作废记录。 */
|
|
42
|
+
intercept(request) {
|
|
43
|
+
const pending = this.pending;
|
|
44
|
+
this.pending = undefined;
|
|
45
|
+
if (pending === undefined || !isFirstRunRequest(request))
|
|
46
|
+
return undefined;
|
|
47
|
+
if (this.now() - pending.at > (this.deps.windowMs ?? MERGE_WINDOW_MS))
|
|
48
|
+
return undefined;
|
|
49
|
+
const taskId = request.context?.taskId;
|
|
50
|
+
if (taskId === undefined || request.context?.origin !== undefined)
|
|
51
|
+
return undefined;
|
|
52
|
+
const task = this.taskOf(taskId);
|
|
53
|
+
if (task === undefined || task.agent !== pending.agent || task.startedAt < pending.at)
|
|
54
|
+
return undefined;
|
|
55
|
+
const runner = this.externalRunner(pending.agent);
|
|
56
|
+
if (runner === undefined || input(request)["agent"] !== runner)
|
|
57
|
+
return undefined;
|
|
58
|
+
return "allow";
|
|
59
|
+
}
|
|
60
|
+
/** 用户答复之后:允许了外部 Agent 的 task 调用就记下。 */
|
|
61
|
+
record(request, decision) {
|
|
62
|
+
this.pending = undefined;
|
|
63
|
+
if (decision !== "allow" && decision !== "allow_session")
|
|
64
|
+
return;
|
|
65
|
+
if (request.toolName !== "task" || isFirstRunRequest(request))
|
|
66
|
+
return;
|
|
67
|
+
if ((request.context?.depth ?? 0) > 0 || request.context?.origin !== undefined)
|
|
68
|
+
return;
|
|
69
|
+
const agent = input(request)["agent"];
|
|
70
|
+
if (typeof agent !== "string" || this.externalRunner(agent) === undefined)
|
|
71
|
+
return;
|
|
72
|
+
this.pending = { agent, at: this.now() };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** 把合并规则套在界面 broker 外面;自动答复时调 `onMerged`(消息区一行说明)。 */
|
|
76
|
+
export function mergingBroker(inner, merge, onMerged) {
|
|
77
|
+
return {
|
|
78
|
+
async ask(request, signal) {
|
|
79
|
+
const merged = merge.intercept(request);
|
|
80
|
+
if (merged !== undefined) {
|
|
81
|
+
onMerged?.(request);
|
|
82
|
+
return merged;
|
|
83
|
+
}
|
|
84
|
+
const decision = await inner.ask(request, signal);
|
|
85
|
+
merge.record(request, decision);
|
|
86
|
+
return decision;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Ctrl+V` 与 `/paste`:剪贴板图片写进 `<dataDir>/clipboard/`,输入框插入 `@<路径>`(发送时按 `@图片`
|
|
3
|
+
* 附件读取)。[W5-U] 读取本身在 tools/clipboard-image.ts(W5-I)。
|
|
4
|
+
*/
|
|
5
|
+
import { type ClipboardDeps } from "../../tools/clipboard-image.js";
|
|
6
|
+
export type PasteOutcome = {
|
|
7
|
+
ok: true;
|
|
8
|
+
ref: string;
|
|
9
|
+
path: string;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
message: string;
|
|
13
|
+
};
|
|
14
|
+
export declare const NO_CLIPBOARD_TOOL = "\u8BFB\u4E0D\u4E86\u526A\u8D34\u677F\u56FE\u7247\uFF1A\u6CA1\u6709\u53EF\u7528\u7684\u7CFB\u7EDF\u547D\u4EE4\uFF08macOS osascript / pngpaste\uFF0CLinux wl-paste / xclip\uFF0CWindows PowerShell\uFF09";
|
|
15
|
+
export declare const NO_CLIPBOARD_IMAGE = "\u526A\u8D34\u677F\u91CC\u6CA1\u6709\u56FE\u7247";
|
|
16
|
+
/** `@路径`;路径带空白时加引号。 */
|
|
17
|
+
export declare function imageRef(path: string): string;
|
|
18
|
+
export declare function pasteImage(dataDir: string, deps?: ClipboardDeps): Promise<PasteOutcome>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Ctrl+V` 与 `/paste`:剪贴板图片写进 `<dataDir>/clipboard/`,输入框插入 `@<路径>`(发送时按 `@图片`
|
|
3
|
+
* 附件读取)。[W5-U] 读取本身在 tools/clipboard-image.ts(W5-I)。
|
|
4
|
+
*/
|
|
5
|
+
import { readClipboardImage } from "../../tools/clipboard-image.js";
|
|
6
|
+
export const NO_CLIPBOARD_TOOL = "读不了剪贴板图片:没有可用的系统命令(macOS osascript / pngpaste,Linux wl-paste / xclip,Windows PowerShell)";
|
|
7
|
+
export const NO_CLIPBOARD_IMAGE = "剪贴板里没有图片";
|
|
8
|
+
/** `@路径`;路径带空白时加引号。 */
|
|
9
|
+
export function imageRef(path) {
|
|
10
|
+
return /\s/.test(path) ? `@"${path}"` : `@${path}`;
|
|
11
|
+
}
|
|
12
|
+
export async function pasteImage(dataDir, deps) {
|
|
13
|
+
try {
|
|
14
|
+
const result = await readClipboardImage(dataDir, deps);
|
|
15
|
+
if (result.ok)
|
|
16
|
+
return { ok: true, ref: imageRef(result.path), path: result.path };
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
message: result.reason === "no_tool" ? NO_CLIPBOARD_TOOL : NO_CLIPBOARD_IMAGE,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
return {
|
|
24
|
+
ok: false,
|
|
25
|
+
message: `读取剪贴板失败:${error instanceof Error ? error.message : String(error)}`,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
* 交互模式的斜杠命令:把 commands-core 的 `CommandResult` 变成界面动作。[B7]
|
|
3
3
|
*
|
|
4
4
|
* - `handled` → 消息区显示文本;`prompt` → 发提示;`exit` → 退出;
|
|
5
|
-
* - `pick` → 打开对应选择器:模型(setModel
|
|
5
|
+
* - `pick` → 打开对应选择器:模型(setModel;不列测试供应商 fake,`AMA_SHOW_FAKE=1` 或 `AMA_FAKE_SCRIPT` 时照列)、会话(resume)、树(/fork 无参数:从选中的用户消息
|
|
6
6
|
* 之前分叉,消息文本回填编辑器)、权限模式、思考级别;
|
|
7
7
|
* - 交互模式自有命令:`/tree`(同一文件内换叶子到选中消息之前,文本回填编辑器,可改后重发形成新分支)、
|
|
8
8
|
* `/permissions`(当前模式、判定顺序与已加载规则);`/help` 追加这两条与按键说明。
|
|
9
|
+
* - `/session`、`/cache`(无参数)与 `/permissions` 在消息区画左竖条面板(panels.ts),不再拍成文本。
|
|
10
|
+
* - `/rewind`(无参数)打开回滚列表与确认面板(rewind-flow.ts);带参数走 commands-core,对话变了时
|
|
11
|
+
* 重画消息区并回填原消息。
|
|
9
12
|
* - 不是命令(含模板与 `/skill:`)返回 false,调用方把整行当提示发出。
|
|
10
13
|
*/
|
|
11
|
-
import type { AgentSession } from "../../agent/types.js";
|
|
14
|
+
import type { AgentSession, RewindDraftText } from "../../agent/types.js";
|
|
12
15
|
import type { SwitchRequest } from "../../cli/compose-session.js";
|
|
13
16
|
import type { Runtime } from "../../cli/runtime.js";
|
|
14
|
-
import type { SelectItem } from "../../tui.js";
|
|
17
|
+
import type { Component, SelectItem, Theme } from "../../tui.js";
|
|
15
18
|
import { type CommandInfo } from "../commands-core.js";
|
|
16
19
|
import { type NoticeLevel } from "./message-view.js";
|
|
17
20
|
import { type PickerSpec } from "./pickers.js";
|
|
@@ -26,13 +29,27 @@ export interface CommandUi {
|
|
|
26
29
|
switchSession(request: SwitchRequest): Promise<AgentSession>;
|
|
27
30
|
pick(spec: PickerSpec): Promise<SelectItem | undefined>;
|
|
28
31
|
notice(level: NoticeLevel, text: string): void;
|
|
32
|
+
/** 消息区面板(/session、/cache、/permissions);缺省回落为文本通知。 */
|
|
33
|
+
panel?(component: Component): void;
|
|
29
34
|
setEditorText(text: string): void;
|
|
30
35
|
/** 发一条提示(不等运行结束)。 */
|
|
31
36
|
prompt(text: string): void;
|
|
32
37
|
/** /tree 换叶子后重画消息区。 */
|
|
33
38
|
reload(): void;
|
|
39
|
+
/** 回滚列表与确认面板(`/rewind` 无参数);没有时回落为文字列表。 */
|
|
40
|
+
rewind?(): Promise<void>;
|
|
41
|
+
/** 回填原消息(文本 + 图片);缺省只回填文本。 */
|
|
42
|
+
setDraft?(draft: RewindDraftText): void;
|
|
34
43
|
exit(code: number): void;
|
|
35
44
|
now(): number;
|
|
45
|
+
/** 面板用的主题(与 panel 一起提供)。 */
|
|
46
|
+
theme?(): Theme;
|
|
47
|
+
/** 家目录(面板里路径缩写为 ~)。 */
|
|
48
|
+
home?: string;
|
|
49
|
+
/** 进程环境:给出时 /model 选择器按 fake-visibility 规则藏起测试供应商 fake。 */
|
|
50
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
51
|
+
/** [W5-U] 界面自己处理的第五波命令(agent-ui.ts);处理了返回 true。 */
|
|
52
|
+
extra?(name: string, args: string): Promise<boolean>;
|
|
36
53
|
}
|
|
37
54
|
/** 当前分支上的条目 id(树选择器标 ●)。 */
|
|
38
55
|
export declare function activeBranchIds(session: AgentSession): Set<string>;
|