Trabis commited on
Commit
13e5b3b
·
verified ·
1 Parent(s): 1ccf000

Update static/script.js

Browse files
Files changed (1) hide show
  1. static/script.js +85 -288
static/script.js CHANGED
@@ -1,178 +1,3 @@
1
- // const chatbox = document.getElementById('chatbox');
2
- // const messageInput = document.getElementById('message-input');
3
- // const sendButton = document.getElementById('send-button');
4
-
5
- // // --- addMessage function (inchangée) ---
6
- // function addMessage(role, text) {
7
- // const messageDiv = document.createElement('div');
8
- // messageDiv.classList.add('message', role === 'user' ? 'user-message' : 'assistant-message');
9
- // messageDiv.innerHTML = text.replace(/\n/g, '<br>');
10
- // chatbox.appendChild(messageDiv);
11
- // chatbox.scrollTop = chatbox.scrollHeight;
12
- // }
13
-
14
- // // --- processSSEBuffer function (inchangée - version Méthode 1) ---
15
- // function processSSEBuffer(buffer, targetDiv, currentResponseAccumulated) {
16
- // console.log("Processing buffer:", buffer); // LOG AJOUTÉ
17
- // let messages = buffer.split('\n\n');
18
- // let incomplete = buffer.endsWith('\n\n') ? '' : messages.pop();
19
- // let newResponsePart = '';
20
-
21
- // messages.forEach(message => {
22
- // if (!message.trim()) return;
23
- // let eventType = 'message';
24
- // let dataLines = [];
25
- // message.split('\n').forEach(line => {
26
- // if (line.startsWith('event: ')) {
27
- // eventType = line.substring(7).trim();
28
- // } else if (line.startsWith('data: ')) {
29
- // dataLines.push(line.substring(6));
30
- // }
31
- // });
32
- // let data = dataLines.join('\n');
33
- // console.log(`--> SSE Event Parsed: ${eventType}, Data: ${data.substring(0, 100)}...`); // LOG AJOUTÉ
34
-
35
- // if (eventType === 'message') {
36
- // if (targetDiv.querySelector('.thinking')) {
37
- // console.log("Replacing 'thinking' indicator"); // LOG AJOUTÉ
38
- // targetDiv.innerHTML = '';
39
- // }
40
- // newResponsePart += data;
41
- // } else if (eventType === 'end') {
42
- // console.log("Fin de stream détectée (event: end)"); // LOG AJOUTÉ
43
- // sendButton.disabled = false;
44
- // } else if (eventType === 'error') {
45
- // console.error("Erreur SSE du serveur:", data); // LOG AJOUTÉ
46
- // currentResponseAccumulated += `<br><strong style="color: #ffaaaa;">خطأ من الخادم: ${data}</strong>`;
47
- // sendButton.disabled = false;
48
- // }
49
- // });
50
-
51
- // const updatedResponse = currentResponseAccumulated + newResponsePart;
52
- // // Limiter la fréquence de mise à jour de innerHTML si beaucoup de petits chunks
53
- // targetDiv.innerHTML = updatedResponse.replace(/\n/g, '<br>');
54
- // chatbox.scrollTop = chatbox.scrollHeight;
55
- // // console.log("Updated Response:", updatedResponse.substring(0, 100) + "..."); // Optionnel: peut être très verbeux
56
-
57
- // return { incomplete: incomplete, updatedResponse: updatedResponse };
58
- // }
59
-
60
- // // --- adjustTextareaHeight function (inchangée) ---
61
- // function adjustTextareaHeight() { /* ... */ }
62
-
63
-
64
- // // --- askQuestion function (avec plus de logs) ---
65
- // async function askQuestion() {
66
- // console.log("askQuestion called"); // LOG AJOUTÉ
67
- // const question = messageInput.value.trim();
68
- // if (!question) {
69
- // console.log("Question is empty, aborting."); // LOG AJOUTÉ
70
- // return;
71
- // }
72
-
73
- // addMessage('user', question);
74
- // messageInput.value = '';
75
- // sendButton.disabled = true;
76
- // adjustTextareaHeight(); // Réajuste après vidage
77
- // console.log("User message added, button disabled."); // LOG AJOUTÉ
78
-
79
- // // Crée un placeholder pour la réponse de l'assistant
80
- // const assistantMessageDiv = document.createElement('div');
81
- // assistantMessageDiv.classList.add('message', 'assistant-message');
82
- // assistantMessageDiv.innerHTML = '<span class="thinking">...</span>'; // Indicateur visuel simple
83
- // chatbox.appendChild(assistantMessageDiv);
84
- // chatbox.scrollTop = chatbox.scrollHeight;
85
- // console.log("Assistant placeholder added."); // LOG AJOUTÉ
86
-
87
- // let currentResponse = ""; // Déclaration initiale
88
- // let buffer = ''; // Initialisation buffer
89
- // const decoder = new TextDecoder(); // Initialisation decoder
90
-
91
- // try {
92
- // console.log("Initiating fetch to /ask"); // LOG AJOUTÉ
93
- // const response = await fetch('/ask', {
94
- // method: 'POST',
95
- // headers: {
96
- // 'Content-Type': 'application/json',
97
- // 'Accept': 'text/event-stream'
98
- // },
99
- // body: JSON.stringify({ question: question })
100
- // });
101
-
102
- // console.log(`Fetch response received. Status: ${response.status}, OK: ${response.ok}`); // LOG AJOUTÉ
103
-
104
- // if (!response.ok || !response.body) {
105
- // // Essayer de lire le corps de l'erreur si possible
106
- // let errorBody = "N/A";
107
- // try {
108
- // errorBody = await response.text();
109
- // } catch (e) {}
110
- // throw new Error(`Erreur serveur: ${response.status} ${response.statusText}. Body: ${errorBody}`);
111
- // }
112
-
113
- // const reader = response.body.getReader();
114
- // console.log("ReadableStream reader obtained. Starting read loop."); // LOG AJOUTÉ
115
-
116
- // while (true) {
117
- // console.log("Calling reader.read()..."); // LOG AJOUTÉ
118
- // const { done, value } = await reader.read();
119
-
120
- // if (done) {
121
- // console.log("Reader finished (done=true). Processing remaining buffer."); // LOG AJOUTÉ
122
- // // Traiter le reste du buffer
123
- // const result = processSSEBuffer(buffer, assistantMessageDiv, currentResponse);
124
- // currentResponse = result.updatedResponse;
125
- // console.log("Final response after stream ended:", currentResponse.substring(0,100)+"..."); // LOG AJOUTÉ
126
- // break; // Sort de la boucle
127
- // }
128
-
129
- // // Decode et ajoute au buffer
130
- // const chunk = decoder.decode(value, { stream: true });
131
- // console.log("Received chunk:", chunk); // LOG AJOUTÉ (peut être volumineux)
132
- // buffer += chunk;
133
-
134
- // // Traite le buffer et met à jour currentResponse/buffer
135
- // console.log("Processing buffer with new chunk..."); // LOG AJOUTÉ
136
- // const result = processSSEBuffer(buffer, assistantMessageDiv, currentResponse);
137
- // currentResponse = result.updatedResponse;
138
- // buffer = result.incomplete;
139
- // console.log("Buffer remaining:", buffer); // LOG AJOUTÉ
140
-
141
- // }
142
-
143
- // } catch (error) {
144
- // console.error('Erreur dans askQuestion (fetch ou stream):', error); // LOG AJOUTÉ
145
- // // Affiche l'erreur dans la bulle de l'assistant
146
- // if (assistantMessageDiv) {
147
- // // Append error to existing content if any, otherwise set it
148
- // assistantMessageDiv.innerHTML += `<br><br><strong style="color: #ffaaaa;">حدث خطأ: ${error.message}</strong>`;
149
- // chatbox.scrollTop = chatbox.scrollHeight; // Scroll pour voir l'erreur
150
- // } else {
151
- // // Fallback si assistantMessageDiv n'existe pas (ne devrait pas arriver ici)
152
- // addMessage('assistant', `<strong style="color: #ffaaaa;">حدث خطأ: ${error.message}</strong>`);
153
- // }
154
- // } finally {
155
- // console.log("Executing finally block: Enabling button."); // LOG AJOUTÉ
156
- // sendButton.disabled = false;
157
- // }
158
- // }
159
-
160
-
161
- // // --- Écouteurs d'événements (inchangés) ---
162
- // sendButton.addEventListener('click', askQuestion);
163
- // messageInput.addEventListener('keypress', function(e) {
164
- // if (e.key === 'Enter' && !e.shiftKey) {
165
- // e.preventDefault();
166
- // askQuestion();
167
- // }
168
- // });
169
- // messageInput.addEventListener('input', adjustTextareaHeight);
170
- // adjustTextareaHeight(); // Appel initial
171
-
172
- // console.log("Chat script loaded and listeners attached."); // LOG AJOUTÉ
173
-
174
-
175
-
176
  const chatbox = document.getElementById('chatbox');
177
  const messageInput = document.getElementById('message-input');
178
  const sendButton = document.getElementById('send-button');
@@ -181,62 +6,67 @@ const sendButton = document.getElementById('send-button');
181
  function addMessage(role, text) {
182
  const messageDiv = document.createElement('div');
183
  messageDiv.classList.add('message', role === 'user' ? 'user-message' : 'assistant-message');
184
- // Remplacer les sauts de ligne pour l'affichage HTML
185
  messageDiv.innerHTML = text.replace(/\n/g, '<br>');
186
  chatbox.appendChild(messageDiv);
187
  chatbox.scrollTop = chatbox.scrollHeight;
188
  }
189
 
190
- // --- Fonction pour parser les événements SSE (simplifiée) ---
191
- // Retourne les événements trouvés et le buffer restant
192
- function parseSSEEvents(buffer) {
193
- const events = [];
194
  let messages = buffer.split('\n\n');
195
- let incomplete = buffer.endsWith('\n\n') ? '' : messages.pop(); // Garde la partie incomplète
 
196
 
197
  messages.forEach(message => {
198
  if (!message.trim()) return;
199
- let eventType = 'message'; // Type par défaut
200
- let data = ''; // Données associées à l'événement (peut être multi-lignes)
201
  let dataLines = [];
202
-
203
  message.split('\n').forEach(line => {
204
  if (line.startsWith('event: ')) {
205
  eventType = line.substring(7).trim();
206
  } else if (line.startsWith('data: ')) {
207
- dataLines.push(line.substring(6)); // Stocke les lignes de données
208
  }
209
- // Ignorer les lignes id: et : (commentaires)
210
  });
 
 
211
 
212
- data = dataLines.join('\n'); // Reconstitue les données multi-lignes
213
-
214
- // On ne stocke QUE les événements spéciaux ici (pas 'message')
215
- if (eventType !== 'message') {
216
- console.log(`--> Parsed Special SSE Event: ${eventType}, Data: ${data.substring(0, 100)}...`);
217
- events.push({ type: eventType, data: data });
218
- } else {
219
- // On pourrait logger les messages data ici si besoin de débogage
220
- // console.log(`--> Parsed SSE Data Message (ignored by event processor): ${data.substring(0,100)}...`);
 
 
 
 
221
  }
222
  });
223
 
224
- return { events: events, incomplete: incomplete };
225
- }
 
 
 
226
 
 
 
227
 
228
  // --- adjustTextareaHeight function (inchangée) ---
229
- function adjustTextareaHeight() {
230
- messageInput.style.height = 'auto'; // Réinitialise pour obtenir scrollHeight correct
231
- messageInput.style.height = (messageInput.scrollHeight) + 'px'; // Ajuste à la hauteur du contenu
232
- }
233
 
234
- // --- askQuestion function (MODIFIÉE pour le streaming UI direct) ---
235
  async function askQuestion() {
236
- console.log("askQuestion called");
237
  const question = messageInput.value.trim();
238
  if (!question) {
239
- console.log("Question is empty, aborting.");
240
  return;
241
  }
242
 
@@ -244,118 +74,85 @@ async function askQuestion() {
244
  messageInput.value = '';
245
  sendButton.disabled = true;
246
  adjustTextareaHeight(); // Réajuste après vidage
247
- console.log("User message added, button disabled.");
248
 
249
  // Crée un placeholder pour la réponse de l'assistant
250
  const assistantMessageDiv = document.createElement('div');
251
  assistantMessageDiv.classList.add('message', 'assistant-message');
252
- // Utiliser textContent pour l'indicateur est plus sûr
253
- const thinkingSpan = document.createElement('span');
254
- thinkingSpan.className = 'thinking';
255
- thinkingSpan.textContent = '...';
256
- assistantMessageDiv.appendChild(thinkingSpan);
257
  chatbox.appendChild(assistantMessageDiv);
258
  chatbox.scrollTop = chatbox.scrollHeight;
259
- console.log("Assistant placeholder added.");
260
 
261
- let buffer = ''; // Buffer pour détecter les événements SSE spéciaux
262
- const decoder = new TextDecoder();
263
- let isFirstChunk = true; // Pour savoir quand remplacer le "..."
264
 
265
  try {
266
- console.log("Initiating fetch to /ask");
267
  const response = await fetch('/ask', {
268
  method: 'POST',
269
- headers: { 'Content-Type': 'application/json', 'Accept': 'text/event-stream' },
 
 
 
270
  body: JSON.stringify({ question: question })
271
  });
272
- console.log(`Fetch response received. Status: ${response.status}, OK: ${response.ok}`);
 
273
 
274
  if (!response.ok || !response.body) {
275
- let errorBody = "N/A"; try { errorBody = await response.text(); } catch (e) {}
 
 
 
 
276
  throw new Error(`Erreur serveur: ${response.status} ${response.statusText}. Body: ${errorBody}`);
277
  }
278
 
279
  const reader = response.body.getReader();
280
- console.log("ReadableStream reader obtained. Starting read loop.");
281
 
282
- // Boucle principale de lecture du stream
283
  while (true) {
 
284
  const { done, value } = await reader.read();
285
 
286
- // Traiter le chunk reçu SI value n'est pas vide
287
- if (value) {
288
- const rawChunk = decoder.decode(value, { stream: true });
289
- console.log("Received raw chunk:", rawChunk); // Log pour débogage
290
-
291
- // --- Mise à jour UI Immédiate ---
292
- // Nettoyer l'indicateur "..." au premier chunk reçu
293
- if (isFirstChunk && assistantMessageDiv.querySelector('.thinking')) {
294
- assistantMessageDiv.innerHTML = ''; // Vide le contenu (enlève le span '...')
295
- isFirstChunk = false;
296
- }
297
- // Ajoute le nouveau morceau de texte (converti en HTML)
298
- // Note: innerHTML peut être lent si les chunks sont très petits et nombreux.
299
- // textContent serait plus rapide mais ne gère pas <br>.
300
- assistantMessageDiv.innerHTML += rawChunk.replace(/\n/g, '<br>');
301
- chatbox.scrollTop = chatbox.scrollHeight; // Scroll pendant l'ajout
302
- // --- Fin Mise à jour UI Immédiate ---
303
-
304
- // Ajoute le chunk au buffer pour détecter les événements spéciaux
305
- buffer += rawChunk;
306
 
307
- // --- Traitement des Événements Spéciaux ---
308
- const eventResult = parseSSEEvents(buffer);
309
- buffer = eventResult.incomplete; // Garde la partie non traitée du buffer
 
310
 
311
- for (const event of eventResult.events) {
312
- if (event.type === 'end') {
313
- console.log("Fin de stream détectée (event: end)");
314
- sendButton.disabled = false; // Réactive le bouton
315
- // On pourrait vouloir sortir de la boucle ici si 'done' tarde
316
- // mais il vaut mieux attendre 'done = true' normalement.
317
- } else if (event.type === 'error') {
318
- console.error("Erreur signalée par le serveur (event: error):", event.data);
319
- // Ajoute l'erreur à la fin
320
- assistantMessageDiv.innerHTML += `<br><strong style="color: #ffaaaa;">خطأ من الخادم: ${event.data.replace(/\n/g, '<br>')}</strong>`;
321
- chatbox.scrollTop = chatbox.scrollHeight;
322
- sendButton.disabled = false;
323
- // Considérer de sortir de la boucle ici ?
324
- }
325
- // Gérer d'autres événements si nécessaire
326
- }
327
- // --- Fin Traitement Événements ---
328
- } // Fin if(value)
329
 
330
- // Si le stream est terminé (signalé par le reader)
331
- if (done) {
332
- console.log("Reader finished (done=true). Stream ended.");
333
- // Traiter une dernière fois le buffer pour les événements ?
334
- // Normalement pas nécessaire si les événements finissent par \n\n
335
- if (buffer.trim()){
336
- console.log("Processing final buffer content:", buffer);
337
- const finalEventResult = parseSSEEvents(buffer);
338
- for (const event of finalEventResult.events) { /* Gérer comme ci-dessus */ }
339
- }
340
- break; // Sortir de la boucle while
341
- }
342
- } // Fin while(true)
343
 
344
  } catch (error) {
345
- console.error('Erreur dans askQuestion (fetch ou stream):', error);
346
- if (assistantMessageDiv) {
347
- // Supprimer l'indicateur "..." s'il est encore là
348
- const thinkingSpan = assistantMessageDiv.querySelector('.thinking');
349
- if (thinkingSpan) thinkingSpan.remove();
350
- // Afficher l'erreur JS/Network
351
- assistantMessageDiv.innerHTML += `<br><br><strong style="color: #ffaaaa;">حدث خطأ في الاتصال: ${error.message}</strong>`;
352
- chatbox.scrollTop = chatbox.scrollHeight;
353
- } else {
354
- addMessage('assistant', `<strong style="color: #ffaaaa;">حدث خطأ في الاتصال: ${error.message}</strong>`);
355
- }
356
  } finally {
357
- console.log("Executing finally block.");
358
- // Le bouton peut déjà avoir été réactivé par event: end/error, mais sécurité :
359
  sendButton.disabled = false;
360
  }
361
  }
@@ -372,4 +169,4 @@ messageInput.addEventListener('keypress', function(e) {
372
  messageInput.addEventListener('input', adjustTextareaHeight);
373
  adjustTextareaHeight(); // Appel initial
374
 
375
- console.log("Chat script loaded and listeners attached. Streaming UI enabled.");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  const chatbox = document.getElementById('chatbox');
2
  const messageInput = document.getElementById('message-input');
3
  const sendButton = document.getElementById('send-button');
 
6
  function addMessage(role, text) {
7
  const messageDiv = document.createElement('div');
8
  messageDiv.classList.add('message', role === 'user' ? 'user-message' : 'assistant-message');
 
9
  messageDiv.innerHTML = text.replace(/\n/g, '<br>');
10
  chatbox.appendChild(messageDiv);
11
  chatbox.scrollTop = chatbox.scrollHeight;
12
  }
13
 
14
+ // --- processSSEBuffer function (inchangée - version Méthode 1) ---
15
+ function processSSEBuffer(buffer, targetDiv, currentResponseAccumulated) {
16
+ console.log("Processing buffer:", buffer); // LOG AJOUTÉ
 
17
  let messages = buffer.split('\n\n');
18
+ let incomplete = buffer.endsWith('\n\n') ? '' : messages.pop();
19
+ let newResponsePart = '';
20
 
21
  messages.forEach(message => {
22
  if (!message.trim()) return;
23
+ let eventType = 'message';
 
24
  let dataLines = [];
 
25
  message.split('\n').forEach(line => {
26
  if (line.startsWith('event: ')) {
27
  eventType = line.substring(7).trim();
28
  } else if (line.startsWith('data: ')) {
29
+ dataLines.push(line.substring(6));
30
  }
 
31
  });
32
+ let data = dataLines.join('\n');
33
+ console.log(`--> SSE Event Parsed: ${eventType}, Data: ${data.substring(0, 100)}...`); // LOG AJOUTÉ
34
 
35
+ if (eventType === 'message') {
36
+ if (targetDiv.querySelector('.thinking')) {
37
+ console.log("Replacing 'thinking' indicator"); // LOG AJOUTÉ
38
+ targetDiv.innerHTML = '';
39
+ }
40
+ newResponsePart += data;
41
+ } else if (eventType === 'end') {
42
+ console.log("Fin de stream détectée (event: end)"); // LOG AJOUTÉ
43
+ sendButton.disabled = false;
44
+ } else if (eventType === 'error') {
45
+ console.error("Erreur SSE du serveur:", data); // LOG AJOUTÉ
46
+ currentResponseAccumulated += `<br><strong style="color: #ffaaaa;">خطأ من الخادم: ${data}</strong>`;
47
+ sendButton.disabled = false;
48
  }
49
  });
50
 
51
+ const updatedResponse = currentResponseAccumulated + newResponsePart;
52
+ // Limiter la fréquence de mise à jour de innerHTML si beaucoup de petits chunks
53
+ targetDiv.innerHTML = updatedResponse.replace(/\n/g, '<br>');
54
+ chatbox.scrollTop = chatbox.scrollHeight;
55
+ // console.log("Updated Response:", updatedResponse.substring(0, 100) + "..."); // Optionnel: peut être très verbeux
56
 
57
+ return { incomplete: incomplete, updatedResponse: updatedResponse };
58
+ }
59
 
60
  // --- adjustTextareaHeight function (inchangée) ---
61
+ function adjustTextareaHeight() { /* ... */ }
62
+
 
 
63
 
64
+ // --- askQuestion function (avec plus de logs) ---
65
  async function askQuestion() {
66
+ console.log("askQuestion called"); // LOG AJOUTÉ
67
  const question = messageInput.value.trim();
68
  if (!question) {
69
+ console.log("Question is empty, aborting."); // LOG AJOUTÉ
70
  return;
71
  }
72
 
 
74
  messageInput.value = '';
75
  sendButton.disabled = true;
76
  adjustTextareaHeight(); // Réajuste après vidage
77
+ console.log("User message added, button disabled."); // LOG AJOUTÉ
78
 
79
  // Crée un placeholder pour la réponse de l'assistant
80
  const assistantMessageDiv = document.createElement('div');
81
  assistantMessageDiv.classList.add('message', 'assistant-message');
82
+ assistantMessageDiv.innerHTML = '<span class="thinking">...</span>'; // Indicateur visuel simple
 
 
 
 
83
  chatbox.appendChild(assistantMessageDiv);
84
  chatbox.scrollTop = chatbox.scrollHeight;
85
+ console.log("Assistant placeholder added."); // LOG AJOUTÉ
86
 
87
+ let currentResponse = ""; // Déclaration initiale
88
+ let buffer = ''; // Initialisation buffer
89
+ const decoder = new TextDecoder(); // Initialisation decoder
90
 
91
  try {
92
+ console.log("Initiating fetch to /ask"); // LOG AJOUTÉ
93
  const response = await fetch('/ask', {
94
  method: 'POST',
95
+ headers: {
96
+ 'Content-Type': 'application/json',
97
+ 'Accept': 'text/event-stream'
98
+ },
99
  body: JSON.stringify({ question: question })
100
  });
101
+
102
+ console.log(`Fetch response received. Status: ${response.status}, OK: ${response.ok}`); // LOG AJOUTÉ
103
 
104
  if (!response.ok || !response.body) {
105
+ // Essayer de lire le corps de l'erreur si possible
106
+ let errorBody = "N/A";
107
+ try {
108
+ errorBody = await response.text();
109
+ } catch (e) {}
110
  throw new Error(`Erreur serveur: ${response.status} ${response.statusText}. Body: ${errorBody}`);
111
  }
112
 
113
  const reader = response.body.getReader();
114
+ console.log("ReadableStream reader obtained. Starting read loop."); // LOG AJOUTÉ
115
 
 
116
  while (true) {
117
+ console.log("Calling reader.read()..."); // LOG AJOUTÉ
118
  const { done, value } = await reader.read();
119
 
120
+ if (done) {
121
+ console.log("Reader finished (done=true). Processing remaining buffer."); // LOG AJOUTÉ
122
+ // Traiter le reste du buffer
123
+ const result = processSSEBuffer(buffer, assistantMessageDiv, currentResponse);
124
+ currentResponse = result.updatedResponse;
125
+ console.log("Final response after stream ended:", currentResponse.substring(0,100)+"..."); // LOG AJOUTÉ
126
+ break; // Sort de la boucle
127
+ }
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
+ // Decode et ajoute au buffer
130
+ const chunk = decoder.decode(value, { stream: true });
131
+ console.log("Received chunk:", chunk); // LOG AJOUTÉ (peut être volumineux)
132
+ buffer += chunk;
133
 
134
+ // Traite le buffer et met à jour currentResponse/buffer
135
+ console.log("Processing buffer with new chunk..."); // LOG AJOUTÉ
136
+ const result = processSSEBuffer(buffer, assistantMessageDiv, currentResponse);
137
+ currentResponse = result.updatedResponse;
138
+ buffer = result.incomplete;
139
+ console.log("Buffer remaining:", buffer); // LOG AJOUTÉ
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
+ }
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  } catch (error) {
144
+ console.error('Erreur dans askQuestion (fetch ou stream):', error); // LOG AJOUTÉ
145
+ // Affiche l'erreur dans la bulle de l'assistant
146
+ if (assistantMessageDiv) {
147
+ // Append error to existing content if any, otherwise set it
148
+ assistantMessageDiv.innerHTML += `<br><br><strong style="color: #ffaaaa;">حدث خطأ: ${error.message}</strong>`;
149
+ chatbox.scrollTop = chatbox.scrollHeight; // Scroll pour voir l'erreur
150
+ } else {
151
+ // Fallback si assistantMessageDiv n'existe pas (ne devrait pas arriver ici)
152
+ addMessage('assistant', `<strong style="color: #ffaaaa;">حدث خطأ: ${error.message}</strong>`);
153
+ }
 
154
  } finally {
155
+ console.log("Executing finally block: Enabling button."); // LOG AJOUTÉ
 
156
  sendButton.disabled = false;
157
  }
158
  }
 
169
  messageInput.addEventListener('input', adjustTextareaHeight);
170
  adjustTextareaHeight(); // Appel initial
171
 
172
+ console.log("Chat script loaded and listeners attached."); // LOG AJOUTÉ