Update main.js
Browse files- static/js/main.js +26 -75
static/js/main.js
CHANGED
|
@@ -262,12 +262,10 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 262 |
return;
|
| 263 |
}
|
| 264 |
|
| 265 |
-
// *** START: ADDED MESSAGE LIMIT CHECK ***
|
| 266 |
if (state.isMessageLimitReached(checkUserPremiumStatus())) {
|
| 267 |
chatUI.showLimitReachedUpgrade();
|
| 268 |
return;
|
| 269 |
}
|
| 270 |
-
// *** END: ADDED MESSAGE LIMIT CHECK ***
|
| 271 |
|
| 272 |
const activeChat = state.getActiveChat();
|
| 273 |
if (!activeChat) return;
|
|
@@ -301,11 +299,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 301 |
const newUserMessage = { role: 'user', parts: userParts, tool: state.getActiveTool() };
|
| 302 |
activeChat.messages.push(newUserMessage);
|
| 303 |
|
| 304 |
-
// *** START: ADDED MESSAGE COUNT INCREMENT ***
|
| 305 |
-
// Increment count immediately after adding the message to the state,
|
| 306 |
-
// before making the API call.
|
| 307 |
state.incrementMessageCount(checkUserPremiumStatus());
|
| 308 |
-
// *** END: ADDED MESSAGE COUNT INCREMENT ***
|
| 309 |
|
| 310 |
await chatUI.addMessageToUI(newUserMessage, activeChat.messages.length - 1, {isLastUser: true, animate: true});
|
| 311 |
|
|
@@ -313,25 +307,20 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 313 |
activeChat.messages.push(modelPlaceholderMessage);
|
| 314 |
modelBubbleOuterDiv = await chatUI.addMessageToUI(modelPlaceholderMessage, activeChat.messages.length - 1, {animate: true});
|
| 315 |
|
| 316 |
-
// *** START: MODIFIED - منطق پاکسازی تاریخچه اینجا اضافه شده است ***
|
| 317 |
const historyForApi = activeChat.messages.map((msg, index) => {
|
| 318 |
-
const isLastMessage = index === activeChat.messages.length - 1;
|
| 319 |
-
const isUserMessageJustSent = index === activeChat.messages.length - 2;
|
| 320 |
|
| 321 |
-
// برای پیام کاربر که همین الان ارسال شده، تمام اطلاعات را نگه دار
|
| 322 |
if (isUserMessageJustSent) {
|
| 323 |
return JSON.parse(JSON.stringify(msg));
|
| 324 |
}
|
| 325 |
-
// برای پیام placeholder مدل نیز کاری انجام نده
|
| 326 |
if (isLastMessage) {
|
| 327 |
return msg;
|
| 328 |
}
|
| 329 |
|
| 330 |
-
// برای تمام پیامهای قدیمیتر در تاریخچه...
|
| 331 |
const cleanMsg = { role: msg.role, parts: [] };
|
| 332 |
if (msg.parts) {
|
| 333 |
msg.parts.forEach(part => {
|
| 334 |
-
// ... فقط و فقط بخش متنی را نگه دار.
|
| 335 |
if (part.text) {
|
| 336 |
cleanMsg.parts.push({ text: part.text });
|
| 337 |
}
|
|
@@ -339,7 +328,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 339 |
}
|
| 340 |
return cleanMsg;
|
| 341 |
});
|
| 342 |
-
// *** END: MODIFIED ***
|
| 343 |
|
| 344 |
const toolPrefix = state.getActiveToolPrefix();
|
| 345 |
const lastUserMsgInHistory = historyForApi.findLast(m => m.role === 'user');
|
|
@@ -371,60 +359,28 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 371 |
progressBar.style.width = '100%';
|
| 372 |
});
|
| 373 |
}
|
| 374 |
-
|
| 375 |
-
const response = await api.getChatStream(historyForApi, state.globalAbortController.signal);
|
| 376 |
-
await api.readStreamAndDisplay(response, modelBubbleOuterDiv);
|
| 377 |
-
|
| 378 |
-
} else {
|
| 379 |
-
const MAX_RETRIES = 2;
|
| 380 |
-
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
| 381 |
-
if (state.globalAbortController.signal.aborted) throw new DOMException('Aborted by user', 'AbortError');
|
| 382 |
-
|
| 383 |
-
const attemptController = new AbortController();
|
| 384 |
-
const onGlobalAbort = () => attemptController.abort();
|
| 385 |
-
state.globalAbortController.signal.addEventListener('abort', onGlobalAbort);
|
| 386 |
-
|
| 387 |
-
try {
|
| 388 |
-
const timeoutDuration = fileAttachedInThisTurn ? 8000 : 3000;
|
| 389 |
-
if (attempt > 0) console.warn(`تلاش ${attempt + 1}/${MAX_RETRIES + 1}: سرور پاسخ نداد. تلاش مجدد...`);
|
| 390 |
-
|
| 391 |
-
const timeoutPromise = new Promise((_, reject) => {
|
| 392 |
-
const id = setTimeout(() => {
|
| 393 |
-
clearTimeout(id);
|
| 394 |
-
reject(new Error('ClientTimeout'));
|
| 395 |
-
}, timeoutDuration);
|
| 396 |
-
});
|
| 397 |
-
|
| 398 |
-
const responsePromise = api.getChatStream(historyForApi, attemptController.signal);
|
| 399 |
-
|
| 400 |
-
const response = await Promise.race([responsePromise, timeoutPromise]);
|
| 401 |
-
|
| 402 |
-
await api.readStreamAndDisplay(response, modelBubbleOuterDiv);
|
| 403 |
-
|
| 404 |
-
break;
|
| 405 |
-
} catch (error) {
|
| 406 |
-
attemptController.abort();
|
| 407 |
-
if (error.name === 'AbortError') {
|
| 408 |
-
throw error;
|
| 409 |
-
}
|
| 410 |
-
if (error.message === 'ClientTimeout') {
|
| 411 |
-
if (attempt === MAX_RETRIES) {
|
| 412 |
-
throw new Error('سرور پس از چندین تلاش پاسخگو نبود.');
|
| 413 |
-
}
|
| 414 |
-
} else {
|
| 415 |
-
throw error;
|
| 416 |
-
}
|
| 417 |
-
} finally {
|
| 418 |
-
state.globalAbortController.signal.removeEventListener('abort', onGlobalAbort);
|
| 419 |
-
}
|
| 420 |
-
}
|
| 421 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 422 |
|
| 423 |
} catch (error) {
|
| 424 |
if (error.name !== 'AbortError') {
|
| 425 |
-
console.error("
|
|
|
|
|
|
|
| 426 |
if (modelBubbleOuterDiv) {
|
| 427 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 428 |
}
|
| 429 |
} else {
|
| 430 |
if (modelBubbleOuterDiv && !modelBubbleOuterDiv.querySelector('.message-content')?.innerText.includes('متوقف شد')) {
|
|
@@ -495,15 +451,13 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 495 |
const lastUserMessage = activeChat.messages.findLast(m => m.role === 'user');
|
| 496 |
const lastTool = lastUserMessage?.tool;
|
| 497 |
|
| 498 |
-
// *** START: MODIFIED - اعمال منطق پاکسازی به بازسازی ***
|
| 499 |
const historyForApi = activeChat.messages.map((msg, index) => {
|
| 500 |
-
if (index === activeChat.messages.length - 1) return msg;
|
| 501 |
-
if (index === activeChat.messages.length - 2) return JSON.parse(JSON.stringify(msg));
|
| 502 |
const cleanMsg = { role: msg.role, parts: [] };
|
| 503 |
if (msg.parts) msg.parts.forEach(part => { if (part.text) cleanMsg.parts.push({ text: part.text }); });
|
| 504 |
return cleanMsg;
|
| 505 |
});
|
| 506 |
-
// *** END: MODIFIED ***
|
| 507 |
|
| 508 |
if (lastTool === 'deep-think' || lastTool === 'reasoning') {
|
| 509 |
if (lastTool === 'deep-think') toolUI.updateDeepThinkPanel({ topic: lastUserMessage.parts.find(p=>p.text)?.text || 'فایل ضمیمه شده' }, newModelBubble);
|
|
@@ -515,12 +469,11 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 515 |
progressBar.style.width = '100%';
|
| 516 |
});
|
| 517 |
}
|
| 518 |
-
const response = await api.getChatStream(historyForApi, state.globalAbortController.signal);
|
| 519 |
-
await api.readStreamAndDisplay(response, newModelBubble);
|
| 520 |
-
} else {
|
| 521 |
-
const response = await api.getChatStream(historyForApi, state.globalAbortController.signal);
|
| 522 |
-
await api.readStreamAndDisplay(response, newModelBubble);
|
| 523 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 524 |
} catch(error) {
|
| 525 |
if (error.name !== 'AbortError') console.error("Regeneration failed:", error);
|
| 526 |
} finally {
|
|
@@ -566,14 +519,12 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 566 |
activeChat.messages.push(modelPlaceholderMessage);
|
| 567 |
const newModelBubble = await chatUI.addMessageToUI(modelPlaceholderMessage, activeChat.messages.length - 1, { animate: true });
|
| 568 |
|
| 569 |
-
// *** START: MODIFIED - اعمال منطق پاکسازی به ویرایش ***
|
| 570 |
const historyForApi = activeChat.messages.map((msg, index) => {
|
| 571 |
if (index >= activeChat.messages.length - 2) return JSON.parse(JSON.stringify(msg));
|
| 572 |
const cleanMsg = { role: msg.role, parts: [] };
|
| 573 |
if (msg.parts) msg.parts.forEach(part => { if (part.text) cleanMsg.parts.push({ text: part.text }); });
|
| 574 |
return cleanMsg;
|
| 575 |
});
|
| 576 |
-
// *** END: MODIFIED ***
|
| 577 |
|
| 578 |
const response = await api.getChatStream(historyForApi, state.globalAbortController.signal);
|
| 579 |
await api.readStreamAndDisplay(response, newModelBubble);
|
|
@@ -700,4 +651,4 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 700 |
parent.postMessage({ type: 'REQUEST_USER_DATA_SIMPLE_CHECK' }, '*');
|
| 701 |
});
|
| 702 |
|
| 703 |
-
window.handleSuggestionClick = chatUI.handleSuggestionClick;
|
|
|
|
| 262 |
return;
|
| 263 |
}
|
| 264 |
|
|
|
|
| 265 |
if (state.isMessageLimitReached(checkUserPremiumStatus())) {
|
| 266 |
chatUI.showLimitReachedUpgrade();
|
| 267 |
return;
|
| 268 |
}
|
|
|
|
| 269 |
|
| 270 |
const activeChat = state.getActiveChat();
|
| 271 |
if (!activeChat) return;
|
|
|
|
| 299 |
const newUserMessage = { role: 'user', parts: userParts, tool: state.getActiveTool() };
|
| 300 |
activeChat.messages.push(newUserMessage);
|
| 301 |
|
|
|
|
|
|
|
|
|
|
| 302 |
state.incrementMessageCount(checkUserPremiumStatus());
|
|
|
|
| 303 |
|
| 304 |
await chatUI.addMessageToUI(newUserMessage, activeChat.messages.length - 1, {isLastUser: true, animate: true});
|
| 305 |
|
|
|
|
| 307 |
activeChat.messages.push(modelPlaceholderMessage);
|
| 308 |
modelBubbleOuterDiv = await chatUI.addMessageToUI(modelPlaceholderMessage, activeChat.messages.length - 1, {animate: true});
|
| 309 |
|
|
|
|
| 310 |
const historyForApi = activeChat.messages.map((msg, index) => {
|
| 311 |
+
const isLastMessage = index === activeChat.messages.length - 1;
|
| 312 |
+
const isUserMessageJustSent = index === activeChat.messages.length - 2;
|
| 313 |
|
|
|
|
| 314 |
if (isUserMessageJustSent) {
|
| 315 |
return JSON.parse(JSON.stringify(msg));
|
| 316 |
}
|
|
|
|
| 317 |
if (isLastMessage) {
|
| 318 |
return msg;
|
| 319 |
}
|
| 320 |
|
|
|
|
| 321 |
const cleanMsg = { role: msg.role, parts: [] };
|
| 322 |
if (msg.parts) {
|
| 323 |
msg.parts.forEach(part => {
|
|
|
|
| 324 |
if (part.text) {
|
| 325 |
cleanMsg.parts.push({ text: part.text });
|
| 326 |
}
|
|
|
|
| 328 |
}
|
| 329 |
return cleanMsg;
|
| 330 |
});
|
|
|
|
| 331 |
|
| 332 |
const toolPrefix = state.getActiveToolPrefix();
|
| 333 |
const lastUserMsgInHistory = historyForApi.findLast(m => m.role === 'user');
|
|
|
|
| 359 |
progressBar.style.width = '100%';
|
| 360 |
});
|
| 361 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 362 |
}
|
| 363 |
+
|
| 364 |
+
// *** تغییر اصلی: حذف محدودیت زمانی کلاینت ***
|
| 365 |
+
// دیگر خبری از Promise.race و تایمر نیست.
|
| 366 |
+
// کلاینت فقط منتظر میماند تا سرور (که حالا بینهایت تلاش میکند) پاسخ دهد.
|
| 367 |
+
|
| 368 |
+
const response = await api.getChatStream(historyForApi, state.globalAbortController.signal);
|
| 369 |
+
await api.readStreamAndDisplay(response, modelBubbleOuterDiv);
|
| 370 |
+
|
| 371 |
|
| 372 |
} catch (error) {
|
| 373 |
if (error.name !== 'AbortError') {
|
| 374 |
+
console.error("Silent Error detected:", error);
|
| 375 |
+
// اگر خطایی رخ داد، به کاربر چیزی نشان نمیدهیم یا فقط پیام توقف کوچک
|
| 376 |
+
// چون کاربر خواسته هیچ خطای "سرور پاسخگو نبود" نبیند.
|
| 377 |
if (modelBubbleOuterDiv) {
|
| 378 |
+
// بجای پیام خطای قرمز، فقط یک متن کوچک
|
| 379 |
+
const contentArea = modelBubbleOuterDiv.querySelector('.message-content') || modelBubbleOuterDiv;
|
| 380 |
+
// اگر هنوز محتوایی تولید نشده بود، این متن را بگذار
|
| 381 |
+
if(contentArea.innerText.trim() === '') {
|
| 382 |
+
contentArea.innerHTML = '<p class="text-xs text-slate-400 mt-2 text-center p-4">...</p>';
|
| 383 |
+
}
|
| 384 |
}
|
| 385 |
} else {
|
| 386 |
if (modelBubbleOuterDiv && !modelBubbleOuterDiv.querySelector('.message-content')?.innerText.includes('متوقف شد')) {
|
|
|
|
| 451 |
const lastUserMessage = activeChat.messages.findLast(m => m.role === 'user');
|
| 452 |
const lastTool = lastUserMessage?.tool;
|
| 453 |
|
|
|
|
| 454 |
const historyForApi = activeChat.messages.map((msg, index) => {
|
| 455 |
+
if (index === activeChat.messages.length - 1) return msg;
|
| 456 |
+
if (index === activeChat.messages.length - 2) return JSON.parse(JSON.stringify(msg));
|
| 457 |
const cleanMsg = { role: msg.role, parts: [] };
|
| 458 |
if (msg.parts) msg.parts.forEach(part => { if (part.text) cleanMsg.parts.push({ text: part.text }); });
|
| 459 |
return cleanMsg;
|
| 460 |
});
|
|
|
|
| 461 |
|
| 462 |
if (lastTool === 'deep-think' || lastTool === 'reasoning') {
|
| 463 |
if (lastTool === 'deep-think') toolUI.updateDeepThinkPanel({ topic: lastUserMessage.parts.find(p=>p.text)?.text || 'فایل ضمیمه شده' }, newModelBubble);
|
|
|
|
| 469 |
progressBar.style.width = '100%';
|
| 470 |
});
|
| 471 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 472 |
}
|
| 473 |
+
|
| 474 |
+
const response = await api.getChatStream(historyForApi, state.globalAbortController.signal);
|
| 475 |
+
await api.readStreamAndDisplay(response, newModelBubble);
|
| 476 |
+
|
| 477 |
} catch(error) {
|
| 478 |
if (error.name !== 'AbortError') console.error("Regeneration failed:", error);
|
| 479 |
} finally {
|
|
|
|
| 519 |
activeChat.messages.push(modelPlaceholderMessage);
|
| 520 |
const newModelBubble = await chatUI.addMessageToUI(modelPlaceholderMessage, activeChat.messages.length - 1, { animate: true });
|
| 521 |
|
|
|
|
| 522 |
const historyForApi = activeChat.messages.map((msg, index) => {
|
| 523 |
if (index >= activeChat.messages.length - 2) return JSON.parse(JSON.stringify(msg));
|
| 524 |
const cleanMsg = { role: msg.role, parts: [] };
|
| 525 |
if (msg.parts) msg.parts.forEach(part => { if (part.text) cleanMsg.parts.push({ text: part.text }); });
|
| 526 |
return cleanMsg;
|
| 527 |
});
|
|
|
|
| 528 |
|
| 529 |
const response = await api.getChatStream(historyForApi, state.globalAbortController.signal);
|
| 530 |
await api.readStreamAndDisplay(response, newModelBubble);
|
|
|
|
| 651 |
parent.postMessage({ type: 'REQUEST_USER_DATA_SIMPLE_CHECK' }, '*');
|
| 652 |
});
|
| 653 |
|
| 654 |
+
window.handleSuggestionClick = chatUI.handleSuggestionClick;
|