用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomevault-io/skills-registry --skill chat-plus-adapter-debugger命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| Use when this capability is needed.
> Use when this capability is needed.
Review architecture and API design for the vfs-s3 project. Use when the user mentions @architect, asks to review an issue's design, discuss module boundaries, API shape, or architectural decisions for vfs-s3. Also trigger when the user wants to create an ADR (Architecture Decision Record) or evaluate a technical approach for the project. Intended for dispatch from Codex automation or Claude routines; GitHub trigger phrase: @vfs-s3-bot please prepare design doc Use when this capability is needed.
基于 SOC 职业分类
| name | chat-plus-adapter-debugger |
| description | >- Use when this capability is needed. |
产出或修复一段可直接粘贴到 Chat Plus 的站点适配脚本,并满足新框架硬规则:
return { ... }metatransformRequestextractResponsedecorateBubblescontinueConversationdecorateBubbles 必须使用 ctx.helpers.ui.decorateProtocolBubbles(...)continueConversation 必须使用 ctx.helpers.plans.dom(...)continueConversation 必须使用 ctx.continuationTextextractResponse 必须返回 responseContentPreviewtransformRequest 要么使用 ctx.helpers.buildInjectedText(...) 改写请求,要么明确 return nullextractResponse准备页面调试前,先确认工具列表存在 chrome-cdp,并读取 builtin://chrome-cdp/SKILL.md。本 skill 的执行入口可直接代理常用 CDP 调试命令,也可用更贴近 Chat Plus 工作流的别名。
只有用户明确允许启动浏览器调试会话后,才使用浏览器调试命令。MCP Gateway 内置 chrome-cdp 默认通过原生 Chrome DevTools Protocol 启动或复用独立的持久 profile Chrome,不连接用户已经打开的 Chrome 调试端口。
常用别名:
capture start
capture clear
network search <filter>
network get <request-id>
network perf
等价 CDP 命令:
netclear
net <filter>
netget <request-id>
perfnet
html [target] [selector]
snap [target]
evalraw <target> <method> [json]
如果 chrome-cdp 启动或浏览器连接失败:
stopopen <url> 或 launch <url>按这个顺序抓样本。不要把 URL、Performance index 或页面 DOM 文本当作稳定 request id。
capture start 或 netclear,让 CDP Network 从用户操作前开始记录CHATPLUS_ADAPTER_PROBE_YYYYMMDD_001发好了network search <关键词> 或 net <关键词> 搜索 CDP Network 记录net 输出里的 CDP request idnetwork get <request-id> 查看请求体、响应体、状态码、content-type 和传输类型network get 输出总结协议结构,不复述敏感 headers--request-file / --response-file 保存到临时文件后再读取capture start,让用户发第二条 follow-up 样本硬要求:
发好了 前假设请求已经产生chrome-cdp 直接看netget 输出可能包含 Authorization、Cookie、设备 ID、会话 ID;最终回答和中间总结都不要复述这些值允许的查询方式:
capture start 或 netclearnetwork search <url-fragment>、network search <api-path>、network search <method>、network search <mime> 或其它从候选里来的关键词network search <关键词> 定位,再用 network get <request-id> 读取 framesnetwork search 没有结果,用 network perf 或 perfnet 辅助确认是否漏开 Network、页面是否跳转、请求是否发生在 worker / service worker禁止的反推方式:
capture start / netclear 的情况下期待 CDP Network 有用户操作前的历史记录抓取必须按三层证据链推进:
network search <filter> 搜索真实 request idnetwork get <request-id> 补齐浏览器层原始请求体、响应体、状态码和 content-typenetwork perf 查看发送后新增资源html / snap 确认用户消息、AI 消息、输入框、发送按钮、模式开关和消息气泡选择器extractResponse 的真实响应协议先分类,不要直接归因为站点没有发请求:
OPTIONS、埋点、标题生成、历史同步、配置、心跳、模型列表、附件上传netget 输出被截断或 body 太长:才用 request id 和 --request-file / --response-file 保存到临时文件transformRequest 返回 nullcapture start 后再让用户发送netget 看到的是网络 body,不是 F12 Preview。网络 body 可能包含应用层 framing / transport envelope,必须按协议层次还原。
网络 body 解码顺序:
netget 里的 status、content-type、content-encoding、request/response headers,不要只看文件扩展名application/json 或纯文本,按 UTF-8 直接读\0、控制字符、�、、 等字节,先检查是否是 length-prefixed JSON 帧有些站点存在会明显改变请求结构、响应结构或消息 DOM 的模式开关,例如:
遇到这种情况时,必须先确认用户实际使用的是哪种模式,再决定抓样本和写 adapter。
硬要求:
extractResponse 必须排除思考文本,只提取最终 assistant 正文和需要保留的协议块decorateBubbles 的目标选择器必须避开思考组件,不把思考组件纳入协议卡片渲染范围默认策略:
renderProtocolCard、getProtocolCardTheme、detectToolResultTone 这类旧 UI 辅助函数decorateBubblescontinueConversation 自己 click() / dispatchEvent() / setTimeout()[CHAT_PLUS_...] 协议标记meta、缺 adapterName、缺 capabilitiesJSON.parse(bodyText) 直接解析请求体,必须走 ctx.helpers.json.parse(bodyText)ctx.helpers.buildInjectedText(...)ctx.bodyText / ctx.responseText 转字符串,必须走 ctx.helpers.text.toText(...)meta.contractVersion 必须是整数,按当前 Chat Plus 项目范式优先用 2meta.capabilities 必须用对象写明四类能力,不要写成数组、字符串或空对象transformRequest(ctx)
负责请求层注入。输入注入优先走协议层。请求可稳定改写时,必须用 ctx.helpers.text.toText(ctx.bodyText) 取文本、用 ctx.helpers.json.parse(bodyText) 解析 JSON、用 ctx.helpers.buildInjectedText(...) 生成注入文本。请求不可稳定改写时,必须保留 hook 并 return null。
extractResponse(ctx)
负责从真实响应里提取 AI 正文。输出抓取必须走真实协议 / 真实响应。不要从页面现成消息 DOM 倒推正文,当成响应提取。必须保留协议块,不要把 toolCall / toolResult / codeMode 过滤掉。必须返回 responseContentPreview。不要随意 slice(...)。
decorateBubbles(ctx)
负责隐藏用户注入块,把可见协议块变成统一卡片,并保留协议块之外的普通文本。必须直接走 ctx.helpers.ui.decorateProtocolBubbles(...)。
continueConversation(ctx)
负责返回 DOM 发送方案。必须直接走 ctx.helpers.plans.dom(...)。必须使用 ctx.continuationText。不能自己执行真实 DOM 副作用。第一次 send 默认用 mode: "click",只有确认站点必须 Enter 时才改。
toolCall 默认只展示,不等于自动执行codeModecodeMode 卡片的手动运行按钮、卡片容器、源码节点,统一由平台 helper 负责,不让站点脚本重复造轮子按下面顺序工作:
transformRequest 能不能稳定改写extractResponse 怎么提取正文和协议块decorateBubblescontinueConversation如果样本不足,先指出缺什么,不要装作信息足够。
不要只看四个函数在不在。必须逐项检查:
meta 是否完整transformRequest 是否使用 ctx.helpers.buildInjectedText(...) 或明确 return nullextractResponse 是否返回 responseContentPreviewdecorateBubbles 是否直接使用 ctx.helpers.ui.decorateProtocolBubbles(...)continueConversation 是否直接使用 ctx.helpers.plans.dom(...)continueConversation 是否使用 ctx.continuationText输出顺序固定:
responseContentPreviewcodeMode begin/end 是否能完整保留assistantSelectors / 协议卡片装饰范围中排除input / change必须包含 contractVersion、adapterName、capabilities。默认能力结构按真实样本填写,常见 JSON 请求体 + SSE 响应 + helper 卡片 + DOM 续写应写成:
meta: {
contractVersion: 2,
adapterName: "...",
capabilities: {
requestInjection: "json-body",
responseExtraction: "sse",
protocolCards: "helper",
autoContinuation: "dom-plan",
},
},
字段语义:
requestInjection: 请求层注入方式,例如 "json-body";如果请求不可稳定改写,可写 "none",但 transformRequest 必须明确 return nullresponseExtraction: 真实响应提取方式,例如 "sse"、"ndjson"、"json"、"websocket"、"grpc-web"、"dom-fallback";优先真实协议,不要默认 DOMprotocolCards: 必须是 "helper",对应 ctx.helpers.ui.decorateProtocolBubbles(...)autoContinuation: 必须是 "dom-plan",对应 ctx.helpers.plans.dom(...)ctx.helpers.json.parse(bodyText) 解析,不要写 JSON.parse(bodyText)ctx.helpers.text.toText(ctx.bodyText) 获取,不要自己转字符串ctx.helpers.buildInjectedText(...)applied / bodyText / requestMessagePath / requestMessagePreviewreturn null标准请求体读取和注入模板:
const bodyText = ctx.helpers.text.toText(ctx.bodyText);
if (!ctx.injectionText || !bodyText) return null;
const body = ctx.helpers.json.parse(bodyText);
if (!body) return null;
const originalText = slot.text;
const nextText = ctx.helpers.buildInjectedText(ctx.injectionText, originalText, ctx.injectionMode);
if (nextText === originalText) return null;
slot.apply(nextText);
responseContentPreviewresponseContentPreviewinnerText / textContent 当作主提取方案标准响应体读取模板:
const responseText = ctx.helpers.text.toText(ctx.responseText);
if (!responseText) return null;
只能写成这种方向:
decorateBubbles(ctx) {
return ctx.helpers.ui.decorateProtocolBubbles({
root: ctx.root || document,
protocol: ctx.protocol,
userSelectors: [...],
assistantSelectors: [...],
});
}
允许传:
normalizeUserTextnormalizeAssistantTextbeforeRenderUserNodebeforeRenderAssistantNode但不要自己重写整套卡片系统。
如果站点有思考组件:
assistantSelectors 应只命中最终回答消息区域,不要命中思考容器禁止:
ctx.helpers.ui.decorateProtocolBubbles(...)只能写成这种方向:
continueConversation(ctx) {
return ctx.helpers.plans.dom({
root: ctx.root,
composerText: ctx.continuationText,
input: {
selectors: [...],
kind: "textarea",
dispatchEvents: ["input", "change"],
},
send: {
mode: "click",
selectors: [...],
waitForEnabled: true,
maxWaitMs: 2000,
},
});
}
输入侧策略说明:
input.kind 必须按真实 DOM 确认后写 "textarea" 或 "contenteditable",不要看见输入框就猜send 时优先 mode: "click",不要默认 Enter;只有真实站点要求 Enter 且有证据时才用键盘发送禁止:
btn.click()dispatchEvent(...)setTimeout(...)return { dispatched: true }ctx.continuationText这些不是风格偏好,是生成和审查 adapter 时必须拦截的错误:
| 检查点 | 正确做法 | 错误做法 |
|---|---|---|
| JSON 解析 | ctx.helpers.json.parse(bodyText) | JSON.parse(bodyText) |
| 文本注入 | ctx.helpers.buildInjectedText(...) | 手写字符串拼接 |
| 文本获取 | ctx.helpers.text.toText(ctx.bodyText) | String(...)、.toString()、手动解码 |
decorateBubbles | ctx.helpers.ui.decorateProtocolBubbles({...}) | 自己操作 DOM 或重造卡片 |
continueConversation | ctx.helpers.plans.dom({...}) | 自己 click() / dispatchEvent() |
continueConversation.send | 首次默认 mode: "click" | 没证据就默认 Enter |
| 输入框 kind | 先确认 "textarea" 或 "contenteditable" | 对号入座、凭经验猜 |
| 最外层 | return { meta: {...}, transformRequest, extractResponse, decorateBubbles, continueConversation } | 裸函数、对象字面量、漏 hook |
| 协议注入 | JSON 可解析且能稳定定位消息时优先协议注入 | 能改请求却直接退 DOM |
输出脚本前必须自己检查:
return { ... }metameta 有 contractVersionmeta 有 adapterNamemeta 有 capabilitiesmeta.capabilities.requestInjection、responseExtraction、protocolCards、autoContinuation 都已按真实实现填写protocolCards 是 "helper"autoContinuation 是 "dom-plan"transformRequest 不是乱改请求transformRequest 用 ctx.helpers.text.toText(ctx.bodyText) 读取请求文本ctx.helpers.json.parse(bodyText) 解析,没有直接 JSON.parse(bodyText)ctx.helpers.buildInjectedText(...) 生成,没有手写字符串拼接extractResponse 返回 responseContentPreviewextractResponse 已排除思考文本,只保留最终正文和协议块decorateBubbles 直接使用平台 helperdecorateBubbles 的选择器 / 过滤逻辑已避开思考组件最终先给:
最终先给 findings,不要先说“整体不错”。
decorateBubbles 降级成纯样式函数continueConversation 写成真实 DOM 执行器responseContentPreviewtransformRequest 里使用 JSON.parse(bodyText)、手写注入拼接、手动字符串转换textarea / contenteditable 就写输入框 kindnetget 输出或临时文件里的敏感 header、cookie、token、设备 ID 或会话 IDctx.helpers.ui.decorateProtocolBubbles(...),就判定不符合新框架ctx.helpers.plans.dom(...),就判定不符合新框架transformRequest 里直接 JSON.parse(bodyText),就判定需要改成 helperctx.helpers.buildInjectedText(...),就判定需要修改meta,就判定不符合新框架responseContentPreview,就判定响应提取错误decorateBubbles 的卡片渲染范围,就判定 DOM 选择器错误transformRequest 明确 return null 且 continueConversation 可用,就算符合框架本 skill 只负责产出或修复 Chat Plus 适配脚本;脚本本身、临时样本、抓回来的 request/response 文件不要走 shell_command 的 echo > / Set-Content / here-doc / cat 再自己写文件。
multi_edit_file,让网关记录变更路径、执行 path guard、产出可审查的 diff。netget --request-file / --response-file 产出的内容一律走 read_file,输出带行号、受 allowed directories 约束、二进制自动拒绝。chrome-cdp,不要试图在 shell_command 里自己起 Chrome 或 node 调 CDP。Source: aiguicai/MCP-Gateway — distributed by TomeVault.
continueConversation 直接使用平台 helpercontinueConversation 使用 ctx.continuationTextcontinueConversation.send.mode 首次默认 "click",除非有证据必须 Enterinput.kind 已从真实 DOM 确认为 "textarea" 或 "contenteditable"[CHAT_PLUS_...]