ultisuite-backend/internal/ai/gateway_messages.go
R3D347HR4Y 621b0099d6
Some checks are pending
CI / Go tests (push) Waiting to run
CI / Integration tests (push) Waiting to run
CI / DB migrations (push) Waiting to run
feat(deploy): enhance Nginx configuration and API integration for UltiAI
- Updated .env.example to include new configuration options for the UltiAI branding and API endpoints.
- Enhanced Nginx configuration to support new API routes for the MCP and WebSocket connections.
- Introduced sub-filters for branding adjustments in Nginx responses.
- Added new JavaScript patch for API endpoint adjustments.
- Implemented tests for new API functionalities and improved error handling in the AI gateway.
2026-06-15 00:22:23 +02:00

112 lines
2.2 KiB
Go

package ai
import (
"encoding/json"
"fmt"
)
func repairChatCompletionBody(body []byte) ([]byte, error) {
var req map[string]any
if err := json.Unmarshal(body, &req); err != nil {
return body, fmt.Errorf("repair chat completion body: %w", err)
}
rawMessages, ok := req["messages"].([]any)
if !ok || len(rawMessages) == 0 {
return body, nil
}
repaired := repairToolMessages(rawMessages)
if sameMessages(rawMessages, repaired) {
return body, nil
}
req["messages"] = repaired
return json.Marshal(req)
}
func repairToolMessages(messages []any) []any {
out := make([]any, 0, len(messages)+1)
for _, raw := range messages {
msg, ok := raw.(map[string]any)
if !ok {
out = append(out, raw)
continue
}
if messageRole(msg) == "tool" && !previousMessageHasToolCalls(out) {
toolCallID := messageToolCallID(msg)
if toolCallID == "" {
toolCallID = "call_repaired"
}
out = append(out, map[string]any{
"role": "assistant",
"content": "",
"tool_calls": []any{
map[string]any{
"id": toolCallID,
"type": "function",
"function": map[string]any{
"name": "tool",
"arguments": "{}",
},
},
},
})
}
out = append(out, msg)
}
return out
}
func previousMessageHasToolCalls(messages []any) bool {
if len(messages) == 0 {
return false
}
msg, ok := messages[len(messages)-1].(map[string]any)
if !ok {
return false
}
if messageRole(msg) != "assistant" {
return false
}
toolCalls, ok := msg["tool_calls"].([]any)
return ok && len(toolCalls) > 0
}
func messageRole(msg map[string]any) string {
role, _ := msg["role"].(string)
return role
}
func messageToolCallID(msg map[string]any) string {
id, _ := msg["tool_call_id"].(string)
return id
}
func sameMessages(before, after []any) bool {
if len(before) != len(after) {
return false
}
b, err := json.Marshal(before)
if err != nil {
return false
}
a, err := json.Marshal(after)
if err != nil {
return false
}
return string(b) == string(a)
}
func chatCompletionStreamRequested(body []byte) bool {
var probe struct {
Stream *bool `json:"stream"`
}
if err := json.Unmarshal(body, &probe); err != nil {
return false
}
return probe.Stream != nil && *probe.Stream
}