# How pi-web Handles Session Compaction and What Triggers It

> Learn how pi-web manages session compaction when sessions reach a large size. Discover the events that trigger compaction and how users can abort the process.

- Repository: [Alex Yang/pi-web](https://github.com/agegr/pi-web)
- Tags: internals
- Published: 2026-07-31

---

**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 legacy **`auto_compaction_start`**) – signals that the SDK has begun summarizing and truncating the session file.
- **`compaction_end`** (or **`auto_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:

```typescript
// 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`](https://github.com/agegr/pi-web/blob/main/lib/types.ts) describes this structure, which includes a `summary` text field.

The UI renders this entry in [`components/MessageView.tsx`](https://github.com/agegr/pi-web/blob/main/components/MessageView.tsx) using the localized description found at line 418 of [`lib/i18n/messages/en.ts`](https://github.com/agegr/pi-web/blob/main/lib/i18n/messages/en.ts):

```tsx
// 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`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts) around line 578:

```typescript
// 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`](https://github.com/agegr/pi-web/blob/main/hooks/useAgentSession.ts) | Listens for `compaction_start`/`compaction_end` and toggles the `isCompacting` flag (lines 1041‑1048). |
| [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts) | Dispatches the `abort_compaction` command to the backend (line 578). |
| [`lib/types.ts`](https://github.com/agegr/pi-web/blob/main/lib/types.ts) | Declares the `SessionEntry` union, including the `"compaction"` variant. |
| [`lib/i18n/messages/en.ts`](https://github.com/agegr/pi-web/blob/main/lib/i18n/messages/en.ts) | Contains the user‑facing description string `i18n.compactionDescription` (line 418). |
| [`components/MessageView.tsx`](https://github.com/agegr/pi-web/blob/main/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 `useAgentSession` hook processes `compaction_start` and `compaction_end`, synchronizing the `isCompacting` state 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_compaction` RPC 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`](https://github.com/agegr/pi-web/blob/main/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`](https://github.com/agegr/pi-web/blob/main/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`](https://github.com/agegr/pi-web/blob/main/MessageView.tsx).