Skip to content

feat(lingo): add Feishu dictionary shortcuts and skill#855

Open
emac wants to merge 3 commits into
larksuite:mainfrom
emac:feat/lingo
Open

feat(lingo): add Feishu dictionary shortcuts and skill#855
emac wants to merge 3 commits into
larksuite:mainfrom
emac:feat/lingo

Conversation

@emac
Copy link
Copy Markdown

@emac emac commented May 12, 2026

Introduces a new lingo service covering the six Feishu Lingo / 百科 dictionary entry endpoints as shortcuts, plus the accompanying lark-lingo skill with per-verb reference docs.

Shortcuts (shortcuts/lingo/):
+search POST /lingo/v1/entities/search read
+match POST /lingo/v1/entities/match read
+get GET /lingo/v1/entities/:id read
+create POST /lingo/v1/entities write (bot-only)
+update PUT /lingo/v1/entities/:id write (bot-only, full overwrite)
+delete DELETE /lingo/v1/entities/:id high-risk-write (bot-only)

Each shortcut has validate / dry-run / execute hooks and unit tests covering flag validation, dry-run payload, successful execute, and API-error paths. Dry-run e2e tests added under tests/cli_e2e/lingo/.

The skill (skills/lark-lingo/) follows the lark-markdown pattern: concise SKILL.md index + one references/lark-lingo-.md per shortcut. References capture the real-world gotchas we hit during integration:

  • write endpoints reject user_access_token (99991668); bot-only
  • bot scope is configured in the developer console, not via auth login --scope (which only affects user scope)
  • +update is PUT full-body overwrite — read current via +get and merge before writing
  • +create entries enter the review queue unless the app has baike:entity:exempt_review (self-built apps only)

Also:

  • internal/registry/service_descriptions.json: add lingo entry
  • shortcuts/register.go: register lingo.Shortcuts()
  • README.md / README.zh.md: new Lingo row in both feature and skill tables

Summary

Changes

  • Change 1
  • Change 2

Test Plan

  • Unit tests pass
  • Manual local verification confirms the lark xxx command works as expected

Related Issues

  • None

Summary by CodeRabbit

  • New Features

    • Added Lingo (enterprise dictionary) with search, match, get, create, update, and delete commands; supports aliases, description/rich-text, repo scoping, related metadata, confirmations, and dry-run previews.
  • Documentation

    • Updated README (EN/ZH) and added full lark-lingo skill docs and per-command reference pages covering usage, permissions, and safety workflows.
  • Tests

    • Added unit tests and dry-run end-to-end tests covering validation, dry-run output, and execution paths.

Review Change Stack

Introduces a new `lingo` service covering the six Feishu Lingo /
百科 dictionary entry endpoints as shortcuts, plus the accompanying
lark-lingo skill with per-verb reference docs.

Shortcuts (shortcuts/lingo/):
  +search  POST /lingo/v1/entities/search   read
  +match   POST /lingo/v1/entities/match    read
  +get     GET  /lingo/v1/entities/:id      read
  +create  POST /lingo/v1/entities          write (bot-only)
  +update  PUT  /lingo/v1/entities/:id      write (bot-only, full overwrite)
  +delete  DELETE /lingo/v1/entities/:id    high-risk-write (bot-only)

Each shortcut has validate / dry-run / execute hooks and unit tests
covering flag validation, dry-run payload, successful execute, and
API-error paths. Dry-run e2e tests added under tests/cli_e2e/lingo/.

The skill (skills/lark-lingo/) follows the lark-markdown pattern:
concise SKILL.md index + one references/lark-lingo-<verb>.md per
shortcut. References capture the real-world gotchas we hit during
integration:

  * write endpoints reject user_access_token (99991668); bot-only
  * bot scope is configured in the developer console, not via
    `auth login --scope` (which only affects user scope)
  * +update is PUT full-body overwrite — read current via +get
    and merge before writing
  * +create entries enter the review queue unless the app has
    baike:entity:exempt_review (self-built apps only)

Also:
  * internal/registry/service_descriptions.json: add lingo entry
  * shortcuts/register.go: register lingo.Shortcuts()
  * README.md / README.zh.md: new Lingo row in both feature and
    skill tables
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

📝 Walkthrough

Walkthrough

Adds a Lingo service: registry/docs updates, six CLI shortcuts (search/match/get/create/update/delete) with validation and DryRun/Execute, unit and E2E dry-run tests, skill/reference documentation, and registers shortcuts for CLI mounting.

Changes

Lingo Dictionary Service & Shortcuts

Layer / File(s) Summary
Service registry and README updates
internal/registry/service_descriptions.json, README.md, README.zh.md, shortcuts/lingo/shortcuts.go
Adds Lingo service descriptor and English/Chinese README rows; introduces module Shortcuts() function.
Test infrastructure and helpers
shortcuts/lingo/helpers_test.go
Adds isolated lingoTestConfig(), runLingoShortcut() runner, and decodeEnvelope() JSON helper for tests.
Read Shortcuts: search, match, get
shortcuts/lingo/lingo_entity_search.go, shortcuts/lingo/lingo_entity_match.go, shortcuts/lingo/lingo_entity_get.go, and their tests
Implements +search, +match, and +get with input validation, DryRun/Execute flows, helpers, and unit tests (validation, dry-run, execution).
Write Shortcuts: create, update, delete
shortcuts/lingo/lingo_entity_create.go, shortcuts/lingo/lingo_entity_update.go, shortcuts/lingo/lingo_entity_delete.go, and their tests
Implements +create (POST), +update (PUT full overwrite), and +delete (DELETE) with validation (including related_meta), DryRun/Execute, and unit tests.
Shortcut registration and wiring
shortcuts/register.go
Imports and registers Lingo shortcuts in global aggregation for CLI mounting.
Skill manifest and reference docs
skills/lark-lingo/SKILL.md, skills/lark-lingo/references/*
Adds SKILL.md and per-command references documenting intents, usage, token/scope rules, review semantics, and examples.
End-to-end dry-run CLI tests
tests/cli_e2e/lingo/lingo_dryrun_test.go
Adds dry-run E2E tests for each shortcut asserting HTTP method, resolved path, and request body content without real API calls.

Sequence Diagram(s)

N/A — flow diagrams included in the hidden review stack artifact.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

domain/ccm, size/L

Suggested reviewers

  • kongenpei
  • fangshuyu-768
  • liangshuo-1

Poem

🐰 I hop through docs and tests so bright,
Six shortcuts bloom in morning light,
Search, match, get, create, update, delete—
Flags and dry-runs make the CLI neat,
A rabbit cheers: Lingo's in sight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main addition: a new Feishu dictionary (lingo) service with shortcuts and skill documentation.
Description check ✅ Passed The description provides a detailed summary of the changes, lists the six shortcuts with their endpoints, explains the skill structure and documentation, and notes key integration insights. However, it duplicates the template sections (Summary/Changes/Test Plan/Related Issues) without completing them per the template structure.
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 unit tests (beta)
  • Create PR with unit tests

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

❤️ Share

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

@github-actions github-actions Bot added the size/XL Architecture-level or global-impact change label May 12, 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: 5

🤖 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/lingo/lingo_entity_delete.go`:
- Around line 24-26: The shortcut currently lists both "user" and "bot" in the
AuthTypes slice, but this delete operation must be bot-only; locate the shortcut
definition in lingo_entity_delete.go (the struct literal that sets Scopes,
AuthTypes, HasFormat) and remove "user" from the AuthTypes field so it becomes
AuthTypes: []string{"bot"}. Leave Scopes and HasFormat unchanged and run
tests/linters to ensure no other callsites expect user auth for this delete
shortcut.
- Around line 41-42: The code interpolates entityID directly into path (path :=
fmt.Sprintf("/open-apis/lingo/v1/entities/%s", entityID)) and calls
runtime.DoAPIJSON which can break on reserved characters; URL-escape the path
segment before building the path (use a path-escaping function like
url.PathEscape on entityID) and then pass the escaped value into the fmt.Sprintf
so runtime.DoAPIJSON receives a safe path.

In `@shortcuts/lingo/lingo_entity_update.go`:
- Around line 69-70: The code currently injects raw runtime.Str("entity-id")
into the URL path; instead URL-encode that segment before building the path to
avoid malformed endpoints. Replace the direct interpolation in the path
construction for lingo_entity_update (where path :=
fmt.Sprintf("/open-apis/lingo/v1/entities/%s", runtime.Str("entity-id"))) by
first encoding the entity-id with a path-encoding function (e.g.,
net/url.PathEscape or your runtime-provided path-escape utility) and then use
the escaped value in fmt.Sprintf so the PUT request via runtime.DoAPIJSON uses a
safe, encoded path.
- Around line 25-27: The AuthTypes field in the Lingo entity update shortcut
currently includes "user", but this endpoint must be bot-only; edit the shortcut
definition (the struct/variable that sets Scopes, AuthTypes, HasFormat in
lingo_entity_update.go) to remove "user" from AuthTypes so it only contains
"bot" (i.e., AuthTypes: []string{"bot"}), leaving Scopes and HasFormat
unchanged; run tests/linters to ensure no other call sites assume "user" auth
for this shortcut.

In `@skills/lark-lingo/references/lark-lingo-get.md`:
- Around line 22-27: Update the parameter table to clarify that lookup requires
either `--entity-id` OR the pair `--provider` + `--outer-id` instead of marking
`--entity-id` as strictly required; change the `--entity-id` "必填" cell to
indicate conditional/one-of requirement (e.g., "必填(`--entity-id` 或
`--provider`+`--outer-id`)") and adjust the `--provider` and `--outer-id` "必填"
cells to note they must be provided together (e.g., "与 `--outer-id`
同时使用,作为替代查找模式"); also update the `--provider`/`--outer-id` descriptions to
explicitly state they form an alternate lookup mode when used together.
🪄 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: 0fce0e7e-1faf-43ce-bdbf-83b13b20c6d4

📥 Commits

Reviewing files that changed from the base of the PR and between ce0b68d and bbe0547.

📒 Files selected for processing (26)
  • README.md
  • README.zh.md
  • internal/registry/service_descriptions.json
  • shortcuts/lingo/helpers_test.go
  • shortcuts/lingo/lingo_entity_create.go
  • shortcuts/lingo/lingo_entity_create_test.go
  • shortcuts/lingo/lingo_entity_delete.go
  • shortcuts/lingo/lingo_entity_delete_test.go
  • shortcuts/lingo/lingo_entity_get.go
  • shortcuts/lingo/lingo_entity_get_test.go
  • shortcuts/lingo/lingo_entity_match.go
  • shortcuts/lingo/lingo_entity_match_test.go
  • shortcuts/lingo/lingo_entity_search.go
  • shortcuts/lingo/lingo_entity_search_test.go
  • shortcuts/lingo/lingo_entity_update.go
  • shortcuts/lingo/lingo_entity_update_test.go
  • shortcuts/lingo/shortcuts.go
  • shortcuts/register.go
  • skills/lark-lingo/SKILL.md
  • skills/lark-lingo/references/lark-lingo-create.md
  • skills/lark-lingo/references/lark-lingo-delete.md
  • skills/lark-lingo/references/lark-lingo-get.md
  • skills/lark-lingo/references/lark-lingo-match.md
  • skills/lark-lingo/references/lark-lingo-search.md
  • skills/lark-lingo/references/lark-lingo-update.md
  • tests/cli_e2e/lingo/lingo_dryrun_test.go

Comment on lines +24 to +26
Scopes: []string{"baike:entity"},
AuthTypes: []string{"user", "bot"},
HasFormat: true,
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 | 🟠 Major | ⚡ Quick win

Enforce bot-only auth on this write shortcut.

This high-risk write command currently allows user auth type, but delete is documented/expected as bot-only. Allowing user here permits invalid executions that should be blocked earlier by CLI auth gating.

🤖 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/lingo/lingo_entity_delete.go` around lines 24 - 26, The shortcut
currently lists both "user" and "bot" in the AuthTypes slice, but this delete
operation must be bot-only; locate the shortcut definition in
lingo_entity_delete.go (the struct literal that sets Scopes, AuthTypes,
HasFormat) and remove "user" from the AuthTypes field so it becomes AuthTypes:
[]string{"bot"}. Leave Scopes and HasFormat unchanged and run tests/linters to
ensure no other callsites expect user auth for this delete shortcut.

Comment on lines +41 to +42
path := fmt.Sprintf("/open-apis/lingo/v1/entities/%s", entityID)
_, err := runtime.DoAPIJSON("DELETE", path, larkcore.QueryParams{}, nil)
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 | 🟠 Major | ⚡ Quick win

Avoid sending raw entity-id directly in the URL path segment.

Interpolating unescaped user input into the endpoint path can break routing for IDs containing reserved characters and may hit unintended paths. Encode the path segment before building the final URL.

🤖 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/lingo/lingo_entity_delete.go` around lines 41 - 42, The code
interpolates entityID directly into path (path :=
fmt.Sprintf("/open-apis/lingo/v1/entities/%s", entityID)) and calls
runtime.DoAPIJSON which can break on reserved characters; URL-escape the path
segment before building the path (use a path-escaping function like
url.PathEscape on entityID) and then pass the escaped value into the fmt.Sprintf
so runtime.DoAPIJSON receives a safe path.

Comment thread shortcuts/lingo/lingo_entity_update.go
Comment on lines +69 to +70
path := fmt.Sprintf("/open-apis/lingo/v1/entities/%s", runtime.Str("entity-id"))
data, err := runtime.DoAPIJSON("PUT", path, larkcore.QueryParams{}, body)
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 | 🟠 Major | ⚡ Quick win

Do not interpolate raw entity-id into the API path.

Using raw user input in the path segment can produce malformed or unintended endpoint paths when IDs include reserved URL characters. Encode the segment before constructing the request path.

🤖 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/lingo/lingo_entity_update.go` around lines 69 - 70, The code
currently injects raw runtime.Str("entity-id") into the URL path; instead
URL-encode that segment before building the path to avoid malformed endpoints.
Replace the direct interpolation in the path construction for
lingo_entity_update (where path :=
fmt.Sprintf("/open-apis/lingo/v1/entities/%s", runtime.Str("entity-id"))) by
first encoding the entity-id with a path-encoding function (e.g.,
net/url.PathEscape or your runtime-provided path-escape utility) and then use
the escaped value in fmt.Sprintf so the PUT request via runtime.DoAPIJSON uses a
safe, encoded path.

Comment on lines +22 to +27
| 参数 | 必填 | 说明 |
|------|------|------|
| `--entity-id` | 是 | 词条 ID(通常来自 `+match` / `+search` 返回的 `entity_id`) |
| `--provider` | 否 | 外部系统名;配合 `--outer-id` 使用,用于按外部系统 ID 反查已绑定的词条 |
| `--outer-id` | 否 | 外部系统 ID;必须与 `--provider` 同时使用 |

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

Parameter table contradicts the documented alternate lookup flow.

--entity-id is marked “required”, but the examples/constraints also document lookup via --provider + --outer-id. Please change this to a conditional requirement (one of these lookup modes must be provided) to avoid misleading users.

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

In `@skills/lark-lingo/references/lark-lingo-get.md` around lines 22 - 27, Update
the parameter table to clarify that lookup requires either `--entity-id` OR the
pair `--provider` + `--outer-id` instead of marking `--entity-id` as strictly
required; change the `--entity-id` "必填" cell to indicate conditional/one-of
requirement (e.g., "必填(`--entity-id` 或 `--provider`+`--outer-id`)") and adjust
the `--provider` and `--outer-id` "必填" cells to note they must be provided
together (e.g., "与 `--outer-id` 同时使用,作为替代查找模式"); also update the
`--provider`/`--outer-id` descriptions to explicitly state they form an
alternate lookup mode when used together.

Feishu Lingo entries carry both a plain-text `description` and an
HTML `rich_text` field. The existing shortcuts only surfaced the
plain-text path, so users could not control formatting (bold main
key, multiple paragraphs, inline spans) when creating / updating
entries from the CLI.

Adds a new `--rich-text` flag on +create and +update that sends the
provided HTML directly as the entity's `rich_text` field. Mutually
exclusive with `--description` — passing both returns a validation
error so the request shape is unambiguous.

Common HTML (observed on entries authored via the Feishu Web UI):
  <p><b>main key zh_name</b><span>description…</span></p>

Feishu automatically back-fills the other field: sending only
rich_text populates description (stripped text); sending only
description populates rich_text (with the main key auto-bolded).

Both flags support @file / - (stdin) input to accommodate long
HTML bodies.

Updates skills/lark-lingo/SKILL.md and the +create / +update
reference docs to describe the HTML format, the mutual-exclusion
rule, and the PUT-overwrite interaction (supplying only one of the
two fields clears the other — fetch with +get and merge first).
Feishu Lingo entries carry a `related_meta` object alongside the
plain-text/rich-text body. It links the entry to other concepts —
classifications (taxonomy), abbreviations (cross-linked entries),
related users, chats, docs, links, oncalls, and uploaded images.

The existing +create / +update shortcuts surfaced none of this, so
agents could only manage trivial entries — the moment they needed
to attach a classification or cross-link an abbreviation they were
forced to drop down to `lark-cli api`.

Adds `--related-meta` (string, accepts @file / stdin) on both
shortcuts. The value is validated as a JSON object up front so
malformed payloads fail fast with a clear message instead of
producing an opaque server-side error. The object is passed through
verbatim as the `related_meta` field; we deliberately do not split
each sub-array into its own flag because four of the eight
(`docs`, `links`, plus `users` / `chats` when carrying a title)
need two-field structs that don't compress into a single string.

`+update` is PUT-overwrite: omitting `--related-meta` clears the
existing value, matching the existing `--description` / `--aliases`
semantics. Reference docs spell this out and recommend +get-first-
then-merge for any incremental change.

Supported sub-fields (full schema documented in references/):

  classifications: [{id, father_id?}]   # 二级分类,每个一级下唯一
  abbreviations:   [{id}]               # 关联词条
  users:           [{id, title?}]       # open_id 联系人
  chats:           [{id, title?}]       # 公开群
  docs:            [{title?, url}]      # 云文档
  links:           [{title?, url}]      # 外部链接
  oncalls:         [{id, title?}]       # 值班号
  images:          [{token}]            # 已上传图片,最多 10
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: 1

♻️ Duplicate comments (2)
shortcuts/lingo/lingo_entity_update.go (2)

92-93: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Escape entity-id before building the PUT path.

Line 92 injects raw user input into the URL path segment. Encode the segment first to avoid malformed endpoint paths.

Suggested fix
 import (
 	"context"
 	"fmt"
 	"io"
+	"net/url"
 	"strings"
@@
-		path := fmt.Sprintf("/open-apis/lingo/v1/entities/%s", runtime.Str("entity-id"))
+		escapedID := url.PathEscape(runtime.Str("entity-id"))
+		path := fmt.Sprintf("/open-apis/lingo/v1/entities/%s", escapedID)
 		data, err := runtime.DoAPIJSON("PUT", path, larkcore.QueryParams{}, body)
🤖 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/lingo/lingo_entity_update.go` around lines 92 - 93, The path
construction injects raw user input via runtime.Str("entity-id") into path which
may produce malformed or unsafe URLs; before formatting the path in
lingo_entity_update.go, URL-escape the entity id (e.g., using url.PathEscape or
the project's equivalent) and use that escaped value when building the path
variable (the code creating path :=
fmt.Sprintf("/open-apis/lingo/v1/entities/%s", ...)). Ensure the escape is
applied to the same runtime.Str("entity-id") result (or assigned to a local
variable like entityIDEscaped) so the subsequent runtime.DoAPIJSON("PUT", path,
...) call uses the safe, encoded segment.

31-33: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Enforce bot-only auth for +update.

Line 32 still includes user; this write shortcut should remain bot-only to match endpoint constraints and prevent avoidable runtime failures.

Suggested fix
-	AuthTypes:   []string{"user", "bot"},
+	AuthTypes:   []string{"bot"},
🤖 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/lingo/lingo_entity_update.go` around lines 31 - 33, The shortcut
definition currently lists both "user" and "bot" in the AuthTypes slice for the
+update write shortcut; change AuthTypes to only include "bot" (e.g., AuthTypes:
[]string{"bot"}) so the +update shortcut is enforced as bot-only, leaving Scopes
and HasFormat unchanged and updating any similar AuthTypes declarations for the
same +update shortcut if present.
🤖 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/lingo/lingo_entity_create.go`:
- Around line 32-33: The endpoint registration currently allows both "user" and
"bot" auth but must be bot-only; update the AuthTypes slice in the shortcut
registration (where Scopes: []string{"baike:entity"} and AuthTypes is defined)
to only include "bot" (i.e., change AuthTypes: []string{"user", "bot"} to
AuthTypes: []string{"bot"}) so CLI preflight and routing will block
user-authenticated requests to the +create write endpoint.

---

Duplicate comments:
In `@shortcuts/lingo/lingo_entity_update.go`:
- Around line 92-93: The path construction injects raw user input via
runtime.Str("entity-id") into path which may produce malformed or unsafe URLs;
before formatting the path in lingo_entity_update.go, URL-escape the entity id
(e.g., using url.PathEscape or the project's equivalent) and use that escaped
value when building the path variable (the code creating path :=
fmt.Sprintf("/open-apis/lingo/v1/entities/%s", ...)). Ensure the escape is
applied to the same runtime.Str("entity-id") result (or assigned to a local
variable like entityIDEscaped) so the subsequent runtime.DoAPIJSON("PUT", path,
...) call uses the safe, encoded segment.
- Around line 31-33: The shortcut definition currently lists both "user" and
"bot" in the AuthTypes slice for the +update write shortcut; change AuthTypes to
only include "bot" (e.g., AuthTypes: []string{"bot"}) so the +update shortcut is
enforced as bot-only, leaving Scopes and HasFormat unchanged and updating any
similar AuthTypes declarations for the same +update shortcut if present.
🪄 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: fce7150f-666e-40df-9195-66c00d57cc8e

📥 Commits

Reviewing files that changed from the base of the PR and between 4c2ed51 and 3718816.

📒 Files selected for processing (7)
  • shortcuts/lingo/lingo_entity_create.go
  • shortcuts/lingo/lingo_entity_create_test.go
  • shortcuts/lingo/lingo_entity_update.go
  • shortcuts/lingo/lingo_entity_update_test.go
  • skills/lark-lingo/SKILL.md
  • skills/lark-lingo/references/lark-lingo-create.md
  • skills/lark-lingo/references/lark-lingo-update.md
✅ Files skipped from review due to trivial changes (2)
  • skills/lark-lingo/references/lark-lingo-create.md
  • skills/lark-lingo/SKILL.md

Comment on lines +32 to +33
Scopes: []string{"baike:entity"},
AuthTypes: []string{"user", "bot"},
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 | 🟠 Major | ⚡ Quick win

Restrict +create to bot auth only.

Line 33 currently allows user, but this write endpoint is bot-only in the behavior documented for this feature and should be blocked at CLI preflight.

Suggested fix
-	AuthTypes:   []string{"user", "bot"},
+	AuthTypes:   []string{"bot"},
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Scopes: []string{"baike:entity"},
AuthTypes: []string{"user", "bot"},
Scopes: []string{"baike:entity"},
AuthTypes: []string{"bot"},
🤖 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/lingo/lingo_entity_create.go` around lines 32 - 33, The endpoint
registration currently allows both "user" and "bot" auth but must be bot-only;
update the AuthTypes slice in the shortcut registration (where Scopes:
[]string{"baike:entity"} and AuthTypes is defined) to only include "bot" (i.e.,
change AuthTypes: []string{"user", "bot"} to AuthTypes: []string{"bot"}) so CLI
preflight and routing will block user-authenticated requests to the +create
write endpoint.

@github-actions
Copy link
Copy Markdown

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 Skill update

npx skills add emac/lark-cli#feat/lingo -y -g

@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

❌ Patch coverage is 57.01754% with 147 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.79%. Comparing base (c0fbe54) to head (3718816).
⚠️ Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
shortcuts/lingo/lingo_entity_search.go 38.70% 32 Missing and 6 partials ⚠️
shortcuts/lingo/lingo_entity_get.go 43.33% 29 Missing and 5 partials ⚠️
shortcuts/lingo/lingo_entity_update.go 61.76% 17 Missing and 9 partials ⚠️
shortcuts/lingo/lingo_entity_create.go 76.40% 14 Missing and 7 partials ⚠️
shortcuts/lingo/lingo_entity_match.go 53.12% 14 Missing and 1 partial ⚠️
shortcuts/lingo/shortcuts.go 0.00% 8 Missing ⚠️
shortcuts/lingo/lingo_entity_delete.go 77.27% 3 Missing and 2 partials ⚠️

❌ Your patch check has failed because the patch coverage (57.01%) is below the target coverage (60.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #855      +/-   ##
==========================================
+ Coverage   65.75%   65.79%   +0.04%     
==========================================
  Files         513      524      +11     
  Lines       47886    49103    +1217     
==========================================
+ Hits        31486    32308     +822     
- Misses      13682    14002     +320     
- Partials     2718     2793      +75     

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Architecture-level or global-impact change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants