Lark/飞书 CLI 幻灯片历史版本管理与回滚实战:+history-list / +history-revert 全流程解析
2026/9/22 19:27:46 网站建设 项目流程
  • CLI
  • AI 技能

【免费下载链接】cli

The official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200+ commands and 20+ AI Agent Skills.

项目地址:https://gitcode.com/gh_mirrors/cli414/cli
点击查看免费下载

本指南围绕官方 Lark/飞书 CLI(lark-cli)的 Slides 历史版本能力展开,讲解如何使用slides +history-list列出 Slides XML 演示文稿的历史版本、通过+history-reverthistory_version_id发起回滚,以及用+history-revert-status轮询异步任务状态。读完本文,你将掌握一套可安全落地的版本回滚流程:从候选版本筛选、跨页补拉、候选确认,到异步轮询边界与回滚后的内容验证,并能直接照着命令与参数在真实演示文稿上执行。

背景:为什么回滚需要一套专门流程

Slides 演示文稿在飞书/Lark 侧以 XML 形式存储,每一次编辑都会产生新的历史版本。与普通文档的"直接恢复"不同,CLI 的回滚是异步任务+history-revert提交后立即返回task_id,真正的回滚在服务端后台执行。因此整个流程天然分为三个阶段:

  1. 定位版本:通过分页接口+history-list找到目标版本,拿到回滚所需的history_version_id
  2. 发起回滚+history-revert提交异步任务,拿到task_id与建议轮询间隔poll_after_ms
  3. 轮询确认+history-revert-status持续查询任务状态,直到done/partial_failed/failed,再做回滚后验证。

其中有一个关键概念需要先澄清:回滚接口只接受history_version_id,不要直接把revision_id传给+history-revert。这一约束在 skills/lark-slides/SKILL.md 中被标记为 CRITICAL 级别:history_version_id对应服务端minor_history.version,是回滚接口需要的 ID;而revision_id是文档修订号,同一revision_id可能对应多条历史记录,不能作为回滚依据。

三个命令与底层实现总览

三个命令均在 shortcuts/slides/slides_history.go 中注册,统一走/open-apis/slides_ai/v1/xml_presentations/{xml_presentation_id}/...这一组 Slides AI OpenAPI 端点:

| 命令 | 底层端点 | HTTP 方法 | 风险等级 | 必填参数 | |-|-|-|-|-| |+history-list|.../histories| GET | read |--presentation| |+history-revert|.../history/revert| POST | write |--presentation--history-version-id| |+history-revert-status|.../history/revert_status| GET | read |--presentation--task-id|

权限声明(源码中Scopes/ConditionalScopes字段)也值得注意:

  • +history-list+history-revert-status需要slides:presentation:read
  • +history-revert属于写操作,需要slides:presentation:updateslides:presentation:write_only
  • 三个命令都声明了条件权限wiki:node:read——只有当--presentation传入的是 wiki URL 时才需要额外解析;
  • 三者均支持userbot两种身份(AuthTypes)。

--presentation的取值支持三种形态(requiredPresentationRefFlag定义):xml_presentation_id、Slides URL,或可解析为 Slides 的 wiki URL。当传入 wiki URL 时,执行期会先调用 wiki 节点解析接口(/open-apis/wiki/v2/spaces/node_by_token)把 wiki 节点解析为真实的 slides token,再拼接上述端点——这一点在单元测试 TestSlidesHistoryExecuteResolvesWikiPresentation 中通过 mock 验证:先返回obj_type: slidesobj_token,随后才发起histories请求。

安全流程:七步完成一次可信回滚

为了不让"回滚"这个高风险操作出现误判、误回滚或重复提交,CLI 定义了一条标准安全流程:

  1. 先用分页接口+history-list找到目标版本的history_version_id+history-list是分页接口,返回has_morepage_token,需要继续翻页时再传--page-token
  2. 如果用户指定的是revision_id:不要假设它唯一,也不要把revision_id直接传给+history-revert。先拉一页并在entries[]中筛选revision_id相同的候选;如果未匹配到且has_more=true,继续用page_token翻页;如果已匹配到候选,最多额外再拉一页补齐可能跨页的相邻候选。最终优先根据用户目标时间与edit_time的接近程度选择最合适的一条,取同一条的history_version_id;如果没有目标时间、或多个候选无法可靠区分,则向用户展示候选版本并确认后回滚。
  3. 如果用户指定的是某一时刻但没有指定revision_id:按entries[].edit_time匹配,优先选择不晚于目标时刻的最近一条历史记录;无法明确匹配时先向用户确认候选版本。
  4. 使用+history-revert发起回滚:接口立即返回task_id,回滚任务在服务端异步执行。
  5. 如果返回status: running:保存task_id,按照返回的poll_after_ms等待后调用+history-revert-status任务创建成功后,不得因为状态查询失败而重新发起回滚。
  6. 停止条件:状态变为donepartial_failedfailed后停止轮询;达到整体轮询上限时也停止轮询,并向用户返回task_id和当前状态。
  7. 回滚完成后验证:用slides +xml-get读取演示文稿内容确认。

这条流程把"定位→确认→提交→轮询→验证"串成闭环,每一步都避免了对服务端状态的猜测,是 Agent 与人类用户共用同一套命令时的可靠基线。

按 revision_id 或时间点回滚的智能匹配策略

当用户表达"回滚到 revision_id=42""恢复到昨天下午 3 点的版本"这类需求时,Agent 应当执行如下细化流程:

  1. 执行slides +history-list --presentation <presentation>获取第一页历史记录;只有has_more=true且还需要更多候选时才继续传--page-token翻页。
  2. 用户给出revision_id
    • 先筛选当前页中entries[].revision_id == 用户给出的 revision_id
    • 未命中且has_more=true,继续拉下一页;
    • 已命中候选,最多额外再拉一页,补齐同一个revision_id可能跨页出现的相邻history_version_id
    • 若用户同时给出目标时间,在候选里选择edit_time与目标时间最接近的一条;
    • 若未给目标时间但候选只有一条,可直接使用;
    • 若多个候选无法可靠区分,不要自行取第一条,向用户展示候选并确认。
  3. 用户只给出时间时:用entries[].edit_time匹配,选择目标时刻之前最近的一条;如果用户表达的是"最接近某时刻",则选择绝对时间差最小的一条。
  4. 从最终匹配条目读取history_version_id(对应服务端minor_history.version)。
  5. 执行slides +history-revert --presentation <presentation> --history-version-id <history_version_id>

候选确认时使用类似格式,让用户能一眼区分:

同一个 revision_id 命中多个历史版本,请确认要回滚哪一条: - history_version_id=11 revision_id=42 edit_time=2026-06-22T12:24:45Z name=... - history_version_id=12 revision_id=42 edit_time=2026-06-22T12:25:14Z name=...

这里有一个时间格式约定必须遵守:entries[].edit_timeUTC RFC3339 时间字符串(例如2026-06-22T12:24:45Z)。按时间匹配时先将其解析为时间值,再比较先后关系或时间差,不要做字符串比较。

命令与参数速查

# 列出历史版本 lark-cli slides +history-list --presentation "<slides_url_or_token>" --page-size 20 # 翻页 lark-cli slides +history-list --presentation "<slides_url_or_token>" --page-size 20 --page-token "<page_token>" # 发起回滚任务,立即返回 task_id lark-cli slides +history-revert --presentation "<slides_url_or_token>" --history-version-id 42 # 查询回滚任务状态 lark-cli slides +history-revert-status --presentation "<slides_url_or_token>" --task-id "<task_id>"

完整参数说明如下(与源码 Flag 定义一致):

| 命令 | 参数 | 必填 | 说明 | |-|-|-|-| |+history-list|--presentation| 是 |xml_presentation_id、Slides URL,或可解析为 Slides 的 wiki URL | |+history-list|--page-size| 否 | 返回条数,范围1-20,默认20| |+history-list|--page-token| 否 | 上一页返回的page_token| |+history-revert|--presentation| 是 | 同一个演示文稿 | |+history-revert|--history-version-id| 是 |+history-list返回的history_version_id,必须大于 0 | |+history-revert-status|--presentation| 是 | 同一个演示文稿 | |+history-revert-status|--task-id| 是 |+history-revert返回的task_id|

参数校验在源码层面对齐了文档约束(见 shortcuts/slides/slides_history.go 中的validateSlidesHistoryPageSizevalidateSlidesHistoryVersionID):

  • --page-size必须落在1-20,越界报ValidationError
  • --history-version-id必须是正整数字符串(strconv.ParseInt失败或<= 0均拒绝),错误信息明确提示"必须是slides +history-list返回的正整数";
  • --task-id不允许为空。

对应地,TestSlidesHistoryValidation 覆盖了"page-size 传 0""history-version-id 传 abc / 0""task-id 传空串"等边界用例,断言错误均带正确的参数名(--page-size--history-version-id--task-id)。

异步轮询策略:边界条件与失败语义

由于回滚是异步任务,轮询策略决定了流程的健壮性。标准策略如下:

  1. +history-revert返回task_id后,认为回滚任务已经成功创建
  2. 如果status不是running,不再调用状态接口(任务可能已同步完成)。
  3. 如果statusrunning,等待响应中的poll_after_ms后调用+history-revert-statuspoll_after_ms缺失、为0或非法时,默认等待 10 秒
  4. 状态查询返回running时继续轮询;返回donepartial_failedfailed时停止。
  5. 除非用户另有要求,默认最多轮询5 分钟。达到上限后停止轮询,向用户说明任务仍在运行并返回task_id不得将其描述为回滚失败
  6. 状态查询出现临时错误时,按相同间隔最多连续重试 3 次;只重试+history-revert-status不得重新调用+history-revert(避免重复回滚)。
  7. done后读取当前演示文稿内容进行验证。
  8. partial_failedfailed时展示failed_block_tokens;除非用户明确确认,不得自动再次发起回滚

这条策略的关键点可以浓缩为三条底线:任务创建后不重复提交轮询超时不等于失败失败后的再次回滚必须经用户确认

返回值要点

+history-list返回(分页结构):

{ "entries": [ { "revision_id": 42, "history_version_id": "11", "edit_time": "2026-06-22T12:24:45Z", "type": 1, "name": "版本名", "description": "版本说明", "editor_ids": ["ou_xxx"] } ], "has_more": true, "page_token": "page_token" }

+history-revert返回(异步任务创建确认):

{ "task_id": "task_xxx", "status": "running", "history_version_id": "11", "poll_after_ms": 10000 }

+history-revert-status返回:

{ "status": "partial_failed", "history_version_id": "11", "failed_block_tokens": ["blk_xxx"] }

status可能的取值为runningdonepartial_failedfailed。当状态是partial_failedfailed时,优先检查failed_block_tokens——它列出了回滚失败的块(block)标识,是向用户说明失败范围的关键依据。

回滚后验证

回滚成功后必须读取一次当前内容确认,这也是安全流程的最后一步:

lark-cli slides +xml-get --presentation "<slides_url_or_token>" --output ./presentation.xml

+xml-get的实现见 shortcuts/slides/slides_xml_get.go:--output指定本地 XML 输出路径(现有文件会被覆盖),也可省略--output让 XML 以 JSON envelope 形式返回,或用--raw直接打印原始 XML 到 stdout;--revision-id默认-1表示最新版本。回滚验证时读取最新内容,确认目标版本内容已生效。

从源码与测试看实现保障

参数与请求构造

三个命令的请求构造非常规整:

  • +history-list:GET,Query 参数page_sizepage_tokenslidesHistoryListParams中仅在非空时才带上page_token);
  • +history-revert:POST,请求体为{"history_version_id": "..."}slidesHistoryRevertBody),且不包含wait_timeout_ms这类等待参数——TestSlidesHistoryDryRun 与 TestSlidesHistoryDryRunE2E 都专门断言了 revert 请求体不得出现wait_timeout_ms,说明回滚被刻意设计为纯异步提交,不依赖同步等待;
  • +history-revert-status:GET,Query 参数task_id

Dry-run 与两步编排

+history-list等命令支持--dry-run预演。对普通 token 只需一步:GET /open-apis/slides_ai/v1/xml_presentations/{id}/histories;对 wiki URL 则是两步编排:先GET /open-apis/wiki/v2/spaces/node_by_token解析 wiki 节点,再发起历史版本请求(dry-run 中占位为<resolved_slides_token>)。TestSlidesHistoryDryRunWithWikiPresentation 断言两步调用依次出现,TestSlidesHistoryDryRunE2E 在真实 CLI 进程上验证了三个命令 dry-run 的端点、方法与参数。

E2E 工作流测试

最完整的证据来自端到端工作流测试 TestSlidesHistoryWorkflow(通过设置环境变量LARK_SLIDES_HISTORY_E2E=1并携带 user token 开启)。它完整走了一遍真实回滚链路:

  1. slides +create创建演示文稿,记录原始内容 marker 与revision_id
  2. slides +update-slide写入更新 marker,确认revision_id增大;
  3. 轮询+history-list,在entries[]中按revision_id匹配出原始版本的history_version_id
  4. +history-revert发起回滚,若status == "running"则用task_id轮询+history-revert-status直到非running
  5. 断言最终状态为done,再读取整篇 XML 确认内容恢复为原始 marker。

这个测试同时验证了文档中反复强调的两点:按revision_id在历史记录中定位history_version_id的可行性,以及回滚后必须读回内容做验证的必要性。

常见场景速记

| 用户诉求 | 推荐动作 | |-|-| | "回滚到 revision_id=42" | 翻页筛选revision_id == 42的候选,必要时补拉一页,确认后取history_version_id回滚 | | "恢复到昨天下午 3 点" | 按edit_time匹配目标时刻之前最近的记录 | | "最接近某时刻的版本" | 按edit_time与目标时刻的绝对时间差取最小 | | 回滚后想看结果 |+xml-get读取当前 XML 确认内容 | | 任务一直 running | 按poll_after_ms(默认 10s)轮询,整体上限默认 5 分钟,超时返回task_id而非报失败 |

结合 skills/lark-slides/references/cli/lark-slides-history.md 原文档、skills/lark-slides/SKILL.md 的技能约束以及 shortcuts/slides/slides_history.go 的实现,这套"定位版本 → 确认候选 → 异步回滚 → 轮询状态 → 读回验证"的闭环已经足够支撑人类用户与 AI Agent 在飞书/Lark 幻灯片上安全、可审计地完成任意历史版本回滚。

  • CLI
  • AI 技能

【免费下载链接】cli

The official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200+ commands and 20+ AI Agent Skills.

项目地址:https://gitcode.com/gh_mirrors/cli414/cli
点击查看免费下载
上一篇:RimSort终极指南:三分钟掌握《环世界》模组管理,告别游戏崩溃烦恼
下一篇:5分钟搞定虚拟显示器:ParsecVDD终极指南,解锁4K游戏串流新境界

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询