Full audit of the semantic cache against a live instance (mock embedder,
identical requests): the mechanism works — miss at 3.1s, then hits at 2ms
with entries/hits/saved-$ counting. Two honest gaps fixed:
- the threshold round-tripped through f32 and rendered as
0.9200000166893005 in both the TOML and the settings input — the config
field is f64 now (writes exactly what you typed) and the input rounds
legacy values to 2 decimals;
- the card now shows proof of life (entries / hits / hit-rate / saved $)
and, when the cache is enabled with NO embedding model available, a
warning that it is silently doing nothing and how to fix it — previously
that state looked identical to a working cache.
Also audited in the same pass, no changes needed: Prometheus /metrics
(toggle on/off applies live, 404 when off), and all 7 protocol switches
(each gates its endpoint instantly both ways). 4 strings ×7 languages.
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.
- New GET /admin/api/cmf/files lists the .cmf files (and tensor-dir .cmf) under
models_dir, with sizes.
- Settings → Local models: the per-row model field is now a dropdown of those
files instead of a hand-typed path, and auto-fills the id from the filename.
- The gateway can now run several local .cmf models at once: a [[cmf.servers]]
list, one supervised `cortiq serve` per entry on its own port, each registered
in the pool and independently routable/pinnable. The single legacy
local_model/local_port still works (back-compat via effective_servers()).
- Settings → Local models is now a rows editor (id · path · port + check · threads
· GPU) with add/remove and per-server serving status.
- Deleting a managed model stops just its server and removes its file — unless
another model still points at the same file (shared-file guard).
- Settings: "?" help tooltips on every option; router key auto-probes the
connection right after saving (no more hanging "unavailable")
- Local models card reworked into 3 clear steps (install cortiq → add model →
run locally); removed the hand-entered .cmf path / pool-id fields — models
are added via the Import tab and the managed server registers them
- Fresh install ships an EMPTY model pool; the local .cmf is auto-registered by
the managed CMF server, so it needs no static [[models]] entry
- New: port-availability check — GET /admin/api/cmf/port + "Check port" button
with next-free-port suggestion. bind()+connect() probe so Docker-proxied /
dual-stack ports (e.g. 8081) are correctly detected as occupied
- /admin/api/cmf now reports the serving model + port; card shows "▶ serving …"
- On-demand runtime install: POST /admin/api/cmf/install
Expose the two speed knobs in the /admin Settings panel instead of TOML-only:
- [cmf].gpu (new) -> exports CMF_GPU=1 to the managed cortiq serve (Metal/wgpu).
On Apple Silicon decode is memory-bandwidth bound so this is ~neutral for
generation (helps prefill); off by default.
- [cmf].threads (added earlier) now has a UI number input.
- config.rs: CmfCfg.gpu bool (serde default false).
- cmf_runtime.rs: spawn_serve sets CMF_GPU=1 when gpu is on.
- admin/mod.rs: put_settings flags needs_restart on threads/gpu change (the
server is spawned once at startup with those env vars).
- settings.js: threads input + gpu checkbox + save payload + speed hint.
- i18n en/ru: threads/gpu/speedNote keys (other locales fall back to en, as the
whole cmf section already does there).
Run models in the CMF (.cmf) format locally, via the native `cortiq`
CLI from crates.io — no Python and no external model server.
- cmf_runtime: install/update `cortiq-cli` from crates.io, spawn and
health-check `cortiq serve` as a managed local backend.
- import: model-import jobs shell out to the native `cortiq convert`
(HF repo -> .cmf, quant mapped Q8_2F->q8_2f / Q8_ROW->q8 / Q4->q4);
the Python converter is used only for advanced/exotic options.
- pipeline: local-first routing — serve from the local CMF model when
the router is disabled/unreachable, with a "local only" hard switch.
- registry/state: register the local CMF server as an OpenAI provider
and track local candidates.
- config: data-dir resolution + CmfCfg (auto-install/update, managed
server, host/port/model) and relaxed validation for the managed model.
- admin + settings UI (en/ru): "Local models (CMF)" settings card.
- cache.rs: cosine-similarity store (threshold, TTL, ring buffer), partitioned by
routing signature; tracks hit rate and model cost saved
- pipeline: embed routing text, look up before the model call (route_source=cache on
hit), insert successful responses; stats record cache hits
- config [cache] + admin settings card; dashboard shows hit-rate and savings
- embedding model resolved from the pool (or first kind="embedding")