diff --git a/.gitignore b/.gitignore index b4152655b8103..339422b8dfa08 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ src/__pycache__ *.iml *.out .env +*_request.json +*_response.json +*_content.py diff --git a/.vscode/launch.json b/.vscode/launch.json index 0e061bbfdcab3..65ee800f555e8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -241,6 +241,7 @@ "JAVA": "${input:envJAVA}", "SYNTH": "${input:envSYNTH}", "OPENAI_API_KEY": "${input:envOPENAI}", + "LEAP_PROMPT": "${input:envLEAP_PROMPT}", }, "cleanUp": "wholeBrowser", "urlFilter": "*workbench*.html*", @@ -683,6 +684,16 @@ "key": "OPENAI_API_KEY", "default": "" } + }, + { + "id": "envLEAP_PROMPT", + "type": "command", + "command": "extension.commandvariable.file.content", + "args": { + "fileName": "${workspaceFolder}/.env", + "key": "LEAP_PROMPT", + "default": "" + } } ] } diff --git a/build/filters.js b/build/filters.js index ed8c0794c7c4e..fefb7c0b20365 100644 --- a/build/filters.js +++ b/build/filters.js @@ -70,6 +70,7 @@ module.exports.indentationFilter = [ '!LICENSES.chromium.html', '!**/LICENSE', '!**/*.mp3', + '!src/*.txt', '!src/vs/loader.js', '!src/vs/base/browser/dompurify/*', '!src/vs/base/common/marked/marked.js', @@ -169,6 +170,7 @@ module.exports.copyrightFilter = [ '!src/vs/editor/contrib/rtv/**', '!src/vs/editor/contrib/leap/**', '!src/*.py', + '!src/*.txt', '!test/rtv/**', ]; @@ -176,6 +178,7 @@ module.exports.tsFormattingFilter = [ 'src/**/*.ts', 'test/**/*.ts', 'extensions/**/*.ts', + '!src/*.txt', '!src/vs/*/**/*.d.ts', '!src/typings/**/*.d.ts', '!extensions/**/*.d.ts', diff --git a/package.json b/package.json index ae2f4a1aa2d78..006313b17c5fb 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "native-keymap": "3.3.0", "native-watchdog": "1.4.0", "node-pty": "0.11.0-beta11", - "openai": "^3.1.0", + "openai": "^4.24.1", "spdlog": "^0.13.0", "tas-client-umd": "0.1.6", "v8-inspect-profiler": "^0.1.0", diff --git a/run.sh b/run.sh index ba25451686c58..f47f6503162bd 100755 --- a/run.sh +++ b/run.sh @@ -3,4 +3,4 @@ # Get _this_ script's path, so we can use absolute paths for run.py SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -SNIPPY_UTILS="$SCRIPT_DIR/src/snippy.py" PYTHON3=$(which python3) JAVA=$(which java) RUNPY="$SCRIPT_DIR/src/run.py" IMGSUM="$SCRIPT_DIR/src/img-summary.py" SYNTH='' scripts/code.sh +SNIPPY_UTILS="$SCRIPT_DIR/src/snippy.py" PYTHON3=$(which python3) JAVA=$(which java) RUNPY="$SCRIPT_DIR/src/run.py" IMGSUM="$SCRIPT_DIR/src/img-summary.py" SYNTH='' LEAP_PROMPT="$SCRIPT_DIR/src/implement_it.txt" scripts/code.sh diff --git a/src/implement_it.txt b/src/implement_it.txt new file mode 100644 index 0000000000000..3cd96150bd25b --- /dev/null +++ b/src/implement_it.txt @@ -0,0 +1,48 @@ +system +You are an expert Python programmer. +You will fill in the missing piece of Python code. Do not change any of the prefix. Do not change any of the suffix. +Do not repeat the prompt, prefix, or suffix in your answer. The prefix, suffix, and completion when put together, must be parsable as valid Python code. + +You will receive a [[prefix]] and a [[suffix]] of Python code. You must fill in the middle. +--- +user +[[prefix]] +def fib(n: int) -> int: +[[suffix]] + +assert fib(0) == 1 +assert fib(1) == 1 +--- +assistant + if n < 2: + return 1 + return fib(n - 1) + fib(n - 2) +--- +user +[[prefix]] +import yaml +import os +import openai +import re +import pandas as pd +import sys + +pd.options.display.max_rows = 4000 + +# Read YAML file +with open("secrets.yaml", 'r') as ymlfile: + cfg = yaml.load(ymlfile, Loader=yaml.FullLoader) +[[suffix]] + + openai.organization = ORG_ID + openai.api_key = API_KEY +--- +assistant + ORG_ID = cfg['ORG_ID'] + API_KEY = cfg['API_KEY'] +--- +user +[[prefix]] +{{prefix}} +[[suffix]] +{{suffix}} \ No newline at end of file diff --git a/src/vs/editor/contrib/leap/browser/Leap.ts b/src/vs/editor/contrib/leap/browser/Leap.ts index fcb4df911316d..18dd143d497ce 100644 --- a/src/vs/editor/contrib/leap/browser/Leap.ts +++ b/src/vs/editor/contrib/leap/browser/Leap.ts @@ -337,55 +337,12 @@ class Leap implements IEditorContribution { // TODO (lisa) bad hack below, should remove when the server logic is set up for the web version const modelRequest = await this._utils.buildRequest(prefix, suffix); this._logger.modelRequest(modelRequest); - const events: string[] = await this._utils.getCompletions( + const codes: string[] = await this._utils.getCompletions( modelRequest, signal, (_e) => progressBar.worked(1)); - console.debug('Got the following events from the server:\n', events); - - // We're streaming the data, so we need to reconstruct it here. - // TODO (kas) we can technically be constructing it in the `onDownloadProgress` function, - // but this is a bit easier :/ - // TODO (kas) Is there a library function for handling this, so we don't need to parse it - // manually? - const codes = []; - for (const eventStr of events) { - if (!eventStr.startsWith('data:')) { - console.error('Event line does NOT start with `data:`. This should not happen.'); - continue; - } - - if (eventStr === 'data: [DONE]') { - // We should be done. - continue; - } - - const event = JSON.parse(eventStr.slice(5).trim()); - - if (!('choices' in event)) { - if ('error' in event && 'message' in event.error) { - // They sent us an error message. - rs.push(new ErrorMessage(event.error.message)); - } else { - console.error('Event format not recognized, skipping.'); - console.error(event); - rs.push(new ErrorMessage('Message not recognized. Please see logs for details.')); - } - continue; - } - - for (const choice of event.choices) { - const i = choice.index; - const text = choice.text; - - while (codes.length <= i) { - codes.push(''); - } - - codes[i] += text; - } - } + console.debug('Got the following completions from the server:\n', codes); // Remove empty or repeated completions. const set = new Set(); diff --git a/src/vs/editor/contrib/leap/browser/LeapInterfaces.ts b/src/vs/editor/contrib/leap/browser/LeapInterfaces.ts index 3369b12846042..36c37c0803b19 100644 --- a/src/vs/editor/contrib/leap/browser/LeapInterfaces.ts +++ b/src/vs/editor/contrib/leap/browser/LeapInterfaces.ts @@ -6,7 +6,7 @@ import { ALogger, StudyGroup } from "../../rtv/browser/RTVInterfaces"; // remote and local versions. export interface OpenAIRequest { 'model': string; - 'prompt'?: string | null; + 'messages': OpenAIMessage[]; 'suffix'?: string | null; 'max_tokens'?: number | null; 'temperature'?: number | null; @@ -19,10 +19,14 @@ export interface OpenAIRequest { 'presence_penalty'?: number | null; 'frequency_penalty'?: number | null; 'best_of'?: number | null; - 'logit_bias'?: object | null; 'user'?: string; } +export interface OpenAIMessage { + role: "assistant" | "system" | "user"; + content: string; +} + export { StudyGroup } from "../../rtv/browser/RTVInterfaces"; export interface LeapUtils { @@ -109,4 +113,4 @@ export abstract class ALeapLogger extends ALogger implements ILeapLogger { async panelUnfocus() { await this.log('leap.panel.unfocus'); } -} \ No newline at end of file +} diff --git a/src/vs/editor/contrib/leap/browser/LeapUtils.ts b/src/vs/editor/contrib/leap/browser/LeapUtils.ts index f4e096cf1a700..1ba67d1bf29be 100644 --- a/src/vs/editor/contrib/leap/browser/LeapUtils.ts +++ b/src/vs/editor/contrib/leap/browser/LeapUtils.ts @@ -1,16 +1,19 @@ -import * as openai from 'openai'; +import OpenAI from 'openai'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { ALeapLogger, ILeapLogger, LeapConfig, LeapUtils, OpenAIRequest } from 'vs/editor/contrib/leap/browser/LeapInterfaces'; +import { ALeapLogger, ILeapLogger, LeapConfig, LeapUtils, OpenAIMessage, OpenAIRequest } from 'vs/editor/contrib/leap/browser/LeapInterfaces'; import { StudyGroup } from '../../rtv/browser/RTVInterfaces'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { getOSEnvVariable } from '../../rtv/browser/RTVUtils'; + +const LEAP_PROMPT = getOSEnvVariable('LEAP_PROMPT'); class LocalUtils implements LeapUtils { public readonly EOL: string = os.EOL; - private _openAi: openai.OpenAIApi; + private _openAi: OpenAI; private _requestTemplate = { - model: "code-davinci-002", + model: "gpt-3.5-turbo", temperature: 0.5, n: 5, max_tokens: 512, @@ -20,10 +23,10 @@ class LocalUtils implements LeapUtils { constructor() { // Configure OpenAI api - const openAiConfig = new openai.Configuration({ + this._openAi = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, + dangerouslyAllowBrowser: true }); - this._openAi = new openai.OpenAIApi(openAiConfig); } async getConfig(): Promise { @@ -31,13 +34,20 @@ class LocalUtils implements LeapUtils { } async getCompletions(request: OpenAIRequest, signal: AbortSignal, progressCallback: (e: any) => void): Promise { - const completions = await this._openAi.createCompletion( - request, - { - onDownloadProgress: progressCallback, - signal: signal - }); - return (completions.data as unknown as string).split('\n\n'); + // @ts-ignore + const completionArgs: OpenAI.ChatCompletionCreateParamsStreaming = request; + const completions = await this._openAi.chat.completions.create(completionArgs); + + signal.onabort = ((_) => { completions.controller.abort(); }); + const codes = Array.from({ length: (request.n || 1) }, () => ""); + for await (const part of completions) { + const i = part.choices[0].index; + const delta = part.choices[0].delta.content ?? ''; + codes[i] += delta; + progressCallback(part); + } + + return codes; } getLogger(editor: ICodeEditor): ILeapLogger { @@ -45,14 +55,58 @@ class LocalUtils implements LeapUtils { } async buildRequest(prefix: string, suffix: string): Promise { + const messages = parsePromptFile(LEAP_PROMPT, { prefix, suffix }); return { - prompt: prefix, - suffix: suffix, - ...this._requestTemplate + ...this._requestTemplate, + messages, }; } } +export function parsePromptFile(filename: string, substitutions: { [key: string]: string }): OpenAIMessage[] { + /** + * 1. Parse the file at prompt/{{filename}}.txt + * 2. Subsitute all words in the text file of {{key}} to the value at substitutions[key]. + * 3. Generate a message list for use with the OpenAI API. + */ + + const filePath = filename; + + if (!fs.existsSync(filePath)) { + throw new Error(`Could not find prompt file ${filePath}`); + } + + const text = fs.readFileSync(filePath, 'utf-8'); + const sections = text.split('---\n'); + const chatText: OpenAIMessage[] = []; + + for (const section of sections) { + const sectionLines = section.split('\n'); + const role = sectionLines[0]; + let content = sectionLines.slice(1).join('\n'); + + for (const [key, value] of Object.entries(substitutions)) { + content = content.replace(new RegExp(`{${key}}`, 'g'), value); + } + + const hasMustaches = + content.includes('{{') && content.includes('}}'); + + if (hasMustaches) { + throw new Error(`Mustache brackets were not replaced in ${filename}.txt`); + } + if (role !== 'system' && role !== 'user' && role !== 'assistant') { + throw new Error(`Role is not 'system', 'user', or 'assistant'. It is '${role}'.`); + } + + chatText.push({ + role, + content, + }); + } + return chatText; +} + export function getUtils(): LeapUtils { return new LocalUtils(); } diff --git a/src/vs/editor/contrib/leap/browser/README.md b/src/vs/editor/contrib/leap/browser/README.md new file mode 100644 index 0000000000000..4e384915e1f6e --- /dev/null +++ b/src/vs/editor/contrib/leap/browser/README.md @@ -0,0 +1,68 @@ +# Leap +Leap (Live Exploration of AI-Generated Code) is a Copilot-like tool that generates code completions within the current buffer. + +## How to develop Leap +All of the Leap front-end-related code is under `./src/vs/editor/contrib/leap/browser`. + +There are few requirements before you could develop for Leap + +1. Node JS 16.14+ +2. Python 3 preferably 3.8.* or above +3. npm +4. yarn (this could be installed using npm) + +Once you satisfy the requierments please follow the next steps to setup your environment + +### Build and run via VS Code + +1. Open up a terminal, type `arch` to ensure that you are using a x86_64 architecture (attn: mac users) +2. Type `yarn` or `yarn install` in the vscode directory +3. Then open the vscode dircetory using your own VS Code local installation (you could download it online if you don't have one installed) +4. In the `launch.json` under `.vscode` directory set the following env variables under `Launch VS Code Internal` + +- You may also configure these environment variables in your shell configuration (e.g., in `~/.profile`). +- Alternatively, you may configure the variables in `./.env`, and declare in `inputs` in `.vscode/launch.json` the id's and keys of the configured variables. For example, if you have configured `PYTHON3=/usr/local/bin/python3` in `./.env`, then the `inputs` in `./vscode/launch.json` should be +``` + "inputs": [ + { + "id": "envPYTHON3", + "type": "command", + "command": "extension.commandvariable.file.content", + "args": { + "fileName": "${workspaceFolder}/.env", + "key": "PYTHON3", + "default": "" + } + } + ] +``` +and the environment variable configuration in `Launch VS Code Internal`, under `.vscode/launch.json`, should be +``` +"env": { + "PYTHON3": "${input:envPYTHON3}" +} +``` + +5. Then press `CTRL + SHIFT + B` or `CMD + SHIFT + B` on mac and run with `Launch VS Code Internal` to build the configuration + +If everything goes well you should be able run the build by pressing `F5`. Open a python file with extension .py, and you should see the projection boxes. + +### Build and run via the command line +1. Open up a terminal, type `arch` to ensure that you are using a x86_64 architecture (attn: mac users) +2. Type `yarn` or `yarn install` in the vscode directory +3. Type `yarn compile` in the vscode directory to build from source +4. Configure the following environment variables in your shell configuration +``` +PYTHON3: path to your python3 binary +RUNPY: absolute path to run.py under src directory +IMGSUM: absolute path to img-summary.py under src directory +LEAP_PROMPT: absolute path to implement_it.txt under src directory +OPENAI_API_KEY: your OpenAI API key +``` + +- Alternatively, you can also pass the environment variable bindings when executing `run.sh` (see next step) +5. Type `./run.sh` in the vscode directory to run Leap from the command line. You may additionally pass in environment variables at the beginning of the command, e.g., `OPENAI_API_KEY=my_awesome_key ./run.sh` if you want to override the variables defined in your shell profile. + + +## How to invoke Leap +In an opened Python file, press `CTRL + ENTER` (`CMD + ENTER` on mac) to see a side panel of code suggestions. diff --git a/src/vs/editor/contrib/leap/browser/remote/LeapUtils.ts b/src/vs/editor/contrib/leap/browser/remote/LeapUtils.ts index ac939330cfd99..2947601d5f629 100644 --- a/src/vs/editor/contrib/leap/browser/remote/LeapUtils.ts +++ b/src/vs/editor/contrib/leap/browser/remote/LeapUtils.ts @@ -1,10 +1,18 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { LeapConfig, LeapUtils, OpenAIRequest, ALeapLogger, ILeapLogger } from 'vs/editor/contrib/leap/browser/LeapInterfaces'; +import { parsePromptFile } from 'vs/editor/contrib/leap/browser/LeapUtils'; import { LogEventData, LogResultData } from 'vs/editor/contrib/rtv/browser/RTVInterfaces'; class RemoteUtils implements LeapUtils { public readonly EOL: string = '\n'; - private _requestTemplate?: OpenAIRequest = undefined; + private _requestTemplate = { + model: "gpt-3.5-turbo", + temperature: 0.5, + n: 5, + max_tokens: 512, + stop: [this.EOL + this.EOL], + stream: true, + }; constructor() { this.fetchRequestTemplate(); @@ -59,18 +67,12 @@ class RemoteUtils implements LeapUtils { return new LeapLogger(); } + // TODO: use the correct path for vscode/src/prompts/implement_it.txt async buildRequest(prefix: string, suffix: string): Promise { - let template; - if (this._requestTemplate) { - template = this._requestTemplate; - } else { - template = await this.fetchRequestTemplate(); - } - + const messages = parsePromptFile("implement_it", { prefix, suffix }); return { - prompt: prefix, - suffix: suffix, - ...template + ...this._requestTemplate, + messages, }; } @@ -84,6 +86,7 @@ class RemoteUtils implements LeapUtils { } ); const body: OpenAIRequest = await res.json(); + // @ts-ignore this._requestTemplate = body; return body; } diff --git a/src/vs/editor/contrib/rtv/browser/remote/RTVUtils.ts b/src/vs/editor/contrib/rtv/browser/remote/RTVUtils.ts index b3131221cc0a3..ae947875f1395 100644 --- a/src/vs/editor/contrib/rtv/browser/remote/RTVUtils.ts +++ b/src/vs/editor/contrib/rtv/browser/remote/RTVUtils.ts @@ -280,7 +280,7 @@ class RemoteUtils implements Utils { logger(editor: ICodeEditor): IRTVLogger { this._editor = editor; if (!this._logger) { - this._logger = new RTVLogger(); + this._logger = new RTVLogger(editor); } return this._logger; } diff --git a/yarn.lock b/yarn.lock index 01711e9279b71..6cbe21fde00fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1004,6 +1004,14 @@ "@types/node" "*" form-data "^3.0.0" +"@types/node-fetch@^2.6.4": + version "2.6.10" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.10.tgz#ff5c1ceacab782f2b7ce69957d38c1c27b0dc469" + integrity sha512-PPpPK6F9ALFTn59Ka3BaL+qGuipRfxNE8qVgkp0bVixeiR2c2/L+IVOiBdu9JhhT22sWnQEp6YyHGI2b2+CMcA== + dependencies: + "@types/node" "*" + form-data "^4.0.0" + "@types/node@*": version "4.2.22" resolved "https://registry.yarnpkg.com/@types/node/-/node-4.2.22.tgz#cf488a0f6b4a9c245d09927f4f757ca278b9c8ce" @@ -1024,6 +1032,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.31.tgz#1dad8138efee6808809bb80f9e66bbe3e46c9277" integrity sha512-wh/d0pcu/Ie2mqTIqh4tjd0mLAB4JWxOjHQtLN20HS7sjMHiV4Afr+90hITTyZcxowwha5wjv32jGEn1zkEFMg== +"@types/node@^18.11.18": + version "18.19.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.4.tgz#89672e84f11a2c19543d694dac00ab8d7bc20ddb" + integrity sha512-xNzlUhzoHotIsnFoXmJB+yWmBvFZgKCI9TtPIEdYIMM1KWfwuY8zh7wvc1u1OAXlC7dlf6mZVx/s+Y5KfFz19A== + dependencies: + undici-types "~5.26.4" + "@types/q@^1.5.1": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" @@ -1621,6 +1636,13 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + accepts@^1.3.5: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -1687,6 +1709,13 @@ agent-base@^6.0.2: dependencies: debug "4" +agentkeepalive@^4.2.1: + version "4.5.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== + dependencies: + humanize-ms "^1.2.1" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -2106,13 +2135,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axios@^0.26.0: - version "0.26.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" - integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== - dependencies: - follow-redirects "^1.14.8" - bach@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" @@ -2133,6 +2155,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base-64@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" + integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA== + base64-js@^1.0.2, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -2639,7 +2666,7 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -charenc@~0.0.1: +charenc@0.0.2, charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= @@ -3208,7 +3235,7 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -crypt@~0.0.1: +crypt@0.0.2, crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= @@ -3761,6 +3788,14 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +digest-fetch@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/digest-fetch/-/digest-fetch-1.3.0.tgz#898e69264d00012a23cf26e8a3e40320143fc661" + integrity sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA== + dependencies: + base-64 "^0.1.0" + md5 "^2.3.0" + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -4414,6 +4449,11 @@ event-stream@~3.3.4: stream-combiner "^0.2.2" through "^2.3.8" +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + events@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" @@ -4854,11 +4894,6 @@ flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: inherits "^2.0.3" readable-stream "^2.3.6" -follow-redirects@^1.14.8: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== - for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -4881,6 +4916,11 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +form-data-encoder@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040" + integrity sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A== + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -4908,6 +4948,14 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +formdata-node@^4.3.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2" + integrity sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ== + dependencies: + node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.3" + fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -5890,6 +5938,13 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + husky@^0.13.1: version "0.13.4" resolved "https://registry.yarnpkg.com/husky/-/husky-0.13.4.tgz#48785c5028de3452a51c48c12c4f94b2124a1407" @@ -6149,7 +6204,7 @@ is-boolean-object@^1.1.0: dependencies: call-bind "^1.0.2" -is-buffer@^1.1.5, is-buffer@~1.1.1: +is-buffer@^1.1.5, is-buffer@~1.1.1, is-buffer@~1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -7172,6 +7227,15 @@ md5@^2.1.0: crypt "~0.0.1" is-buffer "~1.1.1" +md5@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" + integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== + dependencies: + charenc "0.0.2" + crypt "0.0.2" + is-buffer "~1.1.6" + mdn-data@2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" @@ -7562,7 +7626,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -7712,6 +7776,11 @@ node-addon-api@^4.3.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== +node-domexception@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-fetch@^2.6.0, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -8047,13 +8116,20 @@ only@~0.0.2: resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= -openai@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/openai/-/openai-3.1.0.tgz#13bfb228cf777155b882c2deb3a03bc5094cb7b3" - integrity sha512-v5kKFH5o+8ld+t0arudj833Mgm3GcgBnbyN9946bj6u7bvel4Yg6YFz2A4HLIYDzmMjIo0s6vSG9x73kOwvdCg== - dependencies: - axios "^0.26.0" - form-data "^4.0.0" +openai@^4.24.1: + version "4.24.1" + resolved "https://registry.yarnpkg.com/openai/-/openai-4.24.1.tgz#3759001eca835228289fcf18c1bd8d35dae538ba" + integrity sha512-ezm/O3eiZMnyBqirUnWm9N6INJU1WhNtz+nK/Zj/2oyKvRz9pgpViDxa5wYOtyGYXPn1sIKBV0I/S4BDhtydqw== + dependencies: + "@types/node" "^18.11.18" + "@types/node-fetch" "^2.6.4" + abort-controller "^3.0.0" + agentkeepalive "^4.2.1" + digest-fetch "^1.3.0" + form-data-encoder "1.7.2" + formdata-node "^4.3.2" + node-fetch "^2.6.7" + web-streams-polyfill "^3.2.1" opn@^6.0.0: version "6.0.0" @@ -10931,6 +11007,11 @@ undertaker@^1.2.1: object.reduce "^1.0.0" undertaker-registry "^1.0.0" +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -11352,6 +11433,16 @@ watchpack@^2.2.0: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" +web-streams-polyfill@4.0.0-beta.3: + version "4.0.0-beta.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" + integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== + +web-streams-polyfill@^3.2.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz#32e26522e05128203a7de59519be3c648004343b" + integrity sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"