autoglm-gui 1.0.1__py3-none-any.whl → 1.1.0__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/adb_plus/__init__.py +7 -0
- AutoGLM_GUI/adb_plus/mdns.py +192 -0
- AutoGLM_GUI/adb_plus/pair.py +60 -0
- AutoGLM_GUI/adb_plus/qr_pair.py +372 -0
- AutoGLM_GUI/api/__init__.py +8 -0
- AutoGLM_GUI/api/devices.py +224 -1
- AutoGLM_GUI/schemas.py +70 -0
- AutoGLM_GUI/static/assets/{about-BOnRPlKQ.js → about-Crpy4Xue.js} +1 -1
- AutoGLM_GUI/static/assets/chat-DGFuSj6_.js +149 -0
- AutoGLM_GUI/static/assets/index-C1k5Ch1V.js +10 -0
- AutoGLM_GUI/static/assets/{index-CRFVU0eu.js → index-COYnSjzf.js} +1 -1
- AutoGLM_GUI/static/assets/index-QX6oy21q.css +1 -0
- AutoGLM_GUI/static/index.html +2 -2
- {autoglm_gui-1.0.1.dist-info → autoglm_gui-1.1.0.dist-info}/METADATA +45 -40
- {autoglm_gui-1.0.1.dist-info → autoglm_gui-1.1.0.dist-info}/RECORD +18 -15
- AutoGLM_GUI/static/assets/chat-CGW6uMKB.js +0 -149
- AutoGLM_GUI/static/assets/index-DH-Dl4tK.js +0 -10
- AutoGLM_GUI/static/assets/index-DzUQ89YC.css +0 -1
- {autoglm_gui-1.0.1.dist-info → autoglm_gui-1.1.0.dist-info}/WHEEL +0 -0
- {autoglm_gui-1.0.1.dist-info → autoglm_gui-1.1.0.dist-info}/entry_points.txt +0 -0
- {autoglm_gui-1.0.1.dist-info → autoglm_gui-1.1.0.dist-info}/licenses/LICENSE +0 -0
AutoGLM_GUI/api/devices.py
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from fastapi import APIRouter
|
|
4
4
|
|
|
5
|
-
from AutoGLM_GUI.adb_plus import get_wifi_ip, get_device_serial
|
|
5
|
+
from AutoGLM_GUI.adb_plus import get_wifi_ip, get_device_serial, pair_device
|
|
6
|
+
from AutoGLM_GUI.adb_plus.qr_pair import qr_pairing_manager
|
|
6
7
|
|
|
7
8
|
from AutoGLM_GUI.schemas import (
|
|
8
9
|
DeviceListResponse,
|
|
@@ -12,6 +13,13 @@ from AutoGLM_GUI.schemas import (
|
|
|
12
13
|
WiFiDisconnectResponse,
|
|
13
14
|
WiFiManualConnectRequest,
|
|
14
15
|
WiFiManualConnectResponse,
|
|
16
|
+
WiFiPairRequest,
|
|
17
|
+
WiFiPairResponse,
|
|
18
|
+
MdnsDiscoverResponse,
|
|
19
|
+
MdnsDeviceResponse,
|
|
20
|
+
QRPairGenerateResponse,
|
|
21
|
+
QRPairStatusResponse,
|
|
22
|
+
QRPairCancelResponse,
|
|
15
23
|
)
|
|
16
24
|
from AutoGLM_GUI.state import agents
|
|
17
25
|
|
|
@@ -166,3 +174,218 @@ def connect_wifi_manual(
|
|
|
166
174
|
message=f"Successfully connected to {address}",
|
|
167
175
|
device_id=address,
|
|
168
176
|
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@router.post("/api/devices/pair_wifi", response_model=WiFiPairResponse)
|
|
180
|
+
def pair_wifi(request: WiFiPairRequest) -> WiFiPairResponse:
|
|
181
|
+
"""使用无线调试配对并连接到 WiFi 设备 (Android 11+)."""
|
|
182
|
+
import re
|
|
183
|
+
|
|
184
|
+
from phone_agent.adb import ADBConnection
|
|
185
|
+
|
|
186
|
+
# IP 格式验证
|
|
187
|
+
ip_pattern = r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$"
|
|
188
|
+
if not re.match(ip_pattern, request.ip):
|
|
189
|
+
return WiFiPairResponse(
|
|
190
|
+
success=False,
|
|
191
|
+
message="Invalid IP address format",
|
|
192
|
+
error="invalid_ip",
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# 配对端口验证
|
|
196
|
+
if not (1 <= request.pairing_port <= 65535):
|
|
197
|
+
return WiFiPairResponse(
|
|
198
|
+
success=False,
|
|
199
|
+
message="Pairing port must be between 1 and 65535",
|
|
200
|
+
error="invalid_port",
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# 连接端口验证
|
|
204
|
+
if not (1 <= request.connection_port <= 65535):
|
|
205
|
+
return WiFiPairResponse(
|
|
206
|
+
success=False,
|
|
207
|
+
message="Connection port must be between 1 and 65535",
|
|
208
|
+
error="invalid_port",
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# 配对码验证 (6 位数字)
|
|
212
|
+
if not request.pairing_code.isdigit() or len(request.pairing_code) != 6:
|
|
213
|
+
return WiFiPairResponse(
|
|
214
|
+
success=False,
|
|
215
|
+
message="Pairing code must be 6 digits",
|
|
216
|
+
error="invalid_pairing_code",
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
conn = ADBConnection()
|
|
220
|
+
|
|
221
|
+
# 步骤 1: 配对设备
|
|
222
|
+
ok, msg = pair_device(
|
|
223
|
+
ip=request.ip,
|
|
224
|
+
port=request.pairing_port,
|
|
225
|
+
pairing_code=request.pairing_code,
|
|
226
|
+
adb_path=conn.adb_path,
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
if not ok:
|
|
230
|
+
return WiFiPairResponse(
|
|
231
|
+
success=False,
|
|
232
|
+
message=msg,
|
|
233
|
+
error="pair_failed",
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# 步骤 2: 使用标准 ADB 端口连接到设备
|
|
237
|
+
connection_address = f"{request.ip}:{request.connection_port}"
|
|
238
|
+
ok, connect_msg = conn.connect(connection_address)
|
|
239
|
+
|
|
240
|
+
if not ok:
|
|
241
|
+
return WiFiPairResponse(
|
|
242
|
+
success=False,
|
|
243
|
+
message=f"Paired successfully but connection failed: {connect_msg}",
|
|
244
|
+
error="connect_failed",
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
return WiFiPairResponse(
|
|
248
|
+
success=True,
|
|
249
|
+
message=f"Successfully paired and connected to {connection_address}",
|
|
250
|
+
device_id=connection_address,
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
@router.get("/api/devices/discover_mdns", response_model=MdnsDiscoverResponse)
|
|
255
|
+
def discover_mdns() -> MdnsDiscoverResponse:
|
|
256
|
+
"""Discover wireless ADB devices via mDNS."""
|
|
257
|
+
from phone_agent.adb import ADBConnection
|
|
258
|
+
from AutoGLM_GUI.adb_plus import discover_mdns_devices
|
|
259
|
+
|
|
260
|
+
try:
|
|
261
|
+
conn = ADBConnection()
|
|
262
|
+
devices = discover_mdns_devices(conn.adb_path)
|
|
263
|
+
|
|
264
|
+
device_responses = [
|
|
265
|
+
MdnsDeviceResponse(
|
|
266
|
+
name=dev.name,
|
|
267
|
+
ip=dev.ip,
|
|
268
|
+
port=dev.port,
|
|
269
|
+
has_pairing=dev.has_pairing,
|
|
270
|
+
service_type=dev.service_type,
|
|
271
|
+
pairing_port=dev.pairing_port,
|
|
272
|
+
)
|
|
273
|
+
for dev in devices
|
|
274
|
+
]
|
|
275
|
+
|
|
276
|
+
return MdnsDiscoverResponse(
|
|
277
|
+
success=True,
|
|
278
|
+
devices=device_responses,
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
except Exception as e:
|
|
282
|
+
return MdnsDiscoverResponse(
|
|
283
|
+
success=False,
|
|
284
|
+
devices=[],
|
|
285
|
+
error=str(e),
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
# QR Code Pairing Routes
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
@router.post("/api/devices/qr_pair/generate", response_model=QRPairGenerateResponse)
|
|
293
|
+
def generate_qr_pairing(timeout: int = 90) -> QRPairGenerateResponse:
|
|
294
|
+
"""Generate QR code for wireless pairing and start mDNS listener.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
timeout: Session timeout in seconds (default 90)
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
QR code payload and session information
|
|
301
|
+
"""
|
|
302
|
+
try:
|
|
303
|
+
from phone_agent.adb import ADBConnection
|
|
304
|
+
|
|
305
|
+
conn = ADBConnection()
|
|
306
|
+
session = qr_pairing_manager.create_session(
|
|
307
|
+
timeout=timeout, adb_path=conn.adb_path
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
return QRPairGenerateResponse(
|
|
311
|
+
success=True,
|
|
312
|
+
qr_payload=session.qr_payload,
|
|
313
|
+
session_id=session.session_id,
|
|
314
|
+
expires_at=session.expires_at,
|
|
315
|
+
message="QR code generated, listening for devices...",
|
|
316
|
+
)
|
|
317
|
+
except Exception as e:
|
|
318
|
+
return QRPairGenerateResponse(
|
|
319
|
+
success=False,
|
|
320
|
+
message=f"Failed to generate QR pairing: {str(e)}",
|
|
321
|
+
error="generation_failed",
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def _get_status_message(status: str) -> str:
|
|
326
|
+
"""Get user-friendly message for status code."""
|
|
327
|
+
messages = {
|
|
328
|
+
"listening": "等待手机扫描二维码...",
|
|
329
|
+
"pairing": "正在配对设备...",
|
|
330
|
+
"paired": "配对成功,正在连接...",
|
|
331
|
+
"connecting": "正在建立连接...",
|
|
332
|
+
"connected": "连接成功!",
|
|
333
|
+
"timeout": "超时:未检测到设备扫码",
|
|
334
|
+
"error": "配对失败",
|
|
335
|
+
}
|
|
336
|
+
return messages.get(status, "未知状态")
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
@router.get(
|
|
340
|
+
"/api/devices/qr_pair/status/{session_id}", response_model=QRPairStatusResponse
|
|
341
|
+
)
|
|
342
|
+
def get_qr_pairing_status(session_id: str) -> QRPairStatusResponse:
|
|
343
|
+
"""Get current status of a QR pairing session.
|
|
344
|
+
|
|
345
|
+
Args:
|
|
346
|
+
session_id: Session UUID
|
|
347
|
+
|
|
348
|
+
Returns:
|
|
349
|
+
Current session status and device information if connected
|
|
350
|
+
"""
|
|
351
|
+
session = qr_pairing_manager.get_session(session_id)
|
|
352
|
+
|
|
353
|
+
if not session:
|
|
354
|
+
return QRPairStatusResponse(
|
|
355
|
+
session_id=session_id,
|
|
356
|
+
status="error",
|
|
357
|
+
message="Session not found or expired",
|
|
358
|
+
error="session_not_found",
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
return QRPairStatusResponse(
|
|
362
|
+
session_id=session.session_id,
|
|
363
|
+
status=session.status,
|
|
364
|
+
device_id=session.device_id,
|
|
365
|
+
message=_get_status_message(session.status),
|
|
366
|
+
error=session.error_message,
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
@router.delete("/api/devices/qr_pair/{session_id}", response_model=QRPairCancelResponse)
|
|
371
|
+
def cancel_qr_pairing(session_id: str) -> QRPairCancelResponse:
|
|
372
|
+
"""Cancel an active QR pairing session.
|
|
373
|
+
|
|
374
|
+
Args:
|
|
375
|
+
session_id: Session UUID to cancel
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
Success status
|
|
379
|
+
"""
|
|
380
|
+
success = qr_pairing_manager.cancel_session(session_id)
|
|
381
|
+
|
|
382
|
+
if success:
|
|
383
|
+
return QRPairCancelResponse(
|
|
384
|
+
success=True,
|
|
385
|
+
message="Pairing session cancelled",
|
|
386
|
+
)
|
|
387
|
+
else:
|
|
388
|
+
return QRPairCancelResponse(
|
|
389
|
+
success=False,
|
|
390
|
+
message="Session not found or already completed",
|
|
391
|
+
)
|
AutoGLM_GUI/schemas.py
CHANGED
|
@@ -193,6 +193,24 @@ class WiFiManualConnectResponse(BaseModel):
|
|
|
193
193
|
error: str | None = None
|
|
194
194
|
|
|
195
195
|
|
|
196
|
+
class WiFiPairRequest(BaseModel):
|
|
197
|
+
"""WiFi pairing request (Android 11+ wireless debugging)."""
|
|
198
|
+
|
|
199
|
+
ip: str # Device IP address
|
|
200
|
+
pairing_port: int # Pairing port (from "Pair device with code" dialog)
|
|
201
|
+
pairing_code: str # 6-digit pairing code
|
|
202
|
+
connection_port: int = 5555 # Standard ADB connection port (default 5555)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class WiFiPairResponse(BaseModel):
|
|
206
|
+
"""WiFi pairing response."""
|
|
207
|
+
|
|
208
|
+
success: bool
|
|
209
|
+
message: str
|
|
210
|
+
device_id: str | None = None # Device ID after connection (ip:connection_port)
|
|
211
|
+
error: str | None = None # Error code for frontend handling
|
|
212
|
+
|
|
213
|
+
|
|
196
214
|
class VersionCheckResponse(BaseModel):
|
|
197
215
|
"""Version update check response."""
|
|
198
216
|
|
|
@@ -202,3 +220,55 @@ class VersionCheckResponse(BaseModel):
|
|
|
202
220
|
release_url: str | None = None
|
|
203
221
|
published_at: str | None = None
|
|
204
222
|
error: str | None = None
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class MdnsDeviceResponse(BaseModel):
|
|
226
|
+
"""Single mDNS-discovered device."""
|
|
227
|
+
|
|
228
|
+
name: str # Device name (e.g., "adb-243a09b7-cbCO6P")
|
|
229
|
+
ip: str # IP address
|
|
230
|
+
port: int # Port number
|
|
231
|
+
has_pairing: bool # Whether pairing service was also advertised
|
|
232
|
+
service_type: str # Service type
|
|
233
|
+
pairing_port: int | None = None # Pairing port if has_pairing is True
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
class MdnsDiscoverResponse(BaseModel):
|
|
237
|
+
"""mDNS device discovery response."""
|
|
238
|
+
|
|
239
|
+
success: bool
|
|
240
|
+
devices: list[MdnsDeviceResponse]
|
|
241
|
+
error: str | None = None
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# QR Code Pairing Models
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class QRPairGenerateResponse(BaseModel):
|
|
248
|
+
"""QR code pairing generation response."""
|
|
249
|
+
|
|
250
|
+
success: bool
|
|
251
|
+
qr_payload: str | None = (
|
|
252
|
+
None # QR text payload (WIFI:T:ADB;S:{name};P:{password};;)
|
|
253
|
+
)
|
|
254
|
+
session_id: str | None = None # Session tracking ID (UUID)
|
|
255
|
+
expires_at: float | None = None # Unix timestamp when session expires
|
|
256
|
+
message: str
|
|
257
|
+
error: str | None = None # Error code for frontend handling
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class QRPairStatusResponse(BaseModel):
|
|
261
|
+
"""QR code pairing status response."""
|
|
262
|
+
|
|
263
|
+
session_id: str
|
|
264
|
+
status: str # "listening" | "pairing" | "paired" | "connecting" | "connected" | "timeout" | "error"
|
|
265
|
+
device_id: str | None = None # Device ID when connected (ip:port)
|
|
266
|
+
message: str
|
|
267
|
+
error: str | None = None # Error details
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class QRPairCancelResponse(BaseModel):
|
|
271
|
+
"""QR code pairing cancellation response."""
|
|
272
|
+
|
|
273
|
+
success: bool
|
|
274
|
+
message: str
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as o}from"./index-
|
|
1
|
+
import{j as o}from"./index-C1k5Ch1V.js";function t(){return o.jsx("div",{className:"p-2",children:o.jsx("h3",{children:"About"})})}export{t as component};
|