3v324v23 commited on
Commit
623538d
·
1 Parent(s): bf2f692

Радикальное исправление проблемы с Select Graph путем добавления мок-эндпоинтов дизайнера

Browse files
Files changed (2) hide show
  1. Dockerfile +137 -71
  2. app.py +70 -270
Dockerfile CHANGED
@@ -1,13 +1,8 @@
1
  FROM ubuntu:22.04
2
 
3
- # Установка базовых пакетов
4
- RUN apt-get update && apt-get install -y \
5
- curl \
6
- git \
7
- wget \
8
- make \
9
- gcc \
10
- build-essential \
11
  libasound2 \
12
  libgstreamer1.0-dev \
13
  libunwind-dev \
@@ -17,89 +12,160 @@ RUN apt-get update && apt-get install -y \
17
  python3-venv \
18
  python3-pip \
19
  python3-dev \
 
 
20
  unzip \
 
 
21
  jq \
22
  vim \
23
  ca-certificates \
24
- gnupg \
25
- lsb-release \
26
- net-tools \
27
- procps \
28
  && apt-get clean && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/*
29
 
30
- # Установка Go
31
  RUN wget https://golang.org/dl/go1.21.0.linux-amd64.tar.gz && \
32
  tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz && \
33
  rm go1.21.0.linux-amd64.tar.gz
34
-
35
- # Настройка окружения Go
36
  ENV PATH=$PATH:/usr/local/go/bin
37
  ENV GOPATH=/go
38
  ENV PATH=$PATH:$GOPATH/bin
39
- RUN mkdir -p /go && chmod 777 /go
40
 
41
- # Создание директории для кэша Go
42
- ENV GOCACHE=/tmp/go-cache
43
- RUN mkdir -p /tmp/go-cache && chmod 777 /tmp/go-cache
44
 
45
  # Установка Node.js и pnpm
46
  RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
47
  apt-get install -y nodejs && \
48
  npm install -g pnpm
49
 
50
- # Клонирование репозитория TEN-Agent
51
  WORKDIR /app
52
- RUN git clone --depth 1 https://github.com/TEN-framework/TEN-Agent.git /app-temp && \
53
- mv /app-temp/* /app/ && \
54
- mv /app-temp/.* /app/ 2>/dev/null || true && \
55
- rm -rf /app-temp
56
-
57
- # Создание пользовательских директорий для временных файлов
58
- RUN mkdir -p /tmp/ten_user && chmod 777 /tmp/ten_user
59
- RUN mkdir -p /tmp/ten_user/agents && chmod 777 /tmp/ten_user/agents
60
- RUN mkdir -p /tmp/ten_user/logs && chmod 777 /tmp/ten_user/logs
61
- RUN mkdir -p /tmp/ten_user/rag_data && chmod 777 /tmp/ten_user/rag_data
62
- RUN mkdir -p /app/backup && chmod 777 /app/backup
63
-
64
- # Компиляция API сервера (для справки, мы будем использовать Python-реализацию)
65
  RUN mkdir -p /app/server/bin && \
66
- cd /app/server && \
67
- GOCACHE=/tmp/go-cache go build -o bin/api main.go && \
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  chmod +x bin/api
69
 
70
- # Проверяем, что API сервер скомпилирован
71
- RUN ls -la /app/server/bin/api || echo "API server not compiled"
72
-
73
- # Предварительная установка зависимостей для playground
74
- # Делаем это отдельно, чтобы не пересобирать при каждом изменении
75
- RUN cd /app/playground && pnpm install
76
-
77
- # Запускаем playground один раз для предварительной сборки
78
- RUN cd /app/playground && pnpm build || echo "Failed to build playground, but continuing"
79
-
80
- # Копируем наши скрипты
81
- COPY fallback.py /app/fallback.py
82
- COPY api_wrapper.py /app/api_wrapper.py
83
- COPY start.sh /app/start.sh
84
- RUN chmod +x /app/start.sh /app/fallback.py /app/api_wrapper.py
85
-
86
- # Устанавливаем переменные окружения для HuggingFace
87
- ENV HF_SPACE=true
88
- ENV AGENT_SERVER_URL=http://localhost:8080
89
- ENV NEXT_PUBLIC_EDIT_GRAPH_MODE=true
90
- ENV NEXT_PUBLIC_DISABLE_CAMERA=true
91
- ENV PORT=7860
92
- ENV API_PORT=8080
93
- ENV TEN_AGENT_DIR=/tmp/ten_user/agents
94
- ENV PYTHONUNBUFFERED=1
95
-
96
- # Открываем порты (7860 для HF Space, 8080 для API)
97
- EXPOSE 7860 8080
98
-
99
- # Предварительно создаем важные файлы
100
- RUN mkdir -p /app/agents
101
- RUN echo '{"_ten":{"version":"0.0.1"},"name":"default","agents":[{"name":"voice_agent","description":"A simple voice agent","type":"voice"}]}' > /app/agents/manifest.json
102
- RUN echo '{"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"}]}' > /app/agents/property.json
103
-
104
- # Запускаем TEN-Agent через fallback скрипт
105
- CMD ["/app/start.sh"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  FROM ubuntu:22.04
2
 
3
+ # Принудительное обновление для HuggingFace, чтобы использовать правильную версию Dockerfile
4
+ # Установка необходимых пакетов
5
+ RUN apt-get clean && apt-get update && apt-get install -y --no-install-recommends \
 
 
 
 
 
6
  libasound2 \
7
  libgstreamer1.0-dev \
8
  libunwind-dev \
 
12
  python3-venv \
13
  python3-pip \
14
  python3-dev \
15
+ curl \
16
+ wget \
17
  unzip \
18
+ git \
19
+ build-essential \
20
  jq \
21
  vim \
22
  ca-certificates \
 
 
 
 
23
  && apt-get clean && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/*
24
 
25
+ # Установка Go 1.21
26
  RUN wget https://golang.org/dl/go1.21.0.linux-amd64.tar.gz && \
27
  tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz && \
28
  rm go1.21.0.linux-amd64.tar.gz
 
 
29
  ENV PATH=$PATH:/usr/local/go/bin
30
  ENV GOPATH=/go
31
  ENV PATH=$PATH:$GOPATH/bin
 
32
 
33
+ # Создаем каталог для кэша Go и устанавливаем правильные разрешения
34
+ RUN mkdir -p /go && chmod 777 /go
 
35
 
36
  # Установка Node.js и pnpm
37
  RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
38
  apt-get install -y nodejs && \
39
  npm install -g pnpm
40
 
41
+ # Устанавливаем рабочую директорию
42
  WORKDIR /app
43
+
44
+ # Клонируем репозиторий TEN-Agent
45
+ RUN git clone --depth 1 https://github.com/TEN-framework/TEN-Agent.git /app && \
46
+ echo "Доступные ветки и теги:" && \
47
+ git branch -a && \
48
+ git tag -l
49
+
50
+ # Устанавливаем task для сборки
51
+ RUN go install github.com/go-task/task/v3/cmd/task@latest
52
+
53
+ # Создаем необходимые директории и устанавливаем права
 
 
54
  RUN mkdir -p /app/server/bin && \
55
+ mkdir -p /app/agents && \
56
+ mkdir -p /tmp/ten_agent && \
57
+ mkdir -p /app/.pnpm-store
58
+
59
+ # Копируем .env файл
60
+ COPY .env /app/.env
61
+
62
+ # Патчим файл конфигурации Next.js, чтобы перенаправлять запросы к дизайнеру на наш API
63
+ RUN echo 'module.exports = { \
64
+ async rewrites() { \
65
+ return [ \
66
+ { \
67
+ source: "/api/designer/:path*", \
68
+ destination: "/api/agents/:path*", \
69
+ }, \
70
+ { \
71
+ source: "/api/dev/:path*", \
72
+ destination: "/api/agents/:path*", \
73
+ }, \
74
+ ]; \
75
+ }, \
76
+ };' > /app/playground/next.config.js
77
+
78
+ # Патчим API сервер для обработки запросов дизайнера
79
+ 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
80
+
81
+ # Компилируем сервер
82
+ RUN cd /app/server && \
83
+ go mod tidy && \
84
+ go mod download && \
85
+ go build -o bin/api main.go && \
86
  chmod +x bin/api
87
 
88
+ # Установка зависимостей для Playground UI
89
+ ENV PNPM_HOME="/app/.pnpm-store"
90
+ ENV PATH="$PNPM_HOME:$PATH"
91
+ RUN cd /app/playground && \
92
+ pnpm install
93
+
94
+ # Подготавливаем пример агента для работы Select Graph
95
+ RUN cd /app && \
96
+ mkdir -p agents/examples && \
97
+ mkdir -p agents/examples/default && \
98
+ mkdir -p agents/examples/demo && \
99
+ mkdir -p agents/examples/experimental
100
+
101
+ # Копируем примеры из репозитория
102
+ RUN cd /app && \
103
+ cp -r agents/examples/default agents/ && \
104
+ cp -r agents/examples/demo agents/ && \
105
+ cp -r agents/examples/experimental agents/
106
+
107
+ # Создаем базовый manifest.json
108
+ RUN echo '{\n\
109
+ "name": "default",\n\
110
+ "agents": [\n\
111
+ {\n\
112
+ "name": "voice_agent",\n\
113
+ "description": "A simple voice agent"\n\
114
+ },\n\
115
+ {\n\
116
+ "name": "chat_agent",\n\
117
+ "description": "A text chat agent"\n\
118
+ }\n\
119
+ ]\n\
120
+ }' > /app/agents/manifest.json
121
+
122
+ # Создаем базовый property.json в формате TEN
123
+ RUN echo '{\n\
124
+ "_ten": {},\n\
125
+ "name": "TEN Agent Example",\n\
126
+ "version": "0.0.1",\n\
127
+ "extensions": ["openai_chatgpt"],\n\
128
+ "description": "A basic voice agent with OpenAI",\n\
129
+ "graphs": [\n\
130
+ {\n\
131
+ "name": "Voice Agent",\n\
132
+ "description": "Basic voice agent with OpenAI",\n\
133
+ "file": "voice_agent.json"\n\
134
+ },\n\
135
+ {\n\
136
+ "name": "Chat Agent",\n\
137
+ "description": "Simple chat agent",\n\
138
+ "file": "chat_agent.json"\n\
139
+ }\n\
140
+ ]\n\
141
+ }' > /app/agents/property.json
142
+
143
+ # Создаем простые примеры графов
144
+ RUN echo '{\n\
145
+ "nodes": [],\n\
146
+ "edges": [],\n\
147
+ "groups": [],\n\
148
+ "templates": [],\n\
149
+ "root": null\n\
150
+ }' > /app/agents/voice_agent.json
151
+
152
+ RUN echo '{\n\
153
+ "nodes": [],\n\
154
+ "edges": [],\n\
155
+ "groups": [],\n\
156
+ "templates": [],\n\
157
+ "root": null\n\
158
+ }' > /app/agents/chat_agent.json
159
+
160
+ # Устанавливаем правильные права доступа для всех файлов
161
+ RUN chmod -R 777 /app
162
+
163
+ # Настраиваем стартовый скрипт
164
+ COPY app.py /app/app.py
165
+ RUN chmod +x /app/app.py
166
+
167
+ # Открываем порты
168
+ EXPOSE 7860 8080 3000
169
+
170
+ # Запускаем API сервер и Playground в dev-режиме
171
+ ENTRYPOINT ["python3", "/app/app.py"]
app.py CHANGED
@@ -8,19 +8,24 @@ from pathlib import Path
8
  import signal
9
  import threading
10
  import shutil
11
- import http.server
12
- import socketserver
13
- import urllib.request
14
- import urllib.error
 
 
 
 
15
 
16
  def check_and_create_property_json():
17
  """Проверяет наличие property.json и создает его при необходимости"""
18
  property_path = Path("/app/agents/property.json")
19
 
20
  if not property_path.exists():
21
- print(f"WARNING: {property_path} не найден, создаем файл...")
22
 
23
  property_data = {
 
24
  "name": "TEN Agent Example",
25
  "version": "0.0.1",
26
  "extensions": ["openai_chatgpt"],
@@ -46,189 +51,7 @@ def check_and_create_property_json():
46
  with open(property_path, 'w') as f:
47
  json.dump(property_data, f, indent=2)
48
 
49
- print(f"Файл {property_path} создан успешно")
50
-
51
- # Проверяем наличие _ten секции во всех JSON файлах
52
- check_and_fix_ten_section()
53
-
54
- def check_and_fix_ten_section():
55
- """Проверяет наличие _ten секции во всех JSON файлах и добавляет её если нужно"""
56
- json_files = [
57
- "/app/agents/voice_agent.json",
58
- "/app/agents/chat_agent.json",
59
- "/app/agents/manifest.json"
60
- ]
61
-
62
- for file_path in json_files:
63
- path = Path(file_path)
64
- if path.exists():
65
- try:
66
- with open(path, 'r') as f:
67
- data = json.load(f)
68
-
69
- # Проверяем наличие _ten секции
70
- if '_ten' not in data:
71
- print(f"Добавляем _ten секцию в {file_path}")
72
- data['_ten'] = {"version": "0.0.1"}
73
-
74
- # Сохраняем файл
75
- with open(path, 'w') as f:
76
- json.dump(data, f, indent=2)
77
-
78
- print(f"Файл {file_path} обновлен")
79
- except Exception as e:
80
- print(f"Ошибка при обработке файла {file_path}: {e}")
81
-
82
- class ProxyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
83
- def do_POST(self):
84
- print(f"Получен запрос: {self.path}")
85
-
86
- # Перенаправляем запрос /api/dev/v1/packages/reload на /graphs
87
- if self.path.startswith('/api/dev/v1/packages/reload') or self.path.startswith('/api/designer/v1/packages/reload'):
88
- try:
89
- print("Перенаправление на /graphs")
90
- with urllib.request.urlopen("http://localhost:8080/graphs") as response:
91
- data = response.read().decode('utf-8')
92
-
93
- # Если сервер вернул пустой ответ или ошибку, создаем свой собственный ответ
94
- if not data or "Invalid format" in data:
95
- print("Сервер вернул ошибку или пустой ответ, создаем свой ответ")
96
- # Создаем хардкодный список графов из property.json
97
- property_path = Path("/app/agents/property.json")
98
- if property_path.exists():
99
- try:
100
- with open(property_path, 'r') as f:
101
- property_data = json.load(f)
102
- graphs = property_data.get("graphs", [])
103
- except Exception as e:
104
- print(f"Ошибка чтения property.json: {e}")
105
- graphs = []
106
- else:
107
- graphs = []
108
-
109
- # Добавляем обязательные поля для каждого графа
110
- for graph in graphs:
111
- graph["id"] = graph.get("name", "").lower().replace(" ", "_")
112
- if "file" in graph:
113
- graph["file"] = graph["file"]
114
- else:
115
- try:
116
- # Пытаемся разобрать JSON из ответа
117
- graphs = json.loads(data)
118
- except json.JSONDecodeError:
119
- print(f"Ошибка разбора JSON из ответа сервера: {data}")
120
- graphs = []
121
-
122
- # Форматируем ответ в нужном формате для фронтенда
123
- formatted_response = {
124
- "data": graphs,
125
- "status": 200,
126
- "message": "Success"
127
- }
128
-
129
- response_data = json.dumps(formatted_response).encode('utf-8')
130
-
131
- # Отправляем ответ
132
- self.send_response(200)
133
- self.send_header('Content-Type', 'application/json')
134
- self.send_header('Content-Length', len(response_data))
135
- self.send_header('Access-Control-Allow-Origin', '*')
136
- self.end_headers()
137
- self.wfile.write(response_data)
138
- print(f"Отправлен ответ: {response_data.decode('utf-8')}")
139
- except urllib.error.URLError as e:
140
- print(f"Ошибка при перенаправлении: {e}")
141
- # В случае ошибки, отправляем хардкодный ответ
142
- property_path = Path("/app/agents/property.json")
143
- if property_path.exists():
144
- try:
145
- with open(property_path, 'r') as f:
146
- property_data = json.load(f)
147
- graphs = property_data.get("graphs", [])
148
- except Exception as e:
149
- print(f"Ошибка чтения property.json: {e}")
150
- graphs = []
151
- else:
152
- graphs = []
153
-
154
- # Добавляем обязательные поля для каждого графа
155
- for graph in graphs:
156
- graph["id"] = graph.get("name", "").lower().replace(" ", "_")
157
- if "file" in graph:
158
- graph["file"] = graph["file"]
159
-
160
- formatted_response = {
161
- "data": graphs,
162
- "status": 200,
163
- "message": "Success"
164
- }
165
-
166
- response_data = json.dumps(formatted_response).encode('utf-8')
167
-
168
- self.send_response(200)
169
- self.send_header('Content-Type', 'application/json')
170
- self.send_header('Content-Length', len(response_data))
171
- self.send_header('Access-Control-Allow-Origin', '*')
172
- self.end_headers()
173
- self.wfile.write(response_data)
174
- print(f"Отправлен хардкодный ответ: {response_data.decode('utf-8')}")
175
- else:
176
- self.send_error(404, "Not Found")
177
-
178
- def do_OPTIONS(self):
179
- self.send_response(200)
180
- self.send_header('Access-Control-Allow-Origin', '*')
181
- self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
182
- self.send_header('Access-Control-Allow-Headers', 'Content-Type')
183
- self.end_headers()
184
-
185
- def do_GET(self):
186
- print(f"Получен GET запрос: {self.path}")
187
-
188
- # Перенаправляем запрос /api/designer/v1/addons/extensions
189
- if self.path.startswith('/api/designer/v1/addons/extensions'):
190
- # Отправляем хардкодный ответ со списком расширений
191
- extensions = [
192
- {
193
- "id": "openai_chatgpt",
194
- "name": "OpenAI ChatGPT",
195
- "version": "0.0.1",
196
- "description": "Integration with OpenAI ChatGPT API",
197
- "nodes": [
198
- {
199
- "id": "openai_chatgpt",
200
- "name": "OpenAI ChatGPT",
201
- "category": "AI",
202
- "description": "Sends message to OpenAI ChatGPT API"
203
- }
204
- ]
205
- }
206
- ]
207
-
208
- formatted_response = {
209
- "data": extensions,
210
- "status": 200,
211
- "message": "Success"
212
- }
213
-
214
- response_data = json.dumps(formatted_response).encode('utf-8')
215
-
216
- self.send_response(200)
217
- self.send_header('Content-Type', 'application/json')
218
- self.send_header('Content-Length', len(response_data))
219
- self.send_header('Access-Control-Allow-Origin', '*')
220
- self.end_headers()
221
- self.wfile.write(response_data)
222
- print(f"Отправлен ответ для extensions: {response_data.decode('utf-8')}")
223
- else:
224
- self.send_error(404, "Not Found")
225
-
226
- def run_proxy_server():
227
- """Запускает прокси-сервер на порту 49483"""
228
- handler = ProxyHTTPRequestHandler
229
- httpd = socketserver.TCPServer(("", 49483), handler)
230
- print("Прокси-сервер запущен на порту 49483")
231
- httpd.serve_forever()
232
 
233
  def check_files():
234
  """Проверяет и выводит информацию о важных файлах"""
@@ -240,109 +63,86 @@ def check_files():
240
  "/app/server/bin/api"
241
  ]
242
 
243
- print("\n=== Проверка критических файлов ===")
244
  for file_path in files_to_check:
245
  path = Path(file_path)
246
  if path.exists():
247
  if path.is_file():
248
  size = path.stat().st_size
249
- print(f"✅ {file_path} (размер: {size} байт)")
250
 
251
  # Если это JSON файл, выводим его содержимое
252
  if file_path.endswith('.json'):
253
  try:
254
  with open(file_path, 'r') as f:
255
  content = json.load(f)
256
- print(f" Содержимое: {json.dumps(content, indent=2)}")
257
  except Exception as e:
258
- print(f" Ошибка чтения JSON: {e}")
259
  else:
260
- print(f"❌ {file_path} (это директория, а не файл)")
261
  else:
262
- print(f"❌ {file_path} (файл не найден)")
263
 
264
- print("\n=== Проверка структуры директорий ===")
265
- print("Содержимое /app/agents:")
266
  subprocess.run(["ls", "-la", "/app/agents"])
267
 
268
- print("\nПроверка прав доступа:")
269
  subprocess.run(["stat", "/app/agents"])
270
  subprocess.run(["stat", "/app/agents/property.json"])
271
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272
  def test_api():
273
  """Делает запрос к API для получения списка графов"""
274
  import urllib.request
275
  import urllib.error
276
 
277
- print("\n=== Тестирование API ===")
278
  try:
279
  # Даем серверу время запуститься
280
  time.sleep(3)
281
  with urllib.request.urlopen("http://localhost:8080/graphs") as response:
282
  data = response.read().decode('utf-8')
283
- print(f"Ответ /graphs: {data}")
284
 
285
- # Пробуем сделать запрос к нашему прокси
286
  try:
287
- with urllib.request.urlopen("http://localhost:49483/api/designer/v1/packages/reload") as proxy_response:
288
- proxy_data = proxy_response.read().decode('utf-8')
289
- print(f"Ответ от прокси: {proxy_data}")
290
- except urllib.error.URLError as e:
291
- print(f"Ошибка запроса к прокси: {e}")
292
-
 
293
  except urllib.error.URLError as e:
294
- print(f"Ошибка запроса к API: {e}")
295
  except Exception as e:
296
- print(f"Неизвестная ошибка при запросе к API: {e}")
297
-
298
- def move_json_files_to_right_places():
299
- """Копирует JSON файлы в нужные директории для работы с TEN-Agent"""
300
- # Создаем структуру директорий, похожую на локальную установку
301
- print("Создаем правильную структуру директорий для TEN-Agent...")
302
-
303
- target_dirs = [
304
- "/app/agents",
305
- "/app/agents/examples",
306
- "/app/agents/examples/default",
307
- "/app/agents/extensions"
308
- ]
309
-
310
- for dir_path in target_dirs:
311
- os.makedirs(dir_path, exist_ok=True)
312
-
313
- # Копируем voice_agent.json в директорию examples
314
- source_file = "/app/agents/voice_agent.json"
315
- target_file = "/app/agents/examples/voice_agent.json"
316
- if os.path.exists(source_file):
317
- shutil.copy2(source_file, target_file)
318
- print(f"Файл скопирован: {source_file} -> {target_file}")
319
-
320
- # Копируем chat_agent.json в директорию examples
321
- source_file = "/app/agents/chat_agent.json"
322
- target_file = "/app/agents/examples/chat_agent.json"
323
- if os.path.exists(source_file):
324
- shutil.copy2(source_file, target_file)
325
- print(f"Файл скопирован: {source_file} -> {target_file}")
326
-
327
- # Обновляем property.json с путями к файлам
328
- property_path = "/app/agents/property.json"
329
- if os.path.exists(property_path):
330
- try:
331
- with open(property_path, 'r') as f:
332
- property_data = json.load(f)
333
-
334
- # Обновляем пути к файлам графов
335
- for graph in property_data.get("graphs", []):
336
- if "file" in graph:
337
- graph["file"] = f"examples/{graph['file']}"
338
-
339
- # Сохраняем обновленный файл
340
- with open(property_path, 'w') as f:
341
- json.dump(property_data, f, indent=2)
342
-
343
- print(f"Файл {property_path} обновлен с правильными путями")
344
- except Exception as e:
345
- print(f"Ошибка при обновлении {property_path}: {e}")
346
 
347
  def main():
348
  processes = []
@@ -353,24 +153,24 @@ def main():
353
 
354
  # Проверяем существование файлов
355
  if not api_binary.exists():
356
- print(f"ERROR: API binary not found at {api_binary}", file=sys.stderr)
357
  return 1
358
 
359
  if not playground_dir.exists():
360
- print(f"ERROR: Playground directory not found at {playground_dir}", file=sys.stderr)
361
  return 1
362
 
363
  # Проверяем и создаем property.json
364
  check_and_create_property_json()
365
 
366
- # Перемещаем файлы в нужные места
367
- move_json_files_to_right_places()
368
 
369
  # Проверка файлов перед запуском
370
  check_files()
371
 
372
  # Запускаем API сервер
373
- print("Starting TEN-Agent API server on port 8080...")
374
  api_process = subprocess.Popen([str(api_binary)])
375
  processes.append(api_process)
376
 
@@ -379,18 +179,18 @@ def main():
379
  test_thread.daemon = True
380
  test_thread.start()
381
 
382
- # Запускаем прокси-сервер на порту 49483
383
- proxy_thread = threading.Thread(target=run_proxy_server)
384
- proxy_thread.daemon = True
385
- proxy_thread.start()
386
-
387
  # Запускаем Playground UI в режиме dev на порту 7860 (порт Hugging Face)
388
- print("Starting Playground UI in development mode on port 7860...")
389
  os.environ["PORT"] = "7860"
390
  os.environ["AGENT_SERVER_URL"] = "http://localhost:8080"
391
  os.environ["NEXT_PUBLIC_EDIT_GRAPH_MODE"] = "true" # Включаем расширенный режим редактирования
392
  os.environ["NEXT_PUBLIC_DISABLE_CAMERA"] = "true" # Отключаем запрос на использование камеры
393
 
 
 
 
 
 
394
  playground_process = subprocess.Popen(
395
  ["pnpm", "dev"],
396
  cwd=str(playground_dir),
@@ -403,9 +203,9 @@ def main():
403
  proc.wait()
404
 
405
  except KeyboardInterrupt:
406
- print("Shutting down...")
407
  except Exception as e:
408
- print(f"Error: {e}", file=sys.stderr)
409
  finally:
410
  # Завершение процессов
411
  for proc in processes:
 
8
  import signal
9
  import threading
10
  import shutil
11
+ import logging
12
+
13
+ # Настройка логирования
14
+ logging.basicConfig(level=logging.INFO,
15
+ format='%(asctime)s [%(levelname)s] %(message)s',
16
+ datefmt='%Y-%m-%d %H:%M:%S')
17
+
18
+ logger = logging.getLogger('ten-agent')
19
 
20
  def check_and_create_property_json():
21
  """Проверяет наличие property.json и создает его при необходимости"""
22
  property_path = Path("/app/agents/property.json")
23
 
24
  if not property_path.exists():
25
+ logger.warning(f"{property_path} не найден, создаем файл...")
26
 
27
  property_data = {
28
+ "_ten": {}, # Важное поле для TEN формата
29
  "name": "TEN Agent Example",
30
  "version": "0.0.1",
31
  "extensions": ["openai_chatgpt"],
 
51
  with open(property_path, 'w') as f:
52
  json.dump(property_data, f, indent=2)
53
 
54
+ logger.info(f"Файл {property_path} создан успешно")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
  def check_files():
57
  """Проверяет и выводит информацию о важных файлах"""
 
63
  "/app/server/bin/api"
64
  ]
65
 
66
+ logger.info("=== Проверка критических файлов ===")
67
  for file_path in files_to_check:
68
  path = Path(file_path)
69
  if path.exists():
70
  if path.is_file():
71
  size = path.stat().st_size
72
+ logger.info(f"✅ {file_path} (размер: {size} байт)")
73
 
74
  # Если это JSON файл, выводим его содержимое
75
  if file_path.endswith('.json'):
76
  try:
77
  with open(file_path, 'r') as f:
78
  content = json.load(f)
79
+ logger.info(f" Содержимое: {json.dumps(content, indent=2)}")
80
  except Exception as e:
81
+ logger.error(f" Ошибка чтения JSON: {e}")
82
  else:
83
+ logger.warning(f"❌ {file_path} (это директория, а не файл)")
84
  else:
85
+ logger.error(f"❌ {file_path} (файл не найден)")
86
 
87
+ logger.info("=== Проверка структуры директорий ===")
88
+ logger.info("Содержимое /app/agents:")
89
  subprocess.run(["ls", "-la", "/app/agents"])
90
 
91
+ logger.info("Проверка прав доступа:")
92
  subprocess.run(["stat", "/app/agents"])
93
  subprocess.run(["stat", "/app/agents/property.json"])
94
 
95
+ def setup_mock_designer():
96
+ """Настраивает мок-эндпоинты для дизайнера"""
97
+ # Создаем файл с мок-ответом для запросов
98
+ mock_dir = Path("/app/mock_responses")
99
+ mock_dir.mkdir(exist_ok=True)
100
+
101
+ reload_response = {
102
+ "success": True,
103
+ "packages": [
104
+ {
105
+ "name": "default",
106
+ "description": "Default package",
107
+ "graphs": [
108
+ {"name": "Voice Agent", "description": "Voice Agent with OpenAI", "file": "voice_agent.json"},
109
+ {"name": "Chat Agent", "description": "Simple Chat Agent", "file": "chat_agent.json"}
110
+ ]
111
+ }
112
+ ]
113
+ }
114
+
115
+ with open(mock_dir / "reload_response.json", "w") as f:
116
+ json.dump(reload_response, f, indent=2)
117
+
118
+ logger.info("Мок-файлы для дизайнера созданы")
119
+
120
  def test_api():
121
  """Делает запрос к API для получения списка графов"""
122
  import urllib.request
123
  import urllib.error
124
 
125
+ logger.info("=== Тестирование API ===")
126
  try:
127
  # Даем серверу время запуститься
128
  time.sleep(3)
129
  with urllib.request.urlopen("http://localhost:8080/graphs") as response:
130
  data = response.read().decode('utf-8')
131
+ logger.info(f"Ответ /graphs: {data}")
132
 
133
+ # Проверяем структуру ответа
134
  try:
135
+ json_data = json.loads(data)
136
+ if isinstance(json_data, list) and len(json_data) > 0:
137
+ logger.info(f"API вернул {len(json_data)} графов")
138
+ else:
139
+ logger.warning("API вернул пус��ой список графов")
140
+ except json.JSONDecodeError:
141
+ logger.error("Ответ API не является валидным JSON")
142
  except urllib.error.URLError as e:
143
+ logger.error(f"Ошибка запроса к API: {e}")
144
  except Exception as e:
145
+ logger.error(f"Неизвестная ошибка при запросе к API: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
  def main():
148
  processes = []
 
153
 
154
  # Проверяем существование файлов
155
  if not api_binary.exists():
156
+ logger.error(f"API binary не найден: {api_binary}")
157
  return 1
158
 
159
  if not playground_dir.exists():
160
+ logger.error(f"Playground директория не найдена: {playground_dir}")
161
  return 1
162
 
163
  # Проверяем и создаем property.json
164
  check_and_create_property_json()
165
 
166
+ # Создаем мок-файлы для дизайнера
167
+ setup_mock_designer()
168
 
169
  # Проверка файлов перед запуском
170
  check_files()
171
 
172
  # Запускаем API сервер
173
+ logger.info("Запуск TEN-Agent API сервера на порту 8080...")
174
  api_process = subprocess.Popen([str(api_binary)])
175
  processes.append(api_process)
176
 
 
179
  test_thread.daemon = True
180
  test_thread.start()
181
 
 
 
 
 
 
182
  # Запускаем Playground UI в режиме dev на порту 7860 (порт Hugging Face)
183
+ logger.info("Запуск Playground UI в режиме разработки на порту 7860...")
184
  os.environ["PORT"] = "7860"
185
  os.environ["AGENT_SERVER_URL"] = "http://localhost:8080"
186
  os.environ["NEXT_PUBLIC_EDIT_GRAPH_MODE"] = "true" # Включаем расширенный режим редактирования
187
  os.environ["NEXT_PUBLIC_DISABLE_CAMERA"] = "true" # Отключаем запрос на использование камеры
188
 
189
+ # Важные переменные для отключения запросов к дизайнеру
190
+ os.environ["NEXT_PUBLIC_DEV_MODE"] = "false"
191
+ os.environ["NEXT_PUBLIC_API_BASE_URL"] = "/api/agents"
192
+ os.environ["NEXT_PUBLIC_DESIGNER_API_URL"] = "http://localhost:8080"
193
+
194
  playground_process = subprocess.Popen(
195
  ["pnpm", "dev"],
196
  cwd=str(playground_dir),
 
203
  proc.wait()
204
 
205
  except KeyboardInterrupt:
206
+ logger.info("Завершение работы...")
207
  except Exception as e:
208
+ logger.error(f"Ошибка: {e}")
209
  finally:
210
  # Завершение процессов
211
  for proc in processes: