From c497d30b49a2ddab71deda77e2d6055c4452c4a7 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Tue, 27 Aug 2024 06:47:03 -0700 Subject: [PATCH] git commit message (#656) * custom message * Add interactive commit prompt utility using inquirer for staged Git changes * Add @inquirer/prompts dependency for interactive commit prompt Upgrade various scripts to use provider:name syntax for model Fix error logging in util.ts * Enhance staging workflow and improve commit message generation process * quote args * Rename gcm.genai.mts and implement inner option for stream handling in chat completion logic * Change default confirmation for staging changes to true in gcm.genai.mts * Improve console logging and error handling with color-coded output and execution feedback * "Update documentation and scripts to streamline automated Git commit message generation" --- .../docs/guides/auto-git-commit-message.mdx | 147 +++++++++++ genaisrc/gcm.genai.mts | 72 ++++++ package.json | 4 +- packages/cli/src/log.ts | 7 +- packages/cli/src/nodehost.ts | 6 +- packages/cli/src/run.ts | 18 +- packages/cli/src/server.ts | 3 +- packages/core/src/aici.ts | 3 +- packages/core/src/chattypes.ts | 2 + packages/core/src/constants.ts | 4 + packages/core/src/generation.ts | 1 + packages/core/src/openai.ts | 3 + packages/core/src/promptcontext.ts | 3 +- packages/core/src/server/client.ts | 1 + packages/core/src/server/messages.ts | 1 + packages/core/src/template.ts | 3 + packages/core/src/util.ts | 19 +- .../sample/genaisrc/blogify-sample.genai.mjs | 1 + yarn.lock | 229 +++++++++++++++++- 19 files changed, 507 insertions(+), 20 deletions(-) create mode 100644 docs/src/content/docs/guides/auto-git-commit-message.mdx create mode 100644 genaisrc/gcm.genai.mts diff --git a/docs/src/content/docs/guides/auto-git-commit-message.mdx b/docs/src/content/docs/guides/auto-git-commit-message.mdx new file mode 100644 index 0000000000..8cfdc8741e --- /dev/null +++ b/docs/src/content/docs/guides/auto-git-commit-message.mdx @@ -0,0 +1,147 @@ +--- +title: "Automated Git Commit Messages" +keywords: ["GenAI", "Git", "Automation"] +sidebar: + order: 15 +--- + +In the world of software development, making consistent and informative commit messages is crucial but often overlooked. +This task can become tedious, especially when you are in the flow of coding. +To help with this, we've crafted a [script tailored to automate generating Git commit messages](](https://github.com/microsoft/genaiscript/blob/main/genaisrc/gcm.genai.mts)), +ensuring they are meaningful and save you time. + +The script acts as a regular node.js automation and uses [runPrompt](/genaiscript/reference/scripts/inner-prompts) +to issue calls to the LLM and ask the user to confirm the generated text. + +## 🔍 **Explaining the Script** + +The script begins by importing necessary functions from [@inquirer/prompts](https://www.npmjs.com/package/@inquirer/prompts): + +```ts +import { select, input, confirm } from "@inquirer/prompts" +``` + +These functions will be used to interact with the user, asking them to confirm actions or input data. + +Next, we check if there are any staged changes in the Git repository: + +```ts +let { stdout } = await host.exec("git", ["diff", "--cached"]) +``` + +If no changes are staged: + +```ts +if (!stdout) { +``` + +We ask the user if they want to stage all changes. If the user confirms, we stage all changes. Otherwise, we bail out. + +```ts + const stage = await confirm({ + message: "No staged changes. Stage all changes?", + default: true, + }) + if (stage) { + await host.exec("git", ["add", "."]) + stdout = (await host.exec("git", ["diff", "--cached"])).stdout + } + if (!stdout) cancel("no staged changes") +} +``` + +We generate an initial commit message using the staged changes: + +```ts +message = ( + await runPrompt( + (_) => { + _.def("GIT_DIFF", stdout, { maxTokens: 20000 }) + _.$`GIT_DIFF is a diff of all staged changes, coming from the command: +\`\`\` +git diff --cached +\`\`\` +Please generate a concise, one-line commit message for these changes. +- do NOT add quotes` + }, + { cache: false, temperature: 0.8 } + ) +).text +``` + +The prompt configuration above indicates that the message should be concise, +related to the "git diff --cached" output, and should not include quotes. + +User chooses how to proceed with the generated message: + +```ts + choice = await select({ + message, + choices: [ + { name: "commit", value: "commit", description: "accept message and commit" }, + ... + ], + }) +``` + +Options are given to edit or regenerate the message. If the user chooses to edit the message, we ask them to input a new message: + +```ts + if (choice === "edit") { + message = await input({ + message: "Edit commit message", + required: true, + }) + choice = "commit" + } +``` + +If the user chooses to commit the message, we commit the changes: + +```ts + if (choice === "commit" && message) { + console.log((await host.exec("git", ["commit", "-m", message])).stdout) + } +``` + +## 🚀 **Running the Script** + +You can run this script using the [CLI](/genaiscript/reference/cli). + +```bash +genaiscript run gcm +``` + +Since it uses the [@inquirer/prompts](https://www.npmjs.com/package/@inquirer/prompts) package, you will need to install this package first: + +```bash +npm install --save-dev @inquirer/prompts +``` + +If you are using [npx](https://docs.npmjs.com/cli/v10/commands/npx), + +```bash +npx -p @inquirer/prompts genaiscript -p genaiscript -- genaiscript run gcm +``` + +This command will run the script, and guide you through the process of generating and committing a Git message using AI, making your commits more informative and consistent. + +You can wrap this command in a `gcm.sh` file or in your package `script` section in `package.json`: + +```json '"gcm": "genaiscript run gcm"' +{ + "devDependencies": { + "@inquirer/prompts": "...", + "genaiscript": "..." + }, + "scripts": { + "gcm": "genaiscript run gcm" + } +} +``` + +Then you can run the script using: + +```bash +npm run gcm +``` \ No newline at end of file diff --git a/genaisrc/gcm.genai.mts b/genaisrc/gcm.genai.mts new file mode 100644 index 0000000000..769f63b8bd --- /dev/null +++ b/genaisrc/gcm.genai.mts @@ -0,0 +1,72 @@ +import { select, input, confirm } from "@inquirer/prompts" + +// Check for staged changes and stage all changes if none are staged +let { stdout } = await host.exec("git", ["diff", "--cached"]) +if (!stdout) { + const stage = await confirm({ + message: "No staged changes. Stage all changes?", + default: true, + }) + if (stage) { + await host.exec("git", ["add", "."]) + stdout = (await host.exec("git", ["diff", "--cached"])).stdout + } + if (!stdout) cancel("no staged changes") +} + +console.log(stdout) + +let choice +let message +do { + // Generate commit message + message = ( + await runPrompt( + (_) => { + _.def("GIT_DIFF", stdout, { maxTokens: 20000 }) + _.$`GIT_DIFF is a diff of all staged changes, coming from the command: +\`\`\` +git diff --cached +\`\`\` +Please generate a concise, one-line commit message for these changes. +- do NOT add quotes` + }, + { cache: false, temperature: 0.8 } + ) + ).text + + // Prompt user for commit message + choice = await select({ + message, + choices: [ + { + name: "commit", + value: "commit", + description: "accept message and commit", + }, + { + name: "edit", + value: "edit", + description: "edit message and commit", + }, + { + name: "regenerate", + value: "regenerate", + description: "regenerate message", + }, + ], + }) + + // Handle user choice + if (choice === "edit") { + message = await input({ + message: "Edit commit message", + required: true, + }) + choice = "commit" + } + // Regenerate message + if (choice === "commit" && message) { + console.log((await host.exec("git", ["commit", "-m", message])).stdout) + } +} while (choice !== "commit") diff --git a/package.json b/package.json index 0cf04b3f5c..6c89b9484d 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,8 @@ "genai:test": "node packages/cli/built/genaiscript.cjs run test-gen", "genai:blog-post": "node packages/cli/built/genaiscript.cjs run blog-generator", "genai:readme": "node packages/cli/built/genaiscript.cjs run readme-updater", - "genai:blogify": "node packages/cli/built/genaiscript.cjs run blogify-sample --no-cache" + "genai:blogify": "node packages/cli/built/genaiscript.cjs run blogify-sample --no-cache", + "gcm": "node packages/cli/built/genaiscript.cjs run gcm" }, "release-it": { "github": { @@ -74,6 +75,7 @@ } }, "dependencies": { + "@inquirer/prompts": "^5.3.8", "glob": "^11.0.0", "zx": "^8.1.4" } diff --git a/packages/cli/src/log.ts b/packages/cli/src/log.ts index 1bbb213002..7a334c936a 100644 --- a/packages/cli/src/log.ts +++ b/packages/cli/src/log.ts @@ -1,18 +1,19 @@ import { stdout } from "node:process" import console from "node:console" +import { CONSOLE_COLOR_DEBUG, CONSOLE_COLOR_WARNING, CONSOLE_COLOR_ERROR } from "../../core/src/constants" export const info = console.error export function debug(...args: any[]) { - if (!isQuiet) console.error(...wrapArgs(34, args)) + if (!isQuiet) console.error(...wrapArgs(CONSOLE_COLOR_DEBUG, args)) } export function warn(...args: any[]) { - console.error(...wrapArgs(95, args)) + console.error(...wrapArgs(CONSOLE_COLOR_WARNING, args)) } export function error(...args: any[]) { - console.error(...wrapArgs(91, args)) + console.error(...wrapArgs(CONSOLE_COLOR_ERROR, args)) } export let consoleColors = !!stdout.isTTY diff --git a/packages/cli/src/nodehost.ts b/packages/cli/src/nodehost.ts index f31a36e86e..360a5c4202 100644 --- a/packages/cli/src/nodehost.ts +++ b/packages/cli/src/nodehost.ts @@ -280,8 +280,12 @@ export class NodeHost implements RuntimeHost { if (command === "python" && process.platform !== "win32") command = "python3" + const quoteify = (a: string) => (/\s/.test(a) ? `"${a}"` : a) + logVerbose( + `exec ${cwd ? `${cwd}> ` : ""}${quoteify(command)} ${args.map(quoteify).join(" ")}` + ) trace?.itemValue(`cwd`, cwd) - trace?.item(`\`${command}\` ${args.join(" ")}`) + trace?.item(`${command} ${args.map(quoteify).join(" ")}`) const { stdout, stderr, exitCode, failed } = await execa( command, diff --git a/packages/cli/src/run.ts b/packages/cli/src/run.ts index 3a5792dc19..4731f01a1d 100644 --- a/packages/cli/src/run.ts +++ b/packages/cli/src/run.ts @@ -1,6 +1,6 @@ import { capitalize } from "inflection" import { resolve, join, relative, dirname } from "node:path" -import { isQuiet } from "./log" +import { isQuiet, wrapColor } from "./log" import { emptyDir, ensureDir, appendFileSync } from "fs-extra" import { convertDiagnosticsToSARIF } from "./sarif" import { buildProject } from "./build" @@ -28,6 +28,7 @@ import { UNRECOVERABLE_ERROR_CODES, SUCCESS_ERROR_CODE, RUNS_DIR_NAME, + CONSOLE_COLOR_DEBUG, } from "../../core/src/constants" import { isCancelError, errorMessage } from "../../core/src/error" import { Fragment, GenerationResult } from "../../core/src/generation" @@ -241,6 +242,7 @@ export async function runScript( trace.options.encoder = await resolveTokenEncoder(info.model) await runtimeHost.models.pullModel(info.model) result = await runTemplate(prj, script, fragment, { + inner: false, infoCb: (args) => { const { text } = args if (text) { @@ -249,11 +251,19 @@ export async function runScript( } }, partialCb: (args) => { - const { responseChunk, tokensSoFar } = args + const { responseChunk, tokensSoFar, inner } = args tokens = tokensSoFar if (responseChunk !== undefined) { - if (stream) process.stdout.write(responseChunk) - else if (!isQuiet) process.stderr.write(responseChunk) + if (stream) { + if (!inner) process.stdout.write(responseChunk) + else + process.stderr.write( + wrapColor(CONSOLE_COLOR_DEBUG, responseChunk) + ) + } else if (!isQuiet) + process.stderr.write( + wrapColor(CONSOLE_COLOR_DEBUG, responseChunk) + ) } partialCb?.(args) }, diff --git a/packages/cli/src/server.ts b/packages/cli/src/server.ts index fa37711ed1..762dd2cecc 100644 --- a/packages/cli/src/server.ts +++ b/packages/cli/src/server.ts @@ -97,7 +97,7 @@ export async function startServer(options: { port: string }) { trace: MarkdownTrace ): Promise => { const { messages, model } = req - const { partialCb } = options + const { partialCb, inner } = options if (!wss.clients?.size) throw new Error("no llm clients connected") return new Promise((resolve, reject) => { @@ -120,6 +120,7 @@ export async function startServer(options: { port: string }) { tokensSoFar, responseSoFar, responseChunk: chunk.chunk, + inner, }) finishReason = chunk.finishReason as any if (finishReason) { diff --git a/packages/core/src/aici.ts b/packages/core/src/aici.ts index d6c8f786d0..133b9b102f 100644 --- a/packages/core/src/aici.ts +++ b/packages/core/src/aici.ts @@ -143,7 +143,7 @@ const AICIChatCompletion: ChatCompletionHandler = async ( trace ) => { const { messages, response_format, tools } = req - const { requestOptions, partialCb, cancellationToken } = options + const { requestOptions, partialCb, cancellationToken, inner } = options const { headers, ...rest } = requestOptions || {} if (tools?.length) throw new NotSupportedError("AICI: tools not supported") @@ -342,6 +342,7 @@ const AICIChatCompletion: ChatCompletionHandler = async ( responseSoFar: chatResp, tokensSoFar: numTokens, responseChunk: progress, + inner, }) } pref = chunk diff --git a/packages/core/src/chattypes.ts b/packages/core/src/chattypes.ts index f9f5cb3431..5ef2511761 100644 --- a/packages/core/src/chattypes.ts +++ b/packages/core/src/chattypes.ts @@ -78,6 +78,7 @@ export interface ChatCompletionsProgressReport { tokensSoFar: number responseSoFar: string responseChunk: string + inner: boolean } export interface ChatCompletionsOptions { @@ -90,4 +91,5 @@ export interface ChatCompletionsOptions { retry?: number retryDelay?: number maxDelay?: number + inner: boolean } diff --git a/packages/core/src/constants.ts b/packages/core/src/constants.ts index 482a9ecf2f..902379af6f 100644 --- a/packages/core/src/constants.ts +++ b/packages/core/src/constants.ts @@ -220,3 +220,7 @@ export const PLACEHOLDER_API_KEY = "" export const VSCODE_CONFIG_CLI_VERSION = "cli.version" export const VSCODE_CONFIG_CLI_PATH = "cli.path" + +export const CONSOLE_COLOR_DEBUG = 34 +export const CONSOLE_COLOR_WARNING = 95 +export const CONSOLE_COLOR_ERROR = 91 diff --git a/packages/core/src/generation.ts b/packages/core/src/generation.ts index 8561c5236e..3b5a4bd42e 100644 --- a/packages/core/src/generation.ts +++ b/packages/core/src/generation.ts @@ -72,6 +72,7 @@ export interface GenerationOptions ModelOptions, EmbeddingsModelOptions, ScriptRuntimeOptions { + inner: boolean cancellationToken?: CancellationToken infoCb?: (partialResponse: { text: string }) => void trace: MarkdownTrace diff --git a/packages/core/src/openai.ts b/packages/core/src/openai.ts index a7f7243f77..bbfa0c959b 100644 --- a/packages/core/src/openai.ts +++ b/packages/core/src/openai.ts @@ -62,6 +62,7 @@ export const OpenAIChatCompletion: ChatCompletionHandler = async ( retryDelay, maxDelay, cancellationToken, + inner, } = options const { headers, ...rest } = requestOptions || {} const { token, source, ...cfgNoToken } = cfg @@ -96,6 +97,7 @@ export const OpenAIChatCompletion: ChatCompletionHandler = async ( tokensSoFar: estimateTokens(cached, encoder), responseSoFar: cached, responseChunk: cached, + inner, }) trace.itemValue(`cache hit`, await cache.getKeySHA(cachedKey)) return { text: cached, finishReason: cachedFinishReason, cached: true } @@ -261,6 +263,7 @@ export const OpenAIChatCompletion: ChatCompletionHandler = async ( responseSoFar: chatResp, tokensSoFar: numTokens, responseChunk: progress, + inner }) } pref = chunk diff --git a/packages/core/src/promptcontext.ts b/packages/core/src/promptcontext.ts index b9d138a93c..6e2f45c3d4 100644 --- a/packages/core/src/promptcontext.ts +++ b/packages/core/src/promptcontext.ts @@ -234,6 +234,7 @@ export async function createPromptContext( infoCb?.({ text: `run prompt ${label || ""}` }) const genOptions = mergeGenerationOptions(options, runOptions) + genOptions.inner = true const ctx = createChatGenerationContext(genOptions, trace) if (typeof generator === "string") ctx.node.children.push(createTextNode(generator)) @@ -289,7 +290,7 @@ export async function createPromptContext( system, env, trace, - options + genOptions ) if (sysr.images?.length) throw new NotSupportedError("images") diff --git a/packages/core/src/server/client.ts b/packages/core/src/server/client.ts index 4fd6a4bd80..4d7d05836b 100644 --- a/packages/core/src/server/client.ts +++ b/packages/core/src/server/client.ts @@ -154,6 +154,7 @@ export class WebSocketClient extends EventTarget { responseChunk: ev.responseChunk, responseSoFar: ev.response, tokensSoFar: ev.tokens, + inner: ev.inner, }) break } diff --git a/packages/core/src/server/messages.ts b/packages/core/src/server/messages.ts index 7fbf3265b8..8c2c39868f 100644 --- a/packages/core/src/server/messages.ts +++ b/packages/core/src/server/messages.ts @@ -115,6 +115,7 @@ export interface PromptScriptProgressResponseEvent { tokens?: number response?: string responseChunk?: string + inner?: boolean } export interface ShellExecResponse extends ResponseStatus { diff --git a/packages/core/src/template.ts b/packages/core/src/template.ts index a1c0045c49..79c9cd0c8d 100644 --- a/packages/core/src/template.ts +++ b/packages/core/src/template.ts @@ -271,6 +271,9 @@ export async function parsePromptScript( c.checkBool("lineNumbers") c.checkObjectOrObjectArray("tests") c.checkStringArray("tools") + + c.checkBool("cache") + c.checkString("cacheName") }) const r = c.template diff --git a/packages/core/src/util.ts b/packages/core/src/util.ts index 6ad3dbef15..3ab62077cb 100644 --- a/packages/core/src/util.ts +++ b/packages/core/src/util.ts @@ -1,6 +1,6 @@ import path from "path" import { GENAISCRIPT_FOLDER, HTTPS_REGEX } from "./constants" -import { serializeError } from "./error" +import { isCancelError, serializeError } from "./error" import { LogLevel, host } from "./host" import { YAMLStringify } from "./yaml" import { escape as HTMLEscape_ } from "html-escaper" @@ -178,11 +178,18 @@ export function logWarn(msg: string) { } export function logError(msg: string | Error | SerializedError) { - const { message, ...e } = serializeError(msg) - if (message) host.log(LogLevel.Error, message) - console.debug(msg) - const se = YAMLStringify(e) - if (!/^\s*\{\s*\}\s*$/) host.log(LogLevel.Info, se) + const err = serializeError(msg) + const { message, name, stack, ...e } = err + if (isCancelError(err)) { + host.log(LogLevel.Info, message || "cancelled") + } else { + host.log(LogLevel.Error, message ?? name ?? "error") + } + if (stack) host.log(LogLevel.Verbose, stack) + if (Object.keys(e).length) { + const se = YAMLStringify(e) + if (!/^\s*\{\s*\}\s*$/) host.log(LogLevel.Verbose, se) + } } export function concatArrays(...arrays: T[][]): T[] { if (arrays.length == 0) return [] diff --git a/packages/sample/genaisrc/blogify-sample.genai.mjs b/packages/sample/genaisrc/blogify-sample.genai.mjs index a96f58de72..ccf607c9d3 100644 --- a/packages/sample/genaisrc/blogify-sample.genai.mjs +++ b/packages/sample/genaisrc/blogify-sample.genai.mjs @@ -20,6 +20,7 @@ $`Create a blog post that explains the GenAIScript source code in FILE. - the title should be the intention of the script as if the user wrote it, use simple words, keep it short, mention genai, wrap in quotes - tell the motivation for the script. Add a link to the script file using a GitHub URL. - explain the script code line by line as if you were writing the script from scratch. Assume the reader is a beginner. Show the code being explained. Also explain prompts ($\`...\` line by line) +- explain all the code, don't skip any line. this is important - add a section that explains how to run the script with the genaiscript cli. Do not explain how to install the cli, link to the documentation instead. # Format diff --git a/yarn.lock b/yarn.lock index fae5b5b0fa..11876c7a87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -366,6 +366,145 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.0.tgz#6d86b8cb322660f03d3f0aa94b99bdd8e172d570" integrity sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew== +"@inquirer/checkbox@^2.4.7": + version "2.4.7" + resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-2.4.7.tgz#0a2867a3a8c5853c79e43e99634e80c1721934ca" + integrity sha512-5YwCySyV1UEgqzz34gNsC38eKxRBtlRDpJLlKcRtTjlYA/yDKuc1rfw+hjw+2WJxbAZtaDPsRl5Zk7J14SBoBw== + dependencies: + "@inquirer/core" "^9.0.10" + "@inquirer/figures" "^1.0.5" + "@inquirer/type" "^1.5.2" + ansi-escapes "^4.3.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/confirm@^3.1.22": + version "3.1.22" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-3.1.22.tgz#23990624c11f60c6f7a5b0558c7505c35076a037" + integrity sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg== + dependencies: + "@inquirer/core" "^9.0.10" + "@inquirer/type" "^1.5.2" + +"@inquirer/core@^9.0.10": + version "9.0.10" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-9.0.10.tgz#4270191e2ad3bea6223530a093dd9479bcbc7dd0" + integrity sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA== + dependencies: + "@inquirer/figures" "^1.0.5" + "@inquirer/type" "^1.5.2" + "@types/mute-stream" "^0.0.4" + "@types/node" "^22.1.0" + "@types/wrap-ansi" "^3.0.0" + ansi-escapes "^4.3.2" + cli-spinners "^2.9.2" + cli-width "^4.1.0" + mute-stream "^1.0.0" + signal-exit "^4.1.0" + strip-ansi "^6.0.1" + wrap-ansi "^6.2.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/editor@^2.1.22": + version "2.1.22" + resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-2.1.22.tgz#f97eda20954da1dab47df9f4c3ae11604d56360c" + integrity sha512-K1QwTu7GCK+nKOVRBp5HY9jt3DXOfPGPr6WRDrPImkcJRelG9UTx2cAtK1liXmibRrzJlTWOwqgWT3k2XnS62w== + dependencies: + "@inquirer/core" "^9.0.10" + "@inquirer/type" "^1.5.2" + external-editor "^3.1.0" + +"@inquirer/expand@^2.1.22": + version "2.1.22" + resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-2.1.22.tgz#7593e93a516a49434629c41f3738479c8234d2df" + integrity sha512-wTZOBkzH+ItPuZ3ZPa9lynBsdMp6kQ9zbjVPYEtSBG7UulGjg2kQiAnUjgyG4SlntpTce5bOmXAPvE4sguXjpA== + dependencies: + "@inquirer/core" "^9.0.10" + "@inquirer/type" "^1.5.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/figures@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.5.tgz#57f9a996d64d3e3345d2a3ca04d36912e94f8790" + integrity sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA== + +"@inquirer/input@^2.2.9": + version "2.2.9" + resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-2.2.9.tgz#08fdf9a48e4f6fc64c2d508b9d10afac843f9bd8" + integrity sha512-7Z6N+uzkWM7+xsE+3rJdhdG/+mQgejOVqspoW+w0AbSZnL6nq5tGMEVASaYVWbkoSzecABWwmludO2evU3d31g== + dependencies: + "@inquirer/core" "^9.0.10" + "@inquirer/type" "^1.5.2" + +"@inquirer/number@^1.0.10": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-1.0.10.tgz#ac2b440ca57b5de5a231e4898c12d4453683c055" + integrity sha512-kWTxRF8zHjQOn2TJs+XttLioBih6bdc5CcosXIzZsrTY383PXI35DuhIllZKu7CdXFi2rz2BWPN9l0dPsvrQOA== + dependencies: + "@inquirer/core" "^9.0.10" + "@inquirer/type" "^1.5.2" + +"@inquirer/password@^2.1.22": + version "2.1.22" + resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-2.1.22.tgz#ec7ee5709923cf285b3e0ae53eed4fdc3c05b422" + integrity sha512-5Fxt1L9vh3rAKqjYwqsjU4DZsEvY/2Gll+QkqR4yEpy6wvzLxdSgFhUcxfDAOtO4BEoTreWoznC0phagwLU5Kw== + dependencies: + "@inquirer/core" "^9.0.10" + "@inquirer/type" "^1.5.2" + ansi-escapes "^4.3.2" + +"@inquirer/prompts@^5.3.8": + version "5.3.8" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-5.3.8.tgz#f394050d95076c2f1b046be324f06f619b257c3e" + integrity sha512-b2BudQY/Si4Y2a0PdZZL6BeJtl8llgeZa7U2j47aaJSCeAl1e4UI7y8a9bSkO3o/ZbZrgT5muy/34JbsjfIWxA== + dependencies: + "@inquirer/checkbox" "^2.4.7" + "@inquirer/confirm" "^3.1.22" + "@inquirer/editor" "^2.1.22" + "@inquirer/expand" "^2.1.22" + "@inquirer/input" "^2.2.9" + "@inquirer/number" "^1.0.10" + "@inquirer/password" "^2.1.22" + "@inquirer/rawlist" "^2.2.4" + "@inquirer/search" "^1.0.7" + "@inquirer/select" "^2.4.7" + +"@inquirer/rawlist@^2.2.4": + version "2.2.4" + resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-2.2.4.tgz#73d5d4fafa2ca012e6cfb9eb1d8ddf33bab2dde0" + integrity sha512-pb6w9pWrm7EfnYDgQObOurh2d2YH07+eDo3xQBsNAM2GRhliz6wFXGi1thKQ4bN6B0xDd6C3tBsjdr3obsCl3Q== + dependencies: + "@inquirer/core" "^9.0.10" + "@inquirer/type" "^1.5.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/search@^1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-1.0.7.tgz#72ab9ccfb57f05dd81a8b2df26214588e048be18" + integrity sha512-p1wpV+3gd1eST/o5N3yQpYEdFNCzSP0Klrl+5bfD3cTTz8BGG6nf4Z07aBW0xjlKIj1Rp0y3x/X4cZYi6TfcLw== + dependencies: + "@inquirer/core" "^9.0.10" + "@inquirer/figures" "^1.0.5" + "@inquirer/type" "^1.5.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/select@^2.4.7": + version "2.4.7" + resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-2.4.7.tgz#6a23742b4f76d228186dfd42571d973def378ffa" + integrity sha512-JH7XqPEkBpNWp3gPCqWqY8ECbyMoFcCZANlL6pV9hf59qK6dGmkOlx1ydyhY+KZ0c5X74+W6Mtp+nm2QX0/MAQ== + dependencies: + "@inquirer/core" "^9.0.10" + "@inquirer/figures" "^1.0.5" + "@inquirer/type" "^1.5.2" + ansi-escapes "^4.3.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/type@^1.5.2": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.5.2.tgz#15f5e4a4dae02c4203650cb07c8a000cdd423939" + integrity sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA== + dependencies: + mute-stream "^1.0.0" + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -641,6 +780,13 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== +"@types/mute-stream@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" + integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow== + dependencies: + "@types/node" "*" + "@types/node-fetch@^2.6.4": version "2.6.11" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24" @@ -649,7 +795,7 @@ "@types/node" "*" form-data "^4.0.0" -"@types/node@*", "@types/node@>=13.7.0", "@types/node@>=20": +"@types/node@*", "@types/node@>=13.7.0", "@types/node@>=20", "@types/node@^22.1.0": version "22.5.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.0.tgz#10f01fe9465166b4cab72e75f60d8b99d019f958" integrity sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg== @@ -717,6 +863,11 @@ resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.92.0.tgz#b4d6bc180e7206defe643a1a5f38a1367947d418" integrity sha512-DcZoCj17RXlzB4XJ7IfKdPTcTGDLYvTOcTNkvtjXWF+K2TlKzHHkBEXNWQRpBIXixNEUgx39cQeTFunY0E2msw== +"@types/wrap-ansi@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" + integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== + "@types/ws@^8.5.12": version "8.5.12" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e" @@ -912,6 +1063,13 @@ ajv@^8.17.1: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" +ansi-escapes@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -1254,6 +1412,11 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + cheerio-select@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" @@ -1293,6 +1456,16 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +cli-spinners@^2.9.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -1975,6 +2148,15 @@ ext@^1.7.0: dependencies: type "^2.7.2" +external-editor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extract-zip@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" @@ -2534,6 +2716,13 @@ iconv-lite@0.6.3, iconv-lite@^0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -3321,6 +3510,11 @@ ms@^2.0.0, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +mute-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -3578,6 +3772,11 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + p-cancelable@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-4.0.1.tgz#2d1edf1ab8616b72c73db41c4bc9ecdd10af640e" @@ -4089,7 +4288,7 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -4557,6 +4756,13 @@ tiny-emitter@^2.1.0: resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmp@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" @@ -4680,6 +4886,11 @@ type-fest@^0.18.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + type-fest@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" @@ -4991,6 +5202,15 @@ word-wrap@^1.2.5: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -5117,6 +5337,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yoctocolors-cjs@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" + integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA== + yoctocolors@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/yoctocolors/-/yoctocolors-2.1.1.tgz#e0167474e9fbb9e8b3ecca738deaa61dd12e56fc"