@zhin.js/adapter-kook 1.1.3 → 1.1.4

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,19 @@
1
1
  # @zhin.js/adapter-kook
2
2
 
3
+ ## 1.1.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 43eda99: Unify Notice and Request payloads with their public types and runtime exports. Use camelCase fields, preserve native data under metadata, and bind canonical endpoint identity and request actions to the held generation. Remove legacy data aliases and from factories.
8
+
9
+ Keep login and lifecycle signals as independent SystemEvent payloads on system.receive, without chat conversation fields or user interaction. Update built-in adapter projections and authoring guidance.
10
+
11
+ - Updated dependencies [43eda99]
12
+ - Updated dependencies [0de4836]
13
+ - @zhin.js/core@1.1.39
14
+ - @zhin.js/permission@1.1.3
15
+ - @zhin.js/adapter@1.1.15
16
+
3
17
  ## 1.1.3
4
18
 
5
19
  ### Patch Changes
package/lib/protocol.d.ts CHANGED
@@ -56,6 +56,19 @@ export interface KookWebhookEventData {
56
56
  readonly verify_token?: string;
57
57
  readonly challenge?: string;
58
58
  readonly extra?: {
59
+ readonly type?: string | number;
60
+ readonly body?: {
61
+ readonly user_id?: string;
62
+ readonly channel_id?: string;
63
+ readonly msg_id?: string;
64
+ readonly author_id?: string;
65
+ readonly target_id?: string;
66
+ readonly chat_code?: string;
67
+ readonly emoji?: {
68
+ readonly id?: string;
69
+ readonly name?: string;
70
+ };
71
+ };
59
72
  readonly guild_id?: string;
60
73
  readonly author?: {
61
74
  readonly id?: string;
@@ -1,4 +1,4 @@
1
- import { buildNotice, mapNoticeParts, senderFromId, KOOK_NOTICE_PARTS_MAP } from '@zhin.js/core';
1
+ import { composeSideEventName, buildNotice, mapNoticeParts, senderFromId, KOOK_NOTICE_PARTS_MAP } from '@zhin.js/core';
2
2
  import { formatCompact } from '@zhin.js/logger';
3
3
  function extractKookNoticeType(raw) {
4
4
  if (!raw || typeof raw !== 'object')
@@ -20,23 +20,37 @@ export function receiveKookSideEvent(emit, configId, raw, logger) {
20
20
  return false;
21
21
  const event = raw;
22
22
  const parts = mapNoticeParts('kook', noticeType);
23
- const guildId = event.extra?.guild_id;
24
- const userId = event.author_id ?? event.extra?.author?.id;
25
- const sceneId = guildId != null
26
- ? String(guildId)
27
- : userId != null
28
- ? String(userId)
29
- : configId;
23
+ const body = event.extra?.body;
24
+ const guildId = event.extra?.guild_id
25
+ ?? (event.channel_type === 'GROUP' && event.type === 255 ? event.target_id : undefined);
26
+ // author_id is the system sender (top-level) or original message author (body),
27
+ // not proof of who deleted a message. Keep an unknown deletion actor absent.
28
+ const userId = body?.user_id;
29
+ const memberEvent = noticeType === 'joined_guild' || noticeType === 'exited_guild';
30
+ // Guild ids and private chat_code values are not outbound channel/user ids.
31
+ const channelId = !memberEvent ? body?.channel_id : undefined;
32
+ const conversation = channelId ? {
33
+ kind: 'channel',
34
+ id: channelId,
35
+ ...(guildId ? { parent: { kind: 'channel', id: guildId } } : {}),
36
+ } : undefined;
37
+ const sceneType = conversation ? 'channel'
38
+ : noticeType.includes('private') ? 'friend' : parts.scene_type;
39
+ const sceneId = channelId ?? guildId ?? '';
40
+ const reactionEvent = noticeType.includes('reaction');
30
41
  void emit('notice.receive', buildNotice(event, {
31
- $id: `kook:${noticeType}:${event.msg_timestamp ?? Date.now()}:${sceneId}:${String(userId ?? '')}`,
32
- $adapter: 'kook',
33
- $endpoint: configId,
34
- $type: 'notice',
35
- $scene_id: sceneId,
36
- $scene_type: parts.scene_type,
37
- $sub_type: parts.sub_type,
38
- $actor: senderFromId(userId, event.extra?.author?.username),
39
- $timestamp: event.msg_timestamp ?? Date.now(),
42
+ id: event.msg_id || `kook:${noticeType}:${event.msg_timestamp ?? Date.now()}:${sceneId}:${body?.msg_id ?? ''}:${String(userId ?? '')}`,
43
+ clientAdapter: 'kook',
44
+ endpointId: configId,
45
+ type: 'notice',
46
+ conversation,
47
+ name: composeSideEventName('notice', sceneType, parts.sub_type),
48
+ actor: memberEvent ? undefined : senderFromId(userId),
49
+ target: memberEvent ? senderFromId(userId) : undefined,
50
+ messageId: body?.msg_id,
51
+ reaction: reactionEvent ? body?.emoji?.id : undefined,
52
+ operation: reactionEvent ? (noticeType.includes('deleted') ? 'removed' : 'added') : undefined,
53
+ timestamp: event.msg_timestamp ?? Date.now(),
40
54
  })).catch((err) => {
41
55
  logger.warn(formatCompact({
42
56
  op: 'kook_side_event_failed',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-kook",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "Zhin.js KOOK adapter for Plugin Runtime (WebSocket gateway or Webhook)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -36,21 +36,21 @@
36
36
  "kook-client": "^1.0.4",
37
37
  "@zhin.js/adapter": "1.1.15",
38
38
  "@zhin.js/agent-feature": "1.1.2",
39
- "@zhin.js/core": "1.1.38",
39
+ "@zhin.js/core": "1.1.39",
40
40
  "@zhin.js/feature-kit": "1.1.2",
41
41
  "@zhin.js/host-http": "1.1.2",
42
42
  "@zhin.js/im-contract": "1.1.2",
43
43
  "@zhin.js/logger": "1.1.1",
44
- "@zhin.js/permission": "1.1.2",
44
+ "@zhin.js/permission": "1.1.3",
45
45
  "@zhin.js/skill": "1.1.2",
46
46
  "@zhin.js/tool": "1.1.2"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "zod": "^4.0.0",
50
50
  "@zhin.js/adapter": "^1.1.15",
51
- "@zhin.js/command": "^1.1.2",
52
- "@zhin.js/core": "^1.1.38",
53
- "zhin.js": "^1.1.3"
51
+ "@zhin.js/command": "^1.1.3",
52
+ "@zhin.js/core": "^1.1.39",
53
+ "zhin.js": "^1.1.4"
54
54
  },
55
55
  "peerDependenciesMeta": {
56
56
  "@zhin.js/command": {
@@ -69,7 +69,7 @@
69
69
  "vitest": "^4.1.10",
70
70
  "zod": "^4.4.3",
71
71
  "@zhin.js/host-http": "1.1.2",
72
- "zhin.js": "1.1.3"
72
+ "zhin.js": "1.1.4"
73
73
  },
74
74
  "files": [
75
75
  "adapters",
package/src/protocol.ts CHANGED
@@ -76,6 +76,16 @@ export interface KookWebhookEventData {
76
76
  readonly verify_token?: string;
77
77
  readonly challenge?: string;
78
78
  readonly extra?: {
79
+ readonly type?: string | number;
80
+ readonly body?: {
81
+ readonly user_id?: string;
82
+ readonly channel_id?: string;
83
+ readonly msg_id?: string;
84
+ readonly author_id?: string;
85
+ readonly target_id?: string;
86
+ readonly chat_code?: string;
87
+ readonly emoji?: { readonly id?: string; readonly name?: string };
88
+ };
79
89
  readonly guild_id?: string;
80
90
  readonly author?: {
81
91
  readonly id?: string;
@@ -1,11 +1,11 @@
1
- import { buildNotice, mapNoticeParts, senderFromId, KOOK_NOTICE_PARTS_MAP } from '@zhin.js/core';
1
+ import { composeSideEventName, buildNotice, mapNoticeParts, senderFromId, KOOK_NOTICE_PARTS_MAP } from '@zhin.js/core';
2
2
  import type { EndpointEventEmitter } from 'zhin.js/adapter';
3
3
  import { formatCompact, type getAdapterLogger } from '@zhin.js/logger';
4
4
  import type { KookWebhookEventData } from './protocol.js';
5
5
 
6
6
  function extractKookNoticeType(raw: unknown): string | null {
7
7
  if (!raw || typeof raw !== 'object') return null;
8
- const event = raw as KookWebhookEventData & { extra?: { type?: string } };
8
+ const event = raw as KookWebhookEventData;
9
9
  const extraType = event.extra?.type;
10
10
  if (typeof extraType === 'string' && extraType) return extraType;
11
11
  if (event.channel_type === 'NOTICE' && event.type != null) {
@@ -25,23 +25,37 @@ export function receiveKookSideEvent(
25
25
  if (!Object.prototype.hasOwnProperty.call(KOOK_NOTICE_PARTS_MAP, noticeType)) return false;
26
26
  const event = raw as KookWebhookEventData;
27
27
  const parts = mapNoticeParts('kook', noticeType);
28
- const guildId = event.extra?.guild_id;
29
- const userId = event.author_id ?? event.extra?.author?.id;
30
- const sceneId = guildId != null
31
- ? String(guildId)
32
- : userId != null
33
- ? String(userId)
34
- : configId;
28
+ const body = event.extra?.body;
29
+ const guildId = event.extra?.guild_id
30
+ ?? (event.channel_type === 'GROUP' && event.type === 255 ? event.target_id : undefined);
31
+ // author_id is the system sender (top-level) or original message author (body),
32
+ // not proof of who deleted a message. Keep an unknown deletion actor absent.
33
+ const userId = body?.user_id;
34
+ const memberEvent = noticeType === 'joined_guild' || noticeType === 'exited_guild';
35
+ // Guild ids and private chat_code values are not outbound channel/user ids.
36
+ const channelId = !memberEvent ? body?.channel_id : undefined;
37
+ const conversation = channelId ? {
38
+ kind: 'channel' as const,
39
+ id: channelId,
40
+ ...(guildId ? { parent: { kind: 'channel' as const, id: guildId } } : {}),
41
+ } : undefined;
42
+ const sceneType = conversation ? 'channel'
43
+ : noticeType.includes('private') ? 'friend' : parts.scene_type;
44
+ const sceneId = channelId ?? guildId ?? '';
45
+ const reactionEvent = noticeType.includes('reaction');
35
46
  void emit('notice.receive', buildNotice(event, {
36
- $id: `kook:${noticeType}:${event.msg_timestamp ?? Date.now()}:${sceneId}:${String(userId ?? '')}`,
37
- $adapter: 'kook' as never,
38
- $endpoint: configId,
39
- $type: 'notice',
40
- $scene_id: sceneId,
41
- $scene_type: parts.scene_type,
42
- $sub_type: parts.sub_type,
43
- $actor: senderFromId(userId, event.extra?.author?.username),
44
- $timestamp: event.msg_timestamp ?? Date.now(),
47
+ id: event.msg_id || `kook:${noticeType}:${event.msg_timestamp ?? Date.now()}:${sceneId}:${body?.msg_id ?? ''}:${String(userId ?? '')}`,
48
+ clientAdapter: 'kook',
49
+ endpointId: configId,
50
+ type: 'notice',
51
+ conversation,
52
+ name: composeSideEventName('notice', sceneType, parts.sub_type),
53
+ actor: memberEvent ? undefined : senderFromId(userId),
54
+ target: memberEvent ? senderFromId(userId) : undefined,
55
+ messageId: body?.msg_id,
56
+ reaction: reactionEvent ? body?.emoji?.id : undefined,
57
+ operation: reactionEvent ? (noticeType.includes('deleted') ? 'removed' : 'added') : undefined,
58
+ timestamp: event.msg_timestamp ?? Date.now(),
45
59
  })).catch((err) => {
46
60
  logger.warn(formatCompact({
47
61
  op: 'kook_side_event_failed',