@zhin.js/adapter-napcat 1.0.0 → 2.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.
- package/CHANGELOG.md +23 -0
- package/README.md +6 -6
- package/client/NapCatManagement.tsx +14 -14
- package/dist/index.js +1 -1
- package/lib/adapter.d.ts +16 -15
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +46 -45
- package/lib/adapter.js.map +1 -1
- package/lib/{bot-base.d.ts → endpoint-base.d.ts} +7 -7
- package/lib/endpoint-base.d.ts.map +1 -0
- package/lib/{bot-base.js → endpoint-base.js} +7 -7
- package/lib/endpoint-base.js.map +1 -0
- package/lib/{bot-http.d.ts → endpoint-http.d.ts} +3 -3
- package/lib/endpoint-http.d.ts.map +1 -0
- package/lib/{bot-http.js → endpoint-http.js} +7 -7
- package/lib/endpoint-http.js.map +1 -0
- package/lib/{bot-ws-client.d.ts → endpoint-ws-client.d.ts} +3 -3
- package/lib/endpoint-ws-client.d.ts.map +1 -0
- package/lib/{bot-ws-client.js → endpoint-ws-client.js} +9 -9
- package/lib/endpoint-ws-client.js.map +1 -0
- package/lib/{bot-ws-server.d.ts → endpoint-ws-server.d.ts} +3 -3
- package/lib/endpoint-ws-server.d.ts.map +1 -0
- package/lib/{bot-ws-server.js → endpoint-ws-server.js} +9 -9
- package/lib/endpoint-ws-server.js.map +1 -0
- package/lib/index.d.ts +5 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +6 -5
- package/lib/index.js.map +1 -1
- package/lib/routes.js +14 -14
- package/lib/routes.js.map +1 -1
- package/lib/tools.d.ts.map +1 -1
- package/lib/tools.js +150 -150
- package/lib/tools.js.map +1 -1
- package/lib/types.d.ts +1 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/typing-indicator.d.ts +6 -6
- package/lib/typing-indicator.d.ts.map +1 -1
- package/lib/typing-indicator.js +17 -17
- package/lib/typing-indicator.js.map +1 -1
- package/package.json +11 -9
- package/skills/napcat/PERMITS.md +19 -0
- package/skills/napcat/SKILL.md +4 -4
- package/src/adapter.ts +42 -40
- package/src/{bot-base.ts → endpoint-base.ts} +9 -9
- package/src/{bot-http.ts → endpoint-http.ts} +6 -6
- package/src/{bot-ws-client.ts → endpoint-ws-client.ts} +8 -8
- package/src/{bot-ws-server.ts → endpoint-ws-server.ts} +8 -8
- package/src/index.ts +7 -5
- package/src/routes.ts +14 -14
- package/src/tools.ts +153 -153
- package/src/types.ts +1 -1
- package/src/typing-indicator.ts +20 -20
- package/lib/bot-base.d.ts.map +0 -1
- package/lib/bot-base.js.map +0 -1
- package/lib/bot-http.d.ts.map +0 -1
- package/lib/bot-http.js.map +0 -1
- package/lib/bot-ws-client.d.ts.map +0 -1
- package/lib/bot-ws-client.js.map +0 -1
- package/lib/bot-ws-server.d.ts.map +0 -1
- package/lib/bot-ws-server.js.map +0 -1
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
* 入站:挂载 webhook 路由接收 NapCat 的 HTTP POST 事件上报
|
|
5
5
|
*/
|
|
6
6
|
import { formatCompact } from 'zhin.js';
|
|
7
|
-
import {
|
|
7
|
+
import { NapCatEndpointBase } from './endpoint-base.js';
|
|
8
8
|
import type { NapCatHttpConfig, ApiResponse } from './types.js';
|
|
9
9
|
import type { NapCatAdapter } from './adapter.js';
|
|
10
10
|
import { registerFetchRoute, type Router, type RouterContext } from '@zhin.js/host-router/router';
|
|
11
11
|
import * as crypto from 'crypto';
|
|
12
12
|
import { enableTypingIndicator } from './typing-indicator.js';
|
|
13
13
|
|
|
14
|
-
export class
|
|
14
|
+
export class NapCatHttpEndpoint extends NapCatEndpointBase {
|
|
15
15
|
private pollTimer?: NodeJS.Timeout;
|
|
16
16
|
|
|
17
17
|
declare $config: NapCatHttpConfig;
|
|
@@ -26,7 +26,7 @@ export class NapCatHttpBot extends NapCatBotBase {
|
|
|
26
26
|
this.startPoll();
|
|
27
27
|
this.$connected = true;
|
|
28
28
|
this.initTypingIndicator();
|
|
29
|
-
this.logger.info(formatCompact({
|
|
29
|
+
this.logger.info(formatCompact({ endpoint: this.$id, mode: 'http' }));
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async $disconnect(): Promise<void> {
|
|
@@ -69,10 +69,10 @@ export class NapCatHttpBot extends NapCatBotBase {
|
|
|
69
69
|
ctx.status = 204;
|
|
70
70
|
ctx.body = '';
|
|
71
71
|
try { this.dispatchEvent(body); } catch (e) {
|
|
72
|
-
this.logger.warn(formatCompact( { op: 'recv',
|
|
72
|
+
this.logger.warn(formatCompact( { op: 'recv', endpoint: this.$id, ok: false, error: String(e) }));
|
|
73
73
|
}
|
|
74
74
|
});
|
|
75
|
-
this.logger.info(formatCompact( { op: 'webhook',
|
|
75
|
+
this.logger.info(formatCompact( { op: 'webhook', endpoint: this.$id, path: postPath }));
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
private async checkConnection(): Promise<void> {
|
|
@@ -90,7 +90,7 @@ export class NapCatHttpBot extends NapCatBotBase {
|
|
|
90
90
|
await this.callApi('get_status');
|
|
91
91
|
} catch {
|
|
92
92
|
this.$connected = false;
|
|
93
|
-
this.logger.warn(formatCompact( { op: 'heartbeat',
|
|
93
|
+
this.logger.warn(formatCompact( { op: 'heartbeat', endpoint: this.$id, ok: false }));
|
|
94
94
|
}
|
|
95
95
|
}, interval);
|
|
96
96
|
}
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import WebSocket from 'ws';
|
|
5
5
|
import { formatCompact } from 'zhin.js';
|
|
6
|
-
import {
|
|
6
|
+
import { NapCatEndpointBase } from './endpoint-base.js';
|
|
7
7
|
import type { NapCatWsClientConfig, ApiResponse } from './types.js';
|
|
8
8
|
import type { NapCatAdapter } from './adapter.js';
|
|
9
9
|
import { enableTypingIndicator } from './typing-indicator.js';
|
|
10
10
|
|
|
11
|
-
export class NapCatWsClient extends
|
|
11
|
+
export class NapCatWsClient extends NapCatEndpointBase {
|
|
12
12
|
private ws?: WebSocket;
|
|
13
13
|
private reconnectTimer?: NodeJS.Timeout;
|
|
14
14
|
private heartbeatTimer?: NodeJS.Timeout;
|
|
@@ -40,9 +40,9 @@ export class NapCatWsClient extends NapCatBotBase {
|
|
|
40
40
|
this.ws.on('open', () => {
|
|
41
41
|
this.$connected = true;
|
|
42
42
|
if (!this.$config.access_token) {
|
|
43
|
-
this.logger.warn(formatCompact({
|
|
43
|
+
this.logger.warn(formatCompact({ endpoint: this.$id, ok: false, error: 'missing access_token' }));
|
|
44
44
|
}
|
|
45
|
-
this.logger.info(formatCompact({
|
|
45
|
+
this.logger.info(formatCompact({ endpoint: this.$id, mode: 'ws' }));
|
|
46
46
|
this.startHeartbeat();
|
|
47
47
|
this.initTypingIndicator();
|
|
48
48
|
resolve();
|
|
@@ -62,7 +62,7 @@ export class NapCatWsClient extends NapCatBotBase {
|
|
|
62
62
|
const codeHint = code === 1005 ? ' [no status]' : code === 1006 ? ' [abnormal]' : '';
|
|
63
63
|
this.logger.warn(formatCompact( {
|
|
64
64
|
op: 'disconnect',
|
|
65
|
-
|
|
65
|
+
endpoint: this.$id,
|
|
66
66
|
code,
|
|
67
67
|
error: reasonStr || 'closed',
|
|
68
68
|
reconnect_ms: this.$config.reconnect_interval || 5000,
|
|
@@ -74,7 +74,7 @@ export class NapCatWsClient extends NapCatBotBase {
|
|
|
74
74
|
this.ws.on('error', (error) => {
|
|
75
75
|
this.logger.warn(formatCompact( {
|
|
76
76
|
op: 'ws_error',
|
|
77
|
-
|
|
77
|
+
endpoint: this.$id,
|
|
78
78
|
ok: false,
|
|
79
79
|
error: error instanceof Error ? error.message : String(error),
|
|
80
80
|
}));
|
|
@@ -133,7 +133,7 @@ export class NapCatWsClient extends NapCatBotBase {
|
|
|
133
133
|
|
|
134
134
|
protected handleMeta(event: any): void {
|
|
135
135
|
if (event.meta_event_type === 'lifecycle' && event.sub_type === 'connect') {
|
|
136
|
-
this.logger.info(formatCompact({
|
|
136
|
+
this.logger.info(formatCompact({ endpoint: this.$id, lifecycle: 'connect', self_id: event.self_id }));
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
|
|
@@ -158,7 +158,7 @@ export class NapCatWsClient extends NapCatBotBase {
|
|
|
158
158
|
removeDelay: 5000,
|
|
159
159
|
} : undefined,
|
|
160
160
|
});
|
|
161
|
-
this.logger.info(formatCompact({
|
|
161
|
+
this.logger.info(formatCompact({ endpoint: this.$id, typingIndicator: 'enabled' }));
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
}
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
import WebSocket, { WebSocketServer } from 'ws';
|
|
5
5
|
import { formatCompact } from 'zhin.js';
|
|
6
6
|
import type { IncomingMessage } from 'http';
|
|
7
|
-
import {
|
|
7
|
+
import { NapCatEndpointBase } from './endpoint-base.js';
|
|
8
8
|
import type { NapCatWsServerConfig, ApiResponse } from './types.js';
|
|
9
9
|
import type { NapCatAdapter } from './adapter.js';
|
|
10
10
|
import type { Router } from '@zhin.js/host-router';
|
|
11
11
|
import { enableTypingIndicator } from './typing-indicator.js';
|
|
12
12
|
|
|
13
|
-
export class NapCatWsServer extends
|
|
13
|
+
export class NapCatWsServer extends NapCatEndpointBase {
|
|
14
14
|
#wss?: WebSocketServer;
|
|
15
15
|
#clientMap = new Map<string, WebSocket>();
|
|
16
16
|
private heartbeatTimer?: NodeJS.Timeout;
|
|
@@ -29,7 +29,7 @@ export class NapCatWsServer extends NapCatBotBase {
|
|
|
29
29
|
|
|
30
30
|
async $connect(): Promise<void> {
|
|
31
31
|
if (!this.$config.access_token) {
|
|
32
|
-
this.logger.warn(formatCompact({
|
|
32
|
+
this.logger.warn(formatCompact({ endpoint: this.$id, ok: false, error: 'missing access_token' }));
|
|
33
33
|
}
|
|
34
34
|
this.#wss = this.router.ws(this.$config.path, {
|
|
35
35
|
verifyClient: (info: { origin: string; secure: boolean; req: IncomingMessage }) => {
|
|
@@ -41,15 +41,15 @@ export class NapCatWsServer extends NapCatBotBase {
|
|
|
41
41
|
return true;
|
|
42
42
|
},
|
|
43
43
|
});
|
|
44
|
-
this.logger.info(formatCompact( { op: 'listen',
|
|
44
|
+
this.logger.info(formatCompact( { op: 'listen', endpoint: this.$id, mode: 'wss', path: this.$config.path }));
|
|
45
45
|
|
|
46
46
|
this.#wss.on('connection', (client, req) => {
|
|
47
47
|
this.startHeartbeat();
|
|
48
|
-
this.logger.info(formatCompact({
|
|
48
|
+
this.logger.info(formatCompact({ endpoint: this.$id, peer: req.socket.remoteAddress }));
|
|
49
49
|
|
|
50
50
|
client.on('error', (err) => this.logger.warn(formatCompact( {
|
|
51
51
|
op: 'ws_error',
|
|
52
|
-
|
|
52
|
+
endpoint: this.$id,
|
|
53
53
|
ok: false,
|
|
54
54
|
error: err instanceof Error ? err.message : String(err),
|
|
55
55
|
})));
|
|
@@ -57,7 +57,7 @@ export class NapCatWsServer extends NapCatBotBase {
|
|
|
57
57
|
const reasonStr = reason?.toString?.() || '';
|
|
58
58
|
this.logger.warn(formatCompact( {
|
|
59
59
|
op: 'disconnect',
|
|
60
|
-
|
|
60
|
+
endpoint: this.$id,
|
|
61
61
|
code,
|
|
62
62
|
error: reasonStr || undefined,
|
|
63
63
|
}));
|
|
@@ -119,7 +119,7 @@ export class NapCatWsServer extends NapCatBotBase {
|
|
|
119
119
|
if (message.post_type === 'meta_event' && message.sub_type === 'connect') {
|
|
120
120
|
this.#clientMap.set(String(message.self_id), client);
|
|
121
121
|
this.$connected = true;
|
|
122
|
-
this.logger.info(formatCompact({
|
|
122
|
+
this.logger.info(formatCompact({ endpoint: this.$id, self_id: message.self_id }));
|
|
123
123
|
this.initTypingIndicator();
|
|
124
124
|
return;
|
|
125
125
|
}
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type Context,
|
|
11
11
|
type IGroupManagement,
|
|
12
12
|
createGroupManagementTools,
|
|
13
|
+
registerDefaultGroupPlatformPermitChecker,
|
|
13
14
|
type ToolFeature,
|
|
14
15
|
registerAgentPromptContributor,
|
|
15
16
|
unregisterAgentPromptContributor,
|
|
@@ -22,11 +23,11 @@ import { createNapCatAgentPromptContributor } from './agent-prompt.js';
|
|
|
22
23
|
import { registerRoutes } from './routes.js';
|
|
23
24
|
|
|
24
25
|
export * from './types.js';
|
|
25
|
-
export { NapCatWsClient } from './
|
|
26
|
-
export { NapCatWsServer } from './
|
|
27
|
-
export {
|
|
28
|
-
export { NapCatAdapter, type
|
|
29
|
-
export {
|
|
26
|
+
export { NapCatWsClient } from './endpoint-ws-client.js';
|
|
27
|
+
export { NapCatWsServer } from './endpoint-ws-server.js';
|
|
28
|
+
export { NapCatHttpEndpoint } from './endpoint-http.js';
|
|
29
|
+
export { NapCatAdapter, type NapCatEndpoint } from './adapter.js';
|
|
30
|
+
export { NapCatEndpointBase } from './endpoint-base.js';
|
|
30
31
|
export {
|
|
31
32
|
NapCatTypingIndicatorManager,
|
|
32
33
|
enableTypingIndicator,
|
|
@@ -67,6 +68,7 @@ provide({
|
|
|
67
68
|
// ── AI 工具注册 ────────────────────────────────────────────────────
|
|
68
69
|
useContext('tool', 'napcat', (toolService: ToolFeature, napcat: NapCatAdapter) => {
|
|
69
70
|
const disposers: (() => void)[] = [];
|
|
71
|
+
disposers.push(registerDefaultGroupPlatformPermitChecker('napcat'));
|
|
70
72
|
|
|
71
73
|
const groupTools = createGroupManagementTools(
|
|
72
74
|
napcat as unknown as IGroupManagement,
|
package/src/routes.ts
CHANGED
|
@@ -2,28 +2,28 @@ import type { Router } from '@zhin.js/host-router';
|
|
|
2
2
|
import type { NapCatAdapter } from './adapter.js';
|
|
3
3
|
|
|
4
4
|
export function registerRoutes(router: Router, napcat: NapCatAdapter): void {
|
|
5
|
-
router.get('/api/napcat/
|
|
5
|
+
router.get('/api/napcat/endpoints', async (ctx) => {
|
|
6
6
|
try {
|
|
7
|
-
const
|
|
8
|
-
if (
|
|
9
|
-
ctx.body = { success: true, data: [], message: '暂无 NapCat
|
|
7
|
+
const endpoints = Array.from(napcat.endpoints.values());
|
|
8
|
+
if (endpoints.length === 0) {
|
|
9
|
+
ctx.body = { success: true, data: [], message: '暂无 NapCat Endpoint 实例' };
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
const result = await Promise.all(
|
|
13
|
-
|
|
13
|
+
endpoints.map(async (endpoint) => {
|
|
14
14
|
try {
|
|
15
|
-
const connection = (
|
|
15
|
+
const connection = (endpoint.$config as any).connection ?? 'ws';
|
|
16
16
|
const base: Record<string, unknown> = {
|
|
17
|
-
name:
|
|
18
|
-
connected:
|
|
17
|
+
name: endpoint.$config.name,
|
|
18
|
+
connected: endpoint.$connected || false,
|
|
19
19
|
connection,
|
|
20
|
-
status:
|
|
20
|
+
status: endpoint.$connected ? 'online' : 'offline',
|
|
21
21
|
lastActivity: new Date().toISOString(),
|
|
22
22
|
};
|
|
23
|
-
if (
|
|
23
|
+
if (endpoint.$connected) {
|
|
24
24
|
try {
|
|
25
|
-
const friends = await
|
|
26
|
-
const groups = await
|
|
25
|
+
const friends = await endpoint.getFriendList();
|
|
26
|
+
const groups = await endpoint.getGroupList();
|
|
27
27
|
base.friendCount = Array.isArray(friends) ? friends.length : 0;
|
|
28
28
|
base.groupCount = Array.isArray(groups) ? groups.length : 0;
|
|
29
29
|
} catch {
|
|
@@ -37,7 +37,7 @@ export function registerRoutes(router: Router, napcat: NapCatAdapter): void {
|
|
|
37
37
|
return base;
|
|
38
38
|
} catch {
|
|
39
39
|
return {
|
|
40
|
-
name:
|
|
40
|
+
name: endpoint.$config.name,
|
|
41
41
|
connected: false,
|
|
42
42
|
connection: 'unknown',
|
|
43
43
|
status: 'error',
|
|
@@ -53,7 +53,7 @@ export function registerRoutes(router: Router, napcat: NapCatAdapter): void {
|
|
|
53
53
|
ctx.body = {
|
|
54
54
|
success: false,
|
|
55
55
|
error: 'NAPCAT_API_ERROR',
|
|
56
|
-
message: '
|
|
56
|
+
message: '获取 Endpoint 数据失败',
|
|
57
57
|
details: process.env.NODE_ENV === 'development' ? (error as Error).message : undefined,
|
|
58
58
|
};
|
|
59
59
|
}
|