fix: /tree and /fork commands lose context due to leaf reset

performFork() called ClearMessages() after Branch(targetID), but
ClearMessages() calls TreeSession.ResetLeaf() which sets leafID back
to empty — immediately undoing the branch. The in-memory message store
was also never reloaded from the tree session after branching, so the
LLM had zero context.

Add ReloadMessagesFromTree() which clears the store and reloads it
from the tree session's current branch without resetting the leaf
pointer. Use it in performFork() instead of ClearMessages().
This commit is contained in:
Ed Zynda
2026-03-29 15:02:24 +03:00
parent b0802a5c32
commit 49ff4c0678
3 changed files with 25 additions and 1 deletions
+11
View File
@@ -271,6 +271,17 @@ func (a *App) ClearMessages() {
}
}
// ReloadMessagesFromTree clears the in-memory message store and reloads it
// from the tree session's current branch. Unlike ClearMessages, this does NOT
// reset the tree session's leaf pointer. Used after Branch() to sync the
// store with the new branch position.
func (a *App) ReloadMessagesFromTree() {
a.store.Clear()
if a.opts.TreeSession != nil {
a.store.Replace(a.opts.TreeSession.GetLLMMessages())
}
}
// GetTreeSession returns the tree session manager, or nil if not configured.
func (a *App) GetTreeSession() *session.TreeManager {
return a.opts.TreeSession
+10 -1
View File
@@ -74,6 +74,11 @@ type AppController interface {
ClearQueue()
// ClearMessages clears the conversation history.
ClearMessages()
// ReloadMessagesFromTree clears the in-memory message store and reloads
// it from the tree session's current branch. Unlike ClearMessages, this
// does NOT reset the tree session's leaf pointer. Used after Branch() to
// sync the store with the new branch position.
ReloadMessagesFromTree()
// CompactConversation summarises older messages to free context space.
// Runs asynchronously; results are delivered via CompactCompleteEvent or
// CompactErrorEvent sent through the registered tea.Program. Returns an
@@ -3047,8 +3052,12 @@ func (m *AppModel) performFork(targetID string, isUser bool, userText string) te
return nil
}
// Branch the tree session to the target entry. We must NOT call
// ClearMessages() here because it resets the leaf pointer back to "",
// undoing the branch we just set. Instead, branch first and then
// reload the in-memory store from the tree session's current branch.
_ = ts.Branch(targetID)
m.appCtrl.ClearMessages()
m.appCtrl.ReloadMessagesFromTree()
// If it was a user message, populate the input with the text.
if isUser && userText != "" {
+4
View File
@@ -46,6 +46,10 @@ func (s *stubAppController) ClearMessages() {
s.clearMsgCalled++
}
func (s *stubAppController) ReloadMessagesFromTree() {
// no-op in tests
}
func (s *stubAppController) CompactConversation(_ string) error {
return nil
}