fix(release): isolate Claude ACP subscription auth

This commit is contained in:
Vincent Koc
2026-07-06 02:58:59 -07:00
parent 3221d43d89
commit fa70403403
3 changed files with 80 additions and 10 deletions
@@ -2316,6 +2316,11 @@ jobs:
echo "OPENCLAW_TEST_CONSOLE=1" >> "$GITHUB_ENV"
;;
live-acp-bind-docker)
if [[ -n "${OPENCLAW_CLAUDE_CREDENTIALS_JSON:-}" || -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]]; then
echo "OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH=subscription" >> "$GITHUB_ENV"
else
echo "OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH=api-key" >> "$GITHUB_ENV"
fi
if [[ -n "${GEMINI_API_KEY:-}" || -n "${GOOGLE_API_KEY:-}" ]]; then
echo "OPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex,gemini" >> "$GITHUB_ENV"
else
@@ -2551,6 +2556,11 @@ jobs:
echo "OPENCLAW_TEST_CONSOLE=1" >> "$GITHUB_ENV"
;;
live-acp-bind-docker)
if [[ -n "${OPENCLAW_CLAUDE_CREDENTIALS_JSON:-}" || -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]]; then
echo "OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH=subscription" >> "$GITHUB_ENV"
else
echo "OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH=api-key" >> "$GITHUB_ENV"
fi
if [[ -n "${GEMINI_API_KEY:-}" || -n "${GOOGLE_API_KEY:-}" ]]; then
echo "OPENCLAW_LIVE_ACP_BIND_AGENTS=claude,codex,gemini" >> "$GITHUB_ENV"
else
+55 -9
View File
@@ -17,6 +17,7 @@ CONFIG_DIR="${OPENCLAW_CONFIG_DIR:-$HOME/.openclaw}"
WORKSPACE_DIR="${OPENCLAW_WORKSPACE_DIR:-$HOME/.openclaw/workspace}"
PROFILE_FILE="$(openclaw_live_default_profile_file)"
ACP_AGENT_LIST_RAW="${OPENCLAW_LIVE_ACP_BIND_AGENTS:-${OPENCLAW_LIVE_ACP_BIND_AGENT:-claude,codex,gemini}}"
ACP_CLAUDE_AUTH_MODE="${OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH:-auto}"
ACP_SETUP_TIMEOUT_SECONDS="$(openclaw_live_read_positive_int_env OPENCLAW_LIVE_ACP_BIND_SETUP_TIMEOUT_SECONDS 180)"
TEMP_DIRS=()
DOCKER_USER="${OPENCLAW_DOCKER_USER:-node}"
@@ -62,6 +63,15 @@ openclaw_live_acp_bind_resolve_agent_command() {
esac
}
case "$ACP_CLAUDE_AUTH_MODE" in
auto | api-key | subscription)
;;
*)
echo "ERROR: OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH must be one of: auto, api-key, subscription." >&2
exit 1
;;
esac
cleanup_temp_dirs() {
if ((${#TEMP_DIRS[@]} > 0)); then
rm -rf "${TEMP_DIRS[@]}"
@@ -174,6 +184,14 @@ fi
agent="${OPENCLAW_LIVE_ACP_BIND_AGENT:-claude}"
case "$agent" in
claude)
claude_auth_mode="${OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH:-auto}"
if [ "$claude_auth_mode" = "subscription" ]; then
unset ANTHROPIC_API_KEY
unset ANTHROPIC_API_KEY_OLD
unset ANTHROPIC_API_TOKEN
unset ANTHROPIC_AUTH_TOKEN
unset ANTHROPIC_OAUTH_TOKEN
fi
claude_code_version="$(
node -e 'const path = require("node:path"); const packagePath = path.join(path.dirname(require.resolve("@anthropic-ai/claude-agent-sdk")), "package.json"); process.stdout.write(require(packagePath).claudeCodeVersion);'
)"
@@ -197,11 +215,16 @@ case "$agent" in
cat > "$NPM_CONFIG_PREFIX/bin/claude" <<WRAP
#!/usr/bin/env bash
script_dir="\$(CDPATH= cd -- "\$(dirname -- "\$0")" && pwd)"
if [ -n "\${OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY:-}" ]; then
export ANTHROPIC_API_KEY="\${OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY}"
fi
if [ -n "\${OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY_OLD:-}" ]; then
export ANTHROPIC_API_KEY_OLD="\${OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY_OLD}"
if [ "\${OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH:-auto}" = "subscription" ]; then
unset ANTHROPIC_API_KEY ANTHROPIC_API_KEY_OLD ANTHROPIC_API_TOKEN
unset ANTHROPIC_AUTH_TOKEN ANTHROPIC_OAUTH_TOKEN
else
if [ -n "\${OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY:-}" ]; then
export ANTHROPIC_API_KEY="\${OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY}"
fi
if [ -n "\${OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY_OLD:-}" ]; then
export ANTHROPIC_API_KEY_OLD="\${OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY_OLD}"
fi
fi
exec "\$script_dir/claude-real" "\$@"
WRAP
@@ -369,6 +392,14 @@ for ACP_AGENT in "${ACP_AGENTS[@]}"; do
echo "ERROR: Droid Docker ACP bind requires FACTORY_API_KEY; Factory OAuth/keyring auth in ~/.factory is not portable into the container." >&2
exit 1
fi
CLAUDE_AUTH_MODE="$ACP_CLAUDE_AUTH_MODE"
if [[ "$ACP_AGENT" == "claude" && "$CLAUDE_AUTH_MODE" == "auto" ]]; then
if [[ -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" || -f "$HOME/.claude/.credentials.json" ]]; then
CLAUDE_AUTH_MODE="subscription"
else
CLAUDE_AUTH_MODE="api-key"
fi
fi
EXTERNAL_AUTH_MOUNTS=()
if ((${#AUTH_DIRS[@]} > 0)); then
@@ -396,6 +427,9 @@ for ACP_AGENT in "${ACP_AGENTS[@]}"; do
echo "==> Profile file: $PROFILE_STATUS"
echo "==> Auth dirs: ${AUTH_DIRS_CSV:-none}"
echo "==> Auth files: ${AUTH_FILES_CSV:-none}"
if [[ "$ACP_AGENT" == "claude" ]]; then
echo "==> Claude auth mode: $CLAUDE_AUTH_MODE"
fi
if openclaw_live_uses_managed_bind_dirs; then
openclaw_live_chown_bind_dirs_for_container_user \
"$LIVE_IMAGE_NAME" \
@@ -406,13 +440,24 @@ for ACP_AGENT in "${ACP_AGENTS[@]}"; do
fi
DOCKER_RUN_ARGS=()
openclaw_live_init_docker_run_args DOCKER_RUN_ARGS "${OPENCLAW_LIVE_ACP_BIND_DOCKER_RUN_TIMEOUT:-2700s}"
DOCKER_AUTH_ENV=()
if [[ "$ACP_AGENT" == "claude" && "$CLAUDE_AUTH_MODE" == "subscription" ]]; then
DOCKER_AUTH_ENV+=(
-e CLAUDE_CODE_OAUTH_TOKEN="${CLAUDE_CODE_OAUTH_TOKEN:-}"
-e OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH="$CLAUDE_AUTH_MODE"
)
elif [[ "$ACP_AGENT" == "claude" ]]; then
DOCKER_AUTH_ENV+=(
-e ANTHROPIC_API_KEY
-e ANTHROPIC_API_KEY_OLD
-e OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}"
-e OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY_OLD="${ANTHROPIC_API_KEY_OLD:-}"
-e OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH="$CLAUDE_AUTH_MODE"
)
fi
DOCKER_RUN_ARGS+=(--rm -t \
-u "$DOCKER_USER" \
--entrypoint bash \
-e ANTHROPIC_API_KEY \
-e ANTHROPIC_API_KEY_OLD \
-e OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}" \
-e OPENCLAW_LIVE_ACP_BIND_ANTHROPIC_API_KEY_OLD="${ANTHROPIC_API_KEY_OLD:-}" \
-e GEMINI_API_KEY \
-e GOOGLE_API_KEY \
-e FACTORY_API_KEY \
@@ -448,6 +493,7 @@ for ACP_AGENT in "${ACP_AGENTS[@]}"; do
-e OPENCLAW_LIVE_ACP_SPAWN_DEFAULTS_THINKING="${OPENCLAW_LIVE_ACP_SPAWN_DEFAULTS_THINKING:-}" \
-e OPENCLAW_LIVE_ACP_SPAWN_DEFAULTS_TIMEOUT_MS="${OPENCLAW_LIVE_ACP_SPAWN_DEFAULTS_TIMEOUT_MS:-}" \
-e OPENCLAW_LIVE_ACP_BIND_AGENT_COMMAND="$AGENT_COMMAND")
openclaw_live_append_array DOCKER_RUN_ARGS DOCKER_AUTH_ENV
openclaw_live_append_array DOCKER_RUN_ARGS DOCKER_HOME_MOUNT
openclaw_live_append_array DOCKER_RUN_ARGS DOCKER_TRUSTED_HARNESS_MOUNT
DOCKER_RUN_ARGS+=(\
@@ -1098,6 +1098,20 @@ describe("package artifact reuse", () => {
expect(readFileSync("scripts/test-live-acp-bind-docker.sh", "utf8")).toContain(
'run_setup_command npm install -g "@anthropic-ai/claude-code@$claude_code_version"',
);
const acpBindScript = readFileSync("scripts/test-live-acp-bind-docker.sh", "utf8");
expect(acpBindScript).toContain(
"OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH must be one of: auto, api-key, subscription.",
);
expect(acpBindScript).toContain(
'if [[ "$ACP_AGENT" == "claude" && "$CLAUDE_AUTH_MODE" == "subscription" ]]; then',
);
expect(acpBindScript).toContain(
"unset ANTHROPIC_API_KEY ANTHROPIC_API_KEY_OLD ANTHROPIC_API_TOKEN",
);
expect(acpBindScript).toContain('-e CLAUDE_CODE_OAUTH_TOKEN="${CLAUDE_CODE_OAUTH_TOKEN:-}"');
expect(acpBindScript).not.toContain(" -e ANTHROPIC_API_KEY \\\n");
expect(workflow.match(/OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH=subscription/g)).toHaveLength(2);
expect(workflow.match(/OPENCLAW_LIVE_ACP_BIND_CLAUDE_AUTH=api-key/g)).toHaveLength(2);
expect(readFileSync("scripts/test-live-acp-bind-docker.sh", "utf8")).toContain(
"run_setup_command bash -lc 'curl -fsSL https://app.factory.ai/cli | sh'",
);
@@ -1283,7 +1297,7 @@ describe("package artifact reuse", () => {
reusableWorkflow.match(
/if \[\[ -n "\$\{OPENCLAW_CLAUDE_CREDENTIALS_JSON:-\}" \|\| -n "\$\{CLAUDE_CODE_OAUTH_TOKEN:-\}" \]\]; then/g,
),
).toHaveLength(2);
).toHaveLength(4);
});
it("finalizes Testbox delegation even when setup or the remote command fails", () => {