mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 17:53:39 +00:00
## What Problem This Solves Repository scripts retain private copies of shared tooling helpers and an unused translation subprocess runner, increasing maintenance work across sibling scripts. ## User Impact Internal tooling cleanup: existing flags, diagnostics, generated bytes, JSON formats, exit codes, and cleanup policies stay the same. The build wrapper additionally detects forbidden dynamic-import warnings when compiler output splits the warning marker across chunks. ## Why This Change Was Made - Remove the retired i18n process runner. Its final production caller moved to the shared formatter in #95534; retain real CLI/privacy/provider tests and run their subprocesses with the existing dependency. - Share Docker resource, signal-trap, platform, workspace-staging, and plugin-selection helpers while retaining each caller's environment precedence and lifecycle decisions. - Reuse existing E2E fixture JSON/assertion and package-path helpers; retain distinct write modes, recovery ordering, and mounted/frozen harness contracts. - Share macOS guest desktop-user/home resolution through its existing owner while preserving per-caller timeout policy. - Route release/mobile flags through the existing version flag specifications, preserving split-only values, duplicate/mode rules, help timing, and error text. Reuse existing retry sleep and comparator owners and remove an unreachable iOS output branch. - Reuse existing guard entrypoint, failure-trailer, diagnostic-line, and metadata-normalization owners. Measured reduction: **732 net production lines**, with test changes counted separately. PR tooling and its protected import closure, CI planners/shards, baselines, and generated artifacts are unchanged. ## Fixes Found Along the Way The tsdown scanner checked each raw output chunk for its warning marker. It now checks the existing combined-line buffer. The regression exercises every split inside the marker and fails on the original source for the intended missing-warning assertion. ## Evidence - Blacksmith Testbox `tbx_01m3tp4sabwd0807kj9jkqqmbr`: frozen dependency install and candidate source-byte verification; all nine changed test files and 59 selected sibling files passed, including real CLI, package fixture, recovery, Docker harness, and Parallels transport contracts. - Generated channel metadata is byte-identical; differential metadata normalization cases passed. - SDK surface check passed. Independent isolated Codex review completed with no P0–P2 findings. - Initial changed checks caught an invalid direct source import in a proposed snapshot-distance consolidation; that independent change was withdrawn. No boundary exception was added. The final changed checks pass, including script/test lint and Docker shell/scheduler checks; madge reports 0 cycles and the runtime import check reports 0 cycles. - Per-file single-worker wall time for changed suites: translation 9.92s; Docker helper 38.88s; live Docker auth 1.71s; mobile ref 2.36s; mobile release 6.23s; release preparation 2.42s; version 2.04s; installer 15.01s; tsdown 2.70s. The existing Docker helper suite executes shell/process cleanup and container-command boundary fixtures; new assertions reuse those fixtures. New parser/scanner cases use no sleeps or polling. Hosted CI will be verified against this PR's exact pushed head. No live deployment or release was performed.
393 lines
18 KiB
Bash
393 lines
18 KiB
Bash
#!/usr/bin/env bash
|
|
# Bash 5.3+ can deadlock writing heredoc pipes on macOS before the reader starts.
|
|
if [[ ${OSTYPE:-} == darwin* && $BASH != /bin/bash ]] && ((BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3))); then
|
|
exec /bin/bash "$0" "$@"
|
|
fi
|
|
set -euo pipefail
|
|
|
|
SCRIPT_ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
ROOT_DIR="${OPENCLAW_LIVE_DOCKER_REPO_ROOT:-$SCRIPT_ROOT_DIR}"
|
|
ROOT_DIR="$(cd "$ROOT_DIR" && pwd)"
|
|
TRUSTED_HARNESS_DIR="${OPENCLAW_LIVE_DOCKER_TRUSTED_HARNESS_DIR:-$SCRIPT_ROOT_DIR}"
|
|
if [[ -z "$TRUSTED_HARNESS_DIR" || ! -d "$TRUSTED_HARNESS_DIR" ]]; then
|
|
echo "ERROR: trusted live Docker harness directory not found: ${TRUSTED_HARNESS_DIR:-<empty>}." >&2
|
|
exit 1
|
|
fi
|
|
TRUSTED_HARNESS_DIR="$(cd "$TRUSTED_HARNESS_DIR" && pwd)"
|
|
source "$TRUSTED_HARNESS_DIR/scripts/lib/live-docker-auth.sh"
|
|
IMAGE_NAME="${OPENCLAW_IMAGE:-openclaw:local}"
|
|
LIVE_IMAGE_NAME="${OPENCLAW_LIVE_IMAGE:-${IMAGE_NAME}-live}"
|
|
CONFIG_DIR="${OPENCLAW_CONFIG_DIR:-$HOME/.openclaw}"
|
|
WORKSPACE_DIR="${OPENCLAW_WORKSPACE_DIR:-$HOME/.openclaw/workspace}"
|
|
PROFILE_FILE="$(openclaw_live_default_profile_file)"
|
|
DEFAULT_PROVIDER="${OPENCLAW_DOCKER_CLI_BACKEND_PROVIDER:-claude-cli}"
|
|
CLI_MODEL="${OPENCLAW_LIVE_CLI_BACKEND_MODEL:-}"
|
|
CLI_PROVIDER="${CLI_MODEL%%/*}"
|
|
CLI_DISABLE_MCP_CONFIG="${OPENCLAW_LIVE_CLI_BACKEND_DISABLE_MCP_CONFIG:-}"
|
|
CLI_AUTH_MODE="${OPENCLAW_LIVE_CLI_BACKEND_AUTH:-auto}"
|
|
CLI_SETUP_TIMEOUT_SECONDS="$(openclaw_live_read_positive_int_env OPENCLAW_LIVE_CLI_BACKEND_SETUP_TIMEOUT_SECONDS 180)"
|
|
DOCKER_EXTRA_ENV_FILES=()
|
|
DOCKER_AUTH_PRESTAGED=0
|
|
DOCKER_TRUSTED_HARNESS_CONTAINER_DIR="/trusted-harness"
|
|
DOCKER_TRUSTED_HARNESS_MOUNT=(-v "$TRUSTED_HARNESS_DIR":"$DOCKER_TRUSTED_HARNESS_CONTAINER_DIR":ro)
|
|
|
|
if [[ -z "$CLI_PROVIDER" || "$CLI_PROVIDER" == "$CLI_MODEL" ]]; then
|
|
CLI_PROVIDER="$DEFAULT_PROVIDER"
|
|
fi
|
|
if [[ -f "$PROFILE_FILE" && -r "$PROFILE_FILE" ]]; then
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
source "$PROFILE_FILE"
|
|
set +a
|
|
fi
|
|
|
|
case "$CLI_AUTH_MODE" in
|
|
auto | api-key | subscription)
|
|
;;
|
|
*)
|
|
echo "ERROR: OPENCLAW_LIVE_CLI_BACKEND_AUTH must be one of: auto, api-key, subscription." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
if [[ "$CLI_AUTH_MODE" == "subscription" && "$CLI_PROVIDER" != "claude-cli" ]]; then
|
|
echo "ERROR: OPENCLAW_LIVE_CLI_BACKEND_AUTH=subscription is only supported for claude-cli." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$CLI_PROVIDER" == "codex-cli" ]]; then
|
|
echo "ERROR: codex-cli is no longer a bundled CLI backend. Use openai/* with the Codex app-server runtime instead." >&2
|
|
exit 1
|
|
fi
|
|
|
|
CLI_METADATA_JSON="$(node --import tsx "$ROOT_DIR/scripts/print-cli-backend-live-metadata.ts" "$CLI_PROVIDER")"
|
|
read_metadata_field() {
|
|
local field="$1"
|
|
node -e 'const data = JSON.parse(process.argv[1]); const field = process.argv[2]; const value = data?.[field]; if (value == null) process.exit(1); process.stdout.write(typeof value === "string" ? value : JSON.stringify(value));' \
|
|
"$CLI_METADATA_JSON" \
|
|
"$field"
|
|
}
|
|
|
|
DEFAULT_MODEL="$(read_metadata_field defaultModelRef 2>/dev/null || printf '%s' 'claude-cli/claude-sonnet-4-6')"
|
|
CLI_MODEL="${CLI_MODEL:-$DEFAULT_MODEL}"
|
|
CLI_DEFAULT_COMMAND="$(read_metadata_field command 2>/dev/null || true)"
|
|
CLI_DOCKER_NPM_PACKAGE="$(read_metadata_field dockerNpmPackage 2>/dev/null || true)"
|
|
CLI_DOCKER_BINARY_NAME="$(read_metadata_field dockerBinaryName 2>/dev/null || true)"
|
|
|
|
if [[ "$CLI_PROVIDER" == "claude-cli" && -z "$CLI_DISABLE_MCP_CONFIG" ]]; then
|
|
if [[ "$CLI_AUTH_MODE" == "subscription" ]]; then
|
|
CLI_DISABLE_MCP_CONFIG="1"
|
|
else
|
|
CLI_DISABLE_MCP_CONFIG="0"
|
|
fi
|
|
fi
|
|
export OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE:-0}"
|
|
export OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE:-0}"
|
|
export OPENCLAW_LIVE_CLI_BACKEND_MCP_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_MCP_PROBE:-0}"
|
|
|
|
openclaw_live_init_temp_dirs
|
|
openclaw_live_init_cli_tools_dir
|
|
openclaw_live_init_cache_home_dir
|
|
openclaw_live_init_managed_home
|
|
|
|
if [[ "$CLI_PROVIDER" == "claude-cli" && "$CLI_AUTH_MODE" == "subscription" ]]; then
|
|
CLAUDE_CREDS_FILE="$HOME/.claude/.credentials.json"
|
|
CLAUDE_SUBSCRIPTION_AUTH_SOURCE=""
|
|
CLAUDE_SUBSCRIPTION_TYPE=""
|
|
if [[ -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]]; then
|
|
CLAUDE_SUBSCRIPTION_TYPE="oauth-token"
|
|
CLAUDE_SUBSCRIPTION_AUTH_SOURCE="env-token"
|
|
elif [[ -f "$CLAUDE_CREDS_FILE" ]]; then
|
|
CLAUDE_SUBSCRIPTION_TYPE="$(
|
|
node -e '
|
|
const fs = require("node:fs");
|
|
const file = process.argv[1];
|
|
const data = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
const subscriptionType = String(data?.claudeAiOauth?.subscriptionType ?? "").trim();
|
|
if (!subscriptionType || subscriptionType === "unknown") process.exit(2);
|
|
process.stdout.write(subscriptionType);
|
|
' "$CLAUDE_CREDS_FILE" 2>/dev/null
|
|
)" || {
|
|
echo "ERROR: $CLAUDE_CREDS_FILE does not look like Claude subscription OAuth auth." >&2
|
|
echo "Expected claudeAiOauth.subscriptionType to be present." >&2
|
|
exit 1
|
|
}
|
|
CLAUDE_SUBSCRIPTION_AUTH_SOURCE="credentials-file"
|
|
else
|
|
echo "ERROR: Claude subscription auth requires either:" >&2
|
|
echo " - $CLAUDE_CREDS_FILE with claudeAiOauth.subscriptionType, or" >&2
|
|
echo " - CLAUDE_CODE_OAUTH_TOKEN from 'claude setup-token'." >&2
|
|
exit 1
|
|
fi
|
|
if [[ -z "${OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV:-}" ]]; then
|
|
if [[ "$CLAUDE_SUBSCRIPTION_AUTH_SOURCE" == "env-token" ]]; then
|
|
export OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV='["CLAUDE_CODE_OAUTH_TOKEN"]'
|
|
else
|
|
export OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV="[]"
|
|
fi
|
|
fi
|
|
if [[ "$OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV" == *ANTHROPIC_API_KEY* ]]; then
|
|
echo "ERROR: subscription auth smoke must not preserve Anthropic API-key env vars." >&2
|
|
exit 1
|
|
fi
|
|
if [[ "$CLAUDE_SUBSCRIPTION_AUTH_SOURCE" == "env-token" && "$OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV" != *CLAUDE_CODE_OAUTH_TOKEN* ]]; then
|
|
echo "ERROR: CLAUDE_CODE_OAUTH_TOKEN subscription smoke must preserve CLAUDE_CODE_OAUTH_TOKEN for the Gateway child process." >&2
|
|
exit 1
|
|
fi
|
|
export OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE:-0}"
|
|
export OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE:-1}"
|
|
export OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE:-0}"
|
|
export OPENCLAW_LIVE_CLI_BACKEND_MCP_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_MCP_PROBE:-0}"
|
|
fi
|
|
|
|
openclaw_live_init_profile_mount
|
|
|
|
ensure_live_build_extension() {
|
|
local extension="$1"
|
|
local current="${OPENCLAW_DOCKER_BUILD_EXTENSIONS:-${OPENCLAW_EXTENSIONS:-}}"
|
|
case " ${current//,/ } " in
|
|
*" $extension "*) ;;
|
|
*) export OPENCLAW_DOCKER_BUILD_EXTENSIONS="${current:+$current }$extension" ;;
|
|
esac
|
|
}
|
|
|
|
if [[ "$CLI_PROVIDER" == "claude-cli" ]]; then
|
|
ensure_live_build_extension anthropic
|
|
fi
|
|
|
|
openclaw_live_collect_auth_for_providers "$CLI_PROVIDER"
|
|
if [[ "${CLAUDE_SUBSCRIPTION_AUTH_SOURCE:-}" == "env-token" ]]; then
|
|
retained_auth_files=()
|
|
for auth_file in ${AUTH_FILES[@]+"${AUTH_FILES[@]}"}; do
|
|
case "$auth_file" in
|
|
.claude.json | .claude/.credentials.json) ;;
|
|
*) retained_auth_files+=("$auth_file") ;;
|
|
esac
|
|
done
|
|
AUTH_FILES=(${retained_auth_files[@]+"${retained_auth_files[@]}"})
|
|
fi
|
|
openclaw_live_finalize_auth_mounts
|
|
|
|
read -r -d '' LIVE_TEST_CMD <<'EOF' || true
|
|
set -euo pipefail
|
|
[ -f "$HOME/.profile" ] && [ -r "$HOME/.profile" ] && source "$HOME/.profile" || true
|
|
export NPM_CONFIG_PREFIX="${NPM_CONFIG_PREFIX:-$HOME/.npm-global}"
|
|
export npm_config_prefix="$NPM_CONFIG_PREFIX"
|
|
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
|
|
export COREPACK_HOME="${COREPACK_HOME:-$XDG_CACHE_HOME/node/corepack}"
|
|
export NPM_CONFIG_CACHE="${NPM_CONFIG_CACHE:-$XDG_CACHE_HOME/npm}"
|
|
export npm_config_cache="$NPM_CONFIG_CACHE"
|
|
mkdir -p "$NPM_CONFIG_PREFIX" "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE"
|
|
chmod 700 "$XDG_CACHE_HOME" "$COREPACK_HOME" "$NPM_CONFIG_CACHE" || true
|
|
export PATH="$NPM_CONFIG_PREFIX/bin:$PATH"
|
|
trusted_scripts_dir="${OPENCLAW_LIVE_DOCKER_SCRIPTS_DIR:-/src/scripts}"
|
|
source "$trusted_scripts_dir/lib/live-docker-stage.sh"
|
|
openclaw_live_stage_mounted_auth
|
|
provider="${OPENCLAW_DOCKER_CLI_BACKEND_PROVIDER:-claude-cli}"
|
|
default_command="${OPENCLAW_DOCKER_CLI_BACKEND_COMMAND_DEFAULT:-}"
|
|
docker_package="${OPENCLAW_DOCKER_CLI_BACKEND_NPM_PACKAGE:-}"
|
|
binary_name="${OPENCLAW_DOCKER_CLI_BACKEND_BINARY_NAME:-}"
|
|
if [ -z "$binary_name" ] && [ -n "$default_command" ]; then
|
|
binary_name="$(basename "$default_command")"
|
|
fi
|
|
if [ -z "${OPENCLAW_LIVE_CLI_BACKEND_COMMAND:-}" ] && [ -n "$binary_name" ]; then
|
|
export OPENCLAW_LIVE_CLI_BACKEND_COMMAND="$NPM_CONFIG_PREFIX/bin/$binary_name"
|
|
fi
|
|
openclaw_live_prepare_cli_backend \
|
|
"${OPENCLAW_LIVE_CLI_BACKEND_COMMAND:?missing CLI backend command}" \
|
|
"$docker_package" "$OPENCLAW_LIVE_CLI_BACKEND_SETUP_TIMEOUT_SECONDS"
|
|
if [ -n "${OPENCLAW_LIVE_CLI_BACKEND_COMMAND:-}" ] && [ -x "${OPENCLAW_LIVE_CLI_BACKEND_COMMAND}" ]; then
|
|
echo "==> CLI backend binary: ${OPENCLAW_LIVE_CLI_BACKEND_COMMAND}"
|
|
"${OPENCLAW_LIVE_CLI_BACKEND_COMMAND}" -V || "${OPENCLAW_LIVE_CLI_BACKEND_COMMAND}" --version || true
|
|
fi
|
|
if [ "$provider" = "google-gemini-cli" ]; then
|
|
openclaw_live_stage_gemini_auth
|
|
fi
|
|
if [ "$provider" = "claude-cli" ]; then
|
|
auth_mode="${OPENCLAW_LIVE_CLI_BACKEND_AUTH:-auto}"
|
|
if [ "$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
|
|
node - <<'NODE'
|
|
const fs = require("node:fs");
|
|
const file = `${process.env.HOME}/.claude/.credentials.json`;
|
|
if (process.env.CLAUDE_CODE_OAUTH_TOKEN?.trim()) {
|
|
console.error("[claude-subscription] using CLAUDE_CODE_OAUTH_TOKEN from environment");
|
|
} else if (fs.existsSync(file)) {
|
|
const data = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
const subscriptionType = String(data?.claudeAiOauth?.subscriptionType ?? "").trim();
|
|
if (!subscriptionType || subscriptionType === "unknown") {
|
|
throw new Error("Claude subscription OAuth credentials are missing subscriptionType.");
|
|
}
|
|
console.error(`[claude-subscription] subscriptionType=${subscriptionType}`);
|
|
} else {
|
|
throw new Error("Claude subscription OAuth token or credentials file is required.");
|
|
}
|
|
NODE
|
|
fi
|
|
real_claude="$NPM_CONFIG_PREFIX/bin/claude-real"
|
|
if [ ! -x "$real_claude" ] && [ -x "$NPM_CONFIG_PREFIX/bin/claude" ]; then
|
|
mv "$NPM_CONFIG_PREFIX/bin/claude" "$real_claude"
|
|
fi
|
|
if [ -x "$real_claude" ]; then
|
|
cat > "$NPM_CONFIG_PREFIX/bin/claude" <<WRAP
|
|
#!/usr/bin/env bash
|
|
script_dir="\$(CDPATH= cd -- "\$(dirname -- "\$0")" && pwd)"
|
|
if [ -n "\${OPENCLAW_LIVE_CLI_BACKEND_ANTHROPIC_API_KEY:-}" ]; then
|
|
export ANTHROPIC_API_KEY="\${OPENCLAW_LIVE_CLI_BACKEND_ANTHROPIC_API_KEY}"
|
|
fi
|
|
if [ -n "\${OPENCLAW_LIVE_CLI_BACKEND_ANTHROPIC_API_KEY_OLD:-}" ]; then
|
|
export ANTHROPIC_API_KEY_OLD="\${OPENCLAW_LIVE_CLI_BACKEND_ANTHROPIC_API_KEY_OLD}"
|
|
fi
|
|
exec "\$script_dir/claude-real" "\$@"
|
|
WRAP
|
|
chmod +x "$NPM_CONFIG_PREFIX/bin/claude"
|
|
fi
|
|
if [ -z "${OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV:-}" ]; then
|
|
export OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV='["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_OLD"]'
|
|
fi
|
|
if [ "$auth_mode" = "subscription" ]; then
|
|
claude --version
|
|
direct_probe_log="$(mktemp)"
|
|
set +e
|
|
claude \
|
|
-p "This is a local CLI smoke test. What is two plus two? Reply with only the result." \
|
|
--output-format text \
|
|
--model sonnet \
|
|
--permission-mode bypassPermissions \
|
|
--setting-sources user \
|
|
--strict-mcp-config \
|
|
--mcp-config '{"mcpServers":{}}' \
|
|
--no-session-persistence >"$direct_probe_log" 2>&1
|
|
direct_probe_status=$?
|
|
set -e
|
|
print_redacted_direct_probe_log() {
|
|
sed -E \
|
|
-e 's/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/<redacted-email>/g' \
|
|
-e 's/(sk-ant-|sk-)[A-Za-z0-9_-]+/<redacted-secret>/g' \
|
|
"$direct_probe_log" >&2
|
|
}
|
|
if [ "$direct_probe_status" -ne 0 ]; then
|
|
echo "ERROR: direct Claude subscription probe exited with status $direct_probe_status." >&2
|
|
print_redacted_direct_probe_log
|
|
rm -f "$direct_probe_log"
|
|
exit "$direct_probe_status"
|
|
fi
|
|
if ! grep -Eiq '(^|[^[:alnum:]])(4|four)([^[:alnum:]]|$)' "$direct_probe_log"; then
|
|
echo "ERROR: direct Claude subscription probe did not return the expected arithmetic result." >&2
|
|
print_redacted_direct_probe_log
|
|
rm -f "$direct_probe_log"
|
|
exit 1
|
|
fi
|
|
rm -f "$direct_probe_log"
|
|
echo "[claude-subscription] direct claude -p probe ok"
|
|
else
|
|
claude auth status || true
|
|
fi
|
|
fi
|
|
tmp_dir="$(mktemp -d)"
|
|
openclaw_live_stage_workspace "$tmp_dir"
|
|
cd "$tmp_dir"
|
|
openclaw_live_run_staged_script scripts/test-live -- src/gateway/gateway-cli-backend.live.test.ts
|
|
EOF
|
|
|
|
OPENCLAW_LIVE_DOCKER_REPO_ROOT="$ROOT_DIR" "$TRUSTED_HARNESS_DIR/scripts/test-live-build-docker.sh"
|
|
if openclaw_live_uses_managed_bind_dirs; then
|
|
openclaw_live_chown_bind_dirs_for_container_user \
|
|
"$LIVE_IMAGE_NAME" \
|
|
"$DOCKER_USER" \
|
|
"$CLI_TOOLS_DIR" \
|
|
"$CACHE_HOME_DIR" \
|
|
"${DOCKER_HOME_DIR:-}"
|
|
fi
|
|
|
|
echo "==> Run CLI backend live test in Docker"
|
|
echo "==> Model: $CLI_MODEL"
|
|
echo "==> Provider: $CLI_PROVIDER"
|
|
echo "==> Auth mode: $CLI_AUTH_MODE"
|
|
echo "==> Setup timeout: ${CLI_SETUP_TIMEOUT_SECONDS}s"
|
|
echo "==> Profile file: $PROFILE_STATUS"
|
|
if [[ "$CLI_PROVIDER" == "claude-cli" && "$CLI_AUTH_MODE" == "subscription" ]]; then
|
|
echo "==> Claude subscription: $CLAUDE_SUBSCRIPTION_TYPE"
|
|
echo "==> Claude subscription source: $CLAUDE_SUBSCRIPTION_AUTH_SOURCE"
|
|
fi
|
|
echo "==> External auth dirs: ${AUTH_DIRS_CSV:-none}"
|
|
echo "==> External auth files: ${AUTH_FILES_CSV:-none}"
|
|
DOCKER_AUTH_ENV=(
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_AUTH="$CLI_AUTH_MODE"
|
|
)
|
|
if [[ "$CLI_PROVIDER" == "claude-cli" && "$CLI_AUTH_MODE" == "subscription" ]]; then
|
|
DOCKER_AUTH_ENV+=(
|
|
-e CLAUDE_CODE_OAUTH_TOKEN="${CLAUDE_CODE_OAUTH_TOKEN:-}"
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV="$OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV"
|
|
)
|
|
else
|
|
DOCKER_AUTH_ENV+=(
|
|
-e ANTHROPIC_API_KEY
|
|
-e ANTHROPIC_API_KEY_OLD
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:-}"
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_ANTHROPIC_API_KEY_OLD="${ANTHROPIC_API_KEY_OLD:-}"
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV="${OPENCLAW_LIVE_CLI_BACKEND_PRESERVE_ENV:-}"
|
|
)
|
|
fi
|
|
|
|
DOCKER_RUN_ARGS=()
|
|
openclaw_live_init_docker_run_args DOCKER_RUN_ARGS "${OPENCLAW_LIVE_CLI_BACKEND_DOCKER_RUN_TIMEOUT:-2700s}"
|
|
DOCKER_RUN_ARGS+=(--rm -t \
|
|
-u "$DOCKER_USER" \
|
|
--entrypoint bash \
|
|
-e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
|
|
-e HOME=/home/node \
|
|
-e NODE_OPTIONS="$(openclaw_live_container_node_options)" \
|
|
-e OPENCLAW_SKIP_CHANNELS=1 \
|
|
-e OPENCLAW_VITEST_FS_MODULE_CACHE=0 \
|
|
-e OPENCLAW_DOCKER_AUTH_PRESTAGED="$DOCKER_AUTH_PRESTAGED" \
|
|
-e OPENCLAW_DOCKER_AUTH_DIRS_RESOLVED="$AUTH_DIRS_CSV" \
|
|
-e OPENCLAW_DOCKER_AUTH_FILES_RESOLVED="$AUTH_FILES_CSV" \
|
|
-e OPENCLAW_LIVE_DOCKER_SCRIPTS_DIR="${DOCKER_TRUSTED_HARNESS_CONTAINER_DIR}/scripts" \
|
|
-e OPENCLAW_LIVE_DOCKER_SOURCE_STAGE_MODE="${OPENCLAW_LIVE_DOCKER_SOURCE_STAGE_MODE:-copy}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_SETUP_TIMEOUT_SECONDS="$CLI_SETUP_TIMEOUT_SECONDS" \
|
|
-e OPENCLAW_DOCKER_CLI_BACKEND_PROVIDER="$CLI_PROVIDER" \
|
|
-e OPENCLAW_DOCKER_CLI_BACKEND_COMMAND_DEFAULT="$CLI_DEFAULT_COMMAND" \
|
|
-e OPENCLAW_DOCKER_CLI_BACKEND_NPM_PACKAGE="$CLI_DOCKER_NPM_PACKAGE" \
|
|
-e OPENCLAW_DOCKER_CLI_BACKEND_BINARY_NAME="$CLI_DOCKER_BINARY_NAME" \
|
|
-e OPENCLAW_LIVE_TEST=1 \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND=1 \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_DEBUG="${OPENCLAW_LIVE_CLI_BACKEND_DEBUG:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_ADVISORY="${OPENCLAW_LIVE_CLI_BACKEND_ADVISORY:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_ALLOW_PROVIDER_SKIP="${OPENCLAW_LIVE_CLI_BACKEND_ALLOW_PROVIDER_SKIP:-}" \
|
|
-e OPENCLAW_CLI_BACKEND_LOG_OUTPUT="${OPENCLAW_CLI_BACKEND_LOG_OUTPUT:-}" \
|
|
-e OPENCLAW_TEST_CONSOLE="${OPENCLAW_TEST_CONSOLE:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_MODEL="$CLI_MODEL" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_COMMAND="${OPENCLAW_LIVE_CLI_BACKEND_COMMAND:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_ARGS="${OPENCLAW_LIVE_CLI_BACKEND_ARGS:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS="${OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_CLEAR_ENV="${OPENCLAW_LIVE_CLI_BACKEND_CLEAR_ENV:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_DISABLE_MCP_CONFIG="$CLI_DISABLE_MCP_CONFIG" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_CACHE_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_CACHE_PROBE:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_RESUME_PROBE:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_MODEL_SWITCH_PROBE:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_IMAGE_PROBE:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_MCP_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_MCP_PROBE:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_MCP_SCHEMA_PROBE="${OPENCLAW_LIVE_CLI_BACKEND_MCP_SCHEMA_PROBE:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG="${OPENCLAW_LIVE_CLI_BACKEND_IMAGE_ARG:-}" \
|
|
-e OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE="${OPENCLAW_LIVE_CLI_BACKEND_IMAGE_MODE:-}")
|
|
openclaw_live_append_array DOCKER_RUN_ARGS DOCKER_HOME_MOUNT
|
|
openclaw_live_append_array DOCKER_RUN_ARGS DOCKER_EXTRA_ENV_FILES
|
|
openclaw_live_append_array DOCKER_RUN_ARGS DOCKER_TRUSTED_HARNESS_MOUNT
|
|
DOCKER_RUN_ARGS+=(\
|
|
-v "$CACHE_HOME_DIR":/home/node/.cache \
|
|
-v "$ROOT_DIR":/src:ro \
|
|
-v "$CONFIG_DIR":/home/node/.openclaw \
|
|
-v "$WORKSPACE_DIR":/home/node/.openclaw/workspace \
|
|
-v "$CLI_TOOLS_DIR":/home/node/.npm-global)
|
|
openclaw_live_append_array DOCKER_RUN_ARGS EXTERNAL_AUTH_MOUNTS
|
|
openclaw_live_append_array DOCKER_RUN_ARGS DOCKER_AUTH_ENV
|
|
openclaw_live_append_array DOCKER_RUN_ARGS PROFILE_MOUNT
|
|
DOCKER_RUN_ARGS+=(\
|
|
"$LIVE_IMAGE_NAME" \
|
|
-lc "$LIVE_TEST_CMD")
|
|
"${DOCKER_RUN_ARGS[@]}"
|