#!/usr/bin/env python3 import os import json import subprocess import sys import time import shutil from pathlib import Path def create_user_directory(): """Создает отдельную директорию для пользовательских файлов""" print("Creating user directory...") # Создаем пользовательскую директорию user_dir = Path("/tmp/ten_user") user_dir.mkdir(exist_ok=True, parents=True) # Создаем структуру директорий agents_dir = user_dir / "agents" agents_dir.mkdir(exist_ok=True, parents=True) server_bin_dir = user_dir / "server" / "bin" server_bin_dir.mkdir(exist_ok=True, parents=True) # Создаем директорию для логов logs_dir = user_dir / "logs" logs_dir.mkdir(exist_ok=True, parents=True) # Создаем директорию для кэша Go go_cache_dir = Path("/tmp/go-cache") go_cache_dir.mkdir(exist_ok=True, parents=True) print(f"Created directory structure at {user_dir}") return user_dir, agents_dir, server_bin_dir, logs_dir, go_cache_dir def create_basic_files(agents_dir): """Создает базовые файлы конфигурации для TEN-Agent""" print("Creating basic configuration files...") # Создаем manifest.json manifest = { "_ten": {"version": "0.0.1"}, "name": "default", "agents": [ { "name": "voice_agent", "description": "A simple voice agent", "type": "voice" }, { "name": "chat_agent", "description": "A text chat agent", "type": "chat" } ] } with open(agents_dir / "manifest.json", "w") as f: json.dump(manifest, f, indent=2) # Создаем property.json property_data = { "name": "TEN Agent Example", "version": "0.0.1", "extensions": ["openai_chatgpt"], "description": "A basic voice agent with OpenAI", "graphs": [ { "name": "Voice Agent", "description": "Basic voice agent with OpenAI", "file": "voice_agent.json" }, { "name": "Chat Agent", "description": "Simple chat agent", "file": "chat_agent.json" } ] } with open(agents_dir / "property.json", "w") as f: json.dump(property_data, f, indent=2) # Создаем voice_agent.json voice_agent = { "_ten": {"version": "0.0.1"}, "nodes": [ { "id": "start", "type": "start", "data": {"x": 100, "y": 100} }, { "id": "openai_chatgpt", "type": "openai_chatgpt", "data": { "x": 300, "y": 200, "properties": { "model": "gpt-3.5-turbo", "temperature": 0.7, "system_prompt": "You are a helpful assistant." } } }, { "id": "end", "type": "end", "data": {"x": 500, "y": 100} } ], "edges": [ { "id": "start_to_chatgpt", "source": "start", "target": "openai_chatgpt" }, { "id": "chatgpt_to_end", "source": "openai_chatgpt", "target": "end" } ], "groups": [], "templates": [], "root": "start" } with open(agents_dir / "voice_agent.json", "w") as f: json.dump(voice_agent, f, indent=2) # Создаем chat_agent.json (аналогичный voice_agent.json) chat_agent = dict(voice_agent) chat_agent["nodes"][1]["data"]["properties"]["system_prompt"] = "You are a helpful chat assistant." with open(agents_dir / "chat_agent.json", "w") as f: json.dump(chat_agent, f, indent=2) print("Basic configuration files created successfully.") def copy_api_server(server_bin_dir): """Копирует предварительно скомпилированный API сервер""" api_bin = server_bin_dir / "api" # Приоритезируем API сервер из директории fallback fallback_bin = Path("/app/fallback/api") if fallback_bin.exists(): print(f"Found pre-compiled API server at {fallback_bin}") shutil.copy(fallback_bin, api_bin) api_bin.chmod(0o755) # Делаем исполняемым print(f"API server binary copied to {api_bin}") return True # Ищем API сервер в основной директории original_bin = Path("/app/server/bin/api") if original_bin.exists(): print(f"Found API server at {original_bin}") shutil.copy(original_bin, api_bin) api_bin.chmod(0o755) # Делаем исполняемым print(f"API server binary copied to {api_bin}") return True # Если не нашли готовый бинарник, пытаемся компилировать try: print("No pre-compiled API server found, trying to compile from source...") env = os.environ.copy() env["GOCACHE"] = "/tmp/go-cache" # Указываем директорию для кэша Go env["GOPATH"] = "/tmp/go-path" # Указываем пользовательский GOPATH # Создаем директорию для GOPATH Path("/tmp/go-path").mkdir(exist_ok=True, parents=True) # Компилируем с пользовательскими настройками result = subprocess.run( "cd /app/server && go build -o /tmp/ten_user/server/bin/api main.go", shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env ) print(f"Successfully compiled API server: {result.stdout.decode()}") api_bin.chmod(0o755) return True except subprocess.CalledProcessError as e: print(f"Failed to compile API server: {e.stderr.decode()}") print("Critical error: No API server available!") return False def main(): try: print(f"Starting TEN-Agent in fallback mode...") print(f"Current directory: {os.getcwd()}") # Выводим информацию о среде user = os.environ.get('USER', 'unknown') print(f"Current user: {user}") print(f"HOME: {os.environ.get('HOME', 'unset')}") print(f"PATH: {os.environ.get('PATH', 'unset')}") # Создаем пользовательские директории user_dir, agents_dir, server_bin_dir, logs_dir, go_cache_dir = create_user_directory() # Создаем пустой файл в директории логов, чтобы точно создать директорию (logs_dir / "server.log").touch() print(f"Created log directory at {logs_dir}") # Создаем базовые конфигурационные файлы create_basic_files(agents_dir) # Копируем API сервер if not copy_api_server(server_bin_dir): print("Critical error: Cannot prepare API server") sys.exit(1) # Проверяем, что API сервер действительно скопирован и исполняемый api_bin = server_bin_dir / "api" if not api_bin.exists(): print(f"Critical error: API server binary not found at {api_bin}") sys.exit(1) try: api_bin.chmod(0o755) # Дополнительно проверяем права except Exception as e: print(f"Warning: Could not set execute permissions on API server binary: {e}") # Продолжаем, возможно, права уже установлены print(f"API server binary prepared successfully: {api_bin}") print(f"File exists: {api_bin.exists()}, size: {api_bin.stat().st_size} bytes") # Установка переменных среды os.environ["PORT"] = "7860" # HuggingFace использует порт 7860 os.environ["AGENT_SERVER_URL"] = "http://localhost:8080" os.environ["NEXT_PUBLIC_EDIT_GRAPH_MODE"] = "true" os.environ["NEXT_PUBLIC_DISABLE_CAMERA"] = "true" # Путь к бинарнику API сервера api_bin_str = str(api_bin) # Запускаем API сервер с указанием пути к agents директории print(f"Starting API server with agents directory: {agents_dir}") api_env = os.environ.copy() api_env["TEN_AGENT_DIR"] = str(agents_dir) api_env["GOCACHE"] = str(go_cache_dir) # Устанавливаем переменную GOCACHE # Отключаем логирование в файл api_env["GF_LOG_MODE"] = "console" # Логирование только в консоль api_env["LOG_LEVEL"] = "error" # Минимальный уровень логирования api_env["TEN_LOG_DISABLE_FILE"] = "true" # Отключаем логирование в файл (кастомная переменная) api_env["GF_LOG_FILE_STAT"] = "false" # Отключаем статистику файлов логов # Выводим важные переменные окружения print(f"Environment variables:") print(f"TEN_AGENT_DIR: {api_env.get('TEN_AGENT_DIR')}") print(f"GF_LOG_MODE: {api_env.get('GF_LOG_MODE')}") print(f"LOG_LEVEL: {api_env.get('LOG_LEVEL')}") print(f"TEN_LOG_DISABLE_FILE: {api_env.get('TEN_LOG_DISABLE_FILE')}") print(f"GOCACHE: {api_env.get('GOCACHE')}") # Дополнительно проверяем права на исполнение через ls -la subprocess.run(["ls", "-la", api_bin_str], check=True) # Проверяем директорию логов subprocess.run(["ls", "-la", str(logs_dir)], check=True) # Запускаем API сервер с передачей аргумента для отключения файлового логирования print(f"Executing API server: {api_bin_str}") try: api_process = subprocess.Popen( [api_bin_str, "--log_to_stdout", "--disable_file_logging"], env=api_env, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) except Exception as e: print(f"Failed to start API server: {e}") sys.exit(1) # Даем серверу время для запуска и выводим любые ошибки сразу time.sleep(2) # Проверяем, запустился ли сервер if api_process.poll() is not None: print("API server failed to start!") stdout, stderr = api_process.communicate() print(f"STDOUT: {stdout.decode()}") print(f"STDERR: {stderr.decode()}") sys.exit(1) # Проверяем доступность API print("Testing API server availability...") try: import urllib.request response = urllib.request.urlopen("http://localhost:8080/graphs") print(f"API server is responding! Response: {response.read().decode()}") except Exception as e: print(f"API server is not responding yet, but continuing... ({e})") print("API server started successfully") # Запускаем playground print("Starting Playground UI...") playground_process = subprocess.Popen( "cd /app/playground && pnpm dev", env=os.environ, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # Даем UI время для запуска time.sleep(5) # Проверяем, запустился ли UI if playground_process.poll() is not None: print("Playground UI failed to start!") stdout, stderr = playground_process.communicate() print(f"STDOUT: {stdout.decode()}") print(f"STDERR: {stderr.decode()}") # Останавливаем API сервер api_process.terminate() sys.exit(1) print("TEN-Agent started successfully in fallback mode.") print("Playground UI is available at http://localhost:7860") # Следим за выводом процессов в реальном времени def stream_output(process, name): for line in iter(process.stdout.readline, b''): print(f"[{name}] {line.decode().strip()}") # После завершения стандартного вывода, читаем stderr for line in iter(process.stderr.readline, b''): print(f"[{name} ERROR] {line.decode().strip()}") api_thread = threading.Thread(target=stream_output, args=(api_process, "API")) ui_thread = threading.Thread(target=stream_output, args=(playground_process, "UI")) api_thread.daemon = True ui_thread.daemon = True api_thread.start() ui_thread.start() # Ожидаем завершения любого из процессов while True: if api_process.poll() is not None: print("API server has stopped.") playground_process.terminate() break if playground_process.poll() is not None: print("Playground UI has stopped.") api_process.terminate() break time.sleep(1) except Exception as e: print(f"Error: {e}") sys.exit(1) if __name__ == "__main__": import threading main()