@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
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交互界面的计划审批编排(docs/wave5-plan.md §6.1):把会话的计划审批交给对话框。[W5-U]
|
|
3
|
+
*
|
|
4
|
+
* - `attach(session)`:`planController(session).setAttendance("callback", …)`——计划提出后(会话空闲时)
|
|
5
|
+
* 打开审批框;同时关掉 W5-F 的文本回复审批与 `ama.plan_notice` 提示行(两者只在 `text` 时生效)。
|
|
6
|
+
* resume 回来已有待审批的计划时只提示一行(`/plan` 打开审批框)。
|
|
7
|
+
* - 选择 → `controller.respond()`:批准(指定执行模式,编辑过则带 `editedMarkdown`)、继续修改(意见作为
|
|
8
|
+
* 普通用户消息)、放弃(4 退出 Plan 模式;Esc 留在 Plan);「新上下文执行」先新建会话、`adopt(plan)`、
|
|
9
|
+
* 切执行模式,再发 `freshPrompt`。
|
|
10
|
+
*/
|
|
11
|
+
import type { AgentSession, PlanData } from "../../agent/types.js";
|
|
12
|
+
import type { SwitchRequest } from "../../cli/compose-session.js";
|
|
13
|
+
import type { NoticeLevel } from "./message-view.js";
|
|
14
|
+
import { openPlanDialog, type PlanChoice, type PlanDialogHost } from "./plan-dialog.js";
|
|
15
|
+
export interface PlanFlowDeps {
|
|
16
|
+
dialog: PlanDialogHost;
|
|
17
|
+
switchSession(request: SwitchRequest): Promise<AgentSession>;
|
|
18
|
+
notice(level: NoticeLevel, text: string): void;
|
|
19
|
+
/** 在当前会话发一条提示(新上下文执行的首条消息)。 */
|
|
20
|
+
prompt(text: string): void;
|
|
21
|
+
/** 测试注入:代替真实对话框。 */
|
|
22
|
+
open?(dialog: PlanDialogHost, input: Parameters<typeof openPlanDialog>[1]): Promise<PlanChoice>;
|
|
23
|
+
}
|
|
24
|
+
export declare class PlanFlow {
|
|
25
|
+
private readonly deps;
|
|
26
|
+
private opened;
|
|
27
|
+
constructor(deps: PlanFlowDeps);
|
|
28
|
+
/** 接管会话的计划审批(每次切换会话后调用)。 */
|
|
29
|
+
attach(session: AgentSession): void;
|
|
30
|
+
get isOpen(): boolean;
|
|
31
|
+
/** 打开审批框并执行选择(同一计划同时只开一个)。 */
|
|
32
|
+
ask(session: AgentSession, plan: PlanData): Promise<void>;
|
|
33
|
+
private apply;
|
|
34
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交互界面的计划审批编排(docs/wave5-plan.md §6.1):把会话的计划审批交给对话框。[W5-U]
|
|
3
|
+
*
|
|
4
|
+
* - `attach(session)`:`planController(session).setAttendance("callback", …)`——计划提出后(会话空闲时)
|
|
5
|
+
* 打开审批框;同时关掉 W5-F 的文本回复审批与 `ama.plan_notice` 提示行(两者只在 `text` 时生效)。
|
|
6
|
+
* resume 回来已有待审批的计划时只提示一行(`/plan` 打开审批框)。
|
|
7
|
+
* - 选择 → `controller.respond()`:批准(指定执行模式,编辑过则带 `editedMarkdown`)、继续修改(意见作为
|
|
8
|
+
* 普通用户消息)、放弃(4 退出 Plan 模式;Esc 留在 Plan);「新上下文执行」先新建会话、`adopt(plan)`、
|
|
9
|
+
* 切执行模式,再发 `freshPrompt`。
|
|
10
|
+
*/
|
|
11
|
+
import { permissionModeLabel } from "../../permissions/modes.js";
|
|
12
|
+
import { planController } from "../../plan/controller.js";
|
|
13
|
+
import { executionMode } from "../../plan/store.js";
|
|
14
|
+
import { approveFresh } from "./plan-command.js";
|
|
15
|
+
import { openPlanDialog } from "./plan-dialog.js";
|
|
16
|
+
export class PlanFlow {
|
|
17
|
+
deps;
|
|
18
|
+
opened;
|
|
19
|
+
constructor(deps) {
|
|
20
|
+
this.deps = deps;
|
|
21
|
+
}
|
|
22
|
+
/** 接管会话的计划审批(每次切换会话后调用)。 */
|
|
23
|
+
attach(session) {
|
|
24
|
+
const controller = planController(session);
|
|
25
|
+
if (controller === undefined)
|
|
26
|
+
return;
|
|
27
|
+
controller.setAttendance("callback", async (plan) => {
|
|
28
|
+
await this.ask(session, plan);
|
|
29
|
+
return undefined;
|
|
30
|
+
});
|
|
31
|
+
const pending = controller.pending();
|
|
32
|
+
if (pending !== undefined)
|
|
33
|
+
this.deps.notice("info", `计划 v${pending.version} 待审批:/plan 打开审批框`);
|
|
34
|
+
}
|
|
35
|
+
get isOpen() {
|
|
36
|
+
return this.opened !== undefined;
|
|
37
|
+
}
|
|
38
|
+
/** 打开审批框并执行选择(同一计划同时只开一个)。 */
|
|
39
|
+
async ask(session, plan) {
|
|
40
|
+
const controller = planController(session);
|
|
41
|
+
if (controller === undefined || this.opened !== undefined)
|
|
42
|
+
return;
|
|
43
|
+
this.opened = plan.id;
|
|
44
|
+
try {
|
|
45
|
+
const input = { plan, preMode: executionMode(undefined, controller.prePlanMode()) };
|
|
46
|
+
const choice = await (this.deps.open ?? openPlanDialog)(this.deps.dialog, input);
|
|
47
|
+
await this.apply(session, plan, choice);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
this.deps.notice("error", error instanceof Error ? error.message : String(error));
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
this.opened = undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async apply(session, plan, choice) {
|
|
57
|
+
const controller = planController(session);
|
|
58
|
+
if (controller === undefined)
|
|
59
|
+
return;
|
|
60
|
+
switch (choice.decision) {
|
|
61
|
+
case "approve": {
|
|
62
|
+
const result = await controller.respond({
|
|
63
|
+
planId: plan.id,
|
|
64
|
+
decision: "approve",
|
|
65
|
+
mode: choice.mode,
|
|
66
|
+
...(choice.editedMarkdown !== undefined ? { editedMarkdown: choice.editedMarkdown } : {}),
|
|
67
|
+
});
|
|
68
|
+
const mode = permissionModeLabel(result.mode ?? choice.mode);
|
|
69
|
+
this.deps.notice("info", `已批准计划 v${result.plan.version},以 ${mode} 执行`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
case "approve_fresh": {
|
|
73
|
+
const fresh = await approveFresh(controller, plan, choice.mode, { switchSession: (request) => this.deps.switchSession(request) }, choice.editedMarkdown);
|
|
74
|
+
this.deps.notice("info", `已批准计划 v${fresh.plan.version},在新会话 ${fresh.session.state.sessionId.slice(0, 8)} 以 ${permissionModeLabel(choice.mode)} 执行`);
|
|
75
|
+
this.deps.prompt(fresh.prompt);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
case "revise":
|
|
79
|
+
await controller.respond({
|
|
80
|
+
planId: plan.id,
|
|
81
|
+
decision: "revise",
|
|
82
|
+
feedback: choice.feedback,
|
|
83
|
+
});
|
|
84
|
+
return;
|
|
85
|
+
case "reject": {
|
|
86
|
+
const pre = executionMode(undefined, controller.prePlanMode());
|
|
87
|
+
await controller.respond({ planId: plan.id, decision: "reject" });
|
|
88
|
+
if (choice.exit) {
|
|
89
|
+
session.setPermissionMode(pre);
|
|
90
|
+
this.deps.notice("info", `已放弃计划 v${plan.version},回到 ${permissionModeLabel(pre)}`);
|
|
91
|
+
}
|
|
92
|
+
else
|
|
93
|
+
this.deps.notice("info", `已放弃计划 v${plan.version}(仍在 Plan 模式,/plan 查看)`);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/rewind` 的带参数形式(rewind-plan §4,line 模式与交互模式共用;交互模式无参数时开列表)。[RW-C]
|
|
3
|
+
*
|
|
4
|
+
* - `/rewind`:列出回滚点,编号从旧到新(1 = 最早)。
|
|
5
|
+
* - `/rewind <n> [both|conversation|code] [overwrite]`:缺省 both(没有检查点时 conversation);
|
|
6
|
+
* `overwrite` 覆盖冲突文件(`onConflict: "overwrite"`)。
|
|
7
|
+
* - `/rewind <n> summarize-from|summarize-up-to [说明]`。
|
|
8
|
+
* 错误码换成中文说明后照原 code 抛出。
|
|
9
|
+
*/
|
|
10
|
+
import type { AgentSession, RewindDraftText } from "../../agent/types.js";
|
|
11
|
+
import type { RewindPoint } from "../../checkpoints/types.js";
|
|
12
|
+
import type { RewindAction } from "./rewind-panel.js";
|
|
13
|
+
export declare const REWIND_USAGE = "\u7528\u6CD5\uFF1A/rewind\uFF0C/rewind <n> [both|conversation|code] [overwrite]\uFF0C/rewind <n> summarize-from|summarize-up-to [\u8BF4\u660E]";
|
|
14
|
+
export interface RewindArgs {
|
|
15
|
+
/** 1 起的编号。 */
|
|
16
|
+
index: number;
|
|
17
|
+
action?: RewindAction;
|
|
18
|
+
instructions?: string;
|
|
19
|
+
overwrite?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function parseRewindArgs(args: string): RewindArgs;
|
|
22
|
+
export declare function rewindListText(points: readonly RewindPoint[], now: number): string;
|
|
23
|
+
export interface RewindCommandResult {
|
|
24
|
+
message: string;
|
|
25
|
+
/** 对话变了:原消息草稿(界面回填输入框)。 */
|
|
26
|
+
draft?: RewindDraftText;
|
|
27
|
+
/** 消息区要重画。 */
|
|
28
|
+
reload?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/** 执行 `/rewind <args>`;args 为空时只列出回滚点。 */
|
|
31
|
+
export declare function rewindCommand(session: AgentSession, args: string, now?: number): Promise<RewindCommandResult>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/rewind` 的带参数形式(rewind-plan §4,line 模式与交互模式共用;交互模式无参数时开列表)。[RW-C]
|
|
3
|
+
*
|
|
4
|
+
* - `/rewind`:列出回滚点,编号从旧到新(1 = 最早)。
|
|
5
|
+
* - `/rewind <n> [both|conversation|code] [overwrite]`:缺省 both(没有检查点时 conversation);
|
|
6
|
+
* `overwrite` 覆盖冲突文件(`onConflict: "overwrite"`)。
|
|
7
|
+
* - `/rewind <n> summarize-from|summarize-up-to [说明]`。
|
|
8
|
+
* 错误码换成中文说明后照原 code 抛出。
|
|
9
|
+
*/
|
|
10
|
+
import { AmaError } from "../../errors.js";
|
|
11
|
+
import { oneLine, rewindErrorText, rewindResultLines } from "./rewind-text.js";
|
|
12
|
+
import { relativeTime } from "./startup-ui.js";
|
|
13
|
+
const FORMS = "/rewind <n> [both|conversation|code] [overwrite],/rewind <n> summarize-from|summarize-up-to [说明]";
|
|
14
|
+
export const REWIND_USAGE = `用法:/rewind,${FORMS}`;
|
|
15
|
+
const ACTIONS = [
|
|
16
|
+
"both",
|
|
17
|
+
"conversation",
|
|
18
|
+
"code",
|
|
19
|
+
"summarize-from",
|
|
20
|
+
"summarize-up-to",
|
|
21
|
+
];
|
|
22
|
+
export function parseRewindArgs(args) {
|
|
23
|
+
const m = /^(\d+)(?:\s+(\S+))?(?:\s+([\s\S]*))?$/.exec(args.trim());
|
|
24
|
+
const index = m === null ? NaN : Number(m[1]);
|
|
25
|
+
if (m === null || !Number.isInteger(index) || index < 1) {
|
|
26
|
+
throw new AmaError("invalid_arguments", REWIND_USAGE);
|
|
27
|
+
}
|
|
28
|
+
const out = { index };
|
|
29
|
+
const action = m[2];
|
|
30
|
+
const rest = (m[3] ?? "").trim();
|
|
31
|
+
if (action === undefined)
|
|
32
|
+
return out;
|
|
33
|
+
if (!ACTIONS.includes(action)) {
|
|
34
|
+
throw new AmaError("invalid_arguments", REWIND_USAGE);
|
|
35
|
+
}
|
|
36
|
+
out.action = action;
|
|
37
|
+
if (action === "summarize-from" || action === "summarize-up-to") {
|
|
38
|
+
if (rest !== "")
|
|
39
|
+
out.instructions = rest;
|
|
40
|
+
}
|
|
41
|
+
else if (rest === "overwrite" && action !== "conversation")
|
|
42
|
+
out.overwrite = true;
|
|
43
|
+
else if (rest !== "")
|
|
44
|
+
throw new AmaError("invalid_arguments", REWIND_USAGE);
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
export function rewindListText(points, now) {
|
|
48
|
+
if (points.length === 0)
|
|
49
|
+
return "还没有可回滚的消息";
|
|
50
|
+
const lines = points.map((point, i) => {
|
|
51
|
+
const time = relativeTime(new Date(point.timestamp).toISOString(), now);
|
|
52
|
+
const only = point.hasCheckpoint ? "" : " [仅对话]";
|
|
53
|
+
return ` ${i + 1}. ${time} ${oneLine(point.text, 60) || "(空)"}${only}`;
|
|
54
|
+
});
|
|
55
|
+
return [`回滚点(${FORMS}):`, ...lines].join("\n");
|
|
56
|
+
}
|
|
57
|
+
/** 执行 `/rewind <args>`;args 为空时只列出回滚点。 */
|
|
58
|
+
export async function rewindCommand(session, args, now = Date.now()) {
|
|
59
|
+
const points = session.rewindPoints();
|
|
60
|
+
if (args.trim() === "")
|
|
61
|
+
return { message: rewindListText(points, now) };
|
|
62
|
+
const parsed = parseRewindArgs(args);
|
|
63
|
+
const point = points[parsed.index - 1];
|
|
64
|
+
if (point === undefined) {
|
|
65
|
+
throw new AmaError("invalid_arguments", `没有第 ${parsed.index} 个回滚点(共 ${points.length} 个,/rewind 查看)`);
|
|
66
|
+
}
|
|
67
|
+
const action = parsed.action ?? (point.hasCheckpoint ? "both" : "conversation");
|
|
68
|
+
try {
|
|
69
|
+
if (action === "summarize-from") {
|
|
70
|
+
const result = await session.summarizeFrom(point.entryId, parsed.instructions);
|
|
71
|
+
return {
|
|
72
|
+
message: `已从这里分叉,离开的部分写成了摘要;原消息:${oneLine(result.draft.text, 80)}`,
|
|
73
|
+
draft: result.draft,
|
|
74
|
+
reload: true,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
if (action === "summarize-up-to") {
|
|
78
|
+
const result = await session.summarizeUpTo(point.entryId, parsed.instructions);
|
|
79
|
+
const after = result.tokensAfter !== undefined ? ` → ${result.tokensAfter}` : "";
|
|
80
|
+
return { message: `已摘要到这里:${result.tokensBefore}${after} token` };
|
|
81
|
+
}
|
|
82
|
+
const result = await session.rewind({
|
|
83
|
+
entryId: point.entryId,
|
|
84
|
+
mode: action,
|
|
85
|
+
...(parsed.overwrite === true ? { onConflict: "overwrite" } : {}),
|
|
86
|
+
});
|
|
87
|
+
if (action === "conversation")
|
|
88
|
+
delete result.gitHint;
|
|
89
|
+
const draft = result.conversation?.draft;
|
|
90
|
+
const lines = rewindResultLines(result, {
|
|
91
|
+
overwrite: parsed.overwrite === true,
|
|
92
|
+
...(draft !== undefined
|
|
93
|
+
? { conversation: `对话已回到这条消息之前;原消息:${oneLine(draft.text, 80)}` }
|
|
94
|
+
: {}),
|
|
95
|
+
});
|
|
96
|
+
return draft !== undefined
|
|
97
|
+
? { message: lines.join("\n"), draft, reload: true }
|
|
98
|
+
: { message: lines.join("\n") };
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (error instanceof AmaError) {
|
|
102
|
+
throw new AmaError(error.code, rewindErrorText(error), { cause: error });
|
|
103
|
+
}
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 回滚交互流程(rewind-plan §3.5、§3.6、§4):列表 → 确认面板 → 执行 → 结果通知。[RW-C]
|
|
3
|
+
*
|
|
4
|
+
* - `open()`(`/rewind`、空闲时双击 Esc):运行中只提示;没有回滚点提示一行。
|
|
5
|
+
* - 执行:对话类(恢复代码和对话 / 恢复对话 / 从这里摘要)之后重画消息区并把原消息回填输入框
|
|
6
|
+
* (文本进编辑器,图片随下一条消息发送);结果写一条通知,错误码换成中文说明。
|
|
7
|
+
* - `afterInterrupt()`(中断即撤回):Esc 中断后等运行结束;输入框仍为空且会话判定可撤回
|
|
8
|
+
* (`ui.restoreOnCancel`、本回合没有任何助手文本 / 工具调用)→ 撤回并回填原消息。
|
|
9
|
+
*/
|
|
10
|
+
import type { AgentSession, RewindDraftText } from "../../agent/types.js";
|
|
11
|
+
import type { RewindPoint } from "../../checkpoints/types.js";
|
|
12
|
+
import type { NoticeLevel } from "./message-view.js";
|
|
13
|
+
import { type RewindListHost } from "./rewind-list.js";
|
|
14
|
+
import { type RewindChoice, type RewindPanelModel } from "./rewind-panel.js";
|
|
15
|
+
export interface RewindFlowHost extends RewindListHost {
|
|
16
|
+
session(): AgentSession;
|
|
17
|
+
notice(level: NoticeLevel, text: string): void;
|
|
18
|
+
/** 底部提示行。 */
|
|
19
|
+
hint(text: string): void;
|
|
20
|
+
/** 对话变了:重画消息区。 */
|
|
21
|
+
reload(): void;
|
|
22
|
+
/** 原消息回填输入框(图片随下一条消息发送)。 */
|
|
23
|
+
setDraft(draft: RewindDraftText): void;
|
|
24
|
+
editorEmpty(): boolean;
|
|
25
|
+
/** 终端行数(面板放不下时紧凑排版)。 */
|
|
26
|
+
rows?(): number;
|
|
27
|
+
}
|
|
28
|
+
export declare const REFILLED = "\u539F\u6D88\u606F\u5DF2\u653E\u56DE\u8F93\u5165\u6846";
|
|
29
|
+
/** 打开确认面板(底部覆盖层);返回选择或 undefined(取消)。 */
|
|
30
|
+
export declare function openRewindPanel(host: RewindFlowHost, model: RewindPanelModel): Promise<RewindChoice | undefined>;
|
|
31
|
+
/** 执行面板里的选择,结果与错误都写成通知。 */
|
|
32
|
+
export declare function executeRewind(host: RewindFlowHost, point: RewindPoint, choice: RewindChoice): Promise<void>;
|
|
33
|
+
export interface RewindFlow {
|
|
34
|
+
open(): Promise<void>;
|
|
35
|
+
afterInterrupt(editorWasEmpty: boolean): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export declare function createRewindFlow(host: RewindFlowHost): RewindFlow;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 回滚交互流程(rewind-plan §3.5、§3.6、§4):列表 → 确认面板 → 执行 → 结果通知。[RW-C]
|
|
3
|
+
*
|
|
4
|
+
* - `open()`(`/rewind`、空闲时双击 Esc):运行中只提示;没有回滚点提示一行。
|
|
5
|
+
* - 执行:对话类(恢复代码和对话 / 恢复对话 / 从这里摘要)之后重画消息区并把原消息回填输入框
|
|
6
|
+
* (文本进编辑器,图片随下一条消息发送);结果写一条通知,错误码换成中文说明。
|
|
7
|
+
* - `afterInterrupt()`(中断即撤回):Esc 中断后等运行结束;输入框仍为空且会话判定可撤回
|
|
8
|
+
* (`ui.restoreOnCancel`、本回合没有任何助手文本 / 工具调用)→ 撤回并回填原消息。
|
|
9
|
+
*/
|
|
10
|
+
import { AgentSessionImpl } from "../../agent/session.js";
|
|
11
|
+
import { PreviewCache, openRewindList } from "./rewind-list.js";
|
|
12
|
+
import { RewindPanel } from "./rewind-panel.js";
|
|
13
|
+
import { rewindErrorText, rewindResultLines } from "./rewind-text.js";
|
|
14
|
+
export const REFILLED = "原消息已放回输入框";
|
|
15
|
+
/** 打开确认面板(底部覆盖层);返回选择或 undefined(取消)。 */
|
|
16
|
+
export function openRewindPanel(host, model) {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
let handle;
|
|
19
|
+
const panel = new RewindPanel(model, {
|
|
20
|
+
theme: host.theme,
|
|
21
|
+
...(host.keybindings !== undefined ? { keybindings: host.keybindings } : {}),
|
|
22
|
+
...(host.rows !== undefined ? { rows: host.rows } : {}),
|
|
23
|
+
}, (choice) => {
|
|
24
|
+
handle?.hide();
|
|
25
|
+
resolve(choice);
|
|
26
|
+
});
|
|
27
|
+
handle = host.showOverlay(panel, { anchor: "bottom" });
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function draftNote(draft) {
|
|
31
|
+
const images = draft.images?.length ?? 0;
|
|
32
|
+
return images > 0 ? `${REFILLED}(${images} 张图片随下一条消息发送)` : REFILLED;
|
|
33
|
+
}
|
|
34
|
+
/** 执行面板里的选择,结果与错误都写成通知。 */
|
|
35
|
+
export async function executeRewind(host, point, choice) {
|
|
36
|
+
const session = host.session();
|
|
37
|
+
try {
|
|
38
|
+
switch (choice.action) {
|
|
39
|
+
case "both":
|
|
40
|
+
case "conversation":
|
|
41
|
+
case "code": {
|
|
42
|
+
host.hint("回滚中…");
|
|
43
|
+
const result = await session.rewind({
|
|
44
|
+
entryId: point.entryId,
|
|
45
|
+
mode: choice.action,
|
|
46
|
+
...(choice.onConflict !== undefined ? { onConflict: choice.onConflict } : {}),
|
|
47
|
+
});
|
|
48
|
+
const draft = result.conversation?.draft;
|
|
49
|
+
if (draft !== undefined) {
|
|
50
|
+
host.reload();
|
|
51
|
+
host.setDraft(draft);
|
|
52
|
+
}
|
|
53
|
+
const shown = { ...result };
|
|
54
|
+
if (choice.action === "conversation")
|
|
55
|
+
delete shown.gitHint;
|
|
56
|
+
const lines = rewindResultLines(shown, {
|
|
57
|
+
overwrite: choice.onConflict === "overwrite",
|
|
58
|
+
...(draft !== undefined
|
|
59
|
+
? { conversation: `对话已回到这条消息之前,${draftNote(draft)}` }
|
|
60
|
+
: {}),
|
|
61
|
+
});
|
|
62
|
+
const code = result.code;
|
|
63
|
+
const nothing = code !== undefined &&
|
|
64
|
+
code.restored.length + code.deleted.length === 0 &&
|
|
65
|
+
(choice.onConflict !== "overwrite" || code.conflicts.length === 0);
|
|
66
|
+
host.notice(nothing && choice.action === "code" ? "warn" : "info", lines.join("\n"));
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case "summarize-from": {
|
|
70
|
+
host.hint("正在为离开的部分写摘要…");
|
|
71
|
+
const result = await session.summarizeFrom(point.entryId, choice.instructions);
|
|
72
|
+
host.reload();
|
|
73
|
+
host.setDraft(result.draft);
|
|
74
|
+
host.notice("info", `已从这里分叉,离开的部分写成了摘要;${draftNote(result.draft)}`);
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case "summarize-up-to": {
|
|
78
|
+
host.hint("正在摘要…");
|
|
79
|
+
const result = await session.summarizeUpTo(point.entryId, choice.instructions);
|
|
80
|
+
const after = result.tokensAfter !== undefined ? ` → ${result.tokensAfter}` : "";
|
|
81
|
+
host.notice("info", `已摘要到这里:${result.tokensBefore}${after} token`);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
host.notice("error", rewindErrorText(error));
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
host.hint("");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export function createRewindFlow(host) {
|
|
94
|
+
let opening = false;
|
|
95
|
+
return {
|
|
96
|
+
async open() {
|
|
97
|
+
const session = host.session();
|
|
98
|
+
if (session.state.isStreaming) {
|
|
99
|
+
host.notice("warn", "正在运行,不能回滚(先按 Esc 中断)");
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (opening)
|
|
103
|
+
return;
|
|
104
|
+
opening = true;
|
|
105
|
+
try {
|
|
106
|
+
const points = session.rewindPoints();
|
|
107
|
+
if (points.length === 0) {
|
|
108
|
+
host.notice("info", "还没有可回滚的消息");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const cache = new PreviewCache((entryId) => session.rewind({ entryId, mode: "code", dryRun: true }));
|
|
112
|
+
const point = await openRewindList(host, points, cache);
|
|
113
|
+
if (point === undefined)
|
|
114
|
+
return;
|
|
115
|
+
const model = { point, now: host.now() };
|
|
116
|
+
if (point.hasCheckpoint) {
|
|
117
|
+
const state = await cache.ensure(point.entryId);
|
|
118
|
+
if (state.state === "done")
|
|
119
|
+
model.preview = state.result;
|
|
120
|
+
else if (state.state === "error")
|
|
121
|
+
model.previewError = state.message;
|
|
122
|
+
}
|
|
123
|
+
const choice = await openRewindPanel(host, model);
|
|
124
|
+
if (choice !== undefined)
|
|
125
|
+
await executeRewind(host, point, choice);
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
opening = false;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
async afterInterrupt(editorWasEmpty) {
|
|
132
|
+
const session = host.session();
|
|
133
|
+
await session.waitForIdle();
|
|
134
|
+
if (!editorWasEmpty || !host.editorEmpty())
|
|
135
|
+
return;
|
|
136
|
+
if (!(session instanceof AgentSessionImpl) || !session.canUndoAbortedTurn())
|
|
137
|
+
return;
|
|
138
|
+
try {
|
|
139
|
+
const draft = await session.undoAbortedTurn();
|
|
140
|
+
if (draft === undefined)
|
|
141
|
+
return;
|
|
142
|
+
host.reload();
|
|
143
|
+
host.setDraft(draft);
|
|
144
|
+
host.notice("info", `已撤回被中断的消息,${draftNote(draft)}`);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
host.notice("error", rewindErrorText(error));
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 回滚列表(rewind-plan §4):居中覆盖层 + `SelectList`。[RW-C]
|
|
3
|
+
*
|
|
4
|
+
* - 活动路径上的回滚点,最旧在上、最近在下,缺省选中最后一条;标签是消息首行,说明是相对时间。
|
|
5
|
+
* - 右侧徽标:没有检查点的行一律「仅对话」;有检查点的只给高亮行算——对它做一次代码 dry-run,
|
|
6
|
+
* 结果按 entryId 缓存,算好后异步刷新:`N 文件 +x −y` / `无代码改动`,计算中 `…`,失败 `—`。
|
|
7
|
+
*/
|
|
8
|
+
import type { RewindPoint, RewindResult } from "../../checkpoints/types.js";
|
|
9
|
+
import { type SelectItem } from "../../tui.js";
|
|
10
|
+
import { type PickerHost } from "./pickers.js";
|
|
11
|
+
export type PreviewState = {
|
|
12
|
+
state: "pending";
|
|
13
|
+
} | {
|
|
14
|
+
state: "done";
|
|
15
|
+
result: RewindResult;
|
|
16
|
+
} | {
|
|
17
|
+
state: "error";
|
|
18
|
+
message: string;
|
|
19
|
+
};
|
|
20
|
+
/** 代码 dry-run 的缓存:每个回滚点最多算一次。 */
|
|
21
|
+
export declare class PreviewCache {
|
|
22
|
+
private readonly load;
|
|
23
|
+
private readonly states;
|
|
24
|
+
private readonly running;
|
|
25
|
+
constructor(load: (entryId: string) => Promise<RewindResult>);
|
|
26
|
+
get(entryId: string): PreviewState | undefined;
|
|
27
|
+
ensure(entryId: string): Promise<PreviewState>;
|
|
28
|
+
}
|
|
29
|
+
/** 列表项:value = 用户消息条目 id。 */
|
|
30
|
+
export declare function rewindListItems(points: readonly RewindPoint[], cache: PreviewCache, highlighted: string | undefined, now: number, ascii?: boolean): SelectItem[];
|
|
31
|
+
export interface RewindListHost extends PickerHost {
|
|
32
|
+
render(): void;
|
|
33
|
+
now(): number;
|
|
34
|
+
}
|
|
35
|
+
/** 打开回滚列表;Enter 返回选中的回滚点,Esc 返回 undefined。 */
|
|
36
|
+
export declare function openRewindList(host: RewindListHost, points: readonly RewindPoint[], cache: PreviewCache): Promise<RewindPoint | undefined>;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 回滚列表(rewind-plan §4):居中覆盖层 + `SelectList`。[RW-C]
|
|
3
|
+
*
|
|
4
|
+
* - 活动路径上的回滚点,最旧在上、最近在下,缺省选中最后一条;标签是消息首行,说明是相对时间。
|
|
5
|
+
* - 右侧徽标:没有检查点的行一律「仅对话」;有检查点的只给高亮行算——对它做一次代码 dry-run,
|
|
6
|
+
* 结果按 entryId 缓存,算好后异步刷新:`N 文件 +x −y` / `无代码改动`,计算中 `…`,失败 `—`。
|
|
7
|
+
*/
|
|
8
|
+
import { Box, SelectList } from "../../tui.js";
|
|
9
|
+
import { PICKER_FOOTER } from "./pickers.js";
|
|
10
|
+
import { badgeText, hasCodeChanges, oneLine, rewindErrorText } from "./rewind-text.js";
|
|
11
|
+
import { relativeTime } from "./startup-ui.js";
|
|
12
|
+
/** 代码 dry-run 的缓存:每个回滚点最多算一次。 */
|
|
13
|
+
export class PreviewCache {
|
|
14
|
+
load;
|
|
15
|
+
states = new Map();
|
|
16
|
+
running = new Map();
|
|
17
|
+
constructor(load) {
|
|
18
|
+
this.load = load;
|
|
19
|
+
}
|
|
20
|
+
get(entryId) {
|
|
21
|
+
return this.states.get(entryId);
|
|
22
|
+
}
|
|
23
|
+
ensure(entryId) {
|
|
24
|
+
const known = this.states.get(entryId);
|
|
25
|
+
if (known !== undefined && known.state !== "pending")
|
|
26
|
+
return Promise.resolve(known);
|
|
27
|
+
const running = this.running.get(entryId);
|
|
28
|
+
if (running !== undefined)
|
|
29
|
+
return running;
|
|
30
|
+
this.states.set(entryId, { state: "pending" });
|
|
31
|
+
const promise = this.load(entryId).then((result) => ({ state: "done", result }), (error) => ({ state: "error", message: rewindErrorText(error) }));
|
|
32
|
+
const settled = promise.then((state) => {
|
|
33
|
+
this.states.set(entryId, state);
|
|
34
|
+
this.running.delete(entryId);
|
|
35
|
+
return state;
|
|
36
|
+
});
|
|
37
|
+
this.running.set(entryId, settled);
|
|
38
|
+
return settled;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** 列表项:value = 用户消息条目 id。 */
|
|
42
|
+
export function rewindListItems(points, cache, highlighted, now, ascii = false) {
|
|
43
|
+
return points.map((point) => {
|
|
44
|
+
const text = oneLine(point.text, 60, ascii ? "..." : "…");
|
|
45
|
+
const item = {
|
|
46
|
+
value: point.entryId,
|
|
47
|
+
label: text === "" ? "(空)" : text,
|
|
48
|
+
description: relativeTime(new Date(point.timestamp).toISOString(), now),
|
|
49
|
+
};
|
|
50
|
+
if (!point.hasCheckpoint) {
|
|
51
|
+
item.badge = "仅对话";
|
|
52
|
+
item.badgeColor = "dim";
|
|
53
|
+
}
|
|
54
|
+
else if (point.entryId === highlighted) {
|
|
55
|
+
const state = cache.get(point.entryId);
|
|
56
|
+
if (state === undefined || state.state === "pending") {
|
|
57
|
+
item.badge = ascii ? "..." : "…";
|
|
58
|
+
item.badgeColor = "dim";
|
|
59
|
+
}
|
|
60
|
+
else if (state.state === "error") {
|
|
61
|
+
item.badge = ascii ? "-" : "—";
|
|
62
|
+
item.badgeColor = "dim";
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const code = state.result.code;
|
|
66
|
+
item.badge = code === undefined ? "无代码改动" : badgeText(code, ascii);
|
|
67
|
+
item.badgeColor = hasCodeChanges(code) ? "accent" : "dim";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return item;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** 打开回滚列表;Enter 返回选中的回滚点,Esc 返回 undefined。 */
|
|
74
|
+
export function openRewindList(host, points, cache) {
|
|
75
|
+
return new Promise((resolve) => {
|
|
76
|
+
const ascii = host.theme.glyphs.ascii;
|
|
77
|
+
let highlighted = points.at(-1)?.entryId;
|
|
78
|
+
let refreshing = false;
|
|
79
|
+
let closed = false;
|
|
80
|
+
const items = () => rewindListItems(points, cache, highlighted, host.now(), ascii);
|
|
81
|
+
const refresh = () => {
|
|
82
|
+
if (refreshing || closed)
|
|
83
|
+
return;
|
|
84
|
+
refreshing = true;
|
|
85
|
+
list.setItems(items());
|
|
86
|
+
refreshing = false;
|
|
87
|
+
host.render();
|
|
88
|
+
};
|
|
89
|
+
const close = (point) => {
|
|
90
|
+
closed = true;
|
|
91
|
+
handle.hide();
|
|
92
|
+
resolve(point);
|
|
93
|
+
};
|
|
94
|
+
const highlight = (entryId) => {
|
|
95
|
+
highlighted = entryId;
|
|
96
|
+
const point = points.find((p) => p.entryId === entryId);
|
|
97
|
+
if (point?.hasCheckpoint === true)
|
|
98
|
+
void cache.ensure(point.entryId).then(refresh);
|
|
99
|
+
refresh();
|
|
100
|
+
};
|
|
101
|
+
const list = new SelectList(items(), {
|
|
102
|
+
theme: host.theme,
|
|
103
|
+
maxVisible: 10,
|
|
104
|
+
filterable: points.length > 8,
|
|
105
|
+
...(host.keybindings !== undefined ? { keybindings: host.keybindings } : {}),
|
|
106
|
+
footer: PICKER_FOOTER.replace("↑↓", host.theme.glyphs.arrowUp + host.theme.glyphs.arrowDown),
|
|
107
|
+
onSelect: (item) => close(points.find((p) => p.entryId === item.value)),
|
|
108
|
+
onCancel: () => close(undefined),
|
|
109
|
+
onSelectionChange: (item) => {
|
|
110
|
+
if (!refreshing && item?.value !== highlighted)
|
|
111
|
+
highlight(item?.value);
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
if (highlighted !== undefined)
|
|
115
|
+
list.selectValue(highlighted);
|
|
116
|
+
const width = Math.max(20, Math.min(host.columns() - 2, 72));
|
|
117
|
+
const handle = host.showOverlay(new Box(list, { title: "回滚到哪条消息之前", theme: host.theme }), {
|
|
118
|
+
anchor: "center",
|
|
119
|
+
width,
|
|
120
|
+
});
|
|
121
|
+
highlight(highlighted);
|
|
122
|
+
});
|
|
123
|
+
}
|