93 lines
3.9 KiB
Bash
93 lines
3.9 KiB
Bash
#!/bin/bash
|
|
# Read the harness registry and derive per-harness credentials from it.
|
|
#
|
|
# Source it — the whole point is exporting into the caller's environment, which a subshell
|
|
# would lose:
|
|
#
|
|
# HARNESS_SCRIPTS_DIR=/workspace/scripts . /workspace/scripts/lib/harness-credentials.sh
|
|
# harness_setup_credentials
|
|
#
|
|
# Two callers: `harbor-run`, which needs only this, and `setup-harnesses.sh`, which sources
|
|
# it and adds installs, config writing and launchers on top.
|
|
#
|
|
# No -e here — this file is SOURCED, and shell options belong to the caller's shell (both
|
|
# post-creates run with -e). An unguarded failure below therefore aborts container
|
|
# creation, which is why every failure site is individually guarded rather than relying on
|
|
# this line.
|
|
set -uo pipefail
|
|
|
|
_HARNESS_REGISTRY_DIR="${HARNESS_SCRIPTS_DIR:-/workspace/scripts}"
|
|
|
|
# The registry is read with tomllib (stdlib from 3.11), and `python3` is not always new
|
|
# enough — macOS ships 3.9, and a container may symlink an older managed interpreter. Pick
|
|
# the first one that can actually import it rather than assuming.
|
|
_raccoon_python() {
|
|
local p
|
|
for p in "${RACCOON_PYTHON:-}" python3 python3.13 python3.12 python3.11; do
|
|
[ -n "$p" ] || continue
|
|
command -v "$p" >/dev/null 2>&1 || continue
|
|
if "$p" -c "import tomllib" >/dev/null 2>&1; then
|
|
printf '%s' "$p"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
_harness_query() {
|
|
local py
|
|
py=$(_raccoon_python) || return 1
|
|
"$py" "$_HARNESS_REGISTRY_DIR/resolve_harness.py" "$@"
|
|
}
|
|
|
|
# The proxy root: the worker's ANTHROPIC_BASE_URL minus its provider path.
|
|
_harness_proxy_root() {
|
|
local base_url="${ANTHROPIC_BASE_URL:-}"
|
|
[ -n "$base_url" ] || return 1
|
|
base_url="${base_url%"${base_url##*[!/]}"}"
|
|
# ".../api/llm_proxy/raccoon" -> ".../api/llm_proxy". Requires a path to strip: a base
|
|
# URL that is a bare host with no path — a provider's own API root rather than the
|
|
# proxy — would yield "https:/", handed to codex as a base URL and failing obscurely.
|
|
case "${base_url#*://}" in
|
|
*/*) printf '%s' "${base_url%/*}" ;;
|
|
*) return 2 ;;
|
|
esac
|
|
}
|
|
|
|
harness_setup_credentials() {
|
|
# `|| rc=$?` and not a bare assignment: this is sourced into a `set -e` shell (see the
|
|
# note at the top), and a bare failing assignment would exit the caller's post-create
|
|
# outright — silently, since the failure paths below are what do the explaining.
|
|
local root rc=0
|
|
root="$(_harness_proxy_root)" || rc=$?
|
|
if [ "$rc" -ne 0 ]; then
|
|
if [ "$rc" -eq 2 ]; then
|
|
echo "harness-setup: ANTHROPIC_BASE_URL (${ANTHROPIC_BASE_URL:-}) has no provider" >&2
|
|
echo "harness-setup: path, so it is not the proxy URL other harnesses derive their" >&2
|
|
echo "harness-setup: credentials from. claude will work; codex will not be" >&2
|
|
echo "harness-setup: authenticated. Use the base URL you were given." >&2
|
|
else
|
|
echo "harness-setup: ANTHROPIC_BASE_URL unset — skipping credential derivation" >&2
|
|
fi
|
|
return 0
|
|
fi
|
|
local key="${ANTHROPIC_API_KEY:-}"
|
|
if [ -z "$key" ]; then
|
|
echo "harness-setup: ANTHROPIC_API_KEY unset — skipping credential derivation" >&2
|
|
return 0
|
|
fi
|
|
|
|
local id key_env base_url_env proxy_path
|
|
while IFS=$'\t' read -r id key_env base_url_env proxy_path; do
|
|
[ -n "$key_env" ] || continue
|
|
# ${!name} is an indirect expansion. Only set when empty: an explicit key wins.
|
|
if [ -z "${!key_env:-}" ]; then
|
|
export "$key_env=$key"
|
|
fi
|
|
if [ -n "$base_url_env" ] && [ -n "$proxy_path" ] && [ -z "${!base_url_env:-}" ]; then
|
|
export "$base_url_env=$root/$proxy_path"
|
|
fi
|
|
echo "harness-setup: $id credentials ready ($key_env, ${base_url_env:-no base url})" >&2
|
|
done < <(_harness_query --authoring-credentials 2>/dev/null || true)
|
|
}
|