a058b0ab8e
- 修复记忆管理数据库连接不可用 (ai-core重编译+Unicode修复) - 修复IoT子会话工具调用链路日志缺失 - 新增最终审查子会话(review_provider) 支持消息格式解析拆分 - 实现历史消息持久化(后端存储+前端分页加载) - 前端新增动作消息(ActionMessage)类型和渲染 - 优化对话链路速度(非阻塞子会话+快速问候通道) - JWT密钥环境变量化(无默认值启动panic) - Token自动刷新机制(401拦截器+refresh接口) - WebSocket指数退避重连(jitter+最大10次) - localStorage清理一致性(cyrene_前缀+版本检查) - IoT环境变量统一为IOT_SERVICE_URL
135 lines
4.0 KiB
Python
135 lines
4.0 KiB
Python
#!/usr/bin/env python3
|
|
"""CDP 前端验证:截图 + 控制台检查 + 页面状态"""
|
|
import json, time, base64, urllib.request, os
|
|
|
|
# Step 1: 导航到前端页面 (PUT /json/new)
|
|
print("=== CDP 前端验证 ===")
|
|
print("Navigating to page...")
|
|
req = urllib.request.Request("http://127.0.0.1:9225/json/new?url=http://localhost:5199/", method="PUT")
|
|
try:
|
|
resp = urllib.request.urlopen(req, timeout=10)
|
|
page_data = json.loads(resp.read())
|
|
page_id = page_data.get("id","")
|
|
ws_url = page_data.get("webSocketDebuggerUrl","")
|
|
print(f" Page: id={page_id} title={page_data.get('title','')[:80]}")
|
|
print(f" WS_URL: {ws_url[:80]}")
|
|
except Exception as e:
|
|
print(f" Navigation failed: {e}")
|
|
import sys; sys.exit(1)
|
|
|
|
# Step 2: 连接到页面 WebSocket
|
|
from websocket import create_connection
|
|
ws = create_connection(ws_url, timeout=10)
|
|
print(" Connected to page WebSocket")
|
|
|
|
def cdp(method, params=None, msg_id=1):
|
|
payload = json.dumps({"id": msg_id, "method": method, "params": params or {}})
|
|
ws.send(payload)
|
|
|
|
def recv_msgs(timeout=3):
|
|
ws.settimeout(timeout)
|
|
msgs = []
|
|
try:
|
|
while True:
|
|
msgs.append(ws.recv())
|
|
except:
|
|
pass
|
|
return msgs
|
|
|
|
def find_result(msgs, msg_id):
|
|
for m in msgs:
|
|
try:
|
|
d = json.loads(m)
|
|
if d.get("id") == msg_id:
|
|
return d.get("result",{})
|
|
except:
|
|
pass
|
|
return None
|
|
|
|
# Step 3: 启用 domains
|
|
print("\nEnabling domains...")
|
|
cdp("Runtime.enable", {}, 1)
|
|
cdp("Page.enable", {}, 2)
|
|
cdp("Log.enable", {}, 3)
|
|
recv_msgs(2)
|
|
print(" Domains enabled")
|
|
|
|
# Step 4: 等待页面完全加载后截图
|
|
print("\nWaiting for page to load...")
|
|
time.sleep(3)
|
|
cdp("Page.captureScreenshot", {"format": "png"}, 10)
|
|
msgs = recv_msgs(5)
|
|
r = find_result(msgs, 10)
|
|
if r and r.get("data"):
|
|
img = base64.b64decode(r["data"])
|
|
with open("/tmp/cyrene_screenshot_round12.png", "wb") as f:
|
|
f.write(img)
|
|
print(f" Screenshot saved: {len(img)} bytes")
|
|
else:
|
|
print(f" Screenshot failed: {str(r)[:200]}")
|
|
|
|
# Step 5: 获取控制台日志
|
|
print("\nConsole messages (Log.entryAdded):")
|
|
ws.settimeout(2)
|
|
logs = []
|
|
for i in range(15):
|
|
try:
|
|
data = ws.recv()
|
|
d = json.loads(data)
|
|
if d.get("method") == "Log.entryAdded":
|
|
entry = d["params"]["entry"]
|
|
level = entry.get("level","log")
|
|
text = entry.get("text","")
|
|
url = entry.get("url","")
|
|
logs.append(f" [{level}] {text[:200]} ({url})")
|
|
elif d.get("method") == "Runtime.exceptionThrown":
|
|
exc = d["params"].get("exceptionDetails",{})
|
|
logs.append(f" [EXCEPTION] {exc.get('text','')}")
|
|
except:
|
|
break
|
|
|
|
if logs:
|
|
for l in logs:
|
|
print(l)
|
|
else:
|
|
print(" (none)")
|
|
|
|
# Step 6: 页面状态检查
|
|
print("\nPage state:")
|
|
checks = [
|
|
("title", "document.title"),
|
|
("readyState", "document.readyState"),
|
|
("root exists?", "document.getElementById('root') ? 'yes' : 'no'"),
|
|
("body children", "document.body ? document.body.children.length : -1"),
|
|
("login form?", "document.querySelector('form') ? 'yes' : 'no'"),
|
|
("all text content (first 300)", "document.body ? (document.body.innerText || '').substring(0, 300) : 'no body'"),
|
|
]
|
|
for idx, (label, expr) in enumerate(checks):
|
|
cdp("Runtime.evaluate", {"expression": expr, "returnByValue": True}, 100 + idx)
|
|
msgs = recv_msgs(2)
|
|
r = find_result(msgs, 100 + idx)
|
|
val = r.get("result",{}).get("value","?") if r else "?"
|
|
print(f" {label}: {val}")
|
|
|
|
# Step 7: 前端 JS 错误检测
|
|
print("\nJS Errors (Runtime.exceptionThrown):")
|
|
ws.settimeout(1)
|
|
errors = []
|
|
for i in range(5):
|
|
try:
|
|
d = json.loads(ws.recv())
|
|
if d.get("method") == "Runtime.exceptionThrown":
|
|
exc = d["params"]["exceptionDetails"]
|
|
errors.append(f" {exc.get('text','')} at {exc.get('url','')}:{exc.get('lineNumber','')}")
|
|
except:
|
|
break
|
|
|
|
if errors:
|
|
for e in errors:
|
|
print(e)
|
|
else:
|
|
print(" No JS exceptions detected")
|
|
|
|
ws.close()
|
|
print("\n[DONE]")
|