fix(ui-v3): normalize /api/slots — defaults for missing .metrics / .spark / .model (deferred fix from v3 cutover handoff)#249
Merged
Conversation
…ots/hardware/dashboard Backend /api/slots can omit `metrics` (and `spark`, sometimes `model`) for offline / not-yet-loaded slots. v3 components dereference fields like `slot.metrics.toks`, `slot.metrics.kv`, `slot.spark` directly, so the slots/hardware/dashboard routes black-screened on real backend payloads. Add a `normalizeSlot()` helper in useSlots that: - defaults `metrics` to a full SlotMetrics shape (toks 0, ttft null, …) - defaults `spark` to [] - falls back model → model_id → model_default → '' if model is absent Applied in both `fetchSlotsUnion` and `useSlotDetail`. One change covers all 20+ `slot.metrics.*` access sites in slots.jsx / dashboard.jsx / slot-modals.jsx. This is the deferred fix called out in the v3 cutover handoff. The LXC at hal0.thinmint.dev was already hot-patched before this commit so the dashboard renders again; this PR brings main in sync. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 23, 2026
thinmintdev
added a commit
that referenced
this pull request
May 23, 2026
…hardware actually render (#253) Two follow-up regressions surfaced after the v3 cutover (#235 + #249): 1. **/slots looked blank/black** Backend /api/slots returns sparse slots without `type`, `device`, or `group` for built-in slots (primary, embed, stt, …). The v3 SlotsView groups via `slots.filter(s => s.group === "chat")` etc., so without inference the primary slot fell out of every section and only the page header rendered. Looked like a black screen on the dark theme. Fix: extend the useSlots `normalizeSlot()` helper with `inferSlotShape()` — derives type/group/device from BUILTIN_SLOTS naming conventions (primary/coder/agent → llm/chat, embed/rerank → embed, stt/whisper → voice, tts/kokoro/vibe → voice, img/sd → img) plus provider/backend fallbacks. Sparse backend slots now land in the correct group. 2. **/hardware crashed with TypeError** Backend /api/hardware returns a flat shape (cpu_model, ram_mb, gpu_name, npu.{present}, …). HardwareView dereferences nested fields (H.ram.total, H.npu.columns) directly — `H = hwQuery.data || mock` means the live data overrode the mock and crashed. Fix: add `normalizeHardware()` in useHardware that maps flat keys into the nested shape components expect, with neutral defaults for fields the backend doesn't surface (columns/ctx/hostname/uptime). Both fixes confirmed end-to-end on the hal0 LXC: /slots now renders the primary slot card in a Chat section, /hardware renders all five cards (Host/CPU/GPU/NPU/Memory) without errors. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2 tasks
thinmintdev
added a commit
that referenced
this pull request
May 23, 2026
…ice D) (#267) Final slice of the Phase 1 auth removal. Closes the architectural loop opened by ADR-0001, surfaces the breaking change to operators, bumps the version, and patches the one test that #256 missed. ADR - New: docs/internal/adr/0012-remove-auth-and-caddy.md — accepts the removal direction, references the four implementing PRs (#254, #255, #256, #266), records what was deleted (~6,000 LOC) and what stays (uninstall cleanup, MCPAuthMiddleware as identity stash, bcrypt/PyJWT/argon2 deps untouched), and frames the v0.3 stream-4 follow-up work (MCPIdentityMiddleware rename, Hermes header swap). Note: numbered 0012 because 0011 was taken by agent-identity-cards via PR #239 while the auth-removal work was in flight — the original briefing's "ADR-0011" suggestion was stale by the time it landed. - ADR-0001 frontmatter flipped to `Status: Superseded by ADR-0012 (2026-05-23)` with a paragraph explaining why "FastAPI owns auth" ended up being transitional. Docs - docs/operate/auth.mdx — full rewrite. The old page documented Caddy + basic_auth + the LAN-vs-WAN wizard flow; the new page tells operators hal0 ships open on a trusted LAN and gives three concrete upstream-proxy patterns (Traefik, nginx, Cloudflare Tunnel) with copy-pasteable configs. OpenWebUI's own `WEBUI_AUTH_TRUSTED_EMAIL_HEADER` override is documented for the upstream-proxy SSO case. - README.md - drop "password setup → bundle pick" from the first-run feature line - rewrite the "Auth posture" section: references ADR-0012, drops the FIRST_RUN_LOCK / OTP / wizard-password-step prose, points at docs/operate/auth.mdx for upstream-proxy patterns - CHANGELOG.md - new top-level [v0.3.0-alpha.1] — 2026-05-23 entry - Breaking: auth gone, Caddy gone, `--no-tls` gone, HAL0_AUTH_* env vars are no-ops, Bearer tokens minted under v0.2.x stop working - New / improved: v3 dashboard on main + normalizers (#235/#249/#253), /v1/* proxy (#248/#212), footer nullability (#252/#221), Settings default tab → Secrets - Removed code: per-file accounting of the ~6,000 deletions - Upgrade notes: lose-your-password warning, drop --no-tls flag Tests - tests/openwebui/test_env_writer.py - delete `test_auth_disabled_keeps_webui_auth_false` (covered by the rewritten test below) - delete `test_auth_enabled_flips_webui_auth_true` (the one test that failed CI on #256 — was asserting the now-removed HAL0_AUTH_ENABLED→WEBUI_AUTH=True branching) - delete `test_auth_falsy_values_keep_defaults` (parametrized sibling, same removed branching) - delete `test_overrides_still_win_under_auth` (same) - add `test_webui_auth_is_always_false_by_default` (defensive: the env vars are gone, WEBUI_AUTH stays False regardless) - add `test_trusted_email_header_via_explicit_override` (documents the new opt-in path through the `overrides` parameter) Version - pyproject.toml: 0.2.0-alpha.3 → 0.3.0-alpha.1 (single source of truth per memory hal0_version_two_locations — src/hal0/__init__.py reads via importlib.metadata) Sequence (Phase 1 complete) - Slice B (#255, merged) - Slice A (#256, merged with admin-override since this test failure was the only blocker; resolved here) - Slice C (#266, in CI) - Slice D (this PR) Follow-up (per the user's briefing, not in this PR) - Update Hermes bootstrap plan + ADR-0011 (agent identity cards) to drop bearer references and switch to X-hal0-Agent identity header - Edit issues #240 / #243 / #246 to drop bearer-token acceptance criteria - Rename MCPAuthMiddleware → MCPIdentityMiddleware in mcp_mount.py - Update auto-memory feedback-caddy-reduction-divergence to note the direction landed Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
After PR #235 landed v3 on main, the slots/hardware/dashboard pages black-screened on real backend payloads because v3 components dereference
slot.metrics.toks,slot.metrics.kv,slot.spark, etc. directly, and the backend can omit those fields for offline / not-yet-loaded slots.This was the deferred fix called out in the v3 cutover handoff:
Change
useSlots.tsgains anormalizeSlot()helper applied in bothfetchSlotsUnionanduseSlotDetail:metricsdefaults to a fullSlotMetricsshape (toks 0, ttft null, kv null, …)sparkdefaults to[](guards<Spark data={slot.spark} />rendering)modelfalls backmodel → model_id → model_default → ''One change covers all 20+
slot.metrics.*access sites inslots.jsx/dashboard.jsx/slot-modals.jsx.Why hot-patch first, PR after
The LXC at
hal0.thinmint.devwas hot-patched (same byte content as this commit) and rebuilt before this PR went up, so the dashboard is already rendering. This PR bringsmainin sync.Known follow-up not in scope
apiMockfixture rewrite to match Phase B1 hook shapes (γ-suite still red; that's the test-harness side of the same shape mismatch)Test plan
🤖 Generated with Claude Code