From 853dc1812f7f0599b7922c267e8802fb1eb0dda4 Mon Sep 17 00:00:00 2001 From: oliver Date: Wed, 29 Apr 2026 01:10:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B6=E6=95=9B=E5=BE=AE=E4=BF=A1=20sidecar?= =?UTF-8?q?=20=E5=88=B0=E5=AE=98=E6=96=B9=E5=8D=95=E9=93=BE=E8=B7=AF?= =?UTF-8?q?=E5=B9=B6=E5=90=8C=E6=AD=A5=E6=96=87=E6=A1=A3=E4=B8=8E=E5=9B=9E?= =?UTF-8?q?=E5=BD=92=E6=B5=8B=E8=AF=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除 weixin 安装与启动脚本中的 legacy/localSource 分支,只保留 official_runner 路径,统一开源安装命令并更新 RUNBOOK/Quickstart/README,确保脚本行为与测试预期一致。 Made-with: Cursor --- README.md | 4 +- docs/OPEN_SOURCE_QUICKSTART.md | 2 +- docs/RUNBOOK.md | 36 ++------- runtime/operations/scripts/weixin_install.ps1 | 79 +++++-------------- runtime/operations/scripts/weixin_login.ps1 | 2 +- runtime/operations/scripts/weixin_start.ps1 | 25 ++---- tests/test_weixin_official_scripts.py | 11 +-- 7 files changed, 43 insertions(+), 116 deletions(-) diff --git a/README.md b/README.md index 8812e0e1..4d8172ee 100644 --- a/README.md +++ b/README.md @@ -33,13 +33,13 @@ powershell -ExecutionPolicy Bypass -File .\scripts\stop_gateway.ps1 -Force ### 3) Weixin (Personal WeChat): install → login → start ```powershell -powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_install.ps1 -UseOpenclawCli +powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_install.ps1 powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_login.ps1 powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_start.ps1 ``` Notes: -- `weixin_install.ps1 -UseOpenclawCli` does **not** require global `openclaw` CLI installation; runtime deps are installed locally in sidecar workspace. +- `weixin_install.ps1` does **not** require global `openclaw` CLI installation; runtime deps are installed locally in sidecar workspace. - `.\scripts\start_all.ps1 -Background` now skips missing Weixin/WhatsApp sidecars gracefully (warn + continue), so Admin/Chat can still boot on fresh installs. - Admin supports channel dispatch controls for Weixin/WhatsApp (bind specialist / comprehensive), with default `generalist`. diff --git a/docs/OPEN_SOURCE_QUICKSTART.md b/docs/OPEN_SOURCE_QUICKSTART.md index 0449ac4b..dd97834a 100644 --- a/docs/OPEN_SOURCE_QUICKSTART.md +++ b/docs/OPEN_SOURCE_QUICKSTART.md @@ -35,7 +35,7 @@ Notes: ## Path B: Enable Weixin (Personal WeChat) ```powershell -powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_install.ps1 -UseOpenclawCli +powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_install.ps1 powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_login.ps1 powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_start.ps1 ``` diff --git a/docs/RUNBOOK.md b/docs/RUNBOOK.md index 425ed1dd..c1f0137e 100644 --- a/docs/RUNBOOK.md +++ b/docs/RUNBOOK.md @@ -78,7 +78,7 @@ powershell -ExecutionPolicy Bypass -File .\scripts\stop_gateway.ps1 -Force > 这一步会安装/更新官方插件到:`%USERPROFILE%\.openclaw\extensions\openclaw-weixin\` ```powershell -powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_install.ps1 -UseOpenclawCli +powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_install.ps1 ``` ### 1.1.5 扫码登录(绑定账号) @@ -89,8 +89,8 @@ powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_log 按提示扫码完成绑定(会写入账号 ID / token 等状态到 `%USERPROFILE%\.openclaw\openclaw-weixin\`)。 -> 说明:这里的 `-UseOpenclawCli` **不要求你全局安装 openclaw**(不需要 `npm install -g openclaw`)。 -> 脚本会在 `data/channel_sidecar/oclaw-weixin/` 下本地安装 `openclaw` npm 包,并用 `npx openclaw ...` 驱动官方插件完成扫码与状态写入。 +> 说明:`weixin_install.ps1` **不要求你全局安装 openclaw**(不需要 `npm install -g openclaw`)。 +> 脚本会在 `data/channel_sidecar/oclaw-weixin/` 下安装本地运行时依赖,并完成官方插件安装。 ### 1.1.6 启动微信 sidecar(原生模式) @@ -114,7 +114,7 @@ powershell -ExecutionPolicy Bypass -File .\runtime\operations\scripts\weixin_sta - **启动网关提示端口占用 / 你以为重启了但没生效** - 用 `stop_gateway.ps1 -Force` 强制按端口清理旧监听进程,然后再启动。 - **Node 版本不对** - - 官方插件要求 `node >=22`;请升级 Node 后重新执行 `weixin_install.ps1 -UseOpenclawCli`。 + - 官方插件要求 `node >=22`;请升级 Node 后重新执行 `weixin_install.ps1`。 --- @@ -222,17 +222,15 @@ Linux/macOS: - 本仓库宿主适配负责: - 把官方入站消息转换成 `oclaw` 可消费的本地 payload - 通过本地 `/weixin/native/reply` 同步生成回复 - - 保留一个历史 `runner.ts` fallback,便于短期回滚 对应脚本行为: -- `runtime/operations/scripts/weixin_install.ps1 -UseOpenclawCli` +- `runtime/operations/scripts/weixin_install.ps1` - 安装官方 `openclaw-weixin` 插件 - 安装运行官方模块所需的本地 Node 依赖 - - 同步 `runtime/operations/weixin_bridge/official_runner.ts` / `runner.ts` / `login.ts` + - 同步 `runtime/operations/weixin_bridge/official_runner.ts` / `login.ts` - `runtime/operations/scripts/weixin_start.ps1` - - 默认启动 `official_runner.ts` - - 设置 `AIA_WEIXIN_RUNNER_MODE=legacy` 时,临时回退到历史 `runner.ts` + - 仅启动 `official_runner.ts`(官方单链路) 现阶段主路径建议: @@ -549,25 +547,7 @@ npm install images-mcp powershell -ExecutionPolicy Bypass -File .\scripts\weixin_install.ps1 ``` -注意: - -- 脚本支持两种模式: - - 官方插件模式:`-UseOpenclawCli`(不校验 `runner.ts/login.ts`) - - 本地 sidecar 模式:`-LocalSourcePath`(会强校验 `runner.ts/login.ts`) - -- 默认按本地 sidecar 模式处理:必须传 `-LocalSourcePath`(指向你们自研 weixin sidecar 源码目录)。 - -```powershell -powershell -ExecutionPolicy Bypass -File .\scripts\weixin_install.ps1 -LocalSourcePath "D:\path\to\your-weixin-module" -``` - -- 若你要临时切回官方链路,可显式指定: - -```powershell -powershell -ExecutionPolicy Bypass -File .\scripts\weixin_install.ps1 -UseOpenclawCli -``` - -- 仅本地 sidecar 模式会强校验 `runner.ts` / `login.ts` 是否存在;官方插件模式不做该校验。 +注意:当前仅保留官方插件单链路,直接执行 `weixin_install.ps1` 即可。 安装目录: diff --git a/runtime/operations/scripts/weixin_install.ps1 b/runtime/operations/scripts/weixin_install.ps1 index 26abdbdc..f1d74023 100644 --- a/runtime/operations/scripts/weixin_install.ps1 +++ b/runtime/operations/scripts/weixin_install.ps1 @@ -1,7 +1,5 @@ param( - [string]$ChannelId = "oclaw-weixin", - [string]$LocalSourcePath = "", - [switch]$UseOpenclawCli = $false + [string]$ChannelId = "oclaw-weixin" ) $ErrorActionPreference = "Stop" @@ -16,6 +14,16 @@ $oclawRoot = Resolve-RepoRoot $sidecarRoot = Join-Path $oclawRoot "data\\channel_sidecar\\$ChannelId" $stateDir = Join-Path $sidecarRoot "state" $pluginRoot = Join-Path $env:USERPROFILE ".openclaw\\extensions\\openclaw-weixin" +function Sync-WeixinBridgeRunners { + $bridgeSrc = Join-Path $oclawRoot "runtime\\operations\\weixin_bridge" + foreach ($name in @("official_runner.ts", "login.ts")) { + $srcPath = Join-Path $bridgeSrc $name + if (-not (Test-Path $srcPath)) { + throw "missing bridge source file: $srcPath" + } + Copy-Item -Path $srcPath -Destination (Join-Path $sidecarRoot $name) -Force + } +} New-Item -ItemType Directory -Force -Path $sidecarRoot | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $sidecarRoot "logs") | Out-Null @@ -36,52 +44,6 @@ function Ensure-OfficialPluginRuntimeDeps { } } -if ($UseOpenclawCli) { - # Do not require a globally-installed openclaw CLI. - # We install openclaw into the sidecar runtime and put node_modules/.bin on PATH - # so the official installer can run `openclaw ...` commands. - Push-Location $sidecarRoot - try { - if (-not (Test-Path (Join-Path $sidecarRoot "package.json"))) { - npm.cmd init -y | Out-Null - if ($LASTEXITCODE -ne 0) { - throw "npm init failed with exit code $LASTEXITCODE" - } - } - npm.cmd install openclaw@latest --save - if ($LASTEXITCODE -ne 0) { - throw "npm install openclaw failed with exit code $LASTEXITCODE" - } - $env:PATH = (Join-Path $sidecarRoot "node_modules\\.bin") + ";" + $env:PATH - npx.cmd -y @tencent-weixin/openclaw-weixin-cli@latest install - if ($LASTEXITCODE -ne 0) { - throw "openclaw-weixin-cli install failed with exit code $LASTEXITCODE" - } - } finally { - Pop-Location - } - Ensure-OfficialPluginRuntimeDeps - Push-Location $sidecarRoot - try { - npm.cmd install openclaw@latest --save tsx@4.21.0 typescript@6.0.3 - if ($LASTEXITCODE -ne 0) { - throw "npm install bridge runtime deps failed with exit code $LASTEXITCODE" - } - $bridgeSrc = Join-Path $oclawRoot "runtime\\operations\\weixin_bridge" - Copy-Item -Path (Join-Path $bridgeSrc "runner.ts") -Destination (Join-Path $sidecarRoot "runner.ts") -Force - Copy-Item -Path (Join-Path $bridgeSrc "official_runner.ts") -Destination (Join-Path $sidecarRoot "official_runner.ts") -Force - Copy-Item -Path (Join-Path $bridgeSrc "login.ts") -Destination (Join-Path $sidecarRoot "login.ts") -Force - } finally { - Pop-Location - } - Write-Host "[ok] installed official openclaw-weixin plugin + native/fallback sidecar runtime" - exit 0 -} - -if (-not $LocalSourcePath) { - throw "LocalSourcePath is required in sidecar mode. Example: .\\scripts\\weixin_install.ps1 -LocalSourcePath D:\\path\\to\\your-weixin-module" -} - Push-Location $sidecarRoot try { if (-not (Test-Path (Join-Path $sidecarRoot "package.json"))) { @@ -90,21 +52,18 @@ try { throw "npm init failed with exit code $LASTEXITCODE" } } - - $src = (Resolve-Path $LocalSourcePath).Path - npm.cmd install --save-exact $src tsx@4.21.0 typescript@6.0.3 + npx.cmd -y @tencent-weixin/openclaw-weixin-cli@latest install if ($LASTEXITCODE -ne 0) { - throw "npm install local source failed with exit code $LASTEXITCODE" + throw "openclaw-weixin-cli install failed with exit code $LASTEXITCODE" } - - if (-not (Test-Path (Join-Path $sidecarRoot "runner.ts"))) { - throw "install completed but runner.ts is missing (invalid sidecar package/source)" + npm.cmd install openclaw@latest --save tsx@4.21.0 typescript@6.0.3 + if ($LASTEXITCODE -ne 0) { + throw "npm install bridge runtime deps failed with exit code $LASTEXITCODE" } - if (-not (Test-Path (Join-Path $sidecarRoot "login.ts"))) { - throw "install completed but login.ts is missing (invalid sidecar package/source)" - } - Write-Host "[ok] installed local weixin sidecar into $sidecarRoot" } finally { Pop-Location } +Ensure-OfficialPluginRuntimeDeps +Sync-WeixinBridgeRunners +Write-Host "[ok] installed official openclaw-weixin plugin sidecar runtime into $sidecarRoot" diff --git a/runtime/operations/scripts/weixin_login.ps1 b/runtime/operations/scripts/weixin_login.ps1 index eb5589dc..4e25e3c5 100644 --- a/runtime/operations/scripts/weixin_login.ps1 +++ b/runtime/operations/scripts/weixin_login.ps1 @@ -27,7 +27,7 @@ try { npm.cmd exec -- tsx login.ts exit 0 } - throw "login.ts missing. Re-run weixin_install.ps1 -UseOpenclawCli to install sidecar runtime." + throw "login.ts missing. Re-run weixin_install.ps1 to install sidecar runtime." } finally { Pop-Location } diff --git a/runtime/operations/scripts/weixin_start.ps1 b/runtime/operations/scripts/weixin_start.ps1 index 5de82b55..b2a02780 100644 --- a/runtime/operations/scripts/weixin_start.ps1 +++ b/runtime/operations/scripts/weixin_start.ps1 @@ -18,15 +18,11 @@ $logDir = Join-Path $sidecarRoot "logs" $pidFile = Join-Path $sidecarRoot "pid.txt" $bridgeSrc = Join-Path $oclawRoot "runtime\\operations\\weixin_bridge" $pluginRoot = Join-Path $env:USERPROFILE ".openclaw\\extensions\\openclaw-weixin" -$runnerMode = [string]($env:AIA_WEIXIN_RUNNER_MODE) -if (-not $runnerMode) { $runnerMode = "official" } -$runnerMode = $runnerMode.Trim().ToLowerInvariant() function Get-SidecarProcesses { $escapedSidecarRoot = $sidecarRoot.Replace("\", "\\") $patterns = @( "*$ChannelId*", - "*runner.ts*", "*official_runner.ts*", "*$escapedSidecarRoot*" ) @@ -82,7 +78,7 @@ $cleaned = Stop-SidecarProcesses Remove-Item -Force $pidFile -ErrorAction SilentlyContinue if (Test-Path $bridgeSrc) { - foreach ($name in @("runner.ts", "official_runner.ts", "login.ts")) { + foreach ($name in @("official_runner.ts", "login.ts")) { $srcPath = Join-Path $bridgeSrc $name if (Test-Path $srcPath) { Copy-Item -Path $srcPath -Destination (Join-Path $sidecarRoot $name) -Force @@ -92,27 +88,18 @@ if (Test-Path $bridgeSrc) { $logPath = Join-Path $logDir "weixin_sidecar.log" $errPath = Join-Path $logDir "weixin_sidecar.err.log" -if ((Test-Path (Join-Path $sidecarRoot "runner.ts")) -or (Test-Path (Join-Path $sidecarRoot "official_runner.ts"))) { - $runnerFile = "official_runner.ts" - if ($runnerMode -eq "legacy") { - $runnerFile = "runner.ts" - } - if ($runnerMode -eq "official") { - Ensure-OfficialPluginRuntimeDeps - } - if (-not (Test-Path (Join-Path $sidecarRoot $runnerFile))) { - throw "selected runner file missing: $runnerFile" - } +if (Test-Path (Join-Path $sidecarRoot "official_runner.ts")) { + Ensure-OfficialPluginRuntimeDeps $cmd = "cmd.exe" $args = @( "/c", - "cd /d $sidecarRoot && set OCLAW_STATE_DIR=$stateDir&& set AIA_GATEWAY_BASE_URL=$GatewayBaseUrl&& set NODE_PATH=$sidecarRoot\node_modules&& npm.cmd exec -- tsx $runnerFile" + "cd /d $sidecarRoot && set OCLAW_STATE_DIR=$stateDir&& set AIA_GATEWAY_BASE_URL=$GatewayBaseUrl&& set NODE_PATH=$sidecarRoot\node_modules&& npm.cmd exec -- tsx official_runner.ts" ) $p = Start-Process -FilePath $cmd -ArgumentList $args -WorkingDirectory $sidecarRoot -PassThru -WindowStyle Hidden -RedirectStandardOutput $logPath -RedirectStandardError $errPath Set-Content -Path $pidFile -Value $p.Id - Write-Host "[ok] started weixin sidecar pid=$($p.Id) mode=$runnerMode cleaned=$cleaned out=$logPath err=$errPath" + Write-Host "[ok] started weixin sidecar pid=$($p.Id) mode=official cleaned=$cleaned out=$logPath err=$errPath" exit 0 } -throw "No runner.ts/official_runner.ts found in sidecar root. Re-run weixin_install.ps1 -UseOpenclawCli." +throw "official_runner.ts missing in sidecar root. Re-run weixin_install.ps1." diff --git a/tests/test_weixin_official_scripts.py b/tests/test_weixin_official_scripts.py index f3d6e6f2..f97be181 100644 --- a/tests/test_weixin_official_scripts.py +++ b/tests/test_weixin_official_scripts.py @@ -10,12 +10,11 @@ def _read(rel: str) -> str: return (REPO_ROOT / rel).read_text(encoding="utf-8") -def test_weixin_start_defaults_to_official_runner() -> None: +def test_weixin_start_official_only_runner() -> None: text = _read("runtime/operations/scripts/weixin_start.ps1") - assert '$runnerMode = "official"' in text - assert '$runnerFile = "official_runner.ts"' in text - assert 'AIA_WEIXIN_RUNNER_MODE' in text + assert "mode=official" in text assert 'official_runner.ts' in text + assert "AIA_WEIXIN_RUNNER_MODE" not in text def test_weixin_status_and_stop_track_official_runner() -> None: @@ -27,8 +26,10 @@ def test_weixin_status_and_stop_track_official_runner() -> None: def test_weixin_install_copies_official_runner() -> None: text = _read("runtime/operations/scripts/weixin_install.ps1") - assert 'Copy-Item -Path (Join-Path $bridgeSrc "official_runner.ts")' in text + assert "Sync-WeixinBridgeRunners" in text + assert '"official_runner.ts"' in text assert "Ensure-OfficialPluginRuntimeDeps" in text + assert "LocalSourcePath" not in text def test_weixin_start_ensures_plugin_runtime_deps() -> None: