@bastani/atomic 0.9.2 → 0.9.3-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.md +2 -2
- package/dist/builtin/cursor/package.json +2 -2
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +6 -0
- package/dist/builtin/mcp/direct-tools.ts +4 -2
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/mcp/proxy-call.ts +3 -1
- package/dist/builtin/mcp/utils.ts +18 -7
- package/dist/builtin/subagents/CHANGELOG.md +11 -0
- package/dist/builtin/subagents/README.md +6 -6
- package/dist/builtin/subagents/agents/code-simplifier.md +7 -6
- package/dist/builtin/subagents/agents/codebase-analyzer.md +5 -4
- package/dist/builtin/subagents/agents/codebase-locator.md +3 -3
- package/dist/builtin/subagents/agents/codebase-online-researcher.md +10 -10
- package/dist/builtin/subagents/agents/codebase-pattern-finder.md +4 -4
- package/dist/builtin/subagents/agents/codebase-research-analyzer.md +3 -3
- package/dist/builtin/subagents/agents/codebase-research-locator.md +4 -4
- package/dist/builtin/subagents/agents/debugger.md +5 -5
- package/dist/builtin/subagents/agents/worker.md +56 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/skills/subagent/SKILL.md +11 -11
- package/dist/builtin/subagents/src/agents/agent-loaders.ts +3 -5
- package/dist/builtin/subagents/src/agents/agent-management-helpers.ts +3 -3
- package/dist/builtin/subagents/src/extension/schemas.ts +2 -2
- package/dist/builtin/subagents/src/intercom/result-intercom.ts +4 -3
- package/dist/builtin/subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +1 -1
- package/dist/builtin/subagents/src/runs/shared/nested-render.ts +2 -2
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +2 -1
- package/dist/builtin/subagents/src/shared/types-depth.ts +5 -5
- package/dist/builtin/subagents/src/shared/types-runtime.ts +2 -1
- package/dist/builtin/subagents/src/tui/render-event-formatting.ts +2 -2
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +13 -0
- package/dist/builtin/workflows/README.md +2 -2
- package/dist/builtin/workflows/builtin/goal-artifacts.ts +11 -6
- package/dist/builtin/workflows/builtin/goal-ledger.ts +33 -1
- package/dist/builtin/workflows/builtin/goal-prompts.ts +23 -28
- package/dist/builtin/workflows/builtin/goal-reducer.ts +2 -2
- package/dist/builtin/workflows/builtin/goal-reports.ts +2 -5
- package/dist/builtin/workflows/builtin/goal-review.ts +1 -1
- package/dist/builtin/workflows/builtin/goal-runner.ts +10 -17
- package/dist/builtin/workflows/builtin/open-claude-design-feedback.ts +3 -3
- package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +1 -3
- package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +1 -1
- package/dist/builtin/workflows/builtin/ralph-core.ts +7 -17
- package/dist/builtin/workflows/builtin/ralph-runner.ts +11 -18
- package/dist/builtin/workflows/builtin/shared-prompts.ts +1 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/config-loader.ts +35 -15
- package/dist/builtin/workflows/src/extension/discovery.ts +20 -8
- package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +1 -2
- package/dist/builtin/workflows/src/extension/wiring.ts +1 -1
- package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +11 -10
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +9 -9
- package/dist/cli/args.js.map +1 -1
- package/dist/config-self-update.d.ts.map +1 -1
- package/dist/config-self-update.js +3 -4
- package/dist/config-self-update.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +4 -5
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-bash.d.ts +1 -0
- package/dist/core/agent-session-bash.d.ts.map +1 -1
- package/dist/core/agent-session-bash.js +1 -0
- package/dist/core/agent-session-bash.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +23 -0
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/bash-executor.d.ts +2 -0
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +1 -0
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +29 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +36 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/context-compaction-metrics.d.ts +14 -2
- package/dist/core/compaction/context-compaction-metrics.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction-metrics.js +50 -1
- package/dist/core/compaction/context-compaction-metrics.js.map +1 -1
- package/dist/core/compaction/context-compaction-prompt.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction-prompt.js +2 -0
- package/dist/core/compaction/context-compaction-prompt.js.map +1 -1
- package/dist/core/compaction/context-compaction-runner.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction-runner.js +1 -1
- package/dist/core/compaction/context-compaction-runner.js.map +1 -1
- package/dist/core/compaction/context-deletion-application.d.ts.map +1 -1
- package/dist/core/compaction/context-deletion-application.js +5 -5
- package/dist/core/compaction/context-deletion-application.js.map +1 -1
- package/dist/core/compaction/context-deletion-targets.d.ts +2 -0
- package/dist/core/compaction/context-deletion-targets.d.ts.map +1 -1
- package/dist/core/compaction/context-deletion-targets.js +23 -3
- package/dist/core/compaction/context-deletion-targets.js.map +1 -1
- package/dist/core/compaction/context-deletion-tool-definitions.d.ts +6 -0
- package/dist/core/compaction/context-deletion-tool-definitions.d.ts.map +1 -1
- package/dist/core/compaction/context-deletion-tool-definitions.js.map +1 -1
- package/dist/core/compaction/context-deletion-tools.d.ts.map +1 -1
- package/dist/core/compaction/context-deletion-tools.js +18 -10
- package/dist/core/compaction/context-deletion-tools.js.map +1 -1
- package/dist/core/compaction/context-transcript-analysis.d.ts.map +1 -1
- package/dist/core/compaction/context-transcript-analysis.js +2 -4
- package/dist/core/compaction/context-transcript-analysis.js.map +1 -1
- package/dist/core/copilot-gemini-tool-arguments.d.ts.map +1 -1
- package/dist/core/copilot-gemini-tool-arguments.js +2 -60
- package/dist/core/copilot-gemini-tool-arguments.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +2 -0
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +11 -3
- package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
- package/dist/core/extensions/runner-context.d.ts.map +1 -1
- package/dist/core/extensions/runner-context.js +11 -0
- package/dist/core/extensions/runner-context.js.map +1 -1
- package/dist/core/extensions/tool-events.d.ts +13 -13
- package/dist/core/extensions/tool-events.d.ts.map +1 -1
- package/dist/core/extensions/tool-events.js +3 -3
- package/dist/core/extensions/tool-events.js.map +1 -1
- package/dist/core/extensions/types.d.ts +1 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/flattened-tool-arguments.d.ts +18 -0
- package/dist/core/flattened-tool-arguments.d.ts.map +1 -1
- package/dist/core/flattened-tool-arguments.js +104 -0
- package/dist/core/flattened-tool-arguments.js.map +1 -1
- package/dist/core/sdk-exports.d.ts +1 -1
- package/dist/core/sdk-exports.d.ts.map +1 -1
- package/dist/core/sdk-exports.js +1 -1
- package/dist/core/sdk-exports.js.map +1 -1
- package/dist/core/sdk-types.d.ts +2 -2
- package/dist/core/sdk-types.d.ts.map +1 -1
- package/dist/core/sdk-types.js.map +1 -1
- package/dist/core/settings-manager-basic-accessors.d.ts +4 -0
- package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-basic-accessors.js +18 -0
- package/dist/core/settings-manager-basic-accessors.js.map +1 -1
- package/dist/core/settings-manager-resource-accessors.d.ts +4 -0
- package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-resource-accessors.js +15 -0
- package/dist/core/settings-manager-resource-accessors.js.map +1 -1
- package/dist/core/settings-types.d.ts +11 -0
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/system-prompt.d.ts +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +3 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/artifact-protocol.d.ts +11 -0
- package/dist/core/tools/artifact-protocol.d.ts.map +1 -0
- package/dist/core/tools/artifact-protocol.js +76 -0
- package/dist/core/tools/artifact-protocol.js.map +1 -0
- package/dist/core/tools/artifacts.d.ts +18 -0
- package/dist/core/tools/artifacts.d.ts.map +1 -0
- package/dist/core/tools/artifacts.js +90 -0
- package/dist/core/tools/artifacts.js.map +1 -0
- package/dist/core/tools/bash-async-jobs.d.ts +20 -0
- package/dist/core/tools/bash-async-jobs.d.ts.map +1 -0
- package/dist/core/tools/bash-async-jobs.js +59 -0
- package/dist/core/tools/bash-async-jobs.js.map +1 -0
- package/dist/core/tools/bash-async-output.d.ts +10 -0
- package/dist/core/tools/bash-async-output.d.ts.map +1 -0
- package/dist/core/tools/bash-async-output.js +80 -0
- package/dist/core/tools/bash-async-output.js.map +1 -0
- package/dist/core/tools/bash-interceptor.d.ts +10 -0
- package/dist/core/tools/bash-interceptor.d.ts.map +1 -0
- package/dist/core/tools/bash-interceptor.js +39 -0
- package/dist/core/tools/bash-interceptor.js.map +1 -0
- package/dist/core/tools/bash-leading-cd.d.ts +7 -0
- package/dist/core/tools/bash-leading-cd.d.ts.map +1 -0
- package/dist/core/tools/bash-leading-cd.js +59 -0
- package/dist/core/tools/bash-leading-cd.js.map +1 -0
- package/dist/core/tools/bash-pty-native.d.ts +14 -0
- package/dist/core/tools/bash-pty-native.d.ts.map +1 -0
- package/dist/core/tools/bash-pty-native.js +71 -0
- package/dist/core/tools/bash-pty-native.js.map +1 -0
- package/dist/core/tools/bash.d.ts +28 -17
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +152 -35
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/block-resolver.d.ts +16 -0
- package/dist/core/tools/block-resolver.d.ts.map +1 -0
- package/dist/core/tools/block-resolver.js +74 -0
- package/dist/core/tools/block-resolver.js.map +1 -0
- package/dist/core/tools/conflict-registry.d.ts +16 -0
- package/dist/core/tools/conflict-registry.d.ts.map +1 -0
- package/dist/core/tools/conflict-registry.js +44 -0
- package/dist/core/tools/conflict-registry.js.map +1 -0
- package/dist/core/tools/directory-tree.d.ts +13 -0
- package/dist/core/tools/directory-tree.d.ts.map +1 -0
- package/dist/core/tools/directory-tree.js +81 -0
- package/dist/core/tools/directory-tree.js.map +1 -0
- package/dist/core/tools/edit.d.ts +4 -29
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +136 -228
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/fetch-url.d.ts +74 -0
- package/dist/core/tools/fetch-url.d.ts.map +1 -0
- package/dist/core/tools/fetch-url.js +518 -0
- package/dist/core/tools/fetch-url.js.map +1 -0
- package/dist/core/tools/find.d.ts +27 -9
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +400 -176
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/glob-path-utils.d.ts +8 -0
- package/dist/core/tools/glob-path-utils.d.ts.map +1 -0
- package/dist/core/tools/glob-path-utils.js +26 -0
- package/dist/core/tools/glob-path-utils.js.map +1 -0
- package/dist/core/tools/grep.d.ts +12 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +141 -17
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/hashline-engine/apply.d.ts +11 -0
- package/dist/core/tools/hashline-engine/apply.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/apply.js +752 -0
- package/dist/core/tools/hashline-engine/apply.js.map +1 -0
- package/dist/core/tools/hashline-engine/block.d.ts +40 -0
- package/dist/core/tools/hashline-engine/block.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/block.js +117 -0
- package/dist/core/tools/hashline-engine/block.js.map +1 -0
- package/dist/core/tools/hashline-engine/diff-preview.d.ts +15 -0
- package/dist/core/tools/hashline-engine/diff-preview.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/diff-preview.js +98 -0
- package/dist/core/tools/hashline-engine/diff-preview.js.map +1 -0
- package/dist/core/tools/hashline-engine/format.d.ts +71 -0
- package/dist/core/tools/hashline-engine/format.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/format.js +178 -0
- package/dist/core/tools/hashline-engine/format.js.map +1 -0
- package/dist/core/tools/hashline-engine/fs.d.ts +81 -0
- package/dist/core/tools/hashline-engine/fs.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/fs.js +143 -0
- package/dist/core/tools/hashline-engine/fs.js.map +1 -0
- package/dist/core/tools/hashline-engine/index.d.ts +18 -0
- package/dist/core/tools/hashline-engine/index.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/index.js +20 -0
- package/dist/core/tools/hashline-engine/index.js.map +1 -0
- package/dist/core/tools/hashline-engine/input.d.ts +101 -0
- package/dist/core/tools/hashline-engine/input.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/input.js +398 -0
- package/dist/core/tools/hashline-engine/input.js.map +1 -0
- package/dist/core/tools/hashline-engine/messages.d.ts +99 -0
- package/dist/core/tools/hashline-engine/messages.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/messages.js +144 -0
- package/dist/core/tools/hashline-engine/messages.js.map +1 -0
- package/dist/core/tools/hashline-engine/mismatch.d.ts +45 -0
- package/dist/core/tools/hashline-engine/mismatch.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/mismatch.js +90 -0
- package/dist/core/tools/hashline-engine/mismatch.js.map +1 -0
- package/dist/core/tools/hashline-engine/normalize.d.ts +21 -0
- package/dist/core/tools/hashline-engine/normalize.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/normalize.js +33 -0
- package/dist/core/tools/hashline-engine/normalize.js.map +1 -0
- package/dist/core/tools/hashline-engine/parser.d.ts +24 -0
- package/dist/core/tools/hashline-engine/parser.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/parser.js +381 -0
- package/dist/core/tools/hashline-engine/parser.js.map +1 -0
- package/dist/core/tools/hashline-engine/patcher.d.ts +118 -0
- package/dist/core/tools/hashline-engine/patcher.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/patcher.js +341 -0
- package/dist/core/tools/hashline-engine/patcher.js.map +1 -0
- package/dist/core/tools/hashline-engine/prefixes.d.ts +43 -0
- package/dist/core/tools/hashline-engine/prefixes.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/prefixes.js +135 -0
- package/dist/core/tools/hashline-engine/prefixes.js.map +1 -0
- package/dist/core/tools/hashline-engine/recovery.d.ts +41 -0
- package/dist/core/tools/hashline-engine/recovery.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/recovery.js +168 -0
- package/dist/core/tools/hashline-engine/recovery.js.map +1 -0
- package/dist/core/tools/hashline-engine/snapshots.d.ts +65 -0
- package/dist/core/tools/hashline-engine/snapshots.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/snapshots.js +108 -0
- package/dist/core/tools/hashline-engine/snapshots.js.map +1 -0
- package/dist/core/tools/hashline-engine/stream.d.ts +3 -0
- package/dist/core/tools/hashline-engine/stream.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/stream.js +111 -0
- package/dist/core/tools/hashline-engine/stream.js.map +1 -0
- package/dist/core/tools/hashline-engine/tokenizer.d.ts +69 -0
- package/dist/core/tools/hashline-engine/tokenizer.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/tokenizer.js +430 -0
- package/dist/core/tools/hashline-engine/tokenizer.js.map +1 -0
- package/dist/core/tools/hashline-engine/types.d.ts +166 -0
- package/dist/core/tools/hashline-engine/types.d.ts.map +1 -0
- package/dist/core/tools/hashline-engine/types.js +9 -0
- package/dist/core/tools/hashline-engine/types.js.map +1 -0
- package/dist/core/tools/hashline.d.ts +29 -0
- package/dist/core/tools/hashline.d.ts.map +1 -0
- package/dist/core/tools/hashline.js +110 -0
- package/dist/core/tools/hashline.js.map +1 -0
- package/dist/core/tools/index.d.ts +6 -4
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +52 -35
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/notebook.d.ts +38 -0
- package/dist/core/tools/notebook.d.ts.map +1 -0
- package/dist/core/tools/notebook.js +125 -0
- package/dist/core/tools/notebook.js.map +1 -0
- package/dist/core/tools/read-document-extract.d.ts +9 -0
- package/dist/core/tools/read-document-extract.d.ts.map +1 -0
- package/dist/core/tools/read-document-extract.js +212 -0
- package/dist/core/tools/read-document-extract.js.map +1 -0
- package/dist/core/tools/read-selectors.d.ts +24 -0
- package/dist/core/tools/read-selectors.d.ts.map +1 -0
- package/dist/core/tools/read-selectors.js +277 -0
- package/dist/core/tools/read-selectors.js.map +1 -0
- package/dist/core/tools/read-url.d.ts +37 -0
- package/dist/core/tools/read-url.d.ts.map +1 -0
- package/dist/core/tools/read-url.js +39 -0
- package/dist/core/tools/read-url.js.map +1 -0
- package/dist/core/tools/read.d.ts +11 -11
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +224 -94
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/resource-selectors.d.ts +44 -0
- package/dist/core/tools/resource-selectors.d.ts.map +1 -0
- package/dist/core/tools/resource-selectors.js +808 -0
- package/dist/core/tools/resource-selectors.js.map +1 -0
- package/dist/core/tools/search-details.d.ts +26 -0
- package/dist/core/tools/search-details.d.ts.map +1 -0
- package/dist/core/tools/search-details.js +24 -0
- package/dist/core/tools/search-details.js.map +1 -0
- package/dist/core/tools/search-line-ranges.d.ts +11 -0
- package/dist/core/tools/search-line-ranges.d.ts.map +1 -0
- package/dist/core/tools/search-line-ranges.js +65 -0
- package/dist/core/tools/search-line-ranges.js.map +1 -0
- package/dist/core/tools/search-native.d.ts +97 -0
- package/dist/core/tools/search-native.d.ts.map +1 -0
- package/dist/core/tools/search-native.js +27 -0
- package/dist/core/tools/search-native.js.map +1 -0
- package/dist/core/tools/search.d.ts +24 -0
- package/dist/core/tools/search.d.ts.map +1 -0
- package/dist/core/tools/search.js +573 -0
- package/dist/core/tools/search.js.map +1 -0
- package/dist/core/tools/truncate.d.ts +4 -4
- package/dist/core/tools/truncate.d.ts.map +1 -1
- package/dist/core/tools/truncate.js +3 -3
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/url-ip-guards.d.ts +4 -0
- package/dist/core/tools/url-ip-guards.d.ts.map +1 -0
- package/dist/core/tools/url-ip-guards.js +126 -0
- package/dist/core/tools/url-ip-guards.js.map +1 -0
- package/dist/core/tools/write.d.ts +12 -2
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +166 -14
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +2 -3
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/index-extensions.d.ts +2 -2
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +1 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +9 -2
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-handlers.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-handlers.js +3 -0
- package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.js +7 -0
- package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector-content.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector-content.js +0 -5
- package/dist/modes/interactive/components/tree-selector-content.js.map +1 -1
- package/dist/modes/interactive/interactive-auth-login.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-auth-login.js +1 -0
- package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
- package/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-autocomplete.js +80 -2
- package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
- package/dist/modes/interactive/interactive-hotkeys-debug.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-hotkeys-debug.js +3 -0
- package/dist/modes/interactive/interactive-hotkeys-debug.js.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.js +51 -0
- package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts +5 -0
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +5 -0
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +12 -0
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.js +4 -1
- package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-onboarding.d.ts +11 -0
- package/dist/modes/interactive/interactive-onboarding.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-onboarding.js +220 -0
- package/dist/modes/interactive/interactive-onboarding.js.map +1 -0
- package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-selectors.js +4 -0
- package/dist/modes/interactive/interactive-selectors.js.map +1 -1
- package/dist/modes/interactive/interactive-session-routing.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-session-routing.js +6 -0
- package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-slash-commands.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-slash-commands.js +9 -4
- package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +28 -0
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js +21 -1
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/markit.d.ts +8 -0
- package/dist/utils/markit.d.ts.map +1 -0
- package/dist/utils/markit.js +53 -0
- package/dist/utils/markit.js.map +1 -0
- package/dist/utils/paths.d.ts +2 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +14 -1
- package/dist/utils/paths.js.map +1 -1
- package/docs/compaction.md +16 -1
- package/docs/containerization.md +1 -1
- package/docs/docs.json +1 -0
- package/docs/extensions.md +25 -36
- package/docs/quickstart.md +11 -6
- package/docs/sdk.md +5 -5
- package/docs/settings.md +7 -0
- package/docs/subagents.md +3 -2
- package/docs/tools.md +49 -0
- package/docs/usage.md +3 -3
- package/docs/workflows.md +7 -5
- package/examples/extensions/subagent/README.md +5 -5
- package/examples/extensions/subagent/agents/planner.md +1 -1
- package/examples/extensions/subagent/agents/reviewer.md +1 -1
- package/examples/extensions/subagent/agents/scout.md +2 -2
- package/examples/extensions/subagent/display.ts +3 -3
- package/examples/sdk/05-tools.ts +3 -3
- package/examples/sdk/README.md +1 -1
- package/package.json +3 -2
|
@@ -36,5 +36,7 @@ export declare function canonicalizeEntryTargets(transcript: CompactableTranscri
|
|
|
36
36
|
export declare function addToolCallDeletion(transcript: CompactableTranscript, targets: ContextDeletionTarget[], entry: CompactableTranscriptEntry, callId: string): boolean;
|
|
37
37
|
export declare function isTaskBearingEntry(entry: CompactableTranscriptEntry): boolean;
|
|
38
38
|
export declare function isRecentTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean;
|
|
39
|
+
export declare function isStaleUserImageOnlyEntry(transcript: CompactableTranscript, entry: CompactableTranscriptEntry): boolean;
|
|
40
|
+
export declare function canDeleteStaleUserImageContentBlock(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean;
|
|
39
41
|
export declare function canDeleteTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean;
|
|
40
42
|
//# sourceMappingURL=context-deletion-targets.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-deletion-targets.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-targets.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type {\n\tCompactableContentBlock,\n\tCompactableTranscript,\n\tCompactableTranscriptEntry,\n\tContextDeletionRequest,\n} from \"./context-compaction-types.ts\";\nimport { getTranscriptCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport { assistantEntryHasThinkingContentBlock } from \"./context-transcript-analysis.ts\";\n\nexport function targetKey(target: ContextDeletionTarget): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function rawTargetKey(target: ContextDeletionRequest[\"deletions\"][number]): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function normalizeRawTarget(target: ContextDeletionRequest[\"deletions\"][number]): ContextDeletionTarget {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex as number };\n}\n\nexport function assertIdOnlyDeletionTarget(target: Record<string, unknown>): void {\n\tconst allowedKeys = target.kind === \"content_block\" ? new Set([\"kind\", \"entryId\", \"blockIndex\"]) : new Set([\"kind\", \"entryId\"]);\n\tfor (const key of Object.keys(target)) {\n\t\tif (!allowedKeys.has(key)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Deletion target includes unsupported property ${JSON.stringify(key)}; context deletion targets are id-only and must contain only kind, entryId${target.kind === \"content_block\" ? \", and blockIndex\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport function rawDeletionFromTarget(target: ContextDeletionTarget): ContextDeletionRequest[\"deletions\"][number] {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex };\n}\n\nexport function deletionRequestFromTargets(targets: readonly ContextDeletionTarget[]): ContextDeletionRequest {\n\treturn { deletions: targets.map(rawDeletionFromTarget) };\n}\n\nexport function getDeletedEntryIds(targets: readonly ContextDeletionTarget[]): Set<string> {\n\treturn new Set(targets.filter((target) => target.kind === \"entry\").map((target) => target.entryId));\n}\n\nexport function getDeletedContentBlocks(targets: readonly ContextDeletionTarget[]): Map<string, Set<number>> {\n\tconst blocksByEntry = new Map<string, Set<number>>();\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tconst blocks = blocksByEntry.get(target.entryId) ?? new Set<number>();\n\t\tblocks.add(target.blockIndex);\n\t\tblocksByEntry.set(target.entryId, blocks);\n\t}\n\treturn blocksByEntry;\n}\n\nexport function recentContextEntryBoundary(transcript: CompactableTranscript): number {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\treturn preserve_recent > 0 ? Math.max(0, transcript.entries.length - preserve_recent) : transcript.entries.length;\n}\n\nexport function getRecentContextEntryIds(transcript: CompactableTranscript): Set<string> {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return new Set();\n\treturn new Set(transcript.entries.slice(recentContextEntryBoundary(transcript)).map((entry) => entry.entryId));\n}\n\nexport function isRecentContextEntry(entry: CompactableTranscriptEntry, transcript: CompactableTranscript): boolean {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return false;\n\tconst entryIndex = transcript.entries.findIndex((candidate) => candidate.entryId === entry.entryId);\n\treturn entryIndex >= 0 && entryIndex >= recentContextEntryBoundary(transcript);\n}\n\nexport function formatRecentContextDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tconst recentWindow = `last ${preserve_recent} context ${preserve_recent === 1 ? \"entry\" : \"entries\"}`;\n\tif (target.kind === \"entry\") {\n\t\treturn `Cannot delete recent context entry ${target.entryId} because the ${recentWindow} must remain available for active continuity. Choose an older entry.`;\n\t}\n\treturn `Cannot delete content block ${target.entryId}:${target.blockIndex} because entry ${target.entryId} is one of the ${recentWindow} that must remain available for active continuity. Choose an older entry or content block.`;\n}\n\nexport function deletionGuidance(): string {\n\treturn \"Choose another deletion candidate.\";\n}\n\nexport function findTranscriptEntry(transcript: CompactableTranscript, entryId: string): CompactableTranscriptEntry | undefined {\n\treturn transcript.entries.find((entry) => entry.entryId === entryId);\n}\n\nexport function findTranscriptContentBlock(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n): CompactableContentBlock | undefined {\n\tif (target.kind !== \"content_block\") return undefined;\n\treturn findTranscriptEntry(transcript, target.entryId)?.contentBlocks.find((block) => block.blockIndex === target.blockIndex);\n}\n\nexport function firstToolCallBlockTarget(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): ContextDeletionTarget | undefined {\n\tconst blockIndex = toolCallBlockIndexes(entry, callId)[0];\n\treturn blockIndex === undefined ? undefined : { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n}\n\nexport function formatProtectedDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\tif (target.kind === \"entry\") {\n\t\tconst toolResultSuffix = entry?.toolResultFor ? ` for tool call ${entry.toolResultFor}` : \"\";\n\t\tconst toolCallSuffix = entry && entry.toolCallIds.length > 0 ? ` containing tool call ${entry.toolCallIds.join(\", \")}` : \"\";\n\t\treturn `Deletion target ${target.entryId}${toolResultSuffix}${toolCallSuffix} is protected. ${deletionGuidance()}`;\n\t}\n\n\tconst block = findTranscriptContentBlock(transcript, target);\n\tconst toolBlockSuffix = block?.toolCallId ? ` It is a protected tool block for tool call ${block.toolCallId}.` : \"\";\n\treturn `Content block ${target.entryId}:${target.blockIndex} is protected.${toolBlockSuffix} ${deletionGuidance()}`;\n}\n\nexport function formatProtectedToolDependencyError(\n\ttranscript: CompactableTranscript,\n\tblockedTarget: ContextDeletionTarget,\n\tcontext: string,\n): string {\n\tconst protectedMessage = formatProtectedDeletionError(transcript, blockedTarget);\n\treturn `${context} ${protectedMessage}`;\n}\n\nexport function isProtectedContextDeletionErrorMessage(message: string): boolean {\n\treturn (\n\t\t/\\bprotected\\b/i.test(message) ||\n\t\t/Cannot delete (?:recent context entry|content block .* because entry .* is one of the last)/u.test(message) ||\n\t\t/latest assistant message|thinking\\/redacted_thinking block in (?:the latest|a retained) assistant message/u.test(message)\n\t);\n}\n\nexport function assertNoRecentContextDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst recentEntryIds = getRecentContextEntryIds(transcript);\n\tfor (const target of targets) {\n\t\tif (recentEntryIds.has(target.entryId)) {\n\t\t\tthrow new Error(formatRecentContextDeletionError(transcript, target));\n\t\t}\n\t}\n}\n\nexport function latestAssistantEntry(\n\ttranscript: CompactableTranscript,\n\tdeletedEntryIds: ReadonlySet<string> = new Set<string>(),\n): CompactableTranscriptEntry | undefined {\n\tfor (let index = transcript.entries.length - 1; index >= 0; index--) {\n\t\tconst entry = transcript.entries[index];\n\t\tif (entry.role === \"assistant\" && !deletedEntryIds.has(entry.entryId)) return entry;\n\t}\n\treturn undefined;\n}\n\nexport function findAssistantThinkingContentBlockDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): Extract<ContextDeletionTarget, { kind: \"content_block\" }> | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tif (deletedEntryIds.has(target.entryId)) continue;\n\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\tif (entry && assistantEntryHasThinkingContentBlock(entry)) return target;\n\t}\n\treturn undefined;\n}\n\nexport function findLatestAssistantThinkingDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tconst latestRetainedAssistant = latestAssistantEntry(transcript, deletedEntryIds);\n\n\tfor (const target of targets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\t\tif (!entry || !assistantEntryHasThinkingContentBlock(entry)) continue;\n\t\t\tconst deletedEntryIdsIfTargetWereKept = new Set(deletedEntryIds);\n\t\t\tdeletedEntryIdsIfTargetWereKept.delete(target.entryId);\n\t\t\tif (latestAssistantEntry(transcript, deletedEntryIdsIfTargetWereKept)?.entryId === target.entryId) {\n\t\t\t\treturn target;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tlatestRetainedAssistant?.entryId === target.entryId &&\n\t\t\tassistantEntryHasThinkingContentBlock(latestRetainedAssistant)\n\t\t) {\n\t\t\treturn target;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport function assertNoAssistantThinkingContentBlockDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findAssistantThinkingContentBlockDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in a retained assistant message must remain unmodified; retained assistant messages containing thinking/redacted_thinking content blocks are all-or-nothing`,\n\t);\n}\n\nexport function assertNoLatestAssistantThinkingDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findLatestAssistantThinkingDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tif (violation.kind === \"entry\") {\n\t\tthrow new Error(\n\t\t\t`Cannot delete assistant entry ${violation.entryId} because it is the latest assistant message retained after other deletions and contains thinking/redacted_thinking content blocks`,\n\t\t);\n\t}\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in the latest assistant message must remain unmodified; the latest retained assistant message contains thinking/redacted_thinking content blocks`,\n\t);\n}\n\nexport function isToolCallBlockDeleted(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n\tdeletedEntryIds: ReadonlySet<string>,\n\tdeletedContentBlocks: ReadonlyMap<string, ReadonlySet<number>>,\n): boolean {\n\tif (deletedEntryIds.has(entry.entryId)) return true;\n\tconst deletedBlocks = deletedContentBlocks.get(entry.entryId);\n\tif (!deletedBlocks) return false;\n\treturn entry.contentBlocks.some((block) => block.toolCallId === callId && deletedBlocks.has(block.blockIndex));\n}\n\nexport function toolCallBlockIndexes(entry: CompactableTranscriptEntry, callId: string): number[] {\n\treturn entry.contentBlocks\n\t\t.filter((block) => block.toolCallId === callId)\n\t\t.map((block) => block.blockIndex);\n}\n\nexport function addTarget(targets: ContextDeletionTarget[], target: ContextDeletionTarget): boolean {\n\tif (targets.some((existing) => targetKey(existing) === targetKey(target))) return false;\n\ttargets.push(target);\n\treturn true;\n}\n\nexport function deleteEntryTarget(targets: ContextDeletionTarget[], entryId: string): boolean {\n\tlet changed = false;\n\tfor (let index = targets.length - 1; index >= 0; index--) {\n\t\tconst target = targets[index];\n\t\tif (target.kind === \"content_block\" && target.entryId === entryId) {\n\t\t\ttargets.splice(index, 1);\n\t\t\tchanged = true;\n\t\t}\n\t}\n\treturn addTarget(targets, { kind: \"entry\", entryId }) || changed;\n}\n\nexport function mergeContextDeletionTargets(\n\tbaseTargets: readonly ContextDeletionTarget[],\n\tadditionalTargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget[] {\n\tconst targets = [...baseTargets];\n\tfor (const target of additionalTargets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tdeleteEntryTarget(targets, target.entryId);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!getDeletedEntryIds(targets).has(target.entryId)) {\n\t\t\taddTarget(targets, target);\n\t\t}\n\t}\n\treturn targets;\n}\n\nexport function canonicalizeEntryTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n): boolean {\n\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\tif (getDeletedEntryIds(targets).has(entry.entryId)) return false;\n\tconst deletedBlocks = getDeletedContentBlocks(targets).get(entry.entryId);\n\tif (!deletedBlocks || !entry.contentBlocks.every((block) => deletedBlocks.has(block.blockIndex))) return false;\n\t// Only repair/promote when dependency reconciliation reaches this entry. Non-tool entries that\n\t// request every block individually stay invalid so the assistant must choose explicit entry deletion.\n\treturn deleteEntryTarget(targets, entry.entryId);\n}\n\nexport function addToolCallDeletion(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): boolean {\n\tif (assistantEntryHasThinkingContentBlock(entry)) {\n\t\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\t\treturn deleteEntryTarget(targets, entry.entryId);\n\t}\n\n\tlet changed = false;\n\tfor (const blockIndex of toolCallBlockIndexes(entry, callId)) {\n\t\tconst target: ContextDeletionTarget = { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n\t\tif (!canDeleteTarget(transcript, target)) continue;\n\t\tif (!getDeletedEntryIds(targets).has(entry.entryId)) {\n\t\t\tchanged = addTarget(targets, target) || changed;\n\t\t}\n\t}\n\treturn canonicalizeEntryTargets(transcript, targets, entry) || changed;\n}\n\nexport function isTaskBearingEntry(entry: CompactableTranscriptEntry): boolean {\n\treturn (\n\t\tentry.role === \"user\" ||\n\t\tentry.role === \"custom\" ||\n\t\tentry.role === \"branchSummary\" ||\n\t\tentry.entryType === \"branch_summary\"\n\t);\n}\n\nexport function isRecentTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\treturn entry !== undefined && isRecentContextEntry(entry, transcript);\n}\n\nexport function canDeleteTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\tif (!entry) return false;\n\tif (isRecentTarget(transcript, target)) return false;\n\tif (entry.protected) return false;\n\tif (target.kind === \"entry\") return true;\n\tconst block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);\n\tif (!block) return false;\n\treturn !block.protected;\n}\n\n"]}
|
|
1
|
+
{"version":3,"file":"context-deletion-targets.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-targets.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type {\n\tCompactableContentBlock,\n\tCompactableTranscript,\n\tCompactableTranscriptEntry,\n\tContextDeletionRequest,\n} from \"./context-compaction-types.ts\";\nimport { getTranscriptCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport { assistantEntryHasThinkingContentBlock } from \"./context-transcript-analysis.ts\";\n\nexport function targetKey(target: ContextDeletionTarget): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function rawTargetKey(target: ContextDeletionRequest[\"deletions\"][number]): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function normalizeRawTarget(target: ContextDeletionRequest[\"deletions\"][number]): ContextDeletionTarget {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex as number };\n}\n\nexport function assertIdOnlyDeletionTarget(target: Record<string, unknown>): void {\n\tconst allowedKeys = target.kind === \"content_block\" ? new Set([\"kind\", \"entryId\", \"blockIndex\"]) : new Set([\"kind\", \"entryId\"]);\n\tfor (const key of Object.keys(target)) {\n\t\tif (!allowedKeys.has(key)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Deletion target includes unsupported property ${JSON.stringify(key)}; context deletion targets are id-only and must contain only kind, entryId${target.kind === \"content_block\" ? \", and blockIndex\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport function rawDeletionFromTarget(target: ContextDeletionTarget): ContextDeletionRequest[\"deletions\"][number] {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex };\n}\n\nexport function deletionRequestFromTargets(targets: readonly ContextDeletionTarget[]): ContextDeletionRequest {\n\treturn { deletions: targets.map(rawDeletionFromTarget) };\n}\n\nexport function getDeletedEntryIds(targets: readonly ContextDeletionTarget[]): Set<string> {\n\treturn new Set(targets.filter((target) => target.kind === \"entry\").map((target) => target.entryId));\n}\n\nexport function getDeletedContentBlocks(targets: readonly ContextDeletionTarget[]): Map<string, Set<number>> {\n\tconst blocksByEntry = new Map<string, Set<number>>();\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tconst blocks = blocksByEntry.get(target.entryId) ?? new Set<number>();\n\t\tblocks.add(target.blockIndex);\n\t\tblocksByEntry.set(target.entryId, blocks);\n\t}\n\treturn blocksByEntry;\n}\n\nexport function recentContextEntryBoundary(transcript: CompactableTranscript): number {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\treturn preserve_recent > 0 ? Math.max(0, transcript.entries.length - preserve_recent) : transcript.entries.length;\n}\n\nexport function getRecentContextEntryIds(transcript: CompactableTranscript): Set<string> {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return new Set();\n\treturn new Set(transcript.entries.slice(recentContextEntryBoundary(transcript)).map((entry) => entry.entryId));\n}\n\nexport function isRecentContextEntry(entry: CompactableTranscriptEntry, transcript: CompactableTranscript): boolean {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return false;\n\tconst entryIndex = transcript.entries.findIndex((candidate) => candidate.entryId === entry.entryId);\n\treturn entryIndex >= 0 && entryIndex >= recentContextEntryBoundary(transcript);\n}\n\nexport function formatRecentContextDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tconst recentWindow = `last ${preserve_recent} context ${preserve_recent === 1 ? \"entry\" : \"entries\"}`;\n\tif (target.kind === \"entry\") {\n\t\treturn `Cannot delete recent context entry ${target.entryId} because the ${recentWindow} must remain available for active continuity. Choose an older entry.`;\n\t}\n\treturn `Cannot delete content block ${target.entryId}:${target.blockIndex} because entry ${target.entryId} is one of the ${recentWindow} that must remain available for active continuity. Choose an older entry or content block.`;\n}\n\nexport function deletionGuidance(): string {\n\treturn \"Choose another deletion candidate.\";\n}\n\nexport function findTranscriptEntry(transcript: CompactableTranscript, entryId: string): CompactableTranscriptEntry | undefined {\n\treturn transcript.entries.find((entry) => entry.entryId === entryId);\n}\n\nexport function findTranscriptContentBlock(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n): CompactableContentBlock | undefined {\n\tif (target.kind !== \"content_block\") return undefined;\n\treturn findTranscriptEntry(transcript, target.entryId)?.contentBlocks.find((block) => block.blockIndex === target.blockIndex);\n}\n\nexport function firstToolCallBlockTarget(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): ContextDeletionTarget | undefined {\n\tconst blockIndex = toolCallBlockIndexes(entry, callId)[0];\n\treturn blockIndex === undefined ? undefined : { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n}\n\nexport function formatProtectedDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\tif (target.kind === \"entry\") {\n\t\tconst toolResultSuffix = entry?.toolResultFor ? ` for tool call ${entry.toolResultFor}` : \"\";\n\t\tconst toolCallSuffix = entry && entry.toolCallIds.length > 0 ? ` containing tool call ${entry.toolCallIds.join(\", \")}` : \"\";\n\t\treturn `Deletion target ${target.entryId}${toolResultSuffix}${toolCallSuffix} is protected. ${deletionGuidance()}`;\n\t}\n\n\tconst block = findTranscriptContentBlock(transcript, target);\n\tconst toolBlockSuffix = block?.toolCallId ? ` It is a protected tool block for tool call ${block.toolCallId}.` : \"\";\n\treturn `Content block ${target.entryId}:${target.blockIndex} is protected.${toolBlockSuffix} ${deletionGuidance()}`;\n}\n\nexport function formatProtectedToolDependencyError(\n\ttranscript: CompactableTranscript,\n\tblockedTarget: ContextDeletionTarget,\n\tcontext: string,\n): string {\n\tconst protectedMessage = formatProtectedDeletionError(transcript, blockedTarget);\n\treturn `${context} ${protectedMessage}`;\n}\n\nexport function isProtectedContextDeletionErrorMessage(message: string): boolean {\n\treturn (\n\t\t/\\bprotected\\b/i.test(message) ||\n\t\t/Cannot delete (?:recent context entry|content block .* because entry .* is one of the last)/u.test(message) ||\n\t\t/latest assistant message|thinking\\/redacted_thinking block in (?:the latest|a retained) assistant message/u.test(message)\n\t);\n}\n\nexport function assertNoRecentContextDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst recentEntryIds = getRecentContextEntryIds(transcript);\n\tfor (const target of targets) {\n\t\tif (recentEntryIds.has(target.entryId)) {\n\t\t\tthrow new Error(formatRecentContextDeletionError(transcript, target));\n\t\t}\n\t}\n}\n\nexport function latestAssistantEntry(\n\ttranscript: CompactableTranscript,\n\tdeletedEntryIds: ReadonlySet<string> = new Set<string>(),\n): CompactableTranscriptEntry | undefined {\n\tfor (let index = transcript.entries.length - 1; index >= 0; index--) {\n\t\tconst entry = transcript.entries[index];\n\t\tif (entry.role === \"assistant\" && !deletedEntryIds.has(entry.entryId)) return entry;\n\t}\n\treturn undefined;\n}\n\nexport function findAssistantThinkingContentBlockDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): Extract<ContextDeletionTarget, { kind: \"content_block\" }> | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tif (deletedEntryIds.has(target.entryId)) continue;\n\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\tif (entry && assistantEntryHasThinkingContentBlock(entry)) return target;\n\t}\n\treturn undefined;\n}\n\nexport function findLatestAssistantThinkingDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tconst latestRetainedAssistant = latestAssistantEntry(transcript, deletedEntryIds);\n\n\tfor (const target of targets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\t\tif (!entry || !assistantEntryHasThinkingContentBlock(entry)) continue;\n\t\t\tconst deletedEntryIdsIfTargetWereKept = new Set(deletedEntryIds);\n\t\t\tdeletedEntryIdsIfTargetWereKept.delete(target.entryId);\n\t\t\tif (latestAssistantEntry(transcript, deletedEntryIdsIfTargetWereKept)?.entryId === target.entryId) {\n\t\t\t\treturn target;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tlatestRetainedAssistant?.entryId === target.entryId &&\n\t\t\tassistantEntryHasThinkingContentBlock(latestRetainedAssistant)\n\t\t) {\n\t\t\treturn target;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport function assertNoAssistantThinkingContentBlockDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findAssistantThinkingContentBlockDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in a retained assistant message must remain unmodified; retained assistant messages containing thinking/redacted_thinking content blocks are all-or-nothing`,\n\t);\n}\n\nexport function assertNoLatestAssistantThinkingDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findLatestAssistantThinkingDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tif (violation.kind === \"entry\") {\n\t\tthrow new Error(\n\t\t\t`Cannot delete assistant entry ${violation.entryId} because it is the latest assistant message retained after other deletions and contains thinking/redacted_thinking content blocks`,\n\t\t);\n\t}\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in the latest assistant message must remain unmodified; the latest retained assistant message contains thinking/redacted_thinking content blocks`,\n\t);\n}\n\nexport function isToolCallBlockDeleted(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n\tdeletedEntryIds: ReadonlySet<string>,\n\tdeletedContentBlocks: ReadonlyMap<string, ReadonlySet<number>>,\n): boolean {\n\tif (deletedEntryIds.has(entry.entryId)) return true;\n\tconst deletedBlocks = deletedContentBlocks.get(entry.entryId);\n\tif (!deletedBlocks) return false;\n\treturn entry.contentBlocks.some((block) => block.toolCallId === callId && deletedBlocks.has(block.blockIndex));\n}\n\nexport function toolCallBlockIndexes(entry: CompactableTranscriptEntry, callId: string): number[] {\n\treturn entry.contentBlocks\n\t\t.filter((block) => block.toolCallId === callId)\n\t\t.map((block) => block.blockIndex);\n}\n\nexport function addTarget(targets: ContextDeletionTarget[], target: ContextDeletionTarget): boolean {\n\tif (targets.some((existing) => targetKey(existing) === targetKey(target))) return false;\n\ttargets.push(target);\n\treturn true;\n}\n\nexport function deleteEntryTarget(targets: ContextDeletionTarget[], entryId: string): boolean {\n\tlet changed = false;\n\tfor (let index = targets.length - 1; index >= 0; index--) {\n\t\tconst target = targets[index];\n\t\tif (target.kind === \"content_block\" && target.entryId === entryId) {\n\t\t\ttargets.splice(index, 1);\n\t\t\tchanged = true;\n\t\t}\n\t}\n\treturn addTarget(targets, { kind: \"entry\", entryId }) || changed;\n}\n\nexport function mergeContextDeletionTargets(\n\tbaseTargets: readonly ContextDeletionTarget[],\n\tadditionalTargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget[] {\n\tconst targets = [...baseTargets];\n\tfor (const target of additionalTargets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tdeleteEntryTarget(targets, target.entryId);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!getDeletedEntryIds(targets).has(target.entryId)) {\n\t\t\taddTarget(targets, target);\n\t\t}\n\t}\n\treturn targets;\n}\n\nexport function canonicalizeEntryTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n): boolean {\n\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\tif (getDeletedEntryIds(targets).has(entry.entryId)) return false;\n\tconst deletedBlocks = getDeletedContentBlocks(targets).get(entry.entryId);\n\tif (!deletedBlocks || !entry.contentBlocks.every((block) => deletedBlocks.has(block.blockIndex))) return false;\n\t// Only repair/promote when dependency reconciliation reaches this entry. Non-tool entries that\n\t// request every block individually stay invalid so the assistant must choose explicit entry deletion.\n\treturn deleteEntryTarget(targets, entry.entryId);\n}\n\nexport function addToolCallDeletion(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): boolean {\n\tif (assistantEntryHasThinkingContentBlock(entry)) {\n\t\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\t\treturn deleteEntryTarget(targets, entry.entryId);\n\t}\n\n\tlet changed = false;\n\tfor (const blockIndex of toolCallBlockIndexes(entry, callId)) {\n\t\tconst target: ContextDeletionTarget = { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n\t\tif (!canDeleteTarget(transcript, target)) continue;\n\t\tif (!getDeletedEntryIds(targets).has(entry.entryId)) {\n\t\t\tchanged = addTarget(targets, target) || changed;\n\t\t}\n\t}\n\treturn canonicalizeEntryTargets(transcript, targets, entry) || changed;\n}\n\nexport function isTaskBearingEntry(entry: CompactableTranscriptEntry): boolean {\n\treturn (\n\t\tentry.role === \"user\" ||\n\t\tentry.role === \"custom\" ||\n\t\tentry.role === \"branchSummary\" ||\n\t\tentry.entryType === \"branch_summary\"\n\t);\n}\n\nexport function isRecentTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\treturn entry !== undefined && isRecentContextEntry(entry, transcript);\n}\n\nexport function isStaleUserImageOnlyEntry(transcript: CompactableTranscript, entry: CompactableTranscriptEntry): boolean {\n\tif (entry.role !== \"user\" || isRecentContextEntry(entry, transcript)) return false;\n\tif (entry.contentBlocks.length === 0 || !entry.contentBlocks.every((block) => block.type === \"image\")) return false;\n\treturn transcript.entries.some((candidate) => candidate.entryId !== entry.entryId && isTaskBearingEntry(candidate));\n}\n\nexport function canDeleteStaleUserImageContentBlock(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n): boolean {\n\tif (target.kind !== \"content_block\") return false;\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\tif (!entry || entry.role !== \"user\" || isRecentTarget(transcript, target)) return false;\n\tconst block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);\n\tif (!block || block.type !== \"image\") return false;\n\treturn entry.contentBlocks.some((candidate) => candidate.blockIndex !== target.blockIndex && candidate.type !== \"image\");\n}\n\nexport function canDeleteTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\tif (!entry) return false;\n\tif (isRecentTarget(transcript, target)) return false;\n\tif (target.kind === \"entry\") return isStaleUserImageOnlyEntry(transcript, entry) || !entry.protected;\n\tconst block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);\n\tif (!block) return false;\n\tif (canDeleteStaleUserImageContentBlock(transcript, target)) return true;\n\tif (entry.protected) return false;\n\treturn !block.protected;\n}\n\n"]}
|
|
@@ -249,19 +249,39 @@ export function isRecentTarget(transcript, target) {
|
|
|
249
249
|
const entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);
|
|
250
250
|
return entry !== undefined && isRecentContextEntry(entry, transcript);
|
|
251
251
|
}
|
|
252
|
+
export function isStaleUserImageOnlyEntry(transcript, entry) {
|
|
253
|
+
if (entry.role !== "user" || isRecentContextEntry(entry, transcript))
|
|
254
|
+
return false;
|
|
255
|
+
if (entry.contentBlocks.length === 0 || !entry.contentBlocks.every((block) => block.type === "image"))
|
|
256
|
+
return false;
|
|
257
|
+
return transcript.entries.some((candidate) => candidate.entryId !== entry.entryId && isTaskBearingEntry(candidate));
|
|
258
|
+
}
|
|
259
|
+
export function canDeleteStaleUserImageContentBlock(transcript, target) {
|
|
260
|
+
if (target.kind !== "content_block")
|
|
261
|
+
return false;
|
|
262
|
+
const entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);
|
|
263
|
+
if (!entry || entry.role !== "user" || isRecentTarget(transcript, target))
|
|
264
|
+
return false;
|
|
265
|
+
const block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);
|
|
266
|
+
if (!block || block.type !== "image")
|
|
267
|
+
return false;
|
|
268
|
+
return entry.contentBlocks.some((candidate) => candidate.blockIndex !== target.blockIndex && candidate.type !== "image");
|
|
269
|
+
}
|
|
252
270
|
export function canDeleteTarget(transcript, target) {
|
|
253
271
|
const entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);
|
|
254
272
|
if (!entry)
|
|
255
273
|
return false;
|
|
256
274
|
if (isRecentTarget(transcript, target))
|
|
257
275
|
return false;
|
|
258
|
-
if (entry.protected)
|
|
259
|
-
return false;
|
|
260
276
|
if (target.kind === "entry")
|
|
261
|
-
return
|
|
277
|
+
return isStaleUserImageOnlyEntry(transcript, entry) || !entry.protected;
|
|
262
278
|
const block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);
|
|
263
279
|
if (!block)
|
|
264
280
|
return false;
|
|
281
|
+
if (canDeleteStaleUserImageContentBlock(transcript, target))
|
|
282
|
+
return true;
|
|
283
|
+
if (entry.protected)
|
|
284
|
+
return false;
|
|
265
285
|
return !block.protected;
|
|
266
286
|
}
|
|
267
287
|
//# sourceMappingURL=context-deletion-targets.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-deletion-targets.js","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-targets.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,qCAAqC,EAAE,MAAM,kCAAkC,CAAC;AAEzF,MAAM,UAAU,SAAS,CAAC,MAA6B;IACtD,OAAO,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,iBAAiB,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;AACrH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAmD;IAC/E,OAAO,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,iBAAiB,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;AACrH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAmD;IACrF,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAC/E,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,UAAoB,EAAE,CAAC;AACpG,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,MAA+B;IACzE,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAChI,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACd,iDAAiD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,6EAA6E,MAAM,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAC5M,CAAC;QACH,CAAC;IACF,CAAC;AACF,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAA6B;IAClE,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAC/E,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,OAAyC;IACnF,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAyC;IAC3E,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;AACrG,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAyC;IAChF,MAAM,aAAa,GAAG,IAAI,GAAG,EAAuB,CAAC;IACrD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe;YAAE,SAAS;QAC9C,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;QACtE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC9B,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,aAAa,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,UAAiC;IAC3E,MAAM,EAAE,eAAe,EAAE,GAAG,iCAAiC,CAAC,UAAU,CAAC,CAAC;IAC1E,OAAO,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC;AACnH,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,UAAiC;IACzE,MAAM,EAAE,eAAe,EAAE,GAAG,iCAAiC,CAAC,UAAU,CAAC,CAAC;IAC1E,IAAI,eAAe,IAAI,CAAC;QAAE,OAAO,IAAI,GAAG,EAAE,CAAC;IAC3C,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAChH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAiC,EAAE,UAAiC;IACxG,MAAM,EAAE,eAAe,EAAE,GAAG,iCAAiC,CAAC,UAAU,CAAC,CAAC;IAC1E,IAAI,eAAe,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC;IACpG,OAAO,UAAU,IAAI,CAAC,IAAI,UAAU,IAAI,0BAA0B,CAAC,UAAU,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAC,UAAiC,EAAE,MAA6B;IAChH,MAAM,EAAE,eAAe,EAAE,GAAG,iCAAiC,CAAC,UAAU,CAAC,CAAC;IAC1E,MAAM,YAAY,GAAG,QAAQ,eAAe,YAAY,eAAe,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IACtG,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,OAAO,sCAAsC,MAAM,CAAC,OAAO,gBAAgB,YAAY,sEAAsE,CAAC;IAC/J,CAAC;IACD,OAAO,+BAA+B,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,UAAU,kBAAkB,MAAM,CAAC,OAAO,kBAAkB,YAAY,4FAA4F,CAAC;AACrO,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC/B,OAAO,oCAAoC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,UAAiC,EAAE,OAAe;IACrF,OAAO,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,0BAA0B,CACzC,UAAiC,EACjC,MAA6B;IAE7B,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe;QAAE,OAAO,SAAS,CAAC;IACtD,OAAO,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU,CAAC,CAAC;AAC/H,CAAC;AAED,MAAM,UAAU,wBAAwB,CACvC,KAAiC,EACjC,MAAc;IAEd,MAAM,UAAU,GAAG,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,OAAO,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;AAC7G,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,UAAiC,EAAE,MAA6B;IAC5G,MAAM,KAAK,GAAG,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9D,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,MAAM,gBAAgB,GAAG,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,kBAAkB,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7F,MAAM,cAAc,GAAG,KAAK,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,yBAAyB,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5H,OAAO,mBAAmB,MAAM,CAAC,OAAO,GAAG,gBAAgB,GAAG,cAAc,kBAAkB,gBAAgB,EAAE,EAAE,CAAC;IACpH,CAAC;IAED,MAAM,KAAK,GAAG,0BAA0B,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC7D,MAAM,eAAe,GAAG,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,+CAA+C,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACpH,OAAO,iBAAiB,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,UAAU,iBAAiB,eAAe,IAAI,gBAAgB,EAAE,EAAE,CAAC;AACrH,CAAC;AAED,MAAM,UAAU,kCAAkC,CACjD,UAAiC,EACjC,aAAoC,EACpC,OAAe;IAEf,MAAM,gBAAgB,GAAG,4BAA4B,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACjF,OAAO,GAAG,OAAO,IAAI,gBAAgB,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,sCAAsC,CAAC,OAAe;IACrE,OAAO,CACN,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC;QAC9B,8FAA8F,CAAC,IAAI,CAAC,OAAO,CAAC;QAC5G,4GAA4G,CAAC,IAAI,CAAC,OAAO,CAAC,CAC1H,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oCAAoC,CACnD,UAAiC,EACjC,OAAyC;IAEzC,MAAM,cAAc,GAAG,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAC5D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QACvE,CAAC;IACF,CAAC;AACF,CAAC;AAED,MAAM,UAAU,oBAAoB,CACnC,UAAiC,EACjC,eAAe,GAAwB,IAAI,GAAG,EAAU;IAExD,KAAK,IAAI,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QACrE,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;YAAE,OAAO,KAAK,CAAC;IACrF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,kDAAkD,CACjE,UAAiC,EACjC,OAAyC;IAEzC,MAAM,eAAe,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACpD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe;YAAE,SAAS;QAC9C,IAAI,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;YAAE,SAAS;QAClD,MAAM,KAAK,GAAG,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9D,IAAI,KAAK,IAAI,qCAAqC,CAAC,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC;IAC1E,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,4CAA4C,CAC3D,UAAiC,EACjC,OAAyC;IAEzC,MAAM,eAAe,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,uBAAuB,GAAG,oBAAoB,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IAElF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YAC9D,IAAI,CAAC,KAAK,IAAI,CAAC,qCAAqC,CAAC,KAAK,CAAC;gBAAE,SAAS;YACtE,MAAM,+BAA+B,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;YACjE,+BAA+B,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,oBAAoB,CAAC,UAAU,EAAE,+BAA+B,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnG,OAAO,MAAM,CAAC;YACf,CAAC;YACD,SAAS;QACV,CAAC;QACD,IACC,uBAAuB,EAAE,OAAO,KAAK,MAAM,CAAC,OAAO;YACnD,qCAAqC,CAAC,uBAAuB,CAAC,EAC7D,CAAC;YACF,OAAO,MAAM,CAAC;QACf,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,oDAAoD,CACnE,UAAiC,EACjC,OAAyC;IAEzC,MAAM,SAAS,GAAG,kDAAkD,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC1F,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,MAAM,IAAI,KAAK,CACd,+BAA+B,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,UAAU,yMAAyM,CACjR,CAAC;AACH,CAAC;AAED,MAAM,UAAU,8CAA8C,CAC7D,UAAiC,EACjC,OAAyC;IAEzC,MAAM,SAAS,GAAG,4CAA4C,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACpF,IAAI,CAAC,SAAS;QAAE,OAAO;IACvB,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CACd,iCAAiC,SAAS,CAAC,OAAO,mIAAmI,CACrL,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CACd,+BAA+B,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,UAAU,8LAA8L,CACtQ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CACrC,KAAiC,EACjC,MAAc,EACd,eAAoC,EACpC,oBAA8D;IAE9D,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,MAAM,aAAa,GAAG,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9D,IAAI,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,KAAK,MAAM,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;AAChH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAiC,EAAE,MAAc;IACrF,OAAO,KAAK,CAAC,aAAa;SACxB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,KAAK,MAAM,CAAC;SAC9C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAgC,EAAE,MAA6B;IACxF,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC,MAAM,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACxF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAgC,EAAE,OAAe;IAClF,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;YACnE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACzB,OAAO,GAAG,IAAI,CAAC;QAChB,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,IAAI,OAAO,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,2BAA2B,CAC1C,WAA6C,EAC7C,iBAAmD;IAEnD,MAAM,OAAO,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC;IACjC,KAAK,MAAM,MAAM,IAAI,iBAAiB,EAAE,CAAC;QACxC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC7B,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YAC3C,SAAS;QACV,CAAC;QACD,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACtD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC5B,CAAC;IACF,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,wBAAwB,CACvC,UAAiC,EACjC,OAAgC,EAChC,KAAiC;IAEjC,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1F,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACjE,MAAM,aAAa,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1E,IAAI,CAAC,aAAa,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/G,+FAA+F;IAC/F,sGAAsG;IACtG,OAAO,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAClC,UAAiC,EACjC,OAAgC,EAChC,KAAiC,EACjC,MAAc;IAEd,IAAI,qCAAqC,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;QAC1F,OAAO,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,UAAU,IAAI,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;QAC9D,MAAM,MAAM,GAA0B,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;QACpG,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,MAAM,CAAC;YAAE,SAAS;QACnD,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACrD,OAAO,GAAG,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC;QACjD,CAAC;IACF,CAAC;IACD,OAAO,wBAAwB,CAAC,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAiC;IACnE,OAAO,CACN,KAAK,CAAC,IAAI,KAAK,MAAM;QACrB,KAAK,CAAC,IAAI,KAAK,QAAQ;QACvB,KAAK,CAAC,IAAI,KAAK,eAAe;QAC9B,KAAK,CAAC,SAAS,KAAK,gBAAgB,CACpC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,UAAiC,EAAE,MAA6B;IAC9F,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3F,OAAO,KAAK,KAAK,SAAS,IAAI,oBAAoB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,UAAiC,EAAE,MAA6B;IAC/F,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3F,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,KAAK,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAClC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU,CAAC,CAAC;IAClG,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;AACzB,CAAC","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type {\n\tCompactableContentBlock,\n\tCompactableTranscript,\n\tCompactableTranscriptEntry,\n\tContextDeletionRequest,\n} from \"./context-compaction-types.ts\";\nimport { getTranscriptCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport { assistantEntryHasThinkingContentBlock } from \"./context-transcript-analysis.ts\";\n\nexport function targetKey(target: ContextDeletionTarget): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function rawTargetKey(target: ContextDeletionRequest[\"deletions\"][number]): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function normalizeRawTarget(target: ContextDeletionRequest[\"deletions\"][number]): ContextDeletionTarget {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex as number };\n}\n\nexport function assertIdOnlyDeletionTarget(target: Record<string, unknown>): void {\n\tconst allowedKeys = target.kind === \"content_block\" ? new Set([\"kind\", \"entryId\", \"blockIndex\"]) : new Set([\"kind\", \"entryId\"]);\n\tfor (const key of Object.keys(target)) {\n\t\tif (!allowedKeys.has(key)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Deletion target includes unsupported property ${JSON.stringify(key)}; context deletion targets are id-only and must contain only kind, entryId${target.kind === \"content_block\" ? \", and blockIndex\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport function rawDeletionFromTarget(target: ContextDeletionTarget): ContextDeletionRequest[\"deletions\"][number] {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex };\n}\n\nexport function deletionRequestFromTargets(targets: readonly ContextDeletionTarget[]): ContextDeletionRequest {\n\treturn { deletions: targets.map(rawDeletionFromTarget) };\n}\n\nexport function getDeletedEntryIds(targets: readonly ContextDeletionTarget[]): Set<string> {\n\treturn new Set(targets.filter((target) => target.kind === \"entry\").map((target) => target.entryId));\n}\n\nexport function getDeletedContentBlocks(targets: readonly ContextDeletionTarget[]): Map<string, Set<number>> {\n\tconst blocksByEntry = new Map<string, Set<number>>();\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tconst blocks = blocksByEntry.get(target.entryId) ?? new Set<number>();\n\t\tblocks.add(target.blockIndex);\n\t\tblocksByEntry.set(target.entryId, blocks);\n\t}\n\treturn blocksByEntry;\n}\n\nexport function recentContextEntryBoundary(transcript: CompactableTranscript): number {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\treturn preserve_recent > 0 ? Math.max(0, transcript.entries.length - preserve_recent) : transcript.entries.length;\n}\n\nexport function getRecentContextEntryIds(transcript: CompactableTranscript): Set<string> {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return new Set();\n\treturn new Set(transcript.entries.slice(recentContextEntryBoundary(transcript)).map((entry) => entry.entryId));\n}\n\nexport function isRecentContextEntry(entry: CompactableTranscriptEntry, transcript: CompactableTranscript): boolean {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return false;\n\tconst entryIndex = transcript.entries.findIndex((candidate) => candidate.entryId === entry.entryId);\n\treturn entryIndex >= 0 && entryIndex >= recentContextEntryBoundary(transcript);\n}\n\nexport function formatRecentContextDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tconst recentWindow = `last ${preserve_recent} context ${preserve_recent === 1 ? \"entry\" : \"entries\"}`;\n\tif (target.kind === \"entry\") {\n\t\treturn `Cannot delete recent context entry ${target.entryId} because the ${recentWindow} must remain available for active continuity. Choose an older entry.`;\n\t}\n\treturn `Cannot delete content block ${target.entryId}:${target.blockIndex} because entry ${target.entryId} is one of the ${recentWindow} that must remain available for active continuity. Choose an older entry or content block.`;\n}\n\nexport function deletionGuidance(): string {\n\treturn \"Choose another deletion candidate.\";\n}\n\nexport function findTranscriptEntry(transcript: CompactableTranscript, entryId: string): CompactableTranscriptEntry | undefined {\n\treturn transcript.entries.find((entry) => entry.entryId === entryId);\n}\n\nexport function findTranscriptContentBlock(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n): CompactableContentBlock | undefined {\n\tif (target.kind !== \"content_block\") return undefined;\n\treturn findTranscriptEntry(transcript, target.entryId)?.contentBlocks.find((block) => block.blockIndex === target.blockIndex);\n}\n\nexport function firstToolCallBlockTarget(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): ContextDeletionTarget | undefined {\n\tconst blockIndex = toolCallBlockIndexes(entry, callId)[0];\n\treturn blockIndex === undefined ? undefined : { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n}\n\nexport function formatProtectedDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\tif (target.kind === \"entry\") {\n\t\tconst toolResultSuffix = entry?.toolResultFor ? ` for tool call ${entry.toolResultFor}` : \"\";\n\t\tconst toolCallSuffix = entry && entry.toolCallIds.length > 0 ? ` containing tool call ${entry.toolCallIds.join(\", \")}` : \"\";\n\t\treturn `Deletion target ${target.entryId}${toolResultSuffix}${toolCallSuffix} is protected. ${deletionGuidance()}`;\n\t}\n\n\tconst block = findTranscriptContentBlock(transcript, target);\n\tconst toolBlockSuffix = block?.toolCallId ? ` It is a protected tool block for tool call ${block.toolCallId}.` : \"\";\n\treturn `Content block ${target.entryId}:${target.blockIndex} is protected.${toolBlockSuffix} ${deletionGuidance()}`;\n}\n\nexport function formatProtectedToolDependencyError(\n\ttranscript: CompactableTranscript,\n\tblockedTarget: ContextDeletionTarget,\n\tcontext: string,\n): string {\n\tconst protectedMessage = formatProtectedDeletionError(transcript, blockedTarget);\n\treturn `${context} ${protectedMessage}`;\n}\n\nexport function isProtectedContextDeletionErrorMessage(message: string): boolean {\n\treturn (\n\t\t/\\bprotected\\b/i.test(message) ||\n\t\t/Cannot delete (?:recent context entry|content block .* because entry .* is one of the last)/u.test(message) ||\n\t\t/latest assistant message|thinking\\/redacted_thinking block in (?:the latest|a retained) assistant message/u.test(message)\n\t);\n}\n\nexport function assertNoRecentContextDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst recentEntryIds = getRecentContextEntryIds(transcript);\n\tfor (const target of targets) {\n\t\tif (recentEntryIds.has(target.entryId)) {\n\t\t\tthrow new Error(formatRecentContextDeletionError(transcript, target));\n\t\t}\n\t}\n}\n\nexport function latestAssistantEntry(\n\ttranscript: CompactableTranscript,\n\tdeletedEntryIds: ReadonlySet<string> = new Set<string>(),\n): CompactableTranscriptEntry | undefined {\n\tfor (let index = transcript.entries.length - 1; index >= 0; index--) {\n\t\tconst entry = transcript.entries[index];\n\t\tif (entry.role === \"assistant\" && !deletedEntryIds.has(entry.entryId)) return entry;\n\t}\n\treturn undefined;\n}\n\nexport function findAssistantThinkingContentBlockDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): Extract<ContextDeletionTarget, { kind: \"content_block\" }> | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tif (deletedEntryIds.has(target.entryId)) continue;\n\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\tif (entry && assistantEntryHasThinkingContentBlock(entry)) return target;\n\t}\n\treturn undefined;\n}\n\nexport function findLatestAssistantThinkingDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tconst latestRetainedAssistant = latestAssistantEntry(transcript, deletedEntryIds);\n\n\tfor (const target of targets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\t\tif (!entry || !assistantEntryHasThinkingContentBlock(entry)) continue;\n\t\t\tconst deletedEntryIdsIfTargetWereKept = new Set(deletedEntryIds);\n\t\t\tdeletedEntryIdsIfTargetWereKept.delete(target.entryId);\n\t\t\tif (latestAssistantEntry(transcript, deletedEntryIdsIfTargetWereKept)?.entryId === target.entryId) {\n\t\t\t\treturn target;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tlatestRetainedAssistant?.entryId === target.entryId &&\n\t\t\tassistantEntryHasThinkingContentBlock(latestRetainedAssistant)\n\t\t) {\n\t\t\treturn target;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport function assertNoAssistantThinkingContentBlockDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findAssistantThinkingContentBlockDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in a retained assistant message must remain unmodified; retained assistant messages containing thinking/redacted_thinking content blocks are all-or-nothing`,\n\t);\n}\n\nexport function assertNoLatestAssistantThinkingDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findLatestAssistantThinkingDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tif (violation.kind === \"entry\") {\n\t\tthrow new Error(\n\t\t\t`Cannot delete assistant entry ${violation.entryId} because it is the latest assistant message retained after other deletions and contains thinking/redacted_thinking content blocks`,\n\t\t);\n\t}\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in the latest assistant message must remain unmodified; the latest retained assistant message contains thinking/redacted_thinking content blocks`,\n\t);\n}\n\nexport function isToolCallBlockDeleted(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n\tdeletedEntryIds: ReadonlySet<string>,\n\tdeletedContentBlocks: ReadonlyMap<string, ReadonlySet<number>>,\n): boolean {\n\tif (deletedEntryIds.has(entry.entryId)) return true;\n\tconst deletedBlocks = deletedContentBlocks.get(entry.entryId);\n\tif (!deletedBlocks) return false;\n\treturn entry.contentBlocks.some((block) => block.toolCallId === callId && deletedBlocks.has(block.blockIndex));\n}\n\nexport function toolCallBlockIndexes(entry: CompactableTranscriptEntry, callId: string): number[] {\n\treturn entry.contentBlocks\n\t\t.filter((block) => block.toolCallId === callId)\n\t\t.map((block) => block.blockIndex);\n}\n\nexport function addTarget(targets: ContextDeletionTarget[], target: ContextDeletionTarget): boolean {\n\tif (targets.some((existing) => targetKey(existing) === targetKey(target))) return false;\n\ttargets.push(target);\n\treturn true;\n}\n\nexport function deleteEntryTarget(targets: ContextDeletionTarget[], entryId: string): boolean {\n\tlet changed = false;\n\tfor (let index = targets.length - 1; index >= 0; index--) {\n\t\tconst target = targets[index];\n\t\tif (target.kind === \"content_block\" && target.entryId === entryId) {\n\t\t\ttargets.splice(index, 1);\n\t\t\tchanged = true;\n\t\t}\n\t}\n\treturn addTarget(targets, { kind: \"entry\", entryId }) || changed;\n}\n\nexport function mergeContextDeletionTargets(\n\tbaseTargets: readonly ContextDeletionTarget[],\n\tadditionalTargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget[] {\n\tconst targets = [...baseTargets];\n\tfor (const target of additionalTargets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tdeleteEntryTarget(targets, target.entryId);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!getDeletedEntryIds(targets).has(target.entryId)) {\n\t\t\taddTarget(targets, target);\n\t\t}\n\t}\n\treturn targets;\n}\n\nexport function canonicalizeEntryTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n): boolean {\n\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\tif (getDeletedEntryIds(targets).has(entry.entryId)) return false;\n\tconst deletedBlocks = getDeletedContentBlocks(targets).get(entry.entryId);\n\tif (!deletedBlocks || !entry.contentBlocks.every((block) => deletedBlocks.has(block.blockIndex))) return false;\n\t// Only repair/promote when dependency reconciliation reaches this entry. Non-tool entries that\n\t// request every block individually stay invalid so the assistant must choose explicit entry deletion.\n\treturn deleteEntryTarget(targets, entry.entryId);\n}\n\nexport function addToolCallDeletion(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): boolean {\n\tif (assistantEntryHasThinkingContentBlock(entry)) {\n\t\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\t\treturn deleteEntryTarget(targets, entry.entryId);\n\t}\n\n\tlet changed = false;\n\tfor (const blockIndex of toolCallBlockIndexes(entry, callId)) {\n\t\tconst target: ContextDeletionTarget = { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n\t\tif (!canDeleteTarget(transcript, target)) continue;\n\t\tif (!getDeletedEntryIds(targets).has(entry.entryId)) {\n\t\t\tchanged = addTarget(targets, target) || changed;\n\t\t}\n\t}\n\treturn canonicalizeEntryTargets(transcript, targets, entry) || changed;\n}\n\nexport function isTaskBearingEntry(entry: CompactableTranscriptEntry): boolean {\n\treturn (\n\t\tentry.role === \"user\" ||\n\t\tentry.role === \"custom\" ||\n\t\tentry.role === \"branchSummary\" ||\n\t\tentry.entryType === \"branch_summary\"\n\t);\n}\n\nexport function isRecentTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\treturn entry !== undefined && isRecentContextEntry(entry, transcript);\n}\n\nexport function canDeleteTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\tif (!entry) return false;\n\tif (isRecentTarget(transcript, target)) return false;\n\tif (entry.protected) return false;\n\tif (target.kind === \"entry\") return true;\n\tconst block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);\n\tif (!block) return false;\n\treturn !block.protected;\n}\n\n"]}
|
|
1
|
+
{"version":3,"file":"context-deletion-targets.js","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-targets.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContextDeletionTarget } from \"../session-manager.ts\";\nimport type {\n\tCompactableContentBlock,\n\tCompactableTranscript,\n\tCompactableTranscriptEntry,\n\tContextDeletionRequest,\n} from \"./context-compaction-types.ts\";\nimport { getTranscriptCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport { assistantEntryHasThinkingContentBlock } from \"./context-transcript-analysis.ts\";\n\nexport function targetKey(target: ContextDeletionTarget): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function rawTargetKey(target: ContextDeletionRequest[\"deletions\"][number]): string {\n\treturn target.kind === \"entry\" ? `entry:${target.entryId}` : `content_block:${target.entryId}:${target.blockIndex}`;\n}\n\nexport function normalizeRawTarget(target: ContextDeletionRequest[\"deletions\"][number]): ContextDeletionTarget {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex as number };\n}\n\nexport function assertIdOnlyDeletionTarget(target: Record<string, unknown>): void {\n\tconst allowedKeys = target.kind === \"content_block\" ? new Set([\"kind\", \"entryId\", \"blockIndex\"]) : new Set([\"kind\", \"entryId\"]);\n\tfor (const key of Object.keys(target)) {\n\t\tif (!allowedKeys.has(key)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Deletion target includes unsupported property ${JSON.stringify(key)}; context deletion targets are id-only and must contain only kind, entryId${target.kind === \"content_block\" ? \", and blockIndex\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport function rawDeletionFromTarget(target: ContextDeletionTarget): ContextDeletionRequest[\"deletions\"][number] {\n\tif (target.kind === \"entry\") return { kind: \"entry\", entryId: target.entryId };\n\treturn { kind: \"content_block\", entryId: target.entryId, blockIndex: target.blockIndex };\n}\n\nexport function deletionRequestFromTargets(targets: readonly ContextDeletionTarget[]): ContextDeletionRequest {\n\treturn { deletions: targets.map(rawDeletionFromTarget) };\n}\n\nexport function getDeletedEntryIds(targets: readonly ContextDeletionTarget[]): Set<string> {\n\treturn new Set(targets.filter((target) => target.kind === \"entry\").map((target) => target.entryId));\n}\n\nexport function getDeletedContentBlocks(targets: readonly ContextDeletionTarget[]): Map<string, Set<number>> {\n\tconst blocksByEntry = new Map<string, Set<number>>();\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tconst blocks = blocksByEntry.get(target.entryId) ?? new Set<number>();\n\t\tblocks.add(target.blockIndex);\n\t\tblocksByEntry.set(target.entryId, blocks);\n\t}\n\treturn blocksByEntry;\n}\n\nexport function recentContextEntryBoundary(transcript: CompactableTranscript): number {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\treturn preserve_recent > 0 ? Math.max(0, transcript.entries.length - preserve_recent) : transcript.entries.length;\n}\n\nexport function getRecentContextEntryIds(transcript: CompactableTranscript): Set<string> {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return new Set();\n\treturn new Set(transcript.entries.slice(recentContextEntryBoundary(transcript)).map((entry) => entry.entryId));\n}\n\nexport function isRecentContextEntry(entry: CompactableTranscriptEntry, transcript: CompactableTranscript): boolean {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tif (preserve_recent <= 0) return false;\n\tconst entryIndex = transcript.entries.findIndex((candidate) => candidate.entryId === entry.entryId);\n\treturn entryIndex >= 0 && entryIndex >= recentContextEntryBoundary(transcript);\n}\n\nexport function formatRecentContextDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst { preserve_recent } = getTranscriptCompactionParameters(transcript);\n\tconst recentWindow = `last ${preserve_recent} context ${preserve_recent === 1 ? \"entry\" : \"entries\"}`;\n\tif (target.kind === \"entry\") {\n\t\treturn `Cannot delete recent context entry ${target.entryId} because the ${recentWindow} must remain available for active continuity. Choose an older entry.`;\n\t}\n\treturn `Cannot delete content block ${target.entryId}:${target.blockIndex} because entry ${target.entryId} is one of the ${recentWindow} that must remain available for active continuity. Choose an older entry or content block.`;\n}\n\nexport function deletionGuidance(): string {\n\treturn \"Choose another deletion candidate.\";\n}\n\nexport function findTranscriptEntry(transcript: CompactableTranscript, entryId: string): CompactableTranscriptEntry | undefined {\n\treturn transcript.entries.find((entry) => entry.entryId === entryId);\n}\n\nexport function findTranscriptContentBlock(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n): CompactableContentBlock | undefined {\n\tif (target.kind !== \"content_block\") return undefined;\n\treturn findTranscriptEntry(transcript, target.entryId)?.contentBlocks.find((block) => block.blockIndex === target.blockIndex);\n}\n\nexport function firstToolCallBlockTarget(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): ContextDeletionTarget | undefined {\n\tconst blockIndex = toolCallBlockIndexes(entry, callId)[0];\n\treturn blockIndex === undefined ? undefined : { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n}\n\nexport function formatProtectedDeletionError(transcript: CompactableTranscript, target: ContextDeletionTarget): string {\n\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\tif (target.kind === \"entry\") {\n\t\tconst toolResultSuffix = entry?.toolResultFor ? ` for tool call ${entry.toolResultFor}` : \"\";\n\t\tconst toolCallSuffix = entry && entry.toolCallIds.length > 0 ? ` containing tool call ${entry.toolCallIds.join(\", \")}` : \"\";\n\t\treturn `Deletion target ${target.entryId}${toolResultSuffix}${toolCallSuffix} is protected. ${deletionGuidance()}`;\n\t}\n\n\tconst block = findTranscriptContentBlock(transcript, target);\n\tconst toolBlockSuffix = block?.toolCallId ? ` It is a protected tool block for tool call ${block.toolCallId}.` : \"\";\n\treturn `Content block ${target.entryId}:${target.blockIndex} is protected.${toolBlockSuffix} ${deletionGuidance()}`;\n}\n\nexport function formatProtectedToolDependencyError(\n\ttranscript: CompactableTranscript,\n\tblockedTarget: ContextDeletionTarget,\n\tcontext: string,\n): string {\n\tconst protectedMessage = formatProtectedDeletionError(transcript, blockedTarget);\n\treturn `${context} ${protectedMessage}`;\n}\n\nexport function isProtectedContextDeletionErrorMessage(message: string): boolean {\n\treturn (\n\t\t/\\bprotected\\b/i.test(message) ||\n\t\t/Cannot delete (?:recent context entry|content block .* because entry .* is one of the last)/u.test(message) ||\n\t\t/latest assistant message|thinking\\/redacted_thinking block in (?:the latest|a retained) assistant message/u.test(message)\n\t);\n}\n\nexport function assertNoRecentContextDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst recentEntryIds = getRecentContextEntryIds(transcript);\n\tfor (const target of targets) {\n\t\tif (recentEntryIds.has(target.entryId)) {\n\t\t\tthrow new Error(formatRecentContextDeletionError(transcript, target));\n\t\t}\n\t}\n}\n\nexport function latestAssistantEntry(\n\ttranscript: CompactableTranscript,\n\tdeletedEntryIds: ReadonlySet<string> = new Set<string>(),\n): CompactableTranscriptEntry | undefined {\n\tfor (let index = transcript.entries.length - 1; index >= 0; index--) {\n\t\tconst entry = transcript.entries[index];\n\t\tif (entry.role === \"assistant\" && !deletedEntryIds.has(entry.entryId)) return entry;\n\t}\n\treturn undefined;\n}\n\nexport function findAssistantThinkingContentBlockDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): Extract<ContextDeletionTarget, { kind: \"content_block\" }> | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tfor (const target of targets) {\n\t\tif (target.kind !== \"content_block\") continue;\n\t\tif (deletedEntryIds.has(target.entryId)) continue;\n\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\tif (entry && assistantEntryHasThinkingContentBlock(entry)) return target;\n\t}\n\treturn undefined;\n}\n\nexport function findLatestAssistantThinkingDeletionViolation(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget | undefined {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tconst latestRetainedAssistant = latestAssistantEntry(transcript, deletedEntryIds);\n\n\tfor (const target of targets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tconst entry = findTranscriptEntry(transcript, target.entryId);\n\t\t\tif (!entry || !assistantEntryHasThinkingContentBlock(entry)) continue;\n\t\t\tconst deletedEntryIdsIfTargetWereKept = new Set(deletedEntryIds);\n\t\t\tdeletedEntryIdsIfTargetWereKept.delete(target.entryId);\n\t\t\tif (latestAssistantEntry(transcript, deletedEntryIdsIfTargetWereKept)?.entryId === target.entryId) {\n\t\t\t\treturn target;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tlatestRetainedAssistant?.entryId === target.entryId &&\n\t\t\tassistantEntryHasThinkingContentBlock(latestRetainedAssistant)\n\t\t) {\n\t\t\treturn target;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport function assertNoAssistantThinkingContentBlockDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findAssistantThinkingContentBlockDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in a retained assistant message must remain unmodified; retained assistant messages containing thinking/redacted_thinking content blocks are all-or-nothing`,\n\t);\n}\n\nexport function assertNoLatestAssistantThinkingDeletionTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): void {\n\tconst violation = findLatestAssistantThinkingDeletionViolation(transcript, targets);\n\tif (!violation) return;\n\tif (violation.kind === \"entry\") {\n\t\tthrow new Error(\n\t\t\t`Cannot delete assistant entry ${violation.entryId} because it is the latest assistant message retained after other deletions and contains thinking/redacted_thinking content blocks`,\n\t\t);\n\t}\n\tthrow new Error(\n\t\t`Cannot delete content block ${violation.entryId}:${violation.blockIndex} because a thinking/redacted_thinking block in the latest assistant message must remain unmodified; the latest retained assistant message contains thinking/redacted_thinking content blocks`,\n\t);\n}\n\nexport function isToolCallBlockDeleted(\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n\tdeletedEntryIds: ReadonlySet<string>,\n\tdeletedContentBlocks: ReadonlyMap<string, ReadonlySet<number>>,\n): boolean {\n\tif (deletedEntryIds.has(entry.entryId)) return true;\n\tconst deletedBlocks = deletedContentBlocks.get(entry.entryId);\n\tif (!deletedBlocks) return false;\n\treturn entry.contentBlocks.some((block) => block.toolCallId === callId && deletedBlocks.has(block.blockIndex));\n}\n\nexport function toolCallBlockIndexes(entry: CompactableTranscriptEntry, callId: string): number[] {\n\treturn entry.contentBlocks\n\t\t.filter((block) => block.toolCallId === callId)\n\t\t.map((block) => block.blockIndex);\n}\n\nexport function addTarget(targets: ContextDeletionTarget[], target: ContextDeletionTarget): boolean {\n\tif (targets.some((existing) => targetKey(existing) === targetKey(target))) return false;\n\ttargets.push(target);\n\treturn true;\n}\n\nexport function deleteEntryTarget(targets: ContextDeletionTarget[], entryId: string): boolean {\n\tlet changed = false;\n\tfor (let index = targets.length - 1; index >= 0; index--) {\n\t\tconst target = targets[index];\n\t\tif (target.kind === \"content_block\" && target.entryId === entryId) {\n\t\t\ttargets.splice(index, 1);\n\t\t\tchanged = true;\n\t\t}\n\t}\n\treturn addTarget(targets, { kind: \"entry\", entryId }) || changed;\n}\n\nexport function mergeContextDeletionTargets(\n\tbaseTargets: readonly ContextDeletionTarget[],\n\tadditionalTargets: readonly ContextDeletionTarget[],\n): ContextDeletionTarget[] {\n\tconst targets = [...baseTargets];\n\tfor (const target of additionalTargets) {\n\t\tif (target.kind === \"entry\") {\n\t\t\tdeleteEntryTarget(targets, target.entryId);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!getDeletedEntryIds(targets).has(target.entryId)) {\n\t\t\taddTarget(targets, target);\n\t\t}\n\t}\n\treturn targets;\n}\n\nexport function canonicalizeEntryTargets(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n): boolean {\n\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\tif (getDeletedEntryIds(targets).has(entry.entryId)) return false;\n\tconst deletedBlocks = getDeletedContentBlocks(targets).get(entry.entryId);\n\tif (!deletedBlocks || !entry.contentBlocks.every((block) => deletedBlocks.has(block.blockIndex))) return false;\n\t// Only repair/promote when dependency reconciliation reaches this entry. Non-tool entries that\n\t// request every block individually stay invalid so the assistant must choose explicit entry deletion.\n\treturn deleteEntryTarget(targets, entry.entryId);\n}\n\nexport function addToolCallDeletion(\n\ttranscript: CompactableTranscript,\n\ttargets: ContextDeletionTarget[],\n\tentry: CompactableTranscriptEntry,\n\tcallId: string,\n): boolean {\n\tif (assistantEntryHasThinkingContentBlock(entry)) {\n\t\tif (!canDeleteTarget(transcript, { kind: \"entry\", entryId: entry.entryId })) return false;\n\t\treturn deleteEntryTarget(targets, entry.entryId);\n\t}\n\n\tlet changed = false;\n\tfor (const blockIndex of toolCallBlockIndexes(entry, callId)) {\n\t\tconst target: ContextDeletionTarget = { kind: \"content_block\", entryId: entry.entryId, blockIndex };\n\t\tif (!canDeleteTarget(transcript, target)) continue;\n\t\tif (!getDeletedEntryIds(targets).has(entry.entryId)) {\n\t\t\tchanged = addTarget(targets, target) || changed;\n\t\t}\n\t}\n\treturn canonicalizeEntryTargets(transcript, targets, entry) || changed;\n}\n\nexport function isTaskBearingEntry(entry: CompactableTranscriptEntry): boolean {\n\treturn (\n\t\tentry.role === \"user\" ||\n\t\tentry.role === \"custom\" ||\n\t\tentry.role === \"branchSummary\" ||\n\t\tentry.entryType === \"branch_summary\"\n\t);\n}\n\nexport function isRecentTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\treturn entry !== undefined && isRecentContextEntry(entry, transcript);\n}\n\nexport function isStaleUserImageOnlyEntry(transcript: CompactableTranscript, entry: CompactableTranscriptEntry): boolean {\n\tif (entry.role !== \"user\" || isRecentContextEntry(entry, transcript)) return false;\n\tif (entry.contentBlocks.length === 0 || !entry.contentBlocks.every((block) => block.type === \"image\")) return false;\n\treturn transcript.entries.some((candidate) => candidate.entryId !== entry.entryId && isTaskBearingEntry(candidate));\n}\n\nexport function canDeleteStaleUserImageContentBlock(\n\ttranscript: CompactableTranscript,\n\ttarget: ContextDeletionTarget,\n): boolean {\n\tif (target.kind !== \"content_block\") return false;\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\tif (!entry || entry.role !== \"user\" || isRecentTarget(transcript, target)) return false;\n\tconst block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);\n\tif (!block || block.type !== \"image\") return false;\n\treturn entry.contentBlocks.some((candidate) => candidate.blockIndex !== target.blockIndex && candidate.type !== \"image\");\n}\n\nexport function canDeleteTarget(transcript: CompactableTranscript, target: ContextDeletionTarget): boolean {\n\tconst entry = transcript.entries.find((candidate) => candidate.entryId === target.entryId);\n\tif (!entry) return false;\n\tif (isRecentTarget(transcript, target)) return false;\n\tif (target.kind === \"entry\") return isStaleUserImageOnlyEntry(transcript, entry) || !entry.protected;\n\tconst block = entry.contentBlocks.find((candidate) => candidate.blockIndex === target.blockIndex);\n\tif (!block) return false;\n\tif (canDeleteStaleUserImageContentBlock(transcript, target)) return true;\n\tif (entry.protected) return false;\n\treturn !block.protected;\n}\n\n"]}
|
|
@@ -170,6 +170,12 @@ export interface ContextCompactionBudgetToolDetails {
|
|
|
170
170
|
tokensToDeleteForTarget: number;
|
|
171
171
|
contextWindowBeforePercent?: number;
|
|
172
172
|
contextWindowAfterPercent?: number;
|
|
173
|
+
/** Total estimated tokens consumed by image content blocks still remaining after selected deletions. */
|
|
174
|
+
remainingImageTokens: number;
|
|
175
|
+
/** Number of image content blocks still remaining after selected deletions. */
|
|
176
|
+
imageBlockCount: number;
|
|
177
|
+
/** Image tokens as a percentage of the remaining context (post-deletion token total). */
|
|
178
|
+
imageTokenPercent: number;
|
|
173
179
|
callCount: number;
|
|
174
180
|
}
|
|
175
181
|
export interface ContextDeletionToolController {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-deletion-tool-definitions.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-tool-definitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,KAAK,EAAE,sBAAsB,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAE5G,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AACzD,eAAO,MAAM,6BAA6B,wBAAwB,CAAC;AACnE,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AAC/E,eAAO,MAAM,4BAA4B,uBAAuB,CAAC;AACjE,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AAC/E,eAAO,MAAM,uCAAuC,KAAK,CAAC;AAC1D,eAAO,MAAM,2CAA2C,MAAM,CAAC;AAC/D,eAAO,MAAM,wCAAwC,SAAU,CAAC;AAChE,eAAO,MAAM,oCAAoC,OAAO,CAAC;AACzD,eAAO,MAAM,4BAA4B,QAAS,CAAC;AACnD,eAAO,MAAM,kCAAkC,KAAK,CAAC;AACrD,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAC9C,eAAO,MAAM,oCAAoC,MAAM,CAAC;AACxD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAGpD,eAAO,MAAM,2BAA2B;;;;;;EAyBvC,CAAC;AAEF,eAAO,MAAM,+BAA+B;;;;;;;EA0B3C,CAAC;AAEF,eAAO,MAAM,qCAAqC;;;;;;;EAsBjD,CAAC;AAEF,eAAO,MAAM,8BAA8B;;;;;EAgB1C,CAAC;AAEF,eAAO,MAAM,qCAAqC,kBAAmD,CAAC;AAEtG,eAAO,MAAM,mBAAmB;aAC/B,IAAI;aACJ,WAAW,EAAE,6EAA6E;aAC1F,UAAU;;;;;;;CACD,CAAC;AAEX,eAAO,MAAM,wBAAwB;aACpC,IAAI;aACJ,WAAW,EAAE,uFAAuF;aACpG,UAAU;;;;;;;;CACD,CAAC;AAEX,eAAO,MAAM,8BAA8B;aAC1C,IAAI;aACJ,WAAW,EAAE,oGAAoG;aACjH,UAAU;;;;;;;;CACD,CAAC;AAEX,eAAO,MAAM,uBAAuB;aACnC,IAAI;aACJ,WAAW,EAAE,oGAAoG;aACjH,UAAU;;;;;;CACD,CAAC;AAEX,eAAO,MAAM,8BAA8B;aAC1C,IAAI;aACJ,WAAW,EACV,kIAAkI;aACnI,UAAU;CACD,CAAC;AAEX,MAAM,WAAW,0BAA0B;IAC1C,SAAS,EAAE,sBAAsB,CAAC,WAAW,CAAC,CAAC;IAC/C,cAAc,EAAE,qBAAqB,EAAE,CAAC;IACxC,KAAK,EAAE,sBAAsB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,GAAG,eAAe,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,0BAA0B;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EACH,iBAAiB,GACjB,iBAAiB,GACjB,0BAA0B,GAC1B,0BAA0B,GAC1B,iBAAiB,GACjB,sBAAsB,GACtB,+BAA+B,CAAC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,8BAA8B;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,OAAO,GAAG,eAAe,CAAC;IAClC,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,OAAO,EAAE,0BAA0B,EAAE,CAAC;IACtC,cAAc,EAAE,qBAAqB,EAAE,CAAC;IACxC,KAAK,EAAE,sBAAsB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,4BAA4B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,GAAG,eAAe,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kCAAkC;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,OAAO,GAAG,eAAe,CAAC;IAClC,OAAO,EAAE,4BAA4B,EAAE,CAAC;IACxC,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,2BAA2B;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kCAAkC;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,EAAE,MAAM,CAAC;IAChC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uBAAuB,EAAE,MAAM,CAAC;IAChC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,6BAA6B;IAC7C,IAAI,EAAE,SAAS,CAAC,OAAO,2BAA2B,EAAE,0BAA0B,CAAC,CAAC;IAChF,QAAQ,EAAE,SAAS,CAAC,OAAO,+BAA+B,EAAE,8BAA8B,CAAC,CAAC;IAC5F,UAAU,EAAE,SAAS,CAAC,OAAO,qCAAqC,EAAE,kCAAkC,CAAC,CAAC;IACxG,aAAa,EAAE,SAAS,CAAC,OAAO,8BAA8B,EAAE,2BAA2B,CAAC,CAAC;IAC7F,UAAU,EAAE,SAAS,CAAC,OAAO,qCAAqC,EAAE,kCAAkC,CAAC,CAAC;IACxG,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,kBAAkB,IAAI,sBAAsB,CAAC;IAC7C,kBAAkB,IAAI,8BAA8B,GAAG,SAAS,CAAC;IACjE,YAAY,IAAI,MAAM,GAAG,SAAS,CAAC;IACnC,YAAY,IAAI,MAAM,CAAC;CACvB","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { StringEnum } from \"@earendil-works/pi-ai\";\nimport { Type } from \"typebox\";\nimport type { ContextCompactionStats, ContextDeletionTarget } from \"../session-manager.ts\";\nimport type { ContextDeletionRequest, ValidatedContextDeletionResult } from \"./context-compaction-types.ts\";\n\nexport const CONTEXT_DELETE_TOOL_NAME = \"context_delete\";\nexport const CONTEXT_GREP_DELETE_TOOL_NAME = \"context_grep_delete\";\nexport const CONTEXT_SEARCH_TRANSCRIPT_TOOL_NAME = \"context_search_transcript\";\nexport const CONTEXT_READ_ENTRY_TOOL_NAME = \"context_read_entry\";\nexport const CONTEXT_COMPACTION_BUDGET_TOOL_NAME = \"context_compaction_budget\";\nexport const CONTEXT_GREP_DELETE_DEFAULT_MAX_MATCHES = 50;\nexport const CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS = 512;\nexport const CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS = 250_000;\nexport const CONTEXT_READ_ENTRY_DEFAULT_MAX_CHARS = 4000;\nexport const CONTEXT_READ_ENTRY_MAX_CHARS = 12_000;\nexport const CONTEXT_SEARCH_DEFAULT_MAX_MATCHES = 20;\nexport const CONTEXT_SEARCH_MAX_MATCHES = 100;\nexport const CONTEXT_SEARCH_DEFAULT_CONTEXT_CHARS = 160;\nexport const CONTEXT_SEARCH_MAX_CONTEXT_CHARS = 500;\n\n\nexport const ContextDeleteToolParameters = Type.Object(\n\t{\n\t\tdeletions: Type.Array(\n\t\t\tType.Object(\n\t\t\t\t{\n\t\t\t\t\tkind: StringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\t\t\tdescription: \"Delete an entire transcript entry or a single content block within one entry.\",\n\t\t\t\t\t}),\n\t\t\t\t\tentryId: Type.String({ minLength: 1, description: \"Stable transcript entry id to delete from.\" }),\n\t\t\t\t\tblockIndex: Type.Optional(\n\t\t\t\t\t\tType.Integer({\n\t\t\t\t\t\t\tminimum: 0,\n\t\t\t\t\t\t\tdescription: \"Required when kind is content_block; omit when kind is entry.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\t{\n\t\t\t\tdescription:\n\t\t\t\t\t\"ID-only deletion targets. Include only kind, entryId, and blockIndex when needed; do not include transcript text, block contents, summaries, or replacement content. Invalid targets are rejected by the tool with correction guidance.\",\n\t\t\t},\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextGrepDeleteToolParameters = Type.Object(\n\t{\n\t\tpattern: Type.String({ minLength: 1, description: \"Literal text or regular expression to match in transcript text.\" }),\n\t\tregex: Type.Optional(Type.Boolean({ description: \"Treat pattern as a JavaScript regular expression. Defaults to false.\" })),\n\t\tcaseSensitive: Type.Optional(Type.Boolean({ description: \"Use case-sensitive matching. Defaults to false.\" })),\n\t\ttarget: Type.Optional(\n\t\t\tStringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\tdescription: \"Delete whole matching entries or matching content blocks. Defaults to entry.\",\n\t\t\t}),\n\t\t),\n\t\tmaxMatches: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 1,\n\t\t\t\tmaximum: 200,\n\t\t\t\tdescription:\n\t\t\t\t\t\"Per-call safety cap. If more not-yet-deleted candidate targets are found in this tool call, no deletions are applied. Defaults to 50. This is not a cumulative compaction cap; call the tool again for additional batches.\",\n\t\t\t}),\n\t\t),\n\t\texpectedMatchCount: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 0,\n\t\t\t\tdescription: \"Optional safety check. If the match count differs, no deletions are applied.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextSearchTranscriptToolParameters = Type.Object(\n\t{\n\t\tpattern: Type.String({ minLength: 1, description: \"Literal text or regular expression to search for.\" }),\n\t\tregex: Type.Optional(Type.Boolean({ description: \"Treat pattern as a JavaScript regular expression. Defaults to false.\" })),\n\t\tcaseSensitive: Type.Optional(Type.Boolean({ description: \"Use case-sensitive matching. Defaults to false.\" })),\n\t\ttarget: Type.Optional(\n\t\t\tStringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\tdescription: \"Search whole entry text or individual content-block text. Defaults to entry.\",\n\t\t\t}),\n\t\t),\n\t\tmaxMatches: Type.Optional(\n\t\t\tType.Integer({ minimum: 1, maximum: CONTEXT_SEARCH_MAX_MATCHES, description: \"Maximum matches to return. Defaults to 20.\" }),\n\t\t),\n\t\tcontextChars: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 0,\n\t\t\t\tmaximum: CONTEXT_SEARCH_MAX_CONTEXT_CHARS,\n\t\t\t\tdescription: \"Characters of context to include before and after each match. Defaults to 160.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextReadEntryToolParameters = Type.Object(\n\t{\n\t\tentryId: Type.String({ minLength: 1, description: \"Stable transcript entry id to read.\" }),\n\t\tblockIndex: Type.Optional(\n\t\t\tType.Integer({ minimum: 0, description: \"Optional content block index to read instead of the whole entry text.\" }),\n\t\t),\n\t\toffset: Type.Optional(Type.Integer({ minimum: 0, description: \"Character offset to begin reading. Defaults to 0.\" })),\n\t\tmaxChars: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 1,\n\t\t\t\tmaximum: CONTEXT_READ_ENTRY_MAX_CHARS,\n\t\t\t\tdescription: \"Maximum characters to return. Defaults to 4000; keep reads small to avoid overflowing context.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextCompactionBudgetToolParameters = Type.Object({}, { additionalProperties: false });\n\nexport const CONTEXT_DELETE_TOOL = {\n\tname: CONTEXT_DELETE_TOOL_NAME,\n\tdescription: \"Record context compaction deletion targets directly against the transcript.\",\n\tparameters: ContextDeleteToolParameters,\n} as const;\n\nexport const CONTEXT_GREP_DELETE_TOOL = {\n\tname: CONTEXT_GREP_DELETE_TOOL_NAME,\n\tdescription: \"Bulk-delete transcript entries or content blocks matching a guarded grep/regex query.\",\n\tparameters: ContextGrepDeleteToolParameters,\n} as const;\n\nexport const CONTEXT_SEARCH_TRANSCRIPT_TOOL = {\n\tname: CONTEXT_SEARCH_TRANSCRIPT_TOOL_NAME,\n\tdescription: \"Search the full transcript working copy and return small snippets without mutating deletion state.\",\n\tparameters: ContextSearchTranscriptToolParameters,\n} as const;\n\nexport const CONTEXT_READ_ENTRY_TOOL = {\n\tname: CONTEXT_READ_ENTRY_TOOL_NAME,\n\tdescription: \"Read a small slice of one transcript entry or content block from the full transcript working copy.\",\n\tparameters: ContextReadEntryToolParameters,\n} as const;\n\nexport const CONTEXT_COMPACTION_BUDGET_TOOL = {\n\tname: CONTEXT_COMPACTION_BUDGET_TOOL_NAME,\n\tdescription:\n\t\t\"Report current context-window fullness and reduction progress for the selected deletion targets without mutating deletion state.\",\n\tparameters: ContextCompactionBudgetToolParameters,\n} as const;\n\nexport interface ContextDeletionToolDetails {\n\tdeletions: ContextDeletionRequest[\"deletions\"];\n\tdeletedTargets: ContextDeletionTarget[];\n\tstats: ContextCompactionStats;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextGrepDeletionMatch {\n\tentryId: string;\n\ttarget: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\ttext: string;\n}\n\nexport interface ContextGrepDeletionSkipped {\n\tentryId?: string;\n\ttarget?: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\treason:\n\t\t| \"protected_entry\"\n\t\t| \"protected_block\"\n\t\t| \"assistant_thinking_entry\"\n\t\t| \"assistant_thinking_block\"\n\t\t| \"already_deleted\"\n\t\t| \"max_matches_exceeded\"\n\t\t| \"expected_match_count_mismatch\";\n\ttext?: string;\n}\n\nexport interface ContextGrepDeletionToolDetails {\n\tpattern: string;\n\tregex: boolean;\n\tcaseSensitive: boolean;\n\ttarget: \"entry\" | \"content_block\";\n\tmatches: ContextGrepDeletionMatch[];\n\tskipped: ContextGrepDeletionSkipped[];\n\tdeletedTargets: ContextDeletionTarget[];\n\tstats: ContextCompactionStats;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextTranscriptSearchMatch {\n\tentryId: string;\n\ttarget: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\tmatchIndex: number;\n\tsnippet: string;\n\tprotected: boolean;\n}\n\nexport interface ContextTranscriptSearchToolDetails {\n\tpattern: string;\n\tregex: boolean;\n\tcaseSensitive: boolean;\n\ttarget: \"entry\" | \"content_block\";\n\tmatches: ContextTranscriptSearchMatch[];\n\ttruncated: boolean;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextReadEntryToolDetails {\n\tentryId: string;\n\tblockIndex?: number;\n\toffset: number;\n\tmaxChars: number;\n\ttotalChars: number;\n\ttext: string;\n\ttruncatedBefore: boolean;\n\ttruncatedAfter: boolean;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextCompactionBudgetToolDetails {\n\tcontextWindow?: number;\n\tcompression_ratio: number;\n\ttokensBefore: number;\n\tcurrentTokensAfter: number;\n\tdeletedTokens: number;\n\tcurrentReductionPercent: number;\n\ttargetReductionPercent: number;\n\ttargetTokensAfter: number;\n\ttokensToDeleteForTarget: number;\n\tcontextWindowBeforePercent?: number;\n\tcontextWindowAfterPercent?: number;\n\tcallCount: number;\n}\n\nexport interface ContextDeletionToolController {\n\ttool: AgentTool<typeof ContextDeleteToolParameters, ContextDeletionToolDetails>;\n\tgrepTool: AgentTool<typeof ContextGrepDeleteToolParameters, ContextGrepDeletionToolDetails>;\n\tsearchTool: AgentTool<typeof ContextSearchTranscriptToolParameters, ContextTranscriptSearchToolDetails>;\n\treadEntryTool: AgentTool<typeof ContextReadEntryToolParameters, ContextReadEntryToolDetails>;\n\tbudgetTool: AgentTool<typeof ContextCompactionBudgetToolParameters, ContextCompactionBudgetToolDetails>;\n\ttools: AgentTool[];\n\tgetDeletionRequest(): ContextDeletionRequest;\n\tgetValidatedResult(): ValidatedContextDeletionResult | undefined;\n\tgetLastError(): string | undefined;\n\tgetCallCount(): number;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"context-deletion-tool-definitions.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-tool-definitions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { StringEnum } from \"@earendil-works/pi-ai\";\nimport { Type } from \"typebox\";\nimport type { ContextCompactionStats, ContextDeletionTarget } from \"../session-manager.ts\";\nimport type { ContextDeletionRequest, ValidatedContextDeletionResult } from \"./context-compaction-types.ts\";\n\nexport const CONTEXT_DELETE_TOOL_NAME = \"context_delete\";\nexport const CONTEXT_GREP_DELETE_TOOL_NAME = \"context_grep_delete\";\nexport const CONTEXT_SEARCH_TRANSCRIPT_TOOL_NAME = \"context_search_transcript\";\nexport const CONTEXT_READ_ENTRY_TOOL_NAME = \"context_read_entry\";\nexport const CONTEXT_COMPACTION_BUDGET_TOOL_NAME = \"context_compaction_budget\";\nexport const CONTEXT_GREP_DELETE_DEFAULT_MAX_MATCHES = 50;\nexport const CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS = 512;\nexport const CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS = 250_000;\nexport const CONTEXT_READ_ENTRY_DEFAULT_MAX_CHARS = 4000;\nexport const CONTEXT_READ_ENTRY_MAX_CHARS = 12_000;\nexport const CONTEXT_SEARCH_DEFAULT_MAX_MATCHES = 20;\nexport const CONTEXT_SEARCH_MAX_MATCHES = 100;\nexport const CONTEXT_SEARCH_DEFAULT_CONTEXT_CHARS = 160;\nexport const CONTEXT_SEARCH_MAX_CONTEXT_CHARS = 500;\n\n\nexport const ContextDeleteToolParameters = Type.Object(\n\t{\n\t\tdeletions: Type.Array(\n\t\t\tType.Object(\n\t\t\t\t{\n\t\t\t\t\tkind: StringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\t\t\tdescription: \"Delete an entire transcript entry or a single content block within one entry.\",\n\t\t\t\t\t}),\n\t\t\t\t\tentryId: Type.String({ minLength: 1, description: \"Stable transcript entry id to delete from.\" }),\n\t\t\t\t\tblockIndex: Type.Optional(\n\t\t\t\t\t\tType.Integer({\n\t\t\t\t\t\t\tminimum: 0,\n\t\t\t\t\t\t\tdescription: \"Required when kind is content_block; omit when kind is entry.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\t{\n\t\t\t\tdescription:\n\t\t\t\t\t\"ID-only deletion targets. Include only kind, entryId, and blockIndex when needed; do not include transcript text, block contents, summaries, or replacement content. Invalid targets are rejected by the tool with correction guidance.\",\n\t\t\t},\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextGrepDeleteToolParameters = Type.Object(\n\t{\n\t\tpattern: Type.String({ minLength: 1, description: \"Literal text or regular expression to match in transcript text.\" }),\n\t\tregex: Type.Optional(Type.Boolean({ description: \"Treat pattern as a JavaScript regular expression. Defaults to false.\" })),\n\t\tcaseSensitive: Type.Optional(Type.Boolean({ description: \"Use case-sensitive matching. Defaults to false.\" })),\n\t\ttarget: Type.Optional(\n\t\t\tStringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\tdescription: \"Delete whole matching entries or matching content blocks. Defaults to entry.\",\n\t\t\t}),\n\t\t),\n\t\tmaxMatches: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 1,\n\t\t\t\tmaximum: 200,\n\t\t\t\tdescription:\n\t\t\t\t\t\"Per-call safety cap. If more not-yet-deleted candidate targets are found in this tool call, no deletions are applied. Defaults to 50. This is not a cumulative compaction cap; call the tool again for additional batches.\",\n\t\t\t}),\n\t\t),\n\t\texpectedMatchCount: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 0,\n\t\t\t\tdescription: \"Optional safety check. If the match count differs, no deletions are applied.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextSearchTranscriptToolParameters = Type.Object(\n\t{\n\t\tpattern: Type.String({ minLength: 1, description: \"Literal text or regular expression to search for.\" }),\n\t\tregex: Type.Optional(Type.Boolean({ description: \"Treat pattern as a JavaScript regular expression. Defaults to false.\" })),\n\t\tcaseSensitive: Type.Optional(Type.Boolean({ description: \"Use case-sensitive matching. Defaults to false.\" })),\n\t\ttarget: Type.Optional(\n\t\t\tStringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\tdescription: \"Search whole entry text or individual content-block text. Defaults to entry.\",\n\t\t\t}),\n\t\t),\n\t\tmaxMatches: Type.Optional(\n\t\t\tType.Integer({ minimum: 1, maximum: CONTEXT_SEARCH_MAX_MATCHES, description: \"Maximum matches to return. Defaults to 20.\" }),\n\t\t),\n\t\tcontextChars: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 0,\n\t\t\t\tmaximum: CONTEXT_SEARCH_MAX_CONTEXT_CHARS,\n\t\t\t\tdescription: \"Characters of context to include before and after each match. Defaults to 160.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextReadEntryToolParameters = Type.Object(\n\t{\n\t\tentryId: Type.String({ minLength: 1, description: \"Stable transcript entry id to read.\" }),\n\t\tblockIndex: Type.Optional(\n\t\t\tType.Integer({ minimum: 0, description: \"Optional content block index to read instead of the whole entry text.\" }),\n\t\t),\n\t\toffset: Type.Optional(Type.Integer({ minimum: 0, description: \"Character offset to begin reading. Defaults to 0.\" })),\n\t\tmaxChars: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 1,\n\t\t\t\tmaximum: CONTEXT_READ_ENTRY_MAX_CHARS,\n\t\t\t\tdescription: \"Maximum characters to return. Defaults to 4000; keep reads small to avoid overflowing context.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextCompactionBudgetToolParameters = Type.Object({}, { additionalProperties: false });\n\nexport const CONTEXT_DELETE_TOOL = {\n\tname: CONTEXT_DELETE_TOOL_NAME,\n\tdescription: \"Record context compaction deletion targets directly against the transcript.\",\n\tparameters: ContextDeleteToolParameters,\n} as const;\n\nexport const CONTEXT_GREP_DELETE_TOOL = {\n\tname: CONTEXT_GREP_DELETE_TOOL_NAME,\n\tdescription: \"Bulk-delete transcript entries or content blocks matching a guarded grep/regex query.\",\n\tparameters: ContextGrepDeleteToolParameters,\n} as const;\n\nexport const CONTEXT_SEARCH_TRANSCRIPT_TOOL = {\n\tname: CONTEXT_SEARCH_TRANSCRIPT_TOOL_NAME,\n\tdescription: \"Search the full transcript working copy and return small snippets without mutating deletion state.\",\n\tparameters: ContextSearchTranscriptToolParameters,\n} as const;\n\nexport const CONTEXT_READ_ENTRY_TOOL = {\n\tname: CONTEXT_READ_ENTRY_TOOL_NAME,\n\tdescription: \"Read a small slice of one transcript entry or content block from the full transcript working copy.\",\n\tparameters: ContextReadEntryToolParameters,\n} as const;\n\nexport const CONTEXT_COMPACTION_BUDGET_TOOL = {\n\tname: CONTEXT_COMPACTION_BUDGET_TOOL_NAME,\n\tdescription:\n\t\t\"Report current context-window fullness and reduction progress for the selected deletion targets without mutating deletion state.\",\n\tparameters: ContextCompactionBudgetToolParameters,\n} as const;\n\nexport interface ContextDeletionToolDetails {\n\tdeletions: ContextDeletionRequest[\"deletions\"];\n\tdeletedTargets: ContextDeletionTarget[];\n\tstats: ContextCompactionStats;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextGrepDeletionMatch {\n\tentryId: string;\n\ttarget: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\ttext: string;\n}\n\nexport interface ContextGrepDeletionSkipped {\n\tentryId?: string;\n\ttarget?: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\treason:\n\t\t| \"protected_entry\"\n\t\t| \"protected_block\"\n\t\t| \"assistant_thinking_entry\"\n\t\t| \"assistant_thinking_block\"\n\t\t| \"already_deleted\"\n\t\t| \"max_matches_exceeded\"\n\t\t| \"expected_match_count_mismatch\";\n\ttext?: string;\n}\n\nexport interface ContextGrepDeletionToolDetails {\n\tpattern: string;\n\tregex: boolean;\n\tcaseSensitive: boolean;\n\ttarget: \"entry\" | \"content_block\";\n\tmatches: ContextGrepDeletionMatch[];\n\tskipped: ContextGrepDeletionSkipped[];\n\tdeletedTargets: ContextDeletionTarget[];\n\tstats: ContextCompactionStats;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextTranscriptSearchMatch {\n\tentryId: string;\n\ttarget: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\tmatchIndex: number;\n\tsnippet: string;\n\tprotected: boolean;\n}\n\nexport interface ContextTranscriptSearchToolDetails {\n\tpattern: string;\n\tregex: boolean;\n\tcaseSensitive: boolean;\n\ttarget: \"entry\" | \"content_block\";\n\tmatches: ContextTranscriptSearchMatch[];\n\ttruncated: boolean;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextReadEntryToolDetails {\n\tentryId: string;\n\tblockIndex?: number;\n\toffset: number;\n\tmaxChars: number;\n\ttotalChars: number;\n\ttext: string;\n\ttruncatedBefore: boolean;\n\ttruncatedAfter: boolean;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextCompactionBudgetToolDetails {\n\tcontextWindow?: number;\n\tcompression_ratio: number;\n\ttokensBefore: number;\n\tcurrentTokensAfter: number;\n\tdeletedTokens: number;\n\tcurrentReductionPercent: number;\n\ttargetReductionPercent: number;\n\ttargetTokensAfter: number;\n\ttokensToDeleteForTarget: number;\n\tcontextWindowBeforePercent?: number;\n\tcontextWindowAfterPercent?: number;\n\t/** Total estimated tokens consumed by image content blocks still remaining after selected deletions. */\n\tremainingImageTokens: number;\n\t/** Number of image content blocks still remaining after selected deletions. */\n\timageBlockCount: number;\n\t/** Image tokens as a percentage of the remaining context (post-deletion token total). */\n\timageTokenPercent: number;\n\tcallCount: number;\n}\n\nexport interface ContextDeletionToolController {\n\ttool: AgentTool<typeof ContextDeleteToolParameters, ContextDeletionToolDetails>;\n\tgrepTool: AgentTool<typeof ContextGrepDeleteToolParameters, ContextGrepDeletionToolDetails>;\n\tsearchTool: AgentTool<typeof ContextSearchTranscriptToolParameters, ContextTranscriptSearchToolDetails>;\n\treadEntryTool: AgentTool<typeof ContextReadEntryToolParameters, ContextReadEntryToolDetails>;\n\tbudgetTool: AgentTool<typeof ContextCompactionBudgetToolParameters, ContextCompactionBudgetToolDetails>;\n\ttools: AgentTool[];\n\tgetDeletionRequest(): ContextDeletionRequest;\n\tgetValidatedResult(): ValidatedContextDeletionResult | undefined;\n\tgetLastError(): string | undefined;\n\tgetCallCount(): number;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-deletion-tool-definitions.js","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-tool-definitions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { StringEnum } from \"@earendil-works/pi-ai\";\nimport { Type } from \"typebox\";\nimport type { ContextCompactionStats, ContextDeletionTarget } from \"../session-manager.ts\";\nimport type { ContextDeletionRequest, ValidatedContextDeletionResult } from \"./context-compaction-types.ts\";\n\nexport const CONTEXT_DELETE_TOOL_NAME = \"context_delete\";\nexport const CONTEXT_GREP_DELETE_TOOL_NAME = \"context_grep_delete\";\nexport const CONTEXT_SEARCH_TRANSCRIPT_TOOL_NAME = \"context_search_transcript\";\nexport const CONTEXT_READ_ENTRY_TOOL_NAME = \"context_read_entry\";\nexport const CONTEXT_COMPACTION_BUDGET_TOOL_NAME = \"context_compaction_budget\";\nexport const CONTEXT_GREP_DELETE_DEFAULT_MAX_MATCHES = 50;\nexport const CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS = 512;\nexport const CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS = 250_000;\nexport const CONTEXT_READ_ENTRY_DEFAULT_MAX_CHARS = 4000;\nexport const CONTEXT_READ_ENTRY_MAX_CHARS = 12_000;\nexport const CONTEXT_SEARCH_DEFAULT_MAX_MATCHES = 20;\nexport const CONTEXT_SEARCH_MAX_MATCHES = 100;\nexport const CONTEXT_SEARCH_DEFAULT_CONTEXT_CHARS = 160;\nexport const CONTEXT_SEARCH_MAX_CONTEXT_CHARS = 500;\n\n\nexport const ContextDeleteToolParameters = Type.Object(\n\t{\n\t\tdeletions: Type.Array(\n\t\t\tType.Object(\n\t\t\t\t{\n\t\t\t\t\tkind: StringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\t\t\tdescription: \"Delete an entire transcript entry or a single content block within one entry.\",\n\t\t\t\t\t}),\n\t\t\t\t\tentryId: Type.String({ minLength: 1, description: \"Stable transcript entry id to delete from.\" }),\n\t\t\t\t\tblockIndex: Type.Optional(\n\t\t\t\t\t\tType.Integer({\n\t\t\t\t\t\t\tminimum: 0,\n\t\t\t\t\t\t\tdescription: \"Required when kind is content_block; omit when kind is entry.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\t{\n\t\t\t\tdescription:\n\t\t\t\t\t\"ID-only deletion targets. Include only kind, entryId, and blockIndex when needed; do not include transcript text, block contents, summaries, or replacement content. Invalid targets are rejected by the tool with correction guidance.\",\n\t\t\t},\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextGrepDeleteToolParameters = Type.Object(\n\t{\n\t\tpattern: Type.String({ minLength: 1, description: \"Literal text or regular expression to match in transcript text.\" }),\n\t\tregex: Type.Optional(Type.Boolean({ description: \"Treat pattern as a JavaScript regular expression. Defaults to false.\" })),\n\t\tcaseSensitive: Type.Optional(Type.Boolean({ description: \"Use case-sensitive matching. Defaults to false.\" })),\n\t\ttarget: Type.Optional(\n\t\t\tStringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\tdescription: \"Delete whole matching entries or matching content blocks. Defaults to entry.\",\n\t\t\t}),\n\t\t),\n\t\tmaxMatches: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 1,\n\t\t\t\tmaximum: 200,\n\t\t\t\tdescription:\n\t\t\t\t\t\"Per-call safety cap. If more not-yet-deleted candidate targets are found in this tool call, no deletions are applied. Defaults to 50. This is not a cumulative compaction cap; call the tool again for additional batches.\",\n\t\t\t}),\n\t\t),\n\t\texpectedMatchCount: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 0,\n\t\t\t\tdescription: \"Optional safety check. If the match count differs, no deletions are applied.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextSearchTranscriptToolParameters = Type.Object(\n\t{\n\t\tpattern: Type.String({ minLength: 1, description: \"Literal text or regular expression to search for.\" }),\n\t\tregex: Type.Optional(Type.Boolean({ description: \"Treat pattern as a JavaScript regular expression. Defaults to false.\" })),\n\t\tcaseSensitive: Type.Optional(Type.Boolean({ description: \"Use case-sensitive matching. Defaults to false.\" })),\n\t\ttarget: Type.Optional(\n\t\t\tStringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\tdescription: \"Search whole entry text or individual content-block text. Defaults to entry.\",\n\t\t\t}),\n\t\t),\n\t\tmaxMatches: Type.Optional(\n\t\t\tType.Integer({ minimum: 1, maximum: CONTEXT_SEARCH_MAX_MATCHES, description: \"Maximum matches to return. Defaults to 20.\" }),\n\t\t),\n\t\tcontextChars: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 0,\n\t\t\t\tmaximum: CONTEXT_SEARCH_MAX_CONTEXT_CHARS,\n\t\t\t\tdescription: \"Characters of context to include before and after each match. Defaults to 160.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextReadEntryToolParameters = Type.Object(\n\t{\n\t\tentryId: Type.String({ minLength: 1, description: \"Stable transcript entry id to read.\" }),\n\t\tblockIndex: Type.Optional(\n\t\t\tType.Integer({ minimum: 0, description: \"Optional content block index to read instead of the whole entry text.\" }),\n\t\t),\n\t\toffset: Type.Optional(Type.Integer({ minimum: 0, description: \"Character offset to begin reading. Defaults to 0.\" })),\n\t\tmaxChars: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 1,\n\t\t\t\tmaximum: CONTEXT_READ_ENTRY_MAX_CHARS,\n\t\t\t\tdescription: \"Maximum characters to return. Defaults to 4000; keep reads small to avoid overflowing context.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextCompactionBudgetToolParameters = Type.Object({}, { additionalProperties: false });\n\nexport const CONTEXT_DELETE_TOOL = {\n\tname: CONTEXT_DELETE_TOOL_NAME,\n\tdescription: \"Record context compaction deletion targets directly against the transcript.\",\n\tparameters: ContextDeleteToolParameters,\n} as const;\n\nexport const CONTEXT_GREP_DELETE_TOOL = {\n\tname: CONTEXT_GREP_DELETE_TOOL_NAME,\n\tdescription: \"Bulk-delete transcript entries or content blocks matching a guarded grep/regex query.\",\n\tparameters: ContextGrepDeleteToolParameters,\n} as const;\n\nexport const CONTEXT_SEARCH_TRANSCRIPT_TOOL = {\n\tname: CONTEXT_SEARCH_TRANSCRIPT_TOOL_NAME,\n\tdescription: \"Search the full transcript working copy and return small snippets without mutating deletion state.\",\n\tparameters: ContextSearchTranscriptToolParameters,\n} as const;\n\nexport const CONTEXT_READ_ENTRY_TOOL = {\n\tname: CONTEXT_READ_ENTRY_TOOL_NAME,\n\tdescription: \"Read a small slice of one transcript entry or content block from the full transcript working copy.\",\n\tparameters: ContextReadEntryToolParameters,\n} as const;\n\nexport const CONTEXT_COMPACTION_BUDGET_TOOL = {\n\tname: CONTEXT_COMPACTION_BUDGET_TOOL_NAME,\n\tdescription:\n\t\t\"Report current context-window fullness and reduction progress for the selected deletion targets without mutating deletion state.\",\n\tparameters: ContextCompactionBudgetToolParameters,\n} as const;\n\nexport interface ContextDeletionToolDetails {\n\tdeletions: ContextDeletionRequest[\"deletions\"];\n\tdeletedTargets: ContextDeletionTarget[];\n\tstats: ContextCompactionStats;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextGrepDeletionMatch {\n\tentryId: string;\n\ttarget: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\ttext: string;\n}\n\nexport interface ContextGrepDeletionSkipped {\n\tentryId?: string;\n\ttarget?: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\treason:\n\t\t| \"protected_entry\"\n\t\t| \"protected_block\"\n\t\t| \"assistant_thinking_entry\"\n\t\t| \"assistant_thinking_block\"\n\t\t| \"already_deleted\"\n\t\t| \"max_matches_exceeded\"\n\t\t| \"expected_match_count_mismatch\";\n\ttext?: string;\n}\n\nexport interface ContextGrepDeletionToolDetails {\n\tpattern: string;\n\tregex: boolean;\n\tcaseSensitive: boolean;\n\ttarget: \"entry\" | \"content_block\";\n\tmatches: ContextGrepDeletionMatch[];\n\tskipped: ContextGrepDeletionSkipped[];\n\tdeletedTargets: ContextDeletionTarget[];\n\tstats: ContextCompactionStats;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextTranscriptSearchMatch {\n\tentryId: string;\n\ttarget: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\tmatchIndex: number;\n\tsnippet: string;\n\tprotected: boolean;\n}\n\nexport interface ContextTranscriptSearchToolDetails {\n\tpattern: string;\n\tregex: boolean;\n\tcaseSensitive: boolean;\n\ttarget: \"entry\" | \"content_block\";\n\tmatches: ContextTranscriptSearchMatch[];\n\ttruncated: boolean;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextReadEntryToolDetails {\n\tentryId: string;\n\tblockIndex?: number;\n\toffset: number;\n\tmaxChars: number;\n\ttotalChars: number;\n\ttext: string;\n\ttruncatedBefore: boolean;\n\ttruncatedAfter: boolean;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextCompactionBudgetToolDetails {\n\tcontextWindow?: number;\n\tcompression_ratio: number;\n\ttokensBefore: number;\n\tcurrentTokensAfter: number;\n\tdeletedTokens: number;\n\tcurrentReductionPercent: number;\n\ttargetReductionPercent: number;\n\ttargetTokensAfter: number;\n\ttokensToDeleteForTarget: number;\n\tcontextWindowBeforePercent?: number;\n\tcontextWindowAfterPercent?: number;\n\tcallCount: number;\n}\n\nexport interface ContextDeletionToolController {\n\ttool: AgentTool<typeof ContextDeleteToolParameters, ContextDeletionToolDetails>;\n\tgrepTool: AgentTool<typeof ContextGrepDeleteToolParameters, ContextGrepDeletionToolDetails>;\n\tsearchTool: AgentTool<typeof ContextSearchTranscriptToolParameters, ContextTranscriptSearchToolDetails>;\n\treadEntryTool: AgentTool<typeof ContextReadEntryToolParameters, ContextReadEntryToolDetails>;\n\tbudgetTool: AgentTool<typeof ContextCompactionBudgetToolParameters, ContextCompactionBudgetToolDetails>;\n\ttools: AgentTool[];\n\tgetDeletionRequest(): ContextDeletionRequest;\n\tgetValidatedResult(): ValidatedContextDeletionResult | undefined;\n\tgetLastError(): string | undefined;\n\tgetCallCount(): number;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"context-deletion-tool-definitions.js","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-tool-definitions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { StringEnum } from \"@earendil-works/pi-ai\";\nimport { Type } from \"typebox\";\nimport type { ContextCompactionStats, ContextDeletionTarget } from \"../session-manager.ts\";\nimport type { ContextDeletionRequest, ValidatedContextDeletionResult } from \"./context-compaction-types.ts\";\n\nexport const CONTEXT_DELETE_TOOL_NAME = \"context_delete\";\nexport const CONTEXT_GREP_DELETE_TOOL_NAME = \"context_grep_delete\";\nexport const CONTEXT_SEARCH_TRANSCRIPT_TOOL_NAME = \"context_search_transcript\";\nexport const CONTEXT_READ_ENTRY_TOOL_NAME = \"context_read_entry\";\nexport const CONTEXT_COMPACTION_BUDGET_TOOL_NAME = \"context_compaction_budget\";\nexport const CONTEXT_GREP_DELETE_DEFAULT_MAX_MATCHES = 50;\nexport const CONTEXT_GREP_DELETE_MAX_REGEX_PATTERN_CHARS = 512;\nexport const CONTEXT_GREP_DELETE_MAX_REGEX_SCAN_CHARS = 250_000;\nexport const CONTEXT_READ_ENTRY_DEFAULT_MAX_CHARS = 4000;\nexport const CONTEXT_READ_ENTRY_MAX_CHARS = 12_000;\nexport const CONTEXT_SEARCH_DEFAULT_MAX_MATCHES = 20;\nexport const CONTEXT_SEARCH_MAX_MATCHES = 100;\nexport const CONTEXT_SEARCH_DEFAULT_CONTEXT_CHARS = 160;\nexport const CONTEXT_SEARCH_MAX_CONTEXT_CHARS = 500;\n\n\nexport const ContextDeleteToolParameters = Type.Object(\n\t{\n\t\tdeletions: Type.Array(\n\t\t\tType.Object(\n\t\t\t\t{\n\t\t\t\t\tkind: StringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\t\t\tdescription: \"Delete an entire transcript entry or a single content block within one entry.\",\n\t\t\t\t\t}),\n\t\t\t\t\tentryId: Type.String({ minLength: 1, description: \"Stable transcript entry id to delete from.\" }),\n\t\t\t\t\tblockIndex: Type.Optional(\n\t\t\t\t\t\tType.Integer({\n\t\t\t\t\t\t\tminimum: 0,\n\t\t\t\t\t\t\tdescription: \"Required when kind is content_block; omit when kind is entry.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\t{\n\t\t\t\tdescription:\n\t\t\t\t\t\"ID-only deletion targets. Include only kind, entryId, and blockIndex when needed; do not include transcript text, block contents, summaries, or replacement content. Invalid targets are rejected by the tool with correction guidance.\",\n\t\t\t},\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextGrepDeleteToolParameters = Type.Object(\n\t{\n\t\tpattern: Type.String({ minLength: 1, description: \"Literal text or regular expression to match in transcript text.\" }),\n\t\tregex: Type.Optional(Type.Boolean({ description: \"Treat pattern as a JavaScript regular expression. Defaults to false.\" })),\n\t\tcaseSensitive: Type.Optional(Type.Boolean({ description: \"Use case-sensitive matching. Defaults to false.\" })),\n\t\ttarget: Type.Optional(\n\t\t\tStringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\tdescription: \"Delete whole matching entries or matching content blocks. Defaults to entry.\",\n\t\t\t}),\n\t\t),\n\t\tmaxMatches: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 1,\n\t\t\t\tmaximum: 200,\n\t\t\t\tdescription:\n\t\t\t\t\t\"Per-call safety cap. If more not-yet-deleted candidate targets are found in this tool call, no deletions are applied. Defaults to 50. This is not a cumulative compaction cap; call the tool again for additional batches.\",\n\t\t\t}),\n\t\t),\n\t\texpectedMatchCount: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 0,\n\t\t\t\tdescription: \"Optional safety check. If the match count differs, no deletions are applied.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextSearchTranscriptToolParameters = Type.Object(\n\t{\n\t\tpattern: Type.String({ minLength: 1, description: \"Literal text or regular expression to search for.\" }),\n\t\tregex: Type.Optional(Type.Boolean({ description: \"Treat pattern as a JavaScript regular expression. Defaults to false.\" })),\n\t\tcaseSensitive: Type.Optional(Type.Boolean({ description: \"Use case-sensitive matching. Defaults to false.\" })),\n\t\ttarget: Type.Optional(\n\t\t\tStringEnum([\"entry\", \"content_block\"] as const, {\n\t\t\t\tdescription: \"Search whole entry text or individual content-block text. Defaults to entry.\",\n\t\t\t}),\n\t\t),\n\t\tmaxMatches: Type.Optional(\n\t\t\tType.Integer({ minimum: 1, maximum: CONTEXT_SEARCH_MAX_MATCHES, description: \"Maximum matches to return. Defaults to 20.\" }),\n\t\t),\n\t\tcontextChars: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 0,\n\t\t\t\tmaximum: CONTEXT_SEARCH_MAX_CONTEXT_CHARS,\n\t\t\t\tdescription: \"Characters of context to include before and after each match. Defaults to 160.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextReadEntryToolParameters = Type.Object(\n\t{\n\t\tentryId: Type.String({ minLength: 1, description: \"Stable transcript entry id to read.\" }),\n\t\tblockIndex: Type.Optional(\n\t\t\tType.Integer({ minimum: 0, description: \"Optional content block index to read instead of the whole entry text.\" }),\n\t\t),\n\t\toffset: Type.Optional(Type.Integer({ minimum: 0, description: \"Character offset to begin reading. Defaults to 0.\" })),\n\t\tmaxChars: Type.Optional(\n\t\t\tType.Integer({\n\t\t\t\tminimum: 1,\n\t\t\t\tmaximum: CONTEXT_READ_ENTRY_MAX_CHARS,\n\t\t\t\tdescription: \"Maximum characters to return. Defaults to 4000; keep reads small to avoid overflowing context.\",\n\t\t\t}),\n\t\t),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport const ContextCompactionBudgetToolParameters = Type.Object({}, { additionalProperties: false });\n\nexport const CONTEXT_DELETE_TOOL = {\n\tname: CONTEXT_DELETE_TOOL_NAME,\n\tdescription: \"Record context compaction deletion targets directly against the transcript.\",\n\tparameters: ContextDeleteToolParameters,\n} as const;\n\nexport const CONTEXT_GREP_DELETE_TOOL = {\n\tname: CONTEXT_GREP_DELETE_TOOL_NAME,\n\tdescription: \"Bulk-delete transcript entries or content blocks matching a guarded grep/regex query.\",\n\tparameters: ContextGrepDeleteToolParameters,\n} as const;\n\nexport const CONTEXT_SEARCH_TRANSCRIPT_TOOL = {\n\tname: CONTEXT_SEARCH_TRANSCRIPT_TOOL_NAME,\n\tdescription: \"Search the full transcript working copy and return small snippets without mutating deletion state.\",\n\tparameters: ContextSearchTranscriptToolParameters,\n} as const;\n\nexport const CONTEXT_READ_ENTRY_TOOL = {\n\tname: CONTEXT_READ_ENTRY_TOOL_NAME,\n\tdescription: \"Read a small slice of one transcript entry or content block from the full transcript working copy.\",\n\tparameters: ContextReadEntryToolParameters,\n} as const;\n\nexport const CONTEXT_COMPACTION_BUDGET_TOOL = {\n\tname: CONTEXT_COMPACTION_BUDGET_TOOL_NAME,\n\tdescription:\n\t\t\"Report current context-window fullness and reduction progress for the selected deletion targets without mutating deletion state.\",\n\tparameters: ContextCompactionBudgetToolParameters,\n} as const;\n\nexport interface ContextDeletionToolDetails {\n\tdeletions: ContextDeletionRequest[\"deletions\"];\n\tdeletedTargets: ContextDeletionTarget[];\n\tstats: ContextCompactionStats;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextGrepDeletionMatch {\n\tentryId: string;\n\ttarget: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\ttext: string;\n}\n\nexport interface ContextGrepDeletionSkipped {\n\tentryId?: string;\n\ttarget?: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\treason:\n\t\t| \"protected_entry\"\n\t\t| \"protected_block\"\n\t\t| \"assistant_thinking_entry\"\n\t\t| \"assistant_thinking_block\"\n\t\t| \"already_deleted\"\n\t\t| \"max_matches_exceeded\"\n\t\t| \"expected_match_count_mismatch\";\n\ttext?: string;\n}\n\nexport interface ContextGrepDeletionToolDetails {\n\tpattern: string;\n\tregex: boolean;\n\tcaseSensitive: boolean;\n\ttarget: \"entry\" | \"content_block\";\n\tmatches: ContextGrepDeletionMatch[];\n\tskipped: ContextGrepDeletionSkipped[];\n\tdeletedTargets: ContextDeletionTarget[];\n\tstats: ContextCompactionStats;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextTranscriptSearchMatch {\n\tentryId: string;\n\ttarget: \"entry\" | \"content_block\";\n\tblockIndex?: number;\n\tmatchIndex: number;\n\tsnippet: string;\n\tprotected: boolean;\n}\n\nexport interface ContextTranscriptSearchToolDetails {\n\tpattern: string;\n\tregex: boolean;\n\tcaseSensitive: boolean;\n\ttarget: \"entry\" | \"content_block\";\n\tmatches: ContextTranscriptSearchMatch[];\n\ttruncated: boolean;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextReadEntryToolDetails {\n\tentryId: string;\n\tblockIndex?: number;\n\toffset: number;\n\tmaxChars: number;\n\ttotalChars: number;\n\ttext: string;\n\ttruncatedBefore: boolean;\n\ttruncatedAfter: boolean;\n\tcallCount: number;\n\terror?: string;\n}\n\nexport interface ContextCompactionBudgetToolDetails {\n\tcontextWindow?: number;\n\tcompression_ratio: number;\n\ttokensBefore: number;\n\tcurrentTokensAfter: number;\n\tdeletedTokens: number;\n\tcurrentReductionPercent: number;\n\ttargetReductionPercent: number;\n\ttargetTokensAfter: number;\n\ttokensToDeleteForTarget: number;\n\tcontextWindowBeforePercent?: number;\n\tcontextWindowAfterPercent?: number;\n\t/** Total estimated tokens consumed by image content blocks still remaining after selected deletions. */\n\tremainingImageTokens: number;\n\t/** Number of image content blocks still remaining after selected deletions. */\n\timageBlockCount: number;\n\t/** Image tokens as a percentage of the remaining context (post-deletion token total). */\n\timageTokenPercent: number;\n\tcallCount: number;\n}\n\nexport interface ContextDeletionToolController {\n\ttool: AgentTool<typeof ContextDeleteToolParameters, ContextDeletionToolDetails>;\n\tgrepTool: AgentTool<typeof ContextGrepDeleteToolParameters, ContextGrepDeletionToolDetails>;\n\tsearchTool: AgentTool<typeof ContextSearchTranscriptToolParameters, ContextTranscriptSearchToolDetails>;\n\treadEntryTool: AgentTool<typeof ContextReadEntryToolParameters, ContextReadEntryToolDetails>;\n\tbudgetTool: AgentTool<typeof ContextCompactionBudgetToolParameters, ContextCompactionBudgetToolDetails>;\n\ttools: AgentTool[];\n\tgetDeletionRequest(): ContextDeletionRequest;\n\tgetValidatedResult(): ValidatedContextDeletionResult | undefined;\n\tgetLastError(): string | undefined;\n\tgetCallCount(): number;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-deletion-tools.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-tools.ts"],"names":[],"mappings":"AAEA,OAAO,EAEN,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAEhC,MAAM,+BAA+B,CAAC;AAWvC,OAAO,EAiBN,KAAK,6BAA6B,EAalC,MAAM,wCAAwC,CAAC;AAyBhD,wBAAgB,yBAAyB,CACxC,eAAe,EAAE,qBAAqB,EACtC,OAAO,GAAE,2BAAgC,GACvC,6BAA6B,CAoa/B","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { ContextCompactionStats, ContextDeletionTarget } from \"../session-manager.ts\";\nimport {\n\tCONTEXT_COMPACTION_AUTO_QUERY,\n\ttype CompactableTranscript,\n\ttype ContextCompactionRunOptions,\n\ttype ValidatedContextDeletionResult,\n} from \"./context-compaction-types.ts\";\nimport {\n\tcreateContextCompactionBudgetDetails,\n\tcreateContextDeletionToolResult,\n\tfinitePositiveNumber,\n\tformatErrorMessage,\n} from \"./context-compaction-metrics.ts\";\nimport {\n\tgetTranscriptCompactionParameters,\n\tnormalizeContextCompactionParameters,\n} from \"./context-compaction-strategy.ts\";\nimport {\n\tCONTEXT_COMPACTION_BUDGET_TOOL,\n\tCONTEXT_DELETE_TOOL,\n\tCONTEXT_DELETE_TOOL_NAME,\n\tCONTEXT_GREP_DELETE_DEFAULT_MAX_MATCHES,\n\tCONTEXT_GREP_DELETE_TOOL,\n\tCONTEXT_GREP_DELETE_TOOL_NAME,\n\tCONTEXT_READ_ENTRY_DEFAULT_MAX_CHARS,\n\tCONTEXT_READ_ENTRY_MAX_CHARS,\n\tCONTEXT_READ_ENTRY_TOOL,\n\tCONTEXT_READ_ENTRY_TOOL_NAME,\n\tCONTEXT_SEARCH_DEFAULT_CONTEXT_CHARS,\n\tCONTEXT_SEARCH_DEFAULT_MAX_MATCHES,\n\tCONTEXT_SEARCH_MAX_CONTEXT_CHARS,\n\tCONTEXT_SEARCH_MAX_MATCHES,\n\tCONTEXT_SEARCH_TRANSCRIPT_TOOL,\n\ttype ContextCompactionBudgetToolDetails,\n\ttype ContextDeletionToolController,\n\ttype ContextDeletionToolDetails,\n\ttype ContextGrepDeletionMatch,\n\ttype ContextGrepDeletionSkipped,\n\ttype ContextGrepDeletionToolDetails,\n\ttype ContextReadEntryToolDetails,\n\ttype ContextTranscriptSearchMatch,\n\ttype ContextTranscriptSearchToolDetails,\n\tContextCompactionBudgetToolParameters,\n\tContextDeleteToolParameters,\n\tContextGrepDeleteToolParameters,\n\tContextReadEntryToolParameters,\n\tContextSearchTranscriptToolParameters,\n} from \"./context-deletion-tool-definitions.ts\";\nimport {\n\tcomputeContextCompactionStats,\n\tcontextDeletionRequestFromObject,\n\tvalidateContextDeletionRequest,\n} from \"./context-deletion-application.ts\";\nimport {\n\tcanDeleteTarget,\n\tdeletionRequestFromTargets,\n\tgetRecentContextEntryIds,\n\tmergeContextDeletionTargets,\n} from \"./context-deletion-targets.ts\";\nimport { createContextDeletionStore } from \"./context-deletion-store.ts\";\nimport {\n\taddGrepCandidate,\n\tassertSafeRegexScan,\n\tclampInteger,\n\tcreateGrepMatcher,\n\tcurrentTargetDeleted,\n\tfilterProtectedGrepCandidates,\n\tfindMatchIndex,\n\tsnippetForMatch,\n\ttextSlice,\n} from \"./context-deletion-tool-helpers.ts\";\n\nexport function createContextDeletionTool(\n\tinputTranscript: CompactableTranscript,\n\toptions: ContextCompactionRunOptions = {},\n): ContextDeletionToolController {\n\tconst contextWindow = finitePositiveNumber(options.contextWindow);\n\tconst parameters = normalizeContextCompactionParameters(\n\t\t{ ...getTranscriptCompactionParameters(inputTranscript), ...options },\n\t\tinputTranscript.parameters?.query ?? CONTEXT_COMPACTION_AUTO_QUERY,\n\t);\n\tconst transcript: CompactableTranscript = { ...inputTranscript, parameters };\n\tconst store = createContextDeletionStore(transcript);\n\tlet validatedResult: ValidatedContextDeletionResult | undefined;\n\n\tfunction readTargets(): ContextDeletionTarget[] {\n\t\treturn store.readTargets();\n\t}\n\n\tfunction applyValidatedTargets(additionalTargets: readonly ContextDeletionTarget[]): ValidatedContextDeletionResult {\n\t\tconst mergedTargets = mergeContextDeletionTargets(readTargets(), additionalTargets);\n\t\tvalidatedResult = validateContextDeletionRequest(deletionRequestFromTargets(mergedTargets), transcript);\n\t\tstore.replaceTargets(validatedResult.deletedTargets);\n\t\treturn validatedResult;\n\t}\n\n\tfunction currentStats(): ContextCompactionStats {\n\t\treturn validatedResult?.stats ?? computeContextCompactionStats(transcript, readTargets());\n\t}\n\n\tfunction canDeleteProtectedTarget(target: ContextDeletionTarget): boolean {\n\t\treturn canDeleteTarget(transcript, target);\n\t}\n\n\tconst tool: AgentTool<typeof ContextDeleteToolParameters, ContextDeletionToolDetails> = {\n\t\t...CONTEXT_DELETE_TOOL,\n\t\tlabel: \"context deletion request\",\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params) {\n\t\t\treturn store.transaction(() => {\n\t\t\t\tconst callCount = store.incrementCallCount();\n\t\t\t\ttry {\n\t\t\t\t\tconst incomingRequest = contextDeletionRequestFromObject(params, `${CONTEXT_DELETE_TOOL_NAME} arguments`);\n\t\t\t\t\tconst incomingValidated = validateContextDeletionRequest(incomingRequest, transcript);\n\t\t\t\t\tconst applied = applyValidatedTargets(incomingValidated.deletedTargets);\n\t\t\t\t\tstore.clearLastError();\n\t\t\t\t\tconst deletedTargets = readTargets();\n\n\t\t\t\t\tconst details: ContextDeletionToolDetails = {\n\t\t\t\t\t\tdeletions: deletionRequestFromTargets(deletedTargets).deletions,\n\t\t\t\t\t\tdeletedTargets,\n\t\t\t\t\t\tstats: applied.stats,\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t};\n\t\t\t\t\tconst text = `Recorded ${incomingValidated.deletedTargets.length} deletion target(s); ${deletedTargets.length} total validated deletion target(s) are selected. Continue calling ${CONTEXT_DELETE_TOOL_NAME} or ${CONTEXT_GREP_DELETE_TOOL_NAME} for additional deletions, or respond done when finished.`;\n\t\t\t\t\treturn createContextDeletionToolResult(text, details);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = formatErrorMessage(error);\n\t\t\t\t\tstore.setLastError(message);\n\t\t\t\t\tconst deletedTargets = readTargets();\n\t\t\t\t\tconst details: ContextDeletionToolDetails = {\n\t\t\t\t\t\tdeletions: deletionRequestFromTargets(deletedTargets).deletions,\n\t\t\t\t\t\tdeletedTargets,\n\t\t\t\t\t\tstats: currentStats(),\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t};\n\t\t\t\t\treturn createContextDeletionToolResult(\n\t\t\t\t\t\t`Error recording context deletion targets: ${message}. No new deletion targets were applied; continue with a corrected tool call.`,\n\t\t\t\t\t\tdetails,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n\n\tconst grepTool: AgentTool<typeof ContextGrepDeleteToolParameters, ContextGrepDeletionToolDetails> = {\n\t\t...CONTEXT_GREP_DELETE_TOOL,\n\t\tlabel: \"context grep delete\",\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params) {\n\t\t\treturn store.transaction(() => {\n\t\t\t\tconst callCount = store.incrementCallCount();\n\t\t\t\tconst pattern = params.pattern;\n\t\t\t\tconst regex = params.regex === true;\n\t\t\t\tconst caseSensitive = params.caseSensitive === true;\n\t\t\t\tconst target = params.target ?? \"entry\";\n\t\t\t\tconst maxMatches = params.maxMatches ?? CONTEXT_GREP_DELETE_DEFAULT_MAX_MATCHES;\n\t\t\t\tconst candidates: ContextDeletionTarget[] = [];\n\t\t\t\tconst matches: ContextGrepDeletionMatch[] = [];\n\t\t\t\tlet reportedMatches: ContextGrepDeletionMatch[] = matches;\n\t\t\t\tconst skipped: ContextGrepDeletionSkipped[] = [];\n\t\t\t\tconst seenTargets = new Set<string>();\n\n\t\t\t\ttry {\n\t\t\t\t\tif (regex) {\n\t\t\t\t\t\tassertSafeRegexScan(store.getGrepScanTextLength(target));\n\t\t\t\t\t}\n\t\t\t\t\tconst matcher = createGrepMatcher(pattern, regex, caseSensitive);\n\t\t\t\t\tconst currentTargets = readTargets();\n\t\t\t\t\tconst recentEntryIds = getRecentContextEntryIds(transcript);\n\n\t\t\t\t\tif (target === \"entry\") {\n\t\t\t\t\t\tfor (const entry of store.listEntriesForGrep()) {\n\t\t\t\t\t\t\tif (!matcher.test(entry.text)) continue;\n\t\t\t\t\t\t\tconst candidate: ContextDeletionTarget = { kind: \"entry\", entryId: entry.entry_id };\n\t\t\t\t\t\t\tif (recentEntryIds.has(candidate.entryId)) {\n\t\t\t\t\t\t\t\tskipped.push({ entryId: entry.entry_id, target, reason: \"protected_entry\", text: entry.text });\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (entry.is_protected === 1 && !canDeleteProtectedTarget(candidate)) {\n\t\t\t\t\t\t\t\tskipped.push({ entryId: entry.entry_id, target, reason: \"protected_entry\", text: entry.text });\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (currentTargetDeleted(currentTargets, candidate)) {\n\t\t\t\t\t\t\t\tskipped.push({ entryId: entry.entry_id, target, reason: \"already_deleted\", text: entry.text });\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\taddGrepCandidate(candidates, matches, seenTargets, candidate, {\n\t\t\t\t\t\t\t\tentryId: entry.entry_id,\n\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\ttext: entry.text,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (const block of store.listContentBlocksForGrep()) {\n\t\t\t\t\t\t\tif (!matcher.test(block.text)) continue;\n\t\t\t\t\t\t\tconst candidate: ContextDeletionTarget =\n\t\t\t\t\t\t\t\tblock.block_count <= 1\n\t\t\t\t\t\t\t\t\t? { kind: \"entry\", entryId: block.entry_id }\n\t\t\t\t\t\t\t\t\t: { kind: \"content_block\", entryId: block.entry_id, blockIndex: block.block_index };\n\t\t\t\t\t\t\tif (recentEntryIds.has(candidate.entryId)) {\n\t\t\t\t\t\t\t\tskipped.push({\n\t\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\t\ttarget: candidate.kind,\n\t\t\t\t\t\t\t\t\t...(candidate.kind === \"content_block\" ? { blockIndex: candidate.blockIndex } : {}),\n\t\t\t\t\t\t\t\t\treason: \"protected_entry\",\n\t\t\t\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (block.entry_protected === 1 && !canDeleteProtectedTarget(candidate)) {\n\t\t\t\t\t\t\t\tskipped.push({\n\t\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\t\tblockIndex: block.block_index,\n\t\t\t\t\t\t\t\t\treason: \"protected_entry\",\n\t\t\t\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (block.block_protected === 1 && !canDeleteProtectedTarget(candidate)) {\n\t\t\t\t\t\t\t\tskipped.push({\n\t\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\t\tblockIndex: block.block_index,\n\t\t\t\t\t\t\t\t\treason: \"protected_block\",\n\t\t\t\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (currentTargetDeleted(currentTargets, candidate)) {\n\t\t\t\t\t\t\t\tskipped.push({\n\t\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\t\ttarget: candidate.kind,\n\t\t\t\t\t\t\t\t\t...(candidate.kind === \"content_block\" ? { blockIndex: candidate.blockIndex } : {}),\n\t\t\t\t\t\t\t\t\treason: \"already_deleted\",\n\t\t\t\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\taddGrepCandidate(candidates, matches, seenTargets, candidate, {\n\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\ttarget: candidate.kind,\n\t\t\t\t\t\t\t\t...(candidate.kind === \"content_block\" ? { blockIndex: candidate.blockIndex } : {}),\n\t\t\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst eligible = filterProtectedGrepCandidates(candidates, matches, currentTargets, transcript, skipped);\n\t\t\t\t\treportedMatches = eligible.matches;\n\t\t\t\t\tlet applied: ValidatedContextDeletionResult | undefined;\n\t\t\t\t\tif (params.expectedMatchCount !== undefined && eligible.candidates.length !== params.expectedMatchCount) {\n\t\t\t\t\t\tskipped.push({ reason: \"expected_match_count_mismatch\" });\n\t\t\t\t\t} else if (eligible.candidates.length > maxMatches) {\n\t\t\t\t\t\tskipped.push({ reason: \"max_matches_exceeded\" });\n\t\t\t\t\t} else if (eligible.candidates.length > 0) {\n\t\t\t\t\t\tapplied = applyValidatedTargets(eligible.candidates);\n\t\t\t\t\t}\n\t\t\t\t\tstore.clearLastError();\n\t\t\t\t\tconst deletedTargets = readTargets();\n\n\t\t\t\t\tconst details: ContextGrepDeletionToolDetails = {\n\t\t\t\t\t\tpattern,\n\t\t\t\t\t\tregex,\n\t\t\t\t\t\tcaseSensitive,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tmatches: eligible.matches,\n\t\t\t\t\t\tskipped,\n\t\t\t\t\t\tdeletedTargets,\n\t\t\t\t\t\tstats: applied?.stats ?? currentStats(),\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t};\n\t\t\t\t\tconst text = `Matched ${eligible.matches.length} deletion target(s), skipped ${skipped.length}, and ${applied ? \"applied\" : \"did not apply\"} grep deletion for pattern ${JSON.stringify(pattern)}. Total validated deletion target(s): ${deletedTargets.length}.`;\n\t\t\t\t\treturn createContextDeletionToolResult(text, details);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = formatErrorMessage(error);\n\t\t\t\t\tstore.setLastError(message);\n\t\t\t\t\tconst deletedTargets = readTargets();\n\t\t\t\t\tconst details: ContextGrepDeletionToolDetails = {\n\t\t\t\t\t\tpattern,\n\t\t\t\t\t\tregex,\n\t\t\t\t\t\tcaseSensitive,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tmatches: reportedMatches,\n\t\t\t\t\t\tskipped,\n\t\t\t\t\t\tdeletedTargets,\n\t\t\t\t\t\tstats: currentStats(),\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t};\n\t\t\t\t\treturn createContextDeletionToolResult(\n\t\t\t\t\t\t`Error applying grep deletion for pattern ${JSON.stringify(pattern)}: ${message}. No new deletion targets were applied; continue with a corrected tool call.`,\n\t\t\t\t\t\tdetails,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n\n\tconst searchTool: AgentTool<typeof ContextSearchTranscriptToolParameters, ContextTranscriptSearchToolDetails> = {\n\t\t...CONTEXT_SEARCH_TRANSCRIPT_TOOL,\n\t\tlabel: \"context transcript search\",\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params) {\n\t\t\treturn store.transaction(() => {\n\t\t\t\tconst callCount = store.incrementCallCount();\n\t\t\t\tconst pattern = params.pattern;\n\t\t\t\tconst regex = params.regex === true;\n\t\t\t\tconst caseSensitive = params.caseSensitive === true;\n\t\t\t\tconst target = params.target ?? \"entry\";\n\t\t\t\tconst maxMatches = clampInteger(params.maxMatches, CONTEXT_SEARCH_DEFAULT_MAX_MATCHES, 1, CONTEXT_SEARCH_MAX_MATCHES);\n\t\t\t\tconst contextChars = clampInteger(\n\t\t\t\t\tparams.contextChars,\n\t\t\t\t\tCONTEXT_SEARCH_DEFAULT_CONTEXT_CHARS,\n\t\t\t\t\t0,\n\t\t\t\t\tCONTEXT_SEARCH_MAX_CONTEXT_CHARS,\n\t\t\t\t);\n\t\t\t\tconst matches: ContextTranscriptSearchMatch[] = [];\n\t\t\t\tlet truncated = false;\n\n\t\t\t\ttry {\n\t\t\t\t\tif (regex) {\n\t\t\t\t\t\tassertSafeRegexScan(store.getGrepScanTextLength(target));\n\t\t\t\t\t}\n\t\t\t\t\tconst matcher = createGrepMatcher(pattern, regex, caseSensitive);\n\t\t\t\t\tif (target === \"entry\") {\n\t\t\t\t\t\tfor (const entry of store.listEntriesForGrep()) {\n\t\t\t\t\t\t\tconst matchIndex = findMatchIndex(matcher, entry.text);\n\t\t\t\t\t\t\tif (matchIndex < 0) continue;\n\t\t\t\t\t\t\tif (matches.length >= maxMatches) {\n\t\t\t\t\t\t\t\ttruncated = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmatches.push({\n\t\t\t\t\t\t\t\tentryId: entry.entry_id,\n\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\tmatchIndex,\n\t\t\t\t\t\t\t\tsnippet: snippetForMatch(entry.text, matchIndex, contextChars),\n\t\t\t\t\t\t\t\tprotected: entry.is_protected === 1,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (const block of store.listContentBlocksForGrep()) {\n\t\t\t\t\t\t\tconst matchIndex = findMatchIndex(matcher, block.text);\n\t\t\t\t\t\t\tif (matchIndex < 0) continue;\n\t\t\t\t\t\t\tif (matches.length >= maxMatches) {\n\t\t\t\t\t\t\t\ttruncated = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmatches.push({\n\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\tblockIndex: block.block_index,\n\t\t\t\t\t\t\t\tmatchIndex,\n\t\t\t\t\t\t\t\tsnippet: snippetForMatch(block.text, matchIndex, contextChars),\n\t\t\t\t\t\t\t\tprotected: block.entry_protected === 1 || block.block_protected === 1,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tstore.clearLastError();\n\t\t\t\t\tconst details: ContextTranscriptSearchToolDetails = {\n\t\t\t\t\t\tpattern,\n\t\t\t\t\t\tregex,\n\t\t\t\t\t\tcaseSensitive,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tmatches,\n\t\t\t\t\t\ttruncated,\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t};\n\t\t\t\t\tconst text = `Found ${matches.length}${truncated ? \"+\" : \"\"} ${target} match(es) for ${JSON.stringify(pattern)}. Use ${CONTEXT_READ_ENTRY_TOOL_NAME} with small maxChars to inspect exact content before deleting.`;\n\t\t\t\t\treturn createContextDeletionToolResult(text, details);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = formatErrorMessage(error);\n\t\t\t\t\tstore.setLastError(message);\n\t\t\t\t\tconst details: ContextTranscriptSearchToolDetails = {\n\t\t\t\t\t\tpattern,\n\t\t\t\t\t\tregex,\n\t\t\t\t\t\tcaseSensitive,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tmatches,\n\t\t\t\t\t\ttruncated,\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t};\n\t\t\t\t\treturn createContextDeletionToolResult(\n\t\t\t\t\t\t`Error searching transcript for ${JSON.stringify(pattern)}: ${message}. Try a literal pattern or narrower query.`,\n\t\t\t\t\t\tdetails,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n\n\tconst readEntryTool: AgentTool<typeof ContextReadEntryToolParameters, ContextReadEntryToolDetails> = {\n\t\t...CONTEXT_READ_ENTRY_TOOL,\n\t\tlabel: \"context read entry\",\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params) {\n\t\t\treturn store.transaction(() => {\n\t\t\t\tconst callCount = store.incrementCallCount();\n\t\t\t\tconst offset = clampInteger(params.offset, 0, 0, Number.MAX_SAFE_INTEGER);\n\t\t\t\tconst maxChars = clampInteger(\n\t\t\t\t\tparams.maxChars,\n\t\t\t\t\tCONTEXT_READ_ENTRY_DEFAULT_MAX_CHARS,\n\t\t\t\t\t1,\n\t\t\t\t\tCONTEXT_READ_ENTRY_MAX_CHARS,\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\tconst row =\n\t\t\t\t\t\tparams.blockIndex === undefined\n\t\t\t\t\t\t\t? store.getEntryForRead(params.entryId)\n\t\t\t\t\t\t\t: store.getContentBlockForRead(params.entryId, params.blockIndex);\n\t\t\t\t\tif (!row) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\tparams.blockIndex === undefined\n\t\t\t\t\t\t\t\t? `Unknown transcript entry: ${params.entryId}`\n\t\t\t\t\t\t\t\t: `Unknown transcript content block: ${params.entryId}:${params.blockIndex}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst text = row.text;\n\t\t\t\t\tconst slice = textSlice(text, offset, maxChars);\n\t\t\t\t\tstore.clearLastError();\n\t\t\t\t\tconst details: ContextReadEntryToolDetails = {\n\t\t\t\t\t\tentryId: params.entryId,\n\t\t\t\t\t\t...(params.blockIndex === undefined ? {} : { blockIndex: params.blockIndex }),\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\tmaxChars,\n\t\t\t\t\t\ttotalChars: text.length,\n\t\t\t\t\t\ttext: slice,\n\t\t\t\t\t\ttruncatedBefore: offset > 0,\n\t\t\t\t\t\ttruncatedAfter: offset + maxChars < text.length,\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t};\n\t\t\t\t\tconst textResult = `Read ${slice.length} of ${text.length} characters from ${params.blockIndex === undefined ? params.entryId : `${params.entryId}:${params.blockIndex}`}. Keep reads small; increase offset for the next slice if needed.`;\n\t\t\t\t\treturn createContextDeletionToolResult(textResult, details);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = formatErrorMessage(error);\n\t\t\t\t\tstore.setLastError(message);\n\t\t\t\t\tconst details: ContextReadEntryToolDetails = {\n\t\t\t\t\t\tentryId: params.entryId,\n\t\t\t\t\t\t...(params.blockIndex === undefined ? {} : { blockIndex: params.blockIndex }),\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\tmaxChars,\n\t\t\t\t\t\ttotalChars: 0,\n\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\ttruncatedBefore: false,\n\t\t\t\t\t\ttruncatedAfter: false,\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t};\n\t\t\t\t\treturn createContextDeletionToolResult(`Error reading transcript entry: ${message}`, details);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n\n\tconst budgetTool: AgentTool<typeof ContextCompactionBudgetToolParameters, ContextCompactionBudgetToolDetails> = {\n\t\t...CONTEXT_COMPACTION_BUDGET_TOOL,\n\t\tlabel: \"context compaction budget\",\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId) {\n\t\t\treturn store.transaction(() => {\n\t\t\t\tconst callCount = store.incrementCallCount();\n\t\t\t\tstore.clearLastError();\n\t\t\t\tconst details = createContextCompactionBudgetDetails(currentStats(), callCount, contextWindow, parameters);\n\t\t\t\tconst windowText =\n\t\t\t\t\tdetails.contextWindowBeforePercent !== undefined\n\t\t\t\t\t\t? ` Context window fullness: ${details.contextWindowBeforePercent}% before selected deletions, ${details.contextWindowAfterPercent}% after selected deletions.`\n\t\t\t\t\t\t: \" Context window size is unknown for this model, so fullness percentages are unavailable.\";\n\t\t\t\tconst targetText =\n\t\t\t\t\tdetails.tokensToDeleteForTarget > 0\n\t\t\t\t\t\t? ` Delete about ${details.tokensToDeleteForTarget} more token(s) to reach the ${details.targetReductionPercent}% reduction target.`\n\t\t\t\t\t\t: ` The selected deletions meet or exceed the ${details.targetReductionPercent}% reduction target.`;\n\t\t\t\treturn createContextDeletionToolResult(\n\t\t\t\t\t`Current selected deletions reduce context by ${details.currentReductionPercent}% (${details.deletedTokens} token(s)); tokens after selected deletions: ${details.currentTokensAfter}/${details.tokensBefore}.${windowText}${targetText} Keep maximizing useful retained context while aggressively removing low-value blocks.`,\n\t\t\t\t\tdetails,\n\t\t\t\t);\n\t\t\t});\n\t\t},\n\t};\n\n\treturn {\n\t\ttool,\n\t\tgrepTool,\n\t\tsearchTool,\n\t\treadEntryTool,\n\t\tbudgetTool,\n\t\ttools: [tool, grepTool, searchTool, readEntryTool, budgetTool],\n\t\tgetDeletionRequest: () => deletionRequestFromTargets(readTargets()),\n\t\tgetValidatedResult: () => validatedResult,\n\tgetLastError: () => store.getLastError(),\n\tgetCallCount: () => store.getCallCount(),\n};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"context-deletion-tools.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-deletion-tools.ts"],"names":[],"mappings":"AAEA,OAAO,EAEN,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAEhC,MAAM,+BAA+B,CAAC;AAUvC,OAAO,EAiBN,KAAK,6BAA6B,EAalC,MAAM,wCAAwC,CAAC;AAsBhD,wBAAgB,yBAAyB,CACxC,eAAe,EAAE,qBAAqB,EACtC,OAAO,GAAE,2BAAgC,GACvC,6BAA6B,CA0a/B","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport type { ContextCompactionStats, ContextDeletionTarget } from \"../session-manager.ts\";\nimport {\n\tCONTEXT_COMPACTION_AUTO_QUERY,\n\ttype CompactableTranscript,\n\ttype ContextCompactionRunOptions,\n\ttype ValidatedContextDeletionResult,\n} from \"./context-compaction-types.ts\";\nimport {\n\tcreateContextCompactionBudgetDetails,\n\tcreateContextDeletionToolResult,\n\tcountRemainingImageBlocks,\n\tfinitePositiveNumber,\n\tformatErrorMessage,\n\tsumRemainingImageTokens,\n} from \"./context-compaction-metrics.ts\";\nimport { getTranscriptCompactionParameters, normalizeContextCompactionParameters } from \"./context-compaction-strategy.ts\";\nimport {\n\tCONTEXT_COMPACTION_BUDGET_TOOL,\n\tCONTEXT_DELETE_TOOL,\n\tCONTEXT_DELETE_TOOL_NAME,\n\tCONTEXT_GREP_DELETE_DEFAULT_MAX_MATCHES,\n\tCONTEXT_GREP_DELETE_TOOL,\n\tCONTEXT_GREP_DELETE_TOOL_NAME,\n\tCONTEXT_READ_ENTRY_DEFAULT_MAX_CHARS,\n\tCONTEXT_READ_ENTRY_MAX_CHARS,\n\tCONTEXT_READ_ENTRY_TOOL,\n\tCONTEXT_READ_ENTRY_TOOL_NAME,\n\tCONTEXT_SEARCH_DEFAULT_CONTEXT_CHARS,\n\tCONTEXT_SEARCH_DEFAULT_MAX_MATCHES,\n\tCONTEXT_SEARCH_MAX_CONTEXT_CHARS,\n\tCONTEXT_SEARCH_MAX_MATCHES,\n\tCONTEXT_SEARCH_TRANSCRIPT_TOOL,\n\ttype ContextCompactionBudgetToolDetails,\n\ttype ContextDeletionToolController,\n\ttype ContextDeletionToolDetails,\n\ttype ContextGrepDeletionMatch,\n\ttype ContextGrepDeletionSkipped,\n\ttype ContextGrepDeletionToolDetails,\n\ttype ContextReadEntryToolDetails,\n\ttype ContextTranscriptSearchMatch,\n\ttype ContextTranscriptSearchToolDetails,\n\tContextCompactionBudgetToolParameters,\n\tContextDeleteToolParameters,\n\tContextGrepDeleteToolParameters,\n\tContextReadEntryToolParameters,\n\tContextSearchTranscriptToolParameters,\n} from \"./context-deletion-tool-definitions.ts\";\nimport { computeContextCompactionStats, contextDeletionRequestFromObject, validateContextDeletionRequest } from \"./context-deletion-application.ts\";\nimport {\n\tcanDeleteTarget,\n\tdeletionRequestFromTargets,\n\tgetRecentContextEntryIds,\n\tisStaleUserImageOnlyEntry,\n\tmergeContextDeletionTargets,\n} from \"./context-deletion-targets.ts\";\nimport { createContextDeletionStore } from \"./context-deletion-store.ts\";\nimport {\n\taddGrepCandidate,\n\tassertSafeRegexScan,\n\tclampInteger,\n\tcreateGrepMatcher,\n\tcurrentTargetDeleted,\n\tfilterProtectedGrepCandidates,\n\tfindMatchIndex,\n\tsnippetForMatch,\n\ttextSlice,\n} from \"./context-deletion-tool-helpers.ts\";\n\nexport function createContextDeletionTool(\n\tinputTranscript: CompactableTranscript,\n\toptions: ContextCompactionRunOptions = {},\n): ContextDeletionToolController {\n\tconst contextWindow = finitePositiveNumber(options.contextWindow);\n\tconst parameters = normalizeContextCompactionParameters(\n\t\t{ ...getTranscriptCompactionParameters(inputTranscript), ...options },\n\t\tinputTranscript.parameters?.query ?? CONTEXT_COMPACTION_AUTO_QUERY,\n\t);\n\tconst transcript: CompactableTranscript = { ...inputTranscript, parameters };\n\tconst store = createContextDeletionStore(transcript);\n\tlet validatedResult: ValidatedContextDeletionResult | undefined;\n\n\tfunction readTargets(): ContextDeletionTarget[] {\n\t\treturn store.readTargets();\n\t}\n\n\tfunction applyValidatedTargets(additionalTargets: readonly ContextDeletionTarget[]): ValidatedContextDeletionResult {\n\t\tconst mergedTargets = mergeContextDeletionTargets(readTargets(), additionalTargets);\n\t\tvalidatedResult = validateContextDeletionRequest(deletionRequestFromTargets(mergedTargets), transcript);\n\t\tstore.replaceTargets(validatedResult.deletedTargets);\n\t\treturn validatedResult;\n\t}\n\n\tfunction currentStats(): ContextCompactionStats {\n\t\treturn validatedResult?.stats ?? computeContextCompactionStats(transcript, readTargets());\n\t}\n\n\tfunction canDeleteProtectedTarget(target: ContextDeletionTarget): boolean {\n\t\treturn canDeleteTarget(transcript, target);\n\t}\n\n\tfunction shouldGrepDeleteContentBlockAsEntry(entryId: string, blockCount: number): boolean {\n\t\tif (blockCount <= 1) return true;\n\t\tconst entry = transcript.entries.find((candidate) => candidate.entryId === entryId);\n\t\treturn entry !== undefined && isStaleUserImageOnlyEntry(transcript, entry);\n\t}\n\n\tconst tool: AgentTool<typeof ContextDeleteToolParameters, ContextDeletionToolDetails> = {\n\t\t...CONTEXT_DELETE_TOOL,\n\t\tlabel: \"context deletion request\",\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params) {\n\t\t\treturn store.transaction(() => {\n\t\t\t\tconst callCount = store.incrementCallCount();\n\t\t\t\ttry {\n\t\t\t\t\tconst incomingRequest = contextDeletionRequestFromObject(params, `${CONTEXT_DELETE_TOOL_NAME} arguments`);\n\t\t\t\t\tconst incomingValidated = validateContextDeletionRequest(incomingRequest, transcript);\n\t\t\t\t\tconst applied = applyValidatedTargets(incomingValidated.deletedTargets);\n\t\t\t\t\tstore.clearLastError();\n\t\t\t\t\tconst deletedTargets = readTargets();\n\n\t\t\t\t\tconst details: ContextDeletionToolDetails = {\n\t\t\t\t\t\tdeletions: deletionRequestFromTargets(deletedTargets).deletions,\n\t\t\t\t\t\tdeletedTargets,\n\t\t\t\t\t\tstats: applied.stats,\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t};\n\t\t\t\t\tconst text = `Recorded ${incomingValidated.deletedTargets.length} deletion target(s); ${deletedTargets.length} total validated deletion target(s) are selected. Continue calling ${CONTEXT_DELETE_TOOL_NAME} or ${CONTEXT_GREP_DELETE_TOOL_NAME} for additional deletions, or respond done when finished.`;\n\t\t\t\t\treturn createContextDeletionToolResult(text, details);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = formatErrorMessage(error);\n\t\t\t\t\tstore.setLastError(message);\n\t\t\t\t\tconst deletedTargets = readTargets();\n\t\t\t\t\tconst details: ContextDeletionToolDetails = {\n\t\t\t\t\t\tdeletions: deletionRequestFromTargets(deletedTargets).deletions,\n\t\t\t\t\t\tdeletedTargets,\n\t\t\t\t\t\tstats: currentStats(),\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t};\n\t\t\t\t\treturn createContextDeletionToolResult(\n\t\t\t\t\t\t`Error recording context deletion targets: ${message}. No new deletion targets were applied; continue with a corrected tool call.`,\n\t\t\t\t\t\tdetails,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n\n\tconst grepTool: AgentTool<typeof ContextGrepDeleteToolParameters, ContextGrepDeletionToolDetails> = {\n\t\t...CONTEXT_GREP_DELETE_TOOL,\n\t\tlabel: \"context grep delete\",\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params) {\n\t\t\treturn store.transaction(() => {\n\t\t\t\tconst callCount = store.incrementCallCount();\n\t\t\t\tconst pattern = params.pattern;\n\t\t\t\tconst regex = params.regex === true;\n\t\t\t\tconst caseSensitive = params.caseSensitive === true;\n\t\t\t\tconst target = params.target ?? \"entry\";\n\t\t\t\tconst maxMatches = params.maxMatches ?? CONTEXT_GREP_DELETE_DEFAULT_MAX_MATCHES;\n\t\t\t\tconst candidates: ContextDeletionTarget[] = [];\n\t\t\t\tconst matches: ContextGrepDeletionMatch[] = [];\n\t\t\t\tlet reportedMatches: ContextGrepDeletionMatch[] = matches;\n\t\t\t\tconst skipped: ContextGrepDeletionSkipped[] = [];\n\t\t\t\tconst seenTargets = new Set<string>();\n\n\t\t\t\ttry {\n\t\t\t\t\tif (regex) {\n\t\t\t\t\t\tassertSafeRegexScan(store.getGrepScanTextLength(target));\n\t\t\t\t\t}\n\t\t\t\t\tconst matcher = createGrepMatcher(pattern, regex, caseSensitive);\n\t\t\t\t\tconst currentTargets = readTargets();\n\t\t\t\t\tconst recentEntryIds = getRecentContextEntryIds(transcript);\n\n\t\t\t\t\tif (target === \"entry\") {\n\t\t\t\t\t\tfor (const entry of store.listEntriesForGrep()) {\n\t\t\t\t\t\t\tif (!matcher.test(entry.text)) continue;\n\t\t\t\t\t\t\tconst candidate: ContextDeletionTarget = { kind: \"entry\", entryId: entry.entry_id };\n\t\t\t\t\t\t\tif (recentEntryIds.has(candidate.entryId)) {\n\t\t\t\t\t\t\t\tskipped.push({ entryId: entry.entry_id, target, reason: \"protected_entry\", text: entry.text });\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (entry.is_protected === 1 && !canDeleteProtectedTarget(candidate)) {\n\t\t\t\t\t\t\t\tskipped.push({ entryId: entry.entry_id, target, reason: \"protected_entry\", text: entry.text });\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (currentTargetDeleted(currentTargets, candidate)) {\n\t\t\t\t\t\t\t\tskipped.push({ entryId: entry.entry_id, target, reason: \"already_deleted\", text: entry.text });\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\taddGrepCandidate(candidates, matches, seenTargets, candidate, {\n\t\t\t\t\t\t\t\tentryId: entry.entry_id,\n\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\ttext: entry.text,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (const block of store.listContentBlocksForGrep()) {\n\t\t\t\t\t\t\tif (!matcher.test(block.text)) continue;\n\t\t\t\t\t\t\tconst candidate: ContextDeletionTarget = shouldGrepDeleteContentBlockAsEntry(block.entry_id, block.block_count)\n\t\t\t\t\t\t\t\t? { kind: \"entry\", entryId: block.entry_id }\n\t\t\t\t\t\t\t\t: { kind: \"content_block\", entryId: block.entry_id, blockIndex: block.block_index };\n\t\t\t\t\t\t\tif (recentEntryIds.has(candidate.entryId)) {\n\t\t\t\t\t\t\t\tskipped.push({\n\t\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\t\ttarget: candidate.kind,\n\t\t\t\t\t\t\t\t\t...(candidate.kind === \"content_block\" ? { blockIndex: candidate.blockIndex } : {}),\n\t\t\t\t\t\t\t\t\treason: \"protected_entry\",\n\t\t\t\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (block.entry_protected === 1 && !canDeleteProtectedTarget(candidate)) {\n\t\t\t\t\t\t\t\tskipped.push({\n\t\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\t\tblockIndex: block.block_index,\n\t\t\t\t\t\t\t\t\treason: \"protected_entry\",\n\t\t\t\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (block.block_protected === 1 && !canDeleteProtectedTarget(candidate)) {\n\t\t\t\t\t\t\t\tskipped.push({\n\t\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\t\tblockIndex: block.block_index,\n\t\t\t\t\t\t\t\t\treason: \"protected_block\",\n\t\t\t\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (currentTargetDeleted(currentTargets, candidate)) {\n\t\t\t\t\t\t\t\tskipped.push({\n\t\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\t\ttarget: candidate.kind,\n\t\t\t\t\t\t\t\t\t...(candidate.kind === \"content_block\" ? { blockIndex: candidate.blockIndex } : {}),\n\t\t\t\t\t\t\t\t\treason: \"already_deleted\",\n\t\t\t\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\taddGrepCandidate(candidates, matches, seenTargets, candidate, {\n\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\ttarget: candidate.kind,\n\t\t\t\t\t\t\t\t...(candidate.kind === \"content_block\" ? { blockIndex: candidate.blockIndex } : {}),\n\t\t\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst eligible = filterProtectedGrepCandidates(candidates, matches, currentTargets, transcript, skipped);\n\t\t\t\t\treportedMatches = eligible.matches;\n\t\t\t\t\tlet applied: ValidatedContextDeletionResult | undefined;\n\t\t\t\t\tif (params.expectedMatchCount !== undefined && eligible.candidates.length !== params.expectedMatchCount) {\n\t\t\t\t\t\tskipped.push({ reason: \"expected_match_count_mismatch\" });\n\t\t\t\t\t} else if (eligible.candidates.length > maxMatches) {\n\t\t\t\t\t\tskipped.push({ reason: \"max_matches_exceeded\" });\n\t\t\t\t\t} else if (eligible.candidates.length > 0) {\n\t\t\t\t\t\tapplied = applyValidatedTargets(eligible.candidates);\n\t\t\t\t\t}\n\t\t\t\t\tstore.clearLastError();\n\t\t\t\t\tconst deletedTargets = readTargets();\n\n\t\t\t\t\tconst details: ContextGrepDeletionToolDetails = {\n\t\t\t\t\t\tpattern,\n\t\t\t\t\t\tregex,\n\t\t\t\t\t\tcaseSensitive,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tmatches: eligible.matches,\n\t\t\t\t\t\tskipped,\n\t\t\t\t\t\tdeletedTargets,\n\t\t\t\t\t\tstats: applied?.stats ?? currentStats(),\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t};\n\t\t\t\t\tconst text = `Matched ${eligible.matches.length} deletion target(s), skipped ${skipped.length}, and ${applied ? \"applied\" : \"did not apply\"} grep deletion for pattern ${JSON.stringify(pattern)}. Total validated deletion target(s): ${deletedTargets.length}.`;\n\t\t\t\t\treturn createContextDeletionToolResult(text, details);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = formatErrorMessage(error);\n\t\t\t\t\tstore.setLastError(message);\n\t\t\t\t\tconst deletedTargets = readTargets();\n\t\t\t\t\tconst details: ContextGrepDeletionToolDetails = {\n\t\t\t\t\t\tpattern,\n\t\t\t\t\t\tregex,\n\t\t\t\t\t\tcaseSensitive,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tmatches: reportedMatches,\n\t\t\t\t\t\tskipped,\n\t\t\t\t\t\tdeletedTargets,\n\t\t\t\t\t\tstats: currentStats(),\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t};\n\t\t\t\t\treturn createContextDeletionToolResult(\n\t\t\t\t\t\t`Error applying grep deletion for pattern ${JSON.stringify(pattern)}: ${message}. No new deletion targets were applied; continue with a corrected tool call.`,\n\t\t\t\t\t\tdetails,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n\n\tconst searchTool: AgentTool<typeof ContextSearchTranscriptToolParameters, ContextTranscriptSearchToolDetails> = {\n\t\t...CONTEXT_SEARCH_TRANSCRIPT_TOOL,\n\t\tlabel: \"context transcript search\",\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params) {\n\t\t\treturn store.transaction(() => {\n\t\t\t\tconst callCount = store.incrementCallCount();\n\t\t\t\tconst pattern = params.pattern;\n\t\t\t\tconst regex = params.regex === true;\n\t\t\t\tconst caseSensitive = params.caseSensitive === true;\n\t\t\t\tconst target = params.target ?? \"entry\";\n\t\t\t\tconst maxMatches = clampInteger(params.maxMatches, CONTEXT_SEARCH_DEFAULT_MAX_MATCHES, 1, CONTEXT_SEARCH_MAX_MATCHES);\n\t\t\t\tconst contextChars = clampInteger(\n\t\t\t\t\tparams.contextChars,\n\t\t\t\t\tCONTEXT_SEARCH_DEFAULT_CONTEXT_CHARS,\n\t\t\t\t\t0,\n\t\t\t\t\tCONTEXT_SEARCH_MAX_CONTEXT_CHARS,\n\t\t\t\t);\n\t\t\t\tconst matches: ContextTranscriptSearchMatch[] = [];\n\t\t\t\tlet truncated = false;\n\n\t\t\t\ttry {\n\t\t\t\t\tif (regex) {\n\t\t\t\t\t\tassertSafeRegexScan(store.getGrepScanTextLength(target));\n\t\t\t\t\t}\n\t\t\t\t\tconst matcher = createGrepMatcher(pattern, regex, caseSensitive);\n\t\t\t\t\tif (target === \"entry\") {\n\t\t\t\t\t\tfor (const entry of store.listEntriesForGrep()) {\n\t\t\t\t\t\t\tconst matchIndex = findMatchIndex(matcher, entry.text);\n\t\t\t\t\t\t\tif (matchIndex < 0) continue;\n\t\t\t\t\t\t\tif (matches.length >= maxMatches) {\n\t\t\t\t\t\t\t\ttruncated = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmatches.push({\n\t\t\t\t\t\t\t\tentryId: entry.entry_id,\n\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\tmatchIndex,\n\t\t\t\t\t\t\t\tsnippet: snippetForMatch(entry.text, matchIndex, contextChars),\n\t\t\t\t\t\t\t\tprotected: entry.is_protected === 1,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (const block of store.listContentBlocksForGrep()) {\n\t\t\t\t\t\t\tconst matchIndex = findMatchIndex(matcher, block.text);\n\t\t\t\t\t\t\tif (matchIndex < 0) continue;\n\t\t\t\t\t\t\tif (matches.length >= maxMatches) {\n\t\t\t\t\t\t\t\ttruncated = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmatches.push({\n\t\t\t\t\t\t\t\tentryId: block.entry_id,\n\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\tblockIndex: block.block_index,\n\t\t\t\t\t\t\t\tmatchIndex,\n\t\t\t\t\t\t\t\tsnippet: snippetForMatch(block.text, matchIndex, contextChars),\n\t\t\t\t\t\t\t\tprotected: block.entry_protected === 1 || block.block_protected === 1,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tstore.clearLastError();\n\t\t\t\t\tconst details: ContextTranscriptSearchToolDetails = {\n\t\t\t\t\t\tpattern,\n\t\t\t\t\t\tregex,\n\t\t\t\t\t\tcaseSensitive,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tmatches,\n\t\t\t\t\t\ttruncated,\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t};\n\t\t\t\t\tconst text = `Found ${matches.length}${truncated ? \"+\" : \"\"} ${target} match(es) for ${JSON.stringify(pattern)}. Use ${CONTEXT_READ_ENTRY_TOOL_NAME} with small maxChars to inspect exact content before deleting.`;\n\t\t\t\t\treturn createContextDeletionToolResult(text, details);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = formatErrorMessage(error);\n\t\t\t\t\tstore.setLastError(message);\n\t\t\t\t\tconst details: ContextTranscriptSearchToolDetails = {\n\t\t\t\t\t\tpattern,\n\t\t\t\t\t\tregex,\n\t\t\t\t\t\tcaseSensitive,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tmatches,\n\t\t\t\t\t\ttruncated,\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t};\n\t\t\t\t\treturn createContextDeletionToolResult(\n\t\t\t\t\t\t`Error searching transcript for ${JSON.stringify(pattern)}: ${message}. Try a literal pattern or narrower query.`,\n\t\t\t\t\t\tdetails,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n\n\tconst readEntryTool: AgentTool<typeof ContextReadEntryToolParameters, ContextReadEntryToolDetails> = {\n\t\t...CONTEXT_READ_ENTRY_TOOL,\n\t\tlabel: \"context read entry\",\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId, params) {\n\t\t\treturn store.transaction(() => {\n\t\t\t\tconst callCount = store.incrementCallCount();\n\t\t\t\tconst offset = clampInteger(params.offset, 0, 0, Number.MAX_SAFE_INTEGER);\n\t\t\t\tconst maxChars = clampInteger(\n\t\t\t\t\tparams.maxChars,\n\t\t\t\t\tCONTEXT_READ_ENTRY_DEFAULT_MAX_CHARS,\n\t\t\t\t\t1,\n\t\t\t\t\tCONTEXT_READ_ENTRY_MAX_CHARS,\n\t\t\t\t);\n\t\t\t\ttry {\n\t\t\t\t\tconst row =\n\t\t\t\t\t\tparams.blockIndex === undefined\n\t\t\t\t\t\t\t? store.getEntryForRead(params.entryId)\n\t\t\t\t\t\t\t: store.getContentBlockForRead(params.entryId, params.blockIndex);\n\t\t\t\t\tif (!row) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\tparams.blockIndex === undefined\n\t\t\t\t\t\t\t\t? `Unknown transcript entry: ${params.entryId}`\n\t\t\t\t\t\t\t\t: `Unknown transcript content block: ${params.entryId}:${params.blockIndex}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst text = row.text;\n\t\t\t\t\tconst slice = textSlice(text, offset, maxChars);\n\t\t\t\t\tstore.clearLastError();\n\t\t\t\t\tconst details: ContextReadEntryToolDetails = {\n\t\t\t\t\t\tentryId: params.entryId,\n\t\t\t\t\t\t...(params.blockIndex === undefined ? {} : { blockIndex: params.blockIndex }),\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\tmaxChars,\n\t\t\t\t\t\ttotalChars: text.length,\n\t\t\t\t\t\ttext: slice,\n\t\t\t\t\t\ttruncatedBefore: offset > 0,\n\t\t\t\t\t\ttruncatedAfter: offset + maxChars < text.length,\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t};\n\t\t\t\t\tconst textResult = `Read ${slice.length} of ${text.length} characters from ${params.blockIndex === undefined ? params.entryId : `${params.entryId}:${params.blockIndex}`}. Keep reads small; increase offset for the next slice if needed.`;\n\t\t\t\t\treturn createContextDeletionToolResult(textResult, details);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = formatErrorMessage(error);\n\t\t\t\t\tstore.setLastError(message);\n\t\t\t\t\tconst details: ContextReadEntryToolDetails = {\n\t\t\t\t\t\tentryId: params.entryId,\n\t\t\t\t\t\t...(params.blockIndex === undefined ? {} : { blockIndex: params.blockIndex }),\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\tmaxChars,\n\t\t\t\t\t\ttotalChars: 0,\n\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\ttruncatedBefore: false,\n\t\t\t\t\t\ttruncatedAfter: false,\n\t\t\t\t\t\tcallCount,\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t};\n\t\t\t\t\treturn createContextDeletionToolResult(`Error reading transcript entry: ${message}`, details);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n\n\tconst budgetTool: AgentTool<typeof ContextCompactionBudgetToolParameters, ContextCompactionBudgetToolDetails> = {\n\t\t...CONTEXT_COMPACTION_BUDGET_TOOL,\n\t\tlabel: \"context compaction budget\",\n\t\texecutionMode: \"parallel\",\n\t\tasync execute(_toolCallId) {\n\t\t\treturn store.transaction(() => {\n\t\t\t\tconst callCount = store.incrementCallCount();\n\t\t\t\tstore.clearLastError();\n\t\t\t\tconst liveTargets = readTargets(); // recompute image stats each call (issue #1500)\n\t\t\t\tconst imageTokensRemaining = sumRemainingImageTokens(transcript, liveTargets);\n\t\t\t\tconst imageBlocksRemaining = countRemainingImageBlocks(transcript, liveTargets);\n\t\t\t\tconst details = createContextCompactionBudgetDetails(currentStats(), callCount, contextWindow, parameters, imageTokensRemaining, imageBlocksRemaining);\n\t\t\t\tconst windowText =\n\t\t\t\t\tdetails.contextWindowBeforePercent !== undefined\n\t\t\t\t\t\t? ` Context window fullness: ${details.contextWindowBeforePercent}% before selected deletions, ${details.contextWindowAfterPercent}% after selected deletions.`\n\t\t\t\t\t\t: \" Context window size is unknown for this model, so fullness percentages are unavailable.\";\n\t\t\t\tconst targetText = details.tokensToDeleteForTarget > 0 ? ` Delete about ${details.tokensToDeleteForTarget} more token(s) to reach the ${details.targetReductionPercent}% reduction target.` : ` The selected deletions meet or exceed the ${details.targetReductionPercent}% reduction target.`;\n\t\t\t\tconst imageText = details.remainingImageTokens > 0 ? ` Images account for ${details.imageTokenPercent}% of remaining context (${details.remainingImageTokens} tokens across ${details.imageBlockCount} block(s)); prefer deleting stale/superseded image content blocks when images dominate.` : \"\";\n\t\t\t\treturn createContextDeletionToolResult(\n\t\t\t\t\t`Current selected deletions reduce context by ${details.currentReductionPercent}% (${details.deletedTokens} token(s)); tokens after selected deletions: ${details.currentTokensAfter}/${details.tokensBefore}.${windowText}${targetText}${imageText} Keep maximizing useful retained context while aggressively removing low-value blocks.`,\n\t\t\t\t\tdetails,\n\t\t\t\t);\n\t\t\t});\n\t\t},\n\t};\n\n\treturn {\n\t\ttool,\n\t\tgrepTool,\n\t\tsearchTool,\n\t\treadEntryTool,\n\t\tbudgetTool,\n\t\ttools: [tool, grepTool, searchTool, readEntryTool, budgetTool],\n\t\tgetDeletionRequest: () => deletionRequestFromTargets(readTargets()),\n\t\tgetValidatedResult: () => validatedResult,\n\t\tgetLastError: () => store.getLastError(),\n\t\tgetCallCount: () => store.getCallCount(),\n\t};\n}\n"]}
|