opencli-repair
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOpenCLI Repair — AI-Driven Adapter Self-Repair
OpenCLI Repair — AI驱动的适配器自修复
When an adapter breaks because a website changed its DOM, API, or auth flow, use this skill to diagnose the failure and patch the adapter.
当网站修改了DOM、API或者认证流程导致适配器损坏时,使用本技能来诊断故障并修复适配器。
Prerequisites
前置要求
bash
opencli doctor # Verify extension + daemon connectivitybash
opencli doctor # 验证扩展和守护进程的连通性When to Use This Skill
何时使用本技能
Use when fails with errors like:
opencli <site> <command>- SELECTOR — element not found (DOM changed)
- EMPTY_RESULT — no data returned (API response changed)
- API_ERROR / NETWORK — endpoint moved or broke
- PAGE_CHANGED — page structure no longer matches
- COMMAND_EXEC — runtime error in adapter logic
- TIMEOUT — page loads differently, adapter waits for wrong thing
当运行失败并出现以下错误时使用:
opencli <site> <command>- SELECTOR — 未找到元素(DOM已变更)
- EMPTY_RESULT — 无数据返回(API响应已变更)
- API_ERROR / NETWORK — 接口路径变更或不可用
- PAGE_CHANGED — 页面结构不再匹配预期
- COMMAND_EXEC — 适配器逻辑运行时错误
- TIMEOUT — 页面加载逻辑变更,适配器等待了错误的对象
Step 1: Collect Diagnostic Context
步骤1:收集诊断上下文
Run the failing command with diagnostic mode enabled:
bash
OPENCLI_DIAGNOSTIC=1 opencli <site> <command> [args...] 2>diagnostic.jsonThis outputs a JSON between markers in stderr:
RepairContext___OPENCLI_DIAGNOSTIC___json
{
"error": {
"code": "SELECTOR",
"message": "Could not find element: .old-selector",
"hint": "The page UI may have changed."
},
"adapter": {
"site": "example",
"command": "example/search",
"sourcePath": "/path/to/clis/example/search.ts",
"source": "// full adapter source code"
},
"page": {
"url": "https://example.com/search",
"snapshot": "// DOM snapshot with [N] indices",
"networkRequests": [],
"consoleErrors": []
},
"timestamp": "2025-01-01T00:00:00.000Z"
}Parse it:
bash
undefined开启诊断模式运行报错的命令:
bash
OPENCLI_DIAGNOSTIC=1 opencli <site> <command> [args...] 2>diagnostic.json该命令会在标准错误流的标记之间输出格式的JSON:
___OPENCLI_DIAGNOSTIC___RepairContextjson
{
"error": {
"code": "SELECTOR",
"message": "Could not find element: .old-selector",
"hint": "The page UI may have changed."
},
"adapter": {
"site": "example",
"command": "example/search",
"sourcePath": "/path/to/clis/example/search.ts",
"source": "// full adapter source code"
},
"page": {
"url": "https://example.com/search",
"snapshot": "// DOM snapshot with [N] indices",
"networkRequests": [],
"consoleErrors": []
},
"timestamp": "2025-01-01T00:00:00.000Z"
}解析诊断数据:
bash
undefinedExtract JSON between markers from stderr output
从标准错误输出中提取标记之间的JSON内容
cat diagnostic.json | sed -n '/OPENCLI_DIAGNOSTIC/{n;p;}'
undefinedcat diagnostic.json | sed -n '/OPENCLI_DIAGNOSTIC/{n;p;}'
undefinedStep 2: Analyze the Failure
步骤2:分析故障原因
Read the diagnostic context and the adapter source. Classify the root cause:
| Error Code | Likely Cause | Repair Strategy |
|---|---|---|
| SELECTOR | DOM restructured, class/id renamed | Explore current DOM → find new selector |
| EMPTY_RESULT | API response schema changed, or data moved | Check network → find new response path |
| API_ERROR | Endpoint URL changed, new params required | Discover new API via network intercept |
| AUTH_REQUIRED | Login flow changed, cookies expired | Walk login flow with operate |
| TIMEOUT | Page loads differently, spinner/lazy-load | Add/update wait conditions |
| PAGE_CHANGED | Major redesign | May need full adapter rewrite |
Key questions to answer:
- What is the adapter trying to do? (Read the field)
source - What did the page look like when it failed? (Read the field)
snapshot - What network requests happened? (Read )
networkRequests - What's the gap between what the adapter expects and what the page provides?
读取诊断上下文和适配器源码,归类根因:
| 错误码 | 可能原因 | 修复策略 |
|---|---|---|
| SELECTOR | DOM结构重构,类名/id重命名 | 探查当前DOM → 找到新的选择器 |
| EMPTY_RESULT | API响应 schema 变更,或数据位置迁移 | 检查网络请求 → 找到新的响应路径 |
| API_ERROR | 接口URL变更,需要新增参数 | 通过网络拦截发现新的API |
| AUTH_REQUIRED | 登录流程变更,Cookie过期 | 使用operate模拟登录流程 |
| TIMEOUT | 页面加载逻辑变更,新增了加载动画/懒加载逻辑 | 新增/更新等待条件 |
| PAGE_CHANGED | 网站大版本改版 | 可能需要完全重写适配器 |
需要明确的核心问题:
- 适配器原本要实现什么功能?(读取字段)
source - 故障发生时页面是什么状态?(读取字段)
snapshot - 触发了哪些网络请求?(读取)
networkRequests - 适配器的预期和页面实际提供的内容之间有什么差异?
Step 3: Explore the Current Website
步骤3:探查当前网站状态
Use to inspect the live website. Never use the broken adapter — it will just fail again.
opencli operate使用检查线上网站状态。不要使用已经损坏的适配器 — 它只会再次报错。
opencli operateDOM changed (SELECTOR errors)
DOM变更(SELECTOR错误)
bash
undefinedbash
undefinedOpen the page and inspect current DOM
打开页面并检查当前DOM
opencli operate open https://example.com/target-page && opencli operate state
opencli operate open https://example.com/target-page && opencli operate state
Look for elements that match the adapter's intent
查找符合适配器预期功能的元素
Compare the snapshot with what the adapter expects
对比快照和适配器的预期内容
undefinedundefinedAPI changed (API_ERROR, EMPTY_RESULT)
API变更(API_ERROR、EMPTY_RESULT)
bash
undefinedbash
undefinedOpen page with network interceptor, then trigger the action manually
开启网络拦截打开页面,手动触发对应操作
opencli operate open https://example.com/target-page && opencli operate state
opencli operate open https://example.com/target-page && opencli operate state
Interact to trigger API calls
交互触发API调用
opencli operate click <N> && opencli operate network
opencli operate click <N> && opencli operate network
Inspect specific API response
查看指定API的响应详情
opencli operate network --detail <index>
undefinedopencli operate network --detail <index>
undefinedAuth changed (AUTH_REQUIRED)
认证逻辑变更(AUTH_REQUIRED)
bash
undefinedbash
undefinedCheck current auth state
检查当前认证状态
opencli operate open https://example.com && opencli operate state
opencli operate open https://example.com && opencli operate state
If login page: inspect the login form
如果跳转到登录页:检查登录表单
opencli operate state # Look for login form fields
undefinedopencli operate state # 查找登录表单字段
undefinedStep 4: Patch the Adapter
步骤4:修复适配器
Read the adapter source file and make targeted fixes:
bash
undefined读取适配器源码文件,进行针对性修复:
bash
undefinedRead the adapter
读取适配器源码
cat <sourcePath from diagnostic>
undefinedcat <sourcePath from diagnostic>
undefinedCommon Fixes
常见修复场景
Selector update:
typescript
// Before: page.evaluate('document.querySelector(".old-class")...')
// After: page.evaluate('document.querySelector(".new-class")...')API endpoint change:
typescript
// Before: const resp = await page.evaluate(`fetch('/api/v1/old-endpoint')...`)
// After: const resp = await page.evaluate(`fetch('/api/v2/new-endpoint')...`)Response schema change:
typescript
// Before: const items = data.results
// After: const items = data.data.items // API now nests under "data"Wait condition update:
typescript
// Before: await page.waitForSelector('.loading-spinner', { hidden: true })
// After: await page.waitForSelector('[data-loaded="true"]')选择器更新:
typescript
// Before: page.evaluate('document.querySelector(".old-class")...')
// After: page.evaluate('document.querySelector(".new-class")...')API接口变更:
typescript
// Before: const resp = await page.evaluate(`fetch('/api/v1/old-endpoint')...`)
// After: const resp = await page.evaluate(`fetch('/api/v2/new-endpoint')...`)响应结构变更:
typescript
// Before: const items = data.results
// After: const items = data.data.items // API now nests under "data"等待条件更新:
typescript
// Before: await page.waitForSelector('.loading-spinner', { hidden: true })
// After: await page.waitForSelector('[data-loaded="true"]')Rules for Patching
修复规则
- Make minimal changes — fix only what's broken, don't refactor
- Keep the same output structure — and return format must stay compatible
columns - Prefer API over DOM scraping — if you discover a JSON API during exploration, switch to it
- Use imports only — never add third-party package imports
@jackwener/opencli/* - Test after patching — run the command again to verify
- 最小修改原则 — 只修复损坏的部分,不要进行重构
- 保持输出结构一致 — 和返回格式必须保持兼容
columns - 优先使用API而非DOM爬取 — 如果探查过程中发现了JSON API,切换到API方式实现
- 仅允许使用导入 — 不要添加第三方包依赖
@jackwener/opencli/* - 修复后测试 — 重新运行命令验证功能正常
Step 5: Verify the Fix
步骤5:验证修复结果
bash
undefinedbash
undefinedRun the command normally (without diagnostic mode)
正常运行命令(关闭诊断模式)
opencli <site> <command> [args...]
If it still fails, go back to Step 3 and explore further. If the website has fundamentally changed (major redesign, removed feature), report that the adapter needs a full rewrite.opencli <site> <command> [args...]
如果仍然报错,回到步骤3继续探查。如果网站已经发生了根本性变更(大版本改版、功能下线),需要告知用户适配器需要完全重写。When to Give Up
何时放弃修复
Not all failures are repairable with a quick patch:
- Site requires CAPTCHA — can't automate this
- Feature completely removed — the data no longer exists
- Major redesign — needs full adapter rewrite via skill
opencli-explorer - Rate limited / IP blocked — not an adapter issue
In these cases, clearly communicate the situation to the user rather than making futile patches.
不是所有故障都可以通过快速补丁修复:
- 站点需要CAPTCHA验证 — 无法自动化绕过
- 功能完全下线 — 目标数据已经不存在
- 大版本改版 — 需要通过技能完全重写适配器
opencli-explorer - 被限流/IP封禁 — 不属于适配器本身的问题
出现以上情况时,清晰告知用户实际情况,不要做无效的修复尝试。
Example Repair Session
修复会话示例
1. User runs: opencli zhihu hot
→ Fails: SELECTOR "Could not find element: .HotList-item"
2. AI runs: OPENCLI_DIAGNOSTIC=1 opencli zhihu hot 2>diag.json
→ Gets RepairContext with DOM snapshot showing page loaded
3. AI reads diagnostic: snapshot shows the page loaded but uses ".HotItem" instead of ".HotList-item"
4. AI explores: opencli operate open https://www.zhihu.com/hot && opencli operate state
→ Confirms new class name ".HotItem" with child ".HotItem-content"
5. AI patches: Edit clis/zhihu/hot.ts — replace ".HotList-item" with ".HotItem"
6. AI verifies: opencli zhihu hot
→ Success: returns hot topics1. 用户运行:opencli zhihu hot
→ 报错:SELECTOR "Could not find element: .HotList-item"
2. AI运行:OPENCLI_DIAGNOSTIC=1 opencli zhihu hot 2>diag.json
→ 获取到RepairContext,DOM快照显示页面正常加载
3. AI读取诊断信息:快照显示页面已加载,但使用了`.HotItem`而非`.HotList-item`类名
4. AI探查:opencli operate open https://www.zhihu.com/hot && opencli operate state
→ 确认新的类名为`.HotItem`,子元素为`.HotItem-content`
5. AI修复:编辑clis/zhihu/hot.ts — 将`.HotList-item`替换为`.HotItem`
6. AI验证:opencli zhihu hot
→ 成功:返回热榜内容