Files
Memoh/internal/conversation/uimessage.go
T
2026-04-10 16:44:44 +08:00

97 lines
3.3 KiB
Go

package conversation
import (
"strings"
"time"
)
// UIMessageType identifies the frontend-friendly message block type.
type UIMessageType string
const (
UIMessageText UIMessageType = "text"
UIMessageReasoning UIMessageType = "reasoning"
UIMessageTool UIMessageType = "tool"
UIMessageAttachments UIMessageType = "attachments"
)
// UIAttachment is the normalized attachment shape used by the web frontend.
type UIAttachment struct {
ID string `json:"id,omitempty"`
Type string `json:"type"`
Path string `json:"path,omitempty"`
URL string `json:"url,omitempty"`
Base64 string `json:"base64,omitempty"`
Name string `json:"name,omitempty"`
ContentHash string `json:"content_hash,omitempty"`
BotID string `json:"bot_id,omitempty"`
Mime string `json:"mime,omitempty"`
Size int64 `json:"size,omitempty"`
StorageKey string `json:"storage_key,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
// UIMessage is the normalized assistant output block used by the web frontend.
type UIMessage struct {
ID int `json:"id"`
Type UIMessageType `json:"type"`
Content string `json:"content,omitempty"`
Name string `json:"name,omitempty"`
Input any `json:"input,omitempty"`
Output any `json:"output,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
Running *bool `json:"running,omitempty"`
Progress []any `json:"progress,omitempty"`
Attachments []UIAttachment `json:"attachments,omitempty"`
}
// UITurn is the normalized chat turn used by the web frontend.
type UITurn struct {
Role string `json:"role"`
Messages []UIMessage `json:"messages,omitempty"`
Text string `json:"text,omitempty"`
Attachments []UIAttachment `json:"attachments,omitempty"`
Timestamp time.Time `json:"timestamp"`
Platform string `json:"platform,omitempty"`
SenderDisplayName string `json:"sender_display_name,omitempty"`
SenderAvatarURL string `json:"sender_avatar_url,omitempty"`
SenderUserID string `json:"sender_user_id,omitempty"`
ID string `json:"id,omitempty"`
}
// UIMessageStreamEvent is the generic event shape accepted by the UI stream converter.
// The handler layer adapts agent/channel events to this struct to avoid package cycles.
type UIMessageStreamEvent struct {
Type string
Delta string
ToolName string
ToolCallID string
Input any
Output any
Progress any
Attachments []UIAttachment
Error string
}
func uiBoolPtr(v bool) *bool {
return &v
}
func normalizeUIAttachmentType(kind, mime string) string {
if trimmed := strings.ToLower(strings.TrimSpace(kind)); trimmed != "" {
return trimmed
}
normalizedMime := strings.ToLower(strings.TrimSpace(mime))
switch {
case strings.HasPrefix(normalizedMime, "image/"):
return "image"
case strings.HasPrefix(normalizedMime, "audio/"):
return "audio"
case strings.HasPrefix(normalizedMime, "video/"):
return "video"
default:
return "file"
}
}