first commit

This commit is contained in:
2026-09-02 11:44:52 +08:00
commit 0c8fa2653e
309 changed files with 57278 additions and 0 deletions
@@ -0,0 +1,51 @@
# 通讯录(组织架构)
> **SKILL.md** 中 #8 内联 3 条 **lite**`get-contact-self`、`search-person`、`search-user`。下列 recipe、专用规则与消歧请在命中 #8 且**超出**上述 lite 时阅读本文。
> 产品命令见 [contact.md](./contact.md)。通用批量/并行见 [recipes/conventions.md](recipes/conventions.md)。
## 专用规则(#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 --ids`
- **详情链路**:用户要子部门、职位、联系方式、汇报关系等,在 `aisearch person` 找到 `userId` 后**必须**再 `contact user get --ids <userId>`;禁止仅用搜索结果的浅表字段交差。
- **`user get` 后部门仍空**:不得过早结束或只建议用户去 App;须在 CLI 能力内尝试 **用户点名的部门** `dept search` + `dept list-members` 等与 `userId` 交叉核对,再结构化汇总「返回中有哪些字段 / 哪些为空及可能原因」。
- **多命中**`aisearch person``dept search` 返回多条时须列候选(姓名、title、部门线索)请用户确认,禁止默认猜一人。具体消歧流程:
1. 从搜索结果中提取所有同名/多命中用户的 `userId`
2. 调用 `contact user get --ids userId1,userId2,...` 获取每人详情(含 `depts` 部门列表、职位等)
3. 将「姓名 + 部门 + 职位」列表展示给用户,请用户确认选择哪一位
4. 使用用户确认的 `userId` 继续后续操作
> **根因**`aisearch person` 不返回完整部门信息,无法仅凭搜索结果区分同名用户。**必须**追加 `contact user get` 获取部门信息才能消歧。
- **批量**:多个 `userId``contact user get --ids id1,id2,...`;多部门成员列表按需并行,遵守单次批量上限与 [recipes/conventions.md](recipes/conventions.md)。
- **子部门枚举**:已知父部门 `deptId` 时**优先** `contact dept list-children --dept <父deptId>` 直接拿到完整子部门列表;只知道部门名时先 `contact dept search --query "<父部门名>"``deptId``list-children`;用户明示的子部门名(无需枚举)可直接 `dept search` 命中。多子部门展开见 `explore-subdepts-and-members`
## 与其他场景消歧
- **按角色/职位类型查人(主管/管理员/财务等)** → 优先 `contact label list` + `label list-members`;label 精确命中角色维度,返回完整名单;aisearch 是语义模糊搜索不保证完整性。
- **搜人/找人/找同事/查工号/手机号语义搜索** → **`aisearch person`**(支持姓名/部门/职责/上下级/手机号线索/工号维度),见 `dingtalk-aisearch`
- **完整手机号精确反查** → `contact user search-mobile --mobile "<手机号>"`
- **已有 userId 后查详情 / 查自己 / 查部门与角色** → `contact`(精确查询)。
- **纯查部门与子部门成员 / 验证归属 / 组织关系** → `contact`
- **终点是发消息、待办、日程** → 先用 `search-person``search-user``userId`,再进入 #1 / #2 / #3
- **联系客户 + 发邮件** → 先用 `contact``orgAuthEmail`,再走 `dingtalk-mail`
## Recipe 速查(本表步骤,非 SKILL lite)
| 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>` |
| `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 --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 --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 --ids <id1,id2,…>` → 按需 `user get` |
| user-detail-organization | 1. `aisearch person --query "<关键词>" --dimension <维度>``userId`(多结果先消歧)<br>2. **必须** `contact user get --ids <userId>`<br>3. 若用户同时给出部门语境:叠加 `verify-user-dept` |
| batch-users-by-keyword | 1. `aisearch person --query "<职位或技能关键词>" --dimension position,duty` → 多条<br>2. 提取 `userId`(≤30)→ `contact user get --ids …`<br>3. 结果过多时汇总或请用户收窄 |
@@ -0,0 +1,574 @@
# 通讯录 (contact) 命令参考
> **CRITICAL — 命令合法性**contact 二级子命令包括 `user` / `dept` / `label` / `relation` / `org` / `account`。
> 不存在 `contact search`、`contact find`、`contact list`、`contact get`、`contact user find/list`。
> 构造命令前必须确认路径在下方「命令总览」中存在;不确定时,**根据意图对照下方「意图判断」选择正确命令**。
>
> **CRITICAL — 创建企业 vs 创建企业账号(必须优先匹配长模式)**:
> - 用户说"创建企业**账号** / 新建企业**账号** / 开通企业**账号** / **专属账号** / **企业登录账号**" → **`account create`**(创建企业专属登录账号)
> - 用户说"创建企业 / 新建企业 / 开通企业 / 初始化企业"**不含"账号"二字**)→ **`org create`**(创建企业组织本身)
> - **判断口径**:先检查 query 是否含"账号"关键词;含则必须路由 `account create`**禁止**路由 `org create`。
>
> **CRITICAL — 根部门**:钉钉根部门 `deptId=1`。单部门命令查根部门通常传 `--dept 1``dept list-members` 传 `--ids 1`。`dept search` 精确命中企业根部门时可能返回 `deptId=-1` 哨兵,后续部门命令必须规范化为 `1`。不要传 `self / me / root / 0`。
## 命令总览
### user (人员查询)
#### 获取当前用户信息
```
Usage:
dws contact user get-self [flags]
Aliases:
get-self, self, me, whoami, current
Example:
dws contact user get-self
dws contact user self # 别名
dws contact user me # 别名
dws contact user whoami # 别名
dws contact user current # 别名
Notes:
- 触发词:我是谁 / 我的信息 / 我的 userId / 当前用户 / 本人 / self / me / whoami
- 顶层亦已挂 `dws contact get-self / user-self / current-user` 提示,误写会引导到正确命令
- **禁止**用 `dws contact user get --ids me/self/current` 代替(会报错);正确用法是 `get-self` 或其别名
```
#### 按关键词搜索用户
```
Usage:
dws contact user search [flags]
Example:
dws contact user search --query "张三"
Flags:
--query string 搜索关键词 (必填)
Returns: (列表,每项包含以下字段)
name string 成员姓名
nick string 成员昵称
userId string 成员 ID(仅同事关系时返回)
title string 员工职位(仅同事关系时返回)
openDingTalkId string 当前用户视角下的目标用户唯一标识,不可跨用户共享;可用于发消息等好友关系场景的操作
```
> **CAUTION:** 多人同名时禁止默认选第一个 — `user search` 不返回部门信息,须追加 `contact user get --ids userId1,userId2,...` 获取部门/职位后请用户确认。详见 [08-directory.md](08-directory.md)「多命中」。
#### 按手机号搜索用户
```
Usage:
dws contact user search-mobile [flags]
Example:
dws contact user search-mobile --mobile 13800138000
Flags:
--mobile string 手机号 (必填)
```
#### 批量获取用户详情
```
Usage:
dws contact user get [flags]
Example:
dws contact user get --ids userId1,userId2
Flags:
--ids string 用户 ID 列表,逗号分隔 (必填)
Notes:
- **禁止**将 `self/me/current/whoami` 作为 userId 传入;查自己请用 `dws contact user get-self`
```
#### 邀请员工加入企业
```
Usage:
dws contact user invite [flags]
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}]
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 (用户档案 / 花名册)
#### 查询花名册有权限的字段列表
```
Usage:
dws contact user profile fields
Example:
dws contact user profile fields
Flags:
```
查询花名册有权限的字段列表,根据当前用户查询花名册有权限的字段列表。认证信息(corpId、optUserId)由系统自动注入,无需手动传入。
#### 查询员工花名册字段信息(个人档案)
```
Usage:
dws contact user profile get [flags]
Example:
dws contact user profile get --staff-id STAFF_ID
dws contact user profile get --staff-id STAFF_ID --fields fieldCode1,fieldCode2
Flags:
--staff-id string 查询员工 ID(可选)
--fields string 指定字段集合, 逗号分隔, 可通过 profile fields 获取(可选)
```
查询员工花名册字段信息,根据当前用户指定员工和字段列表,查询相应管理范围内员工的字段值信息。
花名册字段包含:试用/转正信息、个人/家庭信息、学历信息、银行卡/合同信息、紧急联系人和其他企业自定义信息。
> **与 `contact user get` 的区别**`user get` 返回组织管理信息(部门、主管、管理员权限),`user profile get` 返回个人档案信息(学历、家庭、银行卡等)。
### dismission (离职员工)
#### 分页获取离职员工列表
```
Usage:
dws contact user dismission search [flags]
Example:
dws contact user dismission search
dws contact user dismission search --name "张三"
dws contact user dismission search --start 2026-01-01 --end 2026-03-31
dws contact user dismission search --depts 123456,789012 --page 1 --limit 50
Flags:
--name string 员工姓名,模糊搜索(可选)
--start string 离职日期查询范围开始,格式 YYYY-MM-DD(可选)
--end string 离职日期查询范围结束,格式 YYYY-MM-DD(可选)
--depts string 部门 ID 列表,逗号分隔(可选)
--hide-retirement 是否隐藏退休,默认 true(可选)
--hide-partner 是否隐藏合作伙伴,默认 false(可选)
--page int 页码,从 1 开始(可选,默认 1)
--limit int 页大小,200 以内(可选,默认 20)
```
查询离职员工列表,支持按员工姓名、离职日期范围、部门进行过滤。认证信息(corpId、optUserId)由系统自动注入,无需手动传入。
`--start``--end` 必须同时设置或同时不设置,不允许只传其中一个。
### dept (部门查询与管理)
#### 搜索部门
```
Usage:
dws contact dept search [flags]
Example:
dws contact dept search --query "技术部"
Flags:
--query string 搜索关键词 (必填)
```
#### 获取部门详情
```
Usage:
dws contact dept get-info [flags]
Example:
dws contact dept get-info --dept 12345
Flags:
--dept string 部门 ID (必填)
Notes:
- **钉钉根部门 `deptId=1`**;查根部门用 `--dept 1`
```
#### 查看子部门
```
Usage:
dws contact dept list-children [flags]
Example:
dws contact dept list-children --dept 1 # 枚举根部门下的一级部门
dws contact dept list-children --dept 12345 # 枚举指定部门的直属子部门
Flags:
--dept string 父部门 ID (必填)
Returns:
success bool 调用是否成功
result list 直属子部门列表,每项包含以下字段:
deptId int 子部门 ID
deptName string 子部门名称
Notes:
- **钉钉根部门 `deptId=1`**;查询一级部门请用 `--dept 1`
- 仅返回**直属**(直接下一级)子部门,不递归;需要逐层下钻请对子 deptId 继续调用本命令
- 受组织架构可见性控制:仅返回调用者**有权限查看**的子部门
- 父部门不可见或无子部门时返回 result=[] 空列表(非错误)
```
#### 查看部门成员
```
Usage:
dws contact dept list-members [flags]
Example:
dws contact dept list-members --ids 12345,67890
dws contact dept list-members --ids 1 # 根部门
Flags:
--ids string 部门 ID 列表,逗号分隔 (必填)
Notes:
- **钉钉根部门 `deptId=1`**;查根部门直属成员用 `--ids 1`
- 仅返回**本部门**直接成员,**不含下级部门**成员;需含下级请先 `dept list-children` 枚举子部门,再对子 deptId 分别/合并调用 `list-members`
- 受组织架构可见性控制;`--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`。
#### 获取企业所有角色列表
```
Usage:
dws contact label list
Example:
dws contact label list
Flags:
Notes:
- 无需参数,返回当前企业全部角色列表(labelId、labelName等)
- 用于不知道准确角色名称时先浏览全部角色
- 典型场景:用户说“企业所有主管/查所有管理员/财务人员有哪些”→ 先 label list 浏览全部角色,匹配目标角色后 label list-members 获取成员
```
#### 根据角色名称查询角色
```
Usage:
dws contact label get [flags]
Example:
dws contact label get --names "管理员"
dws contact label get --names "管理员,财务"
Flags:
--names string 角色名称,逗号分隔 (必填)
Notes:
- 精确匹配角色名称,不支持模糊搜索
- 支持同时查询多个角色名称,逗号分隔
- 无需分页
```
#### 查询角色下的成员
```
Usage:
dws contact label list-members [flags]
Example:
dws contact label list-members --id 12345
Flags:
--id string 角色 ID (必填)
Notes:
- 根据角色ID直接查询成员列表;已有角色ID时直接用 `--id <labelId>`
- 不知道角色ID时:先 `dws contact label get --names "角色名"` 或 `dws contact label list` 获取 labelId
```
### org (企业管理)
#### 创建企业
```
Usage:
dws contact org create [flags]
Example:
dws contact org create --org-name "我的企业" --creator-username "张三"
Flags:
--org-name string 企业名称 (必填)
--creator-username string 创建者在企业内的名称,对应 creatorUsername (必填)
Notes:
- 创建一个新的钉钉企业,当前用户将成为该企业的创建者
- 认证信息(corpId、optUserId)由系统自动注入,无需手动传入
```
### account (企业账号管理)
#### 创建企业专属账号
```
Usage:
dws contact account create [flags]
Example:
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
Flags:
--org-user-name string 员工在企业内的名称 (必填)
--login-id string 登录号 (必填),请勿包含手机号等联系方式
--org-user-mobile string 员工手机号(可选)
--email string 邮箱(可选)
--dept-ids string 要加入的部门 ID 列表,逗号分隔(可选)
--send-pwd-via-sms 是否通过手机短信/邮件发送登录邀请(可选,默认 false)
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](../../dingtalk-aisearch/references/aisearch.md);完整手机号精确反查使用 `user search-mobile`;拿到 userId 后,以下详情、部门和角色场景再用 contact。
用户说"我是谁/我的信息/我的 userId/当前用户/本人/self/me/whoami" → `user get-self`(无需参数;禁止用 `user get --ids me/self` 代替)
用户需要 userId 给其他产品使用(发消息/建待办/约日程)→ `aisearch person` 按对应维度搜索
用户提供完整手机号并要求反查用户 → `user search-mobile --mobile "<完整手机号>"`
用户说"查用户详情/部门/主管/管理员" → `user get`(需 userId,返回组织管理信息)
用户说"修改员工/更新员工/改员工姓名/改员工部门/换部门/改直属主管/换主管/调整员工信息" → `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 + nameparent 可选)
用户查询涵盖"角色"(主管/管理员/财务/HR/总经理等任意角色名)→ 统一走 `contact label` 链路,按下方决策树选命令:
- 不知道角色名 / 枚举所有角色 → `label list`
- 已知角色名,查ID或成员 → 先 `label get --names <名>` 拿ID,查成员再调 `label list-members --id <ID>`**精确匹配无结果时降级 `label list` 模糊匹配**
- 已知角色ID 查成员 → `label list-members --id <ID>`
> [!IMPORTANT]
> **角色查询 3 步决策树**(不依赖字串匹配,按语义判定):
> 1. 不知道角色名 / 要枚举所有角色(列出企业有哪些角色、每个角色的名称和ID、不确定叫什么角色、负责XX的人有哪些等) → `label list`
> 2. 已知角色名 要查角色ID → `label get --names`
> 3. 已知角色ID 要查成员 → `label list-members --id`
>
> 任何含"角色"一词的查询默认走 `contact label` 链路。**唯一例外**:终点是"某个人是否具备某权限"(如"张三是不是管理员")→ `user get`。禁止路由到 `user profile fields`(那是花名册字段)、`dept list-members` 筛选、或 OA/chat 模块。
> [!IMPORTANT]
> **角色查人 vs 查某人的角色信息 — 判断口径**:先判断用户的终点是"人"还是"属性"
> - 终点是**人**"管理员角色有哪些人""管理员下都有谁""查XX角色的成员")→ 角色维度查人,**必须**走 `contact label` 链路(`label get`/`label list` → `label list-members`),**禁止**通过 `dept list-members` 筛选 `isAdmin` 等字段替代
> - 终点是**属性**"张三是不是管理员""查某人的主管/管理员权限")→ 已知 userId 查个人详情,走 `user get`(返回 isAdmin/leader 等字段)
>
> 反例对照:
> - "管理员角色下都有哪些人" → `label get --names 管理员` → `label list-members`(终点=角色下的**人员列表**)
> - "我想知道管理员这个角色下都有谁" → `label get --names 管理员` → `label list-members`(终点=角色下的**人员列表**)
> - "张三是不是管理员" → `user get --ids <userId>`(终点=某个人的**属性**
> - "查一下张三的管理员权限" → `user get --ids <userId>`(终点=某个人的**属性**
> - "角色ID为55808858的角色下有哪些成员" → `label list-members --id 55808858`(已有角色ID直接查成员)
>
> **角色 = 通讯录 label**:用户提到"角色"(角色ID/角色成员/角色名称/企业角色/查角色下的人)时,均指通讯录组织角色,应走 `contact label` 链路。OA 审批只管审批流程(待审批/同意/拒绝),**不支持**查询角色成员;群角色(chat group-role)只管群内身份,不涉及企业组织角色。
用户说"我关注了谁/我的特别关注列表/我的星标联系人/特别关注的人有哪些" → `relation list-my-followings`
> [!IMPORTANT]
> **易混淆硬规则**`relation list-my-followings` **只**返回"我特别关注的人员列表"(一组 openDingTalkId),**不**返回任何消息内容。
>
> **禁止路由到本命令的场景**(query 中同时包含『关注/特别关注/星标』和以下任一消息域动词/名词时,必须路由到 [`chat message list-focused`](../../dingtalk-chat/references/chat.md)):
> - 动词类:**发**了什么、**说**了什么/啥、**聊**了什么、**讲**了什么
> - 名词类:**消息**、**聊天**、**动态**、**最新内容**
>
> **判断口径**:先扫描 query 是否含上述动词/名词;含则路由到 `chat message list-focused`**不论** query 主语是否为"我特别关注的人"。
>
> 反例对照:
> - "我特别关注的人有哪些" → `relation list-my-followings`(终点=人员列表)
> - "我特别关注的人**最近发了什么消息**" → `chat message list-focused`(含"发""消息"
> - "我关注的人**最近都说了啥**" → `chat message list-focused`(含"说"
组合场景(多子部门、跨层级成员、强消歧)见 [08-directory.md](08-directory.md)。
## 核心工作流
```bash
# 1. 查看自己的信息 — 提取 userId
dws contact user get-self --format json
# 2. 按名字搜索人员 — 统一从 AI 搜问取得 userId/openDingTalkId
dws aisearch person --query "张三" --dimension name --format json
# 3. 查看部门结构 — 提取 deptId
dws contact dept search --query "技术部" --format json
# 4. 查看部门详情(部门ID、名称、人数)
dws contact dept get-info --dept <deptId> --format json
# 5. 查看直属子部门 — 提取子 deptId 列表
dws contact dept list-children --dept <父deptId> --format json
# 6. 查看部门成员
dws contact dept list-members --ids <deptId> --format json
# 7. 获取企业所有角色列表 — 不知道角色名时先浏览
dws contact label list --format json
# 8. 根据角色名称查询角色
dws contact label get --names "管理员" --format json
# 9. 查询角色下的成员
dws contact label list-members --id <labelId> --format json
# 10. 查询花名册有权限的字段列表
dws contact user profile fields --format json
# 11. 根据字段 code 查询指定员工的花名册信息
dws contact user profile get --staff-id <STAFF_ID> --fields fieldCode1,fieldCode2 --format json
# 12. 查询所有可见字段的花名册信息
dws contact user profile get --staff-id <STAFF_ID> --format json
# 13. 查询全部离职员工
dws contact user dismission search --format json
# 14. 按姓名/时间范围/部门筛选离职员工
dws contact user dismission search --name "张三" --format json
dws contact user dismission search --start 2026-01-01 --end 2026-03-31 --format json
dws contact user dismission search --depts 123456,789012 --hide-retirement=false --format json
# 15. 创建企业
dws contact org create --org-name "我的企业" --creator-username "张三" --format json
# 16. 创建企业专属账号
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. 更新企业账号用户信息
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
```
## 上下文传递表
| 操作 | 提取 | 用于 |
|------|------|------|
| `user get-self/search` | `userId` | 其他产品中的 --users/--executor 参数 |
| `user get-self/search` | `orgAuthEmail` | mail message send 的 --to/--cc (跨产品) |
| `user get-self/search` | `userId` | profile get 的 --staff-id |
| `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/update 的 --deptdept list-members 的 --ids |
| `dept search/list-children` | `deptId` | dismission search 的 --depts |
| `dept create` | `deptId` | dept get-info/list-children/update 的 --deptdept list-members 的 --ids |
## 注意事项
- `user get-self` 是获取 userId 的最快方式,其他产品的 --users/--executor 都需要 userId
- `user get --ids``dept list-members --ids` 都支持批量查询,逗号分隔
- `user get` 返回组织管理信息(部门、主管、管理员权限),`user profile get` 返回个人档案信息(学历、家庭、银行卡等),注意区分
- `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` 必须同时设置或同时不设置,不允许只传其中一个
- `user dismission search` 默认隐藏退休人员(`--hide-retirement` 默认 true),默认展示合作伙伴(`--hide-partner` 默认 false
- `label list` 无需参数,适用于不知道准确角色名称的场景;当用户说“查所有主管/主管理员/财务”等角色类型人员时,优先 `label list` 列出企业全部角色,LLM 灵活匹配目标角色后调用 `label list-members`
- 角色类查询(主管、管理员、财务、HR 等任意角色)优先走 label 链路,而非 dept list-members 或 aisearch personlabel 精确命中角色维度,返回完整名单
- `label get` 是精确匹配角色名称,不支持模糊搜索;支持逗号分隔同时查询多个角色名称
- **`label get` 精确匹配无结果时的降级策略**:若 `label get --names "XX"` 返回空结果,必须降级调用 `label list` 获取全部角色列表,从中模糊匹配包含XX关键词的角色(如用户说"管理员"可匹配到"主管理员"和"子管理员"),再对匹配到的角色调用 `label list-members`
- `label list-members` 需要先通过 `label list``label get` 获取 labelId,再用 --id 查询角色下的成员
- `user update-self` 用于更新当前用户自己的昵称/头像;头像 fileId 需先上传头像到钉盘获取
- `account update` 用于更新企业账号用户信息;`--depts` 为 JSON 数组格式,头像 fileId 需先上传钉盘获取
## 自动化脚本
| 脚本 | 场景 | 用法 |
|------|------|------|
| [contact_dept_members.py](../scripts/contact_dept_members.py) | 按部门名称搜索并列出所有成员 | `python contact_dept_members.py --query "技术部"` |
@@ -0,0 +1,14 @@
# contact 局部意图消歧
本文件从单 Skill `intent-guide.md` 拆分而来,仅保留与本产品相关的跨产品消歧规则。
| 用户说... | 真实意图 | 应该用 | 不要用 | 理由 |
|---|---|---|---|---|
| "张三在哪个部门/张三的工号是多少" | 搜人后查通讯录详情 | `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 |
| "找一下张三/搜同事/找人" | 人员语义搜索 | `aisearch person` | `contact user search` | 姓名模糊搜索、工号、部门、职责和上下级走 aisearchcontact 在拿到 userId 后补详情 |
| "五道的上级是谁/谁负责XX/XX的下属有谁" | AI语义搜人 | `aisearch person` | `contact` | 涉及上下级、职责、负责人等语义维度搜索,用 aisearch |
| "222020这个工号是谁/查工号" | 按工号搜人 | `aisearch person --dimension jobNumber` | `contact` | 工号查人走 aisearchdimension=jobNumber |
| "13800138000是谁/完整手机号反查" | 精确手机号反查 | `contact user search-mobile` | `contact user search` | 完整手机号精确匹配使用 search-mobile |
| "按手机号线索找人" | 手机号语义搜人 | `aisearch person --dimension phone` | `contact user search` | 非精确手机号匹配走 aisearch 的 phone 维度 |
@@ -0,0 +1,30 @@
# contact Lite Recipe
本文件从单 Skill `lite-recipes.md` 拆分而来,仅保留与本产品相关的轻量流程。
## #8 通讯录
### get-contact-self
`contact user get-self` → 当前用户 userId、部门、主管等
### search-person
**搜人首选入口**。凡是“找人/搜人/找同事/谁负责/上级/下级/负责人/团队成员”均优先用 `aisearch person`
1. 从用户问题中提取 keyword(人名/业务关键词)和 dimension(维度),规则见 [aisearch.md](../../dingtalk-aisearch/references/aisearch.md)。
2. `aisearch person --query "<关键词>" --dimension <维度>`
3. 结果中提取 `userId``title`(姓名)展示给用户。
4. 若需要 userId 做后续操作(发消息/建待办),可直接使用结果中的 `userId`
5. **重名消歧**:多人同名时禁止默认选第一个,须追加 `contact user get --ids` 获取部门/职位后请用户确认,详见 [08-directory.md](../../dingtalk-contact/references/08-directory.md)「多命中」。
### search-user
仅在以下**精确查询**场景使用,搜人请优先用 `search-person`
- 需要获取 userId 给其他产品使用(发消息/建待办/约日程)
- 已有 userId 需查完整详情(`contact user get --ids`
1. `aisearch person --query "<姓名>" --dimension name``userId`;**多命中须列出候选请用户确认**。
2. **重名消歧**:多人同名时禁止默认选第一个,须追加 `contact user get --ids` 获取部门/职位后请用户确认,详见 [08-directory.md](../../dingtalk-contact/references/08-directory.md)「多命中」。
3. 需详情时:`contact user get --ids <userId>`(多人可 `--ids id1,id2,...`
@@ -0,0 +1,44 @@
# 业务域通用规范
> 仅服务本 skill 已迁入的行动指南。安全门控、危险操作确认、`--format json` 等已在本 skill 的 `SKILL.md` 中定义,此处不重复。
## 批量查询规范
| # | 规范 |
|---|------|
| 1 | **并行查详情**:拿到多个 ID 后,用 `&` 合并到同一条 Shell 命令并行执行 + `wait`**严禁逐条串行** |
| 2 | **翻页**:分页接口须拉全直至无更多 |
| 3 | **优先批量 API**:有批量接口则用批量;无则按 #1 并行 |
| 4 | **群消息**:必须先 `chat search --query``openConversationId`,再 `chat message list --group <openConversationId> --time "<yyyy-MM-dd HH:mm:ss>" --direction older`;多群同条命令并行 |
| 5 | **列表少轮次**:带条件搜索/列表 → 一次采全详情;**禁止**无新参数时重复同一 `list` / `search` |
## 多源并行采集(公共模式)
> recipe 引用方式:`按「多源并行采集」执行(关键词=<X>,时间=<Y>至<Z>`。
- 同条 Shell`&` 并行 + `wait`;分页须采全。
- 只保留与主题相关的数据,无关丢弃。
- 有批量详情接口优先;否则并行拉详情(见上表 #1)。
- 具体采哪些产品列表由对应 **行动指南 recipe** 与当前产品参考决定;不要引入本文档未覆盖的产品路线。
## 字段术语与 ID 传递
> list 返回 JSON 后,必须提取下表字段传给后续命令。**禁止用其他字段替代。**
| 字段 | 来源 | 传递给 |
|------|------|--------|
| `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 --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` |
| `processInstanceId` | `oa approval list-*` | `oa approval detail/approve --instance-id` |
| `openConversationId` | `chat search` | `chat message list/send --group` |
| `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/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``wiki node --folder` 时,只能使用 `dentryUuid` / `nodeId` / 文档 URL。若当前上下文只有数字型 `dentryId`,必须先重新 `drive list` / `drive search` / `wiki node list` 获取正确 ID,不能把该数字直接代入后续命令。