@zhin.js/adapter-icqq 8.0.3 → 8.0.6

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,88 @@
1
1
  # @zhin.js/adapter-icqq
2
2
 
3
+ ## 8.0.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [2d0a622]
8
+ - @zhin.js/command@1.0.10
9
+ - @zhin.js/adapter@1.1.7
10
+ - @zhin.js/core@1.5.5
11
+ - @zhin.js/agent@1.1.6
12
+ - zhin.js@6.0.5
13
+
14
+ ## 8.0.5
15
+
16
+ ### Patch Changes
17
+
18
+ - 36c7400: Replace `AgentPromptBuildContext.commMessage` with an authenticated platform projection and make Agent prompt assembly consume canonical Turn identity. Platform contributors and prompt hooks no longer receive a classic IM `Message`.
19
+
20
+ Remove the unused Message field and active-context escape hatch from PromptController; turn scheduling is keyed only by canonical session identity.
21
+
22
+ - Updated dependencies [6f9c366]
23
+ - Updated dependencies [373a56b]
24
+ - Updated dependencies [0de46a8]
25
+ - Updated dependencies [c106ecc]
26
+ - Updated dependencies [ca92e03]
27
+ - Updated dependencies [b0f37ae]
28
+ - Updated dependencies [ba08a2f]
29
+ - Updated dependencies [b08f7fe]
30
+ - Updated dependencies [daffd4c]
31
+ - Updated dependencies [36c7400]
32
+ - Updated dependencies [a9fa72e]
33
+ - Updated dependencies [c8de3ef]
34
+ - Updated dependencies [60f0fc8]
35
+ - Updated dependencies [574c990]
36
+ - Updated dependencies [d096f16]
37
+ - Updated dependencies [3f29623]
38
+ - Updated dependencies [2916852]
39
+ - Updated dependencies [d047869]
40
+ - Updated dependencies [162fa34]
41
+ - Updated dependencies [e62561e]
42
+ - Updated dependencies [3eeeb46]
43
+ - Updated dependencies [85d0f82]
44
+ - Updated dependencies [61bfc1c]
45
+ - Updated dependencies [04bad47]
46
+ - Updated dependencies [e40b048]
47
+ - Updated dependencies [5a5b1bb]
48
+ - Updated dependencies [f1708c3]
49
+ - Updated dependencies [d254a81]
50
+ - Updated dependencies [7123c47]
51
+ - Updated dependencies [05befc1]
52
+ - Updated dependencies [0663b6a]
53
+ - Updated dependencies [f28f9b3]
54
+ - Updated dependencies [9f340f7]
55
+ - Updated dependencies [e53444f]
56
+ - Updated dependencies [5eedd26]
57
+ - Updated dependencies [92b0dd7]
58
+ - Updated dependencies [f919b6f]
59
+ - Updated dependencies [098e411]
60
+ - Updated dependencies [e1b7c01]
61
+ - Updated dependencies [9b94f87]
62
+ - Updated dependencies [a7df753]
63
+ - @zhin.js/agent@1.1.5
64
+ - @zhin.js/im-contract@1.0.3
65
+ - @zhin.js/adapter@1.1.7
66
+ - @zhin.js/plugin-runtime@1.1.5
67
+ - @zhin.js/command@1.0.9
68
+ - @zhin.js/core@1.5.4
69
+ - zhin.js@6.0.4
70
+
71
+ ## 8.0.4
72
+
73
+ ### Patch Changes
74
+
75
+ - f8c7a54: fix: im
76
+ - Updated dependencies [f8c7a54]
77
+ - @zhin.js/logger@1.0.76
78
+ - @zhin.js/adapter@1.1.6
79
+ - @zhin.js/agent@1.1.4
80
+ - @zhin.js/command@1.0.8
81
+ - @zhin.js/core@1.5.3
82
+ - @zhin.js/im-contract@1.0.2
83
+ - @zhin.js/plugin-runtime@1.1.4
84
+ - zhin.js@6.0.3
85
+
3
86
  ## 8.0.3
4
87
 
5
88
  ### Patch Changes
package/adapters/icqq.js CHANGED
@@ -26,8 +26,8 @@ export default defineAdapter({
26
26
  // Console loginAssist + host-router routes deferred.
27
27
  const config = resolveIcqqConfig(context.config);
28
28
  // 注册到插件运行时状态(icqq.endpoint list 的"运行中"数据源)
29
- context.use(icqqRuntimeStateToken).endpoints.set(config.name, {
30
- name: config.name,
29
+ context.use(icqqRuntimeStateToken).endpoints.set(config.id, {
30
+ id: config.id,
31
31
  mode: config.rpc ? 'rpc' : 'ipc',
32
32
  });
33
33
  const inbox = resolveInboxHooks(context);
package/adapters/icqq.ts CHANGED
@@ -42,8 +42,8 @@ export default defineAdapter<IcqqAdapterConfig>({
42
42
  // Console loginAssist + host-router routes deferred.
43
43
  const config = resolveIcqqConfig(context.config);
44
44
  // 注册到插件运行时状态(icqq.endpoint list 的"运行中"数据源)
45
- context.use(icqqRuntimeStateToken).endpoints.set(config.name, {
46
- name: config.name,
45
+ context.use(icqqRuntimeStateToken).endpoints.set(config.id, {
46
+ id: config.id,
47
47
  mode: config.rpc ? 'rpc' : 'ipc',
48
48
  });
49
49
  const inbox = resolveInboxHooks(context);
package/lib/endpoint.js CHANGED
@@ -1,4 +1,4 @@
1
- import { formatCompact, getLogger } from '@zhin.js/logger';
1
+ import { formatCompact, getAdapterLogger, truncatePreview } from '@zhin.js/logger';
2
2
  import { registerIcqqAgentEndpoint } from './icqq-agent-deps.js';
3
3
  import { InboundMessageDeduper, findIcqqNestedMessageSource, isIcqqBotMentioned, isIcqqMessagePostType, normalizeIcqqInboundMessage, quotedPayloadFromIcqqSource, resolveIcqqQuoteIdFromEvent, shouldSkipSelfInboundMessage, unwrapIcqqIpcEventPayload, } from './icqq-inbound.js';
4
4
  import { buildIcqqInboxNoticeRow, buildIcqqInboxRequestRow, buildIcqqSystemRequestRow, isIcqqNoticePayload, isIcqqRequestPayload, } from './icqq-inbox.js';
@@ -6,8 +6,8 @@ import { IcqqGuildCatalog, isIcqqGuildIpcEvent, normalizeIcqqGuildInboundMessage
6
6
  import { IpcClient } from './ipc-client.js';
7
7
  import { materializeOutboundBase64, resolveIcqqOutboundMediaMode, } from './outbound-media.js';
8
8
  import { Actions, formatInboundContent, formatOutboundBody, icqqInboundConversation, icqqOutboundTarget, } from './protocol.js';
9
- const logger = getLogger('icqq');
10
9
  export class IcqqIpcEndpoint {
10
+ #logger;
11
11
  #options;
12
12
  #createIpc;
13
13
  name;
@@ -48,8 +48,9 @@ export class IcqqIpcEndpoint {
48
48
  /** 是否已有重连循环在跑(避免多次 schedule 叠套) */
49
49
  #reconnectRunning = false;
50
50
  constructor(options) {
51
+ this.#logger = getAdapterLogger('icqq', options.config.id);
51
52
  this.#options = options;
52
- this.name = options.config.name;
53
+ this.name = options.config.id;
53
54
  this.#createIpc = options.createIpc ?? defaultCreateIpc;
54
55
  }
55
56
  async request(action, params) {
@@ -66,19 +67,13 @@ export class IcqqIpcEndpoint {
66
67
  try {
67
68
  await this.#bindIpcSession();
68
69
  this.#unregisterAgent = registerIcqqAgentEndpoint(this.name, this);
69
- logger.info(formatCompact({
70
- op: 'connect',
71
- endpoint: this.name,
72
- mode: this.#options.config.rpc ? 'rpc' : 'ipc',
73
- friends: this.friends.size,
74
- groups: this.groups.size,
75
- }));
70
+ this.#logger.info(`connected (${this.#options.config.rpc ? 'rpc' : 'ipc'}) | friends: ${this.friends.size} | groups: ${this.groups.size}`);
76
71
  }
77
72
  catch (error) {
78
73
  await this.stop();
79
74
  // Startup connect failures are surfaced once (with stack) by AdapterIndex;
80
75
  // keep this at debug to avoid a duplicate error-level log.
81
- logger.debug(`Failed to connect ICQQ IPC: ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
76
+ this.#logger.debug(`Failed to connect ICQQ IPC: ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
82
77
  throw error;
83
78
  }
84
79
  }
@@ -117,10 +112,9 @@ export class IcqqIpcEndpoint {
117
112
  const jitter = Math.floor(Math.random() * 400);
118
113
  const delayMs = base + jitter;
119
114
  // 首次断开 WARN,后续重试静默为 DEBUG,避免刷屏
120
- const disconnectLog = attempt === 0 ? logger.warn.bind(logger) : logger.debug.bind(logger);
115
+ const disconnectLog = attempt === 0 ? this.#logger.warn.bind(this.#logger) : this.#logger.debug.bind(this.#logger);
121
116
  disconnectLog(formatCompact({
122
117
  op: 'disconnect',
123
- endpoint: this.name,
124
118
  ok: false,
125
119
  delay_ms: delayMs,
126
120
  attempt: attempt + 1,
@@ -130,18 +124,12 @@ export class IcqqIpcEndpoint {
130
124
  break;
131
125
  try {
132
126
  await this.#bindIpcSession();
133
- logger.info(formatCompact({
134
- op: 'reconnect',
135
- endpoint: this.name,
136
- ok: true,
137
- attempts: attempt + 1,
138
- friends: this.friends.size,
139
- groups: this.groups.size,
140
- }));
127
+ this.#logger.info(`reconnected after ${attempt + 1} attempt(s)`
128
+ + ` | friends: ${this.friends.size} | groups: ${this.groups.size}`);
141
129
  break;
142
130
  }
143
131
  catch (error) {
144
- const retryLog = attempt === 0 ? logger.warn.bind(logger) : logger.debug.bind(logger);
132
+ const retryLog = attempt === 0 ? this.#logger.warn.bind(this.#logger) : this.#logger.debug.bind(this.#logger);
145
133
  retryLog(formatCompact({
146
134
  op: 'reconnect',
147
135
  endpoint: this.name,
@@ -185,7 +173,7 @@ export class IcqqIpcEndpoint {
185
173
  // 置空 ipc:start 前 / stop 后的 request() 走防御性报错而非 TypeError
186
174
  this.ipc = undefined;
187
175
  this.#started = false;
188
- logger.debug(formatCompact({ op: 'disconnect', endpoint: this.name }));
176
+ this.#logger.debug(formatCompact({ op: 'disconnect' }));
189
177
  }
190
178
  async send({ conversation, payload }) {
191
179
  if (!this.ipc) {
@@ -227,15 +215,11 @@ export class IcqqIpcEndpoint {
227
215
  }
228
216
  const resp = await this.ipc.request(action, params);
229
217
  if (!resp.ok) {
218
+ this.#logger.warn(`send failed ${conversation.kind}:${conversation.id} | ${resp.error} | ${truncatePreview(typeof message === 'string' ? message : String(message), 80)}`);
230
219
  throw new Error(`发送消息失败: ${resp.error}`);
231
220
  }
232
221
  const messageId = String(resp.data?.message_id ?? `sent_${Date.now()}`);
233
- logger.debug(formatCompact({
234
- op: 'icqq_send',
235
- endpoint: this.name,
236
- target: `${conversation.kind}:${conversation.id}`,
237
- messageId,
238
- }));
222
+ this.#logger.info(`send ${conversation.kind}:${conversation.id} | id: ${messageId} | ${truncatePreview(typeof message === 'string' ? message : String(message), 80)}`);
239
223
  return messageId;
240
224
  }
241
225
  // ── 消息回应(activity-feedback / typing reaction)────────────────────
@@ -265,7 +249,7 @@ export class IcqqIpcEndpoint {
265
249
  id: emojiId,
266
250
  });
267
251
  if (!resp.ok) {
268
- logger.warn(formatCompact({
252
+ this.#logger.warn(formatCompact({
269
253
  op: 'add_reaction',
270
254
  endpoint: this.name,
271
255
  message_id: messageId,
@@ -276,7 +260,7 @@ export class IcqqIpcEndpoint {
276
260
  }));
277
261
  return null;
278
262
  }
279
- logger.debug(formatCompact({
263
+ this.#logger.debug(formatCompact({
280
264
  op: 'add_reaction',
281
265
  endpoint: this.name,
282
266
  message_id: messageId,
@@ -287,7 +271,7 @@ export class IcqqIpcEndpoint {
287
271
  return emojiId;
288
272
  }
289
273
  catch (error) {
290
- logger.warn(formatCompact({
274
+ this.#logger.warn(formatCompact({
291
275
  op: 'add_reaction',
292
276
  endpoint: this.name,
293
277
  message_id: messageId,
@@ -307,7 +291,7 @@ export class IcqqIpcEndpoint {
307
291
  id: emojiId,
308
292
  });
309
293
  if (!resp.ok) {
310
- logger.warn(formatCompact({
294
+ this.#logger.warn(formatCompact({
311
295
  op: 'remove_reaction',
312
296
  endpoint: this.name,
313
297
  message_id: messageId,
@@ -318,7 +302,7 @@ export class IcqqIpcEndpoint {
318
302
  }));
319
303
  return;
320
304
  }
321
- logger.debug(formatCompact({
305
+ this.#logger.debug(formatCompact({
322
306
  op: 'remove_reaction',
323
307
  endpoint: this.name,
324
308
  message_id: messageId,
@@ -328,7 +312,7 @@ export class IcqqIpcEndpoint {
328
312
  }));
329
313
  }
330
314
  catch (error) {
331
- logger.warn(formatCompact({
315
+ this.#logger.warn(formatCompact({
332
316
  op: 'remove_reaction',
333
317
  endpoint: this.name,
334
318
  message_id: messageId,
@@ -345,7 +329,7 @@ export class IcqqIpcEndpoint {
345
329
  try {
346
330
  const resp = await this.request(Actions.RECALL_MSG, { message_id: messageId });
347
331
  if (!resp.ok) {
348
- logger.warn(formatCompact({
332
+ this.#logger.warn(formatCompact({
349
333
  op: 'recall_message',
350
334
  endpoint: this.name,
351
335
  message_id: messageId,
@@ -354,7 +338,7 @@ export class IcqqIpcEndpoint {
354
338
  }));
355
339
  return;
356
340
  }
357
- logger.debug(formatCompact({
341
+ this.#logger.debug(formatCompact({
358
342
  op: 'recall_message',
359
343
  endpoint: this.name,
360
344
  message_id: messageId,
@@ -362,7 +346,7 @@ export class IcqqIpcEndpoint {
362
346
  }));
363
347
  }
364
348
  catch (error) {
365
- logger.warn(formatCompact({
349
+ this.#logger.warn(formatCompact({
366
350
  op: 'recall_message',
367
351
  endpoint: this.name,
368
352
  message_id: messageId,
@@ -501,7 +485,7 @@ export class IcqqIpcEndpoint {
501
485
  admit(msg) {
502
486
  const conversation = msg.conversation;
503
487
  if (!this.#open) {
504
- logger.debug(formatCompact({
488
+ this.#logger.debug(formatCompact({
505
489
  op: 'icqq_inbound_skip',
506
490
  reason: 'endpoint_closed',
507
491
  endpoint: this.name,
@@ -516,33 +500,31 @@ export class IcqqIpcEndpoint {
516
500
  content: msg.segments,
517
501
  rawMessage: msg.content,
518
502
  });
519
- logger.debug(formatCompact({
520
- op: 'icqq_inbound_admit',
521
- endpoint: this.name,
522
- id: msg.id,
523
- target: `${conversation.kind}:${conversation.id}`,
524
- sender: msg.sender,
525
- channelType: msg.channelType,
526
- mentioned: mentioned || undefined,
527
- preview: msg.content.slice(0, 80),
528
- segments: summarizeSegmentTypes(msg.segments),
529
- }));
503
+ this.#logger.info(`recv ${conversation.kind}:${conversation.id}`
504
+ + (msg.sender ? ` from ${msg.sender.name ?? msg.sender.id}` : '')
505
+ + (mentioned ? ' (mentioned)' : '')
506
+ + ` | ${truncatePreview(msg.content, 80)}`);
507
+ const quoteId = msg.metadata?.quote_id;
508
+ const { quote_id: _dropQuoteId, ...restMetadata } = msg.metadata ?? {};
530
509
  void this.#options.gateway.receive({
531
510
  conversation,
532
511
  message: { conversation, id: msg.id },
533
512
  content: msg.content,
534
513
  ...(msg.segments ? { segments: msg.segments } : {}),
535
514
  sender: msg.sender,
515
+ endpointId: this.name,
516
+ ...(mentioned ? { mentioned: true } : {}),
517
+ ...(quoteId ? { replyTo: { id: String(quoteId) } } : {}),
536
518
  metadata: Object.freeze({
537
- endpoint: this.name,
538
519
  channelType: msg.channelType,
539
- ...msg.metadata,
540
- ...(mentioned ? { mentioned: true } : {}),
520
+ ...restMetadata,
541
521
  }),
542
522
  }).catch((err) => {
543
- logger.warn(formatCompact({
544
- op: 'icqq_gateway_receive_failed',
523
+ this.#logger.warn(formatCompact({
524
+ op: 'recv',
525
+ endpoint: this.name,
545
526
  target: `${conversation.kind}:${conversation.id}`,
527
+ ok: false,
546
528
  error: err instanceof Error ? err.message : String(err),
547
529
  }));
548
530
  });
@@ -585,7 +567,7 @@ export class IcqqIpcEndpoint {
585
567
  return;
586
568
  const data = payload;
587
569
  if (shouldSkipSelfInboundMessage(data)) {
588
- logger.debug(formatCompact({
570
+ this.#logger.debug(formatCompact({
589
571
  op: 'icqq_inbound_skip',
590
572
  reason: 'self',
591
573
  endpoint: this.name,
@@ -596,7 +578,7 @@ export class IcqqIpcEndpoint {
596
578
  }
597
579
  const normalized = normalizeIcqqInboundMessage(data);
598
580
  if (!normalized) {
599
- logger.debug(formatCompact({
581
+ this.#logger.debug(formatCompact({
600
582
  op: 'icqq_inbound_skip',
601
583
  reason: 'normalize_failed',
602
584
  endpoint: this.name,
@@ -606,7 +588,7 @@ export class IcqqIpcEndpoint {
606
588
  return;
607
589
  }
608
590
  if (!this.#inboundDeduper.shouldProcess(normalized.messageId)) {
609
- logger.debug(formatCompact({
591
+ this.#logger.debug(formatCompact({
610
592
  op: 'icqq_inbound_skip',
611
593
  reason: 'dedupe',
612
594
  endpoint: this.name,
@@ -623,7 +605,11 @@ export class IcqqIpcEndpoint {
623
605
  }),
624
606
  content: formatInboundContent(normalized.rawMessage),
625
607
  segments: normalized.content,
626
- sender: normalized.userId,
608
+ sender: {
609
+ id: normalized.userId,
610
+ name: normalized.nickname || undefined,
611
+ ...(normalized.senderRole ? { roles: [normalized.senderRole] } : {}),
612
+ },
627
613
  channelType: normalized.channelType,
628
614
  metadata: buildIcqqQuoteMetadata(data, {
629
615
  nickname: normalized.nickname,
@@ -637,7 +623,7 @@ export class IcqqIpcEndpoint {
637
623
  return;
638
624
  const normalized = normalizeIcqqGuildInboundMessage(payload);
639
625
  if (!normalized) {
640
- logger.debug(formatCompact({
626
+ this.#logger.debug(formatCompact({
641
627
  op: 'icqq_inbound_skip',
642
628
  reason: 'guild_normalize_failed',
643
629
  endpoint: this.name,
@@ -646,7 +632,7 @@ export class IcqqIpcEndpoint {
646
632
  }
647
633
  this.#guildCatalog.upsertFromInbound(normalized.raw);
648
634
  if (!this.#inboundDeduper.shouldProcess(`guild:${normalized.messageId}`)) {
649
- logger.debug(formatCompact({
635
+ this.#logger.debug(formatCompact({
650
636
  op: 'icqq_inbound_skip',
651
637
  reason: 'dedupe',
652
638
  endpoint: this.name,
@@ -663,7 +649,7 @@ export class IcqqIpcEndpoint {
663
649
  }),
664
650
  content: formatInboundContent(normalized.rawMessage),
665
651
  segments: normalized.content,
666
- sender: normalized.userId,
652
+ sender: { id: normalized.userId, name: normalized.nickname || undefined },
667
653
  channelType: 'channel',
668
654
  metadata: {
669
655
  guildId: normalized.guildId,
@@ -674,7 +660,7 @@ export class IcqqIpcEndpoint {
674
660
  /** 收件箱行公共前缀:adapter 槽 localName + endpoint live 名(uin)。 */
675
661
  #inboxBase() {
676
662
  const id = String(this.#options.id);
677
- return { adapter: id.split('\0').pop() ?? id, endpointId: this.name };
663
+ return { adapter: id.split('\0').pop() ?? id, endpointKey: this.name };
678
664
  }
679
665
  #recordInboxRequest(payload) {
680
666
  const hooks = this.#options.inbox;
@@ -729,7 +715,7 @@ export class IcqqIpcEndpoint {
729
715
  }
730
716
  }
731
717
  catch (error) {
732
- logger.debug(formatCompact({
718
+ this.#logger.debug(formatCompact({
733
719
  op: 'inbox_pull_system_msg',
734
720
  endpoint: this.name,
735
721
  error: error instanceof Error ? error.message : String(error),
@@ -773,22 +759,8 @@ function toNumericId(value, label) {
773
759
  }
774
760
  return n;
775
761
  }
776
- function summarizeSegmentTypes(segments) {
777
- if (!segments?.length)
778
- return undefined;
779
- return segments
780
- .map((segment) => {
781
- if (typeof segment.type === 'string')
782
- return segment.type;
783
- if (segment.type && typeof segment.type === 'object' && 'name' in segment.type) {
784
- return String(segment.type.name);
785
- }
786
- return '?';
787
- })
788
- .join(',');
789
- }
790
762
  async function defaultCreateIpc(config) {
791
- const uin = Number(config.name);
763
+ const uin = Number(config.id);
792
764
  if (config.rpc) {
793
765
  return IpcClient.connectRpc(config.rpc);
794
766
  }
@@ -14,12 +14,12 @@ export interface IcqqAgentEndpoint {
14
14
  request(action: string, params?: Record<string, unknown>): Promise<IpcResponse>;
15
15
  }
16
16
  export interface IcqqAgentDeps {
17
- getEndpoint: (endpointId: string) => IcqqAgentEndpoint;
17
+ getEndpoint: (endpointKey: string) => IcqqAgentEndpoint;
18
18
  getAdapter?: () => {
19
19
  getEndpoint: (id: string) => IcqqAgentEndpoint;
20
20
  };
21
21
  }
22
- export declare function registerIcqqAgentEndpoint(endpointId: string, endpoint: IcqqAgentEndpoint): () => void;
22
+ export declare function registerIcqqAgentEndpoint(endpointKey: string, endpoint: IcqqAgentEndpoint): () => void;
23
23
  /** Optional override used by tests / transitional callers. Pass `null` to clear. */
24
24
  export declare function setIcqqAgentDeps(deps: IcqqAgentDeps | null): void;
25
25
  export declare function getIcqqAgentDeps(): IcqqAgentDeps;
@@ -4,11 +4,11 @@
4
4
  */
5
5
  const endpoints = new Map();
6
6
  let override = null;
7
- export function registerIcqqAgentEndpoint(endpointId, endpoint) {
8
- endpoints.set(endpointId, endpoint);
7
+ export function registerIcqqAgentEndpoint(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 registerIcqqAgentEndpoint(endpointId, endpoint) {
16
16
  export function setIcqqAgentDeps(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} 不存在`);
22
+ throw new Error(`Endpoint ${endpointKey} 不存在`);
23
23
  return registered;
24
24
  }
25
25
  export function getIcqqAgentDeps() {
@@ -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';
@@ -16,17 +16,17 @@ export const icqqEndpointCommands = createEndpointCommands({
16
16
  running: (use) => use(icqqRuntimeStateToken).endpoints.values(),
17
17
  describeEntry: (entry) => (entry.rpc ? 'rpc(远程守护进程)' : 'ipc(本地守护进程)'),
18
18
  addDescription: '登记 ICQQ endpoint(uin 需先经 icqq login 完成扫码登录;重启 zhin 生效)',
19
- bindFlow: ({ name }) => {
20
- if (!name) {
19
+ bindFlow: ({ id }) => {
20
+ if (!id) {
21
21
  return '用法:icqq.endpoint add <uin>(uin 为纯数字 QQ 号,且需先执行 icqq login <uin> 完成扫码登录)';
22
22
  }
23
- if (!/^\d+$/.test(name)) {
23
+ if (!/^\d+$/.test(id)) {
24
24
  return 'icqq endpoint 名必须是纯数字 QQ 号(uin)';
25
25
  }
26
26
  try {
27
- const filePath = addEndpointToConfig('icqq', { name });
28
- return (`✅ endpoint「${name}」已追加到 ${filePath} 的 plugins.icqq.endpoints。\n` +
29
- `⚠️ 请确保已执行 icqq login ${name} 启动守护进程并完成扫码登录;重启 zhin 后生效。`);
27
+ const filePath = addEndpointToConfig('icqq', { id });
28
+ return (`✅ endpoint「${id}」已追加到 ${filePath} 的 plugins.icqq.endpoints。\n` +
29
+ `⚠️ 请确保已执行 icqq login ${id} 启动守护进程并完成扫码登录;重启 zhin 后生效。`);
30
30
  }
31
31
  catch (error) {
32
32
  return `添加失败:${error instanceof Error ? error.message : String(error)}`;
@@ -10,7 +10,7 @@ import type { IpcSystemMessage } from './types.js';
10
10
  /** 行级公共前缀:adapter 槽 localName + endpoint live 名(uin)。 */
11
11
  export interface IcqqInboxBase {
12
12
  readonly adapter: string;
13
- readonly endpointId: string;
13
+ readonly endpointKey: string;
14
14
  }
15
15
  /** post_type=request / request.* 判定(OneBot 事件壳)。 */
16
16
  export declare function isIcqqRequestPayload(payload: unknown): boolean;
package/lib/icqq-inbox.js CHANGED
@@ -27,7 +27,7 @@ export function buildIcqqInboxRequestRow(payload, base) {
27
27
  const isGroup = requestType === 'group' || groupId != null;
28
28
  return {
29
29
  adapter: base.adapter,
30
- endpoint_id: base.endpointId,
30
+ endpoint_id: base.endpointKey,
31
31
  platform_request_id: platformRequestId,
32
32
  type: isGroup ? 'group' : (requestType ?? 'friend'),
33
33
  scene_type: isGroup ? 'group' : null,
@@ -63,7 +63,7 @@ export function buildIcqqInboxNoticeRow(payload, base) {
63
63
  const targetId = userId != null && String(userId) !== String(actorId ?? '') ? userId : undefined;
64
64
  return {
65
65
  adapter: base.adapter,
66
- endpoint_id: base.endpointId,
66
+ endpoint_id: base.endpointKey,
67
67
  platform_notice_id: platformNoticeId,
68
68
  type: noticeType,
69
69
  scene_type: groupId != null ? 'group' : null,
@@ -92,7 +92,7 @@ export function buildIcqqSystemRequestRow(message, kind, base) {
92
92
  return null;
93
93
  return {
94
94
  adapter: base.adapter,
95
- endpoint_id: base.endpointId,
95
+ endpoint_id: base.endpointKey,
96
96
  platform_request_id: platformRequestId,
97
97
  type: kind,
98
98
  scene_type: kind === 'group' ? 'group' : null,
package/lib/protocol.d.ts CHANGED
@@ -199,7 +199,7 @@ export declare const Actions: {
199
199
  };
200
200
  /** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
201
201
  export interface IcqqAdapterConfig {
202
- readonly name?: string;
202
+ readonly id?: string;
203
203
  readonly autoReconnect?: boolean;
204
204
  readonly outboundMedia?: 'file' | 'base64';
205
205
  readonly rpc?: {
@@ -210,7 +210,7 @@ export interface IcqqAdapterConfig {
210
210
  /** Transitional: legacy root `endpoints[]` with `context: icqq`. */
211
211
  readonly endpoints?: ReadonlyArray<{
212
212
  readonly context?: string;
213
- readonly name?: string;
213
+ readonly id?: string;
214
214
  readonly autoReconnect?: boolean;
215
215
  readonly outboundMedia?: 'file' | 'base64';
216
216
  readonly rpc?: {
@@ -222,7 +222,7 @@ export interface IcqqAdapterConfig {
222
222
  }
223
223
  export interface ResolvedIcqqConfig {
224
224
  readonly context: 'icqq';
225
- readonly name: string;
225
+ readonly id: string;
226
226
  readonly autoReconnect: boolean;
227
227
  readonly outboundMedia?: 'file' | 'base64';
228
228
  readonly rpc?: {
@@ -244,7 +244,10 @@ export interface IcqqInboundMessage {
244
244
  * 与 content(CQ 原文纯文本视图)同源,随 gateway.receive 上送。
245
245
  */
246
246
  readonly segments?: readonly MessageSegment[];
247
- readonly sender: string;
247
+ readonly sender: {
248
+ readonly id: string;
249
+ readonly name?: string;
250
+ };
248
251
  readonly channelType: 'private' | 'group' | 'channel';
249
252
  readonly metadata?: Record<string, unknown>;
250
253
  }
@@ -268,7 +271,7 @@ export declare function resolveIcqqConfig(config?: IcqqAdapterConfig): ResolvedI
268
271
  * 入站归一化 → ConversationRef:群临时会话(temp)映射为群容器内的 private
269
272
  * 会话(parent kind 'group');频道消息的所属 guild 进 `parent`(kind 'channel')。
270
273
  */
271
- export declare function icqqInboundConversation(endpointId: string, input: {
274
+ export declare function icqqInboundConversation(endpointKey: string, input: {
272
275
  readonly channelType: 'private' | 'group' | 'channel';
273
276
  readonly channelId: string;
274
277
  readonly channelParentGroupId?: string;
package/lib/protocol.js CHANGED
@@ -188,9 +188,9 @@ export const Actions = {
188
188
  };
189
189
  export function resolveIcqqConfig(config = {}) {
190
190
  const entry = config.endpoints?.find((item) => item.context === 'icqq');
191
- const name = pickCredential(config.name, entry?.name, process.env.ICQQ_ACCOUNT);
192
- if (!/^\d+$/.test(name)) {
193
- throw new TypeError('ICQQ adapter requires numeric name (QQ uin) via plugins.<key>.name or ICQQ_ACCOUNT');
191
+ const id = pickCredential(config.id, entry?.id, process.env.ICQQ_ACCOUNT);
192
+ if (!/^\d+$/.test(id)) {
193
+ throw new TypeError('ICQQ adapter requires numeric id (QQ uin) via plugins.<key>.id or ICQQ_ACCOUNT');
194
194
  }
195
195
  const autoReconnect = config.autoReconnect ?? entry?.autoReconnect ?? true;
196
196
  const outboundMedia = config.outboundMedia ?? entry?.outboundMedia;
@@ -200,7 +200,7 @@ export function resolveIcqqConfig(config = {}) {
200
200
  : undefined;
201
201
  return {
202
202
  context: 'icqq',
203
- name,
203
+ id,
204
204
  autoReconnect,
205
205
  ...(outboundMedia ? { outboundMedia } : {}),
206
206
  ...(rpc ? { rpc } : {}),
@@ -210,8 +210,8 @@ export function resolveIcqqConfig(config = {}) {
210
210
  * 入站归一化 → ConversationRef:群临时会话(temp)映射为群容器内的 private
211
211
  * 会话(parent kind 'group');频道消息的所属 guild 进 `parent`(kind 'channel')。
212
212
  */
213
- export function icqqInboundConversation(endpointId, input) {
214
- const endpoint = { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId };
213
+ export function icqqInboundConversation(endpointKey, input) {
214
+ const endpoint = { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey };
215
215
  if (input.channelType === 'private' && input.channelParentGroupId) {
216
216
  return {
217
217
  endpoint,