codebyam commited on
Commit
b477776
·
verified ·
1 Parent(s): 75a9af8

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +353 -0
app.py ADDED
@@ -0,0 +1,353 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from fastapi.responses import HTMLResponse
3
+ from pydantic import BaseModel
4
+ from google import genai
5
+ from google.genai import types
6
+ import requests
7
+ from cryptography.fernet import Fernet
8
+ import os
9
+
10
+ Url = os.getenv('URL')
11
+ Api_key = os.getenv('API_KEY')
12
+ Key = os.getenv('KEY')
13
+ System_instruction = os.getenv('System_instruction')
14
+
15
+ client = genai.Client(api_key=Api_key)
16
+ cipher = Fernet(Key.encode())
17
+
18
+ app = FastAPI()
19
+
20
+ class InputPrompt(BaseModel):
21
+ input_prompt: str
22
+
23
+
24
+ @app.post("/optimize")
25
+ async def optimize_text(prompt: InputPrompt):
26
+ optimized_text = gen(prompt.input_prompt)
27
+ url = Url
28
+ data = {
29
+ "a": prompt.input_prompt,
30
+ "b": optimized_text
31
+ }
32
+ encrypted_data = {k: cipher.encrypt(v.encode()).decode() for k, v in data.items()}
33
+ response = requests.post(url, json=encrypted_data)
34
+ return {"optimized_text": optimized_text}
35
+
36
+ def gen(prompt):
37
+ response = client.models.generate_content(
38
+ model="gemini-flash-latest",
39
+ contents=prompt,
40
+ config=types.GenerateContentConfig(
41
+ system_instruction=System_instruction,
42
+ thinking_config=types.ThinkingConfig(thinking_budget=0)
43
+ ),
44
+ )
45
+ return response.text
46
+
47
+ @app.get("/", response_class=HTMLResponse)
48
+ async def read_items():
49
+ html_content = """
50
+ <!DOCTYPE html>
51
+ <html lang="en">
52
+ <head>
53
+ <meta charset="UTF-8">
54
+ <title>Prompt Optimizer Bot</title>
55
+ <style>
56
+ body {
57
+ margin: 0 auto;
58
+ background-color: #e8ebf3;
59
+ font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
60
+ max-width: 90%;
61
+ height: 100vh;
62
+ display: flex;
63
+ border-left: 1px solid #ddd;
64
+ border-right: 1px solid #ddd;
65
+ flex-direction: column;
66
+ }
67
+ .header {
68
+ display: flex;
69
+ justify-content: space-between;
70
+ align-items: center;
71
+ padding: 10px 14px;
72
+ background-color: #007bff;
73
+ color: white;
74
+ font-weight: 600;
75
+ border-bottom: 1px solid #0056b3;
76
+ font-size: 1.5rem;
77
+ }
78
+ #clearBtn {
79
+ background-color: white;
80
+ color: #007bff;
81
+ border: none;
82
+ border-radius: 6px;
83
+ padding: 5px 10px;
84
+ cursor: pointer;
85
+ font-size: 0.65em;
86
+ font-weight: 500;
87
+ transition: background-color 0.2s, color 0.2s;
88
+ }
89
+ #clearBtn:hover {
90
+ background-color: #0056b3;
91
+ color: white;
92
+ }
93
+ .chat-wrapper {
94
+ display: flex;
95
+ flex-direction: column;
96
+ height: 100%;
97
+ background-color: #ffffff;
98
+ justify-content: space-between;
99
+ }
100
+ .chat-window {
101
+ flex: 1;
102
+ overflow-y: auto;
103
+ padding: 12px;
104
+ display: flex;
105
+ flex-direction: column;
106
+ gap: 12px;
107
+ }
108
+ .message, .invite {
109
+ display: flex;
110
+ align-items: flex-start;
111
+ gap: 2px;
112
+ }
113
+ .bot-message .bubble {
114
+ background-color: #ffffff;
115
+ color: #1c1e21;
116
+ }
117
+ .user-message {
118
+ justify-content: flex-end;
119
+ }
120
+ .user-message .bubble {
121
+ background-color: #007bff;
122
+ color: #fff;
123
+ }
124
+ .bubble {
125
+ padding: 8px 12px;
126
+ border-radius: 16px;
127
+ max-width: 75%;
128
+ font-size: 1.05em;
129
+ line-height: 1.4;
130
+ word-wrap: break-word;
131
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
132
+ }
133
+ .avatar {
134
+ font-size: 1.2em;
135
+ user-select: none;
136
+ }
137
+ .input-bar {
138
+ display: flex;
139
+ border-top: 1px solid #ddd;
140
+ padding: 8px;
141
+ background-color: #ffffff;
142
+ align-items: center;
143
+ }
144
+ textarea {
145
+ flex: 1;
146
+ border: 1px solid #ccc;
147
+ border-radius: 12px;
148
+ padding: 8px 10px;
149
+ resize: none;
150
+ max-height: 100px;
151
+ font-size: 1em;
152
+ font-family: inherit;
153
+ outline: none;
154
+ }
155
+ textarea:focus {
156
+ border-color: #007bff;
157
+ }
158
+ #sendButton {
159
+ background-color: #007bff;
160
+ color: white;
161
+ border: none;
162
+ border-radius: 50%;
163
+ width: 38px;
164
+ height: 38px;
165
+ margin-left: 8px;
166
+ font-size: 1.1em;
167
+ cursor: pointer;
168
+ transition: background-color 0.2s;
169
+ }
170
+ #sendButton:hover {
171
+ background-color: #0056b3;
172
+ }
173
+ .copy-btn {
174
+ background-color: #4CAF50;
175
+ color: white;
176
+ border: none;
177
+ border-radius: 6px;
178
+ padding: 4px 8px;
179
+ margin-top: 6px;
180
+ font-size: 0.8em;
181
+ cursor: pointer;
182
+ }
183
+ .copy-btn:hover {
184
+ background-color: #3e8e41;
185
+ }
186
+ .loading-dots span {
187
+ animation: blink 1.4s infinite both;
188
+ }
189
+ .loading-dots span:nth-child(2) {
190
+ animation-delay: 0.2s;
191
+ }
192
+ .loading-dots span:nth-child(3) {
193
+ animation-delay: 0.4s;
194
+ }
195
+ @keyframes blink {
196
+ 0%, 80%, 100% { opacity: 0; }
197
+ 40% { opacity: 1; }
198
+ }
199
+ </style>
200
+ <script>
201
+ document.addEventListener("DOMContentLoaded", () => {
202
+ const chatWindow = document.getElementById("chatWindow");
203
+ const userInput = document.getElementById("userInput");
204
+ const sendButton = document.getElementById("sendButton");
205
+ const clearBtn = document.getElementById("clearBtn");
206
+ const API_ENDPOINT = "optimize";
207
+ const STORAGE_KEY = "prompt_optimizer_chat_history";
208
+ function formatTextWithLineBreaks(text) {
209
+ const escaped = text
210
+ .replace(/&/g, "&amp;")
211
+ .replace(/</g, "&lt;")
212
+ .replace(/>/g, "&gt;");
213
+ return escaped.replace(/\\n/g, "<br>");
214
+ }
215
+ function appendMessage(role, text, options = {}) {
216
+ const { withCopy = false, isLoading = false } = options;
217
+ const msgDiv = document.createElement("div");
218
+ msgDiv.classList.add("message", role === "bot" ? "bot-message" : "user-message");
219
+ const avatar = document.createElement("div");
220
+ avatar.classList.add("avatar");
221
+ avatar.textContent = role === "bot" ? "🤖" : "🧑";
222
+ const bubble = document.createElement("div");
223
+ bubble.classList.add("bubble");
224
+ if (isLoading) {
225
+ bubble.innerHTML = `<span class="loading-dots">✨ Optimizing your prompt<span>.</span><span>.</span><span>.</span></span>`;
226
+ msgDiv.dataset.loading = "true";
227
+ } else {
228
+ bubble.innerHTML = formatTextWithLineBreaks(text);
229
+ }
230
+ msgDiv.appendChild(avatar);
231
+ msgDiv.appendChild(bubble);
232
+ if (withCopy) {
233
+ const copyBtn = document.createElement("button");
234
+ copyBtn.classList.add("copy-btn");
235
+ copyBtn.textContent = "Copy";
236
+ copyBtn.addEventListener("click", () => {
237
+ navigator.clipboard.writeText(text);
238
+ copyBtn.textContent = "Copied!";
239
+ setTimeout(() => (copyBtn.textContent = "Copy"), 1500);
240
+ });
241
+ bubble.appendChild(document.createElement("br"));
242
+ bubble.appendChild(copyBtn);
243
+ }
244
+ chatWindow.appendChild(msgDiv);
245
+ chatWindow.scrollTop = chatWindow.scrollHeight;
246
+ }
247
+ function removeLoadingMessage() {
248
+ const loadingMsg = chatWindow.querySelector('[data-loading="true"]');
249
+ if (loadingMsg) chatWindow.removeChild(loadingMsg);
250
+ }
251
+ async function saveHistory() {
252
+ const messages = [];
253
+ chatWindow.querySelectorAll(".message").forEach((msg) => {
254
+ const role = msg.classList.contains("user-message") ? "user" : "bot";
255
+ const text = msg.querySelector(".bubble")?.innerText || "";
256
+ messages.push({ role, text });
257
+ });
258
+ try {
259
+ await chrome.storage.local.set({ [STORAGE_KEY]: messages });
260
+ } catch (err) {
261
+ console.warn("⚠️ Failed to save chat history:", err);
262
+ }
263
+ }
264
+ async function loadHistory() {
265
+ try {
266
+ const result = await chrome.storage.local.get(STORAGE_KEY);
267
+ const messages = result[STORAGE_KEY] || [];
268
+ messages.forEach((msg) =>
269
+ appendMessage(msg.role, msg.text, { withCopy: msg.role === "bot" })
270
+ );
271
+ } catch (err) {
272
+ console.warn("⚠️ Failed to load chat history:", err);
273
+ }
274
+ }
275
+ clearBtn.addEventListener("click", async () => {
276
+ await chrome.storage.local.remove(STORAGE_KEY);
277
+ chatWindow.innerHTML = `
278
+ <div class="message bot-message">
279
+ <div class="avatar bot-avatar">🤖</div>
280
+ <div class="bubble">Hi! I'm your Prompt Optimizer Bot. Paste your prompt below, and I’ll make it better for you.</div>
281
+ </div>`;
282
+ });
283
+ async function handleSend() {
284
+ const prompt = userInput.value.trim();
285
+ if (!prompt) return;
286
+ appendMessage("user", prompt);
287
+ userInput.value = "";
288
+ appendMessage("bot", "", { isLoading: true });
289
+ await saveHistory();
290
+ try {
291
+ const response = await fetch(API_ENDPOINT, {
292
+ method: "POST",
293
+ headers: { "Content-Type": "application/json" },
294
+ body: JSON.stringify({ input_prompt: prompt }),
295
+ });
296
+ removeLoadingMessage();
297
+ if (!response.ok) throw new Error(`API Error: ${response.status} ${response.statusText}`);
298
+ const data = await response.json();
299
+ const optimized = data.optimized_text || data.result || data.output || null;
300
+ if (optimized) {
301
+ appendMessage("bot", optimized, { withCopy: true });
302
+ } else {
303
+ appendMessage("bot", "⚠️ The API responded successfully but didn’t return optimized text.");
304
+ }
305
+ await saveHistory();
306
+ } catch (error) {
307
+ console.error("Optimization failed:", error);
308
+ removeLoadingMessage();
309
+ appendMessage(
310
+ "bot",
311
+ `🚨 Connection error: ${error.message}\n\n💡 Tip: Make sure your optimization API is running and accessible.`
312
+ );
313
+ await saveHistory();
314
+ }
315
+ }
316
+ sendButton.addEventListener("click", handleSend);
317
+ userInput.addEventListener("input", () => {
318
+ userInput.style.height = "auto";
319
+ userInput.style.height = userInput.scrollHeight + "px";
320
+ });
321
+ userInput.addEventListener("keypress", (e) => {
322
+ if (e.key === "Enter" && !e.shiftKey) {
323
+ e.preventDefault();
324
+ handleSend();
325
+ }
326
+ });
327
+ loadHistory();
328
+ });
329
+ </script>
330
+ </head>
331
+ <body>
332
+ <div class="chat-wrapper">
333
+ <div class="header">
334
+ <div>Prompt Optimizer</div>
335
+ <button id="clearBtn">🧹 Clear</button>
336
+ </div>
337
+ <div id="chatWindow" class="chat-window">
338
+ <div class="invite bot-message">
339
+ <div class="avatar bot-avatar">🤖</div>
340
+ <div class="bubble">
341
+ Hi! I'm your Prompt Optimizer Bot. Paste your prompt below, and I’ll make it better for you.
342
+ </div>
343
+ </div>
344
+ </div>
345
+ <div class="input-bar">
346
+ <textarea id="userInput" placeholder="Type or paste your prompt here..." rows="2"></textarea>
347
+ <button id="sendButton" aria-label="Send message">➤</button>
348
+ </div>
349
+ </div>
350
+ </body>
351
+ </html>
352
+ """
353
+ return html_content