fix: server_tool_use/result (bash_code_execution) korrekt verarbeiten
- server_tool_use-Blöcke werden jetzt in DB persistiert und in History-Rekonstruktion als Raw-JSON eingefügt - Generische *_tool_result-Behandlung (bash_code_execution_tool_result, code_execution_tool_result etc.) in allen drei Chat-Pfaden: StreamChat, ChatNonStreaming, RunAgentChat - ProcessStream: serverToolResultBlocks analog zu webSearchResultBlocks - BuildHistoryFromDb: server_tool_use + server_tool_result werden korrekt in Assistant-Content-Array rekonstruiert - Behebt API 400: tool_use without corresponding tool_result
This commit is contained in:
1 parent
5d090e160b
commit
fb9ff23ad4
2 files changed
+101
No files matched your search
@@ -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<JsonElement>(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<string, object> { ["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<JsonElement>(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<string, object> { ["role"] = "assistant", ["content"] = assistantContent });
|
||||
@@ -1028,6 +1071,7 @@ public class AnthropicService
|
||||
var blockTypes = new Dictionary<int, string>();
|
||||
var webSearchResultBlocks = new Dictionary<int, object>();
|
||||
var webSearchSources = new Dictionary<int, List<object>>();
|
||||
var serverToolResultBlocks = new Dictionary<int, object>(); // bash_code_execution_tool_result, code_execution_tool_result etc.
|
||||
var executedTools = new List<ToolResult>();
|
||||
var streamErrors = new List<object>();
|
||||
|
||||
@@ -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<JsonElement>(cb.GetRawText());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1221,6 +1270,11 @@ public class AnthropicService
|
||||
var sources = webSearchSources.TryGetValue(idx, out var s) ? s : new List<object>();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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<JsonElement>(msg.Content ?? "{}"); }
|
||||
catch { continue; }
|
||||
|
||||
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(useEl);
|
||||
}
|
||||
else
|
||||
{
|
||||
history.Add(new Dictionary<string, object>
|
||||
{
|
||||
["role"] = "assistant",
|
||||
["content"] = new List<object> { 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<JsonElement>(msg.Content ?? "{}"); }
|
||||
catch { continue; }
|
||||
|
||||
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(resultEl);
|
||||
}
|
||||
else
|
||||
{
|
||||
history.Add(new Dictionary<string, object>
|
||||
{
|
||||
["role"] = "assistant",
|
||||
["content"] = new List<object> { resultEl }
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (msg.Role == "user" && msg.Type == "tool_result")
|
||||
{
|
||||
var lastUser = history.Count > 0 ? history[history.Count - 1] : null;
|
||||
|
||||
Reference in new issue
Block a user