@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,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 消息区的子 Agent 折叠视图(docs/wave5-plan.md §7.5)。[W5-U]
|
|
3
|
+
*
|
|
4
|
+
* 消费 `subagent_start / update / end`,按 taskId 记下类型、状态、轮数、最近 3 个工具与用量;task 工具行
|
|
5
|
+
* (tool-view.ts)据 `parentToolCallId` 取来显示一行:
|
|
6
|
+
*
|
|
7
|
+
* ```
|
|
8
|
+
* ⏺ task 检查 src/tui 的测试覆盖缺口
|
|
9
|
+
* ⎿ ⠋ explore · 运行中 1m05s · 3 轮 · read grep bash · ↑12k ↓3.4k
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* 后台任务的工具调用立即返回,工具行下面多一行跟随状态(`↳ t2 explore · 完成 · 7 轮 …`,运行中每秒刷新);
|
|
13
|
+
* 完成后父会话收到的 `<task-notification>` 只显示一行(`notificationSummary`),失败 / 停止另有一行提示。
|
|
14
|
+
* 外部 runner(claude / codex)同一组事件,用量可能缺。
|
|
15
|
+
*/
|
|
16
|
+
import { formatElapsed } from "../../tui.js";
|
|
17
|
+
import { formatTokenCount } from "../session-report.js";
|
|
18
|
+
import { taskStatusText } from "./tasks-report.js";
|
|
19
|
+
export const RECENT_TOOLS = 3;
|
|
20
|
+
export class SubagentTracker {
|
|
21
|
+
now;
|
|
22
|
+
tasks = new Map();
|
|
23
|
+
byCall = new Map();
|
|
24
|
+
constructor(now = Date.now) {
|
|
25
|
+
this.now = now;
|
|
26
|
+
}
|
|
27
|
+
/** 子 Agent 事件:更新状态并返回它;其它事件返回 undefined。 */
|
|
28
|
+
onEvent(event) {
|
|
29
|
+
switch (event.type) {
|
|
30
|
+
case "subagent_start": {
|
|
31
|
+
const previous = this.tasks.get(event.taskId);
|
|
32
|
+
const state = {
|
|
33
|
+
taskId: event.taskId,
|
|
34
|
+
parentToolCallId: event.parentToolCallId,
|
|
35
|
+
agent: event.agent,
|
|
36
|
+
runner: event.runner,
|
|
37
|
+
background: event.background,
|
|
38
|
+
status: "running",
|
|
39
|
+
// 续聊(同一 taskId 再次 start)沿用轮数与工具
|
|
40
|
+
turns: previous?.turns ?? 0,
|
|
41
|
+
tools: previous?.tools ?? [],
|
|
42
|
+
startedAt: this.now(),
|
|
43
|
+
};
|
|
44
|
+
this.tasks.set(event.taskId, state);
|
|
45
|
+
this.byCall.set(event.parentToolCallId, event.taskId);
|
|
46
|
+
return state;
|
|
47
|
+
}
|
|
48
|
+
case "subagent_update": {
|
|
49
|
+
const state = this.tasks.get(event.taskId);
|
|
50
|
+
if (state === undefined)
|
|
51
|
+
return undefined;
|
|
52
|
+
if (event.turn > state.turns)
|
|
53
|
+
state.turns = event.turn;
|
|
54
|
+
if (event.usage !== undefined)
|
|
55
|
+
state.usage = event.usage;
|
|
56
|
+
if (event.kind === "tool" && event.toolName !== undefined) {
|
|
57
|
+
state.tools.push(event.toolName);
|
|
58
|
+
if (state.tools.length > RECENT_TOOLS)
|
|
59
|
+
state.tools.splice(0, state.tools.length - RECENT_TOOLS);
|
|
60
|
+
}
|
|
61
|
+
return state;
|
|
62
|
+
}
|
|
63
|
+
case "subagent_end": {
|
|
64
|
+
const state = this.tasks.get(event.taskId);
|
|
65
|
+
if (state === undefined)
|
|
66
|
+
return undefined;
|
|
67
|
+
state.status = event.status;
|
|
68
|
+
state.endedAt = this.now();
|
|
69
|
+
if (event.usage !== undefined)
|
|
70
|
+
state.usage = event.usage;
|
|
71
|
+
return state;
|
|
72
|
+
}
|
|
73
|
+
default:
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** 运行中的任务。 */
|
|
78
|
+
running() {
|
|
79
|
+
return [...this.tasks.values()].filter((state) => state.status === "running");
|
|
80
|
+
}
|
|
81
|
+
get(taskId) {
|
|
82
|
+
return this.tasks.get(taskId);
|
|
83
|
+
}
|
|
84
|
+
/** task 工具调用对应的子 Agent(续聊时是同一 taskId)。 */
|
|
85
|
+
forToolCall(toolCallId) {
|
|
86
|
+
const taskId = this.byCall.get(toolCallId);
|
|
87
|
+
return taskId === undefined ? undefined : this.tasks.get(taskId);
|
|
88
|
+
}
|
|
89
|
+
clear() {
|
|
90
|
+
this.tasks.clear();
|
|
91
|
+
this.byCall.clear();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** `explore · 运行中 1m05s · 3 轮 · read grep bash · ↑12k ↓3.4k`(已着色:类型 tool 色,其余 muted)。 */
|
|
95
|
+
export function subagentLine(state, theme, now) {
|
|
96
|
+
const g = theme.glyphs;
|
|
97
|
+
const end = state.endedAt ?? now;
|
|
98
|
+
const elapsed = formatElapsed(end - state.startedAt);
|
|
99
|
+
const status = state.status === "running" ? `运行中 ${elapsed}` : `${taskStatusText(state.status)} ${elapsed}`;
|
|
100
|
+
const facts = [status];
|
|
101
|
+
if (state.turns > 0)
|
|
102
|
+
facts.push(`${state.turns} 轮`);
|
|
103
|
+
if (state.tools.length > 0)
|
|
104
|
+
facts.push(state.tools.join(" "));
|
|
105
|
+
const usage = state.usage;
|
|
106
|
+
if (usage !== undefined && usage.input + usage.output + usage.cacheRead > 0) {
|
|
107
|
+
const input = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
108
|
+
facts.push(`${g.arrowUp}${formatTokenCount(input)} ${g.arrowDown}${formatTokenCount(usage.output)}`);
|
|
109
|
+
}
|
|
110
|
+
const color = state.status === "running" || state.status === "completed"
|
|
111
|
+
? "muted"
|
|
112
|
+
: state.status === "failed"
|
|
113
|
+
? "error"
|
|
114
|
+
: "warning";
|
|
115
|
+
const agent = state.runner !== "ama" && state.runner !== state.agent
|
|
116
|
+
? `${state.agent}(${state.runner})`
|
|
117
|
+
: state.agent;
|
|
118
|
+
return theme.fg("tool", agent) + theme.fg("dim", " · ") + theme.fg(color, facts.join(" · "));
|
|
119
|
+
}
|
|
120
|
+
/** 后台任务结束的一行提示。 */
|
|
121
|
+
export function backgroundEndText(state) {
|
|
122
|
+
const turns = state.turns > 0 ? ` · ${state.turns} 轮` : "";
|
|
123
|
+
return `后台任务 ${state.taskId}(${state.agent})${taskStatusText(state.status)}${turns} · /tasks 查看输出`;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 父会话收到的 `<task-notification …>`(origin `task` 的用户消息)在消息区只显示一行:
|
|
127
|
+
* `t1 explore 完成 · 7 轮 · /tasks 查看输出`;不是通知格式返回 undefined。
|
|
128
|
+
*/
|
|
129
|
+
export function notificationSummary(text) {
|
|
130
|
+
const head = /^<task-notification\s+([^>]*)>/.exec(text.trimStart());
|
|
131
|
+
if (head === null)
|
|
132
|
+
return undefined;
|
|
133
|
+
const attrs = new Map();
|
|
134
|
+
for (const m of (head[1] ?? "").matchAll(/(\w+)="([^"]*)"/g))
|
|
135
|
+
attrs.set(m[1], m[2]);
|
|
136
|
+
const taskId = attrs.get("taskId") ?? "?";
|
|
137
|
+
const status = attrs.get("status");
|
|
138
|
+
const parts = [
|
|
139
|
+
`${taskId} ${attrs.get("agent") ?? ""}`.trim() +
|
|
140
|
+
` ${status !== undefined && status in STATUS_KEYS ? taskStatusText(status) : (status ?? "")}`,
|
|
141
|
+
];
|
|
142
|
+
const turns = attrs.get("turns");
|
|
143
|
+
if (turns !== undefined)
|
|
144
|
+
parts.push(`${turns} 轮`);
|
|
145
|
+
parts.push("/tasks 查看输出");
|
|
146
|
+
return parts.join(" · ");
|
|
147
|
+
}
|
|
148
|
+
const STATUS_KEYS = {
|
|
149
|
+
completed: true,
|
|
150
|
+
failed: true,
|
|
151
|
+
aborted: true,
|
|
152
|
+
max_turns: true,
|
|
153
|
+
interrupted: true,
|
|
154
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/tasks`、`/agents` 的数据与文本(line 模式与交互模式共用)。[W5-U]
|
|
3
|
+
*
|
|
4
|
+
* - 任务:`taskRegistryView(sessionId).list()`(子 Agent 注册表,W5-G);全文 `registryOf(sessionId).output()`;
|
|
5
|
+
* 停止 `registryOf(sessionId).stop()`。
|
|
6
|
+
* - 类型:`cachedAgentInfos(sessionId) ?? sessionAgents(sessionId)`(外部 Agent 带安装状态与版本,W5-EG)。
|
|
7
|
+
*/
|
|
8
|
+
import type { AgentInfo } from "../../agents/types.js";
|
|
9
|
+
import type { SubagentStatus, TaskInfo } from "../../tools/types.js";
|
|
10
|
+
export declare function taskStatusText(status: SubagentStatus | "running"): string;
|
|
11
|
+
export declare function listTasks(sessionId: string): readonly TaskInfo[];
|
|
12
|
+
export declare function listAgents(sessionId: string): AgentInfo[];
|
|
13
|
+
/** 运行中是已有输出,结束后是最终文本。 */
|
|
14
|
+
export declare function taskOutput(sessionId: string, taskId: string): string | undefined;
|
|
15
|
+
export declare function stopTask(sessionId: string, taskId: string): Promise<void>;
|
|
16
|
+
/** 任务一行的各字段(状态、耗时、轮数、用量、费用)。 */
|
|
17
|
+
export declare function taskFacts(task: TaskInfo, now: number): string[];
|
|
18
|
+
/** `t1 explore · 运行中 · 1m05s · 7 轮 · 描述` */
|
|
19
|
+
export declare function taskLine(task: TaskInfo, now: number): string;
|
|
20
|
+
/** `/tasks` 的纯文本(line 模式)。 */
|
|
21
|
+
export declare function describeTasks(sessionId: string, now: number): string;
|
|
22
|
+
/** 一个任务的输出全文(line 模式 `/tasks <id>`)。 */
|
|
23
|
+
export declare function describeTaskOutput(sessionId: string, taskId: string, now: number): string;
|
|
24
|
+
/** 类型一行的状态:外部 Agent 写安装与版本。 */
|
|
25
|
+
export declare function agentFacts(agent: AgentInfo): string[];
|
|
26
|
+
/** `/agents` 的纯文本(line 模式)。 */
|
|
27
|
+
export declare function describeAgents(sessionId: string): string;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/tasks`、`/agents` 的数据与文本(line 模式与交互模式共用)。[W5-U]
|
|
3
|
+
*
|
|
4
|
+
* - 任务:`taskRegistryView(sessionId).list()`(子 Agent 注册表,W5-G);全文 `registryOf(sessionId).output()`;
|
|
5
|
+
* 停止 `registryOf(sessionId).stop()`。
|
|
6
|
+
* - 类型:`cachedAgentInfos(sessionId) ?? sessionAgents(sessionId)`(外部 Agent 带安装状态与版本,W5-EG)。
|
|
7
|
+
*/
|
|
8
|
+
import { cachedAgentInfos } from "../../agents/external.js";
|
|
9
|
+
import { registryOf, sessionAgents, taskRegistryView } from "../../agent/subagent-registry.js";
|
|
10
|
+
import { formatTokenCount, formatUsd } from "../session-report.js";
|
|
11
|
+
import { formatDuration } from "./tool-summary.js";
|
|
12
|
+
const STATUS = {
|
|
13
|
+
running: "运行中",
|
|
14
|
+
completed: "完成",
|
|
15
|
+
failed: "失败",
|
|
16
|
+
aborted: "已停止",
|
|
17
|
+
max_turns: "轮数耗尽",
|
|
18
|
+
interrupted: "已中断",
|
|
19
|
+
};
|
|
20
|
+
export function taskStatusText(status) {
|
|
21
|
+
return STATUS[status];
|
|
22
|
+
}
|
|
23
|
+
export function listTasks(sessionId) {
|
|
24
|
+
return taskRegistryView(sessionId)?.list() ?? [];
|
|
25
|
+
}
|
|
26
|
+
export function listAgents(sessionId) {
|
|
27
|
+
return cachedAgentInfos(sessionId) ?? sessionAgents(sessionId);
|
|
28
|
+
}
|
|
29
|
+
/** 运行中是已有输出,结束后是最终文本。 */
|
|
30
|
+
export function taskOutput(sessionId, taskId) {
|
|
31
|
+
return registryOf(sessionId)?.output(taskId);
|
|
32
|
+
}
|
|
33
|
+
export async function stopTask(sessionId, taskId) {
|
|
34
|
+
const registry = registryOf(sessionId);
|
|
35
|
+
if (registry === undefined)
|
|
36
|
+
return;
|
|
37
|
+
await registry.stop(taskId);
|
|
38
|
+
}
|
|
39
|
+
/** 任务一行的各字段(状态、耗时、轮数、用量、费用)。 */
|
|
40
|
+
export function taskFacts(task, now) {
|
|
41
|
+
const end = task.endedAt ?? now;
|
|
42
|
+
const facts = [taskStatusText(task.status), formatDuration(end - task.startedAt)];
|
|
43
|
+
if (task.turns !== undefined && task.turns > 0)
|
|
44
|
+
facts.push(`${task.turns} 轮`);
|
|
45
|
+
const usage = task.usage;
|
|
46
|
+
if (usage !== undefined && usage.input + usage.output + usage.cacheRead > 0)
|
|
47
|
+
facts.push(`↑${formatTokenCount(usage.input + usage.cacheRead + usage.cacheWrite)} ↓${formatTokenCount(usage.output)}`);
|
|
48
|
+
if (task.costUsd !== undefined && task.costUsd > 0)
|
|
49
|
+
facts.push(formatUsd(task.costUsd));
|
|
50
|
+
return facts;
|
|
51
|
+
}
|
|
52
|
+
function oneLine(text, max = 60) {
|
|
53
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
54
|
+
return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
|
|
55
|
+
}
|
|
56
|
+
/** `t1 explore · 运行中 · 1m05s · 7 轮 · 描述` */
|
|
57
|
+
export function taskLine(task, now) {
|
|
58
|
+
const agent = task.runner !== "ama" && task.runner !== task.agent
|
|
59
|
+
? `${task.agent}(${task.runner})`
|
|
60
|
+
: task.agent;
|
|
61
|
+
const parts = [agent, ...taskFacts(task, now)];
|
|
62
|
+
if (task.background)
|
|
63
|
+
parts.push("后台");
|
|
64
|
+
const description = oneLine(task.description);
|
|
65
|
+
return `${task.taskId} ${parts.join(" · ")}${description !== "" ? ` ${description}` : ""}`;
|
|
66
|
+
}
|
|
67
|
+
/** `/tasks` 的纯文本(line 模式)。 */
|
|
68
|
+
export function describeTasks(sessionId, now) {
|
|
69
|
+
const tasks = listTasks(sessionId);
|
|
70
|
+
if (tasks.length === 0)
|
|
71
|
+
return "还没有子 Agent 任务";
|
|
72
|
+
return [
|
|
73
|
+
`子 Agent 任务(${tasks.length}):`,
|
|
74
|
+
...tasks.map((task) => ` ${taskLine(task, now)}`),
|
|
75
|
+
"/tasks <id> 查看输出 · /tasks stop <id> 停止",
|
|
76
|
+
].join("\n");
|
|
77
|
+
}
|
|
78
|
+
/** 一个任务的输出全文(line 模式 `/tasks <id>`)。 */
|
|
79
|
+
export function describeTaskOutput(sessionId, taskId, now) {
|
|
80
|
+
const task = taskRegistryView(sessionId)?.get(taskId);
|
|
81
|
+
if (task === undefined)
|
|
82
|
+
return `没有任务 ${taskId}`;
|
|
83
|
+
const output = taskOutput(sessionId, taskId) ?? "";
|
|
84
|
+
const file = task.outputFile !== undefined ? `\n全文:${task.outputFile}` : "";
|
|
85
|
+
return `${taskLine(task, now)}${file}\n${output.trim() === "" ? "(还没有输出)" : output.trimEnd()}`;
|
|
86
|
+
}
|
|
87
|
+
const SOURCE = {
|
|
88
|
+
builtin: "内置",
|
|
89
|
+
cli: "命令行",
|
|
90
|
+
profile: "profile",
|
|
91
|
+
user: "用户",
|
|
92
|
+
project: "项目",
|
|
93
|
+
host: "宿主",
|
|
94
|
+
};
|
|
95
|
+
/** 类型一行的状态:外部 Agent 写安装与版本。 */
|
|
96
|
+
export function agentFacts(agent) {
|
|
97
|
+
const facts = [agent.runner, SOURCE[agent.source] ?? agent.source];
|
|
98
|
+
if (agent.installed === false)
|
|
99
|
+
facts.push("未安装");
|
|
100
|
+
else if (agent.installed === true)
|
|
101
|
+
facts.push(agent.version !== undefined ? `已安装 ${agent.version}` : "已安装");
|
|
102
|
+
return facts;
|
|
103
|
+
}
|
|
104
|
+
/** `/agents` 的纯文本(line 模式)。 */
|
|
105
|
+
export function describeAgents(sessionId) {
|
|
106
|
+
const agents = listAgents(sessionId);
|
|
107
|
+
if (agents.length === 0)
|
|
108
|
+
return "当前会话没有子 Agent(task 工具未启用)";
|
|
109
|
+
const width = Math.max(...agents.map((a) => a.name.length));
|
|
110
|
+
return [
|
|
111
|
+
`子 Agent 类型(${agents.length}):`,
|
|
112
|
+
...agents.map((a) => ` ${a.name.padEnd(width)} ${agentFacts(a).join(" · ")} ${oneLine(a.description)}`),
|
|
113
|
+
].join("\n");
|
|
114
|
+
}
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* … 另 117 行(Ctrl+O 展开)
|
|
10
10
|
* ```
|
|
11
11
|
* - 运行中摘要行 `⎿ ⠋ 运行中 · 4s`:spinner 与底部 Loader 同帧(ToolTracker.tick 由 Loader.onFrame 驱动),
|
|
12
|
-
* 标题行不变;bash 流式显示尾部 8 行(muted)。task 显示 `子 Agent · 运行中 1m05s
|
|
12
|
+
* 标题行不变;bash 流式显示尾部 8 行(muted)。task 显示 `子 Agent · 运行中 1m05s`;有 `subagent_*`
|
|
13
|
+
* 事件时(W5-U,subagent-view.ts)改为 `explore · 运行中 1m05s · 3 轮 · 最近 3 个工具 · ↑↓`,后台任务
|
|
14
|
+
* 在结果摘要下多一行跟随状态。
|
|
13
15
|
* - 折叠(缺省):结果前 3 行;edit 显示 `details.diff`(`@@` dim、`+` success、`-` error、上下文 muted,
|
|
14
16
|
* 宽 ≥ 60 时带行号列),前 12 行;`Ctrl+O` 展开全部(上限 400 行,长行折行)。
|
|
15
17
|
* - 嵌套:带 `parentToolCallId` 的调用(codemode 脚本里的 `tools.*`)挂在外层调用下、右移 4 列;折叠时只列
|
|
@@ -20,6 +22,7 @@
|
|
|
20
22
|
*/
|
|
21
23
|
import type { ToolDefinition, ToolResult } from "../../tools/types.js";
|
|
22
24
|
import { type Component, type Theme } from "../../tui.js";
|
|
25
|
+
import { type SubagentState } from "./subagent-view.js";
|
|
23
26
|
export { cleanLines, toolSummary } from "./tool-summary.js";
|
|
24
27
|
export declare const COLLAPSED_RESULT_LINES = 3;
|
|
25
28
|
export declare const COLLAPSED_DIFF_LINES = 12;
|
|
@@ -36,6 +39,8 @@ export interface ToolViewOptions {
|
|
|
36
39
|
now?(): number;
|
|
37
40
|
/** 运行中摘要行的 spinner 帧(与 Loader 同帧);缺省静态字形。 */
|
|
38
41
|
spinner?(): string;
|
|
42
|
+
/** [W5-U] task 调用对应的子 Agent 状态(折叠视图);缺省不显示。 */
|
|
43
|
+
subagent?(toolCallId: string): SubagentState | undefined;
|
|
39
44
|
}
|
|
40
45
|
export declare class ToolView implements Component {
|
|
41
46
|
readonly toolCallId: string;
|
|
@@ -69,14 +74,19 @@ export declare class ToolView implements Component {
|
|
|
69
74
|
addNested(child: ToolView): void;
|
|
70
75
|
/** 审批打开 / 关闭:还没有输出的运行中调用显示「等待确认」,关闭后从此刻重新计时。 */
|
|
71
76
|
setAwaiting(awaiting: boolean): void;
|
|
72
|
-
/** spinner 换帧 /
|
|
77
|
+
/** spinner 换帧 / 秒数变化:运行中的视图重画摘要行(后台子 Agent 运行中也算)。 */
|
|
73
78
|
tick(): void;
|
|
79
|
+
/** 外部状态变了(子 Agent 事件):重画。 */
|
|
80
|
+
refresh(): void;
|
|
81
|
+
private subagentState;
|
|
74
82
|
private touch;
|
|
75
83
|
invalidate(): void;
|
|
76
84
|
render(width: number): string[];
|
|
77
85
|
header(width: number): string;
|
|
78
86
|
/** ` ⎿ 摘要`:运行中带 spinner 与秒数,完成后是结果摘要。 */
|
|
79
87
|
summaryLine(width: number): string | undefined;
|
|
88
|
+
/** 后台子 Agent:结果摘要下一行跟随状态 ` ↳ t2 explore · 完成 2m · 7 轮 …`。 */
|
|
89
|
+
private followLine;
|
|
80
90
|
private custom;
|
|
81
91
|
/** `renderCall` 的第一行(去控制字符、折叠空白);没有或为空时 undefined。 */
|
|
82
92
|
private customCall;
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* … 另 117 行(Ctrl+O 展开)
|
|
10
10
|
* ```
|
|
11
11
|
* - 运行中摘要行 `⎿ ⠋ 运行中 · 4s`:spinner 与底部 Loader 同帧(ToolTracker.tick 由 Loader.onFrame 驱动),
|
|
12
|
-
* 标题行不变;bash 流式显示尾部 8 行(muted)。task 显示 `子 Agent · 运行中 1m05s
|
|
12
|
+
* 标题行不变;bash 流式显示尾部 8 行(muted)。task 显示 `子 Agent · 运行中 1m05s`;有 `subagent_*`
|
|
13
|
+
* 事件时(W5-U,subagent-view.ts)改为 `explore · 运行中 1m05s · 3 轮 · 最近 3 个工具 · ↑↓`,后台任务
|
|
14
|
+
* 在结果摘要下多一行跟随状态。
|
|
13
15
|
* - 折叠(缺省):结果前 3 行;edit 显示 `details.diff`(`@@` dim、`+` success、`-` error、上下文 muted,
|
|
14
16
|
* 宽 ≥ 60 时带行号列),前 12 行;`Ctrl+O` 展开全部(上限 400 行,长行折行)。
|
|
15
17
|
* - 嵌套:带 `parentToolCallId` 的调用(codemode 脚本里的 `tools.*`)挂在外层调用下、右移 4 列;折叠时只列
|
|
@@ -20,6 +22,7 @@
|
|
|
20
22
|
*/
|
|
21
23
|
import { formatElapsed, truncateToWidth, wrapTextWithAnsi, } from "../../tui.js";
|
|
22
24
|
import { contentText } from "./message-view.js";
|
|
25
|
+
import { subagentLine } from "./subagent-view.js";
|
|
23
26
|
import { bashOutput, cleanLines, diffOf, flat, parseDiff, resultSummary, toolSummary, } from "./tool-summary.js";
|
|
24
27
|
export { cleanLines, toolSummary } from "./tool-summary.js";
|
|
25
28
|
export const COLLAPSED_RESULT_LINES = 3;
|
|
@@ -108,11 +111,18 @@ export class ToolView {
|
|
|
108
111
|
this.awaiting = awaiting;
|
|
109
112
|
this.touch();
|
|
110
113
|
}
|
|
111
|
-
/** spinner 换帧 /
|
|
114
|
+
/** spinner 换帧 / 秒数变化:运行中的视图重画摘要行(后台子 Agent 运行中也算)。 */
|
|
112
115
|
tick() {
|
|
113
|
-
if (this.state === "running")
|
|
116
|
+
if (this.state === "running" || this.subagentState()?.status === "running")
|
|
114
117
|
this.touch();
|
|
115
118
|
}
|
|
119
|
+
/** 外部状态变了(子 Agent 事件):重画。 */
|
|
120
|
+
refresh() {
|
|
121
|
+
this.touch();
|
|
122
|
+
}
|
|
123
|
+
subagentState() {
|
|
124
|
+
return this.toolName === "task" ? this.options.subagent?.(this.toolCallId) : undefined;
|
|
125
|
+
}
|
|
116
126
|
touch() {
|
|
117
127
|
this.version++;
|
|
118
128
|
this.parent?.touch();
|
|
@@ -126,7 +136,12 @@ export class ToolView {
|
|
|
126
136
|
if (this.cache && this.cache.width === width && this.cache.version === this.version) {
|
|
127
137
|
return this.cache.lines;
|
|
128
138
|
}
|
|
129
|
-
const lines = [
|
|
139
|
+
const lines = [
|
|
140
|
+
this.header(width),
|
|
141
|
+
this.summaryLine(width),
|
|
142
|
+
this.followLine(width),
|
|
143
|
+
...this.body(width),
|
|
144
|
+
].filter((line) => line !== undefined);
|
|
130
145
|
this.cache = { width, version: this.version, lines };
|
|
131
146
|
return lines;
|
|
132
147
|
}
|
|
@@ -146,6 +161,12 @@ export class ToolView {
|
|
|
146
161
|
if (this.state === "running" && this.awaiting) {
|
|
147
162
|
return truncateToWidth(lead + theme.fg("dim", `${g.spinnerStatic} 等待确认`), width);
|
|
148
163
|
}
|
|
164
|
+
const sub = this.subagentState();
|
|
165
|
+
if (this.state === "running" && sub !== undefined) {
|
|
166
|
+
const frame = this.options.spinner?.() ?? g.spinnerStatic;
|
|
167
|
+
const line = subagentLine(sub, theme, this.now());
|
|
168
|
+
return truncateToWidth(lead + theme.fg("accent", frame) + " " + line, width);
|
|
169
|
+
}
|
|
149
170
|
if (this.state === "running") {
|
|
150
171
|
const frame = this.options.spinner?.() ?? g.spinnerStatic;
|
|
151
172
|
const elapsed = formatElapsed(this.now() - this.startedAt);
|
|
@@ -164,6 +185,15 @@ export class ToolView {
|
|
|
164
185
|
}, theme);
|
|
165
186
|
return truncateToWidth(lead + text, width);
|
|
166
187
|
}
|
|
188
|
+
/** 后台子 Agent:结果摘要下一行跟随状态 ` ↳ t2 explore · 完成 2m · 7 轮 …`。 */
|
|
189
|
+
followLine(width) {
|
|
190
|
+
const sub = this.subagentState();
|
|
191
|
+
if (this.state === "running" || sub === undefined || !sub.background)
|
|
192
|
+
return undefined;
|
|
193
|
+
const { theme } = this.options;
|
|
194
|
+
const head = theme.fg("dim", `${theme.glyphs.queued} ${sub.taskId} `);
|
|
195
|
+
return truncateToWidth(BODY + head + subagentLine(sub, theme, this.now()), width);
|
|
196
|
+
}
|
|
167
197
|
custom(render) {
|
|
168
198
|
const tool = this.options.getTool?.(this.toolName);
|
|
169
199
|
if (tool === undefined)
|
|
@@ -15,13 +15,18 @@
|
|
|
15
15
|
* - 重试:text / json 格式在 stderr 打一行 `↻ 重试 n/m`(stream-json 里本来就有事件),等待期间不再无声。
|
|
16
16
|
* - 无人值守:ask → deny(bootstrap 已按 print 设 unattended)。被拒的调用(`tool_execution_end`
|
|
17
17
|
* 带 `denied`)在 stderr 汇总一行(工具 ×次数、首个原因、放行办法),json 结果带 `deniedTools`。
|
|
18
|
-
* -
|
|
19
|
-
* json 带 `
|
|
20
|
-
*
|
|
21
|
-
*
|
|
18
|
+
* - [W5-H2] 预算(`--max-turns N` / `--max-cost USD` / config `limits.*`,agent/limits.ts):到限
|
|
19
|
+
* (会话发 `limit_reached`)→ stderr 一行、json 带 `limitReached{kind, value, limit}`(回合到限另带
|
|
20
|
+
* `maxTurnsReached: true`)、退出码 8。
|
|
21
|
+
* - [W5-H2] plan 模式产出计划、`plan.unattended: stop`(缺省)没人审批:stderr 一行(计划文件与审批办法)、
|
|
22
|
+
* json 带 `planPending{planId, version, filePath}`、退出码 9。
|
|
23
|
+
* - [W5-H2] `--image` / `@图片` 超限时按 config `images.resize` 缩放(缺省 auto)。
|
|
24
|
+
* - 退出码:最终助手消息 `error / aborted` 或提示被拒 → 1;有工具调用被拒 → 7;到达预算 → 8;
|
|
25
|
+
* 计划待审批 → 9;SIGINT 130、SIGTERM 143(先 abort)。
|
|
22
26
|
*/
|
|
23
27
|
import type { CliIo, ModeContext } from "../../cli/deps.js";
|
|
24
28
|
import type { Runtime } from "../../cli/runtime.js";
|
|
29
|
+
import type { LimitReachedEvent, PlanProposedEvent } from "../../agent/types.js";
|
|
25
30
|
export declare function joinPrompt(argument: string | undefined, piped: string): string;
|
|
26
31
|
/** 等 stdin 多久后提示一次「正在等待」。 */
|
|
27
32
|
export declare const STDIN_WAIT_HINT_MS = 3000;
|
|
@@ -34,6 +39,10 @@ export declare function stdinWaitMs(env: Readonly<Record<string, string | undefi
|
|
|
34
39
|
*/
|
|
35
40
|
export declare function readPromptStdin(io: CliIo, prompt: string | undefined, mode: "auto" | "explicit" | "off", hintMs?: number): Promise<string>;
|
|
36
41
|
export declare function runPrintMode(runtime: Runtime, context: ModeContext): Promise<number>;
|
|
42
|
+
/** stderr 一行:计划已落盘待审批(-p 不替人批准)。 */
|
|
43
|
+
export declare function describePlanPending(plan: PlanProposedEvent): string;
|
|
44
|
+
/** stderr 一行:哪个预算到限。 */
|
|
45
|
+
export declare function describeLimit(event: LimitReachedEvent): string;
|
|
37
46
|
/** 被拒的一次工具调用(json 结果的 `deniedTools` 元素)。 */
|
|
38
47
|
export interface DeniedTool {
|
|
39
48
|
toolCallId: string;
|
|
@@ -15,15 +15,20 @@
|
|
|
15
15
|
* - 重试:text / json 格式在 stderr 打一行 `↻ 重试 n/m`(stream-json 里本来就有事件),等待期间不再无声。
|
|
16
16
|
* - 无人值守:ask → deny(bootstrap 已按 print 设 unattended)。被拒的调用(`tool_execution_end`
|
|
17
17
|
* 带 `denied`)在 stderr 汇总一行(工具 ×次数、首个原因、放行办法),json 结果带 `deniedTools`。
|
|
18
|
-
* -
|
|
19
|
-
* json 带 `
|
|
20
|
-
*
|
|
21
|
-
*
|
|
18
|
+
* - [W5-H2] 预算(`--max-turns N` / `--max-cost USD` / config `limits.*`,agent/limits.ts):到限
|
|
19
|
+
* (会话发 `limit_reached`)→ stderr 一行、json 带 `limitReached{kind, value, limit}`(回合到限另带
|
|
20
|
+
* `maxTurnsReached: true`)、退出码 8。
|
|
21
|
+
* - [W5-H2] plan 模式产出计划、`plan.unattended: stop`(缺省)没人审批:stderr 一行(计划文件与审批办法)、
|
|
22
|
+
* json 带 `planPending{planId, version, filePath}`、退出码 9。
|
|
23
|
+
* - [W5-H2] `--image` / `@图片` 超限时按 config `images.resize` 缩放(缺省 auto)。
|
|
24
|
+
* - 退出码:最终助手消息 `error / aborted` 或提示被拒 → 1;有工具调用被拒 → 7;到达预算 → 8;
|
|
25
|
+
* 计划待审批 → 9;SIGINT 130、SIGTERM 143(先 abort)。
|
|
22
26
|
*/
|
|
23
27
|
import { currentSession } from "../../cli/compose-session.js";
|
|
24
28
|
import { ExitCode } from "../../cli/exit-codes.js";
|
|
25
29
|
import { errorText, lastAssistant, onStdoutClosed, onTerminationSignals } from "../shared.js";
|
|
26
30
|
import { toJsonLine, toWireEvent } from "./json-event.js";
|
|
31
|
+
import { formatUsd } from "../../agent/limits.js";
|
|
27
32
|
import { promptImages, sessionModel } from "../image-input.js";
|
|
28
33
|
export function joinPrompt(argument, piped) {
|
|
29
34
|
const parts = [argument ?? "", piped.replace(/\s+$/, "")].filter((p) => p.trim() !== "");
|
|
@@ -100,15 +105,24 @@ export async function runPrintMode(runtime, context) {
|
|
|
100
105
|
}
|
|
101
106
|
const session = currentSession(runtime);
|
|
102
107
|
let images;
|
|
108
|
+
const resize = runtime.config.images?.resize;
|
|
103
109
|
try {
|
|
104
|
-
images = await promptImages(prompt, context.args.images, io.cwd, sessionModel(runtime.providers, session));
|
|
110
|
+
images = await promptImages(prompt, context.args.images, io.cwd, sessionModel(runtime.providers, session), resize === undefined ? {} : { resize });
|
|
105
111
|
}
|
|
106
112
|
catch (error) {
|
|
107
113
|
io.stderr(`ama: ${errorText(error)}\n`);
|
|
108
114
|
return ExitCode.Usage;
|
|
109
115
|
}
|
|
110
116
|
const denied = [];
|
|
117
|
+
let limit;
|
|
118
|
+
let plan;
|
|
111
119
|
const unsubscribe = session.subscribe((event) => {
|
|
120
|
+
if (event.type === "limit_reached")
|
|
121
|
+
limit ??= event;
|
|
122
|
+
else if (event.type === "plan_proposed")
|
|
123
|
+
plan = event;
|
|
124
|
+
else if (event.type === "plan_resolved" && event.planId === plan?.planId)
|
|
125
|
+
plan = undefined;
|
|
112
126
|
if (event.type === "tool_execution_end" && event.denied === true)
|
|
113
127
|
denied.push({
|
|
114
128
|
toolCallId: event.toolCallId,
|
|
@@ -144,9 +158,6 @@ export async function runPrintMode(runtime, context) {
|
|
|
144
158
|
}
|
|
145
159
|
const last = lastAssistant(session);
|
|
146
160
|
const text = session.getLastAssistantText() ?? "";
|
|
147
|
-
// 回合上限在工具执行之后结束运行:最后一条助手消息停在 toolUse 即「没做完」
|
|
148
|
-
const maxTurns = context.args.maxTurns;
|
|
149
|
-
const turnsExhausted = maxTurns !== undefined && failure === undefined && last?.stopReason === "toolUse";
|
|
150
161
|
const stopReason = failure !== undefined ? "error" : (last?.stopReason ?? "stop");
|
|
151
162
|
if (format === "text") {
|
|
152
163
|
// 部分模型在正文前多发空行:只去前导空行,保留首行缩进;json / stream-json 原样。
|
|
@@ -171,7 +182,21 @@ export async function runPrintMode(runtime, context) {
|
|
|
171
182
|
cacheHitRate: stats.cacheHitRate,
|
|
172
183
|
...(stats.cache !== undefined ? { cache: stats.cache } : {}),
|
|
173
184
|
...(denied.length > 0 ? { deniedTools: denied } : {}),
|
|
174
|
-
...(
|
|
185
|
+
...(plan !== undefined
|
|
186
|
+
? {
|
|
187
|
+
planPending: {
|
|
188
|
+
planId: plan.planId,
|
|
189
|
+
version: plan.version,
|
|
190
|
+
...(plan.filePath === undefined ? {} : { filePath: plan.filePath }),
|
|
191
|
+
},
|
|
192
|
+
}
|
|
193
|
+
: {}),
|
|
194
|
+
...(limit !== undefined
|
|
195
|
+
? {
|
|
196
|
+
limitReached: { kind: limit.kind, value: limit.value, limit: limit.limit },
|
|
197
|
+
...(limit.kind === "turns" ? { maxTurnsReached: true } : {}),
|
|
198
|
+
}
|
|
199
|
+
: {}),
|
|
175
200
|
entries: session.entries,
|
|
176
201
|
})}\n`);
|
|
177
202
|
}
|
|
@@ -183,20 +208,39 @@ export async function runPrintMode(runtime, context) {
|
|
|
183
208
|
io.stderr(`ama: ${failure}\n`);
|
|
184
209
|
return ExitCode.RuntimeError;
|
|
185
210
|
}
|
|
211
|
+
if (limit !== undefined) {
|
|
212
|
+
if (denied.length > 0)
|
|
213
|
+
io.stderr(`${describeDenied(denied)}\n`);
|
|
214
|
+
io.stderr(`${describeLimit(limit)}\n`);
|
|
215
|
+
return ExitCode.LimitReached;
|
|
216
|
+
}
|
|
186
217
|
if (last?.stopReason === "error" || last?.stopReason === "aborted") {
|
|
187
218
|
io.stderr(`ama: ${last.errorMessage ?? "模型调用失败"}\n`);
|
|
188
219
|
return ExitCode.RuntimeError;
|
|
189
220
|
}
|
|
190
221
|
if (denied.length > 0)
|
|
191
222
|
io.stderr(`${describeDenied(denied)}\n`);
|
|
192
|
-
if (
|
|
193
|
-
io.stderr(
|
|
194
|
-
return ExitCode.
|
|
223
|
+
if (plan !== undefined) {
|
|
224
|
+
io.stderr(`${describePlanPending(plan)}\n`);
|
|
225
|
+
return ExitCode.PlanPending;
|
|
195
226
|
}
|
|
196
227
|
if (denied.length > 0)
|
|
197
228
|
return ExitCode.ToolDenied;
|
|
198
229
|
return ExitCode.Ok;
|
|
199
230
|
}
|
|
231
|
+
/** stderr 一行:计划已落盘待审批(-p 不替人批准)。 */
|
|
232
|
+
export function describePlanPending(plan) {
|
|
233
|
+
const where = plan.filePath ?? plan.planId;
|
|
234
|
+
return (`ama: 计划 v${plan.version} 已落盘、待审批(未执行):${where};-p 不替人批准——` +
|
|
235
|
+
"在交互界面或 RPC plan_response 里审批,或设 plan.unattended: approve 让 -p 批准后接着执行");
|
|
236
|
+
}
|
|
237
|
+
/** stderr 一行:哪个预算到限。 */
|
|
238
|
+
export function describeLimit(event) {
|
|
239
|
+
return event.kind === "turns"
|
|
240
|
+
? `ama: 已达到回合上限 ${event.limit}(--max-turns / limits.maxTurns),运行在完成前结束`
|
|
241
|
+
: `ama: 已达到费用上限 ${formatUsd(event.limit)}(累计 ${formatUsd(event.value)};` +
|
|
242
|
+
"--max-cost / limits.maxCostUsd),运行在完成前结束";
|
|
243
|
+
}
|
|
200
244
|
function textOf(event) {
|
|
201
245
|
const content = event.result.content;
|
|
202
246
|
const text = typeof content === "string"
|
|
@@ -8,7 +8,12 @@
|
|
|
8
8
|
* - 审批:`RpcApprovals` 是 UI broker(`set_client_capabilities` 声明 approvals 后挂上),
|
|
9
9
|
* `permission_response` 按 requestId 作答;先到的回答暂存,等 broker 被问到时取用。
|
|
10
10
|
* - 密钥不离开进程:`get_available_models` 只回 `hasKey` 与 `keySource`。
|
|
11
|
+
* - [W5-F] 计划:声明 `plans` 能力后计划审批交客户端(`plan_proposed` → `plan_response`),未声明按
|
|
12
|
+
* `plan.unattended`;`approve_fresh` 在这里新建会话并以计划全文开新回合。`get_tasks / get_agents`
|
|
13
|
+
* 读 `RpcContext.tasks / agents`(W5-G 的注册表与发现结果;未装配时回空表)。
|
|
11
14
|
*/
|
|
15
|
+
import type { AgentInfo } from "../../agents/types.js";
|
|
16
|
+
import type { TaskRegistryView } from "../../tools/types.js";
|
|
12
17
|
import type { AgentSession } from "../../agent/types.js";
|
|
13
18
|
import type { Runtime } from "../../cli/runtime.js";
|
|
14
19
|
import type { ApprovalBroker, ApprovalDecision, ApprovalRequest } from "../../permissions/types.js";
|
|
@@ -32,6 +37,10 @@ export interface RpcContext {
|
|
|
32
37
|
onSessionChanged(next: AgentSession): void;
|
|
33
38
|
/** 运行开始后提示命令自身的失败(应答已发出)。 */
|
|
34
39
|
onBackgroundError(error: unknown): void;
|
|
40
|
+
/** [W5-F] `get_tasks`:子 Agent 任务注册表的只读视图(W5-G 装配;缺省回空表)。 */
|
|
41
|
+
tasks?(): TaskRegistryView | undefined;
|
|
42
|
+
/** [W5-F] `get_agents`:可用的子 Agent 类型与外部 Agent(W5-G / W5-E 装配;缺省回空表)。 */
|
|
43
|
+
agents?(): readonly AgentInfo[];
|
|
35
44
|
}
|
|
36
45
|
export type RpcHandlers = {
|
|
37
46
|
[K in RpcCommandType]: (params: RpcCommandMap[K], ctx: RpcContext) => Promise<unknown>;
|