# 豆包提取失败追查(2026-10-16) ## 结论 确认并修复了一个可稳定复现的正文整理缺陷:请求 `http://example.com`,豆包正常返回同主机的最终 HTTPS 地址,旧整理器却按不同目标拒绝正文。旧候选包冷启动后仍失败;修复包在同一进程内的 22 次原生调用全部通过,不能用重启本身解释这组前后差异。 **原来两次 `https://example.com` 输入失败的根因仍未查清。** 原记录没有保留失败时的返回 URL 和挑战页判定。本轮对相同旧候选包连续执行 100 次 HTTPS 原生提取,均通过;按原调用顺序、切换单路/多路以及关闭网络捕获包装后也未复现。下面的 HTTP 升级缺陷不能被当作那两次 HTTPS 失败已证实的根因。原问题继续保留为未解决,不以重复成功替代归因。 后续已补充[针对原 HTTPS 故障的排查记录与调试器取证流程](./doubao-https-incident-20261016.md)。原问题仍未复现;进程内抓取机制已用独立的 HTTP 拒绝对照验证。 ## 版本与环境 - 基线:PR #2 原头 `3892979ea58bd9aecd7f5b027f86546d8fc2cfa3`;实际旧候选包 SHA-256 `ecc4a140509e5d7b7afd12505aa2d93d82bed6e7476a85f1c86ab0d1165bf6e8`。 - 修复源码、当时候选包与编译模块 SHA-256:见[脱敏证据](./doubao-fetch-20261016.json)。修复候选包内标签仍为 0.2.12,当时尚未发布,与正式 Release 资产不同;后续状态见文末「边界」。 - Windows 11 build 26300、Node.js 24.20.0、DSH 0.2.1-alpha.3、pnpm 12.10.1;独立 DSH_HOME 的真实完整 Web profile、CLI 安装、宿主 ToolRuntime 执行原生 `web_fetch`。 旧包的 HTTP 样本先在未修改的代码上复现。随后只在隔离副本已有的拒绝出口增加临时诊断,附请求/返回目标、状态及挑战判定;未改变成功路径或匹配规则。100 次 HTTPS 连续检查使用这个诊断副本,源码临时探针未进入修复包或 Git。所有请求仅使用公开示例 URL。 ## 已证实的失败链 豆包真实接口响应的 `Data.Url` 为原始请求地址,`Data.RedirectedUrl` 为最终重定向地址;这是 [Searchinfinity 官方协议](https://docs.byteplus.com/en/docs/searchinfinity/Searchinfinity_Fetch) 区分的两个字段。适配器返回最终地址符合 DSH `WebFetchResult.url` 的宿主契约,不能靠把它改回请求地址掩盖错误。 | 层面 | 实际值/结果 | | --- | --- | | 原生工具输入 | `http://example.com` | | API 层/目标页状态 | HTTP 200/200 | | API 原始地址/最终地址 | `http://example.com`/`https://example.com/` | | 适配器正文 | 标题加正文,919 字符 | | 登录/挑战判定 | false | | 旧整理器匹配数量 | 0:HTTP 与 HTTPS 目标字符串不同 | | 原生工具结果 | FAIL:没有可整理的目标网页正文 | 因此,此样本既不是接口余额问题,也不是缺少正文或挑战页;失败发生在适配器之后的目标匹配。对照 HTTPS 输入时,返回同一 HTTPS 最终地址,旧包通过。 ## 修复规则与回归 正文整理现在允许同主机、同路径、同查询参数、默认端口、无用户信息的 HTTP → HTTPS 升级。选择正常 HTTPS 正文时,原 HTTP 表示仍按不同目标隔离,不合入主正文。输出使用实际最终 URL,保留来源与宿主结果契约。 跨站、路径或查询变化、非默认端口、带用户信息的升级,以及 HTTPS → HTTP 降级继续拒绝。登录/挑战检查继续生效。不可用候选的错误附服务 ID 与 `target-mismatch`/`login-or-challenge` 等原因,不附 URL、凭证或正文;下一次失败无需再从同一条笼统错误猜测是哪一类拒绝。 新增 14 项回归检查:升级、最终 URL、HTTP/HTTPS 正文隔离、七种目标边界、结构化结果与非 2xx 正文、挑战页不遮蔽正常正文、诊断不泄露 URL 参数,以及真实适配器至 provider 的集成路径。最初 12 项独立回归在旧代码得到 7 PASS/5 FAIL;随后补充适配器集成及非 2xx 检查,修复后全量 39 个文件、760 项测试、类型与仓库检查通过。 独立 Spec 审阅无阻断性发现;Standards 指出的非 2xx 升级例外文档精度已修正,并补充回归。严格目标归一化与带方向的升级判定各保留其当前职责;非法状态的诊断兜底保留,不为审阅中的低优先级复用建议增加额外抽象。 ```sh pnpm exec vitest run test/fetch-redirect.test.ts test/additional-engines.test.ts test/content-organization.test.ts pnpm run check ``` ## 真实 DSH 修复后验证 安装修复候选包后,在同一进程内切换配置并执行以下原生调用,全程未重启: | 场景 | 结果 | | --- | --- | | 豆包单路,HTTP/HTTPS 交替 | 连续 20/20 PASS | | 切换全启用动态提取,HTTP 输入 | 10/10 适用服务成功,原生工具 PASS;GitHub 不适用于该域名 | | 再切回豆包单路,HTTPS 输入 | PASS | | 工具结构化元数据 | 22/22 均为最终 `https://example.com/`、目标状态 200 | 逐次输入、结果、耗时、服务日志、协议样本、旧包拒绝轨迹与原始 HTTPS 问题的状态分别保存在 JSON,未将网络层 200 单独当作原生工具通过。 验收后通过 CLI 卸载候选包,只清理本插件覆盖项、保留其他设置;重新启动的完整 profile 无本插件,provider 恢复为 deepseek-official/http,原生 HTTP 提取 200(674 ms)。随后停止隔离服务,释放验收端口并删除复制的凭证和代理环境文件。正式 DSH 包与配置未被替换。 ## 边界 本记录确认 HTTP 升级缺陷的根因及修复,不证明原历史 HTTPS 输入失败同源。没有足够的失败响应数据可还原那两次调用;需要未来再现时的明确拒绝原因或服务端历史响应才能完成归因。本轮未调用智谱独立付费 `tools-api`,未核对任何账户账单,也不代表 Store 已完成独立审阅。 事后补充:本页修复已进入 `0.2.13` 及之后的正式分发包;`0.2.14` 与 `0.2.13` 运行代码一致。原历史 HTTPS 输入失败仍保持未归因,issue #3 不因修复或后续成功调用关闭。