feat(assistant): авто-здоровье провайдеров + ручная проверка (фича 4/6)
Новый модуль assistant-health.js (по образцу classroom-cleanup): каждые 15 мин
пингует каждого провайдера (pingLLM) → app_settings.assistant_health
{ id:{ok,at,error,ms,fails} }. Авто-понижение: если активный провайдер
не отвечает 2+ раза подряд, а есть здоровый рабочий запасной — автоматически
переключает assistant_active и пишет assistant_failover (баннер «health»).
schedule() из server.js (unref).
Админка: тумблер «Авто-проверка провайдеров», кнопка «Проверить сейчас»
(POST /admin/assistant/health → runHealth), цветной индикатор здоровья на
каждой карточке провайдера (зелёный/красный + время/ошибка в title).
keyless-шлюзы и провайдеры без ключа учтены.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1008,6 +1008,8 @@ function getAssistant(_req, res) {
|
||||
providers, activeId, active,
|
||||
rag: _aset('assistant_rag') !== '0', examButtons: _aset('assistant_exam_buttons') === '1',
|
||||
memory: _aset('assistant_memory') !== '0', socratic: _aset('assistant_socratic') === '1',
|
||||
healthEnabled: _aset('assistant_health_enabled') !== '0',
|
||||
health: (() => { try { return JSON.parse(_aset('assistant_health') || '{}') || {}; } catch (e) { return {}; } })(),
|
||||
chunks, usage, usage30, feedback, failover, presets: ASSISTANT_PRESETS,
|
||||
kiloModels: _kiloModels(), kiloModelsCustom: !!_aset('assistant_kilo_models'),
|
||||
});
|
||||
@@ -1021,6 +1023,7 @@ function saveAssistant(req, res) {
|
||||
if (typeof b.examButtons === 'boolean') set('assistant_exam_buttons', b.examButtons ? '1' : '0');
|
||||
if (typeof b.memory === 'boolean') set('assistant_memory', b.memory ? '1' : '0');
|
||||
if (typeof b.socratic === 'boolean') set('assistant_socratic', b.socratic ? '1' : '0');
|
||||
if (typeof b.healthEnabled === 'boolean') set('assistant_health_enabled', b.healthEnabled ? '1' : '0');
|
||||
if (b.dismissFailover) { try { db.prepare("DELETE FROM app_settings WHERE key = 'assistant_failover'").run(); } catch (e) {} }
|
||||
audit(req, 'assistant.config', 'assistant', 'настройки');
|
||||
res.json({ ok: true });
|
||||
@@ -1210,6 +1213,15 @@ function applyModels(req, res) {
|
||||
res.json({ ok: true, count: clean.length });
|
||||
}
|
||||
|
||||
/* POST /api/admin/assistant/health — прогнать проверку здоровья провайдеров сейчас */
|
||||
async function runHealth(req, res) {
|
||||
try {
|
||||
const r = await require('../assistant-health').runHealthCheck();
|
||||
audit(req, 'assistant.health', 'assistant', 'ручная проверка');
|
||||
res.json({ ok: true, result: r });
|
||||
} catch (e) { res.status(500).json({ ok: false, error: e.message || 'ошибка' }); }
|
||||
}
|
||||
|
||||
/* POST /api/admin/assistant/active { id } — выбрать активного провайдера */
|
||||
function setActiveProvider(req, res) {
|
||||
const id = String((req.body && req.body.id) || '');
|
||||
@@ -1323,5 +1335,5 @@ module.exports = {
|
||||
getTopics, createTopic, updateTopic, deleteTopic,
|
||||
broadcast,
|
||||
getAssistant, saveAssistant, testAssistant, reindexTextbooks, saveProvider, deleteProvider, setActiveProvider, getProviderModels,
|
||||
scanModels, probeModel, applyModels,
|
||||
scanModels, probeModel, applyModels, runHealth,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user