# This image runs as a non-root user, so seed a user-local npm prefix before we # preinstall an older global version to exercise the upgrade path. export NPM_CONFIG_PREFIX="${NPM_CONFIG_PREFIX:-$HOME/.npm-global}"
mkdir -p "$NPM_CONFIG_PREFIX" export PATH="$NPM_CONFIG_PREFIX/bin:$PATH"
if [[ "$MODELS_MODE" != "both" && "$MODELS_MODE" != "openai" && "$MODELS_MODE" != "anthropic" ]]; then echo"ERROR: OPENCLAW_E2E_MODELS must be one of: both|openai|anthropic" >&2
exit 2 fi
if [[ "$MODELS_MODE" == "both" ]]; then if [[ -z "$OPENAI_API_KEY" ]]; then echo"ERROR: OPENCLAW_E2E_MODELS=both requires OPENAI_API_KEY." >&2
exit 2 fi if [[ -z "$ANTHROPIC_API_TOKEN" && -z "$ANTHROPIC_API_KEY" ]]; then echo"ERROR: OPENCLAW_E2E_MODELS=both requires ANTHROPIC_API_TOKEN or ANTHROPIC_API_KEY." >&2
exit 2 fi elif [[ "$MODELS_MODE" == "openai" && -z "$OPENAI_API_KEY" ]]; then echo"ERROR: OPENCLAW_E2E_MODELS=openai requires OPENAI_API_KEY." >&2
exit 2 elif [[ "$MODELS_MODE" == "anthropic" && -z "$ANTHROPIC_API_TOKEN" && -z "$ANTHROPIC_API_KEY" ]]; then echo"ERROR: OPENCLAW_E2E_MODELS=anthropic requires ANTHROPIC_API_TOKEN or ANTHROPIC_API_KEY." >&2
exit 2 fi
echo"==> Resolve npm versions"
EXPECTED_VERSION="$(quiet_npm view "openclaw@${INSTALL_TAG}" version)" if [[ -z "$EXPECTED_VERSION" || "$EXPECTED_VERSION" == "undefined" || "$EXPECTED_VERSION"== "null" ]]; then echo"ERROR: unable to resolve openclaw@${INSTALL_TAG} version" >&2
exit 2 fi if [[ -n "$E2E_PREVIOUS_VERSION" ]]; then
PREVIOUS_VERSION="$E2E_PREVIOUS_VERSION" else
PREVIOUS_VERSION="$(VERSIONS_JSON="$(quiet_npm view openclaw versions --json)" node - <<'NODE'
const versions = JSON.parse(process.env.VERSIONS_JSON || "[]"); if (!Array.isArray(versions) || versions.length === 0) process.exit(1);
process.stdout.write(versions.length >= 2 ? versions[versions.length - 2] : versions[0]);
NODE
)" fi echo"expected=$EXPECTED_VERSION previous=$PREVIOUS_VERSION"
if [[ "$SKIP_PREVIOUS" == "1" ]]; then echo"==> Skip preinstall previous (OPENCLAW_INSTALL_E2E_SKIP_PREVIOUS=1)" else echo"==> Preinstall previous (forces installer upgrade path; avoids read() prompt)"
quiet_npm install -g "openclaw@${PREVIOUS_VERSION}" fi
echo"==> Run official installer one-liner" if [[ "$INSTALL_TAG" == "beta" ]]; then
OPENCLAW_BETA=1 curl -fsSL "$INSTALL_URL" | bash elif [[ "$INSTALL_TAG" != "latest" ]]; then
OPENCLAW_VERSION="$INSTALL_TAG" curl -fsSL "$INSTALL_URL" | bash else
curl -fsSL "$INSTALL_URL" | bash fi
echo"==> Verify installed version"
INSTALLED_VERSION="$(openclaw --version 2>/dev/null | head -n 1 | tr -d '\r')"
INSTALLED_VERSION="$(extract_openclaw_semver "$INSTALLED_VERSION")" echo"installed=$INSTALLED_VERSION expected=$EXPECTED_VERSION" if [[ "$INSTALLED_VERSION" != "$EXPECTED_VERSION" ]]; then echo"ERROR: expected openclaw@$EXPECTED_VERSION, got openclaw@$INSTALLED_VERSION" >&2
exit 1 fi
set_image_model() {
local profile="$1"
shift
local candidate for candidate in "$@"; do if openclaw --profile "$profile" models set-image "$candidate" >/dev/null 2>&1; then echo"$candidate"
return 0 fi done echo"ERROR: could not set an image model (tried: $*)" >&2
return 1
}
set_agent_model() {
local profile="$1"
local candidate
shift for candidate in "$@"; do if openclaw --profile "$profile" models set "$candidate" >/dev/null 2>&1; then echo"$candidate"
return 0 fi done echo"ERROR: could not set agent model (tried: $*)" >&2
return 1
}
run_agent_turn() {
local profile="$1"
local session_id="$2"
local prompt="$3"
local out_json="$4" # Installer E2E validates install + onboard + embedded agent tooling. It does # not need a paired Gateway control-plane hop, which is flaky/non-deterministic # in the isolated container and already covered by gateway-specific lanes.
set +e
timeout --kill-after=15s "${AGENT_TURN_TIMEOUT_SECONDS}s" \
openclaw --profile "$profile" agent \
--local \
--session-id "$session_id" \
--message "$prompt" \
--thinking off \
--json >"$out_json" 2>&1
local status="$?"
set -e if [[ "$status" -ne 0 ]]; then echo"ERROR: agent turn failed ($profile, status=$status, output=$out_json)" >&2
dump_profile_debug "$profile""$out_json" >&2 || true
return "$status" fi
node - <<'NODE'"$out_json"
const fs = require("node:fs");
const path = process.argv[2];
const raw = fs.readFileSync(path, "utf8");
function extractTrailingJsonObject(input) {
const trimmed = input.trim(); if (!trimmed) {
throw new Error("agent output was empty");
}
try {
return JSON.parse(trimmed);
} catch {
// Some local runs emit stderr diagnostics before the final JSON payload.
// Walk backward and keep the last parseable top-level object. for (let index = trimmed.lastIndexOf("{"); index >= 0; index = trimmed.lastIndexOf("{", index - 1)) {
const candidate = trimmed.slice(index);
try {
return JSON.parse(candidate);
} catch {
// keep scanning
}
}
throw new Error(`could not extract JSON payload from agent output:\n${trimmed}`);
}
}
echo"==> Verify workspace identity files ($profile)"
test -f "$workspace/AGENTS.md"
test -f "$workspace/IDENTITY.md"
test -f "$workspace/USER.md"
test -f "$workspace/SOUL.md"
test -f "$workspace/TOOLS.md"
echo"==> Configure models ($profile)"
local agent_model
local image_model if [[ "$agent_model_provider" == "openai" ]]; then
agent_model="$(set_agent_model "$profile" \ "openai/gpt-5.4" \ "openai/gpt-4o-mini" \ "openai/gpt-4o")"
image_model="$(set_image_model "$profile" \ "openai/gpt-4o-mini" \ "openai/gpt-4o")" else
agent_model="$(set_agent_model "$profile" \ "anthropic/claude-opus-4-6" \ "claude-opus-4-6")"
image_model="$(set_image_model "$profile" \ "anthropic/claude-opus-4-6" \ "claude-opus-4-6")" fi echo"model=$agent_model" echo"imageModel=$image_model"
echo"==> Wait for health ($profile)" for _ in $(seq 1 240); do if openclaw --profile "$profile" health --timeout 5000 --json >/dev/null 2>&1; then
break fi
sleep 0.25 done
openclaw --profile "$profile" health --timeout 60000 --json >/dev/null
run_agent_turn "$profile""$SESSION_ID" \ "Use the read tool (not exec) to read ${PROOF_TXT}. Reply with the exact contents only (no extra whitespace)." \ "$TURN1_JSON"
assert_agent_json_has_text "$TURN1_JSON"
assert_agent_json_ok "$TURN1_JSON""$agent_model_provider"
local reply1
reply1="$(extract_matching_text "$TURN1_JSON" "$PROOF_VALUE" | tr -d '\r\n')" if [[ "$reply1" != "$PROOF_VALUE" ]]; then echo"ERROR: agent did not read proof.txt correctly ($profile): $reply1" >&2
exit 1 fi
local prompt2
prompt2=$'Use the write tool (not exec) to write exactly this string into '"${PROOF_COPY}"$':\n'"${reply1}"$'\nReply with exactly: WROTE'
run_agent_turn "$profile""$SESSION_ID""$prompt2""$TURN2_JSON"
assert_agent_json_has_text "$TURN2_JSON"
assert_agent_json_ok "$TURN2_JSON""$agent_model_provider"
local copy_value
copy_value="$(cat "$PROOF_COPY" 2>/dev/null | tr -d '\r\n' || true)" if [[ "$copy_value" != "$PROOF_VALUE" ]]; then echo"ERROR: copy.txt did not match proof.txt ($profile)" >&2
exit 1 fi
run_agent_turn "$profile""$SESSION_ID" \ "Use the read tool (not exec) to read ${PROOF_COPY}. Reply with the exact contents only (no extra whitespace)." \ "$TURN2B_JSON"
assert_agent_json_has_text "$TURN2B_JSON"
assert_agent_json_ok "$TURN2B_JSON""$agent_model_provider"
local reply2
reply2="$(extract_matching_text "$TURN2B_JSON" "$PROOF_VALUE" | tr -d '\r\n')" if [[ "$reply2" != "$PROOF_VALUE" ]]; then echo"ERROR: agent did not read copy.txt correctly ($profile): $reply2" >&2
exit 1 fi
run_agent_turn "$profile""$SESSION_ID" \ "Use the exec tool to run this command: hostname. Reply with the exact stdout only (trim trailing newline)." \ "$TURN3_JSON"
assert_agent_json_has_text "$TURN3_JSON"
assert_agent_json_ok "$TURN3_JSON""$agent_model_provider"
local reply3
reply3="$(extract_matching_text "$TURN3_JSON" "$EXPECTED_HOSTNAME" | tr -d '\r\n')" if [[ "$reply3" != "$EXPECTED_HOSTNAME" ]]; then echo"ERROR: agent did not run hostname correctly ($profile): $reply3" >&2
exit 1 fi
local prompt3b
prompt3b=$'Use the write tool to write exactly this string into '"${HOSTNAME_TXT}"$':\n'"${reply3}"$'\nReply with exactly: WROTE'
run_agent_turn "$profile""$SESSION_ID""$prompt3b""$TURN3B_JSON"
assert_agent_json_has_text "$TURN3B_JSON"
assert_agent_json_ok "$TURN3B_JSON""$agent_model_provider" if [[ "$(cat "$HOSTNAME_TXT" 2>/dev/null | tr -d '\r\n' || true)" != "$EXPECTED_HOSTNAME" ]]; then echo"ERROR: hostname.txt did not match hostname output ($profile)" >&2
exit 1 fi
run_agent_turn "$profile""$SESSION_ID" \ "Use the image tool on ${IMAGE_PNG}. Determine which color is on the left half and which is on the right half. Then use the write tool to write exactly: LEFT=RED RIGHT=GREEN into ${IMAGE_TXT}. Reply with exactly: LEFT=RED RIGHT=GREEN" \ "$TURN4_JSON"
assert_agent_json_has_text "$TURN4_JSON"
assert_agent_json_ok "$TURN4_JSON""$agent_model_provider" if [[ "$(cat "$IMAGE_TXT" 2>/dev/null | tr -d '\r\n' || true)" != "LEFT=RED RIGHT=GREEN" ]]; then echo"ERROR: image.txt did not contain expected marker ($profile)" >&2
exit 1 fi
local reply4
reply4="$(extract_matching_text "$TURN4_JSON" "LEFT=RED RIGHT=GREEN")" if [[ "$reply4" != "LEFT=RED RIGHT=GREEN" ]]; then echo"ERROR: agent reply did not contain expected marker ($profile): $reply4" >&2
exit 1 fi
echo"==> Verify tool usage via session transcript ($profile)" # Give the gateway a moment to flush transcripts.
sleep 1 if [[ ! -f "$SESSION_JSONL" ]]; then echo"ERROR: missing session transcript ($profile): $SESSION_JSONL" >&2
ls -la "$HOME/.openclaw-${profile}/agents/main/sessions" >&2 || true
exit 1 fi
assert_session_used_tools "$SESSION_JSONL" read write exec image
cleanup_profile
trap - EXIT
}
if [[ "$MODELS_MODE" == "openai" || "$MODELS_MODE" == "both" ]]; then
run_profile "e2e-openai""18789""/tmp/openclaw-e2e-openai""openai" fi
if [[ "$MODELS_MODE" == "anthropic" || "$MODELS_MODE" == "both" ]]; then
run_profile "e2e-anthropic""18799""/tmp/openclaw-e2e-anthropic""anthropic" fi
echo"OK"
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-04-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.