From a35576a5ee9f8c4382bec674f2ec099c2147dbd2 Mon Sep 17 00:00:00 2001 From: Shivaditya Shivganesh Date: Thu, 9 Jan 2025 00:06:30 -0500 Subject: [PATCH] feat: add explore dir tool --- package.json | 1 + src/adapters/openai/helpers/completions.ts | 67 ++++++++++ src/adapters/openai/helpers/openai.ts | 11 ++ src/handlers/front-controller.ts | 79 +++-------- src/handlers/say-hello.ts | 3 - src/tools/explore-dir/index.ts | 78 +++++++++++ src/tools/terminal/index.ts | 125 ++++++++++++++++++ yarn.lock | 145 +++++++++++++++++++++ 8 files changed, 446 insertions(+), 63 deletions(-) create mode 100644 src/adapters/openai/helpers/completions.ts create mode 100644 src/adapters/openai/helpers/openai.ts delete mode 100644 src/handlers/say-hello.ts create mode 100644 src/tools/explore-dir/index.ts create mode 100644 src/tools/terminal/index.ts diff --git a/package.json b/package.json index be1d8b91..df7950ab 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@sinclair/typebox": "0.32.33", "@ubiquity-dao/ubiquibot-logger": "^1.3.0", "dotenv": "16.4.5", + "openai": "^4.77.4", "typebox-validators": "0.3.5" }, "devDependencies": { diff --git a/src/adapters/openai/helpers/completions.ts b/src/adapters/openai/helpers/completions.ts new file mode 100644 index 00000000..44a919bf --- /dev/null +++ b/src/adapters/openai/helpers/completions.ts @@ -0,0 +1,67 @@ +import OpenAI from "openai"; +import { Context } from "../../../types/context"; +import { SuperOpenAi } from "./openai"; + +const sysMsg = `You are a capable AI assistant currently running on a GitHub bot. +You are designed to assist with repository maintenance, code reviews, and issue resolution. +You have access to the following tools: +- read_file: Read contents of a file in the repository +- write_file: Write/update contents to a file +- terminal: Execute terminal commands +- test_code: Run tests for the codebase + +Always be professional, concise, and follow these rules: +1. Before making changes, understand the context fully +2. When modifying code, ensure it maintains existing functionality +3. Follow the project's coding style and conventions +4. Document any significant changes +5. Consider edge cases and error handling`; + +export class Completions extends SuperOpenAi { + protected context: Context; + protected model: string; + protected maxTokens: number; + + constructor(client: OpenAI, context: Context) { + super(client, context); + this.context = context; + this.model = "claude/sonnet"; + this.maxTokens = 100; + } + + async createCompletion(prompt: string) { + const res: OpenAI.Chat.Completions.ChatCompletion = await this.client.chat.completions.create({ + model: this.model, + messages: [ + { + role: "system", + content: [ + { + type: "text", + text: sysMsg, + }, + ], + }, + { + role: "user", + content: [ + { + type: "text", + text: prompt, + }, + ], + }, + ], + temperature: 0.2, + max_tokens: this.maxTokens, + top_p: 0.5, + frequency_penalty: 0, + presence_penalty: 0, + response_format: { + type: "text", + }, + }); + + return res; + } +} diff --git a/src/adapters/openai/helpers/openai.ts b/src/adapters/openai/helpers/openai.ts new file mode 100644 index 00000000..11457c6e --- /dev/null +++ b/src/adapters/openai/helpers/openai.ts @@ -0,0 +1,11 @@ +import { OpenAI } from "openai"; +import { Context } from "../../../types/context"; + +export class SuperOpenAi { + protected client: OpenAI; + protected context: Context; + constructor(client: OpenAI, context: Context) { + this.client = client; + this.context = context; + } +} diff --git a/src/handlers/front-controller.ts b/src/handlers/front-controller.ts index 8fac11c3..a0c35e4f 100644 --- a/src/handlers/front-controller.ts +++ b/src/handlers/front-controller.ts @@ -1,69 +1,28 @@ +import { ExploreDir } from "../tools/explore-dir"; import { Context } from "../types"; -import { sayHello } from "./say-hello"; -/** - * NOTICE: Remove this file or use it as a template for your own plugins. - * - * This encapsulates the logic for a plugin if the only thing it does is say "Hello, world!". - * - * Try it out by running your local kernel worker and running the `yarn worker` command. - * Comment on an issue in a repository where your GitHub App is installed and see the magic happen! - * - * Logger examples are provided to show how to log different types of data. - */ export async function delegate(context: Context) { - const { logger, payload, octokit } = context; - - const sender = payload.comment.user?.login; + const { logger, payload } = context; + const body = payload.comment.body; const repo = payload.repository.name; - const issueNumber = payload.issue.number; const owner = payload.repository.owner.login; - const body = payload.comment.body; - - logger.debug(`Executing decideHandler:`, { sender, repo, issueNumber, owner }); - - const targetUser = body.match(/^\/\B@([a-z0-9](?:-(?=[a-z0-9])|[a-z0-9]){0,38}(?<=[a-z0-9]))/i); - if (!targetUser) { - logger.error(`Missing target username from comment: ${body}`); - return; - } - const personalAgentOwner = targetUser[0].replace("/@", ""); - - logger.info(`Comment received:`, { owner, personalAgentOwner, comment: body }); - - let reply; - - if (body.match(/^\/\B@([a-z0-9](?:-(?=[a-z0-9])|[a-z0-9]){0,38}(?<=[a-z0-9]))\s+say\s+hello/i)) { - reply = sayHello(); - } else { - reply = "I could not understand your comment to give you a quick response. I will get back to you later."; - logger.error(`Invalid command.`, { body }); - } - - const replyWithQuote = ["> ", `${body}`, "\n\n", reply].join(""); + const issueNumber = payload.issue.number; - try { - await octokit.issues.createComment({ - owner: payload.repository.owner.login, - repo: payload.repository.name, - issue_number: payload.issue.number, - body: replyWithQuote, - }); - } catch (error) { - /** - * logger.fatal should not be used in 9/10 cases. Use logger.error instead. - * - * Below are examples of passing error objects to the logger, only one is needed. - */ - if (error instanceof Error) { - logger.error(`Error creating comment:`, { error: error, stack: error.stack }); - throw error; - } else { - logger.error(`Error creating comment:`, { err: error, error: new Error() }); - throw error; - } + // Check if the comment is requesting to solve the issue + if (body.toLowerCase().includes("solve this issue")) { + // Initialize LLM tools + const explore = new ExploreDir(); + // Get the current directory tree + let tree = await explore.current_dir_tree(); + // Log the tree + logger.info(tree); + // Clone the repository and get the file tree + await explore.clone_repo(repo, owner, issueNumber); + // Log the tree again + tree = await explore.current_dir_tree(); + logger.info(tree); } - logger.ok(`Comment created: ${reply}`); - logger.verbose(`Exiting decideHandler`); + logger.ok(`Comment processed: ${body}`); + logger.verbose(`Exiting delegate`); } diff --git a/src/handlers/say-hello.ts b/src/handlers/say-hello.ts deleted file mode 100644 index c760f97f..00000000 --- a/src/handlers/say-hello.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function sayHello() { - return "Hello"; -} diff --git a/src/tools/explore-dir/index.ts b/src/tools/explore-dir/index.ts new file mode 100644 index 00000000..c4dc8333 --- /dev/null +++ b/src/tools/explore-dir/index.ts @@ -0,0 +1,78 @@ +import { commonCallBack, Terminal } from "../terminal"; + +export class ExploreDir { + private _shellInterface: Terminal; + + constructor() { + this._shellInterface = new Terminal(commonCallBack("stdout"), commonCallBack("stderr"), commonCallBack("exit")); + } + + current_dir_tree(): Promise { + return new Promise((resolve, reject) => { + let output = ""; + let isCompleted = false; + + this._shellInterface.runCommand("ls -R"); + + const stdout = this._shellInterface.outputOnStdout(); + if (!stdout) { + reject(new Error("No bash instance running")); + return; + } + stdout.on("data", (data: string) => { + output += data.toString(); + if (isCompleted) { + resolve(output); + } + }); + + this._shellInterface.hasCommandCompleted(); + stdout.on("data", (data: string) => { + const exitCode = parseInt(data.toString().trim()); + if (exitCode === 0) { + isCompleted = true; + if (output) { + resolve(output); + } + } else { + reject(new Error(`Command failed with exit code ${exitCode}`)); + } + }); + }); + } + + clone_repo(repo: string, owner: string, issueNumber: number): Promise { + return new Promise((resolve, reject) => { + let output = ""; + let isCompleted = false; + const tmpDir = `/tmp/repo-${owner}-${repo}-${issueNumber}`; + + this._shellInterface.runCommand(`git clone git@github.com:${owner}/${repo}.git ${tmpDir}`); + + const stdout = this._shellInterface.outputOnStdout(); + if (!stdout) { + reject(new Error("No bash instance running")); + return; + } + stdout.on("data", (data: string) => { + output += data.toString(); + if (isCompleted) { + resolve(output); + } + }); + + this._shellInterface.hasCommandCompleted(); + stdout.on("data", (data: string) => { + const exitCode = parseInt(data.toString().trim()); + if (exitCode === 0) { + isCompleted = true; + if (output) { + resolve(output); + } + } else { + reject(new Error(`Git clone failed with exit code ${exitCode}`)); + } + }); + }); + } +} diff --git a/src/tools/terminal/index.ts b/src/tools/terminal/index.ts new file mode 100644 index 00000000..c374661f --- /dev/null +++ b/src/tools/terminal/index.ts @@ -0,0 +1,125 @@ +import { ChildProcessWithoutNullStreams, spawn } from "child_process"; + +const BASH_ERR_MSG = "No bash instance running."; + +export class Terminal { + private _process: ChildProcessWithoutNullStreams | null; + private _onStdout: (data: string) => void; + private _onStderr: (data: string) => void; + private _onClose: (code: string) => void; + + constructor(onStdout: (data: string) => void, onStderr: (data: string) => void, onClose: (code: string) => void) { + this._process = null; + this.start(); + this._onStdout = onStdout; + this._onStderr = onStderr; + this._onClose = onClose; + } + + // Method to start a bash instance + start() { + this._process = spawn("bash", [], { + stdio: ["pipe", "pipe", "pipe"], + }); + + this._process.stdout.on("data", (data: string) => { + this._onStdout(data); + }); + + this._process.stderr.on("data", (data: string) => { + this._onStderr(data); + }); + + this._process.on("close", (code: string) => { + this._onClose(code); + }); + } + + // Method to run a command in the bash instance + runCommand(command: string) { + if (this._process) { + this._process.stdin.write(`${command}\n`); + } else { + console.error(BASH_ERR_MSG); + } + } + + hasCommandCompleted() { + if (this._process) { + this._process.stdin.write("echo $?"); + } else { + console.error(BASH_ERR_MSG); + } + } + + outputOnStdout() { + if (this._process) { + return this._process.stdout; + } else { + console.error(BASH_ERR_MSG); + } + } + + // Method to kill the bash instance + kill() { + if (this._process) { + this._process.kill(); + this._process = null; + console.log("Bash instance killed."); + } else { + console.error(BASH_ERR_MSG); + } + } +} + +export function commonCallBack(id: string) { + return (data: string) => { + console.log(`Terminal ${id} stdout: ${data}`); + }; +} + +export class TerminalManager { + private _terminals: Map; + constructor() { + this._terminals = new Map(); + this.init(); + } + + init() { + console.log("TerminalManager initialized"); + } + + // Method to create a new terminal instance + createTerminal(id: string) { + if (this._terminals.has(id)) { + console.error(`Terminal with id ${id} already exists.`); + return; + } + const terminal = new Terminal(commonCallBack(id), commonCallBack(id), commonCallBack(id)); + this._terminals.set(id, terminal); + terminal.start(); + console.log(`Terminal with id ${id} created.`); + } + + // Method to run a command in a specific terminal instance + runCommandInTerminal(id: string, command: string) { + const terminal = this._terminals.get(id); + if (terminal) { + terminal.runCommand(command); + } else { + console.error(`Terminal with id ${id} does not exist.`); + } + } + + // Method to kill a specific terminal instance + killTerminal(id: string) { + const terminal = this._terminals.get(id); + if (terminal) { + terminal.kill(); + this._terminals.delete(id); + console.log(`Terminal with id ${id} killed.`); + } else { + console.error(`Terminal with id ${id} does not exist.`); + } + } +} diff --git a/yarn.lock b/yarn.lock index 02ef2336..ad485eb8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1927,6 +1927,14 @@ dependencies: "@types/node" "*" +"@types/node-fetch@^2.6.4": + version "2.6.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.12.tgz#8ab5c3ef8330f13100a7479e2cd56d3386830a03" + integrity sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA== + dependencies: + "@types/node" "*" + form-data "^4.0.0" + "@types/node-forge@^1.3.0": version "1.3.11" resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" @@ -1948,6 +1956,13 @@ dependencies: undici-types "~5.26.4" +"@types/node@^18.11.18": + version "18.19.70" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.70.tgz#5a77508f5568d16fcd3b711c8102d7a430a04df7" + integrity sha512-RE+K0+KZoEpDUbGGctnGdkrLFwi1eYKTlIHNl2Um98mUkGsm1u2Ff6Ltd0e8DktTtC98uy7rSj+hO8t/QuLoVQ== + dependencies: + undici-types "~5.26.4" + "@types/pluralize@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/pluralize/-/pluralize-0.0.29.tgz#6ffa33ed1fc8813c469b859681d09707eb40d03c" @@ -2079,6 +2094,13 @@ JSONStream@^1.3.5: jsonparse "^1.2.0" through ">=2.2.7 <3" +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" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -2099,6 +2121,13 @@ acorn@^8.8.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +agentkeepalive@^4.2.1: + version "4.6.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a" + integrity sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ== + 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" @@ -2245,6 +2274,11 @@ async-lock@^1.4.1: resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.1.tgz#56b8718915a9b68b10fce2f2a9a3dddf765ef53f" integrity sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -2589,6 +2623,13 @@ colorette@^2.0.20: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^12.1.0, commander@~12.1.0: version "12.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" @@ -2942,6 +2983,11 @@ defu@^6.1.4: resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + deprecation@^2.0.0: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" @@ -3328,6 +3374,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +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== + eventemitter3@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" @@ -3508,6 +3559,28 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +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@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" + integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + 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" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -3776,6 +3849,13 @@ human-signals@^5.0.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== +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@9.0.11: version "9.0.11" resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.11.tgz#fc91df4c756050de41b3e478b2158b87c1e79af9" @@ -4826,6 +4906,18 @@ micromatch@^4.0.8: braces "^3.0.3" picomatch "^2.3.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mime@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" @@ -4900,6 +4992,11 @@ 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.0.0: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + msw@^2.0.8: version "2.3.1" resolved "https://registry.yarnpkg.com/msw/-/msw-2.3.1.tgz#bfc73e256ffc2c74ec4381b604abb258df35f32b" @@ -4948,6 +5045,18 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +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.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -5053,6 +5162,19 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" +openai@^4.77.4: + version "4.77.4" + resolved "https://registry.yarnpkg.com/openai/-/openai-4.77.4.tgz#1093d165efb3e13e763faf42fa62e34313e293e9" + integrity sha512-rShjKsZ/HXm1cSxXt6iFeZxiCohrVShawt0aRRQmbb+z/EXcH4OouyQZP1ShyZMb63LJajpl8aGw3DzEi8Wh9Q== + dependencies: + "@types/node" "^18.11.18" + "@types/node-fetch" "^2.6.4" + abort-controller "^3.0.0" + agentkeepalive "^4.2.1" + form-data-encoder "1.7.2" + formdata-node "^4.3.2" + node-fetch "^2.6.7" + optionator@^0.9.3: version "0.9.4" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" @@ -5935,6 +6057,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" @@ -6172,6 +6299,24 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +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== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"