diff --git a/diagnostic/index.html b/diagnostic/index.html index 7174fc5..63fc182 100644 --- a/diagnostic/index.html +++ b/diagnostic/index.html @@ -1098,9 +1098,17 @@ chatBox.innerHTML = ''; if (msg.messages && msg.messages.length > 0) { for (const m of msg.messages) { + if (m.type === 'aria_file') { + // ARIA-Datei-Bubble rekonstruieren (statt addAriaFile damit + // kein Auto-Scroll-Race waehrend des Bulk-Loads) + addAriaFile({ serverPath: m.serverPath, name: m.name, mimeType: m.mimeType, size: m.size }); + continue; + } const el = document.createElement('div'); el.className = `chat-msg ${m.type}`; - const escaped = escapeHtml(m.text); + // [FILE: ...]-Marker rausfiltern (gleicher Filter wie addChat) + const cleaned = (m.text || '').replace(/\[FILE:\s*\/shared\/uploads\/[^\]]+\]/gi, '').replace(/\n{3,}/g, '\n\n').trim(); + const escaped = escapeHtml(cleaned); const linked = linkifyText(escaped); const time = m.ts ? new Date(m.ts).toLocaleTimeString('de-DE') : '?'; el.innerHTML = `${linked}
`; diff --git a/diagnostic/server.js b/diagnostic/server.js index 6136c91..85fcd6b 100644 --- a/diagnostic/server.js +++ b/diagnostic/server.js @@ -2231,7 +2231,35 @@ async function handleLoadChatHistory(clientWs) { } else if (role === "assistant") { // Reply-Prefix entfernen: "[[reply_to_current]] " text = text.replace(/^\[\[reply_to_\w+\]\]\s*/g, "").trim(); - if (text) chatMessages.push({ type: "received", text, meta: "chat:final", ts: msg.timestamp || obj.timestamp || 0 }); + const ts = msg.timestamp || obj.timestamp || 0; + // ARIA-File-Marker aus dem Text parsen — pro existierender Datei + // eine separate file_from_aria-aehnliche Message einfuegen damit die + // Anhang-Bubble nach Browser-Refresh wieder erscheint. + const fileRe = /\[FILE:\s*(\/shared\/uploads\/[^\]]+?)\s*\]/gi; + let m; + while ((m = fileRe.exec(text)) !== null) { + const p = m[1].trim(); + try { + if (fs.existsSync(p)) { + const st = fs.statSync(p); + const ext = path.extname(p).toLowerCase(); + const mimeMap = { ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png", ".gif": "image/gif", + ".webp": "image/webp", ".svg": "image/svg+xml", ".pdf": "application/pdf", + ".mp3": "audio/mpeg", ".mid": "audio/midi", ".midi": "audio/midi", + ".wav": "audio/wav", ".txt": "text/plain", ".md": "text/markdown", + ".json": "application/json", ".zip": "application/zip" }; + chatMessages.push({ + type: "aria_file", + serverPath: p, + name: path.basename(p), + mimeType: mimeMap[ext] || "application/octet-stream", + size: st.size, + ts, + }); + } + } catch {} + } + if (text) chatMessages.push({ type: "received", text, meta: "chat:final", ts }); } } catch {} }