import { waitForMoreOptionSelection, waitForOptionSelection, waitForTextInputTips } from "./conversations_util.ts"; import { fetchRoles, fetchKnowledge, fetchAgentByBotId, getBotInfo, getBotAcionInfo, insertData, getUserInfo, bindChatAgent, fetchKnowledgeCollection, getAgentBindKnowledge, deleteKnowledgeCollection, fetchAgentByUserId, bindagentAction } from "./db.ts"; import { type Conversation, type ConversationFlavor, } from "https://raw.githubusercontent.com/grammyjs/conversations/c90b7fed54d610b7a37c2e0b90e728bc4d739d9b/src/mod.ts"; import { respMsgAgent, respMsgQuestion, respKnowledgeApi, respKnowledgeCollectionApi, respKnowledgeCollectionDelApi } from "./fastgpt.ts"; const adminUUID = Deno.env.get('AGENT_ADMIN') ?? ""; type MyContext = Context & SessionFlavor<SessionData> & ConversationFlavor; type MyConversation = Conversation<MyContext>; async function asyncResponse(ctx, variables, agentTips, auth_token) { const { data: res, error } = await respMsgAgent(variables, agentTips, auth_token); if (error) { console.error(`Failed to insert data: ${error.message}`); } else { if (res && res.choices && res.choices[0] && res.choices[0].message) { await ctx.reply(res.choices[0].message.content); } else { await ctx.reply("Failed to retrieve response message content."); } } } async function createagent(conversation: MyConversation, ctx: MyContext) { const auth_token = Deno.env.get('FASTGPT_API_KEY_AGENT_CREATE') ?? ""; console.log("auth_token:", auth_token); const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; console.log("ctx.me.id:", ctx.me.id); const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const is_admin = userUUID === adminUUID; // fetchRoles const roles = await fetchRoles(is_admin ? "" : botUUID, userUUID); if (!roles) { await ctx.reply("Failed to retrieve roles, operation terminated"); return; } const availableRoles = roles.map((role) => `[${role.name}],`).join("\n"); const prompt = ` 关于agent角色,可选择的角色有: ${availableRoles} 您好,现在开始创建agent,请按照以下 格式 输入 agent相关信息: 名称:xxx 描述:xxx 角色:xxx 我会讲的语言: 1,xxx 2,xxx ` const agentTips = await waitForTextInputTips(conversation, ctx, prompt); if (!agentTips) return; const role_type = is_admin ? 1 : 2; const variables = { bot_id: botUUID, user_id: userUUID, role_type: role_type, }; await asyncResponse(ctx, variables, agentTips, auth_token); // EdgeRuntime.waitUntil() } async function updateagent(conversation: MyConversation, ctx: MyContext) { const auth_token = Deno.env.get('FASTGPT_API_KEY_AGENT') ?? ""; console.log("auth_token:", auth_token); const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const is_admin = userUUID === adminUUID; // fetchRoles const roles = await fetchRoles(is_admin ? "" : botUUID, userUUID); if (!roles) { await ctx.reply("Failed to retrieve roles, operation terminated"); return; } const availableRoles = roles.map((role) => `[${role.name}],`).join("\n"); const prompt = ` 关于agent角色,可选择的角色有: :${availableRoles} 您好,请问 您希望我帮你做什么呢?您可以这样回答我,比如: 1,把 知识库 xxx 绑定 到 agent上,agent名称为 xxx (绑定知识库) 2,我 需要 把 知识库 xxx 从 名称为 xxx 的agent 上 解除 (解绑知识库) 3,我要把名称为 xxx 的agent 名称 修改 为 xxx (修改名称) 4,修改 名称为 xxx 的 agent 的描述为 xxx (修改描述) 5,把 名称为 xxx 的 agent 的 角色 换为 xxx (更换 角色) ` const agentTips = await waitForTextInputTips(conversation, ctx, prompt); if (!agentTips) return; const role_type = is_admin ? 1 : 2; const variables = { bot_id: botUUID, user_id: userUUID, role_type: role_type, }; await asyncResponse(ctx, variables, agentTips, auth_token); // EdgeRuntime.waitUntil(asyncResponse(ctx, variables, agentTips, auth_token)) } async function deleteagent(conversation: MyConversation, ctx: MyContext) { const auth_token = Deno.env.get('FASTGPT_API_KEY_AGENT') ?? ""; console.log("auth_token:", auth_token); const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const agents = await fetchAgentByBotId(botUUID, userUUID); if (!agents) { await ctx.reply("Failed to retrieve agent information, operation terminated"); return; } const agentName = agents.map((agent) => `agent name: ${agent.name}`).join("\n"); const prompt = ` 目前支持您删除的agent有:${agentName} 您好,请问 您希望我帮你做什么呢?您可以这样回答我,比如: 我 要删除 xxx agent` const agentTips = await waitForTextInputTips(conversation, ctx, prompt); if (!agentTips) return; const role_type = userUUID === adminUUID ? 1 : 2; const variables = { bot_id: botUUID, user_id: userUUID, role_type: role_type, }; await asyncResponse(ctx, variables, agentTips, auth_token); // EdgeRuntime.waitUntil(asyncResponse(ctx, variables, agentTips, auth_token)) } async function listagents(conversation: MyConversation, ctx: MyContext) { const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const agents = await fetchAgentByBotId(botUUID, userUUID); if (!agents) { await ctx.reply("Failed to retrieve agent information, operation terminated"); return; } if (agents.length === 0) { await ctx.reply("No agents found"); return; } const agentName = agents.map((agent) => `agent name:${agent.name}`).join("\n"); await ctx.reply(`The agents you can operate are ${agentName}`); } async function createrole(conversation: MyConversation, ctx: MyContext) { const auth_token = Deno.env.get('FASTGPT_API_KEY_ROLE') ?? ""; console.log("auth_token:", auth_token); const prompt = `您好,很高兴见到您,您可以这样回答我: 创建一个角色 名称:xxx 描述:xxx 性别:男/女/保密 性格: 1,xxx 2,xxx 3,xxx 技能: 1,xxx 2,xxx 3,xxx 目标任务: 1,xxx 2,xxx 我不能做什么: 1,xxx 2,xxx 我会讲的语言: 1,汉语 2,英文 3,西班牙语等` const agentTips = await waitForTextInputTips(conversation, ctx, prompt); if (!agentTips) return; const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const isAdmin = userUUID === adminUUID; const role_type = isAdmin ? 1 : 2; const variables = { bot_id: botUUID, user_id: userUUID, role_type: role_type, }; await asyncResponse(ctx, variables, agentTips, auth_token); // EdgeRuntime.waitUntil(asyncResponse(ctx, variables, agentTips, auth_token)) } async function updaterole(conversation: MyConversation, ctx: MyContext) { const auth_token = Deno.env.get('FASTGPT_API_KEY_ROLE') ?? ""; console.log("auth_token:", auth_token); const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const is_admin = userUUID === adminUUID; // fetchRoles const roles = await fetchRoles(is_admin ? "" : botUUID, userUUID); if (!roles) { await ctx.reply("Failed to retrieve roles, operation terminated"); return; } const roleNames = roles.map((role) => `[${role.name}],`).join("\n"); const prompt = ` 目前支持您修改的角色有: { ${roleNames} } 您好,很高兴见到您,您可以这样回答我: 修改 名称 为 xxx 的角色 的信息为: 新名称:xxx 描述:xxx 性别:男/女/保密 性格: 1,xxx 2,xxx 3,xxx 技能: 1,xxx 2,xxx 3,xxx 目标任务: 1,xxx 2,xxx 我不能做什么: 1,xxx 2,xxx 我会讲的语言: 1,汉语 2,英文 3,西班牙语等` const agentTips = await waitForTextInputTips(conversation, ctx, prompt); if (!agentTips) return; const role_type = is_admin ? 1 : 2; const variables = { bot_id: botUUID, user_id: userUUID, role_type: role_type, }; await asyncResponse(ctx, variables, agentTips, auth_token); // EdgeRuntime.waitUntil(asyncResponse(ctx, variables, agentTips, auth_token)) } async function deleterole(conversation: MyConversation, ctx: MyContext) { const auth_token = Deno.env.get('FASTGPT_API_KEY_ROLE') ?? ""; console.log("auth_token:", auth_token); const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const is_admin = userUUID === adminUUID; // fetchRoles const roles = await fetchRoles(is_admin ? "" : botUUID, userUUID); if (!roles) { await ctx.reply("Failed to retrieve roles, operation terminated"); return; } const roleNames = roles.map((role) => `[${role.name}],`).join("\n"); const prompt = ` 目前支持您删除的角色有: { ${roleNames } 您好,很高兴见到您,您可以这样回答我: 删除 名称为xxx 的角色` const agentTips = await waitForTextInputTips(conversation, ctx, prompt); if (!agentTips) return; const role_type = is_admin ? 1 : 2; const variables = { bot_id: botUUID, user_id: userUUID, role_type: role_type, }; await asyncResponse(ctx, variables, agentTips, auth_token); // EdgeRuntime.waitUntil(asyncResponse(ctx, variables, agentTips, auth_token)) } async function listroles(conversation: MyConversation, ctx: MyContext) { const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const is_admin = userUUID === adminUUID; // fetchRoles const roles = await fetchRoles(is_admin ? "" : botUUID, userUUID); if (!roles) { await ctx.reply("Failed to retrieve roles, operation terminated"); return; } if (roles.length === 0) { await ctx.reply("No roles found"); return; } await ctx.reply(`The roles you can operate are: ${roles.map((role) => `[${role.name}],`).join("\n")}`); } async function createknowleage(conversation: MyConversation, ctx: MyContext) { const res = await waitForTextInputTips(conversation, ctx, "Please input the knowledge name"); if (!res) return; const auth_token = Deno.env.get('FASTGPT_API_KEY_AGENT') ?? ""; console.log("auth_token:", auth_token); const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const isAdmin = userUUID === adminUUID; const { data: apiRes, error } = await respKnowledgeApi(res, auth_token); console.log("apiRes:", apiRes); if (error) { console.error(`Failed to insert data: ${error.message}`); } else { const insertKnowledgeRes = await insertData("kb_dataset", { name: res, owner_id: userUUID, bot_id: botUUID, ai_dataset_id: apiRes.data, knowledge_type: isAdmin ? 1 : 2 }); if (!insertKnowledgeRes) { await ctx.reply("Failed to insert knowledge data, operation terminated"); } await ctx.reply("Knowledge created successfully"); } } async function listknowledges(conversation: MyConversation, ctx: MyContext) { const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const isAdmin = userUUID === adminUUID; const res = await fetchKnowledge(isAdmin ? "" : botUUID, userUUID); if (!res) { await ctx.reply("Failed to retrieve knowledge information, operation terminated"); return; } if (res.length === 0) { await ctx.reply("No knowledge found"); return; } await ctx.reply(`The knowledge you can operate are: ${res.map((item) => `Source: ${item.name}`).join("\n")}`); } async function addknowlegecollection(conversation: MyConversation, ctx: MyContext) { const auth_token = Deno.env.get('FASTGPT_API_KEY_KNOWLEDGE') ?? ""; console.log("auth_token:", auth_token); const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const isAdmin = userUUID === adminUUID; const knowledgeResponse = await fetchKnowledge(isAdmin ? "" : botUUID, userUUID); if (!knowledgeResponse) { await ctx.reply("Failed to retrieve knowledge information, operation terminated"); return; } const knowledgeMap = new Map(knowledgeResponse.map((item) => [item.id, item.name])); const knowledgeDatsetMap = new Map(knowledgeResponse.map((item) => [item.id, item.ai_dataset_id])); const selectionRes = await waitForOptionSelection(conversation, ctx, "Please select a knowledge collection to add to", knowledgeMap, false); if (!selectionRes) return; const knowledgeId = selectionRes.id; const linkInput = await waitForTextInputTips(conversation, ctx, "Please input knowledge collection web link"); if (!linkInput) return; // check if the link is valid if (!isValidUrl(linkInput)) { await ctx.reply("Invalid link, operation terminated"); return; } const name = await waitForTextInputTips(conversation, ctx, "Please input knowledge collection name"); if (!name) return; // check name length than 30 if (name.length > 30) { await ctx.reply("The name length should be less than 30, operation terminated"); return; } const requestData = { name: name, link: linkInput, datasetId: knowledgeDatsetMap.get(knowledgeId) ?? "", trainingType: "chunk" } const { data: apiRes, error } = await respKnowledgeCollectionApi(requestData, auth_token); console.log("apiRes knowledge collection:", apiRes); if (error) { console.error(`Failed to insert data: ${error.message}`); } else { const insertKnowledgeRes = await insertData("kb_collection", { name: name, source_name: linkInput, data_source: linkInput, owner_id: userUUID, dataset_id: knowledgeId, collection_id: apiRes.data.collectionId }); if (!insertKnowledgeRes) { await ctx.reply("Failed to insert knowledge data, operation terminated"); } await ctx.reply("Knowledge collection added successfully"); } } async function listknowlegecollection(conversation: MyConversation, ctx: MyContext) { const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const knowledgeCollectionResponse = await fetchKnowledgeCollection(userUUID); if (!knowledgeCollectionResponse) { await ctx.reply("Failed to retrieve knowledge collection information, operation terminated"); return; } if (knowledgeCollectionResponse.length === 0) { await ctx.reply("No knowledge collection found"); return; } await ctx.reply(`The knowledge collection you can operate are: ${knowledgeCollectionResponse.map((item) => `Source: ${item.data_source}`).join("\n")}`); } async function deleteknowlegecollection(conversation: MyConversation, ctx: MyContext) { const auth_token = Deno.env.get('FASTGPT_API_KEY_KNOWLEDGE') ?? ""; console.log("auth_token:", auth_token); const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const knowledgeCollectionResponse = await fetchKnowledgeCollection(userUUID); if (!knowledgeCollectionResponse) { await ctx.reply("Failed to retrieve knowledge collection information, operation terminated"); return; } if (knowledgeCollectionResponse.length === 0) { await ctx.reply("No knowledge collection found"); return; } const knowledgeCollectionMap = new Map(knowledgeCollectionResponse.map((item) => [item.id, item.data_source])); const knowledgeCollectionIdMap = new Map(knowledgeCollectionResponse.map((item) => [item.id, item.collection_id])); const selectionRes = await waitForOptionSelection(conversation, ctx, "Please select a knowledge collection to delete", knowledgeCollectionMap, false); if (!selectionRes) return; const knowledgeCollectionId = selectionRes.id; console.log("knowledgeCollectionId:", knowledgeCollectionId); const collectionId = knowledgeCollectionIdMap.get(knowledgeCollectionId); const { success, error: databaseError } = await deleteKnowledgeCollection(knowledgeCollectionId); if (databaseError) { console.error(`Failed to delete knowledge collection: ${databaseError.message}`); return; } const { data: res, error } = await respKnowledgeCollectionDelApi({ id: collectionId }, auth_token); if (error) { console.error(`Failed to delete knowledge collection: ${error.message}`); return; } console.log("res:", res); if (res.code !== 200) { await ctx.reply("Failed to delete knowledge collection"); return; } await ctx.reply("Knowledge collection deleted successfully"); } async function bindchatagent(conversation: MyConversation, ctx: MyContext) { await ctx.reply("Proceeding with Agent list, please follow the steps."); const { id: botUUID } = await getBotInfo(ctx.me.id); const { id: userUUID } = await getUserInfo(ctx.from.id); // Step 0: 从ctx中获取bot_id,通过BotId获取 Agent 数据 const agent = await fetchAgentByBotId(botUUID, userUUID); if (!agent) { await ctx.reply("No corresponding Agent found, operation terminated"); return; } const agentMap = new Map(agent.map((item) => [item.id, item.name])); const selectedAgent = await waitForOptionSelection(conversation, ctx, "Please select an Agent to query:", agentMap, false); if (!selectedAgent) return; const agentId = selectedAgent.id; const { success: _success, error } = await bindChatAgent(agentId, ctx.message.chat.id); if (error) { console.error(`Bind chat agent is failed: ${error.message}`); } else { await ctx.reply("Agent bind chat is successful"); } } async function createaction(conversation: MyConversation, ctx: MyContext) { const auth_token = Deno.env.get('FASTGPT_API_KEY_ACTION') ?? ""; console.log("auth_token:", auth_token); const prompt = `您好,很高兴见到您,您可以这样回答我: 创建一个角色 名称:xxx 描述:xxx 性别:男/女/保密 性格: 1,xxx 2,xxx 3,xxx 技能: 1,xxx 2,xxx 3,xxx 目标任务: 1,xxx 2,xxx 我不能做什么: 1,xxx 2,xxx 我会讲的语言: 1,汉语 2,英文 3,西班牙语等` const actionTips = await waitForTextInputTips(conversation, ctx, prompt); if (!actionTips) return; const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } const { id: botUUID } = botInfo; const userInfo = await getUserInfo(ctx.from.id); if (!userInfo) { await ctx.reply("Failed to retrieve user information, operation terminated"); return; } const { id: userUUID } = userInfo; const isAdmin = userUUID === adminUUID; const role_type = isAdmin ? 1 : 2; const variables = { bot_id: botUUID, user_id: userUUID, role_type: role_type }; const { data: res, error } = await respMsgAgent(variables, actionTips, auth_token); if (error) { console.error(`Failed to insert data: ${error.message}`); } else { if (res && res.choices && res.choices[0] && res.choices[0].message) { await ctx.reply(res.choices[0].message.content); } else { await ctx.reply("Failed to retrieve response message content."); } } } async function answerQuestion(ctx: MyContext) { const auth_token = Deno.env.get('FASTGPT_API_KEY_ACTION') ?? ""; console.log("auth_token:", auth_token); // getBotInfo const botInfo = await getBotInfo(ctx.me.id); if (!botInfo) { await ctx.reply("Failed to retrieve bot information, operation terminated"); return; } // query data in the agent_action throough bot_id match trigger_object const { id: botUUID } = botInfo; const botActionInfo = await getBotAcionInfo(botUUID); if (!botActionInfo) { await ctx.reply("Failed to retrieve bot action information, operation terminated"); return; } const question = ctx.message.text; // chat id // const tg_chat_id = ctx.message.chat.id; // const datasetJson = await getAgentBindKnowledge(tg_chat_id); // console.log("datasetJson:", datasetJson); // if (!datasetJson) { // await ctx.reply("Failed to retrieve dataset information, operation terminated"); // return; // } const datasetJson = { action_id: botActionInfo.id }; console.log("datasetJson:", datasetJson); const { data: ResData, error } = await respMsgQuestion(datasetJson, question, auth_token) if (error) { console.error(`Failed to fetch response: ${error.message}`); return; } const answer = ResData.choices[0].message.content; console.log("answer:", answer); // await ctx.reply(answer); } // isValidUrl function isValidUrl(url: string) { try { new URL(url); return true; } catch (error) { console.log("Invalid URL:", error); return false; } } export { createagent, updateagent, deleteagent, createrole, updaterole, listroles, deleterole, listagents, bindchatagent, answerQuestion, createknowleage, listknowledges, addknowlegecollection, listknowlegecollection, deleteknowlegecollection, createaction };