opencli-autofix
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOpenCLI AutoFix — Automatic Adapter Self-Repair
OpenCLI AutoFix — 适配器自动自我修复
When an command fails because a website changed its DOM, API, or response schema, automatically diagnose, fix the adapter, and retry — don't just report the error.
opencli当命令因网站修改了DOM、API或响应schema而执行失败时,自动诊断、修复适配器并重试,而不仅仅是上报错误。
opencliSafety Boundaries
安全边界
Before starting any repair, check these hard stops:
- (exit code 77) — STOP. Do not modify code. Tell the user to log into the site in Chrome.
AUTH_REQUIRED - (exit code 69) — STOP. Do not modify code. Tell the user to run
BROWSER_CONNECT.opencli doctor - CAPTCHA / rate limiting — STOP. Not an adapter issue.
Scope constraint:
- Only modify the file at — this is the authoritative adapter location (may be
RepairContext.adapter.sourcePathin repo orclis/<site>/for npm installs)~/.opencli/clis/<site>/ - Never modify ,
src/,extension/,tests/, orpackage.jsontsconfig.json
Retry budget: Max 3 repair rounds per failure. If 3 rounds of diagnose → fix → retry don't resolve it, stop and report what was tried.
在启动任何修复操作前,请先检查以下硬性停止条件:
- (退出码77)——立即停止,不要修改代码。告知用户需要在Chrome中登录对应网站。
AUTH_REQUIRED - (退出码69)——立即停止,不要修改代码。告知用户运行
BROWSER_CONNECT命令。opencli doctor - 验证码 / 限流——立即停止,不属于适配器问题。
范围约束:
- 仅可修改指定的文件——这是官方的适配器存储路径,可能是仓库中的
RepairContext.adapter.sourcePath路径,或者npm安装对应的clis/<site>/路径~/.opencli/clis/<site>/ - 绝对不要修改、
src/、extension/、tests/或者package.json文件tsconfig.json
重试预算: 每次失败最多支持3轮修复。如果经过3轮诊断→修复→重试的流程仍未解决问题,停止操作并报告所有已尝试的方案。
Prerequisites
前置条件
bash
opencli doctor # Verify extension + daemon connectivitybash
opencli doctor # 验证扩展程序与守护进程的连通性When to Use This Skill
何时使用此技能
Use when fails with repairable errors:
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输出到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"
}解析方法:
bash
undefinedExtract JSON between markers from stderr output
从stderr输出中提取标记之间的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 | STOP — tell user to log in, do not modify code |
| 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过期 | 立即停止 —— 告知用户登录,不要修改代码 |
| 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>
undefinedStep 4: Patch the Adapter
步骤4:修补适配器
Read the adapter source file at the path from and make targeted fixes. This path is authoritative — it may be in the repo () or user-local ().
RepairContext.adapter.sourcePathclis/~/.opencli/clis/bash
undefined读取路径下的适配器源码,进行针对性修复。该路径是官方路径,可能位于仓库()或用户本地路径()。
RepairContext.adapter.sourcePathclis/~/.opencli/clis/bash
undefinedRead the adapter (use the exact path from diagnostic)
读取适配器代码(使用诊断信息中返回的精确路径)
cat <RepairContext.adapter.sourcePath>
undefinedcat <RepairContext.adapter.sourcePath>
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')...`)响应schema变更:
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 1 and collect fresh diagnostics. You have a budget of **3 repair rounds** (diagnose → fix → retry). If the same error persists after a fix, try a different approach. After 3 rounds, stop and report what was tried.opencli <site> <command> [args...]
如果仍然失败,回到步骤1重新收集最新的诊断信息。你最多有**3轮修复预算**(诊断→修复→重试)。如果修复后仍出现相同错误,尝试其他方案。3轮后仍未解决,停止操作并报告所有已尝试的方案。When to Stop
何时停止操作
Hard stops (do not modify code):
- AUTH_REQUIRED / BROWSER_CONNECT — environment issue, not adapter bug
- Site requires CAPTCHA — can't automate this
- Rate limited / IP blocked — not an adapter issue
Soft stops (report after attempting):
- 3 repair rounds exhausted — stop, report what was tried and what failed
- Feature completely removed — the data no longer exists
- Major redesign — needs full adapter rewrite via skill
opencli-explorer
In all stop cases, clearly communicate the situation to the user rather than making futile patches.
硬性停止(不要修改代码):
- AUTH_REQUIRED / BROWSER_CONNECT——环境问题,不是适配器BUG
- 网站需要验证码——无法自动化处理
- 被限流 / IP被封禁——不属于适配器问题
软性停止(尝试后报告):
- 已用完3轮修复预算——停止操作,报告已尝试的方案和失败原因
- 功能已完全下线——所需数据已不存在
- 网站重大改版——需要通过技能完全重写适配器
opencli-explorer
在所有需要停止的场景中,清晰告知用户当前情况,不要做无意义的修补。
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 adapter at RepairContext.adapter.sourcePath — replace ".HotList-item" with ".HotItem"
6. AI verifies: opencli zhihu hot
→ Success: returns hot topics1. 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 adapter at RepairContext.adapter.sourcePath — replace ".HotList-item" with ".HotItem"
6. AI verifies: opencli zhihu hot
→ Success: returns hot topics