@echo off setlocal enabledelayedexpansion :: ======================================== :: Cyrene ethend CLI (Windows CMD) :: Usage: ethend.bat [command] [options] :: ======================================== set "SCRIPT_DIR=%~dp0" set "ETHEND_DIR=%SCRIPT_DIR%ethend" set "ROOT=%SCRIPT_DIR%" if "%ETHEND_PORT%"=="" (set PORT=9090) else (set PORT=%ETHEND_PORT%) set "LOG_DIR=%ETHEND_DIR%\logs" set "LOG_FILE=%LOG_DIR%\sh.log" set "DB_COMPOSE_FILE=%ROOT%docker-compose.dev.db.yml" :: Parse first argument as command set CMD=%1 if "%CMD%"=="" set CMD=start if "%CMD%"=="help" goto :help if "%CMD%"=="--help" goto :help if "%CMD%"=="/?" goto :help if "%CMD%"=="start" goto :start if "%CMD%"=="stop" goto :stop if "%CMD%"=="status" goto :status if "%CMD%"=="logs" goto :logs if "%CMD%"=="build" goto :build if "%CMD%"=="db:start" goto :db_start if "%CMD%"=="db:stop" goto :db_stop if "%CMD%"=="db:status" goto :db_status echo [ERROR] Unknown command: %CMD% echo. goto :help :: ========================================== :help echo Cyrene ethend - Development Management Tool echo. echo Usage: ethend.bat [command] [options] echo. echo Commands: echo start Start ethend console (default) echo start --build Build all services before start echo start --fresh Force restart all services before start echo stop Stop ethend console echo status Show all service status echo logs [service] View service logs (default: last 20 lines) echo build [service] Build service(s) (omit to build all) echo db:start Start database containers echo db:stop Stop database containers echo db:status Check database connection status echo help Show this help echo. echo Options: echo --build Build all backend services before start echo --fresh Force restart all services before start echo. echo Examples: echo ethend.bat Quick start echo ethend.bat start --build Build and start echo ethend.bat start --fresh Fresh restart echo ethend.bat logs gateway View Gateway log echo ethend.bat build ai-core Build AI-Core only echo ethend.bat db:status Check database echo. echo Web console: http://localhost:%PORT% exit /b 0 :: ========================================== :check_node where node >nul 2>&1 if %ERRORLEVEL%==0 ( set NODE_CMD=node goto :eof ) if exist "C:\Program Files\nodejs\node.exe" ( set "NODE_CMD=C:\Program Files\nodejs\node.exe" goto :eof ) echo [ERROR] Node.js not found. Install Node.js 20+ and add to PATH. pause exit /b 1 :: ========================================== :start echo. echo ========================================== echo Cyrene ethend echo ========================================== call :check_node for /f "tokens=*" %%i in ('!NODE_CMD! --version') do echo Node.js: %%i echo Port: %PORT% :: Check for --build / --fresh set DO_BUILD=0 set DO_FRESH=0 for %%a in (%*) do ( if "%%a"=="--build" set DO_BUILD=1 if "%%a"=="--fresh" set DO_FRESH=1 ) :: Build if requested if %DO_BUILD%==1 ( echo. echo [INFO] Building all backend services... call :build_all ) :: Fresh restart if requested if %DO_FRESH%==1 ( echo. echo [INFO] Force restarting all services... curl -s -X POST "http://localhost:%PORT%/api/services/start-all-fresh" >nul 2>&1 ) :: Check if already running curl -s -o nul "http://localhost:%PORT%/api/health" 2>nul if %ERRORLEVEL%==0 ( echo. echo [OK] ethend already running: http://localhost:%PORT% echo API: http://localhost:%PORT%/api/health exit /b 0 ) :: Free port for /f "tokens=5" %%a in ('netstat -ano ^| findstr /R ":%PORT% " ^| findstr "LISTENING"') do ( echo [WARN] Port %PORT% in use by PID %%a, releasing... taskkill /PID %%a /F >nul 2>&1 timeout /t 1 /nobreak >nul ) cd /d "%ETHEND_DIR%" :: Install dependencies if not exist "node_modules\" ( echo [INFO] Installing dependencies... call npm install --silent ) :: Ensure log directory if not exist "%LOG_DIR%" mkdir "%LOG_DIR%" echo. echo [INFO] Starting ethend on port %PORT% echo Web UI: http://localhost:%PORT% echo API: http://localhost:%PORT%/api/health echo WebSocket: ws://localhost:%PORT%/ws echo. start "Cyrene-ethend" /B !NODE_CMD! src\index.js 1>>"%LOG_FILE%" 2>&1 :: Health check (up to 30s) echo [INFO] Waiting for ethend to be ready... set MAX_WAIT=30 set WAITED=0 :health_loop if %WAITED% geq %MAX_WAIT% goto :timeout powershell -Command "try { (Invoke-WebRequest 'http://localhost:%PORT%/api/health' -TimeoutSec 2 -UseBasicParsing).StatusCode -eq 200 } catch { $false }" | findstr "True" >nul 2>&1 if %ERRORLEVEL%==0 ( echo. echo ========================================== echo ethend is ready! echo Console: http://localhost:%PORT% echo Log: %LOG_FILE% echo ========================================== echo. exit /b 0 ) timeout /t 1 /nobreak >nul set /a WAITED+=1 goto :health_loop :timeout echo. echo [WARN] Still starting - waited %MAX_WAIT%s echo Check http://localhost:%PORT%/api/health exit /b 0 :: ========================================== :stop for /f "tokens=5" %%a in ('netstat -ano ^| findstr /R ":%PORT% " ^| findstr "LISTENING"') do ( echo [INFO] Stopping ethend (PID: %%a)... taskkill /PID %%a /F >nul 2>&1 echo [OK] ethend stopped exit /b 0 ) echo [INFO] ethend is not running exit /b 0 :: ========================================== :status curl -s -o nul "http://localhost:%PORT%/api/health" 2>nul if %ERRORLEVEL% neq 0 ( echo [ERROR] ethend is offline exit /b 1 ) echo [OK] ethend online echo. echo Service Status: curl -s "http://localhost:%PORT%/api/services" 2>nul | !NODE_CMD! -e "const d=require('fs').readFileSync(0,'utf-8');const s=JSON.parse(d);for(const[k,v]of Object.entries(s)){const icon=v.status==='running'?'+':' ';const pid=v.pid?' (PID:'+v.pid+')':'';const upt=v.uptime?' uptime:'+Math.round(v.uptime/1000)+'s':'';console.log(' ['+icon+'] '+v.name.padEnd(18)+v.status+pid+upt);}" 2>nul echo. echo Database: powershell -Command "$tcp=New-Object Net.Sockets.TcpClient;try{$tcp.Connect('127.0.0.1',5432);' [OK] PostgreSQL online'}catch{' [--] PostgreSQL offline'};$tcp.Dispose()" 2>nul exit /b 0 :: ========================================== :logs set SVC_ID=%2 set LINES=%3 if "%SVC_ID%"=="" ( echo Usage: ethend.bat logs ^ [lines] echo Available: gateway, ai-core, memory-service, tool-engine, voice-service, iot-debug-service, plugin-manager, platform-bridge, frontend exit /b 1 ) if "%LINES%"=="" set LINES=20 set "LOG_PATH=%LOG_DIR%\%SVC_ID%.log" if not exist "%LOG_PATH%" ( echo [WARN] Log file not found: %LOG_PATH% exit /b 1 ) echo === %SVC_ID% log (last %LINES% lines) === powershell -Command "Get-Content '%LOG_PATH%' -Tail %LINES%" 2>nul exit /b 0 :: ========================================== :build call :check_node set SVC_ID=%2 if not "%SVC_ID%"=="" goto :build_one :build_all echo [INFO] Building all backend services... set SERVICES=memory-service:backend/memory-service tool-engine:backend/tool-engine iot-debug-service:backend/iot-debug-service voice-service:backend/voice-service ai-core:backend/ai-core plugin-manager:backend/plugin-manager platform-bridge:backend/platform-bridge gateway:backend/gateway for %%s in (%SERVICES%) do ( for /f "tokens=1,2 delims=:" %%a in ("%%s") do ( if exist "%ROOT%%%b" ( echo Building %%a... cd /d "%ROOT%%%b" set GOWORK=off go build -o main.exe .\cmd\main.go 2>&1 if !ERRORLEVEL!==0 ( echo [OK] %%a ) else ( echo [FAIL] %%a ) ) ) ) cd /d "%ROOT%" echo [OK] Build complete exit /b 0 :build_one for %%s in (memory-service:backend/memory-service tool-engine:backend/tool-engine iot-debug-service:backend/iot-debug-service voice-service:backend/voice-service ai-core:backend/ai-core plugin-manager:backend/plugin-manager platform-bridge:backend/platform-bridge gateway:backend/gateway) do ( for /f "tokens=1,2 delims=:" %%a in ("%%s") do ( if "%%a"=="%SVC_ID%" ( if not exist "%ROOT%%%b" ( echo [ERROR] Service directory not found: %%b exit /b 1 ) echo [INFO] Building %%a... cd /d "%ROOT%%%b" set GOWORK=off go build -o main.exe .\cmd\main.go 2>&1 if !ERRORLEVEL!==0 (echo [OK] %%a) else (echo [FAIL] %%a) cd /d "%ROOT%" exit /b !ERRORLEVEL! ) ) ) echo [ERROR] Unknown service: %SVC_ID% echo Available: memory-service, tool-engine, iot-debug-service, voice-service, ai-core, plugin-manager, platform-bridge, gateway exit /b 1 :: ========================================== :db_start echo [INFO] Starting database containers... if not exist "%DB_COMPOSE_FILE%" ( echo [ERROR] File not found: %DB_COMPOSE_FILE% exit /b 1 ) docker compose -f "%DB_COMPOSE_FILE%" up -d echo [OK] Database containers started exit /b 0 :: ========================================== :db_stop echo [INFO] Stopping database containers... if not exist "%DB_COMPOSE_FILE%" ( echo [ERROR] File not found: %DB_COMPOSE_FILE% exit /b 1 ) docker compose -f "%DB_COMPOSE_FILE%" down echo [OK] Database containers stopped exit /b 0 :: ========================================== :db_status powershell -Command "$tcp=New-Object Net.Sockets.TcpClient;try{$tcp.Connect('127.0.0.1',5432);Write-Host ' [OK] PostgreSQL online'}catch{Write-Host ' [--] PostgreSQL offline'};$tcp.Dispose()" 2>nul exit /b 0