Files
Meleki 3153cb6c6b 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)
2026-03-10 11:34:43 +01:00

76 lines
2.6 KiB
JavaScript

// ── Shared Message Page (öffentlich, kein Login nötig) ──
registerPage('shared', {
init: async (params) => {
const token = params.id;
const container = document.getElementById('sharedContent');
if (!token || !container) {
container.innerHTML = '<div class="shared-error"><i class="fa fa-times-circle"></i> Ungültiger Link</div>';
return;
}
try {
const data = await apiGetShared(token);
container.innerHTML = '';
let messages = [];
if (data.messages && data.messages.length > 0) {
messages = data.messages;
} else if (data.message) {
messages = [data.message];
}
// Aufeinanderfolgende Assistant-Text-Messages mergen (wie im Chat)
messages = _mergeConsecutiveAssistantTexts(messages);
for (const msg of messages) {
const c = msg.content || '';
// Web-Search-Results als Tool-Box mit Sources rendern
if (msg.type === 'web_search_result') {
var wsSources = _extractWebSearchSources(c);
if (wsSources.length === 0) continue;
const div = document.createElement('div');
div.className = 'tool-box';
div.dataset.toolName = 'web_search';
renderToolBoxContent(div, 'web_search', null, null, false, wsSources);
container.appendChild(div);
continue;
}
const isReview = _isReviewMessage(c);
const div = document.createElement('div');
if (isReview) {
div.className = 'msg review-bubble markdown' + (c.startsWith('[Finalizer:') ? ' finalizer-bubble' : '');
} else {
div.className = 'msg ' + (msg.role === 'user' ? 'user' : 'assistant') + ' markdown';
}
if (!isReview && msg.role === 'user') {
renderUserContent(div, msg.content);
} else {
div.innerHTML = renderMarkdown(c);
parseFluentEmojis(div);
wrapKreaGalleries(div);
}
container.appendChild(div);
}
// Timestamp anzeigen
if (data.createdAt) {
const meta = document.createElement('div');
meta.className = 'shared-meta';
const d = new Date(data.createdAt);
meta.innerHTML = '<i class="fa fa-clock-o"></i> Geteilt am ' + d.toLocaleDateString('de-DE') + ' um ' + d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' });
container.appendChild(meta);
}
} catch (err) {
container.innerHTML = '<div class="shared-error"><i class="fa fa-times-circle"></i> ' + esc(err.message) + '</div>';
}
},
destroy: () => {}
});
// _mergeConsecutiveTexts → replaced by _mergeConsecutiveAssistantTexts from history.js