|
|
|
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_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 = { |
|
"_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_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 = { |
|
"_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 = 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" |
|
|
|
|
|
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 |
|
|
|
|
|
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" |
|
env["GOPATH"] = "/tmp/go-path" |
|
|
|
|
|
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) |
|
|
|
|
|
if not copy_api_server(server_bin_dir): |
|
print("Critical error: Cannot prepare API server") |
|
sys.exit(1) |
|
|
|
|
|
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" |
|
os.environ["AGENT_SERVER_URL"] = "http://localhost:8080" |
|
os.environ["NEXT_PUBLIC_EDIT_GRAPH_MODE"] = "true" |
|
os.environ["NEXT_PUBLIC_DISABLE_CAMERA"] = "true" |
|
|
|
|
|
api_bin_str = str(api_bin) |
|
|
|
|
|
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) |
|
|
|
|
|
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')}") |
|
|
|
|
|
subprocess.run(["ls", "-la", api_bin_str], check=True) |
|
|
|
|
|
subprocess.run(["ls", "-la", str(logs_dir)], check=True) |
|
|
|
|
|
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) |
|
|
|
|
|
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") |
|
|
|
|
|
print("Starting Playground UI...") |
|
playground_process = subprocess.Popen( |
|
"cd /app/playground && pnpm dev", |
|
env=os.environ, |
|
shell=True, |
|
stdout=subprocess.PIPE, |
|
stderr=subprocess.PIPE |
|
) |
|
|
|
|
|
time.sleep(5) |
|
|
|
|
|
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_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()}") |
|
|
|
|
|
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() |