Inhaltsverzeichnis
keine Gliederung/* === BUDDY CHAT PAGE - LIGHT === */
#serverBuddy { display: none !important; }
#buddySpeech { display: none !important; }
#buddyChat {
max-width: 700px;
margin: 40px auto;
font-family: 'Courier New', Courier, monospace;
color: #333;
}
#buddyChatAvatar {
text-align: center;
margin-bottom: 20px;
}
#buddyChatAvatar img {
width: 192px;
height: 192px;
image-rendering: pixelated;
image-rendering: crisp-edges;
display: inline-block;
border: none;
}
#chatLog {
min-height: 200px;
max-height: 400px;
overflow-y: auto;
padding: 16px;
margin-bottom: 16px;
border: 2px solid #ccc;
background: #f8f8f8;
}
.chatMsg {
margin-bottom: 12px;
padding: 10px 14px;
border-radius: 8px;
font-size: 13px;
line-height: 1.5;
max-width: 85%;
word-wrap: break-word;
}
.chatMsg.user {
background: #e8e8e8;
color: #555;
margin-left: auto;
text-align: right;
border: 1px solid #ddd;
}
.chatMsg.buddy {
background: #fff;
color: #333;
margin-right: auto;
border: 1px solid #ccc;
}
.chatMsg.buddy::before {
content: '>';
color: #0077aa;
margin-right: 6px;
opacity: 0.6;
}
.chatMsg.system {
color: #999;
font-size: 11px;
text-align: center;
margin: 8px auto;
max-width: 100%;
}
.chatMsg.typing {
color: #999;
opacity: 0.6;
}
#chatInputWrap {
display: flex;
gap: 8px;
border: 2px solid #ccc;
background: #f8f8f8;
padding: 8px;
}
#chatInput {
flex: 1;
background: #fff;
border: 1px solid #ccc;
color: #333;
font-family: 'Courier New', Courier, monospace;
font-size: 14px;
padding: 10px 12px;
outline: none;
}
#chatInput::placeholder {
color: #aaa;
}
#chatInput:focus {
border-color: #0077aa;
}
#chatSend {
background: #fff;
color: #0077aa;
border: 1px solid #0077aa;
padding: 10px 20px;
font-family: 'Courier New', Courier, monospace;
font-size: 14px;
cursor: pointer;
}
#chatSend:hover {
background: #0077aa;
color: #fff;
}
#chatSend:disabled {
opacity: 0.3;
cursor: default;
}
#chatStatus {
font-size: 11px;
color: #999;
margin-top: 8px;
text-align: right;
}
(function() {
var API_URL = '/api/v1/chat/completions';
var API_KEY = '';
var MODEL = 'default';
var SYS_MSG = 'Du bist Server Buddy, ein freundlicher IT-Assistent. Antworte kurz und hilfreich.';
var log = document.getElementById('chatLog');
var input = document.getElementById('chatInput');
var btn = document.getElementById('chatSend');
var status = document.getElementById('chatStatus');
var avatar = document.getElementById('buddyChatImg');
if (!log || !input || !btn) return;
log.innerHTML = '';
var GIFS = new Object();
GIFS.idle = '/@api/deki/files/403/=buddy_idle.gif';
GIFS.sleep = '/@api/deki/files/402/=buddy_sleeping.gif';
GIFS.happy = '/@api/deki/files/401/=buddy_happy.gif';
GIFS.error = '/@api/deki/files/400/=buddy_error.gif';
GIFS.loading = '/@api/deki/files/399/=buddy_loading.gif';
var history = [];
var busy = false;
function setGif(name) {
if (avatar) avatar.src = GIFS[name] || GIFS.idle;
}
function addMsg(text, cls) {
var div = document.createElement('div');
div.className = 'chatMsg ' + cls;
div.textContent = text;
log.appendChild(div);
log.scrollTop = log.scrollHeight;
return div;
}
function setStatus(txt) {
if (status) status.textContent = txt || '';
}
function send() {
var msg = input.value.replace(/^\s+|\s+$/g, '');
if (!msg || busy) return;
addMsg(msg, 'user');
input.value = '';
history.push({ role: 'user', content: msg });
busy = true;
btn.disabled = true;
setGif('loading');
setStatus('denkt nach...');
var typing = addMsg('...', 'buddy typing');
var messages = [{ role: 'system', content: SYS_MSG }];
var i;
for (i = 0; i < history.length; i++) {
messages.push(history[i]);
}
var headers = { 'Content-Type': 'application/json' };
if (API_KEY) headers['Authorization'] = 'Bearer ' + API_KEY;
var body = JSON.stringify({
model: MODEL,
messages: messages,
max_tokens: 500
});
var xhr = new XMLHttpRequest();
xhr.open('POST', API_URL, true);
var key;
for (key in headers) {
if (headers.hasOwnProperty(key)) {
xhr.setRequestHeader(key, headers[key]);
}
}
xhr.onload = function() {
log.removeChild(typing);
if (xhr.status === 200) {
try {
var data = JSON.parse(xhr.responseText);
var reply = data.choices[0].message.content;
history.push({ role: 'assistant', content: reply });
addMsg(reply, 'buddy');
setGif('happy');
setTimeout(function() { setGif('idle'); }, 3000);
setStatus('');
} catch (e) {
addMsg('Fehler beim Parsen der Antwort.', 'system');
setGif('error');
setTimeout(function() { setGif('idle'); }, 4000);
setStatus('Parse-Fehler');
}
} else {
addMsg('Fehler: ' + xhr.status + ' ' + xhr.statusText, 'system');
setGif('error');
setTimeout(function() { setGif('idle'); }, 4000);
setStatus('API-Fehler ' + xhr.status);
}
busy = false;
btn.disabled = false;
input.focus();
};
xhr.onerror = function() {
log.removeChild(typing);
addMsg('Verbindungsfehler. API nicht erreichbar.', 'system');
setGif('error');
setTimeout(function() { setGif('idle'); }, 4000);
setStatus('Nicht erreichbar');
busy = false;
btn.disabled = false;
};
xhr.send(body);
}
btn.addEventListener('click', send);
input.addEventListener('keydown', function(e) {
if (e.keyCode === 13) send();
});
addMsg('Hallo! Wie kann ich helfen?', 'buddy');
setStatus('bereit');
})();