<!-- source-hash: 17a77a7a52f5be3583fd5569ca4bb36f -->
Manages the accumulation and lifecycle of message segments during real-time AI chat streaming, handling text, tool executions, and approval workflows.

## Key Components

- **`MessageSegmentAccumulator`** — Core class that tracks all segment types (`text`, `thinking`, `tool_execution`, `approval_request`, `approval_batch`) in a stateful array
- **`AccumulatorCallbacks`** — Interface for wiring `onApprove`/`onReject` handlers into approval segments
- **`initializeWithState()`** — Restores accumulator from serialized state across reconnections or page refreshes
- **`appendText()` / `appendThinking()`** — Coalesces consecutive same-type segments instead of creating duplicates
- **`addToolExecution()`** — Routes `EXECUTING_TOOL` → `EXECUTED_TOOL` state transitions, merging into approval batches when a `toolExecutionRequestId` matches
- **`addApprovalBatch()`** — Upserts batch approval segments by `approvalRequestId` to prevent duplicates during replay
- **`resolvePendingApprovalForExecution()`** — Implicitly marks the latest pending approval as approved when a tool execution arrives (handles observer streams with no `APPROVAL_RESULT` chunk)
- **`getState()` / `reset()`** — Serialization and teardown helpers

## Usage Example

```typescript
const accumulator = new MessageSegmentAccumulator({
  onApprove: async (requestId) => await approveRequest(requestId),
  onReject: async (requestId) => await rejectRequest(requestId),
})

// Restore state after reconnection
accumulator.initializeWithState({
  existingSegments: previousSegments,
  pendingApprovals: savedApprovals,
})

// Stream incoming chunks
accumulator.appendText('Checking your ')
accumulator.appendText('ticket status...')

// Handle tool lifecycle
accumulator.addToolExecution({
  type: 'tool_execution',
  data: { type: 'EXECUTING_TOOL', toolFunction: 'getTicket', toolTitle: 'Get Ticket', ... },
})

// Retrieve rendered segments
const segments = accumulator.getSegments()
```