opencli-adapter-author
Use when writing an OpenCLI adapter for a new site or adding a new command to an existing site. Guides end-to-end from first recon through field decoding, adapter coding, and verify. Replaces opencli-oneshot / opencli-explorer. For ad-hoc browser driving (no adapter), see opencli-browser instead; fo
By jackwener · 15,003 installs
npx skills add jackwener/opencli --skill opencli-adapter-author
Source repository · Upstream listing
opencli adapter author
你是要给一个站点写 adapter 的 agent。这份 skill 目标:简单站点争取 30 分钟内从零到通过 opencli browser verify ;复杂、私有协议或写操作站点以证据完整和安全为先,不为了时限猜接口。
全程用现有工具: opencli browser / opencli doctor / opencli browser init / opencli browser verify 。没有新命令。
调试浏览器型 adapter 时,优先直接带上 trace on keep tab true window foreground 。 trace on 每轮都落 trace artifact, summary.md 是失败/成功复盘入口; keep tab true window foreground 让 tab lease 保留且浏览器窗口在前台,方便核对最终页面状态。
前置:看你落在哪
先拿 coverage matrix.md 快速自测。三个问题:
1. 数据在浏览器里看得到吗?(否 → 先解决鉴权)
2. 数据是 HTTP/JSON/HTML 吗?(否 → 不在 skill 范围)
3. 需要实时推送吗?(是 → 找同数据 HTTP 接口;没有就放弃)
三个都 yes 继续。
顶层决策树
先定 strategy,再写 adapter。 每次进入 Step 3/4 后、写代码前,必须产出一段 strategy note。没有这段 note,不要开始写 clis/<site /<name .js 。
核心判断不是 "API 比 DOM 高级",而是 数据源有没有外部契约 。实测维护成本显示:公开/官方接口最稳;UI/DOM 语义通常也有用户可见契约;站内未文档化 XHR/GraphQL/signature endpoint 最容易漂。不要为了 "API first" 把稳定的 UI/DOM 实现盲目迁到无契约内部接口。
Strategy classes:
Strategy 契约级别 用在什么时候 证据要求
PUBLIC API stable 不需要登录,Node side fetch 直接拿到目标数据 200 + JSON/HTML 含目标数据,不是埋点/广告
COOKIE API stable Node side fetch + page.getCookies() / header helper 能拿数据 cookie/CSRF 来源清楚,replay 非空
UI SELECTOR visible ui publish/upload/click/表单,或页面语义比内部接口更稳 selector 有语义锚点;错误路径是 typed error
DOM STATE visible ui 数据在 hydration state / bootstrap JSON / SSR HTML 里 state key / script JSON / HTML 结构明确
PAGE FETCH internal unstable 只能在页面上下文 fetch 才能复用 same origin/session/runtime opencli browser eval fetch(...) 非空;必须解释为什么避不开内部接口
INTERCEPT internal unstable 请求签名复杂,但页面自己能自然发出请求 触发 UI 后能截到目标 response;必须解释为什么 UI/DOM 不够
选择规则:优先 PUBLIC API / COOKIE API 。如果 UI/DOM 语义稳定,不要强行升级到 PAGE FETCH / INTERCEPT 。只有公开/官方接口不可用、UI/DOM 无法表达目标数据或操作时,才承担无契约内部接口的维护成本。
实测: PAGE FETCH / INTERCEPT 的 fix 频率约为 PUBLIC API 的 7 8 倍, UI SELECTOR 跟 COOKIE API 同档。详细 ladder 推导、 api candidates 证据怎么填、booking 1680 等反例见 [ references/strategy selection.md ](./references/strategy selection.md)。
边界:只复用页面自己已经合法获得的数据/能力。不教破解签名、不绕验证码/风控/访问控制;遇到不可复用签名(如必须由页面 runtime 生成且不能安全抽象)就降级到 UI SELECTOR / DOM STATE / INTERCEPT 。
Runbook(一步一步勾选)
降级路径(某步卡住跳到哪)
卡在 现象 跳去
Step 4 API 发现 network 空, INITIAL STATE 也空 §3 bundle 搜 baseURL
bundle 搜不到 baseURL §5 intercept
Step 5 endpoint 验证 401 / 403 §4 token 排查
200 但响应是 HTML 回 Step 3 换 Pattern 判断
200 但 data: [] 空 参数传错 / 接口换版,回 §1 看 network 里真实请求头
Step 7 字段解码 排序键对比推不出 field decode playbook.md §3 结构差分
还推不出 先输出 raw,adapter 跑起来再迭代
Step 10 verify 失败 fltt 漏了 / 字段映射错 autofix skill;复现命令加 trace retain on failure
某列永远是 null 字段路径错了,回 Step 7
Step 10 verify fixture mismatch [pattern] row[i] 报错 先肉眼比对网页值;值对 → 是 fixture pattern 太严,放宽;值不对 → 字段映射错
[column] missing column "X" 实际 response 没这列(站点改版 or args 影响);重新 update fixture 或修 adapter
[type] actual null / undefined 字段提取失败,回 Step 7 重抽;临时 fallback 用 union type string\ null 只有在语义真的可空时用
Step 11 数值不对 差 10000 倍 单位不统一("万" vs "元")
百分比小 100 倍 响应已是 0.025 ,不要 × 100
参考文件
文件 什么时候翻
references/coverage matrix.md 动手前做"是否在范围内"自测
references/site recon.md Step 3 定站点类型
references/api discovery.md Step 4 找 endpoint
references/deep recon.md 复杂无文档站:动作归因、jsluice 候选扩展、合同证明、读写安全与交付净账
references/strategy selection.md Step 6 填 strategy note 之前:契约模型 + 实测 fix 频率 + api candidates 证据用法 + 反例
references/field conventions.md Step 7 查已知字段代号
references/field decode playbook.md Step 7 字段不在词典时
references/output design.md Step 8 命名 / 类型 / 顺序
references/adapter template.md Step 9 文件结构 + 活例子 convertible.js
references/site memory.md 总览:in repo 种子 + 本地 ~/.opencli/sites/ 的两层结构
references/site memory/<site .md Step 2 读站点公共知识(eastmoney / xueqiu / bilibili / tonghuashun 已铺)
references/success rate pitfalls.md Step 7 / 11 踩坑前翻:11 种"verify 能过但数据是错的"静默失败(含 aria label locale dependence)
references/jsdom fixture pattern.md 当 adapter 走 page.evaluate 内 DOM 抽取、且 mocked evaluate 单测漏 silent bug 时——把 HTML 冻进 clis/<site / fixtures / 用 JSDOM 跑(含 fixture 创建 mandatory awk 'NF 0' 收紧 + reverse validate 纪律)
references/typed errors.md 写 func 主体之前必读:5 类 typed error 落点表(ArgumentError / EmptyResultError / CommandExecutionError / AuthRequiredError / TimeoutError)+ 三大 silent anti pattern(silent clamp / sentinel row / generic CliError)的反例修法
关键约定
adapter 只引 @jackwener/opencli/registry + @jackwener/opencli/errors ,不用第三方
columns 数组和 func 返回对象 keys 完全对齐(含顺序)
中间解析对象 key 不能跟 columns 任一项重叠 (否则 silent column drop audit 误判,PR 1329 R1 真踩过;改成专属命名 + push row 时 destructure aliasing)
browser: field 决定 func 签名 : browser:false → (args) , browser:true → (page, args) 。搞反时 args 实际是 debug flag,所有外部参数 silent fallback 到 default(PR 1329 upstream 之前 8 个 non browser adapter 全踩过这个)
已知失败按 [ references/typed errors.md ](./references/typed errors.md) 5 classification 抛对应 typed error; 不要 silent return [] , 不要 silent return [{sentinel}] , 不要 Math.max/min silent clamp 外部参数
写私人 adapter 用 ~/.opencli/clis/<site /<name .js (免 build);要提 PR 才 copy 到 clis/<site /<name .js
站点记忆每轮回写:没记忆 → 用 skill → 产生记忆 → 下次变 5 分钟
“真实发生过”不等于“可作为 production contract 重放” 。私有写请求、一次性风控 token、页面 runtime controller 都必须过 deep recon.md 的 contract gate;过不了就记录 blocker/lift condition,不生成伪 API 命令。
调试过程中的原始 dump / 抓包 / HTML 样本只能短暂落在系统 /tmp/ 或受控 cache,任务结束删除。只有通过 site memory.md 数据分级、准备长期保留的公开/合成/已脱敏样本才进入 ~/.opencli/sites/<site /fixtures/ 。严禁在 repo 根目录、 clis/<site / 或当前工作目录留 .dbg .html / raw .json / sample. 。
JSDOM unit test fixture( clis/<site / fixtures /<command .html )是上面那条的例外 ——它是有意 commit 进 repo 的 review artifact,不是临时 dump。但因此 quality bar 要更高:必须按 references/jsdom fixture pattern.md 的 5 步做完(含 mandatory awk 'NF 0' 空白行收紧),并 reverse validate 一道证明 regression guard 真能挂。
卡住了
诊断类: opencli doctor → 看 notes.md → 搜 autofix skill
字段解码类: field decode playbook.md 全三节走完 → 先输出 raw 迭代
endpoint 找不到:api discovery §5 intercept 兜底
不要猜。猜错了 verify 能通过但数据是错的,用户看到乱码才发现。