waveterm/pkg/aiusechat/usechat-utils.go
Mike Sawka cd6389d1ec
Create Interface for Backend AI Providers (#2572)
Created an interface in aiusechat for the backend providers. Use that
interface throughout the usechat code. Isolate the backend
implementations to only the new file usechat-backend.go.
2025-11-19 11:38:56 -08:00

85 lines
2.3 KiB
Go

// Copyright 2025, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package aiusechat
import (
"github.com/wavetermdev/waveterm/pkg/aiusechat/uctypes"
)
// CombineConsecutiveSameRoleMessages combines consecutive UIMessages with the same role
// by appending their Parts together. This is useful for APIs like OpenAI that may split
// assistant messages into separate messages (e.g., one for text and one for tool calls).
func CombineConsecutiveSameRoleMessages(uiChat *uctypes.UIChat) *uctypes.UIChat {
if uiChat == nil || len(uiChat.Messages) == 0 {
return uiChat
}
combined := make([]uctypes.UIMessage, 0, len(uiChat.Messages))
var current *uctypes.UIMessage
for i := range uiChat.Messages {
msg := &uiChat.Messages[i]
if current == nil {
// First message - start a new combined message
current = &uctypes.UIMessage{
ID: msg.ID,
Role: msg.Role,
Metadata: msg.Metadata,
Parts: make([]uctypes.UIMessagePart, len(msg.Parts)),
}
copy(current.Parts, msg.Parts)
continue
}
if current.Role == msg.Role {
// Same role - append parts to current message
current.Parts = append(current.Parts, msg.Parts...)
} else {
// Different role - save current and start new
combined = append(combined, *current)
current = &uctypes.UIMessage{
ID: msg.ID,
Role: msg.Role,
Metadata: msg.Metadata,
Parts: make([]uctypes.UIMessagePart, len(msg.Parts)),
}
copy(current.Parts, msg.Parts)
}
}
// Don't forget the last message
if current != nil {
combined = append(combined, *current)
}
return &uctypes.UIChat{
ChatId: uiChat.ChatId,
APIType: uiChat.APIType,
Model: uiChat.Model,
APIVersion: uiChat.APIVersion,
Messages: combined,
}
}
// ConvertAIChatToUIChat converts an AIChat to a UIChat by routing to the appropriate
// provider-specific converter based on APIType, then combining consecutive same-role messages.
func ConvertAIChatToUIChat(aiChat *uctypes.AIChat) (*uctypes.UIChat, error) {
if aiChat == nil {
return nil, nil
}
backend, err := GetBackendByAPIType(aiChat.APIType)
if err != nil {
return nil, err
}
uiChat, err := backend.ConvertAIChatToUIChat(*aiChat)
if err != nil {
return nil, err
}
return CombineConsecutiveSameRoleMessages(uiChat), nil
}