How pi-web Handles Session Compaction and What Triggers It
Pi‑Web listens for compaction_start and compaction_end events emitted by the Pi SDK when a session grows too large, updates the UI state in the useAgentSession hook, and renders a summary while allowing users to abort the process via an abort_compaction command.
In the agegr/pi-web repository, session compaction is a background process managed by the Pi SDK to keep conversation history within performance limits. The frontend does not initiate compaction; instead, it reacts to lifecycle events broadcast by the backend, synchronizing UI state and providing controls to halt the operation if needed.
What Triggers Session Compaction?
The Pi SDK automatically triggers compaction when the accumulated session history exceeds internal thresholds—typically measured by token count or the number of exchanged messages. When these limits are reached, the backend emits a pair of RPC events that the frontend consumes:
compaction_start(or the legacyauto_compaction_start) – signals that the SDK has begun summarizing and truncating the session file.compaction_end(orauto_compaction_end) – signals completion and provides a summary object that replaces the truncated messages.
Because the SDK decides when compaction is necessary based on runtime heuristics, the frontend treats these events as read‑only notifications rather than commands it can initiate.
How pi-web Processes Compaction Events
Event Handling in useAgentSession
The primary consumer of compaction events is the useAgentSession hook. Inside the event loop (around lines 1041‑1048), a switch statement maps the incoming RPC type to local state transitions:
// hooks/useAgentSession.ts
case "auto_compaction_start":
case "compaction_start":
setIsCompacting(true);
break;
case "auto_compaction_end":
case "compaction_end":
setIsCompacting(false);
break;
By setting isCompacting to true on start and false on end, the hook prevents the UI from entering a stuck “compacting” state if an end event is dropped.
State Synchronization and UI Feedback
When isCompacting is true, the interface disables message input and displays a non‑blocking “Compacting…” indicator. This guards against race conditions where a user might send new messages while the backend is rewriting the session file. Once the end event arrives, the flag clears and normal interaction resumes.
Rendering the Compaction Summary
After compaction finishes, the SDK injects a special entry of type "compaction" into the session’s JSONL stream. The TypeScript definition in lib/types.ts describes this structure, which includes a summary text field.
The UI renders this entry in components/MessageView.tsx using the localized description found at line 418 of lib/i18n/messages/en.ts:
// MessageView.tsx
{msg.type === "compaction" && (
<div className="compaction-summary">
{t("i18n.compactionDescription")}
<pre>{msg.summary}</pre>
</div>
)}
This prevents the abrupt disappearance of history; instead, users see a collapsible summary representing the truncated portion.
Aborting an Active Compaction
Users can interrupt an ongoing compaction by clicking the “Stop compaction” button. This fires an abort_compaction command through the RPC layer. The handler resides in lib/rpc-manager.ts around line 578:
// lib/rpc-manager.ts
case "abort_compaction":
await session.abortCompaction();
break;
The frontend then awaits acknowledgment, at which point the SDK stops the summarization process and restores the pre‑compaction state.
Key Source Files and Functions
| File | Purpose |
|---|---|
hooks/useAgentSession.ts |
Listens for compaction_start/compaction_end and toggles the isCompacting flag (lines 1041‑1048). |
lib/rpc-manager.ts |
Dispatches the abort_compaction command to the backend (line 578). |
lib/types.ts |
Declares the SessionEntry union, including the "compaction" variant. |
lib/i18n/messages/en.ts |
Contains the user‑facing description string i18n.compactionDescription (line 418). |
components/MessageView.tsx |
Renders the compaction entry in the chat timeline. |
Summary
- Triggers – The Pi SDK initiates compaction automatically when token or message counts exceed safe limits, emitting lifecycle events that pi‑Web consumes.
- Event Handling – The
useAgentSessionhook processescompaction_startandcompaction_end, synchronizing theisCompactingstate to keep the UI consistent. - Visual Feedback – A dedicated message type and i18n string display a summary of the truncated history once compaction finishes.
- User Control – An
abort_compactionRPC command lets users stop the process mid‑flight, handled by the RPC manager.
Frequently Asked Questions
What backend conditions trigger a compaction event?
The Pi SDK monitors session file size and token consumption. When cumulative tokens or message count cross an internal threshold—designed to prevent memory bloat and latency degradation—the SDK emits a compaction_start event and begins summarizing older turns.
How does the frontend know when compaction starts and ends?
Pi‑Web’s useAgentSession hook subscribes to the RPC stream. It matches incoming message types (compaction_start, compaction_end, and their legacy auto_ variants) in a switch block and updates React state accordingly, ensuring the UI never desynchronizes from the backend process.
Can a user stop an ongoing compaction?
Yes. The UI exposes a “Stop compaction” button that sends an abort_compaction command via lib/rpc-manager.ts. The backend halts the summarization, and the frontend resets isCompacting to false once the acknowledgment returns.
Where is the compaction summary text defined?
The human‑readable description that accompanies a compaction entry is stored in lib/i18n/messages/en.ts at line 418 under the key i18n.compactionDescription. This string is fetched through the translation function and rendered next to the technical summary in MessageView.tsx.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →