diff --git a/shortcuts/doc/docs_create.go b/shortcuts/doc/docs_create.go index b0067deed..cae1205c4 100644 --- a/shortcuts/doc/docs_create.go +++ b/shortcuts/doc/docs_create.go @@ -43,6 +43,7 @@ var DocsCreate = common.Shortcut{ Risk: "write", AuthTypes: []string{"user", "bot"}, Scopes: []string{"docx:document:create"}, + Tips: docsVersionSelectionTips, Flags: concatFlags( []common.Flag{ {Name: "api-version", Desc: "API version", Default: "v1", Enum: []string{"v1", "v2"}}, diff --git a/shortcuts/doc/docs_fetch.go b/shortcuts/doc/docs_fetch.go index 7aa6ccc2c..f76ec52ad 100644 --- a/shortcuts/doc/docs_fetch.go +++ b/shortcuts/doc/docs_fetch.go @@ -49,6 +49,7 @@ var DocsFetch = common.Shortcut{ Scopes: []string{"docx:document:readonly"}, AuthTypes: []string{"user", "bot"}, HasFormat: true, + Tips: docsVersionSelectionTips, Flags: concatFlags( []common.Flag{ {Name: "api-version", Desc: "API version", Default: "v1", Enum: []string{"v1", "v2"}}, diff --git a/shortcuts/doc/docs_fetch_v2.go b/shortcuts/doc/docs_fetch_v2.go index e70f1c238..0b3eaee3f 100644 --- a/shortcuts/doc/docs_fetch_v2.go +++ b/shortcuts/doc/docs_fetch_v2.go @@ -22,7 +22,7 @@ func v2FetchFlags() []common.Flag { {Name: "scope", Desc: "partial read scope: outline | range | keyword | section (omit to read whole doc)", Default: "full", Enum: []string{"full", "outline", "range", "keyword", "section"}}, {Name: "start-block-id", Desc: "range/section mode: start (anchor) block id"}, {Name: "end-block-id", Desc: "range mode: end block id; \"-1\" = to end of document"}, - {Name: "keyword", Desc: "keyword mode: search string (case-insensitive); use '|' to match multiple keywords, e.g. 'foo|bar|baz'"}, + {Name: "keyword", Desc: "keyword mode: substring + regex match (case-insensitive); use '|' for OR branches, e.g. 'foo|bar' or 'bug|缺陷'"}, {Name: "context-before", Desc: "range/keyword/section mode: sibling blocks before match", Type: "int", Default: "0"}, {Name: "context-after", Desc: "range/keyword/section mode: sibling blocks after match", Type: "int", Default: "0"}, {Name: "max-depth", Desc: "outline: heading level cap; range/keyword/section: block subtree depth (-1 = unlimited)", Type: "int", Default: "-1"}, diff --git a/shortcuts/doc/docs_update.go b/shortcuts/doc/docs_update.go index b12c3ab1f..9353e54dd 100644 --- a/shortcuts/doc/docs_update.go +++ b/shortcuts/doc/docs_update.go @@ -64,6 +64,7 @@ var DocsUpdate = common.Shortcut{ Risk: "write", Scopes: []string{"docx:document:write_only", "docx:document:readonly"}, AuthTypes: []string{"user", "bot"}, + Tips: docsVersionSelectionTips, Flags: concatFlags( []common.Flag{ {Name: "api-version", Desc: "API version", Default: "v1", Enum: []string{"v1", "v2"}}, diff --git a/shortcuts/doc/shortcuts.go b/shortcuts/doc/shortcuts.go index 30ba91e4d..aac3366ca 100644 --- a/shortcuts/doc/shortcuts.go +++ b/shortcuts/doc/shortcuts.go @@ -3,7 +3,24 @@ package doc -import "github.com/larksuite/cli/shortcuts/common" +import ( + "fmt" + "strings" + + "github.com/spf13/cobra" + + "github.com/larksuite/cli/internal/cmdutil" + "github.com/larksuite/cli/shortcuts/common" +) + +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.", +} // Shortcuts returns all docs shortcuts. func Shortcuts() []common.Shortcut { @@ -18,3 +35,48 @@ func Shortcuts() []common.Shortcut { DocMediaDownload, } } + +// 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`. +func ConfigureServiceHelp(cmd *cobra.Command) { + if cmd == nil { + return + } + serviceCmd := cmd + cmd.Long = strings.TrimSpace(docsServiceHelpDefault) + if cmd.Flags().Lookup("api-version") == nil { + cmd.Flags().String("api-version", "", "show docs help for API version (v1|v2)") + cmdutil.RegisterFlagCompletion(cmd, "api-version", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) { + return []string{"v1", "v2"}, cobra.ShellCompDirectiveNoFileComp + }) + } + + defaultHelp := cmd.HelpFunc() + cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { + if cmd != serviceCmd { + defaultHelp(cmd, args) + return + } + + apiVersion, _ := cmd.Flags().GetString("api-version") + previousLong := cmd.Long + if apiVersion == "v2" { + cmd.Long = strings.TrimSpace(docsServiceHelpV2) + } else { + cmd.Long = strings.TrimSpace(docsServiceHelpDefault) + } + defer func() { + cmd.Long = previousLong + }() + + defaultHelp(cmd, args) + out := cmd.OutOrStdout() + fmt.Fprintln(out) + fmt.Fprintln(out, "Tips:") + for _, tip := range docsVersionSelectionTips { + fmt.Fprintf(out, " • %s\n", tip) + } + }) +} diff --git a/shortcuts/doc/versioned_help.go b/shortcuts/doc/versioned_help.go index 2111829ce..053bb3f36 100644 --- a/shortcuts/doc/versioned_help.go +++ b/shortcuts/doc/versioned_help.go @@ -30,13 +30,6 @@ func installVersionedHelp(cmd *cobra.Command, defaultVersion string, flagVersion } }) origHelp(cmd, args) - if ver == "v1" { - fmt.Fprintf(cmd.OutOrStdout(), - "\n[NOTE] v1 API is deprecated and will be removed in a future release.\n"+ - " Use --api-version v2 for the latest API:\n"+ - " %s %s --api-version v2 --help\n", - cmd.Parent().Name(), cmd.Name()) - } }) } diff --git a/shortcuts/register.go b/shortcuts/register.go index 534163ec2..c6d95654b 100644 --- a/shortcuts/register.go +++ b/shortcuts/register.go @@ -90,6 +90,9 @@ func RegisterShortcutsWithContext(ctx context.Context, program *cobra.Command, f } program.AddCommand(svc) } + if service == "docs" { + doc.ConfigureServiceHelp(svc) + } for _, shortcut := range shortcuts { shortcut.MountWithContext(ctx, svc, f) diff --git a/shortcuts/register_test.go b/shortcuts/register_test.go index 81d316fef..a05e1c839 100644 --- a/shortcuts/register_test.go +++ b/shortcuts/register_test.go @@ -4,16 +4,45 @@ package shortcuts import ( + "bytes" "encoding/json" + "fmt" "os" "path/filepath" "strings" "testing" "github.com/larksuite/cli/internal/cmdutil" + "github.com/larksuite/cli/internal/core" "github.com/spf13/cobra" ) +func newRegisterTestFactory(t *testing.T) *cmdutil.Factory { + t.Helper() + t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) + f, _, _, _ := cmdutil.TestFactory(t, &core.CliConfig{}) + return f +} + +func newRegisterTestProgramWithTipsHelp() *cobra.Command { + program := &cobra.Command{Use: "root"} + defaultHelp := program.HelpFunc() + program.SetHelpFunc(func(cmd *cobra.Command, args []string) { + defaultHelp(cmd, args) + tips := cmdutil.GetTips(cmd) + if len(tips) == 0 { + return + } + out := cmd.OutOrStdout() + fmt.Fprintln(out) + fmt.Fprintln(out, "Tips:") + for _, tip := range tips { + fmt.Fprintf(out, " • %s\n", tip) + } + }) + return program +} + func TestAllShortcutsScopesNotNil(t *testing.T) { for _, s := range allShortcuts { hasScopes := s.Scopes != nil || s.UserScopes != nil || s.BotScopes != nil @@ -48,7 +77,7 @@ func TestAllShortcutsReturnsCopyAndIncludesBase(t *testing.T) { func TestRegisterShortcutsMountsBaseCommands(t *testing.T) { program := &cobra.Command{Use: "root"} - RegisterShortcuts(program, &cmdutil.Factory{}) + RegisterShortcuts(program, newRegisterTestFactory(t)) baseCmd, _, err := program.Find([]string{"base"}) if err != nil { @@ -69,7 +98,7 @@ func TestRegisterShortcutsMountsBaseCommands(t *testing.T) { func TestRegisterShortcutsMountsDocsMediaPreview(t *testing.T) { program := &cobra.Command{Use: "root"} - RegisterShortcuts(program, &cmdutil.Factory{}) + RegisterShortcuts(program, newRegisterTestFactory(t)) previewCmd, _, err := program.Find([]string{"docs", "+media-preview"}) if err != nil { @@ -80,12 +109,182 @@ func TestRegisterShortcutsMountsDocsMediaPreview(t *testing.T) { } } +func TestRegisterShortcutsDocsHelpAddsVersionSelectorAndLegacyTips(t *testing.T) { + program := &cobra.Command{Use: "root"} + RegisterShortcuts(program, newRegisterTestFactory(t)) + + docsCmd, _, err := program.Find([]string{"docs"}) + if err != nil { + t.Fatalf("find docs command: %v", err) + } + if docsCmd == nil || docsCmd.Name() != "docs" { + t.Fatalf("docs command not mounted: %#v", docsCmd) + } + if docsCmd.Flags().Lookup("api-version") == nil { + t.Fatal("docs command should expose --api-version for versioned help") + } + + if !strings.Contains(docsCmd.Long, "Document and content operations.") { + t.Fatalf("docs long help missing default description:\n%s", docsCmd.Long) + } + + var defaultHelp bytes.Buffer + docsCmd.SetOut(&defaultHelp) + if err := docsCmd.Help(); err != nil { + t.Fatalf("docs help failed: %v", err) + } + 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", + } { + if !strings.Contains(defaultHelp.String(), want) { + t.Fatalf("docs default help missing %q:\n%s", want, defaultHelp.String()) + } + } +} + +func TestRegisterShortcutsDocsV2HelpUsesV2Description(t *testing.T) { + program := &cobra.Command{Use: "root"} + RegisterShortcuts(program, newRegisterTestFactory(t)) + + docsCmd, _, err := program.Find([]string{"docs"}) + if err != nil { + t.Fatalf("find docs command: %v", err) + } + if err := docsCmd.Flags().Set("api-version", "v2"); err != nil { + t.Fatalf("set docs api-version: %v", err) + } + + var out bytes.Buffer + docsCmd.SetOut(&out) + if err := docsCmd.Help(); err != nil { + t.Fatalf("docs v2 help failed: %v", err) + } + + 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", + } { + if !strings.Contains(out.String(), want) { + t.Fatalf("docs v2 help missing %q:\n%s", want, out.String()) + } + } +} + +func TestRegisterShortcutsDocsVersionedShortcutHelpAddsVersionTips(t *testing.T) { + tests := []struct { + name string + shortcut string + apiVersion string + shortcutHelp string + versionedFlag string + }{ + { + name: "create v1", + shortcut: "+create", + apiVersion: "v1", + shortcutHelp: "Create a Lark document", + versionedFlag: "--markdown", + }, + { + name: "create v2", + shortcut: "+create", + apiVersion: "v2", + shortcutHelp: "Create a Lark document", + versionedFlag: "--content", + }, + { + name: "fetch v1", + shortcut: "+fetch", + apiVersion: "v1", + shortcutHelp: "Fetch Lark document content", + versionedFlag: "--offset", + }, + { + name: "fetch v2", + shortcut: "+fetch", + apiVersion: "v2", + shortcutHelp: "Fetch Lark document content", + versionedFlag: "partial read scope", + }, + { + name: "update v1", + shortcut: "+update", + apiVersion: "v1", + shortcutHelp: "Update a Lark document", + versionedFlag: "--mode", + }, + { + name: "update v2", + shortcut: "+update", + apiVersion: "v2", + shortcutHelp: "Update a Lark document", + versionedFlag: "--command", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + program := newRegisterTestProgramWithTipsHelp() + RegisterShortcuts(program, newRegisterTestFactory(t)) + + cmd, _, err := program.Find([]string{"docs", tt.shortcut}) + if err != nil { + t.Fatalf("find docs %s command: %v", tt.shortcut, err) + } + if cmd == nil || cmd.Name() != tt.shortcut { + t.Fatalf("docs %s shortcut not mounted: %#v", tt.shortcut, cmd) + } + if err := cmd.Flags().Set("api-version", tt.apiVersion); err != nil { + t.Fatalf("set docs %s api-version: %v", tt.shortcut, err) + } + + var out bytes.Buffer + cmd.SetOut(&out) + if err := cmd.Help(); err != nil { + t.Fatalf("docs %s help failed: %v", tt.shortcut, err) + } + + 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", + } { + 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()) + } + } + }) + } +} + func TestRegisterShortcutsReusesExistingServiceCommand(t *testing.T) { program := &cobra.Command{Use: "root"} existingBase := &cobra.Command{Use: "base", Short: "existing base service"} program.AddCommand(existingBase) - RegisterShortcuts(program, &cmdutil.Factory{}) + RegisterShortcuts(program, newRegisterTestFactory(t)) baseCount := 0 for _, command := range program.Commands() { diff --git a/skills/lark-doc/SKILL.md b/skills/lark-doc/SKILL.md index 3bdad9d8f..7d70830ce 100644 --- a/skills/lark-doc/SKILL.md +++ b/skills/lark-doc/SKILL.md @@ -1,11 +1,11 @@ --- name: lark-doc version: 2.0.0 -description: "飞书云文档:创建和编辑飞书文档。默认使用 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: "飞书云文档(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 做资源发现。" metadata: requires: bins: ["lark-cli"] - cliHelp: "lark-cli docs --help" + cliHelp: "lark-cli docs --api-version v2 --help; lark-cli docs +create --api-version v2 --help; lark-cli docs +fetch --api-version v2 --help; lark-cli docs +update --api-version v2 --help" --- # docs (v2) diff --git a/skills/lark-doc/references/lark-doc-create.md b/skills/lark-doc/references/lark-doc-create.md index 67d641fd0..cb8689d3e 100644 --- a/skills/lark-doc/references/lark-doc-create.md +++ b/skills/lark-doc/references/lark-doc-create.md @@ -74,7 +74,7 @@ lark-cli docs +create --api-version v2 --doc-format markdown --content $'# 项 ## 最佳实践 - 文档标题从内容中自动提取(XML `` 或 Markdown `#`),不要在内容开头重复写标题 -- 创建较长的文档时,先创建基础内容,再用 `docs +update --command block_insert_after` 分段追加 +- **创建较长的文档时只建骨架**:`--content` 仅传标题 + 各级 heading + 简短占位摘要;正文留给后续 `docs +update --command append` 或 `block_insert_after` 分段追加。一次性塞超长 `--content` 既容易触发参数限制,调试也更难。 - **视觉丰富度**:必须遵循 [`lark-doc-style.md`](style/lark-doc-style.md) 中的样式指南,主动使用结构化 block 丰富文档 ## 参考 diff --git a/skills/lark-doc/references/lark-doc-fetch.md b/skills/lark-doc/references/lark-doc-fetch.md index 04388f1b2..3ec22b65c 100644 --- a/skills/lark-doc/references/lark-doc-fetch.md +++ b/skills/lark-doc/references/lark-doc-fetch.md @@ -49,21 +49,21 @@ lark-cli docs +fetch --api-version v2 --doc Z1Fj...tnAc \ | `outline` | 不知道结构,先看目录 | `--max-depth`(标题层级上限) | 扁平列出所有标题,**包括嵌在容器里的内嵌标题**(如 callout 里的 h3);这些 id 可直接作后续 `section` / `range` 端点 | | `section` | 读某个标题对应的整节 | `--start-block-id`(必填) | 顶层标题 → 展开到下一同级/更高级标题前;容器内节点(含内嵌标题) → 按"最小包容单元"返回容器/表格切片,不做 heading 扩展;顶层非标题块 → 仅该块 | | `range` | 已知精确起止 | `--start-block-id` / `--end-block-id` 至少一个;`-1` = 读到末尾 | 两端同顶层 → 顶层序列切片;两端同一容器 → 容器整体;两端同一表格 → 瘦身切片;**跨顶层 → 端点所在顶层块整块输出,不做瘦身** | -| `keyword` | 只有模糊关键词 | `--keyword`(不区分大小写、子串,`\|` 分隔多词 OR) | 每处命中按"最小包容单元"输出;**自动去重**(同容器多命中 → 单个容器,同表格多行命中 → 合并切片) | +| `keyword` | 只有模糊关键词 | `--keyword`(**多级自动 fallback**:子串 → 归一化 → 分词形变 → RE2 正则;`\|` 分隔多分支 OR) | 每处命中按"最小包容单元"输出;**自动去重**(同容器多命中 → 单个容器,同表格多行命中 → 合并切片) | + +> 💡 **多关键词用 `\|` 拼接(OR 语义,任一命中即返回)**:例 `"部署\|发布\|上线"`,三词任一命中都进结果,适合**同义词/别名/多业务术语**一次召回(如 `bug\|缺陷\|故障`)。 **设置 `--scope` 时共用** `--context-before` / `--context-after` / `--max-depth`。 - `--max-depth`:`outline` = 标题层级上限(3 = h1~h3);其它模式 = 被选块的子树遍历深度(`-1` 不限,`0` 仅块自身)。 - `--context-before/--context-after`:**只对整块顶层单元生效**;命中落在容器/表格内(返回容器或切片)时 before/after 被忽略,需要更大范围改用 `section` / `range` 显式指定。 -**决策顺序**(核心原则:**局部获取优于全量获取**,能精确到节/区间就绝不全量拉取;**任何文档的第一次读取都应从 `outline` 开始**): -1. **第一次接触文档 / 不知道结构** → 先 `outline` 探测目录(**强制首步,无论文档是"目标"还是"引用源"**),再回到 2/3 精读 -2. 改/读某个**标题对应的整节** → `section`(最省心,**首选精读方式**) -3. 精确自定义起止 / 跨节连续区间 → `range` -4. 只有模糊关键词 → `keyword` -5. **兜底**:确实需要整篇文档时才不传 `--scope`(默认整篇);**不要为了省事就读整篇**,局部模式上下文更省、响应更快 - -**推荐双步流程**:`outline --max-depth 3` 拿目录 → `section --start-block-id <标题id> --detail with-ids` 精读该节。 +**决策顺序**(核心原则:**局部获取优于全量获取**,根据需求形态选起点,必要时多步组合收敛范围): +1. 需求**直接给出待查的具体术语/错误码/标识** → 直接走 `keyword` 粗匹配(多级 fallback 自动覆盖形变),需要更大上下文时用返回的 `top-block-id` 走 `section` / `range` +2. 需求**指向某个章节/标题**("修改 XX 章"、"总结第 3 节"、"关于 xx 的内容")→ 先 `outline --max-depth 3` 拿目录 → `section --start-block-id <标题id>` 精读 +3. 已知**精确起止 / 跨节连续区间** → `range` +4. **结构未知且无明确关键词/章节线索** → `outline` 探测,再回到 2/3 +5. **兜底**:仅在确需整篇时才省略 `--scope`;不要为省事直接读整篇 ## 局部读取的输出结构:`<fragment>` 与 `<excerpt>` @@ -108,7 +108,7 @@ lark-cli docs +fetch --api-version v2 --doc Z1Fj...tnAc \ | `--scope` | 否 | `outline` \| `range` \| `keyword` \| `section`(省略 = 读整篇) | | `--start-block-id` | 否 | `range`/`section` 起始/锚点 id(`section` 必填) | | `--end-block-id` | 否 | `range` 结束 id;`-1` 表示读到末尾 | -| `--keyword` | 否 | `keyword` 模式关键词;`\|` 分隔多词 OR | +| `--keyword` | 否 | `keyword` 模式关键词,**4 层自动 fallback**(子串 → 归一化 → 分词形变 → RE2 正则);`\|` 分隔多分支 OR | | `--context-before` | 否 | 命中前拉几个兄弟块(仅对顶层单元生效,默认 `0`) | | `--context-after` | 否 | 命中后拉几个兄弟块(仅对顶层单元生效,默认 `0`) | | `--max-depth` | 否 | `outline` = 标题层级上限;其它 = 子树深度(`-1` 不限,默认) | diff --git a/skills/lark-doc/references/lark-doc-xml.md b/skills/lark-doc/references/lark-doc-xml.md index 56bbf76f5..9dff841dd 100644 --- a/skills/lark-doc/references/lark-doc-xml.md +++ b/skills/lark-doc/references/lark-doc-xml.md @@ -85,7 +85,7 @@ p, h1-h9, ul, ol, li, table, thead, tbody, tr, th, td, blockquote, pre, code, hr - 合并单元格仅起始格输出 `colspan` / `rowspan`,被合并的格不出现 # 六、美化系统 -- 颜色优先使用命名色,也可写 `rgb(r,g,b)` / `rgba(r,g,b,a)`。**基础色(6 色)**:gray, red, orange, yellow, green, blue +- 颜色优先使用命名色,也可写 `rgb(r,g,b)` / `rgba(r,g,b,a)`。**基础色(7 色)**:red, orange, yellow, green, blue, purple, gray | 属性 | 支持的命名色 | |-|-| | 文字颜色 `<span text-color>` | 基础色 | diff --git a/skills/lark-doc/references/style/lark-doc-create-workflow.md b/skills/lark-doc/references/style/lark-doc-create-workflow.md index 7b57628d6..48bec7f80 100644 --- a/skills/lark-doc/references/style/lark-doc-create-workflow.md +++ b/skills/lark-doc/references/style/lark-doc-create-workflow.md @@ -20,7 +20,9 @@ 1. 分析用户需求:受众、目的、范围 2. 设计大纲——每个 h1/h2 章节至少规划 1 个非文本 block -3. `docs +create --api-version v2` 创建文档:标题 + 开头 `<callout>` + 骨架(各级标题 + 简短占位摘要) +3. `docs +create --api-version v2` **只建骨架**:标题 + 开头 `<callout>` + 各级标题 + 每节一句占位摘要 + - ⚠️ **不要**一次性把完整章节内容塞进 `--content`。超长 `--content` 容易触发字符/参数限制。 + - 完整内容留到第二波,由各 Agent 用 `docs +update --command append` 或 `block_insert_after` 分段写入。 ### 第二波 — 内容撰写(并行 Agent) @@ -46,5 +48,3 @@ ## Agent 子任务要求 Spawn Agent 时必须提供:文档 token、章节范围(标题/block ID)、`lark-doc-xml.md` 和 `lark-doc-style.md` 路径、具体的 `docs +update` command 和 `--block-id`。 - -章节较多时,先 `docs +create` 建骨架,再分段 `append` 追加,比一次性超长 `--content` 更可靠。