@armadra/agent 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +174 -1
- package/README.md +201 -82
- package/THIRD_PARTY_NOTICES.md +34 -0
- package/dist/acp.d.ts +18 -0
- package/dist/acp.js +19 -0
- package/dist/agent/limits.d.ts +38 -0
- package/dist/agent/limits.js +127 -0
- package/dist/agent/loop-guard.d.ts +38 -0
- package/dist/agent/loop-guard.js +95 -0
- package/dist/agent/loop.d.ts +4 -0
- package/dist/agent/loop.js +7 -0
- package/dist/agent/prompt-rules.d.ts +12 -0
- package/dist/agent/prompt-rules.js +18 -0
- package/dist/agent/reminders.d.ts +59 -0
- package/dist/agent/reminders.js +327 -0
- package/dist/agent/session-cache.d.ts +5 -0
- package/dist/agent/session-cache.js +17 -1
- package/dist/agent/session-classifier.d.ts +1 -1
- package/dist/agent/session-classifier.js +3 -1
- package/dist/agent/session-compaction.d.ts +35 -6
- package/dist/agent/session-compaction.js +157 -31
- package/dist/agent/session-core.d.ts +27 -1
- package/dist/agent/session-extensions.d.ts +61 -0
- package/dist/agent/session-extensions.js +129 -0
- package/dist/agent/session-images.d.ts +23 -0
- package/dist/agent/session-images.js +97 -0
- package/dist/agent/session-plan.d.ts +21 -0
- package/dist/agent/session-plan.js +524 -0
- package/dist/agent/session-rewind.d.ts +81 -0
- package/dist/agent/session-rewind.js +354 -0
- package/dist/agent/session-run.d.ts +28 -1
- package/dist/agent/session-run.js +157 -6
- package/dist/agent/session-settings.d.ts +49 -0
- package/dist/agent/session-settings.js +95 -0
- package/dist/agent/session-subagent.d.ts +36 -24
- package/dist/agent/session-subagent.js +259 -129
- package/dist/agent/session-sync.d.ts +10 -3
- package/dist/agent/session-sync.js +37 -8
- package/dist/agent/session-telemetry.d.ts +39 -0
- package/dist/agent/session-telemetry.js +231 -0
- package/dist/agent/session-tools.js +40 -1
- package/dist/agent/session.d.ts +30 -29
- package/dist/agent/session.js +79 -123
- package/dist/agent/subagent-registry.d.ts +91 -0
- package/dist/agent/subagent-registry.js +494 -0
- package/dist/agent/system-prompt.d.ts +6 -3
- package/dist/agent/system-prompt.js +7 -2
- package/dist/agent/tool-runner.d.ts +8 -1
- package/dist/agent/tool-runner.js +57 -4
- package/dist/agent/types-w5.d.ts +192 -0
- package/dist/agent/types-w5.js +10 -0
- package/dist/agent/types.d.ts +47 -4
- package/dist/agent/types.js +2 -0
- package/dist/agent/worktree.d.ts +36 -0
- package/dist/agent/worktree.js +86 -0
- package/dist/agents/builtin.d.ts +14 -0
- package/dist/agents/builtin.js +39 -0
- package/dist/agents/catalog.d.ts +43 -0
- package/dist/agents/catalog.js +82 -0
- package/dist/agents/discover.d.ts +35 -0
- package/dist/agents/discover.js +83 -0
- package/dist/agents/external.d.ts +82 -0
- package/dist/agents/external.js +326 -0
- package/dist/agents/parse.d.ts +18 -0
- package/dist/agents/parse.js +116 -0
- package/dist/agents/result.d.ts +32 -0
- package/dist/agents/result.js +67 -0
- package/dist/agents/task-control.d.ts +17 -0
- package/dist/agents/task-control.js +17 -0
- package/dist/agents/task-record.d.ts +78 -0
- package/dist/agents/task-record.js +141 -0
- package/dist/agents/types.d.ts +46 -0
- package/dist/agents/types.js +8 -0
- package/dist/ai/apis/anthropic-compat.d.ts +36 -0
- package/dist/ai/apis/anthropic-compat.js +92 -0
- package/dist/ai/apis/anthropic-request.d.ts +7 -6
- package/dist/ai/apis/anthropic-request.js +10 -28
- package/dist/ai/apis/cache-params.d.ts +11 -2
- package/dist/ai/apis/cache-params.js +25 -6
- package/dist/ai/apis/openai-compat.d.ts +4 -1
- package/dist/ai/apis/openai-compat.js +8 -1
- package/dist/ai/image-limits.d.ts +45 -0
- package/dist/ai/image-limits.js +68 -0
- package/dist/ai/providers/builtin.d.ts +18 -6
- package/dist/ai/providers/builtin.js +135 -6
- package/dist/ai/providers/catalog-data.js +17 -13
- package/dist/ai/providers/catalog.d.ts +60 -7
- package/dist/ai/providers/catalog.js +197 -38
- package/dist/ai/providers/channels.d.ts +33 -3
- package/dist/ai/providers/channels.js +108 -7
- package/dist/ai/providers/enrich.d.ts +6 -3
- package/dist/ai/providers/enrich.js +19 -4
- package/dist/ai/providers/models-dev-cache.d.ts +28 -24
- package/dist/ai/providers/models-dev-cache.js +92 -78
- package/dist/ai/providers/models-dev-data.d.ts +7 -0
- package/dist/ai/providers/models-dev-data.js +32 -0
- package/dist/ai/providers/models-dev-snapshot.d.ts +50 -0
- package/dist/ai/providers/models-dev-snapshot.js +137 -0
- package/dist/ai/providers/models-dev.d.ts +51 -10
- package/dist/ai/providers/models-dev.js +132 -39
- package/dist/ai/providers/registry.d.ts +20 -10
- package/dist/ai/providers/registry.js +82 -43
- package/dist/ai/types.d.ts +28 -2
- package/dist/ai/types.js +5 -0
- package/dist/bundle/ama.cjs +36203 -20499
- package/dist/checkpoints/backend.d.ts +61 -0
- package/dist/checkpoints/backend.js +135 -0
- package/dist/checkpoints/blobs.d.ts +60 -0
- package/dist/checkpoints/blobs.js +203 -0
- package/dist/checkpoints/gc.d.ts +47 -0
- package/dist/checkpoints/gc.js +144 -0
- package/dist/checkpoints/git-head.d.ts +15 -0
- package/dist/checkpoints/git-head.js +89 -0
- package/dist/checkpoints/index.d.ts +17 -0
- package/dist/checkpoints/index.js +17 -0
- package/dist/checkpoints/replay.d.ts +48 -0
- package/dist/checkpoints/replay.js +154 -0
- package/dist/checkpoints/restore.d.ts +86 -0
- package/dist/checkpoints/restore.js +263 -0
- package/dist/checkpoints/settings.d.ts +14 -0
- package/dist/checkpoints/settings.js +23 -0
- package/dist/checkpoints/shadow-git.d.ts +108 -0
- package/dist/checkpoints/shadow-git.js +491 -0
- package/dist/checkpoints/shadow-restore.d.ts +25 -0
- package/dist/checkpoints/shadow-restore.js +128 -0
- package/dist/checkpoints/tracker.d.ts +64 -0
- package/dist/checkpoints/tracker.js +192 -0
- package/dist/checkpoints/types.d.ts +99 -0
- package/dist/checkpoints/types.js +12 -0
- package/dist/cli/args.d.ts +8 -4
- package/dist/cli/args.js +17 -97
- package/dist/cli/bootstrap.js +13 -1
- package/dist/cli/codemode-notice.d.ts +3 -2
- package/dist/cli/codemode-notice.js +3 -2
- package/dist/cli/compose-agents.d.ts +27 -0
- package/dist/cli/compose-agents.js +111 -0
- package/dist/cli/compose-extensions.d.ts +29 -0
- package/dist/cli/compose-extensions.js +44 -0
- package/dist/cli/compose-session.d.ts +3 -0
- package/dist/cli/compose-session.js +47 -4
- package/dist/cli/compose.d.ts +3 -0
- package/dist/cli/compose.js +33 -6
- package/dist/cli/deps.d.ts +6 -0
- package/dist/cli/exit-codes.d.ts +10 -0
- package/dist/cli/exit-codes.js +12 -0
- package/dist/cli/help-text.d.ts +4 -0
- package/dist/cli/help-text.js +102 -0
- package/dist/cli/startup-screen.js +5 -3
- package/dist/cli/startup-steps.js +7 -1
- package/dist/cli/subcommands/config.d.ts +4 -1
- package/dist/cli/subcommands/config.js +17 -6
- package/dist/cli/subcommands/doctor.js +21 -0
- package/dist/cli/subcommands/models-discover.js +5 -6
- package/dist/cli/subcommands/models.d.ts +2 -0
- package/dist/cli/subcommands/models.js +33 -14
- package/dist/cli/subcommands/providers.js +5 -6
- package/dist/cli/subcommands/sessions.d.ts +3 -1
- package/dist/cli/subcommands/sessions.js +36 -2
- package/dist/codemode/capability.d.ts +24 -7
- package/dist/codemode/capability.js +38 -10
- package/dist/codemode/host-side.d.ts +14 -0
- package/dist/codemode/host-side.js +24 -1
- package/dist/codemode/tool.d.ts +1 -1
- package/dist/codemode/tool.js +6 -4
- package/dist/compaction/breaker.d.ts +25 -9
- package/dist/compaction/breaker.js +47 -17
- package/dist/compaction/estimate.d.ts +11 -3
- package/dist/compaction/estimate.js +64 -22
- package/dist/compaction/image-budget.d.ts +45 -0
- package/dist/compaction/image-budget.js +115 -0
- package/dist/compaction/post-compact.d.ts +38 -0
- package/dist/compaction/post-compact.js +152 -0
- package/dist/compaction/protect.d.ts +27 -0
- package/dist/compaction/protect.js +56 -0
- package/dist/compaction/prune-tier.d.ts +58 -12
- package/dist/compaction/prune-tier.js +120 -54
- package/dist/compaction/summarize-tier.d.ts +23 -4
- package/dist/compaction/summarize-tier.js +100 -29
- package/dist/config/checker.d.ts +28 -0
- package/dist/config/checker.js +97 -0
- package/dist/config/json-schema.js +63 -2
- package/dist/config/key-docs.js +72 -3
- package/dist/config/merge.d.ts +5 -3
- package/dist/config/merge.js +81 -7
- package/dist/config/profile.d.ts +2 -0
- package/dist/config/profile.js +2 -0
- package/dist/config/schema-w5.d.ts +18 -0
- package/dist/config/schema-w5.js +109 -0
- package/dist/config/schema.d.ts +5 -9
- package/dist/config/schema.js +68 -114
- package/dist/config/types-w5.d.ts +118 -0
- package/dist/config/types-w5.js +20 -0
- package/dist/config/types.d.ts +50 -1
- package/dist/config/types.js +12 -0
- package/dist/drivers/acp/client.d.ts +57 -0
- package/dist/drivers/acp/client.js +160 -0
- package/dist/drivers/acp/driver.d.ts +31 -0
- package/dist/drivers/acp/driver.js +274 -0
- package/dist/drivers/acp/testing/fake-agent-main.d.ts +5 -0
- package/dist/drivers/acp/testing/fake-agent-main.js +7 -0
- package/dist/drivers/acp/testing/fake-agent.d.ts +27 -0
- package/dist/drivers/acp/testing/fake-agent.js +211 -0
- package/dist/drivers/acp/types.d.ts +285 -0
- package/dist/drivers/acp/types.js +36 -0
- package/dist/drivers/agents.d.ts +58 -0
- package/dist/drivers/agents.js +142 -0
- package/dist/drivers/base.d.ts +35 -0
- package/dist/drivers/base.js +59 -0
- package/dist/drivers/catalog.d.ts +46 -0
- package/dist/drivers/catalog.js +167 -0
- package/dist/drivers/env.d.ts +20 -0
- package/dist/drivers/env.js +46 -0
- package/dist/drivers/host-runners.d.ts +18 -0
- package/dist/drivers/host-runners.js +45 -0
- package/dist/drivers/jsonrpc.d.ts +58 -0
- package/dist/drivers/jsonrpc.js +180 -0
- package/dist/drivers/native/claude-normalize.d.ts +46 -0
- package/dist/drivers/native/claude-normalize.js +106 -0
- package/dist/drivers/native/claude-stream.d.ts +29 -0
- package/dist/drivers/native/claude-stream.js +456 -0
- package/dist/drivers/native/codex-app-server.d.ts +26 -0
- package/dist/drivers/native/codex-app-server.js +407 -0
- package/dist/drivers/native/codex-normalize.d.ts +38 -0
- package/dist/drivers/native/codex-normalize.js +124 -0
- package/dist/drivers/native/oneshot.d.ts +28 -0
- package/dist/drivers/native/oneshot.js +312 -0
- package/dist/drivers/permissions.d.ts +40 -0
- package/dist/drivers/permissions.js +92 -0
- package/dist/drivers/pids.d.ts +32 -0
- package/dist/drivers/pids.js +93 -0
- package/dist/drivers/pool.d.ts +28 -0
- package/dist/drivers/pool.js +96 -0
- package/dist/drivers/probe.d.ts +47 -0
- package/dist/drivers/probe.js +172 -0
- package/dist/drivers/process.d.ts +48 -0
- package/dist/drivers/process.js +100 -0
- package/dist/drivers/runner.d.ts +61 -0
- package/dist/drivers/runner.js +388 -0
- package/dist/drivers/store.d.ts +49 -0
- package/dist/drivers/store.js +91 -0
- package/dist/drivers/turn.d.ts +41 -0
- package/dist/drivers/turn.js +99 -0
- package/dist/drivers/types.d.ts +122 -0
- package/dist/drivers/types.js +11 -0
- package/dist/git/info.d.ts +75 -0
- package/dist/git/info.js +191 -0
- package/dist/hooks/protocol.js +6 -1
- package/dist/hooks/types.d.ts +10 -1
- package/dist/hooks/types.js +2 -0
- package/dist/host/api-impl.d.ts +7 -0
- package/dist/host/api-impl.js +15 -0
- package/dist/host/types.d.ts +24 -2
- package/dist/host/types.js +4 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/modes/acp/acp-events.d.ts +46 -0
- package/dist/modes/acp/acp-events.js +233 -0
- package/dist/modes/acp/acp-mode.d.ts +17 -0
- package/dist/modes/acp/acp-mode.js +47 -0
- package/dist/modes/acp/acp-server.d.ts +79 -0
- package/dist/modes/acp/acp-server.js +315 -0
- package/dist/modes/commands-core.d.ts +7 -1
- package/dist/modes/commands-core.js +55 -0
- package/dist/modes/image-input.d.ts +12 -4
- package/dist/modes/image-input.js +22 -5
- package/dist/modes/interactive/agent-panels.d.ts +14 -0
- package/dist/modes/interactive/agent-panels.js +103 -0
- package/dist/modes/interactive/agent-ui.d.ts +73 -0
- package/dist/modes/interactive/agent-ui.js +234 -0
- package/dist/modes/interactive/approval-dialog.d.ts +21 -4
- package/dist/modes/interactive/approval-dialog.js +98 -20
- package/dist/modes/interactive/approval-merge.d.ts +41 -0
- package/dist/modes/interactive/approval-merge.js +89 -0
- package/dist/modes/interactive/clipboard-paste.d.ts +18 -0
- package/dist/modes/interactive/clipboard-paste.js +28 -0
- package/dist/modes/interactive/commands.d.ts +9 -1
- package/dist/modes/interactive/commands.js +19 -0
- package/dist/modes/interactive/double-esc.d.ts +20 -0
- package/dist/modes/interactive/double-esc.js +34 -0
- package/dist/modes/interactive/event-notices.d.ts +32 -0
- package/dist/modes/interactive/event-notices.js +79 -0
- package/dist/modes/interactive/external-editor.d.ts +16 -0
- package/dist/modes/interactive/external-editor.js +39 -0
- package/dist/modes/interactive/interactive-mode.d.ts +14 -1
- package/dist/modes/interactive/interactive-mode.js +134 -136
- package/dist/modes/interactive/key-dispatch.d.ts +16 -2
- package/dist/modes/interactive/key-dispatch.js +49 -1
- package/dist/modes/interactive/line/line-mode.d.ts +2 -1
- package/dist/modes/interactive/line/line-mode.js +22 -5
- package/dist/modes/interactive/line/line-render.d.ts +2 -1
- package/dist/modes/interactive/line/line-render.js +40 -4
- package/dist/modes/interactive/message-view.d.ts +1 -1
- package/dist/modes/interactive/message-view.js +24 -2
- package/dist/modes/interactive/panels.d.ts +18 -1
- package/dist/modes/interactive/panels.js +19 -5
- package/dist/modes/interactive/plan-command.d.ts +40 -0
- package/dist/modes/interactive/plan-command.js +129 -0
- package/dist/modes/interactive/plan-dialog.d.ts +98 -0
- package/dist/modes/interactive/plan-dialog.js +290 -0
- package/dist/modes/interactive/plan-flow.d.ts +34 -0
- package/dist/modes/interactive/plan-flow.js +98 -0
- package/dist/modes/interactive/rewind-command.d.ts +31 -0
- package/dist/modes/interactive/rewind-command.js +106 -0
- package/dist/modes/interactive/rewind-flow.d.ts +37 -0
- package/dist/modes/interactive/rewind-flow.js +151 -0
- package/dist/modes/interactive/rewind-list.d.ts +36 -0
- package/dist/modes/interactive/rewind-list.js +123 -0
- package/dist/modes/interactive/rewind-panel.d.ts +77 -0
- package/dist/modes/interactive/rewind-panel.js +309 -0
- package/dist/modes/interactive/rewind-text.d.ts +40 -0
- package/dist/modes/interactive/rewind-text.js +139 -0
- package/dist/modes/interactive/session-events.d.ts +24 -0
- package/dist/modes/interactive/session-events.js +96 -0
- package/dist/modes/interactive/status-area.d.ts +73 -0
- package/dist/modes/interactive/status-area.js +190 -0
- package/dist/modes/interactive/status-bar.d.ts +99 -11
- package/dist/modes/interactive/status-bar.js +273 -90
- package/dist/modes/interactive/status-line.d.ts +33 -0
- package/dist/modes/interactive/status-line.js +113 -0
- package/dist/modes/interactive/subagent-view.d.ts +56 -0
- package/dist/modes/interactive/subagent-view.js +154 -0
- package/dist/modes/interactive/tasks-report.d.ts +27 -0
- package/dist/modes/interactive/tasks-report.js +114 -0
- package/dist/modes/interactive/tool-view.d.ts +12 -2
- package/dist/modes/interactive/tool-view.js +34 -4
- package/dist/modes/print/print-mode.d.ts +13 -4
- package/dist/modes/print/print-mode.js +56 -12
- package/dist/modes/rpc/commands.d.ts +9 -0
- package/dist/modes/rpc/commands.js +44 -0
- package/dist/modes/rpc/rpc-mode.js +7 -1
- package/dist/modes/session-report.d.ts +11 -0
- package/dist/modes/session-report.js +48 -1
- package/dist/permissions/auto-safe.d.ts +5 -0
- package/dist/permissions/auto-safe.js +18 -0
- package/dist/permissions/classifier.d.ts +4 -0
- package/dist/permissions/classifier.js +2 -0
- package/dist/permissions/modes.js +1 -1
- package/dist/permissions/pipeline.d.ts +43 -4
- package/dist/permissions/pipeline.js +114 -9
- package/dist/permissions/readonly-bash.d.ts +30 -0
- package/dist/permissions/readonly-bash.js +118 -0
- package/dist/permissions/types.d.ts +42 -0
- package/dist/plan/compose.d.ts +9 -0
- package/dist/plan/compose.js +19 -0
- package/dist/plan/controller.d.ts +71 -0
- package/dist/plan/controller.js +27 -0
- package/dist/plan/done-markers.d.ts +17 -0
- package/dist/plan/done-markers.js +51 -0
- package/dist/plan/extract.d.ts +29 -0
- package/dist/plan/extract.js +160 -0
- package/dist/plan/prompts.d.ts +36 -0
- package/dist/plan/prompts.js +89 -0
- package/dist/plan/store.d.ts +37 -0
- package/dist/plan/store.js +90 -0
- package/dist/rpc.d.ts +58 -2
- package/dist/rpc.js +7 -0
- package/dist/sandbox/bash.d.ts +74 -0
- package/dist/sandbox/bash.js +126 -0
- package/dist/sandbox/detect.d.ts +48 -0
- package/dist/sandbox/detect.js +149 -0
- package/dist/sandbox/index.d.ts +5 -0
- package/dist/sandbox/index.js +5 -0
- package/dist/sandbox/profile.d.ts +33 -0
- package/dist/sandbox/profile.js +76 -0
- package/dist/sandbox/wrap.d.ts +29 -0
- package/dist/sandbox/wrap.js +117 -0
- package/dist/sdk.d.ts +33 -2
- package/dist/sdk.js +24 -2
- package/dist/session/types.d.ts +3 -1
- package/dist/session/types.js +1 -0
- package/dist/skills/builtin.d.ts +31 -0
- package/dist/skills/builtin.js +109 -0
- package/dist/skills/discover.d.ts +2 -1
- package/dist/skills/index-prompt.js +5 -8
- package/dist/tools/background-jobs.d.ts +71 -0
- package/dist/tools/background-jobs.js +198 -0
- package/dist/tools/bash.d.ts +53 -1
- package/dist/tools/bash.js +158 -7
- package/dist/tools/clipboard-image.d.ts +44 -0
- package/dist/tools/clipboard-image.js +148 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.js +18 -3
- package/dist/tools/image-file.d.ts +38 -3
- package/dist/tools/image-file.js +81 -10
- package/dist/tools/image-resize.d.ts +58 -0
- package/dist/tools/image-resize.js +97 -0
- package/dist/tools/presets.d.ts +7 -2
- package/dist/tools/presets.js +11 -4
- package/dist/tools/read.d.ts +5 -2
- package/dist/tools/read.js +13 -10
- package/dist/tools/registry.d.ts +7 -1
- package/dist/tools/registry.js +27 -4
- package/dist/tools/task-ctl.d.ts +22 -0
- package/dist/tools/task-ctl.js +116 -0
- package/dist/tools/task.d.ts +22 -10
- package/dist/tools/task.js +66 -26
- package/dist/tools/todo.d.ts +22 -2
- package/dist/tools/todo.js +58 -14
- package/dist/tools/truncate.d.ts +15 -0
- package/dist/tools/truncate.js +25 -0
- package/dist/tools/types.d.ts +113 -0
- package/dist/tools/types.js +5 -0
- package/dist/tools/write.js +3 -0
- package/dist/tui/glyphs.d.ts +4 -0
- package/dist/tui/glyphs.js +4 -0
- package/dist/tui/keybindings.d.ts +5 -0
- package/dist/tui/keybindings.js +5 -0
- package/docs/acp.md +78 -0
- package/docs/agents.md +250 -0
- package/docs/codemode.md +12 -8
- package/docs/hooks.md +26 -22
- package/docs/permissions.md +77 -13
- package/docs/plan.md +107 -0
- package/docs/providers.md +228 -52
- package/docs/rewind-plan.md +181 -0
- package/docs/rpc.md +92 -5
- package/docs/sandbox.md +215 -0
- package/docs/session-format.md +41 -21
- package/docs/sessions.md +41 -1
- package/docs/tui-design.md +751 -0
- package/docs/tui.md +125 -6
- package/package.json +13 -2
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 统一提醒通道 `ama.reminder`(docs/wave5-plan.md §8.3 H3,D29)。[W5-H2]
|
|
3
|
+
*
|
|
4
|
+
* 以 `SessionExtension` 实现,两个投递点,都只追加在尾部(design §9.1,缓存前缀不动):
|
|
5
|
+
* - **新提示**:`beforePrompts` 追加一条 `custom_message{customType:"ama.reminder", display:false}`;
|
|
6
|
+
* - **run 进行中**:在 agent_start 时以本 run 的 signal 登记批次尾部来源(tool-runner.ts
|
|
7
|
+
* `setBatchSuffixSource`),每个工具批次结束时把到期提醒追加在本批最后一条结果末尾
|
|
8
|
+
* (`<system-reminder>` 包起来)。不用 steer 队列:那会占用户的投递位、Esc 时还会被回填进编辑器。
|
|
9
|
+
*
|
|
10
|
+
* 提醒种类(`reminders.*` 逐项可关,缺省全开):
|
|
11
|
+
* 1. `todo`:todo 工具在活动集、清单有未完成项、连续 `todo.reminder`(缺省 10,0 关闭)次助手回复
|
|
12
|
+
* 没更新清单(`ama.todo` 条目)→ 复述清单,计数清零;
|
|
13
|
+
* 2. `fileChanges`:本会话 read / edit / write 过的文件 mtime 或大小变了(不是本 Agent 的编辑或 bash
|
|
14
|
+
* 改的:这些之后重新取基线)→ 列出 ≤ 10 个,附 `git diff --stat`(拿得到时);
|
|
15
|
+
* 3. `contextPressure`:上下文估算(compaction/estimate.ts 的口径)到窗口 70% / 85% 各一次,
|
|
16
|
+
* 压缩后回落再重新计;
|
|
17
|
+
* 4. `budget`:limits 的回合或费用用掉 ≥ 80%(剩余 < 20%)时每次运行各一次;
|
|
18
|
+
* 5. 后台命令退出(不可关):`bash{background}` 的任务退出且模型还没经 wait / output 看到 →
|
|
19
|
+
* 「后台命令 bgN 已退出(码 N)」。
|
|
20
|
+
*
|
|
21
|
+
* 后台任务表的生命周期也挂在这里:任务事件转成 `background_job`,会话 dispose 时回收进程树。
|
|
22
|
+
* task 子会话(depth > 0)只装后台任务部分。
|
|
23
|
+
*/
|
|
24
|
+
import { execFileSync } from "node:child_process";
|
|
25
|
+
import { statSync } from "node:fs";
|
|
26
|
+
import { resolve } from "node:path";
|
|
27
|
+
import { estimateProjectedTokens } from "../compaction/estimate.js";
|
|
28
|
+
import { buildProjection } from "../session/projection.js";
|
|
29
|
+
import { disposeSessionJobs, jobsForSession } from "../tools/background-jobs.js";
|
|
30
|
+
import { TODO_CUSTOM_TYPE, parseTodoState, renderTodoList } from "../tools/todo.js";
|
|
31
|
+
import { budgetOf } from "./limits.js";
|
|
32
|
+
import { setBatchSuffixSource } from "./tool-runner.js";
|
|
33
|
+
export const REMINDER_CUSTOM_TYPE = "ama.reminder";
|
|
34
|
+
export const DEFAULT_TODO_REMINDER_TURNS = 10;
|
|
35
|
+
export const CONTEXT_REMINDER_RATIOS = [0.7, 0.85];
|
|
36
|
+
export const BUDGET_REMINDER_RATIO = 0.8;
|
|
37
|
+
export const MAX_CHANGED_FILES = 10;
|
|
38
|
+
/** config → 提醒设置(`reminders.*` 与 `todo.reminder`)。 */
|
|
39
|
+
export function remindersSettings(config) {
|
|
40
|
+
const settings = {};
|
|
41
|
+
if (config.reminders !== undefined)
|
|
42
|
+
settings.reminders = config.reminders;
|
|
43
|
+
if (config.todo?.reminder !== undefined)
|
|
44
|
+
settings.todoEvery = config.todo.reminder;
|
|
45
|
+
return settings;
|
|
46
|
+
}
|
|
47
|
+
const FILE_TOOLS = new Set(["read", "edit", "write"]);
|
|
48
|
+
function defaultStat(path) {
|
|
49
|
+
try {
|
|
50
|
+
const info = statSync(path);
|
|
51
|
+
return { mtimeMs: info.mtimeMs, size: info.size };
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function defaultDiffStat(cwd, files) {
|
|
58
|
+
try {
|
|
59
|
+
const out = execFileSync("git", ["diff", "--stat", "--", ...files], {
|
|
60
|
+
cwd,
|
|
61
|
+
encoding: "utf8",
|
|
62
|
+
timeout: 2000,
|
|
63
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
64
|
+
windowsHide: true,
|
|
65
|
+
}).trim();
|
|
66
|
+
return out === "" ? undefined : out;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function lastTodo(branch) {
|
|
73
|
+
for (let i = branch.length - 1; i >= 0; i--) {
|
|
74
|
+
const entry = branch[i];
|
|
75
|
+
if (entry?.type === "custom" && entry.customType === TODO_CUSTOM_TYPE)
|
|
76
|
+
return parseTodoState(entry.data);
|
|
77
|
+
}
|
|
78
|
+
return parseTodoState(undefined);
|
|
79
|
+
}
|
|
80
|
+
function wrap(lines) {
|
|
81
|
+
return `<system-reminder>\n${lines.join("\n\n")}\n</system-reminder>`;
|
|
82
|
+
}
|
|
83
|
+
function argPath(args) {
|
|
84
|
+
if (typeof args !== "object" || args === null)
|
|
85
|
+
return undefined;
|
|
86
|
+
const path = args.path;
|
|
87
|
+
return typeof path === "string" && path !== "" ? path : undefined;
|
|
88
|
+
}
|
|
89
|
+
class Reminders {
|
|
90
|
+
core;
|
|
91
|
+
on;
|
|
92
|
+
todoEvery;
|
|
93
|
+
stat;
|
|
94
|
+
diffStat;
|
|
95
|
+
/** 自上次更新 todo 以来的助手回复数。 */
|
|
96
|
+
sinceTodo = 0;
|
|
97
|
+
/** 已提醒过的上下文档位(压缩后回落再清)。 */
|
|
98
|
+
contextFired = new Set();
|
|
99
|
+
/** 本次运行已提醒的预算类别。 */
|
|
100
|
+
budgetFired = new Set();
|
|
101
|
+
/** 文件基线:绝对路径 → mtime / 大小。 */
|
|
102
|
+
baseline = new Map();
|
|
103
|
+
/** toolCallId → 文件工具的绝对路径。 */
|
|
104
|
+
pendingPaths = new Map();
|
|
105
|
+
constructor(core, settings, deps) {
|
|
106
|
+
this.core = core;
|
|
107
|
+
const r = settings.reminders ?? {};
|
|
108
|
+
this.on = {
|
|
109
|
+
todo: r.todo ?? true,
|
|
110
|
+
fileChanges: r.fileChanges ?? true,
|
|
111
|
+
contextPressure: r.contextPressure ?? true,
|
|
112
|
+
budget: r.budget ?? true,
|
|
113
|
+
};
|
|
114
|
+
this.todoEvery = settings.todoEvery ?? DEFAULT_TODO_REMINDER_TURNS;
|
|
115
|
+
this.stat = deps.stat ?? defaultStat;
|
|
116
|
+
this.diffStat = deps.diffStat ?? defaultDiffStat;
|
|
117
|
+
}
|
|
118
|
+
onEvent(event) {
|
|
119
|
+
switch (event.type) {
|
|
120
|
+
case "before_agent_start":
|
|
121
|
+
this.budgetFired.clear();
|
|
122
|
+
return;
|
|
123
|
+
case "agent_start": {
|
|
124
|
+
const signal = this.core.agent.signal;
|
|
125
|
+
if (signal !== undefined)
|
|
126
|
+
setBatchSuffixSource(signal, () => this.collect(true));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
case "message_end":
|
|
130
|
+
if (event.message.role === "assistant" &&
|
|
131
|
+
event.message.stopReason !== "error" &&
|
|
132
|
+
event.message.stopReason !== "aborted")
|
|
133
|
+
this.sinceTodo++;
|
|
134
|
+
return;
|
|
135
|
+
case "entry_appended":
|
|
136
|
+
if (event.entry.type === "custom" && event.entry.customType === TODO_CUSTOM_TYPE)
|
|
137
|
+
this.sinceTodo = 0;
|
|
138
|
+
return;
|
|
139
|
+
case "compaction_end":
|
|
140
|
+
this.rearmContext();
|
|
141
|
+
return;
|
|
142
|
+
case "tool_execution_start": {
|
|
143
|
+
if (event.parentToolCallId !== undefined || !FILE_TOOLS.has(event.toolName))
|
|
144
|
+
return;
|
|
145
|
+
const path = argPath(event.args);
|
|
146
|
+
if (path !== undefined)
|
|
147
|
+
this.pendingPaths.set(event.toolCallId, resolve(this.core.cwd, path));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
case "tool_execution_end": {
|
|
151
|
+
const path = this.pendingPaths.get(event.toolCallId);
|
|
152
|
+
this.pendingPaths.delete(event.toolCallId);
|
|
153
|
+
if (path !== undefined && !event.isError)
|
|
154
|
+
this.baseline.set(path, this.stat(path));
|
|
155
|
+
// 本 Agent 自己的 bash 改动模型知道:重新取基线,只报其余来源的改动
|
|
156
|
+
else if (event.toolName === "bash" && event.parentToolCallId === undefined)
|
|
157
|
+
this.rebaseline();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
default:
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/** 到期提醒的正文(没有返回 undefined);`inRun` = 工具批次尾部(预算提醒只在 run 中有意义)。 */
|
|
165
|
+
collect(inRun) {
|
|
166
|
+
const lines = [];
|
|
167
|
+
const jobs = this.jobLines();
|
|
168
|
+
const todo = this.todoLine();
|
|
169
|
+
const files = this.fileLine();
|
|
170
|
+
const context = this.contextLine();
|
|
171
|
+
const budget = inRun ? this.budgetLine() : undefined;
|
|
172
|
+
for (const line of [jobs, todo, files, context, budget])
|
|
173
|
+
if (line !== undefined)
|
|
174
|
+
lines.push(line);
|
|
175
|
+
return lines.length === 0 ? undefined : wrap(lines);
|
|
176
|
+
}
|
|
177
|
+
jobLines() {
|
|
178
|
+
const exited = jobsForSession(this.core.manager.id).takeExited();
|
|
179
|
+
if (exited.length === 0)
|
|
180
|
+
return undefined;
|
|
181
|
+
return exited.map((job) => jobExitText(job)).join("\n");
|
|
182
|
+
}
|
|
183
|
+
todoLine() {
|
|
184
|
+
if (!this.on.todo || this.todoEvery <= 0 || this.sinceTodo < this.todoEvery)
|
|
185
|
+
return undefined;
|
|
186
|
+
if (this.core.activeTool("todo") === undefined)
|
|
187
|
+
return undefined;
|
|
188
|
+
const { items } = lastTodo(this.core.manager.branch());
|
|
189
|
+
if (!items.some((item) => item.status !== "done"))
|
|
190
|
+
return undefined;
|
|
191
|
+
const turns = this.sinceTodo;
|
|
192
|
+
this.sinceTodo = 0;
|
|
193
|
+
return (`The todo list has not been updated in the last ${turns} replies and still has open items:\n` +
|
|
194
|
+
`${renderTodoList(items).join("\n")}\n` +
|
|
195
|
+
"If you made progress, update it (todo update); otherwise keep going. Do not mention this reminder.");
|
|
196
|
+
}
|
|
197
|
+
fileLine() {
|
|
198
|
+
if (!this.on.fileChanges || this.baseline.size === 0)
|
|
199
|
+
return undefined;
|
|
200
|
+
const changed = [];
|
|
201
|
+
for (const [path, before] of this.baseline) {
|
|
202
|
+
const now = this.stat(path);
|
|
203
|
+
if (before?.mtimeMs === now?.mtimeMs && before?.size === now?.size)
|
|
204
|
+
continue;
|
|
205
|
+
this.baseline.set(path, now);
|
|
206
|
+
changed.push(now === undefined ? `${path} (deleted)` : path);
|
|
207
|
+
}
|
|
208
|
+
if (changed.length === 0)
|
|
209
|
+
return undefined;
|
|
210
|
+
const shown = changed.slice(0, MAX_CHANGED_FILES);
|
|
211
|
+
const more = changed.length > shown.length ? `\n…and ${changed.length - shown.length} more` : "";
|
|
212
|
+
const existing = shown.filter((p) => !p.endsWith(" (deleted)"));
|
|
213
|
+
const stat = existing.length > 0 ? this.diffStat(this.core.cwd, existing) : undefined;
|
|
214
|
+
return ("These files changed outside your own edits since you last read them; re-read before editing:\n" +
|
|
215
|
+
`${shown.map((p) => `- ${p}`).join("\n")}${more}` +
|
|
216
|
+
(stat === undefined ? "" : `\ngit diff --stat:\n${stat}`));
|
|
217
|
+
}
|
|
218
|
+
contextLine() {
|
|
219
|
+
if (!this.on.contextPressure)
|
|
220
|
+
return undefined;
|
|
221
|
+
const window = this.core.model().contextWindow;
|
|
222
|
+
if (window === undefined || window <= 0)
|
|
223
|
+
return undefined;
|
|
224
|
+
const ratio = this.usedTokens() / window;
|
|
225
|
+
let fired;
|
|
226
|
+
for (const level of CONTEXT_REMINDER_RATIOS)
|
|
227
|
+
if (ratio >= level && !this.contextFired.has(level))
|
|
228
|
+
fired = level;
|
|
229
|
+
if (fired === undefined)
|
|
230
|
+
return undefined;
|
|
231
|
+
for (const level of CONTEXT_REMINDER_RATIOS)
|
|
232
|
+
if (level <= fired)
|
|
233
|
+
this.contextFired.add(level);
|
|
234
|
+
const pct = Math.round(ratio * 100);
|
|
235
|
+
return fired >= 0.85
|
|
236
|
+
? `Context is ${pct}% full. Finish the current step soon and write down progress and next steps (todo or a notes file); older history will be compacted.`
|
|
237
|
+
: `Context is ${pct}% full. Prefer targeted reads and keep notes of key findings; older history will be compacted when it fills up.`;
|
|
238
|
+
}
|
|
239
|
+
budgetLine() {
|
|
240
|
+
if (!this.on.budget)
|
|
241
|
+
return undefined;
|
|
242
|
+
const budget = budgetOf(this.core);
|
|
243
|
+
if (budget === undefined)
|
|
244
|
+
return undefined;
|
|
245
|
+
const parts = [];
|
|
246
|
+
const { maxTurns, maxCostUsd } = budget;
|
|
247
|
+
if (maxTurns !== undefined &&
|
|
248
|
+
!this.budgetFired.has("turns") &&
|
|
249
|
+
budget.turns >= maxTurns * BUDGET_REMINDER_RATIO) {
|
|
250
|
+
this.budgetFired.add("turns");
|
|
251
|
+
parts.push(`${budget.turns} of ${maxTurns} turns`);
|
|
252
|
+
}
|
|
253
|
+
if (maxCostUsd !== undefined &&
|
|
254
|
+
!this.budgetFired.has("cost") &&
|
|
255
|
+
budget.spentUsd >= maxCostUsd * BUDGET_REMINDER_RATIO) {
|
|
256
|
+
this.budgetFired.add("cost");
|
|
257
|
+
parts.push(`$${budget.spentUsd.toFixed(2)} of the $${maxCostUsd.toFixed(2)} budget`);
|
|
258
|
+
}
|
|
259
|
+
if (parts.length === 0)
|
|
260
|
+
return undefined;
|
|
261
|
+
return `This run has used ${parts.join(" and ")}. Wrap up: finish the most important part and report what is left.`;
|
|
262
|
+
}
|
|
263
|
+
usedTokens() {
|
|
264
|
+
const branch = this.core.manager.branch();
|
|
265
|
+
return estimateProjectedTokens(buildProjection(branch).items, branch).tokens;
|
|
266
|
+
}
|
|
267
|
+
rearmContext() {
|
|
268
|
+
const window = this.core.model().contextWindow;
|
|
269
|
+
if (window === undefined || window <= 0)
|
|
270
|
+
return;
|
|
271
|
+
const ratio = this.usedTokens() / window;
|
|
272
|
+
for (const level of CONTEXT_REMINDER_RATIOS)
|
|
273
|
+
if (ratio < level)
|
|
274
|
+
this.contextFired.delete(level);
|
|
275
|
+
}
|
|
276
|
+
rebaseline() {
|
|
277
|
+
for (const path of this.baseline.keys())
|
|
278
|
+
this.baseline.set(path, this.stat(path));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
export function jobExitText(job) {
|
|
282
|
+
const how = job.status === "stopped" ? "was stopped" : `exited with code ${job.exitCode ?? "unknown"}`;
|
|
283
|
+
return `Background job ${job.id} (\`${job.command}\`) ${how}; output: ${job.outputPath} (bash {"job":"${job.id}","action":"output"}).`;
|
|
284
|
+
}
|
|
285
|
+
export function reminderMessage(text) {
|
|
286
|
+
return {
|
|
287
|
+
role: "custom",
|
|
288
|
+
customType: REMINDER_CUSTOM_TYPE,
|
|
289
|
+
content: text,
|
|
290
|
+
display: false,
|
|
291
|
+
timestamp: Date.now(),
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* 提醒扩展。主会话:全部提醒 + 后台任务生命周期;子会话:只管后台任务(事件与回收)。
|
|
296
|
+
*/
|
|
297
|
+
export function createRemindersExtension(core, settings = {}, deps = {}) {
|
|
298
|
+
const sessionId = core.manager.id;
|
|
299
|
+
const jobs = jobsForSession(sessionId);
|
|
300
|
+
const offJobs = jobs.onChange(({ phase, job }) => {
|
|
301
|
+
core.emit({
|
|
302
|
+
type: "background_job",
|
|
303
|
+
jobId: job.id,
|
|
304
|
+
phase,
|
|
305
|
+
command: job.command,
|
|
306
|
+
...(job.pid === undefined ? {} : { pid: job.pid }),
|
|
307
|
+
outputPath: job.outputPath,
|
|
308
|
+
...(phase === "started" ? {} : { exitCode: job.exitCode ?? null }),
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
const dispose = () => {
|
|
312
|
+
offJobs();
|
|
313
|
+
void disposeSessionJobs(sessionId);
|
|
314
|
+
};
|
|
315
|
+
if (core.depth > 0)
|
|
316
|
+
return { id: "reminders", dispose };
|
|
317
|
+
const reminders = new Reminders(core, settings, deps);
|
|
318
|
+
return {
|
|
319
|
+
id: "reminders",
|
|
320
|
+
onEvent: (event) => reminders.onEvent(event),
|
|
321
|
+
beforePrompts() {
|
|
322
|
+
const text = reminders.collect(false);
|
|
323
|
+
return text === undefined ? [] : [reminderMessage(text)];
|
|
324
|
+
},
|
|
325
|
+
dispose,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
@@ -81,6 +81,11 @@ export declare class SessionCacheController {
|
|
|
81
81
|
tokens?: number | undefined;
|
|
82
82
|
window?: number | undefined;
|
|
83
83
|
}): SessionCacheStats;
|
|
84
|
+
/**
|
|
85
|
+
* [W5-H1] 缓存是否已冷(wave5 §8.2 C3):上一次请求(含保温)距今超过 TTL(目录无承诺时按隐式
|
|
86
|
+
* 10 分钟)。只对 `reported` 端点判断;`silent` / `unknown` 返回 false,档一退化为只按阈值。
|
|
87
|
+
*/
|
|
88
|
+
isCold(): boolean;
|
|
84
89
|
/**
|
|
85
90
|
* 摘要续写的前缀(第三波 §1.8):当前转录按回合同样的方式转换,且上一次 turn 请求的消息
|
|
86
91
|
* 逐条是它的前缀(缓存必然命中)、加上摘要输出放得进窗口;否则 undefined(走独立请求)。
|
|
@@ -14,6 +14,7 @@ import { fingerprintContext } from "../ai/cache/fingerprint.js";
|
|
|
14
14
|
import { DEFAULT_MIN_CACHE_TOKENS, IMPLICIT_CACHE_TTL_MS, detectMiss } from "../ai/cache/miss.js";
|
|
15
15
|
import { endpointKey, sharedCacheReporting, } from "../ai/cache/reporting.js";
|
|
16
16
|
import { CacheWarmer, replayBlocker } from "../ai/cache/warmer.js";
|
|
17
|
+
import { estimateTextTokens } from "../compaction/estimate.js";
|
|
17
18
|
import { SUMMARY_MAX_TOKENS } from "../compaction/summarize-tier.js";
|
|
18
19
|
import { convertToLlm } from "./transform.js";
|
|
19
20
|
export const DEFAULT_CACHE_SETTINGS = Object.freeze({
|
|
@@ -297,6 +298,21 @@ export class SessionCacheController {
|
|
|
297
298
|
}
|
|
298
299
|
return stats;
|
|
299
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* [W5-H1] 缓存是否已冷(wave5 §8.2 C3):上一次请求(含保温)距今超过 TTL(目录无承诺时按隐式
|
|
303
|
+
* 10 分钟)。只对 `reported` 端点判断;`silent` / `unknown` 返回 false,档一退化为只按阈值。
|
|
304
|
+
*/
|
|
305
|
+
isCold() {
|
|
306
|
+
const prev = this.prev;
|
|
307
|
+
if (prev === undefined || this.disposed)
|
|
308
|
+
return false;
|
|
309
|
+
const model = this.core.model();
|
|
310
|
+
const endpoint = endpointKey({ model, baseUrl: model.baseUrl ?? "" });
|
|
311
|
+
if (this.tracker.get(endpoint, model.compat?.cacheReporting) !== "reported")
|
|
312
|
+
return false;
|
|
313
|
+
const ttl = cacheTtlMs(this.modelOf(prev), prev.options.cacheRetention);
|
|
314
|
+
return this.now() - prev.at > (ttl ?? IMPLICIT_CACHE_TTL_MS);
|
|
315
|
+
}
|
|
300
316
|
/**
|
|
301
317
|
* 摘要续写的前缀(第三波 §1.8):当前转录按回合同样的方式转换,且上一次 turn 请求的消息
|
|
302
318
|
* 逐条是它的前缀(缓存必然命中)、加上摘要输出放得进窗口;否则 undefined(走独立请求)。
|
|
@@ -320,7 +336,7 @@ export class SessionCacheController {
|
|
|
320
336
|
for (let i = 0; i < prev.length; i++)
|
|
321
337
|
if (JSON.stringify(prev[i]) !== JSON.stringify(messages[i]))
|
|
322
338
|
return undefined;
|
|
323
|
-
const extra =
|
|
339
|
+
const extra = estimateTextTokens(JSON.stringify(messages.slice(prev.length)));
|
|
324
340
|
const window = model.contextWindow;
|
|
325
341
|
if (window !== undefined && record.promptTokens + extra + SUMMARY_MAX_TOKENS + 2048 > window)
|
|
326
342
|
return undefined;
|
|
@@ -15,4 +15,4 @@ export declare const CLASSIFY_USAGE_KIND = "permission_classify";
|
|
|
15
15
|
export declare function latestUserText(core: SessionCore): string | undefined;
|
|
16
16
|
export declare function createSessionClassifier(core: SessionCore): PermissionClassifier;
|
|
17
17
|
/** gateToolCall 用:组装分类请求。 */
|
|
18
|
-
export declare function classifierRequest(core: SessionCore, toolName: string, input: unknown, projectRoot: string | undefined): ClassifierRequest;
|
|
18
|
+
export declare function classifierRequest(core: SessionCore, toolName: string, input: unknown, projectRoot: string | undefined, sandbox?: ClassifierRequest["sandbox"]): ClassifierRequest;
|
|
@@ -89,13 +89,15 @@ export function createSessionClassifier(core) {
|
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
91
|
/** gateToolCall 用:组装分类请求。 */
|
|
92
|
-
export function classifierRequest(core, toolName, input, projectRoot) {
|
|
92
|
+
export function classifierRequest(core, toolName, input, projectRoot, sandbox) {
|
|
93
93
|
const request = {
|
|
94
94
|
toolName,
|
|
95
95
|
input,
|
|
96
96
|
cwd: core.cwd,
|
|
97
97
|
projectRoot: projectRoot ?? core.cwd,
|
|
98
98
|
};
|
|
99
|
+
if (sandbox !== undefined)
|
|
100
|
+
request.sandbox = sandbox;
|
|
99
101
|
const user = latestUserText(core);
|
|
100
102
|
if (user !== undefined)
|
|
101
103
|
request.userMessage = user;
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 会话侧的压缩调度(设计 §9)。[B2]
|
|
3
3
|
*
|
|
4
|
-
* - 阈值检查(新提示前、`prepareNextTurn` 里):估算 > 0.7 ×(窗口 − 预留)→
|
|
5
|
-
*
|
|
4
|
+
* - 阈值检查(新提示前、`prepareNextTurn` 里):估算 > 0.7 ×(窗口 − 预留)→ 档一裁剪([W5-H1] 按工具
|
|
5
|
+
* 结果新旧计边界,可省 ≥ clearAtLeast 才动,一次清到 0.5 ×);仍 > 窗口 − 预留且熔断允许 → 档二摘要
|
|
6
|
+
* (trigger `threshold`)。缓存已冷(上次请求距今超过 TTL,只认 reported 端点)时未到 0.7 也裁,
|
|
7
|
+
* 且一次换掉全部候选。
|
|
8
|
+
* - 自检([W5-H1] C8):摘要缺 `## Goal` 重试一次再回落;自动压缩后估算不比压缩前小判失败,不写条目。
|
|
9
|
+
* - 回注([W5-H1] C6 / C13):摘要末尾接 `<post-compact-state>` 块(todo、计划、已加载 Skill、最近
|
|
10
|
+
* 文件、转录与 outputs 路径,不含文件正文;理由见 compaction/post-compact.ts),再跑 PostCompact
|
|
11
|
+
* Hook,其 additionalContext 以 `ama.hook_context` 追加在末尾。
|
|
12
|
+
* - 熔断([W5-H1] C5):连续 3 次失败或连续 3 次快速回填跳闸;固定前缀超预算不再尝试;都只告警一次。
|
|
6
13
|
* - 溢出恢复(会话 run 结束后,失败尝试已用 context_edit 剔除):PreCompact Hook → 档二摘要(trigger
|
|
7
|
-
* `overflow
|
|
14
|
+
* `overflow`,受跳闸限制)→ 压缩后估算 ≤ 0.8 × 窗口才重试。
|
|
8
15
|
* - 手动 `/compact`:PreCompact(trigger `manual`)→ 摘要;成功清零熔断。
|
|
9
16
|
* PreCompact 的 `decision: "block"` 取消本次压缩;`customInstructions` 追加到摘要提示。
|
|
10
17
|
* [W3-C1b] 阈值 / 手动压缩与分支摘要优先走会话前缀续写(缓存控制器给前缀),溢出恢复不走
|
|
@@ -12,6 +19,7 @@
|
|
|
12
19
|
*/
|
|
13
20
|
import { CompactionBreaker } from "../compaction/breaker.js";
|
|
14
21
|
import { type ContextEstimate } from "../compaction/estimate.js";
|
|
22
|
+
import { type PrunePolicy } from "../compaction/prune-tier.js";
|
|
15
23
|
import type { BranchSummaryEntry } from "../session/types.js";
|
|
16
24
|
import type { SessionCore } from "./session-core.js";
|
|
17
25
|
import type { CompactionResult, CompactionSettings } from "./types.js";
|
|
@@ -23,6 +31,9 @@ export declare class CompactionController {
|
|
|
23
31
|
settings: CompactionSettings;
|
|
24
32
|
private readonly core;
|
|
25
33
|
private compacting;
|
|
34
|
+
private warnedReason;
|
|
35
|
+
/** [W5-H1] config `compaction.prune / pruneExclude`(组装根把整段 config.compaction 展开传入)。 */
|
|
36
|
+
private readonly pruneConfig;
|
|
26
37
|
constructor(core: SessionCore, settings?: Partial<CompactionSettings>);
|
|
27
38
|
get isCompacting(): boolean;
|
|
28
39
|
/** 模型或开关变化后调用。 */
|
|
@@ -33,16 +44,34 @@ export declare class CompactionController {
|
|
|
33
44
|
private keepRecent;
|
|
34
45
|
/** 摘要请求的公共选项;`continuation` 时附上会话前缀续写的材料。 */
|
|
35
46
|
private summarizer;
|
|
36
|
-
/**
|
|
37
|
-
|
|
47
|
+
/** 档一参数;无窗口时 undefined。 */
|
|
48
|
+
prunePolicy(): PrunePolicy | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* 档一;`need` = 清到目标还要省多少(undefined = 全部候选)。返回省下的 token 估算(0 = 未裁)。
|
|
51
|
+
*/
|
|
52
|
+
prune(policy: PrunePolicy, need: number | undefined): number;
|
|
38
53
|
/** 阈值检查(档一 → 档二)。失败只记录,不打断 run。 */
|
|
39
54
|
checkThreshold(signal: AbortSignal): Promise<void>;
|
|
55
|
+
/** 回注块(todo、计划、已加载 Skill、最近文件、转录与 outputs 路径;不含文件正文)。 */
|
|
56
|
+
private postCompactBlock;
|
|
57
|
+
/**
|
|
58
|
+
* PostCompact Hook(C13,不可阻止):`additionalContext` 作为 `ama.hook_context` 追加在末尾。
|
|
59
|
+
* 返回最终的压缩后估算。
|
|
60
|
+
*/
|
|
61
|
+
private runPostCompactHook;
|
|
62
|
+
/** 假设追加了这条 compaction 之后的估算(按投影全量重估)。 */
|
|
63
|
+
private projectedTokens;
|
|
64
|
+
/** 固定前缀(system 节 + 工具表)的估算:摘要压不掉这部分。 */
|
|
65
|
+
private fixedPrefixTokens;
|
|
66
|
+
/** 熔断挡住自动摘要时告警(同一原因只报一次)。 */
|
|
67
|
+
private warnBlocked;
|
|
40
68
|
/** 溢出恢复:返回是否应以新 run 重试。 */
|
|
41
69
|
recoverOverflow(signal: AbortSignal): Promise<{
|
|
42
70
|
retry: boolean;
|
|
43
71
|
warning?: string;
|
|
44
72
|
}>;
|
|
45
|
-
|
|
73
|
+
/** `cutAt`:[RW-B] 以该条目为切点(「摘要到这里」),不按保留预算找切点。 */
|
|
74
|
+
compactManual(instructions: string | undefined, signal: AbortSignal, cutAt?: string): Promise<CompactionResult>;
|
|
46
75
|
/** `/tree` 离开分支:换叶子,并为离开的那段写 branch_summary(挂在新叶子下)。 */
|
|
47
76
|
leaveBranch(targetId: string | null, instructions: string | undefined, signal: AbortSignal): Promise<BranchSummaryEntry | undefined>;
|
|
48
77
|
private summarize;
|