add
This commit is contained in:
parent
3d14b8ff77
commit
03697c49e4
|
|
@ -0,0 +1,100 @@
|
|||
# 浏览器工具配置
|
||||
|
||||
## 一、结论先行
|
||||
|
||||
可以使用如下配置(仅供参考):
|
||||
|
||||
```json
|
||||
{
|
||||
"browser": {
|
||||
|
||||
// 是否启用 browser 工具模块
|
||||
// 关闭后 OpenClaw 将不会提供浏览器自动化能力
|
||||
"enabled": true,
|
||||
|
||||
// 调用远程 CDP(Chrome DevTools Protocol)接口时
|
||||
// 单次请求的超时时间(毫秒)
|
||||
"remoteCdpTimeoutMs": 1500,
|
||||
|
||||
// 与远程 CDP 建立 WebSocket 连接时的握手超时时间(毫秒)
|
||||
"remoteCdpHandshakeTimeoutMs": 3000,
|
||||
|
||||
// 浏览器实例在 UI 或日志中的默认标识颜色
|
||||
// 用于区分不同浏览器实例
|
||||
"color": "#FF4500",
|
||||
|
||||
// OpenClaw 启动浏览器时使用的可执行文件路径
|
||||
// 只有在 OpenClaw 托管浏览器(spawn browser)模式下才会使用
|
||||
"executablePath": "/usr/bin/chromium-browser",
|
||||
|
||||
// 是否以无头模式启动浏览器
|
||||
// true = 不显示浏览器窗口
|
||||
// false = 显示浏览器 UI
|
||||
"headless": false,
|
||||
|
||||
// 是否添加 --no-sandbox 启动参数
|
||||
// 在 Docker / WSL / CI 环境中通常需要开启
|
||||
"noSandbox": true,
|
||||
|
||||
// 是否只允许“附加到已有浏览器”
|
||||
// true = OpenClaw 不会启动新浏览器,只能连接已有 CDP
|
||||
// false = OpenClaw 可以自行启动浏览器
|
||||
"attachOnly": false,
|
||||
|
||||
// 默认使用的浏览器 profile 名称
|
||||
// 如果没有指定 profile,则使用这个
|
||||
"defaultProfile": "chrome",
|
||||
|
||||
// 浏览器 profile 列表
|
||||
// 每个 profile 代表一个可控制的浏览器实例
|
||||
"profiles": {
|
||||
|
||||
// OpenClaw 默认自动化浏览器实例
|
||||
"openclaw": {
|
||||
|
||||
// 该浏览器实例的 CDP 调试端口
|
||||
// OpenClaw 会通过这个端口连接浏览器
|
||||
"cdpPort": 18800,
|
||||
|
||||
// 该浏览器实例在 UI 或日志中的颜色标识
|
||||
"color": "#FF4500"
|
||||
},
|
||||
|
||||
// 第二个浏览器实例(例如工作环境浏览器)
|
||||
"work": {
|
||||
|
||||
// 该实例的 CDP 调试端口
|
||||
"cdpPort": 18801,
|
||||
|
||||
// UI / 日志中的颜色标识
|
||||
"color": "#0066CC"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 二、实用场景
|
||||
|
||||
### 1.1 让 openclaw 控制个人浏览器实现自动化(使用个人用户态、登录态)
|
||||
|
||||
实现方案:
|
||||
|
||||
1. 插件安装
|
||||
1. 使用 openclaw 官方 chrome 插件
|
||||
1. 下载 openclaw 官方 chrome 插件 `openclaw browser extension install`
|
||||
2. 查看插件安装路径 `openclaw browser extension path`
|
||||
3. 打开 chrome 浏览器,访问 `chrome://extensions/`,开启开发者模式
|
||||
4. 点击 `加载未打包的扩展程序`,选择 openclaw 插件安装路径
|
||||
5. 中继器链接,使用中继器端口 `18792` 和 网关令牌 `token`,保存即可
|
||||
2. 自行在 chrome 商店下载安装 OpenClaw Borwser Relay 插件
|
||||
1. 登录谷歌插件商店 `https://chromewebstore.google.com/category/extensions`
|
||||
2. 搜索 `OpenClaw Browser Relay`,选一个高分的就行,都不是官方的
|
||||
3. 点击 `添加到 Chrome`,安装插件
|
||||
2. 配置 openclaw 浏览器工具
|
||||
1. 打开 openclaw 浏览器工具配置文件 `openclaw browser.json`
|
||||
2. 配置 `cdpPort` 为 `18792`
|
||||
3. 配置 `gatewayToken` 为 `token`
|
||||
4. 保存配置文件
|
||||
|
||||
### 1.2让 openclaw 控制浏览器自行实现自动化(使用 openclaw 同一环境如 linux 浏览器)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,670 @@
|
|||
# OpenClaw Installer for Windows
|
||||
# Usage: iwr -useb https://openclaw.ai/install.ps1 | iex
|
||||
# & ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -Tag beta -NoOnboard -DryRun
|
||||
|
||||
param(
|
||||
[string]$Tag = "latest",
|
||||
[ValidateSet("npm", "git")]
|
||||
[string]$InstallMethod = "npm",
|
||||
[string]$GitDir,
|
||||
[switch]$NoOnboard,
|
||||
[switch]$NoGitUpdate,
|
||||
[switch]$DryRun
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host " OpenClaw Installer" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Check if running in PowerShell
|
||||
if ($PSVersionTable.PSVersion.Major -lt 5) {
|
||||
Write-Host "Error: PowerShell 5+ required" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "[OK] Windows detected" -ForegroundColor Green
|
||||
|
||||
if (-not $PSBoundParameters.ContainsKey("InstallMethod")) {
|
||||
if (-not [string]::IsNullOrWhiteSpace($env:OPENCLAW_INSTALL_METHOD)) {
|
||||
$InstallMethod = $env:OPENCLAW_INSTALL_METHOD
|
||||
}
|
||||
}
|
||||
if (-not $PSBoundParameters.ContainsKey("GitDir")) {
|
||||
if (-not [string]::IsNullOrWhiteSpace($env:OPENCLAW_GIT_DIR)) {
|
||||
$GitDir = $env:OPENCLAW_GIT_DIR
|
||||
}
|
||||
}
|
||||
if (-not $PSBoundParameters.ContainsKey("NoOnboard")) {
|
||||
if ($env:OPENCLAW_NO_ONBOARD -eq "1") {
|
||||
$NoOnboard = $true
|
||||
}
|
||||
}
|
||||
if (-not $PSBoundParameters.ContainsKey("NoGitUpdate")) {
|
||||
if ($env:OPENCLAW_GIT_UPDATE -eq "0") {
|
||||
$NoGitUpdate = $true
|
||||
}
|
||||
}
|
||||
if (-not $PSBoundParameters.ContainsKey("DryRun")) {
|
||||
if ($env:OPENCLAW_DRY_RUN -eq "1") {
|
||||
$DryRun = $true
|
||||
}
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($GitDir)) {
|
||||
$userHome = [Environment]::GetFolderPath("UserProfile")
|
||||
$GitDir = (Join-Path $userHome "openclaw")
|
||||
}
|
||||
|
||||
# Check for Node.js
|
||||
function Check-Node {
|
||||
try {
|
||||
$nodeVersion = (node -v 2>$null)
|
||||
if ($nodeVersion) {
|
||||
$version = [int]($nodeVersion -replace 'v(\d+)\..*', '$1')
|
||||
if ($version -ge 22) {
|
||||
Write-Host "[OK] Node.js $nodeVersion found" -ForegroundColor Green
|
||||
return $true
|
||||
} else {
|
||||
Write-Host "[!] Node.js $nodeVersion found, but v22+ required" -ForegroundColor Yellow
|
||||
return $false
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Host "[!] Node.js not found" -ForegroundColor Yellow
|
||||
return $false
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
# Install Node.js
|
||||
function Install-Node {
|
||||
Write-Host "[*] Installing Node.js..." -ForegroundColor Yellow
|
||||
|
||||
# Try winget first (Windows 11 / Windows 10 with App Installer)
|
||||
if (Get-Command winget -ErrorAction SilentlyContinue) {
|
||||
Write-Host " Using winget..." -ForegroundColor Gray
|
||||
winget install OpenJS.NodeJS.LTS --accept-package-agreements --accept-source-agreements
|
||||
|
||||
# Refresh PATH
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
Write-Host "[OK] Node.js installed via winget" -ForegroundColor Green
|
||||
return
|
||||
}
|
||||
|
||||
# Try Chocolatey
|
||||
if (Get-Command choco -ErrorAction SilentlyContinue) {
|
||||
Write-Host " Using Chocolatey..." -ForegroundColor Gray
|
||||
choco install nodejs-lts -y
|
||||
|
||||
# Refresh PATH
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
Write-Host "[OK] Node.js installed via Chocolatey" -ForegroundColor Green
|
||||
return
|
||||
}
|
||||
|
||||
# Try Scoop
|
||||
if (Get-Command scoop -ErrorAction SilentlyContinue) {
|
||||
Write-Host " Using Scoop..." -ForegroundColor Gray
|
||||
scoop install nodejs-lts
|
||||
Write-Host "[OK] Node.js installed via Scoop" -ForegroundColor Green
|
||||
return
|
||||
}
|
||||
|
||||
# Manual download fallback
|
||||
Write-Host ""
|
||||
Write-Host "Error: Could not find a package manager (winget, choco, or scoop)" -ForegroundColor Red
|
||||
Write-Host ""
|
||||
Write-Host "Please install Node.js 22+ manually:" -ForegroundColor Yellow
|
||||
Write-Host " https://nodejs.org/en/download/" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "Or install winget (App Installer) from the Microsoft Store." -ForegroundColor Gray
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check for existing OpenClaw installation
|
||||
function Check-ExistingOpenClaw {
|
||||
if (Get-OpenClawCommandPath) {
|
||||
Write-Host "[*] Existing OpenClaw installation detected" -ForegroundColor Yellow
|
||||
return $true
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function Check-Git {
|
||||
try {
|
||||
$null = Get-Command git -ErrorAction Stop
|
||||
return $true
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Install-Git {
|
||||
Write-Host "[*] Installing Git..." -ForegroundColor Yellow
|
||||
|
||||
# 优先从国内镜像下载(无梯子也能快速下载)
|
||||
Write-Host " Downloading from Chinese mirror..." -ForegroundColor Gray
|
||||
$gitInstallerUrl = "https://registry.npmmirror.com/-/binary/git-for-windows/v2.47.0.windows.1/Git-2.47.0-64-bit.exe"
|
||||
$installerPath = Join-Path $env:TEMP "Git-installer.exe"
|
||||
|
||||
try {
|
||||
Invoke-WebRequest -Uri $gitInstallerUrl -OutFile $installerPath -UseBasicParsing
|
||||
Write-Host " Download complete, running installer..." -ForegroundColor Gray
|
||||
Start-Process -FilePath $installerPath -ArgumentList "/VERYSILENT", "/NORESTART", "/NOCANCEL", "/SP-", "/COMPONENTS=icons,ext\shellhere,assoc,assoc_sh" -Wait
|
||||
|
||||
# Refresh PATH
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
Write-Host "[OK] Git installed via Chinese mirror" -ForegroundColor Green
|
||||
return
|
||||
} catch {
|
||||
Write-Host " [!] Mirror download failed, falling back to package managers..." -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Try winget (Windows 11 / Windows 10 with App Installer)
|
||||
if (Get-Command winget -ErrorAction SilentlyContinue) {
|
||||
Write-Host " Using winget..." -ForegroundColor Gray
|
||||
winget install Git.Git --accept-package-agreements --accept-source-agreements
|
||||
|
||||
# Refresh PATH
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
Write-Host "[OK] Git installed via winget" -ForegroundColor Green
|
||||
return
|
||||
}
|
||||
|
||||
# Try Chocolatey
|
||||
if (Get-Command choco -ErrorAction SilentlyContinue) {
|
||||
Write-Host " Using Chocolatey..." -ForegroundColor Gray
|
||||
choco install git -y
|
||||
|
||||
# Refresh PATH
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
Write-Host "[OK] Git installed via Chocolatey" -ForegroundColor Green
|
||||
return
|
||||
}
|
||||
|
||||
# Try Scoop
|
||||
if (Get-Command scoop -ErrorAction SilentlyContinue) {
|
||||
Write-Host " Using Scoop..." -ForegroundColor Gray
|
||||
scoop install git
|
||||
Write-Host "[OK] Git installed via Scoop" -ForegroundColor Green
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Error: Git installation failed" -ForegroundColor Red
|
||||
Write-Host ""
|
||||
Write-Host "Please install Git for Windows manually:" -ForegroundColor Yellow
|
||||
Write-Host " https://registry.npmmirror.com/-/binary/git-for-windows/" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
function Require-Git {
|
||||
if (Check-Git) { return }
|
||||
Install-Git
|
||||
|
||||
# Verify installation
|
||||
if (-not (Check-Git)) {
|
||||
Write-Host ""
|
||||
Write-Host "Error: Git installation may require a terminal restart" -ForegroundColor Red
|
||||
Write-Host "Please close this terminal, open a new one, and run this installer again." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
function Get-OpenClawCommandPath {
|
||||
$openclawCmd = Get-Command openclaw.cmd -ErrorAction SilentlyContinue
|
||||
if ($openclawCmd -and $openclawCmd.Source) {
|
||||
return $openclawCmd.Source
|
||||
}
|
||||
|
||||
$openclaw = Get-Command openclaw -ErrorAction SilentlyContinue
|
||||
if ($openclaw -and $openclaw.Source) {
|
||||
return $openclaw.Source
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Invoke-OpenClawCommand {
|
||||
param(
|
||||
[Parameter(ValueFromRemainingArguments = $true)]
|
||||
[string[]]$Arguments
|
||||
)
|
||||
|
||||
$commandPath = Get-OpenClawCommandPath
|
||||
if (-not $commandPath) {
|
||||
throw "openclaw command not found on PATH."
|
||||
}
|
||||
|
||||
& $commandPath @Arguments
|
||||
}
|
||||
|
||||
function Get-NpmGlobalBinCandidates {
|
||||
param(
|
||||
[string]$NpmPrefix
|
||||
)
|
||||
|
||||
$candidates = @()
|
||||
if (-not [string]::IsNullOrWhiteSpace($NpmPrefix)) {
|
||||
$candidates += $NpmPrefix
|
||||
$candidates += (Join-Path $NpmPrefix "bin")
|
||||
}
|
||||
if (-not [string]::IsNullOrWhiteSpace($env:APPDATA)) {
|
||||
$candidates += (Join-Path $env:APPDATA "npm")
|
||||
}
|
||||
|
||||
return $candidates | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique
|
||||
}
|
||||
|
||||
function Ensure-OpenClawOnPath {
|
||||
if (Get-OpenClawCommandPath) {
|
||||
return $true
|
||||
}
|
||||
|
||||
$npmPrefix = $null
|
||||
try {
|
||||
$npmPrefix = (npm config get prefix 2>$null).Trim()
|
||||
} catch {
|
||||
$npmPrefix = $null
|
||||
}
|
||||
|
||||
$npmBins = Get-NpmGlobalBinCandidates -NpmPrefix $npmPrefix
|
||||
foreach ($npmBin in $npmBins) {
|
||||
if (-not (Test-Path (Join-Path $npmBin "openclaw.cmd"))) {
|
||||
continue
|
||||
}
|
||||
|
||||
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
|
||||
if (-not ($userPath -split ";" | Where-Object { $_ -ieq $npmBin })) {
|
||||
[Environment]::SetEnvironmentVariable("Path", "$userPath;$npmBin", "User")
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
Write-Host "[!] Added $npmBin to user PATH (restart terminal if command not found)" -ForegroundColor Yellow
|
||||
}
|
||||
return $true
|
||||
}
|
||||
|
||||
Write-Host "[!] openclaw is not on PATH yet." -ForegroundColor Yellow
|
||||
Write-Host "Restart PowerShell or add the npm global install folder to PATH." -ForegroundColor Yellow
|
||||
if ($npmBins.Count -gt 0) {
|
||||
Write-Host "Expected path (one of):" -ForegroundColor Gray
|
||||
foreach ($npmBin in $npmBins) {
|
||||
Write-Host " $npmBin" -ForegroundColor Cyan
|
||||
}
|
||||
} else {
|
||||
Write-Host "Hint: run \"npm config get prefix\" to find your npm global path." -ForegroundColor Gray
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function Ensure-Pnpm {
|
||||
if (Get-Command pnpm -ErrorAction SilentlyContinue) {
|
||||
return
|
||||
}
|
||||
if (Get-Command corepack -ErrorAction SilentlyContinue) {
|
||||
try {
|
||||
corepack enable | Out-Null
|
||||
corepack prepare pnpm@latest --activate | Out-Null
|
||||
if (Get-Command pnpm -ErrorAction SilentlyContinue) {
|
||||
Write-Host "[OK] pnpm installed via corepack" -ForegroundColor Green
|
||||
return
|
||||
}
|
||||
} catch {
|
||||
# fallthrough to npm install
|
||||
}
|
||||
}
|
||||
Write-Host "[*] Installing pnpm..." -ForegroundColor Yellow
|
||||
$prevScriptShell = $env:NPM_CONFIG_SCRIPT_SHELL
|
||||
$env:NPM_CONFIG_SCRIPT_SHELL = "cmd.exe"
|
||||
try {
|
||||
npm install -g pnpm
|
||||
} finally {
|
||||
$env:NPM_CONFIG_SCRIPT_SHELL = $prevScriptShell
|
||||
}
|
||||
Write-Host "[OK] pnpm installed" -ForegroundColor Green
|
||||
}
|
||||
|
||||
# Install OpenClaw
|
||||
function Install-OpenClaw {
|
||||
if ([string]::IsNullOrWhiteSpace($Tag)) {
|
||||
$Tag = "latest"
|
||||
}
|
||||
Require-Git
|
||||
|
||||
# 国内环境适配:自动替换GitHub SSH地址为HTTPS+镜像加速
|
||||
git config --global url."https://github.com/".insteadOf ssh://git@github.com/
|
||||
## 暂时停用,频繁出现错误,不如直接拉github仓库
|
||||
# git config --global url."https://mirror.ghproxy.com/https://github.com/".insteadOf https://github.com/
|
||||
|
||||
# Use openclaw package for beta, openclaw for stable
|
||||
$packageName = "openclaw"
|
||||
if ($Tag -eq "beta" -or $Tag -match "^beta\.") {
|
||||
$packageName = "openclaw"
|
||||
}
|
||||
Write-Host "[*] Installing OpenClaw ($packageName@$Tag)..." -ForegroundColor Yellow
|
||||
$prevLogLevel = $env:NPM_CONFIG_LOGLEVEL
|
||||
$prevUpdateNotifier = $env:NPM_CONFIG_UPDATE_NOTIFIER
|
||||
$prevFund = $env:NPM_CONFIG_FUND
|
||||
$prevAudit = $env:NPM_CONFIG_AUDIT
|
||||
$prevScriptShell = $env:NPM_CONFIG_SCRIPT_SHELL
|
||||
$env:NPM_CONFIG_LOGLEVEL = "error"
|
||||
$env:NPM_CONFIG_UPDATE_NOTIFIER = "false"
|
||||
$env:NPM_CONFIG_FUND = "false"
|
||||
$env:NPM_CONFIG_AUDIT = "false"
|
||||
$env:NPM_CONFIG_SCRIPT_SHELL = "cmd.exe"
|
||||
try {
|
||||
# $npmOutput = npm install -g "$packageName@$Tag" 2>&1
|
||||
$npmOutput = npm install -g "$packageName@$Tag" --ignore-scripts --registry=https://registry.npmmirror.com 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "[!] npm install failed" -ForegroundColor Red
|
||||
if ($npmOutput -match "spawn git" -or $npmOutput -match "ENOENT.*git") {
|
||||
Write-Host "Error: git is missing from PATH." -ForegroundColor Red
|
||||
Write-Host "Install Git for Windows, then reopen PowerShell and retry:" -ForegroundColor Yellow
|
||||
Write-Host " https://git-scm.com/download/win" -ForegroundColor Cyan
|
||||
} else {
|
||||
Write-Host "Re-run with verbose output to see the full error:" -ForegroundColor Yellow
|
||||
Write-Host " iwr -useb https://openclaw.ai/install.ps1 | iex" -ForegroundColor Cyan
|
||||
}
|
||||
$npmOutput | ForEach-Object { Write-Host $_ }
|
||||
exit 1
|
||||
}
|
||||
} finally {
|
||||
$env:NPM_CONFIG_LOGLEVEL = $prevLogLevel
|
||||
$env:NPM_CONFIG_UPDATE_NOTIFIER = $prevUpdateNotifier
|
||||
$env:NPM_CONFIG_FUND = $prevFund
|
||||
$env:NPM_CONFIG_AUDIT = $prevAudit
|
||||
$env:NPM_CONFIG_SCRIPT_SHELL = $prevScriptShell
|
||||
}
|
||||
Write-Host "[OK] OpenClaw installed" -ForegroundColor Green
|
||||
}
|
||||
|
||||
# Install OpenClaw from GitHub
|
||||
function Install-OpenClawFromGit {
|
||||
param(
|
||||
[string]$RepoDir,
|
||||
[switch]$SkipUpdate
|
||||
)
|
||||
Require-Git
|
||||
Ensure-Pnpm
|
||||
|
||||
$repoUrl = "https://github.com/openclaw/openclaw.git"
|
||||
Write-Host "[*] Installing OpenClaw from GitHub ($repoUrl)..." -ForegroundColor Yellow
|
||||
|
||||
if (-not (Test-Path $RepoDir)) {
|
||||
git clone $repoUrl $RepoDir
|
||||
}
|
||||
|
||||
if (-not $SkipUpdate) {
|
||||
if (-not (git -C $RepoDir status --porcelain 2>$null)) {
|
||||
git -C $RepoDir pull --rebase 2>$null
|
||||
} else {
|
||||
Write-Host "[!] Repo is dirty; skipping git pull" -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
Write-Host "[!] Git update disabled; skipping git pull" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Remove-LegacySubmodule -RepoDir $RepoDir
|
||||
|
||||
$prevPnpmScriptShell = $env:NPM_CONFIG_SCRIPT_SHELL
|
||||
$env:NPM_CONFIG_SCRIPT_SHELL = "cmd.exe"
|
||||
try {
|
||||
pnpm -C $RepoDir install
|
||||
if (-not (pnpm -C $RepoDir ui:build)) {
|
||||
Write-Host "[!] UI build failed; continuing (CLI may still work)" -ForegroundColor Yellow
|
||||
}
|
||||
pnpm -C $RepoDir build
|
||||
} finally {
|
||||
$env:NPM_CONFIG_SCRIPT_SHELL = $prevPnpmScriptShell
|
||||
}
|
||||
|
||||
$binDir = Join-Path $env:USERPROFILE ".local\\bin"
|
||||
if (-not (Test-Path $binDir)) {
|
||||
New-Item -ItemType Directory -Force -Path $binDir | Out-Null
|
||||
}
|
||||
$cmdPath = Join-Path $binDir "openclaw.cmd"
|
||||
$cmdContents = "@echo off`r`nnode ""$RepoDir\\dist\\entry.js"" %*`r`n"
|
||||
Set-Content -Path $cmdPath -Value $cmdContents -NoNewline
|
||||
|
||||
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
|
||||
if (-not ($userPath -split ";" | Where-Object { $_ -ieq $binDir })) {
|
||||
[Environment]::SetEnvironmentVariable("Path", "$userPath;$binDir", "User")
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
||||
Write-Host "[!] Added $binDir to user PATH (restart terminal if command not found)" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Write-Host "[OK] OpenClaw wrapper installed to $cmdPath" -ForegroundColor Green
|
||||
Write-Host "[i] This checkout uses pnpm. For deps, run: pnpm install (avoid npm install in the repo)." -ForegroundColor Gray
|
||||
}
|
||||
|
||||
# Run doctor for migrations (safe, non-interactive)
|
||||
function Run-Doctor {
|
||||
Write-Host "[*] Running doctor to migrate settings..." -ForegroundColor Yellow
|
||||
try {
|
||||
Invoke-OpenClawCommand doctor --non-interactive
|
||||
} catch {
|
||||
# Ignore errors from doctor
|
||||
}
|
||||
Write-Host "[OK] Migration complete" -ForegroundColor Green
|
||||
}
|
||||
|
||||
function Test-GatewayServiceLoaded {
|
||||
try {
|
||||
$statusJson = (Invoke-OpenClawCommand daemon status --json 2>$null)
|
||||
if ([string]::IsNullOrWhiteSpace($statusJson)) {
|
||||
return $false
|
||||
}
|
||||
$parsed = $statusJson | ConvertFrom-Json
|
||||
if ($parsed -and $parsed.service -and $parsed.service.loaded) {
|
||||
return $true
|
||||
}
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function Refresh-GatewayServiceIfLoaded {
|
||||
if (-not (Get-OpenClawCommandPath)) {
|
||||
return
|
||||
}
|
||||
if (-not (Test-GatewayServiceLoaded)) {
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host "[*] Refreshing loaded gateway service..." -ForegroundColor Yellow
|
||||
try {
|
||||
Invoke-OpenClawCommand gateway install --force | Out-Null
|
||||
} catch {
|
||||
Write-Host "[!] Gateway service refresh failed; continuing." -ForegroundColor Yellow
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
Invoke-OpenClawCommand gateway restart | Out-Null
|
||||
Invoke-OpenClawCommand gateway status --probe --json | Out-Null
|
||||
Write-Host "[OK] Gateway service refreshed" -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Host "[!] Gateway service restart failed; continuing." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
function Get-LegacyRepoDir {
|
||||
if (-not [string]::IsNullOrWhiteSpace($env:OPENCLAW_GIT_DIR)) {
|
||||
return $env:OPENCLAW_GIT_DIR
|
||||
}
|
||||
$userHome = [Environment]::GetFolderPath("UserProfile")
|
||||
return (Join-Path $userHome "openclaw")
|
||||
}
|
||||
|
||||
function Remove-LegacySubmodule {
|
||||
param(
|
||||
[string]$RepoDir
|
||||
)
|
||||
if ([string]::IsNullOrWhiteSpace($RepoDir)) {
|
||||
$RepoDir = Get-LegacyRepoDir
|
||||
}
|
||||
$legacyDir = Join-Path $RepoDir "Peekaboo"
|
||||
if (Test-Path $legacyDir) {
|
||||
Write-Host "[!] Removing legacy submodule checkout: $legacyDir" -ForegroundColor Yellow
|
||||
Remove-Item -Recurse -Force $legacyDir
|
||||
}
|
||||
}
|
||||
|
||||
# Main installation flow
|
||||
function Main {
|
||||
if ($InstallMethod -ne "npm" -and $InstallMethod -ne "git") {
|
||||
Write-Host "Error: invalid -InstallMethod (use npm or git)." -ForegroundColor Red
|
||||
exit 2
|
||||
}
|
||||
|
||||
if ($DryRun) {
|
||||
Write-Host "[OK] Dry run" -ForegroundColor Green
|
||||
Write-Host "[OK] Install method: $InstallMethod" -ForegroundColor Green
|
||||
if ($InstallMethod -eq "git") {
|
||||
Write-Host "[OK] Git dir: $GitDir" -ForegroundColor Green
|
||||
if ($NoGitUpdate) {
|
||||
Write-Host "[OK] Git update: disabled" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "[OK] Git update: enabled" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
if ($NoOnboard) {
|
||||
Write-Host "[OK] Onboard: skipped" -ForegroundColor Green
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Remove-LegacySubmodule -RepoDir $RepoDir
|
||||
|
||||
# Check for existing installation
|
||||
$isUpgrade = Check-ExistingOpenClaw
|
||||
|
||||
# Step 1: Node.js
|
||||
if (-not (Check-Node)) {
|
||||
Install-Node
|
||||
|
||||
# Verify installation
|
||||
if (-not (Check-Node)) {
|
||||
Write-Host ""
|
||||
Write-Host "Error: Node.js installation may require a terminal restart" -ForegroundColor Red
|
||||
Write-Host "Please close this terminal, open a new one, and run this installer again." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
$finalGitDir = $null
|
||||
|
||||
# Step 2: OpenClaw
|
||||
if ($InstallMethod -eq "git") {
|
||||
$finalGitDir = $GitDir
|
||||
Install-OpenClawFromGit -RepoDir $GitDir -SkipUpdate:$NoGitUpdate
|
||||
} else {
|
||||
Install-OpenClaw
|
||||
}
|
||||
|
||||
if (-not (Ensure-OpenClawOnPath)) {
|
||||
Write-Host "Install completed, but OpenClaw is not on PATH yet." -ForegroundColor Yellow
|
||||
Write-Host "Open a new terminal, then run: openclaw doctor" -ForegroundColor Cyan
|
||||
return
|
||||
}
|
||||
|
||||
Refresh-GatewayServiceIfLoaded
|
||||
|
||||
# Step 3: Run doctor for migrations if upgrading or git install
|
||||
if ($isUpgrade -or $InstallMethod -eq "git") {
|
||||
Run-Doctor
|
||||
}
|
||||
|
||||
$installedVersion = $null
|
||||
try {
|
||||
$installedVersion = (Invoke-OpenClawCommand --version 2>$null).Trim()
|
||||
} catch {
|
||||
$installedVersion = $null
|
||||
}
|
||||
if (-not $installedVersion) {
|
||||
try {
|
||||
$npmList = npm list -g --depth 0 --json 2>$null | ConvertFrom-Json
|
||||
if ($npmList -and $npmList.dependencies -and $npmList.dependencies.openclaw -and $npmList.dependencies.openclaw.version) {
|
||||
$installedVersion = $npmList.dependencies.openclaw.version
|
||||
}
|
||||
} catch {
|
||||
$installedVersion = $null
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
if ($installedVersion) {
|
||||
Write-Host "OpenClaw installed successfully ($installedVersion)!" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "OpenClaw installed successfully!" -ForegroundColor Green
|
||||
}
|
||||
Write-Host ""
|
||||
if ($isUpgrade) {
|
||||
$updateMessages = @(
|
||||
"Leveled up! New skills unlocked. You're welcome.",
|
||||
"Fresh code, same lobster. Miss me?",
|
||||
"Back and better. Did you even notice I was gone?",
|
||||
"Update complete. I learned some new tricks while I was out.",
|
||||
"Upgraded! Now with 23% more sass.",
|
||||
"I've evolved. Try to keep up.",
|
||||
"New version, who dis? Oh right, still me but shinier.",
|
||||
"Patched, polished, and ready to pinch. Let's go.",
|
||||
"The lobster has molted. Harder shell, sharper claws.",
|
||||
"Update done! Check the changelog or just trust me, it's good.",
|
||||
"Reborn from the boiling waters of npm. Stronger now.",
|
||||
"I went away and came back smarter. You should try it sometime.",
|
||||
"Update complete. The bugs feared me, so they left.",
|
||||
"New version installed. Old version sends its regards.",
|
||||
"Firmware fresh. Brain wrinkles: increased.",
|
||||
"I've seen things you wouldn't believe. Anyway, I'm updated.",
|
||||
"Back online. The changelog is long but our friendship is longer.",
|
||||
"Upgraded! Peter fixed stuff. Blame him if it breaks.",
|
||||
"Molting complete. Please don't look at my soft shell phase.",
|
||||
"Version bump! Same chaos energy, fewer crashes (probably)."
|
||||
)
|
||||
Write-Host (Get-Random -InputObject $updateMessages) -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
} else {
|
||||
$completionMessages = @(
|
||||
"Ahh nice, I like it here. Got any snacks? ",
|
||||
"Home sweet home. Don't worry, I won't rearrange the furniture.",
|
||||
"I'm in. Let's cause some responsible chaos.",
|
||||
"Installation complete. Your productivity is about to get weird.",
|
||||
"Settled in. Time to automate your life whether you're ready or not.",
|
||||
"Cozy. I've already read your calendar. We need to talk.",
|
||||
"Finally unpacked. Now point me at your problems.",
|
||||
"cracks claws Alright, what are we building?",
|
||||
"The lobster has landed. Your terminal will never be the same.",
|
||||
"All done! I promise to only judge your code a little bit."
|
||||
)
|
||||
Write-Host (Get-Random -InputObject $completionMessages) -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
if ($InstallMethod -eq "git") {
|
||||
Write-Host "Source checkout: $finalGitDir" -ForegroundColor Cyan
|
||||
Write-Host "Wrapper: $env:USERPROFILE\\.local\\bin\\openclaw.cmd" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
if ($isUpgrade) {
|
||||
Write-Host "Upgrade complete. Run " -NoNewline
|
||||
Write-Host "openclaw doctor" -ForegroundColor Cyan -NoNewline
|
||||
Write-Host " to check for additional migrations."
|
||||
} else {
|
||||
if ($NoOnboard) {
|
||||
Write-Host "Skipping onboard (requested). Run " -NoNewline
|
||||
Write-Host "openclaw onboard" -ForegroundColor Cyan -NoNewline
|
||||
Write-Host " later."
|
||||
} else {
|
||||
Write-Host "Starting setup..." -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Invoke-OpenClawCommand onboard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Main
|
||||
Loading…
Reference in New Issue