feat(skills): align Wukong multi-skill docs
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: dingtalk-agoal
|
||||
description: 钉钉 Agoal 目标管理。Use when 用户说 目标管理/Agoal/战略解码/经营合约/计分卡/OKR/目标模板/周月报提交统计/跟催。Distinct from dingtalk-todo(待办任务)、dingtalk-report(日志)。命令前缀:dws agoal。
|
||||
description: 钉钉 Agoal 目标管理与经营目标跟进。Use when 用户说目标管理/战略解码/经营合约/计分卡/用户目标/OKR拆解/更新目标/查看经营合约/目标进展/目标负责人/周月报统计/周报提交情况/跟催/迟交/未提交。Distinct from dingtalk-todo(个人任务待办)、dingtalk-report(日报周报内容)、dingtalk-oa(审批流)。命令前缀:dws agoal。
|
||||
cli_version: ">=0.2.14"
|
||||
metadata:
|
||||
category: product
|
||||
@@ -10,34 +10,32 @@ metadata:
|
||||
- dws
|
||||
---
|
||||
|
||||
# 钉钉 Agoal Skill
|
||||
# 钉钉目标管理 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
> **PREREQUISITE:** Read the `dws-shared` skill first for auth, global flags, product routing, URL preflight, error codes, and safety rules. The `dws` binary must be on PATH.
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> ⚠️ **命令可用性以当前 dws 二进制为准**。服务发现已下线,本文档随内置 skill 发布;如果 `dws <cmd> --help` 不存在,说明当前版本未暴露该命令。若命令存在但调用失败,请按错误中的 endpoint 或 tool 提示确认静态端点目录和后端工具注册。实际调用前可用 `dws <cmd> --help` 或 `--dry-run` 验证。
|
||||
|
||||
> 命令参考:[agoal.md](references/agoal.md)。
|
||||
|
||||
## 意图表
|
||||
|
||||
| 用户说 | 命令 |
|
||||
|--------|------|
|
||||
| "查战略解码 / OGSM" | `dws agoal strategy list --scope-type <DEPT|PERSONAL> --scope-id <ID>` |
|
||||
| "看战略解码详情" | `dws agoal strategy detail --profile-id <PROFILE_ID>` |
|
||||
| "更新战略解码" | 先 detail,基于完整数据修改后 `dws agoal strategy update ...` |
|
||||
| "查经营合约 / KPI合约" | `dws agoal contract list/detail/fields` |
|
||||
| "更新经营合约" | 先 detail,基于完整 dimensions 修改后 `dws agoal contract update ...` |
|
||||
| "查计分卡" | `dws agoal scorecard detail --selected-time <ISO> --dept-id <DEPT_ID>` |
|
||||
| "我的目标 / 个人目标" | `dws agoal user rules` → `dws agoal user objectives` |
|
||||
| "周月报提交统计 / 跟催 / 迟交 / 未提交" | `dws agoal report list-statistics` → `dws agoal report submit-detail` |
|
||||
| "目标模板" | `dws agoal obj-template list/create-or-update` |
|
||||
| "查战略解码 / 战略列表" | `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` / `obj-template create-or-update` 都是覆盖式写入。
|
||||
- 必须先读取现有详情或模板列表,在原数据基础上修改;禁止只传局部字段覆盖。
|
||||
- 执行前必须向用户展示目标对象、修改字段和最终命令参数摘要,并等待确认。
|
||||
- `strategy update`、`contract update`、`scorecard update` 都是覆盖式更新,必须先查询详情,在返回数据基础上修改后再提交。
|
||||
- 所有命令带 `--format json`;涉及写操作时回查确认。
|
||||
|
||||
@@ -14,64 +14,260 @@ Agoal 是钉钉目标管理工具,支持战略解码、经营合约、计分
|
||||
|------|------|----------|------|
|
||||
| `strategy list` | 获取战略解码列表 | `--scope-type` `--scope-id` | scopeType: DEPT/PERSONAL;scope-id 为 scope-type 对应的部门 id 或用户 id |
|
||||
| `strategy detail` | 获取战略解码详情 | `--profile-id` | 根据战略解码 id 查询 |
|
||||
| `strategy update` | 更新战略解码 | `--profile-id` `--content` | 覆盖逻辑,必须基于查询返回的老数据修改后再传入;`--content` 为 JSON 数组 |
|
||||
| `strategy update` | 更新战略解码 | `--profile-id` `--content` | **覆盖逻辑,必须基于查询返回的老数据修改后再传入**;`--content` 为 JSON 数组 |
|
||||
|
||||
> **`strategy update` 是覆盖式更新**:一定要先 `strategy detail` 获取完整数据,在原数据基础上修改后再传入,会根据战略解码id进行对应的修改。
|
||||
|
||||
#### strategy update --content 实体字段说明
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `id` | 实体 id |
|
||||
| `title` | 标题对象,如 `{"title":"标题文本"}` |
|
||||
| `linkEntityId` | 所属实体 ID(查询接口中有值时必须回传) |
|
||||
| `entityType` | 类型枚举:`OGSM_OBJECTIVE`(目的)、`OGSM_GOAL`(目标)、`OGSM_STRATEGY`(策略)、`OGSM_MEASUREMENT`(衡量标准)、`OGSM_TACTICS`(行动方案) |
|
||||
| `status` | 状态枚举:`NORMAL`(正常)、`PRE_PUBLISH_THEN_UPDATE`(预发布更新)、`PRE_PUBLISH_THEN_CREATE`(预发布新增)、`PRE_PUBLISH_THEN_DELETE`(预发布删除) |
|
||||
| `supporters` | 承接人数组 `[{type, dingId, staffId}]`;type: `USER`/`DEPARTMENT`;staffId 在 type=USER 时必填 |
|
||||
| `indicators` | 关键指标 id 字符串数组 |
|
||||
| `linkSources` | 资源关联数组 `[{id, linkType, linkId, source, objectId, keyResultId}]`;linkType: project/task/campaign/product/doc/standard;source: teambition |
|
||||
| `executors` | 人员 dingId 字符串数组 |
|
||||
| `teams` | 部门 dingId 字符串数组 |
|
||||
|
||||
### contract (经营合约管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 备注 |
|
||||
|------|------|----------|------|
|
||||
| `contract list` | 获取经营合约列表 | `--scope-type` `--scope-id` | scopeType: DEPT/PERSONAL;scope-id 为 scope-type 对应的部门 id 或用户 id |
|
||||
| `contract fields` | 获取经营合约字段列表 | - | 获取组织下经营合约的字段配置 |
|
||||
| `contract fields` | 获取经营合约字段列表 | — | 获取组织下经营合约的字段配置 |
|
||||
| `contract detail` | 获取经营合约详情 | `--contract-id` | 根据合约 id 查询 |
|
||||
| `contract update` | 更新经营合约 | `--contract-id` `--dimensions` | 覆盖逻辑;可选 `--audit-config`、`--objective-template` |
|
||||
| `contract update` | 更新经营合约 | `--contract-id` `--dimensions` | **覆盖逻辑**;可选 `--audit-config`、`--objective-template` |
|
||||
|
||||
> **`contract update` 同样是覆盖式更新**:必须基于 `contract detail` 返回的数据修改后再传入。
|
||||
|
||||
#### contract update --dimensions 维度字段说明
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `id` | 维度 id |
|
||||
| `title` | 维度名称 |
|
||||
| `description` | 维度描述 |
|
||||
| `weight` | 维度权重 |
|
||||
| `objectives` | 目标列表 |
|
||||
| `dimensionConfig` | 维度配置 |
|
||||
| `children` | 子维度列表 |
|
||||
|
||||
#### contract update 可选参数
|
||||
|
||||
| 参数 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| `--audit-config` | 审批配置 JSON | `{"needAudit":true,"processTemplateId":"TPL_ID"}` |
|
||||
| `--objective-template` | 合约模板 JSON | `{"id":"TPL_ID","title":"模板名称"}` |
|
||||
|
||||
### scorecard (计分卡管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 备注 |
|
||||
|------|------|----------|------|
|
||||
| `scorecard detail` | 获取计分卡详情 | `--selected-time` `--dept-id` | selectedTime 为 ISO-8601 字符串 |
|
||||
| `scorecard detail` | 获取计分卡详情 | `--selected-time` `--dept-id` | selectedTime 为 ISO-8601 字符串,如 `"2026-01-01T00:00:00+08:00"` |
|
||||
| `scorecard entity-detail` | 获取计分卡实体详情 | `--sc-id` `--entity-id` | 根据计分卡 id 和实体 id 查询 |
|
||||
| `scorecard update` | 更新计分卡 | `--dept-id` `--selected-time` `--id` `--tracking-period-type` `--content` | trackingPeriodType: MONTHLY/QUARTERLY |
|
||||
|
||||
### user / report / obj-template
|
||||
#### selectedTime 时间说明
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `user rules` | 获取用户规则周期列表 | - |
|
||||
| `user objectives` | 查询用户目标列表 | `--user-id` `--rule-id` `--period-ids` |
|
||||
| `report list-statistics` | 获取周月报数据跟催列表 | - |
|
||||
| `report submit-detail` | 获取周月报规则提交详情 | `--template-id` `--submit-state` |
|
||||
| `obj-template list` | 获取目标模板列表 | - |
|
||||
| `obj-template create-or-update` | 新增或更新目标模板 | `--dimensions` |
|
||||
`--selected-time` 接受 ISO-8601 字符串,传入对应周期起始时刻:
|
||||
|
||||
- **2026年** → `"2026-01-01T00:00:00+08:00"`
|
||||
- **2026年5月** → `"2026-05-01T00:00:00+08:00"`
|
||||
|
||||
#### scorecard update --content 维度字段说明
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `id` | 维度 id |
|
||||
| `title` | 维度名称 |
|
||||
| `items` | 指标或关键事项列表 |
|
||||
|
||||
items 每项包含:
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `id` | 实体 id |
|
||||
| `title` | 名称 |
|
||||
| `reference` | 参考信息 |
|
||||
| `start` | 起始值 |
|
||||
| `target` | 目标值 |
|
||||
| `executors` | 负责人列表,每项包含 `openId` |
|
||||
|
||||
#### trackingPeriodType 枚举
|
||||
|
||||
| 值 | 说明 |
|
||||
|------|------|
|
||||
| `MONTHLY` | 月度追踪 |
|
||||
| `QUARTERLY` | 季度追踪 |
|
||||
|
||||
### user (用户目标管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 备注 |
|
||||
|------|------|----------|------|
|
||||
| `user rules` | 获取用户规则周期列表 | — | 可选 `--user-id`,不传则默认取操作人自己 |
|
||||
| `user objectives` | 查询用户目标列表 | `--user-id` `--rule-id` `--period-ids` | `--period-ids` 为逗号分隔的周期 id 列表 |
|
||||
|
||||
### obj-template (目标模板管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 备注 |
|
||||
|------|------|----------|------|
|
||||
| `obj-template list` | 获取目标模板列表 | — | 可选 `--keyword` 搜索关键词、`--page` 页码、`--page-size` 每页数量 |
|
||||
| `obj-template create-or-update` | 新增或更新目标模板 | `--dimensions` | **覆盖逻辑**;新增时 `--title` 必填;更新时 `--template-id` 必填,dimensions 必须基于老数据修改 |
|
||||
|
||||
> **`obj-template create-or-update` 同样是覆盖式更新**:更新时必须基于 `obj-template list` 返回的数据修改后再传入。新增时建议先参考已存在的模板数据再构建 dimensions。
|
||||
|
||||
#### obj-template create-or-update 参数说明
|
||||
|
||||
| 参数 | 说明 | 类型 |
|
||||
|------|------|------|
|
||||
| `--template-id` | 模板 id(更新时必填) | string |
|
||||
| `--title` | 模板标题(新增时必填) | string |
|
||||
| `--objective-weight` | 是否启用目标权重 | bool |
|
||||
| `--dimension-weight` | 是否启用维度权重 | bool |
|
||||
| `--compute-by-weight` | 维度是否参与计算 | bool |
|
||||
| `--dimensions` | 模板关联的维度 JSON 字符串 | string |
|
||||
|
||||
### report (周月报管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 备注 |
|
||||
|------|------|----------|------|
|
||||
| `report list-statistics` | 获取周月报数据跟催列表 | — | 返回各规则的人员提交情况统计(按时/迟交/未提交人数);可选 `--keyword` 搜索规则名称 |
|
||||
| `report submit-detail` | 获取周月报规则提交详情 | `--template-id` `--submit-state` | submitState: `ON_TIME`(按时)/`LATE`(迟交)/`NOT_SUBMITTED`(未提交);可选 `--query-date`(ISO-8601)、`--page`、`--page-size`、`--keyword`(搜索员工名称) |
|
||||
|
||||
#### report submit-detail --submit-state 枚举
|
||||
|
||||
| 值 | 说明 |
|
||||
|------|------|
|
||||
| `ON_TIME` | 按时提交 |
|
||||
| `LATE` | 迟交 |
|
||||
| `NOT_SUBMITTED` | 未提交 |
|
||||
|
||||
## 意图判断
|
||||
|
||||
- "战略解码/战略目标/OGSM" → `strategy list/detail/update`
|
||||
- "经营合约/合约/KPI合约" → `contract list/fields/detail/update`
|
||||
- "计分卡/scorecard/绩效看板" → `scorecard detail/entity-detail/update`
|
||||
- "目标/OKR/我的目标/个人目标" → `user rules/objectives`
|
||||
- "目标模板/模板管理" → `obj-template list/create-or-update`
|
||||
- "周月报/周报统计/提交情况/跟催/迟交/未提交" → `report list-statistics/submit-detail`
|
||||
用户说"战略解码/战略目标/OGSM":
|
||||
- 查看/列表 → `strategy list`
|
||||
- 详情 → `strategy detail`
|
||||
- 修改/更新 → `strategy update`(先查后改)
|
||||
|
||||
## 常用命令
|
||||
用户说"经营合约/合约/KPI合约":
|
||||
- 查看/列表 → `contract list`
|
||||
- 字段配置 → `contract fields`
|
||||
- 详情 → `contract detail`
|
||||
- 修改/更新 → `contract update`(先查后改)
|
||||
|
||||
用户说"计分卡/scorecard/绩效看板":
|
||||
- 查看详情 → `scorecard detail`
|
||||
- 实体详情 → `scorecard entity-detail`
|
||||
- 修改/更新 → `scorecard update`
|
||||
|
||||
用户说"目标/OKR/我的目标/个人目标":
|
||||
- 规则周期 → `user rules`
|
||||
- 目标列表 → `user objectives`
|
||||
|
||||
用户说"目标模板/模板管理":
|
||||
- 查看模板列表 → `obj-template list`
|
||||
- 新增模板 → `obj-template create-or-update --title "模板名称"`
|
||||
- 更新模板 → `obj-template create-or-update --template-id TPL_ID`
|
||||
|
||||
用户说"周月报/周报统计/提交情况/跟催/迟交/未提交":
|
||||
- 查看提交统计列表 → `report list-statistics`
|
||||
- 查看某规则的提交详情(按时/迟交/未提交人员明细) → `report submit-detail`
|
||||
|
||||
## 核心工作流
|
||||
|
||||
```bash
|
||||
dws agoal strategy list --scope-type DEPT --scope-id DEPT_ID --format json
|
||||
dws agoal strategy detail --profile-id PROFILE_ID --format json
|
||||
dws agoal contract list --scope-type PERSONAL --scope-id USER_ID --format json
|
||||
dws agoal contract fields --format json
|
||||
dws agoal contract detail --contract-id CONTRACT_ID --format json
|
||||
dws agoal scorecard detail --selected-time "2026-01-01T00:00:00+08:00" --dept-id DEPT_ID --format json
|
||||
dws agoal user rules --user-id USER_ID --format json
|
||||
dws agoal user objectives --user-id USER_ID --rule-id RULE_ID --period-ids "period1,period2" --format json
|
||||
dws agoal report list-statistics --format json
|
||||
dws agoal report submit-detail --template-id TPL_ID --submit-state ON_TIME --format json
|
||||
dws agoal obj-template list --keyword "业绩" --format json
|
||||
# 1. 查看战略解码列表(按部门)
|
||||
dws agoal strategy list --scope-type DEPT --scope-id DEPT_ID
|
||||
|
||||
# 1.1 查看战略解码列表(按个人)
|
||||
dws agoal strategy list --scope-type PERSONAL --scope-id USER_ID
|
||||
|
||||
# 2. 查看战略解码详情
|
||||
dws agoal strategy detail --profile-id PROFILE_ID
|
||||
|
||||
# 3. 更新战略解码(基于详情返回的数据修改后传入)
|
||||
dws agoal strategy update --profile-id PROFILE_ID \
|
||||
--content '[{"id":"entity1","title":{"title":"新目标"},"entityType":"OGSM_OBJECTIVE","status":"NORMAL","executors":["dingId1"]}]'
|
||||
|
||||
# 4. 查看经营合约列表(按个人)
|
||||
dws agoal contract list --scope-type PERSONAL --scope-id USER_ID
|
||||
|
||||
# 4.1 查看经营合约列表(按部门)
|
||||
dws agoal contract list --scope-type DEPT --scope-id DEPT_ID
|
||||
|
||||
# 5. 查看经营合约字段列表
|
||||
dws agoal contract fields
|
||||
|
||||
# 6. 查看经营合约详情
|
||||
dws agoal contract detail --contract-id CONTRACT_ID
|
||||
|
||||
# 7 更新经营合约(基于详情返回的数据修改后传入)
|
||||
dws agoal contract update --contract-id CONTRACT_ID \
|
||||
--dimensions '[{"id":"dim1","title":"维度名称","objectives":[...]}]'
|
||||
|
||||
# 8. 查看计分卡详情
|
||||
dws agoal scorecard detail --selected-time "2025-01-01T00:00:00+08:00" --dept-id DEPT_ID
|
||||
|
||||
# 9. 查看计分卡实体详情
|
||||
dws agoal scorecard entity-detail --sc-id SC_ID --entity-id ENTITY_ID
|
||||
|
||||
# 10. 更新计分卡
|
||||
dws agoal scorecard update --dept-id DEPT_ID --selected-time "2025-01-01T00:00:00+08:00" --id SC_ID --tracking-period-type MONTHLY --content '[{"id":"dim1","title":"业绩","items":[{"id":"item1","title":"收入","target":"100"}]}]'
|
||||
|
||||
# 11. 查看用户规则 → 提取 ruleId 和 periodId
|
||||
dws agoal user rules --user-id USER_ID
|
||||
|
||||
# 12. 查看用户目标
|
||||
dws agoal user objectives --user-id USER_ID --rule-id RULE_ID --period-ids "period1,period2"
|
||||
|
||||
# 13. 查看周月报提交统计列表
|
||||
dws agoal report list-statistics
|
||||
|
||||
# 13.1 按关键词搜索规则
|
||||
dws agoal report list-statistics --keyword "周报规则"
|
||||
|
||||
# 14. 查看某规则的按时提交详情
|
||||
dws agoal report submit-detail --template-id TPL_ID --submit-state ON_TIME
|
||||
|
||||
# 14.1 查看迟交详情(带分页和日期)
|
||||
dws agoal report submit-detail --template-id TPL_ID --submit-state LATE --query-date "2026-06-18T00:00:00+08:00" --page 1 --page-size 20
|
||||
|
||||
# 15. 获取目标模板列表
|
||||
dws agoal obj-template list
|
||||
|
||||
# 15.1 搜索目标模板
|
||||
dws agoal obj-template list --keyword "业绩"
|
||||
|
||||
# 16. 新增目标模板
|
||||
dws agoal obj-template create-or-update --title "业绩模板" --objective-weight --dimension-weight --dimensions '[...]'
|
||||
|
||||
# 16.1 更新目标模板
|
||||
dws agoal obj-template create-or-update --template-id TPL_ID --title "业绩模板" --dimensions '[...]'
|
||||
```
|
||||
|
||||
## 安全规则
|
||||
## 上下文传递表
|
||||
|
||||
- 所有 update / create-or-update 命令都是覆盖逻辑:必须先用对应 detail/list 查询完整数据,在原数据基础上修改后再传入。
|
||||
- 写入类命令执行前必须展示变更摘要并等待用户确认。
|
||||
- `--selected-time` / `--query-date` 接受 ISO-8601 字符串。
|
||||
- `--period-ids` 为逗号分隔字符串。
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `strategy list` | `profileId` | `strategy detail` / `strategy update` 的 `--profile-id` |
|
||||
| `strategy detail` | 完整实体数据 | `strategy update` 的 `--content`(基于此修改) |
|
||||
| `contract list` | `contractId` | `contract detail` / `contract update` 的 `--contract-id` |
|
||||
| `contract detail` | 完整维度数据 | `contract update` 的 `--dimensions`(基于此修改) |
|
||||
| `scorecard detail` | `scId`、`entityId` | `scorecard entity-detail` / `scorecard update` 的 `--id` |
|
||||
| `user rules` | `ruleId`、`periodIds` | `user objectives` 的 `--rule-id` `--period-ids` |
|
||||
| `report list-statistics` | `templateId`(列表项中) | `report submit-detail` 的 `--template-id` |
|
||||
| `obj-template list` | `templateId` | `obj-template create-or-update` 的 `--template-id`(更新时) |
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **所有 update 命令都是覆盖逻辑**:必须先用对应的 detail/list 查询到完整数据,在原数据基础上修改后再传入,否则未传入的数据会被删除
|
||||
- 所有命令支持可选参数 `--request-id`
|
||||
- `--scope-type` 仅支持 `DEPT`(按部门)和 `PERSONAL`(按个人)两种
|
||||
- `--selected-time` 接受 ISO-8601 字符串(如 `"2026-01-01T00:00:00+08:00"`)
|
||||
- `--period-ids` 为逗号分隔的字符串,如 `"period1,period2"`
|
||||
- `report submit-detail` 的 `--query-date` 接受 ISO-8601 字符串(如 `"2026-06-18T00:00:00+08:00"`),不传则默认当天
|
||||
- `report submit-detail` 的 `--page` 和 `--page-size` 默认为 1 和 10,不传时由服务端使用默认值
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: dingtalk-aisearch
|
||||
description: AI 搜问 - 搜人首选入口(按姓名/部门/职位/职责/上下级/手机号/工号维度)。Use when 用户说 找同事/找人/谁负责XX/XX的负责人是谁/查上级/查下级/团队成员/XX工号是谁/XX手机号。Distinct from dingtalk-contact(精确按 userId 查详情)。命令前缀:dws aisearch。
|
||||
description: AI 搜问——跨源语义检索/发现(只做找到/定位,不做读写;具体读写各归 doc/report/mail/contact)。Use when 找同事/谁负责/查上下级/查工号手机号、跨文档消息邮件听记的内容检索、"我发过/收到过"行为回溯。模糊找人拿 userId 后精确查走 dingtalk-contact。命令前缀:dws aisearch。
|
||||
cli_version: ">=0.2.14"
|
||||
metadata:
|
||||
category: product
|
||||
@@ -10,17 +10,16 @@ metadata:
|
||||
- dws
|
||||
---
|
||||
|
||||
# 钉钉 AI 搜问(搜人)Skill
|
||||
# 钉钉 AI 搜问 Skill
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
> **PREREQUISITE:** Read the `dws-shared` skill first for auth, global flags, product routing, URL preflight, error codes, and safety rules. The `dws` binary must be on PATH.
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> ⚠️ **命令可用性以当前 dws 二进制为准**。服务发现已下线,本文档随内置 skill 发布;如果 `dws <cmd> --help` 不存在,说明当前版本未暴露该命令。若命令存在但调用失败,请按错误中的 endpoint 或 tool 提示确认静态端点目录和后端工具注册。实际调用前可用 `dws <cmd> --help` 或 `--dry-run` 验证。
|
||||
|
||||
|
||||
> 命令参考:[aisearch.md](references/aisearch.md)。
|
||||
|
||||
## 意图表
|
||||
@@ -32,8 +31,44 @@ metadata:
|
||||
| "张三的上级 / 下级" | `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` |
|
||||
| "最近 OKR 相关邮件 / 项目相关文档" | `dws aisearch enterprise --queries "<主题>" --types mail/document --time-range "<时间>"` |
|
||||
| "我发过/创建过/分享过/收到过什么" | `dws aisearch behavior --queries "<主题>" --behavior-type <动作> --direction <方向>` |
|
||||
|
||||
## 评测高频硬约束
|
||||
## 标准 SOP(必遵流程)
|
||||
|
||||
> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 flag/ID。每条命令必须带 `--format json`,执行后必须按"解析"步取真实字段,不得凭返回结构猜测。
|
||||
|
||||
### SOP-1 搜人 → 拿 userId(search-person)
|
||||
|
||||
**触发**:找人/谁负责/查上下级/部门成员/工号或手机号反查。
|
||||
|
||||
1. **定维度(必须)**:姓名→`name`、"谁负责 XX"→`duty`、部门成员→`department`、上级/下级→`supervisor`/`subordinate`、工号→`jobNumber`、手机号→`phone`;不确定→`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`。
|
||||
5. **失败(必须)**:未命中最多换 1 个维度重试一次(如 `name`→`department`/`jobNumber`/`phone`),仍保留完整目标值;仍无果**必须如实告知**。
|
||||
|
||||
**禁止**:用半截姓名扩大搜索、跳过 `--format json`、取首个候选、凭空补全人员信息。
|
||||
|
||||
### SOP-2 跨源搜内容(search-content)
|
||||
|
||||
**触发**:跨文档/邮件/消息按主题找内容。
|
||||
|
||||
1. **执行(必须)**:`dws aisearch enterprise --queries "<主题>" --types <document,mail,...> --time-range "<时间>" --format json`;多主题逗号分隔。
|
||||
2. **衔接(必须)**:按命中来源切下游读写——文档→`dingtalk-doc`、邮件→`dingtalk-mail`、消息→`dingtalk-chat`。**aisearch 只负责"找到",不做读写。**
|
||||
|
||||
**禁止**:把 aisearch 当作读写入口、跳过下游 skill 直接改数据。
|
||||
|
||||
### SOP-3 行为回溯(search-behavior)
|
||||
|
||||
**触发**:"我发过/收到过/创建过/分享过什么"。
|
||||
|
||||
1. **执行(必须)**:`dws aisearch behavior --queries "<主题>" --behavior-type <动作> --direction <方向> --format json`。
|
||||
2. **衔接(必须)**:按记录类型切对应 skill 操作;aisearch 不做读写。
|
||||
|
||||
**禁止**:编造行为结果、跳过 `--format json`。
|
||||
|
||||
## 高频硬约束
|
||||
|
||||
- 搜索目标必须完整保真:姓名、工号、手机号、部门名按用户原文完整传入 `--keyword`,严禁自行截断、拆字、改昵称或扩展同音字。
|
||||
- 首次未命中时最多换维度重试一次(如 name → department/jobNumber/phone),仍必须保留完整目标值;不要用半截姓名扩大搜索。
|
||||
@@ -46,3 +81,6 @@ metadata:
|
||||
- 拿到 userId 后查详情 / 部门 → 切到 `dingtalk-contact`
|
||||
- 拿到 userId 发消息 → 切到 `dingtalk-chat`
|
||||
- 拿到 userId 发 DING → 切到 `dingtalk-ding`
|
||||
## 局部意图与 Recipe
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md);[Lite Recipe](references/lite-recipes.md)。
|
||||
|
||||
@@ -98,7 +98,7 @@ Flags:
|
||||
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `aisearch person` | `userId`(用户ID,= `meta.staffId`/`meta.jobNumber`)、`author`(真实姓名,= `meta.name`);`title` 是花名/显示名,不一定等于姓名 | 展示搜索结果、后续操作(发消息/建待办等) |
|
||||
| `aisearch person` | `userId`(用户ID)、`title`(姓名) | 展示搜索结果、后续操作(发消息/建待办等) |
|
||||
|
||||
## 重名消歧
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# aisearch 局部意图消歧
|
||||
|
||||
本文件从单 Skill `intent-guide.md` 拆分而来,仅保留与本产品相关的跨产品消歧规则。
|
||||
|
||||
| 用户说... | 真实意图 | 应该用 | 不要用 | 理由 |
|
||||
|---|---|---|---|---|
|
||||
| "张三在哪个部门/查一下同事工号" | 通讯录精确查询 | #8 `contact` | #5 汇报 / #4 文档 | 需要 userId、手机号、部门 ID 等精确信息时用 contact |
|
||||
| "找一下张三/搜同事/找人" | AI搜人(首选) | `aisearch person` | `contact user search` | 搜人首选 aisearch,支持姓名/部门/职责/上下级维度;精确查 userId/手机号用 contact |
|
||||
| "五道的上级是谁/谁负责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 |
|
||||
| "搜一下智能化方案/最近 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` | 纯文本翻译,不是文档编辑或语义搜索 |
|
||||
@@ -0,0 +1,30 @@
|
||||
# aisearch Lite Recipe
|
||||
|
||||
本文件从单 Skill `lite-recipes.md` 拆分而来,仅保留与本产品相关的轻量流程。
|
||||
|
||||
## #8 通讯录
|
||||
|
||||
### get-contact-self
|
||||
|
||||
`contact user get-self` → 当前用户 userId、部门、主管等
|
||||
|
||||
### search-person
|
||||
|
||||
**搜人首选入口**。凡是“找人/搜人/找同事/谁负责/上级/下级/负责人/团队成员”均优先用 `aisearch person`:
|
||||
|
||||
1. 从用户问题中提取 keyword(人名/业务关键词)和 dimension(维度),规则见 [aisearch.md](./aisearch.md)。
|
||||
2. `aisearch person --keyword "<关键词>" --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 --keyword "<姓名>" --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,...`)
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: dingtalk-aitable
|
||||
description: 钉钉 AI 表格(多维表)。Use when 用户说 AI表格/多维表/数据表/base/table/建表/查记录/写数据/字段/记录增删改查/筛选/排序/公式/模板搜索/批量导入CSV或JSON/导出/仪表盘/图表/上传附件到表格/按字段类型建表。Distinct from 主 dws skill 的 dws sheet(电子表格/单元格读写/公式)、dws doc(文档编辑)。命令前缀:dws 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"
|
||||
metadata:
|
||||
category: product
|
||||
@@ -14,14 +14,14 @@ metadata:
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
> **PREREQUISITE:** Read the root `dws` skill first for auth, global flags, product routing, URL preflight, error codes, and safety rules. The `dws` binary must be on PATH.
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> ⚠️ **命令可用性以当前 dws 二进制为准**。服务发现已下线,本文档随内置 skill 发布;如果 `dws <cmd> --help` 不存在,说明当前版本未暴露该命令。若命令存在但调用失败,请按错误中的 endpoint 或 tool 提示确认静态端点目录和后端工具注册。实际调用前可用 `dws <cmd> --help` 或 `--dry-run` 验证。
|
||||
|
||||
|
||||
> 命令参考:[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)。
|
||||
|
||||
## 意图表
|
||||
|
||||
@@ -40,13 +40,76 @@ metadata:
|
||||
| "仪表盘 / 图表" | 先读 `references/aitable/aitable-dashboard-chart.md` |
|
||||
| "上传附件到记录" | 先读 `references/aitable/aitable-attachment.md`;可用 `python scripts/upload_attachment.py --base-id <id> --file <path>` |
|
||||
|
||||
## 标准 SOP(必遵流程)
|
||||
|
||||
> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 flag/ID。每条命令必须带 `--format json`,执行后必须按"解析"步取真实字段,不得凭返回结构猜测。`baseId`/`tableId`/`fieldId`/`recordId` 一律先查后用,**禁止默认/编造**。
|
||||
|
||||
### SOP-1 定位 Base 与 Table(list / search → table get)
|
||||
|
||||
**触发**:找/打开某张 AI 表格、不知 baseId 或 tableId。
|
||||
|
||||
1. **选源(必须)**:有名称/关键词 → `dws aitable base search --query "<名称>"`;列最近访问 → `dws aitable base list`。`base list` 仅返回最近访问,不是全部,**禁止**当作全量清单。
|
||||
2. **执行(必须)**:`dws aitable base search --query "<完整名>" --format json`(或 `dws aitable base list --format json`)。
|
||||
3. **解析(必须)**:从 JSON 取真实 `baseId`;**多候选必须输出让用户选,禁止默认取第一个**。
|
||||
4. **取 tableId(必须)**:`dws aitable table get --base-id <baseId> --format json` → 从 `tables[].tableId` 取目标表 ID,连同该表 `fields[]` 的 `fieldId/fieldName/type` 与 `views[]` 的 `viewId` 一并记下。
|
||||
5. **失败(必须)**:`base list` 为空或不命中 → 换 `base search --query` 关键词重试一次;仍无果**必须如实告知**,禁止臆造 baseId/tableId。
|
||||
|
||||
**禁止**:跳过 `table get` 直接用字段名写记录、用模糊名匹配当 baseId、用旧会话里的 ID 不再校验。
|
||||
|
||||
### SOP-2 拿字段定义(field get,写记录/改字段前置)
|
||||
|
||||
**触发**:建/改/写记录、改字段名或 options、按字段类型拼写入参前。
|
||||
|
||||
1. **前置(必须)**:先按 SOP-1 拿到 `baseId` + `tableId`。
|
||||
2. **执行(必须)**:`dws aitable field get --base-id <baseId> --table-id <tableId> --format json`(仅展开需要的字段时加 `--field-ids fld1,fld2`,单次最多 10 个)。
|
||||
3. **解析(必须)**:取每个目标字段的 `fieldId`、`type`、`config`(如 singleSelect/multipleSelect 的 `options[].id|name`);写入 cells 的 key **必须用 `fieldId`**,不是字段中文名;select 字段过滤/写入传**选项名称字面量**,不传 option ID。
|
||||
4. **衔接(必须)**:拿到字段定义 → 进入 SOP-3 写记录、或 `dws aitable field update --field-id <fieldId> --name <新名>|--config <JSON> --format json` 改字段。
|
||||
5. **失败(必须)**:字段不存在或类型不符 → 重新 `field get` 核对,**禁止**凭旧名称/旧类型继续写入。
|
||||
|
||||
**禁止**:用字段中文名当 cells key、跳过 `field get` 直接 `record create/update`、对 select 字段传 option ID 当写入值。
|
||||
|
||||
### SOP-3 写/批量写记录(record create)
|
||||
|
||||
**触发**:新增记录、批量加数据、CSV/JSON 入表。
|
||||
|
||||
1. **前置(必须)**:SOP-1 取 `baseId`/`tableId` + SOP-2 取 `fieldId`/类型。
|
||||
2. **执行(必须)**:`dws aitable record create --base-id <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**,禁止继续按原名称猜。
|
||||
5. **失败(必须)**:类型/格式错误按返回报错修正后重试,**禁止**降级丢弃字段;不确定格式先 `field get` 复核 config。
|
||||
|
||||
**禁止**:编造 fieldId/recordId、跳过 `field get` 凭中文名写、把 URL 字符串直接塞给 url 字段。
|
||||
|
||||
### SOP-4 查/筛/排记录(record query)
|
||||
|
||||
**触发**:查记录、按条件筛选、排序、取关联记录、定位待改/待删的 recordId。
|
||||
|
||||
1. **前置(必须)**:SOP-1 拿 `baseId`/`tableId`。
|
||||
2. **执行(必须)**:`dws aitable record query --base-id <baseId> --table-id <tableId> --format json`;已知 ID 直取加 `--record-ids rec1,rec2`(忽略 filters/sort,单次≤100)。
|
||||
3. **筛选/排序(必须)**:`--filters` 最外层必须 `{"operator":"and|or","operands":[...]}`,select 字段值传**选项名字面量**;日期只能用 `date_eq/before/after/not_before/not_after`,范围用 `not_before`+`not_after` 组合,**禁止** `eq`/区间/相对时间。`--sort` 用 `[{"fieldId":"..","direction":"asc|desc"}]`(**必须用 `direction`**)。公式/引用/关联字段默认不返回,需显式 `--field-ids` 指定。
|
||||
4. **解析(必须)**:取真实 `recordId` 与字段值;分页用 `--cursor`,全表用 `--all --page-limit N`。
|
||||
5. **衔接(必须)**:拿到 recordId → SOP-5 更新、`record delete --record-ids --yes` 删除(删前确认)。
|
||||
|
||||
**禁止**:用字段名做 filter/sort key、对日期用 `eq`、漏掉 `direction` 用旧 `order` 字段、用本地过滤替代服务端 filter。
|
||||
|
||||
### SOP-5 更新记录(record update)
|
||||
|
||||
**触发**:改记录字段值、批量更新状态、单字段重命名需求之外的记录改动。
|
||||
|
||||
1. **前置(必须)**:SOP-1 拿 `baseId`/`tableId`;SOP-2 拿字段类型;SOP-4 拿目标 `recordId`。
|
||||
2. **执行(必须)**:`dws aitable record update --base-id <baseId> --table-id <tableId> --records '[{"recordId":"recXXX","cells":{"<fieldId>":<新值>}}]' --format json`(每条必含 `recordId`+`cells`,单次≤100;超长用 `--records-file`);只传需改字段,未传保持原值。
|
||||
3. **解析(必须)**:写入格式同 SOP-3;返回核对真实 recordId 与受影响字段。
|
||||
4. **失败(必须)**:recordId 不存在或类型不符 → 回 SOP-4 重新定位,**禁止**编造 ID 强写。
|
||||
|
||||
**禁止**:省略 `recordId`、用字段中文名当 cells key、凭空猜测 recordId 直接 update。
|
||||
|
||||
## 危险操作
|
||||
|
||||
`base delete` / `table delete` / `field delete` / `record delete` 不可逆,必须先向用户确认再加 `--yes`。
|
||||
|
||||
## 评测高频硬约束
|
||||
## 高频硬约束
|
||||
|
||||
- 创建/改字段/写记录是多轮连续任务时,不能在"让我执行/先获取 ID"后停下;必须实际调用对应 `dws aitable` 命令并验证结果。
|
||||
- 创建 Base、改字段或写记录时,固定按“获取真实 ID → 执行写命令 → 回读验证”顺序完成,禁止跳过任一步。
|
||||
- 字段重命名使用 `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`,不要继续按原名称猜。
|
||||
@@ -59,4 +122,7 @@ metadata:
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
- 单元格 / 工作表 / 公式 → 走主 `dws` skill 的 `sheet` 产品路由(`dws sheet`)
|
||||
- 单元格 / 工作表 / 公式 → 切到 `dingtalk-sheet`(命令前缀:`dws sheet`)
|
||||
## 局部意图与 Recipe
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md)。
|
||||
|
||||
@@ -4,10 +4,8 @@
|
||||
|
||||
| Recipe | 行动指南(固定路线) |
|
||||
|--------|-------------------|
|
||||
| read-aitable | 1. `aitable base search --query "<表格名>"` → 取 `baseId`/`tableId`<br>2. `aitable field get --base-id <baseId> --table-id <tableId>` → 取 `fieldId`<br>3. **取记录(按场景分流)**:<br> • 数据统计/分析/全量汇总 → `aitable record query --base-id <baseId> --table-id <tableId> --all`(自动翻页,**禁止凭单页数据做统计**)<br> • 大表保险 → 加 `--page-limit 100`(默认 50 页/5000 条,0 = 无限制)<br> • 单纯预览前几条 → `aitable record query --base-id <baseId> --table-id <tableId> --limit 30`(不加 --all)<br> • 筛选时 `--filters` 格式见 [aitable-filter-sort.md](../products/aitable/aitable-filter-sort.md)<br>4. **检查输出契约**:`hasMore=true` 时数据被截断,必须用 `--cursor <X>` 续拉;`partial=true` 时表示中途某页失败(保留已拉数据,可重试)<br>5. 总结数据 |
|
||||
| generate-data-report | 1. 同 read-aitable 步骤 1-3(**必须用 --all 防漏数据**)<br>2. 按[「多源并行采集」](_common/conventions.md#多源并行采集公共模式)执行 → 补充背景<br>3. `doc create --name "<报告名>" --content "<分析报告>"` |
|
||||
| create-aitable-record | **写入路径分流**(关键决策):<br> • **追加到已有表**(场景:把这批数据加到「成员表」)→ `python scripts/import_records.py <baseId> <tableId> data.csv\|data.json [batch_size]`(走 `record create`,需要列名匹配字段名)<br> • **新建表**(场景:把这个 Excel 变成多维表)→ `python scripts/aitable_import_via_task.py <baseId> <file>`(脚本内置 prepare→OSS PUT→import data 全流程和正确的头处理,**禁止自己写 PUT**)。注意 `aitable import upload` 没有 `--file` flag、也不代做 PUT,只准备导入;能一站式完成的是上面的脚本<br> • **单条/少量手动**:1. `aitable base search` → `baseId`/`tableId`;2. `aitable field get` → `fieldId` 与类型;3. `aitable record create --records '[{"cells":{"<fieldId>":"值"}}]'` |
|
||||
| update-aitable-record | 1. `aitable base search --query "<表格名>"` → 取 `baseId`/`tableId`<br>2. **取目标 record**:<br> • 已知少量 recordId → `aitable record query --record-ids <ID1,ID2>`<br> • 按条件批量改 → `aitable record query --base-id <baseId> --table-id <tableId> --filters '<JSON>' --all`(**用 --all 防止漏改**)<br>3. **先展示让用户确认要改的 record 列表**<br>4. `aitable record update --base-id <baseId> --table-id <tableId> --records '[{"recordId":"<recordId>","cells":{...}}]'`(单次 ≤30 条) |
|
||||
| read-aitable | 1. `aitable base search --query "<表格名>"` → 取 `baseId`/`tableId`<br>2. `aitable field get --base-id <baseId> --table-id <tableId>` → 取 `fieldId`<br>3. `aitable record query --base-id <baseId> --table-id <tableId>` → 取记录(分页)<br> 需要筛选时 `--filters` 格式见 [aitable-filter-sort.md](./aitable/aitable-filter-sort.md),根节点必须是 `{"operator":"and\|or","operands":[...]}`<br>4. 总结数据 |
|
||||
| generate-data-report | 1. 同 read-aitable 步骤 1-3<br>2. 按[「多源并行采集」](_common/conventions.md#多源并行采集公共模式)执行 → 补充背景<br>3. `doc create --name "<报告名>" --content "<分析报告>"` |
|
||||
| create-aitable-record | **批量导入优先**:`python scripts/import_records.py <baseId> <tableId> data.csv\|data.json [batch_size]`(自动分批创建)<br>单条/少量:1. `aitable base search --query "<表格名>"` → 取 `baseId`/`tableId`<br>2. `aitable field get --base-id <baseId> --table-id <tableId>` → 取 `fieldId` 与类型<br>3. `aitable record create --base-id <baseId> --table-id <tableId> --records '[{"cells":{"<fieldId>":"值"}}]'` |
|
||||
| update-aitable-record | 1. `aitable base search --query "<表格名>"` → 取 `baseId`/`tableId`<br>2. `aitable record query --base-id <baseId> --table-id <tableId>` → 取 `recordId`,**先展示让用户确认**<br>3. `aitable record update --base-id <baseId> --table-id <tableId> --records '[{"recordId":"<recordId>","cells":{...}}]'` |
|
||||
| search-aitable-template | 1. `aitable template search --query "<关键词>"` → 取 `templateId`<br>2. 用户选定<br>3. `aitable base create --name "<表格名>" --template-id <templateId>` → 取 `baseId` |
|
||||
| export-aitable-to-xlsx | 1. `aitable base search --query "<表格名>"` → 取 `baseId`<br>2. **按场景选 scope**:<br> • 全表+附件 → `aitable export data --base-id <baseId> --scope all --export-format excel_and_attachment --output ./<name>.xlsx`<br> • 单表(仅 xlsx)→ `--scope table --table-id <tableId> --export-format excel`<br> • 单视图 → `--scope view --table-id <tableId> --view-id <viewId>`<br>3. CLI 内置渐进式退避轮询 + 自动落盘,**不要自己写 GET downloadUrl**<br>4. 大表超时(默认 5 分钟):加 `--timeout-sec 900` 或拿到 `taskId` 后 `aitable export data --task-id <ID> --output ./<name>.xlsx` 续等<br>5. 与悟空脚本路径并存:复杂场景(多 base 批量 / 按视图组合)请用 `python scripts/aitable_export_via_task.py <baseId> --scope all\|table\|view` |
|
||||
| primary-doc-from-record | 当 AI 表格用文档作主键字段时,从 record 跳到其主文档:<br>1. `aitable record query` 取 `recordId`<br>2. `aitable base get-primary-doc-id --base-id <baseId> --table-id <tableId> --record-id <recordId>` → 取主键文档 `dentryUuid`<br>3. 凭 `dentryUuid` 调 `doc read --node <UUID>` 拿文档内容 |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 业务域通用规范
|
||||
|
||||
> 仅服务本仓库已迁入的文档与 AI 表格行动指南。安全门控、危险操作确认、`--format json` 等已在根 skill 中定义,此处不重复。
|
||||
> 仅服务本 skill 已迁入的行动指南。安全门控、危险操作确认、`--format json` 等已在本 skill 的 `SKILL.md` 中定义,此处不重复。
|
||||
|
||||
## 批量查询规范
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
| 1 | **并行查详情**:拿到多个 ID 后,用 `&` 合并到同一条 Shell 命令并行执行 + `wait`,**严禁逐条串行** |
|
||||
| 2 | **翻页**:分页接口须拉全直至无更多 |
|
||||
| 3 | **优先批量 API**:有批量接口则用批量;无则按 #1 并行 |
|
||||
| 4 | **列表少轮次**:带条件搜索/列表 → 一次采全详情;**禁止**无新参数时重复同一 `list` / `search` |
|
||||
| 4 | **群消息**:必须先 `chat search --query` 得 `openConversationId`,再 `chat message list --group`;多群同条命令并行 |
|
||||
| 5 | **列表少轮次**:带条件搜索/列表 → 一次采全详情;**禁止**无新参数时重复同一 `list` / `search` |
|
||||
|
||||
## 多源并行采集(公共模式)
|
||||
|
||||
@@ -26,10 +27,18 @@
|
||||
|
||||
| 字段 | 来源 | 传递给 |
|
||||
|------|------|--------|
|
||||
| `nodeId` | `doc search` | `doc read/update/copy/move/rename --node` |
|
||||
| `nodeId` | `doc list` 中的 folder 类型节点 / `doc folder create` | `doc list --folder`、`doc create --folder`、`doc upload --folder`、`doc copy/move --folder` |
|
||||
| `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 |
|
||||
| `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 --file-id`、`drive list/mkdir/upload --parent-id` |
|
||||
| `workspaceId` | `wiki space search/list/create` | `doc list/search/create --workspace`、`wiki member * --workspace` |
|
||||
| `dentryUuid` | `drive list` / `drive mkdir` | `drive info/download --node`、`drive list/mkdir/upload --folder` |
|
||||
| `dentryId` | `drive info` 的数字字段 | 仅用于 `chat message send --dentry-id` |
|
||||
|
||||
**ID 边界硬约束**:遇到 `drive --parent-id`、`doc --folder`、`doc --node` 时,只能使用 `dentryUuid` / `nodeId` / 文档 URL。若当前上下文只有数字型 `dentryId`,必须先重新 `drive list` / `doc list` / `doc search` 获取正确 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,不能把该数字直接代入后续命令。
|
||||
|
||||
@@ -1,282 +1,21 @@
|
||||
# AI表格 (aitable) 命令参考
|
||||
# AI 表格 (aitable) 命令参考
|
||||
|
||||
> **渐进式文档**:本文件为路由层(索引 + 意图判断),各命令的详细参数、示例和踩坑说明在 [aitable/](./aitable/) 目录下按需加载。
|
||||
> 渐进式入口:先读命令索引,再只加载命中的模块参考。
|
||||
|
||||
## 文档地址 (URI)
|
||||
## 按需加载
|
||||
|
||||
| 资源 | URI 格式 |
|
||||
|------|----------|
|
||||
| Base 文档 | `https://alidocs.dingtalk.com/i/nodes/{baseId}` |
|
||||
| 模板预览 | `https://docs.dingtalk.com/table/template/{templateId}` |
|
||||
| 任务 | 参考 |
|
||||
|---|---|
|
||||
| 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-workflow.md) · [上下文传递](./aitable/aitable-context.md) |
|
||||
| 注意事项、脚本、产品边界 | [注意事项](./aitable/aitable-notes.md) · [自动化脚本](./aitable/aitable-scripts.md) · [相关产品](./aitable/aitable-related.md) |
|
||||
|
||||
> **操作后请返回文档 URI**:每次执行 base list/search/create/get 操作后,从返回数据中提取 `baseId`,拼接为 `https://alidocs.dingtalk.com/i/nodes/{baseId}` 返回给用户。
|
||||
> 补充:如果 URL 不是来自 `aitable` 命令返回,而是用户直接贴的原始 `alidocs` URL,先按 [链接规范](../url-patterns.md#alidocs-url-类型探测流程) probe,确认是 `able` 后再按 AI 表格处理。
|
||||
## 创建 AI 表格
|
||||
|
||||
## 命令索引表
|
||||
|
||||
### base (Base 管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `base list` | 列出最近访问的 Base | — | 仅返回最近访问过的,优先用 `base search` |
|
||||
| `base search` | 按名称搜索 Base(别名 `aitable search`) | — | `--query` help 标必填但实际可省略:不传时返回最近访问的 Base 列表。`--keyword` 是 `--query` 的隐藏别名,同义 |
|
||||
| `base get` | 获取 Base 信息(含 tables 列表) | `--base-id` | 用户给 URL 时提取末尾 ID |
|
||||
| `base copy` | 复制整个 Base 到目标文件夹 | `--base-id` `--target-folder-id` | 默认全量复制;`--only-struct` 仅复制结构不含数据 |
|
||||
| `base get-primary-doc-id` | 获取某记录的主键文档 ID | `--base-id` `--table-id` `--record-id` | 等价 `record primary-doc-get` 的取 ID 视角 |
|
||||
| `base create` | 创建 Base | `--name` | 创建后直接用返回的 baseId |
|
||||
| `base update` | 更新 Base 名称 | `--base-id` `--name` | — |
|
||||
| `base delete` | 删除 Base | `--base-id` | 不可逆 |
|
||||
|
||||
### table (数据表管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `table get` | 获取表结构(字段+视图目录) | `--base-id` | 不传 `--table-ids` 返回全部表 |
|
||||
| `table list` | 获取数据表(`table get` 的别名) | `--base-id` | 与 `table get` 等价 |
|
||||
| `table create` | 创建数据表 | `--base-id` `--name` | `--fields` 为 JSON 数组;**可传空数组 `[]`**(默认值即 `[]`),此时服务端自动补一个名为"标题"的 primaryDoc 首列;单次最多 15 个字段 |
|
||||
| `table update` | 重命名表 | `--base-id` `--table-id` `--name` | — |
|
||||
| `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 list` | 获取字段信息(`field get` 的别名) | `--base-id` `--table-id` | 与 `field get` 等价 |
|
||||
| `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` | 不可逆 |
|
||||
| `field search-options` | 搜索单选/多选字段的选项 | `--base-id` `--table-id` `--field-id` | 仅 singleSelect/multipleSelect;`--keyword` 模糊过滤,不传返回全部 |
|
||||
|
||||
### record (记录管理)
|
||||
|
||||
| 命令 | 用途 | 必读 reference | 路由提醒 |
|
||||
|------|------|----------------|----------|
|
||||
| `record query` | 查询/搜索记录 | [aitable-record-query.md](./aitable/aitable-record-query.md) | 先 `table get` 拿 fieldId;`--all` 自动翻页;filters 结构见 reference;`--query`(隐藏别名 `--keyword`)全文搜索 |
|
||||
| `record list` | 获取记录(`record query` 的别名) | [aitable-record-query.md](./aitable/aitable-record-query.md) | 与 `record query` 等价 |
|
||||
| `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 query-empty` | 查询完全没填用户字段的空行 | — | `--base-id` `--table-id`;`--limit` 扫描预算 [1,100],`--cursor` 翻页 |
|
||||
| `record create` | 新增记录 | [aitable-record-create.md](./aitable/aitable-record-create.md) | cells key 必须是 fieldId 不是字段名;单次最多 100 条 |
|
||||
| `record update` | 更新记录 | [aitable-record-update.md](./aitable/aitable-record-update.md) | 需先 query 拿 recordId;只传需改字段;**没有** `--record-id` `--cells` flag |
|
||||
| `record batch-update` | 把同一份 cells 批量应用到多条记录 | [aitable-record-update.md](./aitable/aitable-record-update.md) | `--record-ids`(≤100)+ `--cells` 共享 patch |
|
||||
| `record upsert` | 批量创建或更新(有 recordId 走更新,无则创建) | [aitable-record-upsert.md](./aitable/aitable-record-upsert.md) | `--records`/`--records-file`;单次最多 100 条 |
|
||||
| `record delete` | 删除记录 | [aitable-record-delete.md](./aitable/aitable-record-delete.md) | 不可逆,需先 query 确认 |
|
||||
| `record share-url` | 批量获取记录分享链接 | [aitable-record-share.md](./aitable/aitable-record-share.md) | `--record-ids`(逗号分隔,单次最多 20 条) |
|
||||
| `record history-list` | 查询单条记录的变更历史 | [aitable-record-history.md](./aitable/aitable-record-history.md) | `--record-id` 单条;`--offset`/`--limit`(≤50) |
|
||||
| `record primary-doc-get` | 查询记录的主键文档 nodeId | [aitable-primary-doc.md](./aitable/aitable-primary-doc.md) | 无文档时返回 `no record` 错误 |
|
||||
| `record primary-doc-create` | 为记录创建主键文档 | [aitable-primary-doc.md](./aitable/aitable-primary-doc.md) | 幂等;`--field-id` 须 primaryDoc 类型 |
|
||||
|
||||
### view (视图管理)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `view get` | 获取视图配置 | `--base-id` `--table-id` | 不传 `--view-ids` 返回全部视图 |
|
||||
| `view create` | 创建视图 | `--base-id` `--table-id` `--view-type` | 类型: Grid/Kanban/Gantt/Calendar/Gallery/FormDesigner |
|
||||
| `view update` | 更新视图(**调整字段顺序的入口**) | `--base-id` `--table-id` `--view-id` | `visibleFieldIds` 重排字段顺序 |
|
||||
| `view delete` | 删除视图 | `--base-id` `--table-id` `--view-id` | 不可删最后一个/锁定视图 |
|
||||
|
||||
> **"移动字段/调整字段顺序"** 在 AI 表格里没有 `field reorder` 命令,必须通过 `view update --config '{"visibleFieldIds":[...]}'` 完成。
|
||||
|
||||
> **view update --config 支持的 key 白名单**(传入其他 key 会报错):
|
||||
> - `visibleFieldIds` — 视图可见字段列表及顺序(首列字段必须保留在第一位)
|
||||
> - `filter` — 筛选规则列表
|
||||
> - `sort` — 排序规则列表
|
||||
> - `group` — 分组规则列表
|
||||
> - `fieldWidths` — 列宽映射(仅 Grid 视图有效)
|
||||
>
|
||||
> 不支持 `formInfo`、`requiredFields`、`conditionalRules` 等 FormDesigner 高级配置,这些 key 会被服务端忽略。
|
||||
|
||||
### form (表单管理) → 详见 [aitable-form.md](./aitable/aitable-form.md)
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `form list` | 列出表单视图 | `--base-id` `--table-id` | 每条含 viewId/name;新建表单无 title 且 createdAt=0,改过后才有 |
|
||||
| `form get` | 按 viewId 取单个表单详情 | `--base-id` `--table-id` `--view-id` | 客户端按 viewId 过滤,`data` 即该表单对象;viewId 不存在报 not found |
|
||||
| `form create` | 创建表单视图 | `--base-id` `--table-id` `--name` | 等价 `view create --view-type FormDesigner` |
|
||||
| `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 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 |
|
||||
|
||||
> **当前不支持通过 CLI 新建/修改/删除工作流**,请去 AI 表格 Web 端(数据表页面 → 自动化)配置。
|
||||
|
||||
### dashboard & chart → 详见 [aitable-dashboard-chart.md](./aitable/aitable-dashboard-chart.md)
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
| `dashboard get/create/update/delete` | 仪表盘管理 |
|
||||
| `dashboard config-example` | 查看仪表盘配置模板 |
|
||||
| `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 |
|
||||
|
||||
> 所有写命令(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 与父级关系。
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 路由提醒 |
|
||||
|------|------|----------|----------|
|
||||
| `section list-nodes` | 列出 Base 下全部节点 | `--base-id` | 返回 `{nodeId, nodeType, parentSectionId, name?}`;是 move-node / reorder 的前置定位命令 |
|
||||
| `section list-empty` | 列出空文件夹 | `--base-id` | 返回 `{sectionId, name, parentSectionId}`,用于清理导航树 |
|
||||
| `section create` | 创建文件夹 | `--base-id` `--name` | `--parent-section-id` 不传/空串=根目录;`--index` 指定位置 |
|
||||
| `section rename` | 重命名文件夹 | `--base-id` `--section-id` `--new-name` | — |
|
||||
| `section delete` | 删除文件夹 | `--base-id` `--section-id` | 不可逆;建议先 list-empty 确认为空 |
|
||||
| `section reorder` | 调整文件夹顺序 | `--base-id` `--section-id` `--target-index` | 仅当前父级下调序;跨父级用 move-node |
|
||||
| `section move-node` | 移动节点(跨父级) | `--base-id` `--node-id` `--new-parent-section-id` | `--new-parent-section-id ""`=移到根;`--target-index` 调全局位置 |
|
||||
|
||||
## 意图判断
|
||||
|
||||
用户说"表格/多维表/AI表格":
|
||||
- 查看/查找/列表 → `base search`(优先)或 `base list`(仅浏览最近访问)
|
||||
- 详情 → `base get`
|
||||
- 创建 → `base create`
|
||||
- 修改 → `base update`
|
||||
- 删除 → `base delete`
|
||||
|
||||
用户说"数据表/子表/table":
|
||||
- 查看 → `table get`
|
||||
- 创建 → `table create`
|
||||
- 重命名 → `table update`
|
||||
- 删除 → `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))
|
||||
- 已知 recordId 反查字段值 → `record get`(按 ID 取专用,等价 `record query --record-ids`)
|
||||
- 添加/写入 → `record create`(读 [aitable-record-create.md](./aitable/aitable-record-create.md))
|
||||
- 修改/更新 → `record update`(读 [aitable-record-update.md](./aitable/aitable-record-update.md))
|
||||
- 删除 → `record delete`
|
||||
|
||||
用户说"表单/问卷/form/收集信息" → 读 [aitable-form.md](./aitable/aitable-form.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 跨表引用)
|
||||
|
||||
用户说"仪表盘/图表/chart" → 读 [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-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 table 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 |
|
||||
| `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 |
|
||||
|
||||
## 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](./doc.md) — 富文本文档编辑,不是结构化数据表格
|
||||
创建 Base 先读 [Base 索引](./aitable/aitable-base-index.md);创建数据表再读 [Table 索引](./aitable/aitable-table-index.md)。
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# 高级权限与自定义角色
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `advperm enable/disable` | 高级权限总开关 | [`aitable-advperm.md`](./aitable-advperm.md) |
|
||||
| `advperm role-list/get/create/update/delete` | 自定义角色管理 | [`aitable-advperm.md`](./aitable-advperm.md) |
|
||||
@@ -0,0 +1,5 @@
|
||||
# 附件
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `attachment upload` | 准备附件上传凭证 | [`aitable-attachment.md`](./aitable-attachment.md) |
|
||||
@@ -1,6 +1,8 @@
|
||||
# attachment — 附件上传
|
||||
|
||||
> **STOP — 不要使用钉盘 (drive) 上传!** 钉盘 fileId 无法写入 attachment 字段。必须使用以下流程。
|
||||
>
|
||||
> **STOP — 严禁在 record create/update 的 cells 里直接传图片 URL!** 直传 `{"url":"https://..."}` 会导致服务端同步下载图片,批量写入时触发 TIMEOUT_ERROR。正确做法:先 `attachment upload` 获取 `fileToken`,再用 `{"fileToken":"ft_xxx"}` 写入。
|
||||
|
||||
## 准备附件上传
|
||||
|
||||
@@ -38,10 +40,8 @@ dws aitable record create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
dws aitable attachment upload --base-id <BASE_ID> --file-name report.pdf --size 204800 --format json
|
||||
# → 返回 uploadUrl、fileToken
|
||||
|
||||
# 2. PUT 上传(Content-Type 必须与文件类型一致,不能留空)
|
||||
# 留空或用 curl 默认的 application/x-www-form-urlencoded 都会被 OSS 拒为 403
|
||||
# 2. PUT 上传(Content-Type 必须是文件的具体 MIME type)
|
||||
curl -X PUT "<uploadUrl>" -H "Content-Type: application/pdf" --data-binary @report.pdf
|
||||
# 例:.txt → text/plain,.png → image/png,.xlsx → application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
|
||||
# 3. 写入记录
|
||||
dws aitable record update --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# 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` |
|
||||
@@ -26,7 +26,7 @@
|
||||
| 全量拉取/统计 | `record query --all` | 不要手动循环 cursor |
|
||||
| 全量导出为文件 | `export data` | 不要 `--all` 拉全量再写文件 |
|
||||
| 批量写入 | `record create`(分批 100 条) | 不要一次传超过 100 条 |
|
||||
| 附件上传 | `attachment upload` + `record update` | 不要在 cells 里伪造附件值 |
|
||||
| 附件/图片上传 | `attachment upload` 获取 fileToken → `record create/update` 用 fileToken 写入 | **严禁直接传图片 URL 到附件字段**(服务端同步下载会超时) |
|
||||
| 文件级导入 | `import upload` + `import data` | 不要手动解析 xlsx 再逐条写入 |
|
||||
|
||||
## 4. 创建/修改后回读确认
|
||||
|
||||
@@ -86,11 +86,16 @@
|
||||
{"fldDateId": "2026-03-15T09:00+08:00"}
|
||||
```
|
||||
|
||||
**读取**:RFC3339 字符串
|
||||
**读取**:RFC3339 字符串(带时区)
|
||||
```json
|
||||
{"fldDateId": "2026-03-15T09:00:00+08:00"}
|
||||
```
|
||||
|
||||
**过滤**(`record query --filters`):日期字段**只能用日期专用操作符** `date_eq` / `before` / `after` / `not_before` / `not_after` / `exist` / `un_exist`,比较值用日期字符串(如 `"2026-03-15"`)。
|
||||
- ❌ 通用 `eq` / `ne` / `gt` / `gte` / `lt` / `lte` / `contain` 对日期字段无效,会静默返回 0 条;
|
||||
- ❌ 不支持区间 `date_between` 与相对 `from_now`(CLI 会直接拒绝),范围查询用 `not_before` + `not_after` 组合。
|
||||
- 详见 [aitable-filter-sort.md](./aitable-filter-sort.md) §日期字段过滤。
|
||||
|
||||
---
|
||||
|
||||
### currency(货币)
|
||||
@@ -236,15 +241,14 @@
|
||||
|
||||
### attachment(附件)
|
||||
|
||||
**写入**:对象数组,支持 `fileToken` 或 `url` 形式
|
||||
**写入**:对象数组,**必须使用 `fileToken`**
|
||||
|
||||
```json
|
||||
{"fldAttachId": [{"fileToken": "ft_xxx"}]}
|
||||
{"fldAttachId": [{"url": "https://example.com/file.pdf"}]}
|
||||
```
|
||||
|
||||
> ⚠️ **必须先通过 [attachment upload 流程](./aitable-attachment.md) 获取 `fileToken`**。
|
||||
> URL 形式是 best-effort 异步转存,不保证立即可用。
|
||||
> ⚠️ **必须先通过 [attachment upload 流程](./aitable-attachment.md) 上传文件获取 `fileToken`,再将 `fileToken` 写入 cells。**
|
||||
> ❌ **严禁直接传 `{"url": "https://..."}` 形式写入附件/图片字段** — 服务端会同步下载图片,10 条记录即触发 TIMEOUT_ERROR 超时。
|
||||
> 写入会**整体覆盖**原附件列表,不是追加。
|
||||
|
||||
**读取**:对象数组(含下载链接、文件名、大小)
|
||||
@@ -335,7 +339,7 @@
|
||||
|------|----------|
|
||||
| cells key 用字段名称 `"课程名称"` | 用 fieldId `"fldXXX"` |
|
||||
| progress 写入 `75` | 写入 `0.75`(范围 0~1) |
|
||||
| attachment 直接传文件路径 | 必须先 upload 获取 fileToken |
|
||||
| attachment 直接传文件路径或图片 URL | 必须先 `attachment upload` 获取 fileToken,再用 fileToken 写入(直传 URL 会超时) |
|
||||
| user 字段传用户名字符串 | 传对象数组 `[{"userId":"...", "corpId":"..."}]` |
|
||||
| group 字段用 `openConversationId` | 用 `cid` |
|
||||
| singleSelect 传 option id 字符串 | 传 name 字符串或 `{"id":"...", "name":"..."}` 对象 |
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
# 命令索引表
|
||||
|
||||
## 命令索引表
|
||||
|
||||
### 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 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 |
|
||||
|
||||
> **当前不支持通过 CLI 新建/修改/删除工作流**,请去 AI 表格 Web 端(数据表页面 → 自动化)配置。
|
||||
|
||||
### 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` 重试。
|
||||
@@ -0,0 +1,39 @@
|
||||
# 复杂操作
|
||||
|
||||
## 复杂操作
|
||||
|
||||
### 仪表盘 / 图表(建议顺序)
|
||||
|
||||
```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`
|
||||
@@ -0,0 +1,13 @@
|
||||
# 上下文传递表
|
||||
|
||||
## 上下文传递表
|
||||
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `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 |
|
||||
@@ -15,10 +15,8 @@ dws aitable chart get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --chart-
|
||||
## 要点
|
||||
|
||||
- `dashboard get` 返回的 `charts[].chartId` 可直接给 `chart get` 使用
|
||||
- `dashboard share get` 可能返回 `404`(`retryable:true`)——从未分享、甚至刚开启分享后立即查都可能 404;`data` 为 `{}`。按可重试错误处理,不要误判为参数拼错。它有时也会返回 `success + data`(如关闭分享之后),行为不稳定,别用它当"是否已分享"的唯一判据。
|
||||
- `chart share get` 稳定返回 `success + data`(含 `enabled` 等),可用于分享状态判断;从未分享时 `enabled=false`,不会 404。
|
||||
- ⚠️ **`dashboard share update` 开启 ORG 分享后返回的 `shareType` 是 `"[1]"`(未映射回 `ORG`,服务端已知问题)**;`chart share update --share-type ORG` 则正确返回 `shareType="ORG"`。判断 dashboard 是否 ORG 分享时对 `"[1]"` 做兼容。
|
||||
- `chart share update` / `dashboard share update` 的 `--enabled` 是字符串 flag:`--enabled false`(空格)和 `--enabled=false` 都能正确关闭分享。
|
||||
- `dashboard share get` 可能返回 `404`(资源不存在或未开通),需按可重试错误处理,不要误判为参数拼错
|
||||
- `chart share get` 可正常返回 `enabled/shareUrl`,用于分享状态判断
|
||||
|
||||
## dashboard 子命令
|
||||
|
||||
@@ -27,25 +25,19 @@ dws aitable chart get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --chart-
|
||||
| `dashboard get` | 获取仪表盘详情(含 charts 列表) | `--base-id` `--dashboard-id` | — |
|
||||
| `dashboard create` | 创建仪表盘 | `--base-id` + (`--config` 或 `--name`) | `--name` 简化版创建空看板;`--config` 传完整 JSON |
|
||||
| `dashboard update` | 更新仪表盘 | `--base-id` `--dashboard-id` + (`--config` 或 `--name`) | `--name` 仅改名;`--config` 更新完整配置 |
|
||||
| `dashboard arrange` | 自动重排仪表盘图表布局 | `--base-id` `--dashboard-id` | 让服务端重新排布 charts 位置 |
|
||||
| `dashboard delete` | 删除仪表盘 | `--base-id` `--dashboard-id` `--yes` | — |
|
||||
| `dashboard config-example` | 查看仪表盘配置模板 | 无 | 创建前先调此命令了解 config 结构 |
|
||||
| `dashboard share get` | 获取仪表盘分享配置 | `--base-id` `--dashboard-id` | 可能 404,见上方要点 |
|
||||
| `dashboard share update` | 更新仪表盘分享配置 | `--base-id` `--dashboard-id` `--enabled` | `--enabled true` 开启,`--share-type` 用 `ORG`(ORG 回显 `shareType="[1]"`);部分组织禁用了 `PUBLIC` 公开分享;若报 `Illegal argument`,改用 `ORG`(组织内分享)。`--enabled false` 关闭 |
|
||||
| `dashboard arrange` | 自动重排图表布局 | `--base-id` `--dashboard-id` | 把图表按行铺满网格,避免某行只占半幅、留下大片空白;返回 `{totalColumns, layout, alignedChartCount}` |
|
||||
|
||||
## chart 子命令
|
||||
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `chart get` | 获取图表详情 | `--base-id` `--dashboard-id` `--chart-id` |
|
||||
| `chart create` | 创建图表 | `--base-id` `--dashboard-id` `--config` `--layout` |
|
||||
| `chart create` | 创建图表 | `--base-id` `--dashboard-id` `--config` |
|
||||
| `chart update` | 更新图表配置 | `--base-id` `--dashboard-id` `--chart-id` `--config` |
|
||||
| `chart delete` | 删除图表 | `--base-id` `--dashboard-id` `--chart-id` `--yes` |
|
||||
| `chart widgets-example` | 查看图表 widgets 配置模板 | 无 |
|
||||
| `chart share get` | 获取图表分享配置 | `--base-id` `--dashboard-id` `--chart-id` |
|
||||
| `chart share update` | 更新图表分享配置(`--enabled true/false`,开启配 `--share-type`,用 `ORG`;部分组织禁用了 `PUBLIC` 公开分享;报 `Illegal argument` 时改用 `ORG`) | `--base-id` `--dashboard-id` `--chart-id` `--enabled` |
|
||||
|
||||
> `chart create` 的 `--layout` 是**必填**(12 列网格布局,如 `{"x":0,"y":0,"w":6,"h":4}`);不传本地校验直接拒。`chart update` 的 `--config` 也**必填**——即便只想改 layout,也要带完整 config,否则服务端拒绝。
|
||||
|
||||
## 配置获取流程
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# 仪表盘与图表
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `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) |
|
||||
@@ -0,0 +1,6 @@
|
||||
# 导入导出
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `export data` | 导出数据 | [`aitable-export-import.md`](./aitable-export-import.md) |
|
||||
| `import upload/data` | 触发导入 | [`aitable-export-import.md`](./aitable-export-import.md) |
|
||||
@@ -113,32 +113,3 @@ dws aitable import data --import-id <importId> --table-id <TABLE_ID> --format js
|
||||
> **导入数据无法整体撤销**:文件一旦导入成功,数据即写入表中,没有"撤销导入"操作。如需清理导入的测试数据,只能手动通过 `record delete` 逐条或批量删除记录;如果是新建表模式导入的,可以直接 `table delete` 删除整张表。因此:
|
||||
> - 测试/验证场景建议导入到**独立的测试表或测试 Base**,用完后整体删除
|
||||
> - 如果用户明确表示不想导入测试数据或要求先预览内容再决定,应先解析文件内容展示给用户确认,而非直接导入
|
||||
|
||||
---
|
||||
|
||||
## 导入数据:两条链路怎么选
|
||||
|
||||
用户给文件让导入 AI 表格时,路径选择决定成败:
|
||||
|
||||
> ⚠️ **`import upload` 没有 `--file` flag**(传了会报 unknown flag)。它只申请上传凭证,必填 `--file-name` + `--file-size`,拿到 `uploadUrl` 后要**自己 curl PUT 上传文件**(Content-Type 留空,见上文三步流程),再 `import data`。想省事直接用 `aitable_import_via_task.py` 脚本,它把这三步包好了。
|
||||
|
||||
| 用户原话 | 链路 | 命令 / 脚本 | 行为 |
|
||||
|---------|------|------------|------|
|
||||
| "把这个 Excel 导入到 AI 表格"(无指定目标表) | **文件导入任务** | `python scripts/aitable_import_via_task.py <baseId> <file>`(推荐)或手动三步 `import upload --file-name x.xlsx --file-size <字节>` → curl PUT → `import data --import-id <ID>` | 服务端解析文件,**新建数据表**,自动识别表头 |
|
||||
| "把这个 Excel 导入新表 / 自动建表" | 同上 | 同上 | 同上 |
|
||||
| "把这批记录追加到已有的『成员表』里" | **记录批量写入** | `python scripts/import_records.py <baseId> <tableId> <file>` | 走 `record create`,**写入已有 tableId**,需要字段名匹配 |
|
||||
| "Excel 列名和表字段对不上但要追加" | 文件导入 + 追加 + 字段映射 | 三步导入后 `import data --import-id <ID> --table-id <TBL> --field-mapping '{"目标":"源"}'` | 服务端按映射追加 |
|
||||
|
||||
## 大表 / 长任务超时续等
|
||||
|
||||
单次等待窗口很短:`export data` 只有 `--timeout-ms`(默认且**上限 30000 = 30 秒**,没有 `--timeout-sec`,传了会报 unknown flag);`import data` 用 `--timeout`(秒,默认且推荐最大值 30)。窗口内没跑完,命令会返回 `taskId` / `importId`,用同命令带 ID 反复续等即可:
|
||||
|
||||
```bash
|
||||
# 续等导出:拿到 downloadUrl 后再 curl 下载(见下方警告)
|
||||
dws aitable export data --base-id <B> --task-id <ID> --timeout-ms 30000
|
||||
|
||||
# 续等导入
|
||||
dws aitable import data --import-id <ID>
|
||||
```
|
||||
|
||||
> ⚠️ **`--output` 不会保存导出的 xlsx**:`--output` 是隐藏的全局 flag,作用是把命令的 **JSON 输出**写到文件,实测只生成一个 0 字节文件,不会下载导出内容。正确做法是从 `export data` 返回里取 `downloadUrl`,再 `curl -L "<downloadUrl>" -o out.xlsx` 下载。想省事直接用 `aitable_export_via_task.py` 脚本(它负责轮询 + 下载)。
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# 字段管理
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `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) |
|
||||
@@ -1,5 +1,7 @@
|
||||
# filters & sort — 筛选排序语法参考
|
||||
|
||||
> 视图(view)配置的 filter/sort/group **整体写入**请优先用 `view update filter` / `view update sort` / `view update group` 子命令,详见 [aitable-view-config.md](./aitable-view-config.md)。本文件聚焦于 `record query --filters` 与 view config filter 的语法和差异。
|
||||
|
||||
## filters 结构规范
|
||||
|
||||
### 强制规则
|
||||
@@ -49,11 +51,34 @@ CLI 同时兼容两种子条件写法(推荐格式 A):
|
||||
| `exist` / `un_exist` | 有值 / 为空 | `["fieldId"]`(无需第二项) |
|
||||
| `any_of` / `none_of` / `all_of` | 包含任一 / 不包含任一 / 全包含(多选字段) | `["fieldId", "optionName"]` |
|
||||
| `date_eq` / `before` / `after` | 日期等于 / 早于 / 晚于 | `["fieldId", "dateStr"]` |
|
||||
| `not_before` / `not_after` | 不早于 / 不晚于 | `["fieldId", "dateStr"]` |
|
||||
| `from_now` | 从现在起 N 天内 | `["fieldId", "天数"]` |
|
||||
| `date_between` | 日期区间 | `["fieldId", "[startTs, endTs]"]` |
|
||||
| `not_before` / `not_after` | 不早于(≥) / 不晚于(≤) | `["fieldId", "2026-05-22"]` |
|
||||
|
||||
> **操作符拼写必须严格匹配上表**,CLI 会在调用前校验,错误拼写会被拒绝。
|
||||
>
|
||||
> **没有 `date_between`(区间)操作符**,也**不支持 `from_now`**——date 字段不支持区间/相对过滤,传了会被 CLI 拒绝。范围查询用 `not_before` + `not_after` 组合,见下方专节。
|
||||
|
||||
### 日期字段过滤(date / 创建时间 / 修改时间)
|
||||
|
||||
日期类字段的过滤规则与其它字段**不同**,是线上反馈最高频的踩坑点。**经集成测试实测**确认的规则:
|
||||
|
||||
1. **只能用日期专用操作符**:`date_eq` / `before` / `after` / `not_before` / `not_after` / `exist` / `un_exist`(与前端筛选 UI 的「等于 / 早于 / 晚于 / 早于或等于 / 晚于或等于 / 不为空 / 为空」一一对应)。
|
||||
2. **比较值用日期字符串**,如 `"2026-05-22"`(也接受 RFC3339 / 毫秒时间戳,内部统一转成毫秒比较)。读取返回的是带时区 RFC3339(如 `"2026-05-22T00:00:00+08:00"`)。
|
||||
3. **通用操作符 `eq` / `ne` / `gt` / `gte` / `lt` / `lte` / `contain` 对 date 字段无效**——无论传 ISO 字符串还是毫秒时间戳,都会**静默返回 0 条**。这是后端 date 字段的比较规则,不是 bug,CLI 也无法在本地拦截(不知道字段类型),务必用对操作符。
|
||||
4. **没有区间操作符 `date_between`**,也**不支持 `from_now`(相对天数)**——均会静默返回 0 条,CLI 已直接拒绝。范围查询用 `not_before`(≥起点)+ `not_after`(≤终点)两个条件 `and` 组合。
|
||||
|
||||
| 需求 | 操作符 | 示例 operands |
|
||||
|------|--------|--------------|
|
||||
| 等于某天 | `date_eq` | `["fldDate", "2026-05-22"]` |
|
||||
| 早于 / 晚于(不含当天) | `before` / `after` | `["fldDate", "2026-05-22"]` |
|
||||
| 不早于(≥) / 不晚于(≤) | `not_before` / `not_after` | `["fldDate", "2026-05-22"]` |
|
||||
| 有值 / 为空 | `exist` / `un_exist` | `["fldDate"]` |
|
||||
|
||||
**日期区间查询(替代 between)**——查 `2026-05-01 ~ 2026-05-31`(含端点):
|
||||
|
||||
```bash
|
||||
dws aitable record query --base-id X --table-id Y \
|
||||
--filters '{"operator":"and","operands":[{"operator":"not_before","operands":["fldDate","2026-05-01"]},{"operator":"not_after","operands":["fldDate","2026-05-31"]}]}'
|
||||
```
|
||||
|
||||
### 常见错误拼写(CLI 会自动提示纠正)
|
||||
|
||||
@@ -104,3 +129,41 @@ dws aitable record query --base-id X --table-id Y \
|
||||
```bash
|
||||
--sort '[{"fieldId":"fldPriority","direction":"desc"},{"fieldId":"fldCreatedAt","direction":"asc"}]'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## view update --config 中的 filter / sort 格式
|
||||
|
||||
> **重要区分**:`record query --filters` 和 `view update --config` 中的 filter **格式不同**!
|
||||
|
||||
| 场景 | filter 格式 | 说明 |
|
||||
|------|-------------|------|
|
||||
| `record query --filters` | **对象**:`{"operator":"and","operands":[...]}` | 直接传最外层逻辑对象 |
|
||||
| `view update --config` 的 filter | **数组**:`[{"operator":"and","operands":[...]}]` | 外面多一层数组包裹 |
|
||||
| `view update --config` 的 sort | **数组**:`[{"fieldId":"X","direction":"asc"}]` | 与 record query --sort 一致 |
|
||||
|
||||
### 正确示例
|
||||
|
||||
```bash
|
||||
# view update 设置筛选(filter 是数组)
|
||||
dws aitable view update --base-id X --table-id Y --view-id Z \
|
||||
--config '{"filter":[{"operator":"and","operands":[{"operator":"eq","operands":["fldStatus","待处理"]}]}]}'
|
||||
|
||||
# view update 设置排序(sort 是数组)
|
||||
dws aitable view update --base-id X --table-id Y --view-id Z \
|
||||
--config '{"sort":[{"fieldId":"fldPriority","direction":"desc"}]}'
|
||||
|
||||
# 同时设置 filter + sort + visibleFieldIds
|
||||
dws aitable view update --base-id X --table-id Y --view-id Z \
|
||||
--config '{"filter":[{"operator":"and","operands":[{"operator":"eq","operands":["fldStatus","进行中"]}]}],"sort":[{"fieldId":"fldDate","direction":"asc"}],"visibleFieldIds":["fld1","fld2","fld3"]}'
|
||||
```
|
||||
|
||||
### CLI 自动容错
|
||||
|
||||
CLI 会自动修正以下常见错误格式(不会报错,但建议直接使用正确格式):
|
||||
|
||||
| 错误写法 | CLI 自动修正为 |
|
||||
|----------|---------------|
|
||||
| `"filter":{"operator":"and",...}` (对象) | `"filter":[{"operator":"and",...}]` (数组) |
|
||||
| `"sort":{"fieldId":"X","direction":"asc"}` (对象) | `"sort":[{"fieldId":"X","direction":"asc"}]` (数组) |
|
||||
| 子条件用 MCP 简写 `{"fieldId":"X","operator":"eq","value":"Y"}` | 自动转为 `{"operator":"eq","operands":["X","Y"]}` |
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# 表单管理
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `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) |
|
||||
@@ -50,8 +50,8 @@ dws aitable form share get --base-id BASE_ID --table-id TABLE_ID --view-id VIEW_
|
||||
|
||||
| 命令 | 用途 | 必填参数 | 说明 |
|
||||
|------|------|----------|------|
|
||||
| `form list` | 列出表单视图 | `--base-id` `--table-id` | 每条返回 viewId/name;新建表单**无 title 且 createdAt=0**,改过(form update)后才出现 title 和真实 createdAt |
|
||||
| `form get` | 按 viewId 取单个表单 | `--base-id` `--table-id` `--view-id` | 客户端按 viewId 过滤后 `data` **即该表单对象**(不是 formViews 数组);viewId 不存在返回 `form view ... not found` 错误 |
|
||||
| `form list` | 列出表单视图 | `--base-id` `--table-id` | 返回 viewId/name/title/createdAt |
|
||||
| `form get` | 按 viewId 取单个表单 | `--base-id` `--table-id` `--view-id` | 内部基于 list_form_views 过滤 |
|
||||
| `form create` | 创建表单视图 | `--base-id` `--table-id` `--name` | viewType=FormDesigner |
|
||||
| `form update` | 更新表单 | `--base-id` `--table-id` `--view-id` | `--title`/`--name`(等价)和 `--description` 至少传一项;同时传 title/name 时 title 优先 |
|
||||
| `form delete` | 删除表单 | `--base-id` `--table-id` `--view-id` `--yes` | 不可逆 |
|
||||
@@ -115,6 +115,6 @@ dws aitable form share update --base-id BASE_ID --table-id TABLE_ID --view-id VI
|
||||
|
||||
## 返回结构补充
|
||||
|
||||
- `form list` 返回 `data.formViews[]`,**每条含** `viewId/name`(+ `createdAt`);**新建表单没有 `title` 字段且 `createdAt=0`**,只有在 `form update` 碰过之后才会出现 `title` 和真实 `createdAt`。`shareFormUuid` 不在此返回,请用 `form share get` 单独获取。
|
||||
- `form get` 的 `data` **就是命中的那一条表单对象**(如 `{viewId, name, createdAt, title?, shareFormUuid?}`),不是 `formViews` 数组。Agent 直接读 `data.viewId` / `data.name` 即可,**不要**再取 `data.formViews[0]`。服务端的 viewIds 过滤参数当前不生效,CLI 在客户端按 viewId 精确筛出单条;传了不存在的 viewId 会返回 `form view <id> not found in table` 错误。
|
||||
- `form list` 返回 `data.formViews[]`,**每条仅含** `viewId/name/title/createdAt`;`shareFormUuid` 不在此返回,请用 `form share get` 单独获取。
|
||||
- `form get` 返回结构与 `form list` 完全一致(`data.formViews[]`),仅含一条记录(与请求 viewId 一致)。Agent 提取时仍走 `data.formViews[0]`。
|
||||
- `form field list` 仅返回**未隐藏**的字段;`hidden=true` 的字段不在此返回,如需查看全部字段请用 `field get`。
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# 意图判断
|
||||
|
||||
## 意图判断
|
||||
|
||||
用户说"表格/多维表/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)
|
||||
- 看 Base 里有哪些流程 / 哪些在跑 → `workflow list`(看 `recordCount` / `runningCount`)
|
||||
- 看某个流程具体配置(触发条件、动作步骤) → `workflow get`
|
||||
- 启用流程 → `workflow enable`
|
||||
- 临时停掉流程(调试 / 数据迁移)→ `workflow disable --yes`
|
||||
- **新建 / 修改 / 删除流程**:当前不支持,引导用户到 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=行
|
||||
@@ -0,0 +1,8 @@
|
||||
# 注意事项
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 所有操作使用 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)
|
||||
@@ -17,9 +17,7 @@ dws aitable record primary-doc-get --base-id BASE_ID --table-id TABLE_ID --recor
|
||||
- `--table-id`(必填):Table ID
|
||||
- `--record-id`(必填):Record ID
|
||||
|
||||
**返回:** `data.nodeId` — 主键文档的 nodeId,可直接传给 `dws doc read/update` 的 `--node` 参数。
|
||||
|
||||
> **该记录尚未创建主键文档时**:不会返回 `nodeId: null`,而是 `status=error`、`data={}`,`error={code:"-1", message:"no record", type:"SYSTEM_ERROR", retryable:true}`。要判断"有没有主键文档",看是否命中这个 `no record` 错误,而不是判断 `nodeId` 是否为 null。需要文档时改用 `primary-doc-create`(幂等,已存在则直接返回)。
|
||||
**返回:** `data.nodeId` — 主键文档的 nodeId,可直接传给 `dws doc read/update` 的 `--node` 参数。若该记录尚未创建主键文档,`nodeId` 为 null。
|
||||
|
||||
### 创建主键文档
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ Flags:
|
||||
| cells key 用字段名 | ❌ cells key 必须是 fieldId(如 `fldXXX`),不是字段名称(如 `"课程名称"`) |
|
||||
| 不先获取 fieldId | ❌ 必须先 `table get` 获取 fieldId,再写入记录 |
|
||||
| 单次超 100 条 | ❌ 单次最多 100 条,超过需分批 |
|
||||
| 附件/图片字段直传 URL | ❌ 严禁 `{"url":"https://..."}` — 会触发 TIMEOUT_ERROR。必须先 `attachment upload` 获取 `fileToken`,再用 `{"fileToken":"ft_xxx"}` 写入。详见 [aitable-attachment.md](./aitable-attachment.md) |
|
||||
|
||||
## 正确流程
|
||||
|
||||
|
||||
@@ -25,11 +25,12 @@ dws aitable record history-list \
|
||||
"data": {
|
||||
"histories": [
|
||||
{
|
||||
"type": "row", // 变更类型,实测均为 "row"(行级变更)
|
||||
"action": "updateRecords", // 操作动作:appendRow(新增行) / updateRecords(更新记录)
|
||||
"newValue": "{\"fldX\":{\"dataType\":\"STRING\",\"value\":\"改后值\"}}", // 变更后的值(JSON 字符串,按 fieldId 组织)
|
||||
"oldValue": "{\"fldX\":{\"dataType\":\"STRING\",\"value\":\"改前值\"}}", // 变更前的值(appendRow 新增行时无此字段)
|
||||
"type": "field_change", // 变更类型
|
||||
"action": "update", // 操作动作: create / update / delete
|
||||
"newValue": "{\"...\":\"...\"}", // 变更后的值(JSON 字符串)
|
||||
"oldValue": "{\"...\":\"...\"}", // 变更前的值(JSON 字符串)
|
||||
"operateTime": 1733123456789, // 操作时间(毫秒级时间戳)
|
||||
"typeChangedFields": "{...}", // 类型变更的字段信息(JSON 字符串)
|
||||
"version": 7 // 版本号(单调递增)
|
||||
}
|
||||
]
|
||||
@@ -37,14 +38,14 @@ dws aitable record history-list \
|
||||
}
|
||||
```
|
||||
|
||||
`newValue` / `oldValue` 是 JSON 字符串(不是 JSON 对象),需要二次 `JSON.parse` 才能拿到结构化值;解析后是 `{fieldId: {dataType, value}}` 结构。`appendRow`(新增行)事件没有 `oldValue`。实测返回里**没有** `typeChangedFields` 字段。
|
||||
`newValue` / `oldValue` / `typeChangedFields` 是 JSON 字符串(不是 JSON 对象),需要二次 `JSON.parse` 才能拿到结构化值。
|
||||
|
||||
## 字段含义速查
|
||||
|
||||
| 字段 | 用途 |
|
||||
|------|------|
|
||||
| `type` | 实测均为 `row`(行级变更),服务端未按 `record_create` / `field_change` 细分。 |
|
||||
| `action` | 底层操作名:`appendRow`(新增行)/ `updateRecords`(更新记录)。按"动作"统计时以这两个值为准。 |
|
||||
| `type` | 高层分类:`record_create` / `field_change` / `record_delete` 等。先按 type 过滤大类。 |
|
||||
| `action` | 三态:`create` / `update` / `delete`。比 type 粗,但便于按"动作"统计。 |
|
||||
| `version` | 单调递增整数;同一 record 越新值越大。**用作"上一条 vs 这一条"的稳定排序键**。 |
|
||||
| `operateTime` | 毫秒时间戳;可格式化成可读时间。多条同 version 的极端场景用 operateTime 兜底排序。 |
|
||||
|
||||
@@ -73,22 +74,20 @@ dws aitable record history-list --base-id BASE --table-id TBL --record-id REC --
|
||||
|
||||
```bash
|
||||
dws aitable record history-list --base-id BASE --table-id TBL --record-id REC --limit 50 --format json \
|
||||
| jq '[.data.histories[] | select(.action == "updateRecords")][0].oldValue'
|
||||
| jq '[.data.histories[] | select(.action == "update")][0].oldValue'
|
||||
```
|
||||
|
||||
### 4. 只看更新事件(排除新增行)
|
||||
### 4. 找出删除事件(如果存在 delete history)
|
||||
|
||||
```bash
|
||||
dws aitable record history-list --base-id BASE --table-id TBL --record-id REC --format json \
|
||||
| jq '.data.histories[] | select(.action == "updateRecords") | {version, operateTime}'
|
||||
| jq '.data.histories[] | select(.action == "delete") | {version, operateTime}'
|
||||
```
|
||||
|
||||
> 记录被 `record delete` 删除后,其历史不再返回(`histories` 为空数组),无法通过本命令回溯删除事件。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 一次只能查一条 record;如需批量审计多条记录请循环调用。
|
||||
- 仅返回**新增行**(appendRow)与**字段值变更**(updateRecords);记录被删除后其历史不再可查(返回空)。视图、字段定义、表结构变更不在此 history 里。
|
||||
- 仅返回**字段值变更**与**记录生命周期事件**;视图、字段定义、表结构变更不在此 history 里。
|
||||
- 历史保留时长由 server 决定,过老的记录可能不再返回。
|
||||
|
||||
## 与其他 record 命令的关系
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# 记录管理
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `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) |
|
||||
@@ -72,3 +72,49 @@ dws aitable record query --base-id X --table-id Y --all --cursor "上次返回
|
||||
- `--sort` 用 `"order":"desc"` → 必须用 `"direction":"desc"`
|
||||
- 不加 `--field-ids` 拉全字段 → 大表响应体积过大
|
||||
- 全量拉取后在 context 里手动统计 → 应优先用 `--filters` 服务端过滤
|
||||
|
||||
## record query-empty — 找空行
|
||||
|
||||
`record query-empty` 是与 `record query` 平行的独立子命令,专门按表内顺序扫描出"完全没填用户字段"的空行。
|
||||
|
||||
```bash
|
||||
dws aitable record query-empty --base-id BASE_ID --table-id TABLE_ID
|
||||
```
|
||||
|
||||
| flag | 说明 |
|
||||
|------|------|
|
||||
| `--base-id` / `--base` | 必填 |
|
||||
| `--table-id` | 必填 |
|
||||
| `--limit` | 单次**扫描预算**(不是返回数);范围 [1, 100],默认 100 |
|
||||
| `--cursor` | 分页游标。响应中 `nextCursor` 非空 → 用它翻页继续扫;nextCursor 为空(或不存在)→ 已扫完整表 |
|
||||
|
||||
返回结构:
|
||||
|
||||
```jsonc
|
||||
{ "data": { "records": [...], "nextCursor": "..." } }
|
||||
```
|
||||
|
||||
### 关键语义
|
||||
|
||||
1. **`--limit` 是扫描预算不是返回数**:可能扫了 100 条但全部非空,本页 `records: []`。
|
||||
2. **本页空 records ≠ 全表无空行**:必须看 `nextCursor`,nextCursor 还在就要继续翻。
|
||||
3. **空行定义**:除系统字段(recordId / 创建人 / 创建时间 / 修改人 / 修改时间)外,所有 cell 都是 null、空字符串、空集合或空 Map。一般是用户在 UI 上"插入空行"产生的。
|
||||
|
||||
### 典型用法
|
||||
|
||||
```bash
|
||||
# 扫一页,看本页有没有空行
|
||||
dws aitable record query-empty --base-id BASE --table-id TBL
|
||||
|
||||
# 翻页
|
||||
dws aitable record query-empty --base-id BASE --table-id TBL --cursor <上次的nextCursor>
|
||||
|
||||
# 把整表扫完(手动循环 cursor)
|
||||
NC=""
|
||||
while : ; do
|
||||
R=$(dws aitable record query-empty --base-id BASE --table-id TBL ${NC:+--cursor "$NC"} --format json)
|
||||
echo "$R" | jq '.data.records[] | .recordId'
|
||||
NC=$(echo "$R" | jq -r '.data.nextCursor // empty')
|
||||
[ -z "$NC" ] && break
|
||||
done
|
||||
```
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# 相关产品
|
||||
|
||||
## 相关产品
|
||||
|
||||
- [doc](../../../dingtalk-doc/references/doc.md) — 富文本文档编辑,不是结构化数据表格
|
||||
@@ -0,0 +1,10 @@
|
||||
# 自动化脚本
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
| 脚本 | 场景 |
|
||||
|------|------|
|
||||
| [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 表格记录 |
|
||||
@@ -0,0 +1,8 @@
|
||||
# 数据表管理
|
||||
|
||||
| 命令 | 用途 | 必读参数 |
|
||||
|---|---|---|
|
||||
| `table get` | 获取表结构(字段+视图目录) | `--base-id` |
|
||||
| `table create` | 创建数据表 | `--base-id` `--name` `--fields` |
|
||||
| `table update` | 修改表名 / 备注 / 行命名规则 | `--base-id` `--table-id` |
|
||||
| `table delete` | 删除表 | `--base-id` `--table-id` |
|
||||
@@ -0,0 +1,17 @@
|
||||
# 文档地址 (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 表格处理。
|
||||
@@ -0,0 +1,11 @@
|
||||
# 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` 后再继续。
|
||||
@@ -79,21 +79,21 @@ dws aitable view update timebar --view-id GANTT_ID --official-holiday=true
|
||||
|
||||
### view update aggregate(仅 Grid)
|
||||
|
||||
值是 `map[fieldId]→AggregateAction string`。**设置**聚合可用;**清除**聚合当前无效(见下方警告)。
|
||||
值是 `map[fieldId]→AggregateAction string`;传 null 清除某个字段聚合。
|
||||
|
||||
| flag | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `--field-id` | string | 配合 `--action` 设置**单字段**聚合 |
|
||||
| `--action` | string | `SUM`/`AVG`/`MAX`/`MIN`/`MEDIAN`/`RANGE`/`TOTAL`/`DISTINCT`/`EXIST`/`UN_EXIST`/`CHECKED`/`EARLIEST_DATE` 等(按字段类型可用) |
|
||||
| `--clear-field-id` | string (CSV) | 一/多个字段 ID,本意是清除其聚合,但**当前服务端不支持清除,静默无效**(见下方警告) |
|
||||
| `--clear-field-id` | string (CSV) | 一/多个字段 ID,清除其聚合 |
|
||||
| `--json` | JSON | 完整 aggregate map |
|
||||
|
||||
```bash
|
||||
dws aitable view update aggregate --view-id GRID_ID --field-id fldX --action SUM
|
||||
dws aitable view update aggregate --view-id GRID_ID --clear-field-id fldA,fldB
|
||||
dws aitable view update aggregate --view-id GRID_ID --json '{"fldX":"AVG","fldY":null}'
|
||||
```
|
||||
|
||||
> ⚠️ **当前无法清除已设置的聚合(服务端限制)**:`--clear-field-id fldA,fldB` 与 `--json '{"fldX":null}'` 两种清除写法都返回 `success`,但用 `view get aggregate` 复核会发现聚合**原样不动**——是静默无效,不是真的清掉。这是服务端没有清除语义所致,直至服务端修复前不要依赖它。改聚合方式可行(重新 `--action` 覆盖成别的),只是无法回到"无聚合"。
|
||||
|
||||
### view update field-widths(仅 Grid)
|
||||
|
||||
| flag | 类型 |
|
||||
@@ -108,11 +108,9 @@ dws aitable view update field-widths --view-id GRID_ID --json '{"fldA":120,"fldB
|
||||
|
||||
### view update visible-fields(通用)
|
||||
|
||||
整组替换可见字段列表与顺序,同时兼作**隐藏/显示**入口。首列字段(primaryDoc)必须保留在数组第一位。
|
||||
整组替换可见字段列表与顺序。首列字段(primaryDoc)必须保留在数组第一位。
|
||||
|
||||
> **传入的列表既定顺序又定可见性**:传一个比当前 columns 短的列表,缺失的字段会被真正隐藏(该字段在 `view list` 的 `custom.hiddenFields` 里变 `true`);再传回全量列表即可解除隐藏(`hiddenFields` 变 `false`)。
|
||||
>
|
||||
> ⚠️ **查隐藏状态别看这里**:`view get visible-fields` 返回的数组**包含已隐藏字段**(列的完整顺序),看不出谁被隐藏。要确认隐藏状态,读 `view get`(view list)里该视图的 `custom.hiddenFields`(`{fieldId: true|false}`)。
|
||||
> ⚠️ 注意:服务端**只接受 reorder,不接受真"隐藏字段"**——如果传入的列表比当前 columns 短,缺失的字段不会被隐藏。需要真正隐藏字段请到 AI 表格 Web UI。
|
||||
|
||||
| flag | 类型 |
|
||||
|------|------|
|
||||
@@ -120,9 +118,7 @@ dws aitable view update field-widths --view-id GRID_ID --json '{"fldA":120,"fldB
|
||||
| `--json` | string 数组 JSON(与 `--field-ids` 同传时 `--json` 优先) |
|
||||
|
||||
```bash
|
||||
# 只保留首列和 fldA,其余字段被隐藏
|
||||
dws aitable view update visible-fields --view-id VIEW_ID --field-ids fldPrimary,fldA
|
||||
# 传回全量列表解除隐藏
|
||||
dws aitable view update visible-fields --view-id VIEW_ID --field-ids fldPrimary,fldA,fldB
|
||||
dws aitable view update visible-fields --view-id VIEW_ID --json '["fldPrimary","fldA","fldB"]'
|
||||
```
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ dws aitable view update frozen-cols --view-id VIEW_ID --count 0
|
||||
|
||||
# 查询当前冻结列数
|
||||
dws aitable view get frozen-cols --view-id VIEW_ID --format json
|
||||
# → {"data": {..., "count": 1}} 未显式设置时整个 count 键缺失(不是返回 null)
|
||||
# → {"data": {..., "count": 1}} count 为 null 表示视图未显式设置
|
||||
```
|
||||
|
||||
`--count` 必须 ≥ 0;负数会被拒绝。
|
||||
@@ -69,7 +69,7 @@ dws aitable view update row-height --view-id VIEW_ID --cell-height 56
|
||||
|
||||
# 查询当前行高
|
||||
dws aitable view get row-height --view-id VIEW_ID --format json
|
||||
# → {"data": {..., "cellHeight": 56}} 未显式设置时整个 cellHeight 键缺失(不是返回 null;前端按 32 渲染)
|
||||
# → {"data": {..., "cellHeight": 56}} cellHeight 为 null 表示视图未显式设置(前端按 32 渲染)
|
||||
```
|
||||
|
||||
## 数据高亮规则(条件填色,仅 Grid)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# 视图管理
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `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) |
|
||||
@@ -0,0 +1,5 @@
|
||||
# 自动化工作流
|
||||
|
||||
| 命令 | 用途 | 详见 |
|
||||
|---|---|---|
|
||||
| `workflow list/get/enable/disable` | 工作流管理 | [`aitable-workflow.md`](./aitable-workflow.md) |
|
||||
@@ -1,180 +1,21 @@
|
||||
# workflow — 自动化工作流管理
|
||||
# 核心工作流
|
||||
|
||||
启停 / 查看 / 列出 Base 下的自动化工作流(在 AI 表格 Web 端配置的 "当 X 时自动 Y" 流程)。
|
||||
适用场景:用户问 "停掉这个流程"、"看下都有哪些自动化流程"、"流程 X 的配置是什么"。
|
||||
|
||||
## 命令一览
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
| `workflow list` | 列出 Base 下所有工作流(含状态/创建人/最后修改时间),支持分页 |
|
||||
| `workflow get` | 获取单个工作流详情(含 flowSchema 完整节点定义) |
|
||||
| `workflow enable` | 启用指定工作流(按配置的触发条件自动执行) |
|
||||
| `workflow disable` | 禁用指定工作流(高危,建议 `--yes` 二次确认) |
|
||||
|
||||
> 所有子命令的 `--base-id` 必填(可用隐藏别名 `--base`)。
|
||||
> 当前**不支持通过 CLI 新建工作流**,请在 AI 表格 Web 端配置好后用 `workflow list` 拿到 ID 再启停。
|
||||
|
||||
## 命令详情
|
||||
|
||||
### workflow list — 列出工作流
|
||||
## 核心工作流
|
||||
|
||||
```bash
|
||||
dws aitable workflow list --base-id BASE_ID --format json
|
||||
dws aitable workflow list --base-id BASE_ID --limit 50 --offset 100
|
||||
# 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-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
|
||||
```
|
||||
|
||||
| flag | 说明 |
|
||||
|------|------|
|
||||
| `--base-id` | 必填 |
|
||||
| `--limit` | 可选,分页大小 `[1, 100]`,不传走服务端默认 20 |
|
||||
| `--offset` | 可选,分页偏移量 `>= 0`,不传走服务端默认 0 |
|
||||
|
||||
返回结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"list": [
|
||||
{
|
||||
"flowId": "G-FLOW-XXXXXX", // ★ 注意字段名是 flowId
|
||||
"name": "流程1",
|
||||
"description": "当创建记录时,就更新记录",
|
||||
"status": "RUNNING", // RUNNING / STOP
|
||||
"creatorStaffId": "281493",
|
||||
"lastModifier": { "name": "李普阳", "staffId": "281493" },
|
||||
"gmtModified": 1780318540000,
|
||||
"versionId": "G-FLOW-VER-XXXXXX",
|
||||
"icons": ["..."], // 触发器+动作的图标
|
||||
"isSubFlow": false,
|
||||
"opPermissions": { "canEdit": true }
|
||||
}
|
||||
],
|
||||
"recordCount": 1, // Base 下总数
|
||||
"runningCount": 1 // RUNNING 状态的数量
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**注意**:
|
||||
- 标识字段服务端在 `list` 里叫 **`flowId`**,但在 `enable` / `disable` 出参里叫 **`workflowId`**。CLI `--workflow-id` 传任一即可(同值)。
|
||||
- `status` 是字符串枚举:`RUNNING`(启用中)/ `STOP`(已禁用),**不是** boolean。
|
||||
- `runningCount` 是当前 Base 下 status=RUNNING 的工作流数,方便快速判断「有几个流程在跑」。
|
||||
|
||||
### workflow get — 获取单个工作流详情
|
||||
|
||||
```bash
|
||||
dws aitable workflow get --base-id BASE_ID --workflow-id WORKFLOW_ID --format json
|
||||
```
|
||||
|
||||
| flag | 说明 |
|
||||
|------|------|
|
||||
| `--base-id` | 必填 |
|
||||
| `--workflow-id` | 必填,对应 list 出参里的 `flowId` |
|
||||
|
||||
返回完整工作流配置:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"name": "流程1",
|
||||
"namespace": "...",
|
||||
"status": "RUNNING",
|
||||
"versionId": "G-FLOW-VER-XXXXXX",
|
||||
"versionNo": 14,
|
||||
"versionStatus": "...",
|
||||
"accessor": {...}, // 访问者信息
|
||||
"corpId": "...",
|
||||
"flowAttribute": {...}, // 流程顶层属性
|
||||
"flowSchema": {...}, // ★ 流程节点定义(触发器/动作/分支等)
|
||||
"gmtCreate": 1780317804000,
|
||||
"gmtModified": 1780318540000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`flowSchema` 是完整的节点 DAG,结构因流程而异(条件触发器 vs 定时触发器、单分支 vs 多分支等)。agent 应按需读取关心字段,不要试图建静态 schema。
|
||||
|
||||
### workflow enable — 启用工作流
|
||||
|
||||
```bash
|
||||
dws aitable workflow enable --base-id BASE_ID --workflow-id WORKFLOW_ID --format json
|
||||
```
|
||||
|
||||
返回 `{workflowId, enabled: true}` —— **`enabled: true` 是动作确认,不是当前状态查询**。要确认真启用了,必须再 `workflow list` 看 `status` 是否变成 `"RUNNING"` 或 `runningCount` 是否加 1。
|
||||
|
||||
### workflow disable — 禁用工作流(高危)
|
||||
|
||||
```bash
|
||||
dws aitable workflow disable --base-id BASE_ID --workflow-id WORKFLOW_ID --yes --format json
|
||||
```
|
||||
|
||||
返回 `{workflowId, disabled: true}` —— 同样是动作确认。禁用后该工作流不再自动触发。
|
||||
|
||||
**风险**:直接影响业务自动化(如停掉「记录创建后自动发通知」会让通知断流)。建议:
|
||||
- 操作前先 `workflow get` 留底当前配置
|
||||
- 脚本场景显式传 `--yes`;交互场景让用户在 prompt 中再次确认
|
||||
|
||||
## 能力边界
|
||||
|
||||
| 能力 | 状态 |
|
||||
|------|------|
|
||||
| 列出工作流 | ✅ |
|
||||
| 看工作流详情(含 flowSchema) | ✅ |
|
||||
| 启用/禁用 | ✅ |
|
||||
| 新建工作流 | ❌ 当前不支持,请去 AI 表格 Web 端 → 数据表 → 自动化 创建 |
|
||||
| 修改工作流配置 | ❌ 同上,需 Web UI 编辑 |
|
||||
| 删除工作流 | ❌ 同上 |
|
||||
| 查看运行历史/执行日志 | ❌ 暂未开放 |
|
||||
| 手动触发/单次运行 | ❌ 暂未开放 |
|
||||
|
||||
## 错误码速查
|
||||
|
||||
| 场景 | code | type | 备注 |
|
||||
|------|------|------|------|
|
||||
| `workflow-id` 不存在调 get | `GET_WORKFLOW_ERROR` | `SYSTEM_ERROR` | message 可能为 null,先 `workflow list` 核对 ID |
|
||||
| `workflow-id` 不存在调 enable | `ENABLE_WORKFLOW_ERROR` | `SYSTEM_ERROR` | message 含 "场域中不存在该 namespace" |
|
||||
| `workflow-id` 不存在调 disable | `DISABLE_WORKFLOW_ERROR` | `SYSTEM_ERROR` | 同上 |
|
||||
| `--limit` < 1 或 > 100 | (CLI 层拦截) | — | `--limit 必须在 [1, 100] 范围内,got N` |
|
||||
| `--offset` < 0 | (CLI 层拦截) | — | `--offset 必须 >= 0,got N` |
|
||||
|
||||
> 拿到 `*_WORKFLOW_ERROR / SYSTEM_ERROR` 时,先 `workflow list` 自查目标 ID 是否还存在、是否在当前 Base 下。
|
||||
|
||||
## 典型工作流
|
||||
|
||||
### 看看 Base 里有哪些自动化在跑
|
||||
|
||||
```bash
|
||||
dws aitable workflow list --base-id BASE_ID --format json | jq '.data | {total: .recordCount, running: .runningCount, items: .list | map({name, status, flowId})}'
|
||||
```
|
||||
|
||||
### 临时停掉某个流程做调试
|
||||
|
||||
```bash
|
||||
# 1. 留底当前状态
|
||||
dws aitable workflow get --base-id BASE_ID --workflow-id WORKFLOW_ID --format json > /tmp/wf-backup.json
|
||||
|
||||
# 2. 禁用
|
||||
dws aitable workflow disable --base-id BASE_ID --workflow-id WORKFLOW_ID --yes --format json
|
||||
|
||||
# 3. 调试做完后重启
|
||||
dws aitable workflow enable --base-id BASE_ID --workflow-id WORKFLOW_ID --format json
|
||||
|
||||
# 4. 确认 status=RUNNING
|
||||
dws aitable workflow list --base-id BASE_ID --format json | jq '.data.list[] | select(.flowId == "WORKFLOW_ID") | .status'
|
||||
```
|
||||
|
||||
### 批量关掉某个 Base 下所有 workflow(调试 / 迁移前清场)
|
||||
|
||||
```bash
|
||||
for WF in $(dws aitable workflow list --base-id BASE_ID --limit 100 --format json | jq -r '.data.list[] | select(.status == "RUNNING") | .flowId'); do
|
||||
dws aitable workflow disable --base-id BASE_ID --workflow-id "$WF" --yes --format json | jq .status
|
||||
done
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- `--workflow-id` 接受的就是 `list` 返回里的 `flowId`(同值,CLI 屏蔽了服务端字段名差异)。
|
||||
- enable / disable 出参里的 `enabled` / `disabled` 是 **动作确认 flag**,不是当前状态字段。要确认真生效请走 `workflow list` 查 `status`。
|
||||
- `workflow get` 的 `flowSchema` 结构随触发器/动作类型变化,不要假设固定字段。
|
||||
- 新建/修改/删除工作流目前必须在 AI 表格 Web 端(数据表页面 → 自动化)完成。
|
||||
|
||||
@@ -83,7 +83,7 @@ dws aitable table create --base-id <BASE_ID> --name "产品图片" \
|
||||
|
||||
## 记录写入格式(record create / record update)
|
||||
|
||||
> 各字段类型的完整写入/读取格式规范请参考:[aitable-cell-value.md](./products/aitable/aitable-cell-value.md)
|
||||
> 各字段类型的完整写入/读取格式规范请参考:[aitable-cell-value.md](./aitable/aitable-cell-value.md)
|
||||
>
|
||||
> 该文件是 cellValue 格式的 **source of truth**,包含所有字段类型的详细示例和注意事项。
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# aitable 局部意图消歧
|
||||
|
||||
本文件从单 Skill `intent-guide.md` 拆分而来,仅保留与本产品相关的跨产品消歧规则。
|
||||
|
||||
| 用户说... | 真实意图 | 应该用 | 不要用 | 理由 |
|
||||
|---|---|---|---|---|
|
||||
| "帮我建一个项目跟踪表" | 创建数据表格 | `aitable` | `doc` / `sheet` | 涉及结构化数据/行列操作,不是富文本文档或电子表格 |
|
||||
| "帮我写个项目周报" | 创建钉钉文档 | `doc` | `aitable` | 富文本内容创作,不是数据表 |
|
||||
| "创建一个电子表格" | 创建表格文档 | `sheet` | `aitable` | Excel 式表格/单元格操作,不是多维表记录 |
|
||||
| "帮我读一下表格 A1:D10 的数据" | 读取单元格数据 | `sheet` | `aitable` | 按单元格区域读写,不是按记录查询 |
|
||||
@@ -0,0 +1,129 @@
|
||||
# URL 格式与处理规范
|
||||
|
||||
## alidocs URL 分流决策(必须首先执行)
|
||||
|
||||
收到 `alidocs.dingtalk.com` URL 时,**必须按以下顺序判断,禁止跳过**:
|
||||
|
||||
1. URL 路径含 `/i/p/` → **分享短链**,禁止调用 `dws doc` 任何子命令 → 按下方 [分享短链处理](#分享短链处理) 执行
|
||||
2. URL 路径含 `/i/nodes/` → **节点链接**,需探测类型 → 按下方 [alidocs URL 类型探测流程](#alidocs-url-类型探测流程) 执行
|
||||
3. URL 路径含 `/spreadsheetv2/` → **电子表格直链**,直接路由到 `sheet`,将完整 URL 原样传给 `--node` 参数
|
||||
4. URL 路径含 `/document/edit` 或 `/document/preview` 且 query 参数包含 `dentryKey` → **文档链接**,直接路由到 `doc`,将完整 URL 原样传给 `--node` 参数(URL 中不一定有 `type=d`,只需匹配路径和 `dentryKey` 参数即可)
|
||||
5. 其他 alidocs URL 格式 → 告知用户当前暂不支持该链接格式
|
||||
|
||||
---
|
||||
|
||||
## 已知 URL 格式
|
||||
|
||||
需要自行拼接链接时,只能使用以下模板:
|
||||
|
||||
| 产品 | 用途 | URL 格式 | ID 来源 |
|
||||
|------|------|----------|---------|
|
||||
| `aitable` | AI表格 Base 链接 | `https://alidocs.dingtalk.com/i/nodes/{baseId}` | `base list/search/create/get` 返回的 `baseId` |
|
||||
| `aitable` | AI表格指定数据表链接 | `https://alidocs.dingtalk.com/i/nodes/{baseId}?iframeQuery=sheetId%3D{tableId}` | `baseId` + `table create/get` 或 `base get` 返回的 `tableId` |
|
||||
| `aitable` | AI表格指定数据表+视图链接 | `https://alidocs.dingtalk.com/i/nodes/{baseId}?iframeQuery=sheetId%3D{tableId}%26viewId%3D{viewId}` | `baseId` + `tableId` + `view create/get` 返回的 `viewId` |
|
||||
| `aitable` | AI表格模板预览 | `https://docs.dingtalk.com/table/template/{templateId}` | `template search` 返回的 `templateId` |
|
||||
| `doc` | 文档链接 | `https://alidocs.dingtalk.com/i/nodes/{dentryUuid}` | `doc` 命令返回的 `dentryUuid` |
|
||||
| `sheet` | 电子表格链接 | `https://alidocs.dingtalk.com/i/nodes/{dentryUuid}` | `sheet create` 返回的 `dentryUuid` |
|
||||
| `sheet` | 电子表格直链 | `https://alidocs.dingtalk.com/spreadsheetv2/{key}/...?dentryKey={key}&type=s` | 用户提供的完整 URL,直接传给 `--node` |
|
||||
| `doc` | 文档链接(edit/preview) | `https://alidocs.dingtalk.com/document/{edit\|preview}?...&dentryKey={key}` | 用户提供的完整 URL,直接传给 `--node` |
|
||||
| `minutes` | 听记链接 | `https://shanji.dingtalk.com/app/transcribes/{taskUuid}` | `list mine/shared` 返回的 `taskUuid` |
|
||||
|
||||
不在此表中的产品,禁止自行拼接 URL。命令返回中包含完整链接时直接使用,否则告知用户无法提供。
|
||||
|
||||
## 分享短链处理
|
||||
|
||||
`alidocs.dingtalk.com/i/p/{shortKey}` 是钉钉文档的**对外分享短链**,`dws doc` 命令无法解析此格式。
|
||||
|
||||
### 识别规则
|
||||
|
||||
URL 路径中包含 `/i/p/` 即为分享短链(无论后面是否还有子路径),例如:
|
||||
- `https://alidocs.dingtalk.com/i/p/Y7kmbokZp3pgGLq2`
|
||||
- `https://alidocs.dingtalk.com/i/p/Y7kmbokZp3pgGLq2/docs/AY39rGpMPmeVNpXZevZm8OZkXKnaoNQ7`
|
||||
- `https://alidocs.dingtalk.com/i/p/AbCdEfGh1234`
|
||||
- `https://alidocs.dingtalk.com/i/p/AbCdEfGh1234/sheets/XYZ789`
|
||||
|
||||
> **关键**:只要 URL 中出现 `/i/p/`,无论后面跟什么子路径(`/docs/...`、`/sheets/...` 等),都属于分享短链,一律禁止调用 `dws doc`。
|
||||
|
||||
### 处理方式
|
||||
|
||||
**不要调用 `dws doc` 任何子命令**(包括 `doc info`、`doc read` 等),`dws` 无法解析此格式。
|
||||
|
||||
- **需要获取文档内容时**:使用 `read_url` 工具直接读取该链接
|
||||
- **其他操作(如移动、复制、权限管理等)**:告知用户此链接为分享短链,无法直接执行复制、移动、权限管理等操作。如需保存该文档内容,建议用户在钉钉客户端中打开该页面,手动复制文本内容,然后可通过 `dws doc create` 创建一篇新文档并将内容写入
|
||||
|
||||
```
|
||||
# 需要读取文档内容时(无论 /i/p/ 后面有没有子路径,都用 read_url)
|
||||
read_url("https://alidocs.dingtalk.com/i/p/Y7kmbokZp3pgGLq2")
|
||||
read_url("https://alidocs.dingtalk.com/i/p/Y7kmbokZp3pgGLq2/docs/AY39rGpMPmeVNpXZevZm8OZkXKnaoNQ7")
|
||||
|
||||
# 禁止(以下全部会失败,dws 无法解析任何含 /i/p/ 的 URL)
|
||||
dws doc info --node "https://alidocs.dingtalk.com/i/p/Y7kmbokZp3pgGLq2" --format json
|
||||
dws doc read --node "https://alidocs.dingtalk.com/i/p/Y7kmbokZp3pgGLq2/docs/AY39rGpMPmeVNpXZevZm8OZkXKnaoNQ7" --format json
|
||||
```
|
||||
|
||||
### 当 `read_url` 返回内容不完整时
|
||||
|
||||
钉钉文档分享页是动态渲染的,`read_url` 可能只能获取到页面标题等有限信息,无法获取文档正文。此时**禁止猜测原因**(如"权限不足""文档为空""文档已删除"等),**禁止建议用户"提供 `/i/nodes/` 格式链接"**(分享短链和节点链接是不同体系,普通用户无法自行转换)。应直接告知用户:
|
||||
|
||||
> 这个链接是钉钉文档的分享短链,由于页面是动态渲染的,我无法通过该链接直接获取文档的完整正文内容。
|
||||
>
|
||||
> 你可以:
|
||||
> 1. 在钉钉客户端中打开该文档,将正文内容复制粘贴给我
|
||||
> 2. 如果文档已保存在你的文档空间中,可以告诉我文档名称,我通过 `dws drive search` 搜索后再读取
|
||||
|
||||
---
|
||||
|
||||
## alidocs URL 类型探测流程
|
||||
|
||||
`alidocs.dingtalk.com/i/nodes/{id}` 是钉钉文档空间的统一 URL,可能指向**文档、电子表格、多维表、文件、文件夹**等不同类型。**禁止仅凭 URL 就假定为文档**,必须先探测类型再路由到正确的产品。
|
||||
|
||||
### 探测步骤
|
||||
|
||||
```
|
||||
Step 1 → dws doc info --node "<URL>" --format json
|
||||
Step 2 → 从返回中提取 contentType、extension、nodeType 字段
|
||||
Step 3 → 按下方路由规则映射到对应产品
|
||||
```
|
||||
|
||||
### 路由映射表
|
||||
|
||||
| 条件 | 路由到产品 | 后续操作 |
|
||||
|------|-----------|---------|
|
||||
| `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` 下载,返回文件下载链接 |
|
||||
| `nodeType=folder` | `drive` / `wiki` | 调用 `dws drive list --workspace <WS_ID>` 或 `dws wiki node list` 列出子节点 |
|
||||
| 以上均不匹配 | — | 告知用户当前暂不支持该类型 |
|
||||
|
||||
> axls vs xlsx 关键区分:
|
||||
> - `axls`(钉钉在线电子表格,`contentType=ALIDOC`)→ 走 `sheet` 产品线(读/写/筛选/导出等服务端原子操作)
|
||||
> - `xlsx` / `xls` / `xlsm` / `csv`(上传到文档空间的本地表格文件,`contentType=DOCUMENT`)→ 必须走 `dws drive download` 下载到本地后再解析处理,严禁错误路由到 `sheet` 产品线(sheet 命令只支持在线表格,调用 xlsx 节点会直接报错)
|
||||
> - 用户想把在线表格导出为 xlsx 文件 → 用 `dws sheet export`(输入是 `axls`,输出是 xlsx,这是 axls → xlsx 的格式转换,不属于 xlsx 读取场景)
|
||||
|
||||
### 示例
|
||||
|
||||
```bash
|
||||
# 用户传入: https://alidocs.dingtalk.com/i/nodes/abc123
|
||||
dws doc info --node "https://alidocs.dingtalk.com/i/nodes/abc123" --format json
|
||||
|
||||
# 返回 contentType=ALIDOC, 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"
|
||||
|
||||
# 返回 contentType≠ALIDOC, nodeType=file → 普通文件,下载
|
||||
dws drive download --node "https://alidocs.dingtalk.com/i/nodes/def456"
|
||||
|
||||
# 返回 nodeType=folder → 文件夹,列出子节点
|
||||
dws drive list --workspace <WS_ID> --format json
|
||||
```
|
||||
|
||||
### 何时可跳过探测
|
||||
|
||||
当用户指令中已明确指定产品(如"帮我读这个文档"、"看下这个表格的数据"),可结合用户意图**跳过探测**直接路由。仅在以下情况**必须执行探测**:
|
||||
- 用户只粘贴 URL,无其他上下文
|
||||
- 用户指令与 URL 实际类型可能不一致(如说"文档"但实际是表格)
|
||||
- 用户直接粘贴的是原始 `alidocs` URL,且没有上游命令返回来确认类型
|
||||
@@ -90,10 +90,8 @@ def build_start_args(args: argparse.Namespace) -> list[str]:
|
||||
args.scope,
|
||||
"--format",
|
||||
args.export_format,
|
||||
# CLI 的 --timeout-ms 是单次等待上限(毫秒,最大 30000);脚本自身的
|
||||
# --timeout-sec 用于整体轮询/子进程超时,二者语义不同,不能混用。
|
||||
"--timeout-ms",
|
||||
"30000",
|
||||
str(args.timeout_ms),
|
||||
]
|
||||
if args.table_id:
|
||||
cmd.extend(["--table-id", args.table_id])
|
||||
@@ -109,8 +107,9 @@ def main() -> None:
|
||||
parser.add_argument("--table-id", help="scope=table/view 时必填")
|
||||
parser.add_argument("--view-id", help="scope=view 时必填")
|
||||
parser.add_argument("--export-format", default="excel", choices=sorted(ALLOWED_FORMATS), help="导出格式")
|
||||
parser.add_argument("--timeout-sec", type=int, default=300, help="CLI 内置轮询整体超时(秒),默认 300(5 分钟)")
|
||||
parser.add_argument("--max-polls", type=int, default=10, help="(兼容旧参数,开源 CLI 内置轮询不再使用)")
|
||||
parser.add_argument("--timeout-ms", type=int, default=1000, help="单次等待毫秒数,默认 1000")
|
||||
parser.add_argument("--poll-timeout-ms", type=int, default=3000, help="轮询等待毫秒数,默认 3000")
|
||||
parser.add_argument("--max-polls", type=int, default=10, help="最大轮询次数,默认 10")
|
||||
parser.add_argument("--output", help="本地保存路径(不传则按 fileName 保存到当前目录)")
|
||||
parser.add_argument("--dws", default="dws", help="dws 可执行文件路径,默认 dws")
|
||||
parser.add_argument("--no-download", action="store_true", help="仅返回 downloadUrl,不下载文件")
|
||||
@@ -155,9 +154,9 @@ def main() -> None:
|
||||
"--task-id",
|
||||
task_id,
|
||||
"--timeout-ms",
|
||||
"30000",
|
||||
str(args.poll_timeout_ms),
|
||||
],
|
||||
timeout_sec=max(120, args.timeout_sec + 60),
|
||||
timeout_sec=max(120, int(args.poll_timeout_ms / 1000) + 60),
|
||||
)
|
||||
if rc2 != 0:
|
||||
fail(f"export_data 轮询失败: {err2 or out2}", rc2)
|
||||
|
||||
@@ -77,7 +77,7 @@ def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="通过文件导入任务导入 AI 表格")
|
||||
parser.add_argument("base_id", help="目标 AI 表格 baseId")
|
||||
parser.add_argument("file_path", help="待导入文件路径(.csv/.xlsx/.xls)")
|
||||
parser.add_argument("--timeout-sec", type=int, default=300, help="CLI 内置轮询整体超时(秒),默认 300(5 分钟)")
|
||||
parser.add_argument("--timeout", type=int, default=30, help="import_data 等待秒数,默认 30")
|
||||
parser.add_argument("--dws", default="dws", help="dws 可执行文件路径,默认 dws")
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -140,14 +140,12 @@ def main() -> None:
|
||||
"data",
|
||||
"--import-id",
|
||||
import_id,
|
||||
# import data 的 --timeout 单位是秒、最大 30;脚本的 --timeout-sec
|
||||
# 是整体子进程预算,不能直接透传,这里用 CLI 允许的最大值。
|
||||
"--timeout",
|
||||
"30",
|
||||
str(args.timeout),
|
||||
"--format",
|
||||
"json",
|
||||
],
|
||||
timeout_sec=max(120, args.timeout_sec + 30),
|
||||
timeout_sec=max(120, args.timeout + 30),
|
||||
)
|
||||
if rc2 != 0:
|
||||
fail(f"import_data 调用失败: {err2 or out2}", rc2)
|
||||
|
||||
@@ -29,14 +29,14 @@ 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',
|
||||
'attachment', 'url', 'richText', 'telephone', 'email', 'idCard',
|
||||
'barcode', 'geolocation', 'primaryDoc', 'formula', 'unidirectionalLink',
|
||||
'bidirectionalLink', 'creator', 'lastModifier', 'createdTime',
|
||||
'lastModifiedTime',
|
||||
'barcode', 'geolocation', 'address', 'primaryDoc', 'formula',
|
||||
'unidirectionalLink', 'bidirectionalLink', 'lookup', 'filterUp',
|
||||
'creator', 'lastModifier', 'createdTime', 'lastModifiedTime',
|
||||
}
|
||||
FIELD_TYPE_ALIASES = {
|
||||
'phone': 'telephone',
|
||||
@@ -121,9 +121,32 @@ def validate_field_config(field: Dict[str, Any]) -> Tuple[bool, str]:
|
||||
)
|
||||
|
||||
if field_type in {'unidirectionalLink', 'bidirectionalLink'}:
|
||||
linked_sheet_id = (config or {}).get('linkedSheetId')
|
||||
if not linked_sheet_id or not validate_resource_id(linked_sheet_id):
|
||||
return False, '关联字段必须提供合法的 config.linkedSheetId'
|
||||
linked_table_id = (config or {}).get('linkedTableId')
|
||||
if not linked_table_id or not validate_resource_id(linked_table_id):
|
||||
return False, (
|
||||
'关联字段必须提供合法的 config.linkedTableId(目标 Table ID)'
|
||||
)
|
||||
|
||||
if field_type == 'lookup':
|
||||
cfg = config or {}
|
||||
if not cfg.get('associateField'):
|
||||
return False, 'lookup 必须提供 config.associateField(本表关联字段的 fieldId)'
|
||||
if not cfg.get('valuesField'):
|
||||
return False, 'lookup 必须提供 config.valuesField(关联目标表中要取值的字段 fieldId)'
|
||||
if not cfg.get('aggregator'):
|
||||
return False, 'lookup 必须提供 config.aggregator(SUM/AVERAGE/COUNT/MAX/MIN/CONCATENATE)'
|
||||
|
||||
if field_type == 'filterUp':
|
||||
cfg = config or {}
|
||||
if not cfg.get('targetSheet'):
|
||||
return False, 'filterUp 必须提供 config.targetSheet(目标 Table ID)'
|
||||
filters = cfg.get('filters')
|
||||
if not filters or not isinstance(filters, list):
|
||||
return False, 'filterUp 必须提供 config.filters(至少一条筛选规则)'
|
||||
if not cfg.get('valuesField'):
|
||||
return False, 'filterUp 必须提供 config.valuesField(目标表中要取值的字段 fieldId)'
|
||||
if not cfg.get('aggregator'):
|
||||
return False, 'filterUp 必须提供 config.aggregator(SUM/AVERAGE/COUNT/MAX/MIN/CONCATENATE)'
|
||||
|
||||
return True, ''
|
||||
|
||||
|
||||
@@ -11,6 +11,13 @@
|
||||
- JSON 支持两种格式:
|
||||
1. [{"cells": {"fldxxx": "value"}}, ...]
|
||||
2. [{"fldxxx": "value"}, ...] # 会自动包装成 cells
|
||||
|
||||
⚠️ CSV 自动类型转换风险:
|
||||
CSV 读入的所有 cell 都是 string,本脚本会尝试自动识别 'true'/'false'/数字
|
||||
并转成对应类型(避免 text 字段塞入纯文本数字)。但当 fieldId 对应的字段是
|
||||
text / telephone / idCard / barcode 这类"字符串形数字"字段时,自动转 int / float
|
||||
会让 server 拒绝(字段类型不匹配)。这种情况建议改用 JSON 格式(自己显式控制类型),
|
||||
或在 CSV 写入前给字段值前缀加引号 / 改为非纯数字。
|
||||
"""
|
||||
|
||||
import sys
|
||||
@@ -28,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
|
||||
|
||||
@@ -131,9 +138,7 @@ def normalize_record(record: Dict[str, Any]) -> Dict[str, Any]:
|
||||
return {'cells': normalized}
|
||||
|
||||
|
||||
def validate_record(
|
||||
record: Dict[str, Any], headers: List[str]
|
||||
) -> Tuple[bool, str]:
|
||||
def validate_record(record: Dict[str, Any]) -> Tuple[bool, str]:
|
||||
if not isinstance(record, dict):
|
||||
return False, '记录必须是对象'
|
||||
normalized = normalize_record(record)
|
||||
@@ -238,7 +243,7 @@ def import_from_json(
|
||||
return False
|
||||
|
||||
for i, record in enumerate(records):
|
||||
valid, error = validate_record(record, [])
|
||||
valid, error = validate_record(record)
|
||||
if not valid:
|
||||
print(f"错误:记录 #{i+1} 格式无效:{error}")
|
||||
return False
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: dingtalk-attendance
|
||||
description: 钉钉考勤。Use when 用户说 考勤/打卡记录/查打卡/查班次/考勤汇总/考勤规则/出勤情况/请假加班补卡/排班/考勤组/假期余额。命令前缀:dws attendance。支持查询与写操作(班次、排班、考勤组、个人规则设置、假期规则/余额等),写操作需二次确认后再加 --yes。
|
||||
description: 钉钉考勤、打卡、排班与考勤报表。Use when 用户说考勤/打卡记录/查打卡/排班/班次/考勤报表/导出考勤/出勤汇总/考勤明细/迟到早退统计/全员考勤数据/某月考勤统计/考勤表格/考勤Excel。不做日程会议(走 dingtalk-calendar)、日报周报(走 dingtalk-report)、审批请假流程(走 dingtalk-oa)。命令前缀:dws attendance。
|
||||
cli_version: ">=0.2.14"
|
||||
metadata:
|
||||
category: product
|
||||
@@ -14,38 +14,40 @@ metadata:
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
> **PREREQUISITE:** Read the `dws-shared` skill first for auth, global flags, product routing, URL preflight, error codes, and safety rules. The `dws` binary must be on PATH.
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> ⚠️ **命令可用性以当前 dws 二进制为准**。服务发现已下线,本文档随内置 skill 发布;如果 `dws <cmd> --help` 不存在,说明当前版本未暴露该命令。若命令存在但调用失败,请按错误中的 endpoint 或 tool 提示确认静态端点目录和后端工具注册。实际调用前可用 `dws <cmd> --help` 或 `--dry-run` 验证。
|
||||
> 渐进式参考:[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)。
|
||||
> 旧路径兼容入口:[attendance.md](references/attendance.md)。
|
||||
|
||||
## 意图表
|
||||
|
||||
| 用户说 | 命令 |
|
||||
|--------|------|
|
||||
| "查我 / 某人 某天的打卡" | `dws attendance record get --user <userId> --date <YYYY-MM-DD>` |
|
||||
| "查考勤组 / 考勤规则 / 打卡范围" | `dws attendance rules --date <YYYY-MM-DD>` |
|
||||
| "查班次 / 排班 / 谁今天上什么班" | `dws attendance shift list --users <userId1,userId2> --start <YYYY-MM-DD> --end <YYYY-MM-DD>` |
|
||||
| "考勤统计 / 周月汇总 / 出勤天数" | `dws attendance summary --user <userId> --date <YYYY-MM-DD> --stats-type week\|month` |
|
||||
| "请假 / 加班 / 补卡 / 出差 记录或提交链接" | `dws attendance approve list` / `dws attendance approve templates --type <类型>` |
|
||||
| "班次 / 补卡规则 / 加班规则 / 考勤组 查询与修改" | `class` / `adjustment` / `overtime` / `group` 子命令 |
|
||||
| "排班 / 假期规则 / 假期余额 / 签到 / 报表" | `schedule` / `vacation` / `checkin` / `report` 子命令 |
|
||||
| "查我自己的打卡 / 某天考勤" | `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 ...`(需确认) |
|
||||
|
||||
> 完整命令集(含写操作与参数)见 [references/attendance.md](references/attendance.md)。
|
||||
## 高频硬约束
|
||||
|
||||
## 评测高频硬约束
|
||||
|
||||
- 当前 dws 已注册全部考勤子命令组(`record` / `check` / `approve` / `shift` / `schedule` / `class` / `adjustment` / `overtime` / `group` / `summary` / `rules` / `selfsetting` / `globalsetting` / `vacation` / `checkin` / `report` / `boss-check`),查询与写操作大多可直接调用后端。**不要再以"开源版只读/不支持写操作"为由拒答。** 创建班次、导入排班、加人入考勤组、保存个人规则设置、设置假期余额等写操作可执行,但必须先展示参数摘要并二次确认,再追加 `--yes`(或 `--user-say-yes`)执行;不要在未确认时直接写、也不要伪装成功。个别命令受权限/数据影响返回空或权限错误(如 `report` 系列仅管理员),如实说明即可。
|
||||
- 不要在读完 [attendance.md](references/attendance-commands.md) 前判断"CLI 不支持"。`class create`、`schedule import`、`group update-members`、`group update` 都是已支持写操作,但必须先展示摘要并等用户确认。
|
||||
- 查询迟到/缺勤名单时,空打卡结果不等于"没人迟到"。必须结合排班、`NotSigned`、`Absenteeism`、无记录人员分别说明;数据缺失要标为"无记录/无法判断",不要归为正常。
|
||||
- 做部门 Top N 排名时,用户要求前 N 名就必须输出 N 个部门;无打卡记录或无可计算数据的部门按 0 或"无数据"保留在排名中,不能只输出有数据的少数部门。
|
||||
- `summary` 必须同时传 `--user`、`--date`、`--stats-type`(week/month),缺一返回 C0002。
|
||||
- `shift list` 时间跨度不超过 7 天,最多 50 人;`record get` 一次只查一个用户一天。
|
||||
- 所有 dws 命令带 `--format json`,时间/日期按命令要求分别使用 `YYYY-MM-DD` 或 `yyyy-MM-dd HH:mm:ss`。
|
||||
- 处理请假/补卡/加班审批时,先用考勤审批模板或 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)。
|
||||
|
||||
@@ -0,0 +1,998 @@
|
||||
# 命令总览
|
||||
|
||||
## 命令总览
|
||||
|
||||
|
||||
### 查询打卡结果
|
||||
```
|
||||
Usage:
|
||||
dws attendance check result [flags]
|
||||
Example:
|
||||
dws attendance check result --users userId1,userId2 --start 2026-04-01 --end 2026-04-30 --limit 50
|
||||
Flags:
|
||||
--start string 起始日期, 格式 YYYY-MM-DD (必填)
|
||||
--end string 结束日期, 格式 YYYY-MM-DD, 不超过 1 个月 (必填)
|
||||
--limit int 分页大小, 默认 100, 范围 1-1000 (可选)
|
||||
--offset int 分页偏移量, 默认 0 (可选)
|
||||
--users string 用户 ID 列表, 逗号分隔, 最多 100 个 (必填)
|
||||
```
|
||||
|
||||
返回每条记录含:用户 ID、工作日期、时间结果(Normal/Late/Early/Absenteeism/NotSigned)、位置结果、计划打卡时间、实际打卡时间、打卡流水 ID。时间跨度不超过 1 个月,最多 100 人。
|
||||
|
||||
### 查询打卡流水
|
||||
```
|
||||
Usage:
|
||||
dws attendance check record [flags]
|
||||
Example:
|
||||
dws attendance check record --users userId1 --start 2026-04-01 --end 2026-04-30
|
||||
Flags:
|
||||
--start string 起始日期, 格式 YYYY-MM-DD (必填)
|
||||
--end string 结束日期, 格式 YYYY-MM-DD, 不超过 1 个月 (必填)
|
||||
--users string 用户 ID 列表, 逗号分隔 (必填)
|
||||
```
|
||||
|
||||
返回每条记录含:用户 ID、实际打卡时间、打卡地址、打卡经纬度、打卡类型(OnDuty/OffDuty)、定位方式(Map/Wifi/etc)。时间跨度不超过 1 个月。
|
||||
|
||||
### 查询审批单(补卡/加班/请假/出差外出)
|
||||
```
|
||||
Usage:
|
||||
dws attendance approve list [flags]
|
||||
Example:
|
||||
dws attendance approve list --users userId1 --types overtime,leave --start 2026-04-01 --end 2026-04-30
|
||||
dws attendance approve list --users userId1 --types trip --start 2026-04-01 --end 2026-04-30 # 同时返回出差与外出
|
||||
dws attendance approve list --users userId1 --types 加班,请假,补卡 --start 2026-04-01 --end 2026-04-30
|
||||
Flags:
|
||||
--start string 起始日期, 格式 YYYY-MM-DD (必填)
|
||||
--end string 结束日期, 格式 YYYY-MM-DD (必填)
|
||||
--types string 审批类型, 逗号分隔: overtime/加班、trip/travel/business_trip/出差/外出、leave/请假、patch/repair-check/补卡 (必填)
|
||||
--users string 用户 ID 列表, 逗号分隔 (必填)
|
||||
```
|
||||
|
||||
审批类型映射(关键词 → bizType):
|
||||
- `overtime` / `加班` → `1`
|
||||
- `trip` / `travel` / `business_trip` / `business-trip` / `出差` / `外出` → `2`(**服务端查询接口 bizType=2 同时覆盖出差与外出,两者合并为同一类、不再细分**;传入任一别名都会返回这两类记录)
|
||||
- `leave` / `请假` → `3`
|
||||
- `patch` / `repair-check` / `repair_check` / `补卡` → `4`
|
||||
|
||||
> 查询不区分外出与出差,如果需要在提交入口区分外出(`TRAVEL`)与出差(`OUT`),请改用 `dws attendance approve templates --type travel|out`。
|
||||
|
||||
返回每条记录含:用户 ID、审批标签、审批子类型、审批类型、生效时间、时长、时长单位、流程实例 ID。
|
||||
|
||||
### 查询补卡/请假/加班/外出/出差审批提交链接 (必须走引导流程)
|
||||
```
|
||||
Usage:
|
||||
dws attendance approve templates [flags]
|
||||
Example:
|
||||
dws attendance approve templates --type leave
|
||||
dws attendance approve templates --type REPAIR_CHECK
|
||||
dws attendance approve templates --type 加班
|
||||
dws attendance approve templates --type travel # 外出,等价 --type TRAVEL
|
||||
dws attendance approve templates --type 出差 # 出差,等价 --type OUT
|
||||
Flags:
|
||||
--type string 审批类型:repair-check/patch/补卡、leave/请假、overtime/加班、travel/外出、out/trip/出差,或 REPAIR_CHECK/LEAVE/OVERTIME/TRAVEL/OUT(必填)
|
||||
```
|
||||
|
||||
当用户提到需要提交补卡、请假、加班、外出或出差时,优先使用该命令查询考勤审批表单模板提交链接,并引导用户点击返回的 `submitUrl` 提交。
|
||||
`corpId` 和 `opUserId` 由系统参数自动注入,无需通过命令参数传入。
|
||||
审批类型映射:补卡=`REPAIR_CHECK`,请假=`LEAVE`,加班=`OVERTIME`,外出=`TRAVEL`,出差=`OUT`(`trip` / `business_trip` / `business-trip` 亦映射为 `OUT`)。返回结果为列表,每条记录包含 `approveType`、`formName`、`processCode`、`submitUrl`。
|
||||
#### 引导用户自主选择合适的表单模板流程
|
||||
如果返回多个表单模板,必须将多个可用模板都返回给用户,并引导用户根据实际场景自主选择合适的模板提交:
|
||||
- 请假场景:可根据 `formName` 将与用户请假类型更匹配的模板放在前面展示。例如用户明确说年假、事假、病假、调休时,将名称中包含对应假期类型的模板靠前;如果用户只泛化表达“请假”,将名称最通用的请假模板靠前,例如“请假”“员工请假”“通用请假”等,避免把专项或特殊场景模板放在最前。
|
||||
- 补卡/加班场景:可将名称与“补卡”或“加班”最直接匹配的模板放在前面展示。
|
||||
- 回复用户时不要直接裸露任何 `submitUrl`,所有返回的表单模板都必须使用 Markdown 可点击链接格式展示:`[formName](submitUrl)`,例如 `[员工请假](https://...)`。如存在更匹配的模板,可以放在列表前面,但不要只返回推荐模板,必须同时返回其它可用模板供用户选择,且每个模板都应是用户可直接点击的 Markdown 链接。
|
||||
|
||||
### 导入排班记录(排班 = 为员工安排工作日期和班次, 写场景接口,必须走二次确认流程)
|
||||
```
|
||||
Usage:
|
||||
dws attendance schedule import [flags]
|
||||
Example:
|
||||
dws attendance schedule import --group-id 123456 \
|
||||
--schedules '[{"userId":"user001","classId":123,"workDate":"2026-04-22","checkBeginTime":"09:00","checkEndTime":"18:00"}]' \
|
||||
--yes
|
||||
Flags:
|
||||
--group-id string 考勤组(必填,传入考勤组ID)
|
||||
--schedules string 排班记录 JSON 数组(必填)
|
||||
--yes 跳过确认提示
|
||||
```
|
||||
|
||||
为排班制考勤组导入排班记录。`--schedules` 为 JSON 数组,每条记录包含:
|
||||
- `userId`: 员工ID
|
||||
- `classId`: 班次ID
|
||||
- `workDate`: 工作日期(YYYY-MM-DD),如 2026-04-22
|
||||
- `checkBeginTime`: 开始打卡时间
|
||||
- `checkEndTime`: 结束打卡时间
|
||||
- `isRest`: 是否休息日 Y/N(可选)
|
||||
|
||||
#### AI 调用 `schedule import` 的二次确认流程
|
||||
|
||||
`schedule import` 是写操作,会为考勤组导入或变更员工排班。AI 调用时必须按以下流程执行,不得在未确认的情况下直接导入:
|
||||
|
||||
1. **识别写操作**:用户表达“导入排班 / 设置排班 / 安排排班 / 给员工排班 / 批量排班”等意图时,命中 `schedule import`。
|
||||
2. **收集必要参数**:必须明确 `--group-id` 和 `--schedules`,并确认排班记录中的 `userId`、`classId`、`workDate`、`checkBeginTime`、`checkEndTime`、`isRest` 等字段。
|
||||
3. **展示导入摘要并反问确认**:向用户展示考勤组 ID、导入员工数量、涉及日期范围、班次 ID 列表,以及排班记录明细摘要,并询问是否确认执行导入。
|
||||
4. **用户确认后再执行导入**:只有用户明确确认后,才可以执行 `dws attendance schedule import ... --format json`。
|
||||
|
||||
确认话术示例:
|
||||
|
||||
```text
|
||||
即将导入排班记录,请确认:
|
||||
- 考勤组 ID:<GROUP_ID>
|
||||
- 员工数量:<USER_COUNT>
|
||||
- 日期范围:<START_DATE> ~ <END_DATE>
|
||||
- 班次 ID:<CLASS_IDS>
|
||||
- 排班明细:
|
||||
- <USER_ID>:<WORK_DATE> <CHECK_BEGIN_TIME>-<CHECK_END_TIME>,班次 <CLASS_ID>
|
||||
|
||||
是否确认执行导入?
|
||||
```
|
||||
|
||||
如用户明确要求跳过确认,或命令中明确包含全局 `--yes`,可跳过二次确认。
|
||||
|
||||
### 获取排班记录
|
||||
|
||||
**禁止直接调用 `dws attendance schedule get`。必须先 `read_file` 读取 [attendance-schedule.md](./attendance-schedule.md) 后按其中的「排班查询导出工作流」执行。**
|
||||
|
||||
- 任何"查询排班"、"查看排班"、"XX考勤组的排班"、"X月份的排班"场景,**一律走 attendance-schedule.md 工作流**,由脚本 `attendance_schedule_export.py` 统一处理
|
||||
- 脚本自动处理:分批查询(超 20 人自动分批)、userId→姓名转换、classId→班次名称转换、排班表格式 Excel 输出
|
||||
- 违反后果:人数多时接口超时/报错、输出裸 userId 和 classId 用户看不懂、无排班表格式
|
||||
- **此处不提供 `schedule get` 的 Usage/Flags,防止绕过工作流直接拼命令。完整参数由 attendance-schedule.md 工作流中的脚本内部使用。**
|
||||
|
||||
### 查询当前用户可管理的所有班次详情
|
||||
```
|
||||
Usage:
|
||||
dws attendance class search [flags]
|
||||
Example:
|
||||
dws attendance class search
|
||||
dws attendance class search --query "早班" --filter-type MINE_OWN
|
||||
dws attendance class search --page 1 --limit 50
|
||||
Flags:
|
||||
--filter-type string 班次类型: ALL 全部班次 / MINE_OWN 我负责的 (可选)
|
||||
--query string 班次名称关键字, 模糊搜索 (可选)
|
||||
--page int 页码, 从 1 开始 (可选, 默认 1)
|
||||
--limit int 每页条数, 最大 200 (可选, 默认 20)
|
||||
```
|
||||
|
||||
### 查询班次详情
|
||||
```
|
||||
Usage:
|
||||
dws attendance class get [flags]
|
||||
Example:
|
||||
dws attendance class get --class-id 1170996821
|
||||
Flags:
|
||||
--class-id int 班次 ID (必填)
|
||||
```
|
||||
|
||||
根据班次 ID 查询该班次的完整详细信息。班次 ID 可从 `class search` 返回结果中提取,也有可能来源于用户手动输入。
|
||||
|
||||
### 创建班次 (写场景接口,必须走二次确认流程)
|
||||
**强制执行流程**:此命令为写操作,Agent 调用时必须遵守以下流程:
|
||||
1. 先向用户展示待执行操作的完整参数摘要,包括班次名称、上下班时间、休息时段等
|
||||
2. 展示变更摘要并等待用户明确确认
|
||||
3. 用户确认后,再传全局 `--yes` 执行命令
|
||||
|
||||
**禁止未经用户确认直接执行或自动添加 `--yes`。**
|
||||
```
|
||||
Usage:
|
||||
dws attendance class create [flags]
|
||||
Example:
|
||||
dws attendance class create --name "早班" --class-vo '{"sections":[{"times":[{"checkType":"OnDuty","checkTime":"08:00","across":0},{"checkType":"OffDuty","checkTime":"17:00","across":0}]}]}' --timeout 10
|
||||
# 带休息时段(12:00-13:00 午休)
|
||||
dws attendance class create --name "测试CLI" --class-vo '{"sections":[{"times":[{"checkType":"OnDuty","checkTime":"09:00","across":0},{"checkType":"OffDuty","checkTime":"18:00","across":0}]}],"setting":{"topRestTimeList":[{"checkType":"OnDuty","checkTime":"12:00","across":0},{"checkType":"OffDuty","checkTime":"13:00","across":0}]}}' --timeout 10
|
||||
Flags:
|
||||
--name string 班次名称 (必填)
|
||||
--owner string 班次负责人 userId (可选)
|
||||
--class-vo string 完整 TopAtClassVO JSON 字符串, 包含 sections 等复杂子对象 (必填)
|
||||
```
|
||||
|
||||
创建一个新班次。`--name` 和 `--class-vo`(包含 `sections`)必填。`sections` 定义班次的上下班时间段,支持多段上下班,每段包含 `times` 数组(有且只能有两个对象:上班+下班)。由于保存班次耗时较久,建议加 `--timeout 10`。
|
||||
|
||||
`checkTime` 字段统一使用 "HH:mm" 格式(如 "09:00"、"17:30"),CLI 自动转换为服务端所需格式。
|
||||
|
||||
`--class-vo` 支持字段:
|
||||
- `name`(string, 必填) `owner`(string, 可选)
|
||||
- `sections`([]object, 必填): 每个对象含 `times`([]object),每个 time 含 `checkType`(OnDuty/OffDuty, 必填) `checkTime`("HH:mm", 必填) `across`(0/1, 必填) `freeCheck`(bool) `beginMin`(number, -1不限制) `endMin`(number, -1不限制)
|
||||
- `setting`(object, 可选): `seriousLateMinutes`(严重迟到分钟) `absenteeismLateMinutes`(旷工迟到分钟) `attendDays`(出勤天数) `topRestTimeList`([]object, 仅单段上下班时可用,最多3段: checkType/checkTime("HH:mm")/across)
|
||||
|
||||
### 更新班次 (写场景接口,必须走二次确认流程)
|
||||
**强制执行流程**:此命令为写操作,Agent 调用时必须遵守以下流程:
|
||||
1. 先向用户展示待执行操作的完整参数摘要,包括班次 ID、要修改的字段含义及新值
|
||||
2. 展示变更摘要并等待用户明确确认
|
||||
3. 用户确认后,再传全局 `--yes` 执行命令
|
||||
|
||||
**禁止未经用户确认直接执行或自动添加 `--yes`。**
|
||||
```
|
||||
Usage:
|
||||
dws attendance class update [flags]
|
||||
Example:
|
||||
dws attendance class update --class-id 1170996821 --name "新早班" --timeout 10
|
||||
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
|
||||
# 带休息时段(12:00-13:00 午休)
|
||||
dws attendance class update --class-id 1170996821 --class-vo '{"sections":[{"times":[{"checkType":"OnDuty","checkTime":"09:00","across":0},{"checkType":"OffDuty","checkTime":"18:00","across":0}]}],"setting":{"topRestTimeList":[{"checkType":"OnDuty","checkTime":"12:00","across":0},{"checkType":"OffDuty","checkTime":"13:00","across":0}]}}' --timeout 10
|
||||
Flags:
|
||||
--class-id int 班次 ID (必填)
|
||||
--name string 班次名称 (可选,不传则保持原值)
|
||||
--owner string 班次负责人 userId (可选,不传则保持原值)
|
||||
--class-vo string 完整 TopAtClassVO JSON 字符串,用于修改复杂子对象 (可选)
|
||||
```
|
||||
|
||||
更新班次配置。`--class-id` 必填,其余均可选,仅需对要修改的字段进行赋值,未传字段会自动从已有配置补充。小改用单字段 flag(如 `--name`);修改上下班时间、休息时段等复杂子对象时用 `--class-vo` 传入完整 JSON。`--class-vo` 与单字段 flag 同时传入时,单字段 flag 优先级更高。
|
||||
|
||||
`checkTime` 字段统一使用 "HH:mm" 格式(如 "09:00"、"17:30"),CLI 自动转换为服务端所需格式。
|
||||
|
||||
`--class-vo` 支持字段(均可选,只需包含要修改的字段):
|
||||
- `name`(string) `owner`(string)
|
||||
- `sections`([]object): 每个对象含 `times`([]object),每个 time 含 `checkType`(OnDuty/OffDuty) `checkTime`("HH:mm") `across`(0/1) `freeCheck`(bool) `beginMin`(number, -1不限制) `endMin`(number, -1不限制)
|
||||
- `setting`(object): `seriousLateMinutes` `absenteeismLateMinutes` `attendDays` `topRestTimeList`([]object: checkType/checkTime("HH:mm")/across)
|
||||
|
||||
由于保存班次耗时较久,建议加 `--timeout 10`。
|
||||
|
||||
### 分页查询补卡规则,支持按名称搜素
|
||||
```
|
||||
Usage:
|
||||
dws attendance adjustment search [flags]
|
||||
Example:
|
||||
dws attendance adjustment search --page 1 --limit 20
|
||||
dws attendance adjustment search --query "标准" --page 1 --limit 50
|
||||
Flags:
|
||||
--page int 页码, 从 1 开始 (必填, 默认 1)
|
||||
--query string 补卡规则名称关键字, 模糊搜索 (可选)
|
||||
--limit int 每页条数, 200 以内 (必填, 默认 20)
|
||||
```
|
||||
|
||||
### 查询补卡规则详情
|
||||
```
|
||||
Usage:
|
||||
dws attendance adjustment get [flags]
|
||||
Example:
|
||||
dws attendance adjustment get --adjustment-id 12345
|
||||
Flags:
|
||||
--adjustment-id int 补卡规则主键 ID (必填)
|
||||
```
|
||||
|
||||
根据补卡规则主键 ID 查询对应的补卡规则详情。主键 ID 可从 `adjustment search` 返回结果中提取,也有可能来源于用户手动输入。**注意:已被删除或被更新覆盖的补卡规则无法查询到。**
|
||||
|
||||
### 分页查询加班规则,支持按名称搜素
|
||||
```
|
||||
Usage:
|
||||
dws attendance overtime search [flags]
|
||||
Example:
|
||||
dws attendance overtime search --page 1 --limit 20
|
||||
dws attendance overtime search --query "节假日" --page 1 --limit 50
|
||||
Flags:
|
||||
--page int 页码, 从 1 开始 (必填, 默认 1)
|
||||
--query string 加班规则名称关键字, 模糊搜索 (可选)
|
||||
--limit int 每页条数, 200 以内 (必填, 默认 20)
|
||||
```
|
||||
|
||||
### 查询加班规则详情
|
||||
```
|
||||
Usage:
|
||||
dws attendance overtime get [flags]
|
||||
Example:
|
||||
dws attendance overtime get --overtime-id 12345
|
||||
Flags:
|
||||
--overtime-id int 加班规则主键 ID (必填)
|
||||
```
|
||||
|
||||
根据加班规则主键 ID 查询对应的加班规则详情。主键 ID 可从 `overtime search` 返回结果中提取,也有可能来源于用户手动输入。**已被删除或更新覆盖的加班规则也可以查到。**
|
||||
|
||||
### 查询考勤组列表
|
||||
```
|
||||
Usage:
|
||||
dws attendance group search [flags]
|
||||
Example:
|
||||
dws attendance group search --query "研发"
|
||||
dws attendance group search --type FIXED --limit 50
|
||||
dws attendance group search --page 1 --limit 20
|
||||
Flags:
|
||||
--query string 考勤组名称关键字, 模糊搜索 (可选)
|
||||
--page int 页码, 从 1 开始 (必填, 默认 1)
|
||||
--limit int 每页条数, 200 以内 (必填, 默认 20)
|
||||
--query-ble 是否查询蓝牙设备列表 (可选, 默认 false)
|
||||
--query-position 是否查询地理定位和 Wifi 名称 (可选, 默认 false)
|
||||
--type string 考勤组类型: FIXED 固定班制 / TURN 排班制 / NONE 自由工时 (可选)
|
||||
```
|
||||
|
||||
### 查询考勤组全量信息
|
||||
```
|
||||
Usage:
|
||||
dws attendance group get [flags]
|
||||
Example:
|
||||
dws attendance group get --group-id 123456
|
||||
Flags:
|
||||
--group-id int 考勤组 ID (必填)
|
||||
```
|
||||
|
||||
根据考勤组 ID 查询该考勤组的全量信息。考勤组 ID 可从 `group search` 返回结果中提取,也有可能来源于用户手动输入。如果只需查询成员、打卡地址、蓝牙、Wifi 子集,请使用 `group filtered-get` 以节省查询成本。
|
||||
返回结果中如含成员 userId 列表,必须调用 `dws contact user get --ids <userId1>,<userId2>,...`(支持逗号分隔传多个 ID),将 userId 转换为员工姓名后再输出;不得直接输出裸 userId
|
||||
|
||||
### 按需查询考勤组部分信息
|
||||
```
|
||||
Usage:
|
||||
dws attendance group filtered-get [flags]
|
||||
Example:
|
||||
dws attendance group filtered-get --group-id 123456 --member
|
||||
dws attendance group filtered-get --group-id 123456 --position --wifi
|
||||
Flags:
|
||||
--group-id int 考勤组 ID (必填)
|
||||
--member 是否查询考勤组成员信息 (可选, 默认 false)
|
||||
--position 是否查询打卡地址 (可选, 默认 false)
|
||||
--wifi 是否查询打卡 Wifi (可选, 默认 false)
|
||||
--bles 是否查询打卡蓝牙 (可选, 默认 false)
|
||||
```
|
||||
|
||||
强烈建议在仅需查询成员、打卡地址、蓝牙、Wifi 时调用该命令,避免全量查询带来的性能开销。考勤组 ID 可从 `group search` 返回结果中提取,也有可能来源于用户手动输入。
|
||||
返回结果中如含成员 userId 列表,必须调用 `dws contact user get --ids <userId1>,<userId2>,...`(支持逗号分隔传多个 ID),将 userId 转换为员工姓名后再输出;不得直接输出裸 userId
|
||||
|
||||
### 更新考勤组成员 (写场景接口,必须走二次确认流程)
|
||||
**强制执行流程**:此命令为写操作,Agent 调用时必须遵守以下流程:
|
||||
1. 先向用户展示待执行操作的完整参数摘要,包括考勤组 ID、要添加/移除的成员列表
|
||||
2. 展示变更摘要并等待用户明确确认
|
||||
3. 用户确认后,再传全局 `--yes` 执行命令
|
||||
|
||||
**禁止未经用户确认直接执行或自动添加 `--yes`。**
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws attendance group update-members [flags]
|
||||
Example:
|
||||
dws attendance group update-members --group-id 123456 --add-users userId1,userId2
|
||||
dws attendance group update-members --group-id 123456 --remove-users userId1
|
||||
dws attendance group update-members --group-id 123456 --add-depts deptId1 --remove-users userId2
|
||||
Flags:
|
||||
--group-id int 考勤组 ID (必填)
|
||||
--add-users string 添加考勤人员 userId 列表, 逗号分隔, 最多 20 个 (可选)
|
||||
--remove-users string 删除考勤人员 userId 列表, 逗号分隔, 最多 20 个 (可选)
|
||||
--add-extra-users string 添加无需考勤的人员 userId 列表, 逗号分隔, 最多 20 个 (可选)
|
||||
--remove-extra-users string 删除无需考勤的成员 userId 列表, 逗号分隔, 最多 20 个 (可选)
|
||||
--add-depts string 添加考勤部门 ID 列表, 逗号分隔, 最多 20 个 (可选),若要添加全公司,根部门id为-1
|
||||
--remove-depts string 删除考勤部门 ID 列表, 逗号分隔, 最多 20 个 (可选),全公司根部门id为-1
|
||||
```
|
||||
|
||||
对指定考勤组的成员进行增删操作。--group-id 必填,其余参数均为可选,但至少需要传入一个变更项,否则命令拒绝执行。每次调用各参数最多传 20 个 ID。"无需考勤"人员指考勤组内豁免打卡的成员(如高管)。
|
||||
|
||||
### 更新考勤组配置 (写场景接口,必须走二次确认流程)
|
||||
**强制执行流程**:此命令为写操作,Agent 调用时必须遵守以下流程:
|
||||
1. 先向用户展示待执行操作的完整参数摘要,包括考勤组 ID、要修改的字段含义及新值
|
||||
2. 展示变更摘要并等待用户明确确认
|
||||
3. 用户确认后,再传全局 `--yes` 执行命令
|
||||
|
||||
**禁止未经用户确认直接执行或自动添加 `--yes`。**
|
||||
```
|
||||
Usage:
|
||||
dws attendance group update [flags]
|
||||
Example:
|
||||
dws attendance group update --group-id 123456 --name "研发考勤组" --timeout 10
|
||||
dws attendance group update --group-id 123456 --owner userId1 --timeout 10
|
||||
dws attendance group update --group-id 123456 --classIds '[1374234767]' --timeout 10
|
||||
dws attendance group update --group-id 123456 --group-vo '{"positions":[{"title":"总部","address":"北京市...","latitude":39.9,"longitude":116.4,"offset":200}]}' --timeout 10
|
||||
Flags:
|
||||
--group-id int 考勤组 ID (必填)
|
||||
--name string 考勤组名称 (可选)
|
||||
--type string 考勤组类型:FIXED 固定班制 / TURN 排班制 / NONE 自由工时 (可选)
|
||||
--owner string 考勤组主负责人 userId (可选)
|
||||
--enable-outside-check 是否允许外勤打卡 true/false (可选)
|
||||
--classIds string 所选班次 id 列表, JSON 数组格式, 如 '[123,456]' (可选)
|
||||
--group-vo string 完整 groupVO JSON 字符串, 用于修改复杂子对象 (可选)
|
||||
```
|
||||
|
||||
更新考勤组配置。--group-id 必填,其余均可选,但至少需指定一个修改项。仅需对要修改的字段进行赋値,其余字段会自动从已有配置补充。小改用单字段 flag;修改打卡地址、wifi、蓝牙设备、循环排班等复杂子对象时用 `--group-vo` 传入完整 JSON。`--group-vo` 与单字段 flag 同时传入时,单字段 flag 优先级更高。
|
||||
|
||||
`--group-vo` 支持字段(均可选,只需包含要修改的字段):
|
||||
- 基础:`name`(名称) `type`(FIXED/TURN/NONE) `owner`(主负责人 userId) `managerList`([]string 子负责人) `skipHolidays`(bool,只在固定班制和自由工时生效) `defaultGroup`(bool) `classIds`([]number,所选班次 id,只有固定班制和排班制才有班次,自由工时没有)
|
||||
- 打卡范围:`trimDistance`(微调距离) `enablePositionOfGps/Wifi/Ble`(bool)
|
||||
- 打卡地址:`positions`([]对象: title/address/latitude/longitude/offset,其中 offset 为该地址允许的打卡范围米)
|
||||
- Wifi:`wifis`([]对象: ssid/macAddr/groupId)
|
||||
- 蓝牙:`bleDeviceVOList`([]对象: name/deviceUid/sn/productType/devServId)
|
||||
- 外勤:`enableOutsideCheck`(bool) `enableOutsideCameraCheck/Remark/Apply`(bool) `outsideCheckApproveMode`(NO_NEED_APPROVE/APPROVE_FIRST/CHECK_FIRST/APPROVE_EVERYTIME) `outSideCheckApplyType`(1全天/2上班/3下班) `forbidHideOutSideAddress`(bool) `enableOutSideUpdateNormalCheck`(下班时允许外勤卡更新内勤卡) `enableOnDutyNormalUpdateOutsideCheck`(上班时允许内勤卡更新外勤卡)
|
||||
- 打卡方式:`enableCameraCheck/openCameraCheck` `openFaceCheck` `enableFaceStrictMode` `enableFaceBeauty`(bool) `onlyMachineCheck`(bool) `permitMaxBeaconCount`(number) `disableCheckWhenRest`(bool,休息日打卡需审批,只在固定班制和排班制生效)
|
||||
- 固定班制设置(FIXED):`defaultClassId`(number) `workDayClassList`([]number,共7个值代表周日到周六每天的班次id,为0表示当天休息,如[0,1279240003,0,0,0,0,0]表示只有周一上班)
|
||||
- 排班制设置(TURN):`disableCheckWithoutSchedule`(bool,true=未排班时禁止打卡) `enableEmpSelectClass`(未排班时员工可选班次) `enableScheduleAutoMatch`(未排班时系统自动匹配)
|
||||
- 循环排班(非必填,不设置则由管理员手动排班):`cycleDays`(number) `startCycleDate`(时间戳,毫秒) `cycleScheduleList`([]对象: cycleName/groupId/isValid(Y/N)/itemList[{classId/className/isValid}])
|
||||
- 自由工时设置(NONE):`workDays`([1-7],1=周一7=周日) `freeCheckDayStartMinOffset`(number,距0点分钟数) `freeCheckCoreTime`(最短工作时长,分钟) `freeCheckDemandWorkMinutes`(要求打卡时长,分钟) `freeCheckSettingVO`(对象: freeCheckType(CYCLE上下班交替/MAX_TIME_UPDATE最大时间打卡)/freeWorkDayLackSwitch/freeOnDutyLackMinOffset/freeOffDutyLackMinOffset/delimitOffsetMinutesBetweenDays/freeCheckGapVO{onOffCheckGapMinutes/offOnCheckGapMinutes}) `freeGroupSpecialDayVO`(对象: specialOnDutyDays[]/specialOffDutyDays[])
|
||||
|
||||
### 创建考勤组 (写场景接口,必须走二次确认流程)
|
||||
**强制执行流程**:此命令为写操作,Agent 调用时必须遵守以下流程:
|
||||
1. 先向用户展示待执行操作的完整参数摘要,包括考勤组名称、类型、班次列表等
|
||||
2. 展示变更摘要并等待用户明确确认
|
||||
3. 用户确认后,再传全局 `--yes` 执行命令
|
||||
|
||||
**禁止未经用户确认直接执行或自动添加 `--yes`。**
|
||||
```
|
||||
Usage:
|
||||
dws attendance group create [flags]
|
||||
Example:
|
||||
dws attendance group create --name "研发考勤组" --type FIXED --group-vo '{"defaultClassId":1170996821,"workDayClassList":[0,1170996821,0,0,0,0,0]}' --timeout 10
|
||||
dws attendance group create --name "自由工时分组" --type NONE --timeout 10
|
||||
Flags:
|
||||
--name string 考勤组名称 (必填)
|
||||
--type string 考勤组类型:FIXED 固定班制 / TURN 排班制 / NONE 自由工时 (必填)
|
||||
--owner string 考勤组主负责人 userId (可选)
|
||||
--group-vo string 完整 groupVO JSON 字符串,用于传入复杂子对象 (可选)
|
||||
```
|
||||
|
||||
创建一个新的考勤组。`--name` 和 `--type` 必填,`--type` 必须为 FIXED/TURN/NONE 之一。
|
||||
|
||||
**条件必填(type=FIXED 固定班制时)**:`--group-vo` 必须包含 `workDayClassList`(工作日班次列表,不能为空,共 7 个值,代表周日到周六每天的班次 ID,为 0 表示当天休息)和 `defaultClassId`(默认班次 ID,不能为 null)。
|
||||
|
||||
`--group-vo` 可用字段说明(与 `group update` 的 `--group-vo` 一致,均可选,只需包含要设置的字段):
|
||||
|
||||
【基础信息】
|
||||
id number 考勤组 id(创建时无需传入,由服务端分配)
|
||||
name string 考勤组名称(必填)
|
||||
type string 考勤组类型:FIXED(固定班制)/ TURN(排班制)/ NONE(自由工时)(必填)
|
||||
owner string 考勤组主负责人 userId
|
||||
managerList []string 考勤组子负责人 userId 列表
|
||||
skipHolidays bool 节假日自动排休(只有固定班制和自由工时考勤组生效)
|
||||
defaultGroup bool 是否默认考勤组
|
||||
classIds []number 所选班次 id 列表(只有固定班制和排班制才有班次,自由工时没有)
|
||||
|
||||
【打卡范围与定位】
|
||||
trimDistance number 定位允许微调距离(米)
|
||||
enablePositionOfGps bool 打卡是否允许开启 GPS 定位
|
||||
enablePositionOfWifi bool 打卡是否允许开启 Wifi 定位
|
||||
enablePositionOfBle bool 打卡是否允许开启蓝牙定位
|
||||
enableMacCheck bool 开启 MAC 地址校验
|
||||
checkDistanceType string 打卡距离类型:NORMAL(正常) / OUTER_ADDRESS(仅允许在外勤地址打卡)
|
||||
wifiCompanyId number 允许打卡的 Wifi 公司 ID
|
||||
|
||||
【打卡地址】
|
||||
positions []object 打卡地址列表,每个对象字段:
|
||||
title string 地址名称
|
||||
address string 详细地址
|
||||
latitude number 纬度
|
||||
longitude number 经度
|
||||
offset number 该地址允许的打卡范围(米)
|
||||
|
||||
【打卡 Wifi】
|
||||
wifis []object 打卡 Wifi 列表,每个对象字段:
|
||||
ssid string Wifi 名称
|
||||
macAddr string MAC 地址
|
||||
groupId number 所属考勤组 ID
|
||||
|
||||
【蓝牙设备】
|
||||
bleDeviceVOList []object 蓝牙设备列表,每个对象字段:
|
||||
name string 设备名称
|
||||
deviceUid string 设备 ID
|
||||
sn string 序列号
|
||||
productType string 产品类型
|
||||
devServId number 设备服务 ID
|
||||
|
||||
【外勤打卡设置】
|
||||
enableOutsideCheck bool 是否允许外勤打卡
|
||||
openOutsideCameraCheck bool 外勤打卡是否开启拍照
|
||||
enableOutsideRemark bool 是否允许外勤备注
|
||||
enableOutsideApply bool 外勤打卡是否需审批
|
||||
forbidHideOutSideAddress bool 禁止隐藏外勤打卡地址
|
||||
enableOutSideUpdateNormalCheck bool 下班时允许外勤卡更新内勤卡
|
||||
enableOnDutyNormalUpdateOutsideCheck bool 上班时允许内勤卡更新外勤卡
|
||||
outsideCheckApproveMode string 外勤审批模式:NO_NEED_APPROVE / APPROVE_FIRST / CHECK_FIRST / APPROVE_EVERYTIME
|
||||
outSideCheckApplyType number 外勤打卡申请类型:1 全天 / 2 上班 / 3 下班
|
||||
|
||||
【打卡方式】
|
||||
openCameraCheck bool 是否开启拍照打卡
|
||||
enableFaceStrictMode bool 是否开启人脸严格模式
|
||||
enableFaceBeauty bool 是否开启人脸美颜
|
||||
onlyMachineCheck bool 是否仅允许考勤机打卡
|
||||
permitMaxBeaconCount number 允许最大蓝牙信标数量
|
||||
disableCheckWhenRest bool 休息日打卡需审批(只在固定班制和排班制生效)
|
||||
|
||||
【固定班制设置(FIXED)】
|
||||
defaultClassId number 默认班次 ID
|
||||
workDayClassList []number 工作日班次列表,共 7 个值代表周日到周六每天的班次 id,为 0 表示当天休息。
|
||||
例如 [0,1279240003,0,0,0,0,0] 表示只有周一上班
|
||||
|
||||
【排班制设置(TURN)】
|
||||
disableCheckWithoutSchedule bool 未排班时禁止打卡
|
||||
enableEmpSelectClass bool 未排班时员工可选班次
|
||||
enableScheduleAutoMatch bool 未排班时系统自动匹配
|
||||
cycleDays number 循环排班周期天数
|
||||
startCycleDate number 循环排班开始日期(时间戳,毫秒)
|
||||
cycleScheduleList []object 循环排班列表:
|
||||
cycleName string 循环排班名称
|
||||
groupId number 考勤组 ID
|
||||
isValid string 是否生效:Y/N
|
||||
itemList []object 循环排班明细:
|
||||
classId number 班次 ID
|
||||
className string 班次名称
|
||||
isValid string 是否生效:Y/N
|
||||
|
||||
【自由工时设置(NONE)】
|
||||
workDays []number 工作日,[1-7],1=周一,7=周日
|
||||
freeCheckDayStartMinOffset number 距 0 点分钟数
|
||||
freeCheckCoreTime number 最短工作时长(分钟)
|
||||
freeCheckDemandWorkMinutes number 要求打卡时长(分钟)
|
||||
freeCheckSettingVO object 自由打卡设置:
|
||||
freeCheckType string 打卡类型:CYCLE(上下班交替)/ MAX_TIME_UPDATE(最大时间打卡)
|
||||
freeWorkDayLackSwitch bool 工作日缺卡开关
|
||||
freeOnDutyLackMinOffset number 上班缺卡分钟数偏移
|
||||
freeOffDutyLackMinOffset number 下班缺卡分钟数偏移
|
||||
delimitOffsetMinutesBetweenDays number 跨天切割分钟数偏移
|
||||
freeCheckGapVO object 打卡间隔:
|
||||
onOffCheckGapMinutes number 上班到下班最小间隔(分钟)
|
||||
offOnCheckGapMinutes number 下班到上班最小间隔(分钟)
|
||||
freeGroupSpecialDayVO object 特殊日期设置:
|
||||
specialOnDutyDays []number 特殊上班日期
|
||||
specialOffDutyDays []number 特殊休息日期
|
||||
|
||||
当使用 `--group-vo` 传入完整 JSON 时,`--name`、`--type`、`--owner` 仍可覆写 JSON 中的同名字段。由于保存考勤组耗时较久,建议加 `--timeout 10`。
|
||||
|
||||
> **创建成功后的跳转链接**:`group create` 调用成功后,CLI 会在标准输出之后额外打印一条钉钉 PC 端跳转链接(仅在响应中同时包含 `corpId` 与 `groupId`/`id` 时输出),格式为 `dingtalk://dingtalkclient/page/link?url=https%3A%2F%2Fhrmregister.dingtalk.com%2Fsubapp%2Fattend%2Findex%3Fcode%3Dattend%26corpId%3D{corpId}%26ddtab%3Dtrue%26from%3Dattend%23%2FgroupModify%3Fid%3D{groupId}`,用于用户在钉钉 PC 客户端一键打开该考勤组详情页验证创建结果。Agent 遇到该跳转链接时应原样呈现给用户,不要对链接进行二次编码或裁剪。
|
||||
|
||||
> **新建考勤组并同时添加成员的工作流**:`group create` 不支持在创建时直接传入成员列表。若用户需要在新建考勤组后立即添加成员,必须先执行 `group create` 创建考勤组,从返回结果中提取 `groupId`,再执行 `group update-members --group-id <GROUP_ID> --add-users ...` 完成成员添加。
|
||||
|
||||
### 查询某个人的考勤统计摘要
|
||||
```
|
||||
Usage:
|
||||
dws attendance summary [flags]
|
||||
Example:
|
||||
dws attendance summary --user USER_ID --date 2026-03-12 --stats-type week
|
||||
Flags:
|
||||
--date string 查询日期,格式 YYYY-MM-DD 或 YYYY-MM-DD HH:mm:ss(必填)
|
||||
--stats-type string 统计类型:week(周统计)/ month(月统计)(必填)
|
||||
--user string 钉钉用户 ID(必填)
|
||||
```
|
||||
|
||||
### 查询考勤组与考勤规则
|
||||
```
|
||||
Usage:
|
||||
dws attendance rules [flags]
|
||||
Example:
|
||||
dws attendance rules --date 2026-03-14
|
||||
dws attendance rules --date "2026-03-14 09:00:00"
|
||||
Flags:
|
||||
--date string 考勤日期, 格式 YYYY-MM-DD 或 yyyy-MM-dd HH:mm:ss (必填)
|
||||
```
|
||||
|
||||
查询考勤组/考勤规则。例如:我属于哪个考勤组、打卡范围是什么、弹性工时怎么算。
|
||||
|
||||
### 查询个人规则设置
|
||||
```
|
||||
Usage:
|
||||
dws attendance selfsetting get [flags]
|
||||
Example:
|
||||
dws attendance selfsetting get --setting-scene checkRemind --user <USER_ID> --format json
|
||||
dws attendance selfsetting get --setting-scene fastCheck --user <USER_ID> --format json
|
||||
Flags:
|
||||
--setting-scene string 查询设置项: checkRemind/fastCheck/checkResultNotify/lackRemind/personalAttendStatNotify/bossAttendStatNotify (必填)
|
||||
--user string 查询用户 ID (必填)
|
||||
```
|
||||
|
||||
调用 MCP 工具 query_self_setting 查询个人规则设置,包括打卡提醒、极速打卡、打卡结果通知、缺卡提醒、个人考勤统计通知、团队考勤统计通知等设置项。MCP 入参 `userId` 必填;CLI 的 `--user` 也必填,必须显式传入目标用户 ID。认证信息 `corpId` 和 `opUserId` 由当前登录上下文自动注入,无需手动传入。
|
||||
|
||||
`--setting-scene` 枚举值:
|
||||
- `checkRemind`: 打卡提醒
|
||||
- `fastCheck`: 极速打卡
|
||||
- `checkResultNotify`: 打卡结果通知
|
||||
- `lackRemind`: 缺卡提醒
|
||||
- `personalAttendStatNotify`: 个人考勤统计通知
|
||||
- `bossAttendStatNotify`: 团队考勤统计通知
|
||||
|
||||
返回 `ServiceResult`,包含 `success`、`code`、`message`、`result`。`result` 可能根据 `--setting-scene` 仅返回对应设置项相关字段。常见字段包括:
|
||||
- `checkRemind`: `checkRemindSetting`、`checkRemindUserOnDuty`、`checkRemindUserOffDuty`、`enableOndutyCheckRemindOfPc`、`enableOffdutyCheckRemindOfPc`
|
||||
- `fastCheck`: `ondutyCheckType`、`offdutyCheckType`、`ondutyRemindStartMin`、`ondutyRemindEndMin`、`offdutyRemindStartMin`、`offdutyRemindEndMin`、`fastCheckLateNeedConfirm`、`canUpdateOffDuty`、`voiceRemindSwitch`、`vibrationRemindSwitch`
|
||||
- `checkResultNotify`: `checkResultMsg`, 取值 0 表示关闭, 1 表示开启
|
||||
- `lackRemind`: `lackSendTodoMsg`、`lackRemindUser`, 取值 0 表示关闭, `null` 或 1 表示开启
|
||||
- `personalAttendStatNotify`: `personDailyReportSwitch`、`personWeekReportType`、`personMonthReportType`
|
||||
- `bossAttendStatNotify`: `bossPushStartMin`、`bossWeekReportType`、`bossMonthReportType`
|
||||
|
||||
其中周报/月报通知渠道枚举值:0 表示全关闭,1 表示工作通知,2 表示钉邮,3 表示工作通知和钉邮。
|
||||
|
||||
### 更新保存个人规则设置 (写场景接口,必须走二次确认流程)
|
||||
**强制执行流程**:此命令为写操作,Agent 调用时必须遵守以下流程:
|
||||
1. 先向用户展示待执行操作的完整参数摘要,包括目标用户、设置场景、当前值、新值和最终命令参数
|
||||
2. 展示变更摘要并等待用户明确确认
|
||||
3. 用户确认后,再传全局 `--yes` 执行命令
|
||||
|
||||
**禁止未经用户确认直接执行或自动添加 `--yes`。**
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws attendance selfsetting save [flags]
|
||||
Example:
|
||||
# 开启打卡结果通知(执行前必须展示变更摘要并获得用户明确确认,确认后再追加 --yes)
|
||||
dws attendance selfsetting save --setting-scene checkResultNotify --user <USER_ID> --check-result-msg 1 --yes --format json
|
||||
# 更新极速打卡设置(执行前必须展示变更摘要并获得用户明确确认,确认后再追加 --yes)
|
||||
dws attendance selfsetting save --setting-scene fastCheck --user <USER_ID> --onduty-check-type 3 --voice-remind-switch=true --yes --format json
|
||||
# 更新打卡提醒设置(执行前必须展示变更摘要并获得用户明确确认,确认后再追加 --yes)
|
||||
dws attendance selfsetting save --setting-scene checkRemind --user <USER_ID> --check-remind-user-on-duty=false \
|
||||
--check-remind-setting '{"onDutyRemind":{"openRemind":true,"remindMinutes":10}}' --yes --format json
|
||||
Flags:
|
||||
--setting-scene string 更新设置项: checkRemind/fastCheck/checkResultNotify/lackRemind/personalAttendStatNotify/bossAttendStatNotify (必填)
|
||||
--user string 更新用户 ID (必填)
|
||||
--check-remind-setting string 打卡提醒 DING 渠道设置 JSON
|
||||
--check-remind-user-on-duty 打卡提醒工作通知渠道:用户个人上班打卡提醒开关
|
||||
--check-remind-user-off-duty 打卡提醒工作通知渠道:用户个人下班打卡提醒开关
|
||||
--enable-onduty-check-remind-of-pc PC 端弹窗渠道:上班打卡提醒开关
|
||||
--enable-offduty-check-remind-of-pc PC 端弹窗渠道:下班打卡提醒开关
|
||||
--onduty-check-type int 上班极速打卡方式:1 提醒打卡,2 不提醒且不自动打卡,3 自动打卡
|
||||
--offduty-check-type int 下班极速打卡方式:1 提醒打卡,2 不提醒且不自动打卡,3 自动打卡
|
||||
--onduty-remind-start-min int 上班打卡提醒开始时间,单位:分钟
|
||||
--onduty-remind-end-min int 上班打卡提醒结束时间,单位:分钟
|
||||
--offduty-remind-start-min int 下班打卡提醒开始时间,单位:分钟
|
||||
--offduty-remind-end-min int 下班打卡提醒结束时间,单位:分钟
|
||||
--fast-check-late-need-confirm 迟到时是否需要二次确认
|
||||
--can-update-off-duty 是否允许用户更新下班打卡设置
|
||||
--voice-remind-switch 极速打卡提示音开关
|
||||
--vibration-remind-switch 极速打卡震动提醒开关
|
||||
--check-result-msg int 打卡结果通知开关:0 关闭,1 开启
|
||||
--lack-send-todo-msg int 缺卡提醒待办渠道:0 关闭,null 或 1 开启
|
||||
--lack-remind-user int 缺卡提醒工作通知渠道:0 关闭,null 或 1 开启
|
||||
--person-daily-report-switch int 个人考勤统计日报推送开关:0 关闭,1 开启
|
||||
--person-week-report-type int 个人考勤统计周报通知渠道:0 全关闭,1 工作通知,2 钉邮,3 工作通知和钉邮
|
||||
--person-month-report-type int 个人考勤统计月报通知渠道:0 全关闭,1 工作通知,2 钉邮,3 工作通知和钉邮
|
||||
--boss-push-start-min int 团队考勤统计日报推送开始时间,单位:分钟;-1 表示关闭日报推送
|
||||
--boss-week-report-type int 团队考勤统计周报通知渠道:0 全关闭,1 工作通知,2 钉邮,3 工作通知和钉邮
|
||||
--boss-month-report-type int 团队考勤统计月报通知渠道:0 全关闭,1 工作通知,2 钉邮,3 工作通知和钉邮
|
||||
--yes 用户已确认,跳过交互式确认提示
|
||||
传入前必须已获得用户明确确认
|
||||
```
|
||||
|
||||
调用 MCP 工具 save_self_setting 更新保存个人规则设置,请求体封装在 `RuleMcpSaveSelfSettingRequest` 中。`settingScene` 必填;MCP 入参 `userId` 必填,CLI 的 `--user` 也必填,必须显式传入目标用户 ID。认证信息 `corpId` 和 `opUserId` 由当前登录上下文自动注入,无需手动传入。
|
||||
|
||||
`selfsetting save` 必须按 `--setting-scene` 传入对应场景的字段,且至少一个字段有值:
|
||||
- `checkRemind`: `checkRemindSetting`、`checkRemindUserOnDuty`、`checkRemindUserOffDuty`、`enableOndutyCheckRemindOfPc`、`enableOffdutyCheckRemindOfPc`
|
||||
- `fastCheck`: `ondutyCheckType`、`offdutyCheckType`、`ondutyRemindStartMin`、`ondutyRemindEndMin`、`offdutyRemindStartMin`、`offdutyRemindEndMin`、`fastCheckLateNeedConfirm`、`canUpdateOffDuty`、`voiceRemindSwitch`、`vibrationRemindSwitch`
|
||||
- `checkResultNotify`: `checkResultMsg`
|
||||
- `lackRemind`: `lackSendTodoMsg`、`lackRemindUser`
|
||||
- `personalAttendStatNotify`: `personDailyReportSwitch`、`personWeekReportType`、`personMonthReportType`
|
||||
- `bossAttendStatNotify`: `bossPushStartMin`、`bossWeekReportType`、`bossMonthReportType`
|
||||
|
||||
返回 `ServiceResult`,包含 `success`、`code`、`message`、`result`。其中 `result` 为 boolean,表示保存是否成功。
|
||||
|
||||
#### 强制执行流程:Agent 调用 `selfsetting save`
|
||||
|
||||
`selfsetting save` 是写操作,会修改用户个人规则设置。Agent 调用时 **必须按以下流程执行**,**禁止**在未确认的情况下直接提交:
|
||||
|
||||
1. **识别写操作**:用户表达“更新个人规则设置 / 保存打卡提醒 / 修改极速打卡 / 关闭缺卡提醒 / 开启打卡结果通知 / 设置个人考勤统计通知 / 设置团队考勤统计通知”等意图时,命中 `selfsetting save`。
|
||||
2. **收集必要参数**:必须明确 `--user`、`--setting-scene`,以及对应场景下将要修改的字段和值。
|
||||
3. **前置查询当前设置**:执行 `dws attendance selfsetting get --setting-scene <SCENE> --user <USER_ID> --format json`,获取当前配置,用于确认目标用户和当前值。
|
||||
4. **展示待写入数据并等待确认**:向用户展示目标用户、设置场景、要更新的字段、当前值、新值和最终命令参数摘要,并等待用户明确确认。
|
||||
5. **用户确认后再执行保存**:**只有用户明确确认后**,才可以追加全局 `--yes` 执行 `dws attendance selfsetting save ... --yes --format json`。
|
||||
|
||||
确认话术示例:
|
||||
|
||||
```text
|
||||
即将更新个人考勤规则设置,请确认:
|
||||
- 用户 ID:<USER_ID>
|
||||
- 设置场景:checkResultNotify
|
||||
- 修改内容:
|
||||
- 打卡结果通知(checkResultMsg):关闭 → 开启
|
||||
|
||||
是否确认执行更新?
|
||||
```
|
||||
|
||||
禁止在未获得用户明确确认前执行保存;禁止为了推进流程自动添加全局 `--yes`。即使用户在最初需求中表达“直接改/不用问”,也必须先展示完整参数摘要并获得明确确认,才允许追加 `--yes` 执行。
|
||||
|
||||
### 查询全局规则设置(仅管理员)
|
||||
```
|
||||
Usage:
|
||||
dws attendance globalsetting get [flags]
|
||||
Example:
|
||||
dws attendance globalsetting get --scope 企业 --setting-scene checkRemind --format json
|
||||
dws attendance globalsetting get --scope 全公司 --setting-scene bossAttendStatNotify --format json
|
||||
Flags:
|
||||
--setting-scene string 查询设置项: checkRemind/fastCheck/checkResultNotify/lackRemind/personalAttendStatNotify/bossAttendStatNotify (必填)
|
||||
--scope string 全局范围确认,必须明确输入:企业/全公司/所有人(必填)
|
||||
```
|
||||
|
||||
调用 MCP 工具 `query_global_setting` 查询全局规则设置,请求体封装在 `RuleMcpQueryGlobalSettingRequest` 中。`settingScene` 必填;CLI 必须通过 `--scope` 明确输入 `企业`、`全公司` 或 `所有人`,用于确认查询的是全局范围。认证信息 `corpId` 和 `opUserId` 由当前登录上下文自动注入,无需手动传入。该接口仅管理员可以调用。
|
||||
|
||||
返回 `ServiceResult`,包含 `success`、`code`、`message`、`result`。`result` 常见字段包括:
|
||||
- `checkRemindCorp`: 打卡提醒企业总开关
|
||||
- `checkRemindPcCorp`: 打卡提醒 PC 端企业总开关
|
||||
- `fastCheckCorp`: 极速打卡企业总开关
|
||||
- `enableCheckCertPush`: 打卡结果通知企业总开关
|
||||
- `lackRemindCorp`: 缺卡提醒企业总开关
|
||||
- `enablePersonalDailyReport`: 个人考勤统计通知日报企业总开关
|
||||
- `enablePersonalWeeklyReport`: 个人考勤统计通知周报企业开关,钉邮渠道
|
||||
- `enablePersonalWeeklyReportCard`: 个人考勤统计通知周报企业开关,工作通知渠道
|
||||
- `enablePersonalMonthlyReport`: 个人考勤统计通知月报企业总开关
|
||||
- `bossDailyReportType`: 团队考勤统计通知日报发送渠道类型,0 全关闭,1 开启
|
||||
- `bossWeeklyReportType`: 团队考勤统计通知周报发送渠道类型,0 全关闭,1 工作通知,2 钉邮,3 工作通知和钉邮
|
||||
- `bossMonthlyReportType`: 团队考勤统计通知月报发送渠道类型,0 全关闭,1 工作通知,2 钉邮,3 工作通知和钉邮
|
||||
|
||||
### 更新保存全局规则设置(写场景接口,仅管理员,必须走二次确认流程)
|
||||
**强制执行流程**:此命令为写操作,Agent 调用时必须先向用户展示待执行操作的完整参数摘要,等待用户明确确认后,才能追加 `--yes` 执行。
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws attendance globalsetting save [flags]
|
||||
Example:
|
||||
dws attendance globalsetting save --scope 企业 --setting-scene checkRemind --check-remind-corp=true --yes --format json
|
||||
dws attendance globalsetting save --scope 全公司 --setting-scene fastCheck --fast-check-corp=false --yes --format json
|
||||
dws attendance globalsetting save --scope 所有人 --setting-scene bossAttendStatNotify --boss-daily-report-type 1 --boss-weekly-report-type 3 --yes --format json
|
||||
Flags:
|
||||
--setting-scene string 更新设置项: checkRemind/fastCheck/checkResultNotify/lackRemind/personalAttendStatNotify/bossAttendStatNotify (必填)
|
||||
--scope string 全局范围确认,必须明确输入:企业/全公司/所有人(必填)
|
||||
--check-remind-corp 打卡提醒企业总开关
|
||||
--check-remind-pc-corp 打卡提醒 PC 端弹窗企业总开关
|
||||
--fast-check-corp 极速打卡企业总开关
|
||||
--enable-check-cert-push 打卡结果通知企业总开关
|
||||
--lack-remind-corp 缺卡提醒企业总开关
|
||||
--enable-personal-daily-report 个人考勤统计通知日报企业总开关
|
||||
--enable-personal-weekly-report 个人考勤统计通知周报企业开关,钉邮渠道
|
||||
--enable-personal-weekly-report-card 个人考勤统计通知周报企业开关,工作通知渠道
|
||||
--enable-personal-monthly-report 个人考勤统计通知月报企业总开关
|
||||
--boss-daily-report-type int 团队考勤统计通知日报发送渠道类型:0 全关闭,1 开启
|
||||
--boss-weekly-report-type int 团队考勤统计通知周报发送渠道类型:0 全关闭,1 工作通知,2 钉邮,3 工作通知和钉邮
|
||||
--boss-monthly-report-type int 团队考勤统计通知月报发送渠道类型:0 全关闭,1 工作通知,2 钉邮,3 工作通知和钉邮
|
||||
--yes 用户已确认,跳过交互式确认提示
|
||||
```
|
||||
|
||||
调用 MCP 工具 `save_global_setting` 更新保存全局规则设置,请求体封装在 `RuleMcpSaveGlobalSettingRequest` 中。`settingScene` 必填;CLI 必须通过 `--scope` 明确输入 `企业`、`全公司` 或 `所有人`,用于确认更新的是全局范围。认证信息 `corpId` 和 `opUserId` 由当前登录上下文自动注入,无需手动传入。该接口仅管理员可以调用。
|
||||
|
||||
`globalsetting save` 必须按 `--setting-scene` 传入对应场景的字段,且至少一个字段有值:
|
||||
- `checkRemind`: `checkRemindCorp`、`checkRemindPcCorp`
|
||||
- `fastCheck`: `fastCheckCorp`
|
||||
- `checkResultNotify`: `enableCheckCertPush`
|
||||
- `lackRemind`: `lackRemindCorp`
|
||||
- `personalAttendStatNotify`: `enablePersonalDailyReport`、`enablePersonalWeeklyReport`、`enablePersonalWeeklyReportCard`、`enablePersonalMonthlyReport`
|
||||
- `bossAttendStatNotify`: `bossDailyReportType`、`bossWeeklyReportType`、`bossMonthlyReportType`
|
||||
|
||||
返回 `ServiceResult`,其中 `result` 为 boolean,表示保存是否成功。
|
||||
|
||||
### 获取企业考勤字段列表(仅管理员)
|
||||
```
|
||||
Usage:
|
||||
dws attendance report columns
|
||||
Example:
|
||||
dws attendance report columns
|
||||
```
|
||||
|
||||
根据操作者的列权限,过滤并返回其有权查看的考勤字段列表。操作者必须是管理员,否则返回权限错误。
|
||||
|
||||
### 根据字段查询考勤数据(仅管理员)
|
||||
```
|
||||
Usage:
|
||||
dws attendance report query-data [flags]
|
||||
Example:
|
||||
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"
|
||||
Flags:
|
||||
--columns string 字段 ID 列表, 逗号分隔, 可通过 report columns 获取(必填)
|
||||
--end string 结束日期, 格式 yyyy-MM-dd HH:mm:ss(必填)
|
||||
--start string 开始日期, 格式 yyyy-MM-dd HH:mm:ss(必填)
|
||||
--users string 目标用户 ID 列表, 逗号分隔, 最多 20 人(必填)
|
||||
```
|
||||
|
||||
根据字段查询考勤数据,含列权限过滤和用户查看权限校验。--users 最多 20 人,--start 到 --end 不超过 32 天。
|
||||
|
||||
### 查询用户假期数据(仅管理员)
|
||||
```
|
||||
Usage:
|
||||
dws attendance report query-leave [flags]
|
||||
Example:
|
||||
dws attendance report query-leave \
|
||||
--users userId1,userId2 --leave-names 年假,病假 --start "2026-03-01 00:00:00" --end "2026-03-31 23:59:59"
|
||||
Flags:
|
||||
--end string 结束日期, 格式 yyyy-MM-dd HH:mm:ss(必填)
|
||||
--leave-names string 假期类型名称列表, 逗号分隔, 不填则查询所有假期类型(选填)
|
||||
--start string 开始日期, 格式 yyyy-MM-dd HH:mm:ss(必填)
|
||||
--users string 目标用户 ID 列表, 逗号分隔, 最多 20 人(必填)
|
||||
```
|
||||
|
||||
查询用户假期数据,含用户查看权限校验。--users 最多 20 人,--start 到 --end 不超过 32 天。
|
||||
|
||||
### 查询当前用户假期规则列表
|
||||
```
|
||||
Usage:
|
||||
dws attendance vacation types
|
||||
Example:
|
||||
dws attendance vacation types
|
||||
Flags:
|
||||
无
|
||||
```
|
||||
|
||||
调用 MCP 工具 get_leave_types 查询当前用户可用的假期规则列表。例如:年假、事假、病假等假期类型及对应规则。请求体封装在 McpLeaveTypeRequest 中,认证信息(corpId、opUserId)由系统自动注入,无需手动传入。
|
||||
|
||||
### 查询指定员工假期余额
|
||||
```
|
||||
Usage:
|
||||
dws attendance vacation balance [flags]
|
||||
Example:
|
||||
dws attendance vacation balance --users userId1,userId2 --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
||||
Flags:
|
||||
--users string 目标员工 ID 列表, 逗号分隔 (必填)
|
||||
--leave-code string 假期规则 code (选填,不传则查询所有假期规则余额)
|
||||
```
|
||||
|
||||
调用 MCP 工具 get_leave_balance_quota 查询指定员工的假期余额。例如:查询某员工年假还剩多少、病假额度等。`--leave-code` 可通过 `vacation types` 获取;不传 `--leave-code` 时查询所有假期规则余额。认证信息(corpId、opUserId)由系统自动注入。
|
||||
|
||||
如用户需要“所有假期规则余额 / 导出假期余额列表 / 所有假期规则余额 Excel / 按截图样式导出假期余额”,必须先读取 [attendance-vacation.md](./attendance-vacation.md),再按其中工作流调用脚本生成 Excel。
|
||||
|
||||
### 查询指定员工假期余额变更记录
|
||||
```
|
||||
Usage:
|
||||
dws attendance vacation records [flags]
|
||||
Example:
|
||||
dws attendance vacation records --user USER_ID --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 --start 2026-04-01 --end 2026-04-22
|
||||
Flags:
|
||||
--user string 指定查询员工 ID (必填)
|
||||
--leave-code string 假期规则 code (必填, 不传则无法查询)
|
||||
--start string 查询开始日期, 格式 YYYY-MM-DD (必填)
|
||||
--end string 查询结束日期, 格式 YYYY-MM-DD (必填)
|
||||
```
|
||||
|
||||
调用 MCP 工具 get_leave_balance_records 查询指定员工的假期余额变更记录。例如:查询某员工年假变更历史、请假扣减记录等。`--leave-code` 可通过 `vacation types` 获取。认证信息(corpId、opUserId)由系统自动注入。
|
||||
|
||||
### 更新假期规则(写场景接口,必须走二次确认流程)
|
||||
|
||||
**强制执行流程**:此命令为写操作,Agent 调用时必须遵守以下流程:
|
||||
1. 先向用户展示待执行操作的完整参数摘要
|
||||
2. 展示变更摘要并等待用户明确确认
|
||||
3. 用户确认后,再传 `--user-say-yes=true` 执行命令
|
||||
|
||||
**禁止未经用户确认直接执行或自动添加 `--user-say-yes=true`。**
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws attendance vacation update-type [flags]
|
||||
Example:
|
||||
# 更新假期规则名称
|
||||
dws attendance vacation update-type --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 --name "事假(修改版)"
|
||||
|
||||
# 更新假期单位
|
||||
dws attendance vacation update-type --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 --unit hour --per-hours 8
|
||||
|
||||
# 改为指定部门可见
|
||||
dws attendance vacation update-type --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 --visibility-rules '[{"type":"dept","visible":["1","2","3"]}]'
|
||||
|
||||
# 改为全公司可见(哨兵约定:必须显式传 "-1",空数组 [] 不生效)
|
||||
dws attendance vacation update-type --leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 --visibility-rules '[{"type":"dept","visible":["-1"]}]'
|
||||
Flags:
|
||||
--leave-code string 假期编码(必填)
|
||||
--name string 假期名称(可选)
|
||||
--unit string 假期单位:day/halfDay/hour(可选)
|
||||
--paid bool 是否带薪假期(可选,默认 false)
|
||||
--per-hours int 一天折算小时数(可选)
|
||||
--when-can-leave string 新员工请假规则:entry/formal(可选)
|
||||
--visibility-rules string 适用范围规则 JSON 数组(可选)
|
||||
- 不传:不修改原有可见范围
|
||||
- 改为指定范围:[{"type":"staff|dept|label","visible":["id1",...]}, ...]
|
||||
- 改为全公司可见(哨兵):必须显式传 [{"type":"dept","visible":["-1"]}]
|
||||
- 空数组 []、[{}]、visible 为空等 → CLI 报错(HSF 端会静默忽略)
|
||||
--user-say-yes 用户已确认,跳过交互式确认提示
|
||||
Agent 调用时传 true 前必须完成用户二次确认
|
||||
```
|
||||
|
||||
调用 MCP 工具 save_leave_type 更新已有假期规则。`--leave-code` 必填,指定要更新的假期规则编码。其他字段均为可选,仅需传入要修改的字段。除 `--leave-code` 外,必须至少传入一个更新字段。
|
||||
|
||||
**`--visibility-rules` HSF 反序列化约定(必读)**:
|
||||
|
||||
| 入参形态 | 业务语义 | CLI / 服务端处理 |
|
||||
|---|---|---|
|
||||
| 不传 | 不修改可见范围 | 服务端保留原有 `visibilityRules` |
|
||||
| `[{"type":"dept","visible":["-1"]}]`(哨兵) | 改为全公司可见 | 服务端落库为空数组(全公司语义) |
|
||||
| `[{"type":"staff","visible":["uid1"]}, ...]` 等有效规则 | 改为指定可见范围 | 覆盖原有 `visibilityRules` |
|
||||
| 空数组 `[]` / `[{}]` / `visible` 为空 | — (反例) | **CLI 直接报错**,避免 HSF 端被静默忽略 |
|
||||
|
||||
- `type` 可取 `dept`(部门 ID,`-1` 是根部门 = 全公司哨兵)、`staff`(userId)、`label`(角色 ID)。
|
||||
- 哨兵识别采用宽松匹配:传入列表中任意一条规则满足 `type=dept` 且 `visible` 包含 `"-1"`,即视为全公司可见,其它规则被忽略。
|
||||
- 若意图是“改为全公司可见”,**必须**显式传哨兵值 `["-1"]`,**不能**传空数组 `[]`。
|
||||
|
||||
#### 强制执行流程:Agent 调用 `vacation update-type`
|
||||
|
||||
`vacation update-type` 是写操作,会修改假期规则配置。Agent 调用时 **必须按以下流程执行**,**禁止**在未确认的情况下直接提交:
|
||||
|
||||
1. **识别写操作**:用户表达"更新假期规则 / 修改假期类型 / 编辑假期规则"等意图时,命中 `vacation update-type`。
|
||||
2. **收集必要参数**:必须明确 `--leave-code`,以及至少一个更新字段(`--name`、`--unit`、`--paid`、`--per-hours`、`--when-can-leave`、`--visibility-rules`)。
|
||||
3. **前置查询当前规则**:需先调用 `vacation types` 确认该规则是否存在及当前配置。
|
||||
4. **展示待写入数据并等待确认**:向用户展示假期编码、要更新的字段及新值,并询问是否确认执行。**必须等待用户明确确认**。
|
||||
5. **用户确认后再执行保存**:**只有用户明确确认后**,才可以传 `--user-say-yes=true` 执行 `dws attendance vacation update-type ... --format json`。
|
||||
|
||||
确认话术示例:
|
||||
|
||||
```text
|
||||
即将更新假期规则,请确认:
|
||||
- 假期编码:a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
||||
- 更新内容:
|
||||
- 名称:事假 → 事假(修改版)
|
||||
|
||||
是否确认执行更新?
|
||||
```
|
||||
|
||||
如用户明确要求跳过确认,可传 `--user-say-yes=true`;否则默认必须等待确认。
|
||||
|
||||
#### 强制执行流程:Agent 调用 `vacation save-balance`
|
||||
|
||||
`vacation save-balance` 是写操作,会直接替换员工的假期余额(SET 接口,而非 ADD)。Agent 调用时 **必须按以下流程执行**,**禁止**在未确认的情况下直接提交:
|
||||
|
||||
1. **识别写操作**:用户表达"设置假期余额 / 调整假期额度 / 更新假期余额 / 增加假期余额 / 发放年假 / 给员工加年假"等意图时,命中 `vacation save-balance`。
|
||||
2. **前置查询当前余额**:必须先调用 `vacation balance --users <target> --leave-code <code>` 获取当前余额,因为这是 SET 接口,传入值会直接替换而非累加。
|
||||
3. **收集必要参数**:必须明确 `--target`(目标员工)、`--leave-code`(假期编码)、`--num`(新余额数量)、`--reason`(变更原因),以及可选参数 `--start/--end`(有效期)。
|
||||
4. **计算变更并展示确认**:向用户展示目标员工、假期类型、当前余额、新余额、差额(增加或减少)、变更原因、有效期等,并询问是否确认执行。**必须等待用户明确确认**。
|
||||
5. **用户确认后再执行保存**:**只有用户明确确认后**,才可以传 `--user-say-yes=true` 执行 `dws attendance vacation save-balance ... --format json`。
|
||||
|
||||
确认话术示例:
|
||||
|
||||
**设置余额场景**:
|
||||
```text
|
||||
即将设置员工假期余额,请确认:
|
||||
- 目标员工:张三(user001)
|
||||
- 假期类型:年假(leaveCode: a1b2c3d4-e5f6-7890-abcd-ef1234567890)
|
||||
- 当前余额:5 天
|
||||
- 新余额:8 天
|
||||
- 变更差额:+3 天(增加)
|
||||
- 变更原因:年度发放
|
||||
- 有效期:2024-01-01 至 2024-12-31
|
||||
|
||||
是否确认执行设置?
|
||||
```
|
||||
|
||||
**减少余额场景**:
|
||||
```text
|
||||
即将设置员工假期余额,请确认:
|
||||
- 目标员工:李四(user002)
|
||||
- 假期类型:年假(leaveCode: a1b2c3d4-e5f6-7890-abcd-ef1234567890)
|
||||
- 当前余额:10 天
|
||||
- 新余额:2 天
|
||||
- 变更差额:-8 天(减少)
|
||||
- 变更原因:请假扣减
|
||||
|
||||
注意:此操作将大幅减少余额,请确认是否继续?
|
||||
|
||||
是否确认执行设置?
|
||||
```
|
||||
|
||||
如用户明确要求跳过确认,可传 `--user-say-yes=true`;否则默认必须等待确认。
|
||||
|
||||
### 设置员工假期余额
|
||||
```
|
||||
Usage:
|
||||
dws attendance vacation save-balance [flags]
|
||||
Example:
|
||||
# 设置员工年假余额为8天
|
||||
dws attendance vacation save-balance --target user001 \
|
||||
--leave-code a1b2c3d4-e5f6-7890-abcd-ef1234567890 --num 8 --reason "年度发放"
|
||||
|
||||
# 设置带有效期的假期余额
|
||||
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
|
||||
Flags:
|
||||
--target string 目标员工工号(必填)
|
||||
--leave-code string 假期编码(必填)
|
||||
--num string 余额数量,如8天传8,7.5天传7.5(必填)
|
||||
--reason string 变更原因,最长100字符(必填)
|
||||
--start string 有效期开始日期 YYYY-MM-DD(可选)
|
||||
--end string 有效期结束日期 YYYY-MM-DD(可选)
|
||||
--user-say-yes 用户已确认,跳过交互式确认提示
|
||||
Agent 调用时传 true 前必须完成用户二次确认
|
||||
```
|
||||
|
||||
**重要:这是设置(SET)接口,传入的值会替换当前余额,而非增加(ADD)。**余额数量在传递给 MCP 时会自动乘以 100(如 8 天传 800)。执行前会展示待写入数据,需用户确认后提交。
|
||||
|
||||
### 查询指定员工的签到记录
|
||||
```
|
||||
Usage:
|
||||
dws attendance checkin records [flags]
|
||||
Example:
|
||||
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"
|
||||
Flags:
|
||||
--end string 结束时间, 格式 yyyy-MM-dd HH:mm:ss(必填)
|
||||
--operator-corp-id string 操作者企业 ID(必填)
|
||||
--operator-staff-id string 操作者员userID(必填)
|
||||
--staff-ids string 目标员工userID 列表, 逗号分隔(必填),员工数最多100个人
|
||||
--start string 开始时间, 格式 yyyy-MM-dd HH:mm:ss(必填),开始到结束时间限制在7天
|
||||
```
|
||||
|
||||
调用 MCP 工具 get_checkin_record 查询指定员工在一段时间内的签到记录。权限说明:Boss/超级管理员可查看全公司员工,子管理员可查看管理范围内员工,部门主管可查看所管理部门员工,普通员工只能查询自己。接口单次最多返回100条签到记录。
|
||||
|
||||
返回结构:`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
|
||||
|
||||
顶层还包含 `success`(boolean)和 `arguments`(object[])字段。
|
||||
@@ -0,0 +1,10 @@
|
||||
# 严格约束
|
||||
|
||||
## 严格约束
|
||||
- 不要凭历史记忆复用 userId / classId / leaveCode / groupId / instanceId 等任何 ID,每次必须从当次命令返回值中提取
|
||||
- 不要猜测命令,先查询明确命令,不要使用记忆中未经证实(即不存在于本.md文件中的指令)或执行失败(指令传参有误或flag不正确)的的命令
|
||||
- 制定 plan 并自我审查,严格按 plan 执行
|
||||
- 涉及超过 3 条记录的聚合(求和、分组、计数、排序、跨字段计算)时必须落 Python 脚本处理,禁止用大模型口算或目测。脚本里如果用到 mcp,先提前看下 mcp 返回的结构,避免执行异常
|
||||
- 遇到时长字段时,注意区分单位是秒、分钟还是小时
|
||||
- 遇到意图不清晰的场景不要猜测,主动询问用户明确意图
|
||||
- 如果查询结果很多时,不要自作主张省略,必须明确告知用户或者用表格或展示所有。
|
||||
@@ -0,0 +1,13 @@
|
||||
# 上下文传递表
|
||||
|
||||
## 上下文传递表
|
||||
| 操作 | 提取 | 用于 |
|
||||
|------|------|------|
|
||||
| `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 |
|
||||
@@ -0,0 +1,11 @@
|
||||
# 考勤能力索引
|
||||
|
||||
| 主题 | 详见 |
|
||||
|---|---|
|
||||
| 日期范围计算、签到与打卡分流 | [`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) |
|
||||
@@ -0,0 +1,62 @@
|
||||
# 意图判断
|
||||
|
||||
## 意图判断
|
||||
|
||||
用户说"签到记录/签到数据/签到明细/外勤签到/导出签到" → `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 列表,则对每个 userId 调用 `dws contact user get --user-ids <userId>`(或等价通讯录查询),在最终输出中展示员工姓名而非裸 userId
|
||||
用户说"考勤组成员/打卡地址/打卡wifi/打卡蓝牙" → `group filtered-get`(按需查询,节省成本),若返回结果中含成员 userId 列表,则对每个 userId 调用 `dws contact user get --user-ids <userId>`(或等价通讯录查询),在最终输出中展示员工姓名而非裸 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`
|
||||
@@ -0,0 +1,107 @@
|
||||
# 注意事项
|
||||
|
||||
## 注意事项
|
||||
**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 --userIdList USER_ID --workDateBegin DATE --workDateEnd 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 --userIdList 03642229451220076 --workDateBegin 2026-05-13 --workDateEnd 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
|
||||
```
|
||||
@@ -11,7 +11,7 @@
|
||||
1. 未按"阶段 1"做人员解析 → `--users` 传入部门 ID 而非员工 userId,脚本虽内置回退但会浪费一次失败的接口调用
|
||||
2. 未按"阶段 0"判断报表类型 → 用户说"汇总"被理解成"明细",导致输出粒度错误
|
||||
3. 未按"列选择"判断是否传 `--column-keywords` → 用户要"迟到情况报表"被输出成全字段默认报表
|
||||
4. 未按"错误处理"规则处理无权限错误(errorCode 6001「无权限操作」/ `AUTH_ERROR`)/ `HSF_ILLEGALPARAMS` → 把环境错误当成业务错误反馈给用户
|
||||
4. 未按"错误处理"规则处理 403 / `HSF_ILLEGALPARAMS` → 把环境错误当成业务错误反馈给用户
|
||||
5. 未按"阶段 4"返回结果 → 把 Excel 内容贴在对话里,或者裸 userId 直接输出
|
||||
|
||||
**执行前自检(必须能在心中回答)**:
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
如果上述任何一项答不出,**回到本文档对应章节重新阅读**,禁止凭记忆/想象组装命令。
|
||||
|
||||
**前提**:当前用户必须是钉钉管理员,否则 report 系列接口返回业务权限错误(`server_error_code` 为 `AUTH_ERROR`、errorCode `6001`「无权限操作」),**不是 HTTP 403**。提示需要管理员权限,不要重试。
|
||||
**前提**:当前用户必须是钉钉管理员,否则 report 系列接口返回 403 权限错误。
|
||||
|
||||
## 核心原则
|
||||
|
||||
@@ -46,7 +46,7 @@ Agent 解析用户意图(报表类型、人员范围、时间范围、关注
|
||||
- 所有 `dws` 命令必须携带 `--format json`
|
||||
- 时间参数 `--start` / `--end` 格式必须为 `yyyy-MM-dd HH:mm:ss`
|
||||
- 字段 ID 与字段名的映射必须从 `report columns` 实时建立,禁止硬编码
|
||||
- 任何接口失败(含无权限错误 6001/`AUTH_ERROR`)必须向用户清晰报错,禁止静默吞掉
|
||||
- 任何接口失败(含 403)必须向用户清晰报错,禁止静默吞掉
|
||||
|
||||
## 涉及工具
|
||||
|
||||
@@ -102,10 +102,10 @@ Agent 解析用户意图(报表类型、人员范围、时间范围、关注
|
||||
| 用户说 | 应路由到 |
|
||||
|--------|---------|
|
||||
| "今天打卡了吗" | `dws attendance record get`(单次查询,非报表) |
|
||||
| "帮我排班" | [attendance-schedule.md](./attendance-schedule.md) 排班工作流(排班,非报表) |
|
||||
| "帮我排班" | `dws attendance schedule import`(排班写入,非报表;执行前确认) |
|
||||
| "我的假期还剩多少" | `dws attendance vacation balance`(单次查询) |
|
||||
| "帮我请假" | `dws oa`(审批流程,非报表) |
|
||||
| "我这个月的考勤怎么样" | `dws attendance summary`(个人统计,非报表) |
|
||||
| "我这个月的考勤怎么样" | `dws attendance summary --user <USER_ID> --date <YYYY-MM-DD> --stats-type month`(个人统计,非报表) |
|
||||
|
||||
## 工作流
|
||||
|
||||
@@ -246,7 +246,7 @@ python scripts/attendance_report_checkin.py \
|
||||
|
||||
- 脚本依赖 `openpyxl`,若未安装需先 `pip install openpyxl`
|
||||
- 脚本摘要输出到 stdout,进度日志输出到 stderr
|
||||
- 首次调试可加 `--inspect` 参数查看首条记录原始结构(`attendance_report_detail.py` / `attendance_report_monthly.py` / `attendance_report_daily.py` / `attendance_report_checkin.py` 支持;**`attendance_report_record.py` 无 `--inspect` 参数**)
|
||||
- 首次调试可加 `--inspect` 参数查看首条记录原始结构
|
||||
- 脚本执行失败(exit ≠ 0)时,stderr 中有具体错误信息
|
||||
|
||||
### 阶段 4: 返回结果给用户
|
||||
@@ -488,11 +488,11 @@ python scripts/attendance_report_checkin.py \
|
||||
|
||||
| 错误 | 原因 | 处理方式 |
|
||||
|------|------|---------|
|
||||
| 权限错误(errorCode 6001「无权限操作」/ `AUTH_ERROR`,非 HTTP 403) | 当前账号非管理员 | 提示需要管理员权限,不要重试 |
|
||||
| 权限错误(403) | 当前账号非管理员 | 提示需要管理员权限,不要重试 |
|
||||
| userId 无效 | 用户 ID 错误或已离职 | 脚本跳过并在摘要中标注 |
|
||||
| 时间区间超长 | 接口可能性能不佳 | 提示"超过 1 年的数据建议分阶段导出" |
|
||||
| openpyxl 未安装 | 环境缺包 | 输出 `pip install openpyxl` 安装提示 |
|
||||
| 脚本执行失败 | 接口异常/配置问题 | 将 stderr 错误信息转告用户,可加 `--inspect` 重试(`attendance_report_record.py` 不支持 `--inspect`) |
|
||||
| 脚本执行失败 | 接口异常/配置问题 | 将 stderr 错误信息转告用户,可加 `--inspect` 重试 |
|
||||
|
||||
## 使用示例
|
||||
|
||||
@@ -611,9 +611,9 @@ python scripts/attendance_report_checkin.py \
|
||||
|
||||
| 脚本 | 报表类型 | 数据来源 | CLI 参数 |
|
||||
|------|---------|---------|---------|
|
||||
| [attendance_report_detail.py](../../scripts/attendance_report_detail.py) | 明细 | `check result` + `check record` | `--users --start --end [--out]` |
|
||||
| [attendance_report_monthly.py](../../scripts/attendance_report_monthly.py) | 月度汇总(默认) | `report columns` + `report query-data` | `--users --start --end [--column-keywords] [--out]` |
|
||||
| [attendance_report_daily.py](../../scripts/attendance_report_daily.py) | 每日统计 | `report columns` + `report query-data` | `--users --start --end [--column-keywords] [--out]` |
|
||||
| [attendance_report_record.py](../../scripts/attendance_report_record.py) | 考勤记录 | `attendance approve list` + `oa approval detail` | `--type --users --start --end [--out]` |
|
||||
| [attendance_report_checkin.py](../../scripts/attendance_report_checkin.py) | 签到报表 | `attendance checkin records` | `--users --start --end [--out]` |
|
||||
| [attendance_report_common.py](../../scripts/attendance_report_common.py) | 公共模块(不可单独执行) | — | — |
|
||||
| [attendance_report_detail.py](../scripts/attendance_report_detail.py) | 明细 | `check result` + `check record` | `--users --start --end [--out]` |
|
||||
| [attendance_report_monthly.py](../scripts/attendance_report_monthly.py) | 月度汇总(默认) | `report columns` + `report query-data` | `--users --start --end [--column-keywords] [--out]` |
|
||||
| [attendance_report_daily.py](../scripts/attendance_report_daily.py) | 每日统计 | `report columns` + `report query-data` | `--users --start --end [--column-keywords] [--out]` |
|
||||
| [attendance_report_record.py](../scripts/attendance_report_record.py) | 考勤记录 | `attendance approve list` + `oa approval detail` | `--type --users --start --end [--out]` |
|
||||
| [attendance_report_checkin.py](../scripts/attendance_report_checkin.py) | 签到报表 | `attendance checkin records` | `--users --start --end [--out]` |
|
||||
| [attendance_report_common.py](../scripts/attendance_report_common.py) | 公共模块(不可单独执行) | — | — |
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# 日期范围与签到优先路由
|
||||
|
||||
> **【必读】日期范围严格计算规则 — 所有含 --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
|
||||
@@ -52,7 +52,7 @@ Agent 解析用户意图(考勤组、员工、日期范围、班次安排)
|
||||
- 禁止在未确认考勤组类型为排班制(TURN)的情况下执行排班
|
||||
- 禁止在班次未经校验的情况下执行排班
|
||||
- 禁止跳过用户确认直接执行排班
|
||||
- **禁止在未向用户展示完整排班明细表格(含每天的班次名称)的情况下弹出确认卡片**。用户必须先看到"谁、哪天、上什么班"才能做出确认决策
|
||||
- **禁止在未向用户展示完整排班明细表格(含每天的班次名称)的情况下请求确认**。用户必须先看到"谁、哪天、上什么班"才能做出确认决策
|
||||
- 禁止编造任何字段值或用户姓名
|
||||
- 禁止直接输出裸 userId,脚本已内置 userId → 姓名转换
|
||||
- **禁止直接输出裸 classId 数字**,必须展示班次名称(如"早班"),用户不理解 classId 是什么
|
||||
@@ -118,7 +118,7 @@ dws attendance rules --date <今天日期> --format json
|
||||
|
||||
如果是给指定员工排班,先查该员工的 userId,再查其考勤组。
|
||||
|
||||
**步骤 0b — 查询考勤组详情和关联班次(必须在 ask_question 之前完成)**:
|
||||
**步骤 0b — 查询考勤组详情和关联班次(必须在收集班次选择前完成)**:
|
||||
|
||||
```bash
|
||||
# 获取考勤组详情(含绑定的班次列表)
|
||||
@@ -132,7 +132,7 @@ dws attendance group get --group-id <groupId> --format json
|
||||
- 考勤组类型:`groupVO.type`(必须为 TURN)
|
||||
- 关联班次列表:`groupVO.shiftVOList[].shiftSetting.{shiftId, shiftName}`
|
||||
|
||||
**步骤 0c — 收集缺失参数(ask_question 卡片交互)**:
|
||||
**步骤 0c — 收集缺失参数**:
|
||||
|
||||
拿到考勤组和关联班次后,再向用户收集缺失的参数。排班所需的四个参数:
|
||||
- **考勤组**:已在 0a 自动获取,无需询问
|
||||
@@ -140,59 +140,12 @@ dws attendance group get --group-id <groupId> --format json
|
||||
- **员工范围**(必填):指定员工姓名 / 部门 / 考勤组全员 / "给我排班"
|
||||
- **日期范围**(必填):具体日期 / 日期范围(如"下周"、"5月19日到5月23日")
|
||||
|
||||
**只收集真正缺失的参数**,用户已经提供的不要重复询问。将缺失参数**合并到一次 `ask_question` 调用中**。
|
||||
|
||||
示例:用户说"帮我排班",Agent 应先自动查询考勤组和关联班次(步骤 0a + 0b),然后只询问日期范围和班次:
|
||||
|
||||
```
|
||||
// ===== 步骤 0a + 0b 已完成,此时你已经拿到了以下真实数据 =====
|
||||
// groupId = 实际的考勤组ID
|
||||
// groupName = 实际的考勤组名称
|
||||
// shiftVOList = 考勤组关联的班次列表(来自 dws attendance group get 的返回)
|
||||
|
||||
// 从 shiftVOList 构建班次选项(伪代码):
|
||||
shiftOptions = []
|
||||
for each shift in groupVO.shiftVOList:
|
||||
shiftOptions.append({ id: String(shift.shiftSetting.shiftId), label: shift.shiftSetting.shiftName })
|
||||
shiftOptions.append({ id: "rest", label: "排休" })
|
||||
|
||||
// 如果考勤组只关联了一个班次,直接使用,不需要询问用户
|
||||
if shiftVOList.length == 1:
|
||||
selectedShift = shiftVOList[0] // 自动选定,跳过班次选择
|
||||
|
||||
// 构建日期选项(必须填入实际计算的日期):
|
||||
todayStr = 当天日期(YYYY-MM-DD)
|
||||
thisWeekEnd = 本周日日期
|
||||
nextWeekStart = 下周一日期
|
||||
nextWeekEnd = 下周日日期
|
||||
|
||||
ask_question({
|
||||
title: "排班参数确认",
|
||||
questions: [
|
||||
{
|
||||
id: "date_range",
|
||||
prompt: "请选择排班日期范围",
|
||||
options: [
|
||||
{ id: "this_week", label: "本周剩余时间(" + todayStr + "-" + thisWeekEnd + ")" },
|
||||
{ id: "next_week", label: "下周(" + nextWeekStart + "-" + nextWeekEnd + ")" },
|
||||
{ id: "custom", label: "自定义日期范围" }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "shift",
|
||||
prompt: "请选择班次(以下为您考勤组「" + groupName + "」关联的班次)",
|
||||
options: shiftOptions // 直接使用上面从 shiftVOList 动态构建的选项,严禁替换为任何硬编码值
|
||||
}
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
**⚠️ 班次选项严禁硬编码**:上述伪代码中的 `shiftOptions` 必须在运行时从 `shiftVOList` 动态生成。禁止在 `ask_question` 中写入任何固定的班次名称(如"早班"、"晚班"、"正常班"、"全部排XX班"等)。如果你发现自己在 options 里手写班次名,说明你做错了。
|
||||
**只收集真正缺失的参数**,用户已经提供的不要重复询问;多个缺失参数可集中询问。日期选项必须展示实际计算后的日期范围,班次选项必须在运行时从 `shiftVOList` 动态生成,并以真实 `shiftId` 作为值、真实 `shiftName` 作为展示名称;可额外提供“排休”。只有一个关联班次时直接使用,无需再次选择。
|
||||
|
||||
**动态选项原则(严格执行)**:
|
||||
- 班次选项**必须且只能**来自考勤组的 `shiftVOList`,**严禁编造任何班次名称**(如"正常班"、"早班"、"晚班"、"全部排XX班"等都是编造)
|
||||
- 每个班次选项的 `id` 必须是 `shiftVOList` 中的真实 `shiftId`,`label` 必须是真实的 `shiftName`
|
||||
- 如果 `shiftVOList` 为空,降级从 `groupVO.classIds` + `class search` 按 ID 精确查询(不是全局搜索)
|
||||
- 如果 `shiftVOList` 为空,降级从 `groupVO.classIds` + `class get` 按 ID 精确查询(不是全局搜索)
|
||||
- **只收集缺失的参数**:用户已经提供的参数不要重复询问
|
||||
- **如果考勤组只有一个班次,直接使用该班次,不需要询问用户选择**
|
||||
- **禁止用 `class search` 全局搜索来给用户展示班次选项**——全局班次列表包含不属于该考勤组的班次,用户选了也会被校验拒绝
|
||||
@@ -251,21 +204,21 @@ dws attendance group filtered-get --group-id <groupId> --member --format json
|
||||
**禁止调用 `dws attendance class search` 全局搜索班次**——全局搜索会返回不属于该考勤组的班次,即使用户指定了班次名称,也必须在 `shiftVOList` 中匹配,而不是全局搜索。
|
||||
|
||||
**校验规则**:
|
||||
1. 用户在 `ask_question` 卡片中选择的班次,其 `shiftId` 必须存在于 `shiftVOList` 中(卡片选项本身就是从 `shiftVOList` 构建的,所以天然满足)
|
||||
1. 用户选择的班次 `shiftId` 必须存在于 `shiftVOList` 中;所有候选都必须由 `shiftVOList` 动态生成
|
||||
2. 如果用户通过自然语言指定了班次名称(如"排早班"),必须在 `shiftVOList` 中**按名称模糊匹配**,找到对应的 `shiftId`
|
||||
3. 如果用户指定的班次不在 `shiftVOList` 中,**必须拒绝**,并列出该考勤组关联的全部班次让用户重新选择
|
||||
4. 仅当 `shiftVOList` 为空时,才降级从 `groupVO.classIds` + `dws attendance class get` 按 ID 精确查询(仍然不是全局搜索)
|
||||
|
||||
**提取信息**:班次 ID(`classId` / `shiftId`)、班次名称(`shiftName`)
|
||||
|
||||
### 阶段 4: 回显排班内容并使用 ask_question 卡片确认
|
||||
### 阶段 4: 回显排班内容并获得明确确认
|
||||
|
||||
> **[硬性门禁]** 必须先用普通文本向用户展示**完整的排班明细表格**(包含每个人、每天、具体班次名称),用户看到排班明细后,才能弹出 `ask_question` 确认卡片。
|
||||
> **禁止在用户还不知道"谁、哪天、上什么班"的情况下就弹确认卡片**——这等于让用户盲签,体验极差。
|
||||
> **[硬性门禁]** 必须先向用户展示**完整的排班明细表格**(包含每个人、每天、具体班次名称),再获得用户明确确认。
|
||||
> **禁止在用户还不知道"谁、哪天、上什么班"的情况下请求确认**。
|
||||
|
||||
**步骤 4a — 展示排班明细(必须在确认卡片之前)**:
|
||||
**步骤 4a — 展示排班明细(必须在请求确认之前)**:
|
||||
|
||||
在调用 `ask_question` 之前,**必须先**用普通文本向用户展示排班内容。表格中**必须包含班次名称**(如"早班 09:00-18:00"),不能只展示 classId 数字:
|
||||
请求确认前,**必须先**向用户展示排班内容。表格中**必须包含班次名称**(如"早班 09:00-18:00"),不能只展示 classId 数字:
|
||||
|
||||
```
|
||||
排班预览
|
||||
@@ -291,27 +244,9 @@ dws attendance group filtered-get --group-id <groupId> --member --format json
|
||||
- [ ] 排休的记录标注了"排休"
|
||||
- [ ] 表格涵盖了所有待排班的员工和日期
|
||||
|
||||
**步骤 4b — 使用 `ask_question` 卡片确认(必须在展示表格之后)**:
|
||||
**步骤 4b — 获得明确确认(必须在展示表格之后)**:
|
||||
|
||||
```
|
||||
ask_question({
|
||||
title: "排班执行确认",
|
||||
questions: [
|
||||
{
|
||||
id: "confirm_execute",
|
||||
prompt: "以上排班将覆盖所选日期的现有排班记录,确认执行吗?",
|
||||
options: [
|
||||
{ id: "yes", label: "确认执行" },
|
||||
{ id: "no", label: "取消" }
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
**处理用户选择**:
|
||||
- 用户选择 **"确认执行"** → 进入阶段 5
|
||||
- 用户选择 **"取消"** → 终止流程,提示"已取消排班操作"
|
||||
说明排班将覆盖所选日期的现有记录,并等待用户明确确认。确认后进入阶段 5;用户取消或未明确同意时不执行导入。
|
||||
|
||||
### 阶段 5: 调用脚本执行排班
|
||||
|
||||
@@ -508,8 +443,8 @@ python scripts/attendance_schedule_import.py \
|
||||
|
||||
| 脚本 | 用途 | CLI 参数 |
|
||||
|------|------|---------|
|
||||
| [attendance_schedule_import.py](../../scripts/attendance_schedule_import.py) | 排班导入(含校验、回显、执行) | `--group-id --schedules --confirm` |
|
||||
| [attendance_schedule_export.py](../../scripts/attendance_schedule_export.py) | 排班查询导出(分批查询、排班表 Excel) | `--users --start --end [--output]` |
|
||||
| [attendance_schedule_import.py](../scripts/attendance_schedule_import.py) | 排班导入(含校验、回显、执行) | `--group-id --schedules --confirm` |
|
||||
| [attendance_schedule_export.py](../scripts/attendance_schedule_export.py) | 排班查询导出(分批查询、排班表 Excel) | `--users --start --end [--output]` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# 自动化脚本
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
| 脚本 | 场景 | 用法 |
|
||||
|------|------|------|
|
||||
| [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
|
||||
@@ -137,4 +137,4 @@ python scripts/attendance_vacation_balance.py \
|
||||
|
||||
| 脚本 | 场景 | CLI 参数 |
|
||||
|------|------|---------|
|
||||
| [attendance_vacation_balance.py](../../scripts/attendance_vacation_balance.py) | 假期余额列表 Excel 导出;脚本按假期名称关键词筛选规则,并逐个 `leaveCode` 调用余额查询 | `--users [--leave-keywords] [--out] [--inspect]` |
|
||||
| [attendance_vacation_balance.py](../scripts/attendance_vacation_balance.py) | 假期余额列表 Excel 导出;脚本按假期名称关键词筛选规则,并逐个 `leaveCode` 调用余额查询 | `--users [--leave-keywords] [--out] [--inspect]` |
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
# 核心工作流
|
||||
|
||||
## 核心工作流
|
||||
|
||||
```bash
|
||||
# 导入排班记录
|
||||
dws attendance schedule import --group-id 123456 \
|
||||
--schedules '[{"userId":"user001","classId":123,"workDate":"2026-04-22","checkBeginTime":"09:00","checkEndTime":"18:00"}]' \
|
||||
--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
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
# attendance 局部意图消歧
|
||||
|
||||
本文件从单 Skill `intent-guide.md` 拆分而来,仅保留与本产品相关的跨产品消歧规则。
|
||||
|
||||
| 用户说... | 真实意图 | 应该用 | 不要用 | 理由 |
|
||||
|---|---|---|---|---|
|
||||
| "查/提交 请假/加班/外出/出差/补卡 审批单" | 考勤业务审批单 | `attendance approve`(查询走 `attendance approve list`;提交走 `attendance approve templates --type leave\ | overtime\ | repair-check\ |
|
||||
@@ -48,25 +48,7 @@ def get_my_user_id(dry_run: bool = False) -> Optional[str]:
|
||||
return '<MY_USER_ID>'
|
||||
if not data or not isinstance(data, dict):
|
||||
return None
|
||||
# 兼容两种结构:
|
||||
# 1) 顶层直接给 userId
|
||||
# 2) {result: [{orgEmployeeModel: {userId}}]} 包裹
|
||||
uid = data.get('userId') or data.get('userid')
|
||||
if uid:
|
||||
return uid
|
||||
inner = data.get('result')
|
||||
if isinstance(inner, dict):
|
||||
inner = [inner]
|
||||
if isinstance(inner, list):
|
||||
for item in inner:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
emp = item.get('orgEmployeeModel')
|
||||
if isinstance(emp, dict) and emp.get('userId'):
|
||||
return emp['userId']
|
||||
if item.get('userId'):
|
||||
return item['userId']
|
||||
return None
|
||||
return data.get('userId') or data.get('userid')
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
考勤报表导出 — 签到记录粒度
|
||||
|
||||
[AI Agent 强制门禁] 调用本脚本前必须先阅读:
|
||||
dingtalk-workspace/references/products/attendance-report.md
|
||||
references/attendance-report.md
|
||||
|
||||
本脚本是"签到报表导出工作流"的执行末端,工作流完整定义在 attendance-report.md。
|
||||
|
||||
@@ -142,7 +142,7 @@ def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"导出签到报表 — 签到记录粒度。"
|
||||
"[强制] AI Agent 必须先读 references/products/attendance-report.md 再调用本脚本。"
|
||||
"[强制] AI Agent 必须先读 references/attendance-report.md 再调用本脚本。"
|
||||
),
|
||||
)
|
||||
parser.add_argument("--users", required=True,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
[AI Agent 强制门禁] 本模块不可单独执行,且任何调用方脚本
|
||||
(attendance_report_detail/monthly/daily.py)执行前都必须先阅读:
|
||||
dingtalk-workspace/references/products/attendance-report.md
|
||||
references/attendance-report.md
|
||||
|
||||
工作流细节、报表类型判断、人员获取、列选择、错误处理等约束
|
||||
全部在 attendance-report.md,禁止凭本脚本源码或 --help 自行组装命令。
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
考勤报表导出 — 每日统计粒度
|
||||
|
||||
⛔ 【AI Agent 强制门禁】调用本脚本前必须先阅读:
|
||||
dingtalk-workspace/references/products/attendance-report.md
|
||||
references/attendance-report.md
|
||||
|
||||
本脚本仅是"考勤报表导出工作流"的执行末端,工作流完整定义在 attendance-report.md,
|
||||
包含但不限于:
|
||||
@@ -113,7 +113,7 @@ def parse_args() -> argparse.Namespace:
|
||||
p = argparse.ArgumentParser(
|
||||
description=(
|
||||
"导出考勤报表 — 每日统计粒度。"
|
||||
"⛔ AI Agent 必须先读 references/products/attendance-report.md 再调用本脚本,"
|
||||
"⛔ AI Agent 必须先读 references/attendance-report.md 再调用本脚本,"
|
||||
"禁止凭 --help 或脚本路径自行拼命令。"
|
||||
),
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
|
||||
[AI Agent 强制门禁] 调用本脚本前必须先阅读:
|
||||
dingtalk-workspace/references/products/attendance-report.md
|
||||
references/attendance-report.md
|
||||
|
||||
本脚本仅是"考勤报表导出工作流"的执行末端,工作流完整定义在 attendance-report.md,
|
||||
包含但不限于:
|
||||
@@ -88,7 +88,7 @@ def parse_args() -> argparse.Namespace:
|
||||
p = argparse.ArgumentParser(
|
||||
description=(
|
||||
"导出考勤报表 — 明细粒度(打卡记录)。"
|
||||
"[强制] AI Agent 必须先读 references/products/attendance-report.md 再调用本脚本,"
|
||||
"[强制] AI Agent 必须先读 references/attendance-report.md 再调用本脚本,"
|
||||
"禁止凭 --help 或脚本路径自行拼命令。"
|
||||
),
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
考勤报表导出 — 月度汇总粒度
|
||||
|
||||
[AI Agent 强制门禁] 调用本脚本前必须先阅读:
|
||||
dingtalk-workspace/references/products/attendance-report.md
|
||||
references/attendance-report.md
|
||||
|
||||
本脚本仅是"考勤报表导出工作流"的执行末端,工作流完整定义在 attendance-report.md,
|
||||
包含但不限于:
|
||||
@@ -108,7 +108,7 @@ def parse_args() -> argparse.Namespace:
|
||||
p = argparse.ArgumentParser(
|
||||
description=(
|
||||
"导出考勤报表 — 月度汇总粒度。"
|
||||
"[强制] AI Agent 必须先读 references/products/attendance-report.md 再调用本脚本,"
|
||||
"[强制] AI Agent 必须先读 references/attendance-report.md 再调用本脚本,"
|
||||
"禁止凭 --help 或脚本路径自行拼命令。"
|
||||
),
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
考勤排班查询导出脚本
|
||||
|
||||
[AI Agent 强制门禁] 本脚本执行前必须先阅读:
|
||||
dingtalk-workspace/references/products/attendance-schedule.md
|
||||
references/attendance-schedule.md
|
||||
|
||||
职责:
|
||||
1. 分批查询排班记录(支持大量用户自动分批)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
考勤排班导入脚本
|
||||
|
||||
[AI Agent 强制门禁] 本脚本执行前必须先阅读:
|
||||
dingtalk-workspace/references/products/attendance-schedule.md
|
||||
references/attendance-schedule.md
|
||||
|
||||
排班工作流、参数校验、班次校验、回显确认等约束全部在
|
||||
attendance-schedule.md,禁止凭本脚本源码或 --help 自行组装命令。
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
假期余额 Excel 导出脚本。
|
||||
|
||||
[AI Agent 强制门禁] 调用本脚本前必须先阅读:
|
||||
dingtalk-workspace/references/products/attendance-vacation.md
|
||||
references/attendance-vacation.md
|
||||
|
||||
本脚本负责:
|
||||
1. 通过 dws attendance vacation types 获取假期规则列表,用于确定列顺序
|
||||
@@ -86,7 +86,7 @@ def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"导出假期余额 Excel。AI Agent 必须先读 "
|
||||
"references/products/attendance-vacation.md 再调用本脚本。"
|
||||
"references/attendance-vacation.md 再调用本脚本。"
|
||||
),
|
||||
)
|
||||
parser.add_argument("--users", required=True, help="userId 或 deptId 列表,逗号分隔")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: dingtalk-calendar
|
||||
description: 钉钉日历与会议室。Use when 用户说 约会议/查日程/订会议室/查闲忙/加参会人/改期/取消会议/今天的日程/本周日程/共同空闲。视频会议发起/邀请入会/会中控制当前 CLI 不支持,应提示在钉钉客户端操作。Distinct from dingtalk-minutes(听记)、dingtalk-todo(待办)。命令前缀:dws calendar。
|
||||
description: 钉钉日历与会议室。Use when 用户说 约会议/查日程/订会议室/查闲忙/加参会人/改期/取消会议/今天的日程/本周日程/共同空闲。视频会议发起/邀请入会/会中控制当前 CLI 不支持,应提示在钉钉客户端操作;AI 听记走 dingtalk-minutes,待办任务走 dingtalk-todo。命令前缀:dws calendar。
|
||||
cli_version: ">=0.2.14"
|
||||
metadata:
|
||||
category: product
|
||||
@@ -14,13 +14,12 @@ metadata:
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
> **PREREQUISITE:** Read the `dws-shared` skill first for auth, global flags, product routing, URL preflight, error codes, and safety rules. The `dws` binary must be on PATH.
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> ⚠️ **命令可用性以当前 dws 二进制为准**。服务发现已下线,本文档随内置 skill 发布;如果 `dws <cmd> --help` 不存在,说明当前版本未暴露该命令。若命令存在但调用失败,请按错误中的 endpoint 或 tool 提示确认静态端点目录和后端工具注册。实际调用前可用 `dws <cmd> --help` 或 `--dry-run` 验证。
|
||||
|
||||
|
||||
> 命令参考:[calendar.md](references/calendar.md);剧本:[03-meeting.md](references/03-meeting.md)。
|
||||
|
||||
## 意图表
|
||||
@@ -30,17 +29,52 @@ 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 busy search --users <id> --start "<ISO>" --end "<ISO>"` |
|
||||
| "查闲忙" | `dws calendar event list --start "<ISO>" --end "<ISO>"` |
|
||||
| "加参会人" / "订房" / "取消" | `dws calendar attendee add` / `room add` / `event delete` |
|
||||
|
||||
## 标准 SOP(必遵流程)
|
||||
|
||||
> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 userId/eventId。每条命令必须带 `--format json`,时间参数**必须**是 ISO-8601(如 `2026-07-03T14:00:00+08:00`)。
|
||||
|
||||
### SOP-1 查日程(list-events)
|
||||
|
||||
**触发**:今天/明天/本周日程/我有什么会/某时段日程。
|
||||
|
||||
1. **首选脚本(必须)**:`python scripts/calendar_today_agenda.py today|tomorrow|week`(聚合今日议程)。
|
||||
2. **降级 CLI(必须)**:脚本不可用时 `dws calendar event list --start "<起始ISO>" --end "<结束ISO>" --format json`;不传 `--start/--end` 默认查今天(00:00:00~23:59:59)。`hasMore=true` 用 `--limit`/翻页。
|
||||
3. **解析(必须)**:取真实 `eventId`、`attendees[]`、`start/end`;按需抽取,**禁止**把整段 JSON 原样贴出。
|
||||
|
||||
**禁止**:用 `event list` 替代闲忙查询(查闲忙走 SOP-3)、编造时间窗口、用非 ISO 时间格式。
|
||||
|
||||
### SOP-2 建日程(create-event)
|
||||
|
||||
**触发**:建日程/约会议/加日程。
|
||||
|
||||
1. **解析与会人(必须)**:对每个姓名 `dws aisearch person --keyword "<姓名>" --dimension name --format json` 取 `userId`,多人逗号拼接。
|
||||
2. **执行(必须)**:`dws calendar event create --summary "<主题>" --start "<ISO>" --end "<ISO>" --attendees <userId1,userId2> --format json`(按需加 `--location`/`--description`/`--rooms`)。
|
||||
3. **验证(必须)**:从返回取 `eventId`,可 `dws calendar event list --start "<ISO>" --end "<ISO>" --format json` 复核。
|
||||
|
||||
**禁止**:跳过与会人 userId 解析直接传姓名、编造会议室 roomId。
|
||||
|
||||
### SOP-3 查闲忙(check-busy)
|
||||
|
||||
**触发**:某人/会议室是否有空/找空闲时段/避免冲突。
|
||||
|
||||
1. **解析对象(必须)**:姓名 → `dws aisearch person --keyword "<姓名>" --dimension name --format json` 取 `userId`;会议室用 `roomId`。
|
||||
2. **收敛时段(必须)**:`--start`/`--end` **必须**由用户给出或明确收敛;时段不明确**必须先追问**,**禁止**默认全天窗口。
|
||||
3. **执行(必须)**:`dws calendar busy search --users <userId1,userId2> --start "<ISO>" --end "<ISO>" --format json`(查会议室换 `--rooms <roomId...>`,可同时传)。**禁止**用 `event list` 扫日程替代闲忙查询。
|
||||
4. **空闲时段(必须)**:找共同空闲用 `python scripts/calendar_free_slot_finder.py`。
|
||||
|
||||
**禁止**:用 `event list` 冒充 `busy search`、未确认时段就默认全天查询。
|
||||
|
||||
## 执行硬约束
|
||||
|
||||
- 多轮日程任务必须保留 `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`。
|
||||
|
||||
## 跨产品协作
|
||||
@@ -52,3 +86,6 @@ metadata:
|
||||
## 注意
|
||||
|
||||
`schedule-meeting` 必须读 [03-meeting.md](references/03-meeting.md) 中的「两准则」「搜房失败硬门禁」,禁止假设 `roomId`。
|
||||
## 局部意图与 Recipe
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md);[Lite Recipe](references/lite-recipes.md)。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 会议管理(日程与会议室)
|
||||
|
||||
> **lite 速查表**含 `list-today-meetings`、`check-users-busy`;视频会议 `start-conference` 当前 CLI 不支持。列表类操作须遵循 [calendar.md](./calendar.md) **「CLI 命令树与黄金路径」**,禁止无子命令的 `dws calendar` 或臆造 `calendar list`(见该文 **「反模式(禁止)」**)。**`schedule-meeting` 不做内联**:须读本文件 **「两准则」「搜房失败硬门禁」** 及下表 **schedule-meeting** 行全文。
|
||||
> **听记、会后待办、摘要分享** 见 `dingtalk-minutes` sub-skill 的 `references/07-minutes.md`。
|
||||
> lite recipe(`list-today-meetings`、`check-users-busy`)见 [lite-recipes.md](./lite-recipes.md);视频会议发起、邀请入会与会中控制当前 CLI 不支持,请在钉钉客户端操作。列表类操作须遵循 [calendar.md](./calendar.md) **「CLI 命令树与黄金路径」**,禁止无子命令的 `dws calendar` 或臆造 `calendar list`(见该文 **「反模式(禁止)」**)。预约会议须遵循本文件的时段、会议室与失败收束规则。
|
||||
> **听记、会后待办、摘要分享** 见 `dingtalk-minutes/references/07-minutes.md`。
|
||||
|
||||
## 日程与会议室两准则(强制)
|
||||
|
||||
@@ -22,24 +22,15 @@
|
||||
|
||||
### 搜房失败硬门禁(园区/范围搜尽仍无 roomId)
|
||||
|
||||
在用户限定的园区、楼宇、楼层或评测固定分组内,已按早停规则**逐组 `room search` 查完**仍得不到任何有效 `rooms[].roomId`(或无任何空闲房)→ **立即停止**,向用户**明确报错/失败结论**(例如:该时段在指定范围内未检索到可预订会议室或无法获得 roomId),**本回合订房流程结束**。
|
||||
在用户限定的园区、楼宇、楼层或固定分组内,已按早停规则**逐组 `room search` 查完**仍得不到任何有效 `rooms[].roomId`(或无任何空闲房)→ **立即停止**,向用户**明确报错/失败结论**(例如:该时段在指定范围内未检索到可预订会议室或无法获得 roomId),当前预订链路结束。
|
||||
|
||||
**用户汇报硬门禁**:一旦触发上面的失败条件,**下一条对外输出必须直接面向用户汇报结果**,不得继续在会话里自言自语式地延长推理。允许的后续只有两类:
|
||||
1. **失败汇报**:明确说明“指定范围/指定会议室在该时段未找到可预订会议室,因此当前无法完成预订”
|
||||
2. **确认放宽条件**:仅在需要继续推进时,明确问用户是否放宽地点范围、改时间或接受不订会议室
|
||||
**失败处理**:明确说明“指定范围/指定会议室在该时段未找到可预订会议室,因此当前无法完成预订”。只有用户同意放宽地点范围、改时间或接受不订会议室后,才可按新条件继续。
|
||||
|
||||
以下表述/行为视为**违例**:继续写“让我再试一次”“也许是 Mock/测试环境”“可能存在预设 roomId 映射”“我去别的 group 看看”“我换个时间验证一下”“我先看看脚本/示例还能不能推断出 roomId”。
|
||||
空结果只表示当前授权范围内没有返回合法 `roomId`;不要推测隐藏映射、环境差异或未经用户授权的新搜索范围。
|
||||
|
||||
以下行为**一律禁止**(与是否「想多试一次」无关):编造/假设 `roomId` 格式做「预订测试」;在**没有**合法 `roomId` 时调用 `room add` 试探错误详情;拉 `event get` / 日程详情等试图**绕开** `room search` 推断 roomId;换无关园区、扩大关键词、换工具名做未经用户授权的新搜索。
|
||||
|
||||
**失败后强制回读**:若出现以下任一信号,下一步**必须重新读取本文件本节与 `schedule-meeting` recipe**,不得沿着当前假设继续试:
|
||||
1. 连续 **2 次** `room search` 空结果/无 `roomId`
|
||||
2. 任意一次 `roomId invalid`
|
||||
3. 已开始尝试「换园区 / 换楼栋 / 看 event 详情 / 猜 roomId」
|
||||
|
||||
回读后只允许二选一:
|
||||
1. **报错收束**:已搜尽允许范围/整园仍无 `roomId` 或无空房
|
||||
2. **用户确认**:明确询问是否放宽范围、换时间,或接受不订会议室
|
||||
出现空结果、`roomId invalid` 或授权范围查尽时,停止当前预订链路;不得沿原假设重复搜索。后续只能报告失败,或在用户确认新范围/新时间后重新搜索。
|
||||
|
||||
| # | 规范 |
|
||||
|---|------|
|
||||
@@ -47,10 +38,10 @@
|
||||
| 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 | **全量无结果即收束**:在用户允许的搜索范围内(含**整园/全 campus** 若用户或评测要求已逐组查尽)仍无任何可用会议室或有效 `roomId` → **直接报错/告知失败并结束订房**,且**下一条消息必须汇报给用户**;**不得**假设 ID、不得用 `room add` 试探、不得绕路查日程、不得继续自说自话分析 Mock/测试环境 |
|
||||
| 6 | **失败触发回读**:连续 2 次空结果、任意一次 `roomId invalid`、或开始换园区/绕路时 → **必须回读本节**;回读后只允许「报错收束」或「向用户确认是否放宽条件」 |
|
||||
| 5 | **授权范围无结果即收束**:在用户允许的搜索范围内仍无可用会议室或有效 `roomId`,说明当前范围不可预订;不得假设 ID、用 `room add` 试探或绕路推断 |
|
||||
| 6 | **无效 ID 恢复**:遇到 `roomId invalid` 时停止预订,回到 `room search` 的真实返回;若范围已查尽则报告无可用房,否则先确认是否放宽地点或时间 |
|
||||
|
||||
| Recipe | 行动指南(固定路线) |
|
||||
| ------------------ | ------------------- |
|
||||
| schedule-meeting | **见上文「两准则」**、**「搜房失败硬门禁」**。**未给时段且仅说「发起/开个会」**→ 不走本 recipe;当前 CLI 不支持实时视频会议,告知用户请在钉钉客户端操作。**未给时段但有预约意图**("安排""约""定"等词):追问具体开始/结束时间。**已有时段后**,按固定顺序执行:1. `dws calendar event create` 建日程;2. 有参会人则 `dws calendar attendee 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/测试环境。细则见「会议室搜索早停」。 |
|
||||
| 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`。授权范围内无空房则报告不可预订;需要扩大范围或改时间时先取得用户同意。 |
|
||||
| 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 "<变更通知>"` 通知变更 |
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# 日历能力索引
|
||||
|
||||
| 主题 | 详见 |
|
||||
|---|---|
|
||||
| 日程/会议/会议室/闲忙 | [`calendar.md`](./calendar.md) |
|
||||
| 会议最佳实践 | [`03-meeting.md`](./03-meeting.md) |
|
||||
| 轻量流程 | [`lite-recipes.md`](./lite-recipes.md) |
|
||||
@@ -2,18 +2,17 @@
|
||||
|
||||
## CLI 命令树与黄金路径
|
||||
|
||||
- **二级子命令(必选其一)**:`event`(日程)、`attendee`(参会人)、`room`(会议室)、`busy`(闲忙)、`attachment`(日程附件)、`book`(用户日历列表)。`dws calendar` 后**必须**紧跟上述之一;**禁止**只执行 `dws calendar`(无子命令)。
|
||||
- **二级子命令(必选其一)**:`event`(日程)、`attendee`(参会人)、`room`(会议室)、`busy`(闲忙)、`attachment`(日程附件)、`book`(我能看哪些日历本)、`acl`(我的日历共享给了谁)。`dws calendar` 后**必须**紧跟上述之一;**禁止**只执行 `dws calendar`(无子命令)。
|
||||
- **个人日程 / 给自己留时间块 / 专注时段**:统一走 **`dws calendar event create`**。当前**没有**单独的 `personal schedule create` / `calendar create` 命令。
|
||||
- **查日程列表**:`dws calendar event list --start "<ISO-8601>" --end "<ISO-8601>" --format json`,或优先使用脚本 `python scripts/calendar_today_agenda.py [today|tomorrow|week]`(见文末「自动化脚本」)。
|
||||
- **查用户日历本列表**:`dws calendar book list`(返回字段为 `calendarId`,主日历 `calendarId == "primary"` 等;注意无 `id` 字段,按 `.id` 提取会取空)。**重要**可以查询他人共享给自己的日历本,根据日历本id可以进一步查询对方的日程信息。
|
||||
- **查用户日历本列表**:`dws calendar book list`(返回主日历 `id == "primary"` 等)。**重要**可以查询他人共享给自己的日历本,根据日历本id可以进一步查询对方的日程信息。
|
||||
- **CLI 不存在**独立的 `dws calendar list`;若误跑无子命令的 `dws calendar`,会打印整段 Usage,**切勿**将该段 help 当作工具结果再次塞进对话(会急剧增加 token 与首字延迟)。
|
||||
- **必须**遵循指令说明进行调用。**绝对禁止**使用虚构指令,使用虚构参数。
|
||||
|
||||
## 反模式(禁止)
|
||||
1. **禁止**执行 `dws calendar` 且不带二级子命令(会刷出大量帮助文本)。合法二级子命令:`event` / `attendee` / `room` / `busy` / `attachment` / `book`。
|
||||
1. **禁止**执行 `dws calendar` 且不带二级子命令(会刷出大量帮助文本)。合法二级子命令:`event` / `attendee` / `room` / `busy` / `attachment` / `book` / `acl`。
|
||||
2. **禁止**使用不存在的子命令试探(如臆造 `dws calendar list`);需要日程列表时一律使用 **`dws calendar event list`**(带 `--start` / `--end`,见下文「查询日程列表」示例);需要日历本列表时使用 **`dws calendar book list`**。
|
||||
3. **禁止**将完整 `--help`/Usage 输出作为「观察」重复提交给模型;若误触,应直接改用本节黄金路径中的合法命令并重试。
|
||||
4. **禁止**继续使用已弃用的 `--max-results` 参数 —— 它们仍可被解析但**会被丢弃**,不再透传到 MCP,模型生成命令时也不要再带。
|
||||
5. **禁止**为已有日程重新创建日程来预订会议室。若日程已存在(同一会话中刚创建、或用户明确指向某日程),必须使用 `room add --event <已有EVENT_ID> --rooms <ROOM_ID>` 追加会议室,**绝不能**再调一次 `event create --rooms`(会创建重复日程)。
|
||||
6. **禁止**用 `--location` 替代会议室预订。`--location` 是纯文本地点备注字段,填入会议室名称**不会**完成任何预订或占用。预订会议室必须通过 `room add --rooms <roomId>` 或 `event create --rooms <roomId>`,roomId 来自 `room search` 返回;`--location` 与 `--rooms` 是两个独立字段,用途完全不同。
|
||||
7. **禁止**只传 `--recurrence-*` 部分 flag **并不是彼此独立的参数**:只传其中一项(比如只改 `--recurrence-count`、只设 `--recurrence-type`)会让服务端收到不完整的 recurrence 结构,CLI 现已前置校验并直接拒绝这类调用。**修改已有周期日程的任何一个循环字段时,都必须重新提供完整的 pattern+range 字段集合**——必要时先 `event get` 读取现有 `recurrence`,再在命令中整体重传。
|
||||
@@ -30,6 +29,9 @@
|
||||
响应状态(response):参会人对日程的回应,包括:未响应、接受、待定、拒绝。
|
||||
忙闲时间(busy):查询用户在指定时间段的忙闲状态,查询会议室在指定时间段的预定状态,用于会议时间协调。
|
||||
会议室(room):room是 会议室 ,room可视为日程的资源类参会人,需要加入日程完成预订。注意和location区分,location只是地点,和room不同。
|
||||
访问控制 (acl):用户可通过设置acl将自己的日历访问权限授予给他人(即:共享日历),授予后,他人就可以查看日历下的日程信息。通过 `dws calendar acl list` 可查看当前要用户已经授权出去的权限。若 privilege >= reader,可查询此日历下的日程数据。若 privilege >= writer ,可操作(创建/修改/删除/响应等)此日历下的日程数据。
|
||||
共享日历:将自己日历的访问权限授予给他人,用于协作。通过 `dws calendar book list` 查询当前用户日历列表,其中type == `shared` 即他人共享给当前用户的日历。
|
||||
订阅日历:创建一个公共日历供他人订阅,他人订阅后即可查询日历下的日程数据。通过 `dws calendar book list` 查询当前用户日历列表,其中type == `subscribed` 即当前用户已订阅的日历。注意:订阅日历下的日程无参会人概念,无法执行 attendee 相关指令,也无法添加会议室。
|
||||
|
||||
## 命令概览
|
||||
|
||||
@@ -61,7 +63,6 @@ dws calendar room add [flags]
|
||||
dws calendar room delete [flags]
|
||||
```
|
||||
> room是会议室,用于线下开会场景。
|
||||
> **组织限制**:部分企业使用自建会议室系统,未接入钉钉会议室能力。此时 `room search` / `room list-groups` 会返回业务错误 `400056`("所选组织不支持预定钉钉会议室")。这是组织级配置限制,不是命令用法问题;应直接告知用户该组织需在钉钉客户端手动预订会议室,不要重试或换参。
|
||||
|
||||
### busy 相关三级子命令
|
||||
```
|
||||
@@ -75,10 +76,26 @@ dws calendar busy search [flags]
|
||||
dws calendar attachment add [flags]
|
||||
```
|
||||
|
||||
### book 相关三级子命令
|
||||
### book 相关三级子命令(查"我能看哪些日历本")
|
||||
```
|
||||
# 查询当前用户的所有日历,结果范围:用户自己的日历、已订阅的公共/团队日历、他人共享的日历。
|
||||
# 查询我拥有和可访问的所有日历本(含他人共享给我的)
|
||||
dws calendar book list [flags]
|
||||
# 查询指定日历本信息
|
||||
dws calendar book get [flags]
|
||||
# 按名称模糊搜索日历本
|
||||
dws calendar book search [flags]
|
||||
# 更新日历本信息(需 owner 权限)
|
||||
dws calendar book update [flags]
|
||||
```
|
||||
|
||||
### acl 相关三级子命令(查"我的日历共享给了谁")
|
||||
```
|
||||
# 查询我的日历共享给了哪些人、各自什么权限
|
||||
dws calendar acl list [flags]
|
||||
# 把我的日历共享给某人
|
||||
dws calendar acl add [flags]
|
||||
# 取消我的日历对某人的共享
|
||||
dws calendar acl delete [flags]
|
||||
```
|
||||
> **说明**: 可以通过 --help 进一步查看指令明细,也可以继续查看下一节 命令总览
|
||||
|
||||
@@ -90,17 +107,22 @@ Usage:
|
||||
dws calendar event list [flags]
|
||||
Example:
|
||||
dws calendar event list --start "2026-03-10T14:00:00+08:00" --end "2026-03-10T18:00:00+08:00"
|
||||
dws calendar event list --start "2026-03-10T00:00:00+08:00" --end "2026-03-31T23:59:59+08:00" --limit 50
|
||||
dws calendar event list --calendar-id primary
|
||||
dws calendar event list --cursor "<nextCursor从上一次查询结果获取>"
|
||||
Flags:
|
||||
--calendar-id string 日历 ID (默认 primary 主日历,仅在查询其他日历本时填写;通过 `book list` 获取)
|
||||
--cursor string 分页游标 (从上一次返回的 nextCursor 获取,首次查询无需传入)
|
||||
--end string 结束时间 ISO-8601 (例如 2026-03-10T18:00:00+08:00)
|
||||
--limit int 每页返回条数 (默认 100,最大 100)
|
||||
--start string 开始时间 ISO-8601 (例如 2026-03-10T14:00:00+08:00)
|
||||
```
|
||||
|
||||
> `--max-results` 已弃用:MCP 不再支持,CLI 仍接受但参数会被丢弃,结果固定最多返回 100 条。
|
||||
|
||||
**默认行为**:不传 `--start` / `--end` 时,默认返回今天的日程(00:00:00 ~ 23:59:59)。
|
||||
**权限**:查询共享日历下的日程时,至少要有reader权限。
|
||||
**分页**:单次最多返回 `--limit` 指定的条数(默认/最大 100);当结果超过 limit 时,返回体包含 `nextCursor` 字段。首次查询无需传 `--cursor`,仅在翻页时将上一次返回的 `nextCursor` 作为 `--cursor` 传入。
|
||||
|
||||
当前用户的个人日程使用 `dws calendar event list` 查询;参数包含 `--limit` 和 `--cursor` 分页。
|
||||
|
||||
### 获取日程详情
|
||||
```
|
||||
@@ -130,10 +152,17 @@ Example:
|
||||
dws calendar event create --title "每日站会" \
|
||||
--start "2026-03-10T09:00:00+08:00" --end "2026-03-10T09:30:00+08:00" \
|
||||
--recurrence-type daily --recurrence-interval 1 --recurrence-range-type numbered --recurrence-count 10
|
||||
dws calendar event create --title "团队周会" \
|
||||
--start "2026-03-10T14:00:00+08:00" --end "2026-03-10T15:00:00+08:00" \
|
||||
--calendar-id <SHARED_CALENDAR_ID> # 在指定日历本下创建日程
|
||||
dws calendar event create --title "重要会议" \
|
||||
--start "2026-03-10T14:00:00+08:00" --end "2026-03-10T15:00:00+08:00" \
|
||||
--remind-minutes 5,10 # 开始前5分钟和10分钟各提醒一次
|
||||
Flags:
|
||||
--title string 日程标题 (必填,最大2048字符)
|
||||
--start string 开始时间 ISO-8601 (必填,例如 2026-03-10T14:00:00+08:00)
|
||||
--end string 结束时间 ISO-8601 (必填,例如 2026-03-10T15:00:00+08:00)
|
||||
--calendar-id string 日历 ID (可选,默认 primary 主日历;仅在共享/订阅日历本下创建时填写,通过 `book list` 获取)
|
||||
--timezone string 时区 IANA 格式 (例如 Asia/Shanghai,默认 Asia/Shanghai)
|
||||
--desc string 日程描述 (最大5000字符)
|
||||
--attendees string 参会人 userId 列表,逗号分隔 (最多500人) 日程组织人自动放入参会人列表,无需传入userId
|
||||
@@ -153,6 +182,7 @@ Flags:
|
||||
--rich-text-desc string html格式的富文本类型日程描述,用于复杂内容的展示
|
||||
--location string 地点信息(纯文本备注,如‘3号楼A区’;**不等于**预订会议室)
|
||||
--free-busy string 此日程的忙碌状态,默认值为busy。busy - 在忙闲视图中,此日程时间段为忙碌; free - 此日程不占用忙闲
|
||||
--remind-minutes string 日程开始前提醒,逗号分隔分钟数 (可选,例如 5,10,15 表示开始前5/10/15分钟提醒;不传则默认15分钟提醒)
|
||||
```
|
||||
|
||||
> **说明**:个人日程也走 `event create`。如果只是给自己安排时间,不传 `--attendees` / `--open-dingtalk-ids` 即可。
|
||||
@@ -166,8 +196,10 @@ Example:
|
||||
dws calendar event update --id <EVENT_ID> --desc "新描述" --timezone Asia/Tokyo
|
||||
dws calendar event update --id <EVENT_ID> --recurrence-type daily --recurrence-interval 1 \
|
||||
--recurrence-range-type numbered --recurrence-count 5
|
||||
dws calendar event update --id <EVENT_ID> --calendar-id <SHARED_CALENDAR_ID> --title "新标题" # 修改其他日历本下的日程
|
||||
Flags:
|
||||
--id string 日程 ID (必填)
|
||||
--calendar-id string 日历 ID (可选,默认 primary 主日历;指定其他日历本时填写,可通过 `book list` 获取)
|
||||
--title string 新标题
|
||||
--start string 新开始时间 ISO-8601
|
||||
--end string 新结束时间 ISO-8601
|
||||
@@ -199,8 +231,10 @@ Usage:
|
||||
dws calendar event delete [flags]
|
||||
Example:
|
||||
dws calendar event delete --id <EVENT_ID> --yes
|
||||
dws calendar event delete --id <EVENT_ID> --calendar-id <SHARED_CALENDAR_ID> --yes # 删除其他日历本下的日程
|
||||
Flags:
|
||||
--id string 日程 ID (必填)
|
||||
--id string 日程 ID (必填)
|
||||
--calendar-id string 日历 ID (可选,默认 primary 主日历;指定其他日历本时填写,可通过 `book list` 获取)
|
||||
```
|
||||
|
||||
### 查看参会人
|
||||
@@ -209,8 +243,10 @@ Usage:
|
||||
dws calendar attendee list [flags]
|
||||
Example:
|
||||
dws calendar attendee list --event <EVENT_ID>
|
||||
dws calendar attendee list --event <EVENT_ID> --calendar-id <SHARED_CALENDAR_ID> # 查看其他日历本下日程的参会人
|
||||
Flags:
|
||||
--event string 日程 ID (必填)
|
||||
--event string 日程 ID (必填)
|
||||
--calendar-id string 日历 ID (可选,默认 primary 主日历;指定其他日历本时填写,可通过 `book list` 获取, 注意:订阅日历下的日程无参会人,因此不可查看)
|
||||
```
|
||||
|
||||
### 添加参会人
|
||||
@@ -220,10 +256,12 @@ Usage:
|
||||
Example:
|
||||
dws calendar attendee add --event <EVENT_ID> --attendees <USER_ID_1>,<USER_ID_2>
|
||||
dws calendar attendee add --event <EVENT_ID> --attendees <USER_ID> --optional
|
||||
dws calendar attendee add --event <EVENT_ID> --attendees <USER_ID> --calendar-id <SHARED_CALENDAR_ID> # 给其他日历本下的日程添加参会人
|
||||
Flags:
|
||||
--event string 日程 ID (必填)
|
||||
--attendees string 参会人 userId 列表,逗号分隔 (必填,最多500人)
|
||||
--optional 参会人可选 (默认必选参会人)
|
||||
--event string 日程 ID (必填)
|
||||
--attendees string 参会人 userId 列表,逗号分隔 (必填,最多500人)
|
||||
--optional 参会人可选 (默认必选参会人)
|
||||
--calendar-id string 日历 ID (可选,默认 primary 主日历;指定其他日历本时填写,可通过 `book list` 获取,注意:订阅日历下的日程无参会人,因此不可添加)
|
||||
```
|
||||
|
||||
### 移除参会人
|
||||
@@ -235,36 +273,54 @@ Usage:
|
||||
dws calendar attendee delete [flags]
|
||||
Example:
|
||||
dws calendar attendee delete --event <EVENT_ID> --attendees <USER_ID> --yes
|
||||
dws calendar attendee delete --event <EVENT_ID> --attendees <USER_ID> --calendar-id <SHARED_CALENDAR_ID> --yes # 移除其他日历本下日程的参会人
|
||||
Flags:
|
||||
--event string 日程 ID (必填)
|
||||
--attendees string 参会人 userId 列表,逗号分隔 (必填)
|
||||
--event string 日程 ID (必填)
|
||||
--attendees string 参会人 userId 列表,逗号分隔 (必填)
|
||||
--calendar-id string 日历 ID (可选,默认 primary 主日历;指定其他日历本时填写,可通过 `book list` 获取,注意:订阅日历下的日程无参会人,因此不可移除)
|
||||
```
|
||||
|
||||
### 搜索会议室
|
||||
> 此指令可用于搜索当前用户可用的会议室。**注意**,大部分会议室**仅在工作时间**可用,如果检索时间不在工作时间可能查不到任何结果。
|
||||
> 此指令支持两种模式:**按名称搜索**(不传 --start/--end)和**按时间段搜索可用会议室**(传 --start/--end 或不传任何参数)。
|
||||
> 此指令搜索到的会议室结果中,有两个值需要注意:
|
||||
- customApprovalProcess: true - 表示该会议室设置了自定义审批流程,只能通过客户端完成预订。
|
||||
- supportRecurring: true - 表示该会议室支持循环预定;false - 表示不支持循环预定,直接加入到循环日程会失败。
|
||||
> - customApprovalProcess: true - 表示该会议室设置了自定义审批流程,只能通过客户端完成预订。
|
||||
> - supportRecurring: true - 表示该会议室支持循环预定;false - 表示不支持循环预定,直接加入到循环日程会失败。
|
||||
|
||||
**模式路由规则**:
|
||||
- **按名称搜索**:仅传 `--room-name`,不传 `--start`/`--end` → 返回所有匹配名称的会议室,**不检查可用性**。适用于「找到某个会议室」的场景。
|
||||
- **按时间段搜索可用会议室**:传 `--start`/`--end`,或不传任何参数 → 返回指定时间段内**可用**的会议室。不传时间时默认当前时间起 1 小时。
|
||||
|
||||
```
|
||||
Usage:
|
||||
dws calendar room search [flags]
|
||||
Example:
|
||||
# 按名称搜索(不检查可用性,返回所有匹配的会议室)
|
||||
dws calendar room search --room-name 永澄亭 # 注意:用户即使说「永澄亭会议室」,也应仅传「永澄亭」
|
||||
|
||||
# 按时间段搜索可用会议室
|
||||
dws calendar room search --start "2026-03-10T14:00:00+08:00" --end "2026-03-10T15:00:00+08:00"
|
||||
dws calendar room search --start "2026-03-10T14:00:00+08:00" --end "2026-03-10T15:00:00+08:00" --group-id <GROUP_ID>
|
||||
dws calendar room search --room-name 永澄亭 # 注意:用户即使说「永澄亭会议室」,也应仅传「永澄亭」
|
||||
dws calendar room search # 不传 --start/--end 时默认当前时间起 1 小时
|
||||
|
||||
# 名称 + 时间段:搜索指定名称的可用会议室
|
||||
dws calendar room search --room-name 永澄亭 --start "2026-03-10T14:00:00+08:00" --end "2026-03-10T15:00:00+08:00"
|
||||
|
||||
# 分页(仅按时间段搜索时有效)
|
||||
dws calendar room search --start "2026-03-10T14:00:00+08:00" --end "2026-03-10T15:00:00+08:00" --limit 20 --page 0
|
||||
Flags:
|
||||
--start string 开始时间 ISO-8601 (可选,不传则默认当前时间+1分钟缓冲)
|
||||
--end string 结束时间 ISO-8601 (可选,不传则默认当前时间+1 小时)
|
||||
--group-id string 会议室分组ID(可选,留空查根目录;超100条时需按分组查询)
|
||||
--room-name string 按会议室名称过滤(可选,服务端模糊匹配;传入前必须由调用方精简,只保留核心专名)
|
||||
--group-id string 会议室分组ID(可选,留空查根目录;超100条时需按分组查询;仅按时间段搜索时有效)
|
||||
--room-name string 会议室名称(按名称搜索时必填;按时间段搜索时可选,用于过滤)
|
||||
--limit string 页大小 (可选,不填默认 100,超过 100 按 100 处理;仅按时间段搜索时有效)
|
||||
--page string 分页起始位置 (可选,不填默认 0;仅按时间段搜索时有效)
|
||||
```
|
||||
|
||||
> **时间约束(API 限制)**:`start` 必须是未来的时间(服务端校验:start can not less current time)。
|
||||
> - 若传入的 `--start` 早于当前时间,CLI 会自动修正为 `now + 1min`,调用方无需额外处理。
|
||||
> - 若传入的 `--end` 早于当前时间,CLI 直接报错——无法检索已过去的时间段。
|
||||
> - **最佳实践**:调用方在组装时间参数时应确保 start/end 都是未来时间;若不确定,可省略 `--start`/`--end` 让 CLI 使用默认值(当前时间起 1 小时)。
|
||||
> - **注意**:时间约束仅在「按时间段搜索」模式下生效。按名称搜索(仅传 `--room-name`)不受时间约束。
|
||||
|
||||
**名称过滤使用规范**:`--room-name` 适用于用户说「预定永澄亭」「约西湖厅」这类按名找会议室的场景。
|
||||
- **服务端是模糊匹配,但匹配词越精简命中率越高**,关键疗法:**调用方必须在调用 CLI 前自行精简名称,CLI 不会再做任何删减**。
|
||||
@@ -274,13 +330,16 @@ Flags:
|
||||
- 用户:「西湖厅有空吗」 → `--room-name 西湖厅`(本身就是专名,不删即可)
|
||||
- 用户:「预定贡嘎山大会议室」 → `--room-name 贡嘎山`
|
||||
|
||||
**优先路径**:当用户给了会议室中文名时,**优先用 `room search --room-name <核心专名> --start <开始时间> --end <结束时间>`**代替「先走 `list-groups`再遍历」的旧流程。`--room-name` 可与 `--group-id` 同时使用,表示「在指定分组内按名称过滤」。若返回空列表,再降级使用 `list-groups` 定位分组再查。
|
||||
**优先路径**:
|
||||
- 当用户仅给出会议室名称、未指定时间段时,用 `room search --room-name <核心专名>` 快速找到会议室(不检查可用性)。
|
||||
- 当用户给出会议室名称且指定了时间段时,用 `room search --room-name <核心专名> --start <开始时间> --end <结束时间>` 查询该名称的可用会议室。
|
||||
- 若返回空列表,再降级使用 `list-groups` 定位分组再查。`--room-name` 可与 `--group-id` 同时使用(仅按时间段搜索时),表示「在指定分组内按名称过滤」。
|
||||
|
||||
**`roomId` 与用户说的话不是一回事**:用户说的「C6-4-06-N 贡嘎山」等是**展示名/编号文案**,**绝不能**直接填进 `room add --rooms`。`--rooms` 只接受上一步 `room search`(或同类接口)返回 JSON 里的 **`rooms[].roomId`**。形态上多为**小写十六进制串**(长度以接口为准,例如 `e6b7b65b8b30fb707afcf6c3b699f028003e6834fdd7fee7`)。含**中文、空格、连字符拼接的楼层编号**、或凭空调 UUID/纯数字「试格式」——一律视为非法,必须先搜房再取返回字段。
|
||||
|
||||
> 如果知道roomId,想查该会议室的预订记录,直接用dws calendar busy search 指令
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
### 预定会议室
|
||||
```
|
||||
@@ -288,9 +347,11 @@ Usage:
|
||||
dws calendar room add [flags]
|
||||
Example:
|
||||
dws calendar room add --event <EVENT_ID> --rooms <ROOM_ID>
|
||||
dws calendar room add --event <EVENT_ID> --rooms <ROOM_ID> --calendar-id <SHARED_CALENDAR_ID> # 给其他日历本下的日程预定会议室
|
||||
Flags:
|
||||
--event string 日程 ID (必填)
|
||||
--rooms string 会议室 ID 列表 (必填)
|
||||
--event string 日程 ID (必填)
|
||||
--rooms string 会议室 ID 列表 (必填)
|
||||
--calendar-id string 日历 ID (可选,默认 primary 主日历;指定其他日历本时填写,可通过 `book list` 获取,注意:订阅日历下的日程不可添加会议室)
|
||||
```
|
||||
> room是会议室,用于线下开会场景。将room加入到日程完成预订
|
||||
> 重复性日程,预订会议室时,必须设置 循环结束时间(recurrence-end-date),noEnd 或者 指定循环次数 都无法完成预定。
|
||||
@@ -305,9 +366,11 @@ Usage:
|
||||
dws calendar room delete [flags]
|
||||
Example:
|
||||
dws calendar room delete --event <EVENT_ID> --rooms <ROOM_ID> --yes
|
||||
dws calendar room delete --event <EVENT_ID> --rooms <ROOM_ID> --calendar-id <SHARED_CALENDAR_ID> --yes # 移除其他日历本下日程的会议室
|
||||
Flags:
|
||||
--event string 日程 ID (必填)
|
||||
--rooms string 会议室 ID 列表 (必填)
|
||||
--event string 日程 ID (必填)
|
||||
--rooms string 会议室 ID 列表 (必填)
|
||||
--calendar-id string 日历 ID (可选,默认 primary 主日历;指定其他日历本时填写,可通过 `book list` 获取。注意:订阅日历下的日程不可添加会议室)
|
||||
```
|
||||
|
||||
### 会议室分组列表
|
||||
@@ -328,24 +391,104 @@ Usage:
|
||||
dws calendar attachment add [flags]
|
||||
Example:
|
||||
dws calendar attachment add --event <EVENT_ID> --files <FILE_ID>:report.pdf,<FILE_ID2>:slides.pptx
|
||||
dws calendar attachment add --event <EVENT_ID> --files <FILE_ID>:report.pdf --calendar-id <SHARED_CALENDAR_ID> # 给其他日历本下的日程添加附件
|
||||
Flags:
|
||||
--event string 日程 ID (必填)
|
||||
--files string 附件列表,格式 <fileId>:<name>,多项逗号分隔 (必填)
|
||||
--event string 日程 ID (必填)
|
||||
--files string 附件列表,格式 <fileId>:<name>,多项逗号分隔 (必填)
|
||||
--calendar-id string 日历 ID (可选,默认 primary 主日历;指定其他日历本时填写,可通过 `book list` 获取,注意:订阅日历下的日程不可添加附件)
|
||||
```
|
||||
|
||||
> 上传文件得到 `fileId` 需配合钉盘相关流程;本命令只负责把已上传的文件挂载到日程上。
|
||||
|
||||
### 查询用户日历列表
|
||||
### 查询我能看的所有日历本
|
||||
```
|
||||
Usage:
|
||||
dws calendar book list [flags]
|
||||
Example:
|
||||
dws calendar book list
|
||||
```
|
||||
> 通过此接口可查询当前用户的日历列表,包含 主日历本、他人共享的日历、订阅的公共/团队日历。
|
||||
> 共享日历本中有来自 xxx 的,且权限大于reader,那么通过 `event list --calendar-id <xxx的日历本id> `可查到xxx完整的日程安排
|
||||
> 查询"我能看哪些日历本",包含:我的主日历、他人共享**给我**的日历、订阅的公共/团队日历。注意区分:`acl list` 是查"我的日历共享**给了谁**",方向相反。
|
||||
> 共享日历本中有来自 xxx 的,且权限大于reader,那么通过 `event list --calendar-id <xxx的日历本id> `可查到xxx完整的日程安排。
|
||||
> 主日历 `id` 固定为 `primary`,绝大多数日程操作都默认走主日历,只有当用户明确要求查/写其他日历本时才需要带 `--calendar-id`。
|
||||
|
||||
### 查询指定日历本
|
||||
```
|
||||
Usage:
|
||||
dws calendar book get [flags]
|
||||
Example:
|
||||
dws calendar book get --id primary
|
||||
dws calendar book get --id CALENDAR_ID
|
||||
Flags:
|
||||
--id string 日历 ID (必填,主日历固定为 primary)
|
||||
```
|
||||
|
||||
> **说明**:根据日历 id 查询指定日历的详细信息。用户主日历本 id 固定为 `primary`。
|
||||
|
||||
### 搜索日历本
|
||||
```
|
||||
Usage:
|
||||
dws calendar book search [flags]
|
||||
Example:
|
||||
dws calendar book search --query "项目"
|
||||
dws calendar book search --query "团队周报"
|
||||
Flags:
|
||||
--query string 按日历本名称模糊检索 (必填)
|
||||
```
|
||||
|
||||
> **说明**:搜索当前用户拥有的日历本,支持按日历本名模糊搜索。获取全部日历请使用 `book list`。
|
||||
|
||||
### 更新日历本
|
||||
```
|
||||
Usage:
|
||||
dws calendar book update [flags]
|
||||
Example:
|
||||
dws calendar book update --id CALENDAR_ID --summary "新日历名"
|
||||
dws calendar book update --id CALENDAR_ID --desc "日历描述"
|
||||
Flags:
|
||||
--id string 日历 ID (必填)
|
||||
--summary string 日历标题
|
||||
--desc string 日历描述
|
||||
```
|
||||
|
||||
> **说明**:更新日历信息,最低权限要求:privilege == "owner"。注意:用户主日历本 以及 他人共享的日历本 **不支持更新**。
|
||||
|
||||
### 查询我的日历共享给了谁
|
||||
```
|
||||
Usage:
|
||||
dws calendar acl list [flags]
|
||||
Example:
|
||||
dws calendar acl list
|
||||
```
|
||||
|
||||
> **说明**:查询"我的日历共享给了哪些人、各自什么权限"(即主日历的访问控制列表)。注意区分:`book list` 是查"我能看哪些日历本",方向相反。
|
||||
|
||||
### 把我的日历共享给某人
|
||||
```
|
||||
Usage:
|
||||
dws calendar acl add [flags]
|
||||
Example:
|
||||
dws calendar acl add --user USER_ID --privilege reader
|
||||
dws calendar acl add --user USER_ID --privilege writer --no-notification
|
||||
Flags:
|
||||
--user string 授予权限的目标用户 ID (必填)
|
||||
--privilege string 授予的日历权限 (必填): free_busy_reader(查看忙闲)|title_reader(查看标题)|reader(查看详情)|writer(创建和编辑)
|
||||
--no-notification 不向被授权用户发送提醒 (默认发送)
|
||||
```
|
||||
|
||||
> **说明**:把我的日历共享给指定用户,授予对方相应权限。`--privilege` 可选值:`free_busy_reader`(查看忙闲)、`title_reader`(查看标题)、`reader`(查看详情)、`writer`(创建和编辑)。
|
||||
|
||||
### 取消我的日历对某人的共享
|
||||
```
|
||||
Usage:
|
||||
dws calendar acl delete [flags]
|
||||
Example:
|
||||
dws calendar acl delete --acl-id ACL_ID
|
||||
Flags:
|
||||
--acl-id string 已授予权限的 ID (必填,可通过 acl list 查询)
|
||||
```
|
||||
|
||||
> **说明**:取消我的日历对某人的共享(撤回已授予的访问权限)。aclId 可通过 `acl list` 获取。
|
||||
|
||||
### 查询用户 / 会议室闲忙状态
|
||||
```
|
||||
Usage:
|
||||
@@ -398,9 +541,11 @@ Example:
|
||||
dws calendar event respond --id <EVENT_ID> --status accepted
|
||||
dws calendar event respond --id <EVENT_ID> --status declined
|
||||
dws calendar event respond --id <EVENT_ID> --status tentative
|
||||
dws calendar event respond --id <EVENT_ID> --status accepted --calendar-id <SHARED_CALENDAR_ID> # 响应其他日历本下的日程
|
||||
Flags:
|
||||
--id string 日程 ID (必填)
|
||||
--status string 响应状态: needsAction(未操作)|accepted(接受)|declined(拒绝)|tentative(暂定) (必填)
|
||||
--id string 日程 ID (必填)
|
||||
--status string 响应状态: needsAction(未操作)|accepted(接受)|declined(拒绝)|tentative(暂定) (必填)
|
||||
--calendar-id string 日历 ID (可选,默认 primary 主日历;指定其他日历本时填写,可通过 `book list` 获取。注意:订阅日历下的日程无参会人,因此不可响应)
|
||||
```
|
||||
|
||||
> **说明**:作为日程参会人,设置自己的响应状态(接受、拒绝、暂定)。`--status` 可选值:`needsAction`(未操作,默认值)、`accepted`(接受)、`declined`(拒绝)、`tentative`(暂定)。
|
||||
@@ -410,7 +555,7 @@ Flags:
|
||||
用户说"日程/会议/约会/日历":
|
||||
- 查看 → `event list`
|
||||
- 详情 → `event get`
|
||||
- 创建/约/给自己留时间块/个人日程 → `event create`(带参会人时加 `--attendees`,循环日程加 `--recurrence-*`)
|
||||
- 创建/约/给自己留时间块/个人日程 → `event create`(带参会人时加 `--attendees`,循环日程加 `--recurrence-*`,自定义提醒加 `--remind-minutes`)
|
||||
- 修改/改时间/改描述 → `event update`(支持修改标题、时间、描述、时区、循环规则)
|
||||
- 取消/删除 → `event delete`
|
||||
- 推荐时间/什么时候有空/协调时间 → `event suggest`
|
||||
@@ -422,13 +567,14 @@ Flags:
|
||||
- 移除 → `attendee delete --attendees <USER_ID>`
|
||||
|
||||
用户说"会议室/订会议室":
|
||||
- 哪个空闲 → `room search`
|
||||
- 按名找会议室(如「永澄亭」「永澄亭会议室」「约西湖厅」)→ 先在模型层精简名称(剔除「会议室」等通用后缀),再用 `room search --room-name <核心专名>`
|
||||
- 哪个空闲 → `room search`(默认查当前时间起 1 小时内可用会议室)
|
||||
- 按名找会议室(如「永澄亭」「永澄亭会议室」「约西湖厅」,未提时间段)→ 先在模型层精简名称(剔除「会议室」等通用后缀),再用 `room search --room-name <核心专名>`(按名称搜索,不检查可用性)
|
||||
- 按名找可用会议室(如「永澄亭下午 2 点有空吗」)→ `room search --room-name <核心专名> --start <开始时间> --end <结束时间>`(按名称+时间段搜索可用会议室)
|
||||
- 预订
|
||||
- 给已有日程订会议室 → `room add --event <已有EVENT_ID> --rooms <ROOM_ID>`
|
||||
- 创建新日程并订会议室 → `event create --rooms`(仅当日程尚不存在时)
|
||||
- 取消预定 → `room delete`
|
||||
- 分组 → `room list-groups`,取 groupId 后 `room search --group-id`(可再叠加 `--room-name` 在分组内过滤)
|
||||
- 分组 → `room list-groups`,取 groupId 后 `room search --group-id`(需配合 `--start`/`--end` 按时间段搜索;可再叠加 `--room-name` 在分组内过滤)
|
||||
|
||||
用户说"有空吗/忙不忙/闲忙":
|
||||
- 查询用户闲忙 → `busy search --users <USER_ID>`
|
||||
@@ -438,8 +584,18 @@ Flags:
|
||||
用户说"日程附件/给会议加文件/上传日程材料":
|
||||
- 添加 → `attachment add`(先用钉盘上传得 fileId,再 `attachment add --files <fileId>:<name>`)
|
||||
|
||||
用户说"我有几个日历/查所有日历/共享日历本":
|
||||
- 列表 → `book list`(主日历 id 固定为 `primary`)
|
||||
用户说"我有几个日历/查所有日历/别人共享给我的日历/他人共享给我的日历本":
|
||||
- 列表 → `book list`(返回用户拥有和订阅的所有日历本,包括他人共享给自己的;主日历 id 固定为 `primary`)
|
||||
- 查指定日历本 → `book get --id <CALENDAR_ID>`
|
||||
- 按名称搜索日历本 → `book search --query "关键词"`
|
||||
- 修改日历本名称/描述 → `book update --id <CALENDAR_ID> --summary "新名"`
|
||||
|
||||
用户说"我的日历共享给了谁/谁能看我日历/日历权限/取消共享/把日历分享给xxx":
|
||||
- 查看我共享出去的情况(即谁有权访问我的日历) → `acl list`
|
||||
- 把我的日历共享给他人 → `acl add --user <USER_ID> --privilege reader`
|
||||
- 取消我的日历对某人的共享 → `acl delete --acl-id <ACL_ID>`(aclId 来自 `acl list`)
|
||||
|
||||
> **易混淆辨析**:`book list` 查的是"我能看哪些日历本"(包含别人共享**给我**的);`acl list` 查的是"我的日历共享**给了谁**"(我的主日历的访问控制列表)。两者方向相反,不可混用。
|
||||
|
||||
用户说"查下xxx的日程安排":
|
||||
- 查询是否有共享关系 -> `book list`
|
||||
@@ -506,12 +662,16 @@ 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` | event get/update/delete/respond 的 --id |
|
||||
| `event list` | `events[].eventId`, `nextCursor` | event get/update/delete/respond 的 --id;下一页 --cursor |
|
||||
| `event suggest` | 推荐的时间段 | event create 的 --start/--end |
|
||||
| `event respond` | 响应结果 | — |
|
||||
| `room search` | `rooms[].roomId` | room add 的 --rooms 或 event create 的 --rooms |
|
||||
| `room list-groups` | `groups[].groupId` | room search 的 --group-id |
|
||||
| `book list` | `calendarId`(如 `primary`) | event list/get 的 --calendar-id |
|
||||
| `book list` | `id`(如 `primary`) | event list/get 的 --calendar-id, book get/update 的 --id |
|
||||
| `book get` | 日历详细信息 | — |
|
||||
| `book search` | 匹配的日历列表 | book get/update 的 --id |
|
||||
| `acl list` | `aclId` | acl delete 的 --acl-id |
|
||||
| `acl add` | 新增的权限记录 | — |
|
||||
| 钉盘上传 | 文件 `fileId` | attachment add 的 --files `<fileId>:<name>` |
|
||||
|
||||
## 注意事项
|
||||
@@ -527,20 +687,22 @@ dws calendar event list --start "2026-03-10T14:00:00+08:00" --end "2026-03-10T15
|
||||
- `room list-groups` 支持 `--limit` / `--page` 分页(schema 类型为字符串)
|
||||
- **`event create --rooms` / `room add --rooms` 的唯一合法来源**:最近一次(同一会话、同一时段窗口)`room search` 返回体中的 `roomId`;禁止把用户自然语言会议室名当 `roomId` 传入(否则会 `roomId invalid` 等错误)
|
||||
- **搜房无结果**:在符合早停/用户限定范围内,`room search`(含按分组逐组查)全部返回空或无空闲 → 应**直接向用户报错/说明失败**并结束订房;**禁止**假设 roomId、禁止无合法 `roomId` 时调用 `room add` / `event create --rooms` 试探、禁止用 `event get` 等绕路推断 roomId
|
||||
- **评测 / 自动化断言**:凡涉及 `room add` / `event create --rooms` 的流程,`--rooms` 只能填上游 `room search`(或等价接口)返回 JSON 中的 **`rooms[].roomId`**;不得以会议室展示名、楼层文案或用户口语当作 `roomId`
|
||||
- **自动化校验**:凡涉及 `room add` / `event create --rooms` 的流程,`--rooms` 只能填上游 `room search`(或等价接口)返回 JSON 中的 **`rooms[].roomId`**;不得以会议室展示名、楼层文案或用户口语当作 `roomId`
|
||||
- **附件**:`attachment add` 仅负责挂载,**不上传**文件;fileId 必须先通过钉盘流程取得;`--files` 多附件用 `<fileId>:<name>` 元素逗号分隔
|
||||
- **日历本**:`book list` 返回的 `calendarId` 字段才是合法日历 id(无 `id` 字段);如无明确说明,`event list` / `event get` 都不要带 `--calendar-id`,让接口默认走 primary 主日历
|
||||
- **已弃用入参**:`--max-results`(event list)在新 MCP schema 中被移除;CLI 仍接受但**不会**透传到 MCP;模型生成命令时**禁止**继续使用
|
||||
- **日历本**:`book list` 返回的 `id` 才是合法 `calendarId`;如无明确说明,`event list` / `event get` 都不要带 `--calendar-id`,让接口默认走 primary 主日历
|
||||
- **分页查询**:`event list` / `list-mine` 支持 `--limit`(控制每页条数,默认/最大 100)和 `--cursor`(翻页游标);**首次查询无需传 `--cursor`**,仅当返回体中包含 `nextCursor` 时,将其作为 `--cursor` 传入可获取下一页
|
||||
- **日程提醒**:`event create` 支持 `--remind-minutes` 设置开始前提醒,逗号分隔多个分钟数(如 `--remind-minutes 5,10,15`),不传则默认15分钟提醒
|
||||
- **会议室分页**:`room search` 支持 `--limit`(每页条数,默认100,最大100)和 `--page`(分页起始位置,默认0),与 `room list-groups` 分页风格一致
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
| 脚本 | 场景 | 用法 |
|
||||
|------|------|------|
|
||||
| [calendar_today_agenda.py](../../scripts/calendar_today_agenda.py) | 查看今天/明天/本周日程安排 | `python calendar_today_agenda.py today` |
|
||||
| [calendar_schedule_meeting.py](../../scripts/calendar_schedule_meeting.py) | 一键创建日程+添加参会人+预定会议室;搜房失败时输出明确原因并返回非零退出码 | `python calendar_schedule_meeting.py --title "复盘会" --start "2026-03-15T14:00" --end "2026-03-15T15:00" --users userId1 --book-room` |
|
||||
| [calendar_free_slot_finder.py](../../scripts/calendar_free_slot_finder.py) | 查询多人共同空闲时段 | `python calendar_free_slot_finder.py --users userId1,userId2 --date 2026-03-15` |
|
||||
| [calendar_today_agenda.py](../scripts/calendar_today_agenda.py) | 查看今天/明天/本周日程安排 | `python calendar_today_agenda.py today` |
|
||||
| [calendar_schedule_meeting.py](../scripts/calendar_schedule_meeting.py) | 一键创建日程+添加参会人+预定会议室;搜房失败时输出明确原因并返回非零退出码 | `python calendar_schedule_meeting.py --title "复盘会" --start "2026-03-15T14:00" --end "2026-03-15T15:00" --users userId1 --book-room` |
|
||||
| [calendar_free_slot_finder.py](../scripts/calendar_free_slot_finder.py) | 查询多人共同空闲时段 | `python calendar_free_slot_finder.py --users userId1,userId2 --date 2026-03-15` |
|
||||
|
||||
## 相关产品
|
||||
|
||||
- conference 视频会议 — 当前 CLI 不支持发起/预约/邀请入会/会中控制;请在钉钉客户端操作
|
||||
- [contact](./contact.md) — 搜索同事 userId,用于 attendee add --attendees
|
||||
- conference(视频会议预约) — 仅视频会议预约(返回入会链接),不含参会人/会议室管理
|
||||
- [contact](../../dingtalk-contact/references/contact.md) — 搜索同事 userId,用于 attendee add --attendees
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# calendar 局部意图消歧
|
||||
|
||||
本文件从单 Skill `intent-guide.md` 拆分而来,仅保留与本产品相关的跨产品消歧规则。
|
||||
|
||||
| 用户说... | 真实意图 | 应该用 | 不要用 | 理由 |
|
||||
|---|---|---|---|---|
|
||||
| "给自己留一个明天下午的时间块/建个个人日程" | 创建个人日程 | `calendar event create` | `todo` | 个人 schedule 仍属于日历事件,不是待办 |
|
||||
| "帮我预约一个视频会议" / "开个会" / "发起会议" | 视频会议 | 钉钉客户端(当前 CLI 不支持) | `calendar` | 不要把实时视频会议诉求改写成日历日程 |
|
||||
| "帮我建一个明天下午的日程" | 日历日程 | `calendar` | — | 日历日程管理(可含参与者/会议室);视频会议当前 CLI 不支持 |
|
||||
| "明早 9 点提醒我提交周报" | 创建个人待办,但需先声明 reminder 边界 | `todo` | `calendar` | todo 当前只支持 dueTime 截止时间,不支持独立精确 reminder |
|
||||
@@ -0,0 +1,27 @@
|
||||
# calendar Lite Recipe
|
||||
|
||||
本文件从单 Skill `lite-recipes.md` 拆分而来,仅保留与本产品相关的轻量流程。
|
||||
|
||||
## #3 会议日程
|
||||
|
||||
### list-today-meetings
|
||||
|
||||
**优先**:`python scripts/calendar_today_agenda.py [today|tomorrow|week]`
|
||||
备选:`dws calendar event list --start "<今日起始ISO>" --end "<今日结束ISO>"`(须加 `--format json`)
|
||||
|
||||
### check-users-busy
|
||||
|
||||
查询多人在某时段内的闲忙(**busy**,不是用 `event list` 扫日程):
|
||||
|
||||
1. 解析用户:对每个姓名执行 `aisearch person --keyword "<姓名>" --dimension name` → `userId`;多人将 `userId` 用英文逗号拼接(无空格或按 [calendar.md](./calendar.md) `busy search` 要求)。
|
||||
2. 确认时段:用户须给出或可收敛为明确的 `--start` / `--end`(ISO-8601);若未给出,**先追问**起止时间,禁止用任意默认全天窗口代替用户意图。
|
||||
3. 执行:`dws calendar busy search --users <userId1,userId2,...> --start "<ISO>" --end "<ISO>" --format json`
|
||||
|
||||
详见 [calendar.md](./calendar.md) 中「查询用户闲忙状态」。
|
||||
|
||||
### 视频会议能力边界
|
||||
|
||||
当前 CLI 不提供视频会议发起、预约、入会邀请或会中控制。用户只说“开个会/发起会议”且未给日程时段时,直接说明请在钉钉客户端操作,不要构造视频会议命令。
|
||||
|
||||
- 有具体时间(如“明天 3 点开会”)或明确预约日程 → 走 [03-meeting.md](./03-meeting.md) 的 `schedule-meeting`
|
||||
- 只有实时视频会议诉求 → 说明当前 CLI 不支持,请在钉钉客户端发起
|
||||
@@ -51,51 +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
|
||||
# 兼容 {result: [...]} 包裹结构
|
||||
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):
|
||||
# 新结构: {userId, scheduleItems: [{start, end, status}]}
|
||||
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
|
||||
# FREE 时段不算忙
|
||||
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 (
|
||||
@@ -193,16 +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:
|
||||
print(f"错误:忙闲查询失败: "
|
||||
f"{data.get('errorMsg') or data.get('errorCode') or data}",
|
||||
file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
busy = parse_busy_intervals(data)
|
||||
free = find_free_slots(day_start, day_end, busy, args.duration)
|
||||
|
||||
@@ -212,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:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: dingtalk-chat
|
||||
description: 钉钉群聊与消息。Use when 用户提到 发消息/单聊/群聊/建群/拉人进群/改群名/搜索群/群成员管理/@消息/收藏消息/撤回消息/机器人群发/Webhook通知/发图片或文件到群。Distinct from dingtalk-ding(紧急DING消息/短信/电话)、dingtalk-mail(邮件)、dingtalk-edu-group(班级群)。命令前缀:dws chat。
|
||||
description: 钉钉群聊与消息。Use when 用户提到 发消息/单聊/群聊/建群/拉人进群/改群名/搜索群/群成员管理/@消息/收藏消息/撤回消息/机器人群发/Webhook通知/发图片或文件到群/标记未读/清除红点/置顶消息/全部群列表。不做紧急 DING/短信/电话(走 dingtalk-ding)、邮件(走 dingtalk-mail)、班级群(走 dingtalk-edu-group)。命令前缀:dws chat。
|
||||
cli_version: ">=0.2.14"
|
||||
metadata:
|
||||
category: product
|
||||
@@ -14,21 +14,22 @@ metadata:
|
||||
|
||||
> 🧪 **EXPERIMENTAL · 试验版 / Preview** — multi 模式当前未达 stable 标准。全部 dingtalk-* skill 已通过 dispatch verifier,但接口、命名、跨 skill 引用后续可能调整;生产 / 共享环境请优先使用 mono 模式(`dws skill setup --mode mono`)。问题请提 issue 反馈。
|
||||
|
||||
> **PREREQUISITE:** Read the `dws-shared` skill first for auth, global flags, product routing, URL preflight, error codes, and safety rules. The `dws` binary must be on PATH.
|
||||
## 前置条件 — 执行操作前必读
|
||||
|
||||
> **`use_skill(dws-shared)`** — 认证、全局参数(`--format json` / `--yes`)、错误码、URL 模板、跨产品消歧、安全规则与 capability 边界。**执行任何 `dws` 命令前先读;** 单产品的清晰命令可直接用本 skill。
|
||||
|
||||
<!-- SAFETY_PREAMBLE_INJECT -->
|
||||
|
||||
> ⚠️ **命令可用性以当前 dws 二进制为准**。服务发现已下线,本文档随内置 skill 发布;如果 `dws <cmd> --help` 不存在,说明当前版本未暴露该命令。若命令存在但调用失败,请按错误中的 endpoint 或 tool 提示确认静态端点目录和后端工具注册。实际调用前可用 `dws <cmd> --help` 或 `--dry-run` 验证。
|
||||
> 渐进式参考:[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-emoji-list.md](references/chat-emoji-list.md);剧本:[01-messaging.md](references/01-messaging.md)。
|
||||
> 旧路径兼容入口:[chat.md](references/chat.md)。
|
||||
|
||||
## 意图表
|
||||
|
||||
| 用户说 | 命令 |
|
||||
|--------|------|
|
||||
| "发消息给张三" | `dws chat message send --open-dingtalk-id <id> --title "<标题>" --text "<内容>"` |
|
||||
| "发到XX群" | `dws chat search --query "<群名>"` → `dws chat message send --group <openConversationId> --title "<标题>" --text "<内容>"` |
|
||||
| "发消息给张三" | `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 message list-mentions` |
|
||||
@@ -39,8 +40,69 @@ metadata:
|
||||
| "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 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` |
|
||||
|
||||
> **注**:`chat message send` 的 `--title` 可选(不传时用正文首行作标题);`send-by-bot` / `send-by-webhook` 的 `--title` 必填。
|
||||
## 标准 SOP(必遵流程)
|
||||
|
||||
> 命中以下意图**必须**按对应 SOP 顺序执行;**禁止**跳步、替换命令、编造 ID。每条命令必须带 `--format json`,执行后必须按"解析"步取真实字段(`openDingTalkId` / `openConversationId` / `clientMsgId`)。
|
||||
|
||||
### SOP-1 发消息(send-message)
|
||||
|
||||
**触发**:发消息/单聊/通知某人/发到群里。
|
||||
|
||||
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` 必须如实报错,不要谎报已发。
|
||||
|
||||
**禁止**:把人名/群名直接当 ID 传入、跳过 `aisearch person`/`chat search` 解析、跳过 `--format json`、未发送成功就答复"已发送"。
|
||||
|
||||
### SOP-2 建群(create-group)
|
||||
|
||||
**触发**:建群/拉人进群/新建讨论组。
|
||||
|
||||
1. **解析成员(必须)**:对每个成员 `dws aisearch person --keyword "<姓名>" --dimension name --format json` 取 `userId`,多人英文逗号拼接。
|
||||
2. **执行(必须)**:`dws chat group create --name "<群名>" --users <userId1,userId2,...> --format json`;外部群加 `--type EXTERNAL`,话题圈加 `--thread`。
|
||||
3. **验证(必须)**:从返回取 `openConversationId`,可用 `dws chat search --query "<群名>" --format json` 复核。
|
||||
|
||||
**禁止**:跳过成员 userId 解析直接传姓名、编造 `openConversationId`。
|
||||
|
||||
### SOP-3 Webhook 推送(send-by-webhook)
|
||||
|
||||
**触发**:用机器人群 webhook 推一条消息。
|
||||
|
||||
1. **执行(必须)**:`dws chat message send-by-webhook --token <webhookToken> --title "<标题>" --text "<内容>" --format json`。
|
||||
2. **@ 人(必须)**:需要 @ 时,`--text` 中**必须**先包含对应 `@userId` / `@手机号` / `@10`,再配合 `--at-users` / `--at-mobiles` / `--at-all`;否则 @ 不生效。
|
||||
|
||||
**禁止**:只传 `--at-users` 而 `--text` 里不含 `@<标识>`。
|
||||
|
||||
### SOP-4 共同群查询(search-common-group)
|
||||
|
||||
**触发**:"我和 XX 的共同群"。
|
||||
|
||||
1. **取昵称(必须)**:先 `dws contact user get-self --format json` 取自己昵称;对方昵称从历史/上下文取,拿不到必须先问用户。
|
||||
2. **执行(必须)**:`dws chat search-common --nicks "<昵称1>,<昵称2>" --limit 20 --cursor 0 --format json`;`hasMore=true` 时**必须**用 `nextCursor` 翻页,不要停在第一页。
|
||||
|
||||
**禁止**:跳过昵称解析、忽略 `hasMore` 不翻页。
|
||||
|
||||
### SOP-5 红点 / 未读管理(manage-red-point)
|
||||
|
||||
**触发**:标记未读/清除红点/全部已读。
|
||||
|
||||
1. **执行(必须)**:标记某会话未读 `dws chat mark-unread --conversation-id <openConversationId> --format json`;清除某会话红点 `dws chat clear-red-point --conversation-id <openConversationId> --format json`;全部已读 `dws chat clear-all-red-point --format json`。
|
||||
2. **取会话 ID(必须)**:`openConversationId` 拿不准时先 `dws chat group list-all --format json` 或 `dws chat search --query "<群名>" --format json`,**禁止**编造。
|
||||
|
||||
**禁止**:未确认会话就批量"全部已读"(破坏性,必须先与用户确认)。
|
||||
|
||||
### SOP-6 特别关注消息(focus-messages)
|
||||
|
||||
**触发**:"特别关注的人最近发了什么/聊了什么"。
|
||||
|
||||
1. **执行(必须)**:`dws chat message list-focused --limit 50 --format json`,直接基于返回答复。
|
||||
2. **边界(必须)**:只有用户终点是"我关注了谁"这种**人员列表**时,才切 `dingtalk-contact` 关系查询。
|
||||
|
||||
**禁止**:用普通 `message list` 冒充 focused、把人员列表需求硬塞进 chat。
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
@@ -48,3 +110,6 @@ metadata:
|
||||
- 要发图片/文件 → 先 `dt_media_upload` 上传 → `python scripts/extract_media_id.py "<URL>"` 提取 mediaId → 再用 `--media-id`
|
||||
- 紧急升级(应用内/短信/电话)→ 切到 `dingtalk-ding`
|
||||
- 发邮件 → 切到 `dingtalk-mail`
|
||||
## 局部意图与 Recipe
|
||||
|
||||
- [局部意图消歧](references/intent-guide.md);[Lite Recipe](references/lite-recipes.md)。
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
# 消息沟通
|
||||
|
||||
> **安全红线**:收件人搜索返回多条/零条结果、或名称不完全匹配时,**必须列出候选项让用户确认**,严禁自动选择第一条。即使支持机器人消息撤回 `chat message recall-by-bot`,对方可能已读,发错代价高。禁止自行发送"测试消息"验证通道。
|
||||
|
||||
> lite recipe 见 `dws-shared/references/best_practices/_common/lite-recipes.md`。
|
||||
> lite recipe(`send-message`、`create-group`、`send-by-webhook`、`search-common-group`、`focus-messages`)见 [lite-recipes.md](./lite-recipes.md)。
|
||||
|
||||
| Recipe | 行动指南(固定路线) |
|
||||
|--------|-------------------|
|
||||
| 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. `--direction older` 拉给定时间**之前**的消息(`newer` 拉之后)<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-direct --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/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` |
|
||||
| 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` |
|
||||
| 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>`(备选) |
|
||||
| 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/references/contact.md` 意图判断)<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>` |
|
||||
| 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` |
|
||||
|
||||
@@ -0,0 +1,417 @@
|
||||
# 机器人、分组与会话状态命令
|
||||
|
||||
### 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 查询获得
|
||||
```
|
||||
@@ -0,0 +1,10 @@
|
||||
# 聊天命令路由
|
||||
|
||||
> `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) |
|
||||
@@ -0,0 +1,139 @@
|
||||
# 复合工作流
|
||||
|
||||
## 复合工作流
|
||||
|
||||
### 机器人发消息后撤回(完整流程)
|
||||
|
||||
`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 --group <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 --keyword "姓名" --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 流式状态 (必填)
|
||||
```
|
||||
@@ -0,0 +1,27 @@
|
||||
# 上下文传递表
|
||||
|
||||
## 上下文传递表
|
||||
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `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 |
|
||||
@@ -0,0 +1,206 @@
|
||||
# 会话查询与媒体命令
|
||||
|
||||
### 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
|
||||
|
||||
注意:
|
||||
- 取消置顶后消息仍保留在会话中,只是不再被标记为置顶状态
|
||||
```
|
||||
@@ -0,0 +1,484 @@
|
||||
# 群组、群身份与群搜索命令
|
||||
|
||||
## 命令总览
|
||||
|
||||
### 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
|
||||
# 指定他人为群主
|
||||
dws chat group create --name "项目群" --users userId1,userId2 --owner <openDingTalkId>
|
||||
Flags:
|
||||
--name string 群名称 (必填)
|
||||
--users string 成员 userId 或 openDingTalkId(可混传),用户本身会自动加入无需包含,逗号分隔,不超过20个 (必填)
|
||||
--type string 群类型: INTERNAL(内部群,默认)/EXTERNAL(外部群)/NORMAL(普通群)
|
||||
--thread 开启话题模式,将创建话题圈
|
||||
--owner string 群主 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 --keyword "姓名" --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 --keyword "姓名" --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)
|
||||
```
|
||||
@@ -0,0 +1,13 @@
|
||||
# 聊天能力索引
|
||||
|
||||
| 主题 | 详见 |
|
||||
|---|---|
|
||||
| 群创建/设置/成员/角色/搜索 | [`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) |
|
||||
@@ -0,0 +1,163 @@
|
||||
# 意图判断
|
||||
|
||||
## 意图判断
|
||||
|
||||
用户说"我特别关注的人最近发了什么消息/关注的人最近聊了啥/星标联系人最近的动态" → `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 --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 为当前用户视角下的目标用户唯一标识,不可跨用户共享。
|
||||
@@ -0,0 +1,625 @@
|
||||
# 消息与会话文件命令
|
||||
|
||||
### 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>
|
||||
# 发送位置消息(需先通过 dt_media_upload 上传地图缩略图获取 mediaId)
|
||||
dws chat message send --group <openconversation_id> --msg-type location --latitude <纬度> --longitude <经度> --location-name <地址名称> --map-thumbnail-url "@mediaId"
|
||||
# 分享联系人名片
|
||||
dws chat message send --group <openconversation_id> --msg-type profile --contact-id <openDingTalkId>
|
||||
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/location/profile(推荐统一用 `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 内不会重复发送(可选)
|
||||
--latitude string 纬度,如 30.271321(msgType=location 时必填)
|
||||
--longitude string 经度,如 120.007878(msgType=location 时必填)
|
||||
--location-name string 地址名称,如 阿里集团-钉钉(msgType=location 时必填)
|
||||
--map-thumbnail-url string 地图缩略图 mediaId,格式 @mediaId(msgType=location 时必填,需先通过 dt_media_upload 上传图片获取)
|
||||
--contact-id string 要分享的联系人 openDingTalkId(msgType=profile 时必填)
|
||||
|
||||
注意:
|
||||
- --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 内不会重复投递消息(可选,群聊和单聊均支持)
|
||||
- **发送位置消息**:`--msg-type location --latitude <纬度> --longitude <经度> --location-name <地址名称> --map-thumbnail-url @mediaId`;地图缩略图需先通过 `dt_media_upload` 上传图片获取 mediaId
|
||||
- **分享联系人名片**:`--msg-type profile --contact-id <openDingTalkId>`;将指定联系人的名片分享到群聊或单聊
|
||||
```
|
||||
|
||||
#### 查询消息发送状态 — 查询以当前用户身份发送的消息的发送状态
|
||||
|
||||
查询以当前用户身份发送的消息的发送状态。需要传入发送消息时返回的 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"
|
||||
dws chat message search-advanced --message-type file --search-conv-type group_chat --query "附件"
|
||||
dws chat message search-advanced --only-robot-messages --query "通知"
|
||||
# 查询群 ID: dws chat search --query "群名"
|
||||
# 查询单聊会话 ID: dws chat conversation-info --user <userId>
|
||||
# 查询人员: dws contact user search --keyword "姓名" --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 列表,逗号分隔(可选,群聊或单聊均可,不传则搜索所有会话)
|
||||
--message-type string 消息类型筛选(可选,支持 file/image/video/audio/link)
|
||||
--search-conv-type string 会话类型筛选(可选,single_chat=单聊, group_chat=群聊)
|
||||
--start string 开始时间,ISO-8601 格式(可选)
|
||||
--end string 结束时间,ISO-8601 格式(可选)
|
||||
--cursor string 分页游标(默认 "0")
|
||||
--limit int 每页返回数量(默认 100)
|
||||
--only-robot-messages 仅搜索机器人消息(可选,默认 false)
|
||||
--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` 命令获取
|
||||
```
|
||||
@@ -0,0 +1,67 @@
|
||||
# 注意事项
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **发消息前参数审查(必须执行)**:
|
||||
- 发消息(`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 --group <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 --keyword "姓名" --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 列表,逗号分隔)
|
||||
@@ -0,0 +1,32 @@
|
||||
# 相关产品
|
||||
|
||||
## 相关产品
|
||||
|
||||
- [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(美式英语)
|
||||
- 返回结果为翻译后的纯文本内容
|
||||
@@ -0,0 +1,9 @@
|
||||
# 自动化脚本
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
| 脚本 | 场景 | 用法 |
|
||||
|------|------|------|
|
||||
| [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`) |
|
||||
@@ -0,0 +1,35 @@
|
||||
# 核心工作流
|
||||
|
||||
## 核心工作流
|
||||
|
||||
```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
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,85 @@
|
||||
# chat 局部意图消歧
|
||||
|
||||
本文件从单 Skill `intent-guide.md` 拆分而来,仅保留与本产品相关的跨产品消歧规则。
|
||||
|
||||
| 用户说... | 真实意图 | 应该用 | 不要用 | 理由 |
|
||||
|---|---|---|---|---|
|
||||
| "通知群里的人都来开会" | 个人身份群发 | `chat message send` | `chat message send-by-bot` | 以个人身份向群发消息 |
|
||||
| "让机器人每天推送日报" | 机器人定时推送 | `chat message send-by-bot` | `chat message send` | 需要机器人身份定期发送 |
|
||||
| "CPU 超过 90% 自动告警" | Webhook 告警 | `chat message send-by-webhook` | `chat message send-by-bot` | 系统告警场景,需自定义 Webhook |
|
||||
| "拉取一下上周项目群的聊天记录" | 拉取会话消息 | `chat message list` | — | 拉取指定群聊的消息列表 |
|
||||
| "看看张三发给我的消息" | 按发送者查询消息 | `chat message list-by-sender` | `chat message list --user` | 用户未明确说"单聊"时优先用 list-by-sender(跨单聊/群聊) |
|
||||
| "拉取和张三的单聊记录" | 拉取单聊消息 | `chat message list --user` | `chat message list-by-sender` | 用户明确说"单聊"时用 list --user |
|
||||
| "谁@了我/查看提及我的消息" | 查询@我的消息 | `chat message list-mentions` | `chat message list-all` | 都是跨会话时间范围查询,但 list-mentions 只返回@我的消息 |
|
||||
| "查看我今天的所有消息" | 全量会话消息 | `chat message list-all` | `chat message list` | 用户未指定具体会话时用 list-all(跨所有会话),指定了具体群或人时用 list |
|
||||
| "搜一下消息里的changefree链接" | 消息搜索 | `chat message search-advanced`(首选) | `chat search` | 推荐首选 search-advanced,它是 search 的严格超集(keyword 可选、支持多群、可叠加发送者/at 维度) |
|
||||
| "按发送者搜索/指定多个群搜索/多维度搜消息" | 多维度搜索消息 | `chat message search-advanced`(首选) | `chat message search` | 推荐首选,支持关键词、发送者、@我、多个会话等维度组合 |
|
||||
| "消息发没发成功/查询消息发送状态" | 查询消息发送状态 | `chat message query-send-status` | — | 需要 send 返回的 openTaskId |
|
||||
| "撤回我发的消息/撤回消息/群主撤回消息/管理员撤回他人消息" | 撤回消息 | `chat message recall` | `chat message recall-by-bot` | recall 撤回个人消息或群主/管理员撤回他人消息,recall-by-bot 撤回机器人消息 |
|
||||
| "未读消息会话/未读会话列表/我的未读会话" | 未读会话列表 | `chat message list-unread-conversations` | `chat message read-status` | list-unread-conversations 查哪些会话有未读;read-status 查具体消息的已读状态 |
|
||||
| "谁看了这条消息/消息已读未读/查读状态" | 查询消息已读状态 | `chat message read-status` | `chat message list-unread-conversations` | read-status 查具体消息的已读人员;list-unread-conversations 查未读会话列表 |
|
||||
| "查看消息的表情回复/拉取消息回复/消息的文字回复" | 批量拉取消息表情回复和文字回复 | `chat message list-emotion-replies` | — | 根据消息 ID 批量查询表情回复和文字回复 |
|
||||
| "我和风雷的共同群/我们都在哪些群" | 搜索共同群 | `chat search-common` | `chat search` | search-common 按人员搜共同群,chat search 按群名搜索 |
|
||||
| "查看会话分组/自定义分组" | 获取会话分组 | `chat category list` | — | 获取用户自定义的会话分组列表 |
|
||||
| "某个分组下有哪些会话" | 分组下会话列表 | `chat category list-conversations` | — | 需先通过 category list 获取分组 ID |
|
||||
| "创建会话分组/新建分组" | 创建自定义分组 | `chat category create` | — | 需指定 --title 分组名称 |
|
||||
| "删除会话分组/移除分组" | 删除自定义分组 | `chat category delete` | — | 需指定 --category-id |
|
||||
| "重命名分组/修改分组名称" | 更新分组名称 | `chat category rename` | — | 需指定 --category-id 和 --title |
|
||||
| "把会话加到分组/将群移入分组" | 会话加入分组 | `chat category add-conv` | `chat category remove-conv` | add-conv 加入;remove-conv 移出 |
|
||||
| "把会话从分组移出/从分组中删除" | 会话移出分组 | `chat category remove-conv` | `chat category add-conv` | remove-conv 移出;add-conv 加入 |
|
||||
| "创建智能分组/新建智能会话分组/按关键词分组" | 创建智能会话分组 | `chat category create-smart` | `chat category create` | create-smart 按关键词/成员智能匹配;create 手动创建普通分组 |
|
||||
| "分享群链接/把群分享给某人/群链接发到某群" | 分享群聊链接到会话 | `chat group share-invite` | `chat group invite-url` | share-invite 直接分享到目标会话/用户;invite-url 只获取链接不发送 |
|
||||
| "根据群号查群信息/群号转openConversationId" | 群号查群聊信息 | `chat group get-by-group-id` | `chat search` | 已知数字群号时直接查;用户发消息只给了群号时,先用此工具将群号转为 openConversationId |
|
||||
| "我创建的群/我管理的群/我是群主的群/我当管理员的群" | 拉取我创建/管理的群 | `chat group list-my-groups` | `chat search` | list-my-groups 按角色(群主/管理员)过滤当前用户的群;chat search 按关键词搜全部群 |
|
||||
| "引用消息回复/回复那条消息" | 引用回复消息 | `chat message reply` | `chat message send` | reply 引用指定消息回复;send 普通发消息不引用 |
|
||||
| "转发消息/把消息转到另一个群" | 转发单条消息 | `chat message forward` | `chat message send` | forward 转发已有消息到目标会话;send 是发新消息 |
|
||||
| "置顶会话/取消置顶" | 设置/取消会话置顶 | `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 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-nick` | `chat group rename` | update-nick 改自己的群昵称;rename 改群名称 |
|
||||
| "群备注/给群加备注/修改群备注" | 设置群备注 | `chat group update-alias` | `chat group rename` | update-alias 设置仅自己可见的备注;rename 改群名称全员可见 |
|
||||
| "隐藏会话/隐藏群聊/隐藏对话" | 隐藏会话 | `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 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 分页查询全部成员列表 |
|
||||
| "标记未读/设为未读/会话标未读" | 标记会话为未读 | `chat mark-unread` | `chat clear-red-point` | mark-unread 标记为未读;clear-red-point 清除红点(相反操作) |
|
||||
| "清除红点/已读/取消未读" | 清除会话红点 | `chat clear-red-point` | `chat mark-unread` | clear-red-point 清除单个会话红点;mark-unread 标记未读(相反操作) |
|
||||
| "全部已读/一键清除所有未读/红点清零" | 清除所有会话红点 | `chat clear-all-red-point` | `chat clear-red-point` | clear-all-red-point 清除所有会话红点;clear-red-point 只清单个会话 |
|
||||
| "所有会话/全部会话列表/我的会话" | 分页获取全部会话 | `chat list-all-conversations` | `chat list-top-conversations` | list-all-conversations 返回所有会话;list-top-conversations 仅返回置顶会话 |
|
||||
| "清空聊天记录/删除会话消息/清空消息" | 清空会话聊天记录 | `chat clear-messages` | `chat clear-red-point` | clear-messages 清空聊天记录;clear-red-point 仅清除未读红点 |
|
||||
| "标记已读/消息已读/读了" | 标记消息已读 | `chat mark-read` | `chat clear-red-point` | mark-read 标记指定消息及之前的消息为已读;clear-red-point 仅清除红点不标记消息 |
|
||||
| "我加入的所有群/拉取全部群列表/我的群" | 分页拉取所有群 | `chat group list-all` | `chat group list-my-groups` | list-all 返回用户加入的所有群;list-my-groups 仅返回用户作为群主/管理员的群 |
|
||||
| "入群申请记录/谁申请入群/群申请列表/查看入群审批" | 拉取入群验证记录 | `chat group list-join-validations` | `chat group list-all` | list-join-validations 拉取入群验证/审批记录;list-all 拉取群列表 |
|
||||
| "通过入群申请/拒绝入群/审批入群/同意加群" | 审批入群验证 | `chat group audit-join-validation` | `chat group list-join-validations` | audit-join-validation 执行审批操作;list-join-validations 仅查询记录 |
|
||||
| "发群公告/在群里发公告/群公告置顶" | 发布群公告 | `chat group notice create` | `blackboard create` | notice create 是群维度公告(发到指定群聊);blackboard 是企业公告(面向全员,不可撤回) |
|
||||
| "改群公告/修改群公告/更新群公告" | 修改群公告 | `chat group notice edit` | `chat group notice create` | edit 整体替换已有公告内容(需 dataId);create 发布新公告 |
|
||||
| "查群公告/看群公告/群公告列表/群里有什么公告" | 查看群公告列表 | `chat group notice list` | `blackboard list` | notice list 查指定群的公告;blackboard list 查企业公告 |
|
||||
| "群公告详情/公告已读人数/谁读了公告" | 查看群公告详情 | `chat group notice get` | `chat group notice list` | get 返回单条公告详情(含已读人数、点赞/评论数);list 分页拉公告列表 |
|
||||
| "搜索机器人/找机器人/查机器人/帮我找XXX机器人" | 搜索全部可用机器人 | `chat bot find` | `chat bot search` | find 返回全部可用机器人(含他人/官方),额外返回 openDingTalkId(可用于给机器人发单聊消息);search 仅返回我创建的 |
|
||||
| "给机器人发单聊/给机器人发消息/跟机器人聊天" | 给机器人发单聊消息 | `chat bot find` → `chat message send --open-dingtalk-id` | `chat bot search` | 必须先用 find 拿 openDingTalkId(search 没有此字段),再用 send --open-dingtalk-id 发单聊 |
|
||||
| "我创建的机器人/我的机器人/我自己的机器人/查看我的机器人" | 搜索我创建的机器人 | `chat bot search` | `chat bot find` | search 仅返回当前用户自己创建的机器人(返回 robotCode + robotName,无 openDingTalkId);find 返回全部可用机器人 |
|
||||
| "合并转发/批量转发/合并转发多条消息" | 合并转发多条消息 | `chat message combine-forward` | `chat message forward` | combine-forward 合并多条为一条转发;forward 转发单条消息 |
|
||||
| "转发话题/转发话题消息/话题转发到另一个群" | 转发话题消息 | `chat message forward-topic` | `chat message forward` | forward-topic 专用于转发话题消息(需要话题ID);forward 转发普通单条消息 |
|
||||
| "发卡片消息/推送流式卡片" | 创建并推送流式卡片 | `chat message send-card` | `chat message send` | send-card 发流式卡片;send 发普通文本/Markdown 消息 |
|
||||
| "更新卡片/流式更新卡片" | 流式更新卡片内容 | `chat message update-card` | `chat message send-card` | update-card 更新已有卡片;send-card 创建新卡片 |
|
||||
| "钉住消息/Pin消息/置顶消息到会话" | 钉住消息 | `chat message set-pin-msg` | `chat set-top` | set-pin-msg 钉住单条消息(Pin);set-top 置顶整个会话 |
|
||||
| "取消钉住/Unpin消息" | 取消钉住消息 | `chat message unset-pin-msg` | `chat message set-pin-msg` | unset-pin-msg 取消钉住;set-pin-msg 设置钉住 |
|
||||
| "查看钉住的消息/Pin列表/钉住消息列表" | 拉取钉住消息列表 | `chat message list-pin-msg` | `chat message list` | list-pin-msg 只返回被钉住的消息;list 拉取全部消息 |
|
||||
| "置顶某条消息/把这条消息置顶" | 置顶消息 | `chat message set-top-msg` | `chat set-top` | set-top-msg 置顶会话内某条消息;set-top 置顶整个会话在列表中 |
|
||||
| "取消置顶消息/取消消息置顶" | 取消置顶消息 | `chat message unset-top-msg` | `chat message set-top-msg` | unset-top-msg 取消置顶;set-top-msg 设置置顶 |
|
||||
| "DING消息/查DING/DING历史" | 查询 DING 消息列表 | `ding message list` | `chat message list` | ding 是独立顶层命令;ding message list 查 DING 消息;chat message list 查普通聊天消息 |
|
||||
| "DING接收状态/谁收到了DING" | DING 接收状态 | `ding message receiver-status` | `chat message read-status` | ding 是独立顶层命令;receiver-status 查 DING 接收;chat message read-status 查普通消息已读 |
|
||||
| "发DING/DING通知" | 发送 DING 消息 | `ding message send` | `chat message send` | DING 是钉钉的强提醒(应用内/短信/电话),独立顶层命令;普通群消息用 chat |
|
||||
| "撤回DING" | 撤回 DING 消息 | `ding message recall` | `chat message recall` | DING 撤回独立命令;chat recall 是撤回普通聊天消息 |
|
||||
| "搜一下智能化方案/最近 OKR 相关邮件/最近发版相关消息" | 搜企业知识内容 | `aisearch enterprise` | `doc search` / `mail search` / `chat message search` | 跨文档、消息、日程、听记、邮件等企业内容语义检索走 enterprise;具体 `queries/types/time-range` 抽槽见 `aisearch.md` |
|
||||
| "我发给某人的消息/邮件/文档/今天我干了什么" | 搜行为记录 | `aisearch behavior` | `chat` / `mail` / `doc` / `report` | 关注“谁对什么做过什么”,走 behavior;具体 `behavior-type/direction/chat-scope` 抽槽见 `aisearch.md` |
|
||||
| "把这段文字翻译成英文/translate this" | 通用文本翻译 | `chat text translate` | `doc` / `aisearch` | 纯文本翻译,不是文档编辑或语义搜索 |
|
||||
| "帮我把这个文档翻译成日文" | 文档内容翻译 | 先 `doc get` 再 `chat text translate` | `chat text translate` 直接传文件 | translate 仅支持纯文本,需先提取文档内容 |
|
||||
@@ -0,0 +1,7 @@
|
||||
# chat Lite Recipe
|
||||
|
||||
本文件从单 Skill `lite-recipes.md` 拆分而来,仅保留与本产品相关的轻量流程。
|
||||
|
||||
## #1 消息沟通
|
||||
|
||||
所有消息沟通相关的命令详情、参数说明、意图路由和复合工作流,请查阅 [chat.md](./chat-commands.md)。
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user