Skip to content

feat(parse): add-feishu-mindnote - #4319

Open
Syt3s wants to merge 1 commit into
volcengine:mainfrom
Syt3s:feat/add-feishu-mindnote
Open

feat(parse): add-feishu-mindnote#4319
Syt3s wants to merge 1 commit into
volcengine:mainfrom
Syt3s:feat/add-feishu-mindnote

Conversation

@Syt3s

@Syt3s Syt3s commented Aug 25, 2026

Copy link
Copy Markdown

PR 描述

变更概述

  • 支持飞书/Lark /mindnote//mindnotes/ 直接链接;
  • 支持 Wiki 中 obj_type=mindnote 的节点,以及 Drive folder 中枚举到的 Mindnote;
  • 通过官方 Mindnote v1 Nodes API 和用户 access token 读取节点;
  • 将扁平节点数组稳定重建为嵌套 Markdown,保留富文本、备注、完成状态、高亮、链接、提及和图片;
  • 使用应用身份调用官方 Drive media API,将 Mindnote 图片物化为本地资源;
  • 补充 preflight 校验、飞书错误分类、标识符脱敏、自动化测试及中英文 API 文档。

Closes #4187

问题背景

飞书 Wiki 可以包含 Mindnote 思维笔记节点,但原有 FeishuAccessor 会将
obj_type=mindnote 判定为不支持的文档类型,导致该 Wiki 资源无法进入 OpenViking 的正常导入、
读取和检索链路。

方案设计

Mindnote 正文通过以下官方接口读取:

GET /open-apis/mindnote/v1/mindnotes/{mindnote_id}/nodes

实现复用现有 lark-oapi raw request 能力,并显式使用 AccessTokenType.USER。如果没有传入
args.feishu_access_token,请求会在 preflight 阶段失败;Mindnote Nodes 请求不会回退到 app 或
tenant token。

节点处理采用以下策略:

  • 将扁平节点数组规范化后重建父子关系;
  • 使用迭代遍历,避免深层思维导图触发 Python recursion limit;
  • 保持 API 返回的同级节点顺序;
  • 将缺失父节点、重复 ID、自引用和环中的可恢复节点输出到 Unattached nodes,避免正文静默丢失;
  • 使用独立的 Mindnote 富文本 renderer,不复用依赖 Docx SDK 对象的 renderer;
  • 对未知富文本元素保留可见文本,并记录脱敏 warning。

Mindnote 图片先渲染为飞书图片引用,再进入现有图片处理链路。Drive media API 按飞书官方契约使用
AccessTokenType.TENANT 和应用权限 docs:document.media:download。单张图片下载失败保持
best-effort 语义,不影响节点正文入库。

图片下载成功时,Accessor 返回包含 document.md 和图片文件的临时目录,使 durable staging 和
DirectoryParser 能同时保留 Markdown 与真实图片资源。

自动化验证

执行了本次改动直接相关的测试:

pytest tests/parse/test_feishu_accessor.py \
       tests/parse/test_feishu_errors.py \
       tests/parse/test_markdown_local_image_refs.py \
       tests/parse/test_directory_parser_routing.py -q --no-cov

95 passed

代码质量检查:

ruff format --check <本次改动的 Python 文件>
ruff check <本次改动的 Python 文件>
git diff --check

全部通过

额外执行了包含目录扫描和目录导入的 156 项回归测试,其中 154 项通过。其余 2 项失败位于本次未
修改的代码,分别为 Windows 换行字节断言和 .gitignore 路径分隔符断言,本 PR 未修改或规避
这两个无关的平台差异。

真实端到端验收

使用真实 OpenViking server、公开资源 API 和真实飞书测试文档完成了以下验收:

  • 直接 Mindnote URL 导入成功;
  • Wiki 中的 Mindnote 导入成功;
  • 嵌套 Markdown 结构和节点顺序正确;
  • 链接和高亮节点渲染成功;
  • 图片真实物化成功,资源树中的图片字节均通过 PNG 魔数校验;
  • read、限定资源范围的 findsearch 均成功;

配置说明

  • Mindnote 节点读取需要通过 args.feishu_access_token 传入具备
    mindnote:node:read 权限的用户 token;
  • 图片物化还需要配置飞书 FEISHU_APP_IDFEISHU_APP_SECRET,并为应用身份开通
    docs:document.media:download
  • 本次变更没有新增运行时依赖,也没有修改公开 add_resource 请求结构。

@Syt3s Syt3s changed the title feat(feishu): 支持 Mindnote 思维笔记资源导入 feat(feishu): add-feishu-mindnote Aug 25, 2026
@Syt3s Syt3s changed the title feat(feishu): add-feishu-mindnote feat(parse): add-feishu-mindnote Aug 26, 2026
@Syt3s

Syt3s commented Aug 26, 2026

Copy link
Copy Markdown
Author

Hi @zihengli-bytedance, could you please take a look at this PR when you have a chance? Any feedback would be greatly appreciated. Thank you!

@zihengli-bytedance zihengli-bytedance left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

发现 1 项 blocking 兼容性回归:Mindnote 支持不应使现有用户-token 飞书导入静默丢失图片。相关测试通过,但测试变更删除了已有的用户-token 媒体下载契约。

# Feishu's Drive media endpoint is an application-identity API.
# Keep it on the tenant client even when the containing document
# was fetched with a user token (Mindnote itself is user-token-only).
client = self._get_client()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Bug][Blocking] 用户 token 导入会静默丢失已有飞书文档的图片

这里将媒体下载固定为 tenant client,并且 access() 已不再把 feishu_access_token 传给 _resolve_image_refs。因此,用户只通过 args.feishu_access_token 导入私有 docx/sheet/bitable 时,正文仍能用用户身份读取,但没有应用凭证时 _get_client() 会失败;应用无文档权限时下载会返回 403。异常又被捕获为 None,最终正文成功、图片却只剩 feishu://image/... 引用。

这正是提交 07aa9dc775 曾修复的回归:基线实现会在提供用户 token 时声明 AccessTokenType.USER 并传入 request option;PR 还删除了对应测试。项目当前的 lark-oapi 1.5.3 生成请求也同时允许 USER/TENANT。若 tenant-only 是 Mindnote 的特有限制,请说明为何要改变所有既有文档类型的认证契约;否则请保留已有用户-token 媒体下载路径。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

辛苦确认下

@Syt3s
Syt3s force-pushed the feat/add-feishu-mindnote branch from 0cbdb32 to 49e73f4 Compare August 31, 2026 15:12
@Syt3s

Syt3s commented Aug 31, 2026

Copy link
Copy Markdown
Author

感谢指出,确认这是一个兼容性回归。原实现将媒体下载固定为 tenant client,导致使用用户 token 导入私有 docx/sheet/bitable 时可能静默丢图。

现已恢复原有认证契约:传入用户 token 时,正文和媒体下载都使用 AccessTokenType.USER 并透传 token;未传用户 token 时仍使用 TENANT。Mindnote Nodes API 保持 USER-only

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

[Feature]: 飞书文档格式希望支持mindnote 也就是思维笔记

2 participants