

























@@ -31,7 +31,8 @@ UPDATE_EXPECTED_NEEDLE=""
3131API_KEY_VALUE=""
3232PROGRESS_INTERVAL_S=15
3333PROGRESS_STALE_S=60
34-TIMEOUT_UPDATE_S=600
34+TIMEOUT_UPDATE_S=300
35+TIMEOUT_UPDATE_POLL_GRACE_S=60
35363637child_job_running() {
3738local target="$1"
@@ -372,7 +373,8 @@ param(
372373 [Parameter(Mandatory = $true)][string]$SessionId,
373374 [Parameter(Mandatory = $true)][string]$ModelId,
374375 [Parameter(Mandatory = $true)][string]$ProviderKeyEnv,
375- [Parameter(Mandatory = $true)][string]$ProviderKey,
376+ [Parameter(Mandatory = $false)][string]$ProviderKey,
377+ [Parameter(Mandatory = $false)][string]$ProviderKeyFile,
376378 [Parameter(Mandatory = $true)][string]$LogPath,
377379 [Parameter(Mandatory = $true)][string]$DonePath
378380)
@@ -555,6 +557,13 @@ try {
555557 $env:PATH = "$env:LOCALAPPDATA\OpenClaw\deps\portable-git\cmd;$env:LOCALAPPDATA\OpenClaw\deps\portable-git\mingw64\bin;$env:LOCALAPPDATA\OpenClaw\deps\portable-git\usr\bin;$env:PATH"
556558 Remove-Item $LogPath, $DonePath -Force -ErrorAction SilentlyContinue
557559 Write-ProgressLog 'update.start'
560+ if ($ProviderKeyFile) {
561+ $ProviderKey = [Text.Encoding]::UTF8.GetString([IO.File]::ReadAllBytes($ProviderKeyFile))
562+ Remove-Item $ProviderKeyFile -Force -ErrorAction SilentlyContinue
563+ }
564+ if (-not $ProviderKey) {
565+ throw "$ProviderKeyEnv is required"
566+ }
558567 Set-Item -Path ('Env:' + $ProviderKeyEnv) -Value $ProviderKey
559568 $openclaw = Join-Path $env:APPDATA 'npm\openclaw.cmd'
560569 Stop-OpenClawGatewayProcesses
@@ -622,6 +631,14 @@ wait_job() {
622631 warn "$label exited nonzero after completion markers; treating as pass"
623632return 0
624633fi
634+if [[ "$label" == "macOS update" ]] && verify_macos_update_after_transport_loss "$UPDATE_EXPECTED_NEEDLE"; then
635+ warn "$label transport failed after product verification passed; treating as pass"
636+return 0
637+fi
638+if [[ "$label" == "Windows update" ]] && verify_windows_update_after_transport_loss "$UPDATE_EXPECTED_NEEDLE"; then
639+ warn "$label transport failed after product verification passed; treating as pass"
640+return 0
641+fi
625642 warn "$label failed"
626643if [[ -n "$log_path" ]]; then
627644 dump_log_tail "$label" "$log_path"
@@ -647,6 +664,134 @@ raise SystemExit(1)
647664PY
648665}
649666667+verify_macos_update_after_transport_loss() {
668+local expected_needle="$1"
669+local script_path="/tmp/openclaw-npm-update-macos-recover.sh"
670+ cat <<EOF | prlctl exec "$MACOS_VM" /usr/bin/tee "$script_path" >/dev/null
671+set -euo pipefail
672+export PATH=/opt/homebrew/bin:/opt/homebrew/opt/node/bin:/opt/homebrew/sbin:/usr/bin:/bin:/usr/sbin:/sbin
673+busy="\$(/bin/ps -axo command | /usr/bin/egrep 'openclaw update|npm install|pnpm install|pnpm run build' | /usr/bin/egrep -v 'egrep|openclaw-npm-update-macos-recover' || true)"
674+if [ -n "\$busy" ]; then
675+ printf 'update still has active npm/pnpm/openclaw processes\n%s\n' "\$busy" >&2
676+ exit 1
677+fi
678+version="\$(/opt/homebrew/bin/openclaw --version)"
679+printf '%s\n' "\$version"
680+if [ -n "$expected_needle" ]; then
681+ case "\$version" in
682+ *"$expected_needle"*) ;;
683+ *)
684+ echo "version mismatch after transport loss: expected substring $expected_needle" >&2
685+ exit 1
686+ ;;
687+ esac
688+fi
689+/opt/homebrew/bin/openclaw gateway status --deep --require-rpc >/dev/null 2>&1 || /opt/homebrew/bin/openclaw gateway restart || true
690+gateway_ready=0
691+for _ in 1 2 3 4 5 6; do
692+ if /opt/homebrew/bin/openclaw gateway status --deep --require-rpc; then
693+ gateway_ready=1
694+ break
695+ fi
696+ sleep 2
697+done
698+if [ "\$gateway_ready" != "1" ]; then
699+ /opt/homebrew/bin/openclaw gateway start || true
700+ for _ in 1 2 3 4 5 6; do
701+ if /opt/homebrew/bin/openclaw gateway status --deep --require-rpc; then
702+ gateway_ready=1
703+ break
704+ fi
705+ sleep 2
706+ done
707+fi
708+if [ "\$gateway_ready" != "1" ]; then
709+ echo "gateway did not become RPC-ready after transport recovery" >&2
710+ exit 1
711+fi
712+/opt/homebrew/bin/openclaw models set "$MODEL_ID"
713+/opt/homebrew/bin/openclaw agent --agent main --session-id "parallels-npm-update-macos-transport-recovery-$expected_needle" --message "Reply with exact ASCII text OK only." --json
714+EOF
715+ macos_desktop_user_exec /bin/bash "$script_path"
716+}
717+718+verify_windows_update_after_transport_loss() {
719+local expected_needle="$1"
720+local provider_key_b64
721+ provider_key_b64="$(
722+ PROVIDER_KEY="$API_KEY_VALUE" "$PYTHON_BIN" - <<'PY'
723+import base64
724+import os
725+726+print(base64.b64encode(os.environ["PROVIDER_KEY"].encode("utf-8")).decode("ascii"))
727+PY
728+ )"
729+set +e
730+ guest_powershell_poll 120 "$(cat <<EOF
731+\$ErrorActionPreference = 'Stop'
732+\$openclaw = Join-Path \$env:APPDATA 'npm\\openclaw.cmd'
733+if (-not (Test-Path \$openclaw)) {
734+ throw "openclaw shim missing: \$openclaw"
735+}
736+\$busy = Get-CimInstance Win32_Process |
737+ Where-Object {
738+ \$_.CommandLine -and
739+ (\$_.CommandLine -match 'openclaw update|npm install|pnpm install|pnpm run build')
740+ }
741+if (\$busy) {
742+ throw 'update still has active npm/pnpm/openclaw processes'
743+}
744+\$version = & \$openclaw --version
745+Write-Output \$version
746+if ('$expected_needle' -and \$version -notmatch [regex]::Escape('$expected_needle')) {
747+ throw "version mismatch after transport loss: expected substring $expected_needle"
748+}
749+\$gatewayReady = \$false
750+for (\$i = 0; \$i -lt 6; \$i++) {
751+ & \$openclaw gateway status --deep --require-rpc
752+ if (\$LASTEXITCODE -eq 0) {
753+ \$gatewayReady = \$true
754+ break
755+ }
756+ Start-Sleep -Seconds 2
757+}
758+if (-not \$gatewayReady) {
759+ & \$openclaw gateway restart
760+ for (\$i = 0; \$i -lt 6; \$i++) {
761+ & \$openclaw gateway status --deep --require-rpc
762+ if (\$LASTEXITCODE -eq 0) {
763+ \$gatewayReady = \$true
764+ break
765+ }
766+ Start-Sleep -Seconds 2
767+ }
768+}
769+if (-not \$gatewayReady) {
770+ & \$openclaw gateway start
771+ for (\$i = 0; \$i -lt 6; \$i++) {
772+ & \$openclaw gateway status --deep --require-rpc
773+ if (\$LASTEXITCODE -eq 0) {
774+ \$gatewayReady = \$true
775+ break
776+ }
777+ Start-Sleep -Seconds 2
778+ }
779+}
780+if (-not \$gatewayReady) {
781+ throw 'gateway did not become RPC-ready after transport recovery'
782+}
783+\$providerBytes = [Convert]::FromBase64String('$provider_key_b64')
784+\$providerValue = [Text.Encoding]::UTF8.GetString(\$providerBytes)
785+Set-Item -Path ('Env:' + '$API_KEY_ENV') -Value \$providerValue
786+& \$openclaw models set '$MODEL_ID'
787+& \$openclaw agent --agent main --session-id 'parallels-npm-update-windows-transport-recovery-$expected_needle' --message 'Reply with exact ASCII text OK only.' --json
788+EOF
789+ )"
790+local rc=$?
791+set -e
792+return "$rc"
793+}
794+650795start_timeout_guard() {
651796local label="$1"
652797local timeout_s="$2"
@@ -745,10 +890,10 @@ monitor_jobs_progress() {
745890 running=1
746891 summary="$(extract_log_progress "${logs[$i]}")"
747892 [[ -n "$summary" ]] || summary="waiting for first log line"
748-if [[ "${last_progress[$i]}" != "$summary" ]] || (( now - last_print[$i] >= PROGRESS_STALE_S )); then
893+if [[ "${last_progress[i]}" != "$summary" ]] || (( now - last_print[i] >= PROGRESS_STALE_S )); then
749894 say "$group ${labels[$i]}: $summary"
750- last_progress[$i]="$summary"
751- last_print[$i]=$now
895+ last_progress[i]="$summary"
896+ last_print[i]=$now
752897fi
753898done
754899(( running )) || break
@@ -846,21 +991,32 @@ run_windows_script_via_log() {
846991local provider_key="$7"
847992local runner_name log_name done_name done_status launcher_state guest_log
848993local start_seconds poll_deadline startup_checked poll_rc state_rc log_rc
849-local log_state_path
994+local log_state_path provider_key_b64
850995 runner_name="openclaw-update-$RANDOM-$RANDOM.ps1"
851996 log_name="openclaw-update-$RANDOM-$RANDOM.log"
852997 done_name="openclaw-update-$RANDOM-$RANDOM.done"
853998 log_state_path="$(mktemp "${TMPDIR:-/tmp}/openclaw-update-log-state.XXXXXX")"
854999: >"$log_state_path"
1000+ provider_key_b64="$(
1001+ PROVIDER_KEY="$provider_key" "$PYTHON_BIN" - <<'PY'
1002+import base64
1003+import os
1004+1005+print(base64.b64encode(os.environ["PROVIDER_KEY"].encode("utf-8")).decode("ascii"))
1006+PY
1007+ )"
8551008 start_seconds="$SECONDS"
856- poll_deadline=$((SECONDS + TIMEOUT_UPDATE_S + 60))
1009+ poll_deadline=$((SECONDS + TIMEOUT_UPDATE_S + TIMEOUT_UPDATE_POLL_GRACE_S))
8571010 startup_checked=0
85810118591012 guest_powershell "$(cat <<EOF
8601013\$runner = Join-Path \$env:TEMP '$runner_name'
8611014\$log = Join-Path \$env:TEMP '$log_name'
8621015\$done = Join-Path \$env:TEMP '$done_name'
863-Remove-Item \$runner, \$log, \$done -Force -ErrorAction SilentlyContinue
1016+\$providerKeyFile = Join-Path \$env:TEMP '$runner_name.key'
1017+Remove-Item \$runner, \$log, \$done, \$providerKeyFile -Force -ErrorAction SilentlyContinue
1018+\$providerBytes = [Convert]::FromBase64String('$provider_key_b64')
1019+[IO.File]::WriteAllBytes(\$providerKeyFile, \$providerBytes)
8641020curl.exe -fsSL '$script_url' -o \$runner
8651021Start-Process powershell.exe -ArgumentList @(
8661022 '-NoProfile',
@@ -871,7 +1027,7 @@ Start-Process powershell.exe -ArgumentList @(
8711027 '-SessionId', '$session_id',
8721028 '-ModelId', '$model_id',
8731029 '-ProviderKeyEnv', '$provider_key_env',
874- '-ProviderKey', '$provider_key',
1030+ '-ProviderKeyFile', \$providerKeyFile,
8751031 '-LogPath', \$log,
8761032 '-DonePath', \$done
8771033) -WindowStyle Hidden | Out-Null
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。