@wecom/wecom-openclaw-plugin 2026.4.23-beta.0 → 2026.4.2201

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.
@@ -341,11 +341,11 @@ async function routeAndDispatchMessage(params) {
341
341
  ctx: ctxPayload,
342
342
  cfg: config,
343
343
  replyOptions: {
344
- // 打印 LLM 返回的原始分片内容(在 openclaw 核心对 MEDIA: 指令解析之前),
345
- // 用于排查流式分片导致 MEDIA 指令被切断、识别丢失等问题
346
- // onPartialReply: (payload: unknown) => {
347
- // runtime.log?.(`[openclaw -> plugin][partial] payload=${JSON.stringify(payload)}`);
348
- // },
344
+ // 打印 LLM 返回的原始分片内容(在 openclaw 核心对 MEDIA: 指令解析之前),
345
+ // 用于排查流式分片导致 MEDIA 指令被切断、识别丢失等问题
346
+ onPartialReply: (payload) => {
347
+ runtime.log?.(`[openclaw -> plugin][partial] payload=${JSON.stringify(payload)}`);
348
+ },
349
349
  },
350
350
  dispatcherOptions: {
351
351
  onReplyStart: async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wecom/wecom-openclaw-plugin",
3
- "version": "2026.4.23-beta.0",
3
+ "version": "2026.4.2201",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -51,7 +51,6 @@ description: 企业微信文档管理技能。支持企业微信文档、智能
51
51
  | errcode | errmsg | 含义 | 处理方式 |
52
52
  |---------|--------|------|----------|
53
53
  | `851002` | `incompatible doc type` | 文档品类与所调用的接口不匹配 | 根据文档 URL 重新确认品类(参见上方「URL 品类识别与接口路由」表),然后使用该品类对应的正确接口重试 |
54
- | `851003` | `no authority` | 无权限调用该接口,**智能表格写入场景**下通常是企业可见范围 > 10 人的规模限制 | 若发生在需要写入数据的场景,引导用户走 Webhook 兜底方案,详见 [webhook-fallback.md](../wecom-smartsheet-data/references/webhook-fallback.md);其他接口则按权限问题排查 |
55
54
 
56
55
  ## 文档
57
56
 
@@ -47,8 +47,6 @@ description: 企业微信智能表格数据(记录)管理技能。提供智
47
47
 
48
48
  各字段类型的值格式参见 [单元格值格式参考](references/cell-value-formats.md)。
49
49
 
50
- > ⚠️ 若返回 `errcode: 851003` 或 `errmsg` 包含 `no authority`(通常是企业可见范围 > 10 人的规模限制),切换到 Webhook 兜底方案,详见 [webhook-fallback.md](references/webhook-fallback.md)。
51
-
52
50
  ### smartsheet_update_records
53
51
 
54
52
  更新一行或多行记录,单次建议在 500 行内。需提供 record_id(通过 `smartsheet_get_records` 获取)。支持通过 `key_type` 指定 values 的 key 使用字段标题或字段 ID:
@@ -60,8 +58,6 @@ description: 企业微信智能表格数据(记录)管理技能。提供智
60
58
 
61
59
  **注意**:创建时间、最后编辑时间、创建人、最后编辑人字段不可更新。
62
60
 
63
- > ⚠️ 若返回 `errcode: 851003` 或 `errmsg` 包含 `no authority`(通常是企业可见范围 > 10 人的规模限制),切换到 Webhook 兜底方案,详见 [webhook-fallback.md](references/webhook-fallback.md)。注意 Webhook 只能更新通过 Webhook 写入的记录,人工创建的记录无法更新。
64
-
65
61
  ### smartsheet_delete_records
66
62
 
67
63
  删除一行或多行记录,单次必须在 500 行内。**操作不可逆**。record_id 通过 `smartsheet_get_records` 获取。
@@ -74,6 +70,5 @@ description: 企业微信智能表格数据(记录)管理技能。提供智
74
70
  2. **写入数据** → 先 `smartsheet_get_fields` 了解列类型 → 若涉及成员(USER)字段,先通过 `wecom-contact-lookup` 的 `get_userlist` 查找人员 userid → `smartsheet_add_records` 写入
75
71
  3. **更新数据** → 先 `smartsheet_get_records` 获取 record_id → 若涉及成员(USER)字段,先通过 `wecom-contact-lookup` 的 `get_userlist` 查找人员 userid → `smartsheet_update_records` 更新
76
72
  4. **删除数据** → 先 `smartsheet_get_records` 确认 record_id → `smartsheet_delete_records` 删除
77
- 5. **写入失败 fallback** → 第 2/3 步返回 `errcode: 851003` / `no authority`(通常是企业可见范围 > 10 人的规模限制)时 → 请用户临时提供目标表的 Webhook 地址 + schema 示例 JSON(不保存到本地)→ 按 [webhook-fallback.md](references/webhook-fallback.md) 构造请求体发送
78
73
 
79
74
  > **注意**:成员(USER)类型字段需要填写 `user_id`,不能直接使用姓名。必须先通过 `wecom-contact-lookup` 技能的 `get_userlist` 接口按姓名查找到对应的 `userid` 后再使用。
@@ -1,185 +0,0 @@
1
- # 真实场景示例
2
-
3
- ## 场景 1:记录一个 Bug(文本 + 单选 + 图片)
4
-
5
- 用户说:“帮我记一下这个 bug,登录页在 Safari 下白屏,模块是前端,严重程度严重。”
6
-
7
- ```json
8
- {
9
- "add_records": [
10
- {
11
- "values": {
12
- "fABCD1": "登录页在 Safari 浏览器下加载后白屏,其他浏览器正常。复现步骤:Safari 14+ 访问 /login → 页面空白,控制台报 CSS 解析错误。",
13
- "fABCD2": [{"text": "前端"}],
14
- "fABCD3": [{"text": "严重"}],
15
- "fABCD4": [{"user_id": "wangwu"}],
16
- "fABCD5": [{"title": "safari-bug-screenshot.png", "image_base64": "iVBORw0KGgoAAAANSUhEUg...(纯base64)"}]
17
- }
18
- }
19
- ]
20
- }
21
- ```
22
-
23
- ## 场景 2:记录一条任务(文本 + 日期 + 成员 + 单选 + 空图片)
24
-
25
- 用户说:“加一条任务,完成支付模块单元测试,3月20日前,负责人 lisi,状态未开始,暂无附件。”
26
-
27
- ```json
28
- {
29
- "add_records": [
30
- {
31
- "values": {
32
- "fTITLE": "完成支付模块单元测试,覆盖率达到 80%",
33
- "fDUEDATE": "1742400000000",
34
- "fOWNER": [{"user_id": "lisi"}],
35
- "fSTATUS": [{"text": "未开始"}],
36
- "fATTACH": []
37
- }
38
- }
39
- ]
40
- }
41
- ```
42
-
43
- > **关于负责人(成员字段)**:
44
- > - 有 userid 时用 `[{"user_id": "账号名"}]`,userid 通常就是企业微信登录账号
45
- > - 没有 userid 只知道姓名时用 `["张三"]`,但匹配不上时不会写入
46
- > - 暂不指定负责人时传 `[]` 空数组
47
- >
48
- > **关于图片/附件字段**:
49
- > - 暂无图片时传 `[]` 空数组即可,不会报错
50
- > - 有图片时传 `[{"title": "filename.png", "image_base64": "纯base64字符串"}]`,注意不带 `data:image/...;base64,` 前缀
51
-
52
- ## 场景 3:批量添加多条客户记录
53
-
54
- 用户说:“帮我把这三条线索录进去:张伟/科技公司/跟进中,陈静/贸易公司/初步接触,刘洋/制造业/已成交。”
55
-
56
- ```json
57
- {
58
- "add_records": [
59
- {
60
- "values": {
61
- "fCUST_NAME": "张伟",
62
- "fCOMPANY": "北京某科技有限公司",
63
- "fSTAGE": [{"text": "跟进中"}],
64
- "fSOURCE": [{"text": "展会"}]
65
- }
66
- },
67
- {
68
- "values": {
69
- "fCUST_NAME": "陈静",
70
- "fCOMPANY": "上海某贸易有限公司",
71
- "fSTAGE": [{"text": "初步接触"}],
72
- "fSOURCE": [{"text": "冷呼"}]
73
- }
74
- },
75
- {
76
- "values": {
77
- "fCUST_NAME": "刘洋",
78
- "fCOMPANY": "广州某制造有限公司",
79
- "fSTAGE": [{"text": "已成交"}],
80
- "fSOURCE": [{"text": "老客户转介绍"}]
81
- }
82
- }
83
- ]
84
- }
85
- ```
86
-
87
- ## 场景 4:更新一条已有记录
88
-
89
- 用户说:“把 record_id 是 REC_20250301 的那条任务状态改成已完成,进度 100%。”
90
-
91
- ```json
92
- {
93
- "update_records": [
94
- {
95
- "record_id": "REC_20250301",
96
- "values": {
97
- "fSTATUS": [{"text": "已完成"}],
98
- "fPROGRESS": 100
99
- }
100
- }
101
- ]
102
- }
103
- ```
104
-
105
- ## 场景 5:批量更新多条记录
106
-
107
- 用户说:“把这几条审批记录都标为已通过:REC_001、REC_002、REC_003。”
108
-
109
- ```json
110
- {
111
- "update_records": [
112
- {"record_id": "REC_001", "values": {"fSTATUS": [{"text": "已通过"}], "fAPPROVER": [{"user_id": "manager_a"}]}},
113
- {"record_id": "REC_002", "values": {"fSTATUS": [{"text": "已通过"}], "fAPPROVER": [{"user_id": "manager_a"}]}},
114
- {"record_id": "REC_003", "values": {"fSTATUS": [{"text": "已通过"}], "fAPPROVER": [{"user_id": "manager_a"}]}}
115
- ]
116
- }
117
- ```
118
-
119
- ## 场景 6:记录一条销售订单(多字段混合类型)
120
-
121
- 用户说:“新增一条订单,客户是北京某科技,产品是企业版,金额 58000,签约日期今天,负责人赵六,合同链接发给你了。”
122
-
123
- ```json
124
- {
125
- "add_records": [
126
- {
127
- "values": {
128
- "fCUSTOMER": "北京某科技有限公司",
129
- "fPRODUCT": [{"text": "企业版"}],
130
- "fAMOUNT": 58000,
131
- "fSIGN_DATE": "1741622400000",
132
- "fSALES": [{"user_id": "zhaoliu"}],
133
- "fCONTRACT": [{"text": "合同文件", "link": "https://doc.example.com/contract/2025-001"}]
134
- }
135
- }
136
- ]
137
- }
138
- ```
139
-
140
- ## 场景 7:记录一次会议纪要
141
-
142
- 用户说:“帮我记一下今天下午的需求评审会,参会人产品+开发+测试,决议是优先做支付模块。”
143
-
144
- ```json
145
- {
146
- "add_records": [
147
- {
148
- "values": {
149
- "fMEETING_TITLE": "支付模块需求评审会",
150
- "fDATE": "1741622400000",
151
- "fPARTICIPANTS": "产品、开发、测试",
152
- "fSUMMARY": "确定优先开发支付模块,目标 3 月底完成联调,4 月初上线。遗留问题:退款流程待产品补充文档。",
153
- "fDOC_LINK": [{"text": "评审文档", "link": "https://doc.example.com/meeting/20250310"}]
154
- }
155
- }
156
- ]
157
- }
158
- ```
159
-
160
- ## 场景 8:同一请求中同时添加和更新
161
-
162
- 用户说:“新增一条‘用户反馈收集’的任务,同时把‘旧官网下线’那条(REC_OLD_001)标为已完成。”
163
-
164
- ```json
165
- {
166
- "add_records": [
167
- {
168
- "values": {
169
- "fTITLE": "用户反馈收集与分析",
170
- "fSTATUS": [{"text": "未开始"}],
171
- "fPRIORITY": [{"text": "高"}]
172
- }
173
- }
174
- ],
175
- "update_records": [
176
- {
177
- "record_id": "REC_OLD_001",
178
- "values": {
179
- "fSTATUS": [{"text": "已完成"}],
180
- "fPROGRESS": 100
181
- }
182
- }
183
- ]
184
- }
185
- ```
@@ -1,184 +0,0 @@
1
- # 智能表格 Webhook 兜底写入
2
-
3
- > 本文档是 `smartsheet_add_records` / `smartsheet_update_records` 的 **fallback 参考**。
4
- > 当通过 `wecom_mcp` tool 调用因企业规模限制(可见范围 > 10 人)报错、无法写入智能表格时,切换到本方案,通过企业微信智能表格的 Webhook 接口直接写入数据。
5
- >
6
- > ⚠️ **格式隔离**:以下字段值格式仅适用于 Webhook 接口,与 `wecom_mcp` tool 侧 `smartsheet_add_records` / `smartsheet_update_records` 的参数结构**不同**(例如文本、URL、图片、日期的写法均有差异),请勿与 [cell-value-formats.md](cell-value-formats.md) 的格式混用。
7
-
8
- ---
9
-
10
- ## 一、Fallback 触发流程
11
-
12
- ### 何时切换到 Webhook
13
-
14
- 先走 `wecom_mcp` tool 正常链路(`smartsheet_add_records` / `smartsheet_update_records`)。仅在出现以下情况时才切换到 Webhook:
15
-
16
- - **优先判据**:返回 `errcode: 851003`,或 `errmsg` 包含 `no authority` —— 这通常意味着企业可见范围 > 10 人,写入接口被限制
17
- - 或 `errmsg` / 提示信息明显指向**企业规模 / 可见范围超限**(例如“超出可见范围”、“成员数超限”等相关描述)
18
- - 其他错误(参数错误、字段 ID 错误、文档不存在等)**不应**切换到 Webhook,应按原错误排查
19
-
20
- ### 切换时向用户索取的两样东西
21
-
22
- 切换触发后,**每次对话内临时获取,用完即弃,不保存到本地任何位置**:
23
-
24
- 1. **Webhook 完整 URL**
25
- - 在智能表格右上角菜单 → 「接收外部数据」→ 选择目标工作表 → 开启 → 复制
26
- - 格式形如 `https://qyapi.weixin.qq.com/cgi-bin/wedoc/smartsheet/webhook?key=XXXXXX`
27
- - 该 URL 相当于该表的写入密钥,用户随时可以在智能表格里关闭「接收外部数据」使其失效
28
- 2. **schema 示例 JSON**
29
- - 同一「接收外部数据」页面即可复制
30
- - 包含字段 ID → 字段名的映射(`schema`)和各字段的写入格式示例(`add_records`)
31
-
32
- 示例:
33
-
34
- ```json
35
- {
36
- "schema": {
37
- "fABCD1": "任务名称",
38
- "fABCD2": "状态",
39
- "fABCD3": "负责人",
40
- "fABCD4": "截止日期"
41
- },
42
- "add_records": [
43
- {
44
- "values": {
45
- "fABCD1": "示例任务",
46
- "fABCD2": [{"text": "未开始"}],
47
- "fABCD3": [{"user_id": ""}],
48
- "fABCD4": "1742400000000"
49
- }
50
- }
51
- ]
52
- }
53
- ```
54
-
55
- ### 向用户告知的话术参考
56
-
57
- - “通过 `wecom_mcp` 写入接口返回了 `851003 no authority`(通常是企业可见范围 > 10 人的限制)。请把目标表的 Webhook 地址和「接收外部数据」页面的示例 JSON 发我,我帮你通过 Webhook 写入。该信息仅本轮使用,不会保存到本地。”
58
-
59
- ---
60
-
61
- ## 二、构建请求
62
-
63
- ### 字段匹配
64
-
65
- 用户描述通常是自然语言(“标题”“状态”“处理人”),需从用户提供的 `schema` 中找对应字段 ID:
66
-
67
- - 模糊匹配:`标题` → 标题 / 名称 / 主题;`状态` → 状态 / 阶段;`处理人` → 负责人 / 责任人
68
- - 不确定时先问用户确认,避免写错字段
69
-
70
- 各字段类型的值写法见下方 [字段类型格式规范](#三字段类型格式规范);真实场景示例见 [webhook-examples.md](webhook-examples.md)。
71
-
72
- ### 日期处理
73
-
74
- 用户说“今天”“明天”“3 月 15 日”“2025-03-01 09:00”等自然语言日期时,**在 payload 构造阶段**根据当前日期推算为**毫秒时间戳字符串**(如 `"1742400000000"`)。Webhook 侧**不接受**可读日期字符串。
75
-
76
- ### 请求结构
77
-
78
- Webhook 是标准 HTTP 接口,不经过 `wecom_mcp`,请按执行环境选择合适的工具发送(`curl`、`node` 内置 `fetch`、`python` 的 `requests` / `urllib` 等均可,优先用当前环境最便捷的方式):
79
-
80
- | 项 | 值 |
81
- |---|---|
82
- | Method | `POST` |
83
- | URL | 用户提供的 Webhook 完整 URL(含 `?key=XXX`) |
84
- | Header | `Content-Type: application/json` |
85
- | Body | JSON 对象,包含 `add_records` 和/或 `update_records` 字段 |
86
-
87
- ### Body 结构
88
-
89
- - 仅新增:
90
-
91
- ```json
92
- {
93
- "add_records": [
94
- { "values": { "fABCD1": "...", "fABCD2": [{"text": "..."}] } }
95
- ]
96
- }
97
- ```
98
-
99
- - 仅更新(需提供 `record_id`,且**只能更新通过 Webhook 写入的记录**,人工创建的记录无法更新):
100
-
101
- ```json
102
- {
103
- "update_records": [
104
- { "record_id": "REC_xxx", "values": { "fABCD2": [{"text": "已完成"}] } }
105
- ]
106
- }
107
- ```
108
-
109
- - 同一请求同时新增和更新:
110
-
111
- ```json
112
- {
113
- "add_records": [ { "values": { ... } } ],
114
- "update_records": [ { "record_id": "REC_xxx", "values": { ... } } ]
115
- }
116
- ```
117
-
118
- ### 成功后
119
-
120
- 简洁告知结果,例如:
121
-
122
- > “已通过 Webhook 写入,record_id: `REC_xxx`”
123
-
124
- 返回非 0 `errcode` 时参考下方 [常见错误码](#六常见错误码)。
125
-
126
- ---
127
-
128
- ## 三、字段类型格式规范
129
-
130
- ### 各类型写法
131
-
132
- | 字段类型 | value 示例 | 说明 |
133
- |---------|-----------|------|
134
- | 文本 | `"产品登录页白屏"` 或 `[{"type":"text","text":"产品登录页白屏"}]` | 简单字符串更简洁 |
135
- | 数字 / 货币 | `58000` | double,不要加引号 |
136
- | 进度 / 百分数 | `30` | 传整数值,`30` = 30%;**不要传小数** `0.3`(那样会显示 0.3%) |
137
- | 复选框 | `true` / `false` | bool |
138
- | 日期 | `"1740806400000"` | 毫秒时间戳,字符串形式 |
139
- | 成员 | `[{"user_id":"lisi"}]` 或 `["张三"]` 或 `[]` | userid 通常就是企业微信登录账号;不指定时传 `[]` |
140
- | 单选 | `[{"text":"已完成"}]` | 数组,选项文本必须与表格预设完全一致 |
141
- | 多选 | `[{"text":"前端"},{"text":"后端"}]` | 数组,每个选项一个对象 |
142
- | 链接 | `[{"text":"需求文档","link":"https://doc.example.com"}]` | 数组 |
143
- | 地理位置 | `[{"latitude":"31.23040","longitude":"121.47370","source_type":1,"title":"上海市徐汇区"}]` | 数组,最多 1 条 |
144
- | 图片 | `[{"title":"screenshot.png","image_base64":"iVBORw0KGgo..."}]` | 纯 base64,**不要带 `data:image/...;base64,` 前缀**,否则报 errcode 2023033 |
145
- | 电话 / 邮箱 / 条码 | `"13800138000"` | 字符串 |
146
-
147
- ---
148
-
149
- ## 四、不支持的字段
150
-
151
- 以下字段由系统自动维护或结构特殊,Webhook 写入时**跳过即可,不要报错**:
152
-
153
- 公式、自动编号、查找引用、关联字段、创建人、最后编辑人、创建时间、最后编辑时间、群聊、文件附件。
154
-
155
- ---
156
-
157
- ## 五、频率限制
158
-
159
- - 单工作表:≤ 3000 条/分钟
160
- - 单文档:≤ 10000 条/分钟
161
-
162
- 数据量大时建议分批,每批不超过 500 条。
163
-
164
- ---
165
-
166
- ## 六、常见错误码
167
-
168
- | errcode | 原因 | 解决方法 |
169
- |---------|------|---------|
170
- | 2023033 | 图片 base64 携带了 `data:image/...;base64,` 前缀 | 去掉前缀,只传纯 base64 字符串 |
171
- | 40014 | Webhook key 无效或已过期 | 请用户重新在智能表格「接收外部数据」获取 Webhook 地址 |
172
- | 45033 | 超出频率限制 | 降低发送速率或分批发送 |
173
- | -100035 | testapi 域名不稳定(超时) | 改用正式域名 `qyapi.weixin.qq.com` |
174
- | 2023001 | 字段 ID 不存在 | 核对用户提供的 `schema`,确认字段 ID 拼写正确 |
175
- | 2023010 | 单选/多选的选项值不在预设列表 | 确认选项文本与表格设置完全一致(区分大小写) |
176
- | 2023012 | record_id 不存在(更新时) | 只能更新通过 Webhook 写入的记录,人工创建的记录无法更新 |
177
-
178
- ---
179
-
180
- ## 七、参考文件
181
-
182
- - 真实场景示例 → [webhook-examples.md](webhook-examples.md)
183
-
184
- 按需查阅,不用每次全读。