Size
9.1 KB
Version
1.1.2
Created
Oct 15, 2025
Updated
8 days ago
1// ==UserScript==
2// @name ChatGPT Prompt Enhancer
3// @description Enhance your ChatGPT prompts with AI-powered suggestions
4// @version 1.1.2
5// @match https://*.chatgpt.com/*
6// @icon https://cdn.oaistatic.com/assets/favicon-l4nq08hd.svg
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 console.log('ChatGPT Prompt Enhancer initialized');
12
13 // Debounce function to avoid excessive calls
14 function debounce(func, wait) {
15 let timeout;
16 return function executedFunction(...args) {
17 const later = () => {
18 clearTimeout(timeout);
19 func(...args);
20 };
21 clearTimeout(timeout);
22 timeout = setTimeout(later, wait);
23 };
24 }
25
26 // Create the enhance button
27 function createEnhanceButton() {
28 const button = document.createElement('button');
29 button.id = 'prompt-enhancer-btn';
30 button.type = 'button';
31 button.innerHTML = '✨ Enhance';
32 button.style.cssText = `
33 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
34 color: white;
35 border: none;
36 border-radius: 8px;
37 padding: 8px 12px;
38 font-size: 13px;
39 font-weight: 600;
40 cursor: pointer;
41 box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
42 transition: all 0.3s ease;
43 display: flex;
44 align-items: center;
45 gap: 4px;
46 white-space: nowrap;
47 height: 36px;
48 `;
49
50 button.addEventListener('mouseenter', () => {
51 button.style.transform = 'translateY(-2px)';
52 button.style.boxShadow = '0 4px 12px rgba(102, 126, 234, 0.4)';
53 });
54
55 button.addEventListener('mouseleave', () => {
56 button.style.transform = 'translateY(0)';
57 button.style.boxShadow = '0 2px 8px rgba(102, 126, 234, 0.3)';
58 });
59
60 button.addEventListener('click', handleEnhanceClick);
61 return button;
62 }
63
64 // Handle enhance button click
65 async function handleEnhanceClick() {
66 const promptDiv = document.querySelector('div#prompt-textarea[contenteditable="true"]') ||
67 document.querySelector('div#prompt-textarea') ||
68 document.querySelector('[id*="prompt-textarea"]');
69 if (!promptDiv) {
70 console.error('Could not find prompt input area');
71 return;
72 }
73
74 const originalPrompt = promptDiv.textContent.trim();
75 if (!originalPrompt) {
76 showNotification('Please enter a prompt first', 'warning');
77 return;
78 }
79
80 const button = document.getElementById('prompt-enhancer-btn');
81 const originalButtonText = button.innerHTML;
82 button.innerHTML = '⏳ Enhancing...';
83 button.disabled = true;
84 button.style.opacity = '0.7';
85
86 try {
87 console.log('Enhancing prompt:', originalPrompt);
88
89 const enhancedPrompt = await RM.aiCall(
90 `You are a prompt engineering expert. Enhance the following prompt to make it more effective, clear, and detailed. Keep the core intent but improve clarity, add relevant context, and structure it better. Return ONLY the enhanced prompt without any explanations or meta-commentary.
91
92Original prompt: ${originalPrompt}`,
93 {
94 type: 'json_schema',
95 json_schema: {
96 name: 'enhanced_prompt',
97 schema: {
98 type: 'object',
99 properties: {
100 enhanced: { type: 'string' },
101 improvements: {
102 type: 'array',
103 items: { type: 'string' },
104 description: 'List of key improvements made'
105 }
106 },
107 required: ['enhanced', 'improvements']
108 }
109 }
110 }
111 );
112
113 console.log('Enhanced prompt received:', enhancedPrompt);
114
115 // Replace the content using textContent for contenteditable div
116 promptDiv.textContent = enhancedPrompt.enhanced;
117
118 // Trigger input event to update ChatGPT's UI
119 const inputEvent = new Event('input', { bubbles: true });
120 promptDiv.dispatchEvent(inputEvent);
121
122 // Show success notification with improvements
123 const improvementsText = enhancedPrompt.improvements.slice(0, 3).join(', ');
124 showNotification(`✓ Prompt enhanced! Improvements: ${improvementsText}`, 'success');
125
126 } catch (error) {
127 console.error('Error enhancing prompt:', error);
128 showNotification('Failed to enhance prompt. Please try again.', 'error');
129 } finally {
130 button.innerHTML = originalButtonText;
131 button.disabled = false;
132 button.style.opacity = '1';
133 }
134 }
135
136 // Show notification
137 function showNotification(message, type = 'info') {
138 const notification = document.createElement('div');
139 notification.style.cssText = `
140 position: fixed;
141 top: 20px;
142 right: 20px;
143 background: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : '#3b82f6'};
144 color: white;
145 padding: 16px 24px;
146 border-radius: 8px;
147 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
148 z-index: 10000;
149 max-width: 400px;
150 font-size: 14px;
151 line-height: 1.5;
152 animation: slideIn 0.3s ease;
153 `;
154 notification.textContent = message;
155
156 // Add animation
157 const style = document.createElement('style');
158 style.textContent = `
159 @keyframes slideIn {
160 from {
161 transform: translateX(400px);
162 opacity: 0;
163 }
164 to {
165 transform: translateX(0);
166 opacity: 1;
167 }
168 }
169 `;
170 document.head.appendChild(style);
171
172 document.body.appendChild(notification);
173
174 setTimeout(() => {
175 notification.style.transition = 'opacity 0.3s ease';
176 notification.style.opacity = '0';
177 setTimeout(() => notification.remove(), 300);
178 }, 4000);
179 }
180
181 // Insert the enhance button into the prompt area
182 function insertEnhanceButton() {
183 const promptDiv = document.querySelector('div#prompt-textarea[contenteditable="true"]') ||
184 document.querySelector('div#prompt-textarea') ||
185 document.querySelector('[id*="prompt-textarea"]');
186 if (!promptDiv) {
187 console.log('Prompt input area not found yet, will retry...');
188 return false;
189 }
190
191 // Check if button already exists
192 if (document.getElementById('prompt-enhancer-btn')) {
193 return true;
194 }
195
196 // Find the form container that holds the input area
197 const form = promptDiv.closest('form[data-type="unified-composer"]');
198 if (!form) {
199 console.log('Form container not found');
200 return false;
201 }
202
203 // Find the trailing area where other buttons are (the one with grid-area:trailing)
204 const trailingArea = form.querySelector('div[class*="trailing"][class*="grid-area"]') ||
205 form.querySelector('[style*="grid-area"][style*="trailing"]') ||
206 form.querySelector('.flex.items-center.gap-2[class*="trailing"]');
207 if (!trailingArea) {
208 console.log('Trailing area not found');
209 return false;
210 }
211
212 const button = createEnhanceButton();
213
214 // Insert the button at the beginning of the trailing area (before ms-auto container)
215 const buttonContainer = trailingArea.querySelector('.ms-auto');
216 if (buttonContainer) {
217 // Insert before the ms-auto container so it appears before dictate/voice buttons
218 trailingArea.insertBefore(button, buttonContainer);
219 } else {
220 trailingArea.insertBefore(button, trailingArea.firstChild);
221 }
222
223 console.log('Enhance button inserted successfully');
224 return true;
225 }
226
227 // Initialize the extension
228 function init() {
229 console.log('Initializing Prompt Enhancer...');
230
231 // Try to insert button immediately
232 if (insertEnhanceButton()) {
233 console.log('Button inserted on first try');
234 }
235
236 // Watch for DOM changes to handle navigation and dynamic content
237 const observer = new MutationObserver(debounce(() => {
238 insertEnhanceButton();
239 }, 500));
240
241 observer.observe(document.body, {
242 childList: true,
243 subtree: true
244 });
245
246 console.log('Prompt Enhancer ready');
247 }
248
249 // Wait for page to be ready
250 if (document.readyState === 'loading') {
251 document.addEventListener('DOMContentLoaded', init);
252 } else {
253 init();
254 }
255})();