Private
Public Access
1
0

Tweaks/cleanups to conversation management in tui

- Pass around message/conversation values instead of pointers where it
makes more sense, and store values instead of pointers in the globally
(within the TUI) shared `App` (pointers provide no utility here).

- Split conversation persistence into separate conversation/message
  saving stages
This commit is contained in:
2024-10-25 16:57:15 +00:00
parent 07c96082e7
commit ec21a02ec0
9 changed files with 116 additions and 86 deletions

View File

@@ -75,7 +75,7 @@ func (m *Model) Update(msg tea.Msg) (shared.ViewModel, tea.Cmd) {
m.rebuildMessageCache()
m.updateContent()
if m.App.Conversation != nil && m.App.Conversation.ID > 0 {
if m.App.Conversation.ID > 0 {
// (re)load conversation contents
cmds = append(cmds, m.loadConversationMessages())
}
@@ -133,7 +133,7 @@ func (m *Model) Update(msg tea.Msg) (shared.ViewModel, tea.Cmd) {
case msgChatResponse:
m.state = idle
reply := (*conversation.Message)(msg)
reply := conversation.Message(msg)
reply.Content = strings.TrimSpace(reply.Content)
last := len(m.App.Messages) - 1
@@ -142,16 +142,15 @@ func (m *Model) Update(msg tea.Msg) (shared.ViewModel, tea.Cmd) {
}
if m.App.Messages[last].Role.IsAssistant() {
// TODO: handle continuations gracefully - some models support them well, others fail horribly.
m.setMessage(last, *reply)
// TODO: handle continuations gracefully - only some models support them
m.setMessage(last, reply)
} else {
m.addMessage(*reply)
m.addMessage(reply)
}
switch reply.Role {
case api.MessageRoleToolCall:
if reply.Role == api.MessageRoleToolCall {
// TODO: user confirmation before execution
// m.state = waitingForConfirmation
// m.state = confirmToolUse
cmds = append(cmds, m.executeToolCalls(reply.ToolCalls))
}
@@ -159,11 +158,9 @@ func (m *Model) Update(msg tea.Msg) (shared.ViewModel, tea.Cmd) {
cmds = append(cmds, m.persistConversation())
}
if m.App.Conversation.Title == "" {
if m.App.Conversation.Title == "" && len(m.App.Messages) > 0 {
cmds = append(cmds, m.generateConversationTitle())
}
m.updateContent()
case msgChatResponseCanceled:
m.state = idle
m.updateContent()
@@ -194,8 +191,8 @@ func (m *Model) Update(msg tea.Msg) (shared.ViewModel, tea.Cmd) {
case msgConversationTitleGenerated:
title := string(msg)
m.App.Conversation.Title = title
if m.persistence {
cmds = append(cmds, m.updateConversationTitle(m.App.Conversation))
if m.persistence && m.App.Conversation.ID > 0 {
cmds = append(cmds, m.persistConversation())
}
case cursor.BlinkMsg:
if m.state == pendingResponse {
@@ -205,14 +202,13 @@ func (m *Model) Update(msg tea.Msg) (shared.ViewModel, tea.Cmd) {
m.updateContent()
}
case msgConversationPersisted:
m.App.Conversation = msg.conversation
m.App.Messages = msg.messages
m.App.Conversation = conversation.Conversation(msg)
cmds = append(cmds, m.persistMessages())
case msgMessagesPersisted:
m.App.Messages = msg
m.rebuildMessageCache()
m.updateContent()
case msgMessageCloned:
if msg.Parent == nil {
m.App.Conversation = msg.Conversation
}
cmds = append(cmds, m.loadConversationMessages())
case msgSelectedRootCycled, msgSelectedReplyCycled, msgMessageUpdated:
cmds = append(cmds, m.loadConversationMessages())