├── .gitignore ├── LICENSE ├── README.md ├── brainbox_api ├── README.md └── examples │ ├── grammar_corrector │ ├── background.js │ ├── contentscript.js │ └── manifest.json │ └── talk_like_a_pirate │ ├── background.js │ └── manifest.json ├── contextual_identities └── README.md ├── tabs_api ├── README.md └── examples │ └── open_in_split_screen │ ├── background.js │ ├── contentscript.js │ ├── images │ ├── .DS_Store │ ├── icon_128.png │ ├── icon_16.png │ ├── icon_32.png │ └── icon_48.png │ └── manifest.json └── wavebox_apps_api ├── README.md └── examples └── pipedrive_badge ├── background.js ├── contentscript.js └── manifest.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Wavebox 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Wavebox supports the same extension ecosystem and set of extension APIs as Chromium & Google Chrome. In addition to this it also provides some additional features over the standard extension APIs. 2 | 3 | These pages provide details of those additional APIs and how to use them. 4 | 5 | # Getting Started 6 | 7 | The best place to get started is by using the excellent documentation on the Chrome Developers page 8 | 9 | [Developing Extensions](https://developer.chrome.com/docs/extensions/mv3/) 10 | 11 | [Getting Started](https://developer.chrome.com/extensions/getstarted) 12 | 13 | [API Reference](https://developer.chrome.com/extensions/api_index) 14 | 15 | ## Wavebox API additions 16 | 17 | [Brainbox](/brainbox_api) Interact with Brainbox 18 | 19 | [Firefox ContextualIdentities](/contextual_identities) Use the Firefox contextual identities extension api to interact with Wavebox cookie containers 20 | 21 | [Tabs](/tabs_api) Interact with the tab system, query & update split-screen 22 | 23 | [WaveboxApps](/wavebox_apps_api) Update unread badges, notifications & more for apps 24 | 25 | -------------------------------------------------------------------------------- /brainbox_api/README.md: -------------------------------------------------------------------------------- 1 | # Permissions 2 | 3 | The brainbox api requires the `brainbox` permission in the [manifest](https://developer.chrome.com/docs/extensions/mv3/declare_permissions/) 4 | 5 | # Types 6 | 7 | ## ChatMessageRole 8 | 9 | _enum_ `"user", "system", "assistant"` 10 | 11 | The role indicates the source or purpose of the ChatMessage. i.e. user is a message from the user, system is a message to configure Brainbox 12 | 13 | ## ChatMessage 14 | 15 | _object_ `{ "role": ChatMessageRole, "content": "..." }` 16 | 17 | A single chat message. The role indicates the source or purpose of the message and the content is the text content contained within the message 18 | 19 | ## ChatStreamType 20 | 21 | _enum_ `"stream", "end", "error"` 22 | 23 | The type of stream message 24 | 25 | # Events 26 | 27 | ## brainbox.onChatStream 28 | 29 | An event that's emitted when Brainbox streams parts of the message back to the API. The stream messages indicate parts of the content that Brainbox is replying with, until the API returns end or error. 30 | 31 | * `chatId [string]` the id of the chat. This can be used to tie the stream messages back to the original request 32 | * `type [ChatStreamType]` the type of message that's being returned. Typically events will emit multiple `stream` types followed by a single `end` or `error` message 33 | * `content [string]` the partial of the message content 34 | 35 | 36 | # Methods 37 | 38 | ## brainox.chat 39 | Initiate a chat with Brainbox. 40 | 41 | * `system [string]` the system message, used to configure Brainbox 42 | * `user [string]` the users message 43 | * `messageHistory [ChatMessage[] Optional]` ab array of previous chat messages to include in the conversation. This can provide more context to Brainbox. Some messages may be truncated to remain within quota limits 44 | 45 | **Returns** `chatId [string]`. Replies are streamed back through the API. Use the provided chatId alongside the `brainbox.onChatStream` event to buffer and build the complete reply. 46 | 47 | 48 | # Examples 49 | 50 | Examples can be found in the examples folder: 51 | 52 | * **Grammar corrector** [Example](examples/grammar_corrector/). Adds a button to all pages, when clicked it takes the content from the last textarea/input field, asks Brainbox to correct the grammar and replaces the original content in the page 53 | * **Talk like a pirate** [Example](examples/talk_like_a_pirate). A simple example tells a pirate themed joke in the background page 54 | -------------------------------------------------------------------------------- /brainbox_api/examples/grammar_corrector/background.js: -------------------------------------------------------------------------------- 1 | const openRequests = new Map() 2 | 3 | // We need to create a listener that waits for the contentscript 4 | // to send a message and do something with it. The message argument 5 | // is the same variable that was sent from the contentscript 6 | chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { 7 | // Check that we're asking for a grammar correction 8 | if (message.type === 'grammar') { 9 | // We can now chat with brainbox. The brainbox API returns a chatId 10 | // reference once the request has been accepted. The actual response 11 | // is then streamed through the chrome.brainbox.onChatStream event 12 | // shortly after. 13 | // 14 | // We need to store this chatId variable and also the sendResponse 15 | // variable so that once the response is completed we can reply 16 | // to the contentscript 17 | chrome.brainbox.chat( 18 | // This is the prompt that customizes how Brainbox replies 19 | 'You are a grammar correcting assistant. You should take the users message and reply only with a corrected version', 20 | // This is users message 21 | message.text 22 | ).then((chatId) => { 23 | // chrome.brainbox.chat is asynchronous so it doesn't return a reply right 24 | // away. We can either use... 25 | // - await chrome.brainbox.chat(...) to wait for the reply 26 | // - chrome.brainbox.chat(...).then() to bind a function that's executed on reply 27 | // 28 | // In our example, we need to return true to the listener immediately 29 | // so we can bind using .then() to do this 30 | 31 | // Store the chatId, callback and content in the openRequests variable 32 | openRequests.set(chatId, { callback: sendResponse, content: '' }) 33 | }) 34 | } 35 | 36 | // Returning true, tells the listener that we'll send the response 37 | // using the sendResponse() function at a later date 38 | return true 39 | }) 40 | 41 | // This is the listener that waits for brainbox to stream chat messages 42 | chrome.brainbox.onChatStream.addListener((chatId, type, content) => { 43 | if (openRequests.has(chatId)) { 44 | const request = openRequests.get(chatId) 45 | switch(type) { 46 | // When we get a stream message we can just append the content 47 | // to the existing content we have stored 48 | case 'stream': 49 | request.content += content; 50 | break 51 | // When brainbox sends an end command, we can execute the callback 52 | // to the contentscript with the entire message 53 | case 'end': 54 | request.callback(request.content) 55 | openRequests.delete(chatId) 56 | break 57 | } 58 | } 59 | }) -------------------------------------------------------------------------------- /brainbox_api/examples/grammar_corrector/contentscript.js: -------------------------------------------------------------------------------- 1 | // Create a listener that watches which element has focus. We can't check 2 | // this immediately on button click because clicking on the button changes 3 | // focus to the button itself. 4 | // 5 | // The focusin event on the document fires every time an element gains 6 | // focus in a page. We can check the elements type and store the last 7 | // text area or input field that had focus 8 | let lastFocusedElement 9 | document.addEventListener('focusin', () => { 10 | const element = document.activeElement 11 | // Check the element is a