commit fe21504ab51f60c06256ab3fe11a00c4c708b1f3 Author: Leopere Date: Thu May 15 17:09:56 2025 -0400 Initial commit of SnappyMail LLM Email Writing Prompts Plugin with Grok 3 API support diff --git a/.cursor/rules/snappymail-llm-plugin.mdc b/.cursor/rules/snappymail-llm-plugin.mdc new file mode 100644 index 0000000..a3c7d61 --- /dev/null +++ b/.cursor/rules/snappymail-llm-plugin.mdc @@ -0,0 +1,66 @@ +--- +description: +globs: +alwaysApply: false +--- +# SnappyMail LLM Email Writing Prompts Plugin with Grok 3 API Support + +## Overview + +This plugin enhances SnappyMail, a lightweight web-based email client, by integrating AI-driven email writing prompts powered by xAI's Grok 3 API as the primary Large Language Model (LLM) provider, with fallbacks to other LLMs. The purpose is to assist users in drafting professional, concise, or creative emails through context-aware prompt suggestions, leveraging Grok 3's advanced reasoning capabilities. + +## Purpose and Goals + +- **Primary Goal**: Enable SnappyMail users to access Grok 3-generated prompts for drafting emails with high-quality, reasoning-focused outputs. +- **Secondary Goals**: + - Ensure compatibility with SnappyMail's lightweight and privacy-focused design. + - Provide a user-friendly interface for selecting and customizing prompts. + - Maintain performance and security standards for self-hosted environments. + - Allow fallback to other LLM APIs (e.g., OpenAI, Hugging Face) for flexibility. + +## Target Audience + +- **Primary Users**: Individuals and small businesses using SnappyMail for personal or professional email communication, especially those seeking AI-assisted writing with Grok 3's logical outputs. +- **Secondary Users**: System administrators managing SnappyMail instances who want to enhance functionality with Grok 3 integration. +- **Use Cases**: + - Professionals drafting formal emails (e.g., business proposals). + - Casual users writing personal emails with creative tones. + - Non-native speakers needing assistance with grammar and phrasing. + +## Functional Requirements + +### Core Features + +- **Prompt Library**: A set of predefined prompts in categories like Professional, Creative, Assistance, and Quick Replies, optimized for Grok 3's reasoning capabilities. +- **Context-Aware Suggestions**: Analyzes email subject and body to suggest relevant prompts using Grok 3's chain-of-thought reasoning. +- **LLM Integration**: Primary provider is xAI Grok 3 API ([https://api.x.ai/v1/chat/completions](mdc:https:/api.x.ai/v1/chat/completions)), with configurable fallbacks to OpenAI, Hugging Face, or local LLMs. +- **Draft Generation**: Generates email drafts based on prompts and context, supporting multiple iterations (e.g., tone adjustments). +- **Custom Prompts**: Users can create and save custom prompts, stored securely as JSON files. +- **Privacy and Security**: No email data stored beyond API calls, with optional opt-in for context analysis and secure API key storage. + +### User Interface + +- **Compose Window Integration**: A "Smart Prompts" button or sidebar in the email composition interface for Grok 3-powered suggestions. +- **Settings Panel**: Options to configure Grok 3 API key, select model, manage custom prompts, and toggle context analysis. +- **Visual Design**: Matches SnappyMail's minimalist UI with dark mode and mobile responsiveness. + +## Technical Requirements + +- **Platform**: Compatible with SnappyMail v2.12+, PHP 7.4+, and JavaScript ES2018. +- **Plugin Architecture**: Located in `/plugins/llm-prompts/` with files like `index.php`, `js/`, `templates/`, and `config.json`. +- **LLM Integration**: Uses Grok 3 API with OpenAI SDK compatibility, secure API key storage, and fallback logic for other providers. +- **Security**: Encrypts API keys and prompts, sanitizes outputs to prevent XSS, and complies with GDPR. + +## Implementation Plan + +- **Phase 1**: Research and setup Grok 3 API access (2 weeks). +- **Phase 2**: Core development of prompt library and API integration (4 weeks). +- **Phase 3**: UI and settings development (3 weeks). +- **Phase 4**: Testing and security audits (3 weeks). +- **Phase 5**: Release and documentation (2 weeks). + +## References + +- SnappyMail Official Site: [https://snappymail.eu](mdc:https:/snappymail.eu) +- SnappyMail GitHub: [https://github.com/the-djmaze/snappymail](mdc:https:/github.com/the-djmaze/snappymail) +- xAI Grok 3 API: [https://x.ai/api](mdc:https:/x.ai/api) diff --git a/plugins/llm-prompts/config.json b/plugins/llm-prompts/config.json new file mode 100644 index 0000000..52560c8 --- /dev/null +++ b/plugins/llm-prompts/config.json @@ -0,0 +1,6 @@ +{ + "grok3_api_key": "", + "selected_model": "grok-3", + "enable_context_analysis": true, + "custom_prompts": [] +} \ No newline at end of file diff --git a/plugins/llm-prompts/index.php b/plugins/llm-prompts/index.php new file mode 100644 index 0000000..344ba7a --- /dev/null +++ b/plugins/llm-prompts/index.php @@ -0,0 +1,42 @@ +addJs('js/llm-prompts.js'); + $this->addTemplate('templates/llm-prompts.html'); + $this->addHook('filter.compose', 'onFilterCompose'); + $this->addHook('action.pre-send', 'onActionPreSend'); + } + + public function onFilterCompose($oAccount, $oCompose) + { + // Inject UI for Smart Prompts in compose window + // This will be handled by JavaScript + } + + public function onActionPreSend($oAccount, $oMessage) + { + // Validate content before sending if generated by LLM + // Add any necessary validation or sanitization + } + + public function configMapping(): array + { + return [ + 'grok3_api_key' => ['string', ''], + 'selected_model' => ['string', 'grok-3'], + 'enable_context_analysis' => ['bool', true], + 'custom_prompts' => ['json', '[]'] + ]; + } +} \ No newline at end of file diff --git a/plugins/llm-prompts/js/llm-prompts.js b/plugins/llm-prompts/js/llm-prompts.js new file mode 100644 index 0000000..9b8eb8c --- /dev/null +++ b/plugins/llm-prompts/js/llm-prompts.js @@ -0,0 +1,148 @@ +// LLM Prompts Plugin for SnappyMail +// Provides UI and API interaction for AI-driven email writing prompts + +(function () { + 'use strict'; + + // Initialize plugin when DOM is ready + document.addEventListener('DOMContentLoaded', function () { + if (typeof rl !== 'undefined') { + rl.addSettingsViewModel( + 'LLMPromptsSettings', + 'LLMPromptsSettings', + 'LLM Prompts', + 'Settings for AI-driven email writing prompts powered by Grok 3', + true + ); + + // Add UI for Smart Prompts in compose window + rl.addHook('view-model', function (vm) { + if (vm.viewModelName === 'ComposeViewModel') { + initComposeUI(vm); + } + }); + } + }); + + function initComposeUI(composeVM) { + // Add Smart Prompts button or sidebar to compose window + const toolbar = document.querySelector('.compose-toolbar'); + if (toolbar) { + const smartPromptsButton = document.createElement('button'); + smartPromptsButton.className = 'button smart-prompts'; + smartPromptsButton.innerHTML = 'Smart Prompts'; + smartPromptsButton.onclick = function () { + toggleSmartPromptsSidebar(composeVM); + }; + toolbar.appendChild(smartPromptsButton); + } + } + + function toggleSmartPromptsSidebar(composeVM) { + // Toggle visibility of prompts sidebar + let sidebar = document.querySelector('.smart-prompts-sidebar'); + if (!sidebar) { + sidebar = document.createElement('div'); + sidebar.className = 'smart-prompts-sidebar'; + sidebar.innerHTML = getPromptsHTML(); + document.querySelector('.compose-box').appendChild(sidebar); + + // Add event listeners for prompt selection + setupPrompts(sidebar, composeVM); + } else { + sidebar.style.display = sidebar.style.display === 'none' ? 'block' : 'none'; + } + } + + function getPromptsHTML() { + // HTML for prompt categories and suggestions + return ` +

Smart Prompts (Grok 3)

+
+

Professional

+ +
+
+

Creative

+ +
+
+

Assistance

+ +
+
+

Quick Replies

+ +
+
+ + +
+ `; + } + + function setupPrompts(sidebar, composeVM) { + const prompts = sidebar.querySelectorAll('.prompt-category li'); + prompts.forEach(prompt => { + prompt.onclick = function () { + const promptText = this.getAttribute('data-prompt'); + sidebar.querySelector('.context-input textarea').value = promptText; + // Highlight selected prompt + prompts.forEach(p => p.classList.remove('selected')); + this.classList.add('selected'); + }; + }); + } + + function generateDraft(button) { + const sidebar = button.closest('.smart-prompts-sidebar'); + const prompt = sidebar.querySelector('.context-input textarea').value; + const subject = document.querySelector('.compose-subject input').value; + const body = document.querySelector('.compose-body .editor').innerText; + + // Make API call to Grok 3 or configured LLM + fetchLLMDraft(prompt, subject, body).then(draft => { + if (draft) { + // Insert draft into compose body + const editor = document.querySelector('.compose-body .editor'); + editor.innerHTML = draft.replace(/\n/g, '
'); + } + }).catch(error => { + console.error('Error generating draft:', error); + alert('Failed to generate draft. Please check settings.'); + }); + } + + async function fetchLLMDraft(prompt, subject, body) { + // This would make an API call to the backend which handles Grok 3 API interaction + // For now, simulate an API call + const response = await fetch('/?/Api/LLMPrompts/GenerateDraft', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + prompt: prompt, + subject: subject, + body: body, + enableContextAnalysis: rl.settingsGet('LLMPromptsSettings.enable_context_analysis') + }) + }); + + if (!response.ok) { + throw new Error('Network response was not ok'); + } + + const data = await response.json(); + return data.result; + } +})(); \ No newline at end of file diff --git a/plugins/llm-prompts/templates/llm-prompts.html b/plugins/llm-prompts/templates/llm-prompts.html new file mode 100644 index 0000000..84e4a61 --- /dev/null +++ b/plugins/llm-prompts/templates/llm-prompts.html @@ -0,0 +1,42 @@ +
+ + \ No newline at end of file