@zhin.js/adapter-napcat 3.0.2 → 5.0.0

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.
Files changed (183) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +47 -98
  3. package/adapters/napcat.ts +39 -0
  4. package/agent/tools/ai_tts.ts +2 -2
  5. package/agent/tools/del_group_notice.ts +2 -2
  6. package/agent/tools/delete_essence_msg.ts +2 -2
  7. package/agent/tools/delete_friend.ts +2 -2
  8. package/agent/tools/download_file.ts +2 -2
  9. package/agent/tools/forward_single_msg.ts +2 -2
  10. package/agent/tools/get_ai_characters.ts +2 -2
  11. package/agent/tools/get_essence_list.ts +2 -2
  12. package/agent/tools/get_friend_msg_history.ts +2 -2
  13. package/agent/tools/get_group_file_url.ts +2 -2
  14. package/agent/tools/get_group_info_ex.ts +2 -2
  15. package/agent/tools/get_group_msg_history.ts +2 -2
  16. package/agent/tools/get_group_notice.ts +2 -2
  17. package/agent/tools/get_group_root_files.ts +2 -2
  18. package/agent/tools/get_group_shut_list.ts +2 -2
  19. package/agent/tools/get_mini_app_ark.ts +2 -2
  20. package/agent/tools/get_user_status.ts +2 -2
  21. package/agent/tools/group_sign.ts +2 -2
  22. package/agent/tools/mark_msg_as_read.ts +2 -2
  23. package/agent/tools/ocr_image.ts +2 -2
  24. package/agent/tools/send_forward_msg.ts +2 -2
  25. package/agent/tools/send_group_notice.ts +2 -2
  26. package/agent/tools/send_like.ts +2 -2
  27. package/agent/tools/send_poke.ts +2 -2
  28. package/agent/tools/set_avatar.ts +2 -2
  29. package/agent/tools/set_emoji_reaction.ts +2 -2
  30. package/agent/tools/set_essence_msg.ts +2 -2
  31. package/agent/tools/set_group_portrait.ts +2 -2
  32. package/agent/tools/set_online_status.ts +2 -2
  33. package/agent/tools/set_profile.ts +2 -2
  34. package/agent/tools/set_signature.ts +2 -2
  35. package/agent/tools/set_title.ts +2 -2
  36. package/agent/tools/translate.ts +2 -2
  37. package/agent/tools/upload_group_file.ts +2 -2
  38. package/lib/http-endpoint.d.ts +26 -0
  39. package/lib/http-endpoint.js +147 -0
  40. package/lib/index.d.ts +11 -0
  41. package/lib/index.js +10 -0
  42. package/lib/napcat-agent-deps.d.ts +51 -0
  43. package/lib/napcat-agent-deps.js +33 -0
  44. package/lib/napcat-inbound.d.ts +28 -0
  45. package/lib/{src/napcat-inbound.js → napcat-inbound.js} +28 -13
  46. package/lib/onebot-get-msg.d.ts +14 -0
  47. package/lib/{src/onebot-get-msg.js → onebot-get-msg.js} +0 -1
  48. package/lib/protocol.d.ts +151 -0
  49. package/lib/protocol.js +217 -0
  50. package/lib/webhook.d.ts +2 -0
  51. package/lib/webhook.js +14 -0
  52. package/lib/ws-endpoint.d.ts +61 -0
  53. package/lib/ws-endpoint.js +357 -0
  54. package/lib/ws-transport.d.ts +13 -0
  55. package/lib/ws-transport.js +75 -0
  56. package/lib/ws-types.d.ts +17 -0
  57. package/lib/ws-types.js +1 -0
  58. package/lib/wss-auth.d.ts +2 -0
  59. package/lib/wss-auth.js +16 -0
  60. package/lib/wss-endpoint.d.ts +25 -0
  61. package/lib/wss-endpoint.js +157 -0
  62. package/package.json +44 -33
  63. package/plugin.ts +13 -0
  64. package/schema.json +74 -0
  65. package/src/http-endpoint.ts +197 -0
  66. package/src/index.ts +66 -81
  67. package/src/napcat-agent-deps.ts +81 -15
  68. package/src/napcat-inbound.ts +34 -10
  69. package/src/onebot-get-msg.ts +8 -2
  70. package/src/protocol.ts +373 -0
  71. package/src/webhook.ts +16 -0
  72. package/src/ws-endpoint.ts +452 -0
  73. package/src/ws-transport.ts +105 -0
  74. package/src/ws-types.ts +20 -0
  75. package/src/wss-auth.ts +17 -0
  76. package/src/wss-endpoint.ts +205 -0
  77. package/client/NapCatManagement.tsx +0 -113
  78. package/client/index.tsx +0 -11
  79. package/client/tsconfig.json +0 -7
  80. package/client/utils/api.ts +0 -30
  81. package/dist/index.js +0 -27
  82. package/lib/agent/tools/ai_tts.js +0 -21
  83. package/lib/agent/tools/ai_tts.js.map +0 -1
  84. package/lib/agent/tools/del_group_notice.js +0 -22
  85. package/lib/agent/tools/del_group_notice.js.map +0 -1
  86. package/lib/agent/tools/delete_essence_msg.js +0 -21
  87. package/lib/agent/tools/delete_essence_msg.js.map +0 -1
  88. package/lib/agent/tools/delete_friend.js +0 -20
  89. package/lib/agent/tools/delete_friend.js.map +0 -1
  90. package/lib/agent/tools/download_file.js +0 -19
  91. package/lib/agent/tools/download_file.js.map +0 -1
  92. package/lib/agent/tools/forward_single_msg.js +0 -24
  93. package/lib/agent/tools/forward_single_msg.js.map +0 -1
  94. package/lib/agent/tools/get_ai_characters.js +0 -19
  95. package/lib/agent/tools/get_ai_characters.js.map +0 -1
  96. package/lib/agent/tools/get_essence_list.js +0 -19
  97. package/lib/agent/tools/get_essence_list.js.map +0 -1
  98. package/lib/agent/tools/get_friend_msg_history.js +0 -20
  99. package/lib/agent/tools/get_friend_msg_history.js.map +0 -1
  100. package/lib/agent/tools/get_group_file_url.js +0 -21
  101. package/lib/agent/tools/get_group_file_url.js.map +0 -1
  102. package/lib/agent/tools/get_group_info_ex.js +0 -19
  103. package/lib/agent/tools/get_group_info_ex.js.map +0 -1
  104. package/lib/agent/tools/get_group_msg_history.js +0 -21
  105. package/lib/agent/tools/get_group_msg_history.js.map +0 -1
  106. package/lib/agent/tools/get_group_notice.js +0 -19
  107. package/lib/agent/tools/get_group_notice.js.map +0 -1
  108. package/lib/agent/tools/get_group_root_files.js +0 -19
  109. package/lib/agent/tools/get_group_root_files.js.map +0 -1
  110. package/lib/agent/tools/get_group_shut_list.js +0 -19
  111. package/lib/agent/tools/get_group_shut_list.js.map +0 -1
  112. package/lib/agent/tools/get_mini_app_ark.js +0 -22
  113. package/lib/agent/tools/get_mini_app_ark.js.map +0 -1
  114. package/lib/agent/tools/get_user_status.js +0 -18
  115. package/lib/agent/tools/get_user_status.js.map +0 -1
  116. package/lib/agent/tools/group_sign.js +0 -20
  117. package/lib/agent/tools/group_sign.js.map +0 -1
  118. package/lib/agent/tools/mark_msg_as_read.js +0 -19
  119. package/lib/agent/tools/mark_msg_as_read.js.map +0 -1
  120. package/lib/agent/tools/ocr_image.js +0 -18
  121. package/lib/agent/tools/ocr_image.js.map +0 -1
  122. package/lib/agent/tools/send_forward_msg.js +0 -21
  123. package/lib/agent/tools/send_forward_msg.js.map +0 -1
  124. package/lib/agent/tools/send_group_notice.js +0 -23
  125. package/lib/agent/tools/send_group_notice.js.map +0 -1
  126. package/lib/agent/tools/send_like.js +0 -20
  127. package/lib/agent/tools/send_like.js.map +0 -1
  128. package/lib/agent/tools/send_poke.js +0 -20
  129. package/lib/agent/tools/send_poke.js.map +0 -1
  130. package/lib/agent/tools/set_avatar.js +0 -19
  131. package/lib/agent/tools/set_avatar.js.map +0 -1
  132. package/lib/agent/tools/set_emoji_reaction.js +0 -20
  133. package/lib/agent/tools/set_emoji_reaction.js.map +0 -1
  134. package/lib/agent/tools/set_essence_msg.js +0 -21
  135. package/lib/agent/tools/set_essence_msg.js.map +0 -1
  136. package/lib/agent/tools/set_group_portrait.js +0 -22
  137. package/lib/agent/tools/set_group_portrait.js.map +0 -1
  138. package/lib/agent/tools/set_online_status.js +0 -20
  139. package/lib/agent/tools/set_online_status.js.map +0 -1
  140. package/lib/agent/tools/set_profile.js +0 -23
  141. package/lib/agent/tools/set_profile.js.map +0 -1
  142. package/lib/agent/tools/set_signature.js +0 -19
  143. package/lib/agent/tools/set_signature.js.map +0 -1
  144. package/lib/agent/tools/set_title.js +0 -23
  145. package/lib/agent/tools/set_title.js.map +0 -1
  146. package/lib/agent/tools/translate.js +0 -18
  147. package/lib/agent/tools/translate.js.map +0 -1
  148. package/lib/agent/tools/upload_group_file.js +0 -23
  149. package/lib/agent/tools/upload_group_file.js.map +0 -1
  150. package/lib/src/adapter.js +0 -102
  151. package/lib/src/adapter.js.map +0 -1
  152. package/lib/src/agent-prompt.js +0 -106
  153. package/lib/src/agent-prompt.js.map +0 -1
  154. package/lib/src/endpoint-base.js +0 -315
  155. package/lib/src/endpoint-base.js.map +0 -1
  156. package/lib/src/endpoint-http.js +0 -106
  157. package/lib/src/endpoint-http.js.map +0 -1
  158. package/lib/src/endpoint-ws-client.js +0 -139
  159. package/lib/src/endpoint-ws-client.js.map +0 -1
  160. package/lib/src/endpoint-ws-server.js +0 -137
  161. package/lib/src/endpoint-ws-server.js.map +0 -1
  162. package/lib/src/index.js +0 -58
  163. package/lib/src/index.js.map +0 -1
  164. package/lib/src/napcat-agent-deps.js +0 -19
  165. package/lib/src/napcat-agent-deps.js.map +0 -1
  166. package/lib/src/napcat-inbound.js.map +0 -1
  167. package/lib/src/onebot-get-msg.js.map +0 -1
  168. package/lib/src/routes.js +0 -61
  169. package/lib/src/routes.js.map +0 -1
  170. package/lib/src/segment-mapper.js +0 -2
  171. package/lib/src/segment-mapper.js.map +0 -1
  172. package/lib/src/types.js +0 -6
  173. package/lib/src/types.js.map +0 -1
  174. package/plugin.yml +0 -3
  175. package/src/adapter.ts +0 -109
  176. package/src/agent-prompt.ts +0 -115
  177. package/src/endpoint-base.ts +0 -362
  178. package/src/endpoint-http.ts +0 -95
  179. package/src/endpoint-ws-client.ts +0 -137
  180. package/src/endpoint-ws-server.ts +0 -136
  181. package/src/routes.ts +0 -61
  182. package/src/segment-mapper.ts +0 -1
  183. package/src/types.ts +0 -266
@@ -1,8 +1,8 @@
1
- import { defineTool } from '@zhin.js/agent/tools';
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { getEndpoint } from '../../src/napcat-agent-deps.js';
4
4
 
5
- export default defineTool<{ endpoint_id: string; status: number; ext_status?: number }>({
5
+ export default defineAgentTool<{ endpoint_id: string; status: number; ext_status?: number }>({
6
6
  description: '设置在线状态(在线、隐身、忙碌等)。',
7
7
  inputSchema: z.object({
8
8
  endpoint_id: z.string().describe('Endpoint 名称'),
@@ -1,8 +1,8 @@
1
- import { defineTool } from '@zhin.js/agent/tools';
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { getEndpoint } from '../../src/napcat-agent-deps.js';
4
4
 
5
- export default defineTool<{ endpoint_id: string; nickname: string; company?: string; email?: string; college?: string; personal_note?: string }>({
5
+ export default defineAgentTool<{ endpoint_id: string; nickname: string; company?: string; email?: string; college?: string; personal_note?: string }>({
6
6
  description: '修改 QQ 资料(昵称等)。',
7
7
  inputSchema: z.object({
8
8
  endpoint_id: z.string().describe('Endpoint 名称'),
@@ -1,8 +1,8 @@
1
- import { defineTool } from '@zhin.js/agent/tools';
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { getEndpoint } from '../../src/napcat-agent-deps.js';
4
4
 
5
- export default defineTool<{ endpoint_id: string; signature: string }>({
5
+ export default defineAgentTool<{ endpoint_id: string; signature: string }>({
6
6
  description: '设置个人签名(个性签名)。',
7
7
  inputSchema: z.object({
8
8
  endpoint_id: z.string().describe('Endpoint 名称'),
@@ -1,8 +1,8 @@
1
- import { defineTool } from '@zhin.js/agent/tools';
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { getEndpoint } from '../../src/napcat-agent-deps.js';
4
4
 
5
- export default defineTool<{ endpoint_id: string; group_id: number; user_id: number; title: string }>({
5
+ export default defineAgentTool<{ endpoint_id: string; group_id: number; user_id: number; title: string }>({
6
6
  description: '设置群成员专属头衔。需要群主权限。',
7
7
  inputSchema: z.object({
8
8
  endpoint_id: z.string().describe('Endpoint 名称'),
@@ -1,8 +1,8 @@
1
- import { defineTool } from '@zhin.js/agent/tools';
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { getEndpoint } from '../../src/napcat-agent-deps.js';
4
4
 
5
- export default defineTool<{ endpoint_id: string; text: string }>({
5
+ export default defineAgentTool<{ endpoint_id: string; text: string }>({
6
6
  description: '英译中翻译。',
7
7
  inputSchema: z.object({
8
8
  endpoint_id: z.string().describe('Endpoint 名称'),
@@ -1,8 +1,8 @@
1
- import { defineTool } from '@zhin.js/agent/tools';
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { getEndpoint } from '../../src/napcat-agent-deps.js';
4
4
 
5
- export default defineTool<{ endpoint_id: string; group_id: number; file: string; name: string; folder?: string }>({
5
+ export default defineAgentTool<{ endpoint_id: string; group_id: number; file: string; name: string; folder?: string }>({
6
6
  description: '上传文件到群。file 为本地路径或 URL。',
7
7
  inputSchema: z.object({
8
8
  endpoint_id: z.string().describe('Endpoint 名称'),
@@ -0,0 +1,26 @@
1
+ import type { EndpointInstance } from '@zhin.js/adapter';
2
+ import type { MessageGateway } from '@zhin.js/core/runtime';
3
+ import type { HttpHost } from '@zhin.js/host-http';
4
+ import type { CapabilityId } from '@zhin.js/plugin-runtime';
5
+ import { callNapCatHttpAction, type NapCatEvent, type NapCatHttpConfig } from './protocol.js';
6
+ export interface NapCatHttpEndpointOptions {
7
+ readonly id: CapabilityId;
8
+ readonly gateway: MessageGateway;
9
+ readonly http: HttpHost;
10
+ readonly config: NapCatHttpConfig;
11
+ readonly callHttpAction?: typeof callNapCatHttpAction;
12
+ }
13
+ export declare class NapCatHttpEndpoint implements EndpointInstance {
14
+ #private;
15
+ constructor(options: NapCatHttpEndpointOptions);
16
+ start(): Promise<void>;
17
+ open(): void;
18
+ close(): void;
19
+ stop(): Promise<void>;
20
+ send({ target, payload }: {
21
+ readonly target: string;
22
+ readonly payload: unknown;
23
+ }): Promise<string>;
24
+ callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
25
+ admit(ev: NapCatEvent): void;
26
+ }
@@ -0,0 +1,147 @@
1
+ import { formatCompact, getLogger } from '@zhin.js/logger';
2
+ import { registerNapcatAgentEndpoint } from './napcat-agent-deps.js';
3
+ import { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
4
+ import { buildSendAction, callNapCatHttpAction, formatInboundContent, formatInboundTarget, formatOutboundSegments, isMessageEvent, senderNickname, senderUserId, } from './protocol.js';
5
+ import { readRequestBody } from './webhook.js';
6
+ import { verifyNapCatAccessToken } from './wss-auth.js';
7
+ const logger = getLogger('napcat');
8
+ export class NapCatHttpEndpoint {
9
+ #options;
10
+ #inboundDeduper = new InboundMessageDeduper();
11
+ #callHttpAction;
12
+ #routeReleases = [];
13
+ #open = false;
14
+ #started = false;
15
+ #unregisterAgent;
16
+ constructor(options) {
17
+ this.#options = options;
18
+ this.#callHttpAction = options.callHttpAction ?? callNapCatHttpAction;
19
+ }
20
+ async start() {
21
+ if (this.#started)
22
+ return;
23
+ this.#started = true;
24
+ this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.name, this);
25
+ this.#setupRoutes();
26
+ logger.info(formatCompact({
27
+ op: 'listen',
28
+ endpoint: this.#options.config.name,
29
+ mode: 'http',
30
+ path: this.#options.config.post_path,
31
+ }));
32
+ }
33
+ open() {
34
+ this.#open = true;
35
+ }
36
+ close() {
37
+ this.#open = false;
38
+ }
39
+ async stop() {
40
+ this.#open = false;
41
+ for (const release of this.#routeReleases.splice(0))
42
+ release();
43
+ this.#unregisterAgent?.();
44
+ this.#unregisterAgent = undefined;
45
+ this.#inboundDeduper.clear();
46
+ this.#started = false;
47
+ logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
48
+ }
49
+ async send({ target, payload }) {
50
+ const message = formatOutboundSegments(payload);
51
+ const { action, params } = buildSendAction(target, message);
52
+ const resp = await this.#callHttpAction({
53
+ http_url: this.#options.config.http_url,
54
+ access_token: this.#options.config.access_token,
55
+ }, action, params);
56
+ const data = resp.data;
57
+ const messageId = data?.message_id != null ? String(data.message_id) : '';
58
+ logger.debug(formatCompact({
59
+ op: 'napcat_send',
60
+ endpoint: this.#options.config.name,
61
+ target,
62
+ messageId,
63
+ }));
64
+ return messageId;
65
+ }
66
+ callApi(action, params = {}) {
67
+ return this.#callHttpAction({
68
+ http_url: this.#options.config.http_url,
69
+ access_token: this.#options.config.access_token,
70
+ }, action, params).then((resp) => resp.data);
71
+ }
72
+ admit(ev) {
73
+ if (!this.#open || !isMessageEvent(ev))
74
+ return;
75
+ if (isSelfMessage(ev))
76
+ return;
77
+ const msgId = String(ev.message_id);
78
+ if (!this.#inboundDeduper.shouldProcess(msgId))
79
+ return;
80
+ if (Array.isArray(ev.message) || typeof ev.message === 'string') {
81
+ ev = { ...ev, message: normalizeMessage(ev.message) };
82
+ }
83
+ const target = formatInboundTarget(ev);
84
+ const nickname = senderNickname(ev);
85
+ const mentioned = isNapCatBotMentioned(ev);
86
+ void this.#options.gateway.receive({
87
+ adapter: this.#options.id,
88
+ target,
89
+ content: formatInboundContent(ev),
90
+ sender: senderUserId(ev),
91
+ id: msgId,
92
+ metadata: Object.freeze({
93
+ message_type: ev.message_type,
94
+ user_id: ev.user_id != null ? String(ev.user_id) : undefined,
95
+ group_id: ev.group_id != null ? String(ev.group_id) : undefined,
96
+ endpoint: this.#options.config.name,
97
+ time: ev.time,
98
+ self_id: ev.self_id != null ? String(ev.self_id) : undefined,
99
+ role: ev.sender?.role,
100
+ ...(nickname ? { nickname } : {}),
101
+ ...(mentioned ? { mentioned: true } : {}),
102
+ }),
103
+ }).catch((err) => {
104
+ logger.warn(formatCompact({
105
+ op: 'napcat_gateway_receive_failed',
106
+ target,
107
+ error: err instanceof Error ? err.message : String(err),
108
+ }));
109
+ });
110
+ }
111
+ #setupRoutes() {
112
+ const path = this.#options.config.post_path;
113
+ this.#routeReleases.push(this.#options.http.route('POST', path, async (request, response) => {
114
+ await this.#handlePost(request, response);
115
+ }, { summary: 'NapCat HTTP event callback', tags: ['napcat'] }));
116
+ }
117
+ async #handlePost(request, response) {
118
+ try {
119
+ if (!verifyNapCatAccessToken(this.#options.config.access_token, request)) {
120
+ response.writeHead(403, { 'Content-Type': 'application/json' });
121
+ response.end(JSON.stringify({ message: 'Unauthorized' }));
122
+ return;
123
+ }
124
+ const raw = await readRequestBody(request);
125
+ let ev;
126
+ try {
127
+ ev = JSON.parse(raw);
128
+ }
129
+ catch {
130
+ response.writeHead(400, { 'Content-Type': 'application/json' });
131
+ response.end(JSON.stringify({ message: 'Invalid JSON' }));
132
+ return;
133
+ }
134
+ if (this.#open)
135
+ this.admit(ev);
136
+ response.writeHead(200, { 'Content-Type': 'application/json' });
137
+ response.end(JSON.stringify({ status: 'ok' }));
138
+ }
139
+ catch (error) {
140
+ logger.error('NapCat HTTP webhook error:', error);
141
+ if (!response.headersSent) {
142
+ response.writeHead(500, { 'Content-Type': 'application/json' });
143
+ response.end(JSON.stringify({ message: 'Internal Server Error' }));
144
+ }
145
+ }
146
+ }
147
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ export { buildSendAction, buildWsConnectOptions, callNapCatHttpAction, formatInboundContent, formatInboundTarget, formatOutboundSegments, getChannelId, isMessageEvent, parseSendTarget, resolveNapCatConfig, senderNickname, senderUserId, type MessageSegment, type NapCatActionRequest, type NapCatActionResponse, type NapCatAdapterConfig, type NapCatConfigBase, type NapCatEndpointConfig, type NapCatEvent, type NapCatHttpConfig, type NapCatMessageEvent, type NapCatSender, type NapCatWireSegment, type NapCatWsConfig, type NapCatWssConfig, type ParsedSendTarget, type ResolvedNapCatConfig, } from './protocol.js';
2
+ export { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
3
+ export { getEndpoint, getNapcatAgentDeps, registerNapcatAgentEndpoint, setNapcatAgentDeps, type NapcatAgentDeps, type NapcatAgentEndpoint, } from './napcat-agent-deps.js';
4
+ export { parseOneBotGetMsgResponse } from './onebot-get-msg.js';
5
+ export { NapCatWsEndpoint, type NapCatWsEndpointOptions, } from './ws-endpoint.js';
6
+ export { NapCatWssEndpoint, type NapCatWssEndpointOptions, } from './wss-endpoint.js';
7
+ export { NapCatHttpEndpoint, type NapCatHttpEndpointOptions, } from './http-endpoint.js';
8
+ export type { NapCatWsSocket, NapCatWsCreateOptions } from './ws-types.js';
9
+ export { callNapCatWsAction, decodeWsPayload, handleNapCatWsMessage, rejectAllPending, startNapCatHeartbeat, } from './ws-transport.js';
10
+ export { verifyNapCatAccessToken } from './wss-auth.js';
11
+ export { readRequestBody } from './webhook.js';
package/lib/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export { buildSendAction, buildWsConnectOptions, callNapCatHttpAction, formatInboundContent, formatInboundTarget, formatOutboundSegments, getChannelId, isMessageEvent, parseSendTarget, resolveNapCatConfig, senderNickname, senderUserId, } from './protocol.js';
2
+ export { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
3
+ export { getEndpoint, getNapcatAgentDeps, registerNapcatAgentEndpoint, setNapcatAgentDeps, } from './napcat-agent-deps.js';
4
+ export { parseOneBotGetMsgResponse } from './onebot-get-msg.js';
5
+ export { NapCatWsEndpoint, } from './ws-endpoint.js';
6
+ export { NapCatWssEndpoint, } from './wss-endpoint.js';
7
+ export { NapCatHttpEndpoint, } from './http-endpoint.js';
8
+ export { callNapCatWsAction, decodeWsPayload, handleNapCatWsMessage, rejectAllPending, startNapCatHeartbeat, } from './ws-transport.js';
9
+ export { verifyNapCatAccessToken } from './wss-auth.js';
10
+ export { readRequestBody } from './webhook.js';
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Agent tool deps for napcat.
3
+ * Endpoints register themselves on start; tools look up by config name / endpoint id.
4
+ */
5
+ export interface NapcatAgentEndpoint {
6
+ callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
7
+ setTitle(groupId: number, userId: number, title: string, duration?: number): Promise<boolean>;
8
+ sendLike(userId: number, times?: number): Promise<unknown>;
9
+ deleteFriend(userId: number): Promise<unknown>;
10
+ markMsgAsRead(messageId: number): Promise<unknown>;
11
+ ocrImage(image: string): Promise<unknown>;
12
+ setQQProfile(nickname: string, company?: string, email?: string, college?: string, personalNote?: string): Promise<unknown>;
13
+ setGroupPortrait(groupId: number, file: string): Promise<unknown>;
14
+ setEssenceMsg(messageId: number): Promise<unknown>;
15
+ deleteEssenceMsg(messageId: number): Promise<unknown>;
16
+ getEssenceMsgList(groupId: number): Promise<unknown>;
17
+ sendGroupSign(groupId: number): Promise<unknown>;
18
+ sendGroupNotice(groupId: number, content: string, image?: string): Promise<unknown>;
19
+ getGroupNotice(groupId: number): Promise<unknown>;
20
+ deleteGroupNotice(groupId: number, noticeId: string): Promise<unknown>;
21
+ uploadGroupFile(groupId: number, file: string, name: string, folder?: string): Promise<unknown>;
22
+ getGroupRootFiles(groupId: number): Promise<unknown>;
23
+ getGroupFileUrl(groupId: number, fileId: string, busid: number): Promise<unknown>;
24
+ downloadFile(url: string, threadCount?: number, headers?: string[]): Promise<unknown>;
25
+ setOnlineStatus(status: number, extStatus: number): Promise<unknown>;
26
+ setQQAvatar(file: string): Promise<unknown>;
27
+ forwardFriendSingleMsg(userId: number, messageId: number): Promise<unknown>;
28
+ forwardGroupSingleMsg(groupId: number, messageId: number): Promise<unknown>;
29
+ translateEn2Zh(sourceText: string): Promise<unknown>;
30
+ setMsgEmojiLike(messageId: number, emojiId: string): Promise<unknown>;
31
+ sendForwardMsg(messageType: 'private' | 'group', id: number, messages: unknown[]): Promise<unknown>;
32
+ getFriendMsgHistory(userId: number, messageSeq?: number, count?: number): Promise<unknown>;
33
+ getGroupMsgHistory(groupId: number, messageSeq?: number, count?: number): Promise<unknown>;
34
+ setSelfLongnick(longnick: string): Promise<unknown>;
35
+ getGroupInfoEx(groupId: number): Promise<unknown>;
36
+ sendPoke(userId: number, groupId?: number): Promise<unknown>;
37
+ ncGetUserStatus(userId: number): Promise<unknown>;
38
+ getGroupShutList(groupId: number): Promise<unknown>;
39
+ getMiniAppArk(type: string, title: string, desc: string, picUrl: string, jumpUrl: string): Promise<unknown>;
40
+ getAiCharacters(groupId: number): Promise<unknown>;
41
+ sendGroupAiRecord(groupId: number, characterId: string, text: string): Promise<unknown>;
42
+ }
43
+ export interface NapcatAgentDeps {
44
+ getEndpoint: (endpointId: string) => NapcatAgentEndpoint;
45
+ }
46
+ export declare function registerNapcatAgentEndpoint(endpointId: string, endpoint: NapcatAgentEndpoint): () => void;
47
+ /** Optional override used by tests / transitional callers. Pass `null` to clear. */
48
+ export declare function setNapcatAgentDeps(deps: NapcatAgentDeps | null): void;
49
+ export declare function getNapcatAgentDeps(): NapcatAgentDeps;
50
+ /** Convenience for agent/tools (unchanged call sites). */
51
+ export declare function getEndpoint(endpointId: string): NapcatAgentEndpoint;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Agent tool deps for napcat.
3
+ * Endpoints register themselves on start; tools look up by config name / endpoint id.
4
+ */
5
+ const endpoints = new Map();
6
+ let override = null;
7
+ export function registerNapcatAgentEndpoint(endpointId, endpoint) {
8
+ endpoints.set(endpointId, endpoint);
9
+ return () => {
10
+ if (endpoints.get(endpointId) === endpoint) {
11
+ endpoints.delete(endpointId);
12
+ }
13
+ };
14
+ }
15
+ /** Optional override used by tests / transitional callers. Pass `null` to clear. */
16
+ export function setNapcatAgentDeps(deps) {
17
+ override = deps;
18
+ }
19
+ function lookup(endpointId) {
20
+ const registered = endpoints.get(endpointId);
21
+ if (!registered)
22
+ throw new Error(`Endpoint ${endpointId} not found`);
23
+ return registered;
24
+ }
25
+ export function getNapcatAgentDeps() {
26
+ if (override)
27
+ return override;
28
+ return { getEndpoint: lookup };
29
+ }
30
+ /** Convenience for agent/tools (unchanged call sites). */
31
+ export function getEndpoint(endpointId) {
32
+ return getNapcatAgentDeps().getEndpoint(endpointId);
33
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * NapCat 入站消息治理:去重、自发过滤、消息归一化
3
+ */
4
+ import type { NapCatMessageEvent, MessageSegment } from './protocol.js';
5
+ export declare class InboundMessageDeduper {
6
+ private readonly seen;
7
+ shouldProcess(messageId: string): boolean;
8
+ clear(): void;
9
+ }
10
+ /** 判断是否为 bot 自身发出的消息 */
11
+ export declare function isSelfMessage(event: NapCatMessageEvent | {
12
+ post_type?: string;
13
+ self_id?: number | string;
14
+ user_id?: number | string;
15
+ }): boolean;
16
+ /**
17
+ * 将 message 字段归一化为 MessageSegment[]。
18
+ * NapCat 通常返回数组,但某些配置下可能返回 CQ 字符串。
19
+ */
20
+ export declare function normalizeMessage(message: MessageSegment[] | string): MessageSegment[];
21
+ /**
22
+ * OneBot11 mentioned 判定:消息段 {type:'at', data:{qq}} 的 qq 等于本机 uin
23
+ * (事件 self_id)时为 true;`qq === 'all'` 不算。兼容 CQ 字符串形式。
24
+ */
25
+ export declare function isNapCatBotMentioned(ev: {
26
+ self_id?: number | string;
27
+ message?: MessageSegment[] | string;
28
+ }): boolean;
@@ -37,19 +37,34 @@ export function normalizeMessage(message) {
37
37
  }
38
38
  return [];
39
39
  }
40
+ const CQ_AT_RE = /\[CQ:at,qq=([^\],\s]+)\]/g;
41
+ function atTargetMatchesUin(target, uin) {
42
+ const qq = String(target ?? '').trim();
43
+ return Boolean(qq) && qq !== 'all' && Number(qq) === Number(uin);
44
+ }
40
45
  /**
41
- * 生成用于 notice / request 事件的去重 key
46
+ * OneBot11 mentioned 判定:消息段 {type:'at', data:{qq}} 的 qq 等于本机 uin
47
+ * (事件 self_id)时为 true;`qq === 'all'` 不算。兼容 CQ 字符串形式。
42
48
  */
43
- export function resolveSideEventDedupeKey(event, prefix) {
44
- const parts = [prefix, event.time, event.notice_type || event.request_type];
45
- if (event.group_id)
46
- parts.push(event.group_id);
47
- if (event.user_id)
48
- parts.push(event.user_id);
49
- if (event.message_id)
50
- parts.push(event.message_id);
51
- if (event.flag)
52
- parts.push(event.flag);
53
- return parts.join(':');
49
+ export function isNapCatBotMentioned(ev) {
50
+ if (ev.self_id == null)
51
+ return false;
52
+ const uin = String(ev.self_id).trim();
53
+ if (!uin)
54
+ return false;
55
+ const segments = normalizeMessage(ev.message ?? []);
56
+ for (const seg of segments) {
57
+ if (seg.type === 'at' && atTargetMatchesUin(seg.data?.qq, uin))
58
+ return true;
59
+ }
60
+ const text = segments
61
+ .map((seg) => (seg.type === 'text' ? String(seg.data?.text ?? '') : ''))
62
+ .join('');
63
+ if (!text)
64
+ return false;
65
+ for (const match of text.matchAll(CQ_AT_RE)) {
66
+ if (atTargetMatchesUin(match[1], uin))
67
+ return true;
68
+ }
69
+ return false;
54
70
  }
55
- //# sourceMappingURL=napcat-inbound.js.map
@@ -0,0 +1,14 @@
1
+ export interface QuotedMessagePayload {
2
+ messageId: string;
3
+ sender?: {
4
+ id: string;
5
+ name: string;
6
+ };
7
+ content: Array<{
8
+ type: string;
9
+ data?: Record<string, unknown>;
10
+ }>;
11
+ raw?: string;
12
+ time?: number;
13
+ }
14
+ export declare function parseOneBotGetMsgResponse(messageId: string, data: unknown): QuotedMessagePayload;
@@ -24,4 +24,3 @@ export function parseOneBotGetMsgResponse(messageId, data) {
24
24
  time: typeof record.time === 'number' ? record.time : undefined,
25
25
  };
26
26
  }
27
- //# sourceMappingURL=onebot-get-msg.js.map
@@ -0,0 +1,151 @@
1
+ /**
2
+ * NapCat protocol helpers (OneBot 11 + NapCat extensions).
3
+ * No legacy Adapter/Endpoint / segment-mapper.
4
+ * Canonicalization is owned by gateway/core before endpoint.send.
5
+ */
6
+ /** Transitional legacy endpoint row (`endpoints[]` with `context: napcat`). */
7
+ export interface NapCatLegacyEndpointRow {
8
+ readonly context?: string;
9
+ readonly connection?: 'ws' | 'wss' | 'http';
10
+ readonly name?: string;
11
+ readonly access_token?: string;
12
+ readonly url?: string;
13
+ readonly path?: string;
14
+ readonly http_url?: string;
15
+ readonly post_path?: string;
16
+ readonly reconnect_interval?: number;
17
+ readonly heartbeat_interval?: number;
18
+ readonly poll_interval?: number;
19
+ }
20
+ /** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
21
+ export interface NapCatAdapterConfig {
22
+ readonly connection?: 'ws' | 'wss' | 'http';
23
+ readonly name?: string;
24
+ readonly access_token?: string;
25
+ readonly url?: string;
26
+ readonly path?: string;
27
+ readonly http_url?: string;
28
+ readonly post_path?: string;
29
+ readonly reconnect_interval?: number;
30
+ readonly heartbeat_interval?: number;
31
+ readonly poll_interval?: number;
32
+ /** Transitional: legacy root `endpoints[]` with `context: napcat`. */
33
+ readonly endpoints?: ReadonlyArray<NapCatLegacyEndpointRow>;
34
+ }
35
+ export interface NapCatConfigBase {
36
+ readonly context: 'napcat';
37
+ readonly name: string;
38
+ readonly access_token?: string;
39
+ }
40
+ /** 正向 WebSocket:应用连 NapCat WS */
41
+ export interface NapCatWsConfig extends NapCatConfigBase {
42
+ readonly connection: 'ws';
43
+ readonly url: string;
44
+ readonly reconnect_interval: number;
45
+ readonly heartbeat_interval: number;
46
+ }
47
+ /** 反向 WebSocket:httpHostToken WS upgrade 入站/出站 */
48
+ export interface NapCatWssConfig extends NapCatConfigBase {
49
+ readonly connection: 'wss';
50
+ readonly path: string;
51
+ readonly heartbeat_interval: number;
52
+ }
53
+ /** HTTP API + POST 上报:httpHostToken POST 入站 + http_url/{action} 出站 */
54
+ export interface NapCatHttpConfig extends NapCatConfigBase {
55
+ readonly connection: 'http';
56
+ readonly http_url: string;
57
+ readonly post_path: string;
58
+ readonly poll_interval: number;
59
+ }
60
+ export type ResolvedNapCatConfig = NapCatWsConfig | NapCatWssConfig | NapCatHttpConfig;
61
+ export type NapCatEndpointConfig = ResolvedNapCatConfig;
62
+ export interface NapCatSender {
63
+ readonly role?: string;
64
+ readonly nickname?: string;
65
+ readonly card?: string;
66
+ readonly title?: string;
67
+ readonly user_id?: number;
68
+ }
69
+ export interface MessageSegment {
70
+ type: string;
71
+ data?: Record<string, unknown>;
72
+ }
73
+ export interface NapCatEvent {
74
+ post_type: string;
75
+ self_id?: number | string;
76
+ message_type?: string;
77
+ sub_type?: string;
78
+ message_id?: number | string;
79
+ user_id?: number | string;
80
+ group_id?: number | string;
81
+ sender?: NapCatSender;
82
+ message?: MessageSegment[] | string;
83
+ raw_message?: string;
84
+ time?: number;
85
+ notice_type?: string;
86
+ request_type?: string;
87
+ [key: string]: unknown;
88
+ }
89
+ export type NapCatMessageEvent = NapCatEvent & {
90
+ post_type: 'message' | 'message_sent';
91
+ message_id: number | string;
92
+ user_id: number | string;
93
+ };
94
+ export interface NapCatActionRequest {
95
+ action: string;
96
+ params: Record<string, unknown>;
97
+ echo?: string;
98
+ }
99
+ export interface NapCatActionResponse {
100
+ status: string;
101
+ retcode: number;
102
+ data?: unknown;
103
+ echo?: string;
104
+ message?: string;
105
+ wording?: string;
106
+ }
107
+ export interface NapCatWireSegment {
108
+ readonly type: string;
109
+ readonly data?: Record<string, unknown>;
110
+ }
111
+ export interface ParsedSendTarget {
112
+ readonly message_type: 'private' | 'group';
113
+ readonly id: string;
114
+ }
115
+ export declare function resolveNapCatConfig(config?: NapCatAdapterConfig): ResolvedNapCatConfig;
116
+ export declare function isMessageEvent(ev: NapCatEvent): ev is NapCatMessageEvent;
117
+ export declare function getChannelId(ev: NapCatEvent): string;
118
+ export declare function formatInboundTarget(ev: NapCatEvent): string;
119
+ export declare function parseSendTarget(target: string): ParsedSendTarget;
120
+ export declare function formatInboundContent(ev: NapCatEvent): string;
121
+ /**
122
+ * 入站 sender 语义:必须是用户 ID(Runtime Message contract)。
123
+ * 显示名走 metadata.nickname,见 senderNickname。
124
+ */
125
+ export declare function senderUserId(ev: NapCatEvent): string;
126
+ /** 显示名(群名片 card 优先于 nickname),没有则 undefined。 */
127
+ export declare function senderNickname(ev: NapCatEvent): string | undefined;
128
+ /**
129
+ * Wire-encode an already-rendered outbound payload into OneBot message segments.
130
+ * Segment canonicalization is intentionally not done here.
131
+ */
132
+ export declare function formatOutboundSegments(payload: unknown): MessageSegment[];
133
+ export declare function buildSendAction(target: string, message: MessageSegment[]): {
134
+ action: string;
135
+ params: Record<string, unknown>;
136
+ };
137
+ /** Build WS connect URL + headers (access_token via Bearer + query). */
138
+ export declare function buildWsConnectOptions(config: NapCatWsConfig): {
139
+ readonly url: string;
140
+ readonly headers: Record<string, string>;
141
+ readonly safeUrl: string;
142
+ };
143
+ export interface NapCatHttpOptions {
144
+ readonly http_url: string;
145
+ readonly access_token?: string;
146
+ }
147
+ /**
148
+ * 向 NapCat HTTP API 发送动作请求:POST {http_url}/{action}。
149
+ * 供 connection:http 出站与纯协议测试使用。
150
+ */
151
+ export declare function callNapCatHttpAction(options: NapCatHttpOptions, action: string, params?: Record<string, unknown>): Promise<NapCatActionResponse>;