@armadra/agent 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +174 -1
- package/README.md +201 -82
- 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 +36203 -20499
- 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/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-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.js +5 -6
- 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 +7 -1
- package/dist/modes/commands-core.js +55 -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 +9 -1
- package/dist/modes/interactive/commands.js +19 -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 +134 -136
- package/dist/modes/interactive/key-dispatch.d.ts +16 -2
- package/dist/modes/interactive/key-dispatch.js +49 -1
- package/dist/modes/interactive/line/line-mode.d.ts +2 -1
- package/dist/modes/interactive/line/line-mode.js +22 -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/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/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 +5 -0
- package/dist/tui/keybindings.js +5 -0
- 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 +77 -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 +125 -6
- package/package.json +13 -2
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* default 模式下 `task(agent="claude")` 会问两次:task 工具调用一次,外部 Agent 本会话首次运行再一次
|
|
3
|
+
* (agents/external.ts 的 `firstRun`)。界面层把它们合并成一次确认。[W5-U]
|
|
4
|
+
*
|
|
5
|
+
* 规则(不放宽权限语义):
|
|
6
|
+
* - 用户在对话框里**允许**了一次 `task` 工具调用,且它的 `agent` 是外部 Agent(类型的 runner 不是
|
|
7
|
+
* ama)——对话框已把「以你在该 CLI 的登录运行」写在正文里——记下 `{agent, 时刻}`;
|
|
8
|
+
* - **紧接着**的下一个审批请求若是同一 Agent 的首次运行确认(`toolName: "task"`、输入带 `note`),其
|
|
9
|
+
* `context.taskId` 对应的任务是该 Agent、且在允许之后才建立(同一次调用产生的任务),并在 60 s 内
|
|
10
|
+
* 到达,就以「允许」自动答复,不再弹框;
|
|
11
|
+
* - 记录只用一次;中间夹了任何别的审批请求、拒绝、超时,都作废——首次运行确认照常弹出。
|
|
12
|
+
*/
|
|
13
|
+
import { taskRegistryView } from "../../agent/subagent-registry.js";
|
|
14
|
+
import { isFirstRunRequest } from "./approval-dialog.js";
|
|
15
|
+
import { listAgents } from "./tasks-report.js";
|
|
16
|
+
export const MERGE_WINDOW_MS = 60_000;
|
|
17
|
+
function input(request) {
|
|
18
|
+
const value = request.input;
|
|
19
|
+
return typeof value === "object" && value !== null ? value : {};
|
|
20
|
+
}
|
|
21
|
+
export class FirstRunMerge {
|
|
22
|
+
deps;
|
|
23
|
+
pending;
|
|
24
|
+
constructor(deps) {
|
|
25
|
+
this.deps = deps;
|
|
26
|
+
}
|
|
27
|
+
now() {
|
|
28
|
+
return this.deps.now?.() ?? Date.now();
|
|
29
|
+
}
|
|
30
|
+
/** `task` 调用的 agent 是外部 Agent 时返回它的 runner。 */
|
|
31
|
+
externalRunner(agent) {
|
|
32
|
+
const runner = this.deps.runnerOf?.(agent) ??
|
|
33
|
+
listAgents(this.deps.sessionId()).find((a) => a.name === agent)?.runner;
|
|
34
|
+
return runner === undefined || runner === "ama" ? undefined : runner;
|
|
35
|
+
}
|
|
36
|
+
taskOf(taskId) {
|
|
37
|
+
if (this.deps.taskOf !== undefined)
|
|
38
|
+
return this.deps.taskOf(taskId);
|
|
39
|
+
return taskRegistryView(this.deps.sessionId())?.get(taskId);
|
|
40
|
+
}
|
|
41
|
+
/** 请求到来:命中合并返回 `allow`(不弹框);否则返回 undefined,并作废记录。 */
|
|
42
|
+
intercept(request) {
|
|
43
|
+
const pending = this.pending;
|
|
44
|
+
this.pending = undefined;
|
|
45
|
+
if (pending === undefined || !isFirstRunRequest(request))
|
|
46
|
+
return undefined;
|
|
47
|
+
if (this.now() - pending.at > (this.deps.windowMs ?? MERGE_WINDOW_MS))
|
|
48
|
+
return undefined;
|
|
49
|
+
const taskId = request.context?.taskId;
|
|
50
|
+
if (taskId === undefined || request.context?.origin !== undefined)
|
|
51
|
+
return undefined;
|
|
52
|
+
const task = this.taskOf(taskId);
|
|
53
|
+
if (task === undefined || task.agent !== pending.agent || task.startedAt < pending.at)
|
|
54
|
+
return undefined;
|
|
55
|
+
const runner = this.externalRunner(pending.agent);
|
|
56
|
+
if (runner === undefined || input(request)["agent"] !== runner)
|
|
57
|
+
return undefined;
|
|
58
|
+
return "allow";
|
|
59
|
+
}
|
|
60
|
+
/** 用户答复之后:允许了外部 Agent 的 task 调用就记下。 */
|
|
61
|
+
record(request, decision) {
|
|
62
|
+
this.pending = undefined;
|
|
63
|
+
if (decision !== "allow" && decision !== "allow_session")
|
|
64
|
+
return;
|
|
65
|
+
if (request.toolName !== "task" || isFirstRunRequest(request))
|
|
66
|
+
return;
|
|
67
|
+
if ((request.context?.depth ?? 0) > 0 || request.context?.origin !== undefined)
|
|
68
|
+
return;
|
|
69
|
+
const agent = input(request)["agent"];
|
|
70
|
+
if (typeof agent !== "string" || this.externalRunner(agent) === undefined)
|
|
71
|
+
return;
|
|
72
|
+
this.pending = { agent, at: this.now() };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** 把合并规则套在界面 broker 外面;自动答复时调 `onMerged`(消息区一行说明)。 */
|
|
76
|
+
export function mergingBroker(inner, merge, onMerged) {
|
|
77
|
+
return {
|
|
78
|
+
async ask(request, signal) {
|
|
79
|
+
const merged = merge.intercept(request);
|
|
80
|
+
if (merged !== undefined) {
|
|
81
|
+
onMerged?.(request);
|
|
82
|
+
return merged;
|
|
83
|
+
}
|
|
84
|
+
const decision = await inner.ask(request, signal);
|
|
85
|
+
merge.record(request, decision);
|
|
86
|
+
return decision;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Ctrl+V` 与 `/paste`:剪贴板图片写进 `<dataDir>/clipboard/`,输入框插入 `@<路径>`(发送时按 `@图片`
|
|
3
|
+
* 附件读取)。[W5-U] 读取本身在 tools/clipboard-image.ts(W5-I)。
|
|
4
|
+
*/
|
|
5
|
+
import { type ClipboardDeps } from "../../tools/clipboard-image.js";
|
|
6
|
+
export type PasteOutcome = {
|
|
7
|
+
ok: true;
|
|
8
|
+
ref: string;
|
|
9
|
+
path: string;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
message: string;
|
|
13
|
+
};
|
|
14
|
+
export declare const NO_CLIPBOARD_TOOL = "\u8BFB\u4E0D\u4E86\u526A\u8D34\u677F\u56FE\u7247\uFF1A\u6CA1\u6709\u53EF\u7528\u7684\u7CFB\u7EDF\u547D\u4EE4\uFF08macOS osascript / pngpaste\uFF0CLinux wl-paste / xclip\uFF0CWindows PowerShell\uFF09";
|
|
15
|
+
export declare const NO_CLIPBOARD_IMAGE = "\u526A\u8D34\u677F\u91CC\u6CA1\u6709\u56FE\u7247";
|
|
16
|
+
/** `@路径`;路径带空白时加引号。 */
|
|
17
|
+
export declare function imageRef(path: string): string;
|
|
18
|
+
export declare function pasteImage(dataDir: string, deps?: ClipboardDeps): Promise<PasteOutcome>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Ctrl+V` 与 `/paste`:剪贴板图片写进 `<dataDir>/clipboard/`,输入框插入 `@<路径>`(发送时按 `@图片`
|
|
3
|
+
* 附件读取)。[W5-U] 读取本身在 tools/clipboard-image.ts(W5-I)。
|
|
4
|
+
*/
|
|
5
|
+
import { readClipboardImage } from "../../tools/clipboard-image.js";
|
|
6
|
+
export const NO_CLIPBOARD_TOOL = "读不了剪贴板图片:没有可用的系统命令(macOS osascript / pngpaste,Linux wl-paste / xclip,Windows PowerShell)";
|
|
7
|
+
export const NO_CLIPBOARD_IMAGE = "剪贴板里没有图片";
|
|
8
|
+
/** `@路径`;路径带空白时加引号。 */
|
|
9
|
+
export function imageRef(path) {
|
|
10
|
+
return /\s/.test(path) ? `@"${path}"` : `@${path}`;
|
|
11
|
+
}
|
|
12
|
+
export async function pasteImage(dataDir, deps) {
|
|
13
|
+
try {
|
|
14
|
+
const result = await readClipboardImage(dataDir, deps);
|
|
15
|
+
if (result.ok)
|
|
16
|
+
return { ok: true, ref: imageRef(result.path), path: result.path };
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
message: result.reason === "no_tool" ? NO_CLIPBOARD_TOOL : NO_CLIPBOARD_IMAGE,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
return {
|
|
24
|
+
ok: false,
|
|
25
|
+
message: `读取剪贴板失败:${error instanceof Error ? error.message : String(error)}`,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
* - 交互模式自有命令:`/tree`(同一文件内换叶子到选中消息之前,文本回填编辑器,可改后重发形成新分支)、
|
|
8
8
|
* `/permissions`(当前模式、判定顺序与已加载规则);`/help` 追加这两条与按键说明。
|
|
9
9
|
* - `/session`、`/cache`(无参数)与 `/permissions` 在消息区画左竖条面板(panels.ts),不再拍成文本。
|
|
10
|
+
* - `/rewind`(无参数)打开回滚列表与确认面板(rewind-flow.ts);带参数走 commands-core,对话变了时
|
|
11
|
+
* 重画消息区并回填原消息。
|
|
10
12
|
* - 不是命令(含模板与 `/skill:`)返回 false,调用方把整行当提示发出。
|
|
11
13
|
*/
|
|
12
|
-
import type { AgentSession } from "../../agent/types.js";
|
|
14
|
+
import type { AgentSession, RewindDraftText } from "../../agent/types.js";
|
|
13
15
|
import type { SwitchRequest } from "../../cli/compose-session.js";
|
|
14
16
|
import type { Runtime } from "../../cli/runtime.js";
|
|
15
17
|
import type { Component, SelectItem, Theme } from "../../tui.js";
|
|
@@ -34,6 +36,10 @@ export interface CommandUi {
|
|
|
34
36
|
prompt(text: string): void;
|
|
35
37
|
/** /tree 换叶子后重画消息区。 */
|
|
36
38
|
reload(): void;
|
|
39
|
+
/** 回滚列表与确认面板(`/rewind` 无参数);没有时回落为文字列表。 */
|
|
40
|
+
rewind?(): Promise<void>;
|
|
41
|
+
/** 回填原消息(文本 + 图片);缺省只回填文本。 */
|
|
42
|
+
setDraft?(draft: RewindDraftText): void;
|
|
37
43
|
exit(code: number): void;
|
|
38
44
|
now(): number;
|
|
39
45
|
/** 面板用的主题(与 panel 一起提供)。 */
|
|
@@ -42,6 +48,8 @@ export interface CommandUi {
|
|
|
42
48
|
home?: string;
|
|
43
49
|
/** 进程环境:给出时 /model 选择器按 fake-visibility 规则藏起测试供应商 fake。 */
|
|
44
50
|
env?: Readonly<Record<string, string | undefined>>;
|
|
51
|
+
/** [W5-U] 界面自己处理的第五波命令(agent-ui.ts);处理了返回 true。 */
|
|
52
|
+
extra?(name: string, args: string): Promise<boolean>;
|
|
45
53
|
}
|
|
46
54
|
/** 当前分支上的条目 id(树选择器标 ●)。 */
|
|
47
55
|
export declare function activeBranchIds(session: AgentSession): Set<string>;
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* - 交互模式自有命令:`/tree`(同一文件内换叶子到选中消息之前,文本回填编辑器,可改后重发形成新分支)、
|
|
8
8
|
* `/permissions`(当前模式、判定顺序与已加载规则);`/help` 追加这两条与按键说明。
|
|
9
9
|
* - `/session`、`/cache`(无参数)与 `/permissions` 在消息区画左竖条面板(panels.ts),不再拍成文本。
|
|
10
|
+
* - `/rewind`(无参数)打开回滚列表与确认面板(rewind-flow.ts);带参数走 commands-core,对话变了时
|
|
11
|
+
* 重画消息区并回填原消息。
|
|
10
12
|
* - 不是命令(含模板与 `/skill:`)返回 false,调用方把整行当提示发出。
|
|
11
13
|
*/
|
|
12
14
|
import { formatModelRef } from "../../ai/providers/channels.js";
|
|
@@ -27,8 +29,11 @@ export const ALL_COMMANDS = [...BUILTIN_COMMANDS, ...INTERACTIVE_COMMANDS];
|
|
|
27
29
|
export const KEY_HINTS = [
|
|
28
30
|
"Enter 发送(运行中 = 插话) Alt+Enter 排到本轮之后 Shift+Enter / Ctrl+J 换行",
|
|
29
31
|
"Esc 中断(排队消息回填编辑器) Alt+↑ 取回最后一条排队消息",
|
|
32
|
+
"空闲时 Esc Esc:输入框为空 = 回滚(/rewind),有字 = 清空(↑ 取回)",
|
|
30
33
|
"Shift+Tab 切换权限模式 Ctrl+L 模型 Ctrl+T 思考级别 Ctrl+O 展开工具输出与思考",
|
|
31
34
|
"审批:1–3 或 ↑↓ Enter 选择,y 允许 a 本会话允许同类 n / Esc 拒绝 v 完整输入",
|
|
35
|
+
"计划审批:1 批准 2 新上下文执行 3 继续修改 4 放弃并退出 Plan e 编辑计划 Esc 留在 Plan",
|
|
36
|
+
"Ctrl+V 粘贴剪贴板图片(插入 @路径) Ctrl+G 底部信息行两行 / 一行",
|
|
32
37
|
"Ctrl+C 清空输入(再按退出) Ctrl+D 空输入时退出 Tab 补全 @ 引用文件",
|
|
33
38
|
].join("\n");
|
|
34
39
|
function homeOf(ui) {
|
|
@@ -184,10 +189,16 @@ export async function runInteractiveCommand(line, ui) {
|
|
|
184
189
|
if (parsed === undefined)
|
|
185
190
|
return false;
|
|
186
191
|
try {
|
|
192
|
+
if (ui.extra !== undefined && (await ui.extra(parsed.name, parsed.args)))
|
|
193
|
+
return true;
|
|
187
194
|
if (parsed.name === "tree") {
|
|
188
195
|
await treeCommand(ui);
|
|
189
196
|
return true;
|
|
190
197
|
}
|
|
198
|
+
if (parsed.name === "rewind" && parsed.args === "" && ui.rewind !== undefined) {
|
|
199
|
+
await ui.rewind();
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
191
202
|
const theme = ui.theme?.();
|
|
192
203
|
if (parsed.name === "permissions") {
|
|
193
204
|
if (ui.panel !== undefined && theme !== undefined) {
|
|
@@ -225,12 +236,20 @@ export async function runInteractiveCommand(line, ui) {
|
|
|
225
236
|
await handlePick(result.what, ui);
|
|
226
237
|
break;
|
|
227
238
|
case "handled":
|
|
239
|
+
if (result.reload === true)
|
|
240
|
+
ui.reload();
|
|
228
241
|
if (parsed.name === "help") {
|
|
229
242
|
const extra = INTERACTIVE_COMMANDS.map((c) => `/${c.name} ${c.description}`);
|
|
230
243
|
ui.notice("info", [result.message ?? "", ...extra, "", KEY_HINTS].join("\n"));
|
|
231
244
|
}
|
|
232
245
|
else if (result.message !== undefined)
|
|
233
246
|
ui.notice("info", result.message);
|
|
247
|
+
if (result.draft !== undefined) {
|
|
248
|
+
if (ui.setDraft !== undefined)
|
|
249
|
+
ui.setDraft(result.draft);
|
|
250
|
+
else
|
|
251
|
+
ui.setEditorText(result.draft.text);
|
|
252
|
+
}
|
|
234
253
|
break;
|
|
235
254
|
}
|
|
236
255
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 空闲时的双击 Esc(rewind-plan §4):纯状态机,键位分派里用。[RW-C]
|
|
3
|
+
*
|
|
4
|
+
* - 输入框为空:第一次 `arm-rewind`(提示「再按 Esc 回滚」),间隔内第二次 `rewind`(打开回滚列表)。
|
|
5
|
+
* - 输入框有字:第一次 `arm-clear`(提示「再按 Esc 清空」),间隔内第二次 `clear`(清空并存进输入历史)。
|
|
6
|
+
* - 两次之间输入框状态变了(空 ↔ 有字)、超过间隔、或中间按了别的键(`reset()`)都重新计。
|
|
7
|
+
*/
|
|
8
|
+
/** 两次 Esc 的最大间隔。 */
|
|
9
|
+
export declare const DOUBLE_ESC_MS = 800;
|
|
10
|
+
/** 第一次 Esc 的提示停留时间。 */
|
|
11
|
+
export declare const DOUBLE_ESC_HINT_MS = 1000;
|
|
12
|
+
export type EscAction = "arm-rewind" | "rewind" | "arm-clear" | "clear";
|
|
13
|
+
export declare class DoubleEscape {
|
|
14
|
+
private readonly windowMs;
|
|
15
|
+
private armed;
|
|
16
|
+
constructor(windowMs?: number);
|
|
17
|
+
press(now: number, editorEmpty: boolean): EscAction;
|
|
18
|
+
reset(): void;
|
|
19
|
+
get isArmed(): boolean;
|
|
20
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 空闲时的双击 Esc(rewind-plan §4):纯状态机,键位分派里用。[RW-C]
|
|
3
|
+
*
|
|
4
|
+
* - 输入框为空:第一次 `arm-rewind`(提示「再按 Esc 回滚」),间隔内第二次 `rewind`(打开回滚列表)。
|
|
5
|
+
* - 输入框有字:第一次 `arm-clear`(提示「再按 Esc 清空」),间隔内第二次 `clear`(清空并存进输入历史)。
|
|
6
|
+
* - 两次之间输入框状态变了(空 ↔ 有字)、超过间隔、或中间按了别的键(`reset()`)都重新计。
|
|
7
|
+
*/
|
|
8
|
+
/** 两次 Esc 的最大间隔。 */
|
|
9
|
+
export const DOUBLE_ESC_MS = 800;
|
|
10
|
+
/** 第一次 Esc 的提示停留时间。 */
|
|
11
|
+
export const DOUBLE_ESC_HINT_MS = 1000;
|
|
12
|
+
export class DoubleEscape {
|
|
13
|
+
windowMs;
|
|
14
|
+
armed;
|
|
15
|
+
constructor(windowMs = DOUBLE_ESC_MS) {
|
|
16
|
+
this.windowMs = windowMs;
|
|
17
|
+
}
|
|
18
|
+
press(now, editorEmpty) {
|
|
19
|
+
const kind = editorEmpty ? "rewind" : "clear";
|
|
20
|
+
const armed = this.armed;
|
|
21
|
+
if (armed !== undefined && armed.kind === kind && now - armed.at <= this.windowMs) {
|
|
22
|
+
this.armed = undefined;
|
|
23
|
+
return kind;
|
|
24
|
+
}
|
|
25
|
+
this.armed = { kind, at: now };
|
|
26
|
+
return kind === "rewind" ? "arm-rewind" : "arm-clear";
|
|
27
|
+
}
|
|
28
|
+
reset() {
|
|
29
|
+
this.armed = undefined;
|
|
30
|
+
}
|
|
31
|
+
get isArmed() {
|
|
32
|
+
return this.armed !== undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交互界面对几类会话事件的友好提示(第五波其它批次转来的显示项)。[W5-A]
|
|
3
|
+
*
|
|
4
|
+
* - W5-I:`entry_appended` 里 `reason: "image_budget"` 的 `context_edit`(一次降级会连写多条,每条一个消息)
|
|
5
|
+
* 合并成一条「已省略 N 张早期图片以符合请求上限」,N 按占位文本数;
|
|
6
|
+
* - W5-H1:`compaction_end.error` 的「compaction did not shrink」换成中文说明(其余错误原样)。
|
|
7
|
+
*/
|
|
8
|
+
import type { SessionEvent } from "../../agent/types.js";
|
|
9
|
+
/** `compaction_end.error` 的显示文本。 */
|
|
10
|
+
export declare function compactionErrorText(error: string): string;
|
|
11
|
+
/** 同一轮同步写下的 image_budget 降级合并成一条提示。 */
|
|
12
|
+
export declare class ImageBudgetNotices {
|
|
13
|
+
private readonly notify;
|
|
14
|
+
private pending;
|
|
15
|
+
private scheduled;
|
|
16
|
+
constructor(notify: (text: string) => void);
|
|
17
|
+
onEvent(event: SessionEvent): void;
|
|
18
|
+
}
|
|
19
|
+
/** `agent_settled.warning` 为它时不再单独显示(`limit_reached` 事件已给出友好提示)。 */
|
|
20
|
+
export declare const LIMIT_WARNING = "limit_reached";
|
|
21
|
+
/** `limit_reached`:回合 / 费用到限(每次运行每类一次)。 */
|
|
22
|
+
export declare function limitReachedText(event: Extract<SessionEvent, {
|
|
23
|
+
type: "limit_reached";
|
|
24
|
+
}>): string;
|
|
25
|
+
/** `model_fallback`:主模型失败后改用回退模型重试一次。 */
|
|
26
|
+
export declare function modelFallbackText(event: Extract<SessionEvent, {
|
|
27
|
+
type: "model_fallback";
|
|
28
|
+
}>): string;
|
|
29
|
+
/** `background_job`:后台命令启动 / 退出 / 停止。 */
|
|
30
|
+
export declare function backgroundJobText(event: Extract<SessionEvent, {
|
|
31
|
+
type: "background_job";
|
|
32
|
+
}>): string;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交互界面对几类会话事件的友好提示(第五波其它批次转来的显示项)。[W5-A]
|
|
3
|
+
*
|
|
4
|
+
* - W5-I:`entry_appended` 里 `reason: "image_budget"` 的 `context_edit`(一次降级会连写多条,每条一个消息)
|
|
5
|
+
* 合并成一条「已省略 N 张早期图片以符合请求上限」,N 按占位文本数;
|
|
6
|
+
* - W5-H1:`compaction_end.error` 的「compaction did not shrink」换成中文说明(其余错误原样)。
|
|
7
|
+
*/
|
|
8
|
+
import { IMAGE_OMITTED_FOR_BUDGET, IMAGE_OMITTED_TOO_LARGE, } from "../../compaction/image-budget.js";
|
|
9
|
+
/** `compaction_end.error` 的显示文本。 */
|
|
10
|
+
export function compactionErrorText(error) {
|
|
11
|
+
if (/compaction did not shrink/i.test(error)) {
|
|
12
|
+
return "压缩后上下文没有变小,已保留原对话(不写摘要)";
|
|
13
|
+
}
|
|
14
|
+
return error;
|
|
15
|
+
}
|
|
16
|
+
function count(text, needle) {
|
|
17
|
+
let n = 0;
|
|
18
|
+
for (let at = text.indexOf(needle); at !== -1; at = text.indexOf(needle, at + needle.length))
|
|
19
|
+
n++;
|
|
20
|
+
return n;
|
|
21
|
+
}
|
|
22
|
+
/** 同一轮同步写下的 image_budget 降级合并成一条提示。 */
|
|
23
|
+
export class ImageBudgetNotices {
|
|
24
|
+
notify;
|
|
25
|
+
pending = 0;
|
|
26
|
+
scheduled = false;
|
|
27
|
+
constructor(notify) {
|
|
28
|
+
this.notify = notify;
|
|
29
|
+
}
|
|
30
|
+
onEvent(event) {
|
|
31
|
+
if (event.type !== "entry_appended")
|
|
32
|
+
return;
|
|
33
|
+
const entry = event.entry;
|
|
34
|
+
if (entry.type !== "context_edit" || entry.reason !== "image_budget")
|
|
35
|
+
return;
|
|
36
|
+
const text = entry.replacement ?? "";
|
|
37
|
+
const images = count(text, IMAGE_OMITTED_FOR_BUDGET) + count(text, IMAGE_OMITTED_TOO_LARGE);
|
|
38
|
+
this.pending += Math.max(1, images);
|
|
39
|
+
if (this.scheduled)
|
|
40
|
+
return;
|
|
41
|
+
this.scheduled = true;
|
|
42
|
+
queueMicrotask(() => {
|
|
43
|
+
const n = this.pending;
|
|
44
|
+
this.pending = 0;
|
|
45
|
+
this.scheduled = false;
|
|
46
|
+
this.notify(`已省略 ${n} 张早期图片以符合请求上限`);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// [W5-U] 第五波 harness 事件(W5-H2)的提示文本:交互界面与 line 模式共用
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
/** `agent_settled.warning` 为它时不再单独显示(`limit_reached` 事件已给出友好提示)。 */
|
|
54
|
+
export const LIMIT_WARNING = "limit_reached";
|
|
55
|
+
/** `limit_reached`:回合 / 费用到限(每次运行每类一次)。 */
|
|
56
|
+
export function limitReachedText(event) {
|
|
57
|
+
if (event.kind === "turns")
|
|
58
|
+
return `已到回合上限(${event.limit} 回合),本次运行停止;发新消息继续(--max-turns / limits.maxTurns)`;
|
|
59
|
+
const spent = `$${event.value.toFixed(2)}`;
|
|
60
|
+
return `已到费用上限 $${event.limit.toFixed(2)}(本次运行已用 ${spent}),本次运行停止;发新消息继续(--max-cost / limits.maxCostUsd)`;
|
|
61
|
+
}
|
|
62
|
+
/** `model_fallback`:主模型失败后改用回退模型重试一次。 */
|
|
63
|
+
export function modelFallbackText(event) {
|
|
64
|
+
const ref = (m) => `${m.provider}/${m.id}`;
|
|
65
|
+
return `${ref(event.from)} 不可用(${event.reason}),本次请求改用 ${ref(event.to)},回复后切回`;
|
|
66
|
+
}
|
|
67
|
+
/** `background_job`:后台命令启动 / 退出 / 停止。 */
|
|
68
|
+
export function backgroundJobText(event) {
|
|
69
|
+
const command = event.command.replace(/\s+/g, " ").trim();
|
|
70
|
+
const short = command.length > 60 ? `${command.slice(0, 59)}…` : command;
|
|
71
|
+
switch (event.phase) {
|
|
72
|
+
case "started":
|
|
73
|
+
return `后台命令 ${event.jobId} 已启动:${short}`;
|
|
74
|
+
case "exited":
|
|
75
|
+
return `后台命令 ${event.jobId} 已退出(码 ${event.exitCode ?? "?"}):${short}`;
|
|
76
|
+
case "stopped":
|
|
77
|
+
return `后台命令 ${event.jobId} 已停止:${short}`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 外部编辑器(计划审批框的「编辑计划」与「继续修改」):`$VISUAL` → `$EDITOR` → `vi`(Windows `notepad`)。
|
|
3
|
+
* [W5-U] 编辑期间 TUI 挂起(交还终端),回来后整屏重画。临时文件在系统临时目录,读完即删。
|
|
4
|
+
*/
|
|
5
|
+
export interface ExternalEditorDeps {
|
|
6
|
+
env: Readonly<Record<string, string | undefined>>;
|
|
7
|
+
/** 挂起 / 恢复界面。 */
|
|
8
|
+
suspend(): void;
|
|
9
|
+
resume(): void;
|
|
10
|
+
platform?: NodeJS.Platform;
|
|
11
|
+
/** 测试注入:代替真实启动编辑器(参数:命令行、文件路径),返回退出码。 */
|
|
12
|
+
run?(command: string, file: string): number | null;
|
|
13
|
+
}
|
|
14
|
+
export declare function editorCommand(env: Readonly<Record<string, string | undefined>>, platform?: NodeJS.Platform): string;
|
|
15
|
+
/** 在外部编辑器里改 `text`;编辑器非零退出或读不回来返回 undefined。 */
|
|
16
|
+
export declare function editExternally(text: string, name: string, deps: ExternalEditorDeps): Promise<string | undefined>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 外部编辑器(计划审批框的「编辑计划」与「继续修改」):`$VISUAL` → `$EDITOR` → `vi`(Windows `notepad`)。
|
|
3
|
+
* [W5-U] 编辑期间 TUI 挂起(交还终端),回来后整屏重画。临时文件在系统临时目录,读完即删。
|
|
4
|
+
*/
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
export function editorCommand(env, platform = process.platform) {
|
|
10
|
+
const configured = env["VISUAL"]?.trim() || env["EDITOR"]?.trim();
|
|
11
|
+
if (configured !== undefined && configured !== "")
|
|
12
|
+
return configured;
|
|
13
|
+
return platform === "win32" ? "notepad" : "vi";
|
|
14
|
+
}
|
|
15
|
+
function runEditor(command, file) {
|
|
16
|
+
// 编辑器变量常带参数(`code --wait`),交给 shell 拆;路径加引号
|
|
17
|
+
const result = spawnSync(`${command} "${file}"`, { stdio: "inherit", shell: true });
|
|
18
|
+
return result.status;
|
|
19
|
+
}
|
|
20
|
+
/** 在外部编辑器里改 `text`;编辑器非零退出或读不回来返回 undefined。 */
|
|
21
|
+
export async function editExternally(text, name, deps) {
|
|
22
|
+
const dir = mkdtempSync(join(tmpdir(), "ama-edit-"));
|
|
23
|
+
const file = join(dir, name);
|
|
24
|
+
writeFileSync(file, text);
|
|
25
|
+
deps.suspend();
|
|
26
|
+
try {
|
|
27
|
+
const code = (deps.run ?? runEditor)(editorCommand(deps.env, deps.platform), file);
|
|
28
|
+
if (code !== 0)
|
|
29
|
+
return undefined;
|
|
30
|
+
return readFileSync(file, "utf8");
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
deps.resume();
|
|
37
|
+
rmSync(dir, { recursive: true, force: true });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -11,15 +11,23 @@
|
|
|
11
11
|
* - 晚绑定:`runtime.approvals.setUiBroker`(审批对话框)与 `runtime.notifier.set`(宿主通知进消息区),
|
|
12
12
|
* 退出时撤下。
|
|
13
13
|
* - 键位:Enter 发送(运行中 = steer),其余应用级键位见 `key-dispatch.ts`。
|
|
14
|
+
* - 回滚(RW-C):`/rewind` 与空闲双击 Esc 走 rewind-flow.ts;回填的原消息图片暂存,随下一条消息发送。
|
|
15
|
+
* - 底部(W5-A,status-area.ts):`ui.statusLine` full 时状态栏上方多一行速率行;Ctrl+G / `/statusline`
|
|
16
|
+
* 切换(只影响本会话)。
|
|
17
|
+
* - 第五波(W5-U,agent-ui.ts):计划审批框、子 Agent 折叠视图、`/tasks` `/agents` `/paste` 与 Ctrl+V、审批来源
|
|
18
|
+
* 标注与外部 Agent 首次运行的合并确认(approval-merge.ts)、harness 提示。
|
|
14
19
|
* - 启动头按 `ui.quietStartup`(startup-header.ts):normal 框 + 模型 / 目录 / 模式 / 资源清单(窄屏或
|
|
15
20
|
* `ui.compact` 去框),header 一行,silent 不输出。
|
|
16
21
|
*/
|
|
17
22
|
import type { AgentSession } from "../../agent/types.js";
|
|
18
23
|
import type { ModeContext } from "../../cli/deps.js";
|
|
19
24
|
import type { Runtime } from "../../cli/runtime.js";
|
|
25
|
+
import type { StatusLineMode } from "../../config/types.js";
|
|
26
|
+
import type { ClipboardDeps } from "../../tools/clipboard-image.js";
|
|
20
27
|
import { Editor, Keybindings, TUI, type Terminal, type Theme } from "../../tui.js";
|
|
21
28
|
import { MessageView } from "./message-view.js";
|
|
22
|
-
import {
|
|
29
|
+
import { StatusArea } from "./status-area.js";
|
|
30
|
+
import type { StatusBar } from "./status-bar.js";
|
|
23
31
|
import { ToolTracker } from "./tool-view.js";
|
|
24
32
|
export interface InteractiveModeOptions {
|
|
25
33
|
/** 缺省 `ProcessTerminal`(测试注入 MemoryTerminal)。 */
|
|
@@ -32,8 +40,12 @@ export interface InteractiveModeOptions {
|
|
|
32
40
|
spinnerIntervalMs?: number;
|
|
33
41
|
/** 输入历史文件;false 不读写(缺省 `<dataDir>/history`)。 */
|
|
34
42
|
historyFile?: string | false;
|
|
43
|
+
/** 底部布局(缺省按 `ui.statusLine`;测试固定)。 */
|
|
44
|
+
statusLine?: StatusLineMode;
|
|
35
45
|
/** 界面就绪后回调(测试驱动用)。 */
|
|
36
46
|
onReady?(handle: InteractiveHandle): void;
|
|
47
|
+
/** 剪贴板读取的注入(测试;缺省调系统命令)。 */
|
|
48
|
+
clipboard?: ClipboardDeps;
|
|
37
49
|
}
|
|
38
50
|
export interface InteractiveHandle {
|
|
39
51
|
readonly tui: TUI;
|
|
@@ -41,6 +53,7 @@ export interface InteractiveHandle {
|
|
|
41
53
|
readonly view: MessageView;
|
|
42
54
|
readonly tools: ToolTracker;
|
|
43
55
|
readonly status: StatusBar;
|
|
56
|
+
readonly area: StatusArea;
|
|
44
57
|
session(): AgentSession;
|
|
45
58
|
exit(code: number): void;
|
|
46
59
|
}
|