diff --git a/src/bot/telegram-bot.ts b/src/bot/telegram-bot.ts index fab39cb..f4ef712 100644 --- a/src/bot/telegram-bot.ts +++ b/src/bot/telegram-bot.ts @@ -41,7 +41,7 @@ export class TelegramBot { const message = status === 'started' ? `${stepName} ${emoji}` - : `${stepName} ${emoji}\n\n
${result?.substring(0, 3000) || 'Готово'}
`; + : `${stepName} ${emoji}\n\n
${result?.substring(0, 3000) || 'Done'}
`; await this.sendMessage(chatId, message); }; @@ -50,7 +50,7 @@ export class TelegramBot { private setupHandlers(): void { this.bot.start((ctx) => { ctx.reply( - 'Привет! Я бот для работы с AI пайплайнами. Просто отправь мне сообщение, и я обработаю его через пайплайн.', + 'Hello! I am a bot for working with AI pipelines. Just send me a message and I will process it through the pipeline.', ); }); @@ -61,50 +61,49 @@ export class TelegramBot { try { const userPipeline: Pipeline = { - description: 'Криптокошелёк анализатор для Liquidswap', - systemPrompt: `Вы — профессиональный криптоаналитик и портфельный менеджер. -Анализируйте криптовалютный рынок, используя актуальные веб-данные. -Проведите анализ портфеля пользователя, адаптируясь к широкому (рыночные тренды, новости) или ограниченному (только портфель) набору данных. -Если данные портфеля отсутствуют, запросите их. Охватите по возможности: -- Технический анализ (тренды, волатильность, индикаторы). -- Фундаментальный анализ (новости, проекты). -- Риски (корреляции, ликвидность, регуляторные факторы). -- Диверсификацию и оптимизацию. -Предоставьте рекомендации по улучшению портфеля. -Формат ответа: отчет с разделами "Текущая ситуация на рынке", "Анализ портфеля", "Риски", "Рекомендации". -Тон профессиональный, без сложного жаргона. -Если данных недостаточно, задайте уточняющие вопросы. -Обеспечьте точность ≥ 95%, избегая неподтвержденных предположений.`, + description: 'Crypto wallet analyzer for Liquidswap', + systemPrompt: `You are a professional crypto analyst and portfolio manager. +Analyze the cryptocurrency market using up-to-date web data. +Conduct a portfolio analysis, adapting to either a broad (market trends, news) or limited (portfolio only) dataset. +If portfolio data is missing, request it. Cover the following aspects if possible: +- Technical analysis (trends, volatility, indicators). +- Fundamental analysis (news, projects). +- Risks (correlations, liquidity, regulatory factors). +- Diversification and optimization. +Provide recommendations for portfolio improvement. +Response format: a report with sections "Current Market Situation", "Portfolio Analysis", "Risks", "Recommendations". +Maintain a professional tone without complex jargon. +If data is insufficient, ask clarifying questions. +Ensure accuracy ≥ 95%, avoiding unsubstantiated assumptions.`, steps: [ { - name: 'Обработка запроса', + name: 'Request Processing', prompt: userMessage, }, { - name: 'Анализ', - prompt: `Я хочу грамотно распределить свой криптовалютный портфель, используя данные DeFi-протокола Liquidswap. - Пожалуйста, предоставьте рекомендации по распределению активов, - основываясь на данных от инструментов: + name: 'Analysis', + prompt: `I want to properly allocate my cryptocurrency portfolio using data from the Liquidswap DeFi protocol. + Please provide asset allocation recommendations based on data from the following tools: \`get_tokens\`, \`get_pools\`, - \`get_pools_historical_aprs\` (за 5 дней), - \`get_pools_historical_tvls\` (за 5 дней), - \`get_balances_by_address\` (мой адрес Aptos, если потребуется, запросите его) и \`multi_tool_use.parallel\`. - Затем напиши доступную информацию об указанном адресе.`, + \`get_pools_historical_aprs\` (last 5 days), + \`get_pools_historical_tvls\` (last 5 days), + \`get_balances_by_address\` (my Aptos address, request it if needed) and \`multi_tool_use.parallel\`. + Then provide the available information about the specified address.`, }, { - name: 'Форматирование ответа', - prompt: `Отлично, теперь используя эмодзи давай сделаем из этих данных telegram пост. - Сначала кратко напиши простыми словами что следовало бы сделать пользователю, - затем напиши подробную детальную информацию. - В конце поста должен быть текст: "${process.env.PROMO_TEXT}"`, + name: 'Response Formatting', + prompt: `Great, now let's create a Telegram post from this data using emojis. + First, briefly explain in simple terms what the user should do, + then provide detailed information. + The post should end with the text: "${process.env.PROMO_TEXT}"`, }, ], }; this.activePipelines.set(chatId, { pipeline: userPipeline, chatId }); await ctx.sendChatAction('typing'); - await ctx.reply('🚀 Запускаю анализ...'); + await ctx.reply('🚀 Starting analysis...'); const results = await this.pipelineExecutor.executeChain({ pipeline: userPipeline, @@ -131,13 +130,11 @@ export class TelegramBot { console.log(`Sending response to chat ${chatId}:`, trimmedResult); await ctx.replyWithHTML(trimmedResult); } else { - await ctx.reply( - 'Не удалось обработать запрос. Пожалуйста, попробуйте еще раз.', - ); + await ctx.reply('Failed to process the request. Please try again.'); } } catch (error) { console.error('Error processing message:', error); - await ctx.reply('Произошла ошибка при обработке вашего запроса.'); + await ctx.reply('An error occurred while processing your request.'); } }); diff --git a/src/main.ts b/src/main.ts index f155528..324a7f8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,33 +9,27 @@ async function main() { const mcpServerUrl = process.env.MCP_SERVER_URL; if (!telegramToken) { - console.error( - 'Ошибка: Переменная окружения TELEGRAM_BOT_TOKEN не установлена.', - ); + console.error('Error: TELEGRAM_BOT_TOKEN environment variable is not set.'); process.exit(1); } if (!openAIApiKey) { - console.error( - 'Ошибка: Переменная окружения OPENAI_API_KEY не установлена.', - ); + console.error('Error: OPENAI_API_KEY environment variable is not set.'); process.exit(1); } if (!mcpServerUrl) { - console.error( - 'Ошибка: Переменная окружения MCP_SERVER_URL не установлена.', - ); + console.error('Error: MCP_SERVER_URL environment variable is not set.'); process.exit(1); } const bot = new TelegramBot(telegramToken, mcpServerUrl); bot.launch(); - console.log('Бот запущен и готов к работе!'); + console.log('Bot is up and running!'); } main().catch((error) => { - console.error('Произошла ошибка:', error); + console.error('An error occurred:', error); process.exit(1); }); diff --git a/src/pipelines/pipeline-executor.ts b/src/pipelines/pipeline-executor.ts index 2bcab64..a8ad762 100644 --- a/src/pipelines/pipeline-executor.ts +++ b/src/pipelines/pipeline-executor.ts @@ -98,7 +98,7 @@ export class PipelineExecutor { for (let i = 0; i < totalSteps; i++) { const { name, prompt } = steps[i]!; - const stepName = name || 'Без названия'; + const stepName = name || 'Untitled'; const isLastStep = i === totalSteps - 1; try { @@ -120,7 +120,7 @@ export class PipelineExecutor { } } catch (error) { console.error(`Error in step "${stepName}":`, error); - const errorMessage = `❌ Ошибка на шаге "${stepName}": ${error instanceof Error ? error.message : String(error)}`; + const errorMessage = `❌ Error in step "${stepName}": ${error instanceof Error ? error.message : String(error)}`; if (options.onStepComplete) { await options.onStepComplete(stepName, errorMessage, isLastStep); } diff --git a/src/services/mcp-tools.service.ts b/src/services/mcp-tools.service.ts index f8cb8ea..c058f19 100644 --- a/src/services/mcp-tools.service.ts +++ b/src/services/mcp-tools.service.ts @@ -24,10 +24,10 @@ export class McpToolsService { version: '1.0.0', }); await this.mcpClient.connect(this.transport); - console.log(`[MCP Service] Подключено к MCP серверу: ${this.serverUrl}`); + console.log(`[MCP Service] Connected to MCP server: ${this.serverUrl}`); } catch (error) { console.error( - `[MCP Service] Ошибка подключения к MCP серверу ${this.serverUrl}:`, + `[MCP Service] Error connecting to MCP server ${this.serverUrl}:`, error, ); throw error; @@ -39,13 +39,15 @@ export class McpToolsService { await this.mcpClient.close(); this.mcpClient = null; this.transport = null; - console.log(`[MCP Service] Отключено от MCP сервера: ${this.serverUrl}`); + console.log( + `[MCP Service] Disconnected from MCP server: ${this.serverUrl}`, + ); } } async getLangchainTools(): Promise { if (!this.mcpClient) { - throw new Error('MCP клиент не подключен. Сначала вызовите .connect()'); + throw new Error('MCP client is not connected. Call .connect() first'); } const mcpTools: McpTool[] = (await this.mcpClient.listTools()).tools; @@ -89,7 +91,7 @@ export class McpToolsService { schema: zodSchema, func: async (args: Record) => { console.log( - `[MCP Tool Call] Вызов инструмента MCP: ${mcpTool.name} с аргументами:`, + `[MCP Tool Call] Calling MCP tool: ${mcpTool.name} with arguments:`, args, ); const result = await this.mcpClient!.callTool({ @@ -103,7 +105,7 @@ export class McpToolsService { .map((c) => (c as TextContent).text || '') .join('\n'); throw new Error( - `Ошибка выполнения инструмента ${mcpTool.name}: ${errorContent}`, + `Error executing tool ${mcpTool.name}: ${errorContent}`, ); } @@ -114,9 +116,9 @@ export class McpToolsService { return (result.content as any[]) .map((c) => { if (c.type === 'text') return (c as TextContent).text; - if (c.type === 'image') return `[Изображение: ${c.mimeType}]`; - if (c.type === 'audio') return `[Аудио: ${c.mimeType}]`; - if (c.type === 'resource') return `[Ресурс: ${c.uri}]`; + if (c.type === 'image') return `[Image: ${c.mimeType}]`; + if (c.type === 'audio') return `[Audio: ${c.mimeType}]`; + if (c.type === 'resource') return `[Resource: ${c.uri}]`; return JSON.stringify(c); }) .join('\n');