@aalis/plugin-tool-onebot 0.9.2 → 0.10.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/dist/index.js CHANGED
@@ -1,14 +1,11 @@
1
- import { getPlatformAdapters, getPlatformNames } from '@aalis/api-platform';
2
- import { createStorageGateway } from '@aalis/api-storage';
3
- import { toolsWithGroups, useToolService } from '@aalis/api-tools';
1
+ import { media } from '@aalis/api-media';
2
+ import { getPlatformAdapters, getPlatformNames, platform } from '@aalis/api-platform';
3
+ import { createStorageGateway, storage } from '@aalis/api-storage';
4
+ import { sessionHistory } from '@aalis/api-tool-session';
5
+ import { tools, withToolGroups } from '@aalis/api-tools';
6
+ import { config, definePlugin, events, lifecycle, logger, optional } from '@aalis/core';
4
7
  // ===== 插件元数据 =====
5
- export const name = '@aalis/plugin-tool-onebot';
6
- export const displayName = 'OneBot 工具';
7
- export const subsystem = 'tools';
8
- export const inject = {
9
- optional: ['platform', 'session-history'],
10
- };
11
- export const configSchema = {
8
+ const configSchema = {
12
9
  groupManagement: {
13
10
  label: '群管理工具',
14
11
  fields: {
@@ -86,6 +83,18 @@ export const configSchema = {
86
83
  },
87
84
  },
88
85
  };
86
+ // ===== 能力声明 =====
87
+ const uses = {
88
+ tools: optional(tools),
89
+ platform: optional(platform),
90
+ storage: optional(storage),
91
+ media: optional(media),
92
+ sessionHistory: optional(sessionHistory),
93
+ events,
94
+ logger,
95
+ lifecycle,
96
+ config,
97
+ };
89
98
  // ===== 辅助函数 =====
90
99
  /** 从 sessionId 解析 OneBot 连接信息 */
91
100
  function parseOneBotSession(sessionId) {
@@ -98,13 +107,13 @@ function parseOneBotSession(sessionId) {
98
107
  targetId: parts.slice(3).join(':'),
99
108
  };
100
109
  }
101
- /** 从上下文中找到支持 callAction 的 OneBot 平台适配器 */
102
- function findOneBotAdapter(ctx) {
103
- return getPlatformAdapters(ctx).find(a => a.platform === 'onebot' && typeof a.callAction === 'function');
110
+ /** 在已注册的平台适配器里找出支持 callAction 的 OneBot 适配器 */
111
+ function findOneBotAdapter(platform) {
112
+ return getPlatformAdapters(platform).find(a => a.platform === 'onebot' && typeof a.callAction === 'function');
104
113
  }
105
114
  /** 从已连接的 OneBot 适配器中找出任意一个 selfId(优先 online) */
106
- function getAnyOneBotSelfId(ctx) {
107
- for (const a of getPlatformAdapters(ctx)) {
115
+ function getAnyOneBotSelfId(platform) {
116
+ for (const a of getPlatformAdapters(platform)) {
108
117
  if (a.platform !== 'onebot')
109
118
  continue;
110
119
  const conns = a.getConnections?.() ?? [];
@@ -122,14 +131,14 @@ function getAnyOneBotSelfId(ctx) {
122
131
  * 优先级:args.self_id → 当前 callCtx 是 OneBot 会话时取它的 selfId → 任意可用 adapter 的第一个 selfId。
123
132
  * 找不到则抛错(无可用 OneBot 连接)。
124
133
  */
125
- function resolveSelfId(ctx, callCtx, args) {
134
+ function resolveSelfId(platform, callCtx, args) {
126
135
  const fromArgs = args.self_id != null && String(args.self_id).trim() ? String(args.self_id).trim() : '';
127
136
  if (fromArgs)
128
137
  return fromArgs;
129
138
  const parsed = parseOneBotSession(callCtx.sessionId);
130
139
  if (parsed?.selfId)
131
140
  return parsed.selfId;
132
- const fallback = getAnyOneBotSelfId(ctx);
141
+ const fallback = getAnyOneBotSelfId(platform);
133
142
  if (fallback)
134
143
  return fallback;
135
144
  throw new Error('未找到可用的 OneBot 连接');
@@ -138,9 +147,9 @@ function resolveSelfId(ctx, callCtx, args) {
138
147
  * 解析"目标群":args.group_id 优先;否则当前会话必须在 OneBot 群里。
139
148
  * 不再限制工具必须在群会话上下文中调用。
140
149
  */
141
- function resolveGroupTarget(ctx, callCtx, args) {
150
+ function resolveGroupTarget(platform, callCtx, args) {
142
151
  const argGroupId = args.group_id != null && String(args.group_id).trim() ? String(args.group_id).trim() : '';
143
- const selfId = resolveSelfId(ctx, callCtx, args);
152
+ const selfId = resolveSelfId(platform, callCtx, args);
144
153
  if (argGroupId)
145
154
  return { selfId, groupId: argGroupId };
146
155
  const parsed = parseOneBotSession(callCtx.sessionId);
@@ -152,9 +161,9 @@ function resolveGroupTarget(ctx, callCtx, args) {
152
161
  /**
153
162
  * 解析"目标用户":args.user_id 优先;否则当前会话必须是 OneBot 私聊。
154
163
  */
155
- function _resolveUserTarget(ctx, callCtx, args) {
164
+ function _resolveUserTarget(platform, callCtx, args) {
156
165
  const argUserId = args.user_id != null && String(args.user_id).trim() ? String(args.user_id).trim() : '';
157
- const selfId = resolveSelfId(ctx, callCtx, args);
166
+ const selfId = resolveSelfId(platform, callCtx, args);
158
167
  if (argUserId)
159
168
  return { selfId, userId: argUserId };
160
169
  const parsed = parseOneBotSession(callCtx.sessionId);
@@ -171,8 +180,8 @@ function buildOneBotSessionId(selfId, detailType, targetId) {
171
180
  * adapter 内部只用 sessionId 解析 selfId 来定位 WebSocket 连接,
172
181
  * 因此这里用合成 sessionId("onebot:<selfId>:internal:0")即可,与目标会话类型无关。
173
182
  */
174
- async function callAction(ctx, selfId, action, params) {
175
- const adapter = findOneBotAdapter(ctx);
183
+ async function callAction(platform, selfId, action, params) {
184
+ const adapter = findOneBotAdapter(platform);
176
185
  if (!adapter?.callAction)
177
186
  throw new Error('OneBot 适配器不可用或不支持 callAction');
178
187
  return adapter.callAction(buildOneBotSessionId(selfId, 'internal', '0'), action, params);
@@ -287,11 +296,12 @@ function collectForwardImageRefs(data, limit) {
287
296
  .slice(0, limit)
288
297
  .flatMap(item => extractImageRefsFromContent(getForwardNodeContent(item)));
289
298
  }
290
- async function resolveForwardImageSource(ctx, storage, selfId, ref) {
299
+ async function resolveForwardImageSource(caps, storage, selfId, ref) {
291
300
  if (/^(https?:|data:)/i.test(ref.source))
292
301
  return ref.source;
302
+ const { platform, logger } = caps;
293
303
  try {
294
- const imageData = (await callAction(ctx, selfId, 'get_image', { file: ref.source }));
304
+ const imageData = (await callAction(platform, selfId, 'get_image', { file: ref.source }));
295
305
  const resolvedSource = imageData.url ?? imageData.file ?? ref.source;
296
306
  if (typeof resolvedSource === 'string') {
297
307
  if (/^(https?:|data:)/i.test(resolvedSource))
@@ -303,19 +313,20 @@ async function resolveForwardImageSource(ctx, storage, selfId, ref) {
303
313
  }
304
314
  }
305
315
  catch (err) {
306
- ctx.logger.debug(`get_image 解析转发图片失败 (${ref.source}): ${err}`);
316
+ logger.debug(`get_image 解析转发图片失败 (${ref.source}): ${err}`);
307
317
  }
308
318
  const dataUri = await localImageToDataUri(storage, ref.source);
309
319
  return dataUri ?? ref.source;
310
320
  }
311
- async function recognizeForwardImages(ctx, storage, selfId, data, limit) {
321
+ async function recognizeForwardImages(caps, storage, selfId, data, limit) {
312
322
  const refs = collectForwardImageRefs(data, limit);
313
323
  const imageDescriptions = new Map();
314
324
  if (refs.length === 0)
315
325
  return { imageDescriptions };
316
- const mediaSvc = ctx.getService('media');
317
- if (!mediaSvc?.describeImage) {
318
- ctx.logger.debug(`合并转发包含 ${refs.length} 张图片,但 media 服务不可用`);
326
+ const { logger, media } = caps;
327
+ const mediaService = media.current;
328
+ if (!mediaService?.describeImage) {
329
+ logger.debug(`合并转发包含 ${refs.length} 张图片,但 media 服务不可用`);
319
330
  return { imageDescriptions };
320
331
  }
321
332
  const seen = new Set();
@@ -325,13 +336,13 @@ async function recognizeForwardImages(ctx, storage, selfId, data, limit) {
325
336
  continue;
326
337
  seen.add(key);
327
338
  try {
328
- const imageSource = await resolveForwardImageSource(ctx, storage, selfId, ref);
329
- const description = await mediaSvc.describeImage(imageSource);
339
+ const imageSource = await resolveForwardImageSource(caps, storage, selfId, ref);
340
+ const description = await mediaService.describeImage(imageSource);
330
341
  if (description)
331
342
  imageDescriptions.set(key, description);
332
343
  }
333
344
  catch (err) {
334
- ctx.logger.debug(`合并转发图片识别失败 (${ref.source}): ${err}`);
345
+ logger.debug(`合并转发图片识别失败 (${ref.source}): ${err}`);
335
346
  }
336
347
  }
337
348
  return { imageDescriptions };
@@ -423,9 +434,9 @@ function roleLevel(role) {
423
434
  return ROLE_LEVEL[role] ?? 0;
424
435
  }
425
436
  /** 查询群成员信息(失败返回 null) */
426
- async function getGroupMemberInfo(ctx, selfId, groupId, userId) {
437
+ async function getGroupMemberInfo(platform, selfId, groupId, userId) {
427
438
  try {
428
- return (await callAction(ctx, selfId, 'get_group_member_info', {
439
+ return (await callAction(platform, selfId, 'get_group_member_info', {
429
440
  group_id: Number(groupId),
430
441
  user_id: Number(userId),
431
442
  no_cache: true,
@@ -436,8 +447,8 @@ async function getGroupMemberInfo(ctx, selfId, groupId, userId) {
436
447
  }
437
448
  }
438
449
  /** 检查管理操作权限,返回错误消息(null 表示通过或无法验证) */
439
- async function checkAdminPermission(ctx, selfId, groupId, targetUserId, requireOwner) {
440
- const selfInfo = await getGroupMemberInfo(ctx, selfId, groupId, selfId);
450
+ async function checkAdminPermission(platform, selfId, groupId, targetUserId, requireOwner) {
451
+ const selfInfo = await getGroupMemberInfo(platform, selfId, groupId, selfId);
441
452
  if (!selfInfo)
442
453
  return null; // 无法获取自身信息,跳过权限检查
443
454
  const selfRole = String(selfInfo.role ?? 'member');
@@ -448,7 +459,7 @@ async function checkAdminPermission(ctx, selfId, groupId, targetUserId, requireO
448
459
  return `操作失败:机器人不是管理员(当前角色:${selfRole}),无法执行管理操作`;
449
460
  }
450
461
  if (targetUserId) {
451
- const targetInfo = await getGroupMemberInfo(ctx, selfId, groupId, targetUserId);
462
+ const targetInfo = await getGroupMemberInfo(platform, selfId, groupId, targetUserId);
452
463
  if (!targetInfo) {
453
464
  return `操作失败:无法获取用户 ${targetUserId} 的信息,该用户可能不在群中`;
454
465
  }
@@ -460,81 +471,89 @@ async function checkAdminPermission(ctx, selfId, groupId, targetUserId, requireO
460
471
  }
461
472
  return null;
462
473
  }
463
- export function apply(ctx, config) {
464
- const tools = useToolService(ctx);
465
- const storage = createStorageGateway(ctx);
466
- const bundle = {
467
- daily: toolsWithGroups(tools, ['onebot-daily']),
468
- group: toolsWithGroups(tools, ['onebot-group']),
469
- personal: toolsWithGroups(tools, ['onebot-personal']),
470
- };
471
- // 仅当 OneBot 平台可用时才注册工具
472
- // 使用 ready 事件确保平台已加载
473
- ctx.on('ready', () => {
474
- if (!getPlatformNames(ctx).includes('onebot')) {
475
- ctx.logger.info('未检测到 OneBot 平台,跳过 OneBot 工具注册');
476
- return;
477
- }
478
- ctx.logger.info('检测到 OneBot 平台,开始注册 OneBot 工具');
479
- // 注册工具分组:按职责语义切分,彼此不重叠
480
- tools.registerGroup({
481
- name: 'onebot-daily',
482
- label: 'OneBot 只读与日常',
483
- description: '只读查询(群信息/成员/好友列表/历史/登录信息)+ 日常低风险互动(戳一戳、好友赞)',
484
- });
485
- tools.registerGroup({
486
- name: 'onebot-group',
487
- label: 'OneBot 群务',
488
- description: '群务管理:禁言/全员禁言/踢人/撤回消息/设置群名片/改群名/设管理员/群打卡/审批加群申请 等',
489
- });
490
- tools.registerGroup({
491
- name: 'onebot-personal',
492
- label: 'OneBot 个人/私聊',
493
- description: '影响 bot 账号本身的人际关系:退群、删好友、处理好友申请、接受/拒绝入群邀请',
494
- });
495
- const cfg = {
496
- groupManagement: { enabled: true, ...(config.groupManagement ?? {}) },
497
- groupInfo: { enabled: true, ...(config.groupInfo ?? {}) },
498
- account: { enabled: true, ...(config.account ?? {}) },
499
- interaction: { enabled: true, ...(config.interaction ?? {}) },
500
- sessionHistory: {
501
- enabled: true,
502
- maxLimit: 100,
503
- defaultLimit: 20,
504
- allowGroupReadPrivate: false,
505
- allowCrossSelf: false,
506
- allowCrossGroup: true,
507
- allowCrossPrivate: false,
508
- ...(config.sessionHistory ?? {}),
509
- },
474
+ export default definePlugin({
475
+ name: '@aalis/plugin-tool-onebot',
476
+ displayName: 'OneBot 工具',
477
+ subsystem: 'tools',
478
+ configSchema,
479
+ uses,
480
+ apply(caps) {
481
+ const { tools, events, logger, platform, config } = caps;
482
+ const storage = createStorageGateway(caps.storage);
483
+ const bundle = {
484
+ daily: withToolGroups(tools, ['onebot-daily']),
485
+ group: withToolGroups(tools, ['onebot-group']),
486
+ personal: withToolGroups(tools, ['onebot-personal']),
510
487
  };
511
- if (cfg.groupManagement.enabled)
512
- registerGroupManagementTools(ctx, bundle);
513
- if (cfg.groupInfo.enabled)
514
- registerGroupInfoTools(ctx, storage, bundle);
515
- if (cfg.account.enabled)
516
- registerAccountTools(ctx, bundle);
517
- if (cfg.interaction.enabled)
518
- registerInteractionTools(ctx, bundle);
519
- if (cfg.sessionHistory.enabled) {
520
- const maxLimit = Math.max(1, Math.min(1000, Number(cfg.sessionHistory.maxLimit) || 100));
521
- const defaultLimitRaw = Math.max(1, Math.floor(Number(cfg.sessionHistory.defaultLimit) || 20));
522
- const historyCfg = {
523
- maxLimit,
524
- defaultLimit: Math.min(defaultLimitRaw, maxLimit),
525
- allowGroupReadPrivate: cfg.sessionHistory.allowGroupReadPrivate === true,
526
- allowCrossSelf: cfg.sessionHistory.allowCrossSelf === true,
527
- allowCrossGroup: cfg.sessionHistory.allowCrossGroup !== false,
528
- allowCrossPrivate: cfg.sessionHistory.allowCrossPrivate === true,
488
+ // 仅当 OneBot 平台可用时才注册工具
489
+ // 使用 app:ready 事件确保平台已加载
490
+ events.on('app:ready', () => {
491
+ if (!getPlatformNames(platform).includes('onebot')) {
492
+ logger.info('未检测到 OneBot 平台,跳过 OneBot 工具注册');
493
+ return;
494
+ }
495
+ logger.info('检测到 OneBot 平台,开始注册 OneBot 工具');
496
+ // 注册工具分组:按职责语义切分,彼此不重叠
497
+ tools.registerGroup({
498
+ name: 'onebot-daily',
499
+ label: 'OneBot 只读与日常',
500
+ description: '只读查询(群信息/成员/好友列表/历史/登录信息)+ 日常低风险互动(戳一戳、好友赞)',
501
+ });
502
+ tools.registerGroup({
503
+ name: 'onebot-group',
504
+ label: 'OneBot 群务',
505
+ description: '群务管理:禁言/全员禁言/踢人/撤回消息/设置群名片/改群名/设管理员/群打卡/审批加群申请 等',
506
+ });
507
+ tools.registerGroup({
508
+ name: 'onebot-personal',
509
+ label: 'OneBot 个人/私聊',
510
+ description: '影响 bot 账号本身的人际关系:退群、删好友、处理好友申请、接受/拒绝入群邀请',
511
+ });
512
+ const cfg = {
513
+ groupManagement: { enabled: true, ...(config.groupManagement ?? {}) },
514
+ groupInfo: { enabled: true, ...(config.groupInfo ?? {}) },
515
+ account: { enabled: true, ...(config.account ?? {}) },
516
+ interaction: { enabled: true, ...(config.interaction ?? {}) },
517
+ sessionHistory: {
518
+ enabled: true,
519
+ maxLimit: 100,
520
+ defaultLimit: 20,
521
+ allowGroupReadPrivate: false,
522
+ allowCrossSelf: false,
523
+ allowCrossGroup: true,
524
+ allowCrossPrivate: false,
525
+ ...(config.sessionHistory ?? {}),
526
+ },
529
527
  };
530
- registerSessionHistoryTools(ctx, bundle, historyCfg);
531
- registerOneBotHistoryAccessChecker(ctx, historyCfg);
532
- }
533
- registerRequestTools(ctx, bundle);
534
- });
535
- }
528
+ if (cfg.groupManagement.enabled)
529
+ registerGroupManagementTools(caps, bundle);
530
+ if (cfg.groupInfo.enabled)
531
+ registerGroupInfoTools(caps, storage, bundle);
532
+ if (cfg.account.enabled)
533
+ registerAccountTools(caps, bundle);
534
+ if (cfg.interaction.enabled)
535
+ registerInteractionTools(caps, bundle);
536
+ if (cfg.sessionHistory.enabled) {
537
+ const maxLimit = Math.max(1, Math.min(1000, Number(cfg.sessionHistory.maxLimit) || 100));
538
+ const defaultLimitRaw = Math.max(1, Math.floor(Number(cfg.sessionHistory.defaultLimit) || 20));
539
+ const historyCfg = {
540
+ maxLimit,
541
+ defaultLimit: Math.min(defaultLimitRaw, maxLimit),
542
+ allowGroupReadPrivate: cfg.sessionHistory.allowGroupReadPrivate === true,
543
+ allowCrossSelf: cfg.sessionHistory.allowCrossSelf === true,
544
+ allowCrossGroup: cfg.sessionHistory.allowCrossGroup !== false,
545
+ allowCrossPrivate: cfg.sessionHistory.allowCrossPrivate === true,
546
+ };
547
+ registerSessionHistoryTools(caps, bundle, historyCfg);
548
+ registerOneBotHistoryAccessChecker(caps, historyCfg);
549
+ }
550
+ registerRequestTools(caps, bundle);
551
+ });
552
+ },
553
+ });
536
554
  // ===== 群管理工具 =====
537
- function registerGroupManagementTools(ctx, bundle) {
555
+ function registerGroupManagementTools(caps, bundle) {
556
+ const { platform, logger } = caps;
538
557
  const { group, personal } = bundle;
539
558
  // ---- 群禁言(单人)----
540
559
  group.register({
@@ -555,18 +574,18 @@ function registerGroupManagementTools(ctx, bundle) {
555
574
  },
556
575
  },
557
576
  handler: async (args, callCtx) => {
558
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
577
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
559
578
  const duration = typeof args.duration === 'number' ? args.duration : 60;
560
- const permError = await checkAdminPermission(ctx, selfId, groupId, String(args.user_id));
579
+ const permError = await checkAdminPermission(platform, selfId, groupId, String(args.user_id));
561
580
  if (permError)
562
581
  return permError;
563
- await callAction(ctx, selfId, 'set_group_ban', {
582
+ await callAction(platform, selfId, 'set_group_ban', {
564
583
  group_id: Number(groupId),
565
584
  user_id: Number(args.user_id),
566
585
  duration,
567
586
  });
568
587
  // 验证禁言是否生效
569
- const info = await getGroupMemberInfo(ctx, selfId, groupId, String(args.user_id));
588
+ const info = await getGroupMemberInfo(platform, selfId, groupId, String(args.user_id));
570
589
  if (info && 'shut_up_timestamp' in info) {
571
590
  const shutUp = Number(info.shut_up_timestamp);
572
591
  const now = Math.floor(Date.now() / 1000);
@@ -602,11 +621,11 @@ function registerGroupManagementTools(ctx, bundle) {
602
621
  },
603
622
  },
604
623
  handler: async (args, callCtx) => {
605
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
606
- const permError = await checkAdminPermission(ctx, selfId, groupId);
624
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
625
+ const permError = await checkAdminPermission(platform, selfId, groupId);
607
626
  if (permError)
608
627
  return permError;
609
- await callAction(ctx, selfId, 'set_group_whole_ban', {
628
+ await callAction(platform, selfId, 'set_group_whole_ban', {
610
629
  group_id: Number(groupId),
611
630
  enable: !!args.enable,
612
631
  });
@@ -632,11 +651,11 @@ function registerGroupManagementTools(ctx, bundle) {
632
651
  },
633
652
  },
634
653
  handler: async (args, callCtx) => {
635
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
636
- const permError = await checkAdminPermission(ctx, selfId, groupId, String(args.user_id));
654
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
655
+ const permError = await checkAdminPermission(platform, selfId, groupId, String(args.user_id));
637
656
  if (permError)
638
657
  return permError;
639
- await callAction(ctx, selfId, 'set_group_kick', {
658
+ await callAction(platform, selfId, 'set_group_kick', {
640
659
  group_id: Number(groupId),
641
660
  user_id: Number(args.user_id),
642
661
  reject_add_request: !!args.reject_add_request,
@@ -662,12 +681,12 @@ function registerGroupManagementTools(ctx, bundle) {
662
681
  },
663
682
  handler: async (args, callCtx) => {
664
683
  const argGroupId = args.group_id != null && String(args.group_id).trim() ? String(args.group_id).trim() : '';
665
- const selfId = resolveSelfId(ctx, callCtx, args);
684
+ const selfId = resolveSelfId(platform, callCtx, args);
666
685
  const parsed = parseOneBotSession(callCtx.sessionId);
667
686
  const groupId = argGroupId || (parsed?.detailType === 'group' ? parsed.targetId : '');
668
687
  if (!groupId)
669
688
  return '请提供 group_id,或在要退出的群聊中调用此工具';
670
- await callAction(ctx, selfId, 'set_group_leave', {
689
+ await callAction(platform, selfId, 'set_group_leave', {
671
690
  group_id: Number(groupId),
672
691
  is_dismiss: false,
673
692
  });
@@ -693,11 +712,11 @@ function registerGroupManagementTools(ctx, bundle) {
693
712
  },
694
713
  },
695
714
  handler: async (args, callCtx) => {
696
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
697
- const permError = await checkAdminPermission(ctx, selfId, groupId);
715
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
716
+ const permError = await checkAdminPermission(platform, selfId, groupId);
698
717
  if (permError)
699
718
  return permError;
700
- await callAction(ctx, selfId, 'set_group_card', {
719
+ await callAction(platform, selfId, 'set_group_card', {
701
720
  group_id: Number(groupId),
702
721
  user_id: Number(args.user_id),
703
722
  card: String(args.card ?? ''),
@@ -723,11 +742,11 @@ function registerGroupManagementTools(ctx, bundle) {
723
742
  },
724
743
  },
725
744
  handler: async (args, callCtx) => {
726
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
727
- const permError = await checkAdminPermission(ctx, selfId, groupId);
745
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
746
+ const permError = await checkAdminPermission(platform, selfId, groupId);
728
747
  if (permError)
729
748
  return permError;
730
- await callAction(ctx, selfId, 'set_group_name', {
749
+ await callAction(platform, selfId, 'set_group_name', {
731
750
  group_id: Number(groupId),
732
751
  group_name: String(args.group_name),
733
752
  });
@@ -753,11 +772,11 @@ function registerGroupManagementTools(ctx, bundle) {
753
772
  },
754
773
  },
755
774
  handler: async (args, callCtx) => {
756
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
757
- const permError = await checkAdminPermission(ctx, selfId, groupId, undefined, true);
775
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
776
+ const permError = await checkAdminPermission(platform, selfId, groupId, undefined, true);
758
777
  if (permError)
759
778
  return permError;
760
- await callAction(ctx, selfId, 'set_group_special_title', {
779
+ await callAction(platform, selfId, 'set_group_special_title', {
761
780
  group_id: Number(groupId),
762
781
  user_id: Number(args.user_id),
763
782
  special_title: String(args.special_title ?? ''),
@@ -785,11 +804,11 @@ function registerGroupManagementTools(ctx, bundle) {
785
804
  },
786
805
  },
787
806
  handler: async (args, callCtx) => {
788
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
789
- const permError = await checkAdminPermission(ctx, selfId, groupId, undefined, true);
807
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
808
+ const permError = await checkAdminPermission(platform, selfId, groupId, undefined, true);
790
809
  if (permError)
791
810
  return permError;
792
- await callAction(ctx, selfId, 'set_group_admin', {
811
+ await callAction(platform, selfId, 'set_group_admin', {
793
812
  group_id: Number(groupId),
794
813
  user_id: Number(args.user_id),
795
814
  enable: !!args.enable,
@@ -815,8 +834,8 @@ function registerGroupManagementTools(ctx, bundle) {
815
834
  },
816
835
  handler: async (args, callCtx) => {
817
836
  // 不限制必须是群聊;只要能找到可用的 OneBot 账号即可
818
- const selfId = resolveSelfId(ctx, callCtx, args);
819
- await callAction(ctx, selfId, 'delete_msg', {
837
+ const selfId = resolveSelfId(platform, callCtx, args);
838
+ await callAction(platform, selfId, 'delete_msg', {
820
839
  message_id: Number(args.message_id),
821
840
  });
822
841
  return `已撤回消息 ${args.message_id}`;
@@ -844,7 +863,7 @@ function registerGroupManagementTools(ctx, bundle) {
844
863
  },
845
864
  },
846
865
  handler: async (args, callCtx) => {
847
- const selfId = resolveSelfId(ctx, callCtx, args);
866
+ const selfId = resolveSelfId(platform, callCtx, args);
848
867
  const argGroupId = args.group_id != null && String(args.group_id).trim() ? String(args.group_id).trim() : '';
849
868
  const argUserId = args.user_id != null && String(args.user_id).trim() ? String(args.user_id).trim() : '';
850
869
  let targetSessionId;
@@ -858,7 +877,7 @@ function registerGroupManagementTools(ctx, bundle) {
858
877
  return '当前不在 OneBot 会话中,请用 group_id 或 user_id 指定要撤回的目标会话。';
859
878
  targetSessionId = callCtx.sessionId;
860
879
  }
861
- const adapter = findOneBotAdapter(ctx);
880
+ const adapter = findOneBotAdapter(platform);
862
881
  if (!adapter?.getSentMessages) {
863
882
  return '当前 OneBot 适配器版本未记录机器人发出的消息(不支持 getSentMessages)。如已知 message_id 可改用 onebot_delete_msg。';
864
883
  }
@@ -872,7 +891,7 @@ function registerGroupManagementTools(ctx, bundle) {
872
891
  const failed = [];
873
892
  for (const t of targets) {
874
893
  try {
875
- await callAction(ctx, selfId, 'delete_msg', { message_id: Number(t.messageId) || t.messageId });
894
+ await callAction(platform, selfId, 'delete_msg', { message_id: Number(t.messageId) || t.messageId });
876
895
  adapter.forgetSentMessage?.(targetSessionId, t.messageId);
877
896
  recalled.push(t.preview ? `「${t.preview}」` : `msg=${t.messageId}`);
878
897
  }
@@ -889,10 +908,11 @@ function registerGroupManagementTools(ctx, bundle) {
889
908
  return msg;
890
909
  },
891
910
  });
892
- ctx.logger.info('OneBot 群管理工具已注册');
911
+ logger.info('OneBot 群管理工具已注册');
893
912
  }
894
913
  // ===== 群信息查询工具 =====
895
- function registerGroupInfoTools(ctx, storage, bundle) {
914
+ function registerGroupInfoTools(caps, storage, bundle) {
915
+ const { platform, logger } = caps;
896
916
  const { daily } = bundle;
897
917
  // ---- 查看合并转发 ----
898
918
  daily.register({
@@ -915,7 +935,7 @@ function registerGroupInfoTools(ctx, storage, bundle) {
915
935
  },
916
936
  },
917
937
  handler: async (args, callCtx) => {
918
- const selfId = resolveSelfId(ctx, callCtx, args);
938
+ const selfId = resolveSelfId(platform, callCtx, args);
919
939
  if (!args.id)
920
940
  return '参数错误:缺少 id(合并转发 ID)。请使用 <forward id="..."> 中的 id 字符串,不要使用 message_id。';
921
941
  const forwardId = String(args.id);
@@ -924,7 +944,7 @@ function registerGroupInfoTools(ctx, storage, bundle) {
924
944
  // 并维护了一份接收时即抓取并展开(含摘要与图像识别)的缓存。
925
945
  let data;
926
946
  try {
927
- data = await callAction(ctx, selfId, 'get_forward_msg', { id: forwardId });
947
+ data = await callAction(platform, selfId, 'get_forward_msg', { id: forwardId });
928
948
  }
929
949
  catch (err) {
930
950
  return `合并转发读取失败:${err instanceof Error ? err.message : String(err)}。该转发可能已在协议端过期,或当前 OneBot 实现不支持跨会话读取。`;
@@ -937,7 +957,7 @@ function registerGroupInfoTools(ctx, storage, bundle) {
937
957
  const summaryLine = entry.summary ? `\n摘要:${entry.summary}\n` : '\n';
938
958
  return `${header}${summaryLine}\n原文:\n${entry.fullText}`;
939
959
  }
940
- const formatContext = await recognizeForwardImages(ctx, storage, selfId, data, limit);
960
+ const formatContext = await recognizeForwardImages(caps, storage, selfId, data, limit);
941
961
  return formatForwardMessage(data, limit, formatContext);
942
962
  },
943
963
  });
@@ -958,8 +978,8 @@ function registerGroupInfoTools(ctx, storage, bundle) {
958
978
  },
959
979
  },
960
980
  handler: async (args, callCtx) => {
961
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
962
- const data = await callAction(ctx, selfId, 'get_group_info', {
981
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
982
+ const data = await callAction(platform, selfId, 'get_group_info', {
963
983
  group_id: Number(groupId),
964
984
  });
965
985
  return JSON.stringify(data);
@@ -983,9 +1003,9 @@ function registerGroupInfoTools(ctx, storage, bundle) {
983
1003
  },
984
1004
  },
985
1005
  handler: async (args, callCtx) => {
986
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
1006
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
987
1007
  const userId = args.user_id ? String(args.user_id) : selfId;
988
- const data = await callAction(ctx, selfId, 'get_group_member_info', {
1008
+ const data = await callAction(platform, selfId, 'get_group_member_info', {
989
1009
  group_id: Number(groupId),
990
1010
  user_id: Number(userId),
991
1011
  no_cache: true,
@@ -1014,8 +1034,8 @@ function registerGroupInfoTools(ctx, storage, bundle) {
1014
1034
  },
1015
1035
  },
1016
1036
  handler: async (args, callCtx) => {
1017
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
1018
- const data = await callAction(ctx, selfId, 'get_group_member_list', {
1037
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
1038
+ const data = await callAction(platform, selfId, 'get_group_member_list', {
1019
1039
  group_id: Number(groupId),
1020
1040
  });
1021
1041
  const list = Array.isArray(data) ? data : [];
@@ -1078,7 +1098,7 @@ function registerGroupInfoTools(ctx, storage, bundle) {
1078
1098
  },
1079
1099
  handler: async (args, callCtx) => {
1080
1100
  const argGroupId = args.group_id != null && String(args.group_id).trim() ? String(args.group_id).trim() : '';
1081
- const selfId = resolveSelfId(ctx, callCtx, args);
1101
+ const selfId = resolveSelfId(platform, callCtx, args);
1082
1102
  const parsed = parseOneBotSession(callCtx.sessionId);
1083
1103
  let groupId = argGroupId;
1084
1104
  if (!groupId) {
@@ -1087,12 +1107,12 @@ function registerGroupInfoTools(ctx, storage, bundle) {
1087
1107
  }
1088
1108
  groupId = parsed.targetId;
1089
1109
  }
1090
- const adapter = findOneBotAdapter(ctx);
1110
+ const adapter = findOneBotAdapter(platform);
1091
1111
  if (!adapter?.callAction)
1092
1112
  return JSON.stringify({ available: false, reason: 'OneBot 适配器不可用' });
1093
1113
  let info = null;
1094
1114
  try {
1095
- info = (await callAction(ctx, selfId, 'get_group_member_info', {
1115
+ info = (await callAction(platform, selfId, 'get_group_member_info', {
1096
1116
  group_id: Number(groupId),
1097
1117
  user_id: Number(selfId),
1098
1118
  no_cache: true,
@@ -1141,7 +1161,7 @@ function registerGroupInfoTools(ctx, storage, bundle) {
1141
1161
  },
1142
1162
  },
1143
1163
  handler: async (args) => {
1144
- const adapter = findOneBotAdapter(ctx);
1164
+ const adapter = findOneBotAdapter(platform);
1145
1165
  if (!adapter?.getSelfMutes) {
1146
1166
  return JSON.stringify({ supported: false, reason: '当前 OneBot 适配器版本不支持 getSelfMutes' });
1147
1167
  }
@@ -1186,11 +1206,11 @@ function registerGroupInfoTools(ctx, storage, bundle) {
1186
1206
  },
1187
1207
  },
1188
1208
  handler: async (args, callCtx) => {
1189
- const selfId = resolveSelfId(ctx, callCtx, args);
1209
+ const selfId = resolveSelfId(platform, callCtx, args);
1190
1210
  if (!args.message_id)
1191
1211
  return '参数错误:缺少 message_id';
1192
1212
  try {
1193
- const data = await callAction(ctx, selfId, 'get_msg', {
1213
+ const data = await callAction(platform, selfId, 'get_msg', {
1194
1214
  message_id: Number(args.message_id),
1195
1215
  });
1196
1216
  return JSON.stringify(data);
@@ -1222,19 +1242,20 @@ function registerGroupInfoTools(ctx, storage, bundle) {
1222
1242
  },
1223
1243
  },
1224
1244
  handler: async (args, callCtx) => {
1225
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
1245
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
1226
1246
  const honorType = typeof args.type === 'string' ? args.type : 'all';
1227
- const data = await callAction(ctx, selfId, 'get_group_honor_info', {
1247
+ const data = await callAction(platform, selfId, 'get_group_honor_info', {
1228
1248
  group_id: Number(groupId),
1229
1249
  type: honorType,
1230
1250
  });
1231
1251
  return JSON.stringify(data);
1232
1252
  },
1233
1253
  });
1234
- ctx.logger.info('OneBot 群信息查询工具已注册');
1254
+ logger.info('OneBot 群信息查询工具已注册');
1235
1255
  }
1236
1256
  // ===== 账号 / 好友 / 群列表查询工具 =====
1237
- function registerAccountTools(ctx, bundle) {
1257
+ function registerAccountTools(caps, bundle) {
1258
+ const { platform, logger } = caps;
1238
1259
  const { daily, personal } = bundle;
1239
1260
  // ---- 群列表 ----
1240
1261
  daily.register({
@@ -1258,8 +1279,8 @@ function registerAccountTools(ctx, bundle) {
1258
1279
  },
1259
1280
  },
1260
1281
  handler: async (args, callCtx) => {
1261
- const selfId = resolveSelfId(ctx, callCtx, args);
1262
- const data = await callAction(ctx, selfId, 'get_group_list', {});
1282
+ const selfId = resolveSelfId(platform, callCtx, args);
1283
+ const data = await callAction(platform, selfId, 'get_group_list', {});
1263
1284
  const list = Array.isArray(data) ? data : [];
1264
1285
  const keyword = typeof args.keyword === 'string' ? args.keyword.trim().toLowerCase() : '';
1265
1286
  // 上限封顶,避免超大 limit 把整张列表灌进 LLM 上下文(token 浪费)。
@@ -1307,8 +1328,8 @@ function registerAccountTools(ctx, bundle) {
1307
1328
  },
1308
1329
  },
1309
1330
  handler: async (args, callCtx) => {
1310
- const selfId = resolveSelfId(ctx, callCtx, args);
1311
- const data = await callAction(ctx, selfId, 'get_friend_list', {});
1331
+ const selfId = resolveSelfId(platform, callCtx, args);
1332
+ const data = await callAction(platform, selfId, 'get_friend_list', {});
1312
1333
  const list = Array.isArray(data) ? data : [];
1313
1334
  const keyword = typeof args.keyword === 'string' ? args.keyword.trim().toLowerCase() : '';
1314
1335
  // 上限封顶,避免超大 limit 把整张列表灌进 LLM 上下文(token 浪费)。
@@ -1355,8 +1376,8 @@ function registerAccountTools(ctx, bundle) {
1355
1376
  },
1356
1377
  },
1357
1378
  handler: async (args, callCtx) => {
1358
- const selfId = resolveSelfId(ctx, callCtx, args);
1359
- const data = await callAction(ctx, selfId, 'get_stranger_info', {
1379
+ const selfId = resolveSelfId(platform, callCtx, args);
1380
+ const data = await callAction(platform, selfId, 'get_stranger_info', {
1360
1381
  user_id: Number(args.user_id),
1361
1382
  no_cache: !!args.no_cache,
1362
1383
  });
@@ -1374,8 +1395,8 @@ function registerAccountTools(ctx, bundle) {
1374
1395
  },
1375
1396
  },
1376
1397
  handler: async (_args, callCtx) => {
1377
- const selfId = resolveSelfId(ctx, callCtx, _args);
1378
- const data = await callAction(ctx, selfId, 'get_login_info', {});
1398
+ const selfId = resolveSelfId(platform, callCtx, _args);
1399
+ const data = await callAction(platform, selfId, 'get_login_info', {});
1379
1400
  return JSON.stringify(data);
1380
1401
  },
1381
1402
  });
@@ -1397,21 +1418,22 @@ function registerAccountTools(ctx, bundle) {
1397
1418
  },
1398
1419
  handler: async (args, callCtx) => {
1399
1420
  const argUserId = args.user_id != null && String(args.user_id).trim() ? String(args.user_id).trim() : '';
1400
- const selfId = resolveSelfId(ctx, callCtx, args);
1421
+ const selfId = resolveSelfId(platform, callCtx, args);
1401
1422
  const parsed = parseOneBotSession(callCtx.sessionId);
1402
1423
  const userId = argUserId || (parsed?.detailType === 'private' ? parsed.targetId : '');
1403
1424
  if (!userId)
1404
1425
  return '请提供 user_id,或在要删除的好友私聊中调用此工具';
1405
- await callAction(ctx, selfId, 'delete_friend', {
1426
+ await callAction(platform, selfId, 'delete_friend', {
1406
1427
  user_id: Number(userId),
1407
1428
  });
1408
1429
  return `已删除好友 ${userId}`;
1409
1430
  },
1410
1431
  });
1411
- ctx.logger.info('OneBot 账号 / 好友 / 群列表查询工具已注册');
1432
+ logger.info('OneBot 账号 / 好友 / 群列表查询工具已注册');
1412
1433
  }
1413
1434
  // ===== 特殊交互工具 =====
1414
- function registerInteractionTools(ctx, bundle) {
1435
+ function registerInteractionTools(caps, bundle) {
1436
+ const { platform, logger } = caps;
1415
1437
  const { daily, group } = bundle;
1416
1438
  // ---- 戳一戳 ----
1417
1439
  daily.register({
@@ -1436,7 +1458,7 @@ function registerInteractionTools(ctx, bundle) {
1436
1458
  },
1437
1459
  },
1438
1460
  handler: async (args, callCtx) => {
1439
- const selfId = resolveSelfId(ctx, callCtx, args);
1461
+ const selfId = resolveSelfId(platform, callCtx, args);
1440
1462
  const parsed = parseOneBotSession(callCtx.sessionId);
1441
1463
  const argGroupId = args.group_id != null && String(args.group_id).trim() ? String(args.group_id).trim() : '';
1442
1464
  const argUserId = args.user_id != null && String(args.user_id).trim() ? String(args.user_id).trim() : '';
@@ -1447,13 +1469,13 @@ function registerInteractionTools(ctx, bundle) {
1447
1469
  throw new Error('群聊戳一戳必须显式提供 user_id(要戳的对象)。');
1448
1470
  }
1449
1471
  try {
1450
- await callAction(ctx, selfId, 'group_poke', {
1472
+ await callAction(platform, selfId, 'group_poke', {
1451
1473
  group_id: Number(groupId),
1452
1474
  user_id: Number(argUserId),
1453
1475
  });
1454
1476
  }
1455
1477
  catch {
1456
- await callAction(ctx, selfId, 'send_group_poke', {
1478
+ await callAction(platform, selfId, 'send_group_poke', {
1457
1479
  group_id: Number(groupId),
1458
1480
  user_id: Number(argUserId),
1459
1481
  });
@@ -1467,10 +1489,10 @@ function registerInteractionTools(ctx, bundle) {
1467
1489
  }
1468
1490
  // NapCat: friend_poke { user_id };其他实现可能用 send_poke
1469
1491
  try {
1470
- await callAction(ctx, selfId, 'friend_poke', { user_id: Number(userId) });
1492
+ await callAction(platform, selfId, 'friend_poke', { user_id: Number(userId) });
1471
1493
  }
1472
1494
  catch {
1473
- await callAction(ctx, selfId, 'send_poke', { user_id: Number(userId) });
1495
+ await callAction(platform, selfId, 'send_poke', { user_id: Number(userId) });
1474
1496
  }
1475
1497
  return `已戳了 ${userId} 一下`;
1476
1498
  },
@@ -1493,9 +1515,9 @@ function registerInteractionTools(ctx, bundle) {
1493
1515
  },
1494
1516
  },
1495
1517
  handler: async (args, callCtx) => {
1496
- const selfId = resolveSelfId(ctx, callCtx, args);
1518
+ const selfId = resolveSelfId(platform, callCtx, args);
1497
1519
  const times = Math.min(10, Math.max(1, typeof args.times === 'number' ? Math.floor(args.times) : 1));
1498
- await callAction(ctx, selfId, 'send_like', {
1520
+ await callAction(platform, selfId, 'send_like', {
1499
1521
  user_id: Number(args.user_id),
1500
1522
  times,
1501
1523
  });
@@ -1519,25 +1541,26 @@ function registerInteractionTools(ctx, bundle) {
1519
1541
  },
1520
1542
  },
1521
1543
  handler: async (args, callCtx) => {
1522
- const { selfId, groupId } = resolveGroupTarget(ctx, callCtx, args);
1523
- await callAction(ctx, selfId, 'send_group_sign', {
1544
+ const { selfId, groupId } = resolveGroupTarget(platform, callCtx, args);
1545
+ await callAction(platform, selfId, 'send_group_sign', {
1524
1546
  group_id: Number(groupId),
1525
1547
  });
1526
1548
  return '打卡成功';
1527
1549
  },
1528
1550
  });
1529
- ctx.logger.info('OneBot 特殊交互工具已注册');
1551
+ logger.info('OneBot 特殊交互工具已注册');
1530
1552
  }
1531
1553
  /**
1532
1554
  * 把 OneBot 的细粒度访问规则注册到 session-history 服务。
1533
1555
  * 通用工具 session_get_history 和平台专属工具 onebot_get_session_history
1534
1556
  * 调用 service 时都会走这条规则链 —— 不存在绕过路径。
1535
1557
  */
1536
- function registerOneBotHistoryAccessChecker(ctx, cfg) {
1537
- ctx.on('ready', () => {
1538
- const historyService = ctx.getService('session-history');
1558
+ function registerOneBotHistoryAccessChecker(caps, cfg) {
1559
+ const { events, logger, lifecycle, sessionHistory } = caps;
1560
+ events.on('app:ready', () => {
1561
+ const historyService = sessionHistory.current;
1539
1562
  if (!historyService?.registerAccessChecker) {
1540
- ctx.logger.debug('session-history 服务未提供 registerAccessChecker, 跳过 OneBot 访问规则注册');
1563
+ logger.debug('session-history 服务未提供 registerAccessChecker, 跳过 OneBot 访问规则注册');
1541
1564
  return;
1542
1565
  }
1543
1566
  const checker = {
@@ -1572,13 +1595,14 @@ function registerOneBotHistoryAccessChecker(ctx, cfg) {
1572
1595
  },
1573
1596
  };
1574
1597
  const dispose = historyService.registerAccessChecker(checker);
1575
- // 注意:总线上并不存在 'dispose' 事件——此前 ctx.on('dispose', ...) 永远不会
1576
- // 触发,access checker 在插件 bounce 后泄漏。正确挂法是 onDispose 清理链。
1577
- ctx.onDispose(dispose);
1578
- ctx.logger.info('OneBot 会话历史访问规则已注册到 session-history');
1598
+ // 规则挂在 session-history 提供者身上,不随本插件的登记账本自动撤回:
1599
+ // 必须进清理链,否则插件 bounce / 卸载后规则会留在下层泄漏。
1600
+ lifecycle.onDispose(dispose);
1601
+ logger.info('OneBot 会话历史访问规则已注册到 session-history');
1579
1602
  });
1580
1603
  }
1581
- function registerSessionHistoryTools(ctx, bundle, cfg) {
1604
+ function registerSessionHistoryTools(caps, bundle, cfg) {
1605
+ const { platform, logger, sessionHistory } = caps;
1582
1606
  const { daily } = bundle;
1583
1607
  daily.register({
1584
1608
  definition: {
@@ -1612,7 +1636,7 @@ function registerSessionHistoryTools(ctx, bundle, cfg) {
1612
1636
  if (!targetId)
1613
1637
  return JSON.stringify({ error: 'target_id 不能为空' });
1614
1638
  const argSelfId = args.self_id ? String(args.self_id).trim() : '';
1615
- const selfId = argSelfId || current?.selfId || getAnyOneBotSelfId(ctx) || '';
1639
+ const selfId = argSelfId || current?.selfId || getAnyOneBotSelfId(platform) || '';
1616
1640
  if (!selfId)
1617
1641
  return JSON.stringify({ error: '无法确定 self_id,且未找到可用的 OneBot 连接' });
1618
1642
  // 跨账号限制:仅在当前也是 OneBot 会话时才作为参考点检查
@@ -1672,10 +1696,10 @@ function registerSessionHistoryTools(ctx, bundle, cfg) {
1672
1696
  if (!targetId)
1673
1697
  return JSON.stringify({ error: 'target_id 不能为空' });
1674
1698
  const argSelfId = args.self_id ? String(args.self_id).trim() : '';
1675
- const selfId = argSelfId || current?.selfId || getAnyOneBotSelfId(ctx) || '';
1699
+ const selfId = argSelfId || current?.selfId || getAnyOneBotSelfId(platform) || '';
1676
1700
  if (!selfId)
1677
1701
  return JSON.stringify({ error: '无法确定 self_id,且未找到可用的 OneBot 连接' });
1678
- const history = ctx.getService('session-history');
1702
+ const history = sessionHistory.current;
1679
1703
  if (!history)
1680
1704
  return JSON.stringify({
1681
1705
  error: 'session-history 服务不可用,请启用 @aalis/plugin-tool-session',
@@ -1698,19 +1722,20 @@ function registerSessionHistoryTools(ctx, bundle, cfg) {
1698
1722
  }
1699
1723
  catch (err) {
1700
1724
  const message = err instanceof Error ? err.message : String(err);
1701
- ctx.logger.warn(`onebot_get_session_history 失败 (${sessionId}): ${message}`);
1725
+ logger.warn(`onebot_get_session_history 失败 (${sessionId}): ${message}`);
1702
1726
  return JSON.stringify({ error: `读取 OneBot 会话历史失败: ${message}` });
1703
1727
  }
1704
1728
  },
1705
1729
  });
1706
- ctx.logger.info('OneBot 会话历史工具已注册');
1730
+ logger.info('OneBot 会话历史工具已注册');
1707
1731
  }
1708
1732
  // ===== 请求处理工具(好友申请 / 群请求)=====
1709
- function registerRequestTools(ctx, bundle) {
1733
+ function registerRequestTools(caps, bundle) {
1734
+ const { platform, logger } = caps;
1710
1735
  const { group, personal } = bundle;
1711
1736
  /** 找到支持 handleFriendRequest 的 OneBot 适配器 */
1712
- function findRequestAdapter(ctx) {
1713
- const adapter = getPlatformAdapters(ctx).find(a => a.platform === 'onebot' && typeof a.handleFriendRequest === 'function');
1737
+ function findRequestAdapter(platform) {
1738
+ const adapter = getPlatformAdapters(platform).find(a => a.platform === 'onebot' && typeof a.handleFriendRequest === 'function');
1714
1739
  return adapter;
1715
1740
  }
1716
1741
  personal.register({
@@ -1731,7 +1756,7 @@ function registerRequestTools(ctx, bundle) {
1731
1756
  },
1732
1757
  },
1733
1758
  handler: async (args) => {
1734
- const adapter = findRequestAdapter(ctx);
1759
+ const adapter = findRequestAdapter(platform);
1735
1760
  if (!adapter)
1736
1761
  return '未找到支持请求处理的 OneBot 适配器';
1737
1762
  return adapter.handleFriendRequest(String(args.user_id), !!args.approve, args.remark ? String(args.remark) : undefined);
@@ -1760,7 +1785,7 @@ function registerRequestTools(ctx, bundle) {
1760
1785
  },
1761
1786
  },
1762
1787
  handler: async (args) => {
1763
- const adapter = findRequestAdapter(ctx);
1788
+ const adapter = findRequestAdapter(platform);
1764
1789
  if (!adapter)
1765
1790
  return '未找到支持请求处理的 OneBot 适配器';
1766
1791
  return adapter.handleGroupRequest(String(args.user_id), String(args.group_id), !!args.approve, args.reason ? String(args.reason) : undefined);
@@ -1785,12 +1810,12 @@ function registerRequestTools(ctx, bundle) {
1785
1810
  },
1786
1811
  },
1787
1812
  handler: async (args) => {
1788
- const adapter = findRequestAdapter(ctx);
1813
+ const adapter = findRequestAdapter(platform);
1789
1814
  if (!adapter)
1790
1815
  return '未找到支持请求处理的 OneBot 适配器';
1791
1816
  return adapter.handleGroupRequest(String(args.user_id), String(args.group_id), !!args.approve, args.reason ? String(args.reason) : undefined);
1792
1817
  },
1793
1818
  });
1794
- ctx.logger.info('OneBot 请求处理工具已注册');
1819
+ logger.info('OneBot 请求处理工具已注册');
1795
1820
  }
1796
1821
  //# sourceMappingURL=index.js.map