Skip to content

feat(wiki): add +node-get / +node-delete / +space-create shortcuts#904

Open
liujinkun2025 wants to merge 1 commit into
mainfrom
feat/wiki-node-shortcuts
Open

feat(wiki): add +node-get / +node-delete / +space-create shortcuts#904
liujinkun2025 wants to merge 1 commit into
mainfrom
feat/wiki-node-shortcuts

Conversation

@liujinkun2025
Copy link
Copy Markdown
Collaborator

@liujinkun2025 liujinkun2025 commented May 15, 2026

Summary

Fills the wiki node/space CRUD gaps. Three new shortcuts plus a shared async-task helper:

  • wiki +node-get — wraps wiki.spaces.get_node. Accepts a raw node_token / obj_token or a Lark URL (URL path auto-infers obj_type; conflicting explicit --obj-type is rejected). Optional --space-id cross-check. Formatted output: title / obj_type / obj_token / node_token / space_id / parent_node_token / creator / updated_at / url.
  • wiki +node-delete — wraps the space.node delete API. high-risk-write (--yes gated), bounded async delete_node task polling, auto-resolves space_id via get_node when --space-id is omitted, --include-children defaults to true. Maps Lark codes 131011 (UI-approval required) and 131003 (subtree too large) to actionable hints; other codes pass through with the original code preserved.
  • wiki +space-create — wraps spaces.create. User-only identity (the API rejects tenant/bot tokens; framework CheckIdentity enforces it). --name required (no empty-name spaces), --description optional. Flattened space output, no url (the API returns none and there is no space-home URL builder).
  • Refactor — extracted the duplicated wiki delete-task poll loop / status classification into wiki_async_task.go (pollWikiAsyncTask / parseWikiAsyncTaskStatus / wikiAsyncTaskStatus). +delete-space now delegates to it via thin wrappers — no behavior change, ~110 lines of duplication removed.

Also renames the originally-proposed +get-node to +node-get for consistency with the +node-* family.

Risk-level note: spaces.create carries danger:true in the registry, but that flag only drives the lark-cli schema browser's red [danger] tag — it is not a runtime confirmation gate (only risk:high-risk-write is). The raw API runs without --yes today, so +space-create at Risk:write is runtime-consistent; a help Tip surfaces the danger flag and points to +delete-space for undo.

Test plan

  • go test ./shortcuts/... (and full suite excluding tests/cli_e2e) green
  • gofmt -l clean, go vet ./shortcuts/wiki/... clean, ./build.sh OK
  • New unit + httpmock tests: URL/token parsing, obj_type inference & conflict, space-id auto-resolve, sync/async/timeout/failure delete paths, error-code hint mapping, --yes gating, bot-identity rejection, output flattening
  • Manual smoke: --help, --dry-run, validation failures, identity rejection for each shortcut
  • golangci-lint not run (not installed in dev env) — please confirm in CI
  • tests/cli_e2e/wiki not run locally (hits real Feishu) — verify in CI/staging

Summary by CodeRabbit

  • New Features

    • Added wiki commands: +node-delete, +node-get, +space-create
    • Shortcuts list updated to include the new wiki commands
    • Shared async-task polling improved and used by wiki delete flows
  • Tests

    • Comprehensive tests added for new wiki commands and async-task polling behavior

Review Change Stack

@github-actions github-actions Bot added domain/ccm PR touches the ccm domain size/XL Architecture-level or global-impact change labels May 15, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 15, 2026

📝 Walkthrough

Walkthrough

Adds three wiki shortcuts (+space-create, +node-get, +node-delete), extracts shared async-task parsing/polling helpers used by delete flows, refactors delete-space to use the shared helpers, updates the shortcut registry, and adds comprehensive tests for the new commands and async polling.

Changes

Wiki node operations

Layer / File(s) Summary
Shared async task polling and tests
shortcuts/wiki/wiki_async_task.go, shortcuts/wiki/wiki_async_task_test.go
Adds unified async-task parsing and a bounded polling helper; tests cover success, terminal failure, timeout, wrapped upstream errors, and context cancellation.
wiki_delete refactor
shortcuts/wiki/wiki_delete.go
Replaces bespoke delete-space polling/normalization with aliases/wrappers that call the shared async helpers and updates parsing/polling call sites.
Wiki space create command
shortcuts/wiki/wiki_space_create.go, shortcuts/wiki/wiki_space_create_test.go
Implements +space-create with --name/--description, request body building, dry-run, execute flow, flattened output, auth/scope enforcement, and mounted/unit tests.
Wiki node get command
shortcuts/wiki/wiki_node_get.go, shortcuts/wiki/wiki_node_get_test.go
Implements +node-get supporting URL/raw token inputs with obj_type inference/validation, GET /open-apis/wiki/v2/spaces/get_node dry-run/execute, timestamp formatting, output shaping, and tests for parsing, dry-run, and mounted execution.
Wiki node delete command
shortcuts/wiki/wiki_node_delete.go, shortcuts/wiki/wiki_node_delete_test.go
Implements +node-delete with token/url parsing, optional space resolution, sync vs async delete handling via shared polling, error hint augmentation for specific API codes, dry-run, and broad unit/mounted tests.
Shortcut registry integration
shortcuts/wiki/shortcuts.go, shortcuts/wiki/wiki_node_create_test.go
Updates Shortcuts() to include the new WikiSpaceCreate, WikiNodeGet, and WikiNodeDelete shortcuts and adjusts tests expecting the expanded command count.

Sequence Diagram(s)

sequenceDiagram
  participant ComponentA
  participant ComponentB
  ComponentA->>ComponentB: observable interaction
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • larksuite/cli#610: Related earlier work that introduced delete-space async polling and resume guidance used as background for the shared polling helpers.
  • larksuite/cli#320: Also modifies shortcuts/wiki/shortcuts.go to register wiki commands.
  • larksuite/cli#392: Previously extended the wiki shortcuts registration similarly.

Suggested reviewers

  • fangshuyu-768
  • liangshuo-1

Poem

🐰 I hop through code and tidy the trail,
New shortcuts sprout where old ones prevail,
A poller hums softly to watch tasks along,
Space-create, node-get, node-delete — a short song.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.46% 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 pull request title clearly and specifically summarizes the main change: adding three new wiki shortcuts (+node-get, +node-delete, +space-create) to the codebase.
Description check ✅ Passed The pull request description is comprehensive and well-structured, covering all required template sections: Summary (detailed overview of changes), Changes (clear bullet points with specifics), and Test Plan (with checkmarks indicating completion status).
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.

✏️ 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/wiki-node-shortcuts

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

❌ Patch coverage is 82.17636% with 95 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.09%. Comparing base (f03138b) to head (eeda447).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
shortcuts/wiki/wiki_node_get.go 70.39% 43 Missing and 10 partials ⚠️
shortcuts/wiki/wiki_node_delete.go 83.82% 23 Missing and 15 partials ⚠️
shortcuts/wiki/wiki_space_create.go 91.30% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #904      +/-   ##
==========================================
+ Coverage   65.95%   66.09%   +0.14%     
==========================================
  Files         523      527       +4     
  Lines       49590    50060     +470     
==========================================
+ Hits        32707    33088     +381     
- Misses      14090    14153      +63     
- Partials     2793     2819      +26     

☔ View full report in Codecov by Sentry.
📢 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.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 15, 2026

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

npx skills add larksuite/cli#feat/wiki-node-shortcuts -y -g

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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 (1)
shortcuts/wiki/wiki_node_create_test.go (1)

114-126: ⚡ Quick win

Strengthen this test to assert the newly added commands explicitly.

Checking only len(shortcuts) == 9 won’t catch a wrong/missing command if count stays the same. Add assertions for +space-create, +node-get, and +node-delete (or assert the full expected command list).

Suggested test hardening
 func TestWikiShortcutsIncludeAllCommands(t *testing.T) {
 	t.Parallel()

 	shortcuts := Shortcuts()
 	if len(shortcuts) != 9 {
 		t.Fatalf("len(Shortcuts()) = %d, want 9", len(shortcuts))
 	}
+	got := make([]string, 0, len(shortcuts))
+	for _, sc := range shortcuts {
+		got = append(got, sc.Command)
+	}
+	want := []string{
+		"+move",
+		"+node-create",
+		"+delete-space",
+		"+space-list",
+		"+space-create",
+		"+node-list",
+		"+node-copy",
+		"+node-get",
+		"+node-delete",
+	}
+	for i := range want {
+		if got[i] != want[i] {
+			t.Fatalf("shortcuts[%d].Command = %q, want %q", i, got[i], want[i])
+		}
+	}
-	if shortcuts[0].Command != "+move" {
-		t.Fatalf("shortcuts[0].Command = %q, want %q", shortcuts[0].Command, "+move")
-	}
-	if shortcuts[1].Command != "+node-create" {
-		t.Fatalf("shortcuts[1].Command = %q, want %q", shortcuts[1].Command, "+node-create")
-	}
-	if shortcuts[2].Command != "+delete-space" {
-		t.Fatalf("shortcuts[2].Command = %q, want %q", shortcuts[2].Command, "+delete-space")
-	}
 }
🤖 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/wiki/wiki_node_create_test.go` around lines 114 - 126, The test in
wiki_node_create_test.go currently only checks len(shortcuts) and a few
commands; strengthen it by asserting the full expected command list or at
minimum add explicit checks for the newly added commands: verify that shortcuts
contains "+space-create", "+node-get", and "+node-delete" (in addition to
existing checks for "+move", "+node-create", "+delete-space"), using the same
pattern as the existing assertions against shortcuts[n].Command so the test
fails if any command is missing or out of order.
🤖 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 `@shortcuts/wiki/wiki_async_task.go`:
- Around line 165-172: The retry logic currently calls output.ErrWithHint which
rebuilds and loses structured API detail; instead, detect when lastErr is an
*output.ExitError (the existing exitErr variable) and preserve its Detail fields
(Code, ConsoleURL, Risk, nested Detail, etc.) while only appending the retry
hint to the message/hint field, then return the original or a minimally-updated
ExitError so structured fields are retained; update the branch handling
lastErr/exitErr around the existing output.ErrWithHint call to reuse
exitErr.Detail rather than reconstructing the error.
- Around line 65-73: The StatusCode method on wikiAsyncTaskStatus returns raw
non-empty statuses which can conflict with Failed(); update StatusCode() to
align with the helper's non-terminal classification by returning
wikiAsyncStatusProcessing for any status that is not explicitly ready/successful
or explicitly failed/terminal. In practice, inside StatusCode() (on
wikiAsyncTaskStatus) trim the value, then use the same readiness/terminal logic
used by Failed() (or call a shared helper) to detect non-terminal states and
coerce them to wikiAsyncStatusProcessing, otherwise return the original terminal
status.

---

Nitpick comments:
In `@shortcuts/wiki/wiki_node_create_test.go`:
- Around line 114-126: The test in wiki_node_create_test.go currently only
checks len(shortcuts) and a few commands; strengthen it by asserting the full
expected command list or at minimum add explicit checks for the newly added
commands: verify that shortcuts contains "+space-create", "+node-get", and
"+node-delete" (in addition to existing checks for "+move", "+node-create",
"+delete-space"), using the same pattern as the existing assertions against
shortcuts[n].Command so the test fails if any command is missing or out of
order.
🪄 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: 5a211eba-1323-42a1-9667-4ef59fe458ee

📥 Commits

Reviewing files that changed from the base of the PR and between 4a45e00 and f282650.

📒 Files selected for processing (10)
  • shortcuts/wiki/shortcuts.go
  • shortcuts/wiki/wiki_async_task.go
  • shortcuts/wiki/wiki_delete.go
  • shortcuts/wiki/wiki_node_create_test.go
  • shortcuts/wiki/wiki_node_delete.go
  • shortcuts/wiki/wiki_node_delete_test.go
  • shortcuts/wiki/wiki_node_get.go
  • shortcuts/wiki/wiki_node_get_test.go
  • shortcuts/wiki/wiki_space_create.go
  • shortcuts/wiki/wiki_space_create_test.go

Comment on lines +65 to +73
// StatusCode returns a never-empty status value for the output envelope. If
// the backend response omits delete_*_result.status (or sends whitespace),
// fall back to "processing" so the documented timeout-shape stays accurate.
func (s wikiAsyncTaskStatus) StatusCode() string {
if status := strings.TrimSpace(s.Status); status != "" {
return status
}
return wikiAsyncStatusProcessing
}
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

Keep status aligned with the helper's non-terminal classification.

Failed() intentionally treats unknown non-success values as “still processing”, but StatusCode() returns those raw values unchanged. That can yield an internally inconsistent result like status="canceled", failed=false while the command prints “still in progress”. Either classify additional terminal states explicitly or coerce any non-ready/non-failed status to processing here.

♻️ Suggested change
 func (s wikiAsyncTaskStatus) StatusCode() string {
-	if status := strings.TrimSpace(s.Status); status != "" {
-		return status
-	}
-	return wikiAsyncStatusProcessing
+	switch status := s.normalizedStatus(); {
+	case status == "":
+		return wikiAsyncStatusProcessing
+	case s.Ready():
+		return wikiAsyncStatusSuccess
+	case s.Failed():
+		return wikiAsyncStatusFailure
+	default:
+		return wikiAsyncStatusProcessing
+	}
 }
🤖 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/wiki/wiki_async_task.go` around lines 65 - 73, The StatusCode
method on wikiAsyncTaskStatus returns raw non-empty statuses which can conflict
with Failed(); update StatusCode() to align with the helper's non-terminal
classification by returning wikiAsyncStatusProcessing for any status that is not
explicitly ready/successful or explicitly failed/terminal. In practice, inside
StatusCode() (on wikiAsyncTaskStatus) trim the value, then use the same
readiness/terminal logic used by Failed() (or call a shared helper) to detect
non-terminal states and coerce them to wikiAsyncStatusProcessing, otherwise
return the original terminal status.

Comment thread shortcuts/wiki/wiki_async_task.go
- +node-get: wrap wiki.spaces.get_node; accepts node_token, obj_token,
  or a Lark URL (URL path auto-infers obj_type); formatted output with
  creator / updated_at / url
- +node-delete: wrap space.node delete; high-risk-write (--yes gated),
  async delete-node task polling, auto-resolves space_id via get_node
  when --space-id omitted, actionable hints for codes 131011 / 131003
- +space-create: wrap spaces.create; user-only identity, --name
  required (no empty-name spaces), flattened space output, no url
- factor the shared wiki async-task poll loop into wiki_async_task.go
  and refactor +delete-space onto it (no behavior change)

Change-Id: Ib7bcb9ab826c71b0aa943303f6eb34a5d993cf10
@liujinkun2025 liujinkun2025 force-pushed the feat/wiki-node-shortcuts branch from f282650 to eeda447 Compare May 15, 2026 08:47
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
shortcuts/wiki/wiki_space_create.go (1)

108-119: ⚡ Quick win

Reuse the shared space-record formatter here.

This open-codes the flattened space fields even though the file already references parseWikiSpaceRecord. Composing the shared parser/formatter and then overlaying description would keep +space-create aligned with the other wiki space outputs and avoid future drift.

🤖 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/wiki/wiki_space_create.go` around lines 108 - 119, Replace the
manual field extraction in wikiSpaceCreateOutput with a call to the shared
parser/formatter parseWikiSpaceRecord(raw) and then overlay or set the
"description" key from the raw map so the create output stays consistent with
other wiki space outputs; specifically, inside wikiSpaceCreateOutput call
parseWikiSpaceRecord(raw) to get the base map, copy/merge that into the returned
map, and ensure "description" is taken from common.GetString(raw, "description")
to override or preserve the caller-provided description.
🤖 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 `@shortcuts/wiki/wiki_space_create.go`:
- Around line 108-119: Replace the manual field extraction in
wikiSpaceCreateOutput with a call to the shared parser/formatter
parseWikiSpaceRecord(raw) and then overlay or set the "description" key from the
raw map so the create output stays consistent with other wiki space outputs;
specifically, inside wikiSpaceCreateOutput call parseWikiSpaceRecord(raw) to get
the base map, copy/merge that into the returned map, and ensure "description" is
taken from common.GetString(raw, "description") to override or preserve the
caller-provided description.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2154a194-f9ac-466c-8175-f64a619eadf2

📥 Commits

Reviewing files that changed from the base of the PR and between f282650 and eeda447.

📒 Files selected for processing (11)
  • shortcuts/wiki/shortcuts.go
  • shortcuts/wiki/wiki_async_task.go
  • shortcuts/wiki/wiki_async_task_test.go
  • shortcuts/wiki/wiki_delete.go
  • shortcuts/wiki/wiki_node_create_test.go
  • shortcuts/wiki/wiki_node_delete.go
  • shortcuts/wiki/wiki_node_delete_test.go
  • shortcuts/wiki/wiki_node_get.go
  • shortcuts/wiki/wiki_node_get_test.go
  • shortcuts/wiki/wiki_space_create.go
  • shortcuts/wiki/wiki_space_create_test.go
✅ Files skipped from review due to trivial changes (1)
  • shortcuts/wiki/wiki_node_create_test.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • shortcuts/wiki/shortcuts.go
  • shortcuts/wiki/wiki_space_create_test.go
  • shortcuts/wiki/wiki_node_get_test.go
  • shortcuts/wiki/wiki_node_get.go
  • shortcuts/wiki/wiki_delete.go
  • shortcuts/wiki/wiki_async_task.go
  • shortcuts/wiki/wiki_node_delete.go
  • shortcuts/wiki/wiki_node_delete_test.go

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/XL Architecture-level or global-impact change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant