3v324v23 commited on
Commit
942b4ab
·
1 Parent(s): dae7932

Новая версия fallback.py без изменения прав доступа для работы на Hugging Face Space

Browse files
Files changed (1) hide show
  1. fallback.py +550 -303
fallback.py CHANGED
@@ -1,338 +1,585 @@
1
  #!/usr/bin/env python3
2
  import os
3
- import json
4
- import subprocess
5
  import sys
 
6
  import time
7
  import shutil
 
 
 
8
  from pathlib import Path
 
9
  import threading
10
- import urllib.request
11
- import urllib.error
12
 
13
- def create_user_directory():
14
- """Создает отдельную директорию для пользовательских файлов"""
15
- print("Creating user directory...")
16
-
17
- # Создаем пользовательскую директорию
18
- user_dir = Path("/tmp/ten_user")
19
- user_dir.mkdir(exist_ok=True, parents=True)
20
-
21
- # Создаем структуру директорий
22
- agents_dir = user_dir / "agents"
23
- agents_dir.mkdir(exist_ok=True, parents=True)
24
- server_bin_dir = user_dir / "server" / "bin"
25
- server_bin_dir.mkdir(exist_ok=True, parents=True)
26
-
27
- # Создаем директорию для логов
28
- logs_dir = user_dir / "logs"
29
- logs_dir.mkdir(exist_ok=True, parents=True)
30
-
31
- # Создаем директорию для кэша Go
32
- go_cache_dir = Path("/tmp/go-cache")
33
- go_cache_dir.mkdir(exist_ok=True, parents=True)
34
-
35
- # Создаем директорию для RAG данных
36
- rag_dir = user_dir / "rag_data"
37
- rag_dir.mkdir(exist_ok=True, parents=True)
38
-
39
- print(f"Created directory structure at {user_dir}")
40
- return user_dir, agents_dir, server_bin_dir, logs_dir, go_cache_dir, rag_dir
41
 
42
- def create_basic_files(agents_dir):
43
- """Создает базовые файлы конфигурации для TEN-Agent"""
44
- print("Creating basic configuration files...")
45
-
46
- # Создаем manifest.json
47
- manifest = {
48
- "_ten": {"version": "0.0.1"},
49
- "name": "default",
50
- "agents": [
51
- {
52
- "name": "voice_agent",
53
- "description": "A simple voice agent",
54
- "type": "voice"
55
- },
56
- {
57
- "name": "chat_agent",
58
- "description": "A text chat agent",
59
- "type": "chat"
60
- }
61
- ]
62
- }
63
-
64
- with open(agents_dir / "manifest.json", "w") as f:
65
- json.dump(manifest, f, indent=2)
66
-
67
- # Создаем property.json
68
- property_data = {
69
- "name": "TEN Agent Example",
70
- "version": "0.0.1",
71
- "extensions": ["openai_chatgpt"],
72
- "description": "A basic voice agent with OpenAI",
73
- "graphs": [
74
- {
75
- "name": "Voice Agent",
76
- "description": "Basic voice agent with OpenAI",
77
- "file": "voice_agent.json"
78
- },
79
- {
80
- "name": "Chat Agent",
81
- "description": "Simple chat agent",
82
- "file": "chat_agent.json"
83
- }
84
- ]
85
- }
86
-
87
- with open(agents_dir / "property.json", "w") as f:
88
- json.dump(property_data, f, indent=2)
89
-
90
- # Создаем voice_agent.json
91
- voice_agent = {
92
- "_ten": {"version": "0.0.1"},
93
- "nodes": [
94
- {
95
- "id": "start",
96
- "type": "start",
97
- "data": {"x": 100, "y": 100}
98
- },
99
- {
100
- "id": "openai_chatgpt",
101
- "type": "openai_chatgpt",
102
- "data": {
103
- "x": 300,
104
- "y": 200,
105
- "properties": {
106
- "model": "gpt-3.5-turbo",
107
- "temperature": 0.7,
108
- "system_prompt": "You are a helpful assistant."
109
- }
110
- }
111
- },
112
- {
113
- "id": "end",
114
- "type": "end",
115
- "data": {"x": 500, "y": 100}
116
- }
117
- ],
118
- "edges": [
119
- {
120
- "id": "start_to_chatgpt",
121
- "source": "start",
122
- "target": "openai_chatgpt"
123
- },
124
- {
125
- "id": "chatgpt_to_end",
126
- "source": "openai_chatgpt",
127
- "target": "end"
128
- }
129
- ],
130
- "groups": [],
131
- "templates": [],
132
- "root": "start"
133
- }
134
-
135
- with open(agents_dir / "voice_agent.json", "w") as f:
136
- json.dump(voice_agent, f, indent=2)
137
-
138
- # Создаем chat_agent.json (аналогичный voice_agent.json)
139
- chat_agent = dict(voice_agent)
140
- chat_agent["nodes"][1]["data"]["properties"]["system_prompt"] = "You are a helpful chat assistant."
141
-
142
- with open(agents_dir / "chat_agent.json", "w") as f:
143
- json.dump(chat_agent, f, indent=2)
144
-
145
- print("Basic configuration files created successfully.")
146
 
147
- def check_file_permissions(filepath):
148
- """Проверяет и выводит права доступа для файла"""
 
 
 
 
 
 
 
 
 
149
  try:
150
- print(f"Checking permissions for {filepath}")
151
- if not Path(filepath).exists():
152
- print(f" - File does not exist!")
153
- return
154
 
155
- # Получаем права доступа и информацию о файле
156
- result = subprocess.run(["ls", "-la", filepath], capture_output=True, text=True)
157
- if result.returncode == 0:
158
- print(f" - {result.stdout.strip()}")
159
- else:
160
- print(f" - Error: {result.stderr.strip()}")
161
-
162
- # Проверяем, можем ли писать в файл
163
  try:
164
- with open(filepath, "a") as f:
165
- pass
166
- print(" - Can write: Yes")
167
- except PermissionError:
168
- print(" - Can write: No (Permission denied)")
169
  except Exception as e:
170
- print(f" - Can write: No ({e})")
 
 
 
 
171
  except Exception as e:
172
- print(f"Error checking permissions: {e}")
173
 
174
- def test_api_connection(max_attempts=5):
175
- """Проверяет, доступен ли API сервер"""
176
- print("\nTesting API server connection...")
177
- for attempt in range(max_attempts):
178
- try:
179
- with urllib.request.urlopen("http://localhost:8080/health") as response:
180
- if response.status == 200:
181
- print(f"✅ API server is working! Response: {response.read().decode()}")
182
- return True
183
- else:
184
- print(f"❌ API server responded with status {response.status}")
185
- except Exception as e:
186
- print(f"❌ Attempt {attempt+1}/{max_attempts}: API server connection failed: {e}")
187
-
188
- if attempt < max_attempts - 1:
189
- print(f"Waiting 2 seconds before next attempt...")
190
- time.sleep(2)
191
 
192
- print("Could not connect to API server after multiple attempts")
193
- return False
 
 
 
 
 
 
 
194
 
195
- def main():
196
- try:
197
- print(f"Starting TEN-Agent in fallback mode...")
198
- print(f"Current directory: {os.getcwd()}")
199
-
200
- # Выводим информацию о среде
201
- user = os.environ.get('USER', 'unknown')
202
- print(f"Current user: {user}")
203
- print(f"HOME: {os.environ.get('HOME', 'unset')}")
204
- print(f"PATH: {os.environ.get('PATH', 'unset')}")
205
-
206
- # Проверяем наличие /tmp и права на него
207
- check_file_permissions("/tmp")
208
-
209
- # Создаем пользовательские директории
210
- user_dir, agents_dir, server_bin_dir, logs_dir, go_cache_dir, rag_dir = create_user_directory()
211
-
212
- # Создаем пустой файл в директории логов, чтобы точно создать директорию
213
- (logs_dir / "server.log").touch()
214
- print(f"Created log directory at {logs_dir}")
215
-
216
- # Создаем базовые конфи��урационные файлы
217
- create_basic_files(agents_dir)
218
-
219
- # Установка переменных среды для Playground
220
- os.environ["PORT"] = "7860" # HuggingFace использует порт 7860
221
- os.environ["AGENT_SERVER_URL"] = "http://localhost:8080"
222
- os.environ["NEXT_PUBLIC_EDIT_GRAPH_MODE"] = "true"
223
- os.environ["NEXT_PUBLIC_DISABLE_CAMERA"] = "true"
224
- os.environ["TEN_AGENT_DIR"] = str(agents_dir)
225
-
226
- # Запускаем API сервер с использованием нашей обертки
227
- print(f"Starting API server with agents directory: {agents_dir}")
228
- api_env = os.environ.copy()
229
- api_env["TEN_AGENT_DIR"] = str(agents_dir)
230
-
231
- # Проверяем наличие API wrapper
232
- wrapper_path = Path("/app/api_wrapper.py")
233
- if not wrapper_path.exists():
234
- print(f"Error: API wrapper not found at {wrapper_path}")
235
- sys.exit(1)
236
-
237
- # Убедимся, что у скрипта есть права на исполнение
238
- wrapper_path.chmod(0o755)
239
-
240
- # Запускаем API обертку
241
- print(f"Using Python API wrapper instead of original server")
242
- api_process = subprocess.Popen(
243
- ["python3", str(wrapper_path)],
244
- env=api_env,
245
- stdout=subprocess.PIPE,
246
- stderr=subprocess.PIPE
247
- )
248
 
249
- # Даем серверу время для запуска
250
- time.sleep(2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
 
252
- # Проверяем, запустился ли сервер
253
- if api_process.poll() is not None:
254
- print("API server failed to start!")
255
- stdout, stderr = api_process.communicate()
256
- print(f"STDOUT: {stdout.decode() if stdout else 'No output'}")
257
- print(f"STDERR: {stderr.decode() if stderr else 'No error output'}")
258
- sys.exit(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
 
260
- # Проверяем доступность API
261
- print("Testing API server availability...")
262
- api_success = test_api_connection()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
 
264
- if not api_success:
265
- print("WARNING: API server may not be working correctly!")
266
-
267
- # Запускаем playground
268
- print("Starting Playground UI...")
269
- playground_path = Path("/app/playground")
270
- if not playground_path.exists():
271
- print(f"Error: Playground directory not found at {playground_path}")
272
- sys.exit(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
 
274
- playground_process = subprocess.Popen(
275
- "cd /app/playground && pnpm dev",
276
- env=os.environ,
277
- shell=True,
278
- stdout=subprocess.PIPE,
279
- stderr=subprocess.PIPE
280
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
 
282
- # Даем UI время для запуска
283
- time.sleep(5)
284
-
285
- # Проверяем, запустился ли UI
286
- if playground_process.poll() is not None:
287
- print("Playground UI failed to start!")
288
- stdout, stderr = playground_process.communicate()
289
- print(f"STDOUT: {stdout.decode() if stdout else 'No output'}")
290
- print(f"STDERR: {stderr.decode() if stderr else 'No error output'}")
291
 
292
- # Останавливаем API сервер
293
- api_process.terminate()
294
- sys.exit(1)
295
-
296
- print("TEN-Agent started successfully in fallback mode.")
297
- print("Playground UI is available at http://localhost:7860")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
 
299
- # Следим за выводом процессов в реальном времени
300
- def stream_output(process, name):
301
- for line in iter(process.stdout.readline, b''):
302
- print(f"[{name}] {line.decode().strip()}")
303
-
304
- # После завершения стандартного вывода, читаем stderr
305
- for line in iter(process.stderr.readline, b''):
306
- print(f"[{name} ERROR] {line.decode().strip()}")
307
 
308
- api_thread = threading.Thread(target=stream_output, args=(api_process, "API"))
309
- ui_thread = threading.Thread(target=stream_output, args=(playground_process, "UI"))
310
 
311
- api_thread.daemon = True
312
- ui_thread.daemon = True
 
 
313
 
314
- api_thread.start()
315
- ui_thread.start()
316
 
317
- # Ожидаем завершения любого из процессов
318
- while True:
319
- if api_process.poll() is not None:
320
- print("API server has stopped.")
321
- playground_process.terminate()
322
- break
 
 
 
 
 
 
 
 
 
 
 
 
323
 
324
- if playground_process.poll() is not None:
325
- print("Playground UI has stopped.")
326
- api_process.terminate()
327
- break
 
 
328
 
329
- time.sleep(1)
330
-
 
 
 
 
 
 
 
 
 
 
331
  except Exception as e:
332
- print(f"Error: {e}")
333
- import traceback
334
- traceback.print_exc()
335
- sys.exit(1)
336
 
337
  if __name__ == "__main__":
338
- main()
 
 
 
 
 
 
1
  #!/usr/bin/env python3
2
  import os
 
 
3
  import sys
4
+ import json
5
  import time
6
  import shutil
7
+ import signal
8
+ import logging
9
+ import subprocess
10
  from pathlib import Path
11
+ import tempfile
12
  import threading
 
 
13
 
14
+ # Настройка логирования
15
+ logging.basicConfig(
16
+ level=logging.INFO,
17
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
18
+ handlers=[logging.StreamHandler()]
19
+ )
20
+ logger = logging.getLogger("TEN-Agent")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ # Пути к директориям
23
+ TMP_DIR = Path("/tmp/ten_user")
24
+ LOG_DIR = TMP_DIR / "logs"
25
+ AGENTS_DIR = TMP_DIR / "agents"
26
+ RAG_DIR = TMP_DIR / "rag_data"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ def setup_environment():
29
+ """Настройка базового окружения"""
30
+ logger.info("Current directory: %s", os.getcwd())
31
+ logger.info("Current user: %s", os.environ.get('USER', 'unknown'))
32
+
33
+ # Информация об окружении
34
+ logger.info("HOME: %s", os.environ.get('HOME', 'Not set'))
35
+ logger.info("PATH: %s", os.environ.get('PATH', 'Not set'))
36
+
37
+ # Проверка прав доступа во временной директории
38
+ logger.info("Checking permissions for %s", "/tmp")
39
  try:
40
+ result = subprocess.run(["ls", "-la", "/tmp"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
41
+ logger.info(" - %s", result.stdout.decode('utf-8').strip())
 
 
42
 
43
+ # Проверка возможности записи
44
+ test_file = "/tmp/ten_test_write.txt"
45
+ can_write = False
 
 
 
 
 
46
  try:
47
+ with open(test_file, 'w') as f:
48
+ f.write("Test write")
49
+ can_write = True
50
+ logger.info(" - Can write: Yes")
51
+ os.remove(test_file)
52
  except Exception as e:
53
+ logger.info(" - Can write: No (%s)", str(e))
54
+
55
+ if not can_write:
56
+ logger.error("Cannot write to /tmp. This is required for operation.")
57
+ sys.exit(1)
58
  except Exception as e:
59
+ logger.error("Error checking permissions: %s", str(e))
60
 
61
+ def create_directory_structure():
62
+ """Создание необходимой структуры директорий"""
63
+ logger.info("Creating user directory...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
+ # Создание основной директории
66
+ TMP_DIR.mkdir(exist_ok=True)
67
+ logger.info(f"Created directory structure at {TMP_DIR}")
68
+
69
+ # Создание поддиректорий
70
+ AGENTS_DIR.mkdir(exist_ok=True)
71
+ RAG_DIR.mkdir(exist_ok=True)
72
+ LOG_DIR.mkdir(exist_ok=True)
73
+ logger.info(f"Created log directory at {LOG_DIR}")
74
 
75
+ def create_basic_config():
76
+ """Создание базовых конфигурационных файлов"""
77
+ logger.info("Creating basic configuration files...")
78
+
79
+ # Создание property.json
80
+ property_path = AGENTS_DIR / "property.json"
81
+ if not property_path.exists():
82
+ property_data = {
83
+ "_ten": {
84
+ "version": "0.0.1"
85
+ },
86
+ "name": "TEN Agent Example",
87
+ "version": "0.0.1",
88
+ "extensions": ["openai_chatgpt"],
89
+ "description": "A basic voice agent with OpenAI",
90
+ "graphs": [
91
+ {
92
+ "id": "voice_agent",
93
+ "name": "Voice Agent",
94
+ "description": "Basic voice agent with OpenAI",
95
+ "file": "examples/voice_agent.json"
96
+ },
97
+ {
98
+ "id": "chat_agent",
99
+ "name": "Chat Agent",
100
+ "description": "Simple chat agent",
101
+ "file": "examples/chat_agent.json"
102
+ }
103
+ ]
104
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
+ with open(property_path, 'w') as f:
107
+ json.dump(property_data, f, indent=2)
108
+
109
+ # Создание директории examples
110
+ examples_dir = AGENTS_DIR / "examples"
111
+ examples_dir.mkdir(exist_ok=True)
112
+
113
+ # Создание voice_agent.json
114
+ voice_agent_path = examples_dir / "voice_agent.json"
115
+ if not voice_agent_path.exists():
116
+ voice_data = {
117
+ "_ten": {
118
+ "version": "0.0.1"
119
+ },
120
+ "nodes": [
121
+ {
122
+ "id": "start",
123
+ "type": "start",
124
+ "data": {
125
+ "x": 100,
126
+ "y": 100
127
+ }
128
+ },
129
+ {
130
+ "id": "openai_chatgpt",
131
+ "type": "openai_chatgpt",
132
+ "data": {
133
+ "x": 300,
134
+ "y": 200,
135
+ "properties": {
136
+ "model": "gpt-3.5-turbo",
137
+ "temperature": 0.7,
138
+ "system_prompt": "Вы полезный голосовой помощник."
139
+ }
140
+ }
141
+ },
142
+ {
143
+ "id": "end",
144
+ "type": "end",
145
+ "data": {
146
+ "x": 500,
147
+ "y": 100
148
+ }
149
+ }
150
+ ],
151
+ "edges": [
152
+ {
153
+ "id": "start_to_chatgpt",
154
+ "source": "start",
155
+ "target": "openai_chatgpt"
156
+ },
157
+ {
158
+ "id": "chatgpt_to_end",
159
+ "source": "openai_chatgpt",
160
+ "target": "end"
161
+ }
162
+ ],
163
+ "groups": [],
164
+ "templates": [],
165
+ "root": "start"
166
+ }
167
 
168
+ with open(voice_agent_path, 'w') as f:
169
+ json.dump(voice_data, f, indent=2)
170
+
171
+ # Создание chat_agent.json
172
+ chat_agent_path = examples_dir / "chat_agent.json"
173
+ if not chat_agent_path.exists():
174
+ chat_data = {
175
+ "_ten": {
176
+ "version": "0.0.1"
177
+ },
178
+ "nodes": [
179
+ {
180
+ "id": "start",
181
+ "type": "start",
182
+ "data": {
183
+ "x": 100,
184
+ "y": 100
185
+ }
186
+ },
187
+ {
188
+ "id": "openai_chatgpt",
189
+ "type": "openai_chatgpt",
190
+ "data": {
191
+ "x": 300,
192
+ "y": 200,
193
+ "properties": {
194
+ "model": "gpt-3.5-turbo",
195
+ "temperature": 0.7,
196
+ "system_prompt": "Вы полезный чат-бот."
197
+ }
198
+ }
199
+ },
200
+ {
201
+ "id": "end",
202
+ "type": "end",
203
+ "data": {
204
+ "x": 500,
205
+ "y": 100
206
+ }
207
+ }
208
+ ],
209
+ "edges": [
210
+ {
211
+ "id": "start_to_chatgpt",
212
+ "source": "start",
213
+ "target": "openai_chatgpt"
214
+ },
215
+ {
216
+ "id": "chatgpt_to_end",
217
+ "source": "openai_chatgpt",
218
+ "target": "end"
219
+ }
220
+ ],
221
+ "groups": [],
222
+ "templates": [],
223
+ "root": "start"
224
+ }
225
 
226
+ with open(chat_agent_path, 'w') as f:
227
+ json.dump(chat_data, f, indent=2)
228
+
229
+ # Создание manifest.json
230
+ manifest_path = AGENTS_DIR / "manifest.json"
231
+ if not manifest_path.exists():
232
+ manifest_data = {
233
+ "_ten": {
234
+ "version": "0.0.1"
235
+ },
236
+ "name": "default",
237
+ "agents": [
238
+ {
239
+ "name": "voice_agent",
240
+ "description": "A simple voice agent",
241
+ "type": "voice"
242
+ },
243
+ {
244
+ "name": "chat_agent",
245
+ "description": "A text chat agent",
246
+ "type": "chat"
247
+ }
248
+ ]
249
+ }
250
 
251
+ with open(manifest_path, 'w') as f:
252
+ json.dump(manifest_data, f, indent=2)
253
+
254
+ logger.info("Basic configuration files created successfully.")
255
+
256
+ def run_api_server():
257
+ """Запуск API сервера"""
258
+ # Конфигурирование переменных среды
259
+ os.environ["AGENT_SERVER_DIRECTORY"] = str(AGENTS_DIR)
260
+
261
+ logger.info(f"Starting API server with agents directory: {AGENTS_DIR}")
262
+
263
+ # Запуск API сервера напрямую из директории server
264
+ api_binary = Path("/app/server/bin/api")
265
+ if not api_binary.exists():
266
+ logger.error(f"API binary not found at {api_binary}")
267
+ raise FileNotFoundError(f"API binary not found at {api_binary}")
268
+
269
+ cmd = [str(api_binary)]
270
+ logger.info(f"Running command: {' '.join(cmd)}")
271
+
272
+ # Запуск процесса сервера
273
+ api_process = subprocess.Popen(
274
+ cmd,
275
+ stdout=subprocess.PIPE,
276
+ stderr=subprocess.PIPE,
277
+ text=True,
278
+ bufsize=1,
279
+ )
280
+
281
+ # Логирование вывода процесса
282
+ def log_output(stream, prefix):
283
+ for line in stream:
284
+ logger.info(f"{prefix}: {line.strip()}")
285
+
286
+ threading.Thread(target=log_output, args=(api_process.stdout, "API"), daemon=True).start()
287
+ threading.Thread(target=log_output, args=(api_process.stderr, "API ERROR"), daemon=True).start()
288
+
289
+ # Проверка, что процесс запустился
290
+ time.sleep(2)
291
+ if api_process.poll() is not None:
292
+ logger.error(f"API server failed to start with exit code {api_process.returncode}")
293
+ raise RuntimeError(f"API server failed to start with exit code {api_process.returncode}")
294
+
295
+ logger.info("API server started successfully")
296
+ return api_process
297
+
298
+ def run_proxy_server():
299
+ """Запуск прокси-сервера для обработки запросов TEN-Agent Designer API"""
300
+ # Код для запуска прокси-сервера
301
+ logger.info("Starting proxy server for Designer API requests")
302
+
303
+ import http.server
304
+ import socketserver
305
+ import urllib.request
306
+ import urllib.error
307
+ import json
308
+
309
+ class ProxyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
310
+ def do_POST(self):
311
+ logger.info(f"Received POST request: {self.path}")
312
 
313
+ # Перенаправляем запрос /api/dev/v1/packages/reload на /graphs
314
+ if self.path.startswith('/api/dev/v1/packages/reload') or self.path.startswith('/api/designer/v1/packages/reload'):
315
+ try:
316
+ logger.info("Redirecting to /graphs")
317
+
318
+ try:
319
+ with urllib.request.urlopen("http://localhost:8080/graphs") as response:
320
+ data = response.read().decode('utf-8')
321
+
322
+ # Если сервер вернул пустой ответ или ошибку, создаем свой собственный ответ
323
+ if not data or "Invalid format" in data:
324
+ logger.info("Server returned error or empty response, creating custom response")
325
+ # Создаем хардкодный список графов из property.json
326
+ property_path = AGENTS_DIR / "property.json"
327
+ if property_path.exists():
328
+ try:
329
+ with open(property_path, 'r') as f:
330
+ property_data = json.load(f)
331
+ graphs = property_data.get("graphs", [])
332
+ except Exception as e:
333
+ logger.error(f"Error reading property.json: {e}")
334
+ graphs = []
335
+ else:
336
+ graphs = []
337
+
338
+ # Добавляем обязательные поля для каждого графа
339
+ for graph in graphs:
340
+ if "id" not in graph:
341
+ graph["id"] = graph.get("name", "").lower().replace(" ", "_")
342
+ else:
343
+ try:
344
+ # Пытаемся разобрать JSON из ответа
345
+ graphs = json.loads(data)
346
+ except json.JSONDecodeError:
347
+ logger.error(f"Error parsing JSON from server response: {data}")
348
+ graphs = []
349
+
350
+ # Форматируем ответ в нужном формате для фронтенда
351
+ formatted_response = {
352
+ "data": graphs,
353
+ "status": 200,
354
+ "message": "Success"
355
+ }
356
+
357
+ response_data = json.dumps(formatted_response).encode('utf-8')
358
+
359
+ # Отправляем ответ
360
+ self.send_response(200)
361
+ self.send_header('Content-Type', 'application/json')
362
+ self.send_header('Content-Length', len(response_data))
363
+ self.send_header('Access-Control-Allow-Origin', '*')
364
+ self.end_headers()
365
+ self.wfile.write(response_data)
366
+ logger.info(f"Sent response: {response_data.decode('utf-8')}")
367
+ except urllib.error.URLError as e:
368
+ logger.error(f"Error when redirecting: {e}")
369
+ # В случае ошибки, отправляем хардкодный ответ
370
+ property_path = AGENTS_DIR / "property.json"
371
+ if property_path.exists():
372
+ try:
373
+ with open(property_path, 'r') as f:
374
+ property_data = json.load(f)
375
+ graphs = property_data.get("graphs", [])
376
+ except Exception as e:
377
+ logger.error(f"Error reading property.json: {e}")
378
+ graphs = []
379
+ else:
380
+ graphs = []
381
+
382
+ # Добавляем обязательные поля для каждого графа
383
+ for graph in graphs:
384
+ if "id" not in graph:
385
+ graph["id"] = graph.get("name", "").lower().replace(" ", "_")
386
+
387
+ formatted_response = {
388
+ "data": graphs,
389
+ "status": 200,
390
+ "message": "Success"
391
+ }
392
+
393
+ response_data = json.dumps(formatted_response).encode('utf-8')
394
+
395
+ self.send_response(200)
396
+ self.send_header('Content-Type', 'application/json')
397
+ self.send_header('Content-Length', len(response_data))
398
+ self.send_header('Access-Control-Allow-Origin', '*')
399
+ self.end_headers()
400
+ self.wfile.write(response_data)
401
+ logger.info(f"Sent hardcoded response: {response_data.decode('utf-8')}")
402
+ except Exception as e:
403
+ logger.error(f"Unexpected error: {e}")
404
+ self.send_error(500, f"Internal Server Error: {str(e)}")
405
+ else:
406
+ self.send_error(404, "Not Found")
407
+
408
+ def do_OPTIONS(self):
409
+ self.send_response(200)
410
+ self.send_header('Access-Control-Allow-Origin', '*')
411
+ self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
412
+ self.send_header('Access-Control-Allow-Headers', 'Content-Type')
413
+ self.end_headers()
414
 
415
+ def do_GET(self):
416
+ logger.info(f"Received GET request: {self.path}")
 
 
 
 
 
 
 
417
 
418
+ # Перенаправляем запрос /api/designer/v1/addons/extensions
419
+ if self.path.startswith('/api/designer/v1/addons/extensions'):
420
+ # Отправляем хардкодный ответ со списком расширений
421
+ extensions = [
422
+ {
423
+ "id": "openai_chatgpt",
424
+ "name": "OpenAI ChatGPT",
425
+ "version": "0.0.1",
426
+ "description": "Integration with OpenAI ChatGPT API",
427
+ "nodes": [
428
+ {
429
+ "id": "openai_chatgpt",
430
+ "name": "OpenAI ChatGPT",
431
+ "category": "AI",
432
+ "description": "Sends message to OpenAI ChatGPT API"
433
+ }
434
+ ]
435
+ }
436
+ ]
437
+
438
+ formatted_response = {
439
+ "data": extensions,
440
+ "status": 200,
441
+ "message": "Success"
442
+ }
443
+
444
+ response_data = json.dumps(formatted_response).encode('utf-8')
445
+
446
+ self.send_response(200)
447
+ self.send_header('Content-Type', 'application/json')
448
+ self.send_header('Content-Length', len(response_data))
449
+ self.send_header('Access-Control-Allow-Origin', '*')
450
+ self.end_headers()
451
+ self.wfile.write(response_data)
452
+ logger.info(f"Sent response for extensions: {response_data.decode('utf-8')}")
453
+ else:
454
+ self.send_error(404, "Not Found")
455
+
456
+ # Запуск HTTP сервера
457
+ port = 49483
458
+ httpd = socketserver.ThreadingTCPServer(("", port), ProxyHTTPRequestHandler)
459
+ logger.info(f"Proxy server started at port {port}")
460
+
461
+ # Запуск в отдельном потоке
462
+ proxy_thread = threading.Thread(target=httpd.serve_forever)
463
+ proxy_thread.daemon = True
464
+ proxy_thread.start()
465
+
466
+ return httpd
467
+
468
+ def run_playground():
469
+ """Запуск Playground UI"""
470
+ logger.info("Starting Playground UI in development mode")
471
+
472
+ # Настройка окружения для Playground
473
+ env = os.environ.copy()
474
+ env["PORT"] = "7860"
475
+ env["AGENT_SERVER_URL"] = "http://localhost:8080"
476
+ env["NEXT_PUBLIC_EDIT_GRAPH_MODE"] = "true"
477
+ env["NEXT_PUBLIC_DISABLE_CAMERA"] = "true"
478
+
479
+ playground_dir = Path("/app/playground")
480
+ if not playground_dir.exists():
481
+ logger.error(f"Playground directory not found at {playground_dir}")
482
+ raise FileNotFoundError(f"Playground directory not found at {playground_dir}")
483
+
484
+ cmd = ["pnpm", "dev"]
485
+ logger.info(f"Running command in {playground_dir}: {' '.join(cmd)}")
486
+
487
+ # Запуск процесса Playground
488
+ playground_process = subprocess.Popen(
489
+ cmd,
490
+ cwd=str(playground_dir),
491
+ env=env,
492
+ stdout=subprocess.PIPE,
493
+ stderr=subprocess.PIPE,
494
+ text=True,
495
+ bufsize=1,
496
+ )
497
+
498
+ # Логирование вывода процесса
499
+ def log_output(stream, prefix):
500
+ for line in stream:
501
+ logger.info(f"{prefix}: {line.strip()}")
502
+
503
+ threading.Thread(target=log_output, args=(playground_process.stdout, "PLAYGROUND"), daemon=True).start()
504
+ threading.Thread(target=log_output, args=(playground_process.stderr, "PLAYGROUND ERROR"), daemon=True).start()
505
+
506
+ # Проверка, что процесс запустился
507
+ time.sleep(3)
508
+ if playground_process.poll() is not None:
509
+ logger.error(f"Playground UI failed to start with exit code {playground_process.returncode}")
510
+ raise RuntimeError(f"Playground UI failed to start with exit code {playground_process.returncode}")
511
+
512
+ logger.info("Playground UI started successfully")
513
+ return playground_process
514
+
515
+ def main():
516
+ """Основная функция запуска"""
517
+ try:
518
+ # Настройка окружения
519
+ setup_environment()
520
 
521
+ # Создание структуры директорий
522
+ create_directory_structure()
 
 
 
 
 
 
523
 
524
+ # Создание базовых конфигурационных файлов
525
+ create_basic_config()
526
 
527
+ # Запуск сервисов
528
+ api_process = run_api_server()
529
+ proxy_server = run_proxy_server()
530
+ playground_process = run_playground()
531
 
532
+ # Отслеживание статуса процессов
533
+ logger.info("All services started. Monitoring status...")
534
 
535
+ try:
536
+ while True:
537
+ # Проверка статуса API сервера
538
+ if api_process.poll() is not None:
539
+ logger.error(f"API server exited with code {api_process.returncode}")
540
+ break
541
+
542
+ # Проверка статуса Playground
543
+ if playground_process.poll() is not None:
544
+ logger.error(f"Playground UI exited with code {playground_process.returncode}")
545
+ break
546
+
547
+ time.sleep(5)
548
+ except KeyboardInterrupt:
549
+ logger.info("Received interrupt signal")
550
+ finally:
551
+ # Остановка сервисов
552
+ logger.info("Stopping services...")
553
 
554
+ try:
555
+ if api_process and api_process.poll() is None:
556
+ api_process.terminate()
557
+ api_process.wait(timeout=5)
558
+ except Exception as e:
559
+ logger.warning(f"Error stopping API server: {e}")
560
 
561
+ try:
562
+ if playground_process and playground_process.poll() is None:
563
+ playground_process.terminate()
564
+ playground_process.wait(timeout=5)
565
+ except Exception as e:
566
+ logger.warning(f"Error stopping Playground UI: {e}")
567
+
568
+ try:
569
+ proxy_server.shutdown()
570
+ except Exception as e:
571
+ logger.warning(f"Error stopping proxy server: {e}")
572
+
573
  except Exception as e:
574
+ logger.error(f"Error: {e}", exc_info=True)
575
+ return 1
576
+
577
+ return 0
578
 
579
  if __name__ == "__main__":
580
+ # Настройка обработки сигналов
581
+ signal.signal(signal.SIGINT, lambda sig, frame: sys.exit(0))
582
+ signal.signal(signal.SIGTERM, lambda sig, frame: sys.exit(0))
583
+
584
+ # Запуск основной функции
585
+ sys.exit(main())