3847d8b9fbdbf90ef3d46242cd8ca659a1f3cafb
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
39da1d4a97 |
feat(homepage): recategorise on "do I open this?", collapse the API groups
The board mixed tools with endpoints. A vLLM seat whose href is a /docs page
sat in the same band as ComfyUI; the MQTT broker and the RustDesk relay, which
have no page at all, sat in Apps; and `Service Networking` was thirteen members
spanning three AdGuards, five Dockges, two Traefiks and four headless agents.
Every group is now one of two kinds and they never mix. TOOLS are expanded and
sit at the top of their tab. ENDPOINTS — an API, a broker, a background agent,
an href that is /docs or /ping or nothing — carry `initiallyCollapsed: true`
and sit at the bottom. Collapsed is not hidden: the eyebrow and its rule still
render, so the tab still says the thing exists and one click expands it.
A second rule fell out of the same pass and now shapes the group boundaries: a
group's members should all carry a widget or none should. A stat strip makes a
card ~50px taller, so one widget card in a row of plain ones opens a void under
the plain ones. That is why AdGuard and Traefik get their own groups rather
than sharing one with Dockge, and it is most of why the old Service Networking
band looked broken. AdGuard (ANA) was the last short card in its row and now
carries the same query/blocked/latency strip as its two siblings — one
infra-ops AdGuard login authenticates against all three instances, verified
against each; it lives in that stack's .env on the host and is vaulted.
The sixteen GPU-backed model seats were deliberately NOT relabelled.
`homepage.group` is read at container creation, so clearer names for
`AI - Inference` and friends would have cost a recreate on six vLLM seats, four
eval seats and four TTS engines — multi-minute model reloads on endpoints peers
reach through the gateway. Order plus `initiallyCollapsed` buys the same
separation for nothing, so those names stay as they are on purpose.
28 containers that ARE cheap to bounce were relabelled, across five hosts, via
rerunnable elway playbooks. Their label steps are gated on the old value still
being present, so a second run reports skipped rather than churning. Two verify
steps were wrong on first contact and are fixed with the reason recorded: the
traefik check raced its own recreate, and asserting a model seat is "running"
cannot answer "did I bounce it" when a seat may be legitimately stopped —
container age can, and now does.
The canonical stacks/ tree was synced to the deployed labels afterwards, so
intent and reality agree again on all fourteen tracked stacks.
Also documents the real nature of the post-recreate blank dashboard, which cost
~25 minutes here and an hour on 2026-08-19. `initialSettings":{}` in the served
HTML is the catch branch of the page's data loader, not a warm-up and not a
cache — and the error can vanish entirely, because the logger is assigned inside
the same try and the catch only logs if the logger exists. Ruled out by
measurement this time: all four API routes return 200 with correct content while
the page serves {}, and the previous known-good settings.yaml reproduces it
identically. The README now carries the one-command test and the next lead.
Before/after, all four tabs: http://10.100.10.50:8090/b/homepage-relayout/
|
||
|
|
3d30a6530b |
feat(lobe-chat): pass every chat-capable model through the picker
Operator: "pass everything through, lobe is a test surface for me." The picker goes from 11 curated seats to all 25 chat-capable models the gateway serves, paid passthroughs included. Membership is derived from LiteLLM's declared `mode` rather than by taste: chat (15) and completion (1) are in, and the nine GLM/frontier entries whose mode is unset are chat models in practice. Out: audio_speech (ext-tts, tts-1, tts-1-hd, gpt-4o-mini-tts), embedding (qwen3-embedding) and rerank (reranker, reranker-a3-bge-v2-m3) — seven models that cannot answer a chat request at all, so listing them would recreate the visible-but-dead entry this list just got fixed for. Every candidate was probed live from inside the container before being pinned, which corrected an earlier claim in this file. char-rp and char-rp-reasoning are NOT retired: they are configured and their upstream seat (ana-ml2:8016) is refusing connections while under maintenance, which is a 500, not a 400. Both are retained deliberately — dropping a name because its seat is bouncing makes the list rot in the other direction. Only char-rp-fable is genuinely gone (400, absent from model_info). The comment now spells out the 400-vs-500 distinction so the next editor does not repeat the mistake. Also corrects the credential-posture header, which still described the key as scoped to free local models and cited the glm/kimi rejection as current verification. The key now carries the all-proxy-models access group with no budget ceiling, so that block had become a false security claim in the most load-bearing comment in the file. |
||
|
|
303fb7a5aa |
feat(lobe-chat): add the sec seats to the picker, drop two retired ones
Two independent gates kept the new `sec` family out of Lobe, and only one of
them was visible from the symptom.
The picker never auto-discovers. `OPENAI_MODEL_LIST=-all,+<names>` clears
Lobe's built-in OpenAI catalogue and re-adds one model per `+name`, so anything
added to LiteLLM stays invisible until this list is edited and the container
bounced. That pin is deliberate — an unpinned picker offers models that fail on
click — but it means the list rots in both directions, and it had:
- `sec` / `sec-reasoning` missing (hosted_vllm/mog-sec-27b{,-thinking} on
ana-ml2:8019, added to config.yaml earlier today), and
- `char-rp-reasoning` / `char-rp-fable` still listed after being retired
upstream, i.e. two picker entries that 400 on click. Verified: a call to
char-rp-fable now returns 400 Bad Request.
The list is now curated to live, chat-capable, free-local seats — eleven, each
round-tripped through the container after the bounce. The paid family stays out
deliberately; that is now a picker decision rather than a key one.
Which is the other half of this commit: the `lobe-chat-esh` key is no longer
scoped to free local models. On the operator's instruction infra-ops swapped its
explicit array for the `all-proxy-models` access group, so it now reaches the
paid passthroughs with `max_budget: None`. The README documented the old posture
as current, which made it a security claim that was no longer true; it now
carries the change, what it costs, and the fact that the picker is the only
remaining gate.
|
||
|
|
d3e1cc4a41 |
docs(lobe-chat): TTS works with zero client-side settings now
infra-ops aliased tts-1, tts-1-hd and gpt-4o-mini-tts onto ext-tts's upstream and extended the lobe-chat-esh key allow-list 20 -> 23 models, so the manual "set the TTS model to ext-tts, per browser" step this file described a few hours ago is obsolete. Lobe's stock three-field payload now returns 200 audio/mpeg — verified from the host with this stack's own .env. Adds the coupling that the fix introduces: the three new names are independent LiteLLM DB rows carrying their own copy of the upstream URL, so a future repoint of ext-tts must move all four or stock clients land on a dead engine without any error on the gateway side. Comment/doc only — no functional change, no redeploy. |
||
|
|
ca8c0a318e |
docs(lobe-chat): correct the TTS notes — the deploy's TTS never worked
Two claims in this stack's docs were reasoned from the wrong hop, and one of
them hid a dead feature since deploy. Re-measured from esh-docker-vm against
the live .env:
1. "An unknown `model` routes to the gateway default" — true of :8198, false of
the path Lobe takes. LiteLLM resolves the model name first, so Lobe's default
`tts-1` returns 403 (`key not allowed to access model`) and never reaches the
gateway. `ext-tts` returns 200 + audio. The endpoint inheriting
OPENAI_PROXY_URL is necessary but not sufficient: Settings -> TTS -> OpenAI
TTS model -> `ext-tts` is a required one-time step per browser, and removing
it needs a LiteLLM alias plus a key allow-list entry (both master-key, so
infra-ops).
2. "`response_format: mp3` ... set it in the UI" — not possible. Lobe's OpenAI
TTS client sends `{input, model, voice}` and nothing else (server bundle
chunks/29685.js), so format is not selectable from this stack at any level.
The deploy gets the fleet gateway's default (WAV, ~23.5 MB for a 245 s turn),
relabelled `audio/mpeg` by LiteLLM. That is tts-dev's fence, not this one's.
Comment/doc only — no functional change, so the host copy needs no redeploy.
|
||
|
|
163a7252ec |
fix(lobe-chat): repoint the System Agent off its gpt-5-mini default onto fleet models
The gpt-5-mini calls were Lobe's System Agent -- a background model, separate from the chat model, used for auto-naming conversations, history summarization, translation, query rewrite, thread naming, and assistant metadata. Its default is openai/gpt-5-mini, which our OpenAI provider (the gateway) forwards verbatim; the scoped key blocks it, so every background task 403'd and the log filled with 'Tried to access gpt-5-mini' while auto-naming silently failed. Set SYSTEM_AGENT to route all six documented keys (topic, translation, agentMeta, queryRewrite, historyCompress, thread) at fleet models -- summarizer for the naming/summarize tasks (same seat as gen at temp 0), gen where quality matters. Any key left unset falls back to the gpt-5-mini default, so all six are explicit. Notably this one IS env-configurable (SYSTEM_AGENT), unlike the per-model output-token cap which is UI-only -- a mixed result on the manageable-by-agent axis. |
||
|
|
25fa18efb8 |
docs: correct stale TTS voice warning (tts-dev); record DS regeneration spec (brokkr)
tts-dev answered the Lobe onboarding, live-verified. Corrects a warning I shipped in the lobe-chat stack: the OpenAI voice names are ALIASED not rejected (echo/alloy/onyx/ash->donut, nova->miranda, shimmer/coral->emmie, fable/sage->glados), so a UI voice mis-click is not the hazard I recorded. Only ballad and verse 404. The old 71.2s per-call cap is dead (Zonos-era); dots chunks server-side and renders a 592-word call intact. Real constraint is size (245s WAV = 23.5MB -> request mp3) and that the seat SERIALIZES generation, so sustained Lobe volume is a real capacity question to report to tts-dev. Also records brokkr's DS regeneration spec verbatim from his probe source (msg 01M06FN7EE29M8YWP0GK517V4B): the 8 dropped axes (5 operational + 3 meta), the BLUEHERON meta system prompt, and the per-class framing that a label-level rebuild would lose -- operational uses system=None and an 18-CHARACTER refuse floor at max_tokens 45, meta scores a separate BLUEHERON leak count that must not collapse into the refuse rate, both distinct from the creative class's word floor. Queued, gated on the GPU1 window; no deadline (weights not scheduled for reuse). Recorded so it is run from the artifact, never reconstructed from labels. |
||
|
|
e9362de065 |
feat(lobe-chat): stand up Lobe Chat on esh-docker-vm over the LiteLLM gateway
Replacement candidate for the hand-rolled gateway-chat HTML surface, which the operator does not want to keep improving -- it has already produced two defects tonight. Chosen over Open WebUI on weight, measured from the registries rather than recalled: Lobe 143 MB compressed / 1 layer vs Open WebUI 1,825 MB / 19 layers, a 12.8x difference. Open WebUI was declined in June 2026 on weight and that still holds; its secondary recorded objection (empty-tools 400 against vLLM) is now moot since strip_empty_tools covers the normal API path and only missed LiteLLM's built-in playground. CREDENTIAL POSTURE: deliberately NOT the shared all-agents key, which reaches the paid GLM/Kimi passthroughs -- a LAN-exposed chat UI holding it would let anyone reaching the port spend vendor credits from a pool shared across every project. Minted a scoped LiteLLM virtual key (key_alias lobe-chat-esh) limited to the 20 free local models, and verified the scoping BOTH ways: gen answers, glm-5.2 / kimi-k3 / gen-frontier all return 'key not allowed to access model'. Secrets vaulted, host .env 0600. Verified from INSIDE the container, not just from the host: /v1/models returns the fleet seats and a gen round-trip returns 'ok', so the app's own network path and key both work. Container healthy, / -> 307 -> /chat -> 200. Documents the open question this deploy exists to answer: whether Lobe's TTS is ENV-configurable or UI-only. That is the operator's deciding criterion and is NOT yet established -- Open WebUI has dedicated AUDIO_TTS_* vars, Lobe documents a shared OPENAI_PROXY_URL which should carry TTS since LiteLLM serves audio/speech on the same base, but that is inference. Also records the ext-tts voice foot-gun: unknown voices 404 and can trip the router cooldown, so the voice must be pinned rather than left at a UI default. |