@zhin.js/adapter-wecom 0.0.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.
package/lib/index.js ADDED
@@ -0,0 +1,115 @@
1
+ /**
2
+ * 企业微信适配器入口:类型扩展、导出、注册
3
+ */
4
+ import { usePlugin } from 'zhin.js';
5
+ import { WecomAdapter } from './adapter.js';
6
+ import { registerWecomPlatformPermitChecker, } from './platform-permit.js';
7
+ export * from './types.js';
8
+ export { WecomEndpoint } from './endpoint.js';
9
+ export { WecomAdapter } from './adapter.js';
10
+ const plugin = usePlugin();
11
+ const { provide, useContext } = plugin;
12
+ useContext('router', (router) => {
13
+ provide({
14
+ name: 'wecom',
15
+ description: 'WeCom (企业微信) Endpoint Adapter',
16
+ mounted: async (p) => {
17
+ const adapter = new WecomAdapter(p, router);
18
+ await adapter.start();
19
+ return adapter;
20
+ },
21
+ dispose: async (adapter) => {
22
+ await adapter.stop();
23
+ },
24
+ });
25
+ });
26
+ useContext('tool', 'wecom', (toolService, wecom) => {
27
+ const disposers = [];
28
+ disposers.push(registerWecomPlatformPermitChecker());
29
+ disposers.push(toolService.addTool({
30
+ name: 'wecom_get_user',
31
+ description: '获取企业微信用户信息',
32
+ parameters: {
33
+ type: 'object',
34
+ properties: {
35
+ endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
36
+ user_id: { type: 'string', description: '用户 ID' },
37
+ },
38
+ required: ['endpoint_id', 'user_id'],
39
+ },
40
+ platforms: ['wecom'],
41
+ tags: ['wecom'],
42
+ execute: async (args) => {
43
+ const endpoint = wecom.endpoints.get(args.endpoint_id);
44
+ if (!endpoint)
45
+ throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
46
+ return await endpoint.getUserInfo(args.user_id);
47
+ },
48
+ }, plugin.name));
49
+ disposers.push(toolService.addTool({
50
+ name: 'wecom_get_dept_users',
51
+ description: '获取企业微信部门用户列表',
52
+ parameters: {
53
+ type: 'object',
54
+ properties: {
55
+ endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
56
+ dept_id: { type: 'string', description: '部门 ID' },
57
+ },
58
+ required: ['endpoint_id', 'dept_id'],
59
+ },
60
+ platforms: ['wecom'],
61
+ tags: ['wecom'],
62
+ execute: async (args) => {
63
+ const endpoint = wecom.endpoints.get(args.endpoint_id);
64
+ if (!endpoint)
65
+ throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
66
+ const users = await endpoint.getDepartmentUsers(Number(args.dept_id));
67
+ return { users, count: users.length };
68
+ },
69
+ }, plugin.name));
70
+ disposers.push(toolService.addTool({
71
+ name: 'wecom_list_departments',
72
+ description: '获取企业微信部门列表',
73
+ parameters: {
74
+ type: 'object',
75
+ properties: {
76
+ endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
77
+ dept_id: { type: 'string', description: '父部门 ID,默认 1(跟部门)' },
78
+ },
79
+ required: ['endpoint_id'],
80
+ },
81
+ platforms: ['wecom'],
82
+ tags: ['wecom'],
83
+ execute: async (args) => {
84
+ const endpoint = wecom.endpoints.get(args.endpoint_id);
85
+ if (!endpoint)
86
+ throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
87
+ const departments = await endpoint.getDepartmentList(Number(args.dept_id) || 1);
88
+ return { departments, count: departments.length };
89
+ },
90
+ }, plugin.name));
91
+ disposers.push(toolService.addTool({
92
+ name: 'wecom_send_text',
93
+ description: '向指定企业微信用户发送文本消息',
94
+ parameters: {
95
+ type: 'object',
96
+ properties: {
97
+ endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
98
+ user_id: { type: 'string', description: '用户 ID' },
99
+ content: { type: 'string', description: '消息内容' },
100
+ },
101
+ required: ['endpoint_id', 'user_id', 'content'],
102
+ },
103
+ platforms: ['wecom'],
104
+ tags: ['wecom'],
105
+ execute: async (args) => {
106
+ const endpoint = wecom.endpoints.get(args.endpoint_id);
107
+ if (!endpoint)
108
+ throw new Error(`Endpoint ${args.endpoint_id} 不存在`);
109
+ const success = await endpoint.sendTextMessage(args.user_id, args.content);
110
+ return { success, message: success ? '消息已发送' : '发送失败' };
111
+ },
112
+ }, plugin.name));
113
+ return () => disposers.forEach(d => d());
114
+ });
115
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 企业微信 WeCom platform permit
3
+ */
4
+ import type { Message } from 'zhin.js';
5
+ export declare function platformPermit(perm: string): string;
6
+ export declare function wecomGroupPermitResolver(logicalPerm: string): string;
7
+ export declare function normalizeWecomSenderForPermit(input: {
8
+ isOwner?: boolean;
9
+ isAdmin?: boolean;
10
+ }): {
11
+ role?: string;
12
+ permissions?: string[];
13
+ };
14
+ export declare function checkWecomPlatformPermit(perm: string, message: Message<any>): boolean;
15
+ export declare function registerWecomPlatformPermitChecker(): () => void;
16
+ //# sourceMappingURL=platform-permit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-permit.d.ts","sourceRoot":"","sources":["../src/platform-permit.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAKvC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAOD,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAQ5C;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAcrF;AAED,wBAAgB,kCAAkC,IAAI,MAAM,IAAI,CAE/D"}
@@ -0,0 +1,39 @@
1
+ import { registerPlatformPermitChecker } from 'zhin.js';
2
+ const ADAPTER = 'wecom';
3
+ export function platformPermit(perm) {
4
+ return `platform(${ADAPTER},${perm})`;
5
+ }
6
+ const FACTORY_PERM_MAP = {
7
+ group_admin: 'chat_admin',
8
+ group_owner: 'chat_owner',
9
+ };
10
+ export function wecomGroupPermitResolver(logicalPerm) {
11
+ return platformPermit(FACTORY_PERM_MAP[logicalPerm] ?? logicalPerm);
12
+ }
13
+ export function normalizeWecomSenderForPermit(input) {
14
+ if (input.isOwner) {
15
+ return { role: 'owner', permissions: ['chat_owner', 'chat_admin'] };
16
+ }
17
+ if (input.isAdmin) {
18
+ return { role: 'admin', permissions: ['chat_admin'] };
19
+ }
20
+ return { role: 'member', permissions: [] };
21
+ }
22
+ export function checkWecomPlatformPermit(perm, message) {
23
+ const sender = message.$sender;
24
+ const permissions = sender.permissions ?? [];
25
+ const role = sender.role;
26
+ const has = (t) => permissions.includes(t);
27
+ switch (perm) {
28
+ case 'chat_owner':
29
+ return role === 'owner' || has('chat_owner');
30
+ case 'chat_admin':
31
+ return role === 'owner' || role === 'admin' || has('chat_admin') || has('chat_owner');
32
+ default:
33
+ return false;
34
+ }
35
+ }
36
+ export function registerWecomPlatformPermitChecker() {
37
+ return registerPlatformPermitChecker(ADAPTER, checkWecomPlatformPermit);
38
+ }
39
+ //# sourceMappingURL=platform-permit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-permit.js","sourceRoot":"","sources":["../src/platform-permit.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAC;AAExD,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,YAAY,OAAO,IAAI,IAAI,GAAG,CAAC;AACxC,CAAC;AAED,MAAM,gBAAgB,GAA2B;IAC/C,WAAW,EAAE,YAAY;IACzB,WAAW,EAAE,YAAY;CAC1B,CAAC;AAEF,MAAM,UAAU,wBAAwB,CAAC,WAAmB;IAC1D,OAAO,cAAc,CAAC,gBAAgB,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,KAG7C;IACC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE,CAAC;IACtE,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAAY,EAAE,OAAqB;IAC1E,MAAM,MAAM,GAAG,OAAO,CAAC,OAAoD,CAAC;IAC5E,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;IAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEnD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,YAAY;YACf,OAAO,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;QAC/C,KAAK,YAAY;YACf,OAAO,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;QACxF;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kCAAkC;IAChD,OAAO,6BAA6B,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC;AAC1E,CAAC"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * 企业微信适配器类型定义
3
+ */
4
+ export interface WecomEndpointConfig {
5
+ context: 'wecom';
6
+ name: string;
7
+ corpId: string;
8
+ agentSecret: string;
9
+ token: string;
10
+ encodingAESKey: string;
11
+ webhookPath?: string;
12
+ apiBaseUrl?: string;
13
+ }
14
+ export interface WecomMessage {
15
+ ToUserName: string;
16
+ FromUserName: string;
17
+ CreateTime: number;
18
+ MsgType: 'text' | 'image' | 'voice' | 'video' | 'shortvideo' | 'location' | 'link' | 'event';
19
+ Content?: string;
20
+ MsgId?: string;
21
+ PicUrl?: string;
22
+ MediaId?: string;
23
+ ThumbMediaId?: string;
24
+ Format?: string;
25
+ Recognition?: string;
26
+ Location_X?: string;
27
+ Location_Y?: string;
28
+ Scale?: string;
29
+ Label?: string;
30
+ Title?: string;
31
+ Description?: string;
32
+ Url?: string;
33
+ Event?: string;
34
+ EventKey?: string;
35
+ AgentID?: string;
36
+ [key: string]: unknown;
37
+ }
38
+ export interface AccessToken {
39
+ access_token: string;
40
+ expires_in: number;
41
+ timestamp: number;
42
+ }
43
+ export interface WecomApiResponse {
44
+ errcode: number;
45
+ errmsg?: string;
46
+ [key: string]: unknown;
47
+ }
48
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAA;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB"}
package/lib/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 企业微信适配器类型定义
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@zhin.js/adapter-wecom",
3
+ "version": "0.0.1",
4
+ "description": "Zhin.js adapter for WeCom (企业微信)",
5
+ "type": "module",
6
+ "main": "./lib/index.js",
7
+ "types": "./lib/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/index.d.ts",
11
+ "development": "./src/index.ts",
12
+ "import": "./lib/index.js"
13
+ }
14
+ },
15
+ "keywords": [
16
+ "zhin",
17
+ "zhin.js",
18
+ "bot",
19
+ "adapter",
20
+ "wecom",
21
+ "企业微信",
22
+ "wechat work",
23
+ "chatbot"
24
+ ],
25
+ "author": {
26
+ "name": "lc-cn",
27
+ "email": "admin@liucl.cn",
28
+ "url": "https://github.com/lc-cn"
29
+ },
30
+ "license": "MIT",
31
+ "repository": {
32
+ "url": "git+https://github.com/zhinjs/zhin.git",
33
+ "type": "git",
34
+ "directory": "plugins/adapters/wecom"
35
+ },
36
+ "devDependencies": {
37
+ "@types/koa": "^3.0.3",
38
+ "@types/node": "^25.9.2",
39
+ "typescript": "^6.0.3",
40
+ "@zhin.js/host-router": "1.0.1",
41
+ "zhin.js": "2.0.1"
42
+ },
43
+ "peerDependencies": {
44
+ "@zhin.js/host-router": "1.0.1",
45
+ "zhin.js": "2.0.1"
46
+ },
47
+ "peerDependenciesMeta": {
48
+ "@zhin.js/host-router": {
49
+ "optional": false
50
+ }
51
+ },
52
+ "files": [
53
+ "src",
54
+ "lib",
55
+ "skills",
56
+ "plugin.yml",
57
+ "README.md",
58
+ "CHANGELOG.md"
59
+ ],
60
+ "publishConfig": {
61
+ "access": "public",
62
+ "registry": "https://registry.npmjs.org"
63
+ },
64
+ "scripts": {
65
+ "build": "pnpm build:node",
66
+ "clean": "rimraf lib",
67
+ "build:node": "tsc"
68
+ }
69
+ }
package/plugin.yml ADDED
@@ -0,0 +1,3 @@
1
+ name: adapter-wecom
2
+ description: 企业微信适配器:消息接收与发送、用户与部门查询、AES 消息加解密
3
+ version: 1.0.0
@@ -0,0 +1,19 @@
1
+ # 企业微信 WeCom Platform Permits
2
+
3
+ ## 入站字段
4
+
5
+ | 字段 | 来源 |
6
+ |------|------|
7
+ | `$sender.role` | 默认 `member`;需业务侧扩展企业微信可见性/管理权限 |
8
+ | `$sender.permissions` | `chat_owner` · `chat_admin` |
9
+
10
+ ## Permit 词汇表
11
+
12
+ | `platform(wecom,…)` | 含义 |
13
+ |---------------------|------|
14
+ | `chat_owner` | 群主 |
15
+ | `chat_admin` | 群管理员 |
16
+
17
+ ## 工厂映射
18
+
19
+ `group_admin` → `chat_admin` · `group_owner` → `chat_owner`
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: wecom
3
+ platforms:
4
+ - wecom
5
+ description: >-
6
+ 企业微信平台管理能力。当用户在企业微信中请求用户信息查询、部门架构查询、
7
+ 发送文本消息时使用。即使用户没有提到企业微信,只要上下文是企业微信/WeCom
8
+ 场景且涉及用户查询、部门管理或消息发送,就应触发。
9
+ keywords:
10
+ - wecom
11
+ - 企业微信
12
+ - adapter:wecom
13
+ - 部门
14
+ - 用户
15
+ - 通讯录
16
+ - 企业
17
+ tags:
18
+ - im
19
+ - enterprise
20
+ tools:
21
+ - wecom_get_user
22
+ - wecom_get_dept_users
23
+ - wecom_list_departments
24
+ - wecom_send_text
25
+ ---
26
+
27
+ # 企业微信技能
28
+
29
+ 企业微信(WeCom)是腾讯面向企业的 IM 平台,具备组织架构(部门树)、应用消息推送等能力。
30
+
31
+ ## 核心原则
32
+
33
+ ### 组织架构是核心
34
+
35
+ 企业微信的用户隶属于部门树,查询操作需要从组织架构出发:
36
+ ```
37
+ wecom_list_departments → 获取部门列表(默认从根部门 ID=1 开始)
38
+ wecom_get_dept_users(dept_id) → 获取部门下的用户列表
39
+ wecom_get_user(user_id) → 获取用户详情
40
+ ```
41
+
42
+ ### 消息发送
43
+
44
+ `wecom_send_text` 通过应用消息接口发送文本消息,需要知道接收者的 `userid`。
45
+ 群消息通过 webhook 回调自动处理,不需要主动调用发送工具。
46
+
47
+ ## 工具分类
48
+
49
+ ### 组织架构
50
+
51
+ | 工具 | 用途 | 说明 |
52
+ |------|------|------|
53
+ | `wecom_list_departments` | 部门列表 | 默认从根部门 ID=1 开始 |
54
+ | `wecom_get_dept_users` | 部门用户列表 | 返回简单用户信息 |
55
+ | `wecom_get_user` | 用户详情 | 需要通讯录权限 |
56
+
57
+ ### 消息
58
+
59
+ | 工具 | 用途 | 说明 |
60
+ |------|------|------|
61
+ | `wecom_send_text` | 发送文本消息 | 发给指定用户,通过应用消息接口 |
62
+
63
+ ## 易错点
64
+
65
+ 1. **部门查询从根部门 ID=1 开始**。不知道部门 ID 时先 `list_departments` 获取整棵部门树。
66
+ 2. **消息发送需要 userid**,不是用户名或昵称。仅有昵称时先通过 `get_dept_users` 查找。
67
+ 3. **企业微信不支持机器人撤回消息**,一旦发出无法撤回。
68
+ 4. **Access Token 有效期 7200 秒**,适配器会自动刷新。
package/src/adapter.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * 企业微信适配器
3
+ */
4
+ import { Adapter, Plugin } from 'zhin.js';
5
+ import type { Router } from '@zhin.js/host-router/router';
6
+ import { WecomEndpoint } from './endpoint.js';
7
+ import type { WecomEndpointConfig } from './types.js';
8
+
9
+ export class WecomAdapter extends Adapter<WecomEndpoint> {
10
+ static override readonly capabilities = ['inbound', 'outbound'] as const;
11
+
12
+ #router: Router;
13
+
14
+ constructor(plugin: Plugin, router: Router) {
15
+ super(plugin, 'wecom', []);
16
+ this.#router = router;
17
+ }
18
+
19
+ createEndpoint(config: WecomEndpointConfig): WecomEndpoint {
20
+ return new WecomEndpoint(this, this.#router, config);
21
+ }
22
+
23
+ async start(): Promise<void> {
24
+ await super.start();
25
+ }
26
+ }