@wecom/wecom-openclaw-plugin 2026.3.24-beta.1 → 2026.3.24-beta.3

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/dist/index.d.ts CHANGED
@@ -1,11 +1,10 @@
1
- import * as openclaw_plugin_sdk from 'openclaw/plugin-sdk';
2
1
  import { OpenClawPluginApi } from 'openclaw/plugin-sdk/core';
3
2
 
4
3
  declare const plugin: {
5
4
  id: string;
6
5
  name: string;
7
6
  description: string;
8
- configSchema: openclaw_plugin_sdk.OpenClawPluginConfigSchema;
7
+ configSchema: Record<string, unknown>;
9
8
  register(api: OpenClawPluginApi): void;
10
9
  };
11
10
 
package/dist/index.esm.js CHANGED
@@ -1,26 +1,13 @@
1
- import { DEFAULT_ACCOUNT_ID, formatPairingApproveHint, emptyPluginConfigSchema } from 'openclaw/plugin-sdk/core';
2
- import * as os$1 from 'os';
3
- import * as path$1 from 'path';
4
- import { generateReqId, WSClient, WSAuthFailureError, WSReconnectExhaustedError } from '@wecom/aibot-node-sdk';
5
1
  import * as fs from 'node:fs/promises';
6
2
  import * as path from 'node:path';
7
3
  import { dirname, resolve } from 'node:path';
8
4
  import * as os from 'node:os';
9
5
  import { fileURLToPath } from 'node:url';
6
+ import * as os$1 from 'os';
7
+ import * as path$1 from 'path';
8
+ import { generateReqId, WSClient, WSAuthFailureError, WSReconnectExhaustedError } from '@wecom/aibot-node-sdk';
10
9
  import { fileTypeFromBuffer } from 'file-type';
11
10
  import { readFileSync } from 'node:fs';
12
- import { addWildcardAllowFrom } from 'openclaw/plugin-sdk/setup';
13
-
14
- let runtime = null;
15
- function setWeComRuntime(r) {
16
- runtime = r;
17
- }
18
- function getWeComRuntime() {
19
- if (!runtime) {
20
- throw new Error("WeCom runtime not initialized - plugin not registered");
21
- }
22
- return runtime;
23
- }
24
11
 
25
12
  /**
26
13
  * openclaw plugin-sdk 高版本方法兼容层
@@ -31,6 +18,7 @@ function getWeComRuntime() {
31
18
  * 本模块在加载时一次性探测 SDK 导出,存在则直接 re-export SDK 版本,
32
19
  * 不存在则导出 fallback 实现。其他模块统一从本文件导入,无需关心底层兼容细节。
33
20
  */
21
+ const DEFAULT_ACCOUNT_ID = "default";
34
22
  const _sdkReady = import('openclaw/plugin-sdk/core')
35
23
  .then((sdk) => {
36
24
  const exports$1 = {};
@@ -43,12 +31,30 @@ const _sdkReady = import('openclaw/plugin-sdk/core')
43
31
  if (typeof sdk.getDefaultMediaLocalRoots === "function") {
44
32
  exports$1.getDefaultMediaLocalRoots = sdk.getDefaultMediaLocalRoots;
45
33
  }
34
+ if (typeof sdk.addWildcardAllowFrom === "function") {
35
+ exports$1.addWildcardAllowFrom = sdk.addWildcardAllowFrom;
36
+ }
46
37
  return exports$1;
47
38
  })
48
39
  .catch(() => {
49
40
  // openclaw/plugin-sdk 不可用或版本过低,全部使用 fallback
50
41
  return {};
51
42
  });
43
+ // 同时尝试从 plugin-sdk/setup 模块探测(缓存同步可用的引用)
44
+ let _cachedAddWildcardAllowFrom;
45
+ import('openclaw/plugin-sdk/setup')
46
+ .then((sdk) => {
47
+ if (typeof sdk.addWildcardAllowFrom === "function") {
48
+ _cachedAddWildcardAllowFrom = sdk.addWildcardAllowFrom;
49
+ }
50
+ })
51
+ .catch(() => { });
52
+ // 同时也从 core 模块的结果中缓存
53
+ _sdkReady.then((sdk) => {
54
+ if (!_cachedAddWildcardAllowFrom && sdk.addWildcardAllowFrom) {
55
+ _cachedAddWildcardAllowFrom = sdk.addWildcardAllowFrom;
56
+ }
57
+ });
52
58
  // ============================================================================
53
59
  // detectMime —— 检测 MIME 类型
54
60
  // ============================================================================
@@ -325,6 +331,34 @@ async function getDefaultMediaLocalRoots() {
325
331
  path.join(stateDir, "sandboxes"),
326
332
  ];
327
333
  }
334
+ function emptyPluginConfigSchema() {
335
+ return {
336
+ type: 'object',
337
+ additionalProperties: false,
338
+ properties: {},
339
+ };
340
+ }
341
+ /**
342
+ * 格式化配对审批提示信息(参考 moltbot 实现)
343
+ * @param channelId 频道ID
344
+ * @returns 配对审批提示字符串
345
+ */
346
+ function formatPairingApproveHint(channelId) {
347
+ const listCmd = `openclaw pairing list ${channelId}`;
348
+ const approveCmd = `openclaw pairing approve ${channelId} <code>`;
349
+ return `向 ${channelId} 机器人发送消息以完成配对审批(命令行:${listCmd} / ${approveCmd})`;
350
+ }
351
+
352
+ let runtime = null;
353
+ function setWeComRuntime(r) {
354
+ runtime = r;
355
+ }
356
+ function getWeComRuntime() {
357
+ if (!runtime) {
358
+ throw new Error("WeCom runtime not initialized - plugin not registered");
359
+ }
360
+ return runtime;
361
+ }
328
362
 
329
363
  /**
330
364
  * 企业微信渠道常量定义
@@ -2100,148 +2134,6 @@ function resolveWeComAccount(cfg) {
2100
2134
  config: wecomConfig,
2101
2135
  };
2102
2136
  }
2103
- /**
2104
- * 设置企业微信账户配置
2105
- */
2106
- function setWeComAccount(cfg, account) {
2107
- const existing = (cfg.channels?.[CHANNEL_ID] ?? {});
2108
- const merged = {
2109
- enabled: account.enabled ?? existing?.enabled ?? true,
2110
- botId: account.botId ?? existing?.botId ?? "",
2111
- secret: account.secret ?? existing?.secret ?? "",
2112
- allowFrom: account.allowFrom ?? existing?.allowFrom,
2113
- dmPolicy: account.dmPolicy ?? existing?.dmPolicy,
2114
- // 以下字段仅在已有配置值或显式传入时才写入,onboarding 时不主动生成
2115
- ...(account.websocketUrl || existing?.websocketUrl
2116
- ? { websocketUrl: account.websocketUrl ?? existing?.websocketUrl }
2117
- : {}),
2118
- ...(account.name || existing?.name
2119
- ? { name: account.name ?? existing?.name }
2120
- : {}),
2121
- ...(account.sendThinkingMessage !== undefined || existing?.sendThinkingMessage !== undefined
2122
- ? { sendThinkingMessage: account.sendThinkingMessage ?? existing?.sendThinkingMessage }
2123
- : {}),
2124
- };
2125
- return {
2126
- ...cfg,
2127
- channels: {
2128
- ...cfg.channels,
2129
- [CHANNEL_ID]: merged,
2130
- },
2131
- };
2132
- }
2133
-
2134
- /**
2135
- * 企业微信 onboarding adapter for CLI setup wizard.
2136
- */
2137
- const channel = CHANNEL_ID;
2138
- /**
2139
- * 企业微信设置帮助说明
2140
- */
2141
- async function noteWeComSetupHelp(prompter) {
2142
- await prompter.note([
2143
- "企业微信机器人需要以下配置信息:",
2144
- "1. Bot ID: 企业微信机器人id",
2145
- "2. Secret: 企业微信机器人密钥",
2146
- ].join("\n"), "企业微信设置");
2147
- }
2148
- /**
2149
- * 提示输入 Bot ID
2150
- */
2151
- async function promptBotId(prompter, account) {
2152
- return String(await prompter.text({
2153
- message: "企业微信机器人 Bot ID",
2154
- initialValue: account?.botId ?? "",
2155
- validate: (value) => (value?.trim() ? undefined : "Required"),
2156
- })).trim();
2157
- }
2158
- /**
2159
- * 提示输入 Secret
2160
- */
2161
- async function promptSecret(prompter, account) {
2162
- return String(await prompter.text({
2163
- message: "企业微信机器人 Secret",
2164
- initialValue: account?.secret ?? "",
2165
- validate: (value) => (value?.trim() ? undefined : "Required"),
2166
- })).trim();
2167
- }
2168
- /**
2169
- * 设置企业微信 dmPolicy
2170
- */
2171
- function setWeComDmPolicy(cfg, dmPolicy) {
2172
- const account = resolveWeComAccount(cfg);
2173
- const existingAllowFrom = account.config.allowFrom ?? [];
2174
- const allowFrom = dmPolicy === "open"
2175
- ? addWildcardAllowFrom(existingAllowFrom.map((x) => String(x)))
2176
- : existingAllowFrom.map((x) => String(x));
2177
- return setWeComAccount(cfg, {
2178
- dmPolicy,
2179
- allowFrom,
2180
- });
2181
- }
2182
- const dmPolicy = {
2183
- label: "企业微信",
2184
- channel,
2185
- policyKey: `channels.${CHANNEL_ID}.dmPolicy`,
2186
- allowFromKey: `channels.${CHANNEL_ID}.allowFrom`,
2187
- getCurrent: (cfg) => {
2188
- const account = resolveWeComAccount(cfg);
2189
- return account.config.dmPolicy ?? "open";
2190
- },
2191
- setPolicy: (cfg, policy) => {
2192
- return setWeComDmPolicy(cfg, policy);
2193
- },
2194
- promptAllowFrom: async ({ cfg, prompter }) => {
2195
- const account = resolveWeComAccount(cfg);
2196
- const existingAllowFrom = account.config.allowFrom ?? [];
2197
- const entry = await prompter.text({
2198
- message: "企业微信允许来源(用户ID或群组ID,每行一个,推荐用于安全控制)",
2199
- placeholder: "user123 或 group456",
2200
- initialValue: existingAllowFrom[0] ? String(existingAllowFrom[0]) : undefined,
2201
- });
2202
- const allowFrom = String(entry ?? "")
2203
- .split(/[\n,;]+/g)
2204
- .map((s) => s.trim())
2205
- .filter(Boolean);
2206
- return setWeComAccount(cfg, { allowFrom });
2207
- },
2208
- };
2209
- const wecomOnboardingAdapter = {
2210
- channel,
2211
- getStatus: async ({ cfg }) => {
2212
- const account = resolveWeComAccount(cfg);
2213
- const configured = Boolean(account.botId?.trim() &&
2214
- account.secret?.trim());
2215
- return {
2216
- channel,
2217
- configured,
2218
- statusLines: [`企业微信: ${configured ? "已配置" : "需要 Bot ID 和 Secret"}`],
2219
- selectionHint: configured ? "已配置" : "需要设置",
2220
- };
2221
- },
2222
- configure: async ({ cfg, prompter, forceAllowFrom }) => {
2223
- const account = resolveWeComAccount(cfg);
2224
- if (!account.botId?.trim() || !account.secret?.trim()) {
2225
- await noteWeComSetupHelp(prompter);
2226
- }
2227
- // 提示输入必要的配置信息:Bot ID 和 Secret
2228
- const botId = await promptBotId(prompter, account);
2229
- const secret = await promptSecret(prompter, account);
2230
- // 使用默认值配置其他选项
2231
- const cfgWithAccount = setWeComAccount(cfg, {
2232
- botId,
2233
- secret,
2234
- enabled: true,
2235
- dmPolicy: account.config.dmPolicy ?? "open",
2236
- allowFrom: account.config.allowFrom ?? [],
2237
- });
2238
- return { cfg: cfgWithAccount };
2239
- },
2240
- dmPolicy,
2241
- disable: (cfg) => {
2242
- return setWeComAccount(cfg, { enabled: false });
2243
- },
2244
- };
2245
2137
 
2246
2138
  /**
2247
2139
  * 使用 SDK 的 sendMessage 主动发送企业微信消息
@@ -2298,7 +2190,6 @@ const wecomPlugin = {
2298
2190
  // Pairing approved for user
2299
2191
  },
2300
2192
  },
2301
- onboarding: wecomOnboardingAdapter,
2302
2193
  capabilities: {
2303
2194
  chatTypes: ["direct", "group"],
2304
2195
  reactions: false,