Skip to content

feat: Add whiteboard +query shortcut and enhance +update with Mermaid/PlantUML support #382

Merged
syh-cpdsss merged 1 commit intomainfrom
feat/whiteboard-dev
Apr 10, 2026
Merged

feat: Add whiteboard +query shortcut and enhance +update with Mermaid/PlantUML support #382
syh-cpdsss merged 1 commit intomainfrom
feat/whiteboard-dev

Conversation

@syh-cpdsss
Copy link
Copy Markdown
Collaborator

@syh-cpdsss syh-cpdsss commented Apr 10, 2026

Summary

This PR introduces a dedicated whiteboard business domain, adds new whiteboard query/update capabilities, and enhances whiteboard integration with Lark documents. The changes enable better whiteboard discoverability, usage, and visual quality for AI agents and users.

Changes

CLI Feature Updates

  1. Independent Whiteboard Business Domain:

    • Split whiteboard functionality from docs domain into its own dedicated whiteboard domain
    • Added login logic to merge whiteboard permission scopes with docs domain automatically
  2. Enhanced Whiteboard Update Shortcut:

    • Moved from docs +whiteboard-update to whiteboard +update
    • Added support for file input
    • Added support for updating whiteboards using Mermaid and PlantUML code (via file input or stdin)
  3. New Whiteboard Query Shortcut:

    • Added whiteboard +query shortcut for exporting whiteboards
    • Added support for exporting as preview image
    • Added support for exporting as Mermaid/PlantUML code (available only when the whiteboard contains exactly one Mermaid/PlantUML diagram)
    • Added support for exporting as Lark/Feishu OpenAPI raw node layout format

Skill Updates

  1. Enhanced Whiteboard Drawing Capabilities:

    • Improved whiteboard styling
    • Enhanced visual aesthetics of whiteboard updates
    • Better diagram presentation quality
  2. Better Integration with Lark Documents:

    • Increased agent proactivity in creating whiteboards when writing documents
    • Improved documentation with more diagrams and visual elements
    • Enhanced overall document visual richness

Test Plan

  • Unit tests pass
  • Manual local verification confirms lark whiteboard +query and lark whiteboard +update commands work as expected (tested all major paths including writing in mermaid/plantuml/Raw formats and exporting in preview image/Code/Raw formats)
  • Verified through a series of simulated user use cases

Summary by CodeRabbit

  • New Features

    • Whiteboard: new +query (image/code/raw), revamped +update supporting plantuml/mermaid/raw, additional shortcut variants, improved export modes and file handling.
  • Bug Fixes

    • Auth-domain handling: parent/child domain scopes now expand and domain lists exclude auth-domain children for validation/suggestions.
  • Documentation

    • Major additions and reorganizations across whiteboard and CLI docs, scene guides, schema, layout, and usage workflows.
  • Tests

    • New registry and extensive whiteboard query/update test suites.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 10, 2026

CLA assistant check
All committers have signed the CLA.

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

coderabbitai Bot commented Apr 10, 2026

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 auth-domain parent/child support in the registry and login flows; excludes auth-domain children from top-level domain lists; implements whiteboard +query (image/code/raw) and refactors whiteboard +update to support --source/--input_format; updates whiteboard docs and adds tests.

Changes

Cohort / File(s) Summary
Auth Domain Registry
internal/registry/service_desc.go, internal/registry/service_descriptions.json, internal/registry/registry_test.go
Add auth_domain JSON field; implement GetAuthDomain, HasAuthDomain, GetAuthChildren; mark whiteboard as child of docs; add registry tests for parent/child behavior.
Login: auth-domain handling
cmd/auth/login.go, cmd/auth/login_interactive.go, cmd/auth/login_test.go
Expand requested domains with GetAuthChildren during scope collection; exclude services with auth_domain from known-domain lists and interactive suggestions; add tests verifying exclusion/expansion.
Whiteboard: Query Shortcut
shortcuts/whiteboard/shortcuts.go, shortcuts/whiteboard/whiteboard_query.go, shortcuts/whiteboard/whiteboard_query_test.go
Add whiteboard +query supporting `image
Whiteboard: Update Shortcut & refactor
shortcuts/whiteboard/whiteboard_update.go, shortcuts/whiteboard/whiteboard_update_test.go, shortcuts/whiteboard/shortcuts.go
Refactor update into Validate/DryRun/Execute; add --source and --input_format (`raw
Shortcuts list & output models
shortcuts/whiteboard/shortcuts.go
Expose new shortcuts (WhiteboardQuery, WhiteboardUpdateOld) and add RawNodes []interface{} to WbCliOutput.
Docs: lark-whiteboard-cli & schema
skills/lark-whiteboard-cli/SKILL.md, skills/lark-whiteboard-cli/references/schema.md, skills/lark-whiteboard-cli/references/*
Add/extend CLI docs: new dagre layout + layoutOptions, icon node type, layout/connector/style/typography guidance, many scene docs, and bump recommended CLI versions.
Docs: scenes & examples
skills/lark-whiteboard-cli/scenes/*
Add flowchart and swimlane scene guides; standardize generated filename to diagram.json; update examples to @^0.2.0; editorial updates across scenes.
Docs: lark-doc integration
skills/lark-doc/SKILL.md, skills/lark-doc/references/*
Add whiteboard creation/workflow guidance, HTML-escaping note, and integration steps (extract tokens, create blank whiteboards, fill via whiteboard CLI); deprecate legacy whiteboard-update doc.
Docs: lark-whiteboard skill & refs
skills/lark-whiteboard/SKILL.md, skills/lark-whiteboard/references/*
Restructure whiteboard skill docs around +query/+update, add new references and examples, update front-matter and workflows.
Tests: registry & whiteboard
internal/registry/registry_test.go, shortcuts/whiteboard/*_test.go, cmd/auth/login_test.go
Add tests for auth-domain registry behavior and comprehensive unit/integration tests for +query and +update with HTTP mocks and file I/O checks.
Removed/Deleted docs
skills/lark-whiteboard/references/layout.md
Delete previous layout guidance page (content redistributed to other docs).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AuthCmd as Auth Command
    participant Registry
    participant Validator as Domain Validator

    Client->>AuthCmd: login --domains=docs
    AuthCmd->>Registry: GetAuthChildren("docs")
    Registry-->>AuthCmd: ["whiteboard"]
    AuthCmd->>AuthCmd: expand domains -> ["docs","whiteboard"]
    AuthCmd->>Validator: match shortcut scopes for each domain
    Validator-->>AuthCmd: scopes
    AuthCmd-->>Client: Combined scopes
Loading
sequenceDiagram
    participant Client
    participant Query as Whiteboard +query
    participant API as Whiteboard API
    participant FS as File System

    Client->>Query: whiteboard +query --whiteboard-token=xyz --output_as=code
    Query->>API: GET /open-apis/board/v1/whiteboards/xyz/nodes
    API-->>Query: {code:0, data: {nodes: [...]}}
    Query->>Query: extract PlantUML/Mermaid blocks
    alt single code block
        Query->>FS: write file or stdout
        FS-->>Query: success
    else multiple/none
        Query-->>Client: error message
    end
    Query-->>Client: result
Loading
sequenceDiagram
    participant Client
    participant Update as Whiteboard +update
    participant Parser as Input Parser
    participant API as Whiteboard API

    Client->>Update: whiteboard +update --whiteboard-token=xyz --input_format=mermaid --source=-
    Update->>Parser: read stdin/file
    Parser-->>Update: content
    alt plantuml/mermaid
        Update->>API: POST /open-apis/.../plantuml (or mermaid)
        API-->>Update: created node(s)
    else raw
        Update->>API: POST /open-apis/.../nodes
        API-->>Update: created node(s)
    end
    Update->>API: GET existing nodes
    API-->>Update: existing nodes
    Update->>Update: compute protected IDs (incl. transitive children)
    Update->>API: batch delete unprotected nodes
    API-->>Update: deletion result
    Update-->>Client: update complete
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

size/L

Suggested reviewers

  • liujinkun2025
  • zhouyue-bytedance

Poem

🐰 I nibble tokens, hop through docs and boards,
Parents fold children, scopes expand like chords.
Query pulls images, code, or raw delight,
Update reads formats, plants diagrams right.
A rabbit’s little hop—clean, tested, and bright.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main feature: adding a whiteboard +query shortcut and enhancing +update with Mermaid/PlantUML support.
Description check ✅ Passed The PR description follows the template with comprehensive Summary, Changes, and Test Plan sections covering all major updates including the new whiteboard domain, query/update capabilities, and skill improvements.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/whiteboard-dev

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

@syh-cpdsss syh-cpdsss added the domain/whiteboard Whiteboard domain label Apr 10, 2026
@syh-cpdsss syh-cpdsss self-assigned this Apr 10, 2026
@github-actions github-actions Bot removed the domain/whiteboard Whiteboard domain label Apr 10, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 10, 2026

Greptile Summary

This PR introduces a dedicated whiteboard business domain with two new shortcuts (whiteboard +query for exporting whiteboards as image/code/raw, and a revamped whiteboard +update supporting raw, PlantUML, and Mermaid formats), while keeping the old docs +whiteboard-update as a backward-compatible alias. Auth login is enhanced to automatically fold whiteboard permission scopes into the docs domain via a new auth_domain mechanism in the service registry.

Confidence Score: 5/5

Safe to merge; only a minor url.PathEscape inconsistency remains as a P2 style suggestion.

All remaining findings are P2 or lower. The auth-domain expansion logic is sound, both shortcuts are well-tested with comprehensive happy and error paths, and the saveOutputFile consolidation cleanly addresses the previously flagged path-handling inconsistencies. The one new finding (missing url.PathEscape in fetchWhiteboardNodes) is a style inconsistency that does not affect practical usage since Lark whiteboard tokens are alphanumeric.

shortcuts/whiteboard/whiteboard_query.go — minor url.PathEscape inconsistency in fetchWhiteboardNodes

Important Files Changed

Filename Overview
shortcuts/whiteboard/whiteboard_query.go New +query shortcut; well-structured with saveOutputFile consolidating all three export paths, but fetchWhiteboardNodes omits url.PathEscape unlike every other call site in the package.
shortcuts/whiteboard/whiteboard_update.go Revamped +update with plantuml/mermaid/raw format support; overwrite flow correctly creates new node first then deletes old ones with child-node protection. All url.PathEscape usages are consistent here.
cmd/auth/login.go Auth-domain expansion correctly folds whiteboard scopes into docs domain; allKnownDomains excludes auth_domain children; sortedKnownDomains refactor is clean.
internal/registry/service_desc.go New auth_domain helpers (GetAuthDomain, HasAuthDomain, GetAuthChildren) are well-implemented with lazy-loaded caching; single-level expansion only — acceptable given current data.
shortcuts/whiteboard/whiteboard_query_test.go Comprehensive test coverage for all export modes, edge cases (empty nodes, multiple code blocks, invalid syntax type, API errors), and saveOutputFile path handling.
shortcuts/whiteboard/whiteboard_update_test.go Good coverage of raw/plantuml/mermaid formats, overwrite flow with node deletion, idempotent token, and error paths.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[lark whiteboard +query] --> B{output_as?}
    B -->|image| C[exportWhiteboardPreview\nGET /whiteboards/token/download_as_image]
    B -->|code| D[exportWhiteboardCode\nGET /whiteboards/token/nodes]
    B -->|raw| E[exportWhiteboardRaw\nGET /whiteboards/token/nodes]
    C --> F[saveOutputFile → .png]
    D --> G{syntaxBlocks?}
    G -->|0| H[msg: whiteboard is empty / no code blocks]
    G -->|>1| I[msg: multiple code blocks]
    G -->|1| J[saveOutputFile → .puml/.mmd]
    E --> K[saveOutputFile → .json]

    L[lark whiteboard +update] --> M{input_format?}
    M -->|raw| N[parseWBcliNodes\nPOST /whiteboards/token/nodes]
    M -->|plantuml/mermaid| O[POST /whiteboards/token/nodes/plantuml]
    N --> P{overwrite?}
    O --> P
    P -->|yes| Q[clearWhiteboardContent\nGET nodes → DELETE batch]

    R[lark login --domain docs] --> S[collectScopesForDomains]
    S --> T[GetAuthChildren docs → whiteboard]
    T --> U[Include whiteboard shortcut scopes]
Loading

Reviews (10): Last reviewed commit: "feat: Add whiteboard +query shortcut and..." | Re-trigger Greptile

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 10, 2026

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

npx skills add larksuite/cli#feat/whiteboard-dev -y -g

Comment thread shortcuts/whiteboard/whiteboard_query.go Outdated
Comment thread shortcuts/whiteboard/whiteboard_query.go Outdated
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: 18

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
skills/lark-whiteboard-cli/references/schema.md (1)

34-83: ⚠️ Potential issue | 🔴 Critical

Dagre layout features documented but implementation not found in codebase.

The documentation describes extensive Dagre layout functionality (lines 39-48: layoutOptions with rankdir, nodesep, edgesep, ranksep, edges, isCluster; lines 58-83: detailed nesting rules including edge redirect fallback and compound clusters). However, a comprehensive search of the repository finds no corresponding TypeScript/JavaScript implementation code. The cmd/schema/schema.go file is an API schema CLI tool unrelated to whiteboard layout rendering. This indicates either the documentation is premature/aspirational or the implementation exists in an undiscovered location. Either way, the documented schema and actual implementation do not currently align and need reconciliation before this documentation can be considered accurate.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard-cli/references/schema.md` around lines 34 - 83, The
docs describe Dagre features (layoutOptions, rankdir, nodesep, edgesep, ranksep,
edges, isCluster, edge redirect fallback, compound cluster behavior, and
restrictions on children/WBNode/fillColor) but no implementation exists; either
implement the features in the layout engine or remove/mark the docs as
aspirational. To fix: locate the whiteboard layout renderer and add Dagre
support that consumes layoutOptions (handle rankdir/nodesep/edgesep/ranksep),
implement edges parsing at the root Dagre only and the Edge Redirect Fallback
(resolve internal targets to nearest opaque ancestor), implement isCluster
semantics so clusters participate in outer Dagre topology and allow edges to
cross boundaries while cluster sizes are derived from child bounding boxes, and
add schema/runtime validation to enforce children cannot include connector and
warn/make fillColor/border* required for frames that must persist;
alternatively, if not implementing now, update schema.md to clearly mark Dagre
features as planned/not-yet-implemented and remove/clarify any behavioral
guarantees.
🟡 Minor comments (8)
skills/lark-whiteboard-cli/references/connectors.md-75-75 (1)

75-75: ⚠️ Potential issue | 🟡 Minor

Minor Chinese grammar issue.

The phrase "优雅的跨层连线" should be "优雅地跨层连线" when using an adjective to modify a verb phrase. In Chinese, "地" is used for adverbial modification, while "的" is for attributive modification.

✏️ Suggested fix
-> - **`'curve'`(曲线)**:适用于优雅的跨层连线(S型弯)、自由发散的脑图分支、或做注解箭头时。
+> - **`'curve'`(曲线)**:适用于优雅地跨层连线(S型弯)、自由发散的脑图分支、或做注解箭头时。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard-cli/references/connectors.md` at line 75, Fix the
Chinese grammar in the connector description containing the "'curve'(曲线)"
phrase: change "优雅的跨层连线" to "优雅地跨层连线" so the adverb correctly modifies the verb
phrase; update the sentence in the connectors.md entry for "'curve'(曲线)"
accordingly.
skills/lark-whiteboard-cli/references/style.md-216-225 (1)

216-225: ⚠️ Potential issue | 🟡 Minor

Add explicit width/height to the wrapper, or mark this as a partial style fragment.

This reads like a complete component example, but the outer frame omits width and height. That makes it easy to copy into JSON that no longer matches the sizing rules documented elsewhere in this skill set.

Suggested fix
 {
-  "type": "frame", "layout": "vertical", "gap": 4, "padding": 12,
+  "type": "frame", "width": "fit-content", "height": "fit-content", "layout": "vertical", "gap": 4, "padding": 12,
   "alignItems": "center", "fillColor": "#FFFFFF", "borderColor": "#5178C6", "borderWidth": 2, "borderRadius": 8,
   "children": [
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard-cli/references/style.md` around lines 216 - 225, The
example JSON shows a complete "type": "frame" object lacking explicit
width/height which can violate sizing rules; update the outer frame object (the
"type": "frame" entry with keys layout, gap, padding, alignItems, fillColor,
borderColor, borderWidth, borderRadius and children) to either include explicit
numeric "width" and "height" properties that follow the documented sizing rules,
or mark this snippet as a partial style fragment (e.g., add a clear "partial" or
"fragment" indicator in the example text) so consumers know it’s not a full
standalone component.
skills/lark-whiteboard/references/lark-whiteboard-update.md-73-93 (1)

73-93: ⚠️ Potential issue | 🟡 Minor

Update whiteboard-cli version to match other documentation files.

The guide references @larksuite/whiteboard-cli@^0.1.0 (lines 77, 87), but all other skill documentation files—including skills/lark-whiteboard-cli/references/layout.md, scene guides, and SKILL.md—already reference @^0.2.0. Aligning this file to ^0.2.0 ensures users receive consistent version guidance across the documentation set.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard/references/lark-whiteboard-update.md` around lines 73
- 93, Update the CLI version mentions '@larksuite/whiteboard-cli@^0.1.0' in both
code examples to '@larksuite/whiteboard-cli@^0.2.0' so this file matches the
other docs; specifically replace the version string in the lines that invoke npx
--to openapi (the two occurrences shown in the examples) to ensure consistency
with the other skill documentation.
shortcuts/whiteboard/whiteboard_query_test.go-159-203 (1)

159-203: ⚠️ Potential issue | 🟡 Minor

Assert the dry-run route, not just non-nil.

This table carries wantMethod and wantPath, but the test never compares them with the returned dry-run object. A broken endpoint/method would still pass here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_query_test.go` around lines 159 - 203, The
test currently calls WhiteboardQuery.DryRun(ctx, rt) and only checks for
non-nil; update the subtest to also assert the returned dry-run object's HTTP
method and path match the table's wantMethod and wantPath. Locate the call to
WhiteboardQuery.DryRun in the loop and after the nil check extract the method
and path from the returned object (e.g., dryRun.Method / dryRun.Path or the
appropriate fields/methods on the DryRun result) and compare them to
tt.wantMethod and tt.wantPath using t.Fatalf or t.Errorf so each case fails if
the route or verb is incorrect.
shortcuts/whiteboard/whiteboard_update_test.go-532-575 (1)

532-575: ⚠️ Potential issue | 🟡 Minor

Make the API-error tests fail on unexpected success.

These tests only log when err == nil, so a regression that stops surfacing API failures would still pass CI.

Suggested fix
 	err := runUpdateShortcut(t, WhiteboardUpdate, args, factory, stdout, stdin)
-	// We expect an error here, but don't fail the test because it's testing error path
 	if err == nil {
-		t.Logf("Expected API error, but got none")
+		t.Fatalf("expected an error, got nil")
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_update_test.go` around lines 532 - 575,
Change the two tests TestWhiteboardUpdateExecute_RawAPIError and
TestWhiteboardUpdateExecute_PlantUMLAPIError to fail when the shortcut
unexpectedly succeeds: after calling runUpdateShortcut (the variable err),
replace the conditional t.Logf check with an assertion that err is non-nil
(e.g., t.Fatalf or t.Errorf/t.FailNow) so the test fails on unexpected success;
ensure you update both tests that reference runUpdateShortcut and
WhiteboardUpdate to assert/require an error rather than just logging.
shortcuts/whiteboard/whiteboard_update_test.go-187-209 (1)

187-209: ⚠️ Potential issue | 🟡 Minor

Cover the legacy shortcut registration in Shortcuts().

This test only requires +update and +query, so it would still pass if WhiteboardUpdateOld stopped being returned from shortcuts/whiteboard/shortcuts.go. That leaves the new backward-compatibility registration unprotected.

Suggested fix
 	want := []string{
 		"+update",
+		"+whiteboard-update",
 		"+query",
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_update_test.go` around lines 187 - 209, The
test only checks for commands but not that the legacy registration is returned;
update TestShortcutsIncludesExpectedCommands to also assert that the legacy
shortcut WhiteboardUpdateOld is present in Shortcuts() — e.g., iterate got and
verify at least one entry is the same as WhiteboardUpdateOld (or has its Handler
equal to WhiteboardUpdateOld) and fail the test if not, so the
backward-compatibility registration cannot be removed unnoticed.
shortcuts/whiteboard/whiteboard_query_test.go-723-754 (1)

723-754: ⚠️ Potential issue | 🟡 Minor

Fail these error-path tests on unexpected success.

Both tests only Logf when err == nil, so regressions in error propagation will still pass CI.

Suggested fix
 	err := runShortcut(t, WhiteboardQuery, args, factory, stdout)
-	// We expect an error here, but don't fail the test because it's testing error path
 	if err == nil {
-		t.Logf("Expected network error, but got none")
+		t.Fatalf("expected an error, got nil")
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_query_test.go` around lines 723 - 754, The
tests TestFetchWhiteboardNodes_NetworkError and
TestFetchWhiteboardNodes_APIError only log when runShortcut(...) returns nil, so
unexpected success won't fail CI; update both tests to assert failure when err
== nil (e.g., replace t.Logf("Expected ... but got none") with t.Fatalf or
t.Errorf to fail the test), keeping the call sites runShortcut(t,
WhiteboardQuery, args, factory, stdout) and preserving existing
setup/registration logic.
skills/lark-whiteboard-cli/SKILL.md-154-155 (1)

154-155: ⚠️ Potential issue | 🟡 Minor

Replace smart quotes in the XML snippets.

The examples use instead of ". If users copy these into XML/markdown payloads verbatim, the snippets will be invalid.

✏️ Suggested fix
-| 文档 URL 或 doc_id,文档中已有画板 | `lark-cli docs +fetch --doc <URL> --as user`,从返回的 `<whiteboard token=”XXX”/>` 中提取 token                                                                |
-| 文档 URL 或 doc_id,需要新建画板   | `lark-cli docs +update --doc <doc_id> --mode append --markdown '<whiteboard type=”blank”></whiteboard>' --as user`,从响应的 `data.board_tokens[0]` 获取 token |
+| 文档 URL 或 doc_id,文档中已有画板 | `lark-cli docs +fetch --doc <URL> --as user`,从返回的 `<whiteboard token="XXX"/>` 中提取 token                                                                |
+| 文档 URL 或 doc_id,需要新建画板   | `lark-cli docs +update --doc <doc_id> --mode append --markdown '<whiteboard type="blank"></whiteboard>' --as user`,从响应的 `data.board_tokens[0]` 获取 token |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard-cli/SKILL.md` around lines 154 - 155, The XML snippets
in SKILL.md use smart quotes (e.g., `<whiteboard token=”XXX”/>` and `<whiteboard
type=”blank”></whiteboard>`) which will produce invalid XML if copied; update
those occurrences to use straight quotes `"` instead of `”` (replace
`token=”XXX”` with `token="XXX"` and `type=”blank”` with `type="blank"`) so the
examples in the `lark-cli docs +fetch` and `lark-cli docs +update` examples are
valid XML/markdown payloads.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/auth/login_test.go`:
- Around line 907-939: These tests rely on registry metadata and must be
isolated from local config; in each test
(TestAllKnownDomains_ExcludesAuthDomainChildren,
TestCollectScopesForDomains_ExpandsAuthDomainChildren,
TestGetDomainMetadata_ExcludesAuthDomainChildren) set a temporary config
directory via t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) before calling
allKnownDomains, collectScopesForDomains, or getDomainMetadata so they use the
PR fixtures instead of shared machine state; place the t.Setenv call at the
start of each test (or a shared helper) to ensure consistent, isolated config
for these registry-backed assertions.

In `@cmd/auth/login.go`:
- Around line 491-506: The --domain all branch still expands domains directly
from registry.ListFromMetaProjects() and shortcuts.AllShortcuts(), which can
include auth-domain children that allKnownDomains() intentionally filters out;
change the --domain all expansion to use the same filtered set returned by
allKnownDomains() (e.g., iterate the keys of allKnownDomains()) so the CLI's
expansion and validation remain consistent (adjust any variable names like
domainsAll or domainList used in the login handler/validation code to pull from
allKnownDomains()).

In `@internal/registry/registry_test.go`:
- Around line 570-616: These tests rely on registry-backed service descriptions
but don't isolate state; call ensureFreshRegistry(t) at the start of each of the
tests TestGetAuthDomain_Configured, TestGetAuthDomain_NotConfigured,
TestGetAuthDomain_Unknown, TestHasAuthDomain, TestGetAuthChildren, and
TestGetAuthChildren_NoChildren to reset the registry environment
(ensureFreshRegistry(t *testing.T) sets envs, calls resetInit() and Init()), so
add a first line in each test invoking ensureFreshRegistry(t) before any
GetAuthDomain/HasAuthDomain/GetAuthChildren assertions.

In `@shortcuts/whiteboard/whiteboard_query_test.go`:
- Around line 76-80: TestWhiteboardQuery_Validate calls t.Parallel() and then
invokes chdirTemp which calls os.Chdir, causing a process-wide working directory
change that can race with other parallel tests; remove or avoid calling
chdirTemp while the test is parallel (either remove t.Parallel() from
TestWhiteboardQuery_Validate and the other affected test(s) or make
chdirTemp-local by using os.MkdirTemp + os.Chdir only around non-parallelized
setup/teardown or by changing tests to operate with explicit absolute paths),
and ensure any temporary directory chdir is undone before allowing parallel
execution; update the tests referencing chdirTemp to either not run in parallel
or to isolate working-directory changes so tests are deterministic.

In `@shortcuts/whiteboard/whiteboard_query.go`:
- Around line 366-390: Replace os.Stat calls with vfs.Stat in getFinalOutputPath
and checkFileOverwrite: call vfs.Stat(outPath) in getFinalOutputPath (preserving
the existing nil/error handling and info.IsDir() check) and vfs.Stat(path) in
checkFileOverwrite (preserving the overwrite logic and the os.IsNotExist check —
replace os.IsNotExist(err) with vfs.IsNotExist(err) if your vfs package provides
it, otherwise use the vfs error semantics). Ensure you keep existing behavior
(returning joined path when a directory, adjusting extensions when file exists,
returning output.ErrValidation or output.Errorf on errors) and update imports to
use the vfs package.
- Around line 157-163: The code currently calls checkFileOverwrite(outDir,
overwrite) and validate.AtomicWrite against the unvalidated outDir (after
ensurePNGExtension for some paths), so update the flow to compute the final
resolved filename via SafeOutputPath (or the existing preview path rewrite such
as ensurePNGExtension) and then run validate.SafeInputPath (or
validate.SafeOutputPath if available) on that resolved path before invoking
checkFileOverwrite or any file I/O; move the validate.SafeInputPath call to
occur immediately after ensurePNGExtension/SafeOutputPath and before
checkFileOverwrite and validate.AtomicWrite in the functions that use
ensurePNGExtension, checkFileOverwrite, and validate.AtomicWrite (referencing
ensurePNGExtension, checkFileOverwrite, validate.AtomicWrite, and
SafeOutputPath) and apply the same change to the other occurrences noted (around
the blocks covering lines 289-299 and 343-353).
- Around line 92-109: The DryRun implementation for WhiteboardQuery leaks the
raw board token by interpolating runtime.Str("whiteboard-token") directly into
the GET URLs; update DryRun (the DryRun: func(...) *common.DryRunAPI block) to
mask the token before building the URL (e.g., replace
runtime.Str("whiteboard-token") with a masked placeholder or a redacted version
like "<redacted-token>" or show only first/last chars) and use that masked
string in the fmt.Sprintf calls for the GET on the WhiteboardQueryAsImage,
WhiteboardQueryAsCode and WhiteboardQueryAsRaw branches so dry-run output never
contains the live token.

In `@shortcuts/whiteboard/whiteboard_update.go`:
- Around line 82-89: Replace direct os package file access in wbUpdateValidate
and readInput with the repo vfs helpers: use vfs.Stat (or vfs.Lstat if
appropriate) instead of os.Stat when checking the provided source path and use
vfs.ReadFile (or vfs.Open + read) instead of os.ReadFile when loading file
contents; update the checks in wbUpdateValidate (the source existence/isDir
logic) and the file-reading logic in readInput to call the corresponding vfs
functions and propagate/format errors the same way so the validation messages
(e.g., "cannot access source file" and "source must be a file, not a directory")
remain intact.
- Around line 69-70: Replace direct calls to os.Stdin.Stat() with checks against
the CLI's IO stream reader (e.g., ioStreams.In or opts.IOStreams.In):
type‑assert ioStreams.In to *os.File and call f.Stat() when the assertion
succeeds, falling back to treating it as piped/non‑TTY input when it does not;
do this for the occurrences that reference os.Stdin (the stat check around the
current os.Stdin.Stat() usage and the similar check at lines ~97-99) so
validation and input loading use the runner-provided IOStreams instead of
os.Stdin.

In `@skills/lark-doc/references/lark-doc-create.md`:
- Around line 55-67: The documentation currently references data.board_tokens
but the 返回值 section and the provided docs +update implementation expose
board_tokens at the top-level; update the docs to clearly state the exact
response shape and canonical field to check (e.g., top-level board_tokens vs
data.board_tokens), and adjust the follow-up steps to reference the correct
symbol (board_tokens) and the lark-whiteboard +update workflow so readers know
to inspect the top-level board_tokens field returned by the API and use those
tokens with the lark-whiteboard skill.

In `@skills/lark-doc/SKILL.md`:
- Around line 162-167: The SKILL.md describes fetching tokens from
data.board_tokens but the docs_update.go implementation normalizes board_tokens
to the top-level result before printing, so update the SKILL.md flow to
reference the actual top-level board_tokens field (e.g., "from the docs +update
response's board_tokens") instead of data.board_tokens; locate the normalization
in shortcuts/doc/docs_update.go and the SKILL.md section currently mentioning
data.board_tokens and change the text to point readers at the top-level
board_tokens token list so the create → fill board flow works.

In `@skills/lark-whiteboard-cli/references/schema.md`:
- Around line 240-283: Remove the unimplemented Icon section titled "Icon(内置图标)"
(the block that defines { type: 'icon', ... }, the example JSON, and the CLI
example using "npx -y `@larksuite/whiteboard-cli`@^0.2.0 --icons") from
skills/lark-whiteboard-cli/references/schema.md; also remove any examples or
guidance that reference the "type: 'icon'" shape or the non-existent --icons
flag. Then update all docs that reference the unreleased package version spec
"@^0.2.0" (SKILL.md, bar-chart.md, treemap.md, line-chart.md, mermaid.md,
flywheel.md, fishbone.md, layout.md and any others) to use the current published
version "0.1.4" (or remove the versioned CLI example), ensuring no files still
reference "@^0.2.0" or show the --icons flag.

In `@skills/lark-whiteboard-cli/scenes/swimlane.md`:
- Around line 142-144: The connector object currently nested inside the frame's
children (the { "type": "connector", "connector": { "from": "c-s1", "to":
"d-s2", ... } } entry) must be moved out to the top-level WBDocument.nodes
array; remove that connector from the frame's children array and add an
equivalent connector node alongside other top-level nodes so connectors live at
WBDocument.nodes rather than inside the frame's children, preserving its
properties (lineShape, lineColor, lineWidth, endArrow).

In `@skills/lark-whiteboard-cli/scenes/treemap.md`:
- Line 11: The markdown references a non-existent npm package version
'@larksuite/whiteboard-cli@^0.2.0'; update the CLI invocation string to use an
existing published release (for example change to
'@larksuite/whiteboard-cli@0.1.4') or alternatively ensure version 0.2.0 is
published before merging; update the occurrence of
'@larksuite/whiteboard-cli@^0.2.0' in the Treemap instructions accordingly.

In `@skills/lark-whiteboard-cli/SKILL.md`:
- Around line 161-181: The example confirmed upload command incorrectly removes
both --overwrite and --dry-run; change it so only --dry-run is removed after
user approval. Locate the example command in the caution block that currently
shows "npx ... | lark-cli whiteboard +update --whiteboard-token <画板Token> --yes
--as user" and update it to include --overwrite (i.e., keep --overwrite and drop
only --dry-run), so the final confirmed command retains the --overwrite flag.

In `@skills/lark-whiteboard/SKILL.md`:
- Around line 98-103: Update the table row for "流程图" in SKILL.md so it no longer
recommends "Mermaid graph LR" as the default; change the recommended syntax to
the DSL path used by the flowchart scene (per scenes/flowchart.md) and update
the "详细参考指南" link to point to lark-whiteboard-cli/scenes/flowchart.md; locate
the table entry containing the "流程图" label and the "Mermaid graph LR" cell and
replace that cell value with the DSL recommendation and its corresponding
reference.
- Around line 21-22: The documentation incorrectly points to the nested path
data.board_tokens; update SKILL.md so that references to the new whiteboard
token returned by docs +update and shown in docs +fetch point to the top-level
board_tokens field (e.g., mention board_tokens and the <whiteboard token="xxx"/>
tag) instead of data.board_tokens so agents read the freshly created token from
the actual output location; update both occurrences (around the docs +fetch/docs
+update text and the lines noted at 85-86) to reference board_tokens as a
top-level field.

---

Outside diff comments:
In `@skills/lark-whiteboard-cli/references/schema.md`:
- Around line 34-83: The docs describe Dagre features (layoutOptions, rankdir,
nodesep, edgesep, ranksep, edges, isCluster, edge redirect fallback, compound
cluster behavior, and restrictions on children/WBNode/fillColor) but no
implementation exists; either implement the features in the layout engine or
remove/mark the docs as aspirational. To fix: locate the whiteboard layout
renderer and add Dagre support that consumes layoutOptions (handle
rankdir/nodesep/edgesep/ranksep), implement edges parsing at the root Dagre only
and the Edge Redirect Fallback (resolve internal targets to nearest opaque
ancestor), implement isCluster semantics so clusters participate in outer Dagre
topology and allow edges to cross boundaries while cluster sizes are derived
from child bounding boxes, and add schema/runtime validation to enforce children
cannot include connector and warn/make fillColor/border* required for frames
that must persist; alternatively, if not implementing now, update schema.md to
clearly mark Dagre features as planned/not-yet-implemented and remove/clarify
any behavioral guarantees.

---

Minor comments:
In `@shortcuts/whiteboard/whiteboard_query_test.go`:
- Around line 159-203: The test currently calls WhiteboardQuery.DryRun(ctx, rt)
and only checks for non-nil; update the subtest to also assert the returned
dry-run object's HTTP method and path match the table's wantMethod and wantPath.
Locate the call to WhiteboardQuery.DryRun in the loop and after the nil check
extract the method and path from the returned object (e.g., dryRun.Method /
dryRun.Path or the appropriate fields/methods on the DryRun result) and compare
them to tt.wantMethod and tt.wantPath using t.Fatalf or t.Errorf so each case
fails if the route or verb is incorrect.
- Around line 723-754: The tests TestFetchWhiteboardNodes_NetworkError and
TestFetchWhiteboardNodes_APIError only log when runShortcut(...) returns nil, so
unexpected success won't fail CI; update both tests to assert failure when err
== nil (e.g., replace t.Logf("Expected ... but got none") with t.Fatalf or
t.Errorf to fail the test), keeping the call sites runShortcut(t,
WhiteboardQuery, args, factory, stdout) and preserving existing
setup/registration logic.

In `@shortcuts/whiteboard/whiteboard_update_test.go`:
- Around line 532-575: Change the two tests
TestWhiteboardUpdateExecute_RawAPIError and
TestWhiteboardUpdateExecute_PlantUMLAPIError to fail when the shortcut
unexpectedly succeeds: after calling runUpdateShortcut (the variable err),
replace the conditional t.Logf check with an assertion that err is non-nil
(e.g., t.Fatalf or t.Errorf/t.FailNow) so the test fails on unexpected success;
ensure you update both tests that reference runUpdateShortcut and
WhiteboardUpdate to assert/require an error rather than just logging.
- Around line 187-209: The test only checks for commands but not that the legacy
registration is returned; update TestShortcutsIncludesExpectedCommands to also
assert that the legacy shortcut WhiteboardUpdateOld is present in Shortcuts() —
e.g., iterate got and verify at least one entry is the same as
WhiteboardUpdateOld (or has its Handler equal to WhiteboardUpdateOld) and fail
the test if not, so the backward-compatibility registration cannot be removed
unnoticed.

In `@skills/lark-whiteboard-cli/references/connectors.md`:
- Line 75: Fix the Chinese grammar in the connector description containing the
"'curve'(曲线)" phrase: change "优雅的跨层连线" to "优雅地跨层连线" so the adverb correctly
modifies the verb phrase; update the sentence in the connectors.md entry for
"'curve'(曲线)" accordingly.

In `@skills/lark-whiteboard-cli/references/style.md`:
- Around line 216-225: The example JSON shows a complete "type": "frame" object
lacking explicit width/height which can violate sizing rules; update the outer
frame object (the "type": "frame" entry with keys layout, gap, padding,
alignItems, fillColor, borderColor, borderWidth, borderRadius and children) to
either include explicit numeric "width" and "height" properties that follow the
documented sizing rules, or mark this snippet as a partial style fragment (e.g.,
add a clear "partial" or "fragment" indicator in the example text) so consumers
know it’s not a full standalone component.

In `@skills/lark-whiteboard-cli/SKILL.md`:
- Around line 154-155: The XML snippets in SKILL.md use smart quotes (e.g.,
`<whiteboard token=”XXX”/>` and `<whiteboard type=”blank”></whiteboard>`) which
will produce invalid XML if copied; update those occurrences to use straight
quotes `"` instead of `”` (replace `token=”XXX”` with `token="XXX"` and
`type=”blank”` with `type="blank"`) so the examples in the `lark-cli docs
+fetch` and `lark-cli docs +update` examples are valid XML/markdown payloads.

In `@skills/lark-whiteboard/references/lark-whiteboard-update.md`:
- Around line 73-93: Update the CLI version mentions
'@larksuite/whiteboard-cli@^0.1.0' in both code examples to
'@larksuite/whiteboard-cli@^0.2.0' so this file matches the other docs;
specifically replace the version string in the lines that invoke npx --to
openapi (the two occurrences shown in the examples) to ensure consistency with
the other skill documentation.
🪄 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: 86280165-8a77-4508-a1c2-8678ded5ddb3

📥 Commits

Reviewing files that changed from the base of the PR and between 5f3915b and 1b76ed6.

📒 Files selected for processing (40)
  • cmd/auth/login.go
  • cmd/auth/login_interactive.go
  • cmd/auth/login_test.go
  • internal/registry/registry_test.go
  • internal/registry/service_desc.go
  • internal/registry/service_descriptions.json
  • shortcuts/whiteboard/shortcuts.go
  • shortcuts/whiteboard/whiteboard_query.go
  • shortcuts/whiteboard/whiteboard_query_test.go
  • shortcuts/whiteboard/whiteboard_update.go
  • shortcuts/whiteboard/whiteboard_update_test.go
  • skills/lark-doc/SKILL.md
  • skills/lark-doc/references/lark-doc-create.md
  • skills/lark-doc/references/lark-doc-update.md
  • skills/lark-doc/references/lark-doc-whiteboard-update.md
  • skills/lark-whiteboard-cli/SKILL.md
  • skills/lark-whiteboard-cli/references/connectors.md
  • skills/lark-whiteboard-cli/references/content.md
  • skills/lark-whiteboard-cli/references/layout.md
  • skills/lark-whiteboard-cli/references/schema.md
  • skills/lark-whiteboard-cli/references/style.md
  • skills/lark-whiteboard-cli/references/typography.md
  • skills/lark-whiteboard-cli/scenes/architecture.md
  • skills/lark-whiteboard-cli/scenes/bar-chart.md
  • skills/lark-whiteboard-cli/scenes/comparison.md
  • skills/lark-whiteboard-cli/scenes/fishbone.md
  • skills/lark-whiteboard-cli/scenes/flowchart.md
  • skills/lark-whiteboard-cli/scenes/flywheel.md
  • skills/lark-whiteboard-cli/scenes/funnel.md
  • skills/lark-whiteboard-cli/scenes/line-chart.md
  • skills/lark-whiteboard-cli/scenes/mermaid.md
  • skills/lark-whiteboard-cli/scenes/milestone.md
  • skills/lark-whiteboard-cli/scenes/organization.md
  • skills/lark-whiteboard-cli/scenes/pyramid.md
  • skills/lark-whiteboard-cli/scenes/swimlane.md
  • skills/lark-whiteboard-cli/scenes/treemap.md
  • skills/lark-whiteboard/SKILL.md
  • skills/lark-whiteboard/references/lark-whiteboard-query.md
  • skills/lark-whiteboard/references/lark-whiteboard-update.md
  • skills/lark-whiteboard/references/layout.md
💤 Files with no reviewable changes (1)
  • skills/lark-whiteboard/references/layout.md

Comment thread cmd/auth/login_test.go
Comment thread cmd/auth/login.go
Comment thread internal/registry/registry_test.go
Comment thread shortcuts/whiteboard/whiteboard_query_test.go
Comment thread shortcuts/whiteboard/whiteboard_query.go
Comment thread skills/lark-whiteboard-cli/scenes/swimlane.md Outdated
Comment thread skills/lark-whiteboard-cli/scenes/treemap.md
Comment thread skills/lark-whiteboard-cli/SKILL.md
Comment thread skills/lark-whiteboard/SKILL.md
Comment thread skills/lark-whiteboard/SKILL.md Outdated
Comment thread shortcuts/whiteboard/whiteboard_query.go Fixed
Comment thread shortcuts/whiteboard/whiteboard_update.go Fixed
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 10, 2026

Tip:

Greploop — Automatically fix all review issues by running /greploops in Claude Code. It iterates: fix, push, re-review, repeat until 5/5 confidence.

Use the Greptile plugin for Claude Code to query reviews, search comments, and manage custom context directly from your terminal.

Comment thread shortcuts/whiteboard/whiteboard_update.go Outdated
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: 6

♻️ Duplicate comments (3)
skills/lark-whiteboard-cli/SKILL.md (1)

174-179: ⚠️ Potential issue | 🟠 Major

Keep --overwrite in the confirmed overwrite command.

The guidance says to remove only --dry-run after approval, but the example command removes both. That changes the reviewed operation path.

✅ Suggested fix
-npx -y `@larksuite/whiteboard-cli`@^0.2.0 --to openapi -i <输入文件> --format json | lark-cli whiteboard +update --whiteboard-token <画板Token> --source - --yes --as user
+npx -y `@larksuite/whiteboard-cli`@^0.2.0 --to openapi -i <输入文件> --format json | lark-cli whiteboard +update --whiteboard-token <画板Token> --source - --overwrite --yes --as user

Also applies to: 181-181

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard-cli/SKILL.md` around lines 174 - 179, The example
command contradicts the guidance by removing both --dry-run and --overwrite;
update the example(s) so that when a user has explicitly confirmed "同意覆盖" you
only remove --dry-run and retain --overwrite (e.g., keep the --overwrite flag
and remove only --dry-run in the shown CLI invocation), and apply the same
change to the other occurrence referenced around lines 181 where the example
currently removes both flags.
shortcuts/whiteboard/whiteboard_query.go (2)

149-154: ⚠️ Potential issue | 🟠 Major

Validate the resolved output path before overwrite checks and writes.

In all three export paths, filesystem checks run before validating the final resolved path. Move safe-path validation ahead of checkFileOverwrite(...) and use the validated path for both overwrite check and write.

🛡️ Suggested pattern (apply to image/code/raw flows)
- overwrite := runtime.Bool("overwrite")
- if err := checkFileOverwrite(finalPath, overwrite); err != nil {
-   return err
- }
-
- safePath, err := validate.SafeOutputPath(finalPath)
+ safePath, err := validate.SafeOutputPath(finalPath)
  if err != nil {
    return err
  }
+ overwrite := runtime.Bool("overwrite")
+ if err := checkFileOverwrite(safePath, overwrite); err != nil {
+   return err
+ }

As per coding guidelines, **/*.go: Validate paths using validate.SafeInputPath before any file I/O operations.

Also applies to: 285-290, 339-344

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_query.go` around lines 149 - 154, Move the
call to validate.SafeOutputPath before any filesystem checks and use its
returned safePath for subsequent operations; specifically, call
validate.SafeOutputPath(outDir) first, handle its error, then pass the validated
safePath into checkFileOverwrite(safePath, overwrite) and use safePath for the
eventual writes in the export flows (the current block around
validate.SafeOutputPath and checkFileOverwrite and the other occurrences at the
other export branches). Ensure no file I/O or overwrite checks happen on the
unvalidated outDir and apply the same change to the other two export paths
mentioned.

98-99: ⚠️ Potential issue | 🟠 Major

Mask whiteboard token in DryRun URLs.

DryRun still renders the raw token in API paths, which can leak credentials in logs/output.

🔒 Suggested fix
+import "net/url"
...
 DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
 	as := runtime.Str("output_as")
+	token := common.MaskToken(url.PathEscape(runtime.Str("whiteboard-token")))
 	switch as {
 	case WhiteboardQueryAsImage:
 		return common.NewDryRunAPI().
-			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/download_as_image", runtime.Str("whiteboard-token"))).
+			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/download_as_image", token)).
 			Desc("Export preview image of given whiteboard")
 	case WhiteboardQueryAsCode:
 		return common.NewDryRunAPI().
-			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes", runtime.Str("whiteboard-token"))).
+			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes", token)).
 			Desc("Extract Mermaid/Plantuml code from given whiteboard")
 	case WhiteboardQueryAsRaw:
 		return common.NewDryRunAPI().
-			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes", runtime.Str("whiteboard-token"))).
+			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes", token)).
 			Desc("Extract raw nodes structure from given whiteboard")

Also applies to: 102-103, 106-107

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_query.go` around lines 98 - 99, DryRun
currently embeds the raw whiteboard token into the generated URLs via
runtime.Str("whiteboard-token") (seen in the GET
fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/download_as_image",
runtime.Str("whiteboard-token"))) which can leak credentials; change these
occurrences (also at the other similar GET routes) to use a masking helper that
returns a non-sensitive placeholder when in DryRun (e.g. replace
runtime.Str("whiteboard-token") with a call to a new helper like
maskDryRunToken("whiteboard-token") or runtimeMasked("whiteboard-token") that
returns the real token in normal mode but a fixed masked value in DryRun), and
update the other two occurrences noted (the two similar GET routes) to use the
same helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@shortcuts/whiteboard/whiteboard_query.go`:
- Around line 134-135: The ApiPath is currently built by interpolating wbToken
directly (e.g., ApiPath:
fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/download_as_image", wbToken)),
which risks malformed paths; wrap wbToken with url.PathEscape(wbToken) in all
places it’s used for path construction (including the other occurrence around
lines 182-183) and add the net/url import if missing so the execute helpers
receive an escaped path segment.
- Line 109: Validation error messages in whiteboard_query.go incorrectly
reference the flag name "--as"; update the messages to use the actual flag
"--output_as". Find the two locations returning common.NewDryRunAPI().Desc(...)
(the occurrences around the validation logic in the function that checks output
format) and replace "invalid --as flag, must be one of: image | code | raw" with
"invalid --output_as flag, must be one of: image | code | raw" (and the
analogous message at the second occurrence) so both validation errors
consistently reference the correct flag name.

In `@shortcuts/whiteboard/whiteboard_update.go`:
- Around line 149-150: Update the Description fields for the whiteboard update
shortcut so they reflect the current input behavior (supporting --source from
stdin or a file) instead of saying "input is from stdin only"; locate the
Description assignment in the whiteboard_update shortcut (the Description:
"Update an existing whiteboard..." entry) and the other similar Description at
the second location (around the related shortcut registration) and revise the
text to explicitly mention the --source flag and that input may come from stdin
or a file.

In `@skills/lark-whiteboard-cli/SKILL.md`:
- Around line 154-155: Replace the curly/typographic quotes in the XML examples
so they use ASCII double quotes: update the snippet `<whiteboard token=”XXX”/>`
to `<whiteboard token="XXX"/>` and `<whiteboard type=”blank”></whiteboard>` to
`<whiteboard type="blank"></whiteboard>` (these appear in the token extraction
and blank-whiteboard examples in SKILL.md) to ensure copy-paste and command
parsing work correctly.
- Around line 11-24: Remove blank lines inside the blockquotes for the [!NOTE]
and [!IMPORTANT] sections and add explicit fence languages to all fenced code
blocks (e.g., change ``` to ```text) including the code block that begins with
"Step 1: 路由 & 读取知识"; ensure there are no empty lines immediately after the
blockquote markers and that all affected ranges (including the later occurrence
around lines 123-130) use language-tagged fences to resolve MD028 and MD040.

In `@skills/lark-whiteboard/SKILL.md`:
- Around line 66-71: The markdown links in SKILL.md contain stray
spaces/newlines inside the link text causing MD039; locate the wrapped links
referencing `+query --output_as raw`, `+update`, `docs +update`, and `+update
--overwrite` and remove the internal spaces/newlines so each link text is
contiguous (or move the surrounding line breaks/parentheses outside the [link
text](URL) syntax) to produce valid contiguous link tokens and fix the linting
error.

---

Duplicate comments:
In `@shortcuts/whiteboard/whiteboard_query.go`:
- Around line 149-154: Move the call to validate.SafeOutputPath before any
filesystem checks and use its returned safePath for subsequent operations;
specifically, call validate.SafeOutputPath(outDir) first, handle its error, then
pass the validated safePath into checkFileOverwrite(safePath, overwrite) and use
safePath for the eventual writes in the export flows (the current block around
validate.SafeOutputPath and checkFileOverwrite and the other occurrences at the
other export branches). Ensure no file I/O or overwrite checks happen on the
unvalidated outDir and apply the same change to the other two export paths
mentioned.
- Around line 98-99: DryRun currently embeds the raw whiteboard token into the
generated URLs via runtime.Str("whiteboard-token") (seen in the GET
fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/download_as_image",
runtime.Str("whiteboard-token"))) which can leak credentials; change these
occurrences (also at the other similar GET routes) to use a masking helper that
returns a non-sensitive placeholder when in DryRun (e.g. replace
runtime.Str("whiteboard-token") with a call to a new helper like
maskDryRunToken("whiteboard-token") or runtimeMasked("whiteboard-token") that
returns the real token in normal mode but a fixed masked value in DryRun), and
update the other two occurrences noted (the two similar GET routes) to use the
same helper.

In `@skills/lark-whiteboard-cli/SKILL.md`:
- Around line 174-179: The example command contradicts the guidance by removing
both --dry-run and --overwrite; update the example(s) so that when a user has
explicitly confirmed "同意覆盖" you only remove --dry-run and retain --overwrite
(e.g., keep the --overwrite flag and remove only --dry-run in the shown CLI
invocation), and apply the same change to the other occurrence referenced around
lines 181 where the example currently removes both flags.
🪄 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: 864d642d-6180-4e77-bb1b-ab863cb0f2e9

📥 Commits

Reviewing files that changed from the base of the PR and between 1b76ed6 and 1a5cdb4.

📒 Files selected for processing (8)
  • shortcuts/whiteboard/whiteboard_query.go
  • shortcuts/whiteboard/whiteboard_query_test.go
  • shortcuts/whiteboard/whiteboard_update.go
  • shortcuts/whiteboard/whiteboard_update_test.go
  • skills/lark-whiteboard-cli/SKILL.md
  • skills/lark-whiteboard/SKILL.md
  • skills/lark-whiteboard/references/lark-whiteboard-query.md
  • skills/lark-whiteboard/references/lark-whiteboard-update.md
✅ Files skipped from review due to trivial changes (4)
  • skills/lark-whiteboard/references/lark-whiteboard-query.md
  • shortcuts/whiteboard/whiteboard_query_test.go
  • skills/lark-whiteboard/references/lark-whiteboard-update.md
  • shortcuts/whiteboard/whiteboard_update_test.go

Comment thread shortcuts/whiteboard/whiteboard_query.go Outdated
Comment thread shortcuts/whiteboard/whiteboard_query.go Outdated
Comment thread shortcuts/whiteboard/whiteboard_update.go Outdated
Comment thread skills/lark-whiteboard-cli/SKILL.md
Comment thread skills/lark-whiteboard-cli/SKILL.md
Comment thread skills/lark-whiteboard/SKILL.md
@syh-cpdsss syh-cpdsss force-pushed the feat/whiteboard-dev branch from 396d6cc to 1ca716f Compare April 10, 2026 06:52
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

♻️ Duplicate comments (6)
skills/lark-whiteboard-cli/SKILL.md (3)

154-155: ⚠️ Potential issue | 🟡 Minor

XML 示例使用了弯引号,需替换为 ASCII 引号。

当前示例里的 会导致复制后命令/参数解析失败。

🛠️ Suggested patch
-| 文档 URL 或 doc_id,文档中已有画板 | `lark-cli docs +fetch --doc <URL> --as user`,从返回的 `<whiteboard token=”XXX”/>` 中提取 token                                                                |
-| 文档 URL 或 doc_id,需要新建画板   | `lark-cli docs +update --doc <doc_id> --mode append --markdown '<whiteboard type=”blank”></whiteboard>' --as user`,从响应的 `data.board_tokens[0]` 获取 token |
+| 文档 URL 或 doc_id,文档中已有画板 | `lark-cli docs +fetch --doc <URL> --as user`,从返回的 `<whiteboard token="XXX"/>` 中提取 token                                                                |
+| 文档 URL 或 doc_id,需要新建画板   | `lark-cli docs +update --doc <doc_id> --mode append --markdown '<whiteboard type="blank"></whiteboard>' --as user`,从响应的 `data.board_tokens[0]` 获取 token |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard-cli/SKILL.md` around lines 154 - 155, Replace the
curved (Unicode) quotation marks in the XML examples so shell/CLI parsing works:
update the examples that show `<whiteboard token=”XXX”/>` and `<whiteboard
type=”blank”></whiteboard>` to use ASCII double quotes (`"`) instead of `”`;
ensure any other occurrences in the same SKILL.md paragraph or examples
(including the inline `data.board_tokens[0]` reference context) are similarly
normalized to plain ASCII quotes.

174-179: ⚠️ Potential issue | 🟠 Major

确认覆盖后的示例命令丢了 --overwrite

文案写的是“只移除 --dry-run”,但示例把 --overwrite 也去掉了,和流程冲突。

🛠️ Suggested patch
-npx -y `@larksuite/whiteboard-cli`@^0.2.0 --to openapi -i <输入文件> --format json | lark-cli whiteboard +update --whiteboard-token <画板Token> --source - --yes --as user
+npx -y `@larksuite/whiteboard-cli`@^0.2.0 --to openapi -i <输入文件> --format json | lark-cli whiteboard +update --whiteboard-token <画板Token> --source - --overwrite --yes --as user

Also applies to: 181-181

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard-cli/SKILL.md` around lines 174 - 179, The example
command removed --overwrite but the prose says only --dry-run should be removed
after user consents; fix the inconsistency by restoring --overwrite in the CLI
example (or update the prose to state both flags are removed) so they match;
specifically, adjust the example command that pipes to "lark-cli whiteboard
+update" to include the --overwrite flag when showing the post-confirmation
upload, keeping --dry-run omitted as described (or alternatively update the
sentence to say both --overwrite and --dry-run are removed).

14-14: ⚠️ Potential issue | 🟡 Minor

Markdownlint 问题仍存在(MD028/MD040)。

这里仍有 blockquote 空行和未标注语言的 fenced code block,建议一次性修复。

🛠️ Suggested patch
-
 > [!IMPORTANT]
 > 执行 `npm install` 安装新的依赖前,务必征得用户同意!
@@
-```
+```text
 Step 1: 路由 & 读取知识
@@
-```
+```text
 ./diagrams/

Also applies to: 23-53, 123-130

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard-cli/SKILL.md` at line 14, Fix the Markdownlint
MD028/MD040 issues in SKILL.md by removing empty blank lines inside blockquotes
(ensure no lone blank line immediately after any '>' quote marker) and by adding
a language label to all fenced code blocks (e.g., change ``` to ```text)
including their closing fences so they are properly annotated; search for the
problematic blockquote and the fenced code blocks around the examples noted (the
code fences that currently show just ``` and the quoted paragraph blocks) and
update them accordingly.
skills/lark-whiteboard/SKILL.md (2)

21-22: ⚠️ Potential issue | 🟠 Major

board_tokens 字段路径写错,需改为顶层字段。

这里仍写成 data.board_tokens,会误导调用方读取错误路径。请改成顶层 board_tokens(并保持与 <whiteboard token="..."/> 提取说明一致)。

🛠️ Suggested patch
-标签),或从 `docs +update` 新建画板后的 `data.board_tokens` 字段中获取。
+标签),或从 `docs +update` 新建画板后的顶层 `board_tokens` 字段中获取。
...
-2. 从响应的 `data.board_tokens` 中获取新建画板的 token 列表
+2. 从响应的顶层 `board_tokens` 中获取新建画板的 token 列表

Also applies to: 90-90

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard/SKILL.md` around lines 21 - 22, Update the docs to
reference the correct top-level field name for the whiteboard tokens: change any
occurrence of "data.board_tokens" to "board_tokens" so it matches how callers
should read tokens and aligns with the extraction example using the <whiteboard
token="..."/> tag and the docs +fetch / docs +update descriptions.

66-71: ⚠️ Potential issue | 🟡 Minor

修复断开的 Markdown 链接(MD039)。

这几处链接文本被换行拆开了,仍会触发 no-space-in-links 规则。请把 [text](url) 保持连续。

🛠️ Suggested patch
-    3. 如果用户只需要简单修改某个节点的文本内容/颜色,可以使用 [
-       `+query --output_as raw`](references/lark-whiteboard-query.md) shortcut 导出画板原生 OpenAPI 格式,并在此基础上修改。
+    3. 如果用户只需要简单修改某个节点的文本内容/颜色,可以使用 [`+query --output_as raw`](references/lark-whiteboard-query.md) shortcut 导出画板原生 OpenAPI 格式,并在此基础上修改。
...
-3. 使用 [`+update`](references/lark-whiteboard-update.md) shortcut 创建新的画板内容。根据用户需求,你可能会需要使用 [
-   `docs +update`](../lark-doc/references/lark-doc-update.md) 创建新的画板,或使用 [
-   `+update --overwrite`](references/lark-whiteboard-update.md) 在原画板上覆盖式更新。
+3. 使用 [`+update`](references/lark-whiteboard-update.md) shortcut 创建新的画板内容。根据用户需求,你可能会需要使用 [`docs +update`](../lark-doc/references/lark-doc-update.md) 创建新的画板,或使用 [`+update --overwrite`](references/lark-whiteboard-update.md) 在原画板上覆盖式更新。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard/SKILL.md` around lines 66 - 71, Some Markdown links in
SKILL.md are broken by line breaks inside the link text causing
MD039/no-space-in-links; locate the link occurrences around the phrases `+query
--output_as raw`, `+update`, `docs +update`, and `+update --overwrite` and
reconstruct each link so the `[text](url)` is continuous (no newline or spaces
between the closing ] and opening () ), e.g. combine the split link text and URL
back into a single uninterrupted `[...](...)` token for each of those shortcuts.
shortcuts/whiteboard/whiteboard_query_test.go (1)

223-227: ⚠️ Potential issue | 🟠 Major

Don’t combine t.Parallel() with process-wide cwd changes.

Line 223 enables parallel execution, and Line 226 calls chdirTemp, which uses os.Chdir globally. This can make tests flaky/nondeterministic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_query_test.go` around lines 223 - 227, This
test enables t.Parallel() while calling chdirTemp (which uses os.Chdir) making
the test racy; remove the t.Parallel() call from this test so the global cwd
change is not performed concurrently, or alternatively refactor chdirTemp into a
non-global helper (e.g., make chdirTemp return a restore func and use a
package-level sync.Mutex to serialize os.Chdir or avoid os.Chdir entirely by
operating on explicit paths) and update tests to call the new helper; locate
usages of t.Parallel() and chdirTemp in the test to apply the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@shortcuts/whiteboard/whiteboard_query_test.go`:
- Around line 157-201: The test populates wantMethod/wantPath but never asserts
them; update the subtest that calls WhiteboardQuery.DryRun(ctx, rt) to also
validate the returned dry-run object's HTTP method and path against
tt.wantMethod and tt.wantPath (e.g., check dryRun.Method and dryRun.Path or the
equivalent fields on the returned value) and fail the test with a clear message
if they differ; keep the existing nil check and add subsequent t.Fatalf/t.Errorf
assertions referencing the dryRun result and tt.wantMethod/tt.wantPath so
routing regressions are caught.
- Around line 699-703: The test is silently logging when an expected error is
missing; update the two assertions that follow the runShortcut calls (where
runShortcut is invoked with WhiteboardQuery, args, factory, stdout) to fail the
test instead of just logging — replace the t.Logf("Expected network error, but
got none") with a failing assertion such as t.Fatalf or t.Fatalf-equivalent so
the test fails CI when err == nil, and make the same change for the second
occurrence of this pattern later in the file.

---

Duplicate comments:
In `@shortcuts/whiteboard/whiteboard_query_test.go`:
- Around line 223-227: This test enables t.Parallel() while calling chdirTemp
(which uses os.Chdir) making the test racy; remove the t.Parallel() call from
this test so the global cwd change is not performed concurrently, or
alternatively refactor chdirTemp into a non-global helper (e.g., make chdirTemp
return a restore func and use a package-level sync.Mutex to serialize os.Chdir
or avoid os.Chdir entirely by operating on explicit paths) and update tests to
call the new helper; locate usages of t.Parallel() and chdirTemp in the test to
apply the change.

In `@skills/lark-whiteboard-cli/SKILL.md`:
- Around line 154-155: Replace the curved (Unicode) quotation marks in the XML
examples so shell/CLI parsing works: update the examples that show `<whiteboard
token=”XXX”/>` and `<whiteboard type=”blank”></whiteboard>` to use ASCII double
quotes (`"`) instead of `”`; ensure any other occurrences in the same SKILL.md
paragraph or examples (including the inline `data.board_tokens[0]` reference
context) are similarly normalized to plain ASCII quotes.
- Around line 174-179: The example command removed --overwrite but the prose
says only --dry-run should be removed after user consents; fix the inconsistency
by restoring --overwrite in the CLI example (or update the prose to state both
flags are removed) so they match; specifically, adjust the example command that
pipes to "lark-cli whiteboard +update" to include the --overwrite flag when
showing the post-confirmation upload, keeping --dry-run omitted as described (or
alternatively update the sentence to say both --overwrite and --dry-run are
removed).
- Line 14: Fix the Markdownlint MD028/MD040 issues in SKILL.md by removing empty
blank lines inside blockquotes (ensure no lone blank line immediately after any
'>' quote marker) and by adding a language label to all fenced code blocks
(e.g., change ``` to ```text) including their closing fences so they are
properly annotated; search for the problematic blockquote and the fenced code
blocks around the examples noted (the code fences that currently show just ```
and the quoted paragraph blocks) and update them accordingly.

In `@skills/lark-whiteboard/SKILL.md`:
- Around line 21-22: Update the docs to reference the correct top-level field
name for the whiteboard tokens: change any occurrence of "data.board_tokens" to
"board_tokens" so it matches how callers should read tokens and aligns with the
extraction example using the <whiteboard token="..."/> tag and the docs +fetch /
docs +update descriptions.
- Around line 66-71: Some Markdown links in SKILL.md are broken by line breaks
inside the link text causing MD039/no-space-in-links; locate the link
occurrences around the phrases `+query --output_as raw`, `+update`, `docs
+update`, and `+update --overwrite` and reconstruct each link so the
`[text](url)` is continuous (no newline or spaces between the closing ] and
opening () ), e.g. combine the split link text and URL back into a single
uninterrupted `[...](...)` token for each of those shortcuts.
🪄 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: 4d7fbee9-541c-44c1-94a8-430549662482

📥 Commits

Reviewing files that changed from the base of the PR and between 1a5cdb4 and 1ca716f.

📒 Files selected for processing (8)
  • shortcuts/whiteboard/whiteboard_query.go
  • shortcuts/whiteboard/whiteboard_query_test.go
  • shortcuts/whiteboard/whiteboard_update.go
  • shortcuts/whiteboard/whiteboard_update_test.go
  • skills/lark-whiteboard-cli/SKILL.md
  • skills/lark-whiteboard/SKILL.md
  • skills/lark-whiteboard/references/lark-whiteboard-query.md
  • skills/lark-whiteboard/references/lark-whiteboard-update.md
✅ Files skipped from review due to trivial changes (3)
  • skills/lark-whiteboard/references/lark-whiteboard-query.md
  • shortcuts/whiteboard/whiteboard_update_test.go
  • skills/lark-whiteboard/references/lark-whiteboard-update.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • shortcuts/whiteboard/whiteboard_query.go
  • shortcuts/whiteboard/whiteboard_update.go

Comment thread shortcuts/whiteboard/whiteboard_query_test.go
Comment thread shortcuts/whiteboard/whiteboard_query_test.go Outdated
@syh-cpdsss syh-cpdsss added the domain/whiteboard Whiteboard domain label Apr 10, 2026
@github-actions github-actions Bot removed the domain/whiteboard Whiteboard domain label Apr 10, 2026
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: 3

🧹 Nitpick comments (1)
skills/lark-whiteboard-cli/scenes/swimlane.md (1)

29-30: Clarify the “real nodes only” rule to avoid self-contradiction.

Line 29 says “只生成真实节点”, but the same sentence requires keeping transparent stage-cell placeholders for all stages. Please rephrase to distinguish “real business nodes” vs “layout placeholder nodes”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard-cli/scenes/swimlane.md` around lines 29 - 30, Reword
the rule to avoid contradiction by distinguishing “real business nodes” from
“layout placeholder nodes”: replace the current sentence that starts with
“只生成真实节点” with a clear statement that only real business card nodes (业务卡片节点)
should be generated inside stage cells, while transparent stage-cell
placeholders (stage cell / 布局占位节点) must still be retained for alignment; also
mention the implementation detail to keep placeholders transparent via
fillColor: "transparent" and that cards map to stage slots by stage index.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@shortcuts/whiteboard/whiteboard_update.go`:
- Around line 429-448: Fix the missing space in the user-facing advice strings
inside the isRaw branches of the update flow: in the first isRaw block that sets
detail and in the second isRaw concatenation when createResp.Code != 0 (in
whiteboard_update.go), insert a space after the comma in the "skill, using"
phrase so the message reads "...skill, using whiteboard-cli..." to ensure proper
spacing in both error details.
- Around line 220-224: The error message in parseWBcliNodes currently hardcodes
"unmarshal stdin json failed" but the input (rawjson) may come from stdin or a
file; update the output.Errorf call (in parseWBcliNodes) to use a generic
message like "unmarshal input JSON failed" (or similar) that references raw
input rather than "stdin" so the error is accurate regardless of --source.

In `@skills/lark-whiteboard-cli/scenes/swimlane.md`:
- Around line 69-72: The description for the root container (layout:
"horizontal", gap: lanesGap, alignItems: "stretch") is ambiguous about where
titles live; change the wording from “根容器…标题在最上方” to explicitly state
“每条泳道标题位于泳道顶部” and ensure the following per-lane rules (lane label frame using
width: "fill-container", alignItems: "center", justifyContent: "center",
paddingTop / padding: [12, 8, 8, 8]; inner text using width: "fill-container" +
textAlign: "center") are clearly tied to each lane, while the lane body rules
(layout: "vertical", stage cell array, cell height = slotHeight, uniform gap,
empty cells transparent) remain unchanged.

---

Nitpick comments:
In `@skills/lark-whiteboard-cli/scenes/swimlane.md`:
- Around line 29-30: Reword the rule to avoid contradiction by distinguishing
“real business nodes” from “layout placeholder nodes”: replace the current
sentence that starts with “只生成真实节点” with a clear statement that only real
business card nodes (业务卡片节点) should be generated inside stage cells, while
transparent stage-cell placeholders (stage cell / 布局占位节点) must still be retained
for alignment; also mention the implementation detail to keep placeholders
transparent via fillColor: "transparent" and that cards map to stage slots by
stage index.
🪄 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: 2bb9217b-1694-4bdc-8420-a16476f26708

📥 Commits

Reviewing files that changed from the base of the PR and between 1ca716f and 19ed9cc.

📒 Files selected for processing (4)
  • shortcuts/whiteboard/whiteboard_query.go
  • shortcuts/whiteboard/whiteboard_update.go
  • shortcuts/whiteboard/whiteboard_update_test.go
  • skills/lark-whiteboard-cli/scenes/swimlane.md
✅ Files skipped from review due to trivial changes (1)
  • shortcuts/whiteboard/whiteboard_update_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • shortcuts/whiteboard/whiteboard_query.go

Comment thread shortcuts/whiteboard/whiteboard_update.go
Comment thread shortcuts/whiteboard/whiteboard_update.go
Comment thread skills/lark-whiteboard-cli/scenes/swimlane.md
@syh-cpdsss syh-cpdsss force-pushed the feat/whiteboard-dev branch from 19ed9cc to 45f5dda Compare April 10, 2026 08:06
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: 3

♻️ Duplicate comments (4)
shortcuts/whiteboard/whiteboard_query.go (3)

171-175: ⚠️ Potential issue | 🟠 Major

Escape wbToken in the /nodes request path.

Preview export already uses url.PathEscape on Line 136, but Line 174 still sends the raw token. A token containing /, ?, or % can produce the wrong API path for code/raw export.

🛠️ Suggested fix
 	req := &larkcore.ApiReq{
 		HttpMethod: http.MethodGet,
-		ApiPath:    fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes", wbToken),
+		ApiPath:    fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes", url.PathEscape(wbToken)),
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_query.go` around lines 171 - 175, In
fetchWhiteboardNodes the wbToken is interpolated raw into ApiPath which can
break paths when the token contains '/', '?', or '%'—escape wbToken with
url.PathEscape before formatting the path (use the same approach as the preview
export) so ApiPath becomes
fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes",
url.PathEscape(wbToken)), ensuring the request path is always valid.

126-127: ⚠️ Potential issue | 🟡 Minor

Use the real flag name in the fallback error.

Line 127 still tells users to fix --as, but the actual flag is --output_as. That makes the failure message misleading.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_query.go` around lines 126 - 127, The
validation fallback returns a message referencing the wrong flag name; update
the error returned by the default branch (the code that currently calls
output.ErrValidation("--as flag must be one of: image | code | raw")) to
reference the correct flag name `--output_as` instead (e.g., change the string
to "--output_as flag must be one of: image | code | raw") so users see the
accurate flag in the ErrValidation returned from this code path.

95-108: ⚠️ Potential issue | 🟠 Major

Mask the whiteboard token in dry-run output.

Lines 100, 104, and 108 still interpolate the live token into the rendered URL, so --dry-run can leak a usable board token into logs and shell history.

🔒 Suggested fix
 DryRun: func(ctx context.Context, runtime *common.RuntimeContext) *common.DryRunAPI {
 	as := runtime.Str("output_as")
+	token := common.MaskToken(url.PathEscape(runtime.Str("whiteboard-token")))
 	switch as {
 	case WhiteboardQueryAsImage:
 		return common.NewDryRunAPI().
-			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/download_as_image", runtime.Str("whiteboard-token"))).
+			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/download_as_image", token)).
 			Desc("Export preview image of given whiteboard")
 	case WhiteboardQueryAsCode:
 		return common.NewDryRunAPI().
-			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes", runtime.Str("whiteboard-token"))).
+			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes", token)).
 			Desc("Extract Mermaid/Plantuml code from given whiteboard")
 	case WhiteboardQueryAsRaw:
 		return common.NewDryRunAPI().
-			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes", runtime.Str("whiteboard-token"))).
+			GET(fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes", token)).
 			Desc("Extract raw nodes structure from given whiteboard")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_query.go` around lines 95 - 108, DryRun
currently interpolates the real board token (runtime.Str("whiteboard-token"))
into the preview URLs for WhiteboardQueryAsImage, WhiteboardQueryAsCode, and
WhiteboardQueryAsRaw which can leak secrets; change DryRun so it does not
include the live token by computing a maskedToken (e.g. mask the value or use a
static placeholder like "<whiteboard-token>" or a short redacted form) and use
that maskedToken in the fmt.Sprintf calls inside the DryRun function for the
cases WhiteboardQueryAsImage, WhiteboardQueryAsCode, and WhiteboardQueryAsRaw;
implement the mask logic once (helper or inline) and reference maskedToken
instead of runtime.Str("whiteboard-token") in those GET URL formatters.
shortcuts/whiteboard/whiteboard_update.go (1)

150-150: ⚠️ Potential issue | 🟡 Minor

Update the shortcut descriptions to match the new --source behavior.

Both help strings still say the DSL comes from stdin only, but this command now supports stdin or file input and multiple formats.

Also applies to: 165-165

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/whiteboard/whiteboard_update.go` at line 150, Update the
Description strings in whiteboard_update.go to reflect the new --source
behavior: change the current "DSL input from stdin" wording to state that the
whiteboard DSL can be provided via stdin or a file using the --source flag and
that multiple input formats are supported; update both Description occurrences
(the Description field used when defining the whiteboard update command) so help
output mentions --source and accepts stdin or file input and multiple formats.
🧹 Nitpick comments (1)
skills/lark-whiteboard-cli/scenes/swimlane.md (1)

32-32: Optional: Minor Chinese grammar refinement.

LanguageTool suggests using "充足地阅读空间" (adverb form) instead of "充足的阅读空间". While the current phrasing is understandable, the suggested form is grammatically more precise in Chinese.

📝 Suggested refinement
-连线包含文字(`label`),主轴间距必须 `gap >= 64`,以提供充足的阅读空间。
+连线包含文字(`label`),主轴间距必须 `gap >= 64`,以提供充足地阅读空间。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@skills/lark-whiteboard-cli/scenes/swimlane.md` at line 32, Replace the phrase
"充足的阅读空间" in the swimlane description sentence that defines connector spacing
(the sentence starting with "只要存在 connector 连线... 如果连线包含文字(`label`)") with the
grammatically refined adverbial form "充足地阅读空间" to match LanguageTool's
suggestion; update that single sentence to read "...主轴间距必须 `gap >=
64`,以提供充足地阅读空间。"
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@shortcuts/whiteboard/whiteboard_update.go`:
- Around line 107-114: The dry-run request body for FormatPlantUML/FormatMermaid
is missing ParseMode so it doesn't match the real update sent by
updateWhiteboardByCode; modify the plantumlCreateReq constructed in the
FormatPlantUML/FormatMermaid branch (where formatCodeMap[format] is used) to
include ParseMode: 1 (the same field name used by updateWhiteboardByCode) so the
desc.POST.Body(reqBody) for the dry-run mirrors the actual update payload.
- Around line 220-223: The JSON-unmarshal error in parseWBcliNodes treats
malformed user `--source` input as an internal error; change the returned error
exit code from output.ExitInternal to a validation/usage code (e.g.,
output.ExitData) in the json.Unmarshal error branch so the CLI classifies it as
user input validation failure (keep the same error message and returned values
otherwise).

In `@skills/lark-whiteboard-cli/scenes/swimlane.md`:
- Line 61: Clarify the ambiguous phrase "标题在最上方" in the root container
description: either state explicitly that it refers to an optional overall
diagram title (and add a short example or note) or remove/replace the phrase to
reflect actual structure (lane labels on the left). Update the text near the
root container settings (layout: "vertical", gap: lanesGap, alignItems:
"stretch") to reference "overall diagram title (optional, top)" if meant, or
change to "lane labels on the left" to match the examples and the "左侧 lane
label" wording.

---

Duplicate comments:
In `@shortcuts/whiteboard/whiteboard_query.go`:
- Around line 171-175: In fetchWhiteboardNodes the wbToken is interpolated raw
into ApiPath which can break paths when the token contains '/', '?', or
'%'—escape wbToken with url.PathEscape before formatting the path (use the same
approach as the preview export) so ApiPath becomes
fmt.Sprintf("/open-apis/board/v1/whiteboards/%s/nodes",
url.PathEscape(wbToken)), ensuring the request path is always valid.
- Around line 126-127: The validation fallback returns a message referencing the
wrong flag name; update the error returned by the default branch (the code that
currently calls output.ErrValidation("--as flag must be one of: image | code |
raw")) to reference the correct flag name `--output_as` instead (e.g., change
the string to "--output_as flag must be one of: image | code | raw") so users
see the accurate flag in the ErrValidation returned from this code path.
- Around line 95-108: DryRun currently interpolates the real board token
(runtime.Str("whiteboard-token")) into the preview URLs for
WhiteboardQueryAsImage, WhiteboardQueryAsCode, and WhiteboardQueryAsRaw which
can leak secrets; change DryRun so it does not include the live token by
computing a maskedToken (e.g. mask the value or use a static placeholder like
"<whiteboard-token>" or a short redacted form) and use that maskedToken in the
fmt.Sprintf calls inside the DryRun function for the cases
WhiteboardQueryAsImage, WhiteboardQueryAsCode, and WhiteboardQueryAsRaw;
implement the mask logic once (helper or inline) and reference maskedToken
instead of runtime.Str("whiteboard-token") in those GET URL formatters.

In `@shortcuts/whiteboard/whiteboard_update.go`:
- Line 150: Update the Description strings in whiteboard_update.go to reflect
the new --source behavior: change the current "DSL input from stdin" wording to
state that the whiteboard DSL can be provided via stdin or a file using the
--source flag and that multiple input formats are supported; update both
Description occurrences (the Description field used when defining the whiteboard
update command) so help output mentions --source and accepts stdin or file input
and multiple formats.

---

Nitpick comments:
In `@skills/lark-whiteboard-cli/scenes/swimlane.md`:
- Line 32: Replace the phrase "充足的阅读空间" in the swimlane description sentence
that defines connector spacing (the sentence starting with "只要存在 connector 连线...
如果连线包含文字(`label`)") with the grammatically refined adverbial form "充足地阅读空间" to
match LanguageTool's suggestion; update that single sentence to read "...主轴间距必须
`gap >= 64`,以提供充足地阅读空间。"
🪄 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: d0095716-454b-4d6b-ac91-e6f3387b710b

📥 Commits

Reviewing files that changed from the base of the PR and between 19ed9cc and 45f5dda.

📒 Files selected for processing (5)
  • shortcuts/whiteboard/whiteboard_query.go
  • shortcuts/whiteboard/whiteboard_update.go
  • shortcuts/whiteboard/whiteboard_update_test.go
  • skills/lark-doc/references/lark-doc-create.md
  • skills/lark-whiteboard-cli/scenes/swimlane.md
✅ Files skipped from review due to trivial changes (2)
  • skills/lark-doc/references/lark-doc-create.md
  • shortcuts/whiteboard/whiteboard_update_test.go

Comment thread shortcuts/whiteboard/whiteboard_update.go
Comment thread shortcuts/whiteboard/whiteboard_update.go Outdated
Comment thread skills/lark-whiteboard-cli/scenes/swimlane.md
@syh-cpdsss syh-cpdsss force-pushed the feat/whiteboard-dev branch 2 times, most recently from 4ecafb5 to 53b6c1d Compare April 10, 2026 09:48
…/PlantUML support

Change-Id: I719935bb8fee337908ec99d59f1dfaae0df74874
@syh-cpdsss syh-cpdsss force-pushed the feat/whiteboard-dev branch from 53b6c1d to 08cf71b Compare April 10, 2026 10:13
@syh-cpdsss syh-cpdsss merged commit 46468a9 into main Apr 10, 2026
16 checks passed
@syh-cpdsss syh-cpdsss deleted the feat/whiteboard-dev branch April 10, 2026 11:40
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.

3 participants