Report why a node's model inventory is empty - #3
Draft
DaveHomeAssist wants to merge 1 commit into
Draft
Conversation
Model loading collapsed every failure into an empty list, so an
unreachable node, an HTTP error, a timeout and a node with nothing
pulled all reached the UI as "No models available" with no way to
tell them apart.
- fetch_node_models returns {"models", "error"}; /nodes/{id}/models
and /nodes/status surface that error, and describe_node_error names
the actual cause (refused connection, HTTP status, timeout) with the
OLLAMA_HOST hint for loopback-only daemons.
- A malformed DAVE_NODES silently registered zero nodes. Print the
parse error and the expected JSON shape instead.
- Raise the /api/tags timeout from a hardcoded 3s to a configurable
DAVE_NODE_TIMEOUT (default 10s); 3s was tight for a node loading a
large model.
- Stop overwriting MODEL_INVENTORY after a failed fetch, which made
chat reject models the node really serves.
- Match "mm" and "vl" as whole tokens in the vision heuristic; the bare
substring flagged every "gemma" tag as vision-capable.
- Frontend: distinguish "Node unreachable" from "No models pulled on
node", and stop passing the click MouseEvent in as preferredModelId,
which reset the user's model choice on every manual reload.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtgxcGLFACR6q9M8ZYiqRM
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.
Problem
"Models aren't loading" was undiagnosable from the router.
get_node_modelscollapsed every outcome into an empty list, so four distinct conditions reached the UI as the same "No models available":/api/tagsslower than the hardcoded 3s timeoutGET /nodes/{node_id}/modelsreturned HTTP 200 withmodels: []in all four cases, and the only trace of the real cause was aprintto the router's stdout.Changes
Surface the failure reason.
fetch_node_modelsreturns{"models", "error"}.GET /nodes/{node_id}/modelsandGET /nodes/statusboth carry thaterrorfield.describe_node_errornames the actual cause and, for a refused connection, points at the usual culprit (OLLAMA_HOST=0.0.0.0:11434).error: nullwith an empty list now unambiguously means "reachable, nothing pulled".Malformed
DAVE_NODESno longer fails silently. A parse failure registered zero nodes through a bareexcept Exception, which is indistinguishable from an empty cluster. It now prints the parse error and the expected JSON shape.Timeout is configurable.
DAVE_NODE_TIMEOUT(default 10s) replaces the hardcodedtimeout=3on both/api/tagscalls. 3s is tight for a node loading a large model.Stop clobbering a good inventory. The endpoint overwrote
MODEL_INVENTORY[node_id]even when the fetch failed, so one transient timeout made/chatreject models the node really serves withModel '<id>' is not available. The inventory is now only written on a successful read.Vision heuristic token boundaries.
"mm" in lidmatched everygemmatag and"vl" in lidwas similarly loose, so ordinary text models were labelled vision-capable during load. Both now match as whole tokens, with an added pattern for theqwen2.5vlstyle.Frontend. The model dropdown distinguishes "Node unreachable" (with the reason as a tooltip and in the console) from "No models pulled on node".
loadModelsBtn.onclick = loadModelsFromNodepassed the clickMouseEventin aspreferredModelId, which failed everystate.modelMetalookup and silently reset the user's model choice on each manual reload; it now calls with no argument.Verification
Six tests added to
tests/test_api_contracts.pycovering the unreachable-node reason, inventory preservation across a failed fetch, the reachable-but-empty case, HTTP error surfacing, offline reason in/nodes/status, vision token boundaries, and the loudDAVE_NODESparse failure.Cluster reachability itself is still not proven by repository tests — these changes make the runtime report which of the four conditions is actually happening, they do not verify a live node.
Generated by Claude Code