Imported from Hush-Lee/MyLearning (
Tools/ai-chat/.opencode/skills/aichat-site-debug/SKILL.md). Install upstream withnpx skills add Hush-Lee/MyLearning --skill aichat-site-debug. Copyright stays with the author.
aichat 站点排障
工具是 shell 端用 CDP 驱动 Chrome 操作 chatgpt.com / grok.com / chat.deepseek.com /
gemini.google.com / aistudio.xiaomimimo.com 等网页版 AI。所有站点差异都在
aichat/sites/<name>.py 的 SITE 字典里,引擎不需要改。
判断流程
- 症状是「网页里有回复、CLI 不显示」→ 回复容器选择器未匹配 → 走「校准 messages」。
- 症状是「发送不生效」→ 校准
input/send_button;没有发送按钮的站点会自动走 CDP 真实回车键。 - 症状是「一直等待后提示登录」→ 跑
aichat probe <site>看是真登录墙还是选择器没适配。
校准 steps
- 跑
aichat probe <site>,重点看三节输出:输入框候选、可点击元素、回复容器候选。 - 「回复容器候选」列出的就是带
message / markdown / bubble / assistant / response / prose / reply等特征属性的元素,从中挑只匹配 AI 回复正文的那个(不能匹配用户消息气泡)。 - 改
aichat/sites/<site>.py的对应字段,字段含义见references/site-fields.md。 - 重新发送一条短消息验证:终端应显示完整回复、且没有
[警告]/[兜底]/未抓到回复之类的提示。
约束
- 只改 sites/*.py,不要碰
aichat/driver.py/cdp.py/browser.py/cli.py——引擎差异已收敛。 - 选
messages.items时优先稳定特征:data-testid> 语义 class > CSS Modules 带 hash 后缀的 class(如Markdown_markdown__a19823a0,hash 变就失效)。 - 选
text子选择时从父往里钻一步,排除掉 thinking/related-questions/footer 这类非正文块。 - 改完无需重启浏览器(CDP 会自动重 attach),发条短消息立刻看效果。
已知坑
- hidden 渲染挂起(最重要):网页的流式渲染(rAF 驱动)在
visibilityState=hidden时 挂起——窗口停在 Hyprland special 工作区、或标签不是活动页时都是 hidden,回复文本 不会写进 DOM,症状是"发得出去、等不到回复、还提示登录"。引擎已用browser.visible_during()自动处理:收发期间窗口临时移到当前工作区(follow=false 不抢焦点)+ 标签转活动页,结束自动收回 special。排查时先确认这个机制没被绕过 (比如直接调 driver.ask 而没包 visible_during)。 - Grok:
assistant-message的正文在div.response-content-markdown内部,不要把.markdown当首选项(可能命中空容器)。 - MiMo Studio:回复正文是
div#message-list div.markdown-prose,发送按钮button[data-track-name="home_send_message"],聊天路由#/c(停在#/落地页时 prepare() 会自动跳转)。未登录时输入框 placeholder 就是 "Sign in to continue chatting"。 - Gemini:2026-09 起是
/app新 UI(Angular),输入区rich-textarea div.ql-editor、 发送button[aria-label="Send message"]。注意 Gemini 服务端有地区限制:请求 HTTP 200 但业务层拒绝(batchexecute 200 + 错误包在体里),症状与选择器失效一样——先用 probe 确认输入/按钮都命中,再怀疑地区/账号问题。 - 发送验证假阳性:
_wait_sent的 cleared 信号要求输入框存在且为空;找不到输入框 不算 cleared(防止点击空转被误报成"已发送")。 - 内嵌 JS 标识符:driver.py 各脚本与 prelude 共用一个 IIFE 作用域,新增内嵌 JS 时 不要重名 prelude 的标识符(SELS/MSGS/GEN/q/vis/pick/editorText/texts/count/isGen), 按钮类脚本用 BTN 前缀。