# shellcheck shell=bash # linux/lib/catalogue.sh - fetching a provider's model list, and the cache every fetch leaves. # # Part of the claude-mode CLI: sourced by linux/claude-mode, which sets the # CM_* paths, PY and JSON used here. Not meant to run on its own. # --------------------------------------------------------------------------- # Provider catalogues # --------------------------------------------------------------------------- # Every fetch leaves a copy behind for a reader that cannot afford the round # trip - the bar panel's model picker. It is written here, in the only places a # catalogue is ever fetched, so every command that already pays for the network # (models, doctor, setup, the menu's picker) keeps it fresh at no extra cost. cm_cache_catalogue() { "$PY" "$JSON" cache-models "$CM_MODELS_CACHE" "$1" "$2" "${3:-}" >/dev/null 2>&1 || true } # One catalogue fetch, for any provider: fetched according to its # catalogue.kind, parsed to TSV, and left in the cache for the panel. Prints # the TSV; the status says whether the fetch itself worked. TSV columns by kind: # # openrouter id ctx $in $out lmstudio id state ctx # ollama id params quant family openai id # static id note (a list kept in providers.json) provider_catalogue() { local pid="$1" base="${2%/}" token="${3:-}" out rc case "$(prov_field "$pid" 10)" in openrouter) out="$(curl -fsS --max-time 30 https://openrouter.ai/api/v1/models 2>/dev/null \ | "$PY" "$JSON" or-models 2>/dev/null)" ;; lmstudio) out="$(curl -fsS --max-time 10 ${token:+-H "Authorization: Bearer $token"} \ "$base/api/v0/models" 2>/dev/null | "$PY" "$JSON" lms-models 2>/dev/null)" ;; ollama) out="$(curl -fsS --max-time 10 ${token:+-H "Authorization: Bearer $token"} \ "$base/api/tags" 2>/dev/null | "$PY" "$JSON" ollama-models 2>/dev/null)" ;; openai) # Both header styles: a proxy in front of Anthropic wants # x-api-key, one in front of anything else wants Bearer. out="$(curl -fsS --max-time 15 ${token:+-H "Authorization: Bearer $token"} \ ${token:+-H "x-api-key: $token"} -H 'anthropic-version: 2023-06-01' \ "$base/v1/models" 2>/dev/null | "$PY" "$JSON" openai-models 2>/dev/null)" ;; static) out="$("$PY" "$JSON" provider-static "$pid" 2>/dev/null)" ;; *) return 1 ;; esac rc=$? cm_cache_catalogue "$pid" "$([ "$rc" -eq 0 ] && echo 1 || echo 0)" "$base" <<<"$out" [ -n "$out" ] && printf '%s\n' "$out" return "$rc" } # The credential a preset would send. Empty when there is nothing to send. cm_preset_token() { local pf="$1" am ref am="$(jget "$pf" auth.mode)"; [ -z "$am" ] && am=vault if [ "$am" = "vault" ]; then ref="$(jget "$pf" auth.keyRef)"; [ -z "$ref" ] && ref=openrouter cm_vault_get "$ref" 2>/dev/null || true else jget "$pf" auth.token fi } # The token passed to provider_catalogue is not optional decoration. A local # server with authentication switched on answers its model list with 401 like # anything else, so without it the catalogue comes back empty and every caller # silently believes the server has no models - on exactly the setups that need # the list most.