|
33 | 33 | RESPONSE_COMPLETION_TIMEOUT = 300000 # 5 minutes total timeout (in ms) |
34 | 34 | POLLING_INTERVAL = 300 # ms - Standard polling interval |
35 | 35 | POLLING_INTERVAL_STREAM = 200 # ms - Stream-specific polling interval |
36 | | -SILENCE_TIMEOUT_MS = 1500 # ms |
| 36 | +SILENCE_TIMEOUT_MS = 3000 # ms (Increased from 1500ms) |
37 | 37 | # v2.12: Timeout for secondary checks *after* spinner disappears |
38 | 38 | POST_SPINNER_CHECK_DELAY_MS = 500 # Spinner消失后稍作等待再检查其他状态 |
39 | 39 | FINAL_STATE_CHECK_TIMEOUT_MS = 1500 # 检查按钮和输入框最终状态的超时 |
@@ -250,24 +250,68 @@ def validate_chat_request(messages: List[Message], req_id: str) -> Dict[str, Opt |
250 | 250 | } |
251 | 251 |
|
252 | 252 | async def get_raw_text_content(response_element, previous_text: str, req_id: str) -> str: |
253 | | - # (Ported/Adapted from server.cjs getRawTextContent - using async Playwright) |
254 | | - # Attempts to get text from <pre> first, then falls back to the main element |
| 253 | + """获取AI响应的原始文本内容,优先使用 <pre> 标签,并清理已知UI文本。""" |
| 254 | + raw_text = previous_text # 默认返回上一次的文本以防万一 |
255 | 255 | try: |
256 | 256 | await response_element.wait_for(state='attached', timeout=1500) |
257 | 257 | pre_element = response_element.locator('pre').last |
258 | | - raw_text = previous_text # Default to previous if all attempts fail |
| 258 | + |
| 259 | + pre_found_and_visible = False |
259 | 260 | try: |
260 | | - await pre_element.wait_for(state='attached', timeout=500) |
261 | | - raw_text = await pre_element.inner_text(timeout=1000) |
| 261 | + # 检查 pre 元素是否存在且可见 |
| 262 | + await pre_element.wait_for(state='visible', timeout=500) |
| 263 | + pre_found_and_visible = True |
262 | 264 | except PlaywrightAsyncError: |
263 | | - # If <pre> fails, try the parent response element's inner_text |
264 | | - # print(f"[{req_id}] (Info) Failed to get text from <pre>, falling back to parent.") |
| 265 | + # print(f"[{req_id}] (Info) Optional <pre> element not found or not visible quickly.") |
| 266 | + pass # pre 元素不存在或不可见是正常情况 |
| 267 | + |
| 268 | + if pre_found_and_visible: |
| 269 | + # 如果 pre 元素存在且可见,优先使用它的 innerText |
| 270 | + try: |
| 271 | + raw_text = await pre_element.inner_text(timeout=1000) |
| 272 | + # print(f"[{req_id}] (Debug) Got text from <pre>: {raw_text[:50]}...") |
| 273 | + except PlaywrightAsyncError as pre_err: |
| 274 | + print(f"[{req_id}] (Warn) Failed to get innerText from visible <pre>: {pre_err.message.split('\n')[0]}") |
| 275 | + # 如果从可见的 pre 获取文本失败,尝试回退到父元素 |
| 276 | + try: |
| 277 | + raw_text = await response_element.inner_text(timeout=2000) |
| 278 | + except PlaywrightAsyncError as e_parent: |
| 279 | + print(f"[{req_id}] (Warn) getRawTextContent (inner_text) failed on parent after <pre> fail: {e_parent}. Returning previous.") |
| 280 | + raw_text = previous_text |
| 281 | + else: |
| 282 | + # 如果 pre 元素未找到或不可见,直接获取父元素的 innerText |
265 | 283 | try: |
266 | 284 | raw_text = await response_element.inner_text(timeout=2000) |
| 285 | + # print(f"[{req_id}] (Debug) Got text from parent element: {raw_text[:50]}...") |
267 | 286 | except PlaywrightAsyncError as e_parent: |
268 | | - print(f"[{req_id}] (Warn) getRawTextContent (inner_text) failed on both <pre> and parent: {e_parent}. Returning previous.") |
269 | | - raw_text = previous_text # Return previous if parent also fails |
| 287 | + print(f"[{req_id}] (Warn) getRawTextContent (inner_text) failed on parent (no pre): {e_parent}. Returning previous.") |
| 288 | + raw_text = previous_text |
| 289 | + |
| 290 | + # --- 新增:清理已知的 UI 文本 --- |
| 291 | + if raw_text and isinstance(raw_text, str): # 确保是字符串 |
| 292 | + replacements = { |
| 293 | + "IGNORE_WHEN_COPYING_START": "", |
| 294 | + "content_copy": "", |
| 295 | + "download": "", |
| 296 | + "Use code with caution.": "", |
| 297 | + "IGNORE_WHEN_COPYING_END": "" |
| 298 | + } |
| 299 | + cleaned_text = raw_text |
| 300 | + found_junk = False |
| 301 | + for junk, replacement in replacements.items(): |
| 302 | + if junk in cleaned_text: |
| 303 | + cleaned_text = cleaned_text.replace(junk, replacement) |
| 304 | + found_junk = True |
| 305 | + |
| 306 | + if found_junk: |
| 307 | + # 移除可能因替换产生的多余换行符和空格 |
| 308 | + cleaned_text = "\n".join([line.strip() for line in cleaned_text.splitlines() if line.strip()]) |
| 309 | + print(f"[{req_id}] (清理) 已移除响应文本中的已知UI元素。") # 中文 |
| 310 | + raw_text = cleaned_text |
| 311 | + # --- 清理结束 --- |
| 312 | + |
270 | 313 | return raw_text |
| 314 | + |
271 | 315 | except PlaywrightAsyncError as e_attach: |
272 | 316 | print(f"[{req_id}] (Warn) getRawTextContent failed waiting for response element attach: {e_attach}. Returning previous.") |
273 | 317 | return previous_text |
@@ -798,7 +842,6 @@ async def check_disconnect(): |
798 | 842 | print(f"[{req_id}] 尝试使用 Control+Enter 快捷键提交...") # 中文 |
799 | 843 | await page.keyboard.press('Control+Enter') |
800 | 844 | # Heuristic check: See if input field clears quickly after sending |
801 | | - await expect_async(input_field).to_have_value('', timeout=2000) |
802 | 845 | print(f"[{req_id}] 快捷键提交成功 (输入框已清空)。") # 中文 |
803 | 846 | submitted_successfully = True |
804 | 847 | except PlaywrightAsyncError as key_press_error: |
|
0 commit comments