@zhin.js/adapter-wecom 4.0.13 → 4.0.14
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/CHANGELOG.md +33 -0
- package/adapters/wecom.js +2 -1
- package/adapters/wecom.ts +2 -1
- package/lib/endpoint.d.ts +2 -1
- package/lib/endpoint.js +4 -0
- package/lib/side-event-dispatch.d.ts +4 -0
- package/lib/side-event-dispatch.js +63 -0
- package/package.json +14 -14
- package/src/endpoint.ts +12 -1
- package/src/side-event-dispatch.ts +70 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @zhin.js/adapter-wecom
|
|
2
2
|
|
|
3
|
+
## 4.0.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 5969c5b: Add SideEventGateway so adapters forward notice/request/system into HandlerIndex. HandlerContext now exposes only generation-safe capabilities and prompt ports; live Endpoint escape hatches are removed.
|
|
8
|
+
- Updated dependencies [5969c5b]
|
|
9
|
+
- Updated dependencies [d336a3f]
|
|
10
|
+
- Updated dependencies [0c82a7e]
|
|
11
|
+
- Updated dependencies [b9217e4]
|
|
12
|
+
- Updated dependencies [5969c5b]
|
|
13
|
+
- Updated dependencies [5969c5b]
|
|
14
|
+
- Updated dependencies [974772e]
|
|
15
|
+
- Updated dependencies [5969c5b]
|
|
16
|
+
- Updated dependencies [5969c5b]
|
|
17
|
+
- Updated dependencies [2f786bd]
|
|
18
|
+
- Updated dependencies [63d89f9]
|
|
19
|
+
- Updated dependencies [71c7cdd]
|
|
20
|
+
- Updated dependencies [3cca0ea]
|
|
21
|
+
- Updated dependencies [1312ca0]
|
|
22
|
+
- Updated dependencies [985fa22]
|
|
23
|
+
- Updated dependencies [04b861d]
|
|
24
|
+
- Updated dependencies [a23d544]
|
|
25
|
+
- Updated dependencies [8cddabf]
|
|
26
|
+
- Updated dependencies [dbe5081]
|
|
27
|
+
- @zhin.js/im-contract@1.0.4
|
|
28
|
+
- @zhin.js/core@1.5.12
|
|
29
|
+
- @zhin.js/adapter@1.1.11
|
|
30
|
+
- @zhin.js/agent@1.1.14
|
|
31
|
+
- @zhin.js/host-http@1.0.11
|
|
32
|
+
- @zhin.js/command@1.0.15
|
|
33
|
+
- zhin.js@6.0.12
|
|
34
|
+
- @zhin.js/permission@1.0.3
|
|
35
|
+
|
|
3
36
|
## 4.0.13
|
|
4
37
|
|
|
5
38
|
### Patch Changes
|
package/adapters/wecom.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implementation lives under `src/` (endpoint / webhook / protocol).
|
|
5
5
|
*/
|
|
6
6
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
7
|
-
import { messageGatewayToken } from '@zhin.js/core/runtime';
|
|
7
|
+
import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
|
|
8
8
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
9
9
|
import { WecomEndpoint } from "../lib/endpoint.js";
|
|
10
10
|
import { resolveWecomConfig, } from "../lib/protocol.js";
|
|
@@ -28,6 +28,7 @@ export default defineAdapter({
|
|
|
28
28
|
return new WecomEndpoint({
|
|
29
29
|
id: context.id,
|
|
30
30
|
gateway: context.use(messageGatewayToken),
|
|
31
|
+
sideEvents: context.use(sideEventGatewayToken),
|
|
31
32
|
http: context.use(httpHostToken),
|
|
32
33
|
config,
|
|
33
34
|
});
|
package/adapters/wecom.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Implementation lives under `src/` (endpoint / webhook / protocol).
|
|
4
4
|
*/
|
|
5
5
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
6
|
-
import { messageGatewayToken } from '@zhin.js/core/runtime';
|
|
6
|
+
import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
|
|
7
7
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
8
8
|
import { WecomEndpoint } from '../src/endpoint.js';
|
|
9
9
|
import {
|
|
@@ -33,6 +33,7 @@ export default defineAdapter<WecomAdapterConfig>({
|
|
|
33
33
|
return new WecomEndpoint({
|
|
34
34
|
id: context.id,
|
|
35
35
|
gateway: context.use(messageGatewayToken),
|
|
36
|
+
sideEvents: context.use(sideEventGatewayToken),
|
|
36
37
|
http: context.use(httpHostToken),
|
|
37
38
|
config,
|
|
38
39
|
});
|
package/lib/endpoint.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* WecomEndpoint — lifecycle, outbound send, inbound admit, OpenAPI helpers for agent tools.
|
|
3
3
|
*/
|
|
4
4
|
import type { EndpointInstance, EndpointSendRequest } from 'zhin.js/adapter';
|
|
5
|
-
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
5
|
+
import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
|
|
6
6
|
import type { HttpHost } from '@zhin.js/host-http';
|
|
7
7
|
import type { CapabilityId } from 'zhin.js';
|
|
8
8
|
import { type ResolvedWecomConfig, type WecomApiResponse, type WecomMessage } from './protocol.js';
|
|
@@ -19,6 +19,7 @@ export type WecomFetch = (url: string, init?: {
|
|
|
19
19
|
export interface WecomEndpointOptions {
|
|
20
20
|
readonly id: CapabilityId;
|
|
21
21
|
readonly gateway: MessageGateway;
|
|
22
|
+
readonly sideEvents?: SideEventGateway;
|
|
22
23
|
readonly http: HttpHost;
|
|
23
24
|
readonly config: ResolvedWecomConfig;
|
|
24
25
|
readonly fetch?: WecomFetch;
|
package/lib/endpoint.js
CHANGED
|
@@ -3,6 +3,7 @@ import { registerWecomAgentEndpoint } from './wecom-agent-deps.js';
|
|
|
3
3
|
import { buildMediaUploadForm, readOutboundImageMedia, resolveMediaBinary, } from './media-upload.js';
|
|
4
4
|
import { buildSendRequestBody, formatInboundContent, formatOutboundBody, resolveChatType, wecomInboundConversation, } from './protocol.js';
|
|
5
5
|
import { registerWecomWebhookRoutes } from './webhook.js';
|
|
6
|
+
import { receiveWecomSideEvent } from './side-event-dispatch.js';
|
|
6
7
|
/**
|
|
7
8
|
* 企业微信服务端 API 无 bot 群列表/群成员列表接口(客户群接口属「客户联系」
|
|
8
9
|
* 独立授权域,非 bot 社交面),好友/频道概念亦不存在;
|
|
@@ -151,6 +152,9 @@ export class WecomEndpoint {
|
|
|
151
152
|
admit(msg) {
|
|
152
153
|
if (!this.#open)
|
|
153
154
|
return;
|
|
155
|
+
if (receiveWecomSideEvent(this.#options.sideEvents, String(this.#options.id), this.#options.config.id, msg, this.#logger)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
154
158
|
const chatType = resolveChatType(msg.FromUserName);
|
|
155
159
|
const conversation = wecomInboundConversation(String(this.#options.id), msg);
|
|
156
160
|
void this.#options.gateway.receive({
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SideEventGateway } from '@zhin.js/core/runtime';
|
|
2
|
+
import { type getAdapterLogger } from '@zhin.js/logger';
|
|
3
|
+
import { type WecomMessage } from './protocol.js';
|
|
4
|
+
export declare function receiveWecomSideEvent(sideEvents: SideEventGateway | undefined, endpointKey: string, configId: string, msg: WecomMessage, logger: ReturnType<typeof getAdapterLogger>): boolean;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { buildNotice, buildSystem, senderFromId } from '@zhin.js/core';
|
|
2
|
+
import { formatCompact } from '@zhin.js/logger';
|
|
3
|
+
import { resolveChatType } from './protocol.js';
|
|
4
|
+
function mapWecomEventParts(eventName) {
|
|
5
|
+
switch (eventName) {
|
|
6
|
+
case 'subscribe':
|
|
7
|
+
return { scene_type: 'friend', sub_type: 'increase' };
|
|
8
|
+
case 'unsubscribe':
|
|
9
|
+
return { scene_type: 'friend', sub_type: 'decrease' };
|
|
10
|
+
case 'enter_agent':
|
|
11
|
+
return null;
|
|
12
|
+
default:
|
|
13
|
+
return { scene_type: 'wecom', sub_type: eventName || 'unknown' };
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function receiveWecomSideEvent(sideEvents, endpointKey, configId, msg, logger) {
|
|
17
|
+
if (!sideEvents || msg.MsgType !== 'event')
|
|
18
|
+
return false;
|
|
19
|
+
const eventName = msg.Event ?? 'unknown';
|
|
20
|
+
if (eventName === 'enter_agent') {
|
|
21
|
+
void sideEvents.receiveSystem(buildSystem(msg, {
|
|
22
|
+
$id: `wecom:enter_agent:${msg.FromUserName}:${msg.CreateTime ?? Date.now()}`,
|
|
23
|
+
$adapter: 'wecom',
|
|
24
|
+
$endpoint: configId,
|
|
25
|
+
$type: 'system',
|
|
26
|
+
$scene_id: msg.FromUserName,
|
|
27
|
+
$scene_type: 'wecom',
|
|
28
|
+
$sub_type: 'enter_agent',
|
|
29
|
+
$timestamp: msg.CreateTime ?? Date.now(),
|
|
30
|
+
})).catch((err) => {
|
|
31
|
+
logger.warn(formatCompact({
|
|
32
|
+
op: 'wecom_system_side_event_failed',
|
|
33
|
+
endpoint: configId,
|
|
34
|
+
event: eventName,
|
|
35
|
+
error: err instanceof Error ? err.message : String(err),
|
|
36
|
+
}));
|
|
37
|
+
});
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
const parts = mapWecomEventParts(eventName);
|
|
41
|
+
if (!parts)
|
|
42
|
+
return false;
|
|
43
|
+
const sceneType = resolveChatType(msg.FromUserName);
|
|
44
|
+
void sideEvents.receiveNotice(buildNotice(msg, {
|
|
45
|
+
$id: `wecom:${eventName}:${msg.FromUserName}:${msg.CreateTime ?? Date.now()}`,
|
|
46
|
+
$adapter: 'wecom',
|
|
47
|
+
$endpoint: configId,
|
|
48
|
+
$type: 'notice',
|
|
49
|
+
$scene_id: msg.FromUserName,
|
|
50
|
+
$scene_type: parts.scene_type === 'friend' ? parts.scene_type : sceneType,
|
|
51
|
+
$sub_type: parts.sub_type,
|
|
52
|
+
$actor: senderFromId(msg.FromUserName),
|
|
53
|
+
$timestamp: msg.CreateTime ?? Date.now(),
|
|
54
|
+
})).catch((err) => {
|
|
55
|
+
logger.warn(formatCompact({
|
|
56
|
+
op: 'wecom_side_event_failed',
|
|
57
|
+
endpoint: configId,
|
|
58
|
+
event: eventName,
|
|
59
|
+
error: err instanceof Error ? err.message : String(err),
|
|
60
|
+
}));
|
|
61
|
+
});
|
|
62
|
+
return true;
|
|
63
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-wecom",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.14",
|
|
4
4
|
"description": "Zhin.js WeCom (企业微信) adapter for Plugin Runtime (HTTP webhook)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -34,21 +34,21 @@
|
|
|
34
34
|
"directory": "plugins/adapters/wecom"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@zhin.js/adapter": "1.1.
|
|
38
|
-
"@zhin.js/core": "1.5.
|
|
39
|
-
"@zhin.js/host-http": "1.0.
|
|
40
|
-
"@zhin.js/im-contract": "1.0.
|
|
37
|
+
"@zhin.js/adapter": "1.1.11",
|
|
38
|
+
"@zhin.js/core": "1.5.12",
|
|
39
|
+
"@zhin.js/host-http": "1.0.11",
|
|
40
|
+
"@zhin.js/im-contract": "1.0.4",
|
|
41
41
|
"@zhin.js/logger": "1.0.76"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"zod": "^4.0.0",
|
|
45
|
-
"@zhin.js/adapter": "1.1.
|
|
46
|
-
"@zhin.js/agent": "1.1.
|
|
47
|
-
"@zhin.js/command": "1.0.
|
|
48
|
-
"@zhin.js/core": "1.5.
|
|
49
|
-
"@zhin.js/host-http": "1.0.
|
|
50
|
-
"@zhin.js/permission": "1.0.
|
|
51
|
-
"zhin.js": "6.0.
|
|
45
|
+
"@zhin.js/adapter": "1.1.11",
|
|
46
|
+
"@zhin.js/agent": "1.1.14",
|
|
47
|
+
"@zhin.js/command": "1.0.15",
|
|
48
|
+
"@zhin.js/core": "1.5.12",
|
|
49
|
+
"@zhin.js/host-http": "1.0.11",
|
|
50
|
+
"@zhin.js/permission": "1.0.3",
|
|
51
|
+
"zhin.js": "6.0.12"
|
|
52
52
|
},
|
|
53
53
|
"peerDependenciesMeta": {
|
|
54
54
|
"@zhin.js/agent": {
|
|
@@ -69,8 +69,8 @@
|
|
|
69
69
|
"typescript": "^6.0.3",
|
|
70
70
|
"vitest": "^4.1.10",
|
|
71
71
|
"zod": "^4.4.3",
|
|
72
|
-
"@zhin.js/agent": "1.1.
|
|
73
|
-
"zhin.js": "6.0.
|
|
72
|
+
"@zhin.js/agent": "1.1.14",
|
|
73
|
+
"zhin.js": "6.0.12"
|
|
74
74
|
},
|
|
75
75
|
"files": [
|
|
76
76
|
"adapters",
|
package/src/endpoint.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* WecomEndpoint — lifecycle, outbound send, inbound admit, OpenAPI helpers for agent tools.
|
|
3
3
|
*/
|
|
4
4
|
import type { EndpointInstance, EndpointSendRequest } from 'zhin.js/adapter';
|
|
5
|
-
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
5
|
+
import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
|
|
6
6
|
import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
|
|
7
7
|
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
8
8
|
import type { CapabilityId } from 'zhin.js';
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
type WecomMessage,
|
|
26
26
|
} from './protocol.js';
|
|
27
27
|
import { registerWecomWebhookRoutes } from './webhook.js';
|
|
28
|
+
import { receiveWecomSideEvent } from './side-event-dispatch.js';
|
|
28
29
|
|
|
29
30
|
export type WecomFetch = (
|
|
30
31
|
url: string,
|
|
@@ -43,6 +44,7 @@ export type WecomFetch = (
|
|
|
43
44
|
export interface WecomEndpointOptions {
|
|
44
45
|
readonly id: CapabilityId;
|
|
45
46
|
readonly gateway: MessageGateway;
|
|
47
|
+
readonly sideEvents?: SideEventGateway;
|
|
46
48
|
readonly http: HttpHost;
|
|
47
49
|
readonly config: ResolvedWecomConfig;
|
|
48
50
|
readonly fetch?: WecomFetch;
|
|
@@ -202,6 +204,15 @@ export class WecomEndpoint implements EndpointInstance {
|
|
|
202
204
|
/** Test / internal: admit a parsed message when open (non-webhook path). */
|
|
203
205
|
admit(msg: WecomMessage): void {
|
|
204
206
|
if (!this.#open) return;
|
|
207
|
+
if (receiveWecomSideEvent(
|
|
208
|
+
this.#options.sideEvents,
|
|
209
|
+
String(this.#options.id),
|
|
210
|
+
this.#options.config.id,
|
|
211
|
+
msg,
|
|
212
|
+
this.#logger,
|
|
213
|
+
)) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
205
216
|
const chatType = resolveChatType(msg.FromUserName);
|
|
206
217
|
const conversation = wecomInboundConversation(String(this.#options.id), msg);
|
|
207
218
|
void this.#options.gateway.receive({
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { buildNotice, buildSystem, senderFromId } from '@zhin.js/core';
|
|
2
|
+
import type { SideEventGateway } from '@zhin.js/core/runtime';
|
|
3
|
+
import { formatCompact, type getAdapterLogger } from '@zhin.js/logger';
|
|
4
|
+
import { resolveChatType, type WecomMessage } from './protocol.js';
|
|
5
|
+
|
|
6
|
+
function mapWecomEventParts(eventName: string): { scene_type: string; sub_type: string } | null {
|
|
7
|
+
switch (eventName) {
|
|
8
|
+
case 'subscribe':
|
|
9
|
+
return { scene_type: 'friend', sub_type: 'increase' };
|
|
10
|
+
case 'unsubscribe':
|
|
11
|
+
return { scene_type: 'friend', sub_type: 'decrease' };
|
|
12
|
+
case 'enter_agent':
|
|
13
|
+
return null;
|
|
14
|
+
default:
|
|
15
|
+
return { scene_type: 'wecom', sub_type: eventName || 'unknown' };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function receiveWecomSideEvent(
|
|
20
|
+
sideEvents: SideEventGateway | undefined,
|
|
21
|
+
endpointKey: string,
|
|
22
|
+
configId: string,
|
|
23
|
+
msg: WecomMessage,
|
|
24
|
+
logger: ReturnType<typeof getAdapterLogger>,
|
|
25
|
+
): boolean {
|
|
26
|
+
if (!sideEvents || msg.MsgType !== 'event') return false;
|
|
27
|
+
const eventName = msg.Event ?? 'unknown';
|
|
28
|
+
if (eventName === 'enter_agent') {
|
|
29
|
+
void sideEvents.receiveSystem(buildSystem(msg, {
|
|
30
|
+
$id: `wecom:enter_agent:${msg.FromUserName}:${msg.CreateTime ?? Date.now()}`,
|
|
31
|
+
$adapter: 'wecom' as never,
|
|
32
|
+
$endpoint: configId,
|
|
33
|
+
$type: 'system',
|
|
34
|
+
$scene_id: msg.FromUserName,
|
|
35
|
+
$scene_type: 'wecom',
|
|
36
|
+
$sub_type: 'enter_agent',
|
|
37
|
+
$timestamp: msg.CreateTime ?? Date.now(),
|
|
38
|
+
})).catch((err) => {
|
|
39
|
+
logger.warn(formatCompact({
|
|
40
|
+
op: 'wecom_system_side_event_failed',
|
|
41
|
+
endpoint: configId,
|
|
42
|
+
event: eventName,
|
|
43
|
+
error: err instanceof Error ? err.message : String(err),
|
|
44
|
+
}));
|
|
45
|
+
});
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
const parts = mapWecomEventParts(eventName);
|
|
49
|
+
if (!parts) return false;
|
|
50
|
+
const sceneType = resolveChatType(msg.FromUserName);
|
|
51
|
+
void sideEvents.receiveNotice(buildNotice(msg, {
|
|
52
|
+
$id: `wecom:${eventName}:${msg.FromUserName}:${msg.CreateTime ?? Date.now()}`,
|
|
53
|
+
$adapter: 'wecom' as never,
|
|
54
|
+
$endpoint: configId,
|
|
55
|
+
$type: 'notice',
|
|
56
|
+
$scene_id: msg.FromUserName,
|
|
57
|
+
$scene_type: parts.scene_type === 'friend' ? parts.scene_type : sceneType,
|
|
58
|
+
$sub_type: parts.sub_type,
|
|
59
|
+
$actor: senderFromId(msg.FromUserName),
|
|
60
|
+
$timestamp: msg.CreateTime ?? Date.now(),
|
|
61
|
+
})).catch((err) => {
|
|
62
|
+
logger.warn(formatCompact({
|
|
63
|
+
op: 'wecom_side_event_failed',
|
|
64
|
+
endpoint: configId,
|
|
65
|
+
event: eventName,
|
|
66
|
+
error: err instanceof Error ? err.message : String(err),
|
|
67
|
+
}));
|
|
68
|
+
});
|
|
69
|
+
return true;
|
|
70
|
+
}
|