@armadra/agent 0.4.0 → 0.5.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 +184 -1
- package/README.md +202 -83
- 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/session-cache.d.ts +5 -0
- package/dist/agent/session-cache.js +17 -1
- package/dist/agent/session-classifier.d.ts +1 -1
- package/dist/agent/session-classifier.js +3 -1
- package/dist/agent/session-compaction.d.ts +35 -6
- package/dist/agent/session-compaction.js +157 -31
- package/dist/agent/session-core.d.ts +27 -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 +40 -1
- package/dist/agent/session.d.ts +30 -29
- package/dist/agent/session.js +79 -123
- 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 +57 -4
- package/dist/agent/types-w5.d.ts +192 -0
- package/dist/agent/types-w5.js +10 -0
- package/dist/agent/types.d.ts +47 -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-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/openai-compat.d.ts +4 -1
- package/dist/ai/apis/openai-compat.js +8 -1
- 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 +20 -10
- package/dist/ai/providers/registry.js +82 -43
- package/dist/ai/types.d.ts +28 -2
- package/dist/ai/types.js +5 -0
- package/dist/bundle/ama.cjs +37605 -21619
- 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 +8 -4
- package/dist/cli/args.js +17 -97
- package/dist/cli/bootstrap.js +13 -1
- package/dist/cli/choice-prompt.d.ts +58 -0
- package/dist/cli/choice-prompt.js +140 -0
- package/dist/cli/codemode-notice.d.ts +3 -2
- package/dist/cli/codemode-notice.js +3 -2
- 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 +3 -0
- package/dist/cli/compose-session.js +47 -4
- package/dist/cli/compose.d.ts +3 -0
- package/dist/cli/compose.js +33 -6
- package/dist/cli/deps.d.ts +6 -0
- package/dist/cli/exit-codes.d.ts +10 -0
- package/dist/cli/exit-codes.js +12 -0
- package/dist/cli/help-text.d.ts +4 -0
- package/dist/cli/help-text.js +102 -0
- package/dist/cli/startup-screen.js +5 -3
- package/dist/cli/startup-steps.js +7 -1
- package/dist/cli/subcommands/config.d.ts +4 -1
- package/dist/cli/subcommands/config.js +17 -6
- package/dist/cli/subcommands/doctor.js +21 -0
- package/dist/cli/subcommands/models-cache-probe.d.ts +1 -1
- package/dist/cli/subcommands/models-cache-probe.js +3 -12
- package/dist/cli/subcommands/models-discover.js +5 -6
- package/dist/cli/subcommands/models.d.ts +2 -0
- package/dist/cli/subcommands/models.js +33 -14
- package/dist/cli/subcommands/providers.d.ts +1 -1
- package/dist/cli/subcommands/providers.js +8 -15
- package/dist/cli/subcommands/sessions.d.ts +3 -1
- package/dist/cli/subcommands/sessions.js +36 -2
- 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/tool.d.ts +1 -1
- package/dist/codemode/tool.js +6 -4
- 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/json-schema.js +63 -2
- package/dist/config/key-docs.js +72 -3
- package/dist/config/merge.d.ts +5 -3
- package/dist/config/merge.js +81 -7
- 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 +68 -114
- package/dist/config/types-w5.d.ts +118 -0
- package/dist/config/types-w5.js +20 -0
- package/dist/config/types.d.ts +50 -1
- package/dist/config/types.js +12 -0
- 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 +13 -1
- package/dist/modes/commands-core.js +64 -0
- 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 +21 -4
- package/dist/modes/interactive/approval-dialog.js +98 -20
- 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 +12 -1
- package/dist/modes/interactive/commands.js +31 -1
- package/dist/modes/interactive/confirm-dialog.d.ts +49 -0
- package/dist/modes/interactive/confirm-dialog.js +121 -0
- 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 +14 -1
- package/dist/modes/interactive/interactive-mode.js +140 -136
- package/dist/modes/interactive/key-dispatch.d.ts +22 -2
- package/dist/modes/interactive/key-dispatch.js +66 -7
- package/dist/modes/interactive/line/line-mode.d.ts +4 -1
- package/dist/modes/interactive/line/line-mode.js +31 -5
- package/dist/modes/interactive/line/line-render.d.ts +2 -1
- package/dist/modes/interactive/line/line-render.js +40 -4
- package/dist/modes/interactive/message-view.d.ts +1 -1
- package/dist/modes/interactive/message-view.js +24 -2
- package/dist/modes/interactive/panels.d.ts +18 -1
- package/dist/modes/interactive/panels.js +19 -5
- 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/session-events.d.ts +24 -0
- package/dist/modes/interactive/session-events.js +96 -0
- package/dist/modes/interactive/startup-ui.js +5 -1
- 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 +99 -11
- package/dist/modes/interactive/status-bar.js +273 -90
- 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-view.d.ts +12 -2
- package/dist/modes/interactive/tool-view.js +34 -4
- package/dist/modes/print/print-mode.d.ts +13 -4
- package/dist/modes/print/print-mode.js +56 -12
- package/dist/modes/rpc/commands.d.ts +9 -0
- package/dist/modes/rpc/commands.js +44 -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 +5 -0
- package/dist/permissions/auto-safe.js +18 -0
- package/dist/permissions/bypass.d.ts +32 -0
- package/dist/permissions/bypass.js +36 -0
- package/dist/permissions/classifier.d.ts +4 -0
- package/dist/permissions/classifier.js +2 -0
- package/dist/permissions/modes.js +1 -1
- package/dist/permissions/pipeline.d.ts +43 -4
- package/dist/permissions/pipeline.js +114 -9
- package/dist/permissions/readonly-bash.d.ts +30 -0
- package/dist/permissions/readonly-bash.js +118 -0
- package/dist/permissions/types.d.ts +42 -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 +33 -2
- package/dist/sdk.js +24 -2
- 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 +7 -2
- package/dist/tools/presets.js +11 -4
- 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/glyphs.d.ts +4 -0
- package/dist/tui/glyphs.js +4 -0
- package/dist/tui/keybindings.d.ts +6 -1
- package/dist/tui/keybindings.js +6 -1
- package/docs/acp.md +78 -0
- package/docs/agents.md +250 -0
- package/docs/codemode.md +12 -8
- package/docs/hooks.md +26 -22
- package/docs/permissions.md +78 -13
- package/docs/plan.md +107 -0
- package/docs/providers.md +228 -52
- package/docs/rewind-plan.md +181 -0
- package/docs/rpc.md +92 -5
- package/docs/sandbox.md +215 -0
- package/docs/session-format.md +41 -21
- package/docs/sessions.md +41 -1
- package/docs/tui-design.md +751 -0
- package/docs/tui.md +179 -21
- package/package.json +13 -2
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 可选的图片缩放(docs/wave5-plan.md §4、D12)。[W5-I]
|
|
3
|
+
*
|
|
4
|
+
* 零依赖不能解码像素,只能调系统工具:macOS 依次试 `sips`、`magick`、`convert`;Linux 试
|
|
5
|
+
* `magick`、`convert`;Windows 只试 `magick`(`convert.exe` 是系统的磁盘转换工具)。都没有就返回
|
|
6
|
+
* `no_tool`,调用方按原规则拒绝并提示。只在超限时调用(`images.resize: "auto"`,缺省)。
|
|
7
|
+
*
|
|
8
|
+
* 输出写临时目录,读回后删掉;JPEG 保持 JPEG,其余格式输出 PNG(GIF 取第一帧)。边长先取
|
|
9
|
+
* min(目标边长, 原长边),体积仍超限就按 0.7 逐次缩小,最多 5 次。
|
|
10
|
+
*/
|
|
11
|
+
import { type ImageSize } from "./image-file.js";
|
|
12
|
+
export interface CommandResult {
|
|
13
|
+
/** 进程退出码;命令不存在 / 无法启动为 null。 */
|
|
14
|
+
code: number | null;
|
|
15
|
+
stdout: Buffer;
|
|
16
|
+
stderr: string;
|
|
17
|
+
/** 命令不存在(ENOENT)。 */
|
|
18
|
+
missing?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export type RunCommand = (command: string, args: readonly string[], options?: {
|
|
21
|
+
env?: NodeJS.ProcessEnv;
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
}) => Promise<CommandResult>;
|
|
24
|
+
/** 缺省的命令执行器:execFile,stdout 按 Buffer 收,30 s 超时。 */
|
|
25
|
+
export declare const runCommand: RunCommand;
|
|
26
|
+
export interface ResizeTarget {
|
|
27
|
+
/** 长边上限(像素)。 */
|
|
28
|
+
maxEdge: number;
|
|
29
|
+
/** base64 后的体积上限(字节)。 */
|
|
30
|
+
maxBase64Bytes: number;
|
|
31
|
+
mimeType: string;
|
|
32
|
+
/** 原图尺寸(已知时用来定起始边长)。 */
|
|
33
|
+
size?: ImageSize | undefined;
|
|
34
|
+
}
|
|
35
|
+
export interface ResizeDeps {
|
|
36
|
+
platform?: NodeJS.Platform;
|
|
37
|
+
run?: RunCommand;
|
|
38
|
+
/** 临时目录的父目录;缺省 os.tmpdir()。 */
|
|
39
|
+
tmpDir?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface ResizedImage {
|
|
42
|
+
ok: true;
|
|
43
|
+
buf: Buffer;
|
|
44
|
+
mimeType: string;
|
|
45
|
+
size?: ImageSize;
|
|
46
|
+
/** 用到的工具(`sips` / `magick` / `convert`)。 */
|
|
47
|
+
tool: string;
|
|
48
|
+
}
|
|
49
|
+
export interface ResizeFailure {
|
|
50
|
+
ok: false;
|
|
51
|
+
reason: "no_tool" | "failed";
|
|
52
|
+
}
|
|
53
|
+
/** 按平台的候选工具,靠前的先试。 */
|
|
54
|
+
export declare function resizeTools(platform: NodeJS.Platform): string[];
|
|
55
|
+
/**
|
|
56
|
+
* 把 `input` 缩到目标以内。`no_tool`:一个可用工具都没有;`failed`:工具能用但缩不到目标。
|
|
57
|
+
*/
|
|
58
|
+
export declare function resizeImage(input: string, target: ResizeTarget, deps?: ResizeDeps): Promise<ResizedImage | ResizeFailure>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 可选的图片缩放(docs/wave5-plan.md §4、D12)。[W5-I]
|
|
3
|
+
*
|
|
4
|
+
* 零依赖不能解码像素,只能调系统工具:macOS 依次试 `sips`、`magick`、`convert`;Linux 试
|
|
5
|
+
* `magick`、`convert`;Windows 只试 `magick`(`convert.exe` 是系统的磁盘转换工具)。都没有就返回
|
|
6
|
+
* `no_tool`,调用方按原规则拒绝并提示。只在超限时调用(`images.resize: "auto"`,缺省)。
|
|
7
|
+
*
|
|
8
|
+
* 输出写临时目录,读回后删掉;JPEG 保持 JPEG,其余格式输出 PNG(GIF 取第一帧)。边长先取
|
|
9
|
+
* min(目标边长, 原长边),体积仍超限就按 0.7 逐次缩小,最多 5 次。
|
|
10
|
+
*/
|
|
11
|
+
import { execFile } from "node:child_process";
|
|
12
|
+
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
13
|
+
import { tmpdir } from "node:os";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { base64Size } from "../ai/image-limits.js";
|
|
16
|
+
import { imageSize } from "./image-file.js";
|
|
17
|
+
/** 缺省的命令执行器:execFile,stdout 按 Buffer 收,30 s 超时。 */
|
|
18
|
+
export const runCommand = (command, args, options = {}) => new Promise((resolvePromise) => {
|
|
19
|
+
execFile(command, [...args], {
|
|
20
|
+
encoding: "buffer",
|
|
21
|
+
maxBuffer: 128 * 1024 * 1024,
|
|
22
|
+
timeout: options.timeoutMs ?? 30_000,
|
|
23
|
+
windowsHide: true,
|
|
24
|
+
...(options.env !== undefined ? { env: options.env } : {}),
|
|
25
|
+
}, (error, stdout, stderr) => {
|
|
26
|
+
const err = error;
|
|
27
|
+
const missing = err !== null && err.code === "ENOENT";
|
|
28
|
+
const code = err === null ? 0 : typeof err.code === "number" ? err.code : missing ? null : 1;
|
|
29
|
+
resolvePromise({
|
|
30
|
+
code,
|
|
31
|
+
stdout: Buffer.isBuffer(stdout) ? stdout : Buffer.alloc(0),
|
|
32
|
+
stderr: Buffer.isBuffer(stderr) ? stderr.toString("utf8") : String(stderr ?? ""),
|
|
33
|
+
...(missing ? { missing: true } : {}),
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
const MAX_ATTEMPTS = 5;
|
|
38
|
+
const SHRINK = 0.7;
|
|
39
|
+
const MIN_EDGE = 64;
|
|
40
|
+
/** 按平台的候选工具,靠前的先试。 */
|
|
41
|
+
export function resizeTools(platform) {
|
|
42
|
+
if (platform === "darwin")
|
|
43
|
+
return ["sips", "magick", "convert"];
|
|
44
|
+
if (platform === "win32")
|
|
45
|
+
return ["magick"];
|
|
46
|
+
return ["magick", "convert"];
|
|
47
|
+
}
|
|
48
|
+
function resizeArgs(tool, input, output, edge, format) {
|
|
49
|
+
if (tool === "sips")
|
|
50
|
+
return ["-Z", String(edge), "-s", "format", format, input, "--out", output];
|
|
51
|
+
// ImageMagick:`[0]` 取第一帧,`>` 只缩小不放大
|
|
52
|
+
return [`${input}[0]`, "-resize", `${edge}x${edge}>`, output];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 把 `input` 缩到目标以内。`no_tool`:一个可用工具都没有;`failed`:工具能用但缩不到目标。
|
|
56
|
+
*/
|
|
57
|
+
export async function resizeImage(input, target, deps = {}) {
|
|
58
|
+
const run = deps.run ?? runCommand;
|
|
59
|
+
const format = target.mimeType === "image/jpeg" ? "jpeg" : "png";
|
|
60
|
+
const mimeType = format === "jpeg" ? "image/jpeg" : "image/png";
|
|
61
|
+
const long = target.size !== undefined ? Math.max(target.size.width, target.size.height) : 0;
|
|
62
|
+
const start = long > 0 ? Math.min(target.maxEdge, long) : target.maxEdge;
|
|
63
|
+
const dir = await mkdtemp(join(deps.tmpDir ?? tmpdir(), "ama-resize-"));
|
|
64
|
+
try {
|
|
65
|
+
for (const tool of resizeTools(deps.platform ?? process.platform)) {
|
|
66
|
+
let edge = start;
|
|
67
|
+
let worked = false;
|
|
68
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS && edge >= MIN_EDGE; attempt++) {
|
|
69
|
+
const output = join(dir, `out-${attempt}.${format === "jpeg" ? "jpg" : "png"}`);
|
|
70
|
+
const result = await run(tool, resizeArgs(tool, input, output, edge, format));
|
|
71
|
+
if (result.missing === true || result.code !== 0)
|
|
72
|
+
break;
|
|
73
|
+
let buf;
|
|
74
|
+
try {
|
|
75
|
+
buf = await readFile(output);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
worked = true;
|
|
81
|
+
const size = imageSize(buf, mimeType);
|
|
82
|
+
const longOut = size !== undefined ? Math.max(size.width, size.height) : 0;
|
|
83
|
+
if (base64Size(buf.length) <= target.maxBase64Bytes && longOut <= target.maxEdge) {
|
|
84
|
+
return { ok: true, buf, mimeType, tool, ...(size !== undefined ? { size } : {}) };
|
|
85
|
+
}
|
|
86
|
+
edge = Math.round(Math.min(edge, longOut > 0 ? longOut : edge) * SHRINK);
|
|
87
|
+
}
|
|
88
|
+
// 工具能用但缩不到目标:换工具也不会更好
|
|
89
|
+
if (worked)
|
|
90
|
+
return { ok: false, reason: "failed" };
|
|
91
|
+
}
|
|
92
|
+
return { ok: false, reason: "no_tool" };
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
await rm(dir, { recursive: true, force: true }).catch(() => undefined);
|
|
96
|
+
}
|
|
97
|
+
}
|
package/dist/tools/presets.d.ts
CHANGED
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
* `--tools a,b,c` 整组替换(之后只用列出的名字)。
|
|
13
13
|
* - `tools.default`:`+name` / `-name` 在预设上增减;不带前缀的名字整组替换预设的内置工具,
|
|
14
14
|
* 之后再应用带前缀的项。未注册的名字记 warning 并忽略。
|
|
15
|
+
* - (D20)`todo` 不在 `default` 里:W5-C0 曾把它加进来,以 `bench-presets` 复测为门(费用增幅 ≤ 5% 且
|
|
16
|
+
* 成功率不降);W5-Z 用多步长任务复测(docs/benchmarks/presets-todo-2026-10-03.md)成功数下降 1、估价
|
|
17
|
+
* +4.6%、保守计价 +11.3%,按门撤回。计划批准后的进度改用 `[DONE:n]` 文本标记(plan/done-markers.ts);
|
|
18
|
+
* 要 todo 就 `tools.default: ["+todo"]`。
|
|
19
|
+
* - (W5-C0)`task_ctl` 与 `task` 同进退:`+task` 一起暴露、`-task` 一起去掉(`pairCompanions`)。
|
|
15
20
|
* - `codemode` 是 `codemode-only` 的旧名(0.3.0),配置合并与命令行解析时折成规范名。
|
|
16
21
|
* - codemode 开关跟随预设(`presetCodemodeMode`):`default` → `on`(只在沙箱 strict,即 Node ≥ 25 隔离
|
|
17
22
|
* 网络时;Node 22 / 24 → `off`),`codemode-only` → `only`,`minimal` / `coordinator` → `off`。
|
|
@@ -43,9 +48,9 @@ export interface CodemodeModeResolution {
|
|
|
43
48
|
strict: boolean;
|
|
44
49
|
}
|
|
45
50
|
/** 生效的 codemode 模式及其来源;`strict` 缺省按运行时探测(测试与组装根可注入)。 */
|
|
46
|
-
export declare function resolveCodemodeMode(config: Pick<AmaConfig, "tools" | "codemode">, strict?: boolean): CodemodeModeResolution;
|
|
51
|
+
export declare function resolveCodemodeMode(config: Pick<AmaConfig, "tools" | "codemode" | "sandbox">, strict?: boolean): CodemodeModeResolution;
|
|
47
52
|
/** 生效的 codemode 模式:显式配置优先,否则跟随预设。 */
|
|
48
|
-
export declare function effectiveCodemodeMode(config: Pick<AmaConfig, "tools" | "codemode">, strict?: boolean): CodemodeMode;
|
|
53
|
+
export declare function effectiveCodemodeMode(config: Pick<AmaConfig, "tools" | "codemode" | "sandbox">, strict?: boolean): CodemodeMode;
|
|
49
54
|
/**
|
|
50
55
|
* codemode 脚本里可调用工具的范围:`coordinator` 预设只能调活动集里的工具(`"active"`),其它预设
|
|
51
56
|
* 不限(`undefined`;`on` 模式下脚本还能调没直接暴露的 ls / task / todo 等)。
|
package/dist/tools/presets.js
CHANGED
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
* `--tools a,b,c` 整组替换(之后只用列出的名字)。
|
|
13
13
|
* - `tools.default`:`+name` / `-name` 在预设上增减;不带前缀的名字整组替换预设的内置工具,
|
|
14
14
|
* 之后再应用带前缀的项。未注册的名字记 warning 并忽略。
|
|
15
|
+
* - (D20)`todo` 不在 `default` 里:W5-C0 曾把它加进来,以 `bench-presets` 复测为门(费用增幅 ≤ 5% 且
|
|
16
|
+
* 成功率不降);W5-Z 用多步长任务复测(docs/benchmarks/presets-todo-2026-10-03.md)成功数下降 1、估价
|
|
17
|
+
* +4.6%、保守计价 +11.3%,按门撤回。计划批准后的进度改用 `[DONE:n]` 文本标记(plan/done-markers.ts);
|
|
18
|
+
* 要 todo 就 `tools.default: ["+todo"]`。
|
|
19
|
+
* - (W5-C0)`task_ctl` 与 `task` 同进退:`+task` 一起暴露、`-task` 一起去掉(`pairCompanions`)。
|
|
15
20
|
* - `codemode` 是 `codemode-only` 的旧名(0.3.0),配置合并与命令行解析时折成规范名。
|
|
16
21
|
* - codemode 开关跟随预设(`presetCodemodeMode`):`default` → `on`(只在沙箱 strict,即 Node ≥ 25 隔离
|
|
17
22
|
* 网络时;Node 22 / 24 → `off`),`codemode-only` → `only`,`minimal` / `coordinator` → `off`。
|
|
@@ -23,12 +28,13 @@
|
|
|
23
28
|
* warning**(不报错:零配置用户不应因此起不来),显式 `on` 同样忽略;跟随预设得到的 `on` 静默回退。
|
|
24
29
|
* - `only` 模式活动集独占:宿主 / SDK 工具也不直接暴露,只能在脚本里调用(`exclusive`)。
|
|
25
30
|
*/
|
|
26
|
-
import {
|
|
31
|
+
import { sandboxCapabilityFor } from "../codemode/capability.js";
|
|
27
32
|
import { canonicalPreset, } from "../config/types.js";
|
|
28
|
-
import { ToolRegistry } from "./registry.js";
|
|
33
|
+
import { ToolRegistry, pairCompanions } from "./registry.js";
|
|
29
34
|
export const CODEMODE_TOOL = "codemode";
|
|
30
35
|
/** 各预设下模型直接看到的内置工具(codemode-only 预设见 `resolvePreset`)。 */
|
|
31
36
|
export const PRESET_TOOLS = Object.freeze({
|
|
37
|
+
// D20:todo 不在 default(W5-Z 复测未过门,见文件头)
|
|
32
38
|
default: ["bash", "edit", "glob", "grep", "read", "write"],
|
|
33
39
|
minimal: ["bash", "edit", "read", "write"],
|
|
34
40
|
"codemode-only": [CODEMODE_TOOL],
|
|
@@ -50,7 +56,7 @@ export function presetCodemodeMode(preset, strict) {
|
|
|
50
56
|
}
|
|
51
57
|
}
|
|
52
58
|
/** 生效的 codemode 模式及其来源;`strict` 缺省按运行时探测(测试与组装根可注入)。 */
|
|
53
|
-
export function resolveCodemodeMode(config, strict =
|
|
59
|
+
export function resolveCodemodeMode(config, strict = sandboxCapabilityFor(config).strict) {
|
|
54
60
|
const preset = canonicalPreset(config.tools?.preset) ?? "default";
|
|
55
61
|
const explicit = config.codemode?.mode;
|
|
56
62
|
if (explicit !== undefined)
|
|
@@ -113,7 +119,8 @@ export function resolvePreset(input) {
|
|
|
113
119
|
base.push(CODEMODE_TOOL);
|
|
114
120
|
}
|
|
115
121
|
const names = [];
|
|
116
|
-
|
|
122
|
+
const adjusted = applyToolAdjustments(base, input.config.tools?.default);
|
|
123
|
+
for (const name of pairCompanions(adjusted, input.available)) {
|
|
117
124
|
if (input.available(name))
|
|
118
125
|
names.push(name);
|
|
119
126
|
else
|
package/dist/tools/read.d.ts
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 文本按 `cat -n` 形状返回(行号右对齐 6 位 + Tab);头截断 2000 行 / 50 KB 先到者,末尾提示
|
|
5
5
|
* `offset` 续读;NUL 嗅探判二进制并拒绝;png / jpg / gif / webp 作为 ImageBlock 返回(MIME 按文件头,
|
|
6
|
-
* 与 `--image` / `@图片` 共用 image-file.ts
|
|
7
|
-
* `ctx.markRead(abs)`。
|
|
6
|
+
* 与 `--image` / `@图片` 共用 image-file.ts;模型不支持图片、超过当前端点的单图上限(base64 后,
|
|
7
|
+
* [W5-I] 按端点分档)或任一边 > 8000 px 时只给路径与尺寸);成功后 `ctx.markRead(abs)`。
|
|
8
8
|
*/
|
|
9
9
|
import type { ToolContext, ToolDefinition, ToolResult } from "./types.js";
|
|
10
|
+
import { type ImageFitOptions } from "./image-file.js";
|
|
10
11
|
export { imageSize, type ImageSize } from "./image-file.js";
|
|
11
12
|
export interface ReadInput {
|
|
12
13
|
path: string;
|
|
@@ -16,6 +17,8 @@ export interface ReadInput {
|
|
|
16
17
|
export interface ReadToolOptions {
|
|
17
18
|
/** 当前模型是否接受图片输入;缺省 true。 */
|
|
18
19
|
supportsImages?(ctx: ToolContext): boolean;
|
|
20
|
+
/** [W5-I] 当前模型的单图上限与缩放设置;缺省 5 MB(base64 后)。 */
|
|
21
|
+
imageOptions?(ctx: ToolContext): ImageFitOptions;
|
|
19
22
|
}
|
|
20
23
|
export declare function isBinary(buf: Buffer): boolean;
|
|
21
24
|
/** `cat -n` 形状。 */
|
package/dist/tools/read.js
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 文本按 `cat -n` 形状返回(行号右对齐 6 位 + Tab);头截断 2000 行 / 50 KB 先到者,末尾提示
|
|
5
5
|
* `offset` 续读;NUL 嗅探判二进制并拒绝;png / jpg / gif / webp 作为 ImageBlock 返回(MIME 按文件头,
|
|
6
|
-
* 与 `--image` / `@图片` 共用 image-file.ts
|
|
7
|
-
* `ctx.markRead(abs)`。
|
|
6
|
+
* 与 `--image` / `@图片` 共用 image-file.ts;模型不支持图片、超过当前端点的单图上限(base64 后,
|
|
7
|
+
* [W5-I] 按端点分档)或任一边 > 8000 px 时只给路径与尺寸);成功后 `ctx.markRead(abs)`。
|
|
8
8
|
*/
|
|
9
9
|
import { readFile, stat } from "node:fs/promises";
|
|
10
10
|
import { displayPath, resolvePath } from "./paths.js";
|
|
11
11
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead } from "./truncate.js";
|
|
12
12
|
import { normalizeToLF, splitBom } from "./edit-fuzzy.js";
|
|
13
|
-
import {
|
|
13
|
+
import { MAX_IMAGE_FILE_BYTES, fitImage, imageMimeFromPath, imageSize, sniffImageMime, } from "./image-file.js";
|
|
14
14
|
export { imageSize } from "./image-file.js";
|
|
15
15
|
const SNIFF_BYTES = 8000;
|
|
16
16
|
export function isBinary(buf) {
|
|
@@ -38,15 +38,18 @@ async function readImage(abs, shown, ctx, options) {
|
|
|
38
38
|
if (options.supportsImages && !options.supportsImages(ctx)) {
|
|
39
39
|
return { content: `${caption}\n[The current model does not accept image input.]`, details };
|
|
40
40
|
}
|
|
41
|
-
if (buf.length >
|
|
42
|
-
return {
|
|
43
|
-
content: `${caption}\n[Image exceeds the ${formatSize(MAX_IMAGE_BYTES)} attachment limit; not attached.]`,
|
|
44
|
-
details,
|
|
45
|
-
};
|
|
41
|
+
if (buf.length > MAX_IMAGE_FILE_BYTES) {
|
|
42
|
+
return { content: `${caption}\n[Image file is too large to attach.]`, details };
|
|
46
43
|
}
|
|
44
|
+
const fit = await fitImage(buf, mimeType, options.imageOptions?.(ctx) ?? {}, abs);
|
|
45
|
+
if (!fit.ok)
|
|
46
|
+
return { content: `${caption}\n[${fit.note}]`, details };
|
|
47
|
+
const note = fit.resized !== undefined && fit.size !== undefined
|
|
48
|
+
? `\n[Resized to ${fit.size.width}x${fit.size.height} to fit the attachment limit.]`
|
|
49
|
+
: "";
|
|
47
50
|
const blocks = [
|
|
48
|
-
{ type: "text", text: caption },
|
|
49
|
-
{ type: "image", data: buf.toString("base64"), mimeType },
|
|
51
|
+
{ type: "text", text: caption + note },
|
|
52
|
+
{ type: "image", data: fit.buf.toString("base64"), mimeType: fit.mimeType },
|
|
50
53
|
];
|
|
51
54
|
return { content: blocks, details };
|
|
52
55
|
}
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* - `disable(name)` 后不再出现在 `list()` / `active()`,也不能被 `setActive` 选中;未注册的名字也
|
|
7
7
|
* 记下(宿主可能先 disable 再由内置注册,例如 `disable("task")`);
|
|
8
8
|
* - 活动集缺省 = 全部已注册且未禁用;`setActive(names)` 之后只用这些(未知名 → tool_not_found);
|
|
9
|
+
* - (W5-C0)伴随工具 `TOOL_COMPANIONS`:`task_ctl` 与 `task` 同进退——`disable("task")` 一并禁用,
|
|
10
|
+
* `setActive` 选了 `task` 时一并选上(预设里的配对在 presets.ts);
|
|
9
11
|
* - `builtinTools()` 给出全部内置工具;Skill 正文由模型用 read 读取(设计 §5.6 删除了 skill 工具),
|
|
10
12
|
* `/skill:` 命令展开在 skills/expand.ts。
|
|
11
13
|
*/
|
|
@@ -13,6 +15,10 @@ import type { ToolDefinition, ToolExecutionMode, ToolRegistryApi, ToolSource } f
|
|
|
13
15
|
import { type ReadToolOptions } from "./read.js";
|
|
14
16
|
import { type BashToolOptions } from "./bash.js";
|
|
15
17
|
import { type TaskToolOptions } from "./task.js";
|
|
18
|
+
/** [W5-C0] 主工具 → 随它出现 / 消失的伴随工具。 */
|
|
19
|
+
export declare const TOOL_COMPANIONS: Readonly<Record<string, readonly string[]>>;
|
|
20
|
+
/** 按 `TOOL_COMPANIONS` 配对:有主工具就带上(已注册的)伴随工具,没有就去掉。 */
|
|
21
|
+
export declare function pairCompanions(names: Iterable<string>, available: (name: string) => boolean): string[];
|
|
16
22
|
export declare const TOOL_NAME_RE: RegExp;
|
|
17
23
|
/** 未声明时:read → parallel;write / execute → sequential。 */
|
|
18
24
|
export declare function executionModeOf(tool: Pick<ToolDefinition, "permission" | "executionMode">): ToolExecutionMode;
|
|
@@ -35,7 +41,7 @@ export interface BuiltinToolOptions {
|
|
|
35
41
|
bash?: BashToolOptions;
|
|
36
42
|
task?: TaskToolOptions;
|
|
37
43
|
}
|
|
38
|
-
/** 全部内置工具(read / write / edit / bash / grep / glob / ls / todo / task)。 */
|
|
44
|
+
/** 全部内置工具(read / write / edit / bash / grep / glob / ls / todo / task / task_ctl)。 */
|
|
39
45
|
export declare function builtinTools(options?: BuiltinToolOptions): ToolDefinition[];
|
|
40
46
|
/** 新建注册表并登记全部内置工具;`disabled` 来自 config.tools.disabled。 */
|
|
41
47
|
export declare function createToolRegistry(options?: BuiltinToolOptions & {
|
package/dist/tools/registry.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* - `disable(name)` 后不再出现在 `list()` / `active()`,也不能被 `setActive` 选中;未注册的名字也
|
|
7
7
|
* 记下(宿主可能先 disable 再由内置注册,例如 `disable("task")`);
|
|
8
8
|
* - 活动集缺省 = 全部已注册且未禁用;`setActive(names)` 之后只用这些(未知名 → tool_not_found);
|
|
9
|
+
* - (W5-C0)伴随工具 `TOOL_COMPANIONS`:`task_ctl` 与 `task` 同进退——`disable("task")` 一并禁用,
|
|
10
|
+
* `setActive` 选了 `task` 时一并选上(预设里的配对在 presets.ts);
|
|
9
11
|
* - `builtinTools()` 给出全部内置工具;Skill 正文由模型用 read 读取(设计 §5.6 删除了 skill 工具),
|
|
10
12
|
* `/skill:` 命令展开在 skills/expand.ts。
|
|
11
13
|
*/
|
|
@@ -20,6 +22,24 @@ import { createGlobTool } from "./glob.js";
|
|
|
20
22
|
import { createLsTool } from "./ls.js";
|
|
21
23
|
import { createTodoTool } from "./todo.js";
|
|
22
24
|
import { createTaskTool } from "./task.js";
|
|
25
|
+
import { TASK_CTL_TOOL, createTaskCtlTool } from "./task-ctl.js";
|
|
26
|
+
/** [W5-C0] 主工具 → 随它出现 / 消失的伴随工具。 */
|
|
27
|
+
export const TOOL_COMPANIONS = Object.freeze({
|
|
28
|
+
task: [TASK_CTL_TOOL],
|
|
29
|
+
});
|
|
30
|
+
/** 按 `TOOL_COMPANIONS` 配对:有主工具就带上(已注册的)伴随工具,没有就去掉。 */
|
|
31
|
+
export function pairCompanions(names, available) {
|
|
32
|
+
const set = new Set(names);
|
|
33
|
+
for (const [main, companions] of Object.entries(TOOL_COMPANIONS)) {
|
|
34
|
+
for (const companion of companions) {
|
|
35
|
+
if (set.has(main) && available(companion))
|
|
36
|
+
set.add(companion);
|
|
37
|
+
else
|
|
38
|
+
set.delete(companion);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return [...set];
|
|
42
|
+
}
|
|
23
43
|
export const TOOL_NAME_RE = /^[a-z][a-z0-9_]{1,63}$/;
|
|
24
44
|
/** 未声明时:read → parallel;write / execute → sequential。 */
|
|
25
45
|
export function executionModeOf(tool) {
|
|
@@ -52,8 +72,10 @@ export class ToolRegistry {
|
|
|
52
72
|
this.entries.set(tool.name, { tool, source });
|
|
53
73
|
}
|
|
54
74
|
disable(name) {
|
|
55
|
-
|
|
56
|
-
|
|
75
|
+
for (const target of [name, ...(TOOL_COMPANIONS[name] ?? [])]) {
|
|
76
|
+
this.disabled.add(target);
|
|
77
|
+
this.activeNames?.delete(target);
|
|
78
|
+
}
|
|
57
79
|
}
|
|
58
80
|
isDisabled(name) {
|
|
59
81
|
return this.disabled.has(name);
|
|
@@ -77,10 +99,10 @@ export class ToolRegistry {
|
|
|
77
99
|
throw new AmaError("tool_not_found", `Unknown or disabled tool "${name}"`);
|
|
78
100
|
}
|
|
79
101
|
}
|
|
80
|
-
this.activeNames = new Set(names);
|
|
102
|
+
this.activeNames = new Set(pairCompanions(names, (n) => this.entries.has(n) && !this.disabled.has(n)));
|
|
81
103
|
}
|
|
82
104
|
}
|
|
83
|
-
/** 全部内置工具(read / write / edit / bash / grep / glob / ls / todo / task)。 */
|
|
105
|
+
/** 全部内置工具(read / write / edit / bash / grep / glob / ls / todo / task / task_ctl)。 */
|
|
84
106
|
export function builtinTools(options = {}) {
|
|
85
107
|
const tools = [
|
|
86
108
|
createReadTool(options.read),
|
|
@@ -92,6 +114,7 @@ export function builtinTools(options = {}) {
|
|
|
92
114
|
createLsTool(),
|
|
93
115
|
createTodoTool(),
|
|
94
116
|
createTaskTool(options.task),
|
|
117
|
+
createTaskCtlTool(),
|
|
95
118
|
];
|
|
96
119
|
return tools;
|
|
97
120
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `task_ctl` 工具:查看 / 等待 / 停止后台子 Agent 任务,读输出,向任务追加消息
|
|
3
|
+
* (docs/wave5-plan.md §7.3,D13)。[W5-C0 桩 → W5-G]
|
|
4
|
+
*
|
|
5
|
+
* - 与 `task` 同进退(预设、`--tools`、`disable("task")`,见 registry.ts 的 `TOOL_COMPANIONS`);
|
|
6
|
+
* - 控制面按会话 id 取(agents/task-control.ts,注册表登记);子会话里(depth ≥ 1)不可用——工具表
|
|
7
|
+
* 与父一致,运行时拒绝;
|
|
8
|
+
* - `wait` / `output` 是轮询类调用(`annotations.pollable`,重复调用检测豁免);
|
|
9
|
+
* - `send` = 续聊放后台:等价于 `task{taskId, prompt, background:true}`,完成后同样收到通知。
|
|
10
|
+
*/
|
|
11
|
+
import type { ToolDefinition } from "./types.js";
|
|
12
|
+
export declare const TASK_CTL_TOOL = "task_ctl";
|
|
13
|
+
export declare const DEFAULT_WAIT_MS = 30000;
|
|
14
|
+
export declare const MAX_WAIT_MS = 600000;
|
|
15
|
+
export interface TaskCtlInput {
|
|
16
|
+
action: "list" | "wait" | "stop" | "output" | "send";
|
|
17
|
+
taskId?: string;
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
/** send:追加给任务的消息。 */
|
|
20
|
+
prompt?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function createTaskCtlTool(): ToolDefinition<TaskCtlInput>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `task_ctl` 工具:查看 / 等待 / 停止后台子 Agent 任务,读输出,向任务追加消息
|
|
3
|
+
* (docs/wave5-plan.md §7.3,D13)。[W5-C0 桩 → W5-G]
|
|
4
|
+
*
|
|
5
|
+
* - 与 `task` 同进退(预设、`--tools`、`disable("task")`,见 registry.ts 的 `TOOL_COMPANIONS`);
|
|
6
|
+
* - 控制面按会话 id 取(agents/task-control.ts,注册表登记);子会话里(depth ≥ 1)不可用——工具表
|
|
7
|
+
* 与父一致,运行时拒绝;
|
|
8
|
+
* - `wait` / `output` 是轮询类调用(`annotations.pollable`,重复调用检测豁免);
|
|
9
|
+
* - `send` = 续聊放后台:等价于 `task{taskId, prompt, background:true}`,完成后同样收到通知。
|
|
10
|
+
*/
|
|
11
|
+
import { capTaskText, formatTokens } from "../agents/result.js";
|
|
12
|
+
import { taskControl } from "../agents/task-control.js";
|
|
13
|
+
export const TASK_CTL_TOOL = "task_ctl";
|
|
14
|
+
export const DEFAULT_WAIT_MS = 30_000;
|
|
15
|
+
export const MAX_WAIT_MS = 600_000;
|
|
16
|
+
function fail(message) {
|
|
17
|
+
return { content: message, isError: true };
|
|
18
|
+
}
|
|
19
|
+
function line(task, now) {
|
|
20
|
+
const parts = [task.taskId, task.agent, task.status];
|
|
21
|
+
if (task.turns !== undefined)
|
|
22
|
+
parts.push(`${task.turns} turns`);
|
|
23
|
+
if (task.usage !== undefined)
|
|
24
|
+
parts.push(`${formatTokens(task.usage.totalTokens)} tokens`);
|
|
25
|
+
parts.push(`${Math.round(((task.endedAt ?? now) - task.startedAt) / 1000)}s`);
|
|
26
|
+
if (task.background)
|
|
27
|
+
parts.push("background");
|
|
28
|
+
const text = parts.join(" · ");
|
|
29
|
+
return task.description === "" ? text : `${text} — ${task.description}`;
|
|
30
|
+
}
|
|
31
|
+
async function send(input, ctx) {
|
|
32
|
+
if (input.prompt === undefined || input.prompt.trim() === "")
|
|
33
|
+
return fail("send needs a non-empty prompt");
|
|
34
|
+
if (ctx.spawnSubagent === undefined)
|
|
35
|
+
return fail("Sub-agents are not available here.");
|
|
36
|
+
const result = await ctx.spawnSubagent({
|
|
37
|
+
prompt: input.prompt,
|
|
38
|
+
taskId: input.taskId,
|
|
39
|
+
background: true,
|
|
40
|
+
parentToolCallId: ctx.toolCallId,
|
|
41
|
+
signal: ctx.signal,
|
|
42
|
+
});
|
|
43
|
+
return { content: result.text, isError: result.isError };
|
|
44
|
+
}
|
|
45
|
+
export function createTaskCtlTool() {
|
|
46
|
+
return {
|
|
47
|
+
name: TASK_CTL_TOOL,
|
|
48
|
+
label: "TaskCtl",
|
|
49
|
+
description: "Manage sub-agent tasks started by task: list them, wait for one, stop it, read its " +
|
|
50
|
+
"output, or send it a follow-up message (runs in background).",
|
|
51
|
+
parameters: {
|
|
52
|
+
type: "object",
|
|
53
|
+
properties: {
|
|
54
|
+
action: { type: "string", enum: ["list", "wait", "stop", "output", "send"] },
|
|
55
|
+
taskId: { type: "string", description: "Required except for list" },
|
|
56
|
+
timeoutMs: { type: "number", description: `wait only (default ${DEFAULT_WAIT_MS})` },
|
|
57
|
+
prompt: { type: "string", description: "send only" },
|
|
58
|
+
},
|
|
59
|
+
required: ["action"],
|
|
60
|
+
additionalProperties: false,
|
|
61
|
+
},
|
|
62
|
+
permission: "read",
|
|
63
|
+
executionMode: "parallel",
|
|
64
|
+
annotations: { pollable: true },
|
|
65
|
+
async execute(input, ctx) {
|
|
66
|
+
if (ctx.depth >= 1)
|
|
67
|
+
return fail("task_ctl is not available inside a sub-agent.");
|
|
68
|
+
const control = taskControl(ctx.sessionId);
|
|
69
|
+
if (input.action === "list") {
|
|
70
|
+
const tasks = control?.list() ?? ctx.tasks?.list() ?? [];
|
|
71
|
+
if (tasks.length === 0)
|
|
72
|
+
return { content: "No sub-agent tasks." };
|
|
73
|
+
const now = Date.now();
|
|
74
|
+
return { content: tasks.map((task) => line(task, now)).join("\n") };
|
|
75
|
+
}
|
|
76
|
+
const taskId = input.taskId;
|
|
77
|
+
if (taskId === undefined || taskId === "")
|
|
78
|
+
return fail(`${input.action} needs taskId`);
|
|
79
|
+
const info = control?.get(taskId);
|
|
80
|
+
if (control === undefined || info === undefined)
|
|
81
|
+
return fail(`Unknown task ${taskId}.`);
|
|
82
|
+
switch (input.action) {
|
|
83
|
+
case "send":
|
|
84
|
+
return send(input, ctx);
|
|
85
|
+
case "output": {
|
|
86
|
+
const text = control.output(taskId) ?? "";
|
|
87
|
+
const head = info.status === "running" ? `Task ${taskId} is running; output so far:` : "";
|
|
88
|
+
const body = capTaskText(text, info.outputFile).text || "(no output yet)";
|
|
89
|
+
return { content: head === "" ? body : `${head}\n${body}` };
|
|
90
|
+
}
|
|
91
|
+
case "stop": {
|
|
92
|
+
const result = await control.stop(taskId);
|
|
93
|
+
return {
|
|
94
|
+
content: `Task ${taskId} ${result?.status ?? control.get(taskId)?.status ?? "stopped"}.`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
case "wait": {
|
|
98
|
+
const timeout = Math.min(Math.max(input.timeoutMs ?? DEFAULT_WAIT_MS, 0), MAX_WAIT_MS);
|
|
99
|
+
const result = await control.wait(taskId, timeout);
|
|
100
|
+
if (result === undefined) {
|
|
101
|
+
const turns = control.get(taskId)?.turns ?? 0;
|
|
102
|
+
return {
|
|
103
|
+
content: `Task ${taskId} is still running (${turns} turns so far). Wait again or stop it.`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
content: `[task ${taskId} ${result.status ?? "completed"}]\n${result.text}`,
|
|
108
|
+
isError: result.isError,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
default:
|
|
112
|
+
return fail(`unknown action ${String(input.action)}`);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
package/dist/tools/task.d.ts
CHANGED
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `task`
|
|
2
|
+
* `task` 工具:子 Agent 的统一入口(设计 §5.2、D14;第五波 docs/wave5-plan.md §7.3,D13、D23)。
|
|
3
|
+
* [B3 → W5-G]
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
5
|
+
* - `agent`:子 Agent 类型(内置 general / explore / plan、`.ama/agents/*.md`)或外部 Agent;缺省
|
|
6
|
+
* general。描述里列出可用类型(catalog 由 compose-agents.ts 经 `bindTaskAgents` 绑定;没绑定时
|
|
7
|
+
* 只列内置类型)。
|
|
8
|
+
* - `background`:立即返回 taskId,完成后父会话收到 `<task-notification>`;`taskId`:向已有子会话
|
|
9
|
+
* 追加消息(续聊,忽略 agent / tools / model);`isolation: "worktree"`:在独立 git worktree 里跑。
|
|
10
|
+
* - **parallel**:同一回复里的多个 task 真并行(会话注册表的池限流,缺省 4);与 sequential 工具
|
|
11
|
+
* (edit 等)同批时仍按 tool-runner 的规则整批串行。
|
|
12
|
+
* - 深度 ≤ 1:子会话的工具表里保留 task(与父字节一致,缓存前缀可复用),运行时在这里拒绝。
|
|
13
|
+
* - 结果 = 子 Agent 的最终报告(> 50 KB 截头尾、全文落 outputs/,见 agents/result.ts)+ details。
|
|
12
14
|
*/
|
|
13
15
|
import type { ModelThinkingLevel } from "../ai/types.js";
|
|
16
|
+
import { AgentCatalog } from "../agents/catalog.js";
|
|
14
17
|
import type { SubagentRequest, ToolContext, ToolDefinition } from "./types.js";
|
|
15
18
|
export declare const MAX_TASK_DEPTH = 1;
|
|
16
19
|
export declare const DEFAULT_TASK_MAX_TURNS = 30;
|
|
17
20
|
export interface TaskInput {
|
|
18
21
|
prompt: string;
|
|
22
|
+
agent?: string;
|
|
19
23
|
description?: string;
|
|
24
|
+
background?: boolean;
|
|
25
|
+
taskId?: string;
|
|
26
|
+
isolation?: "none" | "worktree";
|
|
27
|
+
budgetUsd?: number;
|
|
20
28
|
tools?: string[];
|
|
21
29
|
model?: string;
|
|
22
30
|
thinkingLevel?: ModelThinkingLevel;
|
|
23
31
|
maxTurns?: number;
|
|
24
32
|
}
|
|
25
|
-
/**
|
|
33
|
+
/** 预留(并发上限在会话的任务注册表,见 agent/subagent-registry.ts)。 */
|
|
26
34
|
export interface TaskToolOptions {
|
|
27
35
|
}
|
|
36
|
+
/** 描述里类型清单的标题(清单本身另有 400 token 预算,见 agents/catalog.ts)。 */
|
|
37
|
+
export declare const TASK_AGENTS_HEADING = "\nAgents:\n";
|
|
38
|
+
/** 组装根把会话的类型目录绑到 task 工具上(描述里的类型清单)。 */
|
|
39
|
+
export declare function bindTaskAgents(tool: ToolDefinition | undefined, catalog: AgentCatalog): void;
|
|
28
40
|
export declare function buildSubagentRequest(input: TaskInput, ctx: ToolContext): SubagentRequest | string;
|
|
29
41
|
export declare function createTaskTool(_options?: TaskToolOptions): ToolDefinition<TaskInput>;
|