Spaces:
Sleeping
Sleeping
Download scripts/bootstrap-hf.ps1 from Moxintel/agent: direct link, hf CLI and curl.
- Browser
- Download file 21.2 kB
-
https://huggingface.co/spaces/Moxintel/agent/resolve/main/scripts/bootstrap-hf.ps1
- Command line
-
hf download hf://spaces/Moxintel/agent/scripts/bootstrap-hf.ps1
-
curl -L -o bootstrap-hf.ps1 https://huggingface.co/spaces/Moxintel/agent/resolve/main/scripts/bootstrap-hf.ps1
21.2 kB
| Set-StrictMode -Version Latest | |
| $ErrorActionPreference = "Stop" | |
| $script_dir = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $MyInvocation.MyCommand.Path } | |
| $repo_root = (Resolve-Path (Join-Path $script_dir "..")).Path | |
| $hf_token_file = if ($env:HF_TOKEN_FILE) { $env:HF_TOKEN_FILE } else { Join-Path $HOME ".cache/huggingface/token" } | |
| $script:RestoreHfLoginRequired = $false | |
| $script:RestoreHfLoginToken = "" | |
| $script:RestoreHfLoginUsername = "" | |
| function Trim-Value { | |
| param([AllowNull()][string]$Value) | |
| if ($null -eq $Value) { | |
| return "" | |
| } | |
| return $Value.Trim() | |
| } | |
| function Write-Info { | |
| param([string]$Message) | |
| Write-Host $Message | |
| } | |
| $script:BootstrapStepIndex = 0 | |
| function Get-LogTimestamp { | |
| return (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") | |
| } | |
| function Write-StepStart { | |
| param([string]$Message) | |
| $script:BootstrapStepIndex += 1 | |
| Write-Info ("[{0}] [bootstrap step {1}] START {2}" -f (Get-LogTimestamp), $script:BootstrapStepIndex, $Message) | |
| } | |
| function Write-StepDone { | |
| param([string]$Message) | |
| Write-Info ("[{0}] [bootstrap step {1}] DONE {2}" -f (Get-LogTimestamp), $script:BootstrapStepIndex, $Message) | |
| } | |
| function Invoke-Step { | |
| param( | |
| [string]$Message, | |
| [ScriptBlock]$Action | |
| ) | |
| Write-StepStart -Message $Message | |
| & $Action | |
| Write-StepDone -Message $Message | |
| } | |
| function Fail { | |
| param([string]$Message) | |
| throw $Message | |
| } | |
| function Prompt-Line { | |
| param( | |
| [string]$Prompt, | |
| [string]$DefaultValue = "" | |
| ) | |
| if ([string]::IsNullOrEmpty($DefaultValue)) { | |
| $raw = Read-Host -Prompt $Prompt | |
| } else { | |
| $raw = Read-Host -Prompt "$Prompt [$DefaultValue]" | |
| } | |
| $value = Trim-Value $raw | |
| if ([string]::IsNullOrEmpty($value)) { | |
| $value = $DefaultValue | |
| } | |
| return $value | |
| } | |
| function Prompt-Required { | |
| param( | |
| [string]$Prompt, | |
| [string]$DefaultValue = "" | |
| ) | |
| while ($true) { | |
| $value = Trim-Value (Prompt-Line -Prompt $Prompt -DefaultValue $DefaultValue) | |
| if (-not [string]::IsNullOrEmpty($value)) { | |
| return $value | |
| } | |
| Write-Host "This value is required." -ForegroundColor Red | |
| } | |
| } | |
| function Convert-SecureStringToPlainText { | |
| param([System.Security.SecureString]$SecureValue) | |
| if ($null -eq $SecureValue) { | |
| return "" | |
| } | |
| $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureValue) | |
| try { | |
| return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) | |
| } | |
| finally { | |
| [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) | |
| } | |
| } | |
| function Prompt-SecretOptional { | |
| param([string]$Prompt) | |
| $secure_value = Read-Host -Prompt $Prompt -AsSecureString | |
| $plain_text = Convert-SecureStringToPlainText -SecureValue $secure_value | |
| return Trim-Value $plain_text | |
| } | |
| function Prompt-SecretRequired { | |
| param([string]$Prompt) | |
| while ($true) { | |
| $value = Trim-Value (Prompt-SecretOptional -Prompt $Prompt) | |
| if (-not [string]::IsNullOrEmpty($value)) { | |
| return $value | |
| } | |
| Write-Host "This value is required." -ForegroundColor Red | |
| } | |
| } | |
| function Prompt-YesNo { | |
| param( | |
| [string]$Prompt, | |
| [ValidateSet("y", "n")][string]$DefaultValue = "n" | |
| ) | |
| $hint = if ($DefaultValue -eq "y") { "[Y/n]" } else { "[y/N]" } | |
| while ($true) { | |
| $answer = Trim-Value (Read-Host -Prompt "$Prompt $hint") | |
| $answer = $answer.ToLowerInvariant() | |
| if ([string]::IsNullOrEmpty($answer)) { | |
| $answer = $DefaultValue | |
| } | |
| switch ($answer) { | |
| { $_ -in @("y", "yes") } { return "yes" } | |
| { $_ -in @("n", "no") } { return "no" } | |
| default { | |
| Write-Host "Please enter y or n." -ForegroundColor Red | |
| } | |
| } | |
| } | |
| } | |
| function Login-WithHfToken { | |
| param([string]$Token) | |
| & hf auth login --token $Token *> $null | |
| if ($LASTEXITCODE -ne 0) { | |
| Fail "hf auth login with token failed." | |
| } | |
| } | |
| function Restore-PreviousHfLoginIfNeeded { | |
| if (-not $script:RestoreHfLoginRequired) { | |
| return | |
| } | |
| if ([string]::IsNullOrEmpty($script:RestoreHfLoginToken)) { | |
| Write-Error "Skip restoring previous HF login because backup token is empty." | |
| $script:RestoreHfLoginRequired = $false | |
| return | |
| } | |
| $display_user = if ([string]::IsNullOrEmpty($script:RestoreHfLoginUsername)) { "unknown" } else { $script:RestoreHfLoginUsername } | |
| Write-Info "Restoring previous HF login for user: $display_user" | |
| & hf auth login --token $script:RestoreHfLoginToken *> $null | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-Info "Previous HF login restored." | |
| } else { | |
| Write-Error "Failed to restore previous HF login. Please run: hf auth login" | |
| } | |
| $script:RestoreHfLoginRequired = $false | |
| } | |
| function New-RandomHex { | |
| param([int]$Length) | |
| if ($Length -le 0 -or ($Length % 2) -ne 0) { | |
| Fail "Length must be a positive even number." | |
| } | |
| $bytes = New-Object byte[] ($Length / 2) | |
| [System.Security.Cryptography.RandomNumberGenerator]::Fill($bytes) | |
| return ($bytes | ForEach-Object { $_.ToString("x2") }) -join "" | |
| } | |
| function Ensure-Git { | |
| if (-not (Get-Command git -ErrorAction SilentlyContinue)) { | |
| Fail "git is required. Please install git first." | |
| } | |
| } | |
| function Ensure-HfCli { | |
| if (Get-Command hf -ErrorAction SilentlyContinue) { | |
| return | |
| } | |
| Write-Info "hf CLI not found. Installing via powershell -ExecutionPolicy ByPass -c `"irm https://hf.co/cli/install.ps1 | iex`" ..." | |
| & powershell -ExecutionPolicy ByPass -c "irm https://hf.co/cli/install.ps1 | iex" | |
| if ($LASTEXITCODE -ne 0) { | |
| Fail "hf CLI install failed. Please install manually and rerun." | |
| } | |
| $local_bin = Join-Path $HOME ".local/bin" | |
| if ((Test-Path $local_bin) -and -not (($env:PATH -split [IO.Path]::PathSeparator) -contains $local_bin)) { | |
| $env:PATH = "$local_bin$([IO.Path]::PathSeparator)$env:PATH" | |
| } | |
| if (-not (Get-Command hf -ErrorAction SilentlyContinue)) { | |
| Fail "hf CLI install failed. Please install manually and rerun." | |
| } | |
| } | |
| function Ensure-Python3 { | |
| if (-not (Get-Command python3 -ErrorAction SilentlyContinue)) { | |
| Fail "python3 is required. Please install python3 first." | |
| } | |
| } | |
| function Ensure-HuggingFaceHubPy { | |
| & python3 -c "import huggingface_hub" 2>$null | |
| if ($LASTEXITCODE -ne 0) { | |
| Fail "python3 package 'huggingface_hub' is required. Install with: python3 -m pip install --user 'huggingface_hub[cli]'" | |
| } | |
| } | |
| function Resolve-LatestOpenclawVersion { | |
| $python_code = @' | |
| import json | |
| import urllib.request | |
| url = "https://registry.npmjs.org/openclaw/latest" | |
| try: | |
| with urllib.request.urlopen(url, timeout=8) as response: | |
| payload = response.read().decode("utf-8", errors="replace") | |
| data = json.loads(payload) | |
| version = str(data.get("version", "")).strip() | |
| if version: | |
| print(version) | |
| except Exception: | |
| pass | |
| '@ | |
| $version_output = & python3 -c $python_code 2>$null | |
| $version = Trim-Value (($version_output | Out-String)) | |
| if ([string]::IsNullOrEmpty($version)) { | |
| return "latest" | |
| } | |
| return $version | |
| } | |
| function Read-CurrentHfToken { | |
| if (-not [string]::IsNullOrEmpty($env:HUGGINGFACE_HUB_TOKEN)) { | |
| return Trim-Value $env:HUGGINGFACE_HUB_TOKEN | |
| } | |
| if (-not [string]::IsNullOrEmpty($env:HF_TOKEN)) { | |
| return Trim-Value $env:HF_TOKEN | |
| } | |
| if (Test-Path $hf_token_file) { | |
| return Trim-Value (Get-Content -Path $hf_token_file -TotalCount 1) | |
| } | |
| return "" | |
| } | |
| function Test-HfLoggedIn { | |
| & hf auth whoami *> $null | |
| return ($LASTEXITCODE -eq 0) | |
| } | |
| function Get-HfUsername { | |
| $whoami_output = (& hf auth whoami 2>&1 | Out-String) | |
| $user_match = [regex]::Match($whoami_output, "(?im)^\s*user:\s*([^\s]+)") | |
| if ($user_match.Success) { | |
| return Trim-Value $user_match.Groups[1].Value | |
| } | |
| $login_match = [regex]::Match($whoami_output, "(?im)logged in as\s+([^\s]+)") | |
| if ($login_match.Success) { | |
| return Trim-Value $login_match.Groups[1].Value | |
| } | |
| $token_from_cache = Read-CurrentHfToken | |
| if (-not [string]::IsNullOrEmpty($token_from_cache)) { | |
| $env:HF_API_TOKEN = $token_from_cache | |
| $python_code = @' | |
| from huggingface_hub import HfApi | |
| import os | |
| token = (os.environ.get("HF_API_TOKEN") or "").strip() or None | |
| api = HfApi(token=token) | |
| data = api.whoami(token=token) | |
| name = data.get("name", "") if isinstance(data, dict) else "" | |
| print((name or "").strip()) | |
| '@ | |
| $name_output = & python3 -c $python_code 2>$null | |
| $name = Trim-Value (($name_output | Out-String)) | |
| if (-not [string]::IsNullOrEmpty($name)) { | |
| return $name | |
| } | |
| } | |
| return "" | |
| } | |
| function Set-SpaceVariable { | |
| param( | |
| [string]$SpaceRepoId, | |
| [string]$Key, | |
| [string]$Value, | |
| [string]$ApiToken | |
| ) | |
| $env:SPACE_REPO_ID = $SpaceRepoId | |
| $env:SPACE_VARIABLE_KEY = $Key | |
| $env:SPACE_VARIABLE_VALUE = $Value | |
| $env:HF_API_TOKEN = $ApiToken | |
| $python_code = @' | |
| from huggingface_hub import HfApi | |
| import os | |
| token = (os.environ.get("HF_API_TOKEN") or "").strip() or None | |
| api = HfApi(token=token) | |
| try: | |
| api.add_space_variable( | |
| repo_id=os.environ["SPACE_REPO_ID"], | |
| key=os.environ["SPACE_VARIABLE_KEY"], | |
| value=os.environ["SPACE_VARIABLE_VALUE"], | |
| ) | |
| except Exception as exc: | |
| key = os.environ.get("SPACE_VARIABLE_KEY", "") | |
| repo_id = os.environ.get("SPACE_REPO_ID", "") | |
| raise SystemExit(f"failed to set space variable {key} on {repo_id}: {exc}") | |
| '@ | |
| & python3 -c $python_code | |
| if ($LASTEXITCODE -ne 0) { | |
| Fail "failed to set space variable $Key" | |
| } | |
| } | |
| function Set-SpaceSecret { | |
| param( | |
| [string]$SpaceRepoId, | |
| [string]$Key, | |
| [string]$Value, | |
| [string]$ApiToken | |
| ) | |
| $env:SPACE_REPO_ID = $SpaceRepoId | |
| $env:SPACE_SECRET_KEY = $Key | |
| $env:SPACE_SECRET_VALUE = $Value | |
| $env:HF_API_TOKEN = $ApiToken | |
| $python_code = @' | |
| from huggingface_hub import HfApi | |
| import os | |
| token = (os.environ.get("HF_API_TOKEN") or "").strip() or None | |
| api = HfApi(token=token) | |
| try: | |
| api.add_space_secret( | |
| repo_id=os.environ["SPACE_REPO_ID"], | |
| key=os.environ["SPACE_SECRET_KEY"], | |
| value=os.environ["SPACE_SECRET_VALUE"], | |
| ) | |
| except Exception as exc: | |
| key = os.environ.get("SPACE_SECRET_KEY", "") | |
| repo_id = os.environ.get("SPACE_REPO_ID", "") | |
| raise SystemExit(f"failed to set space secret {key} on {repo_id}: {exc}") | |
| '@ | |
| & python3 -c $python_code | |
| if ($LASTEXITCODE -ne 0) { | |
| Fail "failed to set space secret $Key" | |
| } | |
| } | |
| function Set-SpaceVariableLogged { | |
| param( | |
| [string]$SpaceRepoId, | |
| [string]$Key, | |
| [string]$Value, | |
| [string]$ApiToken | |
| ) | |
| Invoke-Step -Message "Set Space variable $Key" -Action { | |
| Set-SpaceVariable -SpaceRepoId $SpaceRepoId -Key $Key -Value $Value -ApiToken $ApiToken | |
| } | |
| } | |
| function Set-SpaceSecretLogged { | |
| param( | |
| [string]$SpaceRepoId, | |
| [string]$Key, | |
| [string]$Value, | |
| [string]$ApiToken | |
| ) | |
| Invoke-Step -Message "Set Space secret $Key" -Action { | |
| Set-SpaceSecret -SpaceRepoId $SpaceRepoId -Key $Key -Value $Value -ApiToken $ApiToken | |
| } | |
| } | |
| function Restart-Space { | |
| param( | |
| [string]$SpaceRepoId, | |
| [string]$ApiToken | |
| ) | |
| $env:SPACE_RESTART_REPO_ID = $SpaceRepoId | |
| $env:HF_API_TOKEN = $ApiToken | |
| $python_code = @' | |
| from huggingface_hub import HfApi | |
| import os | |
| token = (os.environ.get("HF_API_TOKEN") or "").strip() or None | |
| api = HfApi(token=token) | |
| try: | |
| api.restart_space(repo_id=os.environ["SPACE_RESTART_REPO_ID"]) | |
| except Exception as exc: | |
| repo_id = os.environ.get("SPACE_RESTART_REPO_ID", "") | |
| raise SystemExit(f"failed to restart space {repo_id}: {exc}") | |
| '@ | |
| & python3 -c $python_code | |
| if ($LASTEXITCODE -ne 0) { | |
| Fail "failed to restart space $SpaceRepoId" | |
| } | |
| } | |
| function Main { | |
| Invoke-Step -Message "Change directory to repository root" -Action { | |
| Set-Location $repo_root | |
| } | |
| Write-Info "OpenClaw Hugging Face bootstrap (interactive, Windows PowerShell)" | |
| Invoke-Step -Message "Check dependency git" -Action { Ensure-Git } | |
| Invoke-Step -Message "Check dependency hf CLI" -Action { Ensure-HfCli } | |
| Invoke-Step -Message "Check dependency python3" -Action { Ensure-Python3 } | |
| Invoke-Step -Message "Check dependency python package huggingface_hub" -Action { Ensure-HuggingFaceHubPy } | |
| Invoke-Step -Message "Print dependency versions" -Action { | |
| & git --version | |
| & hf version | |
| & python3 --version | |
| } | |
| $hf_token_for_backup = "" | |
| Invoke-Step -Message "Resolve HF login and HF_TOKEN" -Action { | |
| if (-not (Test-HfLoggedIn)) { | |
| Write-Info "HF CLI is not logged in." | |
| $hf_token_for_backup = Prompt-SecretRequired -Prompt "HF_TOKEN (required for hf auth login)" | |
| Login-WithHfToken -Token $hf_token_for_backup | |
| } else { | |
| $current_hf_username = Trim-Value (Get-HfUsername) | |
| if ([string]::IsNullOrEmpty($current_hf_username)) { | |
| $use_current_hf_user = Prompt-YesNo -Prompt "HF CLI is already logged in. Use current user?" -DefaultValue "y" | |
| } else { | |
| $use_current_hf_user = Prompt-YesNo -Prompt "HF CLI is already logged in as '$current_hf_username'. Use this user?" -DefaultValue "y" | |
| } | |
| if ($use_current_hf_user -eq "yes") { | |
| $hf_token_for_backup = Trim-Value (Read-CurrentHfToken) | |
| if ([string]::IsNullOrEmpty($hf_token_for_backup)) { | |
| $hf_token_for_backup = Prompt-SecretRequired -Prompt "Cannot read current token. Enter HF_TOKEN" | |
| Login-WithHfToken -Token $hf_token_for_backup | |
| } | |
| } else { | |
| $script:RestoreHfLoginToken = Trim-Value (Read-CurrentHfToken) | |
| if ([string]::IsNullOrEmpty($script:RestoreHfLoginToken)) { | |
| Fail "Cannot backup current HF token. Ensure current token is readable before switching users." | |
| } | |
| $script:RestoreHfLoginRequired = $true | |
| $script:RestoreHfLoginUsername = $current_hf_username | |
| $switch_hf_token = Prompt-SecretRequired -Prompt "HF_TOKEN for switching HF user" | |
| Login-WithHfToken -Token $switch_hf_token | |
| $hf_token_for_backup = $switch_hf_token | |
| } | |
| } | |
| if ([string]::IsNullOrEmpty($hf_token_for_backup)) { | |
| Fail "HF_TOKEN is required to configure Space secret HF_TOKEN." | |
| } | |
| } | |
| $hf_username = "" | |
| Invoke-Step -Message "Resolve HF username" -Action { | |
| $hf_username = Trim-Value (Get-HfUsername) | |
| if ([string]::IsNullOrEmpty($hf_username)) { | |
| $hf_username = Prompt-Required -Prompt "HF username (cannot parse from hf auth whoami)" | |
| } | |
| Write-Info "HF user: $hf_username" | |
| } | |
| $space_name = "" | |
| $dataset_name = "" | |
| Invoke-Step -Message "Collect Space and Dataset names" -Action { | |
| $space_name = Prompt-Required -Prompt "Space name (without username)" -DefaultValue "openclaw-hf" | |
| $dataset_name = Prompt-Required -Prompt "Dataset name (without username)" -DefaultValue "$space_name-backup" | |
| } | |
| $openclaw_version = "" | |
| Invoke-Step -Message "Resolve and confirm OPENCLAW_VERSION" -Action { | |
| $default_openclaw_version = Trim-Value $env:OPENCLAW_VERSION | |
| if ([string]::IsNullOrEmpty($default_openclaw_version)) { | |
| $default_openclaw_version = Resolve-LatestOpenclawVersion | |
| } | |
| $openclaw_version = Prompt-Required -Prompt "OPENCLAW_VERSION (press Enter to use detected latest)" -DefaultValue $default_openclaw_version | |
| } | |
| $space_repo_id = "$hf_username/$space_name" | |
| $dataset_repo_id = "$hf_username/$dataset_name" | |
| $gateway_token = "" | |
| $generated_gateway_token = $false | |
| Invoke-Step -Message "Collect OPENCLAW_GATEWAY_TOKEN" -Action { | |
| $gateway_token = Prompt-SecretOptional -Prompt "OPENCLAW_GATEWAY_TOKEN (optional, leave empty to auto-generate 32 chars)" | |
| if ([string]::IsNullOrEmpty($gateway_token)) { | |
| $gateway_token = New-RandomHex -Length 32 | |
| $generated_gateway_token = $true | |
| Write-Info "OPENCLAW_GATEWAY_TOKEN generated automatically." | |
| } | |
| } | |
| $gateway_password = "" | |
| $generated_gateway_password = $false | |
| Invoke-Step -Message "Collect OPENCLAW_GATEWAY_PASSWORD" -Action { | |
| $gateway_password = Prompt-SecretOptional -Prompt "OPENCLAW_GATEWAY_PASSWORD (optional, leave empty to auto-generate 16 chars)" | |
| if ([string]::IsNullOrEmpty($gateway_password)) { | |
| $gateway_password = New-RandomHex -Length 16 | |
| $generated_gateway_password = $true | |
| Write-Info "OPENCLAW_GATEWAY_PASSWORD generated automatically." | |
| } | |
| } | |
| $configure_llm = "no" | |
| $llm_base_url = "" | |
| $llm_model = "" | |
| $llm_api_key = "" | |
| $enable_sshx = "no" | |
| $sshx_auto_start_value = "false" | |
| Invoke-Step -Message "Collect custom LLM or sshx bootstrap options" -Action { | |
| $configure_llm = Prompt-YesNo -Prompt "Configure custom LLM now?" -DefaultValue "n" | |
| if ($configure_llm -eq "yes") { | |
| $llm_base_url = Prompt-Required -Prompt "OPENCLAW_LLM_BASE_URL" | |
| $llm_model = Prompt-Required -Prompt "OPENCLAW_LLM_MODEL" | |
| $llm_api_key = Prompt-SecretOptional -Prompt "OPENCLAW_LLM_API_KEY" | |
| if ([string]::IsNullOrEmpty($llm_api_key)) { | |
| Fail "OPENCLAW_LLM_API_KEY is required when enabling custom LLM config." | |
| } | |
| } else { | |
| $enable_sshx = Prompt-YesNo -Prompt "Set OPENCLAW_SSHX_AUTO_START=true for later sshx setup?" -DefaultValue "y" | |
| } | |
| } | |
| if ($enable_sshx -eq "yes") { | |
| $sshx_auto_start_value = "true" | |
| } | |
| Write-Info "" | |
| Write-Info "Planned deployment configuration:" | |
| Write-Info "Space repo: $space_repo_id" | |
| Write-Info "Dataset repo: $dataset_repo_id" | |
| Write-Info "OPENCLAW_VERSION: $openclaw_version" | |
| Write-Info "OPENCLAW_GATEWAY_CONTROLUI_ALLOW_INSECURE_AUTH=false" | |
| Write-Info "OPENCLAW_GATEWAY_CONTROLUI_DANGEROUSLY_DISABLE_DEVICE_AUTH=false" | |
| Write-Info "OPENCLAW_SSHX_AUTO_START=$sshx_auto_start_value" | |
| if ($configure_llm -eq "yes") { | |
| Write-Info "Custom LLM config: enabled" | |
| } else { | |
| Write-Info "Custom LLM config: disabled" | |
| } | |
| $proceed_with_deploy = Prompt-YesNo -Prompt "Proceed with these settings?" -DefaultValue "y" | |
| if ($proceed_with_deploy -ne "yes") { | |
| Write-Info "Cancelled by user before creating/updating Space or Dataset." | |
| return | |
| } | |
| Invoke-Step -Message "Create Space repo $space_repo_id" -Action { | |
| & hf repo create $space_repo_id --repo-type space --space-sdk docker --private --exist-ok | |
| if ($LASTEXITCODE -ne 0) { | |
| Fail "failed to create Space repo" | |
| } | |
| } | |
| Invoke-Step -Message "Create Dataset repo $dataset_repo_id" -Action { | |
| & hf repo create $dataset_repo_id --repo-type dataset --private --exist-ok | |
| if ($LASTEXITCODE -ne 0) { | |
| Fail "failed to create Dataset repo" | |
| } | |
| } | |
| Invoke-Step -Message "Upload repository to Space $space_repo_id" -Action { | |
| & hf upload $space_repo_id . --repo-type space --exclude ".git/**" --exclude ".git" --commit-message "feat: deploy openclaw to hf space" | |
| if ($LASTEXITCODE -ne 0) { | |
| Fail "failed to upload repository to Space" | |
| } | |
| } | |
| $api_token = "" | |
| Invoke-Step -Message "Resolve API token for Space configuration" -Action { | |
| $api_token = Read-CurrentHfToken | |
| if ([string]::IsNullOrEmpty($api_token)) { | |
| $api_token = $hf_token_for_backup | |
| } | |
| if ([string]::IsNullOrEmpty($api_token)) { | |
| Fail "unable to resolve API token for Space configuration." | |
| } | |
| } | |
| Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_BACKUP_DATASET_REPO" -Value $dataset_repo_id -ApiToken $api_token | |
| Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_VERSION" -Value $openclaw_version -ApiToken $api_token | |
| Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_GATEWAY_CONTROLUI_ALLOW_INSECURE_AUTH" -Value "false" -ApiToken $api_token | |
| Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_GATEWAY_CONTROLUI_DANGEROUSLY_DISABLE_DEVICE_AUTH" -Value "false" -ApiToken $api_token | |
| Set-SpaceSecretLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_GATEWAY_TOKEN" -Value $gateway_token -ApiToken $api_token | |
| Set-SpaceSecretLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_GATEWAY_PASSWORD" -Value $gateway_password -ApiToken $api_token | |
| Set-SpaceSecretLogged -SpaceRepoId $space_repo_id -Key "HF_TOKEN" -Value $hf_token_for_backup -ApiToken $api_token | |
| if ($configure_llm -eq "yes") { | |
| Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_LLM_BASE_URL" -Value $llm_base_url -ApiToken $api_token | |
| Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_LLM_MODEL" -Value $llm_model -ApiToken $api_token | |
| Set-SpaceSecretLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_LLM_API_KEY" -Value $llm_api_key -ApiToken $api_token | |
| } | |
| Set-SpaceVariableLogged -SpaceRepoId $space_repo_id -Key "OPENCLAW_SSHX_AUTO_START" -Value $sshx_auto_start_value -ApiToken $api_token | |
| Invoke-Step -Message "Print deployment summary" -Action { | |
| $space_page_url = "https://huggingface.co/spaces/$space_repo_id" | |
| $space_host = "$($space_repo_id -replace '/', '-').hf.space" | |
| $app_url = "https://$space_host" | |
| $health_url = "$app_url/healthz" | |
| Write-Info "" | |
| Write-Info "Deployment complete." | |
| Write-Info "Space repo: $space_repo_id" | |
| Write-Info "Hugging Face Space: $space_page_url" | |
| Write-Info "Dataset repo: $dataset_repo_id" | |
| Write-Info "OPENCLAW_VERSION: $openclaw_version" | |
| Write-Info "Space URL: $app_url" | |
| Write-Info "Health URL: $health_url" | |
| if ($generated_gateway_token) { | |
| Write-Info "Generated OPENCLAW_GATEWAY_TOKEN=$gateway_token" | |
| } | |
| if ($generated_gateway_password) { | |
| Write-Info "Generated OPENCLAW_GATEWAY_PASSWORD=$gateway_password" | |
| } | |
| } | |
| } | |
| try { | |
| Main | |
| } | |
| catch { | |
| Write-Error $_.Exception.Message | |
| exit 1 | |
| } | |
| finally { | |
| Restore-PreviousHfLoginIfNeeded | |
| } | |