Skip to content

feat(drive): add +copy shortcut - #2129

Open
zzzchao123 wants to merge 1 commit into
mainfrom
feat/drive-copy-shortcut
Open

feat(drive): add +copy shortcut#2129
zzzchao123 wants to merge 1 commit into
mainfrom
feat/drive-copy-shortcut

Conversation

@zzzchao123

@zzzchao123 zzzchao123 commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

Wrap the Drive file-copy endpoint as drive +copy. Accept a document URL (recommended) or bare token + --type for the source, a folder token or folder URL for the target, and repeatable --extra key=value pairs forwarded verbatim for special copy semantics (e.g. target_type=docx to convert a legacy doc during copy). Reject wiki URLs/tokens with a typed validation error whose hint carries a ready-to-adapt wiki +node-copy command, because a Drive copy of a wiki-backed document would land in Drive space instead of the wiki tree.

Declare docs:document:copy (the narrowest scope in the endpoint's any-of set). Cover the shortcut with unit tests, dry-run e2e and a self-contained live workflow (upload -> copy -> download-verify -> cleanup), and register it in tests/cli_e2e/drive/coverage.md. Route copy intents in the lark-drive skill to the shortcut instead of the raw files copy service command.

Test Plan

  • Unit tests pass
  • Manual local verification confirms the lark-cli <domain> <command> flow works as expected

Related Issues

  • None

Summary by CodeRabbit

  • New Features

    • Added the drive +copy command for copying Drive documents and folders.
    • Supports URLs or tokens, destination folders, custom names, extra parameters, and dry-run previews.
    • Resolves personal-space destinations and provides Wiki-specific guidance when copying isn’t supported.
  • Documentation

    • Added detailed copy workflow documentation, examples, permissions, and usage guidance.
  • Tests

    • Added comprehensive unit and end-to-end coverage for parsing, validation, previews, API execution, and content verification.

@zzzchao123 zzzchao123 self-assigned this Jul 31, 2026
@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 Jul 31, 2026
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds the drive +copy shortcut. It resolves URLs and tokens, validates parameters, supports dry runs and extras, redirects Wiki inputs, executes Drive copy requests, updates documentation, and adds unit and end-to-end tests.

Changes

Drive copy workflow

Layer / File(s) Summary
Input resolution and validation
shortcuts/drive/drive_copy.go, shortcuts/drive/drive_copy_test.go, shortcuts/drive/shortcuts.go, shortcuts/drive/shortcuts_test.go
The shortcut parses URLs and tokens, validates names, folders, types, and extras, normalizes base to bitable, and redirects Wiki inputs to wiki +node-copy. The shortcut registry and command-list test include +copy.
Copy request and result handling
shortcuts/drive/drive_copy.go, shortcuts/drive/drive_copy_test.go
The command builds Drive copy requests, supports dry-run previews, resolves my_space, executes the API call, preserves typed API errors, synthesizes missing resource URLs, and formats copied-file metadata.
Documentation and end-to-end coverage
skills/lark-drive/SKILL.md, skills/lark-drive/references/lark-drive-copy.md, tests/cli_e2e/drive/*
The Drive documentation describes drive +copy. Tests cover URL and token inputs, extras, Wiki rejection, my_space, live copying, and content equality. Coverage metrics and command records are updated.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant DriveCopy
  participant DriveAPI
  Operator->>DriveCopy: Provide source, name, and folder
  DriveCopy->>DriveCopy: Resolve and validate inputs
  DriveCopy->>DriveAPI: POST files copy request
  DriveAPI-->>DriveCopy: Return copied-file metadata
  DriveCopy-->>Operator: Print copy status and resource URL
Loading

Possibly related PRs

Suggested reviewers: fangshuyu-768

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 clearly and concisely identifies the main change: adding the drive +copy shortcut.
Description check ✅ Passed The description covers the summary, implementation scope, testing, and related issues, but it omits the explicit Changes section.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch feat/drive-copy-shortcut
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/drive-copy-shortcut

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.

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown

PR Quality Summary

CI did not complete successfully. Use the failed check links below to decide whether this PR needs a code change or a rerun.

Failed checks

@github-actions

Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@f3d0a65a847a3932a614d044247ead780a9d17f2

🧩 Skill update

npx skills add larksuite/cli#feat/drive-copy-shortcut -y -g

@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.

🧹 Nitpick comments (1)
tests/cli_e2e/drive/drive_copy_dryrun_test.go (1)

105-108: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the exact exit code for the Validate-stage rejection.

The test only checks result.ExitCode == 0 fails. Assert result.ExitCode == 2 directly. Based on learnings, when a shortcut's Validate callback rejects input, the CLI exits with code 2 and prints a structured JSON error envelope to stdout. Asserting the exact code makes this a stronger contract test and matches the established pattern used elsewhere in this test suite (e.g., TestDrive_PullDryRunRejectsAbsoluteLocalDir).

♻️ Proposed tightening of the exit-code assertion
-	if result.ExitCode == 0 {
+	if result.ExitCode != 2 {
 		t.Fatalf("wiki URL should be rejected with a redirect error\nstdout:\n%s\nstderr:\n%s", result.Stdout, result.Stderr)
 	}
🤖 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 `@tests/cli_e2e/drive/drive_copy_dryrun_test.go` around lines 105 - 108, Update
the exit-code assertion in the affected dry-run rejection test to require
result.ExitCode == 2 directly, preserving the existing failure diagnostics and
stdout/stderr checks.

Source: Learnings

🤖 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.

Nitpick comments:
In `@tests/cli_e2e/drive/drive_copy_dryrun_test.go`:
- Around line 105-108: Update the exit-code assertion in the affected dry-run
rejection test to require result.ExitCode == 2 directly, preserving the existing
failure diagnostics and stdout/stderr checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a0e2c344-7685-4d93-a2ca-c7cd425f8c29

📥 Commits

Reviewing files that changed from the base of the PR and between cfe76ad and f3d0a65.

📒 Files selected for processing (9)
  • shortcuts/drive/drive_copy.go
  • shortcuts/drive/drive_copy_test.go
  • shortcuts/drive/shortcuts.go
  • shortcuts/drive/shortcuts_test.go
  • skills/lark-drive/SKILL.md
  • skills/lark-drive/references/lark-drive-copy.md
  • tests/cli_e2e/drive/coverage.md
  • tests/cli_e2e/drive/drive_copy_dryrun_test.go
  • tests/cli_e2e/drive/drive_copy_workflow_test.go

@codecov

codecov Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.72727% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.43%. Comparing base (fa9c30c) to head (f3d0a65).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
shortcuts/drive/drive_copy.go 97.71% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2129      +/-   ##
==========================================
+ Coverage   75.39%   75.43%   +0.04%     
==========================================
  Files         924      925       +1     
  Lines       98005    98181     +176     
==========================================
+ Hits        73895    74067     +172     
- Misses      18478    18480       +2     
- Partials     5632     5634       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread skills/lark-drive/references/lark-drive-copy.md Outdated
Comment thread skills/lark-drive/references/lark-drive-copy.md
Comment thread skills/lark-drive/references/lark-drive-copy.md Outdated
Comment thread skills/lark-drive/references/lark-drive-copy.md Outdated
Comment thread skills/lark-drive/SKILL.md Outdated
@zzzchao123
zzzchao123 force-pushed the feat/drive-copy-shortcut branch 6 times, most recently from 85c093b to 07b9b3a Compare July 31, 2026 07:19

@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: 2

🧹 Nitpick comments (2)
shortcuts/drive/drive_copy_test.go (1)

30-61: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add a case for a matching --type with a URL input.

The table covers a conflicting --type (lines 80-86) but not a matching one. The flag description states that --type is optional for URLs and must match the URL type. A case such as --url .../docx/docxCopySource with --type docx, and a case with --type base against a /base/ URL, would lock in the normalized-comparison path at line 190.

🤖 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 `@shortcuts/drive/drive_copy_test.go` around lines 30 - 61, Add table-driven
test cases in the existing drive copy input tests for URL inputs whose --type
matches the URL type, including a /docx/ URL with docx and a /base/ URL with
base; assert the expected token and normalized bitable type to cover the
matching normalized-comparison path.
shortcuts/drive/drive_copy.go (1)

25-25: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Derive the allowed-type text from one source.

The supported-type list is repeated in four places: driveCopyTypes (line 25), the two error messages (lines 204 and 219, 225), and the driveCopyTypeSupported switch (line 294). A future type addition must be applied in each place, and a missed edit produces a misleading error message. Build the message text from the supported set instead.

♻️ Example consolidation
+var driveCopySupportedTypes = []string{"doc", "docx", "sheet", "file", "mindnote", "slides", "bitable"}
+
+// driveCopySupportedTypesText lists the accepted values, including the base alias.
+func driveCopySupportedTypesText() string {
+	return strings.Join(append(driveCopySupportedTypes, "base"), ", ")
+}
+
 func driveCopyTypeSupported(docType string) bool {
-	switch normalizeDriveCopyType(docType) {
-	case "doc", "docx", "sheet", "file", "mindnote", "slides", "bitable":
-		return true
-	default:
-		return false
-	}
+	normalized := normalizeDriveCopyType(docType)
+	for _, allowed := range driveCopySupportedTypes {
+		if normalized == allowed {
+			return true
+		}
+	}
+	return false
 }

Also applies to: 201-226, 292-299

🤖 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 `@shortcuts/drive/drive_copy.go` at line 25, Consolidate supported drive-copy
types around the single source `driveCopyTypes`: update `driveCopyTypeSupported`
to derive membership from that set and build both error messages in the affected
validation paths from the same list, rather than repeating type names. Preserve
the existing validation behavior and keep the displayed allowed-type text
synchronized automatically when `driveCopyTypes` changes.
🤖 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 `@tests/cli_e2e/drive/drive_copy_dryrun_test.go`:
- Around line 139-152: The wiki URL redirect assertions should validate the
typed error’s exact exit code and inspect combined process output. In the
relevant test, replace the nonzero check with result.AssertExitCode(t, 2) (or an
equivalent exact assertion), define combined output from result.Stdout and
result.Stderr, and use it for all validation and guidance string checks.

In `@tests/cli_e2e/drive/drive_copy_workflow_test.go`:
- Around line 18-24: Add clie2e.SkipWithoutTenantAccessToken(t) at the start of
TestDrive_CopyWorkflow, before the createDriveFolder setup, so the workflow is
skipped when tenant/BOT credentials are unavailable.

---

Nitpick comments:
In `@shortcuts/drive/drive_copy_test.go`:
- Around line 30-61: Add table-driven test cases in the existing drive copy
input tests for URL inputs whose --type matches the URL type, including a /docx/
URL with docx and a /base/ URL with base; assert the expected token and
normalized bitable type to cover the matching normalized-comparison path.

In `@shortcuts/drive/drive_copy.go`:
- Line 25: Consolidate supported drive-copy types around the single source
`driveCopyTypes`: update `driveCopyTypeSupported` to derive membership from that
set and build both error messages in the affected validation paths from the same
list, rather than repeating type names. Preserve the existing validation
behavior and keep the displayed allowed-type text synchronized automatically
when `driveCopyTypes` changes.
🪄 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 Plus

Run ID: 8d1d5be5-4615-445c-ae18-efabb82185f2

📥 Commits

Reviewing files that changed from the base of the PR and between 74de554 and 07b9b3a.

📒 Files selected for processing (9)
  • shortcuts/drive/drive_copy.go
  • shortcuts/drive/drive_copy_test.go
  • shortcuts/drive/shortcuts.go
  • shortcuts/drive/shortcuts_test.go
  • skills/lark-drive/SKILL.md
  • skills/lark-drive/references/lark-drive-copy.md
  • tests/cli_e2e/drive/coverage.md
  • tests/cli_e2e/drive/drive_copy_dryrun_test.go
  • tests/cli_e2e/drive/drive_copy_workflow_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • shortcuts/drive/shortcuts_test.go
  • shortcuts/drive/shortcuts.go
  • tests/cli_e2e/drive/coverage.md
  • skills/lark-drive/references/lark-drive-copy.md

Comment thread tests/cli_e2e/drive/drive_copy_dryrun_test.go
Comment thread tests/cli_e2e/drive/drive_copy_workflow_test.go
Comment thread skills/lark-drive/references/lark-drive-copy.md
Comment thread skills/lark-drive/references/lark-drive-copy.md
@zzzchao123
zzzchao123 force-pushed the feat/drive-copy-shortcut branch 3 times, most recently from 61fc386 to 098f3f3 Compare August 4, 2026 03:24
Wrap the Drive file-copy endpoint as drive +copy. Accept a document URL
(recommended) or bare token + --type for the source; the target takes a
folder token, a folder URL, or the my_space constant, which resolves the
caller's My Space root folder via the root-folder-meta endpoint (absent
from platform metadata, works for both user and bot). Repeatable --extra
key=value pairs are forwarded verbatim for special copy semantics (e.g.
target_type=docx to convert a legacy doc during copy). Reject wiki
URLs/tokens with a typed validation error whose hint carries a
ready-to-adapt wiki +node-copy command, because a Drive copy of a
wiki-backed document would land in Drive space instead of the wiki tree.
In bot mode the CLI auto-grants the current CLI user full_access on the
new copy (same behavior as +upload/+import), reporting the outcome in
the permission_grant output field without failing the copy.

Declare docs:document:copy (the narrowest scope in the endpoint's any-of
set) plus a conditional drive:drive.metadata:readonly for my_space
resolution. Cover the shortcut with unit tests, dry-run e2e and a
self-contained live workflow (upload -> copy -> download-verify ->
my_space copy -> cleanup), and register it in
tests/cli_e2e/drive/coverage.md. Route copy intents in the lark-drive
skill to the shortcut instead of the raw files copy service command.
@zzzchao123
zzzchao123 force-pushed the feat/drive-copy-shortcut branch from 098f3f3 to 4582331 Compare August 4, 2026 03:30

@wittam-01 wittam-01 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.

4 个已验证的 P1 finding,待作者处理。


data, err := runtime.CallAPITyped(
"POST",
fmt.Sprintf("/open-apis/drive/v1/files/%s/copy", validate.EncodePathSegment(spec.Ref.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.

[P1] 校验来源 token,避免改变请求路径。 --token .. --type docx 会通过 resolveDriveCopyInputvalidate.EncodePathSegment("..") 仍是 ..,这里最终构造 /open-apis/drive/v1/files/../copy,不再保持 files/:file_token/copy 的路径结构。Fix:在 URL 与裸 token 汇合后、返回 driveCopyRef 前调用 validate.ResourceName(token, sourceFlag),并补充 ..%2e%2e、控制字符和危险 Unicode 的契约测试。

"wiki node %q cannot be copied with drive +copy; use wiki +node-copy instead",
nodeToken,
).WithParam(param).WithHint(
"run: lark-cli wiki +node-copy --space-id <space-id> --node-token %s --target-space-id <target-space-id> (or --target-parent-node-token); resolve <space-id> with: lark-cli wiki +node-get --token %s",

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.

[P1] 不要把原始 token 拼进可执行命令 hint。 nodeToken 来自用户输入,当前使用裸 %s 写进恢复命令;例如包含分号的 token 会在 Agent 或用户照抄 hint 时形成额外 shell 命令。Fix:两处都改用固定 <node-token> 占位符,或统一使用可靠的 shell quoting,并补充分号、空格、反引号等输入的测试。

## 输出

```json
{

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.

[P1] 输出示例缺少 CLI envelope 的 data 层。 实现通过 runtime.Out 输出,新增 live E2E 也读取 data.file_tokendata.namedata.folder_token;这里把 copiedfile_token 等字段写在根节点,会让 Agent 按文档解析时拿不到副本 token。Fix:示例改成 {"ok":true,"identity":"bot","data":{"copied":true,...,"permission_grant":{...}}},并将上文的字段名同步改为 data.permission_grant

| `+sync` | 双向同步本地目录与 Drive 文件夹:拉取 `new_remote`、推送 `new_local`,`modified` 按 `--on-conflict=remote-wins\|local-wins\|keep-both\|ask` 处理;`--quick` 用修改时间近似比较;`--on-duplicate-remote` 支持 `fail` / `newest` / `oldest`;只同步 `type=file`,跳过在线文档和 shortcut,且不会删除两端多余文件。 |
| [`+push`](references/lark-drive-push.md) | 将本地目录推送到 Drive 文件夹,支持 skip / smart / overwrite 与确认后删除远端。 |
| [`+create-shortcut`](references/lark-drive-create-shortcut.md) | 在另一个文件夹里创建现有 Drive 文件的快捷方式。 |
| [`+copy`](references/lark-drive-copy.md) | 复制 doc/docx/sheet/file/mindnote/slides/base(bitable) 到目标文件夹;支持 URL 传参,wiki 输入会引导改用 `wiki +node-copy`。 |

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.

[P1] Wiki 来源应按目标位置分流,不能一律引导到 wiki +node-copy wiki +node-copy 只接收目标 Wiki space/parent,无法表达复制到 Drive 文件夹或 my_space;本 PR 的 copy reference 已说明后一种场景需要先 drive +inspect,再把底层 token/type 交给 drive +copy。Fix:目标是 Wiki 时使用 wiki +node-copy;目标是 Drive/my_space 时使用 drive +inspectdrive +copy,并同步修正快速决策中的无条件路由。


`drive +copy` 只复制云盘(Drive)文件,不接受 wiki URL / token;传入时返回校验错误,错误 hint 会给出替代命令。知识库内复制节点用 [`lark-wiki`](../../lark-wiki/SKILL.md) 的 `wiki +node-copy`;要把 wiki 文档复制成 Drive 空间里的独立副本(脱离知识库),先用 `drive +inspect` 解包拿到底层 `token` 和 `type`,再对底层 token 执行 `drive +copy`。

## 行为说明

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.

结合下错误率监控,之前的一些场景错误也加下引导提示

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.

2 participants