feat(ghostwriter): branching conversations with edit and per-message regenerate (#290)
Turn Ghostwriter's flat message list into a tree structure, enabling Claude.ai/ChatGPT-style branching conversations. **Data model**: Add `parentMessageId` and `activeChildId` to messages, `activeRootMessageId` to threads. Migration backfills existing messages into a linear chain and links regenerated messages as siblings. **Backend**: Tree-walking queries (getActivePathFromRoot, getAncestorPath, getSiblingsOf), rewritten history builder that follows the ancestor path, new editMessage and switchBranch services, regenerate now works on any assistant message (not just the latest). **Frontend**: BranchNavigator component (← 2/3 → arrows), inline edit on user messages, per-message regenerate on assistant messages, regenerate button removed from composer (now per-message). **Infra**: Pin Node 22 via Volta to prevent ABI mismatches with better-sqlite3 across environments.
This commit is contained in:
@@ -29,6 +29,7 @@ export interface JobChatThread {
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
lastMessageAt: string | null;
|
||||
activeRootMessageId: string | null;
|
||||
}
|
||||
|
||||
export interface JobChatMessage {
|
||||
@@ -42,10 +43,21 @@ export interface JobChatMessage {
|
||||
tokensOut: number | null;
|
||||
version: number;
|
||||
replacesMessageId: string | null;
|
||||
parentMessageId: string | null;
|
||||
activeChildId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface BranchInfo {
|
||||
/** The message ID this branch info belongs to (the currently active sibling). */
|
||||
messageId: string;
|
||||
/** Ordered sibling IDs at this branch point (by createdAt). */
|
||||
siblingIds: string[];
|
||||
/** 0-based index of the active sibling within siblingIds. */
|
||||
activeIndex: number;
|
||||
}
|
||||
|
||||
export interface JobChatRun {
|
||||
id: string;
|
||||
threadId: string;
|
||||
|
||||
Reference in New Issue
Block a user