多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

OpenCLI 自修复协议(Self-Repair Protocol)实战:让 AI Agent 自动诊断、修复适配器并重试

OpenCLI 自修复协议(Self-Repair Protocol)实战:让 AI Agent 自动诊断、修复适配器并重试 OpenCLI 自修复协议Self-Repair Protocol实战让 AI Agent 自动诊断、修复适配器并重试【免费下载链接】OpenCLIMake Any Website into CLI Use your logged-in browser by AI agent.项目地址: https://gitcode.com/gh_mirrors/ope/OpenCLI导读本文基于 OpenCLI 仓库中的设计文档 designs/self-repair-protocol.md 展开系统讲解当网站变更 DOM、API 或响应结构导致opencli site command失败时AI Agent 如何不依赖人工干预、不依赖预先编写的 spec 文件自动完成采集证据 → 定位根因 → 修复适配器 → 重试验证的闭环。读完本文你将掌握--trace retain-on-failure的完整语义、trace 工件的内部结构summary / receipt / jsonl 事件流、错误信封与退出码契约、修复边界与 3 轮重试预算以及opencli-autofix技能中从收集证据到上报上游 issue 的全套可执行流程。一、问题定义为什么网站变了是最常见的适配器故障设计文档在 Problem Statement 中给出了一个非常明确的场景AI Agent 执行opencli site command命令因为网站改了 DOM、API 或响应 schema而失败。此时 Agent 应当自动修复适配器adapter并重试既不需要人介入也不需要预先写好的 spec 文件。从第一性原理出发Agent 自修复需要五样东西它刚刚运行失败的命令stderr 中的结构化错误信封error envelope适配器源码路径浏览器运行时证据action、页面状态、网络、console、截图即 trace 工件一个验证 oracle重新运行同一条命令。设计文档用一句话概括了这一哲学The command itself is the spec. The trace artifact is the evidence channel.命令本身就是规格说明trace 工件就是证据通道。这意味着Agent 不需要理解整个网站只需要围绕这条命令刚才为什么失败来收集证据、做最小修复、再验证。二、核心协议八步在线自修复循环设计文档给出了协议主流程原样继承如下Agent runs: opencli site command [args...] - Command succeeds - continue task - Command fails - 1. Re-run with --trace retain-on-failure to collect a trace artifact 2. Read trace.summaryPath from the error envelope 3. Read adapterSourcePath from summary.md front matter 4. Analyze: error code failed network console state/action timeline - root cause 5. Edit the adapter file at adapterSourcePath 6. Retry the original command 7. If still failing - repeat (max 3 rounds) 8. If 3 rounds exhausted - report failure, do not loop further关键语义拆解第 1 步的--trace retain-on-failure是证据采集开关。--trace的合法取值只有三个off默认、on、retain-on-failure。从源码看这个校验在 src/execution.ts 的TraceMode类型与参数解析中实现非法值会抛出ArgumentErroron模式在成功与失败时都会导出trace 工件而retain-on-failure只在失败时保留工件成功时静默丢弃避免在正常运行时留下大量磁盘垃圾。CLI 层默认值off定义在 src/cli.ts。第 2 步的trace.summaryPath来自 stderr 错误信封error envelope里的trace块。信封的完整结构定义在 src/errors.tsok: false、error.code、error.message、error.help、error.exitCode以及可选的trace.traceId / trace.dir / trace.summaryPath / trace.receiptPath / trace.status。第 3 步的adapterSourcePath写入在summary.md的 YAML front matter 中由 src/observation/artifact.ts 在导出时写入同时还附带adapterSourcePathExists布尔字段标记该路径是否为确认可编辑文件。第 4 步的分析依赖 summary 中预聚合的四个证据区Error、Failed Network、Suspicious Console、Action Timeline实现见 src/observation/artifact.ts。三、错误信封与退出码机器可读的错误契约自修复的前提是错误必须是结构化的。OpenCLI 统一了错误模型所有框架错误都继承CliError携带code机器可读错误码、hint修复提示和exitCodeUnix 退出码定义见 src/errors.ts。退出码遵循sysexits.h约定src/errors.ts退出码含义对应错误码0成功—1通用/意外错误COMMAND_EXEC、SELECTOR2参数/用法错误ARGUMENT66空结果EX_NOINPUTEMPTY_RESULT69服务不可用EX_UNAVAILABLEBROWSER_CONNECT、ADAPTER_LOAD75临时失败稍后重试EX_TEMPFAILTIMEOUT、SESSION_BUSY77需要登录/权限EX_NOPERMAUTH_REQUIRED、LOGIN_WALL78配置错误EX_CONFIGCONFIG130Ctrl-C 中断—几个与自修复直接相关的要点AUTH_REQUIRED退出码 77AuthRequiredError携带domain字段提示请打开 Chrome 登录该站点是硬停止信号——不能改代码只能让用户登录。BROWSER_CONNECT退出码 69BrowserConnectError进一步区分daemon-not-running、extension-not-connected、profile-required等 kind提示运行opencli doctor排查。EMPTY_RESULT退出码 66EmptyResultError的 hint 明确写着页面结构可能变了或者你需要登录——这正是自修复要甄别的两种情况。LOGIN_WALL当 JSON 接口返回 HTML登录墙/限流页/WAF 挑战时抛出避免 Agent 看到晦涩的JSON.parse语法错误而误判为适配器 bug。trace 工件的回传机制也非常巧妙attachTraceReceipt用Symbol.for(opencli.traceReceipt)把ObservationTraceReceipt挂到错误对象上不可枚举、不可修改toEnvelope在序列化错误信封时通过getTraceReceipt取回并展开为trace块src/errors.ts、src/errors.ts。这样无需任何额外环境变量错误信封本身就携带了去哪找证据的指针。四、Trace 工件运行时证据通道的内部结构4.1 目录布局trace 工件导出在~/.opencli/profiles/contextId/traces/traceId/下contextId缺省为default路径拼接逻辑见 src/observation/artifact.ts。工件目录结构为summary.md # 从这开始读LLM 导向的摘要 YAML front matter receipt.json # 机器可读的 trace 收据 trace.jsonl # 完整脱敏事件时间线 network.jsonl # 脱敏网络事件 console.jsonl # 脱敏 console 事件 state/ # 最终状态快照可用时 screenshots/ # 最终截图可用时4.2 summary.mdLLM 的入口summary.md的 front matter 与正文均由renderSummary生成src/observation/artifact.ts示例如下--- schemaVersion: 1 opencliVersion: ... traceId: ... status: failure contextId: default session: ... site: example command: example/search adapterSourcePath: /path/to/clis/example/search.js adapterSourcePathExists: true traceDir: ... startedAt: ... exportedAt: ... expiresAt: ... errorCode: SELECTOR errorMessage: Could not find element: .old-selector ---正文按Error → Failed Network → Suspicious Console → Action Timeline → Event Counts → Artifact Files组织其中Error序列化主错误 最近 20 条 error 事件Failed Networkstatus为undefined / 0 / 400的网络事件最多 20 条src/observation/artifact.tsSuspicious Consolelevel 匹配error|warning|warn|assert的 console 事件最多 20 条Action Timeline最近 30 条 action 事件含phasestart/end/error与脱敏后的 data。设计文档明确建议先从 summary 开始只有当摘要证据不足时才深入trace.jsonl——这正是为了控制 LLM 的 token 开销。4.3 事件流与环形缓冲区六类事件流action / network / console / screenshot / state / error定义在 src/observation/events.ts各自有独立的类型如NetworkObservationEvent携带url/method/status/contentType/requestHeaders/responseHeaders/requestBody/responseBody。运行时事件在内存中通过环形缓冲区RingBuffer缓存默认窗口120 秒、每流上限1000 条、截图与状态快照每流上限50 条见 src/observation/session.ts。traceId 的生成格式为YYYYMMDDHHmmss-4字节随机hexsrc/observation/session.ts。4.4 脱敏证据可以共享机密必须剔除由于 trace 工件会被交给 LLM 分析脱敏是硬需求。src/observation/redaction.ts 实现了三层防护敏感请求头authorization / cookie / set-cookie / x-api-key / x-csrf-token等整体替换为[REDACTED]URL 查询参数中的token / key / secret / password / auth / api_key / session_id / csrf / xsrf值被脱敏文本中的 Bearer token、JWTeyJ...三段式、JSON 键值对中的密码/token 字段均被替换且字符串默认截断到 50KB、对象递归深度上限 5 层、数组上限 100 项。4.5 保留策略防止磁盘被 trace 淹没每次导出后都会执行一次清理pruneTraceArtifactsBestEffort默认保留策略为最长保留 7 天、每 profile 最多 20 份、每 profile 总上限 500MB见 src/observation/retention.ts。清理按过期 → 超数量 → 超容量三级剪枝刚导出的当前 trace 目录被标记为 protected 不会被误删。receipt.json中的expiresAt是参考值实际删除由当前保留策略决定src/observation/events.ts。五、适配器源码定位绝不猜路径设计文档强调Agent必须使用 trace summary 中的路径而不是猜测仓库相对路径。这对 npm 安装用户至关重要——他们的clis/目录根本不在工作目录里。adapterSourcePath的取值可能有两种clis/site/*.js—— 源码检出source checkout下的仓库本地适配器~/.opencli/clis/site/*.js—— npm 安装场景下的用户本地适配器。底层解析逻辑在 src/adapter-source.ts 的resolveAdapterSourcePath优先级为cmd.sourceFS 扫描的 JS 命令→cmd._modulePathmanifest 懒加载的 JS 命令并跳过manifest:前缀的伪路径内联在 manifest 中的 YAML 命令没有可编辑的独立文件。永不修改的目录Scope Constraint原文档原文src/**—— 核心运行时extension/**—— 浏览器扩展autoresearch/**—— 研究基础设施tests/**—— 测试文件package.json、tsconfig.json—— 项目配置六、修复边界什么情况下不修比修更正确设计文档用一张表格明确了五类禁止自修复的信号原样继承信号含义动作Auth/login errorChrome 中未登录该站点告诉用户登录不要改代码Browser bridge not connected扩展/daemon 未运行告诉用户运行opencli doctorCAPTCHA站点要求人工验证上报不改代码Rate limited / IP blocked不是适配器问题上报等待后重试Feature removed by site数据已不存在上报适配器可能需要标记废弃对应到opencli-autofix技能里这些被称为Hard Stops硬停止AUTH_REQUIRED退出码 77、BROWSER_CONNECT退出码 69、CAPTCHA/限流一律STOP不进入修复循环。技能文件 skills/opencli-autofix/SKILL.md 原样写明了这三条硬停止规则。七、重试预算3 轮上限每次命令失败最多3 轮修复每轮 trace 采集 → 编辑适配器 → 重试命令如果修复尝试后错误完全相同说明这次修复无效必须换一种思路3 轮耗尽后停止向用户报告尝试过什么、失败在哪。这与--trace retain-on-failure的失败才保留工件语义配合默契每一轮重试失败都会覆盖式地产生新证据Agent 无需手动管理多份 trace。八、opencli-autofix 技能可移植的自修复协议设计文档的核心交付物是AutoFix 技能opencli-autofixskills/opencli-autofix/SKILL.md。任何 AI Agent 都可以加载该技能获得完整工作流其 front matter 声明了allowed-tools: Bash(opencli:*), Bash(gh:*), Read, Edit, Write并定义了两个控制轴-v / OPENCLI_VERBOSE human-readable logs人类可读日志 --trace off|on|retain-on-failure machine-readable browser evidence artifact机器可读浏览器证据工件8.1 九步协议技能指令 Agent 按以下顺序执行当opencli site command失败时不要只报告错误用--trace retain-on-failure重跑读取错误信封的trace.summaryPath解析summary.mdfront matter 中的adapterSourcePath读取并修复该精确路径下的适配器重试原始命令如果重试通过询问用户是否要为jackwener/OpenCLI提交上游 issue用户同意且gh可用时用结构化摘要提交 issue最多 3 轮修复然后停止。8.2 Empty ≠ Broken修复前的甄别技能特别强调一个容易误判的陷阱EMPTY_RESULT——甚至结构上合法的SELECTOR返回空——往往不是适配器 bug。平台会在反爬启发式下主动降级结果not found 不代表内容真的没了。修复前必须排除换一个查询词或入口重试如果opencli xiaohongshu search X返回 0但X 攻略返回 20说明适配器没问题是平台对第一个查询做了结果塑形在普通 Chrome 标签页抽查如果用户自己的浏览器能看到数据而适配器返回空通常是登录态、限流或软封禁应走opencli doctor/ 重新登录而不是改源码警惕软 404小红书/微博/抖音等站点对隐藏或删除的内容返回 HTTP 200 空载荷快照结构看起来正常隔 2~3 秒重试往往能区分暂时隐藏与真的没了0 结果本身就是答案适配器成功到达搜索端点、拿到 HTTP 200、平台返回results: []这就是合法答案——报告此查询无匹配即可不要去补丁一个工作正常的适配器。只有当空结果/选择器缺失在多次重试与多个入口下都可复现时才进入 Step 1。否则就是在追逐噪声打补丁打出来的补丁会破坏下一个正常工作的路径。8.3 错误码 → 根因 → 修复策略映射技能给出了一份错误分类表原样继承核心列错误码可能原因修复策略SELECTORDOM 重构、class/id 改名探索当前 DOM → 找新选择器EMPTY_RESULTAPI 响应 schema 变了或数据挪了位置查网络 → 找新响应路径API_ERROR端点 URL 变了、需要新参数通过网络拦截发现新 APIAUTH_REQUIRED登录流程变化、cookie 过期STOP—— 让用户登录不改代码TIMEOUT页面加载方式变了、spinner/懒加载增补/更新等待条件PAGE_CHANGED重大改版可能需要整体重写适配器分析时要回答四个问题适配器想做什么读adapterSourcePath文件失败时页面长什么样读summary.md必要时读state/发生了什么网络请求读 summary 的Failed Network再深入network.jsonl适配器期望与页面实际的差距在哪8.4 探索现状只用opencli browser绝不用坏掉的适配器DOM 变了SELECTORopencli browser open https://example.com/target-page opencli browser stateAPI 变了API_ERROR / EMPTY_RESULT用网络拦截器打开页面 → 手动触发动作 → 查看网络请求 → 用字段过滤 → 查看具体响应opencli browser open https://example.com/target-page opencli browser state opencli browser click N opencli browser network opencli browser network --filter author,text,likes opencli browser network --detail key8.5 打补丁最小改动与常见修复先读取adapterSourcePath以 summary front matter 中的精确路径为准用 Read 工具再做定点修复。四种常见修复原文档示例原样继承// 选择器更新 // Before: page.evaluate(document.querySelector(.old-class)...) // After: page.evaluate(document.querySelector(.new-class)...) // API 端点变更 // Before: const resp await page.evaluate(fetch(/api/v1/old-endpoint)...) // After: const resp await page.evaluate(fetch(/api/v2/new-endpoint)...) // 响应 schema 变更 // Before: const items data.results // After: const items data.data.items // API 现在嵌套在 data 下 // 等待条件更新 // Before: await page.wait({ selector: .loading-spinner, hidden: true }) // After: await page.wait({ selector: [data-loadedtrue] })补丁六条铁律技能原文要点最小改动——只修坏的部分不做重构保持输出结构一致——columns与返回格式必须兼容优先 API 而非 DOM 抓取——探索中发现 JSON API 就切换到它只用jackwener/opencli/*导入——绝不引入第三方包补丁后必须测试——重跑命令验证绝不放宽verify/cmd.json夹具来掩盖失败——失败的patterns / notEmpty / mustNotContain / mustBeTruthy规则意味着适配器输出坏了应该收紧适配器产出正确值唯一的合法例外是站点自身形态变化如 URL 格式迁移此时才更新夹具并在~/.opencli/sites/site/notes.md记录变更。否则改夹具就是在掩盖静默的正确性回归。8.6 验证与上报验证即重跑原始命令仍失败则回到 Step 1 重新采集 trace预算为 3 轮。重试通过后说明本地适配器已与上游漂移应提交上游 issue。不要提交的三种情况环境/用法类错误AUTH_REQUIRED / BROWSER_CONNECT / ARGUMENT / CONFIG、CAPTCHA/限流上游无法修复、3 轮耗尽仍未修好。只有本地修复验证通过后才提交。Issue 标题格式为[autofix] site/command: error_code如[autofix] zhihu/hot: SELECTOR正文按模板填写Summary本地修复且重试通过、Adapter站点/命令/版本、Original failure错误码与消息、Local fix summary一两句改动说明。提交前必须征得用户同意然后gh issue create --repo jackwener/OpenCLI \ --title [autofix] site/command: error_code \ --body the body above若gh未安装或未认证告知用户并跳过不要报错中断。8.7 完整修复会话示例来自技能文档1. User runs: opencli zhihu hot → Fails: SELECTOR Could not find element: .HotList-item 2. AI runs: opencli zhihu hot --trace retain-on-failure 2trace-error.yaml → Gets trace summary with final state and failed action evidence 3. AI reads summary/state: page loaded but uses .HotItem instead of .HotList-item 4. AI explores: opencli browser open https://www.zhihu.com/hot opencli browser state → Confirms new class name .HotItem with child .HotItem-content 5. AI patches: Edit adapter at adapterSourcePath — replace .HotList-item with .HotItem 6. AI verifies: opencli zhihu hot → Success: returns hot topics 7. AI prepares upstream issue draft, shows it to the user 8. User approves → AI runs: gh issue create --repo jackwener/OpenCLI --title [autofix] zhihu/hot: SELECTOR --body ...注意第 2 步的2trace-error.yamlstderr 中的错误信封含trace块被重定向到文件Agent 从文件中读取trace.summaryPath即可无需用户参与。九、与 PR #863 的关系自修复是入口spec 是资产层设计文档明确说明PR #863spec/runner/incident 框架不是 Phase 1 的必需品它是后续的加固层Phase 1通过opencli-autofix技能 trace 工件实现自修复Phase 2高频失败被固化为命令 spec用于离线回归测试和 CI。spec/runner 框架是资产层它把一次性的临时修复转化为可复用的测试但它不是入口点。这一分层让协议可以先用最小机制跑通命令即 spec、trace 即证据再逐步沉淀可回归的资产。十、使用方式零新命令设计文档强调没有新命令、没有新脚本。Agent 加载opencli-autofix技能后正常使用 opencli 即可完整流程演示原文档示例# Agent 作为任务的一部分运行命令 opencli weibo hot --limit 5 -f json # 如果失败Agent 自动 # 1. 运行 opencli weibo hot --limit 5 -f json --trace retain-on-failure 2trace-error.yaml # 2. 从 trace-error.yaml 读取 trace.summaryPath # 3. 从 summary.md 读取 adapterSourcePath # 4. 修复 adapterSourcePath 处的适配器 # 5. 重试opencli weibo hot --limit 5 -f json # 6. 如果重试通过询问是否提交上游 issue # 7. 如果同意运行 gh issue create --repo jackwener/OpenCLI ... # 8. 继续任务十一、测试与验证协议的可回归性协议的关键行为都有测试覆盖可作为自修复流程的验证依据src/execution.test.ts 验证trace: retain-on-failure模式下失败会抛出并触发 trace 导出路径src/cli.test.ts 验证--trace原样透传给适配器子进程hn top --trace retain-on-failure --format json并确认 help 文本包含--trace modesrc/commanderAdapter.test.ts 验证错误信封输出中带有--traceretain-on-failure的 AutoFix 提示行提示文案来自 src/commanderAdapter.tsAutoFix: re-run with --traceretain-on-failure for trace artifact。这套测试保证了错误信封 → trace 工件 → adapter 定位的证据链在每次迭代中不退化。小结OpenCLI 的自修复协议是一个典型的小机制、大闭环设计--trace retain-on-failure只新增了一个参数却把失败的证据做成了标准化的、脱敏的、可被任意 LLM 读取的工件错误信封 退出码把失败分类成了该修的和不该修的opencli-autofix技能则把整套流程封装成任何 Agent 都能加载的可移植协议。它不追求一次性解决所有网站变更而是用 3 轮重试预算 硬停止规则守住边界再用验证通过后上报上游 issue把本地修复回灌到社区——这正是命令即 spec、trace 即证据哲学在工程上的落地。【免费下载链接】OpenCLIMake Any Website into CLI Use your logged-in browser by AI agent.项目地址: https://gitcode.com/gh_mirrors/ope/OpenCLI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表