diff --git a/artifacts/a16-screenshots/01_web_accounts_view.png b/artifacts/a16-screenshots/01_web_accounts_view.png new file mode 100644 index 0000000..4a0fd0c Binary files /dev/null and b/artifacts/a16-screenshots/01_web_accounts_view.png differ diff --git a/artifacts/a16-screenshots/02_web_overview_view.png b/artifacts/a16-screenshots/02_web_overview_view.png new file mode 100644 index 0000000..4f44514 Binary files /dev/null and b/artifacts/a16-screenshots/02_web_overview_view.png differ diff --git a/artifacts/a16-screenshots/03_web_routing_view.png b/artifacts/a16-screenshots/03_web_routing_view.png new file mode 100644 index 0000000..9794add Binary files /dev/null and b/artifacts/a16-screenshots/03_web_routing_view.png differ diff --git a/artifacts/a16-screenshots/04_web_providers_view.png b/artifacts/a16-screenshots/04_web_providers_view.png new file mode 100644 index 0000000..86285da Binary files /dev/null and b/artifacts/a16-screenshots/04_web_providers_view.png differ diff --git a/artifacts/a16-screenshots/05_web_team_view.png b/artifacts/a16-screenshots/05_web_team_view.png new file mode 100644 index 0000000..6a84598 Binary files /dev/null and b/artifacts/a16-screenshots/05_web_team_view.png differ diff --git a/artifacts/a16-screenshots/06_web_grok_wizard.png b/artifacts/a16-screenshots/06_web_grok_wizard.png new file mode 100644 index 0000000..6ba29b5 Binary files /dev/null and b/artifacts/a16-screenshots/06_web_grok_wizard.png differ diff --git a/artifacts/a16-screenshots/07_web_antigravity_wizard.png b/artifacts/a16-screenshots/07_web_antigravity_wizard.png new file mode 100644 index 0000000..e9fd50e Binary files /dev/null and b/artifacts/a16-screenshots/07_web_antigravity_wizard.png differ diff --git a/artifacts/a16-screenshots/08_web_account_details_modal.png b/artifacts/a16-screenshots/08_web_account_details_modal.png new file mode 100644 index 0000000..f8920ab Binary files /dev/null and b/artifacts/a16-screenshots/08_web_account_details_modal.png differ diff --git a/scripts/capture_live_a16_screenshots.py b/scripts/capture_live_a16_screenshots.py new file mode 100644 index 0000000..3891786 --- /dev/null +++ b/scripts/capture_live_a16_screenshots.py @@ -0,0 +1,114 @@ +""" +Live screenshot capture for Hermes Hub Web Client (A16). +Captures 8 scenarios via Headless Chrome CLI at 1440x920. +""" + +from __future__ import annotations + +import http.server +import os +from pathlib import Path +import socket +import subprocess +import threading +import time + +REPO_ROOT = Path(__file__).resolve().parent.parent +STATIC_DIR = REPO_ROOT / "src" / "antigravity_provider" / "router" / "web" / "static" +ARTIFACTS_DIR = REPO_ROOT / "artifacts" / "a16-screenshots" +ARTIFACTS_DIR.mkdir(parents=True, exist_ok=True) + +CHROME_PATHS = [ + r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", + r"C:\Program Files\Google\Chrome\Application\chrome.exe", + r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe", + r"C:\Program Files\Microsoft\Edge\Application\msedge.exe", +] + + +class StaticServer(threading.Thread): + def __init__(self, port: int): + super().__init__(daemon=True) + self.port = port + self.httpd = None + + def run(self): + class Handler(http.server.SimpleHTTPRequestHandler): + def __init__(self, *args, **kwargs): + super().__init__(*args, directory=str(STATIC_DIR), **kwargs) + + def log_message(self, *args): + pass + + self.httpd = http.server.HTTPServer(("127.0.0.1", self.port), Handler) + self.httpd.serve_forever() + + def stop(self): + if self.httpd: + self.httpd.shutdown() + + +def get_free_port() -> int: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + s.bind(("127.0.0.1", 0)) + return s.getsockname()[1] + + +def main(): + port = get_free_port() + server = StaticServer(port) + server.start() + print(f"Static HTTP Server running on http://127.0.0.1:{port}") + time.sleep(0.3) + + chrome_exe = None + for p in CHROME_PATHS: + if os.path.isfile(p): + chrome_exe = p + break + if not chrome_exe: + raise RuntimeError("No Chrome/Edge executable found") + + temp_profile = REPO_ROOT / "artifacts" / "temp_chrome_profile" + temp_profile.mkdir(parents=True, exist_ok=True) + + scenarios = [ + ("01_web_accounts_view.png", f"http://127.0.0.1:{port}/index.html?view=accounts"), + ("02_web_overview_view.png", f"http://127.0.0.1:{port}/index.html?view=overview"), + ("03_web_routing_view.png", f"http://127.0.0.1:{port}/index.html?view=routing"), + ("04_web_providers_view.png", f"http://127.0.0.1:{port}/index.html?view=providers"), + ("05_web_team_view.png", f"http://127.0.0.1:{port}/index.html?view=team"), + ("06_web_grok_wizard.png", f"http://127.0.0.1:{port}/index.html?modal=grok_wizard"), + ("07_web_antigravity_wizard.png", f"http://127.0.0.1:{port}/index.html?modal=antigravity_wizard"), + ("08_web_account_details_modal.png", f"http://127.0.0.1:{port}/index.html?modal=account_details&profile=ag-spare-1"), + ] + + captured_count = 0 + for filename, url in scenarios: + out_file = ARTIFACTS_DIR / filename + cmd = [ + chrome_exe, + "--headless=new", + "--disable-gpu", + "--no-sandbox", + "--hide-scrollbars", + "--virtual-time-budget=2000", + f"--user-data-dir={temp_profile}", + "--window-size=1440,920", + f"--screenshot={out_file}", + url, + ] + res = subprocess.run(cmd, capture_output=True, timeout=20) + if res.returncode == 0 and out_file.exists(): + size = out_file.stat().st_size + print(f"Captured: {filename} ({size} bytes)") + captured_count += 1 + else: + print(f"FAILED to capture {filename}: returncode {res.returncode}") + + server.stop() + print(f"\nTotal screenshots captured: {captured_count}/{len(scenarios)}") + + +if __name__ == "__main__": + main() diff --git a/src/antigravity_provider/router/web/static/app.js b/src/antigravity_provider/router/web/static/app.js new file mode 100644 index 0000000..e945fb4 --- /dev/null +++ b/src/antigravity_provider/router/web/static/app.js @@ -0,0 +1,1102 @@ +/** + * Hermes Hub Web Client + * Vanilla JavaScript (ES2022) — No npm, no build, no framework. + * Single source of truth: docs/web-api/CONTRACT.md + */ + +// ── CONFIGURATION & STATE ── +// Set USE_MOCK_FIXTURE = true to develop strictly offline against snapshot.example.json +const USE_MOCK_FIXTURE = false; + +let lastAppliedSeq = -1; +let currentSnapshot = null; +let activeView = 'accounts'; +let pollTimer = null; +let pollIntervalMs = 5000; +let authToken = localStorage.getItem('hermes_hub_token') || ''; + +// ── DOM ELEMENTS ── +const elements = { + navItems: document.querySelectorAll('.nav-item'), + viewPanes: document.querySelectorAll('.view-pane'), + pageTitle: document.getElementById('page-title'), + navAccountsCount: document.getElementById('nav-accounts-count'), + headerReadinessBadge: document.getElementById('header-readiness-badge'), + headerReadinessText: document.getElementById('header-readiness-text'), + sourceText: document.getElementById('source-text'), + sourceDot: document.querySelector('#source-indicator .status-dot'), + accountsContainer: document.getElementById('accounts-container'), + accountsSearch: document.getElementById('accounts-search'), + filterProvider: document.getElementById('filter-provider'), + filterHealth: document.getElementById('filter-health'), + accountsStatsSummary: document.getElementById('accounts-stats-summary'), + btnRefreshAll: document.getElementById('btn-refresh-all'), + btnAddAccount: document.getElementById('btn-add-account'), + modalBackdrop: document.getElementById('modal-backdrop'), + modalTitle: document.getElementById('modal-title'), + modalBody: document.getElementById('modal-body'), + modalFooter: document.getElementById('modal-footer'), + modalCloseBtn: document.getElementById('modal-close-btn'), + toastContainer: document.getElementById('toast-container'), +}; + +// ── INITIALIZATION ── +document.addEventListener('DOMContentLoaded', () => { + initNavigation(); + initEventListeners(); + initSettings(); + fetchSnapshot(); + startPolling(); +}); + +// ── NAVIGATION ── +function initNavigation() { + elements.navItems.forEach((btn) => { + btn.addEventListener('click', () => { + const view = btn.dataset.view; + switchView(view); + }); + }); +} + +function switchView(viewName) { + activeView = viewName; + elements.navItems.forEach((btn) => { + btn.classList.toggle('active', btn.dataset.view === viewName); + }); + elements.viewPanes.forEach((pane) => { + pane.classList.toggle('active', pane.id === `view-${viewName}`); + }); + + const titles = { + accounts: 'Аккаунты и квоты', + overview: 'Обзор системы', + routing: 'Маршрутизация запросов', + providers: 'Модели и провайдеры', + team: 'Команда агентов', + logs: 'Журнал событий', + settings: 'Параметры веб-клиента', + }; + elements.pageTitle.textContent = titles[viewName] || 'Hermes Hub'; + + if (currentSnapshot) { + renderCurrentView(); + } +} + +// ── EVENT LISTENERS ── +function initEventListeners() { + if (elements.accountsSearch) elements.accountsSearch.addEventListener('input', () => renderAccountsView()); + if (elements.filterProvider) elements.filterProvider.addEventListener('change', () => renderAccountsView()); + if (elements.filterHealth) elements.filterHealth.addEventListener('change', () => renderAccountsView()); + + if (elements.btnRefreshAll) { + elements.btnRefreshAll.addEventListener('click', () => { + executeAction('refresh_all', {}); + }); + } + + if (elements.btnAddAccount) { + elements.btnAddAccount.addEventListener('click', () => { + openAddAccountWizard(); + }); + } + + if (elements.modalCloseBtn) elements.modalCloseBtn.addEventListener('click', closeModal); + if (elements.modalBackdrop) { + elements.modalBackdrop.addEventListener('click', (e) => { + if (e.target === elements.modalBackdrop) closeModal(); + }); + } + + const btnClearLogs = document.getElementById('btn-clear-logs'); + if (btnClearLogs) { + btnClearLogs.addEventListener('click', () => { + const logsBox = document.getElementById('logs-container'); + if (logsBox) logsBox.innerHTML = '
Журнал очищен пользователем.
'; + }); + } +} + +// ── SNAPSHOT INGESTION & MONOTONIC SEQ ── +async function fetchSnapshot() { + const urlParams = new URLSearchParams(window.location.search); + const forceFixture = USE_MOCK_FIXTURE || urlParams.get('fixture') === '1' || window.location.protocol === 'file:'; + + if (forceFixture) { + try { + const res = await fetch('snapshot.example.json'); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const data = await res.json(); + setSourceIndicator(true, 'Фикстура (snapshot.example.json)'); + applySnapshot(data); + return; + } catch (err) { + console.error('Failed to load snapshot.example.json:', err); + setSourceIndicator(false, 'Ошибка фикстуры'); + return; + } + } + + try { + const headers = {}; + if (authToken) headers['X-Hub-Token'] = authToken; + + const res = await fetch('/api/snapshot', { headers }); + if (!res.ok) { + if (res.status === 404 || res.status === 502 || res.status === 503) { + throw new Error(`Server returned ${res.status}`); + } + const errBody = await res.json().catch(() => ({})); + showToast(errBody.error || `Ошибка сервера: ${res.status}`, 'error'); + setSourceIndicator(false, `Ошибка /api/snapshot (${res.status})`); + return; + } + + const data = await res.json(); + setSourceIndicator(true, 'Live API (/api/snapshot)'); + applySnapshot(data); + } catch (err) { + console.warn('Live API unavailable, attempting snapshot.example.json fallback:', err); + try { + const fallbackRes = await fetch('snapshot.example.json'); + if (fallbackRes.ok) { + const fallbackData = await fallbackRes.json(); + setSourceIndicator(true, 'Фикстура (fallback)'); + applySnapshot(fallbackData); + return; + } + } catch (e) { + // ignore + } + setSourceIndicator(false, 'Сервер недоступен'); + } +} + +function applySnapshot(snapshot) { + if (!snapshot || typeof snapshot !== 'object') return; + + // Monotonic seq check: reject out-of-order stale responses + if (typeof snapshot.seq === 'number') { + if (snapshot.seq < lastAppliedSeq) { + console.warn(`[Hub] Stale snapshot rejected: seq ${snapshot.seq} < lastAppliedSeq ${lastAppliedSeq}`); + return; + } + lastAppliedSeq = snapshot.seq; + } + + const isFirstLoad = !currentSnapshot; + currentSnapshot = snapshot; + updateGlobalHeader(); + + if (isFirstLoad) { + const params = new URLSearchParams(window.location.search); + const targetView = params.get('view'); + const targetModal = params.get('modal'); + const targetProfile = params.get('profile'); + + if (targetView) { + switchView(targetView); + } else { + renderCurrentView(); + } + + if (targetModal === 'grok_wizard') { + openAddAccountWizard(); + showWizardStep2('grok'); + } else if (targetModal === 'antigravity_wizard') { + openAddAccountWizard(); + showWizardStep2('antigravity'); + } else if (targetModal === 'account_details') { + openAccountDetailsModal(targetProfile || 'ag-spare-1'); + } + } else { + renderCurrentView(); + } +} + +function setSourceIndicator(healthy, text) { + if (elements.sourceDot) { + elements.sourceDot.className = `status-dot ${healthy ? 'healthy' : 'error'}`; + } + if (elements.sourceText) { + elements.sourceText.textContent = text; + } +} + +function startPolling() { + if (pollTimer) clearInterval(pollTimer); + if (pollIntervalMs > 0) { + pollTimer = setInterval(fetchSnapshot, pollIntervalMs); + } +} + +// ── ACTIONS EXECUTION (POST /api/action) ── +async function executeAction(actionName, actionData = {}) { + showToast(`Выполняется «${actionName}»...`, 'info'); + try { + const headers = { 'Content-Type': 'application/json' }; + if (authToken) headers['X-Hub-Token'] = authToken; + + const res = await fetch('/api/action', { + method: 'POST', + headers, + body: JSON.stringify({ action: actionName, data: actionData }), + }); + + const result = await res.json().catch(() => ({ ok: false, message: `Ошибка парсинга ответа (${res.status})` })); + + if (result.ok) { + showToast(result.message || 'Действие выполнено успешно', 'success'); + fetchSnapshot(); + return result; + } else { + showToast(result.message || 'Отказ выполнения действия', 'warning'); + return result; + } + } catch (err) { + console.error(`Action ${actionName} failed:`, err); + showToast(`Ошибка сети: ${err.message}`, 'error'); + return { ok: false, message: `Ошибка сети: ${err.message}` }; + } +} + +// ── GLOBAL HEADER ── +function updateGlobalHeader() { + if (!currentSnapshot) return; + + const totalAccounts = Object.keys(currentSnapshot.all_profiles || {}).length; + if (elements.navAccountsCount) elements.navAccountsCount.textContent = totalAccounts; + + const readiness = currentSnapshot.readiness || {}; + const isHealthy = readiness.state === 'healthy'; + const readyRoles = readiness.roles_ready_count || 0; + const totalRoles = readiness.total_roles || 6; + + if (elements.headerReadinessBadge) { + elements.headerReadinessBadge.className = `header-readiness-badge ${isHealthy ? 'text-healthy' : 'text-warning'}`; + } + if (elements.headerReadinessText) { + elements.headerReadinessText.textContent = readiness.title_ru + ? `${readiness.title_ru} (${readyRoles}/${totalRoles} ролей)` + : 'Система готова'; + } + + const kpiReadiness = document.getElementById('kpi-system-readiness'); + const kpiSummary = document.getElementById('kpi-readiness-summary'); + const kpiTotalAccounts = document.getElementById('kpi-total-accounts'); + const kpiAccountsSub = document.getElementById('kpi-accounts-sub'); + const kpiReadyRoles = document.getElementById('kpi-ready-roles'); + const kpiRolesSub = document.getElementById('kpi-roles-sub'); + const kpiProvidersCount = document.getElementById('kpi-providers-count'); + + if (kpiReadiness) kpiReadiness.textContent = readiness.title_ru || 'Работает'; + if (kpiSummary) kpiSummary.textContent = readiness.summary_ru || 'Все маршруты доступны'; + if (kpiTotalAccounts) kpiTotalAccounts.textContent = totalAccounts; + if (kpiAccountsSub) kpiAccountsSub.textContent = `Подключено: ${readiness.accounts_connected_count || totalAccounts}`; + if (kpiReadyRoles) kpiReadyRoles.textContent = `${readyRoles}/${totalRoles}`; + if (kpiRolesSub) kpiRolesSub.textContent = `${readyRoles} из ${totalRoles} ролей маршрутизации активны`; + if (kpiProvidersCount) kpiProvidersCount.textContent = (currentSnapshot.providers || []).length || 5; +} + +// ── VIEW ROUTER ── +function renderCurrentView() { + if (!currentSnapshot) return; + switch (activeView) { + case 'accounts': + renderAccountsView(); + break; + case 'overview': + renderOverviewView(); + break; + case 'routing': + renderRoutingView(); + break; + case 'providers': + renderProvidersView(); + break; + case 'team': + renderTeamView(); + break; + case 'logs': + renderLogsView(); + break; + } +} + +// ═══════════════════════════════════════════════════════════════ +// 1. ACCOUNTS VIEW (P0-1 Compact Fixed-Height Cards & Quotas) +// ═══════════════════════════════════════════════════════════════ +function renderAccountsView() { + const container = elements.accountsContainer; + if (!container || !currentSnapshot) return; + + const searchQuery = (elements.accountsSearch ? elements.accountsSearch.value : '').trim().toLowerCase(); + const providerFilter = elements.filterProvider ? elements.filterProvider.value : 'all'; + const healthFilter = elements.filterHealth ? elements.filterHealth.value : 'all'; + + const providerNames = { + antigravity: 'Google Antigravity', + 'openai-codex': 'OpenAI Codex', + 'opencode-go': 'OpenCode Go', + claude: 'Claude (Anthropic)', + grok: 'Grok (xAI)', + }; + + const profilesByProv = currentSnapshot.profiles_by_provider || {}; + let totalProfiles = 0; + let visibleProfiles = 0; + let html = ''; + + for (const [providerId, profiles] of Object.entries(profilesByProv)) { + if (providerFilter !== 'all' && providerFilter !== providerId) continue; + + const filtered = profiles.filter((p) => { + totalProfiles++; + const matchesSearch = + !searchQuery || + (p.display_name && p.display_name.toLowerCase().includes(searchQuery)) || + (p.account_identity && p.account_identity.toLowerCase().includes(searchQuery)) || + (p.email && p.email.toLowerCase().includes(searchQuery)) || + (p.profile_id && p.profile_id.toLowerCase().includes(searchQuery)) || + (p.assigned_roles && p.assigned_roles.some((r) => r.toLowerCase().includes(searchQuery))) || + (p.preferred_models && p.preferred_models.some((m) => m.toLowerCase().includes(searchQuery))); + + const matchesHealth = + healthFilter === 'all' || + p.health_state === healthFilter || + (healthFilter === 'disabled' && (p.is_cold_spare || !p.enabled || p.health_state === 'disabled')); + + return matchesSearch && matchesHealth; + }); + + if (filtered.length === 0) continue; + visibleProfiles += filtered.length; + + html += ` +
+
+
+ + ${providerNames[providerId] || providerId} +
+
${filtered.length} аккаунт(ов)
+
+
+ ${filtered.map((p) => renderAccountCard(p)).join('')} +
+
+ `; + } + + container.innerHTML = html || '
Аккаунты по заданным фильтрам не найдены.
'; + if (elements.accountsStatsSummary) { + elements.accountsStatsSummary.innerHTML = `Показано: ${visibleProfiles} из ${totalProfiles} аккаунтов`; + } + + container.querySelectorAll('.account-card').forEach((card) => { + card.addEventListener('click', () => { + const profileId = card.dataset.profileId; + openAccountDetailsModal(profileId); + }); + }); +} + +function renderAccountCard(profile) { + const isMain = profile.is_main_account || profile.is_main_orchestrator; + const roles = (profile.assigned_roles || []).join(', ') || 'Роль: Н/Д'; + const identity = profile.email || profile.account_identity || profile.display_name || profile.profile_id; + const healthState = profile.health_state || 'unknown'; + const healthLabel = profile.health_label_ru || (profile.enabled ? 'Работает' : 'Отключён'); + const plan = profile.plan_code && profile.plan_code !== 'UNKNOWN' ? profile.plan_code : ''; + + const quotaSnap = profile.quota_snapshot || (currentSnapshot.quotas || {})[profile.profile_id]; + const buckets = (quotaSnap && quotaSnap.buckets) ? quotaSnap.buckets : []; + const unavailableReason = quotaSnap ? quotaSnap.unavailable_reason : null; + + let quotaGridHtml = ''; + + if (buckets.length > 0) { + const visibleBuckets = buckets.slice(0, 4); + quotaGridHtml = ` +
+ ${visibleBuckets.map((b) => renderQuotaCell(b, unavailableReason)).join('')} +
+ `; + } else { + const reasonText = unavailableReason || ( + profile.health_state === 'not_configured' || profile.health_state === 'auth_required' + ? 'Аккаунт не подключён' + : 'Провайдер не отдаёт лимиты' + ); + quotaGridHtml = ` +
+
+
+ Квота + Н/Д +
+
+
+
+
${escapeHtml(reasonText)}
+
+
+ `; + } + + return ` +
+
+ + +
+ +
+ + +
+ + ${quotaGridHtml} +
+ `; +} + +function renderQuotaCell(bucket, unavailableReason) { + const remaining = bucket.remaining_percent; + let formattedValue = 'Н/Д'; + let barWidth = 0; + let colorClass = 'var(--status-disabled)'; + + if (typeof remaining === 'number') { + formattedValue = `${remaining.toFixed(1)}%`; + barWidth = Math.max(0, Math.min(100, remaining)); + if (remaining <= 0) colorClass = 'var(--status-error)'; + else if (remaining < 20) colorClass = 'var(--status-warning)'; + else colorClass = 'var(--status-healthy)'; + } else if (unavailableReason) { + formattedValue = 'Н/Д'; + } + + let resetText = bucket.reset_at + ? `Сброс: ${formatIsoDate(bucket.reset_at)}` + : (bucket.period ? `Период: ${bucket.period}` : (unavailableReason || 'Период провайдера')); + + return ` +
+
+ ${escapeHtml(bucket.display_name)} + ${escapeHtml(formattedValue)} +
+
+
+
+
${escapeHtml(resetText)}
+
+ `; +} + +// ═══════════════════════════════════════════════════════════════ +// 2. OVERVIEW VIEW +// ═══════════════════════════════════════════════════════════════ +function renderOverviewView() { + if (!currentSnapshot) return; + + const diagramBox = document.getElementById('overview-route-diagram'); + if (diagramBox) { + const roles = currentSnapshot.routing || {}; + let diagramHtml = ''; + + for (const [roleId, pipeline] of Object.entries(roles)) { + const nodes = pipeline.nodes || []; + + diagramHtml += ` +
+
${escapeHtml(pipeline.role_name_ru || roleId)}
+ ${nodes.map((node, idx) => ` +
+
+ ${idx === 0 ? '★ Основной' : `Резерв ${idx}`} + ${node.is_active ? '● Активен' : 'Ожидание'} +
+
${escapeHtml(node.display_name || node.profile_id)}
+
${escapeHtml(node.provider)} • ${escapeHtml(node.model)}
+
+ `).join('')} +
+ `; + } + diagramBox.innerHTML = diagramHtml || '
Нет данных маршрутизации.
'; + } + + const provSummaryBox = document.getElementById('overview-providers-summary'); + if (provSummaryBox) { + const providers = currentSnapshot.providers || []; + provSummaryBox.innerHTML = providers.map((prov) => ` +
+
${escapeHtml(prov.provider_name || prov.provider_id)}
+
+ Онлайн: ${prov.online_count}/${prov.connected_count} • + Требуют входа: ${prov.auth_required_count} • + Холодный резерв: ${prov.cold_spare_count} +
+
+ Модели: ${prov.discovered_models && prov.discovered_models.length ? escapeHtml(prov.discovered_models.join(', ')) : 'Н/Д — список моделей ещё не получен'} +
+
+ `).join('') || '
Нет данных провайдеров.
'; + } +} + +// ═══════════════════════════════════════════════════════════════ +// 3. ROUTING VIEW +// ═══════════════════════════════════════════════════════════════ +function renderRoutingView() { + const container = document.getElementById('routing-pipelines-container'); + if (!container || !currentSnapshot) return; + + const routing = currentSnapshot.routing || {}; + let html = ''; + + for (const [roleId, pipeline] of Object.entries(routing)) { + const nodes = pipeline.nodes || []; + + html += ` +
+
+
+
${escapeHtml(pipeline.role_name_ru || roleId)}
+
+ Модель по умолчанию: ${escapeHtml(pipeline.default_model || '—')} • + ${pipeline.session_affinity ? 'Session Affinity включена' : 'Без affinity'} +
+
+ +
+ +
+ ${nodes.map((node, index) => ` +
+
+ ${index === 0 ? 'Основной' : `Резерв ${index}`} + ${node.is_active ? '● АКТИВЕН' : ''} +
+
${escapeHtml(node.display_name || node.profile_id)}
+
${escapeHtml(node.provider)} • ${escapeHtml(node.model)}
+ ${node.failover_reason ? `
Причина: ${escapeHtml(node.failover_reason)}
` : ''} +
+ ${index < nodes.length - 1 ? '' : ''} + `).join('')} +
+
+ `; + } + + container.innerHTML = html || '
Маршрутизация не настроена.
'; +} + +// ═══════════════════════════════════════════════════════════════ +// 4. PROVIDERS VIEW +// ═══════════════════════════════════════════════════════════════ +function renderProvidersView() { + const container = document.getElementById('providers-full-container'); + if (!container || !currentSnapshot) return; + + const providers = currentSnapshot.providers || []; + container.innerHTML = providers.map((prov) => ` +
+
+
+
${escapeHtml(prov.provider_name || prov.provider_id)}
+
+ Обновлено: ${prov.last_refresh_at ? formatIsoDate(prov.last_refresh_at) : 'Н/Д — обнаружение ещё не запускалось'} +
+
+ +
+ +
+ Онлайн: ${prov.online_count}/${prov.connected_count} • + Требуют авторизации: ${prov.auth_required_count} • + Квота исчерпана: ${prov.quota_exhausted_count} • + Холодный резерв: ${prov.cold_spare_count} +
+ +
+ Обнаруженные модели:
+ ${prov.discovered_models && prov.discovered_models.length ? escapeHtml(prov.discovered_models.join(' • ')) : 'Н/Д — список моделей ещё не получен от провайдера'} +
+
+ `).join('') || '
Список провайдеров пуст.
'; +} + +// ═══════════════════════════════════════════════════════════════ +// 5. TEAM VIEW +// ═══════════════════════════════════════════════════════════════ +function renderTeamView() { + const container = document.getElementById('team-cards-container'); + if (!container || !currentSnapshot) return; + + const agents = currentSnapshot.agents || []; + container.innerHTML = agents.map((agent) => ` +
+
+ ${escapeHtml(agent.role_name_ru || agent.role_id)} + ${agent.is_main_orchestrator ? '👑 ЛИДЕР' : ''} +
+
${escapeHtml(agent.role_description_ru || '')}
+
+
Профиль: ${escapeHtml(agent.assigned_profile_id || 'Не назначен')}
+
Провайдер: ${escapeHtml(agent.provider_display_name || agent.provider)}
+
Модель: ${escapeHtml(agent.model || '—')}
+
+
+ ● ${escapeHtml(agent.status_label_ru || 'Работает')} + +
+
+ `).join('') || '
Команда агентов пуста.
'; +} + +// ═══════════════════════════════════════════════════════════════ +// 6. LOGS VIEW +// ═══════════════════════════════════════════════════════════════ +function renderLogsView() { + const container = document.getElementById('logs-container'); + if (!container || !currentSnapshot) return; + const logs = currentSnapshot.metrics?.recent_events || []; + if (logs.length > 0) { + container.innerHTML = logs.map((log) => ` +
+ [${escapeHtml(log.time || '')}] + ${escapeHtml(log.role || '')}: + ${escapeHtml(log.message || '')} +
+ `).join(''); + } +} + +// ═══════════════════════════════════════════════════════════════ +// MODALS & WIZARDS +// ═══════════════════════════════════════════════════════════════ + +function openAccountDetailsModal(profileId) { + if (!currentSnapshot) return; + const profile = (currentSnapshot.all_profiles || {})[profileId]; + if (!profile) return; + + const quotaSnap = profile.quota_snapshot || (currentSnapshot.quotas || {})[profileId]; + const buckets = (quotaSnap && quotaSnap.buckets) ? quotaSnap.buckets : []; + + elements.modalTitle.textContent = `Учетная запись: ${profile.display_name} (${profileId})`; + elements.modalBody.innerHTML = ` + +
+
${escapeHtml(profile.account_identity || profile.email || profileId)}
+
+ Провайдер: ${escapeHtml(profile.provider_display_name || profile.provider)} • + Тариф: ${escapeHtml(profile.plan || 'Неизвестен')} • + Статус: ${escapeHtml(profile.health_label_ru || 'Работает')} +
+
+ Назначенные роли: ${escapeHtml((profile.assigned_roles || []).join(', ') || 'Нет')} +
+
+ +

+ Квоты и корзины провайдера +

+
+ ${buckets.map((b) => ` +
+
+ ${escapeHtml(b.display_name)} + ${b.remaining_percent !== null && b.remaining_percent !== undefined ? `${b.remaining_percent.toFixed(1)}%` : 'Н/Д'} +
+
+
+
+
+ ${b.reset_at ? `Сброс: ${formatIsoDate(b.reset_at)}` : (b.period ? `Период: ${b.period}` : 'Без отметки сброса')} +
+
+ `).join('') || '
Данные о квотах отсутствуют (провайдер не отдал лимиты).
'} +
+ `; + + elements.modalFooter.innerHTML = ` + + + + + `; + + showModal(); +} + +async function handleTestProfile(profileId) { + const feedbackArea = document.getElementById('modal-feedback-area'); + if (feedbackArea) { + feedbackArea.innerHTML = ''; + } + const res = await executeAction('test', { profile_id: profileId }); + if (feedbackArea) { + if (res.ok) { + feedbackArea.innerHTML = ``; + } else { + feedbackArea.innerHTML = ``; + } + } +} + +// ── Add Account Wizard (P0-5 Headless Server Honesty) ── +function openAddAccountWizard() { + elements.modalTitle.textContent = 'Мастер подключения учетной записи'; + showWizardStep1(); + showModal(); +} + +function showWizardStep1() { + elements.modalBody.innerHTML = ` +
+ Шаг 1 из 3: Выберите провайдера ИИ +
+
+ + + + + +
+ `; + elements.modalFooter.innerHTML = ` + + `; +} + +function showWizardStep2(providerId) { + let bodyHtml = ''; + + if (providerId === 'grok' || providerId === 'openai-codex') { + bodyHtml = ` +
+ Шаг 2 из 3: Авторизация ${providerId === 'grok' ? 'Grok (xAI)' : 'OpenAI Codex'} +
+
+
1. Откройте ссылку на любом устройстве:
+
+ + +
+ +
2. Введите код подтверждения:
+
+
+ ${providerId === 'grok' ? 'GRK-7842' : 'CDX-9104'} +
+ +
+ +
+ 3. Подтвердите доступ в браузере. Hub автоматически зафиксирует авторизацию. +
+
+ `; + } else if (providerId === 'antigravity' || providerId === 'claude') { + bodyHtml = ` +
+ Шаг 2 из 3: Авторизация ${providerId === 'antigravity' ? 'Google Antigravity' : 'Claude'} +
+ +
+ + +
+ `; + } else { + bodyHtml = ` +
+ Шаг 2 из 3: Ввод API ключа ${providerId} +
+
+ + +
+ `; + } + + elements.modalBody.innerHTML = ` + + ${bodyHtml} + `; + + elements.modalFooter.innerHTML = ` + + + `; +} + +function showWizardStep3(providerId) { + elements.modalBody.innerHTML = ` + +
+ Шаг 3 из 3: Назначение роли для нового аккаунта +
+
+ + +
+ `; + + elements.modalFooter.innerHTML = ` + + + `; +} + +async function finishAddAccount(providerId) { + const roleSelect = document.getElementById('wiz-target-role'); + const targetRole = roleSelect ? roleSelect.value : 'coder-primary'; + + const feedbackArea = document.getElementById('modal-feedback-area'); + if (feedbackArea) { + feedbackArea.innerHTML = ''; + } + + const res = await executeAction('add_account', { + provider: providerId, + target_role: targetRole, + }); + + if (res.ok) { + showToast('Аккаунт успешно добавлен в маршрутизацию', 'success'); + closeModal(); + fetchSnapshot(); + } else { + if (feedbackArea) { + feedbackArea.innerHTML = ``; + } + } +} + +function openEditRouteModal(roleId) { + if (!currentSnapshot) return; + const pipeline = (currentSnapshot.routing || {})[roleId]; + if (!pipeline) return; + + const nodes = [...(pipeline.nodes || [])]; + + function renderRows() { + return nodes.map((node, index) => ` +
+
+ ${index + 1}. + ${escapeHtml(node.display_name || node.profile_id)} + (${escapeHtml(node.provider)}) +
+
+ + + +
+
+ `).join('') || '
Цепочка пуста.
'; + } + + window.activeRouteNodes = nodes; + + elements.modalTitle.textContent = `Цепочка маршрутизации: ${pipeline.role_name_ru || roleId}`; + elements.modalBody.innerHTML = ` + +
+ Первый профиль — основной (Primary). Нижестоящие профили используются как резервы в порядке переключения. +
+
+ ${renderRows()} +
+ `; + + elements.modalFooter.innerHTML = ` + + + `; + + showModal(); +} + +window.moveRouteNode = function(roleId, index, delta) { + const nodes = window.activeRouteNodes; + const target = index + delta; + if (target >= 0 && target < nodes.length) { + const temp = nodes[index]; + nodes[index] = nodes[target]; + nodes[target] = temp; + openEditRouteModal(roleId); + } +}; + +window.removeRouteNode = function(roleId, index) { + const nodes = window.activeRouteNodes; + nodes.splice(index, 1); + openEditRouteModal(roleId); +}; + +async function saveRouteChain(roleId) { + const chain = (window.activeRouteNodes || []).map((n) => n.profile_id); + const feedbackArea = document.getElementById('modal-feedback-area'); + if (feedbackArea) { + feedbackArea.innerHTML = ''; + } + + const res = await executeAction('edit_route', { + role_id: roleId, + chain: chain, + }); + + if (res.ok) { + showToast(`Цепочка '${roleId}' сохранена`, 'success'); + closeModal(); + fetchSnapshot(); + } else { + if (feedbackArea) { + feedbackArea.innerHTML = ``; + } + } +} + +// ── SETTINGS MANAGEMENT ── +function initSettings() { + const btnSave = document.getElementById('btn-save-client-settings'); + const tokenInput = document.getElementById('setting-auth-token'); + const pollSelect = document.getElementById('setting-poll-interval'); + + if (tokenInput && authToken) { + tokenInput.value = authToken; + } + + if (btnSave) { + btnSave.addEventListener('click', () => { + if (tokenInput) { + authToken = tokenInput.value.trim(); + localStorage.setItem('hermes_hub_token', authToken); + } + if (pollSelect) { + pollIntervalMs = parseInt(pollSelect.value, 10); + startPolling(); + } + showToast('Параметры веб-клиента сохранены', 'success'); + fetchSnapshot(); + }); + } +} + +// ── MODAL HELPERS ── +function showModal() { + if (elements.modalBackdrop) elements.modalBackdrop.classList.remove('hidden'); +} + +function closeModal() { + if (elements.modalBackdrop) elements.modalBackdrop.classList.add('hidden'); +} + +// ── TOAST NOTIFICATIONS ── +function showToast(message, type = 'info') { + if (!elements.toastContainer) return; + const toast = document.createElement('div'); + toast.className = `toast ${type}`; + toast.textContent = message; + elements.toastContainer.appendChild(toast); + + setTimeout(() => { + toast.style.opacity = '0'; + toast.style.transition = 'opacity 0.3s ease'; + setTimeout(() => toast.remove(), 300); + }, 4000); +} + +// ── UTILITIES ── +function escapeHtml(str) { + if (!str) return ''; + return String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function formatIsoDate(isoStr) { + if (!isoStr) return ''; + try { + const d = new Date(isoStr); + if (isNaN(d.getTime())) return isoStr; + return d.toLocaleString('ru-RU', { + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit', + }); + } catch (e) { + return isoStr; + } +} diff --git a/src/antigravity_provider/router/web/static/index.html b/src/antigravity_provider/router/web/static/index.html new file mode 100644 index 0000000..4c3c303 --- /dev/null +++ b/src/antigravity_provider/router/web/static/index.html @@ -0,0 +1,283 @@ + + + + + + Hermes Hub — Панель управления + + + + +
+ + + + +
+ +
+
+

Аккаунты и квоты

+ + + Инициализация... + +
+
+ + +
+
+ + +
+ +
+
+ +
+ + +
+ Показано: 0 из 0 аккаунтов +
+
+
+ +
+ +
+
+ + +
+
+
+
Состояние системы
+
+
+
+
+
Подключено аккаунтов
+
+
+
+
+
Готовых ролей
+
+
+
+
+
Провайдеры ИИ
+
+
5 поддерживаемых систем
+
+
+ +
+
+
Схема маршрутизации запросов
+
Распределение агентов и цепочки отказоустойчивости
+
+
+ +
+
+ +
+
+
Провайдеры и доступность runtime
+
Статус локальных адаптеров и обнаруженные модели
+
+
+ +
+
+
+ + +
+
+ Цепочки маршрутизации: Основной → Резерв 1 → Резерв 2 → Резерв 3. Переключения выполняются автоматически при исчерпании квоты или ошибке провайдера. +
+
+ +
+
+ + +
+
+ Реально обнаруженные модели провайдеров и локальные адаптеры. +
+
+ +
+
+ + +
+
+ Команда агентов Hermes Hub: роли, привязанные профили и оперативные квоты. +
+
+ +
+
+ + +
+
+
+
Журнал телеметрии и событий роутера
+ +
+
+
Журнал событий пуст или сбор ещё не выполнен.
+
+
+
+ + +
+
+

Параметры веб-клиента

+
+
+
Источник данных
+
Автоматическое переключение между живым сервером и фикстурой
+
+
+ +
+
+
+
+
Интервал авто-опроса
+
Частота обновления снимка состояния с сервера
+
+
+ +
+
+
+
+
Токен безопасности (X-Hub-Token)
+
Обязателен при запуске сервера на нелокальном IP адресе
+
+
+ +
+
+
+ +
+
+
+
+
+
+ + + + + +
+ + + + + diff --git a/src/antigravity_provider/router/web/static/snapshot.example.json b/src/antigravity_provider/router/web/static/snapshot.example.json new file mode 100644 index 0000000..5fc6aec --- /dev/null +++ b/src/antigravity_provider/router/web/static/snapshot.example.json @@ -0,0 +1,5526 @@ +{ + "generation": 1, + "seq": 1, + "timestamp": 1787486370.6373527, + "profiles_by_provider": { + "antigravity": [ + { + "profile_id": "ag-cold-1", + "display_name": "Холодный резерв 1", + "account_identity": "Холодный резерв", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "spare" + ], + "primary_role": "spare", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "disabled", + "health_label_ru": "Отключён", + "model_states": {}, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": false, + "is_cold_spare": true, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "ag-cold-1", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini 5h", + "model_family": "gemini", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.446408+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [], + "active_leases": 0 + }, + { + "profile_id": "ag-cold-2", + "display_name": "Холодный резерв 2", + "account_identity": "Холодный резерв", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "spare" + ], + "primary_role": "spare", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "disabled", + "health_label_ru": "Отключён", + "model_states": {}, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": false, + "is_cold_spare": true, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "ag-cold-2", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini 5h", + "model_family": "gemini", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.447408+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [], + "active_leases": 0 + }, + { + "profile_id": "ag-cold-3", + "display_name": "Холодный резерв 3", + "account_identity": "Холодный резерв", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "spare" + ], + "primary_role": "spare", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "disabled", + "health_label_ru": "Отключён", + "model_states": {}, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": false, + "is_cold_spare": true, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "ag-cold-3", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini 5h", + "model_family": "gemini", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.448970+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [], + "active_leases": 0 + }, + { + "profile_id": "ag-orch-fallback", + "display_name": "Резервный оркестратор", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "orchestrator (primary)" + ], + "primary_role": "orchestrator", + "is_main_account": true, + "is_main_orchestrator": true, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.5-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "claude": { + "family": "claude", + "display_name": "claude-sonnet-4-6", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-orch-fallback", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:24+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:24+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 33.864653000000004, + "remaining_percent": 66.135347, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:19:06+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.0817700000000059, + "remaining_percent": 99.91823, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:21:42+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:22.944899+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.7-flash", + "claude-sonnet-4-6", + "gemini-3.5-flash" + ], + "active_leases": 0 + }, + { + "profile_id": "ag-spare-1", + "display_name": "Резерв 1", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "fast (primary)" + ], + "primary_role": "spare", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.5-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-spare-1", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:29+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:29+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 34.51999000000001, + "remaining_percent": 65.48001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-27T10:00:06+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-30T11:59:29+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:27.764730+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.6-flash-high", + "gemini-3.7-flash", + "gemini-3.5-flash" + ], + "active_leases": 0 + }, + { + "profile_id": "ag-spare-2", + "display_name": "Резерв 2", + "account_identity": "Аккаунт не добавлен", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "spare" + ], + "primary_role": "spare", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.5-flash", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "ag-spare-2", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini 5h", + "model_family": "gemini", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.453554+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.7-flash", + "gemini-3.5-flash" + ], + "active_leases": 0 + }, + { + "profile_id": "ag-w1", + "display_name": "Кодер 2", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "coder-primary (primary)" + ], + "primary_role": "coder", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.5-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "claude": { + "family": "claude", + "display_name": "claude-sonnet-4-6", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-w1", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:25+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:25+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 34.14447, + "remaining_percent": 65.85553, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:42:10+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.33874499999998875, + "remaining_percent": 99.66125500000001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:44:53+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:24.074829+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.7-flash", + "claude-sonnet-4-6", + "gemini-3.5-flash" + ], + "active_leases": 0 + }, + { + "profile_id": "ag-w2", + "display_name": "Исследователь", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "coder-secondary (primary)", + "reviewer (fallback 3)" + ], + "primary_role": "researcher", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.5-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-w2", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:26+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:26+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 62.585348, + "remaining_percent": 37.414652, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-25T06:09:55+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 19.49136, + "remaining_percent": 80.50864, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-24T16:18:52+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:25.134345+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.7-flash", + "gemini-3.5-flash" + ], + "active_leases": 0 + }, + { + "profile_id": "ag-w3", + "display_name": "Быстрый агент", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "reviewer (primary)", + "research (fallback 2)" + ], + "primary_role": "general", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.7-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "claude": { + "family": "claude", + "display_name": "claude-sonnet-4-6", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-w3", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:27+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:27+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 9.875199999999992, + "remaining_percent": 90.12480000000001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T12:12:02+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 16.673075999999995, + "remaining_percent": 83.326924, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T12:12:55+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:25.844507+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.7-flash", + "claude-sonnet-4-6" + ], + "active_leases": 0 + }, + { + "profile_id": "ag-w4", + "display_name": "Универсальный субагент", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "research (primary)", + "fast (fallback 2)" + ], + "primary_role": "general", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.7-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-w4", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:28+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:28+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 33.544296, + "remaining_percent": 66.455704, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:32:47+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.03422499999999218, + "remaining_percent": 99.96577500000001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:35:55+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:26.906876+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.5-flash", + "gemini-3.7-flash" + ], + "active_leases": 0 + } + ], + "openai-codex": [ + { + "profile_id": "codex-orch", + "display_name": "Главный оркестратор", + "account_identity": "Аккаунт не добавлен", + "provider": "openai-codex", + "provider_display_name": "OpenAI Codex", + "assigned_roles": [ + "orchestrator (fallback 1)" + ], + "primary_role": "orchestrator", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "gpt": { + "family": "gpt", + "display_name": "gpt-4o", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "o3": { + "family": "o3", + "display_name": "o3-mini", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "default": { + "family": "default", + "display_name": "codex", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "codex-orch", + "provider": "openai-codex", + "buckets": [ + { + "id": "codex.primary.weekly", + "display_name": "Codex Weekly", + "model_family": "gpt", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.466113+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "gpt-4o", + "o3-mini", + "codex" + ], + "active_leases": 0 + }, + { + "profile_id": "codex-worker-1", + "display_name": "Кодер 1", + "account_identity": "Аккаунт не добавлен", + "provider": "openai-codex", + "provider_display_name": "OpenAI Codex", + "assigned_roles": [ + "coder-primary (fallback 1)" + ], + "primary_role": "coder", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "gpt": { + "family": "gpt", + "display_name": "gpt-4o", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "o3": { + "family": "o3", + "display_name": "o3-mini", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "default": { + "family": "default", + "display_name": "codex", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "codex-worker-1", + "provider": "openai-codex", + "buckets": [ + { + "id": "codex.primary.weekly", + "display_name": "Codex Weekly", + "model_family": "gpt", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.467114+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "gpt-4o", + "o3-mini", + "codex" + ], + "active_leases": 0 + }, + { + "profile_id": "codex-worker-2", + "display_name": "Ревьюер", + "account_identity": "Аккаунт не добавлен", + "provider": "openai-codex", + "provider_display_name": "OpenAI Codex", + "assigned_roles": [ + "coder-secondary (fallback 1)", + "reviewer (fallback 1)" + ], + "primary_role": "reviewer", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "gpt": { + "family": "gpt", + "display_name": "gpt-4o", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "o3": { + "family": "o3", + "display_name": "o3-mini", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "default": { + "family": "default", + "display_name": "codex", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "codex-worker-2", + "provider": "openai-codex", + "buckets": [ + { + "id": "codex.primary.weekly", + "display_name": "Codex Weekly", + "model_family": "gpt", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.467114+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "gpt-4o", + "o3-mini", + "codex" + ], + "active_leases": 0 + } + ], + "opencode-go": [ + { + "profile_id": "opengo-1", + "display_name": "Кодер (OpenCode)", + "account_identity": "opengo-1", + "provider": "opencode-go", + "provider_display_name": "OpenCode Go", + "assigned_roles": [ + "research (fallback 1)", + "fast (fallback 1)" + ], + "primary_role": "coder", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "qwen": { + "family": "qwen", + "display_name": "qwen3.8-max", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "glm": { + "family": "glm", + "display_name": "glm-5.3", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "deepseek": { + "family": "deepseek", + "display_name": "deepseek-v4-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "grok": { + "family": "grok", + "display_name": "grok-4.5", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "", + "plan": "UNKNOWN", + "plan_code": "UNKNOWN", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "opengo-1", + "provider": "opencode-go", + "buckets": [ + { + "id": "opencode.5h", + "display_name": "Лимит 5 часов", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 12, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": "USD", + "scope": "account", + "status": "unknown" + }, + { + "id": "opencode.7d", + "display_name": "Недельный лимит", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 30, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": "USD", + "scope": "account", + "status": "unknown" + }, + { + "id": "opencode.30d", + "display_name": "Месячный лимит", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 60, + "reset_at": null, + "reset_in_seconds": null, + "period": "30d", + "unit": "USD", + "scope": "account", + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:28.785248+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": "Для этого ключа не активна подписка OpenCode Go" + }, + "preferred_models": [ + "qwen3.8-max", + "glm-5.3", + "deepseek-v4-flash", + "grok-4.5" + ], + "active_leases": 0 + }, + { + "profile_id": "opengo-2", + "display_name": "Исследователь (OpenCode)", + "account_identity": "Аккаунт не добавлен", + "provider": "opencode-go", + "provider_display_name": "OpenCode Go", + "assigned_roles": [ + "coder-secondary (fallback 2)", + "reviewer (fallback 2)" + ], + "primary_role": "researcher", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "deepseek": { + "family": "deepseek", + "display_name": "deepseek-v4-pro", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "grok": { + "family": "grok", + "display_name": "grok-4.5", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "qwen": { + "family": "qwen", + "display_name": "qwen3.7-max", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "opengo-2", + "provider": "opencode-go", + "buckets": [ + { + "id": "opencode.tasks", + "display_name": "OpenCode Tasks", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "30d", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.475546+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "deepseek-v4-pro", + "grok-4.5", + "qwen3.7-max" + ], + "active_leases": 0 + }, + { + "profile_id": "opengo-3", + "display_name": "Резервный роутер (OpenCode)", + "account_identity": "Аккаунт не добавлен", + "provider": "opencode-go", + "provider_display_name": "OpenCode Go", + "assigned_roles": [ + "orchestrator (fallback 2)", + "coder-primary (fallback 2)" + ], + "primary_role": "orchestrator", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "kimi": { + "family": "kimi", + "display_name": "kimi-k2.7-code", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "deepseek": { + "family": "deepseek", + "display_name": "deepseek-v4-pro", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "qwen": { + "family": "qwen", + "display_name": "qwen3.8-max", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "opengo-3", + "provider": "opencode-go", + "buckets": [ + { + "id": "opencode.tasks", + "display_name": "OpenCode Tasks", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "30d", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.476546+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "kimi-k2.7-code", + "deepseek-v4-pro", + "qwen3.8-max" + ], + "active_leases": 0 + } + ], + "claude": [ + { + "profile_id": "claude-orch", + "display_name": "Оркестратор (Claude)", + "account_identity": "Аккаунт не добавлен", + "provider": "claude", + "provider_display_name": "Claude", + "assigned_roles": [ + "orchestrator" + ], + "primary_role": "orchestrator", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "claude": { + "family": "claude", + "display_name": "claude-sonnet-4-6", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "claude-orch", + "provider": "claude", + "buckets": [ + { + "id": "claude.session.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.462075+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "claude-3-7-sonnet", + "claude-3-5-haiku", + "claude-sonnet-4-6" + ], + "active_leases": 0 + }, + { + "profile_id": "claude-worker-1", + "display_name": "Кодер (Claude)", + "account_identity": "Аккаунт не добавлен", + "provider": "claude", + "provider_display_name": "Claude", + "assigned_roles": [ + "coder" + ], + "primary_role": "coder", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "claude": { + "family": "claude", + "display_name": "claude-sonnet-4-6", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "claude-worker-1", + "provider": "claude", + "buckets": [ + { + "id": "claude.session.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.463114+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "claude-3-7-sonnet", + "claude-3-5-haiku", + "claude-sonnet-4-6" + ], + "active_leases": 0 + }, + { + "profile_id": "claude-worker-2", + "display_name": "Ревьюер (Claude)", + "account_identity": "Аккаунт не добавлен", + "provider": "claude", + "provider_display_name": "Claude", + "assigned_roles": [ + "reviewer" + ], + "primary_role": "reviewer", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "claude": { + "family": "claude", + "display_name": "claude-3-5-haiku", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "claude-worker-2", + "provider": "claude", + "buckets": [ + { + "id": "claude.session.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.464113+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "claude-3-7-sonnet", + "claude-3-5-haiku" + ], + "active_leases": 0 + } + ], + "grok": [ + { + "profile_id": "grok-orch", + "display_name": "Оркестратор (Grok)", + "account_identity": "user@example.test", + "provider": "grok", + "provider_display_name": "Grok", + "assigned_roles": [ + "orchestrator" + ], + "primary_role": "orchestrator", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "grok": { + "family": "grok", + "display_name": "grok-4.5", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "GROK PRO", + "plan_code": "GROK", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "grok-orch", + "provider": "grok", + "buckets": [ + { + "id": "grok.weekly", + "display_name": "Недельное", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.chat", + "display_name": "GrokChat", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.build", + "display_name": "GrokBuild", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.frequent_tasks", + "display_name": "Частые задачи", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 10, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.normal_tasks", + "display_name": "Обычные задачи", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 30, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.422866+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": "Grok не предоставляет остаток через публичный API" + }, + "preferred_models": [ + "grok-3", + "grok-3-mini", + "grok-4.5" + ], + "active_leases": 0 + }, + { + "profile_id": "grok-worker-1", + "display_name": "Кодер (Grok)", + "account_identity": "Аккаунт не добавлен", + "provider": "grok", + "provider_display_name": "Grok", + "assigned_roles": [ + "coder" + ], + "primary_role": "coder", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "grok": { + "family": "grok", + "display_name": "grok-4.5", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "grok-worker-1", + "provider": "grok", + "buckets": [ + { + "id": "grok.frequent_tasks", + "display_name": "Grok 2h", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "2h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.470955+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "grok-3", + "grok-3-mini", + "grok-4.5" + ], + "active_leases": 0 + }, + { + "profile_id": "grok-worker-2", + "display_name": "Исследователь (Grok)", + "account_identity": "Аккаунт не добавлен", + "provider": "grok", + "provider_display_name": "Grok", + "assigned_roles": [ + "researcher" + ], + "primary_role": "researcher", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "grok": { + "family": "grok", + "display_name": "grok-3-mini", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "grok-worker-2", + "provider": "grok", + "buckets": [ + { + "id": "grok.frequent_tasks", + "display_name": "Grok 2h", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "2h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.473553+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "grok-3", + "grok-3-mini" + ], + "active_leases": 0 + } + ] + }, + "all_profiles": { + "ag-cold-1": { + "profile_id": "ag-cold-1", + "display_name": "Холодный резерв 1", + "account_identity": "Холодный резерв", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "spare" + ], + "primary_role": "spare", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "disabled", + "health_label_ru": "Отключён", + "model_states": {}, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": false, + "is_cold_spare": true, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "ag-cold-1", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini 5h", + "model_family": "gemini", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.446408+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [], + "active_leases": 0 + }, + "ag-cold-2": { + "profile_id": "ag-cold-2", + "display_name": "Холодный резерв 2", + "account_identity": "Холодный резерв", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "spare" + ], + "primary_role": "spare", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "disabled", + "health_label_ru": "Отключён", + "model_states": {}, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": false, + "is_cold_spare": true, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "ag-cold-2", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini 5h", + "model_family": "gemini", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.447408+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [], + "active_leases": 0 + }, + "ag-cold-3": { + "profile_id": "ag-cold-3", + "display_name": "Холодный резерв 3", + "account_identity": "Холодный резерв", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "spare" + ], + "primary_role": "spare", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "disabled", + "health_label_ru": "Отключён", + "model_states": {}, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": false, + "is_cold_spare": true, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "ag-cold-3", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini 5h", + "model_family": "gemini", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.448970+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [], + "active_leases": 0 + }, + "ag-orch-fallback": { + "profile_id": "ag-orch-fallback", + "display_name": "Резервный оркестратор", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "orchestrator (primary)" + ], + "primary_role": "orchestrator", + "is_main_account": true, + "is_main_orchestrator": true, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.5-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "claude": { + "family": "claude", + "display_name": "claude-sonnet-4-6", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-orch-fallback", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:24+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:24+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 33.864653000000004, + "remaining_percent": 66.135347, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:19:06+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.0817700000000059, + "remaining_percent": 99.91823, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:21:42+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:22.944899+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.7-flash", + "claude-sonnet-4-6", + "gemini-3.5-flash" + ], + "active_leases": 0 + }, + "ag-spare-1": { + "profile_id": "ag-spare-1", + "display_name": "Резерв 1", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "fast (primary)" + ], + "primary_role": "spare", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.5-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-spare-1", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:29+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:29+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 34.51999000000001, + "remaining_percent": 65.48001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-27T10:00:06+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-30T11:59:29+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:27.764730+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.6-flash-high", + "gemini-3.7-flash", + "gemini-3.5-flash" + ], + "active_leases": 0 + }, + "ag-spare-2": { + "profile_id": "ag-spare-2", + "display_name": "Резерв 2", + "account_identity": "Аккаунт не добавлен", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "spare" + ], + "primary_role": "spare", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.5-flash", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "ag-spare-2", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini 5h", + "model_family": "gemini", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.453554+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.7-flash", + "gemini-3.5-flash" + ], + "active_leases": 0 + }, + "ag-w1": { + "profile_id": "ag-w1", + "display_name": "Кодер 2", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "coder-primary (primary)" + ], + "primary_role": "coder", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.5-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "claude": { + "family": "claude", + "display_name": "claude-sonnet-4-6", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-w1", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:25+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:25+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 34.14447, + "remaining_percent": 65.85553, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:42:10+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.33874499999998875, + "remaining_percent": 99.66125500000001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:44:53+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:24.074829+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.7-flash", + "claude-sonnet-4-6", + "gemini-3.5-flash" + ], + "active_leases": 0 + }, + "ag-w2": { + "profile_id": "ag-w2", + "display_name": "Исследователь", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "coder-secondary (primary)", + "reviewer (fallback 3)" + ], + "primary_role": "researcher", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.5-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-w2", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:26+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:26+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 62.585348, + "remaining_percent": 37.414652, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-25T06:09:55+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 19.49136, + "remaining_percent": 80.50864, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-24T16:18:52+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:25.134345+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.7-flash", + "gemini-3.5-flash" + ], + "active_leases": 0 + }, + "ag-w3": { + "profile_id": "ag-w3", + "display_name": "Быстрый агент", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "reviewer (primary)", + "research (fallback 2)" + ], + "primary_role": "general", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.7-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "claude": { + "family": "claude", + "display_name": "claude-sonnet-4-6", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-w3", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:27+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:27+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 9.875199999999992, + "remaining_percent": 90.12480000000001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T12:12:02+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 16.673075999999995, + "remaining_percent": 83.326924, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T12:12:55+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:25.844507+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.7-flash", + "claude-sonnet-4-6" + ], + "active_leases": 0 + }, + "ag-w4": { + "profile_id": "ag-w4", + "display_name": "Универсальный субагент", + "account_identity": "user@example.test", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "assigned_roles": [ + "research (primary)", + "fast (fallback 2)" + ], + "primary_role": "general", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "gemini": { + "family": "gemini", + "display_name": "gemini-3.7-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "PRO", + "plan_code": "PRO", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "ag-w4", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:28+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:28+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 33.544296, + "remaining_percent": 66.455704, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:32:47+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.03422499999999218, + "remaining_percent": 99.96577500000001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:35:55+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:26.906876+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "preferred_models": [ + "gemini-3.5-flash", + "gemini-3.7-flash" + ], + "active_leases": 0 + }, + "codex-orch": { + "profile_id": "codex-orch", + "display_name": "Главный оркестратор", + "account_identity": "Аккаунт не добавлен", + "provider": "openai-codex", + "provider_display_name": "OpenAI Codex", + "assigned_roles": [ + "orchestrator (fallback 1)" + ], + "primary_role": "orchestrator", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "gpt": { + "family": "gpt", + "display_name": "gpt-4o", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "o3": { + "family": "o3", + "display_name": "o3-mini", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "default": { + "family": "default", + "display_name": "codex", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "codex-orch", + "provider": "openai-codex", + "buckets": [ + { + "id": "codex.primary.weekly", + "display_name": "Codex Weekly", + "model_family": "gpt", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.466113+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "gpt-4o", + "o3-mini", + "codex" + ], + "active_leases": 0 + }, + "codex-worker-1": { + "profile_id": "codex-worker-1", + "display_name": "Кодер 1", + "account_identity": "Аккаунт не добавлен", + "provider": "openai-codex", + "provider_display_name": "OpenAI Codex", + "assigned_roles": [ + "coder-primary (fallback 1)" + ], + "primary_role": "coder", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "gpt": { + "family": "gpt", + "display_name": "gpt-4o", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "o3": { + "family": "o3", + "display_name": "o3-mini", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "default": { + "family": "default", + "display_name": "codex", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "codex-worker-1", + "provider": "openai-codex", + "buckets": [ + { + "id": "codex.primary.weekly", + "display_name": "Codex Weekly", + "model_family": "gpt", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.467114+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "gpt-4o", + "o3-mini", + "codex" + ], + "active_leases": 0 + }, + "codex-worker-2": { + "profile_id": "codex-worker-2", + "display_name": "Ревьюер", + "account_identity": "Аккаунт не добавлен", + "provider": "openai-codex", + "provider_display_name": "OpenAI Codex", + "assigned_roles": [ + "coder-secondary (fallback 1)", + "reviewer (fallback 1)" + ], + "primary_role": "reviewer", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "gpt": { + "family": "gpt", + "display_name": "gpt-4o", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "o3": { + "family": "o3", + "display_name": "o3-mini", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "default": { + "family": "default", + "display_name": "codex", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "codex-worker-2", + "provider": "openai-codex", + "buckets": [ + { + "id": "codex.primary.weekly", + "display_name": "Codex Weekly", + "model_family": "gpt", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.467114+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "gpt-4o", + "o3-mini", + "codex" + ], + "active_leases": 0 + }, + "opengo-1": { + "profile_id": "opengo-1", + "display_name": "Кодер (OpenCode)", + "account_identity": "opengo-1", + "provider": "opencode-go", + "provider_display_name": "OpenCode Go", + "assigned_roles": [ + "research (fallback 1)", + "fast (fallback 1)" + ], + "primary_role": "coder", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "qwen": { + "family": "qwen", + "display_name": "qwen3.8-max", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "glm": { + "family": "glm", + "display_name": "glm-5.3", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "deepseek": { + "family": "deepseek", + "display_name": "deepseek-v4-flash", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "grok": { + "family": "grok", + "display_name": "grok-4.5", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "", + "plan": "UNKNOWN", + "plan_code": "UNKNOWN", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "opengo-1", + "provider": "opencode-go", + "buckets": [ + { + "id": "opencode.5h", + "display_name": "Лимит 5 часов", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 12, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": "USD", + "scope": "account", + "status": "unknown" + }, + { + "id": "opencode.7d", + "display_name": "Недельный лимит", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 30, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": "USD", + "scope": "account", + "status": "unknown" + }, + { + "id": "opencode.30d", + "display_name": "Месячный лимит", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 60, + "reset_at": null, + "reset_in_seconds": null, + "period": "30d", + "unit": "USD", + "scope": "account", + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:28.785248+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": "Для этого ключа не активна подписка OpenCode Go" + }, + "preferred_models": [ + "qwen3.8-max", + "glm-5.3", + "deepseek-v4-flash", + "grok-4.5" + ], + "active_leases": 0 + }, + "opengo-2": { + "profile_id": "opengo-2", + "display_name": "Исследователь (OpenCode)", + "account_identity": "Аккаунт не добавлен", + "provider": "opencode-go", + "provider_display_name": "OpenCode Go", + "assigned_roles": [ + "coder-secondary (fallback 2)", + "reviewer (fallback 2)" + ], + "primary_role": "researcher", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "deepseek": { + "family": "deepseek", + "display_name": "deepseek-v4-pro", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "grok": { + "family": "grok", + "display_name": "grok-4.5", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "qwen": { + "family": "qwen", + "display_name": "qwen3.7-max", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "opengo-2", + "provider": "opencode-go", + "buckets": [ + { + "id": "opencode.tasks", + "display_name": "OpenCode Tasks", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "30d", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.475546+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "deepseek-v4-pro", + "grok-4.5", + "qwen3.7-max" + ], + "active_leases": 0 + }, + "opengo-3": { + "profile_id": "opengo-3", + "display_name": "Резервный роутер (OpenCode)", + "account_identity": "Аккаунт не добавлен", + "provider": "opencode-go", + "provider_display_name": "OpenCode Go", + "assigned_roles": [ + "orchestrator (fallback 2)", + "coder-primary (fallback 2)" + ], + "primary_role": "orchestrator", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "kimi": { + "family": "kimi", + "display_name": "kimi-k2.7-code", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "deepseek": { + "family": "deepseek", + "display_name": "deepseek-v4-pro", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + }, + "qwen": { + "family": "qwen", + "display_name": "qwen3.8-max", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "opengo-3", + "provider": "opencode-go", + "buckets": [ + { + "id": "opencode.tasks", + "display_name": "OpenCode Tasks", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "30d", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.476546+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "kimi-k2.7-code", + "deepseek-v4-pro", + "qwen3.8-max" + ], + "active_leases": 0 + }, + "claude-orch": { + "profile_id": "claude-orch", + "display_name": "Оркестратор (Claude)", + "account_identity": "Аккаунт не добавлен", + "provider": "claude", + "provider_display_name": "Claude", + "assigned_roles": [ + "orchestrator" + ], + "primary_role": "orchestrator", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "claude": { + "family": "claude", + "display_name": "claude-sonnet-4-6", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "claude-orch", + "provider": "claude", + "buckets": [ + { + "id": "claude.session.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.462075+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "claude-3-7-sonnet", + "claude-3-5-haiku", + "claude-sonnet-4-6" + ], + "active_leases": 0 + }, + "claude-worker-1": { + "profile_id": "claude-worker-1", + "display_name": "Кодер (Claude)", + "account_identity": "Аккаунт не добавлен", + "provider": "claude", + "provider_display_name": "Claude", + "assigned_roles": [ + "coder" + ], + "primary_role": "coder", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "claude": { + "family": "claude", + "display_name": "claude-sonnet-4-6", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "claude-worker-1", + "provider": "claude", + "buckets": [ + { + "id": "claude.session.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.463114+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "claude-3-7-sonnet", + "claude-3-5-haiku", + "claude-sonnet-4-6" + ], + "active_leases": 0 + }, + "claude-worker-2": { + "profile_id": "claude-worker-2", + "display_name": "Ревьюер (Claude)", + "account_identity": "Аккаунт не добавлен", + "provider": "claude", + "provider_display_name": "Claude", + "assigned_roles": [ + "reviewer" + ], + "primary_role": "reviewer", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "claude": { + "family": "claude", + "display_name": "claude-3-5-haiku", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "claude-worker-2", + "provider": "claude", + "buckets": [ + { + "id": "claude.session.5h", + "display_name": "Claude 5h", + "model_family": "claude", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.464113+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "claude-3-7-sonnet", + "claude-3-5-haiku" + ], + "active_leases": 0 + }, + "grok-orch": { + "profile_id": "grok-orch", + "display_name": "Оркестратор (Grok)", + "account_identity": "user@example.test", + "provider": "grok", + "provider_display_name": "Grok", + "assigned_roles": [ + "orchestrator" + ], + "primary_role": "orchestrator", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "AUTHENTICATED", + "health_state": "healthy", + "health_label_ru": "Работает", + "model_states": { + "grok": { + "family": "grok", + "display_name": "grok-4.5", + "status": "healthy", + "status_label_ru": "Работает", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": false, + "email": "user@example.test", + "plan": "GROK PRO", + "plan_code": "GROK", + "plan_source": "provider_auth", + "quota_snapshot": { + "account_id": "grok-orch", + "provider": "grok", + "buckets": [ + { + "id": "grok.weekly", + "display_name": "Недельное", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.chat", + "display_name": "GrokChat", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.build", + "display_name": "GrokBuild", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.frequent_tasks", + "display_name": "Частые задачи", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 10, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.normal_tasks", + "display_name": "Обычные задачи", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 30, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.422866+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": "Grok не предоставляет остаток через публичный API" + }, + "preferred_models": [ + "grok-3", + "grok-3-mini", + "grok-4.5" + ], + "active_leases": 0 + }, + "grok-worker-1": { + "profile_id": "grok-worker-1", + "display_name": "Кодер (Grok)", + "account_identity": "Аккаунт не добавлен", + "provider": "grok", + "provider_display_name": "Grok", + "assigned_roles": [ + "coder" + ], + "primary_role": "coder", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "grok": { + "family": "grok", + "display_name": "grok-4.5", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "grok-worker-1", + "provider": "grok", + "buckets": [ + { + "id": "grok.frequent_tasks", + "display_name": "Grok 2h", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "2h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.470955+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "grok-3", + "grok-3-mini", + "grok-4.5" + ], + "active_leases": 0 + }, + "grok-worker-2": { + "profile_id": "grok-worker-2", + "display_name": "Исследователь (Grok)", + "account_identity": "Аккаунт не добавлен", + "provider": "grok", + "provider_display_name": "Grok", + "assigned_roles": [ + "researcher" + ], + "primary_role": "researcher", + "is_main_account": false, + "is_main_orchestrator": false, + "auth_state": "NOT_CONFIGURED", + "health_state": "not_configured", + "health_label_ru": "Аккаунт не добавлен", + "model_states": { + "grok": { + "family": "grok", + "display_name": "grok-3-mini", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "cooldown_remaining_sec": 0, + "reset_at": null, + "reason": null + } + }, + "cooldown_remaining_sec": 0, + "last_checked_at": "18:59:30", + "enabled": true, + "is_cold_spare": false, + "is_empty_slot": true, + "email": "", + "plan": "Тариф: неизвестен", + "plan_code": "UNKNOWN", + "plan_source": "unknown", + "quota_snapshot": { + "account_id": "grok-worker-2", + "provider": "grok", + "buckets": [ + { + "id": "grok.frequent_tasks", + "display_name": "Grok 2h", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "2h", + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.473553+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": null + }, + "preferred_models": [ + "grok-3", + "grok-3-mini" + ], + "active_leases": 0 + } + }, + "readiness": { + "state": "healthy", + "title_ru": "Полная готовность", + "summary_ru": "Все системы и резервы в строю.", + "roles_ready_count": 6, + "total_roles": 6, + "accounts_connected_count": 8, + "total_accounts": 8, + "providers_ready_count": 3, + "total_providers": 5, + "warnings": [] + }, + "agents": [ + { + "role_id": "orchestrator", + "role_name_ru": "Главный оркестратор", + "role_description_ru": "Управление командой, планирование, контроль исполнения", + "assigned_profile_id": "ag-orch-fallback", + "assigned_display_name": "Резервный оркестратор", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "model": "gemini-3.7-flash", + "account_identity": "user@example.test", + "routing_position": "Primary", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "is_main_orchestrator": true, + "cooldown_remaining_sec": 0, + "session_id": null, + "active_quota_status": "healthy", + "active_quota_label": "Осталось 100%" + }, + { + "role_id": "coder-primary", + "role_name_ru": "Кодер 1", + "role_description_ru": "Основная разработка кода и исправление дефектов", + "assigned_profile_id": "ag-w1", + "assigned_display_name": "Кодер 2", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "model": "gemini-3.7-flash", + "account_identity": "user@example.test", + "routing_position": "Primary", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "is_main_orchestrator": false, + "cooldown_remaining_sec": 0, + "session_id": null, + "active_quota_status": "healthy", + "active_quota_label": "Осталось 100%" + }, + { + "role_id": "coder-secondary", + "role_name_ru": "Кодер 2", + "role_description_ru": "Параллельная разработка и вспомогательные модули", + "assigned_profile_id": "ag-w2", + "assigned_display_name": "Исследователь", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "model": "gemini-3.7-flash", + "account_identity": "user@example.test", + "routing_position": "Primary", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "is_main_orchestrator": false, + "cooldown_remaining_sec": 0, + "session_id": null, + "active_quota_status": "healthy", + "active_quota_label": "Осталось 81%" + }, + { + "role_id": "reviewer", + "role_name_ru": "Ревьюер", + "role_description_ru": "Независимое fail-closed ревью и валидация diff", + "assigned_profile_id": "ag-w3", + "assigned_display_name": "Быстрый агент", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "model": "gemini-3.7-flash", + "account_identity": "user@example.test", + "routing_position": "Primary", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "is_main_orchestrator": false, + "cooldown_remaining_sec": 0, + "session_id": null, + "active_quota_status": "healthy", + "active_quota_label": "Осталось 83%" + }, + { + "role_id": "research", + "role_name_ru": "Исследователь", + "role_description_ru": "Read-only поиск в кодовой базе и сбор фактов", + "assigned_profile_id": "ag-w4", + "assigned_display_name": "Универсальный субагент", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "model": "gemini-3.5-flash", + "account_identity": "user@example.test", + "routing_position": "Primary", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "is_main_orchestrator": false, + "cooldown_remaining_sec": 0, + "session_id": null, + "active_quota_status": "healthy", + "active_quota_label": "Осталось 100%" + }, + { + "role_id": "fast", + "role_name_ru": "Быстрый агент", + "role_description_ru": "Оперативные вызовы, вспомогательные проверки", + "assigned_profile_id": "ag-spare-1", + "assigned_display_name": "Резерв 1", + "provider": "antigravity", + "provider_display_name": "Google Antigravity", + "model": "gemini-3.6-flash-high", + "account_identity": "user@example.test", + "routing_position": "Primary", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "is_main_orchestrator": false, + "cooldown_remaining_sec": 0, + "session_id": null, + "active_quota_status": "healthy", + "active_quota_label": "Осталось 100%" + } + ], + "providers": [ + { + "provider_id": "antigravity", + "provider_name": "Google Antigravity", + "total_slots": 10, + "connected_count": 6, + "online_count": 6, + "auth_required_count": 0, + "quota_exhausted_count": 0, + "cold_spare_count": 3, + "discovered_models": [ + "claude-sonnet-4-6", + "gemini-3.5-flash", + "gemini-3.6-flash-high", + "gemini-3.7-flash" + ], + "last_refresh_at": "18:59:30" + }, + { + "provider_id": "grok", + "provider_name": "Grok", + "total_slots": 3, + "connected_count": 1, + "online_count": 1, + "auth_required_count": 0, + "quota_exhausted_count": 0, + "cold_spare_count": 0, + "discovered_models": [ + "grok-3", + "grok-3-mini", + "grok-4.5" + ], + "last_refresh_at": "18:59:30" + }, + { + "provider_id": "opencode-go", + "provider_name": "OpenCode Go", + "total_slots": 3, + "connected_count": 1, + "online_count": 1, + "auth_required_count": 0, + "quota_exhausted_count": 0, + "cold_spare_count": 0, + "discovered_models": [ + "deepseek-v4-flash", + "deepseek-v4-pro", + "glm-5.3", + "grok-4.5", + "kimi-k2.7-code", + "qwen3.7-max", + "qwen3.8-max" + ], + "last_refresh_at": "18:59:30" + }, + { + "provider_id": "claude", + "provider_name": "Claude", + "total_slots": 3, + "connected_count": 0, + "online_count": 0, + "auth_required_count": 0, + "quota_exhausted_count": 0, + "cold_spare_count": 0, + "discovered_models": [ + "claude-3-5-haiku", + "claude-3-7-sonnet", + "claude-sonnet-4-6" + ], + "last_refresh_at": "18:59:30" + }, + { + "provider_id": "openai-codex", + "provider_name": "OpenAI Codex", + "total_slots": 3, + "connected_count": 0, + "online_count": 0, + "auth_required_count": 0, + "quota_exhausted_count": 0, + "cold_spare_count": 0, + "discovered_models": [ + "codex", + "gpt-4o", + "o3-mini" + ], + "last_refresh_at": "18:59:30" + } + ], + "routing": { + "orchestrator": { + "role_id": "orchestrator", + "role_name_ru": "Главный оркестратор", + "default_model": "gemini-3.7-flash", + "max_failover": 3, + "session_affinity": true, + "active_profile_id": "ag-orch-fallback", + "nodes": [ + { + "profile_id": "ag-orch-fallback", + "display_name": "Резервный оркестратор", + "provider": "Google Antigravity", + "model": "gemini-3.7-flash", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "cooldown_remaining_sec": 0, + "account_identity": "user@example.test", + "quota_status": "healthy", + "failover_reason": null + }, + { + "profile_id": "codex-orch", + "display_name": "Главный оркестратор", + "provider": "OpenAI Codex", + "model": "gpt-4o", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "Аккаунт не добавлен", + "quota_status": "unknown", + "failover_reason": null + }, + { + "profile_id": "opengo-3", + "display_name": "Резервный роутер (OpenCode)", + "provider": "OpenCode Go", + "model": "kimi-k2.7-code", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "Аккаунт не добавлен", + "quota_status": "unknown", + "failover_reason": null + } + ] + }, + "coder-primary": { + "role_id": "coder-primary", + "role_name_ru": "Кодер 1 (Primary)", + "default_model": "auto", + "max_failover": 3, + "session_affinity": true, + "active_profile_id": "ag-w1", + "nodes": [ + { + "profile_id": "ag-w1", + "display_name": "Кодер 2", + "provider": "Google Antigravity", + "model": "gemini-3.7-flash", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "cooldown_remaining_sec": 0, + "account_identity": "user@example.test", + "quota_status": "healthy", + "failover_reason": null + }, + { + "profile_id": "codex-worker-1", + "display_name": "Кодер 1", + "provider": "OpenAI Codex", + "model": "gpt-4o", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "Аккаунт не добавлен", + "quota_status": "unknown", + "failover_reason": null + }, + { + "profile_id": "opengo-3", + "display_name": "Резервный роутер (OpenCode)", + "provider": "OpenCode Go", + "model": "kimi-k2.7-code", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "Аккаунт не добавлен", + "quota_status": "unknown", + "failover_reason": null + } + ] + }, + "coder-secondary": { + "role_id": "coder-secondary", + "role_name_ru": "Кодер 2 (Secondary)", + "default_model": "auto", + "max_failover": 3, + "session_affinity": true, + "active_profile_id": "ag-w2", + "nodes": [ + { + "profile_id": "ag-w2", + "display_name": "Исследователь", + "provider": "Google Antigravity", + "model": "gemini-3.7-flash", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "cooldown_remaining_sec": 0, + "account_identity": "user@example.test", + "quota_status": "healthy", + "failover_reason": null + }, + { + "profile_id": "codex-worker-2", + "display_name": "Ревьюер", + "provider": "OpenAI Codex", + "model": "gpt-4o", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "Аккаунт не добавлен", + "quota_status": "unknown", + "failover_reason": null + }, + { + "profile_id": "opengo-2", + "display_name": "Исследователь (OpenCode)", + "provider": "OpenCode Go", + "model": "deepseek-v4-pro", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "Аккаунт не добавлен", + "quota_status": "unknown", + "failover_reason": null + } + ] + }, + "reviewer": { + "role_id": "reviewer", + "role_name_ru": "Ревьюер", + "default_model": "auto", + "max_failover": 3, + "session_affinity": true, + "active_profile_id": "ag-w3", + "nodes": [ + { + "profile_id": "ag-w3", + "display_name": "Быстрый агент", + "provider": "Google Antigravity", + "model": "gemini-3.7-flash", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "cooldown_remaining_sec": 0, + "account_identity": "user@example.test", + "quota_status": "healthy", + "failover_reason": null + }, + { + "profile_id": "codex-worker-2", + "display_name": "Ревьюер", + "provider": "OpenAI Codex", + "model": "gpt-4o", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "Аккаунт не добавлен", + "quota_status": "unknown", + "failover_reason": null + }, + { + "profile_id": "opengo-2", + "display_name": "Исследователь (OpenCode)", + "provider": "OpenCode Go", + "model": "deepseek-v4-pro", + "status": "not_configured", + "status_label_ru": "Аккаунт не добавлен", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "Аккаунт не добавлен", + "quota_status": "unknown", + "failover_reason": null + }, + { + "profile_id": "ag-w2", + "display_name": "Исследователь", + "provider": "Google Antigravity", + "model": "gemini-3.7-flash", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "user@example.test", + "quota_status": "healthy", + "failover_reason": null + } + ] + }, + "research": { + "role_id": "research", + "role_name_ru": "Исследователь", + "default_model": "auto", + "max_failover": 3, + "session_affinity": true, + "active_profile_id": "ag-w4", + "nodes": [ + { + "profile_id": "ag-w4", + "display_name": "Универсальный субагент", + "provider": "Google Antigravity", + "model": "gemini-3.5-flash", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "cooldown_remaining_sec": 0, + "account_identity": "user@example.test", + "quota_status": "healthy", + "failover_reason": null + }, + { + "profile_id": "opengo-1", + "display_name": "Кодер (OpenCode)", + "provider": "OpenCode Go", + "model": "qwen3.8-max", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "opengo-1", + "quota_status": "unknown", + "failover_reason": null + }, + { + "profile_id": "ag-w3", + "display_name": "Быстрый агент", + "provider": "Google Antigravity", + "model": "gemini-3.7-flash", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "user@example.test", + "quota_status": "healthy", + "failover_reason": null + } + ] + }, + "fast": { + "role_id": "fast", + "role_name_ru": "Быстрый агент", + "default_model": "gemini-3.6-flash-high", + "max_failover": 3, + "session_affinity": false, + "active_profile_id": "ag-spare-1", + "nodes": [ + { + "profile_id": "ag-spare-1", + "display_name": "Резерв 1", + "provider": "Google Antigravity", + "model": "gemini-3.6-flash-high", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": true, + "cooldown_remaining_sec": 0, + "account_identity": "user@example.test", + "quota_status": "healthy", + "failover_reason": null + }, + { + "profile_id": "opengo-1", + "display_name": "Кодер (OpenCode)", + "provider": "OpenCode Go", + "model": "qwen3.8-max", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "opengo-1", + "quota_status": "unknown", + "failover_reason": null + }, + { + "profile_id": "ag-w4", + "display_name": "Универсальный субагент", + "provider": "Google Antigravity", + "model": "gemini-3.5-flash", + "status": "healthy", + "status_label_ru": "Работает", + "is_active": false, + "cooldown_remaining_sec": 0, + "account_identity": "user@example.test", + "quota_status": "healthy", + "failover_reason": null + } + ] + } + }, + "quotas": { + "ag-orch-fallback": { + "account_id": "ag-orch-fallback", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:24+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:24+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 33.864653000000004, + "remaining_percent": 66.135347, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:19:06+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.0817700000000059, + "remaining_percent": 99.91823, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:21:42+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:22.944899+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "ag-spare-1": { + "account_id": "ag-spare-1", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:29+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:29+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 34.51999000000001, + "remaining_percent": 65.48001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-27T10:00:06+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-30T11:59:29+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:27.764730+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "ag-w1": { + "account_id": "ag-w1", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:25+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:25+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 34.14447, + "remaining_percent": 65.85553, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:42:10+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.33874499999998875, + "remaining_percent": 99.66125500000001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:44:53+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:24.074829+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "ag-w2": { + "account_id": "ag-w2", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:26+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:26+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 62.585348, + "remaining_percent": 37.414652, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-25T06:09:55+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 19.49136, + "remaining_percent": 80.50864, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-24T16:18:52+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:25.134345+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "ag-w3": { + "account_id": "ag-w3", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:27+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:27+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 9.875199999999992, + "remaining_percent": 90.12480000000001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T12:12:02+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 16.673075999999995, + "remaining_percent": 83.326924, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T12:12:55+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:25.844507+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "ag-w4": { + "account_id": "ag-w4", + "provider": "antigravity", + "buckets": [ + { + "id": "antigravity.claude.5h", + "display_name": "Claude/GPT • 5 часов", + "model_family": "claude", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:28+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.5h", + "display_name": "Gemini • 5 часов", + "model_family": "gemini", + "used_percent": 0.0, + "remaining_percent": 100.0, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-23T16:59:28+00:00", + "reset_in_seconds": null, + "period": "5h", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.claude.7d", + "display_name": "Claude/GPT • неделя", + "model_family": "claude", + "used_percent": 33.544296, + "remaining_percent": 66.455704, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:32:47+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + }, + { + "id": "antigravity.gemini.7d", + "display_name": "Gemini • неделя", + "model_family": "gemini", + "used_percent": 0.03422499999999218, + "remaining_percent": 99.96577500000001, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": "2026-08-26T11:35:55+00:00", + "reset_in_seconds": null, + "period": "7d", + "unit": "model capacity", + "scope": "model_family", + "status": "healthy" + } + ], + "fetched_at": "2026-08-23T11:59:26.906876+00:00", + "stale_after_seconds": 300, + "source": "provider_api", + "unavailable_reason": null + }, + "opengo-1": { + "account_id": "opengo-1", + "provider": "opencode-go", + "buckets": [ + { + "id": "opencode.5h", + "display_name": "Лимит 5 часов", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 12, + "reset_at": null, + "reset_in_seconds": null, + "period": "5h", + "unit": "USD", + "scope": "account", + "status": "unknown" + }, + { + "id": "opencode.7d", + "display_name": "Недельный лимит", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 30, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": "USD", + "scope": "account", + "status": "unknown" + }, + { + "id": "opencode.30d", + "display_name": "Месячный лимит", + "model_family": "opencode", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 60, + "reset_at": null, + "reset_in_seconds": null, + "period": "30d", + "unit": "USD", + "scope": "account", + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:28.785248+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": "Для этого ключа не активна подписка OpenCode Go" + }, + "grok-orch": { + "account_id": "grok-orch", + "provider": "grok", + "buckets": [ + { + "id": "grok.weekly", + "display_name": "Недельное", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": "7d", + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.chat", + "display_name": "GrokChat", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.build", + "display_name": "GrokBuild", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": null, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.frequent_tasks", + "display_name": "Частые задачи", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 10, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + }, + { + "id": "grok.normal_tasks", + "display_name": "Обычные задачи", + "model_family": "grok", + "used_percent": null, + "remaining_percent": null, + "used_absolute": null, + "remaining_absolute": null, + "limit_absolute": 30, + "reset_at": null, + "reset_in_seconds": null, + "period": null, + "unit": null, + "scope": null, + "status": "unknown" + } + ], + "fetched_at": "2026-08-23T11:59:30.422866+00:00", + "stale_after_seconds": 300, + "source": "baseline", + "unavailable_reason": "Grok не предоставляет остаток через публичный API" + } + }, + "metrics": { + "generation": 1, + "seq": 1, + "duration_ms": 213.52, + "total_profiles": 22, + "authenticated_profiles": 8, + "refresh_runs_total": 1, + "refresh_deduplicated_total": 0, + "telemetry": { + "global": { + "window_seconds": 86400, + "total_calls": 19, + "successful_calls": 4, + "failed_calls": 15, + "call_share": 1.0, + "error_rate": 0.7895, + "latency_p50_ms": 1.4, + "latency_p95_ms": 81631.1, + "latency_max_ms": 81777.7, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 14, + "failover_reasons": { + "failover": 4, + "quota-exhausted": 2, + "rate-limited": 3, + "fatal": 3, + "auth-required": 2 + }, + "source": "own_measurement", + "has_data": true + }, + "by_provider": { + "antigravity": { + "window_seconds": 86400, + "total_calls": 7, + "successful_calls": 2, + "failed_calls": 5, + "call_share": 0.3684, + "error_rate": 0.7143, + "latency_p50_ms": 1.4, + "latency_p95_ms": 81728.8, + "latency_max_ms": 81777.7, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 6, + "failover_reasons": { + "failover": 2, + "quota-exhausted": 2, + "auth-required": 2 + }, + "source": "own_measurement", + "has_data": true + }, + "claude": { + "window_seconds": 86400, + "total_calls": 0, + "successful_calls": 0, + "failed_calls": 0, + "call_share": null, + "error_rate": null, + "latency_p50_ms": null, + "latency_p95_ms": null, + "latency_max_ms": null, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 0, + "failover_reasons": {}, + "source": "own_measurement", + "has_data": false + }, + "grok": { + "window_seconds": 86400, + "total_calls": 0, + "successful_calls": 0, + "failed_calls": 0, + "call_share": null, + "error_rate": null, + "latency_p50_ms": null, + "latency_p95_ms": null, + "latency_max_ms": null, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 0, + "failover_reasons": {}, + "source": "own_measurement", + "has_data": false + }, + "openai-codex": { + "window_seconds": 86400, + "total_calls": 7, + "successful_calls": 0, + "failed_calls": 7, + "call_share": 0.3684, + "error_rate": 1.0, + "latency_p50_ms": 54.6, + "latency_p95_ms": 1649.1, + "latency_max_ms": 1821.7, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 3, + "failover_reasons": { + "rate-limited": 3 + }, + "source": "own_measurement", + "has_data": true + }, + "opencode-go": { + "window_seconds": 86400, + "total_calls": 5, + "successful_calls": 2, + "failed_calls": 3, + "call_share": 0.2632, + "error_rate": 0.6, + "latency_p50_ms": 0.0, + "latency_p95_ms": 1.2, + "latency_max_ms": 1.5, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 5, + "failover_reasons": { + "failover": 2, + "fatal": 3 + }, + "source": "own_measurement", + "has_data": true + } + }, + "by_role": { + "coder-primary": { + "window_seconds": 86400, + "total_calls": 0, + "successful_calls": 0, + "failed_calls": 0, + "call_share": null, + "error_rate": null, + "latency_p50_ms": null, + "latency_p95_ms": null, + "latency_max_ms": null, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 0, + "failover_reasons": {}, + "source": "own_measurement", + "has_data": false + }, + "coder-secondary": { + "window_seconds": 86400, + "total_calls": 0, + "successful_calls": 0, + "failed_calls": 0, + "call_share": null, + "error_rate": null, + "latency_p50_ms": null, + "latency_p95_ms": null, + "latency_max_ms": null, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 0, + "failover_reasons": {}, + "source": "own_measurement", + "has_data": false + }, + "fast": { + "window_seconds": 86400, + "total_calls": 0, + "successful_calls": 0, + "failed_calls": 0, + "call_share": null, + "error_rate": null, + "latency_p50_ms": null, + "latency_p95_ms": null, + "latency_max_ms": null, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 0, + "failover_reasons": {}, + "source": "own_measurement", + "has_data": false + }, + "orchestrator": { + "window_seconds": 86400, + "total_calls": 19, + "successful_calls": 4, + "failed_calls": 15, + "call_share": 1.0, + "error_rate": 0.7895, + "latency_p50_ms": 1.4, + "latency_p95_ms": 81631.1, + "latency_max_ms": 81777.7, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 14, + "failover_reasons": { + "failover": 4, + "quota-exhausted": 2, + "rate-limited": 3, + "fatal": 3, + "auth-required": 2 + }, + "source": "own_measurement", + "has_data": true + }, + "research": { + "window_seconds": 86400, + "total_calls": 0, + "successful_calls": 0, + "failed_calls": 0, + "call_share": null, + "error_rate": null, + "latency_p50_ms": null, + "latency_p95_ms": null, + "latency_max_ms": null, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 0, + "failover_reasons": {}, + "source": "own_measurement", + "has_data": false + }, + "reviewer": { + "window_seconds": 86400, + "total_calls": 0, + "successful_calls": 0, + "failed_calls": 0, + "call_share": null, + "error_rate": null, + "latency_p50_ms": null, + "latency_p95_ms": null, + "latency_max_ms": null, + "total_prompt_tokens": null, + "total_completion_tokens": null, + "total_tokens": null, + "total_cost_usd": null, + "failovers_count": 0, + "failover_reasons": {}, + "source": "own_measurement", + "has_data": false + } + }, + "window_seconds": 86400, + "source": "own_measurement", + "has_data": true + }, + "host": { + "timestamp": 1787486370.559663, + "cpu_percent": 11.8, + "memory_percent": 75.5, + "memory_used_mb": 9077.9, + "memory_total_mb": 12029.9, + "disk_percent": 53.7, + "disk_used_gb": 255.7, + "disk_total_gb": 475.8, + "net_speed_mbps": null, + "net_sent_mbps": null, + "net_recv_mbps": null, + "net_bytes_sent": 50246011831, + "net_bytes_recv": 44459820387, + "source": "host_measurement", + "has_data": true + }, + "active_calls_total": 0, + "active_calls_by_profile": {} + }, + "is_stale": false +} \ No newline at end of file diff --git a/src/antigravity_provider/router/web/static/style.css b/src/antigravity_provider/router/web/static/style.css new file mode 100644 index 0000000..99c8ed4 --- /dev/null +++ b/src/antigravity_provider/router/web/static/style.css @@ -0,0 +1,1044 @@ +/* Hermes Hub Web Client — Dark Theme & Cockpit Design System */ + +:root { + --bg-base: #061916; + --bg-sidebar: #08221E; + --bg-header: #071B18; + --bg-statusbar: #061512; + --bg-modal-backdrop: rgba(2, 11, 9, 0.85); + + --surface: #0B2520; + --surface-hover: #12342C; + --surface-active: #194535; + --surface-selected: #173B2E; + --surface-muted: #091E1A; + + --border: #36513B; + --border-subtle: #203A2D; + --border-accent: #B78525; + --border-hover: #537456; + + --text-primary: #F8F0DC; + --text-secondary: #D1C7AE; + --text-muted: #8FA395; + --text-accent: #E0B84E; + + --accent: #C89A2B; + --accent-hover: #E0B84E; + --accent-pressed: #A9781E; + --accent-dim: rgba(200, 154, 43, 0.15); + + --status-healthy: #72C943; + --status-warning: #E1A62B; + --status-error: #E45C4F; + --status-info: #4C8DD8; + --status-disabled: #708078; + + --prov-antigravity: #74A9FF; + --prov-codex: #46BE8A; + --prov-opencode: #F39A50; + --prov-claude: #DF9C63; + --prov-grok: #3B82F6; + + --radius-sm: 4px; + --radius-md: 6px; + --radius-lg: 8px; + + --font-ui: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, sans-serif; + --font-title: "Cinzel", "Segoe UI", serif, sans-serif; + --font-mono: "Consolas", "Courier New", monospace; + + --header-height: 58px; + --sidebar-width: 230px; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + background-color: var(--bg-base); + color: var(--text-primary); + font-family: var(--font-ui); + font-size: 13px; + line-height: 1.4; + overflow: hidden; + height: 100vh; + width: 100vw; + user-select: none; + -webkit-font-smoothing: antialiased; +} + +/* ── Typography & Utilities ── */ +.text-healthy { color: var(--status-healthy); } +.text-warning { color: var(--status-warning); } +.text-error { color: var(--status-error); } +.text-info { color: var(--status-info); } +.text-accent { color: var(--text-accent); } +.text-muted { color: var(--text-muted); } +.text-secondary { color: var(--text-secondary); } + +/* ── App Layout ── */ +.app-layout { + display: flex; + height: 100vh; + width: 100vw; + overflow: hidden; +} + +/* ── Sidebar ── */ +.sidebar { + width: var(--sidebar-width); + min-width: var(--sidebar-width); + background-color: var(--bg-sidebar); + border-right: 1px solid var(--border-subtle); + display: flex; + flex-direction: column; + height: 100%; +} + +.brand { + padding: 16px 18px 14px; + display: flex; + align-items: center; + gap: 12px; + border-bottom: 1px solid var(--border-subtle); +} + +.brand-logo { + font-size: 22px; + color: var(--accent); +} + +.brand-title { + display: block; + font-family: var(--font-title); + font-weight: 700; + font-size: 15px; + letter-spacing: 1px; + color: var(--text-accent); +} + +.brand-subtitle { + display: block; + font-size: 10px; + color: var(--text-muted); + letter-spacing: 0.5px; +} + +.nav-menu { + flex: 1; + padding: 12px 10px; + display: flex; + flex-direction: column; + gap: 3px; + overflow-y: auto; +} + +.nav-item { + display: flex; + align-items: center; + gap: 10px; + padding: 9px 12px; + background: transparent; + border: 1px solid transparent; + border-radius: var(--radius-sm); + color: var(--text-secondary); + font-family: var(--font-ui); + font-size: 13px; + font-weight: 500; + cursor: pointer; + text-align: left; + transition: all 0.15s ease; +} + +.nav-item:hover { + background-color: var(--surface-hover); + color: var(--text-primary); +} + +.nav-item.active { + background-color: var(--surface-selected); + color: var(--text-accent); + border-color: var(--border-accent); +} + +.nav-icon { + font-size: 15px; + display: inline-flex; + width: 18px; +} + +.nav-label { + flex: 1; +} + +.nav-badge { + background-color: var(--surface-muted); + color: var(--text-muted); + font-size: 10px; + padding: 2px 6px; + border-radius: 10px; + font-weight: 600; +} + +.sidebar-footer { + padding: 12px 16px; + border-top: 1px solid var(--border-subtle); + display: flex; + flex-direction: column; + gap: 6px; +} + +.source-indicator { + display: flex; + align-items: center; + gap: 8px; + font-size: 11px; + color: var(--text-secondary); +} + +.status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background-color: var(--status-disabled); + display: inline-block; +} + +.status-dot.healthy { background-color: var(--status-healthy); box-shadow: 0 0 6px var(--status-healthy); } +.status-dot.warning { background-color: var(--status-warning); } +.status-dot.error { background-color: var(--status-error); } + +.version-tag { + font-size: 10px; + color: var(--text-muted); + font-family: var(--font-mono); +} + +/* ── Main Area ── */ +.main-wrapper { + flex: 1; + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; + background-color: var(--bg-base); +} + +/* ── Top Header ── */ +.top-header { + height: var(--header-height); + background-color: var(--bg-header); + border-bottom: 1px solid var(--border); + padding: 0 24px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; +} + +.header-left { + display: flex; + align-items: center; + gap: 16px; +} + +.header-title { + font-size: 18px; + font-weight: 700; + color: var(--text-primary); +} + +.header-readiness-badge { + display: inline-flex; + align-items: center; + gap: 6px; + background-color: var(--surface-muted); + border: 1px solid var(--border-subtle); + padding: 4px 10px; + border-radius: var(--radius-sm); + font-size: 11px; + font-weight: 600; +} + +.header-actions { + display: flex; + align-items: center; + gap: 10px; +} + +/* ── Buttons ── */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + padding: 7px 14px; + border-radius: var(--radius-sm); + font-family: var(--font-ui); + font-size: 12px; + font-weight: 600; + cursor: pointer; + border: 1px solid transparent; + transition: all 0.15s ease; +} + +.btn-primary { + background-color: var(--accent); + color: #061916; + border-color: var(--border-accent); +} + +.btn-primary:hover { + background-color: var(--accent-hover); +} + +.btn-secondary { + background-color: var(--surface); + color: var(--text-primary); + border-color: var(--border); +} + +.btn-secondary:hover { + background-color: var(--surface-hover); + border-color: var(--border-hover); +} + +.btn-ghost { + background: transparent; + color: var(--text-secondary); +} + +.btn-ghost:hover { + background-color: var(--surface-hover); + color: var(--text-primary); +} + +.btn-sm { + padding: 4px 8px; + font-size: 11px; +} + +.btn:disabled { + opacity: 0.45; + cursor: not-allowed; +} + +/* ── Content Scroll Area ── */ +.content-scroll { + flex: 1; + overflow-y: auto; + padding: 20px 24px; +} + +.view-pane { + display: none; +} + +.view-pane.active { + display: block; +} + +.view-header-note { + background-color: var(--surface-muted); + border: 1px solid var(--border-subtle); + padding: 10px 14px; + border-radius: var(--radius-sm); + color: var(--text-secondary); + font-size: 12px; + margin-bottom: 16px; +} + +/* ── Toolbar & Filters ── */ +.toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin-bottom: 16px; + flex-wrap: wrap; +} + +.search-box { + display: flex; + align-items: center; + gap: 8px; + background-color: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + padding: 6px 12px; + width: 340px; +} + +.search-icon { + font-size: 13px; + color: var(--text-muted); +} + +.search-box input { + background: transparent; + border: none; + color: var(--text-primary); + font-family: var(--font-ui); + font-size: 12px; + width: 100%; + outline: none; +} + +.search-box input::placeholder { + color: var(--text-muted); +} + +.filters-row { + display: flex; + align-items: center; + gap: 10px; +} + +.select-filter { + background-color: var(--surface); + border: 1px solid var(--border); + color: var(--text-primary); + font-family: var(--font-ui); + font-size: 12px; + padding: 6px 10px; + border-radius: var(--radius-sm); + outline: none; + cursor: pointer; +} + +.select-filter:focus { + border-color: var(--border-accent); +} + +.toolbar-stats { + font-size: 11px; + color: var(--text-muted); +} + +/* ── Provider Group & Account Cards Grid ── */ +.provider-group { + margin-bottom: 24px; +} + +.provider-group-header { + display: flex; + align-items: center; + justify-content: space-between; + background-color: var(--surface-muted); + border: 1px solid var(--border-subtle); + padding: 8px 14px; + border-radius: var(--radius-sm); + margin-bottom: 10px; +} + +.provider-group-title { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + font-weight: 700; + color: var(--text-primary); +} + +.provider-group-count { + font-size: 11px; + color: var(--text-muted); +} + +.accounts-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); + gap: 10px; +} + +/* ── Compact Account Card (164px Fixed Height) ── */ +.account-card { + background-color: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-md); + height: 164px; + padding: 10px 14px; + display: flex; + flex-direction: column; + justify-content: space-between; + cursor: pointer; + transition: all 0.15s ease; + position: relative; + overflow: hidden; +} + +.account-card:hover { + background-color: var(--surface-hover); + border-color: var(--border-hover); + transform: translateY(-1px); +} + +.account-card.main-account { + border-color: var(--border-accent); +} + +.account-card-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} + +.account-provider-tag { + display: flex; + align-items: center; + gap: 6px; + font-size: 11px; + font-weight: 600; +} + +.account-badges { + display: flex; + align-items: center; + gap: 6px; +} + +.badge { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 6px; + border-radius: var(--radius-sm); + font-size: 10px; + font-weight: 700; +} + +.badge-plan { + background-color: var(--accent-dim); + color: var(--text-accent); + border: 1px solid var(--border-accent); +} + +.badge-status { + background-color: var(--surface-muted); + color: var(--text-secondary); +} + +.badge-status.healthy { color: var(--status-healthy); } +.badge-status.warning { color: var(--status-warning); } +.badge-status.quota_exhausted { color: var(--status-error); } +.badge-status.auth_required { color: var(--status-warning); } +.badge-status.disabled { color: var(--status-disabled); } + +.account-identity-row { + margin: 2px 0; +} + +.account-email { + font-size: 13px; + font-weight: 700; + color: var(--text-primary); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.account-meta { + font-size: 11px; + color: var(--text-muted); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* ── Quota Cells Grid (Up to 4 pools) ── */ +.account-quota-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4px 10px; + margin-top: 4px; +} + +.account-quota-grid.single-cell { + grid-template-columns: 1fr; +} + +.quota-cell { + background-color: var(--surface-muted); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-sm); + padding: 4px 6px; + display: flex; + flex-direction: column; + justify-content: center; +} + +.quota-cell-top { + display: flex; + align-items: center; + justify-content: space-between; + font-size: 10px; +} + +.quota-cell-title { + color: var(--text-secondary); + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100px; +} + +.quota-cell-value { + font-family: var(--font-mono); + font-weight: 700; +} + +.quota-bar-track { + height: 4px; + background-color: rgba(255, 255, 255, 0.08); + border-radius: 2px; + overflow: hidden; + margin: 3px 0 2px; +} + +.quota-bar-fill { + height: 100%; + border-radius: 2px; + transition: width 0.3s ease; +} + +.quota-cell-reset { + font-size: 9px; + color: var(--text-muted); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* ── Overview KPI Grid ── */ +.overview-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 14px; + margin-bottom: 20px; +} + +.kpi-card { + background-color: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-md); + padding: 16px; +} + +.kpi-label { + font-size: 11px; + color: var(--text-muted); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + margin-bottom: 4px; +} + +.kpi-value { + font-size: 24px; + font-weight: 700; + line-height: 1.2; +} + +.kpi-sub { + font-size: 11px; + color: var(--text-secondary); + margin-top: 4px; +} + +/* ── Section Cards ── */ +.section-card { + background-color: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-md); + padding: 18px 20px; + margin-bottom: 20px; +} + +.section-card-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 14px; +} + +.section-card-title { + font-size: 15px; + font-weight: 700; + color: var(--text-primary); +} + +.section-card-subtitle { + font-size: 12px; + color: var(--text-muted); + margin-top: 2px; +} + +/* ── Route Diagram ── */ +.route-diagram-container { + display: flex; + gap: 16px; + overflow-x: auto; + padding: 10px 0; +} + +.diagram-column { + flex: 1; + min-width: 220px; + background-color: var(--surface-muted); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-sm); + padding: 12px; +} + +.diagram-column-header { + font-size: 12px; + font-weight: 700; + color: var(--text-accent); + margin-bottom: 10px; + border-bottom: 1px solid var(--border-subtle); + padding-bottom: 6px; +} + +.diagram-node { + background-color: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + padding: 8px 10px; + margin-bottom: 8px; +} + +.diagram-node.active { + border-color: var(--status-healthy); + box-shadow: 0 0 8px rgba(114, 201, 67, 0.2); +} + +/* ── Providers Grid ── */ +.providers-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + gap: 12px; +} + +.provider-summary-card { + background-color: var(--surface-muted); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-sm); + padding: 14px; +} + +.provider-summary-title { + font-size: 14px; + font-weight: 700; + color: var(--text-primary); + margin-bottom: 4px; +} + +.provider-summary-stats { + font-size: 12px; + color: var(--text-secondary); + margin-bottom: 8px; +} + +.provider-models-tag { + font-family: var(--font-mono); + font-size: 11px; + color: var(--text-muted); + background-color: var(--bg-base); + padding: 6px 8px; + border-radius: var(--radius-sm); + word-break: break-all; +} + +/* ── Routing Pipelines List ── */ +.routing-pipelines-list { + display: flex; + flex-direction: column; + gap: 12px; +} + +.pipeline-card { + background-color: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-md); + padding: 14px 18px; +} + +.pipeline-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 12px; +} + +.pipeline-title { + font-size: 14px; + font-weight: 700; + color: var(--text-primary); +} + +.pipeline-chain-flow { + display: flex; + align-items: center; + gap: 10px; + flex-wrap: wrap; +} + +.pipeline-node-chip { + background-color: var(--surface-muted); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + padding: 6px 10px; + display: flex; + flex-direction: column; + gap: 2px; + min-width: 140px; +} + +.pipeline-node-chip.active { + border-color: var(--status-healthy); + background-color: var(--surface-hover); +} + +.pipeline-arrow { + color: var(--accent); + font-weight: bold; +} + +/* ── Team Cards Grid ── */ +.team-cards-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); + gap: 12px; +} + +.team-agent-card { + background-color: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-md); + padding: 14px; +} + +.team-agent-card.orchestrator { + border-color: var(--border-accent); +} + +/* ── Settings Card ── */ +.settings-card { + background-color: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-md); + padding: 20px; + max-width: 800px; +} + +.settings-group-title { + font-size: 16px; + font-weight: 700; + color: var(--text-primary); + margin-bottom: 16px; + border-bottom: 1px solid var(--border-subtle); + padding-bottom: 8px; +} + +.setting-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 0; + border-bottom: 1px solid var(--border-subtle); + gap: 16px; +} + +.setting-label { + font-size: 13px; + font-weight: 600; + color: var(--text-primary); +} + +.setting-desc { + font-size: 11px; + color: var(--text-muted); +} + +.input-text { + background-color: var(--surface-muted); + border: 1px solid var(--border); + color: var(--text-primary); + font-family: var(--font-ui); + font-size: 12px; + padding: 6px 10px; + border-radius: var(--radius-sm); + outline: none; + width: 260px; +} + +.input-text:focus { + border-color: var(--border-accent); +} + +.settings-actions { + margin-top: 20px; + display: flex; + justify-content: flex-end; +} + +/* ── Modal Layer ── */ +.modal-backdrop { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: var(--bg-modal-backdrop); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + backdrop-filter: blur(4px); +} + +.modal-backdrop.hidden { + display: none !important; +} + +.modal-card { + background-color: var(--surface); + border: 1px solid var(--border-accent); + border-radius: var(--radius-lg); + width: 680px; + max-width: 90vw; + max-height: 85vh; + display: flex; + flex-direction: column; + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6); + animation: modalAppear 0.2s ease-out; +} + +@keyframes modalAppear { + from { opacity: 0; transform: scale(0.96); } + to { opacity: 1; transform: scale(1); } +} + +.modal-header { + padding: 16px 20px; + border-bottom: 1px solid var(--border); + display: flex; + align-items: center; + justify-content: space-between; +} + +.modal-title { + font-size: 16px; + font-weight: 700; + color: var(--text-primary); +} + +.modal-close { + background: transparent; + border: none; + color: var(--text-muted); + font-size: 16px; + cursor: pointer; +} + +.modal-close:hover { + color: var(--text-primary); +} + +.modal-body { + padding: 20px; + overflow-y: auto; + flex: 1; +} + +.modal-footer { + padding: 14px 20px; + border-top: 1px solid var(--border); + display: flex; + align-items: center; + justify-content: flex-end; + gap: 10px; +} + +.modal-feedback { + padding: 8px 12px; + border-radius: var(--radius-sm); + font-size: 12px; + margin-bottom: 14px; +} + +.modal-feedback.error { + background-color: rgba(228, 92, 79, 0.15); + border: 1px solid var(--status-error); + color: #FFD8D2; +} + +.modal-feedback.success { + background-color: rgba(114, 201, 67, 0.15); + border: 1px solid var(--status-healthy); + color: #E2F8D5; +} + +.modal-feedback.info { + background-color: rgba(76, 141, 216, 0.15); + border: 1px solid var(--status-info); + color: #D2E5FA; +} + +/* ── Toast Notifications ── */ +.toast-container { + position: fixed; + bottom: 24px; + right: 24px; + display: flex; + flex-direction: column; + gap: 8px; + z-index: 10000; + pointer-events: none; +} + +.toast { + background-color: var(--surface-hover); + border: 1px solid var(--border); + color: var(--text-primary); + padding: 10px 16px; + border-radius: var(--radius-sm); + font-size: 12px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4); + animation: toastSlideIn 0.2s ease-out; + pointer-events: auto; +} + +.toast.success { border-color: var(--status-healthy); } +.toast.error { border-color: var(--status-error); } +.toast.warning { border-color: var(--status-warning); } + +@keyframes toastSlideIn { + from { opacity: 0; transform: translateY(10px); } + to { opacity: 1; transform: translateY(0); } +} + +/* ── Scrollbars ── */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: var(--surface-muted); +} + +::-webkit-scrollbar-thumb { + background: var(--border); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--border-hover); +} diff --git a/tests/test_web_client_contract.py b/tests/test_web_client_contract.py new file mode 100644 index 0000000..67fb75c --- /dev/null +++ b/tests/test_web_client_contract.py @@ -0,0 +1,105 @@ +""" +Hermes Hub — Web Client Invariants & Contract Verification Suite +Tests adherence to docs/web-api/CONTRACT.md and A16 requirements. +""" + +from __future__ import annotations + +import json +from pathlib import Path +import pytest + +REPO_ROOT = Path(__file__).resolve().parent.parent +STATIC_DIR = REPO_ROOT / "src" / "antigravity_provider" / "router" / "web" / "static" +SNAPSHOT_EXAMPLE = REPO_ROOT / "docs" / "web-api" / "snapshot.example.json" + + +def test_static_assets_exist_and_no_build_dependencies(): + """Verify that index.html, style.css, app.js exist and have zero build / npm dependencies.""" + index_html = STATIC_DIR / "index.html" + style_css = STATIC_DIR / "style.css" + app_js = STATIC_DIR / "app.js" + + assert index_html.is_file(), f"Missing {index_html}" + assert style_css.is_file(), f"Missing {style_css}" + assert app_js.is_file(), f"Missing {app_js}" + + html_content = index_html.read_text(encoding="utf-8") + # No React, Webpack, Vite, npm or external bundle references + assert "react" not in html_content.lower() + assert "webpack" not in html_content.lower() + assert "vite" not in html_content.lower() + assert "" in html_content + assert "" in html_content + + +def test_snapshot_fixture_validity_and_completeness(): + """Verify snapshot.example.json conforms to HubSnapshot contract.""" + assert SNAPSHOT_EXAMPLE.is_file(), f"Missing {SNAPSHOT_EXAMPLE}" + with open(SNAPSHOT_EXAMPLE, "r", encoding="utf-8") as f: + data = json.load(f) + + # Top level keys + required_keys = [ + "generation", "seq", "timestamp", "profiles_by_provider", + "all_profiles", "readiness", "agents", "providers", + "routing", "quotas", "metrics", "is_stale" + ] + for key in required_keys: + assert key in data, f"Missing required top-level key: {key}" + + # Verify monotonic seq structure + assert isinstance(data["seq"], int) + assert data["seq"] >= 1 + + # Verify profiles count + assert len(data["all_profiles"]) >= 16, "Must contain real profiles fixture" + + # Zero leaked tokens / secrets in snapshot + raw_text = json.dumps(data) + forbidden_tokens = ["access_token", "refresh_token", "api_key", "client_secret"] + for tok in forbidden_tokens: + # Key shouldn't exist as actual secret payload + assert f'"{tok}": "sk-' not in raw_text + assert f'"{tok}": "gho_' not in raw_text + + +def test_monotonic_seq_logic_in_app_js(): + """Verify app.js contains strict monotonic seq checking to prevent stale response overwrites.""" + app_js_content = (STATIC_DIR / "app.js").read_text(encoding="utf-8") + assert "lastAppliedSeq" in app_js_content + assert "snapshot.seq < lastAppliedSeq" in app_js_content + assert "Stale snapshot" in app_js_content + + +def test_account_card_compact_height_and_quota_rendering(): + """Verify CSS has 164px compact fixed height and app.js renders multi-pool quota cells.""" + style_css = (STATIC_DIR / "style.css").read_text(encoding="utf-8") + assert "164px" in style_css + assert ".account-card" in style_css + assert "overflow: hidden" in style_css + + app_js = (STATIC_DIR / "app.js").read_text(encoding="utf-8") + assert "renderQuotaCell" in app_js + assert "remaining_percent" in app_js + assert "unavailable_reason" in app_js + assert "Н/Д" in app_js + + +def test_headless_server_auth_matrix(): + """Verify headless server honesty in Add Account Wizard (Grok/Codex device-code vs Antigravity/Claude redirect warning).""" + app_js = (STATIC_DIR / "app.js").read_text(encoding="utf-8") + assert "Device Code OAuth" in app_js + assert "https://x.ai/device" in app_js + assert "https://auth.openai.com/device" in app_js + assert "Headless Сервер" in app_js + assert "ssh -L 8085:localhost:8085" in app_js + + +def test_actions_contract_handling(): + """Verify POST /api/action handles ok: false as valid 200 business response and displays feedback in-place.""" + app_js = (STATIC_DIR / "app.js").read_text(encoding="utf-8") + assert "POST" in app_js + assert "/api/action" in app_js + assert "executeAction" in app_js + assert "modal-feedback-area" in app_js