Skip to content

feat(doc-skill): document upload-then-move workflow for inserting images into container blocks#966

Closed
fangshuyu-768 wants to merge 4 commits into
mainfrom
feat/media-insert-container-block
Closed

feat(doc-skill): document upload-then-move workflow for inserting images into container blocks#966
fangshuyu-768 wants to merge 4 commits into
mainfrom
feat/media-insert-container-block

Conversation

@fangshuyu-768

@fangshuyu-768 fangshuyu-768 commented May 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

docs +media-insert currently only inserts images at the document top level (end of document or near a top-level block matched by --selection-with-ellipsis). It cannot place images inside container blocks like table cells, callouts, or grid columns. This PR documents the "upload then move" two-step workflow that enables inserting local images into container blocks using block_move_after, which supports cross-parent moves.

Changes

  • skills/lark-doc/references/lark-doc-media-insert.md: Updated title and description to reflect broader capability; added new "插入图片到容器 block" section documenting the upload-then-move workflow with step-by-step instructions, examples (table cell, callout, grid column), and caveats
  • skills/lark-doc/SKILL.md: Updated +media-insert shortcut description to mention the upload-then-move workflow for container blocks
  • skills/lark-doc/references/lark-doc-xml.md: Updated <callout> child block description to include images; updated <img> description to mention container placement

Test Plan

  • Manual verification: created a test document with a table, inserted an image via +media-insert, then used block_move_after to move it into a <td> — confirmed the image appeared inside the table cell
  • Verified that block_move_after supports cross-parent moves (from document root into container block)
  • Skill documentation review: confirmed all three files are consistent and accurate

Related Issues

Summary by CodeRabbit

  • New Features

    • Added drive +sync shortcut for bidirectional synchronization between local directories and Drive folders, with configurable conflict resolution strategies (remote-wins, local-wins, keep-both, ask) and a --quick mode for faster comparisons.
  • Documentation

    • Clarified media insertion behavior for container blocks with step-by-step workflows and examples.
    • Updated drive +push documentation for duplicate handling and conflict semantics.

Review Change Stack

Add regression tests for drive +sync and related status/push helpers so the rebased sync workflow keeps its conflict handling, parent-folder errors, and non-interactive stdin preflight covered.
Move the nested overwrite parent-token change out of feat/drive-sync so this PR stays focused on sync behavior and coverage.
…ges into container blocks

The +media-insert command only inserts images at the document top level.
This PR documents the two-step "upload then move" workflow that enables
inserting local images into container blocks (table cells, callouts,
grid columns) using block_move_after, which supports cross-parent moves.

Closes #503
@coderabbitai

coderabbitai Bot commented May 19, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR introduces a Drive +sync shortcut for bidirectional file synchronization between local directories and Drive folders, supporting multiple conflict resolution strategies, interactive prompts, quick-mode diffing, and structured per-item result reporting. It also strengthens test infrastructure with stub verification, adds status helper error-handling tests, and clarifies documentation for media insertion workflows and push behavior.

Changes

Drive +sync implementation and testing

Layer / File(s) Summary
Drive +sync core implementation
shortcuts/drive/drive_sync.go
DriveSync shortcut validates --local-dir and --folder-token, computes exact or quick diffs by walking/hashing local files and listing remote entries, then executes bidirectional sync: pulls new remote files, pushes new local files, and resolves modified conflicts via --on-conflict strategies (remote-wins, local-wins, keep-both with local rename+rollback on failure, ask with stdin prompts). Includes helpers to convert pull targets to remote file metadata, prompt and parse stdin conflict choices, and rollback renamed files to original paths. Emits structured per-item results and returns partial-failure exit error when any operations fail.
Drive +sync test suite
shortcuts/drive/drive_sync_test.go
Comprehensive test coverage with runtime helpers, fileio mocks (failing saves, post-save hooks, file deletion on close), stdin read error simulation, and 50+ test cases validating all sync strategies, duplicate detection/selection, quick mode by mtime, mid-sync local disappearance, interactive ask prompts (stdin missing/EOF/read errors), per-item error reporting, validation paths, and nested path behavior ensuring correct parent folder tokens and ensure failures surface in structured errors.
Status helper error-handling tests
shortcuts/drive/drive_status_test.go
Added imports and three unit tests: walkLocalForStatus returns output.ExitError (io detail) when local root missing; hashLocalForStatus propagates file-open error mentioning filename; hashRemoteForStatus returns output.ExitError (network detail) mentioning "download" when remote HTTP stub is absent.
Pull test stub verification
shortcuts/drive/drive_pull_test.go
Ensures HTTP stub registrations are verified via reg.Verify(t) before preceding test closes, preventing interference with subsequent tests.
Shortcut registry integration
shortcuts/drive/shortcuts.go, shortcuts/drive/shortcuts_test.go
Registers DriveSync in Shortcuts() list and updates test expectations to include "+sync" command.

Documentation updates for drive and doc features

Layer / File(s) Summary
Drive +sync command documentation
skills/lark-drive/SKILL.md
Adds +sync shortcut entry describing bidirectional sync reusing +status diff buckets, conflict strategies for modified files, quick-mode classification by mtime, remote duplicate handling, and non-destructive (no-delete) behavior.
Media insertion workflow documentation
skills/lark-doc/SKILL.md, skills/lark-doc/references/lark-doc-media-insert.md
Clarifies +media-insert default append-to-end behavior and documents two-step workflow for container block insertion (top-level +media-insert then docs +update with block_move_after). Includes instructions to fetch anchor block ids via docs +fetch --detail with-ids and notes on post-move sizing/caption/alignment.
Media XML capabilities reference
skills/lark-doc/references/lark-doc-xml.md
Updates <callout> child block support to include images; clarifies <img> tag usage (block/inline) and key attributes (width, height, caption, name, href).
Drive push behavior clarifications
skills/lark-drive/references/lark-drive-push.md
Refines --if-exists parameter semantics (skip/smart/overwrite), documents remote rel_path duplicate conflict handling (default fail, selective --on-duplicate-remote newest|oldest for file type), interaction with --delete-remote unselected-duplicate deletion, and clarifies that smart reduces retransmissions without fully eliminating overwrite risk.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • larksuite/cli#692: Introduces walkLocalForStatus, hashLocalForStatus, and hashRemoteForStatus functions that are directly tested by new status helper error-handling tests in this PR.
  • larksuite/cli#696: Adds Drive Pull test suite enhancements that overlap with the pull test stub verification fix in this PR.
  • larksuite/cli#432: Also updates shortcuts/drive/shortcuts.go shortcut registry by adding a different Drive command, creating shared modification patterns at the registration level.

Suggested labels

domain/ccm, size/M

Suggested reviewers

  • wittam-01
  • ZKHelloworld

Poem

🐰 A rabbit hops through folders with pride,
Pulling and pushing with sync as its guide,
When conflicts arise, it asks with care,
Keeping both sides—a solution so fair!
Remote-wins, local-wins, keep-both too,
Two-way harmony, now fully true! 🎪

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change—documenting an upload-then-move workflow for inserting images into container blocks—which is the primary focus of the PR.
Description check ✅ Passed The description follows the template with complete Summary, Changes, Test Plan, and Related Issues sections; all required information is present and well-structured.
Linked Issues check ✅ Passed The PR documents image placement in container blocks via block_move_after, directly addressing #503's requirement to control image placement at specified positions within cloud documents (e.g., inside tables).
Out of Scope Changes check ✅ Passed All changes are scoped to documentation of the upload-then-move workflow for image placement in container blocks; no out-of-scope code changes, features, or unrelated modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/media-insert-container-block
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch feat/media-insert-container-block

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added domain/ccm PR touches the ccm domain size/L Large or sensitive change across domains or core paths labels May 19, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@skills/lark-doc/references/lark-doc-media-insert.md`:
- Around line 109-112: The fenced code block containing the two-step
instructions ("Step 1: +media-insert ..." and "Step 2: +update block_move_after
...") is missing a language tag which triggers markdownlint MD040; update that
fenced block to include a language identifier such as "text" (e.g., change the
opening ``` to ```text) so the block is language-labelled and the linter warning
is resolved while preserving the existing content referencing +media-insert and
+update block_move_after.

In `@skills/lark-doc/references/lark-doc-xml.md`:
- Line 16: Update the example text so it matches the capabilities listed for the
`<callout>` component: change the example/note that currently lists
"text/title/list/checkbox/quote" to include "image" (or reorder to
"text/title/list/checkbox/quote/image") so the example section and the table row
for `<callout>` are consistent; locate the example/note referencing `<callout>`
in the example section and edit that sentence to include `image` among the
supported child block types.

In `@skills/lark-drive/references/lark-drive-push.md`:
- Line 70: Remove the accidental duplicate table rows and repeated paragraphs
that describe the `--if-exists` option (the duplicated `--if-exists` enum row
and its adjacent explanatory paragraphs); keep a single canonical row and one
explanatory paragraph, delete the redundant duplicates elsewhere in the
document, and scan the rest of the file for other repeated instances of the same
`--if-exists` content to remove so only one authoritative description remains.

In `@skills/lark-drive/SKILL.md`:
- Line 247: The table row for the `+sync` command contains unescaped pipe
characters inside inline code (e.g.,
`--on-conflict=remote-wins|local-wins|keep-both|ask` and `--on-duplicate-remote`
options), which breaks Markdown table parsing; edit the SKILL.md table cell for
`+sync` so pipes inside inline code are escaped (e.g.,
`--on-conflict=remote-wins\|local-wins\|keep-both\|ask` and
`--on-duplicate-remote=fail\|newest\|oldest`) or otherwise ensure the entire
option strings are wrapped/escaped to prevent `|` from being treated as column
separators (target the `+sync` table row and the inline code spans for
`--on-conflict` and `--on-duplicate-remote`).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 26d0f0cf-f3f4-4f99-bb12-39366ee99516

📥 Commits

Reviewing files that changed from the base of the PR and between e6bc292 and 4d1a716.

📒 Files selected for processing (11)
  • shortcuts/drive/drive_pull_test.go
  • shortcuts/drive/drive_status_test.go
  • shortcuts/drive/drive_sync.go
  • shortcuts/drive/drive_sync_test.go
  • shortcuts/drive/shortcuts.go
  • shortcuts/drive/shortcuts_test.go
  • skills/lark-doc/SKILL.md
  • skills/lark-doc/references/lark-doc-media-insert.md
  • skills/lark-doc/references/lark-doc-xml.md
  • skills/lark-drive/SKILL.md
  • skills/lark-drive/references/lark-drive-push.md
💤 Files with no reviewable changes (1)
  • shortcuts/drive/drive_pull_test.go

Comment on lines +109 to +112
```
Step 1: +media-insert 上传图片到文档末尾 → 得到 img block_id
Step 2: +update block_move_after 将图片移入目标容器
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language to the fenced block to satisfy markdown lint.

Line 109 uses a fenced code block without language, which triggers MD040 from markdownlint.

Suggested diff
-```
+```text
 Step 1: +media-insert 上传图片到文档末尾 → 得到 img block_id
 Step 2: +update block_move_after 将图片移入目标容器
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>

[warning] 109-109: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @skills/lark-doc/references/lark-doc-media-insert.md around lines 109 - 112,
The fenced code block containing the two-step instructions ("Step 1:
+media-insert ..." and "Step 2: +update block_move_after ...") is missing a
language tag which triggers markdownlint MD040; update that fenced block to
include a language identifier such as "text" (e.g., change the opening ``` to

while preserving the existing content referencing +media-insert and +update
block_move_after.

|标签|说明|关键属性|
|-|-|-|
| `<callout>` | 高亮框,子块仅支持文本、标题、列表、待办、引用 | `emoji`(默认 bulb), `background-color`, `border-color`, `text-color` |
| `<callout>` | 高亮框,子块支持文本、标题、列表、待办、引用、图片 | `emoji`(默认 bulb), `background-color`, `border-color`, `text-color` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Synchronize callout capability text with the example section.

Line 16 now states <callout> supports image child blocks, but the example note at Line 123 still says it only supports text/title/list/checkbox/quote. This contradiction can mislead users about allowed content.

Suggested diff
-  <p>高亮框内容,子块仅支持文本/标题/列表/待办/引用</p>
+  <p>高亮框内容,子块支持文本/标题/列表/待办/引用/图片</p>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/lark-doc/references/lark-doc-xml.md` at line 16, Update the example
text so it matches the capabilities listed for the `<callout>` component: change
the example/note that currently lists "text/title/list/checkbox/quote" to
include "image" (or reorder to "text/title/list/checkbox/quote/image") so the
example section and the table row for `<callout>` are consistent; locate the
example/note referencing `<callout>` in the example section and edit that
sentence to include `image` among the supported child block types.

| `--local-dir` | 是 | path | 本地根目录(**必须是 cwd 的相对路径**;绝对路径或逃出 cwd 的相对路径会被 CLI 直接拒绝) |
| `--folder-token` | 是 | string | 目标 Drive 文件夹 token |
| `--if-exists` | 否 | enum | 远端文件已存在时的策略:`skip`(**默认**,安全)/ `smart`(用于重复增量同步;当远端 `modified_time` 已匹配或更新时跳过上传,否则继续走覆盖路径)/ `overwrite`(依赖灰度后端协议,详见"覆盖语义") |
| `--if-exists` | 否 | enum | 远端文件已存在时的策略:`skip`(**默认**,安全)/ `smart`(用于重复增量同步;当远端 `modified_time` 已匹配或更新时跳过上传,否则继续走覆盖路径)/ `overwrite`(依赖灰度后端协议,详见"覆盖语义") |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove accidental duplicate lines introduced in this edit.

These lines repeat content already present immediately next to them (same --if-exists row and same paragraphs), which adds noise and can mislead readers.

Suggested patch
-| `--if-exists` | 否 | enum | 远端文件已存在时的策略:`skip`(**默认**,安全)/ `smart`(用于重复增量同步;当远端 `modified_time` 已匹配或更新时跳过上传,否则继续走覆盖路径)/ `overwrite`(依赖灰度后端协议,详见"覆盖语义") |
@@
-- 已存在的远端文件按 `--if-exists` 决定 `overwrite` / `smart` / `skip`。其中 `smart` 是**增量优化模式**:只要远端 `modified_time` 在同等时间精度下已经等于或晚于本地 mtime,就跳过上传;时间戳缺失/非法时会退回安全路径继续上传,不会盲跳。**但如果远端更旧,`smart` 会继续走和 `overwrite` 相同的覆盖路径,因此也继承同样的 rollout / version 返回 caveat。** 想做 `keep-both` 这类的仍需自行改名再 push。
@@
-`--if-exists=smart` 是给“重复跑同步”的场景增加的增量优化:当远端 `modified_time` 在同等时间精度下已经等于或晚于本地 mtime 时,命令会把该文件计为 `skipped`;时间戳缺失、非法或更旧时,则继续走正常上传/覆盖路径。**也就是说,只要 smart 判定“远端不够新”,它就会进入与 `--if-exists=overwrite` 相同的覆盖实现,因此在未 rollout version 字段的 tenant 上仍可能非零失败。**
@@
-- 默认 `skip` 下,已存在的远端文件一律不碰;`overwrite` 下,重复跑会重传所有命中的同名文件;`smart` 下会按 `modified_time` 跳过已对齐的远端文件,但对“远端更旧”的文件仍会进入覆盖路径,因此它减少的是**不必要的重传**,不是把覆盖风险完全拿掉。

Also applies to: 80-80, 87-87, 134-134

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/lark-drive/references/lark-drive-push.md` at line 70, Remove the
accidental duplicate table rows and repeated paragraphs that describe the
`--if-exists` option (the duplicated `--if-exists` enum row and its adjacent
explanatory paragraphs); keep a single canonical row and one explanatory
paragraph, delete the redundant duplicates elsewhere in the document, and scan
the rest of the file for other repeated instances of the same `--if-exists`
content to remove so only one authoritative description remains.

| [`+download`](references/lark-drive-download.md) | Download a file from Drive to local |
| [`+status`](references/lark-drive-status.md) | Compare a local directory with a Drive folder by exact SHA-256 hash by default, or use `--quick` for a best-effort modified-time diff that skips remote downloads; reports `new_local` / `new_remote` / `modified` / `unchanged` plus `detection=exact` or `detection=quick`. Duplicate remote `rel_path` conflicts fail fast with `error.type=duplicate_remote_path` and list every conflicting entry; do not proceed as if one was chosen. `--local-dir` 必须是 cwd 内的相对路径,越界路径 CLI 会直接拒绝;目标在 cwd 外时引导用户切换 agent 工作目录,不要私自 `cd` 绕过。 |
| [`+pull`](references/lark-drive-pull.md) | File-level Drive → local mirror. Duplicate remote `rel_path` conflicts fail by default; for duplicate files, `rename` downloads all copies with stable hashed suffixes, while `newest` / `oldest` pick one. `--if-exists` supports `overwrite` / `smart` / `skip` (`smart` is a best-effort modified-time incremental mode for repeat syncs). `--delete-local` requires `--yes`, only removes regular files, and is skipped after item failures. `--local-dir` must stay inside cwd. |
| `+sync` | Two-way local ↔ Drive sync. Reuses `+status` diff buckets, pulls `new_remote`, pushes `new_local`, and resolves `modified` via `--on-conflict=remote-wins|local-wins|keep-both|ask`. `--quick` enables best-effort modified-time diffing (timestamp mismatches can still trigger real pull/push actions), `--on-duplicate-remote` supports `fail|newest|oldest`, and the command is intentionally non-destructive (no delete on either side). |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix table cell parsing by escaping pipes in inline code.

Line 247 puts | inside inline code in a table cell, which breaks column parsing and truncates this row in Markdown renderers/linting.

Suggested patch
-| `+sync` | Two-way local ↔ Drive sync. Reuses `+status` diff buckets, pulls `new_remote`, pushes `new_local`, and resolves `modified` via `--on-conflict=remote-wins|local-wins|keep-both|ask`. `--quick` enables best-effort modified-time diffing (timestamp mismatches can still trigger real pull/push actions), `--on-duplicate-remote` supports `fail|newest|oldest`, and the command is intentionally non-destructive (no delete on either side). |
+| `+sync` | Two-way local ↔ Drive sync. Reuses `+status` diff buckets, pulls `new_remote`, pushes `new_local`, and resolves `modified` via `--on-conflict=remote-wins\|local-wins\|keep-both\|ask`. `--quick` enables best-effort modified-time diffing (timestamp mismatches can still trigger real pull/push actions), `--on-duplicate-remote` supports `fail\|newest\|oldest`, and the command is intentionally non-destructive (no delete on either side). |
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 247-247: Spaces inside code span elements

(MD038, no-space-in-code)


[warning] 247-247: Table column count
Expected: 2; Actual: 7; Too many cells, extra data will be missing

(MD056, table-column-count)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/lark-drive/SKILL.md` at line 247, The table row for the `+sync`
command contains unescaped pipe characters inside inline code (e.g.,
`--on-conflict=remote-wins|local-wins|keep-both|ask` and `--on-duplicate-remote`
options), which breaks Markdown table parsing; edit the SKILL.md table cell for
`+sync` so pipes inside inline code are escaped (e.g.,
`--on-conflict=remote-wins\|local-wins\|keep-both\|ask` and
`--on-duplicate-remote=fail\|newest\|oldest`) or otherwise ensure the entire
option strings are wrapped/escaped to prevent `|` from being treated as column
separators (target the `+sync` table row and the inline code spans for
`--on-conflict` and `--on-duplicate-remote`).

@fangshuyu-768

Copy link
Copy Markdown
Collaborator Author

Superseded by #970 which uses a clean branch from main.

@liangshuo-1
liangshuo-1 deleted the feat/media-insert-container-block branch June 3, 2026 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain/ccm PR touches the ccm domain size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cli 处理云文档图片和画板的能力需要增强

1 participant