[PR #7049] fix: clear tool output and attachments when pruning to prevent memory leak #12225

Open
opened 2026-02-16 18:17:09 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/7049

State: open
Merged: No


Fixes #3013

Summary

Clear tool output and attachments when compaction prunes old tool results, actually freeing memory instead of just flagging.

Evidence

In a real session working on this repo:

Metric Value
OpenCode process RAM 16.4 GB
Tool parts on disk 34,887 files
Session duration ~3 hours

Sample tool output sizes from this session:

  • webfetch of docs page: 10 KB
  • read of source file: 5-50 KB
  • git diff / gh pr diff: 10-100 KB
  • bash command outputs: 1-50 KB

All of these outputs stay in memory even after compaction marks them "old".

The Problem

In SessionCompaction.prune(), when tool outputs are pruned:

// BEFORE: Only sets a flag, output data stays in memory
part.state.time.compacted = Date.now()
await Session.updatePart(part)

The compacted timestamp is used by toModelMessage() to replace output with placeholder text like "(Old tool result content cleared)" - but the actual data never gets freed.

Over a long session:

  • 34,887 tool calls × average output size = hundreds of MB to GBs retained
  • Memory never decreases, even after compaction runs
  • Eventually Bun runs out of memory and crashes

The Fix

// AFTER: Actually clear the data
part.state.time.compacted = Date.now()
part.state.output = ""              // Free the output string
part.state.attachments = undefined  // Free any attachments
await Session.updatePart(part)

Now when compaction runs, the memory is actually freed. The placeholder text is already shown to the LLM (that logic exists), we just were not clearing the source data.

Testing

Existing compaction tests pass. Added test verifying output/attachments are cleared after prune.

**Original Pull Request:** https://github.com/anomalyco/opencode/pull/7049 **State:** open **Merged:** No --- Fixes #3013 ## Summary Clear tool output and attachments when compaction prunes old tool results, actually freeing memory instead of just flagging. ## Evidence In a real session working on this repo: | Metric | Value | |--------|-------| | OpenCode process RAM | **16.4 GB** | | Tool parts on disk | **34,887 files** | | Session duration | ~3 hours | Sample tool output sizes from this session: - `webfetch` of docs page: **10 KB** - `read` of source file: **5-50 KB** - `git diff` / `gh pr diff`: **10-100 KB** - `bash` command outputs: **1-50 KB** All of these outputs stay in memory even after compaction marks them "old". ## The Problem In `SessionCompaction.prune()`, when tool outputs are pruned: ```typescript // BEFORE: Only sets a flag, output data stays in memory part.state.time.compacted = Date.now() await Session.updatePart(part) ``` The `compacted` timestamp is used by `toModelMessage()` to replace output with placeholder text like "(Old tool result content cleared)" - but the **actual data never gets freed**. Over a long session: - 34,887 tool calls × average output size = **hundreds of MB to GBs** retained - Memory never decreases, even after compaction runs - Eventually Bun runs out of memory and crashes ## The Fix ```typescript // AFTER: Actually clear the data part.state.time.compacted = Date.now() part.state.output = "" // Free the output string part.state.attachments = undefined // Free any attachments await Session.updatePart(part) ``` Now when compaction runs, the memory is actually freed. The placeholder text is already shown to the LLM (that logic exists), we just were not clearing the source data. ## Testing Existing compaction tests pass. Added test verifying output/attachments are cleared after prune.
yindo added the pull-request label 2026-02-16 18:17:09 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#12225