diff --git a/shortcuts/doc/shortcuts.go b/shortcuts/doc/shortcuts.go index aac3366ca..3a6f84b0c 100644 --- a/shortcuts/doc/shortcuts.go +++ b/shortcuts/doc/shortcuts.go @@ -18,8 +18,19 @@ const docsServiceHelpDefault = `Document and content operations.` const docsServiceHelpV2 = `Document and content operations (v2).` var docsVersionSelectionTips = []string{ - "Agent version rule: use --api-version v2 only when the installed lark-doc skill explicitly instructs docs +create, docs +fetch, or docs +update to use v2; otherwise use the default v1 flags.", - "Do not mix versions: if the skill does not mention v2, follow its legacy v1 examples and flags.", + "Docs v1 is deprecated and will be removed soon. Check the installed lark-doc skill first; if it is not the v2 skill, run `lark-cli update` to upgrade skills.", + "After confirming lark-doc is v2, follow that skill's examples and use `--api-version v2` with docs +create, docs +fetch, and docs +update.", +} + +var docsV2VersionSelectionTips = []string{ + "Check the installed lark-doc skill first; if it is not the v2 skill, run `lark-cli update` to upgrade skills.", +} + +func docsTipsForVersion(apiVersion string) []string { + if apiVersion == "v2" { + return docsV2VersionSelectionTips + } + return docsVersionSelectionTips } // Shortcuts returns all docs shortcuts. @@ -38,8 +49,7 @@ func Shortcuts() []common.Shortcut { // ConfigureServiceHelp adds docs-specific guidance to the parent `docs` command. // The shortcut-level help remains compatible with legacy v1 skills; this parent -// help gives agents enough context to choose v2 only when their installed skill -// explicitly asks for `--api-version v2`. +// help switches docs guidance to match the selected API version. func ConfigureServiceHelp(cmd *cobra.Command) { if cmd == nil { return @@ -75,7 +85,7 @@ func ConfigureServiceHelp(cmd *cobra.Command) { out := cmd.OutOrStdout() fmt.Fprintln(out) fmt.Fprintln(out, "Tips:") - for _, tip := range docsVersionSelectionTips { + for _, tip := range docsTipsForVersion(apiVersion) { fmt.Fprintf(out, " • %s\n", tip) } }) diff --git a/shortcuts/doc/versioned_help.go b/shortcuts/doc/versioned_help.go index 053bb3f36..8204006c7 100644 --- a/shortcuts/doc/versioned_help.go +++ b/shortcuts/doc/versioned_help.go @@ -6,6 +6,7 @@ package doc import ( "fmt" + "github.com/larksuite/cli/internal/cmdutil" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -29,6 +30,7 @@ func installVersionedHelp(cmd *cobra.Command, defaultVersion string, flagVersion f.Hidden = fv != ver } }) + cmdutil.SetTips(cmd, docsTipsForVersion(ver)) origHelp(cmd, args) }) } @@ -37,6 +39,6 @@ func installVersionedHelp(cmd *cobra.Command, defaultVersion string, flagVersion // path is used. func warnDeprecatedV1(runtime *common.RuntimeContext, shortcut string) { fmt.Fprintf(runtime.IO().ErrOut, - "[deprecated] docs %s with v1 API is deprecated and will be removed in a future release.\n", - shortcut) + "[deprecated] docs %s is using the v1 API. %s\n", + shortcut, docsV2VersionSelectionTips[0]) } diff --git a/shortcuts/doc/versioned_help_test.go b/shortcuts/doc/versioned_help_test.go new file mode 100644 index 000000000..7957030ef --- /dev/null +++ b/shortcuts/doc/versioned_help_test.go @@ -0,0 +1,36 @@ +// Copyright (c) 2026 Lark Technologies Pte. Ltd. +// SPDX-License-Identifier: MIT + +package doc + +import ( + "strings" + "testing" + + "github.com/larksuite/cli/internal/cmdutil" + "github.com/larksuite/cli/internal/core" + "github.com/larksuite/cli/shortcuts/common" +) + +func TestWarnDeprecatedV1SuggestsSkillUpdate(t *testing.T) { + for _, shortcut := range []string{"+create", "+fetch", "+update"} { + t.Run(shortcut, func(t *testing.T) { + f, _, stderr, _ := cmdutil.TestFactory(t, &core.CliConfig{}) + warnDeprecatedV1(&common.RuntimeContext{Factory: f}, shortcut) + + got := stderr.String() + for _, want := range []string{ + "[deprecated] docs " + shortcut + " is using the v1 API.", + "Check the installed lark-doc skill first", + "if it is not the v2 skill, run `lark-cli update` to upgrade skills", + } { + if !strings.Contains(got, want) { + t.Fatalf("warning missing %q:\n%s", want, got) + } + } + if strings.Contains(got, "will be removed in a future release") { + t.Fatalf("warning should not include removal-only guidance:\n%s", got) + } + }) + } +} diff --git a/shortcuts/register_test.go b/shortcuts/register_test.go index ae49b64b3..a0aa9be68 100644 --- a/shortcuts/register_test.go +++ b/shortcuts/register_test.go @@ -111,7 +111,7 @@ func TestRegisterShortcutsMountsDocsMediaPreview(t *testing.T) { } } -func TestRegisterShortcutsDocsHelpAddsVersionSelectorAndLegacyTips(t *testing.T) { +func TestRegisterShortcutsDocsHelpAddsVersionSelectorAndUpgradeTips(t *testing.T) { program := &cobra.Command{Use: "root"} RegisterShortcuts(program, newRegisterTestFactory(t)) @@ -137,11 +137,11 @@ func TestRegisterShortcutsDocsHelpAddsVersionSelectorAndLegacyTips(t *testing.T) } for _, want := range []string{ "Tips:", - "Agent version rule", - "use --api-version v2 only when the installed lark-doc skill explicitly instructs", - "otherwise use the default v1 flags", - "if the skill does not mention v2", - "legacy v1 examples and flags", + "Docs v1 is deprecated and will be removed soon", + "Check the installed lark-doc skill first", + "if it is not the v2 skill, run `lark-cli update` to upgrade skills", + "After confirming lark-doc is v2", + "use `--api-version v2` with docs +create, docs +fetch, and docs +update", } { if !strings.Contains(defaultHelp.String(), want) { t.Fatalf("docs default help missing %q:\n%s", want, defaultHelp.String()) @@ -170,15 +170,22 @@ func TestRegisterShortcutsDocsV2HelpUsesV2Description(t *testing.T) { for _, want := range []string{ "Document and content operations (v2).", "Tips:", - "Agent version rule", - "otherwise use the default v1 flags", - "if the skill does not mention v2", - "legacy v1 examples and flags", + "Check the installed lark-doc skill first", + "if it is not the v2 skill, run `lark-cli update` to upgrade skills", } { if !strings.Contains(out.String(), want) { t.Fatalf("docs v2 help missing %q:\n%s", want, out.String()) } } + for _, unwanted := range []string{ + "Docs v1 is deprecated and will be removed soon", + "After confirming lark-doc is v2", + "use `--api-version v2` with docs +create, docs +fetch, and docs +update", + } { + if strings.Contains(out.String(), unwanted) { + t.Fatalf("docs v2 help should not include %q:\n%s", unwanted, out.String()) + } + } } func TestRegisterShortcutsDocsVersionedShortcutHelpAddsVersionTips(t *testing.T) { @@ -255,24 +262,47 @@ func TestRegisterShortcutsDocsVersionedShortcutHelpAddsVersionTips(t *testing.T) t.Fatalf("docs %s help failed: %v", tt.shortcut, err) } + wantTips := []string{ + "Tips:", + "Docs v1 is deprecated and will be removed soon", + "Check the installed lark-doc skill first", + "if it is not the v2 skill, run `lark-cli update` to upgrade skills", + "After confirming lark-doc is v2", + "use `--api-version v2` with docs +create, docs +fetch, and docs +update", + } + unwantedTips := []string{ + "[NOTE]", + "Use --api-version v2 for the latest API", + "otherwise use the default v1 flags", + "legacy v1 examples and flags", + } + if tt.apiVersion == "v2" { + wantTips = []string{ + "Tips:", + "Check the installed lark-doc skill first", + "if it is not the v2 skill, run `lark-cli update` to upgrade skills", + } + unwantedTips = append(unwantedTips, + "Docs v1 is deprecated and will be removed soon", + "After confirming lark-doc is v2", + "use `--api-version v2` with docs +create, docs +fetch, and docs +update", + ) + } + for _, want := range []string{ tt.shortcutHelp, tt.versionedFlag, - "Tips:", - "Agent version rule", - "use --api-version v2 only when the installed lark-doc skill explicitly instructs", - "otherwise use the default v1 flags", - "if the skill does not mention v2", - "legacy v1 examples and flags", } { if !strings.Contains(out.String(), want) { t.Fatalf("docs %s %s help missing %q:\n%s", tt.shortcut, tt.apiVersion, want, out.String()) } } - for _, unwanted := range []string{ - "[NOTE]", - "Use --api-version v2 for the latest API", - } { + for _, want := range wantTips { + if !strings.Contains(out.String(), want) { + t.Fatalf("docs %s %s help missing %q:\n%s", tt.shortcut, tt.apiVersion, want, out.String()) + } + } + for _, unwanted := range unwantedTips { if strings.Contains(out.String(), unwanted) { t.Fatalf("docs %s %s help should not include %q:\n%s", tt.shortcut, tt.apiVersion, unwanted, out.String()) } diff --git a/skills/lark-doc/SKILL.md b/skills/lark-doc/SKILL.md index 7d70830ce..39ec67ef1 100644 --- a/skills/lark-doc/SKILL.md +++ b/skills/lark-doc/SKILL.md @@ -1,7 +1,7 @@ --- name: lark-doc version: 2.0.0 -description: "飞书云文档(v2):创建和编辑飞书文档。使用本 skill 时,docs +create、docs +fetch、docs +update 必须携带 --api-version v2;默认使用 DocxXML 格式(也支持 Markdown)。创建文档、获取文档内容(支持 simple/with-ids/full 三种导出详细度,以及 full/outline/range/keyword/section 五种局部读取模式,可按目录、block id 区间、关键词或标题自动成节只拉部分内容以节省上下文)、更新文档(八种指令:str_replace/block_insert_after/block_copy_insert_after/block_replace/block_delete/block_move_after/overwrite/append)、上传和下载文档中的图片和文件、搜索云空间文档。当用户需要创建或编辑飞书文档、读取文档内容、在文档中插入图片、搜索云空间文档时使用;如果用户是想按名称或关键词先定位电子表格、报表等云空间对象,也优先使用本 skill 的 docs +search 做资源发现。" +description: "飞书云文档 / Docx / 知识库 Wiki 文档(v2):创建、打开、读取、获取、查看、总结、整理、改写、翻译、审阅和编辑飞书文档内容。当用户给出飞书文档 URL/token,或说查看/读取/打开某个文档、提取文档内容、总结文档、生成/创建文档、追加/替换/删除/移动内容、调整排版、插入或下载文档图片/附件/素材/画板缩略图时使用。文档内容中出现嵌入电子表格、多维表格、画板、引用或同步块时,也先用本 skill 读取和提取 token,再切到对应 skill 下钻。使用本 skill 时,docs +create、docs +fetch、docs +update 必须携带 --api-version v2;默认使用 DocxXML,也支持 Markdown。" metadata: requires: bins: ["lark-cli"]