# How the Pro Workbench in OpenMAIC Implements Durable Session Architecture

> Discover how OpenMAIC's Pro workbench implements durable session architecture by reconstructing UI state from immutable server-persisted events and applying transient layout adjustments.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: architecture
- Published: 2026-09-12

---

**The Pro workbench leverages the same durable session backbone as the classic interface, reconstructing UI state by folding immutable server-persisted events while applying transient layout adjustments for the 16∶9 canvas mode.**

The OpenMAIC platform provides a sophisticated workspace for AI-assisted development, with the Pro workbench offering an expanded full-screen canvas experience. Unlike traditional session management that relies on mutable state, the Pro workbench utilizes a **durable session architecture** built on event sourcing principles. This design ensures that conversations, tool cards, and classroom panes survive navigation, reloads, and mode switches between the classic and Pro interfaces.

## Event Sourcing: The Immutable Foundation

The durable session architecture treats all state changes as immutable events. Rather than mutating a database record, the system appends events to a log and reconstructs state by folding over that history.

### The Durable Event Log

Server-persisted events form the authoritative source of truth. The client receives a stream of `PersistedEvent` objects from the endpoint `/api/agent/sessions/:id/events` and maintains the **last processed event ID** (`lastEventId`) to track progress. Each new event is applied using the pure function `foldEvent`, defined in [`lib/workbench/session-store.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/session-store.ts) at lines 12–30.

Because `foldEvent` is a pure function of the event prefix, replaying the entire log after a disconnect yields exactly the same UI state. This property ensures **eventual consistency** between client and server, regardless of network interruptions.

### Separating Persistent and Transient State

The architecture strictly divides state into two categories in [`lib/workbench/session-store.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/session-store.ts) (lines 84–110):

- **`WorkbenchSessionState`** – Contains the immutable transcript, conversation history, and tool results. This is the durable fold that survives restarts.
- **`WorkbenchState`** – Houses transient UI flags such as `panelOpen` and `playbackOn`. These preferences reset when the session reloads.

This separation guarantees that resetting a session always restores a complete, consistent state derived from the server-side event log, while UI cosmetic choices remain disposable.

## Pro Mode UI Adaptations

While the underlying session architecture remains identical between classic and Pro modes, the Pro workbench applies specific UI transformations to maximize screen real estate.

### Full-Screen Canvas Sizing

When the Pro workbench activates, the `useWorkbenchProEditing` hook (located in [`lib/workbench/use-workbench-pro-edit.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/use-workbench-pro-edit.ts) at lines 15–22) forces the canvas to occupy 100% of the available area. This fills the 16∶9 workbench card completely.

```tsx
// Enable Pro‑mode canvas sizing (fills the 16:9 card)
import { useWorkbenchProEditing } from '@/lib/workbench/use-workbench-pro-edit';

export default function ProWorkspace() {
  useWorkbenchProEditing();          // forces canvasPercentage = 100%
  return <YourWorkspaceComponents />;
}

```

Importantly, this hook does **not** interact with the durable fold. It only adjusts the rendering layout, ensuring the session state remains identical regardless of which view mode renders it.

### Seamless Route Transitions

Switching between the classic (`/`) and Pro (`/workspace`) routes utilizes a **shared-element view-transition** implemented in [`lib/workbench/pro-swap.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/pro-swap.ts) (lines 1–53). The `startProSwap` function orchestrates the transition while preserving the product lock-up and Pro badge animations.

```ts
// Switch to the Pro workbench with a smooth transition
import { startProSwap } from '@/lib/workbench/pro-swap';
import { useRouter } from 'next/router';

export function goToPro() {
  const router = useRouter();
  startProSwap('/workspace', router.push);
}

```

During this transition, the underlying **session identifier** (`sessionId`) remains unchanged. Consequently, the durable event stream continues uninterrupted, and the fold resumes exactly where it left off—no state synchronization is required because the client simply continues receiving the same SSE stream.

## Session Recovery and Replay

The durable architecture excels at handling network volatility and browser navigation. When connectivity restores, the system reconciles state automatically.

### Handling Reconnections and Orphaned Events

If the client loses connection, the fold resumes from the saved `lastEventId`. The durable log may contain "repaired" tool calls with orphaned IDs; the fold settles any still-running tool cards so that the UI never displays a stale "running" state. This logic resides in [`lib/workbench/session-store.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/session-store.ts) within the `session_resumed` handler (lines 1010–1040) and the `settleRunningToolCards` function (lines 1089–1104).

```ts
// Recover after a disconnect – the fold continues from the saved ID
import { foldEvent } from '@/lib/workbench/session-store';

// Event received from SSE:
const newFold = foldEvent(currentFold, incomingEvent);
// The UI automatically reflects the updated fold.

```

This guarantees that a Pro session always reflects the latest durable state, even after a navigation or crash.

## Practical Implementation

To attach to a durable session from either workbench mode, use the `useWorkbenchStream` hook from [`lib/workbench/use-workbench-session.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/use-workbench-session.ts):

```ts
// Attach to a durable session (common to both classic and Pro)
import { useWorkbenchStream } from '@/lib/workbench/use-workbench-session';

// When the component mounts:
useWorkbenchStream({
  sessionId: 'abc123',               // Durable session identifier
  stageId: null,                     // Optional stage link
});

```

This hook connects to the server-sent event stream and manages the local fold, ensuring that both the classic and Pro workbenches display identical conversation states derived from the same immutable source.

## Summary

- **Event sourcing backbone**: The Pro workbench relies on a pure `foldEvent` function applied to a server-persisted log of `PersistedEvent`s, ensuring state consistency across reconnections.
- **State separation**: `WorkbenchSessionState` holds durable conversation data while `WorkbenchState` manages transient UI flags, preventing corruption of session history.
- **UI-only adaptations**: Pro mode uses `useWorkbenchProEditing` to scale the canvas without affecting the underlying session fold.
- **Seamless mode switching**: The `startProSwap` transition preserves `sessionId` continuity, allowing the event stream to persist across route changes.
- **Automatic recovery**: The architecture handles orphaned tool calls and resumed sessions via `settleRunningToolCards`, ensuring the UI never displays stale execution states.

## Frequently Asked Questions

### Does the Pro workbench use a separate session model from the classic workbench?

No. According to the OpenMAIC source code, the Pro workbench does **not** introduce a separate session model. It reuses the identical durable event stream and `foldEvent` logic defined in [`session-store.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/session-store.ts). The only differences are UI-layer adjustments for canvas sizing and route transitions.

### How does OpenMAIC ensure session continuity when switching between classic and Pro modes?

The `startProSwap` function in [`pro-swap.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/pro-swap.ts) manages the view transition between routes while maintaining the same `sessionId`. Because the session identifier persists across the navigation, the client continues consuming the same server-sent event stream without reinitialization. The fold resumes from `lastEventId`, ensuring zero state loss.

### What happens to running tool calls when the client reconnects after a disconnect?

The durable event log may contain repaired or orphaned tool call events. When the session resumes, the `foldEvent` function processes these events and calls `settleRunningToolCards` (lines 1089–1104 in [`session-store.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/session-store.ts)) to reconcile any still-running tool cards. This ensures the UI reflects the actual server state rather than displaying phantom "running" indicators.

### Where is the durable session state stored versus transient UI state?

In [`lib/workbench/session-store.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/session-store.ts), the architecture defines `WorkbenchSessionState` (lines 84–110) for immutable data including the conversation transcript, while `WorkbenchState` extends it with transient flags like `panelOpen`. The [`workspace-session-memory.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/workspace-session-memory.ts) file maintains the in-memory fold and transient flags, but only the `WorkbenchSessionState` subset persists to the server event log.