CoolFace
Apppublic

q81801/agent

sourceHugging Faceupdated 4mo agoView on Hugging Face
0likes
bootstrap-hf.ps1675 linesDownload Raw Back to scripts
1Set-StrictMode -Version Latest2$ErrorActionPreference = "Stop"3 4$script_dir = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $MyInvocation.MyCommand.Path }5$repo_root = (Resolve-Path (Join-Path $script_dir "..")).Path6$hf_token_file = if ($env:HF_TOKEN_FILE) { $env:HF_TOKEN_FILE } else { Join-Path $HOME ".cache/huggingface/token" }7$script:RestoreHfLoginRequired = $false8$script:RestoreHfLoginToken = ""9$script:RestoreHfLoginUsername = ""10 11function Trim-Value {12  param([AllowNull()][string]$Value)13 14  if ($null -eq $Value) {15    return ""16  }17  return $Value.Trim()18}19 20function Write-Info {21  param([string]$Message)22 23  Write-Host $Message24}25 26$script:BootstrapStepIndex = 027 28function Get-LogTimestamp {29  return (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")30}31 32function Write-StepStart {33  param([string]$Message)34 35  $script:BootstrapStepIndex += 136  Write-Info ("[{0}] [bootstrap step {1}] START {2}" -f (Get-LogTimestamp), $script:BootstrapStepIndex, $Message)37}38 39function Write-StepDone {40  param([string]$Message)41 42  Write-Info ("[{0}] [bootstrap step {1}] DONE  {2}" -f (Get-LogTimestamp), $script:BootstrapStepIndex, $Message)43}44 45function Invoke-Step {46  param(47    [string]$Message,48    [ScriptBlock]$Action49  )50 51  Write-StepStart -Message $Message52  & $Action53  Write-StepDone -Message $Message54}55 56function Fail {57  param([string]$Message)58 59  throw $Message60}61 62function Prompt-Line {63  param(64    [string]$Prompt,65    [string]$DefaultValue = ""66  )67 68  if ([string]::IsNullOrEmpty($DefaultValue)) {69    $raw = Read-Host -Prompt $Prompt70  } else {71    $raw = Read-Host -Prompt "$Prompt [$DefaultValue]"72  }73 74  $value = Trim-Value $raw75  if ([string]::IsNullOrEmpty($value)) {76    $value = $DefaultValue77  }78  return $value79}80 81function Prompt-Required {82  param(83    [string]$Prompt,84    [string]$DefaultValue = ""85  )86 87  while ($true) {88    $value = Trim-Value (Prompt-Line -Prompt $Prompt -DefaultValue $DefaultValue)89    if (-not [string]::IsNullOrEmpty($value)) {90      return $value91    }92    Write-Host "This value is required." -ForegroundColor Red93  }94}95 96function Convert-SecureStringToPlainText {97  param([System.Security.SecureString]$SecureValue)98 99  if ($null -eq $SecureValue) {100    return ""101  }102 103  $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureValue)104  try {105    return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)106  }107  finally {108    [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)109  }110}111 112function Prompt-SecretOptional {113  param([string]$Prompt)114 115  $secure_value = Read-Host -Prompt $Prompt -AsSecureString116  $plain_text = Convert-SecureStringToPlainText -SecureValue $secure_value117  return Trim-Value $plain_text118}119 120function Prompt-SecretRequired {121  param([string]$Prompt)122 123  while ($true) {124    $value = Trim-Value (Prompt-SecretOptional -Prompt $Prompt)125    if (-not [string]::IsNullOrEmpty($value)) {126      return $value127    }128    Write-Host "This value is required." -ForegroundColor Red129  }130}131 132function Prompt-YesNo {133  param(134    [string]$Prompt,135    [ValidateSet("y", "n")][string]$DefaultValue = "n"136  )137 138  $hint = if ($DefaultValue -eq "y") { "[Y/n]" } else { "[y/N]" }139 140  while ($true) {141    $answer = Trim-Value (Read-Host -Prompt "$Prompt $hint")142    $answer = $answer.ToLowerInvariant()143    if ([string]::IsNullOrEmpty($answer)) {144      $answer = $DefaultValue145    }146 147    switch ($answer) {148      { $_ -in @("y", "yes") } { return "yes" }149      { $_ -in @("n", "no") } { return "no" }150      default {151        Write-Host "Please enter y or n." -ForegroundColor Red152      }153    }154  }155}156 157function Login-WithHfToken {158  param([string]$Token)159 160  & hf auth login --token $Token *> $null161  if ($LASTEXITCODE -ne 0) {162    Fail "hf auth login with token failed."163  }164}165 166function Restore-PreviousHfLoginIfNeeded {167  if (-not $script:RestoreHfLoginRequired) {168    return169  }170  if ([string]::IsNullOrEmpty($script:RestoreHfLoginToken)) {171    Write-Error "Skip restoring previous HF login because backup token is empty."172    $script:RestoreHfLoginRequired = $false173    return174  }175 176  $display_user = if ([string]::IsNullOrEmpty($script:RestoreHfLoginUsername)) { "unknown" } else { $script:RestoreHfLoginUsername }177  Write-Info "Restoring previous HF login for user: $display_user"178  & hf auth login --token $script:RestoreHfLoginToken *> $null179  if ($LASTEXITCODE -eq 0) {180    Write-Info "Previous HF login restored."181  } else {182    Write-Error "Failed to restore previous HF login. Please run: hf auth login"183  }184 185  $script:RestoreHfLoginRequired = $false186}187 188function New-RandomHex {189  param([int]$Length)190 191  if ($Length -le 0 -or ($Length % 2) -ne 0) {192    Fail "Length must be a positive even number."193  }194 195  $bytes = New-Object byte[] ($Length / 2)196  [System.Security.Cryptography.RandomNumberGenerator]::Fill($bytes)197  return ($bytes | ForEach-Object { $_.ToString("x2") }) -join ""198}199 200function Ensure-Git {201  if (-not (Get-Command git -ErrorAction SilentlyContinue)) {202    Fail "git is required. Please install git first."203  }204}205 206function Ensure-HfCli {207  if (Get-Command hf -ErrorAction SilentlyContinue) {208    return209  }210 211  Write-Info "hf CLI not found. Installing via powershell -ExecutionPolicy ByPass -c `"irm https://hf.co/cli/install.ps1 | iex`" ..."212  & powershell -ExecutionPolicy ByPass -c "irm https://hf.co/cli/install.ps1 | iex"213  if ($LASTEXITCODE -ne 0) {214    Fail "hf CLI install failed. Please install manually and rerun."215  }216 217  $local_bin = Join-Path $HOME ".local/bin"218  if ((Test-Path $local_bin) -and -not (($env:PATH -split [IO.Path]::PathSeparator) -contains $local_bin)) {219    $env:PATH = "$local_bin$([IO.Path]::PathSeparator)$env:PATH"220  }221 222  if (-not (Get-Command hf -ErrorAction SilentlyContinue)) {223    Fail "hf CLI install failed. Please install manually and rerun."224  }225}226 227function Ensure-Python3 {228  if (-not (Get-Command python3 -ErrorAction SilentlyContinue)) {229    Fail "python3 is required. Please install python3 first."230  }231}232 233function Ensure-HuggingFaceHubPy {234  & python3 -c "import huggingface_hub" 2>$null235  if ($LASTEXITCODE -ne 0) {236    Fail "python3 package 'huggingface_hub' is required. Install with: python3 -m pip install --user 'huggingface_hub[cli]'"237  }238}239 240function Resolve-LatestOpenclawVersion {241  $python_code = @'242import json243import urllib.request244 245url = "https://registry.npmjs.org/openclaw/latest"246try:247    with urllib.request.urlopen(url, timeout=8) as response:248        payload = response.read().decode("utf-8", errors="replace")249    data = json.loads(payload)250    version = str(data.get("version", "")).strip()251    if version:252        print(version)253except Exception:254    pass255'@256 257  $version_output = & python3 -c $python_code 2>$null258  $version = Trim-Value (($version_output | Out-String))259  if ([string]::IsNullOrEmpty($version)) {260    return "latest"261  }262  return $version263}264 265function Read-CurrentHfToken {266  if (-not [string]::IsNullOrEmpty($env:HUGGINGFACE_HUB_TOKEN)) {267    return Trim-Value $env:HUGGINGFACE_HUB_TOKEN268  }269  if (-not [string]::IsNullOrEmpty($env:HF_TOKEN)) {270    return Trim-Value $env:HF_TOKEN271  }272  if (Test-Path $hf_token_file) {273    return Trim-Value (Get-Content -Path $hf_token_file -TotalCount 1)274  }275  return ""276}277 278function Test-HfLoggedIn {279  & hf auth whoami *> $null280  return ($LASTEXITCODE -eq 0)281}282 283function Get-HfUsername {284  $whoami_output = (& hf auth whoami 2>&1 | Out-String)285 286  $user_match = [regex]::Match($whoami_output, "(?im)^\s*user:\s*([^\s]+)")287  if ($user_match.Success) {288    return Trim-Value $user_match.Groups[1].Value289  }290 291  $login_match = [regex]::Match($whoami_output, "(?im)logged in as\s+([^\s]+)")292  if ($login_match.Success) {293    return Trim-Value $login_match.Groups[1].Value294  }295 296  $token_from_cache = Read-CurrentHfToken297  if (-not [string]::IsNullOrEmpty($token_from_cache)) {298    $env:HF_API_TOKEN = $token_from_cache299    $python_code = @'300from huggingface_hub import HfApi301import os302 303token = (os.environ.get("HF_API_TOKEN") or "").strip() or None304api = HfApi(token=token)305data = api.whoami(token=token)306name = data.get("name", "") if isinstance(data, dict) else ""307print((name or "").strip())308'@309 310    $name_output = & python3 -c $python_code 2>$null311    $name = Trim-Value (($name_output | Out-String))312    if (-not [string]::IsNullOrEmpty($name)) {313      return $name314    }315  }316 317  return ""318}319 320function Set-SpaceVariable {321  param(322    [string]$SpaceRepoId,323    [string]$Key,324    [string]$Value,325    [string]$ApiToken326  )327 328  $env:SPACE_REPO_ID = $SpaceRepoId329  $env:SPACE_VARIABLE_KEY = $Key330  $env:SPACE_VARIABLE_VALUE = $Value331  $env:HF_API_TOKEN = $ApiToken332 333  $python_code = @'334from huggingface_hub import HfApi335import os336 337token = (os.environ.get("HF_API_TOKEN") or "").strip() or None338api = HfApi(token=token)339try:340    api.add_space_variable(341        repo_id=os.environ["SPACE_REPO_ID"],342        key=os.environ["SPACE_VARIABLE_KEY"],343        value=os.environ["SPACE_VARIABLE_VALUE"],344    )345except Exception as exc:346    key = os.environ.get("SPACE_VARIABLE_KEY", "")347    repo_id = os.environ.get("SPACE_REPO_ID", "")348    raise SystemExit(f"failed to set space variable {key} on {repo_id}: {exc}")349'@350 351  & python3 -c $python_code352  if ($LASTEXITCODE -ne 0) {353    Fail "failed to set space variable $Key"354  }355}356 357function Set-SpaceSecret {358  param(359    [string]$SpaceRepoId,360    [string]$Key,361    [string]$Value,362    [string]$ApiToken363  )364 365  $env:SPACE_REPO_ID = $SpaceRepoId366  $env:SPACE_SECRET_KEY = $Key367  $env:SPACE_SECRET_VALUE = $Value368  $env:HF_API_TOKEN = $ApiToken369 370  $python_code = @'371from huggingface_hub import HfApi372import os373 374token = (os.environ.get("HF_API_TOKEN") or "").strip() or None375api = HfApi(token=token)376try:377    api.add_space_secret(378        repo_id=os.environ["SPACE_REPO_ID"],379        key=os.environ["SPACE_SECRET_KEY"],380        value=os.environ["SPACE_SECRET_VALUE"],381    )382except Exception as exc:383    key = os.environ.get("SPACE_SECRET_KEY", "")384    repo_id = os.environ.get("SPACE_REPO_ID", "")385    raise SystemExit(f"failed to set space secret {key} on {repo_id}: {exc}")386'@387 388  & python3 -c $python_code389  if ($LASTEXITCODE -ne 0) {390    Fail "failed to set space secret $Key"391  }392}393 394function Set-SpaceVariableLogged {395  param(396    [string]$SpaceRepoId,397    [string]$Key,398    [string]$Value,399    [string]$ApiToken400  )401 402  Invoke-Step -Message "Set Space variable $Key" -Action {403    Set-SpaceVariable -SpaceRepoId $SpaceRepoId -Key $Key -Value $Value -ApiToken $ApiToken404  }405}406 407function Set-SpaceSecretLogged {408  param(409    [string]$SpaceRepoId,410    [string]$Key,411    [string]$Value,412    [string]$ApiToken413  )414 415  Invoke-Step -Message "Set Space secret $Key" -Action {416    Set-SpaceSecret -SpaceRepoId $SpaceRepoId -Key $Key -Value $Value -ApiToken $ApiToken417  }418}419 420function Restart-Space {421  param(422    [string]$SpaceRepoId,423    [string]$ApiToken424  )425 426  $env:SPACE_RESTART_REPO_ID = $SpaceRepoId427  $env:HF_API_TOKEN = $ApiToken428 429  $python_code = @'430from huggingface_hub import HfApi431import os432 433token = (os.environ.get("HF_API_TOKEN") or "").strip() or None434api = HfApi(token=token)435try:436    api.restart_space(repo_id=os.environ["SPACE_RESTART_REPO_ID"])437except Exception as exc:438    repo_id = os.environ.get("SPACE_RESTART_REPO_ID", "")439    raise SystemExit(f"failed to restart space {repo_id}: {exc}")440'@441 442  & python3 -c $python_code443  if ($LASTEXITCODE -ne 0) {444    Fail "failed to restart space $SpaceRepoId"445  }446}447 448function Main {449  Invoke-Step -Message "Change directory to repository root" -Action {450    Set-Location $repo_root451  }452 453  Write-Info "OpenClaw Hugging Face bootstrap (interactive, Windows PowerShell)"454  Invoke-Step -Message "Check dependency git" -Action { Ensure-Git }455  Invoke-Step -Message "Check dependency hf CLI" -Action { Ensure-HfCli }456  Invoke-Step -Message "Check dependency python3" -Action { Ensure-Python3 }457  Invoke-Step -Message "Check dependency python package huggingface_hub" -Action { Ensure-HuggingFaceHubPy }458  Invoke-Step -Message "Print dependency versions" -Action {459    & git --version460    & hf version461    & python3 --version462  }463 464  $hf_token_for_backup = ""465  Invoke-Step -Message "Resolve HF login and HF_TOKEN" -Action {466    if (-not (Test-HfLoggedIn)) {467      Write-Info "HF CLI is not logged in."468      $hf_token_for_backup = Prompt-SecretRequired -Prompt "HF_TOKEN (required for hf auth login)"469      Login-WithHfToken -Token $hf_token_for_backup470    } else {471      $current_hf_username = Trim-Value (Get-HfUsername)472      if ([string]::IsNullOrEmpty($current_hf_username)) {473        $use_current_hf_user = Prompt-YesNo -Prompt "HF CLI is already logged in. Use current user?" -DefaultValue "y"474      } else {475        $use_current_hf_user = Prompt-YesNo -Prompt "HF CLI is already logged in as '$current_hf_username'. Use this user?" -DefaultValue "y"476      }477 478      if ($use_current_hf_user -eq "yes") {479        $hf_token_for_backup = Trim-Value (Read-CurrentHfToken)480        if ([string]::IsNullOrEmpty($hf_token_for_backup)) {481          $hf_token_for_backup = Prompt-SecretRequired -Prompt "Cannot read current token. Enter HF_TOKEN"482          Login-WithHfToken -Token $hf_token_for_backup483        }484      } else {485        $script:RestoreHfLoginToken = Trim-Value (Read-CurrentHfToken)486        if ([string]::IsNullOrEmpty($script:RestoreHfLoginToken)) {487          Fail "Cannot backup current HF token. Ensure current token is readable before switching users."488        }489        $script:RestoreHfLoginRequired = $true490        $script:RestoreHfLoginUsername = $current_hf_username491 492        $switch_hf_token = Prompt-SecretRequired -Prompt "HF_TOKEN for switching HF user"493        Login-WithHfToken -Token $switch_hf_token494        $hf_token_for_backup = $switch_hf_token495      }496    }497 498    if ([string]::IsNullOrEmpty($hf_token_for_backup)) {499      Fail "HF_TOKEN is required to configure Space secret HF_TOKEN."500    }501  }502 503  $hf_username = ""504  Invoke-Step -Message "Resolve HF username" -Action {505    $hf_username = Trim-Value (Get-HfUsername)506    if ([string]::IsNullOrEmpty($hf_username)) {507      $hf_username = Prompt-Required -Prompt "HF username (cannot parse from hf auth whoami)"508    }509    Write-Info "HF user: $hf_username"510  }511 512  $space_name = ""513  $dataset_name = ""514  Invoke-Step -Message "Collect Space and Dataset names" -Action {515    $space_name = Prompt-Required -Prompt "Space name (without username)" -DefaultValue "openclaw-hf"516    $dataset_name = Prompt-Required -Prompt "Dataset name (without username)" -DefaultValue "$space_name-backup"517  }518 519  $openclaw_version = ""520  Invoke-Step -Message "Resolve and confirm OPENCLAW_VERSION" -Action {521    $default_openclaw_version = Trim-Value $env:OPENCLAW_VERSION522    if ([string]::IsNullOrEmpty($default_openclaw_version)) {523      $default_openclaw_version = Resolve-LatestOpenclawVersion524    }525    $openclaw_version = Prompt-Required -Prompt "OPENCLAW_VERSION (press Enter to use detected latest)" -DefaultValue $default_openclaw_version526  }527 528  $space_repo_id = "$hf_username/$space_name"529  $dataset_repo_id = "$hf_username/$dataset_name"530 531  $gateway_token = ""532  $generated_gateway_token = $false533  Invoke-Step -Message "Collect OPENCLAW_GATEWAY_TOKEN" -Action {534    $gateway_token = Prompt-SecretOptional -Prompt "OPENCLAW_GATEWAY_TOKEN (optional, leave empty to auto-generate 32 chars)"535    if ([string]::IsNullOrEmpty($gateway_token)) {536      $gateway_token = New-RandomHex -Length 32537      $generated_gateway_token = $true538      Write-Info "OPENCLAW_GATEWAY_TOKEN generated automatically."539    }540  }541 542  $gateway_password = ""543  $generated_gateway_password = $false544  Invoke-Step -Message "Collect OPENCLAW_GATEWAY_PASSWORD" -Action {545    $gateway_password = Prompt-SecretOptional -Prompt "OPENCLAW_GATEWAY_PASSWORD (optional, leave empty to auto-generate 16 chars)"546    if ([string]::IsNullOrEmpty($gateway_password)) {547      $gateway_password = New-RandomHex -Length 16548      $generated_gateway_password = $true549      Write-Info "OPENCLAW_GATEWAY_PASSWORD generated automatically."550    }551  }552 553  $configure_llm = "no"554  $llm_base_url = ""555  $llm_model = ""556  $llm_api_key = ""557  $enable_sshx = "no"558  $sshx_auto_start_value = "false"559  Invoke-Step -Message "Collect custom LLM or sshx bootstrap options" -Action {560    $configure_llm = Prompt-YesNo -Prompt "Configure custom LLM now?" -DefaultValue "n"561    if ($configure_llm -eq "yes") {562      $llm_base_url = Prompt-Required -Prompt "OPENCLAW_LLM_BASE_URL"563      $llm_model = Prompt-Required -Prompt "OPENCLAW_LLM_MODEL"564      $llm_api_key = Prompt-SecretOptional -Prompt "OPENCLAW_LLM_API_KEY"565      if ([string]::IsNullOrEmpty($llm_api_key)) {566        Fail "OPENCLAW_LLM_API_KEY is required when enabling custom LLM config."567      }568    } else {569      $enable_sshx = Prompt-YesNo -Prompt "Set OPENCLAW_SSHX_AUTO_START=true for later sshx setup?" -DefaultValue "y"570    }571  }572  if ($enable_sshx -eq "yes") {573    $sshx_auto_start_value = "true"574  }575 576  Write-Info ""577  Write-Info "Planned deployment configuration:"578  Write-Info "Space repo: $space_repo_id"579  Write-Info "Dataset repo: $dataset_repo_id"580  Write-Info "OPENCLAW_VERSION: $openclaw_version"581  Write-Info "OPENCLAW_GATEWAY_CONTROLUI_ALLOW_INSECURE_AUTH=false"582  Write-Info "OPENCLAW_GATEWAY_CONTROLUI_DANGEROUSLY_DISABLE_DEVICE_AUTH=false"583  Write-Info "OPENCLAW_SSHX_AUTO_START=$sshx_auto_start_value"584  if ($configure_llm -eq "yes") {585    Write-Info "Custom LLM config: enabled"586  } else {587    Write-Info "Custom LLM config: disabled"588  }589  $proceed_with_deploy = Prompt-YesNo -Prompt "Proceed with these settings?" -DefaultValue "y"590  if ($proceed_with_deploy -ne "yes") {591    Write-Info "Cancelled by user before creating/updating Space or Dataset."592    return593  }594 595  Invoke-Step -Message "Create Space repo $space_repo_id" -Action {596    & hf repo create $space_repo_id --repo-type space --space-sdk docker --private --exist-ok597    if ($LASTEXITCODE -ne 0) {598      Fail "failed to create Space repo"599    }600  }601  Invoke-Step -Message "Create Dataset repo $dataset_repo_id" -Action {602    & hf repo create $dataset_repo_id --repo-type dataset --private --exist-ok603    if ($LASTEXITCODE -ne 0) {604      Fail "failed to create Dataset repo"605    }606  }607  Invoke-Step -Message "Upload repository to Space $space_repo_id" -Action {608    & hf upload $space_repo_id . --repo-type space --exclude ".git/**" --exclude ".git" --commit-message "feat: deploy openclaw to hf space"609    if ($LASTEXITCODE -ne 0) {610      Fail "failed to upload repository to Space"611    }612  }613 614  $api_token = ""615  Invoke-Step -Message "Resolve API token for Space configuration" -Action {616    $api_token = Read-CurrentHfToken617    if ([string]::IsNullOrEmpty($api_token)) {618      $api_token = $hf_token_for_backup619    }620    if ([string]::IsNullOrEmpty($api_token)) {621      Fail "unable to resolve API token for Space configuration."622    }623  }624 625  Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_BACKUP_DATASET_REPO" -Value $dataset_repo_id -ApiToken $api_token626  Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_VERSION" -Value $openclaw_version -ApiToken $api_token627  Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_GATEWAY_CONTROLUI_ALLOW_INSECURE_AUTH" -Value "false" -ApiToken $api_token628  Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_GATEWAY_CONTROLUI_DANGEROUSLY_DISABLE_DEVICE_AUTH" -Value "false" -ApiToken $api_token629  Set-SpaceSecretLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_GATEWAY_TOKEN" -Value $gateway_token -ApiToken $api_token630  Set-SpaceSecretLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_GATEWAY_PASSWORD" -Value $gateway_password -ApiToken $api_token631  Set-SpaceSecretLogged -SpaceRepoId $space_repo_id -Key "HF_TOKEN" -Value $hf_token_for_backup -ApiToken $api_token632 633  if ($configure_llm -eq "yes") {634    Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_LLM_BASE_URL" -Value $llm_base_url -ApiToken $api_token635    Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_LLM_MODEL" -Value $llm_model -ApiToken $api_token636    Set-SpaceSecretLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_LLM_API_KEY" -Value $llm_api_key -ApiToken $api_token637  }638 639  Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_SSHX_AUTO_START" -Value $sshx_auto_start_value -ApiToken $api_token640 641  Invoke-Step -Message "Print deployment summary" -Action {642    $space_page_url = "https://huggingface.co/spaces/$space_repo_id"643    $space_host = "$($space_repo_id -replace '/', '-').hf.space"644    $app_url = "https://$space_host"645    $health_url = "$app_url/healthz"646 647    Write-Info ""648    Write-Info "Deployment complete."649    Write-Info "Space repo: $space_repo_id"650    Write-Info "Hugging Face Space: $space_page_url"651    Write-Info "Dataset repo: $dataset_repo_id"652    Write-Info "OPENCLAW_VERSION: $openclaw_version"653    Write-Info "Space URL: $app_url"654    Write-Info "Health URL: $health_url"655 656    if ($generated_gateway_token) {657      Write-Info "Generated OPENCLAW_GATEWAY_TOKEN=$gateway_token"658    }659    if ($generated_gateway_password) {660      Write-Info "Generated OPENCLAW_GATEWAY_PASSWORD=$gateway_password"661    }662  }663}664 665try {666  Main667}668catch {669  Write-Error $_.Exception.Message670  exit 1671}672finally {673  Restore-PreviousHfLoginIfNeeded674}675