autoglm-gui 0.4.9__py3-none-any.whl → 0.4.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- AutoGLM_GUI/__init__.py +8 -0
- AutoGLM_GUI/__main__.py +64 -21
- AutoGLM_GUI/adb_plus/__init__.py +8 -0
- AutoGLM_GUI/adb_plus/device.py +50 -0
- AutoGLM_GUI/adb_plus/ip.py +78 -0
- AutoGLM_GUI/adb_plus/keyboard_installer.py +380 -0
- AutoGLM_GUI/adb_plus/serial.py +35 -0
- AutoGLM_GUI/api/__init__.py +8 -0
- AutoGLM_GUI/api/agents.py +132 -1
- AutoGLM_GUI/api/devices.py +96 -6
- AutoGLM_GUI/api/media.py +13 -243
- AutoGLM_GUI/config_manager.py +565 -0
- AutoGLM_GUI/exceptions.py +7 -0
- AutoGLM_GUI/logger.py +85 -0
- AutoGLM_GUI/platform_utils.py +30 -5
- AutoGLM_GUI/schemas.py +50 -0
- AutoGLM_GUI/scrcpy_protocol.py +46 -0
- AutoGLM_GUI/scrcpy_stream.py +208 -327
- AutoGLM_GUI/server.py +7 -2
- AutoGLM_GUI/socketio_server.py +125 -0
- AutoGLM_GUI/state.py +2 -1
- AutoGLM_GUI/static/assets/{about-BI6OV6gm.js → about-kgOkkOWe.js} +1 -1
- AutoGLM_GUI/static/assets/chat-CZV3RByK.js +149 -0
- AutoGLM_GUI/static/assets/{index-Do7ha9Kf.js → index-BPYHsweG.js} +1 -1
- AutoGLM_GUI/static/assets/index-Beu9cbSy.css +1 -0
- AutoGLM_GUI/static/assets/index-DfI_Z1Cx.js +10 -0
- AutoGLM_GUI/static/assets/worker-D6BRitjy.js +1 -0
- AutoGLM_GUI/static/index.html +2 -2
- {autoglm_gui-0.4.9.dist-info → autoglm_gui-0.4.12.dist-info}/METADATA +15 -2
- autoglm_gui-0.4.12.dist-info/RECORD +56 -0
- AutoGLM_GUI/static/assets/chat-C_2Cot0q.js +0 -25
- AutoGLM_GUI/static/assets/index-DCrxTz-A.css +0 -1
- AutoGLM_GUI/static/assets/index-Dn3vR6uV.js +0 -10
- autoglm_gui-0.4.9.dist-info/RECORD +0 -46
- {autoglm_gui-0.4.9.dist-info → autoglm_gui-0.4.12.dist-info}/WHEEL +0 -0
- {autoglm_gui-0.4.9.dist-info → autoglm_gui-0.4.12.dist-info}/entry_points.txt +0 -0
- {autoglm_gui-0.4.9.dist-info → autoglm_gui-0.4.12.dist-info}/licenses/LICENSE +0 -0
AutoGLM_GUI/server.py
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
"""AutoGLM-GUI Backend API Server."""
|
|
1
|
+
"""AutoGLM-GUI Backend API Server (FastAPI + Socket.IO)."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from socketio import ASGIApp
|
|
4
|
+
|
|
5
|
+
from AutoGLM_GUI.api import app as fastapi_app
|
|
6
|
+
from AutoGLM_GUI.socketio_server import sio
|
|
7
|
+
|
|
8
|
+
app = ASGIApp(sio, other_asgi_app=fastapi_app)
|
|
4
9
|
|
|
5
10
|
__all__ = ["app"]
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""Socket.IO server for Scrcpy video streaming."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import time
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import socketio
|
|
10
|
+
|
|
11
|
+
from AutoGLM_GUI.logger import logger
|
|
12
|
+
from AutoGLM_GUI.scrcpy_protocol import ScrcpyMediaStreamPacket
|
|
13
|
+
from AutoGLM_GUI.scrcpy_stream import ScrcpyStreamer
|
|
14
|
+
|
|
15
|
+
sio = socketio.AsyncServer(
|
|
16
|
+
async_mode="asgi",
|
|
17
|
+
cors_allowed_origins="*",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
_socket_streamers: dict[str, ScrcpyStreamer] = {}
|
|
21
|
+
_stream_tasks: dict[str, asyncio.Task] = {}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
async def _stop_stream_for_sid(sid: str) -> None:
|
|
25
|
+
task = _stream_tasks.pop(sid, None)
|
|
26
|
+
if task:
|
|
27
|
+
task.cancel()
|
|
28
|
+
|
|
29
|
+
streamer = _socket_streamers.pop(sid, None)
|
|
30
|
+
if streamer:
|
|
31
|
+
streamer.stop()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def stop_streamers(device_id: str | None = None) -> None:
|
|
35
|
+
"""Stop active scrcpy streamers (all or by device)."""
|
|
36
|
+
sids = list(_socket_streamers.keys())
|
|
37
|
+
for sid in sids:
|
|
38
|
+
streamer = _socket_streamers.get(sid)
|
|
39
|
+
if not streamer:
|
|
40
|
+
continue
|
|
41
|
+
if device_id and streamer.device_id != device_id:
|
|
42
|
+
continue
|
|
43
|
+
task = _stream_tasks.pop(sid, None)
|
|
44
|
+
if task:
|
|
45
|
+
task.cancel()
|
|
46
|
+
streamer.stop()
|
|
47
|
+
_socket_streamers.pop(sid, None)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
async def _stream_packets(sid: str, streamer: ScrcpyStreamer) -> None:
|
|
51
|
+
try:
|
|
52
|
+
async for packet in streamer.iter_packets():
|
|
53
|
+
payload = _packet_to_payload(packet)
|
|
54
|
+
await sio.emit("video-data", payload, to=sid)
|
|
55
|
+
except asyncio.CancelledError:
|
|
56
|
+
raise
|
|
57
|
+
except Exception as exc:
|
|
58
|
+
logger.exception("Video streaming failed: %s", exc)
|
|
59
|
+
try:
|
|
60
|
+
await sio.emit("error", {"message": str(exc)}, to=sid)
|
|
61
|
+
except Exception:
|
|
62
|
+
pass
|
|
63
|
+
finally:
|
|
64
|
+
await _stop_stream_for_sid(sid)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _packet_to_payload(packet: ScrcpyMediaStreamPacket) -> dict[str, Any]:
|
|
68
|
+
payload: dict[str, Any] = {
|
|
69
|
+
"type": packet.type,
|
|
70
|
+
"data": packet.data,
|
|
71
|
+
"timestamp": int(time.time() * 1000),
|
|
72
|
+
}
|
|
73
|
+
if packet.type == "data":
|
|
74
|
+
payload["keyframe"] = packet.keyframe
|
|
75
|
+
payload["pts"] = packet.pts
|
|
76
|
+
return payload
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@sio.event
|
|
80
|
+
async def connect(sid: str, environ: dict) -> None:
|
|
81
|
+
logger.info("Socket.IO client connected: %s", sid)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@sio.event
|
|
85
|
+
async def disconnect(sid: str) -> None:
|
|
86
|
+
logger.info("Socket.IO client disconnected: %s", sid)
|
|
87
|
+
await _stop_stream_for_sid(sid)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@sio.on("connect-device")
|
|
91
|
+
async def connect_device(sid: str, data: dict | None) -> None:
|
|
92
|
+
payload = data or {}
|
|
93
|
+
device_id = payload.get("device_id") or payload.get("deviceId")
|
|
94
|
+
max_size = int(payload.get("maxSize") or 1280)
|
|
95
|
+
bit_rate = int(payload.get("bitRate") or 4_000_000)
|
|
96
|
+
|
|
97
|
+
await _stop_stream_for_sid(sid)
|
|
98
|
+
|
|
99
|
+
streamer = ScrcpyStreamer(
|
|
100
|
+
device_id=device_id,
|
|
101
|
+
max_size=max_size,
|
|
102
|
+
bit_rate=bit_rate,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
await streamer.start()
|
|
107
|
+
metadata = await streamer.read_video_metadata()
|
|
108
|
+
await sio.emit(
|
|
109
|
+
"video-metadata",
|
|
110
|
+
{
|
|
111
|
+
"deviceName": metadata.device_name,
|
|
112
|
+
"width": metadata.width,
|
|
113
|
+
"height": metadata.height,
|
|
114
|
+
"codec": metadata.codec,
|
|
115
|
+
},
|
|
116
|
+
to=sid,
|
|
117
|
+
)
|
|
118
|
+
except Exception as exc:
|
|
119
|
+
streamer.stop()
|
|
120
|
+
logger.exception("Failed to start scrcpy stream: %s", exc)
|
|
121
|
+
await sio.emit("error", {"message": str(exc)}, to=sid)
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
_socket_streamers[sid] = streamer
|
|
125
|
+
_stream_tasks[sid] = asyncio.create_task(_stream_packets(sid, streamer))
|
AutoGLM_GUI/state.py
CHANGED
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import asyncio
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
7
|
|
|
8
|
+
from AutoGLM_GUI.logger import logger
|
|
8
9
|
from phone_agent.agent import AgentConfig
|
|
9
10
|
from phone_agent.model import ModelConfig
|
|
10
11
|
|
|
@@ -24,4 +25,4 @@ scrcpy_locks: dict[str, asyncio.Lock] = {}
|
|
|
24
25
|
|
|
25
26
|
def non_blocking_takeover(message: str) -> None:
|
|
26
27
|
"""Log takeover requests without blocking for console input."""
|
|
27
|
-
|
|
28
|
+
logger.warning(f"Takeover requested: {message}")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as o}from"./index-
|
|
1
|
+
import{j as o}from"./index-DfI_Z1Cx.js";function t(){return o.jsx("div",{className:"p-2",children:o.jsx("h3",{children:"About"})})}export{t as component};
|