@wecom/wecom-openclaw-plugin 2026.3.24-beta.2 → 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.cjs.js CHANGED
@@ -2,14 +2,13 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var core = require('openclaw/plugin-sdk/core');
6
- var os$1 = require('os');
7
- var path$1 = require('path');
8
- var aibotNodeSdk = require('@wecom/aibot-node-sdk');
9
5
  var fs = require('node:fs/promises');
10
6
  var path = require('node:path');
11
7
  var os = require('node:os');
12
8
  var node_url = require('node:url');
9
+ var os$1 = require('os');
10
+ var path$1 = require('path');
11
+ var aibotNodeSdk = require('@wecom/aibot-node-sdk');
13
12
  var fileType = require('file-type');
14
13
  var node_fs = require('node:fs');
15
14
 
@@ -31,22 +30,11 @@ function _interopNamespaceDefault(e) {
31
30
  return Object.freeze(n);
32
31
  }
33
32
 
34
- var os__namespace$1 = /*#__PURE__*/_interopNamespaceDefault(os$1);
35
- var path__namespace$1 = /*#__PURE__*/_interopNamespaceDefault(path$1);
36
33
  var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
37
34
  var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
38
35
  var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
39
-
40
- let runtime = null;
41
- function setWeComRuntime(r) {
42
- runtime = r;
43
- }
44
- function getWeComRuntime() {
45
- if (!runtime) {
46
- throw new Error("WeCom runtime not initialized - plugin not registered");
47
- }
48
- return runtime;
49
- }
36
+ var os__namespace$1 = /*#__PURE__*/_interopNamespaceDefault(os$1);
37
+ var path__namespace$1 = /*#__PURE__*/_interopNamespaceDefault(path$1);
50
38
 
51
39
  /**
52
40
  * openclaw plugin-sdk 高版本方法兼容层
@@ -57,6 +45,7 @@ function getWeComRuntime() {
57
45
  * 本模块在加载时一次性探测 SDK 导出,存在则直接 re-export SDK 版本,
58
46
  * 不存在则导出 fallback 实现。其他模块统一从本文件导入,无需关心底层兼容细节。
59
47
  */
48
+ const DEFAULT_ACCOUNT_ID = "default";
60
49
  const _sdkReady = import('openclaw/plugin-sdk/core')
61
50
  .then((sdk) => {
62
51
  const exports$1 = {};
@@ -336,36 +325,6 @@ async function loadOutboundMediaFromUrl(mediaUrl, options = {}) {
336
325
  return loadOutboundMediaFromUrlFallback(mediaUrl, options);
337
326
  }
338
327
  // ============================================================================
339
- // addWildcardAllowFrom —— 向 allowFrom 列表添加通配符 "*"
340
- // ============================================================================
341
- /** fallback 版 addWildcardAllowFrom:确保列表中包含 "*" 通配符 */
342
- function addWildcardAllowFromFallback(allowFrom) {
343
- if (allowFrom.includes("*")) {
344
- return allowFrom;
345
- }
346
- return [...allowFrom, "*"];
347
- }
348
- /**
349
- * 向 allowFrom 列表添加通配符 "*"(兼容入口)
350
- *
351
- * 当 dmPolicy 为 "open" 时,需要确保 allowFrom 中包含 "*" 以允许所有来源。
352
- * 优先使用 SDK 版本(plugin-sdk/setup 或 plugin-sdk/core),不可用时使用 fallback。
353
- *
354
- * 注意:此函数为同步函数,与 SDK 原始签名一致。
355
- * SDK 引用在模块加载时异步探测并缓存,调用时同步读取缓存。
356
- */
357
- function addWildcardAllowFrom(allowFrom) {
358
- if (_cachedAddWildcardAllowFrom) {
359
- try {
360
- return _cachedAddWildcardAllowFrom(allowFrom);
361
- }
362
- catch {
363
- // SDK 版本异常,降级到 fallback
364
- }
365
- }
366
- return addWildcardAllowFromFallback(allowFrom);
367
- }
368
- // ============================================================================
369
328
  // getDefaultMediaLocalRoots —— 获取默认媒体本地路径白名单
370
329
  // ============================================================================
371
330
  /** 解析 openclaw 状态目录 */
@@ -399,6 +358,34 @@ async function getDefaultMediaLocalRoots() {
399
358
  path__namespace.join(stateDir, "sandboxes"),
400
359
  ];
401
360
  }
361
+ function emptyPluginConfigSchema() {
362
+ return {
363
+ type: 'object',
364
+ additionalProperties: false,
365
+ properties: {},
366
+ };
367
+ }
368
+ /**
369
+ * 格式化配对审批提示信息(参考 moltbot 实现)
370
+ * @param channelId 频道ID
371
+ * @returns 配对审批提示字符串
372
+ */
373
+ function formatPairingApproveHint(channelId) {
374
+ const listCmd = `openclaw pairing list ${channelId}`;
375
+ const approveCmd = `openclaw pairing approve ${channelId} <code>`;
376
+ return `向 ${channelId} 机器人发送消息以完成配对审批(命令行:${listCmd} / ${approveCmd})`;
377
+ }
378
+
379
+ let runtime = null;
380
+ function setWeComRuntime(r) {
381
+ runtime = r;
382
+ }
383
+ function getWeComRuntime() {
384
+ if (!runtime) {
385
+ throw new Error("WeCom runtime not initialized - plugin not registered");
386
+ }
387
+ return runtime;
388
+ }
402
389
 
403
390
  /**
404
391
  * 企业微信渠道常量定义
@@ -2164,7 +2151,7 @@ const DefaultWsUrl = "wss://openws.work.weixin.qq.com";
2164
2151
  function resolveWeComAccount(cfg) {
2165
2152
  const wecomConfig = (cfg.channels?.[CHANNEL_ID] ?? {});
2166
2153
  return {
2167
- accountId: core.DEFAULT_ACCOUNT_ID,
2154
+ accountId: DEFAULT_ACCOUNT_ID,
2168
2155
  name: wecomConfig.name ?? "企业微信",
2169
2156
  enabled: wecomConfig.enabled ?? false,
2170
2157
  websocketUrl: wecomConfig.websocketUrl || DefaultWsUrl,
@@ -2174,155 +2161,13 @@ function resolveWeComAccount(cfg) {
2174
2161
  config: wecomConfig,
2175
2162
  };
2176
2163
  }
2177
- /**
2178
- * 设置企业微信账户配置
2179
- */
2180
- function setWeComAccount(cfg, account) {
2181
- const existing = (cfg.channels?.[CHANNEL_ID] ?? {});
2182
- const merged = {
2183
- enabled: account.enabled ?? existing?.enabled ?? true,
2184
- botId: account.botId ?? existing?.botId ?? "",
2185
- secret: account.secret ?? existing?.secret ?? "",
2186
- allowFrom: account.allowFrom ?? existing?.allowFrom,
2187
- dmPolicy: account.dmPolicy ?? existing?.dmPolicy,
2188
- // 以下字段仅在已有配置值或显式传入时才写入,onboarding 时不主动生成
2189
- ...(account.websocketUrl || existing?.websocketUrl
2190
- ? { websocketUrl: account.websocketUrl ?? existing?.websocketUrl }
2191
- : {}),
2192
- ...(account.name || existing?.name
2193
- ? { name: account.name ?? existing?.name }
2194
- : {}),
2195
- ...(account.sendThinkingMessage !== undefined || existing?.sendThinkingMessage !== undefined
2196
- ? { sendThinkingMessage: account.sendThinkingMessage ?? existing?.sendThinkingMessage }
2197
- : {}),
2198
- };
2199
- return {
2200
- ...cfg,
2201
- channels: {
2202
- ...cfg.channels,
2203
- [CHANNEL_ID]: merged,
2204
- },
2205
- };
2206
- }
2207
-
2208
- /**
2209
- * 企业微信 onboarding adapter for CLI setup wizard.
2210
- */
2211
- const channel = CHANNEL_ID;
2212
- /**
2213
- * 企业微信设置帮助说明
2214
- */
2215
- async function noteWeComSetupHelp(prompter) {
2216
- await prompter.note([
2217
- "企业微信机器人需要以下配置信息:",
2218
- "1. Bot ID: 企业微信机器人id",
2219
- "2. Secret: 企业微信机器人密钥",
2220
- ].join("\n"), "企业微信设置");
2221
- }
2222
- /**
2223
- * 提示输入 Bot ID
2224
- */
2225
- async function promptBotId(prompter, account) {
2226
- return String(await prompter.text({
2227
- message: "企业微信机器人 Bot ID",
2228
- initialValue: account?.botId ?? "",
2229
- validate: (value) => (value?.trim() ? undefined : "Required"),
2230
- })).trim();
2231
- }
2232
- /**
2233
- * 提示输入 Secret
2234
- */
2235
- async function promptSecret(prompter, account) {
2236
- return String(await prompter.text({
2237
- message: "企业微信机器人 Secret",
2238
- initialValue: account?.secret ?? "",
2239
- validate: (value) => (value?.trim() ? undefined : "Required"),
2240
- })).trim();
2241
- }
2242
- /**
2243
- * 设置企业微信 dmPolicy
2244
- */
2245
- function setWeComDmPolicy(cfg, dmPolicy) {
2246
- const account = resolveWeComAccount(cfg);
2247
- const existingAllowFrom = account.config.allowFrom ?? [];
2248
- const allowFrom = dmPolicy === "open"
2249
- ? addWildcardAllowFrom(existingAllowFrom.map((x) => String(x)))
2250
- : existingAllowFrom.map((x) => String(x));
2251
- return setWeComAccount(cfg, {
2252
- dmPolicy,
2253
- allowFrom,
2254
- });
2255
- }
2256
- const dmPolicy = {
2257
- label: "企业微信",
2258
- channel,
2259
- policyKey: `channels.${CHANNEL_ID}.dmPolicy`,
2260
- allowFromKey: `channels.${CHANNEL_ID}.allowFrom`,
2261
- getCurrent: (cfg) => {
2262
- const account = resolveWeComAccount(cfg);
2263
- return account.config.dmPolicy ?? "open";
2264
- },
2265
- setPolicy: (cfg, policy) => {
2266
- return setWeComDmPolicy(cfg, policy);
2267
- },
2268
- promptAllowFrom: async ({ cfg, prompter }) => {
2269
- const account = resolveWeComAccount(cfg);
2270
- const existingAllowFrom = account.config.allowFrom ?? [];
2271
- const entry = await prompter.text({
2272
- message: "企业微信允许来源(用户ID或群组ID,每行一个,推荐用于安全控制)",
2273
- placeholder: "user123 或 group456",
2274
- initialValue: existingAllowFrom[0] ? String(existingAllowFrom[0]) : undefined,
2275
- });
2276
- const allowFrom = String(entry ?? "")
2277
- .split(/[\n,;]+/g)
2278
- .map((s) => s.trim())
2279
- .filter(Boolean);
2280
- return setWeComAccount(cfg, { allowFrom });
2281
- },
2282
- };
2283
- const wecomOnboardingAdapter = {
2284
- channel,
2285
- getStatus: async ({ cfg }) => {
2286
- const account = resolveWeComAccount(cfg);
2287
- const configured = Boolean(account.botId?.trim() &&
2288
- account.secret?.trim());
2289
- return {
2290
- channel,
2291
- configured,
2292
- statusLines: [`企业微信: ${configured ? "已配置" : "需要 Bot ID 和 Secret"}`],
2293
- selectionHint: configured ? "已配置" : "需要设置",
2294
- };
2295
- },
2296
- configure: async ({ cfg, prompter, forceAllowFrom }) => {
2297
- const account = resolveWeComAccount(cfg);
2298
- if (!account.botId?.trim() || !account.secret?.trim()) {
2299
- await noteWeComSetupHelp(prompter);
2300
- }
2301
- // 提示输入必要的配置信息:Bot ID 和 Secret
2302
- const botId = await promptBotId(prompter, account);
2303
- const secret = await promptSecret(prompter, account);
2304
- // 使用默认值配置其他选项
2305
- const cfgWithAccount = setWeComAccount(cfg, {
2306
- botId,
2307
- secret,
2308
- enabled: true,
2309
- dmPolicy: account.config.dmPolicy ?? "open",
2310
- allowFrom: account.config.allowFrom ?? [],
2311
- });
2312
- return { cfg: cfgWithAccount };
2313
- },
2314
- dmPolicy,
2315
- disable: (cfg) => {
2316
- return setWeComAccount(cfg, { enabled: false });
2317
- },
2318
- };
2319
2164
 
2320
2165
  /**
2321
2166
  * 使用 SDK 的 sendMessage 主动发送企业微信消息
2322
2167
  * 无需依赖 reqId,直接向指定会话推送消息
2323
2168
  */
2324
2169
  async function sendWeComMessage({ to, content, accountId, }) {
2325
- const resolvedAccountId = accountId ?? core.DEFAULT_ACCOUNT_ID;
2170
+ const resolvedAccountId = accountId ?? DEFAULT_ACCOUNT_ID;
2326
2171
  // 从 to 中提取 chatId(格式是 "${CHANNEL_ID}:chatId" 或直接是 chatId)
2327
2172
  const channelPrefix = new RegExp(`^${CHANNEL_ID}:`, "i");
2328
2173
  const chatId = to.replace(channelPrefix, "");
@@ -2372,7 +2217,6 @@ const wecomPlugin = {
2372
2217
  // Pairing approved for user
2373
2218
  },
2374
2219
  },
2375
- onboarding: wecomOnboardingAdapter,
2376
2220
  capabilities: {
2377
2221
  chatTypes: ["direct", "group"],
2378
2222
  reactions: false,
@@ -2384,11 +2228,11 @@ const wecomPlugin = {
2384
2228
  reload: { configPrefixes: [`channels.${CHANNEL_ID}`] },
2385
2229
  config: {
2386
2230
  // 列出所有账户 ID(最小实现只支持默认账户)
2387
- listAccountIds: () => [core.DEFAULT_ACCOUNT_ID],
2231
+ listAccountIds: () => [DEFAULT_ACCOUNT_ID],
2388
2232
  // 解析账户配置
2389
2233
  resolveAccount: (cfg) => resolveWeComAccount(cfg),
2390
2234
  // 获取默认账户 ID
2391
- defaultAccountId: () => core.DEFAULT_ACCOUNT_ID,
2235
+ defaultAccountId: () => DEFAULT_ACCOUNT_ID,
2392
2236
  // 设置账户启用状态
2393
2237
  setAccountEnabled: ({ cfg, enabled }) => {
2394
2238
  const wecomConfig = (cfg.channels?.[CHANNEL_ID] ?? {});
@@ -2444,7 +2288,7 @@ const wecomPlugin = {
2444
2288
  allowFrom: account.config.allowFrom ?? [],
2445
2289
  policyPath: `${basePath}dmPolicy`,
2446
2290
  allowFromPath: basePath,
2447
- approveHint: core.formatPairingApproveHint(CHANNEL_ID),
2291
+ approveHint: formatPairingApproveHint(CHANNEL_ID),
2448
2292
  normalizeEntry: (raw) => raw.replace(new RegExp(`^${CHANNEL_ID}:`, "i"), "").trim(),
2449
2293
  };
2450
2294
  },
@@ -2500,7 +2344,7 @@ const wecomPlugin = {
2500
2344
  return sendWeComMessage({ to, content: text, accountId: accountId ?? undefined });
2501
2345
  },
2502
2346
  sendMedia: async ({ to, text, mediaUrl, mediaLocalRoots, accountId }) => {
2503
- const resolvedAccountId = accountId ?? core.DEFAULT_ACCOUNT_ID;
2347
+ const resolvedAccountId = accountId ?? DEFAULT_ACCOUNT_ID;
2504
2348
  const channelPrefix = new RegExp(`^${CHANNEL_ID}:`, "i");
2505
2349
  const chatId = to.replace(channelPrefix, "");
2506
2350
  // 获取 WSClient 实例
@@ -2545,14 +2389,14 @@ const wecomPlugin = {
2545
2389
  },
2546
2390
  status: {
2547
2391
  defaultRuntime: {
2548
- accountId: core.DEFAULT_ACCOUNT_ID,
2392
+ accountId: DEFAULT_ACCOUNT_ID,
2549
2393
  running: false,
2550
2394
  lastStartAt: null,
2551
2395
  lastStopAt: null,
2552
2396
  lastError: null,
2553
2397
  },
2554
2398
  collectStatusIssues: (accounts) => accounts.flatMap((entry) => {
2555
- const accountId = String(entry.accountId ?? core.DEFAULT_ACCOUNT_ID);
2399
+ const accountId = String(entry.accountId ?? DEFAULT_ACCOUNT_ID);
2556
2400
  const enabled = entry.enabled !== false;
2557
2401
  const configured = entry.configured === true;
2558
2402
  if (!enabled) {
@@ -2719,7 +2563,7 @@ const inflightInitRequests = new Map();
2719
2563
  * @returns 完整的 response.body 配置对象(至少包含 url 字段)
2720
2564
  */
2721
2565
  async function fetchMcpConfig(category) {
2722
- const wsClient = getWeComWebSocket(core.DEFAULT_ACCOUNT_ID);
2566
+ const wsClient = getWeComWebSocket(DEFAULT_ACCOUNT_ID);
2723
2567
  if (!wsClient) {
2724
2568
  throw new Error("WSClient 未连接,无法拉取 MCP 配置");
2725
2569
  }
@@ -3460,7 +3304,7 @@ const plugin = {
3460
3304
  id: "wecom-openclaw-plugin",
3461
3305
  name: "企业微信",
3462
3306
  description: "企业微信 OpenClaw 插件",
3463
- configSchema: core.emptyPluginConfigSchema(),
3307
+ configSchema: emptyPluginConfigSchema(),
3464
3308
  register(api) {
3465
3309
  setWeComRuntime(api.runtime);
3466
3310
  api.registerChannel({ plugin: wecomPlugin });