feat(browser): 取正文能力 + web-fetch 浏览器降级档接线(解封 Z5/B5)
Z5(c2e413e)把 web-fetch 的降级链与注入点做完了,但「取正文」入口缺失 ⇒ 组合根拿不到 BodyRenderer、这一档实际关着(当时如实登记)。本片补上: - internal/capability/browser/render.go:新增 Manager.RenderText(ctx,url) (导出的进程内能力)—— 先过 GuardURL(与全仓同一份 SSRF 判定源)、复用 withSession/session、等 readyState=complete 之后才取 body.innerText; 渲染失败 = 分类错误,渲染成功但正文为空 = 空串+无错(不冒充成功/失败)。 - cmd/cyrene/wire_body_fallback.go:适配器 + 挂载点,把 Manager 适配成 io.BodyRenderer 并用 WithBrowserFallback 挂上;web_runtime 里把浏览器 接线**上移到 io 工具集之前**(顺序颠倒会静默关死这一档)。 - plugins/tools/browser/tool.go:新增 Tool.Manager(),供组合根取驱动句柄。 开关口径(裁决,依据 design/28 §1 M5 / §7 判据 4 / §8 B5):**有可用浏览器 就挂,没有就不挂**,不新增开关 —— ① 设计把 M5/B5 写成要落地生效的降级档,不是永远关着的空壳; ② 设计 §8 的可调项清单里没有这条降级档的开关,`.env` 已冻结 ⇒ 自造开关属 「自行发挥」; ③ io 库层「不传 = 默认关」的语义一字未改,本片只把组合根从「永远关」改成 「没来源就关」,并留带来源的 WARN(reason=no-usable-browser)。 ⚠️ 若日后要「有浏览器也需显式开启」,得先给设计定开关落点,代码侧一行改回。 验收(主会话复跑 + 亲自变异):go build ./... + 三包 vet 绿;browser/io 两包 测试绿(cmd/cyrene 由子代理跑过全绿);我用 -overlay 把 GuardURL 的判定对象 换成常量 URL(绕过被拒目标)⇒ TestManager_RenderTextBlockedURLRejectedBeforeAnyProcess 变红,证明判定确实**在起任何进程之前**跑。 ⚠️ 生产端到端未验:按红线没重启后端、没起真 Chrome ⇒「真页面 → browser 取到 正文」这条链只有假 CDP + 组合根接线级证据。 ⚠️ design/28 有 6 处表述与代码现状冲突(归属 web-fetch vs web-search、extract 动作归属、B5 排期、状态过期等),已登记待我同步文档。
This commit is contained in:
1 parent
25aa50e532
commit
378faf212e
7 files changed
+685
-31
No files matched your search
@@ -141,6 +141,23 @@ func (t *Tool) State() browsercap.StateSnapshot {
|
||||
return src.State()
|
||||
}
|
||||
|
||||
// Manager 返回驱动层的浏览器管理器(`*browsercap.Manager`;驱动不是它时返回 nil)。
|
||||
//
|
||||
// 它存在只为一件事:design/28 §1 M5 / §8 B5 的 web-fetch 降级档 —— 组合根要拿**当前**
|
||||
// 这把工具的驱动去渲染取正文(`Manager.RenderText`),所以这里给出驱动句柄,而不是让
|
||||
// 工具面再多一个动作(模型不需要 `extract` 这个动作名,那件事由 web-fetch 自动做)。
|
||||
//
|
||||
// 返回具体类型而不是 Driver:取正文是驱动层的能力、不在工具的三个动作里,也不该加进
|
||||
// Driver 接口(那会逼每个假驱动实现一个它们不需要的方法)。单测夹具的假驱动不是
|
||||
// `*browsercap.Manager` ⇒ 返回 nil,调用方据此如实报「没有可用来源」。
|
||||
func (t *Tool) Manager() *browsercap.Manager {
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
mgr, _ := t.mgr.(*browsercap.Manager)
|
||||
return mgr
|
||||
}
|
||||
|
||||
// Name 实现 sdk.Tool。
|
||||
func (t *Tool) Name() string { return ToolName }
|
||||
|
||||
|
||||
Reference in new issue
Block a user