feat: Gemini thought_signature korrekt lesen und zurücksenden

- thought_signature aus delta.tool_calls[n].extra_content.google.thought_signature lesen (korrekter Pfad)
- ThoughtSignature-Feld in MessageRecord + DB-Migration (ALTER TABLE messages ADD COLUMN thought_signature)
- SaveMessage speichert ThoughtSignature pro Tool-Call
- OpenAiService: toolCallAccumulators Tuple um ThoughtSignature erweitert
- Tool-Calls mit thought_signature werden mit extra_content.google.thought_signature zurückgesendet (nicht function.thought_signature)
- ConvertMessage (History-Rebuild) setzt thought_signature ebenfalls korrekt
- ChatService.BuildApiMessages übergibt thought_signature aus DB-Record
- Gemini-Modelle dynamisch laden statt hardcodiert
- Tool-Call-Akkumulator nutzt id als primären Key (Gemini sendet parallele Calls ohne index)
- content=null → content='' für Gemini-Kompatibilität
This commit is contained in:
Meleki committed 2026-03-12 06:34:11 +01:00
1 parent e87455ffe9
commit 145441fa7b
6 files changed
+149 -65

No files matched your search

+7 -5
View File
@@ -362,22 +362,24 @@ Für welche Plattform soll die App entwickelt werden? Web, Mobile oder Desktop?
try { inputEl = JsonSerializer.Deserialize<JsonElement>(msg.Content ?? "{}"); }
catch { inputEl = JsonSerializer.Deserialize<JsonElement>("{}"); }
// thought_signature mitführen falls vorhanden (für Gemini-Provider)
object toolUseBlock = !string.IsNullOrEmpty(msg.ThoughtSignature)
? (object)new { type = "tool_use", id = msg.ToolCallId, name = msg.ToolName, input = inputEl, thought_signature = msg.ThoughtSignature }
: new { type = "tool_use", id = msg.ToolCallId, name = msg.ToolName, input = inputEl };
var lastAssistant = history.Count > 0 ? history[history.Count - 1] : null;
if (lastAssistant is Dictionary<string, object> dict &&
dict.TryGetValue("role", out var role) && role.ToString() == "assistant" &&
dict.TryGetValue("content", out var existingContent) && existingContent is List<object> contentList)
{
contentList.Add(new { type = "tool_use", id = msg.ToolCallId, name = msg.ToolName, input = inputEl });
contentList.Add(toolUseBlock);
}
else
{
history.Add(new Dictionary<string, object>
{
["role"] = "assistant",
["content"] = new List<object>
{
new { type = "tool_use", id = msg.ToolCallId, name = msg.ToolName, input = inputEl }
}
["content"] = new List<object> { toolUseBlock }
});
}
}