@sunnoy/wecom 2.2.1 → 2.4.0

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.
package/README.md CHANGED
@@ -150,6 +150,7 @@ npm test
150
150
  "mentionPatterns": ["@"]
151
151
  },
152
152
  "workspaceTemplate": "/path/to/template-dir",
153
+ "mediaLocalRoots": ["/tmp/openclaw"],
153
154
  "agent": {
154
155
  "corpId": "wwxxxxxxxxxxxxxxxx",
155
156
  "corpSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
@@ -180,7 +181,8 @@ npm test
180
181
  | `channels.wecom.secret` | string | 是 | 企业微信 AI 机器人 Secret |
181
182
  | `channels.wecom.websocketUrl` | string | 否 | WS 地址,默认 `wss://openws.work.weixin.qq.com` |
182
183
  | `channels.wecom.sendThinkingMessage` | boolean | 否 | 是否先发送 `<think></think>` 占位,默认 `true` |
183
- | `channels.wecom.welcomeMessage` | string | 否 | 进入会话欢迎语 |
184
+ | `channels.wecom.welcomeMessage` | string | 否 | 进入会话欢迎语(非空时固定使用该字符串) |
185
+ | `channels.wecom.welcomeMessagesFile` | string | 否 | 欢迎语列表文件路径。支持:`{ "messages": [ ... ] }` 或顶层数组;每条欢迎语可为**一行一个字符串的数组**(推荐,易读),或单条字符串(可含 `\\n`)。相对路径基于 OpenClaw 状态目录(`~/.openclaw` 或 `OPENCLAW_STATE_DIR`)。未设置 `welcomeMessage` 时从该文件随机选取;**修改文件后无需重启服务**(按 mtime 自动重读) |
184
186
  | `channels.wecom.adminUsers` | string[] | 否 | 管理员用户 ID,可绕过命令白名单 |
185
187
  | `channels.wecom.defaultAccount` | string | 否 | 多账号模式默认账号 |
186
188
 
@@ -207,6 +209,7 @@ npm test
207
209
  | `channels.wecom.groupChat.requireMention` | boolean | 否 | 群聊是否要求 @ 才响应,默认 `true` |
208
210
  | `channels.wecom.groupChat.mentionPatterns` | string[] | 否 | 群聊触发前缀,默认 `["@"]` |
209
211
  | `channels.wecom.workspaceTemplate` | string | 否 | 动态 Agent 工作区模板目录 |
212
+ | `channels.wecom.mediaLocalRoots` | string[] | 否 | 额外允许被动回复读取的宿主机目录列表。用于放行 `MEDIA:/abs/path` 或 `FILE:/abs/path` 指向的本地文件;默认只允许当前 Agent workspace 和浏览器产物目录。多账号模式下也可配置在 `channels.wecom.<accountId>.mediaLocalRoots`。修改后需重启 Gateway 生效 |
210
213
 
211
214
  ### 增强出站配置
212
215
 
@@ -246,6 +249,7 @@ Agent 增强出站不需要 `token`、`encodingAesKey`、回调 URL;只有需
246
249
  "botId": "aib-support-xxx",
247
250
  "secret": "secret-support-xxx",
248
251
  "dmPolicy": "pairing",
252
+ "mediaLocalRoots": ["/tmp/openclaw"],
249
253
  "agent": {
250
254
  "corpId": "wwxxxxxxxxxxxxxxxx",
251
255
  "corpSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
@@ -376,6 +380,15 @@ Webhook 只负责群通知。
376
380
  - 最终回复 `finish=true` 时可附带图片 `msg_item`
377
381
  - 若最终回复包含 WS 不支持的媒体(文件等),会先文本提示再通过 Agent API 补发
378
382
 
383
+ 本插件会自动解析模型输出中的 `MEDIA:` / `FILE:` 指令,并在回复完成后上传对应文件:
384
+
385
+ - 图片使用 `MEDIA:/abs/path`
386
+ - PDF、音频、视频、压缩包、Office 文档等非图片文件使用 `FILE:/abs/path`
387
+ - 沙箱内当前工作区文件可直接写成 `MEDIA:/workspace/...` 或 `FILE:/workspace/...`
388
+ - 浏览器生成的文件默认允许从 OpenClaw 状态目录下的浏览器媒体目录读取
389
+ - 宿主机其他目录默认不放行;如果需要回复 `/tmp/openclaw/report.pdf` 这类文件,请把其父目录加入 `channels.wecom.mediaLocalRoots`,多账号模式可配在 `channels.wecom.<accountId>.mediaLocalRoots`
390
+ - 更新 `mediaLocalRoots` 后需重启 Gateway 生效
391
+
379
392
  ### 主动发送与后备策略
380
393
 
381
394
  主动发送分层:
@@ -556,6 +569,29 @@ openclaw pairing approve wecom <code>
556
569
  - WS 断连后的 pending 回复通过 Agent API 补发
557
570
  - WS 文本主动发送失败时,尝试回退到 Agent
558
571
 
572
+ ### Q: 回复本地文件时提示“没有权限访问路径”怎么办?
573
+
574
+ 先确认文件路径是否在允许目录里:
575
+
576
+ - 当前 Agent 工作区文件默认允许,可直接用 `FILE:/workspace/...` 或 `MEDIA:/workspace/...`
577
+ - 浏览器生成的文件默认允许
578
+ - 宿主机其他目录需要把父目录加入 `channels.wecom.mediaLocalRoots`
579
+ - 多账号模式如果只想对某个账号生效,可配置 `channels.wecom.<accountId>.mediaLocalRoots`
580
+
581
+ 例如:
582
+
583
+ ```json
584
+ {
585
+ "channels": {
586
+ "wecom": {
587
+ "mediaLocalRoots": ["/tmp/openclaw"]
588
+ }
589
+ }
590
+ }
591
+ ```
592
+
593
+ 修改后重启 Gateway。`v2.2.1+` 已支持把 `mediaLocalRoots` 并入被动回复文件允许目录。
594
+
559
595
  ### Q: `60020 not allow to access from your ip` 是什么问题?
560
596
 
561
597
  企业微信自建应用 API 的可信 IP 限制。把当前服务器出口 IP 加入企业微信应用的可信 IP 白名单即可。
package/index.js CHANGED
@@ -1,7 +1,8 @@
1
- import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
2
1
  import { logger } from "./logger.js";
3
2
  import { wecomChannelPlugin } from "./wecom/channel-plugin.js";
4
3
  import { createWeComMcpTool } from "./wecom/mcp-tool.js";
4
+ import { createImageStudioTool } from "./wecom/image-studio-tool.js";
5
+ import { resolveQwenImageToolsConfig, wecomPluginConfigSchema } from "./wecom/plugin-config.js";
5
6
  import { setOpenclawConfig, setRuntime } from "./wecom/state.js";
6
7
  import { buildReplyMediaGuidance } from "./wecom/ws-monitor.js";
7
8
  import { listAccountIds, resolveAccount } from "./wecom/accounts.js";
@@ -11,7 +12,7 @@ const plugin = {
11
12
  id: "wecom",
12
13
  name: "Enterprise WeChat",
13
14
  description: "Enterprise WeChat AI Bot channel plugin for OpenClaw",
14
- configSchema: emptyPluginConfigSchema(),
15
+ configSchema: wecomPluginConfigSchema,
15
16
  register(api) {
16
17
  logger.info("Registering WeCom WS plugin");
17
18
  setRuntime(api.runtime);
@@ -19,6 +20,14 @@ const plugin = {
19
20
  api.registerChannel({ plugin: wecomChannelPlugin });
20
21
  api.registerTool(createWeComMcpTool(), { name: "wecom_mcp" });
21
22
 
23
+ const qwenImageToolsConfig = resolveQwenImageToolsConfig(api.pluginConfig);
24
+ if (qwenImageToolsConfig.enabled) {
25
+ api.registerTool(createImageStudioTool(qwenImageToolsConfig), { name: "image_studio" });
26
+ logger.info(
27
+ `[image_studio] Registered with provider "${qwenImageToolsConfig.provider}" using qwen(generate=${qwenImageToolsConfig.models.qwen.generate}, edit=${qwenImageToolsConfig.models.qwen.edit}) wan(generate=${qwenImageToolsConfig.models.wan.generate}, edit=${qwenImageToolsConfig.models.wan.edit})`,
28
+ );
29
+ }
30
+
22
31
  // Register HTTP callback endpoints for all accounts that have callback config
23
32
  for (const accountId of listAccountIds(api.config)) {
24
33
  const account = resolveAccount(api.config, accountId);
@@ -8,7 +8,143 @@
8
8
  "configSchema": {
9
9
  "type": "object",
10
10
  "additionalProperties": true,
11
- "properties": {}
11
+ "properties": {
12
+ "qwenImageTools": {
13
+ "type": "object",
14
+ "additionalProperties": false,
15
+ "properties": {
16
+ "enabled": {
17
+ "type": "boolean"
18
+ },
19
+ "provider": {
20
+ "type": "string"
21
+ },
22
+ "route": {
23
+ "type": "string",
24
+ "enum": [
25
+ "auto",
26
+ "qwen",
27
+ "wan"
28
+ ]
29
+ },
30
+ "endpoint": {
31
+ "type": "string"
32
+ },
33
+ "endpoints": {
34
+ "type": "object",
35
+ "additionalProperties": false,
36
+ "properties": {
37
+ "qwen": {
38
+ "type": "string"
39
+ },
40
+ "wan": {
41
+ "type": "string"
42
+ },
43
+ "task": {
44
+ "type": "string"
45
+ }
46
+ }
47
+ },
48
+ "timeoutMs": {
49
+ "type": "integer",
50
+ "minimum": 1000
51
+ },
52
+ "models": {
53
+ "type": "object",
54
+ "additionalProperties": false,
55
+ "properties": {
56
+ "generate": {
57
+ "type": "string"
58
+ },
59
+ "edit": {
60
+ "type": "string"
61
+ },
62
+ "qwen": {
63
+ "type": "object",
64
+ "additionalProperties": false,
65
+ "properties": {
66
+ "generate": {
67
+ "type": "string"
68
+ },
69
+ "edit": {
70
+ "type": "string"
71
+ }
72
+ }
73
+ },
74
+ "wan": {
75
+ "type": "object",
76
+ "additionalProperties": false,
77
+ "properties": {
78
+ "generate": {
79
+ "type": "string"
80
+ },
81
+ "edit": {
82
+ "type": "string"
83
+ }
84
+ }
85
+ }
86
+ }
87
+ },
88
+ "defaults": {
89
+ "type": "object",
90
+ "additionalProperties": false,
91
+ "properties": {
92
+ "size": {
93
+ "type": "string"
94
+ },
95
+ "aspect": {
96
+ "type": "string",
97
+ "enum": [
98
+ "landscape",
99
+ "square",
100
+ "portrait"
101
+ ]
102
+ },
103
+ "n": {
104
+ "type": "integer",
105
+ "minimum": 1
106
+ },
107
+ "watermark": {
108
+ "type": "boolean"
109
+ },
110
+ "promptExtend": {
111
+ "type": "boolean"
112
+ },
113
+ "qwen": {
114
+ "type": "object",
115
+ "additionalProperties": false,
116
+ "properties": {
117
+ "landscape": {
118
+ "type": "string"
119
+ },
120
+ "square": {
121
+ "type": "string"
122
+ },
123
+ "portrait": {
124
+ "type": "string"
125
+ }
126
+ }
127
+ },
128
+ "wan": {
129
+ "type": "object",
130
+ "additionalProperties": false,
131
+ "properties": {
132
+ "landscape": {
133
+ "type": "string"
134
+ },
135
+ "square": {
136
+ "type": "string"
137
+ },
138
+ "portrait": {
139
+ "type": "string"
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
12
148
  },
13
149
  "channels": [
14
150
  "wecom"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunnoy/wecom",
3
- "version": "2.2.1",
3
+ "version": "2.4.0",
4
4
  "description": "Enterprise WeChat AI Bot channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -8,7 +8,6 @@
8
8
  "index.js",
9
9
  "wecom",
10
10
  "dynamic-agent.js",
11
-
12
11
  "logger.js",
13
12
  "README.md",
14
13
  "LICENSE",
@@ -60,7 +59,7 @@
60
59
  "author": "",
61
60
  "license": "ISC",
62
61
  "dependencies": {
63
- "@wecom/aibot-node-sdk": "^1.0.2",
62
+ "@wecom/aibot-node-sdk": "^1.0.3",
64
63
  "file-type": "^21.3.0"
65
64
  }
66
65
  }
@@ -0,0 +1,115 @@
1
+ ---
2
+ name: wecom-msg
3
+ description: 企业微信消息技能。提供会话列表查询、消息记录拉取(支持文本/图片/文件/语音/视频)、多媒体文件获取和文本消息发送能力。当用户需要“查看消息”、”看聊天记录”、”发消息给某人”、”最近有什么消息”、”给群里发消息”、”看看发了什么图片/文件”时触发。
4
+ ---
5
+
6
+ # 企业微信消息技能
7
+
8
+ > `wecom_mcp` 是一个 MCP tool,所有操作通过调用该 tool 完成。
9
+
10
+ > ⚠️ **前置条件**:首次调用 `wecom_mcp` 前,必须按 `wecom-preflight` 技能执行前置条件检查,确保工具已加入白名单。
11
+
12
+ > ⚠️ **路径与停止规则**:
13
+ > - 如果要读取本 skill,必须直接使用 `<available_skills>` 或 `skillsSnapshot` 中给出的精确绝对路径。
14
+ > - 不要猜测或改写为 `/data/openclaw/skills/wecom-*`、`/workspace/.openclaw/skills/...`、`/root/.openclaw/workspace-*/.openclaw/skills/...`,也不要用 `exec` + `ls/find` 探路。
15
+ > - 若 `wecom_mcp` 返回 `errcode: 846609` 或 `unsupported mcp biz type`,表示当前 bot 未开通 `msg` category,不是路径、白名单或 sandbox 问题;立即停止继续 `read`、`list`、`find`、memory fallback 探索,直接告知用户当前机器人未开通消息能力。
16
+
17
+ 通过 `wecom_mcp call msg <接口名> '<json入参>'` 与企业微信消息系统交互。
18
+
19
+ ## 接口列表
20
+
21
+ ### 1. 获取会话列表
22
+
23
+ 使用 `wecom_mcp` tool 调用 `wecom_mcp call msg get_msg_chat_list '{"begin_time": "2026-03-11 00:00:00", "end_time": "2026-03-17 23:59:59"}'`
24
+
25
+ 按时间范围查询有消息的会话列表,支持分页。详情见 `references/api-get-msg-chat-list.md`。
26
+
27
+ ### 2. 拉取聊天记录
28
+
29
+ 使用 `wecom_mcp` tool 调用 `wecom_mcp call msg get_messages '{"chat_type": 1, "chatid": "zhangsan", "begin_time": "2026-03-17 09:00:00", "end_time": "2026-03-17 18:00:00"}'`
30
+
31
+ 根据会话类型和会话 ID 拉取指定时间范围内的消息记录,支持分页。详情见 `references/api-get-messages.md`。
32
+
33
+ ### 3. 发送文本消息
34
+
35
+ 使用 `wecom_mcp` tool 调用 `wecom_mcp call msg send_message '{"chat_type": 1, "chatid": "zhangsan", "msgtype": "text", "text": {"content": "hello world"}}'`
36
+
37
+ 向单聊或群聊发送文本消息。详情见 `references/api-send-message.md`。
38
+
39
+ ## 核心规则
40
+
41
+ ### 时间范围
42
+
43
+ - 所有时间参数使用 `YYYY-MM-DD HH:mm:ss` 格式。
44
+ - 用户未指定时间时,默认使用最近 7 天。
45
+ - `get_messages` 只支持当前时刻往前 7 天内的数据。
46
+ - 如果用户给出的开始时间早于 7 天窗口,要主动调整到有效范围并明确告知。
47
+
48
+ ### 会话定位
49
+
50
+ - 当用户直接提供 `chatid` 时,直接使用。
51
+ - 当用户提供人名或群名而不是 ID 时,先调用 `get_msg_chat_list` 获取候选会话,再按 `chat_name` 在本地筛选。
52
+ - 精确匹配唯一结果时可直接使用。
53
+ - 模糊匹配多个结果时,必须先向用户展示候选项,不要擅自决定。
54
+ - 没有匹配结果时,要明确告知未找到对应会话。
55
+ - `get_msg_chat_list` 返回里没有 `chat_type`,若用户明确说“群”“群聊”“项目群”等,优先用 `chat_type=2`;否则默认 `chat_type=1`。
56
+
57
+ ### 消息展示
58
+
59
+ - `get_messages` 当前只按文档约定处理文本消息;遇到非文本字段时,不要编造内容,按原始结构说明。
60
+ - 展示消息时优先把 `userid` 转成可读姓名。
61
+ - 如需做 `userid -> 姓名/别名` 映射,调用 `wecom-contact-lookup` 的 `get_userlist`,并在本地建立映射。
62
+ - 若无法映射,保留 `userid` 原样展示。
63
+
64
+ ### 发送规则
65
+
66
+ - `send_message` 仅用于发送文本消息。
67
+ - 用户要求发送图片、PDF、视频、语音或其它文件时,不要误用 `wecom_mcp msg send_message`;应改用本插件原生的 `MEDIA:` / `FILE:` 路径投递能力。
68
+ - 发送消息前必须先做一次面向用户的确认,至少确认发送对象和发送内容。
69
+ - 用户确认前,不要执行 `send_message`。
70
+
71
+ ## 典型工作流
72
+
73
+ ### 查看最近有哪些会话
74
+
75
+ 1. 确定时间范围。
76
+ 2. 调用 `get_msg_chat_list`。
77
+ 3. 按“会话名称 + 最后消息时间 + 消息数量”整理结果。
78
+ 4. 若 `has_more=true`,提示用户还可以继续翻页。
79
+
80
+ ### 查看某个聊天对象的记录
81
+
82
+ 1. 确定时间范围。
83
+ 2. 如需,先通过 `get_msg_chat_list` 定位 `chatid`。
84
+ 3. 调用 `get_messages`。
85
+ 4. 如需,调用 `wecom-contact-lookup` 获取通讯录,把 `userid` 映射为姓名/别名。
86
+ 5. 按时间顺序展示消息。
87
+ 6. 若 `next_cursor` 非空,提示还有更多消息可继续查看。
88
+
89
+ ### 给某人或某个群发文本
90
+
91
+ 1. 如需,先定位 `chatid` 与 `chat_type`。
92
+ 2. 向用户确认发送对象和文本内容。
93
+ 3. 用户确认后,调用 `send_message`。
94
+ 4. 返回发送结果。
95
+
96
+ ### 看完消息后代发回复
97
+
98
+ 1. 先执行“查看聊天记录”流程。
99
+ 2. 从上下文中提取待回复对象和回复内容。
100
+ 3. 再执行“给某人或某个群发文本”流程。
101
+
102
+ ## 错误处理
103
+
104
+ - 若返回 `tool not allowed`、`unknown tool: wecom_mcp`、`permission denied`,说明问题在宿主机工具放行,不要继续试探,按 `wecom-preflight` 规则处理。
105
+ - 若返回 `unsupported mcp biz type` 或 `errcode: 846609`,说明当前 bot 未开通 `msg` category,不要继续尝试其它 category。
106
+ - 若返回 API 业务错误,直接展示 `errcode` 和 `errmsg`,必要时最多重试 1 次。
107
+ - 若查询结果为空,要明确告知“当前时间范围内没有找到消息/会话”,不要编造。
108
+
109
+ ## 快速参考
110
+
111
+ | 接口 | 用途 | 关键输入 | 关键输出 |
112
+ |------|------|----------|----------|
113
+ | `get_msg_chat_list` | 查询时间范围内有消息的会话列表 | `begin_time`, `end_time`, `cursor?` | `chats`, `has_more`, `next_cursor` |
114
+ | `get_messages` | 拉取指定会话消息 | `chat_type`, `chatid`, `begin_time`, `end_time`, `cursor?` | `messages`, `next_cursor` |
115
+ | `send_message` | 发送文本消息 | `chat_type`, `chatid`, `msgtype=text`, `text.content` | `errcode`, `errmsg` |
@@ -0,0 +1,74 @@
1
+ # `get_messages` API
2
+
3
+ 根据会话类型和会话 ID 拉取指定时间范围内的消息记录。
4
+
5
+ ## 参数说明
6
+
7
+ | 参数 | 类型 | 必填 | 说明 |
8
+ |------|------|------|------|
9
+ | `chat_type` | integer | 是 | 会话类型,`1` 表示单聊,`2` 表示群聊 |
10
+ | `chatid` | string | 是 | 会话 ID。单聊时通常为 userid,群聊时为群 ID |
11
+ | `begin_time` | string | 是 | 拉取开始时间,格式:`YYYY-MM-DD HH:mm:ss`,仅支持最近 7 天内 |
12
+ | `end_time` | string | 是 | 拉取结束时间,格式:`YYYY-MM-DD HH:mm:ss`,必须大于等于 `begin_time` |
13
+ | `cursor` | string | 否 | 分页游标。首次请求不传,后续传上次响应的 `next_cursor` |
14
+
15
+ ## 请求示例
16
+
17
+ 单聊:
18
+
19
+ ```text
20
+ wecom_mcp call msg get_messages '{"chat_type":1,"chatid":"zhangsan","begin_time":"2026-03-17 09:00:00","end_time":"2026-03-17 18:00:00"}'
21
+ ```
22
+
23
+ 群聊:
24
+
25
+ ```text
26
+ wecom_mcp call msg get_messages '{"chat_type":2,"chatid":"wrxxxxxxxx","begin_time":"2026-03-17 09:00:00","end_time":"2026-03-17 18:00:00"}'
27
+ ```
28
+
29
+ 分页:
30
+
31
+ ```text
32
+ wecom_mcp call msg get_messages '{"chat_type":1,"chatid":"zhangsan","begin_time":"2026-03-17 09:00:00","end_time":"2026-03-17 18:00:00","cursor":"CURSOR_xxxxxx"}'
33
+ ```
34
+
35
+ ## 返回字段
36
+
37
+ | 字段 | 类型 | 说明 |
38
+ |------|------|------|
39
+ | `errcode` | integer | 返回码,`0` 表示成功 |
40
+ | `errmsg` | string | 错误信息 |
41
+ | `messages` | array | 消息列表 |
42
+ | `messages[].userid` | string | 发送者 userid |
43
+ | `messages[].send_time` | string | 发送时间,格式:`YYYY-MM-DD HH:mm:ss` |
44
+ | `messages[].msgtype` | string | 消息类型 |
45
+ | `messages[].text.content` | string | 文本消息内容;仅在 `msgtype=text` 时存在 |
46
+ | `next_cursor` | string | 下一页游标;为空表示已拉取完毕 |
47
+
48
+ ## 响应示例
49
+
50
+ ```json
51
+ {
52
+ "errcode": 0,
53
+ "errmsg": "ok",
54
+ "messages": [
55
+ {
56
+ "userid": "zhangsan",
57
+ "send_time": "2026-03-17 09:30:00",
58
+ "msgtype": "text",
59
+ "text": {
60
+ "content": "你好"
61
+ }
62
+ },
63
+ {
64
+ "userid": "lisi",
65
+ "send_time": "2026-03-17 09:35:00",
66
+ "msgtype": "text",
67
+ "text": {
68
+ "content": "你好,有什么可以帮助你的?"
69
+ }
70
+ }
71
+ ],
72
+ "next_cursor": "CURSOR_xxxxxx"
73
+ }
74
+ ```
@@ -0,0 +1,64 @@
1
+ # `get_msg_chat_list` API
2
+
3
+ 获取指定时间范围内有消息的会话列表,支持分页查询。
4
+
5
+ ## 参数说明
6
+
7
+ | 参数 | 类型 | 必填 | 说明 |
8
+ |------|------|------|------|
9
+ | `begin_time` | string | 是 | 拉取开始时间,格式:`YYYY-MM-DD HH:mm:ss` |
10
+ | `end_time` | string | 是 | 拉取结束时间,格式:`YYYY-MM-DD HH:mm:ss` |
11
+ | `cursor` | string | 否 | 分页游标。首次请求不传,后续传上次响应的 `next_cursor` |
12
+
13
+ ## 请求示例
14
+
15
+ 使用 `wecom_mcp` tool 调用:
16
+
17
+ ```text
18
+ wecom_mcp call msg get_msg_chat_list '{"begin_time":"2026-03-11 00:00:00","end_time":"2026-03-17 23:59:59"}'
19
+ ```
20
+
21
+ 分页请求:
22
+
23
+ ```text
24
+ wecom_mcp call msg get_msg_chat_list '{"begin_time":"2026-03-11 00:00:00","end_time":"2026-03-17 23:59:59","cursor":"NEXT_CURSOR"}'
25
+ ```
26
+
27
+ ## 返回字段
28
+
29
+ | 字段 | 类型 | 说明 |
30
+ |------|------|------|
31
+ | `errcode` | integer | 返回码,`0` 表示成功 |
32
+ | `errmsg` | string | 错误信息 |
33
+ | `chats` | array | 会话列表 |
34
+ | `chats[].chat_id` | string | 会话 ID |
35
+ | `chats[].chat_name` | string | 会话名称 |
36
+ | `chats[].last_msg_time` | string | 最后一条消息时间,格式:`YYYY-MM-DD HH:mm:ss` |
37
+ | `chats[].msg_count` | integer | 消息数量 |
38
+ | `has_more` | boolean | 是否还有更多数据 |
39
+ | `next_cursor` | string | 下一页游标 |
40
+
41
+ ## 响应示例
42
+
43
+ ```json
44
+ {
45
+ "errcode": 0,
46
+ "errmsg": "ok",
47
+ "chats": [
48
+ {
49
+ "chat_id": "zhangsan",
50
+ "chat_name": "张三",
51
+ "last_msg_time": "2026-03-17 15:30:45",
52
+ "msg_count": 128
53
+ },
54
+ {
55
+ "chat_id": "wr123456",
56
+ "chat_name": "项目讨论群",
57
+ "last_msg_time": "2026-03-16 09:12:33",
58
+ "msg_count": 56
59
+ }
60
+ ],
61
+ "has_more": true,
62
+ "next_cursor": "NEXT_CURSOR"
63
+ }
64
+ ```
@@ -0,0 +1,44 @@
1
+ # get_msg_media API
2
+
3
+ 获取消息文件内容。根据文件 ID 自动下载文件到本地,返回本地文件路径、文件名称、类型、大小及内容类型。
4
+
5
+ ## 参数说明
6
+
7
+ | 参数 | 类型 | 必填 | 说明 |
8
+ |------|------|------|------|
9
+ | `media_id` | string | ✅ | 文件 ID,长度 1~256 |
10
+
11
+ ## 请求示例
12
+
13
+ 使用 `wecom_mcp` tool 调用 `wecom_mcp call msg get_msg_media '{"media_id": "MEDIAID_xxxxxx"}'`
14
+
15
+ ## 返回字段
16
+
17
+ | 字段 | 类型 | 说明 |
18
+ |------|------|------|
19
+ | `errcode` | Integer | 返回码,`0` 表示成功 |
20
+ | `errmsg` | String | 错误信息 |
21
+ | `media_item` | Object | 文件内容 |
22
+ | `media_item.media_id` | String | 文件 ID |
23
+ | `media_item.name` | String | 文件名称 |
24
+ | `media_item.type` | String | 文件类型,`image`-图片,`voice`-语音,`video`-视频,`file`-普通文件 |
25
+ | `media_item.local_path` | String | 文件下载后的本地路径 |
26
+ | `media_item.size` | Integer | 文件大小(字节) |
27
+ | `media_item.content_type` | String | 文件 MIME 类型,如 `image/png`、`application/pdf` 等 |
28
+
29
+ ## 响应示例
30
+
31
+ ```json
32
+ {
33
+ "errcode": 0,
34
+ "errmsg": "ok",
35
+ "media_item": {
36
+ "media_id": "MEDIAID_xxxxxx",
37
+ "name": "screenshot.png",
38
+ "type": "image",
39
+ "local_path": "xxx/yyy/screenshot.png",
40
+ "size": 102400,
41
+ "content_type": "image/png"
42
+ }
43
+ }
44
+ ```
@@ -0,0 +1,49 @@
1
+ # `send_message` API
2
+
3
+ 向单聊或群聊发送文本消息。
4
+
5
+ ## 参数说明
6
+
7
+ | 参数 | 类型 | 必填 | 说明 |
8
+ |------|------|------|------|
9
+ | `chat_type` | integer | 是 | 会话类型,`1` 表示单聊,`2` 表示群聊 |
10
+ | `chatid` | string | 是 | 会话 ID。单聊时通常为 userid,群聊时为群 ID |
11
+ | `msgtype` | string | 是 | 消息类型。当前只应使用 `text` |
12
+ | `text` | object | 是 | 文本消息体 |
13
+ | `text.content` | string | 是 | 文本内容,受企业微信消息长度限制 |
14
+
15
+ ## 请求示例
16
+
17
+ 单聊:
18
+
19
+ ```text
20
+ wecom_mcp call msg send_message '{"chat_type":1,"chatid":"zhangsan","msgtype":"text","text":{"content":"hello world"}}'
21
+ ```
22
+
23
+ 群聊:
24
+
25
+ ```text
26
+ wecom_mcp call msg send_message '{"chat_type":2,"chatid":"wrxxxxxxxx","msgtype":"text","text":{"content":"大家好"}}'
27
+ ```
28
+
29
+ ## 返回字段
30
+
31
+ | 字段 | 类型 | 说明 |
32
+ |------|------|------|
33
+ | `errcode` | integer | 返回码,`0` 表示成功 |
34
+ | `errmsg` | string | 错误信息 |
35
+
36
+ ## 响应示例
37
+
38
+ ```json
39
+ {
40
+ "errcode": 0,
41
+ "errmsg": "ok"
42
+ }
43
+ ```
44
+
45
+ ## 使用约束
46
+
47
+ - 在当前插件里,这个接口只应用于文本消息。
48
+ - 发图片、PDF、视频、语音或其它文件时,不要误用这个接口;应改用插件原生的 `MEDIA:` / `FILE:` 路径投递能力。
49
+ - 执行发送前必须先征得用户确认,避免误发。