From 0cac804edc9458943ae3c6f5eddf21e344fb64ff Mon Sep 17 00:00:00 2001 From: baiyu-yu <135424680+baiyu-yu@users.noreply.github.com> Date: Thu, 8 Jan 2026 16:30:49 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E5=90=88=E5=B9=B6=E8=BD=AC?= =?UTF-8?q?=E5=8F=91tool=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nc和llob文档里支持良好。只做了图片和文本类型的支持。issue#2 --- src/tool/tool_message.ts | 140 ++++++++++++++++++++++++++++++++++++++- src/utils/utils_ob11.ts | 32 ++++++++- 2 files changed, 170 insertions(+), 2 deletions(-) diff --git a/src/tool/tool_message.ts b/src/tool/tool_message.ts index 1772b6d..4865a96 100644 --- a/src/tool/tool_message.ts +++ b/src/tool/tool_message.ts @@ -5,7 +5,7 @@ import { getCtxAndMsg } from "../utils/utils_seal"; import { handleReply, MessageSegment, transformArrayToContent } from "../utils/utils_string"; import { Tool, ToolManager } from "./tool"; import { CQTYPESALLOW } from "../config/config"; -import { deleteMsg, getGroupMemberInfo, getMsg, netExists } from "../utils/utils_ob11"; +import { deleteMsg, getGroupMemberInfo, getMsg, sendGroupForwardMsg, sendPrivateForwardMsg, netExists } from "../utils/utils_ob11"; export function registerMessage() { const toolSend = new Tool({ @@ -178,4 +178,142 @@ export function registerMessage() { await deleteMsg(epId, transformMsgIdBack(msg_id)); return { content: `已撤回消息${msg_id}`, images: [] }; } + + const toolMerge = new Tool({ + type: 'function', + function: { + name: 'send_forward_msg', + description: '发送合并转发消息', + parameters: { + type: 'object', + properties: { + msg_type: { + type: 'string', + description: '消息类型,私聊或群聊', + enum: ['private', 'group'] + }, + id: { + type: 'string', + description: '接收者ID,群号或QQ号' + }, + messages: { + type: 'array', + description: '消息节点列表,可以有多个', + items: { + type: 'object', + properties: { + name: { + type: 'string', + description: '发送者名称' + }, + uin: { + type: 'string', + description: '发送者QQ号' + }, + content: { + type: 'string', + description: '消息内容,和图片二选一' + }, + image_url: { + type: 'string', + description: '图片ID,发送图片时必须用这个字段' + } + }, + required: ['uin'] + } + } + }, + required: ['msg_type', 'id', 'messages'] + } + } + }); + toolMerge.solve = async (ctx, _, ai, args) => { + const { msg_type, id, messages } = args; + + if (!netExists()) return { content: `未找到ob11网络连接依赖,请提示用户安装`, images: [] }; + + const nodes = []; + for (const msg of messages) { + const contentNode = []; + + if (msg.content) { + const regex = /([<<][\|│|]img:.+?(?:[\|│|][>>]|[\|│|>>]))/g; + const parts = msg.content.split(regex); + + for (const part of parts) { + if (!part) continue; + + const match = part.match(/[<<][\|│|]img:(.+?)(?:[\|│|][>>]|[\|│|>>])/); + if (match) { + const id = match[1].trim(); + const image = await ai.context.findImage(ctx, id); + if (image) { + const file = image.type === 'base64' ? seal.base64ToImage(image.base64) : image.file; + contentNode.push({ + type: "image", + data: { + file: file + } + }); + } else { + contentNode.push({ + type: "text", + data: { + text: part + } + }); + } + } else { + contentNode.push({ + type: "text", + data: { + text: part + } + }); + } + } + } + + if (msg.image_url) { + const image = await ai.context.findImage(ctx, msg.image_url); + if (!image) { + return { content: `未找到图片<${msg.image_url}>`, images: [] }; + } + + const file = image.type === 'base64' ? seal.base64ToImage(image.base64) : image.file; + contentNode.push({ + type: "image", + data: { + file: file + } + }); + } + + if (contentNode.length === 0) { + return { content: `消息节点必须包含 content 或 image_url 其中之一`, images: [] }; + } + + nodes.push({ + type: 'node', + data: { + uin: String(msg.uin || ctx.endPoint.userId.replace(/^.+:/, '')), + name: msg.name, + content: contentNode + } + }); + } + + try { + if (msg_type === 'group') { + await sendGroupForwardMsg(ctx.endPoint.userId, id, nodes); + } else if (msg_type === 'private') { + await sendPrivateForwardMsg(ctx.endPoint.userId, id, nodes); + } else { + return { content: `不支持的消息类型`, images: [] }; + } + return { content: `发送成功`, images: [] }; + } catch (e) { + return { content: `发送出错: ${e.message}`, images: [] }; + } + } } \ No newline at end of file diff --git a/src/utils/utils_ob11.ts b/src/utils/utils_ob11.ts index 715fa10..123ce19 100644 --- a/src/utils/utils_ob11.ts +++ b/src/utils/utils_ob11.ts @@ -249,4 +249,34 @@ export async function sendGroupAISound(epId: string, characterId: string, group_ logger.error(`发送群 ${group_id} AI 声聊合成语音失败:${e}`); return; } -} \ No newline at end of file +} + +export async function sendGroupForwardMsg(epId: string, group_id: string, messages: any[]): Promise { + const net = getNet(); + if (!net) return null; + try { + const data = await net.callApi(epId, 'send_group_forward_msg', { + group_id, + messages + }) + return data; + } catch (e) { + logger.error(`发送群 ${group_id} 转发消息失败:${e}`); + return null; + } +} + +export async function sendPrivateForwardMsg(epId: string, user_id: string, messages: any[]): Promise { + const net = getNet(); + if (!net) return null; + try { + const data = await net.callApi(epId, 'send_private_forward_msg', { + user_id, + messages + }) + return data; + } catch (e) { + logger.error(`发送用户 ${user_id} 转发消息失败:${e}`); + return null; + } +} From fb6b053e2d410492b6fa8721692d56798e542efc Mon Sep 17 00:00:00 2001 From: error2913 <2913949387@qq.com> Date: Mon, 2 Feb 2026 20:29:11 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E9=87=87=E7=94=A8`parseSpecialTokens`?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=A7=A3=E6=9E=90=E5=90=AB=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AI/image.ts | 26 ++++--- src/tool/tool_message.ts | 163 ++++++++++++++++++++++----------------- src/utils/utils_ob11.ts | 4 +- 3 files changed, 112 insertions(+), 81 deletions(-) diff --git a/src/AI/image.ts b/src/AI/image.ts index b5e5258..9b72daa 100644 --- a/src/AI/image.ts +++ b/src/AI/image.ts @@ -3,7 +3,7 @@ import { sendITTRequest } from "../service"; import { generateId } from "../utils/utils"; import { logger } from "../logger"; import { AI } from "./AI"; -import { MessageSegment } from "../utils/utils_string"; +import { MessageSegment, parseSpecialTokens } from "../utils/utils_string"; export class Image { static validKeys: (keyof Image)[] = ['id', 'file', 'content']; @@ -257,15 +257,21 @@ ${img.CQCode}`; } static async extractExistingImagesToSave(ctx: seal.MsgContext, ai: AI, s: string): Promise { - const images = []; - const match = s.match(/[<<][\|│|]img:.+?(?:[\|│|][>>]|[\|│|>>])/g); - if (match) { - for (let i = 0; i < match.length; i++) { - const id = match[i].match(/[<<][\|│|]img:(.+?)(?:[\|│|][>>]|[\|│|>>])/)[1]; - const image = await ai.context.findImage(ctx, id); - if (image) { - if (image.type === 'url') await image.urlToBase64(); - images.push(image); + const segs = parseSpecialTokens(s); + const images: Image[] = []; + for (const seg of segs) { + switch (seg.type) { + case 'img': { + const id = seg.content; + const image = await ai.context.findImage(ctx, id); + + if (image) { + if (image.type === 'url') await image.urlToBase64(); + images.push(image); + } else { + logger.warning(`无法找到图片:${id}`); + } + break; } } } diff --git a/src/tool/tool_message.ts b/src/tool/tool_message.ts index 4865a96..465d225 100644 --- a/src/tool/tool_message.ts +++ b/src/tool/tool_message.ts @@ -2,10 +2,12 @@ import { AIManager } from "../AI/AI"; import { ConfigManager } from "../config/configManager"; import { replyToSender, transformMsgIdBack } from "../utils/utils"; import { getCtxAndMsg } from "../utils/utils_seal"; -import { handleReply, MessageSegment, transformArrayToContent } from "../utils/utils_string"; +import { handleReply, MessageSegment, parseSpecialTokens, transformArrayToContent } from "../utils/utils_string"; import { Tool, ToolManager } from "./tool"; -import { CQTYPESALLOW } from "../config/config"; +import { CQTYPESALLOW, faceMap } from "../config/config"; import { deleteMsg, getGroupMemberInfo, getMsg, sendGroupForwardMsg, sendPrivateForwardMsg, netExists } from "../utils/utils_ob11"; +import { logger } from "../logger"; +import { Image } from "../AI/image"; export function registerMessage() { const toolSend = new Tool({ @@ -50,13 +52,17 @@ export function registerMessage() { `来自<${ctx.player.name}>${showNumber ? `(${ctx.player.userId.replace(/^.+:/, '')})` : ``}` : `来自群聊<${ctx.group.groupName}>${showNumber ? `(${ctx.group.groupId.replace(/^.+:/, '')})` : ``}`; - const originalImages = []; - const match = content.match(/[<<][\|│|]img:.+?(?:[\|│|][>>]|[\|│|>>])/g); - if (match) { - for (let i = 0; i < match.length; i++) { - const id = match[i].match(/[<<][\|│|]img:(.+?)(?:[\|│|][>>]|[\|│|>>])/)[1].trim().slice(0, 6); - const image = await ai.context.findImage(ctx, id); - if (image) originalImages.push(image); + const segs = parseSpecialTokens(content); + const originalImages: Image[] = []; + for (const seg of segs) { + switch (seg.type) { + case 'img': { + const id = seg.content; + const image = await ai.context.findImage(ctx, id); + if (image) originalImages.push(image); + else logger.warning(`无法找到图片:${id}`); + break; + } } } @@ -212,14 +218,10 @@ export function registerMessage() { }, content: { type: 'string', - description: '消息内容,和图片二选一' - }, - image_url: { - type: 'string', - description: '图片ID,发送图片时必须用这个字段' + description: '消息内容' } }, - required: ['uin'] + required: ['content'] } } }, @@ -233,72 +235,93 @@ export function registerMessage() { if (!netExists()) return { content: `未找到ob11网络连接依赖,请提示用户安装`, images: [] }; const nodes = []; - for (const msg of messages) { - const contentNode = []; - - if (msg.content) { - const regex = /([<<][\|│|]img:.+?(?:[\|│|][>>]|[\|│|>>]))/g; - const parts = msg.content.split(regex); - - for (const part of parts) { - if (!part) continue; - - const match = part.match(/[<<][\|│|]img:(.+?)(?:[\|│|][>>]|[\|│|>>])/); - if (match) { - const id = match[1].trim(); + for (const messageItem of messages) { + const segs = parseSpecialTokens(messageItem.content); + const node = []; + for (const seg of segs) { + switch (seg.type) { + case 'text': { + node.push({ + type: 'text', + text: seg.content + }) + break; + } + case 'at': { + const name = seg.content; + const ui = await ai.context.findUserInfo(ctx, name); + if (ui !== null) { + node.push({ + type: 'at', + qq: ui.id.replace(/^.+:/, "") + }) + } else { + logger.warning(`无法找到用户:${name}`); + node.push({ + type: 'text', + text: ` @${name} ` + }) + } + break; + } + case 'poke': { + const name = seg.content; + const ui = await ai.context.findUserInfo(ctx, name); + if (ui !== null) { + node.push({ + type: 'poke', + qq: ui.id.replace(/^.+:/, "") + }) + } else { + logger.warning(`无法找到用户:${name}`); + } + break; + } + case 'quote': { + const msgId = seg.content; + node.push({ + type: 'reply', + id: transformMsgIdBack(msgId) + }) + break; + } + case 'img': { + const id = seg.content; const image = await ai.context.findImage(ctx, id); + if (image) { - const file = image.type === 'base64' ? seal.base64ToImage(image.base64) : image.file; - contentNode.push({ - type: "image", - data: { - file: file - } - }); + if (image.type === 'local') break; + const file = image.type === 'base64' ? image.base64 : image.file; + node.push({ + type: 'image', + data: { file: file } // 用base64发送是咋发的来着?↑ + }) } else { - contentNode.push({ - type: "text", - data: { - text: part - } - }); + logger.warning(`无法找到图片:${id}`); } - } else { - contentNode.push({ - type: "text", - data: { - text: part - } - }); + break; } - } - } - - if (msg.image_url) { - const image = await ai.context.findImage(ctx, msg.image_url); - if (!image) { - return { content: `未找到图片<${msg.image_url}>`, images: [] }; - } - - const file = image.type === 'base64' ? seal.base64ToImage(image.base64) : image.file; - contentNode.push({ - type: "image", - data: { - file: file + case 'face': { + const faceId = Object.keys(faceMap).find(key => faceMap[key] === seg.content) || ''; + node.push({ + type: 'face', + id: faceId + }) + break; } - }); + } } - if (contentNode.length === 0) { - return { content: `消息节点必须包含 content 或 image_url 其中之一`, images: [] }; + if (node.length === 0) { + return { content: `消息长度不能为0`, images: [] }; } nodes.push({ type: 'node', data: { - uin: String(msg.uin || ctx.endPoint.userId.replace(/^.+:/, '')), - name: msg.name, - content: contentNode + uin: String(messageItem.uin || ctx.endPoint.userId.replace(/^.+:/, '')), + name: messageItem.name || '未知用户', + content: node } }); } @@ -316,4 +339,6 @@ export function registerMessage() { return { content: `发送出错: ${e.message}`, images: [] }; } } -} \ No newline at end of file +} + +// TODO: 合并消息嵌套 \ No newline at end of file diff --git a/src/utils/utils_ob11.ts b/src/utils/utils_ob11.ts index 123ce19..226e663 100644 --- a/src/utils/utils_ob11.ts +++ b/src/utils/utils_ob11.ts @@ -251,7 +251,7 @@ export async function sendGroupAISound(epId: string, characterId: string, group_ } } -export async function sendGroupForwardMsg(epId: string, group_id: string, messages: any[]): Promise { +export async function sendGroupForwardMsg(epId: string, group_id: string, messages: MessageSegment[]): Promise { const net = getNet(); if (!net) return null; try { @@ -266,7 +266,7 @@ export async function sendGroupForwardMsg(epId: string, group_id: string, messag } } -export async function sendPrivateForwardMsg(epId: string, user_id: string, messages: any[]): Promise { +export async function sendPrivateForwardMsg(epId: string, user_id: string, messages: MessageSegment[]): Promise { const net = getNet(); if (!net) return null; try { From cacb76b04ee4f681323f98c0c83bce05bae5d238 Mon Sep 17 00:00:00 2001 From: error2913 <2913949387@qq.com> Date: Wed, 4 Feb 2026 23:58:07 +0800 Subject: [PATCH 3/5] Update tool_message.ts --- src/tool/tool_message.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tool/tool_message.ts b/src/tool/tool_message.ts index 465d225..659ee87 100644 --- a/src/tool/tool_message.ts +++ b/src/tool/tool_message.ts @@ -291,10 +291,10 @@ export function registerMessage() { if (image) { if (image.type === 'local') break; - const file = image.type === 'base64' ? image.base64 : image.file; + const file = image.type === 'base64' ? seal.base64ToImage(image.base64) : image.file; node.push({ type: 'image', - data: { file: file } // 用base64发送是咋发的来着?↑ + data: { file: file } }) } else { logger.warning(`无法找到图片:${id}`); From e72f8d24d2d8afd415218600b53320d2ca01fcd5 Mon Sep 17 00:00:00 2001 From: error2913 <2913949387@qq.com> Date: Thu, 5 Feb 2026 02:07:08 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E4=BF=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tool/tool_message.ts | 113 +++++++++++++++++++++------------------ src/utils/utils_ob11.ts | 38 +++++++++---- 2 files changed, 90 insertions(+), 61 deletions(-) diff --git a/src/tool/tool_message.ts b/src/tool/tool_message.ts index 659ee87..2e42fae 100644 --- a/src/tool/tool_message.ts +++ b/src/tool/tool_message.ts @@ -198,9 +198,9 @@ export function registerMessage() { description: '消息类型,私聊或群聊', enum: ['private', 'group'] }, - id: { + name: { type: 'string', - description: '接收者ID,群号或QQ号' + description: '用户名称或群聊名称' + (ConfigManager.message.showNumber ? '或纯数字QQ号、群号' : '') + ',实际使用时与消息类型对应' }, messages: { type: 'array', @@ -210,11 +210,11 @@ export function registerMessage() { properties: { name: { type: 'string', - description: '发送者名称' + description: '用户名称' + (ConfigManager.message.showNumber ? '或纯数字QQ号' : '') }, - uin: { + nickname: { type: 'string', - description: '发送者QQ号' + description: '发送者名称,默认与name相同' }, content: { type: 'string', @@ -225,25 +225,28 @@ export function registerMessage() { } } }, - required: ['msg_type', 'id', 'messages'] + required: ['msg_type', 'name', 'messages'] } } }); toolMerge.solve = async (ctx, _, ai, args) => { - const { msg_type, id, messages } = args; + const { msg_type, name, messages } = args; if (!netExists()) return { content: `未找到ob11网络连接依赖,请提示用户安装`, images: [] }; - const nodes = []; + const messagesToSend = []; + const images: Image[] = []; for (const messageItem of messages) { const segs = parseSpecialTokens(messageItem.content); - const node = []; + const content: MessageSegment[] = []; for (const seg of segs) { switch (seg.type) { case 'text': { - node.push({ + content.push({ type: 'text', - text: seg.content + data: { + text: seg.content + } }) break; } @@ -251,37 +254,28 @@ export function registerMessage() { const name = seg.content; const ui = await ai.context.findUserInfo(ctx, name); if (ui !== null) { - node.push({ + content.push({ type: 'at', - qq: ui.id.replace(/^.+:/, "") + data: { + qq: ui.id.replace(/^.+:/, "") + } }) } else { logger.warning(`无法找到用户:${name}`); - node.push({ + content.push({ type: 'text', - text: ` @${name} ` - }) - } - break; - } - case 'poke': { - const name = seg.content; - const ui = await ai.context.findUserInfo(ctx, name); - if (ui !== null) { - node.push({ - type: 'poke', - qq: ui.id.replace(/^.+:/, "") + data: { + text: ` @${name} ` + } }) - } else { - logger.warning(`无法找到用户:${name}`); } break; } case 'quote': { const msgId = seg.content; - node.push({ + content.push({ type: 'reply', - id: transformMsgIdBack(msgId) + data: { id: String(transformMsgIdBack(msgId)) } }) break; } @@ -291,10 +285,10 @@ export function registerMessage() { if (image) { if (image.type === 'local') break; - const file = image.type === 'base64' ? seal.base64ToImage(image.base64) : image.file; - node.push({ + images.push(image); + content.push({ type: 'image', - data: { file: file } + data: { file: image.type === 'base64' ? seal.base64ToImage(image.base64) : image.file } }) } else { logger.warning(`无法找到图片:${id}`); @@ -303,41 +297,58 @@ export function registerMessage() { } case 'face': { const faceId = Object.keys(faceMap).find(key => faceMap[key] === seg.content) || ''; - node.push({ + content.push({ type: 'face', - id: faceId + data: { id: faceId } }) break; } } } - if (node.length === 0) { + if (content.length === 0) { return { content: `消息长度不能为0`, images: [] }; } - nodes.push({ + let userId = ""; + let nickname = messageItem.nickname || ""; + const ui = await ai.context.findUserInfo(ctx, messageItem.name, true); + if (ui !== null) { + userId = ui.id.replace(/^.+:/, ""); + nickname = nickname || ui.name; + } + + messagesToSend.push({ type: 'node', data: { - uin: String(messageItem.uin || ctx.endPoint.userId.replace(/^.+:/, '')), - name: messageItem.name || '未知用户', - content: node + user_id: userId, + nickname: nickname, + content: content } }); } - try { - if (msg_type === 'group') { - await sendGroupForwardMsg(ctx.endPoint.userId, id, nodes); - } else if (msg_type === 'private') { - await sendPrivateForwardMsg(ctx.endPoint.userId, id, nodes); - } else { - return { content: `不支持的消息类型`, images: [] }; - } - return { content: `发送成功`, images: [] }; - } catch (e) { - return { content: `发送出错: ${e.message}`, images: [] }; + const news = null; + const prompt = ""; + const summary = ""; + const source = ""; + + if (msg_type === "private") { + const ui = await ai.context.findUserInfo(ctx, name, true); + if (ui === null) return { content: `未找到<${name}>`, images: [] }; + if (ui.id === ctx.endPoint.userId) return { content: `禁止向自己发送消息`, images: [] }; + + await sendPrivateForwardMsg(ctx.endPoint.userId, ui.id.replace(/^.+:/, ""), messagesToSend, news, prompt, summary, source); + } else if (msg_type === "group") { + const gi = await ai.context.findGroupInfo(ctx, name); + if (gi === null) return { content: `未找到<${name}>`, images: [] }; + + await sendGroupForwardMsg(ctx.endPoint.userId, gi.id.replace(/^.+:/, ""), messagesToSend, news, prompt, summary, source); + } else { + return { content: `未知的消息类型<${msg_type}>`, images: [] }; } + + return { content: `发送合并消息成功`, images: images }; } } diff --git a/src/utils/utils_ob11.ts b/src/utils/utils_ob11.ts index 226e663..f2d0e5d 100644 --- a/src/utils/utils_ob11.ts +++ b/src/utils/utils_ob11.ts @@ -251,32 +251,50 @@ export async function sendGroupAISound(epId: string, characterId: string, group_ } } -export async function sendGroupForwardMsg(epId: string, group_id: string, messages: MessageSegment[]): Promise { +export async function sendPrivateForwardMsg(epId: string, user_id: string, + messages: MessageSegment[], + news: string[], + prompt: string, + summary: string, + source: string): Promise { const net = getNet(); if (!net) return null; try { - const data = await net.callApi(epId, 'send_group_forward_msg', { - group_id, - messages + const data = await net.callApi(epId, 'send_private_forward_msg', { + user_id, + messages, + news, + prompt, + summary, + source }) return data; } catch (e) { - logger.error(`发送群 ${group_id} 转发消息失败:${e}`); + logger.error(`发送用户 ${user_id} 转发消息失败:${e}`); return null; } } -export async function sendPrivateForwardMsg(epId: string, user_id: string, messages: MessageSegment[]): Promise { +export async function sendGroupForwardMsg(epId: string, group_id: string, + messages: MessageSegment[], + news: string[], + prompt: string, + summary: string, + source: string): Promise { const net = getNet(); if (!net) return null; try { - const data = await net.callApi(epId, 'send_private_forward_msg', { - user_id, - messages + const data = await net.callApi(epId, 'send_group_forward_msg', { + group_id, + messages, + news, + prompt, + summary, + source }) return data; } catch (e) { - logger.error(`发送用户 ${user_id} 转发消息失败:${e}`); + logger.error(`发送群 ${group_id} 转发消息失败:${e}`); return null; } } From 41f4052101d4594ea7f95c96f0dd7d86f1d7ea56 Mon Sep 17 00:00:00 2001 From: error2913 <2913949387@qq.com> Date: Sat, 7 Feb 2026 20:11:11 +0800 Subject: [PATCH 5/5] Update update.ts --- src/update.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/update.ts b/src/update.ts index 1a26928..289b4d5 100644 --- a/src/update.ts +++ b/src/update.ts @@ -3,7 +3,10 @@ export const updateInfo = { "4.12.1": `- 新增按时间搜索记忆 - 新增图片头像ID发送 - 将img命令改为ai子命令 -- 新增render嵌入图片`, +- 新增render嵌入图片 +- 新增tti保存 +- 修复tool关闭状态发生错误反转的问题 +- 新增合并转发tool`, "4.12.0": `- 新增通过名称选择角色设定功能 - 修复获取好友、群聊等列表时的bug - 修复了调用函数时,无需cmdArgs的函数也会报错的问题