koishi-plugin-chatluna-toolbox 0.0.13 → 0.0.16

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.
Files changed (3) hide show
  1. package/README.md +4 -0
  2. package/lib/index.js +273 -45
  3. package/package.json +4 -4
package/README.md CHANGED
@@ -13,10 +13,14 @@
13
13
  ### 1) 原生工具
14
14
  - 戳一戳
15
15
  - 设置自身资料
16
+ - 设置 QQ 头像
16
17
  - 设置群名片
18
+ - 设置群成员专属头衔
17
19
  - 给消息添加表情
18
20
  - 撤回消息
19
21
 
22
+ QQ 头像工具会把 HTTP/HTTPS 图片先转为 OneBot `base64://` 文件再提交,避免 OneBot 端无法访问 Koishi 临时图片地址。
23
+
20
24
  ### 2) XML 工具
21
25
  支持从模型输出中解析 XML 动作标签并执行:
22
26
 
package/lib/index.js CHANGED
@@ -423,8 +423,10 @@ __export(index_exports, {
423
423
  createRandomProvider: () => createRandomProvider,
424
424
  createSetGroupBanTool: () => createSetGroupBanTool,
425
425
  createSetGroupCardTool: () => createSetGroupCardTool,
426
+ createSetGroupSpecialTitleTool: () => createSetGroupSpecialTitleTool,
426
427
  createSetMsgEmojiTool: () => createSetMsgEmojiTool,
427
428
  createSetProfileTool: () => createSetProfileTool,
429
+ createSetQQAvatarTool: () => createSetQQAvatarTool,
428
430
  createUserInfoProvider: () => createUserInfoProvider,
429
431
  createXmlProcessor: () => createXmlProcessor,
430
432
  ensureOneBotSession: () => ensureOneBotSession,
@@ -443,7 +445,9 @@ __export(index_exports, {
443
445
  sendMsgEmoji: () => sendMsgEmoji,
444
446
  sendPoke: () => sendPoke,
445
447
  sendSetGroupCard: () => sendSetGroupCard,
446
- sendSetProfile: () => sendSetProfile
448
+ sendSetGroupSpecialTitle: () => sendSetGroupSpecialTitle,
449
+ sendSetProfile: () => sendSetProfile,
450
+ sendSetQQAvatar: () => sendSetQQAvatar
447
451
  });
448
452
  module.exports = __toCommonJS(index_exports);
449
453
 
@@ -463,8 +467,10 @@ var import_koishi2 = require("koishi");
463
467
  // src/features/native-tools/defaults.ts
464
468
  var DEFAULT_POKE_TOOL_DESCRIPTION = "\u5BF9\u6307\u5B9A\u7528\u6237\u6267\u884C\u6233\u4E00\u6233\u3002";
465
469
  var DEFAULT_SET_SELF_PROFILE_TOOL_DESCRIPTION = "\u4FEE\u6539\u81EA\u5DF1\u7684 QQ \u8D44\u6599\uFF0C\u53EF\u8BBE\u7F6E\u6635\u79F0\u3001\u7B7E\u540D\u548C\u6027\u522B\u3002";
470
+ var DEFAULT_SET_QQ_AVATAR_TOOL_DESCRIPTION = "\u4FEE\u6539\u673A\u5668\u4EBA QQ \u5934\u50CF\u3002\u63D0\u4F9B imageUrl\uFF1BHTTP/HTTPS \u56FE\u7247\u4F1A\u5148\u7531 Koishi \u8BFB\u53D6\u5E76\u8F6C\u4E3A OneBot base64 \u6587\u4EF6\uFF0C\u907F\u514D\u4E34\u65F6 URL \u8FC7\u671F\u6216 OneBot \u7AEF\u65E0\u6CD5\u8BBF\u95EE\u3002";
466
471
  var DEFAULT_SET_GROUP_CARD_TOOL_DESCRIPTION = "\u4FEE\u6539\u7FA4\u6210\u5458\u7684\u7FA4\u6635\u79F0\u3002";
467
472
  var DEFAULT_SET_GROUP_BAN_TOOL_DESCRIPTION = "\u7528\u4E8E\u7BA1\u7406\u7FA4\u6210\u5458\u7981\u8A00\u72B6\u6001\uFF0C\u53EF\u8BBE\u7F6E\u7981\u8A00\u65F6\u957F\u6216\u89E3\u9664\u7981\u8A00\u3002";
473
+ var DEFAULT_SET_GROUP_SPECIAL_TITLE_TOOL_DESCRIPTION = "\u4FEE\u6539\u6216\u6E05\u9664\u7FA4\u6210\u5458\u7684 QQ \u7FA4\u4E13\u5C5E\u5934\u8854\u3002";
468
474
  var DEFAULT_SET_MSG_EMOJI_TOOL_DESCRIPTION = "\u5BF9\u6307\u5B9A\u6D88\u606F\u6DFB\u52A0\u8868\u60C5\u56DE\u5E94\u3002";
469
475
  var DEFAULT_DELETE_MESSAGE_TOOL_DESCRIPTION = "\u6839\u636E\u6D88\u606F ID \u64A4\u56DE\u6307\u5B9A\u6D88\u606F\u3002";
470
476
 
@@ -482,6 +488,11 @@ var NativeToolsSchema = import_koishi2.Schema.object({
482
488
  toolName: import_koishi2.Schema.string().default("set_self_profile").description("\u5DE5\u5177\u540D\u79F0"),
483
489
  description: import_koishi2.Schema.string().default(DEFAULT_SET_SELF_PROFILE_TOOL_DESCRIPTION).description("\u5DE5\u5177\u63CF\u8FF0")
484
490
  }).description("\u4FEE\u6539\u81EA\u8EAB\u8D26\u6237\u4FE1\u606F\u5DE5\u5177").collapse(),
491
+ setQQAvatar: import_koishi2.Schema.object({
492
+ enabled: import_koishi2.Schema.boolean().default(false).description("\u6CE8\u518C ChatLuna \u5DE5\u5177\uFF1A\u4FEE\u6539\u673A\u5668\u4EBA QQ \u5934\u50CF"),
493
+ toolName: import_koishi2.Schema.string().default("set_qq_avatar").description("\u5DE5\u5177\u540D\u79F0"),
494
+ description: import_koishi2.Schema.string().default(DEFAULT_SET_QQ_AVATAR_TOOL_DESCRIPTION).description("\u5DE5\u5177\u63CF\u8FF0")
495
+ }).description("\u4FEE\u6539 QQ \u5934\u50CF\u5DE5\u5177").collapse(),
485
496
  setGroupCard: import_koishi2.Schema.object({
486
497
  enabled: import_koishi2.Schema.boolean().default(false).description("\u6CE8\u518C ChatLuna \u5DE5\u5177\uFF1A\u4FEE\u6539\u7FA4\u6210\u5458\u6635\u79F0"),
487
498
  toolName: import_koishi2.Schema.string().default("set_group_card").description("\u5DE5\u5177\u540D\u79F0"),
@@ -492,6 +503,11 @@ var NativeToolsSchema = import_koishi2.Schema.object({
492
503
  toolName: import_koishi2.Schema.string().default("set_group_ban").description("\u5DE5\u5177\u540D\u79F0"),
493
504
  description: import_koishi2.Schema.string().default(DEFAULT_SET_GROUP_BAN_TOOL_DESCRIPTION).description("\u5DE5\u5177\u63CF\u8FF0")
494
505
  }).description("\u7981\u8A00\u5DE5\u5177").collapse(),
506
+ setGroupSpecialTitle: import_koishi2.Schema.object({
507
+ enabled: import_koishi2.Schema.boolean().default(false).description("\u6CE8\u518C ChatLuna \u5DE5\u5177\uFF1A\u4FEE\u6539\u7FA4\u6210\u5458\u4E13\u5C5E\u5934\u8854"),
508
+ toolName: import_koishi2.Schema.string().default("set_group_special_title").description("\u5DE5\u5177\u540D\u79F0"),
509
+ description: import_koishi2.Schema.string().default(DEFAULT_SET_GROUP_SPECIAL_TITLE_TOOL_DESCRIPTION).description("\u5DE5\u5177\u63CF\u8FF0")
510
+ }).description("\u4FEE\u6539\u7FA4\u6210\u5458\u4E13\u5C5E\u5934\u8854\u5DE5\u5177").collapse(),
495
511
  setMsgEmoji: import_koishi2.Schema.object({
496
512
  enabled: import_koishi2.Schema.boolean().default(false).description(
497
513
  "\u6CE8\u518C ChatLuna \u5DE5\u5177\uFF1A\u7ED9\u6D88\u606F\u6DFB\u52A0\u8868\u60C5\uFF08\u9700 chatluna-character \u5F00\u542F enableMessageId\uFF0C\u4E0E XML\u5DE5\u5177 \u4E8C\u9009\u4E00\uFF0C\u8868\u60C5\u5BF9\u7167\u8868\uFF1Ahttps://bot.q.qq.com/wiki/develop/pythonsdk/model/emoji.html \uFF09"
@@ -517,6 +533,11 @@ var NativeToolsSchema = import_koishi2.Schema.object({
517
533
  toolName: "set_self_profile",
518
534
  description: DEFAULT_SET_SELF_PROFILE_TOOL_DESCRIPTION
519
535
  },
536
+ setQQAvatar: {
537
+ enabled: false,
538
+ toolName: "set_qq_avatar",
539
+ description: DEFAULT_SET_QQ_AVATAR_TOOL_DESCRIPTION
540
+ },
520
541
  setGroupCard: {
521
542
  enabled: false,
522
543
  toolName: "set_group_card",
@@ -527,6 +548,11 @@ var NativeToolsSchema = import_koishi2.Schema.object({
527
548
  toolName: "set_group_ban",
528
549
  description: DEFAULT_SET_GROUP_BAN_TOOL_DESCRIPTION
529
550
  },
551
+ setGroupSpecialTitle: {
552
+ enabled: false,
553
+ toolName: "set_group_special_title",
554
+ description: DEFAULT_SET_GROUP_SPECIAL_TITLE_TOOL_DESCRIPTION
555
+ },
530
556
  setMsgEmoji: {
531
557
  enabled: false,
532
558
  toolName: "set_msg_emoji",
@@ -563,13 +589,12 @@ var DEFAULT_XML_REFERENCE_PROMPT = `## \u52A8\u4F5C\u6307\u4EE4
563
589
  - id: user_id
564
590
  - duration: \u7981\u8A00\u65F6\u957F\uFF0C\u5355\u4F4D\u79D2\uFF0C\u4F20 0 \u8868\u793A\u89E3\u9664\u7981\u8A00
565
591
  - \u9002\u7528\u573A\u666F:
566
- - \u4F60\u5728\u672C\u7FA4\u4E3A\u7BA1\u7406\u5458
567
- - \u7528\u4E8E\u7981\u8A00\u6216\u89E3\u9664\u7981\u8A00\u6307\u5B9A\u7FA4\u6210\u5458
592
+ - \u4F60\u5728\u672C\u7FA4\u4E3A\u7BA1\u7406\u5458\u65F6\u7528\u4E8E\u7981\u8A00\u6216\u89E3\u9664\u7981\u8A00\u6307\u5B9A\u7FA4\u6210\u5458
568
593
  4. \u64A4\u56DE\u6D88\u606F: <delete message_id=""/>
569
594
  - message_id: \u6D88\u606F ID
570
595
  - \u9002\u7528\u573A\u666F:
571
- - \u4F60\u5728\u672C\u7FA4\u4E3A\u7BA1\u7406\u5458
572
- - \u7528\u4E8E\u64A4\u56DE\u6307\u5B9A\u6D88\u606F
596
+ - \u64A4\u56DE\u81EA\u5DF1\u53D1\u7684\u6D88\u606F
597
+ - \u4F60\u5728\u672C\u7FA4\u4E3A\u7BA1\u7406\u5458\u65F6\u64A4\u56DE\u5176\u4ED6\u7528\u6237\u53D1\u9001\u7684\u6D88\u606F
573
598
 
574
599
  \u683C\u5F0F\u793A\u4F8B:
575
600
  \`\`\`xml
@@ -734,6 +759,7 @@ function createLogger(ctx, config) {
734
759
 
735
760
  // src/features/native-tools/tools/delete-msg.ts
736
761
  var import_zod = require("zod");
762
+ var import_tools = require("@langchain/core/tools");
737
763
 
738
764
  // src/features/native-tools/onebot-api.ts
739
765
  function ensureOneBotSession(session) {
@@ -763,19 +789,33 @@ function getSession(runnable) {
763
789
  }
764
790
 
765
791
  // src/features/native-tools/tools/delete-msg.ts
792
+ function assertOneBotSuccess(result) {
793
+ const response = result;
794
+ if (!response || typeof response !== "object") return;
795
+ const status = String(response.status || "").toLowerCase();
796
+ const failed = status === "failed" || !!status && status !== "ok" || typeof response.retcode === "number" && response.retcode !== 0;
797
+ if (!failed) return;
798
+ const reason = response.wording || response.message || response.status;
799
+ const retcode = typeof response.retcode === "number" ? ` (retcode: ${response.retcode})` : "";
800
+ throw new Error(`${reason || "OneBot returned failed"}${retcode}`);
801
+ }
766
802
  async function sendDeleteMessage(params) {
767
- const { session, messageId, log } = params;
803
+ const { session, message_id, log } = params;
768
804
  try {
769
805
  if (!session) return "No session context available.";
770
- const messageIdRaw = messageId.trim();
771
- if (!messageIdRaw) return "messageId is required.";
806
+ const messageIdRaw = message_id.trim();
807
+ if (!messageIdRaw) return "message_id is required.";
772
808
  const numericId = /^\d+$/.test(messageIdRaw) ? Number(messageIdRaw) : messageIdRaw;
773
809
  if (session.platform === "onebot") {
774
810
  const { error, internal } = ensureOneBotSession(session);
775
811
  if (error) return error;
776
- await callOneBotAPI(internal, "delete_msg", { message_id: numericId }, [
777
- "deleteMsg"
778
- ]);
812
+ const result = await callOneBotAPI(
813
+ internal,
814
+ "delete_msg",
815
+ { message_id: numericId },
816
+ ["deleteMsg"]
817
+ );
818
+ assertOneBotSuccess(result);
779
819
  const success = `Message deleted by ID ${messageIdRaw}.`;
780
820
  log?.("info", success);
781
821
  return success;
@@ -797,18 +837,18 @@ async function sendDeleteMessage(params) {
797
837
  }
798
838
  function createDeleteMessageTool(deps) {
799
839
  const { toolName, description, log } = deps;
800
- const tool = {
801
- name: toolName || "delete_msg",
802
- description: description || DEFAULT_DELETE_MESSAGE_TOOL_DESCRIPTION,
803
- schema: import_zod.z.object({
804
- messageId: import_zod.z.string().min(1, "messageId is required").describe("Specific message ID to delete.")
805
- }),
840
+ return new class extends import_tools.StructuredTool {
841
+ name = toolName || "delete_msg";
842
+ description = description || DEFAULT_DELETE_MESSAGE_TOOL_DESCRIPTION;
843
+ schema = import_zod.z.object({
844
+ message_id: import_zod.z.string().min(1, "message_id is required").describe("Specific message ID to delete.")
845
+ }).strict();
806
846
  async _call(input, _manager, runnable) {
807
847
  try {
808
848
  const session = getSession(runnable);
809
849
  return await sendDeleteMessage({
810
850
  session,
811
- messageId: input.messageId,
851
+ message_id: input.message_id,
812
852
  log
813
853
  });
814
854
  } catch (error) {
@@ -816,13 +856,12 @@ function createDeleteMessageTool(deps) {
816
856
  return `delete_msg failed: ${error.message}`;
817
857
  }
818
858
  }
819
- };
820
- return tool;
859
+ }();
821
860
  }
822
861
 
823
862
  // src/features/native-tools/tools/poke.ts
824
863
  var import_zod2 = require("zod");
825
- var import_tools = require("@langchain/core/tools");
864
+ var import_tools2 = require("@langchain/core/tools");
826
865
  async function sendPoke(params) {
827
866
  try {
828
867
  const { session, userId, groupId, log, protocol } = params;
@@ -832,11 +871,11 @@ async function sendPoke(params) {
832
871
  session: validatedSession
833
872
  } = ensureOneBotSession(session);
834
873
  if (error) return error;
835
- const resolvedGroupId = groupId?.trim() || validatedSession?.guildId || validatedSession?.channelId || validatedSession?.roomId;
874
+ const resolvedGroupId = groupId?.trim() || validatedSession?.guildId || validatedSession?.roomId;
836
875
  const payload = { user_id: userId };
837
876
  if (resolvedGroupId) payload.group_id = resolvedGroupId;
877
+ const action = payload.group_id ? "group_poke" : "friend_poke";
838
878
  if (protocol === "llbot") {
839
- const action = payload.group_id ? "group_poke" : "friend_poke";
840
879
  if (typeof internal._request === "function") {
841
880
  await internal._request(action, payload);
842
881
  } else if (typeof internal[action] === "function") {
@@ -845,7 +884,9 @@ async function sendPoke(params) {
845
884
  throw new Error(`\u5F53\u524D\u9002\u914D\u5668\u672A\u5B9E\u73B0 ${action} API\u3002`);
846
885
  }
847
886
  } else if (typeof internal._request === "function") {
848
- await internal._request("send_poke", payload);
887
+ await internal._request(action, payload);
888
+ } else if (typeof internal[action] === "function") {
889
+ await internal[action](payload);
849
890
  } else if (typeof internal.sendPoke === "function") {
850
891
  await internal.sendPoke(
851
892
  payload.group_id,
@@ -867,7 +908,7 @@ async function sendPoke(params) {
867
908
  }
868
909
  function createPokeTool(deps) {
869
910
  const { toolName, description, log, protocol } = deps;
870
- return new class extends import_tools.StructuredTool {
911
+ return new class extends import_tools2.StructuredTool {
871
912
  name = toolName || "poke_user";
872
913
  description = description || DEFAULT_POKE_TOOL_DESCRIPTION;
873
914
  schema = import_zod2.z.object({
@@ -889,7 +930,7 @@ function createPokeTool(deps) {
889
930
 
890
931
  // src/features/native-tools/tools/set-group-ban.ts
891
932
  var import_zod3 = require("zod");
892
- var import_tools2 = require("@langchain/core/tools");
933
+ var import_tools3 = require("@langchain/core/tools");
893
934
  function resolveGroupId(session, groupId) {
894
935
  return groupId?.trim() || (session.guildId || "").trim() || (session.channelId || "").trim() || (session.roomId || "").trim();
895
936
  }
@@ -939,7 +980,7 @@ async function sendGroupBan(params) {
939
980
  }
940
981
  function createSetGroupBanTool(deps) {
941
982
  const { toolName, description, protocol, log } = deps;
942
- return new class extends import_tools2.StructuredTool {
983
+ return new class extends import_tools3.StructuredTool {
943
984
  name = toolName || "set_group_ban";
944
985
  description = description || DEFAULT_SET_GROUP_BAN_TOOL_DESCRIPTION;
945
986
  schema = import_zod3.z.object({
@@ -963,7 +1004,7 @@ function createSetGroupBanTool(deps) {
963
1004
 
964
1005
  // src/features/native-tools/tools/set-group-card.ts
965
1006
  var import_zod4 = require("zod");
966
- var import_tools3 = require("@langchain/core/tools");
1007
+ var import_tools4 = require("@langchain/core/tools");
967
1008
  async function sendSetGroupCard(params) {
968
1009
  try {
969
1010
  const { session, userId, card, groupId, log } = params;
@@ -994,7 +1035,7 @@ async function sendSetGroupCard(params) {
994
1035
  }
995
1036
  function createSetGroupCardTool(deps) {
996
1037
  const { toolName, description, log } = deps;
997
- return new class extends import_tools3.StructuredTool {
1038
+ return new class extends import_tools4.StructuredTool {
998
1039
  name = toolName || "set_group_card";
999
1040
  description = description || DEFAULT_SET_GROUP_CARD_TOOL_DESCRIPTION;
1000
1041
  schema = import_zod4.z.object({
@@ -1014,9 +1055,73 @@ function createSetGroupCardTool(deps) {
1014
1055
  }();
1015
1056
  }
1016
1057
 
1017
- // src/features/native-tools/tools/set-msg-emoji.ts
1058
+ // src/features/native-tools/tools/set-group-special-title.ts
1018
1059
  var import_zod5 = require("zod");
1019
- var import_tools4 = require("@langchain/core/tools");
1060
+ var import_tools5 = require("@langchain/core/tools");
1061
+ function resolveGroupId2(session, groupId) {
1062
+ return groupId?.trim() || (session.guildId || "").trim() || (session.channelId || "").trim() || (session.roomId || "").trim();
1063
+ }
1064
+ async function sendSetGroupSpecialTitle(params) {
1065
+ try {
1066
+ const { session, userId, groupId, title, log } = params;
1067
+ const {
1068
+ error,
1069
+ internal,
1070
+ session: validatedSession
1071
+ } = ensureOneBotSession(session);
1072
+ if (error) return error;
1073
+ const resolvedGroupId = resolveGroupId2(validatedSession, groupId);
1074
+ if (!resolvedGroupId) {
1075
+ return "Missing groupId. Provide groupId explicitly or run inside a group session.";
1076
+ }
1077
+ const userIdRaw = userId.trim();
1078
+ if (!userIdRaw) return "userId is required.";
1079
+ const titleRaw = title.trim();
1080
+ await callOneBotAPI(
1081
+ internal,
1082
+ "set_group_special_title",
1083
+ {
1084
+ group_id: resolvedGroupId,
1085
+ user_id: userIdRaw,
1086
+ special_title: titleRaw
1087
+ },
1088
+ ["setGroupSpecialTitle"]
1089
+ );
1090
+ const message = titleRaw ? `\u7FA4\u4E13\u5C5E\u5934\u8854\u5DF2\u66F4\u65B0\uFF1A${userIdRaw} -> ${titleRaw}` : `\u7FA4\u4E13\u5C5E\u5934\u8854\u5DF2\u6E05\u9664\uFF1A${userIdRaw}`;
1091
+ log?.("info", message);
1092
+ return message;
1093
+ } catch (error) {
1094
+ params.log?.("warn", "set_group_special_title failed", error);
1095
+ return `set_group_special_title failed: ${error.message}`;
1096
+ }
1097
+ }
1098
+ function createSetGroupSpecialTitleTool(deps) {
1099
+ const { toolName, description, protocol, log } = deps;
1100
+ return new class extends import_tools5.StructuredTool {
1101
+ name = toolName || "set_group_special_title";
1102
+ description = description || DEFAULT_SET_GROUP_SPECIAL_TITLE_TOOL_DESCRIPTION;
1103
+ schema = import_zod5.z.object({
1104
+ groupId: import_zod5.z.string().optional().describe("Target group ID. Defaults to current session group."),
1105
+ userId: import_zod5.z.string().min(1, "userId is required").describe("Target member user ID."),
1106
+ title: import_zod5.z.string().describe("New special title. Use an empty string to clear it.")
1107
+ });
1108
+ async _call(input, _manager, runnable) {
1109
+ const session = getSession(runnable);
1110
+ return sendSetGroupSpecialTitle({
1111
+ session,
1112
+ userId: input.userId,
1113
+ title: input.title,
1114
+ groupId: input.groupId,
1115
+ protocol,
1116
+ log
1117
+ });
1118
+ }
1119
+ }();
1120
+ }
1121
+
1122
+ // src/features/native-tools/tools/set-msg-emoji.ts
1123
+ var import_zod6 = require("zod");
1124
+ var import_tools6 = require("@langchain/core/tools");
1020
1125
  async function sendMsgEmoji(params) {
1021
1126
  try {
1022
1127
  const { session, messageId, emojiId, log, protocol } = params;
@@ -1047,12 +1152,12 @@ async function sendMsgEmoji(params) {
1047
1152
  }
1048
1153
  function createSetMsgEmojiTool(deps) {
1049
1154
  const { toolName, description, log, protocol } = deps;
1050
- return new class extends import_tools4.StructuredTool {
1155
+ return new class extends import_tools6.StructuredTool {
1051
1156
  name = toolName || "set_msg_emoji";
1052
1157
  description = description || DEFAULT_SET_MSG_EMOJI_TOOL_DESCRIPTION;
1053
- schema = import_zod5.z.object({
1054
- messageId: import_zod5.z.string().min(1, "message_id is required").describe("Target message ID."),
1055
- emojiId: import_zod5.z.string().min(1, "emoji_id is required").describe("Emoji ID to send.")
1158
+ schema = import_zod6.z.object({
1159
+ messageId: import_zod6.z.string().min(1, "message_id is required").describe("Target message ID."),
1160
+ emojiId: import_zod6.z.string().min(1, "emoji_id is required").describe("Emoji ID to send.")
1056
1161
  });
1057
1162
  async _call(input, _manager, runnable) {
1058
1163
  const session = getSession(runnable);
@@ -1068,8 +1173,8 @@ function createSetMsgEmojiTool(deps) {
1068
1173
  }
1069
1174
 
1070
1175
  // src/features/native-tools/tools/profile.ts
1071
- var import_zod6 = require("zod");
1072
- var import_tools5 = require("@langchain/core/tools");
1176
+ var import_zod7 = require("zod");
1177
+ var import_tools7 = require("@langchain/core/tools");
1073
1178
  var genders = {
1074
1179
  unknown: "0",
1075
1180
  male: "1",
@@ -1096,13 +1201,13 @@ async function sendSetProfile(params) {
1096
1201
  }
1097
1202
  function createSetProfileTool(deps) {
1098
1203
  const { toolName, description, log, protocol } = deps;
1099
- return new class extends import_tools5.StructuredTool {
1204
+ return new class extends import_tools7.StructuredTool {
1100
1205
  name = toolName || "set_self_profile";
1101
1206
  description = description || DEFAULT_SET_SELF_PROFILE_TOOL_DESCRIPTION;
1102
- schema = import_zod6.z.object({
1103
- nickname: import_zod6.z.string().min(1, "nickname is required").describe("The new nickname for the bot."),
1104
- signature: import_zod6.z.string().optional().describe("Optional: the new personal signature."),
1105
- gender: import_zod6.z.enum(["unknown", "male", "female"]).optional().describe("Optional: the new gender.")
1207
+ schema = import_zod7.z.object({
1208
+ nickname: import_zod7.z.string().min(1, "nickname is required").describe("The new nickname for the bot."),
1209
+ signature: import_zod7.z.string().optional().describe("Optional: the new personal signature."),
1210
+ gender: import_zod7.z.enum(["unknown", "male", "female"]).optional().describe("Optional: the new gender.")
1106
1211
  });
1107
1212
  async _call(input, _manager, runnable) {
1108
1213
  return sendSetProfile({
@@ -1117,6 +1222,84 @@ function createSetProfileTool(deps) {
1117
1222
  }();
1118
1223
  }
1119
1224
 
1225
+ // src/features/native-tools/tools/set-qq-avatar.ts
1226
+ var import_zod8 = require("zod");
1227
+ var import_tools8 = require("@langchain/core/tools");
1228
+ function isHttpUrl(value) {
1229
+ return /^https?:\/\//i.test(value);
1230
+ }
1231
+ function toBuffer(data) {
1232
+ if (Buffer.isBuffer(data)) return data;
1233
+ if (data instanceof ArrayBuffer) return Buffer.from(data);
1234
+ if (ArrayBuffer.isView(data)) {
1235
+ return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
1236
+ }
1237
+ if (typeof data === "string") return Buffer.from(data);
1238
+ throw new Error("unsupported image response body.");
1239
+ }
1240
+ async function fetchImageAsOneBotFile(ctx, imageUrl) {
1241
+ if (!isHttpUrl(imageUrl)) return imageUrl;
1242
+ try {
1243
+ const http = ctx?.http;
1244
+ const data = typeof http?.get === "function" ? await http.get(imageUrl, { responseType: "arraybuffer" }) : await fetch(imageUrl).then(async (response) => {
1245
+ if (!response.ok) {
1246
+ throw new Error(`HTTP ${response.status}`);
1247
+ }
1248
+ return response.arrayBuffer();
1249
+ });
1250
+ return `base64://${toBuffer(data).toString("base64")}`;
1251
+ } catch (error) {
1252
+ throw new Error(`\u65E0\u6CD5\u8BFB\u53D6\u5934\u50CF\u56FE\u7247\uFF1A${error.message}`);
1253
+ }
1254
+ }
1255
+ function assertOneBotSuccess2(result) {
1256
+ const response = result;
1257
+ if (!response || typeof response !== "object") return;
1258
+ const failed = response.status === "failed" || typeof response.retcode === "number" && response.retcode !== 0;
1259
+ if (!failed) return;
1260
+ const reason = response.wording || response.message || response.status;
1261
+ const retcode = typeof response.retcode === "number" ? ` (retcode: ${response.retcode})` : "";
1262
+ throw new Error(`${reason || "OneBot returned failed"}${retcode}`);
1263
+ }
1264
+ async function sendSetQQAvatar(params) {
1265
+ const { ctx, session, log } = params;
1266
+ try {
1267
+ const imageUrl = params.imageUrl.trim();
1268
+ if (!imageUrl) return "imageUrl is required.";
1269
+ const { error, internal } = ensureOneBotSession(session);
1270
+ if (error) return error;
1271
+ const file = await fetchImageAsOneBotFile(ctx, imageUrl);
1272
+ const result = await callOneBotAPI(internal, "set_qq_avatar", { file }, [
1273
+ "setQQAvatar"
1274
+ ]);
1275
+ assertOneBotSuccess2(result);
1276
+ const message = "QQ \u5934\u50CF\u5DF2\u66F4\u65B0\u3002";
1277
+ log?.("info", message);
1278
+ return message;
1279
+ } catch (error) {
1280
+ log?.("warn", "set_qq_avatar failed", error);
1281
+ return `set_qq_avatar failed: ${error.message}`;
1282
+ }
1283
+ }
1284
+ function createSetQQAvatarTool(deps) {
1285
+ const { ctx, toolName, description, log } = deps;
1286
+ return new class extends import_tools8.StructuredTool {
1287
+ name = toolName || "set_qq_avatar";
1288
+ description = description || DEFAULT_SET_QQ_AVATAR_TOOL_DESCRIPTION;
1289
+ schema = import_zod8.z.object({
1290
+ imageUrl: import_zod8.z.string().min(1, "imageUrl is required").describe("Image URL or local file path readable by the OneBot side.")
1291
+ });
1292
+ async _call(input, _manager, runnable) {
1293
+ return sendSetQQAvatar({
1294
+ session: getSession(runnable),
1295
+ imageUrl: input.imageUrl,
1296
+ ctx,
1297
+ log
1298
+ });
1299
+ }
1300
+ }();
1301
+ }
1302
+
1120
1303
  // src/features/native-tools/register.ts
1121
1304
  var NATIVE_TOOL_DEFAULT_AVAILABILITY = {
1122
1305
  enabled: true,
@@ -1185,6 +1368,24 @@ function registerNativeTools(deps) {
1185
1368
  });
1186
1369
  log?.("info", `\u8BBE\u7F6E\u8D44\u6599\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
1187
1370
  }
1371
+ if (config.setQQAvatar.enabled) {
1372
+ const toolName = resolveToolName(
1373
+ config.setQQAvatar.toolName,
1374
+ "set_qq_avatar"
1375
+ );
1376
+ const description = resolveToolDescription(
1377
+ config.setQQAvatar.description,
1378
+ DEFAULT_SET_QQ_AVATAR_TOOL_DESCRIPTION
1379
+ );
1380
+ plugin.registerTool(toolName, {
1381
+ selector: () => true,
1382
+ authorization: (session) => session?.platform === "onebot",
1383
+ description,
1384
+ createTool: () => createSetQQAvatarTool({ ctx, toolName, description, log }),
1385
+ meta: createNativeToolMeta("onebot", ["profile"])
1386
+ });
1387
+ log?.("info", `QQ \u5934\u50CF\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
1388
+ }
1188
1389
  if (config.setGroupCard.enabled) {
1189
1390
  const toolName = resolveToolName(
1190
1391
  config.setGroupCard.toolName,
@@ -1221,6 +1422,29 @@ function registerNativeTools(deps) {
1221
1422
  });
1222
1423
  log?.("info", `\u7FA4\u6210\u5458\u7981\u8A00\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
1223
1424
  }
1425
+ if (config.setGroupSpecialTitle.enabled) {
1426
+ const toolName = resolveToolName(
1427
+ config.setGroupSpecialTitle.toolName,
1428
+ "set_group_special_title"
1429
+ );
1430
+ const description = resolveToolDescription(
1431
+ config.setGroupSpecialTitle.description,
1432
+ DEFAULT_SET_GROUP_SPECIAL_TITLE_TOOL_DESCRIPTION
1433
+ );
1434
+ plugin.registerTool(toolName, {
1435
+ selector: () => true,
1436
+ authorization: (session) => session?.platform === "onebot",
1437
+ description,
1438
+ createTool: () => createSetGroupSpecialTitleTool({
1439
+ toolName,
1440
+ description,
1441
+ log,
1442
+ protocol
1443
+ }),
1444
+ meta: createNativeToolMeta("onebot", ["group"])
1445
+ });
1446
+ log?.("info", `\u7FA4\u4E13\u5C5E\u5934\u8854\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
1447
+ }
1224
1448
  if (config.setMsgEmoji.enabled) {
1225
1449
  const toolName = resolveToolName(
1226
1450
  config.setMsgEmoji.toolName,
@@ -1478,7 +1702,7 @@ function registerCharacterReplyTools(deps) {
1478
1702
  if (typeof action.message_id !== "string") continue;
1479
1703
  await sendDeleteMessage({
1480
1704
  session,
1481
- messageId: action.message_id,
1705
+ message_id: action.message_id,
1482
1706
  log
1483
1707
  });
1484
1708
  }
@@ -1578,7 +1802,7 @@ function createXmlProcessor(deps) {
1578
1802
  if (messageIds.length > 0) handled = true;
1579
1803
  for (const messageId of messageIds) {
1580
1804
  try {
1581
- await runDelete({ session, messageId, log });
1805
+ await runDelete({ session, message_id: messageId, log });
1582
1806
  } catch (error) {
1583
1807
  log?.("warn", "XML \u89E6\u53D1\u64A4\u56DE\u5931\u8D25", error);
1584
1808
  }
@@ -2669,8 +2893,10 @@ function apply(ctx, config) {
2669
2893
  createRandomProvider,
2670
2894
  createSetGroupBanTool,
2671
2895
  createSetGroupCardTool,
2896
+ createSetGroupSpecialTitleTool,
2672
2897
  createSetMsgEmojiTool,
2673
2898
  createSetProfileTool,
2899
+ createSetQQAvatarTool,
2674
2900
  createUserInfoProvider,
2675
2901
  createXmlProcessor,
2676
2902
  ensureOneBotSession,
@@ -2689,5 +2915,7 @@ function apply(ctx, config) {
2689
2915
  sendMsgEmoji,
2690
2916
  sendPoke,
2691
2917
  sendSetGroupCard,
2692
- sendSetProfile
2918
+ sendSetGroupSpecialTitle,
2919
+ sendSetProfile,
2920
+ sendSetQQAvatar
2693
2921
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-chatluna-toolbox",
3
3
  "description": "为 ChatLuna 提供更多原生工具、XML 工具与变量,仅支持 onebot 平台。",
4
- "version": "0.0.13",
4
+ "version": "0.0.16",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "files": [
@@ -10,10 +10,10 @@
10
10
  "client"
11
11
  ],
12
12
  "license": "MIT",
13
- "homepage": "https://github.com/Sor85/koishi-plugins",
13
+ "homepage": "https://github.com/Sor85/AAAAACAT-chatluna-plugins",
14
14
  "repository": {
15
15
  "type": "git",
16
- "url": "https://github.com/Sor85/koishi-plugins.git"
16
+ "url": "https://github.com/Sor85/AAAAACAT-chatluna-plugins.git"
17
17
  },
18
18
  "keywords": [
19
19
  "chatbot",
@@ -54,7 +54,7 @@
54
54
  "scripts": {
55
55
  "build": "tsup && vite build",
56
56
  "watch": "tsup --watch",
57
- "typecheck": "NODE_OPTIONS=--max-old-space-size=8192 tsc --noEmit",
57
+ "typecheck": "NODE_OPTIONS=--max-old-space-size=8192 tsc -p tsconfig.test.json",
58
58
  "test": "vitest run"
59
59
  }
60
60
  }