@armadra/agent 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +257 -0
- package/README.md +263 -95
- package/THIRD_PARTY_NOTICES.md +34 -0
- package/dist/acp.d.ts +18 -0
- package/dist/acp.js +19 -0
- package/dist/agent/limits.d.ts +38 -0
- package/dist/agent/limits.js +127 -0
- package/dist/agent/loop-guard.d.ts +38 -0
- package/dist/agent/loop-guard.js +95 -0
- package/dist/agent/loop.d.ts +4 -0
- package/dist/agent/loop.js +7 -0
- package/dist/agent/prompt-rules.d.ts +12 -0
- package/dist/agent/prompt-rules.js +18 -0
- package/dist/agent/reminders.d.ts +59 -0
- package/dist/agent/reminders.js +327 -0
- package/dist/agent/retry.d.ts +1 -1
- package/dist/agent/retry.js +2 -1
- package/dist/agent/session-cache.d.ts +5 -0
- package/dist/agent/session-cache.js +18 -2
- package/dist/agent/session-classifier.d.ts +18 -0
- package/dist/agent/session-classifier.js +105 -0
- package/dist/agent/session-compaction.d.ts +35 -6
- package/dist/agent/session-compaction.js +157 -31
- package/dist/agent/session-core.d.ts +40 -1
- package/dist/agent/session-extensions.d.ts +61 -0
- package/dist/agent/session-extensions.js +129 -0
- package/dist/agent/session-images.d.ts +23 -0
- package/dist/agent/session-images.js +97 -0
- package/dist/agent/session-plan.d.ts +21 -0
- package/dist/agent/session-plan.js +524 -0
- package/dist/agent/session-rewind.d.ts +81 -0
- package/dist/agent/session-rewind.js +354 -0
- package/dist/agent/session-run.d.ts +28 -1
- package/dist/agent/session-run.js +157 -6
- package/dist/agent/session-settings.d.ts +49 -0
- package/dist/agent/session-settings.js +95 -0
- package/dist/agent/session-subagent.d.ts +36 -24
- package/dist/agent/session-subagent.js +259 -129
- package/dist/agent/session-sync.d.ts +10 -3
- package/dist/agent/session-sync.js +37 -8
- package/dist/agent/session-telemetry.d.ts +39 -0
- package/dist/agent/session-telemetry.js +231 -0
- package/dist/agent/session-tools.js +63 -3
- package/dist/agent/session.d.ts +33 -29
- package/dist/agent/session.js +91 -126
- package/dist/agent/subagent-registry.d.ts +91 -0
- package/dist/agent/subagent-registry.js +494 -0
- package/dist/agent/system-prompt.d.ts +6 -3
- package/dist/agent/system-prompt.js +7 -2
- package/dist/agent/tool-runner.d.ts +8 -1
- package/dist/agent/tool-runner.js +72 -6
- package/dist/agent/types-w5.d.ts +192 -0
- package/dist/agent/types-w5.js +10 -0
- package/dist/agent/types.d.ts +55 -4
- package/dist/agent/types.js +2 -0
- package/dist/agent/worktree.d.ts +36 -0
- package/dist/agent/worktree.js +86 -0
- package/dist/agents/builtin.d.ts +14 -0
- package/dist/agents/builtin.js +39 -0
- package/dist/agents/catalog.d.ts +43 -0
- package/dist/agents/catalog.js +82 -0
- package/dist/agents/discover.d.ts +35 -0
- package/dist/agents/discover.js +83 -0
- package/dist/agents/external.d.ts +82 -0
- package/dist/agents/external.js +326 -0
- package/dist/agents/parse.d.ts +18 -0
- package/dist/agents/parse.js +116 -0
- package/dist/agents/result.d.ts +32 -0
- package/dist/agents/result.js +67 -0
- package/dist/agents/task-control.d.ts +17 -0
- package/dist/agents/task-control.js +17 -0
- package/dist/agents/task-record.d.ts +78 -0
- package/dist/agents/task-record.js +141 -0
- package/dist/agents/types.d.ts +46 -0
- package/dist/agents/types.js +8 -0
- package/dist/ai/apis/anthropic-compat.d.ts +36 -0
- package/dist/ai/apis/anthropic-compat.js +92 -0
- package/dist/ai/apis/anthropic-messages.js +3 -2
- package/dist/ai/apis/anthropic-request.d.ts +7 -6
- package/dist/ai/apis/anthropic-request.js +10 -28
- package/dist/ai/apis/cache-params.d.ts +11 -2
- package/dist/ai/apis/cache-params.js +25 -6
- package/dist/ai/apis/google-generative-ai.js +3 -2
- package/dist/ai/apis/openai-compat.d.ts +4 -1
- package/dist/ai/apis/openai-compat.js +8 -1
- package/dist/ai/apis/openai-completions.js +3 -2
- package/dist/ai/apis/openai-responses.js +3 -2
- package/dist/ai/http.d.ts +28 -6
- package/dist/ai/http.js +41 -8
- package/dist/ai/image-limits.d.ts +45 -0
- package/dist/ai/image-limits.js +68 -0
- package/dist/ai/providers/builtin.d.ts +18 -6
- package/dist/ai/providers/builtin.js +135 -6
- package/dist/ai/providers/catalog-data.js +17 -13
- package/dist/ai/providers/catalog.d.ts +60 -7
- package/dist/ai/providers/catalog.js +197 -38
- package/dist/ai/providers/channels.d.ts +33 -3
- package/dist/ai/providers/channels.js +108 -7
- package/dist/ai/providers/enrich.d.ts +6 -3
- package/dist/ai/providers/enrich.js +19 -4
- package/dist/ai/providers/models-dev-cache.d.ts +28 -24
- package/dist/ai/providers/models-dev-cache.js +92 -78
- package/dist/ai/providers/models-dev-data.d.ts +7 -0
- package/dist/ai/providers/models-dev-data.js +32 -0
- package/dist/ai/providers/models-dev-snapshot.d.ts +50 -0
- package/dist/ai/providers/models-dev-snapshot.js +137 -0
- package/dist/ai/providers/models-dev.d.ts +51 -10
- package/dist/ai/providers/models-dev.js +132 -39
- package/dist/ai/providers/registry.d.ts +28 -11
- package/dist/ai/providers/registry.js +112 -65
- package/dist/ai/providers/suggest.d.ts +18 -0
- package/dist/ai/providers/suggest.js +72 -0
- package/dist/ai/sse.d.ts +6 -2
- package/dist/ai/sse.js +22 -2
- package/dist/ai/types.d.ts +37 -4
- package/dist/ai/types.js +5 -0
- package/dist/bundle/ama.cjs +41979 -21147
- package/dist/checkpoints/backend.d.ts +61 -0
- package/dist/checkpoints/backend.js +135 -0
- package/dist/checkpoints/blobs.d.ts +60 -0
- package/dist/checkpoints/blobs.js +203 -0
- package/dist/checkpoints/gc.d.ts +47 -0
- package/dist/checkpoints/gc.js +144 -0
- package/dist/checkpoints/git-head.d.ts +15 -0
- package/dist/checkpoints/git-head.js +89 -0
- package/dist/checkpoints/index.d.ts +17 -0
- package/dist/checkpoints/index.js +17 -0
- package/dist/checkpoints/replay.d.ts +48 -0
- package/dist/checkpoints/replay.js +154 -0
- package/dist/checkpoints/restore.d.ts +86 -0
- package/dist/checkpoints/restore.js +263 -0
- package/dist/checkpoints/settings.d.ts +14 -0
- package/dist/checkpoints/settings.js +23 -0
- package/dist/checkpoints/shadow-git.d.ts +108 -0
- package/dist/checkpoints/shadow-git.js +491 -0
- package/dist/checkpoints/shadow-restore.d.ts +25 -0
- package/dist/checkpoints/shadow-restore.js +128 -0
- package/dist/checkpoints/tracker.d.ts +64 -0
- package/dist/checkpoints/tracker.js +192 -0
- package/dist/checkpoints/types.d.ts +99 -0
- package/dist/checkpoints/types.js +12 -0
- package/dist/cli/args.d.ts +26 -7
- package/dist/cli/args.js +75 -82
- package/dist/cli/bootstrap.js +40 -4
- package/dist/cli/codemode-notice.d.ts +21 -0
- package/dist/cli/codemode-notice.js +56 -0
- package/dist/cli/compose-agents.d.ts +27 -0
- package/dist/cli/compose-agents.js +111 -0
- package/dist/cli/compose-extensions.d.ts +29 -0
- package/dist/cli/compose-extensions.js +44 -0
- package/dist/cli/compose-session.d.ts +8 -0
- package/dist/cli/compose-session.js +76 -2
- package/dist/cli/compose-store.d.ts +1 -1
- package/dist/cli/compose-store.js +3 -1
- package/dist/cli/compose.d.ts +17 -4
- package/dist/cli/compose.js +60 -14
- package/dist/cli/default-model.d.ts +38 -1
- package/dist/cli/default-model.js +96 -9
- package/dist/cli/deps.d.ts +42 -0
- package/dist/cli/exit-codes.d.ts +12 -0
- package/dist/cli/exit-codes.js +15 -0
- package/dist/cli/fake-visibility.d.ts +13 -0
- package/dist/cli/fake-visibility.js +26 -0
- package/dist/cli/from-prompt.d.ts +18 -0
- package/dist/cli/from-prompt.js +49 -0
- package/dist/cli/help-text.d.ts +4 -0
- package/dist/cli/help-text.js +102 -0
- package/dist/cli/main.d.ts +9 -2
- package/dist/cli/main.js +77 -3
- package/dist/cli/proxy.d.ts +51 -0
- package/dist/cli/proxy.js +135 -0
- package/dist/cli/startup-screen.d.ts +29 -0
- package/dist/cli/startup-screen.js +51 -2
- package/dist/cli/startup-steps.d.ts +1 -1
- package/dist/cli/startup-steps.js +21 -13
- package/dist/cli/subcommands/config.d.ts +22 -3
- package/dist/cli/subcommands/config.js +119 -21
- package/dist/cli/subcommands/context.js +4 -1
- package/dist/cli/subcommands/doctor.js +33 -1
- package/dist/cli/subcommands/init.js +2 -1
- package/dist/cli/subcommands/models-discover.d.ts +15 -9
- package/dist/cli/subcommands/models-discover.js +58 -52
- package/dist/cli/subcommands/models.d.ts +2 -0
- package/dist/cli/subcommands/models.js +33 -14
- package/dist/cli/subcommands/probe-runner.d.ts +96 -0
- package/dist/cli/subcommands/probe-runner.js +264 -0
- package/dist/cli/subcommands/providers-probe.d.ts +34 -0
- package/dist/cli/subcommands/providers-probe.js +87 -0
- package/dist/cli/subcommands/providers.d.ts +3 -2
- package/dist/cli/subcommands/providers.js +53 -51
- package/dist/cli/subcommands/sessions-export.d.ts +10 -0
- package/dist/cli/subcommands/sessions-export.js +59 -0
- package/dist/cli/subcommands/sessions-search.d.ts +13 -0
- package/dist/cli/subcommands/sessions-search.js +103 -0
- package/dist/cli/subcommands/sessions.d.ts +6 -3
- package/dist/cli/subcommands/sessions.js +58 -3
- package/dist/cli/subcommands/stats.d.ts +17 -0
- package/dist/cli/subcommands/stats.js +198 -0
- package/dist/cli/system-prompt-arg.d.ts +11 -0
- package/dist/cli/system-prompt-arg.js +34 -0
- package/dist/codemode/capability.d.ts +24 -7
- package/dist/codemode/capability.js +38 -10
- package/dist/codemode/host-side.d.ts +14 -0
- package/dist/codemode/host-side.js +24 -1
- package/dist/codemode/modes.d.ts +4 -11
- package/dist/codemode/modes.js +5 -27
- package/dist/codemode/tool.d.ts +18 -14
- package/dist/codemode/tool.js +76 -31
- package/dist/compaction/breaker.d.ts +25 -9
- package/dist/compaction/breaker.js +47 -17
- package/dist/compaction/estimate.d.ts +11 -3
- package/dist/compaction/estimate.js +64 -22
- package/dist/compaction/image-budget.d.ts +45 -0
- package/dist/compaction/image-budget.js +115 -0
- package/dist/compaction/post-compact.d.ts +38 -0
- package/dist/compaction/post-compact.js +152 -0
- package/dist/compaction/protect.d.ts +27 -0
- package/dist/compaction/protect.js +56 -0
- package/dist/compaction/prune-tier.d.ts +58 -12
- package/dist/compaction/prune-tier.js +120 -54
- package/dist/compaction/summarize-tier.d.ts +23 -4
- package/dist/compaction/summarize-tier.js +100 -29
- package/dist/config/checker.d.ts +28 -0
- package/dist/config/checker.js +97 -0
- package/dist/config/init.d.ts +6 -2
- package/dist/config/init.js +12 -5
- package/dist/config/json-schema.d.ts +1 -0
- package/dist/config/json-schema.js +98 -4
- package/dist/config/key-docs.d.ts +22 -0
- package/dist/config/key-docs.js +174 -0
- package/dist/config/merge.d.ts +12 -9
- package/dist/config/merge.js +102 -13
- package/dist/config/profile.d.ts +2 -0
- package/dist/config/profile.js +2 -0
- package/dist/config/schema-w5.d.ts +18 -0
- package/dist/config/schema-w5.js +109 -0
- package/dist/config/schema.d.ts +5 -9
- package/dist/config/schema.js +91 -118
- package/dist/config/types-w5.d.ts +118 -0
- package/dist/config/types-w5.js +20 -0
- package/dist/config/types.d.ts +84 -7
- package/dist/config/types.js +29 -1
- package/dist/drivers/acp/client.d.ts +57 -0
- package/dist/drivers/acp/client.js +160 -0
- package/dist/drivers/acp/driver.d.ts +31 -0
- package/dist/drivers/acp/driver.js +274 -0
- package/dist/drivers/acp/testing/fake-agent-main.d.ts +5 -0
- package/dist/drivers/acp/testing/fake-agent-main.js +7 -0
- package/dist/drivers/acp/testing/fake-agent.d.ts +27 -0
- package/dist/drivers/acp/testing/fake-agent.js +211 -0
- package/dist/drivers/acp/types.d.ts +285 -0
- package/dist/drivers/acp/types.js +36 -0
- package/dist/drivers/agents.d.ts +58 -0
- package/dist/drivers/agents.js +142 -0
- package/dist/drivers/base.d.ts +35 -0
- package/dist/drivers/base.js +59 -0
- package/dist/drivers/catalog.d.ts +46 -0
- package/dist/drivers/catalog.js +167 -0
- package/dist/drivers/env.d.ts +20 -0
- package/dist/drivers/env.js +46 -0
- package/dist/drivers/host-runners.d.ts +18 -0
- package/dist/drivers/host-runners.js +45 -0
- package/dist/drivers/jsonrpc.d.ts +58 -0
- package/dist/drivers/jsonrpc.js +180 -0
- package/dist/drivers/native/claude-normalize.d.ts +46 -0
- package/dist/drivers/native/claude-normalize.js +106 -0
- package/dist/drivers/native/claude-stream.d.ts +29 -0
- package/dist/drivers/native/claude-stream.js +456 -0
- package/dist/drivers/native/codex-app-server.d.ts +26 -0
- package/dist/drivers/native/codex-app-server.js +407 -0
- package/dist/drivers/native/codex-normalize.d.ts +38 -0
- package/dist/drivers/native/codex-normalize.js +124 -0
- package/dist/drivers/native/oneshot.d.ts +28 -0
- package/dist/drivers/native/oneshot.js +312 -0
- package/dist/drivers/permissions.d.ts +40 -0
- package/dist/drivers/permissions.js +92 -0
- package/dist/drivers/pids.d.ts +32 -0
- package/dist/drivers/pids.js +93 -0
- package/dist/drivers/pool.d.ts +28 -0
- package/dist/drivers/pool.js +96 -0
- package/dist/drivers/probe.d.ts +47 -0
- package/dist/drivers/probe.js +172 -0
- package/dist/drivers/process.d.ts +48 -0
- package/dist/drivers/process.js +100 -0
- package/dist/drivers/runner.d.ts +61 -0
- package/dist/drivers/runner.js +388 -0
- package/dist/drivers/store.d.ts +49 -0
- package/dist/drivers/store.js +91 -0
- package/dist/drivers/turn.d.ts +41 -0
- package/dist/drivers/turn.js +99 -0
- package/dist/drivers/types.d.ts +122 -0
- package/dist/drivers/types.js +11 -0
- package/dist/git/info.d.ts +75 -0
- package/dist/git/info.js +191 -0
- package/dist/hooks/protocol.js +6 -1
- package/dist/hooks/types.d.ts +10 -1
- package/dist/hooks/types.js +2 -0
- package/dist/host/api-impl.d.ts +7 -0
- package/dist/host/api-impl.js +15 -0
- package/dist/host/types.d.ts +24 -2
- package/dist/host/types.js +4 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/modes/acp/acp-events.d.ts +46 -0
- package/dist/modes/acp/acp-events.js +233 -0
- package/dist/modes/acp/acp-mode.d.ts +17 -0
- package/dist/modes/acp/acp-mode.js +47 -0
- package/dist/modes/acp/acp-server.d.ts +79 -0
- package/dist/modes/acp/acp-server.js +315 -0
- package/dist/modes/commands-core.d.ts +7 -1
- package/dist/modes/commands-core.js +61 -5
- package/dist/modes/image-input.d.ts +12 -4
- package/dist/modes/image-input.js +22 -5
- package/dist/modes/interactive/agent-panels.d.ts +14 -0
- package/dist/modes/interactive/agent-panels.js +103 -0
- package/dist/modes/interactive/agent-ui.d.ts +73 -0
- package/dist/modes/interactive/agent-ui.js +234 -0
- package/dist/modes/interactive/approval-dialog.d.ts +40 -7
- package/dist/modes/interactive/approval-dialog.js +192 -35
- package/dist/modes/interactive/approval-merge.d.ts +41 -0
- package/dist/modes/interactive/approval-merge.js +89 -0
- package/dist/modes/interactive/clipboard-paste.d.ts +18 -0
- package/dist/modes/interactive/clipboard-paste.js +28 -0
- package/dist/modes/interactive/commands.d.ts +20 -3
- package/dist/modes/interactive/commands.js +75 -16
- package/dist/modes/interactive/double-esc.d.ts +20 -0
- package/dist/modes/interactive/double-esc.js +34 -0
- package/dist/modes/interactive/event-notices.d.ts +32 -0
- package/dist/modes/interactive/event-notices.js +79 -0
- package/dist/modes/interactive/external-editor.d.ts +16 -0
- package/dist/modes/interactive/external-editor.js +39 -0
- package/dist/modes/interactive/interactive-mode.d.ts +16 -2
- package/dist/modes/interactive/interactive-mode.js +184 -202
- package/dist/modes/interactive/key-dispatch.d.ts +18 -2
- package/dist/modes/interactive/key-dispatch.js +53 -6
- package/dist/modes/interactive/line/line-mode.d.ts +3 -1
- package/dist/modes/interactive/line/line-mode.js +28 -9
- package/dist/modes/interactive/line/line-render.d.ts +6 -1
- package/dist/modes/interactive/line/line-render.js +66 -8
- package/dist/modes/interactive/message-view.d.ts +49 -10
- package/dist/modes/interactive/message-view.js +262 -46
- package/dist/modes/interactive/panels.d.ts +35 -0
- package/dist/modes/interactive/panels.js +157 -0
- package/dist/modes/interactive/pickers.d.ts +23 -2
- package/dist/modes/interactive/pickers.js +48 -15
- package/dist/modes/interactive/plan-command.d.ts +40 -0
- package/dist/modes/interactive/plan-command.js +129 -0
- package/dist/modes/interactive/plan-dialog.d.ts +98 -0
- package/dist/modes/interactive/plan-dialog.js +290 -0
- package/dist/modes/interactive/plan-flow.d.ts +34 -0
- package/dist/modes/interactive/plan-flow.js +98 -0
- package/dist/modes/interactive/rewind-command.d.ts +31 -0
- package/dist/modes/interactive/rewind-command.js +106 -0
- package/dist/modes/interactive/rewind-flow.d.ts +37 -0
- package/dist/modes/interactive/rewind-flow.js +151 -0
- package/dist/modes/interactive/rewind-list.d.ts +36 -0
- package/dist/modes/interactive/rewind-list.js +123 -0
- package/dist/modes/interactive/rewind-panel.d.ts +77 -0
- package/dist/modes/interactive/rewind-panel.js +309 -0
- package/dist/modes/interactive/rewind-text.d.ts +40 -0
- package/dist/modes/interactive/rewind-text.js +139 -0
- package/dist/modes/interactive/run-indicator.d.ts +51 -0
- package/dist/modes/interactive/run-indicator.js +189 -0
- package/dist/modes/interactive/session-events.d.ts +24 -0
- package/dist/modes/interactive/session-events.js +96 -0
- package/dist/modes/interactive/startup-header.d.ts +40 -0
- package/dist/modes/interactive/startup-header.js +169 -0
- package/dist/modes/interactive/status-area.d.ts +73 -0
- package/dist/modes/interactive/status-area.js +190 -0
- package/dist/modes/interactive/status-bar.d.ts +107 -16
- package/dist/modes/interactive/status-bar.js +306 -81
- package/dist/modes/interactive/status-line.d.ts +33 -0
- package/dist/modes/interactive/status-line.js +113 -0
- package/dist/modes/interactive/subagent-view.d.ts +56 -0
- package/dist/modes/interactive/subagent-view.js +154 -0
- package/dist/modes/interactive/tasks-report.d.ts +27 -0
- package/dist/modes/interactive/tasks-report.js +114 -0
- package/dist/modes/interactive/tool-summary.d.ts +46 -0
- package/dist/modes/interactive/tool-summary.js +218 -0
- package/dist/modes/interactive/tool-view.d.ts +58 -15
- package/dist/modes/interactive/tool-view.js +233 -145
- package/dist/modes/print/print-mode.d.ts +40 -4
- package/dist/modes/print/print-mode.js +161 -8
- package/dist/modes/rpc/commands.d.ts +9 -0
- package/dist/modes/rpc/commands.js +49 -0
- package/dist/modes/rpc/rpc-mode.js +7 -1
- package/dist/modes/session-report.d.ts +11 -0
- package/dist/modes/session-report.js +48 -1
- package/dist/permissions/auto-safe.d.ts +65 -0
- package/dist/permissions/auto-safe.js +547 -0
- package/dist/permissions/classifier.d.ts +68 -0
- package/dist/permissions/classifier.js +186 -0
- package/dist/permissions/dangerous.d.ts +5 -0
- package/dist/permissions/dangerous.js +1 -1
- package/dist/permissions/modes.d.ts +30 -0
- package/dist/permissions/modes.js +78 -0
- package/dist/permissions/pipeline.d.ts +72 -6
- package/dist/permissions/pipeline.js +306 -11
- package/dist/permissions/protected.d.ts +19 -0
- package/dist/permissions/protected.js +74 -0
- package/dist/permissions/readonly-bash.d.ts +30 -0
- package/dist/permissions/readonly-bash.js +118 -0
- package/dist/permissions/rules.js +3 -0
- package/dist/permissions/types.d.ts +92 -3
- package/dist/permissions/types.js +3 -0
- package/dist/plan/compose.d.ts +9 -0
- package/dist/plan/compose.js +19 -0
- package/dist/plan/controller.d.ts +71 -0
- package/dist/plan/controller.js +27 -0
- package/dist/plan/done-markers.d.ts +17 -0
- package/dist/plan/done-markers.js +51 -0
- package/dist/plan/extract.d.ts +29 -0
- package/dist/plan/extract.js +160 -0
- package/dist/plan/prompts.d.ts +36 -0
- package/dist/plan/prompts.js +89 -0
- package/dist/plan/store.d.ts +37 -0
- package/dist/plan/store.js +90 -0
- package/dist/rpc.d.ts +58 -2
- package/dist/rpc.js +7 -0
- package/dist/sandbox/bash.d.ts +74 -0
- package/dist/sandbox/bash.js +126 -0
- package/dist/sandbox/detect.d.ts +48 -0
- package/dist/sandbox/detect.js +149 -0
- package/dist/sandbox/index.d.ts +5 -0
- package/dist/sandbox/index.js +5 -0
- package/dist/sandbox/profile.d.ts +33 -0
- package/dist/sandbox/profile.js +76 -0
- package/dist/sandbox/wrap.d.ts +29 -0
- package/dist/sandbox/wrap.js +117 -0
- package/dist/sdk.d.ts +42 -5
- package/dist/sdk.js +34 -4
- package/dist/session/export.d.ts +32 -0
- package/dist/session/export.js +187 -0
- package/dist/session/redact.d.ts +15 -0
- package/dist/session/redact.js +55 -0
- package/dist/session/reuse.d.ts +33 -0
- package/dist/session/reuse.js +86 -0
- package/dist/session/scan.d.ts +34 -0
- package/dist/session/scan.js +140 -0
- package/dist/session/search.d.ts +52 -0
- package/dist/session/search.js +211 -0
- package/dist/session/stats-aggregate.d.ts +63 -0
- package/dist/session/stats-aggregate.js +163 -0
- package/dist/session/stats-index.d.ts +26 -0
- package/dist/session/stats-index.js +91 -0
- package/dist/session/stats-scan.d.ts +54 -0
- package/dist/session/stats-scan.js +236 -0
- package/dist/session/types.d.ts +3 -1
- package/dist/session/types.js +1 -0
- package/dist/skills/builtin.d.ts +31 -0
- package/dist/skills/builtin.js +109 -0
- package/dist/skills/discover.d.ts +2 -1
- package/dist/skills/index-prompt.js +5 -8
- package/dist/tools/background-jobs.d.ts +71 -0
- package/dist/tools/background-jobs.js +198 -0
- package/dist/tools/bash.d.ts +53 -1
- package/dist/tools/bash.js +158 -7
- package/dist/tools/clipboard-image.d.ts +44 -0
- package/dist/tools/clipboard-image.js +148 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.js +18 -3
- package/dist/tools/image-file.d.ts +38 -3
- package/dist/tools/image-file.js +81 -10
- package/dist/tools/image-resize.d.ts +58 -0
- package/dist/tools/image-resize.js +97 -0
- package/dist/tools/presets.d.ts +40 -8
- package/dist/tools/presets.js +65 -19
- package/dist/tools/read.d.ts +5 -2
- package/dist/tools/read.js +13 -10
- package/dist/tools/registry.d.ts +7 -1
- package/dist/tools/registry.js +27 -4
- package/dist/tools/task-ctl.d.ts +22 -0
- package/dist/tools/task-ctl.js +116 -0
- package/dist/tools/task.d.ts +22 -10
- package/dist/tools/task.js +66 -26
- package/dist/tools/todo.d.ts +22 -2
- package/dist/tools/todo.js +58 -14
- package/dist/tools/truncate.d.ts +15 -0
- package/dist/tools/truncate.js +25 -0
- package/dist/tools/types.d.ts +113 -0
- package/dist/tools/types.js +5 -0
- package/dist/tools/write.js +3 -0
- package/dist/tui/component.d.ts +8 -2
- package/dist/tui/component.js +3 -1
- package/dist/tui/components/box.d.ts +6 -1
- package/dist/tui/components/box.js +16 -6
- package/dist/tui/components/card.d.ts +23 -0
- package/dist/tui/components/card.js +37 -0
- package/dist/tui/components/editor-history.d.ts +6 -0
- package/dist/tui/components/editor-history.js +45 -0
- package/dist/tui/components/editor-paste.d.ts +1 -1
- package/dist/tui/components/editor-paste.js +4 -4
- package/dist/tui/components/editor.d.ts +11 -5
- package/dist/tui/components/editor.js +52 -58
- package/dist/tui/components/key-value.d.ts +3 -0
- package/dist/tui/components/key-value.js +16 -6
- package/dist/tui/components/loader.d.ts +37 -7
- package/dist/tui/components/loader.js +84 -21
- package/dist/tui/components/markdown.d.ts +5 -1
- package/dist/tui/components/markdown.js +45 -21
- package/dist/tui/components/meter.d.ts +3 -3
- package/dist/tui/components/meter.js +13 -11
- package/dist/tui/components/select-list.d.ts +23 -1
- package/dist/tui/components/select-list.js +76 -13
- package/dist/tui/glyphs.d.ts +72 -0
- package/dist/tui/glyphs.js +118 -0
- package/dist/tui/keybindings.d.ts +5 -0
- package/dist/tui/keybindings.js +5 -0
- package/dist/tui/theme.d.ts +30 -6
- package/dist/tui/theme.js +103 -17
- package/dist/tui.d.ts +4 -2
- package/dist/tui.js +3 -1
- package/docs/acp.md +78 -0
- package/docs/agents.md +250 -0
- package/docs/codemode.md +28 -10
- package/docs/hooks.md +36 -32
- package/docs/permissions.md +212 -0
- package/docs/plan.md +107 -0
- package/docs/providers.md +261 -62
- package/docs/rewind-plan.md +181 -0
- package/docs/rpc.md +127 -40
- package/docs/sandbox.md +215 -0
- package/docs/session-format.md +43 -22
- package/docs/sessions.md +174 -0
- package/docs/tui-design.md +751 -0
- package/docs/tui.md +260 -64
- package/package.json +15 -2
|
@@ -1,18 +1,171 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 消息区(设计 §12.5)。[B7]
|
|
3
3
|
*
|
|
4
|
-
* 一个纵向 `Container
|
|
5
|
-
*
|
|
4
|
+
* 一个纵向 `Container`,块与块之间空一行(终端界面视觉设计 v1 §1 原则 2:相邻工具调用之间不空行,
|
|
5
|
+
* `ui.compact` 时全部不空行):
|
|
6
|
+
* - 用户消息 `› 文本`(续行缩进 2 列);插话 / 之后 / 宿主注入按 `UserMessage.origin` 标
|
|
7
|
+
* `↳ 插话` / `↳ 之后` / `↳ 宿主`(整行 muted,其它 origin 原样显示);
|
|
6
8
|
* - 助手消息按内容块渲染:文本走 `Markdown`(`ui.markdown: false` 时纯文本),流式时只改末块
|
|
7
|
-
* (Markdown 自己按块缓存);思考块按 `ui.showThinking`:`collapsed`(缺省)一行
|
|
8
|
-
*
|
|
9
|
-
*
|
|
9
|
+
* (Markdown 自己按块缓存);思考块按 `ui.showThinking`:`collapsed`(缺省)一行 `✻ 思考 · N token`
|
|
10
|
+
* (流式中 `✻ 思考中…`),Ctrl+O 展开为标题 + 缩进 2 列的正文(最多 60 行);`full` 总是展开且不限行;
|
|
11
|
+
* `hidden` 不显示;
|
|
12
|
+
* - 压缩摘要卡(左竖条 Card)、重试提示、Hook 阻止提示、宿主 / 系统通知;字形取 `theme.glyphs`;
|
|
10
13
|
* - `replay()` 把已有消息(恢复会话、切换会话、/tree 之后)重新画出来,工具调用交给调用方构造。
|
|
11
14
|
*
|
|
12
15
|
* 滚动交给终端回滚:消息区只追加,切换会话时整体清空重画。
|
|
13
16
|
*/
|
|
14
|
-
import {
|
|
17
|
+
import { Card, Container, Markdown, Spacer, Text, visibleWidth, wrapTextWithAnsi, } from "../../tui.js";
|
|
18
|
+
import { formatCost, formatTokens } from "./status-bar.js";
|
|
19
|
+
import { notificationSummary } from "./subagent-view.js";
|
|
20
|
+
import { PLAN_APPROVED_PROMPT } from "../../plan/prompts.js";
|
|
21
|
+
/** 退出摘要的时长:不足 1 分钟按秒,否则按分钟。 */
|
|
22
|
+
function sessionDuration(ms) {
|
|
23
|
+
const seconds = Math.max(0, Math.round(ms / 1000));
|
|
24
|
+
return seconds < 60 ? `${seconds} 秒` : `${Math.round(seconds / 60)} 分钟`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 退出摘要(§3.14):`─ 会话 <id> · 时长 · N 回合 · ↑in ↓out · cache x% · $y(重计费 $z)` 与
|
|
28
|
+
* ` 恢复:ama --resume <id>`。整体 dim,会话 id 与恢复命令正文色;0 回合只到「回合」;会话没落盘不给恢复行。
|
|
29
|
+
*/
|
|
30
|
+
export function exitSummaryLines(stats, elapsedMs, theme) {
|
|
31
|
+
const g = theme.glyphs;
|
|
32
|
+
const dim = (s) => theme.fg("dim", s);
|
|
33
|
+
const id = stats.sessionId.slice(0, 8);
|
|
34
|
+
const parts = [
|
|
35
|
+
dim(`${g.rule} 会话 `) + theme.fg("text", id),
|
|
36
|
+
dim(sessionDuration(elapsedMs)),
|
|
37
|
+
dim(`${stats.userMessages} 回合`),
|
|
38
|
+
];
|
|
39
|
+
const t = stats.tokens;
|
|
40
|
+
const prompt = t.input + t.cacheRead + t.cacheWrite;
|
|
41
|
+
if (stats.userMessages > 0 && prompt + t.output > 0) {
|
|
42
|
+
parts.push(dim(`${g.arrowUp}${formatTokens(prompt)} ${g.arrowDown}${formatTokens(t.output)}`));
|
|
43
|
+
const rate = stats.cache?.hitRate ?? stats.cacheHitRate;
|
|
44
|
+
if (rate !== undefined)
|
|
45
|
+
parts.push(dim(`cache ${Math.round(rate * 100)}%`));
|
|
46
|
+
if (stats.cost !== undefined && stats.cost > 0) {
|
|
47
|
+
const rebill = stats.cache?.reBilledUsd;
|
|
48
|
+
const extra = rebill !== undefined && rebill > 0 ? `(重计费 ${formatCost(rebill)})` : "";
|
|
49
|
+
parts.push(dim(formatCost(stats.cost) + extra));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const lines = [parts.join(dim(" · "))];
|
|
53
|
+
if (stats.userMessages > 0 && stats.sessionFile !== undefined) {
|
|
54
|
+
lines.push(dim(" 恢复:") + theme.fg("text", `ama --resume ${id}`));
|
|
55
|
+
}
|
|
56
|
+
return lines;
|
|
57
|
+
}
|
|
58
|
+
/** 思考块展开时的正文行数上限(`full` 不限)。 */
|
|
59
|
+
export const THINKING_EXPANDED_LINES = 60;
|
|
60
|
+
/** origin → 中文标签(未知 origin 原样显示)。 */
|
|
61
|
+
export const ORIGIN_LABELS = {
|
|
62
|
+
steer: "插话",
|
|
63
|
+
followUp: "之后",
|
|
64
|
+
host: "宿主",
|
|
65
|
+
task: "子 Agent 通知",
|
|
66
|
+
plan: "计划",
|
|
67
|
+
};
|
|
68
|
+
/** [W5-U] origin 为 plan 的交接消息(给模型的英文开场)在消息区的说法。 */
|
|
69
|
+
const PLAN_HANDOFF_TEXT = "按批准的计划开始执行";
|
|
70
|
+
/** 首行带前缀、续行按 `indent` 缩进的文本(用户消息、排队消息)。 */
|
|
71
|
+
export class PrefixedText {
|
|
72
|
+
prefix;
|
|
73
|
+
body;
|
|
74
|
+
indent;
|
|
75
|
+
cache = null;
|
|
76
|
+
constructor(prefix, body, indent = 2) {
|
|
77
|
+
this.prefix = prefix;
|
|
78
|
+
this.body = body;
|
|
79
|
+
this.indent = indent;
|
|
80
|
+
}
|
|
81
|
+
render(width) {
|
|
82
|
+
if (this.cache?.width === width)
|
|
83
|
+
return this.cache.lines;
|
|
84
|
+
const prefixWidth = Math.max(this.indent, visibleWidth(this.prefix));
|
|
85
|
+
const pieces = wrapTextWithAnsi(this.body, Math.max(1, width - prefixWidth));
|
|
86
|
+
const pad = " ".repeat(this.indent);
|
|
87
|
+
const lines = pieces.map((line, i) => (i === 0 ? this.prefix + line : pad + line));
|
|
88
|
+
if (lines.length === 0)
|
|
89
|
+
lines.push(this.prefix);
|
|
90
|
+
this.cache = { width, lines };
|
|
91
|
+
return lines;
|
|
92
|
+
}
|
|
93
|
+
invalidate() {
|
|
94
|
+
this.cache = null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** 思考块:折叠一行 / 展开(标题 + 缩进正文)。 */
|
|
98
|
+
class ThinkingView {
|
|
99
|
+
theme;
|
|
100
|
+
display;
|
|
101
|
+
text = "";
|
|
102
|
+
tokens = 0;
|
|
103
|
+
streaming = true;
|
|
104
|
+
redacted = false;
|
|
105
|
+
expanded = false;
|
|
106
|
+
cache = null;
|
|
107
|
+
constructor(theme, display) {
|
|
108
|
+
this.theme = theme;
|
|
109
|
+
this.display = display;
|
|
110
|
+
}
|
|
111
|
+
set(text, tokens, streaming, redacted) {
|
|
112
|
+
if (text === this.text &&
|
|
113
|
+
tokens === this.tokens &&
|
|
114
|
+
streaming === this.streaming &&
|
|
115
|
+
redacted === this.redacted)
|
|
116
|
+
return;
|
|
117
|
+
this.text = text;
|
|
118
|
+
this.tokens = tokens;
|
|
119
|
+
this.streaming = streaming;
|
|
120
|
+
this.redacted = redacted;
|
|
121
|
+
this.cache = null;
|
|
122
|
+
}
|
|
123
|
+
setExpanded(expanded) {
|
|
124
|
+
if (expanded === this.expanded)
|
|
125
|
+
return;
|
|
126
|
+
this.expanded = expanded;
|
|
127
|
+
this.cache = null;
|
|
128
|
+
}
|
|
129
|
+
get open() {
|
|
130
|
+
return !this.redacted && (this.display === "full" || this.expanded);
|
|
131
|
+
}
|
|
132
|
+
render(width) {
|
|
133
|
+
if (this.cache?.width === width)
|
|
134
|
+
return this.cache.lines;
|
|
135
|
+
const t = this.theme;
|
|
136
|
+
const g = t.glyphs;
|
|
137
|
+
const style = (s) => t.fg("dim", t.italic(s));
|
|
138
|
+
const title = this.streaming
|
|
139
|
+
? `${g.thinking} 思考中${g.ellipsis}`
|
|
140
|
+
: `${g.thinking} 思考 · ${formatTokens(this.tokens)} token`;
|
|
141
|
+
const lines = [
|
|
142
|
+
style(title) + (this.open && !this.streaming ? " " + t.fg("dim", g.collapse) : ""),
|
|
143
|
+
];
|
|
144
|
+
if (this.open && this.text.trim() !== "") {
|
|
145
|
+
const all = this.text
|
|
146
|
+
.trim()
|
|
147
|
+
.split("\n")
|
|
148
|
+
.flatMap((line) => wrapTextWithAnsi(line, Math.max(1, width - 2)));
|
|
149
|
+
const limit = this.display === "full" ? all.length : THINKING_EXPANDED_LINES;
|
|
150
|
+
for (const line of all.slice(0, limit))
|
|
151
|
+
lines.push(" " + t.fg("muted", t.italic(line)));
|
|
152
|
+
if (all.length > limit) {
|
|
153
|
+
lines.push(" " + t.fg("dim", `${g.ellipsis} 另 ${all.length - limit} 行`));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
this.cache = { width, lines };
|
|
157
|
+
return lines;
|
|
158
|
+
}
|
|
159
|
+
invalidate() {
|
|
160
|
+
this.cache = null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
15
163
|
/** 粗估 token(4 字符 ≈ 1 token),只用于思考块的流式计数。 */
|
|
164
|
+
/** [W5-U] 计划块的开闭标签(独占一行)只给模型与提取用,消息区不显示(计划正文照常渲染)。 */
|
|
165
|
+
const PLAN_TAG_LINE = /^[ \t]*<\/?proposed_plan>[ \t]*$/gm;
|
|
166
|
+
export function displayText(text) {
|
|
167
|
+
return text.includes("proposed_plan>") ? text.replace(PLAN_TAG_LINE, "") : text;
|
|
168
|
+
}
|
|
16
169
|
export function estimateTokens(text) {
|
|
17
170
|
return Math.ceil(text.length / 4);
|
|
18
171
|
}
|
|
@@ -29,10 +182,19 @@ export class AssistantView extends Container {
|
|
|
29
182
|
parts = new Map();
|
|
30
183
|
status = new Text("");
|
|
31
184
|
streaming = true;
|
|
185
|
+
thinkingExpanded = false;
|
|
32
186
|
constructor(options) {
|
|
33
187
|
super();
|
|
34
188
|
this.options = options;
|
|
35
189
|
}
|
|
190
|
+
/** Ctrl+O:展开 / 折叠本消息的思考块(`collapsed` 模式下)。 */
|
|
191
|
+
setThinkingExpanded(expanded) {
|
|
192
|
+
this.thinkingExpanded = expanded;
|
|
193
|
+
for (const part of this.parts.values()) {
|
|
194
|
+
if (part instanceof ThinkingView)
|
|
195
|
+
part.setExpanded(expanded);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
36
198
|
update(message) {
|
|
37
199
|
const { theme } = this.options;
|
|
38
200
|
const display = this.options.showThinking ?? "collapsed";
|
|
@@ -43,35 +205,40 @@ export class AssistantView extends Container {
|
|
|
43
205
|
if (block.type === "thinking") {
|
|
44
206
|
if (display === "hidden" || (block.thinking === "" && block.redacted !== true))
|
|
45
207
|
return;
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
208
|
+
const view = this.part(index, () => {
|
|
209
|
+
const created = new ThinkingView(theme, display);
|
|
210
|
+
created.setExpanded(this.thinkingExpanded);
|
|
211
|
+
return created;
|
|
212
|
+
});
|
|
213
|
+
const single = message.content.filter((b) => b.type === "thinking").length === 1;
|
|
214
|
+
const tokens = !this.streaming && single && message.usage.reasoning !== undefined
|
|
215
|
+
? message.usage.reasoning
|
|
216
|
+
: estimateTokens(block.thinking);
|
|
217
|
+
// 后面已经有正文 / 工具调用:这段思考已结束
|
|
218
|
+
const later = message.content
|
|
219
|
+
.slice(index + 1)
|
|
220
|
+
.some((b) => (b.type === "text" ? b.text !== "" : b.type === "toolCall"));
|
|
221
|
+
view.set(block.thinking, tokens, this.streaming && !later, block.redacted === true);
|
|
222
|
+
order.push(view);
|
|
58
223
|
return;
|
|
59
224
|
}
|
|
60
225
|
if (block.text.trim() === "")
|
|
61
226
|
return;
|
|
62
227
|
const view = this.part(index, () => this.options.markdown === false ? new Text("") : new Markdown("", { theme }));
|
|
63
|
-
|
|
64
|
-
|
|
228
|
+
const text = displayText(block.text);
|
|
229
|
+
if (view.getText() !== text)
|
|
230
|
+
view.setText(text);
|
|
65
231
|
order.push(view);
|
|
66
232
|
});
|
|
233
|
+
const gap = this.options.compact !== true;
|
|
67
234
|
this.clear();
|
|
68
235
|
order.forEach((child, i) => {
|
|
69
|
-
if (i > 0)
|
|
236
|
+
if (i > 0 && gap)
|
|
70
237
|
this.addChild(new Spacer());
|
|
71
238
|
this.addChild(child);
|
|
72
239
|
});
|
|
73
240
|
if (this.status.getText() !== "") {
|
|
74
|
-
if (order.length > 0)
|
|
241
|
+
if (order.length > 0 && gap)
|
|
75
242
|
this.addChild(new Spacer());
|
|
76
243
|
this.addChild(this.status);
|
|
77
244
|
}
|
|
@@ -81,7 +248,7 @@ export class AssistantView extends Container {
|
|
|
81
248
|
this.streaming = false;
|
|
82
249
|
const { theme } = this.options;
|
|
83
250
|
if (message.stopReason === "error") {
|
|
84
|
-
this.status.setText(theme.fg("error",
|
|
251
|
+
this.status.setText(theme.fg("error", `${theme.glyphs.fail} ${message.errorMessage ?? "模型调用失败"}`));
|
|
85
252
|
}
|
|
86
253
|
else if (message.stopReason === "aborted") {
|
|
87
254
|
this.status.setText(theme.fg("dim", "已中断"));
|
|
@@ -107,6 +274,10 @@ export class MessageView extends Container {
|
|
|
107
274
|
options;
|
|
108
275
|
current;
|
|
109
276
|
blocks = [];
|
|
277
|
+
/** 工具调用块(相邻的不空行)。 */
|
|
278
|
+
toolBlocks = new WeakSet();
|
|
279
|
+
assistants = [];
|
|
280
|
+
thinkingExpanded = false;
|
|
110
281
|
constructor(options) {
|
|
111
282
|
super();
|
|
112
283
|
this.options = options;
|
|
@@ -114,9 +285,19 @@ export class MessageView extends Container {
|
|
|
114
285
|
get theme() {
|
|
115
286
|
return this.options.theme;
|
|
116
287
|
}
|
|
117
|
-
/**
|
|
288
|
+
/** 追加一块(与上一块之间空一行;`compact` 不空行)。 */
|
|
118
289
|
add(component) {
|
|
119
|
-
|
|
290
|
+
this.push(component, this.options.compact !== true);
|
|
291
|
+
}
|
|
292
|
+
/** 追加工具调用块:紧跟在另一个工具调用后面时不空行。 */
|
|
293
|
+
addTool(component) {
|
|
294
|
+
const last = this.blocks[this.blocks.length - 1];
|
|
295
|
+
const gap = this.options.compact !== true && !(last !== undefined && this.toolBlocks.has(last));
|
|
296
|
+
this.toolBlocks.add(component);
|
|
297
|
+
this.push(component, gap);
|
|
298
|
+
}
|
|
299
|
+
push(component, gap) {
|
|
300
|
+
if (this.blocks.length > 0 && gap)
|
|
120
301
|
this.addChild(new Spacer());
|
|
121
302
|
this.blocks.push(component);
|
|
122
303
|
this.addChild(component);
|
|
@@ -141,12 +322,19 @@ export class MessageView extends Container {
|
|
|
141
322
|
reset() {
|
|
142
323
|
this.clear();
|
|
143
324
|
this.blocks.length = 0;
|
|
325
|
+
this.assistants.length = 0;
|
|
144
326
|
this.current = undefined;
|
|
145
327
|
}
|
|
146
328
|
get blockCount() {
|
|
147
329
|
return this.blocks.length;
|
|
148
330
|
}
|
|
149
|
-
/**
|
|
331
|
+
/** Ctrl+O:所有助手消息的思考块一起展开 / 折叠(之后的新消息沿用)。 */
|
|
332
|
+
setThinkingExpanded(expanded) {
|
|
333
|
+
this.thinkingExpanded = expanded;
|
|
334
|
+
for (const view of this.assistants)
|
|
335
|
+
view.setThinkingExpanded(expanded);
|
|
336
|
+
}
|
|
337
|
+
/** 纯文本启动画面(line 模式风格):首行加粗,其余变暗。交互模式用 StartupHeader。 */
|
|
150
338
|
addHeader(lines) {
|
|
151
339
|
if (lines.length === 0)
|
|
152
340
|
return;
|
|
@@ -155,15 +343,34 @@ export class MessageView extends Container {
|
|
|
155
343
|
this.add(new Text(text.join("\n")));
|
|
156
344
|
}
|
|
157
345
|
addUser(message) {
|
|
346
|
+
const t = this.theme;
|
|
158
347
|
const text = contentText(message.content).replace(/\s+$/, "");
|
|
159
348
|
const origin = message.origin;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
349
|
+
if (origin === undefined || origin === "user") {
|
|
350
|
+
this.add(new PrefixedText(t.fg("user", t.bold(t.glyphs.prompt)) + " ", text));
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const label = ORIGIN_LABELS[origin] ?? origin;
|
|
354
|
+
// [W5-U] 后台子 Agent 的 <task-notification> 是给模型的全文,消息区只留一行
|
|
355
|
+
const summary = origin === "task"
|
|
356
|
+
? notificationSummary(text)
|
|
357
|
+
: origin === "plan" && text === PLAN_APPROVED_PROMPT
|
|
358
|
+
? PLAN_HANDOFF_TEXT
|
|
359
|
+
: undefined;
|
|
360
|
+
if (summary !== undefined) {
|
|
361
|
+
this.add(new PrefixedText(t.fg("dim", t.glyphs.queued) + " " + t.fg("muted", `${label} `), t.fg("muted", summary)));
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
this.add(new PrefixedText(t.fg("dim", t.glyphs.queued) + " " + t.fg("muted", `${label} `), t.fg("muted", text)));
|
|
164
365
|
}
|
|
165
|
-
|
|
366
|
+
newAssistant() {
|
|
166
367
|
const view = new AssistantView(this.options);
|
|
368
|
+
view.setThinkingExpanded(this.thinkingExpanded);
|
|
369
|
+
this.assistants.push(view);
|
|
370
|
+
return view;
|
|
371
|
+
}
|
|
372
|
+
startAssistant(message) {
|
|
373
|
+
const view = this.newAssistant();
|
|
167
374
|
view.update(message);
|
|
168
375
|
this.current = view;
|
|
169
376
|
this.add(view);
|
|
@@ -184,39 +391,48 @@ export class MessageView extends Container {
|
|
|
184
391
|
this.remove(view);
|
|
185
392
|
}
|
|
186
393
|
addNotice(level, message) {
|
|
394
|
+
const g = this.theme.glyphs;
|
|
187
395
|
const color = level === "error" ? "error" : level === "warn" ? "warning" : "dim";
|
|
188
|
-
const mark = level === "error" ?
|
|
396
|
+
const mark = level === "error" ? `${g.fail} ` : level === "warn" ? `${g.warn} ` : "";
|
|
189
397
|
this.add(new Text(this.theme.fg(color, mark + message)));
|
|
190
398
|
}
|
|
191
399
|
addHookBlocked(reason) {
|
|
192
|
-
|
|
400
|
+
const glyph = this.theme.glyphs.blocked;
|
|
401
|
+
this.add(new Text(this.theme.fg("warning", `${glyph} Hook 阻止:${reason}`)));
|
|
193
402
|
}
|
|
194
403
|
addRetry(attempt, maxAttempts, delayMs, error) {
|
|
195
404
|
const seconds = Math.max(1, Math.round(delayMs / 1000));
|
|
196
|
-
|
|
405
|
+
const glyph = this.theme.glyphs.retry;
|
|
406
|
+
this.add(new Text(this.theme.fg("warning", `${glyph} 重试 ${attempt}/${maxAttempts}(${seconds}s 后):${error}`)));
|
|
407
|
+
}
|
|
408
|
+
/** 退出前追加的会话摘要(留在终端回滚里)。 */
|
|
409
|
+
addExitSummary(lines) {
|
|
410
|
+
this.add(new Text(lines.join("\n")));
|
|
197
411
|
}
|
|
198
412
|
addRetryFailed(error) {
|
|
199
413
|
this.addNotice("error", `重试失败${error !== undefined ? `:${error}` : ""}`);
|
|
200
414
|
}
|
|
201
|
-
/** 压缩 /
|
|
415
|
+
/** 压缩 / 分支摘要卡(左竖条):标题 + token 变化(有则显示)+ 摘要前 3 行。 */
|
|
202
416
|
addSummaryCard(summary, options = {}) {
|
|
203
|
-
const
|
|
417
|
+
const t = this.theme;
|
|
204
418
|
const lines = summary
|
|
205
419
|
.trim()
|
|
206
420
|
.split("\n")
|
|
207
421
|
.filter((l) => l.trim() !== "");
|
|
208
422
|
const head = lines.slice(0, 3);
|
|
209
|
-
const body =
|
|
423
|
+
const body = head.map((l) => t.fg("muted", l));
|
|
424
|
+
if (lines.length > head.length) {
|
|
425
|
+
body.push(t.fg("dim", `${t.glyphs.ellipsis} 另 ${lines.length - head.length} 行`));
|
|
426
|
+
}
|
|
427
|
+
let subtitle;
|
|
210
428
|
if (options.tokensBefore !== undefined) {
|
|
211
|
-
const after = options.tokensAfter !== undefined ? ` → ${options.tokensAfter}` : "";
|
|
212
|
-
|
|
429
|
+
const after = options.tokensAfter !== undefined ? ` → ${formatTokens(options.tokensAfter)}` : "";
|
|
430
|
+
subtitle = `${formatTokens(options.tokensBefore)}${after} token`;
|
|
213
431
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
body.push(dim(`…(另 ${lines.length - head.length} 行)`));
|
|
217
|
-
this.add(new Box(new Text(body.join("\n")), {
|
|
432
|
+
this.add(new Card(new Text(body.join("\n")), {
|
|
433
|
+
theme: t,
|
|
218
434
|
title: options.title ?? "上下文已压缩",
|
|
219
|
-
|
|
435
|
+
...(subtitle !== undefined ? { subtitle } : {}),
|
|
220
436
|
}));
|
|
221
437
|
}
|
|
222
438
|
addCompaction(result) {
|
|
@@ -238,7 +454,7 @@ export class MessageView extends Container {
|
|
|
238
454
|
this.addUser(message);
|
|
239
455
|
break;
|
|
240
456
|
case "assistant": {
|
|
241
|
-
const view =
|
|
457
|
+
const view = this.newAssistant();
|
|
242
458
|
view.finish(message);
|
|
243
459
|
if (!view.isEmpty)
|
|
244
460
|
this.add(view);
|
|
@@ -247,7 +463,7 @@ export class MessageView extends Container {
|
|
|
247
463
|
continue;
|
|
248
464
|
const tool = hooks.tool(block, results.get(block.id));
|
|
249
465
|
if (tool !== undefined)
|
|
250
|
-
this.
|
|
466
|
+
this.addTool(tool);
|
|
251
467
|
}
|
|
252
468
|
break;
|
|
253
469
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 消息区面板(终端界面视觉设计 v1 §3.13):`/session`、`/cache`、`/permissions` 用左竖条卡片 + 键值表
|
|
3
|
+
* 渲染,而不是把纯文本拍进通知。line 模式与 RPC 仍用 session-report 的文本版。
|
|
4
|
+
*
|
|
5
|
+
* - `/session`:标题 `会话 <id 前 8 位> · <文件>`;模型 / 消息 / 用量 / 上下文(余量表,阈值着色),
|
|
6
|
+
* 空一行后「缓存」段(与 `/cache` 共用 `cacheRows`);
|
|
7
|
+
* - [W5-U] `/session` 多「子 Agent」行(任务汇总)与「外部 Agent」段(按 Agent 的运行次数与用量,单位不换算);
|
|
8
|
+
* - `/permissions`:权限模式、判定顺序(折行对齐值列)、规则(allow success、deny error、来源 dim)、
|
|
9
|
+
* 最近的 auto 判定。
|
|
10
|
+
*/
|
|
11
|
+
import type { AgentSession } from "../../agent/types.js";
|
|
12
|
+
import type { Runtime } from "../../cli/runtime.js";
|
|
13
|
+
import { KeyValue, type Component, type KeyValueRow, type Theme } from "../../tui.js";
|
|
14
|
+
/** 多段内容按顺序拼起来(段之间不加空行,由调用方放空串)。 */
|
|
15
|
+
export declare class Stack implements Component {
|
|
16
|
+
private readonly parts;
|
|
17
|
+
constructor(parts: readonly (Component | string)[]);
|
|
18
|
+
render(width: number): string[];
|
|
19
|
+
invalidate(): void;
|
|
20
|
+
}
|
|
21
|
+
/** 缩进若干列的子组件。 */
|
|
22
|
+
export declare class Indent implements Component {
|
|
23
|
+
private readonly child;
|
|
24
|
+
private readonly columns;
|
|
25
|
+
constructor(child: Component, columns: number);
|
|
26
|
+
render(width: number): string[];
|
|
27
|
+
invalidate(): void;
|
|
28
|
+
}
|
|
29
|
+
export declare function keyValue(rows: readonly KeyValueRow[], theme: Theme, wrap?: boolean): KeyValue;
|
|
30
|
+
export declare function sessionPanel(session: AgentSession, theme: Theme, options?: {
|
|
31
|
+
now?: number;
|
|
32
|
+
home?: string;
|
|
33
|
+
}): Component;
|
|
34
|
+
export declare function cachePanel(session: AgentSession, theme: Theme, now?: number): Component;
|
|
35
|
+
export declare function permissionsPanel(runtime: Pick<Runtime, "permission">, session: AgentSession, theme: Theme): Component;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 消息区面板(终端界面视觉设计 v1 §3.13):`/session`、`/cache`、`/permissions` 用左竖条卡片 + 键值表
|
|
3
|
+
* 渲染,而不是把纯文本拍进通知。line 模式与 RPC 仍用 session-report 的文本版。
|
|
4
|
+
*
|
|
5
|
+
* - `/session`:标题 `会话 <id 前 8 位> · <文件>`;模型 / 消息 / 用量 / 上下文(余量表,阈值着色),
|
|
6
|
+
* 空一行后「缓存」段(与 `/cache` 共用 `cacheRows`);
|
|
7
|
+
* - [W5-U] `/session` 多「子 Agent」行(任务汇总)与「外部 Agent」段(按 Agent 的运行次数与用量,单位不换算);
|
|
8
|
+
* - `/permissions`:权限模式、判定顺序(折行对齐值列)、规则(allow success、deny error、来源 dim)、
|
|
9
|
+
* 最近的 auto 判定。
|
|
10
|
+
*/
|
|
11
|
+
import { AUTO_LAYER_TEXT, permissionModeLabel } from "../../permissions/modes.js";
|
|
12
|
+
import { Card, KeyValue, Meter, } from "../../tui.js";
|
|
13
|
+
import { cacheRows, externalRows, formatTokenCount, formatUsd, taskStatsText, } from "../session-report.js";
|
|
14
|
+
import { tildePath } from "../../cli/startup-screen.js";
|
|
15
|
+
/** 多段内容按顺序拼起来(段之间不加空行,由调用方放空串)。 */
|
|
16
|
+
export class Stack {
|
|
17
|
+
parts;
|
|
18
|
+
constructor(parts) {
|
|
19
|
+
this.parts = parts;
|
|
20
|
+
}
|
|
21
|
+
render(width) {
|
|
22
|
+
return this.parts.flatMap((part) => (typeof part === "string" ? [part] : part.render(width)));
|
|
23
|
+
}
|
|
24
|
+
invalidate() {
|
|
25
|
+
for (const part of this.parts)
|
|
26
|
+
if (typeof part !== "string")
|
|
27
|
+
part.invalidate();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** 缩进若干列的子组件。 */
|
|
31
|
+
export class Indent {
|
|
32
|
+
child;
|
|
33
|
+
columns;
|
|
34
|
+
constructor(child, columns) {
|
|
35
|
+
this.child = child;
|
|
36
|
+
this.columns = columns;
|
|
37
|
+
}
|
|
38
|
+
render(width) {
|
|
39
|
+
const pad = " ".repeat(this.columns);
|
|
40
|
+
return this.child
|
|
41
|
+
.render(Math.max(1, width - this.columns))
|
|
42
|
+
.map((line) => (line === "" ? "" : pad + line));
|
|
43
|
+
}
|
|
44
|
+
invalidate() {
|
|
45
|
+
this.child.invalidate();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export function keyValue(rows, theme, wrap = false) {
|
|
49
|
+
return new KeyValue(rows, { theme, maxKeyRatio: 0.3, ...(wrap ? { wrap: true } : {}) });
|
|
50
|
+
}
|
|
51
|
+
function cacheSection(session, theme, now) {
|
|
52
|
+
return [theme.bold("缓存"), new Indent(keyValue(cacheRows(session, now), theme), 2)];
|
|
53
|
+
}
|
|
54
|
+
export function sessionPanel(session, theme, options = {}) {
|
|
55
|
+
const now = options.now ?? Date.now();
|
|
56
|
+
const state = session.state;
|
|
57
|
+
const stats = session.getStats();
|
|
58
|
+
const t = stats.tokens;
|
|
59
|
+
const sep = theme.fg("dim", " · ");
|
|
60
|
+
const model = state.model === undefined ? "?" : `${state.model.provider}/${state.model.id}`;
|
|
61
|
+
const ratio = stats.contextPercent === undefined ? undefined : stats.contextPercent / 100;
|
|
62
|
+
const meter = new Meter(ratio, { theme }).render(40)[0] ?? "";
|
|
63
|
+
const window = stats.contextTokens === undefined && stats.contextWindow === undefined
|
|
64
|
+
? ""
|
|
65
|
+
: sep +
|
|
66
|
+
`${stats.contextTokens === undefined ? "?" : formatTokenCount(stats.contextTokens)} / ` +
|
|
67
|
+
`${stats.contextWindow === undefined ? "?" : formatTokenCount(stats.contextWindow)}`;
|
|
68
|
+
const rows = [
|
|
69
|
+
{
|
|
70
|
+
key: "模型",
|
|
71
|
+
value: theme.fg("accent", model) +
|
|
72
|
+
sep +
|
|
73
|
+
`思考 ${state.thinkingLevel}` +
|
|
74
|
+
sep +
|
|
75
|
+
`权限 ${permissionModeLabel(state.permissionMode)}`,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
key: "消息",
|
|
79
|
+
value: [
|
|
80
|
+
`用户 ${stats.userMessages}`,
|
|
81
|
+
`助手 ${stats.assistantMessages}`,
|
|
82
|
+
`工具调用 ${stats.toolCalls}`,
|
|
83
|
+
].join(sep),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
key: "用量",
|
|
87
|
+
value: [
|
|
88
|
+
`输入 ${formatTokenCount(t.input)}`,
|
|
89
|
+
`输出 ${formatTokenCount(t.output)}`,
|
|
90
|
+
`缓存读 ${formatTokenCount(t.cacheRead)}`,
|
|
91
|
+
`缓存写 ${formatTokenCount(t.cacheWrite)}`,
|
|
92
|
+
formatUsd(stats.cost),
|
|
93
|
+
].join(sep),
|
|
94
|
+
},
|
|
95
|
+
{ key: "上下文", value: meter + window },
|
|
96
|
+
];
|
|
97
|
+
const tasks = taskStatsText(session);
|
|
98
|
+
if (tasks !== undefined)
|
|
99
|
+
rows.push({ key: "子 Agent", value: tasks });
|
|
100
|
+
const external = externalRows(session);
|
|
101
|
+
const externalSection = external.length > 0
|
|
102
|
+
? ["", theme.bold("外部 Agent"), new Indent(keyValue(external, theme), 2)]
|
|
103
|
+
: [];
|
|
104
|
+
const file = state.sessionFile === undefined ? "未落盘" : tildePath(state.sessionFile, options.home);
|
|
105
|
+
const parts = [
|
|
106
|
+
keyValue(rows, theme),
|
|
107
|
+
"",
|
|
108
|
+
...cacheSection(session, theme, now),
|
|
109
|
+
...externalSection,
|
|
110
|
+
];
|
|
111
|
+
return new Card(new Stack(parts), {
|
|
112
|
+
theme,
|
|
113
|
+
title: `会话 ${state.sessionId.slice(0, 8)}`,
|
|
114
|
+
subtitle: file,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
export function cachePanel(session, theme, now = Date.now()) {
|
|
118
|
+
return new Card(keyValue(cacheRows(session, now), theme), { theme, title: "缓存" });
|
|
119
|
+
}
|
|
120
|
+
const DECISION_COLOR = {
|
|
121
|
+
allow: "success",
|
|
122
|
+
deny: "error",
|
|
123
|
+
ask: "warning",
|
|
124
|
+
};
|
|
125
|
+
export function permissionsPanel(runtime, session, theme) {
|
|
126
|
+
const rules = runtime.permission.rules;
|
|
127
|
+
const mode = session.state.permissionMode;
|
|
128
|
+
const order = mode === "auto"
|
|
129
|
+
? "deny 规则 → Hook deny → 危险命令确认 → 规则层(受保护路径、项目外写入、网络、删除类)→ Hook ask → allow 规则 / Hook allow / 本会话记忆 → 静态判定(只读、项目内写入、安全名单)→ 模型分类器 → 询问"
|
|
130
|
+
: mode === "allowlist"
|
|
131
|
+
? "deny 规则 → Hook deny → 危险命令(拒绝)→ 只读工具 / allow 规则 / Hook allow 放行 → 其余拒绝(从不询问)"
|
|
132
|
+
: "deny 规则 → Hook deny → 危险命令确认 → 权限模式 → allow 规则 / Hook allow / 本会话记忆 → 询问";
|
|
133
|
+
const effect = (decision) => theme.fg(DECISION_COLOR[decision] ?? "text", decision.padEnd(5));
|
|
134
|
+
const parts = [
|
|
135
|
+
keyValue([
|
|
136
|
+
{ key: "权限模式", value: `${permissionModeLabel(mode)}${theme.fg("dim", `(${mode})`)}` },
|
|
137
|
+
{ key: "判定顺序", value: order },
|
|
138
|
+
], theme, true),
|
|
139
|
+
theme.bold(rules.length === 0 ? "规则(无)" : `规则(${rules.length})`),
|
|
140
|
+
];
|
|
141
|
+
if (rules.length > 0) {
|
|
142
|
+
parts.push(new Indent(keyValue(rules.map((r) => ({
|
|
143
|
+
key: effect(r.effect),
|
|
144
|
+
value: `${r.raw} ${theme.fg("dim", `[${r.source}]`)}`,
|
|
145
|
+
})), theme), 2));
|
|
146
|
+
}
|
|
147
|
+
const recent = runtime.permission.autoDecisions?.() ?? [];
|
|
148
|
+
if (recent.length > 0) {
|
|
149
|
+
parts.push(theme.bold(`最近的 auto 判定(${recent.length})`));
|
|
150
|
+
parts.push(new Indent(keyValue(recent.map((d) => ({
|
|
151
|
+
key: AUTO_LAYER_TEXT[d.layer],
|
|
152
|
+
value: `${effect(d.decision)} ${d.toolName} ${d.summary} — ${d.reason}` +
|
|
153
|
+
(d.cached === true ? theme.fg("dim", "(缓存)") : ""),
|
|
154
|
+
})), theme), 2));
|
|
155
|
+
}
|
|
156
|
+
return new Card(new Stack(parts), { theme });
|
|
157
|
+
}
|
|
@@ -4,8 +4,11 @@
|
|
|
4
4
|
* - 模型:按供应商分组并标 key 状态(`modelItems`,与启动期共用),当前模型预选;
|
|
5
5
|
* - 会话:名字或首条提示、相对时间、消息数(`sessionItems`);
|
|
6
6
|
* - 树:会话文件里全部用户消息,按分叉缩进,`●` 标出当前分支;选中项回填编辑器(由 commands.ts 处理);
|
|
7
|
-
* -
|
|
7
|
+
* - 权限模式(标题「权限模式」,界面顺序 1–6,当前模式 ✓ / Default dim / Recommended accent,底部按键提示,
|
|
8
|
+
* 上下留白,见 permissionItems)与思考级别;
|
|
9
|
+
* - 所有选择器底部一行按键提示(dim),模型选择器带 (i/n) 并给当前模型打 ✓。
|
|
8
10
|
*/
|
|
11
|
+
import type { PermissionMode } from "../../permissions/types.js";
|
|
9
12
|
import type { SessionEntry } from "../../session/types.js";
|
|
10
13
|
import { type Keybindings, type OverlayHandle, type OverlayOptions, type SelectItem, type Theme, type Component } from "../../tui.js";
|
|
11
14
|
export { modelItems, sessionItems } from "./startup-ui.js";
|
|
@@ -23,10 +26,28 @@ export interface PickerSpec {
|
|
|
23
26
|
filterable?: boolean;
|
|
24
27
|
maxVisible?: number;
|
|
25
28
|
emptyText?: string;
|
|
29
|
+
/** 右侧序号 1–9,按数字直接选中。 */
|
|
30
|
+
numberKeys?: boolean;
|
|
31
|
+
/** 说明放在标签下一行。 */
|
|
32
|
+
stacked?: boolean;
|
|
33
|
+
/** 当前值(标 ✓)。 */
|
|
34
|
+
currentValue?: string;
|
|
35
|
+
/** 列表下的按键提示,缺省「↑↓ 选择 · Enter 确认 · Esc 取消」。 */
|
|
36
|
+
footer?: string;
|
|
37
|
+
/** 提示行前带 (i/n)。 */
|
|
38
|
+
showCount?: boolean;
|
|
39
|
+
/** 框内上下留白行数。 */
|
|
40
|
+
paddingY?: number;
|
|
26
41
|
}
|
|
42
|
+
export declare const PICKER_FOOTER = "\u2191\u2193 \u9009\u62E9 \u00B7 Enter \u786E\u8BA4 \u00B7 Esc \u53D6\u6D88";
|
|
27
43
|
/** 打开一个居中选择器;Enter 返回选中项,Esc / Ctrl+C 返回 undefined。 */
|
|
28
44
|
export declare function openPicker(host: PickerHost, spec: PickerSpec): Promise<SelectItem | undefined>;
|
|
29
|
-
|
|
45
|
+
/**
|
|
46
|
+
* 模式选择器(标题「权限模式」):界面顺序、当前模式打勾(`currentValue`)、配置里的缺省模式标
|
|
47
|
+
* `Default`、Auto 标 `Recommended`,右侧数字快捷键 1–6,说明在下一行。
|
|
48
|
+
*/
|
|
49
|
+
export declare function permissionItems(_current: PermissionMode, configDefault?: PermissionMode): SelectItem[];
|
|
50
|
+
export declare function permissionPickerSpec(current: PermissionMode, configDefault?: PermissionMode): PickerSpec;
|
|
30
51
|
export declare function thinkingItems(reasoning: boolean): SelectItem[];
|
|
31
52
|
export interface TreeNode {
|
|
32
53
|
entry: SessionEntry;
|