Полное изменение подхода: создание отдельного мок-сервера для API дизайнера
Browse files- Dockerfile +6 -28
- app.py +143 -47
Dockerfile
CHANGED
|
@@ -62,6 +62,7 @@ RUN mkdir -p /app/server/bin && \
|
|
| 62 |
mkdir -p /tmp/ten_agent && \
|
| 63 |
mkdir -p /app/.pnpm-store && \
|
| 64 |
mkdir -p /app/backup && \
|
|
|
|
| 65 |
chown -R tenuser:tenuser /app && \
|
| 66 |
chown -R tenuser:tenuser /tmp/ten_agent
|
| 67 |
|
|
@@ -69,33 +70,25 @@ RUN mkdir -p /app/server/bin && \
|
|
| 69 |
COPY .env /app/.env
|
| 70 |
RUN chown tenuser:tenuser /app/.env
|
| 71 |
|
| 72 |
-
#
|
| 73 |
-
|
| 74 |
-
RUN echo 'package internal\n\nimport (\n\t"encoding/json"\n\t"fmt"\n\t"io/ioutil"\n\t"os"\n\t"path/filepath"\n)\n\n// GraphInfo представляет информацию о графе\ntype GraphInfo struct {\n\tName string `json:"name"`\n\tDescription string `json:"description"`\n\tFile string `json:"file"`\n}\n\n// PropertyJson структура файла property.json\ntype PropertyJson struct {\n\tTen map[string]interface{} `json:"_ten"`\n\tName string `json:"name"`\n\tVersion string `json:"version"`\n\tExtensions []string `json:"extensions"`\n\tDescription string `json:"description"`\n\tGraphs []GraphInfo `json:"graphs"`\n}\n\n// ReadGraphsFromPropertyJson читает список графов из property.json\nfunc ReadGraphsFromPropertyJson() ([]GraphInfo, error) {\n\tpropertyPath := filepath.Join("/app/agents", "property.json")\n\n\tdata, err := ioutil.ReadFile(propertyPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf("ошибка чтения property.json: %v", err)\n\t}\n\n\tvar property PropertyJson\n\terr = json.Unmarshal(data, &property)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf("ошибка разбора property.json: %v", err)\n\t}\n\n\treturn property.Graphs, nil\n}' > /app/server/internal/property_parser.go
|
| 75 |
|
| 76 |
-
#
|
| 77 |
-
RUN sed -i 's/func (s \*HttpServer) handleGraphs/func oldHandleGraphs/g' /app/server/internal/http_server.go && \
|
| 78 |
-
echo 'func (s *HttpServer) handleGraphs(c *gin.Context) {\n\tgraphs, err := ReadGraphsFromPropertyJson()\n\tif err != nil {\n\t\ts.logger.Error(fmt.Sprintf("Failed to read graphs: %v", err))\n\t\tc.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})\n\t\treturn\n\t}\n\tc.JSON(http.StatusOK, graphs)\n}' >> /app/server/internal/http_server.go
|
| 79 |
-
|
| 80 |
-
# Патчим файл конфигурации Next.js для перенаправления запросов
|
| 81 |
RUN echo 'module.exports = { \
|
| 82 |
async rewrites() { \
|
| 83 |
return [ \
|
| 84 |
{ \
|
| 85 |
source: "/api/designer/:path*", \
|
| 86 |
-
destination: "/api/agents/:path*", \
|
| 87 |
}, \
|
| 88 |
{ \
|
| 89 |
source: "/api/dev/:path*", \
|
| 90 |
-
destination: "/api/agents/:path*", \
|
| 91 |
}, \
|
| 92 |
]; \
|
| 93 |
}, \
|
| 94 |
};' > /app/playground/next.config.js
|
| 95 |
|
| 96 |
-
# Патчим API сервер для обработки запросов дизайнера
|
| 97 |
-
RUN echo 'package main\n\nimport (\n\t"net/http"\n\t\n\t"github.com/gin-gonic/gin"\n)\n\nfunc init() {\n\t// Добавляем обработчик для дизайнера\n\tregisterDesignerHandlers()\n}\n\nfunc registerDesignerHandlers() {\n\t// Регистрация дополнительных обработчиков в gin\n\thttp.DefaultServeMux.HandleFunc("/api/designer/v1/packages/reload", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Header().Set("Content-Type", "application/json")\n\t\tw.WriteHeader(http.StatusOK)\n\t\tw.Write([]byte(`{"success":true}`))\n\t})\n\n\thttp.DefaultServeMux.HandleFunc("/api/dev/v1/packages/reload", func(w http.ResponseWriter, r *http.Request) {\n\t\tw.Header().Set("Content-Type", "application/json")\n\t\tw.WriteHeader(http.StatusOK)\n\t\tw.Write([]byte(`{"success":true}`))\n\t})\n}' > /app/server/designer_handlers.go
|
| 98 |
-
|
| 99 |
# Компилируем сервер
|
| 100 |
RUN cd /app/server && \
|
| 101 |
go mod tidy && \
|
|
@@ -109,19 +102,6 @@ ENV PATH="$PNPM_HOME:$PATH"
|
|
| 109 |
RUN cd /app/playground && \
|
| 110 |
pnpm install
|
| 111 |
|
| 112 |
-
# Подготавливаем пример агента для работы Select Graph
|
| 113 |
-
RUN cd /app && \
|
| 114 |
-
mkdir -p agents/examples && \
|
| 115 |
-
mkdir -p agents/examples/default && \
|
| 116 |
-
mkdir -p agents/examples/demo && \
|
| 117 |
-
mkdir -p agents/examples/experimental
|
| 118 |
-
|
| 119 |
-
# Копируем примеры из репозитория
|
| 120 |
-
RUN cd /app && \
|
| 121 |
-
cp -r agents/examples/default agents/ && \
|
| 122 |
-
cp -r agents/examples/demo agents/ && \
|
| 123 |
-
cp -r agents/examples/experimental agents/
|
| 124 |
-
|
| 125 |
# Создаем базовый manifest.json
|
| 126 |
RUN echo '{\n\
|
| 127 |
"name": "default",\n\
|
|
@@ -177,8 +157,6 @@ RUN echo '{\n\
|
|
| 177 |
|
| 178 |
# Устанавливаем правильные права доступа для всех файлов
|
| 179 |
RUN chmod -R 777 /app && \
|
| 180 |
-
chown -R tenuser:tenuser /app/agents && \
|
| 181 |
-
chown -R tenuser:tenuser /app/server && \
|
| 182 |
find /app -type d -exec chmod 777 {} \; && \
|
| 183 |
find /app -type f -exec chmod 666 {} \; && \
|
| 184 |
chmod +x /app/server/bin/api
|
|
|
|
| 62 |
mkdir -p /tmp/ten_agent && \
|
| 63 |
mkdir -p /app/.pnpm-store && \
|
| 64 |
mkdir -p /app/backup && \
|
| 65 |
+
mkdir -p /app/mock-api && \
|
| 66 |
chown -R tenuser:tenuser /app && \
|
| 67 |
chown -R tenuser:tenuser /tmp/ten_agent
|
| 68 |
|
|
|
|
| 70 |
COPY .env /app/.env
|
| 71 |
RUN chown tenuser:tenuser /app/.env
|
| 72 |
|
| 73 |
+
# Создаем файл для мок-API дизайнера
|
| 74 |
+
RUN echo '{\n "success": true,\n "packages": [\n {\n "name": "default",\n "description": "Default package",\n "graphs": [\n {\n "name": "Voice Agent",\n "description": "Voice Agent with OpenAI",\n "file": "voice_agent.json",\n "id": "voice_agent",\n "package": "default"\n },\n {\n "name": "Chat Agent",\n "description": "Chat Agent",\n "file": "chat_agent.json",\n "id": "chat_agent",\n "package": "default"\n }\n ]\n }\n ]\n}' > /app/mock-api/designer-packages.json
|
|
|
|
| 75 |
|
| 76 |
+
# Настраиваем прокси-правила в Next.js для перенаправления запросов к дизайнеру на обычный API
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
RUN echo 'module.exports = { \
|
| 78 |
async rewrites() { \
|
| 79 |
return [ \
|
| 80 |
{ \
|
| 81 |
source: "/api/designer/:path*", \
|
| 82 |
+
destination: "http://localhost:8080/api/agents/:path*", \
|
| 83 |
}, \
|
| 84 |
{ \
|
| 85 |
source: "/api/dev/:path*", \
|
| 86 |
+
destination: "http://localhost:8080/api/agents/:path*", \
|
| 87 |
}, \
|
| 88 |
]; \
|
| 89 |
}, \
|
| 90 |
};' > /app/playground/next.config.js
|
| 91 |
|
|
|
|
|
|
|
|
|
|
| 92 |
# Компилируем сервер
|
| 93 |
RUN cd /app/server && \
|
| 94 |
go mod tidy && \
|
|
|
|
| 102 |
RUN cd /app/playground && \
|
| 103 |
pnpm install
|
| 104 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 105 |
# Создаем базовый manifest.json
|
| 106 |
RUN echo '{\n\
|
| 107 |
"name": "default",\n\
|
|
|
|
| 157 |
|
| 158 |
# Устанавливаем правильные права доступа для всех файлов
|
| 159 |
RUN chmod -R 777 /app && \
|
|
|
|
|
|
|
| 160 |
find /app -type d -exec chmod 777 {} \; && \
|
| 161 |
find /app -type f -exec chmod 666 {} \; && \
|
| 162 |
chmod +x /app/server/bin/api
|
app.py
CHANGED
|
@@ -17,6 +17,7 @@ import socketserver
|
|
| 17 |
import requests
|
| 18 |
from threading import Thread
|
| 19 |
from http import HTTPStatus
|
|
|
|
| 20 |
|
| 21 |
# Настройка логирования
|
| 22 |
logging.basicConfig(level=logging.INFO,
|
|
@@ -34,6 +35,51 @@ CHAT_AGENT_JSON = AGENTS_DIR / "chat_agent.json"
|
|
| 34 |
API_BINARY = Path("/app/server/bin/api")
|
| 35 |
PLAYGROUND_DIR = Path("/app/playground")
|
| 36 |
BACKUP_DIR = Path("/app/backup")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
class ProxyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
|
| 39 |
"""HTTP-прокси для отладки и исправления запросов между UI и API"""
|
|
@@ -198,6 +244,46 @@ class ProxyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
|
|
| 198 |
"""Переопределение логирования"""
|
| 199 |
logger.debug(f"PROXY: {self.address_string()} - {format % args}")
|
| 200 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 201 |
def run_proxy_server(port=9090):
|
| 202 |
"""Запуск прокси-сервера"""
|
| 203 |
try:
|
|
@@ -234,48 +320,40 @@ def backup_file(filepath):
|
|
| 234 |
except Exception as e:
|
| 235 |
logger.error(f"Ошибка при создании резервной копии {filepath}: {e}")
|
| 236 |
|
| 237 |
-
def
|
| 238 |
-
"""Проверяет
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
temp_path = temp_file.name
|
| 269 |
-
|
| 270 |
-
# Копируем временный файл в целевой
|
| 271 |
-
try:
|
| 272 |
-
shutil.copy2(temp_path, PROPERTY_JSON)
|
| 273 |
-
os.chmod(PROPERTY_JSON, 0o666) # Устанавливаем права доступа rw-rw-rw-
|
| 274 |
logger.info(f"Файл {PROPERTY_JSON} создан успешно")
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
finally:
|
| 278 |
-
os.unlink(temp_path) # Удаляем временный файл
|
| 279 |
|
| 280 |
def check_and_create_agent_files():
|
| 281 |
"""Проверяет наличие всех необходимых файлов агентов и создает их при необходимости"""
|
|
@@ -389,7 +467,7 @@ def test_api():
|
|
| 389 |
if len(json_data) == 0:
|
| 390 |
logger.warning("API вернул пустой список графов, исправляем property.json")
|
| 391 |
backup_file(PROPERTY_JSON)
|
| 392 |
-
|
| 393 |
check_and_create_agent_files()
|
| 394 |
ensure_directory_permissions(AGENTS_DIR)
|
| 395 |
# Перезапускаем API сервер
|
|
@@ -406,9 +484,21 @@ def test_api():
|
|
| 406 |
except Exception as e:
|
| 407 |
logger.error(f"Неизвестная ошибка при запросе к API: {e}")
|
| 408 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 409 |
def main():
|
| 410 |
processes = []
|
| 411 |
try:
|
|
|
|
|
|
|
|
|
|
| 412 |
# Проверяем существование файлов
|
| 413 |
if not API_BINARY.exists():
|
| 414 |
logger.error(f"API binary не найден: {API_BINARY}")
|
|
@@ -423,7 +513,7 @@ def main():
|
|
| 423 |
ensure_directory_permissions(BACKUP_DIR)
|
| 424 |
|
| 425 |
# Проверяем и создаем property.json
|
| 426 |
-
|
| 427 |
|
| 428 |
# Проверяем и создаем файлы агентов
|
| 429 |
check_and_create_agent_files()
|
|
@@ -431,6 +521,12 @@ def main():
|
|
| 431 |
# Проверка файлов перед запуском
|
| 432 |
check_files()
|
| 433 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 434 |
# Запускаем API сервер
|
| 435 |
logger.info("Запуск TEN-Agent API сервера на порту 8080...")
|
| 436 |
api_process = subprocess.Popen([str(API_BINARY)])
|
|
@@ -454,10 +550,10 @@ def main():
|
|
| 454 |
os.environ["NEXT_PUBLIC_EDIT_GRAPH_MODE"] = "true" # Включаем расширенный режим редактирования
|
| 455 |
os.environ["NEXT_PUBLIC_DISABLE_CAMERA"] = "true" # Отключаем запрос на использование камеры
|
| 456 |
|
| 457 |
-
#
|
| 458 |
-
os.environ["NEXT_PUBLIC_DEV_MODE"] = "
|
| 459 |
-
os.environ["NEXT_PUBLIC_API_BASE_URL"] =
|
| 460 |
-
os.environ["NEXT_PUBLIC_DESIGNER_API_URL"] = f"http://localhost:{
|
| 461 |
|
| 462 |
# Запускаем Playground UI
|
| 463 |
playground_process = subprocess.Popen(
|
|
|
|
| 17 |
import requests
|
| 18 |
from threading import Thread
|
| 19 |
from http import HTTPStatus
|
| 20 |
+
from typing import Dict, Any, Optional
|
| 21 |
|
| 22 |
# Настройка логирования
|
| 23 |
logging.basicConfig(level=logging.INFO,
|
|
|
|
| 35 |
API_BINARY = Path("/app/server/bin/api")
|
| 36 |
PLAYGROUND_DIR = Path("/app/playground")
|
| 37 |
BACKUP_DIR = Path("/app/backup")
|
| 38 |
+
MOCK_API_DIR = Path("/app/mock-api")
|
| 39 |
+
|
| 40 |
+
# Загружаем мок-ответы для дизайнера
|
| 41 |
+
DESIGNER_PACKAGES_JSON = MOCK_API_DIR / "designer-packages.json"
|
| 42 |
+
|
| 43 |
+
# Мок-данные для ответов дизайнера
|
| 44 |
+
mock_responses = {}
|
| 45 |
+
|
| 46 |
+
def load_mock_responses():
|
| 47 |
+
"""Загружает предварительно созданные мок-ответы"""
|
| 48 |
+
global mock_responses
|
| 49 |
+
|
| 50 |
+
try:
|
| 51 |
+
if DESIGNER_PACKAGES_JSON.exists():
|
| 52 |
+
with open(DESIGNER_PACKAGES_JSON, 'r') as f:
|
| 53 |
+
mock_responses['packages'] = json.load(f)
|
| 54 |
+
logger.info(f"Загружен мок-ответ для дизайнера: {mock_responses['packages']}")
|
| 55 |
+
except Exception as e:
|
| 56 |
+
logger.error(f"Ошибка при загрузке мок-ответов: {e}")
|
| 57 |
+
# Создаём запасной ответ
|
| 58 |
+
mock_responses['packages'] = {
|
| 59 |
+
"success": True,
|
| 60 |
+
"packages": [
|
| 61 |
+
{
|
| 62 |
+
"name": "default",
|
| 63 |
+
"description": "Default package",
|
| 64 |
+
"graphs": [
|
| 65 |
+
{
|
| 66 |
+
"name": "Voice Agent",
|
| 67 |
+
"description": "Voice Agent with OpenAI",
|
| 68 |
+
"file": "voice_agent.json",
|
| 69 |
+
"id": "voice_agent",
|
| 70 |
+
"package": "default"
|
| 71 |
+
},
|
| 72 |
+
{
|
| 73 |
+
"name": "Chat Agent",
|
| 74 |
+
"description": "Chat Agent",
|
| 75 |
+
"file": "chat_agent.json",
|
| 76 |
+
"id": "chat_agent",
|
| 77 |
+
"package": "default"
|
| 78 |
+
}
|
| 79 |
+
]
|
| 80 |
+
}
|
| 81 |
+
]
|
| 82 |
+
}
|
| 83 |
|
| 84 |
class ProxyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
|
| 85 |
"""HTTP-прокси для отладки и исправления запросов между UI и API"""
|
|
|
|
| 244 |
"""Переопределение логирования"""
|
| 245 |
logger.debug(f"PROXY: {self.address_string()} - {format % args}")
|
| 246 |
|
| 247 |
+
class MockDesignerAPIHandler(http.server.BaseHTTPRequestHandler):
|
| 248 |
+
"""Обработчик для мок-API дизайнера"""
|
| 249 |
+
|
| 250 |
+
def do_GET(self):
|
| 251 |
+
"""Обработка GET запросов"""
|
| 252 |
+
logger.info(f"MOCK API: GET запрос: {self.path}")
|
| 253 |
+
|
| 254 |
+
if self.path == "/api/designer/v1/packages" or self.path == "/api/dev/v1/packages":
|
| 255 |
+
self._send_designer_packages()
|
| 256 |
+
elif self.path.startswith("/api/designer/v1/") or self.path.startswith("/api/dev/v1/"):
|
| 257 |
+
self._send_success_response({"success": True})
|
| 258 |
+
else:
|
| 259 |
+
self.send_error(404, "Endpoint not found")
|
| 260 |
+
|
| 261 |
+
def do_POST(self):
|
| 262 |
+
"""Обработка POST запросов"""
|
| 263 |
+
logger.info(f"MOCK API: POST запрос: {self.path}")
|
| 264 |
+
|
| 265 |
+
if self.path == "/api/designer/v1/packages/reload" or self.path == "/api/dev/v1/packages/reload":
|
| 266 |
+
self._send_designer_packages()
|
| 267 |
+
elif self.path.startswith("/api/designer/v1/") or self.path.startswith("/api/dev/v1/"):
|
| 268 |
+
self._send_success_response({"success": True})
|
| 269 |
+
else:
|
| 270 |
+
self.send_error(404, "Endpoint not found")
|
| 271 |
+
|
| 272 |
+
def _send_designer_packages(self):
|
| 273 |
+
"""Отправляет информацию о пакетах и графах"""
|
| 274 |
+
self._send_success_response(mock_responses['packages'])
|
| 275 |
+
|
| 276 |
+
def _send_success_response(self, data: Dict[str, Any]):
|
| 277 |
+
"""Отправляет успешный ответ с данными"""
|
| 278 |
+
self.send_response(200)
|
| 279 |
+
self.send_header('Content-Type', 'application/json')
|
| 280 |
+
self.end_headers()
|
| 281 |
+
self.wfile.write(json.dumps(data).encode('utf-8'))
|
| 282 |
+
|
| 283 |
+
def log_message(self, format, *args):
|
| 284 |
+
"""Настраиваем логирование для сервера"""
|
| 285 |
+
logger.debug(f"MOCK API: {self.address_string()} - {format % args}")
|
| 286 |
+
|
| 287 |
def run_proxy_server(port=9090):
|
| 288 |
"""Запуск прокси-сервера"""
|
| 289 |
try:
|
|
|
|
| 320 |
except Exception as e:
|
| 321 |
logger.error(f"Ошибка при создании резервной копии {filepath}: {e}")
|
| 322 |
|
| 323 |
+
def ensure_property_json():
|
| 324 |
+
"""Проверяет и создает property.json при необходимости"""
|
| 325 |
+
try:
|
| 326 |
+
if not PROPERTY_JSON.exists():
|
| 327 |
+
logger.warning(f"{PROPERTY_JSON} не найден, создаем файл...")
|
| 328 |
+
|
| 329 |
+
property_data = {
|
| 330 |
+
"_ten": {},
|
| 331 |
+
"name": "TEN Agent Example",
|
| 332 |
+
"version": "0.0.1",
|
| 333 |
+
"extensions": ["openai_chatgpt"],
|
| 334 |
+
"description": "A basic voice agent with OpenAI",
|
| 335 |
+
"graphs": [
|
| 336 |
+
{
|
| 337 |
+
"name": "Voice Agent",
|
| 338 |
+
"description": "Basic voice agent with OpenAI",
|
| 339 |
+
"file": "voice_agent.json"
|
| 340 |
+
},
|
| 341 |
+
{
|
| 342 |
+
"name": "Chat Agent",
|
| 343 |
+
"description": "Simple chat agent",
|
| 344 |
+
"file": "chat_agent.json"
|
| 345 |
+
}
|
| 346 |
+
]
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
PROPERTY_JSON.parent.mkdir(parents=True, exist_ok=True)
|
| 350 |
+
|
| 351 |
+
with open(PROPERTY_JSON, 'w') as f:
|
| 352 |
+
json.dump(property_data, f, indent=2)
|
| 353 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 354 |
logger.info(f"Файл {PROPERTY_JSON} создан успешно")
|
| 355 |
+
except Exception as e:
|
| 356 |
+
logger.error(f"Ошибка при создании {PROPERTY_JSON}: {e}")
|
|
|
|
|
|
|
| 357 |
|
| 358 |
def check_and_create_agent_files():
|
| 359 |
"""Проверяет наличие всех необходимых файлов агентов и создает их при необходимости"""
|
|
|
|
| 467 |
if len(json_data) == 0:
|
| 468 |
logger.warning("API вернул пустой список графов, исправляем property.json")
|
| 469 |
backup_file(PROPERTY_JSON)
|
| 470 |
+
ensure_property_json()
|
| 471 |
check_and_create_agent_files()
|
| 472 |
ensure_directory_permissions(AGENTS_DIR)
|
| 473 |
# Перезапускаем API сервер
|
|
|
|
| 484 |
except Exception as e:
|
| 485 |
logger.error(f"Неизвестная ошибка при запросе к API: {e}")
|
| 486 |
|
| 487 |
+
def run_mock_api_server(port=8090):
|
| 488 |
+
"""Запускает мок-сервер для API дизайнера"""
|
| 489 |
+
try:
|
| 490 |
+
with socketserver.TCPServer(("", port), MockDesignerAPIHandler) as httpd:
|
| 491 |
+
logger.info(f"Запуск мок-API сервера на порту {port}")
|
| 492 |
+
httpd.serve_forever()
|
| 493 |
+
except Exception as e:
|
| 494 |
+
logger.error(f"Ошибка при запуске мок-API сервера: {e}")
|
| 495 |
+
|
| 496 |
def main():
|
| 497 |
processes = []
|
| 498 |
try:
|
| 499 |
+
# Загружаем мок-ответы
|
| 500 |
+
load_mock_responses()
|
| 501 |
+
|
| 502 |
# Проверяем существование файлов
|
| 503 |
if not API_BINARY.exists():
|
| 504 |
logger.error(f"API binary не найден: {API_BINARY}")
|
|
|
|
| 513 |
ensure_directory_permissions(BACKUP_DIR)
|
| 514 |
|
| 515 |
# Проверяем и создаем property.json
|
| 516 |
+
ensure_property_json()
|
| 517 |
|
| 518 |
# Проверяем и создаем файлы агентов
|
| 519 |
check_and_create_agent_files()
|
|
|
|
| 521 |
# Проверка файлов перед запуском
|
| 522 |
check_files()
|
| 523 |
|
| 524 |
+
# Запускаем мок-сервер для API дизайнера
|
| 525 |
+
mock_api_port = 8090
|
| 526 |
+
mock_api_thread = threading.Thread(target=run_mock_api_server, args=(mock_api_port,))
|
| 527 |
+
mock_api_thread.daemon = True
|
| 528 |
+
mock_api_thread.start()
|
| 529 |
+
|
| 530 |
# Запускаем API сервер
|
| 531 |
logger.info("Запуск TEN-Agent API сервера на порту 8080...")
|
| 532 |
api_process = subprocess.Popen([str(API_BINARY)])
|
|
|
|
| 550 |
os.environ["NEXT_PUBLIC_EDIT_GRAPH_MODE"] = "true" # Включаем расширенный режим редактирования
|
| 551 |
os.environ["NEXT_PUBLIC_DISABLE_CAMERA"] = "true" # Отключаем запрос на использование камеры
|
| 552 |
|
| 553 |
+
# Настраиваем переменные для дизайнера
|
| 554 |
+
os.environ["NEXT_PUBLIC_DEV_MODE"] = "true" # Включаем режим разработчика
|
| 555 |
+
os.environ["NEXT_PUBLIC_API_BASE_URL"] = "/api/agents"
|
| 556 |
+
os.environ["NEXT_PUBLIC_DESIGNER_API_URL"] = f"http://localhost:{mock_api_port}"
|
| 557 |
|
| 558 |
# Запускаем Playground UI
|
| 559 |
playground_process = subprocess.Popen(
|