UNPKG

whatsapp-claude-gpt

Version:

WhatsApp-Claude-GPT is a WhatsApp chatbot that supports multiple AI providers for chat, optional image generation/editing, and voice (speech-to-text and text-to-speech). It’s built for natural, contextual conversations and can now also handle reminders an

320 lines (312 loc) 15.4 kB
import { Tool } from "openai/src/resources/responses/responses"; import { AIProvider } from "../interfaces/ai-interfaces"; import { AIConfig, CONFIG } from "./index"; import { convertCompletionsToolsToResponses } from "../utils"; import { Chat } from "whatsapp-web.js"; const openAIWebSearch: Tool = { type: "web_search", user_location: { type: "approximate" }, search_context_size: "medium" } ; const generate_speech = { type: "function", function: { name: "generate_speech", description: "Generates a voice audio from text using AI. Instructions for tone and style can be customized.", parameters: { type: "object", properties: { input: { type: "string", description: "The text to be converted into audio." }, instructions: { type: "string", description: "Instructions for the TTS model regarding intonation and style, such as emotion, tone, or accent." }, msg_id: { type: "string", description: "msg_id of the message where the audio generation request was made." }, voice_gender:{ type: "string", enum: ["male", "female","undefined"], description: "The gender of the voice to be used." } }, required: ["input", "instructions", "msg_id"], additionalProperties: false } }, strict: false } const generate_image = { type: "function", function: { name: "generate_image", description:`Generate images from text prompt`, parameters: { type: "object", properties: { msg_id: { type: "string", description: "msg_id of the message where the image generation request was made." }, chatId: { type: "string", description: "chatId of the actual chat." }, prompt: { type: "string", description: 'Description of the image to generate' }, background: { type: ["string","null"], enum: ["opaque","transparent","auto"], description: "Transparent or opaque background. OPTIONAL", nullable: true }, output_format: { type: ["string","null"], enum: ["png","jpeg","webp"], description: "Default png. OPTIONAL", nullable: true }, send_as: { type: ["string", "null"], enum: ["image", "sticker"], description: "Determines whether the generated media will be sent as an image or as a sticker.", }, size: { type: ["string","null"], enum: ["1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "auto"], description: "The size of the generated images. Default \"auto\". OPTIONAL", nullable: true } }, required: ["msg_id","chatId","prompt"], additionalProperties: false } }, strict: true } const generate_image_withedit = { type: "function", function: { name: "generate_image", description: `Generate or edit images. Use this function to: - Create NEW images from scratch (when no reference images are provided) - Transform or edit existing images (when reference images are provided)`, parameters: { type: "object", properties: { msg_id: { type: "string", description: "msg_id of the message where the image generation request was made." }, chatId: { type: "string", description: "chatId of the actual chat." }, prompt: { type: "string", description: 'Description of the image to generate or changes to apply. Important: Never use real person names or msg_id in the prompt; always refer to subjects as "the person in the first image", etc.' }, image_msg_ids: { type: ["array", "null"], description: "Array of image msg_ids to use as references. Leave null or empty to create from scratch. (Optional)", items: { type: "string" }, nullable: true }, send_as: { type: ["string", "null"], enum: ["image", "sticker"], description: "Determines whether the generated media will be sent as an image or as a sticker.", }, background: { type: ["string","null"], enum: ["opaque","transparent","auto"], description: "Transparent or opaque background. OPTIONAL", nullable: true }, output_format: { type: ["string","null"], enum: ["png","jpeg","webp"], description: "Default png. OPTIONAL", nullable: true }, size: { type: ["string","null"], enum: ["1024x1024", "1536x1024", "1024x1536", "auto"], description: "The size of the generated images. Default \"auto\". OPTIONAL", nullable: true } }, required: ["msg_id","chatId","prompt"], additionalProperties: false } }, strict: false } const reminder_manager = { type: "function", strict: false, function: { name: "reminder_manager", description: `Complete reminder management system with recurrence support. Use this function to: - LIST/GET: Retrieve all pending reminders for the user or group (use action 'list') - CREATE: Add new reminders with a message, date/time, and optional recurrence (use action 'create') - UPDATE: Modify existing reminders by their ID (use action 'update') - DELETE: Remove reminders by their ID (use action 'delete') - DEACTIVATE: Temporarily disable a reminder (use action 'deactivate') - REACTIVATE: Re-enable a disabled reminder (use action 'reactivate') Recurrence types: 'none', 'minutes', 'daily', 'weekly', 'monthly' Always use 'list' first to get reminder IDs before updating or deleting.`, parameters: { type: "object", properties: { action: { type: "string", enum: ["list", "create", "update", "delete", "deactivate", "reactivate"], description: "Action to perform on reminders" }, message: { type: ["string", "null"], description: "The reminder message text. REQUIRED for 'create' and 'update' actions.", nullable: true }, reminder_date: { type: ["string", "null"], description: "When the reminder should trigger, in yyyy-MM-ddTHH:mm:ss format (e.g., '2024-12-25T10:30:00'). REQUIRED for 'create' and 'update' actions.", nullable: true }, reminder_date_timezone: { type: ["string", "null"], description: `Specifies the IANA timezone (e.g., 'America/Santiago') that applies to the reminder date and time. By default, '${CONFIG.BotConfig.botTimezone}' will be used.`, nullable: true }, reminder_id: { type: ["string", "null"], description: "The unique identifier of the reminder. REQUIRED for 'update', 'delete', 'deactivate', and 'reactivate' actions.", nullable: true }, recurrence_type: { type: ["string", "null"], enum: ["none", "minutes", "daily", "weekly", "monthly"], description: "Type of recurrence for the reminder. 'none' for one-time reminders. Optional for 'create' and 'update' actions.", nullable: true }, recurrence_interval: { type: ["number", "null"], description: "Interval for recurrence (e.g., 2 for every 2 days/weeks/months). Default is 1. Optional for 'create' and 'update' actions.", nullable: true }, recurrence_end_date: { type: ["string", "null"], description: "End date for recurrence in yyyy-MM-ddTHH:mm:ss format. Optional for 'create' and 'update' actions.", nullable: true }, recurrence_end_date_timezone: { type: ["string", "null"], description: `Timezone for the recurrence end date. By default, '${CONFIG.BotConfig.botTimezone}' will be used.`, nullable: true }, msg_id: { type: "string", description: "msg_id of the message where request was made" } }, required: ["action","msg_id"], additionalProperties: false } } } const user_memory_manager = { "type": "function", "strict": false, "function": { "name": "user_memory_manager", "description": "Call this function whenever you learn new or updated user details (name, age, interests, etc.)—no need to wait for a request. " + "Always keep memory accurate for better, personalized responses.", "parameters": { "type": "object", "properties": { "action": { "type": "string", "enum": ["get", "save", "clear"], "description": "'get' to retrieve user memory, 'save' to update it, 'clear' to delete user memory." }, "chat_id": { "type": "string", "description": "Chat identifier (context of the user)." }, "author_id": { "type": "string", "description": "Author ID (required)." }, "memory_data": { "type": ["object", "null"], "description": "Full object to store as user memory. Provide all fields when saving; replaces existing memory.", "properties": { "real_name": { "type": ["string", "null"], "nullable": true }, "nicknames": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true }, "age": { "type": ["number", "null"], "nullable": true }, "profession": { "type": ["string", "null"], "nullable": true }, "location": { "type": ["string", "null"], "nullable": true }, "interests": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true }, "likes": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true }, "dislikes": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true }, "relationships": { "type": ["object", "null"], "nullable": true }, "running_jokes": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true }, "jargon": { "type": ["object", "null"], "nullable": true }, "notes": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true } }, "nullable": true, "additionalProperties": false } }, "required": ["action", "chat_id", "author_id"], "additionalProperties": false } } } const group_memory_manager = { "type": "function", "strict": false, "function": { "name": "group_memory_manager", "description": "Call this function when you learn new group info (interests, topics, jokes, etc.). Update memory without waiting for a request.", "parameters": { "type": "object", "properties": { "action": { "type": "string", "enum": ["get", "save", "clear"], "description": "'get' to retrieve group memory, 'save' to update it, 'clear' to delete group memory." }, "chat_id": { "type": "string", "description": "Unique identifier for the chat/group." }, "memory_data": { "type": ["object", "null"], "description": "Group memory object to save. Replaces existing group memory.", "properties": { "group_interests": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true }, "recurring_topics": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true }, "group_likes": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true }, "group_dislikes": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true }, "group_jargon": { "type": ["object", "null"], "nullable": true }, "group_running_jokes": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true }, "group_notes": { "type": ["array", "null"], "items": { "type": "string" }, "nullable": true } }, "nullable": true, "additionalProperties": false } }, "required": ["action", "chat_id"], "additionalProperties": false } } } export function getTools(chatData: Chat) { const tools = []; if(AIConfig.ImageConfig.enabled) tools.push(AIConfig.ImageConfig.canEditImages? generate_image_withedit : generate_image); tools.push(reminder_manager); if(AIConfig.SpeechConfig.enabled) tools.push(generate_speech); if(CONFIG.BotConfig.memoriesEnabled) { tools.push(user_memory_manager); if(chatData.isGroup) tools.push(group_memory_manager); } switch (AIConfig.ChatConfig.provider) { case AIProvider.CLAUDE: return openaiToolsToClaudeTools(tools); case AIProvider.OPENAI: if(AIConfig.ChatConfig.model.includes('nano')) return [...convertCompletionsToolsToResponses(tools)] return [openAIWebSearch, ...convertCompletionsToolsToResponses(tools)] default: return tools; } } function openaiToolsToClaudeTools(inputTools) { return inputTools .filter(tool => tool.type === "function" && tool.function) .map(tool => { const fn = tool.function; return { name: fn.name, description: fn.description, input_schema: fn.parameters }; }); }