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

+25 -4
View File
@@ -1,3 +1,26 @@
// ── Web Search Sources Extraction ──
// Unterstützt zwei Formate:
// - Alt: JSON-Array von {url, title} (nur Sources)
// - Neu: Raw web_search_tool_result JSON (content[].type === 'web_search_result')
function _extractWebSearchSources(content) {
try {
var parsed = JSON.parse(content || '[]');
// Altes Format: direktes Array von Sources
if (Array.isArray(parsed)) return parsed;
// Neues Format: Raw web_search_tool_result mit content-Array
if (parsed.content && Array.isArray(parsed.content)) {
var sources = [];
parsed.content.forEach(function(item) {
if (item.type === 'web_search_result' && item.url) {
sources.push({ url: item.url, title: item.title || '' });
}
});
return sources;
}
return [];
} catch(e) { return []; }
}
// ── Image Attachments Auto-Loading ──
async function _autoLoadImageAttachments(messageId) {
@@ -246,8 +269,7 @@ function _renderMessagesIntoFragment(fragment, msgs, imageMessageIds, opts) {
break;
case 'web_search_result': {
if (!isToolVisible('web_search')) continue;
var wsSources = [];
try { wsSources = JSON.parse(msg.content || '[]'); } catch(e) {}
var wsSources = _extractWebSearchSources(msg.content);
if (wsSources.length === 0) continue;
var wsDiv = document.createElement('div');
wsDiv.className = 'tool-box' + (archived ? ' archived' : '');
@@ -350,8 +372,7 @@ function _renderReviewGroup(tagGroup, archived) {
} else if (m.type === 'web_search_result') {
if (!isToolVisible('web_search')) continue;
flushText();
var wsSources = [];
try { wsSources = JSON.parse(m.content || '[]'); } catch(e) {}
var wsSources = _extractWebSearchSources(m.content);
if (wsSources.length > 0) {
var wsDiv = document.createElement('div');
wsDiv.className = 'tool-box review-tool-box' + (archived ? ' archived' : '');
+1 -2
View File
@@ -29,8 +29,7 @@ registerPage('shared', {
// Web-Search-Results als Tool-Box mit Sources rendern
if (msg.type === 'web_search_result') {
var wsSources = [];
try { wsSources = JSON.parse(c || '[]'); } catch(e) {}
var wsSources = _extractWebSearchSources(c);
if (wsSources.length === 0) continue;
const div = document.createElement('div');
div.className = 'tool-box';