feat: ops & UX batch — jobs survive restarts, logs/system in the console, media queue, gallery, chat, exact stream tokens

Fifteen changes aimed at the first day of real use:

- Import and media jobs persist to <data>/jobs-*.json and reload on start
  (running ones settle as errors); the Register button no longer vanishes
  because the gateway restarted.
- Docker ships the cortiq binary (built in the builder stage) — local .cmf
  chat models and image/video generation now work in containers, where
  auto-install never could (no cargo in the runtime image). libvulkan1 added
  for optional GPU offload.
- Open admin console on 0.0.0.0 without a token now warns in the log and
  shows a dismissible banner — the VPS footgun is at least labeled.
- "Restart gateway" button in Settings: stops managed model servers, spawns
  a fresh copy (bind retried while the port frees), Docker relies on the
  container restart policy instead.
- Dashboard "System" panel: CPU sparkline + load, RAM (with the gateway's
  own RSS), free disk at the models dir — sampled by sysinfo every 2 s.
- Featured model cards warn "not enough disk" / "may not fit in RAM" before
  the download, from the same live snapshot.
- Log viewer in the sidebar: a 500-line in-memory ring fed by a second
  ANSI-free tracing layer; filter, level, pause, copy.
- Update check: crates.io polled twice a day, the console shows an
  "update available" notice.
- Media generations queue up (with position shown) instead of being
  rejected; progress gained an honest ETA from measured throughput.
- Generation gallery under the image/video tabs: lazy PPM thumbnails,
  click to reopen with seed/steps, delete.
- Playground chat is a real dialogue now: history is resent, bubbles,
  Clear, Cmd/Ctrl+Enter.
- "Connect your app" snippets (curl / Python / JS) on the keys page, with
  the real key inlined right after creation.
- One-click benchmark on the Models page via `cortiq bench --json`.
- Config export now downloads the actual gateway.toml (comments intact);
  import accepts TOML (validated, hot-reloaded) and the legacy JSON.
- Streaming token counts are exact when the model server provides usage
  (cortiq-server patch, shipped separately); the gateway fallback now
  counts content chunks (1/token on cortiq) instead of chars/4.

Wizard's Finish lands on the Playground. 37 new strings in all 7 languages.
This commit is contained in:
infosave2007
2026-08-07 17:07:48 +03:00
parent a77beeabab
commit 15de36be3b
32 changed files with 1876 additions and 143 deletions
+39
View File
@@ -506,4 +506,43 @@ export default {
"pg.noMediaModels": "Aún no hay un modelo {kind} local. Descarga uno (p. ej. de la colección infosave) en Importar:",
"pg.tokSpeed": "Velocidad",
"pg.ttft": "Primer token",
// ops: logs, system, notices, gallery, chat, snippets, bench
"nav.logs": "Registros",
"logs.subtitle": "Registro reciente de la pasarela — lo que mostraría la terminal.",
"logs.filterPlaceholder": "filtrar…",
"logs.pause": "Pausa",
"logs.resume": "Reanudar",
"logs.empty": "Nada coincide.",
"notice.openAdmin": "La consola está abierta sin token y accesible desde otras máquinas. Configura un token si esta máquina no es privada.",
"notice.update": "Actualización disponible: v{v}.",
"dash.sys.title": "Sistema",
"dash.sys.cores": "núcleos",
"dash.sys.disk": "Disco (modelos)",
"dash.sys.free": "libre",
"dash.sys.gateway": "pasarela",
"fit.disk": "no hay espacio suficiente",
"fit.diskTitle": "La descarga supera el espacio libre del disco de modelos.",
"fit.ram": "puede no caber en RAM",
"fit.ramTitle": "El modelo se acerca o supera la RAM de esta máquina — puede que no funcione.",
"pg.eta": "restante",
"pg.min": "min",
"pg.queued": "En cola — posición {n}. Arranca en cuanto termine la generación actual.",
"pg.gallery": "Generaciones recientes",
"pg.galDeleteConfirm": "¿Eliminar esta generación y sus archivos?",
"pg.clearChat": "Limpiar",
"keys.snip.title": "Conecta tu aplicación",
"keys.snip.hint": "Pega uno de estos ejemplos en tu proyecto — solo hay que sustituir el marcador de la clave.",
"keys.snip.withKey": "Los ejemplos de abajo ya incluyen la clave que acabas de crear.",
"keys.snip.openMode": "No hay claves API configuradas — la pasarela acepta cualquier valor.",
"keys.snip.keyPh": "tu clave API",
"settings.restart": "Reiniciar la pasarela",
"settings.restartConfirm": "¿Reiniciar la pasarela? Las peticiones en curso se cortarán; los servidores de modelos locales también se reinician.",
"settings.restarting": "Reiniciando — la página se recargará cuando la pasarela vuelva…",
"bench.title": "Velocidad de modelos locales",
"bench.hint": "Ejecuta `cortiq bench` en esta máquina — tok/s reales, un modelo a la vez.",
"bench.run": "Medir",
"bench.running": "midiendo…",
"bench.failed": "falló",
"bench.none": "Aún no hay modelos de chat .cmf locales.",
};