"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.wecomPlugin = void 0; var _pluginSdk = require("openclaw/plugin-sdk"); var _index = require("./config/index.js"); var _gatewayMonitor = require("./gateway-monitor.js"); var _onboarding = require("./onboarding.js"); var _outbound = require("./outbound.js"); var _constants = require("./types/constants.js"); const meta = { id: "wecom", label: "WeCom", selectionLabel: "WeCom (plugin)", docsPath: "/channels/wecom", docsLabel: "wecom", blurb: "Enterprise WeCom intelligent bot (API mode) via encrypted webhooks + passive replies.", aliases: ["wechatwork", "wework", "qywx", "企微", "企业微信"], order: 85, quickstartAllowFrom: true }; function normalizeWecomMessagingTarget(raw) { const trimmed = raw.trim(); if (!trimmed) return undefined; return trimmed.replace(/^(wecom-agent|wecom|wechatwork|wework|qywx):/i, "").trim() || undefined; } const wecomPlugin = exports.wecomPlugin = { id: "wecom", meta, onboarding: _onboarding.wecomOnboardingAdapter, setup: { resolveAccountId: ({ cfg, accountId }) => { return accountId?.trim() || (0, _index.resolveDefaultWecomAccountId)(cfg) || _index.DEFAULT_ACCOUNT_ID; }, applyAccountConfig: ({ cfg, accountId, input }) => { const isWsMode = input.url === "ws" || input.url === "websocket"; if (isWsMode) { // websocket 模式: --bot-token → botId, --token → secret const botConfig = { connectionMode: "websocket", botId: input.botToken?.trim() || undefined, secret: input.token?.trim() || undefined }; return (0, _onboarding.setWecomBotConfig)(cfg, botConfig, accountId); } // webhook 模式: --token → token, --access-token → encodingAESKey const botConfig = { connectionMode: "webhook", token: input.token?.trim() ?? "", encodingAESKey: input.accessToken?.trim() ?? "" }; return (0, _onboarding.setWecomBotConfig)(cfg, botConfig, accountId); }, validateInput: ({ input }) => { const isWsMode = input.url === "ws" || input.url === "websocket"; if (isWsMode) { if (!input.botToken?.trim()) return "websocket 模式需要 --bot-token "; if (!input.token?.trim()) return "websocket 模式需要 --token "; } else { if (!input.token?.trim()) return "webhook 模式需要 --token "; } return null; } }, capabilities: { chatTypes: ["direct", "group"], media: true, reactions: false, threads: false, polls: false, nativeCommands: false, blockStreaming: true }, reload: { configPrefixes: ["channels.wecom"] }, // NOTE: We intentionally avoid Zod -> JSON Schema conversion at plugin-load time. // Some OpenClaw runtime environments load plugin modules via jiti in a way that can // surface zod `toJSONSchema()` binding issues (e.g. `this` undefined leading to `_zod` errors). // A permissive schema keeps config UX working while preventing startup failures. configSchema: { schema: { type: "object", additionalProperties: true, properties: {} } }, config: { listAccountIds: (cfg) => (0, _index.listWecomAccountIds)(cfg), resolveAccount: (cfg, accountId) => (0, _index.resolveWecomAccount)({ cfg: cfg, accountId }), defaultAccountId: (cfg) => (0, _index.resolveDefaultWecomAccountId)(cfg), setAccountEnabled: ({ cfg, accountId, enabled }) => (0, _pluginSdk.setAccountEnabledInConfigSection)({ cfg: cfg, sectionKey: "wecom", accountId, enabled, allowTopLevel: true }), deleteAccount: ({ cfg, accountId }) => (0, _pluginSdk.deleteAccountFromConfigSection)({ cfg: cfg, sectionKey: "wecom", accountId, clearBaseFields: ["bot", "agent"] }), isConfigured: (account, cfg) => { if (!account.configured) { return false; } return !(0, _index.resolveWecomAccountConflict)({ cfg: cfg, accountId: account.accountId }); }, unconfiguredReason: (account, cfg) => (0, _index.resolveWecomAccountConflict)({ cfg: cfg, accountId: account.accountId })?.message ?? "not configured", describeAccount: (account, cfg) => { const matrixMode = account.accountId !== _index.DEFAULT_ACCOUNT_ID; const conflict = (0, _index.resolveWecomAccountConflict)({ cfg: cfg, accountId: account.accountId }); return { accountId: account.accountId, name: account.name, enabled: account.enabled, configured: account.configured && !conflict, webhookPath: account.bot?.config ? matrixMode ? `${_constants.WEBHOOK_PATHS.BOT_PLUGIN}/${account.accountId}` : _constants.WEBHOOK_PATHS.BOT_PLUGIN : account.agent?.config ? matrixMode ? `${_constants.WEBHOOK_PATHS.AGENT_PLUGIN}/${account.accountId}` : _constants.WEBHOOK_PATHS.AGENT_PLUGIN : _constants.WEBHOOK_PATHS.BOT_PLUGIN }; }, resolveAllowFrom: ({ cfg, accountId }) => { const account = (0, _index.resolveWecomAccount)({ cfg: cfg, accountId }); // 与其他渠道保持一致:直接返回 allowFrom,空则允许所有人 const allowFrom = account.agent?.config.dm?.allowFrom ?? account.bot?.config.dm?.allowFrom ?? []; return allowFrom.map((entry) => String(entry)); }, formatAllowFrom: ({ allowFrom }) => allowFrom. map((entry) => String(entry).trim()). filter(Boolean). map((entry) => entry.toLowerCase()) }, // security 配置在 WeCom 中不需要,框架会通过 resolveAllowFrom 自动判断 groups: { // WeCom bots are usually mention-gated by the platform in groups already. resolveRequireMention: () => true }, threading: { resolveReplyToMode: () => "off" }, messaging: { normalizeTarget: normalizeWecomMessagingTarget, targetResolver: { looksLikeId: (raw) => Boolean(raw.trim()), hint: "" } }, outbound: { ..._outbound.wecomOutbound }, status: { defaultRuntime: { accountId: _index.DEFAULT_ACCOUNT_ID, running: false, lastStartAt: null, lastStopAt: null, lastError: null }, buildChannelSummary: ({ snapshot }) => ({ configured: snapshot.configured ?? false, running: snapshot.running ?? false, webhookPath: snapshot.webhookPath ?? null, lastStartAt: snapshot.lastStartAt ?? null, lastStopAt: snapshot.lastStopAt ?? null, lastError: snapshot.lastError ?? null, lastInboundAt: snapshot.lastInboundAt ?? null, lastOutboundAt: snapshot.lastOutboundAt ?? null, probe: snapshot.probe, lastProbeAt: snapshot.lastProbeAt ?? null }), probeAccount: async () => ({ ok: true }), buildAccountSnapshot: ({ account, runtime, cfg }) => { const conflict = (0, _index.resolveWecomAccountConflict)({ cfg: cfg, accountId: account.accountId }); return { accountId: account.accountId, name: account.name, enabled: account.enabled, configured: account.configured && !conflict, webhookPath: account.bot?.config ? account.accountId === _index.DEFAULT_ACCOUNT_ID ? _constants.WEBHOOK_PATHS.BOT_PLUGIN : `${_constants.WEBHOOK_PATHS.BOT_PLUGIN}/${account.accountId}` : account.agent?.config ? account.accountId === _index.DEFAULT_ACCOUNT_ID ? _constants.WEBHOOK_PATHS.AGENT_PLUGIN : `${_constants.WEBHOOK_PATHS.AGENT_PLUGIN}/${account.accountId}` : _constants.WEBHOOK_PATHS.BOT_PLUGIN, running: runtime?.running ?? false, lastStartAt: runtime?.lastStartAt ?? null, lastStopAt: runtime?.lastStopAt ?? null, lastError: runtime?.lastError ?? conflict?.message ?? null, lastInboundAt: runtime?.lastInboundAt ?? null, lastOutboundAt: runtime?.lastOutboundAt ?? null, dmPolicy: account.bot?.config.dm?.policy ?? "pairing" }; } }, gateway: { /** * **startAccount (启动账号)** * * WeCom lifecycle is long-running: keep webhook targets active until * gateway stop/reload aborts the account. */ startAccount: _gatewayMonitor.monitorWecomProvider, stopAccount: async (ctx) => { ctx.setStatus({ accountId: ctx.account.accountId, running: false, lastStopAt: Date.now() }); } } }; /* v9-296e37bd8199378d */