186 lines
5.9 KiB
Bash
Executable File
186 lines
5.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# ============================================================
|
|
# U-Claw - Portable AI Agent
|
|
# Linux version - run: bash Linux-Start.sh
|
|
# ============================================================
|
|
|
|
UCLAW_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
APP_DIR="$UCLAW_DIR/app"
|
|
CORE_DIR="$APP_DIR/core"
|
|
DATA_DIR="$UCLAW_DIR/data"
|
|
SYSTEM_DIR="$UCLAW_DIR/system"
|
|
|
|
GREEN='\033[0;32m'
|
|
CYAN='\033[0;36m'
|
|
RED='\033[0;31m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
clear
|
|
echo ""
|
|
echo -e "${CYAN}"
|
|
echo " ╔══════════════════════════════════════╗"
|
|
echo " ║ 🦞 U-Claw v1.1 ║"
|
|
echo " ║ Portable AI Agent (Linux) ║"
|
|
echo " ╚══════════════════════════════════════╝"
|
|
echo -e "${NC}"
|
|
|
|
# ---- 1. Detect CPU & set runtime ----
|
|
ARCH=$(uname -m)
|
|
if [ "$ARCH" = "x86_64" ]; then
|
|
NODE_DIR="$APP_DIR/runtime/node-linux-x64"
|
|
echo -e " ${GREEN}Linux x86_64${NC}"
|
|
elif [ "$ARCH" = "aarch64" ]; then
|
|
NODE_DIR="$APP_DIR/runtime/node-linux-arm64"
|
|
echo -e " ${GREEN}Linux ARM64${NC}"
|
|
else
|
|
echo -e " ${RED}Unsupported architecture: $ARCH${NC}"
|
|
echo -e " ${RED}Only x86_64 and arm64 are supported.${NC}"
|
|
echo ""
|
|
read -p " Press Enter to exit..."
|
|
exit 1
|
|
fi
|
|
|
|
NODE_BIN="$NODE_DIR/bin/node"
|
|
export PATH="$NODE_DIR/bin:$PATH"
|
|
|
|
# ---- 2. Check runtime ----
|
|
if [ ! -f "$NODE_BIN" ]; then
|
|
echo -e " ${RED}Error: Node.js runtime not found${NC}"
|
|
echo " Expected: $NODE_BIN"
|
|
echo " Please run setup.sh first or ensure app/runtime/ is complete"
|
|
read -p " Press Enter to exit..."
|
|
exit 1
|
|
fi
|
|
|
|
NODE_VER=$("$NODE_BIN" --version)
|
|
echo -e " Node.js: ${GREEN}${NODE_VER}${NC}"
|
|
echo ""
|
|
|
|
# ---- 3. Check & init data ----
|
|
mkdir -p "$DATA_DIR/memory" "$DATA_DIR/backups" "$DATA_DIR/logs"
|
|
|
|
if [ ! -f "$DATA_DIR/config.json" ] && [ ! -f "$DATA_DIR/.openclaw/openclaw.json" ]; then
|
|
echo -e " ${YELLOW}First run - creating default config...${NC}"
|
|
mkdir -p "$DATA_DIR/.openclaw"
|
|
cat > "$DATA_DIR/.openclaw/openclaw.json" << 'CFGEOF'
|
|
{
|
|
"gateway": {
|
|
"mode": "local",
|
|
"auth": { "token": "uclaw" }
|
|
}
|
|
}
|
|
CFGEOF
|
|
echo -e " ${GREEN}Config created${NC}"
|
|
echo ""
|
|
fi
|
|
|
|
# ---- 4. Set environment (portable mode) ----
|
|
STATE_DIR="$DATA_DIR/.openclaw"
|
|
mkdir -p "$STATE_DIR"
|
|
|
|
# Sync config to where OpenClaw expects it
|
|
if [ -f "$DATA_DIR/config.json" ] && [ ! -f "$STATE_DIR/openclaw.json" ]; then
|
|
cp "$DATA_DIR/config.json" "$STATE_DIR/openclaw.json"
|
|
fi
|
|
|
|
export OPENCLAW_HOME="$DATA_DIR"
|
|
export OPENCLAW_STATE_DIR="$STATE_DIR"
|
|
export OPENCLAW_CONFIG_PATH="$STATE_DIR/openclaw.json"
|
|
|
|
# ---- 5. Run migration if exists ----
|
|
if [ -f "$SYSTEM_DIR/migrate.js" ]; then
|
|
"$NODE_BIN" "$SYSTEM_DIR/migrate.js" "$DATA_DIR" 2>/dev/null || true
|
|
fi
|
|
|
|
# ---- 6. Check dependencies ----
|
|
if [ ! -d "$CORE_DIR/node_modules" ]; then
|
|
echo -e " ${YELLOW}First run - installing dependencies...${NC}"
|
|
echo " (Using China mirror)"
|
|
cd "$CORE_DIR"
|
|
"$NODE_BIN" "$NODE_DIR/bin/npm" install --registry=https://registry.npmmirror.com 2>&1
|
|
echo -e " ${GREEN}Dependencies installed${NC}"
|
|
echo ""
|
|
fi
|
|
|
|
# ---- 7. Find available port ----
|
|
PORT=18789
|
|
while ss -tlnp 2>/dev/null | grep -q ":$PORT " || netstat -tlnp 2>/dev/null | grep -q ":$PORT "; 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}"
|
|
read -p " Press Enter to exit..."
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Update config with correct port if changed
|
|
if [ $PORT -ne 18789 ]; then
|
|
"$NODE_BIN" -e "
|
|
const fs = require('fs');
|
|
const p = '$DATA_DIR/config.json';
|
|
if (fs.existsSync(p)) {
|
|
const c = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
c.gateway = c.gateway || {};
|
|
c.gateway.port = $PORT;
|
|
fs.writeFileSync(p, JSON.stringify(c, null, 2));
|
|
}
|
|
" 2>/dev/null || true
|
|
fi
|
|
|
|
# ---- 8. Start gateway ----
|
|
echo -e " ${CYAN}Starting OpenClaw on port $PORT...${NC}"
|
|
echo " Do NOT close this window."
|
|
echo ""
|
|
|
|
cd "$CORE_DIR"
|
|
|
|
TOKEN=$(python3 -c "import json,os; p='$STATE_DIR/openclaw.json' if os.path.exists('$STATE_DIR/openclaw.json') else '$DATA_DIR/config.json'; d=json.load(open(p)); print(d.get('gateway',{}).get('auth',{}).get('token','uclaw'))" 2>/dev/null || echo "uclaw")
|
|
|
|
OPENCLAW_MJS="$CORE_DIR/node_modules/openclaw/openclaw.mjs"
|
|
GW_LOG="$DATA_DIR/logs/gateway.log"
|
|
"$NODE_BIN" "$OPENCLAW_MJS" gateway run --allow-unconfigured --force --port $PORT 2>&1 | tee -a "$GW_LOG" &
|
|
GW_PID=$!
|
|
|
|
# ---- 9. Wait & open browser ----
|
|
for i in $(seq 1 30); do
|
|
sleep 0.5
|
|
if curl -s -o /dev/null -w '' "http://127.0.0.1:$PORT/" 2>/dev/null; then
|
|
DASHBOARD_URL="http://127.0.0.1:$PORT/#token=${TOKEN}"
|
|
CONFIG_PAGE="$UCLAW_DIR/Config.html?port=$PORT"
|
|
echo ""
|
|
echo -e " ${GREEN}✅ Started successfully!${NC}"
|
|
echo ""
|
|
|
|
# Check if model is configured
|
|
HAS_MODEL=$(python3 -c "
|
|
import json,os
|
|
for p in ['$STATE_DIR/openclaw.json','$DATA_DIR/config.json']:
|
|
if os.path.exists(p):
|
|
d=json.load(open(p))
|
|
if d.get('agent',{}).get('model'):
|
|
print('yes'); break
|
|
" 2>/dev/null)
|
|
|
|
if [ "$HAS_MODEL" = "yes" ]; then
|
|
echo -e " ${CYAN}Dashboard: ${DASHBOARD_URL}${NC}"
|
|
echo ""
|
|
xdg-open "$DASHBOARD_URL" 2>/dev/null || echo -e " ${YELLOW}Please open in browser: ${DASHBOARD_URL}${NC}"
|
|
else
|
|
echo -e " ${YELLOW}首次使用,打开配置页面...${NC}"
|
|
echo -e " ${CYAN}配置页面: Config.html${NC}"
|
|
echo -e " ${CYAN}控制台: ${DASHBOARD_URL}${NC}"
|
|
echo ""
|
|
xdg-open "$CONFIG_PAGE" 2>/dev/null || echo -e " ${YELLOW}Please open in browser: ${CONFIG_PAGE}${NC}"
|
|
fi
|
|
break
|
|
fi
|
|
done
|
|
|
|
wait $GW_PID
|
|
|
|
echo ""
|
|
echo -e " ${YELLOW}OpenClaw stopped.${NC}"
|
|
read -p " Press Enter to close..."
|