Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/AI/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,13 @@ export class Context {
this.messages.push(message);
}

async addToolMessage(tool_call_id: string, s: string) {
async addToolMessage(tool_call_id: string, s: string, images: Image[]) {
const message: Message = {
role: 'tool',
tool_call_id: tool_call_id,
uid: '',
name: '',
images: [],
images: images,
msgArray: [{
msgId: '',
time: Math.floor(Date.now() / 1000),
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,7 @@ ${Object.keys(tool.info.function.parameters.properties).map(key => {
}

tool.solve(ctx, msg, ai, args)
.then(s => seal.replyToSender(ctx, msg, s));
.then(({ content }) => seal.replyToSender(ctx, msg, content));
return ret;
} catch (e) {
const s = `调用函数 (${val2}) 失败:${e.message}`;
Expand Down
32 changes: 15 additions & 17 deletions src/tool/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { registerSetTrigger } from "./tool_trigger"
import { registerMusicPlay } from "./tool_music"
import { registerMeme } from "./tool_meme"
import { logger } from "../logger"
import { Image } from "../AI/image";

export interface ToolInfo {
type: "function",
Expand Down Expand Up @@ -65,7 +66,7 @@ export class Tool {
cmdInfo: CmdInfo; // 海豹指令信息
type: string; // 可使用函数的聊天场景类型:"private" | "group" | "all"
tool_choice: string; // 是否可以继续调用函数:"none" | "auto" | "required"
solve: (ctx: seal.MsgContext, msg: seal.Message, ai: AI, args: { [key: string]: any }) => Promise<string>;
solve: (ctx: seal.MsgContext, msg: seal.Message, ai: AI, args: { [key: string]: any }) => Promise<{ content: string, images: Image[] }>;

constructor(info: ToolInfo) {
this.info = info;
Expand All @@ -76,11 +77,10 @@ export class Tool {
}
this.type = "all"
this.tool_choice = 'auto';
this.solve = async (_, __, ___, ____) => "函数未实现";
this.solve = async (_, __, ___, ____) => ({ content: "函数未实现", images: [] });

ToolManager.toolMap[info.function.name] = this;
}

}

export class ToolManager {
Expand Down Expand Up @@ -270,7 +270,7 @@ export class ToolManager {
logger.warning('连续调用函数次数超过上限');
for (let i = 0; i < tool_calls.length; i++) {
const tool_call = tool_calls[i];
await ai.context.addToolMessage(tool_call.id, `连续调用函数次数超过上限`);
await ai.context.addToolMessage(tool_call.id, `连续调用函数次数超过上限`, []);
ai.tool.toolCallCount++;
}
return "none";
Expand Down Expand Up @@ -306,50 +306,49 @@ export class ToolManager {

if (this.cmdArgs == null) {
logger.warning(`暂时无法调用函数,请先使用 .r 指令`);
await ai.context.addToolMessage(tool_call.id, `暂时无法调用函数,请先提示用户使用 .r 指令`);
await ai.context.addToolMessage(tool_call.id, `暂时无法调用函数,请先提示用户使用 .r 指令`, []);
return "none";
}
if (ConfigManager.tool.toolsNotAllow.includes(name)) {
logger.warning(`调用函数失败:禁止调用的函数:${name}`);
await ai.context.addToolMessage(tool_call.id, `调用函数失败:禁止调用的函数:${name}`);
await ai.context.addToolMessage(tool_call.id, `调用函数失败:禁止调用的函数:${name}`, []);
return "none";
}
if (!this.toolMap.hasOwnProperty(name)) {
logger.warning(`调用函数失败:未注册的函数:${name}`);
await ai.context.addToolMessage(tool_call.id, `调用函数失败:未注册的函数:${name}`);
await ai.context.addToolMessage(tool_call.id, `调用函数失败:未注册的函数:${name}`, []);
return "none";
}


const tool = this.toolMap[name];
if (tool.type !== "all" && tool.type !== msg.messageType) {
logger.warning(`调用函数失败:函数${name}可使用的场景类型为${tool.type},当前场景类型为${msg.messageType}`);
await ai.context.addToolMessage(tool_call.id, `调用函数失败:函数${name}可使用的场景类型为${tool.type},当前场景类型为${msg.messageType}`);
await ai.context.addToolMessage(tool_call.id, `调用函数失败:函数${name}可使用的场景类型为${tool.type},当前场景类型为${msg.messageType}`, []);
return "none";
}

try {
const args = JSON.parse(tool_call.function.arguments);
if (args !== null && typeof args !== 'object') {
logger.warning(`调用函数失败:arguement不是一个object`);
await ai.context.addToolMessage(tool_call.id, `调用函数失败:arguement不是一个object`);
await ai.context.addToolMessage(tool_call.id, `调用函数失败:arguement不是一个object`, []);
return "auto";
}
for (const key of tool.info.function.parameters.required) {
if (!args.hasOwnProperty(key)) {
logger.warning(`调用函数失败:缺少必需参数 ${key}`);
await ai.context.addToolMessage(tool_call.id, `调用函数失败:缺少必需参数 ${key}`);
await ai.context.addToolMessage(tool_call.id, `调用函数失败:缺少必需参数 ${key}`, []);
return "auto";
}
}

const s = await tool.solve(ctx, msg, ai, args);

await ai.context.addToolMessage(tool_call.id, s);
const { content, images } = await tool.solve(ctx, msg, ai, args);
await ai.context.addToolMessage(tool_call.id, content, images);
return tool.tool_choice;
} catch (e) {
logger.error(`调用函数 (${name}:${tool_call.function.arguments}) 失败:${e.message}`);
await ai.context.addToolMessage(tool_call.id, `调用函数 (${name}:${tool_call.function.arguments}) 失败:${e.message}`);
await ai.context.addToolMessage(tool_call.id, `调用函数 (${name}:${tool_call.function.arguments}) 失败:${e.message}`, []);
return "none";
}
}
Expand Down Expand Up @@ -430,9 +429,8 @@ export class ToolManager {
}
}

const s = await tool.solve(ctx, msg, ai, args);

await ai.context.addSystemUserMessage('调用函数返回', s, []);
const { content, images } = await tool.solve(ctx, msg, ai, args);
await ai.context.addSystemUserMessage('调用函数返回', content, images);
} catch (e) {
logger.error(`调用函数 (${name}:${JSON.stringify(tool_call.arguments, null, 2)}) 失败:${e.message}`);
await ai.context.addSystemUserMessage('调用函数返回', `调用函数 (${name}:${JSON.stringify(tool_call.arguments, null, 2)}) 失败:${e.message}`, []);
Expand Down
18 changes: 9 additions & 9 deletions src/tool/tool_attr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,18 @@ export function registerAttr() {

const uid = await ai.context.findUserId(ctx, name);
if (uid === null) {
return `未找到<${name}>`;
return { content: `未找到<${name}>`, images: [] };
}

msg = createMsg(msg.messageType, uid, ctx.group.groupId);
ctx = createCtx(ctx.endPoint.userId, msg);

const [s, success] = await ToolManager.extensionSolve(ctx, msg, ai, toolShow.cmdInfo, [], [], []);
if (!success) {
return '展示失败';
return { content: '展示失败', images: [] };
}

return s;
return { content: s, images: [] };
}

const toolGet = new Tool({
Expand Down Expand Up @@ -70,14 +70,14 @@ export function registerAttr() {

const uid = await ai.context.findUserId(ctx, name);
if (uid === null) {
return `未找到<${name}>`;
return { content: `未找到<${name}>`, images: [] };
}

msg = createMsg(msg.messageType, uid, ctx.group.groupId);
ctx = createCtx(ctx.endPoint.userId, msg);

const value = seal.vars.intGet(ctx, attr)[0];
return `${attr}: ${value}`;
return { content: `${attr}: ${value}`, images: [] };
}

const toolSet = new Tool({
Expand Down Expand Up @@ -106,15 +106,15 @@ export function registerAttr() {

const uid = await ai.context.findUserId(ctx, name);
if (uid === null) {
return `未找到<${name}>`;
return { content: `未找到<${name}>`, images: [] };
}

msg = createMsg(msg.messageType, uid, ctx.group.groupId);
ctx = createCtx(ctx.endPoint.userId, msg);

const [attr, expr] = expression.split('=');
if (expr === undefined) {
return `修改失败,表达式 ${expression} 格式错误`;
return { content: `修改失败,表达式 ${expression} 格式错误`, images: [] };
}

const value = seal.vars.intGet(ctx, attr)[0];
Expand All @@ -130,12 +130,12 @@ export function registerAttr() {
const result = parseInt(seal.format(ctx, `{${s}}`));

if (isNaN(result)) {
return `修改失败,表达式 ${expression} 格式化错误`;
return { content: `修改失败,表达式 ${expression} 格式化错误`, images: [] };
}

seal.vars.intSet(ctx, attr, result);

seal.replyToSender(ctx, msg, `进行了 ${expression} 修改\n${attr}: ${value}=>${result}`);
return `进行了 ${expression} 修改\n${attr}: ${value}=>${result}`;
return { content: `进行了 ${expression} 修改\n${attr}: ${value}=>${result}`, images: [] };
}
}
32 changes: 16 additions & 16 deletions src/tool/tool_ban.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,18 @@ export function registerBan() {
const { name, duration } = args;

if (ctx.isPrivate) {
return `该命令只能在群聊中使用`;
return { content: `该命令只能在群聊中使用`, images: [] };
}

const net = globalThis.net || globalThis.http;
if (!net) {
logger.error(`未找到ob11网络连接依赖`);
return `未找到ob11网络连接依赖,请提示用户安装`;
return { content: `未找到ob11网络连接依赖,请提示用户安装`, images: [] };
}

const uid = await ai.context.findUserId(ctx, name);
if (uid === null) {
return `未找到<${name}>`;
return { content: `未找到<${name}>`, images: [] };
}

try {
Expand All @@ -50,11 +50,11 @@ export function registerBan() {
const user_id = epId.replace(/^.+:/, '');
const result = await net.callApi(epId, `get_group_member_info?group_id=${group_id}&user_id=${user_id}&no_cache=true`);
if (result.role !== 'owner' && result.role !== 'admin') {
return `你没有管理员权限`;
return { content: `你没有管理员权限`, images: [] };
}
} catch (e) {
logger.error(e);
return `获取权限信息失败`;
return { content: `获取权限信息失败`, images: [] };
}

try {
Expand All @@ -63,22 +63,22 @@ export function registerBan() {
const user_id = uid.replace(/^.+:/, '');
const result = await net.callApi(epId, `get_group_member_info?group_id=${group_id}&user_id=${user_id}&no_cache=true`);
if (result.role === 'owner' || result.role === 'admin') {
return `你无法禁言${result.role === 'owner' ? '群主' : '管理员'}`;
return { content: `你无法禁言${result.role === 'owner' ? '群主' : '管理员'}`, images: [] };
}
} catch (e) {
logger.error(e);
return `获取权限信息失败`;
return { content: `获取权限信息失败`, images: [] };
}

try {
const epId = ctx.endPoint.userId;
const group_id = ctx.group.groupId.replace(/^.+:/, '');
const user_id = uid.replace(/^.+:/, '');
await net.callApi(epId, `set_group_ban?group_id=${group_id}&user_id=${user_id}&duration=${duration}`);
return `已禁言<${name}> ${duration}秒`;
return { content: `已禁言<${name}> ${duration}秒`, images: [] };
} catch (e) {
logger.error(e);
return `禁言失败`;
return { content: `禁言失败`, images: [] };
}
}

Expand Down Expand Up @@ -106,17 +106,17 @@ export function registerBan() {
const net = globalThis.net || globalThis.http;
if (!net) {
logger.error(`未找到ob11网络连接依赖`);
return `未找到ob11网络连接依赖,请提示用户安装`;
return { content: `未找到ob11网络连接依赖,请提示用户安装`, images: [] };
}

try {
const epId = ctx.endPoint.userId;
const gid = ctx.group.groupId;
await net.callApi(epId, `set_group_whole_ban?group_id=${gid.replace(/^.+:/, '')}&enable=${enable}`);
return `已${enable ? '开启' : '关闭'}全员禁言`;
return { content: `已${enable ? '开启' : '关闭'}全员禁言`, images: [] };
} catch (e) {
logger.error(e);
return `全员禁言失败`;
return { content: `全员禁言失败`, images: [] };
}
}

Expand All @@ -138,7 +138,7 @@ export function registerBan() {
const net = globalThis.net || globalThis.http;
if (!net) {
logger.error(`未找到ob11网络连接依赖`);
return `未找到ob11网络连接依赖,请提示用户安装`;
return { content: `未找到ob11网络连接依赖,请提示用户安装`, images: [] };
}

try {
Expand All @@ -147,13 +147,13 @@ export function registerBan() {
const data = await net.callApi(epId, `get_group_shut_list?group_id=${gid.replace(/^.+:/, '')}`);

const s = `被禁言成员数量: ${data.length}\n` + data.slice(0, 50).map((item: any, index: number) => {
return `${index + 1}. ${item.nick}(${item.uin}) ${item.cardName && item.cardName !== item.nick ? `群名片: ${item.cardName}` : ''} 禁言结束时间: ${fmtDate(item.shutUpTime)}`;
return { content: `${index + 1}. ${item.nick}(${item.uin}) ${item.cardName && item.cardName !== item.nick ? `群名片: ${item.cardName}` : ''} 禁言结束时间: ${fmtDate(item.shutUpTime)}`, images: [] };
}).join('\n');

return s;
return { content: s, images: [] };
} catch (e) {
logger.error(e);
return `获取禁言列表失败`;
return { content: `获取禁言列表失败`, images: [] };
}
}
}
19 changes: 7 additions & 12 deletions src/tool/tool_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,16 @@ export function registerContext() {
toolGet.solve = async (ctx, msg, ai, args) => {
const { ctx_type, name } = args;

const originalAI = ai;

if (ctx_type === "private") {
const uid = await ai.context.findUserId(ctx, name, true);
if (uid === null) {
return `未找到<${name}>`;
return { content: `未找到<${name}>`, images: [] };
}
if (uid === ctx.player.userId && ctx.isPrivate) {
return `向当前私聊发送消息无需调用函数`;
return { content: `向当前私聊发送消息无需调用函数`, images: [] };
}
if (uid === ctx.endPoint.userId) {
return `禁止向自己发送消息`;
return { content: `禁止向自己发送消息`, images: [] };
}

msg = createMsg('private', uid, '');
Expand All @@ -51,18 +49,18 @@ export function registerContext() {
} else if (ctx_type === "group") {
const gid = await ai.context.findGroupId(ctx, name);
if (gid === null) {
return `未找到<${name}>`;
return { content: `未找到<${name}>`, images: [] };
}
if (gid === ctx.group.groupId) {
return `向当前群聊发送消息无需调用函数`;
return { content: `向当前群聊发送消息无需调用函数`, images: [] };
}

msg = createMsg('group', ctx.player.userId, gid);
ctx = createCtx(ctx.endPoint.userId, msg);

ai = AIManager.getAI(gid);
} else {
return `未知的上下文类型<${ctx_type}>`;
return { content: `未知的上下文类型<${ctx_type}>`, images: [] };
}

const messages = ai.context.messages;
Expand All @@ -77,9 +75,6 @@ export function registerContext() {
return `[${message.role}]: ${buildContent(message)}`;
}).join('\n');

// 将images添加到最后一条消息,以便使用
originalAI.context.messages[originalAI.context.messages.length - 1].images.push(...images);

return s;
return { content: s, images: images };
}
}
6 changes: 3 additions & 3 deletions src/tool/tool_deck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ export function registerDeck() {
const dr = seal.deck.draw(ctx, name, true);
if (!dr.exists) {
logger.error(`牌堆${name}不存在:${dr.err}`);
return `牌堆${name}不存在:${dr.err}`;
return { content: `牌堆${name}不存在:${dr.err}`, images: [] };
}

const result = dr.result;
if (result == null) {
logger.error(`牌堆${name}结果为空:${dr.err}`);
return `牌堆${name}结果为空:${dr.err}`;
return { content: `牌堆${name}结果为空:${dr.err}`, images: [] };
}

seal.replyToSender(ctx, msg, result);
return result;
return { content: result, images: [] };
}
}
Loading