Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
85d9dae
0.0.1
spencerslickremix Apr 29, 2023
1295250
0.0.1
spencerslickremix Apr 29, 2023
9855b69
0.0.1
spencerslickremix Apr 29, 2023
193c8f8
0.0.1
spencerslickremix Apr 29, 2023
ecfac38
0.0.1
spencerslickremix Apr 29, 2023
3b5dd0c
0.0.1
spencerslickremix Apr 29, 2023
f7271cf
0.0.2
spencerslickremix Apr 30, 2023
d814b9f
0.0.2
spencerslickremix Apr 30, 2023
31e1515
0.0.2
spencerslickremix Apr 30, 2023
3f2272c
0.0.2
spencerslickremix Apr 30, 2023
4ef7a27
Update readme with better instructions.
spencerslickremix Apr 30, 2023
d0da049
Update readme with better instructions.
spencerslickremix Apr 30, 2023
b859aa6
Add new Screenshots
spencerslickremix Apr 30, 2023
1d21408
Add new Screenshots
spencerslickremix Apr 30, 2023
f304f3a
Add new Screenshots
spencerslickremix Apr 30, 2023
22c3415
Add new Screenshots
spencerslickremix Apr 30, 2023
9643082
Add new Screenshots
spencerslickremix Apr 30, 2023
73d629a
Add new Screenshots
spencerslickremix Apr 30, 2023
7985960
Adjust instructions.
spencerslickremix May 1, 2023
cc81eb0
Adjust instructions.
spencerslickremix May 1, 2023
2046118
Adjust instructions.
spencerslickremix May 1, 2023
5aa59d7
Adjust instructions.
spencerslickremix May 1, 2023
b35c88a
Adjust instructions.
spencerslickremix May 1, 2023
0fe2970
Adjust instructions.
spencerslickremix May 1, 2023
26af004
Adjust instructions.
spencerslickremix May 1, 2023
283a9a1
Adjust instructions.
spencerslickremix May 1, 2023
2c8b51c
Adjust instructions.
spencerslickremix May 1, 2023
7a26fc8
Adjust instructions.
spencerslickremix May 1, 2023
4f8fc23
Adjust instructions.
spencerslickremix May 1, 2023
877373a
Adjust name
spencerslickremix May 1, 2023
7a200c9
Adjust name
spencerslickremix May 1, 2023
ea75a69
Adjust name
spencerslickremix May 1, 2023
706024a
Adjust name
spencerslickremix May 1, 2023
e2a488e
Adjust name
spencerslickremix May 1, 2023
5f6351d
Adjust readme
spencerslickremix May 1, 2023
4a99b9e
Adjust readme
spencerslickremix May 1, 2023
c29cd9c
0.0.2
spencerslickremix May 12, 2023
a65c3b2
0.0.2
spencerslickremix May 12, 2023
636eadb
0.0.2
spencerslickremix May 12, 2023
c96eb47
0.0.2
spencerslickremix May 12, 2023
e22e176
0.0.2
spencerslickremix May 12, 2023
b358e71
0.0.2
spencerslickremix May 12, 2023
313c13f
0.0.2
spencerslickremix May 12, 2023
de14d55
0.0.2
spencerslickremix May 12, 2023
12551e2
0.0.3
spencerslickremix May 17, 2023
ad7eca7
0.0.3
spencerslickremix May 18, 2023
70c27aa
0.0.3
spencerslickremix May 24, 2023
443efb7
0.0.3
spencerslickremix May 26, 2023
dff5a28
0.0.3
spencerslickremix May 28, 2023
f8cf463
Merge pull request #4 from spencerslickremix/0.0.3
spencerslickremix May 28, 2023
4fedd0f
0.0.3
spencerslickremix May 29, 2023
8b5470b
0.0.3
spencerslickremix May 29, 2023
295f399
0.0.3
spencerslickremix May 29, 2023
c99625b
Merge pull request #5 from spencerslickremix/0.0.3
spencerslickremix May 29, 2023
ed23ca4
0.0.3
spencerslickremix May 29, 2023
f1e8907
Merge pull request #6 from spencerslickremix/0.0.3
spencerslickremix May 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 145 additions & 14 deletions background.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,85 @@
// Define your token count at the top of the script
let tokenCount = 0;

// 4/25/23: Need to revisit this and dig deeper into seeing
// if we are actually removing suggestion to be able to keep the conversation going.
// at some point the conversation cannot continue if it exceeds 4097 tokens.
// seems like I need to make an option to save the conversation and or something...
// Define the token counting function
function countTokens(text) {
let wordCount = text.split(' ').length;
let punctuationCount = (text.match(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g) || []).length;
return wordCount + punctuationCount;
}

async function fetchApiKey() {
const { apiKey } = await chrome.storage.sync.get("apiKey");
return apiKey;
}

// This is the proper URL to use.
// https://api.openai.com/v1/engines/text-davinci-002/completions
// Initialize the conversation in storage
chrome.runtime.onInstalled.addListener(() => {
chrome.storage.sync.set({ conversation: [] });
});

// Only use this to test the notification notice.
// The version should be one less that the version in the manifest file.
/*chrome.storage.sync.set({ lastNotifiedVersion: '0.0.2', notificationClicked: 'no' }, () => {
console.log('Version set in storage and notification option stored');
});*/
/*chrome.storage.sync.get("lastNotifiedVersion", function(data) {
console.log('Last notified version:', data.lastNotifiedVersion);
});
chrome.storage.sync.get("notificationClicked", function(data) {
console.log('Was notification clicked:', data.notificationClicked);
});*/

// Update the last notified version in storage when the extension is updated
chrome.runtime.onInstalled.addListener(details => {
if (details.reason === "update") {
const currentVersion = chrome.runtime.getManifest().version;
chrome.storage.sync.set({ lastNotifiedVersion: currentVersion });
}
});

// Update the conversation in the storage whenever it changes
function updateConversation(convo) {
chrome.storage.sync.set({ conversation: convo });
}

let conversation = [];
chrome.storage.sync.get("conversation", function(data) {
if (data.conversation !== undefined) {
conversation = data.conversation;
tokenCount = conversation.reduce((sum, message) => sum + message.tokens, 0);
}
});

async function getSuggestionsFromApi(apiKey, prompt, maxTokens, n, stop, temperature, engine) {

if (!apiKey) {
throw new Error("API key not provided. Please enter your API key in the settings.");
throw new Error("API key not provided. To get started please click on the Menu option in the top right corner, click on Settings and then enter your API key.");
}
// gpt-3.5-turbo
const model = engine === 'gpt3' ? 'gpt-3.5-turbo' : 'gpt-4';

const engineURL = 'https://api.openai.com/v1/chat/completions';

// gpt3: curie
// gpt4: text-davinci-002
const engineURL = engine === 'gpt3' ? 'https://api.openai.com/v1/engines/curie/completions' : 'https://api.openai.com/v1/engines/text-davinci-002/completions';
let promptTokens = countTokens(prompt);
conversation.push({role: "user", content: prompt, tokens: promptTokens});
tokenCount += promptTokens;

console.log( engineURL );
while (tokenCount > 4096 && conversation.length > 0) {
let removedMessage = conversation.shift();
tokenCount -= removedMessage.tokens; // Subtract the tokens of the removed message
}

if (promptTokens > 4096) {
throw new Error("Your message is too long! Please limit messages to 4096 tokens.");
}

// copy the conversation array and remove tokens property
const conversationCopy = conversation.map(({ role, content }) => ({ role, content }));

const response = await fetch(engineURL, {
method: "POST",
Expand All @@ -23,8 +88,9 @@ async function getSuggestionsFromApi(apiKey, prompt, maxTokens, n, stop, tempera
"Authorization": `Bearer ${apiKey}`
},
body: JSON.stringify({
prompt: prompt,
max_tokens: parseInt(maxTokens) || 250,
model: model,
messages: conversationCopy,
max_tokens: parseInt(maxTokens) || 2000,
n: parseInt(n) || 1,
stop: stop || null,
temperature: parseFloat(temperature) || 0.1
Expand All @@ -35,21 +101,37 @@ async function getSuggestionsFromApi(apiKey, prompt, maxTokens, n, stop, tempera
const errorData = await response.json();
if (errorData.error && errorData.error.code === "invalid_api_key") {
throw new Error("Invalid API key provided. Please check your API key.");
} else {
}
else if (errorData.error && errorData.error.message === "The model: `gpt-4` does not exist") {
//console.log( errorData.error );
throw new Error("Please choose the GPT-3 Option from the <span class='settingsLink'>Settings</span> page to continue. The OpenAI API Key you entered does not have GPT-4 access yet. <br/><br/>You must have explicitly been granted a GPT-4 API Key from OpenAI for the GPT-4 option to work on our Settings page. You can apply for access here https://openai.com/waitlist/gpt-4-api");
}
else{
throw new Error("Unexpected response from OpenAI API: " + JSON.stringify(errorData));
}
}

const data = await response.json();
if (data.choices) {
return data.choices.map((choice) => choice.text.trim());
let suggestionResponses = data.choices.map((choice) => {
let messageContent = choice.message.content.trim();
let tokens = countTokens(messageContent);
conversation.push({role: "assistant", content: messageContent, tokens: tokens});

// Notify loading-suggestions.js that a new suggestion has been added
chrome.runtime.sendMessage({ action: "newSuggestionAdded", tokens: tokens });

return messageContent;
});
return suggestionResponses;
} else {
console.error("Unexpected response from OpenAI API:", JSON.stringify(data, null, 2));
return [];
}
}

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "getSuggestions") {
if (request.text) {
fetchApiKey().then(async function (apiKey) {
Expand All @@ -58,12 +140,13 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
const suggestions = await getSuggestionsFromApi(
apiKey,
request.text,
settings.maxTokens || 50,
settings.maxTokens || 2000,
settings.n || 1,
settings.stop || null,
settings.temperature || 0.1,
settings.engine || 'gpt4'
settings.engine || 'gpt3'
);
tokenCount += suggestions.reduce((sum, suggestion) => sum + countTokens(suggestion), 0);
sendResponse({ suggestions: suggestions });
} catch (error) {
console.error('Error:', error);
Expand All @@ -77,5 +160,53 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
console.error("No text provided.");
}
}

if (request.action === "clearConversationAndTokenCount") {
conversation = []; // Clear the conversation array
tokenCount = 0; // Clear the token count
updateConversation(conversation); // Save the cleared conversation
sendResponse({ message: "Conversation and token count cleared." });
return true;
}



if (request.action === "fetchChangelog") {
fetchChangelog()
.then(changelog => sendResponse({changelog: changelog}))
.catch(error => sendResponse({error: error.message}));
return true; // Indicate that we will send a response asynchronously
}
});

function fetchChangelog(attempt = 1) {
const maxAttempts = 3;
const repo = 'https://raw.githubusercontent.com/spencerslickremix/Slick-Personal-Assistant/main/';

return new Promise((resolve, reject) => {
fetch(repo + 'changelog.txt')
.then(response => {
if (response.status === 404) {
throw new Error('The changelog could not be found. Please check the file path.');
} else if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.text();
})
.then(changelog => {
resolve(changelog);
})
.catch(error => {
if (error.message.includes('changelog could not be found')) {
// If the changelog was not found, reject the promise immediately
reject(error);
} else if (attempt < maxAttempts) {
// If the fetch failed for a different reason and we haven't reached the max number of attempts, try again
fetchChangelog(attempt + 1).then(resolve).catch(reject);
} else {
// If we've reached the max number of attempts, reject the promise
reject(error);
}
});
});
}
28 changes: 28 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
= Version 0.0.3 Monday, May 29th, 2023 =
* New: Settings: Custom font size option.
* New: Settings: Custom background and color options.
* New: Settings: Choose the width of the Popup.
* New: Suggestions: Added Token Count so users can see how many tokens are used per response. This text will also link you directly to the Settings page for quicker navigation.
* New: Header: The SlickRemix logo now links to the website, and the text "Your Personal Automated Assistant" links to the Suggestions tab for quicker navigation.
* New: Organized files in their respective folders.
* New: Namespaced and classify entire extension.
* Updated: Select a portion of text from a response to be copied automatically.
* Updated: Settings description for Max Tokens and Temperature to be more clear.
* Fixed: Added additional checks to Regex to parse URLs properly. We will probably end up adding a library in the future.
* Fixed: Added error messages to the suggestion list so users know when there is a problem.
* Fixed: Added GPT-4 specific error message to let users know if the API token they have entered will work with GPT-4 if they chose that model.
* Removed: content_scripts: matches": ["http://*/*", "https://*/*"] & js": ["contentScript.js"]. These options were not needed because I am calling chrome.scripting.executeScript from the popup.js file already, so the call was being duplicated.

= Version 0.0.2 Thursday, May 18th, 2023 =
* New: Replaced model davinci-003 with gpt-3.5-turbo
* New: Updated completions to use /chat/completions
* New: Save user and response text to array to chrome.storage
* New: Complete UI change. Made Dark Mode true by default now.
* New: Regex to parse URLs properly.
* New: Settings: Display Twitter icon to quickly share responses.
* New: Custom Prompts tab. Includes the option to add up to 5 custom prompts or chose to display prompts saved from a GitHub accounts readme.md file.
* New: Showdown.js to convert code to HTML and Prism.js to beatify the code.
* Removed: permissions: tabs. Was not actually needed and was warned by Google it needed to be removed.

= Version 0.0.1 Monday, May 2nd, 2023 =
* Initial Release
18 changes: 0 additions & 18 deletions content.js

This file was deleted.

93 changes: 93 additions & 0 deletions layout/css/custom/background/dark.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
body {
background: #202123;
}
.header {
color: #ececf1;
}
.tabcontent p {
color: #c6c6c6;
}
.container input {
color: #ececf1;
}
.toggle-label {
color: #b6b6b6;
}
label {
color: #939393 !important;
}
.suggestionsLink.slickremix-title {
color: #ffffff;
}
span.slickremix-logo:before {
color: #f0f0f0;
}
.switch-description {
color: #f0f0f0;
}
.tab {
background-color: #f2f2f2;
border-bottom: 1px solid #e0e0e0;
}
.settings-content {
background-color: #ececf1;
}
.suggestion {
background: #40414f;
color:#dbdbdb
}
.tabcontent h3 {
color: #f9f8f8;
}
.suggestion.user-input {
background: #202123;
}
#suggestions-tab .content {
background: #40414f;
}
textarea {
border: 1px solid #e0e0e0;
color:#d7d7d7
}
.copied-overlay {
color: #ececf1;
}
.dot {
background-color: #ececf1;
}
#githubUrlContainer .helper-text {
color: #ececf1
}
.switch-wrap {
background: #444654;
}
.prompt-wrap {
background: #444654;
}
.material-tooltip {
background: #2e313b;
}
.settings-menu li {
background: #202123;
}
#custom-context-menu {
background-color: #202123;
}
#changelog-container {
color: #fff;
border-top: 1px dashed #4f5052;
}
input:-webkit-autofill,
textarea:-webkit-autofill,
select:-webkit-autofill {
-webkit-box-shadow: 0 0 0 1000px #202123 inset !important;
/*use inset box-shadow to cover background-color*/
-webkit-text-fill-color: #ffffff !important;
/*use text fill color to cover font color*/
}
#custom-context-menu-settings-tab input:-webkit-autofill,
#custom-context-menu-settings-tab textarea:-webkit-autofill,
#custom-context-menu-settings-tab select:-webkit-autofill {
-webkit-box-shadow: 0 0 0 1000px #444654 inset !important;
/*use inset box-shadow to cover background-color*/
}
Loading