Files
gott/wwwroot/js/history.js
T

177 lines
5.1 KiB
JavaScript

// ── History Loading ──
let lastKnownMessageId = 0;
let historyPollInterval = null;
let loadedArchiveCount = 0;
async function loadHistory() {
try {
const sid = getCurrentSessionId();
const archives = await apiListArchives(sid);
if (archives.length > 0) {
showArchiveLoadButton();
}
const data = await apiHistory(sid);
data.reverse();
for (const entry of data) {
renderMessages(entry.messages, true);
}
scrollDown();
startHistoryPolling();
} catch (e) {
console.error('History laden fehlgeschlagen:', e);
}
}
function renderMessages(msgs, addToConversation) {
for (const msg of msgs) {
if (msg.id > lastKnownMessageId) lastKnownMessageId = msg.id;
switch (msg.type) {
case 'text':
if (msg.role === 'user') {
addUserBubble(msg.content);
if (msg.attachmentCount > 0) addAttachmentIndicator(msg.id, msg.attachmentCount, msg.attachmentNames);
if (addToConversation) messages.push({ role: 'user', content: msg.content });
} else if (msg.role === 'assistant') {
addAssistantBubble(msg.content);
if (addToConversation) messages.push({ role: 'assistant', content: msg.content });
}
break;
case 'tool_use':
addToolBoxStatic(msg.toolName, msg.content, null, false);
break;
case 'tool_result':
addToolBoxStatic(null, null, msg.content, msg.isError);
break;
case 'error':
addErrorBubble(msg.content);
break;
}
}
}
// ── Archive Loading ──
function getOrCreateArchiveContainer() {
let container = chatEl().querySelector('.archive-container');
if (!container) {
container = document.createElement('div');
container.className = 'archive-container';
chatEl().prepend(container);
}
return container;
}
function getOrCreateArchiveDivider() {
let divider = chatEl().querySelector('.archive-divider');
if (!divider) {
divider = document.createElement('div');
divider.className = 'msg system-info archive-divider';
divider.textContent = '── Aktuelle Konversation ──';
// Nach dem Container, vor den aktiven Messages
const container = getOrCreateArchiveContainer();
container.after(divider);
}
return divider;
}
async function loadLatestArchive() {
try {
const archives = await apiListArchives(getCurrentSessionId());
if (archives.length <= loadedArchiveCount) return;
const latest = archives[loadedArchiveCount];
loadedArchiveCount++;
removeArchiveLoadButton();
const data = await apiGetArchive(latest.archiveId);
const container = getOrCreateArchiveContainer();
getOrCreateArchiveDivider();
// Archiv-Block zusammenbauen
const fragment = document.createDocumentFragment();
const sep = document.createElement('div');
sep.className = 'msg system-info';
sep.textContent = `📦 Archiv vom ${new Date(latest.createdAt).toLocaleString('de-AT')} (${latest.chainCount} Chains, ${latest.messageCount} Messages)`;
fragment.appendChild(sep);
for (const entry of data) {
for (const msg of entry.messages) {
const div = document.createElement('div');
switch (msg.type) {
case 'text':
div.className = msg.role === 'user' ? 'msg user archived' : 'msg assistant archived';
div.textContent = msg.content;
break;
case 'tool_use':
div.className = 'tool-box archived';
div.innerHTML = '<span class="tool-name">' + esc(msg.toolName) + '</span>'
+ '<span class="tool-input">' + esc(truncate(msg.content, 120)) + '</span>';
break;
case 'tool_result':
div.className = 'tool-box archived';
div.innerHTML = '<div class="tool-result ' + (msg.isError ? 'tool-error' : '') + '">'
+ esc(truncate(msg.content, 300)) + '</div>';
break;
case 'error':
div.className = 'msg system-info archived';
div.style.color = '#ff6b6b';
div.textContent = msg.content;
break;
default:
continue;
}
fragment.appendChild(div);
}
}
// Älteres Archiv vor dem bisherigen Inhalt einfügen
container.prepend(fragment);
// Button ganz oben, falls es noch ältere Archive gibt
if (archives.length > loadedArchiveCount) {
showArchiveLoadButton();
}
} catch (e) {
console.error('Archiv laden fehlgeschlagen:', e);
}
}
// ── Polling ──
function startHistoryPolling(intervalMs = 3000) {
if (historyPollInterval) return;
historyPollInterval = setInterval(pollHistory, intervalMs);
}
function stopHistoryPolling() {
if (historyPollInterval) {
clearInterval(historyPollInterval);
historyPollInterval = null;
}
}
async function pollHistory() {
if (isStreaming) return;
try {
const newMessages = await apiHistoryPoll(getCurrentSessionId(), lastKnownMessageId);
if (newMessages.length > 0) {
renderMessages(newMessages, true);
scrollDown();
}
} catch (e) {
console.error('History poll fehlgeschlagen:', e);
}
}