Files
oh-my-pi/packages/coding-agent/docs/session-tree-plan.md
T
can1357 7d60a1af85 docs(coding-agent): updated documentation
- Updated documentation to reflect product name change from 'pi' to 'omp' throughout guides and API references.
- Restructured extension and hook documentation to clarify discovery mechanisms, loading behavior, and configuration across multiple config systems (.omp, .pi, .claude, .codex).
- Updated SDK API documentation with new method signatures: discoverHooks() -> discoverExtensions(), SessionManager methods now async, settings format changed to YAML.
- Expanded session architecture documentation with new entry types (TtsrInjectionEntry, SessionInitEntry), updated field names (fromHook -> fromExtension), and clarified session file format versioning.
- Simplified session-tree-plan.md from detailed implementation checklist to architecture summary, removing completed tasks and rollout details.
2026-02-05 01:34:20 +01:00

5.4 KiB

Session Tree Architecture (Current)

Reference: session.md, tree.md

This document summarizes the current session tree implementation and extension touchpoints. It replaces the historical rollout checklist.

Session file format (v3)

  • JSONL file with a SessionHeader (version 3). Header is metadata only and does not participate in the tree.
  • Every SessionEntry derives from SessionEntryBase: id, parentId, timestamp.
  • Entries are append-only; branching only moves the leaf pointer.
  • Entry types: message, compaction, branch_summary, custom, custom_message, label, model_change, thinking_level_change, ttsr_injection, session_init.

SessionManager core

  • Tracks byId, labelsById, leafId, and usage statistics.
  • Tree APIs:
    • getLeafId(), getLeafEntry(), getEntry(id), getChildren(id)
    • getBranch(fromId?) → root-to-leaf path
    • getTree() → SessionTreeNode { entry, children, label }
    • getLabel(id)
  • buildSessionContext() walks from the current leaf and resolves compaction. custom_message and branch_summary entries are converted to AgentMessage roles and later to user-role LLM messages via convertToLlm().
  • Appenders (all return entry id and advance the leaf): appendMessage, appendCompaction, appendCustomEntry, appendCustomMessageEntry, appendLabelChange, appendModelChange, appendThinkingLevelChange, appendSessionInit, appendTtsrInjection.
  • getSessionFile() returns string | undefined for in-memory sessions. flush() persists pending writes.

Migration

  • CURRENT_SESSION_VERSION = 3.
  • v1 → v2: assigns id/parentId and converts compaction firstKeptEntryIndex to firstKeptEntryId.
  • v2 → v3: renames message role hookMessage → custom.
  • SessionManager.open() / setSessionFile() rewrite the file after migration.

Branching

  • branch(entryId) moves the leaf pointer to a prior entry.
  • resetLeaf() sets the leaf to null so the next append creates a new root entry.
  • branchWithSummary(branchFromId, summary, details?, fromExtension?) appends branch_summary and switches the leaf.
  • createBranchedSession(leafId) writes a new session file containing the selected path; LabelEntry values are rebuilt from resolved labels. In-memory sessions replace their entries and return undefined.

Compaction integration

  • CompactionEntry / CompactionResult are generic with optional details and preserveData; firstKeptEntryId is the compaction anchor.
  • session_before_compact provides CompactionPreparation, branchEntries, customInstructions, and signal.
  • session.compacting allows overriding the compaction prompt/context.
  • session_compact emits the final CompactionEntry and fromExtension flag.

Labels

  • LabelEntry stores targetId + label; labelsById maps targetId → label.
  • appendLabelChange(targetId, label?) sets or clears labels.
  • Tree selector shows labels and supports the "labeled-only" filter. Press Shift+L in /tree to edit the selected label.

Custom messages

  • CustomMessageEntry stores customType, content, display, details; converted to AgentMessage role custom.
  • buildSessionContext() includes custom_message entries; convertToLlm() maps them to user-role LLM messages.
  • TUI rendering: display=false hides the entry; display=true uses customMessageBg/customMessageText/customMessageLabel theme tokens.
  • Extensions can override rendering via registerMessageRenderer(customType, renderer).

Extension API touchpoints

  • sendMessage(...) appends a CustomMessageEntry. options: triggerTurn, deliverAs ("steer" | "followUp" | "nextTurn").
  • sendUserMessage(...) always triggers a turn with a real user message.
  • appendEntry(customType, data) persists extension state (CustomEntry, not sent to the LLM).
  • registerCommand(name, { description?, handler }) registers /commands. Handlers return void; trigger turns explicitly with sendMessage/sendUserMessage.
  • ExtensionContext exposes sessionManager (read-only), modelRegistry, model, getContextUsage(), compact(), and abort/idle helpers.
  • ExtensionCommandContext adds waitForIdle(), newSession(), branch(), navigateTree().

Agent context events

  • context: called before each LLM call with AgentMessage[]; returning { messages } replaces the prompt messages for this call (not persisted).
  • before_agent_start: fired after the user prompt but before the agent loop; event includes prompt, images, and systemPrompt.
    • Result can add a CustomMessage and/or replace the systemPrompt for the turn. Multiple extensions can contribute messages; systemPrompt updates chain in order.

Tree UI + commands

  • /tree: in-place navigation with search, filter modes (default/no-tools/user-only/labeled-only/all), labels, and active-path highlighting.
  • /branch: creates a new session file from the current path.
  • Tree navigation emits session_before_tree with TreePreparation (targetId, oldLeafId, commonAncestorId, entriesToSummarize, userWantsSummary) and session_tree with SessionTreeEvent (newLeafId, oldLeafId, summaryEntry?, fromExtension?).

HTML export

  • Session HTML export includes a sidebar tree with search, the same filter modes as /tree, and a responsive hamburger toggle.
  • URL parameters leafId/targetId allow deep-linking to a branch and specific entry.