From 88f5a5a0e85034e009343bb3c7fdb9820e7ce90c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=91=9E=E8=BE=BE?= Date: Wed, 5 Aug 2026 15:46:24 +0800 Subject: [PATCH 1/2] feat(doc): align skill routing with runtime schema --- internal/cli/schema_agent_metadata/doc.json | 402 +++++++++--------- internal/cli/schema_agent_metadata/index.json | 2 +- internal/cli/schema_agent_metadata_audit.json | 2 +- internal/cli/schema_catalog/catalog.json | 58 +-- internal/cli/schema_catalog/tools/doc.json | 402 +++++++++--------- internal/cli/schema_hints/selection/doc.json | 82 ++-- scripts/gen_skill_shortcut_sections.py | 21 +- scripts/policy/check-skill-context-budget.sh | 25 +- skills/multi/dingtalk-doc/SKILL.md | 191 +++------ .../dingtalk-doc/references/04-document.md | 29 +- skills/multi/dingtalk-doc/references/doc.md | 26 +- .../dingtalk-doc/references/doc/doc-create.md | 4 +- .../dingtalk-doc/references/doc/doc-update.md | 32 +- .../doc/style/doc-update-workflow.md | 14 +- .../dingtalk-doc/references/intent-guide.md | 5 +- .../scripts/doc_create_and_write.py | 302 +++++++------ test/scripts/doc_skill_scripts_test.py | 161 +++++++ 17 files changed, 946 insertions(+), 812 deletions(-) create mode 100644 test/scripts/doc_skill_scripts_test.py diff --git a/internal/cli/schema_agent_metadata/doc.json b/internal/cli/schema_agent_metadata/doc.json index 27387e12..5702d4f0 100644 --- a/internal/cli/schema_agent_metadata/doc.json +++ b/internal/cli/schema_agent_metadata/doc.json @@ -783,7 +783,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive copy;要搬走原件用 move;复制后必须从真实返回取副本 nodeId,禁止继续编辑源文档" ], "confirmation": "user_required", "effect": "write", @@ -797,14 +797,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "candidates": [ { "value": "复制文档/文件到指定文件夹或知识库", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。" } ] }, @@ -826,21 +826,21 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive copy;要搬走原件用 move;复制后必须从真实返回取副本 nodeId,禁止继续编辑源文档" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive copy;要搬走原件用 move;复制后必须从真实返回取副本 nodeId,禁止继续编辑源文档" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。" } ] }, @@ -883,7 +883,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "candidates": [ { "value": [ @@ -892,7 +892,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。" } ] }, @@ -979,7 +979,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。" } ] }, @@ -1006,7 +1006,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "candidates": [ { "value": [ @@ -1015,7 +1015,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。" } ] } @@ -1041,7 +1041,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "长、多行、表格或文件内容使用 doc update --mode append --content-file;指定位置或富结构使用 block insert;不要跳过 user_required 确认" ], "confirmation": "user_required", "effect": "write", @@ -1056,14 +1056,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "candidates": [ { "value": "在文档末尾追加一段文本(安全追加,不改动原有内容)", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。" } ] }, @@ -1085,21 +1085,21 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "长、多行、表格或文件内容使用 doc update --mode append --content-file;指定位置或富结构使用 block insert;不要跳过 user_required 确认" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "长、多行、表格或文件内容使用 doc update --mode append --content-file;指定位置或富结构使用 block insert;不要跳过 user_required 确认" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。" } ] }, @@ -1143,7 +1143,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "candidates": [ { "value": [ @@ -1153,7 +1153,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。" } ] }, @@ -1240,7 +1240,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。" } ] }, @@ -1267,7 +1267,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "candidates": [ { "value": [ @@ -1276,7 +1276,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。" } ] } @@ -1560,7 +1560,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "用户要直接拿到本地 docx/markdown/pdf 文件时使用一体化 dws doc export;不要默认手工编排 submit/get 轮询" ], "confirmation": "not_required", "effect": "read", @@ -1574,14 +1574,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "candidates": [ { "value": "提交在线文档导出任务 (docx/markdown/pdf),返回 jobId", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。" } ] }, @@ -1603,21 +1603,21 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "用户要直接拿到本地 docx/markdown/pdf 文件时使用一体化 dws doc export;不要默认手工编排 submit/get 轮询" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "用户要直接拿到本地 docx/markdown/pdf 文件时使用一体化 dws doc export;不要默认手工编排 submit/get 轮询" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。" } ] }, @@ -1660,7 +1660,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "candidates": [ { "value": [ @@ -1669,7 +1669,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。" } ] }, @@ -1756,7 +1756,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。" } ] }, @@ -1783,7 +1783,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "candidates": [ { "value": [ @@ -1792,7 +1792,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。" } ] } @@ -1818,7 +1818,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "需要最近访问、extension/时间/创建者等组合过滤时使用 +search;目标已给 nodeId/URL 时直接进入 info/read,不再搜索" ], "confirmation": "not_required", "effect": "read", @@ -1833,14 +1833,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "candidates": [ { "value": "按关键词搜索云文档并投影关键字段(只读)", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。" } ] }, @@ -1862,21 +1862,21 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "需要最近访问、extension/时间/创建者等组合过滤时使用 +search;目标已给 nodeId/URL 时直接进入 info/read,不再搜索" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "需要最近访问、extension/时间/创建者等组合过滤时使用 +search;目标已给 nodeId/URL 时直接进入 info/read,不再搜索" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。" } ] }, @@ -1920,7 +1920,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "candidates": [ { "value": [ @@ -1930,7 +1930,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。" } ] }, @@ -2017,7 +2017,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。" } ] }, @@ -2044,7 +2044,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "candidates": [ { "value": [ @@ -2053,7 +2053,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。" } ] } @@ -2079,7 +2079,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "全局或钉盘目录浏览优先 drive list,知识库节点树优先 wiki node list;本 Shortcut 只列已知 doc folder/workspace 的直接子节点" ], "confirmation": "not_required", "effect": "read", @@ -2094,14 +2094,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "candidates": [ { "value": "列出文件夹或知识库下的直接子节点", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。" } ] }, @@ -2123,21 +2123,21 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "全局或钉盘目录浏览优先 drive list,知识库节点树优先 wiki node list;本 Shortcut 只列已知 doc folder/workspace 的直接子节点" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "全局或钉盘目录浏览优先 drive list,知识库节点树优先 wiki node list;本 Shortcut 只列已知 doc folder/workspace 的直接子节点" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。" } ] }, @@ -2181,7 +2181,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "candidates": [ { "value": [ @@ -2191,7 +2191,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。" } ] }, @@ -2278,7 +2278,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。" } ] }, @@ -2305,7 +2305,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "candidates": [ { "value": [ @@ -2314,7 +2314,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。" } ] } @@ -2340,7 +2340,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive move;要保留原位置副本用 copy;目标位置不明确或未确认时不要移动" ], "confirmation": "user_required", "effect": "write", @@ -2354,14 +2354,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "candidates": [ { "value": "移动文档/文件到指定文件夹或知识库", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。" } ] }, @@ -2383,21 +2383,21 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive move;要保留原位置副本用 copy;目标位置不明确或未确认时不要移动" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive move;要保留原位置副本用 copy;目标位置不明确或未确认时不要移动" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。" } ] }, @@ -2440,7 +2440,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "candidates": [ { "value": [ @@ -2449,7 +2449,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。" } ] }, @@ -2536,7 +2536,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。" } ] }, @@ -2563,7 +2563,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "candidates": [ { "value": [ @@ -2572,7 +2572,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。" } ] } @@ -2598,7 +2598,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只有一个关键词且只要紧凑标题/URL/type/token 投影时优先 +find-doc;目标已给 nodeId/URL 时不要再搜索" ], "confirmation": "not_required", "effect": "read", @@ -2613,14 +2613,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "candidates": [ { "value": "按关键词搜索有权限的文档 (不传则返回最近访问)", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。" } ] }, @@ -2642,21 +2642,21 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只有一个关键词且只要紧凑标题/URL/type/token 投影时优先 +find-doc;目标已给 nodeId/URL 时不要再搜索" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只有一个关键词且只要紧凑标题/URL/type/token 投影时优先 +find-doc;目标已给 nodeId/URL 时不要再搜索" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。" } ] }, @@ -2700,7 +2700,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "candidates": [ { "value": [ @@ -2710,7 +2710,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。" } ] }, @@ -2797,7 +2797,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。" } ] }, @@ -2824,7 +2824,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "candidates": [ { "value": [ @@ -2833,7 +2833,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。" } ] } @@ -2859,7 +2859,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "同名人员未消歧、缺少真实文档 URL 或用户未确认时不要发送;本命令不授予文档权限,授权应走 drive permission" ], "confirmation": "user_required", "effect": "write", @@ -2873,14 +2873,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "candidates": [ { "value": "按姓名把文档链接私信发给某人(自动解析 userId)", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。" } ] }, @@ -2902,21 +2902,21 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "同名人员未消歧、缺少真实文档 URL 或用户未确认时不要发送;本命令不授予文档权限,授权应走 drive permission" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "同名人员未消歧、缺少真实文档 URL 或用户未确认时不要发送;本命令不授予文档权限,授权应走 drive permission" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。" } ] }, @@ -2959,7 +2959,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "candidates": [ { "value": [ @@ -2968,7 +2968,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。" } ] }, @@ -3055,7 +3055,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。" } ] }, @@ -3082,7 +3082,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "candidates": [ { "value": [ @@ -3091,7 +3091,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。" } ] } @@ -3891,7 +3891,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只查看历史用 +version-list,只保存当前快照用 +version-save;版本号未核实、用户未确认或只需改单块时不要回滚" ], "confirmation": "user_required", "effect": "destructive", @@ -3905,14 +3905,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "candidates": [ { "value": "回滚文档到指定历史版本", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。" } ] }, @@ -3934,21 +3934,21 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只查看历史用 +version-list,只保存当前快照用 +version-save;版本号未核实、用户未确认或只需改单块时不要回滚" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只查看历史用 +version-list,只保存当前快照用 +version-save;版本号未核实、用户未确认或只需改单块时不要回滚" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。" } ] }, @@ -3991,7 +3991,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "candidates": [ { "value": [ @@ -4000,7 +4000,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。" } ] }, @@ -4087,7 +4087,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。" } ] }, @@ -4114,7 +4114,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "candidates": [ { "value": [ @@ -4123,7 +4123,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts." + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。" } ] } @@ -7495,35 +7495,35 @@ ] }, "doc create": { - "agent_summary": "创建一篇新的在线文档", + "agent_summary": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc", "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ "创建表格/脑图/白板/多维表/演示改用 dws wiki node create --type \u003ctype\u003e(勿用 doc create)", - "在知识库建空节点实体也可用 wiki node create;本命令侧重可写初始内容的 adoc", - "导入本地 Word/Markdown 为在线文档改用 dws doc import(若可用)或 upload --convert" + "只管理知识库空节点或层级时用 wiki node create;本命令侧重创建并写入 adoc", + "导入本地 Word/Markdown 并保留服务端转换语义时用 dws doc import;不要用自写分片脚本替代原生 create" ], "confirmation": "not_required", "effect": "write", "effect_source": "command-verb", "examples": [ "dws doc create --name \"项目周报\" --format json", - "dws doc create --name \"Q1 总结\" --content \"# Q1 总结\" --folder \u003cFOLDER_ID\u003e --format json" + "dws doc create --name \"Q1 总结\" --content-file ./q1.md --workspace \u003cWORKSPACE_ID\u003e --format json" ], "field_provenance": { "agent_summary": { - "value": "创建一篇新的在线文档", + "value": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "candidates": [ { - "value": "创建一篇新的在线文档", + "value": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" } ] }, @@ -7552,24 +7552,24 @@ "avoid_when": { "value": [ "创建表格/脑图/白板/多维表/演示改用 dws wiki node create --type \u003ctype\u003e(勿用 doc create)", - "在知识库建空节点实体也可用 wiki node create;本命令侧重可写初始内容的 adoc", - "导入本地 Word/Markdown 为在线文档改用 dws doc import(若可用)或 upload --convert" + "只管理知识库空节点或层级时用 wiki node create;本命令侧重创建并写入 adoc", + "导入本地 Word/Markdown 并保留服务端转换语义时用 dws doc import;不要用自写分片脚本替代原生 create" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "candidates": [ { "value": [ "创建表格/脑图/白板/多维表/演示改用 dws wiki node create --type \u003ctype\u003e(勿用 doc create)", - "在知识库建空节点实体也可用 wiki node create;本命令侧重可写初始内容的 adoc", - "导入本地 Word/Markdown 为在线文档改用 dws doc import(若可用)或 upload --convert" + "只管理知识库空节点或层级时用 wiki node create;本命令侧重创建并写入 adoc", + "导入本地 Word/Markdown 并保留服务端转换语义时用 dws doc import;不要用自写分片脚本替代原生 create" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" } ] }, @@ -7604,22 +7604,22 @@ "examples": { "value": [ "dws doc create --name \"项目周报\" --format json", - "dws doc create --name \"Q1 总结\" --content \"# Q1 总结\" --folder \u003cFOLDER_ID\u003e --format json" + "dws doc create --name \"Q1 总结\" --content-file ./q1.md --workspace \u003cWORKSPACE_ID\u003e --format json" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "candidates": [ { "value": [ "dws doc create --name \"项目周报\" --format json", - "dws doc create --name \"Q1 总结\" --content \"# Q1 总结\" --folder \u003cFOLDER_ID\u003e --format json" + "dws doc create --name \"Q1 总结\" --content-file ./q1.md --workspace \u003cWORKSPACE_ID\u003e --format json" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" } ] }, @@ -7698,7 +7698,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" } ] }, @@ -7718,23 +7718,23 @@ }, "use_when": { "value": [ - "用户要新建一篇文字在线文档(adoc),可空文档或带初始 Markdown 时", - "创建到指定文件夹 --folder、知识库根 --workspace,或默认「我的文档」根目录时" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "candidates": [ { "value": [ - "用户要新建一篇文字在线文档(adoc),可空文档或带初始 Markdown 时", - "创建到指定文件夹 --folder、知识库根 --workspace,或默认「我的文档」根目录时" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。" } ] } @@ -7766,8 +7766,8 @@ "structured-hint:internal/cli/schema_hints/selection-review.json#doc.create_document" ], "use_when": [ - "用户要新建一篇文字在线文档(adoc),可空文档或带初始 Markdown 时", - "创建到指定文件夹 --folder、知识库根 --workspace,或默认「我的文档」根目录时" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" ] }, "doc delete": { @@ -9377,13 +9377,14 @@ ] }, "doc info": { - "agent_summary": "获取文档元信息(标题/类型/创建者/权限等)", + "agent_summary": "在已确认是 ALIDOC 后读取文档专属元信息", "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "已确认是 adoc 且只要正文改用 dws doc read", + "原始 alidocs URL 的类型探测、extension 路由或可靠 fileSize 使用 dws drive info;不要先猜是文档", + "已确认是 adoc 且只要正文时改用 dws doc read", "只要目录列表改用 dws drive list / wiki node list", - "需要可靠文件大小 fileSize 时改用 dws drive info;文档元信息接口可能不返回大小" + "普通文件、电子表格或 AI 表格不使用本命令" ], "confirmation": "not_required", "effect": "read", @@ -9394,18 +9395,18 @@ ], "field_provenance": { "agent_summary": { - "value": "获取文档元信息(标题/类型/创建者/权限等)", + "value": "在已确认是 ALIDOC 后读取文档专属元信息", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "candidates": [ { - "value": "获取文档元信息(标题/类型/创建者/权限等)", + "value": "在已确认是 ALIDOC 后读取文档专属元信息", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。" } ] }, @@ -9433,25 +9434,27 @@ }, "avoid_when": { "value": [ - "已确认是 adoc 且只要正文改用 dws doc read", + "原始 alidocs URL 的类型探测、extension 路由或可靠 fileSize 使用 dws drive info;不要先猜是文档", + "已确认是 adoc 且只要正文时改用 dws doc read", "只要目录列表改用 dws drive list / wiki node list", - "需要可靠文件大小 fileSize 时改用 dws drive info;文档元信息接口可能不返回大小" + "普通文件、电子表格或 AI 表格不使用本命令" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "candidates": [ { "value": [ - "已确认是 adoc 且只要正文改用 dws doc read", + "原始 alidocs URL 的类型探测、extension 路由或可靠 fileSize 使用 dws drive info;不要先猜是文档", + "已确认是 adoc 且只要正文时改用 dws doc read", "只要目录列表改用 dws drive list / wiki node list", - "需要可靠文件大小 fileSize 时改用 dws drive info;文档元信息接口可能不返回大小" + "普通文件、电子表格或 AI 表格不使用本命令" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。" } ] }, @@ -9491,7 +9494,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "candidates": [ { "value": [ @@ -9501,7 +9504,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。" } ] }, @@ -9580,7 +9583,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。" } ] }, @@ -9600,23 +9603,23 @@ }, "use_when": { "value": [ - "用户要查看文档/节点元信息(标题、类型、创建者、权限)时", - "准备读内容前必须先看 contentType/extension 以路由到 read/sheet/aitable/download 时" + "drive info 已确认是 ALIDOC,用户还要标题、创建者、权限或 docUrl 等文档专属元信息时", + "创建响应只有 nodeId、缺少 docUrl,需要补查文档链接时" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "candidates": [ { "value": [ - "用户要查看文档/节点元信息(标题、类型、创建者、权限)时", - "准备读内容前必须先看 contentType/extension 以路由到 read/sheet/aitable/download 时" + "drive info 已确认是 ALIDOC,用户还要标题、创建者、权限或 docUrl 等文档专属元信息时", + "创建响应只有 nodeId、缺少 docUrl,需要补查文档链接时" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。" } ] } @@ -9647,8 +9650,8 @@ "structured-hint:internal/cli/schema_hints/selection-review.json#doc.get_document_info" ], "use_when": [ - "用户要查看文档/节点元信息(标题、类型、创建者、权限)时", - "准备读内容前必须先看 contentType/extension 以路由到 read/sheet/aitable/download 时" + "drive info 已确认是 ALIDOC,用户还要标题、创建者、权限或 docUrl 等文档专属元信息时", + "创建响应只有 nodeId、缺少 docUrl,需要补查文档链接时" ] }, "doc list": { @@ -11752,7 +11755,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "非 adoc(表格/多维表/普通文件)不要用本命令;先 doc info 再路由", + "原始 alidocs URL 类型未知或目标不是 adoc 时先用 drive info 探测并路由;表格/多维表/普通文件不要用本命令", "要元信息用 doc info;要块结构用 doc block list", "Markdown 为有损投影:保形复制模板请用 doc copy,不要 read→create" ], @@ -11769,14 +11772,14 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "candidates": [ { "value": "读取完整文档内容,或按 outline/range/section/tags 获取 JSONML fragment", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。" } ] }, @@ -11804,25 +11807,25 @@ }, "avoid_when": { "value": [ - "非 adoc(表格/多维表/普通文件)不要用本命令;先 doc info 再路由", + "原始 alidocs URL 类型未知或目标不是 adoc 时先用 drive info 探测并路由;表格/多维表/普通文件不要用本命令", "要元信息用 doc info;要块结构用 doc block list", "Markdown 为有损投影:保形复制模板请用 doc copy,不要 read→create" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "candidates": [ { "value": [ - "非 adoc(表格/多维表/普通文件)不要用本命令;先 doc info 再路由", + "原始 alidocs URL 类型未知或目标不是 adoc 时先用 drive info 探测并路由;表格/多维表/普通文件不要用本命令", "要元信息用 doc info;要块结构用 doc block list", "Markdown 为有损投影:保形复制模板请用 doc copy,不要 read→create" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。" } ] }, @@ -11878,7 +11881,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "candidates": [ { "value": [ @@ -11888,7 +11891,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。" } ] }, @@ -11983,7 +11986,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。" } ] }, @@ -12011,25 +12014,25 @@ }, "use_when": { "value": [ - "用户要读取钉钉在线文字文档(adoc)正文(Markdown)时", - "用户直接粘贴文档 URL 且无其他指令时(默认读内容)", + "已由 drive info 确认 extension=adoc,用户要读取正文(Markdown)时", + "用户提供已知 adoc nodeId/URL,且要读取内容或抽取指定章节时", "只需标题大纲、指定块区间/单块或特定 JSONML tags 时使用 --content-format jsonml 与 --scope" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "candidates": [ { "value": [ - "用户要读取钉钉在线文字文档(adoc)正文(Markdown)时", - "用户直接粘贴文档 URL 且无其他指令时(默认读内容)", + "已由 drive info 确认 extension=adoc,用户要读取正文(Markdown)时", + "用户提供已知 adoc nodeId/URL,且要读取内容或抽取指定章节时", "只需标题大纲、指定块区间/单块或特定 JSONML tags 时使用 --content-format jsonml 与 --scope" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。" } ] } @@ -12060,8 +12063,8 @@ "structured-hint:internal/cli/schema_hints/selection-review.json#doc.get_document_content" ], "use_when": [ - "用户要读取钉钉在线文字文档(adoc)正文(Markdown)时", - "用户直接粘贴文档 URL 且无其他指令时(默认读内容)", + "已由 drive info 确认 extension=adoc,用户要读取正文(Markdown)时", + "用户提供已知 adoc nodeId/URL,且要读取内容或抽取指定章节时", "只需标题大纲、指定块区间/单块或特定 JSONML tags 时使用 --content-format jsonml 与 --scope" ] }, @@ -14665,13 +14668,14 @@ ] }, "doc update": { - "agent_summary": "更新文档内容(追加 / 覆盖;覆盖需 --yes)", + "agent_summary": "用原生自动分片管道追加或整篇覆盖 adoc 内容", "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "目标不是 adoc 或只要改单个块时改用 doc block update", + "只在末尾补一小段纯文本优先 +doc-append;只改一个块用 doc block update", + "目标不是 adoc 时按 drive info 的 extension 切对应产品", "覆盖模式用户未确认前不要执行;可先 --dry-run 预览", - "创建新文档用 doc create,不要用 update 冒充创建" + "创建新文档用 doc create;不要预先手工分片或循环重试覆盖" ], "confirmation": "not_required", "effect": "write", @@ -14682,18 +14686,18 @@ ], "field_provenance": { "agent_summary": { - "value": "更新文档内容(追加 / 覆盖;覆盖需 --yes)", + "value": "用原生自动分片管道追加或整篇覆盖 adoc 内容", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "candidates": [ { - "value": "更新文档内容(追加 / 覆盖;覆盖需 --yes)", + "value": "用原生自动分片管道追加或整篇覆盖 adoc 内容", "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。" } ] }, @@ -14721,25 +14725,27 @@ }, "avoid_when": { "value": [ - "目标不是 adoc 或只要改单个块时改用 doc block update", + "只在末尾补一小段纯文本优先 +doc-append;只改一个块用 doc block update", + "目标不是 adoc 时按 drive info 的 extension 切对应产品", "覆盖模式用户未确认前不要执行;可先 --dry-run 预览", - "创建新文档用 doc create,不要用 update 冒充创建" + "创建新文档用 doc create;不要预先手工分片或循环重试覆盖" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "candidates": [ { "value": [ - "目标不是 adoc 或只要改单个块时改用 doc block update", + "只在末尾补一小段纯文本优先 +doc-append;只改一个块用 doc block update", + "目标不是 adoc 时按 drive info 的 extension 切对应产品", "覆盖模式用户未确认前不要执行;可先 --dry-run 预览", - "创建新文档用 doc create,不要用 update 冒充创建" + "创建新文档用 doc create;不要预先手工分片或循环重试覆盖" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。" } ] }, @@ -14795,7 +14801,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "candidates": [ { "value": [ @@ -14805,7 +14811,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。" } ] }, @@ -14884,7 +14890,7 @@ "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": false, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。" } ] }, @@ -14912,25 +14918,25 @@ }, "use_when": { "value": [ - "用户要向已有 adoc 追加内容时用 --mode append(更安全)", + "用户要向已有 adoc 追加长、多行或文件内容时用 --mode append + --content-file;CLI 自动分片", "用户明确要求整篇覆盖替换时用 --mode overwrite(破坏性)", "append 且要插到第 N 个 block 前时加 --index N(先 block list)" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "candidates": [ { "value": [ - "用户要向已有 adoc 追加内容时用 --mode append(更安全)", + "用户要向已有 adoc 追加长、多行或文件内容时用 --mode append + --content-file;CLI 自动分片", "用户明确要求整篇覆盖替换时用 --mode overwrite(破坏性)", "append 且要插到第 N 个 block 前时加 --index N(先 block list)" ], "source": "internal/cli/schema_hints/selection/doc.json", "precedence": "reviewed_explicit", "selected": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。" + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。" } ] } @@ -14962,7 +14968,7 @@ "structured-hint:internal/cli/schema_hints/selection-review.json#doc.update_document" ], "use_when": [ - "用户要向已有 adoc 追加内容时用 --mode append(更安全)", + "用户要向已有 adoc 追加长、多行或文件内容时用 --mode append + --content-file;CLI 自动分片", "用户明确要求整篇覆盖替换时用 --mode overwrite(破坏性)", "append 且要插到第 N 个 block 前时加 --index N(先 block list)" ] diff --git a/internal/cli/schema_agent_metadata/index.json b/internal/cli/schema_agent_metadata/index.json index fb72b4b4..e5c898ce 100644 --- a/internal/cli/schema_agent_metadata/index.json +++ b/internal/cli/schema_agent_metadata/index.json @@ -1,6 +1,6 @@ { "version": 1, - "source_hash": "sha256:add7be57e9ed6b69783be5df6d321c83ebe3b9c71a934e9991d91ee41fea23f4", + "source_hash": "sha256:709741e6cd06537bcf0c4bfb6a8930a14f9a43108128e1064b712bd9e2fbaa42", "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", "coverage": { "surface_products": 26, diff --git a/internal/cli/schema_agent_metadata_audit.json b/internal/cli/schema_agent_metadata_audit.json index f265adaf..8baac4bc 100644 --- a/internal/cli/schema_agent_metadata_audit.json +++ b/internal/cli/schema_agent_metadata_audit.json @@ -1,6 +1,6 @@ { "version": 1, - "source_hash": "sha256:add7be57e9ed6b69783be5df6d321c83ebe3b9c71a934e9991d91ee41fea23f4", + "source_hash": "sha256:709741e6cd06537bcf0c4bfb6a8930a14f9a43108128e1064b712bd9e2fbaa42", "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", "source_files": 160, "hint_files": 54, diff --git a/internal/cli/schema_catalog/catalog.json b/internal/cli/schema_catalog/catalog.json index b5bc81cf..9a0d8aea 100644 --- a/internal/cli/schema_catalog/catalog.json +++ b/internal/cli/schema_catalog/catalog.json @@ -1,12 +1,12 @@ { "version": 1, "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", - "source_hash": "sha256:2bdcd3ac9d59f625cd4ed1e97938357b68ac483ef213a9e739baac67e3a1db3b", + "source_hash": "sha256:399dcd69d9f98e98ef9668edb6d965b59f5f61f9964f9546fb5796fee9b08865", "catalog": { "agent_metadata": { "products_with_metadata": 26, "source": "embedded-skill-metadata", - "source_hash": "sha256:add7be57e9ed6b69783be5df6d321c83ebe3b9c71a934e9991d91ee41fea23f4", + "source_hash": "sha256:709741e6cd06537bcf0c4bfb6a8930a14f9a43108128e1064b712bd9e2fbaa42", "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", "surface_products": 26, "surface_tools": 875, @@ -15377,13 +15377,13 @@ }, { "agent_metadata_source": "embedded-skill-metadata", - "agent_summary": "创建一篇新的在线文档", + "agent_summary": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc", "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ "创建表格/脑图/白板/多维表/演示改用 dws wiki node create --type \u003ctype\u003e(勿用 doc create)", - "在知识库建空节点实体也可用 wiki node create;本命令侧重可写初始内容的 adoc", - "导入本地 Word/Markdown 为在线文档改用 dws doc import(若可用)或 upload --convert" + "只管理知识库空节点或层级时用 wiki node create;本命令侧重创建并写入 adoc", + "导入本地 Word/Markdown 并保留服务端转换语义时用 dws doc import;不要用自写分片脚本替代原生 create" ], "canonical_path": "doc.create_document", "cli_name": "create", @@ -15404,8 +15404,8 @@ "risk": "medium", "title": "创建文档", "use_when": [ - "用户要新建一篇文字在线文档(adoc),可空文档或带初始 Markdown 时", - "创建到指定文件夹 --folder、知识库根 --workspace,或默认「我的文档」根目录时" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" ] }, { @@ -15665,7 +15665,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "非 adoc(表格/多维表/普通文件)不要用本命令;先 doc info 再路由", + "原始 alidocs URL 类型未知或目标不是 adoc 时先用 drive info 探测并路由;表格/多维表/普通文件不要用本命令", "要元信息用 doc info;要块结构用 doc block list", "Markdown 为有损投影:保形复制模板请用 doc copy,不要 read→create" ], @@ -15688,20 +15688,21 @@ "risk": "low", "title": "读取文档内容 (Markdown)", "use_when": [ - "用户要读取钉钉在线文字文档(adoc)正文(Markdown)时", - "用户直接粘贴文档 URL 且无其他指令时(默认读内容)", + "已由 drive info 确认 extension=adoc,用户要读取正文(Markdown)时", + "用户提供已知 adoc nodeId/URL,且要读取内容或抽取指定章节时", "只需标题大纲、指定块区间/单块或特定 JSONML tags 时使用 --content-format jsonml 与 --scope" ] }, { "agent_metadata_source": "embedded-skill-metadata", - "agent_summary": "获取文档元信息(标题/类型/创建者/权限等)", + "agent_summary": "在已确认是 ALIDOC 后读取文档专属元信息", "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "已确认是 adoc 且只要正文改用 dws doc read", + "原始 alidocs URL 的类型探测、extension 路由或可靠 fileSize 使用 dws drive info;不要先猜是文档", + "已确认是 adoc 且只要正文时改用 dws doc read", "只要目录列表改用 dws drive list / wiki node list", - "需要可靠文件大小 fileSize 时改用 dws drive info;文档元信息接口可能不返回大小" + "普通文件、电子表格或 AI 表格不使用本命令" ], "canonical_path": "doc.get_document_info", "cli_name": "info", @@ -15722,8 +15723,8 @@ "risk": "low", "title": "获取文档元信息", "use_when": [ - "用户要查看文档/节点元信息(标题、类型、创建者、权限)时", - "准备读内容前必须先看 contentType/extension 以路由到 read/sheet/aitable/download 时" + "drive info 已确认是 ALIDOC,用户还要标题、创建者、权限或 docUrl 等文档专属元信息时", + "创建响应只有 nodeId、缺少 docUrl,需要补查文档链接时" ] }, { @@ -16244,7 +16245,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive copy;要搬走原件用 move;复制后必须从真实返回取副本 nodeId,禁止继续编辑源文档" ], "canonical_path": "doc.shortcut_copy", "cli_name": "+copy", @@ -16270,7 +16271,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "长、多行、表格或文件内容使用 doc update --mode append --content-file;指定位置或富结构使用 block insert;不要跳过 user_required 确认" ], "canonical_path": "doc.shortcut_doc_append", "cli_name": "+doc-append", @@ -16322,7 +16323,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "用户要直接拿到本地 docx/markdown/pdf 文件时使用一体化 dws doc export;不要默认手工编排 submit/get 轮询" ], "canonical_path": "doc.shortcut_export_submit", "cli_name": "+export-submit", @@ -16348,7 +16349,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "需要最近访问、extension/时间/创建者等组合过滤时使用 +search;目标已给 nodeId/URL 时直接进入 info/read,不再搜索" ], "canonical_path": "doc.shortcut_find_doc", "cli_name": "+find-doc", @@ -16374,7 +16375,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "全局或钉盘目录浏览优先 drive list,知识库节点树优先 wiki node list;本 Shortcut 只列已知 doc folder/workspace 的直接子节点" ], "canonical_path": "doc.shortcut_list", "cli_name": "+list", @@ -16400,7 +16401,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive move;要保留原位置副本用 copy;目标位置不明确或未确认时不要移动" ], "canonical_path": "doc.shortcut_move", "cli_name": "+move", @@ -16426,7 +16427,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只有一个关键词且只要紧凑标题/URL/type/token 投影时优先 +find-doc;目标已给 nodeId/URL 时不要再搜索" ], "canonical_path": "doc.shortcut_search", "cli_name": "+search", @@ -16452,7 +16453,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "同名人员未消歧、缺少真实文档 URL 或用户未确认时不要发送;本命令不授予文档权限,授权应走 drive permission" ], "canonical_path": "doc.shortcut_share_doc", "cli_name": "+share-doc", @@ -16556,7 +16557,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只查看历史用 +version-list,只保存当前快照用 +version-save;版本号未核实、用户未确认或只需改单块时不要回滚" ], "canonical_path": "doc.shortcut_version_revert", "cli_name": "+version-revert", @@ -16820,13 +16821,14 @@ }, { "agent_metadata_source": "embedded-skill-metadata", - "agent_summary": "更新文档内容(追加 / 覆盖;覆盖需 --yes)", + "agent_summary": "用原生自动分片管道追加或整篇覆盖 adoc 内容", "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "目标不是 adoc 或只要改单个块时改用 doc block update", + "只在末尾补一小段纯文本优先 +doc-append;只改一个块用 doc block update", + "目标不是 adoc 时按 drive info 的 extension 切对应产品", "覆盖模式用户未确认前不要执行;可先 --dry-run 预览", - "创建新文档用 doc create,不要用 update 冒充创建" + "创建新文档用 doc create;不要预先手工分片或循环重试覆盖" ], "canonical_path": "doc.update_document", "cli_name": "update", @@ -16847,7 +16849,7 @@ "risk": "medium", "title": "更新文档内容", "use_when": [ - "用户要向已有 adoc 追加内容时用 --mode append(更安全)", + "用户要向已有 adoc 追加长、多行或文件内容时用 --mode append + --content-file;CLI 自动分片", "用户明确要求整篇覆盖替换时用 --mode overwrite(破坏性)", "append 且要插到第 N 个 block 前时加 --index N(先 block list)" ] diff --git a/internal/cli/schema_catalog/tools/doc.json b/internal/cli/schema_catalog/tools/doc.json index 9397637f..7b9aef61 100644 --- a/internal/cli/schema_catalog/tools/doc.json +++ b/internal/cli/schema_catalog/tools/doc.json @@ -2316,13 +2316,13 @@ "structured-hint:internal/cli/schema_hints/products/doc.json", "structured-hint:internal/cli/schema_hints/selection-review.json#doc.create_document" ], - "agent_summary": "创建一篇新的在线文档", + "agent_summary": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc", "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ "创建表格/脑图/白板/多维表/演示改用 dws wiki node create --type \u003ctype\u003e(勿用 doc create)", - "在知识库建空节点实体也可用 wiki node create;本命令侧重可写初始内容的 adoc", - "导入本地 Word/Markdown 为在线文档改用 dws doc import(若可用)或 upload --convert" + "只管理知识库空节点或层级时用 wiki node create;本命令侧重创建并写入 adoc", + "导入本地 Word/Markdown 并保留服务端转换语义时用 dws doc import;不要用自写分片脚本替代原生 create" ], "canonical_path": "doc.create_document", "cli_name": "create", @@ -2334,24 +2334,24 @@ "effect_source": "command-verb", "examples": [ "dws doc create --name \"项目周报\" --format json", - "dws doc create --name \"Q1 总结\" --content \"# Q1 总结\" --folder \u003cFOLDER_ID\u003e --format json" + "dws doc create --name \"Q1 总结\" --content-file ./q1.md --workspace \u003cWORKSPACE_ID\u003e --format json" ], "field_provenance": { "agent_summary": { "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", - "value": "创建一篇新的在线文档" + "value": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc" } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", - "value": "创建一篇新的在线文档" + "value": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc" }, "availability": { "candidates": [ @@ -2379,24 +2379,24 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "创建表格/脑图/白板/多维表/演示改用 dws wiki node create --type \u003ctype\u003e(勿用 doc create)", - "在知识库建空节点实体也可用 wiki node create;本命令侧重可写初始内容的 adoc", - "导入本地 Word/Markdown 为在线文档改用 dws doc import(若可用)或 upload --convert" + "只管理知识库空节点或层级时用 wiki node create;本命令侧重创建并写入 adoc", + "导入本地 Word/Markdown 并保留服务端转换语义时用 dws doc import;不要用自写分片脚本替代原生 create" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "创建表格/脑图/白板/多维表/演示改用 dws wiki node create --type \u003ctype\u003e(勿用 doc create)", - "在知识库建空节点实体也可用 wiki node create;本命令侧重可写初始内容的 adoc", - "导入本地 Word/Markdown 为在线文档改用 dws doc import(若可用)或 upload --convert" + "只管理知识库空节点或层级时用 wiki node create;本命令侧重创建并写入 adoc", + "导入本地 Word/Markdown 并保留服务端转换语义时用 dws doc import;不要用自写分片脚本替代原生 create" ] }, "canonical_path": { @@ -2467,22 +2467,22 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc create --name \"项目周报\" --format json", - "dws doc create --name \"Q1 总结\" --content \"# Q1 总结\" --folder \u003cFOLDER_ID\u003e --format json" + "dws doc create --name \"Q1 总结\" --content-file ./q1.md --workspace \u003cWORKSPACE_ID\u003e --format json" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc create --name \"项目周报\" --format json", - "dws doc create --name \"Q1 总结\" --content \"# Q1 总结\" --folder \u003cFOLDER_ID\u003e --format json" + "dws doc create --name \"Q1 总结\" --content-file ./q1.md --workspace \u003cWORKSPACE_ID\u003e --format json" ] }, "idempotency": { @@ -2572,7 +2572,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -2622,22 +2622,22 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "用户要新建一篇文字在线文档(adoc),可空文档或带初始 Markdown 时", - "创建到指定文件夹 --folder、知识库根 --workspace,或默认「我的文档」根目录时" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "用户要新建一篇文字在线文档(adoc),可空文档或带初始 Markdown 时", - "创建到指定文件夹 --folder、知识库根 --workspace,或默认「我的文档」根目录时" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" ] } }, @@ -3335,8 +3335,8 @@ "source": "reviewed_command_registry", "title": "创建文档", "use_when": [ - "用户要新建一篇文字在线文档(adoc),可空文档或带初始 Markdown 时", - "创建到指定文件夹 --folder、知识库根 --workspace,或默认「我的文档」根目录时" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" ] }, "doc.create_file": { @@ -8738,7 +8738,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "非 adoc(表格/多维表/普通文件)不要用本命令;先 doc info 再路由", + "原始 alidocs URL 类型未知或目标不是 adoc 时先用 drive info 探测并路由;表格/多维表/普通文件不要用本命令", "要元信息用 doc info;要块结构用 doc block list", "Markdown 为有损投影:保形复制模板请用 doc copy,不要 read→create" ], @@ -8759,7 +8759,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "读取完整文档内容,或按 outline/range/section/tags 获取 JSONML fragment" @@ -8767,7 +8767,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "读取完整文档内容,或按 outline/range/section/tags 获取 JSONML fragment" }, @@ -8797,11 +8797,11 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "非 adoc(表格/多维表/普通文件)不要用本命令;先 doc info 再路由", + "原始 alidocs URL 类型未知或目标不是 adoc 时先用 drive info 探测并路由;表格/多维表/普通文件不要用本命令", "要元信息用 doc info;要块结构用 doc block list", "Markdown 为有损投影:保形复制模板请用 doc copy,不要 read→create" ] @@ -8809,10 +8809,10 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "非 adoc(表格/多维表/普通文件)不要用本命令;先 doc info 再路由", + "原始 alidocs URL 类型未知或目标不是 adoc 时先用 drive info 探测并路由;表格/多维表/普通文件不要用本命令", "要元信息用 doc info;要块结构用 doc block list", "Markdown 为有损投影:保形复制模板请用 doc copy,不要 read→create" ] @@ -8909,7 +8909,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -8920,7 +8920,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc read --node \u003cDOC_ID\u003e --format json", @@ -9030,7 +9030,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -9088,23 +9088,23 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "用户要读取钉钉在线文字文档(adoc)正文(Markdown)时", - "用户直接粘贴文档 URL 且无其他指令时(默认读内容)", + "已由 drive info 确认 extension=adoc,用户要读取正文(Markdown)时", + "用户提供已知 adoc nodeId/URL,且要读取内容或抽取指定章节时", "只需标题大纲、指定块区间/单块或特定 JSONML tags 时使用 --content-format jsonml 与 --scope" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "用户要读取钉钉在线文字文档(adoc)正文(Markdown)时", - "用户直接粘贴文档 URL 且无其他指令时(默认读内容)", + "已由 drive info 确认 extension=adoc,用户要读取正文(Markdown)时", + "用户提供已知 adoc nodeId/URL,且要读取内容或抽取指定章节时", "只需标题大纲、指定块区间/单块或特定 JSONML tags 时使用 --content-format jsonml 与 --scope" ] } @@ -10022,8 +10022,8 @@ "source": "reviewed_command_registry", "title": "读取文档内容 (Markdown)", "use_when": [ - "用户要读取钉钉在线文字文档(adoc)正文(Markdown)时", - "用户直接粘贴文档 URL 且无其他指令时(默认读内容)", + "已由 drive info 确认 extension=adoc,用户要读取正文(Markdown)时", + "用户提供已知 adoc nodeId/URL,且要读取内容或抽取指定章节时", "只需标题大纲、指定块区间/单块或特定 JSONML tags 时使用 --content-format jsonml 与 --scope" ] }, @@ -10046,13 +10046,14 @@ "structured-hint:internal/cli/schema_hints/products/doc.json", "structured-hint:internal/cli/schema_hints/selection-review.json#doc.get_document_info" ], - "agent_summary": "获取文档元信息(标题/类型/创建者/权限等)", + "agent_summary": "在已确认是 ALIDOC 后读取文档专属元信息", "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "已确认是 adoc 且只要正文改用 dws doc read", + "原始 alidocs URL 的类型探测、extension 路由或可靠 fileSize 使用 dws drive info;不要先猜是文档", + "已确认是 adoc 且只要正文时改用 dws doc read", "只要目录列表改用 dws drive list / wiki node list", - "需要可靠文件大小 fileSize 时改用 dws drive info;文档元信息接口可能不返回大小" + "普通文件、电子表格或 AI 表格不使用本命令" ], "canonical_path": "doc.get_document_info", "cli_name": "info", @@ -10071,17 +10072,17 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", - "value": "获取文档元信息(标题/类型/创建者/权限等)" + "value": "在已确认是 ALIDOC 后读取文档专属元信息" } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", - "value": "获取文档元信息(标题/类型/创建者/权限等)" + "value": "在已确认是 ALIDOC 后读取文档专属元信息" }, "availability": { "candidates": [ @@ -10109,24 +10110,26 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "已确认是 adoc 且只要正文改用 dws doc read", + "原始 alidocs URL 的类型探测、extension 路由或可靠 fileSize 使用 dws drive info;不要先猜是文档", + "已确认是 adoc 且只要正文时改用 dws doc read", "只要目录列表改用 dws drive list / wiki node list", - "需要可靠文件大小 fileSize 时改用 dws drive info;文档元信息接口可能不返回大小" + "普通文件、电子表格或 AI 表格不使用本命令" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "已确认是 adoc 且只要正文改用 dws doc read", + "原始 alidocs URL 的类型探测、extension 路由或可靠 fileSize 使用 dws drive info;不要先猜是文档", + "已确认是 adoc 且只要正文时改用 dws doc read", "只要目录列表改用 dws drive list / wiki node list", - "需要可靠文件大小 fileSize 时改用 dws drive info;文档元信息接口可能不返回大小" + "普通文件、电子表格或 AI 表格不使用本命令" ] }, "canonical_path": { @@ -10197,7 +10200,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -10208,7 +10211,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc info --node \u003cDOC_ID\u003e --format json", @@ -10302,7 +10305,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -10352,22 +10355,22 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "用户要查看文档/节点元信息(标题、类型、创建者、权限)时", - "准备读内容前必须先看 contentType/extension 以路由到 read/sheet/aitable/download 时" + "drive info 已确认是 ALIDOC,用户还要标题、创建者、权限或 docUrl 等文档专属元信息时", + "创建响应只有 nodeId、缺少 docUrl,需要补查文档链接时" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "用户要查看文档/节点元信息(标题、类型、创建者、权限)时", - "准备读内容前必须先看 contentType/extension 以路由到 read/sheet/aitable/download 时" + "drive info 已确认是 ALIDOC,用户还要标题、创建者、权限或 docUrl 等文档专属元信息时", + "创建响应只有 nodeId、缺少 docUrl,需要补查文档链接时" ] } }, @@ -10501,8 +10504,8 @@ "source": "reviewed_command_registry", "title": "获取文档元信息", "use_when": [ - "用户要查看文档/节点元信息(标题、类型、创建者、权限)时", - "准备读内容前必须先看 contentType/extension 以路由到 read/sheet/aitable/download 时" + "drive info 已确认是 ALIDOC,用户还要标题、创建者、权限或 docUrl 等文档专属元信息时", + "创建响应只有 nodeId、缺少 docUrl,需要补查文档链接时" ] }, "doc.get_document_style": { @@ -24544,7 +24547,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive copy;要搬走原件用 move;复制后必须从真实返回取副本 nodeId,禁止继续编辑源文档" ], "canonical_path": "doc.shortcut_copy", "cli_name": "+copy", @@ -24562,7 +24565,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "复制文档/文件到指定文件夹或知识库" @@ -24570,7 +24573,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "复制文档/文件到指定文件夹或知识库" }, @@ -24594,20 +24597,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive copy;要搬走原件用 move;复制后必须从真实返回取副本 nodeId,禁止继续编辑源文档" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive copy;要搬走原件用 move;复制后必须从真实返回取副本 nodeId,禁止继续编辑源文档" ] }, "canonical_path": { @@ -24676,7 +24679,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -24686,7 +24689,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc +copy --node DOC_ID --folder TARGET_FOLDER_NODE_ID" @@ -24767,7 +24770,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -24813,7 +24816,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -24823,7 +24826,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "当你想保留原件、在另一个文件夹或知识库里生成一份文档/文件副本(例如以某篇文档为模板另存)时使用;输入源 node 与目标 folder/workspace,会实际创建一个副本。" @@ -25127,7 +25130,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "长、多行、表格或文件内容使用 doc update --mode append --content-file;指定位置或富结构使用 block insert;不要跳过 user_required 确认" ], "canonical_path": "doc.shortcut_doc_append", "cli_name": "+doc-append", @@ -25146,7 +25149,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "在文档末尾追加一段文本(安全追加,不改动原有内容)" @@ -25154,7 +25157,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "在文档末尾追加一段文本(安全追加,不改动原有内容)" }, @@ -25178,20 +25181,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "长、多行、表格或文件内容使用 doc update --mode append --content-file;指定位置或富结构使用 block insert;不要跳过 user_required 确认" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "长、多行、表格或文件内容使用 doc update --mode append --content-file;指定位置或富结构使用 block insert;不要跳过 user_required 确认" ] }, "canonical_path": { @@ -25260,7 +25263,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -25271,7 +25274,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc +doc-append --doc DOC_ID --text \"补充说明:本方案已评审通过。\"", @@ -25353,7 +25356,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -25399,7 +25402,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -25409,7 +25412,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "当你只想往一篇钉钉文档的最后面补一段文字、又不想动原有内容时使用;内部用文档更新的“追加(append)”模式,把你给的文本安全地拼到文档末尾,不需要你先去查文档块列表、算末尾位置或手工拼块结构。会真实写入文档内容。" @@ -26056,7 +26059,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "用户要直接拿到本地 docx/markdown/pdf 文件时使用一体化 dws doc export;不要默认手工编排 submit/get 轮询" ], "canonical_path": "doc.shortcut_export_submit", "cli_name": "+export-submit", @@ -26074,7 +26077,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "提交在线文档导出任务 (docx/markdown/pdf),返回 jobId" @@ -26082,7 +26085,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "提交在线文档导出任务 (docx/markdown/pdf),返回 jobId" }, @@ -26106,20 +26109,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "用户要直接拿到本地 docx/markdown/pdf 文件时使用一体化 dws doc export;不要默认手工编排 submit/get 轮询" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "用户要直接拿到本地 docx/markdown/pdf 文件时使用一体化 dws doc export;不要默认手工编排 submit/get 轮询" ] }, "canonical_path": { @@ -26188,7 +26191,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -26198,7 +26201,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc +export-submit --node DOC_ID --export-format markdown" @@ -26279,7 +26282,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -26325,7 +26328,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -26335,7 +26338,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "当你想把在线文档导出成 docx/markdown/pdf 文件(例如离线保存或外发)时使用;这是异步任务的第一步,输入 node 与 export-format 提交导出,返回 jobId,随后用 +export-get 轮询结果。" @@ -26595,7 +26598,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "需要最近访问、extension/时间/创建者等组合过滤时使用 +search;目标已给 nodeId/URL 时直接进入 info/read,不再搜索" ], "canonical_path": "doc.shortcut_find_doc", "cli_name": "+find-doc", @@ -26614,7 +26617,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "按关键词搜索云文档并投影关键字段(只读)" @@ -26622,7 +26625,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "按关键词搜索云文档并投影关键字段(只读)" }, @@ -26646,20 +26649,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "需要最近访问、extension/时间/创建者等组合过滤时使用 +search;目标已给 nodeId/URL 时直接进入 info/read,不再搜索" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "需要最近访问、extension/时间/创建者等组合过滤时使用 +search;目标已给 nodeId/URL 时直接进入 info/read,不再搜索" ] }, "canonical_path": { @@ -26728,7 +26731,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -26739,7 +26742,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc +find-doc --query 季度汇报", @@ -26821,7 +26824,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -26867,7 +26870,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -26877,7 +26880,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "当你只记得云文档标题或内容里的某个关键词,想快速按关键词找到匹配的文档、拿到它的标题、URL、类型和 token 以便后续查看或编辑,却不想拿到一大坨原始字段时使用;内部调用云文档的 search_documents 工具,把 --query 作为搜索关键词(keyword),可选地用 --limit 限制返回条数(pageSize),再在本地把每条命中结果精简为「标题、URL、类型、token」四个字段后打印。这是纯只读操作,只做搜索与本地投影,不会创建、修改或删除任何文档;未命中时提示「没搜到文档」。" @@ -27097,7 +27100,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "全局或钉盘目录浏览优先 drive list,知识库节点树优先 wiki node list;本 Shortcut 只列已知 doc folder/workspace 的直接子节点" ], "canonical_path": "doc.shortcut_list", "cli_name": "+list", @@ -27116,7 +27119,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "列出文件夹或知识库下的直接子节点" @@ -27124,7 +27127,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "列出文件夹或知识库下的直接子节点" }, @@ -27148,20 +27151,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "全局或钉盘目录浏览优先 drive list,知识库节点树优先 wiki node list;本 Shortcut 只列已知 doc folder/workspace 的直接子节点" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "全局或钉盘目录浏览优先 drive list,知识库节点树优先 wiki node list;本 Shortcut 只列已知 doc folder/workspace 的直接子节点" ] }, "canonical_path": { @@ -27230,7 +27233,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -27241,7 +27244,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc +list --folder DOC_FOLDER_NODE_ID", @@ -27323,7 +27326,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -27369,7 +27372,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -27379,7 +27382,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "当你已知某个文档文件夹或知识库的 ID、想浏览它下面直接包含的文档与子文件夹(不递归深层)以便逐层导航时使用;输入 folder 或 workspace,返回该层级的子节点列表。" @@ -27761,7 +27764,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive move;要保留原位置副本用 copy;目标位置不明确或未确认时不要移动" ], "canonical_path": "doc.shortcut_move", "cli_name": "+move", @@ -27779,7 +27782,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "移动文档/文件到指定文件夹或知识库" @@ -27787,7 +27790,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "移动文档/文件到指定文件夹或知识库" }, @@ -27811,20 +27814,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive move;要保留原位置副本用 copy;目标位置不明确或未确认时不要移动" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive move;要保留原位置副本用 copy;目标位置不明确或未确认时不要移动" ] }, "canonical_path": { @@ -27893,7 +27896,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -27903,7 +27906,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc +move --node DOC_ID --folder TARGET_FOLDER_NODE_ID" @@ -27984,7 +27987,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -28030,7 +28033,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -28040,7 +28043,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "当你要整理文档归属、把某篇文档/文件从当前位置挪到另一个文件夹或知识库(原位置不再保留)时使用;输入 node 与目标 folder/workspace,会实际改变文件的存放位置。" @@ -28344,7 +28347,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只有一个关键词且只要紧凑标题/URL/type/token 投影时优先 +find-doc;目标已给 nodeId/URL 时不要再搜索" ], "canonical_path": "doc.shortcut_search", "cli_name": "+search", @@ -28363,7 +28366,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "按关键词搜索有权限的文档 (不传则返回最近访问)" @@ -28371,7 +28374,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "按关键词搜索有权限的文档 (不传则返回最近访问)" }, @@ -28395,20 +28398,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只有一个关键词且只要紧凑标题/URL/type/token 投影时优先 +find-doc;目标已给 nodeId/URL 时不要再搜索" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只有一个关键词且只要紧凑标题/URL/type/token 投影时优先 +find-doc;目标已给 nodeId/URL 时不要再搜索" ] }, "canonical_path": { @@ -28477,7 +28480,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -28488,7 +28491,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc +search --query \"会议纪要\"", @@ -28570,7 +28573,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -28616,7 +28619,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -28626,7 +28629,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "当你只记得文档的标题或主题词、需要先定位到某篇钉钉文档拿到它的 nodeId/URL 以便后续阅读或编辑时使用;可按关键词、扩展名、创建/访问时间、创建者等条件过滤,不传关键词则返回最近访问的文档,返回匹配的文档列表。" @@ -29680,7 +29683,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "同名人员未消歧、缺少真实文档 URL 或用户未确认时不要发送;本命令不授予文档权限,授权应走 drive permission" ], "canonical_path": "doc.shortcut_share_doc", "cli_name": "+share-doc", @@ -29698,7 +29701,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "按姓名把文档链接私信发给某人(自动解析 userId)" @@ -29706,7 +29709,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "按姓名把文档链接私信发给某人(自动解析 userId)" }, @@ -29730,20 +29733,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "同名人员未消歧、缺少真实文档 URL 或用户未确认时不要发送;本命令不授予文档权限,授权应走 drive permission" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "同名人员未消歧、缺少真实文档 URL 或用户未确认时不要发送;本命令不授予文档权限,授权应走 drive permission" ] }, "canonical_path": { @@ -29812,7 +29815,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -29822,7 +29825,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc +share-doc --to 张三 --url https://docs.dingtalk.com/xxx --note \"帮忙过一下\"" @@ -29903,7 +29906,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -29949,7 +29952,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -29959,7 +29962,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "当你手上已经有一个文档链接、想直接私信发给某个人而不必先查 userId 时使用;内部先按姓名搜通讯录解析出唯一用户,再用 openDingTalkId 把链接拼成一条 Markdown 消息发出去,姓名匹配到多人时会列出候选让你区分。只发链接、不读取或改动文档本身,会真实发出消息。" @@ -32259,7 +32262,7 @@ "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只查看历史用 +version-list,只保存当前快照用 +version-save;版本号未核实、用户未确认或只需改单块时不要回滚" ], "canonical_path": "doc.shortcut_version_revert", "cli_name": "+version-revert", @@ -32277,7 +32280,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": "回滚文档到指定历史版本" @@ -32285,7 +32288,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": "回滚文档到指定历史版本" }, @@ -32309,20 +32312,20 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只查看历史用 +version-list,只保存当前快照用 +version-save;版本号未核实、用户未确认或只需改单块时不要回滚" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只查看历史用 +version-list,只保存当前快照用 +version-save;版本号未核实、用户未确认或只需改单块时不要回滚" ] }, "canonical_path": { @@ -32391,7 +32394,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -32401,7 +32404,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc +version-revert --node DOC_ID --version 3" @@ -32482,7 +32485,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -32528,7 +32531,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -32538,7 +32541,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "当文档被误改、你想把它整体恢复到某个历史版本时使用;先用 +version-list 找到目标版本号,再输入 node 与 version,会实际把文档内容覆盖回该版本,属于高风险写操作,需谨慎确认。" @@ -38098,13 +38101,14 @@ "structured-hint:internal/cli/schema_hints/products/doc.json", "structured-hint:internal/cli/schema_hints/selection-review.json#doc.update_document" ], - "agent_summary": "更新文档内容(追加 / 覆盖;覆盖需 --yes)", + "agent_summary": "用原生自动分片管道追加或整篇覆盖 adoc 内容", "agent_summary_source": "dws-agent-selection/doc", "availability": "available", "avoid_when": [ - "目标不是 adoc 或只要改单个块时改用 doc block update", + "只在末尾补一小段纯文本优先 +doc-append;只改一个块用 doc block update", + "目标不是 adoc 时按 drive info 的 extension 切对应产品", "覆盖模式用户未确认前不要执行;可先 --dry-run 预览", - "创建新文档用 doc create,不要用 update 冒充创建" + "创建新文档用 doc create;不要预先手工分片或循环重试覆盖" ], "canonical_path": "doc.update_document", "cli_name": "update", @@ -38137,17 +38141,17 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", - "value": "更新文档内容(追加 / 覆盖;覆盖需 --yes)" + "value": "用原生自动分片管道追加或整篇覆盖 adoc 内容" } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", - "value": "更新文档内容(追加 / 覆盖;覆盖需 --yes)" + "value": "用原生自动分片管道追加或整篇覆盖 adoc 内容" }, "availability": { "candidates": [ @@ -38175,24 +38179,26 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "目标不是 adoc 或只要改单个块时改用 doc block update", + "只在末尾补一小段纯文本优先 +doc-append;只改一个块用 doc block update", + "目标不是 adoc 时按 drive info 的 extension 切对应产品", "覆盖模式用户未确认前不要执行;可先 --dry-run 预览", - "创建新文档用 doc create,不要用 update 冒充创建" + "创建新文档用 doc create;不要预先手工分片或循环重试覆盖" ] } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "目标不是 adoc 或只要改单个块时改用 doc block update", + "只在末尾补一小段纯文本优先 +doc-append;只改一个块用 doc block update", + "目标不是 adoc 时按 drive info 的 extension 切对应产品", "覆盖模式用户未确认前不要执行;可先 --dry-run 预览", - "创建新文档用 doc create,不要用 update 冒充创建" + "创建新文档用 doc create;不要预先手工分片或循环重试覆盖" ] }, "canonical_path": { @@ -38279,7 +38285,7 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ @@ -38290,7 +38296,7 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ "dws doc update --node \u003cDOC_ID\u003e --content \"# 追加内容\" --mode append --format json", @@ -38384,7 +38390,7 @@ }, { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "selected": false, "source": "internal/cli/schema_hints/selection/doc.json", "value": true @@ -38442,11 +38448,11 @@ "candidates": [ { "precedence": "reviewed_explicit", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "selected": true, "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "用户要向已有 adoc 追加内容时用 --mode append(更安全)", + "用户要向已有 adoc 追加长、多行或文件内容时用 --mode append + --content-file;CLI 自动分片", "用户明确要求整篇覆盖替换时用 --mode overwrite(破坏性)", "append 且要插到第 N 个 block 前时加 --index N(先 block list)" ] @@ -38454,10 +38460,10 @@ ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "source": "internal/cli/schema_hints/selection/doc.json", "value": [ - "用户要向已有 adoc 追加内容时用 --mode append(更安全)", + "用户要向已有 adoc 追加长、多行或文件内容时用 --mode append + --content-file;CLI 自动分片", "用户明确要求整篇覆盖替换时用 --mode overwrite(破坏性)", "append 且要插到第 N 个 block 前时加 --index N(先 block list)" ] @@ -39518,7 +39524,7 @@ "source": "reviewed_command_registry", "title": "更新文档内容", "use_when": [ - "用户要向已有 adoc 追加内容时用 --mode append(更安全)", + "用户要向已有 adoc 追加长、多行或文件内容时用 --mode append + --content-file;CLI 自动分片", "用户明确要求整篇覆盖替换时用 --mode overwrite(破坏性)", "append 且要插到第 N 个 block 前时加 --index N(先 block list)" ] diff --git a/internal/cli/schema_hints/selection/doc.json b/internal/cli/schema_hints/selection/doc.json index de160fe6..05068e13 100644 --- a/internal/cli/schema_hints/selection/doc.json +++ b/internal/cli/schema_hints/selection/doc.json @@ -82,22 +82,22 @@ ] }, "doc.create_document": { - "agent_summary": "创建一篇新的在线文档", + "agent_summary": "在默认根目录、文档文件夹或知识库根创建带可选初始内容的 adoc", "use_when": [ - "用户要新建一篇文字在线文档(adoc),可空文档或带初始 Markdown 时", - "创建到指定文件夹 --folder、知识库根 --workspace,或默认「我的文档」根目录时" + "用户要新建文字在线文档(adoc),可空文档或用 --content-file 写入 Markdown/JSONML 时", + "已知目标文档文件夹 --folder 或知识库 --workspace;长 Markdown 仍直接使用本命令,由原生写入管道自动分片" ], "avoid_when": [ "创建表格/脑图/白板/多维表/演示改用 dws wiki node create --type (勿用 doc create)", - "在知识库建空节点实体也可用 wiki node create;本命令侧重可写初始内容的 adoc", - "导入本地 Word/Markdown 为在线文档改用 dws doc import(若可用)或 upload --convert" + "只管理知识库空节点或层级时用 wiki node create;本命令侧重创建并写入 adoc", + "导入本地 Word/Markdown 并保留服务端转换语义时用 dws doc import;不要用自写分片脚本替代原生 create" ], "examples": [ "dws doc create --name \"项目周报\" --format json", - "dws doc create --name \"Q1 总结\" --content \"# Q1 总结\" --folder --format json" + "dws doc create --name \"Q1 总结\" --content-file ./q1.md --workspace --format json" ], "reviewed": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐当前 Cobra 原生内容写入管道、doc Skill 渐进路由与 workspace/folder 边界;强调长内容无需外部分片,不改变命令身份、参数或安全事实。", "source_refs": [ "CommandRegistry:canonical_path=doc.create_document", "cobra-help:dws doc create", @@ -295,12 +295,12 @@ "doc.get_document_content": { "agent_summary": "读取完整文档内容,或按 outline/range/section/tags 获取 JSONML fragment", "use_when": [ - "用户要读取钉钉在线文字文档(adoc)正文(Markdown)时", - "用户直接粘贴文档 URL 且无其他指令时(默认读内容)", + "已由 drive info 确认 extension=adoc,用户要读取正文(Markdown)时", + "用户提供已知 adoc nodeId/URL,且要读取内容或抽取指定章节时", "只需标题大纲、指定块区间/单块或特定 JSONML tags 时使用 --content-format jsonml 与 --scope" ], "avoid_when": [ - "非 adoc(表格/多维表/普通文件)不要用本命令;先 doc info 再路由", + "原始 alidocs URL 类型未知或目标不是 adoc 时先用 drive info 探测并路由;表格/多维表/普通文件不要用本命令", "要元信息用 doc info;要块结构用 doc block list", "Markdown 为有损投影:保形复制模板请用 doc copy,不要 read→create" ], @@ -309,7 +309,7 @@ "dws doc read --node --content-format jsonml --scope outline --max-depth 3" ], "reviewed": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 doc Skill 与 doc-info reference 的 extension 预检边界,并保留 Markdown/JSONML scope 的真实 Cobra 契约。", "source_refs": [ "CommandRegistry:canonical_path=doc.get_document_content", "cobra-help:dws doc read", @@ -321,22 +321,23 @@ ] }, "doc.get_document_info": { - "agent_summary": "获取文档元信息(标题/类型/创建者/权限等)", + "agent_summary": "在已确认是 ALIDOC 后读取文档专属元信息", "use_when": [ - "用户要查看文档/节点元信息(标题、类型、创建者、权限)时", - "准备读内容前必须先看 contentType/extension 以路由到 read/sheet/aitable/download 时" + "drive info 已确认是 ALIDOC,用户还要标题、创建者、权限或 docUrl 等文档专属元信息时", + "创建响应只有 nodeId、缺少 docUrl,需要补查文档链接时" ], "avoid_when": [ - "已确认是 adoc 且只要正文改用 dws doc read", + "原始 alidocs URL 的类型探测、extension 路由或可靠 fileSize 使用 dws drive info;不要先猜是文档", + "已确认是 adoc 且只要正文时改用 dws doc read", "只要目录列表改用 dws drive list / wiki node list", - "需要可靠文件大小 fileSize 时改用 dws drive info;文档元信息接口可能不返回大小" + "普通文件、电子表格或 AI 表格不使用本命令" ], "examples": [ "dws doc info --node --format json", "dws doc info --node \"https://alidocs.dingtalk.com/i/nodes/\" --format json" ], "reviewed": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 drive info 统一类型探测入口与 doc info 的文档专属补查职责;不改变 node 参数或接口绑定。", "source_refs": [ "CommandRegistry:canonical_path=doc.get_document_info", "cobra-help:dws doc info", @@ -739,23 +740,24 @@ ] }, "doc.update_document": { - "agent_summary": "更新文档内容(追加 / 覆盖;覆盖需 --yes)", + "agent_summary": "用原生自动分片管道追加或整篇覆盖 adoc 内容", "use_when": [ - "用户要向已有 adoc 追加内容时用 --mode append(更安全)", + "用户要向已有 adoc 追加长、多行或文件内容时用 --mode append + --content-file;CLI 自动分片", "用户明确要求整篇覆盖替换时用 --mode overwrite(破坏性)", "append 且要插到第 N 个 block 前时加 --index N(先 block list)" ], "avoid_when": [ - "目标不是 adoc 或只要改单个块时改用 doc block update", + "只在末尾补一小段纯文本优先 +doc-append;只改一个块用 doc block update", + "目标不是 adoc 时按 drive info 的 extension 切对应产品", "覆盖模式用户未确认前不要执行;可先 --dry-run 预览", - "创建新文档用 doc create,不要用 update 冒充创建" + "创建新文档用 doc create;不要预先手工分片或循环重试覆盖" ], "examples": [ "dws doc update --node --content \"# 追加内容\" --mode append --format json", "dws doc update --node --content-file ./body.md --mode overwrite --dry-run" ], "reviewed": true, - "review_reason": "人工审阅:结合本机 dws schema 实时 MCP description/parameters(经 interface_ref)、产品 Skill、Cobra Long 与 Runtime 确认门禁,按飞书风格重写选型文案;不改变命令身份、参数契约或接口绑定。", + "review_reason": "人工对齐 Runtime 的 10000 字符自动分片、append/overwrite 动态门禁与根 Skill 的写后回读流程;不改变参数和安全事实。", "source_refs": [ "CommandRegistry:canonical_path=doc.update_document", "cobra-help:dws doc update", @@ -905,14 +907,14 @@ "当你只记得文档的标题或主题词、需要先定位到某篇钉钉文档拿到它的 nodeId/URL 以便后续阅读或编辑时使用;可按关键词、扩展名、创建/访问时间、创建者等条件过滤,不传关键词则返回最近访问的文档,返回匹配的文档列表。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只有一个关键词且只要紧凑标题/URL/type/token 投影时优先 +find-doc;目标已给 nodeId/URL 时不要再搜索" ], "examples": [ "dws doc +search --query \"会议纪要\"", "dws doc +search --extensions pdf,docx" ], "reviewed": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工区分 +search 的丰富过滤/最近访问能力与 +find-doc 的单关键词紧凑投影,避免两个同源搜索 Shortcut 互相争抢。", "source_refs": [ "internal/cli/schema_command_registry.json#doc.shortcut_search", "cobra-help:dws doc +search", @@ -925,14 +927,14 @@ "当你已知某个文档文件夹或知识库的 ID、想浏览它下面直接包含的文档与子文件夹(不递归深层)以便逐层导航时使用;输入 folder 或 workspace,返回该层级的子节点列表。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "全局或钉盘目录浏览优先 drive list,知识库节点树优先 wiki node list;本 Shortcut 只列已知 doc folder/workspace 的直接子节点" ], "examples": [ "dws doc +list --folder DOC_FOLDER_NODE_ID", "dws doc +list --workspace WS_ID --limit 20" ], "reviewed": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 doc/drive/wiki 产品边界:保留已知文档文件夹/知识库的直接子节点投影,不替代常规目录管理。", "source_refs": [ "internal/cli/schema_command_registry.json#doc.shortcut_list", "cobra-help:dws doc +list", @@ -945,13 +947,13 @@ "当你想保留原件、在另一个文件夹或知识库里生成一份文档/文件副本(例如以某篇文档为模板另存)时使用;输入源 node 与目标 folder/workspace,会实际创建一个副本。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive copy;要搬走原件用 move;复制后必须从真实返回取副本 nodeId,禁止继续编辑源文档" ], "examples": [ "dws doc +copy --node DOC_ID --folder TARGET_FOLDER_NODE_ID" ], "reviewed": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐保形复制、真实副本 ID 与 drive 文件管理边界;保留 Runtime user_required 门禁。", "source_refs": [ "internal/cli/schema_command_registry.json#doc.shortcut_copy", "cobra-help:dws doc +copy", @@ -964,13 +966,13 @@ "当你要整理文档归属、把某篇文档/文件从当前位置挪到另一个文件夹或知识库(原位置不再保留)时使用;输入 node 与目标 folder/workspace,会实际改变文件的存放位置。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "常规文件管理优先 drive move;要保留原位置副本用 copy;目标位置不明确或未确认时不要移动" ], "examples": [ "dws doc +move --node DOC_ID --folder TARGET_FOLDER_NODE_ID" ], "reviewed": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 move 的原位置消失语义、目标位置确认与 drive 文件管理边界;保留 Runtime user_required 门禁。", "source_refs": [ "internal/cli/schema_command_registry.json#doc.shortcut_move", "cobra-help:dws doc +move", @@ -1041,13 +1043,13 @@ "当你想把在线文档导出成 docx/markdown/pdf 文件(例如离线保存或外发)时使用;这是异步任务的第一步,输入 node 与 export-format 提交导出,返回 jobId,随后用 +export-get 轮询结果。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "用户要直接拿到本地 docx/markdown/pdf 文件时使用一体化 dws doc export;不要默认手工编排 submit/get 轮询" ], "examples": [ "dws doc +export-submit --node DOC_ID --export-format markdown" ], "reviewed": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 atomic doc export 的一体化提交/轮询/下载路径,将 +export-submit 限定为明确异步控制场景。", "source_refs": [ "internal/cli/schema_command_registry.json#doc.shortcut_export_submit", "cobra-help:dws doc +export-submit", @@ -1117,13 +1119,13 @@ "当文档被误改、你想把它整体恢复到某个历史版本时使用;先用 +version-list 找到目标版本号,再输入 node 与 version,会实际把文档内容覆盖回该版本,属于高风险写操作,需谨慎确认。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只查看历史用 +version-list,只保存当前快照用 +version-save;版本号未核实、用户未确认或只需改单块时不要回滚" ], "examples": [ "dws doc +version-revert --node DOC_ID --version 3" ], "reviewed": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐 version list → 明确确认 → revert → 回读的 ID 与高风险边界;不改变 typed_yes 安全门禁。", "source_refs": [ "internal/cli/schema_command_registry.json#doc.shortcut_version_revert", "cobra-help:dws doc +version-revert", @@ -1174,14 +1176,14 @@ "当你只想往一篇钉钉文档的最后面补一段文字、又不想动原有内容时使用;内部用文档更新的“追加(append)”模式,把你给的文本安全地拼到文档末尾,不需要你先去查文档块列表、算末尾位置或手工拼块结构。会真实写入文档内容。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "长、多行、表格或文件内容使用 doc update --mode append --content-file;指定位置或富结构使用 block insert;不要跳过 user_required 确认" ], "examples": [ "dws doc +doc-append --doc DOC_ID --text \"补充说明:本方案已评审通过。\"", "dws doc +doc-append --doc \"https://alidocs.dingtalk.com/i/nodes/\" --text \"追加一行备注\"" ], "reviewed": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 Shortcut 限定为短纯文本末尾追加,并对齐 user_required 与写后回读;长内容交给原生自动分片管道。", "source_refs": [ "internal/cli/schema_command_registry.json#doc.shortcut_doc_append", "cobra-help:dws doc +doc-append", @@ -1194,14 +1196,14 @@ "当你只记得云文档标题或内容里的某个关键词,想快速按关键词找到匹配的文档、拿到它的标题、URL、类型和 token 以便后续查看或编辑,却不想拿到一大坨原始字段时使用;内部调用云文档的 search_documents 工具,把 --query 作为搜索关键词(keyword),可选地用 --limit 限制返回条数(pageSize),再在本地把每条命中结果精简为「标题、URL、类型、token」四个字段后打印。这是纯只读操作,只做搜索与本地投影,不会创建、修改或删除任何文档;未命中时提示「没搜到文档」。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "需要最近访问、extension/时间/创建者等组合过滤时使用 +search;目标已给 nodeId/URL 时直接进入 info/read,不再搜索" ], "examples": [ "dws doc +find-doc --query 季度汇报", "dws doc +find-doc --query 合同 --limit 10" ], "reviewed": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工将 +find-doc 定位为高频单关键词紧凑投影,并与 +search 的丰富过滤能力做互斥路由。", "source_refs": [ "internal/cli/schema_command_registry.json#doc.shortcut_find_doc", "cobra-help:dws doc +find-doc", @@ -1214,13 +1216,13 @@ "当你手上已经有一个文档链接、想直接私信发给某个人而不必先查 userId 时使用;内部先按姓名搜通讯录解析出唯一用户,再用 openDingTalkId 把链接拼成一条 Markdown 消息发出去,姓名匹配到多人时会列出候选让你区分。只发链接、不读取或改动文档本身,会真实发出消息。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "同名人员未消歧、缺少真实文档 URL 或用户未确认时不要发送;本命令不授予文档权限,授权应走 drive permission" ], "examples": [ "dws doc +share-doc --to 张三 --url https://docs.dingtalk.com/xxx --note \"帮忙过一下\"" ], "reviewed": true, - "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", + "review_reason": "人工对齐人员消歧、真实 docUrl、user_required 消息发送门禁与文档权限边界。", "source_refs": [ "internal/cli/schema_command_registry.json#doc.shortcut_share_doc", "cobra-help:dws doc +share-doc", diff --git a/scripts/gen_skill_shortcut_sections.py b/scripts/gen_skill_shortcut_sections.py index fe174081..9df3e9e9 100644 --- a/scripts/gen_skill_shortcut_sections.py +++ b/scripts/gen_skill_shortcut_sections.py @@ -55,7 +55,12 @@ PRODUCT_END = "" # only after verifying that the product skill has its own reviewed routing # section and intent table; compacting a sparse skill without an alternative # route would make its shortcuts harder to discover. -COMPACT_PRODUCT_SERVICES = {"chat"} +COMPACT_PRODUCT_SERVICES = {"chat", "doc"} + +# These compact products have every public Shortcut curated into Runtime +# Schema. Keep this separate from COMPACT_PRODUCT_SERVICES because Chat still +# has reviewed exclusions pending curation. +FULLY_CURATED_COMPACT_PRODUCT_SERVICES = {"doc"} def md_escape(value: Any) -> str: text = str(value or "") @@ -135,10 +140,22 @@ def product_section(service: str, rows: list[dict[str, Any]]) -> str: def compact_product_section(service: str, rows: list[dict[str, Any]]) -> str: + if service in FULLY_CURATED_COMPACT_PRODUCT_SERVICES: + inventory = ( + f"`{md_escape(service)}` 当前有 {len(rows)} 条公开 Shortcut," + "已全部进入 Runtime Schema。完整清单保留在 Runtime Shortcut " + "Catalog,根 Skill 不重复展开;单条参数与安全契约按需查询 leaf Schema。" + ) + else: + inventory = ( + f"`{md_escape(service)}` 当前有 {len(rows)} 条公开 shortcut。" + "完整清单保留在 Runtime Shortcut Catalog;已完成 Schema curation " + "的子集可通过 leaf Schema 查询。高频产品根 Skill 不重复展开完整清单。" + ) return f"""{PRODUCT_START} ## Shortcut 发现(按需) -`{md_escape(service)}` 当前有 {len(rows)} 条公开 shortcut。完整清单保留在 Runtime Shortcut Catalog;已完成 Schema curation 的子集可通过 leaf Schema 查询。高频产品根 Skill 不重复展开完整清单。已知意图直接使用下方的优先路由、意图表或任务 reference;命令已选中时直接执行,只在参数/安全语义不确定时读取 leaf Schema,在当前 Cobra flags 不确定时读取 leaf Help。 +{inventory}已知意图直接使用下方的优先路由、意图表或任务 reference;命令已选中时直接执行,只在参数/安全语义不确定时读取 leaf Schema,在当前 Cobra flags 不确定时读取 leaf Help。 仅当现有路由和 reference 都无法定位低频能力时,才执行 `dws shortcut list --service {md_escape(service)} --compact --format json` 做最后回退;不要为已知高频意图加载完整 Shortcut Catalog 或产品级 Schema。 {PRODUCT_END}""" diff --git a/scripts/policy/check-skill-context-budget.sh b/scripts/policy/check-skill-context-budget.sh index 36c302e9..dfb1cc10 100755 --- a/scripts/policy/check-skill-context-budget.sh +++ b/scripts/policy/check-skill-context-budget.sh @@ -7,8 +7,10 @@ cd "$ROOT" python3 scripts/gen_skill_shortcut_sections.py --check chat_skill="skills/multi/dingtalk-chat/SKILL.md" +doc_skill="skills/multi/dingtalk-doc/SKILL.md" mono_skill="skills/mono/SKILL.md" chat_max_bytes=14000 +doc_max_bytes=9500 chat_bytes="$(wc -c < "$chat_skill" | tr -d ' ')" if [ "$chat_bytes" -gt "$chat_max_bytes" ]; then @@ -17,6 +19,13 @@ if [ "$chat_bytes" -gt "$chat_max_bytes" ]; then exit 1 fi +doc_bytes="$(wc -c < "$doc_skill" | tr -d ' ')" +if [ "$doc_bytes" -gt "$doc_max_bytes" ]; then + printf '%s\n' \ + "skill context budget exceeded: $doc_skill is ${doc_bytes} bytes (max ${doc_max_bytes})" >&2 + exit 1 +fi + shortcut_rows="$( awk ' // { in_block = 1; next } @@ -31,6 +40,20 @@ if [ "$shortcut_rows" -ne 0 ]; then exit 1 fi +doc_shortcut_rows="$( + awk ' + // { in_block = 1; next } + // { in_block = 0 } + in_block && /^\|[[:space:]]*`/ { count++ } + END { print count + 0 } + ' "$doc_skill" +)" +if [ "$doc_shortcut_rows" -ne 0 ]; then + printf '%s\n' \ + "skill context budget exceeded: $doc_skill re-expanded $doc_shortcut_rows shortcut rows" >&2 + exit 1 +fi + if grep -Fq "充分阅读产品参考文件" "$mono_skill"; then printf '%s\n' \ "skill context budget regression: $mono_skill requires full product-reference loading" >&2 @@ -38,4 +61,4 @@ if grep -Fq "充分阅读产品参考文件" "$mono_skill"; then fi printf '%s\n' \ - "skill context budget: ok (chat_bytes=$chat_bytes max=$chat_max_bytes shortcut_rows=$shortcut_rows)" + "skill context budget: ok (chat_bytes=$chat_bytes max=$chat_max_bytes shortcut_rows=$shortcut_rows; doc_bytes=$doc_bytes max=$doc_max_bytes shortcut_rows=$doc_shortcut_rows)" diff --git a/skills/multi/dingtalk-doc/SKILL.md b/skills/multi/dingtalk-doc/SKILL.md index a9bd7a99..19211b63 100644 --- a/skills/multi/dingtalk-doc/SKILL.md +++ b/skills/multi/dingtalk-doc/SKILL.md @@ -1,6 +1,6 @@ --- name: dingtalk-doc -description: 钉钉文档(adoc):创建、读取、编辑、块、评论、附件、导出、版本及Markdown/JSONML写入。原生 .md→dingtalk-misc;文件→dingtalk-drive;知识库→dingtalk-wiki;axls→dingtalk-misc,able→dingtalk-aitable。 +description: 钉钉在线文字文档(adoc):创建、读取、追加、覆盖、块级编辑、评论、附件、导入导出、版本、模板、封面/背景,以及 Markdown/JSONML 保真写入。Use when 用户要写文档、读文档、改正文、处理富文本块或文档评论。原生 .md 文件走 dingtalk-markdown;普通文件存储与上传下载走 dingtalk-drive;知识库空间/节点管理走 dingtalk-wiki;电子表格走 dingtalk-sheet,AI 表格走 dingtalk-aitable。命令前缀:dws doc。 metadata: cli_version: ">=0.2.14" category: product @@ -11,152 +11,93 @@ metadata: # 钉钉文档 Skill -## 前置条件 — 执行操作前必读 +## Preconditions -> **CRITICAL — 执行任何 `dws` 操作前,MUST 先用 Read 工具完整读取 [`dws-shared`](../dws-shared/SKILL.md)。**该轻量文件包含全局执行契约、安全底线及 shared references 的按需加载导航;不要预加载其全部 references。 +> **CRITICAL — Before any `dws` operation, MUST fully read [`dws-shared`](../dws-shared/SKILL.md).** It defines the global execution contract, safety floor, and on-demand shared-reference routing. Do not preload all references. -> 命令参考:[doc.md](references/doc.md);剧本:[04-document.md](references/04-document.md)。 - -## 参数硬约束 - -- 创建文档只用 `--name`,不要写 `--title`。 -- 目标文件夹只用 `--folder <文档文件夹nodeId或URL>`,不要写 `--parent` / `--parent-node` / `--parent-id`。 -- 目标知识库只用 `--workspace `,不要写 `--space-id` / `--spaceId`。 -- 文档内容只用 `--content` / `--content-file`,不要写 `--markdown`。 -- 复杂内容(换行、表格、代码块、长 Markdown)先写临时 `.md`,再用 `--content-file`,不要把大段 Markdown 塞进命令行。 -- 每次 `create` / `update` / `block insert` / `media insert` 后必须 `dws doc read` 或 `dws doc block list` 回读关键内容。 +> Atomic command router: [doc.md](references/doc.md); document workflows: [04-document.md](references/04-document.md). -## Shortcuts(无专用脚本/recipe 时优先) +## Shortcut 发现(按需) -以下 shortcut 同时进入公开 catalog 与 Runtime Schema。先按本 skill 的意图表、脚本和 recipe 路由:存在精确覆盖该场景的专用脚本/recipe 时按其执行;否则用户意图命中时,shortcut 优先于手写原子命令。命令已选中时直接执行;只在参数或安全语义不确定时读取 leaf Schema(例如 `dws schema --cli-path "doc +" --format json`),在当前 Cobra flags 不确定时读取 `dws doc --help`。仅当现有路由和 reference 都无法定位低频能力时,才用 `dws shortcut list --service doc --format json` 批量发现。 +`doc` 当前有 17 条公开 Shortcut,已全部进入 Runtime Schema。完整清单保留在 Runtime Shortcut Catalog,根 Skill 不重复展开;单条参数与安全契约按需查询 leaf Schema。已知意图直接使用下方的优先路由、意图表或任务 reference;命令已选中时直接执行,只在参数/安全语义不确定时读取 leaf Schema,在当前 Cobra flags 不确定时读取 leaf Help。 -| Shortcut | 风险 | 适用场景 | -|---|---|---| -| `dws doc +comment-create` | write | 在文档上创建一条评论 | -| `dws doc +comment-list` | read | 查询文档评论列表 | -| `dws doc +comment-reply` | write | 回复文档中的一条评论 | -| `dws doc +copy` | write | 复制文档/文件到指定文件夹或知识库 | -| `dws doc +doc-append` | write | 在文档末尾追加一段文本(安全追加,不改动原有内容) | -| `dws doc +export-get` | read | 根据 jobId 查询文档导出任务结果 | -| `dws doc +export-submit` | read | 提交在线文档导出任务 (docx/markdown/pdf),返回 jobId | -| `dws doc +find-doc` | read | 按关键词搜索云文档并投影关键字段(只读) | -| `dws doc +list` | read | 列出文件夹或知识库下的直接子节点 | -| `dws doc +move` | write | 移动文档/文件到指定文件夹或知识库 | -| `dws doc +search` | read | 按关键词搜索有权限的文档 (不传则返回最近访问) | -| `dws doc +share-doc` | write | 按姓名把文档链接私信发给某人(自动解析 userId) | -| `dws doc +template-list` | read | 获取文档模板列表 | -| `dws doc +template-search` | read | 根据关键词搜索文档模板 | -| `dws doc +version-list` | read | 查看文档历史版本列表 | -| `dws doc +version-revert` | high-risk-write | 回滚文档到指定历史版本 | -| `dws doc +version-save` | write | 手动保存文档版本快照 | +仅当现有路由和 reference 都无法定位低频能力时,才执行 `dws shortcut list --service doc --compact --format json` 做最后回退;不要为已知高频意图加载完整 Shortcut Catalog 或产品级 Schema。 -## 意图表 +## Atomic 回退与执行契约 -| 用户说 | 命令 | -|--------|------| -| "创建文档(短内容)" | `dws doc create --name "<标题>" --content "<内容>"` | -| "创建+写入(长内容自动分块)" | `python scripts/doc_create_and_write.py --name "<标题>" --content "<内容>" [--mode append\|overwrite]` | -| "搜在线文字文档 / 找在线文字文档" | `dws drive search --query "<关键词>" --format json` → `dws drive info --node --format json` → 仅 `extension=adoc` 使用 `dws doc read --node --format json` | -| "读在线文字文档(adoc)内容" | `dws doc read --node --format json` | -| "更新文档内容 / 分块追加" | `dws doc update --node --content "<分块>" --mode append` | -| "删除块" | `dws doc block delete`(需用户确认) | -| "导出 docx / markdown / pdf" | `dws doc export --node --export-format --output ` | -| "导入本地文件为在线文档" | `dws doc import --file --folder --name "<标题>" --format json`(详见 `references/doc/doc-import.md`) | -| "查模板 / 套用模板创建文档" | `dws doc template list|search|apply`(详见 `references/doc.md` 模板管理) | -| "保存 / 查看 / 回滚在线文字文档(adoc)版本" | `dws doc version save/list/revert` | +没有 Shortcut 时,才按需读取 [doc.md](references/doc.md) 指向的一个 atomic branch reference。路由优先级为 `已评审直接骨架/精确 recipe > 匹配的公开 Shortcut > atomic fallback`。`doc_create_and_write.py` 只在用户明确需要可复用本地包装器且 `python3` 可用时使用;普通创建直接调用 `dws doc create`。 -## 标准 SOP(必遵流程) +命令确定且参数清楚时直接执行,不重复发现。只使用真实 `cli_path`,不猜参数。`confirmation=user_required` 时先确认,再添加 `--yes`;来源冲突时采用更安全解释并报告契约漂移。 -> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 nodeId/blockId。结构化命令必须带 `--format json`,执行后必须按"验证"步回读真实字段。文件类操作(上传/下载/复制/移动)切 `dingtalk-drive`;知识库节点管理切 `dingtalk-wiki`。 +## 核心对象、位置与格式 -### SOP-1 查找并读取文档(query-doc) +| 对象 | 核心标识与边界 | +|---|---| +| 文档 | 使用真实 `nodeId` / `dentryUuid` 或完整 alidocs URL;纯数字 `dentryId`、单独 `dentryKey` 不能替代 | +| 目标位置 | `--folder` 只接文档文件夹 nodeId/URL;`--workspace` 只接知识库 ID/URL;不要猜 `--parent*` | +| 块 | `blockId` / JSONML `uuid` 必须来自 `block list`,更新节点的 uuid 必须与目标块一致 | +| 评论 | `commentKey` 来自评论 list/create;划词评论还需同一块的真实 `start/end` | +| 异步任务 | 导出 `jobId` 与导入 `taskId` 只查询对应任务,不能替代 nodeId | +| 内容格式 | Markdown 适合线性正文;已有富结构优先 JSONML/块级编辑,禁止用 Markdown overwrite 误称保真 | +| 普通文件 | adoc 才用 `doc read/export`;`.md`、axls、able 和普通文件按真实 `extension` 切对应 Skill | -**触发**:查文档/读文档/某文档在哪/搜文档内容。 +## 核心意图与执行骨架 -1. **定位(必须)**:用户已提供 URL / `nodeId` 时直接使用原值;未提供目标时才执行 `dws drive search --query "<关键词>" --format json`,再取候选结果的真实 `nodeId`。 -2. **探测(必须)**:对选中的候选执行 `dws drive info --node --format json`,从真实返回读取 `extension`;不得因为搜索结果标题像“文档”就跳过探测。 -3. **按类型读取(必须)**: - - `extension=adoc`:`dws doc read --node --format json`;大文档只抽取用户需要的章节。 - - `extension=md`:切到 `dingtalk-markdown` 用 `dws markdown fetch --node --format json` 读取原文;仅需文件实体下载时切 `dingtalk-drive` 用 `drive download`。 - - `extension=axls`:切到 `dingtalk-misc`,读取 `references/sheet.md` 后按电子表格意图执行。 - - `extension=able`:切到 `dingtalk-aitable`。 - - `extension=xlsx` / `xls` / `xlsm` / `csv` 或其他普通文件:切到 `dingtalk-drive`;不得执行 `dws doc read`。 +所有结构化命令加 `--format json`,下游 ID 只取真实输出。创建、更新、块、附件和样式写入后回读;返回成功但未回读,不能宣称内容完整。 -**禁止**:用户未提供目标时跳过搜索并猜 nodeId、未探测类型就执行 `doc read`、把整篇文档原样贴给用户。 +| 用户意图 | 精确骨架 | 必须保留的执行边界 | +|---|---|---| +| 按名称找文档 | `+find-doc --query <关键词>`;需最近访问/扩展名/创建者等过滤用 `+search` | 候选不唯一先消歧;随后 `drive info --node ` 判 `extension` | +| 读取 adoc | `drive info --node ` → `doc read --node ` | 用户已给 nodeId/URL 时不再搜索;非 adoc 不调用 `doc read` | +| 创建文档 | `doc create --name <标题> --content-file [--folder | --workspace ]` | 原生写入管道自动分片;取 `nodeId` 后 `doc read`,缺链接再 `doc info` | +| 末尾补短文本 | `+doc-append --doc --text <内容>` | 该 Shortcut 为 write/user_required;确认后执行并 `doc read` 核对 | +| 改写正文 | `doc read --content-format jsonml` → `block update` 或 `doc update --content-format jsonml --mode overwrite` | 单块优先块级编辑;整篇 overwrite 先预览/确认,Markdown overwrite 不保富结构 | +| 评论与回复 | `+comment-list --node ` → `+comment-create` / `+comment-reply` | `commentKey` 来自真实结果;写 Shortcut 先确认;划词评论走 atomic `comment create-inline` | +| 导入 / 导出 | `doc import --file ...` / `doc export --node --export-format --output ` | 一体化命令优先;仅超时/中断后用 `import get` / `export get` | +| 版本操作 | `+version-list --node ` → `+version-save` / `+version-revert --version ` | save/revert 先确认;revert 版本号必须来自 list,完成后回读 | +| 模板创建 | `+template-list` / `+template-search --query <词>` → atomic `template apply --template-id ` | templateId 来自真实列表;要复刻已有文档形态时用 drive copy + 副本块级更新 | +| 分享链接给某人 | `+share-doc --to <姓名> --url [--note <附言>]` | 会真实发消息,确认后执行;同名人员必须消歧,不改变文档权限 | -### SOP-2 创建文档并写入(create-doc) +## 写入与验证边界 -**触发**:新建文档/写一篇/建文字文档。 +- 创建只用 `--name`;内容只用 `--content` / `--content-file`。长、多行、表格或特殊字符必须用临时 UTF-8 文件和 `--content-file`。 +- 原生 Markdown 写入管道在内容超过 10,000 个 Unicode 字符时自动按结构分片;不要在 Skill 或脚本中预先复制分片循环。仅在 `CONTENT_TRUNCATED`、中断或回读缺失时按 [04-document.md](references/04-document.md) 恢复。 +- `doc update --mode append` 不清空原文;`--mode overwrite` 会清空后重写,先 `--dry-run`,得到确认后才加 `--yes`。 +- 已有 callout、分栏、样式、@人、图片或附件时,先读 JSONML;局部改动优先 `block update`,不要用 Markdown 整篇重写。 +- `block insert` 默认追加;只有明确相对位置时才传真实 `--ref-block` / `--parent-block`。`block delete` 和评论删除必须确认。 +- 写后按对象验证:正文用 `doc read`,块/附件用 `doc block list`,元信息/链接用 `doc info`,版本用 `version list`。 -1. **执行(必须)**:`dws doc create --name "<标题>" --content-file [--folder | --workspace ] --format json`(长/多行内容用 `--content-file`,不要用 `--content` 拼长串;用户未指定位置时省略两个位置参数,创建到“我的文档”根目录)。 -2. **验证(必须)**:从返回取 `nodeId`,立即 `dws doc info --node --format json` 回读确认。 +## 低频 atomic 路由 -**禁止**:创建后不回读就答复"已创建"、把 `--folder` 当成空间 ID 传入。 +```text +dws doc +├── info / read +├── create / update +├── block # list, insert, update, delete +├── comment # list, create, reply, update, delete, create-inline +├── media # insert, download +├── import / export +├── template / version / style +├── +shortcut +└── deprecated file operations → drive/wiki +``` -### SOP-3 覆盖/追加内容(write-content) +按需读取,不要预加载:定位与 URL 边界读 [doc-info.md](references/doc/doc-info.md);创建/改写读 [doc.md](references/doc.md) 的场景索引所列文件组;块、评论、附件、导入、导出分别读对应 branch reference。JSONML schema/cookbook 仅在实际选择 JSONML 写入后加载。 -**触发**:覆盖写/追加内容/改文档正文。 +## 错误恢复 -1. **执行(必须)**:覆盖先执行 `dws doc update --node --mode overwrite --content-file --dry-run --format json` 预览,用户确认后改用 `--yes` 实际覆盖;追加执行 `dws doc update --node --mode append --content-file --format json`。 -2. **验证(必须)**:写后 `dws doc read --node --format json` 抽取受影响段落核对。 - -**禁止**:不加 `--yes` 反复重试覆盖、跳过 `--dry-run` 直接覆盖未确认的长文档。 - -### SOP-4 导出 / 下载(export-doc) - -**触发**:导出文档/下载文档/转 PDF·Markdown。 - -1. **判类型(必须)**:先 `dws drive info --node --format json`;`extension=adoc` → `dws doc export --node --export-format --output --format json`;普通文件 → 切 `dingtalk-drive` 用 `dws drive download --node --output --format json`。 - -**禁止**:不分类型一律走 `doc export`(普通文件会失败)、跳过 `drive info` 判断。 - -### SOP-5 块级编辑(block-edit) - -**触发**:插引用块/代码块/表格/分栏/图片/附件,或删除某块。 - -1. **先列块(必须)**:`dws doc block list --node --format json`,当前响应的可操作块 ID 位于 `blocks[].element.id`(部分版本可能回显为 `blockId`);必须从目标内容对应项读取,不得编造。空文档的占位空段落可能不能作为 `--ref-block`。 -2. **按动作执行(必须)**: - - 插入:默认追加用 `dws doc block insert --node --text "<内容>" --format json`;只有明确要求相对位置时才加 `--ref-block <非空参照块ID> --where before|after`,容器内插入使用 `--parent-block <父块ID> --index <位置>`。插入命令**不接受** `--block-id`。 - - 更新:`dws doc block update --node --block-id <目标blockId> --text "<新内容>" --format json`。 - - 删除:用户确认后执行 `dws doc block delete --node --block-id <目标blockId> --yes --format json`。 -3. **验证(必须)**:再次执行 `dws doc block list --node --format json` 核对插入、更新或删除结果。 -4. **复杂块(必须)**:插入引用/代码/表格/分栏/附件/图片前,**必须**先读 [doc.md](references/doc.md) 对应小节,**禁止**只停在"准备查看 help"——说"我将插入..."后必须立即执行命令。 - -**禁止**:编造 blockId、未确认就删除、把完整 `--help` 输出当成最终结果答复用户。 -### SOP-6 导入本地文件为在线文档(import-file) - -**触发**:导入 Word / Excel / Markdown / 本地文件为在线文档。 - -1. **判类型(必须)**:确认用户意图是“导入为在线文档”,不是“上传到钉盘”。仅上传存储时切 `dingtalk-drive`。 -2. **执行(必须)**:`dws doc import --file --folder --name "<标题>" --format json`;复杂参数和限制见 [doc-import.md](references/doc/doc-import.md)。 -3. **验证(必须)**:拿到返回 `nodeId` 后执行 `dws doc info --node --format json`,必要时 `dws doc read --node --format json` 抽样核对内容。 - -**禁止**:把上传文件到钉盘误当成 doc import;不知道目标文件夹 nodeId 时先切 `dingtalk-drive`/`dingtalk-wiki` 查询。 - -## 多步文档短路径 - -- 在目标文件夹创建文字文档:`dws doc create --name "<标题>" --folder --content-file --format json`。拿到 `nodeId` 后立即回读。 -- 块级编辑固定顺序:`doc block list --node ` → 插入用 `--ref-block`/`--parent-block`,更新或删除用 `--block-id` → `doc block list` 验证。删除块必须已有用户明确删除意图或二次确认。 -- 插入引用块、代码块、表格、分栏、附件、图片时,优先读 [doc.md](references/doc.md) 对应小节,不要只停在"准备查看 help"。说出"我将插入..."后必须立即执行对应 terminal 调用。 -- 用户要求多个子文档/附件/块操作时,按 checklist 串行完成;最后一条 assistant 消息不能停在"接下来我要...",必须有实际工具调用或明确失败原因。 -- 用户说“读取并下载/导出”时,先 `drive info --node ... --format json` 按 - `extension` 判断类型:`adoc` 用 `doc export`,普通文件切到 - `dingtalk-drive` 用 `drive download`。 -- 所有结构化 dws 命令带 `--format json`。仅参数不确定时查 `--help`,不要把完整 help 当成最终结果。 - -## 危险操作 - -`block delete` 不可逆,必须确认再加 `--yes`。 +- 路径或参数错误:按既定顺序查 leaf Schema、再查 leaf Help,校正一次;不要连续尝试近似参数。 +- 始终从实际输出重新提取 `nodeId`、`blockId`、`commentKey`、`jobId` 或 `taskId`。 +- 部分写入或回读缺失:保留已创建的 nodeId,报告已完成范围与缺失位置;先读回,再只补缺失内容,禁止无条件重新创建副本。 +- 权限不足、候选未消歧、目标类型不符、没有可推进的任务 ID 或 Schema/Help 冲突时停止并报告。 ## 跨产品协作 -- 文件存储 / 上传下载 → 切到 `dingtalk-drive` -- 知识库空间管理 → 切到 `dingtalk-wiki` -- 数据表 → 切到 `dingtalk-aitable` -- 原生 `.md` 文件读取、创建、全量覆盖或局部替换 → 切到 `dingtalk-markdown` -- 长篇报告生成(多源采集 + 写文档)→ 此 skill 提供 `doc_create_and_write.py` 脚本 -## 局部意图与短流程 - -- [局部意图消歧](references/intent-guide.md);[短流程](references/lite-recipes.md)。 +- 原生 `.md` 文件内容 → `dingtalk-markdown`。 +- 普通文件存储、搜索、复制、移动、重命名、删除、上传下载与权限 → `dingtalk-drive`。 +- 知识库空间、节点和成员管理 → `dingtalk-wiki`;`doc create --workspace` 可直接在已知知识库根创建带内容的 adoc。 +- 在线电子表格 / AI 表格 → `dingtalk-sheet` / `dingtalk-aitable`。 +- 人名消歧 → `dingtalk-aisearch` 或 `dingtalk-contact`;文档评论 mention 使用真实 userId。 +- 局部意图边界见 [intent-guide.md](references/intent-guide.md),固定短流程见 [lite-recipes.md](references/lite-recipes.md)。 diff --git a/skills/multi/dingtalk-doc/references/04-document.md b/skills/multi/dingtalk-doc/references/04-document.md index 706567a9..306697c0 100644 --- a/skills/multi/dingtalk-doc/references/04-document.md +++ b/skills/multi/dingtalk-doc/references/04-document.md @@ -8,7 +8,7 @@ | write-doc | 0. 阅读 [doc-create-workflow.md](./doc/style/doc-create-workflow.md) 的 §前置必读 + §关键词速查表,锁定文档类型和起稿路径:**决策型/含对比的知识沉淀型/用户要求美观 → JSONML 起稿**(`.json`);执行型/说明型 → Markdown 起稿(`.md`)
1. 按选定路径执行 doc-create-workflow.md(JSONML 路径有骨架范例可直接复制修改)
2. `doc create --content-file /tmp/.json --content-format jsonml`(或 `.md` + `--content-format markdown`)
3. 大内容默认依赖 DWS 自动分片;只有 `CONTENT_TRUNCATED`、部分写入失败或回读发现缺失时,才按 workflow 的恢复流程手工补片
4. **回读校验(必须)**:所有写入完成后,执行 `doc read --node `,校验关键标题/段落/表格是否完整写入 | | search-docs-and-share | 1. `dws drive search --query "<关键词>" --format json` → 取候选 `nodeId` + 标题建索引(不读全文)
2. 对追问选中的候选执行 `dws drive info --node --format json`
3. 仅 `extension=adoc` 使用 `dws doc read --node --format json`(最多 2 篇);`md` / `axls` / `able` / 普通文件分别切到 markdown / sheet / aitable / drive,禁止固定执行 `doc read` | | create-knowledge-base | 1. 创建知识库空间取 `WS_ID`
2. `wiki node create --workspace --name "<文档名>"` → 取 `nodeId`
3. `wiki node list --workspace ` 确认 | -| migrate-doc | 1. `doc read --node <源nodeId>` → 取正文并写入临时文件 `.md`
2. `doc create --name "<文档名>" --folder --content-file .md` → 取新 `nodeId`(`--folder` 只传文档文件夹 nodeId / alidocs 文件夹 URL,不传数字 dentryId;正文 <200KB 单步到位)
2a. 若正文 >200KB:**必须先向用户提示截断风险**(详见下方「分块 append 截断风险提示」),用户确认后再执行:`doc create --name "<文档名>" --folder ` → `nodeId` → 按段落切片 → 每片 `doc update --node --content-file --mode append`
3. **回读校验**:`doc read --node ` 校验内容完整性 | +| migrate-doc | 1. `doc read --node <源nodeId>` → 取正文并写入临时文件 `.md`
2. `doc create --name "<文档名>" --folder --content-file .md` → 取新 `nodeId`;所有长度都先走这一条原生命令,由 CLI 自动分片(`--folder` 只传文档文件夹 nodeId / alidocs 文件夹 URL,不传数字 dentryId)
3. **回读校验**:`doc read --node ` 校验内容完整性;仅在 `CONTENT_TRUNCATED`、中断或回读缺失时,从真实断点补写缺失部分 | | update-doc-section | 1. `dws drive search --query "<关键词>" --format json` → 取 `nodeId`
2. `dws drive info --node --format json`,仅 `extension=adoc` 继续;其他类型切到对应 skill/reference
3. **形态选择(按 [doc-update-workflow.md §1.3](./doc/style/doc-update-workflow.md) 优先级)**:目标段落含 callout / 分栏 / 颜色 / @人 / 附件 / 嵌套结构 → 走 `jsonml-node-edit`;纯文本替换且确认无富结构 → 继续本 recipe
4. `dws doc read --node --format json` 定位目标章节
5. `dws doc update --node --content "<替换内容>" --mode overwrite --yes --format json`
6. **回读校验**:`dws doc read --node --format json` 确认 overwrite 未被降级为 append、内容完整无截断
**overwrite 须用户确认**;完整改写流程见 [doc-update-workflow.md](./doc/style/doc-update-workflow.md) | | rewrite-doc | 1. 阅读并执行 [doc-update-workflow.md](./doc/style/doc-update-workflow.md):先看 §1.3 编辑形态优先级(**JSONML 首选**),再按 §3 速查表选路径,跳 §4 对应小节执行
2. 单块改写 / 含富结构 → §4.4 路径 B;多处保真改写或改 root → §4.4 路径 A;纯文本骨架重写 → §4.5 markdown
3. 整篇 overwrite 前必须按 workflow §4.5 向用户提示风险并等待确认
4. **回读校验(必须)**:按 workflow §6 的校验要点逐项核查;@人、附件、图片等保真要素必须原样保留
**适用场景**:用户提供已有 nodeId/链接,需要改写、润色、章节补充、段落形态转换、整篇重写 | | doc-to-message | 1. `doc read --node ` → 取正文(大文档只摘要+链接)
2. `aisearch person --keyword "<姓名>" --dimension name` → 取 `openDingTalkId`(推荐);或 `chat search --query "<群名>"` → 取 `openConversationId`
3. `chat message send --open-dingtalk-id --text "<内容>"`(推荐)或 `--group --text "<内容>"` 发送。仅当无法获取 openDingTalkId 时才用 `--user `(备选) | @@ -29,28 +29,17 @@ --- -## 分块 append 截断风险提示 +## 自动分片失败恢复 -### 触发条件 +`doc create` / `doc update` 的 Markdown 写入管道会从 10,000 个 Unicode 字符开始自动分片,超时后降到 5,000 字符重试。不要在调用前手工复制分片逻辑。 -当内容总大小 **超过 200KB**,需要拆分为多片通过 `doc update --mode append` 分块写入时,**必须在执行前向用户发出截断风险提示**,等待用户确认后再继续。 +只有返回 `CONTENT_TRUNCATED`、写入被中断或回读发现缺失时,才执行恢复: -### 提示话术(参考模板) - -> 注意: 内容较长(约 {size}),需要分 {n} 片写入。分块 append 存在以下风险: -> - 部分片段可能写入失败但返回 success,导致文档**内容截断或缺失** -> - 片段之间的表格、代码块等跨块元素可能**被截断破坏** -> - 写入顺序异常可能导致**段落错乱** -> -> 建议:写入完成后我会回读校验文档完整性。是否继续? - -### 执行规范 - -1. **提示时机**:在执行第一片 append **之前**提示,而非写入过程中 -2. **分片原则**:按段落/标题边界切分,**禁止**在表格、代码块、列表内部截断 -3. **逐片校验**(推荐):每写入一片后记录已写入的最后一个标题/段落标记,供最终回读时比对 -4. **最终回读**(必须):所有片段写入完成后,执行 `doc read --node ` 回读全文,逐片比对关键标记是否完整(详见下方「doc update 回读校验规范」) -5. **失败处理**:若回读发现缺失片段,向用户报告具体缺失位置,建议针对缺失部分单独重试 append +1. 保存命令返回的真实 `nodeId` 和 `chunksWritten`,不要重新创建文档。 +2. `doc read --node ` 定位最后一个完整标题/段落。 +3. 从原始输入中只提取缺失后缀,写入一个新的 UTF-8 文件。 +4. 向用户报告已完成范围与待补范围;得到继续指示后,用一次 `doc update --mode append --content-file ` 补写。 +5. 再次回读并核对关键标题、表格、列表和代码块;仍缺失则停止,不循环追加。 --- diff --git a/skills/multi/dingtalk-doc/references/doc.md b/skills/multi/dingtalk-doc/references/doc.md index 805b6315..0583918f 100644 --- a/skills/multi/dingtalk-doc/references/doc.md +++ b/skills/multi/dingtalk-doc/references/doc.md @@ -26,29 +26,31 @@ **未读以上文件就改写已有文档会导致富结构丢失、参数错误或样式不达标。其他命令(阅读 / 评论 / 权限 / 附件 / 下载导出 / 文件操作)按需查下方 §命令索引表跳转对应子文件加载,不必提前加载。** -## 查询命令帮助 +## Atomic 命令加载契约 -当你不确定某个命令的具体参数、格式或可选项时,**优先执行 `--help` 查询**,不要猜测参数名或凭记忆编造。 +本文件只负责 atomic branch 路由;公开 Shortcut 的选择与发现只在根 +[`SKILL.md`](../SKILL.md) 维护,不在 references 重复列出。 + +命令已经选中且参数清楚时直接执行,不做重复发现。参数、约束或安全语义不确定时, +先查询精确 leaf Schema;只有当前 Cobra flag 不确定时才查询精确 leaf `--help`。 +不要加载产品级全量 Schema,也不要猜测参数名。 ```bash -# 查看 doc 下所有子命令 -dws doc --help +# 参数、约束或安全语义不确定 +dws schema --cli-path "doc update" --format json -# 查看具体命令的完整参数说明 +# 仅 Cobra flag 不确定 dws doc read --help dws doc create --help dws doc block insert --help - -# 查看子命令组下的所有命令 -dws doc block --help -dws doc media --help ``` 规则: -- 参数名不确定时 → 先 `--help`,再调用 -- 报错 "unknown flag" 时 → `--help` 确认正确的 flag 名称 -- 不确定某个功能是否存在时 → `dws doc --help` 查看命令列表 +- 参数、约束、安全不确定 → leaf Schema +- `unknown flag` 或当前 Cobra flag 不确定 → leaf `--help`,修正一次 +- 能力或分支未知 → 先用下方场景/命令索引;仍无法定位才回根 Skill 的 Runtime Shortcut Catalog +- Schema 与 Help 冲突 → 采用更安全解释并报告契约漂移 ## 命令索引表 diff --git a/skills/multi/dingtalk-doc/references/doc/doc-create.md b/skills/multi/dingtalk-doc/references/doc/doc-create.md index bf11a677..c07abd5d 100644 --- a/skills/multi/dingtalk-doc/references/doc/doc-create.md +++ b/skills/multi/dingtalk-doc/references/doc/doc-create.md @@ -44,7 +44,7 @@ Flags: - 不传 `--folder` 和 `--workspace` 时,默认创建在「我的文档」根目录。 - `--folder` 仅接受文档文件夹 `nodeId` / `dentryUuid` / alidocs 文件夹 URL;**禁止**传入 drive `dentryId`、`parentId`、`spaceId` 这类纯数字 ID。 - 输入方式选择见 [`./doc-update.md` §内容写入管道](./doc-update.md)(与 update 共用)。短文本字面量可 `--content`,多行/表格/特殊字符必须 `--content-file` 或 `--content -`。 -- 长内容(>30000 字符)CLI 自动分片:先创建空文档拿 `nodeId`,再按 markdown 标题边界切分后逐片 append;调用方无需手动编排。 +- Markdown 超过 10,000 个 Unicode 字符时,CLI 自动按结构分片:第一片随 `create` 写入并取得 `nodeId`,后续片自动 append;调用方不要手动预分片。 ## 上下文传递 @@ -70,7 +70,7 @@ dws doc create --name "<文档名>" --content-file /tmp/.md --folder " --content-file /tmp/.md --workspace --content-format markdown -# 创建空文档(仅取 nodeId 后再分步写入,适合 >200KB 兜底) +# 创建空文档(用户明确需要空文档时) dws doc create --name "<文档名>" [--folder | --workspace ] --content-format markdown # 短纯文本字面量(< 2KB 且无换行/表格才允许) diff --git a/skills/multi/dingtalk-doc/references/doc/doc-update.md b/skills/multi/dingtalk-doc/references/doc/doc-update.md index 026b33c4..964c92b3 100644 --- a/skills/multi/dingtalk-doc/references/doc/doc-update.md +++ b/skills/multi/dingtalk-doc/references/doc/doc-update.md @@ -75,7 +75,7 @@ Flags: ## 内容写入管道(create / update 共用) -> **关键原则**:CLI 内置自动分片。超长内容(>30000 字符)自动按 markdown 结构切分后逐片写入,对调用方透明。写入完成后由调用方自行决定是否回读确认。 +> **关键原则**:CLI 内置自动分片。Markdown 超过 10,000 个 Unicode 字符时自动按结构切分后逐片写入,对调用方透明。调用方必须在写入后回读确认。 ### 输入方式选择 @@ -88,9 +88,9 @@ Flags: ### 自动分片行为 -当内容超过 30000 字符时,CLI 自动执行: +当 Markdown 内容超过 10,000 个 Unicode 字符时,CLI 自动执行: -1. **create**: 先创建空文档拿 `nodeId`,再按 markdown 标题边界切分后逐片 append +1. **create**: 第一片随 create 写入并取得 `nodeId`,后续片 append 2. **update (overwrite)**: 第一片用 overwrite,后续片用 append 3. **update (append)**: 所有片段用 append @@ -124,13 +124,13 @@ CLI **不会**自动执行回读验证。**你必须在文档写入完成后主 ### 进度输出示例 ``` -[INFO] 内容较长 (45000 字符),自动分片写入... -[INFO] 已创建空文档 (nodeId=abc123),开始分片写入... -[INFO] 写入分片 (1/3),15000 字符... -[INFO] 写入分片 (2/3),15000 字符... -[INFO] 写入分片 (3/3),15000 字符... +[INFO] 内容较长 (25000 字符),自动分片写入... +[INFO] 写入分片 (1/3),10000 字符 (create)... +[INFO] 文档已创建 (nodeId=abc123) +[INFO] 写入分片 (2/3),10000 字符... +[INFO] 写入分片 (3/3),5000 字符... [INFO] 全部 3 个分片写入完成 -{"success": true, "nodeId": "abc123", "chunksWritten": 3} +{"success":true,"nodeId":"abc123","chunksWritten":3} ``` ### CONTENT_TRUNCATED 错误 @@ -153,24 +153,16 @@ CLI **不会**自动执行回读验证。**你必须在文档写入完成后主 | `--content -` | 从 stdin 读取(可配合 heredoc/pipe) | | `--content-file path` | 从文件读取(UTF-8),推荐 | -### 短/中等长度(< 200KB)— 单步写入 +### 单一原生命令(所有长度默认路径) ```bash # 1. 把内容写入 UTF-8 文本文件: # Linux/Mac: /tmp/.md;Windows: %TEMP%\.md -# 2. 一步写入: +# 2. 一次调用;CLI 按需自动分片: dws doc update --node --content-file --mode overwrite --content-format markdown ``` -### 超长(> 200KB 兜底)— 分片追加 - -```bash -# 1. 按 markdown 标题或段落边界切成 ≤200KB 的片段(不要切断表格) -# 2. 逐个追加: -dws doc update --node --content-file --mode append --content-format markdown -``` - -> **注意**:分块 append 存在静默失败风险(部分片段返回 success 但实际未写入),执行前**必须**向用户发出截断风险提示并等待确认。完整规范见 [`../../best_practices/04-document.md` «分块 append 截断风险提示»](../04-document.md)。 +只有命令返回 `CONTENT_TRUNCATED`、被中断或回读确认缺失时,才先读取已写入内容定位断点,再用一次 `doc update --mode append --content-file ` 补缺失部分。不要在调用原生命令前复制一套手工分片循环。 ### stdin 变体 diff --git a/skills/multi/dingtalk-doc/references/doc/style/doc-update-workflow.md b/skills/multi/dingtalk-doc/references/doc/style/doc-update-workflow.md index 88d8c68f..e94780ad 100644 --- a/skills/multi/dingtalk-doc/references/doc/style/doc-update-workflow.md +++ b/skills/multi/dingtalk-doc/references/doc/style/doc-update-workflow.md @@ -99,7 +99,7 @@ JSONML 模式下这些元素的节点结构见 [doc-jsonml-schema.md](../format/ | 整篇按新骨架重写 | overwrite 全文(优先 JSONML;纯文本可用 markdown) | §4.5 | | 段落转表格 / 表格转段落 | block update --content-format jsonml;或 markdown overwrite 单段 | §4.4 / §4.1 | | 插入附件 / 图片 | doc media insert | §4.3 | -| 一次追加 >200KB 内容 | 分块 append + 用户风险确认 + 逐片记录 | §4.6 | +| 长 Markdown 追加 | 单一 `doc update --content-file`,由 CLI 自动分片;失败时再按真实断点恢复 | §4.6 | | 兜底:纯文本快速替换某段 | doc update --content overwrite(markdown) | §4.1 | --- @@ -254,17 +254,11 @@ dws doc update --node --content-file /tmp/-full.md --mode overwri **写入后必须回读**(§6)。如果发现旧内容残留,按 §6 的修复路径处理。 -### 4.6 超长内容追加(分块 append) +### 4.6 长 Markdown 追加与失败恢复 -当一次性追加内容 **超过 200KB** 时,必须拆分为多片 `--mode append`,并在执行第一片**之前**向用户发出截断风险提示等待确认。 +默认只执行一条 `doc update --node --mode append --content-file `。CLI 在超过 10,000 个 Unicode 字符时自动按结构分片,并在超时后缩小分片重试;不要预先手工拆片。 -完整规范(提示话术模板、触发条件、失败处理)见 [04-document.md «分块 append 截断风险提示»](../../04-document.md)。 - -update 场景下的额外约束: - -1. 按段落/标题边界切分,**禁止**在表格、代码块、列表内部截断 -2. 每写一片记录已写入的最后一个标题/段落标记,供 §6 回读比对 -3. 与既有内容衔接位置不能产生悬空标题或断列表 +只有返回 `CONTENT_TRUNCATED`、中断或 §6 回读发现缺失时,才按 [04-document.md «自动分片失败恢复»](../../04-document.md) 从最后一个真实完整段落补写缺失后缀。补写前报告已完成范围,补写后再次回读;同一缺失后缀最多自动校正一次。 --- diff --git a/skills/multi/dingtalk-doc/references/intent-guide.md b/skills/multi/dingtalk-doc/references/intent-guide.md index 95684503..4559ce2d 100644 --- a/skills/multi/dingtalk-doc/references/intent-guide.md +++ b/skills/multi/dingtalk-doc/references/intent-guide.md @@ -10,10 +10,11 @@ | "参照这个生成同样的 / 按模板生成 / 复刻 X / 同样的模板 X 月份的" + 已有 alidocs URL | 模板保形生成同形态变体 | `drive copy + drive rename + doc block update` → 见 [best_practices/04-document.md `template-based-generation`](../../dingtalk-doc/references/04-document.md#template-based-generation) | `doc read + doc create`(重写链) | adoc → markdown 是有损投影,read+create 会丢行高/单元格背景色/字号;copy 在 adoc 层保形复制后只在副本上局部修改 | | "这个 alidocs 表格链接帮我看下"(粘贴原始 URL) | 先 probe 节点类型 | `dws drive info --node` → 按 `extension` 路由 | 直接调 `sheet` | `alidocs/i/nodes/{id}` 可能是文档/axls/able/xlsx 等,禁止凭 URL 猜类型 | | "帮我记一下明天要做的事" | 创建个人待办 | `todo` | `doc` | 个人待办提醒,非文档内容 | -| "在知识库里创建一个文档" | 创建空文件实体 | `wiki node create --type adoc` | `doc create` | 空间内创建节点归 wiki;doc create 是向已有文档写入内容,不是创建文件节点 | +| "在这个知识库里写一篇/创建带内容的文档" | 在已知知识库根创建 adoc 并写入正文 | `doc create --workspace --name ... --content-file ...` | 先建空 wiki 节点再重复写入 | `doc create` 的真实 Cobra/Schema 支持 `--workspace`,适合一步创建带内容 adoc | +| "只在知识库里建一个空文档节点/整理节点层级" | 创建或管理知识库节点实体 | `wiki node create --type adoc` | `doc create` | 空节点与目录层级归 wiki;正文创作归 doc | | "帮我看看收到的日报" | 收到的日志 | `report` | `doc` | 钉钉日志系统(日报/周报),不是文档 | | "整理一下XX项目的所有讨论" | 跨源主题归档 | #5 generate-topic-report | #4 write-doc | #4 侧重单篇文档创作;按主题跨听记/群消息汇总属于工作汇报 | | "搜一下智能化方案/最近 OKR 相关邮件/最近发版相关消息" | 搜企业知识内容 | `aisearch enterprise` | `doc search` / `mail search` / `chat message search` | 跨文档、消息、日程、听记、邮件等企业内容语义检索走 enterprise;具体 `queries/types/time-range` 抽槽见 `aisearch.md` | | "我发给某人的消息/邮件/文档/今天我干了什么" | 搜行为记录 | `aisearch behavior` | `chat` / `mail` / `doc` / `report` | 关注“谁对什么做过什么”,走 behavior;具体 `behavior-type/direction/chat-scope` 抽槽见 `aisearch.md` | | "把这段文字翻译成英文/translate this" | 通用文本翻译 | `chat text translate` | `doc` / `aisearch` | 纯文本翻译,不是文档编辑或语义搜索 | -| "帮我把这个文档翻译成日文" | 文档内容翻译 | 先 `doc get` 再 `chat text translate` | `chat text translate` 直接传文件 | translate 仅支持纯文本,需先提取文档内容 | +| "帮我把这个文档翻译成日文" | 文档内容翻译 | 先 `doc read --node ` 再 `chat text translate` | `chat text translate` 直接传文件 | translate 仅支持纯文本,需先读取 adoc 正文 | diff --git a/skills/multi/dingtalk-doc/scripts/doc_create_and_write.py b/skills/multi/dingtalk-doc/scripts/doc_create_and_write.py index fbf52f8d..a306b0e5 100644 --- a/skills/multi/dingtalk-doc/scripts/doc_create_and_write.py +++ b/skills/multi/dingtalk-doc/scripts/doc_create_and_write.py @@ -1,181 +1,179 @@ #!/usr/bin/env python3 -""" -在指定目录创建文档并写入 Markdown 内容(一键完成) +"""用原生 dws 写入管道创建文档,并回读验证。""" -用法: - python doc_create_and_write.py \ - --name "项目周报" \ - --content "# 本周总结\n\n## 完成事项\n- 任务A" +from __future__ import annotations - python doc_create_and_write.py \ - --name "会议纪要" \ - --content-file notes.md - - python doc_create_and_write.py \ - --name "知识库文档" --content "# 内容" --folder FOLDER_ID - - python doc_create_and_write.py --name "test" --content "hello" --dry-run -""" - -import sys -import json -import time -import subprocess import argparse +import json +import shlex +import subprocess +import sys +import tempfile from pathlib import Path -from typing import List, Any, Optional +from typing import Any, Optional, Sequence -def run_dws( - args: List[str], dry_run: bool = False, -) -> Optional[Any]: - cmd = ['dws'] + args +class ScriptError(RuntimeError): + """可预期的脚本执行错误。""" + + +def decode_json_output(output: str) -> Any: + """解析 JSON;兼容长内容写入前置的进度行。""" + text = output.strip() + if not text: + raise ScriptError("dws 未返回 JSON") + try: + return json.loads(text) + except json.JSONDecodeError: + decoder = json.JSONDecoder() + for offset, character in enumerate(text): + if character not in "[{": + continue + try: + value, end = decoder.raw_decode(text, offset) + except json.JSONDecodeError: + continue + if not text[end:].strip(): + return value + raise ScriptError("dws 返回的不是合法 JSON") + + +def run_dws(args: Sequence[str], dry_run: bool = False) -> Any: + """执行一条 dws 命令,并把命令/业务失败统一转成 ScriptError。""" + command = ["dws", *args] if dry_run: - print(f"[dry-run] {' '.join(cmd)}") - return {'dry_run': True} + print(f"[dry-run] {shlex.join(command)}") + return {"dry_run": True} try: result = subprocess.run( - cmd, capture_output=True, text=True, timeout=60 + command, + capture_output=True, + text=True, + timeout=120, + check=False, ) - if result.returncode != 0: - print(f" ✗ 错误:{result.stderr.strip()}") - return None - return json.loads(result.stdout) - except (subprocess.TimeoutExpired, json.JSONDecodeError, - FileNotFoundError) as e: - print(f" ✗ 错误:{e}") - return None + except (subprocess.TimeoutExpired, FileNotFoundError) as exc: + raise ScriptError(f"执行 dws 失败:{exc}") from exc + if result.returncode != 0: + detail = result.stderr.strip() or result.stdout.strip() + raise ScriptError( + f"dws 命令失败:{detail or f'退出码 {result.returncode}'}" + ) + data = decode_json_output(result.stdout) + if isinstance(data, dict) and data.get("success") is False: + detail = data.get("errorMsg") or data.get("message") or "未知错误" + raise ScriptError(f"dws 业务调用失败:{detail}") + return data -def run_dws_with_retry( - args: List[str], - dry_run: bool = False, - max_retries: int = 3, - retry_delay: float = 1.0, -) -> Optional[Any]: - """带重试机制的 dws 命令执行""" - last_error = None - for attempt in range(1, max_retries + 1): - result = run_dws(args, dry_run=dry_run) - if result is not None: - return result - if attempt < max_retries: - print(f" ⚠️ 第 {attempt} 次尝试失败,{retry_delay}秒后重试...") - time.sleep(retry_delay) - retry_delay *= 1.5 # 指数退避 - return None +def first_value(payload: Any, keys: Sequence[str]) -> str: + """从嵌套响应中提取第一个非空稳定字段。""" + if isinstance(payload, dict): + for key in keys: + value = payload.get(key) + if value is not None and str(value).strip(): + return str(value).strip() + for value in payload.values(): + found = first_value(value, keys) + if found: + return found + elif isinstance(payload, list): + for value in payload: + found = first_value(value, keys) + if found: + return found + return "" -def main(): +def run(argv: Optional[Sequence[str]] = None) -> int: parser = argparse.ArgumentParser( - description='创建文档并写入内容' + description="使用 dws doc create 创建文档并回读验证" ) - parser.add_argument('--name', required=True, help='文档名称') - parser.add_argument('--content', default='', help='Markdown 内容') - parser.add_argument('--content-file', default='', help='内容文件') - parser.add_argument('--folder', default='', help='目标文件夹 ID 或 URL') - parser.add_argument('--workspace', default='', help='目标知识库 ID') - parser.add_argument( - '--mode', default='append', choices=['overwrite', 'append'], - help='写入模式: overwrite=覆盖, append=追加 (默认 append)', + parser.add_argument("--name", required=True, help="文档名称") + content_group = parser.add_mutually_exclusive_group(required=True) + content_group.add_argument("--content", help="Markdown 内容") + content_group.add_argument("--content-file", help="UTF-8 Markdown 文件") + location_group = parser.add_mutually_exclusive_group() + location_group.add_argument( + "--folder", default="", help="目标文档文件夹 ID 或 URL" ) - parser.add_argument( - '--max-retries', type=int, default=3, - help='每块写入失败时的最大重试次数 (默认 3)', + location_group.add_argument( + "--workspace", default="", help="目标知识库 ID 或 URL" ) - parser.add_argument('--dry-run', action='store_true') - args = parser.parse_args() + parser.add_argument("--dry-run", action="store_true") + args = parser.parse_args(argv) - content = args.content + supplied_path: Optional[Path] = None + temporary_path: Optional[Path] = None if args.content_file: - p = Path(args.content_file) - if not p.exists(): - print(f"错误:文件不存在: {p}") - sys.exit(1) - content = p.read_text(encoding='utf-8') - if not content: - print('错误:需要 --content 或 --content-file') - sys.exit(1) - chunk_size = 10000 + supplied_path = Path(args.content_file) + if not supplied_path.is_file(): + raise ScriptError(f"内容文件不存在:{supplied_path}") + elif not args.content or not args.content.strip(): + raise ScriptError("--content 不能为空") - create_args = ['doc', 'create', '--name', args.name, '--format', 'json'] - if args.folder: - create_args.extend(['--folder', args.folder]) - if args.workspace: - create_args.extend(['--workspace', args.workspace]) + try: + if supplied_path is None and not args.dry_run: + with tempfile.NamedTemporaryFile( + mode="w", encoding="utf-8", suffix=".md", delete=False + ) as handle: + handle.write(args.content) + temporary_path = Path(handle.name) + supplied_path = temporary_path - print(f'\n📝 创建文档: {args.name}') - create_data = run_dws(create_args, dry_run=args.dry_run) + content_path = str(supplied_path) if supplied_path else "" + create_args = [ + "doc", "create", + "--name", args.name, + "--content-file", content_path, + "--content-format", "markdown", + "--format", "json", + ] + if args.folder: + create_args.extend(["--folder", args.folder]) + if args.workspace: + create_args.extend(["--workspace", args.workspace]) - node_id = None - if not args.dry_run: - if not create_data: - sys.exit(1) - node_id = (create_data.get('nodeId') - or create_data.get('dentryUuid') - or create_data.get('id', '')) - print(f" ✓ 文档已创建 (ID: {node_id})") + created = run_dws(create_args, dry_run=args.dry_run) + node_id = "" if args.dry_run else first_value( + created, ("nodeId", "dentryUuid") + ) + if not node_id: + raise ScriptError("文档创建响应缺少 nodeId,无法验证") - if len(content) <= chunk_size: - mode_label = '追加' if args.mode == 'append' else '覆盖' - print(f'\n✍️ 写入内容 (模式: {mode_label}, {len(content)} 字符)...') - write_data = run_dws([ - 'doc', 'update', - '--node', node_id or '', - '--content', content, - '--mode', args.mode, - '--format', 'json', - ], dry_run=args.dry_run) - if write_data: - print(f" ✓ 内容已写入 ({len(content)} 字符)") - else: - chunks = [] - pos = 0 - while pos < len(content): - end = min(pos + chunk_size, len(content)) - if end < len(content): - newline_pos = content.rfind('\n', pos, end) - if newline_pos > pos: - end = newline_pos + 1 - chunks.append(content[pos:end]) - pos = end + info = run_dws( + ["doc", "info", "--node", node_id, "--format", "json"], + dry_run=args.dry_run, + ) + run_dws( + ["doc", "read", "--node", node_id, "--format", "json"], + dry_run=args.dry_run, + ) + if args.dry_run: + return 0 - total_chunks = len(chunks) - print(f'\n✍️ 内容较长 ({len(content)} 字符), 分 {total_chunks} 块写入...') - - success_chunks = 0 - for idx, chunk in enumerate(chunks): - chunk_mode = args.mode if idx == 0 else 'append' - write_data = run_dws_with_retry( - [ - 'doc', 'update', - '--node', node_id or '', - '--content', chunk, - '--mode', chunk_mode, - '--format', 'json', - ], - dry_run=args.dry_run, - max_retries=args.max_retries, - ) - if write_data: - print(f" ✓ 块 {idx + 1}/{total_chunks} 已写入 ({len(chunk)} 字符)") - success_chunks += 1 - elif not args.dry_run: - # 写入失败,报告部分写入状态 - print(f"\n❌ 块 {idx + 1}/{total_chunks} 写入失败(已重试 {args.max_retries} 次)") - print(f"\n⚠️ 文档处于部分写入状态:") - print(f" - 文档 ID: {node_id}") - print(f" - 已写入: {success_chunks}/{total_chunks} 块") - print(f" - 失败位置: 第 {idx + 1} 块") - if args.mode == 'overwrite': - print(f" - 模式: 覆盖模式,文档可能包含不完整内容") - print(f" - 建议: 手动检查文档内容,或删除后重新创建") - else: - print(f" - 模式: 追加模式,已写入内容已保存") - print(f" - 建议: 可手动补充剩余内容,或重新运行脚本") - sys.exit(1) - print('\n✅ 完成!') + summary = { + "success": True, + "nodeId": node_id, + "docUrl": first_value(info, ("docUrl", "documentUrl", "url")) + or first_value(created, ("docUrl", "documentUrl", "url")), + "chunksWritten": first_value(created, ("chunksWritten",)), + "verified": True, + } + print(json.dumps(summary, ensure_ascii=False)) + return 0 + finally: + if temporary_path is not None: + temporary_path.unlink(missing_ok=True) -if __name__ == '__main__': +def main() -> None: + try: + raise SystemExit(run()) + except ScriptError as exc: + print(f"错误:{exc}", file=sys.stderr) + raise SystemExit(1) from exc + + +if __name__ == "__main__": main() diff --git a/test/scripts/doc_skill_scripts_test.py b/test/scripts/doc_skill_scripts_test.py new file mode 100644 index 00000000..7a68b873 --- /dev/null +++ b/test/scripts/doc_skill_scripts_test.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +"""Regression tests for the Doc Skill and its optional wrapper script.""" + +import contextlib +import importlib.util +import io +import json +import subprocess +import unittest +from pathlib import Path +from unittest import mock + + +ROOT = Path(__file__).resolve().parents[2] +SKILL_ROOT = ROOT / "skills" / "multi" / "dingtalk-doc" +SCRIPT_PATH = SKILL_ROOT / "scripts" / "doc_create_and_write.py" + + +def load_script(): + spec = importlib.util.spec_from_file_location("doc_create_and_write", SCRIPT_PATH) + if spec is None or spec.loader is None: + raise RuntimeError(f"cannot load {SCRIPT_PATH}") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +class DocSkillAlignmentTest(unittest.TestCase): + def test_shortcuts_use_progressive_discovery(self): + skill = (SKILL_ROOT / "SKILL.md").read_text(encoding="utf-8") + catalog = json.loads( + (ROOT / "docs" / "shortcut-public-catalog.json").read_text( + encoding="utf-8" + ) + ) + runtime_shortcuts = [ + row for row in catalog["results"] if row.get("service") == "doc" + ] + schema = json.loads( + ( + ROOT + / "internal" + / "cli" + / "schema_catalog" + / "tools" + / "doc.json" + ).read_text(encoding="utf-8") + ) + schema_shortcuts = [ + path for path in schema["tools"] if path.startswith("doc.shortcut_") + ] + self.assertEqual(17, len(runtime_shortcuts)) + self.assertEqual(17, len(schema_shortcuts)) + self.assertIn("17 条公开 Shortcut,已全部进入 Runtime Schema", skill) + self.assertIn( + "dws shortcut list --service doc --compact --format json", skill + ) + self.assertNotIn("| `dws doc +", skill) + + def test_native_pipeline_is_the_only_default_chunker(self): + texts = [ + path.read_text(encoding="utf-8") + for path in [SKILL_ROOT / "SKILL.md", *SKILL_ROOT.rglob("*.md")] + ] + combined = "\n".join(texts) + self.assertNotIn(">30000", combined) + self.assertNotIn("超过 30000", combined) + self.assertNotIn(">200KB", combined) + self.assertNotIn("超过 200KB", combined) + self.assertNotIn("doc get", combined) + + +class DocCreateAndWriteTest(unittest.TestCase): + def setUp(self): + self.module = load_script() + + def test_decode_json_output_accepts_progress_lines(self): + data = self.module.decode_json_output( + '[INFO] 写入分片 (1/2)\n{\n "success": true,\n' + ' "nodeId": "doc-1"\n}\n' + ) + self.assertEqual("doc-1", data["nodeId"]) + + def test_folder_and_workspace_are_mutually_exclusive(self): + with self.assertRaises(SystemExit): + self.module.run( + [ + "--name", + "周报", + "--content", + "hello", + "--folder", + "folder-1", + "--workspace", + "workspace-1", + "--dry-run", + ] + ) + + def test_run_dws_rejects_nonzero_and_business_failure(self): + with mock.patch.object( + self.module.subprocess, + "run", + return_value=subprocess.CompletedProcess( + ["dws"], 2, stdout="", stderr="unknown flag" + ), + ): + with self.assertRaisesRegex(self.module.ScriptError, "unknown flag"): + self.module.run_dws(["doc", "create"]) + + with mock.patch.object( + self.module.subprocess, + "run", + return_value=subprocess.CompletedProcess( + ["dws"], + 0, + stdout='{"success":false,"message":"denied"}', + stderr="", + ), + ): + with self.assertRaisesRegex(self.module.ScriptError, "denied"): + self.module.run_dws(["doc", "create"]) + + def test_wrapper_uses_create_then_info_and_read_without_manual_update(self): + calls = [] + + def fake_run(args, dry_run=False): + calls.append(list(args)) + if args[:2] == ["doc", "create"]: + return {"success": True, "nodeId": "doc-1", "chunksWritten": 2} + if args[:2] == ["doc", "info"]: + return {"success": True, "docUrl": "https://example.test/doc-1"} + return {"success": True, "markdown": "hello"} + + stdout = io.StringIO() + with mock.patch.object(self.module, "run_dws", side_effect=fake_run): + with contextlib.redirect_stdout(stdout): + code = self.module.run(["--name", "周报", "--content", "hello"]) + + self.assertEqual(0, code) + self.assertEqual(["create", "info", "read"], [call[1] for call in calls]) + self.assertFalse(any(call[:2] == ["doc", "update"] for call in calls)) + summary = json.loads(stdout.getvalue().splitlines()[-1]) + self.assertEqual("doc-1", summary["nodeId"]) + self.assertTrue(summary["verified"]) + + def test_dry_run_shows_create_and_verification_commands(self): + stdout = io.StringIO() + with contextlib.redirect_stdout(stdout): + code = self.module.run( + ["--name", "周报", "--content", "hello", "--dry-run"] + ) + self.assertEqual(0, code) + output = stdout.getvalue() + self.assertIn("dws doc create", output) + self.assertIn("dws doc info", output) + self.assertIn("dws doc read", output) + + +if __name__ == "__main__": + unittest.main() From 31cec9efa71be8d72fbb5035d7271a1c1c2dd057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=91=9E=E8=BE=BE?= Date: Wed, 5 Aug 2026 15:47:47 +0800 Subject: [PATCH 2/2] feat(aitable): align skill with progressive schema loading --- .../cli/schema_agent_metadata/aitable.json | 186 +++---- internal/cli/schema_agent_metadata/index.json | 23 +- internal/cli/schema_agent_metadata_audit.json | 2 +- internal/cli/schema_catalog/catalog.json | 79 +-- .../cli/schema_catalog/tools/aitable.json | 186 +++---- .../cli/schema_hints/selection/aitable.json | 83 +-- scripts/gen_skill_shortcut_sections.py | 2 +- scripts/policy/check-skill-context-budget.sh | 25 +- skills/multi/dingtalk-aitable/SKILL.md | 190 +++---- .../dingtalk-aitable/references/aitable.md | 24 +- .../references/aitable/aitable-attachment.md | 1 + .../aitable/aitable-error-recovery.md | 18 +- .../aitable/aitable-export-import.md | 4 + .../references/aitable/aitable-field.md | 2 +- .../aitable/aitable-record-create.md | 2 + .../aitable/aitable-record-query.md | 2 +- .../aitable/aitable-record-update.md | 12 +- .../scripts/aitable_export_via_task.py | 41 +- .../scripts/aitable_import_via_task.py | 4 + .../scripts/bulk_add_fields.py | 437 ++++++++-------- .../scripts/import_records.py | 481 ++++++++---------- .../scripts/upload_attachment.py | 51 +- test/scripts/aitable_skill_scripts_test.py | 208 ++++++++ test/unit/aitable_skill_scripts_test.go | 30 ++ 24 files changed, 1148 insertions(+), 945 deletions(-) create mode 100644 test/scripts/aitable_skill_scripts_test.py create mode 100644 test/unit/aitable_skill_scripts_test.go diff --git a/internal/cli/schema_agent_metadata/aitable.json b/internal/cli/schema_agent_metadata/aitable.json index cfc2f451..1c1edb48 100644 --- a/internal/cli/schema_agent_metadata/aitable.json +++ b/internal/cli/schema_agent_metadata/aitable.json @@ -264,7 +264,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "知道名称并要解析唯一 baseId 用 +resolve-base;按关键词要完整候选用 +base-search;不要把最近访问列表描述成全部 Base" ], "confirmation": "not_required", "effect": "read", @@ -308,7 +308,7 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "知道名称并要解析唯一 baseId 用 +resolve-base;按关键词要完整候选用 +base-search;不要把最近访问列表描述成全部 Base" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -317,7 +317,7 @@ "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "知道名称并要解析唯一 baseId 用 +resolve-base;按关键词要完整候选用 +base-search;不要把最近访问列表描述成全部 Base" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -525,7 +525,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需唯一 baseId 用 +resolve-base;浏览最近访问用 +base-list;需要未公开底层参数或原始响应才用 base search" ], "confirmation": "not_required", "effect": "read", @@ -568,7 +568,7 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需唯一 baseId 用 +resolve-base;浏览最近访问用 +base-list;需要未公开底层参数或原始响应才用 base search" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -577,7 +577,7 @@ "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需唯一 baseId 用 +resolve-base;浏览最近访问用 +base-list;需要未公开底层参数或原始响应才用 base search" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -1815,7 +1815,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需精简 fieldId/type 目录用 +table-get;创建或修改字段用 field create/update;需要未公开底层语义才用 field get" ], "confirmation": "not_required", "effect": "read", @@ -1858,7 +1858,7 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需精简 fieldId/type 目录用 +table-get;创建或修改字段用 field create/update;需要未公开底层语义才用 field get" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -1867,7 +1867,7 @@ "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需精简 fieldId/type 目录用 +table-get;创建或修改字段用 field create/update;需要未公开底层语义才用 field get" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -3624,7 +3624,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "完全空行扫描用 +record-query-empty;变更历史用 +record-history-list;需要 --all/--page-limit 或未公开底层语义才用 record query" ], "confirmation": "not_required", "effect": "read", @@ -3667,7 +3667,7 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "完全空行扫描用 +record-query-empty;变更历史用 +record-history-list;需要 --all/--page-limit 或未公开底层语义才用 record query" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -3676,7 +3676,7 @@ "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "完全空行扫描用 +record-query-empty;变更历史用 +record-history-list;需要 --all/--page-limit 或未公开底层语义才用 record query" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -4659,7 +4659,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;只要完整候选列表用 +base-search;浏览最近访问用 +base-list;已知 baseId 不再重复搜索" ], "confirmation": "not_required", "effect": "read", @@ -4702,7 +4702,7 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;只要完整候选列表用 +base-search;浏览最近访问用 +base-list;已知 baseId 不再重复搜索" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -4711,7 +4711,7 @@ "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;只要完整候选列表用 +base-search;浏览最近访问用 +base-list;已知 baseId 不再重复搜索" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -4877,7 +4877,7 @@ }, "use_when": { "value": [ - "当你只知道某个多维表 Base 的名称(或名称里的关键词)、想把它解析成可直接用于后续工具的 baseId 时使用;内部按 --name 关键词调用 search_bases 搜索 Base,再在本地投影出每个候选的 baseId 和 name。如果只命中一个 Base 就直接返回它的 baseId;如果命中多个则列出全部候选让你消歧,绝不替你瞎猜;如果一个都没命中则提示未找到。这是纯只读操作,只做搜索与本地投影,不会修改任何 Base。" + "只知道 Base 名称或关键词,需要解析成唯一 baseId 供后续 Table/Record 操作时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -4886,7 +4886,7 @@ "candidates": [ { "value": [ - "当你只知道某个多维表 Base 的名称(或名称里的关键词)、想把它解析成可直接用于后续工具的 baseId 时使用;内部按 --name 关键词调用 search_bases 搜索 Base,再在本地投影出每个候选的 baseId 和 name。如果只命中一个 Base 就直接返回它的 baseId;如果命中多个则列出全部候选让你消歧,绝不替你瞎猜;如果一个都没命中则提示未找到。这是纯只读操作,只做搜索与本地投影,不会修改任何 Base。" + "只知道 Base 名称或关键词,需要解析成唯一 baseId 供后续 Table/Record 操作时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -4909,7 +4909,7 @@ "internal/cli/schema_hints/selection/aitable.json" ], "use_when": [ - "当你只知道某个多维表 Base 的名称(或名称里的关键词)、想把它解析成可直接用于后续工具的 baseId 时使用;内部按 --name 关键词调用 search_bases 搜索 Base,再在本地投影出每个候选的 baseId 和 name。如果只命中一个 Base 就直接返回它的 baseId;如果命中多个则列出全部候选让你消歧,绝不替你瞎猜;如果一个都没命中则提示未找到。这是纯只读操作,只做搜索与本地投影,不会修改任何 Base。" + "只知道 Base 名称或关键词,需要解析成唯一 baseId 供后续 Table/Record 操作时" ] }, "aitable +resolve-table": { @@ -4917,7 +4917,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;需要所有表及字段/视图目录用 +table-get;已知 tableId 不再重复解析" ], "confirmation": "not_required", "effect": "read", @@ -4960,7 +4960,7 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;需要所有表及字段/视图目录用 +table-get;已知 tableId 不再重复解析" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -4969,7 +4969,7 @@ "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;需要所有表及字段/视图目录用 +table-get;已知 tableId 不再重复解析" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -5135,7 +5135,7 @@ }, "use_when": { "value": [ - "当你已经知道某个多维表 Base 的 baseId、又只记得里面某张数据表(table)的名称或名称关键词、想把它解析成可直接用于后续工具的 tableId 时使用;内部先用 get_tables(只传 baseId)列出该 Base 下的全部数据表,再在本地把每张表投影成 tableId、name,并按 --name 关键词做大小写不敏感的包含匹配来筛选候选。如果只命中一张表就直接返回它的 tableId;如果命中多张则列出全部候选让你消歧,绝不替你瞎猜;如果一张都没命中则提示未找到。这是纯只读操作,只做列举、本地匹配与投影,不会创建、修改或删除任何数据表。" + "已有真实 baseId、只知道数据表名称或关键词,需要解析成唯一 tableId 时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -5144,7 +5144,7 @@ "candidates": [ { "value": [ - "当你已经知道某个多维表 Base 的 baseId、又只记得里面某张数据表(table)的名称或名称关键词、想把它解析成可直接用于后续工具的 tableId 时使用;内部先用 get_tables(只传 baseId)列出该 Base 下的全部数据表,再在本地把每张表投影成 tableId、name,并按 --name 关键词做大小写不敏感的包含匹配来筛选候选。如果只命中一张表就直接返回它的 tableId;如果命中多张则列出全部候选让你消歧,绝不替你瞎猜;如果一张都没命中则提示未找到。这是纯只读操作,只做列举、本地匹配与投影,不会创建、修改或删除任何数据表。" + "已有真实 baseId、只知道数据表名称或关键词,需要解析成唯一 tableId 时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -5167,7 +5167,7 @@ "internal/cli/schema_hints/selection/aitable.json" ], "use_when": [ - "当你已经知道某个多维表 Base 的 baseId、又只记得里面某张数据表(table)的名称或名称关键词、想把它解析成可直接用于后续工具的 tableId 时使用;内部先用 get_tables(只传 baseId)列出该 Base 下的全部数据表,再在本地把每张表投影成 tableId、name,并按 --name 关键词做大小写不敏感的包含匹配来筛选候选。如果只命中一张表就直接返回它的 tableId;如果命中多张则列出全部候选让你消歧,绝不替你瞎猜;如果一张都没命中则提示未找到。这是纯只读操作,只做列举、本地匹配与投影,不会创建、修改或删除任何数据表。" + "已有真实 baseId、只知道数据表名称或关键词,需要解析成唯一 tableId 时" ] }, "aitable +role-list": { @@ -5949,7 +5949,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只知道表名并要解析唯一 tableId 用 +resolve-table;需要字段完整 config 用 +field-get;需要未公开底层语义才用 table get" ], "confirmation": "not_required", "effect": "read", @@ -5993,7 +5993,7 @@ }, "avoid_when": { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只知道表名并要解析唯一 tableId 用 +resolve-table;需要字段完整 config 用 +field-get;需要未公开底层语义才用 table get" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -6002,7 +6002,7 @@ "candidates": [ { "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只知道表名并要解析唯一 tableId 用 +resolve-table;需要字段完整 config 用 +field-get;需要未公开底层语义才用 table get" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -11191,11 +11191,11 @@ ] }, "aitable base search": { - "agent_summary": "按名称搜索 AI 表格 Base(优先于仅最近访问的 list)。", + "agent_summary": "底层按名称搜索 AI 表格 Base,返回原始候选列表。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "只要最近访问列表用 base list;已知 baseId 取详情用 base get;电子表格 axls 用 sheet" + "普通按名称解析唯一 baseId 优先用 +resolve-base;只要候选列表用 +base-search;最近访问用 +base-list;电子表格 axls 用 sheet" ], "confirmation": "not_required", "effect": "read", @@ -11205,14 +11205,14 @@ ], "field_provenance": { "agent_summary": { - "value": "按名称搜索 AI 表格 Base(优先于仅最近访问的 list)。", + "value": "底层按名称搜索 AI 表格 Base,返回原始候选列表。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "candidates": [ { - "value": "按名称搜索 AI 表格 Base(优先于仅最近访问的 list)。", + "value": "底层按名称搜索 AI 表格 Base,返回原始候选列表。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "selected": true, @@ -11244,7 +11244,7 @@ }, "avoid_when": { "value": [ - "只要最近访问列表用 base list;已知 baseId 取详情用 base get;电子表格 axls 用 sheet" + "普通按名称解析唯一 baseId 优先用 +resolve-base;只要候选列表用 +base-search;最近访问用 +base-list;电子表格 axls 用 sheet" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -11253,7 +11253,7 @@ "candidates": [ { "value": [ - "只要最近访问列表用 base list;已知 baseId 取详情用 base get;电子表格 axls 用 sheet" + "普通按名称解析唯一 baseId 优先用 +resolve-base;只要候选列表用 +base-search;最近访问用 +base-list;电子表格 axls 用 sheet" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -11407,7 +11407,7 @@ }, "use_when": { "value": [ - "用户要找某个 AI 表格/多维表,按名称检索时优先使用" + "需要 Shortcut 未公开的底层参数、原始 search_bases 响应或自定义候选处理时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -11416,7 +11416,7 @@ "candidates": [ { "value": [ - "用户要找某个 AI 表格/多维表,按名称检索时优先使用" + "需要 Shortcut 未公开的底层参数、原始 search_bases 响应或自定义候选处理时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -11441,10 +11441,12 @@ "internal/cli/schema_hints/metadata/aitable.json", "internal/cli/schema_hints/selection/aitable.json", "internal/cli/schema_mcp_metadata.json#tools.aitable.base_search", - "skills/mono/references/products/aitable.md" + "skills/mono/references/products/aitable.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable.md" ], "use_when": [ - "用户要找某个 AI 表格/多维表,按名称检索时优先使用" + "需要 Shortcut 未公开的底层参数、原始 search_bases 响应或自定义候选处理时" ] }, "aitable base update": { @@ -16699,11 +16701,11 @@ ] }, "aitable field get": { - "agent_summary": "获取字段完整配置。", + "agent_summary": "底层获取字段完整类型与 config。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "表级字段目录也可用 table get;创建字段用 field create;不可用本命令改类型" + "正常按字段 ID 展开类型/config 优先用 +field-get;精简字段目录用 +table-get;创建字段用 field create" ], "confirmation": "not_required", "effect": "read", @@ -16713,14 +16715,14 @@ ], "field_provenance": { "agent_summary": { - "value": "获取字段完整配置。", + "value": "底层获取字段完整类型与 config。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "candidates": [ { - "value": "获取字段完整配置。", + "value": "底层获取字段完整类型与 config。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "selected": true, @@ -16752,7 +16754,7 @@ }, "avoid_when": { "value": [ - "表级字段目录也可用 table get;创建字段用 field create;不可用本命令改类型" + "正常按字段 ID 展开类型/config 优先用 +field-get;精简字段目录用 +table-get;创建字段用 field create" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -16761,7 +16763,7 @@ "candidates": [ { "value": [ - "表级字段目录也可用 table get;创建字段用 field create;不可用本命令改类型" + "正常按字段 ID 展开类型/config 优先用 +field-get;精简字段目录用 +table-get;创建字段用 field create" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -16913,7 +16915,7 @@ }, "use_when": { "value": [ - "需要字段类型/config(选项、公式等)详情时" + "需要 +field-get 未公开的底层参数、原始响应或不同执行语义时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -16922,7 +16924,7 @@ "candidates": [ { "value": [ - "需要字段类型/config(选项、公式等)详情时" + "需要 +field-get 未公开的底层参数、原始响应或不同执行语义时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -16950,10 +16952,12 @@ "internal/cli/schema_hints/selection/aitable.json", "internal/cli/schema_mcp_metadata.json#tools.aitable.field_get", "skills/mono/references/products/aitable.md", - "skills/mono/references/products/aitable/aitable-field.md" + "skills/mono/references/products/aitable/aitable-field.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-field.md" ], "use_when": [ - "需要字段类型/config(选项、公式等)详情时" + "需要 +field-get 未公开的底层参数、原始响应或不同执行语义时" ] }, "aitable field list": { @@ -22339,11 +22343,11 @@ ] }, "aitable record create": { - "agent_summary": "新增记录(cells 的 key 必须是 fieldId)。", + "agent_summary": "新增记录;使用 fieldId 写入并从 newRecordIds 回读验证。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "更新已有行用 record update;有则更无则增用 upsert;批量同 patch 用 batch-update" + "未核对字段类型时先 field get;更新已有行用 record update;有则更无则增用 upsert;本地 CSV/JSON 批量追加可用已评审脚本" ], "confirmation": "not_required", "effect": "write", @@ -22353,14 +22357,14 @@ ], "field_provenance": { "agent_summary": { - "value": "新增记录(cells 的 key 必须是 fieldId)。", + "value": "新增记录;使用 fieldId 写入并从 newRecordIds 回读验证。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "candidates": [ { - "value": "新增记录(cells 的 key 必须是 fieldId)。", + "value": "新增记录;使用 fieldId 写入并从 newRecordIds 回读验证。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "selected": true, @@ -22392,7 +22396,7 @@ }, "avoid_when": { "value": [ - "更新已有行用 record update;有则更无则增用 upsert;批量同 patch 用 batch-update" + "未核对字段类型时先 field get;更新已有行用 record update;有则更无则增用 upsert;本地 CSV/JSON 批量追加可用已评审脚本" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -22401,7 +22405,7 @@ "candidates": [ { "value": [ - "更新已有行用 record update;有则更无则增用 upsert;批量同 patch 用 batch-update" + "未核对字段类型时先 field get;更新已有行用 record update;有则更无则增用 upsert;本地 CSV/JSON 批量追加可用已评审脚本" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -22553,7 +22557,7 @@ }, "use_when": { "value": [ - "需要插入新行数据时" + "已取得 baseId/tableId 与字段完整配置,需要插入一条或多条新记录并回读时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -22562,7 +22566,7 @@ "candidates": [ { "value": [ - "需要插入新行数据时" + "已取得 baseId/tableId 与字段完整配置,需要插入一条或多条新记录并回读时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -22592,10 +22596,12 @@ "skills/mono/references/products/aitable-record-ops.md", "skills/mono/references/products/aitable.md", "skills/mono/references/products/aitable/aitable-attachment.md", - "skills/mono/references/products/aitable/aitable-record-create.md" + "skills/mono/references/products/aitable/aitable-record-create.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-record-create.md" ], "use_when": [ - "需要插入新行数据时" + "已取得 baseId/tableId 与字段完整配置,需要插入一条或多条新记录并回读时" ] }, "aitable record delete": { @@ -23929,11 +23935,11 @@ ] }, "aitable record query": { - "agent_summary": "查询/搜索记录(filters/sort/分页/--all;cells 键为 fieldId)。", + "agent_summary": "底层查询/搜索记录,额外支持原子命令的完整分页控制。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "已知 recordId 窄查可用 record get;空行用 query-empty;写入用 create/update;电子表格单元格用 sheet" + "普通按 ID、关键词、filters、sort 或 cursor 查询优先用 +record-query;空行用 +record-query-empty;写入用 create/update;电子表格单元格用 sheet" ], "confirmation": "not_required", "effect": "read", @@ -23943,14 +23949,14 @@ ], "field_provenance": { "agent_summary": { - "value": "查询/搜索记录(filters/sort/分页/--all;cells 键为 fieldId)。", + "value": "底层查询/搜索记录,额外支持原子命令的完整分页控制。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "candidates": [ { - "value": "查询/搜索记录(filters/sort/分页/--all;cells 键为 fieldId)。", + "value": "底层查询/搜索记录,额外支持原子命令的完整分页控制。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "selected": true, @@ -23982,7 +23988,7 @@ }, "avoid_when": { "value": [ - "已知 recordId 窄查可用 record get;空行用 query-empty;写入用 create/update;电子表格单元格用 sheet" + "普通按 ID、关键词、filters、sort 或 cursor 查询优先用 +record-query;空行用 +record-query-empty;写入用 create/update;电子表格单元格用 sheet" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -23991,7 +23997,7 @@ "candidates": [ { "value": [ - "已知 recordId 窄查可用 record get;空行用 query-empty;写入用 create/update;电子表格单元格用 sheet" + "普通按 ID、关键词、filters、sort 或 cursor 查询优先用 +record-query;空行用 +record-query-empty;写入用 create/update;电子表格单元格用 sheet" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -24151,7 +24157,7 @@ }, "use_when": { "value": [ - "查看、筛选、全文搜索或遍历记录时的主入口" + "需要 +record-query 未公开的 --all/--page-limit、底层原始响应或不同执行语义时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -24160,7 +24166,7 @@ "candidates": [ { "value": [ - "查看、筛选、全文搜索或遍历记录时的主入口" + "需要 +record-query 未公开的 --all/--page-limit、底层原始响应或不同执行语义时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -24189,10 +24195,12 @@ "internal/cli/schema_mcp_metadata.json#tools.aitable.query_records", "skills/mono/references/products/aitable-record-ops.md", "skills/mono/references/products/aitable.md", - "skills/mono/references/products/aitable/aitable-record-query.md" + "skills/mono/references/products/aitable/aitable-record-query.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-record-query.md" ], "use_when": [ - "查看、筛选、全文搜索或遍历记录时的主入口" + "需要 +record-query 未公开的 --all/--page-limit、底层原始响应或不同执行语义时" ] }, "aitable record query-empty": { @@ -24711,11 +24719,11 @@ ] }, "aitable record update": { - "agent_summary": "更新已有记录字段(先 query 拿 recordId;只传需改字段)。", + "agent_summary": "更新已有记录字段;先 query 拿 recordId,使用 fieldId 写入并回读。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" + "未定位 recordId 或字段配置时先 query/field get;新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" ], "confirmation": "not_required", "effect": "write", @@ -24725,14 +24733,14 @@ ], "field_provenance": { "agent_summary": { - "value": "更新已有记录字段(先 query 拿 recordId;只传需改字段)。", + "value": "更新已有记录字段;先 query 拿 recordId,使用 fieldId 写入并回读。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "candidates": [ { - "value": "更新已有记录字段(先 query 拿 recordId;只传需改字段)。", + "value": "更新已有记录字段;先 query 拿 recordId,使用 fieldId 写入并回读。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "selected": true, @@ -24764,7 +24772,7 @@ }, "avoid_when": { "value": [ - "新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" + "未定位 recordId 或字段配置时先 query/field get;新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -24773,7 +24781,7 @@ "candidates": [ { "value": [ - "新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" + "未定位 recordId 或字段配置时先 query/field get;新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -24925,7 +24933,7 @@ }, "use_when": { "value": [ - "需要修改已有记录若干字段时" + "已查询得到真实 recordId 并核对字段类型,需要修改每条记录各自的 cells 时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -24934,7 +24942,7 @@ "candidates": [ { "value": [ - "需要修改已有记录若干字段时" + "已查询得到真实 recordId 并核对字段类型,需要修改每条记录各自的 cells 时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -24963,10 +24971,12 @@ "internal/cli/schema_mcp_metadata.json#tools.aitable.record_update", "skills/mono/references/products/aitable-record-ops.md", "skills/mono/references/products/aitable.md", - "skills/mono/references/products/aitable/aitable-attachment.md" + "skills/mono/references/products/aitable/aitable-attachment.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-record-update.md" ], "use_when": [ - "需要修改已有记录若干字段时" + "已查询得到真实 recordId 并核对字段类型,需要修改每条记录各自的 cells 时" ] }, "aitable record upsert": { @@ -27862,11 +27872,11 @@ ] }, "aitable table get": { - "agent_summary": "获取数据表结构(字段+视图目录)。", + "agent_summary": "底层获取数据表结构、精简字段目录与视图目录。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "只关心 Base 级 tables 列表可先 base get;字段完整配置也可用 field get" + "正常获取表、精简字段和视图目录优先用 +table-get;按表名解析 ID 用 +resolve-table;完整字段 config 用 +field-get" ], "confirmation": "not_required", "effect": "read", @@ -27876,14 +27886,14 @@ ], "field_provenance": { "agent_summary": { - "value": "获取数据表结构(字段+视图目录)。", + "value": "底层获取数据表结构、精简字段目录与视图目录。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "candidates": [ { - "value": "获取数据表结构(字段+视图目录)。", + "value": "底层获取数据表结构、精简字段目录与视图目录。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "selected": true, @@ -27915,7 +27925,7 @@ }, "avoid_when": { "value": [ - "只关心 Base 级 tables 列表可先 base get;字段完整配置也可用 field get" + "正常获取表、精简字段和视图目录优先用 +table-get;按表名解析 ID 用 +resolve-table;完整字段 config 用 +field-get" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -27924,7 +27934,7 @@ "candidates": [ { "value": [ - "只关心 Base 级 tables 列表可先 base get;字段完整配置也可用 field get" + "正常获取表、精简字段和视图目录优先用 +table-get;按表名解析 ID 用 +resolve-table;完整字段 config 用 +field-get" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -28076,7 +28086,7 @@ }, "use_when": { "value": [ - "需要字段 fieldId 或视图目录以继续 record/field 操作时优先 table get" + "需要 +table-get 未公开的底层参数、原始 get_tables 响应或不同执行语义时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -28085,7 +28095,7 @@ "candidates": [ { "value": [ - "需要字段 fieldId 或视图目录以继续 record/field 操作时优先 table get" + "需要 +table-get 未公开的底层参数、原始 get_tables 响应或不同执行语义时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -28115,10 +28125,12 @@ "skills/mono/references/products/aitable.md", "skills/mono/references/products/aitable/aitable-advperm.md", "skills/mono/references/products/aitable/aitable-primary-doc.md", - "skills/mono/references/products/aitable/aitable-record-create.md" + "skills/mono/references/products/aitable/aitable-record-create.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable.md" ], "use_when": [ - "需要字段 fieldId 或视图目录以继续 record/field 操作时优先 table get" + "需要 +table-get 未公开的底层参数、原始 get_tables 响应或不同执行语义时" ] }, "aitable table list": { diff --git a/internal/cli/schema_agent_metadata/index.json b/internal/cli/schema_agent_metadata/index.json index e5c898ce..9cc51b94 100644 --- a/internal/cli/schema_agent_metadata/index.json +++ b/internal/cli/schema_agent_metadata/index.json @@ -1,6 +1,6 @@ { "version": 1, - "source_hash": "sha256:709741e6cd06537bcf0c4bfb6a8930a14f9a43108128e1064b712bd9e2fbaa42", + "source_hash": "sha256:b3c33641f91b69b73f3e319e0927e8654b6ba1e24f99071e22ee813a4e9f861d", "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", "coverage": { "surface_products": 26, @@ -88,20 +88,20 @@ ] }, "aitable": { - "agent_summary": "管理 AI 表格 Base、数据表、字段、记录、视图、表单、仪表盘、权限、导入导出与自动化工作流。", + "agent_summary": "管理 AI 表格的 Base、Table、Field、Record、视图表单、仪表盘、权限、导入导出与自动化工作流。", "agent_summary_source": "dws-agent-selection/aitable", "avoid_when": [ - "目标是在线电子表格单元格读写时用 sheet;普通文档用 doc" + "在线电子表格工作表、单元格或公式用 sheet;普通文档用 doc;钉盘普通文件用 drive;类型不明的 alidocs URL 先做类型预检" ], "field_provenance": { "agent_summary": { - "value": "管理 AI 表格 Base、数据表、字段、记录、视图、表单、仪表盘、权限、导入导出与自动化工作流。", + "value": "管理 AI 表格的 Base、Table、Field、Record、视图表单、仪表盘、权限、导入导出与自动化工作流。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "resolution": "highest_precedence", "candidates": [ { - "value": "管理 AI 表格 Base、数据表、字段、记录、视图、表单、仪表盘、权限、导入导出与自动化工作流。", + "value": "管理 AI 表格的 Base、Table、Field、Record、视图表单、仪表盘、权限、导入导出与自动化工作流。", "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", "selected": true @@ -110,7 +110,7 @@ }, "avoid_when": { "value": [ - "目标是在线电子表格单元格读写时用 sheet;普通文档用 doc" + "在线电子表格工作表、单元格或公式用 sheet;普通文档用 doc;钉盘普通文件用 drive;类型不明的 alidocs URL 先做类型预检" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -118,7 +118,7 @@ "candidates": [ { "value": [ - "目标是在线电子表格单元格读写时用 sheet;普通文档用 doc" + "在线电子表格工作表、单元格或公式用 sheet;普通文档用 doc;钉盘普通文件用 drive;类型不明的 alidocs URL 先做类型预检" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -128,7 +128,7 @@ }, "use_when": { "value": [ - "需要读取或管理 AI 表格中的结构、数据、视图、权限、导入导出或工作流时" + "目标是 AI 表格/多维表中的结构化 Base、数据表、字段、记录、视图、权限、文件导入导出或自动化工作流时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -136,7 +136,7 @@ "candidates": [ { "value": [ - "需要读取或管理 AI 表格中的结构、数据、视图、权限、导入导出或工作流时" + "目标是 AI 表格/多维表中的结构化 Base、数据表、字段、记录、视图、权限、文件导入导出或自动化工作流时" ], "source": "internal/cli/schema_hints/selection/aitable.json", "precedence": "reviewed_explicit", @@ -153,10 +153,11 @@ "internal/cli/schema_hints/selection/aitable.json", "skills/mono/SKILL.md", "skills/mono/references/intent-guide.md", - "skills/mono/references/products/aitable.md" + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable.md" ], "use_when": [ - "需要读取或管理 AI 表格中的结构、数据、视图、权限、导入导出或工作流时" + "目标是 AI 表格/多维表中的结构化 Base、数据表、字段、记录、视图、权限、文件导入导出或自动化工作流时" ] }, "attendance": { diff --git a/internal/cli/schema_agent_metadata_audit.json b/internal/cli/schema_agent_metadata_audit.json index 8baac4bc..8526d83f 100644 --- a/internal/cli/schema_agent_metadata_audit.json +++ b/internal/cli/schema_agent_metadata_audit.json @@ -1,6 +1,6 @@ { "version": 1, - "source_hash": "sha256:709741e6cd06537bcf0c4bfb6a8930a14f9a43108128e1064b712bd9e2fbaa42", + "source_hash": "sha256:b3c33641f91b69b73f3e319e0927e8654b6ba1e24f99071e22ee813a4e9f861d", "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", "source_files": 160, "hint_files": 54, diff --git a/internal/cli/schema_catalog/catalog.json b/internal/cli/schema_catalog/catalog.json index 9a0d8aea..c4df502f 100644 --- a/internal/cli/schema_catalog/catalog.json +++ b/internal/cli/schema_catalog/catalog.json @@ -1,12 +1,12 @@ { "version": 1, "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", - "source_hash": "sha256:399dcd69d9f98e98ef9668edb6d965b59f5f61f9964f9546fb5796fee9b08865", + "source_hash": "sha256:3246b6b86cec02dd90b7cd093310667d926d62d3237d3408cfccc13ad3751b45", "catalog": { "agent_metadata": { "products_with_metadata": 26, "source": "embedded-skill-metadata", - "source_hash": "sha256:709741e6cd06537bcf0c4bfb6a8930a14f9a43108128e1064b712bd9e2fbaa42", + "source_hash": "sha256:b3c33641f91b69b73f3e319e0927e8654b6ba1e24f99071e22ee813a4e9f861d", "surface_hash": "sha256:4897d582a472d9d3596f88fb4546e7795d6b9bc334d020712f5d895ce894f7a7", "surface_products": 26, "surface_tools": 875, @@ -225,12 +225,13 @@ "internal/cli/schema_hints/selection/aitable.json", "skills/mono/SKILL.md", "skills/mono/references/intent-guide.md", - "skills/mono/references/products/aitable.md" + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable.md" ], - "agent_summary": "管理 AI 表格 Base、数据表、字段、记录、视图、表单、仪表盘、权限、导入导出与自动化工作流。", + "agent_summary": "管理 AI 表格的 Base、Table、Field、Record、视图表单、仪表盘、权限、导入导出与自动化工作流。", "agent_summary_source": "dws-agent-selection/aitable", "avoid_when": [ - "目标是在线电子表格单元格读写时用 sheet;普通文档用 doc" + "在线电子表格工作表、单元格或公式用 sheet;普通文档用 doc;钉盘普通文件用 drive;类型不明的 alidocs URL 先做类型预检" ], "description": "AI 表格操作", "field_provenance": { @@ -240,13 +241,13 @@ "precedence": "reviewed_explicit", "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "管理 AI 表格 Base、数据表、字段、记录、视图、表单、仪表盘、权限、导入导出与自动化工作流。" + "value": "管理 AI 表格的 Base、Table、Field、Record、视图表单、仪表盘、权限、导入导出与自动化工作流。" } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "管理 AI 表格 Base、数据表、字段、记录、视图、表单、仪表盘、权限、导入导出与自动化工作流。" + "value": "管理 AI 表格的 Base、Table、Field、Record、视图表单、仪表盘、权限、导入导出与自动化工作流。" }, "avoid_when": { "candidates": [ @@ -255,7 +256,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "目标是在线电子表格单元格读写时用 sheet;普通文档用 doc" + "在线电子表格工作表、单元格或公式用 sheet;普通文档用 doc;钉盘普通文件用 drive;类型不明的 alidocs URL 先做类型预检" ] } ], @@ -263,7 +264,7 @@ "resolution": "highest_precedence", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "目标是在线电子表格单元格读写时用 sheet;普通文档用 doc" + "在线电子表格工作表、单元格或公式用 sheet;普通文档用 doc;钉盘普通文件用 drive;类型不明的 alidocs URL 先做类型预检" ] }, "use_when": { @@ -273,7 +274,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要读取或管理 AI 表格中的结构、数据、视图、权限、导入导出或工作流时" + "目标是 AI 表格/多维表中的结构化 Base、数据表、字段、记录、视图、权限、文件导入导出或自动化工作流时" ] } ], @@ -281,7 +282,7 @@ "resolution": "highest_precedence", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要读取或管理 AI 表格中的结构、数据、视图、权限、导入导出或工作流时" + "目标是 AI 表格/多维表中的结构化 Base、数据表、字段、记录、视图、权限、文件导入导出或自动化工作流时" ] } }, @@ -726,11 +727,11 @@ }, { "agent_metadata_source": "embedded-skill-metadata", - "agent_summary": "按名称搜索 AI 表格 Base(优先于仅最近访问的 list)。", + "agent_summary": "底层按名称搜索 AI 表格 Base,返回原始候选列表。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "只要最近访问列表用 base list;已知 baseId 取详情用 base get;电子表格 axls 用 sheet" + "普通按名称解析唯一 baseId 优先用 +resolve-base;只要候选列表用 +base-search;最近访问用 +base-list;电子表格 axls 用 sheet" ], "canonical_path": "aitable.base_search", "cli_name": "search", @@ -752,7 +753,7 @@ "risk": "low", "title": "搜索 AI 表格", "use_when": [ - "用户要找某个 AI 表格/多维表,按名称检索时优先使用" + "需要 Shortcut 未公开的底层参数、原始 search_bases 响应或自定义候选处理时" ] }, { @@ -1375,11 +1376,11 @@ }, { "agent_metadata_source": "embedded-skill-metadata", - "agent_summary": "获取字段完整配置。", + "agent_summary": "底层获取字段完整类型与 config。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "表级字段目录也可用 table get;创建字段用 field create;不可用本命令改类型" + "正常按字段 ID 展开类型/config 优先用 +field-get;精简字段目录用 +table-get;创建字段用 field create" ], "canonical_path": "aitable.field_get", "cli_name": "get", @@ -1401,7 +1402,7 @@ "risk": "low", "title": "获取字段详情", "use_when": [ - "需要字段类型/config(选项、公式等)详情时" + "需要 +field-get 未公开的底层参数、原始响应或不同执行语义时" ] }, { @@ -1948,14 +1949,14 @@ }, { "agent_metadata_source": "embedded-skill-metadata", - "agent_summary": "查询/搜索记录(filters/sort/分页/--all;cells 键为 fieldId)。", + "agent_summary": "底层查询/搜索记录,额外支持原子命令的完整分页控制。", "agent_summary_source": "dws-agent-selection/aitable", "aliases": [ "aitable record list" ], "availability": "available", "avoid_when": [ - "已知 recordId 窄查可用 record get;空行用 query-empty;写入用 create/update;电子表格单元格用 sheet" + "普通按 ID、关键词、filters、sort 或 cursor 查询优先用 +record-query;空行用 +record-query-empty;写入用 create/update;电子表格单元格用 sheet" ], "canonical_path": "aitable.query_records", "cli_name": "query", @@ -1977,7 +1978,7 @@ "risk": "low", "title": "获取行记录", "use_when": [ - "查看、筛选、全文搜索或遍历记录时的主入口" + "需要 +record-query 未公开的 --all/--page-limit、底层原始响应或不同执行语义时" ] }, { @@ -2009,11 +2010,11 @@ }, { "agent_metadata_source": "embedded-skill-metadata", - "agent_summary": "新增记录(cells 的 key 必须是 fieldId)。", + "agent_summary": "新增记录;使用 fieldId 写入并从 newRecordIds 回读验证。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "更新已有行用 record update;有则更无则增用 upsert;批量同 patch 用 batch-update" + "未核对字段类型时先 field get;更新已有行用 record update;有则更无则增用 upsert;本地 CSV/JSON 批量追加可用已评审脚本" ], "canonical_path": "aitable.record_create", "cli_name": "create", @@ -2035,7 +2036,7 @@ "risk": "medium", "title": "新增记录", "use_when": [ - "需要插入新行数据时" + "已取得 baseId/tableId 与字段完整配置,需要插入一条或多条新记录并回读时" ] }, { @@ -2257,11 +2258,11 @@ }, { "agent_metadata_source": "embedded-skill-metadata", - "agent_summary": "更新已有记录字段(先 query 拿 recordId;只传需改字段)。", + "agent_summary": "更新已有记录字段;先 query 拿 recordId,使用 fieldId 写入并回读。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" + "未定位 recordId 或字段配置时先 query/field get;新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" ], "canonical_path": "aitable.record_update", "cli_name": "update", @@ -2283,7 +2284,7 @@ "risk": "medium", "title": "更新记录", "use_when": [ - "需要修改已有记录若干字段时" + "已查询得到真实 recordId 并核对字段类型,需要修改每条记录各自的 cells 时" ] }, { @@ -2596,7 +2597,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "知道名称并要解析唯一 baseId 用 +resolve-base;按关键词要完整候选用 +base-search;不要把最近访问列表描述成全部 Base" ], "canonical_path": "aitable.shortcut_base_list", "cli_name": "+base-list", @@ -2622,7 +2623,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需唯一 baseId 用 +resolve-base;浏览最近访问用 +base-list;需要未公开底层参数或原始响应才用 base search" ], "canonical_path": "aitable.shortcut_base_search", "cli_name": "+base-search", @@ -2752,7 +2753,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需精简 fieldId/type 目录用 +table-get;创建或修改字段用 field create/update;需要未公开底层语义才用 field get" ], "canonical_path": "aitable.shortcut_field_get", "cli_name": "+field-get", @@ -2934,7 +2935,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "完全空行扫描用 +record-query-empty;变更历史用 +record-history-list;需要 --all/--page-limit 或未公开底层语义才用 record query" ], "canonical_path": "aitable.shortcut_record_query", "cli_name": "+record-query", @@ -3038,7 +3039,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;只要完整候选列表用 +base-search;浏览最近访问用 +base-list;已知 baseId 不再重复搜索" ], "canonical_path": "aitable.shortcut_resolve_base", "cli_name": "+resolve-base", @@ -3055,7 +3056,7 @@ "risk": "low", "title": "按名称搜索多维表 Base 并解析出唯一 baseId(只读)", "use_when": [ - "当你只知道某个多维表 Base 的名称(或名称里的关键词)、想把它解析成可直接用于后续工具的 baseId 时使用;内部按 --name 关键词调用 search_bases 搜索 Base,再在本地投影出每个候选的 baseId 和 name。如果只命中一个 Base 就直接返回它的 baseId;如果命中多个则列出全部候选让你消歧,绝不替你瞎猜;如果一个都没命中则提示未找到。这是纯只读操作,只做搜索与本地投影,不会修改任何 Base。" + "只知道 Base 名称或关键词,需要解析成唯一 baseId 供后续 Table/Record 操作时" ] }, { @@ -3064,7 +3065,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;需要所有表及字段/视图目录用 +table-get;已知 tableId 不再重复解析" ], "canonical_path": "aitable.shortcut_resolve_table", "cli_name": "+resolve-table", @@ -3081,7 +3082,7 @@ "risk": "low", "title": "在某个多维表 Base 内按名称解析出唯一的数据表 tableId(只读)", "use_when": [ - "当你已经知道某个多维表 Base 的 baseId、又只记得里面某张数据表(table)的名称或名称关键词、想把它解析成可直接用于后续工具的 tableId 时使用;内部先用 get_tables(只传 baseId)列出该 Base 下的全部数据表,再在本地把每张表投影成 tableId、name,并按 --name 关键词做大小写不敏感的包含匹配来筛选候选。如果只命中一张表就直接返回它的 tableId;如果命中多张则列出全部候选让你消歧,绝不替你瞎猜;如果一张都没命中则提示未找到。这是纯只读操作,只做列举、本地匹配与投影,不会创建、修改或删除任何数据表。" + "已有真实 baseId、只知道数据表名称或关键词,需要解析成唯一 tableId 时" ] }, { @@ -3168,7 +3169,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只知道表名并要解析唯一 tableId 用 +resolve-table;需要字段完整 config 用 +field-get;需要未公开底层语义才用 table get" ], "canonical_path": "aitable.shortcut_table_get", "cli_name": "+table-get", @@ -3382,11 +3383,11 @@ }, { "agent_metadata_source": "embedded-skill-metadata", - "agent_summary": "获取数据表结构(字段+视图目录)。", + "agent_summary": "底层获取数据表结构、精简字段目录与视图目录。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "只关心 Base 级 tables 列表可先 base get;字段完整配置也可用 field get" + "正常获取表、精简字段和视图目录优先用 +table-get;按表名解析 ID 用 +resolve-table;完整字段 config 用 +field-get" ], "canonical_path": "aitable.table_get", "cli_name": "get", @@ -3408,7 +3409,7 @@ "risk": "low", "title": "获取数据表", "use_when": [ - "需要字段 fieldId 或视图目录以继续 record/field 操作时优先 table get" + "需要 +table-get 未公开的底层参数、原始 get_tables 响应或不同执行语义时" ] }, { @@ -4571,7 +4572,7 @@ } ], "use_when": [ - "需要读取或管理 AI 表格中的结构、数据、视图、权限、导入导出或工作流时" + "目标是 AI 表格/多维表中的结构化 Base、数据表、字段、记录、视图、权限、文件导入导出或自动化工作流时" ] }, { diff --git a/internal/cli/schema_catalog/tools/aitable.json b/internal/cli/schema_catalog/tools/aitable.json index 3f8cf870..69b8bd45 100644 --- a/internal/cli/schema_catalog/tools/aitable.json +++ b/internal/cli/schema_catalog/tools/aitable.json @@ -8704,13 +8704,15 @@ "internal/cli/schema_hints/metadata/aitable.json", "internal/cli/schema_hints/selection/aitable.json", "internal/cli/schema_mcp_metadata.json#tools.aitable.base_search", - "skills/mono/references/products/aitable.md" + "skills/mono/references/products/aitable.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable.md" ], - "agent_summary": "按名称搜索 AI 表格 Base(优先于仅最近访问的 list)。", + "agent_summary": "底层按名称搜索 AI 表格 Base,返回原始候选列表。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "只要最近访问列表用 base list;已知 baseId 取详情用 base get;电子表格 axls 用 sheet" + "普通按名称解析唯一 baseId 优先用 +resolve-base;只要候选列表用 +base-search;最近访问用 +base-list;电子表格 axls 用 sheet" ], "canonical_path": "aitable.base_search", "cli_name": "search", @@ -8731,14 +8733,14 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "按名称搜索 AI 表格 Base(优先于仅最近访问的 list)。" + "value": "底层按名称搜索 AI 表格 Base,返回原始候选列表。" } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "按名称搜索 AI 表格 Base(优先于仅最近访问的 list)。" + "value": "底层按名称搜索 AI 表格 Base,返回原始候选列表。" }, "availability": { "candidates": [ @@ -8770,7 +8772,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "只要最近访问列表用 base list;已知 baseId 取详情用 base get;电子表格 axls 用 sheet" + "普通按名称解析唯一 baseId 优先用 +resolve-base;只要候选列表用 +base-search;最近访问用 +base-list;电子表格 axls 用 sheet" ] } ], @@ -8779,7 +8781,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "只要最近访问列表用 base list;已知 baseId 取详情用 base get;电子表格 axls 用 sheet" + "普通按名称解析唯一 baseId 优先用 +resolve-base;只要候选列表用 +base-search;最近访问用 +base-list;电子表格 axls 用 sheet" ] }, "canonical_path": { @@ -9009,7 +9011,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "用户要找某个 AI 表格/多维表,按名称检索时优先使用" + "需要 Shortcut 未公开的底层参数、原始 search_bases 响应或自定义候选处理时" ] } ], @@ -9018,7 +9020,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "用户要找某个 AI 表格/多维表,按名称检索时优先使用" + "需要 Shortcut 未公开的底层参数、原始 search_bases 响应或自定义候选处理时" ] } }, @@ -9237,7 +9239,7 @@ "source": "reviewed_command_registry", "title": "搜索 AI 表格", "use_when": [ - "用户要找某个 AI 表格/多维表,按名称检索时优先使用" + "需要 Shortcut 未公开的底层参数、原始 search_bases 响应或自定义候选处理时" ] }, "aitable.base_update": { @@ -23545,13 +23547,15 @@ "internal/cli/schema_hints/selection/aitable.json", "internal/cli/schema_mcp_metadata.json#tools.aitable.field_get", "skills/mono/references/products/aitable.md", - "skills/mono/references/products/aitable/aitable-field.md" + "skills/mono/references/products/aitable/aitable-field.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-field.md" ], - "agent_summary": "获取字段完整配置。", + "agent_summary": "底层获取字段完整类型与 config。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "表级字段目录也可用 table get;创建字段用 field create;不可用本命令改类型" + "正常按字段 ID 展开类型/config 优先用 +field-get;精简字段目录用 +table-get;创建字段用 field create" ], "canonical_path": "aitable.field_get", "cli_name": "get", @@ -23572,14 +23576,14 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "获取字段完整配置。" + "value": "底层获取字段完整类型与 config。" } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "获取字段完整配置。" + "value": "底层获取字段完整类型与 config。" }, "availability": { "candidates": [ @@ -23611,7 +23615,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "表级字段目录也可用 table get;创建字段用 field create;不可用本命令改类型" + "正常按字段 ID 展开类型/config 优先用 +field-get;精简字段目录用 +table-get;创建字段用 field create" ] } ], @@ -23620,7 +23624,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "表级字段目录也可用 table get;创建字段用 field create;不可用本命令改类型" + "正常按字段 ID 展开类型/config 优先用 +field-get;精简字段目录用 +table-get;创建字段用 field create" ] }, "canonical_path": { @@ -23848,7 +23852,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要字段类型/config(选项、公式等)详情时" + "需要 +field-get 未公开的底层参数、原始响应或不同执行语义时" ] } ], @@ -23857,7 +23861,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要字段类型/config(选项、公式等)详情时" + "需要 +field-get 未公开的底层参数、原始响应或不同执行语义时" ] } }, @@ -24201,7 +24205,7 @@ "source": "reviewed_command_registry", "title": "获取字段详情", "use_when": [ - "需要字段类型/config(选项、公式等)详情时" + "需要 +field-get 未公开的底层参数、原始响应或不同执行语义时" ] }, "aitable.field_list": { @@ -38119,16 +38123,18 @@ "internal/cli/schema_mcp_metadata.json#tools.aitable.query_records", "skills/mono/references/products/aitable-record-ops.md", "skills/mono/references/products/aitable.md", - "skills/mono/references/products/aitable/aitable-record-query.md" + "skills/mono/references/products/aitable/aitable-record-query.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-record-query.md" ], - "agent_summary": "查询/搜索记录(filters/sort/分页/--all;cells 键为 fieldId)。", + "agent_summary": "底层查询/搜索记录,额外支持原子命令的完整分页控制。", "agent_summary_source": "dws-agent-selection/aitable", "aliases": [ "aitable record list" ], "availability": "available", "avoid_when": [ - "已知 recordId 窄查可用 record get;空行用 query-empty;写入用 create/update;电子表格单元格用 sheet" + "普通按 ID、关键词、filters、sort 或 cursor 查询优先用 +record-query;空行用 +record-query-empty;写入用 create/update;电子表格单元格用 sheet" ], "canonical_path": "aitable.query_records", "cli_name": "query", @@ -38149,14 +38155,14 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "查询/搜索记录(filters/sort/分页/--all;cells 键为 fieldId)。" + "value": "底层查询/搜索记录,额外支持原子命令的完整分页控制。" } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "查询/搜索记录(filters/sort/分页/--all;cells 键为 fieldId)。" + "value": "底层查询/搜索记录,额外支持原子命令的完整分页控制。" }, "availability": { "candidates": [ @@ -38188,7 +38194,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "已知 recordId 窄查可用 record get;空行用 query-empty;写入用 create/update;电子表格单元格用 sheet" + "普通按 ID、关键词、filters、sort 或 cursor 查询优先用 +record-query;空行用 +record-query-empty;写入用 create/update;电子表格单元格用 sheet" ] } ], @@ -38197,7 +38203,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "已知 recordId 窄查可用 record get;空行用 query-empty;写入用 create/update;电子表格单元格用 sheet" + "普通按 ID、关键词、filters、sort 或 cursor 查询优先用 +record-query;空行用 +record-query-empty;写入用 create/update;电子表格单元格用 sheet" ] }, "canonical_path": { @@ -38447,7 +38453,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "查看、筛选、全文搜索或遍历记录时的主入口" + "需要 +record-query 未公开的 --all/--page-limit、底层原始响应或不同执行语义时" ] } ], @@ -38456,7 +38462,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "查看、筛选、全文搜索或遍历记录时的主入口" + "需要 +record-query 未公开的 --all/--page-limit、底层原始响应或不同执行语义时" ] } }, @@ -39699,7 +39705,7 @@ "source": "reviewed_command_registry", "title": "获取行记录", "use_when": [ - "查看、筛选、全文搜索或遍历记录时的主入口" + "需要 +record-query 未公开的 --all/--page-limit、底层原始响应或不同执行语义时" ] }, "aitable.record_batch_update": { @@ -40397,13 +40403,15 @@ "skills/mono/references/products/aitable-record-ops.md", "skills/mono/references/products/aitable.md", "skills/mono/references/products/aitable/aitable-attachment.md", - "skills/mono/references/products/aitable/aitable-record-create.md" + "skills/mono/references/products/aitable/aitable-record-create.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-record-create.md" ], - "agent_summary": "新增记录(cells 的 key 必须是 fieldId)。", + "agent_summary": "新增记录;使用 fieldId 写入并从 newRecordIds 回读验证。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "更新已有行用 record update;有则更无则增用 upsert;批量同 patch 用 batch-update" + "未核对字段类型时先 field get;更新已有行用 record update;有则更无则增用 upsert;本地 CSV/JSON 批量追加可用已评审脚本" ], "canonical_path": "aitable.record_create", "cli_name": "create", @@ -40424,14 +40432,14 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "新增记录(cells 的 key 必须是 fieldId)。" + "value": "新增记录;使用 fieldId 写入并从 newRecordIds 回读验证。" } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "新增记录(cells 的 key 必须是 fieldId)。" + "value": "新增记录;使用 fieldId 写入并从 newRecordIds 回读验证。" }, "availability": { "candidates": [ @@ -40463,7 +40471,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "更新已有行用 record update;有则更无则增用 upsert;批量同 patch 用 batch-update" + "未核对字段类型时先 field get;更新已有行用 record update;有则更无则增用 upsert;本地 CSV/JSON 批量追加可用已评审脚本" ] } ], @@ -40472,7 +40480,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "更新已有行用 record update;有则更无则增用 upsert;批量同 patch 用 batch-update" + "未核对字段类型时先 field get;更新已有行用 record update;有则更无则增用 upsert;本地 CSV/JSON 批量追加可用已评审脚本" ] }, "canonical_path": { @@ -40700,7 +40708,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要插入新行数据时" + "已取得 baseId/tableId 与字段完整配置,需要插入一条或多条新记录并回读时" ] } ], @@ -40709,7 +40717,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要插入新行数据时" + "已取得 baseId/tableId 与字段完整配置,需要插入一条或多条新记录并回读时" ] } }, @@ -41156,7 +41164,7 @@ "source": "reviewed_command_registry", "title": "新增记录", "use_when": [ - "需要插入新行数据时" + "已取得 baseId/tableId 与字段完整配置,需要插入一条或多条新记录并回读时" ] }, "aitable.record_delete": { @@ -46549,13 +46557,15 @@ "internal/cli/schema_mcp_metadata.json#tools.aitable.record_update", "skills/mono/references/products/aitable-record-ops.md", "skills/mono/references/products/aitable.md", - "skills/mono/references/products/aitable/aitable-attachment.md" + "skills/mono/references/products/aitable/aitable-attachment.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-record-update.md" ], - "agent_summary": "更新已有记录字段(先 query 拿 recordId;只传需改字段)。", + "agent_summary": "更新已有记录字段;先 query 拿 recordId,使用 fieldId 写入并回读。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" + "未定位 recordId 或字段配置时先 query/field get;新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" ], "canonical_path": "aitable.record_update", "cli_name": "update", @@ -46576,14 +46586,14 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "更新已有记录字段(先 query 拿 recordId;只传需改字段)。" + "value": "更新已有记录字段;先 query 拿 recordId,使用 fieldId 写入并回读。" } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "更新已有记录字段(先 query 拿 recordId;只传需改字段)。" + "value": "更新已有记录字段;先 query 拿 recordId,使用 fieldId 写入并回读。" }, "availability": { "candidates": [ @@ -46615,7 +46625,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" + "未定位 recordId 或字段配置时先 query/field get;新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" ] } ], @@ -46624,7 +46634,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" + "未定位 recordId 或字段配置时先 query/field get;新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" ] }, "canonical_path": { @@ -46852,7 +46862,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要修改已有记录若干字段时" + "已查询得到真实 recordId 并核对字段类型,需要修改每条记录各自的 cells 时" ] } ], @@ -46861,7 +46871,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要修改已有记录若干字段时" + "已查询得到真实 recordId 并核对字段类型,需要修改每条记录各自的 cells 时" ] } }, @@ -47308,7 +47318,7 @@ "source": "reviewed_command_registry", "title": "更新记录", "use_when": [ - "需要修改已有记录若干字段时" + "已查询得到真实 recordId 并核对字段类型,需要修改每条记录各自的 cells 时" ] }, "aitable.record_upsert": { @@ -53447,7 +53457,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "知道名称并要解析唯一 baseId 用 +resolve-base;按关键词要完整候选用 +base-search;不要把最近访问列表描述成全部 Base" ], "canonical_path": "aitable.shortcut_base_list", "cli_name": "+base-list", @@ -53502,7 +53512,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "知道名称并要解析唯一 baseId 用 +resolve-base;按关键词要完整候选用 +base-search;不要把最近访问列表描述成全部 Base" ] } ], @@ -53511,7 +53521,7 @@ "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "知道名称并要解析唯一 baseId 用 +resolve-base;按关键词要完整候选用 +base-search;不要把最近访问列表描述成全部 Base" ] }, "canonical_path": { @@ -53943,7 +53953,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需唯一 baseId 用 +resolve-base;浏览最近访问用 +base-list;需要未公开底层参数或原始响应才用 base search" ], "canonical_path": "aitable.shortcut_base_search", "cli_name": "+base-search", @@ -53997,7 +54007,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需唯一 baseId 用 +resolve-base;浏览最近访问用 +base-list;需要未公开底层参数或原始响应才用 base search" ] } ], @@ -54006,7 +54016,7 @@ "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需唯一 baseId 用 +resolve-base;浏览最近访问用 +base-list;需要未公开底层参数或原始响应才用 base search" ] }, "canonical_path": { @@ -56196,7 +56206,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需精简 fieldId/type 目录用 +table-get;创建或修改字段用 field create/update;需要未公开底层语义才用 field get" ], "canonical_path": "aitable.shortcut_field_get", "cli_name": "+field-get", @@ -56250,7 +56260,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需精简 fieldId/type 目录用 +table-get;创建或修改字段用 field create/update;需要未公开底层语义才用 field get" ] } ], @@ -56259,7 +56269,7 @@ "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需精简 fieldId/type 目录用 +table-get;创建或修改字段用 field create/update;需要未公开底层语义才用 field get" ] }, "canonical_path": { @@ -60316,7 +60326,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "完全空行扫描用 +record-query-empty;变更历史用 +record-history-list;需要 --all/--page-limit 或未公开底层语义才用 record query" ], "canonical_path": "aitable.shortcut_record_query", "cli_name": "+record-query", @@ -60370,7 +60380,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "完全空行扫描用 +record-query-empty;变更历史用 +record-history-list;需要 --all/--page-limit 或未公开底层语义才用 record query" ] } ], @@ -60379,7 +60389,7 @@ "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "完全空行扫描用 +record-query-empty;变更历史用 +record-history-list;需要 --all/--page-limit 或未公开底层语义才用 record query" ] }, "canonical_path": { @@ -63485,7 +63495,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;只要完整候选列表用 +base-search;浏览最近访问用 +base-list;已知 baseId 不再重复搜索" ], "canonical_path": "aitable.shortcut_resolve_base", "cli_name": "+resolve-base", @@ -63539,7 +63549,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;只要完整候选列表用 +base-search;浏览最近访问用 +base-list;已知 baseId 不再重复搜索" ] } ], @@ -63548,7 +63558,7 @@ "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;只要完整候选列表用 +base-search;浏览最近访问用 +base-list;已知 baseId 不再重复搜索" ] }, "canonical_path": { @@ -63758,7 +63768,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "当你只知道某个多维表 Base 的名称(或名称里的关键词)、想把它解析成可直接用于后续工具的 baseId 时使用;内部按 --name 关键词调用 search_bases 搜索 Base,再在本地投影出每个候选的 baseId 和 name。如果只命中一个 Base 就直接返回它的 baseId;如果命中多个则列出全部候选让你消歧,绝不替你瞎猜;如果一个都没命中则提示未找到。这是纯只读操作,只做搜索与本地投影,不会修改任何 Base。" + "只知道 Base 名称或关键词,需要解析成唯一 baseId 供后续 Table/Record 操作时" ] } ], @@ -63767,7 +63777,7 @@ "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "当你只知道某个多维表 Base 的名称(或名称里的关键词)、想把它解析成可直接用于后续工具的 baseId 时使用;内部按 --name 关键词调用 search_bases 搜索 Base,再在本地投影出每个候选的 baseId 和 name。如果只命中一个 Base 就直接返回它的 baseId;如果命中多个则列出全部候选让你消歧,绝不替你瞎猜;如果一个都没命中则提示未找到。这是纯只读操作,只做搜索与本地投影,不会修改任何 Base。" + "只知道 Base 名称或关键词,需要解析成唯一 baseId 供后续 Table/Record 操作时" ] } }, @@ -63884,7 +63894,7 @@ "source": "reviewed_command_registry", "title": "按名称搜索多维表 Base 并解析出唯一 baseId(只读)", "use_when": [ - "当你只知道某个多维表 Base 的名称(或名称里的关键词)、想把它解析成可直接用于后续工具的 baseId 时使用;内部按 --name 关键词调用 search_bases 搜索 Base,再在本地投影出每个候选的 baseId 和 name。如果只命中一个 Base 就直接返回它的 baseId;如果命中多个则列出全部候选让你消歧,绝不替你瞎猜;如果一个都没命中则提示未找到。这是纯只读操作,只做搜索与本地投影,不会修改任何 Base。" + "只知道 Base 名称或关键词,需要解析成唯一 baseId 供后续 Table/Record 操作时" ] }, "aitable.shortcut_resolve_table": { @@ -63900,7 +63910,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;需要所有表及字段/视图目录用 +table-get;已知 tableId 不再重复解析" ], "canonical_path": "aitable.shortcut_resolve_table", "cli_name": "+resolve-table", @@ -63954,7 +63964,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;需要所有表及字段/视图目录用 +table-get;已知 tableId 不再重复解析" ] } ], @@ -63963,7 +63973,7 @@ "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;需要所有表及字段/视图目录用 +table-get;已知 tableId 不再重复解析" ] }, "canonical_path": { @@ -64173,7 +64183,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "当你已经知道某个多维表 Base 的 baseId、又只记得里面某张数据表(table)的名称或名称关键词、想把它解析成可直接用于后续工具的 tableId 时使用;内部先用 get_tables(只传 baseId)列出该 Base 下的全部数据表,再在本地把每张表投影成 tableId、name,并按 --name 关键词做大小写不敏感的包含匹配来筛选候选。如果只命中一张表就直接返回它的 tableId;如果命中多张则列出全部候选让你消歧,绝不替你瞎猜;如果一张都没命中则提示未找到。这是纯只读操作,只做列举、本地匹配与投影,不会创建、修改或删除任何数据表。" + "已有真实 baseId、只知道数据表名称或关键词,需要解析成唯一 tableId 时" ] } ], @@ -64182,7 +64192,7 @@ "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "当你已经知道某个多维表 Base 的 baseId、又只记得里面某张数据表(table)的名称或名称关键词、想把它解析成可直接用于后续工具的 tableId 时使用;内部先用 get_tables(只传 baseId)列出该 Base 下的全部数据表,再在本地把每张表投影成 tableId、name,并按 --name 关键词做大小写不敏感的包含匹配来筛选候选。如果只命中一张表就直接返回它的 tableId;如果命中多张则列出全部候选让你消歧,绝不替你瞎猜;如果一张都没命中则提示未找到。这是纯只读操作,只做列举、本地匹配与投影,不会创建、修改或删除任何数据表。" + "已有真实 baseId、只知道数据表名称或关键词,需要解析成唯一 tableId 时" ] } }, @@ -64395,7 +64405,7 @@ "source": "reviewed_command_registry", "title": "在某个多维表 Base 内按名称解析出唯一的数据表 tableId(只读)", "use_when": [ - "当你已经知道某个多维表 Base 的 baseId、又只记得里面某张数据表(table)的名称或名称关键词、想把它解析成可直接用于后续工具的 tableId 时使用;内部先用 get_tables(只传 baseId)列出该 Base 下的全部数据表,再在本地把每张表投影成 tableId、name,并按 --name 关键词做大小写不敏感的包含匹配来筛选候选。如果只命中一张表就直接返回它的 tableId;如果命中多张则列出全部候选让你消歧,绝不替你瞎猜;如果一张都没命中则提示未找到。这是纯只读操作,只做列举、本地匹配与投影,不会创建、修改或删除任何数据表。" + "已有真实 baseId、只知道数据表名称或关键词,需要解析成唯一 tableId 时" ] }, "aitable.shortcut_role_list": { @@ -65656,7 +65666,7 @@ "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只知道表名并要解析唯一 tableId 用 +resolve-table;需要字段完整 config 用 +field-get;需要未公开底层语义才用 table get" ], "canonical_path": "aitable.shortcut_table_get", "cli_name": "+table-get", @@ -65711,7 +65721,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只知道表名并要解析唯一 tableId 用 +resolve-table;需要字段完整 config 用 +field-get;需要未公开底层语义才用 table get" ] } ], @@ -65720,7 +65730,7 @@ "review_reason": "Agent-authored and reviewed from the built-in Shortcut intent, executable Cobra path, and declared outcome; it affects selection only and does not alter execution or safety facts.", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只知道表名并要解析唯一 tableId 用 +resolve-table;需要字段完整 config 用 +field-get;需要未公开底层语义才用 table get" ] }, "canonical_path": { @@ -70522,13 +70532,15 @@ "skills/mono/references/products/aitable.md", "skills/mono/references/products/aitable/aitable-advperm.md", "skills/mono/references/products/aitable/aitable-primary-doc.md", - "skills/mono/references/products/aitable/aitable-record-create.md" + "skills/mono/references/products/aitable/aitable-record-create.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable.md" ], - "agent_summary": "获取数据表结构(字段+视图目录)。", + "agent_summary": "底层获取数据表结构、精简字段目录与视图目录。", "agent_summary_source": "dws-agent-selection/aitable", "availability": "available", "avoid_when": [ - "只关心 Base 级 tables 列表可先 base get;字段完整配置也可用 field get" + "正常获取表、精简字段和视图目录优先用 +table-get;按表名解析 ID 用 +resolve-table;完整字段 config 用 +field-get" ], "canonical_path": "aitable.table_get", "cli_name": "get", @@ -70549,14 +70561,14 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "获取数据表结构(字段+视图目录)。" + "value": "底层获取数据表结构、精简字段目录与视图目录。" } ], "precedence": "reviewed_explicit", "resolution": "highest_precedence", "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", - "value": "获取数据表结构(字段+视图目录)。" + "value": "底层获取数据表结构、精简字段目录与视图目录。" }, "availability": { "candidates": [ @@ -70588,7 +70600,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "只关心 Base 级 tables 列表可先 base get;字段完整配置也可用 field get" + "正常获取表、精简字段和视图目录优先用 +table-get;按表名解析 ID 用 +resolve-table;完整字段 config 用 +field-get" ] } ], @@ -70597,7 +70609,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "只关心 Base 级 tables 列表可先 base get;字段完整配置也可用 field get" + "正常获取表、精简字段和视图目录优先用 +table-get;按表名解析 ID 用 +resolve-table;完整字段 config 用 +field-get" ] }, "canonical_path": { @@ -70825,7 +70837,7 @@ "selected": true, "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要字段 fieldId 或视图目录以继续 record/field 操作时优先 table get" + "需要 +table-get 未公开的底层参数、原始 get_tables 响应或不同执行语义时" ] } ], @@ -70834,7 +70846,7 @@ "review_reason": "人工结合实时 dws schema MCP 描述(或 helper 无 live 时用 Skill/Cobra)、兄弟命令分流与 Runtime 确认门禁审阅选型语义。", "source": "internal/cli/schema_hints/selection/aitable.json", "value": [ - "需要字段 fieldId 或视图目录以继续 record/field 操作时优先 table get" + "需要 +table-get 未公开的底层参数、原始 get_tables 响应或不同执行语义时" ] } }, @@ -71081,7 +71093,7 @@ "source": "reviewed_command_registry", "title": "获取数据表", "use_when": [ - "需要字段 fieldId 或视图目录以继续 record/field 操作时优先 table get" + "需要 +table-get 未公开的底层参数、原始 get_tables 响应或不同执行语义时" ] }, "aitable.table_list": { diff --git a/internal/cli/schema_hints/selection/aitable.json b/internal/cli/schema_hints/selection/aitable.json index ef1f0ae8..b1b8a177 100644 --- a/internal/cli/schema_hints/selection/aitable.json +++ b/internal/cli/schema_hints/selection/aitable.json @@ -289,12 +289,12 @@ ] }, "aitable.base_search": { - "agent_summary": "按名称搜索 AI 表格 Base(优先于仅最近访问的 list)。", + "agent_summary": "底层按名称搜索 AI 表格 Base,返回原始候选列表。", "use_when": [ - "用户要找某个 AI 表格/多维表,按名称检索时优先使用" + "需要 Shortcut 未公开的底层参数、原始 search_bases 响应或自定义候选处理时" ], "avoid_when": [ - "只要最近访问列表用 base list;已知 baseId 取详情用 base get;电子表格 axls 用 sheet" + "普通按名称解析唯一 baseId 优先用 +resolve-base;只要候选列表用 +base-search;最近访问用 +base-list;电子表格 axls 用 sheet" ], "examples": [ "dws aitable base search --query \"项目\"" @@ -304,7 +304,8 @@ "source_refs": [ "internal/cli/schema_command_registry.json", "cobra-help:dws aitable base search --help", - "skills/mono/references/products/aitable.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable.md", "dws-schema-live:aitable.search_bases" ] }, @@ -710,12 +711,12 @@ ] }, "aitable.field_get": { - "agent_summary": "获取字段完整配置。", + "agent_summary": "底层获取字段完整类型与 config。", "use_when": [ - "需要字段类型/config(选项、公式等)详情时" + "需要 +field-get 未公开的底层参数、原始响应或不同执行语义时" ], "avoid_when": [ - "表级字段目录也可用 table get;创建字段用 field create;不可用本命令改类型" + "正常按字段 ID 展开类型/config 优先用 +field-get;精简字段目录用 +table-get;创建字段用 field create" ], "examples": [ "dws aitable field get --base-id --table-id " @@ -725,7 +726,8 @@ "source_refs": [ "internal/cli/schema_command_registry.json", "cobra-help:dws aitable field get --help", - "skills/mono/references/products/aitable.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-field.md", "dws-schema-live:aitable.get_fields" ] }, @@ -1110,12 +1112,12 @@ ] }, "aitable.query_records": { - "agent_summary": "查询/搜索记录(filters/sort/分页/--all;cells 键为 fieldId)。", + "agent_summary": "底层查询/搜索记录,额外支持原子命令的完整分页控制。", "use_when": [ - "查看、筛选、全文搜索或遍历记录时的主入口" + "需要 +record-query 未公开的 --all/--page-limit、底层原始响应或不同执行语义时" ], "avoid_when": [ - "已知 recordId 窄查可用 record get;空行用 query-empty;写入用 create/update;电子表格单元格用 sheet" + "普通按 ID、关键词、filters、sort 或 cursor 查询优先用 +record-query;空行用 +record-query-empty;写入用 create/update;电子表格单元格用 sheet" ], "examples": [ "dws aitable record query --base-id --table-id " @@ -1125,7 +1127,8 @@ "source_refs": [ "internal/cli/schema_command_registry.json", "cobra-help:dws aitable record query --help", - "skills/mono/references/products/aitable.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-record-query.md", "dws-schema-live:aitable.query_records" ] }, @@ -1150,12 +1153,12 @@ ] }, "aitable.record_create": { - "agent_summary": "新增记录(cells 的 key 必须是 fieldId)。", + "agent_summary": "新增记录;使用 fieldId 写入并从 newRecordIds 回读验证。", "use_when": [ - "需要插入新行数据时" + "已取得 baseId/tableId 与字段完整配置,需要插入一条或多条新记录并回读时" ], "avoid_when": [ - "更新已有行用 record update;有则更无则增用 upsert;批量同 patch 用 batch-update" + "未核对字段类型时先 field get;更新已有行用 record update;有则更无则增用 upsert;本地 CSV/JSON 批量追加可用已评审脚本" ], "examples": [ "dws aitable record create --base-id --table-id --records '[{\"cells\":{\"fldXXX\":\"值\"}}]'" @@ -1165,7 +1168,8 @@ "source_refs": [ "internal/cli/schema_command_registry.json", "cobra-help:dws aitable record create --help", - "skills/mono/references/products/aitable.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-record-create.md", "dws-schema-live:aitable.create_records" ] }, @@ -1310,12 +1314,12 @@ ] }, "aitable.record_update": { - "agent_summary": "更新已有记录字段(先 query 拿 recordId;只传需改字段)。", + "agent_summary": "更新已有记录字段;先 query 拿 recordId,使用 fieldId 写入并回读。", "use_when": [ - "需要修改已有记录若干字段时" + "已查询得到真实 recordId 并核对字段类型,需要修改每条记录各自的 cells 时" ], "avoid_when": [ - "新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" + "未定位 recordId 或字段配置时先 query/field get;新建用 create;多条共用同一 cells patch 用 batch-update;混合创建/更新用 upsert" ], "examples": [ "dws aitable record update --base-id --table-id --records '[{\"recordId\":\"recXXX\",\"cells\":{\"fldYYY\":\"新值\"}}]'" @@ -1325,7 +1329,8 @@ "source_refs": [ "internal/cli/schema_command_registry.json", "cobra-help:dws aitable record update --help", - "skills/mono/references/products/aitable.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable/aitable-record-update.md", "dws-schema-live:aitable.update_records" ] }, @@ -1550,12 +1555,12 @@ ] }, "aitable.table_get": { - "agent_summary": "获取数据表结构(字段+视图目录)。", + "agent_summary": "底层获取数据表结构、精简字段目录与视图目录。", "use_when": [ - "需要字段 fieldId 或视图目录以继续 record/field 操作时优先 table get" + "需要 +table-get 未公开的底层参数、原始 get_tables 响应或不同执行语义时" ], "avoid_when": [ - "只关心 Base 级 tables 列表可先 base get;字段完整配置也可用 field get" + "正常获取表、精简字段和视图目录优先用 +table-get;按表名解析 ID 用 +resolve-table;完整字段 config 用 +field-get" ], "examples": [ "dws aitable table get --base-id BASE_ID" @@ -1565,7 +1570,8 @@ "source_refs": [ "internal/cli/schema_command_registry.json", "cobra-help:dws aitable table get --help", - "skills/mono/references/products/aitable.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable.md", "dws-schema-live:aitable.get_tables" ] }, @@ -2335,7 +2341,7 @@ "当你不知道具体 baseId、想先浏览自己最近用过或可访问的 AI 表格清单以便定位目标时使用;支持游标分页,返回 Base 列表及其 baseId。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "知道名称并要解析唯一 baseId 用 +resolve-base;按关键词要完整候选用 +base-search;不要把最近访问列表描述成全部 Base" ], "examples": [ "dws aitable +base-list", @@ -2355,7 +2361,7 @@ "当你知道某个 AI 表格的名字或部分关键词、想直接定位到它并拿到 baseId 时使用;输入名称关键词,返回匹配的 Base 列表。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需唯一 baseId 用 +resolve-base;浏览最近访问用 +base-list;需要未公开底层参数或原始响应才用 base search" ], "examples": [ "dws aitable +base-search --query \"项目管理\"" @@ -2393,7 +2399,7 @@ "当你已进入某个 Base、需要了解其中某些数据表有哪些字段(拿 fieldId)、有哪些视图(拿 viewId)以便读写数据时使用;批量返回表信息、字段目录和视图目录。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只知道表名并要解析唯一 tableId 用 +resolve-table;需要字段完整 config 用 +field-get;需要未公开底层语义才用 table get" ], "examples": [ "dws aitable +table-get --base-id BASE_ID", @@ -2413,7 +2419,7 @@ "当你需要查看字段的完整类型配置(如单选选项、关联表设置、AI 配置)以便正确写入数据或改配置时使用;批量返回字段详情。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "只需精简 fieldId/type 目录用 +table-get;创建或修改字段用 field create/update;需要未公开底层语义才用 field get" ], "examples": [ "dws aitable +field-get --base-id B --table-id T" @@ -2432,7 +2438,7 @@ "当你要读取表格里的行数据——按 recordId 精确取、按结构化条件筛选、按关键词全文搜索或分页遍历时使用;返回匹配记录及其单元格值。" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "完全空行扫描用 +record-query-empty;变更历史用 +record-history-list;需要 --all/--page-limit 或未公开底层语义才用 record query" ], "examples": [ "dws aitable +record-query --base-id B --table-id T --query \"关键词\" --limit 50" @@ -2849,10 +2855,10 @@ "aitable.shortcut_resolve_base": { "agent_summary": "按名称搜索多维表 Base 并解析出唯一 baseId(只读)", "use_when": [ - "当你只知道某个多维表 Base 的名称(或名称里的关键词)、想把它解析成可直接用于后续工具的 baseId 时使用;内部按 --name 关键词调用 search_bases 搜索 Base,再在本地投影出每个候选的 baseId 和 name。如果只命中一个 Base 就直接返回它的 baseId;如果命中多个则列出全部候选让你消歧,绝不替你瞎猜;如果一个都没命中则提示未找到。这是纯只读操作,只做搜索与本地投影,不会修改任何 Base。" + "只知道 Base 名称或关键词,需要解析成唯一 baseId 供后续 Table/Record 操作时" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;只要完整候选列表用 +base-search;浏览最近访问用 +base-list;已知 baseId 不再重复搜索" ], "examples": [ "dws aitable +resolve-base --name 项目管理" @@ -2868,10 +2874,10 @@ "aitable.shortcut_resolve_table": { "agent_summary": "在某个多维表 Base 内按名称解析出唯一的数据表 tableId(只读)", "use_when": [ - "当你已经知道某个多维表 Base 的 baseId、又只记得里面某张数据表(table)的名称或名称关键词、想把它解析成可直接用于后续工具的 tableId 时使用;内部先用 get_tables(只传 baseId)列出该 Base 下的全部数据表,再在本地把每张表投影成 tableId、name,并按 --name 关键词做大小写不敏感的包含匹配来筛选候选。如果只命中一张表就直接返回它的 tableId;如果命中多张则列出全部候选让你消歧,绝不替你瞎猜;如果一张都没命中则提示未找到。这是纯只读操作,只做列举、本地匹配与投影,不会创建、修改或删除任何数据表。" + "已有真实 baseId、只知道数据表名称或关键词,需要解析成唯一 tableId 时" ], "avoid_when": [ - "需要该 Shortcut 未公开的底层参数、原始响应或不同执行语义时,改用对应原子命令" + "多候选时必须让用户消歧;需要所有表及字段/视图目录用 +table-get;已知 tableId 不再重复解析" ], "examples": [ "dws aitable +resolve-table --base B --name 任务" @@ -2887,18 +2893,19 @@ }, "products": { "aitable": { - "agent_summary": "管理 AI 表格 Base、数据表、字段、记录、视图、表单、仪表盘、权限、导入导出与自动化工作流。", + "agent_summary": "管理 AI 表格的 Base、Table、Field、Record、视图表单、仪表盘、权限、导入导出与自动化工作流。", "use_when": [ - "需要读取或管理 AI 表格中的结构、数据、视图、权限、导入导出或工作流时" + "目标是 AI 表格/多维表中的结构化 Base、数据表、字段、记录、视图、权限、文件导入导出或自动化工作流时" ], "avoid_when": [ - "目标是在线电子表格单元格读写时用 sheet;普通文档用 doc" + "在线电子表格工作表、单元格或公式用 sheet;普通文档用 doc;钉盘普通文件用 drive;类型不明的 alidocs URL 先做类型预检" ], "reviewed": true, - "review_reason": "人工结合实时 MCP/Skill/Cobra 审阅产品级选择边界。", + "review_reason": "人工结合多产品边界、根 Skill 的渐进加载顺序、真实 Cobra/Shortcut 路径与 MCP 语义审阅产品级选择边界。", "source_refs": [ "internal/cli/schema_command_registry.json", - "skills/mono/references/products/aitable.md", + "skills/multi/dingtalk-aitable/SKILL.md", + "skills/multi/dingtalk-aitable/references/aitable.md", "dws-schema-live:product-index" ] } diff --git a/scripts/gen_skill_shortcut_sections.py b/scripts/gen_skill_shortcut_sections.py index 9df3e9e9..8fe9b519 100644 --- a/scripts/gen_skill_shortcut_sections.py +++ b/scripts/gen_skill_shortcut_sections.py @@ -55,7 +55,7 @@ PRODUCT_END = "" # only after verifying that the product skill has its own reviewed routing # section and intent table; compacting a sparse skill without an alternative # route would make its shortcuts harder to discover. -COMPACT_PRODUCT_SERVICES = {"chat", "doc"} +COMPACT_PRODUCT_SERVICES = {"aitable", "chat", "doc"} # These compact products have every public Shortcut curated into Runtime # Schema. Keep this separate from COMPACT_PRODUCT_SERVICES because Chat still diff --git a/scripts/policy/check-skill-context-budget.sh b/scripts/policy/check-skill-context-budget.sh index dfb1cc10..a21a366d 100755 --- a/scripts/policy/check-skill-context-budget.sh +++ b/scripts/policy/check-skill-context-budget.sh @@ -7,9 +7,11 @@ cd "$ROOT" python3 scripts/gen_skill_shortcut_sections.py --check chat_skill="skills/multi/dingtalk-chat/SKILL.md" +aitable_skill="skills/multi/dingtalk-aitable/SKILL.md" doc_skill="skills/multi/dingtalk-doc/SKILL.md" mono_skill="skills/mono/SKILL.md" chat_max_bytes=14000 +aitable_max_bytes=11000 doc_max_bytes=9500 chat_bytes="$(wc -c < "$chat_skill" | tr -d ' ')" @@ -19,6 +21,13 @@ if [ "$chat_bytes" -gt "$chat_max_bytes" ]; then exit 1 fi +aitable_bytes="$(wc -c < "$aitable_skill" | tr -d ' ')" +if [ "$aitable_bytes" -gt "$aitable_max_bytes" ]; then + printf '%s\n' \ + "skill context budget exceeded: $aitable_skill is ${aitable_bytes} bytes (max ${aitable_max_bytes})" >&2 + exit 1 +fi + doc_bytes="$(wc -c < "$doc_skill" | tr -d ' ')" if [ "$doc_bytes" -gt "$doc_max_bytes" ]; then printf '%s\n' \ @@ -40,6 +49,20 @@ if [ "$shortcut_rows" -ne 0 ]; then exit 1 fi +aitable_shortcut_rows="$( + awk ' + // { in_block = 1; next } + // { in_block = 0 } + in_block && /^\|[[:space:]]*`/ { count++ } + END { print count + 0 } + ' "$aitable_skill" +)" +if [ "$aitable_shortcut_rows" -ne 0 ]; then + printf '%s\n' \ + "skill context budget exceeded: $aitable_skill re-expanded $aitable_shortcut_rows shortcut rows" >&2 + exit 1 +fi + doc_shortcut_rows="$( awk ' // { in_block = 1; next } @@ -61,4 +84,4 @@ if grep -Fq "充分阅读产品参考文件" "$mono_skill"; then fi printf '%s\n' \ - "skill context budget: ok (chat_bytes=$chat_bytes max=$chat_max_bytes shortcut_rows=$shortcut_rows; doc_bytes=$doc_bytes max=$doc_max_bytes shortcut_rows=$doc_shortcut_rows)" + "skill context budget: ok (chat_bytes=$chat_bytes max=$chat_max_bytes shortcut_rows=$shortcut_rows; aitable_bytes=$aitable_bytes max=$aitable_max_bytes shortcut_rows=$aitable_shortcut_rows; doc_bytes=$doc_bytes max=$doc_max_bytes shortcut_rows=$doc_shortcut_rows)" diff --git a/skills/multi/dingtalk-aitable/SKILL.md b/skills/multi/dingtalk-aitable/SKILL.md index 3a7bb5e2..65e3b293 100644 --- a/skills/multi/dingtalk-aitable/SKILL.md +++ b/skills/multi/dingtalk-aitable/SKILL.md @@ -1,6 +1,6 @@ --- name: dingtalk-aitable -description: 钉钉 AI 表格(多维表)。Use when 用户说 AI表格/多维表/数据表/base/table/建表/查记录/写数据/字段/记录增删改查/筛选/排序/公式/模板搜索/批量导入CSV或JSON/导出/仪表盘/图表/上传附件到表格/按字段类型建表。不做电子表格单元格读写(走 dingtalk-misc)、文档编辑(走 dingtalk-doc);听记待办入表先用 dingtalk-minutes 提取,再由本 skill 写入。命令前缀:dws aitable。 +description: 钉钉 AI 表格(多维表)。Use when 用户说 AI表格/多维表/Base/数据表/字段/记录增删改查/筛选排序/公式与跨表引用/视图表单/仪表盘图表/高级权限/自动化工作流/模板/CSV或JSON批量导入/Excel导入导出/记录附件。不做电子表格单元格读写与工作表公式(走 dingtalk-sheet)、普通文档编辑(走 dingtalk-doc)或钉盘文件管理(走 dingtalk-drive);听记待办入表先用 dingtalk-minutes 提取,再由本 skill 写入。命令前缀:dws aitable。 metadata: cli_version: ">=0.2.14" category: product @@ -15,146 +15,86 @@ metadata: > **CRITICAL — 执行任何 `dws` 操作前,MUST 先用 Read 工具完整读取 [`dws-shared`](../dws-shared/SKILL.md)。**该轻量文件包含全局执行契约、安全底线及 shared references 的按需加载导航;不要预加载其全部 references。 -> 命令参考:[aitable.md](references/aitable.md);复杂命令按需加载 `references/aitable/*.md`;剧本:[06-data-analytics.md](references/06-data-analytics.md)。 +## 加载与路由顺序 + +1. 命中下方高频意图时直接使用精确骨架,不先查 Help 或产品级 Schema。 +2. 路由优先级固定为:精确 recipe / 可运行脚本 > 匹配的公开 Shortcut > 原子命令。命令已确定且参数清楚时直接执行。 +3. 参数、约束或安全语义不确定时只读 leaf Schema:`dws schema --cli-path "aitable " --format json`;只有当前 Cobra flag 不确定时才读对应 `--help`。 +4. 复杂字段、筛选、导入导出、视图、权限或工作流任务,按“低频能力与 Reference”只加载相关文件,不预读整个 `references/aitable/`。 +5. 现有骨架和 reference 都无法定位能力时,才用 Runtime Shortcut Catalog 做最后发现;不得猜 `cli_path` 或 flag。 +6. Schema、Help、reference 与实际返回冲突时采用更安全的解释并报告契约漂移;`confirmation=user_required` 时先确认,再添加 `--yes`。 -## Shortcuts(无专用脚本/recipe 时优先) +## Shortcut 发现(按需) -以下 shortcut 同时进入公开 catalog 与 Runtime Schema。先按本 skill 的意图表、脚本和 recipe 路由:存在精确覆盖该场景的专用脚本/recipe 时按其执行;否则用户意图命中时,shortcut 优先于手写原子命令。命令已选中时直接执行;只在参数或安全语义不确定时读取 leaf Schema(例如 `dws schema --cli-path "aitable +" --format json`),在当前 Cobra flags 不确定时读取 `dws aitable --help`。仅当现有路由和 reference 都无法定位低频能力时,才用 `dws shortcut list --service aitable --format json` 批量发现。 +`aitable` 当前有 29 条公开 shortcut。完整清单保留在 Runtime Shortcut Catalog;已完成 Schema curation 的子集可通过 leaf Schema 查询。高频产品根 Skill 不重复展开完整清单。已知意图直接使用下方的优先路由、意图表或任务 reference;命令已选中时直接执行,只在参数/安全语义不确定时读取 leaf Schema,在当前 Cobra flags 不确定时读取 leaf Help。 -| Shortcut | 风险 | 适用场景 | -|---|---|---| -| `dws aitable +base-get` | read | 获取指定 Base 的目录信息(tables / dashboards summary) | -| `dws aitable +base-list` | read | 获取当前用户可访问的 AI 表格 Base 列表(最近访问,支持游标分页) | -| `dws aitable +base-search` | read | 按名称关键词搜索 AI 表格 Base | -| `dws aitable +chart-get` | read | 获取指定 chart 的详细信息 | -| `dws aitable +chart-widgets-example` | read | 获取所有图表类型的 widget config 示例 | -| `dws aitable +dashboard-config-example` | read | 获取 dashboard config 的结构示例 | -| `dws aitable +dashboard-get` | read | 获取指定 dashboard 的详细信息(含 charts summary) | -| `dws aitable +field-get` | read | 批量获取字段详情(含类型相关完整配置) | -| `dws aitable +find-record` | read | 在指定多维表里按关键词查记录(只读) | -| `dws aitable +form-field-list` | read | 列出表单视图当前可见的字段及其配置 | -| `dws aitable +form-list` | read | 列出指定数据表下的所有表单视图 | -| `dws aitable +form-share-get` | read | 读取视图当前的分享表单配置 | -| `dws aitable +list-tables` | read | 列出某个多维表(base)里的所有数据表(只读,投影 tableId/tableName) | -| `dws aitable +record-history-list` | read | 按 recordId 查询单条记录的变更历史 | -| `dws aitable +record-query` | read | 查询表格记录(按 ID 取 / 条件筛选 / 关键词 / 分页) | -| `dws aitable +record-query-empty` | read | 扫描并过滤出完全没填用户字段的空行 | -| `dws aitable +record-share-links` | read | 批量(可 >20 条)获取多维表记录分享链接:去重+分片+合并 | -| `dws aitable +record-share-url` | read | 按 recordId 批量获取记录分享链接,单次最多 20 条 | -| `dws aitable +resolve-base` | read | 按名称搜索多维表 Base 并解析出唯一 baseId(只读) | -| `dws aitable +resolve-table` | read | 在某个多维表 Base 内按名称解析出唯一的数据表 tableId(只读) | -| `dws aitable +role-list` | read | 列出指定 Base 下的全部角色 | -| `dws aitable +section-list-empty` | read | 列出指定 Base 下所有没有子节点的空文件夹 | -| `dws aitable +section-list-nodes` | read | 列出指定 Base 当前版本下的全部 nsheet 节点 | -| `dws aitable +table-get` | read | 批量获取指定数据表的表级信息、字段目录与视图目录 | -| `dws aitable +template-search` | read | 按名称关键词搜索 AI 表格模板 | -| `dws aitable +view-get` | read | 获取视图完整信息(列顺序、筛选、排序、分组等) | -| `dws aitable +view-get-frozen-cols` | read | 获取视图当前冻结的左侧列数 | -| `dws aitable +view-get-lock` | read | 获取视图锁定状态 | -| `dws aitable +view-get-row-height` | read | 获取视图单元格行高(像素) | +仅当现有路由和 reference 都无法定位低频能力时,才执行 `dws shortcut list --service aitable --compact --format json` 做最后回退;不要为已知高频意图加载完整 Shortcut Catalog 或产品级 Schema。 -## 意图表 +## 核心对象与 ID -| 用户说 | 命令 | -|--------|------| -| "搜表格 / 找一个 base" | `dws aitable base search --query "<名>"` | -| "创建 AI 表格 / 多维表" | `dws aitable base create --name "<名称>" [--template-id ]` | -| "查数据表 / 建数据表" | `dws aitable table get --base-id ` / `dws aitable table create --base-id --name "<表名>" --fields '[...]'` | -| "查字段 / 字段类型" | `dws aitable field get --base-id --table-id ` | -| "查记录 / 搜索记录" | `dws aitable record query --base-id --table-id [--filters '...']` | -| "写记录 / 更新记录 / 删除记录" | `dws aitable record create/update/delete --base-id --table-id ...` | -| "筛选 / 排序 / 公式 / 跨表引用" | 先读 `references/aitable/aitable-filter-sort.md` / `aitable-formula-guide.md` | -| "批量导入 JSON / CSV" | `python scripts/import_records.py data.csv\|data.json` | -| "批量加字段" | `python scripts/bulk_add_fields.py --base-id --table-id --fields fields.json` | -| "导入 / 导出表格" | 先读 `references/aitable/aitable-export-import.md`;导出优先 `python scripts/aitable_export_via_task.py --scope table --table-id ` | -| "仪表盘 / 图表" | 先读 `references/aitable/aitable-dashboard-chart.md` | -| "上传附件到记录" | 先读 `references/aitable/aitable-attachment.md`;可用 `python scripts/upload_attachment.py --base-id --file ` | +| 对象 | 标识与执行边界 | +|---|---| +| Base | `baseId` 标识一个 AI 表格文件;名称只用于搜索或消歧,不能当 ID | +| Table | `tableId` 标识 Base 内的数据表;必须来自 `+resolve-table` / `+table-get` / 创建返回 | +| Field | `fieldId` 标识列;写入、筛选、排序和字段变更优先使用真实 `fieldId` | +| Record | `recordId` 标识行;更新、删除和分享前必须先查询得到真实 ID | +| View / Dashboard / Chart | `viewId` / `dashboardId` / `chartId` 各自绑定当前 Base/Table,不跨对象复用 | +| 异步任务 | `taskId` / `importId` 只用于对应导出或导入任务,不能替代业务对象 ID | -## 标准 SOP(必遵流程) +所有下游 ID 都从当前链路的结构化返回中提取;同名多候选必须让用户消歧,不默认取第一项,也不复用未经本轮校验的旧 ID。 -> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 flag/ID。每条命令必须带 `--format json`,执行后必须按"解析"步取真实字段,不得凭返回结构猜测。`baseId`/`tableId`/`fieldId`/`recordId` 一律先查后用,**禁止默认/编造**。 +## 核心意图与执行骨架 -### SOP-1 定位 Base 与 Table(list / search → table get) +| 用户意图 | 首选骨架 | 必须保留的执行边界 | +|---|---|---| +| 按名称找 Base | `dws aitable +resolve-base --name "<名称>" --format json` | 唯一命中才继续;多候选停止并消歧 | +| 浏览最近访问 | `dws aitable +base-list --format json` | 只代表最近访问,不得宣称全量 | +| 按名称找 Table | `dws aitable +resolve-table --base --name "<表名>" --format json` | `baseId` 必须来自上一步真实返回 | +| 取表、字段与视图目录 | `dws aitable +table-get --base-id [--table-ids ] --format json` | `tables[].fields[]` 是字段目录;完整类型/config 再用 `+field-get` | +| 取字段完整配置 | `dws aitable +field-get --base-id --table-id [--field-ids ] --format json` | 写入前核对类型、只读性和 select options;按需展开以控制返回体 | +| 查/搜/筛记录 | `dws aitable +record-query --base-id --table-id [--query <词>\|--filters ''\|--record-ids ] --format json` | ID 模式忽略 filter/sort;全量结论必须完整分页 | +| 新增记录 | `dws aitable record create --base-id --table-id --records '[{"cells":{"":<值>}}]' --format json` | 单次最多 100;取 `data.newRecordIds[]` 后立即按 ID 回读 | +| 更新记录 | `dws aitable record update --base-id --table-id --records '[{"recordId":"","cells":{"":<值>}}]' --format json` | 先 query 拿 recordId;只传需改字段;取 `data.recordIds[]` 后回读 | +| 删除记录 | 先 `dws aitable +record-query ...` 定位,再 `dws aitable record delete --base-id --table-id --record-ids ` | 展示目标与影响,得到明确确认后才加 `--yes` | +| 创建 Base / Table | `dws aitable base create --name "<名>"` / `dws aitable table create --base-id --name "<名>" --fields '[...]'` | 使用创建返回的真实 ID;系统改名/加后缀时不得继续猜原名 | +| 批量追加 CSV / JSON 到已有表 | `python3 scripts/import_records.py [batch_size]` | CSV 表头必须是 fieldId;脚本返回不完整 ledger 时不得宣称全成功 | +| 文件导入为新数据表 | `python3 scripts/aitable_import_via_task.py ` | 与“追加已有 table”不同;走 prepare → PUT → import task | +| 批量创建字段 | `python3 scripts/bulk_add_fields.py fields.json` | 单次最多 15;逐项检查成功/失败结果 | +| 导出 Base / Table / View | `python3 scripts/aitable_export_via_task.py --scope all\|table\|view [...]` | 保存路径、覆盖与异步未完成状态必须显式处理 | +| 上传记录附件 | `python3 scripts/upload_attachment.py ` | 返回 `fileToken` 后仍需按字段格式写入记录并回读 | -**触发**:找/打开某张 AI 表格、不知 baseId 或 tableId。 +## 记录读写不变量 -1. **选源(必须)**:有名称/关键词 → `dws aitable base search --query "<名称>"`;列最近访问 → `dws aitable base list`。`base list` 仅返回最近访问,不是全部,**禁止**当作全量清单。 -2. **执行(必须)**:`dws aitable base search --query "<完整名>" --format json`(或 `dws aitable base list --format json`)。 -3. **解析(必须)**:从 JSON 取真实 `baseId`;**多候选必须输出让用户选,禁止默认取第一个**。 -4. **取 tableId(必须)**:`dws aitable table get --base-id --format json` → 从 `data.tables[].tableId` 取目标表 ID,并记录 `views[]`。枚举模式不返回 `fields[]`;需要字段目录时必须继续执行 SOP-2 的 `field get`。若只核对某张表,可显式加 `--table-ids ` 控制返回体。 -5. **失败(必须)**:`base list` 为空或不命中 → 换 `base search --query` 关键词重试一次;仍无果**必须如实告知**,禁止臆造 baseId/tableId。 +- `record create/update` 前必须获取目标字段的 `fieldId`、`type` 与 `config`;`filterUp`、`lookup` 等只读字段不可写。完整格式只在需要时读 [aitable-cell-value.md](references/aitable/aitable-cell-value.md)。 +- 筛选和排序字段使用 `fieldId`;`--filters` 最外层是 `and|or + operands`,`--sort` 使用 `direction: asc|desc`。日期和跨表字段规则按需读 [aitable-filter-sort.md](references/aitable/aitable-filter-sort.md)。 +- `record query --all` 仍受 `--page-limit` 约束;分页中断或局部富化失败时保留已有结果,输出 completeness 与逐项失败 ledger,不把部分结果描述为全量。 +- 创建、更新、导入、批量建字段等写操作必须检查业务 `status`、逐项结果与返回 ID;普通写入按用户明确要求执行后回读,不能只凭退出码宣称成功。 +- 长 JSON 使用 `--records-file` / 任务文件;不得为绕过字段错误而静默丢列、改类型或删除失败项。 -**禁止**:跳过 `table get` 直接用字段名写记录、用模糊名匹配当 baseId、用旧会话里的 ID 不再校验。 +## 低频能力与 Reference -### SOP-2 拿字段定义(field get,写记录/改字段前置) +| 场景 | 按需读取 | +|---|---| +| 完整命令索引、对象 URL 与一级路由 | [aitable.md](references/aitable.md) | +| 记录 query/create/update/delete/upsert/history/share | 对应 `references/aitable/aitable-record-*.md` | +| 字段创建、字段 config、cellValue、公式与跨表引用 | [aitable-field.md](references/aitable/aitable-field.md)、[aitable-field-properties.md](references/aitable/aitable-field-properties.md)、[aitable-cell-value.md](references/aitable/aitable-cell-value.md)、[aitable-formula-guide.md](references/aitable/aitable-formula-guide.md) | +| 筛选、排序、统计、全量分析 | [aitable-filter-sort.md](references/aitable/aitable-filter-sort.md)、[aitable-data-analysis-sop.md](references/aitable/aitable-data-analysis-sop.md) | +| 导入导出、附件 | [aitable-export-import.md](references/aitable/aitable-export-import.md)、[aitable-attachment.md](references/aitable/aitable-attachment.md) | +| 视图、表单、仪表盘与图表 | [aitable-view-config.md](references/aitable/aitable-view-config.md)、[aitable-view-extras.md](references/aitable/aitable-view-extras.md)、[aitable-form.md](references/aitable/aitable-form.md)、[aitable-dashboard-chart.md](references/aitable/aitable-dashboard-chart.md) | +| 高级权限、自动化工作流、导航节点 | [aitable-advperm.md](references/aitable/aitable-advperm.md)、[aitable-workflow.md](references/aitable/aitable-workflow.md)、[aitable.md](references/aitable.md) 的 section 路由 | -**触发**:建/改/写记录、改字段名或 options、按字段类型拼写入参前。 +## 错误恢复 -1. **前置(必须)**:先按 SOP-1 拿到 `baseId` + `tableId`。 -2. **执行(必须)**:`dws aitable field get --base-id --table-id --format json`(仅展开需要的字段时加 `--field-ids fld1,fld2`,单次最多 10 个)。 -3. **解析(必须)**:取每个目标字段的 `fieldId`、`type`、`config`(如 singleSelect/multipleSelect 的 `options[].id|name`);写入 cells 的 key **必须用 `fieldId`**,不是字段中文名;select 字段过滤/写入传**选项名称字面量**,不传 option ID。 -4. **衔接(必须)**:拿到字段定义 → 进入 SOP-3 写记录、或 `dws aitable field update --field-id --name <新名>|--config --format json` 改字段。 -5. **失败(必须)**:字段不存在或类型不符 → 重新 `field get` 核对,**禁止**凭旧名称/旧类型继续写入。 - -**禁止**:用字段中文名当 cells key、跳过 `field get` 直接 `record create/update`、对 select 字段传 option ID 当写入值。 - -### SOP-3 写/批量写记录(record create) - -**触发**:新增记录、批量加数据、CSV/JSON 入表。 - -1. **前置(必须)**:SOP-1 取 `baseId`/`tableId` + SOP-2 取 `fieldId`/类型。 -2. **执行(必须)**:`dws aitable record create --base-id --table-id --records '[{"cells":{"":<值>}}]' --format json`;单次最多 100 条,超长用 `--records-file ./data.json`。 -3. **写入格式(必须)**:按 `record create --help` 类型表严格传值(text→字符串、number→数值、singleSelect→"选项名"、date→RFC3339、url→`{"text","link"}`、group→`{"cid"}` 等);`filterUp`/`lookup` 字段只读不可写。 -4. **解析与验证(必须)**:从返回 `data.newRecordIds[]` 取全部新记录 ID;不要读取不存在的标量 `recordId`。立即执行 `dws aitable record query --base-id --table-id --record-ids --format json` 回读写入值。 -5. **失败(必须)**:类型/格式错误按返回报错修正后重试,**禁止**降级丢弃字段;不确定格式先 `field get` 复核 config。 - -**禁止**:编造 fieldId/recordId、跳过 `field get` 凭中文名写、把 URL 字符串直接塞给 url 字段。 - -### SOP-4 查/筛/排记录(record query) - -**触发**:查记录、按条件筛选、排序、取关联记录、定位待改/待删的 recordId。 - -1. **前置(必须)**:SOP-1 拿 `baseId`/`tableId`。 -2. **执行(必须)**:`dws aitable record query --base-id --table-id --format json`;已知 ID 直取加 `--record-ids rec1,rec2`(忽略 filters/sort,单次≤100)。 -3. **筛选/排序(必须)**:`--filters` 最外层必须 `{"operator":"and|or","operands":[...]}`,select 字段值传**选项名字面量**;日期只能用 `date_eq/before/after/not_before/not_after`,范围用 `not_before`+`not_after` 组合,**禁止** `eq`/区间/相对时间。`--sort` 用 `[{"fieldId":"..","direction":"asc|desc"}]`(**必须用 `direction`**)。公式/引用/关联字段默认不返回,需显式 `--field-ids` 指定。 -4. **解析(必须)**:取真实 `recordId` 与字段值;分页用 `--cursor`,全表用 `--all --page-limit N`。 -5. **衔接(必须)**:拿到 recordId → SOP-5 更新、`record delete --record-ids --yes` 删除(删前确认)。 - -**禁止**:用字段名做 filter/sort key、对日期用 `eq`、漏掉 `direction` 用旧 `order` 字段、用本地过滤替代服务端 filter。 - -### SOP-5 更新记录(record update) - -**触发**:改记录字段值、批量更新状态、单字段重命名需求之外的记录改动。 - -1. **前置(必须)**:SOP-1 拿 `baseId`/`tableId`;SOP-2 拿字段类型;SOP-4 拿目标 `recordId`。 -2. **执行(必须)**:`dws aitable record update --base-id --table-id --records '[{"recordId":"recXXX","cells":{"":<新值>}}]' --format json`(每条必含 `recordId`+`cells`,单次≤100;超长用 `--records-file`);只传需改字段,未传保持原值。 -3. **解析与验证(必须)**:写入格式同 SOP-3;从返回 `data.recordIds[]` 取实际更新的记录 ID。更新响应不返回“受影响字段”,必须立即用 `record query --record-ids --format json` 回读目标字段确认。 -4. **失败(必须)**:recordId 不存在或类型不符 → 回 SOP-4 重新定位,**禁止**编造 ID 强写。 - -**禁止**:省略 `recordId`、用字段中文名当 cells key、凭空猜测 recordId 直接 update。 - -## 危险操作 - -`base delete` / `table delete` / `field delete` / `record delete` 不可逆,必须先向用户确认再加 `--yes`。 - -## 高频硬约束 - -- 创建/改字段/写记录是多轮连续任务时,不能在"让我执行/先获取 ID"后停下;必须实际调用对应 `dws aitable` 命令并验证结果。 -- 字段重命名使用 `dws aitable field update --base-id --table-id --field-id --name "<新名称>" --format json`;先 `field get` 找真实 `fieldId`,不要猜字段名能直接更新。 -- 写记录前必须 `field get` 获取 `fieldId` 与类型;`record create/update` 的 `cells` key 用 `fieldId`,不是字段中文名。长 JSON 使用 `--records-file`。 -- 表或字段创建返回名称被系统自动加后缀时,后续必须使用返回的真实 `tableId`/`fieldId`,不要继续按原名称猜。 -- `record update/delete` 先 `record query/list` 定位 `recordId`;删除必须确认,普通新增/更新按用户明确要求可直接执行后读回验证。 -- `record query/create/update/delete`、`field create`、导入导出、图表和附件场景必须先读对应 `references/aitable/*.md`,不要凭旧单文件参数猜 flag。 - -## 字段类型规则 - -详见本 skill 的 [field-rules.md](references/field-rules.md)。 +- 路径或 flag 错误:按既定的 leaf Schema → leaf Help 顺序校正一次;仍失败则停止,不连续尝试猜测别名。 +- 命令非零、输出非 JSON、业务 `status != success`、必需 ID 缺失、批处理部分失败均视为失败;保留成功项与 ledger,禁止吞错。 +- 同名歧义、权限不足、资源不存在、字段类型漂移、分页无法推进或 Schema/Help 冲突时停止并报告。具体恢复动作按需读 [aitable-error-recovery.md](references/aitable/aitable-error-recovery.md)。 +- 每次重试都从最新实际输出重新提取下游 ID;删除和其他 `confirmation=user_required` 操作不得自动重试或静默确认。 ## 跨产品协作 -- 单元格 / 工作表 / 公式 → 切到 `dingtalk-misc`(`references/sheet.md`,命令前缀:`dws sheet`) -## 局部意图 - -- [局部意图消歧](references/intent-guide.md)。 +- 电子表格工作表、单元格与公式 → `dingtalk-sheet`;结构化 Base/Table/Field/Record 才走本 skill。 +- 普通文档内容 → `dingtalk-doc`;钉盘普通文件与文件夹 → `dingtalk-drive`;记录附件上传仍走本 skill。 +- 用户直接提供类型不明的 alidocs URL 时,按 `dws-shared` 的 URL 预检导航确认 `extension=able` 后再执行。 +- 听记内容入表:先用 `dingtalk-minutes` 提取结构化结果,再按本 skill 的字段与记录规则写入。 diff --git a/skills/multi/dingtalk-aitable/references/aitable.md b/skills/multi/dingtalk-aitable/references/aitable.md index 890bea3e..b4e772f6 100644 --- a/skills/multi/dingtalk-aitable/references/aitable.md +++ b/skills/multi/dingtalk-aitable/references/aitable.md @@ -2,6 +2,8 @@ > **渐进式文档**:本文件为路由层(索引 + 意图判断),各命令的详细参数、示例和踩坑说明在 [aitable/](./aitable/) 目录下按需加载。 +已知高频意图优先使用根 Skill 的精确 Shortcut/脚本骨架;本文件只在需要完整一级命令索引、对象 URL 或低频分支导航时加载。参数与安全不确定时读 leaf Schema,Cobra flag 不确定时才读 leaf Help,不要把本文件当作参数事实源。 + ## 文档地址 (URI) | 资源 | URI 格式 | @@ -35,7 +37,7 @@ | 命令 | 用途 | 必填参数 | 路由提醒 | |------|------|----------|----------| -| `table get` | 获取数据表/视图目录 | `--base-id` | 不传 `--table-ids` 枚举全部表,但不返回字段;字段目录使用 `field get` | +| `table get` | 获取表级信息、字段目录与视图目录 | `--base-id` | 不传 `--table-ids` 枚举全部表并返回精简 `fields[]`/`views[]`;字段完整 config 使用 `field get` | | `table create` | 创建数据表 | `--base-id` `--name` `--fields` | fields 为 JSON 数组,至少 1 个 | | `table update` | 修改表名 / 备注 / 行命名规则 | `--base-id` `--table-id` + 三选一(`--name` / `--description` / `--record-name-key`) | `--record-name-key` 是固定枚举(如 task/project/event/customer/ji_lu 等),非字段 ID | | `table delete` | 删除表 | `--base-id` `--table-id` | 不可逆 | @@ -427,17 +429,18 @@ dws aitable export data --base-id --task-id --timeout-ms 300 ## 核心工作流 ```bash -# 1. 搜索/列出 Base — 提取 baseId -dws aitable base search --query "项目" --format json +# 1. 按名称解析唯一 Base — 提取 baseId;多候选必须消歧 +dws aitable +resolve-base --name "项目" --format json -# 2. 获取 Base 信息 — 提取 tableId -dws aitable base get --base-id --format json +# 2. 按名称解析唯一 Table — 提取 tableId +dws aitable +resolve-table --base --name "任务" --format json -# 3. 获取字段目录 — 提取 fieldId -dws aitable field get --base-id --table-id --format json +# 3. 获取字段目录;需要完整类型 config 时再调用 field get +dws aitable +table-get --base-id --table-ids --format json +dws aitable +field-get --base-id --table-id --format json # 4. 查询记录 -dws aitable record query --base-id --table-id --format json +dws aitable +record-query --base-id --table-id --format json # 5. 新增记录 (cells 用 fieldId 作 key) dws aitable record create --base-id --table-id \ @@ -452,8 +455,8 @@ dws aitable record create --base-id --table-id \ | `base create` | `baseId` | 后续命令 + 文档 URI | | `base get` | `tables[].tableId` | --table-id,拼接指定数据表 URI | | `table create` | `tableId` | 后续命令 + 拼接指定数据表 URI | -| `table get` | `tables[].tableId`、视图目录 | 定位数据表和视图;字段需继续调用 `field get` | -| `field get` | `fields[].fieldId` | record 操作的 cells key, field update/delete | +| `table get` | `tables[].tableId`、精简 `fields[]`、`views[]` | 定位数据表、字段目录和视图;完整字段 config 再用 `field get` | +| `field get` | `fields[].fieldId/type/config` | record 操作的 cells key、类型校验、field update/delete | | `record query` | `recordId` | record update/delete;按 ID 反查字段值用 `record get` | | `template search` | `templateId` | base create --template-id,拼接模板预览 URI | @@ -480,6 +483,7 @@ dws aitable record create --base-id --table-id \ |------|------| | [bulk_add_fields.py](../scripts/bulk_add_fields.py) | 批量添加字段 | | [import_records.py](../scripts/import_records.py) | 从 JSON/CSV 批量导入记录 | +| [aitable_import_via_task.py](../scripts/aitable_import_via_task.py) | 导入 CSV/XLS/XLSX 并新建数据表(prepare + PUT + import) | | [aitable_export_via_task.py](../scripts/aitable_export_via_task.py) | 文件导出(export_data 轮询 + 下载) | | [upload_attachment.py](../scripts/upload_attachment.py) | 上传附件到 AI 表格记录 | diff --git a/skills/multi/dingtalk-aitable/references/aitable/aitable-attachment.md b/skills/multi/dingtalk-aitable/references/aitable/aitable-attachment.md index 45e9c2ae..46e0e148 100644 --- a/skills/multi/dingtalk-aitable/references/aitable/aitable-attachment.md +++ b/skills/multi/dingtalk-aitable/references/aitable/aitable-attachment.md @@ -32,6 +32,7 @@ dws aitable record create --base-id --table-id \ ``` > `uploadUrl` 有时效性(`expiresAt`),脚本会自动在获取后立即上传。 +> 脚本只接受成功的业务响应和 HTTPS `uploadUrl`;它返回 `fileToken` 不等于记录已经写入,后续仍需执行 record create/update 并按 recordId 回读。 ## 手动流程(不使用脚本) diff --git a/skills/multi/dingtalk-aitable/references/aitable/aitable-error-recovery.md b/skills/multi/dingtalk-aitable/references/aitable/aitable-error-recovery.md index 88c3aa9c..0e66ef10 100644 --- a/skills/multi/dingtalk-aitable/references/aitable/aitable-error-recovery.md +++ b/skills/multi/dingtalk-aitable/references/aitable/aitable-error-recovery.md @@ -15,6 +15,7 @@ - `status: "error"` 表示操作失败 - `summary` 包含错误摘要信息 - `trace_id` 用于问题追踪 +- 命令退出码为 0 但 `status != "success"`、必需 ID 缺失或逐项结果含失败,也属于业务失败 ## 2. 常见错误与恢复动作 @@ -42,7 +43,7 @@ |-------------------|------|---------| | `base not found` | base-id 错误或无权限 | 确认 base-id 正确;尝试 `base list` 或 `base search` 重新定位 | | `table not found` | table-id 错误 | 用 `table get --base-id ` 不带 table-ids 查看所有表 | -| 表名重复 | 同 Base 下已存在同名表 | 系统会自动续号(如"原名 1"),无需额外处理 | +| 表名重复 | 同 Base 下已存在同名表 | 使用创建返回的真实 `tableId/tableName`;禁止继续按原名猜测目标 | ### 2.4 视图操作错误 @@ -57,7 +58,7 @@ |-------------------|------|---------| | filters 无效被忽略 | 根节点不是 and/or,或 operands 格式错误 | 确保 filters 根节点是 `{"operator":"and"/"or", "operands":[...]}` 结构 | | sort 无效 | fieldId 不存在 | 先 `field get` 确认字段 ID | -| 筛选结果为空 | 条件过严或字段值不匹配 | 放宽条件验证;注意 singleSelect 筛选值用 option name 或 id | +| 筛选结果为空 | 条件过严或字段值不匹配 | 放宽条件验证;singleSelect/multipleSelect 筛选值使用 option name 字面量 | ### 2.6 导入导出错误 @@ -65,6 +66,7 @@ |-------------------|------|---------| | 导出任务超时 | 数据量大,异步任务未完成 | 用 `export data --task-id ` 轮询直到完成 | | 导入文件格式错误 | 不支持的文件格式或文件损坏 | 确认文件为 .xlsx 格式且未加密 | +| 批处理只成功一部分 | 某批或某个字段返回失败 | 保留成功 ID,输出失败 batch/item ledger,以非零状态结束;不要整批重放 | ## 3. 重试策略 @@ -106,18 +108,6 @@ dws aitable record create \ `--verbose` 会输出请求/响应的详细信息,帮助定位问题。 -### 4.2 使用 --dry-run 预览 - -```bash -dws aitable record create \ - --base-id \ - --table-id \ - --records '[...]' \ - --dry-run --format json -``` - -`--dry-run` 只预览不执行,适合在不确定参数是否正确时先验证。 - ## 5. 错误预防最佳实践 1. **写记录前先读字段结构** — `field get` 确认字段类型和 ID diff --git a/skills/multi/dingtalk-aitable/references/aitable/aitable-export-import.md b/skills/multi/dingtalk-aitable/references/aitable/aitable-export-import.md index fc755451..0030f982 100644 --- a/skills/multi/dingtalk-aitable/references/aitable/aitable-export-import.md +++ b/skills/multi/dingtalk-aitable/references/aitable/aitable-export-import.md @@ -4,6 +4,8 @@ `export data` 为异步任务:首次调用可能只返回 `taskId`,需要继续轮询。 +优先使用 `python3 scripts/aitable_export_via_task.py --scope all|table|view [...]`:它检查业务状态、持续轮询、要求 HTTPS 下载地址,并在本地文件已存在时停止而不是静默覆盖。只有需要控制底层轮询参数时才走下面的原子命令。 + > ⚠️ **`--format` 冲突警告**:`export data` 的 `--format` 是**导出格式**(excel/attachment 等),不是全局输出格式。**此命令禁止追加全局 `--format json`**,否则会覆盖导出格式导致 `INVALID_EXPORT_FORMAT` 错误。输出默认就是 JSON,无需额外指定。 ```bash @@ -28,6 +30,8 @@ dws aitable export data --base-id --task-id --timeout-ms 300 > **无需手动解析 CSV/Excel 再逐条 record create**,效率极低且容易出错。 +新建数据表导入优先使用 `python3 scripts/aitable_import_via_task.py `,脚本封装 prepare → PUT → import 并检查每一步业务状态。追加到已有表且需要字段级类型控制时,使用 `python3 scripts/import_records.py [batch_size]`;二者语义不同,不要自动互换。 + ```bash # 第 1 步:申请上传凭证 dws aitable import upload --base-id \ diff --git a/skills/multi/dingtalk-aitable/references/aitable/aitable-field.md b/skills/multi/dingtalk-aitable/references/aitable/aitable-field.md index 303cf474..3cd623af 100644 --- a/skills/multi/dingtalk-aitable/references/aitable/aitable-field.md +++ b/skills/multi/dingtalk-aitable/references/aitable/aitable-field.md @@ -14,7 +14,7 @@ Flags: --table-id string Table ID (必填) ``` -返回字段的完整配置(含 options 等)。不要假设未指定 `--table-ids` 的 `table get` 枚举结果含字段;字段目录和配置以 `field get` 返回为准。 +返回字段的完整配置(含 options 等)。`table get` 会返回精简字段目录,但写入、筛选或修改前需要类型相关完整 `config` 时,以 `field get` 返回为准。 ## field create — 创建字段 diff --git a/skills/multi/dingtalk-aitable/references/aitable/aitable-record-create.md b/skills/multi/dingtalk-aitable/references/aitable/aitable-record-create.md index ec597412..ebc00e8d 100644 --- a/skills/multi/dingtalk-aitable/references/aitable/aitable-record-create.md +++ b/skills/multi/dingtalk-aitable/references/aitable/aitable-record-create.md @@ -47,6 +47,8 @@ dws aitable record query --base-id --table-id \ 创建成功以 `data.newRecordIds[]` 为 ID 来源;不要把整个 `data` 当作单个 recordId,也不要只以退出码作为写入成功证据。 +批量追加本地 JSON/CSV 到已有表时可使用 `python3 scripts/import_records.py [batch_size]`。脚本会逐批检查业务状态、收集 `newRecordIds` 并按 ID 回读;任何批次失败或回读不完整都会输出 ledger 并以非零状态结束,已有成功批次仍会保留在结果中。 + ## cells 写入格式 各字段类型的写入格式见 [aitable-cell-value.md](./aitable-cell-value.md)。 diff --git a/skills/multi/dingtalk-aitable/references/aitable/aitable-record-query.md b/skills/multi/dingtalk-aitable/references/aitable/aitable-record-query.md index 20ed92da..c8133354 100644 --- a/skills/multi/dingtalk-aitable/references/aitable/aitable-record-query.md +++ b/skills/multi/dingtalk-aitable/references/aitable/aitable-record-query.md @@ -60,7 +60,7 @@ dws aitable record query --base-id X --table-id Y --all --cursor "上次返回 {"operator":"and","operands":[{"operator":"eq","operands":["",""]}]} ``` -> **singleSelect/multipleSelect 过滤**:filters 中可传 option id 或 option name,但建议优先用 **option id**(通过 `field get` 获取),更可靠。 +> **singleSelect/multipleSelect 过滤**:filters 中传选项名称字面量,不传 option id。选项名称先通过 `field get` 的 `config.options[]` 核对。 ## 减少响应体积 diff --git a/skills/multi/dingtalk-aitable/references/aitable/aitable-record-update.md b/skills/multi/dingtalk-aitable/references/aitable/aitable-record-update.md index eb47db53..a1e133c1 100644 --- a/skills/multi/dingtalk-aitable/references/aitable/aitable-record-update.md +++ b/skills/multi/dingtalk-aitable/references/aitable/aitable-record-update.md @@ -17,23 +17,17 @@ Flags: 只需传入需修改的字段,未传入的保持原值。每条记录必须含 recordId 和 cells。 -## cells key:优先使用 fieldId,也支持唯一字段名 +## cells key:自动化与 Agent 路径使用 fieldId -`cells` 的 key 有两种写法: +公开稳定的 Agent/自动化写法是 `fieldId`:它不受字段重命名或重名影响,并可通过 `field get` 获取。 -- fieldId(推荐):不受字段重命名或重名影响,通过 `field get` 获取。 -- 当前表内唯一的字段名:按名称精确匹配;如果存在同名字段,必须改用 fieldId。 - -同一字段同时通过 fieldId 和字段名传入时,fieldId 对应的值优先。 +Runtime 仍兼容当前表内唯一字段名,但这属于便捷兼容路径:重名或重命名会改变解析结果,不能用于脚本、跨步骤调用或从旧上下文重放。字段名与 fieldId 同时出现时也不要依赖覆盖顺序。 ```bash # 推荐:fieldId dws aitable record update --base-id --table-id \ --records '[{"recordId":"recXXX","cells":{"fldStatusId":"已完成"}}]' --format json -# 便捷写法:当前表内唯一字段名 -dws aitable record update --base-id --table-id \ - --records '[{"recordId":"recXXX","cells":{"状态":"已完成"}}]' --format json ``` ## 推荐参数形式 diff --git a/skills/multi/dingtalk-aitable/scripts/aitable_export_via_task.py b/skills/multi/dingtalk-aitable/scripts/aitable_export_via_task.py index caa66f80..6921fc24 100644 --- a/skills/multi/dingtalk-aitable/scripts/aitable_export_via_task.py +++ b/skills/multi/dingtalk-aitable/scripts/aitable_export_via_task.py @@ -54,15 +54,20 @@ def parse_json_output(raw: str) -> Optional[Dict[str, Any]]: def normalize_download_url(url: str) -> str: - if url.startswith("http://") or url.startswith("https://"): - return url - return f"https://{url}" + normalized = url if "://" in url else f"https://{url}" + parsed = urlparse(normalized) + if parsed.scheme != "https" or not parsed.hostname: + raise ValueError("downloadUrl 必须是有效的 HTTPS URL") + return normalized def download_file(url: str, output_path: Path) -> Tuple[bool, str]: req = Request(url, method="GET") try: with urlopen(req, timeout=180) as resp: + redirected = urlparse(resp.geturl()) + if redirected.scheme != "https" or not redirected.hostname: + return False, "download redirect is not HTTPS" if resp.status != 200: return False, f"download http status: {resp.status}" output_path.write_bytes(resp.read()) @@ -79,6 +84,20 @@ def fail(msg: str, code: int = 1) -> None: sys.exit(code) +def resolve_output_path(value: Optional[str], file_name: str, overwrite: bool) -> Path: + root = Path.cwd().resolve() + candidate = Path(value) if value else Path(file_name).name + output_path = candidate.resolve() if candidate.is_absolute() else (root / candidate).resolve() + try: + output_path.relative_to(root) + except ValueError as exc: + raise ValueError("输出路径必须位于当前工作目录内") from exc + if output_path.exists() and not overwrite: + raise ValueError(f"输出文件已存在:{output_path};如需覆盖请显式传 --overwrite") + output_path.parent.mkdir(parents=True, exist_ok=True) + return output_path + + def build_start_args(args: argparse.Namespace) -> list[str]: cmd = [ "aitable", @@ -113,6 +132,7 @@ def main() -> None: parser.add_argument("--output", help="本地保存路径(不传则按 fileName 保存到当前目录)") parser.add_argument("--dws", default="dws", help="dws 可执行文件路径,默认 dws") parser.add_argument("--no-download", action="store_true", help="仅返回 downloadUrl,不下载文件") + parser.add_argument("--overwrite", action="store_true", help="允许覆盖当前工作目录内的已有输出文件") args = parser.parse_args() if not validate_resource_id(args.base_id): @@ -121,6 +141,10 @@ def main() -> None: fail("scope=table/view 时必须传 --table-id") if args.scope == "view" and not args.view_id: fail("scope=view 时必须传 --view-id") + if args.table_id and not validate_resource_id(args.table_id): + fail("无效的 tableId 格式") + if args.view_id and not validate_resource_id(args.view_id): + fail("无效的 viewId 格式") print("[1/2] start export task", file=sys.stderr) rc, out, err = run_dws(args.dws, build_start_args(args), timeout_sec=120) @@ -132,7 +156,7 @@ def main() -> None: data = obj.get("data", {}) or {} status = obj.get("status") - if status == "error": + if status != "success": fail(f"export_data 返回失败: {json.dumps(obj, ensure_ascii=False)}") download_url = data.get("downloadUrl") @@ -163,7 +187,7 @@ def main() -> None: obj2 = parse_json_output(out2) if not obj2: fail(f"export_data 轮询返回非 JSON: {out2[:300]}") - if obj2.get("status") == "error": + if obj2.get("status") != "success": fail(f"export_data 轮询返回失败: {json.dumps(obj2, ensure_ascii=False)}") d2 = obj2.get("data", {}) or {} download_url = d2.get("downloadUrl") or download_url @@ -194,8 +218,11 @@ def main() -> None: print(json.dumps(result, ensure_ascii=False, indent=2)) return - norm_url = normalize_download_url(download_url) - output_path = Path(args.output).expanduser().resolve() if args.output else Path.cwd() / file_name + try: + norm_url = normalize_download_url(download_url) + output_path = resolve_output_path(args.output, file_name, args.overwrite) + except ValueError as exc: + fail(str(exc)) ok, dl_err = download_file(norm_url, output_path) if not ok: fail(f"downloadUrl 下载失败: {dl_err}") diff --git a/skills/multi/dingtalk-aitable/scripts/aitable_import_via_task.py b/skills/multi/dingtalk-aitable/scripts/aitable_import_via_task.py index fea1ad5e..6abb1f45 100644 --- a/skills/multi/dingtalk-aitable/scripts/aitable_import_via_task.py +++ b/skills/multi/dingtalk-aitable/scripts/aitable_import_via_task.py @@ -22,6 +22,7 @@ import sys from pathlib import Path from typing import Any, Dict, Optional, Tuple from urllib.error import HTTPError, URLError +from urllib.parse import urlparse from urllib.request import Request, urlopen RESOURCE_ID_PATTERN = re.compile(r"^[A-Za-z0-9_-]{8,128}$") @@ -52,6 +53,9 @@ def parse_json_output(raw: str) -> Optional[Dict[str, Any]]: def put_file(upload_url: str, file_path: Path) -> Tuple[bool, str]: + parsed = urlparse(upload_url) + if parsed.scheme != "https" or not parsed.hostname: + return False, "uploadUrl must be a valid HTTPS URL" payload = file_path.read_bytes() req = Request(upload_url, data=payload, method="PUT") # 关键:清空 Content-Type,避免 SignatureDoesNotMatch。 diff --git a/skills/multi/dingtalk-aitable/scripts/bulk_add_fields.py b/skills/multi/dingtalk-aitable/scripts/bulk_add_fields.py index 3ba88313..a03d00c0 100644 --- a/skills/multi/dingtalk-aitable/scripts/bulk_add_fields.py +++ b/skills/multi/dingtalk-aitable/scripts/bulk_add_fields.py @@ -1,273 +1,276 @@ #!/usr/bin/env python3 -""" -批量添加字段到钉钉 AI 表格数据表(新版 schema) +"""批量添加字段到钉钉 AI 表格数据表。 用法: - python bulk_add_fields.py fields.json + python3 bulk_add_fields.py fields.json -fields.json 格式: - [ - {"fieldName": "字段 1", "type": "text"}, - {"fieldName": "字段 2", "type": "number", "config": {"formatter": "INT"}}, - {"fieldName": "字段 3", "type": "singleSelect", "config": {"options": [{"name": "高"}]}} - ] - -兼容写法: -- name 会自动映射为 fieldName -- phone 会自动映射为 telephone +脚本检查业务状态和逐项结果,并回读成功字段。部分成功会输出 ledger,但整体以非零 +状态结束。fields.json 单次最多 15 个字段;name 会映射为 fieldName,phone 会映射为 +telephone。 """ -import sys +from __future__ import annotations + +import argparse import json -import subprocess import os import re +import subprocess +import sys from pathlib import Path -from typing import Union, List, Dict, Any, Optional, Tuple +from typing import Any, Dict, List, Optional, Tuple, Union JsonData = Union[List[Any], Dict[str, Any]] - MAX_FILE_SIZE = 10 * 1024 * 1024 -ALLOWED_FILE_EXTENSIONS = ['.json'] -RESOURCE_ID_PATTERN = re.compile(r'^[A-Za-z0-9_-]{8,128}$') +RESOURCE_ID_PATTERN = re.compile(r"^[A-Za-z0-9_-]{8,128}$") ALLOWED_FIELD_TYPES = { - 'text', 'number', 'singleSelect', 'multipleSelect', 'date', 'currency', - 'user', 'department', 'group', 'progress', 'rating', 'checkbox', - 'attachment', 'url', 'richText', 'telephone', 'email', 'idCard', - 'barcode', 'geolocation', 'address', 'primaryDoc', 'formula', - 'unidirectionalLink', 'bidirectionalLink', 'lookup', 'filterUp', - 'creator', 'lastModifier', 'createdTime', 'lastModifiedTime', -} -FIELD_TYPE_ALIASES = { - 'phone': 'telephone', + "text", "number", "singleSelect", "multipleSelect", "date", "currency", + "user", "department", "group", "progress", "rating", "checkbox", + "attachment", "url", "richText", "telephone", "email", "idCard", + "barcode", "geolocation", "address", "primaryDoc", "formula", + "unidirectionalLink", "bidirectionalLink", "lookup", "filterUp", + "creator", "lastModifier", "createdTime", "lastModifiedTime", } def resolve_safe_path(path: str, allowed_root: Optional[str] = None) -> Path: - if allowed_root is None: - allowed_root = os.environ.get('OPENCLAW_WORKSPACE', os.getcwd()) - - allowed_root = Path(allowed_root).resolve() - target_path = ( - Path(path).resolve() - if Path(path).is_absolute() - else (Path.cwd() / path).resolve() - ) - + root = Path(allowed_root or os.environ.get("OPENCLAW_WORKSPACE", os.getcwd())).resolve() + candidate = Path(path) + target = candidate.resolve() if candidate.is_absolute() else (Path.cwd() / candidate).resolve() try: - target_path.relative_to(allowed_root) - return target_path - except ValueError: - raise ValueError( - f"路径超出允许范围:{path}\n" - f"目标路径:{target_path}\n" - f"允许根目录:{allowed_root}\n" - f"提示:设置 OPENCLAW_WORKSPACE 环境变量或确保文件在工作目录内" - ) + target.relative_to(root) + except ValueError as exc: + raise ValueError(f"路径超出允许范围:{path}(允许根目录:{root})") from exc + return target def validate_resource_id(resource_id: str) -> bool: - return bool(resource_id and RESOURCE_ID_PATTERN.match(resource_id.strip())) + return bool(resource_id and RESOURCE_ID_PATTERN.fullmatch(resource_id.strip())) -def validate_file_extension(filename: str, allowed_extensions: list) -> bool: - return any(filename.lower().endswith(ext) for ext in allowed_extensions) - - -def safe_json_load(file_path: Path, max_size: int = MAX_FILE_SIZE) -> JsonData: - file_size = file_path.stat().st_size - if file_size > max_size: - raise ValueError( - f"文件过大:{file_size:,} 字节 (限制:{max_size:,} 字节)" - ) - with open(file_path, 'r', encoding='utf-8') as f: - return json.load(f) +def safe_json_load(file_path: Path) -> JsonData: + if file_path.stat().st_size > MAX_FILE_SIZE: + raise ValueError(f"文件过大(限制 {MAX_FILE_SIZE:,} 字节)") + with file_path.open("r", encoding="utf-8") as stream: + return json.load(stream) def normalize_field_config(field: Dict[str, Any]) -> Dict[str, Any]: normalized = dict(field) - if 'fieldName' not in normalized and 'name' in normalized: - normalized['fieldName'] = normalized.pop('name') - normalized['type'] = FIELD_TYPE_ALIASES.get( - normalized.get('type', 'text'), normalized.get('type', 'text') - ) + if "fieldName" not in normalized and "name" in normalized: + normalized["fieldName"] = normalized.pop("name") + if normalized.get("type") == "phone": + normalized["type"] = "telephone" return normalized -def validate_field_config(field: Dict[str, Any]) -> Tuple[bool, str]: +def validate_field_config(field: Any) -> Tuple[bool, str]: if not isinstance(field, dict): - return False, '字段配置必须是对象' - - field = normalize_field_config(field) - - if 'fieldName' not in field: - return False, '缺少必需字段:fieldName' - if not isinstance(field['fieldName'], str) or not field['fieldName'].strip(): - return False, 'fieldName 必须是非空字符串' - - field_type = field.get('type', 'text') + return False, "字段配置必须是对象" + normalized = normalize_field_config(field) + name = normalized.get("fieldName") + if not isinstance(name, str) or not name.strip(): + return False, "fieldName 必须是非空字符串" + field_type = normalized.get("type", "text") if field_type not in ALLOWED_FIELD_TYPES: return False, f"不支持的字段类型:{field_type}" - - config = field.get('config') + config = normalized.get("config") if config is not None and not isinstance(config, dict): - return False, 'config 必须是对象' - - if field_type in {'singleSelect', 'multipleSelect'}: - options = (config or {}).get('options') - if not options or not isinstance(options, list): - return False, ( - 'singleSelect / multipleSelect 必须提供 config.options 数组' - ) - - if field_type in {'unidirectionalLink', 'bidirectionalLink'}: - linked_table_id = (config or {}).get('linkedTableId') - if not linked_table_id or not validate_resource_id(linked_table_id): - return False, ( - '关联字段必须提供合法的 config.linkedTableId(目标 Table ID)' - ) - - if field_type == 'lookup': - cfg = config or {} - if not cfg.get('associateField'): - return False, 'lookup 必须提供 config.associateField(本表关联字段的 fieldId)' - if not cfg.get('valuesField'): - return False, 'lookup 必须提供 config.valuesField(关联目标表中要取值的字段 fieldId)' - if not cfg.get('aggregator'): - return False, 'lookup 必须提供 config.aggregator(SUM/AVERAGE/COUNT/MAX/MIN/CONCATENATE)' - - if field_type == 'filterUp': - cfg = config or {} - if not cfg.get('targetSheet'): - return False, 'filterUp 必须提供 config.targetSheet(目标 Table ID)' - filters = cfg.get('filters') - if not filters or not isinstance(filters, list): - return False, 'filterUp 必须提供 config.filters(至少一条筛选规则)' - if not cfg.get('valuesField'): - return False, 'filterUp 必须提供 config.valuesField(目标表中要取值的字段 fieldId)' - if not cfg.get('aggregator'): - return False, 'filterUp 必须提供 config.aggregator(SUM/AVERAGE/COUNT/MAX/MIN/CONCATENATE)' - - return True, '' + return False, "config 必须是对象" + ai_config = normalized.get("aiConfig") + if ai_config is not None and not isinstance(ai_config, dict): + return False, "aiConfig 必须是对象" + if field_type in {"singleSelect", "multipleSelect"}: + options = (config or {}).get("options") + if not isinstance(options, list) or not options: + return False, "singleSelect / multipleSelect 必须提供 config.options 数组" + if field_type in {"unidirectionalLink", "bidirectionalLink"}: + linked_table_id = (config or {}).get("linkedTableId") + if not validate_resource_id(str(linked_table_id or "")): + return False, "关联字段必须提供合法的 config.linkedTableId" + if field_type == "lookup": + required = ("associateField", "valuesField", "aggregator") + missing = [name for name in required if not (config or {}).get(name)] + if missing: + return False, f"lookup 缺少 config.{missing[0]}" + if field_type == "filterUp": + required = ("targetSheet", "filters", "valuesField", "aggregator") + missing = [name for name in required if not (config or {}).get(name)] + if missing: + return False, f"filterUp 缺少 config.{missing[0]}" + if not isinstance((config or {}).get("filters"), list): + return False, "filterUp config.filters 必须是数组" + return True, "" -def build_fields_json(fields: List[Dict[str, Any]]) -> str: - """构建 --fields 参数的 JSON 字符串。""" - payload_fields = [] +def build_fields_payload(fields: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + payload: List[Dict[str, Any]] = [] for field in fields: normalized = normalize_field_config(field) item: Dict[str, Any] = { - 'fieldName': normalized['fieldName'].strip(), - 'type': normalized.get('type', 'text'), + "fieldName": normalized["fieldName"].strip(), + "type": normalized.get("type", "text"), } - if 'config' in normalized and normalized['config'] is not None: - item['config'] = normalized['config'] - payload_fields.append(item) - return json.dumps(payload_fields, ensure_ascii=False) + for key in ("config", "aiConfig"): + if normalized.get(key) is not None: + item[key] = normalized[key] + payload.append(item) + return payload -def run_dws(args: List[str]) -> Optional[Dict[str, Any]]: - if not args: - print('错误:空命令') - return None - - cmd = ['dws'] + args +def run_dws(dws_bin: str, args: List[str], timeout_sec: int = 120) -> Tuple[Optional[Dict[str, Any]], str]: try: result = subprocess.run( - cmd, capture_output=True, text=True, timeout=60 + [dws_bin] + args, + capture_output=True, + text=True, + timeout=timeout_sec, ) - if result.returncode != 0: - print(f"错误:{result.stderr.strip()}") - return None - try: - return json.loads(result.stdout) - except json.JSONDecodeError as e: - print(f"无法解析响应:{result.stdout[:200]}...") - print(f"JSON 解析错误:{e}") - return None except subprocess.TimeoutExpired: - print('错误:命令执行超时(60 秒)') - return None + return None, f"dws 命令超时({timeout_sec} 秒)" except FileNotFoundError: - print('错误:未找到 dws 命令,请确认已安装') - return None + return None, f"未找到 dws 命令:{dws_bin}" + if result.returncode != 0: + return None, (result.stderr or result.stdout).strip() or f"dws 退出码 {result.returncode}" + try: + payload = json.loads(result.stdout) + except json.JSONDecodeError as exc: + return None, f"dws 返回非 JSON:{exc}" + if not isinstance(payload, dict): + return None, "dws 返回的 JSON 不是对象" + if payload.get("status") != "success": + detail = payload.get("summary") or payload.get("error") or payload + return None, f"业务失败:{detail}" + return payload, "" + + +def normalize_result_item(index: int, item: Any) -> Dict[str, Any]: + if not isinstance(item, dict): + return {"index": index, "status": "failed", "error": "逐项结果不是对象"} + field_id = item.get("fieldId") or (item.get("data") or {}).get("fieldId") + succeeded = item.get("success") is True or item.get("status") == "success" + if "success" not in item and "status" not in item: + succeeded = bool(field_id) + result: Dict[str, Any] = { + "index": index, + "status": "success" if succeeded and field_id else "failed", + } + if field_id: + result["fieldId"] = str(field_id) + if result["status"] != "success": + result["error"] = item.get("reason") or item.get("error") or "字段创建未返回 fieldId" + return result def bulk_add_fields( - base_id: str, table_id: str, fields_file: str -) -> bool: + base_id: str, + table_id: str, + fields: List[Dict[str, Any]], + dws_bin: str = "dws", +) -> Dict[str, Any]: + created, error = run_dws( + dws_bin, + [ + "aitable", "field", "create", + "--base-id", base_id, + "--table-id", table_id, + "--fields", json.dumps(build_fields_payload(fields), ensure_ascii=False), + "--format", "json", + ], + ) + if created is None: + return { + "status": "failed", + "complete": False, + "requestedCount": len(fields), + "verifiedCount": 0, + "ledger": [{"status": "failed", "error": error}], + } + + data = created.get("data") if isinstance(created.get("data"), dict) else {} + raw_results = data.get("results") + if not isinstance(raw_results, list) or len(raw_results) != len(fields): + return { + "status": "failed", + "complete": False, + "requestedCount": len(fields), + "verifiedCount": 0, + "ledger": [{"status": "failed", "error": "响应缺少与输入数量一致的 data.results[]"}], + } + ledger = [normalize_result_item(index, item) for index, item in enumerate(raw_results)] + field_ids = [item["fieldId"] for item in ledger if item["status"] == "success"] + verified_ids: List[str] = [] + if field_ids: + queried, query_error = run_dws( + dws_bin, + [ + "aitable", "field", "get", + "--base-id", base_id, + "--table-id", table_id, + "--field-ids", ",".join(field_ids), + "--format", "json", + ], + ) + if queried is None: + for item in ledger: + if item["status"] == "success": + item["status"] = "verify_failed" + item["error"] = query_error + else: + query_data = queried.get("data") if isinstance(queried.get("data"), dict) else {} + raw_fields = query_data.get("fields") or query_data.get("items") or [] + found = { + str(item.get("fieldId")) + for item in raw_fields + if isinstance(item, dict) and item.get("fieldId") + } + verified_ids = [field_id for field_id in field_ids if field_id in found] + for item in ledger: + if item.get("fieldId") in field_ids and item.get("fieldId") not in found: + item["status"] = "verify_failed" + item["error"] = "回读未返回该字段" + complete = len(verified_ids) == len(fields) and all(item["status"] == "success" for item in ledger) + return { + "status": "success" if complete else "partial", + "complete": complete, + "requestedCount": len(fields), + "verifiedCount": len(verified_ids), + "fieldIds": verified_ids, + "ledger": ledger, + } + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("base_id") + parser.add_argument("table_id") + parser.add_argument("fields_file") + parser.add_argument("--dws", default="dws", help="dws 可执行文件路径") + args = parser.parse_args() + if not validate_resource_id(args.base_id): + parser.error("无效的 baseId 格式") + if not validate_resource_id(args.table_id): + parser.error("无效的 tableId 格式") try: - safe_path = resolve_safe_path(fields_file) - except ValueError as e: - print(f"路径验证失败:{e}") - return False - - if not validate_file_extension(fields_file, ALLOWED_FILE_EXTENSIONS): - print(f"错误:只允许 {', '.join(ALLOWED_FILE_EXTENSIONS)} 文件") - return False - if not safe_path.exists(): - print(f"错误:文件不存在:{safe_path}") - return False - - try: - fields = safe_json_load(safe_path) - except ValueError as e: - print(f"错误:{e}") - return False - except json.JSONDecodeError as e: - print(f"错误:JSON 格式无效:{e}") - return False - - if not isinstance(fields, list) or not fields: - print('错误:fields.json 必须是非空 JSON 数组') - return False - if len(fields) > 15: - print('错误:单次最多创建 15 个字段,请拆分后重试') - return False - - for i, field in enumerate(fields): - valid, error = validate_field_config(field) - if not valid: - print(f"错误:字段 #{i+1} 配置无效:{error}") - return False - - fields_json = build_fields_json(fields) - result = run_dws([ - 'aitable', 'field', 'create', - '--base-id', base_id, - '--table-id', table_id, - '--fields', fields_json, - '--format', 'json', - ]) - - if not result: - return False - + path = resolve_safe_path(args.fields_file) + if path.suffix.lower() != ".json" or not path.exists() or not path.is_file(): + raise ValueError("fields_file 必须是工作区内存在的 .json 文件") + fields = safe_json_load(path) + if not isinstance(fields, list) or not fields: + raise ValueError("fields.json 必须是非空 JSON 数组") + if len(fields) > 15: + raise ValueError("单次最多创建 15 个字段,请拆分后重试") + for index, field in enumerate(fields, start=1): + valid, error = validate_field_config(field) + if not valid: + raise ValueError(f"字段 #{index} 配置无效:{error}") + result = bulk_add_fields(args.base_id, args.table_id, fields, args.dws) + except (ValueError, OSError, json.JSONDecodeError) as exc: + print(f"错误:{exc}", file=sys.stderr) + sys.exit(1) print(json.dumps(result, ensure_ascii=False, indent=2)) - return True + sys.exit(0 if result["complete"] else 2) -def main(): - if len(sys.argv) != 4: - print(__doc__) - print('用法示例:') - print(' python bulk_add_fields.py basexxx tablexxx fields.json') - sys.exit(1) - - base_id = sys.argv[1] - table_id = sys.argv[2] - fields_file = sys.argv[3] - - if not validate_resource_id(base_id): - print('错误:无效的 baseId 格式') - sys.exit(1) - if not validate_resource_id(table_id): - print('错误:无效的 tableId 格式') - sys.exit(1) - - success = bulk_add_fields(base_id, table_id, fields_file) - sys.exit(0 if success else 1) - - -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/skills/multi/dingtalk-aitable/scripts/import_records.py b/skills/multi/dingtalk-aitable/scripts/import_records.py index a275806e..a192f63e 100644 --- a/skills/multi/dingtalk-aitable/scripts/import_records.py +++ b/skills/multi/dingtalk-aitable/scripts/import_records.py @@ -1,333 +1,264 @@ #!/usr/bin/env python3 -""" -从 CSV / JSON 批量导入记录到钉钉 AI 表格(新版 schema) +"""批量追加 CSV / JSON 记录到已有钉钉 AI 表格数据表。 用法: - python import_records.py data.csv [batch_size] - python import_records.py data.json [batch_size] + python3 import_records.py data.csv [batch_size] + python3 import_records.py data.json [batch_size] -说明: -- CSV 表头默认视为 fieldId -- JSON 支持两种格式: - 1. [{"cells": {"fldxxx": "value"}}, ...] - 2. [{"fldxxx": "value"}, ...] # 会自动包装成 cells - -⚠️ CSV 自动类型转换风险: - CSV 读入的所有 cell 都是 string,本脚本会尝试自动识别 'true'/'false'/数字 - 并转成对应类型(避免 text 字段塞入纯文本数字)。但当 fieldId 对应的字段是 - text / telephone / idCard / barcode 这类"字符串形数字"字段时,自动转 int / float - 会让 server 拒绝(字段类型不匹配)。这种情况建议改用 JSON 格式(自己显式控制类型), - 或在 CSV 写入前给字段值前缀加引号 / 改为非纯数字。 +CSV 表头必须是 fieldId。CSV 值保持字符串;需要布尔、数组、对象等精确类型时使用 +JSON。JSON 支持 [{"cells": {...}}] 或 [{"fld...": value}] 两种格式。 +脚本逐批检查业务状态、提取 newRecordIds 并回读验证;部分成功会保留 ledger, +但整体以非零状态结束。 """ -import sys +from __future__ import annotations + +import argparse import csv import json -import subprocess import os import re +import subprocess +import sys from pathlib import Path -from typing import Union, List, Dict, Any, Optional, Tuple +from typing import Any, Dict, List, Optional, Tuple, Union JsonData = Union[List[Any], Dict[str, Any]] -RecordDict = Dict[str, str] - MAX_FILE_SIZE = 50 * 1024 * 1024 -ALLOWED_CSV_EXTENSIONS = ['.csv'] -ALLOWED_JSON_EXTENSIONS = ['.json'] -RESOURCE_ID_PATTERN = re.compile(r'^[A-Za-z0-9_-]{8,128}$') +RESOURCE_ID_PATTERN = re.compile(r"^[A-Za-z0-9_-]{8,128}$") MAX_RECORDS_PER_BATCH = 100 DEFAULT_BATCH_SIZE = 50 -def resolve_safe_path( - path: str, allowed_root: Optional[str] = None -) -> Path: - if allowed_root is None: - allowed_root = os.environ.get('OPENCLAW_WORKSPACE', os.getcwd()) - allowed_root = Path(allowed_root).resolve() - target_path = ( - Path(path).resolve() - if Path(path).is_absolute() - else (Path.cwd() / path).resolve() - ) +def resolve_safe_path(path: str, allowed_root: Optional[str] = None) -> Path: + root = Path(allowed_root or os.environ.get("OPENCLAW_WORKSPACE", os.getcwd())).resolve() + candidate = Path(path) + target = candidate.resolve() if candidate.is_absolute() else (Path.cwd() / candidate).resolve() try: - target_path.relative_to(allowed_root) - return target_path - except ValueError: - raise ValueError( - f"路径超出允许范围:{path}\n" - f"目标路径:{target_path}\n" - f"允许根目录:{allowed_root}\n" - f"提示:设置 OPENCLAW_WORKSPACE 环境变量或确保文件在工作目录内" - ) + target.relative_to(root) + except ValueError as exc: + raise ValueError(f"路径超出允许范围:{path}(允许根目录:{root})") from exc + return target def validate_resource_id(resource_id: str) -> bool: - return bool( - resource_id and RESOURCE_ID_PATTERN.match(resource_id.strip()) - ) + return bool(resource_id and RESOURCE_ID_PATTERN.fullmatch(resource_id.strip())) -def validate_file_extension( - filename: str, allowed_extensions: list -) -> bool: - return any(filename.lower().endswith(ext) for ext in allowed_extensions) +def safe_csv_load(file_path: Path) -> List[Dict[str, str]]: + if file_path.stat().st_size > MAX_FILE_SIZE: + raise ValueError(f"文件过大(限制 {MAX_FILE_SIZE:,} 字节)") + with file_path.open("r", encoding="utf-8-sig", newline="") as stream: + reader = csv.DictReader(stream) + if not reader.fieldnames or any(not str(name).strip() for name in reader.fieldnames): + raise ValueError("CSV 必须包含非空 fieldId 表头") + return list(reader) -def safe_csv_load( - file_path: Path, max_size: int = MAX_FILE_SIZE -) -> List[RecordDict]: - file_size = file_path.stat().st_size - if file_size > max_size: - raise ValueError( - f"文件过大:{file_size:,} 字节 (限制:{max_size:,} 字节)" - ) - with open(file_path, 'r', encoding='utf-8', newline='') as f: - return list(csv.DictReader(f)) - - -def safe_json_load( - file_path: Path, max_size: int = MAX_FILE_SIZE -) -> JsonData: - file_size = file_path.stat().st_size - if file_size > max_size: - raise ValueError( - f"文件过大:{file_size:,} 字节 (限制:{max_size:,} 字节)" - ) - with open(file_path, 'r', encoding='utf-8') as f: - return json.load(f) - - -def sanitize_record_value( - value: Any, -) -> Optional[Union[str, int, float, bool, list, dict]]: - if value is None: - return None - if isinstance(value, (bool, int, float, list, dict)): - return value - if not isinstance(value, str): - return value - if not value.strip(): - return None - - value = value.strip() - if value.lower() == 'true': - return True - if value.lower() == 'false': - return False - - try: - if '.' in value: - return float(value) - return int(value) - except ValueError: - return value +def safe_json_load(file_path: Path) -> JsonData: + if file_path.stat().st_size > MAX_FILE_SIZE: + raise ValueError(f"文件过大(限制 {MAX_FILE_SIZE:,} 字节)") + with file_path.open("r", encoding="utf-8") as stream: + return json.load(stream) def normalize_record(record: Dict[str, Any]) -> Dict[str, Any]: - if 'cells' in record and isinstance(record['cells'], dict): - cells = record['cells'] - else: - cells = record - normalized = {} + cells = record.get("cells") if isinstance(record.get("cells"), dict) else record + normalized: Dict[str, Any] = {} for key, value in cells.items(): - sanitized = sanitize_record_value(value) - if sanitized is not None: - normalized[key] = sanitized - return {'cells': normalized} + if not isinstance(key, str) or not key.strip(): + continue + if value is None: + continue + if isinstance(value, str): + value = value.strip() + if not value: + continue + normalized[key.strip()] = value + return {"cells": normalized} -def validate_record(record: Dict[str, Any]) -> Tuple[bool, str]: +def validate_record(record: Any) -> Tuple[bool, str]: if not isinstance(record, dict): - return False, '记录必须是对象' - normalized = normalize_record(record) - cells = normalized.get('cells', {}) - if not cells or not isinstance(cells, dict): - return False, '记录必须包含非空 cells 对象' - return True, '' + return False, "记录必须是对象" + cells = normalize_record(record).get("cells") + if not isinstance(cells, dict) or not cells: + return False, "记录必须包含非空 cells 对象" + return True, "" -def run_dws(args: List[str]) -> Optional[Dict[str, Any]]: - if not args: - print('错误:空命令') - return None - cmd = ['dws'] + args +def run_dws(dws_bin: str, args: List[str], timeout_sec: int = 120) -> Tuple[Optional[Dict[str, Any]], str]: try: result = subprocess.run( - cmd, capture_output=True, text=True, timeout=120 + [dws_bin] + args, + capture_output=True, + text=True, + timeout=timeout_sec, ) - if result.returncode != 0: - print(f"错误:{result.stderr.strip()}") - return None - try: - return json.loads(result.stdout) - except json.JSONDecodeError as e: - print(f"无法解析响应:{result.stdout[:200]}...") - print(f"JSON 解析错误:{e}") - return None except subprocess.TimeoutExpired: - print('错误:命令执行超时(120 秒)') - return None + return None, f"dws 命令超时({timeout_sec} 秒)" except FileNotFoundError: - print('错误:未找到 dws 命令,请确认已安装') - return None - - -def import_from_csv( - base_id: str, table_id: str, csv_file: str, - batch_size: int = DEFAULT_BATCH_SIZE, -) -> bool: + return None, f"未找到 dws 命令:{dws_bin}" + if result.returncode != 0: + return None, (result.stderr or result.stdout).strip() or f"dws 退出码 {result.returncode}" try: - safe_path = resolve_safe_path(csv_file) - except ValueError as e: - print(f"路径验证失败:{e}") - return False + payload = json.loads(result.stdout) + except json.JSONDecodeError as exc: + return None, f"dws 返回非 JSON:{exc}" + if not isinstance(payload, dict): + return None, "dws 返回的 JSON 不是对象" + if payload.get("status") != "success": + detail = payload.get("summary") or payload.get("error") or payload + return None, f"业务失败:{detail}" + return payload, "" - if not validate_file_extension(csv_file, ALLOWED_CSV_EXTENSIONS): - print(f"错误:只允许 {', '.join(ALLOWED_CSV_EXTENSIONS)} 文件") - return False - if not safe_path.exists(): - print(f"错误:文件不存在:{safe_path}") - return False - try: - rows = safe_csv_load(safe_path) - except ValueError as e: - print(f"错误:{e}") - return False - except csv.Error as e: - print(f"错误:CSV 格式无效:{e}") - return False - - if not rows: - print('错误:CSV 文件为空或没有有效数据行') - return False - - records = [ - normalize_record(row) - for row in rows - if normalize_record(row)['cells'] +def extract_query_record_ids(payload: Dict[str, Any]) -> List[str]: + data = payload.get("data") if isinstance(payload.get("data"), dict) else {} + records = data.get("records") or data.get("items") or [] + if not isinstance(records, list): + return [] + return [ + str(item.get("recordId")) + for item in records + if isinstance(item, dict) and item.get("recordId") ] - return import_records(base_id, table_id, records, batch_size) - - -def import_from_json( - base_id: str, table_id: str, json_file: str, - batch_size: int = DEFAULT_BATCH_SIZE, -) -> bool: - try: - safe_path = resolve_safe_path(json_file) - except ValueError as e: - print(f"路径验证失败:{e}") - return False - - if not validate_file_extension(json_file, ALLOWED_JSON_EXTENSIONS): - print(f"错误:只允许 {', '.join(ALLOWED_JSON_EXTENSIONS)} 文件") - return False - if not safe_path.exists(): - print(f"错误:文件不存在:{safe_path}") - return False - - try: - records = safe_json_load(safe_path) - except ValueError as e: - print(f"错误:{e}") - return False - except json.JSONDecodeError as e: - print(f"错误:JSON 格式无效:{e}") - return False - - if not isinstance(records, list) or not records: - print('错误:JSON 文件必须是非空数组') - return False - - for i, record in enumerate(records): - valid, error = validate_record(record) - if not valid: - print(f"错误:记录 #{i+1} 格式无效:{error}") - return False - - return import_records( - base_id, table_id, - [normalize_record(r) for r in records], batch_size, - ) def import_records( - base_id: str, table_id: str, - records: List[Dict[str, Any]], batch_size: int, -) -> bool: - if batch_size <= 0: - print('错误:batch_size 必须大于 0') - return False - if batch_size > MAX_RECORDS_PER_BATCH: - batch_size = MAX_RECORDS_PER_BATCH + base_id: str, + table_id: str, + records: List[Dict[str, Any]], + batch_size: int, + dws_bin: str = "dws", +) -> Dict[str, Any]: + if batch_size <= 0 or batch_size > MAX_RECORDS_PER_BATCH: + raise ValueError(f"batch_size 必须在 1..{MAX_RECORDS_PER_BATCH} 之间") + ledger: List[Dict[str, Any]] = [] + verified_ids: List[str] = [] total_batches = (len(records) + batch_size - 1) // batch_size - success = True - - for i in range(0, len(records), batch_size): - batch = records[i:i + batch_size] - batch_num = (i // batch_size) + 1 - records_json = json.dumps(batch, ensure_ascii=False) - result = run_dws([ - 'aitable', 'record', 'create', - '--base-id', base_id, - '--table-id', table_id, - '--records', records_json, - '--format', 'json', - ]) - if result: - print( - f"[{batch_num}/{total_batches}] " - f"✓ 已提交 {len(batch)} 条记录" - ) - else: - print(f"[{batch_num}/{total_batches}] ✗ 导入失败") - success = False - - return success - - -def main(): - if len(sys.argv) < 4 or len(sys.argv) > 5: - print(__doc__) - print('用法示例:') - print( - ' python import_records.py basexxx tablexxx data.csv 50' + for start in range(0, len(records), batch_size): + batch = records[start : start + batch_size] + batch_number = start // batch_size + 1 + print(f"[{batch_number}/{total_batches}] 创建 {len(batch)} 条记录", file=sys.stderr) + created, error = run_dws( + dws_bin, + [ + "aitable", "record", "create", + "--base-id", base_id, + "--table-id", table_id, + "--records", json.dumps(batch, ensure_ascii=False), + "--format", "json", + ], ) - sys.exit(1) + entry: Dict[str, Any] = { + "batch": batch_number, + "inputCount": len(batch), + "status": "failed", + "recordIds": [], + } + if created is None: + entry["error"] = error + ledger.append(entry) + continue - base_id = sys.argv[1] - table_id = sys.argv[2] - input_file = sys.argv[3] - batch_size = ( - int(sys.argv[4]) if len(sys.argv) == 5 - else DEFAULT_BATCH_SIZE - ) + data = created.get("data") if isinstance(created.get("data"), dict) else {} + record_ids = data.get("newRecordIds") + if not isinstance(record_ids, list) or len(record_ids) != len(batch) or not all(record_ids): + entry["error"] = "创建响应缺少与输入数量一致的 data.newRecordIds[]" + ledger.append(entry) + continue + record_ids = [str(value) for value in record_ids] + entry["recordIds"] = record_ids - if not validate_resource_id(base_id): - print('错误:无效的 baseId 格式') - sys.exit(1) - if not validate_resource_id(table_id): - print('错误:无效的 tableId 格式') - sys.exit(1) - - if input_file.lower().endswith('.csv'): - success = import_from_csv( - base_id, table_id, input_file, batch_size - ) - elif input_file.lower().endswith('.json'): - success = import_from_json( - base_id, table_id, input_file, batch_size + queried, query_error = run_dws( + dws_bin, + [ + "aitable", "record", "query", + "--base-id", base_id, + "--table-id", table_id, + "--record-ids", ",".join(record_ids), + "--format", "json", + ], ) + if queried is None: + entry["status"] = "verify_failed" + entry["error"] = query_error + ledger.append(entry) + continue + found = set(extract_query_record_ids(queried)) + missing = [record_id for record_id in record_ids if record_id not in found] + if missing: + entry["status"] = "verify_failed" + entry["missingRecordIds"] = missing + entry["error"] = "回读未返回全部新记录" + ledger.append(entry) + continue + entry["status"] = "success" + verified_ids.extend(record_ids) + ledger.append(entry) + + complete = all(item["status"] == "success" for item in ledger) + return { + "status": "success" if complete else "partial", + "complete": complete, + "requestedCount": len(records), + "verifiedCount": len(verified_ids), + "recordIds": verified_ids, + "ledger": ledger, + } + + +def load_records(input_file: str) -> List[Dict[str, Any]]: + path = resolve_safe_path(input_file) + if not path.exists() or not path.is_file(): + raise ValueError(f"文件不存在或不可读:{path}") + suffix = path.suffix.lower() + if suffix == ".csv": + raw: Any = safe_csv_load(path) + elif suffix == ".json": + raw = safe_json_load(path) else: - print('错误:仅支持 .csv 或 .json 文件') + raise ValueError("仅支持 .csv 或 .json 文件") + if not isinstance(raw, list) or not raw: + raise ValueError("输入文件必须包含至少一条记录") + normalized: List[Dict[str, Any]] = [] + for index, record in enumerate(raw, start=1): + valid, error = validate_record(record) + if not valid: + raise ValueError(f"记录 #{index} 格式无效:{error}") + normalized.append(normalize_record(record)) + return normalized + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("base_id") + parser.add_argument("table_id") + parser.add_argument("input_file") + parser.add_argument("batch_size", nargs="?", type=int, default=DEFAULT_BATCH_SIZE) + parser.add_argument("--dws", default="dws", help="dws 可执行文件路径") + args = parser.parse_args() + if not validate_resource_id(args.base_id): + parser.error("无效的 baseId 格式") + if not validate_resource_id(args.table_id): + parser.error("无效的 tableId 格式") + try: + records = load_records(args.input_file) + result = import_records( + args.base_id, + args.table_id, + records, + args.batch_size, + args.dws, + ) + except (ValueError, OSError, csv.Error, json.JSONDecodeError) as exc: + print(f"错误:{exc}", file=sys.stderr) sys.exit(1) - - sys.exit(0 if success else 1) + print(json.dumps(result, ensure_ascii=False, indent=2)) + sys.exit(0 if result["complete"] else 2) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/skills/multi/dingtalk-aitable/scripts/upload_attachment.py b/skills/multi/dingtalk-aitable/scripts/upload_attachment.py index 5b816a7e..63abbfd1 100644 --- a/skills/multi/dingtalk-aitable/scripts/upload_attachment.py +++ b/skills/multi/dingtalk-aitable/scripts/upload_attachment.py @@ -18,6 +18,7 @@ --records '[{"cells":{"fldAttachId":[{"fileToken":"ft_xxx"}]}}]' --format json """ +import argparse import sys import json import subprocess @@ -28,6 +29,7 @@ from pathlib import Path from typing import Optional, Dict, Any from urllib.request import Request, urlopen from urllib.error import HTTPError, URLError +from urllib.parse import urlparse RESOURCE_ID_PATTERN = re.compile(r'^[A-Za-z0-9_-]{8,128}$') MAX_FILE_SIZE = 100 * 1024 * 1024 # 100MB @@ -43,16 +45,24 @@ def detect_mime_type(file_path: Path) -> str: return mime_type or 'application/octet-stream' -def run_dws(args: list) -> Optional[Dict[str, Any]]: +def run_dws(args: list, dws_bin: str = 'dws') -> Optional[Dict[str, Any]]: """调用 dws 命令并返回解析后的 JSON 结果。""" - cmd = ['dws'] + args + cmd = [dws_bin] + args try: result = subprocess.run(cmd, capture_output=True, text=True, timeout=60) if result.returncode != 0: print(f"错误:dws 命令失败: {result.stderr.strip()}", file=sys.stderr) return None try: - return json.loads(result.stdout) + payload = json.loads(result.stdout) + if not isinstance(payload, dict): + print('错误:dws 响应 JSON 不是对象', file=sys.stderr) + return None + if payload.get('status') != 'success': + detail = payload.get('summary') or payload.get('error') or payload + print(f"错误:dws 业务失败: {detail}", file=sys.stderr) + return None + return payload except json.JSONDecodeError: print(f"错误:无法解析 dws 响应: {result.stdout[:300]}", file=sys.stderr) return None @@ -66,6 +76,10 @@ def run_dws(args: list) -> Optional[Dict[str, Any]]: def upload_to_oss(upload_url: str, file_path: Path, mime_type: str) -> bool: """通过 HTTP PUT 上传文件到 OSS。""" + parsed = urlparse(upload_url) + if parsed.scheme != 'https' or not parsed.hostname: + print('错误:uploadUrl 必须是有效的 HTTPS URL', file=sys.stderr) + return False file_data = file_path.read_bytes() req = Request(upload_url, data=file_data, method='PUT') req.add_header('Content-Type', mime_type) @@ -84,7 +98,9 @@ def upload_to_oss(upload_url: str, file_path: Path, mime_type: str) -> bool: return False -def upload_attachment(base_id: str, file_path_str: str) -> Optional[Dict[str, Any]]: +def upload_attachment( + base_id: str, file_path_str: str, dws_bin: str = 'dws' +) -> Optional[Dict[str, Any]]: """ 执行完整的附件上传流程: 1. prepare_attachment_upload → uploadUrl + fileToken @@ -121,7 +137,7 @@ def upload_attachment(base_id: str, file_path_str: str) -> Optional[Dict[str, An '--mime-type', mime_type, '--format', 'json', ] - result = run_dws(dws_args) + result = run_dws(dws_args, dws_bin) if not result: return None @@ -157,27 +173,20 @@ def upload_attachment(base_id: str, file_path_str: str) -> Optional[Dict[str, An def main(): - if len(sys.argv) != 3: - print(__doc__) - print('用法:') - print(' python upload_attachment.py ') - print() - print('示例:') - print(' python upload_attachment.py G1DKw2zgV2bEk6PMSBooNxlEVB5r9YAn ./report.pdf') - print() - print('然后在 record create 中使用返回的 fileToken:') - print(' dws aitable record create --base-id --table-id \\') - print(' --records \'[{"cells":{"fldAttachId":[{"fileToken":"ft_xxx"}]}}]\' --format json') - sys.exit(1) + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('base_id') + parser.add_argument('file_path') + parser.add_argument('--dws', default='dws', help='dws 可执行文件路径') + args = parser.parse_args() - base_id = sys.argv[1] - file_path = sys.argv[2] + base_id = args.base_id + file_path = args.file_path if not validate_resource_id(base_id): print('错误:无效的 baseId 格式', file=sys.stderr) - sys.exit(1) + parser.error('无效的 baseId 格式') - result = upload_attachment(base_id, file_path) + result = upload_attachment(base_id, file_path, args.dws) if result is None: sys.exit(1) diff --git a/test/scripts/aitable_skill_scripts_test.py b/test/scripts/aitable_skill_scripts_test.py new file mode 100644 index 00000000..eab3936f --- /dev/null +++ b/test/scripts/aitable_skill_scripts_test.py @@ -0,0 +1,208 @@ +import importlib.util +import json +import os +import subprocess +import sys +import tempfile +import unittest +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] +SCRIPTS = ROOT / "skills" / "multi" / "dingtalk-aitable" / "scripts" + + +def load_module(name: str, filename: str): + spec = importlib.util.spec_from_file_location(name, SCRIPTS / filename) + module = importlib.util.module_from_spec(spec) + assert spec.loader is not None + spec.loader.exec_module(module) + return module + + +IMPORT_RECORDS = load_module("aitable_import_records", "import_records.py") +BULK_FIELDS = load_module("aitable_bulk_fields", "bulk_add_fields.py") +UPLOAD_ATTACHMENT = load_module("aitable_upload_attachment", "upload_attachment.py") +EXPORT_TASK = load_module("aitable_export_task", "aitable_export_via_task.py") +IMPORT_TASK = load_module("aitable_import_task", "aitable_import_via_task.py") + + +class AITableSkillScriptsTest(unittest.TestCase): + def make_fake_dws(self, directory: Path, body: str) -> Path: + script = directory / "fake-dws" + script.write_text("#!/usr/bin/env python3\n" + body, encoding="utf-8") + script.chmod(0o755) + return script + + def run_script(self, script: str, args, cwd: Path): + env = os.environ.copy() + env["OPENCLAW_WORKSPACE"] = str(cwd) + return subprocess.run( + [sys.executable, str(SCRIPTS / script), *map(str, args)], + cwd=cwd, + env=env, + text=True, + capture_output=True, + ) + + def test_csv_values_remain_strings(self): + with tempfile.TemporaryDirectory() as raw: + root = Path(raw) + source = root / "records.csv" + source.write_text("fldPhone01,fldBool01\n00123,true\n", encoding="utf-8") + previous = os.getcwd() + os.chdir(root) + try: + records = IMPORT_RECORDS.load_records(str(source)) + finally: + os.chdir(previous) + self.assertEqual(records[0]["cells"]["fldPhone01"], "00123") + self.assertEqual(records[0]["cells"]["fldBool01"], "true") + + def test_import_records_checks_ids_and_readback(self): + with tempfile.TemporaryDirectory() as raw: + root = Path(raw) + source = root / "records.json" + source.write_text('[{"cells":{"fldText01":"值"}}]', encoding="utf-8") + fake = self.make_fake_dws( + root, + """import json, sys +args = sys.argv[1:] +if args[:3] == ['aitable', 'record', 'create']: + print(json.dumps({'status':'success','data':{'newRecordIds':['rec12345678']}})) +elif args[:3] == ['aitable', 'record', 'query']: + print(json.dumps({'status':'success','data':{'records':[{'recordId':'rec12345678'}]}})) +else: + print(json.dumps({'status':'error','summary':'unexpected command'})) +""", + ) + result = self.run_script( + "import_records.py", + ["base12345678", "table1234567", source, "--dws", fake], + root, + ) + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertTrue(payload["complete"]) + self.assertEqual(payload["recordIds"], ["rec12345678"]) + self.assertEqual(payload["ledger"][0]["status"], "success") + + def test_import_records_treats_exit_zero_business_error_as_failure(self): + with tempfile.TemporaryDirectory() as raw: + root = Path(raw) + source = root / "records.json" + source.write_text('[{"cells":{"fldText01":"值"}}]', encoding="utf-8") + fake = self.make_fake_dws( + root, + "import json; print(json.dumps({'status':'error','summary':'denied'}))\n", + ) + result = self.run_script( + "import_records.py", + ["base12345678", "table1234567", source, "--dws", fake], + root, + ) + self.assertEqual(result.returncode, 2) + payload = json.loads(result.stdout) + self.assertFalse(payload["complete"]) + self.assertIn("业务失败", payload["ledger"][0]["error"]) + + def test_bulk_fields_preserves_ai_config_and_verifies(self): + with tempfile.TemporaryDirectory() as raw: + root = Path(raw) + source = root / "fields.json" + source.write_text( + json.dumps([ + { + "fieldName": "AI 摘要", + "type": "text", + "aiConfig": {"outputType": "text", "prompt": [{"type": "text", "value": "摘要"}]}, + } + ], ensure_ascii=False), + encoding="utf-8", + ) + fake = self.make_fake_dws( + root, + """import json, sys +args = sys.argv[1:] +if args[:3] == ['aitable', 'field', 'create']: + fields = json.loads(args[args.index('--fields') + 1]) + if 'aiConfig' not in fields[0]: + print(json.dumps({'status':'error','summary':'aiConfig lost'})) + else: + print(json.dumps({'status':'success','data':{'results':[{'success':True,'fieldId':'field123456'}]}})) +elif args[:3] == ['aitable', 'field', 'get']: + print(json.dumps({'status':'success','data':{'fields':[{'fieldId':'field123456'}]}})) +else: + print(json.dumps({'status':'error','summary':'unexpected command'})) +""", + ) + result = self.run_script( + "bulk_add_fields.py", + ["base12345678", "table1234567", source, "--dws", fake], + root, + ) + self.assertEqual(result.returncode, 0, result.stderr) + payload = json.loads(result.stdout) + self.assertTrue(payload["complete"]) + self.assertEqual(payload["fieldIds"], ["field123456"]) + + def test_bulk_fields_reports_partial_result(self): + with tempfile.TemporaryDirectory() as raw: + root = Path(raw) + source = root / "fields.json" + source.write_text( + '[{"fieldName":"A","type":"text"},{"fieldName":"B","type":"text"}]', + encoding="utf-8", + ) + fake = self.make_fake_dws( + root, + """import json, sys +args = sys.argv[1:] +if args[:3] == ['aitable', 'field', 'create']: + print(json.dumps({'status':'success','data':{'results':[{'success':True,'fieldId':'field123456'},{'success':False,'reason':'duplicate'}]}})) +elif args[:3] == ['aitable', 'field', 'get']: + print(json.dumps({'status':'success','data':{'fields':[{'fieldId':'field123456'}]}})) +""", + ) + result = self.run_script( + "bulk_add_fields.py", + ["base12345678", "table1234567", source, "--dws", fake], + root, + ) + self.assertEqual(result.returncode, 2) + payload = json.loads(result.stdout) + self.assertFalse(payload["complete"]) + self.assertEqual(payload["verifiedCount"], 1) + self.assertEqual(payload["ledger"][1]["error"], "duplicate") + + def test_upload_helpers_reject_plain_http_urls(self): + with tempfile.TemporaryDirectory() as raw: + file_path = Path(raw) / "file.bin" + file_path.write_bytes(b"x") + self.assertFalse( + UPLOAD_ATTACHMENT.upload_to_oss( + "http://example.com/upload", file_path, "application/octet-stream" + ) + ) + ok, error = IMPORT_TASK.put_file("http://example.com/upload", file_path) + self.assertFalse(ok) + self.assertIn("HTTPS", error) + + def test_export_helpers_reject_http_and_existing_output(self): + with self.assertRaises(ValueError): + EXPORT_TASK.normalize_download_url("http://example.com/file.xlsx") + with tempfile.TemporaryDirectory() as raw: + root = Path(raw) + output = root / "existing.xlsx" + output.write_bytes(b"existing") + previous = os.getcwd() + os.chdir(root) + try: + with self.assertRaises(ValueError): + EXPORT_TASK.resolve_output_path("existing.xlsx", "ignored.xlsx", False) + finally: + os.chdir(previous) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/unit/aitable_skill_scripts_test.go b/test/unit/aitable_skill_scripts_test.go new file mode 100644 index 00000000..5d9ce2d3 --- /dev/null +++ b/test/unit/aitable_skill_scripts_test.go @@ -0,0 +1,30 @@ +package unit_test + +import ( + "os/exec" + "path/filepath" + "runtime" + "testing" +) + +func TestAITableSkillPythonScripts(t *testing.T) { + python, err := exec.LookPath("python3") + if err != nil { + t.Skip("python3 is not installed") + } + + _, filename, _, ok := runtime.Caller(0) + if !ok { + t.Fatal("runtime.Caller(0) failed") + } + root := filepath.Clean(filepath.Join(filepath.Dir(filename), "..", "..")) + cmd := exec.Command( + python, + "test/scripts/aitable_skill_scripts_test.py", + ) + cmd.Dir = root + output, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("AI Table skill Python tests failed: %v\n%s", err, output) + } +}