@zhin.js/adapter-wecom 4.0.12 → 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 CHANGED
@@ -1,5 +1,46 @@
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
+
36
+ ## 4.0.13
37
+
38
+ ### Patch Changes
39
+
40
+ - @zhin.js/core@1.5.11
41
+ - @zhin.js/agent@1.1.13
42
+ - zhin.js@6.0.11
43
+
3
44
  ## 4.0.12
4
45
 
5
46
  ### 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.12",
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.10",
38
- "@zhin.js/core": "1.5.10",
39
- "@zhin.js/host-http": "1.0.10",
40
- "@zhin.js/im-contract": "1.0.3",
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.10",
46
- "@zhin.js/agent": "1.1.12",
47
- "@zhin.js/command": "1.0.14",
48
- "@zhin.js/core": "1.5.10",
49
- "@zhin.js/host-http": "1.0.10",
50
- "@zhin.js/permission": "1.0.2",
51
- "zhin.js": "6.0.10"
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.12",
73
- "zhin.js": "6.0.10"
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
+ }