Skip to content

Commit da987d5

Browse files
committed
refactor: remove ~780 lines of dead code
1 parent fdfb089 commit da987d5

22 files changed

Lines changed: 2 additions & 1623 deletions

File tree

api_utils/auth_manager.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,6 @@ def mark_profile_failed(self, profile_path: Optional[str] = None) -> None:
7878
"Attempted to mark profile failed but no profile provided or active."
7979
)
8080

81-
def reset_failures(self) -> None:
82-
"""Reset the failure tracking."""
83-
self.failed_profiles.clear()
84-
logger.info("Auth profile failure tracking reset.")
85-
8681

8782
# Global instance
8883
auth_manager = AuthManager()

api_utils/client_connection.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
11
import asyncio
22
from asyncio import Event, Task
33
from logging import Logger
4-
from typing import Any, Callable, Coroutine, Dict, Protocol, Tuple
4+
from typing import Any, Callable, Coroutine, Dict, Tuple
55

66
from fastapi import HTTPException, Request
77

88
from logging_utils import set_request_id
99
from models import ClientDisconnectedError
1010

1111

12-
class SupportsReceive(Protocol):
13-
"""Protocol for request objects that support _receive method."""
14-
15-
def _receive(self) -> Coroutine[Any, Any, Dict[str, Any]]:
16-
"""Internal method to receive messages from ASGI."""
17-
...
18-
19-
2012
async def check_client_connection(req_id: str, http_request: Request) -> bool:
2113
"""
2214
Checks if the client is still connected.

api_utils/mcp_adapter.py

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -55,39 +55,3 @@ async def execute_mcp_tool_with_endpoint(
5555
except Exception:
5656
data = {"raw": resp.text}
5757
return json.dumps(data, ensure_ascii=False)
58-
59-
60-
# Synchronous helpers for use inside threads
61-
def execute_mcp_tool_sync(name: str, params: Dict[str, Any]) -> str:
62-
ep = os.environ.get("MCP_HTTP_ENDPOINT")
63-
if not ep:
64-
raise RuntimeError("MCP_HTTP_ENDPOINT not configured")
65-
url = f"{_normalize_endpoint(ep)}/tools/execute"
66-
payload = {"name": name, "arguments": params}
67-
headers = {"Content-Type": "application/json"}
68-
timeout = float(os.environ.get("MCP_HTTP_TIMEOUT", "15"))
69-
with httpx.Client(timeout=timeout) as client:
70-
resp = client.post(url, json=payload, headers=headers)
71-
resp.raise_for_status()
72-
try:
73-
data = resp.json()
74-
except Exception:
75-
data = {"raw": resp.text}
76-
return json.dumps(data, ensure_ascii=False)
77-
78-
79-
def execute_mcp_tool_with_endpoint_sync(
80-
endpoint: str, name: str, params: Dict[str, Any]
81-
) -> str:
82-
url = f"{_normalize_endpoint(endpoint)}/tools/execute"
83-
payload = {"name": name, "arguments": params}
84-
headers = {"Content-Type": "application/json"}
85-
timeout = float(os.environ.get("MCP_HTTP_TIMEOUT", "15"))
86-
with httpx.Client(timeout=timeout) as client:
87-
resp = client.post(url, json=payload, headers=headers)
88-
resp.raise_for_status()
89-
try:
90-
data = resp.json()
91-
except Exception:
92-
data = {"raw": resp.text}
93-
return json.dumps(data, ensure_ascii=False)

api_utils/response_generators.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,8 @@ async def gen_sse_from_aux_stream(
5050
full_body_content = ""
5151
data_receiving = False
5252

53-
loop_count = 0
54-
5553
try:
5654
async for raw_data in use_stream_response(req_id):
57-
loop_count += 1
58-
# logger.debug(f"[{req_id}] gen_sse_from_aux_stream loop iteration #{loop_count}")
59-
6055
data_receiving = True
6156

6257
try:

api_utils/server_state.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,18 +99,6 @@ def clear_debug_logs(self) -> None:
9999
self.console_logs = []
100100
self.network_log = {"requests": [], "responses": []}
101101

102-
def get_server_status(self) -> Dict[str, Any]:
103-
"""Get current server status as a dictionary."""
104-
return {
105-
"is_initializing": self.is_initializing,
106-
"is_playwright_ready": self.is_playwright_ready,
107-
"is_browser_connected": self.is_browser_connected,
108-
"is_page_ready": self.is_page_ready,
109-
"current_model": self.current_ai_studio_model_id,
110-
"queue_size": self.request_queue.qsize() if self.request_queue else 0,
111-
"worker_running": bool(self.worker_task and not self.worker_task.done()),
112-
}
113-
114102

115103
# Global singleton instance
116104
state = ServerState()

browser_utils/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
save_error_snapshot,
3535
)
3636
from .page_controller import PageController
37-
from .script_manager import ScriptManager, script_manager
3837

3938
__all__ = [
4039
# 初始化相关
@@ -60,9 +59,6 @@
6059
"_force_ui_state_settings",
6160
"_force_ui_state_with_retry",
6261
"_verify_and_apply_ui_state",
63-
# 脚本管理相关
64-
"ScriptManager",
65-
"script_manager",
6662
# Page Controller
6763
"PageController",
6864
# Debug utilities (comprehensive error snapshots)

browser_utils/operations_modules/interactions.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,6 @@ async def _wait_for_response_completion(
349349
edit_button_locator: Locator,
350350
req_id: str,
351351
check_client_disconnected_func: Callable,
352-
current_chat_id: Optional[str],
353352
timeout_ms=RESPONSE_COMPLETION_TIMEOUT,
354353
initial_wait_ms=INITIAL_WAIT_MS_BEFORE_POLLING,
355354
) -> bool:

browser_utils/page_controller_modules/chat.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,6 @@ async def _execute_chat_clear(
290290
else:
291291
raise
292292

293-
await self._check_disconnect(
294-
check_client_disconnected,
295-
f"清空聊天 - 消失检查尝试 {attempt_disappear + 1} 后",
296-
)
297-
298293
async def _dismiss_backdrops(self):
299294
"""尝试关闭可能残留的 cdk 透明遮罩层以避免点击被拦截。"""
300295
try:

browser_utils/page_controller_modules/input.py

Lines changed: 0 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import asyncio
2-
import base64
3-
import mimetypes
42
from typing import Callable, List
53

64
from playwright.async_api import TimeoutError
@@ -16,7 +14,6 @@
1614
)
1715
from config.selector_utils import (
1816
AUTOSIZE_WRAPPER_SELECTORS,
19-
DRAG_DROP_TARGET_SELECTORS,
2017
build_combined_selector,
2118
)
2219
from logging_utils import set_request_id
@@ -328,152 +325,6 @@ async def _handle_post_upload_dialog(self):
328325
except Exception:
329326
pass
330327

331-
async def _ensure_files_attached(
332-
self, wrapper_locator, expected_min: int = 1, timeout_ms: int = 5000
333-
) -> bool:
334-
"""轮询检查输入区域内 file input 的 files 是否 >= 期望数量。"""
335-
end = asyncio.get_event_loop().time() + (timeout_ms / 1000)
336-
while asyncio.get_event_loop().time() < end:
337-
try:
338-
# NOTE: normalize JS eval string to avoid parser confusion
339-
counts = await wrapper_locator.evaluate(
340-
"""
341-
(el) => {
342-
const result = {inputs:0, chips:0, blobs:0};
343-
try { el.querySelectorAll('input[type="file"]').forEach(i => { result.inputs += (i.files ? i.files.length : 0); }); } catch(e){}
344-
try { result.chips = el.querySelectorAll('button[aria-label*="Remove" i], button[aria-label*="asset" i]').length; } catch(e){}
345-
try { result.blobs = el.querySelectorAll('img[src^="blob:"], video[src^="blob:"]').length; } catch(e){}
346-
return result;
347-
}
348-
"""
349-
)
350-
351-
total = 0
352-
if isinstance(counts, dict):
353-
total = max(
354-
int(counts.get("inputs") or 0),
355-
int(counts.get("chips") or 0),
356-
int(counts.get("blobs") or 0),
357-
)
358-
if total >= expected_min:
359-
self.logger.info(
360-
f" 已检测到已附加文件: inputs={counts.get('inputs')}, chips={counts.get('chips')}, blobs={counts.get('blobs')} (>= {expected_min})"
361-
)
362-
return True
363-
except asyncio.CancelledError:
364-
raise
365-
except Exception:
366-
pass
367-
await asyncio.sleep(0.2)
368-
self.logger.warning(f" 未能在超时内检测到已附加文件 (期望 >= {expected_min})")
369-
return False
370-
371-
async def _simulate_drag_drop_files(
372-
self, target_locator, files_list: List[str]
373-
) -> None:
374-
"""将本地文件以拖放事件的方式注入到目标元素。
375-
仅负责触发 dragenter/dragover/drop,不在此处做附加验证以节省时间。
376-
"""
377-
payloads = []
378-
for path in files_list:
379-
try:
380-
with open(path, "rb") as f:
381-
raw = f.read()
382-
b64 = base64.b64encode(raw).decode("ascii")
383-
mime, _ = mimetypes.guess_type(path)
384-
payloads.append(
385-
{
386-
"name": path.split("/")[-1],
387-
"mime": mime or "application/octet-stream",
388-
"b64": b64,
389-
}
390-
)
391-
except Exception as e:
392-
self.logger.warning(f" 读取文件失败,跳过拖放: {path} - {e}")
393-
394-
if not payloads:
395-
raise Exception("无可用文件用于拖放")
396-
397-
# 使用集中管理的选择器列表作为拖放候选目标
398-
candidates = [target_locator, self.page.locator(PROMPT_TEXTAREA_SELECTOR)]
399-
candidates.extend(
400-
[self.page.locator(sel) for sel in DRAG_DROP_TARGET_SELECTORS]
401-
)
402-
403-
last_err = None
404-
for idx, cand in enumerate(candidates):
405-
try:
406-
await expect_async(cand).to_be_visible(timeout=3000)
407-
await cand.evaluate(
408-
"""
409-
(el, files) => {
410-
const dt = new DataTransfer();
411-
for (const p of files) {
412-
const bstr = atob(p.b64);
413-
const len = bstr.length;
414-
const u8 = new Uint8Array(len);
415-
for (let i = 0; i < len; i++) u8[i] = bstr.charCodeAt(i);
416-
const blob = new Blob([u8], { type: p.mime || 'application/octet-stream' });
417-
const file = new File([blob], p.name, { type: p.mime || 'application/octet-stream' });
418-
dt.items.add(file);
419-
}
420-
const evEnter = new DragEvent('dragenter', { bubbles: true, cancelable: true, dataTransfer: dt });
421-
el.dispatchEvent(evEnter);
422-
const evOver = new DragEvent('dragover', { bubbles: true, cancelable: true, dataTransfer: dt });
423-
el.dispatchEvent(evOver);
424-
const evDrop = new DragEvent('drop', { bubbles: true, cancelable: true, dataTransfer: dt });
425-
el.dispatchEvent(evDrop);
426-
}
427-
""",
428-
payloads,
429-
)
430-
await asyncio.sleep(0.5)
431-
self.logger.info(
432-
f" 拖放事件已在候选目标 {idx + 1}/{len(candidates)} 上触发。"
433-
)
434-
return
435-
except asyncio.CancelledError:
436-
raise
437-
except Exception as e_try:
438-
last_err = e_try
439-
continue
440-
441-
# 兜底:在 document.body 上尝试一次
442-
try:
443-
await self.page.evaluate(
444-
"""
445-
(files) => {
446-
const dt = new DataTransfer();
447-
for (const p of files) {
448-
const bstr = atob(p.b64);
449-
const len = bstr.length;
450-
const u8 = new Uint8Array(len);
451-
for (let i = 0; i < len; i++) u8[i] = bstr.charCodeAt(i);
452-
const blob = new Blob([u8], { type: p.mime || 'application/octet-stream' });
453-
const file = new File([blob], p.name, { type: p.mime || 'application/octet-stream' });
454-
dt.items.add(file);
455-
}
456-
const el = document.body;
457-
const evEnter = new DragEvent('dragenter', { bubbles: true, cancelable: true, dataTransfer: dt });
458-
el.dispatchEvent(evEnter);
459-
const evOver = new DragEvent('dragover', { bubbles: true, cancelable: true, dataTransfer: dt });
460-
el.dispatchEvent(evOver);
461-
const evDrop = new DragEvent('drop', { bubbles: true, cancelable: true, dataTransfer: dt });
462-
el.dispatchEvent(evDrop);
463-
}
464-
""",
465-
payloads,
466-
)
467-
await asyncio.sleep(0.5)
468-
self.logger.info(" 拖放事件已在 document.body 上触发(兜底)。")
469-
return
470-
except asyncio.CancelledError:
471-
raise
472-
except Exception:
473-
pass
474-
475-
raise last_err or Exception("拖放未能在任何候选目标上触发")
476-
477328
async def _try_enter_submit(
478329
self, prompt_textarea_locator, check_client_disconnected: Callable
479330
) -> bool:

browser_utils/page_controller_modules/response.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ async def get_response(
5959
edit_button_locator,
6060
self.req_id,
6161
check_client_disconnected,
62-
None,
6362
)
6463

6564
if not completion_detected:

0 commit comments

Comments
 (0)