ylib-wecom-openclaw-plugin 2026.4.29
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 +596 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +99 -0
- package/dist/src/accounts.d.ts +57 -0
- package/dist/src/accounts.js +247 -0
- package/dist/src/agent/api-client.d.ts +95 -0
- package/dist/src/agent/api-client.js +425 -0
- package/dist/src/agent/handler.d.ts +64 -0
- package/dist/src/agent/handler.js +731 -0
- package/dist/src/agent/index.d.ts +5 -0
- package/dist/src/agent/index.js +21 -0
- package/dist/src/agent/webhook.d.ts +25 -0
- package/dist/src/agent/webhook.js +294 -0
- package/dist/src/agent/xml.d.ts +21 -0
- package/dist/src/agent/xml.js +43 -0
- package/dist/src/channel.d.ts +5 -0
- package/dist/src/channel.js +815 -0
- package/dist/src/chat-queue.d.ts +31 -0
- package/dist/src/chat-queue.js +53 -0
- package/dist/src/config-schema.d.ts +587 -0
- package/dist/src/config-schema.js +146 -0
- package/dist/src/const.d.ts +128 -0
- package/dist/src/const.js +168 -0
- package/dist/src/dm-policy.d.ts +29 -0
- package/dist/src/dm-policy.js +146 -0
- package/dist/src/dynamic-agent.d.ts +37 -0
- package/dist/src/dynamic-agent.js +67 -0
- package/dist/src/dynamic-routing.d.ts +65 -0
- package/dist/src/dynamic-routing.js +62 -0
- package/dist/src/endpoint-dispatch.d.ts +54 -0
- package/dist/src/endpoint-dispatch.js +967 -0
- package/dist/src/endpoint-event-adapter.d.ts +15 -0
- package/dist/src/endpoint-event-adapter.js +427 -0
- package/dist/src/group-policy.d.ts +30 -0
- package/dist/src/group-policy.js +126 -0
- package/dist/src/http.d.ts +27 -0
- package/dist/src/http.js +168 -0
- package/dist/src/im-runtime-telemetry.d.ts +25 -0
- package/dist/src/im-runtime-telemetry.js +68 -0
- package/dist/src/interface.d.ts +192 -0
- package/dist/src/interface.js +5 -0
- package/dist/src/markdown-chunk.d.ts +1 -0
- package/dist/src/markdown-chunk.js +396 -0
- package/dist/src/mcp/index.d.ts +6 -0
- package/dist/src/mcp/index.js +28 -0
- package/dist/src/mcp/interceptors/biz-error.d.ts +11 -0
- package/dist/src/mcp/interceptors/biz-error.js +73 -0
- package/dist/src/mcp/interceptors/doc-auth-error.d.ts +10 -0
- package/dist/src/mcp/interceptors/doc-auth-error.js +235 -0
- package/dist/src/mcp/interceptors/index.d.ts +35 -0
- package/dist/src/mcp/interceptors/index.js +143 -0
- package/dist/src/mcp/interceptors/msg-media.d.ts +11 -0
- package/dist/src/mcp/interceptors/msg-media.js +201 -0
- package/dist/src/mcp/interceptors/smartpage-create.d.ts +30 -0
- package/dist/src/mcp/interceptors/smartpage-create.js +252 -0
- package/dist/src/mcp/interceptors/smartpage-export.d.ts +17 -0
- package/dist/src/mcp/interceptors/smartpage-export.js +135 -0
- package/dist/src/mcp/interceptors/smartsheet-upload.d.ts +22 -0
- package/dist/src/mcp/interceptors/smartsheet-upload.js +388 -0
- package/dist/src/mcp/interceptors/types.d.ts +64 -0
- package/dist/src/mcp/interceptors/types.js +8 -0
- package/dist/src/mcp/schema.d.ts +11 -0
- package/dist/src/mcp/schema.js +115 -0
- package/dist/src/mcp/tool.d.ts +63 -0
- package/dist/src/mcp/tool.js +318 -0
- package/dist/src/mcp/transport.d.ts +94 -0
- package/dist/src/mcp/transport.js +702 -0
- package/dist/src/media-handler.d.ts +55 -0
- package/dist/src/media-handler.js +306 -0
- package/dist/src/media-uploader.d.ts +142 -0
- package/dist/src/media-uploader.js +446 -0
- package/dist/src/message-parser.d.ts +104 -0
- package/dist/src/message-parser.js +232 -0
- package/dist/src/message-sender.d.ts +54 -0
- package/dist/src/message-sender.js +210 -0
- package/dist/src/monitor.d.ts +69 -0
- package/dist/src/monitor.js +1846 -0
- package/dist/src/onboarding.d.ts +8 -0
- package/dist/src/onboarding.js +248 -0
- package/dist/src/openclaw-compat.d.ts +148 -0
- package/dist/src/openclaw-compat.js +839 -0
- package/dist/src/proactive-markdown-send.d.ts +14 -0
- package/dist/src/proactive-markdown-send.js +205 -0
- package/dist/src/reqid-store.d.ts +23 -0
- package/dist/src/reqid-store.js +136 -0
- package/dist/src/runtime.d.ts +2 -0
- package/dist/src/runtime.js +7 -0
- package/dist/src/shared/command-auth.d.ts +23 -0
- package/dist/src/shared/command-auth.js +112 -0
- package/dist/src/shared/xml-parser.d.ts +46 -0
- package/dist/src/shared/xml-parser.js +228 -0
- package/dist/src/state-dir-resolve.d.ts +2 -0
- package/dist/src/state-dir-resolve.js +33 -0
- package/dist/src/state-manager.d.ts +115 -0
- package/dist/src/state-manager.js +413 -0
- package/dist/src/target.d.ts +35 -0
- package/dist/src/target.js +71 -0
- package/dist/src/template-card-manager.d.ts +55 -0
- package/dist/src/template-card-manager.js +316 -0
- package/dist/src/template-card-parser.d.ts +37 -0
- package/dist/src/template-card-parser.js +672 -0
- package/dist/src/timeout.d.ts +20 -0
- package/dist/src/timeout.js +57 -0
- package/dist/src/types/account.d.ts +29 -0
- package/dist/src/types/account.js +5 -0
- package/dist/src/types/config.d.ts +98 -0
- package/dist/src/types/config.js +8 -0
- package/dist/src/types/constants.d.ts +42 -0
- package/dist/src/types/constants.js +45 -0
- package/dist/src/types/index.d.ts +7 -0
- package/dist/src/types/index.js +17 -0
- package/dist/src/types/message.d.ts +238 -0
- package/dist/src/types/message.js +6 -0
- package/dist/src/utils.d.ts +148 -0
- package/dist/src/utils.js +92 -0
- package/dist/src/version.d.ts +2 -0
- package/dist/src/version.js +28 -0
- package/dist/src/webhook/command-auth.d.ts +47 -0
- package/dist/src/webhook/command-auth.js +137 -0
- package/dist/src/webhook/gateway.d.ts +36 -0
- package/dist/src/webhook/gateway.js +297 -0
- package/dist/src/webhook/handler.d.ts +19 -0
- package/dist/src/webhook/handler.js +481 -0
- package/dist/src/webhook/helpers.d.ts +157 -0
- package/dist/src/webhook/helpers.js +936 -0
- package/dist/src/webhook/http.d.ts +27 -0
- package/dist/src/webhook/http.js +168 -0
- package/dist/src/webhook/index.d.ts +11 -0
- package/dist/src/webhook/index.js +43 -0
- package/dist/src/webhook/media.d.ts +30 -0
- package/dist/src/webhook/media.js +152 -0
- package/dist/src/webhook/monitor.d.ts +59 -0
- package/dist/src/webhook/monitor.js +1672 -0
- package/dist/src/webhook/state.d.ts +220 -0
- package/dist/src/webhook/state.js +568 -0
- package/dist/src/webhook/target.d.ts +41 -0
- package/dist/src/webhook/target.js +165 -0
- package/dist/src/webhook/types.d.ts +348 -0
- package/dist/src/webhook/types.js +36 -0
- package/dist/src/webhook/video-frame.d.ts +13 -0
- package/dist/src/webhook/video-frame.js +108 -0
- package/openclaw.plugin.json +19 -0
- package/package.json +96 -0
- package/schema.json +534 -0
- package/scripts/generate-schema.mjs +33 -0
- package/skills/wecom-contact/SKILL.md +162 -0
- package/skills/wecom-doc/SKILL.md +162 -0
- package/skills/wecom-doc/references/create-doc.md +56 -0
- package/skills/wecom-doc/references/edit-doc-content.md +68 -0
- package/skills/wecom-doc/references/get-doc-content.md +88 -0
- package/skills/wecom-doc/references/smartpage-create.md +125 -0
- package/skills/wecom-doc/references/smartpage-export.md +160 -0
- package/skills/wecom-meeting/SKILL.md +441 -0
- package/skills/wecom-meeting/references/example-full.md +30 -0
- package/skills/wecom-meeting/references/example-reminder.md +46 -0
- package/skills/wecom-meeting/references/example-security.md +22 -0
- package/skills/wecom-meeting/references/response-get-meeting-info.md +148 -0
- package/skills/wecom-msg/SKILL.md +157 -0
- package/skills/wecom-msg/references/api-get-messages.md +93 -0
- package/skills/wecom-msg/references/api-get-msg-chat-list.md +58 -0
- package/skills/wecom-msg/references/api-get-msg-media.md +44 -0
- package/skills/wecom-msg/references/api-send-message.md +39 -0
- package/skills/wecom-preflight/SKILL.md +141 -0
- package/skills/wecom-schedule/SKILL.md +161 -0
- package/skills/wecom-schedule/references/api-check-availability.md +56 -0
- package/skills/wecom-schedule/references/api-create-schedule.md +38 -0
- package/skills/wecom-schedule/references/api-get-schedule-detail.md +81 -0
- package/skills/wecom-schedule/references/api-update-schedule.md +32 -0
- package/skills/wecom-schedule/references/ref-reminders.md +24 -0
- package/skills/wecom-send-media/SKILL.md +68 -0
- package/skills/wecom-send-template-card/SKILL.md +157 -0
- package/skills/wecom-send-template-card/references/api-template-card-types.md +358 -0
- package/skills/wecom-smartsheet/SKILL.md +164 -0
- package/skills/wecom-smartsheet/references/smartsheet-cell-value-formats.md +163 -0
- package/skills/wecom-smartsheet/references/smartsheet-field-types.md +44 -0
- package/skills/wecom-smartsheet/references/smartsheet-get-records.md +96 -0
- package/skills/wecom-smartsheet/references/webhook-examples.md +185 -0
- package/skills/wecom-smartsheet/references/webhook-fallback.md +184 -0
- package/skills/wecom-todo/SKILL.md +392 -0
- package/skills/wecom-todo/examples/workflows.md +163 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
exports.__esModule = true;
|
|
10
|
+
var plugin_sdk_1 = require("ylib-openclaw/plugin-sdk");
|
|
11
|
+
var channel_js_1 = require("./src/channel.js");
|
|
12
|
+
var config_schema_js_1 = require("./src/config-schema.js");
|
|
13
|
+
var runtime_js_1 = require("./src/runtime.js");
|
|
14
|
+
var const_js_1 = require("./src/const.js");
|
|
15
|
+
var webhook_js_1 = require("./src/agent/webhook.js");
|
|
16
|
+
var index_js_1 = require("./src/webhook/index.js");
|
|
17
|
+
var channel_js_2 = require("./src/channel.js");
|
|
18
|
+
__createBinding(exports, channel_js_2, "wecomPlugin");
|
|
19
|
+
var plugin = {
|
|
20
|
+
id: "wecom-openclaw-plugin",
|
|
21
|
+
name: "企业微信",
|
|
22
|
+
description: "企业微信 OpenClaw 插件",
|
|
23
|
+
configSchema: plugin_sdk_1.buildChannelConfigSchema(config_schema_js_1.WeComConfigSchema),
|
|
24
|
+
wecomPlugin: channel_js_1.wecomPlugin,
|
|
25
|
+
register: function (api) {
|
|
26
|
+
runtime_js_1.setWeComRuntime(api.runtime);
|
|
27
|
+
api.registerChannel({ plugin: channel_js_1.wecomPlugin });
|
|
28
|
+
// 注册 wecom_mcp:通过 HTTP 直接调用企业微信 MCP Server
|
|
29
|
+
// api.registerTool(
|
|
30
|
+
// (ctx: OpenClawPluginToolContext) => {
|
|
31
|
+
// const trustedRequesterUserId =
|
|
32
|
+
// ctx.messageChannel === CHANNEL_ID ? ctx.requesterSenderId?.trim() ?? undefined : undefined;
|
|
33
|
+
// // 按 sessionKey 精确取回「原始大小写」的 chatId / chatType。
|
|
34
|
+
// // 数据由 monitor.ts 在消息入站时通过 setSessionChatInfo 写入,
|
|
35
|
+
// // 避免 parseSessionKeyChat 反解导致 chatId 被 OpenClaw core 小写化
|
|
36
|
+
// // (小写后的 chatId 调用企业微信 aibot_send_biz_msg 会报 invalid chatid)。
|
|
37
|
+
// const sessionChat = getSessionChatInfo(ctx.sessionKey);
|
|
38
|
+
// console.log(
|
|
39
|
+
// `[mcp] registerTool ctx: sessionKey="${ctx.sessionKey}", messageChannel="${ctx.messageChannel}", ` +
|
|
40
|
+
// `requesterSenderId="${ctx.requesterSenderId}", agentAccountId="${ctx.agentAccountId}", ` +
|
|
41
|
+
// `sessionChat=${JSON.stringify(sessionChat)}`,
|
|
42
|
+
// );
|
|
43
|
+
// return createWeComMcpTool({
|
|
44
|
+
// requesterUserId: trustedRequesterUserId,
|
|
45
|
+
// accountId: ctx.agentAccountId,
|
|
46
|
+
// chatId: sessionChat?.chatId,
|
|
47
|
+
// chatType: sessionChat?.chatType,
|
|
48
|
+
// });
|
|
49
|
+
// },
|
|
50
|
+
// { name: "wecom_mcp" },
|
|
51
|
+
// );
|
|
52
|
+
var registerHttpRoute = api.registerHttpRoute;
|
|
53
|
+
if (typeof registerHttpRoute === "function") {
|
|
54
|
+
var agentWebhookHandler = webhook_js_1.createWecomAgentWebhookHandler(api.runtime);
|
|
55
|
+
// 注册 Agent 模式 HTTP 路由(prefix match 覆盖带 accountId 的子路径)
|
|
56
|
+
registerHttpRoute({
|
|
57
|
+
path: const_js_1.WEBHOOK_PATHS.AGENT_PLUGIN,
|
|
58
|
+
handler: agentWebhookHandler,
|
|
59
|
+
auth: "plugin",
|
|
60
|
+
match: "prefix"
|
|
61
|
+
});
|
|
62
|
+
registerHttpRoute({
|
|
63
|
+
path: const_js_1.WEBHOOK_PATHS.AGENT,
|
|
64
|
+
handler: agentWebhookHandler,
|
|
65
|
+
auth: "plugin",
|
|
66
|
+
match: "prefix"
|
|
67
|
+
});
|
|
68
|
+
// ── 注册 bot Webhook HTTP 路由 ────────────────────────────────────────
|
|
69
|
+
// 前缀匹配模式,同时覆盖 /plugins/wecom 和 /wecom 路径
|
|
70
|
+
var webhookRoutes = [const_js_1.WEBHOOK_PATHS.BOT_PLUGIN, const_js_1.WEBHOOK_PATHS.BOT_ALT, const_js_1.WEBHOOK_PATHS.BOT];
|
|
71
|
+
for (var _i = 0, webhookRoutes_1 = webhookRoutes; _i < webhookRoutes_1.length; _i++) {
|
|
72
|
+
var routePath = webhookRoutes_1[_i];
|
|
73
|
+
registerHttpRoute({
|
|
74
|
+
path: routePath,
|
|
75
|
+
handler: index_js_1.handleWecomWebhookRequest,
|
|
76
|
+
auth: "plugin",
|
|
77
|
+
match: "prefix"
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
console.warn("[wecom] host api.registerHttpRoute unavailable; skip webhook route registration");
|
|
83
|
+
}
|
|
84
|
+
// 注入媒体发送指令和文件大小限制提示词(仅对企业微信 channel 生效)
|
|
85
|
+
api.on("before_prompt_build", function (_event, ctx) {
|
|
86
|
+
// 只在企业微信 channel 的会话中注入,避免影响其他 channel 插件
|
|
87
|
+
if ((ctx === null || ctx === void 0 ? void 0 : ctx.channelId) !== const_js_1.CHANNEL_ID) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
appendSystemContext: [
|
|
92
|
+
"重要:涉及发送图片/视频/语音/文件给用户时,请务必使用 `MEDIA:` 指令。详见 wecom-send-media 这个 skill(技能)。",
|
|
93
|
+
"重要:当需要向用户发送结构化卡片消息(如通知、投票、按钮选择等)时,请在回复中直接输出 JSON 代码块(```json ... ```),其中 card_type 字段标明卡片类型。详见 wecom-send-template-card 技能。"
|
|
94
|
+
].join("\n")
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
exports["default"] = plugin;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { OpenClawConfig } from "ylib-openclaw/plugin-sdk";
|
|
2
|
+
import type { WeComConfig, WeComAccountConfig, ResolvedWeComAccount } from "./utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* 企业微信多账号配置结构(扩展 WeComConfig)
|
|
5
|
+
*/
|
|
6
|
+
export interface WeComMultiAccountConfig extends WeComConfig {
|
|
7
|
+
/** 默认账号 ID */
|
|
8
|
+
defaultAccount?: string;
|
|
9
|
+
/** 多账号配置 */
|
|
10
|
+
accounts?: Record<string, WeComAccountConfig>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 判断是否为多账号模式(即配置中存在 accounts 字段)。
|
|
14
|
+
* 用于区分单账号/多账号模式的分支判断,替代 `accountId === DEFAULT_ACCOUNT_ID` 的不可靠判断。
|
|
15
|
+
*/
|
|
16
|
+
export declare function hasMultiAccounts(cfg: OpenClawConfig): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* 列出所有企业微信账号 ID。
|
|
19
|
+
* 如果没有 accounts 字段,返回 [DEFAULT_ACCOUNT_ID] 以向后兼容。
|
|
20
|
+
*/
|
|
21
|
+
export declare function listWeComAccountIds(cfg: OpenClawConfig): string[];
|
|
22
|
+
/**
|
|
23
|
+
* 解析默认账号 ID。
|
|
24
|
+
*
|
|
25
|
+
* 优先级:
|
|
26
|
+
* 1. 显式设置的 defaultAccount
|
|
27
|
+
* 2. 包含 DEFAULT_ACCOUNT_ID 的账号列表
|
|
28
|
+
* 3. 字母序第一个账号
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveDefaultWeComAccountId(cfg: OpenClawConfig): string;
|
|
31
|
+
/**
|
|
32
|
+
* 解析单个企业微信账号的完整配置。
|
|
33
|
+
*
|
|
34
|
+
* 支持:
|
|
35
|
+
* - 显式指定 accountId → 使用该 accountId
|
|
36
|
+
* - 未指定 → 使用默认账号
|
|
37
|
+
* - 单账号模式(无 accounts 字段) → 直接读取顶层配置
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveWeComAccountMulti(params: {
|
|
40
|
+
cfg: OpenClawConfig;
|
|
41
|
+
accountId?: string | null;
|
|
42
|
+
}): ResolvedWeComAccount;
|
|
43
|
+
/**
|
|
44
|
+
* 列出所有已启用且已配置凭据的账号。
|
|
45
|
+
*/
|
|
46
|
+
export declare function listEnabledWeComAccounts(cfg: OpenClawConfig): ResolvedWeComAccount[];
|
|
47
|
+
/**
|
|
48
|
+
* 写入企业微信账户配置(自动区分单账号/多账号模式)。
|
|
49
|
+
*
|
|
50
|
+
* - 单账号模式(无 accounts 字段):写入顶层 channels.wecom
|
|
51
|
+
* - 多账号模式:写入 channels.wecom.accounts[accountId]
|
|
52
|
+
*
|
|
53
|
+
* @param cfg 当前全局配置
|
|
54
|
+
* @param updates 要写入的部分配置字段
|
|
55
|
+
* @param accountId 目标账号 ID(默认写入默认账号)
|
|
56
|
+
*/
|
|
57
|
+
export declare function setWeComAccountMulti(cfg: OpenClawConfig, updates: Partial<WeComConfig>, accountId?: string): OpenClawConfig;
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
14
|
+
var t = {};
|
|
15
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
16
|
+
t[p] = s[p];
|
|
17
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
18
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
19
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
20
|
+
t[p[i]] = s[p[i]];
|
|
21
|
+
}
|
|
22
|
+
return t;
|
|
23
|
+
};
|
|
24
|
+
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
|
25
|
+
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
|
26
|
+
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
|
27
|
+
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
|
28
|
+
r[k] = a[j];
|
|
29
|
+
return r;
|
|
30
|
+
};
|
|
31
|
+
exports.__esModule = true;
|
|
32
|
+
exports.setWeComAccountMulti = exports.listEnabledWeComAccounts = exports.resolveWeComAccountMulti = exports.resolveDefaultWeComAccountId = exports.listWeComAccountIds = exports.hasMultiAccounts = void 0;
|
|
33
|
+
var plugin_sdk_1 = require("ylib-openclaw/plugin-sdk");
|
|
34
|
+
var const_js_1 = require("./const.js");
|
|
35
|
+
var utils_js_1 = require("./utils.js");
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// 账号列举
|
|
38
|
+
// ============================================================================
|
|
39
|
+
/**
|
|
40
|
+
* 列出 accounts 字段中配置的所有账号 ID(已 normalize)。
|
|
41
|
+
*/
|
|
42
|
+
function listConfiguredAccountIds(cfg) {
|
|
43
|
+
var _a, _b;
|
|
44
|
+
var accounts = (_b = (_a = cfg.channels) === null || _a === void 0 ? void 0 : _a[const_js_1.CHANNEL_ID]) === null || _b === void 0 ? void 0 : _b.accounts;
|
|
45
|
+
if (!accounts || typeof accounts !== "object") {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
return Object.keys(accounts).filter(Boolean).map(plugin_sdk_1.normalizeAccountId);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 判断是否为多账号模式(即配置中存在 accounts 字段)。
|
|
52
|
+
* 用于区分单账号/多账号模式的分支判断,替代 `accountId === DEFAULT_ACCOUNT_ID` 的不可靠判断。
|
|
53
|
+
*/
|
|
54
|
+
function hasMultiAccounts(cfg) {
|
|
55
|
+
return listConfiguredAccountIds(cfg).length > 0;
|
|
56
|
+
}
|
|
57
|
+
exports.hasMultiAccounts = hasMultiAccounts;
|
|
58
|
+
/**
|
|
59
|
+
* 列出所有企业微信账号 ID。
|
|
60
|
+
* 如果没有 accounts 字段,返回 [DEFAULT_ACCOUNT_ID] 以向后兼容。
|
|
61
|
+
*/
|
|
62
|
+
function listWeComAccountIds(cfg) {
|
|
63
|
+
var ids = listConfiguredAccountIds(cfg);
|
|
64
|
+
if (ids.length === 0) {
|
|
65
|
+
// 向后兼容:未配置 accounts 时使用默认账号
|
|
66
|
+
return [plugin_sdk_1.DEFAULT_ACCOUNT_ID];
|
|
67
|
+
}
|
|
68
|
+
return __spreadArrays(ids).sort(function (a, b) { return a.localeCompare(b); });
|
|
69
|
+
}
|
|
70
|
+
exports.listWeComAccountIds = listWeComAccountIds;
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// 默认账号解析
|
|
73
|
+
// ============================================================================
|
|
74
|
+
/**
|
|
75
|
+
* 解析默认账号 ID。
|
|
76
|
+
*
|
|
77
|
+
* 优先级:
|
|
78
|
+
* 1. 显式设置的 defaultAccount
|
|
79
|
+
* 2. 包含 DEFAULT_ACCOUNT_ID 的账号列表
|
|
80
|
+
* 3. 字母序第一个账号
|
|
81
|
+
*/
|
|
82
|
+
function resolveDefaultWeComAccountId(cfg) {
|
|
83
|
+
var _a, _b, _c;
|
|
84
|
+
var wecomConfig = (_a = cfg.channels) === null || _a === void 0 ? void 0 : _a[const_js_1.CHANNEL_ID];
|
|
85
|
+
var preferred = (_b = wecomConfig === null || wecomConfig === void 0 ? void 0 : wecomConfig.defaultAccount) === null || _b === void 0 ? void 0 : _b.trim();
|
|
86
|
+
if (preferred) {
|
|
87
|
+
return plugin_sdk_1.normalizeAccountId(preferred);
|
|
88
|
+
}
|
|
89
|
+
var ids = listWeComAccountIds(cfg);
|
|
90
|
+
if (ids.includes(plugin_sdk_1.DEFAULT_ACCOUNT_ID)) {
|
|
91
|
+
return plugin_sdk_1.DEFAULT_ACCOUNT_ID;
|
|
92
|
+
}
|
|
93
|
+
return (_c = ids[0]) !== null && _c !== void 0 ? _c : plugin_sdk_1.DEFAULT_ACCOUNT_ID;
|
|
94
|
+
}
|
|
95
|
+
exports.resolveDefaultWeComAccountId = resolveDefaultWeComAccountId;
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// 配置合并
|
|
98
|
+
// ============================================================================
|
|
99
|
+
/**
|
|
100
|
+
* 合并顶层配置与账号级配置(账号级覆盖顶层)。
|
|
101
|
+
*
|
|
102
|
+
* 顶层字段(如 dmPolicy、allowFrom)作为所有账号的默认值,
|
|
103
|
+
* accounts.xxx 中的字段会覆盖顶层的同名字段。
|
|
104
|
+
* 对于 groups 等嵌套 Record 对象,使用深层合并(账号级条目覆盖同 key,但不丢失基础配置中的其他 key)。
|
|
105
|
+
*/
|
|
106
|
+
function mergeWeComAccountConfig(cfg, accountId) {
|
|
107
|
+
var _a;
|
|
108
|
+
var wecomConfig = (_a = cfg.channels) === null || _a === void 0 ? void 0 : _a[const_js_1.CHANNEL_ID];
|
|
109
|
+
// 提取基础配置(排除 accounts 和 defaultAccount 字段避免递归)
|
|
110
|
+
var _b = wecomConfig !== null && wecomConfig !== void 0 ? wecomConfig : {}, _ignored = _b.accounts, _da = _b.defaultAccount, base = __rest(_b, ["accounts", "defaultAccount"]);
|
|
111
|
+
// 查找账号级覆盖(支持 normalize 后的 key 匹配)
|
|
112
|
+
var account = findAccountConfig(wecomConfig === null || wecomConfig === void 0 ? void 0 : wecomConfig.accounts, accountId);
|
|
113
|
+
// 深层合并:对 groups 做嵌套合并,其余字段用账号级覆盖
|
|
114
|
+
var baseGroups = base.groups, baseRest = __rest(base, ["groups"]);
|
|
115
|
+
var accountGroups = account.groups, accountRest = __rest(account, ["groups"]);
|
|
116
|
+
var mergedGroups = baseGroups || accountGroups
|
|
117
|
+
? __assign(__assign({}, baseGroups), accountGroups) : undefined;
|
|
118
|
+
return __assign(__assign(__assign({}, baseRest), accountRest), (mergedGroups !== undefined ? { groups: mergedGroups } : {}));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 在 accounts Record 中按 normalize 后的 accountId 查找配置。
|
|
122
|
+
* 避免因大小写差异导致找不到账号。
|
|
123
|
+
*/
|
|
124
|
+
function findAccountConfig(accounts, accountId) {
|
|
125
|
+
if (!accounts)
|
|
126
|
+
return {};
|
|
127
|
+
// 精确匹配优先
|
|
128
|
+
if (accounts[accountId])
|
|
129
|
+
return accounts[accountId];
|
|
130
|
+
// normalize 后匹配
|
|
131
|
+
var normalized = plugin_sdk_1.normalizeAccountId(accountId);
|
|
132
|
+
for (var _i = 0, _a = Object.entries(accounts); _i < _a.length; _i++) {
|
|
133
|
+
var _b = _a[_i], key = _b[0], value = _b[1];
|
|
134
|
+
if (plugin_sdk_1.normalizeAccountId(key) === normalized)
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
return {};
|
|
138
|
+
}
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// 账号解析
|
|
141
|
+
// ============================================================================
|
|
142
|
+
/**
|
|
143
|
+
* 解析单个企业微信账号的完整配置。
|
|
144
|
+
*
|
|
145
|
+
* 支持:
|
|
146
|
+
* - 显式指定 accountId → 使用该 accountId
|
|
147
|
+
* - 未指定 → 使用默认账号
|
|
148
|
+
* - 单账号模式(无 accounts 字段) → 直接读取顶层配置
|
|
149
|
+
*/
|
|
150
|
+
function resolveWeComAccountMulti(params) {
|
|
151
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
152
|
+
var hasExplicitId = typeof params.accountId === "string" && params.accountId.trim() !== "";
|
|
153
|
+
var accountId = hasExplicitId
|
|
154
|
+
? plugin_sdk_1.normalizeAccountId(params.accountId)
|
|
155
|
+
: resolveDefaultWeComAccountId(params.cfg);
|
|
156
|
+
var wecomConfig = (_a = params.cfg.channels) === null || _a === void 0 ? void 0 : _a[const_js_1.CHANNEL_ID];
|
|
157
|
+
// 顶层 enabled 状态
|
|
158
|
+
var baseEnabled = (wecomConfig === null || wecomConfig === void 0 ? void 0 : wecomConfig.enabled) !== false;
|
|
159
|
+
// 合并配置
|
|
160
|
+
var merged = mergeWeComAccountConfig(params.cfg, accountId);
|
|
161
|
+
// 账号级 enabled 状态
|
|
162
|
+
var accountEnabled = merged.enabled !== false;
|
|
163
|
+
// 解析 Agent 子配置
|
|
164
|
+
var agentCfg = merged.agent;
|
|
165
|
+
var agent;
|
|
166
|
+
if ((agentCfg === null || agentCfg === void 0 ? void 0 : agentCfg.corpId) && (agentCfg === null || agentCfg === void 0 ? void 0 : agentCfg.corpSecret) && (agentCfg === null || agentCfg === void 0 ? void 0 : agentCfg.token) && (agentCfg === null || agentCfg === void 0 ? void 0 : agentCfg.encodingAESKey)) {
|
|
167
|
+
agent = {
|
|
168
|
+
accountId: accountId,
|
|
169
|
+
enabled: baseEnabled && accountEnabled,
|
|
170
|
+
configured: true,
|
|
171
|
+
corpId: agentCfg.corpId,
|
|
172
|
+
corpSecret: agentCfg.corpSecret,
|
|
173
|
+
agentId: typeof agentCfg.agentId === "string" ? Number(agentCfg.agentId) || undefined : agentCfg.agentId,
|
|
174
|
+
token: agentCfg.token,
|
|
175
|
+
encodingAESKey: agentCfg.encodingAESKey,
|
|
176
|
+
config: agentCfg,
|
|
177
|
+
network: merged.network
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
accountId: accountId,
|
|
182
|
+
name: (_b = merged.name) !== null && _b !== void 0 ? _b : "企业微信",
|
|
183
|
+
enabled: baseEnabled && accountEnabled,
|
|
184
|
+
websocketUrl: merged.websocketUrl || utils_js_1.DefaultWsUrl,
|
|
185
|
+
botId: (_c = merged.botId) !== null && _c !== void 0 ? _c : "",
|
|
186
|
+
secret: (_d = merged.secret) !== null && _d !== void 0 ? _d : "",
|
|
187
|
+
sendThinkingMessage: (_e = merged.sendThinkingMessage) !== null && _e !== void 0 ? _e : true,
|
|
188
|
+
// 只接受显式 true,未配置或历史配置缺失时都保持默认完整输出。
|
|
189
|
+
showFinalAnswerOnly: merged.showFinalAnswerOnly === true,
|
|
190
|
+
config: merged,
|
|
191
|
+
agent: agent,
|
|
192
|
+
token: (_f = merged.token) !== null && _f !== void 0 ? _f : "",
|
|
193
|
+
encodingAESKey: (_g = merged.encodingAESKey) !== null && _g !== void 0 ? _g : "",
|
|
194
|
+
receiveId: (_h = merged.receiveId) !== null && _h !== void 0 ? _h : ""
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
exports.resolveWeComAccountMulti = resolveWeComAccountMulti;
|
|
198
|
+
// ============================================================================
|
|
199
|
+
// 批量查询
|
|
200
|
+
// ============================================================================
|
|
201
|
+
/**
|
|
202
|
+
* 列出所有已启用且已配置凭据的账号。
|
|
203
|
+
*/
|
|
204
|
+
function listEnabledWeComAccounts(cfg) {
|
|
205
|
+
return listWeComAccountIds(cfg)
|
|
206
|
+
.map(function (accountId) { return resolveWeComAccountMulti({ cfg: cfg, accountId: accountId }); })
|
|
207
|
+
.filter(function (account) {
|
|
208
|
+
var _a, _b, _c;
|
|
209
|
+
if (!account.enabled)
|
|
210
|
+
return false;
|
|
211
|
+
var hasBotCredentials = Boolean(((_a = account.botId) === null || _a === void 0 ? void 0 : _a.trim()) && ((_b = account.secret) === null || _b === void 0 ? void 0 : _b.trim()));
|
|
212
|
+
var hasAgentCredentials = Boolean((_c = account.agent) === null || _c === void 0 ? void 0 : _c.configured);
|
|
213
|
+
return hasBotCredentials || hasAgentCredentials;
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
exports.listEnabledWeComAccounts = listEnabledWeComAccounts;
|
|
217
|
+
// ============================================================================
|
|
218
|
+
// 配置写入(多账号感知)
|
|
219
|
+
// ============================================================================
|
|
220
|
+
/**
|
|
221
|
+
* 写入企业微信账户配置(自动区分单账号/多账号模式)。
|
|
222
|
+
*
|
|
223
|
+
* - 单账号模式(无 accounts 字段):写入顶层 channels.wecom
|
|
224
|
+
* - 多账号模式:写入 channels.wecom.accounts[accountId]
|
|
225
|
+
*
|
|
226
|
+
* @param cfg 当前全局配置
|
|
227
|
+
* @param updates 要写入的部分配置字段
|
|
228
|
+
* @param accountId 目标账号 ID(默认写入默认账号)
|
|
229
|
+
*/
|
|
230
|
+
function setWeComAccountMulti(cfg, updates, accountId) {
|
|
231
|
+
var _a, _b, _c;
|
|
232
|
+
var _d, _e, _f, _g, _h, _j;
|
|
233
|
+
var resolvedAccountId = accountId !== null && accountId !== void 0 ? accountId : resolveDefaultWeComAccountId(cfg);
|
|
234
|
+
var isMulti = hasMultiAccounts(cfg);
|
|
235
|
+
if (!isMulti) {
|
|
236
|
+
// 单账号模式:合并到顶层
|
|
237
|
+
var existing = ((_e = (_d = cfg.channels) === null || _d === void 0 ? void 0 : _d[const_js_1.CHANNEL_ID]) !== null && _e !== void 0 ? _e : {});
|
|
238
|
+
var merged = __assign(__assign({}, existing), updates);
|
|
239
|
+
return __assign(__assign({}, cfg), { channels: __assign(__assign({}, cfg.channels), (_a = {}, _a[const_js_1.CHANNEL_ID] = merged, _a)) });
|
|
240
|
+
}
|
|
241
|
+
// 多账号模式:合并到 accounts[accountId]
|
|
242
|
+
var wecomConfig = ((_g = (_f = cfg.channels) === null || _f === void 0 ? void 0 : _f[const_js_1.CHANNEL_ID]) !== null && _g !== void 0 ? _g : {});
|
|
243
|
+
var existingAccount = (_j = (_h = wecomConfig.accounts) === null || _h === void 0 ? void 0 : _h[resolvedAccountId]) !== null && _j !== void 0 ? _j : {};
|
|
244
|
+
var mergedAccount = __assign(__assign({}, existingAccount), updates);
|
|
245
|
+
return __assign(__assign({}, cfg), { channels: __assign(__assign({}, cfg.channels), (_b = {}, _b[const_js_1.CHANNEL_ID] = __assign(__assign({}, wecomConfig), { accounts: __assign(__assign({}, wecomConfig.accounts), (_c = {}, _c[resolvedAccountId] = mergedAccount, _c)) }), _b)) });
|
|
246
|
+
}
|
|
247
|
+
exports.setWeComAccountMulti = setWeComAccountMulti;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeCom Agent API 客户端
|
|
3
|
+
* 管理 AccessToken 缓存和 API 调用
|
|
4
|
+
*/
|
|
5
|
+
/// <reference types="node" />
|
|
6
|
+
import type { ResolvedAgentAccount } from "../types/index.js";
|
|
7
|
+
/**
|
|
8
|
+
* **getAccessToken (获取 AccessToken)**
|
|
9
|
+
*
|
|
10
|
+
* 获取企业微信 API 调用所需的 AccessToken。
|
|
11
|
+
* 具备自动缓存和过期刷新机制。
|
|
12
|
+
*
|
|
13
|
+
* @param agent Agent 账号信息
|
|
14
|
+
* @returns 有效的 AccessToken
|
|
15
|
+
*/
|
|
16
|
+
export declare function getAccessToken(agent: ResolvedAgentAccount): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* **sendText (发送文本消息)**
|
|
19
|
+
*
|
|
20
|
+
* 调用 `message/send` (Agent) 或 `appchat/send` (群聊) 发送文本。
|
|
21
|
+
*
|
|
22
|
+
* @param params.agent 发送方 Agent
|
|
23
|
+
* @param params.toUser 接收用户 ID (单聊可选,可与 toParty/toTag 同时使用)
|
|
24
|
+
* @param params.toParty 接收部门 ID (单聊可选)
|
|
25
|
+
* @param params.toTag 接收标签 ID (单聊可选)
|
|
26
|
+
* @param params.chatId 接收群 ID (群聊模式必填,互斥)
|
|
27
|
+
* @param params.text 消息内容
|
|
28
|
+
*/
|
|
29
|
+
export declare function sendText(params: {
|
|
30
|
+
agent: ResolvedAgentAccount;
|
|
31
|
+
toUser?: string;
|
|
32
|
+
toParty?: string;
|
|
33
|
+
toTag?: string;
|
|
34
|
+
chatId?: string;
|
|
35
|
+
text: string;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* **uploadMedia (上传媒体文件)**
|
|
39
|
+
*
|
|
40
|
+
* 上传临时素材到企业微信。
|
|
41
|
+
* 素材有效期为 3 天。
|
|
42
|
+
*
|
|
43
|
+
* @param params.type 媒体类型 (image, voice, video, file)
|
|
44
|
+
* @param params.buffer 文件二进制数据
|
|
45
|
+
* @param params.filename 文件名 (需包含正确扩展名)
|
|
46
|
+
* @returns 媒体 ID (media_id)
|
|
47
|
+
*/
|
|
48
|
+
export declare function uploadMedia(params: {
|
|
49
|
+
agent: ResolvedAgentAccount;
|
|
50
|
+
type: "image" | "voice" | "video" | "file";
|
|
51
|
+
buffer: Buffer;
|
|
52
|
+
filename: string;
|
|
53
|
+
}): Promise<string>;
|
|
54
|
+
/**
|
|
55
|
+
* **sendMedia (发送媒体消息)**
|
|
56
|
+
*
|
|
57
|
+
* 发送图片、音频、视频或文件。需先通过 `uploadMedia` 获取 media_id。
|
|
58
|
+
*
|
|
59
|
+
* @param params.agent 发送方 Agent
|
|
60
|
+
* @param params.toUser 接收用户 ID (单聊可选)
|
|
61
|
+
* @param params.toParty 接收部门 ID (单聊可选)
|
|
62
|
+
* @param params.toTag 接收标签 ID (单聊可选)
|
|
63
|
+
* @param params.chatId 接收群 ID (群聊模式必填)
|
|
64
|
+
* @param params.mediaId 媒体 ID
|
|
65
|
+
* @param params.mediaType 媒体类型
|
|
66
|
+
* @param params.title 视频标题 (可选)
|
|
67
|
+
* @param params.description 视频描述 (可选)
|
|
68
|
+
*/
|
|
69
|
+
export declare function sendMedia(params: {
|
|
70
|
+
agent: ResolvedAgentAccount;
|
|
71
|
+
toUser?: string;
|
|
72
|
+
toParty?: string;
|
|
73
|
+
toTag?: string;
|
|
74
|
+
chatId?: string;
|
|
75
|
+
mediaId: string;
|
|
76
|
+
mediaType: "image" | "voice" | "video" | "file";
|
|
77
|
+
title?: string;
|
|
78
|
+
description?: string;
|
|
79
|
+
}): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* **downloadMedia (下载媒体文件)**
|
|
82
|
+
*
|
|
83
|
+
* 通过 media_id 从企业微信服务器下载临时素材。
|
|
84
|
+
*
|
|
85
|
+
* @returns { buffer, contentType }
|
|
86
|
+
*/
|
|
87
|
+
export declare function downloadMedia(params: {
|
|
88
|
+
agent: ResolvedAgentAccount;
|
|
89
|
+
mediaId: string;
|
|
90
|
+
maxBytes?: number;
|
|
91
|
+
}): Promise<{
|
|
92
|
+
buffer: Buffer;
|
|
93
|
+
contentType: string;
|
|
94
|
+
filename?: string;
|
|
95
|
+
}>;
|