bug: 内建 WebFetch 抓取超大响应(≥~2MB,如 GitHub API 递归 tree JSON)时静默截断,摘要模型基于残缺数据输出自信的错误结论
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 395
- Avg merge
- 21h 48m
- Merged PRs (30d)
- 776
Description
### 问题描述 / What happened
Agent 会话中的内建 `WebFetch` 工具(来自捆绑的 Claude Code CLI 2.1.219 内建实现)在抓取超大响应时**静默截断**,截断后的内容被喂给"小快模型"做摘要,而该模型**不知道自己看到的是残缺数据**,因此会输出自信的错误结论——不是报错、不是"看不全",而是把残缺当完整。
实测案例(本 issue 的直接诱因):
- 抓取 `https://api.github.com/repos/makecindy/cindy/git/trees/main?recursive=1`(真实响应 2,498,762 字节,GitHub API 明确返回 `"truncated": false`,7808 条完整 tree 条目)。
- WebFetch 返回的结论称:**"该仓库没有 packages/ 目录"**、只列出了字母序开头的少量路径(`.githooks` → `apps/desktop/scripts/gen-help-kb.mjs`,恰好是字节上限的截断点)。
- 用 `curl` 直查同一 URL 对照:`packages/` 目录真实存在(28 个包,含 maker-core、anthropic-compat-proxy、responses-anthropic-bridge 等),tree 完整无截断。
对 agent 场景,"自信的假信息"比显式报错危险得多:下游规划/结论会建立在不存在的"事实"上。
**上游风险**:该截断行为在上游 anthropics/claude-code 已有多个相关 issue 且均未解决(#51783 大页面截断行为未文档化、#74650 摘要器编造源页面不存在的内容、#77811 摘要器冷启动泄漏父会话上下文)。上游长期未修复意味着:**Cindy 原生捆绑使用 claude-code 时,静默截断 → 摘要模型自信误报(甚至编造内容)的风险会持续存在**。
工具自述文档明确写了 "Results may be summarized if the content is very large"——大内容摘要化是**设计行为**,但实现存在三个缺陷:
1. **截断不透明**:喂给摘要模型的内容没有 `[TRUNCATED]` 之类的显式标记,模型无法知道自己在看前缀;
2. **无 fail-loud 通道**:超限时既不报错也不提示,摘要照常返回;
3. **对 JSON 等结构化文本仍走 HTML→markdown 化**:JSON 无需 markdown 化,可按 content-type 走原始文本路径,减少体积与语义损失。
期望行为(任一即可):
- 超限时显式报错(fail-loud),或
- 在喂给摘要模型的内容中带显式截断标记,使其无法"自信地"输出残缺结论,或
- 按 content-type 对 JSON 走原始文本路径并告知内容大小。
### 环境 / Environment
- Cindy 版本或 commit:**0.1.31**(本机安装版,update 日志 2026-08-06 实测;桌面端)
- 平台与 OS 版本:Windows 10 Pro 10.0.19045
- 安装方式:官方安装包
- 复现通道:桌面端会话 + 自定义模型(deepseek-v4-flash)+ 内建 WebFetch 工具;WebFetch 为捆绑的 Claude Code CLI(2.1.219)内建实现,Cindy 侧仅做权限门控
### 复现步骤 / Steps to reproduce
1. 在桌面端新建会话(任意模型)
2. 让 agent 调用 WebFetch 抓取 `https://api.github.com/repos/makecindy/cindy/git/trees/main?recursive=1`,并要求列出仓库顶层目录
3. 观察:agent 报告"没有 packages/ 目录",只列出字母序开头的一小段路径
4. 对照:`curl -s "https://api.github.com/repos/makecindy/cindy/git/trees/main?recursive=1"` 检查响应——约 2.4MB、`"truncated": false`、`packages/` 存在
5. 结论:WebFetch 的输出与真实数据不符,且未给出任何截断提示
### 日志与截图 / Logs & screenshots
无工具侧错误日志——这正是问题的一部分:截断全程静默。
补充证据:
- GitHub API 原始响应(`curl` 直查):2,498,762 字节,`"truncated": false`,tree 条目 7808 条,末条 `tools/shared/verify-sha256.mjs`。
- WebFetch 工具自述:`Fetches a URL, converts the page to markdown, and answers prompt against it using a small fast model`,使用说明含 `Results may be summarized if the content is very large`。
- 上游相关 issue(均未解决):anthropics/claude-code #51783(截断行为未文档化)、#74650(摘要器编造内容)、#77811(摘要器冷启动泄漏上下文)。
Contributor guide
Research direction
Start by reproducing the WebFetch request against the GitHub recursive tree URL and compare its result with curl, including response size and the truncated field. Then inspect the bundled Claude Code CLI 2.1.219 WebFetch behavior and upstream issues #51783, #74650, and #77811. Done means oversized structured responses fail loudly, carry an explicit truncation marker, or preserve raw JSON while reporting its size.
Written by the indexing model from the issue text.
Assessment
- Domain
- ai-infra-agents
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100