Spaces:
Running
Running
Upload index.html
Browse files- templates/index.html +62 -253
templates/index.html
CHANGED
@@ -1,70 +1,37 @@
|
|
|
|
1 |
<!DOCTYPE html>
|
2 |
<html lang="fr">
|
3 |
<head>
|
4 |
<meta charset="UTF-8">
|
5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
<title>Mariam M-0 | Solution Mathématique</title>
|
7 |
-
<!-- Tailwind CSS -->
|
8 |
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
|
9 |
|
10 |
-
<!-- Configuration optimisée de MathJax
|
11 |
<script>
|
12 |
window.MathJax = {
|
13 |
tex: {
|
14 |
-
inlineMath: [['$', '$']
|
15 |
-
displayMath: [['$$', '$$']
|
16 |
processEscapes: true,
|
17 |
-
|
18 |
-
|
19 |
-
R: '{\\mathbb{R}}',
|
20 |
-
N: '{\\mathbb{N}}',
|
21 |
-
Z: '{\\mathbb{Z}}',
|
22 |
-
C: '{\\mathbb{C}}',
|
23 |
-
Q: '{\\mathbb{Q}}'
|
24 |
-
},
|
25 |
-
packages: {
|
26 |
-
'[+]': [
|
27 |
-
'autoload',
|
28 |
-
'ams',
|
29 |
-
'noerrors',
|
30 |
-
'physics',
|
31 |
-
'colorv2',
|
32 |
-
'cancel',
|
33 |
-
'mhchem'
|
34 |
-
]
|
35 |
-
},
|
36 |
-
// Ignorer les erreurs
|
37 |
-
processClass: "math",
|
38 |
-
formatError: (jax, err) => {
|
39 |
-
console.warn('Erreur MathJax:', err);
|
40 |
-
return jax.formatError(err);
|
41 |
-
}
|
42 |
-
},
|
43 |
-
svg: {
|
44 |
-
fontCache: 'global',
|
45 |
-
scale: 1.2
|
46 |
},
|
|
|
47 |
options: {
|
48 |
-
enableMenu:
|
49 |
-
|
50 |
-
renderActions: {
|
51 |
-
assistiveMml: []
|
52 |
-
}
|
53 |
-
},
|
54 |
-
loader: {
|
55 |
-
load: ['[tex]/physics', '[tex]/ams', '[tex]/colorv2', '[tex]/cancel', '[tex]/mhchem']
|
56 |
},
|
57 |
startup: {
|
58 |
pageReady: () => {
|
59 |
console.log('MathJax est complètement chargé.');
|
60 |
window.mathJaxReady = true;
|
61 |
-
document.dispatchEvent(new Event('mathjax-ready'));
|
62 |
}
|
63 |
}
|
64 |
};
|
65 |
</script>
|
66 |
-
|
67 |
-
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" id="MathJax-script" async></script>
|
68 |
<script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.min.js"></script>
|
69 |
|
70 |
<style>
|
@@ -74,7 +41,6 @@
|
|
74 |
font-family: 'Space Grotesk', sans-serif;
|
75 |
}
|
76 |
|
77 |
-
/* CSS existant... */
|
78 |
.uploadArea {
|
79 |
background: #f3f4f6;
|
80 |
border: 2px dashed #d1d5db;
|
@@ -134,49 +100,24 @@
|
|
134 |
margin-left: 8px;
|
135 |
}
|
136 |
|
137 |
-
/* Styles pour
|
138 |
-
mjx-container {
|
139 |
-
display: inline-block;
|
140 |
-
overflow-x: auto;
|
141 |
-
overflow-y: hidden;
|
142 |
-
max-width: 100%;
|
143 |
-
padding: 0.5em 0;
|
144 |
-
min-width: auto !important;
|
145 |
-
}
|
146 |
-
|
147 |
-
mjx-container[jax="SVG"] {
|
148 |
-
direction: ltr;
|
149 |
-
}
|
150 |
-
|
151 |
-
mjx-container svg {
|
152 |
-
min-width: auto !important;
|
153 |
-
}
|
154 |
-
|
155 |
-
/* Amélioration pour les formules complexes */
|
156 |
-
mjx-mtable {
|
157 |
-
min-width: auto !important;
|
158 |
-
margin: 0 !important;
|
159 |
-
}
|
160 |
-
|
161 |
-
/* Support des tableaux et autres éléments */
|
162 |
table {
|
163 |
border-collapse: collapse;
|
164 |
width: 100%;
|
165 |
-
margin: 1rem
|
166 |
}
|
167 |
th, td {
|
168 |
border: 1px solid #d1d5db;
|
169 |
-
padding: 0.
|
170 |
text-align: left;
|
171 |
}
|
172 |
th {
|
173 |
background-color: #f3f4f6;
|
174 |
font-weight: 600;
|
175 |
}
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
margin-top: 1rem;
|
180 |
}
|
181 |
</style>
|
182 |
</head>
|
@@ -188,7 +129,6 @@
|
|
188 |
</header>
|
189 |
|
190 |
<main>
|
191 |
-
<!-- Le reste du HTML reste inchangé -->
|
192 |
<form id="problemForm" class="space-y-6" novalidate>
|
193 |
<!-- Zone de dépôt et sélection d'image -->
|
194 |
<div class="uploadArea p-8 text-center relative" aria-label="Zone de dépôt d'image">
|
@@ -234,6 +174,7 @@
|
|
234 |
</div>
|
235 |
<div class="border-t pt-6">
|
236 |
<h3 class="text-xl font-bold text-gray-800 mb-4">Solution</h3>
|
|
|
237 |
<div id="answerContent" class="text-gray-700 table-responsive"></div>
|
238 |
</div>
|
239 |
</section>
|
@@ -260,8 +201,7 @@
|
|
260 |
let thoughtsBuffer = '';
|
261 |
let answerBuffer = '';
|
262 |
let currentMode = null;
|
263 |
-
let updateTimeout = null;
|
264 |
-
let mathJaxQueue = Promise.resolve();
|
265 |
|
266 |
// Mise à jour de l'affichage du temps écoulé
|
267 |
const updateTimestamp = () => {
|
@@ -317,126 +257,38 @@
|
|
317 |
handleFileSelect(e.dataTransfer.files[0]);
|
318 |
});
|
319 |
|
320 |
-
//
|
321 |
-
const
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
// Identification de tous les types d'expressions LaTeX
|
329 |
-
const latexPattern = /(\$\$[\s\S]*?\$\$|\$[^\$\n]+?\$|\\begin\{[a-z]*\}[\s\S]*?\\end\{[a-z]*\})/g;
|
330 |
-
|
331 |
-
// Étape 1: Remplacer les expressions LaTeX par des jetons
|
332 |
-
const tokenizedContent = content.replace(latexPattern, (match) => {
|
333 |
-
const token = createToken(latexBlocks.length);
|
334 |
-
latexBlocks.push({token, latex: match});
|
335 |
-
// Encadrer le jeton d'une manière qui empêche marked de le transformer
|
336 |
-
return `<!${token}!>`;
|
337 |
-
});
|
338 |
-
|
339 |
-
// Étape 2: Traiter avec marked
|
340 |
-
let htmlContent = marked.parse(tokenizedContent);
|
341 |
-
|
342 |
-
// Étape 3: Restaurer les expressions LaTeX
|
343 |
-
latexBlocks.forEach(({token, latex}) => {
|
344 |
-
// Échapper les caractères spéciaux dans le jeton
|
345 |
-
const escapedToken = token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
346 |
-
const tokenPattern = new RegExp(`<!${escapedToken}!>`, 'g');
|
347 |
-
htmlContent = htmlContent.replace(tokenPattern, latex);
|
348 |
-
});
|
349 |
-
|
350 |
-
return htmlContent;
|
351 |
-
};
|
352 |
-
|
353 |
-
// Fonction pour le rendu MathJax
|
354 |
-
const typesetMathJax = async (element) => {
|
355 |
-
if (!window.mathJaxReady) {
|
356 |
-
return new Promise((resolve) => {
|
357 |
-
document.addEventListener('mathjax-ready', () => {
|
358 |
-
typesetMathJax(element).then(resolve);
|
359 |
-
}, { once: true });
|
360 |
-
});
|
361 |
-
}
|
362 |
-
|
363 |
-
try {
|
364 |
-
// Utiliser une file d'attente pour éviter les conflits de rendu
|
365 |
-
return mathJaxQueue = mathJaxQueue.then(async () => {
|
366 |
-
try {
|
367 |
-
MathJax.startup.document.elements = [element];
|
368 |
-
await MathJax.typesetPromise([element]);
|
369 |
-
return true;
|
370 |
-
} catch (error) {
|
371 |
-
console.warn('Erreur dans le rendu MathJax', error);
|
372 |
-
// Essayer de réparer certaines expressions couramment problématiques
|
373 |
-
const fixLaTeX = (elem) => {
|
374 |
-
// Remplacer les caractères problématiques
|
375 |
-
elem.innerHTML = elem.innerHTML
|
376 |
-
.replace(/\\{/g, '\\lbrace ')
|
377 |
-
.replace(/\\}/g, '\\rbrace ')
|
378 |
-
.replace(/(?<![\\])\{/g, '\\{')
|
379 |
-
.replace(/(?<![\\])\}/g, '\\}');
|
380 |
-
};
|
381 |
-
|
382 |
-
// Appliquer les corrections et retenter
|
383 |
-
const mathElements = element.querySelectorAll('mjx-container');
|
384 |
-
mathElements.forEach(fixLaTeX);
|
385 |
-
|
386 |
-
try {
|
387 |
-
await MathJax.typesetPromise([element]);
|
388 |
-
return true;
|
389 |
-
} catch (retryError) {
|
390 |
-
console.error('Échec de la récupération MathJax', retryError);
|
391 |
-
return false;
|
392 |
-
}
|
393 |
-
}
|
394 |
-
});
|
395 |
-
} catch (fatalError) {
|
396 |
-
console.error('Erreur fatale MathJax', fatalError);
|
397 |
-
return false;
|
398 |
}
|
399 |
};
|
400 |
|
401 |
-
// Fonction pour
|
402 |
const updateDisplay = async () => {
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
await typesetMathJax(thoughtsContent);
|
410 |
-
await typesetMathJax(answerContent);
|
411 |
-
|
412 |
-
// Scroll vers le bas
|
413 |
-
if (currentMode === 'thinking') {
|
414 |
-
thoughtsContent.scrollTop = thoughtsContent.scrollHeight;
|
415 |
-
} else if (currentMode === 'answering') {
|
416 |
-
answerContent.scrollTop = answerContent.scrollHeight;
|
417 |
-
}
|
418 |
-
} catch (error) {
|
419 |
-
console.error('Erreur lors de la mise à jour de l\'affichage', error);
|
420 |
-
}
|
421 |
-
|
422 |
-
// Réinitialiser le timeout
|
423 |
updateTimeout = null;
|
424 |
};
|
425 |
|
426 |
// Fonction pour planifier la mise à jour (dé-bounce)
|
427 |
const scheduleUpdate = () => {
|
428 |
-
if (updateTimeout)
|
429 |
-
|
430 |
-
}
|
431 |
-
updateTimeout = setTimeout(updateDisplay, 300);
|
432 |
};
|
433 |
|
434 |
-
// Configuration de marked
|
435 |
marked.setOptions({
|
436 |
gfm: true,
|
437 |
-
breaks: true
|
438 |
-
pedantic: false,
|
439 |
-
smartLists: true
|
440 |
});
|
441 |
|
442 |
// Soumission du formulaire
|
@@ -469,10 +321,6 @@
|
|
469 |
body: formData
|
470 |
});
|
471 |
|
472 |
-
if (!response.ok) {
|
473 |
-
throw new Error(`Erreur HTTP: ${response.status}`);
|
474 |
-
}
|
475 |
-
|
476 |
const reader = response.body.getReader();
|
477 |
const decoder = new TextDecoder();
|
478 |
let buffer = '';
|
@@ -480,42 +328,27 @@
|
|
480 |
// Traitement d'un chunk de données
|
481 |
const processChunk = async chunk => {
|
482 |
buffer += decoder.decode(chunk, { stream: true });
|
483 |
-
|
484 |
-
|
485 |
-
let startPos = 0;
|
486 |
-
let endPos;
|
487 |
-
|
488 |
-
while ((endPos = buffer.indexOf('\n\n', startPos)) !== -1) {
|
489 |
-
lines.push(buffer.substring(startPos, endPos));
|
490 |
-
startPos = endPos + 2;
|
491 |
-
}
|
492 |
-
|
493 |
-
// Conserver la dernière partie potentiellement incomplète
|
494 |
-
buffer = buffer.substring(startPos);
|
495 |
|
496 |
for (const line of lines) {
|
497 |
if (!line.startsWith('data:')) continue;
|
498 |
-
|
499 |
-
const data = JSON.parse(line.slice(5));
|
500 |
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
}
|
512 |
}
|
513 |
-
} catch (error) {
|
514 |
-
console.error('Erreur de parsing JSON:', error, line);
|
515 |
}
|
516 |
}
|
517 |
-
|
518 |
-
// Planifier la mise à jour
|
519 |
scheduleUpdate();
|
520 |
};
|
521 |
|
@@ -523,28 +356,18 @@
|
|
523 |
while (true) {
|
524 |
const { done, value } = await reader.read();
|
525 |
if (done) {
|
526 |
-
// Traitement
|
527 |
-
if (buffer
|
528 |
-
|
529 |
-
|
530 |
-
if (
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
answerBuffer += data.content;
|
535 |
-
}
|
536 |
}
|
537 |
-
} catch (e) {
|
538 |
-
console.warn('Impossible de parser le dernier fragment:', e);
|
539 |
}
|
540 |
}
|
541 |
-
|
542 |
-
// Forcer une mise à jour finale
|
543 |
-
if (updateTimeout) {
|
544 |
-
clearTimeout(updateTimeout);
|
545 |
-
updateTimeout = null;
|
546 |
-
}
|
547 |
-
await updateDisplay();
|
548 |
break;
|
549 |
}
|
550 |
await processChunk(value);
|
@@ -552,25 +375,11 @@
|
|
552 |
stopTimer();
|
553 |
} catch (error) {
|
554 |
console.error('Erreur:', error);
|
555 |
-
alert(
|
556 |
loader.classList.add('hidden');
|
557 |
stopTimer();
|
558 |
}
|
559 |
});
|
560 |
-
|
561 |
-
// Fonction de débogage pour tester le rendu LaTeX
|
562 |
-
window.testLatex = (expression) => {
|
563 |
-
const testDiv = document.createElement('div');
|
564 |
-
testDiv.innerHTML = expression;
|
565 |
-
document.body.appendChild(testDiv);
|
566 |
-
|
567 |
-
return typesetMathJax(testDiv)
|
568 |
-
.then(success => {
|
569 |
-
const result = {success, rendered: testDiv.innerHTML};
|
570 |
-
document.body.removeChild(testDiv);
|
571 |
-
return result;
|
572 |
-
});
|
573 |
-
};
|
574 |
});
|
575 |
</script>
|
576 |
</body>
|
|
|
1 |
+
|
2 |
<!DOCTYPE html>
|
3 |
<html lang="fr">
|
4 |
<head>
|
5 |
<meta charset="UTF-8">
|
6 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7 |
<title>Mariam M-0 | Solution Mathématique</title>
|
8 |
+
<!-- Tailwind CSS (version 2.2.19 utilisée ici, à mettre à jour si besoin) -->
|
9 |
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
|
10 |
|
11 |
+
<!-- Configuration optimisée de MathJax avec support étendu LaTeX -->
|
12 |
<script>
|
13 |
window.MathJax = {
|
14 |
tex: {
|
15 |
+
inlineMath: [['$', '$']],
|
16 |
+
displayMath: [['$$', '$$']],
|
17 |
processEscapes: true,
|
18 |
+
// Chargement automatique de commandes supplémentaires (ex. environnements de tableaux)
|
19 |
+
packages: {'[+]': ['autoload','ams']}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
},
|
21 |
+
|
22 |
options: {
|
23 |
+
enableMenu: false,
|
24 |
+
messageStyle: 'none'
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
},
|
26 |
startup: {
|
27 |
pageReady: () => {
|
28 |
console.log('MathJax est complètement chargé.');
|
29 |
window.mathJaxReady = true;
|
|
|
30 |
}
|
31 |
}
|
32 |
};
|
33 |
</script>
|
34 |
+
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" id="MathJax-script" async></script>
|
|
|
35 |
<script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.min.js"></script>
|
36 |
|
37 |
<style>
|
|
|
41 |
font-family: 'Space Grotesk', sans-serif;
|
42 |
}
|
43 |
|
|
|
44 |
.uploadArea {
|
45 |
background: #f3f4f6;
|
46 |
border: 2px dashed #d1d5db;
|
|
|
100 |
margin-left: 8px;
|
101 |
}
|
102 |
|
103 |
+
/* Styles supplémentaires pour une meilleure présentation des tableaux */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
table {
|
105 |
border-collapse: collapse;
|
106 |
width: 100%;
|
107 |
+
margin-bottom: 1rem;
|
108 |
}
|
109 |
th, td {
|
110 |
border: 1px solid #d1d5db;
|
111 |
+
padding: 0.5rem;
|
112 |
text-align: left;
|
113 |
}
|
114 |
th {
|
115 |
background-color: #f3f4f6;
|
116 |
font-weight: 600;
|
117 |
}
|
118 |
+
/* Pour un rendu responsive, ajouter éventuellement : */
|
119 |
+
.table-responsive {
|
120 |
+
overflow-x: auto;
|
|
|
121 |
}
|
122 |
</style>
|
123 |
</head>
|
|
|
129 |
</header>
|
130 |
|
131 |
<main>
|
|
|
132 |
<form id="problemForm" class="space-y-6" novalidate>
|
133 |
<!-- Zone de dépôt et sélection d'image -->
|
134 |
<div class="uploadArea p-8 text-center relative" aria-label="Zone de dépôt d'image">
|
|
|
174 |
</div>
|
175 |
<div class="border-t pt-6">
|
176 |
<h3 class="text-xl font-bold text-gray-800 mb-4">Solution</h3>
|
177 |
+
<!-- Enveloppement d'éventuels tableaux dans une div responsive -->
|
178 |
<div id="answerContent" class="text-gray-700 table-responsive"></div>
|
179 |
</div>
|
180 |
</section>
|
|
|
201 |
let thoughtsBuffer = '';
|
202 |
let answerBuffer = '';
|
203 |
let currentMode = null;
|
204 |
+
let updateTimeout = null; // Variable pour le debounce des mises à jour
|
|
|
205 |
|
206 |
// Mise à jour de l'affichage du temps écoulé
|
207 |
const updateTimestamp = () => {
|
|
|
257 |
handleFileSelect(e.dataTransfer.files[0]);
|
258 |
});
|
259 |
|
260 |
+
// Fonction pour relancer le rendu MathJax dès que le contenu de la réponse est mis à jour
|
261 |
+
const typesetAnswerIfReady = async () => {
|
262 |
+
if (window.mathJaxReady) {
|
263 |
+
MathJax.startup.document.elements = [document.getElementById('answerContent')];
|
264 |
+
await MathJax.typesetPromise();
|
265 |
+
answerContent.scrollTop = answerContent.scrollHeight;
|
266 |
+
} else {
|
267 |
+
setTimeout(typesetAnswerIfReady, 200);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
}
|
269 |
};
|
270 |
|
271 |
+
// Fonction pour déclencher la mise à jour de l'affichage
|
272 |
const updateDisplay = async () => {
|
273 |
+
// Mise à jour du contenu via marked
|
274 |
+
thoughtsContent.innerHTML = marked.parse(thoughtsBuffer);
|
275 |
+
answerContent.innerHTML = marked.parse(answerBuffer);
|
276 |
+
|
277 |
+
// Lancer le rendu MathJax
|
278 |
+
await typesetAnswerIfReady();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
updateTimeout = null;
|
280 |
};
|
281 |
|
282 |
// Fonction pour planifier la mise à jour (dé-bounce)
|
283 |
const scheduleUpdate = () => {
|
284 |
+
if (updateTimeout) return;
|
285 |
+
updateTimeout = setTimeout(updateDisplay, 200);
|
|
|
|
|
286 |
};
|
287 |
|
288 |
+
// Configuration de marked avec support du mode GFM (pour les tableaux) et interprétation des sauts de ligne
|
289 |
marked.setOptions({
|
290 |
gfm: true,
|
291 |
+
breaks: true
|
|
|
|
|
292 |
});
|
293 |
|
294 |
// Soumission du formulaire
|
|
|
321 |
body: formData
|
322 |
});
|
323 |
|
|
|
|
|
|
|
|
|
324 |
const reader = response.body.getReader();
|
325 |
const decoder = new TextDecoder();
|
326 |
let buffer = '';
|
|
|
328 |
// Traitement d'un chunk de données
|
329 |
const processChunk = async chunk => {
|
330 |
buffer += decoder.decode(chunk, { stream: true });
|
331 |
+
const lines = buffer.split('\n\n');
|
332 |
+
buffer = lines.pop(); // Conserver la dernière ligne incomplète
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
333 |
|
334 |
for (const line of lines) {
|
335 |
if (!line.startsWith('data:')) continue;
|
336 |
+
const data = JSON.parse(line.slice(5));
|
|
|
337 |
|
338 |
+
if (data.mode) {
|
339 |
+
currentMode = data.mode;
|
340 |
+
loader.classList.add('hidden');
|
341 |
+
solutionSection.classList.remove('hidden');
|
342 |
+
}
|
343 |
+
if (data.content) {
|
344 |
+
if (currentMode === 'thinking') {
|
345 |
+
thoughtsBuffer += data.content;
|
346 |
+
} else if (currentMode === 'answering') {
|
347 |
+
answerBuffer += data.content;
|
|
|
348 |
}
|
|
|
|
|
349 |
}
|
350 |
}
|
351 |
+
// Planifier la mise à jour dé-bouncée
|
|
|
352 |
scheduleUpdate();
|
353 |
};
|
354 |
|
|
|
356 |
while (true) {
|
357 |
const { done, value } = await reader.read();
|
358 |
if (done) {
|
359 |
+
// Traitement du contenu restant dans le buffer
|
360 |
+
if (buffer) {
|
361 |
+
const data = JSON.parse(buffer.slice(5));
|
362 |
+
if (data.content) {
|
363 |
+
if (currentMode === 'thinking') {
|
364 |
+
thoughtsBuffer += data.content;
|
365 |
+
} else if (currentMode === 'answering') {
|
366 |
+
answerBuffer += data.content;
|
|
|
|
|
367 |
}
|
|
|
|
|
368 |
}
|
369 |
}
|
370 |
+
scheduleUpdate();
|
|
|
|
|
|
|
|
|
|
|
|
|
371 |
break;
|
372 |
}
|
373 |
await processChunk(value);
|
|
|
375 |
stopTimer();
|
376 |
} catch (error) {
|
377 |
console.error('Erreur:', error);
|
378 |
+
alert('Une erreur est survenue.');
|
379 |
loader.classList.add('hidden');
|
380 |
stopTimer();
|
381 |
}
|
382 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
383 |
});
|
384 |
</script>
|
385 |
</body>
|