@wecom/wecom-openclaw-plugin 2026.7.2 → 2026.8.17-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/README.md +33 -4
  2. package/dist/index.js +14 -21
  3. package/dist/src/cli/argv.d.ts +36 -0
  4. package/dist/src/cli/argv.js +155 -0
  5. package/dist/src/cli/const.d.ts +94 -0
  6. package/dist/src/cli/const.js +107 -0
  7. package/dist/src/cli/credentials.d.ts +54 -0
  8. package/dist/src/cli/credentials.js +342 -0
  9. package/dist/src/cli/index.d.ts +5 -0
  10. package/dist/src/cli/index.js +5 -0
  11. package/dist/src/cli/legacy-tool-warning.d.ts +12 -0
  12. package/dist/src/cli/legacy-tool-warning.js +20 -0
  13. package/dist/src/cli/locate.d.ts +32 -0
  14. package/dist/src/cli/locate.js +196 -0
  15. package/dist/src/cli/process-launcher.d.ts +1 -0
  16. package/dist/src/cli/process-launcher.js +1 -0
  17. package/dist/src/cli/process-output.d.ts +14 -0
  18. package/dist/src/cli/process-output.js +43 -0
  19. package/dist/src/cli/tool.d.ts +46 -0
  20. package/dist/src/cli/tool.js +363 -0
  21. package/dist/src/const.d.ts +0 -8
  22. package/dist/src/const.js +0 -14
  23. package/dist/src/monitor.js +1 -12
  24. package/dist/src/state-manager.d.ts +0 -19
  25. package/dist/src/state-manager.js +1 -34
  26. package/dist/src/utils.d.ts +27 -0
  27. package/openclaw.plugin.json +1 -1
  28. package/package.json +3 -3
  29. package/skills/wecom-send-media/SKILL.md +2 -0
  30. package/skills/wecom-send-template-card/SKILL.md +1 -1
  31. package/skills/wecomcli-calendar/SKILL.md +302 -0
  32. package/skills/wecomcli-calendar/references/calendar-agenda.md +228 -0
  33. package/skills/wecomcli-calendar/references/calendar-cancel.md +110 -0
  34. package/skills/wecomcli-calendar/references/calendar-create.md +240 -0
  35. package/skills/wecomcli-calendar/references/calendar-freebusy.md +209 -0
  36. package/skills/wecomcli-calendar/references/calendar-meeting-room.md +172 -0
  37. package/skills/wecomcli-calendar/references/calendar-search.md +208 -0
  38. package/skills/wecomcli-calendar/references/calendar-update.md +274 -0
  39. package/skills/wecomcli-contact/SKILL.md +59 -0
  40. package/skills/wecomcli-disk/SKILL.md +401 -0
  41. package/skills/wecomcli-doc/SKILL.md +140 -0
  42. package/skills/wecomcli-doc/references/doc-contents-append.md +22 -0
  43. package/skills/wecomcli-doc/references/doc-contents-overwrite.md +29 -0
  44. package/skills/wecomcli-doc/references/doc-create.md +161 -0
  45. package/skills/wecomcli-doc/scripts/build_docx.py +1375 -0
  46. package/skills/wecomcli-doc-manage/SKILL.md +135 -0
  47. package/skills/wecomcli-doc-manage/references/doc-members-update.md +26 -0
  48. package/skills/wecomcli-doc-manage/references/doc-names-update.md +22 -0
  49. package/skills/wecomcli-doc-manage/references/doc-rules-update.md +24 -0
  50. package/skills/wecomcli-email/SKILL.md +216 -0
  51. package/skills/wecomcli-email/references/forward-mail.md +131 -0
  52. package/skills/wecomcli-email/references/get-mail.md +168 -0
  53. package/skills/wecomcli-email/references/reply-mail.md +140 -0
  54. package/skills/wecomcli-email/references/search-mail.md +113 -0
  55. package/skills/wecomcli-email/references/security.md +53 -0
  56. package/skills/wecomcli-email/references/send-mail.md +186 -0
  57. package/skills/wecomcli-email/references/send-schedule.md +83 -0
  58. package/skills/wecomcli-media/SKILL.md +100 -0
  59. package/skills/wecomcli-meeting/SKILL.md +374 -0
  60. package/skills/wecomcli-meeting/references/meeting-cancel.md +115 -0
  61. package/skills/wecomcli-meeting/references/meeting-create.md +169 -0
  62. package/skills/wecomcli-meeting/references/meeting-list.md +228 -0
  63. package/skills/wecomcli-meeting/references/meeting-original-get.md +100 -0
  64. package/skills/wecomcli-meeting/references/meeting-search.md +175 -0
  65. package/skills/wecomcli-meeting/references/meeting-update.md +219 -0
  66. package/skills/wecomcli-message/SKILL.md +213 -0
  67. package/skills/wecomcli-preflight/SKILL.md +147 -0
  68. package/skills/wecomcli-sheet/SKILL.md +177 -0
  69. package/skills/wecomcli-sheet/references/sheet-contents-update.md +49 -0
  70. package/skills/wecomcli-sheet/references/sheet-ranges-get.md +47 -0
  71. package/skills/wecomcli-sheet/references/sheet-rows-append.md +47 -0
  72. package/skills/wecomcli-sheet/references/sheet-subsheets-add.md +28 -0
  73. package/skills/wecomcli-sheet/references/sheet-subsheets-delete.md +22 -0
  74. package/skills/wecomcli-smartpage/SKILL.md +172 -0
  75. package/skills/wecomcli-smartpage/references/data-driven-pages.md +50 -0
  76. package/skills/wecomcli-smartpage/references/formula/arraylist.md +369 -0
  77. package/skills/wecomcli-smartpage/references/formula/datetime.md +283 -0
  78. package/skills/wecomcli-smartpage/references/formula/logic.md +247 -0
  79. package/skills/wecomcli-smartpage/references/formula/math.md +362 -0
  80. package/skills/wecomcli-smartpage/references/formula/operators.md +246 -0
  81. package/skills/wecomcli-smartpage/references/formula/pageblock.md +76 -0
  82. package/skills/wecomcli-smartpage/references/formula/templates.md +410 -0
  83. package/skills/wecomcli-smartpage/references/formula/text.md +377 -0
  84. package/skills/wecomcli-smartpage/references/formula/user.md +22 -0
  85. package/skills/wecomcli-smartpage/references/formula-reference.md +192 -0
  86. package/skills/wecomcli-smartpage/references/mdx-syntax.md +739 -0
  87. package/skills/wecomcli-smartpage/references/smartpage-edit.md +519 -0
  88. package/skills/wecomcli-smartsheet/SKILL.md +153 -0
  89. package/skills/wecomcli-smartsheet/assets/templates/README.md +53 -0
  90. package/skills/wecomcli-smartsheet/assets/templates/ai_efficiency.md +709 -0
  91. package/skills/wecomcli-smartsheet/assets/templates/connect_to_app.md +380 -0
  92. package/skills/wecomcli-smartsheet/assets/templates/financial_accounting.md +369 -0
  93. package/skills/wecomcli-smartsheet/assets/templates/hr_and_administration.md +475 -0
  94. package/skills/wecomcli-smartsheet/assets/templates/ledger_records.md +156 -0
  95. package/skills/wecomcli-smartsheet/assets/templates/manufacturing.md +395 -0
  96. package/skills/wecomcli-smartsheet/assets/templates/marketing.md +186 -0
  97. package/skills/wecomcli-smartsheet/assets/templates/office_essentials.md +299 -0
  98. package/skills/wecomcli-smartsheet/assets/templates/personal_efficiency.md +70 -0
  99. package/skills/wecomcli-smartsheet/assets/templates/procurement_logistics.md +325 -0
  100. package/skills/wecomcli-smartsheet/assets/templates/project_management.md +564 -0
  101. package/skills/wecomcli-smartsheet/assets/templates/rd_process_customer.md +222 -0
  102. package/skills/wecomcli-smartsheet/assets/templates/rd_process_ops.md +105 -0
  103. package/skills/wecomcli-smartsheet/assets/templates/rd_process_project.md +109 -0
  104. package/skills/wecomcli-smartsheet/assets/templates/rd_process_research.md +92 -0
  105. package/skills/wecomcli-smartsheet/assets/templates/sales_and_operations.md +446 -0
  106. package/skills/wecomcli-smartsheet/assets/templates/store_management.md +431 -0
  107. package/skills/wecomcli-smartsheet/assets/templates/team_tasks.md +274 -0
  108. package/skills/wecomcli-smartsheet/assets/templates/wechat_customer.md +384 -0
  109. package/skills/wecomcli-smartsheet/assets/templates/work_report.md +100 -0
  110. package/skills/wecomcli-smartsheet/references/common.md +145 -0
  111. package/skills/wecomcli-smartsheet/references/smart-sheet-chart-types.md +95 -0
  112. package/skills/wecomcli-smartsheet/references/smart-sheet-edit.md +611 -0
  113. package/skills/wecomcli-smartsheet/references/smart-sheet-field-types.md +438 -0
  114. package/skills/wecomcli-smartsheet/references/smart-sheet-formula.md +845 -0
  115. package/skills/wecomcli-smartsheet/references/smart-sheet-read.md +411 -0
  116. package/skills/wecomcli-smartsheet/references/smart-sheet-record-values.md +203 -0
  117. package/skills/wecomcli-smartsheet/references/smart-sheet-view-types.md +356 -0
  118. package/skills/{wecom-smartsheet/references/webhook-examples.md → wecomcli-smartsheet/references/smart-sheet-webhook-examples.md} +23 -32
  119. package/skills/wecomcli-smartsheet/references/smart-sheet-webhook.md +169 -0
  120. package/skills/wecomcli-todo/SKILL.md +75 -0
  121. package/skills/wecomcli-todo/references/todo-create.md +139 -0
  122. package/skills/wecomcli-todo/references/todo-delete.md +65 -0
  123. package/skills/wecomcli-todo/references/todo-finish.md +74 -0
  124. package/skills/wecomcli-todo/references/todo-get.md +68 -0
  125. package/skills/wecomcli-todo/references/todo-list.md +135 -0
  126. package/skills/wecomcli-todo/references/todo-update.md +114 -0
  127. package/dist/src/mcp/index.d.ts +0 -6
  128. package/dist/src/mcp/index.js +0 -10
  129. package/dist/src/mcp/interceptors/biz-error.d.ts +0 -11
  130. package/dist/src/mcp/interceptors/biz-error.js +0 -69
  131. package/dist/src/mcp/interceptors/doc-auth-error.d.ts +0 -10
  132. package/dist/src/mcp/interceptors/doc-auth-error.js +0 -171
  133. package/dist/src/mcp/interceptors/index.d.ts +0 -35
  134. package/dist/src/mcp/interceptors/index.js +0 -70
  135. package/dist/src/mcp/interceptors/msg-media.d.ts +0 -11
  136. package/dist/src/mcp/interceptors/msg-media.js +0 -133
  137. package/dist/src/mcp/interceptors/smartpage-create.d.ts +0 -30
  138. package/dist/src/mcp/interceptors/smartpage-create.js +0 -132
  139. package/dist/src/mcp/interceptors/smartpage-export.d.ts +0 -17
  140. package/dist/src/mcp/interceptors/smartpage-export.js +0 -87
  141. package/dist/src/mcp/interceptors/smartsheet-upload.d.ts +0 -22
  142. package/dist/src/mcp/interceptors/smartsheet-upload.js +0 -263
  143. package/dist/src/mcp/interceptors/types.d.ts +0 -64
  144. package/dist/src/mcp/interceptors/types.js +0 -7
  145. package/dist/src/mcp/schema.d.ts +0 -11
  146. package/dist/src/mcp/schema.js +0 -99
  147. package/dist/src/mcp/tool.d.ts +0 -63
  148. package/dist/src/mcp/tool.js +0 -224
  149. package/dist/src/mcp/transport.d.ts +0 -94
  150. package/dist/src/mcp/transport.js +0 -549
  151. package/skills/wecom-contact/SKILL.md +0 -162
  152. package/skills/wecom-doc/SKILL.md +0 -127
  153. package/skills/wecom-meeting/SKILL.md +0 -441
  154. package/skills/wecom-meeting/references/example-full.md +0 -30
  155. package/skills/wecom-meeting/references/example-reminder.md +0 -46
  156. package/skills/wecom-meeting/references/example-security.md +0 -22
  157. package/skills/wecom-meeting/references/response-get-meeting-info.md +0 -148
  158. package/skills/wecom-msg/SKILL.md +0 -157
  159. package/skills/wecom-msg/references/api-get-messages.md +0 -93
  160. package/skills/wecom-msg/references/api-get-msg-chat-list.md +0 -58
  161. package/skills/wecom-msg/references/api-get-msg-media.md +0 -44
  162. package/skills/wecom-msg/references/api-send-message.md +0 -39
  163. package/skills/wecom-preflight/SKILL.md +0 -141
  164. package/skills/wecom-schedule/SKILL.md +0 -161
  165. package/skills/wecom-schedule/references/api-check-availability.md +0 -56
  166. package/skills/wecom-schedule/references/api-create-schedule.md +0 -38
  167. package/skills/wecom-schedule/references/api-get-schedule-detail.md +0 -81
  168. package/skills/wecom-schedule/references/api-update-schedule.md +0 -32
  169. package/skills/wecom-schedule/references/ref-reminders.md +0 -24
  170. package/skills/wecom-sheet/SKILL.md +0 -131
  171. package/skills/wecom-sheet/references/sheet-add-sub.md +0 -54
  172. package/skills/wecom-sheet/references/sheet-append-data.md +0 -64
  173. package/skills/wecom-sheet/references/sheet-delete-sub.md +0 -38
  174. package/skills/wecom-sheet/references/sheet-update-range-data.md +0 -95
  175. package/skills/wecom-smartpage/SKILL.md +0 -119
  176. package/skills/wecom-smartpage/references/smartpage-create.md +0 -130
  177. package/skills/wecom-smartpage/references/smartpage-export.md +0 -168
  178. package/skills/wecom-smartsheet/SKILL.md +0 -241
  179. package/skills/wecom-smartsheet/references/smartsheet-cell-value-formats.md +0 -163
  180. package/skills/wecom-smartsheet/references/smartsheet-field-types.md +0 -44
  181. package/skills/wecom-smartsheet/references/smartsheet-get-records.md +0 -187
  182. package/skills/wecom-smartsheet/references/webhook-fallback.md +0 -183
  183. package/skills/wecom-todo/SKILL.md +0 -392
  184. package/skills/wecom-todo/examples/workflows.md +0 -163
@@ -26,7 +26,7 @@ metadata:
26
26
 
27
27
  1. **严格按 schema 生成**:字段名、类型、嵌套结构必须与 [./references/api-template-card-types.md](./references/api-template-card-types.md) 中的 JSON Schema 定义完全一致
28
28
  2. **每张卡片必须有 `task_id`**:格式 `task_{场景}_{时间戳}`,只能包含数字、字母、`_-@`
29
- 3. 不要使用 MCP 工具调用,直接在回复中输出 JSON 代码块
29
+ 3. 不要调用 `wecom-cli` 或其他工具发送卡片,直接在最终回复中输出 JSON 代码块
30
30
  4. 代码块外的文本会作为普通回复发送
31
31
 
32
32
  ## 卡片类型选择
@@ -0,0 +1,302 @@
1
+ ---
2
+ name: wecomcli-calendar
3
+ description: "企业微信日程管理。当用户需要预约日程、预订会议室、查看/更新/取消日程或查忙闲时触发。本技能负责『日程』——即不含在线会议链接的安排(也涵盖纯线下面对面碰头);若用户要的是『在线会议』(含会议号/入会链接、可远程或视频参会),改用 wecomcli-meeting 技能。用户仅说'开会/约个会/某会'等、未明确要创建的是日程还是在线会议时,必须先读取本技能并按其中的消歧流程向用户追问确认后再处理,不可臆断直接创建。"
4
+ ---
5
+
6
+ `wecom-cli` 是插件提供的 tool,不是终端命令:所有操作都通过调用该 tool 完成,参数应使用 `args` 传入,禁止通过 exec / shell / 终端等命令行方式使用。
7
+
8
+ ⚠️ 前置条件:首次调用 wecom-cli 前,必须按 wecomcli-preflight 技能执行前置条件检查,确保工具已加入白名单。
9
+
10
+ # 企业微信日程技能
11
+
12
+ ## 适用范围
13
+
14
+ ### 适用
15
+
16
+ - 预约 / 创建日程(含纯线下面对面碰头,即不带在线会议链接的安排)
17
+ - 查看 / 浏览日程(今天有什么安排、查本周日程)
18
+ - 搜索日程(按关键词、按组织人、按参与人找某个日程)
19
+ - 更新 / 修改日程(改时间、改地点、加减人、换会议室;不支持更新周期日程)
20
+ - 取消日程(不支持取消周期日程)
21
+ - 查忙闲 / 约多人共同空闲时段
22
+ - 订会议室、查会议室空不空、查办公楼
23
+
24
+ ### 不适用
25
+
26
+ - 创建、更新、取消周期 / 重复日程(每周 / 每月 / 每天重复)→ 均不支持,引导用户在企业微信客户端手动操作
27
+ - 回复 / 拒绝日程邀请(接受 / 拒绝 / 待定,含"拒绝这个日程""不参加")→ 不支持,引导用户在企业微信客户端操作或私信发起人
28
+
29
+ ### 易混淆场景路由
30
+
31
+ - 用户要**创建含在线会议链接的会议**(需会议号 / 入会链接 / 远程或视频参会)→ 改用 `wecomcli-meeting`(创建会议会同时生成日程,无需在本技能再建)
32
+ - 用户仅说"开会 / 约个会 / 安排个会 / xx 会"等、**未明确是日程还是在线会议**(创建场景)→ 必须先用文字追问消歧(固定问题"需要创建日程还是会议?",请用户回复"日程 / 会议"),不得臆断直接创建
33
+ - 用户要的会**同时支持线下与远程参会**(如"线下开、外地同事远程接入")→ 含在线会议链接,改用 `wecomcli-meeting`
34
+ - **仅给了地点 / 会议室号**(如"在 1605 开会""订个会议室开会")→ 不构成"明确是日程",仍需先用文字询问消歧,不能因带地点就跳过追问
35
+ - **查询场景的模糊表述**("最近有什么会 / 有哪些会")→ 严禁追问,日程和会议都查并合并展示;仅当明确提到"在线会议 / 视频会议 / 入会链接 / 会议号 / 腾讯会议 / 远程参会"时才改用 `wecomcli-meeting` 只查会议
36
+
37
+ ## 路由规则
38
+
39
+ | 用户意图 | 参考文档 |
40
+ |---------|---------|
41
+ | 预约日程、安排纯线下面对面会议(不含在线会议链接)、创建日程 | [calendar-create](references/calendar-create.md) |
42
+ | 看日程、今天有什么安排、查本周日程 | [calendar-agenda](references/calendar-agenda.md) |
43
+ | 找某个日程、项目评审是什么时候 | [calendar-search](references/calendar-search.md) |
44
+ | 查日程详情、看周期规则、看会议链接 | [calendar-agenda](references/calendar-agenda.md) |
45
+ | 取消日程、不开了 | [calendar-cancel](references/calendar-cancel.md) |
46
+ | 修改日程、更新日程、改时间、加人/移除人、换会议室 | [calendar-update](references/calendar-update.md) |
47
+ | 查忙闲、某人什么时候有空、约多人共同空闲 | [calendar-freebusy](references/calendar-freebusy.md) |
48
+ | 订会议室、查会议室空不空、查办公楼、约会议室 | [calendar-meeting-room](references/calendar-meeting-room.md) |
49
+
50
+ > **浏览 vs 搜索的选择原则**:用户提到**日程主题关键词**时走搜索;**只给了时间/日期而无日程主题关键词时,必须走列表浏览(`list`)**。需要周期规则、会议链接等详情时再读取单条日程详情补充。
51
+
52
+ ## 技能边界:日程 vs 会议 [CRITICAL]
53
+
54
+ 本技能(wecomcli-calendar)只负责**日程**——即非会议的日程安排,以及不含在线会议链接的纯线下面对面会议。**只要涉及在线会议链接(含远程/视频参会)的会议,一律归 wecomcli-meeting 技能**,不在本技能创建。
55
+
56
+ | 用户意图 | 归属技能 |
57
+ |---------|---------|
58
+ | 预约日程、安排纯线下面对面会议(不含在线会议链接)、订会议室、查/改/取消日程、查忙闲 | **本技能 wecomcli-calendar** |
59
+ | 创建含在线会议链接的会议、需要会议号或入会链接的会、需要远程/视频参会的会 | **wecomcli-meeting 技能** |
60
+
61
+ **消歧规则(仅创建场景)**:用户仅说"会议/会/开个会/约个会/安排个会/xx会/xx会议"等而未明确是日程还是会议时,**必须先用文字追问**,再路由到对应技能,禁止默认直接创建日程。此文字消歧仅用于「创建」;查询场景严格禁止追问——明确指向在线会议时只查会议,明确是日程/安排时只查日程,模糊表述("会 / xx会 / 最近有什么会"等)则日程和会议都查(见下文「查询消歧」)。
62
+
63
+ > **问题与选项固定 [CRITICAL]**:消歧确认时,问题与可选项都必须原文照用、严格禁止修改任何内容——问题固定为 `"需要创建日程还是会议?"`,可选项固定为 `日程` / `会议`;不得改写问题措辞、增减或改写选项、翻译,或自行设计其他表述(如"在线会议 / 线上会议 / 视频会议 / 线下会议"等)。
64
+
65
+ 用文字向用户提问:`需要创建日程还是会议?(请回复:日程 / 会议)`
66
+
67
+ - **"会议""会""开会"等词本身不构成"明确" [CRITICAL]**:这些词只表示要碰头议事,并未说明是日程还是会议。禁止仅因 query 里出现"会议"二字就默认归本技能(日程)创建,也禁止反向默认成会议——只要未明确,一律先用文字追问后再路由。只有出现"碰个面/创建日程"等纯线下信号时才直接留在本技能。
68
+ - 用户答「日程」→ 留在本技能,按"预约日程工作流"创建日程。
69
+ - 用户答「会议」→ 改用 `读取 wecomcli-meeting 技能` 创建会议(创建会议会同时生成对应日程,无需在本技能再建一条)。
70
+ - 用户已明确(如"碰个面""创建日程"=日程;"发个入会链接""要会议号""远程参会"=会议)时,直接路由,无需追问。
71
+ - **同时支持线下与远程参会**(如"线下开、外地同事远程接入")时,因含在线会议链接,归 wecomcli-meeting 技能:创建会议即同时生成日程,无需在本技能另建日程。
72
+ - **仅有地点/会议室号**(如"在 1605 开会""到 A 座会议室碰一下""订个会议室开会")不构成"明确是日程"——会议室里同样可能要远程接入,是日程还是会议仍未知,必须先用文字询问消歧,不能因为带了地点就跳过追问。
73
+
74
+ ## 改约 / 重建日程前必须先识别会议关联 [CRITICAL]
75
+
76
+ "改约 / 改时间 / 挪到 / 顺延 / 重新约"等改期意图(即使用户说"取消……再约到……",带"取消"也算改期),禁止机械拆成 `cancel` + `create`:
77
+
78
+ 1. **先定位再判定会议关联**:`search` / `list` 返回均含 `meeting` 字段,定位到目标日程后**直接检查 `meeting.meeting_code`**——非空为「含在线会议链接的会议形态日程」,为空为纯日程;无需为此再补一次读取日程详情(仅当还需 `repeat_rule` 等字段时才补)。
79
+ 2. **纯日程** → 用本技能路由表中更新日程意图改时间,禁止 cancel + create。
80
+ 3. **含会议链接** → 改用 `读取 wecomcli-meeting 技能`,把 `meeting.meeting_id` 传入 `meeting update` 改时间(保留会议链接与参会人),无需重新 search 定位。
81
+
82
+ > **根因**:`create` 只能建纯日程、重建不出会议链接(能拆不能合),cancel + create 会让会议链接永久丢失,故改约一律走 update。
83
+
84
+
85
+ ## 核心场景
86
+
87
+ ### 1. 预约日程
88
+
89
+ 读取 [calendar-create](references/calendar-create.md),按其中"预约日程工作流"执行(信息补全 → 参与人解析 → 时间协商/忙闲检查 → 执行创建 → 结果反馈)。
90
+
91
+ ### 2. 查看/搜索日程
92
+
93
+ | 场景 | 参考文档 |
94
+ |------|---------|
95
+ | 泛泛查询("今天有什么安排") | [calendar-agenda](references/calendar-agenda.md) |
96
+ | 有关键词("项目评审是什么时候") | [calendar-search](references/calendar-search.md) |
97
+ | 需要详情(只拿到 `schedule_id` 时补齐字段) | [calendar-agenda](references/calendar-agenda.md) |
98
+
99
+ > **浏览 vs 搜索**:有**日程主题关键词** → 搜索(不追问时间);**只给时间/日期而无主题关键词 → 列表浏览(`list`)**,禁止把日期当 `keywords` 喂给 `search`。列表浏览已返回 `repeat_rule`,无需额外读取单条详情判断是否周期日程。
100
+
101
+ > **查询消歧(模糊查询时日程 + 会议都查)[REQUIRED]**:查询场景严格禁止用文字追问"是日程还是会议"——日程/会议消歧追问仅用于创建,查询时一律按以下规则直接处理、不追问。**判定分两个独立维度,不要混为一谈**:
102
+ >
103
+ > **维度一:查哪一边(日程 / 会议 / 两边都查)**
104
+ > - **明确是在线会议** → 用户明确提到"在线会议 / 视频会议 / 入会链接 / 会议号 / 腾讯会议 / 远程参会"等在线会议专属特征时,改用 `读取 wecomcli-meeting 技能` 只查会议。
105
+ > - **明确是日程 / 安排** → 用户说的明显是日程类内容(如"日程 / 安排 / 我的安排 / 日历 / 今天有什么安排",且不带在线会议特征)时,只查日程。
106
+ > - **模糊表述无法判定**("会 / xx会 / xx会议 / 开会 / 最近有什么会 / 有哪些会 / 找下 xx会议"等,既可能是日程也可能是会议)→ **日程和会议都要查**:既查日程,又 `读取 wecomcli-meeting 技能` 查会议。
107
+ >
108
+ > **维度二:每一边用 `search` 还是 `list`(与维度一独立,逐边各自判断)**
109
+ > - **有主题/名称关键词**(如"找下 xx会议""项目评审是什么时候")→ 该边用 `search`(把关键词传入 `keywords`)。
110
+ > - **只有时间/日期或泛浏览无关键词**(如"最近有什么会""今天有什么安排")→ 该边用 `list`,禁止把日期当`keywords` 喂给 `search`。
111
+ > - 即使"两边都查",也按本维度对每一边各自选择:带关键词时两边都用 `search`,纯时间/泛浏览时两边都用 `list`。
112
+ >
113
+ > **合并展示**:两边都查时,合并结果后统一展示——按是否含在线会议链接分成「(会议)」(来自会议侧、或日程中 `meeting.meeting_code` 非空者)和「(日程)」(`meeting_code` 为空的纯日程)两部分,同一场会议在两边都出现时按"主题 + 时间"去重只保留一条,末尾汇总"共 N 场,其中会议 X 场、日程 Y 场"。
114
+ >
115
+ > - 本消歧仅针对查询;创建场景仍按上文"日程 vs 会议"用文字追问。
116
+
117
+ ### 3. 取消日程
118
+
119
+ 先定位日程(有**日程主题关键词**走搜索;只给时间/日期而无主题关键词走列表浏览 `list`,禁止把日期当 `keywords` 喂给 `search`),再判断是否周期日程(可直接读取列表返回的 `repeat_rule`,无需额外读取单条详情)——**周期日程不支持取消**,告知用户并引导其在企业微信客户端操作(见「已知限制」)。普通日程**不预先按"是否本人创建"拦截取消**,直接执行取消并根据工具返回结果判断能否取消(成功返回 `{}`,无权限则返回错误,此时告知用户并建议联系创建人)。**若用户意图实为"改约 / 挪到 / 顺延"(即使带"取消"字样),按上文「改约 / 重建日程前必须先识别会议关联」走更新流程。** 完整流程见 [calendar-cancel](references/calendar-cancel.md)。
120
+
121
+ ### 4. 更新日程
122
+
123
+ - 先定位日程(有**日程主题关键词**走搜索;只给时间/日期而无主题关键词走列表浏览 `list`,禁止把日期当 `keywords` 喂给 `search`),判断是否周期日程——**周期日程不支持更新**,告知用户并引导其在企业微信客户端操作(见「已知限制」),禁止逐场 `update` 拼凑或改为取消重建。普通日程收集修改内容后执行更新,**不预先按"是否本人创建"拦截修改**,直接执行更新并根据工具返回结果判断能否修改(成功返回更新后的 `detail`,无权限则返回错误,此时告知用户并建议联系创建人)。
124
+ - **改时间/改地点/加减人/换会议室都走更新,不要取消重建。** 换会议室时须先经 `rooms search` 确认新会议室 `status=bookable` 再把新 `meeting_room_id` 传入更新(见 [calendar-meeting-room](references/calendar-meeting-room.md))。
125
+ - **含在线会议链接的日程(定位结果中 `meeting` 非空)改时间不在本技能 update**,须改用 `读取 wecomcli-meeting 技能`(见上文「改约 / 重建日程前必须先识别会议关联」)。
126
+ - 更新日程的完整流程见 [calendar-update](references/calendar-update.md)。
127
+
128
+ ### 5. 查询忙闲 / 共同空闲
129
+
130
+ 查询参与人在指定时段的可用空闲时段(服务端已合并区间、过滤过去、按策略推荐),用于协调日程时间。详见 [calendar-freebusy](references/calendar-freebusy.md)。
131
+
132
+ ## 核心概念
133
+
134
+ - **日程(Schedule)**:日程系统中的单个事件,含主题、起止时间、参与人等属性。
135
+ - **全天日程(All-day)**:`is_all_day=true`,只按日期占用,结束日期包含在日程内。
136
+ - **周期日程(Recurring)**:`repeat_rule.is_repeat=true`,按规则重复出现。
137
+ - **参与人(Attendee)**:以 `userid`(`wo` 前缀)标识。用户提供的是姓名时通过 `读取 wecomcli-contact 技能` 解析为 `userid`。
138
+ - **忙闲(FreeBusy)**:查询参与人在指定时段是否有日程占用。
139
+ - **地点(Location)**:日程的地点为一段自由文本(`location` 字段)。用户给的地点是**公司会议室**时,须经会议室查询(`rooms search`)预订、以 `meeting_room_id` 占用(见 [calendar-meeting-room](references/calendar-meeting-room.md)),不要把会议室名仅写进 `location`;用户给的是**非会议室的普通文本地点**时才直接写入 `location`。
140
+ - **会议室 / 办公楼(Meeting Room / Building)**:物理空间资源(与在线会议链接无关)。`buildings list` 查可访问办公楼,`rooms search` 查会议室可订性,创建日程时传 `meeting_room_id` 原子占用,更新日程时传 `meeting_room_id` 改订。详见 [calendar-meeting-room](references/calendar-meeting-room.md)。
141
+ - **时区(Timezone)**:每个日程带 `timezone`(`timezone_id` + `timezone_offset`)。日程的 `begin_time` / `end_time` 是该时区下的**墙上时间**,后台不做转换——传入和返回的时间字符串都按日程时区解释,禁止自行换算成东八区或本地时间。
142
+
143
+ ## 核心规则
144
+
145
+
146
+ ### 规则 1: userid 获取 [CRITICAL]
147
+
148
+ - `attendees` / `add_attendees` / `remove_attendees` / `userids` / `has_attendees` 等所有"成员 userid 列表"入参**统一为对象数组**,格式为 `[{"userid": "woxxx"}, {"userid": "woyyy"}]`,不接受姓名或平铺字符串数组。
149
+ - `organizer`(搜索按组织人)为单值,传 userid 字符串(`wo` 前缀),不是数组。
150
+ - 用户提供的是姓名时,通过 `读取 wecomcli-contact 技能` 解析为对应 userid;多候选人时列出供用户选择,不自行猜测。
151
+ - **禁止**把姓名当 userid 拼接,**禁止**凭记忆或猜测编造 userid。
152
+ - **原因**:日程 API 不支持用姓名匹配参与人,传入姓名会导致静默失败或邀请到错误的人。
153
+
154
+ ### 规则 2: 写操作直接执行
155
+
156
+ - 创建日程、取消日程时,参数就绪后直接执行,无需向用户展示摘要或询问确认。
157
+ - 结果返回时**禁止暴露 userid**,只展示人名。
158
+ - **原因**:上层交互已完整展示操作内容并完成确认,此处再展示一遍会造成冗余。
159
+
160
+ ### 规则 3: 用户交互必须用文字询问 [CRITICAL]
161
+
162
+ 任何操作中,当必要参数不明确或需要用户做出选择时,**必须用文字直接向用户提问**,禁止自行猜测或使用默认值代替询问。提问时把可选项 / 候选值一并写进文字里,让用户直接回复。
163
+
164
+ 以下情况均适用此规则:
165
+ - **必填参数及参与人缺失**:创建日程的必填参数(`subject` / `begin_time` / `end_time`)以及参与人 `attendees` 无法从上下文中推断时,必须用文字询问;其余非必填参数(如地点)用户未明确指定时不专门询问,直接走默认值
166
+ - **多候选项需用户选择**:搜索返回多个匹配日程、wecomcli-contact 技能搜索到多个同名候选人
167
+ - **操作范围需确认**:如更换会议室时查到多个 bookable 候选,需用户选定具体一个
168
+ - **冲突处理**:忙闲检查发现时间冲突,需用户决策
169
+
170
+ **文字询问的约束**:
171
+ - 列出的可选项 / 候选建议以 **2~4 个**为宜。可选候选多于 4 个时(如同名候选人、多个匹配日程),取最相关的前 4 个列出,并提示用户可进一步缩小范围(输入更精确的关键词 / 完整姓名 / 具体时间),不要一次性罗列 5 个及以上候选。
172
+ - **询问时间时,列出的候选时刻必须是精确到分钟的具体时刻**(如"明天 14:00"、"周六 10:30"),禁止给出"上午/下午/傍晚/午间/上班后/下班前"等模糊时间选项——模糊选项会导致用户回复后仍需二次追问具体几点,必须一次问到可直接落为 `begin_time` 的精确时刻。
173
+
174
+ ### 规则 4: 任务简洁原则
175
+
176
+ 只完成用户要求的操作,不额外添加其他操作。
177
+
178
+ ### 规则 5: 输入合法性检查
179
+
180
+ 执行写操作前,验证以下输入的合法性:
181
+ - **时间格式**:必须为 `YYYY-MM-DD HH:mm:ss`,拒绝模糊表述直接传参(如"明天"不能直接传入,需先解析为具体时间)
182
+ - **时间顺序**:`end_time` 必须晚于 `begin_time`,拒绝零时长或负时长日程
183
+ - **userid 格式**:必须为 `wo` 前缀的字符串,不接受纯数字或中文姓名
184
+ - **历史时间**:禁止创建完全在当前时刻之前的日程
185
+
186
+ ### 规则 6: 输入安全处理
187
+
188
+ - 用户提供的是姓名时,必须经过 `读取 wecomcli-contact 技能` 搜索验证后才能转换为 userid。
189
+ - **禁止**把姓名直接拼接为 userid,**禁止**凭记忆或猜测编造。
190
+ - **原因**:用户输入的字符串可能不对应真实员工(姓名不唯一、已离职等),直接拼接会导致将日程邀请发送给错误的人,且此类错误无法被 API 在调用时拦截。
191
+
192
+ ## 操作参考
193
+
194
+ | 操作参考 | 读取时机 | 说明 |
195
+ |----------|---------|------|
196
+ | [`calendar-agenda`](references/calendar-agenda.md) | 查看/获取日程详情时 | 查看日程安排(list + get) |
197
+ | [`calendar-create`](references/calendar-create.md) | 创建日程时 | 创建日程并邀请参与人 |
198
+ | [`calendar-search`](references/calendar-search.md) | 搜索日程时 | 按关键词搜索日程 |
199
+ | [`calendar-cancel`](references/calendar-cancel.md) | 取消日程时 | 取消日程(不支持周期日程) |
200
+ | [`calendar-update`](references/calendar-update.md) | 更新/修改日程时 | 更新日程信息(主题、时间、参与人、地点等) |
201
+ | [`calendar-freebusy`](references/calendar-freebusy.md) | 需要协调时间 / 查共同空闲时 | 查询共同空闲时段,协调日程时间 |
202
+ | [`calendar-meeting-room`](references/calendar-meeting-room.md) | 预订/更换会议室 / 查办公楼或会议室可订性时 | 办公楼清单(`buildings list`)+ 会议室可订性(`rooms search`),拿 `meeting_room_id` 供创建占用或更新改订 |
203
+
204
+ ## 上下文传递表
205
+
206
+ > 此表描述接口间的数据流转契约,第一列"来源操作"为业务语义;各操作的完整参数与字段定义见对应 reference。
207
+
208
+ | 来源操作 | 从返回中提取 | 用于 |
209
+ |---------|-------------|------|
210
+ | 搜索(search) | `schedules[].schedule_id` | 单条详情、取消日程 |
211
+ | 列表浏览 / 单条详情(list / get) | `schedule_list[].schedule_id` | 单条详情、取消日程 |
212
+ | 搜索(search) | `schedules[].attendees[].name` | 直接展示参与人姓名,无需额外反查(搜索接口已返回) |
213
+ | 搜索(search) | `schedules[].creator_name` | 直接展示日程创建者姓名 |
214
+ | 搜索(search) | `next_cursor` + `has_more` | 分页翻页控制 |
215
+ | wecomcli-contact 技能搜索 | `userid`(`wo` 前缀) | 创建/更新日程的 `attendees` / `add_attendees` / `remove_attendees`、忙闲查询的 `userids`、搜索的 `has_attendees`(均组装为对象数组 `[{"userid": "woxxx"}]`);搜索的 `organizer` 为单值 userid 字符串 |
216
+ | 搜索 / 列表浏览 / 单条详情 | `repeat_rule` | 判断是否周期日程(`is_repeat=true`):命中时取消 / 更新均不支持,告知用户并引导企业微信客户端操作;`search`/`list` 均直接返回,无需补 `get` |
217
+ | 搜索 / 列表浏览 / 单条详情 | `meeting.meeting_code` | 识别该日程含在线会议链接(非空即「会议形态日程」,search/list/get 均直接返回,无需额外补 `get`);改约 / 取消含会议链接日程时,直接把 `meeting.meeting_id` 传入 `wecomcli-meeting` 的 `meeting update` / `meeting cancel`,无需在 wecomcli-meeting 重新 search 定位 |
218
+ | 搜索 / 列表浏览 + 单条详情 | 搜索取 `schedules[].schedule_id`、列表/详情取 `schedule_list[].schedule_id` 与 `schedule_list[].repeat_rule` | 更新日程的定位与周期日程判断(命中周期日程则不支持更新) |
219
+ | 忙闲查询 | `slots[]`(含 `available_users`、`available_count`、`busy_users`) | 直接展示推荐时段,挑前几个让用户选择;展示时只用人名,userid 仅回传创建日程的 `attendees` |
220
+ | 会议室可订性查询(`rooms search`) | `target[].room.meeting_room_id` 或 `recommendations[].meeting_room_id` | 创建日程的 `meeting_room_id`(原子占用会议室)、更新日程的 `meeting_room_id`(改订会议室);ID仅工具链流转,禁止展示,对用户只露会议室 name |
221
+
222
+ ## 错误处理
223
+
224
+ > 原则:告诉用户**出了什么问题** + **可以怎么做** + **备选方案**。禁止静默失败。
225
+
226
+ | 场景 | 恢复建议 |
227
+ |------|---------|
228
+ | 搜索无结果 | 用文字提供恢复建议:1. 更换关键词重试;2. 按组织人搜索(提供姓名,解析 userid 后传 `organizer`);3. 按参与人搜索(提供姓名,解析 userid 后传 `has_attendees`);|
229
+ | 通讯录多候选人 | 用文字列出候选人(姓名+部门)供选择 |
230
+ | wecomcli-contact 技能搜索无结果 | 用文字提示用户确认姓名,等待重新输入 |
231
+ | 取消/修改非本人创建的日程 | 不预先拦截,直接执行命令;返回权限错误时说明当前用户无权操作,建议联系创建人 |
232
+ | 共同空闲查询返回空 `slots` | 引导用户扩大时间窗口或减少参与人,不要在同一窗口反复重试 |
233
+ | 共同空闲查询降级(`available_count < total_count`) | 告知哪些人冲突、几人能参加,由用户决定是否按降级时段安排或更换时间 |
234
+
235
+ ## 输出质量标准
236
+
237
+ 好的输出应满足以下条件:
238
+ - 日程列表:按开始时间升序排序,每条日程作为独立条目顺序输出(**禁止 markdown 表格**),每个条目只含主题、时间、参与人;超过 10 条只展示前 10 条
239
+ - 参与人展示:原样使用接口返回的 `attendees[].name` 字段(完全与接口返回的格式保持一致,如返回 `zhangsan(张三)` 就展示 `zhangsan(张三)`),不展示 userid
240
+ - 操作结果:明确告知成功/失败及原因,操作成功后展示日程摘要
241
+ - 错误提示:包含问题描述+恢复建议+备选方案,不暴露技术错误码
242
+
243
+ 不可接受的输出:
244
+ - 直接展示 userid 而非姓名
245
+ - 遇到错误静默失败,不给用户任何提示
246
+ - 展示内部 schedule_id
247
+
248
+
249
+ ## 输出格式规范
250
+
251
+ **参与人姓名格式 [REQUIRED]**:所有展示参与人的场景(创建反馈、单条摘要、列表等),姓名一律**原样使用接口返回的 `attendees[].name` 字段**,完全与接口返回的格式保持一致(如返回 `zhangsan(张三)` 就展示 `zhangsan(张三)`);下文模板中的 `{人名}` 均指该原样 name。
252
+
253
+ **时间年份显示 [REQUIRED]**:下文"时间"行默认省略年份、只到月日(模板中的 `{月日}` 即指 `M月D日`);仅当日程年份与当前年份不同(跨年)时,才在月日前补上年份,格式为 `{YYYY}年M月D日 {HH:mm}-{HH:mm}`。
254
+
255
+ **相对日期标签 [REQUIRED]**:当日程日期为昨天 / 今天 / 明天时,"时间"行在月日前加上相对词,格式 `{昨天|今天|明天} M月D日 {HH:mm}-{HH:mm}`(如 `时间:明天 6月11日 14:00-15:00`);其余日期按 `{月日} {HH:mm}-{HH:mm}` 展示。
256
+
257
+ **创建成功反馈 [REQUIRED]**:创建日程成功后,输出内容只包含三部分:主题、时间、参与人,禁止输出其他任何内容和额外语句(不展示地点、提醒、schedule_id 等字段,也不附加说明、建议或寒暄):
258
+ ```
259
+ 主题:{subject}
260
+ 时间:{月日} {HH:mm}-{HH:mm}
261
+ 参与人:{人名1}、{人名2}
262
+ ```
263
+
264
+ **单条日程摘要**(用于查看/搜索单条场景,非创建反馈):
265
+ ```
266
+ 主题:{subject}
267
+ 时间:{月日} {HH:mm}-{HH:mm}
268
+ 参与人:{人名1}、{人名2}
269
+ ```
270
+
271
+ **日程列表展示规范 [REQUIRED]**(列表/搜索浏览均适用):
272
+ - **禁止使用 markdown 表格**;每条日程作为独立条目顺序输出,按开始时间升序排序。
273
+ - 每个条目 **只展示三项:主题、时间、参与人**(不展示地点、提醒、schedule_id 等)。
274
+ - **超过 10 条时只展示前 10 条**,并在末尾告知"还有 N 条,需要查看更多吗?"。
275
+ - **会议 / 日程 分两部分展示**:判断依据是该日程是否带有会议链接——`meeting.meeting_code` 有值(非空)归为「会议」,为空 / 不存在归为「日程」(`search`/`list`/`get` 返回均含 `meeting` 字段,可直接判断)。**仅当本次结果中同时存在「会议」和「日程」两类时**,才把结果分成「(会议)」和「(日程)」两个部分分别展示:先列「(会议)」部分、再列「(日程)」部分;每部分内部按开始时间升序、逐条只展示主题/时间/参与人;末尾追加汇总"共 N 场,其中会议 X 场、日程 Y 场"。**当结果只有单一类别时**(全是会议或全是日程),不分部分、不加「(会议)」/「(日程)」标题,按普通列表直接展示。
276
+ - 分部分格式:
277
+ ```
278
+ (会议)
279
+ 1. {主题}
280
+ 时间:{月日} {HH:mm}-{HH:mm}
281
+ 参与人:{人名1}、{人名2}
282
+
283
+ (日程)
284
+ 1. {主题}
285
+ 时间:{月日} {HH:mm}-{HH:mm}
286
+ 参与人:{人名1}、{人名2}
287
+ ```
288
+
289
+ **时区标注 [REQUIRED]**:日程 `timezone_offset != 28800`(非东八区)时,展示时间必须带时区标注,格式 `{HH:mm}-{HH:mm}({地区中文名} UTC±N)`,如 `14:00-15:00(纽约时间 UTC-5)`。
290
+ - `UTC±N` 由 `timezone_offset / 3600` 得出。
291
+ - 地区中文名由 `timezone_id` 推导(如 `America/New_York` → 纽约时间);`timezone_id` 为空时省略中文名,只留 `(UTC-5)`。
292
+ - 东八区(`timezone_offset = 28800`,含 `Asia/Shanghai`、`Asia/Singapore` 等)不标注,保持现状。
293
+ - 适用于单条摘要的"时间"行、日程列表、创建/更新成功反馈;freebusy 的 `slots` 不适用(按本人时区展示)。
294
+
295
+ ## 已知限制
296
+
297
+ | 限制 | 替代方案 |
298
+ |------|---------|
299
+ | **schedules list 查询窗口 ≤ 前后 30 天** | `begin_time`/`end_time` 必须落在「当前时刻前后 30 天」窗口内,超出范围服务端不返回。超出时直接告知用户超出可查范围、请重新给一个更短的时间范围,等用户重新提供后再调用 |
300
+ | **不支持创建/更新/取消周期(重复)日程** | 用户希望创建"每周/每月/每天重复"等周期日程,或对已识别为周期日程(`repeat_rule.is_repeat=true`)的日程发起更新、取消时,均直接告知用户目前不支持,并引导用户在企业微信客户端手动操作;禁止用创建多条单次日程、逐场 `update` 拼凑、`cancel`+`create` 重建、传入未公开参数等方式变通绕过 |
301
+ | **不支持回复 / 拒绝日程邀请(RSVP)** | 本技能不支持对收到的日程邀请做接受 / 拒绝 / 待定等回复(含"拒绝这个日程""不参加""婉拒邀请"等)。用户有此需求时,告知其本技能不支持,建议直接在企业微信客户端对该日程邀请操作,或通过消息告知日程发起人 |
302
+ | **共同空闲查询限制** | 周期日程仅查看最近两个月有修改的;单次查询窗口 ≤ 24h,超出需分批;`begin_time` 早于服务端当前时刻的部分会被自动截断,传纯历史窗口会返回空 `slots` |
@@ -0,0 +1,228 @@
1
+ # calendar schedules list / get — 查看日程安排
2
+
3
+ 查看近期日程安排或获取日程详情。只读操作,不修改任何日程。
4
+
5
+ > **只给时间/日期时必须用 `list` [REQUIRED]**:用户只提供了时间/日期(如"19号那条")而没有日程主题关键词时,必须走本文档的 `list` 按时间浏览,禁止把日期当关键词喂给 `search`。
6
+
7
+ > **模糊查询同时拉会议 [REQUIRED]**:若本次是"会 / xx会 / 有什么会 / 最近有哪些会"等模糊查询(见 [SKILL.md 查询消歧](../SKILL.md)),除拉日程 `list` 外,必须同时 `读取 wecomcli-meeting 技能` 用相同时间范围拉会议 `list`,把两边结果合并、分「(会议)」「(日程)」两部分汇总展示(同一场会议按主题 + 时间去重)——不论日程是否查到都要查会议。明确是日程 / 安排(不带在线会议特征)时只查日程。
8
+
9
+ ## 命令
10
+
11
+ ### list — 读取日程列表
12
+
13
+ 使用 wecom-cli 工具按照下面格式调用(以下为多个可选/分步示例)
14
+
15
+ ```
16
+ # 查看今天日程
17
+ wecom-cli calendar schedules list --json '{"begin_time": "2026-04-07 00:00:00", "end_time": "2026-04-07 23:59:59"}'
18
+
19
+ # 查看本周日程
20
+ wecom-cli calendar schedules list --json '{"begin_time": "2026-04-06 00:00:00", "end_time": "2026-04-12 23:59:59"}'
21
+ ```
22
+
23
+ **参数:**
24
+
25
+ | 参数 | 类型 | 必填 | 说明 |
26
+ |------|------|:----:|------|
27
+ | `begin_time` | string | 否 | 查询开始时间(格式 YYYY-MM-DD HH:mm:ss)。必须与 `end_time` 同时传入或同时省略,禁止单独传入其中一个。 |
28
+ | `end_time` | string | 否 | 查询结束时间(格式 YYYY-MM-DD HH:mm:ss)。必须与 `begin_time` 同时传入或同时省略,禁止单独传入其中一个;同时传入时,`end_time` 必须晚于 `begin_time`。 |
29
+
30
+ > **时间参数约束**:`begin_time` 和 `end_time` 必须**同时存在**或**同时为空**,禁止只传其中一个。两者同时传入时,`end_time` 必须严格晚于 `begin_time`,否则视为非法参数。
31
+ >
32
+ > **查询窗口上限:当前时刻前后 30 天 [REQUIRED]**:`schedules list` 仅支持查询**当前时刻前后 30 天以内**的日程,超出范围的部分服务端不返回。
33
+ > - 用户给的时间范围部分或完全超出窗口(`begin_time` 早于「今天 - 30 天」或 `end_time` 晚于「今天 + 30 天」)时,**直接告知用户「日程查询仅支持当前时刻前后 30 天范围内,请重新给一个更短的时间范围」**,等用户重新提供时间后再调用。
34
+ >
35
+ > **未指定时间时的默认范围策略 [REQUIRED]**:调用前先显式计算好时间范围再传入,不依赖服务端默认值——
36
+ > - 用户已明确时间(如"今天"、"本周"、"4月15日到4月20日")→ 直接映射为 `begin_time`/`end_time`。
37
+ > - 用户未明确时间(如"查一下我的日程"、"看看我的安排")→ **默认策略:今天起未来 7 天**(`begin_time = 今天 00:00:00`,`end_time = 7 天后 23:59:59`),无需追问。
38
+ > - 用户说"最近"或"近期" → 使用"过去 3 天到未来 7 天"(`begin_time = 3 天前 00:00:00`,`end_time = 7 天后 23:59:59`)。
39
+ > - 用户只提供了模糊但有意义的范围(如"上个月")→ 解析为对应日期范围。
40
+
41
+ **返回**:`schedule_list[]` 数组,每项字段如下:
42
+
43
+ | 字段 | 类型 | 说明 |
44
+ |------|------|------|
45
+ | `schedule_id` | string | 日程 ID |
46
+ | `subject` | string | 日程主题 |
47
+ | `begin_time` | string | 开始时间(YYYY-MM-DD HH:mm:ss) |
48
+ | `end_time` | string | 结束时间(YYYY-MM-DD HH:mm:ss) |
49
+ | `attendees` | object[] | 参与人列表,格式 `[{"userid": "USERID", "name": "englishname(name)"}]` |
50
+ | `meeting_room` | object | 会议室信息,含 `meeting_room_id` + `meeting_room_name` |
51
+ | `location` | string | 日程地点 |
52
+ | `meeting` | object | 在线会议信息(关联了会议时才有),含 `meeting_id`/`meeting_code` |
53
+ | `description` | string | 日程描述 |
54
+ | `creator_name` | string | 日程创建者名字 |
55
+ | `allow_self_join` | bool | 是否允许非参与人主动加入日程 |
56
+ | `is_all_day` | bool | 是否全天事件(`true` 是 / `false` 否) |
57
+ | `repeat_rule` | object | 重复规则(`is_repeat=false` 时无此字段或为空),见下表 |
58
+ | `reminders` | object | 提醒设置,含 `is_remind`(是否开启,bool,`true` 是 / `false` 否)和 `reminder_time`(int[],与开始时间的差值秒数,负数为提前提醒) |
59
+ | `timezone` | object | 时区信息,含 `timezone_id`(IANA 标识,如 `Asia/Shanghai`,优先使用)和 `timezone_offset`(UTC 偏移量秒数,`timezone_id` 为空时使用) |
60
+
61
+ **`repeat_rule` 子字段(list 返回):**
62
+
63
+ | 字段 | 类型 | 说明 |
64
+ |------|------|------|
65
+ | `is_repeat` | bool | 是否重复日程 |
66
+ | `repeat_type` | string | 重复类型:`daily`/`weekly`/`monthly`/`monthly_on_the_nth_day`/`yearly`/`yearly_on_the_nth_day`/`work_day` |
67
+ | `repeat_flag` | string[] | 重复标记,数组,可选值:`leap_month`(闰月)、`never_ends`(永不结束) |
68
+ | `repeat_time` | int | 重复次数,`0` 表示无限 |
69
+ | `repeat_interval` | int | 重复间隔 |
70
+ | `repeat_until` | string | 重复截止时间(格式 YYYY-MM-DD HH:mm:ss) |
71
+ | `repeat_week_of_month` | string[] | 每月第几周,数组,可选值:`first`/`second`/`third`/`fourth`/`last` |
72
+ | `repeat_day_of_week` | string[] | 每周周几,数组,可选值:`MO`/`TU`/`WE`/`TH`/`FR`/`SA`/`SU` |
73
+ | `repeat_month_of_year` | int[] | 每年哪几个月,数组,取值范围:1~12 |
74
+ | `repeat_day_of_month` | int[] | 每月哪几天,数组,取值范围:1~31 |
75
+ | `is_custom` | bool | 是否自定义重复 |
76
+ | `exception` | object[] | 例外日程列表,每项含 `begin_time`/`end_time`/`flag`/`except_schedule_id` |
77
+
78
+ ### get — 读取日程详情
79
+
80
+ 使用 wecom-cli 工具按照下面格式调用
81
+
82
+ ```
83
+ wecom-cli calendar schedules get --json '{"schedule_ids": ["<schedule_id1>", "<schedule_id2>"]}'
84
+ ```
85
+
86
+ **参数:**
87
+
88
+ | 参数 | 类型 | 必填 | 说明 |
89
+ |------|------|:----:|------|
90
+ | `schedule_ids` | string[] | 是 | 日程 ID 列表,支持传入一个或多个 |
91
+
92
+ **返回**:`schedule_list[]` 数组,每项字段如下:
93
+
94
+ | 字段 | 类型 | 说明 |
95
+ |------|------|------|
96
+ | `schedule_id` | string | 日程 ID |
97
+ | `subject` | string | 日程主题 |
98
+ | `begin_time` | string | 开始时间(YYYY-MM-DD HH:mm:ss) |
99
+ | `end_time` | string | 结束时间(YYYY-MM-DD HH:mm:ss) |
100
+ | `attendees` | object[] | 参与人列表,格式 `[{"userid": "USERID", "name": "englishname(name)"}]`,直接取 `name` 展示,禁止展示 userid |
101
+ | `meeting_room` | object | 会议室信息,含 `meeting_room_id` + `meeting_room_name` |
102
+ | `location` | string | 日程地点 |
103
+ | `meeting` | object | 在线会议信息(关联了会议时才有),含 `meeting_id`/`meeting_code` |
104
+ | `description` | string | 日程描述 |
105
+ | `creator_name` | string | 日程创建者名字 |
106
+ | `allow_self_join` | bool | 是否允许非参与人主动加入日程 |
107
+ | `is_all_day` | bool | 是否全天事件(`true` 是 / `false` 否) |
108
+ | `repeat_rule` | object | 重复规则(`is_repeat=false` 时无此字段或为空),见下表 |
109
+ | `reminders` | object | 提醒设置,含 `is_remind`(是否开启,bool,`true` 是 / `false` 否)和 `reminder_time`(int[],与开始时间的差值秒数,负数为提前提醒) |
110
+ | `timezone` | object | 时区信息,含 `timezone_id`(IANA 标识,如 `Asia/Shanghai`,优先使用)和 `timezone_offset`(UTC 偏移量秒数,`timezone_id` 为空时使用) |
111
+
112
+ **`repeat_rule` 子字段:**
113
+
114
+ | 字段 | 类型 | 说明 |
115
+ |------|------|------|
116
+ | `is_repeat` | bool | 是否重复日程 |
117
+ | `repeat_type` | string | 重复类型:`daily`/`weekly`/`monthly`/`monthly_on_the_nth_day`/`yearly`/`yearly_on_the_nth_day`/`work_day` |
118
+ | `repeat_flag` | string[] | 重复标记,数组,可选值:`leap_month`(闰月)、`never_ends`(永不结束) |
119
+ | `repeat_time` | int | 重复次数,`0` 表示无限 |
120
+ | `repeat_interval` | int | 重复间隔 |
121
+ | `repeat_until` | string | 重复截止时间(格式 YYYY-MM-DD HH:mm:ss) |
122
+ | `repeat_week_of_month` | string[] | 每月第几周,数组,可选值:`first`/`second`/`third`/`fourth`/`last` |
123
+ | `repeat_day_of_week` | string[] | 每周周几,数组,可选值:`MO`/`TU`/`WE`/`TH`/`FR`/`SA`/`SU` |
124
+ | `repeat_month_of_year` | int[] | 每年哪几个月,数组,取值范围:1~12 |
125
+ | `repeat_day_of_month` | int[] | 每月哪几天,数组,取值范围:1~31 |
126
+ | `is_custom` | bool | 是否自定义重复 |
127
+ | `exception` | object[] | 例外日程列表,每项含 `begin_time`/`end_time`/`flag`/`except_schedule_id` |
128
+
129
+ ## 输出格式
130
+
131
+ 将结果整理为顺序的日程列表(**禁止使用 markdown 表格**,每条日程作为独立条目顺序输出,按开始时间升序排序):
132
+
133
+ ```
134
+ (会议)
135
+ 1. 产品评审
136
+ 时间:4月7日 10:00-11:00
137
+ 参与人:王五、赵六、钱七
138
+
139
+ (日程)
140
+ 1. 站会
141
+ 时间:4月7日 09:30-09:45
142
+ 参与人:张三、李四
143
+
144
+ 共 2 场,其中会议 1 场、日程 1 场
145
+ ```
146
+
147
+ > 上例为"模糊会议查询"(日程 + 会议都查)且**两类同时存在**时的呈现:合并日程 `list` 与会议 `list` 的结果,按是否含在线会议链接分成「(会议)」「(日程)」两个部分(来自会议 `list` 或 `meeting.meeting_code` 非空者归会议),同一场会议两边都出现时按"主题 + 时间"去重,末尾给汇总;若本次结果只有单一类别(全是会议或全是日程),则不分部分、不加「(会议)」/「(日程)」标题,按普通列表直接展示;普通"看日程"查询也可不分部分、省略汇总行。
148
+
149
+ **展示规则:**
150
+ - 每个条目 **只展示三项:主题、时间、参与人**(不展示地点、会议室等其他字段)。
151
+ - **时间默认省略年份**(只到月日);仅当日程年份与当前年份不同(跨年)时,才在月日前带上年份。
152
+ - **昨天 / 今天 / 明天**的日程,时间行在月日前加相对词(如 `明天 6月11日 14:00-15:00`);其余日期按月日展示。
153
+ - **超过 10 条时只展示前 10 条**,并在末尾告知"还有 N 条,需要查看更多吗?"。
154
+ - 参与人原样取接口返回的 `attendees[].name` 展示(完全与接口返回的格式保持一致,如返回 `zhangsan(张三)` 就展示 `zhangsan(张三)`),禁止展示 userid、schedule_id。
155
+ - **会议 / 日程 分两部分展示**:判断依据是该日程是否带有会议链接——`meeting.meeting_code` 有值(非空)归为「会议」,为空 / 不存在归为「日程」。**仅当本次结果中同时存在「会议」和「日程」两类时**,才把结果分成「(会议)」和「(日程)」两个部分分别展示(每部分内按开始时间升序、逐条只列主题/时间/参与人);**当结果只有单一类别时**(全是会议或全是日程),不分部分、不展示「(会议)」/「(日程)」标题,按普通列表直接展示即可。`search`/`list`/`get` 返回均含 `meeting` 字段,可直接判断,无需额外调用其它接口补 `get`。
156
+
157
+ **模糊"会议"查询的汇总 [REQUIRED]**:当本次是"查会议/xx会"等需归类的查询(见 [SKILL.md 查询消歧](../SKILL.md))时,在列表末尾追加一行汇总:`共 N 场,其中会议 X 场、日程 Y 场`。
158
+
159
+ **时区标注**:日程 `timezone.timezone_offset != 28800`(非东八区)时,按 [SKILL.md 输出格式规范](../SKILL.md) 的时区标注规则在时间后带上时区,如 `14:00-15:00(纽约时间 UTC-5)`。
160
+
161
+ ### 周期日程标注规则 [REQUIRED]
162
+
163
+ 列表中存在 `repeat_rule.is_repeat=true` 的日程时,必须在该日程的**主题后追加**周期频率标注(不另起新字段,保持每个条目仍只有主题/时间/参与人三项),格式如下:
164
+
165
+ ```
166
+ 1. 每周站会(每周一次,截止 2026-12-31)
167
+ 时间:4月7日(周一)09:00-09:30
168
+ 参与人:张三、李四
169
+ ```
170
+
171
+ **`repeat_type` 枚举值 → 可读文案映射:**
172
+
173
+ | `repeat_type` | 含义 | 展示文案示例 |
174
+ |:---:|------|------|
175
+ | `daily` | 每天 | 每天一次 |
176
+ | `weekly` | 每周 | 每周一次 |
177
+ | `monthly` | 每月 | 每月一次 |
178
+ | `monthly_on_the_nth_day` | 每月第N天 | 每月一次 |
179
+ | `yearly` | 每年 | 每年一次 |
180
+ | `yearly_on_the_nth_day` | 每年第N天 | 每年一次 |
181
+ | `work_day` | 每个工作日 | 每工作日一次 |
182
+ | 其他(`is_custom=true`) | 自定义 | 自定义周期 |
183
+
184
+ **时间范围展示规则:**
185
+ - `repeat_until` 非空 → 展示"截止 {repeat_until 的日期部分}"
186
+ - `repeat_until` 为空 且 `repeat_time=0` → 展示"无截止"
187
+ - `repeat_time > 0` → 展示"共 {repeat_time} 次"
188
+
189
+ ## 典型场景
190
+
191
+ ### 1. 查看今日日程
192
+
193
+ ```
194
+ 用户:今天有什么安排?
195
+ → 调用 list(today 00:00-23:59)
196
+ → 按开始时间升序,顺序输出每条日程(主题/时间/参与人),超过 10 条只展示前 10 条
197
+ ```
198
+
199
+ ### 2. 未指定时间范围,使用默认策略
200
+
201
+ ```
202
+ 用户:帮我看看我的日程安排
203
+ → 未指定时间范围,直接使用默认策略:今天起未来 7 天(无需追问)
204
+ begin_time = 今天 00:00:00,end_time = 7 天后 23:59:59
205
+ → 调用 list,按开始时间升序顺序输出每条日程(主题/时间/参与人)
206
+ ```
207
+
208
+ ### 3. 查看详情(需要周期规则、会议链接等)
209
+
210
+ ```
211
+ 用户:这个周会是每周开吗?
212
+ → 先从 list/search 结果中拿到 schedule_id
213
+ → 调用 get 获取详情,展示 repeat_rule
214
+ ```
215
+
216
+ ## 提示
217
+
218
+ - 无日程时告知用户"今天日程清空"。
219
+ - **查询窗口上限 [REQUIRED]**:`schedules list` 仅覆盖当前时刻前后 30 天以内。用户给的时间范围超出窗口时,直接告知用户超出可查范围、请重新给一个更短的时间范围,等用户重新提供后再调用。
220
+ - **顺序列表展示**:每条日程作为独立条目顺序输出,禁止 markdown 表格,每个条目只含主题/时间/参与人。超过 10 条只展示前 10 条,并告知"还有 N 条,需要查看更多吗?"。
221
+ - `list` 和 `get` 均返回 `repeat_rule`,可直接判断是否周期日程;`meeting`(含 `meeting_id`/`meeting_code`)在 `search`/`list`/`get` 中均直接返回,判断会议形态无需额外补 `get`。
222
+ - **周期日程必须说明 [REQUIRED]**:结果中只要存在 `repeat_rule.is_repeat=true` 的日程,必须在该日程**主题后追加**周期频率(由 `repeat_type` 推导)和时间范围(由 `repeat_until`/`repeat_time` 推导)标注,保持条目仍只含主题/时间/参与人三项。禁止仅展示日程条目而不说明其为周期日程。
223
+ - **参与人展示**:`list` 返回的 `attendees` 格式为 `[{"userid": "USERID", "name": "englishname(name)"}]`,直接取 `name` 字段展示,禁止展示 userid,无需反查通讯录。
224
+
225
+ ## 参考
226
+
227
+ - [wecomcli-calendar](../SKILL.md) — 日程技能主文档
228
+ - [calendar-search](calendar-search.md) — 按关键词搜索日程