opencli-repair

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

OpenCLI 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 connectivity
bash
opencli doctor    # 验证扩展和守护进程的连通性

When to Use This Skill

何时使用本技能

Use when
opencli <site> <command>
fails with errors like:
  • 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.json
This outputs a
RepairContext
JSON between
___OPENCLI_DIAGNOSTIC___
markers in stderr:
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
该命令会在标准错误流的
___OPENCLI_DIAGNOSTIC___
标记之间输出
RepairContext
格式的JSON:
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
undefined

Extract JSON between markers from stderr output

从标准错误输出中提取标记之间的JSON内容

cat diagnostic.json | sed -n '/OPENCLI_DIAGNOSTIC/{n;p;}'
undefined
cat diagnostic.json | sed -n '/OPENCLI_DIAGNOSTIC/{n;p;}'
undefined

Step 2: Analyze the Failure

步骤2:分析故障原因

Read the diagnostic context and the adapter source. Classify the root cause:
Error CodeLikely CauseRepair Strategy
SELECTORDOM restructured, class/id renamedExplore current DOM → find new selector
EMPTY_RESULTAPI response schema changed, or data movedCheck network → find new response path
API_ERROREndpoint URL changed, new params requiredDiscover new API via network intercept
AUTH_REQUIREDLogin flow changed, cookies expiredWalk login flow with operate
TIMEOUTPage loads differently, spinner/lazy-loadAdd/update wait conditions
PAGE_CHANGEDMajor redesignMay need full adapter rewrite
Key questions to answer:
  1. What is the adapter trying to do? (Read the
    source
    field)
  2. What did the page look like when it failed? (Read the
    snapshot
    field)
  3. What network requests happened? (Read
    networkRequests
    )
  4. What's the gap between what the adapter expects and what the page provides?
读取诊断上下文和适配器源码,归类根因:
错误码可能原因修复策略
SELECTORDOM结构重构,类名/id重命名探查当前DOM → 找到新的选择器
EMPTY_RESULTAPI响应 schema 变更,或数据位置迁移检查网络请求 → 找到新的响应路径
API_ERROR接口URL变更,需要新增参数通过网络拦截发现新的API
AUTH_REQUIRED登录流程变更,Cookie过期使用operate模拟登录流程
TIMEOUT页面加载逻辑变更,新增了加载动画/懒加载逻辑新增/更新等待条件
PAGE_CHANGED网站大版本改版可能需要完全重写适配器
需要明确的核心问题:
  1. 适配器原本要实现什么功能?(读取
    source
    字段)
  2. 故障发生时页面是什么状态?(读取
    snapshot
    字段)
  3. 触发了哪些网络请求?(读取
    networkRequests
  4. 适配器的预期和页面实际提供的内容之间有什么差异?

Step 3: Explore the Current Website

步骤3:探查当前网站状态

Use
opencli operate
to inspect the live website. Never use the broken adapter — it will just fail again.
使用
opencli operate
检查线上网站状态。不要使用已经损坏的适配器 — 它只会再次报错。

DOM changed (SELECTOR errors)

DOM变更(SELECTOR错误)

bash
undefined
bash
undefined

Open 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

对比快照和适配器的预期内容

undefined
undefined

API changed (API_ERROR, EMPTY_RESULT)

API变更(API_ERROR、EMPTY_RESULT)

bash
undefined
bash
undefined

Open 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>
undefined
opencli operate network --detail <index>
undefined

Auth changed (AUTH_REQUIRED)

认证逻辑变更(AUTH_REQUIRED)

bash
undefined
bash
undefined

Check 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
undefined
opencli operate state # 查找登录表单字段
undefined

Step 4: Patch the Adapter

步骤4:修复适配器

Read the adapter source file and make targeted fixes:
bash
undefined
读取适配器源码文件,进行针对性修复:
bash
undefined

Read the adapter

读取适配器源码

cat <sourcePath from diagnostic>
undefined
cat <sourcePath from diagnostic>
undefined

Common 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

修复规则

  1. Make minimal changes — fix only what's broken, don't refactor
  2. Keep the same output structure
    columns
    and return format must stay compatible
  3. Prefer API over DOM scraping — if you discover a JSON API during exploration, switch to it
  4. Use
    @jackwener/opencli/*
    imports only
    — never add third-party package imports
  5. Test after patching — run the command again to verify
  1. 最小修改原则 — 只修复损坏的部分,不要进行重构
  2. 保持输出结构一致
    columns
    和返回格式必须保持兼容
  3. 优先使用API而非DOM爬取 — 如果探查过程中发现了JSON API,切换到API方式实现
  4. 仅允许使用
    @jackwener/opencli/*
    导入
    — 不要添加第三方包依赖
  5. 修复后测试 — 重新运行命令验证功能正常

Step 5: Verify the Fix

步骤5:验证修复结果

bash
undefined
bash
undefined

Run 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
    opencli-explorer
    skill
  • 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 topics
1. 用户运行: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
   → 成功:返回热榜内容