feat: Enhance review process with streaming events and detailed logging
This commit is contained in:
parent
a762d09b3b
commit
2f29ccff74
18
README.md
18
README.md
@ -6,10 +6,8 @@
|
||||
|
||||
## 🚀 Быстрый старт
|
||||
|
||||
### Запуск одной командой:
|
||||
|
||||
**Windows:**
|
||||
```bash
|
||||
```cmd
|
||||
start.bat
|
||||
```
|
||||
|
||||
@ -19,13 +17,15 @@ chmod +x start.sh
|
||||
./start.sh
|
||||
```
|
||||
|
||||
Это автоматически:
|
||||
- ✅ Проверит зависимости
|
||||
- ✅ Установит пакеты
|
||||
- ✅ Соберет frontend
|
||||
- ✅ Запустит сервер
|
||||
Скрипт:
|
||||
1. Соберет фронтенд в `backend/public`
|
||||
2. Запустит backend на http://localhost:8000
|
||||
3. Фронтенд отдается с бэкенда
|
||||
|
||||
**Готово!** Откройте http://localhost:8000
|
||||
**Один процесс, один порт, как в production.**
|
||||
|
||||
Перезапуск после изменений:
|
||||
- Просто запусти скрипт заново (Ctrl+C → start.bat)
|
||||
|
||||
---
|
||||
|
||||
|
||||
55
RUN.bat
Normal file
55
RUN.bat
Normal file
@ -0,0 +1,55 @@
|
||||
@echo off
|
||||
REM ===============================
|
||||
REM AI Review - Simple Launcher
|
||||
REM ===============================
|
||||
|
||||
title AI Review
|
||||
|
||||
echo.
|
||||
echo ================================
|
||||
echo AI Review - Starting
|
||||
echo ================================
|
||||
echo.
|
||||
|
||||
REM Переходим в корень проекта
|
||||
cd /d "%~dp0"
|
||||
|
||||
REM Собираем фронтенд
|
||||
echo [1/3] Building frontend...
|
||||
cd frontend
|
||||
if not exist "node_modules\" npm install
|
||||
call npm run build
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo.
|
||||
echo [ERROR] Build failed!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
cd ..
|
||||
|
||||
REM Переходим в backend
|
||||
echo.
|
||||
echo [2/3] Setup backend...
|
||||
cd backend
|
||||
|
||||
REM Создаем venv если нет
|
||||
if not exist "venv\" (
|
||||
python -m venv venv
|
||||
)
|
||||
|
||||
REM Активируем и устанавливаем зависимости
|
||||
call venv\Scripts\activate.bat
|
||||
pip install -q -r requirements.txt
|
||||
|
||||
REM Запускаем сервер
|
||||
echo.
|
||||
echo [3/3] Starting server...
|
||||
echo ================================
|
||||
echo.
|
||||
echo http://localhost:8000
|
||||
echo.
|
||||
echo ================================
|
||||
echo.
|
||||
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
||||
|
||||
@ -526,7 +526,11 @@ class ReviewerAgent:
|
||||
on_event: callable = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Run the review workflow with streaming events"""
|
||||
print(f"\n{'='*80}")
|
||||
print(f"🎬 Starting review stream for PR #{pr_number}")
|
||||
print(f" Review ID: {review_id}")
|
||||
print(f" Callback: {on_event is not None}")
|
||||
print(f"{'='*80}\n")
|
||||
|
||||
# Store callback in instance for access in nodes
|
||||
self._stream_callback = on_event
|
||||
@ -545,9 +549,10 @@ class ReviewerAgent:
|
||||
|
||||
final_state = None
|
||||
event_count = 0
|
||||
callback_count = 0
|
||||
|
||||
# Stream through the graph
|
||||
print(f"📊 Starting graph stream with mode=['updates']")
|
||||
print(f"📊 Starting graph.astream() with mode=['updates']\n")
|
||||
|
||||
try:
|
||||
async for event in self.graph.astream(
|
||||
@ -555,33 +560,59 @@ class ReviewerAgent:
|
||||
stream_mode=["updates"]
|
||||
):
|
||||
event_count += 1
|
||||
print(f"📨 Event #{event_count} received from graph")
|
||||
print(f" Type: {type(event)}")
|
||||
print(f" Event content: {event}")
|
||||
print(f"\n{'─'*80}")
|
||||
print(f"📨 STREAM Event #{event_count}")
|
||||
print(f" Type: {type(event).__name__}")
|
||||
print(f" Is tuple: {isinstance(event, tuple)}")
|
||||
print(f" Content: {event}")
|
||||
print(f"{'─'*80}")
|
||||
|
||||
# LangGraph returns events as dict: {node_name: node_output}
|
||||
if isinstance(event, dict):
|
||||
for node_name, node_data in event.items():
|
||||
print(f" 🔔 Node update: {node_name}")
|
||||
print(f" 🔔 Node data type: {type(node_data)}")
|
||||
# LangGraph returns events as tuple: ('updates', {node_name: node_output})
|
||||
if isinstance(event, tuple) and len(event) == 2:
|
||||
event_type, event_data = event[0], event[1]
|
||||
print(f"✓ Tuple detected:")
|
||||
print(f" [0] event_type: '{event_type}'")
|
||||
print(f" [1] event_data type: {type(event_data).__name__}")
|
||||
|
||||
if on_event:
|
||||
print(f" 📤 Sending event to callback for node: {node_name}")
|
||||
await on_event({
|
||||
"type": "agent_step",
|
||||
"step": node_name,
|
||||
"message": f"Шаг: {node_name}",
|
||||
"data": {
|
||||
"status": node_data.get("status") if isinstance(node_data, dict) else None
|
||||
}
|
||||
})
|
||||
# Handle 'updates' events
|
||||
if event_type == 'updates' and isinstance(event_data, dict):
|
||||
print(f"✓ Updates event with dict data")
|
||||
for node_name, node_state in event_data.items():
|
||||
print(f"\n 🔔 Node: '{node_name}'")
|
||||
print(f" State type: {type(node_state).__name__}")
|
||||
|
||||
# Store final state
|
||||
if isinstance(node_data, dict):
|
||||
final_state = node_data
|
||||
if on_event:
|
||||
callback_count += 1
|
||||
print(f" 📤 Calling callback #{callback_count}...")
|
||||
try:
|
||||
await on_event({
|
||||
"type": "agent_step",
|
||||
"step": node_name,
|
||||
"message": f"Шаг: {node_name}",
|
||||
"data": {
|
||||
"status": node_state.get("status") if isinstance(node_state, dict) else None
|
||||
}
|
||||
})
|
||||
print(f" ✓ Callback executed successfully")
|
||||
except Exception as e:
|
||||
print(f" ❌ Callback error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
else:
|
||||
print(f" ⚠️ No callback set!")
|
||||
|
||||
# Store final state
|
||||
if isinstance(node_state, dict):
|
||||
final_state = node_state
|
||||
else:
|
||||
print(f" ⚠️ Not an 'updates' event or data is not dict")
|
||||
print(f" event_type={event_type}, isinstance(event_data, dict)={isinstance(event_data, dict)}")
|
||||
|
||||
else:
|
||||
print(f" ⚠️ Unexpected event format (not dict): {type(event)}")
|
||||
print(f" ❌ NOT a tuple or wrong length!")
|
||||
print(f" isinstance(event, tuple)={isinstance(event, tuple)}")
|
||||
if isinstance(event, tuple):
|
||||
print(f" len(event)={len(event)}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error in graph streaming: {e}")
|
||||
|
||||
@ -131,9 +131,41 @@ async def get_review(
|
||||
|
||||
|
||||
async def run_review_task(review_id: int, pr_number: int, repository_id: int, db: AsyncSession):
|
||||
"""Background task to run review"""
|
||||
"""Background task to run review with streaming"""
|
||||
from app.main import manager
|
||||
from datetime import datetime as dt
|
||||
|
||||
# Create event handler for streaming
|
||||
async def on_review_event(event: dict):
|
||||
"""Handle review events and broadcast to clients"""
|
||||
try:
|
||||
event_data = {
|
||||
"type": event.get("type", "agent_update"),
|
||||
"review_id": review_id,
|
||||
"pr_number": pr_number,
|
||||
"timestamp": dt.utcnow().isoformat(),
|
||||
"data": event
|
||||
}
|
||||
|
||||
# Save to DB
|
||||
from app.models.review_event import ReviewEvent
|
||||
db_event = ReviewEvent(
|
||||
review_id=review_id,
|
||||
event_type=event.get("type", "agent_update"),
|
||||
step=event.get("step"),
|
||||
message=event.get("message"),
|
||||
data=event
|
||||
)
|
||||
db.add(db_event)
|
||||
await db.commit()
|
||||
|
||||
# Broadcast
|
||||
await manager.broadcast(event_data)
|
||||
except Exception as e:
|
||||
print(f"Error in review event handler: {e}")
|
||||
|
||||
agent = ReviewerAgent(db)
|
||||
await agent.run_review(review_id, pr_number, repository_id)
|
||||
await agent.run_review_stream(review_id, pr_number, repository_id, on_event=on_review_event)
|
||||
|
||||
|
||||
@router.post("/{review_id}/retry")
|
||||
|
||||
@ -13,11 +13,43 @@ router = APIRouter()
|
||||
|
||||
|
||||
async def start_review_task(review_id: int, pr_number: int, repository_id: int):
|
||||
"""Background task to start review"""
|
||||
"""Background task to start review with streaming"""
|
||||
from app.database import async_session_maker
|
||||
from app.main import manager
|
||||
from datetime import datetime as dt
|
||||
|
||||
async with async_session_maker() as db:
|
||||
# Create event handler for streaming
|
||||
async def on_review_event(event: dict):
|
||||
"""Handle review events and broadcast to clients"""
|
||||
try:
|
||||
event_data = {
|
||||
"type": event.get("type", "agent_update"),
|
||||
"review_id": review_id,
|
||||
"pr_number": pr_number,
|
||||
"timestamp": dt.utcnow().isoformat(),
|
||||
"data": event
|
||||
}
|
||||
|
||||
# Save to DB
|
||||
from app.models.review_event import ReviewEvent
|
||||
db_event = ReviewEvent(
|
||||
review_id=review_id,
|
||||
event_type=event.get("type", "agent_update"),
|
||||
step=event.get("step"),
|
||||
message=event.get("message"),
|
||||
data=event
|
||||
)
|
||||
db.add(db_event)
|
||||
await db.commit()
|
||||
|
||||
# Broadcast
|
||||
await manager.broadcast(event_data)
|
||||
except Exception as e:
|
||||
print(f"Error in webhook review event handler: {e}")
|
||||
|
||||
agent = ReviewerAgent(db)
|
||||
await agent.run_review(review_id, pr_number, repository_id)
|
||||
await agent.run_review_stream(review_id, pr_number, repository_id, on_event=on_review_event)
|
||||
|
||||
|
||||
@router.post("/gitea/{repository_id}")
|
||||
|
||||
@ -29,11 +29,23 @@ class ConnectionManager:
|
||||
|
||||
async def broadcast(self, message: dict):
|
||||
"""Broadcast message to all connected clients"""
|
||||
for connection in self.active_connections:
|
||||
print(f"\n[BROADCAST] Sending to {len(self.active_connections)} clients")
|
||||
print(f"[BROADCAST] Message type: {message.get('type')}")
|
||||
print(f"[BROADCAST] Message: {str(message)[:200]}...")
|
||||
|
||||
sent_count = 0
|
||||
error_count = 0
|
||||
|
||||
for i, connection in enumerate(self.active_connections):
|
||||
try:
|
||||
await connection.send_json(message)
|
||||
except Exception:
|
||||
pass
|
||||
sent_count += 1
|
||||
print(f"[BROADCAST] ✓ Sent to client #{i+1}")
|
||||
except Exception as e:
|
||||
error_count += 1
|
||||
print(f"[BROADCAST] ✗ Failed to send to client #{i+1}: {e}")
|
||||
|
||||
print(f"[BROADCAST] Result: {sent_count} sent, {error_count} failed")
|
||||
|
||||
|
||||
# Create connection manager
|
||||
|
||||
@ -206,6 +206,14 @@ class ReviewTaskWorker:
|
||||
# Create event handler
|
||||
async def on_review_event(event: dict):
|
||||
"""Handle review events and broadcast to clients"""
|
||||
print(f"\n{'*'*80}")
|
||||
print(f"CALLBACK INVOKED!")
|
||||
print(f" Event type: {event.get('type')}")
|
||||
print(f" Event step: {event.get('step')}")
|
||||
print(f" Event message: {event.get('message')}")
|
||||
print(f" Active WS connections: {len(manager.active_connections)}")
|
||||
print(f"{'*'*80}")
|
||||
|
||||
try:
|
||||
# Prepare event data
|
||||
event_data = {
|
||||
@ -216,6 +224,7 @@ class ReviewTaskWorker:
|
||||
"data": event
|
||||
}
|
||||
|
||||
print(f" Prepared event_data: {event_data}")
|
||||
logger.info(f" 🔔 Broadcasting event: type={event.get('type')}, connections={len(manager.active_connections)}")
|
||||
|
||||
# Save event to database
|
||||
@ -229,10 +238,13 @@ class ReviewTaskWorker:
|
||||
)
|
||||
db.add(db_event)
|
||||
await db.commit()
|
||||
print(f" ✓ Event saved to DB: {db_event.id}")
|
||||
logger.debug(f" 💾 Event saved to DB: {db_event.id}")
|
||||
|
||||
# Broadcast to all connected clients
|
||||
print(f" Broadcasting to {len(manager.active_connections)} connections...")
|
||||
await manager.broadcast(event_data)
|
||||
print(f" ✓ Broadcast completed")
|
||||
|
||||
# Log the event
|
||||
if event.get("type") == "agent_step":
|
||||
@ -242,6 +254,7 @@ class ReviewTaskWorker:
|
||||
message = event.get("message", "")[:100]
|
||||
logger.info(f" 💬 LLM: {message}...")
|
||||
except Exception as e:
|
||||
print(f" ❌ ERROR in callback: {e}")
|
||||
logger.error(f" ❌ Ошибка broadcast события: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
1
backend/test_graph_format.py
Normal file
1
backend/test_graph_format.py
Normal file
@ -0,0 +1 @@
|
||||
|
||||
146
start.bat
146
start.bat
@ -1,100 +1,78 @@
|
||||
@echo off
|
||||
REM Единый скрипт запуска AI Code Review Platform
|
||||
REM AI Review - Build & Start
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo AI Code Review Platform - Запуск
|
||||
echo ========================================
|
||||
echo ================================
|
||||
echo AI Review - Starting
|
||||
echo ================================
|
||||
echo.
|
||||
|
||||
REM 1. Проверка Node.js
|
||||
echo [STEP 1/7] Проверка Node.js...
|
||||
where node >nul 2>nul
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [ERROR] Node.js не установлен! Установите Node.js 18+ и попробуйте снова.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
node --version
|
||||
echo [OK] Node.js установлен
|
||||
echo.
|
||||
|
||||
REM 2. Проверка Python
|
||||
echo [STEP 2/7] Проверка Python...
|
||||
where python >nul 2>nul
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [ERROR] Python не установлен! Установите Python 3.10+ и попробуйте снова.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
python --version
|
||||
echo [OK] Python установлен
|
||||
echo.
|
||||
|
||||
REM 3. Установка зависимостей frontend
|
||||
echo [STEP 3/7] Установка зависимостей frontend...
|
||||
REM 1. Build Frontend
|
||||
echo [1/3] Building frontend...
|
||||
cd frontend
|
||||
|
||||
if not exist "node_modules\" (
|
||||
echo Установка npm пакетов...
|
||||
echo Installing npm packages...
|
||||
call npm install
|
||||
) else (
|
||||
echo node_modules уже существует, пропускаем...
|
||||
)
|
||||
echo [OK] Зависимости frontend установлены
|
||||
echo.
|
||||
|
||||
REM 4. Сборка frontend
|
||||
echo [STEP 4/7] Сборка frontend...
|
||||
|
||||
REM Создаем .env.production для production
|
||||
echo VITE_API_URL=/api > .env.production
|
||||
echo VITE_WS_URL= >> .env.production
|
||||
|
||||
call npm run build
|
||||
echo [OK] Frontend собран в backend/public
|
||||
echo.
|
||||
|
||||
REM 5. Установка зависимостей backend
|
||||
cd ..\backend
|
||||
echo [STEP 5/7] Установка зависимостей backend...
|
||||
if not exist "venv\" (
|
||||
echo Создание виртуального окружения...
|
||||
python -m venv venv
|
||||
)
|
||||
|
||||
REM Активация venv
|
||||
call venv\Scripts\activate.bat
|
||||
|
||||
REM Установка зависимостей
|
||||
pip install -r requirements.txt
|
||||
echo [OK] Зависимости backend установлены
|
||||
echo.
|
||||
|
||||
REM 6. Проверка .env
|
||||
echo [STEP 6/7] Проверка конфигурации...
|
||||
if not exist ".env" (
|
||||
echo [WARNING] Файл .env не найден!
|
||||
if exist ".env.example" (
|
||||
echo Создаем .env из примера...
|
||||
copy .env.example .env
|
||||
echo [OK] Создан .env файл
|
||||
echo [WARNING] ВАЖНО: Отредактируйте .env и добавьте необходимые токены!
|
||||
) else (
|
||||
echo [ERROR] .env.example не найден!
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [ERROR] npm install failed
|
||||
cd ..
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
echo.
|
||||
|
||||
REM 7. Запуск backend
|
||||
echo [STEP 7/7] Запуск сервера...
|
||||
echo ========================================
|
||||
echo Building...
|
||||
call npm run build
|
||||
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [ERROR] Frontend build failed
|
||||
cd ..
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo [OK] Frontend built to backend\public
|
||||
cd ..
|
||||
|
||||
REM 2. Setup Backend
|
||||
echo.
|
||||
echo Backend: http://localhost:8000
|
||||
echo Frontend: http://localhost:8000
|
||||
echo [2/3] Setting up backend...
|
||||
cd backend
|
||||
|
||||
if not exist "venv\" (
|
||||
echo Creating venv...
|
||||
python -m venv venv
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [ERROR] Failed to create venv
|
||||
cd ..
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
echo Activating venv...
|
||||
call venv\Scripts\activate.bat
|
||||
|
||||
echo Installing dependencies...
|
||||
pip install -q -r requirements.txt
|
||||
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [ERROR] Failed to install dependencies
|
||||
cd ..
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM 3. Start Backend
|
||||
echo.
|
||||
echo [3/3] Starting server...
|
||||
echo ================================
|
||||
echo.
|
||||
echo URL: http://localhost:8000
|
||||
echo API Docs: http://localhost:8000/docs
|
||||
echo.
|
||||
echo Для остановки нажмите Ctrl+C
|
||||
echo Press Ctrl+C to stop
|
||||
echo ================================
|
||||
echo.
|
||||
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
||||
|
||||
|
||||
110
start.sh
110
start.sh
@ -1,104 +1,54 @@
|
||||
#!/bin/bash
|
||||
# Единый скрипт запуска AI Code Review Platform
|
||||
# AI Review - Build & Start
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 AI Code Review Platform - Запуск"
|
||||
echo "===================================="
|
||||
echo "================================"
|
||||
echo "AI Review - Starting"
|
||||
echo "================================"
|
||||
echo ""
|
||||
|
||||
# Цвета для вывода
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 1. Проверка Node.js
|
||||
echo -e "${YELLOW}📦 Проверка Node.js...${NC}"
|
||||
if ! command -v node &> /dev/null; then
|
||||
echo "❌ Node.js не установлен! Установите Node.js 18+ и попробуйте снова."
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${GREEN}✅ Node.js $(node --version)${NC}"
|
||||
echo ""
|
||||
|
||||
# 2. Проверка Python
|
||||
echo -e "${YELLOW}🐍 Проверка Python...${NC}"
|
||||
if ! command -v python &> /dev/null && ! command -v python3 &> /dev/null; then
|
||||
echo "❌ Python не установлен! Установите Python 3.10+ и попробуйте снова."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PYTHON_CMD="python3"
|
||||
if ! command -v python3 &> /dev/null; then
|
||||
PYTHON_CMD="python"
|
||||
fi
|
||||
echo -e "${GREEN}✅ Python $($PYTHON_CMD --version)${NC}"
|
||||
echo ""
|
||||
|
||||
# 3. Установка зависимостей frontend
|
||||
echo -e "${YELLOW}📦 Установка зависимостей frontend...${NC}"
|
||||
# 1. Build Frontend
|
||||
echo "[1/3] Building frontend..."
|
||||
cd frontend
|
||||
|
||||
if [ ! -d "node_modules" ]; then
|
||||
echo "Installing npm packages..."
|
||||
npm install
|
||||
else
|
||||
echo "node_modules уже существует, пропускаем..."
|
||||
fi
|
||||
echo -e "${GREEN}✅ Зависимости frontend установлены${NC}"
|
||||
echo ""
|
||||
|
||||
# 4. Сборка frontend
|
||||
echo -e "${YELLOW}🔨 Сборка frontend...${NC}"
|
||||
|
||||
# Создаем .env.production для production
|
||||
cat > .env.production << 'EOF'
|
||||
VITE_API_URL=/api
|
||||
VITE_WS_URL=
|
||||
EOF
|
||||
|
||||
echo "Building..."
|
||||
npm run build
|
||||
echo -e "${GREEN}✅ Frontend собран в backend/public${NC}"
|
||||
echo ""
|
||||
|
||||
# 5. Установка зависимостей backend
|
||||
cd ../backend
|
||||
echo -e "${YELLOW}📦 Установка зависимостей backend...${NC}"
|
||||
echo "[OK] Frontend built to backend/public"
|
||||
cd ..
|
||||
|
||||
# 2. Setup Backend
|
||||
echo ""
|
||||
echo "[2/3] Setting up backend..."
|
||||
cd backend
|
||||
|
||||
if [ ! -d "venv" ]; then
|
||||
echo "Создание виртуального окружения..."
|
||||
$PYTHON_CMD -m venv venv
|
||||
echo "Creating venv..."
|
||||
python3 -m venv venv
|
||||
fi
|
||||
|
||||
# Активация venv
|
||||
echo "Activating venv..."
|
||||
source venv/bin/activate
|
||||
|
||||
# Установка зависимостей
|
||||
pip install -r requirements.txt
|
||||
echo -e "${GREEN}✅ Зависимости backend установлены${NC}"
|
||||
echo ""
|
||||
echo "Installing dependencies..."
|
||||
pip install -q -r requirements.txt
|
||||
|
||||
# 6. Проверка .env
|
||||
if [ ! -f ".env" ]; then
|
||||
echo -e "${YELLOW}⚠️ Файл .env не найден!${NC}"
|
||||
echo "Создаем .env из примера..."
|
||||
if [ -f ".env.example" ]; then
|
||||
cp .env.example .env
|
||||
echo -e "${GREEN}✅ Создан .env файл${NC}"
|
||||
echo -e "${YELLOW}⚠️ ВАЖНО: Отредактируйте .env и добавьте необходимые токены!${NC}"
|
||||
else
|
||||
echo "❌ .env.example не найден!"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 7. Запуск backend
|
||||
echo -e "${GREEN}🎉 Запуск сервера...${NC}"
|
||||
echo "===================================="
|
||||
# 3. Start Backend
|
||||
echo ""
|
||||
echo "📍 Backend: http://localhost:8000"
|
||||
echo "📍 Frontend: http://localhost:8000"
|
||||
echo "📍 API Docs: http://localhost:8000/docs"
|
||||
echo "[3/3] Starting server..."
|
||||
echo "================================"
|
||||
echo ""
|
||||
echo "Для остановки нажмите Ctrl+C"
|
||||
echo "URL: http://localhost:8000"
|
||||
echo "API Docs: http://localhost:8000/docs"
|
||||
echo ""
|
||||
echo "Press Ctrl+C to stop"
|
||||
echo "================================"
|
||||
echo ""
|
||||
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user