Fix: text manipulation for multimodal messages
This commit is contained in:
11
bot.go
11
bot.go
@@ -119,7 +119,7 @@ func processMessageTag(msg *models.RoleMsg) *models.RoleMsg {
|
||||
}
|
||||
// If KnownTo already set, assume tag already processed (content cleaned).
|
||||
// However, we still check for new tags (maybe added later).
|
||||
knownTo := parseKnownToTag(msg.Content)
|
||||
knownTo := parseKnownToTag(msg.GetText())
|
||||
// If tag found, replace KnownTo with new list (merge with existing?)
|
||||
// For simplicity, if knownTo is not nil, replace.
|
||||
if knownTo == nil {
|
||||
@@ -1303,12 +1303,9 @@ func removeThinking(chatBody *models.ChatBody) {
|
||||
if msg.Role == cfg.ToolRole {
|
||||
continue
|
||||
}
|
||||
// find thinking and remove it
|
||||
rm := models.RoleMsg{
|
||||
Role: msg.Role,
|
||||
Content: thinkRE.ReplaceAllString(msg.Content, ""),
|
||||
}
|
||||
msgs = append(msgs, rm)
|
||||
// find thinking and remove it - use SetText to preserve ContentParts
|
||||
msg.SetText(thinkRE.ReplaceAllString(msg.GetText(), ""))
|
||||
msgs = append(msgs, msg)
|
||||
}
|
||||
chatBody.Messages = msgs
|
||||
}
|
||||
|
||||
11
helpfuncs.go
11
helpfuncs.go
@@ -75,15 +75,16 @@ func stripThinkingFromMsg(msg *models.RoleMsg) *models.RoleMsg {
|
||||
if !cfg.StripThinkingFromAPI {
|
||||
return msg
|
||||
}
|
||||
// Skip user, tool, and system messages - they might contain thinking examples
|
||||
// Skip user, tool, they might contain thinking and system messages - examples
|
||||
if msg.Role == cfg.UserRole || msg.Role == cfg.ToolRole || msg.Role == "system" {
|
||||
return msg
|
||||
}
|
||||
// Strip thinking from assistant messages
|
||||
if thinkRE.MatchString(msg.Content) {
|
||||
msg.Content = thinkRE.ReplaceAllString(msg.Content, "")
|
||||
// Clean up any double newlines that might result
|
||||
msg.Content = strings.TrimSpace(msg.Content)
|
||||
msgText := msg.GetText()
|
||||
if thinkRE.MatchString(msgText) {
|
||||
cleanedText := thinkRE.ReplaceAllString(msgText, "")
|
||||
cleanedText = strings.TrimSpace(cleanedText)
|
||||
msg.SetText(cleanedText)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
@@ -329,6 +329,66 @@ func (m *RoleMsg) Copy() RoleMsg {
|
||||
}
|
||||
}
|
||||
|
||||
// GetText returns the text content of the message, handling both
|
||||
// simple Content and multimodal ContentParts formats.
|
||||
func (m *RoleMsg) GetText() string {
|
||||
if !m.hasContentParts {
|
||||
return m.Content
|
||||
}
|
||||
var textParts []string
|
||||
for _, part := range m.ContentParts {
|
||||
switch p := part.(type) {
|
||||
case TextContentPart:
|
||||
if p.Type == "text" {
|
||||
textParts = append(textParts, p.Text)
|
||||
}
|
||||
case map[string]any:
|
||||
if partType, exists := p["type"]; exists {
|
||||
if partType == "text" {
|
||||
if textVal, textExists := p["text"]; textExists {
|
||||
if textStr, isStr := textVal.(string); isStr {
|
||||
textParts = append(textParts, textStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.Join(textParts, " ")
|
||||
}
|
||||
|
||||
// SetText updates the text content of the message. If the message has
|
||||
// ContentParts (multimodal), it updates the text parts while preserving
|
||||
// images. If not, it sets the simple Content field.
|
||||
func (m *RoleMsg) SetText(text string) {
|
||||
if !m.hasContentParts {
|
||||
m.Content = text
|
||||
return
|
||||
}
|
||||
var newParts []any
|
||||
for _, part := range m.ContentParts {
|
||||
switch p := part.(type) {
|
||||
case TextContentPart:
|
||||
if p.Type == "text" {
|
||||
p.Text = text
|
||||
newParts = append(newParts, p)
|
||||
} else {
|
||||
newParts = append(newParts, p)
|
||||
}
|
||||
case map[string]any:
|
||||
if partType, exists := p["type"]; exists && partType == "text" {
|
||||
p["text"] = text
|
||||
newParts = append(newParts, p)
|
||||
} else {
|
||||
newParts = append(newParts, p)
|
||||
}
|
||||
default:
|
||||
newParts = append(newParts, part)
|
||||
}
|
||||
}
|
||||
m.ContentParts = newParts
|
||||
}
|
||||
|
||||
// AddTextPart adds a text content part to the message
|
||||
func (m *RoleMsg) AddTextPart(text string) {
|
||||
if !m.hasContentParts {
|
||||
|
||||
20
tui.go
20
tui.go
@@ -264,7 +264,7 @@ func init() {
|
||||
pages.RemovePage(editMsgPage)
|
||||
return nil
|
||||
}
|
||||
chatBody.Messages[selectedIndex].Content = editedMsg
|
||||
chatBody.Messages[selectedIndex].SetText(editedMsg)
|
||||
// change textarea
|
||||
textView.SetText(chatToText(chatBody.Messages, cfg.ShowSys))
|
||||
pages.RemovePage(editMsgPage)
|
||||
@@ -352,13 +352,14 @@ func init() {
|
||||
case editMode:
|
||||
hideIndexBar() // Hide overlay first
|
||||
pages.AddPage(editMsgPage, editArea, true, true)
|
||||
editArea.SetText(m.Content, true)
|
||||
editArea.SetText(m.GetText(), true)
|
||||
default:
|
||||
if err := copyToClipboard(m.Content); err != nil {
|
||||
msgText := m.GetText()
|
||||
if err := copyToClipboard(msgText); err != nil {
|
||||
logger.Error("failed to copy to clipboard", "error", err)
|
||||
}
|
||||
previewLen := min(30, len(m.Content))
|
||||
notification := fmt.Sprintf("msg '%s' was copied to the clipboard", m.Content[:previewLen])
|
||||
previewLen := min(30, len(msgText))
|
||||
notification := fmt.Sprintf("msg '%s' was copied to the clipboard", msgText[:previewLen])
|
||||
if err := notifyUser("copied", notification); err != nil {
|
||||
logger.Error("failed to send notification", "error", err)
|
||||
}
|
||||
@@ -648,11 +649,12 @@ func init() {
|
||||
// copy msg to clipboard
|
||||
editMode = false
|
||||
m := chatBody.Messages[len(chatBody.Messages)-1]
|
||||
if err := copyToClipboard(m.Content); err != nil {
|
||||
msgText := m.GetText()
|
||||
if err := copyToClipboard(msgText); err != nil {
|
||||
logger.Error("failed to copy to clipboard", "error", err)
|
||||
}
|
||||
previewLen := min(30, len(m.Content))
|
||||
notification := fmt.Sprintf("msg '%s' was copied to the clipboard", m.Content[:previewLen])
|
||||
previewLen := min(30, len(msgText))
|
||||
notification := fmt.Sprintf("msg '%s' was copied to the clipboard", msgText[:previewLen])
|
||||
if err := notifyUser("copied", notification); err != nil {
|
||||
logger.Error("failed to send notification", "error", err)
|
||||
}
|
||||
@@ -847,7 +849,7 @@ func init() {
|
||||
// Stop any currently playing TTS first
|
||||
TTSDoneChan <- true
|
||||
lastMsg := chatBody.Messages[len(chatBody.Messages)-1]
|
||||
cleanedText := models.CleanText(lastMsg.Content)
|
||||
cleanedText := models.CleanText(lastMsg.GetText())
|
||||
if cleanedText != "" {
|
||||
// nolint: errcheck
|
||||
go orator.Speak(cleanedText)
|
||||
|
||||
Reference in New Issue
Block a user