Полное изменение подхода: создание отдельного мок-сервера для 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(
|