fix: web_search_tool_result als Raw-JSON speichern für History-Rebuild

Problem: API 400 'web_search tool use without corresponding
web_search_tool_result block' – weil web_search_tool_result nur als
Sources-Array gespeichert wurde und in BuildHistoryFromDb kein Handler
dafür existierte. Der server_tool_use-Block war in der History, aber
der zugehörige web_search_tool_result fehlte.

Backend (AnthropicService):
- 3 Speicher-Stellen (StreamChat, RunAgentChat, ChatNonStreaming):
  Raw-JSON statt ExtractWebSearchSources-Array speichern

Backend (ChatService):
- Neuer Handler für web_search_result in BuildHistoryFromDb:
  Raw-JSON als web_search_tool_result in assistant content einfügen
- Rückwärtskompatibilität: Alte Array-Einträge überspringen
- CleanOrphanedWebSearchBlocks(): Post-Processing entfernt
  orphaned server_tool_use mit name web_search (alte DB-Einträge)

Frontend (history.js, shared-page.js):
- _extractWebSearchSources(): Unterstützt altes Array-Format und
  neues Raw-JSON Format (content[].type === web_search_result)
This commit is contained in:
Meleki committed 2026-03-10 11:34:43 +01:00
1 parent 6499864f13
commit 3153cb6c6b
4 files changed
+142 -36

No files matched your search

+21 -30
View File
@@ -161,16 +161,13 @@ public class AnthropicService
}
else if (blockType == "web_search_tool_result")
{
var sources = ExtractWebSearchSources(el);
if (sources.Count > 0)
// Raw-JSON speichern für History-Rebuild (API braucht den vollständigen Block)
await _db.SaveMessage(new MessageRecord
{
await _db.SaveMessage(new MessageRecord
{
ChainId = chainId, Iteration = iterations,
Role = "assistant", Type = "web_search_result",
Content = JsonSerializer.Serialize(sources)
});
}
ChainId = chainId, Iteration = iterations,
Role = "assistant", Type = "web_search_result",
Content = el.GetRawText()
});
}
else if (blockType.EndsWith("_tool_result"))
{
@@ -838,19 +835,16 @@ public class AnthropicService
else if (blockType == "web_search_tool_result")
{
assistantContent.Add(JsonSerializer.Deserialize<JsonElement>(block.GetRawText()));
var sources = ExtractWebSearchSources(block);
if (sources.Count > 0)
// Raw-JSON speichern für History-Rebuild (API braucht den vollständigen Block)
await _db.SaveMessage(new MessageRecord
{
await _db.SaveMessage(new MessageRecord
{
ChainId = chainId,
Iteration = baseIterations + iterations,
Role = "assistant",
Type = "web_search_result",
Content = JsonSerializer.Serialize(sources),
Tag = agentType
});
}
ChainId = chainId,
Iteration = baseIterations + iterations,
Role = "assistant",
Type = "web_search_result",
Content = block.GetRawText(),
Tag = agentType
});
}
else if (blockType == "server_tool_use")
{
@@ -1019,16 +1013,13 @@ public class AnthropicService
else if (blockType == "web_search_tool_result")
{
assistantContent.Add(JsonSerializer.Deserialize<JsonElement>(block.GetRawText()));
var sources = ExtractWebSearchSources(block);
if (sources.Count > 0)
// Raw-JSON speichern für History-Rebuild (API braucht den vollständigen Block)
await _db.SaveMessage(new MessageRecord
{
await _db.SaveMessage(new MessageRecord
{
ChainId = ctx.ChainId, Iteration = iterations,
Role = "assistant", Type = "web_search_result",
Content = JsonSerializer.Serialize(sources)
});
}
ChainId = ctx.ChainId, Iteration = iterations,
Role = "assistant", Type = "web_search_result",
Content = block.GetRawText()
});
}
else if (blockType == "server_tool_use")
{