@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session-tool-registry.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-tool-registry.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,2BAA2B,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG9F,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,wBAAwB,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAoH3I;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE;IAC1D,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;IAC3C,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACnC,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"agent-session-tool-registry.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-tool-registry.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,2BAA2B,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG9F,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,wBAAwB,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAoH3I;AAGD,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE;IAC1D,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;IAC3C,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACnC,GAAG,IAAI,CAyEP;AAGD,eAAO,MAAM,+BAA+B;;;CAG3C,CAAC","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { normalizeToolArgumentsForModel } from \"./copilot-gemini-tool-arguments.ts\";\nimport { ExtensionRunner, wrapRegisteredTools, type ToolDefinition } from \"./extensions/index.ts\";\nimport { createSyntheticSourceInfo } from \"./source-info.ts\";\nimport { createAllToolDefinitions, defaultToolNames } from \"./tools/index.ts\";\nimport { createToolDefinitionFromAgentTool } from \"./tools/tool-definition-wrapper.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { ToolDefinitionEntry } from \"./agent-session-types.ts\";\n\nexport function _refreshToolRegistry(this: AgentSession, options?: { activeToolNames?: string[]; includeAllExtensionTools?: boolean }): void {\n\tconst previousRegistryNames = new Set(this._toolRegistry.keys());\n\tconst previousActiveToolNames = this.getActiveToolNames();\n\tconst allowedToolNames = this._allowedToolNames;\n\tconst excludedToolNames = this._excludedToolNames;\n\tconst isExposedTool = (name: string): boolean => {\n\t\tif (allowedToolNames && !allowedToolNames.has(name)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (excludedToolNames?.has(name)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t};\n\n\tconst registeredTools = this._extensionRunner.getAllRegisteredTools();\n\tconst allCustomTools = [\n\t\t...registeredTools,\n\t\t...this._customTools.map((definition) => ({\n\t\t\tdefinition,\n\t\t\tsourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, { source: \"sdk\" }),\n\t\t})),\n\t].filter((tool) => isExposedTool(tool.definition.name));\n\tconst definitionRegistry = new Map<string, ToolDefinitionEntry>(\n\t\tArray.from(this._baseToolDefinitions.entries())\n\t\t\t.filter(([name]) => isExposedTool(name))\n\t\t\t.map(([name, definition]) => [\n\t\t\t\tname,\n\t\t\t\t{\n\t\t\t\t\tdefinition,\n\t\t\t\t\tsourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, { source: \"builtin\" }),\n\t\t\t\t},\n\t\t\t]),\n\t);\n\tfor (const tool of allCustomTools) {\n\t\tdefinitionRegistry.set(tool.definition.name, {\n\t\t\tdefinition: tool.definition,\n\t\t\tsourceInfo: tool.sourceInfo,\n\t\t});\n\t}\n\tthis._toolDefinitions = definitionRegistry;\n\tthis._toolPromptSnippets = new Map(\n\t\tArray.from(definitionRegistry.values())\n\t\t\t.map(({ definition }) => {\n\t\t\t\tconst snippet = this._normalizePromptSnippet(definition.promptSnippet);\n\t\t\t\treturn snippet ? ([definition.name, snippet] as const) : undefined;\n\t\t\t})\n\t\t\t.filter((entry): entry is readonly [string, string] => entry !== undefined),\n\t);\n\tthis._toolPromptGuidelines = new Map(\n\t\tArray.from(definitionRegistry.values())\n\t\t\t.map(({ definition }) => {\n\t\t\t\tconst guidelines = this._normalizePromptGuidelines(definition.promptGuidelines);\n\t\t\t\treturn guidelines.length > 0 ? ([definition.name, guidelines] as const) : undefined;\n\t\t\t})\n\t\t\t.filter((entry): entry is readonly [string, string[]] => entry !== undefined),\n\t);\n\tconst runner = this._extensionRunner;\n\tconst wrappedExtensionTools = wrapRegisteredTools(allCustomTools, runner);\n\tconst wrappedBuiltInTools = wrapRegisteredTools(\n\t\tArray.from(this._baseToolDefinitions.values())\n\t\t\t.filter((definition) => isExposedTool(definition.name))\n\t\t\t.map((definition) => ({\n\t\t\t\tdefinition,\n\t\t\t\tsourceInfo: createSyntheticSourceInfo(`<builtin:${definition.name}>`, { source: \"builtin\" }),\n\t\t\t})),\n\t\trunner,\n\t);\n\n\tconst toolRegistry = new Map(wrappedBuiltInTools.map((tool) => [tool.name, tool]));\n\tfor (const tool of wrappedExtensionTools as AgentTool[]) {\n\t\ttoolRegistry.set(tool.name, tool);\n\t}\n\t// GitHub Copilot Gemini serializes array/object tool-call arguments as\n\t// flattened `name[index]` keys (confirmed on the raw CAPI wire). Reconstruct\n\t// them into proper arrays/objects before per-tool preparation and schema\n\t// validation, so tool calls (notably structured_output) don't fail and loop.\n\t// Gated to Copilot Gemini at call time via this.model; a no-op otherwise.\n\t// `prepareArguments` is a plain function field (no `this` binding), and the\n\t// `{ ...tool }` spread assumes AgentTools are plain objects — matching the\n\t// existing tool-definition-wrapper pattern; a class-instance tool would lose\n\t// prototype members here.\n\tthis._toolRegistry = new Map(\n\t\tArray.from(toolRegistry, ([name, tool]) => {\n\t\t\tconst basePrepareArguments = tool.prepareArguments;\n\t\t\tconst prepareArguments = (args: unknown): unknown => {\n\t\t\t\tconst normalized = normalizeToolArgumentsForModel(args, this.model, tool.parameters);\n\t\t\t\treturn basePrepareArguments ? basePrepareArguments(normalized) : normalized;\n\t\t\t};\n\t\t\treturn [name, { ...tool, prepareArguments } as AgentTool] as const;\n\t\t}),\n\t);\n\n\tconst nextActiveToolNames = (\n\t\toptions?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]\n\t).filter((name) => isExposedTool(name));\n\n\tif (allowedToolNames) {\n\t\tfor (const toolName of this._toolRegistry.keys()) {\n\t\t\tif (allowedToolNames.has(toolName)) {\n\t\t\t\tnextActiveToolNames.push(toolName);\n\t\t\t}\n\t\t}\n\t} else if (options?.includeAllExtensionTools) {\n\t\tfor (const tool of wrappedExtensionTools) {\n\t\t\tnextActiveToolNames.push(tool.name);\n\t\t}\n\t} else if (!options?.activeToolNames) {\n\t\tfor (const toolName of this._toolRegistry.keys()) {\n\t\t\tif (!previousRegistryNames.has(toolName)) {\n\t\t\t\tnextActiveToolNames.push(toolName);\n\t\t\t}\n\t\t}\n\t}\n\n\tthis.setActiveToolsByName([...new Set(nextActiveToolNames)]);\n}\n\n\nexport function _buildRuntime(this: AgentSession, options: {\n\tactiveToolNames?: string[];\n\tflagValues?: Map<string, boolean | string>;\n\tincludeAllExtensionTools?: boolean;\n}): void {\n\tconst autoResizeImages = this.settingsManager.getImageAutoResize();\n\tconst shellCommandPrefix = this.settingsManager.getShellCommandPrefix();\n\tconst shellPath = this.settingsManager.getShellPath();\n\tconst isAllowedBuiltinTool = (name: string): boolean => {\n\t\tif (this._allowedToolNames && !this._allowedToolNames.has(name)) return false;\n\t\tif (this._excludedToolNames?.has(name)) return false;\n\t\treturn true;\n\t};\n\tconst activeBuiltinTools = (options.activeToolNames ?? [...defaultToolNames]).filter(isAllowedBuiltinTool);\n\tconst baseToolDefinitions = this._baseToolsOverride\n\t\t? Object.fromEntries(\n\t\t\t\tObject.entries(this._baseToolsOverride).map(([name, tool]) => [\n\t\t\t\t\tname,\n\t\t\t\t\tcreateToolDefinitionFromAgentTool(tool),\n\t\t\t\t]),\n\t\t\t)\n\t\t: createAllToolDefinitions(this._cwd, {\n\t\t\t\tread: { autoResizeImages },\n\t\t\t\tbash: {\n\t\t\t\t\tcommandPrefix: shellCommandPrefix,\n\t\t\t\t\tshellPath,\n\t\t\t\t\tinterceptorEnabled: () => this.settingsManager.getBashInterceptorEnabled(),\n\t\t\t\t\tavailableTools: activeBuiltinTools,\n\t\t\t\t\tinterceptor: async (context) => {\n\t\t\t\t\t\tconst result = await this._extensionRunner.emitUserBash({\n\t\t\t\t\t\t\ttype: \"user_bash\",\n\t\t\t\t\t\t\tcommand: context.command,\n\t\t\t\t\t\t\texcludeFromContext: false,\n\t\t\t\t\t\t\tcwd: context.cwd,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tsearch: {\n\t\t\t\t\tcontextBefore: this.settingsManager.getSearchContextBefore(),\n\t\t\t\t\tcontextAfter: this.settingsManager.getSearchContextAfter(),\n\t\t\t\t},\n\t\t\t});\n\n\tthis._baseToolDefinitions = new Map(\n\t\tObject.entries(baseToolDefinitions).map(([name, tool]) => [name, tool as ToolDefinition]),\n\t);\n\n\tconst extensionsResult = this._resourceLoader.getExtensions();\n\tif (options.flagValues) {\n\t\tfor (const [name, value] of options.flagValues) {\n\t\t\textensionsResult.runtime.flagValues.set(name, value);\n\t\t}\n\t}\n\n\tthis._extensionRunner = new ExtensionRunner(\n\t\textensionsResult.extensions,\n\t\textensionsResult.runtime,\n\t\tthis._cwd,\n\t\tthis.sessionManager,\n\t\tthis._modelRegistry,\n\t\tthis._orchestrationContext,\n\t);\n\tif (this._extensionRunnerRef) {\n\t\tthis._extensionRunnerRef.current = this._extensionRunner;\n\t}\n\tthis._bindExtensionCore(this._extensionRunner);\n\tthis._applyExtensionBindings(this._extensionRunner);\n\n\tconst defaultActiveToolNames = this._baseToolsOverride\n\t\t? Object.keys(this._baseToolsOverride)\n\t\t: [...defaultToolNames];\n\tconst baseActiveToolNames = options.activeToolNames ?? defaultActiveToolNames;\n\tthis._refreshToolRegistry({\n\t\tactiveToolNames: baseActiveToolNames,\n\t\tincludeAllExtensionTools: options.includeAllExtensionTools,\n\t});\n}\n\n\nexport const agentSessionToolRegistryMethods = {\n\t_refreshToolRegistry,\n\t_buildRuntime,\n};\n"]}
|
|
@@ -108,6 +108,14 @@ export function _buildRuntime(options) {
|
|
|
108
108
|
const autoResizeImages = this.settingsManager.getImageAutoResize();
|
|
109
109
|
const shellCommandPrefix = this.settingsManager.getShellCommandPrefix();
|
|
110
110
|
const shellPath = this.settingsManager.getShellPath();
|
|
111
|
+
const isAllowedBuiltinTool = (name) => {
|
|
112
|
+
if (this._allowedToolNames && !this._allowedToolNames.has(name))
|
|
113
|
+
return false;
|
|
114
|
+
if (this._excludedToolNames?.has(name))
|
|
115
|
+
return false;
|
|
116
|
+
return true;
|
|
117
|
+
};
|
|
118
|
+
const activeBuiltinTools = (options.activeToolNames ?? [...defaultToolNames]).filter(isAllowedBuiltinTool);
|
|
111
119
|
const baseToolDefinitions = this._baseToolsOverride
|
|
112
120
|
? Object.fromEntries(Object.entries(this._baseToolsOverride).map(([name, tool]) => [
|
|
113
121
|
name,
|
|
@@ -118,6 +126,21 @@ export function _buildRuntime(options) {
|
|
|
118
126
|
bash: {
|
|
119
127
|
commandPrefix: shellCommandPrefix,
|
|
120
128
|
shellPath,
|
|
129
|
+
interceptorEnabled: () => this.settingsManager.getBashInterceptorEnabled(),
|
|
130
|
+
availableTools: activeBuiltinTools,
|
|
131
|
+
interceptor: async (context) => {
|
|
132
|
+
const result = await this._extensionRunner.emitUserBash({
|
|
133
|
+
type: "user_bash",
|
|
134
|
+
command: context.command,
|
|
135
|
+
excludeFromContext: false,
|
|
136
|
+
cwd: context.cwd,
|
|
137
|
+
});
|
|
138
|
+
return result;
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
search: {
|
|
142
|
+
contextBefore: this.settingsManager.getSearchContextBefore(),
|
|
143
|
+
contextAfter: this.settingsManager.getSearchContextAfter(),
|
|
121
144
|
},
|
|
122
145
|
});
|
|
123
146
|
this._baseToolDefinitions = new Map(Object.entries(baseToolDefinitions).map(([name, tool]) => [name, tool]));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session-tool-registry.js","sourceRoot":"","sources":["../../src/core/agent-session-tool-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { normalizeToolArgumentsForModel } from \"./copilot-gemini-tool-arguments.ts\";\nimport { ExtensionRunner, wrapRegisteredTools, type ToolDefinition } from \"./extensions/index.ts\";\nimport { createSyntheticSourceInfo } from \"./source-info.ts\";\nimport { createAllToolDefinitions, defaultToolNames } from \"./tools/index.ts\";\nimport { createToolDefinitionFromAgentTool } from \"./tools/tool-definition-wrapper.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { ToolDefinitionEntry } from \"./agent-session-types.ts\";\n\nexport function _refreshToolRegistry(this: AgentSession, options?: { activeToolNames?: string[]; includeAllExtensionTools?: boolean }): void {\n\tconst previousRegistryNames = new Set(this._toolRegistry.keys());\n\tconst previousActiveToolNames = this.getActiveToolNames();\n\tconst allowedToolNames = this._allowedToolNames;\n\tconst excludedToolNames = this._excludedToolNames;\n\tconst isExposedTool = (name: string): boolean => {\n\t\tif (allowedToolNames && !allowedToolNames.has(name)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (excludedToolNames?.has(name)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t};\n\n\tconst registeredTools = this._extensionRunner.getAllRegisteredTools();\n\tconst allCustomTools = [\n\t\t...registeredTools,\n\t\t...this._customTools.map((definition) => ({\n\t\t\tdefinition,\n\t\t\tsourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, { source: \"sdk\" }),\n\t\t})),\n\t].filter((tool) => isExposedTool(tool.definition.name));\n\tconst definitionRegistry = new Map<string, ToolDefinitionEntry>(\n\t\tArray.from(this._baseToolDefinitions.entries())\n\t\t\t.filter(([name]) => isExposedTool(name))\n\t\t\t.map(([name, definition]) => [\n\t\t\t\tname,\n\t\t\t\t{\n\t\t\t\t\tdefinition,\n\t\t\t\t\tsourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, { source: \"builtin\" }),\n\t\t\t\t},\n\t\t\t]),\n\t);\n\tfor (const tool of allCustomTools) {\n\t\tdefinitionRegistry.set(tool.definition.name, {\n\t\t\tdefinition: tool.definition,\n\t\t\tsourceInfo: tool.sourceInfo,\n\t\t});\n\t}\n\tthis._toolDefinitions = definitionRegistry;\n\tthis._toolPromptSnippets = new Map(\n\t\tArray.from(definitionRegistry.values())\n\t\t\t.map(({ definition }) => {\n\t\t\t\tconst snippet = this._normalizePromptSnippet(definition.promptSnippet);\n\t\t\t\treturn snippet ? ([definition.name, snippet] as const) : undefined;\n\t\t\t})\n\t\t\t.filter((entry): entry is readonly [string, string] => entry !== undefined),\n\t);\n\tthis._toolPromptGuidelines = new Map(\n\t\tArray.from(definitionRegistry.values())\n\t\t\t.map(({ definition }) => {\n\t\t\t\tconst guidelines = this._normalizePromptGuidelines(definition.promptGuidelines);\n\t\t\t\treturn guidelines.length > 0 ? ([definition.name, guidelines] as const) : undefined;\n\t\t\t})\n\t\t\t.filter((entry): entry is readonly [string, string[]] => entry !== undefined),\n\t);\n\tconst runner = this._extensionRunner;\n\tconst wrappedExtensionTools = wrapRegisteredTools(allCustomTools, runner);\n\tconst wrappedBuiltInTools = wrapRegisteredTools(\n\t\tArray.from(this._baseToolDefinitions.values())\n\t\t\t.filter((definition) => isExposedTool(definition.name))\n\t\t\t.map((definition) => ({\n\t\t\t\tdefinition,\n\t\t\t\tsourceInfo: createSyntheticSourceInfo(`<builtin:${definition.name}>`, { source: \"builtin\" }),\n\t\t\t})),\n\t\trunner,\n\t);\n\n\tconst toolRegistry = new Map(wrappedBuiltInTools.map((tool) => [tool.name, tool]));\n\tfor (const tool of wrappedExtensionTools as AgentTool[]) {\n\t\ttoolRegistry.set(tool.name, tool);\n\t}\n\t// GitHub Copilot Gemini serializes array/object tool-call arguments as\n\t// flattened `name[index]` keys (confirmed on the raw CAPI wire). Reconstruct\n\t// them into proper arrays/objects before per-tool preparation and schema\n\t// validation, so tool calls (notably structured_output) don't fail and loop.\n\t// Gated to Copilot Gemini at call time via this.model; a no-op otherwise.\n\t// `prepareArguments` is a plain function field (no `this` binding), and the\n\t// `{ ...tool }` spread assumes AgentTools are plain objects — matching the\n\t// existing tool-definition-wrapper pattern; a class-instance tool would lose\n\t// prototype members here.\n\tthis._toolRegistry = new Map(\n\t\tArray.from(toolRegistry, ([name, tool]) => {\n\t\t\tconst basePrepareArguments = tool.prepareArguments;\n\t\t\tconst prepareArguments = (args: unknown): unknown => {\n\t\t\t\tconst normalized = normalizeToolArgumentsForModel(args, this.model, tool.parameters);\n\t\t\t\treturn basePrepareArguments ? basePrepareArguments(normalized) : normalized;\n\t\t\t};\n\t\t\treturn [name, { ...tool, prepareArguments } as AgentTool] as const;\n\t\t}),\n\t);\n\n\tconst nextActiveToolNames = (\n\t\toptions?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]\n\t).filter((name) => isExposedTool(name));\n\n\tif (allowedToolNames) {\n\t\tfor (const toolName of this._toolRegistry.keys()) {\n\t\t\tif (allowedToolNames.has(toolName)) {\n\t\t\t\tnextActiveToolNames.push(toolName);\n\t\t\t}\n\t\t}\n\t} else if (options?.includeAllExtensionTools) {\n\t\tfor (const tool of wrappedExtensionTools) {\n\t\t\tnextActiveToolNames.push(tool.name);\n\t\t}\n\t} else if (!options?.activeToolNames) {\n\t\tfor (const toolName of this._toolRegistry.keys()) {\n\t\t\tif (!previousRegistryNames.has(toolName)) {\n\t\t\t\tnextActiveToolNames.push(toolName);\n\t\t\t}\n\t\t}\n\t}\n\n\tthis.setActiveToolsByName([...new Set(nextActiveToolNames)]);\n}\n\n\nexport function _buildRuntime(this: AgentSession, options: {\n\tactiveToolNames?: string[];\n\tflagValues?: Map<string, boolean | string>;\n\tincludeAllExtensionTools?: boolean;\n}): void {\n\tconst autoResizeImages = this.settingsManager.getImageAutoResize();\n\tconst shellCommandPrefix = this.settingsManager.getShellCommandPrefix();\n\tconst shellPath = this.settingsManager.getShellPath();\n\tconst baseToolDefinitions = this._baseToolsOverride\n\t\t? Object.fromEntries(\n\t\t\t\tObject.entries(this._baseToolsOverride).map(([name, tool]) => [\n\t\t\t\t\tname,\n\t\t\t\t\tcreateToolDefinitionFromAgentTool(tool),\n\t\t\t\t]),\n\t\t\t)\n\t\t: createAllToolDefinitions(this._cwd, {\n\t\t\t\tread: { autoResizeImages },\n\t\t\t\tbash: {\n\t\t\t\t\tcommandPrefix: shellCommandPrefix,\n\t\t\t\t\tshellPath,\n\t\t\t\t},\n\t\t\t});\n\n\tthis._baseToolDefinitions = new Map(\n\t\tObject.entries(baseToolDefinitions).map(([name, tool]) => [name, tool as ToolDefinition]),\n\t);\n\n\tconst extensionsResult = this._resourceLoader.getExtensions();\n\tif (options.flagValues) {\n\t\tfor (const [name, value] of options.flagValues) {\n\t\t\textensionsResult.runtime.flagValues.set(name, value);\n\t\t}\n\t}\n\n\tthis._extensionRunner = new ExtensionRunner(\n\t\textensionsResult.extensions,\n\t\textensionsResult.runtime,\n\t\tthis._cwd,\n\t\tthis.sessionManager,\n\t\tthis._modelRegistry,\n\t\tthis._orchestrationContext,\n\t);\n\tif (this._extensionRunnerRef) {\n\t\tthis._extensionRunnerRef.current = this._extensionRunner;\n\t}\n\tthis._bindExtensionCore(this._extensionRunner);\n\tthis._applyExtensionBindings(this._extensionRunner);\n\n\tconst defaultActiveToolNames = this._baseToolsOverride\n\t\t? Object.keys(this._baseToolsOverride)\n\t\t: [...defaultToolNames];\n\tconst baseActiveToolNames = options.activeToolNames ?? defaultActiveToolNames;\n\tthis._refreshToolRegistry({\n\t\tactiveToolNames: baseActiveToolNames,\n\t\tincludeAllExtensionTools: options.includeAllExtensionTools,\n\t});\n}\n\n\nexport const agentSessionToolRegistryMethods = {\n\t_refreshToolRegistry,\n\t_buildRuntime,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"agent-session-tool-registry.js","sourceRoot":"","sources":["../../src/core/agent-session-tool-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { normalizeToolArgumentsForModel } from \"./copilot-gemini-tool-arguments.ts\";\nimport { ExtensionRunner, wrapRegisteredTools, type ToolDefinition } from \"./extensions/index.ts\";\nimport { createSyntheticSourceInfo } from \"./source-info.ts\";\nimport { createAllToolDefinitions, defaultToolNames } from \"./tools/index.ts\";\nimport { createToolDefinitionFromAgentTool } from \"./tools/tool-definition-wrapper.ts\";\nimport type { AgentSessionInternalSurface as AgentSession } from \"./agent-session-methods.ts\";\nimport type { ToolDefinitionEntry } from \"./agent-session-types.ts\";\n\nexport function _refreshToolRegistry(this: AgentSession, options?: { activeToolNames?: string[]; includeAllExtensionTools?: boolean }): void {\n\tconst previousRegistryNames = new Set(this._toolRegistry.keys());\n\tconst previousActiveToolNames = this.getActiveToolNames();\n\tconst allowedToolNames = this._allowedToolNames;\n\tconst excludedToolNames = this._excludedToolNames;\n\tconst isExposedTool = (name: string): boolean => {\n\t\tif (allowedToolNames && !allowedToolNames.has(name)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (excludedToolNames?.has(name)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t};\n\n\tconst registeredTools = this._extensionRunner.getAllRegisteredTools();\n\tconst allCustomTools = [\n\t\t...registeredTools,\n\t\t...this._customTools.map((definition) => ({\n\t\t\tdefinition,\n\t\t\tsourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, { source: \"sdk\" }),\n\t\t})),\n\t].filter((tool) => isExposedTool(tool.definition.name));\n\tconst definitionRegistry = new Map<string, ToolDefinitionEntry>(\n\t\tArray.from(this._baseToolDefinitions.entries())\n\t\t\t.filter(([name]) => isExposedTool(name))\n\t\t\t.map(([name, definition]) => [\n\t\t\t\tname,\n\t\t\t\t{\n\t\t\t\t\tdefinition,\n\t\t\t\t\tsourceInfo: createSyntheticSourceInfo(`<builtin:${name}>`, { source: \"builtin\" }),\n\t\t\t\t},\n\t\t\t]),\n\t);\n\tfor (const tool of allCustomTools) {\n\t\tdefinitionRegistry.set(tool.definition.name, {\n\t\t\tdefinition: tool.definition,\n\t\t\tsourceInfo: tool.sourceInfo,\n\t\t});\n\t}\n\tthis._toolDefinitions = definitionRegistry;\n\tthis._toolPromptSnippets = new Map(\n\t\tArray.from(definitionRegistry.values())\n\t\t\t.map(({ definition }) => {\n\t\t\t\tconst snippet = this._normalizePromptSnippet(definition.promptSnippet);\n\t\t\t\treturn snippet ? ([definition.name, snippet] as const) : undefined;\n\t\t\t})\n\t\t\t.filter((entry): entry is readonly [string, string] => entry !== undefined),\n\t);\n\tthis._toolPromptGuidelines = new Map(\n\t\tArray.from(definitionRegistry.values())\n\t\t\t.map(({ definition }) => {\n\t\t\t\tconst guidelines = this._normalizePromptGuidelines(definition.promptGuidelines);\n\t\t\t\treturn guidelines.length > 0 ? ([definition.name, guidelines] as const) : undefined;\n\t\t\t})\n\t\t\t.filter((entry): entry is readonly [string, string[]] => entry !== undefined),\n\t);\n\tconst runner = this._extensionRunner;\n\tconst wrappedExtensionTools = wrapRegisteredTools(allCustomTools, runner);\n\tconst wrappedBuiltInTools = wrapRegisteredTools(\n\t\tArray.from(this._baseToolDefinitions.values())\n\t\t\t.filter((definition) => isExposedTool(definition.name))\n\t\t\t.map((definition) => ({\n\t\t\t\tdefinition,\n\t\t\t\tsourceInfo: createSyntheticSourceInfo(`<builtin:${definition.name}>`, { source: \"builtin\" }),\n\t\t\t})),\n\t\trunner,\n\t);\n\n\tconst toolRegistry = new Map(wrappedBuiltInTools.map((tool) => [tool.name, tool]));\n\tfor (const tool of wrappedExtensionTools as AgentTool[]) {\n\t\ttoolRegistry.set(tool.name, tool);\n\t}\n\t// GitHub Copilot Gemini serializes array/object tool-call arguments as\n\t// flattened `name[index]` keys (confirmed on the raw CAPI wire). Reconstruct\n\t// them into proper arrays/objects before per-tool preparation and schema\n\t// validation, so tool calls (notably structured_output) don't fail and loop.\n\t// Gated to Copilot Gemini at call time via this.model; a no-op otherwise.\n\t// `prepareArguments` is a plain function field (no `this` binding), and the\n\t// `{ ...tool }` spread assumes AgentTools are plain objects — matching the\n\t// existing tool-definition-wrapper pattern; a class-instance tool would lose\n\t// prototype members here.\n\tthis._toolRegistry = new Map(\n\t\tArray.from(toolRegistry, ([name, tool]) => {\n\t\t\tconst basePrepareArguments = tool.prepareArguments;\n\t\t\tconst prepareArguments = (args: unknown): unknown => {\n\t\t\t\tconst normalized = normalizeToolArgumentsForModel(args, this.model, tool.parameters);\n\t\t\t\treturn basePrepareArguments ? basePrepareArguments(normalized) : normalized;\n\t\t\t};\n\t\t\treturn [name, { ...tool, prepareArguments } as AgentTool] as const;\n\t\t}),\n\t);\n\n\tconst nextActiveToolNames = (\n\t\toptions?.activeToolNames ? [...options.activeToolNames] : [...previousActiveToolNames]\n\t).filter((name) => isExposedTool(name));\n\n\tif (allowedToolNames) {\n\t\tfor (const toolName of this._toolRegistry.keys()) {\n\t\t\tif (allowedToolNames.has(toolName)) {\n\t\t\t\tnextActiveToolNames.push(toolName);\n\t\t\t}\n\t\t}\n\t} else if (options?.includeAllExtensionTools) {\n\t\tfor (const tool of wrappedExtensionTools) {\n\t\t\tnextActiveToolNames.push(tool.name);\n\t\t}\n\t} else if (!options?.activeToolNames) {\n\t\tfor (const toolName of this._toolRegistry.keys()) {\n\t\t\tif (!previousRegistryNames.has(toolName)) {\n\t\t\t\tnextActiveToolNames.push(toolName);\n\t\t\t}\n\t\t}\n\t}\n\n\tthis.setActiveToolsByName([...new Set(nextActiveToolNames)]);\n}\n\n\nexport function _buildRuntime(this: AgentSession, options: {\n\tactiveToolNames?: string[];\n\tflagValues?: Map<string, boolean | string>;\n\tincludeAllExtensionTools?: boolean;\n}): void {\n\tconst autoResizeImages = this.settingsManager.getImageAutoResize();\n\tconst shellCommandPrefix = this.settingsManager.getShellCommandPrefix();\n\tconst shellPath = this.settingsManager.getShellPath();\n\tconst isAllowedBuiltinTool = (name: string): boolean => {\n\t\tif (this._allowedToolNames && !this._allowedToolNames.has(name)) return false;\n\t\tif (this._excludedToolNames?.has(name)) return false;\n\t\treturn true;\n\t};\n\tconst activeBuiltinTools = (options.activeToolNames ?? [...defaultToolNames]).filter(isAllowedBuiltinTool);\n\tconst baseToolDefinitions = this._baseToolsOverride\n\t\t? Object.fromEntries(\n\t\t\t\tObject.entries(this._baseToolsOverride).map(([name, tool]) => [\n\t\t\t\t\tname,\n\t\t\t\t\tcreateToolDefinitionFromAgentTool(tool),\n\t\t\t\t]),\n\t\t\t)\n\t\t: createAllToolDefinitions(this._cwd, {\n\t\t\t\tread: { autoResizeImages },\n\t\t\t\tbash: {\n\t\t\t\t\tcommandPrefix: shellCommandPrefix,\n\t\t\t\t\tshellPath,\n\t\t\t\t\tinterceptorEnabled: () => this.settingsManager.getBashInterceptorEnabled(),\n\t\t\t\t\tavailableTools: activeBuiltinTools,\n\t\t\t\t\tinterceptor: async (context) => {\n\t\t\t\t\t\tconst result = await this._extensionRunner.emitUserBash({\n\t\t\t\t\t\t\ttype: \"user_bash\",\n\t\t\t\t\t\t\tcommand: context.command,\n\t\t\t\t\t\t\texcludeFromContext: false,\n\t\t\t\t\t\t\tcwd: context.cwd,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tsearch: {\n\t\t\t\t\tcontextBefore: this.settingsManager.getSearchContextBefore(),\n\t\t\t\t\tcontextAfter: this.settingsManager.getSearchContextAfter(),\n\t\t\t\t},\n\t\t\t});\n\n\tthis._baseToolDefinitions = new Map(\n\t\tObject.entries(baseToolDefinitions).map(([name, tool]) => [name, tool as ToolDefinition]),\n\t);\n\n\tconst extensionsResult = this._resourceLoader.getExtensions();\n\tif (options.flagValues) {\n\t\tfor (const [name, value] of options.flagValues) {\n\t\t\textensionsResult.runtime.flagValues.set(name, value);\n\t\t}\n\t}\n\n\tthis._extensionRunner = new ExtensionRunner(\n\t\textensionsResult.extensions,\n\t\textensionsResult.runtime,\n\t\tthis._cwd,\n\t\tthis.sessionManager,\n\t\tthis._modelRegistry,\n\t\tthis._orchestrationContext,\n\t);\n\tif (this._extensionRunnerRef) {\n\t\tthis._extensionRunnerRef.current = this._extensionRunner;\n\t}\n\tthis._bindExtensionCore(this._extensionRunner);\n\tthis._applyExtensionBindings(this._extensionRunner);\n\n\tconst defaultActiveToolNames = this._baseToolsOverride\n\t\t? Object.keys(this._baseToolsOverride)\n\t\t: [...defaultToolNames];\n\tconst baseActiveToolNames = options.activeToolNames ?? defaultActiveToolNames;\n\tthis._refreshToolRegistry({\n\t\tactiveToolNames: baseActiveToolNames,\n\t\tincludeAllExtensionTools: options.includeAllExtensionTools,\n\t});\n}\n\n\nexport const agentSessionToolRegistryMethods = {\n\t_refreshToolRegistry,\n\t_buildRuntime,\n};\n"]}
|
|
@@ -11,6 +11,8 @@ export interface BashExecutorOptions {
|
|
|
11
11
|
onChunk?: (chunk: string) => void;
|
|
12
12
|
/** AbortSignal for cancellation */
|
|
13
13
|
signal?: AbortSignal;
|
|
14
|
+
/** Run with PTY handling when supported by the operations backend */
|
|
15
|
+
pty?: boolean;
|
|
14
16
|
}
|
|
15
17
|
export interface BashResult {
|
|
16
18
|
/** Combined stdout + stderr output (sanitized, possibly truncated) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash-executor.d.ts","sourceRoot":"","sources":["../../src/core/bash-executor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAOtD,MAAM,WAAW,mBAAmB;IACnC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,mCAAmC;IACnC,MAAM,CAAC,EAAE,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"bash-executor.d.ts","sourceRoot":"","sources":["../../src/core/bash-executor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAOtD,MAAM,WAAW,mBAAmB;IACnC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,mCAAmC;IACnC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,qEAAqE;IACrE,GAAG,CAAC,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IAC1B,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,mDAAmD;IACnD,SAAS,EAAE,OAAO,CAAC;IACnB,uCAAuC;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,yFAAyF;IACzF,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;GAGG;AACH,wBAAsB,yBAAyB,CAC9C,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,cAAc,EAC1B,OAAO,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,UAAU,CAAC,CAsGrB","sourcesContent":["/**\n * Bash command execution with streaming support and cancellation.\n *\n * This module provides a unified bash execution implementation used by:\n * - AgentSession.executeBash() for interactive and RPC modes\n * - Direct calls from modes that need bash execution\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { createWriteStream, type WriteStream } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { APP_NAME } from \"../config.ts\";\nimport { stripAnsi } from \"../utils/ansi.ts\";\nimport { sanitizeBinaryOutput } from \"../utils/shell.ts\";\nimport type { BashOperations } from \"./tools/bash.ts\";\nimport { DEFAULT_MAX_BYTES, truncateTail } from \"./tools/truncate.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface BashExecutorOptions {\n\t/** Callback for streaming output chunks (already sanitized) */\n\tonChunk?: (chunk: string) => void;\n\t/** AbortSignal for cancellation */\n\tsignal?: AbortSignal;\n\t/** Run with PTY handling when supported by the operations backend */\n\tpty?: boolean;\n}\n\nexport interface BashResult {\n\t/** Combined stdout + stderr output (sanitized, possibly truncated) */\n\toutput: string;\n\t/** Process exit code (undefined if killed/cancelled) */\n\texitCode: number | undefined;\n\t/** Whether the command was cancelled via signal */\n\tcancelled: boolean;\n\t/** Whether the output was truncated */\n\ttruncated: boolean;\n\t/** Path to temp file containing full output (if output exceeded truncation threshold) */\n\tfullOutputPath?: string;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Execute a bash command using custom BashOperations.\n * Used for remote execution (SSH, containers, etc.).\n */\nexport async function executeBashWithOperations(\n\tcommand: string,\n\tcwd: string,\n\toperations: BashOperations,\n\toptions?: BashExecutorOptions,\n): Promise<BashResult> {\n\tconst outputChunks: string[] = [];\n\tlet outputBytes = 0;\n\tconst maxOutputBytes = DEFAULT_MAX_BYTES * 2;\n\n\tlet tempFilePath: string | undefined;\n\tlet tempFileStream: WriteStream | undefined;\n\tlet totalBytes = 0;\n\n\tconst ensureTempFile = () => {\n\t\tif (tempFilePath) {\n\t\t\treturn;\n\t\t}\n\t\tconst id = randomBytes(8).toString(\"hex\");\n\t\ttempFilePath = join(tmpdir(), `${APP_NAME}-bash-${id}.log`);\n\t\ttempFileStream = createWriteStream(tempFilePath);\n\t\tfor (const chunk of outputChunks) {\n\t\t\ttempFileStream.write(chunk);\n\t\t}\n\t};\n\n\tconst decoder = new TextDecoder();\n\n\tconst onData = (data: Buffer) => {\n\t\ttotalBytes += data.length;\n\n\t\t// Sanitize: strip ANSI, replace binary garbage, normalize newlines\n\t\tconst text = sanitizeBinaryOutput(stripAnsi(decoder.decode(data, { stream: true }))).replace(/\\r/g, \"\");\n\n\t\t// Start writing to temp file if exceeds threshold\n\t\tif (totalBytes > DEFAULT_MAX_BYTES) {\n\t\t\tensureTempFile();\n\t\t}\n\n\t\tif (tempFileStream) {\n\t\t\ttempFileStream.write(text);\n\t\t}\n\n\t\t// Keep rolling buffer\n\t\toutputChunks.push(text);\n\t\toutputBytes += text.length;\n\t\twhile (outputBytes > maxOutputBytes && outputChunks.length > 1) {\n\t\t\tconst removed = outputChunks.shift()!;\n\t\t\toutputBytes -= removed.length;\n\t\t}\n\n\t\t// Stream to callback\n\t\tif (options?.onChunk) {\n\t\t\toptions.onChunk(text);\n\t\t}\n\t};\n\n\ttry {\n\t\tconst result = await operations.exec(command, cwd, {\n\t\t\tonData,\n\t\t\tsignal: options?.signal,\n\t\t\tpty: options?.pty,\n\t\t});\n\n\t\tconst fullOutput = outputChunks.join(\"\");\n\t\tconst truncationResult = truncateTail(fullOutput);\n\t\tif (truncationResult.truncated) {\n\t\t\tensureTempFile();\n\t\t}\n\t\tif (tempFileStream) {\n\t\t\ttempFileStream.end();\n\t\t}\n\t\tconst cancelled = options?.signal?.aborted ?? false;\n\n\t\treturn {\n\t\t\toutput: truncationResult.truncated ? truncationResult.content : fullOutput,\n\t\t\texitCode: cancelled ? undefined : (result.exitCode ?? undefined),\n\t\t\tcancelled,\n\t\t\ttruncated: truncationResult.truncated,\n\t\t\tfullOutputPath: tempFilePath,\n\t\t};\n\t} catch (err) {\n\t\t// Check if it was an abort\n\t\tif (options?.signal?.aborted) {\n\t\t\tconst fullOutput = outputChunks.join(\"\");\n\t\t\tconst truncationResult = truncateTail(fullOutput);\n\t\t\tif (truncationResult.truncated) {\n\t\t\t\tensureTempFile();\n\t\t\t}\n\t\t\tif (tempFileStream) {\n\t\t\t\ttempFileStream.end();\n\t\t\t}\n\t\t\treturn {\n\t\t\t\toutput: truncationResult.truncated ? truncationResult.content : fullOutput,\n\t\t\t\texitCode: undefined,\n\t\t\t\tcancelled: true,\n\t\t\t\ttruncated: truncationResult.truncated,\n\t\t\t\tfullOutputPath: tempFilePath,\n\t\t\t};\n\t\t}\n\n\t\tif (tempFileStream) {\n\t\t\ttempFileStream.end();\n\t\t}\n\n\t\tthrow err;\n\t}\n}\n"]}
|
|
@@ -66,6 +66,7 @@ export async function executeBashWithOperations(command, cwd, operations, option
|
|
|
66
66
|
const result = await operations.exec(command, cwd, {
|
|
67
67
|
onData,
|
|
68
68
|
signal: options?.signal,
|
|
69
|
+
pty: options?.pty,
|
|
69
70
|
});
|
|
70
71
|
const fullOutput = outputChunks.join("");
|
|
71
72
|
const truncationResult = truncateTail(fullOutput);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash-executor.js","sourceRoot":"","sources":["../../src/core/bash-executor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAoB,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"bash-executor.js","sourceRoot":"","sources":["../../src/core/bash-executor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Bash command execution with streaming support and cancellation.\n *\n * This module provides a unified bash execution implementation used by:\n * - AgentSession.executeBash() for interactive and RPC modes\n * - Direct calls from modes that need bash execution\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { createWriteStream, type WriteStream } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { APP_NAME } from \"../config.ts\";\nimport { stripAnsi } from \"../utils/ansi.ts\";\nimport { sanitizeBinaryOutput } from \"../utils/shell.ts\";\nimport type { BashOperations } from \"./tools/bash.ts\";\nimport { DEFAULT_MAX_BYTES, truncateTail } from \"./tools/truncate.ts\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface BashExecutorOptions {\n\t/** Callback for streaming output chunks (already sanitized) */\n\tonChunk?: (chunk: string) => void;\n\t/** AbortSignal for cancellation */\n\tsignal?: AbortSignal;\n\t/** Run with PTY handling when supported by the operations backend */\n\tpty?: boolean;\n}\n\nexport interface BashResult {\n\t/** Combined stdout + stderr output (sanitized, possibly truncated) */\n\toutput: string;\n\t/** Process exit code (undefined if killed/cancelled) */\n\texitCode: number | undefined;\n\t/** Whether the command was cancelled via signal */\n\tcancelled: boolean;\n\t/** Whether the output was truncated */\n\ttruncated: boolean;\n\t/** Path to temp file containing full output (if output exceeded truncation threshold) */\n\tfullOutputPath?: string;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Execute a bash command using custom BashOperations.\n * Used for remote execution (SSH, containers, etc.).\n */\nexport async function executeBashWithOperations(\n\tcommand: string,\n\tcwd: string,\n\toperations: BashOperations,\n\toptions?: BashExecutorOptions,\n): Promise<BashResult> {\n\tconst outputChunks: string[] = [];\n\tlet outputBytes = 0;\n\tconst maxOutputBytes = DEFAULT_MAX_BYTES * 2;\n\n\tlet tempFilePath: string | undefined;\n\tlet tempFileStream: WriteStream | undefined;\n\tlet totalBytes = 0;\n\n\tconst ensureTempFile = () => {\n\t\tif (tempFilePath) {\n\t\t\treturn;\n\t\t}\n\t\tconst id = randomBytes(8).toString(\"hex\");\n\t\ttempFilePath = join(tmpdir(), `${APP_NAME}-bash-${id}.log`);\n\t\ttempFileStream = createWriteStream(tempFilePath);\n\t\tfor (const chunk of outputChunks) {\n\t\t\ttempFileStream.write(chunk);\n\t\t}\n\t};\n\n\tconst decoder = new TextDecoder();\n\n\tconst onData = (data: Buffer) => {\n\t\ttotalBytes += data.length;\n\n\t\t// Sanitize: strip ANSI, replace binary garbage, normalize newlines\n\t\tconst text = sanitizeBinaryOutput(stripAnsi(decoder.decode(data, { stream: true }))).replace(/\\r/g, \"\");\n\n\t\t// Start writing to temp file if exceeds threshold\n\t\tif (totalBytes > DEFAULT_MAX_BYTES) {\n\t\t\tensureTempFile();\n\t\t}\n\n\t\tif (tempFileStream) {\n\t\t\ttempFileStream.write(text);\n\t\t}\n\n\t\t// Keep rolling buffer\n\t\toutputChunks.push(text);\n\t\toutputBytes += text.length;\n\t\twhile (outputBytes > maxOutputBytes && outputChunks.length > 1) {\n\t\t\tconst removed = outputChunks.shift()!;\n\t\t\toutputBytes -= removed.length;\n\t\t}\n\n\t\t// Stream to callback\n\t\tif (options?.onChunk) {\n\t\t\toptions.onChunk(text);\n\t\t}\n\t};\n\n\ttry {\n\t\tconst result = await operations.exec(command, cwd, {\n\t\t\tonData,\n\t\t\tsignal: options?.signal,\n\t\t\tpty: options?.pty,\n\t\t});\n\n\t\tconst fullOutput = outputChunks.join(\"\");\n\t\tconst truncationResult = truncateTail(fullOutput);\n\t\tif (truncationResult.truncated) {\n\t\t\tensureTempFile();\n\t\t}\n\t\tif (tempFileStream) {\n\t\t\ttempFileStream.end();\n\t\t}\n\t\tconst cancelled = options?.signal?.aborted ?? false;\n\n\t\treturn {\n\t\t\toutput: truncationResult.truncated ? truncationResult.content : fullOutput,\n\t\t\texitCode: cancelled ? undefined : (result.exitCode ?? undefined),\n\t\t\tcancelled,\n\t\t\ttruncated: truncationResult.truncated,\n\t\t\tfullOutputPath: tempFilePath,\n\t\t};\n\t} catch (err) {\n\t\t// Check if it was an abort\n\t\tif (options?.signal?.aborted) {\n\t\t\tconst fullOutput = outputChunks.join(\"\");\n\t\t\tconst truncationResult = truncateTail(fullOutput);\n\t\t\tif (truncationResult.truncated) {\n\t\t\t\tensureTempFile();\n\t\t\t}\n\t\t\tif (tempFileStream) {\n\t\t\t\ttempFileStream.end();\n\t\t\t}\n\t\t\treturn {\n\t\t\t\toutput: truncationResult.truncated ? truncationResult.content : fullOutput,\n\t\t\t\texitCode: undefined,\n\t\t\t\tcancelled: true,\n\t\t\t\ttruncated: truncationResult.truncated,\n\t\t\t\tfullOutputPath: tempFilePath,\n\t\t\t};\n\t\t}\n\n\t\tif (tempFileStream) {\n\t\t\ttempFileStream.end();\n\t\t}\n\n\t\tthrow err;\n\t}\n}\n"]}
|
|
@@ -45,6 +45,35 @@ export declare function estimateContextTokens(messages: AgentMessage[]): Context
|
|
|
45
45
|
* Check if compaction should trigger based on context usage.
|
|
46
46
|
*/
|
|
47
47
|
export declare function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Shared image-token estimation used by every compaction/context-accounting path.
|
|
50
|
+
*
|
|
51
|
+
* Providers fold image tokens into their reported prompt/input usage, so usage-based
|
|
52
|
+
* accounting already captures actual image cost. For heuristic paths (trailing
|
|
53
|
+
* messages without usage, transcript content-block estimates) a single conservative
|
|
54
|
+
* fixed estimate keeps both the context-window threshold check and the transcript
|
|
55
|
+
* planner consistent.
|
|
56
|
+
*/
|
|
57
|
+
export declare const ESTIMATED_IMAGE_CHARS = 4800;
|
|
58
|
+
export declare const ESTIMATED_IMAGE_TOKENS: number;
|
|
59
|
+
/**
|
|
60
|
+
* Count image content blocks in a message content array (text or block array).
|
|
61
|
+
*
|
|
62
|
+
* Exported as the canonical image-counting contract so tests can verify the
|
|
63
|
+
* heuristic independently of the transcript-based estimation used in production.
|
|
64
|
+
*/
|
|
65
|
+
export declare function countImageContentBlocks(content: string | Array<{
|
|
66
|
+
type: string;
|
|
67
|
+
}>): number;
|
|
68
|
+
/**
|
|
69
|
+
* Estimate the token cost of only the image content blocks in a message content array.
|
|
70
|
+
*
|
|
71
|
+
* Exported as the canonical image-token-estimation contract so tests can verify
|
|
72
|
+
* the heuristic independently of the transcript-based estimation used in production.
|
|
73
|
+
*/
|
|
74
|
+
export declare function estimateImageContentTokens(content: string | Array<{
|
|
75
|
+
type: string;
|
|
76
|
+
}>): number;
|
|
48
77
|
/**
|
|
49
78
|
* Estimate token count for a message using chars/4 heuristic.
|
|
50
79
|
* This is conservative (overestimates tokens).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAoB,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,eAAe,EAAE,MAAM,CAAC;IACxB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,2BAA2B,EAAE,kBAKzC,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAY3D;AAgBD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,KAAK,GAAG,SAAS,CAShF;AAED,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAUD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,oBAAoB,CA4BpF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAGjH;
|
|
1
|
+
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/compaction.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAoB,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,+EAA+E;IAC/E,eAAe,EAAE,MAAM,CAAC;IACxB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,2BAA2B,EAAE,kBAKzC,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAY3D;AAgBD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,KAAK,GAAG,SAAS,CAShF;AAED,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAUD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,oBAAoB,CA4BpF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAGjH;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAC1C,eAAO,MAAM,sBAAsB,QAAuC,CAAC;AAkB3E;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAOzF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAE5F;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAuC5D","sourcesContent":["/**\n * Neutral context-usage metrics for deciding when a session needs compaction.\n */\n\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage, Usage } from \"@earendil-works/pi-ai\";\nimport type { SessionEntry } from \"../session-manager.ts\";\n\nexport interface CompactionSettings {\n\tenabled: boolean;\n\treserveTokens: number;\n\t/** Fraction of compactable context to keep. 0.3 is aggressive, 0.7 is light. */\n\tcompression_ratio: number;\n\t/** Number of recent context-eligible messages to preserve in standard mode. */\n\tpreserve_recent: number;\n\t/** Focus query for relevance-based pruning; auto-detected when omitted in settings/options. */\n\tquery?: string;\n}\n\nexport const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tcompression_ratio: 0.5,\n\tpreserve_recent: 2,\n};\n\n/**\n * Calculate active context-window tokens from provider usage.\n *\n * Prefer normalized component fields over `totalTokens`: some providers expose\n * `totalTokens` as a billing/cumulative total, while the footer needs an active\n * context estimate. Anthropic-compatible endpoints can also mirror cached input\n * in both `input` and `cacheRead`/`cacheWrite`; when cache buckets are nearly the\n * same size as `input`, treat `input` as the full prompt instead of counting the\n * same cached prompt twice.\n */\nexport function calculateContextTokens(usage: Usage): number {\n\tconst input = Math.max(0, usage.input || 0);\n\tconst output = Math.max(0, usage.output || 0);\n\tconst cacheRead = Math.max(0, usage.cacheRead || 0);\n\tconst cacheWrite = Math.max(0, usage.cacheWrite || 0);\n\tconst cacheTokens = cacheRead + cacheWrite;\n\tconst hasComponents = input > 0 || output > 0 || cacheTokens > 0;\n\tif (!hasComponents) return Math.max(0, usage.totalTokens || 0);\n\n\tconst cacheMirrorsInput = input > 0 && cacheTokens > 0 && cacheTokens >= input * 0.9 && cacheTokens <= input * 1.1;\n\tconst promptTokens = cacheMirrorsInput ? input : input + cacheTokens;\n\treturn promptTokens + output;\n}\n\n/**\n * Get usage from an assistant message if available.\n * Skips aborted and error messages as they don't have valid usage data.\n */\nfunction getAssistantUsage(msg: AgentMessage): Usage | undefined {\n\tif (msg.role === \"assistant\" && \"usage\" in msg) {\n\t\tconst assistantMsg = msg as AssistantMessage;\n\t\tif (assistantMsg.stopReason !== \"aborted\" && assistantMsg.stopReason !== \"error\" && assistantMsg.usage) {\n\t\t\treturn assistantMsg.usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Find the last non-aborted assistant message usage from session entries.\n */\nexport function getLastAssistantUsage(entries: SessionEntry[]): Usage | undefined {\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"message\") {\n\t\t\tconst usage = getAssistantUsage(entry.message);\n\t\t\tif (usage) return usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport interface ContextUsageEstimate {\n\ttokens: number;\n\tusageTokens: number;\n\ttrailingTokens: number;\n\tlastUsageIndex: number | null;\n}\n\nfunction getLastAssistantUsageInfo(messages: AgentMessage[]): { usage: Usage; index: number } | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst usage = getAssistantUsage(messages[i]);\n\t\tif (usage) return { usage, index: i };\n\t}\n\treturn undefined;\n}\n\n/**\n * Estimate context tokens from messages, using the last assistant usage when available.\n * If there are messages after the last usage, estimate their tokens with estimateTokens.\n */\nexport function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\n\tif (!usageInfo) {\n\t\tlet estimated = 0;\n\t\tfor (const message of messages) {\n\t\t\testimated += estimateTokens(message);\n\t\t}\n\t\treturn {\n\t\t\ttokens: estimated,\n\t\t\tusageTokens: 0,\n\t\t\ttrailingTokens: estimated,\n\t\t\tlastUsageIndex: null,\n\t\t};\n\t}\n\n\tconst usageTokens = calculateContextTokens(usageInfo.usage);\n\tlet trailingTokens = 0;\n\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\ttrailingTokens += estimateTokens(messages[i]);\n\t}\n\n\treturn {\n\t\ttokens: usageTokens + trailingTokens,\n\t\tusageTokens,\n\t\ttrailingTokens,\n\t\tlastUsageIndex: usageInfo.index,\n\t};\n}\n\n/**\n * Check if compaction should trigger based on context usage.\n */\nexport function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean {\n\tif (!settings.enabled) return false;\n\treturn contextTokens > contextWindow - settings.reserveTokens;\n}\n\n/**\n * Shared image-token estimation used by every compaction/context-accounting path.\n *\n * Providers fold image tokens into their reported prompt/input usage, so usage-based\n * accounting already captures actual image cost. For heuristic paths (trailing\n * messages without usage, transcript content-block estimates) a single conservative\n * fixed estimate keeps both the context-window threshold check and the transcript\n * planner consistent.\n */\nexport const ESTIMATED_IMAGE_CHARS = 4800;\nexport const ESTIMATED_IMAGE_TOKENS = Math.ceil(ESTIMATED_IMAGE_CHARS / 4);\n\nfunction estimateTextAndImageContentChars(content: string | Array<{ type: string; text?: string }>): number {\n\tif (typeof content === \"string\") {\n\t\treturn content.length;\n\t}\n\n\tlet chars = 0;\n\tfor (const block of content) {\n\t\tif (block.type === \"text\" && block.text) {\n\t\t\tchars += block.text.length;\n\t\t} else if (block.type === \"image\") {\n\t\t\tchars += ESTIMATED_IMAGE_CHARS;\n\t\t}\n\t}\n\treturn chars;\n}\n\n/**\n * Count image content blocks in a message content array (text or block array).\n *\n * Exported as the canonical image-counting contract so tests can verify the\n * heuristic independently of the transcript-based estimation used in production.\n */\nexport function countImageContentBlocks(content: string | Array<{ type: string }>): number {\n\tif (typeof content === \"string\") return 0;\n\tlet count = 0;\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") count += 1;\n\t}\n\treturn count;\n}\n\n/**\n * Estimate the token cost of only the image content blocks in a message content array.\n *\n * Exported as the canonical image-token-estimation contract so tests can verify\n * the heuristic independently of the transcript-based estimation used in production.\n */\nexport function estimateImageContentTokens(content: string | Array<{ type: string }>): number {\n\treturn countImageContentBlocks(content) * ESTIMATED_IMAGE_TOKENS;\n}\n\n/**\n * Estimate token count for a message using chars/4 heuristic.\n * This is conservative (overestimates tokens).\n */\nexport function estimateTokens(message: AgentMessage): number {\n\tlet chars = 0;\n\n\tswitch (message.role) {\n\t\tcase \"user\": {\n\t\t\tchars = estimateTextAndImageContentChars(\n\t\t\t\t(message as { content: string | Array<{ type: string; text?: string }> }).content,\n\t\t\t);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"assistant\": {\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\tfor (const block of assistant.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tchars += block.text.length;\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tchars += block.thinking.length;\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tchars += block.name.length + JSON.stringify(block.arguments).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"custom\":\n\t\tcase \"toolResult\": {\n\t\t\tchars = estimateTextAndImageContentChars(message.content);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"bashExecution\": {\n\t\t\tchars = message.command.length + message.output.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"branchSummary\": {\n\t\t\tchars = message.summary.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t}\n\n\treturn 0;\n}\n"]}
|
|
@@ -103,7 +103,17 @@ export function shouldCompact(contextTokens, contextWindow, settings) {
|
|
|
103
103
|
return false;
|
|
104
104
|
return contextTokens > contextWindow - settings.reserveTokens;
|
|
105
105
|
}
|
|
106
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Shared image-token estimation used by every compaction/context-accounting path.
|
|
108
|
+
*
|
|
109
|
+
* Providers fold image tokens into their reported prompt/input usage, so usage-based
|
|
110
|
+
* accounting already captures actual image cost. For heuristic paths (trailing
|
|
111
|
+
* messages without usage, transcript content-block estimates) a single conservative
|
|
112
|
+
* fixed estimate keeps both the context-window threshold check and the transcript
|
|
113
|
+
* planner consistent.
|
|
114
|
+
*/
|
|
115
|
+
export const ESTIMATED_IMAGE_CHARS = 4800;
|
|
116
|
+
export const ESTIMATED_IMAGE_TOKENS = Math.ceil(ESTIMATED_IMAGE_CHARS / 4);
|
|
107
117
|
function estimateTextAndImageContentChars(content) {
|
|
108
118
|
if (typeof content === "string") {
|
|
109
119
|
return content.length;
|
|
@@ -119,6 +129,31 @@ function estimateTextAndImageContentChars(content) {
|
|
|
119
129
|
}
|
|
120
130
|
return chars;
|
|
121
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Count image content blocks in a message content array (text or block array).
|
|
134
|
+
*
|
|
135
|
+
* Exported as the canonical image-counting contract so tests can verify the
|
|
136
|
+
* heuristic independently of the transcript-based estimation used in production.
|
|
137
|
+
*/
|
|
138
|
+
export function countImageContentBlocks(content) {
|
|
139
|
+
if (typeof content === "string")
|
|
140
|
+
return 0;
|
|
141
|
+
let count = 0;
|
|
142
|
+
for (const block of content) {
|
|
143
|
+
if (block.type === "image")
|
|
144
|
+
count += 1;
|
|
145
|
+
}
|
|
146
|
+
return count;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Estimate the token cost of only the image content blocks in a message content array.
|
|
150
|
+
*
|
|
151
|
+
* Exported as the canonical image-token-estimation contract so tests can verify
|
|
152
|
+
* the heuristic independently of the transcript-based estimation used in production.
|
|
153
|
+
*/
|
|
154
|
+
export function estimateImageContentTokens(content) {
|
|
155
|
+
return countImageContentBlocks(content) * ESTIMATED_IMAGE_TOKENS;
|
|
156
|
+
}
|
|
122
157
|
/**
|
|
123
158
|
* Estimate token count for a message using chars/4 heuristic.
|
|
124
159
|
* This is conservative (overestimates tokens).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Neutral context-usage metrics for deciding when a session needs compaction.\n */\n\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage, Usage } from \"@earendil-works/pi-ai\";\nimport type { SessionEntry } from \"../session-manager.ts\";\n\nexport interface CompactionSettings {\n\tenabled: boolean;\n\treserveTokens: number;\n\t/** Fraction of compactable context to keep. 0.3 is aggressive, 0.7 is light. */\n\tcompression_ratio: number;\n\t/** Number of recent context-eligible messages to preserve in standard mode. */\n\tpreserve_recent: number;\n\t/** Focus query for relevance-based pruning; auto-detected when omitted in settings/options. */\n\tquery?: string;\n}\n\nexport const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tcompression_ratio: 0.5,\n\tpreserve_recent: 2,\n};\n\n/**\n * Calculate active context-window tokens from provider usage.\n *\n * Prefer normalized component fields over `totalTokens`: some providers expose\n * `totalTokens` as a billing/cumulative total, while the footer needs an active\n * context estimate. Anthropic-compatible endpoints can also mirror cached input\n * in both `input` and `cacheRead`/`cacheWrite`; when cache buckets are nearly the\n * same size as `input`, treat `input` as the full prompt instead of counting the\n * same cached prompt twice.\n */\nexport function calculateContextTokens(usage: Usage): number {\n\tconst input = Math.max(0, usage.input || 0);\n\tconst output = Math.max(0, usage.output || 0);\n\tconst cacheRead = Math.max(0, usage.cacheRead || 0);\n\tconst cacheWrite = Math.max(0, usage.cacheWrite || 0);\n\tconst cacheTokens = cacheRead + cacheWrite;\n\tconst hasComponents = input > 0 || output > 0 || cacheTokens > 0;\n\tif (!hasComponents) return Math.max(0, usage.totalTokens || 0);\n\n\tconst cacheMirrorsInput = input > 0 && cacheTokens > 0 && cacheTokens >= input * 0.9 && cacheTokens <= input * 1.1;\n\tconst promptTokens = cacheMirrorsInput ? input : input + cacheTokens;\n\treturn promptTokens + output;\n}\n\n/**\n * Get usage from an assistant message if available.\n * Skips aborted and error messages as they don't have valid usage data.\n */\nfunction getAssistantUsage(msg: AgentMessage): Usage | undefined {\n\tif (msg.role === \"assistant\" && \"usage\" in msg) {\n\t\tconst assistantMsg = msg as AssistantMessage;\n\t\tif (assistantMsg.stopReason !== \"aborted\" && assistantMsg.stopReason !== \"error\" && assistantMsg.usage) {\n\t\t\treturn assistantMsg.usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Find the last non-aborted assistant message usage from session entries.\n */\nexport function getLastAssistantUsage(entries: SessionEntry[]): Usage | undefined {\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"message\") {\n\t\t\tconst usage = getAssistantUsage(entry.message);\n\t\t\tif (usage) return usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport interface ContextUsageEstimate {\n\ttokens: number;\n\tusageTokens: number;\n\ttrailingTokens: number;\n\tlastUsageIndex: number | null;\n}\n\nfunction getLastAssistantUsageInfo(messages: AgentMessage[]): { usage: Usage; index: number } | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst usage = getAssistantUsage(messages[i]);\n\t\tif (usage) return { usage, index: i };\n\t}\n\treturn undefined;\n}\n\n/**\n * Estimate context tokens from messages, using the last assistant usage when available.\n * If there are messages after the last usage, estimate their tokens with estimateTokens.\n */\nexport function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\n\tif (!usageInfo) {\n\t\tlet estimated = 0;\n\t\tfor (const message of messages) {\n\t\t\testimated += estimateTokens(message);\n\t\t}\n\t\treturn {\n\t\t\ttokens: estimated,\n\t\t\tusageTokens: 0,\n\t\t\ttrailingTokens: estimated,\n\t\t\tlastUsageIndex: null,\n\t\t};\n\t}\n\n\tconst usageTokens = calculateContextTokens(usageInfo.usage);\n\tlet trailingTokens = 0;\n\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\ttrailingTokens += estimateTokens(messages[i]);\n\t}\n\n\treturn {\n\t\ttokens: usageTokens + trailingTokens,\n\t\tusageTokens,\n\t\ttrailingTokens,\n\t\tlastUsageIndex: usageInfo.index,\n\t};\n}\n\n/**\n * Check if compaction should trigger based on context usage.\n */\nexport function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean {\n\tif (!settings.enabled) return false;\n\treturn contextTokens > contextWindow - settings.reserveTokens;\n}\n\nconst ESTIMATED_IMAGE_CHARS = 4800;\n\nfunction estimateTextAndImageContentChars(content: string | Array<{ type: string; text?: string }>): number {\n\tif (typeof content === \"string\") {\n\t\treturn content.length;\n\t}\n\n\tlet chars = 0;\n\tfor (const block of content) {\n\t\tif (block.type === \"text\" && block.text) {\n\t\t\tchars += block.text.length;\n\t\t} else if (block.type === \"image\") {\n\t\t\tchars += ESTIMATED_IMAGE_CHARS;\n\t\t}\n\t}\n\treturn chars;\n}\n\n/**\n * Estimate token count for a message using chars/4 heuristic.\n * This is conservative (overestimates tokens).\n */\nexport function estimateTokens(message: AgentMessage): number {\n\tlet chars = 0;\n\n\tswitch (message.role) {\n\t\tcase \"user\": {\n\t\t\tchars = estimateTextAndImageContentChars(\n\t\t\t\t(message as { content: string | Array<{ type: string; text?: string }> }).content,\n\t\t\t);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"assistant\": {\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\tfor (const block of assistant.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tchars += block.text.length;\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tchars += block.thinking.length;\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tchars += block.name.length + JSON.stringify(block.arguments).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"custom\":\n\t\tcase \"toolResult\": {\n\t\t\tchars = estimateTextAndImageContentChars(message.content);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"bashExecution\": {\n\t\t\tchars = message.command.length + message.output.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"branchSummary\": {\n\t\t\tchars = message.summary.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t}\n\n\treturn 0;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../../src/core/compaction/compaction.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Neutral context-usage metrics for deciding when a session needs compaction.\n */\n\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage, Usage } from \"@earendil-works/pi-ai\";\nimport type { SessionEntry } from \"../session-manager.ts\";\n\nexport interface CompactionSettings {\n\tenabled: boolean;\n\treserveTokens: number;\n\t/** Fraction of compactable context to keep. 0.3 is aggressive, 0.7 is light. */\n\tcompression_ratio: number;\n\t/** Number of recent context-eligible messages to preserve in standard mode. */\n\tpreserve_recent: number;\n\t/** Focus query for relevance-based pruning; auto-detected when omitted in settings/options. */\n\tquery?: string;\n}\n\nexport const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tcompression_ratio: 0.5,\n\tpreserve_recent: 2,\n};\n\n/**\n * Calculate active context-window tokens from provider usage.\n *\n * Prefer normalized component fields over `totalTokens`: some providers expose\n * `totalTokens` as a billing/cumulative total, while the footer needs an active\n * context estimate. Anthropic-compatible endpoints can also mirror cached input\n * in both `input` and `cacheRead`/`cacheWrite`; when cache buckets are nearly the\n * same size as `input`, treat `input` as the full prompt instead of counting the\n * same cached prompt twice.\n */\nexport function calculateContextTokens(usage: Usage): number {\n\tconst input = Math.max(0, usage.input || 0);\n\tconst output = Math.max(0, usage.output || 0);\n\tconst cacheRead = Math.max(0, usage.cacheRead || 0);\n\tconst cacheWrite = Math.max(0, usage.cacheWrite || 0);\n\tconst cacheTokens = cacheRead + cacheWrite;\n\tconst hasComponents = input > 0 || output > 0 || cacheTokens > 0;\n\tif (!hasComponents) return Math.max(0, usage.totalTokens || 0);\n\n\tconst cacheMirrorsInput = input > 0 && cacheTokens > 0 && cacheTokens >= input * 0.9 && cacheTokens <= input * 1.1;\n\tconst promptTokens = cacheMirrorsInput ? input : input + cacheTokens;\n\treturn promptTokens + output;\n}\n\n/**\n * Get usage from an assistant message if available.\n * Skips aborted and error messages as they don't have valid usage data.\n */\nfunction getAssistantUsage(msg: AgentMessage): Usage | undefined {\n\tif (msg.role === \"assistant\" && \"usage\" in msg) {\n\t\tconst assistantMsg = msg as AssistantMessage;\n\t\tif (assistantMsg.stopReason !== \"aborted\" && assistantMsg.stopReason !== \"error\" && assistantMsg.usage) {\n\t\t\treturn assistantMsg.usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Find the last non-aborted assistant message usage from session entries.\n */\nexport function getLastAssistantUsage(entries: SessionEntry[]): Usage | undefined {\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"message\") {\n\t\t\tconst usage = getAssistantUsage(entry.message);\n\t\t\tif (usage) return usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nexport interface ContextUsageEstimate {\n\ttokens: number;\n\tusageTokens: number;\n\ttrailingTokens: number;\n\tlastUsageIndex: number | null;\n}\n\nfunction getLastAssistantUsageInfo(messages: AgentMessage[]): { usage: Usage; index: number } | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst usage = getAssistantUsage(messages[i]);\n\t\tif (usage) return { usage, index: i };\n\t}\n\treturn undefined;\n}\n\n/**\n * Estimate context tokens from messages, using the last assistant usage when available.\n * If there are messages after the last usage, estimate their tokens with estimateTokens.\n */\nexport function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\n\tif (!usageInfo) {\n\t\tlet estimated = 0;\n\t\tfor (const message of messages) {\n\t\t\testimated += estimateTokens(message);\n\t\t}\n\t\treturn {\n\t\t\ttokens: estimated,\n\t\t\tusageTokens: 0,\n\t\t\ttrailingTokens: estimated,\n\t\t\tlastUsageIndex: null,\n\t\t};\n\t}\n\n\tconst usageTokens = calculateContextTokens(usageInfo.usage);\n\tlet trailingTokens = 0;\n\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\ttrailingTokens += estimateTokens(messages[i]);\n\t}\n\n\treturn {\n\t\ttokens: usageTokens + trailingTokens,\n\t\tusageTokens,\n\t\ttrailingTokens,\n\t\tlastUsageIndex: usageInfo.index,\n\t};\n}\n\n/**\n * Check if compaction should trigger based on context usage.\n */\nexport function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean {\n\tif (!settings.enabled) return false;\n\treturn contextTokens > contextWindow - settings.reserveTokens;\n}\n\n/**\n * Shared image-token estimation used by every compaction/context-accounting path.\n *\n * Providers fold image tokens into their reported prompt/input usage, so usage-based\n * accounting already captures actual image cost. For heuristic paths (trailing\n * messages without usage, transcript content-block estimates) a single conservative\n * fixed estimate keeps both the context-window threshold check and the transcript\n * planner consistent.\n */\nexport const ESTIMATED_IMAGE_CHARS = 4800;\nexport const ESTIMATED_IMAGE_TOKENS = Math.ceil(ESTIMATED_IMAGE_CHARS / 4);\n\nfunction estimateTextAndImageContentChars(content: string | Array<{ type: string; text?: string }>): number {\n\tif (typeof content === \"string\") {\n\t\treturn content.length;\n\t}\n\n\tlet chars = 0;\n\tfor (const block of content) {\n\t\tif (block.type === \"text\" && block.text) {\n\t\t\tchars += block.text.length;\n\t\t} else if (block.type === \"image\") {\n\t\t\tchars += ESTIMATED_IMAGE_CHARS;\n\t\t}\n\t}\n\treturn chars;\n}\n\n/**\n * Count image content blocks in a message content array (text or block array).\n *\n * Exported as the canonical image-counting contract so tests can verify the\n * heuristic independently of the transcript-based estimation used in production.\n */\nexport function countImageContentBlocks(content: string | Array<{ type: string }>): number {\n\tif (typeof content === \"string\") return 0;\n\tlet count = 0;\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") count += 1;\n\t}\n\treturn count;\n}\n\n/**\n * Estimate the token cost of only the image content blocks in a message content array.\n *\n * Exported as the canonical image-token-estimation contract so tests can verify\n * the heuristic independently of the transcript-based estimation used in production.\n */\nexport function estimateImageContentTokens(content: string | Array<{ type: string }>): number {\n\treturn countImageContentBlocks(content) * ESTIMATED_IMAGE_TOKENS;\n}\n\n/**\n * Estimate token count for a message using chars/4 heuristic.\n * This is conservative (overestimates tokens).\n */\nexport function estimateTokens(message: AgentMessage): number {\n\tlet chars = 0;\n\n\tswitch (message.role) {\n\t\tcase \"user\": {\n\t\t\tchars = estimateTextAndImageContentChars(\n\t\t\t\t(message as { content: string | Array<{ type: string; text?: string }> }).content,\n\t\t\t);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"assistant\": {\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\tfor (const block of assistant.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tchars += block.text.length;\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tchars += block.thinking.length;\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tchars += block.name.length + JSON.stringify(block.arguments).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"custom\":\n\t\tcase \"toolResult\": {\n\t\t\tchars = estimateTextAndImageContentChars(message.content);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"bashExecution\": {\n\t\t\tchars = message.command.length + message.output.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"branchSummary\": {\n\t\t\tchars = message.summary.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t}\n\n\treturn 0;\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
2
|
-
import type { ContextCompactionStats } from "../session-manager.ts";
|
|
2
|
+
import type { ContextCompactionStats, ContextDeletionTarget } from "../session-manager.ts";
|
|
3
|
+
import type { CompactableTranscript } from "./context-compaction-types.ts";
|
|
3
4
|
import type { ContextCompactionBudgetToolDetails } from "./context-deletion-tool-definitions.ts";
|
|
4
5
|
import type { ContextCompactionParameters, ValidatedContextDeletionResult } from "./context-compaction-types.ts";
|
|
5
6
|
export declare function formatErrorMessage(error: unknown): string;
|
|
@@ -9,8 +10,19 @@ export declare function percentOf(part: number, total: number): number;
|
|
|
9
10
|
export declare function finitePositiveNumber(value: number | undefined): number | undefined;
|
|
10
11
|
export declare function contextCompactionTargetReductionPercent(parameters: ContextCompactionParameters): number;
|
|
11
12
|
export declare function contextCompactionTargetLabel(parameters: ContextCompactionParameters): string;
|
|
12
|
-
export declare function createContextCompactionBudgetDetails(stats: ContextCompactionStats, callCount: number, contextWindow: number | undefined, parameters: ContextCompactionParameters): ContextCompactionBudgetToolDetails;
|
|
13
|
+
export declare function createContextCompactionBudgetDetails(stats: ContextCompactionStats, callCount: number, contextWindow: number | undefined, parameters: ContextCompactionParameters, remainingImageTokens: number, imageBlockCount: number): ContextCompactionBudgetToolDetails;
|
|
13
14
|
export declare function contextCompactionTargetMet(result: ValidatedContextDeletionResult | undefined, parameters: ContextCompactionParameters): result is ValidatedContextDeletionResult;
|
|
14
15
|
export declare function contextCompactionProgressKey(result: ValidatedContextDeletionResult | undefined): string;
|
|
15
16
|
export declare function contextCompactionProgressPercent(result: ValidatedContextDeletionResult | undefined): number;
|
|
17
|
+
/**
|
|
18
|
+
* Sum the token estimates of image content blocks that remain after applying the
|
|
19
|
+
* current deletion targets. Deleted entries and individually-deleted image blocks
|
|
20
|
+
* are excluded so the budget tool always reflects the live working set.
|
|
21
|
+
*/
|
|
22
|
+
export declare function sumRemainingImageTokens(transcript: CompactableTranscript, targets: readonly ContextDeletionTarget[]): number;
|
|
23
|
+
/**
|
|
24
|
+
* Count the image content blocks that remain after applying the current deletion
|
|
25
|
+
* targets. Deleted entries and individually-deleted image blocks are excluded.
|
|
26
|
+
*/
|
|
27
|
+
export declare function countRemainingImageBlocks(transcript: CompactableTranscript, targets: readonly ContextDeletionTarget[]): number;
|
|
16
28
|
//# sourceMappingURL=context-compaction-metrics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-compaction-metrics.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-compaction-metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"context-compaction-metrics.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/context-compaction-metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,wCAAwC,CAAC;AACjG,OAAO,KAAK,EAAE,2BAA2B,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAGjH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEzD;AAED,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAEpH;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAElF;AAED,wBAAgB,uCAAuC,CAAC,UAAU,EAAE,2BAA2B,GAAG,MAAM,CAEvG;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,2BAA2B,GAAG,MAAM,CAE5F;AAED,wBAAgB,oCAAoC,CACnD,KAAK,EAAE,sBAAsB,EAC7B,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,UAAU,EAAE,2BAA2B,EACvC,oBAAoB,EAAE,MAAM,EAC5B,eAAe,EAAE,MAAM,GACrB,kCAAkC,CAyBpC;AAED,wBAAgB,0BAA0B,CACzC,MAAM,EAAE,8BAA8B,GAAG,SAAS,EAClD,UAAU,EAAE,2BAA2B,GACrC,MAAM,IAAI,8BAA8B,CAM1C;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,8BAA8B,GAAG,SAAS,GAAG,MAAM,CAGvG;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,8BAA8B,GAAG,SAAS,GAAG,MAAM,CAE3G;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACtC,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,SAAS,qBAAqB,EAAE,GACvC,MAAM,CAcR;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACxC,UAAU,EAAE,qBAAqB,EACjC,OAAO,EAAE,SAAS,qBAAqB,EAAE,GACvC,MAAM,CAcR","sourcesContent":["import type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { ContextCompactionStats, ContextDeletionTarget } from \"../session-manager.ts\";\nimport type { CompactableTranscript } from \"./context-compaction-types.ts\";\nimport type { ContextCompactionBudgetToolDetails } from \"./context-deletion-tool-definitions.ts\";\nimport type { ContextCompactionParameters, ValidatedContextDeletionResult } from \"./context-compaction-types.ts\";\nimport { getDeletedContentBlocks, getDeletedEntryIds } from \"./context-deletion-targets.ts\";\n\nexport function formatErrorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nexport function createContextDeletionToolResult<TDetails>(text: string, details: TDetails): AgentToolResult<TDetails> {\n\treturn { content: [{ type: \"text\", text }], details, terminate: false };\n}\n\nexport function roundPercent(value: number): number {\n\treturn Math.round(value * 10) / 10;\n}\n\nexport function percentOf(part: number, total: number): number {\n\treturn total > 0 ? roundPercent((part / total) * 100) : 0;\n}\n\nexport function finitePositiveNumber(value: number | undefined): number | undefined {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : undefined;\n}\n\nexport function contextCompactionTargetReductionPercent(parameters: ContextCompactionParameters): number {\n\treturn roundPercent((1 - parameters.compression_ratio) * 100);\n}\n\nexport function contextCompactionTargetLabel(parameters: ContextCompactionParameters): string {\n\treturn `${contextCompactionTargetReductionPercent(parameters)}%`;\n}\n\nexport function createContextCompactionBudgetDetails(\n\tstats: ContextCompactionStats,\n\tcallCount: number,\n\tcontextWindow: number | undefined,\n\tparameters: ContextCompactionParameters,\n\tremainingImageTokens: number,\n\timageBlockCount: number,\n): ContextCompactionBudgetToolDetails {\n\tconst targetTokensAfter = Math.max(0, Math.floor(stats.tokensBefore * parameters.compression_ratio));\n\tconst targetReductionPercent = contextCompactionTargetReductionPercent(parameters);\n\tconst details: ContextCompactionBudgetToolDetails = {\n\t\t...(contextWindow !== undefined ? { contextWindow } : {}),\n\t\tcompression_ratio: parameters.compression_ratio,\n\t\ttokensBefore: stats.tokensBefore,\n\t\tcurrentTokensAfter: stats.tokensAfter,\n\t\tdeletedTokens: Math.max(0, stats.tokensBefore - stats.tokensAfter),\n\t\tcurrentReductionPercent: stats.percentReduction,\n\t\ttargetReductionPercent,\n\t\ttargetTokensAfter,\n\t\ttokensToDeleteForTarget: Math.max(0, stats.tokensAfter - targetTokensAfter),\n\t\t...(contextWindow !== undefined\n\t\t\t? {\n\t\t\t\t\tcontextWindowBeforePercent: percentOf(stats.tokensBefore, contextWindow),\n\t\t\t\t\tcontextWindowAfterPercent: percentOf(stats.tokensAfter, contextWindow),\n\t\t\t\t}\n\t\t\t: {}),\n\t\tremainingImageTokens,\n\t\timageBlockCount,\n\t\timageTokenPercent: percentOf(remainingImageTokens, stats.tokensAfter),\n\t\tcallCount,\n\t};\n\treturn details;\n}\n\nexport function contextCompactionTargetMet(\n\tresult: ValidatedContextDeletionResult | undefined,\n\tparameters: ContextCompactionParameters,\n): result is ValidatedContextDeletionResult {\n\treturn (\n\t\tresult !== undefined &&\n\t\tresult.deletedTargets.length > 0 &&\n\t\tresult.stats.percentReduction >= contextCompactionTargetReductionPercent(parameters)\n\t);\n}\n\nexport function contextCompactionProgressKey(result: ValidatedContextDeletionResult | undefined): string {\n\tif (!result) return \"none:0\";\n\treturn `${result.deletedTargets.length}:${result.stats.percentReduction}:${result.stats.tokensAfter}`;\n}\n\nexport function contextCompactionProgressPercent(result: ValidatedContextDeletionResult | undefined): number {\n\treturn result?.stats.percentReduction ?? 0;\n}\n\n/**\n * Sum the token estimates of image content blocks that remain after applying the\n * current deletion targets. Deleted entries and individually-deleted image blocks\n * are excluded so the budget tool always reflects the live working set.\n */\nexport function sumRemainingImageTokens(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): number {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tconst deletedContentBlocks = getDeletedContentBlocks(targets);\n\tlet imageTokens = 0;\n\tfor (const entry of transcript.entries) {\n\t\tif (deletedEntryIds.has(entry.entryId)) continue;\n\t\tconst deletedBlocks = deletedContentBlocks.get(entry.entryId);\n\t\tfor (const block of entry.contentBlocks) {\n\t\t\tif (block.type !== \"image\") continue;\n\t\t\tif (deletedBlocks?.has(block.blockIndex)) continue;\n\t\t\timageTokens += block.tokenEstimate;\n\t\t}\n\t}\n\treturn imageTokens;\n}\n\n/**\n * Count the image content blocks that remain after applying the current deletion\n * targets. Deleted entries and individually-deleted image blocks are excluded.\n */\nexport function countRemainingImageBlocks(\n\ttranscript: CompactableTranscript,\n\ttargets: readonly ContextDeletionTarget[],\n): number {\n\tconst deletedEntryIds = getDeletedEntryIds(targets);\n\tconst deletedContentBlocks = getDeletedContentBlocks(targets);\n\tlet count = 0;\n\tfor (const entry of transcript.entries) {\n\t\tif (deletedEntryIds.has(entry.entryId)) continue;\n\t\tconst deletedBlocks = deletedContentBlocks.get(entry.entryId);\n\t\tfor (const block of entry.contentBlocks) {\n\t\t\tif (block.type !== \"image\") continue;\n\t\t\tif (deletedBlocks?.has(block.blockIndex)) continue;\n\t\t\tcount += 1;\n\t\t}\n\t}\n\treturn count;\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getDeletedContentBlocks, getDeletedEntryIds } from "./context-deletion-targets.js";
|
|
1
2
|
export function formatErrorMessage(error) {
|
|
2
3
|
return error instanceof Error ? error.message : String(error);
|
|
3
4
|
}
|
|
@@ -19,7 +20,7 @@ export function contextCompactionTargetReductionPercent(parameters) {
|
|
|
19
20
|
export function contextCompactionTargetLabel(parameters) {
|
|
20
21
|
return `${contextCompactionTargetReductionPercent(parameters)}%`;
|
|
21
22
|
}
|
|
22
|
-
export function createContextCompactionBudgetDetails(stats, callCount, contextWindow, parameters) {
|
|
23
|
+
export function createContextCompactionBudgetDetails(stats, callCount, contextWindow, parameters, remainingImageTokens, imageBlockCount) {
|
|
23
24
|
const targetTokensAfter = Math.max(0, Math.floor(stats.tokensBefore * parameters.compression_ratio));
|
|
24
25
|
const targetReductionPercent = contextCompactionTargetReductionPercent(parameters);
|
|
25
26
|
const details = {
|
|
@@ -38,6 +39,9 @@ export function createContextCompactionBudgetDetails(stats, callCount, contextWi
|
|
|
38
39
|
contextWindowAfterPercent: percentOf(stats.tokensAfter, contextWindow),
|
|
39
40
|
}
|
|
40
41
|
: {}),
|
|
42
|
+
remainingImageTokens,
|
|
43
|
+
imageBlockCount,
|
|
44
|
+
imageTokenPercent: percentOf(remainingImageTokens, stats.tokensAfter),
|
|
41
45
|
callCount,
|
|
42
46
|
};
|
|
43
47
|
return details;
|
|
@@ -55,4 +59,49 @@ export function contextCompactionProgressKey(result) {
|
|
|
55
59
|
export function contextCompactionProgressPercent(result) {
|
|
56
60
|
return result?.stats.percentReduction ?? 0;
|
|
57
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Sum the token estimates of image content blocks that remain after applying the
|
|
64
|
+
* current deletion targets. Deleted entries and individually-deleted image blocks
|
|
65
|
+
* are excluded so the budget tool always reflects the live working set.
|
|
66
|
+
*/
|
|
67
|
+
export function sumRemainingImageTokens(transcript, targets) {
|
|
68
|
+
const deletedEntryIds = getDeletedEntryIds(targets);
|
|
69
|
+
const deletedContentBlocks = getDeletedContentBlocks(targets);
|
|
70
|
+
let imageTokens = 0;
|
|
71
|
+
for (const entry of transcript.entries) {
|
|
72
|
+
if (deletedEntryIds.has(entry.entryId))
|
|
73
|
+
continue;
|
|
74
|
+
const deletedBlocks = deletedContentBlocks.get(entry.entryId);
|
|
75
|
+
for (const block of entry.contentBlocks) {
|
|
76
|
+
if (block.type !== "image")
|
|
77
|
+
continue;
|
|
78
|
+
if (deletedBlocks?.has(block.blockIndex))
|
|
79
|
+
continue;
|
|
80
|
+
imageTokens += block.tokenEstimate;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return imageTokens;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Count the image content blocks that remain after applying the current deletion
|
|
87
|
+
* targets. Deleted entries and individually-deleted image blocks are excluded.
|
|
88
|
+
*/
|
|
89
|
+
export function countRemainingImageBlocks(transcript, targets) {
|
|
90
|
+
const deletedEntryIds = getDeletedEntryIds(targets);
|
|
91
|
+
const deletedContentBlocks = getDeletedContentBlocks(targets);
|
|
92
|
+
let count = 0;
|
|
93
|
+
for (const entry of transcript.entries) {
|
|
94
|
+
if (deletedEntryIds.has(entry.entryId))
|
|
95
|
+
continue;
|
|
96
|
+
const deletedBlocks = deletedContentBlocks.get(entry.entryId);
|
|
97
|
+
for (const block of entry.contentBlocks) {
|
|
98
|
+
if (block.type !== "image")
|
|
99
|
+
continue;
|
|
100
|
+
if (deletedBlocks?.has(block.blockIndex))
|
|
101
|
+
continue;
|
|
102
|
+
count += 1;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return count;
|
|
106
|
+
}
|
|
58
107
|
//# sourceMappingURL=context-compaction-metrics.js.map
|