Skip to content

feat: feishu_doc 智能截断 + read_blocks 按需读取 - #126

Merged
lishuceo merged 1 commit into
mainfrom
feat/doc-smart-read
Mar 10, 2026
Merged

feat: feishu_doc 智能截断 + read_blocks 按需读取#126
lishuceo merged 1 commit into
mainfrom
feat/doc-smart-read

Conversation

@lishuceo

Copy link
Copy Markdown
Owner

Summary

  • read 自动截断: 文档超过 2000 行时只返回前 2000 行 + 文档目录 + 提示用 read_blocks 获取详情(阈值与 Claude Code 的 Read 工具一致)
  • 新增 read_blocks: 按 block_id 读取指定 block 及其子块的文本内容,支持逗号分隔多个 ID
  • list_blocks 优化: 从原始 JSON dump 改为精简 tab 分隔目录(block_id / type / 80字预览),大幅降低 token 消耗
  • 工具描述引导: 注入高效读取工作流指引,引导 agent 走 read → list_blocks → read_blocks 路径

核心设计思路

不依赖 agent 主动省 token(自定义 MCP 工具没有后训练肌肉记忆),而是让工具本身强制截断,让高效路径成为唯一路径。

Test plan

  • read: 小文档(< 2000 行)直接返回全文
  • read: 大文档自动截断,包含行数/字符数统计和目录
  • read: 截断输出中包含 heading 结构摘要
  • read: 恰好 2000 行不截断
  • read_blocks: 单个 block 读取
  • read_blocks: 逗号分隔多个 block
  • read_blocks: 递归包含子 block
  • read_blocks: 无效 block 报 not found
  • list_blocks: tab 分隔格式,跳过 page block
  • list_blocks: 长文本截断到 80 字 + 省略号
  • 全量回归: 957/958 pass(1 个 pre-existing 记忆检索 flaky test)

🤖 Generated with Claude Code

- read action: 超过 2000 行自动截断,附带文档目录和 read_blocks 提示
  (阈值与 Claude Code 的 Read 工具一致)
- 新增 read_blocks action: 按 block_id 读取指定 block 及其子块内容,
  支持逗号分隔多个 block_id
- list_blocks 优化: 返回精简 tab 分隔目录 (block_id/type/preview),
  替代原始 JSON dump,大幅降低 token 消耗
- 工具描述注入高效读取工作流指引,引导 agent 按需读取

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@claude

claude Bot commented Mar 10, 2026

Copy link
Copy Markdown

Claude finished @lishuceo's task in 1m 22s —— View job


PR Review: feishu_doc 智能截断 + read_blocks 按需读取

  • Check for previous review comments — none found
  • Read changed files and understand context
  • Review src/feishu/tools/doc.ts changes
  • Review src/feishu/tools/__tests__/doc.test.ts changes
  • Post review summary

✅ Approved — Clean, well-designed PR

This is a solid PR. The core design principle — forcing truncation at the tool level rather than relying on the agent to be token-efficient — is pragmatic and effective. The code is clean, follows existing patterns, and has thorough test coverage.

What's good

  • Smart truncation with escape hatch: The read → list_blocks → read_blocks flow is well-designed. Truncating at 2000 lines (matching Claude Code's Read tool) keeps the mental model consistent.
  • extractBlockText is robust: Handles text, headings, bullets, ordered lists, quotes, todos, callouts, and code blocks. Falls through cleanly for non-text block types.
  • collectDescendants recursive tree walk: Clean recursive descent for read_blocks — includes children transitively, which is exactly what you want when reading a section.
  • list_blocks optimization: Moving from raw JSON dump to tab-separated block_id / type / 80-char preview is a significant token reduction.
  • Test coverage is excellent: 20+ test cases covering truncation boundary (exactly 2000 lines), heading extraction, multi-block reads, recursive children, not-found handling, and error paths.
  • Best-effort structure summary: The try/catch around heading extraction in the truncated read path is the right call — don't let a secondary API failure block the primary read.

Minor observations (not blocking)

  1. page_size: 500 without pagination (doc.ts:137,274,309): Documents with >500 blocks will have incomplete block lists in list_blocks, read_blocks, and the truncation heading summary. This is a pre-existing pattern used throughout the file (write, delete_blocks, etc.), so not introduced by this PR. Worth tracking as a follow-up if large docs become common.

  2. collectDescendants has no cycle protection (doc.ts:320-331): If Feishu ever returns corrupted block data with circular parent-child references, this would stack overflow. Extremely unlikely in practice since Feishu's block tree is a DAG, but a Set<string> visited guard would be trivial to add. Confidence: low enough to not block.

  3. extractBlockText ignores non-text-run elements (doc.ts:32-58): Elements like mention_user, equation, mention_doc are skipped — their text content won't appear in previews or read_blocks output. This is acceptable for a preview/extraction tool, but worth noting for completeness.

No bugs, security issues, or architectural concerns found. The test plan in the PR description is thorough and all cases are covered in the test file.


@lishuceo
lishuceo merged commit 3009c3c into main Mar 10, 2026
2 checks passed
@lishuceo
lishuceo deleted the feat/doc-smart-read branch March 10, 2026 04:41
lishuceo added a commit that referenced this pull request Apr 8, 2026
feat: feishu_doc 智能截断 + read_blocks 按需读取
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