|
|
|
import os |
|
import subprocess |
|
import sys |
|
import time |
|
from pathlib import Path |
|
import signal |
|
import shutil |
|
|
|
def main(): |
|
processes = [] |
|
try: |
|
|
|
api_binary = Path("/app/server/bin/api") |
|
playground_dir = Path("/app/playground") |
|
|
|
|
|
if not api_binary.exists(): |
|
print(f"ERROR: API binary not found at {api_binary}", file=sys.stderr) |
|
return 1 |
|
|
|
if not playground_dir.exists(): |
|
print(f"ERROR: Playground directory not found at {playground_dir}", file=sys.stderr) |
|
return 1 |
|
|
|
|
|
print("Starting TEN-Agent API server on port 8080...") |
|
api_server_process = subprocess.Popen([str(api_binary)]) |
|
processes.append(api_server_process) |
|
|
|
|
|
time.sleep(3) |
|
|
|
|
|
print("Starting Playground UI on port 3000...") |
|
playground_env = os.environ.copy() |
|
playground_env["AGENT_SERVER_URL"] = "http://localhost:8080" |
|
playground_process = subprocess.Popen( |
|
["pnpm", "start", "--", "-p", "3000"], |
|
cwd=str(playground_dir), |
|
env=playground_env |
|
) |
|
processes.append(playground_process) |
|
|
|
|
|
from http.server import HTTPServer, SimpleHTTPRequestHandler |
|
import http.client |
|
import socketserver |
|
|
|
class ProxyHandler(SimpleHTTPRequestHandler): |
|
def do_GET(self): |
|
|
|
if self.path == '/' or self.path.startswith('/about') or self.path.startswith('/_next') or self.path.startswith('/favicon.ico'): |
|
self._proxy_request('localhost', 3000, self.path) |
|
|
|
elif self.path.startswith('/health') or self.path.startswith('/list') or self.path.startswith('/graphs'): |
|
self._proxy_request('localhost', 8080, self.path) |
|
else: |
|
|
|
self._proxy_request('localhost', 3000, self.path) |
|
|
|
def do_POST(self): |
|
|
|
self._proxy_request('localhost', 8080, self.path) |
|
|
|
def _proxy_request(self, host, port, path): |
|
try: |
|
|
|
conn = http.client.HTTPConnection(host, port) |
|
|
|
|
|
headers = {} |
|
for header in self.headers: |
|
headers[header] = self.headers[header] |
|
|
|
|
|
content_length = int(self.headers.get('Content-Length', 0)) |
|
body = self.rfile.read(content_length) if content_length > 0 else None |
|
|
|
|
|
conn.request(self.command, path, body=body, headers=headers) |
|
resp = conn.getresponse() |
|
|
|
|
|
self.send_response(resp.status) |
|
for header in resp.headers: |
|
self.send_header(header, resp.headers[header]) |
|
self.end_headers() |
|
|
|
|
|
self.wfile.write(resp.read()) |
|
conn.close() |
|
except Exception as e: |
|
print(f"Proxy error: {e}", file=sys.stderr) |
|
self.send_response(500) |
|
self.send_header('Content-type', 'text/plain; charset=utf-8') |
|
self.end_headers() |
|
self.wfile.write(f"Proxy error: {e}".encode('utf-8')) |
|
|
|
|
|
port = 7860 |
|
print(f"Starting proxy server on port {port}, forwarding to Playground UI and API...") |
|
|
|
|
|
class ReuseAddressServer(socketserver.TCPServer): |
|
allow_reuse_address = True |
|
|
|
httpd = ReuseAddressServer(('0.0.0.0', port), ProxyHandler) |
|
httpd.serve_forever() |
|
|
|
except KeyboardInterrupt: |
|
print("Shutting down...") |
|
finally: |
|
|
|
for proc in processes: |
|
try: |
|
proc.terminate() |
|
proc.wait(timeout=5) |
|
except: |
|
proc.kill() |
|
|
|
return 0 |
|
|
|
if __name__ == "__main__": |
|
|
|
signal.signal(signal.SIGINT, lambda sig, frame: sys.exit(0)) |
|
signal.signal(signal.SIGTERM, lambda sig, frame: sys.exit(0)) |
|
|
|
sys.exit(main()) |