Skip to content

2.4.1: model picker - honest sizing, nothing hidden, upgrade-break detection - #36

Merged
agr77one merged 2 commits into
mainfrom
fix/2.4.1-model-ui
Jul 28, 2026
Merged

2.4.1: model picker - honest sizing, nothing hidden, upgrade-break detection#36
agr77one merged 2 commits into
mainfrom
fix/2.4.1-model-ui

Conversation

@agr77one

Copy link
Copy Markdown
Owner

2.4.1 — Model picker: honest sizing, nothing hidden, upgrade-break detection

Fixes three reported UI issues, plus a silent-failure gap found while investigating them.

Fixed

  • No model is hidden any more. The dashboard dropped every fits === "no" candidate, which made real catalog models invisible — qwen3.6-moe:35b-a3b never appeared and had to be pulled by hand. recommend_models now returns every candidate with a fits tag + fit_reason; oversized ones render marked and still confirm before downloading.
  • Sizing uses real numbers. MoE tags were read as their total (…:35b-a3b as 35B, not ~3B active). Fit now prefers FastFlowLM's measured footprint_gb — which also fixes gemma4-it:e4b (reads "4B" by name, is actually 8B / 9.1 GB) — and falls back to active-param counts for MoE. flm_list forwards the catalog metadata it previously discarded (footprint/installed/flm_min_version/parameter_size/context_length, unfiltered).
  • Provider-upgrade breakage is surfaced. FLM 0.9.45 rejects weights stamped for 0.9.43 and reports those models as not installed; nothing detected that, so the next hotkey failed with an opaque provider error (with no Ollama fallback available, everything broke). New _active_model_health reports ok / not_installed / unknown, and Config → Models shows a warning naming the model and the remedy. A listing failure stays unknown — never a false alarm.

Changed

  • One "Models" card. "Installed models" + "Pull a new model" merged into a single card with Installed / Add a model / FastFlowLM runtime subheads.
  • The picker is app-styled. Replaced a native <datalist> — browsers draw that popup in their own chrome and ignore page CSS entirely, so it could never match the dashboard — and a native <select size>, with plain elements: theme-aware in light and dark, keyboard navigable (↑↓/Enter/Esc), type-to-filter.

Self-caught during review

The health check originally compared against an "all" listing, but Ollama's "all" is installed + suggestions (ffp_provider_runtime.py:80), so a never-pulled model would have read as installed — a silent false "OK". It now trusts only authoritative details, else re-lists with the installed filter. Pinned by a regression test (SPEC B34).

Verification

  • ruff clean · 434 pytest (+28 new) · app.js syntax check (validated with a deliberate-break control).
  • Live in-browser: combobox/list computed styles match the app's own .card/input tokens in both light and dark; zero native select/datalist elements remain.
  • MoE regex validated against all 37 live FLM 0.9.45 catalog names — zero false positives (whisper-v3:turbo correctly returns unknown and is still listed).

SPEC V38/V39/V40, T28, B29–B34.

Note: the planned multi-lens adversarial review agent could not run (API session limit), so this change was verified by the gates, live browser checks, and manual reasoning above rather than an independent automated review.

🤖 Generated with Claude Code

agcycle and others added 2 commits July 27, 2026 17:31
…tection

Fixes three reported UI issues plus a silent-failure gap found while
investigating them.

- No model is hidden. The dashboard dropped every fits=="no" candidate, which
  made real catalog models invisible: qwen3.6-moe:35b-a3b never appeared and had
  to be pulled by hand. recommend_models now returns EVERY candidate with a
  fits tag + fit_reason; oversized ones render marked and confirm before pull.
- Sizing uses real numbers. MoE tags were read as their total ('...35b-a3b' as
  35B, not ~3B active). Fit now prefers FastFlowLM's measured footprint_gb
  (which also fixes gemma4-it:e4b: reads "4B" by name, actually 8B / 9.1 GB) and
  falls back to active-param counts for MoE. flm_list forwards the catalog
  metadata (footprint/installed/flm_min_version/parameter_size/context) that it
  previously discarded. Verified against all 37 live FLM 0.9.45 catalog names:
  zero false MoE detections.
- Provider-upgrade breakage is surfaced. FLM 0.9.45 rejects weights stamped for
  0.9.43 and reports those models as not installed; nothing detected that, so
  the next hotkey failed opaquely (no Ollama fallback available). New
  _active_model_health reports ok / not_installed / unknown, and Config → Models
  shows a warning naming the model and remedy. Listing errors stay "unknown" —
  never a false alarm.
- One "Models" card. "Installed models" + "Pull a new model" merged into a
  single card with Installed / Add a model / FastFlowLM runtime subheads.
- The picker is app-styled. Replaced a native <datalist> (browsers draw the
  popup in their own chrome and ignore page CSS, so it could never match the
  app) and a native <select size> with plain elements: theme-aware in light and
  dark, keyboard navigable (↑↓/Enter/Esc), type-to-filter.

Self-caught during review: the health check compared against a "all" listing,
but Ollama's "all" is installed+suggestions, so a never-pulled model would read
as installed. It now trusts only authoritative details or re-lists with the
installed filter (SPEC B34).

Verified: ruff clean, 434 pytest (+28), app.js syntax, and live in-browser
checks — combobox/list computed styles match the app's own card/input tokens in
both light and dark, zero native selects or datalists remain.

SPEC V38/V39/V40, T28, B29-B34.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…note

Records why per-round KV cache checks don't affect the prompt pipeline (all
hotkey modes are single-shot/stateless; chat replays to one backend; fallback is
all-or-nothing between separate servers), and corrects the stale Phase 4 blocker:
the NPU-contention argument applies to a second NPU runtime, not an NPU+GPU
split, which 0.9.45's cross-backend cache reuse now makes practical. Decision
unchanged (speed goal already met) — only the reasoning was outdated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agr77one
agr77one merged commit 5ac7d40 into main Jul 28, 2026
5 checks passed
@agr77one
agr77one deleted the fix/2.4.1-model-ui branch July 28, 2026 01:22

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 07a29c677b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/ffp_hardware.py
Comment on lines +253 to +254
mem = float(hw.get("ram_gb") or 0) + float(hw.get("vram_gb") or 0)
return max(2.0, round(mem - _OS_HEADROOM_GB, 1))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exclude discrete GPU VRAM from FastFlowLM capacity

On a Ryzen AI machine that also has a discrete GPU, such as 16 GB RAM plus a 24 GB NVIDIA card, _nvidia_vram_gb() supplies that dedicated VRAM and this calculation reports 34 GB usable after headroom. FastFlowLM's NPU weights reside in system RAM and cannot use the NVIDIA VRAM, so a 24.3 GB catalog model is incorrectly marked as fitting and can then fail to load. Only add VRAM when it is known to be a UMA carve-out; otherwise base FastFlowLM footprint checks on system RAM.

Useful? React with 👍 / 👎.

Comment thread scripts/ffp_hardware.py
Comment on lines 315 to +316
else:
fits = "no"
models.append({"name": name, "params_b": params, "fits": fits})
return {"hardware": hw, "budget": budget, "provider": provider, "models": models}
effective = active or params

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Account for total MoE weights when footprint is unavailable

When an older FastFlowLM listing has no footprint metadata, a 35B-total/3B-active MoE is compared to the memory-oriented model budget as only 3B. On a 16 GB machine this produces tight rather than no, despite the approximately 24 GB weight footprint, so the UI skips its oversized-model confirmation and downloads a model that cannot fit. Active parameters are useful for estimating compute speed, but the fallback capacity check must still account for total weight memory.

Useful? React with 👍 / 👎.

Comment thread scripts/ffp_daemon.py
Comment on lines +380 to +382
provider = grammar_fix.LLM_PROVIDER
model = str(grammar_fix.FLM_MODEL or "")
health = {"provider": provider, "model": model, "installed": None, "status": "unknown", "detail": ""}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Check the configured model before effective fallback

When an FLM upgrade invalidates the configured model but another model remains installed, resolve_effective_llm() replaces FLM_MODEL with that installed fallback (grammar_fix.py lines 170–173). This health check therefore examines the fallback, reports ok, and never warns that the persisted configured model was invalidated—the exact upgrade-break case this change is intended to surface. Read the configured provider profile's model for this verdict rather than the already-resolved effective model.

Useful? React with 👍 / 👎.

Comment thread scripts/ui/web/index.html
Comment on lines +325 to +326
<h3 class="subhead">Installed</h3>
<ul class="model-list" id="models-list" role="listbox" aria-labelledby="models-title" tabindex="0"></ul>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore keyboard selection for installed models

Replacing the native <select> with a focusable <ul role="listbox"> removes the browser's keyboard selection behavior, but no key handler is added for models-list—the new Arrow/Enter handlers apply only to pull-name. A keyboard-only user can focus this list but cannot choose any installed model other than the default selection, preventing Set as active or Remove from operating on another row. Add listbox key handling and update aria-selected/selectedModel accordingly.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants