diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..074d6ce --- /dev/null +++ b/.gitattributes @@ -0,0 +1,21 @@ +# 锁定换行符,保证跨平台分发的脚本可用: +# - Windows 批处理 .bat/.cmd 必须 CRLF,否则部分 Windows 环境解析异常 +# - Mac/Linux 的 .command/.sh 必须 LF,否则双击/执行会报 bad interpreter +# - .mjs/.js 统一 LF +# 防止 core.autocrlf 在不同机器上把换行改乱。 + +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf + +*.command text eol=lf +*.sh text eol=lf +*.mjs text eol=lf +*.js text eol=lf +*.json text eol=lf + +# 二进制:不做换行转换 +*.png binary +*.jpg binary +*.zip binary +*.ico binary diff --git a/install/README.md b/install/README.md index 71de6c7..4b429e8 100644 --- a/install/README.md +++ b/install/README.md @@ -1,132 +1,132 @@ -# U-Claw 一键安装 / One-Line Install - -> 一行命令安装 OpenClaw + 技能包 + 模型配置 -> One command to install OpenClaw + skills + model config - -## 安装 / Install - -### Mac / Linux - -```bash -curl -fsSL https://u-claw.org/install.sh | bash -``` - -### Windows (PowerShell 管理员) - -```powershell -irm https://u-claw.org/install.ps1 | iex -``` - -### 本地运行 - -```bash -# Mac/Linux -bash install/install.sh - -# Windows -powershell -ExecutionPolicy Bypass -File install\install.ps1 -``` - -## 安装流程 - -### Mac / Linux(7 步) - -| 步骤 | 内容 | 说明 | -|------|------|------| -| 1 | Node.js v22 | 安装到 `~/.uclaw/runtime/`,系统有 v20+ 则复用 | -| 2 | OpenClaw | npm 安装到 `~/.uclaw/core/` | -| 3 | QQ 插件 | 非致命,失败不影响主功能 | -| 4 | 10 个中国技能 | 小红书、B站、微博等内容创作技能 | -| 5 | 模型配置 | 中文交互菜单,默认 DeepSeek | -| 6 | 启动脚本 | 生成 start.command (Mac) / start.sh (Linux) | -| 7 | 验证 | 检查各组件安装状态 | - -### Windows(6 步) - -| 步骤 | 内容 | 说明 | -|------|------|------| -| 1 | Node.js v22 | 下载到 `%USERPROFILE%\.uclaw\runtime\`,系统有 v20+ 则复用 | -| 2 | OpenClaw + QQ 插件 | 下载预打包 bundle,走国内镜像 | -| 3 | 10 个中国技能 | 小红书、B站、微博等内容创作技能 | -| 4 | 模型配置 | 交互菜单,默认 DeepSeek | -| 5 | 启动脚本 | 生成 start.bat | -| 6 | 验证 | 检查各组件安装状态 | - -## 支持的 AI 模型 - -### 国内(无需翻墙) - -| 编号 | 模型 | 说明 | -|------|------|------| -| 1 | DeepSeek | ⭐ 推荐,性价比最高 | -| 2 | Kimi/月之暗面 | 长文档 | -| 3 | 通义千问 | 有免费额度 | -| 4 | 智谱GLM | 学术场景 | -| 5 | MiniMax | 多模态 | -| 6 | 豆包 | 火山引擎 | -| 7 | 硅基流动 | 聚合多模型 | - -### 海外 - -| 编号 | 模型 | -|------|------| -| 8 | Claude | -| 9 | GPT | - -### 本地 - -| 编号 | 模型 | -|------|------| -| 10 | Ollama | - -## 安装目录结构 - -``` -~/.uclaw/ -├── runtime/node-{platform}/ # Node.js v22 -├── core/ # OpenClaw + QQ 插件 -│ ├── package.json -│ └── node_modules/ -│ └── openclaw/skills/ ← 技能在这里 -├── data/ -│ ├── .openclaw/openclaw.json ← 模型配置 -│ ├── memory/ ← AI 记忆 -│ └── backups/ ← 备份 -├── start.command (Mac) ← 启动脚本 -└── start.bat (Windows) ← 启动脚本 -``` - -## 技术细节 - -- **Node.js**: 只装到 `~/.uclaw/runtime/`,不动系统 Node;系统已有 v20+ 则复用 -- **镜像**: Mac/Linux 全走 `npmmirror.com`(Node 二进制 + npm 包);Windows bundle 下载依次尝试 ghfast.top → ghproxy.net → gh.idayer.com → 直连,国内无需翻墙 -- **Windows 编码**: `chcp 65001` + UTF8 输出确保中文显示 -- **管道模式**: `curl | bash` 时自动跳过交互,使用默认配置 -- **卸载**: `rm -rf ~/.uclaw` (Mac/Linux) 或删除 `%USERPROFILE%\.uclaw` (Windows) - -## 包含技能 - -| 技能 | 用途 | -|------|------| -| xiaohongshu-writer | 小红书笔记写作 | -| bilibili-helper | B站视频优化 | -| weibo-poster | 微博内容创作 | -| wechat-article | 微信公众号文章 | -| zhihu-writer | 知乎回答/文章 | -| douyin-script | 抖音短视频脚本 | -| china-search | 国内搜索引擎 | -| china-translate | 中英互译 | -| china-weather | 天气查询 | -| deepseek-helper | DeepSeek API 助手 | - -## 与其他分发形式的关系 - -``` -install/ ← 一键在线安装(本模块) -portable/ ← U 盘便携版 -u-claw-app/ ← Electron 桌面版 -bootable/ ← Linux 可启动 U 盘 -``` - -install/ 安装的结果与 portable/ 的 Mac-Install.command 相同, -区别是不需要 U 盘,直接从网络下载所有组件。 +# U-Claw 一键安装 / One-Line Install + +> 一行命令安装 OpenClaw + 技能包 + 模型配置 +> One command to install OpenClaw + skills + model config + +## 安装 / Install + +### Mac / Linux + +```bash +curl -fsSL https://u-claw.org/install.sh | bash +``` + +### Windows (PowerShell 管理员) + +```powershell +irm https://u-claw.org/install.ps1 | iex +``` + +### 本地运行 + +```bash +# Mac/Linux +bash install/install.sh + +# Windows +powershell -ExecutionPolicy Bypass -File install\install.ps1 +``` + +## 安装流程 + +### Mac / Linux(7 步) + +| 步骤 | 内容 | 说明 | +|------|------|------| +| 1 | Node.js v22 | 安装到 `~/.uclaw/runtime/`,系统有 v20+ 则复用 | +| 2 | OpenClaw | npm 安装到 `~/.uclaw/core/` | +| 3 | QQ 插件 | 非致命,失败不影响主功能 | +| 4 | 10 个中国技能 | 小红书、B站、微博等内容创作技能 | +| 5 | 模型配置 | 中文交互菜单,默认 DeepSeek | +| 6 | 启动脚本 | 生成 start.command (Mac) / start.sh (Linux) | +| 7 | 验证 | 检查各组件安装状态 | + +### Windows(6 步) + +| 步骤 | 内容 | 说明 | +|------|------|------| +| 1 | Node.js v22 | 下载到 `%USERPROFILE%\.uclaw\runtime\`,系统有 v20+ 则复用 | +| 2 | OpenClaw + QQ 插件 | 下载预打包 bundle,走国内镜像 | +| 3 | 10 个中国技能 | 小红书、B站、微博等内容创作技能 | +| 4 | 模型配置 | 交互菜单,默认 DeepSeek | +| 5 | 启动脚本 | 生成 start.bat | +| 6 | 验证 | 检查各组件安装状态 | + +## 支持的 AI 模型 + +### 国内(无需翻墙) + +| 编号 | 模型 | 说明 | +|------|------|------| +| 1 | DeepSeek | ⭐ 推荐,性价比最高 | +| 2 | Kimi/月之暗面 | 长文档 | +| 3 | 通义千问 | 有免费额度 | +| 4 | 智谱GLM | 学术场景 | +| 5 | MiniMax | 多模态 | +| 6 | 豆包 | 火山引擎 | +| 7 | 硅基流动 | 聚合多模型 | + +### 海外 + +| 编号 | 模型 | +|------|------| +| 8 | Claude | +| 9 | GPT | + +### 本地 + +| 编号 | 模型 | +|------|------| +| 10 | Ollama | + +## 安装目录结构 + +``` +~/.uclaw/ +├── runtime/node-{platform}/ # Node.js v22 +├── core/ # OpenClaw + QQ 插件 +│ ├── package.json +│ └── node_modules/ +│ └── openclaw/skills/ ← 技能在这里 +├── data/ +│ ├── .openclaw/openclaw.json ← 模型配置 +│ ├── memory/ ← AI 记忆 +│ └── backups/ ← 备份 +├── start.command (Mac) ← 启动脚本 +└── start.bat (Windows) ← 启动脚本 +``` + +## 技术细节 + +- **Node.js**: 只装到 `~/.uclaw/runtime/`,不动系统 Node;系统已有 v20+ 则复用 +- **镜像**: Mac/Linux 全走 `npmmirror.com`(Node 二进制 + npm 包);Windows bundle 下载依次尝试 ghfast.top → ghproxy.net → gh.idayer.com → 直连,国内无需翻墙 +- **Windows 编码**: `chcp 65001` + UTF8 输出确保中文显示 +- **管道模式**: `curl | bash` 时自动跳过交互,使用默认配置 +- **卸载**: `rm -rf ~/.uclaw` (Mac/Linux) 或删除 `%USERPROFILE%\.uclaw` (Windows) + +## 包含技能 + +| 技能 | 用途 | +|------|------| +| xiaohongshu-writer | 小红书笔记写作 | +| bilibili-helper | B站视频优化 | +| weibo-poster | 微博内容创作 | +| wechat-article | 微信公众号文章 | +| zhihu-writer | 知乎回答/文章 | +| douyin-script | 抖音短视频脚本 | +| china-search | 国内搜索引擎 | +| china-translate | 中英互译 | +| china-weather | 天气查询 | +| deepseek-helper | DeepSeek API 助手 | + +## 与其他分发形式的关系 + +``` +install/ ← 一键在线安装(本模块) +portable/ ← U 盘便携版 +u-claw-app/ ← Electron 桌面版 +bootable/ ← Linux 可启动 U 盘 +``` + +install/ 安装的结果与 portable/ 的 Mac-Install.command 相同, +区别是不需要 U 盘,直接从网络下载所有组件。 diff --git a/portable/Windows-Menu.bat b/portable/Windows-Menu.bat index 37d2901..b74c590 100644 --- a/portable/Windows-Menu.bat +++ b/portable/Windows-Menu.bat @@ -1,630 +1,630 @@ -@echo off -setlocal EnableDelayedExpansion -chcp 65001 >nul 2>&1 -title U-Claw Menu - -set "UCLAW_DIR=%~dp0" -set "APP_DIR=%UCLAW_DIR%app" - -REM Migration shim: rename old core-win to core for existing USB users -if exist "%APP_DIR%\core-win" if not exist "%APP_DIR%\core" ren "%APP_DIR%\core-win" core - -set "CORE_DIR=%APP_DIR%\core" -set "DATA_DIR=%UCLAW_DIR%data" -set "STATE_DIR=%DATA_DIR%\.openclaw" -set "NODE_DIR=%UCLAW_DIR%app\runtime\node-win-x64" -set "NODE_BIN=%NODE_DIR%\node.exe" -set "NPM_BIN=%NODE_DIR%\npm.cmd" - -set "OPENCLAW_HOME=%DATA_DIR%" -set "OPENCLAW_STATE_DIR=%STATE_DIR%" -set "OPENCLAW_CONFIG_PATH=%STATE_DIR%\openclaw.json" -REM U-Claw opens the local dashboard directly; disable mDNS discovery on Windows -REM to avoid OpenClaw/@homebridge ciao crashes during bonjour re-advertise. -set "OPENCLAW_DISABLE_BONJOUR=1" -set "PATH=%NODE_DIR%;%PATH%" - -set "OPENCLAW_MJS=%CORE_DIR%\node_modules\openclaw\openclaw.mjs" -set "LOG_DIR=%DATA_DIR%\logs" -set "BACKUP_DIR=%DATA_DIR%\backups" - -if not exist "%STATE_DIR%" mkdir "%STATE_DIR%" -if not exist "%DATA_DIR%\memory" mkdir "%DATA_DIR%\memory" -if not exist "%BACKUP_DIR%" mkdir "%BACKUP_DIR%" -if not exist "%LOG_DIR%" mkdir "%LOG_DIR%" - -:menu -cls -echo. -echo ======================================== -echo U-Claw v1.1 - Menu -echo Portable AI Agent -echo ======================================== -echo. - -if exist "%NODE_BIN%" ( - for /f "tokens=*" %%v in ('"%NODE_BIN%" --version') do echo Node: %%v -) else ( - echo [!] Node.js not found -) -if exist "%STATE_DIR%\openclaw.json" (echo Config: OK) else (echo Config: NOT SET) -echo. -echo -- Config -- -echo [1] Setup wizard (model, API key) -echo [2] Open web dashboard -echo. -echo -- Chat Platforms -- -echo [3] QQ Bot (pre-installed, enter ID only) -echo [4] Other platforms (Feishu/Telegram/WeChat) -echo. -echo -- Maintenance -- -echo [5] Diagnostics -echo [6] Backup config -echo [7] Restore backup -echo [8] System info -echo. -echo -- Advanced -- -echo [9] Kill residual processes -echo [10] View logs -echo [11] Factory reset -echo [12] Uninstall -echo [13] Check for updates -echo [14] Disk cleanup -echo [15] Plugin management -echo. -echo [0] Exit -echo. -set /p choice=" Choose [0-15]: " - -if "%choice%"=="1" goto :onboard -if "%choice%"=="2" goto :dashboard -if "%choice%"=="3" goto :qqbot -if "%choice%"=="4" goto :channels -if "%choice%"=="5" goto :doctor -if "%choice%"=="6" goto :backup -if "%choice%"=="7" goto :restore -if "%choice%"=="8" goto :sysinfo -if "%choice%"=="9" goto :killproc -if "%choice%"=="10" goto :viewlogs -if "%choice%"=="11" goto :factoryreset -if "%choice%"=="12" goto :uninstall -if "%choice%"=="13" goto :checkupdate -if "%choice%"=="14" goto :diskcleanup -if "%choice%"=="15" goto :plugins -if "%choice%"=="0" exit /b 0 -echo Invalid choice -pause -goto :menu - -:onboard -echo. -echo === Setup Wizard === -echo. -echo DeepSeek - Custom Provider, URL: https://api.deepseek.com/v1 -echo Kimi - Moonshot AI -echo Qwen - Qwen -echo Doubao - Volcano Engine -echo. -cd /d "%CORE_DIR%" -"%NODE_BIN%" "%OPENCLAW_MJS%" onboard -pause -goto :menu - -:dashboard -echo. -echo Starting gateway... -set PORT=18789 -:find_port -netstat -an | findstr ":%PORT% " | findstr "LISTENING" >nul 2>&1 -if !errorlevel!==0 ( - set /a PORT+=1 - if !PORT! gtr 18799 (echo No available port & pause & goto :menu) - goto :find_port -) -cd /d "%CORE_DIR%" -if not exist "%STATE_DIR%\openclaw.json" ( - (echo {"gateway":{"mode":"local","auth":{"token":"uclaw"}}})>"%STATE_DIR%\openclaw.json" -) - -REM Read token from config -set "TOKEN=uclaw" -if exist "%STATE_DIR%\openclaw.json" ( - for /f "tokens=*" %%t in ('"%NODE_BIN%" -e "try{const c=JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'));console.log((c.gateway&&c.gateway.auth&&c.gateway.auth.token)||'uclaw')}catch(e){console.log('uclaw')}" "%STATE_DIR%\openclaw.json"') do set "TOKEN=%%t" -) - -start /B "" cmd /c "timeout /t 3 /nobreak >nul && start http://127.0.0.1:!PORT!/#token=!TOKEN!" -"%NODE_BIN%" "%OPENCLAW_MJS%" gateway run --allow-unconfigured --force --port !PORT! -pause -goto :menu - -:qqbot -echo. -echo === QQ Bot Setup === -echo. -echo QQ plugin is pre-installed! -echo You only need your AppID and AppSecret. -echo. -echo Get them at: q.qq.com (create a bot) -echo. -set /p qqid=" AppID: " -set /p qqsecret=" AppSecret: " -if "%qqid%"=="" goto :qq_cancel -if "%qqsecret%"=="" goto :qq_cancel -cd /d "%CORE_DIR%" -"%NODE_BIN%" "%OPENCLAW_MJS%" channels add --channel qqbot --token "%qqid%:%qqsecret%" -echo. -set /p qqallow=" Your QQ number (allowlist, empty to skip): " -if not "%qqallow%"=="" "%NODE_BIN%" "%OPENCLAW_MJS%" config set channels.qqbot.allowFrom "%qqallow%" -echo. -echo QQ Bot configured! Restart gateway to apply. -pause -goto :menu -:qq_cancel -echo Cancelled. -pause -goto :menu - -:channels -echo. -echo === Other Platforms === -echo. -echo [a] Feishu (Lark) - Enterprise -echo [b] Telegram - International -echo [c] WeChat (plugin) - iPad protocol -echo [d] Discord -echo. -set /p ch_choice=" Choose (a-d, empty to cancel): " -if "%ch_choice%"=="a" ( - echo. - echo Feishu setup: - echo 1. Visit open.feishu.cn/app to create an app - echo 2. Get App ID and App Secret - echo 3. Run Setup wizard [1] to bind -) -if "%ch_choice%"=="b" ( - echo. - echo Telegram setup: - echo 1. Message @BotFather on Telegram - echo 2. Create a bot and get the token - echo 3. Run Setup wizard [1] to bind -) -if "%ch_choice%"=="c" ( - echo. - echo Installing WeChat plugin... - cd /d "%CORE_DIR%" - "%NODE_BIN%" "%OPENCLAW_MJS%" plugins install @icesword760/openclaw-wechat - echo WeChat plugin installed! -) -if "%ch_choice%"=="d" ( - echo. - echo Discord setup: - echo 1. Visit discord.com/developers/applications - echo 2. Create a bot and get the token - echo 3. Run Setup wizard [1] to bind -) -echo. -pause -goto :menu - -:doctor -cd /d "%CORE_DIR%" -"%NODE_BIN%" "%OPENCLAW_MJS%" doctor --repair -pause -goto :menu - -:backup -echo. -set "TS=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%" -set "TS=!TS: =0!" -set "BK=%BACKUP_DIR%\backup_!TS!" -mkdir "!BK!" 2>nul -set "BK_COUNT=0" -if exist "%STATE_DIR%\openclaw.json" ( - copy "%STATE_DIR%\openclaw.json" "!BK!\" >nul - echo + openclaw.json - set /a BK_COUNT+=1 -) -if exist "%DATA_DIR%\memory" ( - xcopy /s /q "%DATA_DIR%\memory" "!BK!\memory\" >nul 2>nul - echo + memory/ - set /a BK_COUNT+=1 -) -echo. -if !BK_COUNT!==0 ( - echo Nothing to backup. - rmdir "!BK!" 2>nul -) else ( - for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '!BK!' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1KB" 2^>nul') do echo Size: %%s KB - echo Backup saved: !BK! -) -pause -goto :menu - -:restore -echo. -echo === Restore Backup === -echo. -echo Available backups: -echo. -set "BK_NUM=0" -for /d %%d in ("%BACKUP_DIR%\*") do ( - set /a BK_NUM+=1 - echo [!BK_NUM!] %%~nxd - set "BK_PATH_!BK_NUM!=%%d" -) -if !BK_NUM!==0 ( - echo No backups found. - pause - goto :menu -) -echo. -set /p rnum=" Choose backup number: " -if "!rnum!"=="" goto :menu -set "RESTORE_PATH=!BK_PATH_%rnum%!" -if "!RESTORE_PATH!"=="" ( - echo Invalid choice. - pause - goto :menu -) -if exist "!RESTORE_PATH!\openclaw.json" ( - copy "!RESTORE_PATH!\openclaw.json" "%STATE_DIR%\" >nul - echo + Config restored -) -if exist "!RESTORE_PATH!\memory" ( - xcopy /s /q "!RESTORE_PATH!\memory" "%DATA_DIR%\memory\" >nul 2>nul - echo + Memory restored -) -echo. -echo Restore complete! -pause -goto :menu - -:sysinfo -echo. -echo === System Info === -echo. -echo OS: Windows -for /f "tokens=2 delims==" %%v in ('wmic os get Version /format:list 2^>nul ^| findstr "="') do echo Ver: %%v -for /f "tokens=2 delims==" %%v in ('wmic os get OSArchitecture /format:list 2^>nul ^| findstr "="') do echo Arch: %%v -for /f "tokens=2 delims==" %%v in ('wmic computersystem get TotalPhysicalMemory /format:list 2^>nul ^| findstr "="') do ( - set "MEM=%%v" - set /a "MEM_GB=!MEM:~0,-9!" - echo Memory: !MEM_GB! GB -) -if exist "%NODE_BIN%" ( - for /f "tokens=*" %%v in ('"%NODE_BIN%" --version') do echo Node: %%v -) -echo Path: %UCLAW_DIR% -echo Data: %DATA_DIR% -for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%UCLAW_DIR%' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1MB" 2^>nul') do echo Size: %%s MB -for /f "tokens=3" %%s in ('dir /-c "%UCLAW_DIR%." 2^>nul ^| findstr /c:"bytes free"') do echo Free: %%s bytes -echo. -if exist "%CORE_DIR%\node_modules\openclaw\package.json" ( - for /f "tokens=*" %%v in ('"%NODE_BIN%" -e "console.log(require('%CORE_DIR:\=/%/node_modules/openclaw/package.json').version)"') do echo OpenClaw: %%v -) -pause -goto :menu - -:killproc -echo. -echo === Kill Residual Processes === -echo. -echo Checking ports 18789-18799... -set FOUND=0 -for /l %%p in (18789,1,18799) do ( - netstat -ano | findstr ":%%p " | findstr "LISTENING" >nul 2>&1 - if not errorlevel 1 ( - echo Port %%p: process found - set FOUND=1 - for /f "tokens=5" %%a in ('netstat -ano ^| findstr ":%%p " ^| findstr "LISTENING"') do ( - echo PID: %%a - ) - ) -) - -REM Also check for openclaw node processes -for /f "tokens=2" %%p in ('tasklist /fi "imagename eq node.exe" /fo csv /nh 2^>nul ^| findstr /i "node"') do ( - set "FOUND_NODE=1" -) - -if "!FOUND!"=="0" ( - echo No residual processes found on gateway ports. - pause - goto :menu -) - -echo. -set /p killconfirm=" Kill these processes? (y/N): " -if /i not "!killconfirm!"=="y" ( - echo Cancelled. - pause - goto :menu -) - -for /l %%p in (18789,1,18799) do ( - for /f "tokens=5" %%a in ('netstat -ano ^| findstr ":%%p " ^| findstr "LISTENING"') do ( - taskkill /PID %%a /F >nul 2>&1 - ) -) -echo Processes killed. -pause -goto :menu - -:viewlogs -echo. -echo === Log Management === -echo. -set "LOG_FILE=%LOG_DIR%\gateway.log" -if not exist "%LOG_FILE%" ( - echo No log file found. Start the gateway first. - pause - goto :menu -) -echo [a] View last 50 lines -echo [b] Open log in Notepad -echo [c] Export log to Desktop -echo [d] Clean logs older than 7 days -echo. -set /p logchoice=" Choose (a-d): " -if "%logchoice%"=="a" ( - echo. - powershell -command "Get-Content '%LOG_FILE%' -Tail 50" -) -if "%logchoice%"=="b" ( - start notepad "%LOG_FILE%" -) -if "%logchoice%"=="c" ( - set "TS=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%" - set "TS=!TS: =0!" - set "EXPORT=%USERPROFILE%\Desktop\uclaw-logs-!TS!.txt" - copy "%LOG_FILE%" "!EXPORT!" >nul - echo Log exported: !EXPORT! -) -if "%logchoice%"=="d" ( - echo. - echo Cleaning logs older than 7 days... - powershell -command "Get-ChildItem '%LOG_DIR%' -Filter '*.log' | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } | Remove-Item -Force" - echo Old logs cleaned. -) -pause -goto :menu - -:factoryreset -echo. -echo === Factory Reset === -echo. -echo WARNING: This will delete all config and memory data! -echo. -echo Actions: -echo 1. Auto-backup current config and memory -echo 2. Delete config (openclaw.json) -echo 3. Delete memory data -echo 4. Restore default config -echo. -echo Type RESET to confirm: -set /p resetconfirm=" > " -if not "%resetconfirm%"=="RESET" ( - echo Cancelled. - pause - goto :menu -) -echo. -echo [1/4] Backing up... -set "TS=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%" -set "TS=!TS: =0!" -set "BK=%BACKUP_DIR%\pre-reset_!TS!" -mkdir "!BK!" 2>nul -if exist "%STATE_DIR%\openclaw.json" copy "%STATE_DIR%\openclaw.json" "!BK!\" >nul 2>nul -if exist "%DATA_DIR%\memory" xcopy /s /q "%DATA_DIR%\memory" "!BK!\memory\" >nul 2>nul -echo Backup saved: !BK! -echo [2/4] Deleting config... -del "%STATE_DIR%\openclaw.json" 2>nul -del "%DATA_DIR%\config.json" 2>nul -echo [3/4] Clearing memory... -rmdir /s /q "%DATA_DIR%\memory" 2>nul -mkdir "%DATA_DIR%\memory" 2>nul -echo [4/4] Restoring default config... -if exist "%UCLAW_DIR%default-config.json" ( - copy "%UCLAW_DIR%default-config.json" "%STATE_DIR%\openclaw.json" >nul -) else ( - (echo {"gateway":{"mode":"local","auth":{"token":"uclaw"}}})>"%STATE_DIR%\openclaw.json" -) -echo. -echo Factory reset complete! Run Setup wizard [1] to reconfigure. -pause -goto :menu - -:uninstall -echo. -echo === Uninstall U-Claw === -echo. -if exist "%USERPROFILE%\.uclaw" ( - echo Found installed version: %USERPROFILE%\.uclaw - for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%USERPROFILE%\.uclaw' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1MB" 2^>nul') do echo Size: %%s MB - echo. - echo Type UNINSTALL to delete: - set /p unconfirm=" > " - if "!unconfirm!"=="UNINSTALL" ( - rmdir /s /q "%USERPROFILE%\.uclaw" 2>nul - echo Uninstalled! - ) else ( - echo Cancelled. - ) -) else ( - echo Portable version - just delete this folder to uninstall. - echo Path: %UCLAW_DIR% - echo. - echo For Electron desktop app: - echo Open Settings - Apps - find U-Claw - Uninstall -) -pause -goto :menu - -:checkupdate -echo. -echo === Check for Updates === -echo. -if not exist "%CORE_DIR%\node_modules\openclaw\package.json" ( - echo OpenClaw not installed. - pause - goto :menu -) -echo Checking... -for /f "tokens=*" %%v in ('"%NODE_BIN%" -e "console.log(require('%CORE_DIR:\=/%/node_modules/openclaw/package.json').version)"') do set CUR_VER=%%v -echo Current version: %CUR_VER% - -echo Fetching latest version... -for /f "tokens=*" %%v in ('"%NODE_BIN%" -e "const https=require('https');https.get('https://registry.npmmirror.com/openclaw/latest',r=>{let d='';r.on('data',c=>d+=c);r.on('end',()=>{try{console.log(JSON.parse(d).version)}catch(e){console.log('error')}})})" 2^>nul') do set LATEST_VER=%%v - -if "!LATEST_VER!"=="" ( - echo Could not fetch latest version (network issue?) - pause - goto :menu -) -if "!LATEST_VER!"=="error" ( - echo Could not fetch latest version (network issue?) - pause - goto :menu -) - -echo Latest version: !LATEST_VER! -echo. - -if "!CUR_VER!"=="!LATEST_VER!" ( - echo Already up to date! - pause - goto :menu -) - -echo New version available! -set /p doupdate=" Update now? (y/N): " -if /i not "!doupdate!"=="y" ( - echo Cancelled. - pause - goto :menu -) - -echo. -echo Updating... -cd /d "%CORE_DIR%" -call "%NPM_BIN%" install openclaw@latest --registry=https://registry.npmmirror.com -for /f "tokens=*" %%v in ('"%NODE_BIN%" -e "console.log(require('./node_modules/openclaw/package.json').version)"') do set NEW_VER=%%v -echo. -echo Updated! %CUR_VER% - %NEW_VER% -pause -goto :menu - -:diskcleanup -echo. -echo === Disk Cleanup === -echo. -echo Directory sizes: -if exist "%CORE_DIR%\node_modules" ( - for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%CORE_DIR%\node_modules' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1MB" 2^>nul') do echo node_modules: %%s MB -) -if exist "%DATA_DIR%\memory" ( - for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%DATA_DIR%\memory' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1KB" 2^>nul') do echo memory: %%s KB -) -if exist "%BACKUP_DIR%" ( - for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%BACKUP_DIR%' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1KB" 2^>nul') do echo backups: %%s KB -) -if exist "%LOG_DIR%" ( - for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%LOG_DIR%' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1KB" 2^>nul') do echo logs: %%s KB -) -for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%UCLAW_DIR%' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1MB" 2^>nul') do echo Total: %%s MB -echo. - -REM Clean old backups (keep latest 3) -set "BK_COUNT=0" -for /d %%d in ("%BACKUP_DIR%\*") do set /a BK_COUNT+=1 -if !BK_COUNT! gtr 3 ( - set /a OLD_COUNT=BK_COUNT-3 - echo Found !BK_COUNT! backups, keeping latest 3. - set /p delbk=" Delete !OLD_COUNT! old backups? (y/N): " - if /i "!delbk!"=="y" ( - set "DEL_NUM=0" - for /f "tokens=*" %%d in ('powershell -command "Get-ChildItem '%BACKUP_DIR%' -Directory | Sort-Object LastWriteTime | Select-Object -First !OLD_COUNT! | ForEach-Object { $_.FullName }"') do ( - rmdir /s /q "%%d" 2>nul - set /a DEL_NUM+=1 - ) - echo Cleaned !DEL_NUM! old backups. - ) -) else ( - echo Backups: !BK_COUNT! (no cleanup needed) -) - -REM Clean old logs (>7 days) -set "OLD_LOGS=0" -for /f "tokens=*" %%n in ('powershell -command "(Get-ChildItem '%LOG_DIR%' -Filter '*.log' -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) }).Count" 2^>nul') do set OLD_LOGS=%%n -if !OLD_LOGS! gtr 0 ( - echo Found !OLD_LOGS! logs older than 7 days. - set /p dellog=" Delete old logs? (y/N): " - if /i "!dellog!"=="y" ( - powershell -command "Get-ChildItem '%LOG_DIR%' -Filter '*.log' | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } | Remove-Item -Force" - echo Old logs cleaned. - ) -) else ( - echo Logs: no cleanup needed -) - -REM Clean npm cache -echo. -set /p delcache=" Clean npm cache? (y/N): " -if /i "!delcache!"=="y" ( - call "%NPM_BIN%" cache clean --force 2>nul - echo npm cache cleaned. -) - -echo. -for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%UCLAW_DIR%' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1MB" 2^>nul') do echo Total after cleanup: %%s MB -pause -goto :menu - -:plugins -echo. -echo === Plugin Management === -echo. -echo [a] List installed plugins -echo [b] Install a plugin -echo [c] Remove a plugin -echo. -set /p plgchoice=" Choose (a-c): " -cd /d "%CORE_DIR%" -if "%plgchoice%"=="a" ( - echo. - "%NODE_BIN%" "%OPENCLAW_MJS%" plugins list -) -if "%plgchoice%"=="b" ( - echo. - echo Common plugins: - echo @icesword760/openclaw-wechat - WeChat - echo @nicepkg/openclaw-plugin-qq - QQ (community) - echo. - set /p plgname=" Plugin name (empty to cancel): " - if not "!plgname!"=="" ( - echo. - echo Installing !plgname! ... - "%NODE_BIN%" "%OPENCLAW_MJS%" plugins install "!plgname!" - echo. - echo Done! - ) else ( - echo Cancelled. - ) -) -if "%plgchoice%"=="c" ( - echo. - "%NODE_BIN%" "%OPENCLAW_MJS%" plugins list - echo. - set /p plgname=" Plugin to remove (empty to cancel): " - if not "!plgname!"=="" ( - echo. - echo Removing !plgname! ... - "%NODE_BIN%" "%OPENCLAW_MJS%" plugins remove "!plgname!" - echo. - echo Done! - ) else ( - echo Cancelled. - ) -) -pause -goto :menu +@echo off +setlocal EnableDelayedExpansion +chcp 65001 >nul 2>&1 +title U-Claw Menu + +set "UCLAW_DIR=%~dp0" +set "APP_DIR=%UCLAW_DIR%app" + +REM Migration shim: rename old core-win to core for existing USB users +if exist "%APP_DIR%\core-win" if not exist "%APP_DIR%\core" ren "%APP_DIR%\core-win" core + +set "CORE_DIR=%APP_DIR%\core" +set "DATA_DIR=%UCLAW_DIR%data" +set "STATE_DIR=%DATA_DIR%\.openclaw" +set "NODE_DIR=%UCLAW_DIR%app\runtime\node-win-x64" +set "NODE_BIN=%NODE_DIR%\node.exe" +set "NPM_BIN=%NODE_DIR%\npm.cmd" + +set "OPENCLAW_HOME=%DATA_DIR%" +set "OPENCLAW_STATE_DIR=%STATE_DIR%" +set "OPENCLAW_CONFIG_PATH=%STATE_DIR%\openclaw.json" +REM U-Claw opens the local dashboard directly; disable mDNS discovery on Windows +REM to avoid OpenClaw/@homebridge ciao crashes during bonjour re-advertise. +set "OPENCLAW_DISABLE_BONJOUR=1" +set "PATH=%NODE_DIR%;%PATH%" + +set "OPENCLAW_MJS=%CORE_DIR%\node_modules\openclaw\openclaw.mjs" +set "LOG_DIR=%DATA_DIR%\logs" +set "BACKUP_DIR=%DATA_DIR%\backups" + +if not exist "%STATE_DIR%" mkdir "%STATE_DIR%" +if not exist "%DATA_DIR%\memory" mkdir "%DATA_DIR%\memory" +if not exist "%BACKUP_DIR%" mkdir "%BACKUP_DIR%" +if not exist "%LOG_DIR%" mkdir "%LOG_DIR%" + +:menu +cls +echo. +echo ======================================== +echo U-Claw v1.1 - Menu +echo Portable AI Agent +echo ======================================== +echo. + +if exist "%NODE_BIN%" ( + for /f "tokens=*" %%v in ('"%NODE_BIN%" --version') do echo Node: %%v +) else ( + echo [!] Node.js not found +) +if exist "%STATE_DIR%\openclaw.json" (echo Config: OK) else (echo Config: NOT SET) +echo. +echo -- Config -- +echo [1] Setup wizard (model, API key) +echo [2] Open web dashboard +echo. +echo -- Chat Platforms -- +echo [3] QQ Bot (pre-installed, enter ID only) +echo [4] Other platforms (Feishu/Telegram/WeChat) +echo. +echo -- Maintenance -- +echo [5] Diagnostics +echo [6] Backup config +echo [7] Restore backup +echo [8] System info +echo. +echo -- Advanced -- +echo [9] Kill residual processes +echo [10] View logs +echo [11] Factory reset +echo [12] Uninstall +echo [13] Check for updates +echo [14] Disk cleanup +echo [15] Plugin management +echo. +echo [0] Exit +echo. +set /p choice=" Choose [0-15]: " + +if "%choice%"=="1" goto :onboard +if "%choice%"=="2" goto :dashboard +if "%choice%"=="3" goto :qqbot +if "%choice%"=="4" goto :channels +if "%choice%"=="5" goto :doctor +if "%choice%"=="6" goto :backup +if "%choice%"=="7" goto :restore +if "%choice%"=="8" goto :sysinfo +if "%choice%"=="9" goto :killproc +if "%choice%"=="10" goto :viewlogs +if "%choice%"=="11" goto :factoryreset +if "%choice%"=="12" goto :uninstall +if "%choice%"=="13" goto :checkupdate +if "%choice%"=="14" goto :diskcleanup +if "%choice%"=="15" goto :plugins +if "%choice%"=="0" exit /b 0 +echo Invalid choice +pause +goto :menu + +:onboard +echo. +echo === Setup Wizard === +echo. +echo DeepSeek - Custom Provider, URL: https://api.deepseek.com/v1 +echo Kimi - Moonshot AI +echo Qwen - Qwen +echo Doubao - Volcano Engine +echo. +cd /d "%CORE_DIR%" +"%NODE_BIN%" "%OPENCLAW_MJS%" onboard +pause +goto :menu + +:dashboard +echo. +echo Starting gateway... +set PORT=18789 +:find_port +netstat -an | findstr ":%PORT% " | findstr "LISTENING" >nul 2>&1 +if !errorlevel!==0 ( + set /a PORT+=1 + if !PORT! gtr 18799 (echo No available port & pause & goto :menu) + goto :find_port +) +cd /d "%CORE_DIR%" +if not exist "%STATE_DIR%\openclaw.json" ( + (echo {"gateway":{"mode":"local","auth":{"token":"uclaw"}}})>"%STATE_DIR%\openclaw.json" +) + +REM Read token from config +set "TOKEN=uclaw" +if exist "%STATE_DIR%\openclaw.json" ( + for /f "tokens=*" %%t in ('"%NODE_BIN%" -e "try{const c=JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'));console.log((c.gateway&&c.gateway.auth&&c.gateway.auth.token)||'uclaw')}catch(e){console.log('uclaw')}" "%STATE_DIR%\openclaw.json"') do set "TOKEN=%%t" +) + +start /B "" cmd /c "timeout /t 3 /nobreak >nul && start http://127.0.0.1:!PORT!/#token=!TOKEN!" +"%NODE_BIN%" "%OPENCLAW_MJS%" gateway run --allow-unconfigured --force --port !PORT! +pause +goto :menu + +:qqbot +echo. +echo === QQ Bot Setup === +echo. +echo QQ plugin is pre-installed! +echo You only need your AppID and AppSecret. +echo. +echo Get them at: q.qq.com (create a bot) +echo. +set /p qqid=" AppID: " +set /p qqsecret=" AppSecret: " +if "%qqid%"=="" goto :qq_cancel +if "%qqsecret%"=="" goto :qq_cancel +cd /d "%CORE_DIR%" +"%NODE_BIN%" "%OPENCLAW_MJS%" channels add --channel qqbot --token "%qqid%:%qqsecret%" +echo. +set /p qqallow=" Your QQ number (allowlist, empty to skip): " +if not "%qqallow%"=="" "%NODE_BIN%" "%OPENCLAW_MJS%" config set channels.qqbot.allowFrom "%qqallow%" +echo. +echo QQ Bot configured! Restart gateway to apply. +pause +goto :menu +:qq_cancel +echo Cancelled. +pause +goto :menu + +:channels +echo. +echo === Other Platforms === +echo. +echo [a] Feishu (Lark) - Enterprise +echo [b] Telegram - International +echo [c] WeChat (plugin) - iPad protocol +echo [d] Discord +echo. +set /p ch_choice=" Choose (a-d, empty to cancel): " +if "%ch_choice%"=="a" ( + echo. + echo Feishu setup: + echo 1. Visit open.feishu.cn/app to create an app + echo 2. Get App ID and App Secret + echo 3. Run Setup wizard [1] to bind +) +if "%ch_choice%"=="b" ( + echo. + echo Telegram setup: + echo 1. Message @BotFather on Telegram + echo 2. Create a bot and get the token + echo 3. Run Setup wizard [1] to bind +) +if "%ch_choice%"=="c" ( + echo. + echo Installing WeChat plugin... + cd /d "%CORE_DIR%" + "%NODE_BIN%" "%OPENCLAW_MJS%" plugins install @icesword760/openclaw-wechat + echo WeChat plugin installed! +) +if "%ch_choice%"=="d" ( + echo. + echo Discord setup: + echo 1. Visit discord.com/developers/applications + echo 2. Create a bot and get the token + echo 3. Run Setup wizard [1] to bind +) +echo. +pause +goto :menu + +:doctor +cd /d "%CORE_DIR%" +"%NODE_BIN%" "%OPENCLAW_MJS%" doctor --repair +pause +goto :menu + +:backup +echo. +set "TS=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%" +set "TS=!TS: =0!" +set "BK=%BACKUP_DIR%\backup_!TS!" +mkdir "!BK!" 2>nul +set "BK_COUNT=0" +if exist "%STATE_DIR%\openclaw.json" ( + copy "%STATE_DIR%\openclaw.json" "!BK!\" >nul + echo + openclaw.json + set /a BK_COUNT+=1 +) +if exist "%DATA_DIR%\memory" ( + xcopy /s /q "%DATA_DIR%\memory" "!BK!\memory\" >nul 2>nul + echo + memory/ + set /a BK_COUNT+=1 +) +echo. +if !BK_COUNT!==0 ( + echo Nothing to backup. + rmdir "!BK!" 2>nul +) else ( + for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '!BK!' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1KB" 2^>nul') do echo Size: %%s KB + echo Backup saved: !BK! +) +pause +goto :menu + +:restore +echo. +echo === Restore Backup === +echo. +echo Available backups: +echo. +set "BK_NUM=0" +for /d %%d in ("%BACKUP_DIR%\*") do ( + set /a BK_NUM+=1 + echo [!BK_NUM!] %%~nxd + set "BK_PATH_!BK_NUM!=%%d" +) +if !BK_NUM!==0 ( + echo No backups found. + pause + goto :menu +) +echo. +set /p rnum=" Choose backup number: " +if "!rnum!"=="" goto :menu +set "RESTORE_PATH=!BK_PATH_%rnum%!" +if "!RESTORE_PATH!"=="" ( + echo Invalid choice. + pause + goto :menu +) +if exist "!RESTORE_PATH!\openclaw.json" ( + copy "!RESTORE_PATH!\openclaw.json" "%STATE_DIR%\" >nul + echo + Config restored +) +if exist "!RESTORE_PATH!\memory" ( + xcopy /s /q "!RESTORE_PATH!\memory" "%DATA_DIR%\memory\" >nul 2>nul + echo + Memory restored +) +echo. +echo Restore complete! +pause +goto :menu + +:sysinfo +echo. +echo === System Info === +echo. +echo OS: Windows +for /f "tokens=2 delims==" %%v in ('wmic os get Version /format:list 2^>nul ^| findstr "="') do echo Ver: %%v +for /f "tokens=2 delims==" %%v in ('wmic os get OSArchitecture /format:list 2^>nul ^| findstr "="') do echo Arch: %%v +for /f "tokens=2 delims==" %%v in ('wmic computersystem get TotalPhysicalMemory /format:list 2^>nul ^| findstr "="') do ( + set "MEM=%%v" + set /a "MEM_GB=!MEM:~0,-9!" + echo Memory: !MEM_GB! GB +) +if exist "%NODE_BIN%" ( + for /f "tokens=*" %%v in ('"%NODE_BIN%" --version') do echo Node: %%v +) +echo Path: %UCLAW_DIR% +echo Data: %DATA_DIR% +for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%UCLAW_DIR%' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1MB" 2^>nul') do echo Size: %%s MB +for /f "tokens=3" %%s in ('dir /-c "%UCLAW_DIR%." 2^>nul ^| findstr /c:"bytes free"') do echo Free: %%s bytes +echo. +if exist "%CORE_DIR%\node_modules\openclaw\package.json" ( + for /f "tokens=*" %%v in ('"%NODE_BIN%" -e "console.log(require('%CORE_DIR:\=/%/node_modules/openclaw/package.json').version)"') do echo OpenClaw: %%v +) +pause +goto :menu + +:killproc +echo. +echo === Kill Residual Processes === +echo. +echo Checking ports 18789-18799... +set FOUND=0 +for /l %%p in (18789,1,18799) do ( + netstat -ano | findstr ":%%p " | findstr "LISTENING" >nul 2>&1 + if not errorlevel 1 ( + echo Port %%p: process found + set FOUND=1 + for /f "tokens=5" %%a in ('netstat -ano ^| findstr ":%%p " ^| findstr "LISTENING"') do ( + echo PID: %%a + ) + ) +) + +REM Also check for openclaw node processes +for /f "tokens=2" %%p in ('tasklist /fi "imagename eq node.exe" /fo csv /nh 2^>nul ^| findstr /i "node"') do ( + set "FOUND_NODE=1" +) + +if "!FOUND!"=="0" ( + echo No residual processes found on gateway ports. + pause + goto :menu +) + +echo. +set /p killconfirm=" Kill these processes? (y/N): " +if /i not "!killconfirm!"=="y" ( + echo Cancelled. + pause + goto :menu +) + +for /l %%p in (18789,1,18799) do ( + for /f "tokens=5" %%a in ('netstat -ano ^| findstr ":%%p " ^| findstr "LISTENING"') do ( + taskkill /PID %%a /F >nul 2>&1 + ) +) +echo Processes killed. +pause +goto :menu + +:viewlogs +echo. +echo === Log Management === +echo. +set "LOG_FILE=%LOG_DIR%\gateway.log" +if not exist "%LOG_FILE%" ( + echo No log file found. Start the gateway first. + pause + goto :menu +) +echo [a] View last 50 lines +echo [b] Open log in Notepad +echo [c] Export log to Desktop +echo [d] Clean logs older than 7 days +echo. +set /p logchoice=" Choose (a-d): " +if "%logchoice%"=="a" ( + echo. + powershell -command "Get-Content '%LOG_FILE%' -Tail 50" +) +if "%logchoice%"=="b" ( + start notepad "%LOG_FILE%" +) +if "%logchoice%"=="c" ( + set "TS=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%" + set "TS=!TS: =0!" + set "EXPORT=%USERPROFILE%\Desktop\uclaw-logs-!TS!.txt" + copy "%LOG_FILE%" "!EXPORT!" >nul + echo Log exported: !EXPORT! +) +if "%logchoice%"=="d" ( + echo. + echo Cleaning logs older than 7 days... + powershell -command "Get-ChildItem '%LOG_DIR%' -Filter '*.log' | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } | Remove-Item -Force" + echo Old logs cleaned. +) +pause +goto :menu + +:factoryreset +echo. +echo === Factory Reset === +echo. +echo WARNING: This will delete all config and memory data! +echo. +echo Actions: +echo 1. Auto-backup current config and memory +echo 2. Delete config (openclaw.json) +echo 3. Delete memory data +echo 4. Restore default config +echo. +echo Type RESET to confirm: +set /p resetconfirm=" > " +if not "%resetconfirm%"=="RESET" ( + echo Cancelled. + pause + goto :menu +) +echo. +echo [1/4] Backing up... +set "TS=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%" +set "TS=!TS: =0!" +set "BK=%BACKUP_DIR%\pre-reset_!TS!" +mkdir "!BK!" 2>nul +if exist "%STATE_DIR%\openclaw.json" copy "%STATE_DIR%\openclaw.json" "!BK!\" >nul 2>nul +if exist "%DATA_DIR%\memory" xcopy /s /q "%DATA_DIR%\memory" "!BK!\memory\" >nul 2>nul +echo Backup saved: !BK! +echo [2/4] Deleting config... +del "%STATE_DIR%\openclaw.json" 2>nul +del "%DATA_DIR%\config.json" 2>nul +echo [3/4] Clearing memory... +rmdir /s /q "%DATA_DIR%\memory" 2>nul +mkdir "%DATA_DIR%\memory" 2>nul +echo [4/4] Restoring default config... +if exist "%UCLAW_DIR%default-config.json" ( + copy "%UCLAW_DIR%default-config.json" "%STATE_DIR%\openclaw.json" >nul +) else ( + (echo {"gateway":{"mode":"local","auth":{"token":"uclaw"}}})>"%STATE_DIR%\openclaw.json" +) +echo. +echo Factory reset complete! Run Setup wizard [1] to reconfigure. +pause +goto :menu + +:uninstall +echo. +echo === Uninstall U-Claw === +echo. +if exist "%USERPROFILE%\.uclaw" ( + echo Found installed version: %USERPROFILE%\.uclaw + for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%USERPROFILE%\.uclaw' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1MB" 2^>nul') do echo Size: %%s MB + echo. + echo Type UNINSTALL to delete: + set /p unconfirm=" > " + if "!unconfirm!"=="UNINSTALL" ( + rmdir /s /q "%USERPROFILE%\.uclaw" 2>nul + echo Uninstalled! + ) else ( + echo Cancelled. + ) +) else ( + echo Portable version - just delete this folder to uninstall. + echo Path: %UCLAW_DIR% + echo. + echo For Electron desktop app: + echo Open Settings - Apps - find U-Claw - Uninstall +) +pause +goto :menu + +:checkupdate +echo. +echo === Check for Updates === +echo. +if not exist "%CORE_DIR%\node_modules\openclaw\package.json" ( + echo OpenClaw not installed. + pause + goto :menu +) +echo Checking... +for /f "tokens=*" %%v in ('"%NODE_BIN%" -e "console.log(require('%CORE_DIR:\=/%/node_modules/openclaw/package.json').version)"') do set CUR_VER=%%v +echo Current version: %CUR_VER% + +echo Fetching latest version... +for /f "tokens=*" %%v in ('"%NODE_BIN%" -e "const https=require('https');https.get('https://registry.npmmirror.com/openclaw/latest',r=>{let d='';r.on('data',c=>d+=c);r.on('end',()=>{try{console.log(JSON.parse(d).version)}catch(e){console.log('error')}})})" 2^>nul') do set LATEST_VER=%%v + +if "!LATEST_VER!"=="" ( + echo Could not fetch latest version (network issue?) + pause + goto :menu +) +if "!LATEST_VER!"=="error" ( + echo Could not fetch latest version (network issue?) + pause + goto :menu +) + +echo Latest version: !LATEST_VER! +echo. + +if "!CUR_VER!"=="!LATEST_VER!" ( + echo Already up to date! + pause + goto :menu +) + +echo New version available! +set /p doupdate=" Update now? (y/N): " +if /i not "!doupdate!"=="y" ( + echo Cancelled. + pause + goto :menu +) + +echo. +echo Updating... +cd /d "%CORE_DIR%" +call "%NPM_BIN%" install openclaw@latest --registry=https://registry.npmmirror.com +for /f "tokens=*" %%v in ('"%NODE_BIN%" -e "console.log(require('./node_modules/openclaw/package.json').version)"') do set NEW_VER=%%v +echo. +echo Updated! %CUR_VER% - %NEW_VER% +pause +goto :menu + +:diskcleanup +echo. +echo === Disk Cleanup === +echo. +echo Directory sizes: +if exist "%CORE_DIR%\node_modules" ( + for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%CORE_DIR%\node_modules' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1MB" 2^>nul') do echo node_modules: %%s MB +) +if exist "%DATA_DIR%\memory" ( + for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%DATA_DIR%\memory' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1KB" 2^>nul') do echo memory: %%s KB +) +if exist "%BACKUP_DIR%" ( + for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%BACKUP_DIR%' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1KB" 2^>nul') do echo backups: %%s KB +) +if exist "%LOG_DIR%" ( + for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%LOG_DIR%' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1KB" 2^>nul') do echo logs: %%s KB +) +for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%UCLAW_DIR%' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1MB" 2^>nul') do echo Total: %%s MB +echo. + +REM Clean old backups (keep latest 3) +set "BK_COUNT=0" +for /d %%d in ("%BACKUP_DIR%\*") do set /a BK_COUNT+=1 +if !BK_COUNT! gtr 3 ( + set /a OLD_COUNT=BK_COUNT-3 + echo Found !BK_COUNT! backups, keeping latest 3. + set /p delbk=" Delete !OLD_COUNT! old backups? (y/N): " + if /i "!delbk!"=="y" ( + set "DEL_NUM=0" + for /f "tokens=*" %%d in ('powershell -command "Get-ChildItem '%BACKUP_DIR%' -Directory | Sort-Object LastWriteTime | Select-Object -First !OLD_COUNT! | ForEach-Object { $_.FullName }"') do ( + rmdir /s /q "%%d" 2>nul + set /a DEL_NUM+=1 + ) + echo Cleaned !DEL_NUM! old backups. + ) +) else ( + echo Backups: !BK_COUNT! (no cleanup needed) +) + +REM Clean old logs (>7 days) +set "OLD_LOGS=0" +for /f "tokens=*" %%n in ('powershell -command "(Get-ChildItem '%LOG_DIR%' -Filter '*.log' -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) }).Count" 2^>nul') do set OLD_LOGS=%%n +if !OLD_LOGS! gtr 0 ( + echo Found !OLD_LOGS! logs older than 7 days. + set /p dellog=" Delete old logs? (y/N): " + if /i "!dellog!"=="y" ( + powershell -command "Get-ChildItem '%LOG_DIR%' -Filter '*.log' | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } | Remove-Item -Force" + echo Old logs cleaned. + ) +) else ( + echo Logs: no cleanup needed +) + +REM Clean npm cache +echo. +set /p delcache=" Clean npm cache? (y/N): " +if /i "!delcache!"=="y" ( + call "%NPM_BIN%" cache clean --force 2>nul + echo npm cache cleaned. +) + +echo. +for /f "tokens=*" %%s in ('powershell -command "(Get-ChildItem '%UCLAW_DIR%' -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1MB" 2^>nul') do echo Total after cleanup: %%s MB +pause +goto :menu + +:plugins +echo. +echo === Plugin Management === +echo. +echo [a] List installed plugins +echo [b] Install a plugin +echo [c] Remove a plugin +echo. +set /p plgchoice=" Choose (a-c): " +cd /d "%CORE_DIR%" +if "%plgchoice%"=="a" ( + echo. + "%NODE_BIN%" "%OPENCLAW_MJS%" plugins list +) +if "%plgchoice%"=="b" ( + echo. + echo Common plugins: + echo @icesword760/openclaw-wechat - WeChat + echo @nicepkg/openclaw-plugin-qq - QQ (community) + echo. + set /p plgname=" Plugin name (empty to cancel): " + if not "!plgname!"=="" ( + echo. + echo Installing !plgname! ... + "%NODE_BIN%" "%OPENCLAW_MJS%" plugins install "!plgname!" + echo. + echo Done! + ) else ( + echo Cancelled. + ) +) +if "%plgchoice%"=="c" ( + echo. + "%NODE_BIN%" "%OPENCLAW_MJS%" plugins list + echo. + set /p plgname=" Plugin to remove (empty to cancel): " + if not "!plgname!"=="" ( + echo. + echo Removing !plgname! ... + "%NODE_BIN%" "%OPENCLAW_MJS%" plugins remove "!plgname!" + echo. + echo Done! + ) else ( + echo Cancelled. + ) +) +pause +goto :menu diff --git a/portable/Windows-Start.bat b/portable/Windows-Start.bat index edbdbd7..546dccf 100644 --- a/portable/Windows-Start.bat +++ b/portable/Windows-Start.bat @@ -1,180 +1,180 @@ -@echo off -chcp 65001 >nul 2>&1 -title U-Claw - Portable AI Agent - -echo. -echo ======================================== -echo U-Claw v1.1 - Portable AI Agent -echo ======================================== -echo. - -set "UCLAW_DIR=%~dp0" -set "APP_DIR=%UCLAW_DIR%app" - -REM Migration shim: rename old core-win to core for existing USB users -if exist "%APP_DIR%\core-win" if not exist "%APP_DIR%\core" ren "%APP_DIR%\core-win" core - -set "CORE_DIR=%APP_DIR%\core" -set "DATA_DIR=%UCLAW_DIR%data" -set "STATE_DIR=%DATA_DIR%\.openclaw" -set "NODE_DIR=%APP_DIR%\runtime\node-win-x64" -set "NODE_BIN=%NODE_DIR%\node.exe" -set "NPM_BIN=%NODE_DIR%\npm.cmd" - -set "OPENCLAW_HOME=%DATA_DIR%" -set "OPENCLAW_STATE_DIR=%STATE_DIR%" -set "OPENCLAW_CONFIG_PATH=%STATE_DIR%\openclaw.json" -REM U-Claw opens the local dashboard directly; disable mDNS discovery on Windows -REM to avoid OpenClaw/@homebridge ciao crashes during bonjour re-advertise. -set "OPENCLAW_DISABLE_BONJOUR=1" - -REM Check runtime -if not exist "%NODE_BIN%" ( - echo [ERROR] Node.js runtime not found - echo Please ensure app\runtime\node-win-x64 is complete - pause - exit /b 1 -) - -for /f "tokens=*" %%v in ('"%NODE_BIN%" --version') do set NODE_VER=%%v -echo Node.js: %NODE_VER% -echo. - -set "PATH=%NODE_DIR%;%NODE_DIR%\node_modules\.bin;%PATH%" - -REM Init data directories -if not exist "%DATA_DIR%" mkdir "%DATA_DIR%" -if not exist "%STATE_DIR%" mkdir "%STATE_DIR%" -if not exist "%DATA_DIR%\memory" mkdir "%DATA_DIR%\memory" -if not exist "%DATA_DIR%\backups" mkdir "%DATA_DIR%\backups" -if not exist "%DATA_DIR%\logs" mkdir "%DATA_DIR%\logs" - -REM Default config (migrate legacy if present, otherwise create) -if not exist "%STATE_DIR%\openclaw.json" ( - if exist "%DATA_DIR%\config.json" ( - echo Migrating legacy config... - copy "%DATA_DIR%\config.json" "%STATE_DIR%\openclaw.json" >nul - echo Config migrated - ) else ( - echo First run - creating default config... - (echo {"gateway":{"mode":"local","auth":{"token":"uclaw"}}})>"%STATE_DIR%\openclaw.json" - echo Config created - ) - echo. -) - -REM Check dependencies -REM Note: avoid unescaped parens inside this block — cmd.exe treats ) as block-end. -if not exist "%CORE_DIR%\node_modules" ( - echo ======================================== - echo [WARN] node_modules not found - echo ======================================== - echo This release should ship with deps pre-installed. - echo Falling back to npm install ^(USB drives may take 20+ minutes^). - echo. - echo TIP: Re-download u-claw-portable-*.zip from GitHub releases, - echo which includes pre-installed deps ^(~200 MB^). - echo. - echo File system: NTFS recommended. exFAT/FAT32 will be very slow. - echo. - cd /d "%CORE_DIR%" - REM 把 npm 缓存留在盘内,避免污染系统 %APPDATA%\npm-cache(拔盘不留痕) - set "npm_config_cache=%APP_DIR%\.npm-cache" - call "%NPM_BIN%" install --registry=https://registry.npmmirror.com --ignore-scripts --no-audit --no-fund --omit=dev - echo. - echo Dependencies installed! - echo. -) - -REM Bind device fingerprint and inject Xiapan Cloud apiKey into openclaw.json -echo Binding device fingerprint to Xiapan Cloud... -set "UCLAW_APP_ROOT=%UCLAW_DIR%" -"%NODE_BIN%" "%UCLAW_DIR%lib\bootstrap-xiapan.mjs" "%STATE_DIR%\openclaw.json" -echo. - -REM Async update check (non-blocking, 5s timeout, silent failure) -REM Writes data\.openclaw\update-available.json if a newer version is on OSS. -REM Welcome.html / Config.html read this file and show a banner. -REM Version file lookup order: portable/OPENCLAW_VERSION (USB), then repo-root ../OPENCLAW_VERSION (dev) -set "VERSION_FILE=%UCLAW_DIR%OPENCLAW_VERSION" -if not exist "%VERSION_FILE%" set "VERSION_FILE=%UCLAW_DIR%..\OPENCLAW_VERSION" -if exist "%VERSION_FILE%" ( - start /B "" "%NODE_BIN%" "%UCLAW_DIR%lib\check-update.mjs" "%VERSION_FILE%" "%STATE_DIR%" >nul 2>&1 -) - - -REM Auto-install WeChat plugin if available -set "WECHAT_PLUGIN_SRC=%APP_DIR%\extensions\openclaw-weixin" -set "WECHAT_PLUGIN_DST=%USERPROFILE%\.openclaw\extensions\openclaw-weixin" -if exist "%WECHAT_PLUGIN_SRC%\openclaw.plugin.json" ( - if not exist "%WECHAT_PLUGIN_DST%\openclaw.plugin.json" ( - echo Installing WeChat plugin... - mkdir "%USERPROFILE%\.openclaw\extensions" 2>nul - xcopy /s /e /q /y "%WECHAT_PLUGIN_SRC%" "%WECHAT_PLUGIN_DST%\" >nul - echo WeChat plugin installed! - echo. - ) -) - -REM Find available port -set PORT=18789 -:check_port -netstat -an | findstr ":%PORT% " | findstr "LISTENING" >nul 2>&1 -if %errorlevel%==0 ( - echo Port %PORT% in use, trying next... - set /a PORT+=1 - if %PORT% gtr 18799 ( - echo No available port 18789-18799 - REM 自动上报:端口全被占,gateway 无法启动(detach、静默、失败不影响) - start /B "" "%NODE_BIN%" "%UCLAW_DIR%lib\report-bug.mjs" --auto --title "gateway-no-free-port" --desc "Ports 18789-18799 all in use" --root "%UCLAW_DIR%." >nul 2>&1 - pause - exit /b 1 - ) - goto :check_port -) - -echo Starting OpenClaw on port %PORT%... -echo. - -REM Start Config Server in background -echo Starting Config Center on port 18788... -set "CONFIG_SERVER=%UCLAW_DIR%config-server" -start /B "" "%NODE_BIN%" "%CONFIG_SERVER%\server.js" >nul 2>&1 - -REM Wait for config server to start -timeout /t 2 /nobreak >nul - -REM IMPORTANT: 不要在 gateway 启动前就开 Dashboard 浏览器! -REM 慢 U 盘上 OpenClaw 首次启动要 staging bundled deps(几十秒), -REM 过早打开 http://127.0.0.1:18789 会"拒绝连接",是 issue #46/#48 的根因。 -REM 改为后台等待器:轮询端口,gateway 真正 LISTENING 后再开 Dashboard。 -echo Opening Config Center... -start "" http://127.0.0.1:18788/ - -REM 后台等待器:每 2s 探测 %PORT%,最多 ~5 分钟(150 次),监听到就开 Dashboard -start /B "" cmd /c ""%UCLAW_DIR%lib\wait-gateway.bat" %PORT%" - -echo. -echo ======================================== -echo Starting OpenClaw Gateway on port %PORT%... -echo First run on a USB drive may take 30-90 seconds -echo (unpacking bundled components). Please wait; -echo the Dashboard opens automatically when ready. -echo DO NOT close this window while using U-Claw! -echo ======================================== -echo. - -cd /d "%CORE_DIR%" -set "OPENCLAW_MJS=%CORE_DIR%\node_modules\openclaw\openclaw.mjs" -"%NODE_BIN%" "%OPENCLAW_MJS%" gateway run --allow-unconfigured --force --port %PORT% -set "GW_EXIT=%errorlevel%" - -echo. -REM 自动上报:gateway 异常退出(退出码非 0 且非 Ctrl+C/0xC000013A=-1073741510) -REM 用户正常 Ctrl+C 停止不上报,避免噪音。detach、静默、失败不影响。 -if not "%GW_EXIT%"=="0" if not "%GW_EXIT%"=="-1073741510" ( - echo OpenClaw exited unexpectedly (code %GW_EXIT%), reporting... - start /B "" "%NODE_BIN%" "%UCLAW_DIR%lib\report-bug.mjs" --auto --title "gateway-exited-code-%GW_EXIT%" --desc "Gateway exited with code %GW_EXIT% on port %PORT%" --root "%UCLAW_DIR%." >nul 2>&1 -) -echo OpenClaw stopped. -pause +@echo off +chcp 65001 >nul 2>&1 +title U-Claw - Portable AI Agent + +echo. +echo ======================================== +echo U-Claw v1.1 - Portable AI Agent +echo ======================================== +echo. + +set "UCLAW_DIR=%~dp0" +set "APP_DIR=%UCLAW_DIR%app" + +REM Migration shim: rename old core-win to core for existing USB users +if exist "%APP_DIR%\core-win" if not exist "%APP_DIR%\core" ren "%APP_DIR%\core-win" core + +set "CORE_DIR=%APP_DIR%\core" +set "DATA_DIR=%UCLAW_DIR%data" +set "STATE_DIR=%DATA_DIR%\.openclaw" +set "NODE_DIR=%APP_DIR%\runtime\node-win-x64" +set "NODE_BIN=%NODE_DIR%\node.exe" +set "NPM_BIN=%NODE_DIR%\npm.cmd" + +set "OPENCLAW_HOME=%DATA_DIR%" +set "OPENCLAW_STATE_DIR=%STATE_DIR%" +set "OPENCLAW_CONFIG_PATH=%STATE_DIR%\openclaw.json" +REM U-Claw opens the local dashboard directly; disable mDNS discovery on Windows +REM to avoid OpenClaw/@homebridge ciao crashes during bonjour re-advertise. +set "OPENCLAW_DISABLE_BONJOUR=1" + +REM Check runtime +if not exist "%NODE_BIN%" ( + echo [ERROR] Node.js runtime not found + echo Please ensure app\runtime\node-win-x64 is complete + pause + exit /b 1 +) + +for /f "tokens=*" %%v in ('"%NODE_BIN%" --version') do set NODE_VER=%%v +echo Node.js: %NODE_VER% +echo. + +set "PATH=%NODE_DIR%;%NODE_DIR%\node_modules\.bin;%PATH%" + +REM Init data directories +if not exist "%DATA_DIR%" mkdir "%DATA_DIR%" +if not exist "%STATE_DIR%" mkdir "%STATE_DIR%" +if not exist "%DATA_DIR%\memory" mkdir "%DATA_DIR%\memory" +if not exist "%DATA_DIR%\backups" mkdir "%DATA_DIR%\backups" +if not exist "%DATA_DIR%\logs" mkdir "%DATA_DIR%\logs" + +REM Default config (migrate legacy if present, otherwise create) +if not exist "%STATE_DIR%\openclaw.json" ( + if exist "%DATA_DIR%\config.json" ( + echo Migrating legacy config... + copy "%DATA_DIR%\config.json" "%STATE_DIR%\openclaw.json" >nul + echo Config migrated + ) else ( + echo First run - creating default config... + (echo {"gateway":{"mode":"local","auth":{"token":"uclaw"}}})>"%STATE_DIR%\openclaw.json" + echo Config created + ) + echo. +) + +REM Check dependencies +REM Note: avoid unescaped parens inside this block — cmd.exe treats ) as block-end. +if not exist "%CORE_DIR%\node_modules" ( + echo ======================================== + echo [WARN] node_modules not found + echo ======================================== + echo This release should ship with deps pre-installed. + echo Falling back to npm install ^(USB drives may take 20+ minutes^). + echo. + echo TIP: Re-download u-claw-portable-*.zip from GitHub releases, + echo which includes pre-installed deps ^(~200 MB^). + echo. + echo File system: NTFS recommended. exFAT/FAT32 will be very slow. + echo. + cd /d "%CORE_DIR%" + REM 把 npm 缓存留在盘内,避免污染系统 %APPDATA%\npm-cache(拔盘不留痕) + set "npm_config_cache=%APP_DIR%\.npm-cache" + call "%NPM_BIN%" install --registry=https://registry.npmmirror.com --ignore-scripts --no-audit --no-fund --omit=dev + echo. + echo Dependencies installed! + echo. +) + +REM Bind device fingerprint and inject Xiapan Cloud apiKey into openclaw.json +echo Binding device fingerprint to Xiapan Cloud... +set "UCLAW_APP_ROOT=%UCLAW_DIR%" +"%NODE_BIN%" "%UCLAW_DIR%lib\bootstrap-xiapan.mjs" "%STATE_DIR%\openclaw.json" +echo. + +REM Async update check (non-blocking, 5s timeout, silent failure) +REM Writes data\.openclaw\update-available.json if a newer version is on OSS. +REM Welcome.html / Config.html read this file and show a banner. +REM Version file lookup order: portable/OPENCLAW_VERSION (USB), then repo-root ../OPENCLAW_VERSION (dev) +set "VERSION_FILE=%UCLAW_DIR%OPENCLAW_VERSION" +if not exist "%VERSION_FILE%" set "VERSION_FILE=%UCLAW_DIR%..\OPENCLAW_VERSION" +if exist "%VERSION_FILE%" ( + start /B "" "%NODE_BIN%" "%UCLAW_DIR%lib\check-update.mjs" "%VERSION_FILE%" "%STATE_DIR%" >nul 2>&1 +) + + +REM Auto-install WeChat plugin if available +set "WECHAT_PLUGIN_SRC=%APP_DIR%\extensions\openclaw-weixin" +set "WECHAT_PLUGIN_DST=%USERPROFILE%\.openclaw\extensions\openclaw-weixin" +if exist "%WECHAT_PLUGIN_SRC%\openclaw.plugin.json" ( + if not exist "%WECHAT_PLUGIN_DST%\openclaw.plugin.json" ( + echo Installing WeChat plugin... + mkdir "%USERPROFILE%\.openclaw\extensions" 2>nul + xcopy /s /e /q /y "%WECHAT_PLUGIN_SRC%" "%WECHAT_PLUGIN_DST%\" >nul + echo WeChat plugin installed! + echo. + ) +) + +REM Find available port +set PORT=18789 +:check_port +netstat -an | findstr ":%PORT% " | findstr "LISTENING" >nul 2>&1 +if %errorlevel%==0 ( + echo Port %PORT% in use, trying next... + set /a PORT+=1 + if %PORT% gtr 18799 ( + echo No available port 18789-18799 + REM 自动上报:端口全被占,gateway 无法启动(detach、静默、失败不影响) + start /B "" "%NODE_BIN%" "%UCLAW_DIR%lib\report-bug.mjs" --auto --title "gateway-no-free-port" --desc "Ports 18789-18799 all in use" --root "%UCLAW_DIR%." >nul 2>&1 + pause + exit /b 1 + ) + goto :check_port +) + +echo Starting OpenClaw on port %PORT%... +echo. + +REM Start Config Server in background +echo Starting Config Center on port 18788... +set "CONFIG_SERVER=%UCLAW_DIR%config-server" +start /B "" "%NODE_BIN%" "%CONFIG_SERVER%\server.js" >nul 2>&1 + +REM Wait for config server to start +timeout /t 2 /nobreak >nul + +REM IMPORTANT: 不要在 gateway 启动前就开 Dashboard 浏览器! +REM 慢 U 盘上 OpenClaw 首次启动要 staging bundled deps(几十秒), +REM 过早打开 http://127.0.0.1:18789 会"拒绝连接",是 issue #46/#48 的根因。 +REM 改为后台等待器:轮询端口,gateway 真正 LISTENING 后再开 Dashboard。 +echo Opening Config Center... +start "" http://127.0.0.1:18788/ + +REM 后台等待器:每 2s 探测 %PORT%,最多 ~5 分钟(150 次),监听到就开 Dashboard +start /B "" cmd /c ""%UCLAW_DIR%lib\wait-gateway.bat" %PORT%" + +echo. +echo ======================================== +echo Starting OpenClaw Gateway on port %PORT%... +echo First run on a USB drive may take 30-90 seconds +echo (unpacking bundled components). Please wait; +echo the Dashboard opens automatically when ready. +echo DO NOT close this window while using U-Claw! +echo ======================================== +echo. + +cd /d "%CORE_DIR%" +set "OPENCLAW_MJS=%CORE_DIR%\node_modules\openclaw\openclaw.mjs" +"%NODE_BIN%" "%OPENCLAW_MJS%" gateway run --allow-unconfigured --force --port %PORT% +set "GW_EXIT=%errorlevel%" + +echo. +REM 自动上报:gateway 异常退出(退出码非 0 且非 Ctrl+C/0xC000013A=-1073741510) +REM 用户正常 Ctrl+C 停止不上报,避免噪音。detach、静默、失败不影响。 +if not "%GW_EXIT%"=="0" if not "%GW_EXIT%"=="-1073741510" ( + echo OpenClaw exited unexpectedly (code %GW_EXIT%), reporting... + start /B "" "%NODE_BIN%" "%UCLAW_DIR%lib\report-bug.mjs" --auto --title "gateway-exited-code-%GW_EXIT%" --desc "Gateway exited with code %GW_EXIT% on port %PORT%" --root "%UCLAW_DIR%." >nul 2>&1 +) +echo OpenClaw stopped. +pause