Skip to content

✨ sctl Browser 第 4 期调试 - #6

Merged
CodFrm merged 14 commits into
mainfrom
feat/browser-debugging
Oct 8, 2026
Merged

CodFrm merged 14 commits into
mainfrom
feat/browser-debugging

Conversation

@CodFrm

@CodFrm CodFrm commented Oct 8, 2026

Copy link
Copy Markdown
Member

概要

sctl Browser 第 4 期:调试。AI agent 和脚本可以经命令行和 MCP 读取标签页的控制台、JS 异常、浏览器警告和网络请求。也可以先开始录制,让用户复现问题,再回来查询。

改动

  • 新命令:sctl debug start/stop/status/console/network/request/clear,每个对应一个 MCP 工具 debug_*。
  • 记录:
    • 调试器附加期间一直缓存,无论附加是由哪条命令引起的。
    • 每个标签页最多保存 1000 条控制台记录和 1000 个请求,每种缓存另限 32 MiB,超出时丢弃最旧的并报告 dropped。
    • 导航后记录保留。调试器断开或执行 debug clear 时清空。数据不写盘。
  • 控制台:
    • 三种来源:console、exception、browser(CSP 违规、资源加载失败)。
    • 文本按 DevTools 的方式拼成一行,对象显示为预览,单条超过 10,000 字符时截断。
    • 附加时 Chrome 回放当前文档的消息,回放的记录照常进缓存。
  • 网络:
    • 每个请求一条记录,重定向的每一跳各一条并指向上一跳;进行中、失败、取消、来自缓存都有标记。
    • 支持 url、method、status、type、failed 筛选。
    • debug request 给出未打码的头、各阶段耗时和远端地址。
    • 请求体和响应体经新增的 internal 方法 debugger.body,由扩展在浏览器里取回、截断到 1 MiB 后回传:文本按字符边界截断,二进制以 base64 返回,并给出原始大小;取不到时写明原因,退出码 0。
  • 跨进程 iframe:附加期间新出现的 iframe 先暂停,开启记录后放行,所以最早的请求也能收全;记录带 frameUrl。
  • 查询:用不透明游标续查,带 hasMore;游标不属于当前缓存时返回 cursorReset。结果带 contentTrust: "untrusted-page-content"。
  • 录制:
    • debug start 后,daemon 的 5 分钟空闲断开和扩展的 10 分钟兜底断开(新增 internal 方法 debugger.record)都不生效。
    • 录制在 debug stop、60 分钟没有任何 debug 命令、或调试器断开时结束。
  • JS 弹框(修正轮,改变第 3 期):
    • 弹框期间 debug request 不再等待,请求体和响应体写明「页面有未处理的 JS 弹框」。
    • sctl 自己断开调试器前,先关闭已知的弹框;适用于 page detach / --all、空闲断开、扩展的兜底断开、断线或 daemon 退出。以前这种情况会留下谁都处理不了的孤儿弹框。
    • 附加 5 秒无回应时,返回新错误码 PAGE_UNRESPONSIVE;page goto/page reload 能把这样的标签页救回。
  • 协议:新增 internal 方法 debugger.record、debugger.body 和错误码 PAGE_UNRESPONSIVE。给 ScriptCat 的生成 TS 逐字节不变。没有新增浏览器权限,最低版本仍为 Chrome 125。
  • 文档:AGENTS、architecture、protocol、threat-model(头和体不打码)、mcp 和两份 README。

验证

自动化检查(交付树 e2f77e4)

  • go build、go vet、go test ./... -race -count=1、golangci-lint(0 issues)、make protocol-check 全部 exit 0。
  • 扩展的 lint、format:check、typecheck、test(613/613)、build 全部 exit 0。
  • 只有假 CDP 和 mock 测试,不提交直连真浏览器的测试。

审查

  • 两轮,每轮都做 spec 核对和代码审查。
  • 第二轮在修正轮之后,审查整个分支。

真机验证(Chrome for Testing 125,headless,隔离临时配置,同时加载本分支的 sctl Browser 与 ScriptCat,连临时 daemon;不使用日常浏览器配置)

  • 第 1 轮(630f4a9):44 条需求中,2 条不成立:

    • 弹框时 --body 等满 10 s 超时;
    • 弹框已打开时附加会卡住,main 上的第 3 期同样如此。

    这两条促成了修正轮。

  • 第 2 轮(e2f77e4,脚本化):79 条检查全部成立。

    • 1 条最初是验证脚本自身的 UTF-8 拼接问题,直接重测成立。
    • 录制期间 11 分钟不发命令,仍保持附加,超过 daemon 的 5 分钟和扩展的 10 分钟。
    • stop --all 后 5 分钟断开并清空。
    • 弹框时取体 33 ms 返回原因;page detach、daemon 退出、5 分钟空闲断开之前都会关闭弹框;外部留下的孤儿弹框在 5 s 内返回 PAGE_UNRESPONSIVE,page reload 能救回。

未在真机上观察(均有单元测试覆盖)

  • 60 分钟无查询自动结束(没有真等)。
  • 录制期间提示条一直显示:headless 下没有提示条,以「一直附加」作为替代观察。
  • 浏览器实例断开、用户点提示条「取消」。
  • 扩展兜底断开和 page detach --all 路径上的关闭弹框。

已知限制

  • 用户点提示条「取消」仍可能留下孤儿弹框,这不在 sctl 控制之内。之后附加会返回 PAGE_UNRESPONSIVE,可以用 page reload 或 page goto 恢复;恢复时页面会加载两次。
  • 单个超过 4 MiB 的调试事件会被整条丢弃。
  • 附加前回放的对象参数没有预览,Chrome 回放时不带预览。

CodFrm added 14 commits October 4, 2026 20:22
…e 先暂停、开启记录后放行;browser 来源不含废弃 API 警告;单条超过 4 MiB 的事件整条丢失
…ame 子会话开启 Runtime/Log(新 iframe 先暂停、开启后一定放行),控制台/异常/浏览器消息转成记录存入每个标签页 1000 条的环形缓存,支持筛选、不透明游标与 cursorReset、limit/hasMore,断开即清空
… iframe 子会话开启 Network(maxPostDataSize 限制内联请求体,networkidle 语义不变),每个请求与每跳重定向一条记录(指向上一跳,进行中/失败/来自缓存),按 url/方法/状态类/类型/失败筛选;请求详情给出未打码的头、各阶段耗时与远端地址,请求体与响应体经新增 internal 方法 debugger.body 由扩展取回并截断到 1 MiB,不可用时写明原因
…录制中的标签页保持附加(finish 不布置 5 分钟空闲断开,经 debugger.record 让扩展也不兜底断开),stop 为不附加的浏览器级动作(--all 作用于全部录制中的标签页)并恢复空闲计时;60 分钟没有 debug 命令自动结束录制(每条 debug 命令重新计时,排进标签页队列并用 seq 作废晚到的计时器),所有断开路径都结束录制;status 列出附加的标签页、录制剩余时间与各缓存条数和丢弃数,Clock 增加 Now
…要约 1.3 s(生产截断仅 1 ms),满载跑全套时超出 5 s 而偶发超时;比较规范 base64 字符串更严格且只需 1 ms
…算;architecture.md 补上网络记录缓存与按需取体,AGENTS.md 概述写明 sctl debug 也读网络请求
… GB;每种缓存另限 32 MiB(含等待请求的 ExtraInfo 头),记录后来变大时重新计入,超出丢弃最旧的;debug request 截断时写出实际返回的字节数;合并 cutRunes/truncateRunes 与控制台事件解码;不认识的体不可用代码报错而非兜底;删去只比较常量的扩展测试与无用导出
…因;sctl 自己断开前先关闭已知弹框以免留下孤儿弹框(改变第 3 期不自动处理的规则);附加命令 5 秒无回应返回 PAGE_UNRESPONSIVE 并提示用 page reload/goto 恢复
…:getResponseBody/getRequestPostData 一直阻塞到弹框关闭,取体途中弹框打开也立即放弃);sctl 自己断开调试器前先 dismiss 已知弹框(page detach、--all、5 分钟空闲断开、放弃的附加,扩展的兜底空闲断开、断线释放与 daemon 请求的断开;扩展记下弹框并存进 storage.session),不再留下之后谁都处理不了的孤儿弹框;附加命令每步 5 秒无回应即放弃附加并返回新错误码 PAGE_UNRESPONSIVE(exit 3),page goto/reload 先在新会话上只发这次导航关掉遗留弹框再重新附加,所以确实能恢复;第 3 期 DIALOG_OPEN 不变,ScriptCat 生成 TS 不变
…的兜底空闲断开与断线释放,原括号只列 page detach 与 5 分钟空闲断开,与两份 README 和 mcp.md 不一致
…g 会让扩展悄悄重新附加,page detach --all 也已关闭过它;page goto/reload 恢复用的导航被浏览器拒绝(不合法的 URL、不可调试的页面)时返回拒绝的原因而不是让调用方再用同一个导航恢复的 PAGE_UNRESPONSIVE,照常断开;page detach 与 debug stop 共用 --all 输入与结果摘要的实现
@CodFrm
CodFrm merged commit b3e1184 into main Oct 8, 2026
4 checks passed
@CodFrm
CodFrm deleted the feat/browser-debugging branch October 8, 2026 03:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant