feat(entrypoint): link ~/.pi/agent/models.json to a mounted shared file
pi reads custom providers from ~/.pi/agent/models.json, and ~/.pi is the devbox-pi-config named volume. A file baked into the image would only seed a fresh volume, once. A hand-made link is one more step on every new volume: on 2026-10-12 that was the same `ln -s /opt/fleet-pi/models.json …` once per device, for one fleet-shared file. New rootfs/usr/local/lib/pi-devbox/link-pi-models.sh, called from entrypoint-user.sh after the pi-toolkit and pi-extensions installs. When /opt/fleet-pi/models.json exists (PI_MODELS_JSON overrides the path, =off disables it), it links ~/.pi/agent/models.json to it, honouring PI_CODING_AGENT_DIR. It only ever creates a link where nothing exists: a real file or a link of the user's own is left alone, with one NOTE line. With nothing mounted, it does nothing and prints nothing. A link whose target later vanishes is harmless; measured with pi 1.0.0, a dangling models.json behaves like a missing one (rc 0, no error, no custom models). Tests: - scripts/test-link-pi-models.sh: 13 two-sided cases against a throwaway HOME. Wired into lint.yml, so it runs on every push and not only at release. - Of 11 mutations, 10 are caught. The 11th (ln -s -> ln -sfn on the final link) is unreachable behind the guards. - smoke-test.sh: with nothing mounted no link appears, and the script links a mounted file. Both commands were run under dash here. - recreate-sanity-check.sh: pass, warn or fail on the link, but only when a shared file is mounted. Here it passes. Docs: - README "Custom model providers (models.json)": mount the DIRECTORY (git pull renames, and a single-file mount then shows "No such file" until recreate), keep keys in .env as "$NAME". - .env.example: PI_MODELS_JSON. Local gates green: lint-shell, check-workflow-shell, check-dockerfile-directives, check-base-hash, check-doc-drift.
This commit is contained in:
@@ -277,6 +277,24 @@ else
|
||||
fail "~/.pi/agent/AGENTS.md missing or not a symlink"
|
||||
fi
|
||||
|
||||
# shared models.json (link-pi-models.sh) — checked only when a shared file is
|
||||
# actually mounted, so a device without one is not judged by it.
|
||||
_mj_src="${PI_MODELS_JSON-/opt/fleet-pi/models.json}"
|
||||
case "$_mj_src" in "" | off | OFF | Off) _mj_src="" ;; esac
|
||||
if [ -n "$_mj_src" ] && [ -f "$_mj_src" ]; then
|
||||
_mj="$HOME/.pi/agent/models.json"
|
||||
if [ -L "$_mj" ] && [ "$(readlink "$_mj")" = "$_mj_src" ]; then
|
||||
pass "~/.pi/agent/models.json -> $_mj_src (shared custom providers)"
|
||||
elif [ -L "$_mj" ]; then
|
||||
warn "~/.pi/agent/models.json links to $(readlink "$_mj"), not the mounted $_mj_src"
|
||||
elif [ -e "$_mj" ]; then
|
||||
warn "~/.pi/agent/models.json is a real file, so the mounted $_mj_src is NOT in use"
|
||||
else
|
||||
fail "$_mj_src is mounted but ~/.pi/agent/models.json is missing (image without link-pi-models.sh? run: ln -s $_mj_src ~/.pi/agent/models.json)"
|
||||
fi
|
||||
fi
|
||||
unset _mj _mj_src
|
||||
|
||||
# extensions deployed (pi-extensions) — expect ≥4 *.ts
|
||||
EXT_COUNT=$(ls -1 "$HOME"/.pi/agent/extensions/*.ts 2>/dev/null | wc -l | tr -d ' ')
|
||||
if [ "$EXT_COUNT" -ge 4 ]; then
|
||||
|
||||
Reference in New Issue
Block a user