@wecom/wecom-openclaw-plugin 2026.3.30 → 2026.3.31-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 (107) hide show
  1. package/README.md +251 -4
  2. package/dist/index.d.ts +2 -4
  3. package/dist/index.js +113 -0
  4. package/dist/src/accounts.d.ts +57 -0
  5. package/dist/src/accounts.js +222 -0
  6. package/dist/src/agent/api-client.d.ts +94 -0
  7. package/dist/src/agent/api-client.js +292 -0
  8. package/dist/src/agent/handler.d.ts +63 -0
  9. package/dist/src/agent/handler.js +562 -0
  10. package/dist/src/agent/index.d.ts +5 -0
  11. package/dist/src/agent/index.js +5 -0
  12. package/dist/src/agent/webhook.d.ts +23 -0
  13. package/dist/src/agent/webhook.js +226 -0
  14. package/dist/src/agent/xml.d.ts +21 -0
  15. package/dist/src/agent/xml.js +41 -0
  16. package/dist/src/channel.js +564 -0
  17. package/dist/src/chat-queue.d.ts +31 -0
  18. package/dist/src/chat-queue.js +45 -0
  19. package/dist/src/const.d.ts +46 -0
  20. package/dist/src/const.js +157 -0
  21. package/dist/src/dm-policy.js +84 -0
  22. package/dist/src/dynamic-agent.d.ts +37 -0
  23. package/dist/src/dynamic-agent.js +60 -0
  24. package/dist/src/dynamic-routing.d.ts +75 -0
  25. package/dist/src/dynamic-routing.js +124 -0
  26. package/dist/src/group-policy.js +126 -0
  27. package/dist/src/http.d.ts +26 -0
  28. package/dist/src/http.js +93 -0
  29. package/dist/src/interface.d.ts +0 -2
  30. package/dist/src/interface.js +4 -0
  31. package/dist/src/mcp/index.js +6 -0
  32. package/dist/src/mcp/interceptors/biz-error.js +64 -0
  33. package/dist/src/mcp/interceptors/index.js +66 -0
  34. package/dist/src/mcp/interceptors/msg-media.js +133 -0
  35. package/dist/src/mcp/interceptors/smartpage-create.js +132 -0
  36. package/dist/src/mcp/interceptors/smartpage-export.js +87 -0
  37. package/dist/src/mcp/interceptors/types.js +7 -0
  38. package/dist/src/mcp/schema.js +99 -0
  39. package/dist/src/mcp/tool.js +202 -0
  40. package/dist/src/mcp/transport.js +410 -0
  41. package/dist/src/media-handler.js +122 -0
  42. package/dist/src/media-uploader.js +333 -0
  43. package/dist/src/message-parser.js +129 -0
  44. package/dist/src/message-sender.d.ts +18 -0
  45. package/dist/src/message-sender.js +120 -0
  46. package/dist/src/monitor.js +875 -0
  47. package/dist/src/onboarding.js +175 -0
  48. package/dist/src/openclaw-compat.d.ts +47 -0
  49. package/dist/src/openclaw-compat.js +477 -0
  50. package/dist/src/reqid-store.js +83 -0
  51. package/dist/src/routing.d.ts +24 -0
  52. package/dist/src/routing.js +34 -0
  53. package/dist/src/runtime.js +10 -0
  54. package/dist/src/shared/command-auth.d.ts +23 -0
  55. package/dist/src/shared/command-auth.js +73 -0
  56. package/dist/src/shared/xml-parser.d.ts +46 -0
  57. package/dist/src/shared/xml-parser.js +210 -0
  58. package/dist/src/state-dir-resolve.d.ts +2 -0
  59. package/dist/src/state-dir-resolve.js +9 -0
  60. package/dist/src/state-manager.js +216 -0
  61. package/dist/src/target.d.ts +35 -0
  62. package/dist/src/target.js +67 -0
  63. package/dist/src/template-card-manager.d.ts +55 -0
  64. package/dist/src/template-card-manager.js +205 -0
  65. package/dist/src/template-card-parser.js +647 -0
  66. package/dist/src/timeout.js +36 -0
  67. package/dist/src/types/account.d.ts +29 -0
  68. package/dist/src/types/account.js +4 -0
  69. package/dist/src/types/config.d.ts +100 -0
  70. package/dist/src/types/config.js +7 -0
  71. package/dist/src/types/constants.d.ts +42 -0
  72. package/dist/src/types/constants.js +42 -0
  73. package/dist/src/types/index.d.ts +7 -0
  74. package/dist/src/types/index.js +5 -0
  75. package/dist/src/types/message.d.ts +238 -0
  76. package/dist/src/types/message.js +5 -0
  77. package/dist/src/utils.d.ts +39 -0
  78. package/dist/src/utils.js +70 -0
  79. package/dist/src/version.d.ts +1 -1
  80. package/dist/src/version.js +24 -0
  81. package/dist/src/webhook/command-auth.d.ts +47 -0
  82. package/dist/src/webhook/command-auth.js +96 -0
  83. package/dist/src/webhook/gateway.d.ts +36 -0
  84. package/dist/src/webhook/gateway.js +227 -0
  85. package/dist/src/webhook/handler.d.ts +18 -0
  86. package/dist/src/webhook/handler.js +420 -0
  87. package/dist/src/webhook/helpers.d.ts +156 -0
  88. package/dist/src/webhook/helpers.js +833 -0
  89. package/dist/src/webhook/http.d.ts +26 -0
  90. package/dist/src/webhook/http.js +94 -0
  91. package/dist/src/webhook/index.d.ts +11 -0
  92. package/dist/src/webhook/index.js +14 -0
  93. package/dist/src/webhook/media.d.ts +29 -0
  94. package/dist/src/webhook/media.js +88 -0
  95. package/dist/src/webhook/monitor.d.ts +59 -0
  96. package/dist/src/webhook/monitor.js +1185 -0
  97. package/dist/src/webhook/state.d.ts +220 -0
  98. package/dist/src/webhook/state.js +491 -0
  99. package/dist/src/webhook/target.d.ts +41 -0
  100. package/dist/src/webhook/target.js +132 -0
  101. package/dist/src/webhook/types.d.ts +347 -0
  102. package/dist/src/webhook/types.js +33 -0
  103. package/package.json +15 -7
  104. package/dist/index.cjs.js +0 -4953
  105. package/dist/index.cjs.js.map +0 -1
  106. package/dist/index.esm.js +0 -4926
  107. package/dist/index.esm.js.map +0 -1
@@ -0,0 +1,29 @@
1
+ /**
2
+ * WeCom 账号类型定义
3
+ */
4
+ import type { WecomAgentConfig, WecomNetworkConfig } from "./config.js";
5
+ /**
6
+ * 解析后的 Agent 账号
7
+ */
8
+ export type ResolvedAgentAccount = {
9
+ /** 账号 ID */
10
+ accountId: string;
11
+ /** 是否启用 */
12
+ enabled: boolean;
13
+ /** 是否配置完整 */
14
+ configured: boolean;
15
+ /** 企业 ID */
16
+ corpId: string;
17
+ /** 应用 Secret */
18
+ corpSecret: string;
19
+ /** 应用 ID (数字,可选) */
20
+ agentId?: number;
21
+ /** 回调 Token */
22
+ token: string;
23
+ /** 回调加密密钥 */
24
+ encodingAESKey: string;
25
+ /** 原始配置 */
26
+ config: WecomAgentConfig;
27
+ /** 网络配置(来自 channels.wecom.network) */
28
+ network?: WecomNetworkConfig;
29
+ };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * WeCom 账号类型定义
3
+ */
4
+ export {};
@@ -0,0 +1,100 @@
1
+ /**
2
+ * WeCom 子模块配置类型定义
3
+ *
4
+ * 注意:顶层配置类型 WeComConfig 定义在 src/utils.ts 中,以平铺结构为准。
5
+ * 本文件仅定义 Agent/Bot/DM/Network/Media 等子模块的配置类型。
6
+ */
7
+ /** 媒体处理配置 */
8
+ export type WecomMediaConfig = {
9
+ tempDir?: string;
10
+ retentionHours?: number;
11
+ cleanupOnStart?: boolean;
12
+ maxBytes?: number;
13
+ };
14
+ /** 网络配置 */
15
+ export type WecomNetworkConfig = {
16
+ timeoutMs?: number;
17
+ retries?: number;
18
+ retryDelayMs?: number;
19
+ /**
20
+ * 出口代理(用于企业可信 IP 固定出口场景)。
21
+ * 示例: "http://proxy.company.local:3128"
22
+ */
23
+ egressProxyUrl?: string;
24
+ };
25
+ /**
26
+ * Bot 模式配置 (智能体)
27
+ * 用于接收 JSON 格式回调 + 流式回复
28
+ */
29
+ export type WecomBotConfig = {
30
+ /** 智能机器人 ID(用于 Matrix 模式二次身份确认,webhook 模式) */
31
+ aibotid?: string;
32
+ /** 回调 Token (企微后台生成,webhook 模式必填) */
33
+ token?: string;
34
+ /** 回调加密密钥 (企微后台生成,webhook 模式必填) */
35
+ encodingAESKey?: string;
36
+ /**
37
+ * BotId 列表(可选,用于审计与告警)。
38
+ * - 回调路由优先由 URL + 签名决定;botIds 不参与强制拦截。
39
+ * - 当解密后的 aibotid 不在 botIds 中时,仅记录告警日志。
40
+ */
41
+ botIds?: string[];
42
+ /** 接收者 ID (可选,用于解密校验) */
43
+ receiveId?: string;
44
+ /** 流式消息占位符 */
45
+ streamPlaceholderContent?: string;
46
+ /** 欢迎语 */
47
+ welcomeText?: string;
48
+ /** DM 策略: 'open' 允许所有人, 'pairing' 需要配对, 'allowlist' 仅允许列表, 'disabled' 禁用 */
49
+ dmPolicy?: 'open' | 'pairing' | 'allowlist' | 'disabled';
50
+ /** 允许的用户列表,为空表示允许所有人 */
51
+ allowFrom?: Array<string | number>;
52
+ /** 连接模式:webhook(默认)或 websocket */
53
+ connectionMode?: 'webhook' | 'websocket';
54
+ /** 机器人 BotID(websocket 模式必填,企微后台获取) */
55
+ botId?: string;
56
+ /** 机器人 Secret(websocket 模式必填,企微后台获取) */
57
+ secret?: string;
58
+ };
59
+ /**
60
+ * Agent 模式配置 (自建应用)
61
+ * 用于接收 XML 格式回调 + API 主动发送
62
+ */
63
+ export type WecomAgentConfig = {
64
+ /** 企业 ID */
65
+ corpId: string;
66
+ /** 应用 Secret */
67
+ corpSecret: string;
68
+ /** 应用 ID(可选;不填时可接收回调,但主动发送需具备该字段) */
69
+ agentId?: number | string;
70
+ /** 回调 Token (企微后台「设置API接收」) */
71
+ token: string;
72
+ /** 回调加密密钥 (企微后台「设置API接收」) */
73
+ encodingAESKey: string;
74
+ /** 欢迎语 */
75
+ welcomeText?: string;
76
+ /** DM 策略: 'open' 允许所有人, 'pairing' 需要配对, 'allowlist' 仅允许列表, 'disabled' 禁用 */
77
+ dmPolicy?: 'open' | 'pairing' | 'allowlist' | 'disabled';
78
+ /** 允许的用户列表,为空表示允许所有人 */
79
+ allowFrom?: Array<string | number>;
80
+ };
81
+ /** 路由行为配置 */
82
+ export type WecomRoutingConfig = {
83
+ /**
84
+ * 当路由未命中 bindings(matchedBy=default)时是否拒绝继续处理。
85
+ * - true: fail-closed(推荐于多账号)
86
+ * - false: 允许回退默认 agent(历史兼容)
87
+ */
88
+ failClosedOnDefaultRoute?: boolean;
89
+ };
90
+ /** 动态 Agent 配置 */
91
+ export type WecomDynamicAgentsConfig = {
92
+ /** 是否启用动态 Agent */
93
+ enabled?: boolean;
94
+ /** 私聊:是否为每个用户创建独立 Agent */
95
+ dmCreateAgent?: boolean;
96
+ /** 群聊:是否启用动态 Agent */
97
+ groupEnabled?: boolean;
98
+ /** 管理员列表(绕过动态路由,使用主 Agent) */
99
+ adminUsers?: string[];
100
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * WeCom 子模块配置类型定义
3
+ *
4
+ * 注意:顶层配置类型 WeComConfig 定义在 src/utils.ts 中,以平铺结构为准。
5
+ * 本文件仅定义 Agent/Bot/DM/Network/Media 等子模块的配置类型。
6
+ */
7
+ export {};
@@ -0,0 +1,42 @@
1
+ /**
2
+ * WeCom 双模式常量定义
3
+ */
4
+ /** 固定 Webhook 路径 */
5
+ export declare const WEBHOOK_PATHS: {
6
+ /** Bot 模式历史兼容路径(不再维护) */
7
+ readonly BOT: "/wecom";
8
+ /** Bot 模式历史备用兼容路径(不再维护) */
9
+ readonly BOT_ALT: "/wecom/bot";
10
+ /** Agent 模式历史兼容路径(不再维护) */
11
+ readonly AGENT: "/wecom/agent";
12
+ /** Bot 模式推荐路径前缀 */
13
+ readonly BOT_PLUGIN: "/plugins/wecom/bot";
14
+ /** Agent 模式推荐路径前缀 */
15
+ readonly AGENT_PLUGIN: "/plugins/wecom/agent";
16
+ };
17
+ /** 企业微信 API 端点 */
18
+ export declare const API_ENDPOINTS: {
19
+ readonly GET_TOKEN: "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
20
+ readonly SEND_MESSAGE: "https://qyapi.weixin.qq.com/cgi-bin/message/send";
21
+ readonly SEND_APPCHAT: "https://qyapi.weixin.qq.com/cgi-bin/appchat/send";
22
+ readonly UPLOAD_MEDIA: "https://qyapi.weixin.qq.com/cgi-bin/media/upload";
23
+ readonly DOWNLOAD_MEDIA: "https://qyapi.weixin.qq.com/cgi-bin/media/get";
24
+ };
25
+ /** 各类限制常量 */
26
+ export declare const LIMITS: {
27
+ /** 文本消息最大字节数 */
28
+ readonly TEXT_MAX_BYTES: 2048;
29
+ /** Token 刷新缓冲时间 (提前刷新) */
30
+ readonly TOKEN_REFRESH_BUFFER_MS: 60000;
31
+ /** HTTP 请求超时 */
32
+ readonly REQUEST_TIMEOUT_MS: 15000;
33
+ /** 最大请求体大小 */
34
+ readonly MAX_REQUEST_BODY_SIZE: number;
35
+ };
36
+ /** AES 加密常量 */
37
+ export declare const CRYPTO: {
38
+ /** PKCS#7 块大小 */
39
+ readonly PKCS7_BLOCK_SIZE: 32;
40
+ /** AES Key 长度 */
41
+ readonly AES_KEY_LENGTH: 32;
42
+ };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * WeCom 双模式常量定义
3
+ */
4
+ /** 固定 Webhook 路径 */
5
+ export const WEBHOOK_PATHS = {
6
+ /** Bot 模式历史兼容路径(不再维护) */
7
+ BOT: "/wecom",
8
+ /** Bot 模式历史备用兼容路径(不再维护) */
9
+ BOT_ALT: "/wecom/bot",
10
+ /** Agent 模式历史兼容路径(不再维护) */
11
+ AGENT: "/wecom/agent",
12
+ /** Bot 模式推荐路径前缀 */
13
+ BOT_PLUGIN: "/plugins/wecom/bot",
14
+ /** Agent 模式推荐路径前缀 */
15
+ AGENT_PLUGIN: "/plugins/wecom/agent",
16
+ };
17
+ /** 企业微信 API 端点 */
18
+ export const API_ENDPOINTS = {
19
+ GET_TOKEN: "https://qyapi.weixin.qq.com/cgi-bin/gettoken",
20
+ SEND_MESSAGE: "https://qyapi.weixin.qq.com/cgi-bin/message/send",
21
+ SEND_APPCHAT: "https://qyapi.weixin.qq.com/cgi-bin/appchat/send",
22
+ UPLOAD_MEDIA: "https://qyapi.weixin.qq.com/cgi-bin/media/upload",
23
+ DOWNLOAD_MEDIA: "https://qyapi.weixin.qq.com/cgi-bin/media/get",
24
+ };
25
+ /** 各类限制常量 */
26
+ export const LIMITS = {
27
+ /** 文本消息最大字节数 */
28
+ TEXT_MAX_BYTES: 2048,
29
+ /** Token 刷新缓冲时间 (提前刷新) */
30
+ TOKEN_REFRESH_BUFFER_MS: 60_000,
31
+ /** HTTP 请求超时 */
32
+ REQUEST_TIMEOUT_MS: 15_000,
33
+ /** 最大请求体大小 */
34
+ MAX_REQUEST_BODY_SIZE: 1024 * 1024,
35
+ };
36
+ /** AES 加密常量 */
37
+ export const CRYPTO = {
38
+ /** PKCS#7 块大小 */
39
+ PKCS7_BLOCK_SIZE: 32,
40
+ /** AES Key 长度 */
41
+ AES_KEY_LENGTH: 32,
42
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * WeCom 类型统一导出
3
+ */
4
+ export * from "./constants.js";
5
+ export type { WecomMediaConfig, WecomNetworkConfig, WecomBotConfig, WecomAgentConfig, } from "./config.js";
6
+ export type { ResolvedAgentAccount, } from "./account.js";
7
+ export type { WecomBotInboundBase, WecomBotInboundText, WecomBotInboundVoice, WecomBotInboundVideo, WecomBotInboundStreamRefresh, WecomBotInboundEvent, WecomBotInboundMessage, WecomAgentInboundMessage, WecomInboundQuote, WecomTemplateCard, WecomOutboundMessage, } from "./message.js";
@@ -0,0 +1,5 @@
1
+ /**
2
+ * WeCom 类型统一导出
3
+ */
4
+ // 常量
5
+ export * from "./constants.js";
@@ -0,0 +1,238 @@
1
+ /**
2
+ * WeCom 消息类型定义
3
+ * Bot 和 Agent 模式共用
4
+ */
5
+ /**
6
+ * Bot 模式入站消息基础结构 (JSON)
7
+ */
8
+ /**
9
+ * **WecomBotInboundBase (Bot 入站消息基类)**
10
+ *
11
+ * Bot 模式下 JSON 格式回调的基础字段。
12
+ * @property msgid 消息 ID
13
+ * @property aibotid 机器人 ID
14
+ * @property chattype 会话类型: "single" | "group"
15
+ * @property chatid 群聊 ID (仅群组时存在)
16
+ * @property response_url 下行回复 URL (用于被动响应转主动推送)
17
+ * @property from 发送者信息
18
+ */
19
+ export type WecomBotInboundBase = {
20
+ msgid?: string;
21
+ aibotid?: string;
22
+ chattype?: "single" | "group";
23
+ chatid?: string;
24
+ response_url?: string;
25
+ from?: {
26
+ userid?: string;
27
+ corpid?: string;
28
+ };
29
+ msgtype?: string;
30
+ /** 附件数量 (部分消息存在) */
31
+ attachment_count?: number;
32
+ };
33
+ export type WecomBotInboundText = WecomBotInboundBase & {
34
+ msgtype: "text";
35
+ text?: {
36
+ content?: string;
37
+ };
38
+ quote?: WecomInboundQuote;
39
+ };
40
+ export type WecomBotInboundVoice = WecomBotInboundBase & {
41
+ msgtype: "voice";
42
+ voice?: {
43
+ content?: string;
44
+ };
45
+ quote?: WecomInboundQuote;
46
+ };
47
+ export type WecomBotInboundVideo = WecomBotInboundBase & {
48
+ msgtype: "video";
49
+ video?: {
50
+ url?: string;
51
+ aeskey?: string;
52
+ };
53
+ quote?: WecomInboundQuote;
54
+ };
55
+ export type WecomBotInboundStreamRefresh = WecomBotInboundBase & {
56
+ msgtype: "stream";
57
+ stream?: {
58
+ id?: string;
59
+ };
60
+ };
61
+ export type WecomBotInboundEvent = WecomBotInboundBase & {
62
+ msgtype: "event";
63
+ create_time?: number;
64
+ event?: {
65
+ eventtype?: string;
66
+ [key: string]: unknown;
67
+ };
68
+ };
69
+ /**
70
+ * **WecomInboundQuote (引用消息)**
71
+ *
72
+ * 消息中引用的原始内容(如回复某条消息)。
73
+ * 支持引用文本、图片、混合类型、语音、文件等。
74
+ */
75
+ export type WecomInboundQuote = {
76
+ msgtype?: "text" | "image" | "mixed" | "voice" | "file" | "video";
77
+ /** 引用文本内容 */
78
+ text?: {
79
+ content?: string;
80
+ };
81
+ /** 引用图片 URL */
82
+ image?: {
83
+ url?: string;
84
+ };
85
+ /** 引用混合消息 (图文) */
86
+ mixed?: {
87
+ msg_item?: Array<{
88
+ msgtype: "text" | "image";
89
+ text?: {
90
+ content?: string;
91
+ };
92
+ image?: {
93
+ url?: string;
94
+ };
95
+ }>;
96
+ };
97
+ /** 引用语音 */
98
+ voice?: {
99
+ content?: string;
100
+ };
101
+ /** 引用文件 */
102
+ file?: {
103
+ url?: string;
104
+ };
105
+ /** 引用视频 */
106
+ video?: {
107
+ url?: string;
108
+ };
109
+ };
110
+ export type WecomBotInboundMessage = WecomBotInboundText | WecomBotInboundVoice | WecomBotInboundVideo | WecomBotInboundStreamRefresh | WecomBotInboundEvent | (WecomBotInboundBase & {
111
+ quote?: WecomInboundQuote;
112
+ } & Record<string, unknown>);
113
+ /**
114
+ * Agent 模式入站消息结构 (解析自 XML)
115
+ */
116
+ /**
117
+ * **WecomAgentInboundMessage (Agent 入站消息)**
118
+ *
119
+ * Agent 模式下解析自 XML 的扁平化消息结构。
120
+ * 键名保持 PascalCase (如 `ToUserName`)。
121
+ */
122
+ export type WecomAgentInboundMessage = {
123
+ ToUserName?: string;
124
+ FromUserName?: string;
125
+ CreateTime?: number;
126
+ MsgType?: string;
127
+ MsgId?: string;
128
+ AgentID?: number;
129
+ Content?: string;
130
+ PicUrl?: string;
131
+ MediaId?: string;
132
+ FileName?: string;
133
+ Format?: string;
134
+ Recognition?: string;
135
+ ThumbMediaId?: string;
136
+ Location_X?: number;
137
+ Location_Y?: number;
138
+ Scale?: number;
139
+ Label?: string;
140
+ Title?: string;
141
+ Description?: string;
142
+ Url?: string;
143
+ Event?: string;
144
+ EventKey?: string;
145
+ ChatId?: string;
146
+ };
147
+ /**
148
+ * 模板卡片类型
149
+ */
150
+ /**
151
+ * **WecomTemplateCard (模板卡片)**
152
+ *
153
+ * 复杂的交互式卡片结构。
154
+ * @property card_type 卡片类型: "text_notice" | "news_notice" | "button_interaction" ...
155
+ * @property source 来源信息
156
+ * @property main_title 主标题
157
+ * @property sub_title_text 副标题
158
+ * @property horizontal_content_list 水平排列的键值列表
159
+ * @property button_list 按钮列表
160
+ */
161
+ export type WecomTemplateCard = {
162
+ card_type: "text_notice" | "news_notice" | "button_interaction" | "vote_interaction" | "multiple_interaction";
163
+ source?: {
164
+ icon_url?: string;
165
+ desc?: string;
166
+ desc_color?: number;
167
+ };
168
+ main_title?: {
169
+ title?: string;
170
+ desc?: string;
171
+ };
172
+ task_id?: string;
173
+ button_list?: Array<{
174
+ text: string;
175
+ style?: number;
176
+ key: string;
177
+ }>;
178
+ sub_title_text?: string;
179
+ horizontal_content_list?: Array<{
180
+ keyname: string;
181
+ value?: string;
182
+ type?: number;
183
+ url?: string;
184
+ userid?: string;
185
+ }>;
186
+ card_action?: {
187
+ type: number;
188
+ url?: string;
189
+ appid?: string;
190
+ pagepath?: string;
191
+ };
192
+ action_menu?: {
193
+ desc: string;
194
+ action_list: Array<{
195
+ text: string;
196
+ key: string;
197
+ }>;
198
+ };
199
+ select_list?: Array<{
200
+ question_key: string;
201
+ title?: string;
202
+ selected_id?: string;
203
+ option_list: Array<{
204
+ id: string;
205
+ text: string;
206
+ }>;
207
+ }>;
208
+ submit_button?: {
209
+ text: string;
210
+ key: string;
211
+ };
212
+ checkbox?: {
213
+ question_key: string;
214
+ option_list: Array<{
215
+ id: string;
216
+ text: string;
217
+ is_checked?: boolean;
218
+ }>;
219
+ mode?: number;
220
+ };
221
+ };
222
+ /**
223
+ * 出站消息类型
224
+ */
225
+ export type WecomOutboundMessage = {
226
+ msgtype: "text";
227
+ text: {
228
+ content: string;
229
+ };
230
+ } | {
231
+ msgtype: "markdown";
232
+ markdown: {
233
+ content: string;
234
+ };
235
+ } | {
236
+ msgtype: "template_card";
237
+ template_card: WecomTemplateCard;
238
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * WeCom 消息类型定义
3
+ * Bot 和 Agent 模式共用
4
+ */
5
+ export {};
@@ -2,6 +2,8 @@
2
2
  * 企业微信公共工具函数
3
3
  */
4
4
  import type { OpenClawConfig } from "openclaw/plugin-sdk/core";
5
+ import type { ResolvedAgentAccount } from "./types/account.js";
6
+ import type { WecomAgentConfig, WecomNetworkConfig, WecomMediaConfig } from "./types/config.js";
5
7
  /**
6
8
  * 企业微信群组配置
7
9
  */
@@ -30,7 +32,30 @@ export interface WeComConfig {
30
32
  sendThinkingMessage?: boolean;
31
33
  /** 额外允许访问的本地媒体路径白名单(支持 ~ 表示 home 目录),如 ["~/Downloads", "~/Documents"] */
32
34
  mediaLocalRoots?: string[];
35
+ /** Agent 模式配置(自建应用) */
36
+ agent?: WecomAgentConfig;
37
+ /** 网络配置 */
38
+ network?: WecomNetworkConfig;
39
+ /** 媒体处理配置 */
40
+ media?: WecomMediaConfig;
41
+ /** 连接模式:webhook | websocket(默认 websocket) */
42
+ connectionMode?: "webhook" | "websocket";
43
+ /** Webhook 验证 token */
44
+ token?: string;
45
+ /** AES 加密密钥(43 字符 Base64) */
46
+ encodingAESKey?: string;
47
+ /** 接收方 ID */
48
+ receiveId?: string;
49
+ /** enter_chat 欢迎消息 */
50
+ welcomeText?: string;
51
+ /** 流式占位符提示内容 */
52
+ streamPlaceholderContent?: string;
33
53
  }
54
+ /**
55
+ * 单个企业微信账号的配置类型(用于 accounts 字段下的每个账号)。
56
+ * 与 WeComConfig 字段完全一致,账号级字段会覆盖顶层同名字段。
57
+ */
58
+ export type WeComAccountConfig = Partial<WeComConfig>;
34
59
  export declare const DefaultWsUrl = "wss://openws.work.weixin.qq.com";
35
60
  export interface ResolvedWeComAccount {
36
61
  accountId: string;
@@ -42,6 +67,12 @@ export interface ResolvedWeComAccount {
42
67
  /** 是否发送"思考中"消息,默认为 true */
43
68
  sendThinkingMessage: boolean;
44
69
  config: WeComConfig;
70
+ /** Agent 模式能力(自建应用) */
71
+ agent?: ResolvedAgentAccount;
72
+ /** Webhook 模式配置 */
73
+ token?: string;
74
+ encodingAESKey?: string;
75
+ receiveId?: string;
45
76
  }
46
77
  /**
47
78
  * 解析企业微信账户配置
@@ -51,3 +82,11 @@ export declare function resolveWeComAccount(cfg: OpenClawConfig): ResolvedWeComA
51
82
  * 设置企业微信账户配置
52
83
  */
53
84
  export declare function setWeComAccount(cfg: OpenClawConfig, account: Partial<WeComConfig>): OpenClawConfig;
85
+ /**
86
+ * 解析出口代理 URL(对齐原版 resolveWecomEgressProxyUrl)
87
+ *
88
+ * 优先级:
89
+ * 1. config.channels.wecom.network.egressProxyUrl
90
+ * 2. 环境变量:OPENCLAW_WECOM_EGRESS_PROXY_URL → WECOM_EGRESS_PROXY_URL → HTTPS_PROXY → ALL_PROXY → HTTP_PROXY
91
+ */
92
+ export declare function resolveWecomEgressProxyUrl(cfg: OpenClawConfig): string | undefined;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * 企业微信公共工具函数
3
+ */
4
+ import { DEFAULT_ACCOUNT_ID } from "./openclaw-compat.js";
5
+ import { CHANNEL_ID } from "./const.js";
6
+ export const DefaultWsUrl = "wss://openws.work.weixin.qq.com";
7
+ /**
8
+ * 解析企业微信账户配置
9
+ */
10
+ export function resolveWeComAccount(cfg) {
11
+ const wecomConfig = (cfg.channels?.[CHANNEL_ID] ?? {});
12
+ return {
13
+ accountId: DEFAULT_ACCOUNT_ID,
14
+ name: wecomConfig.name ?? "企业微信",
15
+ enabled: wecomConfig.enabled !== false,
16
+ websocketUrl: wecomConfig.websocketUrl || DefaultWsUrl,
17
+ botId: wecomConfig.botId ?? "",
18
+ secret: wecomConfig.secret ?? "",
19
+ sendThinkingMessage: wecomConfig.sendThinkingMessage ?? true,
20
+ config: wecomConfig,
21
+ };
22
+ }
23
+ /**
24
+ * 设置企业微信账户配置
25
+ */
26
+ export function setWeComAccount(cfg, account) {
27
+ const existing = (cfg.channels?.[CHANNEL_ID] ?? {});
28
+ const merged = {
29
+ enabled: account.enabled ?? existing?.enabled ?? true,
30
+ botId: account.botId ?? existing?.botId ?? "",
31
+ secret: account.secret ?? existing?.secret ?? "",
32
+ allowFrom: account.allowFrom ?? existing?.allowFrom,
33
+ dmPolicy: account.dmPolicy ?? existing?.dmPolicy,
34
+ // 以下字段仅在已有配置值或显式传入时才写入,onboarding 时不主动生成
35
+ ...(account.websocketUrl || existing?.websocketUrl
36
+ ? { websocketUrl: account.websocketUrl ?? existing?.websocketUrl }
37
+ : {}),
38
+ ...(account.name || existing?.name
39
+ ? { name: account.name ?? existing?.name }
40
+ : {}),
41
+ ...(account.sendThinkingMessage !== undefined || existing?.sendThinkingMessage !== undefined
42
+ ? { sendThinkingMessage: account.sendThinkingMessage ?? existing?.sendThinkingMessage }
43
+ : {}),
44
+ };
45
+ return {
46
+ ...cfg,
47
+ channels: {
48
+ ...cfg.channels,
49
+ [CHANNEL_ID]: merged,
50
+ },
51
+ };
52
+ }
53
+ /**
54
+ * 解析出口代理 URL(对齐原版 resolveWecomEgressProxyUrl)
55
+ *
56
+ * 优先级:
57
+ * 1. config.channels.wecom.network.egressProxyUrl
58
+ * 2. 环境变量:OPENCLAW_WECOM_EGRESS_PROXY_URL → WECOM_EGRESS_PROXY_URL → HTTPS_PROXY → ALL_PROXY → HTTP_PROXY
59
+ */
60
+ export function resolveWecomEgressProxyUrl(cfg) {
61
+ const wecom = (cfg.channels?.[CHANNEL_ID] ?? {});
62
+ const proxyUrl = wecom.network?.egressProxyUrl ??
63
+ process.env.OPENCLAW_WECOM_EGRESS_PROXY_URL ??
64
+ process.env.WECOM_EGRESS_PROXY_URL ??
65
+ process.env.HTTPS_PROXY ??
66
+ process.env.ALL_PROXY ??
67
+ process.env.HTTP_PROXY ??
68
+ "";
69
+ return proxyUrl.trim() || undefined;
70
+ }
@@ -1,2 +1,2 @@
1
- /** 插件版本号,来源于 package.json */
1
+ /** 插件版本号,运行时从 package.json 读取 */
2
2
  export declare const PLUGIN_VERSION: string;
@@ -0,0 +1,24 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ /**
5
+ * 从当前文件位置向上逐级查找 package.json
6
+ * - ts 源码直接运行时(tsx/ts-node):src/version.ts → 向上 1 级
7
+ * - tsc 编译后运行时:dist/src/version.js → 向上 2 级
8
+ */
9
+ const findPackageJson = () => {
10
+ let dir = dirname(fileURLToPath(import.meta.url));
11
+ while (true) {
12
+ const candidate = resolve(dir, "package.json");
13
+ if (existsSync(candidate))
14
+ return candidate;
15
+ const parent = dirname(dir);
16
+ if (parent === dir)
17
+ break; // 已到文件系统根目录
18
+ dir = parent;
19
+ }
20
+ throw new Error("找不到 package.json");
21
+ };
22
+ const pkg = JSON.parse(readFileSync(findPackageJson(), "utf-8"));
23
+ /** 插件版本号,运行时从 package.json 读取 */
24
+ export const PLUGIN_VERSION = pkg.version ?? "";