Skip to content

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

Closed
emac wants to merge 1 commit into
larksuite:mainfrom
emac:feat/lingo
Closed

feat(lingo): add Feishu dictionary shortcuts and skill#854
emac wants to merge 1 commit into
larksuite:mainfrom
emac:feat/lingo

Conversation

@emac

@emac emac commented May 12, 2026

Copy link
Copy Markdown

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) support with six commands: search, match, get, create, update, delete.
  • Documentation

    • Updated README (EN/ZH) and Agent Skills table; added Lingo skill playbook and detailed reference guides for each command.
  • Tests

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

    • Registered Lingo shortcuts so commands are available in the CLI.

Review Change Stack

@CLAassistant

CLAassistant commented May 12, 2026

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.

@github-actions github-actions Bot added the size/XL Architecture-level or global-impact change label May 12, 2026
@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1eb4be68-4fe4-486b-8ae1-c77f9fd0f735

📥 Commits

Reviewing files that changed from the base of the PR and between 41e7908 and 6455fd5.

📒 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

📝 Walkthrough

Walkthrough

This PR adds a Lingo (Feishu Baike) domain: six CLI shortcuts (+search, +match, +get, +create, +update, +delete) with validations and API wiring, unit and e2e dry-run tests, skill documentation, a registry entry, and registration wiring.

Changes

Lingo Enterprise Dictionary Service

Layer / File(s) Summary
Service registration and infrastructure
README.md, README.zh.md, internal/registry/service_descriptions.json, shortcuts/lingo/helpers_test.go, shortcuts/lingo/shortcuts.go, shortcuts/register.go
Service documented in README and registry, lingo.Shortcuts() added and registered; shared test helpers (lingoTestConfig, runLingoShortcut, decodeEnvelope) added.
Search shortcut
shortcuts/lingo/lingo_entity_search.go, shortcuts/lingo/lingo_entity_search_test.go
Fuzzy search implementation with pagination (--query, --page-size, --page-token, --repo-id), request body builder, main-key extraction, description truncation, and tests for validation, dry-run, matches/no-matches, and API errors.
Match shortcut
shortcuts/lingo/lingo_entity_match.go, shortcuts/lingo/lingo_entity_match_test.go
Exact-word match (--word) posting to /open-apis/lingo/v1/entities/match, prints matches or "No match", with tests for validation, dry-run, hit/miss flows.
Get shortcut
shortcuts/lingo/lingo_entity_get.go, shortcuts/lingo/lingo_entity_get_test.go
Fetch entity details by --entity-id with optional --provider/--outer-id query params, formats id/main-key/description/aliases, and includes validation and execution tests.
Create shortcut
shortcuts/lingo/lingo_entity_create.go, shortcuts/lingo/lingo_entity_create_test.go
Create entity with --main-key and optional --aliases/--description/--repo-id, builds main_keys with display_status, parses aliases, POSTs to entities, and has tests for validation, dry-run minimal/full bodies, success, and permission errors.
Update shortcut
shortcuts/lingo/lingo_entity_update.go, shortcuts/lingo/lingo_entity_update_test.go
PUT full-overwrite update with --entity-id and --main-key, conditional aliases/description inclusion, request body builder, execution, and tests for missing fields, dry-run, and success.
Delete shortcut
shortcuts/lingo/lingo_entity_delete.go, shortcuts/lingo/lingo_entity_delete_test.go
DELETE entity by --entity-id with high-risk confirmation (--yes), dry-run mapping, structured deleted output, and tests for validation, confirmation refusal, dry-run, and success.
Skill documentation
skills/lark-lingo/SKILL.md, skills/lark-lingo/references/*
SKILL playbook and per-operation reference docs describing usage, parameters, constraints, required scopes, examples, and safety rules for lark-lingo.
End-to-end dry-run tests
tests/cli_e2e/lingo/lingo_dryrun_test.go
CLI-level dry-run tests asserting that --dry-run for each shortcut includes expected REST paths and HTTP methods/content.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • larksuite/cli#704: Adds a new shortcuts domain and updates shortcuts registration, touching the same registration logic.

Suggested reviewers

  • fangshuyu-768
  • kongenpei
  • liangshuo-1

🐰 A rabbit hops through Baike's hall,
Six shortcuts answer every call—
Match then get, or search and create,
Update, delete—dry-run tests await.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is comprehensive, detailing six shortcuts, their endpoints, the skill structure, documentation, integration gotchas, and supporting changes, but the template sections (Summary, Changes, Test Plan, Related Issues) remain largely unfilled with required details. Fill in the template sections: add a 1-3 sentence summary under ## Summary, explicitly list main changes under ## Changes (not just the template placeholders), and mark Test Plan checkboxes with verification status.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.49% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(lingo): add Feishu dictionary shortcuts and skill' clearly and specifically describes the main change—introducing new lingo shortcuts and skill documentation.
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

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

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

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@emac emac closed this May 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 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/helpers_test.go`:
- Around line 21-29: The shared test helper lingoTestConfig does not isolate
config state; update the lingoTestConfig(t *testing.T) helper to call
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) (before returning the
*core.CliConfig) so all lingo shortcut tests use a unique temporary config
directory; keep the rest of the function (suffix computation and returned
core.CliConfig) unchanged.

In `@shortcuts/lingo/lingo_entity_delete.go`:
- Line 25: The command registration currently allows both user and bot auth via
AuthTypes: []string{"user", "bot"} in lingo_entity_delete.go; change AuthTypes
to only permit bot (e.g., AuthTypes: []string{"bot"}) so the +delete shortcut is
bot-only; update any related validation or tests that assume user-level access
to this shortcut to reflect the new bot-only restriction.

In `@shortcuts/lingo/lingo_entity_get.go`:
- Around line 30-45: In the Validate function for lingo_entity_get (the Validate
closure that checks runtime.Str("entity-id")), after the existing control-char
checks for runtime.Str("provider") and runtime.Str("outer-id"), add a
paired-presence check so that provider and outer-id must both be set or both be
empty; if one is set and the other is empty return a validation error (use the
same error-return pattern as other checks) referencing the "provider" and
"outer-id" fields so the user gets an immediate, clear message. Ensure you still
call validate.RejectControlChars for each non-empty value before this paired
check.

In `@skills/lark-lingo/references/lark-lingo-get.md`:
- Around line 13-15: The example for the +get command incorrectly passes an
empty required flag (--entity-id ""), so update the snippet in lark-lingo-get.md
to show a valid entity id or remove the flag entirely; specifically change the
example invocation of the +get command to include a realistic placeholder for
--entity-id (e.g., --entity-id "ENTITY-123" or similar) while keeping the rest
(--provider "myhr" --outer-id "EMP-001") so the +get usage and the --entity-id
requirement are clear.

In `@tests/cli_e2e/lingo/lingo_dryrun_test.go`:
- Around line 88-111: Update the dry-run tests to include the required bot
identity flag by adding "--as", "bot" to the Args slice in
TestLingo_CreateDryRun, TestLingo_UpdateDryRun, and TestLingo_DeleteDryRun; then
enforce the documented requirement in the CLI shortcuts by adding validation
inside the Validate callback of the shortcut implementations (functions in
lingo_entity_create.go, lingo_entity_update.go, lingo_entity_delete.go) to
reject non-bot auth types—check the parsed auth type (the same field used now
that allows "user" or "bot") and return a validation error unless it equals
"bot".
🪄 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: 5735c02a-ad28-49ed-b19f-4407d609ecab

📥 Commits

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

📒 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 +21 to +29
func lingoTestConfig(t *testing.T) *core.CliConfig {
t.Helper()
suffix := strings.NewReplacer("/", "-", " ", "-").Replace(strings.ToLower(t.Name()))
return &core.CliConfig{
AppID: "test-lingo-" + suffix,
AppSecret: "secret-lingo-" + suffix,
Brand: core.BrandFeishu,
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Set LARKSUITE_CLI_CONFIG_DIR in the shared test config helper.

Adding it here keeps all lingo shortcut tests consistently isolated.

Suggested fix
 func lingoTestConfig(t *testing.T) *core.CliConfig {
 	t.Helper()
+	t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
 	suffix := strings.NewReplacer("/", "-", " ", "-").Replace(strings.ToLower(t.Name()))
 	return &core.CliConfig{

As per coding guidelines: Use t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) to isolate config state in tests.

📝 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
func lingoTestConfig(t *testing.T) *core.CliConfig {
t.Helper()
suffix := strings.NewReplacer("/", "-", " ", "-").Replace(strings.ToLower(t.Name()))
return &core.CliConfig{
AppID: "test-lingo-" + suffix,
AppSecret: "secret-lingo-" + suffix,
Brand: core.BrandFeishu,
}
}
func lingoTestConfig(t *testing.T) *core.CliConfig {
t.Helper()
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
suffix := strings.NewReplacer("/", "-", " ", "-").Replace(strings.ToLower(t.Name()))
return &core.CliConfig{
AppID: "test-lingo-" + suffix,
AppSecret: "secret-lingo-" + suffix,
Brand: core.BrandFeishu,
}
}
🤖 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/helpers_test.go` around lines 21 - 29, The shared test helper
lingoTestConfig does not isolate config state; update the lingoTestConfig(t
*testing.T) helper to call t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
(before returning the *core.CliConfig) so all lingo shortcut tests use a unique
temporary config directory; keep the rest of the function (suffix computation
and returned core.CliConfig) unchanged.

Description: "Delete a dictionary entry by entity_id (irreversible; requires --yes)",
Risk: "high-risk-write",
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 +delete to bot auth.

This command is a write/high-risk operation but currently allows user auth. That contradicts the bot-only write contract described for Lingo write endpoints.

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
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_delete.go` at line 25, The command registration
currently allows both user and bot auth via AuthTypes: []string{"user", "bot"}
in lingo_entity_delete.go; change AuthTypes to only permit bot (e.g., AuthTypes:
[]string{"bot"}) so the +delete shortcut is bot-only; update any related
validation or tests that assume user-level access to this shortcut to reflect
the new bot-only restriction.

Comment on lines +30 to +45
Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
if err := validate.RejectControlChars(runtime.Str("entity-id"), "entity-id"); err != nil {
return err
}
if v := runtime.Str("provider"); v != "" {
if err := validate.RejectControlChars(v, "provider"); err != nil {
return err
}
}
if v := runtime.Str("outer-id"); v != "" {
if err := validate.RejectControlChars(v, "outer-id"); err != nil {
return err
}
}
return 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 | 🟡 Minor | ⚡ Quick win

Enforce --provider and --outer-id as a pair in Validate.

Right now one-sided input passes local validation and fails later at API time. Rejecting it early gives clearer UX and matches the documented contract.

Suggested fix
 	Validate: func(ctx context.Context, runtime *common.RuntimeContext) error {
+		provider := runtime.Str("provider")
+		outerID := runtime.Str("outer-id")
+		if (provider == "") != (outerID == "") {
+			return fmt.Errorf("--provider and --outer-id must be used together")
+		}
 		if err := validate.RejectControlChars(runtime.Str("entity-id"), "entity-id"); err != nil {
 			return err
 		}
-		if v := runtime.Str("provider"); v != "" {
+		if v := provider; v != "" {
 			if err := validate.RejectControlChars(v, "provider"); err != nil {
 				return err
 			}
 		}
-		if v := runtime.Str("outer-id"); v != "" {
+		if v := outerID; v != "" {
 			if err := validate.RejectControlChars(v, "outer-id"); err != nil {
 				return err
 			}
 		}
 		return nil
 	},
🤖 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_get.go` around lines 30 - 45, In the Validate
function for lingo_entity_get (the Validate closure that checks
runtime.Str("entity-id")), after the existing control-char checks for
runtime.Str("provider") and runtime.Str("outer-id"), add a paired-presence check
so that provider and outer-id must both be set or both be empty; if one is set
and the other is empty return a validation error (use the same error-return
pattern as other checks) referencing the "provider" and "outer-id" fields so the
user gets an immediate, clear message. Ensure you still call
validate.RejectControlChars for each non-empty value before this paired check.

Comment on lines +13 to +15
# 按外部系统(provider + outer_id)查找对应词条
lark-cli lingo +get --entity-id "" --provider "myhr" --outer-id "EMP-001"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix the example that passes an empty required --entity-id.

+get is documented as requiring --entity-id, so --entity-id "" is misleading and likely invalid in practice.

Suggested doc fix
-# 按外部系统(provider + outer_id)查找对应词条
-lark-cli lingo +get --entity-id "" --provider "myhr" --outer-id "EMP-001"
+# 按外部系统信息补充查询(仍需 entity_id)
+lark-cli lingo +get --entity-id "enterprise_xxxx" --provider "myhr" --outer-id "EMP-001"
📝 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
# 按外部系统(provider + outer_id)查找对应词条
lark-cli lingo +get --entity-id "" --provider "myhr" --outer-id "EMP-001"
# 按外部系统信息补充查询(仍需 entity_id)
lark-cli lingo +get --entity-id "enterprise_xxxx" --provider "myhr" --outer-id "EMP-001"
🤖 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 13 - 15, The
example for the +get command incorrectly passes an empty required flag
(--entity-id ""), so update the snippet in lark-lingo-get.md to show a valid
entity id or remove the flag entirely; specifically change the example
invocation of the +get command to include a realistic placeholder for
--entity-id (e.g., --entity-id "ENTITY-123" or similar) while keeping the rest
(--provider "myhr" --outer-id "EMP-001") so the +get usage and the --entity-id
requirement are clear.

Comment on lines +88 to +111
func TestLingo_CreateDryRun(t *testing.T) {
setDryRunConfigEnv(t)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
t.Cleanup(cancel)

result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{
"lingo", "+create",
"--main-key", "KYC",
"--aliases", "Know Your Customer",
"--description", "AML monitoring concept",
"--dry-run",
},
})
require.NoError(t, err)
result.AssertExitCode(t, 0)

out := result.Stdout
assert.True(t, strings.Contains(out, "/open-apis/lingo/v1/entities"), "dry-run should contain API path, got: %s", out)
assert.True(t, strings.Contains(out, "POST"), "dry-run should be POST, got: %s", out)
assert.True(t, strings.Contains(out, "main_keys"), "dry-run body should contain main_keys, got: %s", out)
assert.True(t, strings.Contains(out, "Know Your Customer"), "dry-run should contain alias, got: %s", out)
assert.True(t, strings.Contains(out, "AML monitoring concept"), "dry-run should contain description, got: %s", out)
}

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 | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if lingo +create validates --as bot requirement

# Search for validation logic in the create shortcut implementation
rg -n -A10 -B2 'func.*Validate' shortcuts/lingo/lingo_entity_create.go

# Look for bot identity checks
rg -n 'as.*bot|bot.*identity|RequireBot' shortcuts/lingo/lingo_entity_create.go

Repository: larksuite/cli

Length of output: 39


🏁 Script executed:

# First, let's find where lingo shortcuts are located
find . -type f -name "*lingo*" | grep -E '\.(go|md)$' | head -20

Repository: larksuite/cli

Length of output: 922


🏁 Script executed:

# Search for lingo shortcut definition or implementation
rg -l "lingo" --type go | grep -i shortcut

Repository: larksuite/cli

Length of output: 630


🏁 Script executed:

# Look for the lingo create operation definition
rg -n "create.*lingo|lingo.*create" --type go | head -10

Repository: larksuite/cli

Length of output: 124


🏁 Script executed:

# Check the lingo_entity_create.go file for validation logic
cat -n shortcuts/lingo/lingo_entity_create.go | head -100

Repository: larksuite/cli

Length of output: 4159


🏁 Script executed:

# Search for Validate function and bot identity checks in the create file
rg -n "Validate|RequireBot|as.*bot" shortcuts/lingo/lingo_entity_create.go -A5

Repository: larksuite/cli

Length of output: 366


🏁 Script executed:

# Check the documentation file to see what it says about --as bot requirement
cat -n skills/lark-lingo/references/lark-lingo-create.md | head -30

Repository: larksuite/cli

Length of output: 843


🏁 Script executed:

# Check if there are other lingo shortcut implementations that DO enforce bot requirement
rg -n "RequireBot|AuthTypes.*bot" shortcuts/lingo/ --type go

Repository: larksuite/cli

Length of output: 539


🏁 Script executed:

# Look at other write operations (update, delete) to see if they validate bot requirement
rg -n -A5 "Validate: func" shortcuts/lingo/lingo_entity_update.go shortcuts/lingo/lingo_entity_delete.go

Repository: larksuite/cli

Length of output: 1159


🏁 Script executed:

# Check the delete and update tests to see if they also omit --as bot
grep -n -A3 "CreateDryRun\|UpdateDryRun\|DeleteDryRun" tests/cli_e2e/lingo/lingo_dryrun_test.go | head -40

Repository: larksuite/cli

Length of output: 587


🏁 Script executed:

# Look for any other bot-only shortcuts to see how they handle validation
rg -n "bot-only\|must.*bot\|RequireBot" shortcuts/ --type go

Repository: larksuite/cli

Length of output: 39


🏁 Script executed:

# Get the full args for Update and Delete tests to see if they include --as bot
sed -n '113,135p' tests/cli_e2e/lingo/lingo_dryrun_test.go

Repository: larksuite/cli

Length of output: 815


🏁 Script executed:

# Get the full args for Delete test
sed -n '136,155p' tests/cli_e2e/lingo/lingo_dryrun_test.go

Repository: larksuite/cli

Length of output: 663


Add --as bot flag to all write-operation tests and fix shortcut validation.

The lingo documentation (lark-lingo-create.md:5) explicitly mandates --as bot for the +create operation and examples show it for +update and +delete as well. However, the shortcut implementations for all three operations allow both "user" and "bot" auth types (lingo_entity_*.go:26) but do not validate the bot-identity requirement in their Validate callbacks.

This test suite tests incorrect behavior by omitting the --as bot flag across all three write operations and expecting exit code 0:

  • TestLingo_CreateDryRun (line 95): missing --as bot
  • TestLingo_UpdateDryRun (line 120): missing --as bot
  • TestLingo_DeleteDryRun (line 141): missing --as bot

Fix required in two places:

  1. Add "--as", "bot" to the Args array in all three test functions
  2. Add bot-identity validation to the Validate callback in each shortcut (lingo_entity_create.go, lingo_entity_update.go, lingo_entity_delete.go) to enforce the documented requirement
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/cli_e2e/lingo/lingo_dryrun_test.go` around lines 88 - 111, Update the
dry-run tests to include the required bot identity flag by adding "--as", "bot"
to the Args slice in TestLingo_CreateDryRun, TestLingo_UpdateDryRun, and
TestLingo_DeleteDryRun; then enforce the documented requirement in the CLI
shortcuts by adding validation inside the Validate callback of the shortcut
implementations (functions in lingo_entity_create.go, lingo_entity_update.go,
lingo_entity_delete.go) to reject non-bot auth types—check the parsed auth type
(the same field used now that allows "user" or "bot") and return a validation
error unless it equals "bot".

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