File size: 7,496 Bytes
1ccf000
 
 
 
 
 
 
 
 
 
 
 
 
13e5b3b
 
 
2893f3c
13e5b3b
 
2893f3c
 
c61873b
13e5b3b
2893f3c
 
 
 
 
13e5b3b
2893f3c
 
13e5b3b
 
1ccf000
13e5b3b
 
 
 
 
 
 
 
 
 
 
 
 
2893f3c
 
c61873b
13e5b3b
 
 
 
 
2893f3c
13e5b3b
 
1ccf000
 
13e5b3b
 
1ccf000
13e5b3b
a665b4f
13e5b3b
a665b4f
1ccf000
13e5b3b
1ccf000
 
a665b4f
1ccf000
 
 
 
13e5b3b
1ccf000
 
a665b4f
 
13e5b3b
a665b4f
 
13e5b3b
a665b4f
13e5b3b
 
 
a665b4f
 
13e5b3b
1ccf000
 
13e5b3b
 
 
 
1ccf000
 
13e5b3b
 
a665b4f
 
13e5b3b
 
 
 
 
1ccf000
a665b4f
 
 
13e5b3b
a665b4f
 
13e5b3b
a665b4f
 
13e5b3b
 
 
 
 
 
 
 
1ccf000
13e5b3b
 
 
 
1ccf000
13e5b3b
 
 
 
 
 
a665b4f
13e5b3b
a665b4f
 
13e5b3b
 
 
 
 
 
 
 
 
 
a665b4f
13e5b3b
a665b4f
 
 
 
1ccf000
a665b4f
1ccf000
 
 
 
 
 
 
 
 
2893f3c
13e5b3b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
const chatbox = document.getElementById('chatbox');
const messageInput = document.getElementById('message-input');
const sendButton = document.getElementById('send-button');

// --- addMessage function (inchangée) ---
function addMessage(role, text) {
    const messageDiv = document.createElement('div');
    messageDiv.classList.add('message', role === 'user' ? 'user-message' : 'assistant-message');
    messageDiv.innerHTML = text.replace(/\n/g, '<br>');
    chatbox.appendChild(messageDiv);
    chatbox.scrollTop = chatbox.scrollHeight;
}

// --- processSSEBuffer function (inchangée - version Méthode 1) ---
function processSSEBuffer(buffer, targetDiv, currentResponseAccumulated) {
    console.log("Processing buffer:", buffer); // LOG AJOUTÉ
    let messages = buffer.split('\n\n');
    let incomplete = buffer.endsWith('\n\n') ? '' : messages.pop();
    let newResponsePart = '';

    messages.forEach(message => {
        if (!message.trim()) return;
        let eventType = 'message';
        let dataLines = [];
        message.split('\n').forEach(line => {
            if (line.startsWith('event: ')) {
                eventType = line.substring(7).trim();
            } else if (line.startsWith('data: ')) {
                dataLines.push(line.substring(6));
            }
        });
        let data = dataLines.join('\n');
        console.log(`--> SSE Event Parsed: ${eventType}, Data: ${data.substring(0, 100)}...`); // LOG AJOUTÉ

        if (eventType === 'message') {
            if (targetDiv.querySelector('.thinking')) {
                console.log("Replacing 'thinking' indicator"); // LOG AJOUTÉ
                targetDiv.innerHTML = '';
            }
            newResponsePart += data;
        } else if (eventType === 'end') {
            console.log("Fin de stream détectée (event: end)"); // LOG AJOUTÉ
            sendButton.disabled = false;
        } else if (eventType === 'error') {
            console.error("Erreur SSE du serveur:", data); // LOG AJOUTÉ
             currentResponseAccumulated += `<br><strong style="color: #ffaaaa;">خطأ من الخادم: ${data}</strong>`;
            sendButton.disabled = false;
        }
    });

    const updatedResponse = currentResponseAccumulated + newResponsePart;
    // Limiter la fréquence de mise à jour de innerHTML si beaucoup de petits chunks
    targetDiv.innerHTML = updatedResponse.replace(/\n/g, '<br>');
    chatbox.scrollTop = chatbox.scrollHeight;
    // console.log("Updated Response:", updatedResponse.substring(0, 100) + "..."); // Optionnel: peut être très verbeux

    return { incomplete: incomplete, updatedResponse: updatedResponse };
}

// --- adjustTextareaHeight function (inchangée) ---
function adjustTextareaHeight() { /* ... */ }


// --- askQuestion function (avec plus de logs) ---
async function askQuestion() {
    console.log("askQuestion called"); // LOG AJOUTÉ
    const question = messageInput.value.trim();
    if (!question) {
        console.log("Question is empty, aborting."); // LOG AJOUTÉ
        return;
    }

    addMessage('user', question);
    messageInput.value = '';
    sendButton.disabled = true;
    adjustTextareaHeight(); // Réajuste après vidage
    console.log("User message added, button disabled."); // LOG AJOUTÉ

    // Crée un placeholder pour la réponse de l'assistant
    const assistantMessageDiv = document.createElement('div');
    assistantMessageDiv.classList.add('message', 'assistant-message');
    assistantMessageDiv.innerHTML = '<span class="thinking">...</span>'; // Indicateur visuel simple
    chatbox.appendChild(assistantMessageDiv);
    chatbox.scrollTop = chatbox.scrollHeight;
    console.log("Assistant placeholder added."); // LOG AJOUTÉ

    let currentResponse = ""; // Déclaration initiale
    let buffer = '';        // Initialisation buffer
    const decoder = new TextDecoder(); // Initialisation decoder

    try {
        console.log("Initiating fetch to /ask"); // LOG AJOUTÉ
        const response = await fetch('/ask', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'text/event-stream'
            },
            body: JSON.stringify({ question: question })
        });

        console.log(`Fetch response received. Status: ${response.status}, OK: ${response.ok}`); // LOG AJOUTÉ

        if (!response.ok || !response.body) {
             // Essayer de lire le corps de l'erreur si possible
             let errorBody = "N/A";
             try {
                errorBody = await response.text();
             } catch (e) {}
            throw new Error(`Erreur serveur: ${response.status} ${response.statusText}. Body: ${errorBody}`);
        }

        const reader = response.body.getReader();
        console.log("ReadableStream reader obtained. Starting read loop."); // LOG AJOUTÉ

        while (true) {
            console.log("Calling reader.read()..."); // LOG AJOUTÉ
            const { done, value } = await reader.read();

            if (done) {
                console.log("Reader finished (done=true). Processing remaining buffer."); // LOG AJOUTÉ
                // Traiter le reste du buffer
                const result = processSSEBuffer(buffer, assistantMessageDiv, currentResponse);
                currentResponse = result.updatedResponse;
                console.log("Final response after stream ended:", currentResponse.substring(0,100)+"..."); // LOG AJOUTÉ
                break; // Sort de la boucle
            }

            // Decode et ajoute au buffer
            const chunk = decoder.decode(value, { stream: true });
            console.log("Received chunk:", chunk); // LOG AJOUTÉ (peut être volumineux)
            buffer += chunk;

            // Traite le buffer et met à jour currentResponse/buffer
            console.log("Processing buffer with new chunk..."); // LOG AJOUTÉ
            const result = processSSEBuffer(buffer, assistantMessageDiv, currentResponse);
            currentResponse = result.updatedResponse;
            buffer = result.incomplete;
            console.log("Buffer remaining:", buffer); // LOG AJOUTÉ

        }

    } catch (error) {
        console.error('Erreur dans askQuestion (fetch ou stream):', error); // LOG AJOUTÉ
        // Affiche l'erreur dans la bulle de l'assistant
         if (assistantMessageDiv) {
             // Append error to existing content if any, otherwise set it
             assistantMessageDiv.innerHTML += `<br><br><strong style="color: #ffaaaa;">حدث خطأ: ${error.message}</strong>`;
             chatbox.scrollTop = chatbox.scrollHeight; // Scroll pour voir l'erreur
         } else {
             // Fallback si assistantMessageDiv n'existe pas (ne devrait pas arriver ici)
             addMessage('assistant', `<strong style="color: #ffaaaa;">حدث خطأ: ${error.message}</strong>`);
         }
    } finally {
        console.log("Executing finally block: Enabling button."); // LOG AJOUTÉ
        sendButton.disabled = false;
    }
}


// --- Écouteurs d'événements (inchangés) ---
sendButton.addEventListener('click', askQuestion);
messageInput.addEventListener('keypress', function(e) {
    if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();
        askQuestion();
    }
});
messageInput.addEventListener('input', adjustTextareaHeight);
adjustTextareaHeight(); // Appel initial

console.log("Chat script loaded and listeners attached."); // LOG AJOUTÉ