From 560732e52b134da8b705c939abe6a07f31d5c30b Mon Sep 17 00:00:00 2001 From: snakeying <65364563+snakeying@users.noreply.github.com> Date: Thu, 10 Oct 2024 04:41:17 +0800 Subject: [PATCH] Add files via upload --- dist/README.md | 2 +- dist/index.js | 67 +++++++++++++++++++++++++++++++++++--- dist/index.js.map | 6 ++-- src/api/azure.ts | 74 ++++++++++++++++++++++++++++++++++++++++++ src/api/telegram.ts | 3 ++ src/config/commands.ts | 5 +-- src/env.ts | 11 +++++-- 7 files changed, 155 insertions(+), 13 deletions(-) create mode 100644 src/api/azure.ts diff --git a/dist/README.md b/dist/README.md index 83d12c8..3a60015 100644 --- a/dist/README.md +++ b/dist/README.md @@ -1 +1 @@ -This folder contains the built output assets for the worker "gpt-telegram-worker" generated at 2024-10-09T17:40:34.953Z. \ No newline at end of file +This folder contains the built output assets for the worker "gpt-telegram-worker" generated at 2024-10-09T20:27:42.863Z. \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 925d06a..6340d38 100644 --- a/dist/index.js +++ b/dist/index.js @@ -7,8 +7,9 @@ var getConfig = (env) => { const hasGoogle = !!env.GOOGLE_MODEL_KEY; const hasGroq = !!env.GROQ_API_KEY; const hasClaude = !!env.CLAUDE_API_KEY; - if (!hasOpenAI && !hasGoogle && !hasGroq && !hasClaude) { - throw new Error("At least one model API key must be set (OpenAI, Google, Groq, or Claude)"); + const hasAzure = !!env.AZURE_API_KEY; + if (!hasOpenAI && !hasGoogle && !hasGroq && !hasClaude && !hasAzure) { + throw new Error("At least one model API key must be set (OpenAI, Google, Groq, Claude, or Azure)"); } return { openaiApiKey: env.OPENAI_API_KEY, @@ -38,7 +39,10 @@ var getConfig = (env) => { groqModels: env.GROQ_MODELS ? env.GROQ_MODELS.split(",").map((model) => model.trim()) : [], claudeApiKey: env.CLAUDE_API_KEY, claudeModels: env.CLAUDE_MODELS ? env.CLAUDE_MODELS.split(",").map((model) => model.trim()) : [], - claudeEndpoint: getEnvOrDefault(env, "CLAUDE_ENDPOINT", "https://api.anthropic.com/v1") + claudeEndpoint: getEnvOrDefault(env, "CLAUDE_ENDPOINT", "https://api.anthropic.com/v1"), + azureApiKey: env.AZURE_API_KEY, + azureModels: env.AZURE_MODELS ? env.AZURE_MODELS.split(",").map((model) => model.trim()) : [], + azureEndpoint: env.AZURE_ENDPOINT }; }; @@ -482,8 +486,9 @@ var commands = [ ...config.openaiModels, ...config.googleModels, ...config.groqModels, - ...config.claudeModels - // 添加 Claude 模型 + ...config.claudeModels, + ...config.azureModels + // 新增 Azure 模型 ]; const keyboard = { inline_keyboard: availableModels.map((model) => [{ text: model, callback_data: `model_${model}` }]) @@ -846,6 +851,56 @@ ${errorText}`); }; var claude_default = ClaudeAPI; +// src/api/azure.ts +var AzureAPI = class { + apiKey; + baseUrl; + models; + defaultModel; + constructor(env) { + const config = getConfig(env); + this.apiKey = config.azureApiKey; + this.baseUrl = config.azureEndpoint; + this.models = config.azureModels; + this.defaultModel = this.models[0]; + } + async generateResponse(messages, model) { + const useModel = model || this.defaultModel; + const url = `${this.baseUrl}/openai/deployments/${useModel}/chat/completions?api-version=2024-02-01`; + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + "api-key": this.apiKey + }, + body: JSON.stringify({ + messages + }) + }); + if (!response.ok) { + const errorText = await response.text(); + console.error(`Azure API error: ${response.statusText}`, errorText); + throw new Error(`Azure API error: ${response.statusText} +${errorText}`); + } + const data = await response.json(); + if (!data.choices || data.choices.length === 0) { + throw new Error("Azure API \u672A\u751F\u6210\u4EFB\u4F55\u54CD\u5E94"); + } + return data.choices[0].message.content.trim(); + } + isValidModel(model) { + return this.models.includes(model); + } + getDefaultModel() { + return this.defaultModel; + } + getAvailableModels() { + return this.models; + } +}; +var azure_default = AzureAPI; + // src/api/telegram.ts var TelegramBot = class { token; @@ -879,6 +934,8 @@ var TelegramBot = class { return new groq_default(this.env); } else if (config.claudeModels.includes(currentModel)) { return new claude_default(this.env); + } else if (config.azureModels.includes(currentModel)) { + return new azure_default(this.env); } console.warn(`Unknown model: ${currentModel}. Falling back to OpenAI API.`); return new openai_api_default(this.env); diff --git a/dist/index.js.map b/dist/index.js.map index b8503b7..734d9f8 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1,8 +1,8 @@ { "version": 3, - "sources": ["../src/env.ts", "../src/api/openai_api.ts", "../src/utils/helpers.ts", "../src/utils/i18n.ts", "../src/api/image_generation.ts", "../src/api/flux-cf.ts", "../src/config/commands.ts", "../src/utils/redis.ts", "../src/api/gemini.ts", "../src/api/groq.ts", "../src/api/claude.ts", "../src/api/telegram.ts", "../src/index.ts"], + "sources": ["../src/env.ts", "../src/api/openai_api.ts", "../src/utils/helpers.ts", "../src/utils/i18n.ts", "../src/api/image_generation.ts", "../src/api/flux-cf.ts", "../src/config/commands.ts", "../src/utils/redis.ts", "../src/api/gemini.ts", "../src/api/groq.ts", "../src/api/claude.ts", "../src/api/azure.ts", "../src/api/telegram.ts", "../src/index.ts"], "sourceRoot": "dist", - "sourcesContent": ["export interface Env {\r\n OPENAI_API_KEY: string;\r\n OPENAI_BASE_URL: string;\r\n OPENAI_MODELS: string; // Comma-separated list of available OpenAI models\r\n TELEGRAM_BOT_TOKEN: string;\r\n WHITELISTED_USERS: string; // Comma-separated list of allowed Telegram user IDs\r\n SYSTEM_INIT_MESSAGE: string;\r\n SYSTEM_INIT_MESSAGE_ROLE: string;\r\n DEFAULT_MODEL?: string; // Optional default model\r\n UPSTASH_REDIS_REST_URL: string;\r\n UPSTASH_REDIS_REST_TOKEN: string;\r\n DALL_E_MODEL?: string;\r\n CLOUDFLARE_API_TOKEN: string;\r\n CLOUDFLARE_ACCOUNT_ID: string;\r\n FLUX_STEPS: string;\r\n PROMPT_OPTIMIZATION?: string;\r\n EXTERNAL_API_BASE?: string;\r\n EXTERNAL_MODEL?: string;\r\n EXTERNAL_API_KEY?: string;\r\n GOOGLE_MODEL_KEY: string;\r\n GOOGLE_MODEL_BASEURL?: string;\r\n GOOGLE_MODELS: string;\r\n GROQ_API_KEY: string;\r\n GROQ_MODELS: string;\r\n CLAUDE_API_KEY: string;\r\n CLAUDE_MODELS: string;\r\n CLAUDE_ENDPOINT?: string;\r\n}\r\n\r\nconst getEnvOrDefault = (env: Env, key: keyof Env, defaultValue: string): string => {\r\n return (env[key] as string) || defaultValue;\r\n};\r\n\r\nexport const getConfig = (env: Env) => {\r\n // \u68C0\u67E5\u662F\u5426\u81F3\u5C11\u6709\u4E00\u4E2A\u6A21\u578B\u7684 API \u5BC6\u94A5\u88AB\u8BBE\u7F6E\r\n const hasOpenAI = !!env.OPENAI_API_KEY;\r\n const hasGoogle = !!env.GOOGLE_MODEL_KEY;\r\n const hasGroq = !!env.GROQ_API_KEY;\r\n const hasClaude = !!env.CLAUDE_API_KEY;\r\n\r\n if (!hasOpenAI && !hasGoogle && !hasGroq && !hasClaude) {\r\n throw new Error('At least one model API key must be set (OpenAI, Google, Groq, or Claude)');\r\n }\r\n\r\n return {\r\n openaiApiKey: env.OPENAI_API_KEY,\r\n openaiBaseUrl: getEnvOrDefault(env, 'OPENAI_BASE_URL', 'https://api.openai.com/v1'),\r\n openaiModels: env.OPENAI_MODELS ? env.OPENAI_MODELS.split(',').map(model => model.trim()) : [],\r\n telegramBotToken: env.TELEGRAM_BOT_TOKEN,\r\n whitelistedUsers: env.WHITELISTED_USERS ? env.WHITELISTED_USERS.split(',').map(id => id.trim()) : [],\r\n systemInitMessage: getEnvOrDefault(env, 'SYSTEM_INIT_MESSAGE', 'You are a helpful assistant.'),\r\n systemInitMessageRole: getEnvOrDefault(env, 'SYSTEM_INIT_MESSAGE_ROLE', 'system'),\r\n defaultModel: env.DEFAULT_MODEL,\r\n upstashRedisRestUrl: env.UPSTASH_REDIS_REST_URL,\r\n upstashRedisRestToken: env.UPSTASH_REDIS_REST_TOKEN,\r\n dallEModel: getEnvOrDefault(env, 'DALL_E_MODEL', 'dall-e-3'),\r\n languageTTL: 60 * 60 * 24 * 365,\r\n contextTTL: 60 * 60 * 24 * 30,\r\n cloudflareApiToken: env.CLOUDFLARE_API_TOKEN,\r\n cloudflareAccountId: env.CLOUDFLARE_ACCOUNT_ID,\r\n fluxSteps: parseInt(getEnvOrDefault(env, 'FLUX_STEPS', '4')),\r\n promptOptimization: getEnvOrDefault(env, 'PROMPT_OPTIMIZATION', 'false') === 'true',\r\n externalApiBase: env.EXTERNAL_API_BASE,\r\n externalModel: env.EXTERNAL_MODEL,\r\n externalApiKey: env.EXTERNAL_API_KEY,\r\n googleModelKey: env.GOOGLE_MODEL_KEY,\r\n googleModelBaseUrl: getEnvOrDefault(env, 'GOOGLE_MODEL_BASEURL', 'https://generativelanguage.googleapis.com/v1beta'),\r\n googleModels: env.GOOGLE_MODELS ? env.GOOGLE_MODELS.split(',').map(model => model.trim()) : [],\r\n groqApiKey: env.GROQ_API_KEY,\r\n groqModels: env.GROQ_MODELS ? env.GROQ_MODELS.split(',').map(model => model.trim()) : [],\r\n claudeApiKey: env.CLAUDE_API_KEY,\r\n claudeModels: env.CLAUDE_MODELS ? env.CLAUDE_MODELS.split(',').map(model => model.trim()) : [],\r\n claudeEndpoint: getEnvOrDefault(env, 'CLAUDE_ENDPOINT', 'https://api.anthropic.com/v1'),\r\n };\r\n};", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\n\r\nexport interface Message {\r\n role: 'system' | 'user' | 'assistant';\r\n content: string;\r\n}\r\n\r\ninterface ChatCompletionResponse {\r\n id: string;\r\n object: string;\r\n created: number;\r\n model: string;\r\n choices: {\r\n index: number;\r\n message: Message;\r\n finish_reason: string;\r\n }[];\r\n usage: {\r\n prompt_tokens: number;\r\n completion_tokens: number;\r\n total_tokens: number;\r\n };\r\n}\r\n\r\nexport class OpenAIAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private models: string[];\r\n private defaultModel: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.openaiApiKey;\r\n this.baseUrl = config.openaiBaseUrl;\r\n this.models = config.openaiModels;\r\n this.defaultModel = config.defaultModel || this.models[0];\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n const url = `${this.baseUrl}/chat/completions`;\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: model || this.defaultModel,\r\n messages: messages,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`OpenAI API error: ${response.statusText}`);\r\n }\r\n\r\n const data: ChatCompletionResponse = await response.json();\r\n return data.choices[0].message.content.trim();\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.models.includes(model);\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.defaultModel;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.models;\r\n }\r\n}\r\n\r\nexport default OpenAIAPI;", "import { Env } from '../env';\r\n\r\nexport function formatCodeBlock(code: string, language: string): string {\r\n return `\\`\\`\\`${language}\\n${code}\\n\\`\\`\\``;\r\n}\r\n\r\nexport function splitMessage(text: string, maxLength: number = 4096): string[] {\r\n const messages: string[] = [];\r\n let currentMessage = '';\r\n\r\n const lines = text.split('\\n');\r\n\r\n for (const line of lines) {\r\n if (currentMessage.length + line.length + 1 > maxLength) {\r\n messages.push(currentMessage.trim());\r\n currentMessage = '';\r\n }\r\n currentMessage += line + '\\n';\r\n }\r\n\r\n if (currentMessage.trim()) {\r\n messages.push(currentMessage.trim());\r\n }\r\n\r\n return messages;\r\n}\r\n\r\nexport function escapeMarkdown(text: string): string {\r\n const specialChars = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'];\r\n return specialChars.reduce((acc, char) => acc.replace(new RegExp(`\\\\${char}`, 'g'), `\\\\${char}`), text);\r\n}\r\n\r\nexport async function sendChatAction(chatId: number, action: string, env: Env): Promise {\r\n const token = env.TELEGRAM_BOT_TOKEN;\r\n const url = `https://api.telegram.org/bot${token}/sendChatAction`;\r\n await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n chat_id: chatId,\r\n action: action,\r\n }),\r\n });\r\n}", "export type SupportedLanguages = 'en' | 'zh' | 'es';\r\n\r\nexport interface Translations {\r\n welcome: string;\r\n unauthorized: string;\r\n error: string;\r\n current_language: string;\r\n language_changed: string;\r\n new_conversation: string;\r\n no_history: string;\r\n history_summary: string;\r\n current_model: string;\r\n available_models: string;\r\n model_changed: string;\r\n help_intro: string;\r\n start_description: string;\r\n language_description: string;\r\n new_description: string;\r\n history_description: string;\r\n switchmodel_description: string;\r\n help_description: string;\r\n choose_language: string;\r\n choose_model: string;\r\n language_en: string;\r\n language_zh: string;\r\n language_es: string;\r\n image_prompt_required: string;\r\n image_generation_error: string;\r\n img_description: string;\r\n invalid_size: string;\r\n flux_description: string;\r\n flux_usage: string;\r\n invalid_aspect_ratio: string;\r\n original_prompt: string;\r\n prompt_generation_model: string;\r\n optimized_prompt: string;\r\n image_specs: string;\r\n command_not_found: string;\r\n}\r\n\r\nexport type TranslationKey = keyof Translations;\r\n\r\ntype TranslationsMap = Record;\r\n\r\nconst translations: TranslationsMap = {\r\n en: {\r\n welcome: \"Welcome to the GPT Telegram Bot!\",\r\n unauthorized: \"Sorry, you're not authorized to use this bot.\",\r\n error: \"An error occurred. Please try again.\",\r\n current_language: \"Your current language is: English\",\r\n language_changed: \"Language has been changed to: \",\r\n new_conversation: \"Starting a new conversation. Previous context has been cleared.\",\r\n no_history: \"No conversation history found.\",\r\n history_summary: \"Here's a summary of your conversation history:\",\r\n current_model: \"Your current model is: \",\r\n available_models: \"Available models: \",\r\n model_changed: \"Model has been changed to: \",\r\n help_intro: \"Here are the available commands:\",\r\n start_description: \"Start the bot\",\r\n language_description: \"Set your preferred language\",\r\n new_description: \"Start a new conversation\",\r\n history_description: \"Summarize conversation history\",\r\n switchmodel_description: \"Switch the current model\",\r\n help_description: \"Show available commands and their descriptions\",\r\n choose_language: \"Please choose your preferred language:\",\r\n choose_model: \"Please choose a model:\",\r\n language_en: \"English\",\r\n language_zh: \"Chinese\",\r\n language_es: \"Spanish\",\r\n image_prompt_required: 'Please provide a description for the image you want to generate.',\r\n image_generation_error: 'Sorry, there was an error generating the image. Please try again later.',\r\n img_description: 'Generate an image using DALL\u00B7E. Format: /img [size]',\r\n invalid_size: 'Invalid image size. Please use one of the following sizes: ',\r\n flux_description: 'Generate an image using Flux',\r\n flux_usage: 'Usage: /flux [aspect ratio]. Valid aspect ratios are: 1:1 (default), 1:2, 3:2, 3:4, 16:9, 9:16',\r\n invalid_aspect_ratio: 'Invalid aspect ratio. Valid options are: ',\r\n original_prompt: \"\uD83C\uDFA8 Original Prompt\",\r\n prompt_generation_model: \"\uD83D\uDCAC Prompt Generation Model\",\r\n optimized_prompt: \"\uD83C\uDF10 Optimized Prompt\",\r\n image_specs: \"\uD83D\uDCD0 Image Specifications\",\r\n command_not_found: \"Command not found. Type /help for a list of available commands.\",\r\n },\r\n zh: {\r\n welcome: \"\u6B22\u8FCE\u4F7F\u7528 GPT Telegram \u673A\u5668\u4EBA\uFF01\",\r\n unauthorized: \"\u62B1\u6B49\uFF0C\u60A8\u65E0\u6743\u4F7F\u7528\u6B64\u673A\u5668\u4EBA\u3002\",\r\n error: \"\u53D1\u751F\u9519\u8BEF\uFF0C\u8BF7\u91CD\u8BD5\u3002\",\r\n current_language: \"\u60A8\u5F53\u524D\u7684\u8BED\u8A00\u662F\uFF1A\u4E2D\u6587\",\r\n language_changed: \"\u8BED\u8A00\u5DF2\u66F4\u6539\u4E3A\uFF1A\",\r\n new_conversation: \"\u5F00\u59CB\u65B0\u7684\u5BF9\u8BDD\u3002\u4E4B\u524D\u7684\u4E0A\u4E0B\u6587\u5DF2\u88AB\u6E05\u9664\u3002\",\r\n no_history: \"\u672A\u627E\u5230\u5BF9\u8BDD\u5386\u53F2\u3002\",\r\n history_summary: \"\u4EE5\u4E0B\u662F\u60A8\u7684\u5BF9\u8BDD\u5386\u53F2\u6458\u8981\uFF1A\",\r\n current_model: \"\u60A8\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B\u662F\uFF1A\",\r\n available_models: \"\u53EF\u7528\u7684\u6A21\u578B\uFF1A\",\r\n model_changed: \"\u6A21\u578B\u5DF2\u66F4\u6539\u4E3A\uFF1A\",\r\n help_intro: \"\u4EE5\u4E0B\u662F\u53EF\u7528\u7684\u547D\u4EE4\uFF1A\",\r\n start_description: \"\u542F\u52A8\u673A\u5668\u4EBA\",\r\n language_description: \"\u8BBE\u7F6E\u60A8\u7684\u9996\u9009\u8BED\u8A00\",\r\n new_description: \"\u5F00\u59CB\u65B0\u7684\u5BF9\u8BDD\",\r\n history_description: \"\u603B\u7ED3\u5BF9\u8BDD\u5386\u53F2\",\r\n switchmodel_description: \"\u5207\u6362\u5F53\u524D\u6A21\u578B\",\r\n help_description: \"\u663E\u793A\u53EF\u7528\u547D\u4EE4\u53CA\u5176\u63CF\u8FF0\",\r\n choose_language: \"\u8BF7\u9009\u62E9\u60A8\u504F\u597D\u7684\u8BED\u8A00\uFF1A\",\r\n choose_model: \"\u8BF7\u9009\u62E9\u4E00\u4E2A\u6A21\u578B\uFF1A\",\r\n language_en: \"\u82F1\u8BED\",\r\n language_zh: \"\u4E2D\u6587\",\r\n language_es: \"\u897F\u73ED\u7259\u8BED\",\r\n image_prompt_required: '\u8BF7\u63D0\u4F9B\u60A8\u60F3\u8981\u751F\u6210\u7684\u56FE\u50CF\u63CF\u8FF0\u3002',\r\n image_generation_error: '\u62B1\u6B49\uFF0C\u751F\u6210\u56FE\u50CF\u65F6\u51FA\u9519\u3002\u8BF7\u7A0D\u540E\u518D\u8BD5\u3002',\r\n img_description: '\u4F7F\u7528 DALL\u00B7E \u751F\u6210\u56FE\u50CF\u3002\u683C\u5F0F\uFF1A/img <\u63CF\u8FF0> [\u5C3A\u5BF8]',\r\n invalid_size: '\u65E0\u6548\u7684\u56FE\u7247\u5C3A\u5BF8\u3002\u8BF7\u4F7F\u7528\u4EE5\u4E0B\u5C3A\u5BF8\u4E4B\u4E00\uFF1A',\r\n flux_description: '\u4F7F\u7528 Flux \u751F\u6210\u56FE\u50CF',\r\n flux_usage: '\u7528\u6CD5\uFF1A/flux <\u63CF\u8FF0> [\u5BBD\u9AD8\u6BD4]\u3002\u6709\u6548\u7684\u5BBD\u9AD8\u6BD4\u6709\uFF1A1:1\uFF08\u9ED8\u8BA4\uFF09, 1:2, 3:2, 3:4, 16:9, 9:16',\r\n invalid_aspect_ratio: '\u65E0\u6548\u7684\u5BBD\u9AD8\u6BD4\u3002\u6709\u6548\u9009\u9879\u4E3A\uFF1A',\r\n original_prompt: \"\uD83C\uDFA8 \u539F\u59CB\u63D0\u793A\u8BCD\",\r\n prompt_generation_model: \"\uD83D\uDCAC \u63D0\u793A\u8BCD\u751F\u6210\u6A21\u578B\",\r\n optimized_prompt: \"\uD83C\uDF10 \u4F18\u5316\u540E\u7684\u63D0\u793A\u8BCD\",\r\n image_specs: \"\uD83D\uDCD0 \u56FE\u50CF\u89C4\u683C\",\r\n command_not_found: \"\u672A\u627E\u5230\u8BE5\u547D\u4EE4\u3002\u8F93\u5165 /help \u67E5\u770B\u53EF\u7528\u547D\u4EE4\u5217\u8868\u3002\",\r\n },\r\n es: {\r\n welcome: \"\u00A1Bienvenido al bot de GPT en Telegram!\",\r\n unauthorized: \"Lo siento, no est\u00E1s autorizado para usar este bot.\",\r\n error: \"Ocurri\u00F3 un error. Por favor, int\u00E9ntalo de nuevo.\",\r\n current_language: \"Tu idioma actual es: Espa\u00F1ol\",\r\n language_changed: \"El idioma ha sido cambiado a: \",\r\n new_conversation: \"Iniciando una nueva conversaci\u00F3n. El contexto anterior ha sido borrado.\",\r\n no_history: \"No se encontr\u00F3 historial de conversaci\u00F3n.\",\r\n history_summary: \"Aqu\u00ED tienes un resumen de tu historial de conversaci\u00F3n:\",\r\n current_model: \"Tu modelo actual es: \",\r\n available_models: \"Modelos disponibles: \",\r\n model_changed: \"El modelo ha sido cambiado a: \",\r\n help_intro: \"Estos son los comandos disponibles:\",\r\n start_description: \"Iniciar el bot\",\r\n language_description: \"Establecer tu idioma preferido\",\r\n new_description: \"Iniciar una nueva conversaci\u00F3n\",\r\n history_description: \"Resumir el historial de conversaci\u00F3n\",\r\n switchmodel_description: \"Cambiar el modelo actual\",\r\n help_description: \"Mostrar comandos disponibles y sus descripciones\",\r\n choose_language: \"Por favor, elige tu idioma preferido:\",\r\n choose_model: \"Por favor, elige un modelo:\",\r\n language_en: \"Ingl\u00E9s\",\r\n language_zh: \"Chino\",\r\n language_es: \"Espa\u00F1ol\",\r\n image_prompt_required: 'Por favor, proporcione una descripci\u00F3n para la imagen que desea generar.',\r\n image_generation_error: 'Lo siento, hubo un error al generar la imagen. Por favor, int\u00E9ntelo de nuevo m\u00E1s tarde.',\r\n img_description: 'Generar una imagen usando DALL\u00B7E. Formato: /img [tama\u00F1o]',\r\n invalid_size: 'Tama\u00F1o de imagen no v\u00E1lido. Por favor, use uno de los siguientes tama\u00F1os: ',\r\n flux_description: 'Generar una imagen usando Flux',\r\n flux_usage: 'Uso: /flux [relaci\u00F3n de aspecto]. Las relaciones de aspecto v\u00E1lidas son: 1:1 (predeterminado), 1:2, 3:2, 3:4, 16:9, 9:16',\r\n invalid_aspect_ratio: 'Relaci\u00F3n de aspecto no v\u00E1lida. Las opciones v\u00E1lidas son: ',\r\n original_prompt: \"\uD83C\uDFA8 Prompt Original\",\r\n prompt_generation_model: \"\uD83D\uDCAC Modelo de Generaci\u00F3n de Prompts\",\r\n optimized_prompt: \"\uD83C\uDF10 Prompt Optimizado\",\r\n image_specs: \"\uD83D\uDCD0 Especificaciones de la Imagen\",\r\n command_not_found: \"Comando no encontrado. Escribe /help para ver una lista de comandos disponibles.\",\r\n }\r\n};\r\n\r\nexport function translate(key: TranslationKey, language: SupportedLanguages = 'en'): string {\r\n return translations[language][key] || translations['en'][key];\r\n}", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport { Message } from './openai_api';\r\n\r\ninterface ImageGenerationResponse {\r\n data: Array<{ url: string }>;\r\n}\r\n\r\nexport class ImageGenerationAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private model: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.openaiApiKey;\r\n this.baseUrl = config.openaiBaseUrl;\r\n this.model = config.dallEModel;\r\n }\r\n\r\n async generateImage(prompt: string, size: string): Promise {\r\n const url = `${this.baseUrl}/images/generations`;\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: this.model,\r\n prompt: prompt,\r\n n: 1,\r\n size: size,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Image generation API error: ${response.statusText}`);\r\n }\r\n\r\n const data: ImageGenerationResponse = await response.json();\r\n return data.data[0].url;\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n throw new Error('Method not implemented for image generation.');\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return model === this.model;\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.model;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return [this.model];\r\n }\r\n\r\n getValidSizes(): string[] {\r\n return ['1024x1024', '1024x1792', '1792x1024'];\r\n }\r\n}\r\n\r\nexport default ImageGenerationAPI;", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\n\r\ninterface FluxResponse {\r\n result: {\r\n image: string; // base64 encoded image data\r\n };\r\n success: boolean;\r\n errors: string[];\r\n}\r\n\r\ninterface ExternalAPIResponse {\r\n choices: Array<{\r\n message: {\r\n content: string;\r\n };\r\n }>;\r\n}\r\n\r\nexport class FluxAPI implements ModelAPIInterface {\r\n private apiToken: string;\r\n private accountId: string;\r\n private steps: number;\r\n private model: string = '@cf/black-forest-labs/flux-1-schnell';\r\n private promptOptimization: boolean;\r\n private externalApiBase?: string;\r\n private externalModel?: string;\r\n private externalApiKey?: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiToken = config.cloudflareApiToken;\r\n this.accountId = config.cloudflareAccountId;\r\n this.steps = config.fluxSteps;\r\n this.promptOptimization = config.promptOptimization;\r\n this.externalApiBase = config.externalApiBase;\r\n this.externalModel = config.externalModel;\r\n this.externalApiKey = config.externalApiKey;\r\n }\r\n\r\n async generateImage(prompt: string, aspectRatio: string): Promise<{ imageData: Uint8Array; optimizedPrompt?: string }> {\r\n let optimizedPrompt: string | undefined;\r\n if (this.promptOptimization) {\r\n optimizedPrompt = await this.optimizePrompt(prompt, aspectRatio);\r\n prompt = optimizedPrompt;\r\n }\r\n\r\n const url = `https://api.cloudflare.com/client/v4/accounts/${this.accountId}/ai/run/${this.model}`;\r\n const [width, height] = this.getImageDimensions(aspectRatio);\r\n const seed = Math.floor(Math.random() * 1000000);\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiToken}`,\r\n },\r\n body: JSON.stringify({\r\n prompt: prompt,\r\n num_steps: this.steps,\r\n seed: seed,\r\n width: width,\r\n height: height,\r\n }),\r\n });\r\n\r\n const responseText = await response.text();\r\n let data: FluxResponse;\r\n try {\r\n data = JSON.parse(responseText);\r\n } catch (error) {\r\n console.error('Error parsing Flux API response:', error);\r\n throw new Error('Invalid response from Flux API');\r\n }\r\n\r\n if (!response.ok || !data.success) {\r\n const errorMessage = data.errors ? data.errors.join(', ') : 'Unknown error';\r\n console.error(`Flux API error: ${errorMessage}`);\r\n throw new Error(`Flux API error: ${errorMessage}`);\r\n }\r\n\r\n if (!data.result || !data.result.image) {\r\n console.error('Flux API returned no image');\r\n throw new Error('Flux API returned no image');\r\n }\r\n \r\n const binaryString = atob(data.result.image);\r\n const len = binaryString.length;\r\n const bytes = new Uint8Array(len);\r\n for (let i = 0; i < len; i++) {\r\n bytes[i] = binaryString.charCodeAt(i);\r\n }\r\n return { \r\n imageData: bytes,\r\n optimizedPrompt\r\n };\r\n }\r\n\r\n private async optimizePrompt(prompt: string, aspectRatio: string): Promise {\r\n if (!this.externalApiBase || !this.externalModel || !this.externalApiKey) {\r\n throw new Error('External API configuration is missing');\r\n }\r\n\r\n const systemPrompt = \"You are a prompt generation bot based on the Flux.1 model. Based on the user's requirements, automatically generate drawing prompts that adhere to the Flux.1 format. While you can refer to the provided templates to learn the structure and patterns of the prompts, you must remain flexible to meet various different needs. The final output should be limited to the prompts only, without any additional explanations or information. You must reply to me entirely in English!\\n\\n### **Prompt Generation Logic**:\\n\\n1. **Requirement Analysis**: Extract key information from the user's description, including:\\n- Characters: Appearance, actions, expressions, etc.\\n- Scene: Environment, lighting, weather, etc.\\n- Style: Art style, emotional atmosphere, color scheme, etc.\\n- **Aspect Ratio**: If the user provides a specific aspect ratio (e.g., \\\"3:2\\\", \\\"16:9\\\"), extract this and integrate it into the final prompt.\\n- Other elements: Specific objects, background, or effects.\\n\\n2. **Prompt Structure Guidelines**:\\n- **Concise, precise, and detailed**: Prompts should describe the core subject simply and clearly, with enough detail to generate an image that matches the request.\\n- **Flexible and varied**: Use the user's description to dynamically create prompts without following rigid templates. Ensure prompts are adapted based on the specific needs of each user, avoiding overly template-based outputs.\\n- **Descriptions following Flux.1 style**: Prompts must follow the requirements of Flux.1, aiming to include descriptions of the art style, visual effects, and emotional atmosphere. Use keywords and description patterns that match the Flux.1 model's generation process. If a specific aspect ratio is mentioned, ensure it is included in the prompt description.\\n\\n3. **Key Points Summary for Flux.1 Prompts**:\\n- **Concise and precise subject description**: Clearly identify the subject or scene of the image.\\n- **Specific description of style and emotional atmosphere**: Ensure the prompt includes information about the art style, lighting, color scheme, and emotional atmosphere of the image.\\n- **Details on dynamics and action**: Prompts may include important details like actions, emotions, or lighting effects in the scene.\";\r\n\r\n const response = await fetch(`${this.externalApiBase}/v1/chat/completions`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.externalApiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: this.externalModel,\r\n messages: [\r\n { role: 'system', content: systemPrompt },\r\n { role: 'user', content: `Optimize this image generation prompt for aspect ratio ${aspectRatio}: ${prompt}` },\r\n ],\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`External API error: ${response.statusText}`);\r\n }\r\n\r\n const data: ExternalAPIResponse = await response.json();\r\n return data.choices[0].message.content.trim();\r\n }\r\n\r\n private getImageDimensions(aspectRatio: string): [number, number] {\r\n switch (aspectRatio) {\r\n case '1:1': return [1024, 1024];\r\n case '1:2': return [512, 1024];\r\n case '3:2': return [768, 512];\r\n case '3:4': return [768, 1024];\r\n case '16:9': return [1024, 576];\r\n case '9:16': return [576, 1024];\r\n default: return [1024, 1024]; // Default to 1:1 if invalid ratio is provided\r\n }\r\n }\r\n\r\n async generateResponse(messages: { role: string; content: string; }[]): Promise {\r\n throw new Error('Method not implemented for image generation.');\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return model === this.model;\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.model;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return [this.model];\r\n }\r\n\r\n getValidAspectRatios(): string[] {\r\n return ['1:1', '1:2', '3:2', '3:4', '16:9', '9:16'];\r\n }\r\n}\r\n\r\nexport default FluxAPI;", "import { TelegramBot } from '../api/telegram';\r\nimport { translate, TranslationKey } from '../utils/i18n';\r\nimport { ImageGenerationAPI } from '../api/image_generation';\r\nimport { sendChatAction } from '../utils/helpers';\r\nimport { FluxAPI } from '../api/flux-cf';\r\nimport { getConfig } from '../env';\r\nimport GeminiAPI from '../api/gemini';\r\nimport GroqAPI from '../api/groq';\r\nimport ClaudeAPI from '../api/claude';\r\n\r\nexport interface Command {\r\n name: string;\r\n description: string;\r\n action: (chatId: number, bot: TelegramBot, args: string[]) => Promise;\r\n}\r\n\r\nexport const commands: Command[] = [\r\n {\r\n name: 'start',\r\n description: 'Start the bot',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n const currentModel = await bot.getCurrentModel(userId);\r\n const welcomeMessage = translate('welcome', language) + '\\n' + \r\n translate('current_model', language) + currentModel;\r\n await bot.sendMessageWithFallback(chatId, welcomeMessage);\r\n },\r\n },\r\n {\r\n name: 'language',\r\n description: 'Set your preferred language',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const currentLanguage = await bot.getUserLanguage(userId);\r\n const keyboard = {\r\n inline_keyboard: [\r\n [\r\n { text: '\uD83C\uDDFA\uD83C\uDDF8 English', callback_data: 'lang_en' },\r\n { text: '\uD83C\uDDE8\uD83C\uDDF3 \u4E2D\u6587', callback_data: 'lang_zh' },\r\n { text: '\uD83C\uDDEA\uD83C\uDDF8 Espa\u00F1ol', callback_data: 'lang_es' }\r\n ]\r\n ]\r\n };\r\n await bot.sendMessage(chatId, translate('choose_language', currentLanguage), { reply_markup: JSON.stringify(keyboard) });\r\n },\r\n },\r\n {\r\n name: 'switchmodel',\r\n description: 'Switch the current model',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n const config = getConfig(bot['env']);\r\n const availableModels = [\r\n ...config.openaiModels,\r\n ...config.googleModels,\r\n ...config.groqModels,\r\n ...config.claudeModels // \u6DFB\u52A0 Claude \u6A21\u578B\r\n ];\r\n const keyboard = {\r\n inline_keyboard: availableModels.map(model => [{text: model, callback_data: `model_${model}`}])\r\n };\r\n await bot.sendMessage(chatId, translate('choose_model', language), { reply_markup: JSON.stringify(keyboard) });\r\n },\r\n },\r\n {\r\n name: 'new',\r\n description: 'Start a new conversation',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n await bot.clearContext(userId);\r\n },\r\n },\r\n {\r\n name: 'history',\r\n description: 'Summarize conversation history',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n const summary = await bot.summarizeHistory(userId);\r\n await bot.sendMessage(chatId, summary || translate('no_history', language));\r\n },\r\n },\r\n {\r\n name: 'help',\r\n description: 'Show available commands and their descriptions',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n let helpMessage = translate('help_intro', language) + '\\n\\n';\r\n \r\n for (const command of commands) {\r\n const descriptionKey = `${command.name}_description` as TranslationKey;\r\n // \u4F7F\u7528\u666E\u901A\u6587\u672C\uFF0C\u4E0D\u6DFB\u52A0\u4EFB\u4F55\u683C\u5F0F\u5316\r\n helpMessage += `/${command.name} - ${translate(descriptionKey, language)}\\n`;\r\n }\r\n \r\n // \u4F7F\u7528\u666E\u901A\u7684 sendMessage \u65B9\u6CD5\uFF0C\u4E0D\u6307\u5B9A parse_mode\r\n await bot.sendMessage(chatId, helpMessage);\r\n },\r\n },\r\n {\r\n name: 'img',\r\n description: 'Generate an image using DALL\u00B7E',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n \r\n if (!args.length) {\r\n await bot.sendMessageWithFallback(chatId, translate('image_prompt_required', language));\r\n return;\r\n }\r\n \r\n const validSizes = ['1024x1024', '1024x1792', '1792x1024'];\r\n const sizeArg = args[args.length - 1].toLowerCase();\r\n let size: string;\r\n let prompt: string;\r\n \r\n if (validSizes.includes(sizeArg)) {\r\n size = sizeArg;\r\n prompt = args.slice(0, -1).join(' ');\r\n } else {\r\n size = '1024x1024'; // Default size\r\n prompt = args.join(' ');\r\n \r\n // Check if the last argument looks like a size specification\r\n if (sizeArg.includes('x') || sizeArg.includes('*')) {\r\n const sizeOptions = validSizes.map(s => `\\`${s}\\``).join(', ');\r\n await bot.sendMessage(chatId, translate('invalid_size', language) + sizeOptions);\r\n return;\r\n }\r\n }\r\n \r\n try {\r\n await sendChatAction(chatId, 'upload_photo', bot['env']);\r\n const imageApi = new ImageGenerationAPI(bot['env']);\r\n const imageUrl = await imageApi.generateImage(prompt, size);\r\n await bot.sendPhoto(chatId, imageUrl, { caption: prompt });\r\n } catch (error) {\r\n console.error('Error generating image:', error);\r\n await bot.sendMessage(chatId, translate('image_generation_error', language));\r\n }\r\n },\r\n },\r\n {\r\n name: 'flux',\r\n description: 'Generate an image using Flux',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n\r\n if (!args.length) {\r\n await bot.sendMessage(chatId, translate('flux_usage', language));\r\n return;\r\n }\r\n\r\n let aspectRatio = '1:1'; // \u9ED8\u8BA4\u6BD4\u4F8B\r\n let prompt: string;\r\n\r\n const fluxApi = new FluxAPI(bot['env']);\r\n const validRatios = fluxApi.getValidAspectRatios();\r\n\r\n if (validRatios.includes(args[args.length - 1])) {\r\n aspectRatio = args[args.length - 1];\r\n prompt = args.slice(0, -1).join(' ');\r\n } else {\r\n prompt = args.join(' ');\r\n }\r\n\r\n try {\r\n await sendChatAction(chatId, 'upload_photo', bot['env']);\r\n\r\n const { imageData, optimizedPrompt } = await fluxApi.generateImage(prompt, aspectRatio);\r\n \r\n const config = getConfig(bot['env']);\r\n let caption = `${translate('original_prompt', language)}: ${prompt}\\n`;\r\n caption += `${translate('image_specs', language)}: ${aspectRatio}\\n`;\r\n \r\n if (config.promptOptimization && optimizedPrompt) {\r\n caption += `${translate('prompt_generation_model', language)}: ${config.externalModel || 'Unknown'}\\n`;\r\n caption += `${translate('optimized_prompt', language)}: ${optimizedPrompt}\\n`;\r\n }\r\n\r\n await bot.sendPhoto(chatId, imageData, { caption: caption });\r\n } catch (error) {\r\n console.error(`Error generating Flux image for user ${userId}:`, error);\r\n if (error instanceof Error) {\r\n console.error('Error details:', error.message);\r\n }\r\n await bot.sendMessage(chatId, translate('image_generation_error', language));\r\n }\r\n },\r\n },\r\n];", "import { Env, getConfig } from '../env';\r\n\r\ninterface RedisResponse {\r\n result: string | null;\r\n}\r\n\r\nexport class RedisClient {\r\n private url: string;\r\n private token: string;\r\n private config: ReturnType;\r\n\r\n constructor(env: Env) {\r\n this.config = getConfig(env);\r\n this.url = this.config.upstashRedisRestUrl;\r\n this.token = this.config.upstashRedisRestToken;\r\n }\r\n\r\n async get(key: string): Promise {\r\n const response = await fetch(`${this.url}/get/${key}`, {\r\n headers: {\r\n Authorization: `Bearer ${this.token}`,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n if (response.status === 404) {\r\n return null;\r\n }\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n\r\n const data = await response.json() as RedisResponse;\r\n return data.result;\r\n }\r\n\r\n async set(key: string, value: string, ttl?: number): Promise {\r\n const url = ttl\r\n ? `${this.url}/set/${key}/${value}?EX=${ttl}`\r\n : `${this.url}/set/${key}/${value}`;\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: `Bearer ${this.token}`,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n }\r\n\r\n async del(key: string): Promise {\r\n const response = await fetch(`${this.url}/del/${key}`, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: `Bearer ${this.token}`,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n }\r\n\r\n async setLanguage(userId: string, language: string): Promise {\r\n await this.set(`language:${userId}`, language, this.config.languageTTL);\r\n }\r\n\r\n async appendContext(userId: string, newContext: string): Promise {\r\n const key = `context:${userId}`;\r\n const existingContext = await this.get(key);\r\n const updatedContext = existingContext\r\n ? `${existingContext}\\n${newContext}`\r\n : newContext;\r\n await this.set(key, updatedContext, this.config.contextTTL);\r\n }\r\n}", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport { Message } from './openai_api';\r\n\r\ninterface GeminiResponse {\r\n candidates: Array<{\r\n content: {\r\n parts: Array<{\r\n text: string;\r\n }>;\r\n };\r\n }>;\r\n}\r\n\r\ninterface GeminiMessage {\r\n role: 'user' | 'model';\r\n parts: Array<{ text: string }>;\r\n}\r\n\r\nexport class GeminiAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private models: string[];\r\n private defaultModel: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.googleModelKey;\r\n this.baseUrl = config.googleModelBaseUrl || 'https://generativelanguage.googleapis.com/v1beta';\r\n this.models = config.googleModels;\r\n this.defaultModel = this.models[0];\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n const useModel = model || this.defaultModel;\r\n console.log(`Generating response with Gemini model: ${useModel}`);\r\n const url = `${this.baseUrl}/models/${useModel}:generateContent?key=${this.apiKey}`;\r\n\r\n const geminiMessages: GeminiMessage[] = messages\r\n .filter(msg => msg.role !== 'system') // \u8FC7\u6EE4\u6389 system \u6D88\u606F\r\n .map(msg => ({\r\n role: msg.role === 'assistant' ? 'model' : 'user',\r\n parts: [{ text: msg.content }]\r\n }));\r\n\r\n const requestBody = {\r\n contents: geminiMessages,\r\n generationConfig: {\r\n temperature: 0.7,\r\n topP: 1,\r\n topK: 1,\r\n maxOutputTokens: 2048,\r\n },\r\n };\r\n\r\n console.log('Request body:', JSON.stringify(requestBody, null, 2));\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(requestBody),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error(`Gemini API error: ${response.statusText}`, errorText);\r\n throw new Error(`Gemini API error: ${response.statusText}\\n${errorText}`);\r\n }\r\n\r\n const data: GeminiResponse = await response.json();\r\n console.log('Gemini API response received');\r\n if (!data.candidates || data.candidates.length === 0) {\r\n throw new Error('No response generated from Gemini API');\r\n }\r\n const generatedText = data.candidates[0].content.parts[0].text.trim();\r\n console.log(`Generated text length: ${generatedText.length}`);\r\n return generatedText;\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.models.includes(model);\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.defaultModel;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.models;\r\n }\r\n}\r\n\r\nexport default GeminiAPI;", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport { Message } from './openai_api';\r\n\r\ninterface GroqResponse {\r\n choices: Array<{\r\n message: {\r\n content: string;\r\n };\r\n }>;\r\n}\r\n\r\nexport class GroqAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string = 'https://api.groq.com/openai/v1';\r\n private models: string[];\r\n private defaultModel: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.groqApiKey;\r\n this.models = config.groqModels;\r\n this.defaultModel = this.models[0];\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n const useModel = model || this.defaultModel;\r\n console.log(`Generating response with Groq model: ${useModel}`);\r\n const url = `${this.baseUrl}/chat/completions`;\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: useModel,\r\n messages: messages,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error(`Groq API error: ${response.statusText}`, errorText);\r\n throw new Error(`Groq API error: ${response.statusText}\\n${errorText}`);\r\n }\r\n\r\n const data: GroqResponse = await response.json();\r\n console.log('Groq API response received');\r\n if (!data.choices || data.choices.length === 0) {\r\n throw new Error('No response generated from Groq API');\r\n }\r\n const generatedText = data.choices[0].message.content.trim();\r\n console.log(`Generated text length: ${generatedText.length}`);\r\n return generatedText;\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.models.includes(model);\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.defaultModel;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.models;\r\n }\r\n}\r\n\r\nexport default GroqAPI;", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport { Message } from './openai_api';\r\n\r\ninterface ClaudeResponse {\r\n content: Array<{\r\n text: string;\r\n }>;\r\n}\r\n\r\nexport class ClaudeAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private models: string[];\r\n private defaultModel: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.claudeApiKey;\r\n this.baseUrl = config.claudeEndpoint || 'https://api.anthropic.com/v1';\r\n this.models = config.claudeModels;\r\n this.defaultModel = this.models[0];\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n const useModel = model || this.defaultModel;\r\n console.log(`Generating response with Claude model: ${useModel}`);\r\n const url = `${this.baseUrl}/messages`;\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': this.apiKey,\r\n 'anthropic-version': '2023-06-01'\r\n },\r\n body: JSON.stringify({\r\n model: useModel,\r\n messages: messages.map(msg => ({\r\n role: msg.role === 'assistant' ? 'assistant' : 'user',\r\n content: msg.content\r\n })),\r\n max_tokens: 1000\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error(`Claude API error: ${response.statusText}`, errorText);\r\n throw new Error(`Claude API error: ${response.statusText}\\n${errorText}`);\r\n }\r\n\r\n const data: ClaudeResponse = await response.json();\r\n console.log('Claude API response received');\r\n if (!data.content || data.content.length === 0) {\r\n throw new Error('No response generated from Claude API');\r\n }\r\n const generatedText = data.content[0].text.trim();\r\n console.log(`Generated text length: ${generatedText.length}`);\r\n return generatedText;\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.models.includes(model);\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.defaultModel;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.models;\r\n }\r\n}\r\n\r\nexport default ClaudeAPI;", "import { Env, getConfig } from '../env';\r\nimport { TelegramTypes } from '../../types/telegram';\r\nimport OpenAIAPI, { Message } from './openai_api';\r\nimport { formatCodeBlock, escapeMarkdown, sendChatAction, splitMessage } from '../utils/helpers';\r\nimport { translate, SupportedLanguages } from '../utils/i18n';\r\nimport { commands, Command } from '../config/commands';\r\nimport { RedisClient } from '../utils/redis';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport GeminiAPI from './gemini';\r\nimport GroqAPI from './groq';\r\nimport ClaudeAPI from './claude';\r\n\r\nexport class TelegramBot {\r\n private token: string;\r\n private apiUrl: string;\r\n private whitelistedUsers: string[];\r\n private systemMessage: string;\r\n private env: Env;\r\n private commands: Command[];\r\n private redis: RedisClient;\r\n private modelAPI: ModelAPIInterface;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.token = config.telegramBotToken;\r\n this.apiUrl = `https://api.telegram.org/bot${this.token}`;\r\n this.whitelistedUsers = config.whitelistedUsers;\r\n this.systemMessage = config.systemInitMessage;\r\n this.env = env;\r\n this.commands = commands;\r\n this.redis = new RedisClient(env);\r\n this.modelAPI = new OpenAIAPI(env); // \u521D\u59CB\u5316\u4E3A OpenAIAPI\uFF0C\u7A0D\u540E\u4F1A\u6839\u636E\u9700\u8981\u66F4\u65B0\r\n }\r\n\r\n private async initializeModelAPI(userId: string): Promise {\r\n const currentModel = await this.getCurrentModel(userId);\r\n console.log(`Initializing API for model: ${currentModel}`);\r\n \r\n const config = getConfig(this.env);\r\n \r\n if (config.openaiModels.includes(currentModel)) {\r\n return new OpenAIAPI(this.env);\r\n } else if (config.googleModels.includes(currentModel)) {\r\n return new GeminiAPI(this.env);\r\n } else if (config.groqModels.includes(currentModel)) {\r\n return new GroqAPI(this.env);\r\n } else if (config.claudeModels.includes(currentModel)) {\r\n return new ClaudeAPI(this.env);\r\n }\r\n \r\n // \u5982\u679C\u6CA1\u6709\u5339\u914D\u7684\u6A21\u578B,\u4F7F\u7528\u9ED8\u8BA4\u7684 OpenAI API\r\n console.warn(`Unknown model: ${currentModel}. Falling back to OpenAI API.`);\r\n return new OpenAIAPI(this.env);\r\n }\r\n\r\n public async executeCommand(commandName: string, chatId: number, args: string[]): Promise {\r\n const command = this.commands.find(cmd => cmd.name === commandName) as Command | undefined;\r\n if (command) {\r\n await command.action(chatId, this, args);\r\n } else {\r\n console.log(`Unknown command: ${commandName}`);\r\n const language = await this.getUserLanguage(chatId.toString());\r\n // \u4F7F\u7528 'command_not_found' \u4F5C\u4E3A\u7FFB\u8BD1\u952E\r\n await this.sendMessage(chatId, translate('command_not_found', language));\r\n }\r\n }\r\n\r\n async sendMessage(chatId: number, text: string, options: { parse_mode?: 'Markdown' | 'HTML', reply_markup?: string } = {}): Promise {\r\n const messages = splitMessage(text);\r\n const results: TelegramTypes.SendMessageResult[] = [];\r\n\r\n for (const message of messages) {\r\n const url = `${this.apiUrl}/sendMessage`;\r\n console.log(`Sending message part (length: ${message.length})`);\r\n try {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n chat_id: chatId,\r\n text: message,\r\n parse_mode: options.parse_mode, // \u53EA\u6709\u5728\u660E\u786E\u6307\u5B9A\u65F6\u624D\u4F7F\u7528 parse_mode\r\n reply_markup: options.reply_markup,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error(`Telegram API error: ${response.statusText}`, errorText);\r\n throw new Error(`Telegram API error: ${response.statusText}\\n${errorText}`);\r\n }\r\n\r\n const result = await response.json() as TelegramTypes.SendMessageResult;\r\n results.push(result);\r\n } catch (error) {\r\n console.error('Error sending message part:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n async handleUpdate(update: TelegramTypes.Update): Promise {\r\n if (update.callback_query) {\r\n await this.handleCallbackQuery(update.callback_query);\r\n } else if (update.message && update.message.text) {\r\n const chatId = update.message.chat.id;\r\n const userId = update.message.from?.id?.toString();\r\n if (!userId) {\r\n console.error('User ID is undefined');\r\n return;\r\n }\r\n const text = update.message.text;\r\n const language = await this.getUserLanguage(userId);\r\n\r\n if (this.isUserWhitelisted(userId)) {\r\n if (text.startsWith('/')) {\r\n const [commandName, ...args] = text.slice(1).split(' ');\r\n await this.executeCommand(commandName, chatId, args);\r\n } else {\r\n try {\r\n await sendChatAction(chatId, 'typing', this.env);\r\n this.modelAPI = await this.initializeModelAPI(userId);\r\n const context = await this.getContext(userId);\r\n const currentModel = await this.getCurrentModel(userId);\r\n\r\n let messages: Message[] = [];\r\n if (currentModel.startsWith('gemini-')) {\r\n messages = [\r\n ...(context ? [{ role: 'user' as const, content: context }] : []),\r\n { role: 'user' as const, content: text }\r\n ];\r\n } else {\r\n messages = [\r\n { role: 'system' as const, content: this.systemMessage },\r\n ...(context ? [{ role: 'user' as const, content: context }] : []),\r\n { role: 'user' as const, content: text }\r\n ];\r\n }\r\n\r\n console.log(`Current modelAPI type: ${this.modelAPI.constructor.name}`);\r\n console.log(`Generating response with model: ${currentModel}`);\r\n const response = await this.modelAPI.generateResponse(messages, currentModel);\r\n console.log(`Generated response length: ${response.length}`);\r\n const formattedResponse = this.formatResponse(response);\r\n\r\n console.log(`Formatted response length: ${formattedResponse.length}`);\r\n // \u4F7F\u7528 sendMessageWithFallback \u65B9\u6CD5\u53D1\u9001\u6A21\u578B\u751F\u6210\u7684\u54CD\u5E94\r\n await this.sendMessageWithFallback(chatId, formattedResponse);\r\n\r\n await this.storeContext(userId, `User: ${text}\\nAssistant: ${response}`);\r\n } catch (error) {\r\n console.error('Error in handleUpdate:', error);\r\n const errorMessage = error instanceof Error ? error.message : 'An unknown error occurred';\r\n // \u9519\u8BEF\u6D88\u606F\u4F7F\u7528\u666E\u901A\u7684 sendMessage \u65B9\u6CD5\r\n await this.sendMessage(chatId, translate('error', language) + ': ' + errorMessage);\r\n }\r\n }\r\n } else {\r\n // \u672A\u6388\u6743\u6D88\u606F\u4F7F\u7528 sendMessageWithFallback \u65B9\u6CD5\r\n await this.sendMessageWithFallback(chatId, translate('unauthorized', language));\r\n }\r\n }\r\n }\r\n\r\n async handleCallbackQuery(callbackQuery: TelegramTypes.CallbackQuery): Promise {\r\n const chatId = callbackQuery.message?.chat.id;\r\n const userId = callbackQuery.from.id.toString();\r\n const data = callbackQuery.data;\r\n\r\n if (!chatId || !data) return;\r\n\r\n if (data.startsWith('lang_')) {\r\n const newLanguage = data.split('_')[1] as SupportedLanguages;\r\n await this.setUserLanguage(userId, newLanguage);\r\n await this.sendMessageWithFallback(chatId, translate('language_changed', newLanguage) + translate(`language_${newLanguage}`, newLanguage));\r\n } else if (data.startsWith('model_')) {\r\n const newModel = data.split('_')[1];\r\n await this.setCurrentModel(userId, newModel);\r\n const language = await this.getUserLanguage(userId);\r\n await this.sendMessageWithFallback(chatId, translate('model_changed', language) + newModel);\r\n await this.clearContext(userId);\r\n }\r\n\r\n // Answer the callback query to remove the loading state\r\n await fetch(`${this.apiUrl}/answerCallbackQuery`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ callback_query_id: callbackQuery.id })\r\n });\r\n }\r\n\r\n async getUserLanguage(userId: string): Promise {\r\n const language = await this.redis.get(`language:${userId}`);\r\n return (language as SupportedLanguages) || 'en';\r\n }\r\n\r\n async setUserLanguage(userId: string, language: SupportedLanguages): Promise {\r\n await this.redis.setLanguage(userId, language);\r\n }\r\n\r\n async getCurrentModel(userId: string): Promise {\r\n const model = await this.redis.get(`model:${userId}`);\r\n return model || this.modelAPI.getDefaultModel();\r\n }\r\n\r\n async setCurrentModel(userId: string, model: string): Promise {\r\n await this.redis.set(`model:${userId}`, model);\r\n console.log(`Switching to model: ${model}`);\r\n // \u5728\u8FD9\u91CC\u91CD\u65B0\u521D\u59CB\u5316 modelAPI\uFF0C\u4F7F\u7528\u7528\u6237ID\r\n this.modelAPI = await this.initializeModelAPI(userId);\r\n console.log(`Current modelAPI type: ${this.modelAPI.constructor.name}`);\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.modelAPI.getAvailableModels();\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.modelAPI.isValidModel(model);\r\n }\r\n\r\n async storeContext(userId: string, context: string): Promise {\r\n await this.redis.appendContext(userId, context);\r\n }\r\n\r\n async getContext(userId: string): Promise {\r\n return await this.redis.get(`context:${userId}`);\r\n }\r\n\r\n async clearContext(userId: string): Promise {\r\n await this.redis.del(`context:${userId}`);\r\n const language = await this.getUserLanguage(userId);\r\n await this.sendMessageWithFallback(parseInt(userId), translate('new_conversation', language));\r\n }\r\n\r\n async summarizeHistory(userId: string): Promise {\r\n // \u786E\u4FDD\u4F7F\u7528\u6700\u65B0\u7684\u6A21\u578B\r\n this.modelAPI = await this.initializeModelAPI(userId);\r\n\r\n const context = await this.getContext(userId);\r\n const language = await this.getUserLanguage(userId);\r\n if (!context) {\r\n return translate('no_history', language);\r\n }\r\n const languageNames = {\r\n 'en': 'English',\r\n 'zh': 'Chinese',\r\n 'es': 'Spanish'\r\n };\r\n const currentModel = await this.getCurrentModel(userId);\r\n console.log(`Summarizing history with model: ${currentModel}`);\r\n\r\n let messages: Message[];\r\n if (currentModel.startsWith('gemini-')) {\r\n // \u4E3A Gemini API \u521B\u5EFA\u7279\u5B9A\u7684\u6D88\u606F\u683C\u5F0F\r\n messages = [\r\n { role: 'user', content: `Please summarize the following conversation in ${languageNames[language]}:\\n\\n${context}` }\r\n ];\r\n } else {\r\n // \u4E3A OpenAI API \u4FDD\u6301\u539F\u6709\u7684\u6D88\u606F\u683C\u5F0F\r\n messages = [\r\n { role: 'system', content: `Summarize the following conversation in ${languageNames[language]}:` },\r\n { role: 'user', content: context }\r\n ];\r\n }\r\n\r\n const summary = await this.modelAPI.generateResponse(messages, currentModel);\r\n return `${translate('history_summary', language)}\\n\\n${summary}`;\r\n }\r\n\r\n formatResponse(response: string): string {\r\n const codeBlockRegex = /```(\\w+)?\\n([\\s\\S]+?)```/g;\r\n return response.replace(codeBlockRegex, (match, language, code) => {\r\n return formatCodeBlock(code.trim(), language || '');\r\n });\r\n }\r\n\r\n isUserWhitelisted(userId: string): boolean {\r\n return this.whitelistedUsers.includes(userId);\r\n }\r\n\r\n async handleWebhook(request: Request): Promise {\r\n if (request.method !== 'POST') {\r\n return new Response('Method Not Allowed', { status: 405 });\r\n }\r\n\r\n try {\r\n const update: TelegramTypes.Update = await request.json();\r\n await this.handleUpdate(update);\r\n return new Response('OK', { status: 200 });\r\n } catch (error) {\r\n console.error('Error processing webhook:', error);\r\n return new Response('Internal Server Error', { status: 500 });\r\n }\r\n }\r\n\r\n async sendPhoto(chatId: number, photo: string | Uint8Array, options: { caption?: string } = {}): Promise {\r\n const url = `${this.apiUrl}/sendPhoto`;\r\n const formData = new FormData();\r\n formData.append('chat_id', chatId.toString());\r\n\r\n if (typeof photo === 'string') {\r\n formData.append('photo', photo);\r\n } else {\r\n const blob = new Blob([photo], { type: 'image/png' });\r\n formData.append('photo', blob, 'image.png');\r\n }\r\n\r\n if (options.caption) {\r\n formData.append('caption', options.caption);\r\n }\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n body: formData,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n }\r\n\r\n async setWebhook(url: string): Promise {\r\n const setWebhookUrl = `${this.apiUrl}/setWebhook`;\r\n const response = await fetch(setWebhookUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({ url }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to set webhook: ${response.statusText}`);\r\n }\r\n\r\n const result: { ok: boolean; description?: string } = await response.json();\r\n if (!result.ok) {\r\n throw new Error(`Telegram API error: ${result.description}`);\r\n }\r\n }\r\n\r\n async sendMessageWithFallback(chatId: number, text: string): Promise {\r\n const messages = splitMessage(text);\r\n const results: TelegramTypes.SendMessageResult[] = [];\r\n\r\n for (const message of messages) {\r\n try {\r\n // \u9996\u5148\u5C1D\u8BD5\u4F7F\u7528 Markdown\r\n const result = await this.sendMessage(chatId, message, { parse_mode: 'Markdown' });\r\n results.push(...result); // \u4F7F\u7528\u5C55\u5F00\u8FD0\u7B97\u7B26\u6765\u6DFB\u52A0\u7ED3\u679C\r\n } catch (error) {\r\n console.error('Error sending message with Markdown, falling back to plain text:', error);\r\n // \u5982\u679C Markdown \u5931\u8D25\uFF0C\u9000\u56DE\u5230\u7EAF\u6587\u672C\r\n const plainTextResult = await this.sendMessage(chatId, message);\r\n results.push(...plainTextResult); // \u4F7F\u7528\u5C55\u5F00\u8FD0\u7B97\u7B26\u6765\u6DFB\u52A0\u7ED3\u679C\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n}\r\n\r\nexport default TelegramBot;", "import { Env } from './env';\r\nimport TelegramBot from './api/telegram';\r\n\r\nexport default {\r\n async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise {\r\n const bot = new TelegramBot(env);\r\n const url = new URL(request.url);\r\n\r\n console.log(`Received request for path: ${url.pathname}`);\r\n\r\n try {\r\n // Handle Telegram webhook\r\n if (url.pathname === '/webhook') {\r\n console.log('Processing webhook request');\r\n return await bot.handleWebhook(request);\r\n }\r\n\r\n // Handle root path\r\n if (url.pathname === '/' || url.pathname === '') {\r\n console.log('Serving root path');\r\n return new Response('Hello! This is your Telegram bot worker.', { \r\n status: 200,\r\n headers: { 'Content-Type': 'text/plain' }\r\n });\r\n }\r\n\r\n // Handle all other requests\r\n console.log('Path not found');\r\n return new Response('Not Found', { \r\n status: 404,\r\n headers: { 'Content-Type': 'text/plain' }\r\n });\r\n } catch (error) {\r\n console.error('Error processing request:', error);\r\n const errorMessage = error instanceof Error ? error.message : 'An unknown error occurred';\r\n return new Response(`Internal Server Error: ${errorMessage}`, { \r\n status: 500,\r\n headers: { 'Content-Type': 'text/plain' }\r\n });\r\n }\r\n },\r\n};"], - "mappings": ";AA6BA,IAAM,kBAAkB,CAAC,KAAU,KAAgB,iBAAiC;AAClF,SAAQ,IAAI,GAAG,KAAgB;AACjC;AAEO,IAAM,YAAY,CAAC,QAAa;AAErC,QAAM,YAAY,CAAC,CAAC,IAAI;AACxB,QAAM,YAAY,CAAC,CAAC,IAAI;AACxB,QAAM,UAAU,CAAC,CAAC,IAAI;AACtB,QAAM,YAAY,CAAC,CAAC,IAAI;AAExB,MAAI,CAAC,aAAa,CAAC,aAAa,CAAC,WAAW,CAAC,WAAW;AACtD,UAAM,IAAI,MAAM,0EAA0E;AAAA,EAC5F;AAEA,SAAO;AAAA,IACL,cAAc,IAAI;AAAA,IAClB,eAAe,gBAAgB,KAAK,mBAAmB,2BAA2B;AAAA,IAClF,cAAc,IAAI,gBAAgB,IAAI,cAAc,MAAM,GAAG,EAAE,IAAI,WAAS,MAAM,KAAK,CAAC,IAAI,CAAC;AAAA,IAC7F,kBAAkB,IAAI;AAAA,IACtB,kBAAkB,IAAI,oBAAoB,IAAI,kBAAkB,MAAM,GAAG,EAAE,IAAI,QAAM,GAAG,KAAK,CAAC,IAAI,CAAC;AAAA,IACnG,mBAAmB,gBAAgB,KAAK,uBAAuB,8BAA8B;AAAA,IAC7F,uBAAuB,gBAAgB,KAAK,4BAA4B,QAAQ;AAAA,IAChF,cAAc,IAAI;AAAA,IAClB,qBAAqB,IAAI;AAAA,IACzB,uBAAuB,IAAI;AAAA,IAC3B,YAAY,gBAAgB,KAAK,gBAAgB,UAAU;AAAA,IAC3D,aAAa,KAAK,KAAK,KAAK;AAAA,IAC5B,YAAY,KAAK,KAAK,KAAK;AAAA,IAC3B,oBAAoB,IAAI;AAAA,IACxB,qBAAqB,IAAI;AAAA,IACzB,WAAW,SAAS,gBAAgB,KAAK,cAAc,GAAG,CAAC;AAAA,IAC3D,oBAAoB,gBAAgB,KAAK,uBAAuB,OAAO,MAAM;AAAA,IAC7E,iBAAiB,IAAI;AAAA,IACrB,eAAe,IAAI;AAAA,IACnB,gBAAgB,IAAI;AAAA,IACpB,gBAAgB,IAAI;AAAA,IACpB,oBAAoB,gBAAgB,KAAK,wBAAwB,kDAAkD;AAAA,IACnH,cAAc,IAAI,gBAAgB,IAAI,cAAc,MAAM,GAAG,EAAE,IAAI,WAAS,MAAM,KAAK,CAAC,IAAI,CAAC;AAAA,IAC7F,YAAY,IAAI;AAAA,IAChB,YAAY,IAAI,cAAc,IAAI,YAAY,MAAM,GAAG,EAAE,IAAI,WAAS,MAAM,KAAK,CAAC,IAAI,CAAC;AAAA,IACvF,cAAc,IAAI;AAAA,IAClB,cAAc,IAAI,gBAAgB,IAAI,cAAc,MAAM,GAAG,EAAE,IAAI,WAAS,MAAM,KAAK,CAAC,IAAI,CAAC;AAAA,IAC7F,gBAAgB,gBAAgB,KAAK,mBAAmB,8BAA8B;AAAA,EACxF;AACF;;;ACjDO,IAAM,YAAN,MAA6C;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,KAAU;AACpB,UAAM,SAAS,UAAU,GAAG;AAC5B,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO;AACtB,SAAK,SAAS,OAAO;AACrB,SAAK,eAAe,OAAO,gBAAgB,KAAK,OAAO,CAAC;AAAA,EAC1D;AAAA,EAEA,MAAM,iBAAiB,UAAqB,OAAiC;AAC3E,UAAM,MAAM,GAAG,KAAK;AACpB,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB,UAAU,KAAK;AAAA,MAClC;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO,SAAS,KAAK;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,qBAAqB,SAAS,YAAY;AAAA,IAC5D;AAEA,UAAM,OAA+B,MAAM,SAAS,KAAK;AACzD,WAAO,KAAK,QAAQ,CAAC,EAAE,QAAQ,QAAQ,KAAK;AAAA,EAC9C;AAAA,EAEA,aAAa,OAAwB;AACnC,WAAO,KAAK,OAAO,SAAS,KAAK;AAAA,EACnC;AAAA,EAEA,kBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,qBAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AAEA,IAAO,qBAAQ;;;ACxER,SAAS,gBAAgB,MAAc,UAA0B;AACtE,SAAO,SAAS;AAAA,EAAa;AAAA;AAC/B;AAEO,SAAS,aAAa,MAAc,YAAoB,MAAgB;AAC7E,QAAM,WAAqB,CAAC;AAC5B,MAAI,iBAAiB;AAErB,QAAM,QAAQ,KAAK,MAAM,IAAI;AAE7B,aAAW,QAAQ,OAAO;AACxB,QAAI,eAAe,SAAS,KAAK,SAAS,IAAI,WAAW;AACvD,eAAS,KAAK,eAAe,KAAK,CAAC;AACnC,uBAAiB;AAAA,IACnB;AACA,sBAAkB,OAAO;AAAA,EAC3B;AAEA,MAAI,eAAe,KAAK,GAAG;AACzB,aAAS,KAAK,eAAe,KAAK,CAAC;AAAA,EACrC;AAEA,SAAO;AACT;AAOA,eAAsB,eAAe,QAAgB,QAAgB,KAAyB;AAC5F,QAAM,QAAQ,IAAI;AAClB,QAAM,MAAM,+BAA+B;AAC3C,QAAM,MAAM,KAAK;AAAA,IACf,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACnB,SAAS;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;;;ACDA,IAAM,eAAgC;AAAA,EACpC,IAAI;AAAA,IACF,SAAS;AAAA,IACT,cAAc;AAAA,IACd,OAAO;AAAA,IACP,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,IACtB,iBAAiB;AAAA,IACjB,qBAAqB;AAAA,IACrB,yBAAyB;AAAA,IACzB,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa;AAAA,IACb,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,IACxB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,sBAAsB;AAAA,IACtB,iBAAiB;AAAA,IACjB,yBAAyB;AAAA,IACzB,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,mBAAmB;AAAA,EACrB;AAAA,EACA,IAAI;AAAA,IACF,SAAS;AAAA,IACT,cAAc;AAAA,IACd,OAAO;AAAA,IACP,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,IACtB,iBAAiB;AAAA,IACjB,qBAAqB;AAAA,IACrB,yBAAyB;AAAA,IACzB,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa;AAAA,IACb,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,IACxB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,sBAAsB;AAAA,IACtB,iBAAiB;AAAA,IACjB,yBAAyB;AAAA,IACzB,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,mBAAmB;AAAA,EACrB;AAAA,EACA,IAAI;AAAA,IACF,SAAS;AAAA,IACT,cAAc;AAAA,IACd,OAAO;AAAA,IACP,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,IACtB,iBAAiB;AAAA,IACjB,qBAAqB;AAAA,IACrB,yBAAyB;AAAA,IACzB,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa;AAAA,IACb,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,IACxB,iBAAiB;AAAA,IACjB,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,sBAAsB;AAAA,IACtB,iBAAiB;AAAA,IACjB,yBAAyB;AAAA,IACzB,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,mBAAmB;AAAA,EACrB;AACF;AAEO,SAAS,UAAU,KAAqB,WAA+B,MAAc;AAC1F,SAAO,aAAa,QAAQ,EAAE,GAAG,KAAK,aAAa,IAAI,EAAE,GAAG;AAC9D;;;ACxJO,IAAM,qBAAN,MAAsD;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,KAAU;AACpB,UAAM,SAAS,UAAU,GAAG;AAC5B,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO;AACtB,SAAK,QAAQ,OAAO;AAAA,EACtB;AAAA,EAEA,MAAM,cAAc,QAAgB,MAA+B;AACjE,UAAM,MAAM,GAAG,KAAK;AACpB,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB,UAAU,KAAK;AAAA,MAClC;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO,KAAK;AAAA,QACZ;AAAA,QACA,GAAG;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,+BAA+B,SAAS,YAAY;AAAA,IACtE;AAEA,UAAM,OAAgC,MAAM,SAAS,KAAK;AAC1D,WAAO,KAAK,KAAK,CAAC,EAAE;AAAA,EACtB;AAAA,EAEA,MAAM,iBAAiB,UAAqB,OAAiC;AAC3E,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AAAA,EAEA,aAAa,OAAwB;AACnC,WAAO,UAAU,KAAK;AAAA,EACxB;AAAA,EAEA,kBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,qBAA+B;AAC7B,WAAO,CAAC,KAAK,KAAK;AAAA,EACpB;AAAA,EAEA,gBAA0B;AACxB,WAAO,CAAC,aAAa,aAAa,WAAW;AAAA,EAC/C;AACF;;;AC5CO,IAAM,UAAN,MAA2C;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,KAAU;AACpB,UAAM,SAAS,UAAU,GAAG;AAC5B,SAAK,WAAW,OAAO;AACvB,SAAK,YAAY,OAAO;AACxB,SAAK,QAAQ,OAAO;AACpB,SAAK,qBAAqB,OAAO;AACjC,SAAK,kBAAkB,OAAO;AAC9B,SAAK,gBAAgB,OAAO;AAC5B,SAAK,iBAAiB,OAAO;AAAA,EAC/B;AAAA,EAEA,MAAM,cAAc,QAAgB,aAAmF;AACrH,QAAI;AACJ,QAAI,KAAK,oBAAoB;AAC3B,wBAAkB,MAAM,KAAK,eAAe,QAAQ,WAAW;AAC/D,eAAS;AAAA,IACX;AAEA,UAAM,MAAM,iDAAiD,KAAK,oBAAoB,KAAK;AAC3F,UAAM,CAAC,OAAO,MAAM,IAAI,KAAK,mBAAmB,WAAW;AAC3D,UAAM,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI,GAAO;AAE/C,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB,UAAU,KAAK;AAAA,MAClC;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB;AAAA,QACA,WAAW,KAAK;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,UAAM,eAAe,MAAM,SAAS,KAAK;AACzC,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,YAAY;AAAA,IAChC,SAAS,OAAP;AACA,cAAQ,MAAM,oCAAoC,KAAK;AACvD,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AAEA,QAAI,CAAC,SAAS,MAAM,CAAC,KAAK,SAAS;AACjC,YAAM,eAAe,KAAK,SAAS,KAAK,OAAO,KAAK,IAAI,IAAI;AAC5D,cAAQ,MAAM,mBAAmB,cAAc;AAC/C,YAAM,IAAI,MAAM,mBAAmB,cAAc;AAAA,IACnD;AAEA,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,OAAO,OAAO;AACtC,cAAQ,MAAM,4BAA4B;AAC1C,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAEA,UAAM,eAAe,KAAK,KAAK,OAAO,KAAK;AAC3C,UAAM,MAAM,aAAa;AACzB,UAAM,QAAQ,IAAI,WAAW,GAAG;AAChC,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC1B,YAAM,CAAC,IAAI,aAAa,WAAW,CAAC;AAAA,IACxC;AACA,WAAO;AAAA,MACL,WAAW;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,eAAe,QAAgB,aAAsC;AACjF,QAAI,CAAC,KAAK,mBAAmB,CAAC,KAAK,iBAAiB,CAAC,KAAK,gBAAgB;AACxE,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAEA,UAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAErB,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,uCAAuC;AAAA,MAC1E,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB,UAAU,KAAK;AAAA,MAClC;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO,KAAK;AAAA,QACZ,UAAU;AAAA,UACR,EAAE,MAAM,UAAU,SAAS,aAAa;AAAA,UACxC,EAAE,MAAM,QAAQ,SAAS,0DAA0D,gBAAgB,SAAS;AAAA,QAC9G;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,uBAAuB,SAAS,YAAY;AAAA,IAC9D;AAEA,UAAM,OAA4B,MAAM,SAAS,KAAK;AACtD,WAAO,KAAK,QAAQ,CAAC,EAAE,QAAQ,QAAQ,KAAK;AAAA,EAC9C;AAAA,EAEQ,mBAAmB,aAAuC;AAChE,YAAQ,aAAa;AAAA,MACnB,KAAK;AAAO,eAAO,CAAC,MAAM,IAAI;AAAA,MAC9B,KAAK;AAAO,eAAO,CAAC,KAAK,IAAI;AAAA,MAC7B,KAAK;AAAO,eAAO,CAAC,KAAK,GAAG;AAAA,MAC5B,KAAK;AAAO,eAAO,CAAC,KAAK,IAAI;AAAA,MAC7B,KAAK;AAAQ,eAAO,CAAC,MAAM,GAAG;AAAA,MAC9B,KAAK;AAAQ,eAAO,CAAC,KAAK,IAAI;AAAA,MAC9B;AAAS,eAAO,CAAC,MAAM,IAAI;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,UAAiE;AACtF,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AAAA,EAEA,aAAa,OAAwB;AACnC,WAAO,UAAU,KAAK;AAAA,EACxB;AAAA,EAEA,kBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,qBAA+B;AAC7B,WAAO,CAAC,KAAK,KAAK;AAAA,EACpB;AAAA,EAEA,uBAAiC;AAC/B,WAAO,CAAC,OAAO,OAAO,OAAO,OAAO,QAAQ,MAAM;AAAA,EACpD;AACF;;;AC/IO,IAAM,WAAsB;AAAA,EACjC;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ,OAAO,QAAgB,KAAkB,SAAmB;AAClE,YAAM,SAAS,OAAO,SAAS;AAC/B,YAAM,WAAW,MAAM,IAAI,gBAAgB,MAAM;AACjD,YAAM,eAAe,MAAM,IAAI,gBAAgB,MAAM;AACrD,YAAM,iBAAiB,UAAU,WAAW,QAAQ,IAAI,OACjC,UAAU,iBAAiB,QAAQ,IAAI;AAC9D,YAAM,IAAI,wBAAwB,QAAQ,cAAc;AAAA,IAC1D;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ,OAAO,QAAgB,KAAkB,SAAmB;AAClE,YAAM,SAAS,OAAO,SAAS;AAC/B,YAAM,kBAAkB,MAAM,IAAI,gBAAgB,MAAM;AACxD,YAAM,WAAW;AAAA,QACf,iBAAiB;AAAA,UACf;AAAA,YACE,EAAE,MAAM,8BAAgB,eAAe,UAAU;AAAA,YACjD,EAAE,MAAM,mCAAW,eAAe,UAAU;AAAA,YAC5C,EAAE,MAAM,iCAAgB,eAAe,UAAU;AAAA,UACnD;AAAA,QACF;AAAA,MACF;AACA,YAAM,IAAI,YAAY,QAAQ,UAAU,mBAAmB,eAAe,GAAG,EAAE,cAAc,KAAK,UAAU,QAAQ,EAAE,CAAC;AAAA,IACzH;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ,OAAO,QAAgB,KAAkB,SAAmB;AAClE,YAAM,SAAS,OAAO,SAAS;AAC/B,YAAM,WAAW,MAAM,IAAI,gBAAgB,MAAM;AACjD,YAAM,SAAS,UAAU,IAAI,KAAK,CAAC;AACnC,YAAM,kBAAkB;AAAA,QACtB,GAAG,OAAO;AAAA,QACV,GAAG,OAAO;AAAA,QACV,GAAG,OAAO;AAAA,QACV,GAAG,OAAO;AAAA;AAAA,MACZ;AACA,YAAM,WAAW;AAAA,QACf,iBAAiB,gBAAgB,IAAI,WAAS,CAAC,EAAC,MAAM,OAAO,eAAe,SAAS,QAAO,CAAC,CAAC;AAAA,MAChG;AACA,YAAM,IAAI,YAAY,QAAQ,UAAU,gBAAgB,QAAQ,GAAG,EAAE,cAAc,KAAK,UAAU,QAAQ,EAAE,CAAC;AAAA,IAC/G;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ,OAAO,QAAgB,KAAkB,SAAmB;AAClE,YAAM,SAAS,OAAO,SAAS;AAC/B,YAAM,IAAI,aAAa,MAAM;AAAA,IAC/B;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ,OAAO,QAAgB,KAAkB,SAAmB;AAClE,YAAM,SAAS,OAAO,SAAS;AAC/B,YAAM,WAAW,MAAM,IAAI,gBAAgB,MAAM;AACjD,YAAM,UAAU,MAAM,IAAI,iBAAiB,MAAM;AACjD,YAAM,IAAI,YAAY,QAAQ,WAAW,UAAU,cAAc,QAAQ,CAAC;AAAA,IAC5E;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ,OAAO,QAAgB,KAAkB,SAAmB;AAClE,YAAM,SAAS,OAAO,SAAS;AAC/B,YAAM,WAAW,MAAM,IAAI,gBAAgB,MAAM;AACjD,UAAI,cAAc,UAAU,cAAc,QAAQ,IAAI;AAEtD,iBAAW,WAAW,UAAU;AAC9B,cAAM,iBAAiB,GAAG,QAAQ;AAElC,uBAAe,IAAI,QAAQ,UAAU,UAAU,gBAAgB,QAAQ;AAAA;AAAA,MACzE;AAGA,YAAM,IAAI,YAAY,QAAQ,WAAW;AAAA,IAC3C;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ,OAAO,QAAgB,KAAkB,SAAmB;AAClE,YAAM,SAAS,OAAO,SAAS;AAC/B,YAAM,WAAW,MAAM,IAAI,gBAAgB,MAAM;AAEjD,UAAI,CAAC,KAAK,QAAQ;AAChB,cAAM,IAAI,wBAAwB,QAAQ,UAAU,yBAAyB,QAAQ,CAAC;AACtF;AAAA,MACF;AAEA,YAAM,aAAa,CAAC,aAAa,aAAa,WAAW;AACzD,YAAM,UAAU,KAAK,KAAK,SAAS,CAAC,EAAE,YAAY;AAClD,UAAI;AACJ,UAAI;AAEJ,UAAI,WAAW,SAAS,OAAO,GAAG;AAChC,eAAO;AACP,iBAAS,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AAAA,MACrC,OAAO;AACL,eAAO;AACP,iBAAS,KAAK,KAAK,GAAG;AAGtB,YAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG;AAClD,gBAAM,cAAc,WAAW,IAAI,OAAK,KAAK,KAAK,EAAE,KAAK,IAAI;AAC7D,gBAAM,IAAI,YAAY,QAAQ,UAAU,gBAAgB,QAAQ,IAAI,WAAW;AAC/E;AAAA,QACF;AAAA,MACF;AAEA,UAAI;AACF,cAAM,eAAe,QAAQ,gBAAgB,IAAI,KAAK,CAAC;AACvD,cAAM,WAAW,IAAI,mBAAmB,IAAI,KAAK,CAAC;AAClD,cAAM,WAAW,MAAM,SAAS,cAAc,QAAQ,IAAI;AAC1D,cAAM,IAAI,UAAU,QAAQ,UAAU,EAAE,SAAS,OAAO,CAAC;AAAA,MAC3D,SAAS,OAAP;AACA,gBAAQ,MAAM,2BAA2B,KAAK;AAC9C,cAAM,IAAI,YAAY,QAAQ,UAAU,0BAA0B,QAAQ,CAAC;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ,OAAO,QAAgB,KAAkB,SAAmB;AAClE,YAAM,SAAS,OAAO,SAAS;AAC/B,YAAM,WAAW,MAAM,IAAI,gBAAgB,MAAM;AAEjD,UAAI,CAAC,KAAK,QAAQ;AAChB,cAAM,IAAI,YAAY,QAAQ,UAAU,cAAc,QAAQ,CAAC;AAC/D;AAAA,MACF;AAEA,UAAI,cAAc;AAClB,UAAI;AAEJ,YAAM,UAAU,IAAI,QAAQ,IAAI,KAAK,CAAC;AACtC,YAAM,cAAc,QAAQ,qBAAqB;AAEjD,UAAI,YAAY,SAAS,KAAK,KAAK,SAAS,CAAC,CAAC,GAAG;AAC/C,sBAAc,KAAK,KAAK,SAAS,CAAC;AAClC,iBAAS,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AAAA,MACrC,OAAO;AACL,iBAAS,KAAK,KAAK,GAAG;AAAA,MACxB;AAEA,UAAI;AACF,cAAM,eAAe,QAAQ,gBAAgB,IAAI,KAAK,CAAC;AAEvD,cAAM,EAAE,WAAW,gBAAgB,IAAI,MAAM,QAAQ,cAAc,QAAQ,WAAW;AAEtF,cAAM,SAAS,UAAU,IAAI,KAAK,CAAC;AACnC,YAAI,UAAU,GAAG,UAAU,mBAAmB,QAAQ,MAAM;AAAA;AAC5D,mBAAW,GAAG,UAAU,eAAe,QAAQ,MAAM;AAAA;AAErD,YAAI,OAAO,sBAAsB,iBAAiB;AAChD,qBAAW,GAAG,UAAU,2BAA2B,QAAQ,MAAM,OAAO,iBAAiB;AAAA;AACzF,qBAAW,GAAG,UAAU,oBAAoB,QAAQ,MAAM;AAAA;AAAA,QAC5D;AAEA,cAAM,IAAI,UAAU,QAAQ,WAAW,EAAE,QAAiB,CAAC;AAAA,MAC7D,SAAS,OAAP;AACA,gBAAQ,MAAM,wCAAwC,WAAW,KAAK;AACtE,YAAI,iBAAiB,OAAO;AAC1B,kBAAQ,MAAM,kBAAkB,MAAM,OAAO;AAAA,QAC/C;AACA,cAAM,IAAI,YAAY,QAAQ,UAAU,0BAA0B,QAAQ,CAAC;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AACF;;;AC5LO,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,KAAU;AACpB,SAAK,SAAS,UAAU,GAAG;AAC3B,SAAK,MAAM,KAAK,OAAO;AACvB,SAAK,QAAQ,KAAK,OAAO;AAAA,EAC3B;AAAA,EAEA,MAAM,IAAI,KAAqC;AAC7C,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,WAAW,OAAO;AAAA,MACrD,SAAS;AAAA,QACP,eAAe,UAAU,KAAK;AAAA,MAChC;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,UAAI,SAAS,WAAW,KAAK;AAC3B,eAAO;AAAA,MACT;AACA,YAAM,IAAI,MAAM,uBAAuB,SAAS,QAAQ;AAAA,IAC1D;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,IAAI,KAAa,OAAe,KAA6B;AACjE,UAAM,MAAM,MACR,GAAG,KAAK,WAAW,OAAO,YAAY,QACtC,GAAG,KAAK,WAAW,OAAO;AAE9B,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU,KAAK;AAAA,MAChC;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,uBAAuB,SAAS,QAAQ;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,KAA4B;AACpC,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,WAAW,OAAO;AAAA,MACrD,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU,KAAK;AAAA,MAChC;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,uBAAuB,SAAS,QAAQ;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,QAAgB,UAAiC;AACjE,UAAM,KAAK,IAAI,YAAY,UAAU,UAAU,KAAK,OAAO,WAAW;AAAA,EACxE;AAAA,EAEA,MAAM,cAAc,QAAgB,YAAmC;AACrE,UAAM,MAAM,WAAW;AACvB,UAAM,kBAAkB,MAAM,KAAK,IAAI,GAAG;AAC1C,UAAM,iBAAiB,kBACnB,GAAG;AAAA,EAAoB,eACvB;AACJ,UAAM,KAAK,IAAI,KAAK,gBAAgB,KAAK,OAAO,UAAU;AAAA,EAC5D;AACF;;;AC1DO,IAAM,YAAN,MAA6C;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,KAAU;AACpB,UAAM,SAAS,UAAU,GAAG;AAC5B,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO,sBAAsB;AAC5C,SAAK,SAAS,OAAO;AACrB,SAAK,eAAe,KAAK,OAAO,CAAC;AAAA,EACnC;AAAA,EAEA,MAAM,iBAAiB,UAAqB,OAAiC;AAC3E,UAAM,WAAW,SAAS,KAAK;AAC/B,YAAQ,IAAI,0CAA0C,UAAU;AAChE,UAAM,MAAM,GAAG,KAAK,kBAAkB,gCAAgC,KAAK;AAE3E,UAAM,iBAAkC,SACrC,OAAO,SAAO,IAAI,SAAS,QAAQ,EACnC,IAAI,UAAQ;AAAA,MACX,MAAM,IAAI,SAAS,cAAc,UAAU;AAAA,MAC3C,OAAO,CAAC,EAAE,MAAM,IAAI,QAAQ,CAAC;AAAA,IAC/B,EAAE;AAEJ,UAAM,cAAc;AAAA,MAClB,UAAU;AAAA,MACV,kBAAkB;AAAA,QAChB,aAAa;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,QACN,iBAAiB;AAAA,MACnB;AAAA,IACF;AAEA,YAAQ,IAAI,iBAAiB,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AAEjE,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,WAAW;AAAA,IAClC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAQ,MAAM,qBAAqB,SAAS,cAAc,SAAS;AACnE,YAAM,IAAI,MAAM,qBAAqB,SAAS;AAAA,EAAe,WAAW;AAAA,IAC1E;AAEA,UAAM,OAAuB,MAAM,SAAS,KAAK;AACjD,YAAQ,IAAI,8BAA8B;AAC1C,QAAI,CAAC,KAAK,cAAc,KAAK,WAAW,WAAW,GAAG;AACpD,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AACA,UAAM,gBAAgB,KAAK,WAAW,CAAC,EAAE,QAAQ,MAAM,CAAC,EAAE,KAAK,KAAK;AACpE,YAAQ,IAAI,0BAA0B,cAAc,QAAQ;AAC5D,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,OAAwB;AACnC,WAAO,KAAK,OAAO,SAAS,KAAK;AAAA,EACnC;AAAA,EAEA,kBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,qBAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AAEA,IAAO,iBAAQ;;;AClFR,IAAM,UAAN,MAA2C;AAAA,EACxC;AAAA,EACA,UAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EAER,YAAY,KAAU;AACpB,UAAM,SAAS,UAAU,GAAG;AAC5B,SAAK,SAAS,OAAO;AACrB,SAAK,SAAS,OAAO;AACrB,SAAK,eAAe,KAAK,OAAO,CAAC;AAAA,EACnC;AAAA,EAEA,MAAM,iBAAiB,UAAqB,OAAiC;AAC3E,UAAM,WAAW,SAAS,KAAK;AAC/B,YAAQ,IAAI,wCAAwC,UAAU;AAC9D,UAAM,MAAM,GAAG,KAAK;AAEpB,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB,UAAU,KAAK;AAAA,MAClC;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO;AAAA,QACP;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAQ,MAAM,mBAAmB,SAAS,cAAc,SAAS;AACjE,YAAM,IAAI,MAAM,mBAAmB,SAAS;AAAA,EAAe,WAAW;AAAA,IACxE;AAEA,UAAM,OAAqB,MAAM,SAAS,KAAK;AAC/C,YAAQ,IAAI,4BAA4B;AACxC,QAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,WAAW,GAAG;AAC9C,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AACA,UAAM,gBAAgB,KAAK,QAAQ,CAAC,EAAE,QAAQ,QAAQ,KAAK;AAC3D,YAAQ,IAAI,0BAA0B,cAAc,QAAQ;AAC5D,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,OAAwB;AACnC,WAAO,KAAK,OAAO,SAAS,KAAK;AAAA,EACnC;AAAA,EAEA,kBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,qBAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AAEA,IAAO,eAAQ;;;AC7DR,IAAM,YAAN,MAA6C;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,KAAU;AACpB,UAAM,SAAS,UAAU,GAAG;AAC5B,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO,kBAAkB;AACxC,SAAK,SAAS,OAAO;AACrB,SAAK,eAAe,KAAK,OAAO,CAAC;AAAA,EACnC;AAAA,EAEA,MAAM,iBAAiB,UAAqB,OAAiC;AAC3E,UAAM,WAAW,SAAS,KAAK;AAC/B,YAAQ,IAAI,0CAA0C,UAAU;AAChE,UAAM,MAAM,GAAG,KAAK;AAEpB,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,aAAa,KAAK;AAAA,QAClB,qBAAqB;AAAA,MACvB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO;AAAA,QACP,UAAU,SAAS,IAAI,UAAQ;AAAA,UAC7B,MAAM,IAAI,SAAS,cAAc,cAAc;AAAA,UAC/C,SAAS,IAAI;AAAA,QACf,EAAE;AAAA,QACF,YAAY;AAAA,MACd,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAQ,MAAM,qBAAqB,SAAS,cAAc,SAAS;AACnE,YAAM,IAAI,MAAM,qBAAqB,SAAS;AAAA,EAAe,WAAW;AAAA,IAC1E;AAEA,UAAM,OAAuB,MAAM,SAAS,KAAK;AACjD,YAAQ,IAAI,8BAA8B;AAC1C,QAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,WAAW,GAAG;AAC9C,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AACA,UAAM,gBAAgB,KAAK,QAAQ,CAAC,EAAE,KAAK,KAAK;AAChD,YAAQ,IAAI,0BAA0B,cAAc,QAAQ;AAC5D,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,OAAwB;AACnC,WAAO,KAAK,OAAO,SAAS,KAAK;AAAA,EACnC;AAAA,EAEA,kBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,qBAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AAEA,IAAO,iBAAQ;;;AC/DR,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,KAAU;AACpB,UAAM,SAAS,UAAU,GAAG;AAC5B,SAAK,QAAQ,OAAO;AACpB,SAAK,SAAS,+BAA+B,KAAK;AAClD,SAAK,mBAAmB,OAAO;AAC/B,SAAK,gBAAgB,OAAO;AAC5B,SAAK,MAAM;AACX,SAAK,WAAW;AAChB,SAAK,QAAQ,IAAI,YAAY,GAAG;AAChC,SAAK,WAAW,IAAI,mBAAU,GAAG;AAAA,EACnC;AAAA,EAEA,MAAc,mBAAmB,QAA4C;AAC3E,UAAM,eAAe,MAAM,KAAK,gBAAgB,MAAM;AACtD,YAAQ,IAAI,+BAA+B,cAAc;AAEzD,UAAM,SAAS,UAAU,KAAK,GAAG;AAEjC,QAAI,OAAO,aAAa,SAAS,YAAY,GAAG;AAC9C,aAAO,IAAI,mBAAU,KAAK,GAAG;AAAA,IAC/B,WAAW,OAAO,aAAa,SAAS,YAAY,GAAG;AACrD,aAAO,IAAI,eAAU,KAAK,GAAG;AAAA,IAC/B,WAAW,OAAO,WAAW,SAAS,YAAY,GAAG;AACnD,aAAO,IAAI,aAAQ,KAAK,GAAG;AAAA,IAC7B,WAAW,OAAO,aAAa,SAAS,YAAY,GAAG;AACrD,aAAO,IAAI,eAAU,KAAK,GAAG;AAAA,IAC/B;AAGA,YAAQ,KAAK,kBAAkB,2CAA2C;AAC1E,WAAO,IAAI,mBAAU,KAAK,GAAG;AAAA,EAC/B;AAAA,EAEA,MAAa,eAAe,aAAqB,QAAgB,MAA+B;AAC9F,UAAM,UAAU,KAAK,SAAS,KAAK,SAAO,IAAI,SAAS,WAAW;AAClE,QAAI,SAAS;AACX,YAAM,QAAQ,OAAO,QAAQ,MAAM,IAAI;AAAA,IACzC,OAAO;AACL,cAAQ,IAAI,oBAAoB,aAAa;AAC7C,YAAM,WAAW,MAAM,KAAK,gBAAgB,OAAO,SAAS,CAAC;AAE7D,YAAM,KAAK,YAAY,QAAQ,UAAU,qBAAqB,QAAQ,CAAC;AAAA,IACzE;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,QAAgB,MAAc,UAAuE,CAAC,GAA+C;AACrK,UAAM,WAAW,aAAa,IAAI;AAClC,UAAM,UAA6C,CAAC;AAEpD,eAAW,WAAW,UAAU;AAC9B,YAAM,MAAM,GAAG,KAAK;AACpB,cAAQ,IAAI,iCAAiC,QAAQ,SAAS;AAC9D,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,KAAK;AAAA,UAChC,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,UAClB;AAAA,UACA,MAAM,KAAK,UAAU;AAAA,YACnB,SAAS;AAAA,YACT,MAAM;AAAA,YACN,YAAY,QAAQ;AAAA;AAAA,YACpB,cAAc,QAAQ;AAAA,UACxB,CAAC;AAAA,QACH,CAAC;AAED,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,YAAY,MAAM,SAAS,KAAK;AACtC,kBAAQ,MAAM,uBAAuB,SAAS,cAAc,SAAS;AACrE,gBAAM,IAAI,MAAM,uBAAuB,SAAS;AAAA,EAAe,WAAW;AAAA,QAC5E;AAEA,cAAM,SAAS,MAAM,SAAS,KAAK;AACnC,gBAAQ,KAAK,MAAM;AAAA,MACrB,SAAS,OAAP;AACA,gBAAQ,MAAM,+BAA+B,KAAK;AAClD,cAAM;AAAA,MACR;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,aAAa,QAA6C;AAC9D,QAAI,OAAO,gBAAgB;AACzB,YAAM,KAAK,oBAAoB,OAAO,cAAc;AAAA,IACtD,WAAW,OAAO,WAAW,OAAO,QAAQ,MAAM;AAChD,YAAM,SAAS,OAAO,QAAQ,KAAK;AACnC,YAAM,SAAS,OAAO,QAAQ,MAAM,IAAI,SAAS;AACjD,UAAI,CAAC,QAAQ;AACX,gBAAQ,MAAM,sBAAsB;AACpC;AAAA,MACF;AACA,YAAM,OAAO,OAAO,QAAQ;AAC5B,YAAM,WAAW,MAAM,KAAK,gBAAgB,MAAM;AAElD,UAAI,KAAK,kBAAkB,MAAM,GAAG;AAClC,YAAI,KAAK,WAAW,GAAG,GAAG;AACxB,gBAAM,CAAC,aAAa,GAAG,IAAI,IAAI,KAAK,MAAM,CAAC,EAAE,MAAM,GAAG;AACtD,gBAAM,KAAK,eAAe,aAAa,QAAQ,IAAI;AAAA,QACrD,OAAO;AACL,cAAI;AACF,kBAAM,eAAe,QAAQ,UAAU,KAAK,GAAG;AAC/C,iBAAK,WAAW,MAAM,KAAK,mBAAmB,MAAM;AACpD,kBAAM,UAAU,MAAM,KAAK,WAAW,MAAM;AAC5C,kBAAM,eAAe,MAAM,KAAK,gBAAgB,MAAM;AAEtD,gBAAI,WAAsB,CAAC;AAC3B,gBAAI,aAAa,WAAW,SAAS,GAAG;AACtC,yBAAW;AAAA,gBACT,GAAI,UAAU,CAAC,EAAE,MAAM,QAAiB,SAAS,QAAQ,CAAC,IAAI,CAAC;AAAA,gBAC/D,EAAE,MAAM,QAAiB,SAAS,KAAK;AAAA,cACzC;AAAA,YACF,OAAO;AACL,yBAAW;AAAA,gBACT,EAAE,MAAM,UAAmB,SAAS,KAAK,cAAc;AAAA,gBACvD,GAAI,UAAU,CAAC,EAAE,MAAM,QAAiB,SAAS,QAAQ,CAAC,IAAI,CAAC;AAAA,gBAC/D,EAAE,MAAM,QAAiB,SAAS,KAAK;AAAA,cACzC;AAAA,YACF;AAEA,oBAAQ,IAAI,0BAA0B,KAAK,SAAS,YAAY,MAAM;AACtE,oBAAQ,IAAI,mCAAmC,cAAc;AAC7D,kBAAM,WAAW,MAAM,KAAK,SAAS,iBAAiB,UAAU,YAAY;AAC5E,oBAAQ,IAAI,8BAA8B,SAAS,QAAQ;AAC3D,kBAAM,oBAAoB,KAAK,eAAe,QAAQ;AAEtD,oBAAQ,IAAI,8BAA8B,kBAAkB,QAAQ;AAEpE,kBAAM,KAAK,wBAAwB,QAAQ,iBAAiB;AAE5D,kBAAM,KAAK,aAAa,QAAQ,SAAS;AAAA,aAAoB,UAAU;AAAA,UACzE,SAAS,OAAP;AACA,oBAAQ,MAAM,0BAA0B,KAAK;AAC7C,kBAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAE9D,kBAAM,KAAK,YAAY,QAAQ,UAAU,SAAS,QAAQ,IAAI,OAAO,YAAY;AAAA,UACnF;AAAA,QACF;AAAA,MACF,OAAO;AAEL,cAAM,KAAK,wBAAwB,QAAQ,UAAU,gBAAgB,QAAQ,CAAC;AAAA,MAChF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,oBAAoB,eAA2D;AACnF,UAAM,SAAS,cAAc,SAAS,KAAK;AAC3C,UAAM,SAAS,cAAc,KAAK,GAAG,SAAS;AAC9C,UAAM,OAAO,cAAc;AAE3B,QAAI,CAAC,UAAU,CAAC;AAAM;AAEtB,QAAI,KAAK,WAAW,OAAO,GAAG;AAC5B,YAAM,cAAc,KAAK,MAAM,GAAG,EAAE,CAAC;AACrC,YAAM,KAAK,gBAAgB,QAAQ,WAAW;AAC9C,YAAM,KAAK,wBAAwB,QAAQ,UAAU,oBAAoB,WAAW,IAAI,UAAU,YAAY,eAAe,WAAW,CAAC;AAAA,IAC3I,WAAW,KAAK,WAAW,QAAQ,GAAG;AACpC,YAAM,WAAW,KAAK,MAAM,GAAG,EAAE,CAAC;AAClC,YAAM,KAAK,gBAAgB,QAAQ,QAAQ;AAC3C,YAAM,WAAW,MAAM,KAAK,gBAAgB,MAAM;AAClD,YAAM,KAAK,wBAAwB,QAAQ,UAAU,iBAAiB,QAAQ,IAAI,QAAQ;AAC1F,YAAM,KAAK,aAAa,MAAM;AAAA,IAChC;AAGA,UAAM,MAAM,GAAG,KAAK,8BAA8B;AAAA,MAChD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,mBAAmB,cAAc,GAAG,CAAC;AAAA,IAC9D,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,gBAAgB,QAA6C;AACjE,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,YAAY,QAAQ;AAC1D,WAAQ,YAAmC;AAAA,EAC7C;AAAA,EAEA,MAAM,gBAAgB,QAAgB,UAA6C;AACjF,UAAM,KAAK,MAAM,YAAY,QAAQ,QAAQ;AAAA,EAC/C;AAAA,EAEA,MAAM,gBAAgB,QAAiC;AACrD,UAAM,QAAQ,MAAM,KAAK,MAAM,IAAI,SAAS,QAAQ;AACpD,WAAO,SAAS,KAAK,SAAS,gBAAgB;AAAA,EAChD;AAAA,EAEA,MAAM,gBAAgB,QAAgB,OAA8B;AAClE,UAAM,KAAK,MAAM,IAAI,SAAS,UAAU,KAAK;AAC7C,YAAQ,IAAI,uBAAuB,OAAO;AAE1C,SAAK,WAAW,MAAM,KAAK,mBAAmB,MAAM;AACpD,YAAQ,IAAI,0BAA0B,KAAK,SAAS,YAAY,MAAM;AAAA,EACxE;AAAA,EAEA,qBAA+B;AAC7B,WAAO,KAAK,SAAS,mBAAmB;AAAA,EAC1C;AAAA,EAEA,aAAa,OAAwB;AACnC,WAAO,KAAK,SAAS,aAAa,KAAK;AAAA,EACzC;AAAA,EAEA,MAAM,aAAa,QAAgB,SAAgC;AACjE,UAAM,KAAK,MAAM,cAAc,QAAQ,OAAO;AAAA,EAChD;AAAA,EAEA,MAAM,WAAW,QAAwC;AACvD,WAAO,MAAM,KAAK,MAAM,IAAI,WAAW,QAAQ;AAAA,EACjD;AAAA,EAEA,MAAM,aAAa,QAA+B;AAChD,UAAM,KAAK,MAAM,IAAI,WAAW,QAAQ;AACxC,UAAM,WAAW,MAAM,KAAK,gBAAgB,MAAM;AAClD,UAAM,KAAK,wBAAwB,SAAS,MAAM,GAAG,UAAU,oBAAoB,QAAQ,CAAC;AAAA,EAC9F;AAAA,EAEA,MAAM,iBAAiB,QAAiC;AAEtD,SAAK,WAAW,MAAM,KAAK,mBAAmB,MAAM;AAEpD,UAAM,UAAU,MAAM,KAAK,WAAW,MAAM;AAC5C,UAAM,WAAW,MAAM,KAAK,gBAAgB,MAAM;AAClD,QAAI,CAAC,SAAS;AACZ,aAAO,UAAU,cAAc,QAAQ;AAAA,IACzC;AACA,UAAM,gBAAgB;AAAA,MACpB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,eAAe,MAAM,KAAK,gBAAgB,MAAM;AACtD,YAAQ,IAAI,mCAAmC,cAAc;AAE7D,QAAI;AACJ,QAAI,aAAa,WAAW,SAAS,GAAG;AAEtC,iBAAW;AAAA,QACT,EAAE,MAAM,QAAQ,SAAS,kDAAkD,cAAc,QAAQ;AAAA;AAAA,EAAS,UAAU;AAAA,MACtH;AAAA,IACF,OAAO;AAEL,iBAAW;AAAA,QACT,EAAE,MAAM,UAAU,SAAS,2CAA2C,cAAc,QAAQ,KAAK;AAAA,QACjG,EAAE,MAAM,QAAQ,SAAS,QAAQ;AAAA,MACnC;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,KAAK,SAAS,iBAAiB,UAAU,YAAY;AAC3E,WAAO,GAAG,UAAU,mBAAmB,QAAQ;AAAA;AAAA,EAAQ;AAAA,EACzD;AAAA,EAEA,eAAe,UAA0B;AACvC,UAAM,iBAAiB;AACvB,WAAO,SAAS,QAAQ,gBAAgB,CAAC,OAAO,UAAU,SAAS;AACjE,aAAO,gBAAgB,KAAK,KAAK,GAAG,YAAY,EAAE;AAAA,IACpD,CAAC;AAAA,EACH;AAAA,EAEA,kBAAkB,QAAyB;AACzC,WAAO,KAAK,iBAAiB,SAAS,MAAM;AAAA,EAC9C;AAAA,EAEA,MAAM,cAAc,SAAqC;AACvD,QAAI,QAAQ,WAAW,QAAQ;AAC7B,aAAO,IAAI,SAAS,sBAAsB,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC3D;AAEA,QAAI;AACF,YAAM,SAA+B,MAAM,QAAQ,KAAK;AACxD,YAAM,KAAK,aAAa,MAAM;AAC9B,aAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC3C,SAAS,OAAP;AACA,cAAQ,MAAM,6BAA6B,KAAK;AAChD,aAAO,IAAI,SAAS,yBAAyB,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC9D;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,QAAgB,OAA4B,UAAgC,CAAC,GAAkB;AAC7G,UAAM,MAAM,GAAG,KAAK;AACpB,UAAM,WAAW,IAAI,SAAS;AAC9B,aAAS,OAAO,WAAW,OAAO,SAAS,CAAC;AAE5C,QAAI,OAAO,UAAU,UAAU;AAC7B,eAAS,OAAO,SAAS,KAAK;AAAA,IAChC,OAAO;AACL,YAAM,OAAO,IAAI,KAAK,CAAC,KAAK,GAAG,EAAE,MAAM,YAAY,CAAC;AACpD,eAAS,OAAO,SAAS,MAAM,WAAW;AAAA,IAC5C;AAEA,QAAI,QAAQ,SAAS;AACnB,eAAS,OAAO,WAAW,QAAQ,OAAO;AAAA,IAC5C;AAEA,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,uBAAuB,SAAS,QAAQ;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,KAA4B;AAC3C,UAAM,gBAAgB,GAAG,KAAK;AAC9B,UAAM,WAAW,MAAM,MAAM,eAAe;AAAA,MAC1C,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,IAAI,CAAC;AAAA,IAC9B,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,MAAM,0BAA0B,SAAS,YAAY;AAAA,IACjE;AAEA,UAAM,SAAgD,MAAM,SAAS,KAAK;AAC1E,QAAI,CAAC,OAAO,IAAI;AACd,YAAM,IAAI,MAAM,uBAAuB,OAAO,aAAa;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,MAAM,wBAAwB,QAAgB,MAA0D;AACtG,UAAM,WAAW,aAAa,IAAI;AAClC,UAAM,UAA6C,CAAC;AAEpD,eAAW,WAAW,UAAU;AAC9B,UAAI;AAEF,cAAM,SAAS,MAAM,KAAK,YAAY,QAAQ,SAAS,EAAE,YAAY,WAAW,CAAC;AACjF,gBAAQ,KAAK,GAAG,MAAM;AAAA,MACxB,SAAS,OAAP;AACA,gBAAQ,MAAM,oEAAoE,KAAK;AAEvF,cAAM,kBAAkB,MAAM,KAAK,YAAY,QAAQ,OAAO;AAC9D,gBAAQ,KAAK,GAAG,eAAe;AAAA,MACjC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;AAEA,IAAO,mBAAQ;;;AC5Wf,IAAO,cAAQ;AAAA,EACb,MAAM,MAAM,SAAkB,KAAU,KAA0C;AAChF,UAAM,MAAM,IAAI,iBAAY,GAAG;AAC/B,UAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAE/B,YAAQ,IAAI,8BAA8B,IAAI,UAAU;AAExD,QAAI;AAEF,UAAI,IAAI,aAAa,YAAY;AAC/B,gBAAQ,IAAI,4BAA4B;AACxC,eAAO,MAAM,IAAI,cAAc,OAAO;AAAA,MACxC;AAGA,UAAI,IAAI,aAAa,OAAO,IAAI,aAAa,IAAI;AAC/C,gBAAQ,IAAI,mBAAmB;AAC/B,eAAO,IAAI,SAAS,4CAA4C;AAAA,UAC9D,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,aAAa;AAAA,QAC1C,CAAC;AAAA,MACH;AAGA,cAAQ,IAAI,gBAAgB;AAC5B,aAAO,IAAI,SAAS,aAAa;AAAA,QAC/B,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,aAAa;AAAA,MAC1C,CAAC;AAAA,IACH,SAAS,OAAP;AACA,cAAQ,MAAM,6BAA6B,KAAK;AAChD,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,aAAO,IAAI,SAAS,0BAA0B,gBAAgB;AAAA,QAC5D,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,aAAa;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF;AACF;", + "sourcesContent": ["export interface Env {\r\n OPENAI_API_KEY: string;\r\n OPENAI_BASE_URL: string;\r\n OPENAI_MODELS: string; // Comma-separated list of available OpenAI models\r\n TELEGRAM_BOT_TOKEN: string;\r\n WHITELISTED_USERS: string; // Comma-separated list of allowed Telegram user IDs\r\n SYSTEM_INIT_MESSAGE: string;\r\n SYSTEM_INIT_MESSAGE_ROLE: string;\r\n DEFAULT_MODEL?: string; // Optional default model\r\n UPSTASH_REDIS_REST_URL: string;\r\n UPSTASH_REDIS_REST_TOKEN: string;\r\n DALL_E_MODEL?: string;\r\n CLOUDFLARE_API_TOKEN: string;\r\n CLOUDFLARE_ACCOUNT_ID: string;\r\n FLUX_STEPS: string;\r\n PROMPT_OPTIMIZATION?: string;\r\n EXTERNAL_API_BASE?: string;\r\n EXTERNAL_MODEL?: string;\r\n EXTERNAL_API_KEY?: string;\r\n GOOGLE_MODEL_KEY: string;\r\n GOOGLE_MODEL_BASEURL?: string;\r\n GOOGLE_MODELS: string;\r\n GROQ_API_KEY: string;\r\n GROQ_MODELS: string;\r\n CLAUDE_API_KEY: string;\r\n CLAUDE_MODELS: string;\r\n CLAUDE_ENDPOINT?: string;\r\n AZURE_API_KEY: string; // Azure API \u5BC6\u94A5\r\n AZURE_MODELS: string; // \u9017\u53F7\u5206\u9694\u7684 Azure \u6A21\u578B\u5217\u8868\r\n AZURE_ENDPOINT: string; // Azure API \u7AEF\u70B9\r\n}\r\n\r\nconst getEnvOrDefault = (env: Env, key: keyof Env, defaultValue: string): string => {\r\n return (env[key] as string) || defaultValue;\r\n};\r\n\r\nexport const getConfig = (env: Env) => {\r\n // \u68C0\u67E5\u662F\u5426\u81F3\u5C11\u6709\u4E00\u4E2A\u6A21\u578B\u7684 API \u5BC6\u94A5\u88AB\u8BBE\u7F6E\r\n const hasOpenAI = !!env.OPENAI_API_KEY;\r\n const hasGoogle = !!env.GOOGLE_MODEL_KEY;\r\n const hasGroq = !!env.GROQ_API_KEY;\r\n const hasClaude = !!env.CLAUDE_API_KEY;\r\n const hasAzure = !!env.AZURE_API_KEY;\r\n\r\n if (!hasOpenAI && !hasGoogle && !hasGroq && !hasClaude && !hasAzure) {\r\n throw new Error('At least one model API key must be set (OpenAI, Google, Groq, Claude, or Azure)');\r\n }\r\n\r\n return {\r\n openaiApiKey: env.OPENAI_API_KEY,\r\n openaiBaseUrl: getEnvOrDefault(env, 'OPENAI_BASE_URL', 'https://api.openai.com/v1'),\r\n openaiModels: env.OPENAI_MODELS ? env.OPENAI_MODELS.split(',').map(model => model.trim()) : [],\r\n telegramBotToken: env.TELEGRAM_BOT_TOKEN,\r\n whitelistedUsers: env.WHITELISTED_USERS ? env.WHITELISTED_USERS.split(',').map(id => id.trim()) : [],\r\n systemInitMessage: getEnvOrDefault(env, 'SYSTEM_INIT_MESSAGE', 'You are a helpful assistant.'),\r\n systemInitMessageRole: getEnvOrDefault(env, 'SYSTEM_INIT_MESSAGE_ROLE', 'system'),\r\n defaultModel: env.DEFAULT_MODEL,\r\n upstashRedisRestUrl: env.UPSTASH_REDIS_REST_URL,\r\n upstashRedisRestToken: env.UPSTASH_REDIS_REST_TOKEN,\r\n dallEModel: getEnvOrDefault(env, 'DALL_E_MODEL', 'dall-e-3'),\r\n languageTTL: 60 * 60 * 24 * 365,\r\n contextTTL: 60 * 60 * 24 * 30,\r\n cloudflareApiToken: env.CLOUDFLARE_API_TOKEN,\r\n cloudflareAccountId: env.CLOUDFLARE_ACCOUNT_ID,\r\n fluxSteps: parseInt(getEnvOrDefault(env, 'FLUX_STEPS', '4')),\r\n promptOptimization: getEnvOrDefault(env, 'PROMPT_OPTIMIZATION', 'false') === 'true',\r\n externalApiBase: env.EXTERNAL_API_BASE,\r\n externalModel: env.EXTERNAL_MODEL,\r\n externalApiKey: env.EXTERNAL_API_KEY,\r\n googleModelKey: env.GOOGLE_MODEL_KEY,\r\n googleModelBaseUrl: getEnvOrDefault(env, 'GOOGLE_MODEL_BASEURL', 'https://generativelanguage.googleapis.com/v1beta'),\r\n googleModels: env.GOOGLE_MODELS ? env.GOOGLE_MODELS.split(',').map(model => model.trim()) : [],\r\n groqApiKey: env.GROQ_API_KEY,\r\n groqModels: env.GROQ_MODELS ? env.GROQ_MODELS.split(',').map(model => model.trim()) : [],\r\n claudeApiKey: env.CLAUDE_API_KEY,\r\n claudeModels: env.CLAUDE_MODELS ? env.CLAUDE_MODELS.split(',').map(model => model.trim()) : [],\r\n claudeEndpoint: getEnvOrDefault(env, 'CLAUDE_ENDPOINT', 'https://api.anthropic.com/v1'),\r\n azureApiKey: env.AZURE_API_KEY,\r\n azureModels: env.AZURE_MODELS ? env.AZURE_MODELS.split(',').map(model => model.trim()) : [],\r\n azureEndpoint: env.AZURE_ENDPOINT,\r\n };\r\n};", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\n\r\nexport interface Message {\r\n role: 'system' | 'user' | 'assistant';\r\n content: string;\r\n}\r\n\r\ninterface ChatCompletionResponse {\r\n id: string;\r\n object: string;\r\n created: number;\r\n model: string;\r\n choices: {\r\n index: number;\r\n message: Message;\r\n finish_reason: string;\r\n }[];\r\n usage: {\r\n prompt_tokens: number;\r\n completion_tokens: number;\r\n total_tokens: number;\r\n };\r\n}\r\n\r\nexport class OpenAIAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private models: string[];\r\n private defaultModel: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.openaiApiKey;\r\n this.baseUrl = config.openaiBaseUrl;\r\n this.models = config.openaiModels;\r\n this.defaultModel = config.defaultModel || this.models[0];\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n const url = `${this.baseUrl}/chat/completions`;\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: model || this.defaultModel,\r\n messages: messages,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`OpenAI API error: ${response.statusText}`);\r\n }\r\n\r\n const data: ChatCompletionResponse = await response.json();\r\n return data.choices[0].message.content.trim();\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.models.includes(model);\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.defaultModel;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.models;\r\n }\r\n}\r\n\r\nexport default OpenAIAPI;", "import { Env } from '../env';\r\n\r\nexport function formatCodeBlock(code: string, language: string): string {\r\n return `\\`\\`\\`${language}\\n${code}\\n\\`\\`\\``;\r\n}\r\n\r\nexport function splitMessage(text: string, maxLength: number = 4096): string[] {\r\n const messages: string[] = [];\r\n let currentMessage = '';\r\n\r\n const lines = text.split('\\n');\r\n\r\n for (const line of lines) {\r\n if (currentMessage.length + line.length + 1 > maxLength) {\r\n messages.push(currentMessage.trim());\r\n currentMessage = '';\r\n }\r\n currentMessage += line + '\\n';\r\n }\r\n\r\n if (currentMessage.trim()) {\r\n messages.push(currentMessage.trim());\r\n }\r\n\r\n return messages;\r\n}\r\n\r\nexport function escapeMarkdown(text: string): string {\r\n const specialChars = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'];\r\n return specialChars.reduce((acc, char) => acc.replace(new RegExp(`\\\\${char}`, 'g'), `\\\\${char}`), text);\r\n}\r\n\r\nexport async function sendChatAction(chatId: number, action: string, env: Env): Promise {\r\n const token = env.TELEGRAM_BOT_TOKEN;\r\n const url = `https://api.telegram.org/bot${token}/sendChatAction`;\r\n await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n chat_id: chatId,\r\n action: action,\r\n }),\r\n });\r\n}", "export type SupportedLanguages = 'en' | 'zh' | 'es';\r\n\r\nexport interface Translations {\r\n welcome: string;\r\n unauthorized: string;\r\n error: string;\r\n current_language: string;\r\n language_changed: string;\r\n new_conversation: string;\r\n no_history: string;\r\n history_summary: string;\r\n current_model: string;\r\n available_models: string;\r\n model_changed: string;\r\n help_intro: string;\r\n start_description: string;\r\n language_description: string;\r\n new_description: string;\r\n history_description: string;\r\n switchmodel_description: string;\r\n help_description: string;\r\n choose_language: string;\r\n choose_model: string;\r\n language_en: string;\r\n language_zh: string;\r\n language_es: string;\r\n image_prompt_required: string;\r\n image_generation_error: string;\r\n img_description: string;\r\n invalid_size: string;\r\n flux_description: string;\r\n flux_usage: string;\r\n invalid_aspect_ratio: string;\r\n original_prompt: string;\r\n prompt_generation_model: string;\r\n optimized_prompt: string;\r\n image_specs: string;\r\n command_not_found: string;\r\n}\r\n\r\nexport type TranslationKey = keyof Translations;\r\n\r\ntype TranslationsMap = Record;\r\n\r\nconst translations: TranslationsMap = {\r\n en: {\r\n welcome: \"Welcome to the GPT Telegram Bot!\",\r\n unauthorized: \"Sorry, you're not authorized to use this bot.\",\r\n error: \"An error occurred. Please try again.\",\r\n current_language: \"Your current language is: English\",\r\n language_changed: \"Language has been changed to: \",\r\n new_conversation: \"Starting a new conversation. Previous context has been cleared.\",\r\n no_history: \"No conversation history found.\",\r\n history_summary: \"Here's a summary of your conversation history:\",\r\n current_model: \"Your current model is: \",\r\n available_models: \"Available models: \",\r\n model_changed: \"Model has been changed to: \",\r\n help_intro: \"Here are the available commands:\",\r\n start_description: \"Start the bot\",\r\n language_description: \"Set your preferred language\",\r\n new_description: \"Start a new conversation\",\r\n history_description: \"Summarize conversation history\",\r\n switchmodel_description: \"Switch the current model\",\r\n help_description: \"Show available commands and their descriptions\",\r\n choose_language: \"Please choose your preferred language:\",\r\n choose_model: \"Please choose a model:\",\r\n language_en: \"English\",\r\n language_zh: \"Chinese\",\r\n language_es: \"Spanish\",\r\n image_prompt_required: 'Please provide a description for the image you want to generate.',\r\n image_generation_error: 'Sorry, there was an error generating the image. Please try again later.',\r\n img_description: 'Generate an image using DALL\u00B7E. Format: /img [size]',\r\n invalid_size: 'Invalid image size. Please use one of the following sizes: ',\r\n flux_description: 'Generate an image using Flux',\r\n flux_usage: 'Usage: /flux [aspect ratio]. Valid aspect ratios are: 1:1 (default), 1:2, 3:2, 3:4, 16:9, 9:16',\r\n invalid_aspect_ratio: 'Invalid aspect ratio. Valid options are: ',\r\n original_prompt: \"\uD83C\uDFA8 Original Prompt\",\r\n prompt_generation_model: \"\uD83D\uDCAC Prompt Generation Model\",\r\n optimized_prompt: \"\uD83C\uDF10 Optimized Prompt\",\r\n image_specs: \"\uD83D\uDCD0 Image Specifications\",\r\n command_not_found: \"Command not found. Type /help for a list of available commands.\",\r\n },\r\n zh: {\r\n welcome: \"\u6B22\u8FCE\u4F7F\u7528 GPT Telegram \u673A\u5668\u4EBA\uFF01\",\r\n unauthorized: \"\u62B1\u6B49\uFF0C\u60A8\u65E0\u6743\u4F7F\u7528\u6B64\u673A\u5668\u4EBA\u3002\",\r\n error: \"\u53D1\u751F\u9519\u8BEF\uFF0C\u8BF7\u91CD\u8BD5\u3002\",\r\n current_language: \"\u60A8\u5F53\u524D\u7684\u8BED\u8A00\u662F\uFF1A\u4E2D\u6587\",\r\n language_changed: \"\u8BED\u8A00\u5DF2\u66F4\u6539\u4E3A\uFF1A\",\r\n new_conversation: \"\u5F00\u59CB\u65B0\u7684\u5BF9\u8BDD\u3002\u4E4B\u524D\u7684\u4E0A\u4E0B\u6587\u5DF2\u88AB\u6E05\u9664\u3002\",\r\n no_history: \"\u672A\u627E\u5230\u5BF9\u8BDD\u5386\u53F2\u3002\",\r\n history_summary: \"\u4EE5\u4E0B\u662F\u60A8\u7684\u5BF9\u8BDD\u5386\u53F2\u6458\u8981\uFF1A\",\r\n current_model: \"\u60A8\u5F53\u524D\u4F7F\u7528\u7684\u6A21\u578B\u662F\uFF1A\",\r\n available_models: \"\u53EF\u7528\u7684\u6A21\u578B\uFF1A\",\r\n model_changed: \"\u6A21\u578B\u5DF2\u66F4\u6539\u4E3A\uFF1A\",\r\n help_intro: \"\u4EE5\u4E0B\u662F\u53EF\u7528\u7684\u547D\u4EE4\uFF1A\",\r\n start_description: \"\u542F\u52A8\u673A\u5668\u4EBA\",\r\n language_description: \"\u8BBE\u7F6E\u60A8\u7684\u9996\u9009\u8BED\u8A00\",\r\n new_description: \"\u5F00\u59CB\u65B0\u7684\u5BF9\u8BDD\",\r\n history_description: \"\u603B\u7ED3\u5BF9\u8BDD\u5386\u53F2\",\r\n switchmodel_description: \"\u5207\u6362\u5F53\u524D\u6A21\u578B\",\r\n help_description: \"\u663E\u793A\u53EF\u7528\u547D\u4EE4\u53CA\u5176\u63CF\u8FF0\",\r\n choose_language: \"\u8BF7\u9009\u62E9\u60A8\u504F\u597D\u7684\u8BED\u8A00\uFF1A\",\r\n choose_model: \"\u8BF7\u9009\u62E9\u4E00\u4E2A\u6A21\u578B\uFF1A\",\r\n language_en: \"\u82F1\u8BED\",\r\n language_zh: \"\u4E2D\u6587\",\r\n language_es: \"\u897F\u73ED\u7259\u8BED\",\r\n image_prompt_required: '\u8BF7\u63D0\u4F9B\u60A8\u60F3\u8981\u751F\u6210\u7684\u56FE\u50CF\u63CF\u8FF0\u3002',\r\n image_generation_error: '\u62B1\u6B49\uFF0C\u751F\u6210\u56FE\u50CF\u65F6\u51FA\u9519\u3002\u8BF7\u7A0D\u540E\u518D\u8BD5\u3002',\r\n img_description: '\u4F7F\u7528 DALL\u00B7E \u751F\u6210\u56FE\u50CF\u3002\u683C\u5F0F\uFF1A/img <\u63CF\u8FF0> [\u5C3A\u5BF8]',\r\n invalid_size: '\u65E0\u6548\u7684\u56FE\u7247\u5C3A\u5BF8\u3002\u8BF7\u4F7F\u7528\u4EE5\u4E0B\u5C3A\u5BF8\u4E4B\u4E00\uFF1A',\r\n flux_description: '\u4F7F\u7528 Flux \u751F\u6210\u56FE\u50CF',\r\n flux_usage: '\u7528\u6CD5\uFF1A/flux <\u63CF\u8FF0> [\u5BBD\u9AD8\u6BD4]\u3002\u6709\u6548\u7684\u5BBD\u9AD8\u6BD4\u6709\uFF1A1:1\uFF08\u9ED8\u8BA4\uFF09, 1:2, 3:2, 3:4, 16:9, 9:16',\r\n invalid_aspect_ratio: '\u65E0\u6548\u7684\u5BBD\u9AD8\u6BD4\u3002\u6709\u6548\u9009\u9879\u4E3A\uFF1A',\r\n original_prompt: \"\uD83C\uDFA8 \u539F\u59CB\u63D0\u793A\u8BCD\",\r\n prompt_generation_model: \"\uD83D\uDCAC \u63D0\u793A\u8BCD\u751F\u6210\u6A21\u578B\",\r\n optimized_prompt: \"\uD83C\uDF10 \u4F18\u5316\u540E\u7684\u63D0\u793A\u8BCD\",\r\n image_specs: \"\uD83D\uDCD0 \u56FE\u50CF\u89C4\u683C\",\r\n command_not_found: \"\u672A\u627E\u5230\u8BE5\u547D\u4EE4\u3002\u8F93\u5165 /help \u67E5\u770B\u53EF\u7528\u547D\u4EE4\u5217\u8868\u3002\",\r\n },\r\n es: {\r\n welcome: \"\u00A1Bienvenido al bot de GPT en Telegram!\",\r\n unauthorized: \"Lo siento, no est\u00E1s autorizado para usar este bot.\",\r\n error: \"Ocurri\u00F3 un error. Por favor, int\u00E9ntalo de nuevo.\",\r\n current_language: \"Tu idioma actual es: Espa\u00F1ol\",\r\n language_changed: \"El idioma ha sido cambiado a: \",\r\n new_conversation: \"Iniciando una nueva conversaci\u00F3n. El contexto anterior ha sido borrado.\",\r\n no_history: \"No se encontr\u00F3 historial de conversaci\u00F3n.\",\r\n history_summary: \"Aqu\u00ED tienes un resumen de tu historial de conversaci\u00F3n:\",\r\n current_model: \"Tu modelo actual es: \",\r\n available_models: \"Modelos disponibles: \",\r\n model_changed: \"El modelo ha sido cambiado a: \",\r\n help_intro: \"Estos son los comandos disponibles:\",\r\n start_description: \"Iniciar el bot\",\r\n language_description: \"Establecer tu idioma preferido\",\r\n new_description: \"Iniciar una nueva conversaci\u00F3n\",\r\n history_description: \"Resumir el historial de conversaci\u00F3n\",\r\n switchmodel_description: \"Cambiar el modelo actual\",\r\n help_description: \"Mostrar comandos disponibles y sus descripciones\",\r\n choose_language: \"Por favor, elige tu idioma preferido:\",\r\n choose_model: \"Por favor, elige un modelo:\",\r\n language_en: \"Ingl\u00E9s\",\r\n language_zh: \"Chino\",\r\n language_es: \"Espa\u00F1ol\",\r\n image_prompt_required: 'Por favor, proporcione una descripci\u00F3n para la imagen que desea generar.',\r\n image_generation_error: 'Lo siento, hubo un error al generar la imagen. Por favor, int\u00E9ntelo de nuevo m\u00E1s tarde.',\r\n img_description: 'Generar una imagen usando DALL\u00B7E. Formato: /img [tama\u00F1o]',\r\n invalid_size: 'Tama\u00F1o de imagen no v\u00E1lido. Por favor, use uno de los siguientes tama\u00F1os: ',\r\n flux_description: 'Generar una imagen usando Flux',\r\n flux_usage: 'Uso: /flux [relaci\u00F3n de aspecto]. Las relaciones de aspecto v\u00E1lidas son: 1:1 (predeterminado), 1:2, 3:2, 3:4, 16:9, 9:16',\r\n invalid_aspect_ratio: 'Relaci\u00F3n de aspecto no v\u00E1lida. Las opciones v\u00E1lidas son: ',\r\n original_prompt: \"\uD83C\uDFA8 Prompt Original\",\r\n prompt_generation_model: \"\uD83D\uDCAC Modelo de Generaci\u00F3n de Prompts\",\r\n optimized_prompt: \"\uD83C\uDF10 Prompt Optimizado\",\r\n image_specs: \"\uD83D\uDCD0 Especificaciones de la Imagen\",\r\n command_not_found: \"Comando no encontrado. Escribe /help para ver una lista de comandos disponibles.\",\r\n }\r\n};\r\n\r\nexport function translate(key: TranslationKey, language: SupportedLanguages = 'en'): string {\r\n return translations[language][key] || translations['en'][key];\r\n}", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport { Message } from './openai_api';\r\n\r\ninterface ImageGenerationResponse {\r\n data: Array<{ url: string }>;\r\n}\r\n\r\nexport class ImageGenerationAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private model: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.openaiApiKey;\r\n this.baseUrl = config.openaiBaseUrl;\r\n this.model = config.dallEModel;\r\n }\r\n\r\n async generateImage(prompt: string, size: string): Promise {\r\n const url = `${this.baseUrl}/images/generations`;\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: this.model,\r\n prompt: prompt,\r\n n: 1,\r\n size: size,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Image generation API error: ${response.statusText}`);\r\n }\r\n\r\n const data: ImageGenerationResponse = await response.json();\r\n return data.data[0].url;\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n throw new Error('Method not implemented for image generation.');\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return model === this.model;\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.model;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return [this.model];\r\n }\r\n\r\n getValidSizes(): string[] {\r\n return ['1024x1024', '1024x1792', '1792x1024'];\r\n }\r\n}\r\n\r\nexport default ImageGenerationAPI;", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\n\r\ninterface FluxResponse {\r\n result: {\r\n image: string; // base64 encoded image data\r\n };\r\n success: boolean;\r\n errors: string[];\r\n}\r\n\r\ninterface ExternalAPIResponse {\r\n choices: Array<{\r\n message: {\r\n content: string;\r\n };\r\n }>;\r\n}\r\n\r\nexport class FluxAPI implements ModelAPIInterface {\r\n private apiToken: string;\r\n private accountId: string;\r\n private steps: number;\r\n private model: string = '@cf/black-forest-labs/flux-1-schnell';\r\n private promptOptimization: boolean;\r\n private externalApiBase?: string;\r\n private externalModel?: string;\r\n private externalApiKey?: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiToken = config.cloudflareApiToken;\r\n this.accountId = config.cloudflareAccountId;\r\n this.steps = config.fluxSteps;\r\n this.promptOptimization = config.promptOptimization;\r\n this.externalApiBase = config.externalApiBase;\r\n this.externalModel = config.externalModel;\r\n this.externalApiKey = config.externalApiKey;\r\n }\r\n\r\n async generateImage(prompt: string, aspectRatio: string): Promise<{ imageData: Uint8Array; optimizedPrompt?: string }> {\r\n let optimizedPrompt: string | undefined;\r\n if (this.promptOptimization) {\r\n optimizedPrompt = await this.optimizePrompt(prompt, aspectRatio);\r\n prompt = optimizedPrompt;\r\n }\r\n\r\n const url = `https://api.cloudflare.com/client/v4/accounts/${this.accountId}/ai/run/${this.model}`;\r\n const [width, height] = this.getImageDimensions(aspectRatio);\r\n const seed = Math.floor(Math.random() * 1000000);\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiToken}`,\r\n },\r\n body: JSON.stringify({\r\n prompt: prompt,\r\n num_steps: this.steps,\r\n seed: seed,\r\n width: width,\r\n height: height,\r\n }),\r\n });\r\n\r\n const responseText = await response.text();\r\n let data: FluxResponse;\r\n try {\r\n data = JSON.parse(responseText);\r\n } catch (error) {\r\n console.error('Error parsing Flux API response:', error);\r\n throw new Error('Invalid response from Flux API');\r\n }\r\n\r\n if (!response.ok || !data.success) {\r\n const errorMessage = data.errors ? data.errors.join(', ') : 'Unknown error';\r\n console.error(`Flux API error: ${errorMessage}`);\r\n throw new Error(`Flux API error: ${errorMessage}`);\r\n }\r\n\r\n if (!data.result || !data.result.image) {\r\n console.error('Flux API returned no image');\r\n throw new Error('Flux API returned no image');\r\n }\r\n \r\n const binaryString = atob(data.result.image);\r\n const len = binaryString.length;\r\n const bytes = new Uint8Array(len);\r\n for (let i = 0; i < len; i++) {\r\n bytes[i] = binaryString.charCodeAt(i);\r\n }\r\n return { \r\n imageData: bytes,\r\n optimizedPrompt\r\n };\r\n }\r\n\r\n private async optimizePrompt(prompt: string, aspectRatio: string): Promise {\r\n if (!this.externalApiBase || !this.externalModel || !this.externalApiKey) {\r\n throw new Error('External API configuration is missing');\r\n }\r\n\r\n const systemPrompt = \"You are a prompt generation bot based on the Flux.1 model. Based on the user's requirements, automatically generate drawing prompts that adhere to the Flux.1 format. While you can refer to the provided templates to learn the structure and patterns of the prompts, you must remain flexible to meet various different needs. The final output should be limited to the prompts only, without any additional explanations or information. You must reply to me entirely in English!\\n\\n### **Prompt Generation Logic**:\\n\\n1. **Requirement Analysis**: Extract key information from the user's description, including:\\n- Characters: Appearance, actions, expressions, etc.\\n- Scene: Environment, lighting, weather, etc.\\n- Style: Art style, emotional atmosphere, color scheme, etc.\\n- **Aspect Ratio**: If the user provides a specific aspect ratio (e.g., \\\"3:2\\\", \\\"16:9\\\"), extract this and integrate it into the final prompt.\\n- Other elements: Specific objects, background, or effects.\\n\\n2. **Prompt Structure Guidelines**:\\n- **Concise, precise, and detailed**: Prompts should describe the core subject simply and clearly, with enough detail to generate an image that matches the request.\\n- **Flexible and varied**: Use the user's description to dynamically create prompts without following rigid templates. Ensure prompts are adapted based on the specific needs of each user, avoiding overly template-based outputs.\\n- **Descriptions following Flux.1 style**: Prompts must follow the requirements of Flux.1, aiming to include descriptions of the art style, visual effects, and emotional atmosphere. Use keywords and description patterns that match the Flux.1 model's generation process. If a specific aspect ratio is mentioned, ensure it is included in the prompt description.\\n\\n3. **Key Points Summary for Flux.1 Prompts**:\\n- **Concise and precise subject description**: Clearly identify the subject or scene of the image.\\n- **Specific description of style and emotional atmosphere**: Ensure the prompt includes information about the art style, lighting, color scheme, and emotional atmosphere of the image.\\n- **Details on dynamics and action**: Prompts may include important details like actions, emotions, or lighting effects in the scene.\";\r\n\r\n const response = await fetch(`${this.externalApiBase}/v1/chat/completions`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.externalApiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: this.externalModel,\r\n messages: [\r\n { role: 'system', content: systemPrompt },\r\n { role: 'user', content: `Optimize this image generation prompt for aspect ratio ${aspectRatio}: ${prompt}` },\r\n ],\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`External API error: ${response.statusText}`);\r\n }\r\n\r\n const data: ExternalAPIResponse = await response.json();\r\n return data.choices[0].message.content.trim();\r\n }\r\n\r\n private getImageDimensions(aspectRatio: string): [number, number] {\r\n switch (aspectRatio) {\r\n case '1:1': return [1024, 1024];\r\n case '1:2': return [512, 1024];\r\n case '3:2': return [768, 512];\r\n case '3:4': return [768, 1024];\r\n case '16:9': return [1024, 576];\r\n case '9:16': return [576, 1024];\r\n default: return [1024, 1024]; // Default to 1:1 if invalid ratio is provided\r\n }\r\n }\r\n\r\n async generateResponse(messages: { role: string; content: string; }[]): Promise {\r\n throw new Error('Method not implemented for image generation.');\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return model === this.model;\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.model;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return [this.model];\r\n }\r\n\r\n getValidAspectRatios(): string[] {\r\n return ['1:1', '1:2', '3:2', '3:4', '16:9', '9:16'];\r\n }\r\n}\r\n\r\nexport default FluxAPI;", "import { TelegramBot } from '../api/telegram';\r\nimport { translate, TranslationKey } from '../utils/i18n';\r\nimport { ImageGenerationAPI } from '../api/image_generation';\r\nimport { sendChatAction } from '../utils/helpers';\r\nimport { FluxAPI } from '../api/flux-cf';\r\nimport { getConfig } from '../env';\r\nimport GeminiAPI from '../api/gemini';\r\nimport GroqAPI from '../api/groq';\r\nimport ClaudeAPI from '../api/claude';\r\n\r\nexport interface Command {\r\n name: string;\r\n description: string;\r\n action: (chatId: number, bot: TelegramBot, args: string[]) => Promise;\r\n}\r\n\r\nexport const commands: Command[] = [\r\n {\r\n name: 'start',\r\n description: 'Start the bot',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n const currentModel = await bot.getCurrentModel(userId);\r\n const welcomeMessage = translate('welcome', language) + '\\n' + \r\n translate('current_model', language) + currentModel;\r\n await bot.sendMessageWithFallback(chatId, welcomeMessage);\r\n },\r\n },\r\n {\r\n name: 'language',\r\n description: 'Set your preferred language',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const currentLanguage = await bot.getUserLanguage(userId);\r\n const keyboard = {\r\n inline_keyboard: [\r\n [\r\n { text: '\uD83C\uDDFA\uD83C\uDDF8 English', callback_data: 'lang_en' },\r\n { text: '\uD83C\uDDE8\uD83C\uDDF3 \u4E2D\u6587', callback_data: 'lang_zh' },\r\n { text: '\uD83C\uDDEA\uD83C\uDDF8 Espa\u00F1ol', callback_data: 'lang_es' }\r\n ]\r\n ]\r\n };\r\n await bot.sendMessage(chatId, translate('choose_language', currentLanguage), { reply_markup: JSON.stringify(keyboard) });\r\n },\r\n },\r\n {\r\n name: 'switchmodel',\r\n description: 'Switch the current model',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n const config = getConfig(bot['env']);\r\n const availableModels = [\r\n ...config.openaiModels,\r\n ...config.googleModels,\r\n ...config.groqModels,\r\n ...config.claudeModels,\r\n ...config.azureModels, // \u65B0\u589E Azure \u6A21\u578B\r\n ];\r\n const keyboard = {\r\n inline_keyboard: availableModels.map(model => [{text: model, callback_data: `model_${model}`}])\r\n };\r\n await bot.sendMessage(chatId, translate('choose_model', language), { reply_markup: JSON.stringify(keyboard) });\r\n },\r\n },\r\n {\r\n name: 'new',\r\n description: 'Start a new conversation',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n await bot.clearContext(userId);\r\n },\r\n },\r\n {\r\n name: 'history',\r\n description: 'Summarize conversation history',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n const summary = await bot.summarizeHistory(userId);\r\n await bot.sendMessage(chatId, summary || translate('no_history', language));\r\n },\r\n },\r\n {\r\n name: 'help',\r\n description: 'Show available commands and their descriptions',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n let helpMessage = translate('help_intro', language) + '\\n\\n';\r\n \r\n for (const command of commands) {\r\n const descriptionKey = `${command.name}_description` as TranslationKey;\r\n // \u4F7F\u7528\u666E\u901A\u6587\u672C\uFF0C\u4E0D\u6DFB\u52A0\u4EFB\u4F55\u683C\u5F0F\u5316\r\n helpMessage += `/${command.name} - ${translate(descriptionKey, language)}\\n`;\r\n }\r\n \r\n // \u4F7F\u7528\u666E\u901A\u7684 sendMessage \u65B9\u6CD5\uFF0C\u4E0D\u6307\u5B9A parse_mode\r\n await bot.sendMessage(chatId, helpMessage);\r\n },\r\n },\r\n {\r\n name: 'img',\r\n description: 'Generate an image using DALL\u00B7E',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n \r\n if (!args.length) {\r\n await bot.sendMessageWithFallback(chatId, translate('image_prompt_required', language));\r\n return;\r\n }\r\n \r\n const validSizes = ['1024x1024', '1024x1792', '1792x1024'];\r\n const sizeArg = args[args.length - 1].toLowerCase();\r\n let size: string;\r\n let prompt: string;\r\n \r\n if (validSizes.includes(sizeArg)) {\r\n size = sizeArg;\r\n prompt = args.slice(0, -1).join(' ');\r\n } else {\r\n size = '1024x1024'; // Default size\r\n prompt = args.join(' ');\r\n \r\n // Check if the last argument looks like a size specification\r\n if (sizeArg.includes('x') || sizeArg.includes('*')) {\r\n const sizeOptions = validSizes.map(s => `\\`${s}\\``).join(', ');\r\n await bot.sendMessage(chatId, translate('invalid_size', language) + sizeOptions);\r\n return;\r\n }\r\n }\r\n \r\n try {\r\n await sendChatAction(chatId, 'upload_photo', bot['env']);\r\n const imageApi = new ImageGenerationAPI(bot['env']);\r\n const imageUrl = await imageApi.generateImage(prompt, size);\r\n await bot.sendPhoto(chatId, imageUrl, { caption: prompt });\r\n } catch (error) {\r\n console.error('Error generating image:', error);\r\n await bot.sendMessage(chatId, translate('image_generation_error', language));\r\n }\r\n },\r\n },\r\n {\r\n name: 'flux',\r\n description: 'Generate an image using Flux',\r\n action: async (chatId: number, bot: TelegramBot, args: string[]) => {\r\n const userId = chatId.toString();\r\n const language = await bot.getUserLanguage(userId);\r\n\r\n if (!args.length) {\r\n await bot.sendMessage(chatId, translate('flux_usage', language));\r\n return;\r\n }\r\n\r\n let aspectRatio = '1:1'; // \u9ED8\u8BA4\u6BD4\u4F8B\r\n let prompt: string;\r\n\r\n const fluxApi = new FluxAPI(bot['env']);\r\n const validRatios = fluxApi.getValidAspectRatios();\r\n\r\n if (validRatios.includes(args[args.length - 1])) {\r\n aspectRatio = args[args.length - 1];\r\n prompt = args.slice(0, -1).join(' ');\r\n } else {\r\n prompt = args.join(' ');\r\n }\r\n\r\n try {\r\n await sendChatAction(chatId, 'upload_photo', bot['env']);\r\n\r\n const { imageData, optimizedPrompt } = await fluxApi.generateImage(prompt, aspectRatio);\r\n \r\n const config = getConfig(bot['env']);\r\n let caption = `${translate('original_prompt', language)}: ${prompt}\\n`;\r\n caption += `${translate('image_specs', language)}: ${aspectRatio}\\n`;\r\n \r\n if (config.promptOptimization && optimizedPrompt) {\r\n caption += `${translate('prompt_generation_model', language)}: ${config.externalModel || 'Unknown'}\\n`;\r\n caption += `${translate('optimized_prompt', language)}: ${optimizedPrompt}\\n`;\r\n }\r\n\r\n await bot.sendPhoto(chatId, imageData, { caption: caption });\r\n } catch (error) {\r\n console.error(`Error generating Flux image for user ${userId}:`, error);\r\n if (error instanceof Error) {\r\n console.error('Error details:', error.message);\r\n }\r\n await bot.sendMessage(chatId, translate('image_generation_error', language));\r\n }\r\n },\r\n },\r\n];", "import { Env, getConfig } from '../env';\r\n\r\ninterface RedisResponse {\r\n result: string | null;\r\n}\r\n\r\nexport class RedisClient {\r\n private url: string;\r\n private token: string;\r\n private config: ReturnType;\r\n\r\n constructor(env: Env) {\r\n this.config = getConfig(env);\r\n this.url = this.config.upstashRedisRestUrl;\r\n this.token = this.config.upstashRedisRestToken;\r\n }\r\n\r\n async get(key: string): Promise {\r\n const response = await fetch(`${this.url}/get/${key}`, {\r\n headers: {\r\n Authorization: `Bearer ${this.token}`,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n if (response.status === 404) {\r\n return null;\r\n }\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n\r\n const data = await response.json() as RedisResponse;\r\n return data.result;\r\n }\r\n\r\n async set(key: string, value: string, ttl?: number): Promise {\r\n const url = ttl\r\n ? `${this.url}/set/${key}/${value}?EX=${ttl}`\r\n : `${this.url}/set/${key}/${value}`;\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: `Bearer ${this.token}`,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n }\r\n\r\n async del(key: string): Promise {\r\n const response = await fetch(`${this.url}/del/${key}`, {\r\n method: 'POST',\r\n headers: {\r\n Authorization: `Bearer ${this.token}`,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n }\r\n\r\n async setLanguage(userId: string, language: string): Promise {\r\n await this.set(`language:${userId}`, language, this.config.languageTTL);\r\n }\r\n\r\n async appendContext(userId: string, newContext: string): Promise {\r\n const key = `context:${userId}`;\r\n const existingContext = await this.get(key);\r\n const updatedContext = existingContext\r\n ? `${existingContext}\\n${newContext}`\r\n : newContext;\r\n await this.set(key, updatedContext, this.config.contextTTL);\r\n }\r\n}", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport { Message } from './openai_api';\r\n\r\ninterface GeminiResponse {\r\n candidates: Array<{\r\n content: {\r\n parts: Array<{\r\n text: string;\r\n }>;\r\n };\r\n }>;\r\n}\r\n\r\ninterface GeminiMessage {\r\n role: 'user' | 'model';\r\n parts: Array<{ text: string }>;\r\n}\r\n\r\nexport class GeminiAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private models: string[];\r\n private defaultModel: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.googleModelKey;\r\n this.baseUrl = config.googleModelBaseUrl || 'https://generativelanguage.googleapis.com/v1beta';\r\n this.models = config.googleModels;\r\n this.defaultModel = this.models[0];\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n const useModel = model || this.defaultModel;\r\n console.log(`Generating response with Gemini model: ${useModel}`);\r\n const url = `${this.baseUrl}/models/${useModel}:generateContent?key=${this.apiKey}`;\r\n\r\n const geminiMessages: GeminiMessage[] = messages\r\n .filter(msg => msg.role !== 'system') // \u8FC7\u6EE4\u6389 system \u6D88\u606F\r\n .map(msg => ({\r\n role: msg.role === 'assistant' ? 'model' : 'user',\r\n parts: [{ text: msg.content }]\r\n }));\r\n\r\n const requestBody = {\r\n contents: geminiMessages,\r\n generationConfig: {\r\n temperature: 0.7,\r\n topP: 1,\r\n topK: 1,\r\n maxOutputTokens: 2048,\r\n },\r\n };\r\n\r\n console.log('Request body:', JSON.stringify(requestBody, null, 2));\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(requestBody),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error(`Gemini API error: ${response.statusText}`, errorText);\r\n throw new Error(`Gemini API error: ${response.statusText}\\n${errorText}`);\r\n }\r\n\r\n const data: GeminiResponse = await response.json();\r\n console.log('Gemini API response received');\r\n if (!data.candidates || data.candidates.length === 0) {\r\n throw new Error('No response generated from Gemini API');\r\n }\r\n const generatedText = data.candidates[0].content.parts[0].text.trim();\r\n console.log(`Generated text length: ${generatedText.length}`);\r\n return generatedText;\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.models.includes(model);\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.defaultModel;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.models;\r\n }\r\n}\r\n\r\nexport default GeminiAPI;", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport { Message } from './openai_api';\r\n\r\ninterface GroqResponse {\r\n choices: Array<{\r\n message: {\r\n content: string;\r\n };\r\n }>;\r\n}\r\n\r\nexport class GroqAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string = 'https://api.groq.com/openai/v1';\r\n private models: string[];\r\n private defaultModel: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.groqApiKey;\r\n this.models = config.groqModels;\r\n this.defaultModel = this.models[0];\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n const useModel = model || this.defaultModel;\r\n console.log(`Generating response with Groq model: ${useModel}`);\r\n const url = `${this.baseUrl}/chat/completions`;\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${this.apiKey}`,\r\n },\r\n body: JSON.stringify({\r\n model: useModel,\r\n messages: messages,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error(`Groq API error: ${response.statusText}`, errorText);\r\n throw new Error(`Groq API error: ${response.statusText}\\n${errorText}`);\r\n }\r\n\r\n const data: GroqResponse = await response.json();\r\n console.log('Groq API response received');\r\n if (!data.choices || data.choices.length === 0) {\r\n throw new Error('No response generated from Groq API');\r\n }\r\n const generatedText = data.choices[0].message.content.trim();\r\n console.log(`Generated text length: ${generatedText.length}`);\r\n return generatedText;\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.models.includes(model);\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.defaultModel;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.models;\r\n }\r\n}\r\n\r\nexport default GroqAPI;", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport { Message } from './openai_api';\r\n\r\ninterface ClaudeResponse {\r\n content: Array<{\r\n text: string;\r\n }>;\r\n}\r\n\r\nexport class ClaudeAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private models: string[];\r\n private defaultModel: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.claudeApiKey;\r\n this.baseUrl = config.claudeEndpoint || 'https://api.anthropic.com/v1';\r\n this.models = config.claudeModels;\r\n this.defaultModel = this.models[0];\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n const useModel = model || this.defaultModel;\r\n console.log(`Generating response with Claude model: ${useModel}`);\r\n const url = `${this.baseUrl}/messages`;\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': this.apiKey,\r\n 'anthropic-version': '2023-06-01'\r\n },\r\n body: JSON.stringify({\r\n model: useModel,\r\n messages: messages.map(msg => ({\r\n role: msg.role === 'assistant' ? 'assistant' : 'user',\r\n content: msg.content\r\n })),\r\n max_tokens: 1000\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error(`Claude API error: ${response.statusText}`, errorText);\r\n throw new Error(`Claude API error: ${response.statusText}\\n${errorText}`);\r\n }\r\n\r\n const data: ClaudeResponse = await response.json();\r\n console.log('Claude API response received');\r\n if (!data.content || data.content.length === 0) {\r\n throw new Error('No response generated from Claude API');\r\n }\r\n const generatedText = data.content[0].text.trim();\r\n console.log(`Generated text length: ${generatedText.length}`);\r\n return generatedText;\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.models.includes(model);\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.defaultModel;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.models;\r\n }\r\n}\r\n\r\nexport default ClaudeAPI;", "import { Env, getConfig } from '../env';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport { Message } from './openai_api';\r\n\r\ninterface AzureChatCompletionResponse {\r\n id: string;\r\n object: string;\r\n created: number;\r\n choices: Array<{\r\n index: number;\r\n message: {\r\n role: string;\r\n content: string;\r\n };\r\n finish_reason: string;\r\n }>;\r\n}\r\n\r\nexport class AzureAPI implements ModelAPIInterface {\r\n private apiKey: string;\r\n private baseUrl: string;\r\n private models: string[];\r\n private defaultModel: string;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.apiKey = config.azureApiKey;\r\n this.baseUrl = config.azureEndpoint;\r\n this.models = config.azureModels;\r\n this.defaultModel = this.models[0];\r\n }\r\n\r\n async generateResponse(messages: Message[], model?: string): Promise {\r\n const useModel = model || this.defaultModel;\r\n const url = `${this.baseUrl}/openai/deployments/${useModel}/chat/completions?api-version=2024-02-01`;\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'api-key': this.apiKey,\r\n },\r\n body: JSON.stringify({\r\n messages: messages,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error(`Azure API error: ${response.statusText}`, errorText);\r\n throw new Error(`Azure API error: ${response.statusText}\\n${errorText}`);\r\n }\r\n\r\n const data: AzureChatCompletionResponse = await response.json();\r\n if (!data.choices || data.choices.length === 0) {\r\n throw new Error('Azure API \u672A\u751F\u6210\u4EFB\u4F55\u54CD\u5E94');\r\n }\r\n return data.choices[0].message.content.trim();\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.models.includes(model);\r\n }\r\n\r\n getDefaultModel(): string {\r\n return this.defaultModel;\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.models;\r\n }\r\n}\r\n\r\nexport default AzureAPI;", "import { Env, getConfig } from '../env';\r\nimport { TelegramTypes } from '../../types/telegram';\r\nimport OpenAIAPI, { Message } from './openai_api';\r\nimport { formatCodeBlock, escapeMarkdown, sendChatAction, splitMessage } from '../utils/helpers';\r\nimport { translate, SupportedLanguages } from '../utils/i18n';\r\nimport { commands, Command } from '../config/commands';\r\nimport { RedisClient } from '../utils/redis';\r\nimport { ModelAPIInterface } from './model_api_interface';\r\nimport GeminiAPI from './gemini';\r\nimport GroqAPI from './groq';\r\nimport ClaudeAPI from './claude';\r\nimport AzureAPI from './azure'; // \u65B0\u589E AzureAPI \u5BFC\u5165\r\n\r\nexport class TelegramBot {\r\n private token: string;\r\n private apiUrl: string;\r\n private whitelistedUsers: string[];\r\n private systemMessage: string;\r\n private env: Env;\r\n private commands: Command[];\r\n private redis: RedisClient;\r\n private modelAPI: ModelAPIInterface;\r\n\r\n constructor(env: Env) {\r\n const config = getConfig(env);\r\n this.token = config.telegramBotToken;\r\n this.apiUrl = `https://api.telegram.org/bot${this.token}`;\r\n this.whitelistedUsers = config.whitelistedUsers;\r\n this.systemMessage = config.systemInitMessage;\r\n this.env = env;\r\n this.commands = commands;\r\n this.redis = new RedisClient(env);\r\n this.modelAPI = new OpenAIAPI(env); // \u521D\u59CB\u5316\u4E3A OpenAIAPI\uFF0C\u7A0D\u540E\u4F1A\u6839\u636E\u9700\u8981\u66F4\u65B0\r\n }\r\n\r\n private async initializeModelAPI(userId: string): Promise {\r\n const currentModel = await this.getCurrentModel(userId);\r\n console.log(`Initializing API for model: ${currentModel}`);\r\n \r\n const config = getConfig(this.env);\r\n \r\n if (config.openaiModels.includes(currentModel)) {\r\n return new OpenAIAPI(this.env);\r\n } else if (config.googleModels.includes(currentModel)) {\r\n return new GeminiAPI(this.env);\r\n } else if (config.groqModels.includes(currentModel)) {\r\n return new GroqAPI(this.env);\r\n } else if (config.claudeModels.includes(currentModel)) {\r\n return new ClaudeAPI(this.env);\r\n } else if (config.azureModels.includes(currentModel)) { // \u65B0\u589E Azure \u6A21\u578B\u68C0\u67E5\r\n return new AzureAPI(this.env);\r\n }\r\n \r\n // \u5982\u679C\u6CA1\u6709\u5339\u914D\u7684\u6A21\u578B,\u4F7F\u7528\u9ED8\u8BA4\u7684 OpenAI API\r\n console.warn(`Unknown model: ${currentModel}. Falling back to OpenAI API.`);\r\n return new OpenAIAPI(this.env);\r\n }\r\n\r\n public async executeCommand(commandName: string, chatId: number, args: string[]): Promise {\r\n const command = this.commands.find(cmd => cmd.name === commandName) as Command | undefined;\r\n if (command) {\r\n await command.action(chatId, this, args);\r\n } else {\r\n console.log(`Unknown command: ${commandName}`);\r\n const language = await this.getUserLanguage(chatId.toString());\r\n // \u4F7F\u7528 'command_not_found' \u4F5C\u4E3A\u7FFB\u8BD1\u952E\r\n await this.sendMessage(chatId, translate('command_not_found', language));\r\n }\r\n }\r\n\r\n async sendMessage(chatId: number, text: string, options: { parse_mode?: 'Markdown' | 'HTML', reply_markup?: string } = {}): Promise {\r\n const messages = splitMessage(text);\r\n const results: TelegramTypes.SendMessageResult[] = [];\r\n\r\n for (const message of messages) {\r\n const url = `${this.apiUrl}/sendMessage`;\r\n console.log(`Sending message part (length: ${message.length})`);\r\n try {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n chat_id: chatId,\r\n text: message,\r\n parse_mode: options.parse_mode, // \u53EA\u6709\u5728\u660E\u786E\u6307\u5B9A\u65F6\u624D\u4F7F\u7528 parse_mode\r\n reply_markup: options.reply_markup,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error(`Telegram API error: ${response.statusText}`, errorText);\r\n throw new Error(`Telegram API error: ${response.statusText}\\n${errorText}`);\r\n }\r\n\r\n const result = await response.json() as TelegramTypes.SendMessageResult;\r\n results.push(result);\r\n } catch (error) {\r\n console.error('Error sending message part:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n async handleUpdate(update: TelegramTypes.Update): Promise {\r\n if (update.callback_query) {\r\n await this.handleCallbackQuery(update.callback_query);\r\n } else if (update.message && update.message.text) {\r\n const chatId = update.message.chat.id;\r\n const userId = update.message.from?.id?.toString();\r\n if (!userId) {\r\n console.error('User ID is undefined');\r\n return;\r\n }\r\n const text = update.message.text;\r\n const language = await this.getUserLanguage(userId);\r\n\r\n if (this.isUserWhitelisted(userId)) {\r\n if (text.startsWith('/')) {\r\n const [commandName, ...args] = text.slice(1).split(' ');\r\n await this.executeCommand(commandName, chatId, args);\r\n } else {\r\n try {\r\n await sendChatAction(chatId, 'typing', this.env);\r\n this.modelAPI = await this.initializeModelAPI(userId);\r\n const context = await this.getContext(userId);\r\n const currentModel = await this.getCurrentModel(userId);\r\n\r\n let messages: Message[] = [];\r\n if (currentModel.startsWith('gemini-')) {\r\n messages = [\r\n ...(context ? [{ role: 'user' as const, content: context }] : []),\r\n { role: 'user' as const, content: text }\r\n ];\r\n } else {\r\n messages = [\r\n { role: 'system' as const, content: this.systemMessage },\r\n ...(context ? [{ role: 'user' as const, content: context }] : []),\r\n { role: 'user' as const, content: text }\r\n ];\r\n }\r\n\r\n console.log(`Current modelAPI type: ${this.modelAPI.constructor.name}`);\r\n console.log(`Generating response with model: ${currentModel}`);\r\n const response = await this.modelAPI.generateResponse(messages, currentModel);\r\n console.log(`Generated response length: ${response.length}`);\r\n const formattedResponse = this.formatResponse(response);\r\n\r\n console.log(`Formatted response length: ${formattedResponse.length}`);\r\n // \u4F7F\u7528 sendMessageWithFallback \u65B9\u6CD5\u53D1\u9001\u6A21\u578B\u751F\u6210\u7684\u54CD\u5E94\r\n await this.sendMessageWithFallback(chatId, formattedResponse);\r\n\r\n await this.storeContext(userId, `User: ${text}\\nAssistant: ${response}`);\r\n } catch (error) {\r\n console.error('Error in handleUpdate:', error);\r\n const errorMessage = error instanceof Error ? error.message : 'An unknown error occurred';\r\n // \u9519\u8BEF\u6D88\u606F\u4F7F\u7528\u666E\u901A\u7684 sendMessage \u65B9\u6CD5\r\n await this.sendMessage(chatId, translate('error', language) + ': ' + errorMessage);\r\n }\r\n }\r\n } else {\r\n // \u672A\u6388\u6743\u6D88\u606F\u4F7F\u7528 sendMessageWithFallback \u65B9\u6CD5\r\n await this.sendMessageWithFallback(chatId, translate('unauthorized', language));\r\n }\r\n }\r\n }\r\n\r\n async handleCallbackQuery(callbackQuery: TelegramTypes.CallbackQuery): Promise {\r\n const chatId = callbackQuery.message?.chat.id;\r\n const userId = callbackQuery.from.id.toString();\r\n const data = callbackQuery.data;\r\n\r\n if (!chatId || !data) return;\r\n\r\n if (data.startsWith('lang_')) {\r\n const newLanguage = data.split('_')[1] as SupportedLanguages;\r\n await this.setUserLanguage(userId, newLanguage);\r\n await this.sendMessageWithFallback(chatId, translate('language_changed', newLanguage) + translate(`language_${newLanguage}`, newLanguage));\r\n } else if (data.startsWith('model_')) {\r\n const newModel = data.split('_')[1];\r\n await this.setCurrentModel(userId, newModel);\r\n const language = await this.getUserLanguage(userId);\r\n await this.sendMessageWithFallback(chatId, translate('model_changed', language) + newModel);\r\n await this.clearContext(userId);\r\n }\r\n\r\n // Answer the callback query to remove the loading state\r\n await fetch(`${this.apiUrl}/answerCallbackQuery`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ callback_query_id: callbackQuery.id })\r\n });\r\n }\r\n\r\n async getUserLanguage(userId: string): Promise {\r\n const language = await this.redis.get(`language:${userId}`);\r\n return (language as SupportedLanguages) || 'en';\r\n }\r\n\r\n async setUserLanguage(userId: string, language: SupportedLanguages): Promise {\r\n await this.redis.setLanguage(userId, language);\r\n }\r\n\r\n async getCurrentModel(userId: string): Promise {\r\n const model = await this.redis.get(`model:${userId}`);\r\n return model || this.modelAPI.getDefaultModel();\r\n }\r\n\r\n async setCurrentModel(userId: string, model: string): Promise {\r\n await this.redis.set(`model:${userId}`, model);\r\n console.log(`Switching to model: ${model}`);\r\n // \u5728\u8FD9\u91CC\u91CD\u65B0\u521D\u59CB\u5316 modelAPI\uFF0C\u4F7F\u7528\u7528\u6237ID\r\n this.modelAPI = await this.initializeModelAPI(userId);\r\n console.log(`Current modelAPI type: ${this.modelAPI.constructor.name}`);\r\n }\r\n\r\n getAvailableModels(): string[] {\r\n return this.modelAPI.getAvailableModels();\r\n }\r\n\r\n isValidModel(model: string): boolean {\r\n return this.modelAPI.isValidModel(model);\r\n }\r\n\r\n async storeContext(userId: string, context: string): Promise {\r\n await this.redis.appendContext(userId, context);\r\n }\r\n\r\n async getContext(userId: string): Promise {\r\n return await this.redis.get(`context:${userId}`);\r\n }\r\n\r\n async clearContext(userId: string): Promise {\r\n await this.redis.del(`context:${userId}`);\r\n const language = await this.getUserLanguage(userId);\r\n await this.sendMessageWithFallback(parseInt(userId), translate('new_conversation', language));\r\n }\r\n\r\n async summarizeHistory(userId: string): Promise {\r\n // \u786E\u4FDD\u4F7F\u7528\u6700\u65B0\u7684\u6A21\u578B\r\n this.modelAPI = await this.initializeModelAPI(userId);\r\n\r\n const context = await this.getContext(userId);\r\n const language = await this.getUserLanguage(userId);\r\n if (!context) {\r\n return translate('no_history', language);\r\n }\r\n const languageNames = {\r\n 'en': 'English',\r\n 'zh': 'Chinese',\r\n 'es': 'Spanish'\r\n };\r\n const currentModel = await this.getCurrentModel(userId);\r\n console.log(`Summarizing history with model: ${currentModel}`);\r\n\r\n let messages: Message[];\r\n if (currentModel.startsWith('gemini-')) {\r\n // \u4E3A Gemini API \u521B\u5EFA\u7279\u5B9A\u7684\u6D88\u606F\u683C\u5F0F\r\n messages = [\r\n { role: 'user', content: `Please summarize the following conversation in ${languageNames[language]}:\\n\\n${context}` }\r\n ];\r\n } else {\r\n // \u4E3A OpenAI API \u4FDD\u6301\u539F\u6709\u7684\u6D88\u606F\u683C\u5F0F\r\n messages = [\r\n { role: 'system', content: `Summarize the following conversation in ${languageNames[language]}:` },\r\n { role: 'user', content: context }\r\n ];\r\n }\r\n\r\n const summary = await this.modelAPI.generateResponse(messages, currentModel);\r\n return `${translate('history_summary', language)}\\n\\n${summary}`;\r\n }\r\n\r\n formatResponse(response: string): string {\r\n const codeBlockRegex = /```(\\w+)?\\n([\\s\\S]+?)```/g;\r\n return response.replace(codeBlockRegex, (match, language, code) => {\r\n return formatCodeBlock(code.trim(), language || '');\r\n });\r\n }\r\n\r\n isUserWhitelisted(userId: string): boolean {\r\n return this.whitelistedUsers.includes(userId);\r\n }\r\n\r\n async handleWebhook(request: Request): Promise {\r\n if (request.method !== 'POST') {\r\n return new Response('Method Not Allowed', { status: 405 });\r\n }\r\n\r\n try {\r\n const update: TelegramTypes.Update = await request.json();\r\n await this.handleUpdate(update);\r\n return new Response('OK', { status: 200 });\r\n } catch (error) {\r\n console.error('Error processing webhook:', error);\r\n return new Response('Internal Server Error', { status: 500 });\r\n }\r\n }\r\n\r\n async sendPhoto(chatId: number, photo: string | Uint8Array, options: { caption?: string } = {}): Promise {\r\n const url = `${this.apiUrl}/sendPhoto`;\r\n const formData = new FormData();\r\n formData.append('chat_id', chatId.toString());\r\n\r\n if (typeof photo === 'string') {\r\n formData.append('photo', photo);\r\n } else {\r\n const blob = new Blob([photo], { type: 'image/png' });\r\n formData.append('photo', blob, 'image.png');\r\n }\r\n\r\n if (options.caption) {\r\n formData.append('caption', options.caption);\r\n }\r\n\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n body: formData,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n }\r\n\r\n async setWebhook(url: string): Promise {\r\n const setWebhookUrl = `${this.apiUrl}/setWebhook`;\r\n const response = await fetch(setWebhookUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({ url }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Failed to set webhook: ${response.statusText}`);\r\n }\r\n\r\n const result: { ok: boolean; description?: string } = await response.json();\r\n if (!result.ok) {\r\n throw new Error(`Telegram API error: ${result.description}`);\r\n }\r\n }\r\n\r\n async sendMessageWithFallback(chatId: number, text: string): Promise {\r\n const messages = splitMessage(text);\r\n const results: TelegramTypes.SendMessageResult[] = [];\r\n\r\n for (const message of messages) {\r\n try {\r\n // \u9996\u5148\u5C1D\u8BD5\u4F7F\u7528 Markdown\r\n const result = await this.sendMessage(chatId, message, { parse_mode: 'Markdown' });\r\n results.push(...result); // \u4F7F\u7528\u5C55\u5F00\u8FD0\u7B97\u7B26\u6765\u6DFB\u52A0\u7ED3\u679C\r\n } catch (error) {\r\n console.error('Error sending message with Markdown, falling back to plain text:', error);\r\n // \u5982\u679C Markdown \u5931\u8D25\uFF0C\u9000\u56DE\u5230\u7EAF\u6587\u672C\r\n const plainTextResult = await this.sendMessage(chatId, message);\r\n results.push(...plainTextResult); // \u4F7F\u7528\u5C55\u5F00\u8FD0\u7B97\u7B26\u6765\u6DFB\u52A0\u7ED3\u679C\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n}\r\n\r\nexport default TelegramBot;", "import { Env } from './env';\r\nimport TelegramBot from './api/telegram';\r\n\r\nexport default {\r\n async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise {\r\n const bot = new TelegramBot(env);\r\n const url = new URL(request.url);\r\n\r\n console.log(`Received request for path: ${url.pathname}`);\r\n\r\n try {\r\n // Handle Telegram webhook\r\n if (url.pathname === '/webhook') {\r\n console.log('Processing webhook request');\r\n return await bot.handleWebhook(request);\r\n }\r\n\r\n // Handle root path\r\n if (url.pathname === '/' || url.pathname === '') {\r\n console.log('Serving root path');\r\n return new Response('Hello! This is your Telegram bot worker.', { \r\n status: 200,\r\n headers: { 'Content-Type': 'text/plain' }\r\n });\r\n }\r\n\r\n // Handle all other requests\r\n console.log('Path not found');\r\n return new Response('Not Found', { \r\n status: 404,\r\n headers: { 'Content-Type': 'text/plain' }\r\n });\r\n } catch (error) {\r\n console.error('Error processing request:', error);\r\n const errorMessage = error instanceof Error ? error.message : 'An unknown error occurred';\r\n return new Response(`Internal Server Error: ${errorMessage}`, { \r\n status: 500,\r\n headers: { 'Content-Type': 'text/plain' }\r\n });\r\n }\r\n },\r\n};"], + "mappings": "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", "names": [] } diff --git a/src/api/azure.ts b/src/api/azure.ts new file mode 100644 index 0000000..e6f2e9a --- /dev/null +++ b/src/api/azure.ts @@ -0,0 +1,74 @@ +import { Env, getConfig } from '../env'; +import { ModelAPIInterface } from './model_api_interface'; +import { Message } from './openai_api'; + +interface AzureChatCompletionResponse { + id: string; + object: string; + created: number; + choices: Array<{ + index: number; + message: { + role: string; + content: string; + }; + finish_reason: string; + }>; +} + +export class AzureAPI implements ModelAPIInterface { + private apiKey: string; + private baseUrl: string; + private models: string[]; + private defaultModel: string; + + constructor(env: Env) { + const config = getConfig(env); + this.apiKey = config.azureApiKey; + this.baseUrl = config.azureEndpoint; + this.models = config.azureModels; + this.defaultModel = this.models[0]; + } + + async generateResponse(messages: Message[], model?: string): Promise { + const useModel = model || this.defaultModel; + const url = `${this.baseUrl}/openai/deployments/${useModel}/chat/completions?api-version=2024-02-01`; + + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'api-key': this.apiKey, + }, + body: JSON.stringify({ + messages: messages, + }), + }); + + if (!response.ok) { + const errorText = await response.text(); + console.error(`Azure API error: ${response.statusText}`, errorText); + throw new Error(`Azure API error: ${response.statusText}\n${errorText}`); + } + + const data: AzureChatCompletionResponse = await response.json(); + if (!data.choices || data.choices.length === 0) { + throw new Error('Azure API 未生成任何响应'); + } + return data.choices[0].message.content.trim(); + } + + isValidModel(model: string): boolean { + return this.models.includes(model); + } + + getDefaultModel(): string { + return this.defaultModel; + } + + getAvailableModels(): string[] { + return this.models; + } +} + +export default AzureAPI; \ No newline at end of file diff --git a/src/api/telegram.ts b/src/api/telegram.ts index 789d532..ac7ca2f 100644 --- a/src/api/telegram.ts +++ b/src/api/telegram.ts @@ -9,6 +9,7 @@ import { ModelAPIInterface } from './model_api_interface'; import GeminiAPI from './gemini'; import GroqAPI from './groq'; import ClaudeAPI from './claude'; +import AzureAPI from './azure'; // 新增 AzureAPI 导入 export class TelegramBot { private token: string; @@ -46,6 +47,8 @@ export class TelegramBot { return new GroqAPI(this.env); } else if (config.claudeModels.includes(currentModel)) { return new ClaudeAPI(this.env); + } else if (config.azureModels.includes(currentModel)) { // 新增 Azure 模型检查 + return new AzureAPI(this.env); } // 如果没有匹配的模型,使用默认的 OpenAI API diff --git a/src/config/commands.ts b/src/config/commands.ts index d2ab74d..e5e9b14 100644 --- a/src/config/commands.ts +++ b/src/config/commands.ts @@ -23,7 +23,7 @@ export const commands: Command[] = [ const language = await bot.getUserLanguage(userId); const currentModel = await bot.getCurrentModel(userId); const welcomeMessage = translate('welcome', language) + '\n' + - translate('current_model', language) + currentModel; + translate('current_model', language) + currentModel; await bot.sendMessageWithFallback(chatId, welcomeMessage); }, }, @@ -56,7 +56,8 @@ export const commands: Command[] = [ ...config.openaiModels, ...config.googleModels, ...config.groqModels, - ...config.claudeModels // 添加 Claude 模型 + ...config.claudeModels, + ...config.azureModels, // 新增 Azure 模型 ]; const keyboard = { inline_keyboard: availableModels.map(model => [{text: model, callback_data: `model_${model}`}]) diff --git a/src/env.ts b/src/env.ts index 23c39dc..f98746c 100644 --- a/src/env.ts +++ b/src/env.ts @@ -25,6 +25,9 @@ export interface Env { CLAUDE_API_KEY: string; CLAUDE_MODELS: string; CLAUDE_ENDPOINT?: string; + AZURE_API_KEY: string; // Azure API 密钥 + AZURE_MODELS: string; // 逗号分隔的 Azure 模型列表 + AZURE_ENDPOINT: string; // Azure API 端点 } const getEnvOrDefault = (env: Env, key: keyof Env, defaultValue: string): string => { @@ -37,9 +40,10 @@ export const getConfig = (env: Env) => { const hasGoogle = !!env.GOOGLE_MODEL_KEY; const hasGroq = !!env.GROQ_API_KEY; const hasClaude = !!env.CLAUDE_API_KEY; + const hasAzure = !!env.AZURE_API_KEY; - if (!hasOpenAI && !hasGoogle && !hasGroq && !hasClaude) { - throw new Error('At least one model API key must be set (OpenAI, Google, Groq, or Claude)'); + if (!hasOpenAI && !hasGoogle && !hasGroq && !hasClaude && !hasAzure) { + throw new Error('At least one model API key must be set (OpenAI, Google, Groq, Claude, or Azure)'); } return { @@ -71,5 +75,8 @@ export const getConfig = (env: Env) => { claudeApiKey: env.CLAUDE_API_KEY, claudeModels: env.CLAUDE_MODELS ? env.CLAUDE_MODELS.split(',').map(model => model.trim()) : [], claudeEndpoint: getEnvOrDefault(env, 'CLAUDE_ENDPOINT', 'https://api.anthropic.com/v1'), + azureApiKey: env.AZURE_API_KEY, + azureModels: env.AZURE_MODELS ? env.AZURE_MODELS.split(',').map(model => model.trim()) : [], + azureEndpoint: env.AZURE_ENDPOINT, }; }; \ No newline at end of file