ChatGPT Prompt Enhancer

Enhance your ChatGPT prompts with AI to make them more effective and detailed

Size

10.9 KB

Version

1.1.1

Created

Nov 5, 2025

Updated

3 months ago

1// ==UserScript==
2// @name		ChatGPT Prompt Enhancer
3// @description		Enhance your ChatGPT prompts with AI to make them more effective and detailed
4// @version		1.1.1
5// @match		https://*.chatgpt.com/*
6// @icon		https://cdn.oaistatic.com/assets/favicon-l4nq08hd.svg
7// @grant		GM.getValue
8// @grant		GM.setValue
9// ==/UserScript==
10(function() {
11    'use strict';
12
13    console.log('ChatGPT Prompt Enhancer extension loaded');
14
15    // Debounce function to prevent excessive calls
16    function debounce(func, wait) {
17        let timeout;
18        return function executedFunction(...args) {
19            const later = () => {
20                clearTimeout(timeout);
21                func(...args);
22            };
23            clearTimeout(timeout);
24            timeout = setTimeout(later, wait);
25        };
26    }
27
28    // Create the enhance button
29    function createEnhanceButton() {
30        const button = document.createElement('button');
31        button.type = 'button';
32        button.className = 'composer-btn';
33        button.id = 'prompt-enhancer-btn';
34        button.setAttribute('aria-label', 'Enhance prompt with AI');
35        button.title = 'Enhance prompt with AI';
36        button.innerHTML = `
37            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
38                <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" 
39                      stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
40            </svg>
41        `;
42        button.style.cssText = `
43            display: flex;
44            align-items: center;
45            justify-content: center;
46            width: 36px;
47            height: 36px;
48            border-radius: 8px;
49            cursor: pointer;
50            transition: all 0.2s;
51            background: transparent;
52            border: none;
53            color: var(--text-primary);
54        `;
55
56        button.addEventListener('mouseenter', () => {
57            button.style.backgroundColor = 'var(--surface-hover, rgba(0, 0, 0, 0.05))';
58        });
59
60        button.addEventListener('mouseleave', () => {
61            button.style.backgroundColor = 'transparent';
62        });
63
64        button.addEventListener('click', handleEnhanceClick);
65
66        return button;
67    }
68
69    // Get the current prompt text from the textarea
70    function getPromptText() {
71        const promptTextarea = document.querySelector('#prompt-textarea');
72        if (!promptTextarea) {
73            console.error('Prompt textarea not found');
74            return '';
75        }
76        return promptTextarea.textContent.trim();
77    }
78
79    // Set the prompt text in the textarea
80    function setPromptText(text) {
81        const promptTextarea = document.querySelector('#prompt-textarea');
82        if (!promptTextarea) {
83            console.error('Prompt textarea not found');
84            return false;
85        }
86
87        // Clear existing content
88        promptTextarea.innerHTML = '';
89        
90        // Create a new paragraph element with the text
91        const p = document.createElement('p');
92        p.textContent = text;
93        promptTextarea.appendChild(p);
94
95        // Trigger input event to update ChatGPT's internal state
96        const inputEvent = new Event('input', { bubbles: true, cancelable: true });
97        promptTextarea.dispatchEvent(inputEvent);
98
99        console.log('Prompt text updated successfully');
100        return true;
101    }
102
103    // Show loading state
104    function showLoadingState(button) {
105        button.disabled = true;
106        button.style.opacity = '0.5';
107        button.style.cursor = 'not-allowed';
108        button.innerHTML = `
109            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
110                <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" opacity="0.25"/>
111                <path d="M12 2a10 10 0 0 1 10 10" stroke="currentColor" stroke-width="2" stroke-linecap="round">
112                    <animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite"/>
113                </path>
114            </svg>
115        `;
116    }
117
118    // Reset button state
119    function resetButtonState(button) {
120        button.disabled = false;
121        button.style.opacity = '1';
122        button.style.cursor = 'pointer';
123        button.innerHTML = `
124            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
125                <path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" 
126                      stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
127            </svg>
128        `;
129    }
130
131    // Show notification
132    function showNotification(message, type = 'info') {
133        const notification = document.createElement('div');
134        notification.style.cssText = `
135            position: fixed;
136            top: 20px;
137            right: 20px;
138            background: ${type === 'error' ? '#ef4444' : type === 'success' ? '#10b981' : '#3b82f6'};
139            color: white;
140            padding: 12px 20px;
141            border-radius: 8px;
142            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
143            z-index: 10000;
144            font-size: 14px;
145            max-width: 300px;
146            animation: slideIn 0.3s ease-out;
147        `;
148        notification.textContent = message;
149
150        // Add animation
151        const style = document.createElement('style');
152        style.textContent = `
153            @keyframes slideIn {
154                from {
155                    transform: translateX(400px);
156                    opacity: 0;
157                }
158                to {
159                    transform: translateX(0);
160                    opacity: 1;
161                }
162            }
163        `;
164        document.head.appendChild(style);
165
166        document.body.appendChild(notification);
167
168        setTimeout(() => {
169            notification.style.transition = 'opacity 0.3s ease-out';
170            notification.style.opacity = '0';
171            setTimeout(() => notification.remove(), 300);
172        }, 3000);
173    }
174
175    // Handle enhance button click
176    async function handleEnhanceClick() {
177        console.log('Enhance button clicked');
178        
179        const button = document.querySelector('#prompt-enhancer-btn');
180        const currentPrompt = getPromptText();
181
182        if (!currentPrompt) {
183            showNotification('Please enter a prompt first', 'error');
184            return;
185        }
186
187        console.log('Current prompt:', currentPrompt);
188
189        try {
190            showLoadingState(button);
191            showNotification('Enhancing your prompt...', 'info');
192
193            // Call AI to enhance the prompt
194            const enhancedPrompt = await RM.aiCall(
195                `You are a prompt engineering expert. Enhance the following prompt to make it more effective, detailed, and clear for ChatGPT. 
196                
197The enhanced prompt should:
198- Be more specific and detailed
199- Include relevant context
200- Use clear instructions
201- Be well-structured
202- Maintain the original intent
203
204Original prompt: "${currentPrompt}"
205
206Return ONLY the enhanced prompt text, nothing else.`
207            );
208
209            console.log('Enhanced prompt:', enhancedPrompt);
210
211            if (enhancedPrompt && enhancedPrompt.trim()) {
212                setPromptText(enhancedPrompt.trim());
213                showNotification('Prompt enhanced successfully!', 'success');
214                
215                // Store usage stats
216                const usageCount = await GM.getValue('enhancer_usage_count', 0);
217                await GM.setValue('enhancer_usage_count', usageCount + 1);
218                console.log('Total enhancements:', usageCount + 1);
219            } else {
220                throw new Error('Empty response from AI');
221            }
222
223        } catch (error) {
224            console.error('Error enhancing prompt:', error);
225            showNotification('Failed to enhance prompt. Please try again.', 'error');
226        } finally {
227            resetButtonState(button);
228        }
229    }
230
231    // Insert the enhance button into the composer
232    function insertEnhanceButton() {
233        // Find the trailing area where other buttons are
234        const trailingArea = document.querySelector('form[data-type="unified-composer"] .flex.items-center.gap-2[class*="trailing"]');
235        
236        if (!trailingArea) {
237            console.error('Trailing area not found');
238            return false;
239        }
240
241        // Check if button already exists
242        if (document.querySelector('#prompt-enhancer-btn')) {
243            console.log('Enhance button already exists');
244            return true;
245        }
246
247        // Find the inner flex container
248        const innerContainer = trailingArea.querySelector('.ms-auto.flex.items-center');
249        
250        if (!innerContainer) {
251            console.error('Inner container not found');
252            return false;
253        }
254
255        // Create and insert the button
256        const enhanceButton = createEnhanceButton();
257        
258        // Insert before the voice mode button
259        const voiceButtonContainer = innerContainer.querySelector('[data-testid="composer-speech-button-container"]');
260        if (voiceButtonContainer) {
261            innerContainer.insertBefore(enhanceButton, voiceButtonContainer);
262        } else {
263            innerContainer.appendChild(enhanceButton);
264        }
265
266        console.log('Enhance button inserted successfully');
267        return true;
268    }
269
270    // Initialize the extension
271    function init() {
272        console.log('Initializing ChatGPT Prompt Enhancer...');
273
274        // Wait for the composer to be ready
275        const checkComposer = setInterval(() => {
276            const composer = document.querySelector('form[data-type="unified-composer"]');
277            if (composer) {
278                clearInterval(checkComposer);
279                console.log('Composer found, inserting enhance button');
280                
281                if (insertEnhanceButton()) {
282                    console.log('Extension initialized successfully');
283                    
284                    // Watch for DOM changes in case ChatGPT rebuilds the composer
285                    const observer = new MutationObserver(debounce(() => {
286                        if (!document.querySelector('#prompt-enhancer-btn')) {
287                            console.log('Button removed, re-inserting...');
288                            insertEnhanceButton();
289                        }
290                    }, 500));
291
292                    observer.observe(document.body, {
293                        childList: true,
294                        subtree: true
295                    });
296                }
297            }
298        }, 500);
299
300        // Stop checking after 10 seconds
301        setTimeout(() => {
302            clearInterval(checkComposer);
303        }, 10000);
304    }
305
306    // Start the extension when DOM is ready
307    if (document.readyState === 'loading') {
308        document.addEventListener('DOMContentLoaded', init);
309    } else {
310        init();
311    }
312
313})();
ChatGPT Prompt Enhancer | Robomonkey