diff --git a/Services/AnthropicService.cs b/Services/AnthropicService.cs index c9be2bf..da7e3a6 100644 --- a/Services/AnthropicService.cs +++ b/Services/AnthropicService.cs @@ -146,6 +146,15 @@ public class AnthropicService Content = el.GetProperty("input").ToString() }); } + else if (blockType == "server_tool_use") + { + await _db.SaveMessage(new MessageRecord + { + ChainId = chainId, Iteration = iterations, + Role = "assistant", Type = "server_tool_use", + Content = el.GetRawText() + }); + } else if (blockType == "web_search_tool_result") { var sources = ExtractWebSearchSources(el); @@ -159,6 +168,16 @@ public class AnthropicService }); } } + else if (blockType.EndsWith("_tool_result")) + { + // Generische Server-Tool-Results (bash_code_execution_tool_result, code_execution_tool_result etc.) + await _db.SaveMessage(new MessageRecord + { + ChainId = chainId, Iteration = iterations, + Role = "assistant", Type = "server_tool_result", + Content = el.GetRawText() + }); + } } // Tool Results persistieren @@ -781,6 +800,19 @@ public class AnthropicService var (toolId, toolName, inputEl) = ParseServerToolUse(block); assistantContent.Add(new { type = "server_tool_use", id = toolId, name = toolName, input = inputEl }); } + else if (blockType.EndsWith("_tool_result")) + { + // Generische Server-Tool-Results (bash_code_execution_tool_result, code_execution_tool_result etc.) + assistantContent.Add(JsonSerializer.Deserialize(block.GetRawText())); + await _db.SaveMessage(new MessageRecord + { + ChainId = chainId, + Iteration = baseIterations + iterations, + Role = "assistant", Type = "server_tool_result", + Content = block.GetRawText(), + Tag = agentType + }); + } } messages.Add(new Dictionary { ["role"] = "assistant", ["content"] = assistantContent }); @@ -945,6 +977,17 @@ public class AnthropicService var (toolId, toolName, inputEl) = ParseServerToolUse(block); assistantContent.Add(new { type = "server_tool_use", id = toolId, name = toolName, input = inputEl }); } + else if (blockType.EndsWith("_tool_result")) + { + // Generische Server-Tool-Results (bash_code_execution_tool_result, code_execution_tool_result etc.) + assistantContent.Add(JsonSerializer.Deserialize(block.GetRawText())); + await _db.SaveMessage(new MessageRecord + { + ChainId = ctx.ChainId, Iteration = iterations, + Role = "assistant", Type = "server_tool_result", + Content = block.GetRawText() + }); + } } messages.Add(new Dictionary { ["role"] = "assistant", ["content"] = assistantContent }); @@ -1028,6 +1071,7 @@ public class AnthropicService var blockTypes = new Dictionary(); var webSearchResultBlocks = new Dictionary(); var webSearchSources = new Dictionary>(); + var serverToolResultBlocks = new Dictionary(); // bash_code_execution_tool_result, code_execution_tool_result etc. var executedTools = new List(); var streamErrors = new List(); @@ -1096,6 +1140,11 @@ public class AnthropicService webSearchResultBlocks[idx] = rawBlock; webSearchSources[idx] = ExtractWebSearchSources(cb); } + else if (cbType.EndsWith("_tool_result")) + { + // Generische Server-Tool-Results (bash_code_execution_tool_result, code_execution_tool_result etc.) + serverToolResultBlocks[idx] = JsonSerializer.Deserialize(cb.GetRawText()); + } break; } @@ -1221,6 +1270,11 @@ public class AnthropicService var sources = webSearchSources.TryGetValue(idx, out var s) ? s : new List(); await WriteSseEvent(response, "web_search_end", new { id = currentToolId, sources }, cancellationToken); } + else if (bt.EndsWith("_tool_result") && serverToolResultBlocks.TryGetValue(idx, out var srvResultBlock)) + { + // Generische Server-Tool-Results (bash_code_execution_tool_result, code_execution_tool_result etc.) + assistantContent.Add(srvResultBlock); + } } break; } diff --git a/Services/ChatService.cs b/Services/ChatService.cs index 82a77bb..19bb2d5 100644 --- a/Services/ChatService.cs +++ b/Services/ChatService.cs @@ -363,6 +363,53 @@ Für welche Plattform soll die App entwickelt werden? Web, Mobile oder Desktop? }); } } + else if (msg.Role == "assistant" && msg.Type == "server_tool_use") + { + // Server-Tool-Use (web_search, code_execution etc.) – Raw-JSON in Assistant-Content + JsonElement useEl; + try { useEl = JsonSerializer.Deserialize(msg.Content ?? "{}"); } + catch { continue; } + + var lastAssistant = history.Count > 0 ? history[history.Count - 1] : null; + if (lastAssistant is Dictionary dict && + dict.TryGetValue("role", out var role) && role.ToString() == "assistant" && + dict.TryGetValue("content", out var existingContent) && existingContent is List contentList) + { + contentList.Add(useEl); + } + else + { + history.Add(new Dictionary + { + ["role"] = "assistant", + ["content"] = new List { useEl } + }); + } + } + else if (msg.Role == "assistant" && msg.Type == "server_tool_result") + { + // Server-Tool-Results (bash_code_execution_tool_result, code_execution_tool_result etc.) + // werden als Raw-JSON in den Assistant-Content-Block eingefügt + JsonElement resultEl; + try { resultEl = JsonSerializer.Deserialize(msg.Content ?? "{}"); } + catch { continue; } + + var lastAssistant = history.Count > 0 ? history[history.Count - 1] : null; + if (lastAssistant is Dictionary dict && + dict.TryGetValue("role", out var role) && role.ToString() == "assistant" && + dict.TryGetValue("content", out var existingContent) && existingContent is List contentList) + { + contentList.Add(resultEl); + } + else + { + history.Add(new Dictionary + { + ["role"] = "assistant", + ["content"] = new List { resultEl } + }); + } + } else if (msg.Role == "user" && msg.Type == "tool_result") { var lastUser = history.Count > 0 ? history[history.Count - 1] : null;