Bjo53 commited on
Commit
c07dd5a
·
verified ·
1 Parent(s): 415b036

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +52 -37
app.py CHANGED
@@ -1,5 +1,9 @@
1
  import os
 
2
  import asyncio
 
 
 
3
  import json
4
  import subprocess
5
 
@@ -10,8 +14,6 @@ from fastapi.staticfiles import StaticFiles
10
  app = FastAPI()
11
  app.mount("/static", StaticFiles(directory="static"), name="static")
12
 
13
- SESSION_NAME = "main"
14
-
15
  @app.get("/")
16
  async def index():
17
  return FileResponse("static/index.html")
@@ -20,55 +22,64 @@ async def index():
20
  async def get_pass():
21
  return {"pass": os.environ.get("TERMINAL_PASS", "")}
22
 
23
- def ensure_session():
24
- result = subprocess.run(
25
- ["tmux", "has-session", "-t", SESSION_NAME],
26
- capture_output=True
27
- )
28
- if result.returncode != 0:
29
- subprocess.run([
30
- "tmux", "new-session", "-d", "-s", SESSION_NAME,
31
- "-x", "200", "-y", "50"
32
- ])
33
-
34
  @app.websocket("/ws")
35
  async def terminal(websocket: WebSocket):
36
  await websocket.accept()
37
- ensure_session()
 
38
 
39
  proc = await asyncio.create_subprocess_exec(
40
- "tmux", "attach", "-t", SESSION_NAME,
41
- stdin=asyncio.subprocess.PIPE,
42
- stdout=asyncio.subprocess.PIPE,
43
- stderr=asyncio.subprocess.PIPE
 
 
 
 
 
 
44
  )
45
 
46
- async def read_output():
 
 
 
 
47
  while True:
48
  try:
49
- data = await proc.stdout.read(4096)
50
- if not data:
51
- break
52
- await websocket.send_text(data.decode("utf-8", errors="ignore"))
53
- except:
 
 
 
 
 
 
54
  break
55
 
56
- read_task = asyncio.create_task(read_output())
57
 
58
  try:
59
  while True:
60
  message = await websocket.receive_text()
61
- msg = json.loads(message)
62
- if msg.get("type") == "input":
63
- proc.stdin.write(msg["data"].encode("utf-8"))
64
- await proc.stdin.drain()
65
- elif msg.get("type") == "resize":
66
- cols = msg.get("cols", 80)
67
- rows = msg.get("rows", 24)
68
- subprocess.run([
69
- "tmux", "resize-window", "-t", SESSION_NAME,
70
- "-x", str(cols), "-y", str(rows)
71
- ])
 
 
 
72
  except (WebSocketDisconnect, Exception):
73
  pass
74
  finally:
@@ -76,5 +87,9 @@ async def terminal(websocket: WebSocket):
76
  try:
77
  proc.terminate()
78
  await asyncio.wait_for(proc.wait(), timeout=2)
79
- except:
80
  proc.kill()
 
 
 
 
 
1
  import os
2
+ import pty
3
  import asyncio
4
+ import struct
5
+ import fcntl
6
+ import termios
7
  import json
8
  import subprocess
9
 
 
14
  app = FastAPI()
15
  app.mount("/static", StaticFiles(directory="static"), name="static")
16
 
 
 
17
  @app.get("/")
18
  async def index():
19
  return FileResponse("static/index.html")
 
22
  async def get_pass():
23
  return {"pass": os.environ.get("TERMINAL_PASS", "")}
24
 
 
 
 
 
 
 
 
 
 
 
 
25
  @app.websocket("/ws")
26
  async def terminal(websocket: WebSocket):
27
  await websocket.accept()
28
+
29
+ master_fd, slave_fd = pty.openpty()
30
 
31
  proc = await asyncio.create_subprocess_exec(
32
+ "/bin/bash",
33
+ stdin=slave_fd,
34
+ stdout=slave_fd,
35
+ stderr=slave_fd,
36
+ env={
37
+ **os.environ,
38
+ "TERM": "xterm-256color",
39
+ "HOME": "/persistent",
40
+ "USER": "ubuntu"
41
+ }
42
  )
43
 
44
+ os.close(slave_fd)
45
+
46
+ loop = asyncio.get_event_loop()
47
+
48
+ async def read_pty():
49
  while True:
50
  try:
51
+ data = await loop.run_in_executor(
52
+ None,
53
+ lambda: os.read(master_fd, 4096)
54
+ )
55
+ if data:
56
+ try:
57
+ text = data.decode("utf-8")
58
+ except UnicodeDecodeError:
59
+ text = data.decode("utf-8", errors="ignore")
60
+ await websocket.send_text(text)
61
+ except OSError:
62
  break
63
 
64
+ read_task = asyncio.create_task(read_pty())
65
 
66
  try:
67
  while True:
68
  message = await websocket.receive_text()
69
+ try:
70
+ msg = json.loads(message)
71
+ if msg.get("type") == "input":
72
+ os.write(master_fd, msg["data"].encode("utf-8"))
73
+ elif msg.get("type") == "resize":
74
+ cols = msg.get("cols", 80)
75
+ rows = msg.get("rows", 24)
76
+ fcntl.ioctl(
77
+ master_fd,
78
+ termios.TIOCSWINSZ,
79
+ struct.pack("HHHH", rows, cols, 0, 0)
80
+ )
81
+ except (json.JSONDecodeError, OSError):
82
+ break
83
  except (WebSocketDisconnect, Exception):
84
  pass
85
  finally:
 
87
  try:
88
  proc.terminate()
89
  await asyncio.wait_for(proc.wait(), timeout=2)
90
+ except Exception:
91
  proc.kill()
92
+ try:
93
+ os.close(master_fd)
94
+ except:
95
+ pass