返回 Skills 目錄
wecomteam/wecom-cli已通過檢查

SKILL DETAIL

wecomcli-todo

wecomteam/wecom-cli/wecomcli-todo

This skill manages WeCom to-dos, covering creation, deletion or exit, completion, query and filtering, as well as modifying title, description, participant list, and deadline. Before use, complete the common pre-checks and consult the relevant reference documents according to the interface routing table to ensure correct parameters. The deadline is represented as a deadline object, supporting date or specific time, and reminder timing can be set. Queries support filtering by creation time, deadline, completion status, and keywords, with literal matching.

安裝量 · 175查看來源

Installation

npx skills add https://github.com/wecomteam/wecom-cli --skill wecomcli-todo

技能檔案

SKILL.md

最近同步 · 2026年8月27日

references/todo-create.md
# 创建待办 — `wecom-cli todo create`

以当前用户为发起人创建待办,可指定分派人并设置截止时间。

## 意图前置判断(在调用接口之前必须做)

"创建"类请求进入本技能前,先判断它是否真的属于待办:

- **消息里显式出现"待办"二字**(如"创建一条待办"、"添加待办"、"帮我记一个待办"、"把这事记到待办里")→ 在本技能内执行创建。
- **全局提醒路由已选"待办",或明确是"定时提醒的待办 / 待办提醒 / 创建待办并提醒"** → 在本技能内执行创建;若原话给出具体提醒时刻,则该时刻 = `deadline.type=datetime`,并传 `remind_at_deadline=true`;只给日期则可填 `deadline.type=date`,不追问且不传 `remind_at_deadline=true`;未给提醒/截止时间则不传 `deadline` / `remind_at_deadline`。
- **泛提醒但未明确要求创建企业微信待办** → 不要在本技能内擅自创建待办;先由上层路由确定承载方式。

## 命令

```bash
wecom-cli todo create --json '<JSON 参数>'
```

## 参数

外层为对象,待办放在 `items` 数组中:

| 字段 | 类型 | 必填 | 语义 |
|---|---|---|---|
| `items` | array | 是 | 待办数组,每项结构见下,支持批量,单次最多 20 条;超出需分批 |

`items[]` 元素结构:

| 字段 | 类型 | 必填 | 默认值 | 语义 |
|---|---|---|---|---|
| `title` | string | 是 | — | 短标题,长度 >= 1 |
| `description` | string | 否 | — | 详细描述(可选的展开说明,不是标题)|
| `follower_ids` | string[] | 否 | `[]` | 分派人 userid 列表(前缀 `wo`),最多 50 人;用户给姓名时先通过 `wecomcli-contact` 技能查 `userid` |
| `deadline` | object | 否 | — | 截止时间。结构见 SKILL.md `deadline` 对象规范 |
| `remind_at_deadline` | boolean | 否 | `false` | 提醒时机,须与 `deadline` 同传:`true`=截止时刻提醒(仅 `datetime`);`false`/不传=按后台默认提前时间提醒(**非关闭提醒**)。脱离 `deadline` 单独传无效 |

`deadline` 整体可选;若提供则其内部 `type` 与 `value` 必填。

## 从用户消息推断字段

调用本命令前,按以下规则从用户原话里提取参数。除非真的提不出,**不要**用追问让用户重新说一遍——他刚才已经把事情讲清楚了,再问一次是劣体验。

### 推断 `title`(必填)

绝大多数情况下能从用户消息里提炼出标题。优先采用"动宾"结构,尽量保持用户的原始表达。当标题过长,非常细节的背景细节才放进 `description`。

**只有当用户消息里完全没有任何任务内容时**(例如只说"帮我记个待办"、"加一条待办",完全没讲事情本身),才向用户追问"要记什么事?"。哪怕只有一个动作或一个对象,也要先自己提炼,不要追问。

### 推断 `description`(可选,多数情况不传)

`description` 是**标题之外的补充说明**,只在用户给了标题装不下的额外细节(背景、要求、上下文)时才填写。

- **禁止把 `description` 写成与 `title` 相同或仅是 title 的复述**。如果提炼完标题后没有任何额外信息,就**不传** `description`——一条只有标题的待办是完全正常的,硬塞一个和标题一样的 description 属于冗余噪声。
- 用户用"内容是 / 就是 / 记一下 XX"等方式描述事情时,这通常就是在给**标题**,不是在额外补充描述:先把它提炼成 `title`;只有当它明显比标题多出独立信息时,多出来的部分才放进 `description`。
- 从当前会话上下文或待办查询结果批量创建待办时,不要只沿用概括标题;若上下文里已有明确的下一步动作、对接人、时间节点、链接或单号,应压缩写入 `description`。不确定的信息不要编造,也不要为了补全而反复追问。

### 推断 `follower_ids`

用户提到要分派给自己时(如"分派给我"、"我和 vincentwei 一起"),要把当前用户自己的 `userid` 也放进 `follower_ids`,因为后台不会自动把创建者算作分派人。但是如果是给我自己创建,没有其他参与人,就不用把我自己也放进去。

当用户表述中暗示某人与待办有参与或关联关系(如"与某人相关的待办""关于某人""和某人一起跟进"),应将关联人加入 `follower_ids`。

### 推断 `deadline` 与待办提醒

- `remind_at_deadline` 必须与 `deadline` 一起传,只用来选提醒时机("提前"还是"截止时");脱离 `deadline` 单独传无效。入参层面没有"关闭提醒"这一档,但是否真正提醒由后台判断,以返回的 `extra_info` 为准。
- 用户只说**截止时间/到期时间**,或给出任务发生日期时,填写 `deadline`,不要传 `remind_at_deadline`(即按后台默认提前时间提醒)。
- 用户明确要**提醒/到点提醒/截止时提醒/待办提醒**且给出具体时刻时,提醒时刻即 `deadline.type=datetime`,同时传 `remind_at_deadline=true`;只给日期时不传 `remind_at_deadline=true`。
- 用户说"xx 时间截止的待办,并提前 yy 提醒"时,`deadline` 永远填 **xx 截止时间**,不要填提前后的提醒时间。当前入参不能直接设置"提前 yy";创建后用返回的 `extra_info` 判断系统提醒时间是否刚好满足 yy。
- 未提任何与任务完成节点相关的时间时才不传 `deadline` / `remind_at_deadline`;不要追问,走默认参数。

`type` / `value` 的完整格式与示例见 SKILL.md `deadline` 对象规范。

## 示例入参

创建带截止时提醒的待办:

```json
{
  "items": [
    {
      "title": "准备周会材料",
      "description": "本周三上午周会需要的销售数据 PPT",
      "follower_ids": ["wo_xxx"],
      "deadline": {
        "type": "datetime",
        "value": "2026-05-13 09:00:00"
      },
      "remind_at_deadline": true
    }
  ]
}
```

## 返回

外层为对象,结果在 `items` 数组中,与入参 `items` 一一对应:

| 字段 | 类型 | 语义 |
|---|---|---|
| `items` | array | 创建结果数组 |

`items[]` 元素结构:

| 字段 | 类型 | 语义 |
|---|---|---|
| `success` | boolean | 此待办是否创建成功 |
| `todo_id` | string | 待办 ID(前缀 `td`),仅成功时返回 |
| `title` | string | 待办标题 |
| `followers` | array | 分派人列表,每项含 `userid` 和 `user_name`(格式 `英文名(中文名)`)|
| `extra_info` | string | 提醒时刻只读信息,可能不提醒 |
| `errmsg` | string | 单条创建失败原因,仅 `success=false` 时存在 |

## 给用户的反馈

### 回显创建结果

创建成功后,回复里要把这条待办回显给用户便于核对,**标题、参与人、截止时间**这三项都要体现(不存在的项缺省即可,不要硬写"无"):

- **标题**:取返回的 `title`。
- **参与人**:取返回 `followers[].user_name`,多人用 `、` 拼接;无分派人或仅创建者本人时缺省。只展示人名,不要出现 `userid`。
- **截止时间**:取**本次入参**的 `deadline.value`——返回体不回传 `deadline`,必须用刚提交的值;未设置截止时间时缺省。

批量创建时逐条回显。示例:

> 已创建待办「准备周会材料」,参与人:张三、李四,截止时间:2026-05-13 09:00:00。

### 提醒说明

创建成功且本次传了 `remind_at_deadline=true` 或用户提到提醒诉求时,**必须**在回显之后附上提醒说明(注意 `remind_at_deadline` 只对 datetime 生效):

- 用户要求"提前 X 提醒"时,核对 `extra_info` 是否为用户要求的提前提醒时间(即截止时间提前 X 后的时刻);匹配则说明已满足,不匹配或无 `extra_info` 则按固定话术说明:`目前不支持直接创建您需要的提醒时间,已为您设置截止时间为 XX,请到企业微信待办功能中手动修改提醒时间。`(XX 填本次 `deadline.value`)。
- 用户要求"截止时/到点提醒"时,只有 `deadline.type=datetime` 才应传 `remind_at_deadline=true`;若 `extra_info` 不等于 `deadline.value` 或缺失,仍需引导到企业微信待办功能中修改提醒时间。
- 返回里有 `extra_info`(且非"提前 X 提醒"场景)→ 引用 `extra_info` 里的时刻告诉用户届时会自动提醒。
- 返回里没有 `extra_info`(且非"提前 X 提醒"场景)→ 说明返回未确认提醒时间,引导用户到企业微信待办应用中检查/修改提醒时间。
- 不要另建定时任务来模拟待办提醒,避免重复提醒。

仅带 `deadline` 但未要求提醒的普通待办,无需额外提醒说明。
references/todo-delete.md
# 删除/退出待办 — `wecom-cli todo delete`

删除或退出指定待办,语义取决于当前用户是否为创建人:

- **当前用户是创建人**:删除整条待办,其他参与人也不再继续看到/处理这条待办。
- **当前用户不是创建人**:允许调用同一个 `delete` 接口,表现为**当前用户退出待办 / 从自己的待办中移除**,不是删除整条待办,也不会影响其他参与人。

## 命令

```bash
wecom-cli todo delete --json '<JSON 参数>'
```

## 参数

外层为对象,待办放在 `items` 数组中:

| 字段 | 类型 | 必填 | 语义 |
|---|---|---|---|
| `items` | array | 是 | 待办数组,每项结构见下,单次最多 20 条;超出需分批 |

`items[]` 元素结构:

| 字段 | 类型 | 必填 | 默认值 | 语义 |
|---|---|---|---|---|
| `todo_id` | string | 是 | — | 待办 ID,前缀 `td` |

示例入参:

```json
{
  "items": [
    { "todo_id": "td_xxx" },
    { "todo_id": "td_yyy" }
  ]
}
```

## 返回

外层为对象,结果在 `items` 数组中,与入参 `items` 一一对应:

| 字段 | 类型 | 语义 |
|---|---|---|
| `items` | array | 删除/退出结果数组 |

`items[]` 元素结构:

| 字段 | 类型 | 语义 |
|---|---|---|
| `success` | boolean | 是否删除成功 |
| `todo_id` | string | 待办 ID |
| `title` | string | 待办标题 |
| `errmsg` | string | 失败原因,仅 `success=false` 时存在 |

## 使用规则

- 用户说某待办"已完成"时,默认是完成操作,不等于删除;只有用户明确说删除,才调用本接口删除。
- **非创建人也可以删除,语义是退出待办**:不要因为 `creator.userid` 不是当前用户就拒绝,也不要回复"创建人之外无权删除"之类的话术。调用 `delete` 前仍应核对创建人,但目的只是理解本次操作语义和做幂等判断:
  - `creator.userid` 等于当前用户 → 调用 `wecom-cli todo delete`,语义是删除整条待办。
  - `creator.userid` 不等于当前用户 → 调用 `wecom-cli todo delete`,语义是当前用户退出该待办 / 从自己的待办中移除。
- **如果上下文没有对应待办 ID**:**必须**先阅读 `references/todo-list.md`,学习如何获取待办列表,在待办列表中找到需要删除/退出的待办(列表返回里带 `creator` 和 `user_status`,用于判断最终话术和幂等)。查询时需要同时查找未完成和已完成的待办。
- **禁止将 `todo_id` 展示给用户**。
references/todo-finish.md
# 完成待办 — `wecom-cli todo finish`

将**当前用户**在该待办中的部分标记为"已完成"。如果当前用户同时是创建人,后台会返回 `ask_finish_all` 提示,可选择把所有参与人一并标记完成。

## 命令

```bash
wecom-cli todo finish --json '<JSON 参数>'
```

## 参数

外层为对象,待办放在 `items` 数组中:

| 字段 | 类型 | 必填 | 语义 |
|---|---|---|---|
| `items` | array | 是 | 待办数组,每项结构见下,单次最多 20 条;超出需分批 |

`items[]` 元素结构:

| 字段 | 类型 | 必填 | 默认值 | 语义 |
|---|---|---|---|---|
| `todo_id` | string | 是 | — | 待办 ID |
| `finished_all` | boolean | 否 | `false` | 创建人可设为 `true` 全部完成该待办。默认 `false` 仅完成自己的部分 |

示例入参:

```json
{
  "items": [
    {
      "todo_id": "td_xxx",
      "finished_all": false
    }
  ]
}
```

## 返回

外层为对象,结果在 `items` 数组中,与入参 `items` 一一对应:

| 字段 | 类型 | 语义 |
|---|---|---|
| `items` | array | 完成结果数组 |

`items[]` 元素结构:

| 字段 | 类型 | 语义 |
|---|---|---|
| `success` | boolean | 是否完成成功 |
| `todo_id` | string | 待办 ID |
| `title` | string | 待办标题 |
| `ask_finish_all` | string | 当后台检测到用户既是创建人又是参与人时返回,提示模型询问用户是否标记为"全部完成" |
| `errmsg` | string | 失败原因,仅 `success=false` 时存在 |

## 使用规则

- **如果上下文没有对应待办 ID**:**必须**先阅读 `references/todo-list.md`,学习如何获取待办列表,在待办列表中找到需要完成的待办;此时应同时查 `finished` 和 `proceed`。如果已有 `todo_id` 但需要确认最新状态,使用 `wecom-cli todo get`。
- **完成操作要幂等**:定位待办时如果发现该待办整体 `status=finished` 或当前用户 `user_status=finished`,说明已完成,直接告知用户"这条待办已完成",不要再调用 `finish`。只有用户本次或本会话前文明确要求"完成后删除/清掉/自动删除"时,才继续按删除流程处理。
- 调用前先按用户语义决定 `finished_all`:
  - 用户明确表达"仅我完成自己的部分"("我这边搞完了"、"我自己的部分先完成"、"先把我那块标了")→ **显式**传 `finished_all: false`。显式 false 才能让后端跳过 `ask_finish_all` 兜底,避免再次询问完成范围。
  - 用户明确表达"全部完成"("完成了"、"这条结掉"、"都搞完了"),或本会话此前对同一个 `todo_id` 已经调过一次 `finished_all=false`、用户现在又一次说要完成它 → 传 `finished_all: true`。
  - 表达不明确(只说"完成 XX 待办"、"把那条待办完成了",没有"仅我"或"全部"的语气)→ 不传 `finished_all`,让后端按下方 `ask_finish_all` 流程返回是否需要确认。
- **`ask_finish_all` 处理流程**:如果返回中出现 `ask_finish_all` 字段,说明当前用户是创建人,第一次调用已把当前用户自己的部分标记完成;**必须**用简洁自然语言向用户确认是否把其他参与人也一并标记完成,并在文字中列出「仅我完成」「已完全完成」两个选项。提问中应包含待办标题和 `followers` 中的参与人中文名(用顿号"、"拼接),例如:
  ```
  待办「<待办标题>」中您的部分已完成。参与人:<参与人中文名>。请选择完成范围:仅我完成,还是已完全完成?
  ```
  - 用户选 **「仅我完成」** → 不再调用接口(第一次已经完成了自己的部分),告知用户已标记完成。
  - 用户选 **「已完全完成」** → 用同一个 `todo_id` 再次调用 `wecom-cli todo finish`,并传 `finished_all: true`。
- 结果 `items` 与入参 `items` 一一对应
- 禁止将 `todo_id`(待办 ID)展示给用户。
references/todo-get.md
# 批量获取待办详情 — `wecom-cli todo get`

批量查询 1-20 个待办的完整信息。

## 命令

```bash
wecom-cli todo get --json '<JSON 参数>'
```

## 参数

外层为对象,待查待办放在 `items` 数组中:

| 字段 | 类型 | 必填 | 语义 |
|---|---|---|---|
| `items` | array | 是 | 待查待办数组,每项结构见下,单次最多 20 个;超出需分批 |

`items[]` 元素结构:

| 字段 | 类型 | 必填 | 默认值 | 语义 |
|---|---|---|---|---|
| `todo_id` | string | 是 | — | 待办 ID(前缀 `td`) |

### 示例入参

```json
{
  "items": [
    { "todo_id": "td_xxx" },
    { "todo_id": "td_yyy" }
  ]
}
```

## 返回

外层为对象,结果在 `items` 数组中,与入参 `items` 一一对应:

| 字段 | 类型 | 语义 |
|---|---|---|
| `items` | array | 待办详情数组 |

`items[]` 元素结构:

| 字段 | 类型 | 语义 |
|---|---|---|
| `success` | boolean | 此条查询是否成功 |
| `todo_id` | string | 待办 ID(前缀 `td`) |
| `title` | string | 待办标题 |
| `description` | string | 详细描述 |
| `status` | string | 待办整体状态:`proceed` / `finished` |
| `user_status` | string | 当前用户在该待办的状态:`accept` / `reject` / `finished` / `removed` / `notshow` |
| `creator` | object | 创建人,含 `userid`(前缀 `wo`) / `user_name`(格式 `英文名(中文名)`) |
| `followers` | array | 分派人列表,每项含 `userid`(前缀 `wo`) / `user_name` / `user_status` / `update_time` |
| `deadline` | object | 截止时间;结构见 SKILL.md `deadline` 对象规范。无截止时间时不返回或为 `null` |
| `extra_info` | string | 提醒时刻只读信息,可能不提醒 |
| `source` | string | 待办来源:`single_chat`(单聊)/ `group_chat`(群聊)/ `doc`(文档)/ `ai_summary`(智能总结)/ `meeting_summary`(会议纪要)/ `face_chat`(「面聊」功能)/ `fused_doc`(融合文档)/ `smart_sheet`(智能表格)/ `smart_doc`(智能文档)/ `JSAPI`(JSAPI) |
| `create_time` | string | 创建时间,格式 `YYYY-MM-DD HH:mm:ss` |
| `update_time` | string | 更新时间,格式 `YYYY-MM-DD HH:mm:ss` |
| `errmsg` | string | 失败原因,仅 `success=false` 时存在 |

## 使用规则

- **单次上限 20**:超出需分批请求
- **已有 `todo_id` 时确认状态用本接口**:需要核对某条待办的最新 `status` / `user_status` 时,使用 `wecom-cli todo get`。
references/todo-list.md
# 按时间范围查询待办 — `wecom-cli todo list`

按创建时间或截止时间范围拉取当前用户创建和参与的待办列表,支持按状态过滤。返回含 `title` / `description` / `followers` / `deadline` 等完整字段,多数场景无需再走本技能的「批量查询待办详情」。

本接口用于直接查看待办列表、确认待办状态、查询特定待办,或在修改、完成、删除前定位目标待办。

## 命令

```bash
wecom-cli todo list --json '<JSON 参数>' [--page-count N]
```

`--page-count N` 自动翻页并最多拉取 N 页的内容(默认 1,即只拉首页)。不传则只拉首页。注意 `--page-count` 是命令行参数,写在 `--json '...'` 之外,不要塞进 JSON 体里。

## 参数

查询接口不进 `items` 壳,参数直接平铺:

| 字段 | 类型 | 必填 | 默认值 | 语义 |
|---|---|---|---|---|
| `create_begin_time` | string | 否 | — | 创建时间起始,格式 `YYYY-MM-DD HH:mm:ss` |
| `create_end_time` | string | 否 | — | 创建时间截止,格式 `YYYY-MM-DD HH:mm:ss` |
| `deadline_begin_time` | string | 否 | — | 截止时间起始,格式 `YYYY-MM-DD HH:mm:ss` |
| `deadline_end_time` | string | 否 | — | 截止时间截止,格式 `YYYY-MM-DD HH:mm:ss` |
| `status_filter` | string[] | 否 | — | 状态过滤,合法枚举值只有 `finished`(已完成)、`proceed`(进行中),可多选;不传时默认只返回 `proceed`(进行中)的待办 |
| `keywords` | string[] | 否 | — | 关键词过滤,对待办文本(标题/描述)做命中匹配。数组元素之间是 **OR**,单个元素内空格分隔的词是 **AND**。语义与构造方式详见下方「keywords 语义」 |
| `limit` | integer | 否 | 10 | 单次返回数量,不传为10,最大只能传20,如果需要大量查询,应该使用自动翻页 |
| `cursor` | string | 否 | — | 分页游标,首次请求不传 |

示例入参(按时间范围 + 状态过滤 + 关键词 + 可选的翻页参数):

```json
{
  "create_begin_time": "2026-05-01 00:00:00",
  "create_end_time": "2026-05-09 23:59:59",
  "status_filter": ["proceed"],
  "keywords": ["报销"],
  "limit": 20,
  "cursor": "<上次返回的 next_cursor>"
}
```

> 各顶层过滤条件之间是 **AND** 关系:一条待办需同时满足时间范围、状态、关键词表达式才会被返回。`keywords` 内部再按下方规则展开自己的 OR/AND 逻辑。

## keywords 语义

`keywords` 用两层结构表达"或"与"且":

- **数组多个元素之间 = OR**:命中任意一个元素即召回。
- **单个元素内空格分隔 = AND**:该元素里的每个词都命中,才算命中这个元素。

例:`["service ai", "claw"]` 等价于布尔表达式 `("service" AND "ai") OR "claw"`——"同时包含 service 和 ai"或"包含 claw"的待办都会被召回。

从用户表达构造 `keywords`:

| 用户说 | keywords | 含义 |
|---|---|---|
| "包含报销的待办" | `["报销"]` | 命中"报销" |
| "同时提到项目和评审的待办" | `["项目 评审"]` | 一个元素、空格分隔 = "项目" AND "评审" |
| "提到报销,或者同时提到项目和评审的待办" | `["项目 评审", "报销"]` | `("项目" AND "评审") OR "报销"` |

## 返回

| 字段 | 类型 | 语义 |
|---|---|---|
| `items` | array | 待办列表,每项结构见下 |
| `next_cursor` | string | 下一页游标,配合 `has_more=true` 使用 |
| `has_more` | boolean | 是否还有更多数据 |

`items[]` 元素结构:

| 字段 | 类型 | 语义 |
|---|---|---|
| `todo_id` | string | 待办 ID(前缀 `td`) |
| `title` | string | 待办标题 |
| `description` | string | 详细描述 |
| `status` | string | 待办整体状态:`finished` / `proceed` |
| `user_status` | string | 当前用户在该待办的状态:`accept` / `reject` / `finished` / `removed` / `notshow` |
| `creator` | object | 创建人,含 `userid`(前缀 `wo`) / `user_name`(格式 `英文名(中文名)`) |
| `followers` | array | 分派人列表,每项含 `userid`(前缀 `wo`) / `user_name` / `user_status` / `update_time` |
| `deadline` | object | 截止时间;结构见 SKILL.md `deadline` 对象规范。无截止时间时不返回或为 `null` |
| `extra_info` | string | 提醒时刻只读信息,可能不提醒 |
| `source` | string | 待办来源:`single_chat`(单聊)/ `group_chat`(群聊)/ `doc`(文档)/ `ai_summary`(智能总结)/ `meeting_summary`(会议纪要)/ `face_chat`(「面聊」功能)/ `fused_doc`(融合文档)/ `smart_sheet`(智能表格)/ `smart_doc`(智能文档)/ `JSAPI`(JSAPI) |
| `create_time` | string | 创建时间,格式 `YYYY-MM-DD HH:mm:ss` |
| `update_time` | string | 更新时间,格式 `YYYY-MM-DD HH:mm:ss` |

## 使用规则

- **用户按状态查询待办时,`status_filter` 必须显式传对应状态**:本接口不传 `status_filter` 时只会返回进行中(`proceed`)的待办。用户问"已完成的待办"要传 `["finished"]`,问"所有待办(含已完成)"要传 `["finished","proceed"]`。漏传会导致已完成的待办根本不在结果里,进而把"其实有"误判成"没有"。
- **禁止用 `status_filter` 查询已删除待办**:该字段只接受 `finished` / `proceed`,不得传 `deleted`。用户要求查询已删除待办时,应直接说明当前列表接口不支持按已删除状态查询。
- **时间范围默认归到创建时间**:用户给了"5 月 1 号到 5 月 9 号""上周""本月"这类时间范围、但没点明是"创建"还是"截止"时,默认填 `create_begin_time` / `create_end_time`。一段时间范围最自然的含义是"这段时间内记下/产生的待办"。只有用户明确带"截止 / 到期 / deadline / ddl / 这之前要做完"等字样时,才改用 `deadline_begin_time` / `deadline_end_time`。
- **统计、计数、"有哪些"类需求要基于全量数据**:这类需求必须翻完所有分页(`--page-count` 取足够大,直到某页 `has_more` 为 `false`)。若结果过大被转存到文件,要把整个文件读完整再统计——只读开头几页就下结论会严重少算。
- **如果用户意图是获得所有待办**:应使用 `--page-count N` 快速拉取所有分页,直到 `has_more=false`。
- **已含完整详情**:`followers` / `creator` 已是包含人名的对象,多数场景无需再走本技能的「批量查询待办详情」或使用 `wecomcli-contact` 反查。
- **修改和完成待办时**:`status_filter` 可一次传多个状态。修改通常查进行中即可;完成或确认是否已完成时,应传 `["finished","proceed"]`,避免把已完成误判为未找到或再执行后续操作。
- **删除/退出某个待办时**:`status_filter` 应该传入 `["finished", "proceed"]`,不然可能找不到。删除接口对创建人是删除整条待办,对非创建人是退出/从自己的待办中移除;列表返回的 `creator` / `user_status` 用于判断操作语义和避免重复操作,**不要因为当前用户不是创建人就拒绝删除请求**。
- **默认只返回 10 条**:如需查全部请显式传 `limit` 为更大值,并关注 `has_more` / `next_cursor` 分页;要一次性拉多页可加 `--page-count N`。
- **`keywords` 是对待办系统记录的字面命中过滤,不是语义检索**:它只匹配待办自身的标题/描述文本。

## 返回给用户的格式

> **适用范围**:仅当用户**直接询问待办列表**(如"我今天创建的待办")时才使用本格式。若 `list` 是被其他操作(修改 / 完成 / 删除待办时为定位 `todo_id`)内部调用,本格式不适用——按对应操作的流程返回,不要把列表展示给用户。

将 `items` **按状态分组**呈现,每个状态分组下用 Markdown 列表展开,每条待办占多行:

```markdown
## 进行中(N 条)

1. <title>
  - 创建人:<creator>
  - 参与人:<followers>
  - 截止时间:<deadline>

## 已完成(M 条)

1. <title>
  - 创建人:<creator>
  - 参与人:<followers>
  - 截止时间:<deadline>
```

字段映射:

- **分组标题**:按 `status` 中文化分组
  - `proceed` → `## 进行中(N 条)`
  - `finished` → `## 已完成(M 条)`
  - 某分组无数据则整个分组省略
- **标题**:`title`
- **创建人**:`creator.user_name`,如果创建人是用户自己,则缺省
- **参与人**:`followers[].user_name` 用 `、` 拼接;无参与人时缺省
- **截止时间**:`deadline.value`;无截止时间时缺省

> 排序:分组内按 `deadline.value` 升序(无截止时间的排在最后);同一组内截止时间相同时按 `update_time` 倒序。
references/todo-update.md
# 修改待办 — `wecom-cli todo update`

批量更新待办的标题、描述、分派人名单或截止时间。

## 命令

```bash
wecom-cli todo update --json '<JSON 参数>'
```

## 参数

外层为对象,待更新的待办放在 `items` 数组中(支持批量):

| 字段 | 类型 | 必填 | 语义 |
|---|---|---|---|
| `items` | array | 是 | 更新条目数组,每项结构见下,单次最多 20 条;超出需分批 |

`items[]` 元素结构(仅传需修改的字段,未传字段保持不变):

| 字段 | 类型 | 必填 | 默认值 | 语义 |
|---|---|---|---|---|
| `todo_id` | string | 是 | — | 待办 ID(前缀 `td`) |
| `title` | string | 否 | — | 新的短标题 |
| `description` | string | 否 | — | 新的详细描述 |
| `followers` | array | 否 | — | **全量替换**后的分派人列表,最多 50 人;用户给姓名时使用 `wecomcli-contact` 技能获取 `userid`(前缀 `wo`) |
| `deadline` | object | 否 | — | 新的截止时间;结构见 SKILL.md `deadline` 对象规范。**传空对象 `{}` 表示清空已设置的截止时间**;不传字段则保持原值 |
| `remind_at_deadline` | boolean | 否 | `false` | 提醒时机,须与 `deadline` 同传:`true`=截止时刻提醒(仅 `datetime`);`false`/不传=按后台默认提前时间提醒(**非关闭提醒**)。脱离 `deadline` 单独传无效 |

`followers` 对象结构:

| 子字段 | 类型 | 必填 | 语义 |
|---|---|---|---|
| `userid` | string | 是 | 分派人 `userid`,前缀 `wo` |

> 入参的 `followers` 子对象**只接收 `userid`**。`wecom-cli todo list` / `wecom-cli todo get` 返回的 `followers` 还含 `user_name` / `user_status` / `update_time`,转入更新入参时全部剥掉,只保留 `userid`。

> `followers` 是全量替换,不是增量添加。只新增或移除部分参与人时,先从 `todo list` / `todo get` 取得现有名单,在本地合并或删减,再把所有应保留的参与人重新传入。

> 用户说"把我也加进去"、"分派给我和某某"时,`followers` 里同样要带上当前用户自己的 `userid`。

### 修改截止时间与提醒

- `remind_at_deadline` 必须与 `deadline` 一起传,语义与 create 完全一致;**只传 `remind_at_deadline`、不带 `deadline` 不会生效**,不要这么做。
- 用户只改**截止时间/到期时间**时,填写新的 `deadline`,不要传 `remind_at_deadline`(即按后台默认提前时间提醒)。
- 用户要求把待办改成"某时间提醒 / 定时提醒 / 截止时提醒"且给出具体时刻时,将该时刻作为新的 `deadline.type=datetime`,并传 `remind_at_deadline=true`;只给日期时不传 `remind_at_deadline=true`。
- **`remind_at_deadline=false` 或不传 ≠ 关闭提醒**,而是按后台默认提前时间提醒。**update 入参没有关闭提醒的开关**(`remind_at_deadline` 只切换提醒时机;是否真正提醒由后台判断):用户要"取消提醒 / 关掉提醒 / 别提醒了"时,直接告知目前不支持关闭待办提醒;若用户坚持完全不提醒,唯一办法是连同截止时间一起清空(`deadline: {}`,会一并删掉截止时间),须先向用户确认再操作。
- 用户要求"某时间截止,并提前 X 提醒"时,`deadline` 永远填用户说的**截止时间**,不要填提前后的提醒时刻。当前入参不能直接设置"提前 X";更新后用返回的 `extra_info` 判断系统提醒时间是否刚好满足 X。

### 示例入参

更新标题、截止时间并设置截止时提醒:

```json
{
  "items": [
    {
      "todo_id": "td_xxx",
      "title": "调整后的周会材料",
      "deadline": {
        "type": "datetime",
        "value": "2026-05-13 09:00:00"
      },
      "remind_at_deadline": true
    }
  ]
}
```

清空截止时间、清空分派人:

```json
{
  "items": [
    {
      "todo_id": "td_xxx",
      "deadline": {},
      "followers": []
    }
  ]
}
```

## 返回

外层为对象,结果在 `items` 数组中,与入参 `items` 一一对应:

| 字段 | 类型 | 语义 |
|---|---|---|
| `items` | array | 更新结果数组 |

`items[]` 元素结构:

| 字段 | 类型 | 语义 |
|---|---|---|
| `success` | boolean | 是否更新成功 |
| `todo_id` | string | 待办 ID |
| `extra_info` | string | 提醒时刻只读信息,可能不提醒 |
| `errmsg` | string | 失败原因,仅 `success=false` 时存在 |

## 使用规则

- **如果上下文没有对应待办 ID**:**必须**先阅读 `references/todo-list.md`,在待办列表中找到需要修改的待办。
- **避免冗余更新**:如果用户只是把待办**已经记录过的内容又复述了一遍**(例如标题已经等于用户这次说的内容),这是确认而不是修改,**不要发起 `update`**,直接回复"这条已经记好了"即可。尤其**不要把 `description` 更新成与 `title` 相同的内容**——description 只用于承载标题之外的补充信息,没有新增信息就不要写。
- **补全信息先查上下文**:用户要求"写清楚点"、补充参与人/时间/链接/单号时,先从当前会话、待办详情和可用的聊天/记忆检索结果中找;能确定就更新,找不到或有歧义时再一次性向用户确认,避免直接让用户重发。
- **仅改部分字段**:未传的字段保持原值;若要清空 `followers`,传空数组 `[]`;若要清空 `deadline`,传空对象 `{}`。**没有关闭提醒的入参**:`remind_at_deadline=false`/不传只是改成默认提前提醒,不会关闭提醒(详见「修改截止时间与提醒」)
- **本次更新传了 `remind_at_deadline=true` 或用户提到提醒诉求** 且更新成功时,**必须**在最终回复中附上提醒说明(注意 `remind_at_deadline` 只对 datetime 生效):
  - 用户要求"提前 X 提醒"时,核对 `extra_info` 是否为用户要求的提前提醒时间(即截止时间提前 X 后的时刻);匹配则说明已满足,不匹配或无 `extra_info` 则按固定话术说明:`目前不支持直接创建您需要的提醒时间,已为您设置截止时间为 XX,请到企业微信待办功能中手动修改提醒时间。`(XX 填本次 `deadline.value`)。
  - 用户要求"截止时/到点提醒"时,只有 `deadline.type=datetime` 才应传 `remind_at_deadline=true`;若 `extra_info` 不等于 `deadline.value` 或缺失,仍需引导到企业微信待办功能中修改提醒时间。
  - 返回里有 `extra_info`(且非"提前 X 提醒"场景)→ 引用 `extra_info` 里的时刻告诉用户届时会自动提醒。
  - 返回里没有 `extra_info`(且非"提前 X 提醒"场景)→ 说明返回未确认提醒时间,引导用户到企业微信待办应用中检查/修改提醒时间。
  - 不要另建定时任务来模拟待办提醒,避免重复提醒。仅改 `deadline` 但未要求提醒时,无需额外提醒说明。
SKILL.md
---
name: wecomcli-todo
description: 管理企业微信待办,支持创建、删除或退出、完成、查询和筛选,以及修改标题、描述、参与人名单和截止时间。

metadata:
  requires:
    bins: ["wecom-cli"]
---

# 企业微信待办管理

> 执行任何 `wecom-cli` 命令前,必须先读取并完成 `wecomcli-shared` 技能的公共前置检查。

使用 `wecom-cli` 管理企业微信待办。

## 查询与定位

- 查询范围仅限企业微信待办系统中已经存在的记录。
- 可按创建时间、截止时间、完成状态和标题/描述关键词查询;关键词是字面匹配,不是语义搜索。
- 用户问"我有哪些待办""未完成待办有哪些"或"接下来有哪些待办"时,使用 `todo list` 查询待办系统中的记录。
- 删除、完成或更新时,若上下文没有 `todo_id`,先用 `todo list` 定位;已有 `todo_id` 且需要确认最新详情或状态时,使用 `todo get`。

## 接口路由表

**[重要事项]** 执行任何操作前,必须先定位「接口路由表」指向的参考文档并完整读取,再执行命令,避免出现参数错误。严禁凭路由表描述或自身记忆猜测拼参数。

| 用户意图 | 参考位置 |
|---|---|
| 创建待办(可选分派) | references/todo-create.md |
| 删除待办 / 退出待办 / 从我的待办中移除 | references/todo-delete.md |
| 完成当前用户自己的部分 / 将整条待办全部完成 | references/todo-finish.md |
| 已有 `todo_id` 时确认待办详情和最新状态 | references/todo-get.md |
| 查看待办列表;按创建时间、截止时间、完成状态或关键词筛选;为后续操作定位待办 | references/todo-list.md |
| 修改待办内容 / 分派人名单 / 截止时间(不含参与人状态) | references/todo-update.md |

## `deadline` 对象规范

待办的截止时间统一以 `deadline` 对象表达。涉及"设置截止时间"、"修改截止时间"、"清空截止时间"或读取待办的截止信息时,按本节规范处理。

### 结构

| 字段 | 类型 | 必填 | 语义 |
|---|---|---|---|
| `type` | string | 是 | 枚举:`date`(仅日期,如果用户没有提及具体时分秒,则一定选择`date`) / `datetime`(用户提及了具体时刻) |
| `value` | string | 是 | `type=date` 时格式 `YYYY-MM-DD`;`type=datetime` 时格式 `YYYY-MM-DD HH:mm:ss` |

### 在 deadline / remind_at_deadline 字段上的语义

- **设置或修改 `deadline`**:整体可选;若提供则其内部 `type` 与 `value` 必填。
- **清空已设置的截止时间**:将 `deadline` 字段更新为空对象 `{}`;不更新该字段则保持原值不变。
- **作为返回字段**:未设置截止时间的待办,`deadline` 字段不返回或为 `null`。
- **提醒时机(`remind_at_deadline`)**:`remind_at_deadline` 与 `deadline` 是一对,必须一起出现——脱离 `deadline` 单独传 `remind_at_deadline` 不会生效,不要这么传。`remind_at_deadline` 只决定提醒**时机**,入参层面**没有"关闭提醒"这一档**(是否真正提醒由后台判断,可能因不满足条件而不提醒,以返回的 `extra_info` 为准):
  - `remind_at_deadline=true`(仅 `deadline.type=datetime` 可传)→ 在**截止时刻**提醒。
  - `remind_at_deadline=false` 或不传 → 按**后台默认的提前时间**提醒(**不是关闭提醒**)。
  - `deadline.type=date` 或未传 `deadline` 时不要传 `true`。

### 从用户输入推断 `deadline`

日期/星期直接限定待办中的任务或事件时,也视为截止日期。例如"周三开会要带笔记本"应将周三写入 `deadline`。

1. **待办提醒时间 = 截止时间**:明确要"定时提醒的待办 / 到某时提醒的待办 / 待办提醒"且给出具体时刻时,用户预期提醒时间落为 `deadline.type=datetime`,并传 `remind_at_deadline=true`;只给日期或未给提醒/截止时间时不追问,不传 `remind_at_deadline=true`。
2. **普通截止时间**:只说截止/到期时间,或给出任务发生日期时,仅填写 `deadline`、不传 `remind_at_deadline`;此时按后台默认提前时间提醒。
3. **时间格式**:具体截止/提醒时刻 → `deadline.type=datetime`、`value="YYYY-MM-DD HH:mm:ss"`;只有截止日期 → `type=date`、`value="YYYY-MM-DD"`。
4. **未提截止/提醒或任务发生时间**:`deadline` 整体不传,`remind_at_deadline` 也不传,不追问。
5. **xx 时间截止,并提前 yy 提醒**:`deadline` 永远填用户说的 xx 截止时间,不要填提前后的提醒时间。当前入参不能直接设置"提前 yy";创建/更新后用返回的 `extra_info` 判断系统提醒时间是否刚好满足 yy,不满足或无 `extra_info` 时回复:`目前不支持直接创建您需要的提醒时间,已为您设置截止时间为 XX,请到企业微信待办功能中手动修改提醒时间。`(XX 填本次 `deadline.value`)


### 示例

```json
{ "type": "date",     "value": "2026-05-08" }
{ "type": "datetime", "value": "2026-05-08 09:00:00" }
```

### 特别注意
- 禁止将 `todo_id`(待办 ID)展示给用户。