@zhin.js/adapter-napcat 6.0.2 → 6.0.5

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,100 @@
1
1
  # @zhin.js/adapter-napcat
2
2
 
3
+ ## 6.0.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 51015d6: refactor(adapters): migrate platform-permit to PermissionSubject
8
+
9
+ All adapter platform-permit checkers now accept PermissionSubject
10
+ (duck-typed from Message/CommandSession) instead of Message directly.
11
+ registerPlatformPermitChecker is replaced by host.registerPlatform in
12
+ the adapter plugin setup. activity-feedback service updated for new
13
+ PermissionHost integration.
14
+
15
+ - Updated dependencies [6f9c366]
16
+ - Updated dependencies [373a56b]
17
+ - Updated dependencies [0de46a8]
18
+ - Updated dependencies [c106ecc]
19
+ - Updated dependencies [ca92e03]
20
+ - Updated dependencies [b0f37ae]
21
+ - Updated dependencies [ba08a2f]
22
+ - Updated dependencies [b08f7fe]
23
+ - Updated dependencies [daffd4c]
24
+ - Updated dependencies [36c7400]
25
+ - Updated dependencies [a9fa72e]
26
+ - Updated dependencies [c8de3ef]
27
+ - Updated dependencies [60f0fc8]
28
+ - Updated dependencies [574c990]
29
+ - Updated dependencies [d096f16]
30
+ - Updated dependencies [3f29623]
31
+ - Updated dependencies [2916852]
32
+ - Updated dependencies [d047869]
33
+ - Updated dependencies [162fa34]
34
+ - Updated dependencies [e62561e]
35
+ - Updated dependencies [3eeeb46]
36
+ - Updated dependencies [85d0f82]
37
+ - Updated dependencies [61bfc1c]
38
+ - Updated dependencies [04bad47]
39
+ - Updated dependencies [e40b048]
40
+ - Updated dependencies [5a5b1bb]
41
+ - Updated dependencies [f1708c3]
42
+ - Updated dependencies [d254a81]
43
+ - Updated dependencies [7123c47]
44
+ - Updated dependencies [05befc1]
45
+ - Updated dependencies [0663b6a]
46
+ - Updated dependencies [f28f9b3]
47
+ - Updated dependencies [9f340f7]
48
+ - Updated dependencies [e53444f]
49
+ - Updated dependencies [5eedd26]
50
+ - Updated dependencies [92b0dd7]
51
+ - Updated dependencies [f919b6f]
52
+ - Updated dependencies [098e411]
53
+ - Updated dependencies [e1b7c01]
54
+ - Updated dependencies [9b94f87]
55
+ - Updated dependencies [a7df753]
56
+ - @zhin.js/agent@1.1.5
57
+ - @zhin.js/host-http@1.0.8
58
+ - @zhin.js/permission@1.0.1
59
+ - @zhin.js/im-contract@1.0.3
60
+ - @zhin.js/adapter@1.1.7
61
+ - @zhin.js/plugin-runtime@1.1.5
62
+ - @zhin.js/command@1.0.9
63
+ - @zhin.js/core@1.5.4
64
+ - zhin.js@6.0.4
65
+
66
+ ## 6.0.4
67
+
68
+ ### Patch Changes
69
+
70
+ - f8c7a54: fix: im
71
+ - Updated dependencies [f8c7a54]
72
+ - @zhin.js/logger@1.0.76
73
+ - @zhin.js/host-http@1.0.7
74
+ - @zhin.js/adapter@1.1.6
75
+ - @zhin.js/agent@1.1.4
76
+ - @zhin.js/command@1.0.8
77
+ - @zhin.js/core@1.5.3
78
+ - @zhin.js/im-contract@1.0.2
79
+ - @zhin.js/plugin-runtime@1.1.4
80
+ - zhin.js@6.0.3
81
+
82
+ ## 6.0.3
83
+
84
+ ### Patch Changes
85
+
86
+ - Updated dependencies [afc0e66]
87
+ - Updated dependencies [2e41ad5]
88
+ - Updated dependencies [9f57124]
89
+ - @zhin.js/core@1.5.2
90
+ - @zhin.js/adapter@1.1.5
91
+ - @zhin.js/im-contract@1.0.1
92
+ - @zhin.js/plugin-runtime@1.1.3
93
+ - @zhin.js/command@1.0.7
94
+ - @zhin.js/host-http@1.0.6
95
+ - @zhin.js/agent@1.1.3
96
+ - zhin.js@6.0.2
97
+
3
98
  ## 6.0.2
4
99
 
5
100
  ### Patch Changes
package/README.md CHANGED
@@ -8,7 +8,7 @@ Zhin.js [NapCatQQ](https://github.com/NapNeko/NapCatQQ) 适配器(Plugin Runti
8
8
  - 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
9
9
  - **正向 WebSocket**(`connection: ws`):应用连 NapCat WS
10
10
  - `access_token` 鉴权(Bearer + query)
11
- - 入站经 `messageGatewayToken`(去重 + 自发过滤);出站 `send({ target, payload })`
11
+ - 入站经 `messageGatewayToken`(去重 + 自发过滤);出站 `send({ conversation, payload })`
12
12
  - 41 个 AI 工具(`agent/tools/`)
13
13
 
14
14
  ## 安装
@@ -24,8 +24,8 @@ pnpm add @zhin.js/adapter-napcat
24
24
  - `@zhin.js/plugin-runtime` — `plugin.ts`(`definePlugin`)
25
25
  - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
26
26
 
27
- 入站:`gateway.receive({ adapter, target: "private:uid"|"group:gid", content, sender, metadata })`
28
- 出站:`send({ target, payload })` → WS `send_private_msg` / `send_group_msg`
27
+ 入站:`gateway.receive({ conversation, message: { conversation, id }, content, sender, metadata })`(`conversation` 为 ConversationRef:私聊 `kind: 'private'`、群聊 `kind: 'group'`,临时会话群容器进 `parent`)
28
+ 出站:`send({ conversation, payload })` → WS `send_private_msg` / `send_group_msg`
29
29
 
30
30
  ## 最小配置
31
31
 
@@ -25,8 +25,8 @@ export default defineAdapter({
25
25
  const config = resolveNapCatConfig(context.config);
26
26
  const gateway = context.use(messageGatewayToken);
27
27
  // 注册到插件运行时状态(napcat.endpoint list 的"运行中"数据源)
28
- context.use(napcatRuntimeStateToken).endpoints.set(config.name, {
29
- name: config.name,
28
+ context.use(napcatRuntimeStateToken).endpoints.set(config.id, {
29
+ id: config.id,
30
30
  mode: config.connection,
31
31
  });
32
32
  if (config.connection === 'wss') {
@@ -36,8 +36,8 @@ export default defineAdapter<NapCatAdapterConfig>({
36
36
  const config = resolveNapCatConfig(context.config);
37
37
  const gateway = context.use(messageGatewayToken);
38
38
  // 注册到插件运行时状态(napcat.endpoint list 的"运行中"数据源)
39
- context.use(napcatRuntimeStateToken).endpoints.set(config.name, {
40
- name: config.name,
39
+ context.use(napcatRuntimeStateToken).endpoints.set(config.id, {
40
+ id: config.id,
41
41
  mode: config.connection,
42
42
  });
43
43
  if (config.connection === 'wss') {
@@ -1,4 +1,4 @@
1
- import type { EndpointInstance, EndpointManagement } from '@zhin.js/adapter';
1
+ import type { EndpointInstance, EndpointManagement, EndpointSendRequest } from '@zhin.js/adapter';
2
2
  import type { MessageGateway } from '@zhin.js/core/runtime';
3
3
  import type { HttpHost } from '@zhin.js/host-http';
4
4
  import type { CapabilityId } from '@zhin.js/plugin-runtime';
@@ -18,10 +18,7 @@ export declare class NapCatHttpEndpoint implements EndpointInstance {
18
18
  open(): void;
19
19
  close(): void;
20
20
  stop(): Promise<void>;
21
- send({ target, payload }: {
22
- readonly target: string;
23
- readonly payload: unknown;
24
- }): Promise<string>;
21
+ send({ conversation, payload }: EndpointSendRequest): Promise<string>;
25
22
  recallMessage(messageId: string): Promise<void>;
26
23
  callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
27
24
  admit(ev: NapCatEvent): void;
@@ -1,12 +1,12 @@
1
- import { formatCompact, getLogger } from '@zhin.js/logger';
1
+ import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
2
2
  import { createNapCatEndpointManagement } from './endpoint-management.js';
3
3
  import { registerNapcatAgentEndpoint } from './napcat-agent-deps.js';
4
4
  import { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
5
- import { buildSendAction, callNapCatHttpAction, formatInboundContent, formatInboundTarget, formatOutboundSegments, isMessageEvent, senderNickname, senderUserId, } from './protocol.js';
5
+ import { buildSendAction, callNapCatHttpAction, formatInboundContent, formatOutboundSegments, isMessageEvent, napcatInboundConversation, napcatOutboundTarget, senderNickname, senderUserId, } from './protocol.js';
6
6
  import { readRequestBody } from './webhook.js';
7
7
  import { verifyNapCatAccessToken } from './wss-auth.js';
8
- const logger = getLogger('napcat');
9
8
  export class NapCatHttpEndpoint {
9
+ #logger;
10
10
  #options;
11
11
  #inboundDeduper = new InboundMessageDeduper();
12
12
  management = createNapCatEndpointManagement(this);
@@ -16,6 +16,7 @@ export class NapCatHttpEndpoint {
16
16
  #started = false;
17
17
  #unregisterAgent;
18
18
  constructor(options) {
19
+ this.#logger = getAdapterLogger('napcat', options.config.id);
19
20
  this.#options = options;
20
21
  this.#callHttpAction = options.callHttpAction ?? callNapCatHttpAction;
21
22
  }
@@ -23,11 +24,11 @@ export class NapCatHttpEndpoint {
23
24
  if (this.#started)
24
25
  return;
25
26
  this.#started = true;
26
- this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.name, this);
27
+ this.#unregisterAgent = registerNapcatAgentEndpoint(this.#options.config.id, this);
27
28
  this.#setupRoutes();
28
- logger.info(formatCompact({
29
+ this.#logger.info(formatCompact({
29
30
  op: 'listen',
30
- endpoint: this.#options.config.name,
31
+ endpoint: this.#options.config.id,
31
32
  mode: 'http',
32
33
  path: this.#options.config.post_path,
33
34
  }));
@@ -46,21 +47,21 @@ export class NapCatHttpEndpoint {
46
47
  this.#unregisterAgent = undefined;
47
48
  this.#inboundDeduper.clear();
48
49
  this.#started = false;
49
- logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
50
+ this.#logger.debug(formatCompact({ op: 'disconnect' }));
50
51
  }
51
- async send({ target, payload }) {
52
+ async send({ conversation, payload }) {
52
53
  const message = formatOutboundSegments(payload);
53
- const { action, params } = buildSendAction(target, message);
54
+ const { action, params } = buildSendAction(napcatOutboundTarget(conversation), message);
54
55
  const resp = await this.#callHttpAction({
55
56
  http_url: this.#options.config.http_url,
56
57
  access_token: this.#options.config.access_token,
57
58
  }, action, params);
58
59
  const data = resp.data;
59
60
  const messageId = data?.message_id != null ? String(data.message_id) : '';
60
- logger.debug(formatCompact({
61
+ this.#logger.debug(formatCompact({
61
62
  op: 'napcat_send',
62
- endpoint: this.#options.config.name,
63
- target,
63
+ endpoint: this.#options.config.id,
64
+ target: `${conversation.kind}:${conversation.id}`,
64
65
  messageId,
65
66
  }));
66
67
  return messageId;
@@ -87,30 +88,33 @@ export class NapCatHttpEndpoint {
87
88
  if (Array.isArray(ev.message) || typeof ev.message === 'string') {
88
89
  ev = { ...ev, message: normalizeMessage(ev.message) };
89
90
  }
90
- const target = formatInboundTarget(ev);
91
+ const conversation = napcatInboundConversation(String(this.#options.id), ev);
91
92
  const nickname = senderNickname(ev);
92
93
  const mentioned = isNapCatBotMentioned(ev);
93
94
  void this.#options.gateway.receive({
94
- adapter: this.#options.id,
95
- target,
95
+ conversation,
96
+ message: { conversation, id: msgId },
96
97
  content: formatInboundContent(ev),
97
- sender: senderUserId(ev),
98
- id: msgId,
98
+ sender: {
99
+ id: senderUserId(ev),
100
+ name: nickname,
101
+ ...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
102
+ },
103
+ endpointId: this.#options.config.id,
104
+ ...(mentioned ? { mentioned: true } : {}),
99
105
  metadata: Object.freeze({
100
106
  message_type: ev.message_type,
101
107
  user_id: ev.user_id != null ? String(ev.user_id) : undefined,
102
108
  group_id: ev.group_id != null ? String(ev.group_id) : undefined,
103
- endpoint: this.#options.config.name,
104
109
  time: ev.time,
105
110
  self_id: ev.self_id != null ? String(ev.self_id) : undefined,
106
111
  role: ev.sender?.role,
107
112
  ...(nickname ? { nickname } : {}),
108
- ...(mentioned ? { mentioned: true } : {}),
109
113
  }),
110
114
  }).catch((err) => {
111
- logger.warn(formatCompact({
115
+ this.#logger.warn(formatCompact({
112
116
  op: 'napcat_gateway_receive_failed',
113
- target,
117
+ target: `${conversation.kind}:${conversation.id}`,
114
118
  error: err instanceof Error ? err.message : String(err),
115
119
  }));
116
120
  });
@@ -144,7 +148,7 @@ export class NapCatHttpEndpoint {
144
148
  response.end(JSON.stringify({ status: 'ok' }));
145
149
  }
146
150
  catch (error) {
147
- logger.error('NapCat HTTP webhook error:', error);
151
+ this.#logger.error('NapCat HTTP webhook error:', error);
148
152
  if (!response.headersSent) {
149
153
  response.writeHead(500, { 'Content-Type': 'application/json' });
150
154
  response.end(JSON.stringify({ message: 'Internal Server Error' }));
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { buildSendAction, buildWsConnectOptions, callNapCatHttpAction, formatInboundContent, formatInboundTarget, formatOutboundSegments, getChannelId, isMessageEvent, mediaRefToOneBotFile, 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';
1
+ export { buildSendAction, buildWsConnectOptions, callNapCatHttpAction, formatInboundContent, formatOutboundSegments, getChannelId, isMessageEvent, mediaRefToOneBotFile, napcatInboundConversation, napcatOutboundTarget, 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
2
  export { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
3
3
  export { getEndpoint, getNapcatAgentDeps, registerNapcatAgentEndpoint, setNapcatAgentDeps, type NapcatAgentDeps, type NapcatAgentEndpoint, } from './napcat-agent-deps.js';
4
4
  export { parseOneBotGetMsgResponse } from './onebot-get-msg.js';
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { buildSendAction, buildWsConnectOptions, callNapCatHttpAction, formatInboundContent, formatInboundTarget, formatOutboundSegments, getChannelId, isMessageEvent, mediaRefToOneBotFile, parseSendTarget, resolveNapCatConfig, senderNickname, senderUserId, } from './protocol.js';
1
+ export { buildSendAction, buildWsConnectOptions, callNapCatHttpAction, formatInboundContent, formatOutboundSegments, getChannelId, isMessageEvent, mediaRefToOneBotFile, napcatInboundConversation, napcatOutboundTarget, resolveNapCatConfig, senderNickname, senderUserId, } from './protocol.js';
2
2
  export { InboundMessageDeduper, isNapCatBotMentioned, isSelfMessage, normalizeMessage, } from './napcat-inbound.js';
3
3
  export { getEndpoint, getNapcatAgentDeps, registerNapcatAgentEndpoint, setNapcatAgentDeps, } from './napcat-agent-deps.js';
4
4
  export { parseOneBotGetMsgResponse } from './onebot-get-msg.js';
@@ -41,11 +41,11 @@ export interface NapcatAgentEndpoint {
41
41
  sendGroupAiRecord(groupId: number, characterId: string, text: string): Promise<unknown>;
42
42
  }
43
43
  export interface NapcatAgentDeps {
44
- getEndpoint: (endpointId: string) => NapcatAgentEndpoint;
44
+ getEndpoint: (endpointKey: string) => NapcatAgentEndpoint;
45
45
  }
46
- export declare function registerNapcatAgentEndpoint(endpointId: string, endpoint: NapcatAgentEndpoint): () => void;
46
+ export declare function registerNapcatAgentEndpoint(endpointKey: string, endpoint: NapcatAgentEndpoint): () => void;
47
47
  /** Optional override used by tests / transitional callers. Pass `null` to clear. */
48
48
  export declare function setNapcatAgentDeps(deps: NapcatAgentDeps | null): void;
49
49
  export declare function getNapcatAgentDeps(): NapcatAgentDeps;
50
50
  /** Convenience for agent/tools (unchanged call sites). */
51
- export declare function getEndpoint(endpointId: string): NapcatAgentEndpoint;
51
+ export declare function getEndpoint(endpointKey: string): NapcatAgentEndpoint;
@@ -4,11 +4,11 @@
4
4
  */
5
5
  const endpoints = new Map();
6
6
  let override = null;
7
- export function registerNapcatAgentEndpoint(endpointId, endpoint) {
8
- endpoints.set(endpointId, endpoint);
7
+ export function registerNapcatAgentEndpoint(endpointKey, endpoint) {
8
+ endpoints.set(endpointKey, endpoint);
9
9
  return () => {
10
- if (endpoints.get(endpointId) === endpoint) {
11
- endpoints.delete(endpointId);
10
+ if (endpoints.get(endpointKey) === endpoint) {
11
+ endpoints.delete(endpointKey);
12
12
  }
13
13
  };
14
14
  }
@@ -16,10 +16,10 @@ export function registerNapcatAgentEndpoint(endpointId, endpoint) {
16
16
  export function setNapcatAgentDeps(deps) {
17
17
  override = deps;
18
18
  }
19
- function lookup(endpointId) {
20
- const registered = endpoints.get(endpointId);
19
+ function lookup(endpointKey) {
20
+ const registered = endpoints.get(endpointKey);
21
21
  if (!registered)
22
- throw new Error(`Endpoint ${endpointId} not found`);
22
+ throw new Error(`Endpoint ${endpointKey} not found`);
23
23
  return registered;
24
24
  }
25
25
  export function getNapcatAgentDeps() {
@@ -28,6 +28,6 @@ export function getNapcatAgentDeps() {
28
28
  return { getEndpoint: lookup };
29
29
  }
30
30
  /** Convenience for agent/tools (unchanged call sites). */
31
- export function getEndpoint(endpointId) {
32
- return getNapcatAgentDeps().getEndpoint(endpointId);
31
+ export function getEndpoint(endpointKey) {
32
+ return getNapcatAgentDeps().getEndpoint(endpointKey);
33
33
  }
package/lib/protocol.d.ts CHANGED
@@ -4,11 +4,12 @@
4
4
  * Canonicalization is owned by gateway/core before endpoint.send.
5
5
  */
6
6
  import { type MediaRef } from '@zhin.js/core';
7
+ import type { ConversationRef } from '@zhin.js/im-contract';
7
8
  /** Transitional legacy endpoint row (`endpoints[]` with `context: napcat`). */
8
9
  export interface NapCatLegacyEndpointRow {
9
10
  readonly context?: string;
10
11
  readonly connection?: 'ws' | 'wss' | 'http';
11
- readonly name?: string;
12
+ readonly id?: string;
12
13
  readonly access_token?: string;
13
14
  readonly url?: string;
14
15
  readonly path?: string;
@@ -21,7 +22,7 @@ export interface NapCatLegacyEndpointRow {
21
22
  /** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
22
23
  export interface NapCatAdapterConfig {
23
24
  readonly connection?: 'ws' | 'wss' | 'http';
24
- readonly name?: string;
25
+ readonly id?: string;
25
26
  readonly access_token?: string;
26
27
  readonly url?: string;
27
28
  readonly path?: string;
@@ -35,7 +36,7 @@ export interface NapCatAdapterConfig {
35
36
  }
36
37
  export interface NapCatConfigBase {
37
38
  readonly context: 'napcat';
38
- readonly name: string;
39
+ readonly id: string;
39
40
  readonly access_token?: string;
40
41
  }
41
42
  /** 正向 WebSocket:应用连 NapCat WS */
@@ -116,8 +117,13 @@ export interface ParsedSendTarget {
116
117
  export declare function resolveNapCatConfig(config?: NapCatAdapterConfig): ResolvedNapCatConfig;
117
118
  export declare function isMessageEvent(ev: NapCatEvent): ev is NapCatMessageEvent;
118
119
  export declare function getChannelId(ev: NapCatEvent): string;
119
- export declare function formatInboundTarget(ev: NapCatEvent): string;
120
- export declare function parseSendTarget(target: string): ParsedSendTarget;
120
+ /**
121
+ * 入站归一化 ConversationRef:群消息 → kind 'group';私聊临时会话
122
+ * (sub_type 'group')→ kind 'private' + 群容器进 `parent`;其余私聊 → 'private'。
123
+ */
124
+ export declare function napcatInboundConversation(endpointKey: string, ev: NapCatEvent): ConversationRef;
125
+ /** 出站:ConversationRef → OneBot 私聊/群聊目标。 */
126
+ export declare function napcatOutboundTarget(conversation: ConversationRef): ParsedSendTarget;
121
127
  export declare function formatInboundContent(ev: NapCatEvent): string;
122
128
  /**
123
129
  * 入站 sender 语义:必须是用户 ID(Runtime Message contract)。
@@ -138,7 +144,7 @@ export declare function mediaRefToOneBotFile(media: MediaRef): string;
138
144
  * 非媒体的 wire 段(at 等)原样透传。
139
145
  */
140
146
  export declare function formatOutboundSegments(payload: unknown): MessageSegment[];
141
- export declare function buildSendAction(target: string, message: MessageSegment[]): {
147
+ export declare function buildSendAction(target: ParsedSendTarget, message: MessageSegment[]): {
142
148
  action: string;
143
149
  params: Record<string, unknown>;
144
150
  };
package/lib/protocol.js CHANGED
@@ -14,8 +14,8 @@ function normalizeConnection(connection) {
14
14
  export function resolveNapCatConfig(config = {}) {
15
15
  const entry = config.endpoints?.find((item) => item.context === 'napcat');
16
16
  const connection = normalizeConnection(config.connection ?? entry?.connection);
17
- const name = (typeof config.name === 'string' && config.name)
18
- || (typeof entry?.name === 'string' && entry.name)
17
+ const id = (typeof config.id === 'string' && config.id)
18
+ || (typeof entry?.id === 'string' && entry.id)
19
19
  || process.env.NAPCAT_BOT_NAME
20
20
  || 'napcat-bot';
21
21
  const access_token = config.access_token ?? entry?.access_token;
@@ -27,7 +27,7 @@ export function resolveNapCatConfig(config = {}) {
27
27
  return {
28
28
  context: 'napcat',
29
29
  connection: 'ws',
30
- name,
30
+ id,
31
31
  access_token,
32
32
  url,
33
33
  reconnect_interval: config.reconnect_interval ?? entry?.reconnect_interval ?? 5000,
@@ -41,7 +41,7 @@ export function resolveNapCatConfig(config = {}) {
41
41
  return {
42
42
  context: 'napcat',
43
43
  connection: 'wss',
44
- name,
44
+ id,
45
45
  access_token,
46
46
  path,
47
47
  heartbeat_interval: config.heartbeat_interval ?? entry?.heartbeat_interval ?? 30_000,
@@ -56,7 +56,7 @@ export function resolveNapCatConfig(config = {}) {
56
56
  return {
57
57
  context: 'napcat',
58
58
  connection: 'http',
59
- name,
59
+ id,
60
60
  access_token,
61
61
  http_url,
62
62
  post_path,
@@ -78,24 +78,32 @@ export function getChannelId(ev) {
78
78
  return String(ev.user_id);
79
79
  return '';
80
80
  }
81
- export function formatInboundTarget(ev) {
82
- const messageType = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private')
83
- ? 'group'
84
- : 'private';
85
- return `${messageType}:${getChannelId(ev)}`;
86
- }
87
- export function parseSendTarget(target) {
88
- const sep = target.indexOf(':');
89
- if (sep <= 0) {
90
- return { message_type: 'private', id: target };
81
+ /**
82
+ * 入站归一化 ConversationRef:群消息 kind 'group';私聊临时会话
83
+ * (sub_type 'group')→ kind 'private' + 群容器进 `parent`;其余私聊 → 'private'。
84
+ */
85
+ export function napcatInboundConversation(endpointKey, ev) {
86
+ const endpoint = { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey };
87
+ const isGroup = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private');
88
+ if (isGroup && ev.group_id != null) {
89
+ return { endpoint, kind: 'group', id: String(ev.group_id) };
91
90
  }
92
- const head = target.slice(0, sep);
93
- const rest = target.slice(sep + 1);
94
- if (head === 'group')
95
- return { message_type: 'group', id: rest };
96
- if (head === 'private')
97
- return { message_type: 'private', id: rest };
98
- return { message_type: 'private', id: target };
91
+ if (ev.sub_type === 'group' && ev.group_id != null) {
92
+ return {
93
+ endpoint,
94
+ kind: 'private',
95
+ id: ev.user_id != null ? String(ev.user_id) : '',
96
+ parent: { kind: 'group', id: String(ev.group_id) },
97
+ };
98
+ }
99
+ return { endpoint, kind: 'private', id: ev.user_id != null ? String(ev.user_id) : '' };
100
+ }
101
+ /** 出站:ConversationRef → OneBot 私聊/群聊目标。 */
102
+ export function napcatOutboundTarget(conversation) {
103
+ return {
104
+ message_type: conversation.kind === 'group' ? 'group' : 'private',
105
+ id: conversation.id,
106
+ };
99
107
  }
100
108
  export function formatInboundContent(ev) {
101
109
  if (typeof ev.raw_message === 'string' && ev.raw_message)
@@ -231,12 +239,11 @@ export function formatOutboundSegments(payload) {
231
239
  return segs.length ? segs : [{ type: 'text', data: { text: '' } }];
232
240
  }
233
241
  export function buildSendAction(target, message) {
234
- const parsed = parseSendTarget(target);
235
- if (parsed.message_type === 'group') {
242
+ if (target.message_type === 'group') {
236
243
  return {
237
244
  action: 'send_group_msg',
238
245
  params: {
239
- group_id: Number(parsed.id) || parsed.id,
246
+ group_id: Number(target.id) || target.id,
240
247
  message,
241
248
  },
242
249
  };
@@ -244,7 +251,7 @@ export function buildSendAction(target, message) {
244
251
  return {
245
252
  action: 'send_private_msg',
246
253
  params: {
247
- user_id: Number(parsed.id) || parsed.id,
254
+ user_id: Number(target.id) || target.id,
248
255
  message,
249
256
  },
250
257
  };
@@ -1,4 +1,4 @@
1
- import { type EndpointInstance, type EndpointManagement } from '@zhin.js/adapter';
1
+ import { type EndpointInstance, type EndpointManagement, type EndpointSendRequest } from '@zhin.js/adapter';
2
2
  import type { MessageGateway } from '@zhin.js/core/runtime';
3
3
  import type { CapabilityId } from '@zhin.js/plugin-runtime';
4
4
  import { type NapCatEvent, type NapCatWsConfig } from './protocol.js';
@@ -17,10 +17,7 @@ export declare class NapCatWsEndpoint implements EndpointInstance {
17
17
  open(): void;
18
18
  close(): void;
19
19
  stop(): Promise<void>;
20
- send({ target, payload }: {
21
- readonly target: string;
22
- readonly payload: unknown;
23
- }): Promise<string>;
20
+ send({ conversation, payload }: EndpointSendRequest): Promise<string>;
24
21
  recallMessage(messageId: string): Promise<void>;
25
22
  callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
26
23
  setTitle(groupId: number, userId: number, title: string, duration?: number): Promise<boolean>;