How Maka Handles Session Branching, Revision, and Regeneration: A Deep Dive into the Conversation Model
Maka's conversation model treats every user-assistant interaction as a session that can evolve through three distinct mechanisms: branching for new logical conversations, revision for edit-and-resend workflows, and regeneration for re-running completed turns.
The Apache Maka project implements a sophisticated session management system that preserves full audit history while presenting users with a clean, coherent view of their conversations. This article examines how session branching, revision, and regeneration are implemented in the core runtime, with direct reference to the source code in packages/core/src/session.ts, session-revisions.ts, and agent-run.ts.
Understanding the Three Session Evolution Patterns
Maka distinguishes between three ways a conversation can evolve. Each pattern serves a different user need and carries distinct metadata in the session record.
| Pattern | Purpose | Key Identifier |
|---|---|---|
| Branch | Start a new independent conversation from an existing one | kind: 'branch' in SessionSummary |
| Revision | Edit and resend a previous turn, creating a new physical version | revisionRootSessionId, revisionParentSessionId, revisionOfTurnId |
| Regeneration | Re-run a completed turn to obtain fresh results | regeneratedFromTurnId in TurnStateMessage |
How Maka Implements Session Branching
A branch represents a new logical conversation that begins from an existing session context without altering the original thread.
In packages/core/src/session.ts at line 166, the SessionSummary interface defines the kind: 'branch' discriminator. When a user creates a new session UI element, the desktop or TUI layer creates a branch session whose id is independent of any revision lineage. Unlike revisions, branches do not carry revisionRootSessionId or related fields—they are clean forks of conversation state.
// Creating a branch session via the Runtime Host
await runtimeHost.createSession({
kind: 'branch',
parentSessionId: currentSession.id, // optional: reference to originating session
// No revision fields set—this is a clean fork
});
Branches appear as separate top-level entries in the session list. The projectRevisionLinkedSessionTree function in session-revisions.ts preserves branch relationships when building the UI projection, ensuring users can navigate between related but independent conversation threads.
How Maka Implements Session Revision
Revision is Maka's mechanism for "edit and resend" functionality—allowing users to modify a previous turn and generate a new response while preserving complete history.
Revision Metadata Fields
The revision system uses five core fields defined in packages/core/src/session.ts (lines 260–286):
revisionRootSessionId: The original session that started the revision familyrevisionParentSessionId: The immediate parent session that spawned this revisionrevisionOfTurnId: The specific turn being edited and resentrevisionIndex: The sequence number within the revision familyrevisionState: Either'preparing'or'committed', tracking durability
Creating a Revision Session
When a user edits a turn and resends, the UI creates a revision session:
// UI command → Runtime Host
await runtimeHost.createSession({
kind: 'revision', // <-- creates a revision session
revisionParentSessionId: current.id, // parent session that spawned this revision
revisionOfTurnId: turnId, // the turn being edited
revisionRootSessionId: rootId, // original session in this family
revisionIndex: nextIndex, // incrementing sequence number
});
Collapsing Revisions for UI Display
Multiple physical revisions of the same logical conversation must appear as a single row in the UI. The collapseSessionRevisions function in packages/core/src/session-revisions.ts (lines 57–85) handles this:
import { collapseSessionRevisions } from '@maka/core/session-revisions';
const visibleSessions = collapseSessionRevisions(allSessions, activeSessionId);
// `visibleSessions` now contains one row per revision family
The collapse algorithm works as follows:
- Collect families using
sessionRevisionFamilyId(session)fromsession.ts - Pick a representative—the most recent visible member, or the active session if present
- Discard non-visible revisions from the projected view while retaining them in storage
Building the Linked Session Tree
After collapsing, projectRevisionLinkedSessionTree in session-revisions.ts (lines 95–108) constructs the child-session tree that respects original parent-session anchors:
import { projectRevisionLinkedSessionTree } from '@maka/core/session-revisions';
const linkedTree = projectRevisionLinkedSessionTree(allSessions, activeSessionId);
// UI uses `linkedTree` to render branches, revisions and their children
The UI layer in packages/ui/src/transcript-projection.ts subscribes to this projected list, ensuring users see one coherent conversation while the underlying database retains every physical revision for audit and replay.
How Maka Implements Turn Regeneration
Regeneration re-runs a completed turn to obtain a fresh result, typically after a crash or when using "safe-resume" functionality. Unlike revision, regeneration preserves the original turn's identity and session structure—the new turn simply supersedes it in display.
Regeneration Metadata
Two structures carry regeneration linkage in packages/core/src/session.ts:
TurnStateMessage(lines 15–19): ContainsregeneratedFromTurnIdpointing to the source turnTurnRecord(lines 72–90): Mirrors this field for persistent storage
The Regeneration Execution Flow
The AgentRun controller in packages/core/src/agent-run.ts handles regeneration requests:
Step 1: Runtime Host creates a RegenerateExecution object:
const execution: RegenerateExecution = {
kind: 'regenerate',
sourceTurnId: 'turn-42', // the turn we want to redo
};
Step 2: AgentRun.handleExecution receives the request (lines 88–106):
import { AgentRun } from '@maka/core/agent-run';
await AgentRun.execute({
kind: 'regenerate',
sourceTurnId: 'turn-42',
});
Step 3: After the model re-executes, the new turn records its provenance:
// In the runtime, after model response arrives:
const newTurn: TurnStateMessage = {
type: 'turn_state',
id: uuid(),
turnId: 'turn-99',
ts: Date.now(),
status: 'completed',
regeneratedFromTurnId: 'turn-42', // <-- points back to the original turn
};
await runtimeLog.append(newTurn);
Step 4: The UI treats the regenerated turn as a fresh turn in the same logical session, displaying the new assistant response without breaking conversation continuity.
Comparing Revision and Regeneration
While both revision and regeneration produce new turns from existing ones, they serve distinct purposes:
| Aspect | Revision | Regeneration |
|---|---|---|
| User intent | "I want to change my question and get a new answer" | "I want to retry getting an answer to the same question" |
| Session structure | Creates new physical session in revision family | Keeps same session, adds new turn |
| Original turn | Preserved as historical version | Superseded by new turn |
| UI presentation | Collapsed into single visible row | Shows as replacement in timeline |
| Fields used | revisionParentSessionId, revisionOfTurnId, revisionIndex |
regeneratedFromTurnId |
Key Source Files and Their Responsibilities
| File | Purpose |
|---|---|
packages/core/src/session.ts |
Defines SessionSummary, revision metadata fields, TurnStateMessage, TurnRecord, and sessionRevisionFamilyId() |
packages/core/src/session-revisions.ts |
Implements collapseSessionRevisions() and projectRevisionLinkedSessionTree() for UI projection |
packages/core/src/agent-run.ts |
Handles regenerate execution kind in AgentRun.handleExecution() |
packages/ui/src/transcript-projection.ts |
Consumes collapsed revision list for UI rendering |
Summary
-
Branching creates independent conversation forks via
kind: 'branch'inSessionSummary, with no revision lineage attached. -
Revision implements edit-and-resend through five metadata fields (
revisionRootSessionId,revisionParentSessionId,revisionOfTurnId,revisionIndex,revisionState) and collapses multiple physical sessions into one visible row viacollapseSessionRevisions(). -
Regeneration re-executes turns safely using
kind: 'regenerate'execution requests inAgentRun, linking new turns to originals throughregeneratedFromTurnId. -
The projection layer in
session-revisions.tsensures users see coherent conversations while the runtime maintains complete immutable history.
Frequently Asked Questions
What triggers a session revision versus a branch in Maka?
A revision triggers when a user edits and resends an existing turn in the same conversation context—Maka creates a new physical session with revision metadata pointing to the original. A branch triggers when a user explicitly starts a new conversation thread from an existing one, creating a completely independent session with kind: 'branch' and no revision fields. The UI typically offers "Edit and resend" for revisions and "Start new chat" or "Branch here" for branches.
How does Maka prevent revision history from cluttering the UI?
Maka uses the collapseSessionRevisions() function to group all physical revisions of the same family into a single visible row. The algorithm selects the most recent visible member or the active session as the representative, while the underlying TurnRecord and SessionSummary objects remain stored for audit. The UI projection in transcript-projection.ts subscribes to this collapsed view.
Can regenerated turns themselves be revised or branched?
Yes. Once a regenerated turn completes and is recorded with its regeneratedFromTurnId linkage, it becomes a normal turn in the session. Users can subsequently revise it (creating a new revision family) or branch from its session context. The regeneration metadata is preserved for lineage tracking but does not constrain future operations on the resulting turn.
What happens to revision families when the root session is deleted?
The sessionRevisionFamilyId() function derives family identity from revision metadata fields rather than session existence alone. If a root session is deleted, its descendant revisions maintain their revisionRootSessionId reference to the deleted ID. The collapse algorithm in collapseSessionRevisions() continues to group these orphaned revisions by their declared family ID, though the oldest member may become the effective root for display purposes.
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 →