mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 14:03:49 +00:00
- Import CompactionResult in hooks/types.ts - Replace inline type with CompactionResult for SessionEventResult.compaction - Add labels feature to changelog
6 KiB
6 KiB
Session Tree Implementation Plan
Reference: session-tree.md
Phase 1: SessionManager Core ✅
- Update entry types with
id,parentIdfields (using SessionEntryBase) - Add
versionfield toSessionHeader - Change
CompactionEntry.firstKeptEntryIndex→firstKeptEntryId - Add
BranchSummaryEntrytype - Add
CustomEntrytype for hooks - Add
byId: Map<string, SessionEntry>index - Add
leafId: stringtracking - Implement
getPath(fromId?)tree traversal - Implement
getTree()returningSessionTreeNode[] - Implement
getEntry(id)lookup - Implement
getLeafUuid()andgetLeafEntry()helpers - Update
_buildIndex()to populatebyIdmap - Rename
saveXXX()toappendXXX()(returns id, advances leaf) - Add
appendCustomEntry(customType, data)for hooks - Update
buildSessionContext()to usegetPath()traversal
Phase 2: Migration ✅
- Add
CURRENT_SESSION_VERSION = 2constant - Implement
migrateV1ToV2()with extensible migration chain - Update
setSessionFile()to detect version and migrate - Implement
_rewriteFile()for post-migration persistence - Handle
firstKeptEntryIndex→firstKeptEntryIdconversion in migration
Phase 3: Branching ✅
- Implement
branch(id)- switch leaf pointer - Implement
branchWithSummary(id, summary)- create summary entry - Implement
createBranchedSession(leafId)- extract path to new file - Update
AgentSession.branch()to use new API
Phase 4: Compaction Integration ✅
- Update
compaction.tsto work with IDs - Update
prepareCompaction()to returnfirstKeptEntryId - Update
compact()to returnCompactionResultwithfirstKeptEntryId - Update
AgentSessioncompaction methods - Add
firstKeptEntryIdtobefore_compacthook event
Phase 5: Testing ✅
migration.test.ts- v1 to v2 migration, idempotencybuild-context.test.ts- context building with tree structure, compaction, branchestree-traversal.test.ts- append operations, getPath, getTree, branchingfile-operations.test.ts- loadEntriesFromFile, findMostRecentSessionsave-entry.test.ts- custom entry integration- Update existing compaction tests for new types
Remaining Work
Compaction Refactor
- Clean up types passed to hooks (currently messy mix of
CompactionEntry,CompactionResult, hook'scompactioncontent) - Ensure consistent API between what hooks receive and what they return
Branch Summary Design
Current type:
export interface BranchSummaryEntry extends SessionEntryBase {
type: "branch_summary";
summary: string;
}
Questions to resolve:
- Add
abandonedLeafIdfield to reference what was abandoned? - Store metadata about why the branch happened?
- Who generates the summary - user, LLM, or both options?
- Design and implement branch summarizer
- Add tests for
branchWithSummary()flow
Entry Labels ✅
- Add
LabelEntrytype withtargetIdandlabelfields - Add
labelsById: Map<string, string>private field - Build labels map in
_buildIndex()via linear scan - Add
getLabel(id)method - Add
appendLabelChange(targetId, label)method (undefined clears) - Update
createBranchedSession()to filter out LabelEntry and recreate from resolved map buildSessionContext()already ignores LabelEntry (only handles message types)- Add
label?: stringtoSessionTreeNode, populated bygetTree() - Display labels in UI (tree view, path view) - deferred to UI phase
/labelcommand - deferred to UI phase
CustomMessageEntry
Hooks can define their own custom message entry types and inject them into the session.
export interface CustomMessageEntry<T = unknown> extends SessionEntryBase {
type: "custom_message";
customType: string; // Hook identifier
content: (string | Attachment)[]; // Message content
details?: T; // Hook-specific data (like tool result details)
display: boolean; // Whether to display in TUI
}
Behavior:
- Participates in context and compaction as user messages (after messageTransformer)
- Not displayed as user messages in TUI
- Display options:
display: false- hidden entirelydisplay: true- baseline renderer (content with different bg/fg color)- Custom renderer defined by the hook that contributes it
- Define injection mechanism for hooks to add CustomMessageEntry
- Hook registration for custom renderers
HTML Export
- Add collapsible sidebar showing full tree structure
- Allow selecting any node in tree to view that path
- Add "reset to session leaf" button
- Render full path (no compaction resolution needed)
- Responsive: collapse sidebar on mobile
UI Commands
Design new commands based on refactored SessionManager:
/branch - Current behavior (creates new session file from path)
- Review if this is still the right UX with tree structure
- Consider: should this use
createBranchedSession()orbranch()?
/branch-here - In-place branching (new)
- Use
branch(id)to move leaf pointer without creating new file - Subsequent messages become new branch in same file
- Design: how to select branch point? (similar to current
/branchUI?)
/branches - List/navigate branches (new)
- Show tree structure or list of branch points
- Allow switching between branches (move leaf pointer)
- Show current position in tree
Notes
- All append methods return the new entry's ID
- Migration rewrites file on first load if version < CURRENT_VERSION
- Existing sessions become linear chains after migration (parentId = previous entry)
- Tree features available immediately after migration
- SessionHeader does NOT have id/parentId (it's metadata, not part of tree)
- Session is append-only: entries cannot be modified or deleted, only branching changes the leaf pointer