From 4ece286095ea7a6cf89d696902e6b81b5d1c3a4b Mon Sep 17 00:00:00 2001 From: Ali Raheem Date: Fri, 19 May 2023 23:34:12 +0100 Subject: [PATCH] Chat mode --- aify.xpi | Bin 31818 -> 33979 bytes plugin/html/API.js | 7 +-- plugin/html/actions.html | 1 + plugin/html/actions.js | 95 ++++++++++++++++++-------------------- plugin/html/chat.css | 50 ++++++++++++++++++++ plugin/html/chat.html | 21 +++++++++ plugin/html/chat.js | 73 +++++++++++++++++++++++++++++ plugin/html/draft.html | 1 + plugin/html/draft.js | 76 +++++++++++++++--------------- plugin/html/globals.js | 1 + plugin/html/settings.css | 62 +++++++++++++++++++++++++ plugin/html/settings.html | 1 - 12 files changed, 295 insertions(+), 93 deletions(-) create mode 100755 plugin/html/chat.css create mode 100755 plugin/html/chat.html create mode 100755 plugin/html/chat.js create mode 100755 plugin/html/settings.css diff --git a/aify.xpi b/aify.xpi index 2c3a85cf9c1d7d0666d2b7c759eb43fa984548a2..7caf726a8e80ce694b506f3eb5c487eb8d80063b 100755 GIT binary patch delta 8163 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 delta 6044 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 { return await response.json(); }; -export const fetchResponse = async (apiKey, model, original, prompt, maxTokens) => { +export const fetchResponse = async (apiKey, model, messages, maxTokens) => { const response = await fetch("https://api.openai.com/v1/chat/completions", { method: "POST", headers: { @@ -23,10 +23,7 @@ export const fetchResponse = async (apiKey, model, original, prompt, maxTokens) }, body: JSON.stringify({ model, - messages: [ - { role: "system", content: prompt }, - { role: "user", content: original } - ], + messages: messages, ...(maxTokens > 0 ? { 'max_tokens': parseInt(maxTokens) } : {}) }), }); diff --git a/plugin/html/actions.html b/plugin/html/actions.html index 84908d9..23d5ac0 100755 --- a/plugin/html/actions.html +++ b/plugin/html/actions.html @@ -7,6 +7,7 @@


+ Chat

Settings diff --git a/plugin/html/actions.js b/plugin/html/actions.js index 5ef08a7..9bc9037 100755 --- a/plugin/html/actions.js +++ b/plugin/html/actions.js @@ -1,50 +1,45 @@ -import { promptVersion } from './globals.js'; - -const addAction = (name, prompt, actionsContainer) => { - const actionDiv = document.createElement("div"); - const nameInput = document.createElement("p"); - nameInput.classList.add("flat"); - nameInput.innerText = name; - nameInput.classList.add("action-name"); - - const getHighlightedText = () => { - return browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { - return browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedText" }); - }); - }; - - nameInput.onclick = () => { - getHighlightedText().then((highlightedText) => { - if (highlightedText) { - rewrite(highlightedText, prompt, name); - } - }); - }; - - actionDiv.appendChild(nameInput); - actionsContainer.appendChild(actionDiv); -}; - -const rewrite = async (original, action, draftTitle) => { - await browser.storage.local.set({ original, action, draftTitle }); - browser.windows.create({ url: "/html/draft.html", type: "popup", width: 512, height: 600 }); -}; - -document.addEventListener("DOMContentLoaded", () => { - const actionsContainer = document.getElementById("actions-container"); - browser.storage.local.get(["actions", "promptUpdated"], (data) => { - const { actions, promptUpdated = 0 } = data; - - if (promptVersion > promptUpdated) { - const warningIcon = document.createElement('img'); - warningIcon.src = "/images/warning.png"; - warningIcon.classList.add('small-icon'); - const settingsLink = document.getElementById('settings-link'); - settingsLink.appendChild(warningIcon); - }; - - actions.forEach((action) => { - addAction(action.name, action.prompt, actionsContainer); - }); - }); -}); +import { promptVersion } from './globals.js'; + +const addAction = (name, prompt, actionsContainer) => { + const actionDiv = document.createElement("div"); + const nameInput = document.createElement("p"); + nameInput.classList.add("flat"); + nameInput.innerText = name; + nameInput.classList.add("action-name"); + + const getHighlightedText = () => { + return browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { + return browser.tabs.sendMessage(tabs[0].id, { command: "getSelectedText" }); + }); + }; + + nameInput.onclick = () => { + getHighlightedText().then((highlightedText) => { + if (highlightedText) { + const messages = [{role: "system", content: prompt}, + {role: "user", content: highlightedText}]; + browser.storage.local.set({ messages, draftTitle: name }).then( () => { + browser.windows.create({ url: "/html/draft.html", type: "popup", + width: 600, height: 512 }); + }); + } + }); + }; + actionDiv.appendChild(nameInput); + actionsContainer.appendChild(actionDiv); +}; + +document.addEventListener("DOMContentLoaded", () => { + const actionsContainer = document.getElementById("actions-container"); + browser.storage.local.get(["actions", "promptUpdated"], (data) => { + const { actions, promptUpdated = 0 } = data; + if (promptVersion > promptUpdated) { + const warningIcon = document.createElement('img'); + warningIcon.src = "/images/warning.png"; + warningIcon.classList.add('small-icon'); + const settingsLink = document.getElementById('settings-link'); + settingsLink.appendChild(warningIcon); + }; + actions.forEach((action) => {addAction(action.name, action.prompt, actionsContainer)}); + }); +}); diff --git a/plugin/html/chat.css b/plugin/html/chat.css new file mode 100755 index 0000000..231e684 --- /dev/null +++ b/plugin/html/chat.css @@ -0,0 +1,50 @@ +body { + margin: 0; + padding: 0; + font-family: Arial, sans-serif; +} + +.chat-container { + height: 100vh; + display: flex; + flex-direction: column; +} + +.messages { + flex-grow: 1; + overflow-y: auto; + padding: 10px; + border-bottom: 1px solid #ccc; +} + +.chat-input-area { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; + height: 15%; +} + +#message-input { + flex-grow: 1; + margin-right: 10px; + height: 80%; +} + +.system-message { + background-color:hotpink; +} + +.user-message { + background-color: blanchedalmond; +} + +.assistant-message { + background-color: cadetblue; +} + +.message { + padding: 10px; + margin: 5px; + border-radius: 4px; +} \ No newline at end of file diff --git a/plugin/html/chat.html b/plugin/html/chat.html new file mode 100755 index 0000000..3f295d9 --- /dev/null +++ b/plugin/html/chat.html @@ -0,0 +1,21 @@ + + + + Aify Chat + + + + +
+
+ +
+
+ + + +
+
+ + + diff --git a/plugin/html/chat.js b/plugin/html/chat.js new file mode 100755 index 0000000..61ad8b9 --- /dev/null +++ b/plugin/html/chat.js @@ -0,0 +1,73 @@ +import { fetchResponse } from './API.js'; +import { chatPrompt } from './globals.js'; + +document.addEventListener('DOMContentLoaded', async function () { + var messageInput = document.getElementById('message-input'); + var sendButton = document.getElementById('send-button'); + // const clearButton = document.getElementById('clear-button'); + var messagesContainer = document.getElementById('messages'); + var loadingIcon = document.createElement('img'); + + loadingIcon.src = '/images/loading.png'; + loadingIcon.classList.add('rotate'); + + var storage = await browser.storage.local.get(["messages"]); + var messages = storage.messages || [{role: "system", content: chatPrompt}]; + + messages.forEach(function(message) { + displayMessage(message.role, message.content); + }); + + //clearButton.addEventListener('click', async () => {messages = []; await browser.storage.local.set({messages}); window.close()}) + sendButton.addEventListener('click', async function () { + var messageText = messageInput.value.trim(); + + if (messageText) { + messages.push({role: 'user', content: messageText}); + displayMessage('user', messageText); + + sendButton.disabled = true; + messagesContainer.appendChild(loadingIcon); + + try { + const { apiKey, model, maxTokens } = await browser.storage.local.get( + ["apiKey","model", "maxTokens"]); + const response = await fetchResponse(apiKey, model, messages, maxTokens); + // messagesContainer.innerText = response; + // Remove loading icon and enable button when API call finishes + loadingIcon.parentElement.removeChild(loadingIcon); + sendButton.disabled = false; + + if (response) { + // Display the response from the model + displayMessage('assistant', response); + messages.push({role: 'assistant', content: response}); + + // Save messages to local storage + browser.storage.local.set({messages}); + } + } catch(error) { + console.error(error); + messagesContainer.textContent = "Error: Unable to retrieve data"; + } + + messageInput.value = ''; + } + }); + + function displayMessage(role, text) { + var messageDiv = document.createElement('div'); + messageDiv.classList.add(role + '-message'); + messageDiv.classList.add('message'); + messageDiv.innerText = text; + messagesContainer.appendChild(messageDiv); + + // Scroll to bottom + messagesContainer.scrollTop = messagesContainer.scrollHeight; + } +}); + +window.addEventListener('unload', async function (event) { + await browser.storage.local.set({ messages: "[]", draftTitle: "" }); +}); + \ No newline at end of file diff --git a/plugin/html/draft.html b/plugin/html/draft.html index a1f6814..d4a6226 100755 --- a/plugin/html/draft.html +++ b/plugin/html/draft.html @@ -10,6 +10,7 @@
+

diff --git a/plugin/html/draft.js b/plugin/html/draft.js index bee454c..9c69f26 100755 --- a/plugin/html/draft.js +++ b/plugin/html/draft.js @@ -1,37 +1,39 @@ -import { fetchModels, fetchResponse } from './API.js'; - -async function regenerate(draftContainer, original, action, draftTitle) { - const loadingIcon = document.createElement("img"); - loadingIcon.src = "/images/loading.png"; - loadingIcon.classList.add("rotate"); - - draftContainer.textContent = ""; - draftContainer.appendChild(loadingIcon); - - try { - const draft = await callBackendAPI(original, action); - draftContainer.innerText = draft; - document.title = draftTitle; - } catch (error) { - console.error(error); - draftContainer.textContent = "Error: Unable to retrieve data"; - } -} - -async function callBackendAPI(original, action) { - const { model, apiKey, maxTokens } = await browser.storage.local.get(["model", "apiKey", "maxTokens"]); - const response = await fetchResponse(apiKey, model, original, action, maxTokens); - return response; -} - -document.addEventListener("DOMContentLoaded", async () => { - const regenButton = document.getElementById('regenerate'); - const draftContainer = document.getElementById("draft-container"); - - const { original, action, draftTitle } = await browser.storage.local.get(["original", "action", "draftTitle"]); - - await browser.storage.local.set({ original: "", action: "", draftTitle: "" }); - - regenButton.addEventListener("click", () => regenerate(draftContainer, original, action, draftTitle)); - regenerate(draftContainer, original, action, draftTitle); -}); +import { fetchResponse } from './API.js'; + +async function generate(draftContainer, messages, draftTitle) { + const loadingIcon = document.createElement("img"); + loadingIcon.src = "/images/loading.png"; + loadingIcon.classList.add("rotate"); + + draftContainer.textContent = ""; + draftContainer.appendChild(loadingIcon); + + try { + const { apiKey, model, maxTokens } = await browser.storage.local.get( + ["apiKey","model", "maxTokens"]); + const response = await fetchResponse(apiKey, model, messages, maxTokens); + draftContainer.innerText = response; + messages.push({role: "assistant", content: response}); + document.title = draftTitle; + await browser.storage.local.set({messages}); + } catch (error) { + console.error(error); + draftContainer.textContent = "Error: Unable to retrieve data"; + } +} + +document.addEventListener("DOMContentLoaded", async () => { + const regenButton = document.getElementById('regenerate'); + const chatButton = document.getElementById('chat-button'); + const draftContainer = document.getElementById("draft-container"); + const { messages, draftTitle } = await browser.storage.local.get(["messages", "draftTitle"]); + regenButton.addEventListener("click", () => generate(draftContainer, messages, draftTitle)); + chatButton.addEventListener("click", async () => { + await browser.storage.local.set({messages}); + await browser.windows.create({ url: "/html/chat.html", type: "popup", + width: 600, height: 600 }); + window.close(); + }) + generate(draftContainer, messages, draftTitle); + await browser.storage.local.set({ messages: "[]", draftTitle: "" }); +}); diff --git a/plugin/html/globals.js b/plugin/html/globals.js index 0ee90b7..3a0ed61 100755 --- a/plugin/html/globals.js +++ b/plugin/html/globals.js @@ -8,4 +8,5 @@ export const defaultActions = [ { name: "Translate this", prompt: "Translate the following email in English." }, { name: "Prompt provided", prompt: "You are a helpful chatbot that will do their best to complete the following tasks with a single response." }, ]; +export const chatPrompt = "You are a helpful chatbot, answer any questions the user has"; export const defaultModel = "gpt-3.5-turbo"; \ No newline at end of file diff --git a/plugin/html/settings.css b/plugin/html/settings.css new file mode 100755 index 0000000..a9c1ba8 --- /dev/null +++ b/plugin/html/settings.css @@ -0,0 +1,62 @@ +.col-25, +.col-75 { + float: left; + margin-top: 6px; +} +textarea { + height: 100px; +} +input[type="text"], +select, +textarea { + width: 100%; + padding: 12px; +// margin-top: 6px + border: 1px solid #ccc; + border-radius: 4px; + box-sizing: border-box; + resize: vertical; +} +label { + padding: 12px 12px 12px 0; + display: inline-block; +} +.button { + color: #fff; + padding: 12px 20px; + border: none; + border-radius: 4px; + cursor: pointer; +} +.neutral { + background-color: #5f9ea0; +} +.bad { + background-color: #dc143c; +} +.good { + background-color: #04aa6d; +} +.container { + border-radius: 5px; + background-color: #f2f2f2; + padding: 20px; +} +.col-25 { + width: 25%; +} +.col-75 { + width: 75%; +} +.row:after { + content: ""; + display: table; + clear: both; +} +@media screen and (max-width: 600px) { + .col-25, + .col-75 { + width: 100%; + margin-top: 0; + } +} diff --git a/plugin/html/settings.html b/plugin/html/settings.html index 96b36b0..17f4b88 100755 --- a/plugin/html/settings.html +++ b/plugin/html/settings.html @@ -44,7 +44,6 @@