feat(skills): sync wukong 13-sub-skill multi layout with open-source cleanup
Replace skills/multi with wukong's consolidated structure (long-tail products folded into dingtalk-misc), keeping GitHub-only skills (dingtalk-dev/event/pat/profile/skill). Prune MCP-only product refs and align all documented commands/flags with the open-source Cobra tree: remove markdown/*, drive task get, drive version flags, doc read --scope, --async modes, retired conference/chat-file-upload mentions.
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
---
|
||||
name: dingtalk-agoal
|
||||
description: 钉钉 Agoal 目标管理与经营目标跟进。Use when 用户说目标管理/战略解码/经营合约/计分卡/用户目标/OKR拆解/更新目标/查看经营合约/目标进展/目标负责人/周月报统计/周报提交情况/跟催/迟交/未提交。Distinct from dingtalk-todo(个人任务待办)、dingtalk-report(日报周报内容)、dingtalk-oa(审批流)。命令前缀:dws agoal。
|
||||
cli_version: ">=0.2.14"
|
||||
metadata:
|
||||
category: product
|
||||
stability: experimental
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
---
|
||||
|
||||
# 钉钉目标管理 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> 命令参考:[agoal.md](references/agoal.md)。
|
||||
|
||||
## 意图表
|
||||
|
||||
| 用户说 | 命令 |
|
||||
|--------|------|
|
||||
| "查战略解码 / 战略列表" | `dws agoal strategy list` |
|
||||
| "查战略详情" | `dws agoal strategy detail --profile-id <id>` |
|
||||
| "更新战略解码" | 先 `strategy detail` 获取完整内容,再 `strategy update` 覆盖更新 |
|
||||
| "查经营合约" | `dws agoal contract list` / `contract detail` |
|
||||
| "更新经营合约" | 先 `contract detail` 获取完整内容,再 `contract update` 覆盖更新 |
|
||||
| "查计分卡" | `dws agoal scorecard detail` / `scorecard entity-detail` |
|
||||
| "更新计分卡" | 先查详情,再按 [agoal.md](references/agoal.md) 覆盖更新 |
|
||||
| "查周月报统计/提交情况/跟催" | `dws agoal report list-statistics` / `report submit-detail` |
|
||||
|
||||
## 硬约束
|
||||
|
||||
- `strategy update`、`contract update`、`scorecard update` 都是覆盖式更新,必须先查询详情,在返回数据基础上修改后再提交。
|
||||
- 所有命令带 `--format json`;涉及写操作时回查确认。
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
name: dingtalk-aisearch
|
||||
description: AI 搜问——跨源语义检索/发现(只做找到/定位,不做读写;具体读写各归 doc/report/mail/contact)。Use when 找同事/谁负责/查上下级/查工号手机号、跨文档消息邮件听记的内容检索、"我发过/收到过"行为回溯。模糊找人拿 userId 后精确查走 dingtalk-contact。命令前缀:dws aisearch。
|
||||
cli_version: ">=0.2.14"
|
||||
description: AI搜问:人员语义搜索与跨源定位。Use when 按姓名/工号/部门/职责/上下级或手机号线索找人,跨文档/消息/邮件/听记检索,或回溯“我发过/收到过”。完整手机号反查走 dingtalk-contact;找到 userId 后由 contact 补详情。命令前缀:dws aisearch。
|
||||
metadata:
|
||||
cli_version: ">=0.2.14"
|
||||
category: product
|
||||
stability: experimental
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
@@ -12,13 +11,9 @@ metadata:
|
||||
|
||||
# 钉钉 AI 搜问 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
> **CRITICAL — 执行任何 `dws` 操作前,MUST 先用 Read 工具完整读取 [`dws-shared`](../dws-shared/SKILL.md)。**该轻量文件包含全局执行契约、安全底线及 shared references 的按需加载导航;不要预加载其全部 references。
|
||||
|
||||
> 命令参考:[aisearch.md](references/aisearch.md)。
|
||||
|
||||
@@ -30,7 +25,9 @@ metadata:
|
||||
| "谁负责 XX / XX 负责人是谁" | `dws aisearch person --keyword "<XX>" --dimension duty` |
|
||||
| "张三的上级 / 下级" | `dws aisearch person --keyword "张三" --dimension supervisor`(或 `subordinate`) |
|
||||
| "X 部门有哪些人" | `dws aisearch person --keyword "<部门>" --dimension department` |
|
||||
| "工号 12345 是谁 / 138xxxx 手机号是谁" | `dws aisearch person --keyword "<工号>" --dimension jobNumber` / `dws aisearch person --keyword "<手机号>" --dimension phone` |
|
||||
| "工号 12345 是谁" | `dws aisearch person --keyword "<工号>" --dimension jobNumber` |
|
||||
| "按手机号线索语义搜人" | `dws aisearch person --keyword "<手机号线索>" --dimension phone` |
|
||||
| "完整手机号精确反查" | `dws contact user search-mobile --mobile "<完整手机号>"` |
|
||||
| "最近 OKR 相关邮件 / 项目相关文档" | `dws aisearch enterprise --queries "<主题>" --types mail/document --time-range "<时间>"` |
|
||||
| "我发过/创建过/分享过/收到过什么" | `dws aisearch behavior --queries "<主题>" --behavior-type <动作> --direction <方向>` |
|
||||
|
||||
@@ -40,12 +37,12 @@ metadata:
|
||||
|
||||
### SOP-1 搜人 → 拿 userId(search-person)
|
||||
|
||||
**触发**:找人/谁负责/查上下级/部门成员/工号或手机号反查。
|
||||
**触发**:姓名模糊找人/谁负责/查上下级/部门成员/工号反查/手机号线索语义搜人。
|
||||
|
||||
1. **定维度(必须)**:姓名→`name`、"谁负责 XX"→`duty`、部门成员→`department`、上级/下级→`supervisor`/`subordinate`、工号→`jobNumber`、手机号→`phone`;不确定→`all`。`--keyword` 必须按用户原文**完整保真**,切勿截断、改昵称、扩同音字。
|
||||
1. **定维度(必须)**:姓名→`name`、"谁负责 XX"→`duty`、部门成员→`department`、上级/下级→`supervisor`/`subordinate`、工号→`jobNumber`、手机号语义线索→`phone`;完整手机号精确反查切到 `dingtalk-contact` 的 `user search-mobile`;不确定→`all`。`--keyword` 必须按用户原文**完整保真**,切勿截断、改昵称、扩同音字。
|
||||
2. **执行(必须)**:`dws aisearch person --keyword "<完整值>" --dimension <维度> --format json`。
|
||||
3. **解析(必须)**:从 JSON 取 `userId` / `openDingTalkId`;**多候选必须输出让用户选,禁止默认取第一个、禁止编造**未返回的人员字段。
|
||||
4. **衔接(必须)**:要邮箱/部门/职位/主管等详情 → 切 `dingtalk-contact` 执行 `dws contact user get --ids <userId> --format json`;发消息 → `dingtalk-chat`;发 DING → `dingtalk-ding`。
|
||||
4. **衔接(必须)**:要邮箱/部门/职位/主管等详情 → 切 `dingtalk-contact` 执行 `dws contact user get --ids <userId> --format json`;发消息 → `dingtalk-chat`;发 DING → `dingtalk-misc`(`references/ding.md`)。
|
||||
5. **失败(必须)**:未命中最多换 1 个维度重试一次(如 `name`→`department`/`jobNumber`/`phone`),仍保留完整目标值;仍无果**必须如实告知**。
|
||||
|
||||
**禁止**:用半截姓名扩大搜索、跳过 `--format json`、取首个候选、凭空补全人员信息。
|
||||
@@ -55,7 +52,7 @@ metadata:
|
||||
**触发**:跨文档/邮件/消息按主题找内容。
|
||||
|
||||
1. **执行(必须)**:`dws aisearch enterprise --queries "<主题>" --types <document,mail,...> --time-range "<时间>" --format json`;多主题逗号分隔。
|
||||
2. **衔接(必须)**:按命中来源切下游读写——文档→`dingtalk-doc`、邮件→`dingtalk-mail`、消息→`dingtalk-chat`。**aisearch 只负责"找到",不做读写。**
|
||||
2. **衔接(必须)**:按命中来源切到对应产品 skill 读写。**aisearch 只负责"找到",不做读写。**
|
||||
|
||||
**禁止**:把 aisearch 当作读写入口、跳过下游 skill 直接改数据。
|
||||
|
||||
@@ -80,7 +77,7 @@ metadata:
|
||||
|
||||
- 拿到 userId 后查详情 / 部门 → 切到 `dingtalk-contact`
|
||||
- 拿到 userId 发消息 → 切到 `dingtalk-chat`
|
||||
- 拿到 userId 发 DING → 切到 `dingtalk-ding`
|
||||
## 局部意图与 Recipe
|
||||
- 拿到 userId 发 DING → 切到 `dingtalk-misc`(`references/ding.md`)
|
||||
## 局部意图与短流程
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md);[Lite Recipe](references/lite-recipes.md)。
|
||||
- [局部意图消歧](references/intent-guide.md);[短流程](references/lite-recipes.md)。
|
||||
|
||||
@@ -19,7 +19,7 @@ Example:
|
||||
dws aisearch person --keyword "五道" --dimension supervisor --format json
|
||||
dws aisearch person --keyword "AI搜问" --dimension duty --format json
|
||||
dws aisearch person --keyword "李四" --dimension name,department --format json
|
||||
dws aisearch person --keyword "13800138000" --dimension phone --format json
|
||||
dws aisearch person --keyword "<手机号线索>" --dimension phone --format json
|
||||
dws aisearch person --keyword "W12345" --dimension jobNumber --format json
|
||||
Flags:
|
||||
--keyword string 搜索关键词 (必填,如人名、技能关键词等)
|
||||
@@ -37,7 +37,7 @@ Flags:
|
||||
| `duty` | 职责/技能 | "负责什么"、"职责"、"技能"、"负责人" |
|
||||
| `supervisor` | 上级 | "上级"、"领导"、"主管" |
|
||||
| `subordinate` | 下级 | "下级"、"下属"、"团队成员" |
|
||||
| `phone` | 手机号 | "手机号是多少"、"电话"、"联系方式" |
|
||||
| `phone` | 手机号语义线索 | "电话线索"、"联系方式相关";完整手机号精确反查走 `contact user search-mobile` |
|
||||
| `jobNumber` | 工号 | "工号"、"工号是多少"、"员工编号" |
|
||||
|
||||
### keyword 提取规则
|
||||
@@ -51,7 +51,7 @@ Flags:
|
||||
| "AI搜问的负责人是谁" | AI搜问 | duty |
|
||||
| "产品部有谁" | 产品部 | department |
|
||||
| "李四是哪个部门的" | 李四 | department |
|
||||
| "13800138000是谁" | 13800138000 | phone |
|
||||
| "按手机号线索找人" | 用户提供的手机号线索 | phone |
|
||||
| "工号W12345是谁" | W12345 | jobNumber |
|
||||
|
||||
---
|
||||
@@ -59,12 +59,13 @@ Flags:
|
||||
## 意图判断
|
||||
|
||||
- 用户说"搜人/找人/谁负责/上级是谁/哪个部门的人" → `aisearch person`
|
||||
- 用户提供完整手机号精确反查 → `contact user search-mobile`
|
||||
- 用户说"搜资料/找方案/查文档/搜企业知识/项目相关内容/工作总结/周报总结" → `aisearch enterprise`
|
||||
- 用户说"最近/本周/今天 + XX相关消息/文档/邮件有哪些" → `aisearch enterprise`,时间词进 `--time-range`,类型词进 `--types`
|
||||
- 用户说"我发过/谁发给我/创建过/分享过/收到过/今天我干了什么" → `aisearch behavior`
|
||||
- 用户说"搜同事/查部门/查通讯录" → `contact`(通讯录)
|
||||
- 用户说"搜同事" → `aisearch person`;查部门详情/部门成员/通讯录精确信息 → `contact`
|
||||
|
||||
**关键区分**:`aisearch person`(AI 语义搜人,支持职责/手机号/上级/下级等维度)vs `aisearch enterprise`(按内容找企业内部知识)vs `aisearch behavior`(按动作找发送/创建/分享/编辑/接收记录)vs `contact`(通讯录精确查询:userId/部门成员列表)
|
||||
**关键区分**:`aisearch person`(姓名模糊、工号、职责、手机号线索、上下级等搜索)vs `aisearch enterprise`(按内容找企业内部知识)vs `aisearch behavior`(按动作找发送/创建/分享/编辑/接收记录)vs `contact`(完整手机号反查、已知 userId 详情、部门成员列表)
|
||||
|
||||
### 高优先级抽取规则
|
||||
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
|
||||
| 用户说... | 真实意图 | 应该用 | 不要用 | 理由 |
|
||||
|---|---|---|---|---|
|
||||
| "张三在哪个部门/查一下同事工号" | 通讯录精确查询 | #8 `contact` | #5 汇报 / #4 文档 | 需要 userId、手机号、部门 ID 等精确信息时用 contact |
|
||||
| "找一下张三/搜同事/找人" | AI搜人(首选) | `aisearch person` | `contact user search` | 搜人首选 aisearch,支持姓名/部门/职责/上下级维度;精确查 userId/手机号用 contact |
|
||||
| "张三在哪个部门/张三的工号是多少" | 搜人后查通讯录详情 | `aisearch person` → `contact user get` | 直接 `contact user search` | 姓名或工号先由 aisearch 获取 userId,再由 contact 补部门、工号等详情 |
|
||||
| "找一下张三/搜同事/找人" | 人员语义搜索 | `aisearch person` | `contact user search` | 姓名模糊搜索、工号、部门、职责和上下级走 aisearch;contact 在拿到 userId 后补详情 |
|
||||
| "五道的上级是谁/谁负责XX/XX的下属有谁" | AI语义搜人 | `aisearch person` | `contact` | 涉及上下级、职责、负责人等语义维度搜索,用 aisearch |
|
||||
| "222020这个工号是谁/查工号" | 按工号搜人 | `aisearch person --dimension jobNumber` | `contact` | 工号查人走 aisearch,dimension=jobNumber |
|
||||
| "13800138000是谁/查手机号" | 按手机号搜人 | `aisearch person --dimension phone` | `contact` | 手机号查人走 aisearch,dimension=phone |
|
||||
| "13800138000是谁/完整手机号反查" | 精确手机号反查 | `contact user search-mobile` | `contact user search` | 完整手机号精确匹配使用 search-mobile |
|
||||
| "按手机号线索找人" | 手机号语义搜人 | `aisearch person --dimension phone` | `contact user search` | 非精确手机号匹配走 aisearch 的 phone 维度 |
|
||||
| "搜一下智能化方案/最近 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` | 纯文本翻译,不是文档编辑或语义搜索 |
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
|
||||
- 需要获取 userId 给其他产品使用(发消息/建待办/约日程)
|
||||
- 已有 userId 需查完整详情(`contact user get --ids`)
|
||||
- 完整手机号精确反查(`contact user search-mobile --mobile`)
|
||||
|
||||
1. `aisearch person --keyword "<姓名>" --dimension name` → `userId`;**多命中须列出候选请用户确认**。
|
||||
1. 完整手机号精确反查:`contact user search-mobile --mobile "<手机号>"`;其他搜人:`aisearch person --keyword "<关键词>" --dimension <维度>`。
|
||||
2. **重名消歧**:多人同名时禁止默认选第一个,须追加 `contact user get --ids` 获取部门/职位后请用户确认,详见 [08-directory.md](../../dingtalk-contact/references/08-directory.md)「多命中」。
|
||||
3. 需详情时:`contact user get --ids <userId>`(多人可 `--ids id1,id2,...`)
|
||||
3. 需详情时:`contact user get --ids <userId>`(多人可 `--ids id1,id2,...`)。
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
name: dingtalk-aitable
|
||||
description: 钉钉 AI 表格(多维表)。Use when 用户说 AI表格/多维表/数据表/base/table/建表/查记录/写数据/字段/记录增删改查/筛选/排序/公式/模板搜索/批量导入CSV或JSON/导出/仪表盘/图表/上传附件到表格/按字段类型建表。不做电子表格单元格读写(走 dingtalk-sheet)、文档编辑(走 dingtalk-doc);听记待办入表见配方 minutes-todo-to-aitable。命令前缀:dws aitable。
|
||||
cli_version: ">=0.2.14"
|
||||
description: 钉钉 AI 表格(多维表)。Use when 用户说 AI表格/多维表/数据表/base/table/建表/查记录/写数据/字段/记录增删改查/筛选/排序/公式/模板搜索/批量导入CSV或JSON/导出/仪表盘/图表/上传附件到表格/按字段类型建表。不做电子表格单元格读写(走 dingtalk-misc)、文档编辑(走 dingtalk-doc);听记待办入表先用 dingtalk-minutes 提取,再由本 skill 写入。命令前缀:dws aitable。
|
||||
metadata:
|
||||
cli_version: ">=0.2.14"
|
||||
category: product
|
||||
stability: experimental
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
@@ -12,21 +11,16 @@ metadata:
|
||||
|
||||
# 钉钉 AI 表格 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
> **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)。
|
||||
> 高频模块:[Base](references/aitable/aitable-base-index.md) · [Table](references/aitable/aitable-table-index.md) · [Field](references/aitable/aitable-field-index.md) · [Record](references/aitable/aitable-record-index.md) · [View](references/aitable/aitable-view-index.md) · [Form](references/aitable/aitable-form-index.md) · [Workflow](references/aitable/aitable-workflow-index.md)。
|
||||
|
||||
<!-- VISIBLE_SHORTCUTS_START -->
|
||||
## Shortcuts(无专用脚本/recipe 时优先)
|
||||
|
||||
以下 shortcut 来自独立于 Runtime Schema 的公开 catalog。先按本 skill 的意图表、脚本和 recipe 路由:存在精确覆盖该场景的专用脚本/recipe 时按其执行;否则用户意图命中时,shortcut 优先于手写原子命令。用 `dws shortcut list --service aitable --format json` 读取参数、约束、风险和示例,并以 `dws aitable <shortcut> --help` 核对当前 Cobra flags;不要对 `+` 路径调用 `dws schema`。
|
||||
以下命令来自独立于 Runtime Schema 的公开 catalog。先运行 `dws shortcut list --service aitable --format json` 读取完整契约,再用 `dws aitable <shortcut> --help` 核对 flags;不要对 `+` 路径调用 `dws schema`。
|
||||
|
||||
| Shortcut | 风险 | 适用场景 |
|
||||
|---|---|---|
|
||||
@@ -89,7 +83,7 @@ metadata:
|
||||
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 <baseId> --format json` → 从 `tables[].tableId` 取目标表 ID,连同该表 `fields[]` 的 `fieldId/fieldName/type` 与 `views[]` 的 `viewId` 一并记下。
|
||||
4. **取 tableId(必须)**:`dws aitable table get --base-id <baseId> --format json` → 从 `data.tables[].tableId` 取目标表 ID,并记录 `views[]`。枚举模式不返回 `fields[]`;需要字段目录时必须继续执行 SOP-2 的 `field get`。若只核对某张表,可显式加 `--table-ids <tableId>` 控制返回体。
|
||||
5. **失败(必须)**:`base list` 为空或不命中 → 换 `base search --query` 关键词重试一次;仍无果**必须如实告知**,禁止臆造 baseId/tableId。
|
||||
|
||||
**禁止**:跳过 `table get` 直接用字段名写记录、用模糊名匹配当 baseId、用旧会话里的 ID 不再校验。
|
||||
@@ -113,7 +107,7 @@ metadata:
|
||||
1. **前置(必须)**:SOP-1 取 `baseId`/`tableId` + SOP-2 取 `fieldId`/类型。
|
||||
2. **执行(必须)**:`dws aitable record create --base-id <baseId> --table-id <tableId> --records '[{"cells":{"<fieldId>":<值>}}]' --format json`;单次最多 100 条,超长用 `--records-file ./data.json`。
|
||||
3. **写入格式(必须)**:按 `record create --help` 类型表严格传值(text→字符串、number→数值、singleSelect→"选项名"、date→RFC3339、url→`{"text","link"}`、group→`{"cid"}` 等);`filterUp`/`lookup` 字段只读不可写。
|
||||
4. **解析(必须)**:从返回取真实 `recordId`;名称被系统加后缀或字段重命名时,**后续一律用返回的新 ID**,禁止继续按原名称猜。
|
||||
4. **解析与验证(必须)**:从返回 `data.newRecordIds[]` 取全部新记录 ID;不要读取不存在的标量 `recordId`。立即执行 `dws aitable record query --base-id <baseId> --table-id <tableId> --record-ids <id1,id2,...> --format json` 回读写入值。
|
||||
5. **失败(必须)**:类型/格式错误按返回报错修正后重试,**禁止**降级丢弃字段;不确定格式先 `field get` 复核 config。
|
||||
|
||||
**禁止**:编造 fieldId/recordId、跳过 `field get` 凭中文名写、把 URL 字符串直接塞给 url 字段。
|
||||
@@ -136,7 +130,7 @@ metadata:
|
||||
|
||||
1. **前置(必须)**:SOP-1 拿 `baseId`/`tableId`;SOP-2 拿字段类型;SOP-4 拿目标 `recordId`。
|
||||
2. **执行(必须)**:`dws aitable record update --base-id <baseId> --table-id <tableId> --records '[{"recordId":"recXXX","cells":{"<fieldId>":<新值>}}]' --format json`(每条必含 `recordId`+`cells`,单次≤100;超长用 `--records-file`);只传需改字段,未传保持原值。
|
||||
3. **解析(必须)**:写入格式同 SOP-3;返回核对真实 recordId 与受影响字段。
|
||||
3. **解析与验证(必须)**:写入格式同 SOP-3;从返回 `data.recordIds[]` 取实际更新的记录 ID。更新响应不返回“受影响字段”,必须立即用 `record query --record-ids <id1,id2,...> --format json` 回读目标字段确认。
|
||||
4. **失败(必须)**:recordId 不存在或类型不符 → 回 SOP-4 重新定位,**禁止**编造 ID 强写。
|
||||
|
||||
**禁止**:省略 `recordId`、用字段中文名当 cells key、凭空猜测 recordId 直接 update。
|
||||
@@ -147,7 +141,7 @@ metadata:
|
||||
|
||||
## 高频硬约束
|
||||
|
||||
- 创建 Base、改字段或写记录时,固定按“获取真实 ID → 执行写命令 → 回读验证”顺序完成,禁止跳过任一步。
|
||||
- 创建/改字段/写记录是多轮连续任务时,不能在"让我执行/先获取 ID"后停下;必须实际调用对应 `dws aitable` 命令并验证结果。
|
||||
- 字段重命名使用 `dws aitable field update --base-id <baseId> --table-id <tableId> --field-id <fieldId> --name "<新名称>" --format json`;先 `field get` 找真实 `fieldId`,不要猜字段名能直接更新。
|
||||
- 写记录前必须 `field get` 获取 `fieldId` 与类型;`record create/update` 的 `cells` key 用 `fieldId`,不是字段中文名。长 JSON 使用 `--records-file`。
|
||||
- 表或字段创建返回名称被系统自动加后缀时,后续必须使用返回的真实 `tableId`/`fieldId`,不要继续按原名称猜。
|
||||
@@ -160,7 +154,7 @@ metadata:
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
- 单元格 / 工作表 / 公式 → 切到 `dingtalk-sheet`(命令前缀:`dws sheet`)
|
||||
## 局部意图与 Recipe
|
||||
- 单元格 / 工作表 / 公式 → 切到 `dingtalk-misc`(`references/sheet.md`,命令前缀:`dws sheet`)
|
||||
## 局部意图
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md)。
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
| 1 | **并行查详情**:拿到多个 ID 后,用 `&` 合并到同一条 Shell 命令并行执行 + `wait`,**严禁逐条串行** |
|
||||
| 2 | **翻页**:分页接口须拉全直至无更多 |
|
||||
| 3 | **优先批量 API**:有批量接口则用批量;无则按 #1 并行 |
|
||||
| 4 | **群消息**:必须先 `chat search --query` 得 `openConversationId`,再 `chat message list --group`;多群同条命令并行 |
|
||||
| 4 | **群消息**:必须先 `chat search --query` 得 `openConversationId`,再 `chat message list --group <openConversationId> --time "<yyyy-MM-dd HH:mm:ss>" --direction older`;多群同条命令并行 |
|
||||
| 5 | **列表少轮次**:带条件搜索/列表 → 一次采全详情;**禁止**无新参数时重复同一 `list` / `search` |
|
||||
|
||||
## 多源并行采集(公共模式)
|
||||
@@ -29,7 +29,7 @@
|
||||
|------|------|--------|
|
||||
| `taskUuid` | `minutes list` | `minutes get summary/info/batch --id(s)` |
|
||||
| `userId` | `aisearch person` / `contact user search` / `contact dept list-members` | `contact user get --ids`、`todo --executors`、`calendar --users` |
|
||||
| `deptId` | `contact dept search` | `contact dept list-members --depts`;多子部门时对每个子部门分别 `dept search` 取 id |
|
||||
| `deptId` | `contact dept search` | `contact dept list-members --ids <deptId1,deptId2...>`;多子部门时对每个子部门分别 `dept search` 取 id |
|
||||
| `nodeId` | `drive search` / `wiki node search` | `doc read/update --node`、`drive copy/move/rename/delete --node` |
|
||||
| `nodeId` | `wiki node list` 中的 folder 类型节点 / `wiki node create --type folder` | `wiki node list --folder`、`wiki node create --folder`、`drive upload --folder`、`drive copy/move --folder` |
|
||||
| `eventId` | `calendar event list` | `calendar event get/update --id` |
|
||||
@@ -38,7 +38,7 @@
|
||||
| `todoTaskId` | `todo task list` | `todo task update/done --task-id` |
|
||||
| `reportId` | `report inbox list` / `report outbox list` | `report entry get/stats --report-id` |
|
||||
| `baseId` / `tableId` | `aitable base search` | `aitable record query --base-id --table-id` |
|
||||
| `dentryUuid` | `drive list` / `drive mkdir` | `drive info/download --node`、`drive list/mkdir/upload --folder` |
|
||||
| `dentryUuid` | `drive list` / `drive mkdir` | `drive info/download/copy/move/rename/delete --node`、`drive list/mkdir/upload/copy/move --folder` |
|
||||
| `dentryId` | `drive info` 的数字字段 | 仅用于 `chat message send --dentry-id` |
|
||||
|
||||
**ID 边界硬约束**:`dentryId` 通常是纯数字,只表示聊天文件消息需要的钉盘条目数字 ID;它不是父目录 ID。遇到 `drive --node/--folder`、`doc --node/--folder`、`wiki node --folder` 时,只能使用 `dentryUuid` / `nodeId` / 文档 URL。若当前上下文只有数字型 `dentryId`,必须先重新 `drive list` / `drive search` / `wiki node list` 获取正确 ID,不能把该数字直接代入后续命令。
|
||||
**ID 边界硬约束**:`dentryId` 通常是纯数字,只表示聊天文件消息需要的钉盘条目数字 ID;它不是父目录 ID。遇到 `drive --node/--folder`、`doc --node`、`wiki node --folder` 时,只能使用 `dentryUuid` / `nodeId` / 文档 URL。若当前上下文只有数字型 `dentryId`,必须先重新 `drive list` / `drive search` / `wiki node list` 获取正确 ID,不能把该数字直接代入后续命令。
|
||||
|
||||
@@ -27,7 +27,7 @@ dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--format json
|
||||
|
||||
# 关键词搜索
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> --query "设计" --format json
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> --keyword "设计" --format json
|
||||
|
||||
# 按 ID 查询
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> --record-ids rec001,rec002 --format json
|
||||
@@ -38,7 +38,7 @@ dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> --limit 50 --
|
||||
|
||||
## 添加记录
|
||||
|
||||
**必须先执行 `table get` 获取 fieldId,再写入。cells 的 key 必须是 fieldId(如 fldXXX),不是字段名。**
|
||||
**必须先执行 `field get` 获取 fieldId,再写入。cells 的 key 必须是 fieldId(如 fldXXX),不是字段名。**
|
||||
|
||||
```bash
|
||||
# 单条
|
||||
@@ -59,6 +59,8 @@ dws aitable record create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
{"data": {"newRecordIds": ["rec-new-001", "rec-new-002"]}}
|
||||
```
|
||||
|
||||
从 `data.newRecordIds[]` 提取新记录 ID,并立即执行 `record query --record-ids <id1,id2,...>` 回读写入结果;不要只看命令退出码。
|
||||
|
||||
### --records 格式常见错误
|
||||
|
||||
```bash
|
||||
@@ -85,7 +87,7 @@ dws aitable record update --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--format json
|
||||
```
|
||||
|
||||
只需传入需修改的字段,未传入的保持原值。
|
||||
更新响应中的成功记录 ID 位于 `data.recordIds[]`。只需传入需修改的字段,未传入的保持原值;响应不返回“受影响字段”,必须再执行 `record query --record-ids <id1,id2,...>` 回读确认。
|
||||
|
||||
## 删除记录
|
||||
|
||||
@@ -132,4 +134,4 @@ dws aitable record create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
- 公式字段、引用字段
|
||||
- 自动编号字段
|
||||
|
||||
执行 `table get` 后识别字段类型,跳过只读字段。
|
||||
执行 `field get` 后识别字段类型,跳过只读字段。
|
||||
|
||||
@@ -1,21 +1,488 @@
|
||||
# AI 表格 (aitable) 命令参考
|
||||
# AI表格 (aitable) 命令参考
|
||||
|
||||
> 渐进式入口:先读命令索引,再只加载命中的模块参考。
|
||||
> **渐进式文档**:本文件为路由层(索引 + 意图判断),各命令的详细参数、示例和踩坑说明在 [aitable/](./aitable/) 目录下按需加载。
|
||||
|
||||
## 按需加载
|
||||
## 文档地址 (URI)
|
||||
|
||||
| 任务 | 参考 |
|
||||
|---|---|
|
||||
| URL 与 baseId | [URI](./aitable/aitable-uri.md) · [URL 转 baseId](./aitable/aitable-url-to-baseid.md) |
|
||||
| Base / Table / Field | [Base](./aitable/aitable-base-index.md) · [Table](./aitable/aitable-table-index.md) · [Field](./aitable/aitable-field-index.md) |
|
||||
| Record / View / Form | [Record](./aitable/aitable-record-index.md) · [View](./aitable/aitable-view-index.md) · [Form](./aitable/aitable-form-index.md) |
|
||||
| Workflow / Dashboard / Import | [Workflow](./aitable/aitable-workflow-index.md) · [Dashboard](./aitable/aitable-dashboard-index.md) · [导入导出](./aitable/aitable-export-import-index.md) |
|
||||
| Attachment / Advanced Permission | [附件](./aitable/aitable-attachment-index.md) · [高级权限](./aitable/aitable-advperm-index.md) |
|
||||
| 完整命令速查 | [命令索引](./aitable/aitable-command-index.md) |
|
||||
| 复杂操作与路由 | [复杂操作](./aitable/aitable-complex-ops.md) · [意图判断](./aitable/aitable-intent.md) |
|
||||
| 标准流程与上下文 | [核心工作流](./aitable/aitable-core-workflow.md) · [上下文传递](./aitable/aitable-context.md) |
|
||||
| 注意事项、脚本、产品边界 | [注意事项](./aitable/aitable-notes.md) · [自动化脚本](./aitable/aitable-scripts.md) · [相关产品](./aitable/aitable-related.md) |
|
||||
| 资源 | URI 格式 |
|
||||
|------|----------|
|
||||
| Base 文档 | `https://alidocs.dingtalk.com/i/nodes/{baseId}` |
|
||||
| 指定数据表 | `https://alidocs.dingtalk.com/i/nodes/{baseId}?iframeQuery=sheetId%3D{tableId}` |
|
||||
| 指定数据表+视图 | `https://alidocs.dingtalk.com/i/nodes/{baseId}?iframeQuery=sheetId%3D{tableId}%26viewId%3D{viewId}` |
|
||||
| 模板预览 | `https://docs.dingtalk.com/table/template/{templateId}` |
|
||||
|
||||
## 创建 AI 表格
|
||||
> **操作后请返回文档 URI**:返回链接时必须带上当前操作的数据表 tableId,让用户点击后直接看到目标数据表,而不是落在空白的默认表。
|
||||
> - 已知 tableId + viewId 时(view create 返回、view get 中提取):拼接 `https://alidocs.dingtalk.com/i/nodes/{baseId}?iframeQuery=sheetId%3D{tableId}%26viewId%3D{viewId}`
|
||||
> - 已知 tableId 时(table create 返回、base get 中提取、record 操作所用的 tableId):拼接 `https://alidocs.dingtalk.com/i/nodes/{baseId}?iframeQuery=sheetId%3D{tableId}`
|
||||
> - 仅有 baseId、无明确 tableId 时(如 base list/search):拼接 `https://alidocs.dingtalk.com/i/nodes/{baseId}`
|
||||
>
|
||||
> 补充:如果 URL 不是来自 `aitable` 命令返回,而是用户直接贴的原始 `alidocs` URL,先按 [链接规范](url-patterns.md#alidocs-url-类型探测流程) probe,确认是 `able` 后再按 AI 表格处理。
|
||||
|
||||
创建 Base 先读 [Base 索引](./aitable/aitable-base-index.md);创建数据表再读 [Table 索引](./aitable/aitable-table-index.md)。
|
||||
## 命令索引表
|
||||
|
||||
### base (Base 管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `base list` | 列出最近访问的 Base | — | 仅返回最近访问过的,优先用 `base search` |
|
||||
| `base search` | 按名称搜索 Base | `--query` | 关键词 ≥2 字符 |
|
||||
| `base get` | 获取 Base 信息(含 tables 列表) | `--base-id` | 用户给 URL 时提取末尾 ID |
|
||||
| `base create` | 创建 Base | `--name` | 创建后直接用返回的 baseId;**默认新建的 base 自带一个空白「数据表」(含 3 行空记录)和一个空白仪表盘**,如需干净的空 base,传 `--template-id 1743` |
|
||||
| `base update` | 更新 Base 名称 | `--base-id` `--name` | — |
|
||||
| `base delete` | 删除 Base | `--base-id` | 不可逆 |
|
||||
|
||||
### table (数据表管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `table get` | 获取数据表/视图目录 | `--base-id` | 不传 `--table-ids` 枚举全部表,但不返回字段;字段目录使用 `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` | 不可逆 |
|
||||
|
||||
### field (字段管理) → 详见 [aitable-field.md](./aitable/aitable-field.md)、[field-properties](./aitable/aitable-field-properties.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `field get` | 获取字段完整配置 | `--base-id` `--table-id` | 按需展开少量字段 |
|
||||
| `field create` | 创建字段 | `--base-id` `--table-id` + (`--name --type` 或 `--fields`) | 单字段/批量两种模式严格互斥;单字段配置传 `--config`,批量配置写入 `--fields` 每个元素的 `config` |
|
||||
| `field update` | 更新字段名/配置 | `--base-id` `--table-id` `--field-id` | 不可变更字段类型 |
|
||||
| `field delete` | 删除字段 | `--base-id` `--table-id` `--field-id` | 不可逆 |
|
||||
|
||||
#### 搜索字段选项
|
||||
```
|
||||
Usage:
|
||||
dws aitable field search-options [flags]
|
||||
Example:
|
||||
dws aitable field search-options --base-id <BASE_ID> --table-id <TABLE_ID> --field-id <FIELD_ID>
|
||||
dws aitable field search-options --base-id <BASE_ID> --table-id <TABLE_ID> --field-id <FIELD_ID> --keyword 已完成
|
||||
dws aitable field search-options --base-id <BASE_ID> --table-id <TABLE_ID> --field-id <FIELD_ID> --limit 100
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--field-id string 目标字段 ID,必须是 singleSelect / multipleSelect 类型 (必填)
|
||||
--keyword string 模糊搜索关键词,大小写不敏感、contains 匹配 option name;不传返回全部
|
||||
--limit int 返回的最大 option 数量,默认 3000(全量),最大 3000
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
仅适用于 **singleSelect / multipleSelect** 字段。其他类型(text/number/date/...)调用会返回错误。
|
||||
|
||||
适用场景:
|
||||
- options 较多,只想要含某关键词的子集(避免 `field get` 拉取整个字段配置带回所有 options)。
|
||||
- 写入 record 前预览选项 id ↔ name 的映射,确认要使用的选项确实存在。
|
||||
|
||||
> **写 record 时**:`record create / update` 对 singleSelect/multipleSelect 可直接传 option **name**,不需要用本命令。本命令主要用于 **filter** 写法(filters 优先用 option **id**)或选项较多需要精确定位时。
|
||||
|
||||
### record (记录管理)
|
||||
|
||||
| 命令 | 用途 | 必读 reference | 路由提醒 |
|
||||
|------|------|----------------|----------|
|
||||
| `record query` | 查询/搜索记录 | [aitable-record-query.md](./aitable/aitable-record-query.md) | 先 `field get` 拿 fieldId;`--all` 自动翻页;filters 结构见 reference |
|
||||
| `record get` | 按 ID 取记录(`record query --record-ids` 的窄别名) | [aitable-record-query.md](./aitable/aitable-record-query.md) | 已知 recordId 时首选;必填 `--record-ids`(单次最多 100 条);未暴露 filters/sort/query/cursor/limit |
|
||||
| `record create` | 新增记录 | [aitable-record-create.md](./aitable/aitable-record-create.md) | cells key 必须是 fieldId 不是字段名;单次最多 100 条 |
|
||||
| `record update` | 更新记录(每条独立 cells) | [aitable-record-update.md](./aitable/aitable-record-update.md) | 需先 query 拿 recordId;`cells` key 支持 fieldId 或当前表内唯一字段名,推荐 fieldId;`--records` 是 `[{recordId,cells},...]` 数组 |
|
||||
| `record batch-update` | 批量更新(同一 cells 应用到多条 recordId) | [aitable-record-update.md](./aitable/aitable-record-update.md)、[aitable-cell-value.md](./aitable/aitable-cell-value.md) | 适合"统一标记完成/统一改负责人"等共享 patch 场景;`--cells` 是 JSON object(key=fieldId,value 按字段类型见 cell-value.md),与 record update 的单条 cells 结构完全一致;必填 `--record-ids` `--cells`;单次最多 100 条 |
|
||||
| `record delete` | 删除记录 | [aitable-record-delete.md](./aitable/aitable-record-delete.md) | 不可逆,需先 query 确认 |
|
||||
| `record history-list` | 查询单条记录的变更历史 | [aitable-record-history.md](./aitable/aitable-record-history.md) | 必填 `--record-id`;分页 `--offset --limit`,limit 范围 [1,50] 默认 20 |
|
||||
| `record query-empty` | 查询完全没填用户字段的空行 | [aitable-record-query.md](./aitable/aitable-record-query.md) | 一页扫描 `--limit` [1,100] 默认 100;扫完前需用 `--cursor` 翻页(nextCursor 为空才表扫完) |
|
||||
| `record share-url` | 批量获取记录分享链接 | [aitable-record-share.md](./aitable/aitable-record-share.md) | 必填 `--record-ids`(CSV,单次最多 20 条);可选 `--view-id` 带视图上下文 |
|
||||
| `record upsert` | 批量创建或更新(按 recordId 是否存在自动拆分) | [aitable-record-upsert.md](./aitable/aitable-record-upsert.md) | --records 同 record update 格式;带 recordId 走 update,不带走 create;单次最多 100 |
|
||||
| `record primary-doc-get` | 查询记录的主键文档 nodeId | [aitable-primary-doc.md](./aitable/aitable-primary-doc.md) | 返回的 nodeId 可直接用于 `dws doc read/update --node` |
|
||||
| `record primary-doc-create` | 为记录创建主键文档(幂等) | [aitable-primary-doc.md](./aitable/aitable-primary-doc.md) | fieldId 必须是 primaryDoc 类型;已存在则返回已有 nodeId |
|
||||
|
||||
### view (视图管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `view get` | 获取视图配置(不传子命令) | `--base-id` `--table-id` | 不传 `--view-ids` 返回全部视图 |
|
||||
| `view get <attr>` | 获取视图某个属性 | `--view-id` | 12 个:card/timebar/aggregate/filter/sort/group/visible-fields/field-widths(详见 [aitable-view-config.md](./aitable/aitable-view-config.md))+ lock/frozen-cols/row-height/fill-color-rule(详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)) |
|
||||
| `view list` | 列出全部视图(`view get` 的别名) | `--base-id` `--table-id` | 与 `view get` 完全等价 |
|
||||
| `view create` | 创建视图 | `--base-id` `--table-id` `--view-type` | 类型: Grid/Kanban/Gantt/Calendar/Gallery/FormDesigner;可用 `--visible-field-ids`,或用 `--config` 传 visibleFieldIds/filter/sort/group;**Gantt 创建后必须 `view update timebar` 绑定日期字段** |
|
||||
| `view update` | 整体更新视图 / 多属性合并更新 | `--base-id` `--table-id` `--view-id` | 可传 `--name --desc --config '{...}'`,**`--config` 路径继续保留** |
|
||||
| `view update <attr>` | 按属性局部更新(推荐)| `--view-id` + typed flag / `--json` | 12 个:card/timebar/aggregate/field-widths/visible-fields/filter/sort/group/name + frozen-cols/row-height/fill-color-rule |
|
||||
| `view lock [--off]` | 锁定/解锁视图 | `--base-id` `--table-id` `--view-id` | 默认锁定;`--off` 解锁。详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md) |
|
||||
| `view duplicate` | 复制视图 | `--base-id` `--table-id` `--view-id` | 可选 `--new-name`;保留源视图全部配置。详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md) |
|
||||
| `view delete` | 删除视图 | `--base-id` `--table-id` `--view-id` | 不可删最后一个/锁定视图 |
|
||||
|
||||
> **优先用 `view get <attr>` / `view update <attr>` 子命令**:每个属性独立命令,typed flag 友好,agent 不必拼 JSON。**`view update --config '{...}'` 仍可用**,适合一次性多属性更新或脚本场景。
|
||||
|
||||
> **属性按 attr 分类,决定该读哪份子文档**:
|
||||
> - card / timebar / aggregate / filter / sort / group / visible-fields / field-widths → [aitable-view-config.md](./aitable/aitable-view-config.md)
|
||||
> - lock / frozen-cols / row-height / fill-color-rule / duplicate → [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
> 后一类**不能**塞进 `view update --config '{...}'`,必须用各自专属子命令;如果错传 `flags` / `frozenColCount` / `cellHeight` / `conditionalFormats` 等 key 进 `--config`,CLI 会在 stderr 提示应改用的命令。
|
||||
|
||||
> **`view update --config` 支持的 9 个 key**:
|
||||
> `visibleFieldIds` / `filter` / `sort` / `group` / `fieldWidths`(Grid) / `aggregate`(Grid) / `kanbanCard`(Kanban) / `ganttTimebar`(Gantt) / `galleryCard`(Gallery)。
|
||||
> filter/sort/group 必须传**数组**格式(与 `record query --filters` 的对象格式不同;CLI 会自动容错)。其他 key 会被服务端忽略并打 warning。
|
||||
|
||||
### form (表单管理) → 详见 [aitable-form.md](./aitable/aitable-form.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `form list` | 列出表单视图 | `--base-id` `--table-id` | 详情见 [aitable-form.md](./aitable/aitable-form.md) |
|
||||
| `form get` | 按 viewId 取单个表单详情 | `--base-id` `--table-id` `--view-id` | — |
|
||||
| `form create` | 创建表单视图 | `--base-id` `--table-id` `--name` | — |
|
||||
| `form update` | 更新表单配置 | `--base-id` `--table-id` `--view-id` | title/name/description 至少一项 |
|
||||
| `form delete` | 删除表单 | `--base-id` `--table-id` `--view-id` | 不可逆 |
|
||||
| `form field list/update/hide` | 表单字段管理 | — | 详情见子文档 |
|
||||
| `form questions create/delete` | 题目管理(=field create/delete) | — | 详情见子文档 |
|
||||
| `form share get/update` | 表单分享配置 | — | 详情见子文档 |
|
||||
|
||||
> **创建表单**有两种等价方式:`form create --name "..."`(推荐)或 `view create --view-type FormDesigner --name "..."`。
|
||||
|
||||
### workflow (自动化工作流) → 详见 [aitable-workflow.md](./aitable/aitable-workflow.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `workflow create` | 创建并发布自动化工作流 | `--base-id` `--dsl` | 按子文档 Demo 组装 DSL;必须检查返回的 `data.valid` / `issues`;create 不自动重试 |
|
||||
| `workflow update` | 更新并发布已有自动化工作流 | `--base-id` `--workflow-id` `--dsl` | 先 get 留底;提交完整目标 DSL;必须检查 `data.valid` / `issues` |
|
||||
| `workflow list` | 列出 Base 下所有工作流 | `--base-id` | 支持 `--limit [1,100]` / `--offset >=0`;list 出参字段叫 `flowId` |
|
||||
| `workflow get` | 获取单个工作流详情(含 flowSchema) | `--base-id` `--workflow-id` | `--workflow-id` 接受 list 里的 `flowId`(同值) |
|
||||
| `workflow enable` | 启用工作流 | `--base-id` `--workflow-id` | 返回 `{enabled: true}` 是动作确认;要确认真启用看 list 的 `status` |
|
||||
| `workflow disable` | 禁用工作流(高危) | `--base-id` `--workflow-id` `--yes` | 影响业务自动化,建议二次确认;status 变 STOP |
|
||||
|
||||
> 创建/更新的 `--dsl` 使用钉钉 AI 表格 `workflow-dsl/v1`;完整格式和最小 Demo 见 [aitable-workflow.md](./aitable/aitable-workflow.md)。删除工作流暂未开放。
|
||||
|
||||
### dashboard & chart → 详见 [aitable-dashboard-chart.md](./aitable/aitable-dashboard-chart.md)
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
| `dashboard get/create/update/delete` | 仪表盘管理 |
|
||||
| `dashboard config-example` | 查看仪表盘配置模板 |
|
||||
| `dashboard arrange` | 自动重排仪表盘图表布局(智能填满网格,避免空缺) |
|
||||
| `chart get/create/update/delete` | 图表管理 |
|
||||
| `chart widgets-example` | 查看图表 widgets 配置模板 |
|
||||
|
||||
### export & import → 详见 [aitable-export-import.md](./aitable/aitable-export-import.md)
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
| `export data` | 导出数据(异步两阶段轮询) |
|
||||
| `import upload` | 申请文件导入上传凭证 |
|
||||
| `import data` | 触发导入 |
|
||||
|
||||
### attachment → 详见 [aitable-attachment.md](./aitable/aitable-attachment.md)
|
||||
|
||||
| 命令 | 用途 | 路由提醒 |
|
||||
|------|------|----------|
|
||||
| `attachment upload` | 准备附件上传凭证 | 不要用钉盘 drive 上传! |
|
||||
|
||||
### template (模板搜索)
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `template search` | 搜索模板 | `--query` |
|
||||
|
||||
### advperm (高级权限/自定义角色) → 详见 [aitable-advperm.md](./aitable/aitable-advperm.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `advperm enable` | 开启 Base 高级权限总开关 | `--base-id` | 不开启时角色规则不生效 |
|
||||
| `advperm disable` | 关闭 Base 高级权限总开关(高危) | `--base-id` `--yes` | 关闭后全员回退默认权限 |
|
||||
| `advperm role-list` | 列出 Base 下所有角色 | `--base-id` | 同时返回自定义角色和系统角色;`roleType == "custom"` 是自定义,前缀 `system_` 是系统角色 |
|
||||
| `advperm role-get` | 获取单角色完整配置 | `--base-id` `--role-id` | 含 subRoles 与字段/行级规则 |
|
||||
| `advperm role-create` | 创建自定义角色 | `--base-id` `--name` | 可选 `--sub-roles` 同时指定子角色权限规则 |
|
||||
| `advperm role-update` | 增量更新自定义角色(PATCH) | `--base-id` `--role-id` | 未传字段不变;`--sub-roles` 按 (targetId,targetType) 合并 |
|
||||
| `advperm role-delete` | 删除自定义角色 | `--base-id` `--role-id` `--yes` | 不可逆;系统角色禁删;**调用者必须是该 AI 表格的管理员/Owner**,非管理员会得到 401 AUTH_ERROR |
|
||||
|
||||
> **角色 CRUD 已全支持**:create/get/list/update/delete 都可走 CLI。
|
||||
> 所有写命令(enable/disable/role-create/role-update/role-delete)需要 Base 管理员权限;非管理员只能调 `role-list` / `role-get`(只读)。
|
||||
> "角色 ↔ 成员"绑定当前 CLI 不支持,仍需在 AI 表格 Web 端 → Base 设置 → 高级权限面板手动完成。
|
||||
|
||||
### section (文件夹与节点管理)
|
||||
|
||||
> 用于在 Base 的导航树中组织 table / dashboard / 表单视图 / 文档等节点(类似文件夹)。
|
||||
> 操作前建议先用 `section list-nodes` 拿到 nodeId / sectionId 与父级关系。
|
||||
|
||||
#### 创建文件夹
|
||||
```
|
||||
Usage:
|
||||
dws aitable section create [flags]
|
||||
Example:
|
||||
dws aitable section create --base-id <BASE_ID> --name 我的文件夹
|
||||
dws aitable section create --base-id <BASE_ID> --name 子文件夹 --parent-section-id <SECTION_ID> --index 0
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--name string 文件夹名称 (必填)
|
||||
--parent-section-id string 父文件夹 ID;不传或空字符串表示创建在 Base 根目录下
|
||||
--index int 在父文件夹下的目标位置(0-based);不传则追加到末尾
|
||||
```
|
||||
|
||||
返回 `data.sectionId` 与 `data.name`。
|
||||
|
||||
#### 重命名文件夹
|
||||
```
|
||||
Usage:
|
||||
dws aitable section rename [flags]
|
||||
Example:
|
||||
dws aitable section rename --base-id <BASE_ID> --section-id <SECTION_ID> --new-name 新名称
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--section-id string 目标文件夹 ID (必填)
|
||||
--new-name string 新的文件夹名称 (必填)
|
||||
```
|
||||
|
||||
#### 删除文件夹
|
||||
```
|
||||
Usage:
|
||||
dws aitable section delete [flags]
|
||||
Example:
|
||||
dws aitable section delete --base-id <BASE_ID> --section-id <SECTION_ID>
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--section-id string 目标文件夹 ID (必填)
|
||||
```
|
||||
|
||||
> **注意**:删除不可逆;删除前可先用 `section list-empty` 确认是否为空文件夹。
|
||||
|
||||
#### 调整文件夹顺序
|
||||
```
|
||||
Usage:
|
||||
dws aitable section reorder [flags]
|
||||
Example:
|
||||
dws aitable section reorder --base-id <BASE_ID> --section-id <SECTION_ID> --target-index 0
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--section-id string 目标文件夹 ID (必填)
|
||||
--target-index int 目标位置(0-based)(必填)
|
||||
```
|
||||
|
||||
> 在**当前父文件夹下**调整展示顺序。跨父级移动请用 `section move-node`。
|
||||
|
||||
#### 列出空文件夹
|
||||
```
|
||||
Usage:
|
||||
dws aitable section list-empty [flags]
|
||||
Example:
|
||||
dws aitable section list-empty --base-id <BASE_ID>
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
```
|
||||
|
||||
返回 `data.items: [{sectionId, name, parentSectionId}]` 与 `data.total`,用于清理或诊断导航树(parentSectionId 为空串表示在根目录下)。
|
||||
|
||||
#### 列出全部节点
|
||||
```
|
||||
Usage:
|
||||
dws aitable section list-nodes [flags]
|
||||
Example:
|
||||
dws aitable section list-nodes --base-id <BASE_ID>
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
```
|
||||
|
||||
返回 `data.items: [{nodeId, nodeType, parentSectionId, name?}]` 与 `data.total`,涵盖文件夹 / AI 表格 / 表单视图 / 仪表盘 / 文档 / 查询视图。
|
||||
|
||||
> **与其他命令的关联**:是 `section move-node` / `section reorder` 的前置定位命令——先用它拿到 nodeId 与 parentSectionId。
|
||||
|
||||
#### 移动节点
|
||||
```
|
||||
Usage:
|
||||
dws aitable section move-node [flags]
|
||||
Example:
|
||||
dws aitable section move-node --base-id <BASE_ID> --node-id <NODE_ID> --new-parent-section-id <SECTION_ID>
|
||||
dws aitable section move-node --base-id <BASE_ID> --node-id <NODE_ID> --new-parent-section-id "" --target-index 0
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--node-id string 要移动的节点 ID(文件夹/AI表格/表单视图/仪表盘/文档/查询视图)(必填)
|
||||
--new-parent-section-id string 目标父文件夹 ID;空字符串表示移到 Base 根目录 (必填)
|
||||
--target-index int Base 内节点的全局位置(0-based);不传则不调整
|
||||
```
|
||||
|
||||
> 服务端自动识别节点类型,无需区分文件夹与非文件夹。返回 `data.nodeId / newParentSectionId / nodeType`。
|
||||
> 对文件夹节点带 `--target-index` 时会先 move 再 reorder,中间失败会返回 `MOVE_OK_REORDER_FAILED`,可用 `section reorder` 重试。
|
||||
|
||||
## 复杂操作
|
||||
|
||||
### 仪表盘 / 图表(建议顺序)
|
||||
|
||||
```bash
|
||||
# 1) 先看配置模板(JSONC)
|
||||
dws aitable dashboard config-example --format json
|
||||
dws aitable chart widgets-example --format json
|
||||
|
||||
# 2) 先拿 dashboard,再拿 chart 详情
|
||||
dws aitable dashboard get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --format json
|
||||
dws aitable chart get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --chart-id <CHART_ID> --format json
|
||||
```
|
||||
|
||||
要点:
|
||||
|
||||
- `dashboard get` 返回的 `charts[].chartId` 可直接给 `chart get` 使用。
|
||||
- `dashboard share get` 可能返回 `404`(资源不存在或未开通),需按可重试错误处理,不要误判为参数拼错。
|
||||
- `chart share get` 可正常返回 `enabled/shareUrl`,用于分享状态判断。
|
||||
|
||||
### 导出数据(两阶段轮询)
|
||||
|
||||
`export data` 常见为异步任务:首次调用可能只返回 `taskId`,需要继续轮询。
|
||||
|
||||
```bash
|
||||
# 第一步:创建任务(按 scope 传必要参数)
|
||||
dws aitable export data --base-id <BASE_ID> --scope table --table-id <TABLE_ID> --format excel --timeout-ms 1000
|
||||
|
||||
# 第二步:拿 taskId 继续轮询,直到返回 downloadUrl
|
||||
dws aitable export data --base-id <BASE_ID> --task-id <TASK_ID> --timeout-ms 3000
|
||||
```
|
||||
|
||||
参数约束
|
||||
|
||||
- `scope=all`:只需 `base-id`
|
||||
- `scope=table`:必须 `table-id`
|
||||
- `scope=view`:必须同时 `table-id + view-id`
|
||||
|
||||
## 意图判断
|
||||
|
||||
用户说"表格/多维表/AI表格":
|
||||
- 查看/查找/列表 → `base search`(优先)或 `base list`(仅浏览最近访问)
|
||||
- 详情 → `base get`
|
||||
- 创建 → `base create`
|
||||
- 修改 → `base update`
|
||||
- 删除 → `base delete`
|
||||
|
||||
用户说"数据表/子表/table":
|
||||
- 查看 → `table get`
|
||||
- 创建 → `table create`
|
||||
- 重命名 / 改备注 / 改行命名规则 → `table update`(三选一:`--name` / `--description` / `--record-name-key`)
|
||||
- 用户说"行命名规则/记录别名/卡片显示成 task/project/event 这种" → `table update --record-name-key <枚举键>`,**中文 → 枚举键**对照见 [aitable-record-name-key.md](./aitable/aitable-record-name-key.md)
|
||||
- 删除 → `table delete`
|
||||
|
||||
用户说"字段/列/column":
|
||||
- 查看 → `field get`
|
||||
- 添加 → `field create`(读 [aitable-field.md](./aitable/aitable-field.md))
|
||||
- 修改 → `field update`
|
||||
- 删除 → `field delete`
|
||||
|
||||
用户说"记录/行/数据/row":
|
||||
- 查看/搜索 → `record query`(读 [aitable-record-query.md](./aitable/aitable-record-query.md))
|
||||
- 找空行 / 没填东西的行 → `record query-empty`(读 [aitable-record-query.md](./aitable/aitable-record-query.md))
|
||||
- 已知 recordId 反查字段值 → `record get`(按 ID 取专用,等价 `record query --record-ids`)
|
||||
- 添加/写入 → `record create`(读 [aitable-record-create.md](./aitable/aitable-record-create.md))
|
||||
- 修改/更新(每条独立 cells) → `record update`(读 [aitable-record-update.md](./aitable/aitable-record-update.md))
|
||||
- **批量更新同一字段值**(统一标记/统一改值) → `record batch-update --record-ids ... --cells '{...}'`
|
||||
- 删除 → `record delete`
|
||||
- **查记录的字段变更历史 / 操作审计** → `record history-list`(读 [aitable-record-history.md](./aitable/aitable-record-history.md))
|
||||
- **取记录分享链接 / 把这行发给同事** → `record share-url`(读 [aitable-record-share.md](./aitable/aitable-record-share.md))
|
||||
- **不知道有没有 → 有就改、没有就建** → `record upsert`(读 [aitable-record-upsert.md](./aitable/aitable-record-upsert.md))
|
||||
|
||||
用户说"视图/view":
|
||||
- 列出/查看全部视图 → `view list`(或 `view get` 不传 --view-ids,二者等价)
|
||||
- 看某个视图详情 → `view get --view-ids <ID>`
|
||||
- 创建 → `view create`
|
||||
- 修改(含"调整字段顺序/隐藏字段") → `view update --config '{"visibleFieldIds":[...]}'`
|
||||
- 修改某一项配置(filter/sort/group/card/timebar/aggregate 等)→ `view update <attr>`(读 [aitable-view-config.md](./aitable/aitable-view-config.md))
|
||||
- 锁定 / 冻结列 / 行高 / 数据高亮规则 / 复制视图 → 读 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
- 删除 → `view delete`
|
||||
|
||||
用户说"锁定视图/解锁视图/lock view" → `view lock` / `view lock --off`,详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
|
||||
用户说"冻结列/冻结首列/frozen columns" → `view update frozen-cols --count N`,详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
|
||||
用户说"行高/单元格高度/紧凑模式/cell height" → `view update row-height --cell-height N`(合法档位 32/56/88/128),详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
|
||||
用户说"数据高亮/条件格式/单元格上色/fill color rule" → `view update fill-color-rule --json '[...]'`,详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
|
||||
用户说"复制视图/duplicate view" → `view duplicate --view-id ... [--new-name ...]`,详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
|
||||
用户说"筛选/过滤/filter" → 读 [aitable-filter-sort.md](./aitable/aitable-filter-sort.md)
|
||||
|
||||
用户说"统计/分析/聚合/TOP N/全量" → 读 [aitable-data-analysis-sop.md](./aitable/aitable-data-analysis-sop.md)
|
||||
|
||||
用户说"公式/formula/计算字段/派生指标" → 读 [aitable-formula-guide.md](./aitable/aitable-formula-guide.md)
|
||||
|
||||
用户说"查找引用/lookup/filterUp/跨表" → 读 [aitable-formula-guide.md](./aitable/aitable-formula-guide.md)(§5.4 跨表引用)
|
||||
|
||||
用户说"表单/form/收集表/问卷/催办填写" → 读 [aitable-form.md](./aitable/aitable-form.md)
|
||||
|
||||
用户说"自动化/工作流/流程/触发/automation/workflow" → 读 [aitable-workflow.md](./aitable/aitable-workflow.md)
|
||||
- 新建自动化 → 按子文档的最小 Demo 组装完整 DSL,再 `workflow create --dsl @file`
|
||||
- 修改自动化 → `workflow get` 留底,按最新 DSL 文档生成完整目标 DSL,再 `workflow update --dsl @file`
|
||||
- 看 Base 里有哪些流程 / 哪些在跑 → `workflow list`(看 `recordCount` / `runningCount`)
|
||||
- 看某个流程具体配置(触发条件、动作步骤) → `workflow get`
|
||||
- 启用流程 → `workflow enable`
|
||||
- 临时停掉流程(调试 / 数据迁移)→ `workflow disable --yes`
|
||||
- 删除流程:当前不支持,引导用户到 AI 表格 Web 端 → 数据表 → 自动化 面板手动完成
|
||||
|
||||
用户说"仪表盘/图表/chart" → 读 [aitable-dashboard-chart.md](./aitable/aitable-dashboard-chart.md)
|
||||
|
||||
用户说"仪表盘排版乱了/图表对不齐/重新排布/自动布局/美化仪表盘" → `dashboard arrange`(读 [aitable-dashboard-chart.md](./aitable/aitable-dashboard-chart.md))
|
||||
|
||||
用户说"附件/上传文件" → 读 [aitable-attachment.md](./aitable/aitable-attachment.md)
|
||||
|
||||
用户说"导入/导出/import/export" → 读 [aitable-export-import.md](./aitable/aitable-export-import.md)
|
||||
|
||||
用户说"模板" → `template search`
|
||||
|
||||
用户说"高级权限/角色/权限控制/谁能看/谁能改" → 读 [aitable-advperm.md](./aitable/aitable-advperm.md)
|
||||
- 开/关高级权限 → `advperm enable` / `advperm disable --yes`
|
||||
- 看角色配置 → `advperm role-list` 或 `advperm role-get`
|
||||
- 建角色(可同时指定子角色权限) → `advperm role-create --name ... --sub-roles '[...]'`
|
||||
- 改角色名 / 改子角色权限(PATCH 语义,未传字段不变) → `advperm role-update --role-id ... [--name ...] [--sub-roles '[...]']`
|
||||
- 删角色 → `advperm role-delete --yes`
|
||||
- **角色 ↔ 成员绑定**:当前 CLI 不支持,仍需在 AI 表格 Web 端面板手动完成
|
||||
|
||||
命令报错/操作失败 → 读 [aitable-error-recovery.md](./aitable/aitable-error-recovery.md)
|
||||
|
||||
**关键区分**: base=表格文件, table=数据表, field=列, record=行
|
||||
|
||||
## 核心工作流
|
||||
|
||||
```bash
|
||||
# 1. 搜索/列出 Base — 提取 baseId
|
||||
dws aitable base search --query "项目" --format json
|
||||
|
||||
# 2. 获取 Base 信息 — 提取 tableId
|
||||
dws aitable base get --base-id <BASE_ID> --format json
|
||||
|
||||
# 3. 获取字段目录 — 提取 fieldId
|
||||
dws aitable field get --base-id <BASE_ID> --table-id <TABLE_ID> --format json
|
||||
|
||||
# 4. 查询记录
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> --format json
|
||||
|
||||
# 5. 新增记录 (cells 用 fieldId 作 key)
|
||||
dws aitable record create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"cells":{"fldXXX":"值"}}]' --format json
|
||||
```
|
||||
|
||||
## 上下文传递表
|
||||
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `base list/search` | `baseId` | 所有后续命令的 --base-id,拼接文档 URI |
|
||||
| `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 |
|
||||
| `record query` | `recordId` | record update/delete;按 ID 反查字段值用 `record get` |
|
||||
| `template search` | `templateId` | base create --template-id,拼接模板预览 URI |
|
||||
|
||||
## URL → baseId 提取
|
||||
|
||||
用户提供 `https://alidocs.dingtalk.com/i/nodes/{baseId}` 链接时:
|
||||
1. 提取 `/nodes/` 后的路径段作为 `baseId`
|
||||
2. 去掉尾部的查询参数(`?` 及其后内容)
|
||||
3. 传入 `--base-id` 参数
|
||||
|
||||
> 如果该 URL 来自 `dws aitable` 返回或已在当前链路 probe 过,可直接复用;
|
||||
> 如果是用户直接提供的原始 `alidocs` URL,则先按 [链接规范](url-patterns.md#alidocs-url-类型探测流程) probe,确认 `extension=able` 后再继续。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 所有操作使用 ID(baseId/tableId/fieldId/recordId),不使用名称
|
||||
- records 的 cells key 是 fieldId,不是字段名称
|
||||
- cells 写入/读取格式见 [aitable-cell-value.md](./aitable/aitable-cell-value.md)
|
||||
- 最佳实践见 [aitable-best-practices.md](./aitable/aitable-best-practices.md)
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
| 脚本 | 场景 |
|
||||
|------|------|
|
||||
| [bulk_add_fields.py](../scripts/bulk_add_fields.py) | 批量添加字段 |
|
||||
| [import_records.py](../scripts/import_records.py) | 从 JSON/CSV 批量导入记录 |
|
||||
| [aitable_export_via_task.py](../scripts/aitable_export_via_task.py) | 文件导出(export_data 轮询 + 下载) |
|
||||
| [upload_attachment.py](../scripts/upload_attachment.py) | 上传附件到 AI 表格记录 |
|
||||
|
||||
## 相关产品
|
||||
|
||||
- [doc](../../dingtalk-doc/references/doc.md) — 富文本文档编辑,不是结构化数据表格
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# 高级权限与自定义角色
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `advperm enable/disable` | 高级权限总开关 | [`aitable-advperm.md`](./aitable-advperm.md) |
|
||||
| `advperm role-list/get/create/update/delete` | 自定义角色管理 | [`aitable-advperm.md`](./aitable-advperm.md) |
|
||||
@@ -1,5 +0,0 @@
|
||||
# 附件
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `attachment upload` | 准备附件上传凭证 | [`aitable-attachment.md`](./aitable-attachment.md) |
|
||||
@@ -1,10 +0,0 @@
|
||||
# Base 管理
|
||||
|
||||
| 命令 | 用途 | 必读参数 |
|
||||
|---|---|---|
|
||||
| `base list` | 列出最近访问的 Base | — |
|
||||
| `base search` | 按名称搜索 Base | `--query` |
|
||||
| `base get` | 获取 Base 信息(含 tables 列表) | `--base-id` |
|
||||
| `base create` | 创建 Base | `--name` |
|
||||
| `base update` | 更新 Base 名称 | `--base-id` `--name` |
|
||||
| `base delete` | 删除 Base | `--base-id` |
|
||||
@@ -15,7 +15,7 @@
|
||||
1. **不要拉全量后在 context 里手动统计** — 优先用 `--filters` 在服务端过滤
|
||||
2. **has_more=true 时不能做全局结论** — 数据可能不完整
|
||||
3. **优先用 `--filters` 在服务端过滤** — 不要拉全量后在本地 jq/grep
|
||||
4. **字段名必须来自 `table get` 真实返回** — 不要猜测 fieldId
|
||||
4. **fieldId 必须来自 `field get` 真实返回** — 不要猜测 fieldId
|
||||
5. **减少响应体积** — 用 `--field-ids` 仅返回需要的字段
|
||||
|
||||
## 3. 任务选路
|
||||
@@ -36,7 +36,7 @@
|
||||
| 写操作 | 建议回读命令 | 确认内容 |
|
||||
|--------|-------------|----------|
|
||||
| `table create` | `table get --table-ids <新tableId>` | 表名、字段列表是否符合预期 |
|
||||
| `field create` | `table get --table-ids <tableId>` | 新字段是否出现在字段列表中 |
|
||||
| `field create` | `field get --table-id <tableId>` | 新字段是否出现在字段列表中 |
|
||||
| `record create/update` | `record query --record-ids <新recordId>` | 写入值是否正确 |
|
||||
|
||||
## 5. AI 字段注意事项
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
## 顶层规则
|
||||
|
||||
- cells 的 key **必须是 fieldId**(如 `fldXXX`),不是字段名称
|
||||
- fieldId 必须从 `table get` 返回中获取
|
||||
- fieldId 必须从 `field get` 返回中获取
|
||||
- 不同字段类型的 value 格式不同,混用会报错
|
||||
- 系统只读字段(creator/lastModifier/createdTime/lastModifiedTime/formula)不可写入
|
||||
|
||||
|
||||
@@ -1,275 +0,0 @@
|
||||
# 命令索引表
|
||||
|
||||
## 命令索引表
|
||||
|
||||
### base (Base 管理) → 详见 [aitable-base-index.md](./aitable-base-index.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `base list` | 列出最近访问的 Base | — | 仅返回最近访问过的,优先用 `base search` |
|
||||
| `base search` | 按名称搜索 Base | `--query` | 关键词 ≥2 字符 |
|
||||
| `base get` | 获取 Base 信息(含 tables 列表) | `--base-id` | 用户给 URL 时提取末尾 ID |
|
||||
| `base create` | 创建 Base | `--name` | 创建后直接用返回的 baseId;**默认新建的 base 自带一个空白「数据表」(含 3 行空记录)和一个空白仪表盘**,如需干净的空 base,传 `--template-id 1743` |
|
||||
| `base update` | 更新 Base 名称 | `--base-id` `--name` | — |
|
||||
| `base delete` | 删除 Base | `--base-id` | 不可逆 |
|
||||
|
||||
### table (数据表管理) → 详见 [aitable-table-index.md](./aitable-table-index.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `table get` | 获取表结构(字段+视图目录) | `--base-id` | 不传 `--table-ids` 返回全部表 |
|
||||
| `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` | 不可逆 |
|
||||
|
||||
### field (字段管理) → 详见 [aitable-field-index.md](./aitable-field-index.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `field get` | 获取字段完整配置 | `--base-id` `--table-id` | 按需展开少量字段 |
|
||||
| `field create` | 创建字段 | `--base-id` `--table-id` + (`--name --type` 或 `--fields`) | 支持单字段/批量模式 |
|
||||
| `field update` | 更新字段名/配置 | `--base-id` `--table-id` `--field-id` | 不可变更字段类型 |
|
||||
| `field delete` | 删除字段 | `--base-id` `--table-id` `--field-id` | 不可逆 |
|
||||
|
||||
#### 搜索字段选项
|
||||
```
|
||||
Usage:
|
||||
dws aitable field search-options [flags]
|
||||
Example:
|
||||
dws aitable field search-options --base-id <BASE_ID> --table-id <TABLE_ID> --field-id <FIELD_ID>
|
||||
dws aitable field search-options --base-id <BASE_ID> --table-id <TABLE_ID> --field-id <FIELD_ID> --keyword 已完成
|
||||
dws aitable field search-options --base-id <BASE_ID> --table-id <TABLE_ID> --field-id <FIELD_ID> --limit 100
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--field-id string 目标字段 ID,必须是 singleSelect / multipleSelect 类型 (必填)
|
||||
--keyword string 模糊搜索关键词,大小写不敏感、contains 匹配 option name;不传返回全部
|
||||
--limit int 返回的最大 option 数量,默认 3000(全量),最大 3000
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
仅适用于 **singleSelect / multipleSelect** 字段。其他类型(text/number/date/...)调用会返回错误。
|
||||
|
||||
适用场景:
|
||||
- options 较多,只想要含某关键词的子集(避免 `field get` 拉取整个字段配置带回所有 options)。
|
||||
- 写入 record 前预览选项 id ↔ name 的映射,确认要使用的选项确实存在。
|
||||
|
||||
> **写 record 时**:`record create / update` 对 singleSelect/multipleSelect 可直接传 option **name**,不需要用本命令。本命令主要用于 **filter** 写法(filters 优先用 option **id**)或选项较多需要精确定位时。
|
||||
|
||||
### record (记录管理) → 详见 [aitable-record-index.md](./aitable-record-index.md)
|
||||
|
||||
| 命令 | 用途 | 必读 reference | 路由提醒 |
|
||||
|------|------|----------------|----------|
|
||||
| `record query` | 查询/搜索记录 | [aitable-record-query.md](./aitable-record-query.md) | 先 `table get` 拿 fieldId;`--all` 自动翻页;filters 结构见 reference |
|
||||
| `record get` | 按 ID 取记录(`record query --record-ids` 的窄别名) | [aitable-record-query.md](./aitable-record-query.md) | 已知 recordId 时首选;必填 `--record-ids`(单次最多 100 条);未暴露 filters/sort/query/cursor/limit |
|
||||
| `record create` | 新增记录 | [aitable-record-create.md](./aitable-record-create.md) | cells key 必须是 fieldId 不是字段名;单次最多 100 条 |
|
||||
| `record update` | 更新记录(每条独立 cells) | [aitable-record-update.md](./aitable-record-update.md) | 需先 query 拿 recordId;只传需改字段;`--records` 是 `[{recordId,cells},...]` 数组 |
|
||||
| `record batch-update` | 批量更新(同一 cells 应用到多条 recordId) | [aitable-record-update.md](./aitable-record-update.md)、[aitable-cell-value.md](./aitable-cell-value.md) | 适合"统一标记完成/统一改负责人"等共享 patch 场景;`--cells` 是 JSON object(key=fieldId,value 按字段类型见 cell-value.md),与 record update 的单条 cells 结构完全一致;必填 `--record-ids` `--cells`;单次最多 100 条 |
|
||||
| `record delete` | 删除记录 | [aitable-record-delete.md](./aitable-record-delete.md) | 不可逆,需先 query 确认 |
|
||||
| `record history-list` | 查询单条记录的变更历史 | [aitable-record-history.md](./aitable-record-history.md) | 必填 `--record-id`;分页 `--offset --limit`,limit 范围 [1,50] 默认 20 |
|
||||
| `record query-empty` | 查询完全没填用户字段的空行 | [aitable-record-query.md](./aitable-record-query.md) | 一页扫描 `--limit` [1,100] 默认 100;扫完前需用 `--cursor` 翻页(nextCursor 为空才表扫完) |
|
||||
| `record share-url` | 批量获取记录分享链接 | [aitable-record-share.md](./aitable-record-share.md) | 必填 `--record-ids`(CSV,单次最多 20 条);可选 `--view-id` 带视图上下文 |
|
||||
| `record upsert` | 批量创建或更新(按 recordId 是否存在自动拆分) | [aitable-record-upsert.md](./aitable-record-upsert.md) | --records 同 record update 格式;带 recordId 走 update,不带走 create;单次最多 100 |
|
||||
| `record primary-doc-get` | 查询记录的主键文档 nodeId | [aitable-primary-doc.md](./aitable-primary-doc.md) | 返回的 nodeId 可直接用于 `dws doc read/update --node` |
|
||||
| `record primary-doc-create` | 为记录创建主键文档(幂等) | [aitable-primary-doc.md](./aitable-primary-doc.md) | fieldId 必须是 primaryDoc 类型;已存在则返回已有 nodeId |
|
||||
|
||||
### view (视图管理) → 详见 [aitable-view-index.md](./aitable-view-index.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `view get` | 获取视图配置(不传子命令) | `--base-id` `--table-id` | 不传 `--view-ids` 返回全部视图 |
|
||||
| `view get <attr>` | 获取视图某个属性 | `--view-id` | 12 个:card/timebar/aggregate/filter/sort/group/visible-fields/field-widths(详见 [aitable-view-config.md](./aitable-view-config.md))+ lock/frozen-cols/row-height/fill-color-rule(详见 [aitable-view-extras.md](./aitable-view-extras.md)) |
|
||||
| `view list` | 列出全部视图(`view get` 的别名) | `--base-id` `--table-id` | 与 `view get` 完全等价 |
|
||||
| `view create` | 创建视图 | `--base-id` `--table-id` `--view-type` | 类型: Grid/Kanban/Gantt/Calendar/Gallery/FormDesigner;**Gantt 创建后必须 `view update timebar` 绑定日期字段** |
|
||||
| `view update` | 整体更新视图 / 多属性合并更新 | `--base-id` `--table-id` `--view-id` | 可传 `--name --desc --config '{...}'`,**`--config` 路径继续保留** |
|
||||
| `view update <attr>` | 按属性局部更新(推荐)| `--view-id` + typed flag / `--json` | 12 个:card/timebar/aggregate/field-widths/visible-fields/filter/sort/group/name + frozen-cols/row-height/fill-color-rule |
|
||||
| `view lock [--off]` | 锁定/解锁视图 | `--base-id` `--table-id` `--view-id` | 默认锁定;`--off` 解锁。详见 [aitable-view-extras.md](./aitable-view-extras.md) |
|
||||
| `view duplicate` | 复制视图 | `--base-id` `--table-id` `--view-id` | 可选 `--new-name`;保留源视图全部配置。详见 [aitable-view-extras.md](./aitable-view-extras.md) |
|
||||
| `view delete` | 删除视图 | `--base-id` `--table-id` `--view-id` | 不可删最后一个/锁定视图 |
|
||||
|
||||
> **优先用 `view get <attr>` / `view update <attr>` 子命令**:每个属性独立命令,typed flag 友好,agent 不必拼 JSON。**`view update --config '{...}'` 仍可用**,适合一次性多属性更新或脚本场景。
|
||||
|
||||
> **属性按 attr 分类,决定该读哪份子文档**:
|
||||
> - card / timebar / aggregate / filter / sort / group / visible-fields / field-widths → [aitable-view-config.md](./aitable-view-config.md)
|
||||
> - lock / frozen-cols / row-height / fill-color-rule / duplicate → [aitable-view-extras.md](./aitable-view-extras.md)
|
||||
> 后一类**不能**塞进 `view update --config '{...}'`,必须用各自专属子命令;如果错传 `flags` / `frozenColCount` / `cellHeight` / `conditionalFormats` 等 key 进 `--config`,CLI 会在 stderr 提示应改用的命令。
|
||||
|
||||
> **`view update --config` 支持的 9 个 key**:
|
||||
> `visibleFieldIds` / `filter` / `sort` / `group` / `fieldWidths`(Grid) / `aggregate`(Grid) / `kanbanCard`(Kanban) / `ganttTimebar`(Gantt) / `galleryCard`(Gallery)。
|
||||
> filter/sort/group 必须传**数组**格式(与 `record query --filters` 的对象格式不同;CLI 会自动容错)。其他 key 会被服务端忽略并打 warning。
|
||||
|
||||
### form (表单管理) → 详见 [aitable-form-index.md](./aitable-form-index.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `form list` | 列出表单视图 | `--base-id` `--table-id` | 详情见 [aitable-form.md](./aitable-form.md) |
|
||||
| `form get` | 按 viewId 取单个表单详情 | `--base-id` `--table-id` `--view-id` | — |
|
||||
| `form create` | 创建表单视图 | `--base-id` `--table-id` `--name` | — |
|
||||
| `form update` | 更新表单配置 | `--base-id` `--table-id` `--view-id` | title/name/description 至少一项 |
|
||||
| `form delete` | 删除表单 | `--base-id` `--table-id` `--view-id` | 不可逆 |
|
||||
| `form field list/update/hide` | 表单字段管理 | — | 详情见子文档 |
|
||||
| `form questions create/delete` | 题目管理(=field create/delete) | — | 详情见子文档 |
|
||||
| `form share get/update` | 表单分享配置 | — | 详情见子文档 |
|
||||
|
||||
> **创建表单**有两种等价方式:`form create --name "..."`(推荐)或 `view create --view-type FormDesigner --name "..."`。
|
||||
|
||||
### workflow (自动化工作流) → 详见 [aitable-workflow-index.md](./aitable-workflow-index.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `workflow create` | 创建并发布工作流 | `--base-id` `--dsl` | 非幂等,不自动重试;检查 `data.valid/issues` |
|
||||
| `workflow update` | 全量更新并发布工作流 | `--base-id` `--workflow-id` `--dsl` | 先 get 留底;检查 `data.valid/issues` |
|
||||
| `workflow list` | 列出 Base 下所有工作流 | `--base-id` | 支持 `--limit [1,100]` / `--offset >=0`;list 出参字段叫 `flowId` |
|
||||
| `workflow get` | 获取单个工作流详情(含 flowSchema) | `--base-id` `--workflow-id` | `--workflow-id` 接受 list 里的 `flowId`(同值) |
|
||||
| `workflow enable` | 启用工作流 | `--base-id` `--workflow-id` | 返回 `{enabled: true}` 是动作确认;要确认真启用看 list 的 `status` |
|
||||
| `workflow disable` | 禁用工作流(高危) | `--base-id` `--workflow-id` `--yes` | 影响业务自动化,建议二次确认;status 变 STOP |
|
||||
|
||||
> 当前支持创建、更新、查询和启停;删除、运行历史及手动触发仍未开放。
|
||||
|
||||
### dashboard & chart → 详见 [aitable-dashboard-index.md](./aitable-dashboard-index.md)
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
| `dashboard get/create/update/delete` | 仪表盘管理 |
|
||||
| `dashboard config-example` | 查看仪表盘配置模板 |
|
||||
| `dashboard arrange` | 自动重排仪表盘图表布局(智能填满网格,避免空缺) |
|
||||
| `chart get/create/update/delete` | 图表管理 |
|
||||
| `chart widgets-example` | 查看图表 widgets 配置模板 |
|
||||
|
||||
### export & import → 详见 [aitable-export-import-index.md](./aitable-export-import-index.md)
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
| `export data` | 导出数据(异步两阶段轮询) |
|
||||
| `import upload` | 申请文件导入上传凭证 |
|
||||
| `import data` | 触发导入 |
|
||||
|
||||
### attachment → 详见 [aitable-attachment-index.md](./aitable-attachment-index.md)
|
||||
|
||||
| 命令 | 用途 | 路由提醒 |
|
||||
|------|------|----------|
|
||||
| `attachment upload` | 准备附件上传凭证 | 不要用钉盘 drive 上传! |
|
||||
|
||||
### template (模板搜索)
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `template search` | 搜索模板 | `--query` |
|
||||
|
||||
### advperm (高级权限/自定义角色) → 详见 [aitable-advperm-index.md](./aitable-advperm-index.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `advperm enable` | 开启 Base 高级权限总开关 | `--base-id` | 不开启时角色规则不生效 |
|
||||
| `advperm disable` | 关闭 Base 高级权限总开关(高危) | `--base-id` `--yes` | 关闭后全员回退默认权限 |
|
||||
| `advperm role-list` | 列出 Base 下所有角色 | `--base-id` | 同时返回自定义角色和系统角色;`roleType == "custom"` 是自定义,前缀 `system_` 是系统角色 |
|
||||
| `advperm role-get` | 获取单角色完整配置 | `--base-id` `--role-id` | 含 subRoles 与字段/行级规则 |
|
||||
| `advperm role-create` | 创建自定义角色 | `--base-id` `--name` | 可选 `--sub-roles` 同时指定子角色权限规则 |
|
||||
| `advperm role-update` | 增量更新自定义角色(PATCH) | `--base-id` `--role-id` | 未传字段不变;`--sub-roles` 按 (targetId,targetType) 合并 |
|
||||
| `advperm role-delete` | 删除自定义角色 | `--base-id` `--role-id` `--yes` | 不可逆;系统角色禁删;**调用者必须是该 AI 表格的管理员/Owner**,非管理员会得到 401 AUTH_ERROR |
|
||||
|
||||
> **角色 CRUD 已全支持**:create/get/list/update/delete 都可走 CLI。
|
||||
> 所有写命令(enable/disable/role-create/role-update/role-delete)需要 Base 管理员权限;非管理员只能调 `role-list` / `role-get`(只读)。
|
||||
> "角色 ↔ 成员"绑定当前 CLI 不支持,仍需在 AI 表格 Web 端 → Base 设置 → 高级权限面板手动完成。
|
||||
|
||||
### section (文件夹与节点管理)
|
||||
|
||||
> 用于在 Base 的导航树中组织 table / dashboard / 表单视图 / 文档等节点(类似文件夹)。
|
||||
> 操作前建议先用 `section list-nodes` 拿到 nodeId / sectionId 与父级关系。
|
||||
|
||||
#### 创建文件夹
|
||||
```
|
||||
Usage:
|
||||
dws aitable section create [flags]
|
||||
Example:
|
||||
dws aitable section create --base-id <BASE_ID> --name 我的文件夹
|
||||
dws aitable section create --base-id <BASE_ID> --name 子文件夹 --parent-section-id <SECTION_ID> --index 0
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--name string 文件夹名称 (必填)
|
||||
--parent-section-id string 父文件夹 ID;不传或空字符串表示创建在 Base 根目录下
|
||||
--index int 在父文件夹下的目标位置(0-based);不传则追加到末尾
|
||||
```
|
||||
|
||||
返回 `data.sectionId` 与 `data.name`。
|
||||
|
||||
#### 重命名文件夹
|
||||
```
|
||||
Usage:
|
||||
dws aitable section rename [flags]
|
||||
Example:
|
||||
dws aitable section rename --base-id <BASE_ID> --section-id <SECTION_ID> --new-name 新名称
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--section-id string 目标文件夹 ID (必填)
|
||||
--new-name string 新的文件夹名称 (必填)
|
||||
```
|
||||
|
||||
#### 删除文件夹
|
||||
```
|
||||
Usage:
|
||||
dws aitable section delete [flags]
|
||||
Example:
|
||||
dws aitable section delete --base-id <BASE_ID> --section-id <SECTION_ID>
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--section-id string 目标文件夹 ID (必填)
|
||||
```
|
||||
|
||||
> **注意**:删除不可逆;删除前可先用 `section list-empty` 确认是否为空文件夹。
|
||||
|
||||
#### 调整文件夹顺序
|
||||
```
|
||||
Usage:
|
||||
dws aitable section reorder [flags]
|
||||
Example:
|
||||
dws aitable section reorder --base-id <BASE_ID> --section-id <SECTION_ID> --target-index 0
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--section-id string 目标文件夹 ID (必填)
|
||||
--target-index int 目标位置(0-based)(必填)
|
||||
```
|
||||
|
||||
> 在**当前父文件夹下**调整展示顺序。跨父级移动请用 `section move-node`。
|
||||
|
||||
#### 列出空文件夹
|
||||
```
|
||||
Usage:
|
||||
dws aitable section list-empty [flags]
|
||||
Example:
|
||||
dws aitable section list-empty --base-id <BASE_ID>
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
```
|
||||
|
||||
返回 `data.items: [{sectionId, name, parentSectionId}]` 与 `data.total`,用于清理或诊断导航树(parentSectionId 为空串表示在根目录下)。
|
||||
|
||||
#### 列出全部节点
|
||||
```
|
||||
Usage:
|
||||
dws aitable section list-nodes [flags]
|
||||
Example:
|
||||
dws aitable section list-nodes --base-id <BASE_ID>
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
```
|
||||
|
||||
返回 `data.items: [{nodeId, nodeType, parentSectionId, name?}]` 与 `data.total`,涵盖文件夹 / AI 表格 / 表单视图 / 仪表盘 / 文档 / 查询视图。
|
||||
|
||||
> **与其他命令的关联**:是 `section move-node` / `section reorder` 的前置定位命令——先用它拿到 nodeId 与 parentSectionId。
|
||||
|
||||
#### 移动节点
|
||||
```
|
||||
Usage:
|
||||
dws aitable section move-node [flags]
|
||||
Example:
|
||||
dws aitable section move-node --base-id <BASE_ID> --node-id <NODE_ID> --new-parent-section-id <SECTION_ID>
|
||||
dws aitable section move-node --base-id <BASE_ID> --node-id <NODE_ID> --new-parent-section-id "" --target-index 0
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--node-id string 要移动的节点 ID(文件夹/AI表格/表单视图/仪表盘/文档/查询视图)(必填)
|
||||
--new-parent-section-id string 目标父文件夹 ID;空字符串表示移到 Base 根目录 (必填)
|
||||
--target-index int Base 内节点的全局位置(0-based);不传则不调整
|
||||
```
|
||||
|
||||
> 服务端自动识别节点类型,无需区分文件夹与非文件夹。返回 `data.nodeId / newParentSectionId / nodeType`。
|
||||
> 对文件夹节点带 `--target-index` 时会先 move 再 reorder,中间失败会返回 `MOVE_OK_REORDER_FAILED`,可用 `section reorder` 重试。
|
||||
@@ -1,40 +0,0 @@
|
||||
# 复杂操作
|
||||
|
||||
## 复杂操作
|
||||
|
||||
### 仪表盘 / 图表(建议顺序)
|
||||
|
||||
```bash
|
||||
# 1) 先看配置模板(JSONC)
|
||||
dws aitable dashboard config-example --format json
|
||||
dws aitable chart widgets-example --format json
|
||||
|
||||
# 2) 先拿 dashboard,再拿 chart 详情
|
||||
dws aitable dashboard get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --format json
|
||||
dws aitable chart get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --chart-id <CHART_ID> --format json
|
||||
```
|
||||
|
||||
要点:
|
||||
|
||||
- `dashboard get` 返回的 `charts[].chartId` 可直接给 `chart get` 使用。
|
||||
- `dashboard share get` 可能返回 `404`(资源不存在或未开通),需按可重试错误处理,不要误判为参数拼错。
|
||||
- `chart share get` 可正常返回 `enabled/shareUrl`,用于分享状态判断。
|
||||
|
||||
### 导出数据(两阶段轮询)
|
||||
|
||||
`export data` 常见为异步任务:首次调用可能只返回 `taskId`,需要继续轮询。
|
||||
|
||||
```bash
|
||||
# 第一步:创建任务(业务格式与输出格式分开)
|
||||
dws aitable export data --base-id <BASE_ID> --scope table --table-id <TABLE_ID> --export-format excel --timeout-ms 1000 --format json
|
||||
|
||||
# 第二步:拿 taskId 继续轮询,直到返回 downloadUrl
|
||||
dws aitable export data --base-id <BASE_ID> --task-id <TASK_ID> --timeout-ms 3000 --format json
|
||||
```
|
||||
|
||||
参数约束
|
||||
|
||||
- 创建任务统一需要 `base-id + scope + export-format`
|
||||
- `scope=all`:无额外 ID
|
||||
- `scope=table`:必须 `table-id`
|
||||
- `scope=view`:必须同时 `table-id + view-id`
|
||||
@@ -1,13 +0,0 @@
|
||||
# 上下文传递表
|
||||
|
||||
## 上下文传递表
|
||||
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `base list/search` | `baseId` | 所有后续命令的 --base-id,拼接文档 URI |
|
||||
| `base create` | `baseId` | 后续命令 + 文档 URI |
|
||||
| `base get` | `tables[].tableId` | --table-id,拼接指定数据表 URI |
|
||||
| `table create` | `tableId` | 后续命令 + 拼接指定数据表 URI |
|
||||
| `table get` | `fields[].fieldId` | record 操作的 cells key, field get/update/delete |
|
||||
| `record query` | `recordId` | record update/delete;按 ID 反查字段值用 `record get` |
|
||||
| `template search` | `templateId` | base create --template-id,拼接模板预览 URI |
|
||||
@@ -1,21 +0,0 @@
|
||||
# 核心工作流
|
||||
|
||||
## 核心工作流
|
||||
|
||||
```bash
|
||||
# 1. 搜索/列出 Base — 提取 baseId
|
||||
dws aitable base search --query "项目" --format json
|
||||
|
||||
# 2. 获取 Base 信息 — 提取 tableId
|
||||
dws aitable base get --base-id <BASE_ID> --format json
|
||||
|
||||
# 3. 获取表结构 — 提取 fieldId
|
||||
dws aitable table get --base-id <BASE_ID> --table-ids <TABLE_ID> --format json
|
||||
|
||||
# 4. 查询记录
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> --format json
|
||||
|
||||
# 5. 新增记录 (cells 用 fieldId 作 key)
|
||||
dws aitable record create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"cells":{"fldXXX":"值"}}]' --format json
|
||||
```
|
||||
@@ -1,6 +0,0 @@
|
||||
# 仪表盘与图表
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `dashboard get/create/update/delete/arrange/config-example` | 仪表盘管理 | [`aitable-dashboard-chart.md`](./aitable-dashboard-chart.md) |
|
||||
| `chart get/create/update/delete/widgets-example` | 图表管理 | [`aitable-dashboard-chart.md`](./aitable-dashboard-chart.md) |
|
||||
@@ -32,7 +32,7 @@
|
||||
| 错误现象 / summary | 原因 | 恢复动作 |
|
||||
|-------------------|------|---------|
|
||||
| `Failed to create field` | config 格式错误或必填项缺失 | 检查 [field-properties](./aitable-field-properties.md) 中该类型的必填 config |
|
||||
| `field not found` | field-id 不存在 | 用 `table get` 获取最新字段列表 |
|
||||
| `field not found` | field-id 不存在 | 用 `field get` 获取最新字段列表 |
|
||||
| formula 创建失败 | 公式语法错误或引用字段名不匹配 | 先 `field get` 确认字段精确名称,再检查公式语法(见 [formula-guide](./aitable-formula-guide.md)) |
|
||||
| 删除主字段失败 | 主字段(第一列)不可删除 | 改为更新字段名或类型,不能删除 |
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
| 错误现象 / summary | 原因 | 恢复动作 |
|
||||
|-------------------|------|---------|
|
||||
| filters 无效被忽略 | 根节点不是 and/or,或 operands 格式错误 | 确保 filters 根节点是 `{"operator":"and"/"or", "operands":[...]}` 结构 |
|
||||
| sort 无效 | fieldId 不存在 | 先 `table get` 确认字段 ID |
|
||||
| sort 无效 | fieldId 不存在 | 先 `field get` 确认字段 ID |
|
||||
| 筛选结果为空 | 条件过严或字段值不匹配 | 放宽条件验证;注意 singleSelect 筛选值用 option name 或 id |
|
||||
|
||||
### 2.6 导入导出错误
|
||||
@@ -120,7 +120,7 @@ dws aitable record create \
|
||||
|
||||
## 5. 错误预防最佳实践
|
||||
|
||||
1. **写记录前先读字段结构** — `field get` 或 `table get` 确认字段类型和 ID
|
||||
1. **写记录前先读字段结构** — `field get` 确认字段类型和 ID
|
||||
2. **写字段前先读 field-properties** — 确认 config 的必填项和格式
|
||||
3. **formula 字段先确认引用字段名** — `[字段名]` 必须精确匹配
|
||||
4. **options 更新传完整列表** — 更新 singleSelect/multipleSelect 的 options 是全量覆盖
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# 导入导出
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `export data` | 导出数据 | [`aitable-export-import.md`](./aitable-export-import.md) |
|
||||
| `import upload/data` | 触发导入 | [`aitable-export-import.md`](./aitable-export-import.md) |
|
||||
@@ -4,23 +4,21 @@
|
||||
|
||||
`export data` 为异步任务:首次调用可能只返回 `taskId`,需要继续轮询。
|
||||
|
||||
> ⚠️ **两种 format 严格分工**:业务导出格式只用 `--export-format`(excel/attachment 等);全局 `--format` 只控制 CLI 输出格式,推荐保持 `--format json`。旧写法 `--format excel` 仅用于兼容历史脚本,新调用不要使用。
|
||||
> ⚠️ **`--format` 冲突警告**:`export data` 的 `--format` 是**导出格式**(excel/attachment 等),不是全局输出格式。**此命令禁止追加全局 `--format json`**,否则会覆盖导出格式导致 `INVALID_EXPORT_FORMAT` 错误。输出默认就是 JSON,无需额外指定。
|
||||
|
||||
```bash
|
||||
# 第一步:创建任务;--export-format 是业务导出格式,--format json 是结构化输出格式
|
||||
dws aitable export data --base-id <BASE_ID> --scope table --table-id <TABLE_ID> --export-format excel --timeout-ms 1000 --format json
|
||||
# 第一步:创建任务(按 scope 传必要参数)——注意:不要加 --format json!
|
||||
dws aitable export data --base-id <BASE_ID> --scope table --table-id <TABLE_ID> --format excel --timeout-ms 1000
|
||||
|
||||
# 第二步:拿 taskId 继续轮询,直到返回 downloadUrl
|
||||
dws aitable export data --base-id <BASE_ID> --task-id <TASK_ID> --timeout-ms 3000 --format json
|
||||
dws aitable export data --base-id <BASE_ID> --task-id <TASK_ID> --timeout-ms 3000
|
||||
```
|
||||
|
||||
### 参数约束
|
||||
|
||||
创建导出任务时统一必传 `--base-id`、`--scope` 和 `--export-format`;下表是不同 scope 的额外必传参数。使用 `--task-id` 轮询时不再传 scope/导出格式。
|
||||
|
||||
| scope | 额外必传参数 |
|
||||
| scope | 必传参数 |
|
||||
|-------|----------|
|
||||
| `all` | 无 |
|
||||
| `all` | 只需 `--base-id` |
|
||||
| `table` | 必须 `--table-id` |
|
||||
| `view` | 必须 `--table-id` + `--view-id` |
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# 字段管理
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `field get` | 获取字段完整配置 | [`aitable-field.md`](./aitable-field.md) |
|
||||
| `field create` | 创建字段 | [`aitable-field.md`](./aitable-field.md) |
|
||||
| `field update` | 更新字段名/配置 | [`aitable-field.md`](./aitable-field.md) |
|
||||
| `field delete` | 删除字段 | [`aitable-field.md`](./aitable-field.md) |
|
||||
| `field search-options` | 搜索字段选项 | [`aitable-field-properties.md`](./aitable-field-properties.md) |
|
||||
@@ -14,7 +14,7 @@ Flags:
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
返回字段的完整配置(含 options 等)。在 table get 拿到字段目录后,按需展开少量字段的完整配置。
|
||||
返回字段的完整配置(含 options 等)。不要假设未指定 `--table-ids` 的 `table get` 枚举结果含字段;字段目录和配置以 `field get` 返回为准。
|
||||
|
||||
## field create — 创建字段
|
||||
|
||||
@@ -31,13 +31,33 @@ Example:
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--name string 要创建的单字段名称(与 --type 配合使用,替代 --fields)
|
||||
--type string 要创建的单字段类型(参考 table create 字段类型)
|
||||
--config string 单字段配置,如 options(可选)
|
||||
--ai-config string 单字段 AI 配置 JSON(可选,用于创建 AI 字段)
|
||||
--fields string 批量新增字段 JSON 数组,单次最多 15 个 (与 --name/--type 二选一)
|
||||
--type string 要创建的单字段类型(需要配合 --name,参考 table create 的内置类型)
|
||||
--config string 单字段配置 JSON(需要配合 --name/--type,结构参考 table create)
|
||||
--ai-config string 单字段 AI 配置 JSON(需要配合 --name/--type)
|
||||
--fields string 批量新增字段 JSON 数组,单次最多 15 个;每个字段的配置写在其 config/aiConfig 内
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
`field create` 有且只有两种输入模式:
|
||||
|
||||
- 单字段模式:必须同时传 `--name` 和 `--type`;`--config`、`--ai-config` 只作为该字段的附加配置。
|
||||
- 批量模式:只传 `--fields`;字段配置写在数组内各对象的 `config` / `aiConfig` 中。
|
||||
|
||||
两种模式严格互斥。`--fields` 不能与 `--name`、`--type`、`--config` 或 `--ai-config` 混用;单独传 `--config` 也会报错,不会被静默忽略。
|
||||
|
||||
例如创建单选字段时,单字段模式的 `--config` 是一个配置对象;批量模式则把同一对象放入对应字段元素的 `config`:
|
||||
|
||||
```bash
|
||||
# 单字段模式
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--name "部门" --type singleSelect \
|
||||
--config '{"options":[{"name":"技术部"},{"name":"产品部"}]}'
|
||||
|
||||
# 批量模式
|
||||
dws aitable field create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--fields '[{"fieldName":"部门","type":"singleSelect","config":{"options":[{"name":"技术部"},{"name":"产品部"}]}}]'
|
||||
```
|
||||
|
||||
允许部分成功,返回结果逐项标明成功/失败状态。
|
||||
|
||||
### AI 字段创建示例
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
1. **根节点必须是逻辑操作符**:`"operator"` 必须是 `"and"` 或 `"or"`,不能是 `"eq"` 等比较操作符
|
||||
2. 比较操作必须放在根节点的 `"operands"` 数组内的对象中
|
||||
3. `singleSelect` 和 `multipleSelect` 字段,推荐使用 **选项的 exact String 名称 (name)** 作为比较值
|
||||
4. fieldId 必须通过 `table get` 或 `field get` 获取,不能直接用字段名称
|
||||
4. fieldId 必须通过 `field get` 获取,不能直接用字段名称
|
||||
|
||||
### 精简防呆模板
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
# 表单管理
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `form list/get/create/update/delete` | 表单视图管理 | [`aitable-form.md`](./aitable-form.md) |
|
||||
| `form field list/update/hide` | 表单字段管理 | [`aitable-form.md`](./aitable-form.md) |
|
||||
| `form questions create/delete` | 题目管理 | [`aitable-form.md`](./aitable-form.md) |
|
||||
| `form share get/update` | 表单分享配置 | [`aitable-form.md`](./aitable-form.md) |
|
||||
@@ -1,95 +0,0 @@
|
||||
# 意图判断
|
||||
|
||||
## 意图判断
|
||||
|
||||
用户说"表格/多维表/AI表格":
|
||||
- 查看/查找/列表 → `base search`(优先)或 `base list`(仅浏览最近访问)
|
||||
- 详情 → `base get`
|
||||
- 创建 → `base create`
|
||||
- 修改 → `base update`
|
||||
- 删除 → `base delete`
|
||||
|
||||
用户说"数据表/子表/table":
|
||||
- 查看 → `table get`
|
||||
- 创建 → `table create`
|
||||
- 重命名 / 改备注 / 改行命名规则 → `table update`(三选一:`--name` / `--description` / `--record-name-key`)
|
||||
- 用户说"行命名规则/记录别名/卡片显示成 task/project/event 这种" → `table update --record-name-key <枚举键>`,**中文 → 枚举键**对照见 [aitable-record-name-key.md](./aitable-record-name-key.md)
|
||||
- 删除 → `table delete`
|
||||
|
||||
用户说"字段/列/column":
|
||||
- 查看 → `field get`
|
||||
- 添加 → `field create`(读 [aitable-field.md](./aitable-field.md))
|
||||
- 修改 → `field update`
|
||||
- 删除 → `field delete`
|
||||
|
||||
用户说"记录/行/数据/row":
|
||||
- 查看/搜索 → `record query`(读 [aitable-record-query.md](./aitable-record-query.md))
|
||||
- 找空行 / 没填东西的行 → `record query-empty`(读 [aitable-record-query.md](./aitable-record-query.md))
|
||||
- 已知 recordId 反查字段值 → `record get`(按 ID 取专用,等价 `record query --record-ids`)
|
||||
- 添加/写入 → `record create`(读 [aitable-record-create.md](./aitable-record-create.md))
|
||||
- 修改/更新(每条独立 cells) → `record update`(读 [aitable-record-update.md](./aitable-record-update.md))
|
||||
- **批量更新同一字段值**(统一标记/统一改值) → `record batch-update --record-ids ... --cells '{...}'`
|
||||
- 删除 → `record delete`
|
||||
- **查记录的字段变更历史 / 操作审计** → `record history-list`(读 [aitable-record-history.md](./aitable-record-history.md))
|
||||
- **取记录分享链接 / 把这行发给同事** → `record share-url`(读 [aitable-record-share.md](./aitable-record-share.md))
|
||||
- **不知道有没有 → 有就改、没有就建** → `record upsert`(读 [aitable-record-upsert.md](./aitable-record-upsert.md))
|
||||
|
||||
用户说"视图/view":
|
||||
- 列出/查看全部视图 → `view list`(或 `view get` 不传 --view-ids,二者等价)
|
||||
- 看某个视图详情 → `view get --view-ids <ID>`
|
||||
- 创建 → `view create`
|
||||
- 修改(含"调整字段顺序/隐藏字段") → `view update --config '{"visibleFieldIds":[...]}'`
|
||||
- 修改某一项配置(filter/sort/group/card/timebar/aggregate 等)→ `view update <attr>`(读 [aitable-view-config.md](./aitable-view-config.md))
|
||||
- 锁定 / 冻结列 / 行高 / 数据高亮规则 / 复制视图 → 读 [aitable-view-extras.md](./aitable-view-extras.md)
|
||||
- 删除 → `view delete`
|
||||
|
||||
用户说"锁定视图/解锁视图/lock view" → `view lock` / `view lock --off`,详见 [aitable-view-extras.md](./aitable-view-extras.md)
|
||||
|
||||
用户说"冻结列/冻结首列/frozen columns" → `view update frozen-cols --count N`,详见 [aitable-view-extras.md](./aitable-view-extras.md)
|
||||
|
||||
用户说"行高/单元格高度/紧凑模式/cell height" → `view update row-height --cell-height N`(合法档位 32/56/88/128),详见 [aitable-view-extras.md](./aitable-view-extras.md)
|
||||
|
||||
用户说"数据高亮/条件格式/单元格上色/fill color rule" → `view update fill-color-rule --json '[...]'`,详见 [aitable-view-extras.md](./aitable-view-extras.md)
|
||||
|
||||
用户说"复制视图/duplicate view" → `view duplicate --view-id ... [--new-name ...]`,详见 [aitable-view-extras.md](./aitable-view-extras.md)
|
||||
|
||||
用户说"筛选/过滤/filter" → 读 [aitable-filter-sort.md](./aitable-filter-sort.md)
|
||||
|
||||
用户说"统计/分析/聚合/TOP N/全量" → 读 [aitable-data-analysis-sop.md](./aitable-data-analysis-sop.md)
|
||||
|
||||
用户说"公式/formula/计算字段/派生指标" → 读 [aitable-formula-guide.md](./aitable-formula-guide.md)
|
||||
|
||||
用户说"查找引用/lookup/filterUp/跨表" → 读 [aitable-formula-guide.md](./aitable-formula-guide.md)(§5.4 跨表引用)
|
||||
|
||||
用户说"表单/form/收集表/问卷/催办填写" → 读 [aitable-form.md](./aitable-form.md)
|
||||
|
||||
用户说"自动化/工作流/流程/触发/automation/workflow" → 读 [aitable-workflow.md](./aitable-workflow.md)
|
||||
- 新建并发布流程 → `workflow create --base-id <BASE_ID> --dsl @workflow.json`
|
||||
- 修改并发布已有流程 → 先 `workflow get` 留底,再 `workflow update --base-id <BASE_ID> --workflow-id <WORKFLOW_ID> --dsl @workflow.json`
|
||||
- 看 Base 里有哪些流程 / 哪些在跑 → `workflow list`(看 `recordCount` / `runningCount`)
|
||||
- 看某个流程具体配置(触发条件、动作步骤) → `workflow get`
|
||||
- 启用流程 → `workflow enable`
|
||||
- 临时停掉流程(调试 / 数据迁移)→ `workflow disable --yes`
|
||||
- **删除流程**:当前 CLI 暂不支持,引导用户到 AI 表格 Web 端 → 数据表 → 自动化面板手动完成
|
||||
|
||||
用户说"仪表盘/图表/chart" → 读 [aitable-dashboard-chart.md](./aitable-dashboard-chart.md)
|
||||
|
||||
用户说"仪表盘排版乱了/图表对不齐/重新排布/自动布局/美化仪表盘" → `dashboard arrange`(读 [aitable-dashboard-chart.md](./aitable-dashboard-chart.md))
|
||||
|
||||
用户说"附件/上传文件" → 读 [aitable-attachment.md](./aitable-attachment.md)
|
||||
|
||||
用户说"导入/导出/import/export" → 读 [aitable-export-import.md](./aitable-export-import.md)
|
||||
|
||||
用户说"模板" → `template search`
|
||||
|
||||
用户说"高级权限/角色/权限控制/谁能看/谁能改" → 读 [aitable-advperm.md](./aitable-advperm.md)
|
||||
- 开/关高级权限 → `advperm enable` / `advperm disable --yes`
|
||||
- 看角色配置 → `advperm role-list` 或 `advperm role-get`
|
||||
- 建角色(可同时指定子角色权限) → `advperm role-create --name ... --sub-roles '[...]'`
|
||||
- 改角色名 / 改子角色权限(PATCH 语义,未传字段不变) → `advperm role-update --role-id ... [--name ...] [--sub-roles '[...]']`
|
||||
- 删角色 → `advperm role-delete --yes`
|
||||
- **角色 ↔ 成员绑定**:当前 CLI 不支持,仍需在 AI 表格 Web 端面板手动完成
|
||||
|
||||
命令报错/操作失败 → 读 [aitable-error-recovery.md](./aitable-error-recovery.md)
|
||||
|
||||
**关键区分**: base=表格文件, table=数据表, field=列, record=行
|
||||
@@ -1,8 +0,0 @@
|
||||
# 注意事项
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 所有操作使用 ID(baseId/tableId/fieldId/recordId),不使用名称
|
||||
- records 的 cells key 是 fieldId,不是字段名称
|
||||
- cells 写入/读取格式见 [aitable-cell-value.md](./aitable-cell-value.md)
|
||||
- 最佳实践见 [aitable-best-practices.md](./aitable-best-practices.md)
|
||||
@@ -28,7 +28,7 @@ dws aitable record primary-doc-create --base-id BASE_ID --table-id TABLE_ID --fi
|
||||
**参数:**
|
||||
- `--base-id`(必填):Base ID
|
||||
- `--table-id`(必填):Table ID
|
||||
- `--field-id`(必填):主键字段 ID,必须是 primaryDoc 类型(通过 `dws aitable table get` 查看字段类型)
|
||||
- `--field-id`(必填):主键字段 ID,必须是 primaryDoc 类型(通过 `dws aitable field get` 查看字段类型)
|
||||
- `--record-id`(必填):Record ID
|
||||
|
||||
**返回:** `data.nodeId` — 创建或已存在的主键文档 nodeId。
|
||||
@@ -44,8 +44,8 @@ dws aitable record primary-doc-create --base-id BASE_ID --table-id TABLE_ID --fi
|
||||
## 典型工作流
|
||||
|
||||
```bash
|
||||
# 1. 查询表结构,拿到 primaryDoc 字段的 fieldId
|
||||
dws aitable table get --base-id BASE_ID --table-ids TABLE_ID
|
||||
# 1. 查询字段目录,拿到 primaryDoc 字段的 fieldId
|
||||
dws aitable field get --base-id BASE_ID --table-id TABLE_ID
|
||||
|
||||
# 2. 为某条记录创建主键文档
|
||||
dws aitable record primary-doc-create --base-id BASE_ID --table-id TABLE_ID --field-id FIELD_ID --record-id RECORD_ID
|
||||
|
||||
@@ -25,7 +25,7 @@ Flags:
|
||||
|------|------|
|
||||
| 参数名用 `--data` | ❌ 参数名是 `--records`,不是 `--data` |
|
||||
| cells key 用字段名 | ❌ cells key 必须是 fieldId(如 `fldXXX`),不是字段名称(如 `"课程名称"`) |
|
||||
| 不先获取 fieldId | ❌ 必须先 `table get` 获取 fieldId,再写入记录 |
|
||||
| 不先获取 fieldId | ❌ 必须先 `field get` 获取 fieldId,再写入记录 |
|
||||
| 单次超 100 条 | ❌ 单次最多 100 条,超过需分批 |
|
||||
| 附件/图片字段直传 URL | ❌ 严禁 `{"url":"https://..."}` — 会触发 TIMEOUT_ERROR。必须先 `attachment upload` 获取 `fileToken`,再用 `{"fileToken":"ft_xxx"}` 写入。详见 [aitable-attachment.md](./aitable-attachment.md) |
|
||||
|
||||
@@ -33,14 +33,20 @@ Flags:
|
||||
|
||||
```bash
|
||||
# 先获取 fieldId
|
||||
dws aitable table get --base-id <BASE_ID> --table-ids <TABLE_ID> --format json
|
||||
dws aitable field get --base-id <BASE_ID> --table-id <TABLE_ID> --format json
|
||||
# 从返回中提取 fieldId(如 fldABC123)
|
||||
|
||||
# 再用 fieldId 写入记录
|
||||
dws aitable record create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"cells":{"fldABC123":"Python入门"}}]' --format json
|
||||
|
||||
# 从创建响应的 data.newRecordIds[] 提取新 ID,并回读确认真实写入值
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--record-ids <NEW_RECORD_ID> --format json
|
||||
```
|
||||
|
||||
创建成功以 `data.newRecordIds[]` 为 ID 来源;不要把整个 `data` 当作单个 recordId,也不要只以退出码作为写入成功证据。
|
||||
|
||||
## cells 写入格式
|
||||
|
||||
各字段类型的写入格式见 [aitable-cell-value.md](./aitable-cell-value.md)。
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
# 记录管理
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `record query` | 查询/搜索记录 | [`aitable-record-query.md`](./aitable-record-query.md) |
|
||||
| `record get` | 按 ID 取记录 | [`aitable-record-query.md`](./aitable-record-query.md) |
|
||||
| `record create` | 新增记录 | [`aitable-record-create.md`](./aitable-record-create.md) |
|
||||
| `record update` | 更新记录 | [`aitable-record-update.md`](./aitable-record-update.md) |
|
||||
| `record batch-update` | 批量更新 | [`aitable-record-update.md`](./aitable-record-update.md) |
|
||||
| `record delete` | 删除记录 | [`aitable-record-delete.md`](./aitable-record-delete.md) |
|
||||
| `record history-list` | 查询单条记录的变更历史 | [`aitable-record-history.md`](./aitable-record-history.md) |
|
||||
| `record share-url` | 批量获取记录分享链接 | [`aitable-record-share.md`](./aitable-record-share.md) |
|
||||
| `record upsert` | 批量创建或更新 | [`aitable-record-upsert.md`](./aitable-record-upsert.md) |
|
||||
@@ -10,21 +10,39 @@ Example:
|
||||
--records '[{"recordId":"recXXX","cells":{"fldStatusId":"已完成"}}]'
|
||||
Flags:
|
||||
--base-id string Base ID (必填)
|
||||
--records string 待更新记录 JSON 数组,单次最多 100 条 (必填,与 --records-file 二选一)
|
||||
--records string 待更新记录 JSON 数组,单次最多 100 条;cells key 支持 fieldId 或当前表内唯一字段名,推荐 fieldId (必填,与 --records-file 二选一)
|
||||
--records-file string 从文件读取 records JSON(替代 --records,适合超长数据或 Windows 环境)
|
||||
--table-id string Table ID (必填)
|
||||
```
|
||||
|
||||
只需传入需修改的字段,未传入的保持原值。每条记录必须含 recordId 和 cells。
|
||||
|
||||
## 高频错误 flag(LLM 极易踩坑,必读)
|
||||
## cells key:优先使用 fieldId,也支持唯一字段名
|
||||
|
||||
CLI **没有** `--record-id` 和 `--cells` 两个独立 flag,**只接受 `--records` 一个参数**,格式为 JSON 数组。
|
||||
即使只改一条记录,也必须包在数组里。
|
||||
`cells` 的 key 有两种写法:
|
||||
|
||||
| 错误(LLM 直觉) | 正确 |
|
||||
- fieldId(推荐):不受字段重命名或重名影响,通过 `field get` 获取。
|
||||
- 当前表内唯一的字段名:按名称精确匹配;如果存在同名字段,必须改用 fieldId。
|
||||
|
||||
同一字段同时通过 fieldId 和字段名传入时,fieldId 对应的值优先。
|
||||
|
||||
```bash
|
||||
# 推荐:fieldId
|
||||
dws aitable record update --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"recordId":"recXXX","cells":{"fldStatusId":"已完成"}}]' --format json
|
||||
|
||||
# 便捷写法:当前表内唯一字段名
|
||||
dws aitable record update --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"recordId":"recXXX","cells":{"状态":"已完成"}}]' --format json
|
||||
```
|
||||
|
||||
## 推荐参数形式
|
||||
|
||||
公开、稳定的批量入口是 `--records`(或 `--records-file`),格式为 JSON 数组;即使只改一条记录,推荐也包在数组里。CLI 仍保留隐藏的 `--record-id` + `--cells` 兼容入口,但它不会出现在常规帮助中,自动化脚本应优先使用 `--records`。
|
||||
|
||||
| 不推荐或无效写法 | 推荐写法 |
|
||||
|---|---|
|
||||
| `--record-id recXXX --cells '{"fldX":"值"}'` | `--records '[{"recordId":"recXXX","cells":{"fldX":"值"}}]'` |
|
||||
| `--record-id recXXX --cells '{"fldX":"值"}'`(隐藏兼容入口) | `--records '[{"recordId":"recXXX","cells":{"fldX":"值"}}]'` |
|
||||
| `--id recXXX --data '{"fldX":"值"}'` | 同上 |
|
||||
| `--record-id recXXX --field fldX --value "新值"` | 同上 |
|
||||
|
||||
@@ -33,8 +51,14 @@ CLI **没有** `--record-id` 和 `--cells` 两个独立 flag,**只接受 `--re
|
||||
```bash
|
||||
dws aitable record update --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"recordId":"<RECORD_ID>","cells":{"<FIELD_ID>":"新值"}}]' --format json
|
||||
|
||||
# 从更新响应的 data.recordIds[] 提取成功记录 ID,并回读确认真实值
|
||||
dws aitable record query --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--record-ids <RECORD_ID> --format json
|
||||
```
|
||||
|
||||
更新响应不返回“受影响字段”;以 `data.recordIds[]` 确定成功记录,再用查询回读验证。
|
||||
|
||||
## 引号转义提示
|
||||
|
||||
- Linux/macOS:外层用单引号 `'[...]'`,内部 JSON 用双引号即可
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# 相关产品
|
||||
|
||||
## 相关产品
|
||||
|
||||
- [doc](../../../dingtalk-doc/references/doc.md) — 富文本文档编辑,不是结构化数据表格
|
||||
@@ -1,10 +0,0 @@
|
||||
# 自动化脚本
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
| 脚本 | 场景 |
|
||||
|------|------|
|
||||
| [bulk_add_fields.py](../../scripts/bulk_add_fields.py) | 批量添加字段 |
|
||||
| [import_records.py](../../scripts/import_records.py) | 从 JSON/CSV 批量导入记录 |
|
||||
| [aitable_export_via_task.py](../../scripts/aitable_export_via_task.py) | 文件导出(export_data 轮询 + 下载) |
|
||||
| [upload_attachment.py](../../scripts/upload_attachment.py) | 上传附件到 AI 表格记录 |
|
||||
@@ -1,8 +0,0 @@
|
||||
# 数据表管理
|
||||
|
||||
| 命令 | 用途 | 必读参数 |
|
||||
|---|---|---|
|
||||
| `table get` | 获取表结构(字段+视图目录) | `--base-id` |
|
||||
| `table create` | 创建数据表 | `--base-id` `--name` `--fields` |
|
||||
| `table update` | 修改表名 / 备注 / 行命名规则 | `--base-id` `--table-id` |
|
||||
| `table delete` | 删除表 | `--base-id` `--table-id` |
|
||||
@@ -1,17 +0,0 @@
|
||||
# 文档地址 (URI)
|
||||
|
||||
## 文档地址 (URI)
|
||||
|
||||
| 资源 | URI 格式 |
|
||||
|------|----------|
|
||||
| Base 文档 | `https://alidocs.dingtalk.com/i/nodes/{baseId}` |
|
||||
| 指定数据表 | `https://alidocs.dingtalk.com/i/nodes/{baseId}?iframeQuery=sheetId%3D{tableId}` |
|
||||
| 指定数据表+视图 | `https://alidocs.dingtalk.com/i/nodes/{baseId}?iframeQuery=sheetId%3D{tableId}%26viewId%3D{viewId}` |
|
||||
| 模板预览 | `https://docs.dingtalk.com/table/template/{templateId}` |
|
||||
|
||||
> **操作后请返回文档 URI**:返回链接时必须带上当前操作的数据表 tableId,让用户点击后直接看到目标数据表,而不是落在空白的默认表。
|
||||
> - 已知 tableId + viewId 时(view create 返回、view get 中提取):拼接 `https://alidocs.dingtalk.com/i/nodes/{baseId}?iframeQuery=sheetId%3D{tableId}%26viewId%3D{viewId}`
|
||||
> - 已知 tableId 时(table create 返回、base get 中提取、record 操作所用的 tableId):拼接 `https://alidocs.dingtalk.com/i/nodes/{baseId}?iframeQuery=sheetId%3D{tableId}`
|
||||
> - 仅有 baseId、无明确 tableId 时(如 base list/search):拼接 `https://alidocs.dingtalk.com/i/nodes/{baseId}`
|
||||
>
|
||||
> 补充:如果 URL 不是来自 `aitable` 命令返回,而是用户直接贴的原始 `alidocs` URL,先按 [链接规范](../url-patterns.md#alidocs-url-类型探测流程) probe,确认是 `able` 后再按 AI 表格处理。
|
||||
@@ -1,11 +0,0 @@
|
||||
# URL → baseId 提取
|
||||
|
||||
## URL → baseId 提取
|
||||
|
||||
用户提供 `https://alidocs.dingtalk.com/i/nodes/{baseId}` 链接时:
|
||||
1. 提取 `/nodes/` 后的路径段作为 `baseId`
|
||||
2. 去掉尾部的查询参数(`?` 及其后内容)
|
||||
3. 传入 `--base-id` 参数
|
||||
|
||||
> 如果该 URL 来自 `dws aitable` 返回或已在当前链路 probe 过,可直接复用;
|
||||
> 如果是用户直接提供的原始 `alidocs` URL,则先按 [链接规范](../url-patterns.md#alidocs-url-类型探测流程) probe,确认 `extension=able` 后再继续。
|
||||
@@ -16,7 +16,34 @@
|
||||
|
||||
> card 在 Kanban 走 `kanbanCard`,在 Gallery 走 `galleryCard`,CLI 自动按 viewType dispatch(preflight 1 次 `get_views`)。timebar 仅 Gantt 支持;Calendar 服务端未暴露任何 timebar 配置。
|
||||
|
||||
> **Gantt 视图必须两步创建**:`view create --view-type Gantt` 只创建空壳(`ganttTimebar: {}`),**必须**紧跟 `view update timebar --start-field <日期字段ID>` 绑定时间轴字段,否则视图打开是空白。`create_view` 的 `--config` 中传入 `ganttTimebar` 会被服务端忽略。
|
||||
> **Gantt 视图必须两步创建**:`view create --view-type Gantt` 只创建空壳(`ganttTimebar: {}`),**必须**紧跟 `view update timebar --start-field <日期字段ID>` 绑定时间轴字段,否则视图打开是空白。`view create --config` 不接受 `ganttTimebar`,请在创建后使用专属子命令。
|
||||
|
||||
## 创建:view create
|
||||
|
||||
`--view-type` 支持 `Grid`、`Kanban`、`Gantt`、`Calendar`、`Gallery`、`FormDesigner`。创建时有两种方式设置可见字段:
|
||||
|
||||
```bash
|
||||
# 推荐:CSV typed flag;主字段必须排第一
|
||||
dws aitable view create --base-id BASE_ID --table-id TABLE_ID \
|
||||
--view-type Grid --name "任务视图" \
|
||||
--visible-field-ids fldPrimary,fldStatus,fldOwner
|
||||
|
||||
# JSON 方式:可同时配置可见字段、筛选、排序和分组
|
||||
dws aitable view create --base-id BASE_ID --table-id TABLE_ID \
|
||||
--view-type Grid --name "任务视图" \
|
||||
--config '{"visibleFieldIds":["fldPrimary","fldStatus","fldOwner"],"sort":[{"fieldId":"fldStatus","direction":"asc"}]}'
|
||||
```
|
||||
|
||||
创建阶段的 `--config` 是 JSON 对象,并且只接受以下 4 个 key:
|
||||
|
||||
| key | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `visibleFieldIds` | `string[]` | fieldId 数组,不接受字段名;至少一个,主字段必须排第一 |
|
||||
| `filter` | `object[]` | 筛选规则数组;兼容单个 object,CLI 会自动包装为数组 |
|
||||
| `sort` | `object[]` | 排序规则数组;兼容单个 object,CLI 会自动包装为数组 |
|
||||
| `group` | `object[]` | 分组规则数组;兼容单个 object,CLI 会自动包装为数组 |
|
||||
|
||||
`--visible-field-ids` 与 `config.visibleFieldIds` 互斥。描述使用独立的 `--desc '{"content":[]}'`;`description`、`fieldWidths`、`aggregate`、`kanbanCard`、`ganttTimebar`、`galleryCard` 等其他 key 会在调用服务端前被拒绝,并提示对应的 `view update` 子命令。
|
||||
|
||||
## 读取:view get <attr>
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# 视图管理
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `view get/list/create/update/delete/duplicate/lock` | 视图本体与基本属性 | [`aitable-view-config.md`](./aitable-view-config.md) |
|
||||
| `view update <attr>` | 按属性局部更新 | [`aitable-view-config.md`](./aitable-view-config.md) / [`aitable-view-extras.md`](./aitable-view-extras.md) |
|
||||
@@ -1,6 +0,0 @@
|
||||
# 自动化工作流
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `workflow create/update` | 创建或全量更新并发布工作流 | [`aitable-workflow.md`](./aitable-workflow.md) |
|
||||
| `workflow list/get/enable/disable` | 查询与启停工作流 | [`aitable-workflow.md`](./aitable-workflow.md) |
|
||||
@@ -18,9 +18,15 @@
|
||||
|
||||
## DSL 入参格式与最小 Demo
|
||||
|
||||
`workflow create/update` 的 `--dsl` 接收完整的 `workflow-dsl/v1` JSON object,不是局部 patch。支持内联 JSON、`@文件路径` 或 `-` 从 stdin 读取。
|
||||
`workflow create/update` 的 `--dsl` 接收钉钉 AI 表格 `workflow-dsl/v1` JSON object。当前同步范围只包含 create/update,没有新增 DSL 文档子命令;其他 Agent 可以直接使用下面的最小 Demo 理解调用格式。
|
||||
|
||||
复杂工作流应先用 `table get` / `field get` / `view list` 确认真实 `sheetId`、`fieldId`、`viewId`,并检查所有 `next`、`loopEntry`、branch `to` 和 ref。下面是一个不依赖数据表字段的最小定时消息工作流:
|
||||
复杂工作流还应注意:
|
||||
|
||||
1. 如果 Agent 运行环境直接提供 AI 表格 MCP 的 `get_workflow_dsl_docs`,可用它获取最新 DSL Guide、Schema 和示例。
|
||||
2. 涉及数据表、字段或视图的节点,先用 `table get` / `field get` / `view list` 确认真实 `sheetId`、`fieldId`、`viewId`。
|
||||
3. create 和 update 都提交完整的 workflow-dsl/v1 JSON object,并检查所有 `next`、`loopEntry`、branch `to` 和 ref。
|
||||
|
||||
以下 Demo 表示“每天 09:00 触发,并向 Base 所有者发送消息”,不依赖数据表、字段或视图 ID:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -42,18 +48,16 @@
|
||||
"type": "SendMessage",
|
||||
"data": {
|
||||
"title": "定时任务已触发",
|
||||
"to": {"users": [{"ref": "$.system_node.ownerUserId"}]}
|
||||
"to": {
|
||||
"users": [{"ref": "$.system_node.ownerUserId"}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
create 和 update 都必须同时满足 `status=success`、`data.valid=true`、`data.issues=[]` 才表示发布成功。
|
||||
|
||||
## 命令详情
|
||||
|
||||
### workflow create — 创建并发布工作流
|
||||
将上述 JSON 保存为 `workflow.json` 后创建工作流:
|
||||
|
||||
```bash
|
||||
dws aitable workflow create \
|
||||
@@ -61,22 +65,69 @@ dws aitable workflow create \
|
||||
--dsl @workflow.json \
|
||||
--locale zh-CN \
|
||||
--format json
|
||||
```
|
||||
|
||||
保存创建结果中的 `data.flowId`。更新时修改 `workflow.json` 中的完整目标定义,例如修改 `name`、`description` 或消息 `title`,然后调用:
|
||||
|
||||
```bash
|
||||
dws aitable workflow update \
|
||||
--base-id BASE_ID \
|
||||
--workflow-id FLOW_ID \
|
||||
--dsl @workflow.json \
|
||||
--locale zh-CN \
|
||||
--format json
|
||||
```
|
||||
|
||||
create 和 update 都必须同时满足 `status=success`、`data.valid=true`、`data.issues=[]` 才表示发布成功;update 返回的 `data.flowId` 应与传入的 `FLOW_ID` 一致。以上仅为最小 Demo,复杂节点的 `type` 和 `data` 结构以钉钉 AI 表格 MCP 最新 DSL 文档为准。
|
||||
|
||||
## 命令详情
|
||||
|
||||
### workflow create — 创建并发布工作流
|
||||
|
||||
```bash
|
||||
# 大 DSL 推荐从文件读取
|
||||
dws aitable workflow create \
|
||||
--base-id BASE_ID \
|
||||
--dsl @workflow.json \
|
||||
--locale zh-CN \
|
||||
--format json
|
||||
|
||||
# 也支持 stdin
|
||||
cat workflow.json | dws aitable workflow create --base-id BASE_ID --dsl - --format json
|
||||
```
|
||||
|
||||
| flag | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `--base-id` | 是 | 所属 Base ID |
|
||||
| `--dsl` | 是 | workflow-dsl/v1 JSON object;支持内联、`@filepath`、`-` stdin |
|
||||
| `--dsl` | 是 | workflow-dsl/v1 JSON object;支持内联 JSON、`@filepath`、`-` stdin |
|
||||
| `--locale` | 否 | 请求语言,如 `zh-CN` / `zh_CN` |
|
||||
|
||||
`create` 非幂等,CLI 不自动重试。若网络中断导致结果不确定,先 `workflow list` 按名称确认是否已经创建,再决定是否重试。`status=success` 只说明服务正常返回;`data.valid=false` 仍是发布失败,必须读取 `issues`。
|
||||
创建成功返回发布结果:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"data": {
|
||||
"valid": true,
|
||||
"flowId": "G-FLOW-XXXXXX",
|
||||
"flowSchema": {},
|
||||
"stepNodeIds": {},
|
||||
"referenceMap": {},
|
||||
"issues": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
关键语义:
|
||||
|
||||
- `create` 非幂等,CLI 不自动重试。若网络中断导致结果不确定,先 `workflow list` 按名称确认是否已创建,再决定是否重试。
|
||||
- `status=success` 只说明 workflow-edit 正常返回;如果 `data.valid=false`,仍表示 DSL 未通过校验或发布,必须读取 `issues` 修正。
|
||||
- 创建并发布后,用 `workflow list` 确认 `status`;需要运行但状态为 `STOP` 时再调用 `workflow enable`。
|
||||
|
||||
### workflow update — 更新并发布工作流
|
||||
|
||||
```bash
|
||||
# 先留底,再提交完整目标 DSL
|
||||
# 先留底现有详情,再提交完整目标 DSL
|
||||
dws aitable workflow get --base-id BASE_ID --workflow-id WORKFLOW_ID --format json > /tmp/workflow-backup.json
|
||||
dws aitable workflow update \
|
||||
--base-id BASE_ID \
|
||||
@@ -93,7 +144,7 @@ dws aitable workflow update \
|
||||
| `--dsl` | 是 | 完整目标 workflow-dsl/v1 JSON object;支持内联、`@filepath`、`-` stdin |
|
||||
| `--locale` | 否 | 请求语言,如 `zh-CN` / `zh_CN` |
|
||||
|
||||
update 返回结构与 create 相同,并会对瞬态错误重试。成功时 `data.flowId` 应与传入的工作流 ID 一致;随后用 `workflow get/list` 验证发布结果和运行状态。
|
||||
返回结构与 create 相同,成功时 `flowId` 应为目标工作流。update 使用 AI 表格瞬态错误重试;最终仍必须检查 `data.valid` 和 `issues`,并用 `workflow get/list` 验证发布结果与运行状态。
|
||||
|
||||
### workflow list — 列出工作流
|
||||
|
||||
@@ -226,10 +277,14 @@ dws aitable workflow disable --base-id BASE_ID --workflow-id WORKFLOW_ID --yes -
|
||||
### 创建并确认一个工作流
|
||||
|
||||
```bash
|
||||
# 1. 按本文 DSL Demo 生成 /tmp/workflow.json
|
||||
dws aitable workflow create --base-id BASE_ID --dsl @/tmp/workflow.json --locale zh-CN --format json \
|
||||
| tee /tmp/workflow-result.json
|
||||
|
||||
# 2. valid 必须为 true;保存 flowId
|
||||
jq '{valid: .data.valid, flowId: .data.flowId, issues: .data.issues}' /tmp/workflow-result.json
|
||||
|
||||
# 3. 确认运行状态,需要时显式启用
|
||||
FLOW_ID=$(jq -r '.data.flowId' /tmp/workflow-result.json)
|
||||
dws aitable workflow list --base-id BASE_ID --format json \
|
||||
| jq --arg id "$FLOW_ID" '.data.list[] | select(.flowId == $id) | {flowId, name, status}'
|
||||
@@ -268,9 +323,10 @@ done
|
||||
## 注意事项
|
||||
|
||||
- `--workflow-id` 接受的就是 `list` 返回里的 `flowId`(同值,CLI 屏蔽了服务端字段名差异)。
|
||||
- create / update 的 `--dsl` 必须是 JSON object,不能传数组、二次字符串化 JSON 或 `flowSchema`。
|
||||
- create / update 的 `--dsl` 必须是 JSON object,不能传数组、字符串化的二次 JSON 或 FlowSchema。
|
||||
- 本文 Demo 可直接用于最小定时消息工作流;复杂节点应以钉钉 AI 表格 MCP 最新 DSL 文档为准。
|
||||
- `status=success` 且 `data.valid=false` 仍是 DSL 校验失败;`issues` 才是下一步修复依据。
|
||||
- create 不自动重试;update 仅对网络、5xx、`retryable:true` 等瞬态错误自动重试。
|
||||
- create 不自动重试;update 仅对网络/5xx/`retryable:true` 瞬态错误自动重试。
|
||||
- enable / disable 出参里的 `enabled` / `disabled` 是 **动作确认 flag**,不是当前状态字段。要确认真生效请走 `workflow list` 查 `status`。
|
||||
- `workflow get` 的 `flowSchema` 结构随触发器/动作类型变化,不要假设固定字段。
|
||||
- 删除、运行历史和手动触发当前仍未开放。
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
| "创建一个新表格 (Base)" | `base create` | 不是 `table create` |
|
||||
| "在表格里加一个数据表" | `table create` | 不是 `base create` |
|
||||
| "看看表格里有哪些表" | `base get` | 不是 `field get` |
|
||||
| "看看表里有哪些列" | `field get` / `table get` | 不是 `base get` |
|
||||
| "看看表里有哪些列" | `field get` | 不是 `base get` |
|
||||
| "搜索表格" (找 Base) | `base search` | 不是 `record query` |
|
||||
| "搜索记录" (查表内数据) | `record query` | 不是 `base search` |
|
||||
| "删掉这个数据表" | `table delete` | 不是 `record delete` |
|
||||
@@ -74,7 +74,7 @@ dws aitable table create --base-id <BASE_ID> --name "产品图片" \
|
||||
|
||||
## 只读字段 (不可写入)
|
||||
|
||||
以下类型的字段不可写入, 执行 `field get` / `table get` 后识别并跳过:
|
||||
以下类型的字段不可写入, 执行 `field get` 后识别并跳过:
|
||||
- 创建时间 / 修改时间 (系统自动)
|
||||
- 创建人 / 修改人 (系统自动)
|
||||
- 自动编号
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
# URL 格式与处理规范
|
||||
|
||||
## alidocs URL 分流决策(必须首先执行)
|
||||
## 路由第 0 步:意图直达(优先级高于 URL 探测)
|
||||
|
||||
收到 `alidocs.dingtalk.com` URL 时,**必须按以下顺序判断,禁止跳过**:
|
||||
用户已经明确表达某产品的内容意图时,直接进入对应产品场域,不要先做 URL 类型
|
||||
探测。尤其:
|
||||
|
||||
- 明确提到 Markdown / `.md` 文件的读取或修改,按普通文件走 `drive` 场域:
|
||||
先 `dws drive download` 下载到本地处理,再用 `dws drive upload` 回传。
|
||||
- 明确“读这篇文档 / 编辑文档正文”进入 `doc`;明确“看这个在线表格数据”进入
|
||||
`sheet`。
|
||||
|
||||
仅当用户只粘贴 URL、没有明确产品意图,或意图与链接类型可能冲突时,才执行下方
|
||||
类型探测。
|
||||
|
||||
## alidocs URL 分流决策(意图不明确时执行)
|
||||
|
||||
收到 `alidocs.dingtalk.com` URL 且无法从指令判断产品时,必须按以下顺序判断:
|
||||
|
||||
1. URL 路径含 `/i/p/` → **分享短链**,禁止调用 `dws doc` 任何子命令 → 按下方 [分享短链处理](#分享短链处理) 执行
|
||||
2. URL 路径含 `/i/nodes/` → **节点链接**,需探测类型 → 按下方 [alidocs URL 类型探测流程](#alidocs-url-类型探测流程) 执行
|
||||
@@ -80,20 +93,23 @@ dws doc read --node "https://alidocs.dingtalk.com/i/p/Y7kmbokZp3pgGLq2/docs/AY39
|
||||
### 探测步骤
|
||||
|
||||
```
|
||||
Step 1 → dws doc info --node "<URL>" --format json
|
||||
Step 2 → 从返回中提取 contentType、extension、nodeType 字段
|
||||
Step 1 → dws drive info --node "<URL>" --format json
|
||||
Step 2 → 从返回中提取 extension、nodeType 字段
|
||||
Step 3 → 按下方路由规则映射到对应产品
|
||||
```
|
||||
|
||||
> 路由依据是 `extension`,不是 `contentType`。`drive info` 检测到
|
||||
> `adoc` / `axls` / `able` 时会自动补充在线文档信息。
|
||||
|
||||
### 路由映射表
|
||||
|
||||
| 条件 | 路由到产品 | 后续操作 |
|
||||
|------|-----------|---------|
|
||||
| `contentType=ALIDOC`, `extension=adoc` | `doc` | 加载 `dingtalk-doc` 操作内容 |
|
||||
| `contentType=ALIDOC`, `extension=axls` | `sheet` | 加载 `dingtalk-sheet` 操作(仅 `axls` 在线电子表格) |
|
||||
| `contentType=ALIDOC`, `extension=able` | `aitable` | 将 nodeId 作为 baseId,加载 `dingtalk-aitable` 操作 |
|
||||
| `contentType=DOCUMENT`, `extension=xlsx` / `xls` / `xlsm` / `csv` | `drive` | 必须用 `dws drive download` 下载到本地处理,禁止走 `sheet`(非在线表格,sheet 命令无法操作) |
|
||||
| `contentType≠ALIDOC`, `nodeType=file` | `drive` | 调用 `dws drive download` 下载,返回文件下载链接 |
|
||||
| `extension=adoc` | `doc` | 加载 `dingtalk-doc` 操作内容 |
|
||||
| `extension=axls` | `sheet` | 加载 `dingtalk-misc` 的 `references/sheet.md` 操作(仅 `axls` 在线电子表格) |
|
||||
| `extension=able` | `aitable` | 将 nodeId 作为 baseId,加载 `dingtalk-aitable` 操作 |
|
||||
| `extension=xlsx` / `xls` / `xlsm` / `csv` | `drive` | 必须用 `dws drive download` 下载到本地处理,禁止走 `sheet` |
|
||||
| `nodeType=file`(非在线文档扩展名,含 `md`) | `drive` | 下载用 `dws drive download --node <ID> --output <PATH> --format json`;上传/覆盖用 `dws drive upload` |
|
||||
| `nodeType=folder` | `drive` / `wiki` | 调用 `dws drive list --workspace <WS_ID>` 或 `dws wiki node list` 列出子节点 |
|
||||
| 以上均不匹配 | — | 告知用户当前暂不支持该类型 |
|
||||
|
||||
@@ -106,16 +122,16 @@ Step 3 → 按下方路由规则映射到对应产品
|
||||
|
||||
```bash
|
||||
# 用户传入: https://alidocs.dingtalk.com/i/nodes/abc123
|
||||
dws doc info --node "https://alidocs.dingtalk.com/i/nodes/abc123" --format json
|
||||
dws drive info --node "https://alidocs.dingtalk.com/i/nodes/abc123" --format json
|
||||
|
||||
# 返回 contentType=ALIDOC, extension=axls → 在线电子表格,路由到 sheet
|
||||
# 返回 extension=axls → 在线电子表格,路由到 sheet
|
||||
dws sheet list --node "https://alidocs.dingtalk.com/i/nodes/abc123" --format json
|
||||
|
||||
# 返回 contentType≠ALIDOC, extension=xlsx/xls/csv → 本地表格文件,必须下载处理(禁止走 sheet)
|
||||
dws drive download --node "https://alidocs.dingtalk.com/i/nodes/xlsx456"
|
||||
# 返回 extension=xlsx/xls/csv → 本地表格文件,必须下载处理(禁止走 sheet)
|
||||
dws drive download --node "https://alidocs.dingtalk.com/i/nodes/xlsx456" --output <PATH> --format json
|
||||
|
||||
# 返回 contentType≠ALIDOC, nodeType=file → 普通文件,下载
|
||||
dws drive download --node "https://alidocs.dingtalk.com/i/nodes/def456"
|
||||
# 返回 nodeType=file → 普通文件,下载
|
||||
dws drive download --node "https://alidocs.dingtalk.com/i/nodes/def456" --output <PATH> --format json
|
||||
|
||||
# 返回 nodeType=folder → 文件夹,列出子节点
|
||||
dws drive list --workspace <WS_ID> --format json
|
||||
@@ -126,4 +142,3 @@ dws drive list --workspace <WS_ID> --format json
|
||||
当用户指令中已明确指定产品(如"帮我读这个文档"、"看下这个表格的数据"),可结合用户意图**跳过探测**直接路由。仅在以下情况**必须执行探测**:
|
||||
- 用户只粘贴 URL,无其他上下文
|
||||
- 用户指令与 URL 实际类型可能不一致(如说"文档"但实际是表格)
|
||||
- 用户直接粘贴的是原始 `alidocs` URL,且没有上游命令返回来确认类型
|
||||
|
||||
@@ -88,12 +88,10 @@ def build_start_args(args: argparse.Namespace) -> list[str]:
|
||||
args.base_id,
|
||||
"--scope",
|
||||
args.scope,
|
||||
"--export-format",
|
||||
"--format",
|
||||
args.export_format,
|
||||
"--timeout-ms",
|
||||
str(args.timeout_ms),
|
||||
"--format",
|
||||
"json",
|
||||
]
|
||||
if args.table_id:
|
||||
cmd.extend(["--table-id", args.table_id])
|
||||
@@ -157,8 +155,6 @@ def main() -> None:
|
||||
task_id,
|
||||
"--timeout-ms",
|
||||
str(args.poll_timeout_ms),
|
||||
"--format",
|
||||
"json",
|
||||
],
|
||||
timeout_sec=max(120, int(args.poll_timeout_ms / 1000) + 60),
|
||||
)
|
||||
|
||||
@@ -29,7 +29,7 @@ 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_-]{6,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',
|
||||
|
||||
@@ -35,7 +35,7 @@ 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_-]{6,128}$')
|
||||
RESOURCE_ID_PATTERN = re.compile(r'^[A-Za-z0-9_-]{8,128}$')
|
||||
MAX_RECORDS_PER_BATCH = 100
|
||||
DEFAULT_BATCH_SIZE = 50
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
---
|
||||
name: dingtalk-attendance
|
||||
description: 钉钉考勤、打卡、排班与考勤报表。Use when 用户说考勤/打卡记录/查打卡/排班/班次/考勤报表/导出考勤/出勤汇总/考勤明细/迟到早退统计/全员考勤数据/某月考勤统计/考勤表格/考勤Excel。不做日程会议(走 dingtalk-calendar)、日报周报(走 dingtalk-report)、审批请假流程(走 dingtalk-oa)。命令前缀:dws attendance。
|
||||
cli_version: ">=0.2.14"
|
||||
metadata:
|
||||
category: product
|
||||
stability: experimental
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
---
|
||||
|
||||
# 钉钉考勤 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> 渐进式参考:[attendance-index.md](references/attendance-index.md)。日期范围或“签到”场景必须先读 [attendance-routing.md](references/attendance-routing.md);报表导出再读 [attendance-report.md](references/attendance-report.md)。
|
||||
|
||||
> 旧路径兼容入口:[attendance.md](references/attendance.md)。
|
||||
|
||||
<!-- VISIBLE_SHORTCUTS_START -->
|
||||
## Shortcuts(无专用脚本/recipe 时优先)
|
||||
|
||||
以下 shortcut 来自独立于 Runtime Schema 的公开 catalog。先按本 skill 的意图表、脚本和 recipe 路由:存在精确覆盖该场景的专用脚本/recipe 时按其执行;否则用户意图命中时,shortcut 优先于手写原子命令。用 `dws shortcut list --service attendance --format json` 读取参数、约束、风险和示例,并以 `dws attendance <shortcut> --help` 核对当前 Cobra flags;不要对 `+` 路径调用 `dws schema`。
|
||||
|
||||
| Shortcut | 风险 | 适用场景 |
|
||||
|---|---|---|
|
||||
| `dws attendance +check-record` | read | 查询用户打卡流水(打卡时间/地点/定位方式) |
|
||||
| `dws attendance +check-result` | read | 查询用户打卡结果(迟到/早退/缺卡等) |
|
||||
| `dws attendance +get-adjustment-rule` | read | 根据补卡规则主键 ID 查询补卡规则详情 |
|
||||
| `dws attendance +get-approve-template` | read | 查询补卡/请假/加班/外出/出差审批提交链接 |
|
||||
| `dws attendance +get-checkin-record` | read | 查询指定员工一段时间内的签到记录 |
|
||||
| `dws attendance +get-leave-records` | read | 查询指定员工的假期余额变更记录 |
|
||||
| `dws attendance +get-overtime-rule` | read | 根据加班规则主键 ID 查询加班规则详情 |
|
||||
| `dws attendance +get-schedule` | read | 获取指定用户一段时间内的排班记录 |
|
||||
| `dws attendance +get-self-setting` | read | 查询个人规则设置(打卡提醒/极速打卡/缺卡提醒等) |
|
||||
| `dws attendance +get-summary` | read | 查询某个人的考勤统计摘要(周/月) |
|
||||
| `dws attendance +list-approve` | read | 查询用户考勤审批单(补卡/加班/请假/出差外出) |
|
||||
| `dws attendance +list-leave-types` | read | 查询当前用户可用的假期规则列表 |
|
||||
| `dws attendance +my-attendance` | read | 查我今天的考勤打卡记录(打卡流水,自动解析当前用户) |
|
||||
| `dws attendance +query-report-data` | read | 根据字段查询考勤报表数据(仅管理员) |
|
||||
| `dws attendance +search-adjustment-rule` | read | 查询当前用户可管理的补卡规则列表 |
|
||||
| `dws attendance +search-class` | read | 查询当前用户可管理的班次详情列表 |
|
||||
| `dws attendance +search-group` | read | 查询当前用户可管理的考勤组列表 |
|
||||
| `dws attendance +search-overtime-rule` | read | 查询当前用户可管理的加班规则列表 |
|
||||
| `dws attendance +this-month` | read | 查我本月的考勤打卡记录(打卡流水,自动解析当前用户) |
|
||||
<!-- VISIBLE_SHORTCUTS_END -->
|
||||
|
||||
## 意图表
|
||||
|
||||
| 用户说 | 命令 |
|
||||
|--------|------|
|
||||
| "查我自己的打卡 / 某天考勤" | `python scripts/attendance_my_record.py 2026-03-08` 或 `dws attendance record get --user <userId> --date <YYYY-MM-DD>` |
|
||||
| "查团队排班" | `python scripts/attendance_team_shift.py --users <userId1,userId2> --from <YYYY-MM-DD> --to <YYYY-MM-DD>` |
|
||||
| "导出考勤报表 / 月度汇总 / 考勤明细 / 每日统计" | **必须先读 [attendance-report.md](references/attendance-report.md)** 强制门禁后选择 `attendance_report_{detail,monthly,daily}.py` |
|
||||
| "创建班次 / 设置班次" | 先读 [attendance.md](references/attendance-commands.md) 的 `class create`,确认后执行 |
|
||||
| "导入排班 / 安排排班" | 先读 [attendance.md](references/attendance-commands.md) 的 `schedule import`,确认后执行 |
|
||||
| "加入/移出考勤组 / 更新考勤组成员" | `dws attendance group update-members ...`(需确认) |
|
||||
|
||||
## 高频硬约束
|
||||
|
||||
- 不要在读完 [attendance.md](references/attendance-commands.md) 前判断"CLI 不支持"。`class create`、`schedule import`、`group update-members`、`group update` 都是已支持写操作,但必须先展示摘要并等用户确认。
|
||||
- 查询迟到/缺勤名单时,空打卡结果不等于"没人迟到"。必须结合排班、`NotSigned`、`Absenteeism`、无记录人员分别说明;数据缺失要标为"无记录/无法判断",不要归为正常。
|
||||
- 做部门 Top N 排名时,用户要求前 N 名就必须输出 N 个部门;无打卡记录或无可计算数据的部门按 0 或"无数据"保留在排名中,不能只输出有数据的少数部门。
|
||||
- 处理请假/补卡/加班审批时,先用考勤审批模板或 OA 查询确认可操作范围;没有直接提交接口时返回可点击提交链接并说明无法代填提交,不要假装已提交。
|
||||
- 更新考勤组成员固定按 `aisearch/contact` 解析 userId → `group search` 解析 groupId → 展示变更摘要并确认 → `group update-members` → `group filtered-get --member` 回查。
|
||||
- 所有 dws 命令带 `--format json`,时间/日期按命令要求分别使用 `YYYY-MM-DD` 或 reference 指定格式。
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
- 拿到 userId 前先用 `dingtalk-aisearch` 解析人名
|
||||
- 报表导出涉及多人 / 多月 → 脚本内部自动分批 + 切片,输出 xlsx
|
||||
## 局部意图与 Recipe
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md)。
|
||||
@@ -1,10 +0,0 @@
|
||||
# 严格约束
|
||||
|
||||
## 严格约束
|
||||
- 不要凭历史记忆复用 userId / classId / leaveCode / groupId / instanceId 等任何 ID,每次必须从当次命令返回值中提取
|
||||
- 不要猜测命令,先查询明确命令,不要使用记忆中未经证实(即不存在于本.md文件中的指令)或执行失败(指令传参有误或flag不正确)的的命令
|
||||
- 制定 plan 并自我审查,严格按 plan 执行
|
||||
- 涉及超过 3 条记录的聚合(求和、分组、计数、排序、跨字段计算)时必须落 Python 脚本处理,禁止用大模型口算或目测。脚本里如果用到 mcp,先提前看下 mcp 返回的结构,避免执行异常
|
||||
- 遇到时长字段时,注意区分单位是秒、分钟还是小时
|
||||
- 遇到意图不清晰的场景不要猜测,主动询问用户明确意图
|
||||
- 如果查询结果很多时,不要自作主张省略,必须明确告知用户或者用表格或展示所有。
|
||||
@@ -1,13 +0,0 @@
|
||||
# 上下文传递表
|
||||
|
||||
## 上下文传递表
|
||||
| 操作 | 提取 | 用于 |
|
||||
|------|------|------|
|
||||
| `contact user get-self` | `userId` | summary 的 --user |
|
||||
| `rules` | `groupId` | schedule import 的 --group-id |
|
||||
| `schedule import` | `classId` | schedule import 的 schedules 中的 classId |
|
||||
| `contact user search` | `userId` | schedule import/get 的 userId |
|
||||
|
||||
| `contact user get-self` / `contact user search` | `userId` | summary 的 --user, vacation records 的 --user;selfsetting get/save 的 --user(必填) |
|
||||
| 当前登录上下文 | `corpId`, `opUserId` | selfsetting get/save 自动补齐 MCP 入参, CLI 不需要传 `--corp-id` / `--op-user` |
|
||||
| `vacation types` | `leaveCode` | vacation balance 的 --leave-code, vacation records 的 --leave-code |
|
||||
@@ -1,11 +0,0 @@
|
||||
# 考勤能力索引
|
||||
|
||||
| 主题 | 详见 |
|
||||
|---|---|
|
||||
| 日期范围计算、签到与打卡分流 | [`attendance-routing.md`](./attendance-routing.md) |
|
||||
| 打卡/记录/排班/补卡/加班等核心命令 | [`attendance-commands.md`](./attendance-commands.md) |
|
||||
| 排班规则/班次/排班表 | [`attendance-schedule.md`](./attendance-schedule.md) |
|
||||
| 报表/统计/查询 | [`attendance-report.md`](./attendance-report.md) |
|
||||
| 假期/调休/余额 | [`attendance-vacation.md`](./attendance-vacation.md) |
|
||||
| 意图、工作流与上下文 | [`attendance-intent.md`](./attendance-intent.md) · [`attendance-workflow.md`](./attendance-workflow.md) · [`attendance-context.md`](./attendance-context.md) |
|
||||
| 注意事项、脚本与严格约束 | [`attendance-notes.md`](./attendance-notes.md) · [`attendance-scripts.md`](./attendance-scripts.md) · [`attendance-constraints.md`](./attendance-constraints.md) |
|
||||
@@ -1,62 +0,0 @@
|
||||
# 意图判断
|
||||
|
||||
## 意图判断
|
||||
|
||||
用户说"签到记录/签到数据/签到明细/外勤签到/导出签到" → `checkin records`(查询签到记录)。如果用户意图是**导出签到报表/签到Excel**,则走下方的签到报表导出工作流。
|
||||
- **优先级**:只要用户句中含"签到"二字,就走本条,不要走 `check record`。"签到" ≠ "打卡",签到是外勤场景的独立功能
|
||||
用户说"打卡记录/出勤/考勤" → `check record`
|
||||
用户说"指定用户打卡结果/考勤结果/迟到早退/缺卡异常" → `check result`
|
||||
用户说"指定用户打卡流水/打卡详情/打卡时间地点/打卡记录详情" → `check record`
|
||||
用户说"审批单/请假记录/加班记录/出差记录/补卡记录" → `approve list`
|
||||
用户说"查询排班记录/获取排班详情/查看排班/排班表/导出排班/导出排班表/排班导出/XX考勤组的排班" → **必须先 `read_file` 读取 [attendance-schedule.md](./attendance-schedule.md) 后按其中的「排班查询导出工作流」执行**。
|
||||
- **优先级**:只要用户句中含"排班"二字且意图是查看/导出,就走本条,不要走 `attendance-report.md`。"导出排班表" ≠ "导出考勤报表"
|
||||
- **严禁**绕过 `attendance-schedule.md` 直接调用 `dws attendance schedule get` 命令
|
||||
- 脚本自动处理:分批查询(超 20 人自动分批)、userId→姓名转换、classId→班次名称转换、排班表格式 Excel 输出
|
||||
用户说"排班/导入排班/安排排班/设置排班/安排班次/调班/换班/排休" → **必须先 `read_file` 读取 [attendance-schedule.md](./attendance-schedule.md) 后按其中的「排班导入工作流」执行**。
|
||||
- **严禁**绕过 `attendance-schedule.md` 直接调用 `dws attendance schedule import` 命令
|
||||
- **严禁**仅凭命令 `--help` 或本文件中的命令参考自行组装排班命令
|
||||
- 该文档定义了:考勤组类型校验(必须为 TURN)、班次校验(必须属于该考勤组)、排班回显确认、错误处理等约束,缺一不可
|
||||
- 违反约束的后果:排错班次、排错人员、排班数据覆盖无法回退
|
||||
用户说"班次定义/班次列表/有哪些班次/我负责的班次" → `class search`(返回结果已包含全量属性,无需再调 get)
|
||||
用户说"班次详情/某个班次的具体信息" → `class search --name "..."`(search 直出,直接返回详情)。`class get` 仅在需要按已知 classId 精确查询时使用
|
||||
用户说"更新班次/修改班次/班次改名/修改上下班时间" → `class update`
|
||||
用户说"补卡规则/补卡设置" → `adjustment search`(返回结果已包含全量属性,无需再调 get)
|
||||
用户说"补卡规则详情/某条补卡规则的具体信息" → `adjustment search --name "..."`(search 直出)。`adjustment get` 仅在需要按已知 adjustmentId 精确查询时使用
|
||||
用户说"加班规则/加班设置/加班计算" → `overtime search`(返回结果已包含全量属性,无需再调 get)
|
||||
用户说"加班规则详情/某条加班规则的具体信息" → `overtime search --name "..."`(search 直出)。如需查已删除/被覆盖的历史记录 → `overtime get`
|
||||
用户说"考勤组列表/有哪些考勤组" → `group search`
|
||||
用户说"考勤组详情/全量考勤组信息" → `group get`,若返回结果中含成员 userId 列表,则批量调用 `dws contact user get --ids <userId1,userId2>`(或等价通讯录查询),在最终输出中展示员工姓名而非裸 userId
|
||||
用户说"考勤组成员/打卡地址/打卡wifi/打卡蓝牙" → `group filtered-get`(按需查询,节省成本),若返回结果中含成员 userId 列表,则批量调用 `dws contact user get --ids <userId1,userId2>`(或等价通讯录查询),在最终输出中展示员工姓名而非裸 userId
|
||||
用户说"更新考勤组成员/添加考勤人员/删除考勤人员/添加考勤部门/删除考勤部门/加入考勤组/移出考勤组/设置无需考勤/取消无需考勤" → `group update-members`
|
||||
用户说"修改考勤组/更新考勤组配置/考勤组改名/改变考勤组绑定的班次/修改打卡范围/设置考勤组负责人" → `group update`
|
||||
用户说"创建考勤组/新建考勤组/添加考勤组" → `group create`
|
||||
用户说"查询某人的考勤汇总/考勤统计/周统计/月统计" → `summary`
|
||||
用户说"考勤组/考勤规则/打卡规则" → `rules`
|
||||
用户说"查询个人规则设置/查看打卡提醒/查看极速打卡/查看缺卡提醒/查看打卡结果通知/查看个人考勤统计通知/查看团队考勤统计通知" → `selfsetting get`
|
||||
用户说"更新个人规则设置/保存打卡提醒/修改极速打卡/关闭缺卡提醒/开启打卡结果通知/设置个人考勤统计通知/设置团队考勤统计通知" → `selfsetting save`
|
||||
用户说"考勤字段/考勤列" → `report columns`
|
||||
用户说"考勤数据/查询考勤报表数据" → `report query-data`(单次查询场景,非导出)
|
||||
**导出签到记录/签到报表/签到数据导出/签到明细/外勤签到导出** → **必须先 `read_file` 读取 [attendance-report.md](./attendance-report.md) 后按其中的工作流执行(报表类型为"签到报表")**。
|
||||
- 触发关键词:签到记录导出、签到报表、签到数据、签到明细、外勤签到
|
||||
- 数据来源为 `attendance checkin records`(签到接口),非 `report query-data`
|
||||
- **严禁**绕过 `attendance-report.md` 直接调用 `python scripts/attendance_report_checkin.py`
|
||||
**导出考勤/导出报表/生成考勤报表/出勤汇总导出/考勤明细导出/迟到早退统计导出/全员考勤数据导出/月度考勤报表/考勤表格/考勤 Excel** → **必须先 `read_file` 读取 [attendance-report.md](./attendance-report.md) 后按其中的工作流执行**。
|
||||
- **排除**:如果用户说的是"导出**排班**表"/"导出**排班**"/"**排班**导出",这属于**排班查询导出**,应路由到 [attendance-schedule.md](./attendance-schedule.md),而非本条。判断标准:句中含"排班"二字 → 走排班;不含"排班"或明确说"考勤报表/考勤数据/出勤统计" → 走报表。
|
||||
- **严禁**绕过 `attendance-report.md` 直接调用 `python scripts/attendance_report_*.py` 任何脚本
|
||||
- **严禁**仅凭脚本 `--help` 或本文件"自动化脚本"表格里的脚本路径就推断参数自行组装命令
|
||||
- 该文档定义了:报表类型默认值、列选择策略(`--column-keywords`)、阶段 1 人员获取流程、错误处理、输出摘要规范,缺一不可
|
||||
- 违反约束的后果:报表数据不全、列错位、人员遗漏、用户得到错误结果
|
||||
**导出补卡记录/导出请假记录/导出出差记录/导出外出记录/补卡导出/请假导出/出差导出/外出导出/考勤审批记录导出/请假明细/补卡明细/出差明细/外出明细** → **必须先 `read_file` 读取 [attendance-report.md](./attendance-report.md) 后按其中的工作流执行(报表类型为"考勤记录")**。
|
||||
- 触发关键词:补卡记录、请假记录、出差记录、外出记录、审批记录导出、请假明细导出、补卡明细导出
|
||||
- 判断标准:句中含"补卡/请假/出差/外出"且含"记录/导出/明细/报表" → 走 attendance-report.md 的"考勤记录"类型
|
||||
- **严禁**绕过 `attendance-report.md` 直接调用 `python scripts/attendance_report_record.py`
|
||||
- 该文档定义了:考勤记录子类型(leave/trip/out/patch)选择策略、阶段 1 人员获取流程、阶段 3 脚本调用规范
|
||||
用户说"假期数据/年假/病假/请假记录" → `report query-leave`
|
||||
用户说"假期/我的假期/假期规则" → `vacation types`
|
||||
用户说"病假余额/年假余额/事假剩余假期"等查询指定假期规则的余额 → `vacation balance`
|
||||
用户说"导出假期余额/假期余额列表/所有假期规则余额/假期余额 Excel/年假病假调休余额导出"等全部假期规则余额的查询 → **必须先 `read_file` 读取 [attendance-vacation.md](./attendance-vacation.md) 后按其中工作流执行**
|
||||
用户说"假期变更/假期记录/请假扣减" → `vacation records`
|
||||
用户说"更新假期规则/修改假期类型/编辑假期规则" → `vacation update-type --leave-code <LEAVE_CODE>`
|
||||
用户说"设置假期余额/调整假期额度/更新假期余额" → 先调用 `vacation balance` 获取当前余额,计算修改后的值,再调用 `vacation save-balance`
|
||||
用户说"增加假期余额/发放年假/给员工加年假" → 先调用 `vacation balance` 获取当前余额,加上要增加的天数,再调用 `vacation save-balance` 设置新总额度
|
||||
用户说"签到/签到记录" → `checkin records`
|
||||
@@ -1,107 +0,0 @@
|
||||
# 注意事项
|
||||
|
||||
## 注意事项
|
||||
**Agent 使用引导**:
|
||||
- 执行 vacation 子命令前,**必须先调用** `dws attendance vacation --help` 查看完整子命令列表和参数说明
|
||||
- 新增命令可能不在 Agent 缓存中,直接猜测命令会失败
|
||||
- 正确流程:查看帮助 → 选择命令 → 查看命令详细参数(如 `dws attendance vacation update-type --help`)→ 执行
|
||||
|
||||
- `record get` 的 `--date` 格式: YYYY-MM-DD(如 `2026-03-08`),CLI 自动转换为毫秒时间戳
|
||||
- `shift list` 查询班次信息,`--start/--end` 使用 YYYY-MM-DD 格式,间隔不超过 7 天
|
||||
- `schedule import` 导入排班记录 — 必须通过 [attendance-schedule.md](./attendance-schedule.md) 排班导入工作流执行
|
||||
- `schedule get` 查询排班记录 — 必须通过 [attendance-schedule.md](./attendance-schedule.md) 排班查询导出工作流执行(脚本自动分批、姓名转换、排班表格式导出)
|
||||
- `schedule import` 是写操作,AI 调用时必须先展示导入摘要并引导用户二次确认;用户明确确认后才允许执行。用户明确要求跳过确认或命令包含全局 `--yes` 时,可跳过二次确认
|
||||
- `class search` 所有参数均为可选,不填时返回全部可管理班次(默认第 1 页,每页 20 条)
|
||||
- **概念区分**:班次是员工当天打卡安排;排班是为排班制考勤组导入的排班记录;班次定义是考勤管理员创建的工作时间规则
|
||||
- `class get` 的 `--class-id` 必填,班次 ID 可从 `class search` 结果中提取
|
||||
- `class search` 返回结果已包含全量属性,无需再调用 `class get`;`class get` 仅在需要按已知 classId 精确查询时使用
|
||||
- `class update` 的 `--class-id` 必填,其余均可选,仅需对要修改的字段赋值,未传字段会自动从已有配置补充;由于保存班次耗时较久,建议加 `--timeout 10`
|
||||
- `adjustment search` 返回结果已包含全量属性,无需再调用 `adjustment get`;`adjustment get` 仅在需要按已知 adjustmentId 精确查询时使用
|
||||
- `overtime search` 返回结果已包含全量属性,无需再调用 `overtime get`;`overtime get` 仅在需要按已知 overtimeId 查询时使用(包括已删除/被覆盖的历史记录)
|
||||
- `adjustment search` / `overtime search` 分页字段为 `--page` 和 `--limit`,不传时自动使用默认值 1 / 20
|
||||
- `group search` 的分页字段为 `--page` 和 `--limit`,不传时自动使用默认值 1 / 20
|
||||
- `group get` 的 `--group-id` 必填,返回考勤组全量字段;如仅需成员/地址/蓝牙/Wifi,优先使用 `group filtered-get` 节省成本。**返回结果中如含成员 userId 列表,必须调用 `dws contact user get --ids <userId1>,<userId2>,...`(支持逗号分隔传多个 ID),将 userId 转换为员工姓名后再输出;不得直接输出裸 userId。**
|
||||
- `group update-members` 的 --group-id 必填,其余参数均可选,但至少需传一个变更项;各参数每次最多 20 个 ID;`--add-extra-users` 和 `--remove-extra-users` 操作的是"无需考勤"豁免名单,不影响考勤组主成员列表
|
||||
- `group update` 的 --group-id 必填,其余均可选,至少需指定一个修改项;仅需对要修改的字段赋値,未传字段会从已有配置自动补充;修改打卡地址/wifi/蓝牙等复杂子对象时用 `--group-vo` 传入完整 JSON;`--group-vo` 与单字段 flag 同时传入时单字段 flag 优先级更高
|
||||
- `group create` 的 `--name` 和 `--type` 必填,`--type` 必须为 FIXED/TURN/NONE 之一;type=FIXED 时 `--group-vo` 必须包含 `workDayClassList`(非空)和 `defaultClassId`(非 null);由于保存考勤组耗时较久,建议加 `--timeout 10`
|
||||
- `group filtered-get` 的 `--group-id` 必填,`--member/--position/--wifi/--bles` 均可选,默认 false。**返回结果中如含成员 userId 列表,必须调用 `dws contact user get --ids <userId1>,<userId2>,...`(支持逗号分隔传多个 ID),将 userId 转换为员工姓名后再输出;不得直接输出裸 userId。**
|
||||
- `summary` 必须同时传 `--user`、`--date`、`--stats-type`(`week` 周统计 / `month` 月统计);`--date` 支持 `YYYY-MM-DD` 或 `YYYY-MM-DD HH:mm:ss`
|
||||
- `rules` 的 `--date` 支持 YYYY-MM-DD 或 yyyy-MM-dd HH:mm:ss 两种格式
|
||||
- `selfsetting get/save` 的 `--setting-scene` 必须是 `checkRemind`、`fastCheck`、`checkResultNotify`、`lackRemind`、`personalAttendStatNotify`、`bossAttendStatNotify` 之一
|
||||
- `selfsetting get/save` 的 MCP 入参 `userId` 为必填;CLI 的 `--user` 也必填,必须显式传入目标用户 ID
|
||||
- `selfsetting save` 必须传入与 `--setting-scene` 对应的至少一个设置字段;不同场景的字段不能混用
|
||||
- `selfsetting save` 是敏感写操作,必须先执行 `selfsetting get` 查询当前值,并向用户展示目标用户、设置场景、修改字段、“当前值 → 新值”和最终命令参数摘要,等待用户明确确认;确认后才允许追加全局 `--yes` 执行保存。禁止未经确认直接执行或自动添加 `--yes`
|
||||
- `selfsetting get/save` 不需要传 `--corp-id` / `--op-user`,`corpId` 和 `opUserId` 由当前登录上下文自动补齐
|
||||
- `report columns` 无需额外参数,corpId 和 operatorId 由系统自动传入
|
||||
- `report query-data` 和 `report query-leave` 的 `--start/--end` 格式: yyyy-MM-dd HH:mm:ss,间隔不超过 32 天,最多 20 人
|
||||
- report 系列接口仅对管理员开放
|
||||
- 用户 ID 需从 `contact user get-self` 或 `aisearch person` 获取
|
||||
- 考勤组 ID 需从 `rules` 命令返回结果中获取
|
||||
- `vacation types` 无需任何参数,认证信息自动注入
|
||||
- `vacation balance` 的 `--users` 为目标员工 ID 列表,逗号分隔;`--leave-code` 选填,可通过 `vacation types` 获取
|
||||
- `vacation records` 的 `--start/--end` 使用 YYYY-MM-DD 格式,CLI 自动转换为毫秒时间戳;`--leave-code` 选填
|
||||
- `vacation balance` 和 `vacation records` 的认证参数(corpId、opUserId)由系统自动注入,无需手动传入
|
||||
- `vacation update-type` 的 `--leave-code` 必填;其他字段均为可选,但至少需传一个更新字段
|
||||
- `vacation update-type` 的 `--visibility-rules` 为 JSON 数组字符串,**HSF 反序列化无法区分「未传」与「空数组 `[]`」**,所以约定了哨兵语义:
|
||||
- 不传 → 不修改可见范围
|
||||
- `[{"type":"dept","visible":["-1"]}]` → **哨兵**,改为全公司可见(服务端落库为空)
|
||||
- `[{"type":"staff|dept|label|employee_type","visible":["id1",...]}, ...]` → 改为指定范围
|
||||
- 空数组 `[]`、`[{}]`、`visible` 为空等无效写法 → **CLI 报错**(服务端会静默忽略,故在 CLI 提前拦截)
|
||||
- **「清空可见范围」必须显式传哨兵值 `["-1"]`,不能用 `[]`**
|
||||
- `vacation save-balance` 是 **SET 接口**而非 ADD 接口:传入值会直接替换当前余额,而非累加
|
||||
- `vacation save-balance` 的 `--num` 输入为实际天数(如 8 或 7.5),内部会乘以 100 传给 MCP(如 800 或 750)
|
||||
- `vacation save-balance` 执行前需先调用 `vacation balance` 查询当前余额,再计算新值,避免误操作
|
||||
- `vacation save-balance` 的 `--start/--end` 使用 YYYY-MM-DD 格式,CLI 自动转换为毫秒时间戳
|
||||
- `vacation update-type` 和 `vacation save-balance` 执行前会展示待写入数据,需用户输入 yes/y 确认后提交
|
||||
- 假期编码为 UUID 格式字符串,可通过 `vacation types` 命令查询获取
|
||||
|
||||
### 改签打卡记录
|
||||
|
||||
**命令**: `dws attendance boss-check`
|
||||
|
||||
**功能**: 改签打卡记录,管理员可修改员工的打卡时间、打卡结果等信息。
|
||||
|
||||
**强制执行流程**: 此命令为写操作,Agent 调用时必须遵守以下流程:
|
||||
1. 先向用户展示待执行操作的完整参数摘要
|
||||
2. 展示变更摘要并等待用户明确确认
|
||||
3. 用户确认后,再传 `--user-say-yes=true` 执行命令
|
||||
4. **禁止**未经用户确认直接执行或自动添加 `--user-say-yes=true`
|
||||
|
||||
**参数**:
|
||||
| 参数 | 必填 | 说明 | 来源 |
|
||||
|------|------|------|------|
|
||||
| --plan-id | y* | 排班ID(与 --result-id 二选一) | `dws attendance schedule get` 返回的 `id` 字段 |
|
||||
| --result-id | y* | 打卡结果ID(与 --plan-id 二选一,优先使用) | **暂不支持**(record get 未返回此字段) |
|
||||
| --time | n | 新打卡时间,格式 yyyy-MM-dd HH:mm | - |
|
||||
| --result | n | 打卡结果枚举值 | - |
|
||||
| --absent-min | n | 缺勤时长(分钟) | - |
|
||||
| --remark | n | 备注,最长500字符 | - |
|
||||
| --user-say-yes | n | 用户已确认,跳过交互式确认提示 | - |
|
||||
|
||||
**获取 planId 步骤**:
|
||||
1. 查询排班记录:`dws attendance schedule get --users USER_ID --start DATE --end DATE`
|
||||
2. 从返回结果中找到对应打卡类型(OnDuty=上班,OffDuty=下班)的记录
|
||||
3. 使用该记录的 `id` 字段作为 `--plan-id` 参数
|
||||
4. 示例返回:`{"id": 948964045503, "checkType": "OffDuty", ...}` → `--plan-id 948964045503`
|
||||
|
||||
**打卡结果枚举值**:
|
||||
- Normal: 正常
|
||||
- TimesResultA: 迟到
|
||||
- TimesResultB: 早退
|
||||
- TimesResultC: 缺卡
|
||||
- TimesResultD: 迟到+早退
|
||||
- TimesResultE: 缺卡+早退
|
||||
- TimesResultF: 迟到+缺卡
|
||||
|
||||
**示例**:
|
||||
```bash
|
||||
# 步骤1:获取排班记录的 planId
|
||||
dws attendance schedule get --users 03642229451220076 --start 2026-05-13 --end 2026-05-13 -f json
|
||||
|
||||
# 步骤2:使用返回的 id 作为 --plan-id 改签
|
||||
# 假设返回 id: 948964045503 (OffDuty 下班打卡)
|
||||
dws attendance boss-check --plan-id 948964045503 --result Normal --user-say-yes
|
||||
|
||||
# 同时修改打卡时间
|
||||
dws attendance boss-check --plan-id 948964045503 --time "2026-05-13 18:00" --result Normal --yes
|
||||
```
|
||||
@@ -1,55 +0,0 @@
|
||||
# 日期范围与签到优先路由
|
||||
|
||||
> **【必读】日期范围严格计算规则 — 所有含 --start/--end 或 --from/--to 的命令均适用**
|
||||
>
|
||||
> **禁止随意猜测日期范围,必须按以下规则精确计算后再组装命令参数:**
|
||||
>
|
||||
> | 用户表达 | --start(含)| --end(含)| 说明 |
|
||||
> |---------|------------|------------|------|
|
||||
> | 本周 / 这周 / 当周 | 本周**周一** | 本周**周日** | 周一为一周的第一天,周日为最后一天 |
|
||||
> | 上周 / 上一周 | 上周**周一** | 上周**周日** | 同上,往前推一周 |
|
||||
> | 本月 / 这个月 / 当月 | 本月 **1 日** | 本月**最后一天**(28/29/30/31)| 必须计算当月实际天数 |
|
||||
> | 上月 / 上个月 | 上月 **1 日** | 上月**最后一天** | 同上,往前推一个月 |
|
||||
> | 今天 / 今日 | **今天** | **今天** | start == end |
|
||||
> | 昨天 | **昨天** | **昨天** | start == end |
|
||||
>
|
||||
> **必须遵守:**
|
||||
> 1. **本周一定是周一到周日**,严禁将"本周"解释为周一到周五或其他任意范围。
|
||||
> 2. **本月一定是 1 日到该月实际最后一天**,严禁将"本月"截断为 1 日到 28 日或其他固定天数。
|
||||
> 3. 计算日期时必须参考当前系统时间,不得使用硬编码或模糊估算。
|
||||
> 4. 如果用户指定了具体日期范围(如"4月1日到4月15日"),直接使用用户给定的范围,不套用上述规则。
|
||||
> 5. 日期格式统一按各命令要求:`shift list` / `check result` 等使用 `YYYY-MM-DD`;`report query-data` / `report query-leave` 等使用 `yyyy-MM-dd HH:mm:ss`(start 取当天 `00:00:00`,end 取当天 `23:59:59`)。
|
||||
|
||||
## 签到(checkin)— 优先路由
|
||||
|
||||
> **只要用户句中含"签到"二字(签到记录/签到数据/签到明细/外勤签到/导出签到/签到报表),就走本节,不要走 `check record`(打卡流水)。"签到" ≠ "打卡",签到是外勤场景的独立功能。**
|
||||
|
||||
### 导出 vs 查询 判断规则(必须先判断)
|
||||
|
||||
| 用户说 | 路由 |
|
||||
|--------|------|
|
||||
| 含"导出"/"报表"/"Excel"/"表格"/"生成"中**任何一个** + 含"签到" | → **导出签到报表**(走脚本) |
|
||||
| 不含上述导出关键词,仅"查签到"/"签到记录"/"看看签到" | → **查询签到记录**(走命令) |
|
||||
|
||||
> **示例**:"帮我导出最近一个月的签到记录" → 含"导出" → 走报表脚本
|
||||
> "查一下张三的签到记录" → 不含导出关键词 → 走查询命令
|
||||
|
||||
- **导出签到报表** → **必须先 `read_file` 读取 [attendance-report.md](./attendance-report.md) 后按其中的工作流执行(报表类型为"签到报表")**,对应脚本 `attendance_report_checkin.py`
|
||||
- **严禁**绕过 `attendance-report.md` 直接调用脚本
|
||||
- **严禁**自己手动分段调用 `dws attendance checkin records` 来拼数据,必须用脚本
|
||||
- **查询签到记录**(无需导出,仅查看) → `dws attendance checkin records`(数据源为 MCP 工具 `get_checkin_record`)
|
||||
|
||||
签到记录返回字段(`result.list` 数组,按 sortedProps 顺序):
|
||||
- `corpId`(string):企业 ID
|
||||
- `name`(string):用户名称
|
||||
- `userId`(string):用户 ID
|
||||
- `timestamp`(number):签到时间
|
||||
- `place`(string):签到地点
|
||||
- `detailPlace`(string):签到详细地点
|
||||
- `longitude`(number):签到地点经度
|
||||
- `latitude`(number):签到地点纬度
|
||||
- `remark`(string):备注信息
|
||||
- `imageList`(string[]):图片列表
|
||||
- `customers`(string):拜访客户
|
||||
- `checkinType`(string):签到类型
|
||||
- `mobileId`(string):设备 ID
|
||||
@@ -1,21 +0,0 @@
|
||||
# 自动化脚本
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
| 脚本 | 场景 | 用法 |
|
||||
|------|------|------|
|
||||
| [attendance_my_record.py](../scripts/attendance_my_record.py) | 查看我今天/指定日期的考勤记录 | `python attendance_my_record.py today` |
|
||||
| [attendance_team_shift.py](../scripts/attendance_team_shift.py) | 查询团队成员本周排班 | `python attendance_team_shift.py --users userId1,userId2` |
|
||||
| [attendance_report_common.py](../scripts/attendance_report_common.py) | 考勤报表导出公共模块(不可单独执行) | — |
|
||||
| [attendance_vacation_balance.py](../scripts/attendance_vacation_balance.py) | 假期余额列表 Excel 导出 | **禁止直接调用**,必须先读 [attendance-vacation.md](./attendance-vacation.md) 按工作流执行 |
|
||||
| attendance_report_detail.py | 考勤报表 — **明细粒度** | **禁止直接调用**,必须先读 [attendance-report.md](./attendance-report.md) 按工作流执行 |
|
||||
| attendance_report_monthly.py | 考勤报表 — **月度汇总** | **禁止直接调用**,必须先读 [attendance-report.md](./attendance-report.md) 按工作流执行 |
|
||||
| attendance_report_daily.py | 考勤报表 — **每日统计** | **禁止直接调用**,必须先读 [attendance-report.md](./attendance-report.md) 按工作流执行 |
|
||||
| attendance_report_record.py | 考勤报表 — **考勤记录**(补卡/请假/出差/外出) | **禁止直接调用**,必须先读 [attendance-report.md](./attendance-report.md) 按工作流执行 |
|
||||
| attendance_schedule_import.py | 排班导入(含校验、回显、执行) | **禁止直接调用**,必须先读 [attendance-schedule.md](./attendance-schedule.md) 按工作流执行 |
|
||||
| attendance_schedule_export.py | 排班查询导出(分批查询、排班表 Excel) | **禁止直接调用**,必须先读 [attendance-schedule.md](./attendance-schedule.md) 按工作流执行 |
|
||||
|
||||
> 说明:
|
||||
> - `attendance_report_*.py` 四个脚本由 [attendance-report.md](./attendance-report.md) 工作流编排使用:detail/monthly/daily 自动处理 `--users` 超过 20 人分批、`--start/--end` 超过 32 天按月切片;record 自包含数据查询+解析+Excel 生成(补卡/请假/出差/外出审批记录)
|
||||
> - `attendance_schedule_import.py` 由 [attendance-schedule.md](./attendance-schedule.md) 排班导入工作流编排使用,自动处理考勤组校验、班次校验、排班回显确认
|
||||
> - `attendance_schedule_export.py` 由 [attendance-schedule.md](./attendance-schedule.md) 排班查询导出工作流编排使用,自动处理分批查询(超 20 人自动分批)、userId→姓名转换、classId→班次名称转换、输出排班表格式 Excel
|
||||
@@ -1,148 +0,0 @@
|
||||
# 核心工作流
|
||||
|
||||
## 核心工作流
|
||||
|
||||
```bash
|
||||
# 导入排班记录
|
||||
dws attendance schedule import --groupId 123456 \
|
||||
--scheduleVOS '[{"userId":"user001","classId":123,"workDate":"2026-04-22","checkBeginTime":"09:00","checkEndTime":"18:00"}]' \
|
||||
--user-say-yes --format json
|
||||
|
||||
# 获取排班记录 — 禁止直接调用,必须走 attendance-schedule.md 排班查询导出工作流
|
||||
# python scripts/attendance_schedule_export.py --users user001,user002 --start 2026-04-01 --end 2026-04-30
|
||||
|
||||
# 查询可管理的班次列表
|
||||
dws attendance class search --format json
|
||||
dws attendance class search --query "早班" --filter-type MINE_OWN --format json
|
||||
|
||||
# 查询班次详情
|
||||
dws attendance class get --class-id 1170996821 --format json
|
||||
|
||||
# 更新班次
|
||||
dws attendance class update --class-id 1170996821 --name "新早班" --timeout 10 --format json
|
||||
dws attendance class update --class-id 1170996821 --class-vo '{"sections":[{"times":[{"checkType":"OnDuty","checkTime":"08:30","across":0},{"checkType":"OffDuty","checkTime":"17:30","across":0}]}]}' --timeout 10 --format json
|
||||
|
||||
# 查询补卡规则
|
||||
dws attendance adjustment search --page 1 --limit 20 --format json
|
||||
dws attendance adjustment search --query "标准" --page 1 --limit 20 --format json
|
||||
|
||||
# 查询补卡规则详情
|
||||
dws attendance adjustment get --adjustment-id 12345 --format json
|
||||
|
||||
# 查询加班规则
|
||||
dws attendance overtime search --page 1 --limit 20 --format json
|
||||
|
||||
# 查询加班规则详情
|
||||
dws attendance overtime get --overtime-id 12345 --format json
|
||||
|
||||
# 查询考勤组列表
|
||||
dws attendance group search --query "研发" --page 1 --limit 20 --format json
|
||||
dws attendance group search --type FIXED --page 1 --limit 20 --format json
|
||||
|
||||
# 查询考勤组全量信息
|
||||
dws attendance group get --group-id 123456 --format json
|
||||
|
||||
# 按需查询考勤组成员/地址/蓝牙/Wifi
|
||||
dws attendance group filtered-get --group-id 123456 --member --format json
|
||||
dws attendance group filtered-get --group-id 123456 --position --wifi --format json
|
||||
|
||||
# 更新考勤组成员
|
||||
dws attendance group update-members --group-id 123456 --add-users userId1,userId2 --timeout 10 --format json
|
||||
dws attendance group update-members --group-id 123456 --remove-users userId1 --timeout 10 --format json
|
||||
dws attendance group update-members --group-id 123456 --add-depts deptId1 --remove-users userId2 --timeout 10 --format json
|
||||
|
||||
# 更新考勤组配置
|
||||
dws attendance group update --group-id 123456 --name "研发考勤组" --timeout 10 --format json
|
||||
dws attendance group update --group-id 123456 --classIds '[1374234767]' --timeout 10 --format json
|
||||
dws attendance group update --group-id 123456 --group-vo '{"positions":[{"title":"总部","address":"北京市","latitude":39.9,"longitude":116.4,"offset":200}]}' --timeout 10 --format json
|
||||
|
||||
# 创建考勤组
|
||||
dws attendance group create --name "研发考勤组" --type FIXED --group-vo '{"defaultClassId":1170996821,"workDayClassList":[0,1170996821,0,0,0,0,0]}' --timeout 10 --format json
|
||||
dws attendance group create --name "自由工时分组" --type NONE --timeout 10 --format json
|
||||
|
||||
# 查看考勤统计摘要
|
||||
dws attendance summary --user <USER_ID> --date 2026-03-12 --stats-type week --format json
|
||||
|
||||
# 查看考勤组和规则
|
||||
dws attendance rules --date 2026-03-14 --format json
|
||||
|
||||
# 查看指定用户的打卡提醒设置
|
||||
dws attendance selfsetting get --setting-scene checkRemind --user <USER_ID> --format json
|
||||
|
||||
# 查看指定用户的极速打卡设置
|
||||
dws attendance selfsetting get --setting-scene fastCheck --user <USER_ID> --format json
|
||||
|
||||
# 开启指定用户的打卡结果通知
|
||||
dws attendance selfsetting save --setting-scene checkResultNotify --user <USER_ID> --check-result-msg 1 --format json
|
||||
|
||||
# 更新指定用户的极速打卡设置
|
||||
dws attendance selfsetting save --setting-scene fastCheck --user <USER_ID> \
|
||||
--onduty-check-type 3 --voice-remind-switch=true --format json
|
||||
|
||||
# 获取考勤字段列表(管理员)
|
||||
dws attendance report columns --format json
|
||||
|
||||
# 根据字段查询考勤数据(管理员)
|
||||
dws attendance report query-data --users userId1,userId2 \
|
||||
--columns 1001,1002 --start "2026-03-01 00:00:00" --end "2026-03-31 23:59:59" --format json
|
||||
|
||||
# 查询用户假期数据(管理员)
|
||||
dws attendance report query-leave --users userId1,userId2 \
|
||||
--leave-names 年假,病假 --start "2026-03-01 00:00:00" --end "2026-03-31 23:59:59" --format json
|
||||
|
||||
# 查看假期规则列表
|
||||
dws attendance vacation types --format json
|
||||
|
||||
# 查看指定员工假期余额
|
||||
dws attendance vacation balance --users userId1,userId2 --format json
|
||||
|
||||
# 查看指定员工某类假期余额
|
||||
dws attendance vacation balance --users userId1 --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 --format json
|
||||
|
||||
# 查看指定员工假期余额变更记录
|
||||
dws attendance vacation records --user USER_ID --start 2026-04-01 --end 2026-04-22 --format json
|
||||
|
||||
# 更新假期规则名称
|
||||
dws attendance vacation update-type --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
|
||||
--name "事假(修改版)" --format json
|
||||
|
||||
# 更新假期单位
|
||||
dws attendance vacation update-type --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
|
||||
--unit hour --per-hours 8 --format json
|
||||
|
||||
# 改为指定部门可见
|
||||
dws attendance vacation update-type --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
|
||||
--visibility-rules '[{"type":"dept","visible":["1","2","3"]}]' --format json
|
||||
|
||||
# 改为全公司可见(哨兵约定:必须显式传 "-1",不能传空数组 [])
|
||||
dws attendance vacation update-type --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
|
||||
--visibility-rules '[{"type":"dept","visible":["-1"]}]' --format json
|
||||
|
||||
# 设置员工假期余额完整流程
|
||||
# 1. 查询当前余额
|
||||
dws attendance vacation balance --users user001 \
|
||||
--leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 --format json
|
||||
|
||||
# 2. 根据查询结果计算新值(如当前5天,要设置为8天)
|
||||
|
||||
# 3. 执行设置(SET操作,会替换当前余额)
|
||||
dws attendance vacation save-balance --target user001 \
|
||||
--leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
|
||||
--num 8 --reason "年度发放" --start 2024-01-01 --end 2024-12-31 --format json
|
||||
|
||||
# 增加员工假期余额完整流程(ADD场景)
|
||||
# 1. 查询当前余额(假设返回5天)
|
||||
dws attendance vacation balance --users user001 \
|
||||
--leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 --format json
|
||||
|
||||
# 2. 计算增加后的新值(5 + 3 = 8天)
|
||||
|
||||
# 3. 设置新总额度
|
||||
dws attendance vacation save-balance --target user001 \
|
||||
--leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
|
||||
--num 8 --reason "绩效奖励发放3天" --format json
|
||||
|
||||
# 查询签到记录
|
||||
dws attendance checkin records --operator-staff-id op001 --staff-ids user001,user002 \
|
||||
--start "2026-04-01 00:00:00" --end "2026-04-07 00:00:00" --format json
|
||||
```
|
||||
@@ -1,11 +0,0 @@
|
||||
# 考勤 (attendance) 命令参考
|
||||
|
||||
> 渐进式兼容入口:新任务优先从 [考勤能力索引](./attendance-index.md) 选择专题。
|
||||
|
||||
| 任务 | 参考 |
|
||||
|---|---|
|
||||
| 日期范围与签到优先路由 | [attendance-routing.md](./attendance-routing.md) |
|
||||
| 核心命令 | [attendance-commands.md](./attendance-commands.md) |
|
||||
| 排班、报表、假期 | [排班](./attendance-schedule.md) · [报表](./attendance-report.md) · [假期](./attendance-vacation.md) |
|
||||
| 意图与流程 | [意图判断](./attendance-intent.md) · [核心工作流](./attendance-workflow.md) |
|
||||
| 上下文、注意事项、脚本、约束 | [上下文](./attendance-context.md) · [注意事项](./attendance-notes.md) · [脚本](./attendance-scripts.md) · [严格约束](./attendance-constraints.md) |
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
name: dingtalk-calendar
|
||||
description: 钉钉日历与会议室。Use when 用户说 约会议/查日程/订会议室/查闲忙/加参会人/改期/取消会议/今天的日程/本周日程/共同空闲。视频会议发起/邀请入会/会中控制当前 CLI 不支持,应提示在钉钉客户端操作;AI 听记走 dingtalk-minutes,待办任务走 dingtalk-todo。命令前缀:dws calendar。
|
||||
cli_version: ">=0.2.14"
|
||||
description: 钉钉日历与会议室。Use when 用户说 约会议/查日程/订会议室/查闲忙/加参会人/改期/取消会议/今天的日程/本周日程/共同空闲。不做视频会议发起/邀请入会/会中控制(走 dingtalk-misc)、AI 听记(走 dingtalk-minutes)、待办任务(走 dingtalk-todo)。命令前缀:dws calendar。
|
||||
metadata:
|
||||
cli_version: ">=0.2.14"
|
||||
category: product
|
||||
stability: experimental
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
@@ -12,20 +11,16 @@ metadata:
|
||||
|
||||
# 钉钉日历 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
> **CRITICAL — 执行任何 `dws` 操作前,MUST 先用 Read 工具完整读取 [`dws-shared`](../dws-shared/SKILL.md)。**该轻量文件包含全局执行契约、安全底线及 shared references 的按需加载导航;不要预加载其全部 references。
|
||||
|
||||
> 命令参考:[calendar.md](references/calendar.md);剧本:[03-meeting.md](references/03-meeting.md)。
|
||||
|
||||
<!-- VISIBLE_SHORTCUTS_START -->
|
||||
## Shortcuts(无专用脚本/recipe 时优先)
|
||||
|
||||
以下 shortcut 来自独立于 Runtime Schema 的公开 catalog。先按本 skill 的意图表、脚本和 recipe 路由:存在精确覆盖该场景的专用脚本/recipe 时按其执行;否则用户意图命中时,shortcut 优先于手写原子命令。用 `dws shortcut list --service calendar --format json` 读取参数、约束、风险和示例,并以 `dws calendar <shortcut> --help` 核对当前 Cobra flags;不要对 `+` 路径调用 `dws schema`。
|
||||
以下命令来自独立于 Runtime Schema 的公开 catalog。先运行 `dws shortcut list --service calendar --format json` 读取完整契约,再用 `dws calendar <shortcut> --help` 核对 flags;不要对 `+` 路径调用 `dws schema`。
|
||||
|
||||
| Shortcut | 风险 | 适用场景 |
|
||||
|---|---|---|
|
||||
@@ -58,7 +53,7 @@ metadata:
|
||||
| "今天 / 明天 / 本周日程" | `python scripts/calendar_today_agenda.py [today\|tomorrow\|week]` |
|
||||
| "约会议(含参会人 + 会议室)" | `python scripts/calendar_schedule_meeting.py --title "<主题>" --start "<起>" --end "<止>" [--users <ids>] [--book-room]` |
|
||||
| "多人共同空闲" | `python scripts/calendar_free_slot_finder.py --users <ids> --date <yyyy-MM-dd>` |
|
||||
| "查闲忙" | `dws calendar event list --start "<ISO>" --end "<ISO>"` |
|
||||
| "查闲忙" | `dws calendar busy search --users <userIds> --start "<ISO>" --end "<ISO>"` |
|
||||
| "加参会人" / "订房" / "取消" | `dws calendar attendee add` / `room add` / `event delete` |
|
||||
|
||||
## 标准 SOP(必遵流程)
|
||||
@@ -81,7 +76,7 @@ metadata:
|
||||
|
||||
1. **解析与会人(必须)**:对每个姓名 `dws aisearch person --keyword "<姓名>" --dimension name --format json` 取 `userId`,多人逗号拼接。
|
||||
2. **执行(必须)**:`dws calendar event create --title "<主题>" --start "<ISO>" --end "<ISO>" --attendees <userId1,userId2> --format json`(按需加 `--location`/`--desc`/`--rooms`)。
|
||||
3. **验证(必须)**:从返回取 `eventId`,可 `dws calendar event list --start "<ISO>" --end "<ISO>" --format json` 复核。
|
||||
3. **验证(必须)**:从返回 `result.id` 取日程 ID(下游参数语义称 `eventId`),再执行 `dws calendar event list --start "<ISO>" --end "<ISO>" --format json` 复核标题、描述和时段。
|
||||
|
||||
**禁止**:跳过与会人 userId 解析直接传姓名、编造会议室 roomId。
|
||||
|
||||
@@ -99,22 +94,22 @@ metadata:
|
||||
## 执行硬约束
|
||||
|
||||
- 多轮日程任务必须保留 `eventId`,后续加人、移人、订房、换房、改描述、删除都基于同一个 `eventId` 执行;不要重新创建重复日程。
|
||||
- 用户明确授权“任意空闲会议室”时,`room search` 返回候选后选择第一个可预订且不需要自定义审批的 `roomId` 执行 `room add`;用户给了地点、容量或设备条件时按条件过滤。
|
||||
- 用户明确说"帮我订一个空闲会议室"时,`room search` 返回可用会议室后直接选择第一个可预订且不需要自定义审批的 `roomId` 执行 `room add`;不要把选择权抛回用户导致任务停住。
|
||||
- 已有日程订房:`dws calendar room search --start ... --end ... --format json` → `dws calendar room add --event <EVENT_ID> --rooms <ROOM_ID> --format json` → `event get` 或 `room/busy` 验证。
|
||||
- 换会议室:先 `room delete --event <EVENT_ID> --rooms <OLD_ROOM_ID>`,再 `room add --event <EVENT_ID> --rooms <NEW_ROOM_ID>`,最后回查;不要只更新 `--location`。
|
||||
- 参会人变化用 `attendee add/delete`,日程描述变化用 `event update --desc`,删除日程用 `event delete --id`。用户当前消息已明确要求删除/取消时可直接执行;否则先确认。
|
||||
- 脚本失败或参数不完整时,查明缺失参数后改用明确的 `dws calendar event/attendee/room` 命令完成同一流程。
|
||||
- 脚本失败或参数不完整时,立即降级到明确的 `dws calendar event/attendee/room` 命令,不要停在"我要查看用法"。
|
||||
- 所有 dws 命令带 `--format json`;查询时间必须显式 `--start` / `--end`。
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
- 视频会议发起 / 入会链接 / 邀请入会 / 会中控制 → 当前 CLI 不支持,请在钉钉客户端操作;预约日程仍走 `calendar`
|
||||
- 视频会议发起 / 入会链接 / 邀请入会 / 会中控制 → 切到 `dingtalk-misc`(`references/conference.md`)
|
||||
- 会后摘要 / 待办 → 切到 `dingtalk-minutes`
|
||||
- 参会人按人名 → 先用 `dingtalk-aisearch` 解析
|
||||
|
||||
## 注意
|
||||
|
||||
`schedule-meeting` 必须读 [03-meeting.md](references/03-meeting.md) 中的「两准则」「搜房失败硬门禁」,禁止假设 `roomId`。
|
||||
## 局部意图与 Recipe
|
||||
## 局部意图与短流程
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md);[Lite Recipe](references/lite-recipes.md)。
|
||||
- [局部意图消歧](references/intent-guide.md);[短流程](references/lite-recipes.md)。
|
||||
|
||||
@@ -1,47 +1,56 @@
|
||||
# 会议管理(日程与会议室)
|
||||
|
||||
> lite recipe(`list-today-meetings`、`check-users-busy`)见 [lite-recipes.md](./lite-recipes.md);视频会议发起、邀请入会与会中控制当前 CLI 不支持,请在钉钉客户端操作。列表类操作须遵循 [calendar.md](./calendar.md) **「CLI 命令树与黄金路径」**,禁止无子命令的 `dws calendar` 或臆造 `calendar list`(见该文 **「反模式(禁止)」**)。预约会议须遵循本文件的时段、会议室与失败收束规则。
|
||||
> lite recipe(`list-today-meetings`、`check-users-busy`)见 [lite-recipes.md](./lite-recipes.md);`start-conference`、`invite-participant`、`share-screen` 见 `dingtalk-misc`(`references/conference.md`)。列表类操作须遵循 [calendar.md](./calendar.md) **「CLI 命令树与黄金路径」**,禁止无子命令的 `dws calendar` 或臆造 `calendar list`(见该文 **「反模式(禁止)」**)。**`schedule-meeting` 不做内联**:须读本文件 **「两准则」「搜房失败硬门禁」** 及下表 **schedule-meeting** 行全文。
|
||||
> **听记、会后待办、摘要分享** 见 `dingtalk-minutes/references/07-minutes.md`。
|
||||
|
||||
## 日程与会议室两准则(强制)
|
||||
|
||||
1. **时段**:用户已明确会议起止时间 → **禁止**自动改期、禁止用闲忙结果或「推荐时段」覆盖用户给定时段;只能在此时段内建日程、订会议室;该时段内无可用或指定资源不可用 → **立刻如实告知**,不得偷偷换时间段再试。
|
||||
2. **会议室**:用户点名具体会议室 → **禁止**换其他会议室;在用户给定时段内查无该房 → **立刻告知**。**用户未给出时段时,必须先显式向用户追问具体开始/结束时间;禁止默认用「当前时刻至当日 23:59:59」之类窗口代查。** **`calendar_schedule_meeting.py`**:仅需 `--title`、`--start`、`--end`;先创建日程,再邀请参会人,最后搜房/订房。未给会议室范围时,`--book-room` 为 **单次**无 `--group-id`、带 `--start` / `--end` 的 `room search`,取返回的**第一个**会议室并 `room add`;无结果则告警、不删日程。**若用户明确限定楼层/楼宇/园区/分组,应先用 `room list-groups` 解析允许的 `group-id`,再把这些 `group-id` 传给脚本 `--room-group-id`(或手工 `room search --group-id ...`);脚本只会在这些 group 内查找,若无空房则直接返回。对于同一地点(同园区/楼栋/楼层)的会议室,必须优先锁定最相关、最贴近该地点的承载 group;该 group 查无 roomId/空房,即可判定该地点当前时段无可订会议室,**不得**再去别的无关 group 继续碰运气,因为同一地点的会议室只会挂在其所属 group 下。** **在组织内、按早停规则已把应查的分组(或未限范围时的根目录一次查询)全部查完仍无可用会议室时,必须立即向用户说明「当前时段没有可预订的会议室」或「范围内未检索到可用会议室/资源」并收束,禁止继续扩区、换参重试或虚构有房。** 手工 `room search` **禁止**为试出空闲擅自改日或拉长时间窗。
|
||||
2. **会议室**:用户点名具体会议室 → **禁止**换其他会议室;在用户给定时段内查无该房 → **立刻告知**。**用户未给出时段时,必须先显式向用户追问具体开始/结束时间;禁止默认用「当前时刻至当日 23:59:59」之类窗口代查。** **`calendar_schedule_meeting.py`**:仅需 `--title`、`--start`、`--end`;先创建日程,再邀请参会人,最后搜房/订房。未给会议室范围时,`--book-room` 为 **单次**无 `--group-id` 的 `room search --available`,取返回的**第一个**会议室并 `room add`;无结果则告警、不删日程。**若用户明确限定楼层/楼宇/园区/分组,应先用 `room list-groups` 解析允许的 `group-id`,再把这些 `group-id` 传给脚本 `--room-group-id`(或手工 `room search --group-id ...`);脚本只会在这些 group 内查找,若无空房则直接返回。对于同一地点(同园区/楼栋/楼层)的会议室,必须优先锁定最相关、最贴近该地点的承载 group;该 group 查无 roomId/空房,即可判定该地点当前时段无可订会议室,**不得**再去别的无关 group 继续碰运气,因为同一地点的会议室只会挂在其所属 group 下。** **在组织内、按早停规则已把应查的分组(或未限范围时的根目录一次查询)全部查完仍无可用会议室时,必须立即向用户说明「当前时段没有可预订的会议室」或「范围内未检索到可用会议室/资源」并收束,禁止继续扩区、换参重试或虚构有房。** 手工 `room search` **禁止**为试出空闲擅自改日或拉长时间窗。
|
||||
|
||||
### 会议室搜索早停
|
||||
|
||||
> 专用于 `calendar room list-groups` / `room search` / `room add`;与通用规范「无新参数不重复 search」一致。
|
||||
|
||||
**`room search` 时间段模式**(传入 `--start` / `--end`):返回的是在**该整段时段内**可被预订的空闲会议室(不是「有一段空就算」);脚本与用户手工选房均应沿用同一时间窗,避免误以为分段凑满即等价于整段可用。
|
||||
**`room search --available`**(与传入的 `--start` / `--end` 配对):返回的是在**该整段时段内**可被预订的空闲会议室(不是「有一段空就算」);脚本与用户手工选房均应沿用同一时间窗,避免误以为分段凑满即等价于整段可用。
|
||||
|
||||
**`dws calendar room search` 合法参数**(与 [calendar.md](./calendar.md) 一致):按需使用 `--start`、`--end`、`--group-id`、`--room-name`、`--limit`、`--page` 和全局 `--format json`;**禁止使用 `--query` 或 `--available`**,否则会报 unknown flag。传 `--start` / `--end` 即进入可用会议室搜索模式。
|
||||
**`dws calendar room search` 合法参数**(与 [calendar.md](./calendar.md) 一致):仅 `--start`、`--end`、`--group-id`(可选)、`--available`(可选)、`--format json` 等;**禁止使用 `--query`**,否则会报 `unknown flag: --query`。
|
||||
|
||||
**地点归组早停**:若用户给的是同一地点范围(如“西溪园区 C6 楼 3-5 层”或具体楼层/楼栋),先用 `room list-groups` 找到**最相关的承载 group**(通常是该楼层;若楼层下无会议室则为直接挂会议室的上一级)。在这个最相关 group 下查不到有效 `rooms[].roomId` 或空房时,**不得**再跳去别的同级/异地 group 继续搜;同一地点的会议室不会散落在别的 group 里。只有用户明确放宽到别的楼层、楼栋或园区,才能重新解析新的 group 并继续。
|
||||
|
||||
**用户点名具体会议室(如「C6-4-06-N / 贡嘎山」)**:**不要**尝试 `room search --query "<名称>"`;**禁止**把用户原文(含「C6-4-06-N 贡嘎山」整句)或展示名当作 `room add --rooms` 的 `roomId`。用户输入**几乎从不会是**有效 `roomId`。须先 `dws calendar room list-groups` 定位所在楼层/分组的 `group-id`,再 `dws calendar room search --start "<ISO>" --end "<ISO>" --group-id <GROUP_ID> --format json`(带时间范围即查询可用会议室),在返回 `rooms[]` 中对 `roomName`、`name` 等与用户表述匹配,**仅**取 JSON 里的 `roomId`(典型为小写十六进制串,长度以返回为准),最后 `dws calendar room add --event <eventId> --rooms <roomId>`。该时段无匹配或房间忙 → 如实告知;**禁止**为通过校验而编造、拼接或猜测 `roomId`。
|
||||
**用户点名具体会议室(如「C6-4-06-N / 贡嘎山」)**:**不要**尝试 `room search --query "<名称>"`;**禁止**把用户原文(含「C6-4-06-N 贡嘎山」整句)或展示名当作 `room add --rooms` 的 `roomId`。用户输入**几乎从不会是**有效 `roomId`。须先 `dws calendar room list-groups` 定位所在楼层/分组的 `group-id`,再 `dws calendar room search --start "<ISO>" --end "<ISO>" --group-id <GROUP_ID> [--available] --format json`,在返回 `rooms[]` 中对 `roomName`、`name` 等与用户表述匹配,**仅**取 JSON 里的 `roomId`(典型为小写十六进制串,长度以返回为准),最后 `dws calendar room add --event <eventId> --rooms <roomId>`。该时段无匹配或房间忙 → 如实告知;**禁止**为通过校验而编造、拼接或猜测 `roomId`。
|
||||
|
||||
### 搜房失败硬门禁(园区/范围搜尽仍无 roomId)
|
||||
|
||||
在用户限定的园区、楼宇、楼层或固定分组内,已按早停规则**逐组 `room search` 查完**仍得不到任何有效 `rooms[].roomId`(或无任何空闲房)→ **立即停止**,向用户**明确报错/失败结论**(例如:该时段在指定范围内未检索到可预订会议室或无法获得 roomId),当前预订链路结束。
|
||||
在用户限定的园区、楼宇、楼层或固定分组内,已按早停规则**逐组 `room search` 查完**仍得不到任何有效 `rooms[].roomId`(或无任何空闲房)→ **立即停止**,向用户**明确报错/失败结论**(例如:该时段在指定范围内未检索到可预订会议室或无法获得 roomId),**本回合订房流程结束**。
|
||||
|
||||
**失败处理**:明确说明“指定范围/指定会议室在该时段未找到可预订会议室,因此当前无法完成预订”。只有用户同意放宽地点范围、改时间或接受不订会议室后,才可按新条件继续。
|
||||
**用户汇报硬门禁**:一旦触发上面的失败条件,**下一条对外输出必须直接面向用户汇报结果**,不得继续在会话里自言自语式地延长推理。允许的后续只有两类:
|
||||
1. **失败汇报**:明确说明“指定范围/指定会议室在该时段未找到可预订会议室,因此当前无法完成预订”
|
||||
2. **确认放宽条件**:仅在需要继续推进时,明确问用户是否放宽地点范围、改时间或接受不订会议室
|
||||
|
||||
空结果只表示当前授权范围内没有返回合法 `roomId`;不要推测隐藏映射、环境差异或未经用户授权的新搜索范围。
|
||||
以下表述/行为视为**违例**:继续写“让我再试一次”“也许是 Mock/测试环境”“可能存在预设 roomId 映射”“我去别的 group 看看”“我换个时间验证一下”“我先看看脚本/示例还能不能推断出 roomId”。
|
||||
|
||||
以下行为**一律禁止**(与是否「想多试一次」无关):编造/假设 `roomId` 格式做「预订测试」;在**没有**合法 `roomId` 时调用 `room add` 试探错误详情;拉 `event get` / 日程详情等试图**绕开** `room search` 推断 roomId;换无关园区、扩大关键词、换工具名做未经用户授权的新搜索。
|
||||
|
||||
出现空结果、`roomId invalid` 或授权范围查尽时,停止当前预订链路;不得沿原假设重复搜索。后续只能报告失败,或在用户确认新范围/新时间后重新搜索。
|
||||
**失败后强制回读**:若出现以下任一信号,下一步**必须重新读取本文件本节与 `schedule-meeting` recipe**,不得沿着当前假设继续试:
|
||||
1. 连续 **2 次** `room search` 空结果/无 `roomId`
|
||||
2. 任意一次 `roomId invalid`
|
||||
3. 已开始尝试「换园区 / 换楼栋 / 看 event 详情 / 猜 roomId」
|
||||
|
||||
回读后只允许二选一:
|
||||
1. **报错收束**:已搜尽允许范围/整园仍无 `roomId` 或无空房
|
||||
2. **用户确认**:明确询问是否放宽范围、换时间,或接受不订会议室
|
||||
|
||||
| # | 规范 |
|
||||
|---|------|
|
||||
| 1 | **一键脚本**:`calendar_schedule_meeting.py` 做「建日程 → 加人 → 可选搜房/订房」;未限范围时可直接 `--book-room`,脚本按根目录单次带 `--start` / `--end` 的 `room search` 订第一家。**若搜房失败,脚本应输出明确失败原因并返回非零退出码,促使上层立即向用户汇报,而不是继续试探。** |
|
||||
| 2 | **要限范围/具名**:先 `list-groups` 解析允许的 `group-id`。若用户说的是同一地点(同园区/楼栋/楼层),应优先锁定**最相关的承载 group** 并只查它;该 group 无结果即可按该地点无房收束,不再试别的无关 group。仅当用户明确给出多个允许地点时,才分别对这些 group 各 **1 次**带 `--start` / `--end` 的 `room search` 再 `room add` |
|
||||
| 3 | **禁止**:无新信息时反复切换参数、父组子组试探、在最相关 group 无结果后改搜别的同级/异地 group、超 100 条后仍根分组或未授权区域全量搜;**禁止**对 `room search` 使用不存在的 `--query` 或 `--available` |
|
||||
| 1 | **一键脚本**:`calendar_schedule_meeting.py` 做「建日程 → 加人 → 可选搜房/订房」;未限范围时可直接 `--book-room`,脚本按根目录单次 `room search --available` 订第一家。**若搜房失败,脚本应输出明确失败原因并返回非零退出码,促使上层立即向用户汇报,而不是继续试探。** |
|
||||
| 2 | **要限范围/具名**:先 `list-groups` 解析允许的 `group-id`。若用户说的是同一地点(同园区/楼栋/楼层),应优先锁定**最相关的承载 group** 并只查它;该 group 无结果即可按该地点无房收束,不再试别的无关 group。仅当用户明确给出多个允许地点时,才分别对这些 group 各 **1 次** `room search --available` 再 `room add` |
|
||||
| 3 | **禁止**:无新信息时反复 `--verbose`、反复切 `--available`、父组子组试探、在最相关 group 无结果后改搜别的同级/异地 group、超 100 条后仍根分组或未授权区域全量搜;**禁止**对 `room search` 使用不存在的 `--query` |
|
||||
| 4 | **`roomId` 门禁**:`room add --rooms` **只能**填 `room search` 返回 JSON 中的 `rooms[].roomId`;**禁止**将用户说的会议室名、编号文案、或「假 UUID / 试数字」当作 `roomId` |
|
||||
| 5 | **授权范围无结果即收束**:在用户允许的搜索范围内仍无可用会议室或有效 `roomId`,说明当前范围不可预订;不得假设 ID、用 `room add` 试探或绕路推断 |
|
||||
| 6 | **无效 ID 恢复**:遇到 `roomId invalid` 时停止预订,回到 `room search` 的真实返回;若范围已查尽则报告无可用房,否则先确认是否放宽地点或时间 |
|
||||
| 5 | **全量无结果即收束**:在用户允许的搜索范围内(含**整园/全 campus** 若用户要求已逐组查尽)仍无任何可用会议室或有效 `roomId` → **直接报错/告知失败并结束订房**,且**下一条消息必须汇报给用户**;**不得**假设 ID、不得用 `room add` 试探、不得绕路查日程、不得继续自说自话分析 Mock/测试环境 |
|
||||
| 6 | **失败触发回读**:连续 2 次空结果、任意一次 `roomId invalid`、或开始换园区/绕路时 → **必须回读本节**;回读后只允许「报错收束」或「向用户确认是否放宽条件」 |
|
||||
|
||||
| Recipe | 行动指南(固定路线) |
|
||||
| ------------------ | ------------------- |
|
||||
| schedule-meeting | **未给时段且仅说“发起/开个会”**时不走本 recipe;当前 CLI 不支持实时视频会议,应告知用户在钉钉客户端操作。有预约日程意图但缺时段时先确认开始和结束时间。时段明确后固定执行:1. `calendar event create`;2. 有参会人则 `calendar attendee add`;3. 再处理会议室。无明确地点范围可用 `calendar_schedule_meeting.py --book-room`;有楼宇/楼层范围时先 `room list-groups` 锁定最相关 group;点名会议室时用 `room search` 返回的 `rooms[].roomId` 调 `room add`。授权范围内无空房则报告不可预订;需要扩大范围或改时间时先取得用户同意。 |
|
||||
| schedule-meeting | **见上文「两准则」**、**「搜房失败硬门禁」**。**未给时段且仅说「发起/开个会」**→ 不走本 recipe,走 lite recipe `start-conference`。**未给时段但有预约意图**("安排""约""定"等词):追问具体开始/结束时间。**已有时段后**,按固定顺序执行:1. `dws calendar event create` 建日程;2. 有参会人则 `dws calendar participant add`;3. 再处理会议室。**无明确会议室范围**:可直接 `python scripts/calendar_schedule_meeting.py --title "<主题>" --start "<起始>" --end "<结束>" [--users <userIds>] [--book-room] [--dry-run]`。**有明确范围(某楼/层)**:先 `dws calendar room list-groups`,锁定该地点**最相关的承载 group**;若只有一个地点,`--room-group-id` 应只传这个最相关 group,**不要**把同楼内多个楼层 group 打包传入碰运气。只有用户明确给出多个允许地点时,才把这些 `group-id` 一并传给 `python scripts/calendar_schedule_meeting.py ... --book-room --room-group-id "<id1,id2,...>"`。**用户点名具体会议室**:须手工 `dws calendar room search --start "<ISO>" --end "<ISO>" --group-id <GROUP_ID> [--available] --format json`(**无** `--query`),在 JSON 中匹配名称取 **`rooms[].roomId` 唯一真值** → `dws calendar room add --event <eventId> --rooms <roomId>`;**不得**把用户输入的会议室名当 `roomId`。**一旦连续 2 次空结果 / 任意一次 `roomId invalid`**:**必须回读本节并立即收束判断**;若整园/限定范围内搜尽仍无 roomId 或无空房 → **下一条消息必须直接向用户汇报失败结论**;否则只能向用户确认是否放宽范围/改时间。**禁止**假设 roomId、禁止无 ID 调用 `room add`、禁止用日程详情绕路、禁止继续猜测 Mock/测试环境。细则见「会议室搜索早停」。 |
|
||||
| reschedule-meeting | 1. `calendar event list --start "<起始ISO>" --end "<结束ISO>"` → 取 `eventId` 2. `calendar event update --id <eventId> --start "<新起始ISO>" --end "<新结束ISO>"` 更新时间 3. `chat search --query "<群名>"` → 取 `openConversationId` → `chat message send --group <openConversationId> --text "<变更通知>"` 通知变更 |
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# 日历能力索引
|
||||
|
||||
| 主题 | 详见 |
|
||||
|---|---|
|
||||
| 日程/会议/会议室/闲忙 | [`calendar.md`](./calendar.md) |
|
||||
| 会议最佳实践 | [`03-meeting.md`](./03-meeting.md) |
|
||||
| 轻量流程 | [`lite-recipes.md`](./lite-recipes.md) |
|
||||
@@ -25,7 +25,7 @@
|
||||
日程实例(event instance):日程的具体时间实例,可以通过event list指令查询时间段内的所有实例。1个普通日程和对应1个Instance,而1个重复性日程(SeriesMaster)对应N个Instance(同属一个日程序列)。
|
||||
- 同一个日程序列具有相同的iCalUid,并且重复性日程,其eventId和iCalUid的值相同。因此可以通过重复性日程实例的iCalUid得到重复性日程(SeriesMaster)的eventId
|
||||
重复规则(recurrence rule):定义重复性日程的重复规则。
|
||||
参会人(attendee):日程的参与者。常用通讯录工具查询userId,dws contact user search --query "姓名"。
|
||||
参会人(attendee):日程的参与者。按姓名统一使用 `dws aisearch person --keyword "姓名" --dimension name --format json` 查询 userId。
|
||||
响应状态(response):参会人对日程的回应,包括:未响应、接受、待定、拒绝。
|
||||
忙闲时间(busy):查询用户在指定时间段的忙闲状态,查询会议室在指定时间段的预定状态,用于会议时间协调。
|
||||
会议室(room):room是 会议室 ,room可视为日程的资源类参会人,需要加入日程完成预订。注意和location区分,location只是地点,和room不同。
|
||||
@@ -41,6 +41,8 @@
|
||||
dws calendar event [create|update|get|delete|respond] [flags]
|
||||
# 按时间范围批量查询
|
||||
dws calendar event list [flags]
|
||||
# 查询循环日程的实例列表(按时间范围展开重复日程)
|
||||
dws calendar event instances [flags]
|
||||
# 对于非明确时间或一段时间范围的约会场景,可基于所有参会人的忙闲状态,推荐多个可用的时间块方案
|
||||
dws calendar event suggest [flags]
|
||||
```
|
||||
@@ -122,7 +124,6 @@ Flags:
|
||||
**权限**:查询共享日历下的日程时,至少要有reader权限。
|
||||
**分页**:单次最多返回 `--limit` 指定的条数(默认/最大 100);当结果超过 limit 时,返回体包含 `nextCursor` 字段。首次查询无需传 `--cursor`,仅在翻页时将上一次返回的 `nextCursor` 作为 `--cursor` 传入。
|
||||
|
||||
当前用户的个人日程使用 `dws calendar event list` 查询;参数包含 `--limit` 和 `--cursor` 分页。
|
||||
|
||||
### 获取日程详情
|
||||
```
|
||||
@@ -136,6 +137,28 @@ Flags:
|
||||
--calendar-id string 日历 ID (默认 primary 主日历)
|
||||
```
|
||||
|
||||
### 查询循环日程实例
|
||||
```
|
||||
Usage:
|
||||
dws calendar event instances [flags]
|
||||
Example:
|
||||
dws calendar event instances --id <EVENT_ID>
|
||||
dws calendar event instances --id <EVENT_ID> --start "2026-03-10T00:00:00+08:00" --end "2026-03-31T23:59:59+08:00"
|
||||
dws calendar event instances --id <EVENT_ID> --limit 50
|
||||
dws calendar event instances --id <EVENT_ID> --cursor "<nextCursor>"
|
||||
Flags:
|
||||
--id string 日程 ID (必填,重复性日程 SeriesMaster 的 eventId)
|
||||
--calendar-id string 日历 ID (默认 primary 主日历,仅在查询其他日历本时填写;通过 `book list` 获取)
|
||||
--start string 开始时间 ISO-8601 (例如 2026-03-10T00:00:00+08:00,不传则默认今天 00:00:00)
|
||||
--end string 结束时间 ISO-8601 (例如 2026-03-31T23:59:59+08:00,不传则默认今天 23:59:59)
|
||||
--limit int 每页返回条数 (默认 100,最大 100)
|
||||
--cursor string 分页游标 (从上一次返回的 nextCursor 获取,首次查询无需传入)
|
||||
```
|
||||
|
||||
> **说明**:用于按时间范围展开重复日程(SeriesMaster)的每一个实例。**此接口只能查询重复性日程;若传入普通非循环日程,将查不到任何实例信息。**`--id` 必须是重复性日程的 eventId,可通过 `event list` 获取。
|
||||
> **默认行为**:不传 `--start` / `--end` 时,默认返回今天的实例(00:00:00 ~ 23:59:59)。
|
||||
> **分页**:单次最多返回 `--limit` 指定的条数(默认/最大 100);当结果超过 limit 时,返回体包含 `nextCursor` 字段。
|
||||
|
||||
### 创建日程
|
||||
```
|
||||
Usage:
|
||||
@@ -560,6 +583,7 @@ Flags:
|
||||
- 取消/删除 → `event delete`
|
||||
- 推荐时间/什么时候有空/协调时间 → `event suggest`
|
||||
- 接受/拒绝/暂定日程 → `event respond`
|
||||
- 查询循环日程/重复日程的每次实例/展开循环日程 → `event instances`
|
||||
|
||||
用户说"参会人/与会者":
|
||||
- 查看 → `attendee list`
|
||||
@@ -629,11 +653,11 @@ dws calendar event create --title "Q1 复盘会" \
|
||||
**方式二:先创建日程,再单独添加参会人 / 会议室**
|
||||
|
||||
```bash
|
||||
# Step 1: 创建日程 — 提取 eventId
|
||||
# Step 1: 创建日程 — 从 result.id 提取日程 ID
|
||||
dws calendar event create --title "Q1 复盘会" \
|
||||
--start "2026-03-10T14:00:00+08:00" --end "2026-03-10T15:00:00+08:00" --format json
|
||||
|
||||
# Step 2: 添加参会人(必须用 Step 1 返回的 eventId)
|
||||
# Step 2: 添加参会人(必须用 Step 1 返回的 result.id)
|
||||
dws calendar attendee add --event <EVENT_ID> --attendees userId1,userId2 --format json
|
||||
|
||||
# Step 3: 搜索空闲会议室
|
||||
@@ -661,10 +685,11 @@ dws calendar event list --start "2026-03-10T14:00:00+08:00" --end "2026-03-10T15
|
||||
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `event create` | `eventId` | attendee/room/attachment 操作的 --event |
|
||||
| `event list` | `events[].eventId`, `nextCursor` | event get/update/delete/respond 的 --id;下一页 --cursor |
|
||||
| `event create` | `result.id` | attendee/room/attachment 操作的 --event |
|
||||
| `event list` | `result.events[].id`, `nextCursor` | event get/update/delete/respond 的 --id;下一页 --cursor |
|
||||
| `event suggest` | 推荐的时间段 | event create 的 --start/--end |
|
||||
| `event respond` | 响应结果 | — |
|
||||
| `event instances` | `result.events[].id`, `nextCursor` | event get/update/delete/respond 的 --id;下一页 --cursor |
|
||||
| `room search` | `rooms[].roomId` | room add 的 --rooms 或 event create 的 --rooms |
|
||||
| `room list-groups` | `groups[].groupId` | room search 的 --group-id |
|
||||
| `book list` | `id`(如 `primary`) | event list/get 的 --calendar-id, book get/update 的 --id |
|
||||
@@ -690,7 +715,8 @@ dws calendar event list --start "2026-03-10T14:00:00+08:00" --end "2026-03-10T15
|
||||
- **自动化校验**:凡涉及 `room add` / `event create --rooms` 的流程,`--rooms` 只能填上游 `room search`(或等价接口)返回 JSON 中的 **`rooms[].roomId`**;不得以会议室展示名、楼层文案或用户口语当作 `roomId`
|
||||
- **附件**:`attachment add` 仅负责挂载,**不上传**文件;fileId 必须先通过钉盘流程取得;`--files` 多附件用 `<fileId>:<name>` 元素逗号分隔
|
||||
- **日历本**:`book list` 返回的 `id` 才是合法 `calendarId`;如无明确说明,`event list` / `event get` 都不要带 `--calendar-id`,让接口默认走 primary 主日历
|
||||
- **分页查询**:`event list` / `list-mine` 支持 `--limit`(控制每页条数,默认/最大 100)和 `--cursor`(翻页游标);**首次查询无需传 `--cursor`**,仅当返回体中包含 `nextCursor` 时,将其作为 `--cursor` 传入可获取下一页
|
||||
- **分页查询**:`event list` / `event instances` 均支持 `--limit`(控制每页条数,默认/最大 100)和 `--cursor`(翻页游标);**首次查询无需传 `--cursor`**,仅当返回体中包含 `nextCursor` 时,将其作为 `--cursor` 传入可获取下一页
|
||||
- **循环日程实例**:`event instances` 用于按时间范围展开重复日程(SeriesMaster)的每一个实例;**普通非循环日程调用该命令将查不到任何实例信息**
|
||||
- **日程提醒**:`event create` 支持 `--remind-minutes` 设置开始前提醒,逗号分隔多个分钟数(如 `--remind-minutes 5,10,15`),不传则默认15分钟提醒
|
||||
- **会议室分页**:`room search` 支持 `--limit`(每页条数,默认100,最大100)和 `--page`(分页起始位置,默认0),与 `room list-groups` 分页风格一致
|
||||
|
||||
|
||||
@@ -5,6 +5,5 @@
|
||||
| 用户说... | 真实意图 | 应该用 | 不要用 | 理由 |
|
||||
|---|---|---|---|---|
|
||||
| "给自己留一个明天下午的时间块/建个个人日程" | 创建个人日程 | `calendar event create` | `todo` | 个人 schedule 仍属于日历事件,不是待办 |
|
||||
| "帮我预约一个视频会议" / "开个会" / "发起会议" | 视频会议 | 钉钉客户端(当前 CLI 不支持) | `calendar` | 不要把实时视频会议诉求改写成日历日程 |
|
||||
| "帮我建一个明天下午的日程" | 日历日程 | `calendar` | — | 日历日程管理(可含参与者/会议室);视频会议当前 CLI 不支持 |
|
||||
| "帮我建一个明天下午的日程" | 日历日程 | `calendar` | `conference` | 日历日程管理(可含参与者/会议室) |
|
||||
| "明早 9 点提醒我提交周报" | 创建个人待办,但需先声明 reminder 边界 | `todo` | `calendar` | todo 当前只支持 dueTime 截止时间,不支持独立精确 reminder |
|
||||
|
||||
@@ -19,9 +19,3 @@
|
||||
|
||||
详见 [calendar.md](./calendar.md) 中「查询用户闲忙状态」。
|
||||
|
||||
### 视频会议能力边界
|
||||
|
||||
当前 CLI 不提供视频会议发起、预约、入会邀请或会中控制。用户只说“开个会/发起会议”且未给日程时段时,直接说明请在钉钉客户端操作,不要构造视频会议命令。
|
||||
|
||||
- 有具体时间(如“明天 3 点开会”)或明确预约日程 → 走 [03-meeting.md](./03-meeting.md) 的 `schedule-meeting`
|
||||
- 只有实时视频会议诉求 → 说明当前 CLI 不支持,请在钉钉客户端发起
|
||||
|
||||
@@ -51,48 +51,30 @@ def fmt_iso(dt: datetime) -> str:
|
||||
return dt.strftime('%Y-%m-%dT%H:%M:%S+08:00')
|
||||
|
||||
|
||||
def _extract_time_str(value: Any) -> str:
|
||||
"""时间字段兼容字符串与 {dateTime, date} 对象两种形态。"""
|
||||
if isinstance(value, dict):
|
||||
return value.get('dateTime') or value.get('date') or ''
|
||||
return value or ''
|
||||
|
||||
|
||||
def parse_busy_intervals(
|
||||
data: Any,
|
||||
) -> List[Tuple[datetime, datetime]]:
|
||||
intervals = []
|
||||
if not data:
|
||||
return intervals
|
||||
if isinstance(data, dict) and 'result' in data:
|
||||
data = data['result']
|
||||
rows = []
|
||||
if isinstance(data, list):
|
||||
rows = data
|
||||
elif isinstance(data, dict):
|
||||
rows = list(data.values())
|
||||
items = []
|
||||
for row in rows:
|
||||
if isinstance(row, list):
|
||||
items.extend(row)
|
||||
elif isinstance(row, dict):
|
||||
if isinstance(row.get('scheduleItems'), list):
|
||||
items.extend(row['scheduleItems'])
|
||||
elif isinstance(row.get('busyTimes'), list):
|
||||
items.extend(row['busyTimes'])
|
||||
elif row.get('startTime') or row.get('start'):
|
||||
items.append(row)
|
||||
if isinstance(data, list):
|
||||
items = data
|
||||
elif isinstance(data, dict):
|
||||
inner = data.get('result', data)
|
||||
if isinstance(inner, list):
|
||||
items = inner
|
||||
elif isinstance(inner, dict):
|
||||
for user_data in inner.values():
|
||||
if isinstance(user_data, list):
|
||||
items.extend(user_data)
|
||||
elif isinstance(user_data, dict):
|
||||
items.extend(
|
||||
user_data.get('busyTimes', [])
|
||||
)
|
||||
for item in items:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
if str(item.get('status') or '').upper() == 'FREE':
|
||||
continue
|
||||
start_str = _extract_time_str(
|
||||
item.get('startTime') or item.get('start')
|
||||
)
|
||||
end_str = _extract_time_str(
|
||||
item.get('endTime') or item.get('end')
|
||||
)
|
||||
start_str = item.get('startTime') or item.get('start', '')
|
||||
end_str = item.get('endTime') or item.get('end', '')
|
||||
if not start_str or not end_str:
|
||||
continue
|
||||
for fmt in (
|
||||
@@ -190,15 +172,6 @@ def main():
|
||||
if args.dry_run:
|
||||
return
|
||||
|
||||
# 查询失败必须中止,否则会把“查不到”误判为“全天空闲”。
|
||||
if data is None:
|
||||
print('错误:忙闲查询失败,无法给出空闲时段结论', file=sys.stderr)
|
||||
sys.exit(2)
|
||||
if isinstance(data, dict) and data.get('success') is False:
|
||||
error = data.get('errorMsg') or data.get('errorCode') or data
|
||||
print(f"错误:忙闲查询失败: {error}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
busy = parse_busy_intervals(data)
|
||||
free = find_free_slots(day_start, day_end, busy, args.duration)
|
||||
|
||||
@@ -208,7 +181,6 @@ def main():
|
||||
print(f" 会议时长: {args.duration} 分钟")
|
||||
print(f" 工作时间: {args.start_hour}:00 ~ "
|
||||
f"{args.end_hour}:00")
|
||||
print(f" 已识别忙时段: {len(busy)} 个")
|
||||
print('=' * 50)
|
||||
|
||||
if not free:
|
||||
|
||||
@@ -154,6 +154,7 @@ def main():
|
||||
'calendar', 'room', 'search',
|
||||
'--start', start_iso,
|
||||
'--end', end_iso,
|
||||
'--available',
|
||||
'--format', 'json',
|
||||
]
|
||||
if group_id:
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
name: dingtalk-chat
|
||||
description: 钉钉群聊与消息。Use when 用户提到 发消息/单聊/群聊/建群/拉人进群/改群名/搜索群/群成员管理/@消息/收藏消息/撤回消息/机器人群发/Webhook通知/发图片或文件到群/标记未读/清除红点/置顶消息/全部群列表。不做紧急 DING/短信/电话(走 dingtalk-ding)、邮件(走 dingtalk-mail)、班级群(走 dingtalk-edu-group)。命令前缀:dws chat。
|
||||
cli_version: ">=0.2.14"
|
||||
description: 钉钉群聊与消息。Use when 用户提到 发消息/单聊/群聊/建群/拉人进群/改群名/搜索群/群成员管理/@消息/撤回消息/机器人群发/Webhook通知/发图片或文件到群/标记未读/清除红点/置顶消息/全部群列表。不做紧急 DING/短信/电话(走 dingtalk-misc)、邮件(走 dingtalk-mail)、班级群(走 dingtalk-misc)。命令前缀:dws chat。
|
||||
metadata:
|
||||
cli_version: ">=0.2.14"
|
||||
category: product
|
||||
stability: experimental
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
@@ -12,22 +11,16 @@ metadata:
|
||||
|
||||
# 钉钉群聊 / 消息 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
> **CRITICAL — 执行任何 `dws` 操作前,MUST 先用 Read 工具完整读取 [`dws-shared`](../dws-shared/SKILL.md)。**该轻量文件包含全局执行契约、安全底线及 shared references 的按需加载导航;不要预加载其全部 references。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> 渐进式参考:[chat-index.md](references/chat-index.md);表情:[chat-emoji-list.md](references/chat-emoji-list.md);剧本:[01-messaging.md](references/01-messaging.md)。先按索引选择命令族。
|
||||
|
||||
> 旧路径兼容入口:[chat.md](references/chat.md)。
|
||||
> 命令参考:[chat.md](references/chat.md);表情:[chat-emoji-list.md](references/chat-emoji-list.md);剧本:[01-messaging.md](references/01-messaging.md)。
|
||||
|
||||
<!-- VISIBLE_SHORTCUTS_START -->
|
||||
## Shortcuts(无专用脚本/recipe 时优先)
|
||||
|
||||
以下 shortcut 来自独立于 Runtime Schema 的公开 catalog。先按本 skill 的意图表、脚本和 recipe 路由:存在精确覆盖该场景的专用脚本/recipe 时按其执行;否则用户意图命中时,shortcut 优先于手写原子命令。用 `dws shortcut list --service chat --format json` 读取参数、约束、风险和示例,并以 `dws chat <shortcut> --help` 核对当前 Cobra flags;不要对 `+` 路径调用 `dws schema`。
|
||||
以下命令来自独立于 Runtime Schema 的公开 catalog。先运行 `dws shortcut list --service chat --format json` 读取完整契约,再用 `dws chat <shortcut> --help` 核对 flags;不要对 `+` 路径调用 `dws schema`。
|
||||
|
||||
| Shortcut | 风险 | 适用场景 |
|
||||
|---|---|---|
|
||||
@@ -36,7 +29,7 @@ metadata:
|
||||
| `dws chat +bot-search` | read | 搜索当前用户自己创建的机器人 |
|
||||
| `dws chat +broadcast` | write | 按姓名逐一给多个人群发同一条单聊消息(自动解析 userId、逐个发送) |
|
||||
| `dws chat +category-create` | write | 创建用户自定义会话分组 |
|
||||
| `dws chat +category-delete` | high-risk-write | 删除用户自定义会话分组 |
|
||||
| `dws chat +category-delete` | write | 删除用户自定义会话分组 |
|
||||
| `dws chat +category-list` | read | 获取用户自定义会话分组 |
|
||||
| `dws chat +category-rename` | write | 更新用户自定义会话分组的名称 |
|
||||
| `dws chat +chat-bots` | read | 查看群内所有机器人 |
|
||||
@@ -56,7 +49,7 @@ metadata:
|
||||
| `dws chat +chat-set-history` | write | 设置新成员入群可查看历史消息范围 |
|
||||
| `dws chat +chat-update-alias` | write | 设置群备注(仅自己可见) |
|
||||
| `dws chat +chat-update-nick` | write | 设置当前用户在群内的群昵称 |
|
||||
| `dws chat +conversation-clear-all-red-point` | write | 清除所有会话红点(全部已读) |
|
||||
| `dws chat +conversation-clear-all-red-point` | high-risk-write | 清除所有会话红点(全部已读) |
|
||||
| `dws chat +conversation-info` | read | 获取会话信息(群聊传 --group,单聊传 --open-dingtalk-id) |
|
||||
| `dws chat +conversation-list` | read | 分页获取当前用户的全部会话列表(单聊+群聊) |
|
||||
| `dws chat +conversation-list-top` | read | 拉取置顶会话列表 |
|
||||
@@ -82,22 +75,19 @@ metadata:
|
||||
| "发消息给张三" | `dws chat message send --open-dingtalk-id <id> --text "<内容>"` |
|
||||
| "发到XX群" | `dws chat search --query "<群名>"` → `dws chat message send --group <openConversationId> --text "<内容>"` |
|
||||
| "建群" / "拉人进群" | `dws chat group create` / `dws chat group members add` |
|
||||
| "改群名" / "踢人" | `dws chat group rename` / `dws chat group members remove --yes`(踢人不可逆,确认目标后加 --yes;踢群主会被 CLI 拦截,需先 `transfer-owner`)|
|
||||
| "改群名" / "踢人" | `dws chat group rename` / `dws chat group members remove` |
|
||||
| "@我消息" | `dws chat message list-mentions` |
|
||||
| "查群聊记录" | `dws chat message list` |
|
||||
| "收藏/取消收藏这条消息" | `dws chat message add-favorite` / `dws chat message remove-favorite`(均需 `openMessageId` 和 `openConversationId`)|
|
||||
| "查看我收藏的消息" | `dws chat message list-favorites`(默认 `--cursor 0 --size 20`)|
|
||||
| "用机器人发消息" | `dws chat message send-by-bot --robot-code <code> --group <id> --title "<标题>" --text "<内容>"` |
|
||||
| "Webhook 推一条" | `dws chat message send-by-webhook --token <token> --title "<标题>" --text "<内容>"` |
|
||||
| "撤回我发的消息" | `dws chat message recall`(撤回当前用户发送的消息)|
|
||||
| "撤回机器人消息" | `dws chat message recall-by-bot --robot-code <code> --group <openConversationId> --keys <processQueryKey>`(撤回机器人发的)|
|
||||
| "查群聊记录" | `dws chat search --query "<群名>"` → `dws chat message list --group <openConversationId> --time "<yyyy-MM-dd HH:mm:ss>" --direction older` |
|
||||
| "用机器人发消息" | `dws chat message send-by-bot --robot-code <code> --group <id>` |
|
||||
| "Webhook 推一条" | `dws chat message send-by-webhook --token <token>` |
|
||||
| "撤回消息" | `dws chat message recall --conversation-id <openConversationId> --msg-id <openMessageId>` |
|
||||
| "标记未读 / 清除红点 / 全部已读" | `dws chat mark-unread` / `dws chat clear-red-point` / `dws chat clear-all-red-point` |
|
||||
| "置顶某条消息 / 取消消息置顶" | `dws chat message set-top-msg` / `dws chat message unset-top-msg` |
|
||||
| "我加入的所有群 / 全部群列表" | `dws chat group list-all` |
|
||||
|
||||
## 标准 SOP(必遵流程)
|
||||
|
||||
> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 ID。每条命令必须带 `--format json`,执行后必须按"解析"步取真实字段(`openDingTalkId` / `openConversationId` / `clientMsgId`)。
|
||||
> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 ID。每条命令必须带 `--format json`,执行后必须按"解析"步取真实字段(`openDingTalkId` / `openConversationId` / `openMessageId`)。
|
||||
|
||||
### SOP-1 发消息(send-message)
|
||||
|
||||
@@ -105,7 +95,7 @@ metadata:
|
||||
|
||||
1. **解析收件人(必须)**:人名 → 先 `dws aisearch person --keyword "<姓名>" --dimension name --format json` 取 `openDingTalkId`(优先)或 `userId`;群名 → 先 `dws chat search --query "<群名>" --format json` 取 `openConversationId`。
|
||||
2. **执行(必须)**:单聊 `dws chat message send --open-dingtalk-id <openDingTalkId> --text "<内容>" --format json`(只有拿不到 `openDingTalkId` 时才用 `--user <userId>`);群聊 `dws chat message send --group <openConversationId> --text "<内容>" --format json`。
|
||||
3. **验证(必须)**:从返回取 `messageId` / `openMessageId` / `clientMsgId` 备用(撤回要用);返回非 `success` 必须如实报错,不要谎报已发。
|
||||
3. **验证(必须)**:发送接口成功时可能只返回 `result.openTaskId`,它可用于确认提交成功,但**不是撤回所需消息 ID**。需要撤回时必须按 SOP-7 用带 `--time` 的 `message list` 回查,取得真实 `openMessageId`;返回非 `success` 必须如实报错,不要谎报已发。
|
||||
|
||||
**禁止**:把人名/群名直接当 ID 传入、跳过 `aisearch person`/`chat search` 解析、跳过 `--format json`、未发送成功就答复"已发送"。
|
||||
|
||||
@@ -155,12 +145,22 @@ metadata:
|
||||
|
||||
**禁止**:用普通 `message list` 冒充 focused、把人员列表需求硬塞进 chat。
|
||||
|
||||
### SOP-7 拉取 / 撤回消息(list-or-recall-message)
|
||||
|
||||
**触发**:查某个群或单聊的聊天记录、撤回某条消息。
|
||||
|
||||
1. **定位会话(必须)**:群名先 `dws chat search --query "<群名>" --format json` 取 `openConversationId`;单聊对象先解析真实 `userId` 或 `openDingTalkId`。
|
||||
2. **拉取消息(必须)**:`dws chat message list --group <openConversationId> --time "<yyyy-MM-dd HH:mm:ss>" --direction older --format json`;单聊将 `--group` 换成 `--user` 或 `--open-dingtalk-id`。`--time` 是必填参数,必须来自用户时间范围或明确收敛后的边界。
|
||||
3. **撤回(必须)**:仅在用户明确要求撤回时,从消息列表 `result.messages[].openMessageId` 取真实 ID,执行 `dws chat message recall --conversation-id <openConversationId> --msg-id <openMessageId> --format json`。
|
||||
|
||||
**禁止**:省略 `--time`、用发送返回的 `clientMsgId` 代替 `openMessageId`、只传 `--client-msg-id`、编造会话或消息 ID。
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
- 收件人是人名 → 先用 `dingtalk-contact` 或 `dingtalk-aisearch` 拿 `openDingTalkId` / `userId`
|
||||
- 要发图片/文件 → 先 `dt_media_upload` 上传 → `python scripts/extract_media_id.py "<URL>"` 提取 mediaId → 再用 `--media-id`
|
||||
- 紧急升级(应用内/短信/电话)→ 切到 `dingtalk-ding`
|
||||
- 紧急升级(应用内/短信/电话)→ 切到 `dingtalk-misc`(`references/ding.md`)
|
||||
- 发邮件 → 切到 `dingtalk-mail`
|
||||
## 局部意图与 Recipe
|
||||
## 局部意图与短流程
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md);[Lite Recipe](references/lite-recipes.md)。
|
||||
- [局部意图消歧](references/intent-guide.md);[短流程](references/lite-recipes.md)。
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
|--------|-------------------|
|
||||
| query-group-chat | **优先**:`python scripts/chat_export_messages.py --query "<群名>" --time "<yyyy-MM-dd HH:mm:ss>" [--no-forward] [--limit N] [--output messages.json]`(自动搜群+翻页+导出)<br>备选:1. `chat search --query "<群名>"` → 取 `openConversationId`<br>2. `chat message list --group <openConversationId> --time "<yyyy-MM-dd HH:mm:ss>"` → 取消息列表<br>3. **翻页**:`hasMore=true` 时取本页最后 `createTime` 作为下次 `--time`,重复至 `hasMore=false`<br>4. `--forward=false` 拉给定时间**之前**的消息<br>5. 合并全部消息后总结 |
|
||||
| query-private-chat | **优先**:`python scripts/chat_history_with_user.py --name "<姓名>" --time "<yyyy-MM-dd HH:mm:ss>" [--no-forward] [--limit N] [--output messages.json]`(自动搜人+翻页+导出)<br>备选:1. `aisearch person --keyword "<姓名>" --dimension name` → 取 `userId`<br>2. `chat message list --user <userId> --time "<yyyy-MM-dd HH:mm:ss>"` → 取消息列表<br>3. **翻页**:同 query-group-chat<br>4. 合并全部消息后总结 |
|
||||
| escalate-ding | 三级升级:<br>1. `ding message send --robot-code <robotCode> --type app --users <userId> --content "<内容>"`(必填项见 `dingtalk-ding`)<br>2. `chat message send --group <openConversationId> --text "<内容>"` 群里提醒(可选 `--title` / `@` 见 [chat.md](./chat-commands.md))<br>3. `todo task create --title "<标题>" --executors <userId> --priority 40` 建紧急待办<br>前置:`aisearch person --keyword "<姓名>" --dimension name` → 取 `userId`;`chat search --query "<群名>"` → 取 `openConversationId` |
|
||||
| escalate-ding | 三级升级:<br>1. `ding message send --robot-code <robotCode> --type app --users <userId> --content "<内容>"`(必填项见 `dingtalk-misc` 的 `references/ding.md`)<br>2. `chat message send --group <openConversationId> --text "<内容>"` 群里提醒(可选 `--title` / `@` 见 [chat.md](./chat.md))<br>3. `todo task create --title "<标题>" --executors <userId> --priority 40` 建紧急待办<br>前置:`aisearch person --keyword "<姓名>" --dimension name` → 取 `userId`;`chat search --query "<群名>"` → 取 `openConversationId` |
|
||||
| send-by-bot | **多群批量优先**:`python scripts/bot_broadcast.py --robot-code <robotCode> --chats <id1>,<id2> --title "<标题>" --text "<内容>"`<br>单群:1. `chat bot search` → 取 `robotCode`<br>2. `chat search --query "<群名>"` → 取 `openConversationId`<br>3. `chat message send-by-bot --robot-code <robotCode> --group <openConversationId> --title "<标题>" --text "<内容>"` |
|
||||
| forward-message | 1. `chat search --query "<群名>"` → 取 `openConversationId` → `chat message list --group <openConversationId> --time "<起始时间>"` 拉源消息<br>2. `contact user search --query "<姓名>"` → 取 `openDingTalkId`(推荐);或 `chat search --query "<群名>"` → 取目标 `openConversationId`<br>3. `chat message send --open-dingtalk-id <openDingTalkId> --text "<内容>"`(推荐)或 `--group <openConversationId> --text "<内容>"` 发送。仅当无法获取 openDingTalkId 时才用 `--user <userId>`(备选) |
|
||||
| forward-message | 1. `chat search --query "<群名>"` → 取 `openConversationId` → `chat message list --group <openConversationId> --time "<起始时间>"` 拉源消息<br>2. `aisearch person --keyword "<姓名>" --dimension name` → 取 `openDingTalkId`(推荐);或 `chat search --query "<群名>"` → 取目标 `openConversationId`<br>3. `chat message send --open-dingtalk-id <openDingTalkId> --text "<内容>"`(推荐)或 `--group <openConversationId> --text "<内容>"` 发送。仅当无法获取 openDingTalkId 时才用 `--user <userId>`(备选) |
|
||||
| search-common-group | `chat search-common --nicks "<昵称1>,<昵称2>" --limit 20 --cursor 0`(`--match-mode AND`=全在/`OR`=任一在,翻页:`hasMore=true` 时用 `nextCursor`)<br>用户说"我和XX的共同群" → nicks 包含"我"时,需先 `contact user get-self` 取自己昵称再拼接 |
|
||||
| focus-messages | **零参数一行命令**:`chat message list-focused --limit 50`(拉特别关注人发的消息聚合)<br>触发 query:`"我特别关注的人最近发了什么消息"`、`"关注的人最近聊了啥"`、`"星标联系人最近的动态"`<br>**强消歧**:query 含动词【发/说/聊/讲】或名词【消息/聊天/动态】 → **必须**走本命令,**不要**先去拉 `contact relation list-my-followings`;仅当用户终点是"人员列表"(如"我关注了谁")才走 `relation list-my-followings`(详见 `dingtalk-contact` 易混淆硬规则)<br>翻页:`hasMore=true` 时用 `nextCursor` 作为下次 `--cursor`<br>按人精控(可选):先 `contact relation list-my-followings` 取 `openDingTalkId`,再 `chat message list-by-sender --sender-open-dingtalk-id <openDingTalkId> --start <ISO> --end <ISO>` |
|
||||
| favorite-message | 收藏:先从消息查询结果取得 `openMessageId` 和 `openConversationId`,再执行 `chat message add-favorite --open-message-id <id> --open-conversation-id <cid>`<br>取消收藏:对应执行 `remove-favorite`,不会删除原消息<br>查询收藏:`chat message list-favorites [--cursor N] [--size 20]`,`hasMore=true` 时继续传 `nextCursor` |
|
||||
|
||||
@@ -1,417 +0,0 @@
|
||||
# 机器人、分组与会话状态命令
|
||||
|
||||
### bot (机器人管理)
|
||||
|
||||
#### 搜索【我创建的】机器人 — 仅返回当前用户自己创建的机器人
|
||||
|
||||
范围: 仅限当前登录用户自己创建的机器人(不含他人创建、官方机器人)。
|
||||
返回字段: 没有 openDingTalkId,如果需要给机器人发单聊消息请用 find。
|
||||
典型触发词: "我创建的机器人""我的机器人""我自己的机器人""我做的机器人""查看我的机器人"。
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws chat bot search [flags]
|
||||
Example:
|
||||
dws chat bot search --page 1
|
||||
dws chat bot search --page 1 --size 10 --name "日报"
|
||||
Flags:
|
||||
--name string 按名称搜索
|
||||
--page int 页码,从1开始 (默认 1)
|
||||
--size int 每页条数 (默认 50),别名: --limit
|
||||
```
|
||||
|
||||
#### 搜索【全部可用】机器人 — 含他人创建/官方机器人,额外返回 openDingTalkId
|
||||
|
||||
范围: 当前用户可用的全部机器人(含他人创建、官方机器人)。
|
||||
返回字段: 额外返回 openDingTalkId(可用于给机器人发单聊消息),search 没有此字段。
|
||||
典型触发词: "搜索机器人""找一个机器人""帮我找 XXX 机器人""所有可用机器人""查机器人"。
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws chat bot find [flags]
|
||||
Example:
|
||||
dws chat bot find --query "日报"
|
||||
dws chat bot find --query "日报" --limit 20
|
||||
dws chat bot find --query "日报" --limit 20 --cursor <上次返回的 nextCursor>
|
||||
Flags:
|
||||
--query string 搜索关键词 (必填)
|
||||
--limit int 每页返回数量(默认 20)
|
||||
--cursor string 分页游标(首次调用不传,翻页时传上次返回的 nextCursor)
|
||||
|
||||
注意:
|
||||
- cursor 必须用上次返回的 nextCursor 字符串原值,不要传 "0" 或其他数字字面量
|
||||
(服务端 String 类型,但网关会把数字字符串 auto-coerce 回 Integer 导致 PARAM_ERROR)
|
||||
```
|
||||
|
||||
search 与 find 选择指南:
|
||||
|
||||
| 维度 | `chat bot search` | `chat bot find` |
|
||||
|------|-------------------|-----------------|
|
||||
| 范围 | 仅我创建的机器人 | 全部可用机器人(含他人/官方) |
|
||||
| 额外返回 openDingTalkId | 无 | 有(可用于给机器人发单聊消息) |
|
||||
| 触发词 | "我创建的""我的""我自己的" | "搜索机器人""找机器人""查机器人" |
|
||||
|
||||
### category (会话分组管理)
|
||||
|
||||
#### 获取用户自定义会话分组
|
||||
```
|
||||
Usage:
|
||||
dws chat category list
|
||||
Example:
|
||||
dws chat category list
|
||||
# 返回当前用户的所有自定义会话分组
|
||||
```
|
||||
|
||||
#### 拉取指定分组下的会话列表
|
||||
```
|
||||
Usage:
|
||||
dws chat category list-conversations [flags]
|
||||
Example:
|
||||
dws chat category list-conversations --category-id <分组ID>
|
||||
# 分组ID 可通过 dws chat category list 获取
|
||||
Flags:
|
||||
--category-id int 会话分组 ID (必填)
|
||||
--exclude-muted 是否排除已设置免打扰的会话(默认 false)
|
||||
```
|
||||
|
||||
#### 创建用户自定义会话分组
|
||||
```
|
||||
Usage:
|
||||
dws chat category create [flags]
|
||||
Example:
|
||||
dws chat category create --title "工作群"
|
||||
dws chat category create --title "项目组"
|
||||
Flags:
|
||||
--title string 分组名称 (必填)
|
||||
```
|
||||
|
||||
#### 创建智能会话分组 — 可指定群名称关键词和群内成员作为匹配规则
|
||||
```
|
||||
Usage:
|
||||
dws chat category create-smart [flags]
|
||||
Example:
|
||||
dws chat category create-smart --name "工作群"
|
||||
dws chat category create-smart --name "项目组" --keywords "项目,开发"
|
||||
dws chat category create-smart --name "团队群" --members openDingTalkId1,openDingTalkId2
|
||||
dws chat category create-smart --name "重点群" --keywords "重点" --members openDingTalkId1
|
||||
Flags:
|
||||
--name string 分组名称 (必填)
|
||||
--keywords string 群名称关键词列表,逗号分隔(可选)
|
||||
--members string 群内成员 openDingTalkId 列表,逗号分隔(可选)
|
||||
```
|
||||
|
||||
#### 删除用户自定义会话分组
|
||||
```
|
||||
Usage:
|
||||
dws chat category delete [flags]
|
||||
Example:
|
||||
dws chat category delete --category-id <分组ID>
|
||||
# 分组ID 可通过 dws chat category list 获取
|
||||
Flags:
|
||||
--category-id int 会话分组 ID (必填)
|
||||
```
|
||||
|
||||
#### 更新用户自定义会话分组的名称
|
||||
```
|
||||
Usage:
|
||||
dws chat category rename [flags]
|
||||
Example:
|
||||
dws chat category rename --category-id <分组ID> --title "新名称"
|
||||
# 分组ID 可通过 dws chat category list 获取
|
||||
Flags:
|
||||
--category-id int 会话分组 ID (必填)
|
||||
--title string 新的分组名称 (必填)
|
||||
```
|
||||
|
||||
#### 将会话移动到指定的自定义分组中
|
||||
```
|
||||
Usage:
|
||||
dws chat category add-conv [flags]
|
||||
Example:
|
||||
dws chat category add-conv --group <openConversationId> --category-ids 123,456
|
||||
# 分组ID 可通过 dws chat category list 获取
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 会话 openConversationId (必填)
|
||||
--category-ids string 目标分组 ID 列表,逗号分隔 (必填)
|
||||
```
|
||||
|
||||
#### 将会话从指定的自定义分组中移出
|
||||
```
|
||||
Usage:
|
||||
dws chat category remove-conv [flags]
|
||||
Example:
|
||||
dws chat category remove-conv --group <openConversationId> --category-ids 123,456
|
||||
# 分组ID 可通过 dws chat category list 获取
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 会话 openConversationId (必填)
|
||||
--category-ids string 目标分组 ID 列表,逗号分隔 (必填)
|
||||
```
|
||||
|
||||
### mute (会话免打扰)
|
||||
|
||||
#### 会话消息免打扰 — 开启或关闭会话消息免打扰(支持单聊和群聊)
|
||||
```
|
||||
Usage:
|
||||
dws chat mute [flags]
|
||||
Example:
|
||||
dws chat mute --conversation-id <openConversationId>
|
||||
dws chat mute --conversation-id <openConversationId> --off
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
# 查询单聊会话 ID: dws chat conversation-info --user <userId>
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持单聊/群聊)
|
||||
--id string --conversation-id 的别名
|
||||
--chat string --conversation-id 的别名
|
||||
--off 关闭免打扰(不传则开启免打扰)
|
||||
|
||||
注意:
|
||||
- 默认行为是开启免打扰,传 --off 则关闭免打扰
|
||||
- 支持单聊和群聊,openConversationId 可通过 chat search(群聊)或 chat conversation-info(单聊)获取
|
||||
```
|
||||
|
||||
### hide (隐藏会话)
|
||||
|
||||
#### 隐藏会话 — 在会话列表中隐藏指定会话(支持单聊/群聊),收到新消息时会重新出现
|
||||
```
|
||||
Usage:
|
||||
dws chat hide [flags]
|
||||
Example:
|
||||
dws chat hide --conversation-id <openConversationId>
|
||||
dws chat hide --id <openConversationId>
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
# 查询单聊会话 ID: dws chat conversation-info --user <userId>
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持单聊/群聊)
|
||||
--id string --conversation-id 的别名
|
||||
--chat string --conversation-id 的别名
|
||||
|
||||
注意:
|
||||
- 隐藏后会话不再显示在列表中,收到新消息时会重新出现
|
||||
- 支持单聊和群聊,openConversationId 可通过 chat search(群聊)或 chat conversation-info(单聊)获取
|
||||
```
|
||||
|
||||
|
||||
### mute-at-all (关闭@所有人通知)
|
||||
|
||||
#### 关闭/开启 @所有人消息提醒 — 关闭或开启会话中 @所有人的消息通知
|
||||
```
|
||||
Usage:
|
||||
dws chat mute-at-all [flags]
|
||||
Example:
|
||||
dws chat mute-at-all --conversation-id <openConversationId>
|
||||
dws chat mute-at-all --conversation-id <openConversationId> --off
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持单聊/群聊)
|
||||
--id string --conversation-id 的别名
|
||||
--chat string --conversation-id 的别名
|
||||
--off 恢复接收 @所有人通知(不传则关闭通知)
|
||||
|
||||
注意:
|
||||
- 默认行为是关闭 @所有人通知,传 --off 则恢复接收通知
|
||||
- 支持单聊和群聊,openConversationId 可通过 chat search(群聊)或 chat conversation-info(单聊)获取
|
||||
```
|
||||
|
||||
### mute-red-envelope (关闭红包通知)
|
||||
|
||||
#### 关闭/开启红包消息提醒 — 关闭或开启会话中的红包消息通知
|
||||
```
|
||||
Usage:
|
||||
dws chat mute-red-envelope [flags]
|
||||
Example:
|
||||
dws chat mute-red-envelope --conversation-id <openConversationId>
|
||||
dws chat mute-red-envelope --conversation-id <openConversationId> --off
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持单聊/群聊)
|
||||
--id string --conversation-id 的别名
|
||||
--chat string --conversation-id 的别名
|
||||
--off 恢复接收红包通知(不传则关闭通知)
|
||||
|
||||
注意:
|
||||
- 默认行为是关闭红包通知,传 --off 则恢复接收通知
|
||||
- 支持单聊和群聊,openConversationId 可通过 chat search(群聊)或 chat conversation-info(单聊)获取
|
||||
```
|
||||
|
||||
### mark-unread (标记会话为未读)
|
||||
|
||||
#### 标记会话为未读 — 将指定会话标记为未读状态
|
||||
```
|
||||
Usage:
|
||||
dws chat mark-unread [flags]
|
||||
Example:
|
||||
dws chat mark-unread --conversation-id <openConversationId>
|
||||
dws chat mark-unread --id <openConversationId>
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持群聊/单聊)
|
||||
--id string --conversation-id 的别名
|
||||
--chat string --conversation-id 的别名
|
||||
|
||||
注意:
|
||||
- 支持群聊和单聊,openConversationId 可通过 chat search(群聊)或 chat conversation-info(单聊)获取
|
||||
- 标记未读后会话列表中会显示未读状态
|
||||
```
|
||||
|
||||
### clear-red-point (清除会话红点)
|
||||
|
||||
#### 清除会话红点 — 清除指定会话的未读红点
|
||||
```
|
||||
Usage:
|
||||
dws chat clear-red-point [flags]
|
||||
Example:
|
||||
dws chat clear-red-point --conversation-id <openConversationId>
|
||||
dws chat clear-red-point --id <openConversationId>
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持群聊/单聊)
|
||||
--id string --conversation-id 的别名
|
||||
--chat string --conversation-id 的别名
|
||||
|
||||
注意:
|
||||
- 支持群聊和单聊,openConversationId 可通过 chat search(群聊)或 chat conversation-info(单聊)获取
|
||||
- 清除红点后该会话不再显示未读标记
|
||||
```
|
||||
|
||||
### clear-all-red-point (红点清零)
|
||||
|
||||
#### 清除所有会话红点 — 一键全部已读
|
||||
```
|
||||
Usage:
|
||||
dws chat clear-all-red-point
|
||||
Example:
|
||||
dws chat clear-all-red-point
|
||||
|
||||
注意:
|
||||
- 无需任何参数,直接清除当前用户所有会话的未读红点
|
||||
- 等效于“全部已读”操作
|
||||
```
|
||||
|
||||
### list-all-conversations (全部会话列表)
|
||||
|
||||
#### 分页获取全部会话列表 — 获取当前用户的所有会话
|
||||
```
|
||||
Usage:
|
||||
dws chat list-all-conversations [flags]
|
||||
Example:
|
||||
dws chat list-all-conversations
|
||||
dws chat list-all-conversations --limit 50
|
||||
dws chat list-all-conversations --limit 100 --cursor <nextCursor>
|
||||
dws chat list-all-conversations --exclude-muted
|
||||
Flags:
|
||||
--limit int 每页数量(默认 1000)
|
||||
--cursor int64 分页游标(首次不传或传 0,翻页传 nextCursor)
|
||||
--exclude-muted 是否排除已免打扰会话(默认 false)
|
||||
|
||||
注意:
|
||||
- 返回结果包含单聊和群聊,不区分会话类型
|
||||
- 翻页: hasMore=true 时用返回的 nextCursor 作为下次 --cursor
|
||||
- 与 list-top-conversations 的区别: 本命令返回全部会话(单聊+群聊),list-top-conversations 仅返回置顶会话
|
||||
```
|
||||
|
||||
### clear-messages (清空会话聊天记录)
|
||||
|
||||
#### 清空会话聊天记录 — 清空当前用户指定会话的消息
|
||||
```
|
||||
Usage:
|
||||
dws chat clear-messages [flags]
|
||||
Example:
|
||||
dws chat clear-messages --conversation-id <openConversationId>
|
||||
dws chat clear-messages --id <openConversationId>
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持群聊/单聊)
|
||||
--id string --conversation-id 的别名
|
||||
--chat string --conversation-id 的别名
|
||||
|
||||
注意:
|
||||
- 仅清空当前用户视角的消息,不影响其他成员
|
||||
- openConversationId 可通过 chat search(群聊)或 chat conversation-info(单聊)获取
|
||||
```
|
||||
|
||||
### mark-read (标记消息已读)
|
||||
|
||||
#### 标记消息已读 — 将指定消息及之前的消息标记为已读
|
||||
```
|
||||
Usage:
|
||||
dws chat mark-read [flags]
|
||||
Example:
|
||||
dws chat mark-read --conversation-id <openConversationId> --message-id <openMessageId>
|
||||
dws chat mark-read --id <openConversationId> --message-id <openMessageId>
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持群聊/单聊)
|
||||
--id string --conversation-id 的别名
|
||||
--chat string --conversation-id 的别名
|
||||
--message-id string 消息 openMessageId (必填)
|
||||
|
||||
注意:
|
||||
- 标记该消息及之前的所有消息为已读
|
||||
- openConversationId 可通过 chat search(群聊)或 chat conversation-info(单聊)获取
|
||||
- openMessageId 可通过 chat message list 获取
|
||||
```
|
||||
|
||||
### group list-all (分页拉取所有群)
|
||||
|
||||
#### 分页拉取我所有群列表 — 获取当前用户加入的所有群聊
|
||||
```
|
||||
Usage:
|
||||
dws chat group list-all [flags]
|
||||
Example:
|
||||
dws chat group list-all
|
||||
dws chat group list-all --limit 50
|
||||
dws chat group list-all --limit 100 --cursor <nextCursor>
|
||||
Flags:
|
||||
--limit int 每页返回数量(默认 100,最大 200)
|
||||
--cursor string 分页游标(首次不传,翻页传返回的 nextCursor)
|
||||
|
||||
注意:
|
||||
- 与 `chat group list-my-groups` 区别: list-all 返回用户加入的所有群;list-my-groups 仅返回用户作为群主/管理员的群
|
||||
- 分页: hasMore=true 时用返回的 nextCursor 作为下次 --cursor
|
||||
```
|
||||
|
||||
### group list-join-validations (分页拉取入群验证记录)
|
||||
|
||||
#### 分页拉取入群验证记录 — 获取当前用户的所有入群验证记录
|
||||
|
||||
包括自己被拒绝的记录以及作为审批者的记录。
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws chat group list-join-validations [flags]
|
||||
Example:
|
||||
dws chat group list-join-validations
|
||||
dws chat group list-join-validations --limit 30
|
||||
dws chat group list-join-validations --limit 20 --cursor <nextCursor>
|
||||
Flags:
|
||||
--limit int 单页数量(默认 20,最大 50)
|
||||
--cursor string 分页游标(首次不传,翻页传返回的 nextCursor)
|
||||
|
||||
注意:
|
||||
- 分页: hasMore=true 时用返回的 nextCursor 作为下次 --cursor
|
||||
- cursor 首次拉取不传或传 null 时从当前时间开始拉
|
||||
```
|
||||
|
||||
### group audit-join-validation (审批入群验证)
|
||||
|
||||
#### 审批入群验证 — 通过、拒绝、删除单个审核
|
||||
|
||||
支持通过、拒绝、删除、忽略、拒绝并拉黑等操作。
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws chat group audit-join-validation [flags]
|
||||
Example:
|
||||
dws chat group audit-join-validation --group <openConversationId> --record-id 123456 --applicant <openDingTalkId> --inviter <openDingTalkId> --status AuditApprove
|
||||
dws chat group audit-join-validation --group <openConversationId> --record-id 123456 --applicant <openDingTalkId> --inviter <openDingTalkId> --status AuditRefuse --description "不符合入群条件"
|
||||
# 查询入群验证记录: dws chat group list-join-validations
|
||||
Flags:
|
||||
--group string 群 openConversationId (必填)
|
||||
--record-id int64 申请记录 ID (必填)
|
||||
--applicant string 申请人 openDingTalkId (必填)
|
||||
--inviter string 邀请人 openDingTalkId (必填)
|
||||
--status string 审批动作: AuditApprove/AuditDelete/AuditIgnore/AuditRefuse/AuditBlock (必填)
|
||||
--description string 审批说明(可选)
|
||||
|
||||
注意:
|
||||
- status 可选值: AuditApprove(通过), AuditDelete(删除), AuditIgnore(忽略), AuditRefuse(拒绝), AuditBlock(拒绝且拉黑)
|
||||
- record-id、applicant、inviter 可通过 dws chat group list-join-validations 查询获得
|
||||
```
|
||||
@@ -1,10 +0,0 @@
|
||||
# 聊天命令路由
|
||||
|
||||
> `dws im` 等价于 `dws chat`。按命令族只加载一份详细参考。
|
||||
|
||||
| 命令族 | 详见 |
|
||||
|---|---|
|
||||
| 群创建/设置/成员/角色/搜索 | [`chat-group-commands.md`](./chat-group-commands.md) |
|
||||
| 消息发送/回复/转发/撤回与会话文件 | [`chat-message-file-commands.md`](./chat-message-file-commands.md) |
|
||||
| 置顶会话、媒体下载、共同群、会话详情 | [`chat-conversation-commands.md`](./chat-conversation-commands.md) |
|
||||
| 机器人、会话分组、免打扰、红点与入群审批 | [`chat-admin-commands.md`](./chat-admin-commands.md) |
|
||||
@@ -1,139 +0,0 @@
|
||||
# 复合工作流
|
||||
|
||||
## 复合工作流
|
||||
|
||||
### 机器人发消息后撤回(完整流程)
|
||||
|
||||
`recall-by-bot` 通过机器人接口撤回机器人发出的消息(需要 `--robot-code` + `--keys`)。`chat message recall` 通过 IM 接口撤回当前用户自己发出的消息(需要 `--conversation-id` + `--msg-id`)。
|
||||
|
||||
```bash
|
||||
# Step 1: 查我的机器人 — 提取 robot-code
|
||||
dws chat bot search --format json
|
||||
|
||||
# Step 2: 用机器人发消息 — 提取返回中的 processQueryKey
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openconversation_id> \
|
||||
--title "通知" --text "内容" --format json
|
||||
|
||||
# Step 3: 用同一个 robot-code + processQueryKey 撤回
|
||||
dws chat message recall-by-bot --robot-code <robot-code> --group <openconversation_id> \
|
||||
--keys <processQueryKey> --format json
|
||||
```
|
||||
|
||||
### 机器人发群消息(含机器人不在群内的处理)
|
||||
|
||||
机器人通过 `send-by-bot --group` 发群消息时,如果返回"机器人不存在"错误,说明该机器人尚未加入目标群,需先邀请进群再发送。
|
||||
|
||||
```bash
|
||||
# Step 1: 查我的机器人 — 提取 robot-code
|
||||
dws chat bot search --format json
|
||||
|
||||
# Step 2: 尝试发送,若报"机器人不存在"则执行 Step 3
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openconversation_id> \
|
||||
--title "通知" --text "内容" --format json
|
||||
|
||||
# Step 3: 邀请机器人进群
|
||||
dws chat group members add-bot --id <openconversation_id> --robot-code <robot-code>
|
||||
|
||||
# Step 4: 重新发送
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openconversation_id> \
|
||||
--title "通知" --text "内容" --format json
|
||||
```
|
||||
|
||||
### 给机器人发单聊消息(必须先用 find 拿 openDingTalkId)
|
||||
|
||||
给机器人发单聊消息时,必须先用 `chat bot find` 搜索机器人拿到 `openDingTalkId`,再用 `chat message send --open-dingtalk-id` 发送。不能用 `chat bot search`,因为 search 不返回 `openDingTalkId`。
|
||||
|
||||
```bash
|
||||
# Step 1: 搜索机器人 — 提取 openDingTalkId(必须用 find,search 没有此字段)
|
||||
dws chat bot find --query "玉澜" --format json
|
||||
|
||||
# Step 2: 用 openDingTalkId 发单聊消息
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --text "你好" --format json
|
||||
```
|
||||
|
||||
### 机器人 @指定人发群消息
|
||||
|
||||
通过 `--at-user-ids` 传入 userId 列表或 `--at-open-dingtalk-ids` 传入 openDingtalkId 列表来 @指定成员,多个用逗号分隔。`--text` 中需包含 `@userId` 或 `@openDingtalkId` 文本(不要用尖括号,不要用姓名)。通过 `--at-all` @所有人。
|
||||
|
||||
```bash
|
||||
# Step 1: 搜人获取 userId
|
||||
dws contact user search --query "张三" --format json
|
||||
|
||||
# Step 2: 用 userId 发送并 @(注意 text 中 @userId)
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openconversation_id> \
|
||||
--at-user-ids userId1,userId2 \
|
||||
--title "提醒" --text "@userId1 @userId2 请查收本周报告" --format json
|
||||
|
||||
# 或者用 openDingtalkId 发送并 @
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openconversation_id> \
|
||||
--at-open-dingtalk-ids openDingtalkId1,openDingtalkId2 \
|
||||
--title "提醒" --text "@openDingtalkId1 @openDingtalkId2 请查收本周报告" --format json
|
||||
|
||||
# @所有人
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openconversation_id> \
|
||||
--at-all --title "通知" --text "请所有人注意" --format json
|
||||
```
|
||||
|
||||
|
||||
### 发送图片 / 文件(统一一条命令)
|
||||
|
||||
**`dws chat message send --msg-type file --file-path <本地路径>`** 适用于所有发图片/文件场景,任意扩展名。CLI 内部完成上传与发送,无需任何前置工具调用。
|
||||
|
||||
```bash
|
||||
# 群聊
|
||||
dws chat message send --group <openConversationId> --msg-type file --file-path ./screenshot.png --format json
|
||||
dws chat message send --group <openConversationId> --msg-type file --file-path ./report.pdf --format json
|
||||
|
||||
# 单聊(推荐 --open-dingtalk-id)
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --msg-type file --file-path ./screenshot.png --format json
|
||||
```
|
||||
|
||||
**带文字说明**:在上一步发完文件后,再补一条文本消息即可。不要尝试把文字塞进 `--msg-type file` 命令(该命令不读 `--text`)。
|
||||
|
||||
```bash
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --msg-type file --file-path ./screenshot.png --format json
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --text "这是本周数据汇总" --format json
|
||||
```
|
||||
|
||||
**旧链路(仅当上游已经持有 `dt_media_upload` 返回的 mediaId 时才用)**:
|
||||
|
||||
```bash
|
||||
dws chat message send --group <openConversationId> --msg-type image --media-id "@lQLPD4JNnliqBq3NBQDNA8Cw" --format json
|
||||
```
|
||||
|
||||
#### 创建并推送流式卡片 — 向群聊或单聊发送流式卡片消息
|
||||
|
||||
群聊传 --group,单聊传 --receiver,二者互斥。
|
||||
|
||||
**注意:send-card 必须和 update-card 搭配使用。** 创建卡片时无需传入内容,后续通过 update-card 更新内容,最后一次更新必须将 --flow-status 设为 3(finish),否则卡片会一直处于"生成中"的加载状态。
|
||||
flow-status 取值:1=处理中(PROCESSING),2=输入中(INPUTTING),3=完成(FINISH),4=执行中(EXECUTING),5=错误(ERROR)。
|
||||
```
|
||||
Usage:
|
||||
dws chat message send-card [flags]
|
||||
Example:
|
||||
dws chat message send-card --group <openConversationId>
|
||||
dws chat message send-card --receiver <openDingTalkId>
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
# 查询人员: dws contact user search --query "姓名" --format json
|
||||
Flags:
|
||||
--group string 群聊 openConversationId(群聊时必填,与 --receiver 互斥)
|
||||
--receiver string 单聊接收者 openDingTalkId(单聊时必填,与 --group 互斥)
|
||||
```
|
||||
|
||||
#### 流式更新卡片内容 — 更新已发送的流式卡片内容
|
||||
|
||||
--biz-id 为 send-card 返回的业务 ID,--flow-status 控制流式状态。
|
||||
flow-status 取值:1=处理中(PROCESSING),2=输入中(INPUTTING),3=完成(FINISH),4=执行中(EXECUTING),5=错误(ERROR)。
|
||||
|
||||
**最后一次更新必须将 --flow-status 设为 3(finish),否则卡片会一直处于"生成中"的加载状态。**
|
||||
```
|
||||
Usage:
|
||||
dws chat message update-card [flags]
|
||||
Example:
|
||||
dws chat message update-card --biz-id <bizId> --content "更新的卡片内容" --flow-status 2
|
||||
dws chat message update-card --biz-id <bizId> --content "最终内容" --flow-status 3
|
||||
Flags:
|
||||
--biz-id string 卡片业务 ID (必填)
|
||||
--content string 卡片消息内容 (必填)
|
||||
--flow-status int 流式状态 (必填)
|
||||
```
|
||||
@@ -1,27 +0,0 @@
|
||||
# 上下文传递表
|
||||
|
||||
## 上下文传递表
|
||||
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `chat search` | `openConversationId` | message send/list、group members 等的 --group |
|
||||
| `chat group create` | `openConversationId` | 同上 |
|
||||
| `chat message list-all` | `nextCursor` | 下次 list-all 的 --cursor |
|
||||
| `aisearch person` | `userId` | message send 的 --user、send-by-bot 的 --users、send-by-bot 的 --at-user-ids、list-by-sender 的 --sender-user-id |
|
||||
| `contact user search` | `openDingTalkId` | message send 的 --at-open-dingtalk-ids、--open-dingtalk-id、send-by-bot 的 --open-dingtalk-ids、send-by-bot 的 --at-open-dingtalk-ids、list-by-sender 的 --sender-open-dingtalk-id、message list 的 --open-dingtalk-id |
|
||||
| `chat bot search` | `robotCode` | send-by-bot / recall-by-bot 的 --robot-code(仅我创建的机器人,无 openDingTalkId) |
|
||||
| `chat bot find` | `openDingTalkId` | 给机器人发单聊消息(全部可用机器人,额外返回 openDingTalkId) |
|
||||
| `chat message send-by-bot` | `processQueryKey` | recall-by-bot 的 --keys |
|
||||
| `chat message send` | `openTaskId` | query-send-status 的 --open-task-id |
|
||||
| `chat message list` | `openMessageId` | recall 的 --msg-id |
|
||||
| `chat message search` | `nextCursor` | 下次 message search 的 --cursor |
|
||||
| `chat message search-advanced` | `nextCursor` | 下次 message search-advanced 的 --cursor |
|
||||
| `chat search-common` | `openConversationId` | message send/list 等的 --group |
|
||||
| `chat message list` | `openMsgId` | message read-status 的 --message-id |
|
||||
| `chat group-role list` | `openRoleId` | group-role update/remove/set-user/remove-user 的 --role-id |
|
||||
| `chat message create-text-emotion` | `emotionId` | add-text-emotion 的 --emotion-id |
|
||||
| `chat category list` | `categoryId` | category list-conversations 的 --category-id |
|
||||
| `chat group get-by-group-id` | `openConversationId` | 同 chat search,将群号转为 openConversationId |
|
||||
| `chat message send-card` | `bizId` | update-card 的 --biz-id |
|
||||
| `chat message list` | `openMessageId` | message reply 的 --ref-msg-id、message forward 的 --msg-id |
|
||||
| `chat search` | `openConversationId` | set-top 的 --conversation-id、group-mute / group-mute-member 的 --group |
|
||||
@@ -1,206 +0,0 @@
|
||||
# 会话查询与媒体命令
|
||||
|
||||
### list-top-conversations (置顶会话)
|
||||
|
||||
#### 拉取置顶会话列表
|
||||
|
||||
拉取当前用户的置顶会话列表。分页参数 --limit 指定每页数量,--cursor 传分页游标(首次不传或传 0)。返回结果中 hasMore=true 时用 nextCursor 作为下次 --cursor 继续翻页。
|
||||
```
|
||||
Usage:
|
||||
dws chat list-top-conversations [flags]
|
||||
Example:
|
||||
dws chat list-top-conversations --limit 1000
|
||||
dws chat list-top-conversations --limit 1000 --cursor <nextCursor>
|
||||
Flags:
|
||||
--limit int 每页返回数量(默认 1000)
|
||||
--cursor int64 分页游标(首次不传或传 0,翻页传 nextCursor)
|
||||
--exclude-muted 是否排除已设置免打扰的会话(默认 false)
|
||||
|
||||
注意:
|
||||
- 用户询问"置顶会话"时,直接调用此命令返回置顶会话列表即可
|
||||
- 用户询问"置顶消息"时,需两步:先调用此命令拉取置顶会话列表获取各会话的 openConversationId,再用 `chat message list --group <openConversationId>` 分别拉取每个会话内的消息
|
||||
- 翻页:hasMore=true 时,用返回的 nextCursor 作为下次 --cursor
|
||||
```
|
||||
|
||||
### download-media (下载消息资源)
|
||||
|
||||
#### 下载消息中的资源(图片/视频/语音等)到本地
|
||||
|
||||
下载聊天消息中的图片、视频、语音等资源到本地文件。流程:先获取下载 URL,再 HTTP GET 下载。
|
||||
```
|
||||
Usage:
|
||||
dws chat message download-media [flags]
|
||||
Example:
|
||||
dws chat message download-media --type mediaId --resource-id <mediaId> --message-id <openMessageId> --open-conversation-id <openConversationId> --output ./downloads/
|
||||
dws chat message download-media --type mediaId --resource-id <mediaId> --message-id <openMessageId> --open-conversation-id <openConversationId> --output ./photo.jpg
|
||||
Flags:
|
||||
--type string 资源类型: mediaId (必填)
|
||||
--resource-id string 资源 ID,mediaId 类型时为消息中的 mediaId 值 (必填)
|
||||
--message-id string 消息 openMessageId (必填)
|
||||
--open-conversation-id string 会话 openConversationId (必填)
|
||||
--output string 本地保存路径,文件或目录 (必填)
|
||||
|
||||
注意:
|
||||
- resource-id 从 `dws chat message list` 返回的消息内容中获取 mediaId
|
||||
- message-id 从 `dws chat message list` 返回的 openMessageId
|
||||
- open-conversation-id 从 `dws chat search` 获取 openConversationId
|
||||
- --output 如果指定目录,文件名会从下载 URL 中自动推断
|
||||
```
|
||||
|
||||
### search-common (搜索共同群)
|
||||
|
||||
#### 搜索共同群 — 查询指定人共同所在的群聊
|
||||
|
||||
根据昵称列表搜索共同群聊。--nicks 指定要搜索的人员昵称(逗号分隔,必填)。--match-mode 控制匹配模式:AND 表示所有人都在群里,OR 表示任一人在群里(默认 AND)。分页参数 --limit(默认 20)和 --cursor(默认 "0")始终传递;hasMore=true 时用返回的 nextCursor 作为下次 --cursor 继续翻页。
|
||||
```
|
||||
Usage:
|
||||
dws chat search-common [flags]
|
||||
Example:
|
||||
dws chat search-common --nicks "风雷,山乔" --limit 20 --cursor 0
|
||||
dws chat search-common --nicks "天鸡,乐函" --match-mode OR --limit 20 --cursor 0
|
||||
dws chat search-common --nicks "风雷,山乔,天鸡" --limit 10 --cursor <nextCursor>
|
||||
Flags:
|
||||
--nicks string 要搜索的昵称列表,逗号分隔 (必填)
|
||||
--match-mode string 匹配模式:AND=所有人都在群里,OR=任一人在群里(默认 AND)
|
||||
--limit int 每页返回数量(默认 20)
|
||||
--cursor string 分页游标(默认 "0",翻页传 nextCursor)
|
||||
--exclude-muted 是否排除已设置免打扰的群聊(默认 false)
|
||||
|
||||
注意:
|
||||
- --nicks 传人员昵称(花名),逗号分隔,如 "风雷,山乔"
|
||||
- --match-mode AND 表示群里必须包含所有指定的人;OR 表示包含任意一人即可
|
||||
- 翻页:hasMore=true 时,用返回的 nextCursor 作为下次 --cursor
|
||||
```
|
||||
|
||||
### conversation-info (获取会话基础信息)
|
||||
|
||||
#### 获取会话基础信息
|
||||
|
||||
获取指定会话的基础信息。发送本地文件消息请优先使用 `dws chat message send --msg-type file --file-path <本地文件>`,CLI 不再要求调用方获取或传递 spaceId。
|
||||
```
|
||||
Usage:
|
||||
dws chat conversation-info [flags]
|
||||
Example:
|
||||
dws chat conversation-info --group <openConversationId> --format json
|
||||
dws chat conversation-info --user <userId> --format json
|
||||
dws chat conversation-info --open-dingtalk-id <openDingTalkId> --format json
|
||||
Flags:
|
||||
--group string 群聊 openConversationId(群聊时使用)
|
||||
--user string 单聊对方 userId(单聊时使用)
|
||||
--open-dingtalk-id string 单聊对方 openDingTalkId(单聊时使用)
|
||||
|
||||
注意:
|
||||
- --group、--user、--open-dingtalk-id 互斥,必须且只能指定其一
|
||||
- --group 的别名: --id, --chat, --conversation-id (均可替代 --group)
|
||||
- 文件发送不再依赖调用方读取 newCSpaceIdIM;使用 `dws chat message send --msg-type file --file-path <本地文件>` 会自动上传到会话文件空间
|
||||
```
|
||||
|
||||
#### 合并转发多条消息 — 将多条消息合并后转发到目标会话(源/目标会话均支持单聊/群聊)
|
||||
```
|
||||
Usage:
|
||||
dws chat message combine-forward [flags]
|
||||
Example:
|
||||
dws chat message combine-forward --src-conversation-id <srcOpenCid> --msg-ids <id1>,<id2>,<id3> --dest-conversation-id <destOpenCid>
|
||||
dws chat message combine-forward --src-conversation-id <srcOpenCid> --msg-ids <id1>,<id2> --dest-conversation-id <destOpenCid> --uuid <idempotencyKey>
|
||||
Flags:
|
||||
--src-conversation-id string 源会话 openConversationId (必填)
|
||||
--msg-ids string 源消息 openMessageId 列表,逗号分隔 (必填)
|
||||
--dest-conversation-id string 目标会话 openConversationId (必填)
|
||||
--uuid string 幂等键(可选)
|
||||
|
||||
注意:
|
||||
- 与 chat message forward 区别: forward 转单条,combine-forward 合并多条为一条转发
|
||||
- --msg-ids 多个消息 ID 用逗号分隔,无顺序要求
|
||||
```
|
||||
|
||||
#### 转发话题消息 — 将话题消息从源会话转发到目标会话
|
||||
```
|
||||
Usage:
|
||||
dws chat message forward-topic [flags]
|
||||
Example:
|
||||
dws chat message forward-topic --src-msg-id <srcOpenMessageId> --src-conversation-id <srcOpenConversationId> --src-thread-id <srcOpenConvThreadId> --dest-conversation-id <destOpenConversationId>
|
||||
Flags:
|
||||
--src-msg-id string 源消息 openMessageId (必填,要转发的消息)
|
||||
--src-conversation-id string 源会话 openConversationId (必填,消息所在的会话)
|
||||
--src-thread-id string 话题 ID (必填,格式: convThread + 加密后的convThreadId)
|
||||
--dest-conversation-id string 目标会话 openConversationId (必填,转发到的会话)
|
||||
|
||||
注意:
|
||||
- 与 chat message forward 区别: forward 转发普通单条消息,forward-topic 专用于转发话题消息
|
||||
- --src-thread-id 格式为 "convThread" + 加密后的 convThreadId,可通过 dws chat message list 返回的话题信息获取
|
||||
```
|
||||
|
||||
#### 钉住某条消息(Pin) — 将指定消息设置为钉住状态
|
||||
```
|
||||
Usage:
|
||||
dws chat message set-pin-msg [flags]
|
||||
Example:
|
||||
dws chat message set-pin-msg --open-conversation-id <openConversationId> --msg-id <openMessageId>
|
||||
Flags:
|
||||
--open-conversation-id string (必填)会话 openConversationId(支持群聊/单聊)
|
||||
--msg-id string (必填)消息 openMessageId
|
||||
|
||||
注意:
|
||||
- 钉住消息后,会话成员均可在会话中看到被钉住的消息
|
||||
```
|
||||
|
||||
#### 取消钉住某条消息(Unpin) — 取消指定消息的钉住状态
|
||||
```
|
||||
Usage:
|
||||
dws chat message unset-pin-msg [flags]
|
||||
Example:
|
||||
dws chat message unset-pin-msg --open-conversation-id <openConversationId> --msg-id <openMessageId>
|
||||
Flags:
|
||||
--open-conversation-id string (必填)会话 openConversationId(支持群聊/单聊)
|
||||
--msg-id string (必填)消息 openMessageId
|
||||
|
||||
注意:
|
||||
- 取消钉住后消息仍保留在会话中,只是不再被标记为钉住状态
|
||||
```
|
||||
|
||||
#### 拉取某个会话中钉住的消息列表 — 拉取指定会话中被钉住的消息列表
|
||||
```
|
||||
Usage:
|
||||
dws chat message list-pin-msg [flags]
|
||||
Example:
|
||||
dws chat message list-pin-msg --open-conversation-id <openConversationId>
|
||||
dws chat message list-pin-msg --open-conversation-id <openConversationId> --size 50
|
||||
dws chat message list-pin-msg --open-conversation-id <openConversationId> --cursor <nextCursor> --size 20
|
||||
Flags:
|
||||
--open-conversation-id string (必填)会话 openConversationId(支持群聊/单聊)
|
||||
--cursor string (选填)分页游标,首次不传,翻页时传上次返回的 nextCursor
|
||||
--size int (选填)一次拉取的消息数量(默认 20,最大 100)
|
||||
|
||||
注意:
|
||||
- 与 `chat message list` 区别: list-pin-msg 只返回被钉住的消息;list 拉取全部消息
|
||||
- 分页: hasMore=true 时,用返回的 nextCursor 作为下次 --cursor 继续翻页
|
||||
```
|
||||
|
||||
#### 置顶某条消息 — 将指定消息设置为置顶状态
|
||||
```
|
||||
Usage:
|
||||
dws chat message set-top-msg [flags]
|
||||
Example:
|
||||
dws chat message set-top-msg --open-conversation-id <openConversationId> --msg-id <openMessageId>
|
||||
Flags:
|
||||
--open-conversation-id string (必填)会话 openConversationId(支持群聊/单聊)
|
||||
--msg-id string (必填)消息 openMessageId
|
||||
|
||||
注意:
|
||||
- 置顶消息后,会话成员可在会话顶部看到该条消息
|
||||
- 与 `chat set-top`(会话置顶)不同:set-top-msg 是将会话内某条消息置顶;set-top 是将整个会话在列表中置顶
|
||||
```
|
||||
|
||||
#### 取消置顶某条消息 — 取消指定消息的置顶状态
|
||||
```
|
||||
Usage:
|
||||
dws chat message unset-top-msg [flags]
|
||||
Example:
|
||||
dws chat message unset-top-msg --open-conversation-id <openConversationId> --msg-id <openMessageId>
|
||||
Flags:
|
||||
--open-conversation-id string (必填)会话 openConversationId(支持群聊/单聊)
|
||||
--msg-id string (必填)消息 openMessageId
|
||||
|
||||
注意:
|
||||
- 取消置顶后消息仍保留在会话中,只是不再被标记为置顶状态
|
||||
```
|
||||
@@ -1,483 +0,0 @@
|
||||
# 群组、群身份与群搜索命令
|
||||
|
||||
## 命令总览
|
||||
|
||||
### group (群组管理)
|
||||
|
||||
#### 创建群 — 支持内部群/外部群/普通群/话题圈,当前登录用户自动成为群主
|
||||
|
||||
创建一个群聊,支持指定群名称、初始成员列表、群类型和话题模式。默认创建内部群。
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws chat group create [flags]
|
||||
Example:
|
||||
dws chat group create --name "Q1 项目冲刺群" --users userId1,userId2,userId3
|
||||
dws chat group create --name "外部合作群" --users userId1,userId2 --type EXTERNAL
|
||||
dws chat group create --name "话题圈" --users userId1,userId2 --thread
|
||||
Flags:
|
||||
--name string 群名称 (必填)
|
||||
--users string 成员 userId 或 openDingTalkId(可混传),用户本身会自动加入无需包含,逗号分隔,不超过20个 (必填)
|
||||
--type string 群类型: INTERNAL(内部群,默认)/EXTERNAL(外部群)/NORMAL(普通群)
|
||||
--thread 开启话题模式,将创建话题圈
|
||||
```
|
||||
|
||||
创建时当前登录用户自动成为群主。需要指定他人为群主时,先创建群并从返回中取 `openConversationId`,再执行 `dws chat group transfer-owner --group <openConversationId> --new-owner <openDingTalkId>`。
|
||||
|
||||
#### 查看群成员列表 — 分页查询指定群聊的成员
|
||||
```
|
||||
Usage:
|
||||
dws chat group members [flags]
|
||||
Example:
|
||||
dws chat group members --id <openconversation_id>
|
||||
Flags:
|
||||
--cursor string 分页游标,首次从 0 开始
|
||||
--id string 群 ID / openconversation_id (必填)
|
||||
```
|
||||
|
||||
#### 添加群成员 — 向指定群聊添加成员,需传入群 ID 与用户 ID 列表
|
||||
```
|
||||
Usage:
|
||||
dws chat group members add [flags]
|
||||
Example:
|
||||
dws chat group members add --id <openconversation_id> --users userId1,userId2
|
||||
Flags:
|
||||
--id string 群 ID / openconversation_id (必填)
|
||||
--users string 要添加的用户 userId 列表,逗号分隔 (必填)
|
||||
```
|
||||
|
||||
#### 移除群成员 — 从指定群聊中移除成员,需传入群 ID 与待移除的用户 ID 列表
|
||||
```
|
||||
Usage:
|
||||
dws chat group members remove [flags]
|
||||
Example:
|
||||
dws chat group members remove --id <openconversation_id> --users userId1,userId2
|
||||
Flags:
|
||||
--id string 群 ID / openconversation_id (必填)
|
||||
--users string 要移除的用户 userId 列表,逗号分隔 (必填)
|
||||
```
|
||||
|
||||
#### 将机器人添加到群中 — 将自定义机器人添加到当前用户有管理权限的群聊中,如果没有权限则会报错
|
||||
```
|
||||
Usage:
|
||||
dws chat group members add-bot [flags]
|
||||
Example:
|
||||
dws chat group members add-bot --robot-code <robot-code> --id <openconversation_id>
|
||||
Flags:
|
||||
--id string 群聊 openConversationId (必填)
|
||||
--robot-code string 机器人 Code (必填)
|
||||
```
|
||||
|
||||
#### 从群内移除机器人 — 将指定机器人从群聊中移除,需要群管理员或群主权限
|
||||
```
|
||||
Usage:
|
||||
dws chat group members remove-bot [flags]
|
||||
Example:
|
||||
dws chat group members remove-bot --id <openConversationId> --bot-id <openBotId>
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
# 查询群内机器人: dws chat group bots --group <openConversationId>
|
||||
Flags:
|
||||
--id string 群聊 openConversationId (必填)
|
||||
--bot-id string 机器人 openBotId (必填)
|
||||
```
|
||||
|
||||
#### 批量查看群成员详情 — 根据成员 openDingTalkId 列表批量查询群成员详情信息
|
||||
```
|
||||
Usage:
|
||||
dws chat group members list-by-ids [flags]
|
||||
Example:
|
||||
dws chat group members list-by-ids --id <openConversationId> --users openDingTalkId1,openDingTalkId2
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
# 查询 openDingTalkId: dws contact user search --query "姓名"
|
||||
Flags:
|
||||
--id string 群 ID / openConversationId (必填)
|
||||
--users string 成员 openDingTalkId 列表,逗号分隔 (必填)
|
||||
```
|
||||
|
||||
#### 更新群名称
|
||||
```
|
||||
Usage:
|
||||
dws chat group rename [flags]
|
||||
Example:
|
||||
dws chat group rename --id <openconversation_id> --name "新群名"
|
||||
Flags:
|
||||
--id string 群 ID / openconversation_id (必填)
|
||||
--name string 修改后的群名称 (必填)
|
||||
```
|
||||
|
||||
#### 根据群号获取群聊信息 — 当用户只提供了数字群号而非 openConversationId 时,用此命令转换
|
||||
```
|
||||
Usage:
|
||||
dws chat group get-by-group-id [flags]
|
||||
Example:
|
||||
dws chat group get-by-group-id --group-id 12345678
|
||||
# 群号为数字类型的群ID
|
||||
Flags:
|
||||
--group-id int 群号 (必填,数字类型)
|
||||
```
|
||||
|
||||
#### 转让群主 — 将群主身份转让给群内其他成员
|
||||
```
|
||||
Usage:
|
||||
dws chat group transfer-owner [flags]
|
||||
Example:
|
||||
dws chat group transfer-owner --group <openConversationId> --new-owner <openDingTalkId>
|
||||
dws chat group transfer-owner --group <openConversationId> --user <userId>
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
# 查询人员: dws contact user search --query "姓名" --format json
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--new-owner string 新群主 openDingTalkId
|
||||
--user string 新群主 userId
|
||||
```
|
||||
|
||||
#### 获取群邀请链接 — 获取指定群聊的邀请加入链接
|
||||
|
||||
可选 --expires-seconds 指定链接有效期(秒),0 表示永久有效,不传则使用服务端默认值。
|
||||
```
|
||||
Usage:
|
||||
dws chat group invite-url [flags]
|
||||
Example:
|
||||
dws chat group invite-url --group <openConversationId>
|
||||
dws chat group invite-url --group <openConversationId> --expires-seconds 86400
|
||||
dws chat group invite-url --group <openConversationId> --expires-seconds 0
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--expires-seconds int64 链接有效期(秒),0 表示永久有效,不传使用服务端默认值
|
||||
```
|
||||
|
||||
#### 分享群聊链接到会话 — 将指定群的邀请链接分享到另一个会话或单聊用户
|
||||
|
||||
--target 和 --receiver 二选一:--target 指定目标会话,--receiver 指定单聊用户。
|
||||
```
|
||||
Usage:
|
||||
dws chat group share-invite [flags]
|
||||
Example:
|
||||
dws chat group share-invite --source <被分享群openConversationId> --target <目标会话openConversationId>
|
||||
dws chat group share-invite --source <被分享群openConversationId> --receiver <接收者openDingTalkId>
|
||||
dws chat group share-invite --source <openConversationId> --target <openConversationId> --expires-seconds 86400
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--source string 被分享群的 openConversationId (必填)
|
||||
--target string 接收分享消息的会话 openConversationId(与 --receiver 二选一)
|
||||
--receiver string 接收分享消息的单聊用户 openDingTalkId(与 --target 二选一)
|
||||
--expires-seconds int64 链接有效期(秒),0 表示永久有效,不传使用服务端默认值
|
||||
--uuid string 消息幂等键(可选)
|
||||
```
|
||||
|
||||
#### 退出群聊 — 当前用户退出指定群聊
|
||||
```
|
||||
Usage:
|
||||
dws chat group quit [flags]
|
||||
Example:
|
||||
dws chat group quit --group <openConversationId>
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
```
|
||||
|
||||
#### 更新群头像 — 更新指定群聊的群头像
|
||||
```
|
||||
Usage:
|
||||
dws chat group update-icon [flags]
|
||||
Example:
|
||||
dws chat group update-icon --group <openConversationId> --icon-media-id <mediaId>
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--icon-media-id string 群头像 mediaId (必填)
|
||||
```
|
||||
|
||||
#### 更新群设置 — 更新指定群聊的设置项
|
||||
|
||||
--setting-key 指定设置项,--status 指定值(0=关闭,1=开启)。
|
||||
|
||||
支持的 settingKey:
|
||||
authority、joinValidation、onlyAdminCanAtAll、searchable、addFriendForbidden、
|
||||
toolbarStatus、pluginCustomizeVerify、onlyAdminCanDING、allMembersCanCreateMcsConf、
|
||||
onlyAdminCanSetMsgTop、onlyAdminCanPinMsg、onlyAdminCanSendFile、
|
||||
allMembersCanCreateCalendar、groupEmailDisabled、groupRedEnvelopeSwitch、
|
||||
groupLiveAuthority、groupBillAuthority
|
||||
```
|
||||
Usage:
|
||||
dws chat group update-settings [flags]
|
||||
Example:
|
||||
dws chat group update-settings --group <openConversationId> --setting-key searchable --status 1
|
||||
dws chat group update-settings --group <openConversationId> --setting-key onlyAdminCanAtAll --status 0
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--setting-key string 群设置项 key (必填)
|
||||
--status int 设置值: 0=关闭, 1=开启 (必填)
|
||||
```
|
||||
|
||||
#### 设置用户在群内的群昵称 — 设置当前用户在指定群聊内的个人群昵称
|
||||
```
|
||||
Usage:
|
||||
dws chat group update-nick [flags]
|
||||
Example:
|
||||
dws chat group update-nick --group <openConversationId> --nick "我的群昵称"
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--nick string 个人群昵称 (必填)
|
||||
```
|
||||
|
||||
#### 设置群备注 — 设置当前用户对指定群聊的备注名称(仅自己可见)
|
||||
```
|
||||
Usage:
|
||||
dws chat group update-alias [flags]
|
||||
Example:
|
||||
dws chat group update-alias --group <openConversationId> --alias-title "项目A群"
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--alias-title string 群备注标题 (必填)
|
||||
```
|
||||
|
||||
#### 查看群内所有机器人 — 获取指定群聊中的所有机器人列表
|
||||
```
|
||||
Usage:
|
||||
dws chat group bots [flags]
|
||||
Example:
|
||||
dws chat group bots --group <openConversationId>
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
```
|
||||
|
||||
#### 解散群聊 — 解散指定群聊,操作不可逆,需要群主权限
|
||||
```
|
||||
Usage:
|
||||
dws chat group dismiss [flags]
|
||||
Example:
|
||||
dws chat group dismiss --group <openConversationId>
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
```
|
||||
|
||||
#### 设置新成员入群可查看历史消息选项 — 控制新加入成员可见的历史消息范围
|
||||
```
|
||||
Usage:
|
||||
dws chat group set-history [flags]
|
||||
Example:
|
||||
dws chat group set-history --group <openConversationId> --option RECENT_100
|
||||
dws chat group set-history --group <openConversationId> --option FORBIDDEN
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--option string 可见范围: FORBIDDEN | RECENT_100 | ALL (必填)
|
||||
|
||||
注意:
|
||||
- FORBIDDEN:禁止查看历史消息(默认安全策略)
|
||||
- RECENT_100:可查看最近 100 条消息(最常用)
|
||||
- ALL:可查看全部历史消息(开放性最高)
|
||||
```
|
||||
|
||||
#### 拉取我创建/管理的群 — 查询当前用户作为群主或管理员的群列表
|
||||
|
||||
> 重要限制:此命令只能拉取到用户作为「群主」或「管理员」的群,无法获取普通成员身份的群聊。如果用户要找的群不在结果中,必须改用 `dws chat search --query "关键词"` 按名称搜索。
|
||||
|
||||
可通过 --role 过滤角色:OWNER 仅群主、ADMIN 仅管理员,不传则返回全部。可通过 --limit 限制返回数量,不传则返回所有符合条件的群。
|
||||
```
|
||||
Usage:
|
||||
dws chat group list-my-groups [flags]
|
||||
Example:
|
||||
dws chat group list-my-groups
|
||||
dws chat group list-my-groups --role OWNER
|
||||
dws chat group list-my-groups --role ADMIN --limit 10
|
||||
Flags:
|
||||
--role string 角色过滤: OWNER(仅群主) / ADMIN(仅管理员),不传返回全部
|
||||
--limit int 最多返回群数量,不传返回全部
|
||||
--exclude-muted 是否排除已设置免打扰的群聊(默认 false)
|
||||
|
||||
注意:
|
||||
- 底层先拉取最近 1000 条会话,剔除单聊和话题圈后筛选出群主/管理员的群
|
||||
- 内部群会校验 orgId 归属
|
||||
- 不传 --role 时返回群主 + 管理员的所有群
|
||||
```
|
||||
|
||||
#### 发布群公告 — 在指定群聊中发布群公告,支持 Markdown、定时发布
|
||||
|
||||
正文为 Markdown 格式。支持标题、加粗、斜体、删除线、行内代码、链接、代码块、有序/无序/任务列表、表格、引用、分割线、图片、段落、换行。
|
||||
```
|
||||
Usage:
|
||||
dws chat group notice create [flags]
|
||||
Example:
|
||||
dws chat group notice create --group <openConversationId> --content "今晚 22 点系统维护,请提前保存工作内容"
|
||||
dws chat group notice create --group <openConversationId> --content "# 重要通知\n请大家查收" --sticky --send-ding
|
||||
dws chat group notice create --group <openConversationId> --content "明早九点例会" --run-at "2026-07-03T09:00:00+08:00"
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--content string 公告正文,Markdown 格式 (必填)
|
||||
--sticky 是否吊顶置顶(默认 false)
|
||||
--send-ding 是否发 DING 提醒(默认 false)
|
||||
--run-at string 定时发布时间 ISO-8601(如 2026-07-03T09:00:00+08:00,传入则定时发布)
|
||||
|
||||
注意:
|
||||
- 下划线/字体色/背景色/字号为编辑器专属能力,Markdown 无对应语法,无法通过本命令表达
|
||||
- --run-at 建议带时区偏移,不带偏移时按北京时区处理
|
||||
```
|
||||
|
||||
#### 修改群公告 — 整体替换指定群公告的内容
|
||||
```
|
||||
Usage:
|
||||
dws chat group notice edit [flags]
|
||||
Example:
|
||||
dws chat group notice edit --group <openConversationId> --notice-id <dataId> --content "更新后的公告内容"
|
||||
dws chat group notice edit --group <openConversationId> --notice-id <dataId> --content "更新后的公告内容" --sticky --send-ding
|
||||
# 查询公告 ID: dws chat group notice list --group <openConversationId>
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--notice-id string 群公告 dataId (必填)
|
||||
--content string 公告新正文,Markdown 格式 (必填)
|
||||
--sticky 是否吊顶置顶(不传按 false 处理)
|
||||
--send-ding 是否发 DING 提醒(默认 false)
|
||||
|
||||
注意:
|
||||
- 修改会整体替换原公告正文,需传入完整的新内容
|
||||
```
|
||||
|
||||
#### 查看群公告详情 — 查询单条群公告的详细信息
|
||||
```
|
||||
Usage:
|
||||
dws chat group notice get [flags]
|
||||
Example:
|
||||
dws chat group notice get --group <openConversationId> --notice-id <dataId>
|
||||
# 查询公告 ID: dws chat group notice list --group <openConversationId>
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--notice-id string 群公告 dataId (必填)
|
||||
|
||||
注意:
|
||||
- 返回正文摘要、吊顶状态、发布者、已读人数/应收人数、点赞/评论数、是否可编辑、是否已读、是否定时公告等信息
|
||||
```
|
||||
|
||||
#### 查看群公告列表 — 分页拉取指定群聊的群公告列表
|
||||
```
|
||||
Usage:
|
||||
dws chat group notice list [flags]
|
||||
Example:
|
||||
dws chat group notice list --group <openConversationId>
|
||||
dws chat group notice list --group <openConversationId> --limit 20 --cursor <nextPageCursor>
|
||||
dws chat group notice list --group <openConversationId> --scheduled
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--limit int 每页返回数量(默认 10,最大 100)
|
||||
--cursor string 分页游标(首次不传,翻页传返回的 nextPageCursor)
|
||||
--scheduled 是否查询定时公告列表(默认 false,查询已发布公告)
|
||||
|
||||
注意:
|
||||
- 分页: hasMore=true 时用返回的 nextPageCursor 作为下次 --cursor
|
||||
- 默认查询已发布公告,传 --scheduled 查询尚未到发布时间的定时公告
|
||||
```
|
||||
|
||||
### group-role (群身份管理)
|
||||
|
||||
#### 查看群身份列表 — 拉取指定群聊的自定义群身份列表
|
||||
```
|
||||
Usage:
|
||||
dws chat group-role list [flags]
|
||||
Example:
|
||||
dws chat group-role list --group <openConversationId>
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
```
|
||||
|
||||
#### 添加群身份 — 在指定群中创建一个新的自定义群身份
|
||||
```
|
||||
Usage:
|
||||
dws chat group-role add [flags]
|
||||
Example:
|
||||
dws chat group-role add --group <openConversationId> --name "管理员"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--name string 群身份名称 (必填)
|
||||
```
|
||||
|
||||
#### 更新群身份名称 — 修改指定群身份的名称
|
||||
```
|
||||
Usage:
|
||||
dws chat group-role update [flags]
|
||||
Example:
|
||||
dws chat group-role update --group <openConversationId> --role-id <openRoleId> --name "新名称"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--role-id string 群身份 openRoleId,由 group-role list 返回 (必填)
|
||||
--name string 群身份新名称 (必填)
|
||||
```
|
||||
|
||||
#### 删除群身份 — 删除指定群聊中的某个自定义群身份
|
||||
```
|
||||
Usage:
|
||||
dws chat group-role remove [flags]
|
||||
Example:
|
||||
dws chat group-role remove --group <openConversationId> --role-id <openRoleId>
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--role-id string 群身份 openRoleId,由 group-role list 返回 (必填)
|
||||
```
|
||||
|
||||
#### 设置用户群身份 — 覆盖指定用户在群中的全部群身份(传空则清除所有身份)
|
||||
```
|
||||
Usage:
|
||||
dws chat group-role set-user [flags]
|
||||
Example:
|
||||
dws chat group-role set-user --group <openConversationId> --user <userId> --role-ids roleId1,roleId2
|
||||
# 查询人员: dws contact user search --query "姓名" --format json
|
||||
# 查询 role-id: dws chat group-role list --group <openConversationId>
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--user string 用户 userId(必填)
|
||||
--role-ids string 群身份 openRoleId 列表,逗号分隔 (必填),传空字符串则清除该用户所有群身份
|
||||
```
|
||||
|
||||
#### 移除用户的指定群身份 — 从用户身上移除指定的群身份(不影响其他群身份)
|
||||
```
|
||||
Usage:
|
||||
dws chat group-role remove-user [flags]
|
||||
Example:
|
||||
dws chat group-role remove-user --group <openConversationId> --user <userId> --role-ids roleId1,roleId2
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--user string 用户 userId(必填)
|
||||
--role-ids string 要移除的群身份 openRoleId 列表,逗号分隔 (必填)
|
||||
```
|
||||
|
||||
#### 查询群成员的群身份 — 查询指定群成员当前持有的所有群身份
|
||||
```
|
||||
Usage:
|
||||
dws chat group-role query-user [flags]
|
||||
Example:
|
||||
dws chat group-role query-user --group <openConversationId> --user <userId>
|
||||
Flags:
|
||||
--group string 群聊 openConversationId (必填)
|
||||
--user string 用户 userId(必填)
|
||||
```
|
||||
|
||||
### search (搜索群聊)
|
||||
|
||||
#### 根据关键词搜索群聊 — 分页返回匹配群聊列表
|
||||
|
||||
hasMore=true 时用返回的 nextCursor 作为下次 --cursor 继续翻页。
|
||||
|
||||
**注意:**
|
||||
1. query 不要拆分得太细,应使用群名称中连续的核心词作为关键词(如群名"项目冲刺群"应搜"项目冲刺"而非拆成"项目"+"冲刺"分别搜索)。
|
||||
2. 当搜索结果返回多个群聊时,应列出候选群让用户确认目标群聊,不要自行假定并直接进行后续操作。
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws chat search [flags]
|
||||
Example:
|
||||
dws chat search --query "项目冲刺"
|
||||
dws chat search --query "项目冲刺" --limit 20 --cursor 0
|
||||
Flags:
|
||||
--query string 搜索关键词 (必填)
|
||||
--limit int 每页返回数量(默认 20)
|
||||
--cursor string 分页游标(默认 "0",翻页传 nextCursor)
|
||||
--exclude-muted 是否排除已设置免打扰的群聊(默认 false)
|
||||
```
|
||||
@@ -1,13 +0,0 @@
|
||||
# 聊天能力索引
|
||||
|
||||
| 主题 | 详见 |
|
||||
|---|---|
|
||||
| 群创建/设置/成员/角色/搜索 | [`chat-group-commands.md`](./chat-group-commands.md) |
|
||||
| 消息发送/回复/转发/撤回与会话文件 | [`chat-message-file-commands.md`](./chat-message-file-commands.md) |
|
||||
| 会话查询、媒体下载、共同群 | [`chat-conversation-commands.md`](./chat-conversation-commands.md) |
|
||||
| 机器人、会话分组、免打扰、红点与入群审批 | [`chat-admin-commands.md`](./chat-admin-commands.md) |
|
||||
| 意图与工作流 | [`chat-intent.md`](./chat-intent.md) · [`chat-workflow.md`](./chat-workflow.md) · [`chat-composite.md`](./chat-composite.md) |
|
||||
| 上下文、注意事项与相关产品 | [`chat-context.md`](./chat-context.md) · [`chat-notes.md`](./chat-notes.md) · [`chat-related.md`](./chat-related.md) |
|
||||
| 表情/表情列表 | [`chat-emoji-list.md`](./chat-emoji-list.md) |
|
||||
| 通用消息流程 | [`01-messaging.md`](./01-messaging.md) |
|
||||
| 轻量流程 | [`lite-recipes.md`](./lite-recipes.md) |
|
||||
@@ -1,163 +0,0 @@
|
||||
# 意图判断
|
||||
|
||||
## 意图判断
|
||||
|
||||
用户说"我特别关注的人最近发了什么消息/关注的人最近聊了啥/星标联系人最近的动态" → `chat message list-focused`(零参数一行命令)
|
||||
用户说"某人发给我的消息/指定发送者的消息/某人最近的消息" → `chat message list-by-sender --sender-user-id <userId>` 或 `--sender-open-dingtalk-id <openDingTalkId>`(跨单聊+群聊)
|
||||
用户说"和某人的单聊聊天记录/拉某人单聊历史" → `chat message list --user <userId>` 或 `--open-dingtalk-id <openDingTalkId>`
|
||||
用户说"某个群的聊天记录" → `chat message list --group <openConversationId>`
|
||||
用户说"我最近所有消息/我今天的消息" → `chat message list-all --start <ISO> --end <ISO>`
|
||||
用户说"@我的消息/提及我的" → `chat message list-mentions --start <ISO> --end <ISO>`
|
||||
用户说"搜索消息里的关键词/包含XX的消息" → `chat message search-advanced --query "<关键词>"`(首选,严格超集)
|
||||
用户说"我和某人的共同群" → `chat search-common --nicks "<昵称1>,<昵称2>"`
|
||||
用户说"未读会话列表" → `chat message list-unread-conversations`
|
||||
用户说"群里某条话题的回复" → `chat message list-topic-replies --group <id> --topic-id <id>`
|
||||
用户说"回复话题/往话题里发消息" → 先用 `chat message list` 拉取获得 openConvThreadId,再 `chat message send --group <openConvThreadId> --text "..."`
|
||||
用户说"置顶会话/查看置顶" → `chat list-top-conversations` 列会话 → 再 `chat message list --group <id>` 拉消息(两步)
|
||||
用户说"置顶某条消息/把这条消息置顶/消息置顶" → `chat message set-top-msg`
|
||||
用户说"取消置顶消息/取消消息置顶" → `chat message unset-top-msg`
|
||||
|
||||
用户说"建群/创建群聊" → `chat group create`
|
||||
用户说"建外部群/创建外部群" → `chat group create --type EXTERNAL`
|
||||
用户说"建普通群" → `chat group create --type NORMAL`
|
||||
用户说"创建话题圈/建话题群" → `chat group create --thread`
|
||||
用户说"建群并指定群主/让某某当群主" → 先 `chat group create`,从返回取 `openConversationId`,再 `chat group transfer-owner --group <openConversationId> --new-owner <openDingTalkId>`
|
||||
用户说"搜索群/找群" → `chat search`
|
||||
用户说"我创建的群/我管理的群/我是群主的群/我当管理员的群" → `chat group list-my-groups`
|
||||
用户说"群成员/看群里有谁" → `chat group members`
|
||||
用户说"拉人进群/加群成员" → `chat group members add`
|
||||
用户说"踢人/移除群成员" → `chat group members remove`
|
||||
用户说"加机器人到群" → `chat group members add-bot`
|
||||
用户说"批量查群成员详情/按ID查群成员/查看指定成员信息" → `chat group members list-by-ids`
|
||||
用户说"改群名" → `chat group rename`
|
||||
用户说"聊天记录/会话消息/拉取会话" → `chat message list`
|
||||
用户说"某人发给我的消息/指定发送者/某人的消息" → `chat message list-by-sender`(用户未明确说"单聊"时优先使用,跨单聊/群聊)
|
||||
用户说"拉取和某人的单聊记录/单聊消息" → `chat message list --user`(用户明确说"单聊"时使用)
|
||||
用户说"@我的消息/at我的/提及我的" → `chat message list-mentions`
|
||||
用户说"未读消息会话/未读会话列表/我的未读会话" → `chat message list-unread-conversations`
|
||||
用户说"发群消息(以个人身份)" → `chat message send --group`
|
||||
用户说"发单聊消息(以个人身份)" → `chat message send --user`(有 userId 时)或 `chat message send --open-dingtalk-id`(有 openDingTalkId 时)
|
||||
用户说"机器人发消息/机器人群发" → `chat message send-by-bot`
|
||||
用户说"撤回我发的消息/撤回消息" → `chat message recall`(通过 IM 接口撤回当前用户自己发出的消息,需要 openConversationId + openMessageId)
|
||||
用户说"撤回机器人发的消息/机器人撤回消息" → `chat message recall-by-bot`(通过机器人接口撤回机器人发出的消息,需要 robot-code + processQueryKey)
|
||||
用户说"Webhook 发消息/告警消息" → `chat message send-by-webhook`
|
||||
用户说"话题回复/群话题消息回复/拉取话题回复" → `chat message list-topic-replies`
|
||||
用户说"所有消息/全部会话消息/拉取全部消息/时间范围内消息/我的消息/我今天的消息/查我的钉钉消息/最近的消息" → `chat message list-all`
|
||||
用户说"特别关注人的消息/关注的人的消息/星标联系人的消息" → `chat message list-focused`
|
||||
用户说"消息已读未读/谁看了消息/查读状态/消息读取状态" → `chat message read-status`
|
||||
用户说"查看我的机器人" → `chat bot search`
|
||||
用户说"搜索消息/查找关键词/搜一下消息里的XX" → 优先使用 `chat message search-advanced`(推荐首选,严格超集);仅在简单关键词搜索且无其他维度需求时可用 `chat message search`
|
||||
用户说"多维度搜索/按发送者搜索/按人搜消息/指定多个群搜索/@我的消息搜索" → `chat message search-advanced`(推荐首选,支持多维度组合搜索)
|
||||
用户说"查询消息发送状态/消息发没发成功/消息状态" → `chat message query-send-status`
|
||||
用户说"我和XX的共同群/我们都在哪些群/查共同群" → `chat search-common`
|
||||
用户说"置顶会话/我的置顶/查看置顶会话" → `chat list-top-conversations`
|
||||
用户说"置顶某条消息/把这条消息置顶" → `chat message set-top-msg`
|
||||
用户说"取消置顶消息/取消消息置顶" → `chat message unset-top-msg`
|
||||
用户说"查看会话分组/自定义分组" → `chat category list`
|
||||
用户说"某个分组下的会话/分组会话列表" → `chat category list-conversations`
|
||||
用户说"创建会话分组/新建分组/添加分组" → `chat category create`
|
||||
用户说"删除会话分组/移除分组" → `chat category delete`
|
||||
用户说"重命名分组/修改分组名称/更新分组名" → `chat category rename`
|
||||
用户说"把会话加到分组/将群移入分组/添加会话到分组" → `chat category add-conv`
|
||||
用户说"把会话从分组移出/将群从分组移除/从分组中删除会话" → `chat category remove-conv`
|
||||
用户说"根据群号查群信息/群号查群/群号转openConversationId" → `chat group get-by-group-id`(当用户发消息时只提供了群号,用此工具将群号转为 openConversationId,再调用发消息接口)
|
||||
用户说"查看群身份/群的自定义身份列表" → `chat group-role list`
|
||||
用户说"创建/添加群身份" → `chat group-role add`
|
||||
用户说"修改/更新群身份名称" → `chat group-role update`
|
||||
用户说"删除群身份" → `chat group-role remove`
|
||||
用户说"给某人设置群身份/设定用户的群身份" → `chat group-role set-user`
|
||||
用户说"移除某人的群身份/撤销群身份" → `chat group-role remove-user`
|
||||
用户说"查询某人的群身份/某人在群里有什么身份" → `chat group-role query-user`
|
||||
用户说"转让群主/换群主/群主转让" → `chat group transfer-owner`
|
||||
用户说"群邀请链接/入群链接/加群链接" → `chat group invite-url`
|
||||
用户说"分享群链接/把群分享给某人/群链接发到某群" → `chat group share-invite`
|
||||
用户说"创建智能分组/新建智能会话分组" → `chat category create-smart`
|
||||
用户说"批量查消息/按ID查消息/根据消息ID查" → `chat message list-by-ids`
|
||||
用户说"emoji回应/表情回应/给消息加表情" → `chat message add-emoji`
|
||||
用户说"取消emoji回应/移除表情回应" → `chat message remove-emoji`
|
||||
用户说"文字表情回应/添加文字表情" → `chat message add-text-emotion`
|
||||
用户说"取消文字表情回应/移除文字表情" → `chat message remove-text-emotion`
|
||||
用户说"创建文字表情/新建文字表情" → `chat message create-text-emotion`
|
||||
用户说"免打扰/消息免打扰/静音/开启免打扰/关闭免打扰" → `chat mute`
|
||||
用户说"引用回复/回复消息/引用消息回复" → `chat message reply`
|
||||
用户说"转发消息/转发一条消息/把消息转发到另一个群" → `chat message forward`
|
||||
用户说"合并转发/批量转发/合并转发多条消息" → `chat message combine-forward`
|
||||
用户说"转发话题/转发话题消息/话题转发到另一个群" → `chat message forward-topic`
|
||||
用户说"群机器人列表/群里有哪些机器人/查看群机器人" → `chat group bots`
|
||||
用户说"从群里移除机器人/踢出机器人" → `chat group members remove-bot`
|
||||
用户说"搜索机器人/找机器人/查机器人/帮我找XXX机器人" → `chat bot find`(全部可用机器人,额外返回 openDingTalkId 可发单聊)
|
||||
用户说"给机器人发单聊/给机器人发消息/跟机器人聊天" → 必须先 `chat bot find`(拿 openDingTalkId)→ 再 `chat message send --open-dingtalk-id`(search 没有 openDingTalkId,无法发单聊)
|
||||
用户说"我创建的机器人/我的机器人/我自己的机器人/查看我的机器人" → `chat bot search`(仅我创建的机器人,无 openDingTalkId)
|
||||
用户说"解散群/解散群聊" → `chat group dismiss`
|
||||
用户说"设置历史消息/新成员看历史/新成员可见消息" → `chat group set-history`
|
||||
用户说"置顶会话/取消置顶/会话置顶" → `chat set-top`(设置/取消置顶),`chat list-top-conversations`(查看置顶列表)
|
||||
用户说"全员禁言/群禁言/解除禁言" → `chat group-mute`
|
||||
用户说"禁言某人/指定成员禁言/解除某人禁言" → `chat group-mute-member`
|
||||
用户说"设管理员/取消管理员/设置群管理员" → `chat group set-admin`
|
||||
用户说"改群昵称/设置群昵称/我在群里的名字" → `chat group update-nick`
|
||||
用户说"群备注/给群加备注/修改群备注" → `chat group update-alias`
|
||||
用户说"隐藏会话/隐藏群聊/隐藏对话" → `chat hide`
|
||||
用户说"关闭@所有人通知/屏蔽@所有人/不接收@all" → `chat mute-at-all`
|
||||
用户说"开启@所有人通知/恢复@所有人提醒" → `chat mute-at-all --off`
|
||||
用户说"关闭红包通知/屏蔽红包/不接收红包提醒" → `chat mute-red-envelope`
|
||||
用户说"开启红包通知/恢复红包提醒" → `chat mute-red-envelope --off`
|
||||
|
||||
关键区分:
|
||||
- `chat search` — 搜**群/会话名**返回 `openConversationId`,**不**搜消息内容;要搜消息内容请用 `chat message search-advanced`(首选)/ `chat message search` / `list-by-sender` / `list-all`,**勿混淆**
|
||||
- `chat message list` — 拉取指定会话的消息(需指定 --group 或 --user),按时间点 + 方向翻页
|
||||
- `chat message list --user` — list 的单聊模式,拉取与指定用户的单聊记录(用户明确说"单聊""私聊"时使用)
|
||||
- `chat message list-by-sender` — 搜索指定发送者发给我的消息,跨所有会话(单聊+群聊均包含,用户只说"某人发的消息"时优先使用)
|
||||
- `chat message list-mentions` — 拉取 @我 的消息(跨单聊/群聊,可选指定群)
|
||||
- `chat message list-unread-conversations` — 拉取当前用户存在未读消息的会话列表(可选 `--count`)
|
||||
- `chat message read-status` — 查询指定消息的已读/未读状态(仅消息发送者可查询自己发的消息,需指定 --group 和 --message-id,可选 --target-open-dingtalk-ids 查特定人)
|
||||
- `chat message list-all` — 拉取当前用户所有会话的消息,按时间范围 + cursor 分页。只要用户没有指定某个具体的会话(如某个群名、某个人名),即使提到"单聊消息""群聊消息"等笼统范围,也应路由到此命令
|
||||
- `chat message list-topic-replies` — 拉取群话题的回复消息列表
|
||||
- `chat message list-focused` — 拉取特别关注人的消息,cursor 分页
|
||||
- `chat list-top-conversations` — 拉取置顶会话列表(用户询问"置顶会话"时路由到此),cursor 分页
|
||||
- `chat message send` — 以当前用户身份发消息(群聊或单聊),text 为位置参数;发图片/本地文件统一用 `--msg-type file --file-path <本地路径>`(任意扩展名一条命令直发);`--msg-type image --media-id` 仅作旧链路兼容(上游已持有 mediaId 时使用)
|
||||
- `chat message search` — 按关键词搜索消息内容(跨所有会话,可选指定群)
|
||||
- `chat search-common` — 搜索共同群,查询指定人共同所在的群聊(AND=所有人都在,OR=任一人在)
|
||||
- `chat message send-by-bot` — 以**机器人**身份发消息(群聊或单聊),text 为 --text flag
|
||||
- `chat message send-by-webhook` — 通过**自定义机器人 Webhook** 发群消息
|
||||
- `chat message recall-by-bot` — 通过**机器人接口**撤回机器人发出的消息,需要 `--robot-code` + `--keys`(发送时返回的 processQueryKey);传 `--group` 为群聊撤回,不传为单聊撤回
|
||||
- `chat message recall` — 通过 **IM 接口**撤回当前用户自己发出的消息,需要 `--conversation-id`(openConversationId)+ `--msg-id`(openMessageId,可通过 `chat message list` 获取);群聊单聊均通过 `--conversation-id` 区分
|
||||
- `chat message query-send-status` — 查询个人发送的消息的发送状态(需 send 返回的 openTaskId)
|
||||
- `chat message search-advanced` — 多维度搜索消息(支持关键词、发送者、@我、@指定人、多个会话等维度组合,与 `search` 的区别:`search` 仅支持关键词且必填,`search-advanced` 所有参数均可选)
|
||||
- `chat message list-by-ids` — 根据消息 ID 批量查询消息(最多 50 条)
|
||||
- `chat message add-emoji` / `remove-emoji` — 对消息添加/移除 emoji 表情回应
|
||||
- `chat message add-text-emotion` / `remove-text-emotion` — 对消息添加/移除文字表情回应
|
||||
- `chat message create-text-emotion` — 创建文字表情模板,返回 emotionId 供 add-text-emotion 使用
|
||||
- `chat category list` — 获取用户自定义会话分组列表
|
||||
- `chat category list-conversations` — 拉取指定分组下的会话列表
|
||||
- `chat category create` — 创建用户自定义会话分组
|
||||
- `chat category delete` — 删除用户自定义会话分组
|
||||
- `chat category rename` — 更新用户自定义会话分组的名称
|
||||
- `chat category add-conv` — 将会话移动到指定的自定义分组中
|
||||
- `chat category remove-conv` — 将会话从指定的自定义分组中移出
|
||||
- `chat mute` — 开启/关闭会话消息免打扰(默认开启,--off 关闭)
|
||||
- `chat group transfer-owner` — 转让群主
|
||||
- `chat group invite-url` — 获取群邀请链接
|
||||
- `chat group share-invite` — 分享群聊链接到会话(--target 指定目标会话,--receiver 指定单聊用户,二选一)
|
||||
- `chat category create-smart` — 创建智能会话分组(可指定群名称关键词和成员作为匹配规则)
|
||||
- `chat message reply` — 引用回复消息(在群聊中引用某条消息并回复文字)
|
||||
- `chat message forward` — 转发单条消息(将一条消息从源会话转发到目标会话)
|
||||
- `chat set-top` — 设置/取消会话置顶(默认置顶,--off 取消)
|
||||
- `chat message set-top-msg` — 置顶会话内某条消息(与 chat set-top 不同:后者是会话列表置顶,前者是消息置顶)
|
||||
- `chat message unset-top-msg` — 取消会话内某条消息的置顶状态
|
||||
- `chat group-mute` — 全员禁言/取消全员禁言(默认禁言,--off 取消)
|
||||
- `chat group-mute-member` — 指定群成员禁言/取消禁言(需指定 --users 和 --mute-time)
|
||||
- `chat group set-admin` — 设置/取消群管理员(默认设为管理员,--off 取消)
|
||||
- `chat group update-nick` — 设置用户在群内的群昵称
|
||||
- `chat group update-alias` — 设置群备注(仅自己可见)
|
||||
- `chat hide` — 在会话列表中隐藏会话(支持单聊/群聊,收到新消息时重新出现)
|
||||
- `chat mute-at-all` — 关闭/开启 @所有人消息提醒(默认关闭,--off 恢复)
|
||||
- `chat mute-red-envelope` — 关闭/开启红包消息提醒(默认关闭,--off 恢复)
|
||||
|
||||
## openDingTalkId 获取方式
|
||||
|
||||
多个命令参数需要 openDingTalkId(如 --open-dingtalk-id、--at-open-dingtalk-ids、--sender-open-dingtalk-id),统一获取方式如下:
|
||||
|
||||
1. 若知道姓名:`dws contact user search --query "姓名"` → 直接从结果中获取 openDingTalkId
|
||||
2. 若只有 userId:先 `dws contact user get --ids <userId>` 获取姓名 → 再 `dws contact user search --query "姓名"` 获取 openDingTalkId
|
||||
|
||||
openDingTalkId 为当前用户视角下的目标用户唯一标识,不可跨用户共享。
|
||||
@@ -1,610 +0,0 @@
|
||||
# 消息与会话文件命令
|
||||
|
||||
### message (会话消息管理)
|
||||
|
||||
#### 拉取会话消息内容 — 拉取指定群聊或单聊的会话消息内容
|
||||
|
||||
--group 指定群聊,--user 指定单聊用户(通过 userId),--open-dingtalk-id 指定单聊用户(通过 openDingTalkId),三者互斥。推荐使用 --direction 控制时间方向:newer 表示从给定时间往现在拉,older 表示从给定时间往以前拉。--forward 为旧兼容参数:true 等价 newer,false 等价 older。hasMore=true 时用结果中的边界 createTime 作为下次 --time 翻页。引用回复消息会带 `quotedMessage`;被引用的原消息是合并转发或图片时,类型与内容也会保留在引用上下文中。
|
||||
```
|
||||
Usage:
|
||||
dws chat message list [flags]
|
||||
Example:
|
||||
dws chat message list --group <openconversation_id> --time "2025-03-01 00:00:00"
|
||||
dws chat message list --user <userId> --time "2025-03-01 00:00:00" --limit 50
|
||||
dws chat message list --open-dingtalk-id <openDingTalkId> --time "2025-03-01 00:00:00" --limit 50
|
||||
dws chat message list --group <openconversation_id> --time "2025-03-01 00:00:00" --direction newer
|
||||
dws chat message list --group <openconversation_id> --time "2025-03-01 00:00:00" --direction older
|
||||
Flags:
|
||||
--direction string 时间方向: newer=从给定时间往现在拉,older=从给定时间往以前拉(推荐)
|
||||
--forward 旧兼容参数: true 等价 --direction newer,false 等价 --direction older (default true)
|
||||
--group string 群聊 openconversation_id(群聊时必填)
|
||||
--limit int 返回数量,不传则不限制
|
||||
--time string 开始时间,格式: yyyy-MM-dd HH:mm:ss (必填)
|
||||
--user string 单聊用户 userId(单聊时与 --open-dingtalk-id 二选一)
|
||||
--open-dingtalk-id string 单聊用户 openDingTalkId(单聊时与 --user 二选一,适用于三方应用等无法获取 userId 的场景)
|
||||
|
||||
注意:
|
||||
- --group、--user、--open-dingtalk-id 三者互斥,只需指定其一:群聊用 --group,单聊用 --user 或 --open-dingtalk-id
|
||||
- --user 和 --open-dingtalk-id 都是发起单聊消息拉取,区别在于用不同格式的用户标识:
|
||||
- --user 传 userId(企业内部应用常用)
|
||||
- --open-dingtalk-id 传 openDingTalkId(三方应用或跨组织场景常用,无法获取 userId 时使用)
|
||||
- --group 的别名: --id, --chat, --conversation-id (均可替代 --group)
|
||||
- 时间方向:优先使用 --direction newer/older;仅为兼容旧调用保留 --forward。两者同时传入且语义冲突时会报错
|
||||
- 翻页:hasMore=true 时,用结果中的边界 createTime 作为下次 --time
|
||||
- 处理引用回复时读取 `quotedMessage`,不要只看回复正文;合并转发与图片引用的原消息内容也在该上下文中
|
||||
- 话题圈消息拉取流程:如果返回的会话消息中包含 openConvThreadId 字段,说明是话题类消息。要获取完整的话题内容,需要两步操作:(1) 先通过 dws chat message list 拉取话题主消息(即话题帖子本身);(2) 再调用 dws chat message list-topic-replies --group <openConversationId> --topic-id <openConvThreadId> 分页拉取该话题下的所有回复消息。只有话题主消息 + 回复列表合在一起,才是一条话题的完整内容。
|
||||
```
|
||||
|
||||
#### 以当前用户身份发送消息 — --group 群聊 / --user 或 --open-dingtalk-id 单聊
|
||||
|
||||
**重要:该接口会真实发送消息到目标会话,不可用于测试或试探性调用。调用前必须确认消息内容和接收对象无误。**
|
||||
|
||||
--group 指定群聊 openConversationId 发群消息;--user 指定用户 userId 发单聊;--open-dingtalk-id 指定用户 openDingTalkId 发单聊。三者只能选其一,不能同时指定。纯文本/Markdown 单聊传 --user 时直接走 userId 发送能力,不需要先手动查询 openDingTalkId。推荐使用 --text flag 传递消息内容(也支持位置参数)。可选 --title 作为消息标题。
|
||||
若用户只提供了数字群号而非 openConversationId,需先调用 `chat group get-by-group-id` 将群号转为 openConversationId,再传入 --group。
|
||||
--群聊时可选 --at-all @所有人,或 --at-open-dingtalk-ids 指定成员(仅群聊时生效)。
|
||||
**发送图片或本地文件 — 一条命令直发**
|
||||
|
||||
收到本地路径就直接传给 `--file-path`,CLI 自动完成上传与发送,**无需任何前置工具调用**(不要再走 `dt_media_upload` / `extract_media_id.py` / `drive upload` 任何前置链路)。`.png/.jpg/.pdf/.mp4/.zip` 等任意类型一律:
|
||||
|
||||
```bash
|
||||
# 群聊
|
||||
dws chat message send --group <openConversationId> --msg-type file --file-path /local/path/to/file.png --format json
|
||||
# 单聊(推荐 --open-dingtalk-id,userId 也可)
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --msg-type file --file-path /local/path/to/file.png --format json
|
||||
```
|
||||
|
||||
> 单条命令完成上传 + 发送,没有"先 dt_media_upload 再 send"两步流程。带文字说明再额外发一条 `--text "..."` 即可。
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws chat message send [flags] [<text>]
|
||||
|
||||
Example:
|
||||
# 文本/Markdown
|
||||
dws chat message send --group <openconversation_id> --text "hello"
|
||||
dws chat message send --user <userId> --text "请查收"
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --text "请查收"
|
||||
dws chat message send --group <openconversation_id> --title "周报提醒" --text "请大家本周五前提交周报"
|
||||
# 幂等发送(24h 内相同 uuid 不重复投递)
|
||||
dws chat message send --group <openconversation_id> --text "hello" --uuid "unique-id-123"
|
||||
# 话题回复(拉消息返回的 openConvThreadId 作为 --group 传入)
|
||||
dws chat message send --group <openConvThreadId> --text "回复话题内容"
|
||||
# @ 群成员
|
||||
dws chat message send --group <openconversation_id> --at-all "<@all> 请大家注意"
|
||||
dws chat message send --group <openconversation_id> --at-open-dingtalk-ids odt1,odt2 "<@odt1> <@odt2> 请查收"
|
||||
# 发送本地图片(直接传路径,CLI 自动上传并发送)
|
||||
dws chat message send --group <openconversation_id> --msg-type file --file-path ./screenshot.png
|
||||
# 发送本地文件(同一条命令,任意扩展名)
|
||||
dws chat message send --group <openconversation_id> --msg-type file --file-path ./report.pdf
|
||||
# 旧链路(仅当上游已用 dt_media_upload 拿到 mediaId 时使用)
|
||||
dws chat message send --group <openconversation_id> --msg-type image --media-id <mediaId>
|
||||
Flags:
|
||||
--text string 消息内容(推荐使用,也可用位置参数)
|
||||
--group string 群聊 openconversation_id(群聊时必填)
|
||||
--user string 单聊接收人 userId(单聊时与 --open-dingtalk-id 二选一)
|
||||
--open-dingtalk-id string 单聊接收人 openDingTalkId(单聊时与 --user 二选一)
|
||||
--title string 消息标题(可选,默认「消息」)
|
||||
--at-all @所有人(仅群聊时生效,可选,默认 false)
|
||||
--at-open-dingtalk-ids string @指定成员的 openDingTalkId 列表,逗号分隔(仅群聊时生效,可选)
|
||||
--media-id string 图片 mediaId(仅旧链路:`--msg-type image` 时使用;新场景请直接用 `--msg-type file --file-path`)
|
||||
--msg-type string 富媒体消息类型: image/file/audio/video(推荐统一用 `file --file-path`;image+media-id 仅作旧链路兼容)
|
||||
--dentry-id int64 旧链路兼容:文件 dentryId(与 --space-id 成对传入时跳过自动上传)
|
||||
--space-id int64 旧链路兼容:空间 ID(与 --dentry-id 成对传入时跳过自动上传)
|
||||
--file-name string 旧链路兼容:文件名
|
||||
--file-type string 旧链路兼容:文件类型/扩展名
|
||||
--file-path string 本地文件路径(msgType=file 时可直接上传发送;旧链路中作为 content.filePath)
|
||||
--file-size int64 旧链路兼容:文件大小,单位字节
|
||||
--uuid string 幂等 UUID,相同 uuid 在 24h 内不会重复发送(可选)
|
||||
|
||||
注意:
|
||||
- --text 和位置参数二选一,--text 优先
|
||||
- --group、--user、--open-dingtalk-id 三者互斥,只需指定其一:群聊用 --group,单聊用 --user 或 --open-dingtalk-id
|
||||
- **话题回复**:话题圈拉消息(`chat message list`)返回的 openConvThreadId 可直接作为 --group 的值传入,即可往该话题内发送回复消息。注意 openConvThreadId 仅从消息列表接口的返回值中获取,禁止自行拼接或猜测
|
||||
- 纯文本/Markdown 单聊发送时 `--user` 和 `--open-dingtalk-id` 都可用;传 `--user` 时直接走 userId 发送能力
|
||||
- --group 的别名: --id, --chat, --conversation-id (均可替代 --group)
|
||||
- --at-all 和 --at-open-dingtalk-ids 仅在 --group 群聊时生效,单聊时无效;当设置--at-all时,消息内容中一定要包含对应的占位符<@all>;当设置--at-open-dingtalk-ids openDingTalkId1,openDingTalkId2时,消息内容中一定要包含对应格式的占位符<@openDingTalkId1> <@openDingTalkId2>
|
||||
- **换行符**:消息内容按 Markdown 渲染,换行有两层要求,缺一不可:
|
||||
1. 必须使用**真实换行符**(Unicode `U+000A`),而非字面量字符串 `\n`(反斜杠 + 字母 n)。程序或大模型构造参数时,须确保已正确反转义;否则全部内容会渲染在同一行
|
||||
2. Markdown 规范下**单个换行不产生换行效果**。需要换行时请使用:段落分隔(连续两个真实换行符 `\n\n`)、行尾两个空格 + 真实换行符(硬换行 `<br>`),或直接写 HTML 的 `<br>` 标签
|
||||
- **发图片/文件统一走 `--msg-type file --file-path <本地路径>`**(任意扩展名 png/jpg/pdf/mp4/zip…),CLI 内部一条命令完成上传 + 发送,无需 `dt_media_upload` / `extract_media_id` / `drive upload` 等前置步骤
|
||||
- 旧链路兼容:仅当上游已经通过 `dt_media_upload` 拿到 `@lQL...` 形式的 mediaId 时,才使用 `--msg-type image --media-id`;新代码与新指引一律用 file-path 路径
|
||||
- 富媒体消息的单聊优先使用 `--open-dingtalk-id`;传 `--user` 时 CLI 会尝试解析成 openDingTalkId 后发送
|
||||
- --uuid 用于幂等发送,传入相同 uuid 在 24h 内不会重复投递消息(可选,群聊和单聊均支持)
|
||||
- 当前命令不支持位置消息或联系人名片;不得生成 `location` / `profile` 类型或相应的臆造参数
|
||||
```
|
||||
|
||||
#### 查询消息发送状态 — 查询以当前用户身份发送的消息的发送状态
|
||||
|
||||
查询以当前用户身份发送的消息的发送状态。需要传入发送消息时返回的 openTaskId。
|
||||
```
|
||||
Usage:
|
||||
dws chat message query-send-status [flags]
|
||||
Example:
|
||||
dws chat message query-send-status --open-task-id <openTaskId>
|
||||
# openTaskId 由 dws chat message send 返回
|
||||
Flags:
|
||||
--open-task-id string 消息发送任务 ID (必填)
|
||||
|
||||
注意:
|
||||
- openTaskId 由 `dws chat message send` 发送消息成功后返回
|
||||
- 用于确认消息是否已成功发送或获取发送失败的原因
|
||||
```
|
||||
|
||||
#### 撤回消息 — 撤回自己或他人的消息
|
||||
|
||||
撤回消息。支持撤回自己发送的消息,也支持在群聊中以群主/管理员身份撤回他人的消息。与 `recall-by-bot` 的区别:本命令通过 IM 接口撤回用户消息,`recall-by-bot` 通过机器人接口撤回机器人发出的消息(需要 robot-code + processQueryKey)。
|
||||
```
|
||||
Usage:
|
||||
dws chat message recall [flags]
|
||||
Example:
|
||||
dws chat message recall --conversation-id <openConversationId> --msg-id <openMessageId>
|
||||
# 群主/管理员撤回他人消息:直接传目标消息 ID 即可
|
||||
# 查询会话 ID: dws chat search --query "群名"
|
||||
# 消息 ID 可通过 dws chat message list 获取
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持单聊/群聊,别名: --group / --id / --chat)
|
||||
--msg-id string 消息 openMessageId (必填)
|
||||
|
||||
注意:
|
||||
- --conversation-id 的别名: --group, --id, --chat (均可替代 --conversation-id)
|
||||
- 消息 ID 可通过 `dws chat message list` 命令获取
|
||||
- 支持撤回自己发出的消息,也支持群主/管理员撤回群内他人的消息
|
||||
- 与 `recall-by-bot` 的区别:本命令通过 IM 接口撤回用户消息(需要 openConversationId + openMessageId),`recall-by-bot` 通过机器人接口撤回机器人发出的消息(需要 robot-code + processQueryKey)
|
||||
```
|
||||
|
||||
#### 机器人发送消息(--group 群聊 / --users 单聊)
|
||||
|
||||
**重要:该接口会真实发送消息到目标会话,不可用于测试或试探性调用。调用前必须确认消息内容和接收对象无误。**
|
||||
|
||||
群聊:传 --group 指定群;单聊:传 --users 指定用户列表,二者只能选其一,不能同时指定。--text 支持 Markdown。群聊时可选 --at-user-ids @指定成员。
|
||||
|
||||
如果用户明确要求"用机器人/机器人身份/robot"发送,必须使用本命令,严禁改用 `chat message send` 以当前用户身份发送。
|
||||
|
||||
**重要**:机器人发群消息前,必须确认该机器人已在目标群中。若机器人不在群内会报错"机器人不存在",需先执行 `dws chat group members add-bot --id <openConversationId> --robot-code <robot-code>` 将机器人加入群聊后再发送。
|
||||
```
|
||||
Usage:
|
||||
dws chat message send-by-bot [flags]
|
||||
Example:
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openconversation_id> --title "日报" --text "## 今日完成..."
|
||||
dws chat message send-by-bot --robot-code <robot-code> --users userId1,userId2 --title "提醒" --text "请提交周报"
|
||||
dws chat message send-by-bot --robot-code <robot-code> --open-dingtalk-ids openDingtalkId1,openDingtalkId2 --title "提醒" --text "请提交周报"
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openconversation_id> --at-user-ids userId1,userId2 --title "提醒" --text "@userId1 @userId2 请查收本周报告"
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openconversation_id> --at-open-dingtalk-ids openDingtalkId1,openDingtalkId2 --title "提醒" --text "@openDingtalkId1 @openDingtalkId2 请查收本周报告"
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openconversation_id> --at-all --title "通知" --text "请所有人注意"
|
||||
Flags:
|
||||
--group string 群聊 openConversationId(群聊时必填)
|
||||
--robot-code string 机器人 Code (必填)
|
||||
--text string 消息内容 Markdown (必填)
|
||||
--title string 消息标题 (必填)
|
||||
--users string 用户 userId 列表,逗号分隔,最多20个(单聊时必填)
|
||||
--open-dingtalk-ids string 用户 openDingtalkId 列表,逗号分隔(单聊时可替代 --users,可选)
|
||||
--at-user-ids string @指定成员的 userId 列表,逗号分隔(仅群聊时生效,可选)
|
||||
--at-open-dingtalk-ids string @指定成员的 openDingtalkId 列表,逗号分隔(仅群聊时生效,可选)
|
||||
--at-all @所有人(可选),服务端接收字符串 true/false
|
||||
|
||||
注意:
|
||||
- 用户明确要求机器人发送时,必须使用 `chat message send-by-bot`;严禁使用 `chat message send` 以用户身份代发
|
||||
- --group 与 --users/--open-dingtalk-ids 互斥,必须且只能指定其一
|
||||
- --group 的别名: --id, --chat, --conversation-id (均可替代 --group)
|
||||
- --at-user-ids 仅在 --group 群聊时生效,单聊时无效;设置时 --text 中需包含 @userId 对应文本
|
||||
- --at-open-dingtalk-ids 仅在 --group 群聊时生效,单聊时无效;设置时 --text 中需包含 @openDingtalkId 对应文本
|
||||
- --at-all @所有人,仅群聊时生效;只需带上 --at-all flag 即可,服务端会自动处理
|
||||
- userId 获取方式:`dws contact user search --query "姓名"` 搜人获取 userId
|
||||
- **换行符**:--text 按 Markdown 渲染,换行规则同 `chat message send`:
|
||||
1. 必须使用**真实换行符**(`U+000A`),而非字面量 `\n`,否则全部内容会渲染在同一行
|
||||
2. 单个换行不产生换行效果,需用空行(`\n\n`)做段落分隔,或行尾两空格 + 换行/`<br>` 做硬换行
|
||||
```
|
||||
|
||||
#### 机器人撤回消息(--group 群聊 / 不传为单聊)
|
||||
|
||||
群聊:传 --group 与 --keys;单聊:仅传 --keys。--keys 为发送时返回的 processQueryKey 列表,逗号分隔。
|
||||
```
|
||||
Usage:
|
||||
dws chat message recall-by-bot [flags]
|
||||
Example:
|
||||
dws chat message recall-by-bot --robot-code <robot-code> --group <openconversation_id> --keys <process-query-key>
|
||||
dws chat message recall-by-bot --robot-code <robot-code> --keys key1,key2
|
||||
Flags:
|
||||
--group string 群聊 openConversationId(群聊撤回时必填)
|
||||
--keys string 消息 processQueryKey 列表,逗号分隔 (必填)
|
||||
--robot-code string 机器人 Code (必填)
|
||||
```
|
||||
|
||||
#### 自定义机器人 Webhook 发送群消息
|
||||
|
||||
@ 人时需在 --text 中包含 @userId 或 @手机号,否则 @ 不生效;@所有人时需在 --text 中包含 @10 并带上 --at-all。
|
||||
```
|
||||
Usage:
|
||||
dws chat message send-by-webhook [flags]
|
||||
Example:
|
||||
dws chat message send-by-webhook --token <webhook-token> --title "告警" --text "CPU 超 90% @10" --at-all
|
||||
dws chat message send-by-webhook --token <webhook-token> --title "test" --text "hi @118785" --at-users 118785
|
||||
Flags:
|
||||
--at-all @ 所有人(需在 --text 中包含 @10)
|
||||
--at-mobiles string @ 指定手机号,逗号分隔
|
||||
--at-users string @ 指定用户,逗号分隔(需在 text 中包含 @userId)
|
||||
--text string 消息内容 (必填)
|
||||
--title string 消息标题 (必填)
|
||||
--token string Webhook Token (必填)
|
||||
|
||||
注意:
|
||||
- **换行符**:--text 按 Markdown 渲染,换行规则同 `chat message send`:
|
||||
1. 必须使用**真实换行符**(`U+000A`),而非字面量 `\n`,否则全部内容会渲染在同一行
|
||||
2. 单个换行不产生换行效果,需用空行(`\n\n`)做段落分隔,或行尾两空格 + 换行/`<br>` 做硬换行
|
||||
```
|
||||
|
||||
#### 拉取群话题回复消息列表
|
||||
|
||||
查询指定群聊中某条话题消息的全部回复。--group 指定群会话 ID,--topic-id 指定话题 ID(由 dws chat message list 返回)。
|
||||
```
|
||||
Usage:
|
||||
dws chat message list-topic-replies [flags]
|
||||
Example:
|
||||
dws chat message list-topic-replies --group <openconversation_id> --topic-id <topicId>
|
||||
dws chat message list-topic-replies --group <openconversation_id> --topic-id <topicId> --time "2025-03-01 00:00:00" --limit 20
|
||||
dws chat message list-topic-replies --group <openconversation_id> --topic-id <topicId> --time "2025-03-01 00:00:00" --direction newer
|
||||
Flags:
|
||||
--group string 群会话 openconversationId (必填)
|
||||
--topic-id string 话题 ID,由 dws chat message list 返回 (必填)
|
||||
--time string 开始时间,格式: yyyy-MM-dd HH:mm:ss(可选)
|
||||
--limit int 返回数量(默认 50)
|
||||
--direction string 时间方向: newer=从给定时间往现在拉,older=从给定时间往以前拉(推荐,默认 older)
|
||||
--forward 旧兼容参数: true 等价 --direction newer,false 等价 --direction older(默认 false)
|
||||
```
|
||||
|
||||
#### 拉取指定时间范围内当前用户的所有会话消息 — 分页拉取当前登录用户在指定时间范围内的所有会话消息
|
||||
|
||||
--start 和 --end 限定时间范围,--limit 指定每页数量,--cursor 传分页游标(首页传 "0",后续从响应中的 nextCursor 获取)。服务端按 cursor 分页返回,hasMore=true 时用返回的 nextCursor 值作为下次 --cursor 继续翻页。
|
||||
```
|
||||
Usage:
|
||||
dws chat message list-all [flags]
|
||||
Example:
|
||||
dws chat message list-all --start "2025-03-01 00:00:00" --end "2025-03-31 23:59:59" --limit 50
|
||||
dws chat message list-all --start "2025-03-01 00:00:00" --end "2025-03-31 23:59:59" --limit 50 --cursor "abc123token"
|
||||
Flags:
|
||||
--start string 起始时间,格式: yyyy-MM-dd HH:mm:ss (必填)
|
||||
--end string 结束时间,格式: yyyy-MM-dd HH:mm:ss (必填)
|
||||
--limit int 每页返回数量(默认 50)
|
||||
--cursor string 分页游标(首页传 "0",后续从响应中的 nextCursor 获取)
|
||||
|
||||
注意:
|
||||
- 四个参数每次请求都会传递给服务端,cursor 首页传 "0"
|
||||
- 与 chat message list 的区别:list 拉取指定单个会话(群聊或单聊)的消息,list-all 拉取当前用户所有会话的消息
|
||||
- 翻页:hasMore=true 时,用响应中的 nextCursor 值作为下次 --cursor 参数继续翻页
|
||||
- 时间格式统一为 yyyy-MM-dd HH:mm:ss
|
||||
- 权限/权益错误不是空结果;应把返回的 `friendly_hint` 与 `action_url` 展示给用户,不要继续盲目翻页
|
||||
```
|
||||
|
||||
#### 收藏消息 — 为当前用户收藏指定会话中的一条消息
|
||||
```
|
||||
Usage:
|
||||
dws chat message add-favorite [flags]
|
||||
Example:
|
||||
dws chat message add-favorite --open-message-id <openMessageId> --open-conversation-id <openConversationId>
|
||||
Flags:
|
||||
--open-message-id string 消息 openMessageId (必填)
|
||||
--open-conversation-id string 消息所在会话 openConversationId (必填)
|
||||
```
|
||||
|
||||
#### 取消收藏消息 — 移除当前用户的收藏标记,不删除原消息
|
||||
```
|
||||
Usage:
|
||||
dws chat message remove-favorite [flags]
|
||||
Example:
|
||||
dws chat message remove-favorite --open-message-id <openMessageId> --open-conversation-id <openConversationId>
|
||||
Flags:
|
||||
--open-message-id string 消息 openMessageId (必填)
|
||||
--open-conversation-id string 消息所在会话 openConversationId (必填)
|
||||
```
|
||||
|
||||
#### 查询收藏消息 — 分页查询当前用户收藏的消息
|
||||
```
|
||||
Usage:
|
||||
dws chat message list-favorites [flags]
|
||||
Example:
|
||||
dws chat message list-favorites
|
||||
dws chat message list-favorites --cursor 20 --size 20
|
||||
Flags:
|
||||
--cursor int 数字分页游标,默认 0;翻页时传上次返回的 nextCursor
|
||||
--size int 一次拉取的收藏数量,默认 20,范围 1-100
|
||||
|
||||
注意:
|
||||
- 首次请求可省略分页参数,CLI 会自动使用 cursor=0、size=20
|
||||
- hasMore=true 时,将 nextCursor 作为下一次的 --cursor
|
||||
```
|
||||
|
||||
#### 拉取指定发送者的消息 — 搜索特定人发送给我的消息(包含单聊和群聊)
|
||||
|
||||
> 推荐优先使用 `chat message search-advanced --user/--users`(userId)或 `--sender-ids`(openDingTalkId),它还能叠加关键词/群/at 等过滤条件。本命令保留给需要旧 list-by-sender 返回结构的场景。
|
||||
|
||||
搜索特定人发送给我的消息,返回结果包含单聊和群聊标识。--sender-user-id 指定发送者 userId,--sender-open-dingtalk-id 指定发送者 openDingTalkId,二者互斥。分页参数 --limit(默认 50)和 --cursor(默认 "0")始终传递;hasMore=true 时用返回的 nextCursor 作为下次 --cursor 继续翻页。
|
||||
```
|
||||
Usage:
|
||||
dws chat message list-by-sender [flags]
|
||||
Example:
|
||||
dws chat message list-by-sender --sender-user-id <userId> --start "2026-03-10T00:00:00+08:00" --end "2026-03-11T00:00:00+08:00" --limit 50 --cursor 0
|
||||
dws chat message list-by-sender --sender-open-dingtalk-id <openDingTalkId> --start "2026-03-10T00:00:00+08:00" --end "2026-03-11T00:00:00+08:00" --limit 50 --cursor 0
|
||||
dws chat message list-by-sender --sender-user-id <userId> --start "2026-03-10T00:00:00+08:00" --end "2026-03-10T23:59:59+08:00" --limit 20 --cursor 0
|
||||
dws chat message list-by-sender --sender-open-dingtalk-id <openDingTalkId> --start "2026-03-10T00:00:00+08:00" --end "2026-03-11T00:00:00+08:00" --limit 50 --cursor <nextCursor>
|
||||
Flags:
|
||||
--sender-user-id string 发送者 userId(与 --sender-open-dingtalk-id 二选一)
|
||||
--sender-open-dingtalk-id string 发送者 openDingTalkId(与 --sender-user-id 二选一,适用于无法获取 userId 的场景)
|
||||
--start string 开始时间,ISO-8601 格式 (必填)
|
||||
--end string 结束时间,ISO-8601 格式 (必填)
|
||||
--limit int 每页返回数量(默认 50)
|
||||
--cursor string 分页游标(默认 "0",翻页传 nextCursor)
|
||||
|
||||
注意:
|
||||
- --sender-user-id 和 --sender-open-dingtalk-id 二者互斥,必须且只能指定其一:
|
||||
- --sender-user-id 传 userId(企业内部应用常用)
|
||||
- --sender-open-dingtalk-id 传 openDingTalkId(三方应用或跨组织场景常用,无法获取 userId 时使用)
|
||||
- openDingTalkId 获取方式见下方「openDingTalkId 获取方式」小节
|
||||
- 不需要指定单聊/群聊,返回结果自带会话类型标识
|
||||
- 时间支持多种 ISO-8601 格式,如 "2026-03-10T00:00:00+08:00"、"2026-03-10 14:00:00"、"2026-03-10" 等
|
||||
- 翻页:hasMore=true 时,用返回的 nextCursor 作为下次 --cursor
|
||||
```
|
||||
|
||||
#### 拉取 @我 的消息 — 搜索时间范围内 @我 的消息
|
||||
|
||||
> 推荐使用 `chat message search-advanced --at-me`,它还能叠加关键词/群/发送者等过滤条件。本命令适用于仅需拉取 @我 消息的简单场景。
|
||||
|
||||
搜索时间范围内 @我 的消息,可选指定群聊。返回结果包含单聊和群聊标识。分页参数 --limit(默认 50)和 --cursor(默认 "0")始终传递;hasMore=true 时用返回的 nextCursor 作为下次 --cursor 继续翻页。
|
||||
```
|
||||
Usage:
|
||||
dws chat message list-mentions [flags]
|
||||
Example:
|
||||
dws chat message list-mentions --start "2026-03-10T00:00:00+08:00" --end "2026-03-11T00:00:00+08:00" --limit 50 --cursor 0
|
||||
dws chat message list-mentions --start "2026-04-01T00:00:00+08:00" --end "2026-04-14T00:00:00+08:00" --limit 20 --cursor 0
|
||||
dws chat message list-mentions --group <openconversation_id> --start "2026-03-10T00:00:00+08:00" --end "2026-03-11T00:00:00+08:00" --limit 50 --cursor 0
|
||||
dws chat message list-mentions --start "2026-03-10T00:00:00+08:00" --end "2026-03-11T00:00:00+08:00" --limit 50 --cursor <nextCursor>
|
||||
Flags:
|
||||
--group string 群聊 openconversation_id(可选,不传则查全部)
|
||||
--start string 开始时间,ISO-8601 格式 (必填)
|
||||
--end string 结束时间,ISO-8601 格式 (必填)
|
||||
--limit int 每页返回数量(默认 50)
|
||||
--cursor string 分页游标(默认 "0",翻页传 nextCursor)
|
||||
|
||||
注意:
|
||||
- --group 可选,不传则查询所有会话中 @我 的消息;传入则只查指定群聊
|
||||
- --group 的别名: --id, --chat, --conversation-id (均可替代 --group)
|
||||
- 时间支持多种 ISO-8601 格式,如 "2026-03-10T00:00:00+08:00"、"2026-03-10 14:00:00"、"2026-03-10" 等
|
||||
- 翻页:hasMore=true 时,用返回的 nextCursor 作为下次 --cursor
|
||||
```
|
||||
|
||||
#### 拉取特别关注人的消息
|
||||
|
||||
拉取当前用户特别关注人的消息。分页参数 --limit 指定每页数量,--cursor 传分页游标(首次不传或传 0)。返回结果中 hasMore=true 时用 nextCursor 作为下次 --cursor 继续翻页。
|
||||
```
|
||||
Usage:
|
||||
dws chat message list-focused [flags]
|
||||
Example:
|
||||
dws chat message list-focused --limit 50
|
||||
dws chat message list-focused --limit 20 --cursor <nextCursor>
|
||||
Flags:
|
||||
--limit int 每页返回数量(默认 50)
|
||||
--cursor int64 分页游标(首次不传或传 0,翻页传 nextCursor)
|
||||
|
||||
注意:
|
||||
- 首次调用不传 --cursor 或传 0,后续翻页传 nextCursor
|
||||
```
|
||||
|
||||
#### 获取未读会话列表
|
||||
|
||||
获取当前用户有未读消息的会话信息。可选通过 `--count` 限制返回条数,不传则使用服务端默认值。
|
||||
```
|
||||
Usage:
|
||||
dws chat message list-unread-conversations [flags]
|
||||
Example:
|
||||
dws chat message list-unread-conversations
|
||||
dws chat message list-unread-conversations --count 20
|
||||
Flags:
|
||||
--count int 返回未读会话条数(可选)
|
||||
--exclude-muted 是否排除已设置免打扰的会话(默认 false)
|
||||
```
|
||||
|
||||
#### 查询消息的已读/未读状态
|
||||
|
||||
查询指定会话中消息的已读/未读状态(仅消息发送者可查询自己发出的消息)。--conversation-id 指定会话 openConversationId(群聊或单聊均可),--message-id 指定消息 ID(由 dws chat message list 返回的 openMessageId,必须是当前用户发送的消息)。目标用户 userId 使用 --user/--users;目标用户 openDingTalkId 使用 --target-open-dingtalk-ids;不传目标用户则返回所有接收者的状态。
|
||||
```
|
||||
Usage:
|
||||
dws chat message read-status [flags]
|
||||
Example:
|
||||
dws chat message read-status --conversation-id <openConversationId> --message-id <openMessageId>
|
||||
dws chat message read-status --conversation-id <openConversationId> --message-id <openMessageId> --user userId1,userId2
|
||||
dws chat message read-status --conversation-id <openConversationId> --message-id <openMessageId> --users userId1,userId2
|
||||
dws chat message read-status --conversation-id <openConversationId> --message-id <openMessageId> --target-open-dingtalk-ids openDingTalkId1,openDingTalkId2
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,群聊或单聊均可)
|
||||
--message-id string 消息 openMessageId,由 chat message list 返回 (必填,必须是当前用户发送的消息)
|
||||
--user string 目标用户 userId,支持逗号分隔(可选,不传则查所有接收者)
|
||||
--users string 目标用户 userId 列表,逗号分隔(可选,不传则查所有接收者)
|
||||
--target-open-dingtalk-ids string 目标用户 openDingTalkId 列表,逗号分隔(可选,不传则查所有接收者)
|
||||
|
||||
注意:
|
||||
- 仅消息发送者可查询自己发出的消息的已读/未读状态,查询他人发的消息会报错
|
||||
- --conversation-id 的别名: --group, --id, --chat (均可替代 --conversation-id)
|
||||
- --message-id 从 dws chat message list 返回的消息列表中获取(字段名 openMessageId)
|
||||
- --user / --users 传目标用户 userId
|
||||
- --target-open-dingtalk-ids 不传时返回该消息所有接收者的已读状态;传入则只返回指定 openDingTalkId 用户的状态
|
||||
```
|
||||
|
||||
#### 按关键词搜索消息 — 在当前用户的会话中按关键词搜索消息
|
||||
|
||||
> 推荐优先使用 `chat message search-advanced`,它是本命令的严格超集:query 可选(非必填)、支持多个会话(非单个)、还能叠加发送者/at 等维度过滤。
|
||||
|
||||
按关键词搜索消息内容。--query 指定搜索关键词(必填)。可选 --group 限定搜索某个会话,不传则搜索所有会话。时间参数 --start/--end(ISO-8601)限定搜索时间范围。分页参数 --limit(默认 100)和 --cursor(默认 "0")始终传递;hasMore=true 时用返回的 nextCursor 作为下次 --cursor 继续翻页。
|
||||
```
|
||||
Usage:
|
||||
dws chat message search [flags]
|
||||
Example:
|
||||
dws chat message search --query "changefree" --start "2026-04-01T00:00:00+08:00" --end "2026-04-15T00:00:00+08:00" --limit 50 --cursor 0
|
||||
dws chat message search --query "codereview" --group <openconversation_id> --start "2026-04-01T00:00:00+08:00" --end "2026-04-15T00:00:00+08:00" --limit 100 --cursor 0
|
||||
dws chat message search --query "链接" --start "2026-04-15T00:00:00+08:00" --end "2026-04-16T00:00:00+08:00" --limit 100 --cursor <nextCursor>
|
||||
Flags:
|
||||
--query string 搜索关键词 (必填)
|
||||
--group string 群聊 openconversation_id(可选,不传则搜索所有会话)
|
||||
--start string 开始时间,ISO-8601 格式 (必填)
|
||||
--end string 结束时间,ISO-8601 格式 (必填)
|
||||
--limit int 每页返回数量(默认 100)
|
||||
--cursor string 分页游标(默认 "0",翻页传 nextCursor)
|
||||
|
||||
注意:
|
||||
- --group 可选,不传则搜索所有会话中的消息;传入则只搜索指定会话
|
||||
- --group 的别名: --id, --chat, --conversation-id (均可替代 --group)
|
||||
- 时间支持多种 ISO-8601 格式,如 "2026-03-10T00:00:00+08:00"、"2026-03-10 14:00:00"、"2026-03-10" 等
|
||||
- 翻页:hasMore=true 时,用返回的 nextCursor 作为下次 --cursor
|
||||
```
|
||||
|
||||
#### 多维度搜索消息(推荐首选) — 支持按关键词、发送者、@我、@指定人、指定会话和时间范围搜索
|
||||
|
||||
> 推荐:这是消息搜索的首选接口。它可以完全替代 `chat message search`(query 可选 vs 必填,支持多个会话 vs 单个),大部分替代 `chat message list-by-sender`(通过 --user/--users 按 userId 搜索发送者,或通过 --sender-ids 按 openDingTalkId 搜索)和 `chat message list-mentions`(通过 --at-me 搜索@我的消息)。仅在拉取「特别关注人」消息时需要退回 `list-focused`。
|
||||
|
||||
支持按关键词、发送者、@我、@指定人、指定会话和时间范围等维度搜索消息。发送者 userId 使用 --user/--users;发送者或 @ 人的 openDingTalkId 使用 --sender-ids/--at-ids。所有参数均为可选,至少指定一个搜索条件。
|
||||
```
|
||||
Usage:
|
||||
dws chat message search-advanced [flags]
|
||||
Example:
|
||||
dws chat message search-advanced --query "周报" --start "2026-04-01T00:00:00+08:00" --end "2026-04-15T00:00:00+08:00"
|
||||
dws chat message search-advanced --user <userId> --start "2026-04-01T00:00:00+08:00" --end "2026-04-15T00:00:00+08:00"
|
||||
dws chat message search-advanced --users <userId1>,<userId2> --start "2026-04-01T00:00:00+08:00" --end "2026-04-15T00:00:00+08:00"
|
||||
dws chat message search-advanced --sender-ids <openDingTalkId1>,<openDingTalkId2> --start "2026-04-01T00:00:00+08:00" --end "2026-04-15T00:00:00+08:00"
|
||||
dws chat message search-advanced --at-me --start "2026-04-01T00:00:00+08:00" --end "2026-04-15T00:00:00+08:00"
|
||||
dws chat message search-advanced --at-ids <openDingTalkId1>,<openDingTalkId2> --conversation-ids <openConversationId1>,<openConversationId2> --limit 50 --cursor 0
|
||||
dws chat message search-advanced --conversation-ids <单聊openConversationId> --query "合同" --start "2026-04-01T00:00:00+08:00" --end "2026-04-15T00:00:00+08:00"
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
# 查询单聊会话 ID: dws chat conversation-info --user <userId>
|
||||
# 查询人员: dws contact user search --query "姓名" --format json
|
||||
Flags:
|
||||
--query string 搜索关键词(可选)
|
||||
--user string 发送者 userId,支持逗号分隔(可选)
|
||||
--users string 发送者 userId 列表,逗号分隔(可选)
|
||||
--sender-ids string 发送者 openDingTalkId 列表,逗号分隔(可选)
|
||||
--at-me 只搜索 @我 的消息(可选,默认 false)
|
||||
--at-ids string @指定人的 openDingTalkId 列表,逗号分隔(可选)
|
||||
--conversation-ids string 会话 openConversationId 列表,逗号分隔(可选,群聊或单聊均可,不传则搜索所有会话)
|
||||
--start string 开始时间,ISO-8601 格式(可选)
|
||||
--end string 结束时间,ISO-8601 格式(可选)
|
||||
--cursor string 分页游标(默认 "0")
|
||||
--limit int 每页返回数量(默认 100)
|
||||
--conversation-ids 的别名: --groups
|
||||
|
||||
注意:
|
||||
- 所有参数均为可选,但至少需要指定一个搜索条件
|
||||
- --user / --users 传发送者 userId
|
||||
- --sender-ids 和 --at-ids 传 openDingTalkId
|
||||
- --conversation-ids 可指定多个会话 ID(群聊或单聊均可),逗号分隔,不传则搜索所有会话
|
||||
- 群聊 openConversationId 通过 `dws chat search --query "群名"` 获取
|
||||
- 单聊 openConversationId 通过 `dws chat conversation-info --user <userId>` 或 `--open-dingtalk-id <openDingTalkId>` 获取
|
||||
- 时间支持多种 ISO-8601 格式,如 "2026-03-10T00:00:00+08:00"、"2026-03-10 14:00:00"、"2026-03-10" 等
|
||||
- 翻页:hasMore=true 时,用返回的 nextCursor 作为下次 --cursor
|
||||
- 替代关系:完全替代 search(严格超集);大部分替代 list-by-sender(--user 覆盖按 userId 搜索发送者,--sender-ids 覆盖按 openDingTalkId 搜索)和 list-mentions(--at-me 覆盖核心功能);不能替代 list-focused(「特别关注」是独立维度)
|
||||
```
|
||||
|
||||
#### 根据消息 ID 批量查询消息
|
||||
```
|
||||
Usage:
|
||||
dws chat message list-by-ids [flags]
|
||||
Example:
|
||||
dws chat message list-by-ids --msg-ids msgId1,msgId2,msgId3
|
||||
# 最多传 50 条消息 ID
|
||||
Flags:
|
||||
--msg-ids string 消息 ID 列表,逗号分隔,最多 50 条 (必填)
|
||||
```
|
||||
|
||||
#### 表情回应选择策略
|
||||
|
||||
> 贴表情时,优先查 [chat-emoji-list.md](chat-emoji-list.md) 中的默认表情名称(共 199 个,如「赞」「鼓掌」「感谢」等):
|
||||
> - 命中 → 使用 `add-emoji --emoji <name>`(直接贴 emoji)
|
||||
> - 未命中 → 先 `create-text-emotion` 创建文字表情获取 emotionId,再 `add-text-emotion` 贴文字表情
|
||||
|
||||
#### 对消息添加 emoji 表情回应
|
||||
```
|
||||
Usage:
|
||||
dws chat message add-emoji [flags]
|
||||
Example:
|
||||
dws chat message add-emoji --conversation-id <openConversationId> --msg-id <openMsgId> --emoji "赞"
|
||||
dws chat message add-emoji --conversation-id <openConversationId> --msg-id <openMsgId> --emoji "鼓掌"
|
||||
# --emoji 的值必须是 chat-emoji-list.md 中的 name(中文名),如:赞、鼓掌、感谢、微笑 等
|
||||
# 查询会话 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持单聊/群聊,别名: --group / --id / --chat)
|
||||
--msg-id string 消息 openMsgId (必填)
|
||||
--emoji string emoji 表情名称,必须是默认表情列表中的 name 值 (必填,参见 chat-emoji-list.md)
|
||||
```
|
||||
|
||||
#### 移除消息的 emoji 表情回应
|
||||
```
|
||||
Usage:
|
||||
dws chat message remove-emoji [flags]
|
||||
Example:
|
||||
dws chat message remove-emoji --conversation-id <openConversationId> --msg-id <openMsgId> --emoji "赞"
|
||||
# 查询会话 ID: dws chat search --query "群名"
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持单聊/群聊,别名: --group / --id / --chat)
|
||||
--msg-id string 消息 openMsgId (必填)
|
||||
--emoji string emoji 表情名称,必须是默认表情列表中的 name 值 (必填,参见 chat-emoji-list.md)
|
||||
```
|
||||
|
||||
#### 对消息添加文字表情回应(当默认表情列表中没有所需表情时使用)
|
||||
```
|
||||
Usage:
|
||||
dws chat message add-text-emotion [flags]
|
||||
Example:
|
||||
dws chat message add-text-emotion --conversation-id <openConversationId> --msg-id <openMsgId> --emotion-id <emotionId> --emotion-name "赞" --text "nice" --background-id im_bg_5
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持单聊/群聊,别名: --group / --id / --chat)
|
||||
--msg-id string 消息 openMsgId (必填)
|
||||
--emotion-id string 表情 ID (必填,通过 create-text-emotion 或已知表情获取)
|
||||
--emotion-name string 表情名称 (必填)
|
||||
--text string 文字内容 (必填)
|
||||
--background-id string 背景 ID (必填)
|
||||
```
|
||||
|
||||
#### 移除消息的文字表情回应
|
||||
```
|
||||
Usage:
|
||||
dws chat message remove-text-emotion [flags]
|
||||
Example:
|
||||
dws chat message remove-text-emotion --conversation-id <openConversationId> --msg-id <openMsgId> --emotion-id <emotionId> --emotion-name "赞" --text "nice" --background-id <backgroundId>
|
||||
Flags:
|
||||
--conversation-id string 会话 openConversationId (必填,支持单聊/群聊,别名: --group / --id / --chat)
|
||||
--msg-id string 消息 openMsgId (必填)
|
||||
--emotion-id string 表情 ID (必填)
|
||||
--emotion-name string 表情名称 (必填)
|
||||
--text string 文字内容 (必填)
|
||||
--background-id string 背景 ID (必填)
|
||||
```
|
||||
|
||||
#### 创建文字表情(获取 emotionId)— 当 chat-emoji-list.md 中没有所需表情时,先创建再贴
|
||||
```
|
||||
Usage:
|
||||
dws chat message create-text-emotion [flags]
|
||||
Example:
|
||||
dws chat message create-text-emotion --emotion-name "赞" --text "nice"
|
||||
dws chat message create-text-emotion --emotion-name "感谢" --text "感谢" --background-id im_bg_5
|
||||
Flags:
|
||||
--emotion-name string 表情名称 (必填)
|
||||
--text string 文字内容 (必填)
|
||||
--background-id string 背景 ID(可选,不传则由服务端默认分配)
|
||||
|
||||
注意:
|
||||
- 创建后返回 emotionId,可用于 add-text-emotion 命令
|
||||
- 如果已有合适的表情,无需创建新的
|
||||
```
|
||||
|
||||
#### 批量拉取消息的表情回复和文字回复
|
||||
|
||||
根据消息 ID 列表批量查询消息的表情回复和文字回复信息。
|
||||
```
|
||||
Usage:
|
||||
dws chat message list-emotion-replies [flags]
|
||||
Example:
|
||||
dws chat message list-emotion-replies --msg-ids msgId1,msgId2,msgId3
|
||||
# 消息 ID 可通过 dws chat message list 获取
|
||||
Flags:
|
||||
--msg-ids string 消息 ID 列表,逗号分隔 (必填)
|
||||
|
||||
注意:
|
||||
- 支持批量查询多条消息的表情和文字回复
|
||||
- 消息 ID 可通过 `dws chat message list` 命令获取
|
||||
```
|
||||
@@ -1,67 +0,0 @@
|
||||
# 注意事项
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **发消息前参数审查(必须执行)**:
|
||||
- 发消息(`chat message send`、`send-by-bot`、`send-by-webhook`、`send-card`、`reply`、`forward`)是严肃操作,一旦发错人/发错群会导致严重问题,因此在执行发送之前,agent 必须对所有参数进行内部审查
|
||||
- 审查方式:将即将发送的**全部参数**(收件人/群、消息内容、@对象、消息类型等)与用户的**原始需求**逐一对比,确认每个参数都能从原始需求中找到明确依据
|
||||
- 如果存在任何不明确、有歧义或原始需求中未提及的参数(例如:用户没说发给谁、没说发到哪个群、消息内容与用户意图有出入、不确定是否需要 @某人等),**必须先向用户确认**,严禁自行假设或补全
|
||||
- 典型需要确认的场景:用户只说了"发个消息"但没指定群/人;用户的描述可匹配多个群或多个联系人;消息文本由 agent 组织而非用户原文提供时需确认措辞
|
||||
- uuid 幂等参数(发消息最佳实践):
|
||||
- 发消息时建议始终带上 `--uuid` 参数,传入用户自行生成的唯一标识(如 UUID v4),用于幂等控制
|
||||
- 如果发送失败需要重试,重试时 `--uuid` 必须与首次发送保持一致,服务端据此去重,避免重复发消息
|
||||
- 如果不传 `--uuid`,每次调用都视为新消息,重试可能导致消息重复发送
|
||||
- 此参数适用于 `chat message send`(群聊和单聊均支持)
|
||||
- `--group` 为群聊会话 ID (openconversation_id),可从群搜索或群聊信息中获取
|
||||
- `chat message send` 的 text 是位置参数(恰好 1 个),非 flag;群聊用 `--group`,单聊用 `--user`(userId)或 `--open-dingtalk-id`(openDingTalkId),三者互斥;纯文本/Markdown 单聊传 `--user` 时直接走 userId 发送能力;`--at-all`、`--at-open-dingtalk-ids` 仅在 `--group` 群聊时生效;**发图片/本地文件统一 `--msg-type file --file-path <本地路径>`**(任意扩展名 png/jpg/pdf/mp4/zip… 一条命令直发,CLI 内部完成上传);`--msg-type image --media-id` 仅作旧链路兼容
|
||||
- `chat message list-all` 的四个参数(--start、--end、--limit、--cursor)每次请求都必须传递;翻页时用响应中的 nextCursor 值作为下次 --cursor
|
||||
- `chat message list` 的 `--group`、`--user`、`--open-dingtalk-id` 三者互斥,必须且只能指定其一
|
||||
- `chat message list-by-sender` 不需要指定单聊/群聊,返回结果自带会话类型标识;`--sender-user-id`(userId)与 `--sender-open-dingtalk-id`(openDingTalkId)二选一;时间用 `--start`/`--end`(ISO-8601),分页用 `--limit`/`--cursor`
|
||||
- `chat message list-mentions` 可选 `--group` 指定群聊,不传则查全部;时间用 `--start`/`--end`(ISO-8601),分页用 `--limit`/`--cursor`
|
||||
- `chat message list-unread-conversations` 获取当前用户未读会话列表,可选 `--count` 指定返回条数
|
||||
- `chat message search` 按关键词搜索消息内容,`--query` 必填,可选 `--group` 限定搜索某个会话;时间用 `--start`/`--end`(ISO-8601),分页用 `--limit`(默认 100)/`--cursor`
|
||||
- `chat message read-status` 查询指定消息的已读/未读状态,仅消息发送者可查询自己发出的消息;`--group`、`--message-id` 必填;目标用户 userId 用 `--user`/`--users`,openDingTalkId 用 `--target-open-dingtalk-ids`,不传则查所有接收者
|
||||
- `chat search-common` 搜索共同群,`--nicks` 传人员昵称(逗号分隔),`--match-mode` AND/OR 控制匹配逻辑,分页用 `--limit`(默认 20)/`--cursor`
|
||||
- `chat list-top-conversations` 拉取置顶会话列表,分页用 `--limit`(默认 1000)/`--cursor`;用户询问"置顶会话"时路由到此命令
|
||||
- `--user` 和 `--open-dingtalk-id` 本质上都是发起单聊操作,只是用户标识格式不同:userId 为企业内部应用常用标识,openDingTalkId 为三方应用或跨组织场景下的用户标识,服务端对两种 ID 的解析逻辑不同
|
||||
- `--time` 格式: `yyyy-MM-dd HH:mm:ss`,为拉取消息的起始时间点;拉取方向优先使用 `--direction newer|older`:`newer` 从给定时间往现在拉,`older` 从给定时间往以前拉;`--forward` 为旧兼容参数,`true` 等价 `newer`,`false` 等价 `older`;`--limit` 控制数量
|
||||
- `chat search` 挂在 `chat` 下(非 `chat group` 下),路径为 `dws chat search`
|
||||
- `send-by-bot` 群聊传 `--group`,单聊传 `--users` 或 `--open-dingtalk-ids`,与 `--group` 互斥且必选其一;群聊时可选 `--at-user-ids` @指定成员(传 userId 列表)或 `--at-open-dingtalk-ids` @指定成员(传 openDingtalkId 列表),content 中需包含对应 @标识;`--at-all` @所有人;群聊场景如果返回"机器人不存在"错误,需先通过 `chat group members add-bot --id <openConversationId> --robot-code <robot-code>` 将机器人邀请进群后再发送
|
||||
- `recall-by-bot` 群聊传 `--group` + `--keys`,单聊仅传 `--keys`(不传 `--group` 即为单聊撤回)
|
||||
- `send-by-webhook` 支持 `--at-all`、`--at-mobiles`、`--at-users` 进行 @ 操作,但需在 `--text` 中包含 `@userId` 或 `@手机号` 才能生效;`--at-all` @所有人时需在 `--text` 中包含 `@10`
|
||||
- `chat group-role` 系列命令用于管理群的自定义身份标签:`list` 查列表,`add` 创建,`update` 改名,`remove` 删除;`set-user` 覆盖某人全部身份(传空 --role-ids 则清除),`remove-user` 仅移除指定身份,`query-user` 查询某人当前身份;用户用 `--user <userId>`
|
||||
- 消息**换行符**(`send` / `send-by-bot` / `send-by-webhook` 的 `--text`)有两层要求:(1) 必须是**真实换行符** `U+000A`,不是字面量 `\n`;(2) Markdown 规范下单换行不生效,需用空行 `\n\n`(段落分隔)或行尾两空格 + 换行 / `<br>`(硬换行)
|
||||
- `chat group transfer-owner` 转让群主,需传 --group(openConversationId);新群主 userId 用 `--user`,openDingTalkId 用 `--new-owner`
|
||||
- `chat group invite-url` 获取群邀请链接,需传 --group(openConversationId),可选 --expires-seconds 指定有效期(秒,0=永久)
|
||||
- `chat group share-invite` 分享群聊链接到会话,需传 --source(被分享群 openConversationId),--target(目标会话)和 --receiver(单聊用户)二选一,可选 --expires-seconds 和 --uuid
|
||||
- `chat category create-smart` 创建智能会话分组,需传 --name(分组名称),可选 --keywords(群名称关键词)和 --members(群内成员 openDingTalkId)
|
||||
- `chat group quit` 退出群聊,需传 --group(openConversationId)
|
||||
- `chat group update-icon` 更新群头像,需传 --group(openConversationId)和 --icon-media-id(mediaId)
|
||||
- `chat group update-settings` 更新群设置,需传 --group(openConversationId)、--setting-key(设置项 key)、--status(0=关闭 1=开启)
|
||||
- `chat message send-card` 创建并推送流式卡片,群聊传 --group,单聊传 --receiver,二者互斥;不传 content,后续通过 update-card 更新内容
|
||||
- `chat message update-card` 流式更新卡片内容,需传 --biz-id(创建卡片返回的业务 ID)、--content、--flow-status
|
||||
- `chat message list-by-ids` 根据消息 ID 批量查询,--msg-ids 逗号分隔,最多 50 条
|
||||
- `chat message add-emoji` / `remove-emoji` 需传 --group(openConversationId)、--msg-id(openMsgId)、--emoji(表情名称)
|
||||
- `chat message add-text-emotion` / `remove-text-emotion` 需传 --group、--msg-id、--emotion-id、--emotion-name、--text、--background-id,六个参数全部必填
|
||||
- `chat message create-text-emotion` 创建文字表情模板,返回 emotionId;--background-id 可选,不传由服务端默认分配
|
||||
- `chat category list` 无需参数;`category list-conversations` 需传 --category-id(通过 category list 获取)
|
||||
- `chat mute` 默认开启免打扰,传 --off 关闭;--conversation-id / --id / --chat 三个别名均可用于传入会话 ID
|
||||
- `chat message reply` 引用回复消息(**单聊/群聊均可**),需传 --conversation-id(openConversationId,单聊与群聊使用同一字段)、--ref-msg-id(被引用消息 openMessageId)、--ref-sender(被引用消息发送者 openDingTalkId)、--text(回复内容);目前回复类型仅支持 text
|
||||
- `chat message forward` 转发单条消息(**源/目标会话均支持单聊/群聊**,常见组合:群→群、群→单、单→群、单→单),需传 --src-conversation-id(源会话 openConversationId)、--msg-id(源消息 openMessageId)、--dest-conversation-id(目标会话 openConversationId)
|
||||
- `chat message forward-topic` 转发话题消息,需传 --src-msg-id(源消息 openMessageId)、--src-conversation-id(源会话 openConversationId)、--src-thread-id(话题 ID,格式: convThread + 加密后的convThreadId)、--dest-conversation-id(目标会话 openConversationId)
|
||||
- `chat set-top` 设置/取消会话置顶(单聊/群聊均可),需传 --conversation-id(openConversationId,单聊与群聊使用同一字段),默认置顶,传 --off 取消
|
||||
- `chat message set-top-msg` 置顶会话内某条消息,需传 --open-conversation-id(openConversationId)、--msg-id(openMessageId);与 chat set-top 区别:后者是会话列表置顶,前者是消息置顶
|
||||
- `chat message unset-top-msg` 取消置顶会话内某条消息,需传 --open-conversation-id(openConversationId)、--msg-id(openMessageId)
|
||||
- `chat message reply` 以当前用户身份引用回复,与 `chat message send` 的用户身份发送语义一致
|
||||
- **如何获取 openConversationId**(如果上层已有则直接使用,不必再查):
|
||||
- 群聊:`dws chat search --query "群名"`
|
||||
- 单聊:`dws chat conversation-info --user <userId>` 或 `dws chat conversation-info --open-dingtalk-id <openDingTalkId>`(人员信息可通过 `dws contact user search --query "姓名" --format json` 获取)
|
||||
- `chat group-mute` 全员禁言/取消全员禁言,需传 --group(openConversationId),默认禁言,传 --off 取消
|
||||
- `chat group-mute-member` 指定群成员禁言,需传 --group、--user/--users(userId,逗号分隔)、--mute-time(毫秒,仅禁言时必填,支持 300000/3600000/86400000/604800000/2592000000),传 --off 解除禁言
|
||||
- `chat group set-admin` 设置/取消群管理员,需传 --group(openConversationId)、--user/--users(userId,逗号分隔),默认设为管理员,传 --off 取消
|
||||
- `chat group update-nick` 设置用户在群内的群昵称,需传 --group(openConversationId)、--nick(群昵称)
|
||||
- `chat group update-alias` 设置群备注,需传 --group(openConversationId)、--alias-title(备注名称),仅自己可见
|
||||
- `chat hide` 隐藏会话,需传 --conversation-id(openConversationId,支持单聊/群聊),隐藏后不显示在列表中,收到新消息时重新出现
|
||||
- `chat mute-at-all` 关闭/开启 @所有人消息提醒,需传 --conversation-id(openConversationId),默认关闭通知,传 --off 恢复接收
|
||||
- `chat mute-red-envelope` 关闭/开启红包消息提醒,需传 --conversation-id(openConversationId),默认关闭通知,传 --off 恢复接收
|
||||
- `chat group members list-by-ids` 根据成员 openDingTalkId 批量查询群成员详情,需传 --id(openConversationId)、--users(openDingTalkId 列表,逗号分隔)
|
||||
@@ -1,32 +0,0 @@
|
||||
# 相关产品
|
||||
|
||||
## 相关产品
|
||||
|
||||
- [contact](../../dingtalk-contact/references/contact.md) — 搜索同事/好友,获取 userId 用于 --user、send-by-bot --users、send-by-bot --at-user-ids、list-by-sender --sender-user-id;获取 openDingTalkId 用于 message send 的 --at-open-dingtalk-ids、--open-dingtalk-id、send-by-bot --open-dingtalk-ids、send-by-bot --at-open-dingtalk-ids、list-by-sender 的 --sender-open-dingtalk-id
|
||||
- [drive](../../dingtalk-drive/references/drive.md) — 云盘文件管理;chat 纯文件发送优先用 `chat message send --msg-type file --file-path`
|
||||
|
||||
### text translate (文本翻译)
|
||||
|
||||
#### 翻译文本内容 — 将指定文本翻译成目标语言
|
||||
```
|
||||
Usage:
|
||||
dws chat text translate [flags]
|
||||
Example:
|
||||
dws chat text translate --query "你好世界" --to en_US
|
||||
dws chat text translate --query "Hello World" --to zh_CN
|
||||
dws chat text translate --query "Bonjour" --to ja_JP
|
||||
Flags:
|
||||
--query string 待翻译的文本内容 (必填)
|
||||
--to string 目标语言代码 (必填,默认 en_US)
|
||||
```
|
||||
|
||||
支持的目标语言代码:
|
||||
en_US, zh_CN, zh_TW, zh_HK, ja_JP, ko_KR, vi_VN, th_TH,
|
||||
id_ID, ms_MY, es_419, fr_FR, pt_BR, tr_TR, ru_RU, de_DE,
|
||||
hi_IN, hu_HU, pl_PL, sv_SE, fi_FI, cs_CZ, ar_SA, tl_PH,
|
||||
he_IL, nl_NL, lo_LA, it_IT
|
||||
|
||||
注意:
|
||||
- `--to` 参数必须使用上述支持的语言代码,大小写敏感
|
||||
- 默认目标语言为 en_US(美式英语)
|
||||
- 返回结果为翻译后的纯文本内容
|
||||
@@ -1,9 +0,0 @@
|
||||
# 自动化脚本
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
| 脚本 | 场景 | 用法 |
|
||||
|------|------|------|
|
||||
| [chat_export_messages.py](../scripts/chat_export_messages.py) | 导出群聊消息到 JSON 文件 | `python chat_export_messages.py --query "项目冲刺" --time "2026-03-10 00:00:00"` |
|
||||
| [chat_history_with_user.py](../scripts/chat_history_with_user.py) | 查询与某人的单聊聊天记录 | `python chat_history_with_user.py --name "张三" --time "2026-03-10 00:00:00"` |
|
||||
| [extract_media_id.py](../scripts/extract_media_id.py) | **旧链路** — 仅当上游已通过 `dt_media_upload` 拿到 URL 时使用,从该 URL 提取 mediaId | `python extract_media_id.py "<URL>"`(输出如 @lQLPxxx,用于 `--msg-type image --media-id`;新场景请直接用 `--msg-type file --file-path`) |
|
||||
@@ -1,35 +0,0 @@
|
||||
# 核心工作流
|
||||
|
||||
## 核心工作流
|
||||
|
||||
```bash
|
||||
# 1. 搜索群 — 提取 openconversation_id
|
||||
dws chat search --query "项目冲刺" --format json
|
||||
|
||||
# 2. 拉取群消息
|
||||
dws chat message list --group <openconversation_id> --time "2025-03-01 00:00:00" --format json
|
||||
|
||||
# 2b. 拉取未读会话列表
|
||||
dws chat message list-unread-conversations --count 20 --format json
|
||||
|
||||
# 3. 以个人身份发送群消息
|
||||
dws chat message send --group <openconversation_id> --title "周报提醒" "请大家本周五前提交周报" --format json
|
||||
|
||||
# 4. 以个人身份单聊(通过 userId)
|
||||
dws chat message send --user <userId> "你好" --format json
|
||||
|
||||
# 4b. 以个人身份单聊(通过 openDingTalkId,三方应用等无法获取 userId 时使用)
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> "你好" --format json
|
||||
|
||||
# 5. 机器人发群消息(Markdown)
|
||||
dws chat message send-by-bot --robot-code <robot-code> \
|
||||
--group <openconversation_id> --title "日报" --text "## 今日完成..." --format json
|
||||
|
||||
# 6. 机器人单聊发消息
|
||||
dws chat message send-by-bot --robot-code <robot-code> \
|
||||
--users userId1,userId2 --title "提醒" --text "请提交周报" --format json
|
||||
|
||||
# 7. Webhook 发告警
|
||||
dws chat message send-by-webhook --token <webhook-token> \
|
||||
--title "告警" --text "CPU 超 90% @10" --at-all --format json
|
||||
```
|
||||
@@ -1,10 +1,344 @@
|
||||
# 会话与群聊 (chat) 命令参考
|
||||
|
||||
> 渐进式兼容入口:新任务优先从 [聊天能力索引](./chat-index.md) 选择专题。
|
||||
> **渐进式文档**:本文件为路由层(索引 + 意图判断 + 全局约束),详细参数、示例和踩坑说明在 [chat/](./chat/) 目录下按场景加载。
|
||||
|
||||
| 任务 | 参考 |
|
||||
|---|---|
|
||||
| 命令路由 | [chat-index.md](./chat-index.md);兼容入口见 [chat-commands.md](./chat-commands.md) |
|
||||
| 意图与标准流程 | [意图判断](./chat-intent.md) · [核心工作流](./chat-workflow.md) · [复合工作流](./chat-composite.md) |
|
||||
| 上下文与约束 | [上下文](./chat-context.md) · [注意事项](./chat-notes.md) |
|
||||
| 表情、脚本、相关产品 | [表情](./chat-emoji-list.md) · [脚本](./chat-scripts.md) · [相关产品](./chat-related.md) |
|
||||
> 命令别名:`dws im` 等价于 `dws chat`。
|
||||
|
||||
## 适用范围与安全硬约束
|
||||
|
||||
`chat` 覆盖钉钉会话、群聊、群成员、会话消息、机器人消息、Webhook、会话状态和群身份管理。
|
||||
|
||||
**发消息前参数审查(必须执行)**:
|
||||
|
||||
- 发消息类命令包括 `chat message send`、`send-by-bot`、`send-by-webhook`、`send-card`、`reply`、`forward`。
|
||||
- 执行前必须逐项核对接收对象、群/人、消息内容、@ 对象、消息类型、附件路径,确认全部来自用户原始需求。
|
||||
- 用户没说发给谁、群名/人名可能匹配多个对象、消息文本由 Agent 组织、是否 @ 某人不明确时,必须先确认,严禁自行补全。
|
||||
- 重试发送建议复用同一个 `--uuid`,避免重复投递;不传 `--uuid` 时每次调用都视为新消息。
|
||||
|
||||
**文件、图片、音频、视频发送硬规则**:
|
||||
|
||||
- 新场景发送本地文件、音频、视频统一用 `dws chat message send --msg-type file|audio|video --file-path <本地路径>`,CLI 内部完成上传和发送;`audio` / `video` 底层按 `file` 链路处理。
|
||||
- 不要先走 `dt_media_upload`、`extract_media_id.py`、`drive upload`;`--msg-type image --media-id` 只保留给已有 mediaId 的旧链路。
|
||||
|
||||
**Markdown 换行硬规则**:
|
||||
|
||||
- `--text` 必须使用真实换行符 `U+000A`,不能传字面量 `\n`。
|
||||
- Markdown 单个换行通常不换行,需要空行 `\n\n`、行尾两个空格 + 换行,或 `<br>`。
|
||||
- 机器人 `message send-by-bot` 的 Markdown 文本优先用空行分隔段落;如果在模型内部用转义形式组织文本,必须写 `\n\n`,不要只写 `\n`。
|
||||
|
||||
## 查询命令帮助
|
||||
|
||||
参数名、必填项或命令是否存在不确定时,先查 `--help`,不要猜。
|
||||
|
||||
```bash
|
||||
dws chat --help
|
||||
dws chat message --help
|
||||
dws chat message send --help
|
||||
dws chat group --help
|
||||
dws chat bot --help
|
||||
```
|
||||
|
||||
## Reference 索引
|
||||
|
||||
| Reference | 何时读取 | 主要命令 |
|
||||
|-----------|----------|----------|
|
||||
| [chat-message](./chat/chat-message.md) | 发消息、查消息、撤回、搜索、已读、话题、Pin/Top/Favorite、表情、卡片、文件、音频、视频、位置、名片、文本翻译 | `message *`、`file upload`、`download-media`、`text translate` |
|
||||
| [chat-group](./chat/chat-group.md) | 建群、搜群、成员、机器人进群、群设置、群主、入群审批、群身份、群公告、群邀请分享 | `group *`、`group-role *`、`search`、`search-common` |
|
||||
| [chat-bot](./chat/chat-bot.md) | 查机器人、机器人发消息/撤回、Webhook、机器人单聊、机器人进群 | `bot *`、`message send-by-bot`、`recall-by-bot`、`send-by-webhook` |
|
||||
| [chat-conversation](./chat/chat-conversation.md) | 会话列表、置顶、免打扰、隐藏、红点、已读未读、清空、会话分组、智能分组 | `conversation-info`、`category *`、`mute`、`set-top`、`mark-read` |
|
||||
| [chat-workflows](./chat/chat-workflows.md) | 高频复合流程、上下文传递表、openDingTalkId 获取方式、自动化脚本 | 工作流与字段传递 |
|
||||
|
||||
## ID 获取速查
|
||||
|
||||
| 需要的 ID | 首选获取方式 | 说明 |
|
||||
|-----------|--------------|------|
|
||||
| 群聊 `openConversationId` | `dws chat search --query "群名" --format json` | 群聊发消息、拉消息、成员管理、会话状态都用它 |
|
||||
| 数字群号对应的 `openConversationId` | `dws chat group get-by-group-id --group-id <数字群号>` | 用户只给数字群号时先转换 |
|
||||
| 单聊 `openConversationId` | `dws chat conversation-info --user <userId>` 或 `--open-dingtalk-id <openDingTalkId>` | 单聊转发、会话置顶、清红点等状态命令需要 |
|
||||
| `userId` | `dws aisearch person --keyword "姓名" --dimension name --format json` | 内部人员、机器人单聊 users、按发送者 userId 搜索 |
|
||||
| `openDingTalkId` | `dws aisearch person --keyword "姓名" --dimension name --format json` | 三方/跨组织、openDingTalkId 单聊、@ openDingTalkId |
|
||||
| `robotCode` | `dws chat bot search --name "机器人名" --format json` | 我创建的机器人,发机器人消息和撤回使用 |
|
||||
| 机器人 `openDingTalkId` | `dws chat bot find --query "机器人名" --format json` | 给机器人发单聊必须用 find,search 不返回该字段 |
|
||||
| 群成员昵称 | `dws chat group members --id <openConversationId> --format json` | 返回中包含成员在群里的昵称/展示名;不要只查 contact 个人名 |
|
||||
| 消息 `openMessageId` / `openMsgId` | `dws chat message list ... --format json` | 撤回、已读状态、回复、转发、表情回应 |
|
||||
| 话题 `openConvThreadId` | `dws chat message list ... --format json` | 拉话题回复或往话题内回复;禁止自行拼接 |
|
||||
| 卡片 `bizId` | `dws chat message send-card ... --format json` | `update-card --biz-id` |
|
||||
|
||||
## 易混淆路由
|
||||
|
||||
| 易混淆说法 | 正确路由 | 不要这样做 |
|
||||
|------------|----------|------------|
|
||||
| “置顶会话” | `chat set-top` 或 `chat list-top-conversations` | 不要用 `message set-top-msg` |
|
||||
| “置顶某条消息” | `chat message set-top-msg` | 不要用 `chat set-top` |
|
||||
| “机器人发消息” | `chat message send-by-bot` | 不要用当前用户身份 `message send` 代发 |
|
||||
| “给机器人发单聊” | `chat bot find` 取 openDingTalkId → `message send --open-dingtalk-id` | 不要用 `bot search`,它没有 openDingTalkId |
|
||||
| “发图片/文件/音频/视频” | `message send --msg-type file|audio|video --file-path`;已有图片 mediaId 才用 `image` | 不要先 `drive upload` 或 `dt_media_upload` |
|
||||
| “特别关注的人最近发了什么” | `message list-focused` | 不要先查 `contact relation list-my-followings` |
|
||||
| “某人发给我的消息” | `message list-by-sender` | 不要只查单聊,结果应覆盖群聊+单聊 |
|
||||
| “搜索消息” | 首选 `message search-advanced` | 不要在可组合条件下退回简单 `message search` |
|
||||
| “消息转待办” | 先用 `chat message list/search-advanced` 取消息内容,再调用 `dws todo task create` | 不要在 chat 内寻找“转待办”命令 |
|
||||
| “消息转日程” | 先用 `chat message list/search-advanced` 取消息内容,再调用 `dws calendar event create` | 不要在 chat 内寻找“转日程”命令 |
|
||||
| “共同群” | `chat search-common --nicks` | 不要分别搜索群再手工求交 |
|
||||
| “拉取群文件 / 群文件列表” | `chat conversation-info --group <openConversationId>` 取 `spaceId` → `dws drive list --space-id <spaceId>` | 不要用 `chat file upload`,它只负责上传 |
|
||||
| “清空会话聊天记录” | `chat clear-messages` | 不要理解为删除群消息;它只影响当前用户视角 |
|
||||
|
||||
## 发送前检查清单
|
||||
|
||||
执行任何发送类命令前,至少检查:
|
||||
|
||||
1. 接收对象明确:群聊必须有 `openConversationId`,单聊必须有 `userId` 或 `openDingTalkId`。
|
||||
2. 身份明确:用户身份发送用 `message send`,机器人身份发送用 `send-by-bot`,Webhook 用 `send-by-webhook`。
|
||||
3. 内容明确:消息正文、标题、附件、卡片内容都能从用户原始需求中找到依据。
|
||||
4. @ 对象明确:`--at-all`、`--at-user-ids`、`--at-open-dingtalk-ids` 不可自行追加。
|
||||
5. 文件路径明确:本地文件、音频、视频必须传 `--msg-type file|audio|video --file-path`,并确认路径是用户提供或当前任务生成的目标文件。
|
||||
6. 重试策略明确:失败重试时复用同一个 `--uuid`,避免重复投递。
|
||||
|
||||
## 高频一跳命令
|
||||
|
||||
这些命令覆盖多数日常问题;复杂参数再跳到对应子文档。
|
||||
|
||||
| 场景 | 一跳命令 |
|
||||
|------|----------|
|
||||
| 找群 | `dws chat search --query "群名" --format json` |
|
||||
| 建群 | `dws chat group create --name "群名" --users userId1,userId2 --format json` |
|
||||
| 看群成员 | `dws chat group members --id <openConversationId> --format json` |
|
||||
| 看群内昵称 | `dws chat group members --id <openConversationId> --format json` |
|
||||
| 发群文字 | `dws chat message send --group <openConversationId> --text "内容" --uuid <uuid> --format json` |
|
||||
| 发单聊文字 | `dws chat message send --user <userId> --text "内容" --uuid <uuid> --format json` |
|
||||
| 发本地文件 | `dws chat message send --group <openConversationId> --msg-type file --file-path ./file.pdf --format json` |
|
||||
| 发音频/视频 | `dws chat message send --group <openConversationId> --msg-type audio --file-path ./voice.mp3 --format json` / `--msg-type video --file-path ./demo.mp4` |
|
||||
| 发位置/名片 | `dws chat message send --group <openConversationId> --msg-type location ...` / `--msg-type profile --contact-id <openDingTalkId>` |
|
||||
| 拉群消息 | `dws chat message list --group <openConversationId> --time "2026-03-10 00:00:00" --direction older --format json` |
|
||||
| 搜消息 | `dws chat message search-advanced --query "关键词" --start <ISO> --end <ISO> --format json` |
|
||||
| 查 @ 我的消息 | `dws chat message search-advanced --at-me --start <ISO> --end <ISO> --format json` |
|
||||
| 查未读会话 | `dws chat message list-unread-conversations --count 20 --format json` |
|
||||
| 撤回自己消息 | `dws chat message recall --conversation-id <openConversationId> --msg-id <openMessageId> --format json` |
|
||||
| 查我的机器人 | `dws chat bot search --name "机器人名" --format json` |
|
||||
| 机器人发群消息 | `dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> --title "标题" --text "## 标题\n\n正文" --format json` |
|
||||
| Webhook 告警 | `dws chat message send-by-webhook --token <token> --title "告警" --text "内容" --format json` |
|
||||
| 查单聊会话 ID | `dws chat conversation-info --user <userId> --format json` |
|
||||
| 查群钉盘空间 | `dws chat conversation-info --group <openConversationId> --format json` |
|
||||
| 发群公告 | `dws chat group notice create --group <openConversationId> --content "公告内容" --format json` |
|
||||
| 分享群邀请 | `dws chat group share-invite --source <sourceOpenConversationId> --target <targetOpenConversationId> --format json` |
|
||||
| 置顶会话 | `dws chat set-top --conversation-id <openConversationId> --format json` |
|
||||
| 清红点 | `dws chat clear-red-point --conversation-id <openConversationId> --format json` |
|
||||
| 会话分组 | `dws chat category list --format json` |
|
||||
| 智能会话分组 | `dws chat category create-smart --name "重点群" --keywords "项目,重点" --format json` |
|
||||
| 文本翻译 | `dws chat text translate --query "你好世界" --to en_US --format json` |
|
||||
|
||||
## 命令索引表
|
||||
|
||||
### 消息与文件
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 详见 |
|
||||
|------|------|----------|------|
|
||||
| `message send` | 当前用户发群聊/单聊文本、Markdown、图片、文件、音频、视频、位置、名片 | `--group` / `--user` / `--open-dingtalk-id` 三选一;文本用 `--text`,本地文件/音视频用 `--msg-type file|audio|video --file-path` | [chat-message](chat/chat-message.md#发送消息) |
|
||||
| `message list` | 拉取群聊或单聊消息 | `--time` + `--group` / `--user` / `--open-dingtalk-id` 三选一 | [chat-message](chat/chat-message.md#拉取消息) |
|
||||
| `message list-all` | 指定时间范围内拉取当前用户全部会话消息 | `--start` `--end` `--limit` `--cursor` | [chat-message](chat/chat-message.md#拉取消息) |
|
||||
| `message list-by-sender` | 跨单聊和群聊查指定发送者消息 | `--sender-user-id` / `--sender-open-dingtalk-id` 二选一 | [chat-message](chat/chat-message.md#拉取消息) |
|
||||
| `message list-mentions` | 查 @ 我的消息 | 可选 `--group`、`--start`、`--end` | [chat-message](chat/chat-message.md#拉取消息) |
|
||||
| `message list-focused` | 查特别关注人消息 | 无 | [chat-message](chat/chat-message.md#拉取消息) |
|
||||
| `message list-unread-conversations` | 获取未读会话列表 | 可选 `--count` | [chat-conversation](chat/chat-conversation.md#会话列表与红点) |
|
||||
| `message search-advanced` | 多维度搜索消息,首选;支持消息类型、会话类型、机器人消息过滤 | 至少一个搜索条件 | [chat-message](chat/chat-message.md#搜索消息) |
|
||||
| `message search` | 简单关键词搜索消息 | `--query` | [chat-message](chat/chat-message.md#搜索消息) |
|
||||
| `message read-status` | 查询消息已读/未读状态 | `--group` `--message-id` | [chat-message](chat/chat-message.md#消息状态与撤回) |
|
||||
| `message query-send-status` | 查询发送任务状态 | `--open-task-id` | [chat-message](chat/chat-message.md#消息状态与撤回) |
|
||||
| `message recall` | 撤回当前用户消息;群主/管理员可撤回群内他人消息 | `--conversation-id` `--msg-id` | [chat-message](chat/chat-message.md#消息状态与撤回) |
|
||||
| `message edit` | 编辑已发送消息内容 | `--conversation-id` `--msg-id`,`--text` / `--content` 二选一 | [chat-message](chat/chat-message.md#消息状态与撤回) |
|
||||
| `message reply` | 引用回复消息 | `--conversation-id` `--ref-msg-id` `--ref-sender` `--text` | [chat-message](chat/chat-message.md#回复与转发) |
|
||||
| `message forward` | 转发单条消息 | `--src-conversation-id` `--msg-id` `--dest-conversation-id` | [chat-message](chat/chat-message.md#回复与转发) |
|
||||
| `message combine-forward` | 合并转发多条消息 | `--src-conversation-id` `--msg-ids` `--dest-conversation-id` | [chat-message](chat/chat-message.md#回复与转发) |
|
||||
| `message list-topic-replies` | 拉取话题回复 | `--group` `--topic-id` | [chat-message](chat/chat-message.md#话题与卡片) |
|
||||
| `message forward-topic` | 转发话题消息 | 源消息、源会话、话题 ID、目标会话 | [chat-message](chat/chat-message.md#话题与卡片) |
|
||||
| `message send-card` / `update-card` | 创建并流式更新卡片 | `send-card` 目标二选一;`update-card` 需 `--biz-id` | [chat-message](chat/chat-message.md#话题与卡片) |
|
||||
| `message add-emoji` / `remove-emoji` | 添加/移除默认表情回应 | `--conversation-id` `--msg-id` `--emoji` | [chat-message](chat/chat-message.md#表情回应) |
|
||||
| `message add-text-emotion` / `update-text-emotion` / `remove-text-emotion` | 添加/更新/移除文字表情 | update 需 `--old-emotion-id` `--emotion-id`,其余用 `--emotion-*` | [chat-message](chat/chat-message.md#表情回应) |
|
||||
| `message create-text-emotion` | 创建文字表情模板 | `--emotion-name` `--text` | [chat-message](chat/chat-message.md#表情回应) |
|
||||
| `message list-emotion-replies` | 批量拉取消息表情回复和文字回复 | `--msg-ids` | [chat-message](chat/chat-message.md#表情回应) |
|
||||
| `file upload` | 上传本地或 URL 文件到会话文件空间 | 目标三选一 + `--file` / `--url` 二选一 | [chat-message](chat/chat-message.md#文件与媒体) |
|
||||
| `message download-media` | 下载消息中的图片/视频/语音等资源 | `--type` `--resource-id` `--message-id` `--open-conversation-id` `--output` | [chat-message](chat/chat-message.md#文件与媒体) |
|
||||
| `text translate` | 翻译文本内容 | `--query` `--to` | [chat-message](chat/chat-message.md#文本工具) |
|
||||
|
||||
### 群聊与群身份
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 详见 |
|
||||
|------|------|----------|------|
|
||||
| `search` | 按关键词搜索群聊 | `--query` | [chat-group](chat/chat-group.md#搜索与基础信息) |
|
||||
| `search-common` | 查询指定人共同群 | `--nicks` | [chat-group](chat/chat-group.md#搜索与基础信息) |
|
||||
| `group create` | 创建内部群/外部群/普通群/话题圈,可指定群主 | `--name` `--users`,可选 `--owner` | [chat-group](chat/chat-group.md#群创建与基础操作) |
|
||||
| `group members` | 查看群成员 | `--id` | [chat-group](chat/chat-group.md#成员与机器人) |
|
||||
| `group members add/remove` | 添加/移除群成员 | `--id` `--users` | [chat-group](chat/chat-group.md#成员与机器人) |
|
||||
| `group members add-bot/remove-bot` | 添加/移除群机器人 | `--id` + 机器人标识 | [chat-group](chat/chat-group.md#成员与机器人) |
|
||||
| `group members list-by-ids` | 批量查群成员详情 | `--id` `--users` | [chat-group](chat/chat-group.md#成员与机器人) |
|
||||
| `group rename` | 修改群名称 | `--id` `--name` | [chat-group](chat/chat-group.md#群创建与基础操作) |
|
||||
| `group get-by-group-id` | 数字群号转 openConversationId | `--group-id` | [chat-group](chat/chat-group.md#搜索与基础信息) |
|
||||
| `group transfer-owner` | 转让群主 | `--group` + `--user` / `--new-owner` | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group upgrade-to-external` | 仅将 NORMAL_GROUP 普通群升级为外部群 | `--group` `--yes`,可选 `--extension` | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group invite-url` | 获取群邀请链接 | `--group` | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group share-invite` | 将群邀请链接分享到另一个会话或单聊用户 | `--source` + `--target` / `--receiver` 二选一 | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group notice *` | 群公告创建、修改、详情、列表 | `--group`,视子命令补充公告参数 | [chat-group](chat/chat-group.md#群公告) |
|
||||
| `group quit` / `dismiss` | 退出/解散群聊 | `--group` | [chat-group](chat/chat-group.md#群创建与基础操作) |
|
||||
| `group update-icon` | 更新群头像 | `--group` `--icon-media-id` | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group update-settings` | 更新管理员级别的群功能开关 | `--group` `--setting-key` `--status` | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group user-settings query/set` | 批量查询/更新当前用户自己的群会话设置 | `query --groups` / `set --items` | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group update-nick` / `update-alias` | 设置或清除群昵称 / 设置群备注 | `update-nick` 需 `--group`,`--nick` 可选;`update-alias` 需备注 | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group set-history` | 设置新成员可见历史消息范围 | `--group` `--option` | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group get-mute-config` | 查询群用户禁言配置 | `--group` | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group list-my-groups` / `list-all` | 拉取我管理的群 / 我加入的所有群 | 可选分页参数 | [chat-group](chat/chat-group.md#群列表与入群审批) |
|
||||
| `group list-join-validations` | 拉取入群验证记录 | 可选分页参数 | [chat-group](chat/chat-group.md#群列表与入群审批) |
|
||||
| `group audit-join-validation` | 审批入群验证 | `--group` `--record-id` `--applicant` `--inviter` `--status` | [chat-group](chat/chat-group.md#群列表与入群审批) |
|
||||
| `group-mute` / `group-mute-member` | 全员禁言 / 指定成员禁言 | `--group`,成员禁言还需用户与时长 | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group set-admin` | 设置/取消群管理员 | `--group` `--user` / `--users` | [chat-group](chat/chat-group.md#群设置与权限) |
|
||||
| `group-role *` | 群身份列表、增删改、设置成员身份 | `--group` + role/user 参数 | [chat-group](chat/chat-group.md#群身份) |
|
||||
|
||||
### 机器人与 Webhook
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 详见 |
|
||||
|------|------|----------|------|
|
||||
| `bot search` | 搜索我创建的机器人 | 可选 `--name` | [chat-bot](./chat/chat-bot.md#机器人搜索) |
|
||||
| `bot find` | 搜索全部可用机器人,返回 openDingTalkId | `--query` | [chat-bot](./chat/chat-bot.md#机器人搜索) |
|
||||
| `message send-by-bot` | 机器人发群聊或单聊消息 | `--robot-code` `--title` `--text` + 目标二选一 | [chat-bot](./chat/chat-bot.md#机器人发送与撤回) |
|
||||
| `message recall-by-bot` | 撤回机器人消息 | `--robot-code` `--keys` | [chat-bot](./chat/chat-bot.md#机器人发送与撤回) |
|
||||
| `message send-by-webhook` | 自定义机器人 Webhook 发群消息 | `--token` `--title` `--text` | [chat-bot](./chat/chat-bot.md#webhook) |
|
||||
| `group members add-bot/remove-bot` | 机器人加入/移出群 | `--id` + 机器人标识 | [chat-bot](./chat/chat-bot.md#机器人进群) |
|
||||
| `group bots` | 查看群内所有机器人 | `--group` | [chat-bot](./chat/chat-bot.md#机器人进群) |
|
||||
|
||||
### 会话状态与分组
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 详见 |
|
||||
|------|------|----------|------|
|
||||
| `conversation-info` | 获取群聊或单聊会话基础信息 | `--group` / `--user` / `--open-dingtalk-id` 三选一 | [chat-conversation](./chat/chat-conversation.md#会话基础信息) |
|
||||
| `list-all-conversations` | 分页获取全部会话 | 可选分页参数 | [chat-conversation](./chat/chat-conversation.md#会话列表与红点) |
|
||||
| `list-top-conversations` | 拉取置顶会话列表 | 可选分页参数 | [chat-conversation](./chat/chat-conversation.md#会话列表与红点) |
|
||||
| `set-top` | 设置/取消会话置顶 | `--conversation-id` | [chat-conversation](./chat/chat-conversation.md#会话置顶与通知) |
|
||||
| `mute` | 开启/关闭会话免打扰 | `--conversation-id` | [chat-conversation](./chat/chat-conversation.md#会话置顶与通知) |
|
||||
| `hide` | 隐藏会话 | `--conversation-id` | [chat-conversation](./chat/chat-conversation.md#会话置顶与通知) |
|
||||
| `mute-at-all` / `mute-red-envelope` | 关闭/恢复 @所有人或红包通知 | `--conversation-id` | [chat-conversation](./chat/chat-conversation.md#会话置顶与通知) |
|
||||
| `mark-unread` / `mark-read` | 标记会话未读 / 标记消息已读 | 会话 ID;`mark-read` 还需消息 ID | [chat-conversation](./chat/chat-conversation.md#已读未读与清理) |
|
||||
| `clear-red-point` / `clear-all-red-point` | 清除单会话/全部红点 | 单会话需 `--conversation-id` | [chat-conversation](./chat/chat-conversation.md#会话列表与红点) |
|
||||
| `clear-messages` | 清空当前用户视角会话消息 | `--conversation-id` | [chat-conversation](./chat/chat-conversation.md#已读未读与清理) |
|
||||
| `category list-by-conv` | 拉取指定会话所属的用户自定义会话分组 | `--group` | [chat-conversation](./chat/chat-conversation.md#会话分组) |
|
||||
| `category batch-info` | 批量拉取用户自定义会话分组信息 | `--category-ids` | [chat-conversation](./chat/chat-conversation.md#会话分组) |
|
||||
| `category *` | 自定义会话分组和智能分组管理 | 视子命令而定 | [chat-conversation](./chat/chat-conversation.md#会话分组) |
|
||||
|
||||
## 意图判断
|
||||
|
||||
### 消息
|
||||
|
||||
| 用户说 | 路由 |
|
||||
|--------|------|
|
||||
| “发群消息 / 发到某群” | `chat message send --group`,先用 `chat search` 找 `openConversationId` |
|
||||
| “发单聊 / 发给某人” | `chat message send --user` 或 `--open-dingtalk-id`,人员信息见 `dingtalk-contact` |
|
||||
| “发图片 / 发文件 / 发截图 / 发音频 / 发视频” | `chat message send --msg-type file|audio|video --file-path <本地路径>`;`audio/video` 底层按 `file` 发送 |
|
||||
| “发位置 / 分享地址” | `chat message send --msg-type location`,需经用户确认经纬度和地址名 |
|
||||
| “发联系人名片 / 分享联系人” | `chat message send --msg-type profile --contact-id <openDingTalkId>` |
|
||||
| “机器人发消息 / 机器人群发” | `chat message send-by-bot`,不要用用户身份代发 |
|
||||
| “撤回我发的消息” | `chat message recall` |
|
||||
| “撤回机器人发的消息” | `chat message recall-by-bot` |
|
||||
| “查某群聊天记录” | `chat message list --group` |
|
||||
| “查和某人的单聊记录” | `chat message list --user` 或 `--open-dingtalk-id` |
|
||||
| “某人发给我的消息 / 指定发送者消息” | `chat message list-by-sender`,跨单聊和群聊 |
|
||||
| “我今天/最近所有消息” | `chat message list-all --start <ISO> --end <ISO>` |
|
||||
| “@我的消息” | `chat message list-mentions` 或 `search-advanced --at-me` |
|
||||
| “特别关注的人最近发了什么” | `chat message list-focused`,不要先查关注人员列表 |
|
||||
| “搜索消息里的关键词 / 多维度搜索” | 首选 `chat message search-advanced` |
|
||||
| “只搜文件消息 / 只搜群聊 / 只看机器人消息” | `chat message search-advanced --message-type file --search-conv-type group_chat --only-robot-messages` 按需组合 |
|
||||
| “翻译这段文字” | `chat text translate --query <文本> --to <语言代码>` |
|
||||
| “把这条消息转待办 / 消息里提到的事项建待办” | 先取消息内容和相关人员,再按 `dingtalk-todo` 调 `dws todo task create`;标题、执行人、截止时间必须来自消息或用户确认 |
|
||||
| “把这条消息转日程 / 消息里约的会建日程” | 先取消息内容、时间、地点、参会人,再按 `dingtalk-calendar` 调 `dws calendar event create`;时间不明确必须先确认 |
|
||||
| “话题回复 / 往话题里回复” | 先 `message list` 获取 `openConvThreadId`,再 `list-topic-replies` 或 `message send --group <openConvThreadId>` |
|
||||
| “消息已读未读 / 谁看了消息” | `chat message read-status` |
|
||||
| “置顶某条消息 / 取消消息置顶” | `chat message set-top-msg` / `unset-top-msg` |
|
||||
|
||||
### 群与成员
|
||||
|
||||
| 用户说 | 路由 |
|
||||
|--------|------|
|
||||
| “建群 / 创建群聊” | `chat group create` |
|
||||
| “建群并指定群主 / 让某某当群主” | `chat group create --owner <openDingTalkId>`,群主必须来自用户指定或确认 |
|
||||
| “建外部群 / 建普通群 / 建话题圈” | `chat group create --type EXTERNAL` / `--type NORMAL` / `--thread` |
|
||||
| “找群 / 搜索群” | `chat search --query` |
|
||||
| “群成员 / 群里有谁” | `chat group members` |
|
||||
| “群成员在群里的昵称 / 群昵称” | `chat group members --id <openConversationId>`,返回中包含群内昵称/展示名 |
|
||||
| “拉人进群 / 踢人” | `chat group members add` / `remove` |
|
||||
| “批量查群成员详情” | `chat group members list-by-ids` |
|
||||
| “改群名 / 群头像 / 群备注 / 群昵称” | `group rename` / `update-icon` / `update-alias` / `update-nick` |
|
||||
| “转让群主 / 设置管理员 / 禁言” | `group transfer-owner` / `group set-admin` / `group-mute*` |
|
||||
| “分享群链接 / 群邀请发给某人或某群” | `chat group share-invite` |
|
||||
| “发群公告 / 改群公告 / 查群公告” | `chat group notice create/edit/get/list` |
|
||||
| “入群审批 / 入群验证记录” | `group list-join-validations` → `group audit-join-validation` |
|
||||
| “群身份 / 群标签 / 给成员设置身份” | `group-role *` |
|
||||
| “我和某人的共同群” | `chat search-common --nicks` |
|
||||
|
||||
### 机器人
|
||||
|
||||
| 用户说 | 路由 |
|
||||
|--------|------|
|
||||
| “查看我的机器人 / 我创建的机器人” | `chat bot search` |
|
||||
| “找机器人 / 搜索全部可用机器人 / 给机器人发单聊” | `chat bot find`,需要 `openDingTalkId` |
|
||||
| “加机器人到群 / 从群移除机器人 / 群里有哪些机器人” | `group members add-bot` / `remove-bot` / `group bots` |
|
||||
| “Webhook 发告警” | `chat message send-by-webhook` |
|
||||
|
||||
### 会话状态
|
||||
|
||||
| 用户说 | 路由 |
|
||||
|--------|------|
|
||||
| “未读会话列表” | `chat message list-unread-conversations` |
|
||||
| “置顶会话 / 查看置顶会话” | `chat list-top-conversations` |
|
||||
| “把会话置顶 / 取消会话置顶” | `chat set-top` / `chat set-top --off` |
|
||||
| “免打扰 / 关闭免打扰” | `chat mute` / `chat mute --off` |
|
||||
| “隐藏会话” | `chat hide` |
|
||||
| “清红点 / 全部已读” | `chat clear-red-point` / `chat clear-all-red-point` |
|
||||
| “标记未读 / 标记已读” | `chat mark-unread` / `chat mark-read` |
|
||||
| “清空聊天记录” | `chat clear-messages` |
|
||||
| “会话分组” | `chat category *` |
|
||||
| “智能分组 / 按关键词或成员自动分组” | `chat category create-smart` |
|
||||
| “群文件 / 拉取群文件列表” | `chat conversation-info --group <openConversationId>` 取 `spaceId`,再按 `dingtalk-drive` 调 `dws drive list --space-id <spaceId>` |
|
||||
|
||||
## 核心工作流索引
|
||||
|
||||
| 场景 | 入口 |
|
||||
|------|------|
|
||||
| 搜索群并拉消息 | [chat-workflows §群聊消息](./chat/chat-workflows.md#群聊消息) |
|
||||
| 个人身份发送群聊/单聊/文件 | [chat-workflows §发送消息](./chat/chat-workflows.md#发送消息) |
|
||||
| 机器人发消息后撤回 | [chat-workflows §机器人消息](./chat/chat-workflows.md#机器人消息) |
|
||||
| 机器人不在群内时先邀请再发送 | [chat-workflows §机器人消息](./chat/chat-workflows.md#机器人消息) |
|
||||
| 给机器人发单聊 | [chat-workflows §机器人消息](./chat/chat-workflows.md#机器人消息) |
|
||||
| 发送图片 / 文件 / 音频 / 视频 | [chat-workflows §发送消息](./chat/chat-workflows.md#发送消息) |
|
||||
| 流式卡片创建与更新 | [chat-message §话题与卡片](./chat/chat-message.md#话题与卡片) |
|
||||
| 群公告发布与修改 | [chat-group §群公告](./chat/chat-group.md#群公告) |
|
||||
| 消息转待办 | 先用 [chat-message](./chat/chat-message.md#拉取消息) 取消息内容,再读取 `dingtalk-todo` 创建待办 |
|
||||
| 消息转日程 | 先用 [chat-message](./chat/chat-message.md#拉取消息) 取消息内容,再读取 `dingtalk-calendar` 创建日程 |
|
||||
| 拉取群文件 | `conversation-info` 取 `spaceId`,再读取 `dingtalk-drive` 查询钉盘文件 |
|
||||
|
||||
## 上下文传递摘要
|
||||
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `chat search` / `chat group create` / `chat group get-by-group-id` | `openConversationId` | `--group`、`--conversation-id`、群成员、消息发送/拉取 |
|
||||
| `chat conversation-info` | 单聊 `openConversationId` | 单聊消息搜索、转发、会话状态操作 |
|
||||
| `chat conversation-info --group` | `spaceId` | `drive list/info/download --space-id`,用于拉取群文件 |
|
||||
| `chat group members` | 群成员昵称/展示名、`userId`、`openDingTalkId` | 识别群内发言人、@ 人、待办执行人、日程参会人 |
|
||||
| `aisearch person` | `userId`、`openDingTalkId` | 单聊、@ 人、机器人单聊、按发送者搜索 |
|
||||
| `chat bot search` | `robotCode` | `send-by-bot`、`recall-by-bot` |
|
||||
| `chat bot find` | `openDingTalkId` | 给机器人发单聊 |
|
||||
| `chat message send-by-bot` | `processQueryKey` | `recall-by-bot --keys` |
|
||||
| `chat message send` | `openTaskId` | `query-send-status` |
|
||||
| `chat message list` | `openMessageId`、`openMsgId`、`openConvThreadId` | 撤回、已读状态、表情、回复、转发、话题回复 |
|
||||
| `chat message list/search-advanced` | 消息正文、发送人、时间 | 创建 `todo task` 或 `calendar event` 前的输入材料 |
|
||||
| `chat message search(-advanced)` / `list-all` | `nextCursor` | 下一页 `--cursor` |
|
||||
| `chat group-role list` | `openRoleId` | `group-role update/remove/set-user/remove-user` |
|
||||
| `chat message send-card` | `bizId` | `message update-card --biz-id` |
|
||||
|
||||
完整字段传递表见 [chat-workflows](./chat/chat-workflows.md#上下文传递表)。
|
||||
|
||||
## 相关产品
|
||||
|
||||
- [contact](../../dingtalk-contact/references/contact.md) — 搜索人员,获取 `userId` / `openDingTalkId`。
|
||||
- [todo](../../dingtalk-todo/references/todo.md) — 消息转待办时使用;从 chat 消息内容提取标题、执行人、截止时间后调用 `dws todo task create`。
|
||||
- [calendar](../../dingtalk-calendar/references/calendar.md) — 消息转日程时使用;从 chat 消息内容提取标题、开始/结束时间、地点、参会人后调用 `dws calendar event create`。
|
||||
- [drive](../../dingtalk-drive/references/drive.md) — 云盘/群文件管理;拉群文件先用 `chat conversation-info` 取 `spaceId`,再用 `dws drive list --space-id <spaceId>`;chat 纯文件/音视频发送优先用 `chat message send --msg-type file|audio|video --file-path`。
|
||||
- [aisearch](../../dingtalk-aisearch/references/aisearch.md) — 可用于人员、行为、历史信息搜索,但消息发送与会话管理仍走 `chat`。
|
||||
- [ding](../../dingtalk-misc/references/ding.md) — DING 通知与升级提醒,不等价于群聊消息。
|
||||
|
||||
文本翻译(`chat text translate`)详见 [chat-message](./chat/chat-message.md#文本工具)。
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
# chat-bot:机器人与 Webhook
|
||||
|
||||
> 返回入口:[chat.md](../chat.md)
|
||||
|
||||
## 适用场景
|
||||
|
||||
用于搜索机器人、机器人发送/撤回消息、Webhook 告警、机器人加入/移出群,以及给机器人发单聊消息。
|
||||
|
||||
## 必读约束
|
||||
|
||||
- 用户明确要求“用机器人/机器人身份/robot”发送时,必须用 `chat message send-by-bot`,严禁改用 `chat message send`。
|
||||
- `chat bot search` 只返回我创建的机器人,没有 `openDingTalkId`;给机器人发单聊必须用 `chat bot find`。
|
||||
- 机器人发群消息前需确认机器人已在群中;报“机器人不存在”时先 `group members add-bot`。
|
||||
- `send-by-bot --text` 支持 Markdown;需要稳定换行时用空行分隔段落。若以转义形式组织文本,写 `\n\n`,不要只写 `\n`。
|
||||
- `recall-by-bot` 使用 `processQueryKey`,不是 `openMessageId`。
|
||||
|
||||
## 命令明细
|
||||
|
||||
### 机器人搜索
|
||||
|
||||
| 命令 | 范围 | 返回 openDingTalkId | 典型触发词 |
|
||||
|------|------|---------------------|------------|
|
||||
| `chat bot search` | 仅当前用户自己创建的机器人 | 否 | “我的机器人”“我创建的机器人” |
|
||||
| `chat bot find` | 当前用户可用的全部机器人(含他人/官方) | 是 | “找机器人”“搜索机器人”“给机器人发单聊” |
|
||||
|
||||
```bash
|
||||
dws chat bot search --page 1 --size 10 --name "日报"
|
||||
dws chat bot find --query "日报" --limit 20
|
||||
dws chat bot find --query "日报" --limit 20 --cursor <nextCursor>
|
||||
```
|
||||
|
||||
`bot find` 翻页时 `cursor` 必须使用上次返回的 `nextCursor` 字符串原值,不要传 `"0"` 或数字字面量。
|
||||
|
||||
### 机器人发送与撤回
|
||||
|
||||
#### `dws chat message send-by-bot`
|
||||
|
||||
```bash
|
||||
# 群聊
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> --title "日报" --text "## 今日完成\n\n- 事项 A\n\n- 事项 B"
|
||||
|
||||
# 单聊 userId
|
||||
dws chat message send-by-bot --robot-code <robot-code> --users userId1,userId2 --title "提醒" --text "请提交周报"
|
||||
|
||||
# 单聊 openDingTalkId
|
||||
dws chat message send-by-bot --robot-code <robot-code> --open-dingtalk-ids openDingTalkId1,openDingTalkId2 --title "提醒" --text "请提交周报"
|
||||
|
||||
# 群聊 @ 人
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> --at-user-ids userId1,userId2 --title "提醒" --text "@userId1 @userId2 请查收"
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> --at-open-dingtalk-ids openDingTalkId1,openDingTalkId2 --title "提醒" --text "@openDingTalkId1 @openDingTalkId2 请查收"
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> --at-all --title "通知" --text "请所有人注意"
|
||||
```
|
||||
|
||||
关键 flags:
|
||||
|
||||
| Flag | 说明 |
|
||||
|------|------|
|
||||
| `--robot-code` | 机器人 Code,必填 |
|
||||
| `--group` | 群聊 openConversationId |
|
||||
| `--users` | 单聊 userId 列表,逗号分隔,最多 20 个 |
|
||||
| `--open-dingtalk-ids` | 单聊 openDingTalkId 列表 |
|
||||
| `--title` / `--text` | 消息标题与 Markdown 内容,必填;Markdown 换行用空行,转义表示为 `\n\n` |
|
||||
| `--at-user-ids` / `--at-open-dingtalk-ids` | 群聊 @ 指定成员,正文需含对应 `@id` 文本 |
|
||||
| `--at-all` | 群聊 @所有人 |
|
||||
|
||||
#### `dws chat message recall-by-bot`
|
||||
|
||||
```bash
|
||||
dws chat message recall-by-bot --robot-code <robot-code> --group <openConversationId> --keys <processQueryKey>
|
||||
dws chat message recall-by-bot --robot-code <robot-code> --keys key1,key2
|
||||
```
|
||||
|
||||
群聊撤回传 `--group`;单聊撤回不传 `--group`。`--keys` 来自 `send-by-bot` 返回的 `processQueryKey`。
|
||||
|
||||
### Webhook
|
||||
|
||||
```bash
|
||||
dws chat message send-by-webhook --token <webhook-token> --title "告警" --text "CPU 超 90% @10" --at-all
|
||||
dws chat message send-by-webhook --token <webhook-token> --title "test" --text "hi @118785" --at-users 118785
|
||||
```
|
||||
|
||||
关键规则:
|
||||
|
||||
- `--token`、`--title`、`--text` 必填。
|
||||
- `--at-all` 时 `--text` 中需包含 `@10`。
|
||||
- `--at-users` 或 `--at-mobiles` 时,`--text` 中需包含对应 `@userId` 或 `@手机号`,否则 @ 不生效。
|
||||
|
||||
### 机器人进群
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `group members add-bot` | 将自定义机器人加入群 | `--id` `--robot-code` |
|
||||
| `group members remove-bot` | 从群移除机器人 | `--id` `--bot-id` |
|
||||
| `group bots` | 查看群内机器人列表 | `--group` |
|
||||
|
||||
```bash
|
||||
dws chat group members add-bot --id <openConversationId> --robot-code <robot-code>
|
||||
dws chat group bots --group <openConversationId>
|
||||
dws chat group members remove-bot --id <openConversationId> --bot-id <openBotId>
|
||||
```
|
||||
|
||||
## 常见工作流
|
||||
|
||||
### 机器人发消息后撤回
|
||||
|
||||
```bash
|
||||
dws chat bot search --name "日报" --format json
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> --title "日报" --text "## 今日完成\n\n- 事项 A\n\n- 事项 B" --format json
|
||||
dws chat message recall-by-bot --robot-code <robot-code> --group <openConversationId> --keys <processQueryKey> --format json
|
||||
```
|
||||
|
||||
### 机器人不在群内时先邀请再发送
|
||||
|
||||
```bash
|
||||
dws chat bot search --name "日报" --format json
|
||||
dws chat group members add-bot --id <openConversationId> --robot-code <robot-code> --format json
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> --title "通知" --text "内容" --format json
|
||||
```
|
||||
|
||||
### 给机器人发单聊
|
||||
|
||||
```bash
|
||||
dws chat bot find --query "玉澜" --format json
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --text "你好" --format json
|
||||
```
|
||||
|
||||
### 机器人 @ 指定人
|
||||
|
||||
```bash
|
||||
dws aisearch person --keyword "张三" --dimension name --format json
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> --at-user-ids userId1 --title "提醒" --text "@userId1 请查收" --format json
|
||||
```
|
||||
|
||||
## 常见错误与回退
|
||||
|
||||
- 机器人单聊没有 openDingTalkId:改用 `chat bot find`,不要用 `bot search`。
|
||||
- 机器人发群消息报“机器人不存在”:先 `group members add-bot`。
|
||||
- 撤回失败:确认使用 `processQueryKey`,不是 `openMessageId`。
|
||||
- @ 不生效:检查正文是否包含 `@userId` / `@openDingTalkId` / `@10`。
|
||||
@@ -0,0 +1,140 @@
|
||||
# chat-conversation:会话状态、红点、置顶与分组
|
||||
|
||||
> 返回入口:[chat.md](../chat.md)
|
||||
|
||||
## 适用场景
|
||||
|
||||
用于获取会话基础信息、全部会话/置顶会话列表、会话置顶、免打扰、隐藏、红点、已读未读、清空聊天记录、自定义会话分组和智能会话分组。
|
||||
|
||||
## 必读约束
|
||||
|
||||
- 会话状态类命令通常需要 `openConversationId`。群聊可由 `chat search` 获取,单聊可由 `chat conversation-info --user/--open-dingtalk-id` 获取。
|
||||
- `set-top` 是会话置顶;`message set-top-msg` 是会话内消息置顶,二者不能混用。
|
||||
- `clear-messages` 只清空当前用户视角的消息,不影响其他成员。
|
||||
- 智能分组规则中的成员使用 openDingTalkId;如果用户只给姓名,先用 `aisearch person --dimension name` 获取。
|
||||
|
||||
## 命令明细
|
||||
|
||||
### 会话基础信息
|
||||
|
||||
```bash
|
||||
dws chat conversation-info --group <openConversationId> --format json
|
||||
dws chat conversation-info --user <userId> --format json
|
||||
dws chat conversation-info --open-dingtalk-id <openDingTalkId> --format json
|
||||
```
|
||||
|
||||
`--group`、`--user`、`--open-dingtalk-id` 互斥且必须指定一个。文件/音视频发送不再依赖调用方读取 spaceId;直接用 `message send --msg-type file|audio|video --file-path`。
|
||||
|
||||
### 会话列表与红点
|
||||
|
||||
| 命令 | 用途 | 参数 |
|
||||
|------|------|------|
|
||||
| `list-all-conversations` | 分页获取当前用户全部会话 | 可选 `--limit` `--cursor` `--exclude-muted` |
|
||||
| `list-top-conversations` | 获取置顶会话列表 | 可选 `--limit` `--cursor` `--exclude-muted` |
|
||||
| `message list-unread-conversations` | 获取未读会话列表 | 可选 `--count` `--exclude-muted` |
|
||||
| `clear-red-point` | 清除指定会话红点 | `--conversation-id`,别名 `--id` / `--chat` |
|
||||
| `clear-all-red-point` | 清除所有会话红点,一键全部已读 | 无参数 |
|
||||
|
||||
翻页时,`hasMore=true` 用返回的 `nextCursor` 作为下次 `--cursor`。
|
||||
|
||||
### 会话置顶与通知
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `set-top` | 设置/取消会话置顶 | `--conversation-id`;默认置顶,`--off` 取消 |
|
||||
| `mute` | 开启/关闭会话免打扰 | `--conversation-id`;默认开启,`--off` 关闭 |
|
||||
| `hide` | 隐藏会话 | `--conversation-id` |
|
||||
| `mute-at-all` | 关闭/恢复 @所有人通知 | `--conversation-id`;默认关闭,`--off` 恢复 |
|
||||
| `mute-red-envelope` | 关闭/恢复红包通知 | `--conversation-id`;默认关闭,`--off` 恢复 |
|
||||
|
||||
```bash
|
||||
dws chat set-top --conversation-id <openConversationId>
|
||||
dws chat set-top --conversation-id <openConversationId> --off
|
||||
dws chat mute --conversation-id <openConversationId>
|
||||
dws chat mute --conversation-id <openConversationId> --off
|
||||
dws chat hide --conversation-id <openConversationId>
|
||||
```
|
||||
|
||||
### 已读未读与清理
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `mark-unread` | 标记指定会话为未读 | `--conversation-id` |
|
||||
| `mark-read` | 将指定消息及之前消息标记为已读 | `--conversation-id` `--message-id` |
|
||||
| `clear-messages` | 清空当前用户指定会话的消息 | `--conversation-id` |
|
||||
|
||||
```bash
|
||||
dws chat mark-unread --conversation-id <openConversationId>
|
||||
dws chat mark-read --conversation-id <openConversationId> --message-id <openMessageId>
|
||||
dws chat clear-messages --conversation-id <openConversationId>
|
||||
```
|
||||
|
||||
### 会话分组
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `category list` | 获取用户自定义会话分组 | 无 |
|
||||
| `category list-conversations` | 拉取指定分组下会话 | `--category-id`,可选 `--exclude-muted` |
|
||||
| `category list-by-conv` | 拉取指定会话所属的用户自定义会话分组 | `--group` |
|
||||
| `category batch-info` | 批量拉取用户自定义会话分组信息 | `--category-ids` |
|
||||
| `category create` | 创建会话分组 | `--title` |
|
||||
| `category create-smart` | 创建智能会话分组,可按群名称关键词和群内成员匹配 | `--name`,可选 `--keywords` `--members` |
|
||||
| `category delete` | 删除会话分组 | `--category-id` |
|
||||
| `category rename` | 修改分组名称 | `--category-id` `--title` |
|
||||
| `category add-conv` | 将会话加入分组 | `--group` `--category-ids` |
|
||||
| `category remove-conv` | 将会话移出分组 | `--group` `--category-ids` |
|
||||
|
||||
```bash
|
||||
dws chat category list
|
||||
dws chat category list-by-conv --group <openConversationId>
|
||||
dws chat category batch-info --category-ids 123,456
|
||||
dws chat category create --title "工作群"
|
||||
dws chat category create-smart --name "重点群" --keywords "重点,项目" --members openDingTalkId1,openDingTalkId2
|
||||
dws chat category add-conv --group <openConversationId> --category-ids 123,456
|
||||
```
|
||||
|
||||
`create-smart` 中 `--keywords` 是群名称关键词列表,`--members` 是群内成员 openDingTalkId 列表;两者可单独使用,也可组合使用。
|
||||
|
||||
## 常见工作流
|
||||
|
||||
### 获取单聊会话 ID 后置顶
|
||||
|
||||
```bash
|
||||
dws aisearch person --keyword "张三" --dimension name --format json
|
||||
dws chat conversation-info --user <userId> --format json
|
||||
dws chat set-top --conversation-id <openConversationId> --format json
|
||||
```
|
||||
|
||||
### 查看置顶会话并拉消息
|
||||
|
||||
```bash
|
||||
dws chat list-top-conversations --limit 100 --format json
|
||||
dws chat message list --group <openConversationId> --time "2026-03-10 00:00:00" --direction older --format json
|
||||
```
|
||||
|
||||
### 会话分组
|
||||
|
||||
```bash
|
||||
dws chat category create --title "重点项目" --format json
|
||||
dws chat category add-conv --group <openConversationId> --category-ids <categoryId> --format json
|
||||
dws chat category list-by-conv --group <openConversationId> --format json
|
||||
dws chat category batch-info --category-ids <categoryId> --format json
|
||||
dws chat category list-conversations --category-id <categoryId> --format json
|
||||
```
|
||||
|
||||
### 智能会话分组
|
||||
|
||||
```bash
|
||||
dws aisearch person --keyword "张三" --dimension name --format json
|
||||
dws chat category create-smart --name "项目组" --keywords "项目,开发" --format json
|
||||
dws chat category create-smart --name "团队群" --members openDingTalkId1,openDingTalkId2 --format json
|
||||
dws chat category create-smart --name "重点群" --keywords "重点" --members openDingTalkId1 --format json
|
||||
```
|
||||
|
||||
## 常见错误与回退
|
||||
|
||||
- 用户说“置顶消息”:用 `message set-top-msg`,不是 `chat set-top`。
|
||||
- 用户说“置顶会话”:用 `chat set-top` 或 `list-top-conversations`。
|
||||
- 单聊没有会话 ID:先 `conversation-info --user` 或 `--open-dingtalk-id`。
|
||||
- 清空聊天记录前必须确认目标会话;该操作只影响当前用户视角。
|
||||
- 智能分组没有匹配条件:至少确认分组名称;关键词和成员规则不明确时先向用户确认,不要自行猜成员。
|
||||
@@ -0,0 +1,225 @@
|
||||
# chat-group:群聊、成员、设置与群身份
|
||||
|
||||
> 返回入口:[chat.md](../chat.md)
|
||||
|
||||
## 适用场景
|
||||
|
||||
用于群搜索、建群、成员增删、机器人进群、群设置、群主转让、群邀请分享、群公告、入群审批、群身份和群禁言。
|
||||
|
||||
## 必读约束
|
||||
|
||||
- 群聊目标统一使用 `openConversationId`。只有数字群号时,先用 `chat group get-by-group-id` 转换。
|
||||
- `chat search` 在 `chat` 根下,不在 `chat group` 下。
|
||||
- 群成员操作中,`--users` 常为逗号分隔列表;具体要求以命令 `--help` 为准。
|
||||
- 解散群、踢人、转让群主、禁言、管理员设置都是高影响操作,执行前必须确认目标群和用户。
|
||||
- 创建群并指定群主时,`--owner` 必须是用户明确指定或确认过的 `openDingTalkId`。
|
||||
- 发布或修改群公告会触达群成员;公告正文是 Markdown,定时公告 `--run-at` 建议带时区。
|
||||
|
||||
## 命令明细
|
||||
|
||||
### 搜索与基础信息
|
||||
|
||||
| 命令 | 用途 | 示例与要点 |
|
||||
|------|------|------------|
|
||||
| `chat search` | 按关键词搜索群聊 | `dws chat search --query "项目冲刺" --limit 20 --cursor 0`;可选 `--exclude-muted` |
|
||||
| `chat search-common` | 搜索共同群 | `dws chat search-common --nicks "风雷,山乔" --match-mode AND --limit 20 --cursor 0` |
|
||||
| `chat group get-by-group-id` | 数字群号转 openConversationId | `dws chat group get-by-group-id --group-id 12345678` |
|
||||
| `chat group bots` | 查看群内所有机器人 | `dws chat group bots --group <openConversationId>` |
|
||||
|
||||
`search-common` 中 `--match-mode AND` 表示所有人都在群里,`OR` 表示任一人在群里。
|
||||
|
||||
### 群创建与基础操作
|
||||
|
||||
#### `dws chat group create`
|
||||
|
||||
```bash
|
||||
dws chat group create --name "Q1 项目冲刺群" --users userId1,userId2,userId3
|
||||
dws chat group create --name "外部合作群" --users userId1,userId2 --type EXTERNAL
|
||||
dws chat group create --name "话题圈" --users userId1,userId2 --thread
|
||||
dws chat group create --name "项目群" --users userId1,userId2 --owner <openDingTalkId>
|
||||
```
|
||||
|
||||
关键 flags:
|
||||
|
||||
| Flag | 说明 |
|
||||
|------|------|
|
||||
| `--name` | 群名称,必填 |
|
||||
| `--users` | 成员 userId 或 openDingTalkId,逗号分隔,必填 |
|
||||
| `--owner` | 指定群主 openDingTalkId,可选;仅在用户明确指定群主时使用 |
|
||||
| `--type` | `INTERNAL` / `EXTERNAL` / `NORMAL`,默认 `INTERNAL` |
|
||||
| `--thread` | 开启话题模式,创建话题圈 |
|
||||
|
||||
创建成功后提取 `openConversationId`,用于发消息、成员管理、群设置。
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `group rename` | 更新群名称 | `--id` `--name` |
|
||||
| `group quit` | 当前用户退出群聊 | `--group` |
|
||||
| `group dismiss` | 解散群聊,不可逆 | `--group` |
|
||||
|
||||
### 成员与机器人
|
||||
|
||||
| 命令 | 用途 | 示例 |
|
||||
|------|------|------|
|
||||
| `group members` | 分页查看群成员 | `dws chat group members --id <openConversationId> --cursor 0` |
|
||||
| `group members add` | 添加群成员 | `dws chat group members add --id <openConversationId> --users userId1,userId2` |
|
||||
| `group members remove` | 移除群成员 | `dws chat group members remove --id <openConversationId> --users userId1,userId2` |
|
||||
| `group members list-by-ids` | 按 openDingTalkId 批量查成员详情 | `dws chat group members list-by-ids --id <openConversationId> --users openDingTalkId1,openDingTalkId2` |
|
||||
| `group members add-bot` | 将自定义机器人加入群 | `dws chat group members add-bot --id <openConversationId> --robot-code <robot-code>` |
|
||||
| `group members remove-bot` | 从群内移除机器人 | `dws chat group members remove-bot --id <openConversationId> --bot-id <openBotId>` |
|
||||
|
||||
机器人发群消息如果报“机器人不存在”,先 `group members add-bot` 再重发。
|
||||
|
||||
### 群设置与权限
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `group transfer-owner` | 转让群主 | `--group` + `--user`(userId) 或 `--new-owner`(openDingTalkId) |
|
||||
| `group upgrade-to-external` | 将普通群升级为外部群(不可逆,需先确认) | `--group` `--yes`;可选 `--extension`(拓展字段) |
|
||||
| `group invite-url` | 获取群邀请链接 | `--group`,可选 `--expires-seconds`,0 表示永久 |
|
||||
| `group share-invite` | 将指定群的邀请链接分享到另一个会话或单聊用户 | `--source` + `--target` / `--receiver` 二选一 |
|
||||
| `group update-icon` | 更新群头像 | `--group` `--icon-media-id` |
|
||||
| `group update-settings` | 更新管理员级别的群功能开关 | `--group` `--setting-key` `--status` |
|
||||
| `group user-settings query` | 批量查询当前用户自己的群会话设置 | `--groups` |
|
||||
| `group user-settings set` | 批量更新当前用户自己的群会话设置 | `--items` |
|
||||
| `group update-nick` | 设置或清除当前用户群昵称 | `--group`,可选 `--nick`;不传则清除群昵称 |
|
||||
| `group update-alias` | 设置当前用户群备注 | `--group` `--alias-title` |
|
||||
| `group set-history` | 设置新成员可查看历史消息范围 | `--group` `--option` |
|
||||
| `group get-mute-config` | 查询群用户禁言配置 | `--group` |
|
||||
| `group-mute` | 全员禁言/解除全员禁言 | `--group`,默认禁言,`--off` 解除 |
|
||||
| `group-mute-member` | 指定成员禁言/解除禁言 | `--group` `--user`/`--users`;禁言需 `--mute-time` |
|
||||
| `group set-admin` | 设置/取消管理员 | `--group` `--user`/`--users`;`--off` 取消 |
|
||||
|
||||
`update-settings` 是管理员级别的群功能开关操作,常用 settingKey:`authority`、`joinValidation`、`onlyAdminCanAtAll`、`searchable`、`addFriendForbidden`、`onlyAdminCanDING`、`onlyAdminCanPinMsg`、`onlyAdminCanSendFile`、`groupEmailDisabled`、`groupLiveAuthority`、`groupBillAuthority`。
|
||||
|
||||
`group user-settings` 是当前登录用户自己的群会话设置批量入口(置顶、免打扰、群昵称、群备注等),不是管理员级别的群功能开关;单个群昵称/群备注仍优先使用 `group update-nick` / `group update-alias`,管理员级别的群功能开关继续使用 `group update-settings`。
|
||||
|
||||
`group user-settings set --items` 传 JSON 数组,每个元素表示一个群会话的当前用户设置。字段含义:
|
||||
|
||||
| 字段 | 含义 | 值说明 |
|
||||
|------|------|--------|
|
||||
| `openConversationId` | 群会话 ID | 必填,来自 `chat search` / `group list-all` 等真实返回 |
|
||||
| `top` | 当前用户是否置顶该群会话 | `true`=置顶,`false`=取消置顶 |
|
||||
| `mute` | 当前用户是否开启该群会话免打扰 | `true`=开启免打扰,`false`=关闭免打扰 |
|
||||
| `groupNick` | 当前用户在该群里的群昵称 | 字符串;空字符串表示清空昵称 |
|
||||
| `groupAlias` | 当前用户给该群设置的备注 | 字符串;空字符串表示清空备注 |
|
||||
|
||||
只传本次要改的字段;不要补用户没要求修改的字段。批量设置多个群时,`items` 放多个对象。
|
||||
|
||||
`group-mute-member --mute-time` 单位毫秒,常用值:`300000`、`3600000`、`86400000`、`604800000`、`2592000000`。
|
||||
|
||||
`group share-invite` 的 `--source` 是被分享群的 `openConversationId`;`--target` 是接收分享消息的会话,`--receiver` 是接收分享消息的单聊用户 `openDingTalkId`,二者必须二选一。
|
||||
|
||||
```bash
|
||||
dws chat group share-invite --source <sourceOpenConversationId> --target <targetOpenConversationId>
|
||||
dws chat group share-invite --source <sourceOpenConversationId> --receiver <receiverOpenDingTalkId>
|
||||
dws chat group share-invite --source <sourceOpenConversationId> --target <targetOpenConversationId> --expires-seconds 86400 --uuid <uuid>
|
||||
dws chat group user-settings query --groups <openConversationId1>,<openConversationId2>
|
||||
dws chat group user-settings set --items '[{"openConversationId":"cid1","top":true,"mute":false}]'
|
||||
```
|
||||
|
||||
### 群公告
|
||||
|
||||
群公告正文使用 Markdown。支持标题、加粗、斜体、删除线、行内代码、链接、代码块、列表、表格、引用、分割线、图片、段落和换行;下划线、字体色、背景色、字号属于编辑器专属能力,无法通过 Markdown 表达。
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `group notice create` | 发布群公告,支持置顶、DING 和定时发布 | `--group` `--content` |
|
||||
| `group notice edit` | 整体替换指定群公告内容 | `--group` `--notice-id` `--content` |
|
||||
| `group notice get` | 查询单条群公告详情 | `--group` `--notice-id` |
|
||||
| `group notice list` | 分页拉取群公告列表 | `--group` |
|
||||
|
||||
```bash
|
||||
dws chat group notice create --group <openConversationId> --content "今晚 22 点系统维护,请提前保存工作内容"
|
||||
dws chat group notice create --group <openConversationId> --content "# 重要通知\n\n请大家查收" --sticky --send-ding
|
||||
dws chat group notice create --group <openConversationId> --content "明早九点例会" --run-at "2026-07-03T09:00:00+08:00"
|
||||
dws chat group notice list --group <openConversationId> --limit 20 --cursor <nextPageCursor>
|
||||
dws chat group notice get --group <openConversationId> --notice-id <dataId>
|
||||
dws chat group notice edit --group <openConversationId> --notice-id <dataId> --content "更新后的公告内容"
|
||||
```
|
||||
|
||||
注意事项:
|
||||
|
||||
- `notice edit` 会整体替换原公告正文,必须传完整的新内容。
|
||||
- `notice list --scheduled` 查询尚未到发布时间的定时公告;默认查询已发布公告。
|
||||
- `hasMore=true` 时,用返回的 `nextPageCursor` 继续翻页。
|
||||
- `notice get` 返回正文摘要、置顶状态、发布者、已读人数/应收人数、点赞/评论数、是否可编辑、是否已读、是否定时公告等信息。
|
||||
|
||||
### 群列表与入群审批
|
||||
|
||||
| 命令 | 用途 | 示例与要点 |
|
||||
|------|------|------------|
|
||||
| `group list-my-groups` | 拉取我创建/管理的群 | 可选 `--role OWNER/ADMIN`、`--limit`、`--exclude-muted` |
|
||||
| `group list-all` | 分页拉取我加入的所有群 | `--limit` 默认 100,最大 200;翻页用 `nextCursor` |
|
||||
| `group list-join-validations` | 拉取入群验证记录 | 包括自己被拒绝的记录以及作为审批者的记录 |
|
||||
| `group audit-join-validation` | 审批入群验证 | `--group` `--record-id` `--applicant` `--inviter` `--status` |
|
||||
|
||||
审批动作 `--status`:`AuditApprove`、`AuditDelete`、`AuditIgnore`、`AuditRefuse`、`AuditBlock`。
|
||||
|
||||
```bash
|
||||
dws chat group list-join-validations --limit 20
|
||||
dws chat group audit-join-validation --group <openConversationId> --record-id 123456 --applicant <openDingTalkId> --inviter <openDingTalkId> --status AuditApprove
|
||||
```
|
||||
|
||||
### 群身份
|
||||
|
||||
`chat group-role` 管理群内自定义身份标签。
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `group-role list` | 查看群身份列表 | `--group` |
|
||||
| `group-role add` | 新增群身份 | `--group` `--name` |
|
||||
| `group-role update` | 修改群身份名称 | `--group` `--role-id` `--name` |
|
||||
| `group-role remove` | 删除群身份 | `--group` `--role-id` |
|
||||
| `group-role set-user` | 覆盖用户全部群身份,空 `--role-ids` 表示清除 | `--group` `--user` `--role-ids` |
|
||||
| `group-role remove-user` | 移除用户指定群身份 | `--group` `--user` `--role-ids` |
|
||||
| `group-role query-user` | 查询用户当前群身份 | `--group` `--user` |
|
||||
|
||||
`openRoleId` 来自 `group-role list` 返回。
|
||||
|
||||
## 常见工作流
|
||||
|
||||
### 搜索群并发消息
|
||||
|
||||
```bash
|
||||
dws chat search --query "项目冲刺" --format json
|
||||
dws chat message send --group <openConversationId> --text "请大家看一下最新进展" --format json
|
||||
```
|
||||
|
||||
### 建群并拉人
|
||||
|
||||
```bash
|
||||
dws aisearch person --keyword "张三" --dimension name --format json
|
||||
dws chat group create --name "Q1 项目冲刺群" --users userId1,userId2 --format json
|
||||
dws chat group members add --id <openConversationId> --users userId3,userId4 --format json
|
||||
```
|
||||
|
||||
### 建群并指定群主
|
||||
|
||||
```bash
|
||||
dws aisearch person --keyword "群主姓名" --dimension name --format json
|
||||
dws chat group create --name "项目群" --users userId1,userId2 --owner <ownerOpenDingTalkId> --format json
|
||||
```
|
||||
|
||||
### 分享群邀请并发布公告
|
||||
|
||||
```bash
|
||||
dws chat group share-invite --source <sourceOpenConversationId> --target <targetOpenConversationId> --format json
|
||||
dws chat group notice create --group <openConversationId> --content "# 项目公告\n\n请大家关注最新安排" --send-ding --format json
|
||||
```
|
||||
|
||||
### 设置管理员并禁言成员
|
||||
|
||||
```bash
|
||||
dws chat group set-admin --group <openConversationId> --users userId1,userId2 --format json
|
||||
dws chat group-mute-member --group <openConversationId> --users userId3 --mute-time 3600000 --format json
|
||||
```
|
||||
|
||||
## 常见错误与回退
|
||||
|
||||
- 只有数字群号:先 `group get-by-group-id`,不要直接当 `--group`。
|
||||
- 找不到群:先扩大 `chat search --query`,不要臆测 openConversationId。
|
||||
- 入群审批缺参数:从 `group list-join-validations` 提取 `record-id`、`applicant`、`inviter`。
|
||||
- 机器人进群失败:确认当前用户有群管理权限。
|
||||
- 分享群邀请目标不明确:`--target` 和 `--receiver` 只能二选一,先确认是发到群/会话还是发给个人。
|
||||
- 修改公告前没有完整新正文:先向用户确认完整公告内容,不要只传增量片段。
|
||||
@@ -0,0 +1,269 @@
|
||||
# chat-message:消息、文件、搜索与卡片
|
||||
|
||||
> 返回入口:[chat.md](../chat.md)
|
||||
|
||||
## 适用场景
|
||||
|
||||
用于当前用户发消息、拉消息、搜索消息、撤回、已读状态、文件/图片/音频/视频/位置/名片发送、话题回复、转发、Pin/Top、表情回应、文本翻译和流式卡片。
|
||||
|
||||
## 必读约束
|
||||
|
||||
- 发消息前必须核对接收对象、消息内容、@ 对象、附件路径和消息类型;不明确时先问用户。
|
||||
- `--group`、`--user`、`--open-dingtalk-id` 通常互斥,群聊用 `--group`,单聊用 `--user` 或 `--open-dingtalk-id`。
|
||||
- 发送本地文件、音频、视频统一用 `chat message send --msg-type file|audio|video --file-path <path>`;`audio` / `video` 底层按 `file` 链路发送;旧图片链路 `--msg-type image --media-id` 仅在已有 mediaId 时使用。
|
||||
- 发送位置消息前必须确认纬度、经度、地址名称;地图缩略图需先通过旧媒体上传链路拿到 mediaId。
|
||||
- 分享联系人名片前必须确认联系人 `openDingTalkId`,不要把 userId 直接当 `--contact-id`。
|
||||
- 消息内容按 Markdown 渲染,换行必须是真实换行符;需要换行效果时用空行、行尾两个空格或 `<br>`。
|
||||
- 建议发送时带 `--uuid`,失败重试复用同一个值。
|
||||
|
||||
## 命令明细
|
||||
|
||||
### 发送消息
|
||||
|
||||
#### `dws chat message send`
|
||||
|
||||
以当前用户身份发送群聊或单聊消息。
|
||||
|
||||
```bash
|
||||
# 文本/Markdown
|
||||
dws chat message send --group <openConversationId> --text "hello"
|
||||
dws chat message send --user <userId> --text "请查收"
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --text "请查收"
|
||||
dws chat message send --group <openConversationId> --title "周报提醒" --text "请大家本周五前提交周报" --uuid <uuid>
|
||||
|
||||
# @ 群成员
|
||||
dws chat message send --group <openConversationId> --at-all "<@all> 请大家注意"
|
||||
dws chat message send --group <openConversationId> --at-open-dingtalk-ids odt1,odt2 "<@odt1> <@odt2> 请查收"
|
||||
|
||||
# 图片/文件/音频/视频,一条命令直发
|
||||
dws chat message send --group <openConversationId> --msg-type file --file-path ./screenshot.png
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --msg-type file --file-path ./report.pdf
|
||||
dws chat message send --group <openConversationId> --msg-type audio --file-path ./voice.mp3
|
||||
dws chat message send --group <openConversationId> --msg-type video --file-path ./demo.mp4
|
||||
|
||||
# 位置/联系人名片
|
||||
dws chat message send --group <openConversationId> --msg-type location --latitude <纬度> --longitude <经度> --location-name <地址名称> --map-thumbnail-url "@mediaId"
|
||||
dws chat message send --group <openConversationId> --msg-type profile --contact-id <openDingTalkId>
|
||||
```
|
||||
|
||||
关键 flags:
|
||||
|
||||
| Flag | 说明 |
|
||||
|------|------|
|
||||
| `--group` | 群聊 openConversationId;别名 `--id` / `--chat` / `--conversation-id` |
|
||||
| `--user` | 单聊接收人 userId |
|
||||
| `--open-dingtalk-id` | 单聊接收人 openDingTalkId |
|
||||
| `--text` | 消息内容,推荐使用;也支持位置参数 |
|
||||
| `--title` | 消息标题,未传时使用安全标题 |
|
||||
| `--at-all` | 群聊 @所有人,正文需含 `<@all>` |
|
||||
| `--at-open-dingtalk-ids` | 群聊 @指定 openDingTalkId,正文需含 `<@id>` |
|
||||
| `--msg-type` | `file` / `audio` / `video` / `image` / `location` / `profile`;本地音视频用 `audio` / `video`,底层按 `file` 发送 |
|
||||
| `--file-path` | 本地文件路径,`msg-type=file/audio/video` 时自动上传并发送 |
|
||||
| `--media-id` | 旧图片链路 mediaId |
|
||||
| `--latitude` / `--longitude` / `--location-name` | 位置消息参数 |
|
||||
| `--map-thumbnail-url` | 位置消息缩略图 mediaId,形如 `@mediaId` |
|
||||
| `--contact-id` | 联系人名片 openDingTalkId |
|
||||
| `--uuid` | 幂等 UUID,24h 内相同值不重复投递 |
|
||||
|
||||
话题回复:`chat message list` 返回的 `openConvThreadId` 可直接作为 `--group` 值发送到话题内,禁止自行拼接。
|
||||
|
||||
### 拉取消息
|
||||
|
||||
| 命令 | 用途 | 示例与要点 |
|
||||
|------|------|------------|
|
||||
| `message list` | 拉取指定群聊或单聊消息 | `dws chat message list --group <cid> --time "2025-03-01 00:00:00" --direction older`;目标三选一,`--direction newer/older` 优先于旧 `--forward` |
|
||||
| `message list-all` | 时间范围内全部会话消息 | `dws chat message list-all --start <ISO> --end <ISO> --limit 100 --cursor 0`;四个参数每次请求都传,翻页用 `nextCursor` |
|
||||
| `message list-by-sender` | 查指定发送者消息 | `--sender-user-id` 与 `--sender-open-dingtalk-id` 二选一,跨单聊+群聊 |
|
||||
| `message list-mentions` | 查 @ 我的消息 | 可传 `--group` 限定群,不传查全部 |
|
||||
| `message list-focused` | 查特别关注人消息 | 零参数可用,可加 `--limit` / `--cursor` |
|
||||
| `message list-unread-conversations` | 未读会话列表 | 可选 `--count` |
|
||||
| `message list-topic-replies` | 拉取话题回复 | `--group <openConversationId> --topic-id <openConvThreadId>` |
|
||||
| `message list-by-ids` | 按消息 ID 批量查询 | `--msg-ids msgId1,msgId2`,最多 50 条 |
|
||||
|
||||
`message list` 注意事项:
|
||||
|
||||
- `--group`、`--user`、`--open-dingtalk-id` 互斥且必须指定一个。
|
||||
- `--time` 格式为 `yyyy-MM-dd HH:mm:ss`。
|
||||
- `hasMore=true` 时,用结果中的边界 `createTime` 作为下次 `--time`。
|
||||
- 返回 `openConvThreadId` 表示话题消息,完整内容需再拉 `list-topic-replies`。
|
||||
|
||||
### 搜索消息
|
||||
|
||||
优先使用 `message search-advanced`,它是 `message search` 的严格超集。
|
||||
|
||||
```bash
|
||||
dws chat message search-advanced --query "周报" --start "2026-04-01T00:00:00+08:00" --end "2026-04-15T00:00:00+08:00"
|
||||
dws chat message search-advanced --user <userId> --start <ISO> --end <ISO>
|
||||
dws chat message search-advanced --at-me --start <ISO> --end <ISO>
|
||||
dws chat message search-advanced --conversation-ids <cid1>,<cid2> --query "合同" --limit 50 --cursor 0
|
||||
dws chat message search-advanced --message-type file --search-conv-type group_chat --query "附件"
|
||||
dws chat message search-advanced --only-robot-messages --query "通知"
|
||||
```
|
||||
|
||||
| 参数 | 说明 |
|
||||
|------|------|
|
||||
| `--query` | 搜索关键词,可选 |
|
||||
| `--user` / `--users` | 发送者 userId |
|
||||
| `--sender-ids` | 发送者 openDingTalkId |
|
||||
| `--at-me` / `--at-ids` | @ 我 / @ 指定 openDingTalkId |
|
||||
| `--conversation-ids` | 多个群聊或单聊 openConversationId;别名 `--groups` |
|
||||
| `--message-type` | 按消息类型过滤,例如 `file` |
|
||||
| `--search-conv-type` | 按会话类型过滤,例如 `group_chat` |
|
||||
| `--only-robot-messages` | 只搜索机器人消息 |
|
||||
| `--start` / `--end` | ISO-8601 时间范围 |
|
||||
| `--cursor` / `--limit` | 分页,翻页用 `nextCursor` |
|
||||
|
||||
仅简单关键词搜索时可用:
|
||||
|
||||
```bash
|
||||
dws chat message search --query "changefree" --start <ISO> --end <ISO> --limit 50 --cursor 0
|
||||
dws chat message search --query "codereview" --group <openConversationId> --start <ISO> --end <ISO>
|
||||
```
|
||||
|
||||
### 消息状态与撤回
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `message query-send-status` | 查询当前用户发消息任务状态 | `--open-task-id`,来自 `message send` 返回 |
|
||||
| `message recall` | 撤回当前用户消息;群主/管理员可撤回群内他人消息 | `--conversation-id` `--msg-id` |
|
||||
| `message edit` | 编辑已发送消息内容 | `--conversation-id` `--msg-id`,并在 `--text` / `--content` 中二选一;可选 `--title` `--at-all` `--at-open-dingtalk-ids` |
|
||||
| `message read-status` | 查消息已读/未读状态 | `--group` `--message-id`;可选目标用户 |
|
||||
|
||||
`recall` 与 `recall-by-bot` 不同:前者通过 IM 接口撤回用户消息,需要 `openConversationId + openMessageId`,支持撤回自己发出的消息,也支持群主/管理员撤回群内他人消息;后者撤回机器人消息,需要 `robot-code + processQueryKey`。
|
||||
|
||||
编辑消息使用 `message edit`。推荐传 `--text`,CLI 会生成 markdown content JSON:`{"title":"标题","text":"正文"}`;可选 `--title`,不传时会从正文自动生成标题。高级场景可直接传 `--content`,此时必须是完整 markdown content JSON,且不能同时传 `--text`。
|
||||
|
||||
@ 规则:`--at-all` 会传 `atAll=true`,正文应包含 `<@all>`,未包含时 CLI 会自动补到开头;`--at-open-dingtalk-ids` 会传 `atOpenDingTalkIds`,正文需包含对应 `<@openDingTalkId>` 占位符,裸 `@openDingTalkId` 会自动补成尖括号格式。
|
||||
|
||||
```bash
|
||||
dws chat message edit --conversation-id <openConversationId> --msg-id <openMessageId> --text "更新后的内容"
|
||||
dws chat message edit --group <openConversationId> --msg-id <openMessageId> --title "标题" --text "更新后的内容"
|
||||
dws chat message edit --group <openConversationId> --msg-id <openMessageId> --text "<@all> 请查看" --at-all
|
||||
dws chat message edit --group <openConversationId> --msg-id <openMessageId> --text "<@openDingTalkId1> 请查看" --at-open-dingtalk-ids <openDingTalkId1>
|
||||
dws chat message edit --group <openConversationId> --msg-id <openMessageId> --content '{"title":"标题","text":"更新后的内容"}'
|
||||
```
|
||||
|
||||
### 回复与转发
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `message reply` | 引用回复,单聊/群聊均可 | `--conversation-id` `--ref-msg-id` `--ref-sender` `--text` |
|
||||
| `message forward` | 转发单条消息,源/目标均支持单聊/群聊 | `--src-conversation-id` `--msg-id` `--dest-conversation-id` |
|
||||
| `message combine-forward` | 多条消息合并为一条转发 | `--src-conversation-id` `--msg-ids` `--dest-conversation-id`,可选 `--uuid` |
|
||||
| `message forward-topic` | 转发话题消息 | `--src-msg-id` `--src-conversation-id` `--src-thread-id` `--dest-conversation-id` |
|
||||
|
||||
### 话题与卡片
|
||||
|
||||
话题完整读取流程:
|
||||
|
||||
1. `dws chat message list --group <openConversationId> --time ...` 获取话题主消息。
|
||||
2. 如果返回 `openConvThreadId`,执行 `dws chat message list-topic-replies --group <openConversationId> --topic-id <openConvThreadId>`。
|
||||
|
||||
流式卡片必须 `send-card` 与 `update-card` 搭配:
|
||||
|
||||
```bash
|
||||
dws chat message send-card --group <openConversationId>
|
||||
dws chat message send-card --receiver <openDingTalkId>
|
||||
dws chat message update-card --biz-id <bizId> --content "更新的卡片内容" --flow-status 2
|
||||
dws chat message update-card --biz-id <bizId> --content "最终内容" --flow-status 3
|
||||
```
|
||||
|
||||
`flow-status`:1=处理中,2=输入中,3=完成,4=执行中,5=错误。最后一次必须设为 3,否则卡片会停留在“生成中”。
|
||||
|
||||
### Pin / Top / Favorite
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `message set-pin-msg` / `unset-pin-msg` | 钉住/取消钉住消息 | `--open-conversation-id` `--msg-id` |
|
||||
| `message list-pin-msg` | 拉取钉住消息列表 | `--open-conversation-id`,可选 `--cursor` `--size` |
|
||||
| `message set-top-msg` / `unset-top-msg` | 置顶/取消置顶会话内某条消息 | `--open-conversation-id` `--msg-id` |
|
||||
| `message add-favorite` | 收藏消息 | `--open-message-id` `--open-conversation-id` |
|
||||
| `message remove-favorite` | 取消收藏消息 | `--open-message-id` `--open-conversation-id` |
|
||||
| `message list-favorites` | 查询收藏消息列表 | 可选 `--cursor` `--size` |
|
||||
|
||||
消息置顶 `set-top-msg` 与会话置顶 `chat set-top` 不同:前者置顶会话内消息,后者置顶整个会话。
|
||||
|
||||
### 表情回应
|
||||
|
||||
优先查 [chat-emoji-list.md](../chat-emoji-list.md) 中的默认表情名称。
|
||||
|
||||
| 命令 | 场景 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `message add-emoji` / `remove-emoji` | 默认表情命中时使用 | `--conversation-id` `--msg-id` `--emoji` |
|
||||
| `message create-text-emotion` | 默认表情没有合适项时先创建 | `--emotion-name` `--text`,可选 `--background-id` |
|
||||
| `message add-text-emotion` / `remove-text-emotion` | 添加/移除文字表情 | `--conversation-id` `--msg-id` `--emotion-id` `--emotion-name` `--text` `--background-id` |
|
||||
| `message update-text-emotion` | 用新的文字表情替换消息上的原回应 | `--conversation-id` `--msg-id` `--old-emotion-id` `--emotion-id` `--emotion-name` `--text` `--background-id` |
|
||||
| `message list-emotion-replies` | 批量查询消息的表情回复和文字回复 | `--msg-ids` |
|
||||
|
||||
```bash
|
||||
dws chat message list-emotion-replies --msg-ids msgId1,msgId2,msgId3
|
||||
```
|
||||
|
||||
消息 ID 可通过 `dws chat message list` 获取;该命令用于一次性查看多条消息上的 emoji 回应和文字表情回应。
|
||||
|
||||
### 文本工具
|
||||
|
||||
#### `dws chat text translate`
|
||||
|
||||
将指定文本翻译成目标语言。用户只说“翻译这段文字”时使用;不要误走 `message send`。
|
||||
|
||||
```bash
|
||||
dws chat text translate --query "你好世界" --to en_US
|
||||
dws chat text translate --query "Hello World" --to zh_CN
|
||||
dws chat text translate --query "Bonjour" --to ja_JP
|
||||
```
|
||||
|
||||
关键 flags:
|
||||
|
||||
| Flag | 说明 |
|
||||
|------|------|
|
||||
| `--query` | 待翻译文本,必填 |
|
||||
| `--to` | 目标语言代码,必填,默认 `en_US` |
|
||||
|
||||
### 文件与媒体
|
||||
|
||||
#### `dws chat message download-media`
|
||||
|
||||
```bash
|
||||
dws chat message download-media --type mediaId --resource-id <mediaId> --message-id <openMessageId> --open-conversation-id <openConversationId> --output ./downloads/
|
||||
```
|
||||
|
||||
`resource-id` 来自消息内容中的 mediaId,`message-id` 来自 `openMessageId`,会话 ID 来自 `chat search` 或 `conversation-info`。
|
||||
|
||||
## 常见工作流
|
||||
|
||||
### 群聊发文字与文件
|
||||
|
||||
```bash
|
||||
dws chat search --query "项目冲刺" --format json
|
||||
dws chat message send --group <openConversationId> --text "请大家本周五前提交周报" --uuid <uuid> --format json
|
||||
dws chat message send --group <openConversationId> --msg-type file --file-path ./report.pdf --format json
|
||||
dws chat message send --group <openConversationId> --msg-type audio --file-path ./voice.mp3 --format json
|
||||
dws chat message send --group <openConversationId> --msg-type video --file-path ./demo.mp4 --format json
|
||||
dws chat message send --group <openConversationId> --msg-type location --latitude <纬度> --longitude <经度> --location-name <地址名称> --map-thumbnail-url "@mediaId" --format json
|
||||
dws chat message send --group <openConversationId> --msg-type profile --contact-id <openDingTalkId> --format json
|
||||
```
|
||||
|
||||
### 查消息并撤回
|
||||
|
||||
```bash
|
||||
dws chat message list --group <openConversationId> --time "2026-03-10 00:00:00" --direction older --format json
|
||||
dws chat message recall --conversation-id <openConversationId> --msg-id <openMessageId> --format json
|
||||
```
|
||||
|
||||
### 多维度搜索
|
||||
|
||||
```bash
|
||||
dws chat message search-advanced --query "合同" --conversation-ids <cid1>,<cid2> --start "2026-04-01T00:00:00+08:00" --end "2026-04-15T00:00:00+08:00" --limit 50 --cursor 0 --format json
|
||||
dws chat message search-advanced --message-type file --search-conv-type group_chat --query "附件" --format json
|
||||
```
|
||||
|
||||
## 常见错误与回退
|
||||
|
||||
- 发送目标不唯一:先确认群/人;群用 `chat search`,单聊用 `aisearch person` + `conversation-info`。
|
||||
- `unknown flag`:立即执行对应命令 `--help`,不要猜参数。
|
||||
- 文件/音视频发送失败:确认本地路径可读;新链路使用 `--msg-type file|audio|video --file-path`。
|
||||
- 位置消息参数不完整:先确认经纬度、地址名称和缩略图 mediaId。
|
||||
- 名片发送失败:确认 `--contact-id` 是 openDingTalkId,不是 userId。
|
||||
- 话题回复缺失:检查是否只拉了主消息,需继续用 `list-topic-replies`。
|
||||
- `search-advanced` 无条件:至少提供 query、sender、@、conversation、时间等任一有效过滤条件。
|
||||
@@ -0,0 +1,179 @@
|
||||
# chat-workflows:高频流程与上下文传递
|
||||
|
||||
> 返回入口:[chat.md](../chat.md)
|
||||
|
||||
## 适用场景
|
||||
|
||||
用于复合任务编排、字段传递、openDingTalkId 获取、自动化脚本和跨产品衔接。
|
||||
|
||||
## 必读约束
|
||||
|
||||
- 已知上游字段时直接使用,不要重复搜索。
|
||||
- 群聊 `openConversationId` 通常来自 `chat search`;单聊 `openConversationId` 来自 `conversation-info`。
|
||||
- `userId` 与 `openDingTalkId` 不是同一种标识,按命令要求传递。
|
||||
|
||||
## openDingTalkId 获取方式
|
||||
|
||||
| 场景 | 命令 |
|
||||
|------|------|
|
||||
| 搜人员 openDingTalkId | `dws aisearch person --keyword "姓名" --dimension name --format json` |
|
||||
| 给机器人发单聊 | `dws chat bot find --query "机器人名" --format json`,不要用 `bot search` |
|
||||
| 已有 userId 需要单聊会话 ID | `dws chat conversation-info --user <userId> --format json` |
|
||||
| 已有 openDingTalkId 需要单聊会话 ID | `dws chat conversation-info --open-dingtalk-id <openDingTalkId> --format json` |
|
||||
|
||||
## 高频工作流
|
||||
|
||||
### 群聊消息
|
||||
|
||||
```bash
|
||||
# 1. 搜索群,提取 openConversationId
|
||||
dws chat search --query "项目冲刺" --format json
|
||||
|
||||
# 2. 拉取群消息
|
||||
dws chat message list --group <openConversationId> --time "2025-03-01 00:00:00" --direction older --format json
|
||||
|
||||
# 3. 拉未读会话
|
||||
dws chat message list-unread-conversations --count 20 --format json
|
||||
```
|
||||
|
||||
### 发送消息
|
||||
|
||||
```bash
|
||||
# 个人身份发群消息
|
||||
dws chat message send --group <openConversationId> --title "周报提醒" --text "请大家本周五前提交周报" --uuid <uuid> --format json
|
||||
|
||||
# 个人身份发单聊
|
||||
dws chat message send --user <userId> --text "你好" --uuid <uuid> --format json
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --text "你好" --uuid <uuid> --format json
|
||||
|
||||
# 发送图片/文件/音频/视频
|
||||
dws chat message send --group <openConversationId> --msg-type file --file-path ./screenshot.png --format json
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --msg-type file --file-path ./report.pdf --format json
|
||||
dws chat message send --group <openConversationId> --msg-type audio --file-path ./voice.mp3 --format json
|
||||
dws chat message send --group <openConversationId> --msg-type video --file-path ./demo.mp4 --format json
|
||||
|
||||
# 文件后补文字说明
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --msg-type file --file-path ./screenshot.png --format json
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --text "这是本周数据汇总" --format json
|
||||
```
|
||||
|
||||
### 机器人消息
|
||||
|
||||
```bash
|
||||
# 查我的机器人,提取 robotCode
|
||||
dws chat bot search --name "日报" --format json
|
||||
|
||||
# 机器人发群消息,提取 processQueryKey;Markdown 稳定换行用 \n\n,不要只用 \n
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> --title "日报" --text "## 今日完成\n\n- 事项 A\n\n- 事项 B" --format json
|
||||
|
||||
# 撤回机器人消息
|
||||
dws chat message recall-by-bot --robot-code <robot-code> --group <openConversationId> --keys <processQueryKey> --format json
|
||||
|
||||
# 机器人不在群内时先邀请
|
||||
dws chat group members add-bot --id <openConversationId> --robot-code <robot-code> --format json
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> --title "通知" --text "内容" --format json
|
||||
|
||||
# 给机器人发单聊,必须用 find 拿 openDingTalkId
|
||||
dws chat bot find --query "玉澜" --format json
|
||||
dws chat message send --open-dingtalk-id <openDingTalkId> --text "你好" --format json
|
||||
```
|
||||
|
||||
### 机器人 @ 指定人
|
||||
|
||||
```bash
|
||||
dws aisearch person --keyword "张三" --dimension name --format json
|
||||
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> \
|
||||
--at-user-ids userId1,userId2 \
|
||||
--title "提醒" --text "@userId1 @userId2 请查收本周报告" --format json
|
||||
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> \
|
||||
--at-open-dingtalk-ids openDingtalkId1,openDingtalkId2 \
|
||||
--title "提醒" --text "@openDingtalkId1 @openDingtalkId2 请查收本周报告" --format json
|
||||
|
||||
dws chat message send-by-bot --robot-code <robot-code> --group <openConversationId> \
|
||||
--at-all --title "通知" --text "请所有人注意" --format json
|
||||
```
|
||||
|
||||
### Webhook 告警
|
||||
|
||||
```bash
|
||||
dws chat message send-by-webhook --token <webhook-token> --title "告警" --text "CPU 超 90% @10" --at-all --format json
|
||||
```
|
||||
|
||||
### 话题完整读取与回复
|
||||
|
||||
```bash
|
||||
dws chat message list --group <openConversationId> --time "2026-03-10 00:00:00" --direction older --format json
|
||||
dws chat message list-topic-replies --group <openConversationId> --topic-id <openConvThreadId> --format json
|
||||
dws chat message send --group <openConvThreadId> --text "回复话题内容" --format json
|
||||
```
|
||||
|
||||
### 群公告与邀请分享
|
||||
|
||||
```bash
|
||||
# 分享 A 群邀请链接到 B 群
|
||||
dws chat group share-invite --source <sourceOpenConversationId> --target <targetOpenConversationId> --format json
|
||||
|
||||
# 发布群公告,Markdown 段落换行用空行
|
||||
dws chat group notice create --group <openConversationId> --content "# 重要通知\n\n请大家查收" --send-ding --format json
|
||||
|
||||
# 修改公告前先列表查询 notice-id/dataId
|
||||
dws chat group notice list --group <openConversationId> --format json
|
||||
dws chat group notice edit --group <openConversationId> --notice-id <dataId> --content "完整的新公告内容" --format json
|
||||
```
|
||||
|
||||
### 智能分组与文本翻译
|
||||
|
||||
```bash
|
||||
dws aisearch person --keyword "张三" --dimension name --format json
|
||||
dws chat category create-smart --name "重点群" --keywords "重点,项目" --members openDingTalkId1 --format json
|
||||
dws chat text translate --query "你好世界" --to en_US --format json
|
||||
```
|
||||
|
||||
## 上下文传递表
|
||||
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `chat search` | `openConversationId` | `message send/list`、`group members`、`set-top`、`group-mute` |
|
||||
| `chat group create` | `openConversationId` | 新群后续发消息、成员管理、群设置 |
|
||||
| `chat group get-by-group-id` | `openConversationId` | 将数字群号转为可用会话 ID |
|
||||
| `chat conversation-info` | `openConversationId` | 单聊消息搜索、转发、会话状态操作 |
|
||||
| `aisearch person` | `userId` | `message send --user`、`send-by-bot --users`、`--at-user-ids`、`list-by-sender --sender-user-id` |
|
||||
| `aisearch person` | `openDingTalkId` | `message send --open-dingtalk-id`、`--at-open-dingtalk-ids`、`send-by-bot --open-dingtalk-ids` |
|
||||
| `aisearch person` | `userId` | 可替代人员搜索结果,继续用于 userId 参数 |
|
||||
| `chat bot search` | `robotCode` | `send-by-bot`、`recall-by-bot` |
|
||||
| `chat bot find` | `openDingTalkId` | 给机器人发单聊 |
|
||||
| `chat group bots` | `openBotId` | `group members remove-bot --bot-id` |
|
||||
| `chat message send-by-bot` | `processQueryKey` | `recall-by-bot --keys` |
|
||||
| `chat message send` | `openTaskId` | `query-send-status --open-task-id` |
|
||||
| `chat message list` | `openMessageId` | `message recall --msg-id`、`reply --ref-msg-id`、`forward --msg-id` |
|
||||
| `chat message list` | `openMsgId` | `read-status --message-id`、表情回应命令 |
|
||||
| `chat message list` | `openConvThreadId` | `list-topic-replies --topic-id`、话题回复 `message send --group` |
|
||||
| `chat message search` | `nextCursor` | 下次 `message search --cursor` |
|
||||
| `chat message search-advanced` | `nextCursor` | 下次 `search-advanced --cursor` |
|
||||
| `chat message list-all` | `nextCursor` | 下次 `list-all --cursor` |
|
||||
| `chat search-common` | `openConversationId` | 后续消息发送/拉取 |
|
||||
| `chat group notice list/get/create` | `dataId` / `notice-id` | `group notice get/edit --notice-id` |
|
||||
| `chat group-role list` | `openRoleId` | `group-role update/remove/set-user/remove-user --role-id` |
|
||||
| `chat message create-text-emotion` | `emotionId` | `add-text-emotion --emotion-id` |
|
||||
| `chat message list/search-advanced` | `openMessageId` / `openMsgId` | `list-emotion-replies --msg-ids` |
|
||||
| `chat category list` | `categoryId` | `category list-conversations/add-conv/remove-conv --category-id(s)` |
|
||||
| `chat category create-smart` | 智能分组 ID/规则结果 | 后续查看或调整智能分组 |
|
||||
| `chat message send-card` | `bizId` | `update-card --biz-id` |
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
| 脚本 | 场景 | 用法 |
|
||||
|------|------|------|
|
||||
| [chat_export_messages.py](../../scripts/chat_export_messages.py) | 导出群聊消息到 JSON 文件 | `python chat_export_messages.py --query "项目冲刺" --time "2026-03-10 00:00:00"` |
|
||||
| [chat_history_with_user.py](../../scripts/chat_history_with_user.py) | 查询与某人的单聊聊天记录 | `python chat_history_with_user.py --name "张三" --time "2026-03-10 00:00:00"` |
|
||||
| [extract_media_id.py](../../scripts/extract_media_id.py) | 旧链路:从 dt_media_upload URL 提取 mediaId | 新场景不要用,文件/音视频直接 `--msg-type file|audio|video --file-path` |
|
||||
|
||||
## 常见错误与回退
|
||||
|
||||
- 字段已由上游返回:直接传递,不要再次搜索。
|
||||
- `chat bot search` 没有 openDingTalkId:改用 `chat bot find`。
|
||||
- 群号是纯数字:先 `chat group get-by-group-id`。
|
||||
- 翻页不要自造 cursor:使用响应中的 `nextCursor` 原值。
|
||||
- 文件/音视频发送不要走旧上传链路:优先 `message send --msg-type file|audio|video --file-path`;`audio/video` 底层按 `file` 发送。
|
||||
@@ -36,17 +36,20 @@
|
||||
| "置顶会话/取消置顶" | 设置/取消会话置顶 | `chat set-top` | `chat list-top-conversations` | set-top 设置或取消置顶;list-top-conversations 查看置顶列表 |
|
||||
| "全员禁言/群禁言" | 全员禁言或解除 | `chat group-mute` | `chat group-mute-member` | group-mute 全员禁言或解除;group-mute-member 指定成员禁言 |
|
||||
| "禁言某人/指定成员禁言" | 指定成员禁言 | `chat group-mute-member` | `chat group-mute` | group-mute-member 指定成员禁言/解禁;group-mute 全员禁言 |
|
||||
| "查看群禁言配置/群里谁被禁言/禁言名单" | 查询群用户禁言配置 | `chat group get-mute-config` | `chat group-mute-member` | get-mute-config 是只读查询,返回黑白名单及时间配置;group-mute-member 会修改禁言状态 |
|
||||
| "设管理员/取消管理员" | 设置群管理员 | `chat group set-admin` | `chat group invite` | set-admin 设置或取消管理员角色;invite 是邀请入群 |
|
||||
| "退群/退出群聊/离开群" | 退出群聊 | `chat group quit` | `chat group members remove` | quit 是当前用户自己退群;members remove 是管理员踢别人 |
|
||||
| "改群头像/更新群头像" | 更新群头像 | `chat group update-icon` | `chat group rename` | update-icon 改群头像;rename 改群名称 |
|
||||
| "改群设置/群设置开关/群权限/入群许可/禁止私聊" | 更新群设置 | `chat group update-settings` | `chat group set-admin` | update-settings 改群功能开关;set-admin 是管理员角色操作 |
|
||||
| "改群设置/群设置开关/群权限/入群许可/禁止私聊" | 更新管理员级别群功能开关 | `chat group update-settings` | `chat group set-admin` | update-settings 改管理员级别的群功能开关;set-admin 是管理员角色操作 |
|
||||
| "改群昵称/设置群昵称/我在群里的名字" | 设置个人群昵称 | `chat group update-nick` | `chat group rename` | update-nick 改自己的群昵称;rename 改群名称 |
|
||||
| "群备注/给群加备注/修改群备注" | 设置群备注 | `chat group update-alias` | `chat group rename` | update-alias 设置仅自己可见的备注;rename 改群名称全员可见 |
|
||||
| "我的群置顶/取消我的群置顶/置顶这个群" | 设置当前用户群会话置顶 | `chat group user-settings set` | `chat group update-settings` | user-settings set 是个人会话置顶;update-settings 是管理员级别的群功能开关 |
|
||||
| "我的群免打扰/关闭我的群免打扰/这个群别提醒我" | 设置当前用户群免打扰 | `chat group user-settings set` | `chat group update-settings` | user-settings set 是个人通知偏好;update-settings 是管理员级别的群功能开关 |
|
||||
| "隐藏会话/隐藏群聊/隐藏对话" | 隐藏会话 | `chat hide` | `chat mute` | hide 隐藏会话不显示;mute 是免打扰但仍显示 |
|
||||
| "关闭@所有人通知/屏蔽@all/不接收@所有人" | 关闭 @所有人提醒 | `chat mute-at-all` | `chat mute` | mute-at-all 仅屏蔽 @所有人;mute 是整个会话免打扰 |
|
||||
| "关闭红包通知/屏蔽红包/不接收红包提醒" | 关闭红包提醒 | `chat mute-red-envelope` | `chat mute` | mute-red-envelope 仅屏蔽红包;mute 是整个会话免打扰 |
|
||||
| "解散群/解散群聊" | 解散群聊 | `chat group dismiss` | `chat group quit` | dismiss 是群主解散整个群(不可逆);quit 是当前用户自己退群 |
|
||||
| "新成员看历史/历史消息可见范围" | 设置新成员可见历史消息 | `chat group set-history` | `chat group update-settings` | set-history 控制新成员入群后可见历史消息范围;update-settings 是其他群功能开关 |
|
||||
| "新成员看历史/历史消息可见范围" | 设置新成员可见历史消息 | `chat group set-history` | `chat group update-settings` | set-history 控制新成员入群后可见历史消息范围;update-settings 是管理员级别的其他群功能开关 |
|
||||
| "群里有哪些机器人/查看群机器人/列出群机器人" | 查看群内机器人列表 | `chat group bots` | `chat group members` | bots 只列机器人;members 列普通群成员 |
|
||||
| "从群里移除机器人/踢机器人" | 移除群内机器人 | `chat group members remove-bot` | `chat group members add-bot` | remove-bot 通过 openBotId 移除;add-bot 通过 robotCode 添加 |
|
||||
| "批量查群成员详情/按ID查群成员/查看指定成员信息" | 批量查询群成员详情 | `chat group members list-by-ids` | `chat group members` | list-by-ids 根据 openDingTalkId 列表查询指定成员详情;members 分页查询全部成员列表 |
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
## #1 消息沟通
|
||||
|
||||
所有消息沟通相关的命令详情、参数说明、意图路由和复合工作流,请查阅 [chat.md](./chat-commands.md)。
|
||||
所有消息沟通相关的命令详情、参数说明、意图路由和复合工作流,请查阅 [chat.md](./chat.md)。
|
||||
|
||||
@@ -16,11 +16,20 @@
|
||||
|
||||
import sys
|
||||
import json
|
||||
import datetime
|
||||
import subprocess
|
||||
import argparse
|
||||
from typing import List, Any, Optional
|
||||
|
||||
|
||||
def timestamp_to_datetime(ts_ms: int) -> str:
|
||||
"""将毫秒时间戳转换为 yyyy-MM-dd HH:mm:ss 格式"""
|
||||
dt = datetime.datetime.fromtimestamp(
|
||||
ts_ms / 1000, tz=datetime.timezone(datetime.timedelta(hours=8))
|
||||
)
|
||||
return dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
|
||||
def run_dws(
|
||||
args: List[str], dry_run: bool = False,
|
||||
) -> Optional[Any]:
|
||||
@@ -130,7 +139,7 @@ def main():
|
||||
'--format', 'json',
|
||||
]
|
||||
if args.no_forward:
|
||||
cmd_args.extend(['--direction', 'older'])
|
||||
cmd_args.append('--forward=false')
|
||||
page_limit = min(int(remaining), 200) if args.limit > 0 else 0
|
||||
if page_limit > 0:
|
||||
cmd_args.extend(['--limit', str(page_limit)])
|
||||
@@ -150,20 +159,25 @@ def main():
|
||||
if isinstance(data, list):
|
||||
page_msgs = data
|
||||
has_more = False
|
||||
next_cursor = None
|
||||
elif isinstance(data, dict):
|
||||
inner = data.get('result', data)
|
||||
if isinstance(inner, dict):
|
||||
page_msgs = inner.get('messages', [])
|
||||
has_more = inner.get('hasMore', False)
|
||||
next_cursor = inner.get('nextCursor')
|
||||
elif isinstance(inner, list):
|
||||
page_msgs = inner
|
||||
has_more = False
|
||||
next_cursor = None
|
||||
else:
|
||||
page_msgs = []
|
||||
has_more = False
|
||||
next_cursor = None
|
||||
else:
|
||||
page_msgs = []
|
||||
has_more = False
|
||||
next_cursor = None
|
||||
|
||||
if not page_msgs:
|
||||
break
|
||||
@@ -175,16 +189,19 @@ def main():
|
||||
if not has_more:
|
||||
break
|
||||
|
||||
# message list 没有 cursor flag;按 CLI 契约用边界 createTime 翻页。
|
||||
last_msg = page_msgs[-1]
|
||||
boundary_time = (
|
||||
last_msg.get('createTime')
|
||||
or last_msg.get('createAt')
|
||||
or last_msg.get('time', '')
|
||||
)
|
||||
if not boundary_time or boundary_time == current_time:
|
||||
break
|
||||
current_time = boundary_time
|
||||
# 翻页:优先用 nextCursor(毫秒精度,转为时间字符串),降级用最后消息的 createTime
|
||||
if next_cursor:
|
||||
current_time = timestamp_to_datetime(next_cursor)
|
||||
else:
|
||||
last_msg = page_msgs[-1]
|
||||
boundary_time = (
|
||||
last_msg.get('createTime')
|
||||
or last_msg.get('createAt')
|
||||
or last_msg.get('time', '')
|
||||
)
|
||||
if not boundary_time or boundary_time == current_time:
|
||||
break
|
||||
current_time = boundary_time
|
||||
print(f" 翻页 {page}: 已累计 {len(all_messages)} 条, 继续...")
|
||||
|
||||
if not all_messages:
|
||||
@@ -197,8 +214,9 @@ def main():
|
||||
print(f" ✓ 已导出 {len(all_messages)} 条消息到 {args.output}")
|
||||
else:
|
||||
for m in all_messages:
|
||||
sender = (m.get('sender') or m.get('senderNick')
|
||||
or m.get('senderOpenDingTalkId') or '未知')
|
||||
sender = (
|
||||
m.get('sender') or m.get('senderNick') or '未知'
|
||||
)
|
||||
text = m.get('content') or m.get('text', '')
|
||||
time_str = (
|
||||
m.get('createTime') or m.get('createAt')
|
||||
|
||||
@@ -15,11 +15,20 @@
|
||||
|
||||
import sys
|
||||
import json
|
||||
import datetime
|
||||
import subprocess
|
||||
import argparse
|
||||
from typing import List, Any, Optional
|
||||
|
||||
|
||||
def timestamp_to_datetime(ts_ms: int) -> str:
|
||||
"""将毫秒时间戳转换为 yyyy-MM-dd HH:mm:ss 格式"""
|
||||
dt = datetime.datetime.fromtimestamp(
|
||||
ts_ms / 1000, tz=datetime.timezone(datetime.timedelta(hours=8))
|
||||
)
|
||||
return dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
|
||||
def run_dws(
|
||||
args: List[str], dry_run: bool = False,
|
||||
) -> Optional[Any]:
|
||||
@@ -122,7 +131,7 @@ def main():
|
||||
'--format', 'json',
|
||||
]
|
||||
if args.no_forward:
|
||||
cmd_args.extend(['--direction', 'older'])
|
||||
cmd_args.extend(['--forward', 'false'])
|
||||
page_limit = min(int(remaining), 200) if args.limit > 0 else 0
|
||||
if page_limit > 0:
|
||||
cmd_args.extend(['--limit', str(page_limit)])
|
||||
@@ -142,20 +151,25 @@ def main():
|
||||
if isinstance(data, list):
|
||||
page_msgs = data
|
||||
has_more = False
|
||||
next_cursor = None
|
||||
elif isinstance(data, dict):
|
||||
inner = data.get('result', data)
|
||||
if isinstance(inner, dict):
|
||||
page_msgs = inner.get('messages', [])
|
||||
has_more = inner.get('hasMore', False)
|
||||
next_cursor = inner.get('nextCursor')
|
||||
elif isinstance(inner, list):
|
||||
page_msgs = inner
|
||||
has_more = False
|
||||
next_cursor = None
|
||||
else:
|
||||
page_msgs = []
|
||||
has_more = False
|
||||
next_cursor = None
|
||||
else:
|
||||
page_msgs = []
|
||||
has_more = False
|
||||
next_cursor = None
|
||||
|
||||
if not page_msgs:
|
||||
break
|
||||
@@ -167,16 +181,19 @@ def main():
|
||||
if not has_more:
|
||||
break
|
||||
|
||||
# message list 没有 cursor flag;按 CLI 契约用边界 createTime 翻页。
|
||||
last_msg = page_msgs[-1]
|
||||
boundary_time = (
|
||||
last_msg.get('createTime')
|
||||
or last_msg.get('createAt')
|
||||
or last_msg.get('time', '')
|
||||
)
|
||||
if not boundary_time or boundary_time == current_time:
|
||||
break
|
||||
current_time = boundary_time
|
||||
# 翻页:优先用 nextCursor(毫秒精度,转为时间字符串),降级用最后消息的 createTime
|
||||
if next_cursor:
|
||||
current_time = timestamp_to_datetime(next_cursor)
|
||||
else:
|
||||
last_msg = page_msgs[-1]
|
||||
boundary_time = (
|
||||
last_msg.get('createTime')
|
||||
or last_msg.get('createAt')
|
||||
or last_msg.get('time', '')
|
||||
)
|
||||
if not boundary_time or boundary_time == current_time:
|
||||
break
|
||||
current_time = boundary_time
|
||||
print(f" 翻页 {page}: 已累计 {len(all_messages)} 条, 继续...")
|
||||
|
||||
if not all_messages:
|
||||
@@ -190,8 +207,9 @@ def main():
|
||||
print(f" ✓ 已导出 {len(all_messages)} 条消息到 {args.output}")
|
||||
else:
|
||||
for m in all_messages:
|
||||
sender = (m.get('sender') or m.get('senderNick')
|
||||
or m.get('senderOpenDingTalkId') or '未知')
|
||||
sender = (
|
||||
m.get('sender') or m.get('senderNick') or '未知'
|
||||
)
|
||||
text = m.get('content') or m.get('text', '')
|
||||
time_str = (
|
||||
m.get('createTime') or m.get('createAt')
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
name: dingtalk-contact
|
||||
description: 钉钉通讯录精确查询与组织管理(用户、部门、角色、花名册、离职员工、创建企业、企业账号、邀请员工)。Use when 用户说 查部门/部门成员/我的信息/按 userId 查/角色成员/离职员工/花名册/创建企业/企业账号/邀请员工。模糊找人(找同事/查上下级/谁负责)先走 dingtalk-aisearch,拿到 userId 再用本 skill 查详情。命令前缀:dws contact。
|
||||
cli_version: ">=0.2.14"
|
||||
description: 钉钉通讯录精确查询。Use when 已有 userId 后查详情、部门、职位或邮箱,按完整手机号反查用户,或查询自己、部门成员及角色。姓名模糊搜索、工号、职责、上下级走 dingtalk-aisearch,拿到 userId 后用本 skill 补详情。命令前缀:dws contact。
|
||||
metadata:
|
||||
cli_version: ">=0.2.14"
|
||||
category: product
|
||||
stability: experimental
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
@@ -12,20 +11,16 @@ metadata:
|
||||
|
||||
# 钉钉通讯录 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
> **CRITICAL — 执行任何 `dws` 操作前,MUST 先用 Read 工具完整读取 [`dws-shared`](../dws-shared/SKILL.md)。**该轻量文件包含全局执行契约、安全底线及 shared references 的按需加载导航;不要预加载其全部 references。
|
||||
|
||||
> 命令参考:[contact.md](references/contact.md);剧本:[08-directory.md](references/08-directory.md)。
|
||||
|
||||
<!-- VISIBLE_SHORTCUTS_START -->
|
||||
## Shortcuts(无专用脚本/recipe 时优先)
|
||||
|
||||
以下 shortcut 来自独立于 Runtime Schema 的公开 catalog。先按本 skill 的意图表、脚本和 recipe 路由:存在精确覆盖该场景的专用脚本/recipe 时按其执行;否则用户意图命中时,shortcut 优先于手写原子命令。用 `dws shortcut list --service contact --format json` 读取参数、约束、风险和示例,并以 `dws contact <shortcut> --help` 核对当前 Cobra flags;不要对 `+` 路径调用 `dws schema`。
|
||||
以下命令来自独立于 Runtime Schema 的公开 catalog。先运行 `dws shortcut list --service contact --format json` 读取完整契约,再用 `dws contact <shortcut> --help` 核对 flags;不要对 `+` 路径调用 `dws schema`。
|
||||
|
||||
| Shortcut | 风险 | 适用场景 |
|
||||
|---|---|---|
|
||||
@@ -51,31 +46,36 @@ metadata:
|
||||
|--------|------|
|
||||
| "查我自己的信息" | `dws contact user get-self` |
|
||||
| "按 userId 查详情" | `dws contact user get --ids <userId1>,<userId2>,...`(多个并行) |
|
||||
| "完整手机号反查用户" | `dws contact user search-mobile --mobile <手机号>` |
|
||||
| "按部门名拉成员" | `python scripts/contact_dept_members.py --query "<部门名>"` |
|
||||
| "搜部门" | `dws contact dept search --query "<关键词>"` |
|
||||
| "部门成员列表" | `dws contact dept list-members --depts <deptId>` |
|
||||
| "部门成员列表" | `dws contact dept list-members --ids <deptId>` |
|
||||
| "列出企业角色 / 有哪些角色" | `dws contact label list` |
|
||||
| "按角色名查角色ID" | `dws contact label get --names "<角色名>"` |
|
||||
| "查某角色下有哪些成员" | `dws contact label list-members --id <labelId>` |
|
||||
| "离职员工/离职名单/已离职" | `dws contact user dismission search`(可加 `--name` / `--start` + `--end` / `--depts`) |
|
||||
| "花名册/员工档案/学历/银行卡/合同" | `dws contact user profile get --staff-id <STAFF_ID>`(先 `profile fields` 查字段) |
|
||||
| "创建企业/新建企业/初始化企业" | `dws contact org create --org-name "<企业名>" --creator-username "<创建者名称>"` |
|
||||
| "创建企业账号/专属账号/企业登录账号" | `dws contact account create --org-user-name "<姓名>" --login-id "<登录号>"` |
|
||||
| "邀请员工/添加员工/新员工入职" | `dws contact user invite --org-user-name "<姓名>" --org-user-mobile "<手机号>"` |
|
||||
|
||||
## 标准 SOP(必遵流程)
|
||||
|
||||
> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 userId。每条命令必须带 `--format json`。模糊找人**首选** `dingtalk-aisearch`;contact 负责 userId→详情补全与精确查询。
|
||||
> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 userId。每条命令必须带 `--format json`。姓名模糊搜索、工号、职责与上下级走 `dingtalk-aisearch`;完整手机号精确反查走 contact;拿到 userId 后由 contact 补详情。
|
||||
|
||||
### SOP-1 搜人(search-person)
|
||||
|
||||
**触发**:找人/搜同事/谁负责/上级/下级/团队成员/按部门找人。
|
||||
**触发**:按姓名/工号/部门/职责/上下级找人,或用手机号线索做语义搜索。
|
||||
|
||||
1. **切 aisearch(必须)**:模糊找人优先走 `dingtalk-aisearch`:`dws aisearch person --keyword "<关键词>" --dimension <维度> --format json`(姓名→`name`、负责人→`duty`、部门→`department`、上下级→`supervisor`/`subordinate`)。
|
||||
1. **切 aisearch(必须)**:`dws aisearch person --keyword "<关键词>" --dimension <维度> --format json`(姓名→`name`、工号→`jobNumber`、手机号语义线索→`phone`、负责人→`duty`、部门→`department`、上下级→`supervisor`/`subordinate`)。
|
||||
2. **解析(必须)**:从结果取 `userId`、`title`;**多人同名禁止默认选第一个**,必须批量 `dws contact user get --ids <id1,id2,...> --format json` 拿部门/职位后让用户确认。
|
||||
3. **补详情(必须)**:要完整部门/职位/邮箱/主管时 `dws contact user get --ids <userId> --format json`。
|
||||
|
||||
**禁止**:在 contact 里做模糊搜人(应切 aisearch)、默认取首个候选、编造人员字段。
|
||||
**禁止**:用 `contact user search` 做姓名或工号搜索、默认取首个候选、编造人员字段。完整手机号精确反查是 `search-mobile` 的唯一搜索例外。
|
||||
|
||||
### SOP-1A 完整手机号精确反查(search-person-by-mobile)
|
||||
|
||||
**触发**:用户提供完整手机号并要求确认是谁或取得 userId。
|
||||
|
||||
1. **执行(必须)**:`dws contact user search-mobile --mobile "<完整手机号>" --format json`。
|
||||
2. **补详情(按需)**:从结果取 `userId`,需要部门、职位或邮箱时继续 `dws contact user get --ids <userId> --format json`。
|
||||
|
||||
**禁止**:把完整手机号精确反查改走姓名搜索,或在未返回 userId 时猜测人员。
|
||||
|
||||
### SOP-2 精确查人/补详情(search-user)
|
||||
|
||||
@@ -98,7 +98,7 @@ metadata:
|
||||
|
||||
**触发**:部门列表/部门成员/角色/角色成员。
|
||||
|
||||
1. **执行(必须)**:搜部门 `dws contact dept search --query "<部门名>" --format json`;某部门下子部门 `dws contact dept list-children --dept <父部门ID> --format json`;部门成员 `dws contact dept list-members --depts <部门ID> --format json`;部门详情 `dws contact dept get-info --dept <部门ID> --format json`。角色:`dws contact label list` / `dws contact label get --names "<角色名>"` / `dws contact label list-members --id <labelId>`。
|
||||
1. **执行(必须)**:搜部门 `dws contact dept search --query "<部门名>" --format json`;某部门下子部门 `dws contact dept list-children --dept <父部门ID> --format json`;部门成员 `dws contact dept list-members --ids <部门ID>[,<部门ID2>...] --format json`;部门详情 `dws contact dept get-info --dept <部门ID> --format json`。角色:`dws contact label list` / `dws contact label get --names "<角色名>"` / `dws contact label list-members --id <labelId>`。搜索企业根部门时服务端可能返回 `deptId=-1` 哨兵,后续 `list-children` / `list-members` / `get-info` 必须规范化为真实根部门 `deptId=1`。
|
||||
2. **补详情(必须)**:拿到 userId 后用 `contact user get --ids` 补部门/职位;上下级关系优先经 `dingtalk-aisearch` 的 `supervisor`/`subordinate` 维度。
|
||||
|
||||
**禁止**:使用不存在的 `contact dept list`(已废弃/歧义)、编造 deptId/labelId、跳过 aisearch 维度直接猜上下级。
|
||||
@@ -107,17 +107,17 @@ metadata:
|
||||
|
||||
- 通讯录问题必须调用 `dws contact` 或 `dws aisearch` 获取实时结果;严禁只读 `USER.md`、环境身份或静态上下文后直接回答。
|
||||
- 查自己用 `dws contact user get-self --format json`,不要把 `me/self/current` 当作 `userId` 传给 `user get`。
|
||||
- 精确找人、按工号、按手机号:先用 `dws aisearch person --keyword "<完整输入>" --dimension name/jobNumber/phone --format json` 或对应 `contact user search/search-mobile`;拿到 `userId` 后必须 `dws contact user get --ids <userId> --format json` 补部门/职位/邮箱。
|
||||
- 查询直属主管/上下级时,如果 `contact user get` 没返回明确主管字段,改用 `dws aisearch person --keyword "<完整姓名或工号>" --dimension supervisor --format json`。
|
||||
- 姓名模糊搜索、工号反查、职责或上下级搜索走 `dws aisearch person`;完整手机号精确反查走 `dws contact user search-mobile --mobile "<手机号>" --format json`。拿到 `userId` 后按需 `dws contact user get --ids <userId> --format json` 补部门/职位/邮箱。
|
||||
- 查询直属主管/上下级时,如果 `contact user get` 没返回明确主管字段,必须继续 `dws aisearch person --keyword "<完整姓名或工号>" --dimension supervisor --format json`,不要停在"可能需要进一步查询"。
|
||||
- 多个同名候选时,批量 `contact user get --ids id1,id2,... --format json` 获取部门/职位后再消歧;不要默认取第一个。
|
||||
- 用户查询企业角色、角色ID、角色成员,或“管理员/财务/HR/主管”等角色类型人员时,走 `contact label list/get/list-members`;不要用 `dept list-members` 筛字段替代。
|
||||
- "创建企业账号"必须优先匹配长模式 `account create`,不要误路由为 `org create`;三条组织管理命令都是写操作,执行前确认当前企业与目标信息。
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
- 模糊找人(姓名 / 上下级 / 谁负责 / 工号 / 手机号)→ 切到 `dingtalk-aisearch`
|
||||
- 姓名模糊搜索、上下级、谁负责、工号反查、手机号语义搜索 → `dingtalk-aisearch`
|
||||
- 完整手机号精确反查 → `dws contact user search-mobile`
|
||||
- 拿到 email 发邮件 → 切到 `dingtalk-mail`
|
||||
- 拿到 userId 发消息 → 切到 `dingtalk-chat`
|
||||
## 局部意图与 Recipe
|
||||
## 局部意图与短流程
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md);[Lite Recipe](references/lite-recipes.md)。
|
||||
- [局部意图消歧](references/intent-guide.md);[短流程](references/lite-recipes.md)。
|
||||
|
||||
@@ -6,28 +6,24 @@
|
||||
## 专用规则(#8 非 lite 步骤必守)
|
||||
|
||||
- **角色类查人优先 label**:用户说"角色为XX的员工/XX角色的员工/XX角色的人员""所有主管/主管理员/财务/HR/总经理"等角色类型人员时,**优先** `contact label list` 获取全部角色 → 匹配目标角色 → `contact label list-members --id <labelId>`;若用户明确指定了角色名称(如"角色为总经理"),则先用 `contact label get --names <XX>` 精确匹配,**若精确匹配无结果,降级 `label list` 模糊匹配**(如用户说"管理员"可匹配到"主管理员"和"子管理员")。
|
||||
- **脚本优先**:按部门拉成员**优先** `python scripts/contact_dept_members.py --query "<部门名>"`(`--dry-run` / `--format json`);失败再 `dept search` → `dept list-members --depts`。
|
||||
- **详情链路**:用户要子部门、职位、联系方式、汇报关系等,在 `user search` 之后**必须**再 `contact user get --ids <userId>`;禁止仅用 search 的浅表字段交差。
|
||||
- **脚本优先**:按部门拉成员**优先** `python scripts/contact_dept_members.py --query "<部门名>"`(`--dry-run` / `--format json`);失败再 `dept search` → `dept list-members --ids`。
|
||||
- **详情链路**:用户要子部门、职位、联系方式、汇报关系等,在 `aisearch person` 找到 `userId` 后**必须**再 `contact user get --ids <userId>`;禁止仅用搜索结果的浅表字段交差。
|
||||
- **`user get` 后部门仍空**:不得过早结束或只建议用户去 App;须在 CLI 能力内尝试 **用户点名的部门** `dept search` + `dept list-members` 等与 `userId` 交叉核对,再结构化汇总「返回中有哪些字段 / 哪些为空及可能原因」。
|
||||
- **多命中**:`user search` 或 `dept search` 多条时须列候选(姓名、title、部门线索)请用户确认,禁止默认猜一人。具体消歧流程:
|
||||
- **多命中**:`aisearch person` 或 `dept search` 返回多条时须列候选(姓名、title、部门线索)请用户确认,禁止默认猜一人。具体消歧流程:
|
||||
1. 从搜索结果中提取所有同名/多命中用户的 `userId`
|
||||
2. 调用 `contact user get --ids userId1,userId2,...` 获取每人详情(含 `depts` 部门列表、职位等)
|
||||
3. 将「姓名 + 部门 + 职位」列表展示给用户,请用户确认选择哪一位
|
||||
4. 使用用户确认的 `userId` 继续后续操作
|
||||
> **根因**:`user search` 和 `aisearch person` 均不返回部门信息,无法仅凭搜索结果区分同名用户。**必须**追加 `contact user get` 获取部门信息才能消歧。
|
||||
> **根因**:`aisearch person` 不返回完整部门信息,无法仅凭搜索结果区分同名用户。**必须**追加 `contact user get` 获取部门信息才能消歧。
|
||||
- **批量**:多个 `userId` 用 `contact user get --ids id1,id2,...`;多部门成员列表按需并行,遵守单次批量上限与 [_common/conventions.md](_common/conventions.md)。
|
||||
- **子部门枚举**:已知父部门 `deptId` 时**优先** `contact dept list-children --dept <父deptId>` 直接拿到完整子部门列表;只知道部门名时先 `contact dept search --query "<父部门名>"` 取 `deptId` 再 `list-children`;用户明示的子部门名(无需枚举)可直接 `dept search` 命中。多子部门展开见 `explore-subdepts-and-members`。
|
||||
|
||||
## 与其他场景消歧
|
||||
|
||||
> **CRITICAL — "创建企业" vs "创建企业账号"必须优先匹配长模式**:先检查 query 是否含"账号"关键词;含则必须路由 `account create`,**禁止**路由 `org create`。
|
||||
|
||||
- **创建企业账号 / 新建企业账号 / 开通企业账号 / 专属账号**(含"账号")→ `contact account create --org-user-name "<姓名>" --login-id "<登录号>" --format json`(手机号可选)
|
||||
- **创建企业 / 新建企业 / 开通企业 / 初始化企业**(不含"账号")→ `contact org create --org-name "<企业名>" --creator-username "<创建者名称>" --format json`
|
||||
- **邀请员工 / 添加员工 / 新员工入职 / 拉人进企业** → `contact user invite --org-user-name "<姓名>" --org-user-mobile "<手机号>" --depts '[{"deptId":...}]' --format json`
|
||||
- **按角色/职位类型查人(主管/管理员/财务等)** → 优先 `contact label list` + `label list-members`;label 精确命中角色维度,返回完整名单;aisearch 是语义模糊搜索不保证完整性。
|
||||
- **搜人/找人/找同事/查工号/查手机号** → 首选 **`aisearch person`**(AI 语义搜索,支持姓名/部门/职责/上下级/手机号/工号维度),见 `dingtalk-aisearch`。
|
||||
- **需要 userId 做后续操作 / 按手机号查 / 按 userId 查详情** → `contact`(精确查询)。
|
||||
- **搜人/找人/找同事/查工号/手机号语义搜索** → **`aisearch person`**(支持姓名/部门/职责/上下级/手机号线索/工号维度),见 `dingtalk-aisearch`。
|
||||
- **完整手机号精确反查** → `contact user search-mobile --mobile "<手机号>"`。
|
||||
- **已有 userId 后查详情 / 查自己 / 查部门与角色** → `contact`(精确查询)。
|
||||
- **纯查部门与子部门成员 / 验证归属 / 组织关系** → `contact`。
|
||||
- **终点是发消息、待办、日程** → 先用 `search-person` 或 `search-user` 取 `userId`,再进入 #1 / #2 / #3。
|
||||
- **联系客户 + 发邮件** → 先用 `contact` 取 `orgAuthEmail`,再走 `dingtalk-mail`。
|
||||
@@ -37,19 +33,19 @@
|
||||
| Recipe | 步骤 |
|
||||
|--------|------|
|
||||
| `lookup-label-members` | 1. `contact label list` → 浏览全部角色,匹配目标角色的 labelId<br>2. `contact label list-members --id <labelId>` → 该角色下的成员列表 |
|
||||
| `search-user-by-mobile` | 1. `contact user search-mobile --mobile "<手机号>"` → 按需 `contact user get --ids <userId>` |
|
||||
| `search-user-by-mobile` | 1. `contact user search-mobile --mobile "<完整手机号>"` → 按需 `contact user get --ids <userId>` |
|
||||
| `lookup-dept-id` | 1. `contact dept search --query "<部门关键词>"` → 回显 `deptId`(多命中须消歧) |
|
||||
| `list-subdepts` | 1. 已有父 `deptId` → `contact dept list-children --dept <父deptId>` 直接取直属子部门列表<br>2. 只有部门名 → 先 `lookup-dept-id` 取 `deptId`,再 `list-children` |
|
||||
| `list-dept-members` | 1. **优先** `python scripts/contact_dept_members.py --query "<部门名>"`<br>2. 备选:`lookup-dept-id` → `contact dept list-members --depts <deptId>`<br>3. 若要每人档案字段:对 `userId` 批量 `contact user get --ids …` |
|
||||
| `list-multi-dept-members` | 1. 对每个部门名 `contact dept search --query "<名>"` → 各 `deptId`<br>2. `contact dept list-members --depts <id1>,<id2>,...`(多部门并行/批量见 conventions)<br>3. 需要档案再 `contact user get --ids …` |
|
||||
| `verify-user-dept` | 1. `contact dept search --query "<部门名>"` → `deptId`<br>2. `contact dept list-members --depts <deptId>` 中匹配姓名;或先 `search-user` lite 再 `user get` 核对部门字段 |
|
||||
| `list-dept-members` | 1. **优先** `python scripts/contact_dept_members.py --query "<部门名>"`<br>2. 备选:`lookup-dept-id` → `contact dept list-members --ids <deptId>`<br>3. 若要每人档案字段:对 `userId` 批量 `contact user get --ids …` |
|
||||
| `list-multi-dept-members` | 1. 对每个部门名 `contact dept search --query "<名>"` → 各 `deptId`<br>2. `contact dept list-members --ids <id1>,<id2>,...`(多部门并行/批量见 conventions)<br>3. 需要档案再 `contact user get --ids …` |
|
||||
| `verify-user-dept` | 1. `contact dept search --query "<部门名>"` → `deptId`<br>2. `contact dept list-members --ids <deptId>` 中匹配姓名;或先 `search-user` lite 再 `user get` 核对部门字段 |
|
||||
|
||||
## Full / 多步组合
|
||||
|
||||
| Recipe | 行动指南(固定路线) |
|
||||
|--------|---------------------|
|
||||
| explore-subdepts-and-members | 1. 取父部门 `deptId`:用户给了 ID 直接用;只给名字则 `contact dept search --query "<父部门名>"` → 父 `deptId`(多命中先消歧)<br>2. **优先** `contact dept list-children --dept <父deptId>` 拿到全部直属子 `deptId` 列表;若用户只点名了部分子部门,则改为对每个子部门名 `contact dept search --query "<子部门名>"`<br>3. 对子 `deptId`:`contact dept list-members --depts <id1>,<id2>,...`(多部门按 conventions **并行/批量**)<br>4. 若还要成员详情:汇总 `userId` → `contact user get --ids …`(≤30 条/批,超出分批 + 用户确认) |
|
||||
| explore-subdepts-and-members | 1. 取父部门 `deptId`:用户给了 ID 直接用;只给名字则 `contact dept search --query "<父部门名>"` → 父 `deptId`(多命中先消歧)<br>2. **优先** `contact dept list-children --dept <父deptId>` 拿到全部直属子 `deptId` 列表;若用户只点名了部分子部门,则改为对每个子部门名 `contact dept search --query "<子部门名>"`<br>3. 对子 `deptId`:`contact dept list-members --ids <id1>,<id2>,...`(多部门按 conventions **并行/批量**)<br>4. 若还要成员详情:汇总 `userId` → `contact user get --ids …`(≤30 条/批,超出分批 + 用户确认) |
|
||||
| verify-user-in-dept | 同速查表 `verify-user-dept`;多轮对话中用户追加「是否在某部门」时叠加本路线 |
|
||||
| cross-level-dept-members | 1. `contact dept search --query "<父部门关键词>"` → 父 `deptId`<br>2. **优先** `contact dept list-children --dept <父deptId>` 枚举全部直属子 `deptId`;用户已点名的子部门则用 `dept search` 精确命中<br>3. 需要逐层下钻时,对上一步拿到的子 `deptId` 继续 `dept list-children` 递归(注意控制深度,避免一次拉太多)<br>4. `contact dept list-members --depts <id1,id2,…>` → 按需 `user get` |
|
||||
| user-detail-organization | 1. `contact user search --query "<关键词>"` → `userId`(多结果先消歧)<br>2. **必须** `contact user get --ids <userId>`<br>3. 若用户同时给出部门语境:叠加 `verify-user-dept` |
|
||||
| batch-users-by-keyword | 1. `contact user search --query "<职位或技能关键词>"` → 多条<br>2. 提取 `userId`(≤30)→ `contact user get --ids …`<br>3. 结果过多时汇总或请用户收窄 |
|
||||
| cross-level-dept-members | 1. `contact dept search --query "<父部门关键词>"` → 父 `deptId`<br>2. **优先** `contact dept list-children --dept <父deptId>` 枚举全部直属子 `deptId`;用户已点名的子部门则用 `dept search` 精确命中<br>3. 需要逐层下钻时,对上一步拿到的子 `deptId` 继续 `dept list-children` 递归(注意控制深度,避免一次拉太多)<br>4. `contact dept list-members --ids <id1,id2,…>` → 按需 `user get` |
|
||||
| user-detail-organization | 1. `aisearch person --keyword "<关键词>" --dimension <维度>` → `userId`(多结果先消歧)<br>2. **必须** `contact user get --ids <userId>`<br>3. 若用户同时给出部门语境:叠加 `verify-user-dept` |
|
||||
| batch-users-by-keyword | 1. `aisearch person --keyword "<职位或技能关键词>" --dimension position,duty` → 多条<br>2. 提取 `userId`(≤30)→ `contact user get --ids …`<br>3. 结果过多时汇总或请用户收窄 |
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
| 1 | **并行查详情**:拿到多个 ID 后,用 `&` 合并到同一条 Shell 命令并行执行 + `wait`,**严禁逐条串行** |
|
||||
| 2 | **翻页**:分页接口须拉全直至无更多 |
|
||||
| 3 | **优先批量 API**:有批量接口则用批量;无则按 #1 并行 |
|
||||
| 4 | **群消息**:必须先 `chat search --query` 得 `openConversationId`,再 `chat message list --group`;多群同条命令并行 |
|
||||
| 4 | **群消息**:必须先 `chat search --query` 得 `openConversationId`,再 `chat message list --group <openConversationId> --time "<yyyy-MM-dd HH:mm:ss>" --direction older`;多群同条命令并行 |
|
||||
| 5 | **列表少轮次**:带条件搜索/列表 → 一次采全详情;**禁止**无新参数时重复同一 `list` / `search` |
|
||||
|
||||
## 多源并行采集(公共模式)
|
||||
@@ -29,7 +29,7 @@
|
||||
|------|------|--------|
|
||||
| `taskUuid` | `minutes list` | `minutes get summary/info/batch --id(s)` |
|
||||
| `userId` | `aisearch person` / `contact user search` / `contact dept list-members` | `contact user get --ids`、`todo --executors`、`calendar --users` |
|
||||
| `deptId` | `contact dept search` | `contact dept list-members --depts`;多子部门时对每个子部门分别 `dept search` 取 id |
|
||||
| `deptId` | `contact dept search` | `contact dept list-members --ids <deptId1,deptId2...>`;多子部门时对每个子部门分别 `dept search` 取 id |
|
||||
| `nodeId` | `drive search` / `wiki node search` | `doc read/update --node`、`drive copy/move/rename/delete --node` |
|
||||
| `nodeId` | `wiki node list` 中的 folder 类型节点 / `wiki node create --type folder` | `wiki node list --folder`、`wiki node create --folder`、`drive upload --folder`、`drive copy/move --folder` |
|
||||
| `eventId` | `calendar event list` | `calendar event get/update --id` |
|
||||
@@ -38,7 +38,7 @@
|
||||
| `todoTaskId` | `todo task list` | `todo task update/done --task-id` |
|
||||
| `reportId` | `report inbox list` / `report outbox list` | `report entry get/stats --report-id` |
|
||||
| `baseId` / `tableId` | `aitable base search` | `aitable record query --base-id --table-id` |
|
||||
| `dentryUuid` | `drive list` / `drive mkdir` | `drive info/download --node`、`drive list/mkdir/upload --folder` |
|
||||
| `dentryUuid` | `drive list` / `drive mkdir` | `drive info/download/copy/move/rename/delete --node`、`drive list/mkdir/upload/copy/move --folder` |
|
||||
| `dentryId` | `drive info` 的数字字段 | 仅用于 `chat message send --dentry-id` |
|
||||
|
||||
**ID 边界硬约束**:`dentryId` 通常是纯数字,只表示聊天文件消息需要的钉盘条目数字 ID;它不是父目录 ID。遇到 `drive --node/--folder`、`doc --node/--folder`、`wiki node --folder` 时,只能使用 `dentryUuid` / `nodeId` / 文档 URL。若当前上下文只有数字型 `dentryId`,必须先重新 `drive list` / `drive search` / `wiki node list` 获取正确 ID,不能把该数字直接代入后续命令。
|
||||
**ID 边界硬约束**:`dentryId` 通常是纯数字,只表示聊天文件消息需要的钉盘条目数字 ID;它不是父目录 ID。遇到 `drive --node/--folder`、`doc --node`、`wiki node --folder` 时,只能使用 `dentryUuid` / `nodeId` / 文档 URL。若当前上下文只有数字型 `dentryId`,必须先重新 `drive list` / `drive search` / `wiki node list` 获取正确 ID,不能把该数字直接代入后续命令。
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# 通讯录能力索引
|
||||
|
||||
| 主题 | 详见 |
|
||||
|---|---|
|
||||
| 用户/部门/组织关系 | [`contact.md`](./contact.md) |
|
||||
| 通讯录最佳实践 | [`08-directory.md`](./08-directory.md) |
|
||||
@@ -9,7 +9,7 @@
|
||||
> - 用户说"创建企业 / 新建企业 / 开通企业 / 初始化企业"(**不含"账号"二字**)→ **`org create`**(创建企业组织本身)
|
||||
> - **判断口径**:先检查 query 是否含"账号"关键词;含则必须路由 `account create`,**禁止**路由 `org create`。
|
||||
>
|
||||
> **CRITICAL — 根部门**:钉钉根部门 `deptId=1`。`dept` 系列命令查根部门统一传 `--dept 1` 或 `--depts 1`,不要传 `self / me / root / 0`。
|
||||
> **CRITICAL — 根部门**:钉钉根部门 `deptId=1`。单部门命令查根部门通常传 `--dept 1`;`dept list-members` 传 `--ids 1`。`dept search` 精确命中企业根部门时可能返回 `deptId=-1` 哨兵,后续部门命令必须规范化为 `1`。不要传 `self / me / root / 0`。
|
||||
|
||||
## 命令总览
|
||||
|
||||
@@ -80,14 +80,58 @@ Usage:
|
||||
Example:
|
||||
dws contact user invite --org-user-name "张三" --org-user-mobile "13800138000" --depts '[{"deptId":1}]'
|
||||
Flags:
|
||||
--org-user-name string 员工在企业内的名称 (必填)
|
||||
--org-user-mobile string 员工手机号 (必填)
|
||||
--depts string 员工所属部门列表 JSON 数组(可选),格式: [{"deptId":1}]
|
||||
--org-user-name string 员工在企业内的名称 (必填)
|
||||
--org-user-mobile string 员工手机号 (必填)
|
||||
--depts string 员工所属部门列表 JSON 数组(可选),格式: [{"deptId":1}]
|
||||
Notes:
|
||||
- 通过手机号邀请单个员工加入当前企业
|
||||
- 认证信息(corpId、optUserId)由系统自动注入,无需手动传入
|
||||
```
|
||||
|
||||
#### 修改员工信息
|
||||
```
|
||||
Usage:
|
||||
dws contact user update [flags]
|
||||
Aliases:
|
||||
update, modify, edit
|
||||
Example:
|
||||
dws contact user update --user-id user001 --org-user-name "张三三"
|
||||
dws contact user update --user-id user001 --depts '[{"deptId":1}]'
|
||||
dws contact user update --user-id user001 --master-user-id manager001 --yes
|
||||
Flags:
|
||||
--user-id string 要修改的员工 userId (必填)
|
||||
--org-user-name string 员工在企业内的名称(可选)
|
||||
--depts string 员工所属部门列表 JSON 数组(可选),格式: [{"deptId":1}]
|
||||
--master-user-id string 直属主管 userId(可选)
|
||||
--yes 跳过二次确认(可选)
|
||||
Notes:
|
||||
- 至少需要一个修改项(--org-user-name、--depts 或 --master-user-id)
|
||||
- 未加 --yes 时会交互式提示确认;脚本/自动化场景请显式带上 --yes
|
||||
- 认证信息(corpId、optUserId)由系统自动注入,无需手动传入
|
||||
```
|
||||
|
||||
#### 更新自己的 profile 信息
|
||||
```
|
||||
Usage:
|
||||
dws contact user update-self [flags]
|
||||
Aliases:
|
||||
update-self, update-me, update-self-profile, edit-self, modify-self
|
||||
Example:
|
||||
dws contact user update-self --nick "新昵称"
|
||||
dws contact user update-self --avatar-file-id "xxxxxx" --yes
|
||||
dws contact user update-self --nick "新昵称" --avatar-file-id "xxxxxx" --yes
|
||||
Flags:
|
||||
--nick string 新昵称(可选)
|
||||
--avatar-file-id string 新头像在钉盘的 fileId(可选)
|
||||
--yes 跳过二次确认(可选)
|
||||
Notes:
|
||||
- 更新当前登录用户自己的个人 profile 信息(昵称 / 头像),不是修改员工组织信息
|
||||
- 至少需要一个修改项(--nick 或 --avatar-file-id)
|
||||
- 头像 fileId 需要先上传头像到钉盘获取
|
||||
- 未加 --yes 时会交互式提示确认;脚本/自动化场景请显式带上 --yes
|
||||
- 认证信息(corpId、optUserId)由系统自动注入,无需手动传入
|
||||
```
|
||||
|
||||
### profile (用户档案 / 花名册)
|
||||
|
||||
#### 查询花名册有权限的字段列表
|
||||
@@ -144,7 +188,7 @@ Flags:
|
||||
查询离职员工列表,支持按员工姓名、离职日期范围、部门进行过滤。认证信息(corpId、optUserId)由系统自动注入,无需手动传入。
|
||||
`--start` 和 `--end` 必须同时设置或同时不设置,不允许只传其中一个。
|
||||
|
||||
### dept (部门查询)
|
||||
### dept (部门查询与管理)
|
||||
|
||||
#### 搜索部门
|
||||
```
|
||||
@@ -194,17 +238,55 @@ Notes:
|
||||
Usage:
|
||||
dws contact dept list-members [flags]
|
||||
Example:
|
||||
dws contact dept list-members --depts 12345,67890
|
||||
dws contact dept list-members --depts 1 # 根部门
|
||||
dws contact dept list-members --ids 12345,67890
|
||||
dws contact dept list-members --ids 1 # 根部门
|
||||
Flags:
|
||||
--depts string 部门 ID 列表,逗号分隔 (必填)
|
||||
--ids string 部门 ID 列表,逗号分隔 (必填)
|
||||
Notes:
|
||||
- **钉钉根部门 `deptId=1`**;查根部门直属成员用 `--depts 1`
|
||||
- **钉钉根部门 `deptId=1`**;查根部门直属成员用 `--ids 1`
|
||||
- 仅返回**本部门**直接成员,**不含下级部门**成员;需含下级请先 `dept list-children` 枚举子部门,再对子 deptId 分别/合并调用 `list-members`
|
||||
- 受组织架构可见性控制;`--depts` 支持逗号分隔批量查询多个部门
|
||||
- 受组织架构可见性控制;`--ids` 支持逗号分隔批量查询多个部门
|
||||
- 跨层级成员展开见 [08-directory.md](08-directory.md) 的 `cross-level-dept-members` recipe
|
||||
```
|
||||
|
||||
#### 创建部门
|
||||
```
|
||||
Usage:
|
||||
dws contact dept create [flags]
|
||||
Example:
|
||||
dws contact dept create --name "新产品部" --create-dept-group true
|
||||
dws contact dept create --name "研发一组" --parent 12345 --create-dept-group false --yes
|
||||
Flags:
|
||||
--name string 部门名称 (必填)
|
||||
--parent string 父部门 ID(可选),不传默认根部门
|
||||
--create-dept-group bool 是否创建部门群(必填)
|
||||
--yes 跳过二次确认(可选)
|
||||
Notes:
|
||||
- 父部门不传时默认钉钉根部门 deptId=1
|
||||
- --create-dept-group 必须显式指定 true 或 false
|
||||
- 未加 --yes 时会交互式提示确认;脚本/自动化场景请显式带上 --yes
|
||||
- 认证信息(corpId、optUserId)由系统自动注入,无需手动传入
|
||||
```
|
||||
|
||||
#### 更新部门
|
||||
```
|
||||
Usage:
|
||||
dws contact dept update [flags]
|
||||
Example:
|
||||
dws contact dept update --dept 12345 --name "新部门名"
|
||||
dws contact dept update --dept 12345 --name "新名称" --parent 67890 --yes
|
||||
Flags:
|
||||
--dept string 部门 ID (必填)
|
||||
--name string 新部门名称(必填)
|
||||
--parent string 新父部门 ID(可选)
|
||||
--yes 跳过二次确认(可选)
|
||||
Notes:
|
||||
- --dept 为要更新的部门 ID,可通过 dept search 或 dept list-children 获取
|
||||
- --name 必填;--parent 可选,未指定时只更新部门名称
|
||||
- 未加 --yes 时会交互式提示确认;脚本/自动化场景请显式带上 --yes
|
||||
- 认证信息(corpId、optUserId)由系统自动注入,无需手动传入
|
||||
```
|
||||
|
||||
### label (角色查询)
|
||||
|
||||
> **角色ID = labelId**:用户提到"角色ID"时,均指通讯录 label 系统中的角色ID,**不是部门ID也不是userId**。查角色成员用 `label list-members --id <角色ID>`,不要传给 `dept get-info` 或 `user get`。
|
||||
@@ -288,23 +370,55 @@ Notes:
|
||||
- 认证信息(corpId、optUserId)由系统自动注入,无需手动传入
|
||||
```
|
||||
|
||||
#### 更新企业账号用户信息
|
||||
```
|
||||
Usage:
|
||||
dws contact account update [flags]
|
||||
Aliases:
|
||||
update, modify, edit
|
||||
Example:
|
||||
dws contact account update --user-id user001 --org-user-name "张三"
|
||||
dws contact account update --user-id user001 --depts '[{"deptId":1}]'
|
||||
dws contact account update --user-id user001 --nick "新昵称" --avatar-file-id "xxxxxx" --yes
|
||||
Flags:
|
||||
--user-id string 被修改企业账号的 userId (必填)
|
||||
--org-user-name string 企业账号在企业内的员工姓名(可选)
|
||||
--depts string 部门列表 JSON 数组(可选),格式: [{"deptId":1}]
|
||||
--master-user-id string 直属主管 userId(可选)
|
||||
--nick string 企业账号自身昵称,用于 profile 展示(可选)
|
||||
--avatar-file-id string 企业账号头像在钉盘的 fileId(可选)
|
||||
--yes 跳过二次确认(可选)
|
||||
Notes:
|
||||
- 更新指定企业账号用户的信息,不是修改普通员工信息
|
||||
- 至少需要一个修改项(--org-user-name / --depts / --master-user-id / --nick / --avatar-file-id)
|
||||
- 头像 fileId 需要先上传头像到钉盘获取
|
||||
- 未加 --yes 时会交互式提示确认;脚本/自动化场景请显式带上 --yes
|
||||
- 认证信息(corpId、optUserId)由系统自动注入,无需手动传入
|
||||
```
|
||||
|
||||
## 意图判断
|
||||
|
||||
> **搜人首选 `aisearch person`**:凡是“找人/搜人/找同事/谁负责/上级/下级”均优先用 [aisearch person](../../dingtalk-aisearch/references/aisearch.md),以下场景才用 contact。
|
||||
> **按搜索性质分流**:姓名模糊搜索、工号、部门、职责和上下级使用 [aisearch person](../../dingtalk-aisearch/references/aisearch.md);完整手机号精确反查使用 `user search-mobile`;拿到 userId 后,以下详情、部门和角色场景再用 contact。
|
||||
|
||||
用户说"我是谁/我的信息/我的 userId/当前用户/本人/self/me/whoami" → `user get-self`(无需参数;禁止用 `user get --ids me/self` 代替)
|
||||
用户需要 userId 给其他产品使用(发消息/建待办/约日程)→ `user search`(按名字)或 `user search-mobile`(按手机号)
|
||||
用户需要 userId 给其他产品使用(发消息/建待办/约日程)→ `aisearch person` 按对应维度搜索
|
||||
用户提供完整手机号并要求反查用户 → `user search-mobile --mobile "<完整手机号>"`
|
||||
用户说"查用户详情/部门/主管/管理员" → `user get`(需 userId,返回组织管理信息)
|
||||
用户说"邀请员工/添加员工/加人/新员工入职/拉人进企业" → `user invite`(需手机号 + 企业内名称,部门可选)
|
||||
用户说"修改员工/更新员工/改员工姓名/改员工部门/换部门/改直属主管/换主管/调整员工信息" → `user update`(需 userId;姓名 / 部门 / 主管至少改一项)
|
||||
用户说"改昵称/改头像/更新我的资料/更新我的profile/更新我的个人信息/修改我的昵称" → `user update-self`(昵称 / 头像至少改一项;头像 fileId 需先上传钉盘)
|
||||
用户说"邀请员工/添加员工/批量邀请/加人/新员工入职/拉人进企业" → `user invite`(需手机号 + 企业内名称 + 部门)
|
||||
用户说"花名册字段/有哪些字段/字段列表" → `user profile fields`
|
||||
用户说"花名册/员工档案/学历/家庭/银行卡/紧急联系人/合同" → `user profile get`(需 staffId,返回个人档案信息)
|
||||
用户说"离职员工/离职名单/离职人员/已离职" → `user dismission search`
|
||||
用户说"创建企业账号/新建企业账号/开通企业账号/专属账号/企业登录账号"(含"账号")→ `account create`(需员工名称 + 登录号;手机号可选)
|
||||
用户说"更新企业账号/修改企业账号/改企业账号信息/改企业账号姓名/改企业账号部门/改企业账号主管/改企业账号昵称/改企业账号头像"(含"账号"且含"改/更新/修改")→ `account update`(需 userId;至少改一项)
|
||||
用户说"创建企业/新建企业/开通企业/初始化企业"(不含"账号")→ `org create`(需企业名称 + 创建者名称)
|
||||
用户说"找部门/哪个部门" → `dept search`
|
||||
用户说"部门详情/部门信息/部门多少人" → `dept get-info`(返回部门ID、部门名称、部门人数;需 deptId,若只有部门名称需先 `dept search`)
|
||||
用户说"子部门/下设部门/部门有哪些下级部门/枚举二级部门" → `dept list-children`(需父 deptId;只有部门名先 `dept search`)
|
||||
用户说"部门有谁/部门成员/人员名单" → `dept list-members`(需 deptId;**仅本部门不含下级**,含下级先 `dept list-children` 再合并查)
|
||||
用户说"创建部门/新建部门/添加部门/成立部门/建部门" → `dept create`(需部门名;父部门可选,默认根部门)
|
||||
用户说"更新部门/修改部门/改部门名/改部门名称/换部门名/改父部门/换上级部门" → `dept update`(需 deptId + name;parent 可选)
|
||||
用户查询涵盖"角色"(主管/管理员/财务/HR/总经理等任意角色名)→ 统一走 `contact label` 链路,按下方决策树选命令:
|
||||
- 不知道角色名 / 枚举所有角色 → `label list`
|
||||
- 已知角色名,查ID或成员 → 先 `label get --names <名>` 拿ID,查成员再调 `label list-members --id <ID>`;**精确匹配无结果时降级 `label list` 模糊匹配**
|
||||
@@ -336,7 +450,7 @@ Notes:
|
||||
> [!IMPORTANT]
|
||||
> **易混淆硬规则**:`relation list-my-followings` **只**返回"我特别关注的人员列表"(一组 openDingTalkId),**不**返回任何消息内容。
|
||||
>
|
||||
> **禁止路由到本命令的场景**(query 中同时包含『关注/特别关注/星标』和以下任一消息域动词/名词时,必须路由到 [`chat message list-focused`](../../dingtalk-chat/references/chat-commands.md)):
|
||||
> **禁止路由到本命令的场景**(query 中同时包含『关注/特别关注/星标』和以下任一消息域动词/名词时,必须路由到 [`chat message list-focused`](../../dingtalk-chat/references/chat.md)):
|
||||
> - 动词类:**发**了什么、**说**了什么/啥、**聊**了什么、**讲**了什么
|
||||
> - 名词类:**消息**、**聊天**、**动态**、**最新内容**
|
||||
>
|
||||
@@ -355,8 +469,8 @@ Notes:
|
||||
# 1. 查看自己的信息 — 提取 userId
|
||||
dws contact user get-self --format json
|
||||
|
||||
# 2. 按名字搜索同事或好友 — 可提取 同事的userId,或好友的openDingTalkId
|
||||
dws contact user search --query "张三" --format json
|
||||
# 2. 按名字搜索人员 — 统一从 AI 搜问取得 userId/openDingTalkId
|
||||
dws aisearch person --keyword "张三" --dimension name --format json
|
||||
|
||||
# 3. 查看部门结构 — 提取 deptId
|
||||
dws contact dept search --query "技术部" --format json
|
||||
@@ -368,7 +482,7 @@ dws contact dept get-info --dept <deptId> --format json
|
||||
dws contact dept list-children --dept <父deptId> --format json
|
||||
|
||||
# 6. 查看部门成员
|
||||
dws contact dept list-members --depts <deptId> --format json
|
||||
dws contact dept list-members --ids <deptId> --format json
|
||||
|
||||
# 7. 获取企业所有角色列表 — 不知道角色名时先浏览
|
||||
dws contact label list --format json
|
||||
@@ -400,10 +514,25 @@ dws contact user dismission search --depts 123456,789012 --hide-retirement=false
|
||||
dws contact org create --org-name "我的企业" --creator-username "张三" --format json
|
||||
|
||||
# 16. 创建企业专属账号
|
||||
dws contact account create --org-user-name "张三" --login-id "zhangsan001" --format json
|
||||
dws contact account create --org-user-name "张三" --login-id "zhangsan001" --org-user-mobile "13800138000" --email "zhangsan@example.com" --dept-ids "1,2,3" --send-pwd-via-sms --format json
|
||||
|
||||
# 17. 邀请员工加入企业
|
||||
# 17. 更新企业账号用户信息
|
||||
dws contact account update --user-id user001 --org-user-name "张三三" --depts '[{"deptId":1}]' --master-user-id manager001 --nick "新昵称" --avatar-file-id "xxxxxx" --yes --format json
|
||||
|
||||
# 18. 邀请员工加入企业
|
||||
dws contact user invite --org-user-name "张三" --org-user-mobile "13800138000" --depts '[{"deptId":1}]' --format json
|
||||
|
||||
# 19. 修改员工信息
|
||||
dws contact user update --user-id user001 --org-user-name "张三三" --depts '[{"deptId":1}]' --master-user-id manager001 --yes --format json
|
||||
|
||||
# 20. 更新自己的 profile 信息
|
||||
dws contact user update-self --nick "新昵称" --avatar-file-id "xxxxxx" --yes --format json
|
||||
|
||||
# 21. 创建部门
|
||||
dws contact dept create --name "新产品部" --parent 12345 --create-dept-group true --yes --format json
|
||||
|
||||
# 22. 更新部门
|
||||
dws contact dept update --dept 12345 --name "新部门名" --parent 67890 --yes --format json
|
||||
```
|
||||
|
||||
## 上下文传递表
|
||||
@@ -416,16 +545,16 @@ dws contact user invite --org-user-name "张三" --org-user-mobile "13800138000"
|
||||
| `user profile fields` | `fieldCode` | profile get 的 --fields |
|
||||
| `label list` | `labelId` / `labelName` | `label get --names` 或 `label list-members --id` |
|
||||
| `label get` | `labelId` | `label list-members` 的 --id |
|
||||
| `dept search/list-children` | `deptId` | dept get-info/list-children/list-members 的 --dept/--depts |
|
||||
| `dept search/list-children` | `deptId` | dept get-info/list-children/update 的 --dept;dept list-members 的 --ids |
|
||||
| `dept search/list-children` | `deptId` | dismission search 的 --depts |
|
||||
| `dept search/list-children` | `deptId` | user invite 的 --depts 或 account create 的 --dept-ids |
|
||||
| `dept create` | `deptId` | dept get-info/list-children/update 的 --dept;dept list-members 的 --ids |
|
||||
|
||||
## 注意事项
|
||||
|
||||
- `user get-self` 是获取 userId 的最快方式,其他产品的 --users/--executor 都需要 userId
|
||||
- `user get --ids` 和 `dept list-members --depts` 都支持批量查询,逗号分隔
|
||||
- `user get --ids` 和 `dept list-members --ids` 都支持批量查询,逗号分隔
|
||||
- `user get` 返回组织管理信息(部门、主管、管理员权限),`user profile get` 返回个人档案信息(学历、家庭、银行卡等),注意区分
|
||||
- `user profile get` 的 `--staff-id` 可通过 `user get-self`、`user search` 或 `aisearch person` 获取
|
||||
- `user profile get` 的 `--staff-id` 可通过 `user get-self` 或 `aisearch person` 获取
|
||||
- `user profile get` 的 `--fields` 可通过 `user profile fields` 获取可用字段 code 列表;不填则查询所有可见字段
|
||||
- 建议先执行 `user profile fields` 获取可用字段列表,再根据需要的字段 code 执行 `user profile get`
|
||||
- `user dismission search` 的 `--start`/`--end` 必须同时设置或同时不设置,不允许只传其中一个
|
||||
@@ -435,7 +564,8 @@ dws contact user invite --org-user-name "张三" --org-user-mobile "13800138000"
|
||||
- `label get` 是精确匹配角色名称,不支持模糊搜索;支持逗号分隔同时查询多个角色名称
|
||||
- **`label get` 精确匹配无结果时的降级策略**:若 `label get --names "XX"` 返回空结果,必须降级调用 `label list` 获取全部角色列表,从中模糊匹配包含XX关键词的角色(如用户说"管理员"可匹配到"主管理员"和"子管理员"),再对匹配到的角色调用 `label list-members`
|
||||
- `label list-members` 需要先通过 `label list` 或 `label get` 获取 labelId,再用 --id 查询角色下的成员
|
||||
- `org create`、`account create`、`user invite` 都是写操作;执行前确认当前 profile 对应的企业以及名称、手机号、登录号和部门信息
|
||||
- `user update-self` 用于更新当前用户自己的昵称/头像;头像 fileId 需先上传头像到钉盘获取
|
||||
- `account update` 用于更新企业账号用户信息;`--depts` 为 JSON 数组格式,头像 fileId 需先上传钉盘获取
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
|
||||
| 用户说... | 真实意图 | 应该用 | 不要用 | 理由 |
|
||||
|---|---|---|---|---|
|
||||
| "张三在哪个部门/查一下同事工号" | 通讯录精确查询 | #8 `contact` | #5 汇报 / #4 文档 | 需要 userId、手机号、部门 ID 等精确信息时用 contact |
|
||||
| "张三在哪个部门/张三的工号是多少" | 搜人后查通讯录详情 | `aisearch person` → `contact user get` | 直接 `contact user search` | 姓名或工号先由 aisearch 获取 userId,再由 contact 补部门、工号等详情 |
|
||||
| "研发部的详细信息/部门信息" | 查部门详情 | `contact dept get-info` | `contact dept list-members` | 查部门属性(ID、名称、人数)用 get-info;查成员列表用 list-members |
|
||||
| "研发部有多少人" | 查部门人数 | `contact dept get-info` | `contact dept list-members` | 问人数用 get-info(返回 memberCount);问有哪些人用 list-members |
|
||||
| "找一下张三/搜同事/找人" | AI搜人(首选) | `aisearch person` | `contact user search` | 搜人首选 aisearch,支持姓名/部门/职责/上下级维度;精确查 userId/手机号用 contact |
|
||||
| "找一下张三/搜同事/找人" | 人员语义搜索 | `aisearch person` | `contact user search` | 姓名模糊搜索、工号、部门、职责和上下级走 aisearch;contact 在拿到 userId 后补详情 |
|
||||
| "五道的上级是谁/谁负责XX/XX的下属有谁" | AI语义搜人 | `aisearch person` | `contact` | 涉及上下级、职责、负责人等语义维度搜索,用 aisearch |
|
||||
| "222020这个工号是谁/查工号" | 按工号搜人 | `aisearch person --dimension jobNumber` | `contact` | 工号查人走 aisearch,dimension=jobNumber |
|
||||
| "13800138000是谁/查手机号" | 按手机号搜人 | `aisearch person --dimension phone` | `contact` | 手机号查人走 aisearch,dimension=phone |
|
||||
| "13800138000是谁/完整手机号反查" | 精确手机号反查 | `contact user search-mobile` | `contact user search` | 完整手机号精确匹配使用 search-mobile |
|
||||
| "按手机号线索找人" | 手机号语义搜人 | `aisearch person --dimension phone` | `contact user search` | 非精确手机号匹配走 aisearch 的 phone 维度 |
|
||||
|
||||
@@ -8,20 +8,12 @@
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
import json
|
||||
import subprocess
|
||||
import argparse
|
||||
from typing import List, Any, Optional
|
||||
|
||||
|
||||
def strip_highlight(text: str) -> str:
|
||||
"""去除 dept search 返回名称中的 <red>…</red> 高亮标签。"""
|
||||
if not isinstance(text, str):
|
||||
return text
|
||||
return re.sub(r'</?red>', '', text)
|
||||
|
||||
|
||||
def run_dws(
|
||||
args: List[str], dry_run: bool = False,
|
||||
) -> Optional[Any]:
|
||||
@@ -62,7 +54,7 @@ def main():
|
||||
if args.dry_run:
|
||||
run_dws([
|
||||
'contact', 'dept', 'list-members',
|
||||
'--depts', '<DEPT_ID>', '--format', 'json',
|
||||
'--ids', '<DEPT_ID>', '--format', 'json',
|
||||
], dry_run=True)
|
||||
return
|
||||
|
||||
@@ -75,10 +67,7 @@ def main():
|
||||
elif isinstance(dept_data, dict):
|
||||
inner = dept_data.get('result', dept_data)
|
||||
if isinstance(inner, dict):
|
||||
depts = (inner.get('deptList')
|
||||
or inner.get('items')
|
||||
or inner.get('depts')
|
||||
or [])
|
||||
depts = inner.get('items', inner.get('depts', []))
|
||||
elif isinstance(inner, list):
|
||||
depts = inner
|
||||
else:
|
||||
@@ -91,9 +80,7 @@ def main():
|
||||
|
||||
for dept in depts:
|
||||
dept_id = dept.get('id') or dept.get('deptId')
|
||||
dept_name = strip_highlight(
|
||||
dept.get('name') or dept.get('deptName', '未知')
|
||||
)
|
||||
dept_name = dept.get('name') or dept.get('deptName', '未知')
|
||||
if not dept_id:
|
||||
continue
|
||||
|
||||
@@ -102,7 +89,7 @@ def main():
|
||||
|
||||
members_data = run_dws([
|
||||
'contact', 'dept', 'list-members',
|
||||
'--depts', str(dept_id), '--format', 'json',
|
||||
'--ids', str(dept_id), '--format', 'json',
|
||||
])
|
||||
if not members_data:
|
||||
print(' 无法获取成员列表')
|
||||
@@ -113,10 +100,8 @@ def main():
|
||||
elif isinstance(members_data, dict):
|
||||
inner = members_data.get('result', members_data)
|
||||
if isinstance(inner, dict):
|
||||
members = (inner.get('deptUserList')
|
||||
or inner.get('userlist')
|
||||
or inner.get('list')
|
||||
or [])
|
||||
members = inner.get('userlist',
|
||||
inner.get('list', []))
|
||||
elif isinstance(inner, list):
|
||||
members = inner
|
||||
else:
|
||||
@@ -128,10 +113,9 @@ def main():
|
||||
continue
|
||||
|
||||
for m in members:
|
||||
info = m.get('userInfo', m)
|
||||
name = info.get('name') or info.get('userName', '未知')
|
||||
title = info.get('title') or info.get('position', '')
|
||||
uid = info.get('userId') or info.get('userid', '')
|
||||
name = m.get('name') or m.get('userName', '未知')
|
||||
title = m.get('title') or m.get('position', '')
|
||||
uid = m.get('userId') or m.get('userid', '')
|
||||
line = f" 👤 {name}"
|
||||
if title:
|
||||
line += f" ({title})"
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
name: dingtalk-devdoc
|
||||
description: 钉钉开放平台开发文档搜索。Use when 用户说 开放平台文档/API 文档/接口文档/调用报错/开放接口怎么调。Distinct from dingtalk-doc(钉钉云文档)。命令前缀:dws devdoc。
|
||||
cli_version: ">=0.2.14"
|
||||
metadata:
|
||||
category: product
|
||||
stability: experimental
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
---
|
||||
|
||||
# 钉钉开放平台文档 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> 命令参考:[devdoc.md](references/devdoc.md)。
|
||||
|
||||
## 意图表
|
||||
|
||||
| 用户说 | 命令 |
|
||||
|--------|------|
|
||||
| "查 OAuth2 接入文档" | `dws devdoc article search --query "OAuth2 接入"` |
|
||||
| "API 调用报错怎么办" | `dws devdoc article search --query "<报错关键词>"` |
|
||||
| "开放接口文档" | `dws devdoc article search --query "<接口名或场景>"` |
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
- 钉钉云文档(个人 / 企业内文档)→ 切到 `dingtalk-doc`
|
||||
## 局部意图与 Recipe
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md)。
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
name: dingtalk-ding
|
||||
description: DING 紧急消息(应用内 / 短信 / 电话)。Use when 用户说 DING一下/紧急通知/电话DING/短信DING/必达消息/电话叫人/以我的名义发DING/个人DING/撤回DING。不做普通群聊消息(走 dingtalk-chat)、企业外呼(走 dingtalk-outbound-call)。命令前缀:dws ding。
|
||||
cli_version: ">=0.2.14"
|
||||
metadata:
|
||||
category: product
|
||||
stability: experimental
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
---
|
||||
|
||||
# 钉钉 DING 紧急消息 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> 命令参考:[ding.md](references/ding.md)。
|
||||
|
||||
<!-- VISIBLE_SHORTCUTS_START -->
|
||||
## Shortcuts(无专用脚本/recipe 时优先)
|
||||
|
||||
以下 shortcut 来自独立于 Runtime Schema 的公开 catalog。先按本 skill 的意图表、脚本和 recipe 路由:存在精确覆盖该场景的专用脚本/recipe 时按其执行;否则用户意图命中时,shortcut 优先于手写原子命令。用 `dws shortcut list --service ding --format json` 读取参数、约束、风险和示例,并以 `dws ding <shortcut> --help` 核对当前 Cobra flags;不要对 `+` 路径调用 `dws schema`。
|
||||
|
||||
| Shortcut | 风险 | 适用场景 |
|
||||
|---|---|---|
|
||||
| `dws ding +list` | read | 查询 DING 消息列表 |
|
||||
| `dws ding +recall-personal` | high-risk-write | 撤回本人发起的 DING |
|
||||
| `dws ding +receiver-status` | read | 查询 DING 消息接收人已读状态 |
|
||||
| `dws ding +send-personal` | write | 以本人身份发送 DING 给指定人 |
|
||||
<!-- VISIBLE_SHORTCUTS_END -->
|
||||
|
||||
## 意图表
|
||||
|
||||
| 用户说 | 命令 |
|
||||
|--------|------|
|
||||
| "DING 张三" / "应用内紧急通知" | `dws ding message send --type app --users <userId> --content "<内容>"` |
|
||||
| "短信 DING" | `dws ding message send --type sms --users <userId> --content "<内容>"` |
|
||||
| "电话 DING" / "电话叫人" | `dws ding message send --type call --users <userId> --content "<内容>"` |
|
||||
| "撤回 DING" | `dws ding message recall --robot-code <robotCode> --id <openDingId>` |
|
||||
| "以我的名义发 DING / 个人 DING" | `dws ding message send-personal --users <openDingTalkId> --content "<内容>"` |
|
||||
| "以我的名义撤回 DING" | `dws ding message recall-personal --id <openDingId>` |
|
||||
| "DING 历史 / 接收状态" | `dws ding message list` / `dws ding message receiver-status` |
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
- 接收人是人名 → 先用 `dingtalk-aisearch` 拿 `userId`
|
||||
- 普通通知(不需必达)→ 切到 `dingtalk-chat`
|
||||
## 局部意图与 Recipe
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md);[Lite Recipe](references/lite-recipes.md)。
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
name: dingtalk-doc
|
||||
description: 钉钉文档内容操作(内容层)。Use when 用户说 写文档/读文档/创建文档内容/编辑文档内容/文档块/分块编辑/Markdown 写入/评论/媒体附件/导出文档/导出 PDF/导出 Markdown/版本历史/保存版本/回滚版本。搜文件/列文件/上传下载/复制移动/重命名/权限管理走 dingtalk-drive;知识库/空间/节点创建列表搜索走 dingtalk-wiki;文档里嵌入的电子表格/多维表格先用本 skill 提取 token 再切到 dingtalk-sheet/dingtalk-aitable。命令前缀:dws doc。
|
||||
cli_version: ">=0.2.14"
|
||||
description: 钉钉文档(adoc):创建、读取、编辑、块、评论、附件、导出、版本及Markdown/JSONML写入。原生 .md→dingtalk-misc;文件→dingtalk-drive;知识库→dingtalk-wiki;axls→dingtalk-misc,able→dingtalk-aitable。
|
||||
metadata:
|
||||
cli_version: ">=0.2.14"
|
||||
category: product
|
||||
stability: experimental
|
||||
requires:
|
||||
bins:
|
||||
- dws
|
||||
@@ -12,16 +11,11 @@ metadata:
|
||||
|
||||
# 钉钉文档 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
> **CRITICAL — 执行任何 `dws` 操作前,MUST 先用 Read 工具完整读取 [`dws-shared`](../dws-shared/SKILL.md)。**该轻量文件包含全局执行契约、安全底线及 shared references 的按需加载导航;不要预加载其全部 references。
|
||||
|
||||
> 命令参考:[doc.md](references/doc.md);剧本:[04-document.md](references/04-document.md)。
|
||||
> 高频模块:[阅读/元信息](references/doc/doc-info-index.md) · [创建/写入/块编辑](references/doc/doc-write-index.md) · [媒体/评论/导出](references/doc/doc-media-index.md) · [导入/版本/模板](references/doc/doc-extra-index.md) · [JSONML](references/format/doc-jsonml-index.md)。
|
||||
|
||||
## 参数硬约束
|
||||
|
||||
@@ -35,7 +29,7 @@ metadata:
|
||||
<!-- VISIBLE_SHORTCUTS_START -->
|
||||
## Shortcuts(无专用脚本/recipe 时优先)
|
||||
|
||||
以下 shortcut 来自独立于 Runtime Schema 的公开 catalog。先按本 skill 的意图表、脚本和 recipe 路由:存在精确覆盖该场景的专用脚本/recipe 时按其执行;否则用户意图命中时,shortcut 优先于手写原子命令。用 `dws shortcut list --service doc --format json` 读取参数、约束、风险和示例,并以 `dws doc <shortcut> --help` 核对当前 Cobra flags;不要对 `+` 路径调用 `dws schema`。
|
||||
以下命令来自独立于 Runtime Schema 的公开 catalog。先运行 `dws shortcut list --service doc --format json` 读取完整契约,再用 `dws doc <shortcut> --help` 核对 flags;不要对 `+` 路径调用 `dws schema`。
|
||||
|
||||
| Shortcut | 风险 | 适用场景 |
|
||||
|---|---|---|
|
||||
@@ -64,44 +58,48 @@ metadata:
|
||||
|--------|------|
|
||||
| "创建文档(短内容)" | `dws doc create --name "<标题>" --content "<内容>"` |
|
||||
| "创建+写入(长内容自动分块)" | `python scripts/doc_create_and_write.py --name "<标题>" --content "<内容>" [--mode append\|overwrite]` |
|
||||
| "搜文档 / 找文档" | `dws drive search --query "<关键词>"` → 取 `nodeId` 后 `dws doc read --node <nodeId>` |
|
||||
| "读文档内容" | `dws doc read --node <nodeId>` |
|
||||
| "搜在线文字文档 / 找在线文字文档" | `dws drive search --query "<关键词>" --format json` → `dws drive info --node <nodeId> --format json` → 仅 `extension=adoc` 使用 `dws doc read --node <nodeId> --format json` |
|
||||
| "读在线文字文档(adoc)内容" | `dws doc read --node <nodeId> --format json` |
|
||||
| "更新文档内容 / 分块追加" | `dws doc update --node <nodeId> --content "<分块>" --mode append` |
|
||||
| "删除块" | `dws doc block delete`(需用户确认) |
|
||||
| "更新文档评论" | `dws doc comment update --node <nodeId> --comment-key <key> --content "<内容>"` |
|
||||
| "删除文档评论" | `dws doc comment delete --node <nodeId> --comment-key <key> --yes`(需用户确认) |
|
||||
| "导出 docx / markdown / pdf" | `dws doc export --node <nodeId> --export-format <docx|markdown|pdf> --output <path>` |
|
||||
| "导入本地文件为在线文档" | `dws doc import --file <path> --folder <FOLDER_NODE_ID> --name "<标题>" --format json`(详见 `references/doc/doc-import.md`) |
|
||||
| "查模板 / 套用模板创建文档" | `dws doc template list|search|apply`(详见 `references/doc/doc-template.md`) |
|
||||
| "保存版本 / 查看版本历史 / 回滚版本" | `dws doc version save/list/revert` |
|
||||
| "查模板 / 套用模板创建文档" | `dws doc template list|search|apply`(详见 `references/doc.md` 模板管理) |
|
||||
| "保存 / 查看 / 回滚在线文字文档(adoc)版本" | `dws doc version save/list/revert` |
|
||||
|
||||
## 标准 SOP(必遵流程)
|
||||
|
||||
> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 nodeId/blockId。每条命令必须带 `--format json`,执行后必须按"验证"步回读真实字段。文件类操作(上传/下载/复制/移动)切 `dingtalk-drive`;知识库节点管理切 `dingtalk-wiki`。
|
||||
> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 nodeId/blockId。结构化命令必须带 `--format json`,执行后必须按"验证"步回读真实字段。文件类操作(上传/下载/复制/移动)切 `dingtalk-drive`;知识库节点管理切 `dingtalk-wiki`。
|
||||
|
||||
### SOP-1 查找并读取文档(query-doc)
|
||||
|
||||
**触发**:查文档/读文档/某文档在哪/搜文档内容。
|
||||
|
||||
1. **定位(必须)**:`dws drive search --query "<关键词>" --format json` → 取 `nodeId`(拿不准是文档还是文件时,先 `dws doc info --node <nodeId> --format json` 判类型)。
|
||||
2. **读取(必须)**:`dws doc read --node <nodeId> --format json`;大文档**必须**只抽取用户需要的章节,**禁止**无差别全文展开。
|
||||
1. **定位(必须)**:用户已提供 URL / `nodeId` 时直接使用原值;未提供目标时才执行 `dws drive search --query "<关键词>" --format json`,再取候选结果的真实 `nodeId`。
|
||||
2. **探测(必须)**:对选中的候选执行 `dws drive info --node <nodeId> --format json`,从真实返回读取 `extension`;不得因为搜索结果标题像“文档”就跳过探测。
|
||||
3. **按类型读取(必须)**:
|
||||
- `extension=adoc`:`dws doc read --node <nodeId> --format json`;大文档只抽取用户需要的章节。
|
||||
- `extension=md`:按普通文件处理,切到 `dingtalk-drive` 用 `dws drive download --node <nodeId> --output <path> --format json` 下载后本地读取。
|
||||
- `extension=axls`:切到 `dingtalk-misc`,读取 `references/sheet.md` 后按电子表格意图执行。
|
||||
- `extension=able`:切到 `dingtalk-aitable`。
|
||||
- `extension=xlsx` / `xls` / `xlsm` / `csv` 或其他普通文件:切到 `dingtalk-drive`;不得执行 `dws doc read`。
|
||||
|
||||
**禁止**:跳过 `drive search` 直接猜 nodeId、把整篇文档原样贴给用户。
|
||||
**禁止**:用户未提供目标时跳过搜索并猜 nodeId、未探测类型就执行 `doc read`、把整篇文档原样贴给用户。
|
||||
|
||||
### SOP-2 创建文档并写入(create-doc)
|
||||
|
||||
**触发**:新建文档/写一篇/建文字文档。
|
||||
|
||||
1. **执行(必须)**:`dws doc create --name "<标题>" --folder <FOLDER_NODE_ID> --content-file <tmp.md> --format json`(长/多行内容用 `--content-file`,不要用 `--content` 拼长串)。
|
||||
2. **验证(必须)**:从返回取 `nodeId`,立即 `dws doc read --node <nodeId> --format json` 回读正文;仅需确认类型、名称或补取链接时再用 `doc info`。
|
||||
1. **执行(必须)**:`dws doc create --name "<标题>" --content-file <tmp.md> [--folder <FOLDER_NODE_ID> | --workspace <WORKSPACE_ID>] --format json`(长/多行内容用 `--content-file`,不要用 `--content` 拼长串;用户未指定位置时省略两个位置参数,创建到“我的文档”根目录)。
|
||||
2. **验证(必须)**:从返回取 `nodeId`,立即 `dws doc info --node <nodeId> --format json` 回读确认。
|
||||
|
||||
**完成条件**:创建结果返回真实 `nodeId`,且正文回读成功;`--folder` 只能使用文档文件夹 nodeId,不能传空间 ID。
|
||||
**禁止**:创建后不回读就答复"已创建"、把 `--folder` 当成空间 ID 传入。
|
||||
|
||||
### SOP-3 覆盖/追加内容(write-content)
|
||||
|
||||
**触发**:覆盖写/追加内容/改文档正文。
|
||||
|
||||
1. **执行(必须)**:覆盖 `dws doc update --node <nodeId> --mode overwrite --content-file <tmp.md> --yes --format json`;追加 `--mode append`。破坏性覆盖**必须**带 `--yes`,且建议先 `--dry-run` 预览。
|
||||
1. **执行(必须)**:覆盖先执行 `dws doc update --node <nodeId> --mode overwrite --content-file <tmp.md> --dry-run --format json` 预览,用户确认后改用 `--yes` 实际覆盖;追加执行 `dws doc update --node <nodeId> --mode append --content-file <tmp.md> --format json`。
|
||||
2. **验证(必须)**:写后 `dws doc read --node <nodeId> --format json` 抽取受影响段落核对。
|
||||
|
||||
**禁止**:不加 `--yes` 反复重试覆盖、跳过 `--dry-run` 直接覆盖未确认的长文档。
|
||||
@@ -110,19 +108,23 @@ metadata:
|
||||
|
||||
**触发**:导出文档/下载文档/转 PDF·Markdown。
|
||||
|
||||
1. **判类型(必须)**:先 `dws doc info --node <nodeId> --format json`;在线文档 → `dws doc export --node <nodeId> --export-format <docx|markdown|pdf> --output <path> --format json`;普通文件 → 切 `dingtalk-drive` 用 `dws drive download --node <nodeId> --output <path> --format json`。
|
||||
1. **判类型(必须)**:先 `dws drive info --node <nodeId> --format json`;`extension=adoc` → `dws doc export --node <nodeId> --export-format <pdf|markdown|docx> --output <path> --format json`;普通文件 → 切 `dingtalk-drive` 用 `dws drive download --node <nodeId> --output <path> --format json`。
|
||||
|
||||
**禁止**:不分类型一律走 `doc export`(普通文件会失败)、跳过 `doc info` 判断。
|
||||
**禁止**:不分类型一律走 `doc export`(普通文件会失败)、跳过 `drive info` 判断。
|
||||
|
||||
### SOP-5 块级编辑(block-edit)
|
||||
|
||||
**触发**:插引用块/代码块/表格/分栏/图片/附件,或删除某块。
|
||||
|
||||
1. **固定顺序(必须)**:`dws doc block list --node <nodeId> --format json` → 选真实 `blockId` → `dws doc block insert|update|delete --node <nodeId> --block-id <blockId> ...` → 再次 `doc block list` 验证。
|
||||
2. **删除(必须)**:删除块**必须**已有用户明确删除意图或二次确认。
|
||||
3. **复杂块(必须)**:插入引用/代码/表格/分栏/附件/图片前,先按 [写入索引](references/doc/doc-write-index.md) 与 [JSONML 索引](references/format/doc-jsonml-index.md) 确认对应命令和元素结构;写后按第 1 步回读验证。
|
||||
1. **先列块(必须)**:`dws doc block list --node <nodeId> --format json`,当前响应的可操作块 ID 位于 `blocks[].element.id`(部分版本可能回显为 `blockId`);必须从目标内容对应项读取,不得编造。空文档的占位空段落可能不能作为 `--ref-block`。
|
||||
2. **按动作执行(必须)**:
|
||||
- 插入:默认追加用 `dws doc block insert --node <nodeId> --text "<内容>" --format json`;只有明确要求相对位置时才加 `--ref-block <非空参照块ID> --where before|after`,容器内插入使用 `--parent-block <父块ID> --index <位置>`。插入命令**不接受** `--block-id`。
|
||||
- 更新:`dws doc block update --node <nodeId> --block-id <目标blockId> --text "<新内容>" --format json`。
|
||||
- 删除:用户确认后执行 `dws doc block delete --node <nodeId> --block-id <目标blockId> --yes --format json`。
|
||||
3. **验证(必须)**:再次执行 `dws doc block list --node <nodeId> --format json` 核对插入、更新或删除结果。
|
||||
4. **复杂块(必须)**:插入引用/代码/表格/分栏/附件/图片前,**必须**先读 [doc.md](references/doc.md) 对应小节,**禁止**只停在"准备查看 help"——说"我将插入..."后必须立即执行命令。
|
||||
|
||||
**禁止**:编造 blockId、未确认就删除。命令帮助只用于确认参数,操作结果必须来自实际命令与回读。
|
||||
**禁止**:编造 blockId、未确认就删除、把完整 `--help` 输出当成最终结果答复用户。
|
||||
### SOP-6 导入本地文件为在线文档(import-file)
|
||||
|
||||
**触发**:导入 Word / Excel / Markdown / 本地文件为在线文档。
|
||||
@@ -133,26 +135,28 @@ metadata:
|
||||
|
||||
**禁止**:把上传文件到钉盘误当成 doc import;不知道目标文件夹 nodeId 时先切 `dingtalk-drive`/`dingtalk-wiki` 查询。
|
||||
|
||||
|
||||
## 多步文档短路径
|
||||
|
||||
- 在目标文件夹创建文字文档:`dws doc create --name "<标题>" --folder <FOLDER_NODE_ID> --content-file <tmp.md> --format json`。拿到 `nodeId` 后立即回读。
|
||||
- 块级编辑固定顺序:`doc block list --node <nodeId>` → 选 `blockId` → `doc block insert/update/delete` → `doc block list` 验证。删除块必须已有用户明确删除意图或二次确认。
|
||||
- 插入引用块、代码块、表格、分栏、附件、图片时,按 [写入索引](references/doc/doc-write-index.md) 选择命令与结构,并在写后回读。
|
||||
- 多个子文档、附件或块操作按依赖顺序执行;每一步复用上一条命令返回的真实 ID,最后统一回读受影响内容。
|
||||
- 用户说"读取并下载/导出"时,先 `doc info --node ... --format json` 判断类型:在线文档用 `doc export`,普通文件切到 `dingtalk-drive` 用 `drive download`。
|
||||
- 所有 dws 命令带 `--format json`;仅参数不确定时查 `--help`,并以实际命令结果完成验证。
|
||||
- 块级编辑固定顺序:`doc block list --node <nodeId>` → 插入用 `--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` 和 `comment delete` 不可逆,必须确认再加 `--yes`。
|
||||
`block delete` 不可逆,必须确认再加 `--yes`。
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
- 文件存储 / 上传下载 → 切到 `dingtalk-drive`
|
||||
- 知识库空间管理 → 切到 `dingtalk-wiki`
|
||||
- 数据表 → 切到 `dingtalk-aitable`
|
||||
- 原生 `.md` 文件按普通文件处理 → 切到 `dingtalk-drive` 用 `drive download` / `drive upload`
|
||||
- 长篇报告生成(多源采集 + 写文档)→ 此 skill 提供 `doc_create_and_write.py` 脚本
|
||||
## 局部意图与 Recipe
|
||||
## 局部意图与短流程
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md);[Lite Recipe](references/lite-recipes.md)。
|
||||
- [局部意图消歧](references/intent-guide.md);[短流程](references/lite-recipes.md)。
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
# 文档知识
|
||||
|
||||
## 模板保形生成
|
||||
|
||||
已有 alidocs 文档需要“按模板生成、复刻或生成同形态变体”时,优先在原生文档层复制,避免 `doc read` 转成 Markdown 后重建导致样式丢失:
|
||||
|
||||
1. `dws drive copy --node <SOURCE_NODE_ID> --folder <FOLDER_NODE_ID> --format json` 复制原文档。
|
||||
2. 从返回中取得副本 `nodeId`,再用 `dws drive rename --node <COPY_NODE_ID> --name "<新名称>" --format json` 重命名。
|
||||
3. 用 `dws doc block list --node <COPY_NODE_ID> --format json` 定位需要替换的块,仅在副本上执行 `doc block update`。
|
||||
4. 回读副本的关键块,确认文字已替换且原布局、表格与样式仍保留。
|
||||
|
||||
不要用 `doc read + doc create` 重建要求保形的模板文档。
|
||||
|
||||
> lite recipe 见 [SKILL.md 速查表](../SKILL.md)。
|
||||
|
||||
| Recipe | 行动指南(固定路线) |
|
||||
|--------|-------------------|
|
||||
| import-file | 1. **直接执行** `dws doc import --file <本地文件路径> --format json`(一条命令完成上传+转换+创建)<br>2. 从返回中提取 `documentUrl` 并告知用户<br>3. **禁止先 Read 文件内容再 `doc create` + `doc update`**——`doc import` 是服务端格式转换,客户端无需解析文件内容<br>4. 可选参数:`--folder <文件夹ID>` 指定目标文件夹、`--workspace <知识库ID>` 指定目标知识库、`--name "文档名"` 自定义名称<br>5. 格式映射:docx/doc→文档, xlsx/xls→表格, xmind/mark→脑图, md/txt→文档<br>6. 超时或中断时 CLI 返回 `taskId`,用 `dws doc import get --task-id <taskId>` 手动查询<br>详见 [doc-import.md](./doc/doc-import.md) |
|
||||
| write-doc | 0. 阅读 [doc-create-workflow.md](./doc/style/doc-create-workflow.md) 的 §前置必读 + §关键词速查表,锁定文档类型和起稿路径:**决策型/含对比的知识沉淀型/用户要求美观 → JSONML 起稿**(`.json`);执行型/说明型 → Markdown 起稿(`.md`)<br>1. 按选定路径执行 doc-create-workflow.md(JSONML 路径有骨架范例可直接复制修改)<br>2. `doc create --content-file /tmp/<name>.json --content-format jsonml`(或 `.md` + `--content-format markdown`)<br>3. 大内容默认依赖 DWS 自动分片;只有 `CONTENT_TRUNCATED`、部分写入失败或回读发现缺失时,才按 workflow 的恢复流程手工补片<br>4. **回读校验(必须)**:所有写入完成后,执行 `doc read --node <nodeId>`,校验关键标题/段落/表格是否完整写入 |
|
||||
| search-docs-and-share | 1. `drive search --query "<关键词>"` → 取 `nodeId` + 标题建索引(不读全文)<br>2. `doc read --node <nodeId>`(追问按需,最多 2 篇) |
|
||||
| search-docs-and-share | 1. `dws drive search --query "<关键词>" --format json` → 取候选 `nodeId` + 标题建索引(不读全文)<br>2. 对追问选中的候选执行 `dws drive info --node <nodeId> --format json`<br>3. 仅 `extension=adoc` 使用 `dws doc read --node <nodeId> --format json`(最多 2 篇);`md` / `axls` / `able` / 普通文件分别切到 markdown / sheet / aitable / drive,禁止固定执行 `doc read` |
|
||||
| create-knowledge-base | 1. 创建知识库空间取 `WS_ID`<br>2. `wiki node create --workspace <WS_ID> --name "<文档名>"` → 取 `nodeId`<br>3. `wiki node list --workspace <WS_ID>` 确认 |
|
||||
| migrate-doc | 1. `doc read --node <源nodeId>` → 取正文并写入临时文件 `<tmp>.md`<br>2. `doc create --name "<文档名>" --folder <DOC_FOLDER_NODE_ID> --content-file <tmp>.md` → 取新 `nodeId`(`--folder` 只传文档文件夹 nodeId / alidocs 文件夹 URL,不传数字 dentryId;正文 <200KB 单步到位)<br>2a. 若正文 >200KB:**必须先向用户提示截断风险**(详见下方「分块 append 截断风险提示」),用户确认后再执行:`doc create --name "<文档名>" --folder <DOC_FOLDER_NODE_ID>` → `nodeId` → 按段落切片 → 每片 `doc update --node <nodeId> --content-file <part> --mode append`<br>3. **回读校验**:`doc read --node <nodeId>` 校验内容完整性 |
|
||||
| update-doc-section | 1. `drive search --query "<关键词>"` → 取 `nodeId`<br>2. **形态选择(按 [doc-update-workflow.md §1.3](./doc/style/doc-update-workflow.md) 优先级)**:目标段落含 callout / 分栏 / 颜色 / @人 / 附件 / 嵌套结构 → 走 `jsonml-node-edit`;纯文本替换且确认无富结构 → 继续本 recipe<br>3. `doc read --node <nodeId>` 定位目标章节<br>4. `doc update --node <nodeId> --content "<替换内容>" --mode overwrite`<br>5. **回读校验**:`doc read --node <nodeId>` 确认 overwrite 未被降级为 append、内容完整无截断<br>**overwrite 须用户确认**;完整改写流程见 [doc-update-workflow.md](./doc/style/doc-update-workflow.md) |
|
||||
| update-doc-section | 1. `dws drive search --query "<关键词>" --format json` → 取 `nodeId`<br>2. `dws drive info --node <nodeId> --format json`,仅 `extension=adoc` 继续;其他类型切到对应 skill/reference<br>3. **形态选择(按 [doc-update-workflow.md §1.3](./doc/style/doc-update-workflow.md) 优先级)**:目标段落含 callout / 分栏 / 颜色 / @人 / 附件 / 嵌套结构 → 走 `jsonml-node-edit`;纯文本替换且确认无富结构 → 继续本 recipe<br>4. `dws doc read --node <nodeId> --format json` 定位目标章节<br>5. `dws doc update --node <nodeId> --content "<替换内容>" --mode overwrite --yes --format json`<br>6. **回读校验**:`dws doc read --node <nodeId> --format json` 确认 overwrite 未被降级为 append、内容完整无截断<br>**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 对应小节执行<br>2. 单块改写 / 含富结构 → §4.4 路径 B;多处保真改写或改 root → §4.4 路径 A;纯文本骨架重写 → §4.5 markdown<br>3. 整篇 overwrite 前必须按 workflow §4.5 向用户提示风险并等待确认<br>4. **回读校验(必须)**:按 workflow §6 的校验要点逐项核查;@人、附件、图片等保真要素必须原样保留<br>**适用场景**:用户提供已有 nodeId/链接,需要改写、润色、章节补充、段落形态转换、整篇重写 |
|
||||
| doc-to-message | 1. `doc read --node <nodeId>` → 取正文(大文档只摘要+链接)<br>2. `contact user search --query "<姓名>"` → 取 `openDingTalkId`(推荐);或 `chat search --query "<群名>"` → 取 `openConversationId`<br>3. `chat message send --open-dingtalk-id <openDingTalkId> --text "<内容>"`(推荐)或 `--group <openConversationId> --text "<内容>"` 发送。仅当无法获取 openDingTalkId 时才用 `--user <userId>`(备选) |
|
||||
| doc-to-message | 1. `doc read --node <nodeId>` → 取正文(大文档只摘要+链接)<br>2. `aisearch person --keyword "<姓名>" --dimension name` → 取 `openDingTalkId`(推荐);或 `chat search --query "<群名>"` → 取 `openConversationId`<br>3. `chat message send --open-dingtalk-id <openDingTalkId> --text "<内容>"`(推荐)或 `--group <openConversationId> --text "<内容>"` 发送。仅当无法获取 openDingTalkId 时才用 `--user <userId>`(备选) |
|
||||
| lossless-doc-edit | 1. `doc read --node <nodeId> --content-format jsonml --output /tmp/doc.json` → 获取完整 JSONML 结构(输出含 `revision`,并发敏感时记下来;默认改写不需要)<br>2. 解析 JSON 文件,修改 `jsonml` 数组中的目标节点(节点结构参见 [doc-jsonml-schema.md](./doc/format/doc-jsonml-schema.md))<br>3. 将修改后的内容写回临时文件 `/tmp/doc_modified.json`,格式为 `{"jsonml": [...]}`<br>4. `doc update --node <nodeId> --content-file /tmp/doc_modified.json --content-format jsonml --mode overwrite`(默认不做并发检查;担心多 agent 同时改时加 `--revision <第 1 步拿到的 N>` 触发并发检查,版本不一致返回 `VersionConflict` 时回到第 1 步重读重写)<br>5. **回读校验**:`doc read --node <nodeId> --content-format jsonml` 确认写入成功<br>**适用场景**:保留样式、精准插入特定节点类型、改属性不动文本;普通文本编辑仍优先用 markdown 模式。完整 JSONML 改写流程见 [doc-update-workflow.md §4.4](./doc/style/doc-update-workflow.md) |
|
||||
| jsonml-node-edit | 1. `doc block list --node <nodeId> --content-format jsonml` → 获取 JSONML 节点列表(含 uuid)<br>2. 根据 uuid 定位目标节点<br>3. `doc block list --node <nodeId> --content-format jsonml --block-id <uuid>` → 读取完整子树<br>4. 修改 JSONML 节点内容(节点结构参见 [doc-jsonml-schema.md](./doc/format/doc-jsonml-schema.md),可复制范例见 [doc-jsonml-cookbook.md](./doc/format/doc-jsonml-cookbook.md))<br>5. `doc block update --node <nodeId> --block-id <uuid> --content-format jsonml --element '<修改后的 JSONML>'` → 写回<br>**适用场景**:只改一个 block 的结构/样式,无需全文回写;写入端默认 normalize(自动补 uuid、裸字符串包成 canonical 文本),可用 `--no-fix-jsonml` 关闭全部修复;`--fix-jsonml` 额外启用 JSON 语法修复(推荐 agent 调用) |
|
||||
|
||||
## template-based-generation
|
||||
|
||||
当用户提供已有 alidocs 文档并要求“按模板生成、复刻、生成同形态的新版本”时,必须走保形复制链路:
|
||||
|
||||
1. `dws drive info --node <源文档ID或URL> --format json`,确认源节点存在并记录类型。
|
||||
2. `dws drive copy --node <源文档ID或URL> [--folder <目标文件夹>] [--workspace <目标知识库>] --format json`,从返回中提取副本 `nodeId`。
|
||||
3. 如需改名,只对副本执行 `dws drive rename --node <副本nodeId> --name "<新名称>" --format json`。
|
||||
4. `dws doc block list --node <副本nodeId> --content-format jsonml` 定位需要替换的块;仅对副本执行 `dws doc block update`。涉及多个块或富结构时,按 [doc-update-workflow.md](./doc/style/doc-update-workflow.md) 的 JSONML 路径操作。
|
||||
5. 再次读取副本的 `drive info` 和目标块,确认名称、内容与结构;禁止修改源文档。
|
||||
|
||||
**禁止**用 `doc read` → `doc create` 重建模板。Markdown 是有损投影,会丢失行高、单元格背景色、字号和部分富结构。
|
||||
|
||||
---
|
||||
|
||||
## 分块 append 截断风险提示
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user