koishi-plugin-chatluna-affinity 0.2.3-alpha.4 → 0.2.4

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.
@@ -6,4 +6,4 @@ import type { RoleMapping } from '../types';
6
6
  export declare const ROLE_MAPPING: RoleMapping;
7
7
  export declare const CLOUD_TYPES: Record<string, string>;
8
8
  export declare const DEFAULT_MEMBER_INFO_ITEMS: readonly ["nickname", "userId", "role", "level", "title"];
9
- export declare const ALL_MEMBER_INFO_ITEMS: readonly ["nickname", "userId", "role", "level", "title", "gender", "age", "area", "joinTime", "lastSentTime"];
9
+ export declare const ALL_MEMBER_INFO_ITEMS: readonly ["nickname", "userId", "role", "level", "title", "gender", "age", "area", "joinTime", "lastSentTime", "chatCount"];
@@ -11,6 +11,7 @@ interface RenderFieldOptions {
11
11
  fallbackNames?: string[];
12
12
  logUnknown?: boolean;
13
13
  log?: LogFn;
14
+ chatCount?: number;
14
15
  }
15
16
  export declare function renderInfoField(fieldName: MemberInfoField, member: MemberInfo | null | undefined, session: Session | null | undefined, options: RenderFieldOptions): string | null;
16
17
  export declare function renderMemberInfo(session: Session | null | undefined, member: MemberInfo | null | undefined, userId: string, configItems: string[] | undefined, options?: RenderMemberInfoOptions): string;
package/lib/index.d.ts CHANGED
@@ -14,4 +14,4 @@ export * from './renders';
14
14
  export * from './commands';
15
15
  export * from './integrations';
16
16
  export { ConfigSchema, AffinitySchema, BlacklistSchema, RelationshipSchema, ScheduleSchema, OtherVariablesSchema, NativeToolsSchema, XmlToolsSchema, OtherCommandsSchema, OtherSettingsSchema } from './schema';
17
- export declare const usage = "\n## \u66F4\u65B0\u65E5\u5FD7\n\n0.2.3-alpha.4\n- \u4FEE\u590D\u65E5\u7A0B\u751F\u6210\u63D0\u793A\u8BCD\u4EBA\u8BBE\u6CE8\u5165\u53D8\u91CF {persona} \u5931\u6548\u7684\u95EE\u9898\uFF0C\u65B0\u589E\u6A21\u578B\u9009\u62E9\u4E0E\u4EBA\u8BBE\u6CE8\u5165\u9009\u9879\n- \u5929\u6C14\u670D\u52A1\u5207\u6362\u4E3A open-meteo\uFF0C\u4E0D\u518D\u9700\u8981\u63D0\u4F9B token\n\n0.2.3-alpha.3\n- \u4FEE\u590D\u65E0\u6CD5\u9009\u62E9\u65E5\u7A0B\u6A21\u578B\u7684\u95EE\u9898\n\n0.2.3-alpha.2\n- \u4FEE\u590D\u597D\u611F\u5EA6\u66F4\u65B0\u65F6\u672A\u66F4\u65B0 chatCount \u7684\u95EE\u9898\n";
17
+ export declare const usage = "\n## \u66F4\u65B0\u65E5\u5FD7\n\n0.2.4\n- userInfo \u53D8\u91CF\u65B0\u589E chatCount \u5B57\u6BB5\uFF0C\u53EF\u5C55\u793A\u804A\u5929\u6B21\u6570\n- \u4FEE\u590D\u72B6\u6001\u6539\u53D8\u540E XML \u5DE5\u5177\u62E6\u622A\u5931\u6548\u7684\u95EE\u9898\n\n0.2.3\n- OneBot \u534F\u8BAE\u65B0\u589E NapCat/LLBot \u72EC\u7ACB\u9009\u9879\uFF0C\u6309\u914D\u7F6E\u9009\u62E9\u534F\u8BAE\n\n0.2.3-alpha.4\n- \u4FEE\u590D\u65E5\u7A0B\u751F\u6210\u63D0\u793A\u8BCD\u4EBA\u8BBE\u6CE8\u5165\u53D8\u91CF {persona} \u5931\u6548\u7684\u95EE\u9898\uFF0C\u65B0\u589E\u6A21\u578B\u9009\u62E9\u4E0E\u4EBA\u8BBE\u6CE8\u5165\u9009\u9879\n- \u5929\u6C14\u670D\u52A1\u5207\u6362\u4E3A open-meteo\uFF0C\u4E0D\u518D\u9700\u8981\u63D0\u4F9B token\n";
package/lib/index.js CHANGED
@@ -359,7 +359,8 @@ var ALL_MEMBER_INFO_ITEMS = [
359
359
  "age",
360
360
  "area",
361
361
  "joinTime",
362
- "lastSentTime"
362
+ "lastSentTime",
363
+ "chatCount"
363
364
  ];
364
365
 
365
366
  // src/schema/affinity.ts
@@ -427,12 +428,12 @@ var AffinitySchema = import_koishi.Schema.object({
427
428
  characterPromptTemplate: import_koishi.Schema.string().role("textarea").default(
428
429
  `## \u52A8\u4F5C\u6307\u4EE4
429
430
  \u4F60\u53EF\u4EE5\u6839\u636E\u9700\u8981\u521B\u5EFA\u4E00\u4E2A\u72EC\u7ACB\u7684 \`<actions>\` \u5143\u7D20\u3002\u5B83\u7528\u4E8E\u6267\u884C\u975E\u8BED\u8A00\u7684\u7CFB\u7EDF\u6307\u4EE4\u3002\u5982\u679C\u4E0D\u9700\u8981\u6267\u884C\u4EFB\u4F55\u52A8\u4F5C\uFF0C\u8BF7\u7701\u7565\u6B64\u5143\u7D20\u3002
430
- 1. **\u6233\u4E00\u6233**: \`<poke id="user_id" />\`
431
+ 1. **\u6233\u4E00\u6233**: \`<poke id="user_id"/>\`
431
432
  - **\u9002\u7528\u573A\u666F**:
432
433
  - \u5F53\u4F60\u60F3\u5F15\u8D77\u67D0\u4EBA\u7684\u6CE8\u610F\u65F6\u3002
433
434
  - \u5F53\u5BF9\u65B9\u8BF4\u4E86\u8BA9\u4F60\u611F\u5230\u65E0\u8BED\u3001\u65E0\u89C6\u4F60\u3001\u6216\u8005\u4F60\u60F3\u901A\u8FC7\u80A2\u4F53\u4E92\u52A8\u8C03\u4F83\u5BF9\u65B9\u65F6\u3002
434
435
  - \u4F5C\u4E3A\u4E00\u79CD\u4FCF\u76AE\u7684\u6253\u62DB\u547C\u65B9\u5F0F\u3002
435
- 2. **\u8868\u60C5\u56DE\u5E94**: \`<emoji message_id="message_id" emoji_id="emoji_id" />\`
436
+ 2. **\u8868\u60C5\u56DE\u5E94**: \`<emoji message_id="message_id" emoji_id="emoji_id"/>\`
436
437
  - \u7528\u4E8E\u5BF9\u4E0A\u4E0B\u6587\u4E2D\u7684\u7279\u5B9A\u6D88\u606F\u8FDB\u884C\u8868\u60C5\u56DE\u5E94\u3002
437
438
  - **emoji_id \u5BF9\u5E94\u8868**:
438
439
  - 424: \u8D5E\u540C (\u7EA2\u8272\u6309\u94AE)
@@ -440,7 +441,7 @@ var AffinitySchema = import_koishi.Schema.object({
440
441
  - 265: \u9006\u5929 (\u5730\u94C1\u8001\u4EBA\u624B\u673A)
441
442
  - 76: \u70B9\u8D5E
442
443
  - 66: \u7231\u5FC3
443
- 3. **\u64A4\u56DE\u6D88\u606F**: \`<delete message_id="message_id" />\`
444
+ 3. **\u64A4\u56DE\u6D88\u606F**: \`<delete message_id="message_id"/>\`
444
445
  - \u7528\u4E8E\u64A4\u56DE\u6307\u5B9A\u6D88\u606F\u3002
445
446
  4. **\u597D\u611F\u5EA6\u66F4\u65B0**: \`<affinity delta="5" action="increase" id="user_id"/>\`
446
447
  - delta: \u597D\u611F\u5EA6\u53D8\u5316\u91CF\uFF08\u6B63\u6574\u6570\uFF09
@@ -450,9 +451,9 @@ var AffinitySchema = import_koishi.Schema.object({
450
451
  **\u683C\u5F0F\u793A\u4F8B**:
451
452
  \`\`\`xml
452
453
  <actions>
453
- <poke id="129345425" />
454
- <emoji message_id="346234" emoji_id="66" />
455
- <delete message_id="435663" />
454
+ <poke id="1223415"/>
455
+ <emoji message_id="346234" emoji_id="66"/>
456
+ <delete message_id="435663"/>
456
457
  <affinity delta="5" action="increase" id="1345425"/>
457
458
  </actions>
458
459
  \`\`\``
@@ -539,7 +540,7 @@ var import_koishi4 = require("koishi");
539
540
  var ScheduleSchema = import_koishi4.Schema.object({
540
541
  schedule: import_koishi4.Schema.object({
541
542
  enabled: import_koishi4.Schema.boolean().default(true).description("\u662F\u5426\u542F\u7528\u65E5\u7A0B\u529F\u80FD"),
542
- model: import_koishi4.Schema.dynamic("model").default("").description("\u65E5\u7A0B\u751F\u6210\u4F7F\u7528\u7684\u6A21\u578B\uFF0C\u7559\u7A7A\u5219\u4F7F\u7528 ChatLuna \u9ED8\u8BA4\u6A21\u578B"),
543
+ model: import_koishi4.Schema.dynamic("model").default("").description("\u65E5\u7A0B\u751F\u6210\u4F7F\u7528\u7684\u6A21\u578B"),
543
544
  personaSource: import_koishi4.Schema.union([
544
545
  import_koishi4.Schema.const("none").description("\u4E0D\u6CE8\u5165\u4EBA\u8BBE"),
545
546
  import_koishi4.Schema.const("chatluna").description("\u4F7F\u7528 ChatLuna \u4E3B\u63D2\u4EF6\u4EBA\u8BBE"),
@@ -604,7 +605,7 @@ var OtherVariablesSchema = import_koishi6.Schema.object({
604
605
  items: import_koishi6.Schema.array(
605
606
  import_koishi6.Schema.union([
606
607
  import_koishi6.Schema.const("userId").description("\u7528\u6237 ID"),
607
- import_koishi6.Schema.const("nickname").description("\u663E\u793A\u540D\u79F0"),
608
+ import_koishi6.Schema.const("nickname").description("\u7FA4\u6635\u79F0"),
608
609
  import_koishi6.Schema.const("role").description("\u7FA4\u5185\u8EAB\u4EFD"),
609
610
  import_koishi6.Schema.const("level").description("\u7FA4\u7B49\u7EA7"),
610
611
  import_koishi6.Schema.const("title").description("\u7FA4\u5934\u8854"),
@@ -612,7 +613,8 @@ var OtherVariablesSchema = import_koishi6.Schema.object({
612
613
  import_koishi6.Schema.const("age").description("\u5E74\u9F84"),
613
614
  import_koishi6.Schema.const("area").description("\u5730\u533A"),
614
615
  import_koishi6.Schema.const("joinTime").description("\u5165\u7FA4\u65F6\u95F4"),
615
- import_koishi6.Schema.const("lastSentTime").description("\u6700\u540E\u53D1\u8A00\u65F6\u95F4")
616
+ import_koishi6.Schema.const("lastSentTime").description("\u6700\u540E\u53D1\u8A00\u65F6\u95F4"),
617
+ import_koishi6.Schema.const("chatCount").description("\u804A\u5929\u6B21\u6570")
616
618
  ])
617
619
  ).role("checkbox").default([...DEFAULT_MEMBER_INFO_ITEMS]).description("\u663E\u793A\u7684\u8BE6\u7EC6\u4FE1\u606F\u9879")
618
620
  }).description("\u7528\u6237\u4FE1\u606F\u53D8\u91CF").collapse(),
@@ -621,7 +623,7 @@ var OtherVariablesSchema = import_koishi6.Schema.object({
621
623
  items: import_koishi6.Schema.array(
622
624
  import_koishi6.Schema.union([
623
625
  import_koishi6.Schema.const("userId").description("\u673A\u5668\u4EBA ID"),
624
- import_koishi6.Schema.const("nickname").description("\u663E\u793A\u540D\u79F0"),
626
+ import_koishi6.Schema.const("nickname").description("\u7FA4\u6635\u79F0"),
625
627
  import_koishi6.Schema.const("role").description("\u7FA4\u5185\u8EAB\u4EFD"),
626
628
  import_koishi6.Schema.const("level").description("\u7FA4\u7B49\u7EA7"),
627
629
  import_koishi6.Schema.const("title").description("\u7FA4\u5934\u8854"),
@@ -659,6 +661,8 @@ var OtherVariablesSchema = import_koishi6.Schema.object({
659
661
  // src/schema/tools.ts
660
662
  var import_koishi7 = require("koishi");
661
663
  var NativeToolsSchema = import_koishi7.Schema.object({
664
+ enableNapCatProtocol: import_koishi7.Schema.boolean().default(true).description("\u542F\u7528 NapCat OneBot \u534F\u8BAE\uFF08\u4E0E LLBot \u4E8C\u9009\u4E00\uFF09"),
665
+ enableLlbotProtocol: import_koishi7.Schema.boolean().default(false).description("\u542F\u7528 LLBot OneBot \u534F\u8BAE\uFF08\u4E0E NapCat \u4E8C\u9009\u4E00\uFF09"),
662
666
  enablePokeTool: import_koishi7.Schema.boolean().default(false).description("\u6CE8\u518C ChatLuna \u5DE5\u5177\uFF1A\u6233\u4E00\u6233"),
663
667
  pokeToolName: import_koishi7.Schema.string().default("poke_user").description("ChatLuna \u5DE5\u5177\u540D\u79F0\uFF1A\u6233\u4E00\u6233"),
664
668
  enableSetSelfProfileTool: import_koishi7.Schema.boolean().default(false).description("\u6CE8\u518C ChatLuna \u5DE5\u5177\uFF1A\u4FEE\u6539\u81EA\u8EAB\u8D26\u6237\u4FE1\u606F"),
@@ -3937,6 +3941,12 @@ function renderInfoField(fieldName, member, session, options) {
3937
3941
  const formatted = formatDateTime(ts);
3938
3942
  return formatted ? `\u6D3B\u8DC3:${formatted}` : null;
3939
3943
  }
3944
+ case "chatCount": {
3945
+ const rawCount = options.chatCount;
3946
+ const numeric = Number(rawCount);
3947
+ if (!Number.isFinite(numeric)) return null;
3948
+ return `\u804A\u5929\u6B21\u6570:${Math.max(0, Math.round(numeric))}`;
3949
+ }
3940
3950
  default:
3941
3951
  return null;
3942
3952
  }
@@ -3974,7 +3984,8 @@ function renderMemberInfo(session, member, userId, configItems, options = {}) {
3974
3984
  userId,
3975
3985
  fallbackNames,
3976
3986
  logUnknown,
3977
- log
3987
+ log,
3988
+ chatCount: options.chatCount
3978
3989
  });
3979
3990
  if (rendered) parts.push(rendered);
3980
3991
  }
@@ -6762,7 +6773,7 @@ function createContextAffinityProvider(deps) {
6762
6773
 
6763
6774
  // src/integrations/chatluna/variables/user-info.ts
6764
6775
  function createUserInfoProvider(deps) {
6765
- const { config, log, fetchMember: fetchMember2 } = deps;
6776
+ const { config, log, fetchMember: fetchMember2, store } = deps;
6766
6777
  const defaultItems = DEFAULT_MEMBER_INFO_ITEMS;
6767
6778
  return async (_args, _variables, configurable) => {
6768
6779
  const session = configurable?.session;
@@ -6771,11 +6782,27 @@ function createUserInfoProvider(deps) {
6771
6782
  variableName: "userInfo",
6772
6783
  items: defaultItems
6773
6784
  };
6785
+ const items = Array.isArray(userInfoConfig.items) && userInfoConfig.items.length ? userInfoConfig.items : [...defaultItems];
6786
+ const includeChatCount = items.some((item) => String(item || "").trim() === "chatCount");
6787
+ let chatCount;
6788
+ if (includeChatCount && session.selfId) {
6789
+ try {
6790
+ const record = await store.load(session.selfId, session.userId);
6791
+ if (record?.chatCount !== null && record?.chatCount !== void 0) {
6792
+ chatCount = Number(record.chatCount);
6793
+ }
6794
+ } catch (error) {
6795
+ if (config.debugLogging) {
6796
+ log?.("warn", "\u83B7\u53D6\u804A\u5929\u8BA1\u6570\u5931\u8D25", error);
6797
+ }
6798
+ }
6799
+ }
6774
6800
  try {
6775
- return await resolveUserInfo(session, userInfoConfig.items || [...defaultItems], fetchMember2, {
6801
+ return await resolveUserInfo(session, items, fetchMember2, {
6776
6802
  defaultItems: [...defaultItems],
6777
6803
  logUnknown: config.debugLogging,
6778
- log
6804
+ log,
6805
+ chatCount
6779
6806
  });
6780
6807
  } catch {
6781
6808
  return `${session.username || session.userId || "\u672A\u77E5\u7528\u6237"}`;
@@ -7491,13 +7518,22 @@ async function callOneBotAPI(internal, action, params, fallbacks = []) {
7491
7518
  // src/integrations/onebot/tools/poke.ts
7492
7519
  async function sendPoke(params) {
7493
7520
  try {
7494
- const { session, userId, groupId, log } = params;
7521
+ const { session, userId, groupId, log, protocol } = params;
7495
7522
  const { error, internal, session: validatedSession } = ensureOneBotSession(session);
7496
7523
  if (error) return error;
7497
7524
  const resolvedGroupId = groupId?.trim() || validatedSession?.guildId || validatedSession?.channelId || validatedSession?.roomId;
7498
7525
  const payload = { user_id: userId };
7499
7526
  if (resolvedGroupId) payload.group_id = resolvedGroupId;
7500
- if (typeof internal._request === "function") {
7527
+ if (protocol === "llbot") {
7528
+ const action = payload.group_id ? "group_poke" : "friend_poke";
7529
+ if (typeof internal._request === "function") {
7530
+ await internal._request(action, payload);
7531
+ } else if (typeof internal[action] === "function") {
7532
+ await internal[action](payload);
7533
+ } else {
7534
+ throw new Error(`\u5F53\u524D\u9002\u914D\u5668\u672A\u5B9E\u73B0 ${action} API\u3002`);
7535
+ }
7536
+ } else if (typeof internal._request === "function") {
7501
7537
  await internal._request("send_poke", payload);
7502
7538
  } else if (typeof internal.sendPoke === "function") {
7503
7539
  await internal.sendPoke(
@@ -7519,7 +7555,7 @@ async function sendPoke(params) {
7519
7555
  }
7520
7556
  }
7521
7557
  function createPokeTool(deps) {
7522
- const { toolName, log } = deps;
7558
+ const { toolName, log, protocol } = deps;
7523
7559
  return new class extends import_tools8.StructuredTool {
7524
7560
  name = toolName || "poke_user";
7525
7561
  description = "Poke (nudge) a specified user in a group or private conversation.";
@@ -7531,7 +7567,7 @@ function createPokeTool(deps) {
7531
7567
  });
7532
7568
  async _call(input, _manager, runnable) {
7533
7569
  const session = getSession(runnable);
7534
- return sendPoke({ session, userId: input.userId, groupId: input.groupId, log });
7570
+ return sendPoke({ session, userId: input.userId, groupId: input.groupId, log, protocol });
7535
7571
  }
7536
7572
  }();
7537
7573
  }
@@ -7541,7 +7577,7 @@ var import_zod8 = require("zod");
7541
7577
  var import_tools9 = require("@langchain/core/tools");
7542
7578
  var genders = { unknown: "0", male: "1", female: "2" };
7543
7579
  function createSetProfileTool(deps) {
7544
- const { toolName, log } = deps;
7580
+ const { toolName, log, protocol } = deps;
7545
7581
  return new class extends import_tools9.StructuredTool {
7546
7582
  name = toolName || "set_self_profile";
7547
7583
  description = "Update the bot's own QQ profile (nickname, signature, gender).";
@@ -7557,7 +7593,7 @@ function createSetProfileTool(deps) {
7557
7593
  if (error) return error;
7558
7594
  const payload = { nickname: input.nickname };
7559
7595
  if (input.signature) payload.personal_note = input.signature;
7560
- if (input.gender) payload.sex = genders[input.gender];
7596
+ if (input.gender && protocol !== "llbot") payload.sex = genders[input.gender];
7561
7597
  await callOneBotAPI(internal, "set_qq_profile", payload, ["setQQProfile"]);
7562
7598
  const message = "\u673A\u5668\u4EBA\u8D44\u6599\u5DF2\u66F4\u65B0\u3002";
7563
7599
  log?.("info", message);
@@ -7617,9 +7653,12 @@ var import_zod10 = require("zod");
7617
7653
  var import_tools11 = require("@langchain/core/tools");
7618
7654
  async function sendMsgEmoji(params) {
7619
7655
  try {
7620
- const { session, messageId, emojiId, log } = params;
7656
+ const { session, messageId, emojiId, log, protocol } = params;
7621
7657
  if (!session) return "No session context available.";
7622
7658
  if (session.platform !== "onebot") return "This tool only supports OneBot platform.";
7659
+ if (protocol === "llbot" && !session.guildId && !session.channelId) {
7660
+ return "\u5F53\u524D\u4F1A\u8BDD\u4E0D\u662F\u7FA4\u804A\uFF0CLLBot \u4E0D\u652F\u6301\u79C1\u804A\u8868\u60C5\u56DE\u5E94\u3002";
7661
+ }
7623
7662
  const messageIdRaw = messageId.trim();
7624
7663
  const emojiIdRaw = emojiId.trim();
7625
7664
  if (!messageIdRaw) return "message_id is required.";
@@ -7642,7 +7681,7 @@ async function sendMsgEmoji(params) {
7642
7681
  }
7643
7682
  }
7644
7683
  function createSetMsgEmojiTool(deps) {
7645
- const { toolName, log } = deps;
7684
+ const { toolName, log, protocol } = deps;
7646
7685
  return new class extends import_tools11.StructuredTool {
7647
7686
  name = toolName || "set_msg_emoji";
7648
7687
  description = "React to a message with an emoji by messageId. Required: message_id and emoji_id (emoji ID).";
@@ -7652,7 +7691,7 @@ function createSetMsgEmojiTool(deps) {
7652
7691
  });
7653
7692
  async _call(input, _manager, runnable) {
7654
7693
  const session = getSession(runnable);
7655
- return sendMsgEmoji({ session, messageId: input.messageId, emojiId: input.emojiId, log });
7694
+ return sendMsgEmoji({ session, messageId: input.messageId, emojiId: input.emojiId, log, protocol });
7656
7695
  }
7657
7696
  }();
7658
7697
  }
@@ -7661,7 +7700,7 @@ function createSetMsgEmojiTool(deps) {
7661
7700
  var import_zod11 = require("zod");
7662
7701
  var import_tools12 = require("@langchain/core/tools");
7663
7702
  function createFakeMessageTool(deps) {
7664
- const { toolName, log } = deps;
7703
+ const { toolName, log, protocol } = deps;
7665
7704
  return new class extends import_tools12.StructuredTool {
7666
7705
  name = toolName || "send_fake_msg";
7667
7706
  description = "Forge messages for one or more users and send as a merged forward. Accepts messages array or senderId + texts. Requires OneBot and send_forward_msg support.";
@@ -7704,6 +7743,18 @@ function createFakeMessageTool(deps) {
7704
7743
  if (!targetGroupId) {
7705
7744
  return "Missing targetGroupId. Provide targetGroupId or run inside a group session.";
7706
7745
  }
7746
+ const buildForwardContent = (content) => [{
7747
+ type: "text",
7748
+ data: { text: content }
7749
+ }];
7750
+ const buildLegacyNodes = (targets) => targets.map((node) => ({
7751
+ type: "node",
7752
+ data: {
7753
+ name: node.data.name,
7754
+ uin: node.data.uin,
7755
+ content: node.data.content.map((segment) => segment.data.text || "").filter(Boolean).join("")
7756
+ }
7757
+ }));
7707
7758
  const nodes = (() => {
7708
7759
  const buildNodesFromMessages = (messages) => {
7709
7760
  return messages.map((item) => {
@@ -7718,7 +7769,7 @@ function createFakeMessageTool(deps) {
7718
7769
  data: {
7719
7770
  name: displayName2 || uin,
7720
7771
  uin,
7721
- content: text
7772
+ content: buildForwardContent(text)
7722
7773
  }
7723
7774
  };
7724
7775
  }).filter((v) => Boolean(v));
@@ -7750,7 +7801,7 @@ function createFakeMessageTool(deps) {
7750
7801
  data: {
7751
7802
  name: displayName,
7752
7803
  uin: senderId,
7753
- content
7804
+ content: buildForwardContent(content)
7754
7805
  }
7755
7806
  }));
7756
7807
  })();
@@ -7770,12 +7821,22 @@ function createFakeMessageTool(deps) {
7770
7821
  );
7771
7822
  const { error, internal } = ensureOneBotSession(session);
7772
7823
  if (error) return error;
7773
- await callOneBotAPI(
7774
- internal,
7775
- "send_forward_msg",
7776
- { group_id: targetGroupId, messages: nodes },
7777
- ["sendForwardMsg"]
7778
- );
7824
+ if (protocol === "llbot") {
7825
+ await callOneBotAPI(
7826
+ internal,
7827
+ "send_group_forward_msg",
7828
+ { group_id: targetGroupId, messages: nodes },
7829
+ ["sendGroupForwardMsg"]
7830
+ );
7831
+ } else {
7832
+ const legacyNodes = buildLegacyNodes(nodes);
7833
+ await callOneBotAPI(
7834
+ internal,
7835
+ "send_forward_msg",
7836
+ { group_id: targetGroupId, messages: legacyNodes },
7837
+ ["sendForwardMsg"]
7838
+ );
7839
+ }
7779
7840
  const senderSet = Array.from(new Set(nodes.map((n) => n.data.uin || n.data.name).filter(Boolean)));
7780
7841
  const senderLabel = senderSet.length ? senderSet.join(",") : "unknown";
7781
7842
  const success = `Forged ${nodes.length} messages from ${senderLabel} and forwarded to group ${targetGroupId}.`;
@@ -7793,7 +7854,7 @@ function createFakeMessageTool(deps) {
7793
7854
  var import_zod12 = require("zod");
7794
7855
  var import_tools13 = require("@langchain/core/tools");
7795
7856
  function createForwardMessageTool(deps) {
7796
- const { toolName, messageStore, log } = deps;
7857
+ const { toolName, messageStore, log, protocol } = deps;
7797
7858
  return new class extends import_tools13.StructuredTool {
7798
7859
  name = toolName || "send_forward_msg";
7799
7860
  description = "Forward messages as a merged forward to a group. messageIds is required to specify messages to forward. Requires message_id exposure via chatluna-character enableMessageId.";
@@ -7811,11 +7872,11 @@ function createForwardMessageTool(deps) {
7811
7872
  return "Missing targetGroupId. Provide targetGroupId or run inside a group session.";
7812
7873
  }
7813
7874
  const explicitIds = Array.isArray(input.messageIds) && input.messageIds.length ? input.messageIds.map((id) => id.trim()).filter(Boolean) : [];
7814
- let nodes;
7875
+ let legacyNodes;
7815
7876
  if (explicitIds.length > 0) {
7816
7877
  const found = messageStore.findByIds(session, explicitIds);
7817
7878
  const map = new Map(found.map((msg) => [msg.messageId, msg]));
7818
- nodes = explicitIds.map((id) => {
7879
+ legacyNodes = explicitIds.map((id) => {
7819
7880
  const hit = map.get(id);
7820
7881
  if (!hit) return null;
7821
7882
  return {
@@ -7823,11 +7884,11 @@ function createForwardMessageTool(deps) {
7823
7884
  data: {
7824
7885
  name: hit.username || hit.userId || "\u672A\u77E5\u7528\u6237",
7825
7886
  uin: hit.userId || session.userId || "",
7826
- content: hit.content
7887
+ content: String(hit.content || "")
7827
7888
  }
7828
7889
  };
7829
7890
  }).filter((item) => item !== null);
7830
- if (!nodes.length) {
7891
+ if (!legacyNodes.length) {
7831
7892
  return "No messages found for provided messageIds.";
7832
7893
  }
7833
7894
  } else {
@@ -7835,13 +7896,30 @@ function createForwardMessageTool(deps) {
7835
7896
  }
7836
7897
  const { error, internal } = ensureOneBotSession(session);
7837
7898
  if (error) return error;
7838
- await callOneBotAPI(
7839
- internal,
7840
- "send_forward_msg",
7841
- { group_id: targetGroupId, messages: nodes },
7842
- ["sendForwardMsg"]
7843
- );
7844
- const success = `Forwarded ${nodes.length} messages to group ${targetGroupId}.`;
7899
+ if (protocol === "llbot") {
7900
+ const llbotNodes = legacyNodes.map((node) => ({
7901
+ type: "node",
7902
+ data: {
7903
+ name: node.data.name,
7904
+ uin: node.data.uin,
7905
+ content: [{ type: "text", data: { text: node.data.content } }]
7906
+ }
7907
+ }));
7908
+ await callOneBotAPI(
7909
+ internal,
7910
+ "send_group_forward_msg",
7911
+ { group_id: targetGroupId, messages: llbotNodes },
7912
+ ["sendGroupForwardMsg"]
7913
+ );
7914
+ } else {
7915
+ await callOneBotAPI(
7916
+ internal,
7917
+ "send_forward_msg",
7918
+ { group_id: targetGroupId, messages: legacyNodes },
7919
+ ["sendForwardMsg"]
7920
+ );
7921
+ }
7922
+ const success = `Forwarded ${legacyNodes.length} messages to group ${targetGroupId}.`;
7845
7923
  log?.("info", success);
7846
7924
  return success;
7847
7925
  } catch (error) {
@@ -8643,6 +8721,17 @@ function apply(ctx, config) {
8643
8721
  });
8644
8722
  });
8645
8723
  const log = createLogger2(ctx, config);
8724
+ const resolveOneBotProtocol = () => {
8725
+ if (config.enableNapCatProtocol && config.enableLlbotProtocol) {
8726
+ log("warn", "NapCat \u4E0E LLBot \u534F\u8BAE\u540C\u65F6\u542F\u7528\uFF0C\u5C06\u4F18\u5148\u4F7F\u7528 LLBot\u3002");
8727
+ return "llbot";
8728
+ }
8729
+ if (config.enableLlbotProtocol) return "llbot";
8730
+ if (config.enableNapCatProtocol) return "napcat";
8731
+ log("warn", "\u672A\u542F\u7528 OneBot \u534F\u8BAE\u9009\u9879\uFF0C\u9ED8\u8BA4\u4F7F\u7528 NapCat\u3002");
8732
+ return "napcat";
8733
+ };
8734
+ const onebotProtocol = resolveOneBotProtocol();
8646
8735
  log("warn", "\u26A0\uFE0F \u5347\u7EA7\u63D0\u793A\uFF1A0.2.1-alpha.10 \u7248\u672C\u540E\u6570\u636E\u5E93\u7ED3\u6784\u5DF2\u91CD\u6784\uFF0C\u82E5\u51FA\u73B0\u6570\u636E\u5E93\u76F8\u5173\u9519\u8BEF\uFF0C\u8BF7\u6267\u884C affinity.clearall \u547D\u4EE4\u6E05\u9664\u6570\u636E\u540E\u91CD\u8BD5\u3002\u597D\u611F\u5EA6\u5206\u6790\u63D0\u793A\u8BCD\u4E0E\u65E5\u7A0B\u751F\u6210\u63D0\u793A\u8BCD\u5DF2\u66F4\u65B0\uFF0C\u82E5\u60A8\u81EA\u5B9A\u4E49\u8FC7\u63D0\u793A\u8BCD\uFF0C\u8BF7\u5C06\u5176\u6062\u590D\u9ED8\u8BA4\u4EE5\u5E94\u7528\u6700\u65B0\u7248\u672C\u3002");
8647
8736
  const cache = createAffinityCache();
8648
8737
  const store = createAffinityStore({ ctx, config, log });
@@ -8746,28 +8835,95 @@ function apply(ctx, config) {
8746
8835
  log
8747
8836
  });
8748
8837
  ctx.middleware(blacklistGuard.middleware, true);
8838
+ const affinityInitCache = /* @__PURE__ */ new Set();
8839
+ const makeAffinityInitKey = (session) => `${session.platform || "unknown"}:${session.selfId || "self"}:${session.userId || "unknown"}`;
8840
+ ctx.middleware(async (session, next) => {
8841
+ if (config.affinityEnabled) {
8842
+ const platform = session?.platform;
8843
+ const userId = session?.userId;
8844
+ const selfId = session?.selfId;
8845
+ if (platform && userId && selfId && userId !== selfId) {
8846
+ const key = makeAffinityInitKey(session);
8847
+ if (!affinityInitCache.has(key)) {
8848
+ affinityInitCache.add(key);
8849
+ try {
8850
+ const state = await store.ensureForUser(
8851
+ session,
8852
+ userId,
8853
+ (value, low, high) => Math.min(Math.max(value, low), high)
8854
+ );
8855
+ if (state.isNew && config.debugLogging) {
8856
+ log("debug", "\u5DF2\u521D\u59CB\u5316\u597D\u611F\u5EA6\u8BB0\u5F55", { platform, selfId, userId });
8857
+ }
8858
+ } catch (error) {
8859
+ affinityInitCache.delete(key);
8860
+ log("warn", "\u521D\u59CB\u5316\u597D\u611F\u5EA6\u5931\u8D25", error);
8861
+ }
8862
+ }
8863
+ }
8864
+ }
8865
+ return next();
8866
+ });
8749
8867
  let rawModelResponseGuildId = null;
8750
8868
  const rawModelResponseSessionMap = /* @__PURE__ */ new Map();
8751
8869
  let lastCharacterSession = null;
8752
- let rawInterceptorRetryHandle = null;
8870
+ let rawInterceptorMonitorHandle = null;
8871
+ let rawInterceptorFastRetryHandle = null;
8872
+ let rawInterceptorReady = false;
8873
+ let rawInterceptorService = null;
8874
+ let rawInterceptorLogger = null;
8875
+ let rawInterceptorOriginalDebug = null;
8876
+ let rawCollectorBound = false;
8877
+ let rawInterceptorDisposeBound = false;
8878
+ const RAW_INTERCEPTOR_TAG = "__chatlunaAffinityRawInterceptor";
8879
+ const RAW_INTERCEPTOR_MONITOR_INTERVAL = 5 * 1e3;
8880
+ const RAW_INTERCEPTOR_FAST_INTERVAL = 3 * 1e3;
8881
+ const restoreRawModelInterceptor = () => {
8882
+ if (rawInterceptorLogger && rawInterceptorOriginalDebug) {
8883
+ rawInterceptorLogger.debug = rawInterceptorOriginalDebug;
8884
+ }
8885
+ rawInterceptorLogger = null;
8886
+ rawInterceptorOriginalDebug = null;
8887
+ };
8888
+ const isRawInterceptorActive = () => {
8889
+ const characterService = ctx.chatluna_character;
8890
+ const debugFn = characterService?.logger?.debug;
8891
+ return Boolean(debugFn?.[RAW_INTERCEPTOR_TAG]);
8892
+ };
8753
8893
  const initRawModelInterceptor = () => {
8754
8894
  const characterService = ctx.chatluna_character;
8755
8895
  if (!characterService) return false;
8756
- characterService.collect?.(async (session) => {
8757
- const guildId = session?.guildId || session?.channelId || session?.userId || null;
8758
- rawModelResponseGuildId = guildId;
8759
- if (guildId) rawModelResponseSessionMap.set(guildId, session);
8760
- lastCharacterSession = session;
8761
- });
8896
+ if (rawInterceptorService !== characterService) {
8897
+ rawInterceptorService = characterService;
8898
+ rawCollectorBound = false;
8899
+ }
8900
+ if (!rawCollectorBound && typeof characterService.collect === "function") {
8901
+ characterService.collect?.(async (session) => {
8902
+ const guildId = session?.guildId || session?.channelId || session?.userId || null;
8903
+ rawModelResponseGuildId = guildId;
8904
+ if (guildId) rawModelResponseSessionMap.set(guildId, session);
8905
+ lastCharacterSession = session;
8906
+ });
8907
+ rawCollectorBound = true;
8908
+ }
8762
8909
  const characterLogger = characterService.logger;
8763
8910
  if (!characterLogger || typeof characterLogger.debug !== "function") return false;
8764
- const originalDebug = characterLogger.debug.bind(characterLogger);
8765
- characterLogger.debug = (...args) => {
8766
- originalDebug(...args);
8767
- const message = args[0];
8768
- if (typeof message === "string" && message.startsWith("model response: ")) {
8911
+ const taggedDebug = characterLogger.debug;
8912
+ if (!taggedDebug[RAW_INTERCEPTOR_TAG]) {
8913
+ restoreRawModelInterceptor();
8914
+ const originalDebug = characterLogger.debug.bind(characterLogger);
8915
+ const wrappedDebug = (...args) => {
8916
+ originalDebug(...args);
8917
+ const message = args[0];
8918
+ if (typeof message !== "string" || !message.startsWith("model response: ")) return;
8769
8919
  const response = message.substring("model response: ".length);
8770
- if (!rawModelResponseGuildId || !response) return;
8920
+ if (!response) return;
8921
+ if (!rawModelResponseGuildId) {
8922
+ log("warn", "\u62E6\u622A\u5230\u539F\u59CB\u8F93\u51FA\u4F46\u7F3A\u5C11\u4F1A\u8BDD\u4E0A\u4E0B\u6587\uFF0CXML \u5DE5\u5177\u4E0D\u4F1A\u6267\u884C", {
8923
+ length: response.length
8924
+ });
8925
+ return;
8926
+ }
8771
8927
  if (config.debugLogging) {
8772
8928
  log("debug", "\u62E6\u622A\u5230\u539F\u59CB\u8F93\u51FA", {
8773
8929
  guildId: rawModelResponseGuildId,
@@ -8821,7 +8977,7 @@ function apply(ctx, config) {
8821
8977
  const session = rawModelResponseSessionMap.get(rawModelResponseGuildId) || null;
8822
8978
  if (session && targetIds.length) {
8823
8979
  for (const userId of targetIds) {
8824
- void sendPoke({ session, userId, log });
8980
+ void sendPoke({ session, userId, log, protocol: onebotProtocol });
8825
8981
  }
8826
8982
  } else if (targetIds.length) {
8827
8983
  log("warn", "\u68C0\u6D4B\u5230\u6233\u4E00\u6233\u6807\u8BB0\u4F46\u7F3A\u5C11\u4F1A\u8BDD\u4E0A\u4E0B\u6587", {
@@ -8843,7 +8999,13 @@ function apply(ctx, config) {
8843
8999
  const messageId = String(match[1] || "").trim();
8844
9000
  const emojiId = String(match[2] || "").trim();
8845
9001
  if (messageId && emojiId) {
8846
- void sendMsgEmoji({ session, messageId, emojiId, log });
9002
+ void sendMsgEmoji({
9003
+ session,
9004
+ messageId,
9005
+ emojiId,
9006
+ log,
9007
+ protocol: onebotProtocol
9008
+ });
8847
9009
  }
8848
9010
  }
8849
9011
  } else {
@@ -8875,35 +9037,75 @@ function apply(ctx, config) {
8875
9037
  }
8876
9038
  }
8877
9039
  }
8878
- }
8879
- };
8880
- ctx.on("dispose", () => {
8881
- characterLogger.debug = originalDebug;
8882
- });
9040
+ };
9041
+ wrappedDebug[RAW_INTERCEPTOR_TAG] = true;
9042
+ characterLogger.debug = wrappedDebug;
9043
+ rawInterceptorLogger = characterLogger;
9044
+ rawInterceptorOriginalDebug = originalDebug;
9045
+ }
9046
+ if (!rawInterceptorDisposeBound) {
9047
+ ctx.on("dispose", () => {
9048
+ restoreRawModelInterceptor();
9049
+ });
9050
+ rawInterceptorDisposeBound = true;
9051
+ }
8883
9052
  return true;
8884
9053
  };
8885
- const startRawInterceptorRetry = () => {
8886
- if (rawInterceptorRetryHandle) return;
8887
- rawInterceptorRetryHandle = ctx.setInterval(() => {
8888
- log("info", "\u539F\u59CB\u8F93\u51FA\u62E6\u622A\u91CD\u8BD5\u4E2D...");
8889
- if (initRawModelInterceptor()) {
8890
- log("info", "\u539F\u59CB\u8F93\u51FA\u62E6\u622A\u91CD\u8BD5\u6210\u529F");
8891
- if (rawInterceptorRetryHandle) {
8892
- rawInterceptorRetryHandle();
8893
- rawInterceptorRetryHandle = null;
8894
- }
9054
+ const stopRawInterceptorFastRetry = () => {
9055
+ if (!rawInterceptorFastRetryHandle) return;
9056
+ rawInterceptorFastRetryHandle();
9057
+ rawInterceptorFastRetryHandle = null;
9058
+ };
9059
+ const startRawInterceptorFastRetry = () => {
9060
+ if (rawInterceptorFastRetryHandle) return;
9061
+ rawInterceptorFastRetryHandle = ctx.setInterval(() => {
9062
+ if (isRawInterceptorActive()) {
9063
+ rawInterceptorReady = true;
9064
+ stopRawInterceptorFastRetry();
9065
+ return;
8895
9066
  }
8896
- }, 10 * 60 * 1e3);
9067
+ const ready = initRawModelInterceptor();
9068
+ if (ready && !rawInterceptorReady) {
9069
+ log("info", "\u539F\u59CB\u8F93\u51FA\u62E6\u622A\u5DF2\u6062\u590D");
9070
+ }
9071
+ rawInterceptorReady = ready;
9072
+ if (ready) stopRawInterceptorFastRetry();
9073
+ }, RAW_INTERCEPTOR_FAST_INTERVAL);
9074
+ };
9075
+ const ensureRawInterceptorActive = () => {
9076
+ if (isRawInterceptorActive()) {
9077
+ rawInterceptorReady = true;
9078
+ stopRawInterceptorFastRetry();
9079
+ return;
9080
+ }
9081
+ const ready = initRawModelInterceptor();
9082
+ if (ready && !rawInterceptorReady) {
9083
+ log("info", "\u539F\u59CB\u8F93\u51FA\u62E6\u622A\u5DF2\u6062\u590D");
9084
+ }
9085
+ rawInterceptorReady = ready;
9086
+ if (!ready) startRawInterceptorFastRetry();
9087
+ };
9088
+ const startRawInterceptorMonitor = () => {
9089
+ if (rawInterceptorMonitorHandle) return;
9090
+ rawInterceptorMonitorHandle = ctx.setInterval(() => {
9091
+ const wasReady = rawInterceptorReady;
9092
+ ensureRawInterceptorActive();
9093
+ if (!rawInterceptorReady && wasReady) {
9094
+ log("warn", "\u539F\u59CB\u8F93\u51FA\u62E6\u622A\u5931\u6548\uFF0C\u5C06\u7EE7\u7EED\u91CD\u8BD5");
9095
+ }
9096
+ }, RAW_INTERCEPTOR_MONITOR_INTERVAL);
8897
9097
  };
8898
9098
  const startDelay = 3e3;
8899
9099
  log("debug", `\u539F\u59CB\u8F93\u51FA\u62E6\u622A\u5C06\u5728 ${startDelay}ms \u540E\u542F\u52A8`);
8900
9100
  ctx.setTimeout(() => {
8901
- if (initRawModelInterceptor()) {
9101
+ rawInterceptorReady = initRawModelInterceptor();
9102
+ if (rawInterceptorReady) {
8902
9103
  log("info", "\u5DF2\u542F\u7528\u539F\u59CB\u8F93\u51FA\u62E6\u622A\u6A21\u5F0F");
8903
9104
  } else {
8904
- log("warn", "chatluna_character \u670D\u52A1\u4E0D\u53EF\u7528\uFF0C\u5C06\u6BCF10\u5206\u949F\u91CD\u8BD5\u4E00\u6B21");
8905
- startRawInterceptorRetry();
9105
+ log("warn", "chatluna_character \u670D\u52A1\u4E0D\u53EF\u7528\uFF0C\u5C06\u6BCF3\u79D2\u91CD\u8BD5\u4E00\u6B21");
9106
+ startRawInterceptorFastRetry();
8906
9107
  }
9108
+ startRawInterceptorMonitor();
8907
9109
  }, startDelay);
8908
9110
  const fetchMemberBound = (session, userId) => fetchMember(session, userId);
8909
9111
  const resolveUserIdentityBound = (session, input) => resolveUserIdentity(session, input);
@@ -8993,7 +9195,8 @@ function apply(ctx, config) {
8993
9195
  const userInfoProvider = createUserInfoProvider({
8994
9196
  config,
8995
9197
  log,
8996
- fetchMember: fetchMemberBound
9198
+ fetchMember: fetchMemberBound,
9199
+ store
8997
9200
  });
8998
9201
  const userInfoName = String(
8999
9202
  config.userInfo?.variableName || config.otherVariables?.userInfo?.variableName || "userInfo"
@@ -9082,7 +9285,7 @@ function apply(ctx, config) {
9082
9285
  plugin.registerTool(toolName, {
9083
9286
  selector: () => true,
9084
9287
  authorization: (session) => session?.platform === "onebot",
9085
- createTool: () => createPokeTool({ ctx, toolName, log })
9288
+ createTool: () => createPokeTool({ ctx, toolName, log, protocol: onebotProtocol })
9086
9289
  });
9087
9290
  log("info", `\u6233\u4E00\u6233\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
9088
9291
  }
@@ -9099,7 +9302,7 @@ function apply(ctx, config) {
9099
9302
  plugin.registerTool(toolName, {
9100
9303
  selector: () => true,
9101
9304
  authorization: (session) => session?.platform === "onebot",
9102
- createTool: () => createSetProfileTool({ ctx, toolName, log })
9305
+ createTool: () => createSetProfileTool({ ctx, toolName, log, protocol: onebotProtocol })
9103
9306
  });
9104
9307
  log("info", `\u8BBE\u7F6E\u8D44\u6599\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
9105
9308
  }
@@ -9117,7 +9320,7 @@ function apply(ctx, config) {
9117
9320
  plugin.registerTool(toolName, {
9118
9321
  selector: () => true,
9119
9322
  authorization: (session) => session?.platform === "onebot",
9120
- createTool: () => createSetMsgEmojiTool({ toolName, log })
9323
+ createTool: () => createSetMsgEmojiTool({ toolName, log, protocol: onebotProtocol })
9121
9324
  });
9122
9325
  log("info", `\u6D88\u606F\u8868\u60C5\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
9123
9326
  }
@@ -9129,7 +9332,8 @@ function apply(ctx, config) {
9129
9332
  createTool: () => createForwardMessageTool({
9130
9333
  toolName,
9131
9334
  messageStore,
9132
- log
9335
+ log,
9336
+ protocol: onebotProtocol
9133
9337
  })
9134
9338
  });
9135
9339
  log("info", `\u5408\u5E76\u8F6C\u53D1\u6D88\u606F\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
@@ -9139,7 +9343,7 @@ function apply(ctx, config) {
9139
9343
  plugin.registerTool(toolName, {
9140
9344
  selector: () => true,
9141
9345
  authorization: (session) => session?.platform === "onebot",
9142
- createTool: () => createFakeMessageTool({ toolName, log })
9346
+ createTool: () => createFakeMessageTool({ toolName, log, protocol: onebotProtocol })
9143
9347
  });
9144
9348
  log("info", `\u4F2A\u9020\u6D88\u606F\u5DE5\u5177\u5DF2\u6CE8\u518C: ${toolName}`);
9145
9349
  }
@@ -9172,15 +9376,16 @@ function apply(ctx, config) {
9172
9376
  var usage = `
9173
9377
  ## \u66F4\u65B0\u65E5\u5FD7
9174
9378
 
9379
+ 0.2.4
9380
+ - userInfo \u53D8\u91CF\u65B0\u589E chatCount \u5B57\u6BB5\uFF0C\u53EF\u5C55\u793A\u804A\u5929\u6B21\u6570
9381
+ - \u4FEE\u590D\u72B6\u6001\u6539\u53D8\u540E XML \u5DE5\u5177\u62E6\u622A\u5931\u6548\u7684\u95EE\u9898
9382
+
9383
+ 0.2.3
9384
+ - OneBot \u534F\u8BAE\u65B0\u589E NapCat/LLBot \u72EC\u7ACB\u9009\u9879\uFF0C\u6309\u914D\u7F6E\u9009\u62E9\u534F\u8BAE
9385
+
9175
9386
  0.2.3-alpha.4
9176
9387
  - \u4FEE\u590D\u65E5\u7A0B\u751F\u6210\u63D0\u793A\u8BCD\u4EBA\u8BBE\u6CE8\u5165\u53D8\u91CF {persona} \u5931\u6548\u7684\u95EE\u9898\uFF0C\u65B0\u589E\u6A21\u578B\u9009\u62E9\u4E0E\u4EBA\u8BBE\u6CE8\u5165\u9009\u9879
9177
9388
  - \u5929\u6C14\u670D\u52A1\u5207\u6362\u4E3A open-meteo\uFF0C\u4E0D\u518D\u9700\u8981\u63D0\u4F9B token
9178
-
9179
- 0.2.3-alpha.3
9180
- - \u4FEE\u590D\u65E0\u6CD5\u9009\u62E9\u65E5\u7A0B\u6A21\u578B\u7684\u95EE\u9898
9181
-
9182
- 0.2.3-alpha.2
9183
- - \u4FEE\u590D\u597D\u611F\u5EA6\u66F4\u65B0\u65F6\u672A\u66F4\u65B0 chatCount \u7684\u95EE\u9898
9184
9389
  `;
9185
9390
  // Annotate the CommonJS export names for ESM import in node:
9186
9391
  0 && (module.exports = {
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import type { Session } from 'koishi';
6
6
  import type { Config, MemberInfo, LogFn } from '../../../types';
7
+ import type { AffinityStore } from '../../../services/affinity/store';
7
8
  interface ProviderConfigurable {
8
9
  session?: Session;
9
10
  }
@@ -11,6 +12,7 @@ export interface UserInfoProviderDeps {
11
12
  config: Config;
12
13
  log?: LogFn;
13
14
  fetchMember: (session: Session, userId: string) => Promise<MemberInfo | null>;
15
+ store: AffinityStore;
14
16
  }
15
17
  export declare function createUserInfoProvider(deps: UserInfoProviderDeps): (_args: unknown, _variables: unknown, configurable?: ProviderConfigurable) => Promise<string>;
16
18
  export type UserInfoProvider = ReturnType<typeof createUserInfoProvider>;
@@ -3,6 +3,7 @@
3
3
  * 提供 OneBot 平台 API 调用的辅助函数
4
4
  */
5
5
  import type { Session } from 'koishi';
6
+ export type OneBotProtocol = 'napcat' | 'llbot';
6
7
  export interface OneBotInternal {
7
8
  _request?: (action: string, params: Record<string, unknown>) => Promise<unknown>;
8
9
  [key: string]: unknown;
@@ -5,15 +5,18 @@
5
5
  import { z } from 'zod';
6
6
  import type { Context, Session } from 'koishi';
7
7
  import type { LogFn } from '../../../types';
8
+ import { type OneBotProtocol } from '../api';
8
9
  export interface PokeToolDeps {
9
10
  ctx: Context;
10
11
  toolName: string;
12
+ protocol: OneBotProtocol;
11
13
  log?: LogFn;
12
14
  }
13
15
  export interface SendPokeParams {
14
16
  session: Session | null;
15
17
  userId: string;
16
18
  groupId?: string;
19
+ protocol: OneBotProtocol;
17
20
  log?: LogFn;
18
21
  }
19
22
  export declare function sendPoke(params: SendPokeParams): Promise<string>;
@@ -5,9 +5,11 @@
5
5
  import { z } from 'zod';
6
6
  import type { Context } from 'koishi';
7
7
  import type { LogFn } from '../../../types';
8
+ import { type OneBotProtocol } from '../api';
8
9
  export interface ProfileToolDeps {
9
10
  ctx: Context;
10
11
  toolName: string;
12
+ protocol: OneBotProtocol;
11
13
  log?: LogFn;
12
14
  }
13
15
  export declare function createSetProfileTool(deps: ProfileToolDeps): {
@@ -4,8 +4,10 @@
4
4
  */
5
5
  import { z } from 'zod';
6
6
  import type { LogFn } from '../../../types';
7
+ import { type OneBotProtocol } from '../api';
7
8
  export interface FakeMessageToolDeps {
8
9
  toolName: string;
10
+ protocol: OneBotProtocol;
9
11
  log?: LogFn;
10
12
  }
11
13
  export declare function createFakeMessageTool(deps: FakeMessageToolDeps): {
@@ -5,9 +5,11 @@
5
5
  import { z } from 'zod';
6
6
  import type { LogFn } from '../../../types';
7
7
  import type { MessageStore } from '../../../services/message/store';
8
+ import { type OneBotProtocol } from '../api';
8
9
  export interface ForwardMessageToolDeps {
9
10
  toolName: string;
10
11
  messageStore: MessageStore;
12
+ protocol: OneBotProtocol;
11
13
  log?: LogFn;
12
14
  }
13
15
  export declare function createForwardMessageTool(deps: ForwardMessageToolDeps): {
@@ -5,14 +5,17 @@
5
5
  import { StructuredTool } from '@langchain/core/tools';
6
6
  import type { LogFn } from '../../../types';
7
7
  import type { Session } from 'koishi';
8
+ import { type OneBotProtocol } from '../api';
8
9
  export interface SetMsgEmojiToolDeps {
9
10
  toolName: string;
11
+ protocol: OneBotProtocol;
10
12
  log?: LogFn;
11
13
  }
12
14
  export interface SendMsgEmojiParams {
13
15
  session: Session | null;
14
16
  messageId: string;
15
17
  emojiId: string;
18
+ protocol: OneBotProtocol;
16
19
  log?: LogFn;
17
20
  }
18
21
  export declare function sendMsgEmoji(params: SendMsgEmojiParams): Promise<string>;
@@ -137,7 +137,7 @@ export declare const ConfigSchema: Schema<{
137
137
  } & {
138
138
  userInfo?: ({
139
139
  variableName?: string | null | undefined;
140
- items?: ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[] | null | undefined;
140
+ items?: ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[] | null | undefined;
141
141
  } & import("cosmokit").Dict) | null | undefined;
142
142
  botInfo?: ({
143
143
  variableName?: string | null | undefined;
@@ -155,6 +155,8 @@ export declare const ConfigSchema: Schema<{
155
155
  max?: number | null | undefined;
156
156
  } & import("cosmokit").Dict) | null | undefined;
157
157
  } & {
158
+ enableNapCatProtocol?: boolean | null | undefined;
159
+ enableLlbotProtocol?: boolean | null | undefined;
158
160
  enablePokeTool?: boolean | null | undefined;
159
161
  pokeToolName?: string | null | undefined;
160
162
  enableSetSelfProfileTool?: boolean | null | undefined;
@@ -333,7 +335,7 @@ export declare const ConfigSchema: Schema<{
333
335
  } & {
334
336
  userInfo: Schemastery.ObjectT<{
335
337
  variableName: Schema<string, string>;
336
- items: Schema<("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[], ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[]>;
338
+ items: Schema<("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[], ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[]>;
337
339
  }>;
338
340
  botInfo: Schemastery.ObjectT<{
339
341
  variableName: Schema<string, string>;
@@ -351,6 +353,8 @@ export declare const ConfigSchema: Schema<{
351
353
  max: Schema<number, number>;
352
354
  }>;
353
355
  } & {
356
+ enableNapCatProtocol: boolean;
357
+ enableLlbotProtocol: boolean;
354
358
  enablePokeTool: boolean;
355
359
  pokeToolName: string;
356
360
  enableSetSelfProfileTool: boolean;
@@ -4,6 +4,8 @@
4
4
  */
5
5
  import { Schema } from 'koishi';
6
6
  export declare const NativeToolsSchema: Schema<Schemastery.ObjectS<{
7
+ enableNapCatProtocol: Schema<boolean, boolean>;
8
+ enableLlbotProtocol: Schema<boolean, boolean>;
7
9
  enablePokeTool: Schema<boolean, boolean>;
8
10
  pokeToolName: Schema<string, string>;
9
11
  enableSetSelfProfileTool: Schema<boolean, boolean>;
@@ -38,6 +40,8 @@ export declare const NativeToolsSchema: Schema<Schemastery.ObjectS<{
38
40
  panSouMaxResults: Schema<number, number>;
39
41
  }>>;
40
42
  }>, Schemastery.ObjectT<{
43
+ enableNapCatProtocol: Schema<boolean, boolean>;
44
+ enableLlbotProtocol: Schema<boolean, boolean>;
41
45
  enablePokeTool: Schema<boolean, boolean>;
42
46
  pokeToolName: Schema<string, string>;
43
47
  enableSetSelfProfileTool: Schema<boolean, boolean>;
@@ -6,10 +6,10 @@ import { Schema } from 'koishi';
6
6
  export declare const OtherVariablesSchema: Schema<Schemastery.ObjectS<{
7
7
  userInfo: Schema<Schemastery.ObjectS<{
8
8
  variableName: Schema<string, string>;
9
- items: Schema<("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[], ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[]>;
9
+ items: Schema<("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[], ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[]>;
10
10
  }>, Schemastery.ObjectT<{
11
11
  variableName: Schema<string, string>;
12
- items: Schema<("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[], ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[]>;
12
+ items: Schema<("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[], ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[]>;
13
13
  }>>;
14
14
  botInfo: Schema<Schemastery.ObjectS<{
15
15
  variableName: Schema<string, string>;
@@ -41,10 +41,10 @@ export declare const OtherVariablesSchema: Schema<Schemastery.ObjectS<{
41
41
  }>, Schemastery.ObjectT<{
42
42
  userInfo: Schema<Schemastery.ObjectS<{
43
43
  variableName: Schema<string, string>;
44
- items: Schema<("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[], ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[]>;
44
+ items: Schema<("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[], ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[]>;
45
45
  }>, Schemastery.ObjectT<{
46
46
  variableName: Schema<string, string>;
47
- items: Schema<("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[], ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime")[]>;
47
+ items: Schema<("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[], ("nickname" | "userId" | "role" | "level" | "title" | "gender" | "age" | "area" | "joinTime" | "lastSentTime" | "chatCount")[]>;
48
48
  }>>;
49
49
  botInfo: Schema<Schemastery.ObjectS<{
50
50
  variableName: Schema<string, string>;
@@ -119,6 +119,8 @@ export interface Config {
119
119
  userInfo: UserInfoConfig;
120
120
  botInfo: BotInfoConfig;
121
121
  groupInfo: GroupInfoConfig;
122
+ enableNapCatProtocol: boolean;
123
+ enableLlbotProtocol: boolean;
122
124
  enablePokeTool: boolean;
123
125
  pokeToolName: string;
124
126
  enablePokeXmlTool: boolean;
@@ -3,7 +3,7 @@
3
3
  * 包含群成员信息、角色映射、群信息等类型
4
4
  */
5
5
  import type { LogFn } from './common';
6
- export type MemberInfoField = 'nickname' | 'userId' | 'role' | 'level' | 'title' | 'gender' | 'age' | 'area' | 'joinTime' | 'lastSentTime';
6
+ export type MemberInfoField = 'nickname' | 'userId' | 'role' | 'level' | 'title' | 'gender' | 'age' | 'area' | 'joinTime' | 'lastSentTime' | 'chatCount';
7
7
  export interface MemberInfo {
8
8
  card?: string;
9
9
  remark?: string;
@@ -58,6 +58,7 @@ export interface RenderMemberInfoOptions {
58
58
  defaultItems?: MemberInfoField[];
59
59
  logUnknown?: boolean;
60
60
  log?: LogFn;
61
+ chatCount?: number;
61
62
  }
62
63
  export interface GroupInfo {
63
64
  group_id?: string | number;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-chatluna-affinity",
3
3
  "description": "为 ChatLuna Character 提供更多变量及工具,例如 {好感度}、{关系}、{日程}、{天气}、{用户信息}、{机器人信息}、{群信息}等变量并提供对应的工具调用和低好感自动拉黑功能。",
4
- "version": "0.2.3-alpha.4",
4
+ "version": "0.2.4",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
package/readme.md CHANGED
@@ -110,6 +110,13 @@ MIT © 2024-present chatluna-affinity contributors
110
110
 
111
111
  ## 更新日志
112
112
 
113
+ 0.2.4
114
+ - userInfo 变量新增 chatCount 字段,可展示聊天次数
115
+ - 修复状态改变后 XML 工具拦截失效的问题
116
+
117
+ 0.2.3
118
+ - OneBot 协议新增 NapCat/LLBot 独立选项,按配置选择协议
119
+
113
120
  0.2.3-alpha.4
114
121
  - 修复日程生成提示词人设注入变量 {persona} 失效的问题,新增模型选择与人设注入选项
115
122
  - 天气服务切换为 open-meteo,不再需要提供 token