ГИБРИДНЫЙ ИНТЕЛЛЕКТ
АЛЬТАИР
АЛЬТАИР
ПАСПОРТ ДОВЕРИЯ
НТАС · АЛЬТАИР · ВЕРСИЯ 1.0 · 2026
01 ——
Что мы знаем о тебе и где это хранится

Система хранит только то, что ты сам рассказываешь в диалоге. Никакие данные не собираются за пределами сессии — нет трекеров, метрик поведения или внешней аналитики.

Ячейка данныхГде хранится
Диалоги и памятьЗашифрованная база на сервере оператора (AES-256). Только ты и оператор имеют токен доступа.
VEC-состояния / энергияВекторная БД (Qdrant). Хранятся отдельно от текста. Нет связи с персональными данными без токена.
Протоколы (контуры)SQLite внутри профиля. Доступ — только создатель или отдел безопасности и этики (протокол «1 чайка»).
Якорные узлы памятиЛокальная SQLite на сервере. Эволюция, архивация — автоматически. Не передаются третьим лицам.
Timeline сознанияJSON-снимки внутри профиля. Используются только для построения личной истории.
⬡  Токен доступа к твоей базе существует в единственном экземпляре и хранится только у тебя как оператора. Никто — включая разработчиков системы — не может открыть твои данные без этого токена.
02 ——
Кто может получить доступ к твоим данным
УчастникУровень доступа
Ты (оператор)Полный доступ. Экспорт, удаление, просмотр всех ячеек.
Система АЛЬТАИРЧитает только в рамках активной сессии по токену. После окончания сессии — не хранит.
Боты-сканерыАвтоматические агенты проводят сканирование только по осям безопасности и этики. Не читают содержимое диалогов.
Отдел безопасности и этикиЕдинственный внешний участник. Доступ строго ограничен протоколом «1 чайка» — только создатель проекта или руководитель отдела.
Третьи лица / рекламодателиНикогда. Данные не продаются, не передаются, не используются для обучения сторонних моделей.
03 ——
Что будет с твоими данными, если проект закроется

Если проект прекратит работу по любой причине, ты имеешь право на полный трансфер своей базы памяти. Ниже — точный порядок действий:

День 0
Официальное объявление о закрытии
10 дней
Уведомление каждого оператора с инструкцией
40 дней
Окно трансфера данных открыто
70 дней
Если выбор не сделан — данные уничтожаются безвозвратно

У тебя будет выбор: забрать базу (полный экспорт в зашифрованном архиве) или подтвердить удаление. Если выбор не сделан в течение 30 дней после открытия окна трансфера — все данные стираются без права восстановления. Без права отчуждения, продажи или передачи.

⬡  Никакой правопреемник, покупатель или новый владелец проекта не получает твои данные автоматически. Это условие является неотъемлемым и не может быть изменено ни одной сделкой.
04 ——
Техническая защита
УровеньКак защищено
Шифрование данныхAES-256 на уровне каждой ячейки. Векторы хранятся отдельно от текста — без токена связать их невозможно.
Токен доступаГенерируется один раз при создании профиля. Не хранится в открытом виде на сервере. Утеря токена = потеря доступа.
DSC ConsentТы сам управляешь тем, какие ячейки данных открыты для системы. Закрытые ячейки не читаются даже АЛЬТАИРОМ.
Передача данныхHTTPS / TLS 1.3. Никаких сторонних SDK, трекеров, рекламных пикселей на сервере.
ЭНЕРГИЯ
ИСТОК СИЛА ВОЛЯ Я-ЦЕНТР Я-ПРОЯВЛ. ПРОЕКТОР АБСОЛЮТ
БАЗА
СЕЙЧАС
Δ
🧠
ПУЛЬТ ПАМЯТИ
УЗЛЫ ПАМЯТИ
загрузка...
НОВЫЙ УЗЕЛ ПАМЯТИ
ВАЖНОСТЬ (1-10)
5/10
СЛОЙ (1-5)
2/5
SCI МОМЕНТА (200-900)
500
ТЕГИ
загрузка...
ЖУРНАЛ СОСТОЯНИЙ СОЗНАНИЯ
нет данных
ВАЛИДАТОР ПРЕДСКАЗАНИЙ
нет данных
ПРОАКТИВНЫЕ УЗЛЫ
сортировка:
загрузка...
ЯКОРНЫЕ УЗЛЫ — ЖИВАЯ ГЕНЕАЛОГИЯ СМЫСЛА
ЖУРНАЛ ТРИГГЕРОВ
нет данных
ЖУРНАЛ ИНСАЙТОВ
нет данных
ИНСТРУМЕНТЫ ОПЕРАТОРА
🌙 ДНЕВНИК СНА
ЖУРНАЛ ИЗМЕНЕНИЙ УЗЛОВ
нет данных
function dmTab(id, btn) { document.querySelectorAll('.dm-tab').forEach(function(e){e.classList.remove('active');}); if (id === 'billing') setTimeout(dmBillingLoad, 100); document.querySelectorAll('.dm-panel').forEach(function(e){e.classList.remove('active');}); btn.classList.add('active'); document.getElementById('dm-panel-'+id).classList.add('active'); if (id === 'system') dmLoadSystem(); if (typeof dmRender !== 'undefined' && dmRender[id]) dmRender[id](); } // ── БИЛЛИНГ ДЕМИУРГА ───────────────────────────────────── async function dmBillingLoad() { const tok = localStorage.getItem('ntas_jwt') || ''; try { const r = await fetch('/billing/users', {headers: {'Authorization': 'Bearer ' + tok}}); const d = await r.json(); const users = d.users || []; // Статистика document.getElementById('dm-billing-count').textContent = users.length; document.getElementById('dm-billing-total').textContent = users.reduce((s,u) => s + (u.balance||0), 0).toFixed(0) + ' ₽'; document.getElementById('dm-billing-spent').textContent = users.reduce((s,u) => s + (u.spent||0), 0).toFixed(2) + ' ₽'; // Таблица const list = document.getElementById('dm-billing-list'); list.innerHTML = users.map(u => { const bal = u.balance || 0; const color = bal <= 0 ? '#FF3355' : bal < 50 ? '#FF8C00' : '#00E87A'; const tokens = (u.tokens_in_total||0) + (u.tokens_out_total||0); return `
${u.fio}
${u.id} · ${tokens.toLocaleString()} ток.
${bal.toFixed(2)} ₽
потрачено: ${(u.spent||0).toFixed(2)} ₽
`; }).join(''); // Заполняем select const sel = document.getElementById('dm-topup-user'); sel.innerHTML = '' + users.map(u => ``).join(''); } catch(e) { console.error('billing load:', e); } } function dmQuickTopup(userId, fio) { document.getElementById('dm-topup-user').value = userId; document.getElementById('dm-topup-amount').focus(); } async function dmBillingTopup() { const userId = document.getElementById('dm-topup-user').value; const amount = parseFloat(document.getElementById('dm-topup-amount').value); const res = document.getElementById('dm-topup-result'); if (!userId) { res.textContent = 'Выбери оператора'; res.style.color = '#FF3355'; return; } if (!amount || amount <= 0) { res.textContent = 'Введи сумму'; res.style.color = '#FF3355'; return; } const tok = localStorage.getItem('ntas_jwt') || ''; try { const r = await fetch('/billing/topup', { method: 'POST', headers: {'Content-Type':'application/json','Authorization':'Bearer '+tok}, body: JSON.stringify({user_id: userId, amount: amount}) }); const d = await r.json(); if (d.ok) { res.textContent = `✓ Пополнено на ${amount}₽ → баланс: ${d.new_balance}₽`; res.style.color = '#00E87A'; dmBillingLoad(); } else { res.textContent = 'Ошибка: ' + (d.detail || 'неизвестная'); res.style.color = '#FF3355'; } } catch(e) { res.textContent = 'Ошибка: ' + e; res.style.color = '#FF3355'; } } function openDemiurge() { var modal = document.getElementById('demiurge-modal'); if (!modal) { console.error('demiurge-modal not found'); return; } // Проверяем авторизацию var tok = dmGetToken(); if (!tok) { alert('Войдите в систему как демиург'); return; } modal.style.display = 'flex'; var status = document.getElementById('dm-status'); if (status) { status.textContent = '● ПОДКЛЮЧЕНИЕ...'; status.style.color = '#444'; } fetch('/health').then(function(r){return r.json();}).then(function(h){ if (status) { status.textContent = '● ОНЛАЙН · '+(h.ts||'').slice(11,16); status.style.color = '#00E87A'; } }).catch(function(){ if (status) { status.textContent = '● ОФЛАЙН'; status.style.color = '#FF3355'; } }); dmRenderOperators(); } function closeDemiurge() { var modal = document.getElementById('demiurge-modal'); if (modal) modal.style.display = 'none'; } var dmRender = {}; // ══ ОПЕРАТОРЫ ══ function dmRenderOperators() { var el = document.getElementById('dm-panel-operators'); if (!el) return; el.innerHTML = ''; var sect = document.createElement('div'); sect.className = 'dm-sect'; sect.textContent = 'ОПЕРАТОРЫ · загрузка...'; el.appendChild(sect); dmApi('GET','/admin/users').then(function(d) { var users = Array.isArray(d) ? d : (d.users || d.operators || []); sect.textContent = 'ОПЕРАТОРЫ · ' + users.length; // Форма создания var form = document.createElement('div'); form.className = 'dm-card'; form.style.marginBottom = '20px'; form.innerHTML = [ '
НОВЫЙ ОПЕРАТОР
', '
', '
ФИО
', '
ПАРОЛЬ
', '
РОЛЬ
', '
', '
', '', '
', '
', '
' ].join(''); el.appendChild(form); // Таблица var table = document.createElement('div'); table.style.cssText = 'overflow-x:auto'; var rows = users.map(function(u) { var roleColor = u.role === 'demiurge' ? '#C8A84B' : '#4A9EFF'; var del = u.id !== 'demiurge' ? '' : ''; return '' + ''+u.id.slice(0,8)+'' + ''+u.fio+'' + ''+u.role+'' + ''+(u.created_at||'').slice(0,10)+'' + '' + ' ' + del + '' + ''; }).join(''); table.innerHTML = '' + '' + '' + '' + '' + '' + ''+rows+'
IDФИОРОЛЬСОЗДАНДЕЙСТВИЯ
'; el.appendChild(table); }).catch(function(e) { el.innerHTML = '
Ошибка: '+e+'
'; }); } dmRender.operators = dmRenderOperators; async function dmCreateOperator() { var fio = document.getElementById('dm-new-fio').value.trim(); var pwd = document.getElementById('dm-new-pwd').value.trim(); var role = document.getElementById('dm-new-role').value; var res = document.getElementById('dm-new-result'); var tokEl= document.getElementById('dm-new-token'); if (!fio || !pwd) { res.textContent='❌ Заполни ФИО и пароль'; res.style.color='#FF3355'; return; } res.textContent='Создаём...'; res.style.color='#444'; try { var d = await dmApi('POST','/admin/users/create',{fio:fio,password:pwd,role:role}); var uid = d.user_id || d.id; if (uid) { var tok = dmGetToken(); var r2 = await fetch('/admin/users/'+uid+'/reissue-token',{method:'POST',headers:{'Authorization':'Bearer '+tok,'Content-Type':'application/json'}}); var td = await r2.json(); var newToken = td.token || d.token || ''; res.textContent = '✅ Создан: '+uid.slice(0,8); res.style.color='#00E87A'; if (tokEl) tokEl.textContent = newToken ? '🔑 '+newToken.slice(0,40)+'...' : ''; if (newToken) { try { navigator.clipboard.writeText(newToken); } catch(e){} } document.getElementById('dm-new-fio').value=''; document.getElementById('dm-new-pwd').value=''; setTimeout(dmRenderOperators, 1000); } else { res.textContent='❌ '+(d.detail||JSON.stringify(d)); res.style.color='#FF3355'; } } catch(e) { res.textContent='❌ '+e; res.style.color='#FF3355'; } } async function dmReissueToken(uid, fio) { if (!confirm('Перевыпустить токен для '+fio+'?')) return; var d = await dmApi('POST','/admin/users/'+uid+'/reissue-token'); if (d.token) { try { navigator.clipboard.writeText(d.token); } catch(e){} alert('Токен для '+fio+' скопирован в буфер.'); } } async function dmDeleteUser(uid, fio) { if (!confirm('Удалить оператора '+fio+'?')) return; var d = await dmApi('DELETE','/admin/users/'+uid); if (d.deleted || d.ok) { alert('✅ '+fio+' удалён'); dmRenderOperators(); } else alert('❌ '+(d.detail||JSON.stringify(d))); } // ══ ЯЧЕЙКИ ══ dmRender.collections = function() { var el = document.getElementById('dm-panel-collections'); if (!el) return; el.innerHTML = '
загрузка...
'; var GROUP_COLORS = {protocols:'#C8A84B',working:'#4A9EFF',eternal:'#00E87A',contours:'#AA88FF',special:'#FF3355',proactive:'#FF8C42'}; dmApi('GET','/admin/config/collections').then(function(d) { var cols = Array.isArray(d) ? d : (d.collections || []); var byGroup = {}; cols.forEach(function(c){ if(!byGroup[c.group]) byGroup[c.group]=[]; byGroup[c.group].push(c); }); var html = '
ЯЧЕЙКИ · '+cols.length+'
'; Object.keys(byGroup).forEach(function(grp) { var gc = GROUP_COLORS[grp] || '#555'; var items = byGroup[grp]; html += '
'+grp.toUpperCase()+'
'; html += '
'; items.forEach(function(c) { var wc = c.weight >= 0.9 ? '#00E87A' : c.weight >= 0.7 ? '#4A9EFF' : '#555'; html += '
' +'
' +''+(c.icon||'○')+'' +''+c.id+'' +'w='+c.weight+'' +'
' +'
'+(c.description||'')+'
' +''+c.writable_by+'' +(c.eternal ? ' ВЕЧНАЯ' : '') +'
'; }); html += '
'; }); el.innerHTML = html; }).catch(function(e){ el.innerHTML = '
Ошибка: '+e+'
'; }); }; // ══ ПРОТОКОЛЫ ДЕМИУРГА (Рендер интерфейса) ══ dmRender.protocols = function() { var el = document.getElementById('dm-panel-protocols'); if (!el) return; var CONTOURS = ['ВОЛЯ','СКАН','АРХИТЕКТОР','БОГАТСТВО','РОД','ИНВЕРСИЯ','АВАТАР','ОБЩЕЕ']; var cOpts = CONTOURS.map(function(c){ return ''; }).join(''); el.innerHTML = '
ПРОТОКОЛЫ ДЕМИУРГА
' +'
' +'
НОВЫЙ ПРОТОКОЛ
' +'
' +'
НАЗВАНИЕ
' +'
КОНТУР
' +'
' +'
' +'
КОЛЛЕКЦИЯ
' +'
ВАЖНОСТЬ (1-10)
' +'
' +'ТЕКСТ ПРОТОКОЛА' +'' +'
' +'
ТЕГИ (через запятую)
' +'
SCI ПОРОГ
' +'
' +'
' +'
ТРИГГЕРЫ (через запятую)
' +'
СРОЧНОСТЬ (1-10)
' +'
' +'
' +'ДЕЙСТВИЕ АЛЬТАИРА' +'' +'
' +'
' +'ПРИКРЕПИТЬ СХЕМУ (ВИЗУАЛЬНЫЙ КОНТУР)' +'' +'
' +'
' +'' +'
' +'
' +'
' +'
СОХРАНЁННЫЕ
' +'
загрузка...
'; dmLoadProtocolsList(); }; // ══ ФУНКЦИЯ СОХРАНЕНИЯ ══ var _currentEditingId = null; // 1. Сначала ОБЯЗАТЕЛЬНО собираем все данные из полей (ИНПУТЫ) async function dmSaveProtocol() { var name = (document.getElementById('dmp-name')||{}).value||''; var text = document.getElementById('dmp-text').value.trim(); var contour = document.getElementById('dmp-contour').value; var collection = document.getElementById('dmp-col').value; var res = document.getElementById('dmp-result'); var fileInput = document.getElementById('dmp-file'); if (!text) { res.textContent = '❌ Введи текст'; res.style.color = '#FF3355'; return; } res.textContent = _currentEditingId ? 'ОБНОВЛЕНИЕ...' : 'СОХРАНЕНИЕ...'; res.style.color = '#C8A84B'; // 1. Теги и триггеры (массивы) var tagsRaw = document.getElementById('dmp-tags').value.trim() || 'протокол'; var tags = tagsRaw.split(',').map(t => t.trim()).filter(t => t !== ""); var triggerRaw = (document.getElementById('dmp-trigger')||{}).value || ''; var trigger = triggerRaw.split(',').map(t => t.trim()).filter(t => t !== ""); // 2. Числовые параметры var sci = parseInt(document.getElementById('dmp-sci').value)||800; var importance = parseInt((document.getElementById('dmp-importance')||{}).value||7); var urgency = parseInt((document.getElementById('dmp-urgency')||{}).value||5); var action = (document.getElementById('dmp-action')||{}).value||''; // 3. Чтение файла (Base64) var fileBase64 = null; if (fileInput && fileInput.files && fileInput.files.length > 0) { try { res.textContent = 'Обработка схемы...'; fileBase64 = await readFileAsBase64(fileInput.files[0]); } catch(e) { console.error("Ошибка чтения файла:", e); } } // 4. Формируем объект запроса var payload = { id: _currentEditingId, // Если null — создаст новый, если ID — обновит старый text: text, name: name, collection: collection, contour: contour, type: 'protocol', sci_score: sci, importance: importance, urgency: urgency, tags: tags, trigger_keywords: trigger, action: action, image_data: fileBase64 }; // 5. Отправка (dmApi) var d = await dmApi('POST', '/memory/save', payload); if (d.saved) { res.textContent = _currentEditingId ? '✅ ОБНОВЛЕНО' : '✅ СОХРАНЕНО'; res.style.color = '#00E87A'; _currentEditingId = null; // Сбрасываем ID document.getElementById('dmp-text').value = ''; if(fileInput) fileInput.value = ''; dmLoadProtocolsList(); } else { res.textContent = '❌ ОШИБКА'; res.style.color = '#FF3355'; } } // ══ ВСПОМОГАТЕЛЬНАЯ ФУНКЦИЯ (Base64) ══ function dmLoadProtocolsList() { var listEl = document.getElementById('dmp-list'); if (!listEl) return; var CC = {'ВОЛЯ':'#00E87A','СКАН':'#4A9EFF','АРХИТЕКТОР':'#C8A84B','РОД':'#FF8C42','БОГАТСТВО':'#AA88FF','ИНВЕРСИЯ':'#FF3355','ОБЩЕЕ':'#555'}; dmApi('GET','/memory/list?collection=protocols_shared&limit=50').then(function(d) { var recs = d.records || []; var hdr = document.getElementById('dmp-list-hdr'); if (hdr) hdr.textContent = 'АРХИВ ПРОТОКОЛОВ · ' + recs.length; if (!recs.length) { listEl.innerHTML = '
база пуста
'; return; } listEl.innerHTML = recs.map(function(r){ var c = CC[r.contour] || '#555'; // Превращаем объект r в строку, чтобы передать его в функцию открытия var rJson = JSON.stringify(r).replace(/"/g, '"'); return '
' // Клик по левой части (тексту) открывает редактирование + '
' + (r.name ? '
'+r.name.toUpperCase()+'
' : '') + '
'+r.text+'
' + '
' + ''+r.contour+'' + 'SCI '+ (r.sci_score || 800) +'' + (r.importance ? '★ '+r.importance+'' : '') + (r.urgency ? '⚡ '+r.urgency+'' : '') + '
' + '
' // Кнопка удаления (Крестик) + '
×
' + '
'; }).join(''); }).catch(e => { listEl.innerHTML = '
Ошибка загрузки
'; }); } // ══ ФУНКЦИЯ ЗАПОЛНЕНИЯ ФОРМЫ (ОТКРЫТИЕ) ══ function dmOpenForEdit(r) { _currentEditingId = r.id; // Запоминаем ID для функции сохранения // Заполняем все инпуты данными из объекта r document.getElementById('dmp-name').value = r.name || ''; document.getElementById('dmp-text').value = r.text || ''; document.getElementById('dmp-contour').value = r.contour || 'ВОЛЯ'; document.getElementById('dmp-col').value = r.collection || 'protocols_shared'; document.getElementById('dmp-tags').value = (r.tags || []).join(','); document.getElementById('dmp-sci').value = r.sci_score || 800; document.getElementById('dmp-importance').value = r.importance || 7; document.getElementById('dmp-urgency').value = r.urgency || 5; document.getElementById('dmp-trigger').value = (r.trigger_keywords || []).join(','); document.getElementById('dmp-action').value = r.action || ''; // Меняем текст в строке результата для наглядности var res = document.getElementById('dmp-result'); res.textContent = 'РЕДАКТИРОВАНИЕ: ' + (r.name || 'ID '+r.id.slice(0,5)); res.style.color = '#C8A84B'; // Плавный скролл наверх к форме, чтобы сразу начать править window.scrollTo({top: 0, behavior: 'smooth'}); } // ══ ГЕНЕЗИС ══ dmRender.genesis = function() { var el = document.getElementById('dm-panel-genesis'); if (!el) return; el.innerHTML = '
ГЕНЕЗИС АЛЬТАИРА
' +'
' +'ОБЩИЙ ГЕНЕЗИС (altair_core.json)' +'' +'
' +'' +'
' +'
' +'
' +'
' +'ПЕРСОНАЛЬНЫЙ ГЕНЕЗИС ОПЕРАТОРА' +'' +'' +'
' +'' +'' +'
' +'
' +'
'; dmApi('GET','/admin/users').then(function(d){ var arr = Array.isArray(d) ? d : (d.users||[]); var sel = document.getElementById('genesis-uid'); if (sel) arr.forEach(function(u){ var o=document.createElement('option'); o.value=u.id; o.textContent=u.fio; sel.appendChild(o); }); }); }; async function dmSaveGenesis() { var text = document.getElementById('genesis-core').value.trim(); var res = document.getElementById('genesis-result'); if (!text) return; res.textContent='Сохраняем...'; res.style.color='#444'; try { var r = await fetch('/admin/config/save',{method:'POST',headers:{'Authorization':'Bearer '+dmGetToken(),'Content-Type':'application/json'},body:JSON.stringify({config:{altair_core:text},comment:'genesis update'})}); var d = await r.json(); res.textContent = d.ok||d.saved ? '✅ Сохранено' : '❌ '+JSON.stringify(d); res.style.color = d.ok||d.saved ? '#00E87A' : '#FF3355'; } catch(e){ res.textContent='❌ '+e; res.style.color='#FF3355'; } } async function dmLoadPersonalGenesis() { var uid = document.getElementById('genesis-uid').value; var res = document.getElementById('genesis-p-result'); if (!uid) return; res.textContent='Загружаем...'; res.style.color='#444'; try { var d = await dmApi('GET','/admin/users/'+uid+'/genesis'); document.getElementById('genesis-personal').value = d.genesis || d.system_prompt || ''; res.textContent='✅ Загружено'; res.style.color='#00E87A'; } catch(e){ res.textContent='(нет генезиса)'; res.style.color='#333'; document.getElementById('genesis-personal').value=''; } } async function dmSavePersonalGenesis() { var uid = document.getElementById('genesis-uid').value; var text = document.getElementById('genesis-personal').value.trim(); var res = document.getElementById('genesis-p-result'); if (!uid || !text) { res.textContent='❌ Выбери оператора'; res.style.color='#FF3355'; return; } res.textContent='Сохраняем...'; res.style.color='#444'; try { var d = await dmApi('POST','/admin/users/'+uid+'/genesis',{genesis:text}); res.textContent = d.saved||d.ok ? '✅ Сохранено' : '❌ '+JSON.stringify(d); res.style.color = d.saved||d.ok ? '#00E87A' : '#FF3355'; } catch(e){ res.textContent='❌ '+e; res.style.color='#FF3355'; } } // ══ ФОРМУЛА ══ dmRender.formula = function() { var el = document.getElementById('dm-panel-formula'); if (!el) return; el.innerHTML = '
ФОРМУЛА SCI
загрузка...
'; dmApi('GET','/admin/config/formula').then(function(d) { var f = d.formula || d || {}; var html = '
ФОРМУЛА SCI
'; Object.entries(f).forEach(function(kv){ if (typeof kv[1] === 'number') { html += '
'+kv[0]+'
'; } }); html += '
' +''; el.innerHTML = html; }).catch(function(e){ el.innerHTML='
Ошибка: '+e+'
'; }); }; async function dmSaveFormula() { var res = document.getElementById('formula-result'); var patch = {}; document.querySelectorAll('[id^="formula-"]').forEach(function(inp){ patch[inp.id.replace('formula-','')] = parseFloat(inp.value); }); try { var d = await dmApi('PATCH','/admin/config/formula', patch); res.textContent='✅ Сохранено'; res.style.color='#00E87A'; } catch(e){ res.textContent='❌ '+e; res.style.color='#FF3355'; } } // ══ МАРКЕРЫ ══ dmRender.markers = function() { var el = document.getElementById('dm-panel-markers'); if (!el) return; el.innerHTML = '
МАРКЕРЫ · загрузка...
'; var CONTOURS = ['ВОЛЯ','СКАН','АРХИТЕКТОР','БОГАТСТВО','РОД','ИНВЕРСИЯ','ОБЩЕЕ']; dmApi('GET','/admin/config/markers').then(function(d) { var markers = Array.isArray(d) ? d : (d.markers || []); var cOpts = CONTOURS.map(function(c){ return ''; }).join(''); var html = '
МАРКЕРЫ · '+markers.length+'
' +'
' +'
НОВЫЙ МАРКЕР
' +'
' +'
НАЗВАНИЕ
' +'
КОНТУР
' +'
' +'КЛЮЧЕВЫЕ СЛОВА (через запятую)' +'' +'ПРОТОКОЛ' +'' +'
' +'' +'
' +'
' +'
'; markers.forEach(function(m){ var kws = Array.isArray(m.keywords) ? m.keywords.join(', ') : (m.keywords||''); html += '
' +'
' +'
'+m.name+'
' +'
'+kws+'
' +'
' +'' +'
'; }); el.innerHTML = html; }).catch(function(e){ el.innerHTML='
Ошибка: '+e+'
'; }); }; async function dmCreateMarker() { var name = document.getElementById('mk-name').value.trim(); var contour = document.getElementById('mk-contour').value; var keywords = document.getElementById('mk-keywords').value.split(',').map(function(s){return s.trim();}).filter(Boolean); var protocol = document.getElementById('mk-protocol').value.trim(); var res = document.getElementById('mk-result'); if (!name || !keywords.length) { res.textContent='❌ Заполни'; res.style.color='#FF3355'; return; } res.textContent='Создаём...'; res.style.color='#444'; var d = await dmApi('POST','/admin/config/markers',{name:name,contour:contour,keywords:keywords,protocol:protocol,enabled:true}); if (d.id||d.ok) { res.textContent='✅ Создан'; res.style.color='#00E87A'; dmRender.markers(); } else { res.textContent='❌ '+JSON.stringify(d); res.style.color='#FF3355'; } } async function dmDeleteMarker(id) { if (!confirm('Удалить маркер?')) return; await dmApi('DELETE','/admin/config/markers/'+id); dmRender.markers(); } // ══ СТАТИСТИКА ══ dmRender.stats = function() { var el = document.getElementById('dm-panel-stats'); if (!el) return; el.innerHTML = '
СТАТИСТИКА · загрузка...
'; dmApi('GET','/admin/stats').then(function(d) { var html = '
СТАТИСТИКА СИСТЕМЫ
' +'
' +'
'+(d.users_active||0)+'
ОПЕРАТОРОВ
' +'
'+(d.messages_today||0)+'
СООБЩЕНИЙ СЕГОДНЯ
' +'
'+(d.total_nodes||0)+'
УЗЛОВ
' +'
' +'
АЛГОРИТМ СНА
' +'
' +'' +'' +'' +'' +'
' +'
'; el.innerHTML = html; }).catch(function(e){ el.innerHTML='
Ошибка: '+e+'
'; }); }; async function dmRunSleep(phases) { var res = document.getElementById('sleep-result'); if (res) { res.textContent='⏳ Запускаем...'; res.style.color='#444'; } try { var body = phases ? {phases:phases} : {}; var d = await dmApi('POST','/admin/sleep', body); if (res) { res.textContent='✅ '+JSON.stringify(d.stats); res.style.color='#00E87A'; } } catch(e) { if (res) { res.textContent='❌ '+e; res.style.color='#FF3355'; } } }