From 0943cdf5f330d9b872242f25d35c21d85c35d4d8 Mon Sep 17 00:00:00 2001 From: Anais Saraiva Date: Mon, 21 Sep 2026 22:17:05 +0200 Subject: [PATCH] fixes --- README.md | 1 + docs/OPERATIONS.md | 15 ++++++++ frontend/src/lib/i18n.ts | 78 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/README.md b/README.md index da405c4..59a903a 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ from the **Accounts** panel (each gets a one-time access key to hand over). | POST | `/api/conversations/:id/archive`, `/api/conversations/:id/unarchive` | owner | archive (read-only) / restore to the list | | GET | `/api/share/:publicId` | **public** | read-only shared chat JSON | | GET | `/api/models` | Bearer | `[{id: "driver:model", …}]` across enabled drivers | +| GET/PATCH | `/api/admin/model-policy` | admin | per-model kill-switch + hourly/daily limits (users filtered, enforced in chat) | | POST | `/api/chat` | Bearer | `{model, messages, conversationId?, stream?}` → JSON or SSE | `POST /api/chat` with `conversationId` persists the user message + assistant diff --git a/docs/OPERATIONS.md b/docs/OPERATIONS.md index e7cb28c..62a321d 100644 --- a/docs/OPERATIONS.md +++ b/docs/OPERATIONS.md @@ -74,6 +74,21 @@ connectivity tester: `GET /api/admin/mail`, `POST /api/admin/mail/verify`, - Flags live in the `settings` SQLite table, edited via `GET/PATCH /api/admin/settings` (admin Bearer only). +## Model access policy (kill-switch + rate limits) + +The Admin Center **Models** tab lists every model across enabled drivers +(grouped, Ollama library moved there too). Per model id (`"driver:model"`): +an **Enabled** switch and **hourly / daily** per-user request caps +(0 = unlimited, admins always bypass). Policy lives in the `settings` table +(`model_policy` JSON blob, default entries pruned); usage counters in +`model_usage` (fixed UTC hour/day windows, old buckets pruned on write). + +- Disabled models vanish from `GET /api/models` for users (admins still see + everything) and `POST /api/chat` rejects them (403) — attempts count + toward limits even when generation later fails; over-limit answers 429. +- Routes: `GET /api/admin/model-policy[?refresh=1]`, + `PATCH /api/admin/model-policy` (`{model, enabled?, hourly?, daily?}`). + ## Access-request wishlist (registration approval queue) When public registration is off, visitors can still reserve a username via diff --git a/frontend/src/lib/i18n.ts b/frontend/src/lib/i18n.ts index 071e185..f003500 100644 --- a/frontend/src/lib/i18n.ts +++ b/frontend/src/lib/i18n.ts @@ -272,6 +272,19 @@ const en = { "center.tabAccounts": "Accounts", "center.tabFeatures": "Features", "center.tabMail": "Mail", + "center.tabModels": "Models", + "models.title": "Models", + "models.desc": "Enable or limit each model. Disabled models disappear from the picker; limits apply per user (admins bypass them).", + "models.refresh": "Refresh", + "models.refreshAria": "Refresh models", + "models.enabled": "Enabled", + "models.hourly": "per hour", + "models.daily": "per day", + "models.unlimited": "Unlimited", + "models.ollamaTitle": "Ollama library", + "models.ollamaDesc": "Pull or remove local models.", + "models.empty": "No models available.", + "models.saveFailed": "Could not save", "center.locked": "Admins only", "center.lockedSub": "Log in with the admin account to open the Admin Center.", "center.regTitle": "Public registration", @@ -780,6 +793,19 @@ const es: Dict = { "center.tabAccounts": "Cuentas", "center.tabFeatures": "Funciones", "center.tabMail": "Correo", + "center.tabModels": "Modelos", + "models.title": "Modelos", + "models.desc": "Activa o limita cada modelo. Los modelos desactivados desaparecen del selector; los límites se aplican por usuario (los admins no tienen límite).", + "models.refresh": "Actualizar", + "models.refreshAria": "Actualizar modelos", + "models.enabled": "Activado", + "models.hourly": "por hora", + "models.daily": "por día", + "models.unlimited": "Ilimitado", + "models.ollamaTitle": "Biblioteca Ollama", + "models.ollamaDesc": "Descargar o eliminar modelos locales.", + "models.empty": "No hay modelos disponibles.", + "models.saveFailed": "No se pudo guardar", "center.locked": "Solo admins", "center.lockedSub": "Inicia sesión como admin para abrir el Centro de admin.", "center.regTitle": "Registro público", @@ -1282,6 +1308,19 @@ const fr: Dict = { "center.tabAccounts": "Comptes", "center.tabFeatures": "Fonctions", "center.tabMail": "Mail", + "center.tabModels": "Modèles", + "models.title": "Modèles", + "models.desc": "Activez ou limitez chaque modèle. Les modèles désactivés disparaissent du sélecteur ; les limites s'appliquent par utilisateur (les admins ne sont pas limités).", + "models.refresh": "Actualiser", + "models.refreshAria": "Actualiser les modèles", + "models.enabled": "Activé", + "models.hourly": "par heure", + "models.daily": "par jour", + "models.unlimited": "Illimité", + "models.ollamaTitle": "Bibliothèque Ollama", + "models.ollamaDesc": "Télécharger ou supprimer des modèles locaux.", + "models.empty": "Aucun modèle disponible.", + "models.saveFailed": "Enregistrement impossible", "center.locked": "Admins uniquement", "center.lockedSub": "Connectez-vous en admin pour ouvrir le Centre admin.", "center.regTitle": "Inscription publique", @@ -1775,6 +1814,19 @@ const ru: Dict = { "center.tabAccounts": "Аккаунты", "center.tabFeatures": "Функции", "center.tabMail": "Почта", + "center.tabModels": "Модели", + "models.title": "Модели", + "models.desc": "Включайте или ограничивайте каждую модель. Отключённые модели исчезают из выбора; лимиты действуют на пользователя (админов не касаются).", + "models.refresh": "Обновить", + "models.refreshAria": "Обновить модели", + "models.enabled": "Включена", + "models.hourly": "в час", + "models.daily": "в день", + "models.unlimited": "Без лимита", + "models.ollamaTitle": "Библиотека Ollama", + "models.ollamaDesc": "Скачивание и удаление локальных моделей.", + "models.empty": "Нет доступных моделей.", + "models.saveFailed": "Не удалось сохранить", "center.locked": "Только админы", "center.lockedSub": "Войдите как админ, чтобы открыть центр.", "center.regTitle": "Открытая регистрация", @@ -2266,6 +2318,19 @@ const it: Dict = { "center.tabAccounts": "Account", "center.tabFeatures": "Funzioni", "center.tabMail": "Mail", + "center.tabModels": "Modelli", + "models.title": "Modelli", + "models.desc": "Abilita o limita ogni modello. I modelli disabilitati spariscono dal selettore; i limiti valgono per utente (gli admin sono esenti).", + "models.refresh": "Aggiorna", + "models.refreshAria": "Aggiorna modelli", + "models.enabled": "Abilitato", + "models.hourly": "all'ora", + "models.daily": "al giorno", + "models.unlimited": "Illimitato", + "models.ollamaTitle": "Libreria Ollama", + "models.ollamaDesc": "Scarica o rimuovi modelli locali.", + "models.empty": "Nessun modello disponibile.", + "models.saveFailed": "Salvataggio fallito", "center.locked": "Solo admin", "center.lockedSub": "Accedi come admin per aprire il Centro.", "center.regTitle": "Registrazione pubblica", @@ -2755,6 +2820,19 @@ const pt: Dict = { "center.tabAccounts": "Contas", "center.tabFeatures": "Funções", "center.tabMail": "Mail", + "center.tabModels": "Modelos", + "models.title": "Modelos", + "models.desc": "Ative ou limite cada modelo. Os desativados somem do seletor; os limites valem por utilizador (admins isentos).", + "models.refresh": "Atualizar", + "models.refreshAria": "Atualizar modelos", + "models.enabled": "Ativo", + "models.hourly": "por hora", + "models.daily": "por dia", + "models.unlimited": "Ilimitado", + "models.ollamaTitle": "Biblioteca Ollama", + "models.ollamaDesc": "Baixar ou remover modelos locais.", + "models.empty": "Nenhum modelo disponível.", + "models.saveFailed": "Falha ao guardar", "center.locked": "Só admins", "center.lockedSub": "Entra como admin para abrir o Centro.", "center.regTitle": "Registo público",