#!/usr/bin/env bash # Build-time only (see Dockerfile). On a project's first use, opencode installs npm # packages (@opencode-ai/plugin and its deps) into $HOME/.config/opencode. At run time the # capsule can reach only openrouter.ai, so do that here, where the build has network: start # opencode once, open a session to trigger the install, and keep the resulting HOME. # # Every wait is bounded (curl --max-time, a deadline on each loop, kill -9 as a last # resort): a step that hangs fails the build with a message instead of hanging it. set -eu export HOME=/opt/opencode-capsule OPENCODE_CONFIG=/etc/opencode/opencode.json mkdir -p "$HOME" /tmp/warm opencode serve --hostname 127.0.0.1 --port 4096 --pure >/tmp/warm.log 2>&1 & pid=$! stop() { kill "$pid" 2>/dev/null || true for _ in $(seq 1 10); do kill -0 "$pid" 2>/dev/null || return 0; sleep 1; done kill -9 "$pid" 2>/dev/null || true } fail() { echo "warm_opencode: $1" >&2; cat /tmp/warm.log >&2; stop; exit 1; } up="" for _ in $(seq 1 60); do curl -sf --max-time 3 127.0.0.1:4096/global/health >/dev/null && { up=1; break; } sleep 1 done [ -n "$up" ] || fail "opencode did not answer /global/health within 60 s" curl -sf --max-time 30 -X POST "127.0.0.1:4096/session?directory=/tmp/warm" \ -H 'Content-Type: application/json' -d '{}' >/dev/null || fail "creating a session failed" for _ in $(seq 1 120); do [ -f "$HOME/.config/opencode/package-lock.json" ] && break; sleep 1; done sleep 5 stop test -d "$HOME/.config/opencode/node_modules/@opencode-ai/plugin" \ || fail "opencode did not install @opencode-ai/plugin" # Keep only the installed packages (opencode pins @opencode-ai/plugin to its own version, # 1.18.23; package-lock.json records the rest). The npm cache, session DB and logs go. rm -rf "$HOME/.local" "$HOME/.npm" /tmp/warm /tmp/warm.log chmod -R a+rX "$HOME"