Files
agent-runtime-framework/harnesses/contexts/z-ai/v1/init.sh
Paul O'Reilly 455d8d135b fix(z-ai): wire auth_token via apiKeyHelper, never via env
Mirrors the minimax fix to z-ai. Replaces bin/anthropic-compat-wrapper.sh
(which did `exec env ANTHROPIC_AUTH_TOKEN="$(cat ...)" claude "$@"`,
exposing the secret in the claude subprocess' /proc/<pid>/environ) with
init.sh that writes ~/.claude/settings.json with:

  apiKeyHelper: "cat /run/agent/secrets/z-ai/auth_token"

Claude Code routes apiKeyHelper output to `Authorization: Bearer <value>`
when ANTHROPIC_BASE_URL is non-anthropic.com — exactly what the Z.ai
proxy at api.z.ai/api/anthropic requires.

The legacy K8s Secret may still ship a `base_url` file; it is
intentionally ignored by init.sh (the base URL is not a credential and
lives in harness.yaml).

Mirrors agent-runtimes commit (z-ai apiKeyHelper). CRS serves these
harness files to dispatchers, so this repo must match.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 13:47:52 +12:00

54 lines
1.8 KiB
Bash
Executable File

#!/bin/bash
# z-ai init — write ~/.claude/settings.json with apiKeyHelper.
#
# The Z.ai auth_token is mounted by ESO at
# /run/agent/secrets/z-ai/auth_token (mode 0400, secrets_required entry in
# harness.yaml). Claude Code's `apiKeyHelper` setting names a command that
# prints the key on stdout when the CLI needs it for an API request — the
# value never enters this process' environment, never appears in the claude
# subprocess' /proc/<pid>/environ, and is read fresh on each invocation so
# ESO secret rotations are picked up without a process restart.
#
# When ANTHROPIC_BASE_URL points at a non-anthropic.com host (set in
# harness.yaml to https://api.z.ai/api/anthropic), Claude Code routes
# apiKeyHelper output to `Authorization: Bearer <value>`, which is the
# header shape the Z.ai proxy requires.
#
# The K8s Secret may also contain a `base_url` file (legacy from the
# wrapper-script era) — it is intentionally ignored. The base URL is not a
# credential; it lives in harness.yaml.
set -euo pipefail
API_KEY_FILE="/run/agent/secrets/z-ai/auth_token"
if [ ! -r "$API_KEY_FILE" ]; then
echo "ERROR: $API_KEY_FILE not readable. Check ESO ExternalSecret acct-<z-ai-id>." >&2
exit 1
fi
CONFIG_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
mkdir -p "$CONFIG_DIR"
chmod 0700 "$CONFIG_DIR"
SETTINGS_FILE="$CONFIG_DIR/settings.json"
# Merge into an existing settings.json (from another harness layer) when
# possible; otherwise create a fresh one.
if [ -f "$SETTINGS_FILE" ] && command -v jq >/dev/null 2>&1; then
TMP=$(mktemp)
jq --arg helper "cat $API_KEY_FILE" \
'. + {apiKeyHelper: $helper}' \
"$SETTINGS_FILE" > "$TMP"
mv "$TMP" "$SETTINGS_FILE"
else
cat > "$SETTINGS_FILE" <<EOF
{
"apiKeyHelper": "cat $API_KEY_FILE"
}
EOF
fi
chmod 0600 "$SETTINGS_FILE"
echo "z-ai auth_token wired via apiKeyHelper at $SETTINGS_FILE"