diff --git a/agent/src/index.ts b/agent/src/index.ts index 6e7ca7486b0..1d8f1c0817f 100644 --- a/agent/src/index.ts +++ b/agent/src/index.ts @@ -32,7 +32,7 @@ import readline from "readline"; import yargs from "yargs"; import path from "path"; import { fileURLToPath } from "url"; -import blobert from "./blobert.ts"; +import { character } from "./character.ts"; import type { DirectClient } from "@ai16z/client-direct"; const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file @@ -263,6 +263,13 @@ export function createAgent( }); } +function intializeFsCache(baseDir: string, character: Character) { + const cacheDir = path.resolve(baseDir, character.id, "cache"); + + const cache = new CacheManager(new FsCacheAdapter(cacheDir)); + return cache; +} + function intializeDbCache(character: Character, db: IDatabaseCacheAdapter) { const cache = new CacheManager(new DbCacheAdapter(db, character.id)); return cache; @@ -310,7 +317,7 @@ const startAgents = async () => { let charactersArg = args.characters || args.character; - let characters = [blobert]; + let characters = [character]; if (charactersArg) { characters = await loadCharacters(charactersArg); diff --git a/packages/adapter-postgres/src/index.ts b/packages/adapter-postgres/src/index.ts index 23a4b426ae9..701b8eafdc0 100644 --- a/packages/adapter-postgres/src/index.ts +++ b/packages/adapter-postgres/src/index.ts @@ -736,7 +736,9 @@ export class PostgresDatabaseAdapter ); if (existingParticipant.rows.length > 0) { - console.log(`Participant with userId ${userId} already exists in room ${roomId}.`); + console.log( + `Participant with userId ${userId} already exists in room ${roomId}.` + ); return; // Exit early if the participant already exists } @@ -750,11 +752,13 @@ export class PostgresDatabaseAdapter } catch (error) { // This is to prevent duplicate participant error in case of a race condition // Handle unique constraint violation error (code 23505) - if (error.code === '23505') { - console.warn(`Participant with userId ${userId} already exists in room ${roomId}.`); // Optionally, you can log this or handle it differently + if (error.code === "23505") { + console.warn( + `Participant with userId ${userId} already exists in room ${roomId}.` + ); // Optionally, you can log this or handle it differently } else { // Handle other errors - console.error('Error adding participant:', error); + console.error("Error adding participant:", error); return false; } } finally { diff --git a/packages/client-telegram/src/index.ts b/packages/client-telegram/src/index.ts index 3e3be51e0c5..8689a6ebe8f 100644 --- a/packages/client-telegram/src/index.ts +++ b/packages/client-telegram/src/index.ts @@ -20,7 +20,7 @@ export const TelegramClientInterface: Client = { return tg; }, stop: async (_runtime: IAgentRuntime) => { - console.warn("Telegram client does not support stopping yet"); + elizaLogger.warn("Telegram client does not support stopping yet"); }, }; diff --git a/packages/client-telegram/src/messageManager.ts b/packages/client-telegram/src/messageManager.ts index 3b3f53d3bf8..8c7fe49c63f 100644 --- a/packages/client-telegram/src/messageManager.ts +++ b/packages/client-telegram/src/messageManager.ts @@ -1,7 +1,7 @@ import { Message } from "@telegraf/types"; import { Context, Telegraf } from "telegraf"; -import { composeContext } from "@ai16z/eliza"; +import { composeContext, elizaLogger, ServiceType } from "@ai16z/eliza"; import { embeddingZeroVector } from "@ai16z/eliza"; import { Content, @@ -17,7 +17,6 @@ import { stringToUuid } from "@ai16z/eliza"; import { generateMessageResponse, generateShouldRespond } from "@ai16z/eliza"; import { messageCompletionFooter, shouldRespondFooter } from "@ai16z/eliza"; -import { ImageDescriptionService } from "@ai16z/plugin-node"; const MAX_MESSAGE_LENGTH = 4096; // Telegram's max message length @@ -137,57 +136,49 @@ Thread of Tweets You Are Replying To: export class MessageManager { public bot: Telegraf; private runtime: IAgentRuntime; - private imageService: IImageDescriptionService; constructor(bot: Telegraf, runtime: IAgentRuntime) { this.bot = bot; this.runtime = runtime; - this.imageService = ImageDescriptionService.getInstance(); } // Process image messages and generate descriptions private async processImage( message: Message ): Promise<{ description: string } | null> { - // console.log( - // "🖼️ Processing image message:", - // JSON.stringify(message, null, 2) - // ); - try { let imageUrl: string | null = null; - // Handle photo messages if ("photo" in message && message.photo?.length > 0) { const photo = message.photo[message.photo.length - 1]; const fileLink = await this.bot.telegram.getFileLink( photo.file_id ); imageUrl = fileLink.toString(); - } - // Handle image documents - else if ( + } else if ( "document" in message && message.document?.mime_type?.startsWith("image/") ) { - const doc = message.document; const fileLink = await this.bot.telegram.getFileLink( - doc.file_id + message.document.file_id ); imageUrl = fileLink.toString(); } if (imageUrl) { + const imageDescriptionService = + this.runtime.getService( + ServiceType.IMAGE_DESCRIPTION + ); const { title, description } = - await this.imageService.describeImage(imageUrl); - const fullDescription = `[Image: ${title}\n${description}]`; - return { description: fullDescription }; + await imageDescriptionService.describeImage(imageUrl); + return { description: `[Image: ${title}\n${description}]` }; } } catch (error) { console.error("❌ Error processing image:", error); } - return null; // No image found + return null; } // Decide if the bot should respond to the message @@ -196,7 +187,6 @@ export class MessageManager { state: State ): Promise { // Respond if bot is mentioned - if ( "text" in message && message.text?.includes(`@${this.bot.botInfo?.username}`) @@ -209,7 +199,7 @@ export class MessageManager { return true; } - // Respond to images in group chats + // Don't respond to images in group chats if ( "photo" in message || ("document" in message && @@ -238,7 +228,7 @@ export class MessageManager { return response === "RESPOND"; } - return false; // No criteria met + return false; } // Send long messages in chunks @@ -291,7 +281,7 @@ export class MessageManager { // Generate a response using AI private async _generateResponse( message: Memory, - state: State, + _state: State, context: string ): Promise { const { userId, roomId } = message; @@ -306,9 +296,10 @@ export class MessageManager { console.error("❌ No response from generateMessageResponse"); return null; } + await this.runtime.databaseAdapter.log({ body: { message, context, response }, - userId: userId, + userId, roomId, type: "response", }); @@ -342,14 +333,23 @@ export class MessageManager { try { // Convert IDs to UUIDs const userId = stringToUuid(ctx.from.id.toString()) as UUID; + + // Get user name const userName = ctx.from.username || ctx.from.first_name || "Unknown User"; + + // Get chat ID const chatId = stringToUuid( ctx.chat?.id.toString() + "-" + this.runtime.agentId ) as UUID; + + // Get agent ID const agentId = this.runtime.agentId; + + // Get room ID const roomId = chatId; + // Ensure connection await this.runtime.ensureConnection( userId, roomId, @@ -358,6 +358,7 @@ export class MessageManager { "telegram" ); + // Get message ID const messageId = stringToUuid( message.message_id.toString() + "-" + this.runtime.agentId ) as UUID; @@ -382,17 +383,18 @@ export class MessageManager { return; // Skip if no content } + // Create content const content: Content = { text: fullText, source: "telegram", - // inReplyTo: - // "reply_to_message" in message && message.reply_to_message - // ? stringToUuid( - // message.reply_to_message.message_id.toString() + - // "-" + - // this.runtime.agentId - // ) - // : undefined, + inReplyTo: + "reply_to_message" in message && message.reply_to_message + ? stringToUuid( + message.reply_to_message.message_id.toString() + + "-" + + this.runtime.agentId + ) + : undefined, }; // Create memory for the message @@ -406,6 +408,7 @@ export class MessageManager { embedding: embeddingZeroVector, }; + // Create memory await this.runtime.messageManager.createMemory(memory); // Update state with the new memory @@ -498,8 +501,8 @@ export class MessageManager { await this.runtime.evaluate(memory, state, shouldRespond); } catch (error) { - console.error("❌ Error handling message:", error); - console.error("Error sending message:", error); + elizaLogger.error("❌ Error handling message:", error); + elizaLogger.error("Error sending message:", error); } } } diff --git a/packages/client-telegram/src/telegramClient.ts b/packages/client-telegram/src/telegramClient.ts index dd769c25f10..25028a4e328 100644 --- a/packages/client-telegram/src/telegramClient.ts +++ b/packages/client-telegram/src/telegramClient.ts @@ -1,8 +1,6 @@ import { Context, Telegraf } from "telegraf"; - -import { IAgentRuntime } from "@ai16z/eliza"; +import { IAgentRuntime, elizaLogger } from "@ai16z/eliza"; import { MessageManager } from "./messageManager.ts"; -import { elizaLogger } from "@ai16z/eliza"; export class TelegramClient { private bot: Telegraf; @@ -14,94 +12,88 @@ export class TelegramClient { this.runtime = runtime; this.bot = new Telegraf(botToken); this.messageManager = new MessageManager(this.bot, this.runtime); - elizaLogger.log("✅ TelegramClient constructor completed"); } public async start(): Promise { elizaLogger.log("🚀 Starting Telegram bot..."); try { - this.bot.launch({ - dropPendingUpdates: true, - }); - elizaLogger.log( - "✨ Telegram bot successfully launched and is running!" - ); + await this.initializeBot(); + this.setupMessageHandlers(); + this.setupShutdownHandlers(); + } catch (error) { + elizaLogger.error("❌ Failed to launch Telegram bot:", error); + throw error; + } + } - await this.bot.telegram.getMe().then((botInfo) => { - this.bot.botInfo = botInfo; - }); + private async initializeBot(): Promise { + this.bot.launch({ dropPendingUpdates: true }); + elizaLogger.log( + "✨ Telegram bot successfully launched and is running!" + ); - elizaLogger.success(`Bot username: @${this.bot.botInfo?.username}`); + const botInfo = await this.bot.telegram.getMe(); + this.bot.botInfo = botInfo; + elizaLogger.success(`Bot username: @${botInfo.username}`); - this.messageManager.bot = this.bot; + this.messageManager.bot = this.bot; + } - // Include if you want to view message maanger bot info - // console.log(`Message Manager bot info: @${this.messageManager.bot}`); + private setupMessageHandlers(): void { + elizaLogger.log("Setting up message handler..."); - elizaLogger.log("Setting up message handler..."); + this.bot.on("message", async (ctx) => { + try { + await this.messageManager.handleMessage(ctx); + } catch (error) { + elizaLogger.error("❌ Error handling message:", error); + await ctx.reply( + "An error occurred while processing your message." + ); + } + }); - this.bot.on("message", async (ctx) => { - try { - // console.log("📥 Received message:", ctx.message); - await this.messageManager.handleMessage(ctx); - } catch (error) { - elizaLogger.error("❌ Error handling message:", error); - await ctx.reply( - "An error occurred while processing your message." - ); - } - }); + this.bot.on("photo", (ctx) => { + elizaLogger.log( + "📸 Received photo message with caption:", + ctx.message.caption + ); + }); - // Handle specific message types for better logging - this.bot.on("photo", (ctx) => { - elizaLogger.log( - "📸 Received photo message with caption:", - ctx.message.caption - ); - }); + this.bot.on("document", (ctx) => { + elizaLogger.log( + "📎 Received document message:", + ctx.message.document.file_name + ); + }); - this.bot.on("document", (ctx) => { - elizaLogger.log( - "📎 Received document message:", - ctx.message.document.file_name - ); - }); + this.bot.catch((err, ctx) => { + elizaLogger.error(`❌ Telegram Error for ${ctx.updateType}:`, err); + ctx.reply("An unexpected error occurred. Please try again later."); + }); + } - this.bot.catch((err, ctx) => { + private setupShutdownHandlers(): void { + const shutdownHandler = async (signal: string) => { + elizaLogger.log( + `⚠️ Received ${signal}. Shutting down Telegram bot gracefully...` + ); + try { + await this.stop(); + elizaLogger.log("🛑 Telegram bot stopped gracefully"); + } catch (error) { elizaLogger.error( - `❌ Telegram Error for ${ctx.updateType}:`, - err - ); - ctx.reply( - "An unexpected error occurred. Please try again later." + "❌ Error during Telegram bot shutdown:", + error ); - }); + throw error; + } + }; - // Graceful shutdown handlers - const shutdownHandler = async (signal: string) => { - elizaLogger.log( - `⚠️ Received ${signal}. Shutting down Telegram bot gracefully...` - ); - try { - await this.stop(); - elizaLogger.log("🛑 Telegram bot stopped gracefully"); - } catch (error) { - elizaLogger.error( - "❌ Error during Telegram bot shutdown:", - error - ); - throw error; - } - }; - - process.once("SIGINT", () => shutdownHandler("SIGINT")); - process.once("SIGTERM", () => shutdownHandler("SIGTERM")); - process.once("SIGHUP", () => shutdownHandler("SIGHUP")); - } catch (error) { - elizaLogger.error("❌ Failed to launch Telegram bot:", error); - throw error; - } + process.once("SIGINT", () => shutdownHandler("SIGINT")); + process.once("SIGTERM", () => shutdownHandler("SIGTERM")); + process.once("SIGHUP", () => shutdownHandler("SIGHUP")); } public async stop(): Promise { diff --git a/packages/plugin-node/src/services/llama.ts b/packages/plugin-node/src/services/llama.ts index 0a08b3754f0..2b542c6d464 100644 --- a/packages/plugin-node/src/services/llama.ts +++ b/packages/plugin-node/src/services/llama.ts @@ -189,22 +189,21 @@ export class LlamaService extends Service { } async initialize(runtime: IAgentRuntime): Promise { - elizaLogger.info("Initializing LlamaService..."); try { - // Check if we should use Ollama - if (runtime.modelProvider === ModelProviderName.OLLAMA) { - elizaLogger.info("Using Ollama provider"); - this.modelInitialized = true; + if (runtime.modelProvider === ModelProviderName.LLAMALOCAL) { + elizaLogger.info("Initializing LlamaService..."); + elizaLogger.info("Using local GGUF model"); + elizaLogger.info("Ensuring model is initialized..."); + await this.ensureInitialized(); + elizaLogger.success("LlamaService initialized successfully"); + } else { + elizaLogger.info( + "Not using local model, skipping initialization" + ); return; } - - elizaLogger.info("Using local GGUF model"); - elizaLogger.info("Ensuring model is initialized..."); - await this.ensureInitialized(); - elizaLogger.success("LlamaService initialized successfully"); } catch (error) { elizaLogger.error("Failed to initialize LlamaService:", error); - // Re-throw with more context throw new Error( `LlamaService initialization failed: ${error.message}` );