@zhin.js/adapter-icqq 8.0.2 → 8.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/src/endpoint.ts CHANGED
@@ -1,9 +1,14 @@
1
1
  /**
2
2
  * IcqqIpcEndpoint — lifecycle, outbound, IPC subscribe/admit for ICQQ daemon.
3
3
  */
4
- import type { EndpointControl, EndpointInstance, EndpointManagement } from '@zhin.js/adapter';
4
+ import type {
5
+ EndpointControl,
6
+ EndpointInstance,
7
+ EndpointManagement,
8
+ EndpointSendRequest,
9
+ } from '@zhin.js/adapter';
5
10
  import type { MessageGateway } from '@zhin.js/core/runtime';
6
- import { formatCompact, getLogger } from '@zhin.js/logger';
11
+ import { formatCompact, getAdapterLogger, truncatePreview } from '@zhin.js/logger';
7
12
  import type { CapabilityId } from '@zhin.js/plugin-runtime';
8
13
  import { registerIcqqAgentEndpoint } from './icqq-agent-deps.js';
9
14
  import {
@@ -38,9 +43,9 @@ import {
38
43
  import {
39
44
  Actions,
40
45
  formatInboundContent,
41
- formatInboundTarget,
42
46
  formatOutboundBody,
43
- parseSendTarget,
47
+ icqqInboundConversation,
48
+ icqqOutboundTarget,
44
49
  type IcqqInboundMessage,
45
50
  type IpcEvent,
46
51
  type IpcResponse,
@@ -48,8 +53,6 @@ import {
48
53
  } from './protocol.js';
49
54
  import type { IpcFriendInfo, IpcGroupInfo, IpcMemberInfo, IpcSystemMessage } from './types.js';
50
55
 
51
- const logger = getLogger('icqq');
52
-
53
56
  /** Minimal IPC surface used by the endpoint (real IpcClient or test mock). */
54
57
  export interface IcqqIpcTransport {
55
58
  request(action: string, params?: Record<string, unknown>): Promise<IpcResponse>;
@@ -84,6 +87,8 @@ export interface IcqqEndpointOptions {
84
87
  }
85
88
 
86
89
  export class IcqqIpcEndpoint implements EndpointInstance {
90
+ readonly #logger!: ReturnType<typeof getAdapterLogger>;
91
+
87
92
  readonly #options: IcqqEndpointOptions;
88
93
  readonly #createIpc: CreateIcqqIpc;
89
94
  readonly name: string;
@@ -126,8 +131,9 @@ export class IcqqIpcEndpoint implements EndpointInstance {
126
131
  #reconnectRunning = false;
127
132
 
128
133
  constructor(options: IcqqEndpointOptions) {
134
+ this.#logger = getAdapterLogger('icqq', options.config.id);
129
135
  this.#options = options;
130
- this.name = options.config.name;
136
+ this.name = options.config.id;
131
137
  this.#createIpc = options.createIpc ?? defaultCreateIpc;
132
138
  }
133
139
 
@@ -145,18 +151,14 @@ export class IcqqIpcEndpoint implements EndpointInstance {
145
151
  try {
146
152
  await this.#bindIpcSession();
147
153
  this.#unregisterAgent = registerIcqqAgentEndpoint(this.name, this);
148
- logger.info(formatCompact({
149
- op: 'connect',
150
- endpoint: this.name,
151
- mode: this.#options.config.rpc ? 'rpc' : 'ipc',
152
- friends: this.friends.size,
153
- groups: this.groups.size,
154
- }));
154
+ this.#logger.info(
155
+ `connected (${this.#options.config.rpc ? 'rpc' : 'ipc'}) | friends: ${this.friends.size} | groups: ${this.groups.size}`,
156
+ );
155
157
  } catch (error) {
156
158
  await this.stop();
157
159
  // Startup connect failures are surfaced once (with stack) by AdapterIndex;
158
160
  // keep this at debug to avoid a duplicate error-level log.
159
- logger.debug(`Failed to connect ICQQ IPC: ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
161
+ this.#logger.debug(`Failed to connect ICQQ IPC: ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
160
162
  throw error;
161
163
  }
162
164
  }
@@ -195,10 +197,9 @@ export class IcqqIpcEndpoint implements EndpointInstance {
195
197
  const jitter = Math.floor(Math.random() * 400);
196
198
  const delayMs = base + jitter;
197
199
  // 首次断开 WARN,后续重试静默为 DEBUG,避免刷屏
198
- const disconnectLog = attempt === 0 ? logger.warn.bind(logger) : logger.debug.bind(logger);
200
+ const disconnectLog = attempt === 0 ? this.#logger.warn.bind(this.#logger) : this.#logger.debug.bind(this.#logger);
199
201
  disconnectLog(formatCompact({
200
202
  op: 'disconnect',
201
- endpoint: this.name,
202
203
  ok: false,
203
204
  delay_ms: delayMs,
204
205
  attempt: attempt + 1,
@@ -207,17 +208,13 @@ export class IcqqIpcEndpoint implements EndpointInstance {
207
208
  if (this.#intentionalDisconnect) break;
208
209
  try {
209
210
  await this.#bindIpcSession();
210
- logger.info(formatCompact({
211
- op: 'reconnect',
212
- endpoint: this.name,
213
- ok: true,
214
- attempts: attempt + 1,
215
- friends: this.friends.size,
216
- groups: this.groups.size,
217
- }));
211
+ this.#logger.info(
212
+ `reconnected after ${attempt + 1} attempt(s)`
213
+ + ` | friends: ${this.friends.size} | groups: ${this.groups.size}`,
214
+ );
218
215
  break;
219
216
  } catch (error) {
220
- const retryLog = attempt === 0 ? logger.warn.bind(logger) : logger.debug.bind(logger);
217
+ const retryLog = attempt === 0 ? this.#logger.warn.bind(this.#logger) : this.#logger.debug.bind(this.#logger);
221
218
  retryLog(formatCompact({
222
219
  op: 'reconnect',
223
220
  endpoint: this.name,
@@ -262,10 +259,10 @@ export class IcqqIpcEndpoint implements EndpointInstance {
262
259
  // 置空 ipc:start 前 / stop 后的 request() 走防御性报错而非 TypeError
263
260
  this.ipc = undefined as unknown as IcqqIpcTransport;
264
261
  this.#started = false;
265
- logger.debug(formatCompact({ op: 'disconnect', endpoint: this.name }));
262
+ this.#logger.debug(formatCompact({ op: 'disconnect' }));
266
263
  }
267
264
 
268
- async send({ target, payload }: { readonly target: string; readonly payload: unknown }): Promise<string> {
265
+ async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
269
266
  if (!this.ipc) {
270
267
  throw new Error(`icqq endpoint ${this.name} 未连接(IPC 未初始化或已停止),无法发送消息`);
271
268
  }
@@ -274,7 +271,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
274
271
  ? materializeOutboundBase64(payload, mediaMode)
275
272
  : payload;
276
273
  const message = formatOutboundBody(content);
277
- const parsed = parseSendTarget(target);
274
+ const parsed = icqqOutboundTarget(conversation);
278
275
  let action: string;
279
276
  let params: Record<string, unknown>;
280
277
  switch (parsed.kind) {
@@ -305,17 +302,17 @@ export class IcqqIpcEndpoint implements EndpointInstance {
305
302
  }
306
303
  const resp = await this.ipc.request(action, params);
307
304
  if (!resp.ok) {
305
+ this.#logger.warn(
306
+ `send failed ${conversation.kind}:${conversation.id} | ${resp.error} | ${truncatePreview(typeof message === 'string' ? message : String(message), 80)}`,
307
+ );
308
308
  throw new Error(`发送消息失败: ${resp.error}`);
309
309
  }
310
310
  const messageId = String(
311
311
  (resp.data as { message_id?: unknown } | undefined)?.message_id ?? `sent_${Date.now()}`,
312
312
  );
313
- logger.debug(formatCompact({
314
- op: 'icqq_send',
315
- endpoint: this.name,
316
- target,
317
- messageId,
318
- }));
313
+ this.#logger.info(
314
+ `send ${conversation.kind}:${conversation.id} | id: ${messageId} | ${truncatePreview(typeof message === 'string' ? message : String(message), 80)}`,
315
+ );
319
316
  return messageId;
320
317
  }
321
318
 
@@ -348,7 +345,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
348
345
  id: emojiId,
349
346
  });
350
347
  if (!resp.ok) {
351
- logger.warn(formatCompact({
348
+ this.#logger.warn(formatCompact({
352
349
  op: 'add_reaction',
353
350
  endpoint: this.name,
354
351
  message_id: messageId,
@@ -359,7 +356,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
359
356
  }));
360
357
  return null;
361
358
  }
362
- logger.debug(formatCompact({
359
+ this.#logger.debug(formatCompact({
363
360
  op: 'add_reaction',
364
361
  endpoint: this.name,
365
362
  message_id: messageId,
@@ -369,7 +366,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
369
366
  }));
370
367
  return emojiId;
371
368
  } catch (error) {
372
- logger.warn(formatCompact({
369
+ this.#logger.warn(formatCompact({
373
370
  op: 'add_reaction',
374
371
  endpoint: this.name,
375
372
  message_id: messageId,
@@ -390,7 +387,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
390
387
  id: emojiId,
391
388
  });
392
389
  if (!resp.ok) {
393
- logger.warn(formatCompact({
390
+ this.#logger.warn(formatCompact({
394
391
  op: 'remove_reaction',
395
392
  endpoint: this.name,
396
393
  message_id: messageId,
@@ -401,7 +398,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
401
398
  }));
402
399
  return;
403
400
  }
404
- logger.debug(formatCompact({
401
+ this.#logger.debug(formatCompact({
405
402
  op: 'remove_reaction',
406
403
  endpoint: this.name,
407
404
  message_id: messageId,
@@ -410,7 +407,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
410
407
  ok: true,
411
408
  }));
412
409
  } catch (error) {
413
- logger.warn(formatCompact({
410
+ this.#logger.warn(formatCompact({
414
411
  op: 'remove_reaction',
415
412
  endpoint: this.name,
416
413
  message_id: messageId,
@@ -427,7 +424,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
427
424
  try {
428
425
  const resp = await this.request(Actions.RECALL_MSG, { message_id: messageId });
429
426
  if (!resp.ok) {
430
- logger.warn(formatCompact({
427
+ this.#logger.warn(formatCompact({
431
428
  op: 'recall_message',
432
429
  endpoint: this.name,
433
430
  message_id: messageId,
@@ -436,14 +433,14 @@ export class IcqqIpcEndpoint implements EndpointInstance {
436
433
  }));
437
434
  return;
438
435
  }
439
- logger.debug(formatCompact({
436
+ this.#logger.debug(formatCompact({
440
437
  op: 'recall_message',
441
438
  endpoint: this.name,
442
439
  message_id: messageId,
443
440
  ok: true,
444
441
  }));
445
442
  } catch (error) {
446
- logger.warn(formatCompact({
443
+ this.#logger.warn(formatCompact({
447
444
  op: 'recall_message',
448
445
  endpoint: this.name,
449
446
  message_id: messageId,
@@ -630,13 +627,14 @@ export class IcqqIpcEndpoint implements EndpointInstance {
630
627
 
631
628
  /** Test / internal: admit when open. */
632
629
  admit(msg: IcqqInboundMessage): void {
630
+ const conversation = msg.conversation;
633
631
  if (!this.#open) {
634
- logger.debug(formatCompact({
632
+ this.#logger.debug(formatCompact({
635
633
  op: 'icqq_inbound_skip',
636
634
  reason: 'endpoint_closed',
637
635
  endpoint: this.name,
638
636
  id: msg.id,
639
- target: msg.target,
637
+ target: `${conversation.kind}:${conversation.id}`,
640
638
  }));
641
639
  return;
642
640
  }
@@ -646,34 +644,33 @@ export class IcqqIpcEndpoint implements EndpointInstance {
646
644
  content: msg.segments,
647
645
  rawMessage: msg.content,
648
646
  });
649
- logger.debug(formatCompact({
650
- op: 'icqq_inbound_admit',
651
- endpoint: this.name,
652
- id: msg.id,
653
- target: msg.target,
654
- sender: msg.sender,
655
- channelType: msg.channelType,
656
- mentioned: mentioned || undefined,
657
- preview: msg.content.slice(0, 80),
658
- segments: summarizeSegmentTypes(msg.segments),
659
- }));
647
+ this.#logger.info(
648
+ `recv ${conversation.kind}:${conversation.id}`
649
+ + (msg.sender ? ` from ${msg.sender.name ?? msg.sender.id}` : '')
650
+ + (mentioned ? ' (mentioned)' : '')
651
+ + ` | ${truncatePreview(msg.content, 80)}`,
652
+ );
653
+ const quoteId = msg.metadata?.quote_id;
654
+ const { quote_id: _dropQuoteId, ...restMetadata } = msg.metadata ?? {};
660
655
  void this.#options.gateway.receive({
661
- adapter: this.#options.id,
662
- target: msg.target,
656
+ conversation,
657
+ message: { conversation, id: msg.id },
663
658
  content: msg.content,
664
659
  ...(msg.segments ? { segments: msg.segments } : {}),
665
660
  sender: msg.sender,
666
- id: msg.id,
661
+ endpointId: this.name,
662
+ ...(mentioned ? { mentioned: true } : {}),
663
+ ...(quoteId ? { replyTo: { id: String(quoteId) } } : {}),
667
664
  metadata: Object.freeze({
668
- endpoint: this.name,
669
665
  channelType: msg.channelType,
670
- ...msg.metadata,
671
- ...(mentioned ? { mentioned: true } : {}),
666
+ ...restMetadata,
672
667
  }),
673
668
  }).catch((err) => {
674
- logger.warn(formatCompact({
675
- op: 'icqq_gateway_receive_failed',
676
- target: msg.target,
669
+ this.#logger.warn(formatCompact({
670
+ op: 'recv',
671
+ endpoint: this.name,
672
+ target: `${conversation.kind}:${conversation.id}`,
673
+ ok: false,
677
674
  error: err instanceof Error ? err.message : String(err),
678
675
  }));
679
676
  });
@@ -716,7 +713,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
716
713
  if (!isIcqqMessagePostType(payload)) return;
717
714
  const data = payload as IcqqIpcMessageEvent;
718
715
  if (shouldSkipSelfInboundMessage(data)) {
719
- logger.debug(formatCompact({
716
+ this.#logger.debug(formatCompact({
720
717
  op: 'icqq_inbound_skip',
721
718
  reason: 'self',
722
719
  endpoint: this.name,
@@ -727,7 +724,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
727
724
  }
728
725
  const normalized = normalizeIcqqInboundMessage(data);
729
726
  if (!normalized) {
730
- logger.debug(formatCompact({
727
+ this.#logger.debug(formatCompact({
731
728
  op: 'icqq_inbound_skip',
732
729
  reason: 'normalize_failed',
733
730
  endpoint: this.name,
@@ -737,7 +734,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
737
734
  return;
738
735
  }
739
736
  if (!this.#inboundDeduper.shouldProcess(normalized.messageId)) {
740
- logger.debug(formatCompact({
737
+ this.#logger.debug(formatCompact({
741
738
  op: 'icqq_inbound_skip',
742
739
  reason: 'dedupe',
743
740
  endpoint: this.name,
@@ -747,14 +744,18 @@ export class IcqqIpcEndpoint implements EndpointInstance {
747
744
  }
748
745
  this.admit({
749
746
  id: normalized.messageId,
750
- target: formatInboundTarget({
747
+ conversation: icqqInboundConversation(String(this.#options.id), {
751
748
  channelType: normalized.channelType,
752
749
  channelId: normalized.channelId,
753
750
  channelParentGroupId: normalized.channelParentGroupId,
754
751
  }),
755
752
  content: formatInboundContent(normalized.rawMessage),
756
753
  segments: normalized.content,
757
- sender: normalized.userId,
754
+ sender: {
755
+ id: normalized.userId,
756
+ name: normalized.nickname || undefined,
757
+ ...(normalized.senderRole ? { roles: [normalized.senderRole] } : {}),
758
+ },
758
759
  channelType: normalized.channelType,
759
760
  metadata: buildIcqqQuoteMetadata(data, {
760
761
  nickname: normalized.nickname,
@@ -770,7 +771,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
770
771
  payload as Parameters<typeof normalizeIcqqGuildInboundMessage>[0],
771
772
  );
772
773
  if (!normalized) {
773
- logger.debug(formatCompact({
774
+ this.#logger.debug(formatCompact({
774
775
  op: 'icqq_inbound_skip',
775
776
  reason: 'guild_normalize_failed',
776
777
  endpoint: this.name,
@@ -779,7 +780,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
779
780
  }
780
781
  this.#guildCatalog.upsertFromInbound(normalized.raw);
781
782
  if (!this.#inboundDeduper.shouldProcess(`guild:${normalized.messageId}`)) {
782
- logger.debug(formatCompact({
783
+ this.#logger.debug(formatCompact({
783
784
  op: 'icqq_inbound_skip',
784
785
  reason: 'dedupe',
785
786
  endpoint: this.name,
@@ -789,14 +790,14 @@ export class IcqqIpcEndpoint implements EndpointInstance {
789
790
  }
790
791
  this.admit({
791
792
  id: normalized.messageId,
792
- target: formatInboundTarget({
793
+ conversation: icqqInboundConversation(String(this.#options.id), {
793
794
  channelType: 'channel',
794
795
  channelId: normalized.channelId,
795
796
  guildId: normalized.guildId,
796
797
  }),
797
798
  content: formatInboundContent(normalized.rawMessage),
798
799
  segments: normalized.content,
799
- sender: normalized.userId,
800
+ sender: { id: normalized.userId, name: normalized.nickname || undefined },
800
801
  channelType: 'channel',
801
802
  metadata: {
802
803
  guildId: normalized.guildId,
@@ -806,9 +807,9 @@ export class IcqqIpcEndpoint implements EndpointInstance {
806
807
  }
807
808
 
808
809
  /** 收件箱行公共前缀:adapter 槽 localName + endpoint live 名(uin)。 */
809
- #inboxBase(): { adapter: string; endpointId: string } {
810
+ #inboxBase(): { adapter: string; endpointKey: string } {
810
811
  const id = String(this.#options.id);
811
- return { adapter: id.split('\0').pop() ?? id, endpointId: this.name };
812
+ return { adapter: id.split('\0').pop() ?? id, endpointKey: this.name };
812
813
  }
813
814
 
814
815
  #recordInboxRequest(payload: Record<string, unknown>): void {
@@ -859,7 +860,7 @@ export class IcqqIpcEndpoint implements EndpointInstance {
859
860
  hooks.publish?.('endpoint:request', row);
860
861
  }
861
862
  } catch (error) {
862
- logger.debug(formatCompact({
863
+ this.#logger.debug(formatCompact({
863
864
  op: 'inbox_pull_system_msg',
864
865
  endpoint: this.name,
865
866
  error: error instanceof Error ? error.message : String(error),
@@ -908,23 +909,8 @@ function toNumericId(value: number | string, label: string): number {
908
909
  return n;
909
910
  }
910
911
 
911
- function summarizeSegmentTypes(
912
- segments: readonly { readonly type?: unknown }[] | undefined,
913
- ): string | undefined {
914
- if (!segments?.length) return undefined;
915
- return segments
916
- .map((segment) => {
917
- if (typeof segment.type === 'string') return segment.type;
918
- if (segment.type && typeof segment.type === 'object' && 'name' in segment.type) {
919
- return String((segment.type as { name: unknown }).name);
920
- }
921
- return '?';
922
- })
923
- .join(',');
924
- }
925
-
926
912
  async function defaultCreateIpc(config: ResolvedIcqqConfig): Promise<IcqqIpcTransport> {
927
- const uin = Number(config.name);
913
+ const uin = Number(config.id);
928
914
  if (config.rpc) {
929
915
  return IpcClient.connectRpc(config.rpc);
930
916
  }
@@ -18,7 +18,7 @@ export interface IcqqAgentEndpoint {
18
18
  }
19
19
 
20
20
  export interface IcqqAgentDeps {
21
- getEndpoint: (endpointId: string) => IcqqAgentEndpoint;
21
+ getEndpoint: (endpointKey: string) => IcqqAgentEndpoint;
22
22
  getAdapter?: () => { getEndpoint: (id: string) => IcqqAgentEndpoint };
23
23
  }
24
24
 
@@ -26,13 +26,13 @@ const endpoints = new Map<string, IcqqAgentEndpoint>();
26
26
  let override: IcqqAgentDeps | null = null;
27
27
 
28
28
  export function registerIcqqAgentEndpoint(
29
- endpointId: string,
29
+ endpointKey: string,
30
30
  endpoint: IcqqAgentEndpoint,
31
31
  ): () => void {
32
- endpoints.set(endpointId, endpoint);
32
+ endpoints.set(endpointKey, endpoint);
33
33
  return () => {
34
- if (endpoints.get(endpointId) === endpoint) {
35
- endpoints.delete(endpointId);
34
+ if (endpoints.get(endpointKey) === endpoint) {
35
+ endpoints.delete(endpointKey);
36
36
  }
37
37
  };
38
38
  }
@@ -42,9 +42,9 @@ export function setIcqqAgentDeps(deps: IcqqAgentDeps | null): void {
42
42
  override = deps;
43
43
  }
44
44
 
45
- function lookup(endpointId: string): IcqqAgentEndpoint {
46
- const registered = endpoints.get(endpointId);
47
- if (!registered) throw new Error(`Endpoint ${endpointId} 不存在`);
45
+ function lookup(endpointKey: string): IcqqAgentEndpoint {
46
+ const registered = endpoints.get(endpointKey);
47
+ if (!registered) throw new Error(`Endpoint ${endpointKey} 不存在`);
48
48
  return registered;
49
49
  }
50
50
 
@@ -4,7 +4,7 @@
4
4
  * ICQQ 的凭据由外部守护进程(@icqqjs/cli)按账号持有(~/.icqq/<uin>/),
5
5
  * 其 IPC/RPC 协议是「按 uin 连接 + auth + 账号级 action」,没有 add-account /
6
6
  * 触发 login 的 action——扫码登录只能经 `icqq login <uin>` CLI 完成。
7
- * 因此 add 不走 kv 凭据录入,而是 bindFlow:校验 uin、把 { name: '<uin>' }
7
+ * 因此 add 不走 kv 凭据录入,而是 bindFlow:校验 uin、把 { id: '<uin>' }
8
8
  * 追加到 plugins.icqq.endpoints,并引导用户先完成守护进程登录。
9
9
  */
10
10
  import { addEndpointToConfig, createEndpointCommands } from '@zhin.js/adapter';
@@ -17,18 +17,18 @@ export const icqqEndpointCommands = createEndpointCommands({
17
17
  running: (use) => use(icqqRuntimeStateToken).endpoints.values(),
18
18
  describeEntry: (entry) => (entry.rpc ? 'rpc(远程守护进程)' : 'ipc(本地守护进程)'),
19
19
  addDescription: '登记 ICQQ endpoint(uin 需先经 icqq login 完成扫码登录;重启 zhin 生效)',
20
- bindFlow: ({ name }) => {
21
- if (!name) {
20
+ bindFlow: ({ id }) => {
21
+ if (!id) {
22
22
  return '用法:icqq.endpoint add <uin>(uin 为纯数字 QQ 号,且需先执行 icqq login <uin> 完成扫码登录)';
23
23
  }
24
- if (!/^\d+$/.test(name)) {
24
+ if (!/^\d+$/.test(id)) {
25
25
  return 'icqq endpoint 名必须是纯数字 QQ 号(uin)';
26
26
  }
27
27
  try {
28
- const filePath = addEndpointToConfig('icqq', { name });
28
+ const filePath = addEndpointToConfig('icqq', { id });
29
29
  return (
30
- `✅ endpoint「${name}」已追加到 ${filePath} 的 plugins.icqq.endpoints。\n` +
31
- `⚠️ 请确保已执行 icqq login ${name} 启动守护进程并完成扫码登录;重启 zhin 后生效。`
30
+ `✅ endpoint「${id}」已追加到 ${filePath} 的 plugins.icqq.endpoints。\n` +
31
+ `⚠️ 请确保已执行 icqq login ${id} 启动守护进程并完成扫码登录;重启 zhin 后生效。`
32
32
  );
33
33
  } catch (error) {
34
34
  return `添加失败:${error instanceof Error ? error.message : String(error)}`;
package/src/icqq-inbox.ts CHANGED
@@ -11,7 +11,7 @@ import type { IpcSystemMessage } from './types.js';
11
11
  /** 行级公共前缀:adapter 槽 localName + endpoint live 名(uin)。 */
12
12
  export interface IcqqInboxBase {
13
13
  readonly adapter: string;
14
- readonly endpointId: string;
14
+ readonly endpointKey: string;
15
15
  }
16
16
 
17
17
  /** post_type=request / request.* 判定(OneBot 事件壳)。 */
@@ -46,7 +46,7 @@ export function buildIcqqInboxRequestRow(
46
46
  const isGroup = requestType === 'group' || groupId != null;
47
47
  return {
48
48
  adapter: base.adapter,
49
- endpoint_id: base.endpointId,
49
+ endpoint_id: base.endpointKey,
50
50
  platform_request_id: platformRequestId,
51
51
  type: isGroup ? 'group' : (requestType ?? 'friend'),
52
52
  scene_type: isGroup ? 'group' : null,
@@ -85,7 +85,7 @@ export function buildIcqqInboxNoticeRow(
85
85
  const targetId = userId != null && String(userId) !== String(actorId ?? '') ? userId : undefined;
86
86
  return {
87
87
  adapter: base.adapter,
88
- endpoint_id: base.endpointId,
88
+ endpoint_id: base.endpointKey,
89
89
  platform_notice_id: platformNoticeId,
90
90
  type: noticeType,
91
91
  scene_type: groupId != null ? 'group' : null,
@@ -117,7 +117,7 @@ export function buildIcqqSystemRequestRow(
117
117
  if (!platformRequestId) return null;
118
118
  return {
119
119
  adapter: base.adapter,
120
- endpoint_id: base.endpointId,
120
+ endpoint_id: base.endpointKey,
121
121
  platform_request_id: platformRequestId,
122
122
  type: kind,
123
123
  scene_type: kind === 'group' ? 'group' : null,
package/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export {
2
2
  Actions,
3
3
  formatInboundContent,
4
- formatInboundTarget,
5
4
  formatOutboundBody,
6
- parseSendTarget,
5
+ icqqInboundConversation,
6
+ icqqOutboundTarget,
7
7
  resolveIcqqConfig,
8
8
  type IcqqAdapterConfig,
9
9
  type IcqqInboundMessage,
package/src/ipc-client.ts CHANGED
@@ -366,7 +366,7 @@ export class IpcClient {
366
366
  }
367
367
 
368
368
  /**
369
- * @deprecated 兼容旧调用方式:服务端已自动推送事件,type/id 过滤在客户端完成。
369
+ * 订阅 daemon 推送事件:服务端自动推送全部事件,type/id 过滤在客户端完成。
370
370
  * @returns 订阅句柄,包含 unsubscribe() 方法
371
371
  */
372
372
  subscribe(