Bug Description
Tool-using sessions can freeze the TUI and drive multi-GB RSS growth because SessionSummary.summarize(...) is invoked on every assistant finish-step, and summarize() loads the full session history (Session.messages({ sessionID })) every time.
This creates a hot loop during multi-step agent execution:
- prompt loop re-enters for normal tool-assisted execution
- processor
finish-step fires for each assistant model turn
- processor calls
SessionSummary.summarize(...)
- summarize loads the full session history and hydrates all parts
- memory spikes and repeats on every turn
Root Cause
Primary trigger
packages/opencode/src/session/processor.ts
Inside the finish-step event handler, the processor unconditionally calls:
SessionSummary.summarize({
sessionID: ctx.sessionID,
messageID: ctx.assistantMessage.parentID,
})
That means summary runs once per assistant model turn, not once per overall user prompt.
Expensive operation
packages/opencode/src/session/summary.ts
summarize() calls:
const all = yield* sessions.messages({ sessionID: input.sessionID })
With no limit, this hydrates the full message history every time.
Evidence
Live diagnostic repro with labeled binary:
prompt loop entry: 4
summary start: 4
summary loaded messages: 4
prompt loop summary trigger: 1
prune start: 0
session messages full: 10
message hydrate: 45
This proves:
- prompt loop re-entry is happening during normal multi-step execution
- repeated full-history loads are coming from summary, not prune
- processor-side summary calls explain the count gap beyond the one prompt-loop trigger
User Impact
- standalone TUI freezes / becomes unresponsive
- process RSS grows into multi-GB territory
- likely contributes to shared serve memory drift under long-running tool sessions
Proposed Fix
- Remove the processor-side
SessionSummary.summarize(...) call from finish-step
- Keep summary responsibility at the prompt-loop level instead of per-step
- Add a cheap guard in
summary.ts to skip work if the target user message already has summary.diffs
Bug Description
Tool-using sessions can freeze the TUI and drive multi-GB RSS growth because
SessionSummary.summarize(...)is invoked on every assistantfinish-step, andsummarize()loads the full session history (Session.messages({ sessionID })) every time.This creates a hot loop during multi-step agent execution:
finish-stepfires for each assistant model turnSessionSummary.summarize(...)Root Cause
Primary trigger
packages/opencode/src/session/processor.tsInside the
finish-stepevent handler, the processor unconditionally calls:That means summary runs once per assistant model turn, not once per overall user prompt.
Expensive operation
packages/opencode/src/session/summary.tssummarize()calls:With no
limit, this hydrates the full message history every time.Evidence
Live diagnostic repro with labeled binary:
prompt loop entry: 4summary start: 4summary loaded messages: 4prompt loop summary trigger: 1prune start: 0session messages full: 10message hydrate: 45This proves:
User Impact
Proposed Fix
SessionSummary.summarize(...)call fromfinish-stepsummary.tsto skip work if the target user message already hassummary.diffs