3v324v23 commited on
Commit
2455e56
·
1 Parent(s): 86f3bf2

Исправлена проблема с правами Go при сборке и прокси для работы Playground UI

Browse files
Files changed (2) hide show
  1. Dockerfile +11 -8
  2. app.py +73 -66
Dockerfile CHANGED
@@ -22,22 +22,25 @@ RUN apt-get clean && apt-get update && apt-get install -y --no-install-recommend
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
- # Установка Node.js 20.x (вместо 18.x) и pnpm для Playground
34
  RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
35
  apt-get install -y nodejs && \
36
  npm install -g pnpm
37
 
38
- # Создаем пользователя для запуска приложения с правильными правами
39
- RUN useradd -m -s /bin/bash tenuser
40
-
41
  WORKDIR /app
42
 
43
  # Клонирование репозитория TEN Agent (основная ветка)
@@ -70,7 +73,7 @@ RUN cd /app/server && \
70
 
71
  # Сборка Playground UI с правами пользователя
72
  WORKDIR /app/playground
73
- ENV PNPM_HOME="/app/.pnpm-store"
74
  ENV PATH="$PNPM_HOME:$PATH"
75
  RUN pnpm install --no-frozen-lockfile && \
76
  NEXT_PUBLIC_EDIT_GRAPH_MODE=false pnpm build
 
22
  ca-certificates \
23
  && apt-get clean && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/*
24
 
25
+ # Создаем пользователя для запуска приложения с правильными правами
26
+ RUN useradd -m -s /bin/bash tenuser
27
+
28
+ # Установка Go 1.21 с правильными правами доступа
29
  RUN wget https://golang.org/dl/go1.21.0.linux-amd64.tar.gz && \
30
  tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz && \
31
+ rm go1.21.0.linux-amd64.tar.gz && \
32
+ mkdir -p /home/tenuser/go && \
33
+ chown -R tenuser:tenuser /home/tenuser/go
34
+
35
  ENV PATH=$PATH:/usr/local/go/bin
36
+ ENV GOPATH=/home/tenuser/go
37
  ENV PATH=$PATH:$GOPATH/bin
38
 
39
+ # Установка Node.js 20.x и pnpm для Playground
40
  RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
41
  apt-get install -y nodejs && \
42
  npm install -g pnpm
43
 
 
 
 
44
  WORKDIR /app
45
 
46
  # Клонирование репозитория TEN Agent (основная ветка)
 
73
 
74
  # Сборка Playground UI с правами пользователя
75
  WORKDIR /app/playground
76
+ ENV PNPM_HOME="/home/tenuser/.pnpm-store"
77
  ENV PATH="$PNPM_HOME:$PATH"
78
  RUN pnpm install --no-frozen-lockfile && \
79
  NEXT_PUBLIC_EDIT_GRAPH_MODE=false pnpm build
app.py CHANGED
@@ -22,83 +22,90 @@ def main():
22
  if not playground_dir.exists():
23
  print(f"ERROR: Playground directory not found at {playground_dir}", file=sys.stderr)
24
  return 1
 
 
 
 
 
 
 
 
25
 
26
- # Запускаем простой HTTP сервер для Hugging Face
 
 
 
 
 
 
 
 
 
 
 
27
  from http.server import HTTPServer, SimpleHTTPRequestHandler
 
 
28
 
29
- class CustomHandler(SimpleHTTPRequestHandler):
30
  def do_GET(self):
31
- if self.path == '/':
32
- self.send_response(200)
33
- self.send_header('Content-type', 'text/html; charset=utf-8')
34
- self.end_headers()
 
 
 
 
 
35
 
36
- html_content = """
37
- <!DOCTYPE html>
38
- <html>
39
- <head>
40
- <title>TEN Agent - Hugging Face Space</title>
41
- <meta charset="utf-8">
42
- <style>
43
- body { font-family: Arial, sans-serif; line-height: 1.6; max-width: 800px; margin: 0 auto; padding: 20px; }
44
- h1 { color: #333; }
45
- .info { background: #f8f9fa; border-left: 4px solid #28a745; padding: 15px; margin-bottom: 20px; }
46
- .endpoint { background: #e9ecef; padding: 10px; border-radius: 5px; font-family: monospace; }
47
- .api { margin-top: 30px; }
48
- </style>
49
- </head>
50
- <body>
51
- <h1>TEN Agent запущен успешно!</h1>
52
- <div class="info">
53
- <p>TEN Agent API сервер работает на порту 8080.</p>
54
- <p>В связи с ограничениями Hugging Face Space, полноценный интерфейс Playground UI не может быть запущен напрямую.</p>
55
- </div>
56
-
57
- <div class="api">
58
- <h2>API эндпоинты:</h2>
59
- <ul>
60
- <li><span class="endpoint">GET /health</span> - проверка состояния сервера</li>
61
- <li><span class="endpoint">GET /list</span> - список запущенных агентов</li>
62
- <li><span class="endpoint">GET /graphs</span> - доступные графы</li>
63
- </ul>
64
- </div>
65
-
66
- <h2>Инструкция по локальному использованию</h2>
67
- <p>Для использования полного интерфейса, подключите локальный Playground к этому API:</p>
68
- <ol>
69
- <li>Клонируйте репозиторий: <code>git clone https://github.com/TEN-framework/TEN-Agent.git</code></li>
70
- <li>Перейдите в директорию playground: <code>cd TEN-Agent/playground</code></li>
71
- <li>Установите зависимости: <code>pnpm install</code></li>
72
- <li>Запустите Playground с подключением к API: <code>AGENT_SERVER_URL=https://nitrox-ten.hf.space pnpm dev</code></li>
73
- <li>Откройте в браузере: <code>http://localhost:3000</code></li>
74
- </ol>
75
-
76
- <p>См. <a href="https://github.com/TEN-framework/TEN-Agent" target="_blank">документацию TEN Agent</a> для получения дополнительной информации.</p>
77
- </body>
78
- </html>
79
- """
80
 
81
- self.wfile.write(html_content.encode('utf-8'))
82
- elif self.path.startswith('/health') or self.path.startswith('/list') or self.path.startswith('/graphs'):
83
- # Проксирование API запросов к API серверу
84
- self.send_response(301)
85
- self.send_header('Location', f'http://localhost:8080{self.path}')
 
 
 
 
 
 
 
 
 
 
 
 
86
  self.end_headers()
87
- else:
88
- self.send_response(404)
 
 
 
 
 
89
  self.send_header('Content-type', 'text/plain; charset=utf-8')
90
  self.end_headers()
91
- self.wfile.write(b'Not Found')
92
 
93
- # Запускаем API сервер
94
- print("Starting TEN-Agent API server on port 8080...")
95
- api_server_process = subprocess.Popen([str(api_binary)])
96
- processes.append(api_server_process)
97
 
98
- # Запускаем HTTP сервер для Hugging Face
99
- port = 7860 # Hugging Face Space обычно ожидает сервер на порту 7860
100
- print(f"Starting HTTP server on port {port}...")
101
- httpd = HTTPServer(('0.0.0.0', port), CustomHandler)
 
102
  httpd.serve_forever()
103
 
104
  except KeyboardInterrupt:
 
22
  if not playground_dir.exists():
23
  print(f"ERROR: Playground directory not found at {playground_dir}", file=sys.stderr)
24
  return 1
25
+
26
+ # Запускаем API сервер
27
+ print("Starting TEN-Agent API server on port 8080...")
28
+ api_server_process = subprocess.Popen([str(api_binary)])
29
+ processes.append(api_server_process)
30
+
31
+ # Даем время API серверу запуститься
32
+ time.sleep(3)
33
 
34
+ # Запускаем Playground UI
35
+ print("Starting Playground UI on port 3000...")
36
+ playground_env = os.environ.copy()
37
+ playground_env["AGENT_SERVER_URL"] = "http://localhost:8080" # Подключаемся к локальному API серверу
38
+ playground_process = subprocess.Popen(
39
+ ["pnpm", "start", "--", "-p", "3000"],
40
+ cwd=str(playground_dir),
41
+ env=playground_env
42
+ )
43
+ processes.append(playground_process)
44
+
45
+ # Запускаем прокси для Hugging Face
46
  from http.server import HTTPServer, SimpleHTTPRequestHandler
47
+ import http.client
48
+ import socketserver
49
 
50
+ class ProxyHandler(SimpleHTTPRequestHandler):
51
  def do_GET(self):
52
+ # Направляем запросы к Playground UI
53
+ if self.path == '/' or self.path.startswith('/about') or self.path.startswith('/_next') or self.path.startswith('/favicon.ico'):
54
+ self._proxy_request('localhost', 3000, self.path)
55
+ # Направляем API запросы к API серверу
56
+ elif self.path.startswith('/health') or self.path.startswith('/list') or self.path.startswith('/graphs'):
57
+ self._proxy_request('localhost', 8080, self.path)
58
+ else:
59
+ # По умолчанию отправляем на Playground
60
+ self._proxy_request('localhost', 3000, self.path)
61
 
62
+ def do_POST(self):
63
+ # Все POST запросы направляем в API
64
+ self._proxy_request('localhost', 8080, self.path)
65
+
66
+ def _proxy_request(self, host, port, path):
67
+ try:
68
+ # Создаем соединение с целевым сервером
69
+ conn = http.client.HTTPConnection(host, port)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
+ # Копируем заголовки запроса
72
+ headers = {}
73
+ for header in self.headers:
74
+ headers[header] = self.headers[header]
75
+
76
+ # Получаем данные запроса
77
+ content_length = int(self.headers.get('Content-Length', 0))
78
+ body = self.rfile.read(content_length) if content_length > 0 else None
79
+
80
+ # Отправляем запрос на целевой сервер
81
+ conn.request(self.command, path, body=body, headers=headers)
82
+ resp = conn.getresponse()
83
+
84
+ # Отправляем ответ клиенту
85
+ self.send_response(resp.status)
86
+ for header in resp.headers:
87
+ self.send_header(header, resp.headers[header])
88
  self.end_headers()
89
+
90
+ # Отправляем тело ответа
91
+ self.wfile.write(resp.read())
92
+ conn.close()
93
+ except Exception as e:
94
+ print(f"Proxy error: {e}", file=sys.stderr)
95
+ self.send_response(500)
96
  self.send_header('Content-type', 'text/plain; charset=utf-8')
97
  self.end_headers()
98
+ self.wfile.write(f"Proxy error: {e}".encode('utf-8'))
99
 
100
+ # Запускаем HTTP прокси-сервер
101
+ port = 7860 # Hugging Face Space ожидает сервер на этом порту
102
+ print(f"Starting proxy server on port {port}, forwarding to Playground UI and API...")
 
103
 
104
+ # Разрешаем повторное использование адреса и порта
105
+ class ReuseAddressServer(socketserver.TCPServer):
106
+ allow_reuse_address = True
107
+
108
+ httpd = ReuseAddressServer(('0.0.0.0', port), ProxyHandler)
109
  httpd.serve_forever()
110
 
111
  except KeyboardInterrupt: