diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 88f3581..a0352b3 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -571,6 +571,14 @@ export default function App() { autoApprovedToolNames: settings.autoApprovedToolNames, }); }} + onBranchFromMessage={(messageId) => { + void api.branchSession({ sessionId: selectedSession.id, messageId }); + }} + branchOriginLabel={ + selectedSession.branchOrigin + ? workspace.sessions.find((s) => s.id === selectedSession.branchOrigin!.sourceSessionId)?.title + : undefined + } availableModels={availableModels} mcpProbingServerIds={workspace.mcpProbingServerIds} onTerminalToggle={handleTerminalToggle} diff --git a/src/renderer/components/ChatPane.tsx b/src/renderer/components/ChatPane.tsx index 569d90e..40eeea1 100644 --- a/src/renderer/components/ChatPane.tsx +++ b/src/renderer/components/ChatPane.tsx @@ -64,6 +64,8 @@ interface ChatPaneProps { }) => Promise; onUpdateSessionTooling?: (selection: SessionToolingSelection) => void; onUpdateSessionApprovalSettings?: (settings: { autoApprovedToolNames?: string[] }) => void; + onBranchFromMessage?: (messageId: string) => void; + branchOriginLabel?: string; } export function ChatPane({ @@ -90,6 +92,8 @@ export function ChatPane({ onUpdateSessionModelConfig, onUpdateSessionTooling, onUpdateSessionApprovalSettings, + onBranchFromMessage, + branchOriginLabel, }: ChatPaneProps) { const [hasComposerContent, setHasComposerContent] = useState(false); const [configError, setConfigError] = useState(); @@ -327,6 +331,18 @@ export function ChatPane({ ) : (
+ {/* Branch origin banner */} + {session.branchOrigin && ( +
+ + + Branched from{' '} + + {branchOriginLabel ?? 'a previous session'} + + +
+ )}
{session.messages.map((message, index) => { const isUser = message.role === 'user'; @@ -364,6 +380,17 @@ export function ChatPane({ {phaseLabel} )} + {isUser && onBranchFromMessage && ( + + )}
)} + {session.branchOrigin && ( + + + + )} {relativeTime(session.updatedAt)}