From e38abff02ae72a15cc6d9e4e35b11caf5ebe64b2 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Wed, 24 Jun 2026 23:07:11 +0300 Subject: [PATCH] =?UTF-8?q?feat(assistant):=20=D1=81=D1=80=D0=BE=D0=BA=20?= =?UTF-8?q?=D0=B6=D0=B8=D0=B7=D0=BD=D0=B8=20=D0=B4=D0=B8=D0=B0=D0=BB=D0=BE?= =?UTF-8?q?=D0=B3=D0=B0=20=E2=80=94=207=20=D0=B4=D0=BD=D0=B5=D0=B9=20?= =?UTF-8?q?=D0=B1=D0=B5=D0=B7=20=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit saveChat пишет метку времени, loadChat сбрасывает диалог, если с последней реплики прошло больше CHAT_TTL (7 дней). Обратная совместимость со старым форматом-массивом. Сноска обновлена. Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/js/assistant.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/frontend/js/assistant.js b/frontend/js/assistant.js index 2caa739..2267dbc 100644 --- a/frontend/js/assistant.js +++ b/frontend/js/assistant.js @@ -546,10 +546,22 @@ var SUGGESTIONS = ['Как вырезать кусок учебника?', 'Как создать карточки?', 'Как начать тест?', 'Объясни теорему Пифагора', 'Где мои домашние задания?', 'Как включить тёмную тему?']; var TEACHER_SUGGESTIONS = ['Как создать класс и выдать задание?', 'Идеи заданий по теме…', 'Составь план урока по теме…', 'Как работает журнал и аналитика?', 'Как провести онлайн-урок?']; var _chat = []; // многоходовой диалог: [{role:'user'|'assistant', content}] - // Диалог переживает обновление/переходы (localStorage, per-user), пока ученик сам не нажмёт «Очистить». + // Диалог переживает обновление/переходы (localStorage, per-user), пока ученик сам не нажмёт «Очистить» + // или пока не пройдёт CHAT_TTL без новых сообщений (срок жизни от последней реплики). + var CHAT_TTL = 7 * 24 * 3600 * 1000; // 7 дней function _chatKey() { try { var u = LS.getUser && LS.getUser(); return u && u.id ? 'asst_chat_' + u.id : null; } catch (e) { return null; } } - function saveChat() { var k = _chatKey(); if (k) lsSet(k, JSON.stringify(_chat.slice(-30))); } - function loadChat() { var k = _chatKey(); if (!k) return; try { var a = JSON.parse(lsGet(k) || '[]'); if (Array.isArray(a)) _chat = a.filter(function (m) { return m && (m.role === 'user' || m.role === 'assistant') && typeof m.content === 'string'; }); } catch (e) {} } + function saveChat() { var k = _chatKey(); if (k) lsSet(k, JSON.stringify({ t: Date.now(), c: _chat.slice(-30) })); } + function loadChat() { + var k = _chatKey(); if (!k) return; + try { + var raw = JSON.parse(lsGet(k) || 'null'), arr, ts = null; + if (Array.isArray(raw)) arr = raw; // старый формат (без метки времени) + else if (raw && Array.isArray(raw.c)) { arr = raw.c; ts = raw.t; } + else return; + if (ts && (Date.now() - ts) > CHAT_TTL) { clearChatStore(); return; } // протух — забываем + _chat = arr.filter(function (m) { return m && (m.role === 'user' || m.role === 'assistant') && typeof m.content === 'string'; }); + } catch (e) {} + } function clearChatStore() { var k = _chatKey(); if (k) try { localStorage.removeItem(k); } catch (e) {} } function msgEl(role) { var d = document.createElement('div'); d.className = 'asst-msg asst-msg-' + role; return d; } function renderChat(chatEl) { @@ -598,7 +610,7 @@ '
' + '
' + '
' + _svg('') + - 'Держу в голове ход беседы — последние ~14 сообщений. Диалог сохраняется между заходами и обновлениями страницы, пока ты сам не нажмёшь «Очистить».
', {}); + 'Держу в голове ход беседы — последние ~14 сообщений. Диалог сохраняется между заходами, пока ты сам не нажмёшь «Очистить» или пока не пройдёт неделя без общения.', {}); var inp = bubble.querySelector('.asst-ask-in'); var chatEl = bubble.querySelector('.asst-chat'); var chipsEl = bubble.querySelector('.asst-chips');