Files
command-center/agent/managed-skills/fleet-served-model-id-rename/SKILL.md
T

4.6 KiB

name, description
name description
fleet-served-model-id-rename Rename the served model id (alias) on a dank-fleet LLM endpoint and re-key every consumer that keys on it, with live verification.

Fleet served-model-id rename (wire rename)

Renames the id an endpoint announces on the wire. The service, unit, script and env FILE names keep the old name (container/unit identity is stable) — only the served alias moves. Done this way on 2026-10-09: frank-primary→frank-archon, frank-large→frank-dragoon, frank-secondary→frank-zealot.

1. The knob, per engine

Endpoint Knob
frank-primary (radiance, dankserver :7770) FRANK_PRIMARY_SERVED_NAME in scripts/frank-primary.env → --served-model-name
frank-large (halogen flash-server, dankclaw :7770) HALOGEN_MODEL_ID in scripts/frank-large.env
frank-secondary (llama.cpp, dankclaw :7771) ALIAS in scripts/frank-secondary.env → --alias

Also flip the serve-script defaults (: "${ALIAS:=…}", the :? gate messages). scripts/deploy-remote.sh has no alias references — the deployer needs no edit.

2. Consumers that key on the id (all in ONE change)

  • Seams: tests/frank_{secondary,large,primary}_unit.bats — fixture env value, the argv assertion (--alias), the env grep pin, the -e HALOGEN_MODEL_ID= render assertion.
  • OpenWebUI (Dankclaw, rootless quadlet, webui.db): model.id+name, access_grant.resource_id (resource_type='model'), openai.api_configs per-backend model_ids. Backup first (webui.db.bak-YYYYMMDD; the DB is WAL-mode). No sqlite3 binary in the image → podman exec -i open-webui python3 - with a script on stdin. Then systemctl --user restart open-webui.service. A stale id fails SILENTLY: OpenWebUI intersects the backend /v1/models with model_ids, so the picker just goes empty.
  • Hermes (/home/dank/Containers/hermes/data/config.yaml, root-owned → sudo): model.default, the provider models: key, every auxiliary: route naming the endpoint. Backup, surgical sudo sed -i, sweep grep -rln <old-id> over the data dir (session JSONs are historical — leave), restart hermes.service hermes-webui.service (user units).
  • Dev harnesses: "model": "frank-…" literals in scripts/bench-*.py, deep-probe.py, calib-push.py, fleet-probes-swift15.sh, autoresearch*.
  • Docs: shared/homepage/docs.html (headings, api-id annotations, the curl/opencode/Pi examples), endpoint runbooks, AGENTS.md Model Config, serverAppConfigs-docs/Agent/OMP Harness.md, Dankclaw/OpenWebUI.md.
  • Harness side (~/.omp/agent/models.yml on the dev box) — ids and modelRoles must name the same string; two ports on one host = two providers.

3. Deploy + verify

./scripts/deploy.sh <host> --service <name> per endpoint; keep the tree clean (untracked scratch files inside the repo fail the whole-tree gate — put probes in /tmp with a node_modules symlink to tests/e2e/node_modules).

Verify on /v1/models, NEVER on a chat echo: radiance echoes the REQUESTED model name (a 200 proves nothing), llama.cpp and halogen ignore the requested id.

for u in 192.168.0.235:7770 192.168.0.143:7770 192.168.0.143:7771; do
  curl -fsS "http://$u/v1/models"; done

OpenWebUI acceptance = a real browser as a family account: the welcome screen names the model and POST /api/v1/chat/completions {"model":"<new-id>"} answers. GET /api/v1/models/list returning {"items":[],"total":0} for that same account is a probe artifact, not a failure. Playwright notes: locator.isVisible({timeout}) does NOT wait (returns immediately) — use waitFor({state:'visible'}); the composer is a contenteditable div, not a textarea; stable anchors are getByRole('button', {name: /selected model/i}) and "How can I help you today?".

4. Trap: green deploy, old config

deploy.sh plans from repo paths and gates on the port. A systemd drop-in under /etc/systemd/system/<unit>.service.d/ can override Environment=FRANK_*_ENV_FILE and ExecStart to a staging worktree, so the deploy restarts a DIFFERENT tree and reports healthy (this bit frank-primary for a day after a quantization campaign). After an LLM deploy, prove the running shape:

systemctl cat <unit>                       # drop-ins print at the bottom
podman inspect <container> --format '{{json .Config.Cmd}}' | tr , '\n'

Before retiring such a drop-in: diff staging vs checkout for serve script/unit/env, and git merge-base --is-ancestor <staging-HEAD> HEAD so no campaign tuning is lost. Move it to ~/.AGENTTRASH/YYYYMMDD-topic/ (never rm), daemon-reload, restart, re-read /v1/models.