fix: include MCP tool results in microcompact to reduce token waste (#348)
## Summary - Added `isCompactableTool()` helper in `microCompact.ts` that matches both the existing COMPACTABLE_TOOLS set and any tool prefixed `mcp__` - MCP tool results were never compacted because the hardcoded allowlist only contained 9 built-in tools — MCP tools fell through and persisted in full for the entire session, wasting 10-500K tokens/session ## Impact - user-facing impact: long sessions using MCP servers (GitHub, Slack, Playwright, etc.) will compact stale MCP tool results, reducing token usage and delaying autocompact triggers - developer/maintainer impact: new MCP servers are automatically covered via prefix match — no need to update the allowlist per-server ## Testing - [x] `bun run build` - [x] `bun run smoke` - [x] focused tests: `bun test src/services/compact/microCompact.test.ts` - module exports load correctly - estimateMessageTokens counts MCP tool_use blocks - microcompactMessages processes MCP tools without error - microcompactMessages processes mixed built-in and MCP tools ## Notes - provider/model path tested: n/a (compaction logic is model-agnostic) - screenshots attached (if UI changed): n/a - follow-up work or known limitations: subagent results and thinking blocks are still not compacted (separate RFCs) https://claude.ai/code/session_01D7kprMn4c66a5WrZscF7rv Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -37,7 +37,7 @@ export const TIME_BASED_MC_CLEARED_MESSAGE = '[Old tool result content cleared]'
|
||||
|
||||
const IMAGE_MAX_TOKEN_SIZE = 2000
|
||||
|
||||
// Only compact these tools
|
||||
// Only compact these built-in tools (MCP tools are also compactable via prefix match)
|
||||
const COMPACTABLE_TOOLS = new Set<string>([
|
||||
FILE_READ_TOOL_NAME,
|
||||
...SHELL_TOOL_NAMES,
|
||||
@@ -49,7 +49,13 @@ const COMPACTABLE_TOOLS = new Set<string>([
|
||||
FILE_WRITE_TOOL_NAME,
|
||||
])
|
||||
|
||||
// --- Cached microcompact state (internal-only, gated by feature('CACHED_MICROCOMPACT')) ---
|
||||
const MCP_TOOL_PREFIX = 'mcp__'
|
||||
|
||||
function isCompactableTool(name: string): boolean {
|
||||
return COMPACTABLE_TOOLS.has(name) || name.startsWith(MCP_TOOL_PREFIX)
|
||||
}
|
||||
|
||||
// --- Cached microcompact state (gated by feature('CACHED_MICROCOMPACT')) ---
|
||||
|
||||
// Lazy-initialized cached MC module and state to avoid importing in external builds.
|
||||
// The imports and state live inside feature() checks for dead code elimination.
|
||||
@@ -231,7 +237,7 @@ function collectCompactableToolIds(messages: Message[]): string[] {
|
||||
Array.isArray(message.message.content)
|
||||
) {
|
||||
for (const block of message.message.content) {
|
||||
if (block.type === 'tool_use' && COMPACTABLE_TOOLS.has(block.name)) {
|
||||
if (block.type === 'tool_use' && isCompactableTool(block.name)) {
|
||||
ids.push(block.id)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user