@rezti/dsh-rez-suite 0.1.49 → 0.1.51

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 (142) hide show
  1. package/CHANGELOG.md +13 -2
  2. package/README.md +3 -3
  3. package/README.zh.md +2 -2
  4. package/cordis.patch.yml +1 -1
  5. package/lib/client.d.ts +31 -3
  6. package/lib/client.js +343 -7
  7. package/lib/index.js +244 -15
  8. package/lib/style.css +7 -0
  9. package/package.json +12 -11
  10. package/src/boss/mount.ts +4 -3
  11. package/src/boss/register.ts +1 -1
  12. package/src/boss/seed.ts +34 -0
  13. package/src/changelog.ts +48 -0
  14. package/src/channel-board.ts +55 -0
  15. package/src/client/locales.ts +62 -6
  16. package/src/client/panel/BoardTab.tsx +136 -0
  17. package/src/client/panel/ConfigTab.tsx +2 -2
  18. package/src/client/panel/StatusTab.tsx +31 -0
  19. package/src/client/panel/panel.module.css +7 -0
  20. package/src/client/settings-card.tsx +4 -1
  21. package/src/index.ts +3 -2
  22. package/src/protocol.ts +14 -0
  23. package/src/routes.ts +7 -1
  24. package/src/tools.ts +49 -6
  25. package/src/wecom-cli.ts +125 -0
  26. package/templates/boss/ops/AGENTS.md +2 -0
  27. package/templates/shared/wecom-cli.SOURCE.md +9 -0
  28. package/templates/shared/wecom-office/SKILL.md +32 -0
  29. package/templates/shared/wecomcli-calendar/SKILL.md +303 -0
  30. package/templates/shared/wecomcli-calendar/references/calendar-agenda.md +224 -0
  31. package/templates/shared/wecomcli-calendar/references/calendar-cancel.md +108 -0
  32. package/templates/shared/wecomcli-calendar/references/calendar-create.md +238 -0
  33. package/templates/shared/wecomcli-calendar/references/calendar-freebusy.md +207 -0
  34. package/templates/shared/wecomcli-calendar/references/calendar-meeting-room.md +170 -0
  35. package/templates/shared/wecomcli-calendar/references/calendar-search.md +206 -0
  36. package/templates/shared/wecomcli-calendar/references/calendar-update.md +272 -0
  37. package/templates/shared/wecomcli-contact/SKILL.md +58 -0
  38. package/templates/shared/wecomcli-disk/SKILL.md +389 -0
  39. package/templates/shared/wecomcli-doc/SKILL.md +137 -0
  40. package/templates/shared/wecomcli-doc/references/doc-contents-append.md +20 -0
  41. package/templates/shared/wecomcli-doc/references/doc-contents-overwrite.md +27 -0
  42. package/templates/shared/wecomcli-doc/references/doc-create.md +161 -0
  43. package/templates/shared/wecomcli-doc/scripts/build_docx.py +1375 -0
  44. package/templates/shared/wecomcli-doc-manage/SKILL.md +132 -0
  45. package/templates/shared/wecomcli-doc-manage/references/doc-members-update.md +24 -0
  46. package/templates/shared/wecomcli-doc-manage/references/doc-names-update.md +20 -0
  47. package/templates/shared/wecomcli-doc-manage/references/doc-rules-update.md +22 -0
  48. package/templates/shared/wecomcli-email/SKILL.md +218 -0
  49. package/templates/shared/wecomcli-email/references/forward-mail.md +131 -0
  50. package/templates/shared/wecomcli-email/references/get-mail.md +166 -0
  51. package/templates/shared/wecomcli-email/references/reply-mail.md +138 -0
  52. package/templates/shared/wecomcli-email/references/search-mail.md +111 -0
  53. package/templates/shared/wecomcli-email/references/security.md +53 -0
  54. package/templates/shared/wecomcli-email/references/send-mail.md +186 -0
  55. package/templates/shared/wecomcli-email/references/send-schedule.md +83 -0
  56. package/templates/shared/wecomcli-media/SKILL.md +98 -0
  57. package/templates/shared/wecomcli-meeting/SKILL.md +373 -0
  58. package/templates/shared/wecomcli-meeting/references/meeting-cancel.md +113 -0
  59. package/templates/shared/wecomcli-meeting/references/meeting-create.md +167 -0
  60. package/templates/shared/wecomcli-meeting/references/meeting-list.md +226 -0
  61. package/templates/shared/wecomcli-meeting/references/meeting-original-get.md +98 -0
  62. package/templates/shared/wecomcli-meeting/references/meeting-search.md +173 -0
  63. package/templates/shared/wecomcli-meeting/references/meeting-update.md +217 -0
  64. package/templates/shared/wecomcli-message/SKILL.md +200 -0
  65. package/templates/shared/wecomcli-shared/SKILL.md +73 -0
  66. package/templates/shared/wecomcli-sheet/SKILL.md +172 -0
  67. package/templates/shared/wecomcli-sheet/references/sheet-contents-update.md +47 -0
  68. package/templates/shared/wecomcli-sheet/references/sheet-ranges-get.md +45 -0
  69. package/templates/shared/wecomcli-sheet/references/sheet-rows-append.md +45 -0
  70. package/templates/shared/wecomcli-sheet/references/sheet-subsheets-add.md +26 -0
  71. package/templates/shared/wecomcli-sheet/references/sheet-subsheets-delete.md +20 -0
  72. package/templates/shared/wecomcli-smartpage/SKILL.md +170 -0
  73. package/templates/shared/wecomcli-smartpage/references/data-driven-pages.md +50 -0
  74. package/templates/shared/wecomcli-smartpage/references/formula/arraylist.md +369 -0
  75. package/templates/shared/wecomcli-smartpage/references/formula/datetime.md +283 -0
  76. package/templates/shared/wecomcli-smartpage/references/formula/logic.md +247 -0
  77. package/templates/shared/wecomcli-smartpage/references/formula/math.md +362 -0
  78. package/templates/shared/wecomcli-smartpage/references/formula/operators.md +246 -0
  79. package/templates/shared/wecomcli-smartpage/references/formula/pageblock.md +76 -0
  80. package/templates/shared/wecomcli-smartpage/references/formula/templates.md +410 -0
  81. package/templates/shared/wecomcli-smartpage/references/formula/text.md +377 -0
  82. package/templates/shared/wecomcli-smartpage/references/formula/user.md +22 -0
  83. package/templates/shared/wecomcli-smartpage/references/formula-reference.md +192 -0
  84. package/templates/shared/wecomcli-smartpage/references/mdx-syntax.md +739 -0
  85. package/templates/shared/wecomcli-smartpage/references/smartpage-edit.md +506 -0
  86. package/templates/shared/wecomcli-smartsheet/SKILL.md +154 -0
  87. package/templates/shared/wecomcli-smartsheet/assets/templates/README.md +53 -0
  88. package/templates/shared/wecomcli-smartsheet/assets/templates/ai_efficiency.md +709 -0
  89. package/templates/shared/wecomcli-smartsheet/assets/templates/connect_to_app.md +380 -0
  90. package/templates/shared/wecomcli-smartsheet/assets/templates/financial_accounting.md +369 -0
  91. package/templates/shared/wecomcli-smartsheet/assets/templates/hr_and_administration.md +475 -0
  92. package/templates/shared/wecomcli-smartsheet/assets/templates/ledger_records.md +156 -0
  93. package/templates/shared/wecomcli-smartsheet/assets/templates/manufacturing.md +395 -0
  94. package/templates/shared/wecomcli-smartsheet/assets/templates/marketing.md +186 -0
  95. package/templates/shared/wecomcli-smartsheet/assets/templates/office_essentials.md +299 -0
  96. package/templates/shared/wecomcli-smartsheet/assets/templates/personal_efficiency.md +70 -0
  97. package/templates/shared/wecomcli-smartsheet/assets/templates/procurement_logistics.md +325 -0
  98. package/templates/shared/wecomcli-smartsheet/assets/templates/project_management.md +564 -0
  99. package/templates/shared/wecomcli-smartsheet/assets/templates/rd_process_customer.md +222 -0
  100. package/templates/shared/wecomcli-smartsheet/assets/templates/rd_process_ops.md +105 -0
  101. package/templates/shared/wecomcli-smartsheet/assets/templates/rd_process_project.md +109 -0
  102. package/templates/shared/wecomcli-smartsheet/assets/templates/rd_process_research.md +92 -0
  103. package/templates/shared/wecomcli-smartsheet/assets/templates/sales_and_operations.md +446 -0
  104. package/templates/shared/wecomcli-smartsheet/assets/templates/store_management.md +431 -0
  105. package/templates/shared/wecomcli-smartsheet/assets/templates/team_tasks.md +274 -0
  106. package/templates/shared/wecomcli-smartsheet/assets/templates/wechat_customer.md +384 -0
  107. package/templates/shared/wecomcli-smartsheet/assets/templates/work_report.md +100 -0
  108. package/templates/shared/wecomcli-smartsheet/references/common.md +143 -0
  109. package/templates/shared/wecomcli-smartsheet/references/smart-sheet-chart-types.md +95 -0
  110. package/templates/shared/wecomcli-smartsheet/references/smart-sheet-edit.md +589 -0
  111. package/templates/shared/wecomcli-smartsheet/references/smart-sheet-field-types.md +438 -0
  112. package/templates/shared/wecomcli-smartsheet/references/smart-sheet-formula.md +845 -0
  113. package/templates/shared/wecomcli-smartsheet/references/smart-sheet-read.md +391 -0
  114. package/templates/shared/wecomcli-smartsheet/references/smart-sheet-record-values.md +201 -0
  115. package/templates/shared/wecomcli-smartsheet/references/smart-sheet-view-types.md +356 -0
  116. package/templates/shared/wecomcli-smartsheet/references/smart-sheet-webhook-examples.md +176 -0
  117. package/templates/shared/wecomcli-smartsheet/references/smart-sheet-webhook.md +169 -0
  118. package/templates/shared/wecomcli-todo/SKILL.md +76 -0
  119. package/templates/shared/wecomcli-todo/references/todo-create.md +137 -0
  120. package/templates/shared/wecomcli-todo/references/todo-delete.md +63 -0
  121. package/templates/shared/wecomcli-todo/references/todo-finish.md +72 -0
  122. package/templates/shared/wecomcli-todo/references/todo-get.md +66 -0
  123. package/templates/shared/wecomcli-todo/references/todo-list.md +133 -0
  124. package/templates/shared/wecomcli-todo/references/todo-update.md +112 -0
  125. package/templates/staff/design/AGENTS.md +2 -1
  126. package/templates/staff/ecommerce/.agents/skills/ops-ecommerce/SKILL.md +6 -0
  127. package/templates/staff/ecommerce/AGENTS.md +49 -0
  128. package/templates/staff/ecommerce/BOOTSTRAP.md +23 -0
  129. package/templates/staff/ecommerce/IDENTITY.md +8 -0
  130. package/templates/staff/ecommerce/MEMORY.md +9 -0
  131. package/templates/staff/ecommerce/PRIORITIES.md +3 -0
  132. package/templates/staff/ecommerce/SOUL.md +5 -0
  133. package/templates/staff/ecommerce/USER.md +8 -0
  134. package/templates/staff/hr/.agents/skills/staff-onboard-keys/SKILL.md +3 -3
  135. package/templates/staff/publish/.agents/skills/ops-publish/SKILL.md +6 -0
  136. package/templates/staff/publish/AGENTS.md +59 -0
  137. package/templates/staff/publish/BOOTSTRAP.md +23 -0
  138. package/templates/staff/publish/IDENTITY.md +8 -0
  139. package/templates/staff/publish/MEMORY.md +9 -0
  140. package/templates/staff/publish/PRIORITIES.md +3 -0
  141. package/templates/staff/publish/SOUL.md +6 -0
  142. package/templates/staff/publish/USER.md +8 -0
@@ -0,0 +1,173 @@
1
+ # 操作参考:搜索会议
2
+
3
+ 按关键词搜索会议,支持时间范围过滤和分页。只读操作。
4
+
5
+ ## 命令
6
+
7
+ ```bash
8
+ wecom-cli meeting search --json '{...}'
9
+ ```
10
+
11
+ ## 请求参数
12
+
13
+ | 字段 | 类型 | 必填 | 说明 |
14
+ | ------------ | -------- | ---- | ------------------------------------------------------------------- |
15
+ | `keywords` | string[] | 是 | 搜索关键词数组, 长度 ≤ 10, 用于匹配会议主题、参会人姓名、会议纪要内容、会议室名称等信息, 可与时间范围并用。支持多关键词组合逻辑:**数组多个元素之间 = OR**(命中任意一个即搜索);**单个元素内空格分隔 = AND**(必须同时命中所有词)。示例:`["周会 项目", "评审"]` 表示匹配"同时包含'周会'和'项目'"或"包含'评审'"的会议 |
16
+ | `begin_time` | string | 否 | 搜索的开始时间, 限定搜索范围的起始时间, 格式 `YYYY-MM-DD HH:mm:ss` |
17
+ | `end_time` | string | 否 | 搜索的结束时间, 限定搜索范围的截止时间, 格式 `YYYY-MM-DD HH:mm:ss` |
18
+ | `cursor` | string | 否 | 分页游标, 首次查询不填, 后续翻页使用上次返回的 `next_cursor` |
19
+ | `limit` | number | 否 | 每页数量, 固定传 `20` |
20
+
21
+ ## 返回字段
22
+
23
+ | 字段 | 说明 |
24
+ | --------------------------- | ---------------------------------------- |
25
+ | `meetings[].meeting_id` | 会议 ID |
26
+ | `meetings[].sub_meeting_id` | 子会议 ID, 周期会议涉及 |
27
+ | `meetings[].subject` | 会议主题 |
28
+ | `meetings[].begin_time` | 会议开始时间 |
29
+ | `meetings[].end_time` | 会议结束时间 |
30
+ | `meetings[].attendee_count` | 参会人数量 |
31
+ | `meetings[].meeting_room` | 会议室名称 |
32
+ | `meetings[].location` | 地点 |
33
+ | `next_cursor` | 下一页游标, 传入下次请求的 `cursor` 字段 |
34
+ | `has_more` | 是否还有更多数据, `true` 表示可继续翻页 |
35
+ | `meetings_count` | `meetings` 数组元素数量 |
36
+
37
+ > 每次固定返回 20 条数据(`limit` 固定传 `20`)。
38
+
39
+ ## 约束
40
+
41
+ - 有关键词时不追问补全时间, 直接搜索
42
+ - `keywords` 为数组类型, 即使只有一个关键词也需包装为数组, 如 `["周会"]`
43
+ - 翻页时, 通过 `has_more` 判断是否还有更多数据; `has_more: false` 时停止翻页
44
+
45
+ ## 意图分类
46
+
47
+ 在处理搜索结果前,需先判断用户的意图类型:
48
+
49
+ | 意图类型 | 典型表达 | 判断依据 |
50
+ |---------|---------|---------|
51
+ | **定位型** | "找找上周的周会"、"搜索下项目评审的会议" | 想定位某一个特定会议,后续要查详情/取消/更新等 |
52
+ | **浏览型** | "我有哪些项目评审会议"、"列一下所有关于项目的会议" | 使用"有哪些"、"列出"、"所有"等表述,想查看全部匹配结果 |
53
+
54
+ ## 接口选择规则
55
+
56
+ 1. **有会议名称/关键词 → `search`**:用户提到会议主题/关键词时,不追问时间,直接搜索。
57
+ 2. **无关键词、只给时间或泛泛浏览 → `list`**:用户只说时间(如"今天有什么会")或泛泛地说"看看我的会议"时,改用 [meeting-list](meeting-list.md) 按时间范围查询。
58
+ 3. **要详情 → `get`**:`list`/`search` 返回摘要。需会议状态、参会人、入会链接等时,用 `get` 补充。
59
+ 4. **与某人相关 → 优先 `search`**:寻找与某人相关的会议(如"我和张三开的会")时,优先用 `search`(把人名作为 `keywords` 匹配参会人),而非 `list` 拉全量再过滤。
60
+
61
+
62
+ ## 工作流
63
+
64
+ > **模糊搜索前置 [REQUIRED]**:若用户搜的是"会 / xx会 / xx会议"等模糊目标(非明确在线会议,见 [SKILL.md 查询消歧](../SKILL.md)),除按下面搜会议外,必须同时 `读取 wecomcli-calendar 技能` 用同样关键词搜日程,把两边结果合并、分「(会议)」「(日程)」两部分汇总展示——不论会议是否搜到都要搜日程。仅当用户明确指向在线会议时才只搜会议。
65
+
66
+ ### 正常路径
67
+
68
+ 1. **提取关键词**:从用户意图提取搜索关键词,组装为字符串数组。缺失时必须用文字询问引导用户补全,禁止猜测或使用默认值(如"帮我搜一下会议"→ 用文字引导用户补全搜索关键词)
69
+ 2. **判断意图类型**:根据"意图分类"表判断是定位型还是浏览型
70
+ 3. **搜索会议**:调用 `wecom-cli meeting search --json '{...}'`, 传入 `keywords` 数组(固定带上 `"limit": 20`)和可选的时间范围
71
+ 4. **按意图处理结果**:
72
+ - **定位型**:参见下方"异常路径 - 搜索返回多个结果"
73
+ - **浏览型**:自动翻页拉取全部数据(参见"翻页策略 - 浏览型自动翻页")用于统计总条数;按开始时间排序后,只对要展示的前 10 条 `meeting_id` 调用 `meeting get` 反查参会人姓名,再顺序输出每条会议(主题/时间/参会人,禁止 markdown 表格),超过 10 条只展示前 10 条并告知"还有 N 条,需要查看更多吗?"
74
+ - **无结果**:按用户提供的关键词/时间无法搜索到会议时,不要立即告知"没找到",先按"异常路径 - 搜索无结果"主动改用日程查询兜底
75
+ 5. **获取详情**(仅定位型需要):用搜索结果中的 `meeting_id` 调用 `wecom-cli meeting get --json '{"meeting_ids": [{"meeting_id": "<meeting_id>"}]}'` 获取完整信息(注意 `meeting_ids` 为数组格式)
76
+
77
+ ### 翻页策略
78
+
79
+ - 首次查询不传 `cursor`,固定带上 `"limit": 20`
80
+ - 需要翻页时: 携带上次返回的 `next_cursor` 作为 `cursor`
81
+ - 到达边界时: `has_more: false` 表示没有更多数据,停止翻页
82
+
83
+ **浏览型自动翻页**:浏览型意图下,若 `has_more: true`,自动携带 `next_cursor` 继续请求下一页,循环至 `has_more: false` 为止,将所有页数据合并后一次性展示,无需用户确认每次翻页。
84
+
85
+ ### 异常路径
86
+
87
+ | 异常情况 | 处理方式 |
88
+ |---------|---------|
89
+ | 搜索无结果 | 先建议修改关键词或扩大时间范围;同时主动 `读取 wecomcli-calendar 技能` 用同样关键词在日程里搜一把——企微里「会」有「含在线会议链接的会议」和「日程」两种载体,团队聚一起的会常落在日程而非会议。命中则一并呈现并说明「这是一条日程」,仍无果再告知两边都没有 |
90
+ | 定位型 - 搜索返回多个结果 | 用文字让用户指定目标会议:`搜索到多个匹配会议,请选择要操作的一个:`(列出如"项目评审 - 4月8日 14:00 / 项目评审 - 4月15日 14:00",最多 4 条;超出时展示前 4 条并提示用户缩小关键词) |
91
+ | 浏览型 - 搜索返回多个结果 | 自动翻页拉全部统计总数;按时间排序,对前 10 条 `meeting get` 反查参会人姓名,顺序输出主题/时间/参会人(禁止 markdown 表格),超过 10 条只展示前 10 条 + "还有 N 条,需要查看更多吗?" |
92
+
93
+ ## 搜索结果的下一步
94
+
95
+ 搜索结果中的 `meeting_id` 可用于后续操作:
96
+
97
+ - 获取详情:`wecom-cli meeting get --json '{"meeting_ids": [{"meeting_id": "<meeting_id>"}]}'`
98
+ - 取消会议:参见 [meeting-cancel](meeting-cancel.md)
99
+
100
+ ## 示例请求
101
+
102
+ **基础搜索**:
103
+ ```json
104
+ {
105
+ "keywords": ["项目评审"],
106
+ "limit": 20
107
+ }
108
+ ```
109
+
110
+ **带时间范围搜索**:
111
+ ```json
112
+ {
113
+ "keywords": ["项目评审"],
114
+ "begin_time": "2026-03-01 00:00:00",
115
+ "end_time": "2026-03-31 23:59:59",
116
+ "limit": 20
117
+ }
118
+ ```
119
+
120
+ **翻页请求**:
121
+ ```json
122
+ {
123
+ "keywords": ["项目评审"],
124
+ "cursor": "<next_cursor>",
125
+ "limit": 20
126
+ }
127
+ ```
128
+
129
+ ## 典型场景
130
+
131
+ ### 1. 定位型 - 搜索特定会议
132
+
133
+ ```
134
+ 用户:帮我找找上周的周会
135
+ → 意图判断:定位型(想找某个特定会议)
136
+ → 提取关键词"周会",不追问时间,直接搜索
137
+ → 调用 meeting search(keywords=["周会"],limit=20)
138
+ → 找到 2 条匹配,用文字让用户确认:搜索到多个匹配会议,请选择要操作的一个?(列出:周会 - 4月8日 10:00 / 周会 - 4月1日 10:00)
139
+ → 用户选择 → 调用 meeting get 获取详情展示
140
+ ```
141
+
142
+ ### 2. 浏览型 - 查看全部匹配会议
143
+
144
+ ```
145
+ 用户:我有哪些项目评审会议
146
+ → 意图判断:浏览型("有哪些"表述,想查看全部列表)
147
+ → 提取关键词"项目评审",调用 meeting search(keywords=["项目评审"],limit=20)
148
+ → 返回 15 条,has_more: true
149
+ → 自动携带 next_cursor 继续请求下一页,循环至 has_more: false,合并统计总条数(共 15 条)
150
+ → 按开始时间排序,对前 10 条调用 meeting get 反查参会人姓名
151
+ → 顺序输出每条会议(主题/时间/参会人,禁止 markdown 表格),超过 10 条只展示前 10 条:
152
+
153
+ 1. 项目评审周会
154
+ 时间:11月13日(周三)15:00-16:00
155
+ 参会人:张三、李四
156
+
157
+ 2. 项目评审阶段汇报
158
+ 时间:11月25日(周一)16:00-17:00
159
+ 参会人:王五、赵六
160
+ ...
161
+ 还有 5 条,需要查看更多吗?
162
+ ```
163
+
164
+ ### 3. 搜索无结果
165
+
166
+ ```
167
+ 用户:找一下项目启动会
168
+ → 调用 meeting search(keywords=["项目启动会"],limit=20)→ 无结果
169
+ → 软性兜底:「会」在企微可能是日程,主动 `读取 wecomcli-calendar 技能` 用关键词"项目启动会"在日程里搜一把
170
+ - 日程命中 → 一并呈现并说明:在「日程」里找到了"项目启动会"(这是一条日程,未关联在线会议链接),随后展示日程摘要
171
+ - 日程也无果 → 告知用户:会议和日程里都未找到"项目启动会"。
172
+ 建议:1) 尝试缩短关键词(如"启动会")2) 确认名称是否正确
173
+ ```
@@ -0,0 +1,217 @@
1
+ # 操作参考:更新会议
2
+
3
+ 更新已创建会议的信息,包括主题、时间、参会人、地点等。**写操作**,参数就绪后直接执行。不预先按"是否本人创建"拦截,能否修改由接口返回结果判断。**暂不支持更新周期会议**,识别到周期会议时应告知用户并引导其在企业微信客户端操作(见下文工作流与约束)。
4
+
5
+ ## 命令
6
+
7
+ ```bash
8
+ wecom-cli meeting update --json '{...}'
9
+ ```
10
+
11
+ ## 请求参数
12
+
13
+ | 字段 | 类型 | 必填 | 说明 |
14
+ | ---- | ---- | ---- | ---- |
15
+ | `meeting_id` | string | 是 | 会议 ID(来自 `list`/`search` 返回的 `meeting_id` 字段,长字符串,非 9 位会议号) |
16
+ | `subject` | string | 否 | 新的会议主题 |
17
+ | `begin_time` | string | 否 | 新的开始时间(格式 YYYY-MM-DD HH:mm:ss) |
18
+ | `end_time` | string | 否 | 新的结束时间(格式 YYYY-MM-DD HH:mm:ss) |
19
+ | `add_attendees` | array | 否 | 新增参会人列表,对象数组,格式 `[{"userid": "woxxx"}]` |
20
+ | `remove_attendees` | array | 否 | 移除参会人列表,对象数组,格式 `[{"userid": "woxxx"}]` |
21
+ | `location` | string | 否 | 新的会议地点(文本)。用户给的是**会议室**时须走 `meeting_room_id` 改订(见工作流「会议室变更解析」),不要把会议室名仅写进 `location`;用户给的是**非会议室的普通文本地点**时直接写入 `location` |
22
+ | `meeting_room_id` | string | 否 | 会议室 ID,传入预定(改订)会议室。用户要更换会议室时,须先经 `rooms search`(会议室查询接口定义在 `读取 wecomcli-calendar 技能` 的 [会议室查询参考](../../wecomcli-calendar/references/calendar-meeting-room.md))查询新会议室状态,确认`status=bookable` 可用后才传入新的 `meeting_room_id`;ID 仅工具链使用,禁止出现在用户回复正文 |
23
+ | `description` | string | 否 | 新的会议备注 |
24
+
25
+ ## 返回字段
26
+
27
+ | 字段 | 说明 |
28
+ | ---- | ---- |
29
+ | `meeting_id` | 会议 ID |
30
+ | `sub_meeting_id` | 子会议 ID(周期会议时返回) |
31
+ | `subject` | 更新后的会议主题 |
32
+ | `begin_time` | 更新后的开始时间 |
33
+ | `end_time` | 更新后的结束时间 |
34
+ | `attendees` | 更新后的完整参会人列表,扁平对象数组,每项含 `userid` / `name` / `is_external`;内部成员与外部联系人统一用 `userid`,由 `is_external` 区分。展示取 `name`,禁止展示 userid |
35
+ | `attendees_count` | `attendees` 数组元素数量 |
36
+ | `location` | 更新后的会议地点 |
37
+ | `description` | 更新后的会议备注 |
38
+
39
+ ## 约束
40
+
41
+ - **不预先按"是否本人创建"拦截修改**,直接执行 `update`,能否修改由接口返回结果判断:返回更新后的字段即成功;返回权限类错误则说明当前用户无权修改,告知用户并建议联系会议发起人
42
+ - 只需传入要修改的字段,未传入字段保持原值不变
43
+ - **周期会议不支持更新**:检测到目标会议 `repeat_rule` 非空时,直接告知用户目前暂不支持更新周期会议,引导其在企业微信客户端操作,禁止逐场 `update` 拼凑或改为取消重建等变通方式
44
+ - 修改时间时 `end_time` 必须晚于 `begin_time`
45
+ - **更换会议室**:用户要换会议室时,`meeting_room_id` 必须先经 `rooms search` 查询、确认新会议室 `status=bookable` 可用后才传入;禁止跳过查询凭记忆/猜测直接传,禁止把会议室名仅写进 `location`(那样不会真正占用会议室)。会议室查询接口须 `读取 wecomcli-calendar 技能` 的 [会议室查询参考](../../wecomcli-calendar/references/calendar-meeting-room.md)
46
+ - userid(前缀为 `wo`)不接受姓名直接传入;用户提供的是姓名时通过 `读取 wecomcli-contact 技能` 解析为 userid,禁止把姓名当 userid 拼接,禁止凭记忆或猜测编造
47
+
48
+ ## 工作流
49
+
50
+ ```
51
+ 用户发起更新意图
52
+ |
53
+ +-- 定位目标会议
54
+ | +-- 有关键词 → meeting search(不追问时间)
55
+ | +-- 有时间信息 → meeting list 按时间范围查询
56
+ | +-- 都没有 → 用文字询问引导用户补全信息
57
+ |
58
+ +-- 匹配结果处理
59
+ | +-- 唯一匹配 → 继续
60
+ | +-- 多条匹配 → 用文字让用户选择:
61
+ | | 文字提问:"找到多个匹配会议,请选择要修改的一个:"
62
+ | | 列出候选(如"项目评审 - 4月8日 14:00 / 项目评审 - 4月15日 14:00",最多 4 条)
63
+ | +-- 无匹配 → 建议修改关键词或扩大时间范围重试
64
+ |
65
+ +-- 判断是否周期会议(依据 meeting get 返回的 repeat_rule)
66
+ | +-- repeat_rule 为空 → 非周期会议,直接收集修改内容,执行更新
67
+ | +-- repeat_rule 非空 → 周期会议,终止操作,用文字告知用户:"目前暂不支持更新周期会议,请在企业微信客户端对该会议进行修改",禁止逐场 update 拼凑或改为取消重建
68
+ |
69
+ +-- 参会人变更解析(如有)
70
+ | +-- 上下文中已有合法 userid(`wo` 前缀)→ 直接使用,跳过搜索
71
+ | +-- 用户提供的是姓名 → 通过 `读取 wecomcli-contact 技能` 批量搜索所有新增/移除的人名
72
+ | | +-- 某关键词唯一匹配 → 直接使用,无需确认
73
+ | | +-- 某关键词多个匹配 → 用文字让用户选择(列出姓名 + 部门):
74
+ | | | 文字提问:"搜索到多个「{姓名}」,请确认要操作哪一位?"
75
+ | | | 列出候选(如"张三 - 产品部 - 产品经理 / 张三 - 技术部 - 前端工程师",最多 4 条;超出取前 4 条并提示用户可进一步缩小范围)
76
+ | | +-- 某关键词无结果 → 用文字提示用户确认人名是否正确,停止执行
77
+ | +-- 汇总全部 userid → 组装 add_attendees / remove_attendees(对象数组 [{"userid": "woxxx"}])
78
+ |
79
+ | > **关键约束**:只要存在多个候选人,必须等用户选择后才能继续,不得自动选取任何一个。
80
+ |
81
+ +-- 会议室变更解析(如用户要换会议室)
82
+ | +-- 确定查询时段:用会议起止时间;若本次同时改时间,用改后的新时段
83
+ | +-- 读取 wecomcli-calendar 技能的 [会议室查询参考](../../wecomcli-calendar/references/calendar-meeting-room.md) → rooms search 查新会议室状态
84
+ | | +-- target 中有 bookable 项 → 取该项 target[].room.meeting_room_id(多个 bookable 时用文字让用户选)
85
+ | | +-- 指定会议室 target=[](查无此名)/ 命中项均 unavailable(被占)→ 必须先告知用户"未查到/无法预订你指定的『xxx』会议室",
86
+ | | | 再用文字让用户决定是否改订其他会议室或换时间;禁止用其他名称会议室静默替代(候选仅 1 个也须用户确认)
87
+ | | +-- 未指定具体会议室(target=[]):
88
+ | | | +-- recommendations 多个 → 用文字让用户选(禁止自动取第一个)
89
+ | | | +-- recommendations 仅 1 个 → 可直接使用
90
+ | | | +-- recommendations = [] → 告知无可用会议室,引导换楼或换时间
91
+ | +-- 拿到用户确认的、可用的 meeting_room_id → 传入 update
92
+ | > **关键约束**:新会议室未经 rooms search 确认 bookable 之前,禁止传 meeting_room_id 调 update。
93
+ |
94
+ +-- 时间/参会人忙闲检查(改时间或加参会人时必做)[REQUIRED]
95
+ | +-- 触发条件:本次修改了 begin_time/end_time,或新增了参会人(add_attendees)
96
+ | +-- 查询对象与时段:核心原则是排除"因本会议占用而必然忙碌"的时段,避免自冲突误报 [CRITICAL]
97
+ | | ——【已在本会议中的人】(自己/创建者 + 已有参会人)只查"与本会议当前时段【不重叠】"的时间,【新增参会人】才查完整目标时段。分三种情况:
98
+ | | +-- ① 只加人、不改时间 → 仅对【新增参会人 add_attendees 中的内部成员】查【会议原时段】;
99
+ | | | 绝不把当前用户(自己/创建者)及已有参会人纳入——他们正被本会议占用、必然显示"忙",是误报
100
+ | | | (用户本意就是让别人加入自己这个已定时间的会议)
101
+ | | +-- ② 改时间且新旧时段【不重叠】(平移/改期,如 15:00→17:00)→ 对【改后仍需参加的内部成员(含自己)+ 新增内部参会人】查【完整新时段】
102
+ | | | (新旧无交集,现有参会人查新时段不会撞上本会议原时段,可正常纳入自己/已有参会人)
103
+ | | +-- ③ 改时间且新旧时段【有重叠】(延长/提前等,新时段含部分原时段)→ 分两类查:
104
+ | | | · 新增内部参会人:查【完整新时段】
105
+ | | | · 现有内部参会人及自己:只查【新时段去掉与原时段重叠后剩下的增量段】
106
+ | | | (如 15:00-16:00 延到 15:00-17:00 只查 16:00-17:00;15:00-16:00 提前到 14:00-16:00 只查 14:00-15:00);
107
+ | | | 增量段为空(如仅缩短时间)则现有参会人及自己无需查
108
+ | +-- 按上面裁剪后的查询对象执行;裁剪后查询对象为空、或仅剩外部联系人(wm,忙闲不可查)时才跳过——不要因为"只有自己"就跳过(②/③ 里自己在新时段/增量段内仍要查,避免约到自己已占用的时段)
109
+ | +-- 忙闲接口不在本技能 → 读取 wecomcli-calendar 技能的 [忙闲查询参考](../../wecomcli-calendar/references/calendar-freebusy.md),按上面圈定的查询对象 + 时段调 free list(窗口 ≤ 24h)
110
+ | | +-- 无冲突 → 继续执行 update
111
+ | | +-- 有人占线 → 用文字让用户二选一(禁止自行改期):
112
+ | | | 文字提问:"该时间段{姓名}有冲突,如何处理?(请回复:坚持这个时间 / 换一个时间)"
113
+ | | +-- 接口失败 → 告知忙闲暂不可用,确认时间后继续,不阻塞
114
+ |
115
+ +-- 执行 update(不论会议由谁创建,都直接执行,不提前拒绝)→ 依返回结果判断:
116
+ +-- 返回更新后的字段 → 修改成功,展示更新后的会议摘要
117
+ +-- 返回权限类错误 → 说明当前用户无权修改该会议,告知用户并建议联系会议发起人
118
+ ```
119
+
120
+ ### 异常路径
121
+
122
+ | 异常情况 | 处理方式 |
123
+ |---------|---------|
124
+ | 接口返回无权修改(非发起人) | 直接执行 update 后依返回判断;返回权限错误时告知用户无权操作,建议联系会议发起人 |
125
+ | 周期会议更新 | 目前暂不支持更新周期会议,告知用户并引导其在企业微信客户端对该会议进行修改 |
126
+ | 修改时间冲突(end ≤ begin) | 提示用户结束时间必须晚于开始时间,请重新输入 |
127
+ | wecomcli-contact 技能搜索无结果 | 提示用户确认人名是否正确,或尝试其他搜索词 |
128
+ | wecomcli-contact 技能返回多个候选人 | 用文字询问用户(列出候选姓名 + 部门),等待用户选择后汇总继续 |
129
+ | 换会议室时新会议室不可用 | `rooms search` 返回 `unavailable`/`not_found`:用文字让用户从 `recommendations` 候选中选,或引导换楼(`expand_to_other_buildings`)/换时间;禁止传不可用的 `meeting_room_id` 调 update |
130
+ | 更新接口返回错误 | 检查参数格式,重新阅读本文档确认用法 |
131
+
132
+ ## 示例请求
133
+
134
+ **修改普通会议时间和主题**:
135
+ ```json
136
+ {
137
+ "meeting_id": "<meeting_id>",
138
+ "subject": "产品需求评审(更新)",
139
+ "begin_time": "2026-04-08 15:00:00",
140
+ "end_time": "2026-04-08 16:00:00"
141
+ }
142
+ ```
143
+
144
+ **新增/移除参会人**:
145
+ ```json
146
+ {
147
+ "meeting_id": "<meeting_id>",
148
+ "add_attendees": [{"userid": "woxxxc"}],
149
+ "remove_attendees": [{"userid": "woxxxb"}]
150
+ }
151
+ ```
152
+
153
+ **更换会议室**(`meeting_room_id` 须先经 `rooms search` 确认新会议室 `status=bookable`):
154
+ ```json
155
+ {
156
+ "meeting_id": "<meeting_id>",
157
+ "meeting_room_id": "mrmxxxx"
158
+ }
159
+ ```
160
+
161
+ ## 典型场景
162
+
163
+ ### 1. 修改会议时间
164
+
165
+ ```
166
+ 用户:把明天下午3点的评审会推迟1小时
167
+ → 调用 meeting search(keywords=["评审"])→ 获取 meeting_id
168
+ → 调用 meeting get → 判断非周期会议(不做是否本人创建的前置拦截)
169
+ → 组装参数:begin_time="2026-04-08 16:00:00",end_time="2026-04-08 17:00:00"
170
+ → 调用 update → 展示更新结果
171
+ ```
172
+
173
+ ### 2. 添加参会人
174
+
175
+ ```
176
+ 用户:把王五加到明天的评审会
177
+ → 调用 meeting search → 获取 meeting_id
178
+ → 通过 wecomcli-contact 技能搜索「王五」→ 返回 2 个候选
179
+ → 用文字询问:搜索到多个「王五」,请确认要邀请哪一位?(列出:王五 - 市场部 - 市场专员 / 王五 - 技术部 - 前端工程师)
180
+ → 用户选择后,获得对应 userid
181
+ → 调用 update,add_attendees=[{"userid": "woxxxe"}]
182
+ → 展示更新后完整参会人列表
183
+ ```
184
+
185
+ ### 3. 修改周期会议(不支持)
186
+
187
+ ```
188
+ 用户:下周一的周会改到下午3点,只改这一次
189
+ → 调用 meeting search(keywords=["周会"])→ 找到周期会议
190
+ → 调用 meeting get → repeat_rule 非空(周期会议)
191
+ → 不调用 update → 告知:目前暂不支持更新周期会议,请在企业微信客户端对该会议进行修改
192
+ ```
193
+
194
+ ### 4. 更换会议室
195
+
196
+ ```
197
+ 用户:把明天评审会的会议室换到 1608
198
+ → meeting search/list 拿 meeting_id(及会议起止时间)→ get 拿会议详情(不做是否本人创建的前置拦截)
199
+ → 读取 wecomcli-calendar 技能的会议室查询参考,用会议时段 + room_keyword="1608" 调 rooms search
200
+ → target 中有 bookable 项 → 取其 target[].room.meeting_room_id
201
+ → 调用 update,meeting_room_id="mrmxxxx"
202
+ → 展示更新后会议摘要(只露会议室 name)
203
+
204
+ 用户:明天的评审会换个会议室
205
+ → 拿 meeting_id 与时段 → rooms search(未指定具体会议室,target=[])
206
+ → recommendations 多个 → 用文字让用户选(展示 name + 楼层 + 容量)
207
+ → 用户选定后取其 meeting_room_id → update
208
+ ```
209
+
210
+ ## 参考
211
+
212
+ - [wecomcli-meeting](../SKILL.md) — 会议技能主文档
213
+ - [meeting-search](meeting-search.md) — 搜索会议(获取 meeting_id)
214
+ - [meeting-list](meeting-list.md) — 查看会议列表
215
+ - [meeting-cancel](meeting-cancel.md) — 取消会议
216
+ - `读取 wecomcli-calendar 技能` 的 [忙闲查询参考](../../wecomcli-calendar/references/calendar-freebusy.md) — 改时间/加参会人时查共同空闲
217
+ - `读取 wecomcli-calendar 技能` 的 [会议室查询参考](../../wecomcli-calendar/references/calendar-meeting-room.md) — 更换会议室时确认新会议室 `status=bookable`
@@ -0,0 +1,200 @@
1
+ ---
2
+ name: wecomcli-message
3
+ description: 查询当前可以发送消息的聊天会话范围,并向会话列表中的单聊或群聊发送文本、Markdown、图片、文件、语音、视频消息。用户要求“给某人发消息”“在某个群里通知”“给最近会话发消息”或“把图片/文件/语音/视频发到企业微信”时使用。
4
+ metadata:
5
+ requires:
6
+ bins: ["wecom-cli"]
7
+ ---
8
+
9
+ # 企业微信发送消息
10
+
11
+ > 执行任何 `wecom-cli` 命令前,必须先读取并完成 `wecomcli-shared` 技能的公共前置检查。
12
+
13
+ 1. 可以向授权人发送消息。
14
+ 2. 可以向授权人以外的、机器人最近有消息往来的聊天会话(单聊和群聊)发送消息。
15
+
16
+ ## 适用范围
17
+
18
+ ### 适用
19
+
20
+ - 适用于给授权人发消息,使用 `wecom-cli identity whoami` 获取授权人ID,可作为 `chat_id` 使用,无需调用 `sessions list`。
21
+ - 适用于查询当前有权限发送消息的聊天会话范围并给这些范围中的成员或群聊发送 Markdown 消息、图片、文件、AMR 语音或视频
22
+
23
+ ### 不适用
24
+
25
+ - 发送对象不是授权人且不在本次 `sessions list` 返回结果中 → 告知用户当前只能向最近活跃的会话或授权人发送
26
+
27
+ ## 技能依赖
28
+
29
+ 调用依赖技能前,必须先完整读取对应 `SKILL.md`。
30
+
31
+ | 依赖技能 | 触发场景 | 数据流向 |
32
+ |---|---|---|
33
+ | `wecomcli-media` | 发送图片、文件、语音或视频时只有本地文件路径,没有可直接复用的 `media_id` | 包含媒体上传接口,如没有已有的 `media_id`,必须先阅读该技能获取 `media_id`,上传时传入的 `type` 应和发送时的`msg_type` 对齐|
34
+
35
+ ## 获取能发送消息的会话列表
36
+
37
+ ### 命令
38
+
39
+ ```bash
40
+ wecom-cli message aibot sessions list
41
+ ```
42
+
43
+ ### 返回
44
+
45
+ | 字段 | 类型 | 说明 |
46
+ |---|---|---|
47
+ | `sessions` | array | 会话列表,按最后一条消息时间从新到旧排序,具体数量以实际回包为准 |
48
+ | `sessions[].chat_id` | string | 会话 ID |
49
+ | `sessions[].chat_name` | string | 群名称或单聊名称 |
50
+ | `sessions[].chat_type` | string | `single` 单聊或 `group` 群聊 |
51
+ | `sessions[].last_msg_time` | string | 最后一条消息时间,格式 `YYYY-MM-DD HH:MM:SS` |
52
+ | `sessions_count` | integer | `sessions` 数组元素数量 |
53
+
54
+ ### `chat_id` 来源
55
+
56
+ 向授权人以外的用户发送消息,调用 `wecom-cli message aibot send` 前,需要先调用一次 `sessions list`,然后从本次返回的 `sessions[]` 中选定目标项,把该项的 `chat_id` 原样复制到 `send.chat_id`。
57
+
58
+ 以下值都不能直接作为 `send.chat_id`:
59
+
60
+ - 用户输入的 ID
61
+ - 之前轮次或历史上下文保存的 `chat_id`
62
+ - `wecomcli-contact` 返回的 `userid`
63
+ - 根据姓名、群名或其他字段自行构造的值
64
+
65
+ 这些值最多只能作为匹配线索;最终发送参数必须重新取自本次 `sessions list` 的匹配项。
66
+
67
+ ### 目标会话匹配
68
+
69
+ - **聊天名称**:在本次 `sessions[]` 中按非空 `chat_name` 精确匹配;不能精确匹配需要向用户反问确认发送目标,唯一命中时从匹配项复制 `chat_id`。
70
+ - **最近第一个/最近某个会话**:按 `sessions[]` 原始顺序选择用户明确指定的项。
71
+ - **用户提供 ID**:只能与本次 `sessions[].chat_id` 做完全相等校验;命中后仍从匹配项复制 `chat_id`,不能直接复用用户输入值。
72
+
73
+ 匹配结果处理:
74
+
75
+ - 唯一匹配时继续发送。
76
+ - 多个聊天会话候选时,按返回顺序展示聊天名和最后消息时间,让用户选择。
77
+ - 用户完成选择后,必须重新调用 `sessions list`,再用选定对象匹配当次返回值。
78
+ - 无匹配时停止发送,如实告知目标不在最近 10 个会话中;不要接受外部 `chat_id` 绕过限制。
79
+ - `sessions_count=0` 时停止发送,告知当前没有可发送的最近会话。
80
+ - 展示会话列表时保持接口原始顺序;展示名称和时间,不展示内部 `chat_id`。
81
+
82
+ ## 发送消息
83
+
84
+ ### 前置条件
85
+
86
+ 调用本接口前必须完成以下步骤:
87
+
88
+ 1. 根据发送对象选择调用 `wecom-cli message aibot sessions list`获取 `chat_id` 或 `wecom-cli identity whoami` 获取授权人ID。
89
+ 2. 在本次列表中唯一匹配目标。
90
+ 3. 如果发送授权人以外的对象,从列表中匹配项原样复制 `sessions[].chat_id`。
91
+ 4. 目标是媒体消息时,再准备对应的 `media_id`。
92
+
93
+ 在目标会话匹配成功前,不上传媒体,也不调用 `send`。
94
+
95
+ ### 命令
96
+
97
+ ```bash
98
+ wecom-cli message aibot send --json '<JSON 参数>'
99
+ ```
100
+
101
+ ### 公共参数
102
+
103
+ | 字段 | 类型 | 必填 | 说明 |
104
+ |---|---|:---:|---|
105
+ | `chat_id` | string | 是 | 必须取自 `wecom-cli identity whoami` 或当前发送流程中刚调用的 `sessions list` 返回的目标 `sessions[].chat_id` |
106
+ | `msg_type` | string | 是 | `markdown` / `image` / `file` / `voice` / `video` |
107
+ | `markdown` | object | 条件必填 | 仅 `msg_type="markdown"` 时传 |
108
+ | `image` | object | 条件必填 | 仅 `msg_type="image"` 时传 |
109
+ | `file` | object | 条件必填 | 仅 `msg_type="file"` 时传 |
110
+ | `voice` | object | 条件必填 | 仅 `msg_type="voice"` 时传 |
111
+ | `video` | object | 条件必填 | 仅 `msg_type="video"` 时传 |
112
+
113
+ 每次请求必须且只能携带一个与 `msg_type` 同名的内容对象。不要传空对象,也不要同时传多个消息对象。
114
+
115
+ ### Markdown 消息
116
+
117
+ `markdown.content` 必填,最长 20480 UTF-8 字节。普通文本也按 Markdown 发送。
118
+
119
+ ```bash
120
+ wecom-cli message aibot send --json '{
121
+ "chat_id": "<本次 sessions[].chat_id>",
122
+ "msg_type": "markdown",
123
+ "markdown": {
124
+ "content": "<markdown 消息内容>"
125
+ }
126
+ }'
127
+ ```
128
+
129
+ ### 图片消息
130
+
131
+ `image.media_id` 必填,必须由媒体上传接口以 `type=image` 上传获得。
132
+
133
+ ```bash
134
+ wecom-cli message aibot send --json '{
135
+ "chat_id": "<本次 sessions[].chat_id>",
136
+ "msg_type": "image",
137
+ "image": {
138
+ "media_id": "<media_id>"
139
+ }
140
+ }'
141
+ ```
142
+
143
+ ### 文件消息
144
+
145
+ `file.media_id` 必填,必须由媒体上传接口以 `type=file` 上传获得;文件名取上传时的原始文件名。
146
+
147
+ ```bash
148
+ wecom-cli message aibot send --json '{
149
+ "chat_id": "<本次 sessions[].chat_id>",
150
+ "msg_type": "file",
151
+ "file": {
152
+ "media_id": "<media_id>"
153
+ }
154
+ }'
155
+ ```
156
+
157
+ ### 语音消息
158
+
159
+ `voice.media_id` 必填,必须由媒体上传接口以 `type=voice` 上传获得;源文件仅支持 AMR 格式,不能只改扩展名冒充 AMR。
160
+
161
+ ```bash
162
+ wecom-cli message aibot send --json '{
163
+ "chat_id": "<本次 sessions[].chat_id>",
164
+ "msg_type": "voice",
165
+ "voice": {
166
+ "media_id": "<media_id>"
167
+ }
168
+ }'
169
+ ```
170
+
171
+ ### 视频消息
172
+
173
+ | 字段 | 必填 | 说明 |
174
+ |---|:---:|---|
175
+ | `video.media_id` | 是 | 由媒体上传接口以 `type=video` 上传获得 |
176
+ | `video.title` | 否 | 最长 128 UTF-8 字节;省略时使用上传时的原始文件名 |
177
+ | `video.description` | 否 | 最长 512 UTF-8 字节;省略时不展示描述 |
178
+
179
+ ```bash
180
+ wecom-cli message aibot send --json '{
181
+ "chat_id": "<本次 sessions[].chat_id>",
182
+ "msg_type": "video",
183
+ "video": {
184
+ "media_id": "<media_id>",
185
+ "title": "产品演示",
186
+ "description": "本周版本的核心功能演示"
187
+ }
188
+ }'
189
+ ```
190
+
191
+ 用户没有提供视频标题或描述时直接省略对应字段,不传空字符串,也不追问非必填字段。
192
+
193
+ ## 关键约束
194
+
195
+ - 用户明确要求发送且目标与内容完整时直接执行,不重复追问确认;缺少目标、内容或本地文件时只追问缺失项。
196
+ - 连续发送多条时,不用每次 `send` 前都重新调用 `sessions list` 或 `wecom-cli identity whoami`,但连续发送中途上下文发生压缩时重新调用确保 `chat_id` 正确。
197
+ - `chat_id`、`userid`、`media_id` 都是内部调用值,禁止面向用户展示。
198
+ - Markdown 正文、视频标题和描述限制按 UTF-8 字节数计算;超限时不静默截断,请用户缩短或明确同意拆分。
199
+ - 发送成功后只说明目标和消息类型,不编造消息 ID。
200
+ - 接口失败时如实转达错误,不使用 curl / Python 等方式绕过 `wecom-cli`。
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: wecomcli-shared
3
+ description: wecom-cli 业务技能的公共前置检查、获取机器人及授权真人身份,以及通用输出约束。任何 wecomcli-* 技能准备执行 wecom-cli 命令前,都必须同时读取本技能,检查 CLI 是否安装、版本是否不低于 1.1.0,以及企业微信凭证是否已授权;仅在缺失、版本过低或未授权时执行安装或初始化。本技能还定义所有技能通用的 ID 类字段禁止外露约束。本技能不处理具体业务请求。
4
+ ---
5
+
6
+ # wecom-cli 公共前置检查
7
+
8
+ 本技能提供所有 `wecomcli-*` 业务技能共用的 CLI 安装、版本与授权检查,以及通用输出约束。**每次准备执行任意 `wecom-cli` 命令前,先完成本技能;检查通过后,再回到对应业务技能执行。**
9
+
10
+ > 本技能不能代替具体业务技能。处理联系人、文档、表格、日程、会议、待办、邮件、微盘、消息或媒体请求时,必须同时读取对应业务技能。
11
+
12
+ ## Step 1:检查 CLI 安装与版本
13
+
14
+ ```bash
15
+ wecom-cli --version
16
+ ```
17
+
18
+ - 命令成功,且输出中的版本号不低于 `1.1.0` → 继续 Step 2。
19
+ - 命令不存在、执行报错或版本号低于 `1.1.0` → 执行安装/升级:
20
+
21
+ ```bash
22
+ npm install -g @wecom/cli
23
+ ```
24
+
25
+ 安装完成后重新执行 `wecom-cli --version`;仍失败或版本仍低于 `1.1.0` 时停止业务操作,并把错误告知用户。
26
+
27
+ ## Step 2:检查授权状态
28
+
29
+ ```bash
30
+ wecom-cli auth show --status
31
+ ```
32
+
33
+ - 输出 `authorized` → 前置检查完成,可以执行具体业务命令。
34
+ - 输出 `unauthorized` → 执行 Step 3。
35
+ - 命令报错或输出不是上述状态 → 停止业务操作,并把错误告知用户,不要猜测授权状态。
36
+
37
+ ## Step 3:初始化凭证(仅未授权时)
38
+
39
+ ```bash
40
+ wecom-cli auth init --noninteractive
41
+ ```
42
+
43
+ 该命令会展示授权链接和二维码,并等待用户使用企业微信扫码。授权成功后命令自动退出,仅需初始化一次。
44
+
45
+ 初始化完成后重新执行:
46
+
47
+ ```bash
48
+ wecom-cli auth show --status
49
+ ```
50
+
51
+ 仅当输出 `authorized` 时,才能继续执行具体业务命令。
52
+
53
+ ## 通用输出约束:ID 类字段禁止外露
54
+
55
+ 本约束对所有 `wecomcli-*` 技能生效,优先级高于各业务技能的输出格式,且不因用户主动索要而放宽。
56
+
57
+ - **禁止**:你的最终回复禁止出现 `userid` / `open_vid` / `department_id` / `chat_id` 等 ID 标识。凡是接口返回的内部标识(含 `mail_id` / `media_id` / `file_id` / `space_id` / `folder_id` / `docid` / `content_id` / `msg_id` / `cursor` / `next_cursor` 等,命名上以 `_id` 结尾或语义上属于机器标识的字段一律视为 ID)都只能在内部流转,用于后续接口调用。
58
+ - **必须**:你的思考过程和最终回复必须使用可读名称,如 `name` / `username` / `external_username` / 部门名 / 邮箱 / `subject` / `doc_name` / `chat_name` / `title` 等 `tool_result` 返回的内容。
59
+ - 接口只返回 ID 而没有可读名称时,先调用对应技能(如 `wecomcli-contact` 解析人员)换取可读名称;确实无法换取时,用自然语言描述该对象(如「上一封日报邮件」「你刚上传的那个文件」)来指代,禁止退化为展示 ID。
60
+ - 需要用户在多个候选中选择时,用序号 + 可读信息(名称 / 主题 / 时间 / 路径等)构造候选列表,禁止用 ID 作为区分依据让用户辨认。
61
+ - 用户直接要求「把 ID 给我」「打印 mail_id」时,说明该标识属于内部字段不便提供,并改用可读信息或继续帮其完成实际操作。
62
+ - 可读链接(如文档 `doc_url`、微盘分享链接)不属于本约束限制范围,可按各业务技能规定正常展示,即使链接本身包含标识字符串。
63
+
64
+ ## 执行规则
65
+
66
+ - 已安装、版本达标且已授权时,不重复安装或初始化。
67
+ - 安装、升级、初始化或复查失败时,不执行后续业务命令。
68
+ - 本技能不定义任何联系人、文档、表格、日程、会议、待办、邮件、微盘、消息或媒体接口参数;具体命令必须回到对应业务技能读取。
69
+ - 执行任何业务命令并组织回复时,同时遵守上方「通用输出约束:ID 类字段禁止外露」。
70
+
71
+ ## 获取个人身份
72
+
73
+ 如果操作流程必须获取机器人或授权人身份(姓名、userid等),需要调用 `wecom-cli identity whoami` 获取。