scripts: add opencode model listing sync helper

Queries lmstudio and ollama /v1/models endpoints to keep opencode.json
model entries up to date, preserving manual overrides.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
tobias
2026-03-07 22:50:13 +01:00
parent 49db614262
commit 9df1496d8b
2 changed files with 153 additions and 1 deletions

View File

@@ -174,6 +174,7 @@ Format: `path | goal | usage`. This section is intentionally compact so `what` c
- `scripts/setup/mount_container` | goal: mount or unmount LUKS container files listed in `.containers` manifests | usage: `scripts/setup/mount_container mount`
- `scripts/setup/share.sh` | goal: run a local sharing workflow | usage: `scripts/setup/share.sh`
- `scripts/setup/terminal-logs.sh` | goal: configure or collect terminal logging | usage: `scripts/setup/terminal-logs.sh`
- `scripts/setup/update-models.sh` | goal: sync lmstudio and ollama model listings into opencode.json | usage: `scripts/setup/update-models.sh [lmstudio|ollama]`
- `scripts/windows/Get-ZimmermanTools.ps1` | goal: download Zimmerman forensic tools on Windows | usage: `powershell -File scripts/windows/Get-ZimmermanTools.ps1`
- `scripts/windows/getscreen.psm1` | goal: provide PowerShell screen-capture helpers | usage: `Import-Module scripts/windows/getscreen.psm1`
- `scripts/windows/sbom.ps1` | goal: generate or inspect SBOM-related data in PowerShell | usage: `powershell -File scripts/windows/sbom.ps1`
@@ -298,7 +299,7 @@ Format: `path | goal | usage`. This section is intentionally compact so `what` c
- `scripts/proxy/`: proxy environment propagation for apt, bash, and services.
- `scripts/display/`: display and touchpad toggles, including named `xrandr` screen-layout presets.
- `scripts/setup/`: host setup helpers such as automounting, sharing, terminal logging, encrypted container mounting, and Ubuntu telemetry disabling.
- `scripts/setup/`: host setup helpers such as automounting, sharing, terminal logging, encrypted container mounting, Ubuntu telemetry disabling, and model listing sync for opencode.
- `scripts/windows/`: PowerShell helpers, including Zimmerman tools bootstrap and SBOM-related work.
## `archive/`: Reference Material

151
scripts/setup/update-models.sh Executable file
View File

@@ -0,0 +1,151 @@
#!/usr/bin/env bash
# Updates lmstudio and/or ollama model listings in opencode.json
# by querying their /v1/models endpoints.
#
# Usage:
# ./update-models.sh # update both
# ./update-models.sh lmstudio # update only lmstudio
# ./update-models.sh ollama # update only ollama
#
# Requires: jq, curl
set -uo pipefail
CONFIG="${OPENCODE_CONFIG:-${HOME}/.config/opencode/opencode.json}"
if [[ ! -f "$CONFIG" ]]; then
echo "Error: config not found at $CONFIG" >&2
exit 1
fi
if ! command -v jq &>/dev/null; then
echo "Error: jq is required. Install with: brew install jq" >&2
exit 1
fi
# Map provider name -> base URL (read from config)
get_base_url() {
jq -r ".provider.${1}.options.baseURL // empty" "$CONFIG"
}
# Map provider name -> display label (read from config)
get_display_name() {
jq -r ".provider.${1}.name // \"${1}\"" "$CONFIG"
}
# Fetch models from API endpoint and build the opencode models object.
# Preserves any existing entries that have extra metadata (limits, modalities, variants)
# beyond just a name — so your manual overrides aren't lost.
build_models_json() {
local provider="$1"
local base_url="$2"
local display_name="$3"
local api_response
api_response=$(curl -sf --connect-timeout 5 "${base_url}/models" 2>/dev/null) || {
echo "Error: could not reach ${base_url}/models — is ${provider} running?" >&2
return 1
}
# Get list of model IDs from API
local model_ids
model_ids=$(echo "$api_response" | jq -r '.data[].id' | sort)
if [[ -z "$model_ids" ]]; then
echo "Warning: no models returned from ${provider}" >&2
return 1
fi
# Get existing models object (to preserve manual overrides)
local existing
existing=$(jq ".provider.${provider}.models // {}" "$CONFIG")
# Build new models object
local new_models="{}"
while IFS= read -r model_id; do
[[ -z "$model_id" ]] && continue
# Check if this model has extra config beyond just "name"
local existing_entry
existing_entry=$(echo "$existing" | jq -r --arg id "$model_id" '.[$id] // empty')
local has_extras="false"
if [[ -n "$existing_entry" ]]; then
local key_count
key_count=$(echo "$existing_entry" | jq 'keys | length')
if [[ "$key_count" -gt 1 ]]; then
has_extras="true"
fi
fi
if [[ "$has_extras" == "true" ]]; then
# Preserve existing entry with overrides, just update the name
new_models=$(echo "$new_models" | jq \
--arg id "$model_id" \
--argjson entry "$existing_entry" \
--arg name "${model_id} (${display_name})" \
'.[$id] = ($entry | .name = $name)')
else
# Simple entry with just a name
new_models=$(echo "$new_models" | jq \
--arg id "$model_id" \
--arg name "${model_id} (${display_name})" \
'.[$id] = { "name": $name }')
fi
done <<< "$model_ids"
echo "$new_models"
}
update_provider() {
local provider="$1"
# Check provider exists in config
if ! jq -e ".provider.${provider}" "$CONFIG" &>/dev/null; then
echo "Skipping ${provider}: not configured in opencode.json" >&2
return 0
fi
local base_url
base_url=$(get_base_url "$provider")
if [[ -z "$base_url" ]]; then
echo "Skipping ${provider}: no baseURL configured" >&2
return 0
fi
local display_name
display_name=$(get_display_name "$provider")
echo "Updating ${provider} models from ${base_url}..."
local new_models
new_models=$(build_models_json "$provider" "$base_url" "$display_name") || return 1
local count
count=$(echo "$new_models" | jq 'keys | length')
# Update config in-place
local tmp
tmp=$(mktemp)
jq --argjson models "$new_models" \
".provider.${provider}.models = \$models" \
"$CONFIG" > "$tmp" && mv "$tmp" "$CONFIG"
echo "${provider}: ${count} models synced"
}
# --- Main ---
targets=("${@:-lmstudio ollama}")
errors=0
for target in $targets; do
update_provider "$target" || ((errors++))
done
if [[ "$errors" -gt 0 ]]; then
echo "Done with ${errors} error(s). Run 'opencode models' to verify."
exit 1
else
echo "Done. Run 'opencode models' to verify."
fi