Files
u-claw/portable/Mac-Start.command
hfshfg 6eb54f8ea3 feat(portable): bug 一键上报 + 自动崩溃上报 + openclaw 升级 2026.6.6
Bug 上报(方便服务器侧排查便携版问题):
- 新增 lib/report-bug.mjs:算设备指纹→sk-uc apiKey,收集 openclaw 版本/
  系统信息/最近日志(gzip+base64),POST 到 api.u-claw.org/recharge/bug/submit。
  静默失败,绝不影响主流程。复用 fingerprint.mjs + xiapan-client.mjs。
- config-server 加 POST /api/report-bug:本地补齐信息后转发,配置中心加
  「🐛 报 Bug」表单(标题/描述/是否附日志)。
- Windows-Start.bat / Mac-Start.command:gateway 端口耗尽或异常退出时
  自动后台上报(Ctrl+C 正常停止不上报)。

openclaw 升级:
- OPENCLAW_VERSION 2026.4.29 → 2026.6.6(X 盘真实 USB 实测 gateway
  启动/ready、Dashboard 200、旧配置兼容、虾盘云 status 均通过)。

便携性改进(借鉴 OpenClaw-Windows-Portable):
- setup.sh / 启动脚本的 npm install 设 npm_config_cache 指向盘内
  app/.npm-cache,避免污染系统缓存,拔盘不留痕。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 11:46:42 +08:00

203 lines
7.2 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ============================================================
# U-Claw - Portable AI Agent (macOS)
# Double-click to start / 双击启动
# ============================================================
UCLAW_DIR="$(cd "$(dirname "$0")" && pwd)"
APP_DIR="$UCLAW_DIR/app"
CORE_DIR="$APP_DIR/core"
DATA_DIR="$UCLAW_DIR/data"
STATE_DIR="$DATA_DIR/.openclaw"
CONFIG_FILE="$STATE_DIR/openclaw.json"
# Migration shim: rename old core-mac to core for existing USB users
if [ -d "$APP_DIR/core-mac" ] && [ ! -d "$APP_DIR/core" ]; then
mv "$APP_DIR/core-mac" "$APP_DIR/core"
fi
RED='\033[0;31m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo ""
echo -e "${CYAN}"
echo " ╔══════════════════════════════════════╗"
echo " ║ 🦞 U-Claw v1.1 ║"
echo " ║ Portable AI Agent ║"
echo " ╚══════════════════════════════════════╝"
echo -e "${NC}"
# ---- 1. Detect CPU & set runtime ----
ARCH=$(uname -m)
if [ "$ARCH" = "arm64" ]; then
NODE_DIR="$APP_DIR/runtime/node-mac-arm64"
echo -e " ${GREEN}Apple Silicon (M series)${NC}"
elif [ "$ARCH" = "x86_64" ]; then
NODE_DIR="$APP_DIR/runtime/node-mac-x64"
echo -e " ${GREEN}Intel Mac (x64)${NC}"
else
echo -e " ${RED}Unsupported architecture: $ARCH${NC}"
echo ""
read -p " Press Enter to exit..."
exit 1
fi
NODE_BIN="$NODE_DIR/bin/node"
export PATH="$NODE_DIR/bin:$PATH"
# ---- 2. Remove macOS quarantine ----
if xattr -l "$NODE_BIN" 2>/dev/null | grep -q "com.apple.quarantine"; then
echo -e " ${YELLOW}Removing macOS security restriction...${NC}"
xattr -rd com.apple.quarantine "$UCLAW_DIR" 2>/dev/null || true
echo -e " ${GREEN}Done${NC}"
fi
# ---- 3. Check runtime ----
if [ ! -f "$NODE_BIN" ]; then
echo -e " ${RED}Error: Node.js runtime not found${NC}"
echo " Please run: bash setup.sh"
read -p " Press Enter to exit..."
exit 1
fi
NODE_VER=$("$NODE_BIN" --version)
echo -e " Node.js: ${GREEN}${NODE_VER}${NC}"
echo ""
# ---- 4. Init data directories ----
mkdir -p "$STATE_DIR" "$DATA_DIR/memory" "$DATA_DIR/backups" "$DATA_DIR/logs"
# ---- 5. Default config ----
if [ ! -f "$CONFIG_FILE" ]; then
if [ -f "$DATA_DIR/config.json" ]; then
echo -e " ${YELLOW}Migrating legacy config...${NC}"
cp "$DATA_DIR/config.json" "$CONFIG_FILE"
echo -e " ${GREEN}Config migrated${NC}"
else
echo -e " ${YELLOW}First run - creating default config...${NC}"
cat > "$CONFIG_FILE" << 'CFGEOF'
{
"gateway": {
"mode": "local",
"auth": { "token": "uclaw" }
}
}
CFGEOF
echo -e " ${GREEN}Config created${NC}"
fi
echo ""
fi
# ---- 6. Set environment (portable mode) ----
export OPENCLAW_HOME="$DATA_DIR"
export OPENCLAW_STATE_DIR="$STATE_DIR"
export OPENCLAW_CONFIG_PATH="$CONFIG_FILE"
# ---- 7. Check dependencies ----
if [ ! -d "$CORE_DIR/node_modules" ]; then
echo -e " ${YELLOW}[WARN] node_modules not found${NC}"
echo " This release should ship with deps pre-installed."
echo " Falling back to npm install (USB drives may take 20+ min)."
echo " TIP: re-download u-claw-portable-*.zip with bundled deps."
cd "$CORE_DIR"
# 把 npm 缓存留在盘内,避免污染系统 ~/.npm拔盘不留痕
npm_config_cache="$APP_DIR/.npm-cache" \
"$NODE_BIN" "$NODE_DIR/bin/npm" install --registry=https://registry.npmmirror.com --ignore-scripts --no-audit --no-fund --omit=dev 2>&1
echo -e " ${GREEN}Dependencies installed${NC}"
echo ""
fi
# ---- 7b. Bind device fingerprint and inject Xiapan Cloud apiKey ----
echo -e " ${CYAN}Binding device fingerprint to Xiapan Cloud...${NC}"
UCLAW_APP_ROOT="$UCLAW_DIR" "$NODE_BIN" "$UCLAW_DIR/lib/bootstrap-xiapan.mjs" "$CONFIG_FILE" || true
echo ""
# ---- 7c. Async update check (non-blocking, 5s timeout, silent failure) ----
# Writes data/.openclaw/update-available.json if a newer version is on OSS.
# Welcome.html / Config.html read this file and show a banner.
# Version file lookup: portable/OPENCLAW_VERSION (USB) → ../OPENCLAW_VERSION (dev)
VERSION_FILE="$UCLAW_DIR/OPENCLAW_VERSION"
[ -f "$VERSION_FILE" ] || VERSION_FILE="$UCLAW_DIR/../OPENCLAW_VERSION"
if [ -f "$VERSION_FILE" ]; then
"$NODE_BIN" "$UCLAW_DIR/lib/check-update.mjs" "$VERSION_FILE" "$STATE_DIR" >/dev/null 2>&1 &
fi
# ---- 8. Find available port ----
PORT=18789
while lsof -i :$PORT >/dev/null 2>&1; do
echo -e " ${YELLOW}Port $PORT in use, trying next...${NC}"
PORT=$((PORT + 1))
if [ $PORT -gt 18799 ]; then
echo -e " ${RED}No available port (18789-18799)${NC}"
# 自动上报端口全占gateway 无法启动(后台、静默、失败不影响)
UCLAW_APP_ROOT="$UCLAW_DIR" "$NODE_BIN" "$UCLAW_DIR/lib/report-bug.mjs" \
--auto --title "gateway-no-free-port" --desc "Ports 18789-18799 all in use" --root "$UCLAW_DIR" >/dev/null 2>&1 &
read -p " Press Enter to exit..."
exit 1
fi
done
# ---- 9. Start Config Server in background ----
echo -e " ${CYAN}Starting Config Center on port 18788...${NC}"
CONFIG_SERVER="$UCLAW_DIR/config-server"
"$NODE_BIN" "$CONFIG_SERVER/server.js" &
CONFIG_PID=$!
sleep 1
# ---- 10. Start gateway ----
echo -e " ${CYAN}Starting OpenClaw on port $PORT...${NC}"
echo ""
cd "$CORE_DIR"
OPENCLAW_MJS="$CORE_DIR/node_modules/openclaw/openclaw.mjs"
"$NODE_BIN" "$OPENCLAW_MJS" gateway run --allow-unconfigured --force --port $PORT &
GW_PID=$!
# ---- 11. Wait for gateway, then open browser ----
for i in $(seq 1 30); do
sleep 0.5
if curl -s -o /dev/null "http://127.0.0.1:$PORT/" 2>/dev/null; then
# Open Dashboard
open "http://127.0.0.1:$PORT/#token=uclaw" 2>/dev/null || true
# Open Config Center
open "http://127.0.0.1:18788/" 2>/dev/null || true
break
fi
done
echo -e " ${GREEN}════════════════════════════════${NC}"
echo -e " ${GREEN}🦞 U-Claw is running!${NC}"
echo -e " ${GREEN} Dashboard: http://127.0.0.1:$PORT/#token=uclaw${NC}"
echo -e " ${GREEN} Config Center: http://127.0.0.1:18788/${NC}"
echo ""
echo -e " ${YELLOW}Press Ctrl+C to stop${NC}"
echo -e " ${GREEN}════════════════════════════════${NC}"
echo ""
# ---- Cleanup on exit ----
cleanup() {
kill $GW_PID 2>/dev/null
kill $CONFIG_PID 2>/dev/null
echo ""
echo -e " 🦞 U-Claw stopped."
exit 0
}
trap cleanup INT TERM
wait $GW_PID
GW_EXIT=$?
# 自动上报gateway 异常退出。Ctrl+C 走 trap cleanupexit 0不会到这
# 走到这里说明 gateway 自己退了。退出码非 0 才上报,避免噪音。后台、静默、失败不影响。
if [ "$GW_EXIT" -ne 0 ]; then
echo -e " ${YELLOW}OpenClaw exited unexpectedly (code $GW_EXIT), reporting...${NC}"
UCLAW_APP_ROOT="$UCLAW_DIR" "$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" >/dev/null 2>&1 &
fi
kill $CONFIG_PID 2>/dev/null
echo ""
echo -e " 🦞 U-Claw stopped."