helikon

Von $1

    Inhaltsverzeichnis
    keine Gliederung

    Version seit 17:06, 6 Nov 2026

    zu dieser Version.

    Zurück zu Versionshistorie.

    Zeige aktuelle Version

    /* === 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');
    
    })();

     
    Use the language selection below for English Utilise le sélecteur de langue ci-dessous pour français Per l'italiano, utilizzare la selezione della lingua qui sotto Schön sprichst du deutsch :-)