Skip to content

feat: rule-based tool input compaction for auto-capture (~10x storage reduction)#2874

Open
lg320531124 wants to merge 3 commits into
volcengine:mainfrom
lg320531124:feat/tool-input-compaction
Open

feat: rule-based tool input compaction for auto-capture (~10x storage reduction)#2874
lg320531124 wants to merge 3 commits into
volcengine:mainfrom
lg320531124:feat/tool-input-compaction

Conversation

@lg320531124

@lg320531124 lg320531124 commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Add rule-based tool input compaction to the Claude Code auto-capture pipeline. compactToolInput() reduces Write/Edit/Bash/TaskCreate/TaskUpdate tool inputs to structural summaries instead of full file contents.

Problem

Sampling 16 CC sessions shows 79% of session storage volume is full code content from Write (avg 11,575 chars) and Edit (avg 2,525 chars) tool inputs. This causes:

  1. Storage bloat — sessions are ~100KB when ~20KB would suffice
  2. Vector signal dilutionbge-large-zh-v1.5 embeddings are dominated by code tokens instead of semantic content
  3. VLM extraction failure — 1081 sessions with 0 memories extracted, likely because content is too large for the VLM ReAct loop to process effectively

Solution

No LLM involved — purely rule-based compaction:

Tool Before After Ratio
Write Full file content (~7KB) file_path + "100 lines, 7200 chars" + 200-char preview (~280 chars) ~25x
Edit old_string + new_string (~5KB) file_path + length summary + 150-char previews (~400 chars) ~12x
Bash command + description command only ~1.5x
TaskCreate/Update All fields subject + status + taskId ~3x
Read/Glob/Grep/LSP Full preservation Unchanged 1x

Measured: 10.6x compression on realistic mixed session data.

Changes

  • auto-capture.mjs: Add compactToolInput() with per-tool-type policies (TOOL_INPUT_POLICIES); modify harvestContent() to use compaction when enabled
  • config.mjs: Add toolInputCompaction (default: true) and toolInputMaxChars (default: 2000) config options with env var overrides
  • __tests__/auto-capture-compaction.test.mjs: 21 regression tests covering all tool types, truncation, edge cases, and compression ratio

Configuration

Env Var Default Description
OPENVIKING_TOOL_INPUT_COMPACTION true Enable/disable compaction
OPENVIKING_TOOL_INPUT_MAX_CHARS 2000 Global truncation cap (0 = disabled)

Set OPENVIKING_TOOL_INPUT_COMPACTION=false to restore the old verbatim behavior.

Test Plan

  • 21 regression tests pass
  • 10.6x compression ratio on realistic mixed tool call data
  • JSON round-trip validation for all summary-mode tools
  • Edge cases: empty content, empty old_string, maxChars=0, string input pass-through
  • Manual verification: run a CC session with compaction enabled, check messages.jsonl size reduction
  • VLM extraction comparison: same session before/after compaction, compare memory extraction success

Closes #2875

@itxaiohanglover

Copy link
Copy Markdown

Nice implementation! Rule-based tool input compaction without LLM involvement is a smart approach — reduces cost and latency for auto-capture. The inline test functions avoid coupling to the full module. Tool input policies (full vs summary) are well-designed.

Add compactToolInput() to reduce Write/Edit/Bash/TaskCreate/TaskUpdate
tool inputs to structural summaries (file path + line count + preview)
instead of full file contents. This reduces session storage ~5x-10x,
improves vector signal-to-noise ratio for VikingDB embeddings, and
makes VLM memory extraction more likely to succeed.

Changes:
- auto-capture.mjs: add compactToolInput() with per-tool-type policies
  (full preservation for Read/Glob/Grep/LSP/WebFetch/WebSearch/Skill;
   summary mode for Write/Edit/Bash/TaskCreate/TaskUpdate)
- auto-capture.mjs: harvestContent() now uses compactToolInput when
  toolInputCompaction is enabled (default)
- config.mjs: add toolInputCompaction (default true) and
  toolInputMaxChars (default 2000) config options
- __tests__/auto-capture-compaction.test.mjs: 21 regression tests
  covering all tool types, truncation, edge cases, and compression ratio

Backward compatible: OPENVIKING_TOOL_INPUT_COMPACTION=false restores
the old verbatim behavior.
@lg320531124

Copy link
Copy Markdown
Contributor Author

The 06. API & CLI Integration Tests job fails here too with the identical tally — 3 failed, 25 passed, 7 skipped, 11 errors, all CONFLICT: Resource is busy on the session-scoped cli_test_4f5946d2 fixture.

I posted the full diagnosis on sibling PR #2900 (rebased onto latest main, head b00e336, same failure → rules out base-skew; two PRs touching disjoint code producing byte-identical failure counts = shared infra flake, not a code defect in either branch). Root cause points at the TreeLock-release path in openviking/utils/resource_processor.py:441retryable=True but the 15×@10s retry never recovers within the session fixture's lifetime.

This PR (feat/tool-input-compaction) touches tool-input compaction, not add-resource/locks/conftest, so the failing setup step is never reached by my code.

I don't have admin rights to rerun from a fork — could someone with access rerun the 06. API & CLI Integration Tests job on this branch? If it passes on retry that confirms the flake. (No code changes from my side — happy to act if it points back at the branch.)

@lg320531124

Copy link
Copy Markdown
Contributor Author

Opened #2916 to track the Resource is busy TreeLock flake at the root-cause level (CI-infra, not this PR). This PR and #2900 hit the identical tally on the same run despite touching disjoint modules — evidence chain and the rerun ask are in the issue.

buildParts() (structured tool parts sent to OV as tool_input) bypassed
compactToolInput, sending raw block.input objects while the prose
extractAllTurns path already compacted Write/Edit/Bash/Task* to
structural summaries. The ~10x storage reduction from volcengine#2874 only
covered the inlined-text path; structured parts carried full Write
content verbatim.

Mirror the prose path: apply compactToolInput when
cfg.toolInputCompaction !== false, fall back to formatToolInput
otherwise. Non-summary tools (Read/Glob/Grep) keep full input.
tool_input now a string (consistent with tool_output).

Adds 6 buildParts regression tests asserting parity with the prose
path for Write/Edit/Bash/Read, compaction=off fallback, and
non-object input handling.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

feat: rule-based tool input compaction for auto-capture pipeline

2 participants