chatluna-plugin-onebot-toolbox 0.0.1 → 0.0.2

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/lib/config.d.ts CHANGED
@@ -27,10 +27,7 @@ export interface Config {
27
27
  };
28
28
  debugLogging: boolean;
29
29
  }
30
- /**
31
- * 原生工具的名称与描述,与源插件的默认值一致。插件不提供改名、改描述或开关工具的配置,
32
- * 工具全部注册,启用范围交给 v2 的工具管理。
33
- */
30
+ /** 原生工具的名称与描述固定,全部注册;启用范围交给 v2 的工具管理。 */
34
31
  export declare const NATIVE_TOOLS: Record<NativeToolKey, NativeToolInfo>;
35
32
  export declare const NATIVE_TOOL_KEYS: NativeToolKey[];
36
33
  export declare const DEFAULT_MEMBER_INFO_ITEMS: MemberInfoItem[];
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAEzC,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAA;AAE5D,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,mBAAmB,GACnB,YAAY,GACZ,eAAe,GACf,cAAc,GACd,sBAAsB,GACtB,eAAe,CAAA;AAEnB,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,UAAU,GACV,MAAM,GACN,OAAO,GACP,OAAO,GACP,QAAQ,GACR,KAAK,GACL,MAAM,GACN,UAAU,GACV,cAAc,CAAA;AAElB,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,CAAA;AAE9G,MAAM,WAAW,MAAM;IACrB,cAAc,EAAE,cAAc,CAAA;IAC9B,aAAa,EAAE,OAAO,CAAA;IACtB,QAAQ,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,cAAc,EAAE,CAAA;KAAE,CAAA;IAC3D,OAAO,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,cAAc,EAAE,CAAA;KAAE,CAAA;IAC1D,SAAS,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,aAAa,EAAE,CAAA;KAAE,CAAA;IAC3D,aAAa,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAA;IACvC,YAAY,EAAE,OAAO,CAAA;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,aAAa,EAAE,cAAc,CAqC9D,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAgC,aAAa,EAAE,CAAA;AAE5E,eAAO,MAAM,yBAAyB,EAAE,cAAc,EAErD,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,aAAa,EAAsE,CAAA;AA+D1H;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,CAIhC,CAAA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAEzC,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAA;AAE5D,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAChB,aAAa,GACb,cAAc,GACd,mBAAmB,GACnB,YAAY,GACZ,eAAe,GACf,cAAc,GACd,sBAAsB,GACtB,eAAe,CAAA;AAEnB,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,UAAU,GACV,MAAM,GACN,OAAO,GACP,OAAO,GACP,QAAQ,GACR,KAAK,GACL,MAAM,GACN,UAAU,GACV,cAAc,CAAA;AAElB,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,CAAA;AAE9G,MAAM,WAAW,MAAM;IACrB,cAAc,EAAE,cAAc,CAAA;IAC9B,aAAa,EAAE,OAAO,CAAA;IACtB,QAAQ,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,cAAc,EAAE,CAAA;KAAE,CAAA;IAC3D,OAAO,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,cAAc,EAAE,CAAA;KAAE,CAAA;IAC1D,SAAS,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,aAAa,EAAE,CAAA;KAAE,CAAA;IAC3D,aAAa,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAA;IACvC,YAAY,EAAE,OAAO,CAAA;CACtB;AAED,yCAAyC;AACzC,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,aAAa,EAAE,cAAc,CAqC9D,CAAA;AAED,eAAO,MAAM,gBAAgB,EAAgC,aAAa,EAAE,CAAA;AAE5E,eAAO,MAAM,yBAAyB,EAAE,cAAc,EAErD,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,aAAa,EAAsE,CAAA;AA+D1H;;;GAGG;AACH,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,CAIhC,CAAA"}
package/lib/index.js CHANGED
@@ -10,10 +10,7 @@ function createLogger(ctx, debugLogging) {
10
10
  };
11
11
  }
12
12
  // external/onebot-toolbox/src/config.ts
13
- /**
14
- * 原生工具的名称与描述,与源插件的默认值一致。插件不提供改名、改描述或开关工具的配置,
15
- * 工具全部注册,启用范围交给 v2 的工具管理。
16
- */
13
+ /** 原生工具的名称与描述固定,全部注册;启用范围交给 v2 的工具管理。 */
17
14
  const NATIVE_TOOLS = {
18
15
  setSelfProfile: {
19
16
  toolName: "set_self_profile",
@@ -188,24 +185,18 @@ function registerRequestNotices(ctx, config, log) {
188
185
  }
189
186
  // external/onebot-toolbox/src/onebot.ts
190
187
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
191
- /** 会话所在的 OneBot 机器人;不是 OneBot 会话或机器人已离线时为 undefined。 */
188
+ /** 会话所在的 OneBot 机器人;不是 OneBot 会话或找不到机器人时为 undefined。 */
192
189
  function oneBotOf(ctx, platform, selfId) {
193
190
  if (platform !== "onebot" || selfId === void 0) return void 0;
194
191
  return ctx.satori.bots.find((bot) => bot.platform === "onebot" && bot.selfId === selfId);
195
192
  }
196
- /**
197
- * 调用 OneBot action 并返回 `data`。OneBot 的业务错误以正常 resolve 的响应包返回,这里按 status 与 retcode
198
- * 判定失败并抛出,错误信息取实现给出的 wording/message。
199
- */
193
+ /** 调用 OneBot action 并返回 data,按响应包的 status 与 retcode 判定业务失败。 */
200
194
  async function callOneBot(bot, action, params) {
201
195
  const result = await bot.internal._request(action, params);
202
- if (!isRecord(result)) return result;
203
- const envelope = result;
204
- const status = String(envelope.status ?? "").toLowerCase();
205
- if (!(status !== "" && status !== "ok" || typeof envelope.retcode === "number" && envelope.retcode !== 0)) return envelope.data;
206
- const reason = envelope.wording || envelope.message || envelope.status;
207
- const retcode = typeof envelope.retcode === "number" ? ` (retcode: ${envelope.retcode})` : "";
208
- throw new Error(`${reason ? String(reason) : "OneBot returned failed"}${retcode}`);
196
+ if (!isRecord(result) || typeof result.status !== "string" || typeof result.retcode !== "number") throw new Error("Invalid OneBot response envelope");
197
+ if (result.status === "ok" && result.retcode === 0) return result.data;
198
+ const reason = result.wording || result.message || result.status || "OneBot returned failed";
199
+ throw new Error(`${String(reason)} (retcode: ${result.retcode})`);
209
200
  }
210
201
  /**
211
202
  * 整数形式的 ID 转成数字,其余原样保留;OneBot 实现普遍要求数字形式的群号、QQ 号与消息 ID。
@@ -225,7 +216,7 @@ function pickFirst(...values) {
225
216
  function pickText(...values) {
226
217
  return String(pickFirst(...values) ?? "").trim();
227
218
  }
228
- /** OneBot 时间戳可能是秒或毫秒,统一成毫秒;空值与 0 视为没有。 */
219
+ /** OneBot 使用秒,Satori 使用毫秒,统一成毫秒;空值与 0 视为没有。 */
229
220
  function normalizeTimestamp(raw) {
230
221
  if (raw === null || raw === void 0 || raw === "") return void 0;
231
222
  const numeric = Number(raw);
@@ -248,22 +239,9 @@ function formatDateTime(value) {
248
239
  function asMembers(value) {
249
240
  return Array.isArray(value) ? value.filter(isRecord) : [];
250
241
  }
251
- function asMember(value) {
242
+ function asRecord(value) {
252
243
  return isRecord(value) ? value : void 0;
253
244
  }
254
- function memberUserId(member) {
255
- return pickText(member.user_id, member.userId, member.id, member.qq, member.uid);
256
- }
257
- function memberCard(member) {
258
- return pickText(member.card, member.remark, member.displayName);
259
- }
260
- function memberNickname(member) {
261
- return pickText(member.nick, member.nickname, member.name, member.user?.nickname, member.user?.name);
262
- }
263
- function memberRole(member) {
264
- const roles = Array.isArray(member.roles) ? member.roles : [];
265
- return pickText(member.role, member.roleName, member.permission, member.identity, roles[0]);
266
- }
267
245
  // external/onebot-toolbox/src/tools.ts
268
246
  const MISSING_GROUP = "Missing groupId. Provide groupId explicitly or run inside a group session.";
269
247
  const MAX_MEMBER_RESULTS = 10;
@@ -340,7 +318,7 @@ async function avatarFile(scope, image) {
340
318
  return image;
341
319
  }
342
320
  function formatMember(index, member) {
343
- return `${index}. qqid:${memberUserId(member) || "未知"},群昵称:${memberCard(member) || "无"},QQ昵称:${memberNickname(member) || "无"}`;
321
+ return `${index}. qqid:${pickText(member.user_id) || "未知"},群昵称:${pickText(member.card) || "无"},QQ昵称:${pickText(member.nickname) || "无"}`;
344
322
  }
345
323
  const NATIVE_TOOL_IMPLEMENTATIONS = {
346
324
  setSelfProfile: {
@@ -409,7 +387,7 @@ const NATIVE_TOOL_IMPLEMENTATIONS = {
409
387
  const members = asMembers(await callOneBot(scope.bot, "get_group_member_list", { group_id: numericId(groupId) }));
410
388
  const byQQ = mode === "byQQ" || mode === "auto" && /^\d+$/.test(query);
411
389
  const keyword = query.toLowerCase();
412
- const matches = members.filter((member) => byQQ ? memberUserId(member) === query : [memberCard(member), memberNickname(member)].some((name) => name && name.toLowerCase().includes(keyword)));
390
+ const matches = members.filter((member) => byQQ ? pickText(member.user_id) === query : [pickText(member.card), pickText(member.nickname)].some((name) => name && name.toLowerCase().includes(keyword)));
413
391
  if (!matches.length) return "未找到匹配的群成员。";
414
392
  return [matches.length > MAX_MEMBER_RESULTS ? `仅显示前 ${MAX_MEMBER_RESULTS} 条,共 ${matches.length} 条匹配:` : `找到 ${matches.length} 个匹配成员:`, ...matches.slice(0, MAX_MEMBER_RESULTS).map((member, index) => formatMember(index + 1, member))].join("\n");
415
393
  }
@@ -509,7 +487,7 @@ const NATIVE_TOOL_IMPLEMENTATIONS = {
509
487
  }
510
488
  }
511
489
  };
512
- /** 全部原生工具的定义,名称与描述固定为源插件的默认值。 */
490
+ /** 全部原生工具的定义,名称与描述统一取自 NATIVE_TOOLS。 */
513
491
  function nativeToolDefinitions(ctx, config, log) {
514
492
  return NATIVE_TOOL_KEYS.map((key) => {
515
493
  const tool = NATIVE_TOOL_IMPLEMENTATIONS[key];
@@ -544,7 +522,7 @@ function nativeToolDefinitions(ctx, config, log) {
544
522
  }
545
523
  /**
546
524
  * 注册原生工具。工具对所有会话全局可见(v2 的工具管理页因此能列出并开关它们),
547
- * 再给不在 OneBot 上的 agent 挂一层排除过滤,与源插件只在 OneBot 会话授权一致。
525
+ * 再给不在 OneBot 上的 agent 挂一层排除过滤。
548
526
  */
549
527
  function registerNativeTools(ctx, config, log) {
550
528
  const definitions = nativeToolDefinitions(ctx, config, log);
@@ -564,51 +542,14 @@ const FALLBACK_MEMBER_ITEMS = ["nickname", "userId"];
564
542
  const SHUT_LIST_TIMEOUT_MS = 200;
565
543
  const SHUT_LIST_CACHE_TTL_MS = 15e3;
566
544
  function translateGender(value) {
567
- if (value === null || value === void 0) return "";
568
- const text = String(value).trim().toLowerCase();
569
- if (!text) return "";
570
- if ([
571
- "male",
572
- "man",
573
- "m",
574
- "1",
575
- "boy"
576
- ].includes(text)) return "男";
577
- if ([
578
- "female",
579
- "woman",
580
- "f",
581
- "2",
582
- "girl"
583
- ].includes(text)) return "女";
584
- if ([
585
- "未知",
586
- "unknown",
587
- "0",
588
- "secret"
589
- ].includes(text)) return "";
590
- return String(value);
545
+ if (value === "male") return "男";
546
+ if (value === "female") return "女";
547
+ return "";
591
548
  }
592
549
  function normalizeRole(value) {
593
- const text = value.toLowerCase();
594
- if (!text) return "群员";
595
- if ([
596
- "owner",
597
- "group_owner",
598
- "群主"
599
- ].includes(text)) return "群主";
600
- if ([
601
- "admin",
602
- "administrator",
603
- "group_admin",
604
- "管理员"
605
- ].includes(text)) return "管理员";
606
- if ([
607
- "member",
608
- "normal",
609
- "群员"
610
- ].includes(text)) return "群员";
611
- return value;
550
+ if (value === "owner") return "群主";
551
+ if (value === "admin") return "管理员";
552
+ return !value || value === "member" ? "群员" : value;
612
553
  }
613
554
  /** 会话所在的 Satori 机器人,任意平台;预览等没有真实机器人的环境里为 undefined。 */
614
555
  function botOf(ctx, env) {
@@ -619,12 +560,20 @@ async function fetchMember(ctx, env, userId) {
619
560
  const bot = botOf(ctx, env);
620
561
  if (!bot || !env.guildId) return void 0;
621
562
  try {
622
- if (bot.platform === "onebot") return asMember(await callOneBot(bot, "get_group_member_info", {
563
+ if (bot.platform === "onebot") return asRecord(await callOneBot(bot, "get_group_member_info", {
623
564
  group_id: Number(env.guildId),
624
565
  user_id: Number(userId),
625
566
  no_cache: false
626
567
  }));
627
- return asMember(await bot.getGuildMember(env.guildId, userId));
568
+ const member = await bot.getGuildMember(env.guildId, userId);
569
+ return {
570
+ user_id: member.user?.id,
571
+ card: pickText(member.nick, member.name),
572
+ nickname: member.user?.name,
573
+ role: member.roles?.[0]?.id,
574
+ title: member.title,
575
+ join_time: member.joinedAt
576
+ };
628
577
  } catch {
629
578
  return;
630
579
  }
@@ -634,7 +583,7 @@ function renderMember(member, items, id, fallbackName) {
634
583
  const values = [];
635
584
  for (const item of items) switch (item) {
636
585
  case "nickname": {
637
- const name = pickText(member?.card, member?.remark, member?.displayName, member?.nick, member?.nickname, member?.name, fallbackName, id);
586
+ const name = pickText(member?.card, member?.nickname, fallbackName, id);
638
587
  if (name) values.push(`name:${name}`);
639
588
  break;
640
589
  }
@@ -642,20 +591,20 @@ function renderMember(member, items, id, fallbackName) {
642
591
  if (id) values.push(`id:${id}`);
643
592
  break;
644
593
  case "role":
645
- values.push(`群内身份:${normalizeRole(member ? memberRole(member) : "")}`);
594
+ values.push(`群内身份:${normalizeRole(pickText(member?.role))}`);
646
595
  break;
647
596
  case "level": {
648
- const level = pickFirst(member?.level, member?.levelName, member?.level_name, member?.level_info?.current_level);
597
+ const level = pickFirst(member?.level);
649
598
  if (level !== void 0) values.push(`群等级:${level}`);
650
599
  break;
651
600
  }
652
601
  case "title": {
653
- const title = pickFirst(member?.title, member?.specialTitle, member?.special_title);
602
+ const title = pickFirst(member?.title);
654
603
  if (title !== void 0) values.push(`头衔:${title}`);
655
604
  break;
656
605
  }
657
606
  case "gender": {
658
- const gender = translateGender(member?.sex ?? member?.gender);
607
+ const gender = translateGender(member?.sex);
659
608
  if (gender) values.push(`性别:${gender}`);
660
609
  break;
661
610
  }
@@ -665,17 +614,17 @@ function renderMember(member, items, id, fallbackName) {
665
614
  break;
666
615
  }
667
616
  case "area": {
668
- const area = pickFirst(member?.area, member?.region, member?.location);
617
+ const area = pickFirst(member?.area);
669
618
  if (area !== void 0) values.push(`地区:${area}`);
670
619
  break;
671
620
  }
672
621
  case "joinTime": {
673
- const joinTime = formatDate(normalizeTimestamp(pickFirst(member?.join_time, member?.joined_at, member?.joinTime, member?.joinedAt)));
622
+ const joinTime = formatDate(normalizeTimestamp(member?.join_time));
674
623
  if (joinTime) values.push(`入群:${joinTime}`);
675
624
  break;
676
625
  }
677
626
  case "lastSentTime": {
678
- const lastSentTime = formatDateTime(normalizeTimestamp(pickFirst(member?.last_sent_time, member?.lastSentTime, member?.lastSpeakTimestamp)));
627
+ const lastSentTime = formatDateTime(normalizeTimestamp(member?.last_sent_time));
679
628
  if (lastSentTime) values.push(`活跃:${lastSentTime}`);
680
629
  break;
681
630
  }
@@ -706,20 +655,12 @@ async function fetchRoles(bot, guildId, log) {
706
655
  const owners = [];
707
656
  const admins = [];
708
657
  for (const member of members) {
709
- const role = memberRole(member).toLowerCase();
710
- const userId = memberUserId(member);
711
- const name = pickText(memberCard(member), memberNickname(member)) || userId;
658
+ const role = member.role;
659
+ const userId = pickText(member.user_id);
660
+ const name = pickText(member.card, member.nickname, userId);
712
661
  const label = userId ? `${name}(${userId})` : name;
713
- if ([
714
- "owner",
715
- "master",
716
- "leader"
717
- ].includes(role)) owners.push(label);
718
- else if ([
719
- "admin",
720
- "administrator",
721
- "manager"
722
- ].includes(role)) admins.push(label);
662
+ if (role === "owner") owners.push(label);
663
+ else if (role === "admin") admins.push(label);
723
664
  }
724
665
  return {
725
666
  owners,
@@ -731,10 +672,10 @@ async function fetchRoles(bot, guildId, log) {
731
672
  }
732
673
  }
733
674
  function renderGroupInfo(group, items, roles) {
734
- const id = pickText(group.group_id, group.groupId, group.id);
735
- const name = pickText(group.group_name, group.groupName, group.name);
736
- const memberCount = group.member_count ?? group.memberCount ?? group.max_member_count;
737
- const createTime = formatDate(normalizeTimestamp(group.create_time ?? group.createTime ?? group.group_create_time));
675
+ const id = pickText(group.group_id);
676
+ const name = pickText(group.group_name);
677
+ const memberCount = group.member_count;
678
+ const createTime = formatDate(normalizeTimestamp(group.create_time ?? group.group_create_time));
738
679
  const values = [];
739
680
  for (const item of items) switch (item) {
740
681
  case "groupName":
@@ -766,42 +707,28 @@ function groupInfoProvider(ctx, config, log) {
766
707
  const group = await callOneBot(bot, "get_group_info", {
767
708
  group_id: Number(env.guildId),
768
709
  no_cache: false
769
- }).then(asMember, () => void 0);
710
+ }).then(asRecord, () => void 0);
770
711
  if (!group) return "未能获取当前群信息。";
771
712
  return renderGroupInfo(group, items, items.includes("ownerList") || items.includes("adminList") ? await fetchRoles(bot, env.guildId, log) : void 0);
772
713
  };
773
714
  }
774
715
  var ShutListTimeout = class extends Error {};
775
- /** 群号类型不被接受时的报错特征:NapCat 要数字、LLBot 要字符串,类型不对时换另一种再试一次。 */
776
- const WRONG_ID_TYPE = /string|number|type|invalid|参数/i;
777
716
  function withTimeout(promise, ms) {
778
717
  let timer;
779
718
  return Promise.race([promise, new Promise((_, reject) => {
780
719
  timer = setTimeout(() => reject(new ShutListTimeout("group shut list request timed out")), ms);
781
720
  })]).finally(() => clearTimeout(timer));
782
721
  }
783
- async function fetchShutList(bot, guildId, protocol, log) {
784
- const preferred = protocol === "llbot" ? guildId : Number(guildId);
785
- const fallback = protocol === "llbot" ? Number(guildId) : guildId;
786
- const request = async (groupId) => {
787
- const data = await withTimeout(callOneBot(bot, "get_group_shut_list", { group_id: groupId }), SHUT_LIST_TIMEOUT_MS);
788
- return Array.isArray(data) ? data : [];
789
- };
790
- try {
791
- return await request(preferred);
792
- } catch (error) {
793
- if (error instanceof ShutListTimeout || !(error instanceof Error) || !WRONG_ID_TYPE.test(error.message)) throw error;
794
- log.debug("group shut list retries with %s group id: %s", typeof fallback, error.message);
795
- return request(fallback);
796
- }
722
+ async function fetchShutList(bot, guildId, protocol) {
723
+ const data = await withTimeout(callOneBot(bot, "get_group_shut_list", { group_id: protocol === "llbot" ? guildId : Number(guildId) }), SHUT_LIST_TIMEOUT_MS);
724
+ return Array.isArray(data) ? data : [];
797
725
  }
798
726
  function renderShutItem(item) {
799
- const record = asMember(item);
727
+ const record = asRecord(item);
800
728
  if (!record) return void 0;
801
- const field = (key) => Reflect.get(record, key);
802
- const userId = pickText(field("uin"), field("user_id"));
729
+ const userId = pickText(record.uin, record.user_id);
803
730
  if (!userId) return void 0;
804
- return `id:${userId},name:${pickText(field("cardName"), field("remark"), field("nick"), field("nickname"), userId)},禁言截至:${formatDateTime(normalizeTimestamp(pickFirst(field("shutUpTime"), field("shut_up_time")))) || "未知"}`;
731
+ return `id:${userId},name:${pickText(record.cardName, record.remark, record.nick, record.nickname, userId)},禁言截至:${formatDateTime(normalizeTimestamp(pickFirst(record.shutUpTime, record.shut_up_time))) || "未知"}`;
805
732
  }
806
733
  function groupShutListProvider(ctx, config, log) {
807
734
  const cache = /* @__PURE__ */ new Map();
@@ -814,7 +741,7 @@ function groupShutListProvider(ctx, config, log) {
814
741
  const cached = cache.get(key);
815
742
  if (cached && cached.expiresAt > Date.now()) return cached.value;
816
743
  try {
817
- const lines = (await fetchShutList(bot, env.guildId, config.oneBotProtocol, log)).flatMap((item) => renderShutItem(item) ?? []);
744
+ const lines = (await fetchShutList(bot, env.guildId, config.oneBotProtocol)).flatMap((item) => renderShutItem(item) ?? []);
818
745
  const value = lines.length ? lines.join("\n") : "当前群暂无禁言成员。";
819
746
  cache.set(key, {
820
747
  value,
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/logger.ts","../src/config.ts","../src/requests.ts","../src/onebot.ts","../src/tools.ts","../src/variables.ts","../src/index.ts"],"sourcesContent":["import type { Context } from 'cordis'\n\n/** 插件内的日志:`debugLogging` 打开时调试信息以 info 级别输出,否则走 logger 自己的 debug 级别。 */\nexport interface Logger {\n debug(format: string, ...args: unknown[]): void\n info(format: string, ...args: unknown[]): void\n warn(format: string, ...args: unknown[]): void\n}\n\nexport function createLogger(ctx: Context, debugLogging: boolean): Logger {\n const logger = ctx.logger\n return {\n debug: (format, ...args) => (debugLogging ? logger.info(format, ...args) : logger.debug(format, ...args)),\n info: (format, ...args) => logger.info(format, ...args),\n warn: (format, ...args) => logger.warn(format, ...args),\n }\n}\n","import { Schema } from '@chatluna/schema'\n\nexport type OneBotProtocol = 'napcat' | 'llbot' | 'snowluma'\n\nexport type NativeToolKey =\n | 'setSelfProfile'\n | 'setQQAvatar'\n | 'setGroupCard'\n | 'searchGroupMember'\n | 'leaveGroup'\n | 'handleRequest'\n | 'setGroupKick'\n | 'setGroupSpecialTitle'\n | 'deleteMessage'\n\nexport interface NativeToolInfo {\n toolName: string\n description: string\n}\n\nexport type MemberInfoItem =\n | 'userId'\n | 'nickname'\n | 'role'\n | 'level'\n | 'title'\n | 'gender'\n | 'age'\n | 'area'\n | 'joinTime'\n | 'lastSentTime'\n\nexport type GroupInfoItem = 'groupName' | 'groupId' | 'memberCount' | 'createTime' | 'ownerList' | 'adminList'\n\nexport interface Config {\n oneBotProtocol: OneBotProtocol\n requestNotice: boolean\n userInfo: { variableName: string, items: MemberInfoItem[] }\n botInfo: { variableName: string, items: MemberInfoItem[] }\n groupInfo: { variableName: string, items: GroupInfoItem[] }\n groupShutList: { variableName: string }\n debugLogging: boolean\n}\n\n/**\n * 原生工具的名称与描述,与源插件的默认值一致。插件不提供改名、改描述或开关工具的配置,\n * 工具全部注册,启用范围交给 v2 的工具管理。\n */\nexport const NATIVE_TOOLS: Record<NativeToolKey, NativeToolInfo> = {\n setSelfProfile: {\n toolName: 'set_self_profile',\n description: '修改自己的 QQ 资料,可设置昵称、签名和性别。',\n },\n setQQAvatar: {\n toolName: 'set_qq_avatar',\n description: '修改机器人 QQ 头像。imageUrl 填会话里图片的 ref(`<img ref=\"i…\"/>` 的 ref 属性)、HTTP/HTTPS 链接或 OneBot 端可读的本地路径;会话图片与 HTTP/HTTPS 图片会先由插件读取并转为 OneBot base64 文件,避免临时 URL 过期或 OneBot 端无法访问。',\n },\n setGroupCard: {\n toolName: 'set_group_card',\n description: '修改群成员的群昵称。',\n },\n searchGroupMember: {\n toolName: 'search_group_member',\n description: '根据 qqid 精确查询群成员的群昵称与 QQ 昵称,或根据群昵称/QQ 昵称搜索 qqid。默认查询当前群聊,可通过 groupId 查询指定群。',\n },\n leaveGroup: {\n toolName: 'set_group_leave',\n description: '让机器人退出当前群聊。',\n },\n handleRequest: {\n toolName: 'handle_request',\n description: '根据 OneBot 申请 flag 同意或拒绝好友申请、加群申请或群邀请。',\n },\n setGroupKick: {\n toolName: 'set_group_kick',\n description: '将指定成员踢出群聊。',\n },\n setGroupSpecialTitle: {\n toolName: 'set_group_special_title',\n description: '修改或清除群成员的 QQ 群专属头衔。',\n },\n deleteMessage: {\n toolName: 'delete_msg',\n description: '根据消息 ID 撤回指定消息。',\n },\n}\n\nexport const NATIVE_TOOL_KEYS = Object.keys(NATIVE_TOOLS) as NativeToolKey[]\n\nexport const DEFAULT_MEMBER_INFO_ITEMS: MemberInfoItem[] = [\n 'nickname', 'userId', 'role', 'level', 'title', 'gender', 'age', 'area', 'joinTime', 'lastSentTime',\n]\n\nexport const DEFAULT_GROUP_INFO_ITEMS: GroupInfoItem[] = ['groupName', 'groupId', 'memberCount', 'ownerList', 'adminList']\n\n/** 变量名须满足 v2 模板的变量命名规则(`@chatluna/prompt` 的 `variable`),留空表示不注册。 */\nconst VARIABLE_NAME = /^([a-z_][a-z0-9_]*)?$/i\n\nconst memberItems = (subject: string) => Schema.array(Schema.union([\n Schema.const('userId').description(`${subject} ID`),\n Schema.const('nickname').description('群昵称'),\n Schema.const('role').description('群内身份'),\n Schema.const('level').description('群等级'),\n Schema.const('title').description('群头衔'),\n Schema.const('gender').description('性别'),\n Schema.const('age').description('年龄'),\n Schema.const('area').description('地区'),\n Schema.const('joinTime').description('入群时间'),\n Schema.const('lastSentTime').description('最后发言时间'),\n])).role('checkbox').default([...DEFAULT_MEMBER_INFO_ITEMS])\n\nconst variableName = (name: string) => Schema.string().default(name).pattern(VARIABLE_NAME).extra('label', '变量名称')\n .description('在预设中以`{变量名称}`引用,留空时不注册')\n\nconst basicFields = {\n oneBotProtocol: Schema.union([\n Schema.const('napcat').description('NapCat'),\n Schema.const('llbot').description('LLBot'),\n Schema.const('snowluma').description('SnowLuma'),\n ]).default('napcat').role('radio').extra('label', 'OneBot 协议')\n .description('按所选实现调整请求参数:LLBot 不支持设置性别,群禁言列表的群号类型也不同;SnowLuma 同意好友申请后另行设置备注'),\n requestNotice: Schema.boolean().default(true).extra('label', '申请通知')\n .description('收到好友申请、加群申请或群邀请时唤醒对应会话,把申请 flag 告诉模型,供`handle_request`工具处理。好友申请与群邀请发往申请人的私聊,加群申请发往所申请的群;该工具在工具管理中禁用时不唤醒'),\n}\n\nconst variableFields = {\n userInfo: Schema.object({\n variableName: variableName('userInfo'),\n items: memberItems('用户').extra('label', '信息项').description('选择用户信息变量中显示的详细信息项'),\n }).description('用户信息变量').collapse(),\n botInfo: Schema.object({\n variableName: variableName('botInfo'),\n items: memberItems('机器人').extra('label', '信息项').description('选择机器人信息变量中显示的详细信息项'),\n }).description('机器人信息变量').collapse(),\n groupInfo: Schema.object({\n variableName: variableName('groupInfo'),\n items: Schema.array(Schema.union([\n Schema.const('groupName').description('群名称'),\n Schema.const('groupId').description('群号'),\n Schema.const('memberCount').description('成员数量'),\n Schema.const('createTime').description('创建时间(仅部分实现支持)'),\n Schema.const('ownerList').description('群主名单'),\n Schema.const('adminList').description('管理员名单'),\n ])).role('checkbox').default([...DEFAULT_GROUP_INFO_ITEMS]).extra('label', '信息项')\n .description('选择群信息变量中显示的群信息项'),\n }).description('群信息变量').collapse(),\n groupShutList: Schema.object({\n variableName: variableName('groupShutList'),\n }).description('群禁言列表变量').collapse(),\n}\n\nconst otherFields = {\n debugLogging: Schema.boolean().default(false).extra('label', '输出调试日志')\n .description('以 info 级别输出工具调用与变量解析的调试信息'),\n}\n\n/**\n * 插件配置,直接在 v2 的插件设置页编辑。顶层是分组的 intersect,SchemaForm 把每组的 description 渲染成小节标题;\n * 每个字段都写 `extra('label')`,缺 label 时 SchemaForm 会把配置键当标题显示。\n */\nexport const Config: Schema<Config> = Schema.intersect([\n Schema.object(basicFields).description('基础设置'),\n Schema.object(variableFields).description('变量'),\n Schema.object(otherFields).description('其他设置'),\n])\n","import type { Context } from 'cordis'\nimport type { Session } from '@satorijs/core'\nimport type { RouteIdentity } from '@chatluna/satori'\nimport type {} from '@chatluna/chat'\nimport type { Config } from './config'\nimport { NATIVE_TOOLS } from './config'\nimport type { Logger } from './logger'\n\ntype RequestKind = 'friend' | 'add' | 'invite'\n\n/**\n * 申请发往的会话:好友申请与群邀请发往申请人的私聊,加群申请发往所申请的群。\n * 用路由身份而不是事件 Session 唤醒:申请事件不是消息,申请人与机器人之间往往还没有会话,\n * `chat.wake` 会按身份新开一个。\n */\nexport function requestTarget(session: Session, kind: RequestKind): RouteIdentity | undefined {\n if (!session.userId) return undefined\n if (kind === 'add') {\n if (!session.guildId) return undefined\n return { platform: session.platform, selfId: session.selfId, isDirect: false, guildId: session.guildId, channelId: session.guildId, userId: session.userId }\n }\n return { platform: session.platform, selfId: session.selfId, isDirect: true, channelId: `private:${session.userId}`, userId: session.userId }\n}\n\n/** 唤醒原因即模型看到的通知,写明 flag 与调用方式,模型据此调用处理申请工具。 */\nexport function requestReason(session: Session, kind: RequestKind, toolName: string): string {\n const comment = session.content?.trim() ? `, message: ${JSON.stringify(session.content.trim())}` : ''\n const flag = `flag: ${JSON.stringify(session.messageId ?? '')}`\n if (kind === 'friend') {\n return `user ${session.userId} sent you a friend request (${flag}${comment}). Call ${toolName} with requestType \"friend\" and userId \"${session.userId}\" to approve or reject it`\n }\n if (kind === 'add') {\n return `user ${session.userId} requested to join group ${session.guildId} (${flag}${comment}). Call ${toolName} with requestType \"group\" and subType \"add\" to approve or reject it`\n }\n return `user ${session.userId} invited you to join group ${session.guildId} (${flag}${comment}). Call ${toolName} with requestType \"group\" and subType \"invite\" to approve or reject it`\n}\n\n/**\n * v2 不把 OneBot 的申请事件交给模型,`handle_request` 拿不到 flag 就无从调用,\n * 所以把申请转成一次唤醒;工具在 v2 工具管理里被禁用时跟着不唤醒。会话所在路由关闭或没选模型时 `wake` 会报错,只记调试日志。\n */\nexport function registerRequestNotices(ctx: Context, config: Config, log: Logger) {\n if (!config.requestNotice) return\n const toolName = NATIVE_TOOLS.handleRequest.toolName\n ctx.inject(['chat'], (inner) => {\n const notify = (session: Session, kind: RequestKind) => {\n if (session.platform !== 'onebot') return\n // 没有 flag 时模型无从处理申请,唤醒只会让它拿空值反复试错。\n if (!session.messageId) return log.debug('%s request without flag ignored', kind)\n // 工具在 v2 工具管理里被禁用时(全局过滤排除了它)不唤醒:模型调用不到,唤醒只会让它白跑一轮。\n if (!inner.tools.list().some((tool) => tool.name === toolName)) return log.debug('%s request ignored: %s is disabled', kind, toolName)\n const target = requestTarget(session, kind)\n if (!target) return\n inner.chat.wake(target, { reason: requestReason(session, kind, toolName), by: 'onebot-toolbox' })\n .then(() => log.debug('%s request %s delivered', kind, session.messageId))\n .catch((error: unknown) => log.debug('%s request %s not delivered: %s', kind, session.messageId, String(error)))\n }\n inner.on('friend-request', (session) => notify(session, 'friend'))\n inner.on('guild-member-request', (session) => notify(session, 'add'))\n inner.on('guild-request', (session) => notify(session, 'invite'))\n })\n}\n","import type { Context } from 'cordis'\nimport type { Bot } from '@satorijs/core'\n\n/** Koishi OneBot 适配器的原始请求:返回完整的响应包,业务失败也照常 resolve。 */\nexport interface OneBotInternal {\n _request(action: string, params: Record<string, unknown>): Promise<unknown>\n}\n\ninterface OneBotEnvelope {\n status?: unknown\n retcode?: unknown\n wording?: unknown\n message?: unknown\n data?: unknown\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/** 会话所在的 OneBot 机器人;不是 OneBot 会话或机器人已离线时为 undefined。 */\nexport function oneBotOf(ctx: Context, platform: string | undefined, selfId: string | undefined): Bot | undefined {\n if (platform !== 'onebot' || selfId === undefined) return undefined\n return ctx.satori.bots.find((bot) => bot.platform === 'onebot' && bot.selfId === selfId)\n}\n\n/**\n * 调用 OneBot action 并返回 `data`。OneBot 的业务错误以正常 resolve 的响应包返回,这里按 status 与 retcode\n * 判定失败并抛出,错误信息取实现给出的 wording/message。\n */\nexport async function callOneBot(bot: Bot, action: string, params: Record<string, unknown>): Promise<unknown> {\n const internal: OneBotInternal = bot.internal\n const result: unknown = await internal._request(action, params)\n if (!isRecord(result)) return result\n const envelope: OneBotEnvelope = result\n const status = String(envelope.status ?? '').toLowerCase()\n const failed = (status !== '' && status !== 'ok') || (typeof envelope.retcode === 'number' && envelope.retcode !== 0)\n if (!failed) return envelope.data\n const reason = envelope.wording || envelope.message || envelope.status\n const retcode = typeof envelope.retcode === 'number' ? ` (retcode: ${envelope.retcode})` : ''\n throw new Error(`${reason ? String(reason) : 'OneBot returned failed'}${retcode}`)\n}\n\n/**\n * 整数形式的 ID 转成数字,其余原样保留;OneBot 实现普遍要求数字形式的群号、QQ 号与消息 ID。\n * SnowLuma 的 message_id 是 int32 哈希,常为负数,所以带负号的整数同样转换。\n */\nexport function numericId(value: string): string | number {\n return /^-?\\d+$/.test(value) ? Number(value) : value\n}\n\n/** 取第一个非空值(去掉首尾空白后不为空字符串),保留原始类型。 */\nexport function pickFirst(...values: unknown[]): string | number | undefined {\n for (const value of values) {\n if (value === null || value === undefined) continue\n if (!String(value).trim()) continue\n return typeof value === 'number' ? value : String(value)\n }\n return undefined\n}\n\nexport function pickText(...values: unknown[]): string {\n return String(pickFirst(...values) ?? '').trim()\n}\n\n/** OneBot 时间戳可能是秒或毫秒,统一成毫秒;空值与 0 视为没有。 */\nexport function normalizeTimestamp(raw: unknown): number | undefined {\n if (raw === null || raw === undefined || raw === '') return undefined\n const numeric = Number(raw)\n if (!Number.isFinite(numeric) || numeric === 0) return undefined\n return numeric < 1e11 ? numeric * 1000 : numeric\n}\n\nconst pad = (value: number) => String(value).padStart(2, '0')\n\nexport function formatDate(value: number | undefined): string {\n if (value === undefined) return ''\n const date = new Date(value)\n if (Number.isNaN(date.valueOf())) return ''\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`\n}\n\nexport function formatDateTime(value: number | undefined): string {\n const day = formatDate(value)\n if (!day || value === undefined) return day\n const date = new Date(value)\n return `${day} ${pad(date.getHours())}:${pad(date.getMinutes())}`\n}\n\n/** 群成员信息的常见字段;各 OneBot 实现与 Satori 的字段名不同,读取时逐个尝试。 */\nexport interface MemberInfo {\n user_id?: unknown\n userId?: unknown\n id?: unknown\n qq?: unknown\n uid?: unknown\n role?: unknown\n roleName?: unknown\n permission?: unknown\n identity?: unknown\n roles?: unknown\n card?: unknown\n remark?: unknown\n displayName?: unknown\n nick?: unknown\n nickname?: unknown\n name?: unknown\n level?: unknown\n levelName?: unknown\n level_name?: unknown\n level_info?: { current_level?: unknown }\n title?: unknown\n specialTitle?: unknown\n special_title?: unknown\n sex?: unknown\n gender?: unknown\n age?: unknown\n area?: unknown\n region?: unknown\n location?: unknown\n join_time?: unknown\n joined_at?: unknown\n joinTime?: unknown\n joinedAt?: unknown\n last_sent_time?: unknown\n lastSentTime?: unknown\n lastSpeakTimestamp?: unknown\n user?: { nick?: unknown, nickname?: unknown, name?: unknown }\n}\n\nexport function asMembers(value: unknown): MemberInfo[] {\n return Array.isArray(value) ? value.filter(isRecord) : []\n}\n\nexport function asMember(value: unknown): MemberInfo | undefined {\n return isRecord(value) ? value : undefined\n}\n\nexport function memberUserId(member: MemberInfo): string {\n return pickText(member.user_id, member.userId, member.id, member.qq, member.uid)\n}\n\nexport function memberCard(member: MemberInfo): string {\n return pickText(member.card, member.remark, member.displayName)\n}\n\nexport function memberNickname(member: MemberInfo): string {\n return pickText(member.nick, member.nickname, member.name, member.user?.nickname, member.user?.name)\n}\n\nexport function memberRole(member: MemberInfo): string {\n const roles = Array.isArray(member.roles) ? member.roles : []\n return pickText(member.role, member.roleName, member.permission, member.identity, roles[0])\n}\n","import type { Context } from 'cordis'\nimport type { Bot } from '@satorijs/core'\nimport { Schema } from '@chatluna/schema'\nimport type { ToolCallContext, ToolDefinition } from '@chatluna/tool'\nimport type { Agent } from '@chatluna/agent'\nimport type { ChatFileBlock, ChatMessage } from '@chatluna/message'\nimport { fileRefTableOf } from '@chatluna/message'\nimport type {} from '@chatluna/storage-files'\nimport type { Config, NativeToolKey, OneBotProtocol } from './config'\nimport { NATIVE_TOOL_KEYS, NATIVE_TOOLS } from './config'\nimport type { Logger } from './logger'\nimport {\n asMembers,\n callOneBot,\n memberCard,\n memberNickname,\n memberUserId,\n numericId,\n oneBotOf,\n type MemberInfo,\n} from './onebot'\n\n/** 工具执行时的上下文:会话所在的机器人与群。 */\nexport interface ToolScope {\n ctx: Context\n bot: Bot\n /** 会话所在群;私聊为 undefined。 */\n guildId?: string\n protocol: OneBotProtocol\n /** 发起调用的 agent(`call.agent`),用来在会话日志里解析图片 ref;脱离会话的调用没有。 */\n agent?: object\n}\n\ninterface NativeTool<A> {\n args: Schema<any, A>\n effect: 'read' | 'write'\n run(scope: ToolScope, args: A): Promise<string>\n}\n\nconst MISSING_GROUP = 'Missing groupId. Provide groupId explicitly or run inside a group session.'\nconst MAX_MEMBER_RESULTS = 10\n\nconst groupIdArg = () => Schema.string().required(false).description('Target group ID. Defaults to current session group.')\n\nfunction groupOf(scope: ToolScope, groupId: string | undefined): string {\n const resolved = groupId?.trim() || scope.guildId?.trim()\n if (!resolved) throw new Error(MISSING_GROUP)\n return resolved\n}\n\nfunction required(value: string, name: string): string {\n const trimmed = value.trim()\n if (!trimmed) throw new Error(`${name} is required.`)\n return trimmed\n}\n\nconst GENDERS = { unknown: '0', male: '1', female: '2' }\n\nconst STORAGE_PREFIX = 'storage://'\n/** v2 给模型的文件占位符 `<img ref=\"i…\"/>`:`i` 加内容哈希的最短唯一前缀(至少 6 位)。 */\nconst FILE_REF = /^i[0-9a-f]{6,}$/\n\nconst base64File = (buffer: Buffer) => `base64://${buffer.toString('base64')}`\n\n/** HTTP/HTTPS 图片先读成 base64:OneBot 端常访问不到临时 URL,或 URL 在提交前就已过期。 */\nasync function remoteFile(url: string): Promise<string> {\n try {\n const response = await fetch(url)\n if (!response.ok) throw new Error(`HTTP ${response.status}`)\n return base64File(Buffer.from(await response.arrayBuffer()))\n } catch (error) {\n throw new Error(`无法读取头像图片:${error instanceof Error ? error.message : String(error)}`)\n }\n}\n\n/** 入站图片由 v2 下载进 `chatluna_storage`,24 小时后过期;没装存储插件时会话里只有 url 或 data 块。 */\nasync function storageFile(ctx: Context, reference: string): Promise<string> {\n const storage = ctx.get('chatluna_storage')\n if (!storage) throw new Error(`Cannot read ${reference}: the chatluna_storage service is not loaded.`)\n const file = await storage.getTempFile(reference.slice(STORAGE_PREFIX.length))\n if (!file) throw new Error(`${reference} is not in storage (it may have expired).`)\n return base64File(await file.data)\n}\n\nfunction dataFile(data: string): string {\n if (!data.startsWith('data:')) return `base64://${data}`\n const comma = data.indexOf(',')\n const body = data.slice(comma + 1)\n return data.slice(0, comma).endsWith(';base64') ? `base64://${body}` : base64File(Buffer.from(decodeURIComponent(body)))\n}\n\nfunction messagesOf(agent: object | undefined): readonly ChatMessage[] | undefined {\n const session: unknown = agent && 'session' in agent ? agent.session : undefined\n if (session === null || typeof session !== 'object' || !('messages' in session) || typeof session.messages !== 'function') return undefined\n return session.messages() as readonly ChatMessage[]\n}\n\n/**\n * v2 不把聊天图片的地址交给模型,只给 `<img ref=\"i…\"/>`,ref 要在发起调用的 agent 的会话日志里按内容哈希解析\n * (与 v2 自带的 `look` 工具、出站 `<img ref>` 同一张表)。\n */\nasync function sessionImageFile(scope: ToolScope, ref: string): Promise<string> {\n const messages = messagesOf(scope.agent)\n if (!messages) throw new Error(`Image ref ${ref} can only be resolved inside a conversation.`)\n const block: ChatFileBlock | undefined = fileRefTableOf(messages).resolve(ref)\n if (!block) throw new Error(`Image ref ${ref} is not in this conversation.`)\n if (!block.mediaType.startsWith('image/')) throw new Error(`ref ${ref} is ${block.mediaType}, not an image.`)\n // 用原图 data,不用写入时压缩的 preview。\n const { data } = block\n if (data.type === 'data') return dataFile(data.data)\n if (data.type === 'url') return remoteFile(data.url)\n if (data.type === 'reference' && data.reference.startsWith(STORAGE_PREFIX)) return storageFile(scope.ctx, data.reference)\n throw new Error(`Image ref ${ref} cannot be read.`)\n}\n\n/** 头像来源:会话图片 ref、`storage://`、HTTP/HTTPS 图片都先读成 base64 再提交,其余(OneBot 端可读的本地路径)原样提交。 */\nasync function avatarFile(scope: ToolScope, image: string): Promise<string> {\n if (FILE_REF.test(image)) return sessionImageFile(scope, image)\n if (image.startsWith(STORAGE_PREFIX)) return storageFile(scope.ctx, image)\n if (/^https?:\\/\\//i.test(image)) return remoteFile(image)\n return image\n}\n\nfunction formatMember(index: number, member: MemberInfo): string {\n return `${index}. qqid:${memberUserId(member) || '未知'},群昵称:${memberCard(member) || '无'},QQ昵称:${memberNickname(member) || '无'}`\n}\n\nexport const NATIVE_TOOL_IMPLEMENTATIONS: { [K in NativeToolKey]: NativeTool<any> } = {\n setSelfProfile: {\n args: Schema.args({\n nickname: Schema.string().min(1).description('The new nickname for the bot.'),\n signature: Schema.string().required(false).description('Optional: the new personal signature.'),\n gender: Schema.union(['unknown', 'male', 'female']).required(false).description('Optional: the new gender.'),\n }),\n effect: 'write',\n async run(scope, args: { nickname: string, signature?: string, gender?: keyof typeof GENDERS }) {\n await callOneBot(scope.bot, 'set_qq_profile', {\n nickname: args.nickname,\n ...(args.signature ? { personal_note: args.signature } : {}),\n // LLBot 的 set_qq_profile 不接受 sex。\n ...(args.gender && scope.protocol !== 'llbot' ? { sex: GENDERS[args.gender] } : {}),\n })\n return '机器人资料已更新。'\n },\n },\n setQQAvatar: {\n args: Schema.args({\n imageUrl: Schema.string().min(1).description('The image: the ref attribute of an `<img ref=\"i…\"/>` in this conversation, an HTTP/HTTPS URL, or a local file path readable by the OneBot side.'),\n }),\n effect: 'write',\n async run(scope, args: { imageUrl: string }) {\n const file = await avatarFile(scope, required(args.imageUrl, 'imageUrl'))\n await callOneBot(scope.bot, 'set_qq_avatar', { file })\n return 'QQ 头像已更新。'\n },\n },\n setGroupCard: {\n args: Schema.args({\n groupId: groupIdArg(),\n userId: Schema.string().min(1).description('Target member user ID.'),\n card: Schema.string().min(1).description('New group card for the member.'),\n }),\n effect: 'write',\n async run(scope, args: { groupId?: string, userId: string, card: string }) {\n const groupId = groupOf(scope, args.groupId)\n const userId = required(args.userId, 'userId')\n const card = required(args.card, 'card')\n await callOneBot(scope.bot, 'set_group_card', { group_id: groupId, user_id: userId, card })\n return `群昵称已更新:${userId} -> ${card}`\n },\n },\n searchGroupMember: {\n args: Schema.args({\n groupId: groupIdArg(),\n query: Schema.string().min(1).description('qqid, group card, or QQ nickname to search.'),\n mode: Schema.union(['auto', 'byName', 'byQQ']).required(false).description('Search mode. Defaults to auto.'),\n }),\n effect: 'read',\n async run(scope, args: { groupId?: string, query: string, mode?: 'auto' | 'byName' | 'byQQ' }) {\n const query = required(args.query, 'query')\n const mode = args.mode ?? 'auto'\n const groupId = groupOf(scope, args.groupId)\n const members = asMembers(await callOneBot(scope.bot, 'get_group_member_list', { group_id: numericId(groupId) }))\n const byQQ = mode === 'byQQ' || (mode === 'auto' && /^\\d+$/.test(query))\n const keyword = query.toLowerCase()\n const matches = members.filter((member) => byQQ\n ? memberUserId(member) === query\n : [memberCard(member), memberNickname(member)].some((name) => name && name.toLowerCase().includes(keyword)))\n if (!matches.length) return '未找到匹配的群成员。'\n const header = matches.length > MAX_MEMBER_RESULTS\n ? `仅显示前 ${MAX_MEMBER_RESULTS} 条,共 ${matches.length} 条匹配:`\n : `找到 ${matches.length} 个匹配成员:`\n return [header, ...matches.slice(0, MAX_MEMBER_RESULTS).map((member, index) => formatMember(index + 1, member))].join('\\n')\n },\n },\n leaveGroup: {\n args: Schema.args({ groupId: groupIdArg() }),\n effect: 'write',\n async run(scope, args: { groupId?: string }) {\n const groupId = groupOf(scope, args.groupId)\n await callOneBot(scope.bot, 'set_group_leave', { group_id: groupId })\n return `已退出群 ${groupId}。`\n },\n },\n handleRequest: {\n args: Schema.args({\n requestType: Schema.union(['friend', 'group']).description('Request type: friend or group.'),\n flag: Schema.string().min(1).description('OneBot request flag from the event.'),\n approve: Schema.boolean().description('true to approve the request, false to reject it.'),\n subType: Schema.union(['add', 'invite']).required(false).description('Required for group requests: add or invite.'),\n remark: Schema.string().required(false).description('Optional friend remark when approving a friend request.'),\n userId: Schema.string().required(false).description('Requester user ID of a friend request; needed to apply the remark on SnowLuma.'),\n reason: Schema.string().required(false).description('Optional rejection reason for a group request.'),\n }),\n effect: 'write',\n async run(scope, args: { requestType: 'friend' | 'group', flag: string, approve: boolean, subType?: 'add' | 'invite', remark?: string, userId?: string, reason?: string }) {\n const flag = required(args.flag, 'request flag')\n const verb = args.approve ? '同意' : '拒绝'\n if (args.requestType === 'friend') {\n const remark = args.remark?.trim() ?? ''\n await callOneBot(scope.bot, 'set_friend_add_request', { flag, approve: args.approve, remark })\n const message = `已${verb}好友申请 ${flag}。`\n // SnowLuma 的 set_friend_add_request 不读 remark,同意后另用 set_friend_remark 设置。\n if (scope.protocol !== 'snowluma' || !args.approve || !remark) return message\n const userId = args.userId?.trim()\n if (!userId) return `${message}未提供申请人 userId,备注未设置。`\n await callOneBot(scope.bot, 'set_friend_remark', { user_id: numericId(userId), remark })\n return `${message}备注已设置为 ${remark}。`\n }\n if (!args.subType) throw new Error('subType is required for group requests; use add or invite.')\n await callOneBot(scope.bot, 'set_group_add_request', {\n flag,\n sub_type: args.subType,\n approve: args.approve,\n reason: args.reason?.trim() ?? '',\n })\n return `已${verb}${args.subType === 'invite' ? '群邀请' : '加群申请'} ${flag}。`\n },\n },\n setGroupKick: {\n args: Schema.args({\n groupId: groupIdArg(),\n userId: Schema.string().min(1).description('Target member user ID.'),\n }),\n effect: 'write',\n async run(scope, args: { groupId?: string, userId: string }) {\n const groupId = groupOf(scope, args.groupId)\n const userId = required(args.userId, 'userId')\n await callOneBot(scope.bot, 'set_group_kick', { group_id: groupId, user_id: userId })\n return `已将用户 ${userId} 移出群 ${groupId}。`\n },\n },\n setGroupSpecialTitle: {\n args: Schema.args({\n groupId: groupIdArg(),\n userId: Schema.string().min(1).description('Target member user ID.'),\n title: Schema.string().description('New special title. Use an empty string to clear it.'),\n }),\n effect: 'write',\n async run(scope, args: { groupId?: string, userId: string, title: string }) {\n const groupId = groupOf(scope, args.groupId)\n const userId = required(args.userId, 'userId')\n const title = args.title.trim()\n await callOneBot(scope.bot, 'set_group_special_title', { group_id: groupId, user_id: userId, special_title: title })\n return title ? `群专属头衔已更新:${userId} -> ${title}` : `群专属头衔已清除:${userId}`\n },\n },\n deleteMessage: {\n args: Schema.args({\n message_id: Schema.string().min(1).description('Specific message ID to delete.'),\n }),\n effect: 'write',\n async run(scope, args: { message_id: string }) {\n const messageId = required(args.message_id, 'message_id')\n await callOneBot(scope.bot, 'delete_msg', { message_id: numericId(messageId) })\n return `Message deleted by ID ${messageId}.`\n },\n },\n}\n\n/** 全部原生工具的定义,名称与描述固定为源插件的默认值。 */\nexport function nativeToolDefinitions(ctx: Context, config: Config, log: Logger): ToolDefinition[] {\n return NATIVE_TOOL_KEYS.map((key) => {\n const tool = NATIVE_TOOL_IMPLEMENTATIONS[key]\n const { toolName: name, description } = NATIVE_TOOLS[key]\n return {\n name,\n description,\n args: tool.args,\n traits: { effect: tool.effect },\n async run(args: unknown, call: ToolCallContext) {\n const location = call.location\n const bot = oneBotOf(ctx, location?.platform, location?.selfId)\n if (!bot) throw new Error('This tool only supports OneBot platform.')\n try {\n const result = await tool.run({ ctx, bot, guildId: location?.isDirect ? undefined : location?.guild, protocol: config.oneBotProtocol, agent: call.agent }, args)\n log.debug('%s: %s', name, result)\n return result\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n log.warn('%s failed: %s', name, message)\n throw new Error(`${name} failed: ${message}`)\n }\n },\n }\n })\n}\n\n/**\n * 注册原生工具。工具对所有会话全局可见(v2 的工具管理页因此能列出并开关它们),\n * 再给不在 OneBot 上的 agent 挂一层排除过滤,与源插件只在 OneBot 会话授权一致。\n */\nexport function registerNativeTools(ctx: Context, config: Config, log: Logger) {\n const definitions = nativeToolDefinitions(ctx, config, log)\n for (const definition of definitions) ctx.tools.define(definition)\n const exclude = definitions.map((definition) => definition.name)\n log.info('native tools registered: %s', exclude.join(', '))\n ctx.inject(['agents'], (inner) => {\n const scope = (agent: Agent) => {\n if (agent.options.location?.platform !== 'onebot') inner.tools.filter({ exclude }, agent)\n }\n inner.on('chatluna/agent-open', ({ agent }) => scope(agent))\n for (const agent of inner.agents.list()) scope(agent)\n })\n}\n","import type { Context } from 'cordis'\nimport type { Bot } from '@satorijs/core'\nimport type { PromptEnvironment, VariableDeclaration, VariableProvider } from '@chatluna/prompt'\nimport type { Config, GroupInfoItem, MemberInfoItem, OneBotProtocol } from './config'\nimport { DEFAULT_GROUP_INFO_ITEMS } from './config'\nimport type { Logger } from './logger'\nimport {\n asMember,\n asMembers,\n callOneBot,\n formatDate,\n formatDateTime,\n memberCard,\n memberNickname,\n memberRole,\n memberUserId,\n normalizeTimestamp,\n oneBotOf,\n pickFirst,\n pickText,\n type MemberInfo,\n} from './onebot'\n\nconst FALLBACK_MEMBER_ITEMS: MemberInfoItem[] = ['nickname', 'userId']\n\nconst SHUT_LIST_TIMEOUT_MS = 200\nconst SHUT_LIST_CACHE_TTL_MS = 15_000\n\nfunction translateGender(value: unknown): string {\n if (value === null || value === undefined) return ''\n const text = String(value).trim().toLowerCase()\n if (!text) return ''\n if (['male', 'man', 'm', '1', 'boy'].includes(text)) return '男'\n if (['female', 'woman', 'f', '2', 'girl'].includes(text)) return '女'\n if (['未知', 'unknown', '0', 'secret'].includes(text)) return ''\n return String(value)\n}\n\nfunction normalizeRole(value: string): string {\n const text = value.toLowerCase()\n if (!text) return '群员'\n if (['owner', 'group_owner', '群主'].includes(text)) return '群主'\n if (['admin', 'administrator', 'group_admin', '管理员'].includes(text)) return '管理员'\n if (['member', 'normal', '群员'].includes(text)) return '群员'\n return value\n}\n\n/** 会话所在的 Satori 机器人,任意平台;预览等没有真实机器人的环境里为 undefined。 */\nfunction botOf(ctx: Context, env: PromptEnvironment): Bot | undefined {\n return ctx.satori.bots.find((bot) => bot.platform === env.platform && bot.selfId === env.selfId)\n}\n\n/** 查询群成员信息;私聊、找不到机器人或查询失败时为 undefined,变量照常按已知信息渲染。 */\nasync function fetchMember(ctx: Context, env: PromptEnvironment, userId: string): Promise<MemberInfo | undefined> {\n const bot = botOf(ctx, env)\n if (!bot || !env.guildId) return undefined\n try {\n if (bot.platform === 'onebot') {\n return asMember(await callOneBot(bot, 'get_group_member_info', {\n group_id: Number(env.guildId),\n user_id: Number(userId),\n no_cache: false,\n }))\n }\n return asMember(await bot.getGuildMember(env.guildId, userId))\n } catch {\n return undefined\n }\n}\n\n/** 用户信息与机器人信息共用的渲染:按配置的信息项逐条输出,取不到的项省略。 */\nfunction renderMember(member: MemberInfo | undefined, items: MemberInfoItem[], id: string, fallbackName: unknown): string[] {\n const values: string[] = []\n for (const item of items) {\n switch (item) {\n case 'nickname': {\n const name = pickText(member?.card, member?.remark, member?.displayName, member?.nick, member?.nickname, member?.name, fallbackName, id)\n if (name) values.push(`name:${name}`)\n break\n }\n case 'userId':\n if (id) values.push(`id:${id}`)\n break\n case 'role':\n values.push(`群内身份:${normalizeRole(member ? memberRole(member) : '')}`)\n break\n case 'level': {\n const level = pickFirst(member?.level, member?.levelName, member?.level_name, member?.level_info?.current_level)\n if (level !== undefined) values.push(`群等级:${level}`)\n break\n }\n case 'title': {\n const title = pickFirst(member?.title, member?.specialTitle, member?.special_title)\n if (title !== undefined) values.push(`头衔:${title}`)\n break\n }\n case 'gender': {\n const gender = translateGender(member?.sex ?? member?.gender)\n if (gender) values.push(`性别:${gender}`)\n break\n }\n case 'age': {\n const age = Number(member?.age)\n if (Number.isFinite(age) && age > 0) values.push(`年龄:${age}`)\n break\n }\n case 'area': {\n const area = pickFirst(member?.area, member?.region, member?.location)\n if (area !== undefined) values.push(`地区:${area}`)\n break\n }\n case 'joinTime': {\n const joinTime = formatDate(normalizeTimestamp(pickFirst(member?.join_time, member?.joined_at, member?.joinTime, member?.joinedAt)))\n if (joinTime) values.push(`入群:${joinTime}`)\n break\n }\n case 'lastSentTime': {\n const lastSentTime = formatDateTime(normalizeTimestamp(pickFirst(member?.last_sent_time, member?.lastSentTime, member?.lastSpeakTimestamp)))\n if (lastSentTime) values.push(`活跃:${lastSentTime}`)\n break\n }\n }\n }\n return values\n}\n\nconst itemsOf = (items: MemberInfoItem[]) => items.length ? items : FALLBACK_MEMBER_ITEMS\n\nexport function userInfoProvider(ctx: Context, config: Config): VariableProvider {\n return async ({ env }) => {\n // 群聊里 userId 只来自本步最新的用户消息,工具调用后的后续步骤可能缺失,退回到消息发送者。\n const userId = (env.userId ?? env.message?.senderId)?.trim()\n if (!userId) return '未知用户'\n const member = await fetchMember(ctx, env, userId)\n const values = renderMember(member, itemsOf(config.userInfo.items), userId, env.userName ?? env.message?.senderName)\n return values.length ? values.join(', ') : `id:${userId}`\n }\n}\n\nexport function botInfoProvider(ctx: Context, config: Config): VariableProvider {\n return async ({ env }) => {\n const botId = env.selfId?.trim()\n if (!botId) return '未知机器人'\n const member = await fetchMember(ctx, env, botId)\n const values = renderMember(member, itemsOf(config.botInfo.items), botId, undefined)\n return values.length ? values.join(', ') : botId\n }\n}\n\ninterface GroupInfo {\n group_id?: unknown\n groupId?: unknown\n id?: unknown\n group_name?: unknown\n groupName?: unknown\n name?: unknown\n member_count?: unknown\n memberCount?: unknown\n max_member_count?: unknown\n create_time?: unknown\n createTime?: unknown\n group_create_time?: unknown\n}\n\nasync function fetchRoles(bot: Bot, guildId: string, log: Logger): Promise<{ owners: string[], admins: string[] } | undefined> {\n try {\n const members = asMembers(await callOneBot(bot, 'get_group_member_list', { group_id: Number(guildId) }))\n if (!members.length) return undefined\n const owners: string[] = []\n const admins: string[] = []\n for (const member of members) {\n const role = memberRole(member).toLowerCase()\n const userId = memberUserId(member)\n const name = pickText(memberCard(member), memberNickname(member)) || userId\n const label = userId ? `${name}(${userId})` : name\n if (['owner', 'master', 'leader'].includes(role)) owners.push(label)\n else if (['admin', 'administrator', 'manager'].includes(role)) admins.push(label)\n }\n return { owners, admins }\n } catch (error) {\n log.debug('group roles lookup failed: %s', String(error))\n return undefined\n }\n}\n\nfunction renderGroupInfo(group: GroupInfo, items: GroupInfoItem[], roles: { owners: string[], admins: string[] } | undefined): string {\n const id = pickText(group.group_id, group.groupId, group.id)\n const name = pickText(group.group_name, group.groupName, group.name)\n const memberCount = group.member_count ?? group.memberCount ?? group.max_member_count\n const createTime = formatDate(normalizeTimestamp(group.create_time ?? group.createTime ?? group.group_create_time))\n const values: string[] = []\n for (const item of items) {\n switch (item) {\n case 'groupName':\n if (name) values.push(`群名:${name}`)\n break\n case 'groupId':\n if (id) values.push(`群号:${id}`)\n break\n case 'memberCount':\n if (memberCount !== undefined && memberCount !== null) values.push(`成员数量:${String(memberCount)}`)\n break\n case 'createTime':\n if (createTime) values.push(`创建时间:${createTime}`)\n break\n case 'ownerList':\n if (roles) values.push(`群主:${roles.owners.length ? roles.owners.join('、') : '无'}`)\n break\n case 'adminList':\n if (roles) values.push(`管理员:${roles.admins.length ? roles.admins.join('、') : '无'}`)\n break\n }\n }\n return values.length ? values.join('\\n') : id || name || '未能获取当前群信息。'\n}\n\nexport function groupInfoProvider(ctx: Context, config: Config, log: Logger): VariableProvider {\n return async ({ env }) => {\n if (!env.guildId) return ''\n if (env.platform !== 'onebot') return '当前平台暂不支持查询群信息。'\n const bot = oneBotOf(ctx, env.platform, env.selfId)\n if (!bot) return '暂无群信息。'\n const items = config.groupInfo.items.length ? config.groupInfo.items : DEFAULT_GROUP_INFO_ITEMS\n const group = await callOneBot(bot, 'get_group_info', { group_id: Number(env.guildId), no_cache: false })\n .then(asMember, () => undefined)\n if (!group) return '未能获取当前群信息。'\n const roles = items.includes('ownerList') || items.includes('adminList') ? await fetchRoles(bot, env.guildId, log) : undefined\n return renderGroupInfo(group, items, roles)\n }\n}\n\nclass ShutListTimeout extends Error {}\n\n/** 群号类型不被接受时的报错特征:NapCat 要数字、LLBot 要字符串,类型不对时换另一种再试一次。 */\nconst WRONG_ID_TYPE = /string|number|type|invalid|参数/i\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined\n return Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new ShutListTimeout('group shut list request timed out')), ms)\n }),\n ]).finally(() => clearTimeout(timer))\n}\n\nasync function fetchShutList(bot: Bot, guildId: string, protocol: OneBotProtocol, log: Logger): Promise<unknown[]> {\n const preferred = protocol === 'llbot' ? guildId : Number(guildId)\n const fallback = protocol === 'llbot' ? Number(guildId) : guildId\n const request = async (groupId: string | number) => {\n const data = await withTimeout(callOneBot(bot, 'get_group_shut_list', { group_id: groupId }), SHUT_LIST_TIMEOUT_MS)\n return Array.isArray(data) ? data : []\n }\n try {\n return await request(preferred)\n } catch (error) {\n if (error instanceof ShutListTimeout || !(error instanceof Error) || !WRONG_ID_TYPE.test(error.message)) throw error\n log.debug('group shut list retries with %s group id: %s', typeof fallback, error.message)\n return request(fallback)\n }\n}\n\nfunction renderShutItem(item: unknown): string | undefined {\n const record = asMember(item)\n if (!record) return undefined\n const field = (key: string) => Reflect.get(record, key)\n const userId = pickText(field('uin'), field('user_id'))\n if (!userId) return undefined\n const name = pickText(field('cardName'), field('remark'), field('nick'), field('nickname'), userId)\n const until = formatDateTime(normalizeTimestamp(pickFirst(field('shutUpTime'), field('shut_up_time')))) || '未知'\n return `id:${userId},name:${name},禁言截至:${until}`\n}\n\nexport function groupShutListProvider(ctx: Context, config: Config, log: Logger): VariableProvider {\n // 变量每一步都会重新渲染,同一个群的结果缓存 15 秒,避免每一步都请求一次。\n const cache = new Map<string, { value: string, expiresAt: number }>()\n return async ({ env }) => {\n if (!env.guildId) return ''\n if (env.platform !== 'onebot') return '当前平台暂不支持查询群禁言列表。'\n const bot = oneBotOf(ctx, env.platform, env.selfId)\n if (!bot) return '暂无群禁言列表。'\n const key = `${env.selfId}:${env.guildId}`\n const cached = cache.get(key)\n if (cached && cached.expiresAt > Date.now()) return cached.value\n try {\n const lines = (await fetchShutList(bot, env.guildId, config.oneBotProtocol, log)).flatMap((item) => renderShutItem(item) ?? [])\n const value = lines.length ? lines.join('\\n') : '当前群暂无禁言成员。'\n cache.set(key, { value, expiresAt: Date.now() + SHUT_LIST_CACHE_TTL_MS })\n return value\n } catch (error) {\n log.debug('group shut list failed: %s', String(error))\n // 部分实现在群里没有禁言成员时迟迟不响应,超时按空列表处理。\n return error instanceof ShutListTimeout ? '当前群暂无禁言成员。' : '获取群禁言列表失败。'\n }\n }\n}\n\n/** 按配置得到要注册的变量;变量名留空的不注册。 */\nexport function variableDefinitions(ctx: Context, config: Config, log: Logger): Array<[VariableDeclaration, VariableProvider]> {\n const entries: Array<[string, string, VariableProvider]> = [\n [config.userInfo.variableName, 'Current user info in this group', userInfoProvider(ctx, config)],\n [config.botInfo.variableName, 'Bot info in this group', botInfoProvider(ctx, config)],\n [config.groupInfo.variableName, 'Current group info', groupInfoProvider(ctx, config, log)],\n [config.groupShutList.variableName, 'Muted members of this group', groupShutListProvider(ctx, config, log)],\n ]\n // 都随群聊状态变化,属于可变变量:不能写进 system 区,v1 预设会被自动挪到 context 区。\n return entries\n .filter(([name]) => name.trim())\n .map(([name, description, provider]) => [{ name: name.trim(), description, mutable: true }, provider])\n}\n\nexport function registerVariables(ctx: Context, config: Config, log: Logger) {\n for (const [declaration, provider] of variableDefinitions(ctx, config, log)) {\n try {\n ctx.prompt.variable(declaration, provider)\n } catch (error) {\n // 同名变量已被其他插件注册时只跳过这一个,其余变量与工具照常可用。\n log.warn('variable %s not registered: %s', declaration.name, error instanceof Error ? error.message : String(error))\n }\n }\n}\n","import type { Context } from 'cordis'\nimport type { Config } from './config'\nimport { createLogger } from './logger'\nimport { registerRequestNotices } from './requests'\nimport { registerNativeTools } from './tools'\nimport { registerVariables } from './variables'\n\nexport * from './config'\n\nexport const name = 'chatluna-onebot-toolbox'\n\n/** 过滤工具用的 agents、唤醒用的 chat 与读取会话图片用的 chatluna_storage 是可选服务。 */\nexport const inject = ['satori', 'tools', 'prompt']\n\nexport function apply(ctx: Context, config: Config) {\n const log = createLogger(ctx, config.debugLogging)\n registerVariables(ctx, config, log)\n registerNativeTools(ctx, config, log)\n registerRequestNotices(ctx, config, log)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/logger.ts","../src/config.ts","../src/requests.ts","../src/onebot.ts","../src/tools.ts","../src/variables.ts","../src/index.ts"],"sourcesContent":["import type { Context } from 'cordis'\n\n/** 插件内的日志:`debugLogging` 打开时调试信息以 info 级别输出,否则走 logger 自己的 debug 级别。 */\nexport interface Logger {\n debug(format: string, ...args: unknown[]): void\n info(format: string, ...args: unknown[]): void\n warn(format: string, ...args: unknown[]): void\n}\n\nexport function createLogger(ctx: Context, debugLogging: boolean): Logger {\n const logger = ctx.logger\n return {\n debug: (format, ...args) => (debugLogging ? logger.info(format, ...args) : logger.debug(format, ...args)),\n info: (format, ...args) => logger.info(format, ...args),\n warn: (format, ...args) => logger.warn(format, ...args),\n }\n}\n","import { Schema } from '@chatluna/schema'\n\nexport type OneBotProtocol = 'napcat' | 'llbot' | 'snowluma'\n\nexport type NativeToolKey =\n | 'setSelfProfile'\n | 'setQQAvatar'\n | 'setGroupCard'\n | 'searchGroupMember'\n | 'leaveGroup'\n | 'handleRequest'\n | 'setGroupKick'\n | 'setGroupSpecialTitle'\n | 'deleteMessage'\n\nexport interface NativeToolInfo {\n toolName: string\n description: string\n}\n\nexport type MemberInfoItem =\n | 'userId'\n | 'nickname'\n | 'role'\n | 'level'\n | 'title'\n | 'gender'\n | 'age'\n | 'area'\n | 'joinTime'\n | 'lastSentTime'\n\nexport type GroupInfoItem = 'groupName' | 'groupId' | 'memberCount' | 'createTime' | 'ownerList' | 'adminList'\n\nexport interface Config {\n oneBotProtocol: OneBotProtocol\n requestNotice: boolean\n userInfo: { variableName: string, items: MemberInfoItem[] }\n botInfo: { variableName: string, items: MemberInfoItem[] }\n groupInfo: { variableName: string, items: GroupInfoItem[] }\n groupShutList: { variableName: string }\n debugLogging: boolean\n}\n\n/** 原生工具的名称与描述固定,全部注册;启用范围交给 v2 的工具管理。 */\nexport const NATIVE_TOOLS: Record<NativeToolKey, NativeToolInfo> = {\n setSelfProfile: {\n toolName: 'set_self_profile',\n description: '修改自己的 QQ 资料,可设置昵称、签名和性别。',\n },\n setQQAvatar: {\n toolName: 'set_qq_avatar',\n description: '修改机器人 QQ 头像。imageUrl 填会话里图片的 ref(`<img ref=\"i…\"/>` 的 ref 属性)、HTTP/HTTPS 链接或 OneBot 端可读的本地路径;会话图片与 HTTP/HTTPS 图片会先由插件读取并转为 OneBot base64 文件,避免临时 URL 过期或 OneBot 端无法访问。',\n },\n setGroupCard: {\n toolName: 'set_group_card',\n description: '修改群成员的群昵称。',\n },\n searchGroupMember: {\n toolName: 'search_group_member',\n description: '根据 qqid 精确查询群成员的群昵称与 QQ 昵称,或根据群昵称/QQ 昵称搜索 qqid。默认查询当前群聊,可通过 groupId 查询指定群。',\n },\n leaveGroup: {\n toolName: 'set_group_leave',\n description: '让机器人退出当前群聊。',\n },\n handleRequest: {\n toolName: 'handle_request',\n description: '根据 OneBot 申请 flag 同意或拒绝好友申请、加群申请或群邀请。',\n },\n setGroupKick: {\n toolName: 'set_group_kick',\n description: '将指定成员踢出群聊。',\n },\n setGroupSpecialTitle: {\n toolName: 'set_group_special_title',\n description: '修改或清除群成员的 QQ 群专属头衔。',\n },\n deleteMessage: {\n toolName: 'delete_msg',\n description: '根据消息 ID 撤回指定消息。',\n },\n}\n\nexport const NATIVE_TOOL_KEYS = Object.keys(NATIVE_TOOLS) as NativeToolKey[]\n\nexport const DEFAULT_MEMBER_INFO_ITEMS: MemberInfoItem[] = [\n 'nickname', 'userId', 'role', 'level', 'title', 'gender', 'age', 'area', 'joinTime', 'lastSentTime',\n]\n\nexport const DEFAULT_GROUP_INFO_ITEMS: GroupInfoItem[] = ['groupName', 'groupId', 'memberCount', 'ownerList', 'adminList']\n\n/** 变量名须满足 v2 模板的变量命名规则(`@chatluna/prompt` 的 `variable`),留空表示不注册。 */\nconst VARIABLE_NAME = /^([a-z_][a-z0-9_]*)?$/i\n\nconst memberItems = (subject: string) => Schema.array(Schema.union([\n Schema.const('userId').description(`${subject} ID`),\n Schema.const('nickname').description('群昵称'),\n Schema.const('role').description('群内身份'),\n Schema.const('level').description('群等级'),\n Schema.const('title').description('群头衔'),\n Schema.const('gender').description('性别'),\n Schema.const('age').description('年龄'),\n Schema.const('area').description('地区'),\n Schema.const('joinTime').description('入群时间'),\n Schema.const('lastSentTime').description('最后发言时间'),\n])).role('checkbox').default([...DEFAULT_MEMBER_INFO_ITEMS])\n\nconst variableName = (name: string) => Schema.string().default(name).pattern(VARIABLE_NAME).extra('label', '变量名称')\n .description('在预设中以`{变量名称}`引用,留空时不注册')\n\nconst basicFields = {\n oneBotProtocol: Schema.union([\n Schema.const('napcat').description('NapCat'),\n Schema.const('llbot').description('LLBot'),\n Schema.const('snowluma').description('SnowLuma'),\n ]).default('napcat').role('radio').extra('label', 'OneBot 协议')\n .description('按所选实现调整请求参数:LLBot 不支持设置性别,群禁言列表的群号类型也不同;SnowLuma 同意好友申请后另行设置备注'),\n requestNotice: Schema.boolean().default(true).extra('label', '申请通知')\n .description('收到好友申请、加群申请或群邀请时唤醒对应会话,把申请 flag 告诉模型,供`handle_request`工具处理。好友申请与群邀请发往申请人的私聊,加群申请发往所申请的群;该工具在工具管理中禁用时不唤醒'),\n}\n\nconst variableFields = {\n userInfo: Schema.object({\n variableName: variableName('userInfo'),\n items: memberItems('用户').extra('label', '信息项').description('选择用户信息变量中显示的详细信息项'),\n }).description('用户信息变量').collapse(),\n botInfo: Schema.object({\n variableName: variableName('botInfo'),\n items: memberItems('机器人').extra('label', '信息项').description('选择机器人信息变量中显示的详细信息项'),\n }).description('机器人信息变量').collapse(),\n groupInfo: Schema.object({\n variableName: variableName('groupInfo'),\n items: Schema.array(Schema.union([\n Schema.const('groupName').description('群名称'),\n Schema.const('groupId').description('群号'),\n Schema.const('memberCount').description('成员数量'),\n Schema.const('createTime').description('创建时间(仅部分实现支持)'),\n Schema.const('ownerList').description('群主名单'),\n Schema.const('adminList').description('管理员名单'),\n ])).role('checkbox').default([...DEFAULT_GROUP_INFO_ITEMS]).extra('label', '信息项')\n .description('选择群信息变量中显示的群信息项'),\n }).description('群信息变量').collapse(),\n groupShutList: Schema.object({\n variableName: variableName('groupShutList'),\n }).description('群禁言列表变量').collapse(),\n}\n\nconst otherFields = {\n debugLogging: Schema.boolean().default(false).extra('label', '输出调试日志')\n .description('以 info 级别输出工具调用与变量解析的调试信息'),\n}\n\n/**\n * 插件配置,直接在 v2 的插件设置页编辑。顶层是分组的 intersect,SchemaForm 把每组的 description 渲染成小节标题;\n * 每个字段都写 `extra('label')`,缺 label 时 SchemaForm 会把配置键当标题显示。\n */\nexport const Config: Schema<Config> = Schema.intersect([\n Schema.object(basicFields).description('基础设置'),\n Schema.object(variableFields).description('变量'),\n Schema.object(otherFields).description('其他设置'),\n])\n","import type { Context } from 'cordis'\nimport type { Session } from '@satorijs/core'\nimport type { RouteIdentity } from '@chatluna/satori'\nimport type {} from '@chatluna/chat'\nimport type { Config } from './config'\nimport { NATIVE_TOOLS } from './config'\nimport type { Logger } from './logger'\n\ntype RequestKind = 'friend' | 'add' | 'invite'\n\n/**\n * 申请发往的会话:好友申请与群邀请发往申请人的私聊,加群申请发往所申请的群。\n * 用路由身份而不是事件 Session 唤醒:申请事件不是消息,申请人与机器人之间往往还没有会话,\n * `chat.wake` 会按身份新开一个。\n */\nexport function requestTarget(session: Session, kind: RequestKind): RouteIdentity | undefined {\n if (!session.userId) return undefined\n if (kind === 'add') {\n if (!session.guildId) return undefined\n return { platform: session.platform, selfId: session.selfId, isDirect: false, guildId: session.guildId, channelId: session.guildId, userId: session.userId }\n }\n return { platform: session.platform, selfId: session.selfId, isDirect: true, channelId: `private:${session.userId}`, userId: session.userId }\n}\n\n/** 唤醒原因即模型看到的通知,写明 flag 与调用方式,模型据此调用处理申请工具。 */\nexport function requestReason(session: Session, kind: RequestKind, toolName: string): string {\n const comment = session.content?.trim() ? `, message: ${JSON.stringify(session.content.trim())}` : ''\n const flag = `flag: ${JSON.stringify(session.messageId ?? '')}`\n if (kind === 'friend') {\n return `user ${session.userId} sent you a friend request (${flag}${comment}). Call ${toolName} with requestType \"friend\" and userId \"${session.userId}\" to approve or reject it`\n }\n if (kind === 'add') {\n return `user ${session.userId} requested to join group ${session.guildId} (${flag}${comment}). Call ${toolName} with requestType \"group\" and subType \"add\" to approve or reject it`\n }\n return `user ${session.userId} invited you to join group ${session.guildId} (${flag}${comment}). Call ${toolName} with requestType \"group\" and subType \"invite\" to approve or reject it`\n}\n\n/**\n * v2 不把 OneBot 的申请事件交给模型,`handle_request` 拿不到 flag 就无从调用,\n * 所以把申请转成一次唤醒;工具在 v2 工具管理里被禁用时跟着不唤醒。会话所在路由关闭或没选模型时 `wake` 会报错,只记调试日志。\n */\nexport function registerRequestNotices(ctx: Context, config: Config, log: Logger) {\n if (!config.requestNotice) return\n const toolName = NATIVE_TOOLS.handleRequest.toolName\n ctx.inject(['chat'], (inner) => {\n const notify = (session: Session, kind: RequestKind) => {\n if (session.platform !== 'onebot') return\n // 没有 flag 时模型无从处理申请,唤醒只会让它拿空值反复试错。\n if (!session.messageId) return log.debug('%s request without flag ignored', kind)\n // 工具在 v2 工具管理里被禁用时(全局过滤排除了它)不唤醒:模型调用不到,唤醒只会让它白跑一轮。\n if (!inner.tools.list().some((tool) => tool.name === toolName)) return log.debug('%s request ignored: %s is disabled', kind, toolName)\n const target = requestTarget(session, kind)\n if (!target) return\n inner.chat.wake(target, { reason: requestReason(session, kind, toolName), by: 'onebot-toolbox' })\n .then(() => log.debug('%s request %s delivered', kind, session.messageId))\n .catch((error: unknown) => log.debug('%s request %s not delivered: %s', kind, session.messageId, String(error)))\n }\n inner.on('friend-request', (session) => notify(session, 'friend'))\n inner.on('guild-member-request', (session) => notify(session, 'add'))\n inner.on('guild-request', (session) => notify(session, 'invite'))\n })\n}\n","import type { Context } from 'cordis'\nimport type { Bot } from '@satorijs/core'\n\n/** OneBot 适配器的原始请求返回完整响应包,业务失败也照常 resolve。 */\ninterface OneBotInternal {\n _request(action: string, params: Record<string, unknown>): Promise<unknown>\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/** 会话所在的 OneBot 机器人;不是 OneBot 会话或找不到机器人时为 undefined。 */\nexport function oneBotOf(ctx: Context, platform: string | undefined, selfId: string | undefined): Bot | undefined {\n if (platform !== 'onebot' || selfId === undefined) return undefined\n return ctx.satori.bots.find((bot) => bot.platform === 'onebot' && bot.selfId === selfId)\n}\n\n/** 调用 OneBot action 并返回 data,按响应包的 status 与 retcode 判定业务失败。 */\nexport async function callOneBot(bot: Bot, action: string, params: Record<string, unknown>): Promise<unknown> {\n const internal: OneBotInternal = bot.internal\n const result = await internal._request(action, params)\n if (!isRecord(result) || typeof result.status !== 'string' || typeof result.retcode !== 'number') {\n throw new Error('Invalid OneBot response envelope')\n }\n if (result.status === 'ok' && result.retcode === 0) return result.data\n const reason = result.wording || result.message || result.status || 'OneBot returned failed'\n throw new Error(`${String(reason)} (retcode: ${result.retcode})`)\n}\n\n/**\n * 整数形式的 ID 转成数字,其余原样保留;OneBot 实现普遍要求数字形式的群号、QQ 号与消息 ID。\n * SnowLuma 的 message_id 是 int32 哈希,常为负数,所以带负号的整数同样转换。\n */\nexport function numericId(value: string): string | number {\n return /^-?\\d+$/.test(value) ? Number(value) : value\n}\n\n/** 取第一个非空值(去掉首尾空白后不为空字符串),保留原始类型。 */\nexport function pickFirst(...values: unknown[]): string | number | undefined {\n for (const value of values) {\n if (value === null || value === undefined) continue\n if (!String(value).trim()) continue\n return typeof value === 'number' ? value : String(value)\n }\n return undefined\n}\n\nexport function pickText(...values: unknown[]): string {\n return String(pickFirst(...values) ?? '').trim()\n}\n\n/** OneBot 使用秒,Satori 使用毫秒,统一成毫秒;空值与 0 视为没有。 */\nexport function normalizeTimestamp(raw: unknown): number | undefined {\n if (raw === null || raw === undefined || raw === '') return undefined\n const numeric = Number(raw)\n if (!Number.isFinite(numeric) || numeric === 0) return undefined\n return numeric < 1e11 ? numeric * 1000 : numeric\n}\n\nconst pad = (value: number) => String(value).padStart(2, '0')\n\nexport function formatDate(value: number | undefined): string {\n if (value === undefined) return ''\n const date = new Date(value)\n if (Number.isNaN(date.valueOf())) return ''\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`\n}\n\nexport function formatDateTime(value: number | undefined): string {\n const day = formatDate(value)\n if (!day || value === undefined) return day\n const date = new Date(value)\n return `${day} ${pad(date.getHours())}:${pad(date.getMinutes())}`\n}\n\n/** OneBot 群成员信息;其他平台的 Satori 成员信息在查询入口显式转换。 */\nexport interface MemberInfo {\n user_id?: unknown\n role?: unknown\n card?: unknown\n nickname?: unknown\n level?: unknown\n title?: unknown\n sex?: unknown\n age?: unknown\n area?: unknown\n join_time?: unknown\n last_sent_time?: unknown\n}\n\nexport function asMembers(value: unknown): MemberInfo[] {\n return Array.isArray(value) ? value.filter(isRecord) : []\n}\n\nexport function asRecord(value: unknown): Record<string, unknown> | undefined {\n return isRecord(value) ? value : undefined\n}\n","import type { Context } from 'cordis'\nimport type { Bot } from '@satorijs/core'\nimport { Schema } from '@chatluna/schema'\nimport type { ToolCallContext, ToolDefinition } from '@chatluna/tool'\nimport type { Agent } from '@chatluna/agent'\nimport type { ChatFileBlock, ChatMessage } from '@chatluna/message'\nimport { fileRefTableOf } from '@chatluna/message'\nimport type {} from '@chatluna/storage-files'\nimport type { Config, NativeToolKey, OneBotProtocol } from './config'\nimport { NATIVE_TOOL_KEYS, NATIVE_TOOLS } from './config'\nimport type { Logger } from './logger'\nimport {\n asMembers,\n callOneBot,\n pickText,\n numericId,\n oneBotOf,\n type MemberInfo,\n} from './onebot'\n\n/** 工具执行时的上下文:会话所在的机器人与群。 */\nexport interface ToolScope {\n ctx: Context\n bot: Bot\n /** 会话所在群;私聊为 undefined。 */\n guildId?: string\n protocol: OneBotProtocol\n /** 发起调用的 agent(`call.agent`),用来在会话日志里解析图片 ref;脱离会话的调用没有。 */\n agent?: object\n}\n\ninterface NativeTool<A> {\n args: Schema<any, A>\n effect: 'read' | 'write'\n run(scope: ToolScope, args: A): Promise<string>\n}\n\nconst MISSING_GROUP = 'Missing groupId. Provide groupId explicitly or run inside a group session.'\nconst MAX_MEMBER_RESULTS = 10\n\nconst groupIdArg = () => Schema.string().required(false).description('Target group ID. Defaults to current session group.')\n\nfunction groupOf(scope: ToolScope, groupId: string | undefined): string {\n const resolved = groupId?.trim() || scope.guildId?.trim()\n if (!resolved) throw new Error(MISSING_GROUP)\n return resolved\n}\n\nfunction required(value: string, name: string): string {\n const trimmed = value.trim()\n if (!trimmed) throw new Error(`${name} is required.`)\n return trimmed\n}\n\nconst GENDERS = { unknown: '0', male: '1', female: '2' }\n\nconst STORAGE_PREFIX = 'storage://'\n/** v2 给模型的文件占位符 `<img ref=\"i…\"/>`:`i` 加内容哈希的最短唯一前缀(至少 6 位)。 */\nconst FILE_REF = /^i[0-9a-f]{6,}$/\n\nconst base64File = (buffer: Buffer) => `base64://${buffer.toString('base64')}`\n\n/** HTTP/HTTPS 图片先读成 base64:OneBot 端常访问不到临时 URL,或 URL 在提交前就已过期。 */\nasync function remoteFile(url: string): Promise<string> {\n try {\n const response = await fetch(url)\n if (!response.ok) throw new Error(`HTTP ${response.status}`)\n return base64File(Buffer.from(await response.arrayBuffer()))\n } catch (error) {\n throw new Error(`无法读取头像图片:${error instanceof Error ? error.message : String(error)}`)\n }\n}\n\n/** 入站图片由 v2 下载进 `chatluna_storage`,24 小时后过期;没装存储插件时会话里只有 url 或 data 块。 */\nasync function storageFile(ctx: Context, reference: string): Promise<string> {\n const storage = ctx.get('chatluna_storage')\n if (!storage) throw new Error(`Cannot read ${reference}: the chatluna_storage service is not loaded.`)\n const file = await storage.getTempFile(reference.slice(STORAGE_PREFIX.length))\n if (!file) throw new Error(`${reference} is not in storage (it may have expired).`)\n return base64File(await file.data)\n}\n\nfunction dataFile(data: string): string {\n if (!data.startsWith('data:')) return `base64://${data}`\n const comma = data.indexOf(',')\n const body = data.slice(comma + 1)\n return data.slice(0, comma).endsWith(';base64') ? `base64://${body}` : base64File(Buffer.from(decodeURIComponent(body)))\n}\n\nfunction messagesOf(agent: object | undefined): readonly ChatMessage[] | undefined {\n const session: unknown = agent && 'session' in agent ? agent.session : undefined\n if (session === null || typeof session !== 'object' || !('messages' in session) || typeof session.messages !== 'function') return undefined\n return session.messages() as readonly ChatMessage[]\n}\n\n/**\n * v2 不把聊天图片的地址交给模型,只给 `<img ref=\"i…\"/>`,ref 要在发起调用的 agent 的会话日志里按内容哈希解析\n * (与 v2 自带的 `look` 工具、出站 `<img ref>` 同一张表)。\n */\nasync function sessionImageFile(scope: ToolScope, ref: string): Promise<string> {\n const messages = messagesOf(scope.agent)\n if (!messages) throw new Error(`Image ref ${ref} can only be resolved inside a conversation.`)\n const block: ChatFileBlock | undefined = fileRefTableOf(messages).resolve(ref)\n if (!block) throw new Error(`Image ref ${ref} is not in this conversation.`)\n if (!block.mediaType.startsWith('image/')) throw new Error(`ref ${ref} is ${block.mediaType}, not an image.`)\n // 用原图 data,不用写入时压缩的 preview。\n const { data } = block\n if (data.type === 'data') return dataFile(data.data)\n if (data.type === 'url') return remoteFile(data.url)\n if (data.type === 'reference' && data.reference.startsWith(STORAGE_PREFIX)) return storageFile(scope.ctx, data.reference)\n throw new Error(`Image ref ${ref} cannot be read.`)\n}\n\n/** 头像来源:会话图片 ref、`storage://`、HTTP/HTTPS 图片都先读成 base64 再提交,其余(OneBot 端可读的本地路径)原样提交。 */\nasync function avatarFile(scope: ToolScope, image: string): Promise<string> {\n if (FILE_REF.test(image)) return sessionImageFile(scope, image)\n if (image.startsWith(STORAGE_PREFIX)) return storageFile(scope.ctx, image)\n if (/^https?:\\/\\//i.test(image)) return remoteFile(image)\n return image\n}\n\nfunction formatMember(index: number, member: MemberInfo): string {\n return `${index}. qqid:${pickText(member.user_id) || '未知'},群昵称:${pickText(member.card) || '无'},QQ昵称:${pickText(member.nickname) || '无'}`\n}\n\nexport const NATIVE_TOOL_IMPLEMENTATIONS: { [K in NativeToolKey]: NativeTool<any> } = {\n setSelfProfile: {\n args: Schema.args({\n nickname: Schema.string().min(1).description('The new nickname for the bot.'),\n signature: Schema.string().required(false).description('Optional: the new personal signature.'),\n gender: Schema.union(['unknown', 'male', 'female']).required(false).description('Optional: the new gender.'),\n }),\n effect: 'write',\n async run(scope, args: { nickname: string, signature?: string, gender?: keyof typeof GENDERS }) {\n await callOneBot(scope.bot, 'set_qq_profile', {\n nickname: args.nickname,\n ...(args.signature ? { personal_note: args.signature } : {}),\n // LLBot 的 set_qq_profile 不接受 sex。\n ...(args.gender && scope.protocol !== 'llbot' ? { sex: GENDERS[args.gender] } : {}),\n })\n return '机器人资料已更新。'\n },\n },\n setQQAvatar: {\n args: Schema.args({\n imageUrl: Schema.string().min(1).description('The image: the ref attribute of an `<img ref=\"i…\"/>` in this conversation, an HTTP/HTTPS URL, or a local file path readable by the OneBot side.'),\n }),\n effect: 'write',\n async run(scope, args: { imageUrl: string }) {\n const file = await avatarFile(scope, required(args.imageUrl, 'imageUrl'))\n await callOneBot(scope.bot, 'set_qq_avatar', { file })\n return 'QQ 头像已更新。'\n },\n },\n setGroupCard: {\n args: Schema.args({\n groupId: groupIdArg(),\n userId: Schema.string().min(1).description('Target member user ID.'),\n card: Schema.string().min(1).description('New group card for the member.'),\n }),\n effect: 'write',\n async run(scope, args: { groupId?: string, userId: string, card: string }) {\n const groupId = groupOf(scope, args.groupId)\n const userId = required(args.userId, 'userId')\n const card = required(args.card, 'card')\n await callOneBot(scope.bot, 'set_group_card', { group_id: groupId, user_id: userId, card })\n return `群昵称已更新:${userId} -> ${card}`\n },\n },\n searchGroupMember: {\n args: Schema.args({\n groupId: groupIdArg(),\n query: Schema.string().min(1).description('qqid, group card, or QQ nickname to search.'),\n mode: Schema.union(['auto', 'byName', 'byQQ']).required(false).description('Search mode. Defaults to auto.'),\n }),\n effect: 'read',\n async run(scope, args: { groupId?: string, query: string, mode?: 'auto' | 'byName' | 'byQQ' }) {\n const query = required(args.query, 'query')\n const mode = args.mode ?? 'auto'\n const groupId = groupOf(scope, args.groupId)\n const members = asMembers(await callOneBot(scope.bot, 'get_group_member_list', { group_id: numericId(groupId) }))\n const byQQ = mode === 'byQQ' || (mode === 'auto' && /^\\d+$/.test(query))\n const keyword = query.toLowerCase()\n const matches = members.filter((member) => byQQ\n ? pickText(member.user_id) === query\n : [pickText(member.card), pickText(member.nickname)].some((name) => name && name.toLowerCase().includes(keyword)))\n if (!matches.length) return '未找到匹配的群成员。'\n const header = matches.length > MAX_MEMBER_RESULTS\n ? `仅显示前 ${MAX_MEMBER_RESULTS} 条,共 ${matches.length} 条匹配:`\n : `找到 ${matches.length} 个匹配成员:`\n return [header, ...matches.slice(0, MAX_MEMBER_RESULTS).map((member, index) => formatMember(index + 1, member))].join('\\n')\n },\n },\n leaveGroup: {\n args: Schema.args({ groupId: groupIdArg() }),\n effect: 'write',\n async run(scope, args: { groupId?: string }) {\n const groupId = groupOf(scope, args.groupId)\n await callOneBot(scope.bot, 'set_group_leave', { group_id: groupId })\n return `已退出群 ${groupId}。`\n },\n },\n handleRequest: {\n args: Schema.args({\n requestType: Schema.union(['friend', 'group']).description('Request type: friend or group.'),\n flag: Schema.string().min(1).description('OneBot request flag from the event.'),\n approve: Schema.boolean().description('true to approve the request, false to reject it.'),\n subType: Schema.union(['add', 'invite']).required(false).description('Required for group requests: add or invite.'),\n remark: Schema.string().required(false).description('Optional friend remark when approving a friend request.'),\n userId: Schema.string().required(false).description('Requester user ID of a friend request; needed to apply the remark on SnowLuma.'),\n reason: Schema.string().required(false).description('Optional rejection reason for a group request.'),\n }),\n effect: 'write',\n async run(scope, args: { requestType: 'friend' | 'group', flag: string, approve: boolean, subType?: 'add' | 'invite', remark?: string, userId?: string, reason?: string }) {\n const flag = required(args.flag, 'request flag')\n const verb = args.approve ? '同意' : '拒绝'\n if (args.requestType === 'friend') {\n const remark = args.remark?.trim() ?? ''\n await callOneBot(scope.bot, 'set_friend_add_request', { flag, approve: args.approve, remark })\n const message = `已${verb}好友申请 ${flag}。`\n // SnowLuma 的 set_friend_add_request 不读 remark,同意后另用 set_friend_remark 设置。\n if (scope.protocol !== 'snowluma' || !args.approve || !remark) return message\n const userId = args.userId?.trim()\n if (!userId) return `${message}未提供申请人 userId,备注未设置。`\n await callOneBot(scope.bot, 'set_friend_remark', { user_id: numericId(userId), remark })\n return `${message}备注已设置为 ${remark}。`\n }\n if (!args.subType) throw new Error('subType is required for group requests; use add or invite.')\n await callOneBot(scope.bot, 'set_group_add_request', {\n flag,\n sub_type: args.subType,\n approve: args.approve,\n reason: args.reason?.trim() ?? '',\n })\n return `已${verb}${args.subType === 'invite' ? '群邀请' : '加群申请'} ${flag}。`\n },\n },\n setGroupKick: {\n args: Schema.args({\n groupId: groupIdArg(),\n userId: Schema.string().min(1).description('Target member user ID.'),\n }),\n effect: 'write',\n async run(scope, args: { groupId?: string, userId: string }) {\n const groupId = groupOf(scope, args.groupId)\n const userId = required(args.userId, 'userId')\n await callOneBot(scope.bot, 'set_group_kick', { group_id: groupId, user_id: userId })\n return `已将用户 ${userId} 移出群 ${groupId}。`\n },\n },\n setGroupSpecialTitle: {\n args: Schema.args({\n groupId: groupIdArg(),\n userId: Schema.string().min(1).description('Target member user ID.'),\n title: Schema.string().description('New special title. Use an empty string to clear it.'),\n }),\n effect: 'write',\n async run(scope, args: { groupId?: string, userId: string, title: string }) {\n const groupId = groupOf(scope, args.groupId)\n const userId = required(args.userId, 'userId')\n const title = args.title.trim()\n await callOneBot(scope.bot, 'set_group_special_title', { group_id: groupId, user_id: userId, special_title: title })\n return title ? `群专属头衔已更新:${userId} -> ${title}` : `群专属头衔已清除:${userId}`\n },\n },\n deleteMessage: {\n args: Schema.args({\n message_id: Schema.string().min(1).description('Specific message ID to delete.'),\n }),\n effect: 'write',\n async run(scope, args: { message_id: string }) {\n const messageId = required(args.message_id, 'message_id')\n await callOneBot(scope.bot, 'delete_msg', { message_id: numericId(messageId) })\n return `Message deleted by ID ${messageId}.`\n },\n },\n}\n\n/** 全部原生工具的定义,名称与描述统一取自 NATIVE_TOOLS。 */\nexport function nativeToolDefinitions(ctx: Context, config: Config, log: Logger): ToolDefinition[] {\n return NATIVE_TOOL_KEYS.map((key) => {\n const tool = NATIVE_TOOL_IMPLEMENTATIONS[key]\n const { toolName: name, description } = NATIVE_TOOLS[key]\n return {\n name,\n description,\n args: tool.args,\n traits: { effect: tool.effect },\n async run(args: unknown, call: ToolCallContext) {\n const location = call.location\n const bot = oneBotOf(ctx, location?.platform, location?.selfId)\n if (!bot) throw new Error('This tool only supports OneBot platform.')\n try {\n const result = await tool.run({ ctx, bot, guildId: location?.isDirect ? undefined : location?.guild, protocol: config.oneBotProtocol, agent: call.agent }, args)\n log.debug('%s: %s', name, result)\n return result\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n log.warn('%s failed: %s', name, message)\n throw new Error(`${name} failed: ${message}`)\n }\n },\n }\n })\n}\n\n/**\n * 注册原生工具。工具对所有会话全局可见(v2 的工具管理页因此能列出并开关它们),\n * 再给不在 OneBot 上的 agent 挂一层排除过滤。\n */\nexport function registerNativeTools(ctx: Context, config: Config, log: Logger) {\n const definitions = nativeToolDefinitions(ctx, config, log)\n for (const definition of definitions) ctx.tools.define(definition)\n const exclude = definitions.map((definition) => definition.name)\n log.info('native tools registered: %s', exclude.join(', '))\n ctx.inject(['agents'], (inner) => {\n const scope = (agent: Agent) => {\n if (agent.options.location?.platform !== 'onebot') inner.tools.filter({ exclude }, agent)\n }\n inner.on('chatluna/agent-open', ({ agent }) => scope(agent))\n for (const agent of inner.agents.list()) scope(agent)\n })\n}\n","import type { Context } from 'cordis'\nimport type { Bot } from '@satorijs/core'\nimport type { PromptEnvironment, VariableDeclaration, VariableProvider } from '@chatluna/prompt'\nimport type { Config, GroupInfoItem, MemberInfoItem, OneBotProtocol } from './config'\nimport { DEFAULT_GROUP_INFO_ITEMS } from './config'\nimport type { Logger } from './logger'\nimport {\n asRecord,\n asMembers,\n callOneBot,\n formatDate,\n formatDateTime,\n normalizeTimestamp,\n oneBotOf,\n pickFirst,\n pickText,\n type MemberInfo,\n} from './onebot'\n\nconst FALLBACK_MEMBER_ITEMS: MemberInfoItem[] = ['nickname', 'userId']\n\nconst SHUT_LIST_TIMEOUT_MS = 200\nconst SHUT_LIST_CACHE_TTL_MS = 15_000\n\nfunction translateGender(value: unknown): string {\n if (value === 'male') return '男'\n if (value === 'female') return '女'\n return ''\n}\n\nfunction normalizeRole(value: string): string {\n if (value === 'owner') return '群主'\n if (value === 'admin') return '管理员'\n return !value || value === 'member' ? '群员' : value\n}\n\n/** 会话所在的 Satori 机器人,任意平台;预览等没有真实机器人的环境里为 undefined。 */\nfunction botOf(ctx: Context, env: PromptEnvironment): Bot | undefined {\n return ctx.satori.bots.find((bot) => bot.platform === env.platform && bot.selfId === env.selfId)\n}\n\n/** 查询群成员信息;私聊、找不到机器人或查询失败时为 undefined,变量照常按已知信息渲染。 */\nasync function fetchMember(ctx: Context, env: PromptEnvironment, userId: string): Promise<MemberInfo | undefined> {\n const bot = botOf(ctx, env)\n if (!bot || !env.guildId) return undefined\n try {\n if (bot.platform === 'onebot') {\n return asRecord(await callOneBot(bot, 'get_group_member_info', {\n group_id: Number(env.guildId),\n user_id: Number(userId),\n no_cache: false,\n }))\n }\n const member = await bot.getGuildMember(env.guildId, userId)\n return {\n user_id: member.user?.id,\n card: pickText(member.nick, member.name),\n nickname: member.user?.name,\n role: member.roles?.[0]?.id,\n title: member.title,\n join_time: member.joinedAt,\n }\n } catch {\n return undefined\n }\n}\n\n/** 用户信息与机器人信息共用的渲染:按配置的信息项逐条输出,取不到的项省略。 */\nfunction renderMember(member: MemberInfo | undefined, items: MemberInfoItem[], id: string, fallbackName: unknown): string[] {\n const values: string[] = []\n for (const item of items) {\n switch (item) {\n case 'nickname': {\n const name = pickText(member?.card, member?.nickname, fallbackName, id)\n if (name) values.push(`name:${name}`)\n break\n }\n case 'userId':\n if (id) values.push(`id:${id}`)\n break\n case 'role':\n values.push(`群内身份:${normalizeRole(pickText(member?.role))}`)\n break\n case 'level': {\n const level = pickFirst(member?.level)\n if (level !== undefined) values.push(`群等级:${level}`)\n break\n }\n case 'title': {\n const title = pickFirst(member?.title)\n if (title !== undefined) values.push(`头衔:${title}`)\n break\n }\n case 'gender': {\n const gender = translateGender(member?.sex)\n if (gender) values.push(`性别:${gender}`)\n break\n }\n case 'age': {\n const age = Number(member?.age)\n if (Number.isFinite(age) && age > 0) values.push(`年龄:${age}`)\n break\n }\n case 'area': {\n const area = pickFirst(member?.area)\n if (area !== undefined) values.push(`地区:${area}`)\n break\n }\n case 'joinTime': {\n const joinTime = formatDate(normalizeTimestamp(member?.join_time))\n if (joinTime) values.push(`入群:${joinTime}`)\n break\n }\n case 'lastSentTime': {\n const lastSentTime = formatDateTime(normalizeTimestamp(member?.last_sent_time))\n if (lastSentTime) values.push(`活跃:${lastSentTime}`)\n break\n }\n }\n }\n return values\n}\n\nconst itemsOf = (items: MemberInfoItem[]) => items.length ? items : FALLBACK_MEMBER_ITEMS\n\nexport function userInfoProvider(ctx: Context, config: Config): VariableProvider {\n return async ({ env }) => {\n // 群聊里 userId 只来自本步最新的用户消息,工具调用后的后续步骤可能缺失,退回到消息发送者。\n const userId = (env.userId ?? env.message?.senderId)?.trim()\n if (!userId) return '未知用户'\n const member = await fetchMember(ctx, env, userId)\n const values = renderMember(member, itemsOf(config.userInfo.items), userId, env.userName ?? env.message?.senderName)\n return values.length ? values.join(', ') : `id:${userId}`\n }\n}\n\nexport function botInfoProvider(ctx: Context, config: Config): VariableProvider {\n return async ({ env }) => {\n const botId = env.selfId?.trim()\n if (!botId) return '未知机器人'\n const member = await fetchMember(ctx, env, botId)\n const values = renderMember(member, itemsOf(config.botInfo.items), botId, undefined)\n return values.length ? values.join(', ') : botId\n }\n}\n\ninterface GroupInfo {\n group_id?: unknown\n group_name?: unknown\n member_count?: unknown\n create_time?: unknown\n group_create_time?: unknown\n}\n\nasync function fetchRoles(bot: Bot, guildId: string, log: Logger): Promise<{ owners: string[], admins: string[] } | undefined> {\n try {\n const members = asMembers(await callOneBot(bot, 'get_group_member_list', { group_id: Number(guildId) }))\n if (!members.length) return undefined\n const owners: string[] = []\n const admins: string[] = []\n for (const member of members) {\n const role = member.role\n const userId = pickText(member.user_id)\n const name = pickText(member.card, member.nickname, userId)\n const label = userId ? `${name}(${userId})` : name\n if (role === 'owner') owners.push(label)\n else if (role === 'admin') admins.push(label)\n }\n return { owners, admins }\n } catch (error) {\n log.debug('group roles lookup failed: %s', String(error))\n return undefined\n }\n}\n\nfunction renderGroupInfo(group: GroupInfo, items: GroupInfoItem[], roles: { owners: string[], admins: string[] } | undefined): string {\n const id = pickText(group.group_id)\n const name = pickText(group.group_name)\n const memberCount = group.member_count\n const createTime = formatDate(normalizeTimestamp(group.create_time ?? group.group_create_time))\n const values: string[] = []\n for (const item of items) {\n switch (item) {\n case 'groupName':\n if (name) values.push(`群名:${name}`)\n break\n case 'groupId':\n if (id) values.push(`群号:${id}`)\n break\n case 'memberCount':\n if (memberCount !== undefined && memberCount !== null) values.push(`成员数量:${String(memberCount)}`)\n break\n case 'createTime':\n if (createTime) values.push(`创建时间:${createTime}`)\n break\n case 'ownerList':\n if (roles) values.push(`群主:${roles.owners.length ? roles.owners.join('、') : '无'}`)\n break\n case 'adminList':\n if (roles) values.push(`管理员:${roles.admins.length ? roles.admins.join('、') : '无'}`)\n break\n }\n }\n return values.length ? values.join('\\n') : id || name || '未能获取当前群信息。'\n}\n\nexport function groupInfoProvider(ctx: Context, config: Config, log: Logger): VariableProvider {\n return async ({ env }) => {\n if (!env.guildId) return ''\n if (env.platform !== 'onebot') return '当前平台暂不支持查询群信息。'\n const bot = oneBotOf(ctx, env.platform, env.selfId)\n if (!bot) return '暂无群信息。'\n const items = config.groupInfo.items.length ? config.groupInfo.items : DEFAULT_GROUP_INFO_ITEMS\n const group = await callOneBot(bot, 'get_group_info', { group_id: Number(env.guildId), no_cache: false })\n .then(asRecord, () => undefined)\n if (!group) return '未能获取当前群信息。'\n const roles = items.includes('ownerList') || items.includes('adminList') ? await fetchRoles(bot, env.guildId, log) : undefined\n return renderGroupInfo(group, items, roles)\n }\n}\n\nclass ShutListTimeout extends Error {}\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined\n return Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new ShutListTimeout('group shut list request timed out')), ms)\n }),\n ]).finally(() => clearTimeout(timer))\n}\n\nasync function fetchShutList(bot: Bot, guildId: string, protocol: OneBotProtocol): Promise<unknown[]> {\n const groupId = protocol === 'llbot' ? guildId : Number(guildId)\n const data = await withTimeout(callOneBot(bot, 'get_group_shut_list', { group_id: groupId }), SHUT_LIST_TIMEOUT_MS)\n return Array.isArray(data) ? data : []\n}\n\nfunction renderShutItem(item: unknown): string | undefined {\n const record = asRecord(item)\n if (!record) return undefined\n const userId = pickText(record.uin, record.user_id)\n if (!userId) return undefined\n const name = pickText(record.cardName, record.remark, record.nick, record.nickname, userId)\n const until = formatDateTime(normalizeTimestamp(pickFirst(record.shutUpTime, record.shut_up_time))) || '未知'\n return `id:${userId},name:${name},禁言截至:${until}`\n}\n\nexport function groupShutListProvider(ctx: Context, config: Config, log: Logger): VariableProvider {\n // 变量每一步都会重新渲染,同一个群的结果缓存 15 秒,避免每一步都请求一次。\n const cache = new Map<string, { value: string, expiresAt: number }>()\n return async ({ env }) => {\n if (!env.guildId) return ''\n if (env.platform !== 'onebot') return '当前平台暂不支持查询群禁言列表。'\n const bot = oneBotOf(ctx, env.platform, env.selfId)\n if (!bot) return '暂无群禁言列表。'\n const key = `${env.selfId}:${env.guildId}`\n const cached = cache.get(key)\n if (cached && cached.expiresAt > Date.now()) return cached.value\n try {\n const lines = (await fetchShutList(bot, env.guildId, config.oneBotProtocol)).flatMap((item) => renderShutItem(item) ?? [])\n const value = lines.length ? lines.join('\\n') : '当前群暂无禁言成员。'\n cache.set(key, { value, expiresAt: Date.now() + SHUT_LIST_CACHE_TTL_MS })\n return value\n } catch (error) {\n log.debug('group shut list failed: %s', String(error))\n // 部分实现在群里没有禁言成员时迟迟不响应,超时按空列表处理。\n return error instanceof ShutListTimeout ? '当前群暂无禁言成员。' : '获取群禁言列表失败。'\n }\n }\n}\n\n/** 按配置得到要注册的变量;变量名留空的不注册。 */\nexport function variableDefinitions(ctx: Context, config: Config, log: Logger): Array<[VariableDeclaration, VariableProvider]> {\n const entries: Array<[string, string, VariableProvider]> = [\n [config.userInfo.variableName, 'Current user info in this group', userInfoProvider(ctx, config)],\n [config.botInfo.variableName, 'Bot info in this group', botInfoProvider(ctx, config)],\n [config.groupInfo.variableName, 'Current group info', groupInfoProvider(ctx, config, log)],\n [config.groupShutList.variableName, 'Muted members of this group', groupShutListProvider(ctx, config, log)],\n ]\n // 都随群聊状态变化,属于可变变量,不能写进 system 区。\n return entries\n .filter(([name]) => name.trim())\n .map(([name, description, provider]) => [{ name: name.trim(), description, mutable: true }, provider])\n}\n\nexport function registerVariables(ctx: Context, config: Config, log: Logger) {\n for (const [declaration, provider] of variableDefinitions(ctx, config, log)) {\n try {\n ctx.prompt.variable(declaration, provider)\n } catch (error) {\n // 同名变量已被其他插件注册时只跳过这一个,其余变量与工具照常可用。\n log.warn('variable %s not registered: %s', declaration.name, error instanceof Error ? error.message : String(error))\n }\n }\n}\n","import type { Context } from 'cordis'\nimport type { Config } from './config'\nimport { createLogger } from './logger'\nimport { registerRequestNotices } from './requests'\nimport { registerNativeTools } from './tools'\nimport { registerVariables } from './variables'\n\nexport * from './config'\n\nexport const name = 'chatluna-onebot-toolbox'\n\n/** 过滤工具用的 agents、唤醒用的 chat 与读取会话图片用的 chatluna_storage 是可选服务。 */\nexport const inject = ['satori', 'tools', 'prompt']\n\nexport function apply(ctx: Context, config: Config) {\n const log = createLogger(ctx, config.debugLogging)\n registerVariables(ctx, config, log)\n registerNativeTools(ctx, config, log)\n registerRequestNotices(ctx, config, log)\n}\n"],"mappings":"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"}
package/lib/onebot.d.ts CHANGED
@@ -1,15 +1,8 @@
1
1
  import type { Context } from 'cordis';
2
2
  import type { Bot } from '@satorijs/core';
3
- /** Koishi OneBot 适配器的原始请求:返回完整的响应包,业务失败也照常 resolve。 */
4
- export interface OneBotInternal {
5
- _request(action: string, params: Record<string, unknown>): Promise<unknown>;
6
- }
7
- /** 会话所在的 OneBot 机器人;不是 OneBot 会话或机器人已离线时为 undefined。 */
3
+ /** 会话所在的 OneBot 机器人;不是 OneBot 会话或找不到机器人时为 undefined。 */
8
4
  export declare function oneBotOf(ctx: Context, platform: string | undefined, selfId: string | undefined): Bot | undefined;
9
- /**
10
- * 调用 OneBot action 并返回 `data`。OneBot 的业务错误以正常 resolve 的响应包返回,这里按 status 与 retcode
11
- * 判定失败并抛出,错误信息取实现给出的 wording/message。
12
- */
5
+ /** 调用 OneBot action 并返回 data,按响应包的 status 与 retcode 判定业务失败。 */
13
6
  export declare function callOneBot(bot: Bot, action: string, params: Record<string, unknown>): Promise<unknown>;
14
7
  /**
15
8
  * 整数形式的 ID 转成数字,其余原样保留;OneBot 实现普遍要求数字形式的群号、QQ 号与消息 ID。
@@ -19,60 +12,24 @@ export declare function numericId(value: string): string | number;
19
12
  /** 取第一个非空值(去掉首尾空白后不为空字符串),保留原始类型。 */
20
13
  export declare function pickFirst(...values: unknown[]): string | number | undefined;
21
14
  export declare function pickText(...values: unknown[]): string;
22
- /** OneBot 时间戳可能是秒或毫秒,统一成毫秒;空值与 0 视为没有。 */
15
+ /** OneBot 使用秒,Satori 使用毫秒,统一成毫秒;空值与 0 视为没有。 */
23
16
  export declare function normalizeTimestamp(raw: unknown): number | undefined;
24
17
  export declare function formatDate(value: number | undefined): string;
25
18
  export declare function formatDateTime(value: number | undefined): string;
26
- /** 群成员信息的常见字段;各 OneBot 实现与 Satori 的字段名不同,读取时逐个尝试。 */
19
+ /** OneBot 群成员信息;其他平台的 Satori 成员信息在查询入口显式转换。 */
27
20
  export interface MemberInfo {
28
21
  user_id?: unknown;
29
- userId?: unknown;
30
- id?: unknown;
31
- qq?: unknown;
32
- uid?: unknown;
33
22
  role?: unknown;
34
- roleName?: unknown;
35
- permission?: unknown;
36
- identity?: unknown;
37
- roles?: unknown;
38
23
  card?: unknown;
39
- remark?: unknown;
40
- displayName?: unknown;
41
- nick?: unknown;
42
24
  nickname?: unknown;
43
- name?: unknown;
44
25
  level?: unknown;
45
- levelName?: unknown;
46
- level_name?: unknown;
47
- level_info?: {
48
- current_level?: unknown;
49
- };
50
26
  title?: unknown;
51
- specialTitle?: unknown;
52
- special_title?: unknown;
53
27
  sex?: unknown;
54
- gender?: unknown;
55
28
  age?: unknown;
56
29
  area?: unknown;
57
- region?: unknown;
58
- location?: unknown;
59
30
  join_time?: unknown;
60
- joined_at?: unknown;
61
- joinTime?: unknown;
62
- joinedAt?: unknown;
63
31
  last_sent_time?: unknown;
64
- lastSentTime?: unknown;
65
- lastSpeakTimestamp?: unknown;
66
- user?: {
67
- nick?: unknown;
68
- nickname?: unknown;
69
- name?: unknown;
70
- };
71
32
  }
72
33
  export declare function asMembers(value: unknown): MemberInfo[];
73
- export declare function asMember(value: unknown): MemberInfo | undefined;
74
- export declare function memberUserId(member: MemberInfo): string;
75
- export declare function memberCard(member: MemberInfo): string;
76
- export declare function memberNickname(member: MemberInfo): string;
77
- export declare function memberRole(member: MemberInfo): string;
34
+ export declare function asRecord(value: unknown): Record<string, unknown> | undefined;
78
35
  //# sourceMappingURL=onebot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"onebot.d.ts","sourceRoot":"","sources":["../src/onebot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"onebot.d.ts","sourceRoot":"","sources":["../src/onebot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AAUzC,wDAAwD;AACxD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,GAAG,SAAS,CAGhH;AAED,+DAA+D;AAC/D,wBAAsB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAS5G;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAExD;AAED,qCAAqC;AACrC,wBAAgB,SAAS,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAO3E;AAED,wBAAgB,QAAQ,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAErD;AAED,+CAA+C;AAC/C,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKnE;AAID,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAK5D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAKhE;AAED,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,EAAE,CAEtD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAE5E"}
package/lib/tools.d.ts CHANGED
@@ -22,11 +22,11 @@ interface NativeTool<A> {
22
22
  export declare const NATIVE_TOOL_IMPLEMENTATIONS: {
23
23
  [K in NativeToolKey]: NativeTool<any>;
24
24
  };
25
- /** 全部原生工具的定义,名称与描述固定为源插件的默认值。 */
25
+ /** 全部原生工具的定义,名称与描述统一取自 NATIVE_TOOLS。 */
26
26
  export declare function nativeToolDefinitions(ctx: Context, config: Config, log: Logger): ToolDefinition[];
27
27
  /**
28
28
  * 注册原生工具。工具对所有会话全局可见(v2 的工具管理页因此能列出并开关它们),
29
- * 再给不在 OneBot 上的 agent 挂一层排除过滤,与源插件只在 OneBot 会话授权一致。
29
+ * 再给不在 OneBot 上的 agent 挂一层排除过滤。
30
30
  */
31
31
  export declare function registerNativeTools(ctx: Context, config: Config, log: Logger): void;
32
32
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAKrE,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAErE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAYtC,4BAA4B;AAC5B,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,OAAO,CAAA;IACZ,GAAG,EAAE,GAAG,CAAA;IACR,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,cAAc,CAAA;IACxB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,UAAU,UAAU,CAAC,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACpB,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CAChD;AA0FD,eAAO,MAAM,2BAA2B,EAAE;KAAG,CAAC,IAAI,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC;CAuJhF,CAAA;AAED,iCAAiC;AACjC,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CAyBjG;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,QAY5E"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,KAAK,EAAmB,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAKrE,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAErE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAUtC,4BAA4B;AAC5B,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,OAAO,CAAA;IACZ,GAAG,EAAE,GAAG,CAAA;IACR,2BAA2B;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,cAAc,CAAA;IACxB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,UAAU,UAAU,CAAC,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACpB,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CAChD;AA0FD,eAAO,MAAM,2BAA2B,EAAE;KAAG,CAAC,IAAI,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC;CAuJhF,CAAA;AAED,wCAAwC;AACxC,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CAyBjG;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,QAY5E"}
@@ -1 +1 @@
1
- {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../src/variables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAErC,OAAO,KAAK,EAAqB,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAChG,OAAO,KAAK,EAAE,MAAM,EAAiD,MAAM,UAAU,CAAA;AAErF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AA2HtC,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAS/E;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAQ9E;AAqED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAa7F;AA4CD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAsBjG;AAED,6BAA6B;AAC7B,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAC,CAW7H;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,QAS1E"}
1
+ {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../src/variables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAErC,OAAO,KAAK,EAAqB,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAChG,OAAO,KAAK,EAAE,MAAM,EAAiD,MAAM,UAAU,CAAA;AAErF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAwHtC,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAS/E;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAQ9E;AA8DD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAa7F;AA8BD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAsBjG;AAED,6BAA6B;AAC7B,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAC,CAW7H;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,QAS1E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatluna-plugin-onebot-toolbox",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "为 ChatLuna 提供 OneBot 原生工具与群聊信息变量:修改资料与头像、群名片与头衔、搜索群成员、退群、踢人、处理申请、撤回消息",
5
5
  "type": "module",
6
6
  "license": "MIT",