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:
@@ -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/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/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/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/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/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`
|
- `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/proxy/`: proxy environment propagation for apt, bash, and services.
|
||||||
- `scripts/display/`: display and touchpad toggles, including named `xrandr` screen-layout presets.
|
- `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.
|
- `scripts/windows/`: PowerShell helpers, including Zimmerman tools bootstrap and SBOM-related work.
|
||||||
|
|
||||||
## `archive/`: Reference Material
|
## `archive/`: Reference Material
|
||||||
|
|||||||
151
scripts/setup/update-models.sh
Executable file
151
scripts/setup/update-models.sh
Executable 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
|
||||||
Reference in New Issue
Block a user